From 1b38e4d0cf62cbf42820b5e7a440a60dcbd5f3e8 Mon Sep 17 00:00:00 2001 From: okuji Date: Wed, 6 Sep 2000 03:02:39 +0000 Subject: [PATCH] add support for saving a default entry number in your disk. --- ChangeLog | 30 +++++++++++++++++ NEWS | 3 ++ THANKS | 1 + grub/asmstub.c | 1 + stage1/stage1.h | 2 +- stage2/asm.S | 17 ++++++++-- stage2/builtins.c | 84 +++++++++++++++++++++++++++++++++++++++++++++-- stage2/shared.h | 10 ++++-- stage2/stage2.c | 7 ++-- stage2/start.S | 2 ++ 10 files changed, 146 insertions(+), 11 deletions(-) diff --git a/ChangeLog b/ChangeLog index db352e36c..652e826fc 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,33 @@ +2000-09-06 OKUJI Yoshinori + + Add support for "boot previously booted entry by default", based + on the patch by Mike Meyer , but I've modified + his patch thoroughly. + + * grub/asmstub.c (saved_entryno): New variable. This is a dummy. + * stage1/stage1.h (COMPAT_VERSION_MINOR): Incremented. + * stage2/asm.S (saved_entryno): New variable. + (codestart) [!SUPPORT_DISKLESS]: Set INSTALL_SECOND_SECTOR to + %ebp. %ebp is set in start.S. + (install_second_sector): New variable. + * stage2/builtins.c (current_entryno): New variable. + (default_func) [!SUPPORT_DISKLESS]: If ARG is "saved", set + DEFAULT_ENTRY to SAVED_ENTRYNO. + (savedefault_func): New function. + (builtin_savedefault): New variable. + (builtin_table): Added a pointer to BUILTIN_SAVEDEFAULT. + * stage2/shared.h (STAGE2_SAVED_ENTRYNO): New macro. + (STAGE2_STAGE2_ID): Changed to 0x10. + (STAGE2_FORCE_LBA): Chaged to 0x11. + (STAGE2_VER_STR_OFFS): Changed to 0x12. + (install_second_sector): Declared. + (saved_entryno): Likewise. + (current_entryno): Likewise. + * stage2/stage2.c (run_menu): Set CURRENT_ENTRYNO to FIRST_ENTRY + + ENTRYNO, right before calling run_script. + * stage2/start.S (start): Save the sector number of the second + sector in %ebp. + 2000-09-05 OKUJI Yoshinori * stage1/stage1.S (lba_mode) [!NO_BUGGY_BIOS_IN_THE_WORLD]: diff --git a/NEWS b/NEWS index 07d22d4e4..b1c39698e 100644 --- a/NEWS +++ b/NEWS @@ -32,6 +32,9 @@ New in 0.5.96 - XXXX-XX-XX: * Also only for developers: you can specify an optional argument to the option `--hold' for the grub shell. The argument means how many seconds the grub shell should wait until diving into the main routine. +* New command, "savedefault". Now you can save current entry number to + your disk with this command and then you can set the default boot + entry to it by the command "default saved". New in 0.5.95 - 2000-06-27: * NetBSD ELF kernel support is added. You have to specify the new option diff --git a/THANKS b/THANKS index ac432cbf2..a92e47122 100644 --- a/THANKS +++ b/THANKS @@ -35,6 +35,7 @@ M. Meiarashi Mark Lundeberg Matthias Kretschmer Michael Hohmuth +Mike Meyer Miles Bader Neal H Walfield OKUJI Yoshinori diff --git a/grub/asmstub.c b/grub/asmstub.c index 01d63b602..0383fd723 100644 --- a/grub/asmstub.c +++ b/grub/asmstub.c @@ -67,6 +67,7 @@ int grub_stage2 (void); unsigned long install_partition = 0x20000; unsigned long boot_drive = 0; +int saved_entryno = 0; char version_string[] = VERSION; char config_file[128] = "/boot/grub/menu.lst"; /* FIXME: arbitrary */ unsigned long linux_text_len = 0; diff --git a/stage1/stage1.h b/stage1/stage1.h index 25ddbbf9c..370009063 100644 --- a/stage1/stage1.h +++ b/stage1/stage1.h @@ -23,7 +23,7 @@ /* Define the version numbers here, so that Stage 1 can know them. */ #define COMPAT_VERSION_MAJOR 3 -#define COMPAT_VERSION_MINOR 1 +#define COMPAT_VERSION_MINOR 2 #define COMPAT_VERSION ((COMPAT_VERSION_MINOR << 8) \ | COMPAT_VERSION_MAJOR) diff --git a/stage2/asm.S b/stage2/asm.S index 830c8aaf4..2c0706ee0 100644 --- a/stage2/asm.S +++ b/stage2/asm.S @@ -40,9 +40,9 @@ #include "shared.h" #ifdef STAGE1_5 -#define ABS(x) ((x) - EXT_C(main) + 0x2200) +# define ABS(x) ((x) - EXT_C(main) + 0x2200) #else -#define ABS(x) ((x) - EXT_C(main) + 0x8200) +# define ABS(x) ((x) - EXT_C(main) + 0x8200) #endif .file "asm.S" @@ -88,6 +88,8 @@ ENTRY(main) VARIABLE(install_partition) .long 0xFFFFFF +VARIABLE(saved_entryno) + .long 0 VARIABLE(stage2_id) .byte STAGE2_ID VARIABLE(force_lba) @@ -118,6 +120,14 @@ codestart: movw %ax, %ss movw %ax, %es +#ifndef SUPPORT_DISKLESS + /* + * Save the sector number of the second sector (i.e. this sector) + * in INSTALL_SECOND_SECTOR. See also "stage2/start.S". + */ + ADDR32 movl %ebp, EXT_C(install_second_sector) +#endif + /* set up the real mode/BIOS stack */ movl $STACKOFF, %ebp movl %ebp, %esp @@ -2103,6 +2113,9 @@ VARIABLE(boot_drive) .long 0 #endif +VARIABLE(install_second_sector) + .long 0 + /* an address can only be long-jumped to if it is in memory, this is used by multiple routines */ offset: diff --git a/stage2/builtins.c b/stage2/builtins.c index 073ed7ae8..98c883e40 100644 --- a/stage2/builtins.c +++ b/stage2/builtins.c @@ -55,6 +55,8 @@ int debug = 0; int default_entry = 0; /* The fallback entry. */ int fallback_entry = -1; +/* The number of current entry. */ +int current_entryno; /* The address for Multiboot command-line buffer. */ static char *mb_cmdline; /* The password. */ @@ -713,6 +715,14 @@ static struct builtin builtin_debug = static int default_func (char *arg, int flags) { +#ifndef SUPPORT_DISKLESS + if (grub_strcmp (arg, "saved") == 0) + { + default_entry = saved_entryno; + return 0; + } +#endif /* SUPPORT_DISKLESS */ + if (! safe_parse_maxint (&arg, &default_entry)) return 1; @@ -725,9 +735,9 @@ static struct builtin builtin_default = default_func, BUILTIN_MENU, #if 0 - "default NUM", + "default [NUM | `saved']", "Set the default entry to entry number NUM (if not specified, it is" - " 0, the first entry)." + " 0, the first entry) or the entry number saved by savedefault." #endif }; @@ -2644,6 +2654,75 @@ static struct builtin builtin_rootnoverify = " derived from attempting the mount will NOT work correctly." }; + +/* savedefault */ +static int +savedefault_func (char *arg, int flags) +{ +#if !defined(SUPPORT_DISKLESS) && !defined(GRUB_UTIL) + struct geometry geom; + int *entryno_ptr; + + /* This command is only useful when you boot an entry from the menu + interface. */ + if (! (flags & BUILTIN_SCRIPT)) + { + errnum = ERR_UNRECOGNIZED; + return 1; + } + + /* Get the geometry of the boot drive (i.e. the disk which contains + this stage2). */ + if (get_diskinfo (boot_drive, &geom)) + { + errnum = ERR_NO_DISK; + return 1; + } + + /* Load the second sector of this stage2. */ + if (biosdisk (BIOSDISK_READ, boot_drive, &geom, + install_second_sector, 1, SCRATCHSEG)) + { + errnum = ERR_READ; + return 1; + } + + entryno_ptr = (int *) ((char *) SCRATCHADDR + STAGE2_SAVED_ENTRYNO); + + /* Check if the saved entry number differs from current entry number. */ + if (*entryno_ptr != current_entryno) + { + /* Overwrite the saved entry number. */ + *entryno_ptr = current_entryno; + + /* Save the image in the disk. */ + if (biosdisk (BIOSDISK_WRITE, boot_drive, &geom, + install_second_sector, 1, SCRATCHSEG)) + { + errnum = ERR_WRITE; + return 1; + } + + /* Clear the cache. */ + buf_track = -1; + } + + return 0; +#else /* ! SUPPORT_DISKLESS && ! GRUB_UTIL */ + errnum = ERR_UNRECOGNIZED; + return 1; +#endif /* ! SUPPORT_DISKLESS && ! GRUB_UTIL */ +} + +static struct builtin builtin_savedefault = +{ + "savedefault", + savedefault_func, + BUILTIN_CMDLINE, + "savedefault", + "Save the current entry as the default boot entry." +}; + /* serial */ static int @@ -3665,6 +3744,7 @@ struct builtin *builtin_table[] = &builtin_reboot, &builtin_root, &builtin_rootnoverify, + &builtin_savedefault, &builtin_serial, &builtin_setkey, &builtin_setup, diff --git a/stage2/shared.h b/stage2/shared.h index 79852a4af..41d1130f4 100644 --- a/stage2/shared.h +++ b/stage2/shared.h @@ -192,9 +192,10 @@ extern char *grub_scratch_mem; #define STAGE2_VER_MAJ_OFFS 0x6 #define STAGE2_INSTALLPART 0x8 -#define STAGE2_STAGE2_ID 0xc -#define STAGE2_FORCE_LBA 0xd -#define STAGE2_VER_STR_OFFS 0xe +#define STAGE2_SAVED_ENTRYNO 0xc +#define STAGE2_STAGE2_ID 0x10 +#define STAGE2_FORCE_LBA 0x11 +#define STAGE2_VER_STR_OFFS 0x12 /* Stage 2 identifiers */ #define STAGE2_ID_STAGE2 0 @@ -464,8 +465,10 @@ typedef enum extern unsigned long install_partition; extern unsigned long boot_drive; +extern unsigned long install_second_sector; extern unsigned long boot_part_addr; extern unsigned long boot_part_offset; +extern int saved_entryno; extern unsigned char force_lba; extern char version_string[]; extern char config_file[]; @@ -497,6 +500,7 @@ extern void assign_device_name (int drive, const char *device); /* GUI interface variables. */ extern int fallback_entry; extern int default_entry; +extern int current_entryno; extern char *password; extern int auth; extern char commands[]; diff --git a/stage2/stage2.c b/stage2/stage2.c index e4034b481..4bf433040 100644 --- a/stage2/stage2.c +++ b/stage2/stage2.c @@ -681,9 +681,7 @@ restart: } } - /* - * Attempt to boot an entry. - */ + /* Attempt to boot an entry. */ boot_entry: while (1) { @@ -698,6 +696,9 @@ restart: if (! cur_entry) cur_entry = get_entry (config_entries, first_entry + entryno, 1); + /* Set CURRENT_ENTRYNO for the command "savedefault". */ + current_entryno = first_entry + entryno; + if (run_script (cur_entry, heap)) { if (fallback_entry < 0) diff --git a/stage2/start.S b/stage2/start.S index f44cc36c5..af079fc04 100644 --- a/stage2/start.S +++ b/stage2/start.S @@ -74,6 +74,8 @@ _start: /* this sets up for the first run through "bootloop" */ movw $ABS(firstlist - BOOTSEC_LISTSIZE), %di + /* save the sector number of the second sector in %ebp */ + movl (%di), %ebp /* this is the loop for reading the secondary boot-loader in */ bootloop: