Module Name:    src
Committed By:   nonaka
Date:           Sun Mar 12 05:33:48 UTC 2017

Modified Files:
        src/sys/arch/i386/stand/efiboot: boot.c
        src/sys/arch/i386/stand/lib: exec.c libi386.h

Log Message:
efiboot: Kernel modules are loaded in pre-allocated memory.


To generate a diff of this commit:
cvs rdiff -u -r1.3 -r1.4 src/sys/arch/i386/stand/efiboot/boot.c
cvs rdiff -u -r1.66 -r1.67 src/sys/arch/i386/stand/lib/exec.c
cvs rdiff -u -r1.41 -r1.42 src/sys/arch/i386/stand/lib/libi386.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/arch/i386/stand/efiboot/boot.c
diff -u src/sys/arch/i386/stand/efiboot/boot.c:1.3 src/sys/arch/i386/stand/efiboot/boot.c:1.4
--- src/sys/arch/i386/stand/efiboot/boot.c:1.3	Fri Mar  3 09:29:57 2017
+++ src/sys/arch/i386/stand/efiboot/boot.c	Sun Mar 12 05:33:48 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: boot.c,v 1.3 2017/03/03 09:29:57 nonaka Exp $	*/
+/*	$NetBSD: boot.c,v 1.4 2017/03/12 05:33:48 nonaka Exp $	*/
 
 /*-
  * Copyright (c) 2016 Kimihiro Nonaka <non...@netbsd.org>
@@ -31,10 +31,9 @@
 #include <sys/bootblock.h>
 #include <sys/boot_flag.h>
 
-#include <lib/libsa/bootcfg.h>
-
-#include <bootmod.h>
-#include <bootmenu.h>
+#include "bootcfg.h"
+#include "bootmod.h"
+#include "bootmenu.h"
 #include "devopen.h"
 
 int errno;
@@ -207,16 +206,40 @@ clearit(void)
 static void
 bootit(const char *filename, int howto)
 {
+	EFI_STATUS status;
+	EFI_PHYSICAL_ADDRESS bouncebuf;
+	UINTN npages;
+	u_long allocsz;
 
 	if (howto & AB_VERBOSE)
 		printf("booting %s (howto 0x%x)\n", sprint_bootsel(filename),
 		    howto);
 
-	if (exec_netbsd(filename, 0, howto, 0, efi_cleanup) < 0)
+	if (count_netbsd(filename, &allocsz) < 0) {
+		printf("boot: %s: %s\n", sprint_bootsel(filename),
+		       strerror(errno));
+		return;
+	}
+
+	bouncebuf = EFI_ALLOCATE_MAX_ADDRESS;
+	npages = EFI_SIZE_TO_PAGES(allocsz);
+	status = uefi_call_wrapper(BS->AllocatePages, 4, AllocateMaxAddress,
+	    EfiLoaderData, npages, &bouncebuf);
+	if (EFI_ERROR(status)) {
+		printf("boot: %s: %s\n", sprint_bootsel(filename),
+		       strerror(ENOMEM));
+		return;
+	}
+
+	efi_loadaddr = bouncebuf;
+	if (exec_netbsd(filename, bouncebuf, howto, 0, efi_cleanup) < 0)
 		printf("boot: %s: %s\n", sprint_bootsel(filename),
 		       strerror(errno));
 	else
 		printf("boot returned\n");
+
+	(void) uefi_call_wrapper(BS->FreePages, 2, bouncebuf, npages);
+	efi_loadaddr = 0;
 }
 
 void

Index: src/sys/arch/i386/stand/lib/exec.c
diff -u src/sys/arch/i386/stand/lib/exec.c:1.66 src/sys/arch/i386/stand/lib/exec.c:1.67
--- src/sys/arch/i386/stand/lib/exec.c:1.66	Thu Feb 23 12:14:53 2017
+++ src/sys/arch/i386/stand/lib/exec.c	Sun Mar 12 05:33:48 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: exec.c,v 1.66 2017/02/23 12:14:53 nonaka Exp $	 */
+/*	$NetBSD: exec.c,v 1.67 2017/03/12 05:33:48 nonaka Exp $	 */
 
 /*
  * Copyright (c) 2008, 2009 The NetBSD Foundation, Inc.
@@ -151,6 +151,11 @@ static void	module_add_common(const char
 
 static void	userconf_init(void);
 
+static void	extract_device(const char *, char *, size_t);
+static void	module_base_path(char *, size_t);
+static int	module_open(boot_module_t *, int, const char *, const char *,
+		    bool);
+
 void
 framebuffer_configure(struct btinfo_framebuffer *fb)
 {
@@ -196,6 +201,10 @@ module_add_common(const char *name, uint
 	while (*name == ' ' || *name == '\t')
 		++name;
 
+	for (bm = boot_modules; bm != NULL; bm = bm->bm_next)
+		if (bm->bm_type == type && strcmp(bm->bm_path, name) == 0)
+			return;
+
 	bm = alloc(sizeof(boot_module_t));
 	len = strlen(name) + 1;
 	str = alloc(len);
@@ -299,30 +308,6 @@ common_load_kernel(const char *file, u_l
 			return ENOMEM;
 	}
 #endif
-#ifdef EFIBOOT
-	{
-		EFI_STATUS status;
-		EFI_PHYSICAL_ADDRESS addr;
-		UINTN kernsize;
-
-		marks[MARK_START] = loadaddr;
-		if ((fd = loadfile(file, marks, COUNT_KERNEL)) == -1)
-			return EIO;
-		close(fd);
-
-		/* Allocate temporary arena. */
-		addr = EFI_ALLOCATE_MAX_ADDRESS;
-		kernsize = marks[MARK_END] - loadaddr;
-		kernsize = EFI_SIZE_TO_PAGES(kernsize);
-		status = uefi_call_wrapper(BS->AllocatePages, 4,
-		    AllocateMaxAddress, EfiLoaderData, kernsize, &addr);
-		if (EFI_ERROR(status))
-			return ENOMEM;
-		efi_loadaddr = loadaddr = addr;
-
-		memset(marks, 0, sizeof(marks[0]) * MARK_MAX);
-	}
-#endif
 	marks[MARK_START] = loadaddr;
 	if ((fd = loadfile(file, marks,
 	    LOAD_KERNEL & ~(floppy ? LOAD_BACKWARDS : 0))) == -1)
@@ -360,15 +345,6 @@ common_load_kernel(const char *file, u_l
 		ppbcopy(loadaddr, origaddr, marks[MARK_END]);
 	}
 #endif
-#ifdef EFIBOOT
-	marks[MARK_START] -= loadaddr;
-	marks[MARK_ENTRY] -= loadaddr;
-	marks[MARK_DATA] -= loadaddr;
-	/* MARK_NSYM */
-	marks[MARK_SYM] -= loadaddr;
-	marks[MARK_END] -= loadaddr;
-	/* Copy the kernel to original load address later. */
-#endif
 	marks[MARK_END] = (((u_long) marks[MARK_END] + sizeof(int) - 1)) &
 	    (-sizeof(int));
 	image_end = marks[MARK_END];
@@ -410,6 +386,15 @@ exec_netbsd(const char *file, physaddr_t
 		errno = error;
 		goto out;
 	}
+#ifdef EFIBOOT
+	/* adjust to the real load address */
+	marks[MARK_START] -= efi_loadaddr;
+	marks[MARK_ENTRY] -= efi_loadaddr;
+	marks[MARK_DATA] -= efi_loadaddr;
+	/* MARK_NSYM */
+	marks[MARK_SYM] -= efi_loadaddr;
+	marks[MARK_END] -= efi_loadaddr;
+#endif
 
 	boot_argv[0] = boothowto;
 	boot_argv[1] = 0;
@@ -422,6 +407,14 @@ exec_netbsd(const char *file, physaddr_t
 	if (boot_modules_enabled) {
 		module_init(file);
 		if (btinfo_modulelist) {
+#ifdef EFIBOOT
+			/* convert module loaded address to paddr */
+			struct bi_modulelist_entry *bim;
+			bim = (void *)(btinfo_modulelist + 1);
+			for (i = 0; i < btinfo_modulelist->num; i++, bim++)
+				bim->base -= efi_loadaddr;
+			btinfo_modulelist->endpa -= efi_loadaddr;
+#endif
 			BI_ADD(btinfo_modulelist, BTINFO_MODULELIST,
 			    btinfo_modulelist_size);
 		}
@@ -459,7 +452,7 @@ exec_netbsd(const char *file, physaddr_t
 	}
 
 	efi_kernel_start = marks[MARK_START];
-	efi_kernel_size = marks[MARK_END] - efi_kernel_start;
+	efi_kernel_size = image_end - efi_loadaddr - efi_kernel_start;
 #endif
 	startprog(marks[MARK_ENTRY], BOOT_NARGS, boot_argv,
 	    x86_trunc_page(basemem * 1024));
@@ -471,6 +464,53 @@ out:
 	return -1;
 }
 
+int
+count_netbsd(const char *file, u_long *rsz)
+{
+	u_long marks[MARK_MAX];
+	char kdev[64];
+	char base_path[64];
+	struct stat st;
+	boot_module_t *bm;
+	u_long sz;
+	int err, fd;
+
+	memset(marks, 0, sizeof(marks));
+	if ((fd = loadfile(file, marks, COUNT_KERNEL)) == -1)
+		return -1;
+	close(fd);
+	marks[MARK_END] = (((u_long) marks[MARK_END] + sizeof(int) - 1)) &
+	    (-sizeof(int));
+	sz = marks[MARK_END];
+
+	/* The modules must be allocated after the kernel */
+	if (boot_modules_enabled) {
+		extract_device(file, kdev, sizeof(kdev));
+		module_base_path(base_path, sizeof(base_path));
+
+		/* If the root fs type is unusual, load its module. */
+		if (fsmod != NULL)
+			module_add(__UNCONST(fsmod));
+
+		for (bm = boot_modules; bm; bm = bm->bm_next) {
+			fd = module_open(bm, 0, kdev, base_path, false);
+			if (fd == -1)
+				continue;
+			sz = (image_end + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1);
+			err = fstat(fd, &st);
+			if (err == -1 || st.st_size == -1) {
+				close(fd);
+				continue;
+			}
+			sz += st.st_size;
+			close(fd);
+		}
+	}
+
+	*rsz = sz;
+	return 0;
+}
+
 static void
 extract_device(const char *path, char *buf, size_t buflen)
 {
@@ -486,7 +526,7 @@ extract_device(const char *path, char *b
 }
 
 static const char *
-module_path(boot_module_t *bm, const char *kdev)
+module_path(boot_module_t *bm, const char *kdev, const char *base_path)
 {
 	static char buf[256];
 	char name_buf[256], dev_buf[64];
@@ -510,7 +550,7 @@ module_path(boot_module_t *bm, const cha
 			p++;
 			extract_device(name, dev_buf, sizeof(dev_buf));
 			snprintf(buf, sizeof(buf), "%s%s/%s/%s.kmod",
-			    dev_buf, module_base, p, p);
+			    dev_buf, base_path, p, p);
 		}
 	} else {
 		/* device not specified; load from kernel device if known */
@@ -518,20 +558,21 @@ module_path(boot_module_t *bm, const cha
 			snprintf(buf, sizeof(buf), "%s%s", kdev, name);
 		else
 			snprintf(buf, sizeof(buf), "%s%s/%s/%s.kmod",
-			    kdev, module_base, name, name);
+			    kdev, base_path, name, name);
 	}
 
 	return buf;
 }
 
 static int
-module_open(boot_module_t *bm, int mode, const char *kdev, bool doload)
+module_open(boot_module_t *bm, int mode, const char *kdev,
+    const char *base_path, bool doload)
 {
 	int fd;
 	const char *path;
 
 	/* check the expanded path first */
-	path = module_path(bm, kdev);
+	path = module_path(bm, kdev, base_path);
 	fd = open(path, mode);
 	if (fd != -1) {
 		if ((howto & AB_SILENT) == 0 && doload)
@@ -552,19 +593,9 @@ module_open(boot_module_t *bm, int mode,
 }
 
 static void
-module_init(const char *kernel_path)
+module_base_path(char *buf, size_t bufsize)
 {
-	struct bi_modulelist_entry *bi;
-	struct stat st;
 	const char *machine;
-	char kdev[64];
-	char *buf;
-	boot_module_t *bm;
-	ssize_t len;
-	off_t off;
-	int err, fd, nfail = 0;
-
-	extract_device(kernel_path, kdev, sizeof(kdev));
 
 	switch (netbsd_elf_class) {
 	case ELFCLASS32:
@@ -579,23 +610,39 @@ module_init(const char *kernel_path)
 	}
 	if (netbsd_version / 1000000 % 100 == 99) {
 		/* -current */
-		snprintf(module_base, sizeof(module_base),
+		snprintf(buf, bufsize,
 		    "/stand/%s/%d.%d.%d/modules", machine,
 		    netbsd_version / 100000000,
 		    netbsd_version / 1000000 % 100,
 		    netbsd_version / 100 % 100);
 	} else if (netbsd_version != 0) {
 		/* release */
-		snprintf(module_base, sizeof(module_base),
+		snprintf(buf, bufsize,
 		    "/stand/%s/%d.%d/modules", machine,
 		    netbsd_version / 100000000,
 		    netbsd_version / 1000000 % 100);
 	}
+}
+
+static void
+module_init(const char *kernel_path)
+{
+	struct bi_modulelist_entry *bi;
+	struct stat st;
+	char kdev[64];
+	char *buf;
+	boot_module_t *bm;
+	ssize_t len;
+	off_t off;
+	int err, fd, nfail = 0;
+
+	extract_device(kernel_path, kdev, sizeof(kdev));
+	module_base_path(module_base, sizeof(module_base));
 
 	/* First, see which modules are valid and calculate btinfo size */
 	len = sizeof(struct btinfo_modulelist);
 	for (bm = boot_modules; bm; bm = bm->bm_next) {
-		fd = module_open(bm, 0, kdev, false);
+		fd = module_open(bm, 0, kdev, module_base, false);
 		if (fd == -1) {
 			bm->bm_len = -1;
 			++nfail;
@@ -632,7 +679,7 @@ module_init(const char *kernel_path)
 	for (bm = boot_modules; bm; bm = bm->bm_next) {
 		if (bm->bm_len == -1)
 			continue;
-		fd = module_open(bm, 0, kdev, true);
+		fd = module_open(bm, 0, kdev, module_base, true);
 		if (fd == -1)
 			continue;
 		image_end = (image_end + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1);

Index: src/sys/arch/i386/stand/lib/libi386.h
diff -u src/sys/arch/i386/stand/lib/libi386.h:1.41 src/sys/arch/i386/stand/lib/libi386.h:1.42
--- src/sys/arch/i386/stand/lib/libi386.h:1.41	Tue Jan 24 11:09:14 2017
+++ src/sys/arch/i386/stand/lib/libi386.h	Sun Mar 12 05:33:48 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: libi386.h,v 1.41 2017/01/24 11:09:14 nonaka Exp $	*/
+/*	$NetBSD: libi386.h,v 1.42 2017/03/12 05:33:48 nonaka Exp $	*/
 
 /*
  * Copyright (c) 1996
@@ -43,6 +43,7 @@ void multiboot(physaddr_t, physaddr_t, p
 
 int exec_netbsd(const char *, physaddr_t, int, int, void (*)(void));
 int exec_multiboot(const char *, char *);
+int count_netbsd(const char *, u_long *);
 
 void delay(int);
 int getbasemem(void);

Reply via email to