[syslinux:master] chain.c: Introduce sseg and fseg options.

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


Commit-ID:  1f948d6ff5f9539cc2d722ca4d20b26eaa5e420d
Gitweb:     http://www.syslinux.org/commit/1f948d6ff5f9539cc2d722ca4d20b26eaa5e420d
Author:     Michal Soltys <soltys at ziu.info>
AuthorDate: Mon, 16 Aug 2010 12:47:02 +0200
Committer:  Michal Soltys <soltys at ziu.info>
CommitDate: Sun, 22 Aug 2010 23:45:15 +0200

chain.c: Introduce sseg and fseg options.

Add options for detailed specification of load and jump addresses.
Misc adjustments.

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

---
 com32/chain/Makefile |    5 ++-
 com32/chain/chain.c  |  108 +++++++++++++++++++++++++++++++++-----------------
 2 files changed, 76 insertions(+), 37 deletions(-)

diff --git a/com32/chain/Makefile b/com32/chain/Makefile
index 9c1e467..1c2b188 100644
--- a/com32/chain/Makefile
+++ b/com32/chain/Makefile
@@ -16,13 +16,16 @@ topdir = ../..
 include ../MCONFIG
 
 OBJS = chain.o partiter.o
-GCCWARN += -Wextra -Wconversion -pedantic -Wno-error
+GCCWARN2 = -Wextra -Wconversion -pedantic -Wno-error
 
 all: chain.c32
 
 chain.elf: $(OBJS) $(LIBS) $(C_LIBS)
 	$(LD) $(LDFLAGS) -o $@ $^
 
+%.o: %.c
+	$(CC) $(MAKEDEPS) $(CFLAGS) $(GCCWARN2) -c -o $@ $<
+
 tidy dist:
 	rm -f *.o *.lo *.a *.lst *.elf .*.d *.tmp
 
diff --git a/com32/chain/chain.c b/com32/chain/chain.c
index 9eb6983..6b69302 100644
--- a/com32/chain/chain.c
+++ b/com32/chain/chain.c
@@ -41,12 +41,17 @@
 static const char cmldr_signature[8] = "cmdcons";
 
 static struct options {
+    uint32_t flin;
+    uint16_t fseg;
+    uint16_t fip;
+    uint32_t slin;
+    uint16_t sseg;
+    uint16_t sip;
     const char *drivename;
     const char *partition;
     const char *loadfile;
     const char *grubcfg;
     uint16_t keeppxe;
-    uint16_t seg;
     bool isolinux;
     bool cmldr;
     bool grub;
@@ -275,7 +280,7 @@ static void do_boot(struct data_area *data, int ndata)
 	opt.regs.esi.l = opt.regs.es = 0;
 	opt.regs.ecx.l = sizeof swapstub >> 2;
 	opt.regs.ip = 0x10;	/* Installer offset */
-	opt.regs.ebx.b[0] = opt.regs.edx.b[0] = swapdrive;	//FIXME this silently assumes DOS expectations
+	opt.regs.ebx.b[0] = opt.regs.edx.b[0] = swapdrive;
 
 	if (syslinux_add_movelist(&mlist, endimage, (addr_t) swapstub,
 				  sizeof swapstub))
@@ -465,42 +470,66 @@ Usage:\n\
 static int parse_args(int argc, char *argv[])
 {
     int i;
+    unsigned int v;
     char *p;
 
     for (i = 1; i < argc; i++) {
 	if (!strncmp(argv[i], "file=", 5)) {
 	    opt.loadfile = argv[i] + 5;
-	} else if (!strncmp(argv[i], "seg=", 4)) {
-	    if(soi2sli(argv[i] + 4, &opt.seg, NULL, NULL))
+	} else if ((v = 4, !strncmp(argv[i], "seg=", v)) ||
+		   (v = 5, !strncmp(argv[i], "fseg=", v))) {
+	    if(soi2sli(argv[i] + v, &opt.fseg, &opt.flin, &opt.fip))
 		goto bail;
+	} else if (!strncmp(argv[i], "sseg=", 5)) {
+	    if(soi2sli(argv[i] + 5, &opt.sseg, &opt.slin, &opt.sip))
+		goto bail;
+	    if(opt.slin + SECTOR - 1 > ADDRMAX) {
+		error("Option 'sseg' is invalid - address too big.\n");
+		goto bail;
+	    }
 	} else if (!strncmp(argv[i], "isolinux=", 9)) {
 	    opt.loadfile = argv[i] + 9;
 	    opt.isolinux = true;
 	} else if (!strncmp(argv[i], "ntldr=", 6)) {
-	    opt.seg = 0x2000;	/* NTLDR wants this address */
+	    opt.fseg = 0x2000;  /* NTLDR wants this address */
+	    opt.flin = 0x20000;
+	    opt.fip = 0;
 	    opt.loadfile = argv[i] + 6;
 	    opt.sethid = true;
 	} else if (!strncmp(argv[i], "cmldr=", 6)) {
-	    opt.seg = 0x2000;	/* CMLDR wants this address */
+	    opt.fseg = 0x2000;  /* CMLDR wants this address */
+	    opt.flin = 0x20000;
+	    opt.fip = 0;
 	    opt.loadfile = argv[i] + 6;
 	    opt.cmldr = true;
 	    opt.sethid = true;
 	} else if (!strncmp(argv[i], "freedos=", 8)) {
-	    opt.seg = 0x60;	/* FREEDOS wants this address */
+	    opt.fseg = 0x60;    /* FREEDOS wants this address */
+	    opt.flin = 0x600;
+	    opt.fip = 0;
 	    opt.loadfile = argv[i] + 8;
 	    opt.sethid = true;
 	} else if (!strncmp(argv[i], "msdos=", 6) ||
 		   !strncmp(argv[i], "pcdos=", 6)) {
-	    opt.seg = 0x70;	/* MS-DOS 2.0+ wants this address */
+	    opt.fseg = 0x70;    /* MS-DOS 2.00 .. 6.xx wants this address */
+	    opt.flin = 0x700;
+	    opt.fip = 0;
+#if 0
+	    opt.file_ip = val == 7 ? 0x200 : 0;  /* MS-DOS 7.0+ wants this ip */
+#endif
 	    opt.loadfile = argv[i] + 6;
 	    opt.sethid = true;
 	} else if (!strncmp(argv[i], "drmk=", 5)) {
-	    opt.seg = 0x70;	/* DRMK wants this address */
+	    opt.fseg = 0x70;    /* DRMK wants this address */
+	    opt.flin = 0x700;
+	    opt.fip = 0;
 	    opt.loadfile = argv[i] + 5;
 	    opt.sethid = true;
 	    opt.drmk = true;
 	} else if (!strncmp(argv[i], "grub=", 5)) {
-	    opt.seg = 0x800;	/* stage2 wants this address */
+	    opt.fseg = 0x800;	/* stage2 wants this address */
+	    opt.flin = 0x8000;
+	    opt.fip = 0x200;
 	    opt.loadfile = argv[i] + 5;
 	    opt.grub = true;
 	} else if (!strncmp(argv[i], "grubcfg=", 8)) {
@@ -521,10 +550,10 @@ static int parse_args(int argc, char *argv[])
 	} else if (!strcmp(argv[i], "nokeeppxe")) {
 	    opt.keeppxe = 0;
 	} else if (!strcmp(argv[i], "sethid") ||
-		!strcmp(argv[i], "sethidden")) {
+		   !strcmp(argv[i], "sethidden")) {
 	    opt.sethid = true;
 	} else if (!strcmp(argv[i], "nosethid") ||
-		!strcmp(argv[i], "nosethidden")) {
+		   !strcmp(argv[i], "nosethidden")) {
 	    opt.sethid = false;
 	} else if (((argv[i][0] == 'h' || argv[i][0] == 'f')
 		    && argv[i][1] == 'd')
@@ -609,7 +638,7 @@ int find_dp(struct part_iter **_iter)
 	       opt.drivename[1] == 'd') {
 	hd = opt.drivename[0] == 'h' ? 0x80 : 0;
 	opt.drivename += 2;
-	drive = hd | (int)strtoul(opt.drivename, NULL, 0);
+	drive = hd | strtol(opt.drivename, NULL, 0);
 
 	if (disk_get_params(drive, &diskinfo))
 	    goto bail;
@@ -652,12 +681,12 @@ int find_dp(struct part_iter **_iter)
 	error("Unparsable drive specification.\n");
 	goto bail;
     }
-    /* main options done, only thing left is explicit parition specification
+    /* main options done - only thing left is explicit partition specification,
      * if we're still at the disk stage with the iterator AND user supplied
      * partition number (including disk).
      */
     if (!iter->index && opt.partition) {
-	partition = (int)strtoul(opt.partition, NULL, 0);
+	partition = strtol(opt.partition, NULL, 0);
 	/* search for matching part#, including disk */
 	do {
 	    if (iter->index == partition)
@@ -820,9 +849,6 @@ static int manglef_grublegacy(const struct part_iter *_iter, struct data_area *_
 	goto bail;
     }
 
-    /* jump 0x200 bytes into the loadfile */
-    opt.regs.ip = 0x200;
-
     /*
      * GRUB Legacy wants the partition number in the install_partition
      * variable, located at offset 0x208 of stage2.
@@ -889,7 +915,7 @@ static int manglef_drmk(struct data_area *_data)
     }
     _data->size = tsize;
     /* ds:[bp+28] must be 0x0000003f */
-    opt.regs.ds = (uint16_t)((tsize >> 4) + (opt.seg - 2u));
+    opt.regs.ds = (uint16_t)((tsize >> 4) + (opt.fseg - 2u));
     /* "Patch" into tail of the new space */
     *(uint32_t *)((char*)_data->data + tsize - 4) = 0x0000003f;
 
@@ -902,30 +928,40 @@ int main(int argc, char *argv[])
 {
     struct part_iter *iter = NULL;
 
-    void *sect_area = NULL;
     void *file_area = NULL;
+    void *sect_area = NULL;
     struct disk_dos_part_entry *hand_area = NULL;
 
     struct data_area data[3];
     int ndata = 0, fidx = -1, sidx = -1;
-    addr_t load_base;
 
     openconsole(&dev_null_r, &dev_stdcon_w);
 
-    /* Prepare and set default values */
+    /* Prepare and set defaults */
+    memset(data, 0, sizeof(data));
     memset(&opt, 0, sizeof(opt));
-    opt.drivename = "boot";	/* potential FIXME: maybe we shouldn't assume boot by default, do wonder later */
-
+    opt.flin = opt.slin = opt.fip = opt.sip = 0x7C00;
+    opt.drivename = "boot";	/*
+				 * potential FIXME: maybe
+				 * we shouldn't assume boot
+				 * by default, do wonder later
+				 */
     /* Parse arguments */
     if(parse_args(argc, argv))
 	goto bail;
 
-    if (opt.seg) {
+    /* Set initial registry values, file takes precedence */
+    if(opt.loadfile) {
 	opt.regs.es = opt.regs.cs = opt.regs.ss =
-	    opt.regs.ds = opt.regs.fs = opt.regs.gs = opt.seg;
+	   opt.regs.ds = opt.regs.fs = opt.regs.gs = opt.fseg;
+	opt.regs.ip = opt.fip;
     } else {
-	opt.regs.esp.l = opt.regs.ip = 0x7c00;
+	opt.regs.es = opt.regs.cs = opt.regs.ss =
+	    opt.regs.ds = opt.regs.fs = opt.regs.gs = opt.sseg;
+	opt.regs.ip = opt.sip;
     }
+    if(opt.regs.ip == 0x7C00 && !opt.regs.cs)
+	opt.regs.esp.l = 0x7C00;
 
     /* Get disk/part iterator matching user supplied options */
     if(find_dp(&iter))
@@ -937,29 +973,29 @@ int main(int argc, char *argv[])
 
     /* Load file and bs/mbr */
 
-    load_base = opt.seg ? (uint32_t)(opt.seg << 4) : 0x7c00;
-
     if (opt.loadfile) {
-	fputs("Loading the boot file...\n", stdout);
 	if (loadfile(opt.loadfile, &data[ndata].data, &data[ndata].size)) {
 	    error("Couldn't read the boot file.\n");
 	    goto bail;
 	}
+	if (opt.flin + data[ndata].size - 1 > ADDRMAX) {
+	    error("Can't load the boot file at this address.\n");
+	    goto bail;
+	}
+
 	file_area = (void *)data[ndata].data;
-	data[ndata].base = load_base;
-	load_base = 0x7c00;	/* If we also load a boot sector */
+	data[ndata].base = opt.flin;
 	fidx = ndata;
 	ndata++;
     }
 
     if (!opt.loadfile || data[0].base >= 0x7c00 + SECTOR) {
 	if (!(data[ndata].data = disk_read_sectors(&iter->di, iter->start_lba, 1))) {
-	    error("Couldn't read the boot sector or mbr.\n");
+	    error("Couldn't read the bs / mbr.\n");
 	    goto bail;
 	}
-
 	sect_area = (void *)data[ndata].data;
-	data[ndata].base = load_base;
+	data[ndata].base = opt.slin;
 	data[ndata].size = SECTOR;
 	sidx = ndata;
 	ndata++;
@@ -997,7 +1033,7 @@ int main(int argc, char *argv[])
      * this modifies the field used by FAT and NTFS filesystems, and
      * possibly other boot loaders which use the same format.
      */
-    if (iter->index && opt.sethidden) {
+    if (iter->index && opt.sethid) {
 	if(iter->start_lba < 0x100000000)
 	    *(uint32_t *) ((char *)data[sidx].data + 0x1c) = (uint32_t)iter->start_lba;
 	else


More information about the Syslinux-commits mailing list