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);