From 9b214e3a532d7613993dbef36adc94ba1785b2a9 Mon Sep 17 00:00:00 2001 From: Robert Millan Date: Mon, 21 Dec 2009 20:22:12 +0000 Subject: [PATCH] 2009-12-21 Robert Millan * util/mkisofs/msdos_partition.h: New file (based on include/grub/msdos_partition.h). * util/mkisofs/mkisofs.c (use_protective_msdos_label): New variable. (OPTION_PROTECTIVE_MSDOS_LABEL): New macro. (ld_options, main): Recognize --protective-msdos-label. * util/mkisofs/mkisofs.h (use_protective_msdos_label): New declaration. * util/mkisofs/write.c: Include `"msdos_partition.h"'. (padblock_write): If `use_protective_msdos_label' is set, patch a protective DOS-style label in the output image. * util/grub-mkrescue.in: Use --protective-msdos-label. --- ChangeLog | 14 +++++++ util/grub-mkrescue.in | 2 +- util/mkisofs/mkisofs.c | 10 ++++- util/mkisofs/mkisofs.h | 1 + util/mkisofs/msdos_partition.h | 75 ++++++++++++++++++++++++++++++++++ util/mkisofs/write.c | 33 +++++++++++++-- 6 files changed, 129 insertions(+), 6 deletions(-) create mode 100644 util/mkisofs/msdos_partition.h diff --git a/ChangeLog b/ChangeLog index 62005f2f9..b64f8fddd 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,17 @@ +2009-12-21 Robert Millan + + * util/mkisofs/msdos_partition.h: New file (based on + include/grub/msdos_partition.h). + * util/mkisofs/mkisofs.c (use_protective_msdos_label): New variable. + (OPTION_PROTECTIVE_MSDOS_LABEL): New macro. + (ld_options, main): Recognize --protective-msdos-label. + * util/mkisofs/mkisofs.h (use_protective_msdos_label): New declaration. + * util/mkisofs/write.c: Include `"msdos_partition.h"'. + (padblock_write): If `use_protective_msdos_label' is set, patch a + protective DOS-style label in the output image. + + * util/grub-mkrescue.in: Use --protective-msdos-label. + 2009-12-21 Robert Millan * util/grub-mkrescue.in: Do not zero-pad image for BIOS-based disk diff --git a/util/grub-mkrescue.in b/util/grub-mkrescue.in index bc9a1b86f..e2d5644f3 100644 --- a/util/grub-mkrescue.in +++ b/util/grub-mkrescue.in @@ -180,7 +180,7 @@ if test -e "${pc_dir}" ; then fi # build iso image -grub-mkisofs ${grub_mkisofs_arguments} -o ${output_image} -r ${iso9660_dir} ${source} +grub-mkisofs ${grub_mkisofs_arguments} --protective-msdos-label -o ${output_image} -r ${iso9660_dir} ${source} rm -rf ${iso9660_dir} rm -f ${embed_img} diff --git a/util/mkisofs/mkisofs.c b/util/mkisofs/mkisofs.c index 98fcf2f20..e6386fba4 100644 --- a/util/mkisofs/mkisofs.c +++ b/util/mkisofs/mkisofs.c @@ -91,6 +91,7 @@ int extension_record_size = 0; int use_eltorito = 0; int use_eltorito_emul_floppy = 0; int use_embedded_boot = 0; +int use_protective_msdos_label = 0; int use_boot_info_table = 0; int use_RockRidge = 0; int use_Joliet = 0; @@ -199,6 +200,8 @@ struct ld_option #define OPTION_VERSION 173 +#define OPTION_PROTECTIVE_MSDOS_LABEL 174 + static const struct ld_option ld_options[] = { { {"all-files", no_argument, NULL, 'a'}, @@ -213,6 +216,8 @@ static const struct ld_option ld_options[] = '\0', N_("FILE"), N_("Set Copyright filename"), ONE_DASH }, { {"embedded-boot", required_argument, NULL, 'G'}, 'G', N_("FILE"), N_("Set embedded boot image name"), TWO_DASHES }, + { {"protective-msdos-label", no_argument, NULL, OPTION_PROTECTIVE_MSDOS_LABEL }, + '\0', NULL, N_("Patch a protective DOS-style label in the image"), TWO_DASHES }, { {"eltorito-boot", required_argument, NULL, 'b'}, 'b', N_("FILE"), N_("Set El Torito boot image name"), ONE_DASH }, { {"eltorito-catalog", required_argument, NULL, 'c'}, @@ -726,11 +731,14 @@ int FDECL2(main, int, argc, char **, argv){ error (1, 0, _("Required boot image pathname missing")); break; case 'G': - use_embedded_boot++; + use_embedded_boot = 1; boot_image_embed = optarg; /* pathname of the boot image on host filesystem */ if (boot_image_embed == NULL) error (1, 0, _("Required boot image pathname missing")); break; + case OPTION_PROTECTIVE_MSDOS_LABEL: + use_protective_msdos_label = 1; + break; case 'c': use_eltorito++; boot_catalog = optarg; /* pathname of the boot image on cd */ diff --git a/util/mkisofs/mkisofs.h b/util/mkisofs/mkisofs.h index adc10e945..1f1ef99ac 100644 --- a/util/mkisofs/mkisofs.h +++ b/util/mkisofs/mkisofs.h @@ -297,6 +297,7 @@ extern struct iso_directory_record jroot_record; extern int use_eltorito; extern int use_embedded_boot; +extern int use_protective_msdos_label; extern int use_eltorito_emul_floppy; extern int use_boot_info_table; extern int use_RockRidge; diff --git a/util/mkisofs/msdos_partition.h b/util/mkisofs/msdos_partition.h new file mode 100644 index 000000000..13985f7bb --- /dev/null +++ b/util/mkisofs/msdos_partition.h @@ -0,0 +1,75 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 1999,2000,2001,2002,2004,2007 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#ifndef MSDOS_PARTITION_H +#define MSDOS_PARTITION_H 1 + +#include + +/* The signature. */ +#define MSDOS_PARTITION_SIGNATURE ((0xaa << 8) | 0x55) + +/* This is not a flag actually, but used as if it were a flag. */ +#define MSDOS_PARTITION_TYPE_HIDDEN_FLAG 0x10 + +/* The partition entry. */ +struct msdos_partition_entry +{ + /* If active, 0x80, otherwise, 0x00. */ + uint8_t flag; + + /* The head of the start. */ + uint8_t start_head; + + /* (S | ((C >> 2) & 0xC0)) where S is the sector of the start and C + is the cylinder of the start. Note that S is counted from one. */ + uint8_t start_sector; + + /* (C & 0xFF) where C is the cylinder of the start. */ + uint8_t start_cylinder; + + /* The partition type. */ + uint8_t type; + + /* The end versions of start_head, start_sector and start_cylinder, + respectively. */ + uint8_t end_head; + uint8_t end_sector; + uint8_t end_cylinder; + + /* The start sector. Note that this is counted from zero. */ + uint32_t start; + + /* The length in sector units. */ + uint32_t length; +} __attribute__ ((packed)); + +/* The structure of MBR. */ +struct msdos_partition_mbr +{ + /* The code area (actually, including BPB). */ + uint8_t code[446]; + + /* Four partition entries. */ + struct msdos_partition_entry entries[4]; + + /* The signature 0xaa55. */ + uint16_t signature; +} __attribute__ ((packed)); + +#endif diff --git a/util/mkisofs/write.c b/util/mkisofs/write.c index d9c847268..987ca1512 100644 --- a/util/mkisofs/write.c +++ b/util/mkisofs/write.c @@ -21,11 +21,10 @@ along with this program; if not, see . */ +#include "config.h" + #include #include -#include "config.h" -#include "mkisofs.h" -#include "iso9660.h" #include #include @@ -37,6 +36,10 @@ #ifdef HAVE_UNISTD_H #include #endif + +#include "mkisofs.h" +#include "iso9660.h" +#include "msdos_partition.h" #ifdef __SVR4 extern char * strdup(const char *); @@ -1424,7 +1427,6 @@ static int FDECL1(dirtree_cleanup, FILE *, outfile) static int FDECL1(padblock_write, FILE *, outfile) { char *buffer; - int i; buffer = e_malloc (2048 * PADBLOCK_SIZE); memset (buffer, 0, 2048 * PADBLOCK_SIZE); @@ -1437,6 +1439,29 @@ static int FDECL1(padblock_write, FILE *, outfile) fread (buffer, 2048 * PADBLOCK_SIZE, 1, fp); } + if (use_protective_msdos_label) + { + struct msdos_partition_mbr *mbr = (void *) buffer; + + memset (mbr->entries, 0, sizeof(mbr->entries)); + + /* Some idiotic BIOSes refuse to boot if they don't find at least + one partition with active bit set. */ + mbr->entries[0].flag = 0x80; + + /* Doesn't really matter, as long as it's non-zero. It seems that + 0xCD is used elsewhere, so we follow suit. */ + mbr->entries[0].type = 0xcd; + + /* Start immediately (sector 1). */ + mbr->entries[0].start = 1; + + /* We don't know yet. Let's keep it safe. */ + mbr->entries[0].length = UINT32_MAX; + + mbr->signature = MSDOS_PARTITION_SIGNATURE; + } + xfwrite (buffer, 1, 2048 * PADBLOCK_SIZE, outfile); last_extent_written += PADBLOCK_SIZE;