[syslinux] [PATCH] chain.c32: add menu support to grub loader

Paul Bolle pebolle at tiscali.nl
Wed Jun 30 05:05:22 PDT 2010


Allow the grub loader to (optionally) support using a GRUB menu file.
For example
    chain fs grub=stage2,grub.conf

will load GRUB's stage2 and pass the (absolute) path to the file
"grub.conf" in the Syslinux filesystem to GRUB's stage2. The path is
passed to stage2 in GRUB's device/partition syntax (eg, "(hd0,1)/foo").
Note that we don't check whether the menu file actually exists in the
Syslinux filesystem. GRUB will do the right thing if the file doesn't
exist and will just fall back to its prompt.

(This patch pushes the usage string over the 80 characters border, which
might not be acceptable.)

Signed-off-by: Paul Bolle <pebolle at tiscali.nl>
---
 com32/modules/chain.c |   58 ++++++++++++++++++++++++++++++++++++------------
 1 files changed, 43 insertions(+), 15 deletions(-)

diff --git a/com32/modules/chain.c b/com32/modules/chain.c
index 4f5baf1..a386502 100644
--- a/com32/modules/chain.c
+++ b/com32/modules/chain.c
@@ -76,7 +76,7 @@
  *	equivalent to seg=0x70 file=<loader> sethidden,
  *	used with DOS' io.sys.
  *
- * grub=<loader>
+ * grub=<loader>[,<menu>]
  *	same as seg=0x800 file=<loader> & jumping to seg 0x820,
  *	used with GRUB stage2 files.
  *
@@ -124,6 +124,7 @@ static struct options {
     bool isolinux;
     bool cmldr;
     bool grub;
+    char *grubmenu;
     bool grldr;
     bool swap;
     bool hide;
@@ -1269,20 +1270,20 @@ Usage:   chain.c32 [options]\n\
          chain.c32 label:<label> [<partition>] [options]\n\
          chain.c32 boot [<partition>] [options]\n\
          chain.c32 fs [options]\n\
-Options: file=<loader>      Load and execute 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/2003\n\
-         freedos=<loader>   Load FreeDOS KERNEL.SYS\n\
-         msdos=<loader>     Load MS-DOS IO.SYS\n\
-         pcdos=<loader>     Load PC-DOS IBMBIO.COM\n\
-         grub=<loader>      Load GRUB stage2\n\
-         grldr=<loader>     Load GRUB4DOS grldr\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\
-         keeppxe            Keep the PXE and UNDI stacks in memory (PXELINUX)\n\
+Options: file=<loader>           Load and execute 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/2003\n\
+         freedos=<loader>        Load FreeDOS KERNEL.SYS\n\
+         msdos=<loader>          Load MS-DOS IO.SYS\n\
+         pcdos=<loader>          Load PC-DOS IBMBIO.COM\n\
+         grub=<loader>[,<menu>]  Load GRUB stage2, using (optional) <menu> file\n\
+         grldr=<loader>          Load GRUB4DOS grldr\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\
+         keeppxe                 Keep the PXE and UNDI stacks in memory (PXELINUX)\n\
 See syslinux/com32/modules/chain.c for more information\n";
     error(usage);
 }
@@ -1349,6 +1350,11 @@ int main(int argc, char *argv[])
 	    opt.seg = 0x800;	/* stage2 wants this address */
 	    opt.loadfile = argv[i] + 5;
 	    opt.grub = true;
+	    opt.grubmenu = strchr(opt.loadfile, ',');
+	    if (opt.grubmenu) {
+		*opt.grubmenu = '\0';
+		opt.grubmenu += 1;
+	    }
 	} else if (!strncmp(argv[i], "grldr=", 6)) {
 	    opt.loadfile = argv[i] + 6;
 	    opt.grldr = true;
@@ -1583,8 +1589,30 @@ int main(int argc, char *argv[])
 	}
 
 	if (opt.grub) {
+	    char *path;
 	    regs.ip = 0x200;	/* jump 0x200 bytes into the loadfile */
 
+	    /* 89 bytes reserved for menu at offset 0x217 */
+	    path = zalloc(89);
+
+	    if (path && opt.grubmenu) {
+		char partition[5];	/* maximum is ",100" and up! */
+		int len;
+
+		if (whichpart > 1)
+		    sprintf(partition, ",%d", whichpart - 1);
+		else
+		    partition[0] = '\0';
+		sprintf(path, "(%cd%d%s)/",
+		        drive & 0x80 ? 'h': 'f',
+		        (drive & 0x7),
+			partition);
+		len = strlen(path);
+		strncpy (path + len, opt.grubmenu, 89 - len);
+		memcpy(data[ndata].data + 0x217, path, 89);
+		memset(path + 88, '\0', 1);	/* to be safe*/
+	    }
+
 	    /* GRUB's stage2 wants the partition number in the install_partition
 	     * variable, located at memory address 0x8208.
 	     * We only need to change the value of memory address 0x820a too:
-- 
1.7.1






More information about the Syslinux mailing list