[PATCH] chain.c32: Allow chaining the current Syslinux partition
Shao Miller
shao.miller at yrdsb.edu.on.ca
Sat Mar 13 04:50:32 PST 2010
"chain.c32 fs" will determine the disk and partition (if
applicable) and boot it, possibly with additional options.
Only applicable from SYSLINUX and EXTLINUX at this time.
Signed-off-by: Shao Miller <shao.miller at yrdsb.edu.on.ca>
---
com32/modules/chain.c | 112 ++++++++++++++++++++++++++++++++-----------------
1 files changed, 74 insertions(+), 38 deletions(-)
mode change 100644 => 100755 com32/modules/chain.c
diff --git a/com32/modules/chain.c b/com32/modules/chain.c
old mode 100644
new mode 100755
index 160aa70..07e1bc6
--- a/com32/modules/chain.c
+++ b/com32/modules/chain.c
@@ -16,24 +16,33 @@
*
* Chainload a hard disk (currently rather braindead.)
*
- * Usage: chain hd<disk#> [<partition>] [options]
+ * Usage: chain [options]
+ * chain hd<disk#> [<partition>] [options]
* chain fd<disk#> [options]
* chain mbr:<id> [<partition>] [options]
* chain boot [<partition>] [options]
+ * chain fs [options]
*
- * ... e.g. "chain hd0 1" will boot the first partition on the first hard
+ * For example, "chain msdos=io.sys" will load DOS from the current Syslinux
+ * filesystem. "chain hd0 1" will boot the first partition on the first hard
* disk.
*
+ * When none of the "hdX", "fdX", "mbr:", "boot" or "fs" options are specified,
+ * the default behaviour is equivalent to "boot". "boot" means to use the
+ * current Syslinux drive, and you can also specify a partition.
*
* The mbr: syntax means search all the hard disks until one with a
* specific MBR serial number (bytes 440-443) is found.
*
* Partitions 1-4 are primary, 5+ logical, 0 = boot MBR (default.)
*
+ * "fs" will use the current Syslinux filesystem as the boot drive/partition.
+ * When booting from PXELINUX, you will most likely wish to specify a disk.
+ *
* Options:
*
* file=<loader>:
- * loads the file <loader> **from the SYSLINUX filesystem**
+ * loads the file <loader> **from the Syslinux filesystem**
* instead of loading the boot sector.
*
* seg=<segment>:
@@ -376,7 +385,7 @@ struct part_entry {
are relative to the beginning of the extended partition all the way back
at the MBR... but still not absolute! */
-int nextpart; /* Number of the next logical partition */
+int nextpart = 1; /* Number of the next logical partition */
static struct part_entry *find_logical_partition(int whichpart, char *table,
struct part_entry *self,
@@ -406,6 +415,15 @@ static struct part_entry *find_logical_partition(int whichpart, char *table,
if (!ptab[i].length)
continue;
+ /*
+ * We support a reverse-lookup mode where "self" is a
+ * partition table entry to find the partition number for.
+ */
+ if (whichpart == 0 &&
+ self->start_lba == ptab[i].start_lba &&
+ self->length == ptab[i].length)
+ return self;
+
/* Adjust the offset to account for the extended partition itself */
ptab[i].start_lba += self->start_lba;
@@ -596,10 +614,8 @@ static int hide_unhide(char *mbr, int part)
int i;
struct part_entry *pt;
const uint16_t mask =
- (1 << 0x01) | (1 << 0x04) | (1 << 0x06) | (1 << 0x07) | (1 << 0x0b) | (1
- <<
- 0x0c)
- | (1 << 0x0e);
+ (1 << 0x01) | (1 << 0x04) | (1 << 0x06) |
+ (1 << 0x07) | (1 << 0x0b) | (1 << 0x0c) | (1 << 0x0e);
uint8_t t;
bool write_back = false;
@@ -668,21 +684,29 @@ static uint32_t get_file_lba(const char *filename)
static void usage(void)
{
- error("Usage: chain.c32 hd<disk#> [<partition>] [options]\n"
+ error("Usage: chain.c32 [options]\n"
+ " chain.c32 hd<disk#> [<partition>] [options]\n"
" chain.c32 fd<disk#> [options]\n"
" chain.c32 mbr:<id> [<partition>] [options]\n"
" chain.c32 boot [<partition>] [options]\n"
- "Options: file=<loader> load file, instead of boot sector\n"
- " isolinux=<loader> load another version of ISOLINUX\n"
- " ntldr=<loader> load Windows NTLDR, SETUPLDR.BIN or BOOTMGR\n"
- " cmldr=<loader> load Recovery Console of Windows NT/2K/XP\n"
- " freedos=<loader> load FreeDOS kernel.sys\n"
- " msdos=<loader> load MS-DOS io.sys\n"
- " pcdos=<loader> load PC-DOS ibmbio.com\n"
- " seg=<segment> jump to <seg>:0000 instead of 0000:7C00\n"
- " swap swap drive numbers, if bootdisk is not fd0/hd0\n"
- " hide hide primary partitions, except selected partition\n"
- " sethidden set the FAT/NTFS hidden sectors field\n"
+ " chain.c32 fs [options]\n"
+ "Options: file=<loader> Load file, instead of boot sector\n"
+ " isolinux=<loader> Load another version of ISOLINUX\n"
+ " ntldr=<loader> Load Windows NTLDR, SETUPLDR.BIN or "
+ "BOOTMGR\n"
+ " cmldr=<loader> Load Recovery Console of Windows "
+ "NT/2K/XP\n"
+ " freedos=<loader> Load FreeDOS kernel.sys\n"
+ " msdos=<loader> Load MS-DOS io.sys\n"
+ " pcdos=<loader> Load PC-DOS ibmbio.com\n"
+ " seg=<segment> Jump to <seg>:0000 instead of "
+ "0000:7C00\n"
+ " swap Swap drive numbers, if bootdisk is not "
+ "fd0/hd0\n"
+ " hide Hide primary partitions, except "
+ "selected partition\n"
+ " sethidden Set the FAT/NTFS hidden sectors field\n"
+ "See syslinux/com32/modules/chain.c for more information\n"
);
}
@@ -691,9 +715,10 @@ int main(int argc, char *argv[])
{
char *mbr, *p;
struct part_entry *partinfo;
+ static struct part_entry *fs = NULL; /* Syslinux partition */
struct syslinux_rm_regs regs;
char *drivename, *partition;
- int hd, drive, whichpart;
+ int hd, drive, whichpart = 0; /* MBR by default */
int i;
uint32_t file_lba = 0;
unsigned char *isolinux_bin;
@@ -761,7 +786,8 @@ int main(int argc, char *argv[])
|| !strncmp(argv[i], "mbr:", 4)
|| !strncmp(argv[i], "mbr=", 4)
|| !strcmp(argv[i], "boot")
- || !strncmp(argv[i], "boot,", 5)) {
+ || !strncmp(argv[i], "boot,", 5)
+ || !strncmp(argv[i], "fs", 2)) {
drivename = argv[i];
p = strchr(drivename, ',');
if (p) {
@@ -795,13 +821,19 @@ int main(int argc, char *argv[])
hd = drivename[0] == 'h';
drivename += 2;
drive = (hd ? 0x80 : 0) | strtoul(drivename, NULL, 0);
- } else if (!strcmp(drivename, "boot")) {
+ } else if (!strcmp(drivename, "boot") || !strcmp(drivename, "fs")) {
const union syslinux_derivative_info *sdi;
+
sdi = syslinux_derivative_info();
if (sdi->c.filesystem == SYSLINUX_FS_PXELINUX)
drive = 0x80; /* Boot drive not available */
else
drive = sdi->disk.drive_number;
+ if (!strcmp(drivename, "fs")
+ && (sdi->c.filesystem == SYSLINUX_FS_SYSLINUX
+ || sdi->c.filesystem == SYSLINUX_FS_EXTLINUX))
+ /* We should lookup the Syslinux partition number and use it */
+ fs = (struct part_entry *)sdi->disk.ptab_ptr;
} else {
error("Unparsable drive specification\n");
goto bail;
@@ -810,34 +842,38 @@ int main(int argc, char *argv[])
/* DOS kernels want the drive number in BL instead of DL. Indulge them. */
regs.ebx.b[0] = regs.edx.b[0] = drive;
- whichpart = 0; /* Default */
+ /* Get the disk geometry and disk access setup */
+ if (get_disk_params(drive)) {
+ error("Cannot get disk parameters\n");
+ goto bail;
+ }
+
+ /* Get MBR */
+ if (!(mbr = read_sector(0))) {
+ error("Cannot read Master Boot Record\n");
+ goto bail;
+ }
+
if (partition)
whichpart = strtoul(partition, NULL, 0);
+ /* We should lookup the Syslinux partition number and use it */
+ if (fs != NULL)
+ whichpart = (find_logical_partition(0, mbr, fs, NULL) != NULL)
+ ? nextpart : 0;
+
if (!(drive & 0x80) && whichpart) {
error("Warning: Partitions of floppy devices may not work\n");
}
- /*
- * grldr of Grub4dos wants the partition number in DH:
+ /*
+ * GRLDR of GRUB4DOS wants the partition number in DH:
* -1: whole drive (default)
* 0-3: primary partitions
* 4-*: logical partitions
*/
regs.edx.b[1] = whichpart-1;
- /* Get the disk geometry and disk access setup */
- if (get_disk_params(drive)) {
- error("Cannot get disk parameters\n");
- goto bail;
- }
-
- /* Get MBR */
- if (!(mbr = read_sector(0))) {
- error("Cannot read Master Boot Record\n");
- goto bail;
- }
-
if (opt.hide) {
if (whichpart < 1 || whichpart > 4)
error("WARNING: hide specified without a non-primary partition\n");
--
1.5.3.4
--------------060300050103070204070604--
More information about the Syslinux
mailing list