From c6ec01220b2545dba4b8dc57be7cec8776fe6cf3 Mon Sep 17 00:00:00 2001 From: okuji Date: Tue, 2 Nov 1999 12:54:19 +0000 Subject: [PATCH] add an extra option into the command install, and allow to mount extended partitions. --- ChangeLog | 23 +++++++++ NEWS | 2 + TODO | 2 - docs/user-ref.texi | 32 +++++++------ stage2/builtins.c | 116 +++++++++++++++++++++++++++++++-------------- stage2/char_io.c | 32 +++++-------- stage2/disk_io.c | 47 +++++++++--------- stage2/shared.h | 1 + 8 files changed, 160 insertions(+), 95 deletions(-) diff --git a/ChangeLog b/ChangeLog index 2d822b4f7..eee41954b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,26 @@ +1999-11-02 OKUJI Yoshinori + + * stage2/disk_io.c (real_open_partition): Check for the right + partition for any extended partition as well. Set EXT to I after + the check is done. Reported by Jeff Scheinberg + . + + * stage2/builtins.c (color_func): Use the function + nul_terminate. + (device_func) [GRUB_UTIL]: Likewise. + (help_func): Likewise. + (install_func): Save CURRENT_DRIVE, CURRENT_PARTITION and + BUG_GEOM in SRC_DRIVE, SRC_PARTITION and SRC_GEOM respectively, + and use them when patching the Stage 2. + NUL-terminate the configuration filename CONFIG_FILENAME. + If IS_STAGE1_5 is true, then check if the "real config file" + option is present, and, if so, patch the Stage 2 CONFIG_FILENAME + with the configuration filename REAL_CONFIG_FILENAME. + (setkey_func): Use nul_terminate instead of the local function + null_terminate. + * stage2/char_io.c [!STAGE1_5] (nul_terminate): New function. + * stage2/shared.h (nul_terminate): Declared. + 1999-11-01 OKUJI Yoshinori * docs/grub.texi: Add "I/O ports detection" into the menu. diff --git a/NEWS b/NEWS index f862393a3..77048b60e 100644 --- a/NEWS +++ b/NEWS @@ -24,6 +24,8 @@ New in 0.5.94: * The command "ioprobe" detects what I/O ports are used for a BIOS drive. * OpenBSD support in the grub shell is improved. +* The command "install" can now patch a Stage 2 with a different + filename from "/boot/grub/menu.lst" even if a Stage 1.5 is used. New in 0.5.93: * ELF format of FreeBSD kernel is supported. diff --git a/TODO b/TODO index 7899040b0..2dde4c028 100644 --- a/TODO +++ b/TODO @@ -36,8 +36,6 @@ Priorities: * Add ISA PnP support. -* Accept any extended partition when using it for chain-loading. !!! - * Fix the completion so that it works for BSD partitions as well. !! * Add more filesystems support (XFS, NTFS, etc.) diff --git a/docs/user-ref.texi b/docs/user-ref.texi index 4560f7628..8418081ef 100644 --- a/docs/user-ref.texi +++ b/docs/user-ref.texi @@ -830,7 +830,7 @@ Load an initial ramdisk for a Linux format boot image and set the appropriate parameters in the Linux setup area in memory. @end deffn -@deffn Command install stage1_file [@option{d}] dest_dev file [addr] [@option{p}] [config_file] +@deffn Command install stage1_file [@option{d}] dest_dev stage2_file [addr] [@option{p}] [config_file] [real_config_file] This command is fairly complex, and you should not use this command unless you are familiar with GRUB. In short, it will perform a full install presuming the Stage 2 or Stage 1.5@footnote{They're loaded the @@ -839,19 +839,23 @@ is in its final install location. In slightly more detail, it will load @var{stage1_file}, validate that it is a GRUB Stage 1 of the right version number, install a blocklist for -loading @var{file} as a Stage 2. If the option @option{d} is present, the -Stage 1 will always look for the actual disk @var{file} was installed on, -rather than using the booting drive. The Stage 2 will be loaded at -address @var{addr}, which must be @samp{0x8000} for a true Stage 2, and -@samp{0x2000} for a Stage 1.5. If @var{addr} is not present, GRUB will -determine the address automatically. It then writes the completed Stage 1 -to the first block of the device @var{dest_dev}. If the options @option{p} -or @var{config_file} are present, then it reads the first block of -stage2, modifies it with the values of the partition @var{file} was -found on (for @option{p}) or places the string @var{config_file} into the -area telling the stage2 where to look for a configuration file at boot -time. This command preserves the DOS BPB (and for hard disks, the -partition table) of the sector the Stage 1 is to be installed into. +loading @var{stage2_file} as a Stage 2. If the option @option{d} is +present, the Stage 1 will always look for the actual disk +@var{stage2_file} was installed on, rather than using the booting +drive. The Stage 2 will be loaded at address @var{addr}, which must be +@samp{0x8000} for a true Stage 2, and @samp{0x2000} for a Stage 1.5. If +@var{addr} is not present, GRUB will determine the address +automatically. It then writes the completed Stage 1 to the first block +of the device @var{dest_dev}. If the options @option{p} or +@var{config_file} are present, then it reads the first block of stage2, +modifies it with the values of the partition @var{stage2_file} was found +on (for @option{p}) or places the string @var{config_file} into the area +telling the stage2 where to look for a configuration file at boot +time. Likewise, if @var{real_config_file} is present and +@var{stage2_file} is a Stage 1.5, then the Stage 2 @var{config_file} is +patched with the configuration filename @var{real_config_file}. This +command preserves the DOS BPB (and for hard disks, the partition table) +of the sector the Stage 1 is to be installed into. @end deffn @deffn Command ioprobe drive diff --git a/stage2/builtins.c b/stage2/builtins.c index de2a5d4fd..7de1b4038 100644 --- a/stage2/builtins.c +++ b/stage2/builtins.c @@ -290,12 +290,7 @@ color_func (char *arg, int flags) return -1; str = ptr; - /* Find a space. */ - for (; *ptr && ! grub_isspace (*ptr); ptr++) - ; - - /* Terminate the string STR. */ - *ptr = 0; + nul_terminate (str); /* Search for the color name. */ for (i = 0; i < 8; i++) @@ -451,7 +446,6 @@ device_func (char *arg, int flags) #ifdef GRUB_UTIL char *drive = arg; char *device; - char *ptr; /* Get the drive number from DRIVE. */ if (! set_device (drive)) @@ -466,10 +460,7 @@ device_func (char *arg, int flags) } /* Terminate DEVICE. */ - ptr = device; - while (*ptr && *ptr != ' ') - ptr++; - *ptr = 0; + nul_terminate (device); assign_device_name (current_drive, device); @@ -951,16 +942,13 @@ help_func (char *arg, int flags) do { struct builtin **builtin; - char *ptr = arg; char *next_arg; /* Get the next argument. */ next_arg = skip_to (0, arg); /* Terminate ARG. */ - while (*ptr && *ptr != ' ') - ptr++; - *ptr = 0; + nul_terminate (arg); for (builtin = builtin_table; *builtin; builtin++) { @@ -1120,11 +1108,14 @@ install_func (char *arg, int flags) char *old_sect = stage1_buffer + SECTOR_SIZE; char *stage2_first_buffer = old_sect + SECTOR_SIZE; char *stage2_second_buffer = stage2_first_buffer + SECTOR_SIZE; - char *dummy = stage2_second_buffer + SECTOR_SIZE; + /* XXX: Probably SECTOR_SIZE is reasonable. */ + char *config_filename = stage2_second_buffer + SECTOR_SIZE; + char *dummy = config_filename + SECTOR_SIZE; int new_drive = 0xFF; int dest_drive, dest_sector; + int src_drive, src_partition; int i; - struct geometry dest_geom; + struct geometry dest_geom, src_geom; int saved_sector; int stage2_first_sector, stage2_second_sector; char *ptr; @@ -1251,9 +1242,13 @@ install_func (char *arg, int flags) if (! is_open) goto fail; + src_drive = current_drive; + src_partition = current_partition; + src_geom = buf_geom; + if (! new_drive) - new_drive = current_drive; - else if (current_drive != dest_drive) + new_drive = src_drive; + else if (src_drive != dest_drive) grub_printf ("Warning: the option `d' was not used, but the Stage 1 will" " be installed on a\ndifferent drive than the drive where" " the Stage 2 resides.\n"); @@ -1340,7 +1335,7 @@ install_func (char *arg, int flags) if (*ptr == 'p') { *((long *) (stage2_second_buffer + STAGE2_INSTALLPART)) - = current_partition; + = src_partition; if (is_stage1_5) { /* Reset the device information in FILE if it is a Stage 1.5. */ @@ -1355,6 +1350,9 @@ install_func (char *arg, int flags) if (*ptr) { + grub_strcpy (config_filename, ptr); + nul_terminate (config_filename); + if (! is_stage1_5) /* If it is a Stage 2, just copy PTR to CONFIG_FILE_LOCATION. */ grub_strcpy (config_file_location, ptr); @@ -1362,7 +1360,6 @@ install_func (char *arg, int flags) { char *config_file; unsigned long device; - int tmp = current_drive; /* Translate the external device syntax to the internal device syntax. */ @@ -1374,11 +1371,63 @@ install_func (char *arg, int flags) } device = current_drive << 24 | current_partition; - current_drive = tmp; grub_memmove (config_file_location, (char *) &device, sizeof (device)); grub_strcpy (config_file_location + sizeof (device), config_file); } + + /* Check if the configuration filename is specified, if a Stage 1.5 + is used. */ + if (is_stage1_5) + { + char *real_config_filename = skip_to (0, ptr); + + if (*real_config_filename) + { + /* Specified */ + char *location; + + is_open = grub_open (config_filename); + if (! is_open) + goto fail; + + /* Skip the first sector. */ + filepos = SECTOR_SIZE; + + disk_read_hook = disk_read_savesect_func; + if (grub_read ((char *) SCRATCHADDR, SECTOR_SIZE) != SECTOR_SIZE) + goto fail; + + disk_read_hook = 0; + grub_close (); + is_open = 0; + + /* Sanity check. */ + if (*((unsigned char *) SCRATCHADDR + STAGE2_STAGE2_ID) + != STAGE2_ID_STAGE2) + { + errnum = ERR_BAD_VERSION; + goto fail; + } + + /* Find a string for the configuration filename. */ + location = (char *) SCRATCHADDR + STAGE2_VER_STR_OFFS; + while (*(location++)) + ; + + /* Copy the name. */ + grub_strcpy (location, real_config_filename); + + /* Write it to the disk. */ + buf_track = -1; + if (biosdisk (BIOSDISK_WRITE, current_drive, &buf_geom, + saved_sector, 1, SCRATCHSEG)) + { + errnum = ERR_WRITE; + goto fail; + } + } + } } /* Clear the cache. */ @@ -1386,7 +1435,7 @@ install_func (char *arg, int flags) /* Write the modified first sector of Stage2 to the disk. */ grub_memmove ((char *) SCRATCHADDR, stage2_first_buffer, SECTOR_SIZE); - if (biosdisk (BIOSDISK_WRITE, current_drive, &buf_geom, + if (biosdisk (BIOSDISK_WRITE, src_drive, &src_geom, stage2_first_sector, 1, SCRATCHSEG)) { errnum = ERR_WRITE; @@ -1395,7 +1444,7 @@ install_func (char *arg, int flags) /* Write the modified second sector of Stage2 to the disk. */ grub_memmove ((char *) SCRATCHADDR, stage2_second_buffer, SECTOR_SIZE); - if (biosdisk (BIOSDISK_WRITE, current_drive, &buf_geom, + if (biosdisk (BIOSDISK_WRITE, src_drive, &src_geom, stage2_second_sector, 1, SCRATCHSEG)) { errnum = ERR_WRITE; @@ -1429,7 +1478,7 @@ static struct builtin builtin_install = "install", install_func, BUILTIN_CMDLINE, - "install STAGE1 [d] DEVICE STAGE2 [ADDR] [p] [CONFIG_FILE]", + "install STAGE1 [d] DEVICE STAGE2 [ADDR] [p] [CONFIG_FILE] [REAL_CONFIG_FILE]", "Install STAGE1 on DEVICE, and install a blocklist for loading STAGE2" " as a Stage 2. If the option `d' is present, the Stage 1 will always" " look for the disk where STAGE2 was installed, rather than using" @@ -1438,7 +1487,9 @@ static struct builtin builtin_install = " the option `p' or CONFIG_FILE is present, then the first block" " of Stage 2 is patched with new values of the partition and name" " of the configuration file used by the true Stage 2 (for a Stage 1.5," - " this is the name of the true Stage 2) at boot time." + " this is the name of the true Stage 2) at boot time. If STAGE2 is a Stage" + " 1.5 and REAL_CONFIG_FILE is present, then the Stage 2 CONFIG_FILE is" + " patched with the configuration filename REAL_CONFIG_FILE." }; @@ -1875,7 +1926,7 @@ struct keysym unsigned char keycode; /* keyboard scancode */ }; -/* The table for key symbols. If the "unshifted" member of an entry is +/* The table for key symbols. If the "shifted" member of an entry is NULL, the entry does not have shifted state. */ static struct keysym keysym_table[] = { @@ -1956,13 +2007,6 @@ setkey_func (char *arg, int flags) int to_code, from_code; int map_in_interrupt = 0; - static void null_terminate (char *str) - { - while (*str && ! grub_isspace (*str)) - str++; - *str = 0; - } - static int find_key_code (char *key) { int i; @@ -1996,8 +2040,8 @@ setkey_func (char *arg, int flags) to_key = arg; from_key = skip_to (0, to_key); - null_terminate (to_key); - null_terminate (from_key); + nul_terminate (to_key); + nul_terminate (from_key); to_code = find_ascii_code (to_key); from_code = find_ascii_code (from_key); diff --git a/stage2/char_io.c b/stage2/char_io.c index a3a95fd78..55290ff5b 100644 --- a/stage2/char_io.c +++ b/stage2/char_io.c @@ -19,10 +19,8 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ - #include "shared.h" - void print_error (void) { @@ -35,7 +33,6 @@ print_error (void) #endif /* STAGE1_5 */ } - char * convert_to_ascii (char *buf, int c,...) { @@ -78,7 +75,6 @@ convert_to_ascii (char *buf, int c,...) return ptr; } - void grub_printf (const char *format,...) { @@ -123,7 +119,6 @@ grub_printf (const char *format,...) } } - #ifndef STAGE1_5 int grub_sprintf (char *buffer, const char *format, ...) @@ -168,10 +163,6 @@ grub_sprintf (char *buffer, const char *format, ...) *bp = 0; return bp - buffer; } -#endif /* ! STAGE1_5 */ - - -#ifndef STAGE1_5 void init_page (void) @@ -611,10 +602,8 @@ get_cmdline (char *prompt, char *cmdline, int maxlen, return 0; } - #endif /* STAGE1_5 */ - int safe_parse_maxint (char **str_ptr, int *myint_ptr) { @@ -669,7 +658,6 @@ safe_parse_maxint (char **str_ptr, int *myint_ptr) return 1; } - int grub_tolower (int c) { @@ -679,7 +667,6 @@ grub_tolower (int c) return c; } - int grub_isspace (int c) { @@ -706,9 +693,7 @@ grub_memcmp (const char *s1, const char *s2, int n) return 0; } -#endif /* ! STAGE1_5 */ -#ifndef STAGE1_5 int grub_strncat (char *s1, const char *s2, int n) { @@ -727,9 +712,7 @@ grub_strncat (char *s1, const char *s2, int n) return 1; } -#endif /* ! STAGE1_5 */ -#ifndef STAGE1_5 int grub_strcmp (const char *s1, const char *s2) { @@ -766,8 +749,18 @@ substring (char *s1, char *s2) return 1; } - #ifndef STAGE1_5 +/* Terminate the string STR with NUL. */ +char * +nul_terminate (char *str) +{ + while (*str && ! grub_isspace (*str)) + str++; + + *str++ = 0; + return str; +} + char * grub_strstr (const char *s1, const char *s2) { @@ -799,7 +792,6 @@ grub_strlen (const char *str) } #endif /* ! STAGE1_5 */ - int memcheck (int addr, int len) { @@ -840,7 +832,6 @@ memcheck (int addr, int len) return ! errnum; } - char * grub_memmove (char *to, const char *from, int len) { @@ -877,7 +868,6 @@ grub_memmove (char *to, const char *from, int len) return errnum ? NULL : to; } - #ifndef STAGE1_5 void * grub_memset (void *start, int c, int len) diff --git a/stage2/disk_io.c b/stage2/disk_io.c index 9a8bf7547..6d3b0b2e0 100644 --- a/stage2/disk_io.c +++ b/stage2/disk_io.c @@ -494,7 +494,7 @@ real_open_partition (int flags) slice_no = 0; /* if this is the whole disk, return here */ - if (!flags && current_partition == 0xFFFFFFuL) + if (! flags && current_partition == 0xFFFFFFuL) return 1; /* @@ -508,7 +508,7 @@ real_open_partition (int flags) /* * If the table isn't valid, we can't continue */ - if (!PC_MBR_CHECK_SIG (mbr_buf)) + if (! PC_MBR_CHECK_SIG (mbr_buf)) { errnum = ERR_BAD_PART_TABLE; return 0; @@ -527,7 +527,9 @@ real_open_partition (int flags) part_start = part_offset + PC_SLICE_START (mbr_buf, i); part_length = PC_SLICE_LENGTH (mbr_buf, i); #ifndef STAGE1_5 - memmove (cur_part_desc, mbr_buf + PC_SLICE_OFFSET + (i << 4), 16); + grub_memmove (cur_part_desc, + mbr_buf + PC_SLICE_OFFSET + (i << 4), + 16); #endif /* @@ -535,21 +537,11 @@ real_open_partition (int flags) */ if (current_slice) { - /* - * Is this an extended partition? - */ - if (IS_PC_SLICE_TYPE_EXTENDED (current_slice)) - { - if (ext == -1) - { - ext = i; - } - } -# ifndef STAGE1_5 +#ifndef STAGE1_5 /* * Display partition information */ - else if (flags) + if (flags && ! IS_PC_SLICE_TYPE_EXTENDED (current_slice)) { current_partition |= 0xFFFF; if (! do_completion) @@ -576,13 +568,15 @@ real_open_partition (int flags) errnum = ERR_NONE; } -# endif /* ! STAGE1_5 */ +#endif /* ! STAGE1_5 */ + /* * If we've found the right partition, we're done */ - else if (part_no == slice_no - || (part_no == 0xFF - && IS_PC_SLICE_TYPE_BSD (current_slice))) + if (! flags + && (part_no == slice_no + || (part_no == 0xFF + && IS_PC_SLICE_TYPE_BSD (current_slice)))) { if ((current_partition & 0xFF00) != 0xFF00) { @@ -595,6 +589,15 @@ real_open_partition (int flags) ext = -2; break; } + + /* + * Is this an extended partition? + */ + if (IS_PC_SLICE_TYPE_EXTENDED (current_slice)) + { + if (ext == -1) + ext = i; + } } /* @@ -609,7 +612,7 @@ real_open_partition (int flags) } part_offset = ext_offset + PC_SLICE_START (mbr_buf, ext); - if (!ext_offset) + if (! ext_offset) ext_offset = part_offset; } } @@ -634,14 +637,14 @@ real_open_partition (int flags) ext = -2; } } -# ifndef STAGE1_5 +#ifndef STAGE1_5 else { current_partition = 0xFFFFFF; check_and_print_mount (); errnum = 0; } -# endif /* STAGE1_5 */ +#endif /* STAGE1_5 */ } } diff --git a/stage2/shared.h b/stage2/shared.h index 2b425ce61..105eec383 100644 --- a/stage2/shared.h +++ b/stage2/shared.h @@ -695,6 +695,7 @@ char *convert_to_ascii (char *buf, int c, ...); int get_cmdline (char *prompt, char *cmdline, int maxlen, int echo_char, int history); int substring (char *s1, char *s2); +char *nul_terminate (char *str); int get_based_digit (int c, int base); int safe_parse_maxint (char **str_ptr, int *myint_ptr); int memcheck (int start, int len);