This patch, that is.
-- Matthew Garrett | mj...@srcf.ucam.org
diff -ur grub-0.97.clean/stage2/asm.S grub-0.97/stage2/asm.S --- grub-0.97.clean/stage2/asm.S 2010-05-19 13:18:50.638314187 -0400 +++ grub-0.97/stage2/asm.S 2010-05-19 13:23:39.273210663 -0400 @@ -90,6 +90,8 @@ /* This variable is here only because of a historical reason. */ VARIABLE(saved_entryno) .long 0 +VARIABLE(failed_boot) + .byte 0 VARIABLE(stage2_id) .byte STAGE2_ID VARIABLE(force_lba) diff -ur grub-0.97.clean/stage2/builtins.c grub-0.97/stage2/builtins.c --- grub-0.97.clean/stage2/builtins.c 2010-05-19 13:18:50.692309957 -0400 +++ grub-0.97/stage2/builtins.c 2010-05-19 13:37:36.757188824 -0400 @@ -78,13 +78,23 @@ int grub_timeout = -1; /* Whether to show the menu or not. */ int show_menu = 1; +/* The bootflag. */ +char grub_bootflag = 0; /* The BIOS drive map. */ static unsigned short bios_drive_map[DRIVE_MAP_SIZE + 1]; /* Prototypes for allowing straightfoward calling of builtins functions inside other functions. */ static int configfile_func (char *arg, int flags); - +#if !defined(SUPPORT_DISKLESS) && !defined(GRUB_UTIL) && !defined(PLATFORM_EFI) +static int bootflag_get (char *bootflag); +#else +static int bootflag_get (char *bootflag) +{ + *bootflag = 0; + return 0; +} +#endif /* Initialize the data for builtins. */ void init_builtins (void) @@ -104,6 +114,8 @@ fallback_entryno = -1; fallback_entries[0] = -1; grub_timeout = -1; + if (bootflag_get(&grub_bootflag)) + grub_bootflag = 0; } /* Check a password for correctness. Returns 0 if password was @@ -401,6 +413,206 @@ "Boot the OS/chain-loader which has been loaded." }; +#if !defined(SUPPORT_DISKLESS) && !defined(GRUB_UTIL) && !defined(PLATFORM_EFI) +/* Get current boot flag from stage2 */ +static int +bootflag_get(char *value) +{ + char *bootflag_ptr + + /* Get the geometry of the boot drive (i.e. the disk which contains + this stage2). */ + if (get_diskinfo (boot_drive, &buf_geom)) + { + errnum = ERR_NO_DISK; + return 1; + } + + /* Load the second sector of this stage2. */ + if (! rawread (boot_drive, install_second_sector, 0, SECTOR_SIZE, buffer)) + { + return 1; + } + + /* Sanity check. */ + if (buffer[STAGE2_STAGE2_ID] != STAGE2_ID_STAGE2 + || *((short *) (buffer + STAGE2_VER_MAJ_OFFS)) != COMPAT_VERSION) + { + errnum = ERR_BAD_VERSION; + return 1; + } + + bootflag_ptr = (char *) (buffer + STAGE2_FAILED_BOOT); + *value = *bootflag_ptr; + return 0; +} + +/* Write boot flag into stage2 */ +static int +bootflag_helper(int value) +{ + char *bootflag_ptr; + + /* Get the geometry of the boot drive (i.e. the disk which contains + this stage2). */ + if (get_diskinfo (boot_drive, &buf_geom)) + { + errnum = ERR_NO_DISK; + return 1; + } + + /* Load the second sector of this stage2. */ + if (! rawread (boot_drive, install_second_sector, 0, SECTOR_SIZE, buffer)) + { + return 1; + } + + /* Sanity check. */ + if (buffer[STAGE2_STAGE2_ID] != STAGE2_ID_STAGE2 + || *((short *) (buffer + STAGE2_VER_MAJ_OFFS)) != COMPAT_VERSION) + { + errnum = ERR_BAD_VERSION; + return 1; + } + + bootflag_ptr = (char *) (buffer + STAGE2_FAILED_BOOT); + + *bootflag_ptr = value; + + /* Save the image in the disk. */ + if (! rawwrite (boot_drive, install_second_sector, buffer)) + return 1; + + /* Clear the cache. */ + buf_track = -1; + + return 0; +} +#endif + +#if !defined(SUPPORT_DISKLESS) && defined(GRUB_UTIL) +static int +bootflag_shell(char *arg, int flags) +{ + char *stage2_os_file = "/boot/grub/stage2"; /* Default filename */ + FILE *fp; + char buffer[512]; + char *bootflag_ptr; + int new_bootflag; + + while (1) + { + if (grub_memcmp ("--stage2=", arg, sizeof ("--stage2=") - 1) == 0) + { + stage2_os_file = arg + sizeof ("--stage2=") - 1; + arg = skip_to (0, arg); + nul_terminate (stage2_os_file); + } + else if (grub_memcmp ("--bootflag=", arg, sizeof ("--bootflag=") - 1) == 0) + { + char *p = arg + sizeof ("--bootflag=") - 1; + if (! safe_parse_maxint (&p, &new_bootflag)) + return 1; + arg = skip_to (0, arg); + } + else + break; + } + + if (! (fp = fopen(stage2_os_file, "r+"))) + { + errnum = ERR_FILE_NOT_FOUND; + return 1; + } + + if (fseek (fp, SECTOR_SIZE, SEEK_SET) != 0) + { + fclose (fp); + errnum = ERR_BAD_VERSION; + return 1; + } + + if (fread (buffer, 1, SECTOR_SIZE, fp) != SECTOR_SIZE) + { + fclose (fp); + errnum = ERR_READ; + return 1; + } + + /* Sanity check. */ + if (buffer[STAGE2_STAGE2_ID] != STAGE2_ID_STAGE2 + || *((short *) (buffer + STAGE2_VER_MAJ_OFFS)) != COMPAT_VERSION) + { + errnum = ERR_BAD_VERSION; + return 1; + } + + bootflag_ptr = (char *) (buffer + STAGE2_FAILED_BOOT); + + *bootflag_ptr = new_bootflag; + + if (fseek (fp, SECTOR_SIZE, SEEK_SET) != 0) + { + fclose (fp); + errnum = ERR_BAD_VERSION; + return 1; + } + + if (fwrite (buffer, 1, SECTOR_SIZE, fp) != SECTOR_SIZE) + { + fclose (fp); + errnum = ERR_WRITE; + return 1; + } + + (void)fflush (fp); + fclose (fp); + return 0; +} +#endif + +/* bootflag */ +static int +bootflag_func (char *arg, int flags) +{ +#if !defined(SUPPORT_DISKLESS) +#if !defined(GRUB_UTIL) +#if !defined(PLATFORM_EFI) + /* This command is only useful when you boot an entry from the menu + interface. */ + if (! (flags & BUILTIN_SCRIPT)) + { + errnum = ERR_UNRECOGNIZED; + return 1; + } + + return bootflag_helper(1); +#else /* defined(PLATFORM_EFI) */ + return 1; /* FIXME EFI support */ +#endif +#else /* defined(GRUB_UTIL) */ + return bootflag_shell(arg, flags); +#endif +#else /* ! SUPPORT_DISKLESS && ! GRUB_UTIL */ + errnum = ERR_UNRECOGNIZED; + return 1; +#endif /* ! SUPPORT_DISKLESS && ! GRUB_UTIL */ +} + +static struct builtin builtin_bootflag = +{ + "bootflag", + bootflag_func, + BUILTIN_CMDLINE, +#ifdef GRUB_UTIL + "bootflag [--stage2=STAGE2_FILE] [--bootflag=DEFAULT]", + "Set DEFAULT as the bootflag entry in STAGE2_FILE." +#else + "bootflag", + "Set the stage 2 bootflag to 1." +#endif +}; + #ifdef SUPPORT_NETBOOT /* bootp */ @@ -4975,6 +5187,13 @@ /* One-shot default shenanigans -- don't piss around with the menu! */ if (grub_timeout != -1) return 0; + + if (grub_bootflag != 0) + { + grub_timeout = 30; + return 0; + } + if ((saved_entryno & STAGE2_ONCEONLY_ENTRY) != 0) { grub_timeout = 0; @@ -5185,6 +5404,7 @@ #endif &builtin_blocklist, &builtin_boot, + &builtin_bootflag, #ifdef SUPPORT_NETBOOT &builtin_bootp, #endif /* SUPPORT_NETBOOT */ diff -ur grub-0.97.clean/stage2/shared.h grub-0.97/stage2/shared.h --- grub-0.97.clean/stage2/shared.h 2010-05-19 13:18:50.699309128 -0400 +++ grub-0.97/stage2/shared.h 2010-05-19 13:32:55.436310548 -0400 @@ -197,9 +197,10 @@ #define STAGE2_VER_MAJ_OFFS 0x6 #define STAGE2_INSTALLPART 0x8 #define STAGE2_SAVED_ENTRYNO 0xc -#define STAGE2_STAGE2_ID 0x10 -#define STAGE2_FORCE_LBA 0x11 -#define STAGE2_VER_STR_OFFS 0x12 +#define STAGE2_FAILED_BOOT 0x10 +#define STAGE2_STAGE2_ID 0x11 +#define STAGE2_FORCE_LBA 0x12 +#define STAGE2_VER_STR_OFFS 0x13 #define STAGE2_ONCEONLY_ENTRY 0x10000 @@ -881,6 +882,7 @@ extern kernel_t kernel_type; extern int show_menu; extern int grub_timeout; +extern char grub_bootflag; void init_builtins (void); void init_config (void);
-- devel mailing list devel@lists.fedoraproject.org https://admin.fedoraproject.org/mailman/listinfo/devel