From dd73313cbafb7c6c87fb3a1159daa3639939f7d6 Mon Sep 17 00:00:00 2001 From: Jon McCune Date: Mon, 9 Dec 2013 16:52:12 -0800 Subject: [PATCH] Add --no-rs-codes flag to optionally disable reed-solomon codes in grub-install and grub-bios-setup for x86 BIOS targets. --- ChangeLog | 5 +++++ docs/grub.texi | 14 ++++++++++++- include/grub/util/install.h | 6 ++++-- util/grub-install.c | 19 +++++++++++++---- util/grub-setup.c | 19 +++++++++++++++-- util/setup.c | 41 ++++++++++++++++++++++++------------- 6 files changed, 81 insertions(+), 23 deletions(-) diff --git a/ChangeLog b/ChangeLog index 36d1d941d..3992fb977 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2013-12-09 Jon McCune + + * Add --no-rs-codes flag to optionally disable reed-solomon codes + in grub-install and grub-bios-setup for x86 BIOS targets. + 2013-12-09 Vladimir Serbinenko Implement sparc64 trampolines (needed for sparc64-emu). diff --git a/docs/grub.texi b/docs/grub.texi index 54b02fd52..91fa1de5d 100644 --- a/docs/grub.texi +++ b/docs/grub.texi @@ -5994,8 +5994,20 @@ mounted on Recheck the device map, even if @file{/boot/grub/device.map} already exists. You should use this option whenever you add/remove a disk into/from your computer. -@end table +@item --no-rs-codes +By default on x86 BIOS systems, @command{grub-install} will use some +extra space in the bootloader embedding area for Reed-Solomon +error-correcting codes. This enables GRUB to still boot successfully +if some blocks are corrupted. The exact amount of protection offered +is dependent on available space in the embedding area. R sectors of +redundancy can tolerate up to R/2 corrupted sectors. This +redundancy may be cumbersome if attempting to cryptographically +validate the contents of the bootloader embedding area, or in more +modern systems with GPT-style partition tables (@pxref{BIOS +installation}) where GRUB does not reside in any unpartitioned space +outside of the MBR. Disable the Reed-Solomon codes with this option. +@end table @node Invoking grub-mkconfig @chapter Invoking grub-mkconfig diff --git a/include/grub/util/install.h b/include/grub/util/install.h index beca2d25d..20626d4e6 100644 --- a/include/grub/util/install.h +++ b/include/grub/util/install.h @@ -183,12 +183,14 @@ void grub_util_bios_setup (const char *dir, const char *boot_file, const char *core_file, const char *dest, int force, - int fs_probe, int allow_floppy); + int fs_probe, int allow_floppy, + int add_rs_codes); void grub_util_sparc_setup (const char *dir, const char *boot_file, const char *core_file, const char *dest, int force, - int fs_probe, int allow_floppy); + int fs_probe, int allow_floppy, + int add_rs_codes); char * grub_install_get_image_targets_string (void); diff --git a/util/grub-install.c b/util/grub-install.c index 0aa7f48b4..5d22f902e 100644 --- a/util/grub-install.c +++ b/util/grub-install.c @@ -68,6 +68,7 @@ static int have_load_cfg = 0; static FILE * load_cfg_f = NULL; static char *load_cfg; static int install_bootsector = 1; +static int add_rs_codes = 1; enum { @@ -93,7 +94,8 @@ enum OPTION_DEBUG_IMAGE, OPTION_NO_FLOPPY, OPTION_DISK_MODULE, - OPTION_NO_BOOTSECTOR + OPTION_NO_BOOTSECTOR, + OPTION_NO_RS_CODES, }; static int fs_probe = 1; @@ -180,6 +182,10 @@ argp_parser (int key, char *arg, struct argp_state *state) install_bootsector = 0; return 0; + case OPTION_NO_RS_CODES: + add_rs_codes = 0; + return 0; + case OPTION_DEBUG: verbosity++; return 0; @@ -238,6 +244,9 @@ static struct argp_option options[] = { N_("do not probe for filesystems in DEVICE"), 0}, {"no-bootsector", OPTION_NO_BOOTSECTOR, 0, 0, N_("do not install bootsector"), 0}, + {"no-rs-codes", OPTION_NO_RS_CODES, 0, 0, + N_("Do not apply any reed-solomon codes when embedding core.img. " + "This option is only available on x86 BIOS targets."), 0}, {"debug", OPTION_DEBUG, 0, OPTION_HIDDEN, 0, 2}, {"no-floppy", OPTION_NO_FLOPPY, 0, OPTION_HIDDEN, 0, 2}, @@ -1435,12 +1444,13 @@ main (int argc, char *argv[]) "boot.img"); grub_install_copy_file (boot_img_src, boot_img, 1); - grub_util_info ("%sgrub-bios-setup %s %s %s %s --directory='%s' --device-map='%s' '%s'", + grub_util_info ("%sgrub-bios-setup %s %s %s %s %s --directory='%s' --device-map='%s' '%s'", install_bootsector ? "" : "NOT RUNNING: ", allow_floppy ? "--allow-floppy " : "", verbosity ? "--verbose " : "", force ? "--force " : "", !fs_probe ? "--skip-fs-probe" : "", + !add_rs_codes ? "--no-rs-codes" : "", platdir, device_map, install_device); @@ -1449,7 +1459,7 @@ main (int argc, char *argv[]) if (install_bootsector) grub_util_bios_setup (platdir, "boot.img", "core.img", install_drive, force, - fs_probe, allow_floppy); + fs_probe, allow_floppy, add_rs_codes); break; } case GRUB_INSTALL_PLATFORM_SPARC64_IEEE1275: @@ -1475,7 +1485,8 @@ main (int argc, char *argv[]) if (install_bootsector) grub_util_sparc_setup (platdir, "boot.img", "core.img", install_device, force, - fs_probe, allow_floppy); + fs_probe, allow_floppy, + 0 /* unused */ ); break; } diff --git a/util/grub-setup.c b/util/grub-setup.c index 90b9de013..7a6ca78b2 100644 --- a/util/grub-setup.c +++ b/util/grub-setup.c @@ -64,6 +64,12 @@ #define DEFAULT_BOOT_FILE "boot.img" #define DEFAULT_CORE_FILE "core.img" +/* Non-printable "keys" for arguments with no short form. + * See grub-core/gnulib/argp.h for details. */ +enum { + NO_RS_CODES_KEY = 0x100, +}; + static struct argp_option options[] = { {"boot-image", 'b', N_("FILE"), 0, N_("use FILE as the boot image [default=%s]"), 0}, @@ -82,7 +88,9 @@ static struct argp_option options[] = { /* TRANSLATORS: The potential breakage isn't limited to floppies but it's likely to make the install unbootable from HDD. */ N_("make the drive also bootable as floppy (default for fdX devices). May break on some BIOSes."), 0}, - + {"no-rs-codes", NO_RS_CODES_KEY, 0, 0, + N_("Do not apply any reed-solomon codes when embedding core.img. " + "This option is only available on x86 BIOS targets."), 0}, { 0, 0, 0, 0, 0, 0 } }; @@ -118,6 +126,7 @@ struct arguments int fs_probe; int allow_floppy; char *device; + int add_rs_codes; }; static error_t @@ -173,6 +182,10 @@ argp_parser (int key, char *arg, struct argp_state *state) verbosity++; break; + case NO_RS_CODES_KEY: + arguments->add_rs_codes = 0; + break; + case ARGP_KEY_ARG: if (state->arg_num == 0) arguments->device = xstrdup(arg); @@ -233,6 +246,7 @@ main (int argc, char *argv[]) /* Default option values. */ memset (&arguments, 0, sizeof (struct arguments)); arguments.fs_probe = 1; + arguments.add_rs_codes = 1; /* Parse our arguments */ if (argp_parse (&argp, argc, argv, 0, 0, &arguments) != 0) @@ -292,7 +306,8 @@ main (int argc, char *argv[]) arguments.boot_file ? : DEFAULT_BOOT_FILE, arguments.core_file ? : DEFAULT_CORE_FILE, dest_dev, arguments.force, - arguments.fs_probe, arguments.allow_floppy); + arguments.fs_probe, arguments.allow_floppy, + arguments.add_rs_codes); /* Free resources. */ grub_fini_all (); diff --git a/util/setup.c b/util/setup.c index 337c304ef..60bce683c 100644 --- a/util/setup.c +++ b/util/setup.c @@ -248,7 +248,8 @@ void SETUP (const char *dir, const char *boot_file, const char *core_file, const char *dest, int force, - int fs_probe, int allow_floppy) + int fs_probe, int allow_floppy, + int add_rs_codes __attribute__ ((unused))) /* unused on sparc64 */ { char *core_path; char *boot_img, *core_img, *boot_path; @@ -486,7 +487,11 @@ SETUP (const char *dir, nsec = core_sectors; - maxsec = 2 * core_sectors; + if (add_rs_codes) + maxsec = 2 * core_sectors; + else + maxsec = core_sectors; + if (maxsec > ((0x78000 - GRUB_KERNEL_I386_PC_LINK_ADDR) >> GRUB_DISK_SECTOR_BITS)) maxsec = ((0x78000 - GRUB_KERNEL_I386_PC_LINK_ADDR) @@ -543,15 +548,16 @@ SETUP (const char *dir, write_rootdev (root_dev, boot_img, bl.first_sector); - core_img = realloc (core_img, nsec * GRUB_DISK_SECTOR_SIZE); + /* Round up to the nearest sector boundary, and zero the extra memory */ + core_img = xrealloc (core_img, nsec * GRUB_DISK_SECTOR_SIZE); + assert (core_img && (nsec * GRUB_DISK_SECTOR_SIZE >= core_size)); + memset (core_img + core_size, 0, nsec * GRUB_DISK_SECTOR_SIZE - core_size); + bl.first_block = (struct grub_boot_blocklist *) (core_img + GRUB_DISK_SECTOR_SIZE - sizeof (*bl.block)); grub_size_t no_rs_length; - grub_set_unaligned32 ((core_img + GRUB_DISK_SECTOR_SIZE - + GRUB_KERNEL_I386_PC_REED_SOLOMON_REDUNDANCY), - grub_host_to_target32 (nsec * GRUB_DISK_SECTOR_SIZE - core_size)); no_rs_length = grub_target_to_host16 (grub_get_unaligned16 (core_img + GRUB_DISK_SECTOR_SIZE @@ -560,14 +566,21 @@ SETUP (const char *dir, if (no_rs_length == 0xffff) grub_util_error ("%s", _("core.img version mismatch")); - void *tmp = xmalloc (core_size); - grub_memcpy (tmp, core_img, core_size); - grub_reed_solomon_add_redundancy (core_img + no_rs_length + GRUB_DISK_SECTOR_SIZE, - core_size - no_rs_length - GRUB_DISK_SECTOR_SIZE, - nsec * GRUB_DISK_SECTOR_SIZE - - core_size); - assert (grub_memcmp (tmp, core_img, core_size) == 0); - free (tmp); + if (add_rs_codes) + { + grub_set_unaligned32 ((core_img + GRUB_DISK_SECTOR_SIZE + + GRUB_KERNEL_I386_PC_REED_SOLOMON_REDUNDANCY), + grub_host_to_target32 (nsec * GRUB_DISK_SECTOR_SIZE - core_size)); + + void *tmp = xmalloc (core_size); + grub_memcpy (tmp, core_img, core_size); + grub_reed_solomon_add_redundancy (core_img + no_rs_length + GRUB_DISK_SECTOR_SIZE, + core_size - no_rs_length - GRUB_DISK_SECTOR_SIZE, + nsec * GRUB_DISK_SECTOR_SIZE + - core_size); + assert (grub_memcmp (tmp, core_img, core_size) == 0); + free (tmp); + } /* Write the core image onto the disk. */ for (i = 0; i < nsec; i++) -- 2.39.5