[syslinux:elflink] execute(): move chainbooting code to its own file

syslinux-bot for H. Peter Anvin hpa at zytor.com
Thu Jun 7 15:27:08 PDT 2012


Commit-ID:  83f4c75f69986637ae653cd94a37329f3841f65a
Gitweb:     http://www.syslinux.org/commit/83f4c75f69986637ae653cd94a37329f3841f65a
Author:     H. Peter Anvin <hpa at zytor.com>
AuthorDate: Thu, 7 Jun 2012 15:23:46 -0700
Committer:  H. Peter Anvin <hpa at zytor.com>
CommitDate: Thu, 7 Jun 2012 15:23:46 -0700

execute(): move chainbooting code to its own file

To improve readability, move chainbooting to its own source file.

Signed-off-by: H. Peter Anvin <hpa at zytor.com>

---
 com32/elflink/ldlinux/Makefile    |    2 +-
 com32/elflink/ldlinux/chainboot.c |  175 +++++++++++++++++++++++++++++++++++++
 com32/elflink/ldlinux/execute.c   |  137 +----------------------------
 com32/include/menu.h              |    3 +
 4 files changed, 180 insertions(+), 137 deletions(-)

diff --git a/com32/elflink/ldlinux/Makefile b/com32/elflink/ldlinux/Makefile
index 75c618f..dc48ca9 100644
--- a/com32/elflink/ldlinux/Makefile
+++ b/com32/elflink/ldlinux/Makefile
@@ -20,7 +20,7 @@ LIBS = --whole-archive $(com32)/lib/libcom32min.a
 all: ldlinux.c32 ldlinux_lnx.a
 
 ldlinux.c32 : ldlinux.o cli.o readconfig.o refstr.o colors.o getadv.o \
-		adv.o execute.o kernel.o get_key.o \
+		adv.o execute.o chainboot.o kernel.o get_key.o \
 		advwrite.o setadv.o eprintf.o loadhigh.o
 	$(LD) $(LDFLAGS) -o $@ $^ $(LIBS)
 
diff --git a/com32/elflink/ldlinux/chainboot.c b/com32/elflink/ldlinux/chainboot.c
new file mode 100644
index 0000000..28f3280
--- /dev/null
+++ b/com32/elflink/ldlinux/chainboot.c
@@ -0,0 +1,175 @@
+/* ----------------------------------------------------------------------- *
+ *   
+ *   Copyright 2012 Intel Corporation, author: H. Peter Anvin
+ *
+ *   This program 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, Inc., 51 Franklin St, Fifth Floor,
+ *   Boston MA 02110-1301, USA; either version 2 of the License, or
+ *   (at your option) any later version; incorporated herein by reference.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * chainbooting - replace the current bootloader completely.  This
+ * is BIOS-specific.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <dprintf.h>
+
+#include <com32.h>
+#include <sys/exec.h>
+#include <sys/io.h>
+#include "core.h"
+#include "menu.h"
+#include "fs.h"
+#include "config.h"
+#include "localboot.h"
+#include "bios.h"
+
+#include <syslinux/bootrm.h>
+#include <syslinux/movebits.h>
+#include <syslinux/config.h>
+
+void chainboot_file(const char *file, enum kernel_type type)
+{
+    uint8_t keeppxe = 0;
+    const union syslinux_derivative_info *sdi;
+    struct syslinux_rm_regs regs;
+    struct syslinux_movelist *fraglist = NULL;
+    struct syslinux_memmap *mmap = NULL;
+    struct com32_filedata fd;
+    unsigned int free_mem, new_free_mem;
+    unsigned int edx, esi, bx;
+    com32sys_t reg;
+    char *stack;
+    void *buf;
+    int rv, max, size;
+    
+    max = 0xA0000;		/* Maximum load */
+    buf = malloc(max);
+    if (!buf)
+	goto bail;
+    
+    rv = open_file(file, &fd);
+    if (rv == -1) {
+	free(buf);
+	goto bail;
+    }
+    
+    reg.eax.l = max;
+    reg.ebx.l = 0;
+    reg.edx.w[0] = 0;
+    reg.edi.l = (uint32_t)buf;
+    reg.ebp.l = -1;	/* XXX: limit? */
+    reg.esi.w[0] = rv;
+
+    pm_load_high(&reg);
+
+    size = reg.edi.l - (unsigned long)buf;
+    if (size > 0xA0000 - 0x7C00) {
+	printf("Too large for a boostrap (need LINUX instead of KERNEL?)\n");
+	goto boot_bail;
+    }
+
+    esi = 0;
+    bx = 0;
+
+    sdi = syslinux_derivative_info();
+    edx = sdi->rr.r.edx.b[0];
+
+    memset(&regs, 0, sizeof(regs));
+
+    if (sdi->c.filesystem == SYSLINUX_FS_SYSLINUX ||
+	sdi->c.filesystem == SYSLINUX_FS_EXTLINUX) {
+	memcpy((void *)0x800 - 18, sdi->r.esbx, 16);
+
+	/* DS:SI points to partition info */
+	esi = 0x800 - 18;
+    }
+
+    /*
+     * For a BSS boot sector we have to transfer the
+     * superblock.
+     */
+    if (sdi->c.filesystem == SYSLINUX_FS_SYSLINUX &&
+	type == KT_BSS && vfat_copy_superblock(buf))
+	goto boot_bail;
+
+    /*
+     * Set up initial stack frame (not used by PXE if
+     * keeppxe is set - we use the PXE stack then.)
+     */
+    if (sdi->c.filesystem == SYSLINUX_FS_PXELINUX) {
+	keeppxe = 0x03;		/* Chainloading + keep PXE */
+	stack = (char *)sdi->r.fssi;
+
+	/*
+	 * Restore DS, EDX and ESI to the true initial
+	 * values.
+	 */
+	bx = *(uint16_t *)&stack[6];
+	edx = *(uint32_t *)&stack[28];
+	esi = *(uint32_t *)&stack[12];
+
+	/* Reset stack to PXE original */
+	regs.es = regs.ss = sdi->rr.r.fs;
+	regs.esp.w[0] = sdi->rr.r.esi.w[0] + 44;
+    } else {
+	char *esdi = (char *)sdi->disk.esdi_ptr;
+
+	/*
+	 * StackBuf is guaranteed to have 44 bytes
+	 * free immediately above it, and will not
+	 * interfere with our existing stack.
+	 */
+	stack = StackBuf;
+	memset(stack, 0, 44);
+
+	regs.esp.w[0] = (uint16_t)(unsigned long)stack + 44;
+
+	/*
+	 * DON'T DO THIS FOR PXELINUX...
+	 * For PXE, ES:BX -> PXENV+, and this would
+	 * corrupt that use.
+	 *
+	 * Restore ES:DI -> $PnP (if we were ourselves
+	 * called that way...)
+	 */
+
+	/* New DI */
+	*(uint16_t *)&stack[8] = *(uint16_t *)&esdi[0];
+
+	/* New ES */
+	*(uint16_t *)&stack[4] = *(uint16_t *)&esdi[2];
+
+    }
+
+    *(uint32_t *)&stack[28] = edx; /* New EDX */
+    *(uint32_t *)&stack[12] = esi; /* New ESI */
+    *(uint16_t *)&stack[6] = bx; /* New DS */
+
+    regs.ip = 0x7c00;
+    regs.esi.l = esi;
+    regs.edx.l = edx;
+
+    free_mem = *(volatile unsigned int *)BIOS_fbm;
+    free_mem <<= 10;
+    new_free_mem = free_mem - (0x7c00 + size);
+
+    mmap = syslinux_memory_map();
+    if (!mmap)
+	goto boot_bail;
+
+    if (!syslinux_add_movelist(&fraglist, 0x7c00, (addr_t)buf, size))
+	syslinux_shuffle_boot_rm(fraglist, mmap, keeppxe, &regs);
+
+    free(mmap);
+boot_bail:
+    free(buf);
+bail:
+    return;
+}
diff --git a/com32/elflink/ldlinux/execute.c b/com32/elflink/ldlinux/execute.c
index 5e47a62..97e5116 100644
--- a/com32/elflink/ldlinux/execute.c
+++ b/com32/elflink/ldlinux/execute.c
@@ -53,7 +53,6 @@ void execute(const char *cmdline, enum kernel_type type)
 	const char *kernel, *args;
 	com32sys_t ireg;
 	char *q;
-	uint8_t keeppxe = 0;
 
 	memset(&ireg, 0, sizeof ireg);
 
@@ -109,147 +108,13 @@ void execute(const char *cmdline, enum kernel_type type)
 	} else if (type == KT_LOCALBOOT) {
 		local_boot(strtoul(kernel, NULL, 0));
 	} else if (type == KT_PXE || type == KT_BSS || type == KT_BOOT) {
-		const union syslinux_derivative_info *sdi;
-		struct syslinux_rm_regs regs;
-		struct syslinux_movelist *fraglist = NULL;
-		struct syslinux_memmap *mmap = NULL;
-		struct com32_filedata fd;
-		unsigned int free_mem, new_free_mem;
-		unsigned int edx, esi, bx;
-		com32sys_t reg;
-		char *stack;
-		void *buf;
-		int rv, max, size;
-
-		max = 0xA0000;	/* Maximum load */
-		buf = malloc(max);
-		if (!buf)
-			goto bail;
-
-		rv = open_file(kernel, &fd);
-		if (rv == -1) {
-			free(buf);
-			goto bail;
-		}
-
-		reg.eax.l = max;
-		reg.ebx.l = 0;
-		reg.edx.w[0] = 0;
-		reg.edi.l = (uint32_t)buf;
-		reg.ebp.l = -1;	/* XXX: limit? */
-		reg.esi.w[0] = rv;
-
-		pm_load_high(&reg);
-
-		size = reg.edi.l - (unsigned long)buf;
-		if (size > 0xA0000 - 0x7C00) {
-			printf("Too large for a boostrap (need LINUX instead of KERNEL?)\n");
-			goto boot_bail;
-		}
-
-		esi = 0;
-		bx = 0;
-
-		sdi = syslinux_derivative_info();
-		edx = sdi->rr.r.edx.b[0];
-
-		memset(&regs, 0, sizeof(regs));
-
-		if (sdi->c.filesystem == SYSLINUX_FS_SYSLINUX ||
-		    sdi->c.filesystem == SYSLINUX_FS_EXTLINUX) {
-			memcpy((void *)0x800 - 18, sdi->r.esbx, 16);
-
-			/* DS:SI points to partition info */
-			esi = 0x800 - 18;
-		}
-
-		/*
-		 * For a BSS boot sector we have to transfer the
-		 * superblock.
-		 */
-		if (sdi->c.filesystem == SYSLINUX_FS_SYSLINUX &&
-		    type == KT_BSS && vfat_copy_superblock(buf))
-			goto boot_bail;
-
-		/*
-		 * Set up initial stack frame (not used by PXE if
-		 * keeppxe is set - we use the PXE stack then.)
-		 */
-		if (sdi->c.filesystem == SYSLINUX_FS_PXELINUX) {
-			keeppxe = 0x03;		/* Chainloading + keep PXE */
-			stack = (char *)sdi->r.fssi;
-
-			/*
-			 * Restore DS, EDX and ESI to the true initial
-			 * values.
-			 */
-			bx = *(uint16_t *)&stack[6];
-			edx = *(uint32_t *)&stack[28];
-			esi = *(uint32_t *)&stack[12];
-
-			/* Reset stack to PXE original */
-			regs.es = regs.ss = sdi->rr.r.fs;
-			regs.esp.w[0] = sdi->rr.r.esi.w[0] + 44;
-		} else {
-			char *esdi = (char *)sdi->disk.esdi_ptr;
-
-			/*
-			 * StackBuf is guaranteed to have 44 bytes
-			 * free immediately above it, and will not
-			 * interfere with our existing stack.
-			 */
-			stack = StackBuf;
-			memset(stack, 0, 44);
-
-			regs.esp.w[0] = (uint16_t)(unsigned long)stack + 44;
-
-			/*
-			 * DON'T DO THIS FOR PXELINUX...
-			 * For PXE, ES:BX -> PXENV+, and this would
-			 * corrupt that use.
-			 *
-			 * Restore ES:DI -> $PnP (if we were ourselves
-			 * called that way...)
-			 */
-
-			/* New DI */
-			*(uint16_t *)&stack[8] = *(uint16_t *)&esdi[0];
-
-			/* New ES */
-			*(uint16_t *)&stack[4] = *(uint16_t *)&esdi[2];
-
-		}
-
-		*(uint32_t *)&stack[28] = edx; /* New EDX */
-		*(uint32_t *)&stack[12] = esi; /* New ESI */
-		*(uint16_t *)&stack[6] = bx; /* New DS */
-
-		regs.ip = 0x7c00;
-		regs.esi.l = esi;
-		regs.edx.l = edx;
-
-		free_mem = *(volatile unsigned int *)BIOS_fbm;
-		free_mem <<= 10;
-		new_free_mem = free_mem - (0x7c00 + size);
-
-		mmap = syslinux_memory_map();
-		if (!mmap)
-			goto boot_bail;
-
-		if (!syslinux_add_movelist(&fraglist, 0x7c00,
-					   (addr_t)buf, size))
-			syslinux_shuffle_boot_rm(fraglist, mmap,
-						 keeppxe, &regs);
-		free(mmap);
-boot_bail:
-		free(buf);
+		chainboot_file(kernel, type);
 	} else {
 		/* Need add one item for kernel load, as we don't use
 		* the assembly runkernel.inc any more */
 		new_linux_kernel((char *)kernel, (char *)cmdline);
 	}
 
-bail:
 	lfree((void *)kernel);
 
 	/* If this returns, something went bad; return to menu */
diff --git a/com32/include/menu.h b/com32/include/menu.h
index ba6b9ce..be2eaeb 100644
--- a/com32/include/menu.h
+++ b/com32/include/menu.h
@@ -234,4 +234,7 @@ void execute(const char *cmdline, enum kernel_type type);
 /* drain.c */
 void drain_keyboard(void);
 
+/* chainboot.c */
+void chainboot_file(const char *file, enum kernel_type type);
+
 #endif /* MENU_H */


More information about the Syslinux-commits mailing list