Hi, This patch add environment block support, which can be used to locate root device using uuid or label.
The environment block occupied the space previously used to store prefix. The structure is like this: Magic numbe: "EvbK" (4 bytes) Length of environment block (2 bytes) null-ended name=value pairs, ended with an empty string. The previous prefix is stored in variable rdir. Different platform use grub_machine_get_envblk to return a pointer to the name=value area of environment block. In main.c, it uses grub_parse_envblk to walk through the list and assign values to variables. I also replace grub_machine_set_prefix with grub_machine_set_root. As it seems strange to compute the prefix in grub_machine_set_prefix, and then split it in grub_set_root_dev to get the root device. Now, grub_machine_set_root set the root directly, and in grub_set_root_dev, it uses root and rdir to generate the prefix. A new tool grub-editenv is added to manage the environment block, for example: grub-editenv FILE create Create a blank environment block file. It's used to store external environment file. grub-editenv FILE info Show the info about location and size of environment block in core.img or external environment file. grub-editenv FILE list List the content of environment block. grub-editenv FILE edit name=value Edit the environment block. If no value is specify, name=, it deletes the item. grub-editenv FILE clear Remove all variables in the environment block. And there is a new module findroot.mod. It will scan all partitions and compare their uuid/label with the uuid and label variable, whose value can be set in the environment block. Here is an example: First, use grub-mkimage to create core.img: grub-mkimage -o core.img pc ext2 findroot grub-mkimage will initialize the environment block with one item: rdir=/boot/grub Second, use grub-editenv to set the uuid or label of the root device. For example: grub-editenv core.img edit uuid=xxx-xxxx grub-editenv core.img edit label=System If both uuid and label is specified, uuid will take preference, unless the fs don't support uuid. You can also change rdir to change the default root directory, or add debug=all to show debug message, etc. -- Bean
diff --git a/boot/i386/pc/lnxboot.S b/boot/i386/pc/lnxboot.S index 955cc41..380ef08 100644 --- a/boot/i386/pc/lnxboot.S +++ b/boot/i386/pc/lnxboot.S @@ -185,7 +185,7 @@ real_code_2: call move_memory /* Check for multiboot signature. */ - cmpl $MULTIBOOT_MAGIC, %ss:(DATA_ADDR + 0x50) + cmpl $MULTIBOOT_MAGIC, %ss:(DATA_ADDR + GRUB_KERNEL_MACHINE_DATA_END) jz 1f movl (ramdisk_image - start), %esi diff --git a/conf/common.rmk b/conf/common.rmk index acbebc7..0582d56 100644 --- a/conf/common.rmk +++ b/conf/common.rmk @@ -94,6 +94,12 @@ grub_fstest_init.c: grub_fstest_init.lst $(filter-out grub_fstest_init.c,$(grub_ rm -f $@; sh $(srcdir)/geninit.sh $< $(filter %.c,$^) > $@ DISTCLEANFILES += grub_fstest_init.c +# for grub-editenv +bin_UTILITIES += grub-editenv +grub_editenv_SOURCES = util/grub-editenv.c util/envblk.c util/misc.c \ + kern/err.c kern/misc.c +CLEANFILES += grub-editenv + # For update-grub update-grub: util/update-grub.in config.status ./config.status --file=$@:$< @@ -365,7 +371,7 @@ hexdump_mod_CFLAGS = $(COMMON_CFLAGS) hexdump_mod_LDFLAGS = $(COMMON_LDFLAGS) # Misc. -pkglib_MODULES += gzio.mod elf.mod +pkglib_MODULES += gzio.mod elf.mod findroot.mod # For elf.mod. elf_mod_SOURCES = kern/elf.c @@ -386,3 +392,8 @@ read_mod_LDFLAGS = $(COMMON_LDFLAGS) sleep_mod_SOURCES = commands/sleep.c sleep_mod_CFLAGS = $(COMMON_CFLAGS) sleep_mod_LDFLAGS = $(COMMON_LDFLAGS) + +# For findroot.mod. +findroot_mod_SOURCES = kern/findroot.c +findroot_mod_CFLAGS = $(COMMON_CFLAGS) +findroot_mod_LDFLAGS = $(COMMON_LDFLAGS) diff --git a/include/grub/envblk.h b/include/grub/envblk.h new file mode 100755 index 0000000..7811723 --- /dev/null +++ b/include/grub/envblk.h @@ -0,0 +1,47 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2008 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef GRUB_ENVBLK_HEADER +#define GRUB_ENVBLK_HEADER 1 + +#define GRUB_ENVBLK_SIGNATURE 0x4b627645 /* EvbK */ + +#define GRUB_ENVBLK_MAXLEN 8192 + +/* Names of important environment variables. */ +#define GRUB_ENVBLK_RDIR "rdir" +#define GRUB_ENVBLK_UUID "uuid" +#define GRUB_ENVBLK_LABEL "label" + +#ifndef ASM_FILE + +struct grub_envblk +{ + grub_uint32_t signature; + grub_uint16_t length; + char data[0]; +} __attribute__ ((packed)); +typedef struct grub_envblk *grub_envblk_t; + +grub_envblk_t grub_envblk_find (char *buf); +int grub_envblk_insert (grub_envblk_t envblk, char *name, char *value); +void grub_envblk_delete (grub_envblk_t envblk, char *name); + +#endif + +#endif /* ! GRUB_ENVBLK_HEADER */ diff --git a/include/grub/i386/pc/kernel.h b/include/grub/i386/pc/kernel.h index 43a8d5b..13548c5 100644 --- a/include/grub/i386/pc/kernel.h +++ b/include/grub/i386/pc/kernel.h @@ -37,14 +37,14 @@ /* The offset of GRUB_MEMDISK_IMAGE_SIZE. */ #define GRUB_KERNEL_MACHINE_MEMDISK_IMAGE_SIZE 0x1c -/* The offset of GRUB_PREFIX. */ -#define GRUB_KERNEL_MACHINE_PREFIX 0x20 +/* The offset of GRUB_ENVBLK. */ +#define GRUB_KERNEL_MACHINE_ENVBLK 0x26 /* End of the data section. */ -#define GRUB_KERNEL_MACHINE_DATA_END 0x50 +#define GRUB_KERNEL_MACHINE_DATA_END 0x70 /* The size of the first region which won't be compressed. */ -#define GRUB_KERNEL_MACHINE_RAW_SIZE 0x4A0 +#define GRUB_KERNEL_MACHINE_RAW_SIZE 0x4C0 #ifndef ASM_FILE @@ -66,9 +66,9 @@ extern grub_int32_t grub_install_bsd_part; /* The size of memory disk image, if present. */ extern grub_int32_t grub_memdisk_image_size; -/* The prefix which points to the directory where GRUB modules and its - configuration file are located. */ -extern char grub_prefix[]; +/* The envblk contains variable which can be used to locate the directory where + GRUB modules and its configuration file. */ +extern char grub_envblk[]; /* The boot BIOS drive number. */ extern grub_int32_t EXPORT_VAR(grub_boot_drive); diff --git a/include/grub/kernel.h b/include/grub/kernel.h index 4a4e2cc..49f3516 100644 --- a/include/grub/kernel.h +++ b/include/grub/kernel.h @@ -55,8 +55,10 @@ void grub_machine_init (void); /* The machine-specific finalization. */ void grub_machine_fini (void); -/* The machine-specific prefix initialization. */ -void grub_machine_set_prefix (void); +/* The machine-specific root initialization. */ +void grub_machine_set_root (void); + +char *grub_machine_get_envblk (void); /* Register all the exported symbols. This is automatically generated. */ void grub_register_exported_symbols (void); diff --git a/kern/findroot.c b/kern/findroot.c new file mode 100755 index 0000000..3ac5ce5 --- /dev/null +++ b/kern/findroot.c @@ -0,0 +1,96 @@ +/* findroot.c - search for root device */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2008 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <grub/types.h> +#include <grub/misc.h> +#include <grub/mm.h> +#include <grub/err.h> +#include <grub/dl.h> +#include <grub/device.h> +#include <grub/file.h> +#include <grub/env.h> +#include <grub/machine/kernel.h> + +#define KERNEL_FILE "/normal.mod" + +static void +findroot (void) +{ + char *label, *uuid; + + auto int iterate_device (const char *name); + int iterate_device (const char *name) + { + int found = 0; + grub_device_t dev; + grub_fs_t fs; + + dev = grub_device_open (name); + if (dev) + { + fs = grub_fs_probe (dev); + if (fs) + { + if ((uuid) && (fs->uuid)) + { + char *cur; + + fs->uuid (dev, &cur); + if (cur) + { + found = (! grub_strcmp (uuid, cur)); + grub_free (cur); + } + } + else if ((label) && (fs->label)) + { + char *cur; + + fs->label (dev, &cur); + if (cur) + { + found = (! grub_strcmp (label, cur)); + grub_free (cur); + } + } + + if (found) + grub_env_set ("root", name); + } + + grub_device_close (dev); + } + + grub_errno = GRUB_ERR_NONE; + return found; + } + + label = grub_env_get ("label"); + uuid = grub_env_get ("uuid"); + + if ((! label) && (! uuid)) + return; + + grub_device_iterate (iterate_device); +} + +GRUB_MOD_INIT(findroot) +{ + findroot (); +} diff --git a/kern/i386/pc/init.c b/kern/i386/pc/init.c index 757f5d5..aabdff2 100644 --- a/kern/i386/pc/init.c +++ b/kern/i386/pc/init.c @@ -58,40 +58,6 @@ grub_arch_sync_caches (void *address __attribute__ ((unused)), { } -static char * -make_install_device (void) -{ - /* XXX: This should be enough. */ - char dev[100]; - - if (grub_memdisk_image_size) - { - grub_sprintf (dev, "(memdisk)%s", grub_prefix); - grub_strcpy (grub_prefix, dev); - } - else if (grub_install_dos_part != -2) - { - /* If the root drive is not set explicitly, assume that it is identical - to the boot drive. */ - if (grub_root_drive == 0xFF) - grub_root_drive = grub_boot_drive; - - grub_sprintf (dev, "(%cd%u", (grub_root_drive & 0x80) ? 'h' : 'f', - grub_root_drive & 0x7f); - - if (grub_install_dos_part >= 0) - grub_sprintf (dev + grub_strlen (dev), ",%u", grub_install_dos_part + 1); - - if (grub_install_bsd_part >= 0) - grub_sprintf (dev + grub_strlen (dev), ",%c", grub_install_bsd_part + 'a'); - - grub_sprintf (dev + grub_strlen (dev), ")%s", grub_prefix); - grub_strcpy (grub_prefix, dev); - } - - return grub_prefix; -} - /* Add a memory region. */ static void add_mem_region (grub_addr_t addr, grub_size_t size) @@ -238,11 +204,40 @@ grub_machine_init (void) grub_fatal ("no upper memory"); } +char * +grub_machine_get_envblk (void) +{ + return grub_envblk; +} + void -grub_machine_set_prefix (void) +grub_machine_set_root (void) { - /* Initialize the prefix. */ - grub_env_set ("prefix", make_install_device ()); + /* XXX: This should be enough. */ + char dev[100]; + + if (grub_memdisk_image_size) + { + grub_env_set ("root", "memdisk"); + } + else if (grub_install_dos_part != -2) + { + /* If the root drive is not set explicitly, assume that it is identical + to the boot drive. */ + if (grub_root_drive == 0xFF) + grub_root_drive = grub_boot_drive; + + grub_sprintf (dev, "%cd%u", (grub_root_drive & 0x80) ? 'h' : 'f', + grub_root_drive & 0x7f); + + if (grub_install_dos_part >= 0) + grub_sprintf (dev + grub_strlen (dev), ",%u", grub_install_dos_part + 1); + + if (grub_install_bsd_part >= 0) + grub_sprintf (dev + grub_strlen (dev), ",%c", grub_install_bsd_part + 'a'); + + grub_env_set ("root", dev); + } } void diff --git a/kern/i386/pc/startup.S b/kern/i386/pc/startup.S index ebb98fe..cba710a 100644 --- a/kern/i386/pc/startup.S +++ b/kern/i386/pc/startup.S @@ -52,6 +52,7 @@ #include <grub/term.h> #include <multiboot.h> #include <multiboot2.h> +#include <grub/envblk.h> #define ABS(x) ((x) - EXT_C(start) + GRUB_BOOT_MACHINE_KERNEL_ADDR + 0x200) @@ -98,14 +99,19 @@ VARIABLE(grub_install_bsd_part) .long 0xFFFFFFFF VARIABLE(grub_memdisk_image_size) .long 0 -VARIABLE(grub_prefix) + .long GRUB_ENVBLK_SIGNATURE + .word envblk_end - grub_envblk +VARIABLE(grub_envblk) + .byte 0 /* to be filled by grub-mkimage */ /* * Leave some breathing room for the prefix. */ - . = EXT_C(start) + 0x50 + . = EXT_C(start) + 0x70 + +envblk_end: /* * Support for booting GRUB from a Multiboot boot loader (e.g. GRUB itself). diff --git a/kern/main.c b/kern/main.c index 09de03a..729dd78 100644 --- a/kern/main.c +++ b/kern/main.c @@ -28,6 +28,33 @@ #include <grub/device.h> #include <grub/env.h> +static void +grub_parse_envblk (void) +{ + char *env; + + env = grub_machine_get_envblk (); + if (! env) + return; + + while (*env) + { + char *value; + + value = grub_strchr (env, '='); + if (value) + { + *(value++) = 0; + grub_env_set (env, value); + env = value; + } + else + grub_env_set (env, ""); + + env += grub_strlen (env) + 1; + } +} + /* Load all modules in core. */ static void grub_load_modules (void) @@ -75,24 +102,28 @@ grub_env_write_root (struct grub_env_var *var __attribute__ ((unused)), static void grub_set_root_dev (void) { - const char *prefix; + char *root, *rdir, *prefix; + + if (! grub_env_get ("root")) + grub_machine_set_root (); grub_register_variable_hook ("root", 0, grub_env_write_root); grub_env_export ("root"); - prefix = grub_env_get ("prefix"); + root = grub_env_get ("root"); + if (! *root) + return; - if (prefix) - { - char *dev; - - dev = grub_file_get_device_name (prefix); - if (dev) - { - grub_env_set ("root", dev); - grub_free (dev); - } - } + rdir = grub_env_get ("rdir"); + if (! rdir) + rdir = "/"; + + prefix = grub_malloc (grub_strlen (root) + grub_strlen (rdir) + 3); + grub_sprintf (prefix, "(%s)%s", root, rdir); + + grub_env_set ("prefix", prefix); + + grub_free (prefix); } /* Load the normal mode module and execute the normal mode if possible. */ @@ -118,13 +149,15 @@ grub_main (void) grub_printf ("Welcome to GRUB!\n\n"); grub_setcolorstate (GRUB_TERM_COLOR_STANDARD); + /* Parse the environment block. */ + grub_parse_envblk (); + /* Load pre-loaded modules and free the space. */ grub_register_exported_symbols (); grub_load_modules (); /* It is better to set the root device as soon as possible, for convenience. */ - grub_machine_set_prefix (); grub_set_root_dev (); /* Load the normal mode module. */ diff --git a/util/envblk.c b/util/envblk.c new file mode 100755 index 0000000..82ec674 --- /dev/null +++ b/util/envblk.c @@ -0,0 +1,123 @@ +/* envblk.c - Common function for environment block. */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2008 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <config.h> +#include <grub/types.h> +#include <grub/misc.h> +#include <grub/envblk.h> + +grub_envblk_t +grub_envblk_find (char *buf) +{ + grub_uint32_t *pd; + int len; + + pd = (grub_uint32_t *) buf; + + for (len = GRUB_ENVBLK_MAXLEN - 6; len > 0; len -= 4, pd++) + if (*pd == GRUB_ENVBLK_SIGNATURE) + { + grub_envblk_t p; + + p = (grub_envblk_t) pd; + if (p->length <= len) + return p; + } + + return 0; +} + +int +grub_envblk_insert (grub_envblk_t envblk, char *name, char *value) +{ + char *p, *pend; + char *found = 0; + int nl; + + nl = grub_strlen (name); + p = envblk->data; + pend = p + envblk->length; + + while (*p) + { + if ((! found) && (! grub_memcmp (name, p, nl)) && (p[nl] == '=')) + found = p + nl + 1; + + p += strlen (p) + 1; + if (p >= pend) + return 1; + } + + if (found) + { + int len1, len2; + + len1 = grub_strlen (found); + len2 = grub_strlen (value); + if ((p - envblk->data) + 1 - len1 + len2 > envblk->length) + return 1; + + grub_memcpy (found + len2 + 1, found + len1 + 1, (p - found) - len1); + grub_strcpy (found, value); + } + else + { + int len2 = grub_strlen (value); + + if ((p - envblk->data) + nl + 1 + len2 + 2 > envblk->length) + return 1; + + grub_strcpy (p, name); + p[nl] = '='; + grub_strcpy (p + nl + 1, value); + p[nl + 1 + len2 + 1] = 0; + } + + return 0; +} + +void +grub_envblk_delete (grub_envblk_t envblk, char *name) +{ + char *p, *pend; + char *found = 0; + int nl; + + nl = grub_strlen (name); + p = envblk->data; + pend = p + envblk->length; + + while (*p) + { + if ((! found) && (! grub_memcmp (name, p, nl)) && (p[nl] == '=')) + found = p; + + p += strlen (p) + 1; + if (p >= pend) + return; + } + + if (found) + { + int len; + + len = grub_strlen (found); + grub_memcpy (found, found + len + 1, (p - found) - len); + } +} diff --git a/util/grub-editenv.c b/util/grub-editenv.c new file mode 100755 index 0000000..d4d7919 --- /dev/null +++ b/util/grub-editenv.c @@ -0,0 +1,259 @@ +/* grub-editenv.c - tool to edit environment block. */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2008 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <config.h> +#include <grub/types.h> +#include <grub/util/misc.h> + +#include <grub/envblk.h> + +#include <stdio.h> +#include <unistd.h> +#include <string.h> +#include <stdlib.h> +#include <getopt.h> + +void +grub_putchar (int c) +{ + putchar (c); +} + +int +grub_getkey (void) +{ + return -1; +} + +void * +grub_term_get_current (void) +{ + return 0; +} + +void +grub_refresh (void) +{ + fflush (stdout); +} + +char * +grub_env_get (const char * name) +{ + (void) name; + + return 0; +} + +static struct option options[] = { + {"help", no_argument, 0, 'h'}, + {"version", no_argument, 0, 'V'}, + {"verbose", no_argument, 0, 'v'}, + {0, 0, 0, 0} +}; + +char buffer[GRUB_ENVBLK_MAXLEN]; +grub_envblk_t envblk; + +static void +usage (int status) +{ + if (status) + fprintf (stderr, "Try ``grub-editenv --help'' for more information.\n"); + else + printf ("\ +Usage: grub-editenv [OPTIONS] FILENAME COMMAND\n\ +\n\ +Tool to edit environment block.\n\ +\nCommands:\n\ + create create a blank environment block file\n\ + info show information about the environment block\n\ + list list the current variables\n\ + edit [name=value] ... change/delete variables\n\ + clear delete all variables\n\ +\nOptions:\n\ + -h, --help display this message and exit\n\ + -V, --version print version information and exit\n\ + -v, --verbose print verbose messages\n\ +\n\ +Report bugs to <%s>.\n", PACKAGE_BUGREPORT); + + exit (status); +} + +int +create_envblk_file (char *name) +{ + FILE *f; + grub_envblk_t p; + + f = fopen (name, "w"); + if (! f) + return 1; + + /* Just in case OS don't save 0s. */ + memset (buffer, -1, sizeof (buffer)); + + p = (grub_envblk_t) &buffer[0]; + p->signature = GRUB_ENVBLK_SIGNATURE; + p->length = sizeof (buffer) - sizeof (struct grub_envblk); + p->data[0] = p->data[1] = 0; + + fwrite (buffer, sizeof (buffer), 1, f); + + fclose (f); + return 0; +} + +FILE * +open_envblk_file (char *name) +{ + FILE *f; + + f = fopen (name, "r+"); + if (! f) + grub_util_error ("Can\'t open file %s", name); + + if (fread (buffer, 1, sizeof (buffer), f) != sizeof (buffer)) + grub_util_error ("The envblk file is too short"); + + envblk = grub_envblk_find (buffer); + if (! envblk) + grub_util_error ("Can\'t find environment block"); + + return f; +} + +static void +cmd_info (void) +{ + printf ("Envblk offset: %d\n", (char *) envblk - buffer); + printf ("Envblk length: %d\n", envblk->length); +} + +static void +cmd_list (void) +{ + char *p = envblk->data; + + while (*p) + { + printf ("%s\n", p); + p += strlen (p) + 1; + } +} + +static void +cmd_edit (int argc, char *argv[]) +{ + while (argc) + { + char *p; + + p = strchr (argv[0], '='); + if (! p) + grub_util_error ("Invalid parameter"); + + *(p++) = 0; + + if (*p) + { + if (grub_envblk_insert (envblk, argv[0], p)) + grub_util_error ("Environment block too small"); + } + else + grub_envblk_delete (envblk, argv[0]); + + argc--; + argv++; + } +} + +static void +cmd_clear (void) +{ + envblk->data[0] = envblk->data[1] = 0; +} + +int +main (int argc, char *argv[]) +{ + FILE *f; + + progname = "grub-editenv"; + + /* Check for options. */ + while (1) + { + int c = getopt_long (argc, argv, "hVv", options, 0); + + if (c == -1) + break; + else + switch (c) + { + case 'h': + usage (0); + break; + + case 'V': + printf ("%s (%s) %s\n", progname, PACKAGE_NAME, PACKAGE_VERSION); + return 0; + + case 'v': + verbosity++; + break; + + default: + usage (1); + break; + } + } + + /* Obtain PATH. */ + if (optind + 1 >= argc) + { + fprintf (stderr, "Not enough parameter.\n"); + usage (1); + } + + if (! strcmp (argv[optind + 1], "create")) + return create_envblk_file (argv[optind]); + + f = open_envblk_file (argv[optind]); + + optind++; + if (! strcmp (argv[optind], "info")) + cmd_info (); + else if (! strcmp (argv[optind], "list")) + cmd_list (); + else + { + if (! strcmp (argv[optind], "edit")) + cmd_edit (argc - optind - 1, argv + optind + 1); + else if (! strcmp (argv[optind], "clear")) + cmd_clear (); + + fseek (f, 0, SEEK_SET); + fwrite (buffer, sizeof (buffer), 1, f); + } + fclose (f); + + return 0; +} diff --git a/util/grub-emu.c b/util/grub-emu.c index 00a2c49..aa7ceb9 100644 --- a/util/grub-emu.c +++ b/util/grub-emu.c @@ -36,15 +36,13 @@ #include <grub/util/getroot.h> #include <grub/env.h> #include <grub/partition.h> +#include <grub/envblk.h> #include <grub_emu_init.h> /* Used for going back to the main function. */ jmp_buf main_env; -/* Store the prefix specified by an argument. */ -static char *prefix = 0; - grub_addr_t grub_arch_modules_addr (void) { @@ -76,11 +74,15 @@ grub_machine_init (void) } void -grub_machine_set_prefix (void) +grub_machine_set_root (void) { - grub_env_set ("prefix", prefix); - free (prefix); - prefix = 0; + /* Do nothing, as root is already set. */ +} + +char * +grub_machine_get_envblk (void) +{ + return 0; } void @@ -205,8 +207,8 @@ main (int argc, char *argv[]) } dir = grub_get_prefix (dir); - prefix = xmalloc (strlen (root_dev) + 2 + strlen (dir) + 1); - sprintf (prefix, "(%s)%s", root_dev, dir); + grub_env_set (GRUB_ENVBLK_RDIR, dir); + grub_env_set ("root", root_dev); free (dir); /* Start GRUB! */ diff --git a/util/i386/pc/grub-mkimage.c b/util/i386/pc/grub-mkimage.c index 48d6dfc..f71924b 100644 --- a/util/i386/pc/grub-mkimage.c +++ b/util/i386/pc/grub-mkimage.c @@ -27,6 +27,7 @@ #include <grub/util/misc.h> #include <grub/util/resolve.h> #include <grub/misc.h> +#include <grub/envblk.h> #include <stdio.h> #include <unistd.h> @@ -109,9 +110,10 @@ generate_image (const char *dir, char *prefix, FILE *out, char *mods[], char *me kernel_img = xmalloc (kernel_size + total_module_size + memdisk_size); grub_util_load_image (kernel_path, kernel_img); - if (GRUB_KERNEL_MACHINE_PREFIX + strlen (prefix) + 1 > GRUB_KERNEL_MACHINE_DATA_END) + if (GRUB_KERNEL_MACHINE_ENVBLK + sizeof (GRUB_ENVBLK_RDIR) + 2 + strlen (prefix) > GRUB_KERNEL_MACHINE_DATA_END) grub_util_error ("prefix too long"); - strcpy (kernel_img + GRUB_KERNEL_MACHINE_PREFIX, prefix); + strcpy (kernel_img + GRUB_KERNEL_MACHINE_ENVBLK, GRUB_ENVBLK_RDIR "="); + strcpy (kernel_img + GRUB_KERNEL_MACHINE_ENVBLK + sizeof (GRUB_ENVBLK_RDIR), prefix); /* Fill in the grub_module_info structure. */ modinfo = (struct grub_module_info *) (kernel_img + kernel_size); diff --git a/util/i386/pc/grub-setup.c b/util/i386/pc/grub-setup.c index 535a8d0..2a243e8 100644 --- a/util/i386/pc/grub-setup.c +++ b/util/i386/pc/grub-setup.c @@ -34,6 +34,7 @@ #include <grub/term.h> #include <grub/util/raid.h> #include <grub/util/lvm.h> +#include <grub/envblk.h> static const grub_gpt_part_type_t grub_gpt_partition_type_bios_boot = GRUB_GPT_PARTITION_TYPE_BIOS_BOOT; @@ -235,7 +236,10 @@ setup (const char *prefix, const char *dir, install_bsd_part = (grub_int32_t *) (core_img + GRUB_DISK_SECTOR_SIZE + GRUB_KERNEL_MACHINE_INSTALL_BSD_PART); install_prefix = (core_img + GRUB_DISK_SECTOR_SIZE - + GRUB_KERNEL_MACHINE_PREFIX); + + GRUB_KERNEL_MACHINE_ENVBLK); + + strcpy (install_prefix, GRUB_ENVBLK_RDIR "="); + install_prefix += sizeof (GRUB_ENVBLK_RDIR); /* Open the root device and the destination device. */ root_dev = grub_device_open (root);
_______________________________________________ Grub-devel mailing list Grub-devel@gnu.org http://lists.gnu.org/mailman/listinfo/grub-devel