From: Vladimir 'phcoder' Serbinenko Date: Sun, 12 Sep 2010 12:01:02 +0000 (+0200) Subject: Fix bunch of memory problems and implement hdbias X-Git-Tag: 1.99~490^2~15 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=64ad6157ae4f9d68be1b96ad7882544241a3e0f4;p=thirdparty%2Fgrub.git Fix bunch of memory problems and implement hdbias --- diff --git a/grub-core/commands/legacycfg.c b/grub-core/commands/legacycfg.c index 82901b0e7..e42ca5878 100644 --- a/grub-core/commands/legacycfg.c +++ b/grub-core/commands/legacycfg.c @@ -30,6 +30,8 @@ #include #include #include +#include +#include static grub_err_t legacy_file (const char *filename) @@ -67,7 +69,7 @@ legacy_file (const char *filename) while (1) { char *buf = grub_file_getline (file); - char *parsed; + char *parsed = NULL; if (!buf && grub_errno) { @@ -84,7 +86,7 @@ legacy_file (const char *filename) oldname = entryname; parsed = grub_legacy_parse (buf, &entryname, &is_suffix); - grub_free (buf); + buf = NULL; if (is_suffix) { char *t; @@ -100,7 +102,7 @@ legacy_file (const char *filename) grub_free (suffix); return grub_errno; } - grub_memcpy (entrysrc + grub_strlen (entrysrc), parsed, + grub_memcpy (suffix + grub_strlen (suffix), parsed, grub_strlen (parsed) + 1); grub_free (parsed); parsed = NULL; @@ -117,6 +119,9 @@ legacy_file (const char *filename) args[0] = oldname; grub_normal_add_menu_entry (1, args, NULL, NULL, NULL, NULL, entrysrc); + grub_free (args); + entrysrc[0] = 0; + grub_free (oldname); } } @@ -125,6 +130,7 @@ legacy_file (const char *filename) grub_normal_parse_line (parsed, getline); grub_print_error (); grub_free (parsed); + parsed = NULL; } else if (parsed) { @@ -163,11 +169,13 @@ legacy_file (const char *filename) } args[0] = entryname; grub_normal_add_menu_entry (1, args, NULL, NULL, NULL, NULL, entrysrc); + grub_free (args); } grub_normal_parse_line (suffix, getline); grub_print_error (); grub_free (suffix); + grub_free (entrysrc); if (menu && menu->size) grub_show_menu (menu, 1); @@ -215,6 +223,7 @@ grub_cmd_legacy_kernel (struct grub_command *mycmd __attribute__ ((unused)), struct grub_command *cmd; char **cutargs; int cutargc; + for (i = 0; i < 2; i++) { /* FIXME: really support this. */ @@ -309,46 +318,118 @@ grub_cmd_legacy_kernel (struct grub_command *mycmd __attribute__ ((unused)), grub_errno = GRUB_ERR_NONE; } - /* k*BSD didn't really work well with grub-legacy. */ - if (kernel_type == GUESS_IT || kernel_type == KFREEBSD) + { + int bsd_device = -1; + int bsd_slice = -1; + int bsd_part = -1; { - cmd = grub_command_find ("kfreebsd"); - if (cmd) + grub_device_t dev; + char *hdbiasstr; + int hdbias = 0; + hdbiasstr = grub_env_get ("legacy_hdbias"); + if (hdbiasstr) { - if (!(cmd->func) (cmd, cutargc, cutargs)) + hdbias = grub_strtoul (hdbiasstr, 0, 0); + grub_errno = GRUB_ERR_NONE; + } + dev = grub_device_open (0); + if (dev && dev->disk + && dev->disk->dev->id == GRUB_DISK_DEVICE_BIOSDISK_ID + && dev->disk->dev->id >= 0x80 && dev->disk->dev->id <= 0x90) + { + struct grub_partition *part = dev->disk->partition; + bsd_device = dev->disk->id - 0x80 - hdbias; + if (part && (grub_strcmp (part->partmap->name, "netbsd") == 0 + || grub_strcmp (part->partmap->name, "openbsd") == 0 + || grub_strcmp (part->partmap->name, "bsd") == 0)) { - kernel_type = KFREEBSD; - return GRUB_ERR_NONE; + bsd_part = part->number; + part = part->parent; } + if (part && grub_strcmp (part->partmap->name, "msdos") == 0) + bsd_slice = part->number; } - grub_errno = GRUB_ERR_NONE; } - if (kernel_type == GUESS_IT || kernel_type == KNETBSD) + + /* k*BSD didn't really work well with grub-legacy. */ + if (kernel_type == GUESS_IT || kernel_type == KFREEBSD) + { + char buf[sizeof("adXXXXXXXXXXXXsXXXXXXXXXXXXYYY")]; + if (bsd_device != -1) + { + if (bsd_slice != -1 && bsd_part != -1) + grub_snprintf(buf, sizeof(buf), "ad%ds%d%c", bsd_device, + bsd_slice, 'a' + bsd_part); + else if (bsd_slice != -1) + grub_snprintf(buf, sizeof(buf), "ad%ds%d", bsd_device, + bsd_slice); + else + grub_snprintf(buf, sizeof(buf), "ad%d", bsd_device); + grub_env_set ("kFreeBSD.vfs.root.mountfrom", buf); + } + else + grub_env_unset ("kFreeBSD.vfs.root.mountfrom"); + cmd = grub_command_find ("kfreebsd"); + if (cmd) + { + if (!(cmd->func) (cmd, cutargc, cutargs)) + { + kernel_type = KFREEBSD; + return GRUB_ERR_NONE; + } + } + grub_errno = GRUB_ERR_NONE; + } { - cmd = grub_command_find ("knetbsd"); - if (cmd) + char **bsdargs; + int bsdargc; + char bsddevname[sizeof ("wdXXXXXXXXXXXXY")]; + if (bsd_device == -1) { - if (!(cmd->func) (cmd, cutargc, cutargs)) + bsdargs = cutargs; + bsdargc = cutargc; + } + else + { + bsdargc = cutargc + 2; + bsdargs = grub_malloc (sizeof (bsdargs[0]) * bsdargc); + grub_memcpy (bsdargs, args, argc * sizeof (bsdargs[0])); + bsdargs[argc] = "-r"; + bsdargs[argc + 1] = bsddevname; + grub_snprintf (bsddevname, sizeof (bsddevname), + "wd%d%c", bsd_device, + bsd_part != -1 ? bsd_part + 'a' : 'c'); + } + if (kernel_type == GUESS_IT || kernel_type == KNETBSD) + { + cmd = grub_command_find ("knetbsd"); + if (cmd) { - kernel_type = KNETBSD; - return GRUB_ERR_NONE; + if (!(cmd->func) (cmd, bsdargc, bsdargs)) + { + kernel_type = KNETBSD; + return GRUB_ERR_NONE; + } } + grub_errno = GRUB_ERR_NONE; } - grub_errno = GRUB_ERR_NONE; - } - if (kernel_type == GUESS_IT || kernel_type == KOPENBSD) - { - cmd = grub_command_find ("kopenbsd"); - if (cmd) + if (kernel_type == GUESS_IT || kernel_type == KOPENBSD) { - if (!(cmd->func) (cmd, cutargc, cutargs)) + cmd = grub_command_find ("kopenbsd"); + if (cmd) { - kernel_type = KOPENBSD; - return GRUB_ERR_NONE; + if (!(cmd->func) (cmd, bsdargc, bsdargs)) + { + kernel_type = KOPENBSD; + return GRUB_ERR_NONE; + } } + grub_errno = GRUB_ERR_NONE; } - grub_errno = GRUB_ERR_NONE; + if (bsdargs != cutargs) + grub_free (bsdargs); } + } } while (0); diff --git a/grub-core/lib/legacy_parse.c b/grub-core/lib/legacy_parse.c index dabc497be..01b836087 100644 --- a/grub-core/lib/legacy_parse.c +++ b/grub-core/lib/legacy_parse.c @@ -195,7 +195,9 @@ struct legacy_command legacy_commands[] = {"reboot", "reboot\n", 0, {}, 0, 0, "Reboot your system."}, /* FIXME: Support HDBIAS. */ /* FIXME: Support printing. */ - {"root", "set root='%s'\n", 1, {TYPE_PARTITION}, 0, "[DEVICE [HDBIAS]]", + {"root", "set root='%s'; set legacy_hdbias='%s'\n", + 2, {TYPE_PARTITION, TYPE_INT}, 0, + "[DEVICE [HDBIAS]]", "Set the current \"root device\" to the device DEVICE, then" " attempt to mount it to get the partition size (for passing the" " partition descriptor in `ES:ESI', used by some chain-loaded" @@ -206,7 +208,8 @@ struct legacy_command legacy_commands[] = " how many BIOS drive numbers are on controllers before the current" " one. For example, if there is an IDE disk and a SCSI disk, and your" " FreeBSD root partition is on the SCSI disk, then use a `1' for HDBIAS."}, - {"rootnoverify", "set root='%s'\n", 1, {TYPE_PARTITION}, 0, + {"rootnoverify", "set root='%s'; set legacy_hdbias='%s'\n", + 2, {TYPE_PARTITION, TYPE_INT}, 0, "[DEVICE [HDBIAS]]", "Similar to `root', but don't attempt to mount the partition. This" " is useful for when an OS is outside of the area of the disk that" @@ -265,7 +268,7 @@ grub_legacy_escape (const char *in, grub_size_t len) for (ptr = in; ptr < in + len && *ptr; ptr++) if (*ptr == '\'' || *ptr == '\\') overhead++; - ret = grub_malloc (ptr - in + overhead); + ret = grub_malloc (ptr - in + overhead + 1); if (!ret) return NULL; outptr = ret; @@ -371,7 +374,15 @@ grub_legacy_parse (const char *buf, char **entryname, int *suffix) for (ptr = buf; *ptr && grub_isspace (*ptr); ptr++); if (!*ptr || *ptr == '#') - return grub_strdup (buf); + { + char *ret; + int len = grub_strlen (buf); + ret = grub_malloc (len + 2); + grub_memcpy (ret, buf, len); + ret[len] = '\n'; + ret[len + 1] = 0; + return ret; + } cmdname = ptr; for (ptr = buf; *ptr && !grub_isspace (*ptr) && *ptr != '='; ptr++); @@ -412,7 +423,7 @@ grub_legacy_parse (const char *buf, char **entryname, int *suffix) unsigned j = 0; int hold_arg = 0; const char *curarg = NULL; - for (i = 0; i < legacy_commands[cmdnum].argc; i++) + for (i = 0; i < legacy_commands[cmdnum].argc + hold_arg; i++) { grub_size_t curarglen; if (hold_arg) @@ -495,7 +506,7 @@ grub_legacy_parse (const char *buf, char **entryname, int *suffix) args[j++] = grub_strndup (curarg, curarglen); break; } - args[j++] = ""; + args[j++] = grub_strdup (""); hold_arg = 1; break; case TYPE_INT: @@ -536,7 +547,14 @@ grub_legacy_parse (const char *buf, char **entryname, int *suffix) } } } - - return grub_xasprintf (legacy_commands[cmdnum].map, args[0], args[1], args[2], - args[3]); + + { + char *ret = grub_xasprintf (legacy_commands[cmdnum].map, args[0], args[1], + args[2], args[3]); + grub_free (args[0]); + grub_free (args[1]); + grub_free (args[2]); + grub_free (args[3]); + return ret; + } } diff --git a/util/grub-menulst2cfg.c b/util/grub-menulst2cfg.c index 0184b3fe3..38a906c0a 100644 --- a/util/grub-menulst2cfg.c +++ b/util/grub-menulst2cfg.c @@ -88,12 +88,18 @@ main (int argc, char **argv) if (oldname != entryname && oldname) fprintf (out, "}\n\n"); if (oldname != entryname) - fprintf (out, "menuentry \'%s\' {\n", - grub_legacy_escape (entryname, strlen (entryname))); + { + char *escaped = grub_legacy_escape (entryname, strlen (entryname)); + fprintf (out, "menuentry \'%s\' {\n", escaped); + grub_free (escaped); + grub_free (oldname); + } } if (parsed) fprintf (out, "%s%s", entryname ? " " : "", parsed); + grub_free (parsed); + parsed = NULL; } if (entryname) @@ -101,6 +107,10 @@ main (int argc, char **argv) fwrite (out, 1, suffixlen, suffix); + grub_free (buf); + grub_free (suffix); + grub_free (entryname); + if (in != stdin) fclose (in); if (out != stdout)