diff -pru grub/docs/grub.texi grub-alpha/docs/grub.texi --- grub/docs/grub.texi Tue Feb 27 11:23:55 2001 +++ grub-alpha/docs/grub.texi Fri Mar 2 15:44:30 2001 @@ -1169,7 +1169,8 @@ If you decided to use a server to assign server and run @command{bootp} (@pxref{bootp}), @command{dhcp} (@pxref{dhcp}) or @command{rarp} (@pxref{rarp}) for BOOTP, DHCP or RARP, respectively. Each command will show an assigned IP address, a netmask, -an IP address for your TFTP server and a gateway. If any of the +an IP address for your TFTP server and a gateway, and, if the option is +set for BOOTP or DHCP, the filename to boot. If any of the addresses is wrong or it causes an error, probably the configuration of your servers isn't set up properly. @@ -1185,7 +1186,10 @@ manually). @xref{ifconfig}, for more det Finally, download your OS images from your network. The network can be accessed using the network drive @samp{(nd)}. Everything else is very -similar to the normal instructions (@pxref{Booting}). +similar to the normal instructions (@pxref{Booting}), except that, if you +use BOOTP or DHCP, and the filename to boot was given by the server, _after +setting the correct root device via @command{root}_, you can give the option address@hidden to @command{kernel} to tell GRUB to use the given value. Here is an example: @@ -1196,6 +1200,7 @@ Probing... [NE*000] NE2000 base ... Address: 192.168.110.23 Netmask: 255.255.255.0 Server: 192.168.110.14 Gateway: 192.168.110.1 +Boot file: none given grub> @kbd{root (nd)} grub> @kbd{kernel /tftproot/gnumach.gz root=sd0s1} @@ -1204,6 +1209,22 @@ grub> @kbd{boot} @end group @end example +Another example with the use of the "environment variable" : + address@hidden address@hidden +grub> @kbd{bootp} +Probing... [NE*000] +NE2000 base ... +Address: 192.168.110.23 Netmask: 255.255.255.0 +Server: 192.168.110.14 Gateway: 192.168.110.1 +Boot file: /tftpboot/bzImage + +grub> @kbd{root (nd)} +grub> @kbd{kernel --env-kernel root=/dev/hda5} +grub> @kbd{boot} address@hidden group address@hidden example @node Diskless @section Booting from a network diff -pru grub/netboot/main.c grub-alpha/netboot/main.c --- grub/netboot/main.c Tue Feb 27 11:23:56 2001 +++ grub-alpha/netboot/main.c Thu Mar 1 17:14:39 2001 @@ -851,6 +851,18 @@ await_reply (int type, int ival, void *p kernel = kernel_buf; } #endif /* ! GRUB */ +#ifdef GRUB + /* Setting the "environment" variable KERNEL for GRUB */ + { + struct symbol *symb_ptr; + + if ((symb_ptr = symb_search("KERNEL"))) + { + grub_memmove(symb_ptr->def, bootpreply->bp_file, 128); + (symb_ptr->def)[128] = '\0'; + } + } +#endif /* GRUB */ grub_memmove ((char *) BOOTP_DATA_ADDR, (char *) bootpreply, sizeof (struct bootpd_t)); diff -pru grub/stage2/boot.c grub-alpha/stage2/boot.c --- grub/stage2/boot.c Mon Oct 16 06:27:56 2000 +++ grub-alpha/stage2/boot.c Fri Mar 2 15:29:58 2001 @@ -317,7 +317,7 @@ load_image (char *kernel, char *arg, ker That is, copy "mem=XXX" to the end of the command-line, and avoid to copy spaces unnecessarily. Hell. */ { - char *src = skip_to (0, arg); + char *src = (env_kernel)? arg : skip_to (0, arg); char *dest = (char *) CL_MY_LOCATION; while (((int) dest) < CL_MY_END_ADDR && *src) diff -pru grub/stage2/builtins.c grub-alpha/stage2/builtins.c --- grub/stage2/builtins.c Thu Mar 1 11:31:41 2001 +++ grub-alpha/stage2/builtins.c Fri Mar 2 15:44:55 2001 @@ -80,6 +80,20 @@ int show_menu = 1; /* The BIOS drive map. */ static unsigned short bios_drive_map[DRIVE_MAP_SIZE + 1]; +/* We need to allow statically the memory for the KERNEL symbol */ +struct symbol kernel = { + NULL, + "KERNEL", + NULL +}; + +/* GRUB environment table */ +struct symbol *grub_env [GRUB_ENV_SIZE] = {&kernel}; + +/* Flag set if the kernel name is _not_ in the command line. See also boot.c + * for the explanation of this need */ +short env_kernel = 0; + /* Initialize the data for builtins. */ void init_builtins (void) @@ -88,6 +102,9 @@ init_builtins (void) /* BSD and chainloading evil hacks! */ bootdev = set_bootdev (0); mb_cmdline = (char *) MB_CMDLINE_BUF; + /* Kernel filename is not set */ + kernel.def = (char *) KERNEL_BUF; + kernel.def[0] = '\0'; } /* Initialize the data for the configuration file. */ @@ -130,6 +147,19 @@ disk_read_print_func (int sector, int of } +/* Functions to handle the environment table */ +struct symbol * +symb_search(char *s) +{ + struct symbol *ps; + + for (ps = grub_env[0]; ps != NULL; ps = ps->next) + if (grub_strcmp(s, ps->name) == 0) + return ps; + return NULL; +} + + /* blocklist */ static int blocklist_func (char *arg, int flags) @@ -349,6 +379,8 @@ static struct builtin builtin_boot = static int bootp_func (char *arg, int flags) { + struct symbol *symb_ptr = NULL; + if (! bootp ()) { if (errnum == ERR_NONE) @@ -359,6 +391,9 @@ bootp_func (char *arg, int flags) /* Notify the configuration. */ print_network_configuration (); + grub_printf("Boot file: %s\n", + ( (symb_ptr = symb_search("KERNEL")) && *symb_ptr->def)? + symb_ptr->def : "none given"); return 0; } @@ -2209,6 +2244,7 @@ static int kernel_func (char *arg, int flags) { int len; + struct symbol *symb_ptr = NULL; kernel_t suggested_type = KERNEL_TYPE_NONE; unsigned long load_flags = 0; @@ -2250,6 +2286,17 @@ kernel_func (char *arg, int flags) has no effect. */ else if (grub_memcmp (arg, "--no-mem-option", 15) == 0) load_flags |= KERNEL_LOAD_NO_MEM_OPTION; + else if (grub_memcmp (arg, "--env-kernel", 12) == 0) + { + if (!(symb_ptr = symb_search("KERNEL")) || !(*symb_ptr->def)) + /* KERNEL is not set or definition is empty*/ + { + errnum = ERR_BAD_SYMBOL; + return 1; + } + else + env_kernel = 1; + } else break; @@ -2267,9 +2314,20 @@ kernel_func (char *arg, int flags) return 1; } + /* Copy the command-line to MB_CMDLINE. */ grub_memmove (mb_cmdline, arg, len + 1); + /* If we have to use the environment variable for the kernel */ + /* We make the following assumptions : + * - additionnal informations like "(nd)" MUST be set by the user + * via the `root' command; the string is taken as is; + * - if an environment variable is set, it is defined at least by the + * empty string ; */ + if (symb_ptr) + arg = symb_ptr->def; + kernel_type = load_image (arg, mb_cmdline, suggested_type, load_flags); + env_kernel = 0; if (kernel_type == KERNEL_TYPE_NONE) return 1; @@ -2282,14 +2340,17 @@ static struct builtin builtin_kernel = "kernel", kernel_func, BUILTIN_CMDLINE, - "kernel [--no-mem-option] [--type=TYPE] FILE [ARG ...]", + "kernel [--no-mem-option] [--type=TYPE] [--env-kernel ] [FILE] [ARG ...]", "Attempt to load the primary boot image from FILE. The rest of the" "line is passed verbatim as the \"kernel command line\". Any modules" " must be reloaded after using this command. The option --type is used" " to suggest what type of kernel to be loaded. TYPE must be either of" " \"netbsd\", \"freebsd\", \"openbsd\", \"linux\", \"biglinux\" and" - " \"multiboot\". The option --no-mem-option tells GRUB not to pass a" - " Linux's mem option automatically." + " \"multiboot\". The option \"--no-mem-option\" tells GRUB not to pass a" + " Linux's mem option automatically. The option \"--env-kernel\" is used to " + " tell GRUB to take the name of the kernel from a value already set in" + " the environment (only set when using `bootp' at the moment, and you " + " have to specify the correct root device first)." }; diff -pru grub/stage2/common.c grub-alpha/stage2/common.c --- grub/stage2/common.c Sun Nov 26 19:31:30 2000 +++ grub-alpha/stage2/common.c Fri Mar 2 12:26:40 2001 @@ -84,6 +84,7 @@ char *err_list[] = [ERR_UNRECOGNIZED] = "Unrecognized command", [ERR_WONT_FIT] = "Selected item cannot fit into memory", [ERR_WRITE] = "Disk write error", + [ERR_BAD_SYMBOL] = "Environment variable not set or empty", }; diff -pru grub/stage2/shared.h grub-alpha/stage2/shared.h --- grub/stage2/shared.h Wed Feb 28 11:35:08 2001 +++ grub-alpha/stage2/shared.h Fri Mar 2 15:16:02 2001 @@ -122,6 +122,14 @@ extern char *grub_scratch_mem; #define MENU_BUF (UNIQUE_BUF + UNIQUE_BUFLEN) #define MENU_BUFLEN (0x8000 + PASSWORD_BUF - UNIQUE_BUF) + +/* XXX These are all temporary work around. The right way is the + * implementation of a real symbol table, but this implies using dynamic + * memory */ +/* The buffer for the kernel name. */ +#define KERNEL_BUF (MENU_BUF + MENU_BUFLEN) +#define KERNEL_BUFLEN 129 /* since via netboot we accept 128 +'\0'*/ + /* The size of the drive map. */ #define DRIVE_MAP_SIZE 8 @@ -538,6 +546,7 @@ typedef enum ERR_BAD_ARGUMENT, ERR_UNALIGNED, ERR_PRIVILEGED, + ERR_BAD_SYMBOL, MAX_ERR_NUM } grub_error_t; @@ -846,6 +855,33 @@ struct builtin /* All the builtins are registered in this. */ extern struct builtin *builtin_table[]; +/* Structure symbol to handle environment variables */ +struct symbol +{ + struct symbol *next; + char *name; + char *def; +}; + +/* grub_env table of symbols --- defined in builtins.c */ +/* We don't use dynamic memory at the moment, thus this environment is + * almost a fake one : the size of the table is hardcoded, and when a symbol + * is defined, it can be : + * - invalid : symbol.def == NULL ; + * - defined : !invalid, but can be the empty string if : + * *symbol.definition == '\0'; + * NOTE : at the moment a symbol can't be "unset" ! */ +extern struct symbol *grub_env []; + +/* We define here the maximum size of the array */ +#define GRUB_ENV_SIZE 1 + +/* XXX This flag is a work around because, at the moment, the way we handle + * the command line assumes that the kernel filename is the first token in + * it. This assumption is false when we take the kernel name from the + * environment variable */ +extern short env_kernel; + /* The constants for kernel types. */ typedef enum { @@ -1006,6 +1042,9 @@ int load_module (char *module, char *arg int load_initrd (char *initrd); int check_password(char *entered, char* expected, password_t type); + +/* Functions to handle environment table */ +struct symbol *symb_search(char *s); #endif void init_bios_info (void);