* [PATCH] Environment block support for grub2 @ 2008-05-30 20:27 Bean 2008-05-31 10:10 ` Robert Millan 0 siblings, 1 reply; 23+ messages in thread From: Bean @ 2008-05-30 20:27 UTC (permalink / raw) To: The development of GRUB 2 [-- Attachment #1: Type: text/plain, Size: 2238 bytes --] 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 [-- Warning: decoded text below may be mangled, UTF-8 assumed --] [-- Attachment #2: envblk.diff --] [-- Type: text/x-diff; name=envblk.diff, Size: 24877 bytes --] 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); ^ permalink raw reply related [flat|nested] 23+ messages in thread
* Re: [PATCH] Environment block support for grub2 2008-05-30 20:27 [PATCH] Environment block support for grub2 Bean @ 2008-05-31 10:10 ` Robert Millan 2008-05-31 10:54 ` Bean 0 siblings, 1 reply; 23+ messages in thread From: Robert Millan @ 2008-05-31 10:10 UTC (permalink / raw) To: The development of GRUB 2 On Sat, May 31, 2008 at 04:27:31AM +0800, Bean wrote: > Hi, > > This patch add environment block support, which can be used to locate > root device using uuid or label. Nice :-) > The previous prefix is stored in variable rdir. Do we need this? > 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. Note that root and prefix don't necessarily have to point at the same device. prefix always points at the directory containing GRUB modules etc, and is needed at initial stage. root is used later on by grub.cfg to access our payload (I think our current use of root to initialise prefix is gratuitous and could better be avoided). Since for initialising root we don't have any problem, as we can use all the fancy stuff grub.cfg allows, unless I missed something I think it's better if at this stage we just focus on prefix. > 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: Would it be simpler if grub-mkimage embedded an initialised environment block directly? -- Robert Millan <GPLv2> I know my rights; I want my phone call! <DRM> What good is a phone call… if you are unable to speak? (as seen on /.) ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH] Environment block support for grub2 2008-05-31 10:10 ` Robert Millan @ 2008-05-31 10:54 ` Bean 2008-05-31 11:39 ` Robert Millan 0 siblings, 1 reply; 23+ messages in thread From: Bean @ 2008-05-31 10:54 UTC (permalink / raw) To: The development of GRUB 2 On Sat, May 31, 2008 at 6:10 PM, Robert Millan <rmh@aybabtu.com> wrote: >> 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. > > Note that root and prefix don't necessarily have to point at the same device. > > prefix always points at the directory containing GRUB modules etc, and is > needed at initial stage. root is used later on by grub.cfg to access our > payload (I think our current use of root to initialise prefix is gratuitous > and could better be avoided). > > Since for initialising root we don't have any problem, as we can use all > the fancy stuff grub.cfg allows, unless I missed something I think it's > better if at this stage we just focus on prefix. > The root is assigned in the initialization phraze. Currently, it's done this way: machine_machine_init -> calculate root device, then set variable prefix using root and grub_prefix. modules initialization grub_set_root_dev -> Use variable prefix to get the root variable. Load normal.mod As you can see, it first create prefix, then split it to find root. At the end of grub_set_root_dev, prefix and root will point to the same device. This also make it different to change the root setting in findroot, which is run in modules initialization stage. We must split prefix to find the root directory, and use the new root to form a new prefix. The prefix would later be split again to find root, what a mess. The new method: machine_machine_init -> calculate root device, then set root variable directly. Load variable in the environment block modules initialization findroot more modules initialization grub_set_root_dev -> Use variable root to get the root prefix. Load normal.mod The end result would be the same, but the new method is cleaner, and allows overwrite of the root and rdir variable using environment block and 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: > > Would it be simpler if grub-mkimage embedded an initialised environment > block directly? I think it's better to have a seperate tool to do this. Besides, grub-editenv can also be used to manage external environment block file, which is used to load/save persistent variable like default. -- Bean ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH] Environment block support for grub2 2008-05-31 10:54 ` Bean @ 2008-05-31 11:39 ` Robert Millan 2008-05-31 12:09 ` Bean 0 siblings, 1 reply; 23+ messages in thread From: Robert Millan @ 2008-05-31 11:39 UTC (permalink / raw) To: The development of GRUB 2 On Sat, May 31, 2008 at 06:54:43PM +0800, Bean wrote: > > The root is assigned in the initialization phraze. Currently, it's > done this way: > > machine_machine_init -> calculate root device, then set variable > prefix using root and grub_prefix. > > modules initialization > > grub_set_root_dev -> Use variable prefix to get the root variable. > > Load normal.mod > > As you can see, it first create prefix, then split it to find root. At > the end of grub_set_root_dev, prefix and root will point to the same > device. This also make it different to change the root setting in > findroot, which is run in modules initialization stage. We must split > prefix to find the root directory, and use the new root to form a new > prefix. The prefix would later be split again to find root, what a > mess. > > The new method: > > machine_machine_init -> calculate root device, then set root variable directly. > > Load variable in the environment block > > modules initialization > > findroot > > more modules initialization > > grub_set_root_dev -> Use variable root to get the root prefix. > > Load normal.mod > > The end result would be the same, but the new method is cleaner, and > allows overwrite of the root and rdir variable using environment block > and findroot. I think the method is sound; what I'm complaining about (and it's not something specific to your patch) is that we're referring to two different things by the same name ("root"), and even put them in the same variable. In the initialization phase, "root" is the device that contains our GRUB directory. Afterwards, "root" is the device we're currently accessing (be it for loading fonts, backgrounds, Linux images, whatever). If "root" means "just a placeholder for whatever device we're acessing at the moment", then it would make sense, but in our code (i.e. in the names we're giving to commands and functions) it's assumed to mean "the device containing /boot/grub". So what do we want to do with this? Should we have different variables for each thing (and in that case, is "root" for initial stage or for grub.cfg) or should we use "root" as a placeholder for any path reference, and adjust our function names etc to reflect that? -- Robert Millan <GPLv2> I know my rights; I want my phone call! <DRM> What good is a phone call… if you are unable to speak? (as seen on /.) ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH] Environment block support for grub2 2008-05-31 11:39 ` Robert Millan @ 2008-05-31 12:09 ` Bean 2008-05-31 15:09 ` Bean 2008-05-31 15:21 ` [PATCH] Environment block support for grub2 Robert Millan 0 siblings, 2 replies; 23+ messages in thread From: Bean @ 2008-05-31 12:09 UTC (permalink / raw) To: The development of GRUB 2 On Sat, May 31, 2008 at 7:39 PM, Robert Millan <rmh@aybabtu.com> wrote: > > I think the method is sound; what I'm complaining about (and it's not > something specific to your patch) is that we're referring to two different > things by the same name ("root"), and even put them in the same variable. > > In the initialization phase, "root" is the device that contains our GRUB > directory. > > Afterwards, "root" is the device we're currently accessing (be it for loading > fonts, backgrounds, Linux images, whatever). > > If "root" means "just a placeholder for whatever device we're acessing at the > moment", then it would make sense, but in our code (i.e. in the names we're > giving to commands and functions) it's assumed to mean "the device containing > /boot/grub". > > So what do we want to do with this? Should we have different variables for > each thing (and in that case, is "root" for initial stage or for grub.cfg) > or should we use "root" as a placeholder for any path reference, and adjust > our function names etc to reflect that? root is used in loaders as well, we shouldn't change its name. We could use another variable to store the root device at initial stage, it could actually be useful as it always points to the boot media. Perhaps we can name it "boot". What's your idea ? -- Bean ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH] Environment block support for grub2 2008-05-31 12:09 ` Bean @ 2008-05-31 15:09 ` Bean 2008-06-03 21:09 ` Robert Millan 2008-05-31 15:21 ` [PATCH] Environment block support for grub2 Robert Millan 1 sibling, 1 reply; 23+ messages in thread From: Bean @ 2008-05-31 15:09 UTC (permalink / raw) To: The development of GRUB 2 [-- Attachment #1: Type: text/plain, Size: 1234 bytes --] Hi, This is the new patch, it contain the following changes: 1. command edit -> set in grub-editenv, as it seems more natural. grub-editenv FILE set name=value ... 2. findroot can locate the root device using filename. To use it, just set idfile to any file inside the directory, For example: idfile=normal.mod Scan preference: uuid > label > idfile 3. Change the order device are reported in biosdisk, so that floppy appear last. 4. Add new command loadenv, which can be used to load/save environment variable. load_env [-f FILE] Load environment variable from external environment block file. The default file is $prefix/grubenv, but you can overwrite it with -f parameter. list_env [-f FILE] List the variables in external environment block file. save_env [-f FILE] variable_name .. Save the value of variable_name to external environment block file So, to archive the effect of savedefault command in grub legacy, you can use: load_env .. menuentry aa { .. save_env default } You can also use save_env to save the variable directly to core.img, but it's not recommended. The environment block inside core.img is quite small, it's mainly used to store critical variable like rdir, uuid, label and idfile. -- Bean [-- Warning: decoded text below may be mangled, UTF-8 assumed --] [-- Attachment #2: envblk_2.diff --] [-- Type: text/x-diff; name=envblk_2.diff, Size: 34863 bytes --] 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/commands/loadenv.c b/commands/loadenv.c new file mode 100755 index 0000000..970baf3 --- /dev/null +++ b/commands/loadenv.c @@ -0,0 +1,250 @@ +/* loadenv.c - command to load/save environment variable. */ +/* + * 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/normal.h> +#include <grub/dl.h> +#include <grub/mm.h> +#include <grub/arg.h> +#include <grub/file.h> +#include <grub/disk.h> +#include <grub/misc.h> +#include <grub/env.h> +#include <grub/envblk.h> + +static const struct grub_arg_option options[] = + { + {"file", 'f', 0, "specify filename", 0, ARG_TYPE_PATHNAME}, + {0, 0, 0, 0, 0, 0} + }; + +char buffer[GRUB_ENVBLK_MAXLEN]; +grub_envblk_t envblk; + +static grub_file_t +read_envblk_file (char *filename, void NESTED_FUNC_ATTR read_hook (grub_disk_addr_t sector, unsigned offset, unsigned length)) +{ + char *buf = 0; + grub_file_t file; + + if (! filename) + { + char *prefix; + + prefix = grub_env_get ("prefix"); + if (prefix) + { + int len; + + len = grub_strlen (prefix); + buf = grub_malloc (len + 1 + sizeof (GRUB_ENVBLK_DEFCFG)); + grub_strcpy (buf, prefix); + buf[len] = '/'; + grub_strcpy (buf + len + 1, GRUB_ENVBLK_DEFCFG); + filename = buf; + } + else + { + grub_error (GRUB_ERR_FILE_NOT_FOUND, "prefix is not found"); + return 0; + } + } + + file = grub_file_open (filename); + grub_free (buf); + if (! file) + return 0; + + if (read_hook) + { + if (! file->device->disk) + { + grub_file_close (file); + grub_error (GRUB_ERR_BAD_DEVICE, + "this command is available only for disk devices."); + return 0; + } + file->read_hook = read_hook; + } + + if (grub_file_read (file, buffer, GRUB_ENVBLK_MAXLEN) != GRUB_ENVBLK_MAXLEN) + { + grub_file_close (file); + grub_error (GRUB_ERR_BAD_FILE_TYPE, "file too short"); + return 0; + } + + envblk = grub_envblk_find (buffer); + if (! envblk) + { + grub_file_close (file); + grub_error (GRUB_ERR_BAD_FILE_TYPE, "environment block not found"); + return 0; + } + + return file; +} + +static grub_err_t +grub_cmd_load_env (struct grub_arg_list *state, + int argc __attribute__ ((unused)), char **args __attribute__ ((unused))) + +{ + grub_file_t file; + + auto int hook (char *name, char *value); + int hook (char *name, char *value) + { + grub_env_set (name, value); + + return 0; + } + + file = read_envblk_file ((state[0].set) ? state[0].arg : 0, 0); + if (! file) + return grub_errno; + + grub_file_close (file); + + grub_envblk_iterate (envblk, hook); + + return grub_errno; +} + +static grub_err_t +grub_cmd_list_env (struct grub_arg_list *state, + int argc __attribute__ ((unused)), char **args __attribute__ ((unused))) +{ + grub_file_t file; + + auto int hook (char *name, char *value); + int hook (char *name, char *value) + { + grub_printf ("%s=%s\n", name, value); + + return 0; + } + + file = read_envblk_file ((state[0].set) ? state[0].arg : 0, 0); + if (! file) + return grub_errno; + + grub_file_close (file); + + grub_envblk_iterate (envblk, hook); + + return grub_errno; +} + +static grub_err_t +grub_cmd_save_env (struct grub_arg_list *state, int argc, char **args) +{ + grub_file_t file; + grub_disk_t disk; + grub_disk_addr_t addr[GRUB_ENVBLK_MAXLEN >> GRUB_DISK_SECTOR_BITS]; + char buf[GRUB_DISK_SECTOR_SIZE]; + int num = 0; + + auto void NESTED_FUNC_ATTR hook (grub_disk_addr_t sector, unsigned offset, + unsigned length); + + void NESTED_FUNC_ATTR hook (grub_disk_addr_t sector, + unsigned offset, unsigned length) + { + if ((offset != 0) || (length != GRUB_DISK_SECTOR_SIZE)) + return; + + if (num < (GRUB_ENVBLK_MAXLEN >> GRUB_DISK_SECTOR_BITS)) + addr[num++] = sector; + } + + if (! argc) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "No variable is specified"); + + file = read_envblk_file ((state[0].set) ? state[0].arg : 0, hook); + if (! file) + return grub_errno; + + file->read_hook = 0; + + if (num != GRUB_ENVBLK_MAXLEN >> GRUB_DISK_SECTOR_BITS) + { + grub_error (GRUB_ERR_BAD_DEVICE, "invalid blocklist"); + goto quit; + } + + disk = file->device->disk; + for (num = 0; num < (GRUB_ENVBLK_MAXLEN >> GRUB_DISK_SECTOR_BITS); num++) + { + if (disk->dev->read (disk, addr[num], 1, buf)) + goto quit; + + if (grub_memcmp (&buffer[num << GRUB_DISK_SECTOR_BITS], buf, + GRUB_DISK_SECTOR_SIZE)) + { + grub_error (GRUB_ERR_BAD_DEVICE, "invalid blocklist"); + goto quit; + } + } + + while (argc) + { + char *value; + + value = grub_env_get (args[0]); + if (value) + { + if (grub_envblk_insert (envblk, args[0], value)) + { + grub_error (GRUB_ERR_BAD_ARGUMENT, "environment block too small"); + goto quit; + } + } + + argc--; + args++; + } + + for (num = 0; num < (GRUB_ENVBLK_MAXLEN >> GRUB_DISK_SECTOR_BITS); num++) + if (disk->dev->write (disk, addr[num], 1, + &buffer[num << GRUB_DISK_SECTOR_BITS])) + goto quit; + +quit: + grub_file_close (file); + + return grub_errno; +} + +GRUB_MOD_INIT(loadenv) +{ + (void) mod; + grub_register_command ("load_env", grub_cmd_load_env, GRUB_COMMAND_FLAG_BOTH, + "load_env [-f FILE]", "Load variables from environment block file.", options); + grub_register_command ("list_env", grub_cmd_list_env, GRUB_COMMAND_FLAG_BOTH, + "list_env [-f FILE]", "List variables from environment block file.", options); + grub_register_command ("save_env", grub_cmd_save_env, GRUB_COMMAND_FLAG_BOTH, + "save_env [-f FILE] variable_name [...]", "Save variables to environment block file.", options); +} + +GRUB_MOD_FINI(loadenv) +{ + grub_unregister_command ("load_env"); + grub_unregister_command ("list_env"); + grub_unregister_command ("save_env"); +} diff --git a/conf/common.rmk b/conf/common.rmk index acbebc7..99252ac 100644 --- a/conf/common.rmk +++ b/conf/common.rmk @@ -94,6 +94,11 @@ 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 +CLEANFILES += grub-editenv + # For update-grub update-grub: util/update-grub.in config.status ./config.status --file=$@:$< @@ -282,7 +287,7 @@ pkglib_MODULES += hello.mod boot.mod terminal.mod ls.mod \ cmp.mod cat.mod help.mod font.mod search.mod \ loopback.mod configfile.mod echo.mod \ terminfo.mod test.mod blocklist.mod hexdump.mod \ - read.mod sleep.mod + read.mod sleep.mod loadenv.mod # For hello.mod. hello_mod_SOURCES = hello/hello.c @@ -364,8 +369,23 @@ hexdump_mod_SOURCES = commands/hexdump.c hexdump_mod_CFLAGS = $(COMMON_CFLAGS) hexdump_mod_LDFLAGS = $(COMMON_LDFLAGS) +# For read.mod. +read_mod_SOURCES = commands/read.c +read_mod_CFLAGS = $(COMMON_CFLAGS) +read_mod_LDFLAGS = $(COMMON_LDFLAGS) + +# For sleep.mod. +sleep_mod_SOURCES = commands/sleep.c +sleep_mod_CFLAGS = $(COMMON_CFLAGS) +sleep_mod_LDFLAGS = $(COMMON_LDFLAGS) + +# For loadenv.mod. +loadenv_mod_SOURCES = commands/loadenv.c util/envblk.c +loadenv_mod_CFLAGS = $(COMMON_CFLAGS) +loadenv_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 @@ -377,12 +397,7 @@ gzio_mod_SOURCES = io/gzio.c gzio_mod_CFLAGS = $(COMMON_CFLAGS) gzio_mod_LDFLAGS = $(COMMON_LDFLAGS) -# For read.mod. -read_mod_SOURCES = commands/read.c -read_mod_CFLAGS = $(COMMON_CFLAGS) -read_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For sleep.mod. -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/disk/i386/pc/biosdisk.c b/disk/i386/pc/biosdisk.c index 094bde0..6e5292f 100644 --- a/disk/i386/pc/biosdisk.c +++ b/disk/i386/pc/biosdisk.c @@ -66,12 +66,6 @@ grub_biosdisk_iterate (int (*hook) (const char *name)) int drive; int num_floppies; - /* For floppy disks, we can get the number safely. */ - num_floppies = grub_biosdisk_get_num_floppies (); - for (drive = 0; drive < num_floppies; drive++) - if (grub_biosdisk_call_hook (hook, drive)) - return 1; - /* For hard disks, attempt to read the MBR. */ for (drive = 0x80; drive < 0x90; drive++) { @@ -92,6 +86,12 @@ grub_biosdisk_iterate (int (*hook) (const char *name)) return 1; } + /* For floppy disks, we can get the number safely. */ + num_floppies = grub_biosdisk_get_num_floppies (); + for (drive = 0; drive < num_floppies; drive++) + if (grub_biosdisk_call_hook (hook, drive)) + return 1; + return 0; } diff --git a/include/grub/envblk.h b/include/grub/envblk.h new file mode 100755 index 0000000..e075089 --- /dev/null +++ b/include/grub/envblk.h @@ -0,0 +1,51 @@ +/* + * 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" +#define GRUB_ENVBLK_IDFILE "idfile" + +#define GRUB_ENVBLK_DEFCFG "grubenv" + +#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); +void grub_envblk_iterate (grub_envblk_t envblk, int hook (char *name, char *value)); + +#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..44d5eb8 --- /dev/null +++ b/kern/findroot.c @@ -0,0 +1,110 @@ +/* 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> +#include <grub/envblk.h> + +static void +findroot (void) +{ + char *label, *uuid, *idfile, *rdir; + int found = 0; + + auto int iterate_rdir (const char *filename, int dir); + int iterate_rdir (const char *filename, int dir) + { + (void) dir; + + found = (! grub_strcmp (filename, idfile)); + return found; + } + + auto int iterate_device (const char *name); + int iterate_device (const char *name) + { + 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); + } + } + else if (idfile) + fs->dir (dev, rdir, iterate_rdir); + + if (found) + grub_env_set ("root", name); + } + + grub_device_close (dev); + } + + grub_errno = GRUB_ERR_NONE; + return found; + } + + uuid = grub_env_get (GRUB_ENVBLK_UUID); + label = grub_env_get (GRUB_ENVBLK_LABEL); + idfile = grub_env_get (GRUB_ENVBLK_IDFILE); + rdir = grub_env_get (GRUB_ENVBLK_RDIR); + if (! rdir) + rdir = "/"; + + if ((! label) && (! uuid) && (! idfile)) + 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..5b27062 --- /dev/null +++ b/util/envblk.c @@ -0,0 +1,171 @@ +/* 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/envblk.h> + +#ifdef GRUB_UTIL + +#include <string.h> + +#define grub_strlen strlen +#define grub_strcpy strcpy +#define grub_strchr strchr +#define grub_memcmp memcmp +#define grub_memcpy memcpy + +#else + +#include <grub/misc.h> + +#endif + +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 += grub_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 += grub_strlen (p) + 1; + if (p >= pend) + return; + } + + if (found) + { + int len; + + len = grub_strlen (found); + grub_memcpy (found, found + len + 1, (p - found) - len); + } +} + +void +grub_envblk_iterate (grub_envblk_t envblk, + int hook (char *name, char *value)) +{ + char *p, *pend; + + p = envblk->data; + pend = p + envblk->length; + + while (*p) + { + char *v; + int r; + + v = grub_strchr (p, '='); + if (v) + { + *v = 0; + r = hook (p, v + 1); + *v = '='; + } + else + r = hook (p, ""); + + if (r) + break; + + p += grub_strlen (p) + 1; + if (p >= pend) + break; + } +} diff --git a/util/grub-editenv.c b/util/grub-editenv.c new file mode 100755 index 0000000..8c08694 --- /dev/null +++ b/util/grub-editenv.c @@ -0,0 +1,228 @@ +/* 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> + +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\ + set [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, "wb"); + 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+b"); + 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", envblk->data - buffer); + printf ("Envblk length: %d\n", envblk->length); +} + +static void +cmd_list (void) +{ + auto int hook (char *name, char *value); + int hook (char *name, char *value) + { + printf ("%s=%s\n", name, value); + return 0; + } + + grub_envblk_iterate (envblk, hook); +} + +static void +cmd_set (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], "set")) + cmd_set (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); ^ permalink raw reply related [flat|nested] 23+ messages in thread
* Re: [PATCH] Environment block support for grub2 2008-05-31 15:09 ` Bean @ 2008-06-03 21:09 ` Robert Millan 2008-06-04 3:49 ` Bean 0 siblings, 1 reply; 23+ messages in thread From: Robert Millan @ 2008-06-03 21:09 UTC (permalink / raw) To: The development of GRUB 2 I've been thinking a bit more about this, and I think it should be possible to solve the problem at hand without extending the existing framework. I'm concerned about finding a solution that is as simple (and small) as possible. Do you mind waiting a few days? I'll send a proposal tomorrow or so. -- Robert Millan <GPLv2> I know my rights; I want my phone call! <DRM> What good is a phone call… if you are unable to speak? (as seen on /.) ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH] Environment block support for grub2 2008-06-03 21:09 ` Robert Millan @ 2008-06-04 3:49 ` Bean 2008-06-06 16:43 ` UUID-based boot (Re: [PATCH] Environment block support for grub2) Robert Millan 0 siblings, 1 reply; 23+ messages in thread From: Bean @ 2008-06-04 3:49 UTC (permalink / raw) To: The development of GRUB 2 On Wed, Jun 4, 2008 at 5:09 AM, Robert Millan <rmh@aybabtu.com> wrote: > > I've been thinking a bit more about this, and I think it should be > possible to solve the problem at hand without extending the existing > framework. I'm concerned about finding a solution that is as simple > (and small) as possible. > > Do you mind waiting a few days? I'll send a proposal tomorrow or so. Ok, no hurry. -- Bean ^ permalink raw reply [flat|nested] 23+ messages in thread
* UUID-based boot (Re: [PATCH] Environment block support for grub2) 2008-06-04 3:49 ` Bean @ 2008-06-06 16:43 ` Robert Millan 2008-06-06 17:22 ` Bean 0 siblings, 1 reply; 23+ messages in thread From: Robert Millan @ 2008-06-06 16:43 UTC (permalink / raw) To: The development of GRUB 2 [-- Attachment #1: Type: text/plain, Size: 1519 bytes --] On Wed, Jun 04, 2008 at 11:49:14AM +0800, Bean wrote: > On Wed, Jun 4, 2008 at 5:09 AM, Robert Millan <rmh@aybabtu.com> wrote: > > > > I've been thinking a bit more about this, and I think it should be > > possible to solve the problem at hand without extending the existing > > framework. I'm concerned about finding a solution that is as simple > > (and small) as possible. > > > > Do you mind waiting a few days? I'll send a proposal tomorrow or so. > > Ok, no hurry. Sorry for the delay; it was quite a bit of work as I got hit by a number of bugs here and there :-) Considering that the problem was quite similar to the "boot from LVM" issue we already knew about, I thought it'd be a good idea to start with that. Although not directly related, the patch at in "boot from LVM / RAID" mail I just sent would allow to easily boot via UUID as well. If we add a UUID-based disk driver (see "disk/fs_uuid.c" mail), then it's just a matter of increasing the grub_prefix size so that an UUID can fit in it, and adjusting the install scripts to do it. Here's a sample (untested) patch to illustrate it. Then for the Vista use case, I suppose the remaining questions are if NTFS supports UUIDs (or otherwise we have to ressort to labels?), and if we can extract filesystem metadata from Windows (if possible without requiring that a Cygwin installation is present). -- Robert Millan <GPLv2> I know my rights; I want my phone call! <DRM> What good is a phone call… if you are unable to speak? (as seen on /.) [-- Attachment #2: uuid_boot.diff --] [-- Type: text/x-diff, Size: 2359 bytes --] diff -x ChangeLog -x configure -x config.h.in -x CVS -x '*~' -x '*.mk' -urp ../tmp.old/include/grub/i386/pc/kernel.h ./include/grub/i386/pc/kernel.h --- ../tmp.old/include/grub/i386/pc/kernel.h 2008-06-06 18:29:28.000000000 +0200 +++ ./include/grub/i386/pc/kernel.h 2008-06-06 18:32:27.000000000 +0200 @@ -41,7 +41,7 @@ #define GRUB_KERNEL_MACHINE_PREFIX 0x20 /* End of the data section. */ -#define GRUB_KERNEL_MACHINE_DATA_END 0x50 +#define GRUB_KERNEL_MACHINE_DATA_END 0x60 /* The size of the first region which won't be compressed. */ #define GRUB_KERNEL_MACHINE_RAW_SIZE (GRUB_KERNEL_MACHINE_DATA_END + 0x450) diff -x ChangeLog -x configure -x config.h.in -x CVS -x '*~' -x '*.mk' -urp ../tmp.old/util/i386/pc/grub-install.in ./util/i386/pc/grub-install.in --- ../tmp.old/util/i386/pc/grub-install.in 2008-06-06 18:30:02.000000000 +0200 +++ ./util/i386/pc/grub-install.in 2008-06-06 18:33:26.000000000 +0200 @@ -232,13 +232,13 @@ partmap_module=`$grub_probe --target=par devabstraction_module=`$grub_probe --target=abstraction --device ${grub_device}` if [ "x${devabstraction_module}" = "x" ] ; then - prefix_drive= + prefix_drive=\(UUID=`$grub_probe --target=fs_uuid --device ${grub_device}`\) else prefix_drive=`$grub_probe --target=drive --device ${grub_device}` fi # _chain is often useful -modules="$modules $fs_module $partmap_module biosdisk $devabstraction_module _chain" +modules="$modules $fs_module $partmap_module biosdisk $devabstraction_module _chain fs_uuid" $grub_mkimage --output=${grubdir}/core.img \ --prefix=${prefix_drive}`make_system_path_relative_to_its_root ${grubdir}`/ \ diff -x ChangeLog -x configure -x config.h.in -x CVS -x '*~' -x '*.mk' -urp ../tmp.old/util/i386/pc/grub-setup.c ./util/i386/pc/grub-setup.c --- ../tmp.old/util/i386/pc/grub-setup.c 2008-06-06 18:30:02.000000000 +0200 +++ ./util/i386/pc/grub-setup.c 2008-06-06 18:32:27.000000000 +0200 @@ -300,7 +300,9 @@ setup (const char *prefix, const char *d block->segment = 0; /* Embed information about the installed location. */ - if (must_embed) + if (install_prefix[0] == '(') + /* If we included a drive explicitly in prefix, force GRUB to use that instead + of root_drive. */ *install_dos_part = *install_bsd_part = grub_cpu_to_le32 (-2); else if (root_dev->disk->partition) { ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: UUID-based boot (Re: [PATCH] Environment block support for grub2) 2008-06-06 16:43 ` UUID-based boot (Re: [PATCH] Environment block support for grub2) Robert Millan @ 2008-06-06 17:22 ` Bean 2008-06-06 22:03 ` Robert Millan 2008-06-06 23:31 ` [PATCH] ntfs UUIDs (Re: UUID-based boot (Re: [PATCH] Environment block support for grub2)) Robert Millan 0 siblings, 2 replies; 23+ messages in thread From: Bean @ 2008-06-06 17:22 UTC (permalink / raw) To: The development of GRUB 2 On Sat, Jun 7, 2008 at 12:43 AM, Robert Millan <rmh@aybabtu.com> wrote: > Sorry for the delay; it was quite a bit of work as I got hit by a number of > bugs here and there :-) > > Considering that the problem was quite similar to the "boot from LVM" issue > we already knew about, I thought it'd be a good idea to start with that. > > Although not directly related, the patch at in "boot from LVM / RAID" mail I > just sent would allow to easily boot via UUID as well. > > If we add a UUID-based disk driver (see "disk/fs_uuid.c" mail), then it's just > a matter of increasing the grub_prefix size so that an UUID can fit in it, and > adjusting the install scripts to do it. > > Here's a sample (untested) patch to illustrate it. I take a quick look at your patch, the method should work, but i remember okuji oppose embedding device name in prefix, don't know how he look at it now. > > Then for the Vista use case, I suppose the remaining questions are if NTFS > supports UUIDs (or otherwise we have to ressort to labels?), and if we can > extract filesystem metadata from Windows (if possible without requiring that > a Cygwin installation is present). ntfs has a 64-bit serial number, it's not quite the same as uuid, but it can be used to identify the partition. -- Bean ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: UUID-based boot (Re: [PATCH] Environment block support for grub2) 2008-06-06 17:22 ` Bean @ 2008-06-06 22:03 ` Robert Millan 2008-06-07 4:33 ` Bean 2008-06-07 7:24 ` Vesa Jääskeläinen 2008-06-06 23:31 ` [PATCH] ntfs UUIDs (Re: UUID-based boot (Re: [PATCH] Environment block support for grub2)) Robert Millan 1 sibling, 2 replies; 23+ messages in thread From: Robert Millan @ 2008-06-06 22:03 UTC (permalink / raw) To: The development of GRUB 2; +Cc: Yoshinori K. Okuji On Sat, Jun 07, 2008 at 01:22:23AM +0800, Bean wrote: > On Sat, Jun 7, 2008 at 12:43 AM, Robert Millan <rmh@aybabtu.com> wrote: > > Sorry for the delay; it was quite a bit of work as I got hit by a number of > > bugs here and there :-) > > > > Considering that the problem was quite similar to the "boot from LVM" issue > > we already knew about, I thought it'd be a good idea to start with that. > > > > Although not directly related, the patch at in "boot from LVM / RAID" mail I > > just sent would allow to easily boot via UUID as well. > > > > If we add a UUID-based disk driver (see "disk/fs_uuid.c" mail), then it's just > > a matter of increasing the grub_prefix size so that an UUID can fit in it, and > > adjusting the install scripts to do it. > > > > Here's a sample (untested) patch to illustrate it. > > I take a quick look at your patch, the method should work, but i > remember okuji oppose embedding device name in prefix, don't know how > he look at it now. Do you remember why? (or where it was discussed) Anyway, CCing him. Okuji, please say something! :-) -- Robert Millan <GPLv2> I know my rights; I want my phone call! <DRM> What good is a phone call… if you are unable to speak? (as seen on /.) ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: UUID-based boot (Re: [PATCH] Environment block support for grub2) 2008-06-06 22:03 ` Robert Millan @ 2008-06-07 4:33 ` Bean 2008-06-08 19:26 ` Robert Millan 2008-06-07 7:24 ` Vesa Jääskeläinen 1 sibling, 1 reply; 23+ messages in thread From: Bean @ 2008-06-07 4:33 UTC (permalink / raw) To: The development of GRUB 2 On Sat, Jun 7, 2008 at 6:03 AM, Robert Millan <rmh@aybabtu.com> wrote: > On Sat, Jun 07, 2008 at 01:22:23AM +0800, Bean wrote: >> On Sat, Jun 7, 2008 at 12:43 AM, Robert Millan <rmh@aybabtu.com> wrote: >> > Sorry for the delay; it was quite a bit of work as I got hit by a number of >> > bugs here and there :-) >> > >> > Considering that the problem was quite similar to the "boot from LVM" issue >> > we already knew about, I thought it'd be a good idea to start with that. >> > >> > Although not directly related, the patch at in "boot from LVM / RAID" mail I >> > just sent would allow to easily boot via UUID as well. >> > >> > If we add a UUID-based disk driver (see "disk/fs_uuid.c" mail), then it's just >> > a matter of increasing the grub_prefix size so that an UUID can fit in it, and >> > adjusting the install scripts to do it. >> > >> > Here's a sample (untested) patch to illustrate it. >> >> I take a quick look at your patch, the method should work, but i >> remember okuji oppose embedding device name in prefix, don't know how >> he look at it now. > > Do you remember why? (or where it was discussed) > > Anyway, CCing him. Okuji, please say something! :-) Hi, I find the post: http://lists.gnu.org/archive/html/grub-devel/2008-02/msg00542.html -- Bean ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: UUID-based boot (Re: [PATCH] Environment block support for grub2) 2008-06-07 4:33 ` Bean @ 2008-06-08 19:26 ` Robert Millan 0 siblings, 0 replies; 23+ messages in thread From: Robert Millan @ 2008-06-08 19:26 UTC (permalink / raw) To: The development of GRUB 2 On Sat, Jun 07, 2008 at 12:33:47PM +0800, Bean wrote: > > Hi, > > I find the post: > > http://lists.gnu.org/archive/html/grub-devel/2008-02/msg00542.html I completely agree. The patch I sent makes it rely on UUIDs unconditionaly because it was just a proof of concept, but my intention is to only use UUIDs when at grub-install time we determined that there's no reliable way to find the root drive. I would handle the following cases in the installer: - If the boot drive is the same as the root drive, the BIOS will tell us about it at boot time, so we don't use UUIDs. - If the root drive is LVM or RAID, we can reliably identify it by its LVM or RAID name, so there's no need to ressort to UUIDs. - If the boot drive is different than the root drive, often a device.map guess will work, but not always. So we use UUIDs whenever they're available. What do you think? -- Robert Millan <GPLv2> I know my rights; I want my phone call! <DRM> What good is a phone call… if you are unable to speak? (as seen on /.) ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: UUID-based boot (Re: [PATCH] Environment block support for grub2) 2008-06-06 22:03 ` Robert Millan 2008-06-07 4:33 ` Bean @ 2008-06-07 7:24 ` Vesa Jääskeläinen 1 sibling, 0 replies; 23+ messages in thread From: Vesa Jääskeläinen @ 2008-06-07 7:24 UTC (permalink / raw) To: The development of GRUB 2 Robert Millan wrote: > On Sat, Jun 07, 2008 at 01:22:23AM +0800, Bean wrote: >> On Sat, Jun 7, 2008 at 12:43 AM, Robert Millan <rmh@aybabtu.com> wrote: >>> Sorry for the delay; it was quite a bit of work as I got hit by a number of >>> bugs here and there :-) >>> >>> Considering that the problem was quite similar to the "boot from LVM" issue >>> we already knew about, I thought it'd be a good idea to start with that. >>> >>> Although not directly related, the patch at in "boot from LVM / RAID" mail I >>> just sent would allow to easily boot via UUID as well. >>> >>> If we add a UUID-based disk driver (see "disk/fs_uuid.c" mail), then it's just >>> a matter of increasing the grub_prefix size so that an UUID can fit in it, and >>> adjusting the install scripts to do it. >>> >>> Here's a sample (untested) patch to illustrate it. >> I take a quick look at your patch, the method should work, but i >> remember okuji oppose embedding device name in prefix, don't know how >> he look at it now. > > Do you remember why? (or where it was discussed) > > Anyway, CCing him. Okuji, please say something! :-) > I thinks its related to recovery for server platforms. Anyway... Should we start creating use cases to wiki in what failure situations grub can face and then we can see how it can perform those situations. ^ permalink raw reply [flat|nested] 23+ messages in thread
* [PATCH] ntfs UUIDs (Re: UUID-based boot (Re: [PATCH] Environment block support for grub2)) 2008-06-06 17:22 ` Bean 2008-06-06 22:03 ` Robert Millan @ 2008-06-06 23:31 ` Robert Millan 2008-06-07 5:44 ` Tomáš Ebenlendr 1 sibling, 1 reply; 23+ messages in thread From: Robert Millan @ 2008-06-06 23:31 UTC (permalink / raw) To: The development of GRUB 2 [-- Attachment #1: Type: text/plain, Size: 787 bytes --] On Sat, Jun 07, 2008 at 01:22:23AM +0800, Bean wrote: > > Then for the Vista use case, I suppose the remaining questions are if NTFS > > supports UUIDs (or otherwise we have to ressort to labels?), and if we can > > extract filesystem metadata from Windows (if possible without requiring that > > a Cygwin installation is present). > > ntfs has a 64-bit serial number, it's not quite the same as uuid, but > it can be used to identify the partition. This patch adds the 64-bit serial number as UUID. But I'm not sure what is the "standard" method to stringify this number. Apparently, Windows only prints half of it in the dir command. -- Robert Millan <GPLv2> I know my rights; I want my phone call! <DRM> What good is a phone call… if you are unable to speak? (as seen on /.) [-- Attachment #2: ntfs_uuid.diff --] [-- Type: text/x-diff, Size: 2181 bytes --] diff -x ChangeLog -x configure -x config.h.in -x CVS -x '*~' -x '*.mk' -urp ../grub2/fs/ntfs.c ./fs/ntfs.c --- ../grub2/fs/ntfs.c 2008-05-29 15:02:13.000000000 +0200 +++ ./fs/ntfs.c 2008-06-07 01:28:13.000000000 +0200 @@ -830,6 +830,8 @@ grub_ntfs_mount (grub_disk_t disk) (disk, data->mft_start, 0, data->mft_size << BLK_SHR, data->mmft.buf)) goto fail; + *((grub_uint64_t *) &data->uuid) = bpb.num_serial; + if (fixup (data, data->mmft.buf, data->mft_size, "FILE")) goto fail; @@ -1078,6 +1080,36 @@ fail: return grub_errno; } +static grub_err_t +grub_ntfs_uuid (grub_device_t device, char **uuid) +{ + struct grub_ntfs_data *data; + grub_disk_t disk = device->disk; + +#ifndef GRUB_UTIL + grub_dl_ref (my_mod); +#endif + + data = grub_ntfs_mount (disk); + if (data) + { + *uuid = grub_malloc (sizeof ("xxxx-xxxx-xxxx-xxxx")); + grub_sprintf (*uuid, "%04x-%04x-%04x-%04x", + grub_le_to_cpu16 (data->uuid[0]), grub_le_to_cpu16 (data->uuid[1]), + grub_le_to_cpu16 (data->uuid[2]), grub_le_to_cpu16 (data->uuid[3])); + } + else + *uuid = NULL; + +#ifndef GRUB_UTIL + grub_dl_unref (my_mod); +#endif + + grub_free (data); + + return grub_errno; +} + static struct grub_fs grub_ntfs_fs = { .name = "ntfs", .dir = grub_ntfs_dir, @@ -1085,6 +1117,7 @@ static struct grub_fs grub_ntfs_fs = { .read = grub_ntfs_read, .close = grub_ntfs_close, .label = grub_ntfs_label, + .uuid = grub_ntfs_uuid, .next = 0 }; diff -x ChangeLog -x configure -x config.h.in -x CVS -x '*~' -x '*.mk' -urp ../grub2/include/grub/ntfs.h ./include/grub/ntfs.h --- ../grub2/include/grub/ntfs.h 2008-04-07 16:34:45.000000000 +0200 +++ ./include/grub/ntfs.h 2008-06-07 01:17:44.000000000 +0200 @@ -115,7 +115,7 @@ struct grub_ntfs_bpb grub_int8_t reserved_4[3]; grub_int8_t clusters_per_index; grub_int8_t reserved_5[3]; - grub_uint64_t serial_number; + grub_uint64_t num_serial; grub_uint32_t checksum; } __attribute__ ((packed)); @@ -151,6 +151,7 @@ struct grub_ntfs_data grub_uint32_t spc; grub_uint32_t blocksize; grub_uint32_t mft_start; + grub_uint16_t uuid[4]; }; struct grub_ntfs_comp ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH] ntfs UUIDs (Re: UUID-based boot (Re: [PATCH] Environment block support for grub2)) 2008-06-06 23:31 ` [PATCH] ntfs UUIDs (Re: UUID-based boot (Re: [PATCH] Environment block support for grub2)) Robert Millan @ 2008-06-07 5:44 ` Tomáš Ebenlendr 2008-06-08 3:34 ` Pavel Roskin 0 siblings, 1 reply; 23+ messages in thread From: Tomáš Ebenlendr @ 2008-06-07 5:44 UTC (permalink / raw) To: The development of GRUB 2 Dne 7 Červen 2008, 01:31, Robert Millan napsal(a): > This patch adds the 64-bit serial number as UUID. But I'm not sure what > is the "standard" method to stringify this number. Apparently, Windows > only prints half of it in the dir command. That seems to me as some backward (pronounce: awkward) compatibility of M$ Volume ID. Volume ID in M$ windows is (as you say) 'xxxx-xxxx' two 16 bit hexadecimal numbers. And all programs I tested report the number this way. So if we want user to enter these numbers manually we should ignore the remaining four bits. Alternatively we can provide utility that prints out whole serial number. -- Tomas Ebenlendr http://drak.ucw.cz/~ebik ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH] ntfs UUIDs (Re: UUID-based boot (Re: [PATCH] Environment block support for grub2)) 2008-06-07 5:44 ` Tomáš Ebenlendr @ 2008-06-08 3:34 ` Pavel Roskin 2008-06-08 19:19 ` Robert Millan 0 siblings, 1 reply; 23+ messages in thread From: Pavel Roskin @ 2008-06-08 3:34 UTC (permalink / raw) To: The development of GRUB 2 On Sat, 2008-06-07 at 07:44 +0200, Tomáš Ebenlendr wrote: > Dne 7 Červen 2008, 01:31, Robert Millan napsal(a): > > This patch adds the 64-bit serial number as UUID. But I'm not sure what > > is the "standard" method to stringify this number. Apparently, Windows > > only prints half of it in the dir command. > > That seems to me as some backward (pronounce: awkward) compatibility of > M$ Volume ID. Volume ID in M$ windows is (as you say) 'xxxx-xxxx' two > 16 bit hexadecimal numbers. And all programs I tested report the number > this way. So if we want user to enter these numbers manually we should > ignore the remaining four bits. Alternatively we can provide utility that > prints out whole serial number. I suggest that you check udev sources: http://www.us.kernel.org/pub/linux/utils/kernel/hotplug/ It calculates UUID for many filesystems (see extras/lib/volime_id/lib). It would be nice to stay compatible with udev. -- Regards, Pavel Roskin ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH] ntfs UUIDs (Re: UUID-based boot (Re: [PATCH] Environment block support for grub2)) 2008-06-08 3:34 ` Pavel Roskin @ 2008-06-08 19:19 ` Robert Millan 0 siblings, 0 replies; 23+ messages in thread From: Robert Millan @ 2008-06-08 19:19 UTC (permalink / raw) To: The development of GRUB 2 On Sat, Jun 07, 2008 at 11:34:39PM -0400, Pavel Roskin wrote: > On Sat, 2008-06-07 at 07:44 +0200, Tomáš Ebenlendr wrote: > > Dne 7 Červen 2008, 01:31, Robert Millan napsal(a): > > > This patch adds the 64-bit serial number as UUID. But I'm not sure what > > > is the "standard" method to stringify this number. Apparently, Windows > > > only prints half of it in the dir command. > > > > That seems to me as some backward (pronounce: awkward) compatibility of > > M$ Volume ID. Volume ID in M$ windows is (as you say) 'xxxx-xxxx' two > > 16 bit hexadecimal numbers. And all programs I tested report the number > > this way. So if we want user to enter these numbers manually we should > > ignore the remaining four bits. Alternatively we can provide utility that > > prints out whole serial number. > > I suggest that you check udev sources: > http://www.us.kernel.org/pub/linux/utils/kernel/hotplug/ > > It calculates UUID for many filesystems (see extras/lib/volime_id/lib). > It would be nice to stay compatible with udev. Ok. I adjusted it to output the same format as vol_id and committed. Turns out this was the simplest to implement (get a 64-bit LE and print right away). -- Robert Millan <GPLv2> I know my rights; I want my phone call! <DRM> What good is a phone call… if you are unable to speak? (as seen on /.) ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH] Environment block support for grub2 2008-05-31 12:09 ` Bean 2008-05-31 15:09 ` Bean @ 2008-05-31 15:21 ` Robert Millan 2008-06-13 22:48 ` Yoshinori K. Okuji 1 sibling, 1 reply; 23+ messages in thread From: Robert Millan @ 2008-05-31 15:21 UTC (permalink / raw) To: The development of GRUB 2; +Cc: Yoshinori K. Okuji On Sat, May 31, 2008 at 08:09:50PM +0800, Bean wrote: > On Sat, May 31, 2008 at 7:39 PM, Robert Millan <rmh@aybabtu.com> wrote: > > > > I think the method is sound; what I'm complaining about (and it's not > > something specific to your patch) is that we're referring to two different > > things by the same name ("root"), and even put them in the same variable. > > > > In the initialization phase, "root" is the device that contains our GRUB > > directory. > > > > Afterwards, "root" is the device we're currently accessing (be it for loading > > fonts, backgrounds, Linux images, whatever). > > > > If "root" means "just a placeholder for whatever device we're acessing at the > > moment", then it would make sense, but in our code (i.e. in the names we're > > giving to commands and functions) it's assumed to mean "the device containing > > /boot/grub". > > > > So what do we want to do with this? Should we have different variables for > > each thing (and in that case, is "root" for initial stage or for grub.cfg) > > or should we use "root" as a placeholder for any path reference, and adjust > > our function names etc to reflect that? > > root is used in loaders as well, we shouldn't change its name. We > could use another variable to store the root device at initial stage, > it could actually be useful as it always points to the boot media. > Perhaps we can name it "boot". What's your idea ? I'm fine with "boot". I'm CCing Okuji; would like to make sure he doesn't have any objections (I think it was he who gave it this layout). -- Robert Millan <GPLv2> I know my rights; I want my phone call! <DRM> What good is a phone call… if you are unable to speak? (as seen on /.) ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH] Environment block support for grub2 2008-05-31 15:21 ` [PATCH] Environment block support for grub2 Robert Millan @ 2008-06-13 22:48 ` Yoshinori K. Okuji 2008-06-14 3:41 ` Bean 0 siblings, 1 reply; 23+ messages in thread From: Yoshinori K. Okuji @ 2008-06-13 22:48 UTC (permalink / raw) To: grub-devel; +Cc: Robert Millan On Saturday 31 May 2008 17:21:25 Robert Millan wrote: > On Sat, May 31, 2008 at 08:09:50PM +0800, Bean wrote: > > On Sat, May 31, 2008 at 7:39 PM, Robert Millan <rmh@aybabtu.com> wrote: > > > I think the method is sound; what I'm complaining about (and it's not > > > something specific to your patch) is that we're referring to two > > > different things by the same name ("root"), and even put them in the > > > same variable. > > > > > > In the initialization phase, "root" is the device that contains our > > > GRUB directory. > > > > > > Afterwards, "root" is the device we're currently accessing (be it for > > > loading fonts, backgrounds, Linux images, whatever). > > > > > > If "root" means "just a placeholder for whatever device we're acessing > > > at the moment", then it would make sense, but in our code (i.e. in the > > > names we're giving to commands and functions) it's assumed to mean "the > > > device containing /boot/grub". > > > > > > So what do we want to do with this? Should we have different variables > > > for each thing (and in that case, is "root" for initial stage or for > > > grub.cfg) or should we use "root" as a placeholder for any path > > > reference, and adjust our function names etc to reflect that? > > > > root is used in loaders as well, we shouldn't change its name. We > > could use another variable to store the root device at initial stage, > > it could actually be useful as it always points to the boot media. > > Perhaps we can name it "boot". What's your idea ? > > I'm fine with "boot". I'm CCing Okuji; would like to make sure he doesn't > have any objections (I think it was he who gave it this layout). "boot" is used for a command, so it is very confusing to use the same name for a variable. If you want to have this kind of variable, please find another name. I myself have no idea. Okuji ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH] Environment block support for grub2 2008-06-13 22:48 ` Yoshinori K. Okuji @ 2008-06-14 3:41 ` Bean 2008-06-14 18:32 ` Robert Millan 0 siblings, 1 reply; 23+ messages in thread From: Bean @ 2008-06-14 3:41 UTC (permalink / raw) To: The development of GRUB 2 On Sat, Jun 14, 2008 at 6:48 AM, Yoshinori K. Okuji <okuji@enbug.org> wrote: > On Saturday 31 May 2008 17:21:25 Robert Millan wrote: >> On Sat, May 31, 2008 at 08:09:50PM +0800, Bean wrote: >> > On Sat, May 31, 2008 at 7:39 PM, Robert Millan <rmh@aybabtu.com> wrote: >> > > I think the method is sound; what I'm complaining about (and it's not >> > > something specific to your patch) is that we're referring to two >> > > different things by the same name ("root"), and even put them in the >> > > same variable. >> > > >> > > In the initialization phase, "root" is the device that contains our >> > > GRUB directory. >> > > >> > > Afterwards, "root" is the device we're currently accessing (be it for >> > > loading fonts, backgrounds, Linux images, whatever). >> > > >> > > If "root" means "just a placeholder for whatever device we're acessing >> > > at the moment", then it would make sense, but in our code (i.e. in the >> > > names we're giving to commands and functions) it's assumed to mean "the >> > > device containing /boot/grub". >> > > >> > > So what do we want to do with this? Should we have different variables >> > > for each thing (and in that case, is "root" for initial stage or for >> > > grub.cfg) or should we use "root" as a placeholder for any path >> > > reference, and adjust our function names etc to reflect that? >> > >> > root is used in loaders as well, we shouldn't change its name. We >> > could use another variable to store the root device at initial stage, >> > it could actually be useful as it always points to the boot media. >> > Perhaps we can name it "boot". What's your idea ? >> >> I'm fine with "boot". I'm CCing Okuji; would like to make sure he doesn't >> have any objections (I think it was he who gave it this layout). > > "boot" is used for a command, so it is very confusing to use the same name for > a variable. If you want to have this kind of variable, please find another > name. I myself have no idea. Hi, No problem, I can find another name. BTW, there are now two schemes for locating device at boot, the environment block and robert's uuid device, which one do you favor, or is there other scheme you prefer ? -- Bean ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH] Environment block support for grub2 2008-06-14 3:41 ` Bean @ 2008-06-14 18:32 ` Robert Millan 2008-06-14 19:22 ` Bean 0 siblings, 1 reply; 23+ messages in thread From: Robert Millan @ 2008-06-14 18:32 UTC (permalink / raw) To: The development of GRUB 2 On Sat, Jun 14, 2008 at 11:41:18AM +0800, Bean wrote: > > Hi, > > No problem, I can find another name. Sorry, my mistake. I complained about $root being inappropiate for early stage use, but after that I noticed that $root is used in every stage to refer to "whatever drive we're currently accessing"; even before $prefix is initialised! I'm fine with $root if nobody objects. > BTW, there are now two schemes for locating device at boot, the > environment block and robert's uuid device, which one do you favor, or > is there other scheme you prefer ? I think there's no problem with having two schemes as long as they don't take extra core.img space (except for the rare use cases they're intended to) and don't conflict with each other. As for the "findroot" approach, I have two comments/ideas: - Since findroot.mod is basicaly an heuristic, and it's possible we may want different kinds of methods that work similarly, how about calling it "findroot_by_file" or something like that? Then we could have a separate module for "findroot_by_uuid", etc. - I think your idea has the potential of obsoleting some parts of our init routines, maybe (if we're lucky) making kernel.img smaller. For example, we currently make grub_prefix a static length string (could it be dynamic? -> less space); then try to extract $root from it, since we embedded it in the same place (if we had a scheme to specify it separately -> less code to parse it). -- Robert Millan <GPLv2> I know my rights; I want my phone call! <DRM> What good is a phone call… if you are unable to speak? (as seen on /.) ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH] Environment block support for grub2 2008-06-14 18:32 ` Robert Millan @ 2008-06-14 19:22 ` Bean 0 siblings, 0 replies; 23+ messages in thread From: Bean @ 2008-06-14 19:22 UTC (permalink / raw) To: The development of GRUB 2 On Sun, Jun 15, 2008 at 2:32 AM, Robert Millan <rmh@aybabtu.com> wrote: > On Sat, Jun 14, 2008 at 11:41:18AM +0800, Bean wrote: >> >> Hi, >> >> No problem, I can find another name. > > Sorry, my mistake. I complained about $root being inappropiate for early > stage use, but after that I noticed that $root is used in every stage to > refer to "whatever drive we're currently accessing"; even before $prefix > is initialised! > > I'm fine with $root if nobody objects. > >> BTW, there are now two schemes for locating device at boot, the >> environment block and robert's uuid device, which one do you favor, or >> is there other scheme you prefer ? > > I think there's no problem with having two schemes as long as they don't > take extra core.img space (except for the rare use cases they're intended > to) and don't conflict with each other. Yes, they can coexist easily. The environment block can overwrite root variable, so to use uuid fs, just set the root variable, and to use findroot, set uuid/lable/idfile. > > As for the "findroot" approach, I have two comments/ideas: > > - Since findroot.mod is basicaly an heuristic, and it's possible we may > want different kinds of methods that work similarly, how about > calling it "findroot_by_file" or something like that? Then we could > have a separate module for "findroot_by_uuid", etc. Seems fine to me. > > - I think your idea has the potential of obsoleting some parts of our > init routines, maybe (if we're lucky) making kernel.img smaller. For > example, we currently make grub_prefix a static length string (could it > be dynamic? -> less space); then try to extract $root from it, since we > embedded it in the same place (if we had a scheme to specify it > separately -> less code to parse it). I think it can be dynamic, we can store it right after the modules. Although the area is compressed, so we can't use grub-editenv to change it easily. -- Bean ^ permalink raw reply [flat|nested] 23+ messages in thread
end of thread, other threads:[~2008-06-14 19:22 UTC | newest] Thread overview: 23+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2008-05-30 20:27 [PATCH] Environment block support for grub2 Bean 2008-05-31 10:10 ` Robert Millan 2008-05-31 10:54 ` Bean 2008-05-31 11:39 ` Robert Millan 2008-05-31 12:09 ` Bean 2008-05-31 15:09 ` Bean 2008-06-03 21:09 ` Robert Millan 2008-06-04 3:49 ` Bean 2008-06-06 16:43 ` UUID-based boot (Re: [PATCH] Environment block support for grub2) Robert Millan 2008-06-06 17:22 ` Bean 2008-06-06 22:03 ` Robert Millan 2008-06-07 4:33 ` Bean 2008-06-08 19:26 ` Robert Millan 2008-06-07 7:24 ` Vesa Jääskeläinen 2008-06-06 23:31 ` [PATCH] ntfs UUIDs (Re: UUID-based boot (Re: [PATCH] Environment block support for grub2)) Robert Millan 2008-06-07 5:44 ` Tomáš Ebenlendr 2008-06-08 3:34 ` Pavel Roskin 2008-06-08 19:19 ` Robert Millan 2008-05-31 15:21 ` [PATCH] Environment block support for grub2 Robert Millan 2008-06-13 22:48 ` Yoshinori K. Okuji 2008-06-14 3:41 ` Bean 2008-06-14 18:32 ` Robert Millan 2008-06-14 19:22 ` Bean
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.