[syslinux:master] chain.c: add 'smap' and 'hand' options, update handover code

syslinux-bot for Michal Soltys soltys at ziu.info
Mon Mar 26 15:03:10 PDT 2012


Commit-ID:  7bfd45d022308089e8c17d80460be02dd1e61245
Gitweb:     http://www.syslinux.org/commit/7bfd45d022308089e8c17d80460be02dd1e61245
Author:     Michal Soltys <soltys at ziu.info>
AuthorDate: Tue, 17 Aug 2010 14:36:52 +0200
Committer:  Michal Soltys <soltys at ziu.info>
CommitDate: Sun, 22 Aug 2010 23:45:15 +0200

chain.c: add 'smap' and 'hand' options, update handover code

'[no]hand' allows explicit control whenever to create handover data

'[no]smap' allows loading bootsector without mapping it during
actual chainloading (meant for upcoming BPB mangling options)

Expanded handover code moved mostly to its own function

Signed-off-by: Michal Soltys <soltys at ziu.info>

---
 com32/chain/chain.c |  210 +++++++++++++++++++++++++++++++--------------------
 1 files changed, 129 insertions(+), 81 deletions(-)

diff --git a/com32/chain/chain.c b/com32/chain/chain.c
index 9c73291..aa7b700 100644
--- a/com32/chain/chain.c
+++ b/com32/chain/chain.c
@@ -61,6 +61,8 @@ static struct options {
     bool hide;
     bool sethid;
     bool drmk;
+    bool hand;
+    bool smap;
     struct syslinux_rm_regs regs;
 } opt;
 
@@ -70,8 +72,7 @@ struct data_area {
     addr_t size;
 };
 
-
-static inline void error(const char *msg)
+static void error(const char *msg)
 {
     fputs(msg, stderr);
 }
@@ -460,6 +461,8 @@ Usage:\n\
     grubcfg=<filename> Set alternative config filename for GRUB Legacy\n\
     grldr=<loader>     Load GRUB4DOS grldr\n\
     seg=<segment>      Jump to <seg>:0000, instead of 0000:7C00\n\
+    smap               Map loaded boot sector / mbr\n\
+    hand               Prepare handover data\n\
     swap               Swap drive numbers, if bootdisk is not fd0/hd0\n\
     hide               Hide primary partitions, except selected partition\n\
     sethid[den]        Set the FAT/NTFS hidden sectors field\n\
@@ -538,6 +541,14 @@ static int parse_args(int argc, char *argv[])
 	} else if (!strncmp(argv[i], "grldr=", 6)) {
 	    opt.loadfile = argv[i] + 6;
 	    opt.grldr = true;
+	} else if (!strcmp(argv[i], "smap")) {
+	    opt.smap = true;
+	} else if (!strcmp(argv[i], "nosmap")) {
+	    opt.smap = false;
+	} else if (!strcmp(argv[i], "hand")) {
+	    opt.hand = true;
+	} else if (!strcmp(argv[i], "nohand")) {
+	    opt.hand = false;
 	} else if (!strcmp(argv[i], "swap")) {
 	    opt.swap = true;
 	} else if (!strcmp(argv[i], "noswap")) {
@@ -587,12 +598,17 @@ static int parse_args(int argc, char *argv[])
 	goto bail;
     }
 
+    if (!opt.smap && !opt.loadfile) {
+	error("You have to load something.\n");
+	goto bail;
+    }
+
     return 0;
 bail:
     return -1;
 }
 
-inline static int is_phys(uint8_t sdifs)
+static int is_phys(uint8_t sdifs)
 {
     return
 	sdifs == SYSLINUX_FS_SYSLINUX ||
@@ -933,6 +949,89 @@ bail:
     return -1;
 }
 
+
+static int noov(const struct data_area *a, const struct data_area *b)
+{
+    return
+	a->base + a->size <= b->base ||
+	b->base + b->size <= a->base;
+}
+
+int setup_handover(const struct part_iter *iter,
+		   struct data_area *data)
+{
+    struct disk_dos_part_entry *ha;
+    const struct disk_gpt_part_entry *gp;
+    uint64_t lba_count;
+    uint32_t synth_size;
+    uint32_t *plen;
+
+    data->data = NULL;
+
+    if (!iter->index || !opt.hand)	/* we load mbr, or explicitly blocked */
+	return 0;
+    if (iter->type == typegpt) {
+
+	/* GPT handover protocol */
+	gp = (const struct disk_gpt_part_entry *)iter->record;
+	lba_count = gp->lba_last - gp->lba_first + 1;
+	synth_size = sizeof(struct disk_dos_part_entry) +
+	    sizeof(uint32_t) + (uint32_t)iter->sub.gpt.pe_size;
+
+	ha = malloc(synth_size);
+	if (!ha) {
+	    error("Could not build GPT hand-over record!\n");
+	    return -1;
+	}
+	memset(ha, 0, synth_size);
+	ha->active_flag = 0x80;
+	ha->ostype = 0xED;
+	/* All bits set by default */
+	ha->start_lba = ~0u;
+	ha->length = ~0u;
+	/* If these fit the precision, pass them on */
+	if (iter->start_lba < ha->start_lba)
+	    ha->start_lba = (uint32_t)iter->start_lba;
+	if (lba_count < ha->length)
+	    ha->length = (uint32_t)lba_count;
+	/* Next comes the GPT partition record length */
+	plen = (uint32_t *) (ha + 1);
+	plen[0] = (uint32_t)iter->sub.gpt.pe_size;
+	/* Next comes the GPT partition record copy */
+	memcpy(plen + 1, gp, plen[0]);
+#ifdef DEBUG
+	dprintf("GPT handover:\n");
+	disk_dos_part_dump(ha);
+	disk_gpt_part_dump((struct disk_gpt_part_entry *)(plen + 1));
+#endif
+    } else if (iter->type == typedos) {
+
+	/* MBR handover protocol */
+	synth_size = sizeof(struct disk_dos_part_entry);
+	ha = malloc(synth_size);
+	if (!ha) {
+	    error("Could not build MBR hand-over record!\n");
+	    return -1;
+	}
+	memcpy(ha, iter->record, synth_size);
+	ha->start_lba = (uint32_t)iter->start_lba;
+#ifdef DEBUG
+	dprintf("MBR handover:\n");
+	disk_dos_part_dump(ha);
+#endif
+    } else {
+
+	/* shouldn't ever happen */
+	return -1;
+    }
+
+    data->base = 0x7be;
+    data->size = synth_size;
+    data->data = (void *)ha;
+
+    return 0;
+}
+
 int main(int argc, char *argv[])
 {
     struct part_iter *iter = NULL;
@@ -947,8 +1046,9 @@ int main(int argc, char *argv[])
     openconsole(&dev_null_r, &dev_stdcon_w);
 
     /* Prepare and set defaults */
-    memset(data, 0, sizeof(data));
     memset(&opt, 0, sizeof(opt));
+    opt.hand = true;	/* by def do prepare handover */
+    opt.smap = true;	/* by def map bs / mbr */
     opt.flin = opt.slin = opt.fip = opt.sip = 0x7C00;
     opt.drivename = "boot";	/*
 				 * potential FIXME: maybe
@@ -986,6 +1086,7 @@ int main(int argc, char *argv[])
 
     /* Load file and bs/mbr */
 
+    data[ndata].base = opt.flin;
     if (opt.loadfile) {
 	if (loadfile(opt.loadfile, &data[ndata].data, &data[ndata].size)) {
 	    error("Couldn't read the boot file.\n");
@@ -997,21 +1098,22 @@ int main(int argc, char *argv[])
 	}
 
 	file_area = (void *)data[ndata].data;
-	data[ndata].base = opt.flin;
 	fidx = ndata;
 	ndata++;
     }
 
-    if (!opt.loadfile || data[0].base >= 0x7c00 + SECTOR) {
+    data[ndata].base = opt.slin;
+    data[ndata].size = SECTOR;
+    if (!opt.loadfile || !opt.smap || noov(data + fidx, data + ndata)) {
 	if (!(data[ndata].data = disk_read_sectors(&iter->di, iter->start_lba, 1))) {
 	    error("Couldn't read the bs / mbr.\n");
 	    goto bail;
 	}
 	sect_area = (void *)data[ndata].data;
-	data[ndata].base = opt.slin;
-	data[ndata].size = SECTOR;
 	sidx = ndata;
-	ndata++;
+	if(opt.smap) {
+	    ndata++;
+	}
     }
 
     /* Mangle file area */
@@ -1054,79 +1156,25 @@ int main(int argc, char *argv[])
     }
 
     /* Prepare handover */
-
-    if (iter->index) {
-	if (iter->type == typegpt) {
-	    /* Do GPT hand-over, if applicable (as per syslinux/doc/gpt.txt) */
-	    /* Look at the GPT partition */
-	    const struct disk_gpt_part_entry *gp =
-		(const struct disk_gpt_part_entry *)iter->record;
-	    /* Note the partition length */
-	    uint64_t lba_count = gp->lba_last - gp->lba_first + 1;
-	    /* The length of the hand-over */
-	    uint32_t synth_size =
-		sizeof(struct disk_dos_part_entry) + sizeof(uint32_t) +
-		(uint32_t)iter->sub.gpt.pe_size;
-	    /* Will point to the partition record length in the hand-over */
-	    uint32_t *plen;
-
-	    /* Allocate the hand-over record */
-	    hand_area = malloc(synth_size);
-	    if (!hand_area) {
-		error("Could not build GPT hand-over record!\n");
-		goto bail;
-	    }
-	    /* Synthesize the record */
-	    memset(hand_area, 0, synth_size);
-	    hand_area->active_flag = 0x80;
-	    hand_area->ostype = 0xED;
-	    /* All bits set by default */
-	    hand_area->start_lba = ~0u;
-	    hand_area->length = ~0u;
-	    /* If these fit the precision, pass them on */
-	    if (iter->start_lba < hand_area->start_lba)
-		hand_area->start_lba = (uint32_t)iter->start_lba;
-	    if (lba_count < hand_area->length)
-		hand_area->length = (uint32_t)lba_count;
-	    /* Next comes the GPT partition record length */
-	    plen = (uint32_t *) (hand_area + 1);
-	    plen[0] = (uint32_t)iter->sub.gpt.pe_size;
-	    /* Next comes the GPT partition record copy */
-	    memcpy(plen + 1, gp, plen[0]);
-
-	    opt.regs.eax.l = 0x54504721;	/* '!GPT' */
-	    data[ndata].base = 0x7be;
-	    data[ndata].size = synth_size;
-	    data[ndata].data = (void *)hand_area;
-	    ndata++;
-	    opt.regs.esi.w[0] = 0x7be;
-#ifdef DEBUG
-	    dprintf("GPT handover:\n");
-	    disk_dos_part_dump(hand_area);
-	    disk_gpt_part_dump((struct disk_gpt_part_entry *)(plen + 1));
-#endif
-	} else if (iter->type == typedos) {
-	    /* MBR handover protocol */
-	    /* Allocate the hand-over record */
-	    hand_area = malloc(sizeof(struct disk_dos_part_entry));
-	    if (!hand_area) {
-		error("Could not build MBR hand-over record!\n");
-		goto bail;
-	    }
-
-	    memcpy(hand_area, iter->record, sizeof(struct disk_dos_part_entry));
-	    hand_area->start_lba = (uint32_t)iter->start_lba;
-
-	    data[ndata].base = 0x7be;
-	    data[ndata].size = sizeof(struct disk_dos_part_entry);
-	    data[ndata].data = (void *)hand_area;
+    if (setup_handover(iter, data + ndata))
+	goto bail;
+    if(data[ndata].data) {
+	hand_area = data[ndata].data;
+	/* We have to make sure, that handover data doesn't overlap with the
+	 * file and/or the boot sector. For example, part of FreeDOS kernel
+	 * loaded at 0x600 would conflict with the handover data. Handover
+	 * is not critical, so we can let it pass with a warning.
+	 */
+	if ( ( fidx < 0 || noov(data + fidx, data + ndata)) &&
+	     ( sidx < 0 || noov(data + sidx, data + ndata)) ) {
+	    /* If all is fine, prep registers and inc ndata */
+	    opt.regs.esi.w[0] = opt.regs.ebp.w[0] = 0x7be;
+	    opt.regs.ds = 0;
+	    if(iter->type == typegpt)
+		opt.regs.eax.l = 0x54504721;	/* '!GPT' */
 	    ndata++;
-	    opt.regs.esi.w[0] = 0x7be;
-
-#ifdef DEBUG
-	    dprintf("MBR handover:\n");
-	    disk_dos_part_dump(hand_area);
-#endif
+	} else {
+	    error("WARNING: Handover ignored due to overlapping regions.\n");
 	}
     }
 


More information about the Syslinux-commits mailing list