Module Name: src Committed By: nonaka Date: Tue Jan 24 11:09:15 UTC 2017
Modified Files: src/distrib/sets/lists/base: md.amd64 src/sys/arch/i386/stand: Makefile src/sys/arch/i386/stand/lib: biosdisk.c bootinfo_biosgeom.c diskbuf.c exec.c libi386.h vbe.c src/sys/arch/x86/acpi: acpi_machdep.c src/sys/arch/x86/include: bootinfo.h efi.h src/sys/arch/x86/x86: efi.c x86_machdep.c src/sys/lib/libgnuefi: Makefile Makefile.inc Added Files: src/sys/arch/i386/stand/efiboot: Makefile Makefile.efiboot boot.c conf.c devopen.c devopen.h efiboot.c efiboot.h eficons.c efidelay.c efidisk.c efidisk.h efidisk_ll.c efigetsecs.c efimemory.c panic.c self_reloc.c version src/sys/arch/i386/stand/efiboot/bootia32: Makefile efiboot_machdep.h efibootia32.c ldscript start.S src/sys/arch/i386/stand/efiboot/bootx64: Makefile efiboot_machdep.h efibootx64.c ldscript start.S startprog64.S src/sys/lib/libgnuefi/arch/i386: Makefile.inc src/sys/lib/libgnuefi/arch/x86_64: Makefile.inc Log Message: Initial commit of native amd64 EFI boot loader. To generate a diff of this commit: cvs rdiff -u -r1.267 -r1.268 src/distrib/sets/lists/base/md.amd64 cvs rdiff -u -r1.27 -r1.28 src/sys/arch/i386/stand/Makefile cvs rdiff -u -r0 -r1.1 src/sys/arch/i386/stand/efiboot/Makefile \ src/sys/arch/i386/stand/efiboot/Makefile.efiboot \ src/sys/arch/i386/stand/efiboot/boot.c \ src/sys/arch/i386/stand/efiboot/conf.c \ src/sys/arch/i386/stand/efiboot/devopen.c \ src/sys/arch/i386/stand/efiboot/devopen.h \ src/sys/arch/i386/stand/efiboot/efiboot.c \ src/sys/arch/i386/stand/efiboot/efiboot.h \ src/sys/arch/i386/stand/efiboot/eficons.c \ src/sys/arch/i386/stand/efiboot/efidelay.c \ src/sys/arch/i386/stand/efiboot/efidisk.c \ src/sys/arch/i386/stand/efiboot/efidisk.h \ src/sys/arch/i386/stand/efiboot/efidisk_ll.c \ src/sys/arch/i386/stand/efiboot/efigetsecs.c \ src/sys/arch/i386/stand/efiboot/efimemory.c \ src/sys/arch/i386/stand/efiboot/panic.c \ src/sys/arch/i386/stand/efiboot/self_reloc.c \ src/sys/arch/i386/stand/efiboot/version cvs rdiff -u -r0 -r1.1 src/sys/arch/i386/stand/efiboot/bootia32/Makefile \ src/sys/arch/i386/stand/efiboot/bootia32/efiboot_machdep.h \ src/sys/arch/i386/stand/efiboot/bootia32/efibootia32.c \ src/sys/arch/i386/stand/efiboot/bootia32/ldscript \ src/sys/arch/i386/stand/efiboot/bootia32/start.S cvs rdiff -u -r0 -r1.1 src/sys/arch/i386/stand/efiboot/bootx64/Makefile \ src/sys/arch/i386/stand/efiboot/bootx64/efiboot_machdep.h \ src/sys/arch/i386/stand/efiboot/bootx64/efibootx64.c \ src/sys/arch/i386/stand/efiboot/bootx64/ldscript \ src/sys/arch/i386/stand/efiboot/bootx64/start.S \ src/sys/arch/i386/stand/efiboot/bootx64/startprog64.S cvs rdiff -u -r1.45 -r1.46 src/sys/arch/i386/stand/lib/biosdisk.c cvs rdiff -u -r1.22 -r1.23 src/sys/arch/i386/stand/lib/bootinfo_biosgeom.c cvs rdiff -u -r1.6 -r1.7 src/sys/arch/i386/stand/lib/diskbuf.c cvs rdiff -u -r1.62 -r1.63 src/sys/arch/i386/stand/lib/exec.c cvs rdiff -u -r1.40 -r1.41 src/sys/arch/i386/stand/lib/libi386.h cvs rdiff -u -r1.8 -r1.9 src/sys/arch/i386/stand/lib/vbe.c cvs rdiff -u -r1.14 -r1.15 src/sys/arch/x86/acpi/acpi_machdep.c cvs rdiff -u -r1.24 -r1.25 src/sys/arch/x86/include/bootinfo.h cvs rdiff -u -r1.1 -r1.2 src/sys/arch/x86/include/efi.h cvs rdiff -u -r1.4 -r1.5 src/sys/arch/x86/x86/efi.c cvs rdiff -u -r1.81 -r1.82 src/sys/arch/x86/x86/x86_machdep.c cvs rdiff -u -r1.4 -r1.5 src/sys/lib/libgnuefi/Makefile cvs rdiff -u -r1.3 -r1.4 src/sys/lib/libgnuefi/Makefile.inc cvs rdiff -u -r0 -r1.1 src/sys/lib/libgnuefi/arch/i386/Makefile.inc cvs rdiff -u -r0 -r1.1 src/sys/lib/libgnuefi/arch/x86_64/Makefile.inc Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/distrib/sets/lists/base/md.amd64 diff -u src/distrib/sets/lists/base/md.amd64:1.267 src/distrib/sets/lists/base/md.amd64:1.268 --- src/distrib/sets/lists/base/md.amd64:1.267 Sat Sep 26 01:46:14 2015 +++ src/distrib/sets/lists/base/md.amd64 Tue Jan 24 11:09:14 2017 @@ -1,4 +1,4 @@ -# $NetBSD: md.amd64,v 1.267 2015/09/26 01:46:14 christos Exp $ +# $NetBSD: md.amd64,v 1.268 2017/01/24 11:09:14 nonaka Exp $ ./dev/lms0 base-obsolete obsolete ./dev/mms0 base-obsolete obsolete ./libexec/ld.elf_so-i386 base-sys-shlib compat,pic @@ -30,6 +30,8 @@ ./usr/mdec/biosboot_com0_57600.sym base-obsolete obsolete ./usr/mdec/biosboot_com0_9600.sym base-obsolete obsolete ./usr/mdec/boot base-sysutil-bin +./usr/mdec/bootia32.efi base-sysutil-bin +./usr/mdec/bootx64.efi base-sysutil-bin ./usr/mdec/bootxx_cd9660 base-sysutil-bin ./usr/mdec/bootxx_dosfs base-obsolete obsolete ./usr/mdec/bootxx_ext2fs base-sysutil-bin Index: src/sys/arch/i386/stand/Makefile diff -u src/sys/arch/i386/stand/Makefile:1.27 src/sys/arch/i386/stand/Makefile:1.28 --- src/sys/arch/i386/stand/Makefile:1.27 Fri Jan 27 08:41:35 2012 +++ src/sys/arch/i386/stand/Makefile Tue Jan 24 11:09:14 2017 @@ -1,8 +1,11 @@ -# $NetBSD: Makefile,v 1.27 2012/01/27 08:41:35 jnemeth Exp $ +# $NetBSD: Makefile,v 1.28 2017/01/24 11:09:14 nonaka Exp $ SUBDIR= mbr boot SUBDIR+= bootxx cdboot fatboot SUBDIR+= dosboot misc SUBDIR+= pxeboot +.if ${MACHINE} == "amd64" +SUBDIR+= efiboot +.endif .include <bsd.subdir.mk> Index: src/sys/arch/i386/stand/lib/biosdisk.c diff -u src/sys/arch/i386/stand/lib/biosdisk.c:1.45 src/sys/arch/i386/stand/lib/biosdisk.c:1.46 --- src/sys/arch/i386/stand/lib/biosdisk.c:1.45 Sun Jun 5 14:06:31 2016 +++ src/sys/arch/i386/stand/lib/biosdisk.c Tue Jan 24 11:09:14 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: biosdisk.c,v 1.45 2016/06/05 14:06:31 maxv Exp $ */ +/* $NetBSD: biosdisk.c,v 1.46 2017/01/24 11:09:14 nonaka Exp $ */ /* * Copyright (c) 1996, 1998 @@ -102,6 +102,13 @@ struct biosdisk { daddr_t offset; daddr_t size; int fstype; +#ifdef EFIBOOT + const struct gpt_part { + const struct uuid *guid; + const char *name; + } *guid; + uint64_t attr; +#endif } part[BIOSDISKNPART]; #endif }; @@ -111,6 +118,55 @@ const struct uuid GET_nbsd_raid = GPT_EN const struct uuid GET_nbsd_ffs = GPT_ENT_TYPE_NETBSD_FFS; const struct uuid GET_nbsd_lfs = GPT_ENT_TYPE_NETBSD_LFS; const struct uuid GET_nbsd_swap = GPT_ENT_TYPE_NETBSD_SWAP; +const struct uuid GET_nbsd_ccd = GPT_ENT_TYPE_NETBSD_CCD; +const struct uuid GET_nbsd_cgd = GPT_ENT_TYPE_NETBSD_CGD; +#ifdef EFIBOOT +const struct uuid GET_efi = GPT_ENT_TYPE_EFI; +const struct uuid GET_mbr = GPT_ENT_TYPE_MBR; +const struct uuid GET_fbsd = GPT_ENT_TYPE_FREEBSD; +const struct uuid GET_fbsd_swap = GPT_ENT_TYPE_FREEBSD_SWAP; +const struct uuid GET_fbsd_ufs = GPT_ENT_TYPE_FREEBSD_UFS; +const struct uuid GET_fbsd_vinum = GPT_ENT_TYPE_FREEBSD_VINUM; +const struct uuid GET_fbsd_zfs = GPT_ENT_TYPE_FREEBSD_ZFS; +const struct uuid GET_ms_rsvd = GPT_ENT_TYPE_MS_RESERVED; +const struct uuid GET_ms_basic_data = GPT_ENT_TYPE_MS_BASIC_DATA; +const struct uuid GET_ms_ldm_metadata = GPT_ENT_TYPE_MS_LDM_METADATA; +const struct uuid GET_ms_ldm_data = GPT_ENT_TYPE_MS_LDM_DATA; +const struct uuid GET_linux_data = GPT_ENT_TYPE_LINUX_DATA; +const struct uuid GET_linux_raid = GPT_ENT_TYPE_LINUX_RAID; +const struct uuid GET_linux_swap = GPT_ENT_TYPE_LINUX_SWAP; +const struct uuid GET_linux_lvm = GPT_ENT_TYPE_LINUX_LVM; +const struct uuid GET_apple_hfs = GPT_ENT_TYPE_APPLE_HFS; +const struct uuid GET_apple_ufs = GPT_ENT_TYPE_APPLE_UFS; +const struct uuid GET_bios = GPT_ENT_TYPE_BIOS; + +const struct gpt_part gpt_parts[] = { + { &GET_nbsd_raid, "NetBSD RAID" }, + { &GET_nbsd_ffs, "NetBSD FFS" }, + { &GET_nbsd_lfs, "NetBSD LFS" }, + { &GET_nbsd_swap, "NetBSD Swap" }, + { &GET_nbsd_ccd, "NetBSD ccd" }, + { &GET_nbsd_cgd, "NetBSD cgd" }, + { &GET_efi, "EFI System" }, + { &GET_mbr, "MBR" }, + { &GET_fbsd, "FreeBSD" }, + { &GET_fbsd_swap, "FreeBSD Swap" }, + { &GET_fbsd_ufs, "FreeBSD UFS" }, + { &GET_fbsd_vinum, "FreeBSD Vinum" }, + { &GET_fbsd_zfs, "FreeBSD ZFS" }, + { &GET_ms_rsvd, "Microsoft Reserved" }, + { &GET_ms_basic_data, "Microsoft Basic data" }, + { &GET_ms_ldm_metadata, "Microsoft LDM metadata" }, + { &GET_ms_ldm_data, "Microsoft LDM data" }, + { &GET_linux_data, "Linux data" }, + { &GET_linux_raid, "Linux RAID" }, + { &GET_linux_swap, "Linux Swap" }, + { &GET_linux_lvm, "Linux LVM" }, + { &GET_apple_hfs, "Apple HFS" }, + { &GET_apple_ufs, "Apple UFS" }, + { &GET_bios, "BIOS Boot (GRUB)" }, +}; +#endif #endif /* NO_GPT */ #ifdef _STANDALONE @@ -273,7 +329,7 @@ check_gpt(struct biosdisk *d, daddr_t se entblk += sectors; crc = crc32(crc, (const void *)d->buf, size); - for (i = 0; j < BIOSDISKNPART && i < entries; i++, j++) { + for (i = 0; j < BIOSDISKNPART && i < entries; i++) { u = (const struct uuid *)ep[i].ent_type; if (!guid_is_nil(u)) { d->part[j].offset = ep[i].ent_lba_start; @@ -287,8 +343,22 @@ check_gpt(struct biosdisk *d, daddr_t se d->part[j].fstype = FS_RAID; else if (guid_is_equal(u, &GET_nbsd_swap)) d->part[j].fstype = FS_SWAP; + else if (guid_is_equal(u, &GET_nbsd_ccd)) + d->part[j].fstype = FS_CCD; + else if (guid_is_equal(u, &GET_nbsd_cgd)) + d->part[j].fstype = FS_CGD; else d->part[j].fstype = FS_OTHER; +#ifdef EFIBOOT + for (int k = 0; + k < __arraycount(gpt_parts); + k++) { + if (guid_is_equal(u, gpt_parts[k].guid)) + d->part[j].guid = &gpt_parts[k]; + } + d->part[j].attr = ep[i].ent_attr; +#endif + j++; } } @@ -649,6 +719,11 @@ biosdisk_probe(void) first = 0; } printf(" hd%d%c(", d.ll.dev & 0x7f, part + 'a'); +#ifdef EFIBOOT + if (d.part[part].guid != NULL) + printf("%s", d.part[part].guid->name); + else +#endif if (d.part[part].fstype < FSMAXTYPES) printf("%s", fstypenames[d.part[part].fstype]); @@ -674,6 +749,10 @@ biosdisk_findpartition(int biosdev, dadd #else struct biosdisk *d; int partition = 0; +#ifdef EFIBOOT + int candidate = 0; +#endif + #ifdef DISK_DEBUG printf("looking for partition device %x, sector %"PRId64"\n", biosdev, sector); #endif @@ -687,9 +766,31 @@ biosdisk_findpartition(int biosdev, dadd for (partition = (BIOSDISKNPART-1); --partition;) { if (d->part[partition].fstype == FS_UNUSED) continue; +#ifdef EFIBOOT + if (d->part[partition].attr & GPT_ENT_ATTR_BOOTME) { + switch (d->part[partition].fstype) { + case FS_BSDFFS: + case FS_BSDLFS: + case FS_RAID: + case FS_CCD: + case FS_CGD: + break; + + default: + candidate = partition; + continue; + } + break; + } +#else if (d->part[partition].offset == sector) break; +#endif } +#ifdef EFIBOOT + if (partition == 0 && candidate != 0) + partition = candidate; +#endif } dealloc(d, sizeof(*d)); Index: src/sys/arch/i386/stand/lib/bootinfo_biosgeom.c diff -u src/sys/arch/i386/stand/lib/bootinfo_biosgeom.c:1.22 src/sys/arch/i386/stand/lib/bootinfo_biosgeom.c:1.23 --- src/sys/arch/i386/stand/lib/bootinfo_biosgeom.c:1.22 Thu May 16 19:06:44 2013 +++ src/sys/arch/i386/stand/lib/bootinfo_biosgeom.c Tue Jan 24 11:09:14 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: bootinfo_biosgeom.c,v 1.22 2013/05/16 19:06:44 christos Exp $ */ +/* $NetBSD: bootinfo_biosgeom.c,v 1.23 2017/01/24 11:09:14 nonaka Exp $ */ /* * Copyright (c) 1997 @@ -78,7 +78,6 @@ bi_getbiosgeom(void) return; for (i = nvalid = 0; i < MAX_BIOSDISKS && nvalid < nhd; i++) { - d.dev = 0x80 + i; if (set_geometry(&d, &ed)) Index: src/sys/arch/i386/stand/lib/diskbuf.c diff -u src/sys/arch/i386/stand/lib/diskbuf.c:1.6 src/sys/arch/i386/stand/lib/diskbuf.c:1.7 --- src/sys/arch/i386/stand/lib/diskbuf.c:1.6 Sun Dec 11 12:17:48 2005 +++ src/sys/arch/i386/stand/lib/diskbuf.c Tue Jan 24 11:09:14 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: diskbuf.c,v 1.6 2005/12/11 12:17:48 christos Exp $ */ +/* $NetBSD: diskbuf.c,v 1.7 2017/01/24 11:09:14 nonaka Exp $ */ /* * Copyright (c) 1996 @@ -28,6 +28,8 @@ /* data buffer for BIOS disk / DOS I/O */ +#include <sys/inttypes.h> + #include <lib/libsa/stand.h> #include "diskbuf.h" @@ -48,10 +50,12 @@ alloc_diskbuf(const void *user) diskbuf_user = user; if (!diskbufp) { diskbufp = alloc(DISKBUFSIZE); - if (((int)diskbufp & 0xffff) + DISKBUFSIZE > 0x10000) { - printf("diskbufp %x\n", (unsigned)diskbufp); +#ifndef EFIBOOT + if (((uintptr_t)diskbufp & 0xffff) + DISKBUFSIZE > 0x10000) { + printf("diskbufp %" PRIxPTR "\n", (uintptr_t)diskbufp); panic("diskbuf crosses 64k boundary"); } +#endif } return diskbufp; } Index: src/sys/arch/i386/stand/lib/exec.c diff -u src/sys/arch/i386/stand/lib/exec.c:1.62 src/sys/arch/i386/stand/lib/exec.c:1.63 --- src/sys/arch/i386/stand/lib/exec.c:1.62 Sun Dec 4 08:21:08 2016 +++ src/sys/arch/i386/stand/lib/exec.c Tue Jan 24 11:09:14 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: exec.c,v 1.62 2016/12/04 08:21:08 maxv Exp $ */ +/* $NetBSD: exec.c,v 1.63 2017/01/24 11:09:14 nonaka Exp $ */ /* * Copyright (c) 2008, 2009 The NetBSD Foundation, Inc. @@ -109,6 +109,11 @@ #ifdef SUPPORT_PS2 #include "biosmca.h" #endif +#ifdef EFIBOOT +#include "efiboot.h" +#undef DEBUG /* XXX */ +static u_long efi_loadaddr; +#endif #define BOOT_NARGS 6 @@ -295,6 +300,31 @@ 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 += 1 * 1024 * 1024; /* XXX: kernel size COUNT_KERNEL vs LOAD_KERNL (lacked some SYMTAB?) */ + 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) @@ -332,6 +362,15 @@ 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]; @@ -349,6 +388,7 @@ exec_netbsd(const char *file, physaddr_t struct btinfo_symtab btinfo_symtab; u_long extmem; u_long basemem; + int error; #ifdef DEBUG printf("exec: file=%s loadaddr=0x%lx\n", file ? file : "NULL", @@ -363,8 +403,12 @@ exec_netbsd(const char *file, physaddr_t memset(marks, 0, sizeof(marks)); - if (common_load_kernel(file, &basemem, &extmem, loadaddr, floppy, marks)) + error = common_load_kernel(file, &basemem, &extmem, loadaddr, floppy, + marks); + if (error) { + errno = error; goto out; + } boot_argv[0] = boothowto; boot_argv[1] = 0; @@ -404,6 +448,12 @@ exec_netbsd(const char *file, physaddr_t if (callback != NULL) (*callback)(); +#ifdef EFIBOOT + /* Copy the kernel to original load address. */ + memmove((void *)marks[MARK_START], + (void *)(efi_loadaddr + marks[MARK_START]), + marks[MARK_END] - marks[MARK_START]); +#endif startprog(marks[MARK_ENTRY], BOOT_NARGS, boot_argv, x86_trunc_page(basemem * 1024)); panic("exec returned"); Index: src/sys/arch/i386/stand/lib/libi386.h diff -u src/sys/arch/i386/stand/lib/libi386.h:1.40 src/sys/arch/i386/stand/lib/libi386.h:1.41 --- src/sys/arch/i386/stand/lib/libi386.h:1.40 Sun Nov 24 17:20:00 2013 +++ src/sys/arch/i386/stand/lib/libi386.h Tue Jan 24 11:09:14 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: libi386.h,v 1.40 2013/11/24 17:20:00 jakllsch Exp $ */ +/* $NetBSD: libi386.h,v 1.41 2017/01/24 11:09:14 nonaka Exp $ */ /* * Copyright (c) 1996 @@ -26,6 +26,9 @@ * */ +#ifndef __I386_STAND_LIBI386_H__ +#define __I386_STAND_LIBI386_H__ + typedef unsigned long physaddr_t; /* this is in startup code */ @@ -144,3 +147,5 @@ void userconf_add(char *); struct btinfo_framebuffer; void framebuffer_configure(struct btinfo_framebuffer *); + +#endif /* __I386_STAND_LIBI386_H__ */ Index: src/sys/arch/i386/stand/lib/vbe.c diff -u src/sys/arch/i386/stand/lib/vbe.c:1.8 src/sys/arch/i386/stand/lib/vbe.c:1.9 --- src/sys/arch/i386/stand/lib/vbe.c:1.8 Fri May 31 15:11:07 2013 +++ src/sys/arch/i386/stand/lib/vbe.c Tue Jan 24 11:09:14 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: vbe.c,v 1.8 2013/05/31 15:11:07 tsutsui Exp $ */ +/* $NetBSD: vbe.c,v 1.9 2017/01/24 11:09:14 nonaka Exp $ */ /*- * Copyright (c) 2009 Jared D. McNeill <jmcne...@invisible.ca> @@ -145,6 +145,7 @@ vbe_set_mode(int modenum) for (i = 0; i < 256; i++) vbe_set_palette(&rasops_cmap[i * 3], i); + memset(&fb, 0, sizeof(fb)); fb.physaddr = (uint64_t)mi.PhysBasePtr & 0xffffffff; fb.width = mi.XResolution; fb.height = mi.YResolution; Index: src/sys/arch/x86/acpi/acpi_machdep.c diff -u src/sys/arch/x86/acpi/acpi_machdep.c:1.14 src/sys/arch/x86/acpi/acpi_machdep.c:1.15 --- src/sys/arch/x86/acpi/acpi_machdep.c:1.14 Sat Oct 15 16:46:14 2016 +++ src/sys/arch/x86/acpi/acpi_machdep.c Tue Jan 24 11:09:14 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: acpi_machdep.c,v 1.14 2016/10/15 16:46:14 jdolecek Exp $ */ +/* $NetBSD: acpi_machdep.c,v 1.15 2017/01/24 11:09:14 nonaka Exp $ */ /* * Copyright 2001 Wasabi Systems, Inc. @@ -40,7 +40,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: acpi_machdep.c,v 1.14 2016/10/15 16:46:14 jdolecek Exp $"); +__KERNEL_RCSID(0, "$NetBSD: acpi_machdep.c,v 1.15 2017/01/24 11:09:14 nonaka Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -366,30 +366,63 @@ acpi_md_ncpus(void) static bool acpi_md_mcfg_validate(uint64_t addr, int bus_start, int *bus_end) { - struct btinfo_memmap *bim; + union { + struct btinfo_common *common; + struct btinfo_memmap *bios; + struct btinfo_efimemmap *efi; + } bim; uint64_t size, mapaddr, mapsize; uint32_t type; - int i, n; + int i, n, num; + bool efimemmap; - bim = lookup_bootinfo(BTINFO_MEMMAP); - if (bim == NULL) - return false; + bim.common = lookup_bootinfo(BTINFO_EFIMEMMAP); + if (bim.common == NULL) { + bim.common = lookup_bootinfo(BTINFO_MEMMAP); + if (bim.common == NULL) + return false; + } + efimemmap = bim.common->type == BTINFO_EFIMEMMAP; + num = efimemmap ? bim.efi->num : bim.bios->num; size = *bus_end - bus_start + 1; size *= ACPIMCFG_SIZE_PER_BUS; - for (i = 0; i < bim->num; i++) { - mapaddr = bim->entry[i].addr; - mapsize = bim->entry[i].size; - type = bim->entry[i].type; - - aprint_debug("MCFG: MEMMAP: 0x%016" PRIx64 "-0x%016" PRIx64 - ", size=0x%016" PRIx64 ", type=%d(%s)\n", - mapaddr, mapaddr + mapsize - 1, mapsize, type, - (type == BIM_Memory) ? "Memory" : - (type == BIM_Reserved) ? "Reserved" : - (type == BIM_ACPI) ? "ACPI" : - (type == BIM_NVS) ? "NVS" : - "unknown"); + for (i = 0; i < num; i++) { +#ifndef XEN + if (efimemmap) { + struct efi_md *md = (struct efi_md *) + (bim.efi->memmap + bim.efi->size * i); + mapaddr = md->md_phys; + mapsize = md->md_pages * EFI_PAGE_SIZE; + type = efi_getbiosmemtype(md->md_type, md->md_attr); + + aprint_debug("MCFG: MEMMAP: " + "p0x%016" PRIx64 "-0x%016" PRIx64 + ", v0x%016" PRIx64 "-0x%016" PRIx64 + ", size=0x%016" PRIx64 ", attr=0x%016" PRIx64 + ", type=%d(%s)\n", + mapaddr, mapaddr + mapsize - 1, + (uint64_t)(u_long)md->md_virt, + (uint64_t)(u_long)md->md_virt + mapsize - 1, + size, md->md_attr, md->md_type, + efi_getmemtype_str(md->md_type)); + } else +#endif + { + mapaddr = bim.bios->entry[i].addr; + mapsize = bim.bios->entry[i].size; + type = bim.bios->entry[i].type; + + aprint_debug("MCFG: MEMMAP: 0x%016" PRIx64 + "-0x%016" PRIx64 ", size=0x%016" PRIx64 + ", type=%d(%s)\n", + mapaddr, mapaddr + mapsize - 1, mapsize, type, + (type == BIM_Memory) ? "Memory" : + (type == BIM_Reserved) ? "Reserved" : + (type == BIM_ACPI) ? "ACPI" : + (type == BIM_NVS) ? "NVS" : + "unknown"); + } switch (type) { case BIM_ACPI: Index: src/sys/arch/x86/include/bootinfo.h diff -u src/sys/arch/x86/include/bootinfo.h:1.24 src/sys/arch/x86/include/bootinfo.h:1.25 --- src/sys/arch/x86/include/bootinfo.h:1.24 Thu Jan 28 01:09:56 2016 +++ src/sys/arch/x86/include/bootinfo.h Tue Jan 24 11:09:14 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: bootinfo.h,v 1.24 2016/01/28 01:09:56 christos Exp $ */ +/* $NetBSD: bootinfo.h,v 1.25 2017/01/24 11:09:14 nonaka Exp $ */ /* * Copyright (c) 1997 @@ -39,10 +39,11 @@ #define BTINFO_FRAMEBUFFER 12 #define BTINFO_USERCONFCOMMANDS 13 #define BTINFO_EFI 14 +#define BTINFO_EFIMEMMAP 15 #define BTINFO_STR "bootpath", "rootdevice", "bootdisk", "netif", \ "console", "biosgeom", "symtab", "memmap", "bootwedge", "modulelist", \ - "framebuffer", "userconfcommands", "efi", + "framebuffer", "userconfcommands", "efi", "efimemmap", #ifndef _LOCORE @@ -221,7 +222,18 @@ struct btinfo_userconfcommands { /* EFI Information */ struct btinfo_efi { struct btinfo_common common; - paddr_t bi_systbl; /* Physical address of the EFI System Table */ + uint64_t systblpa; /* Physical address of the EFI System Table */ + uint32_t flags; +#define BI_EFI_32BIT __BIT(0) /* 32bit UEFI */ + uint8_t reserved[12]; +}; + +struct btinfo_efimemmap { + struct btinfo_common common; + uint32_t num; /* number of memory descriptor */ + uint32_t version; /* version of memory descriptor */ + uint32_t size; /* size of memory descriptor */ + uint8_t memmap[1]; /* whole memory descriptors */ }; #endif /* _LOCORE */ Index: src/sys/arch/x86/include/efi.h diff -u src/sys/arch/x86/include/efi.h:1.1 src/sys/arch/x86/include/efi.h:1.2 --- src/sys/arch/x86/include/efi.h:1.1 Thu Jan 28 01:09:56 2016 +++ src/sys/arch/x86/include/efi.h Tue Jan 24 11:09:14 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: efi.h,v 1.1 2016/01/28 01:09:56 christos Exp $ */ +/* $NetBSD: efi.h,v 1.2 2017/01/24 11:09:14 nonaka Exp $ */ /*- * Copyright (c) 2004 Marcel Moolenaar @@ -56,7 +56,7 @@ typedef unsigned long efi_status; struct efi_cfgtbl { struct uuid ct_uuid; - uint64_t ct_data; + void *ct_data; }; struct efi_md { uint32_t md_type; @@ -143,17 +143,19 @@ struct efi_systbl { #define EFI_SYSTBL_SIG 0x5453595320494249UL efi_char *st_fwvendor; uint32_t st_fwrev; +#ifdef __amd64__ uint32_t __pad; +#endif void *st_cin; void *st_cinif; void *st_cout; void *st_coutif; void *st_cerr; void *st_cerrif; - uint64_t st_rt; + struct efi_rt *st_rt; void *st_bs; u_long st_entries; - uint64_t st_cfgtbl; + struct efi_cfgtbl *st_cfgtbl; }; bool efi_probe(void); @@ -161,6 +163,8 @@ paddr_t efi_getsystblpa(void) struct efi_systbl *efi_getsystbl(void); paddr_t efi_getcfgtblpa(const struct uuid*); void *efi_getcfgtbl(const struct uuid*); +int efi_getbiosmemtype(uint32_t, uint64_t); +const char *efi_getmemtype_str(uint32_t); /* void efi_boot_finish(void); int efi_boot_minimal(uint64_t); Index: src/sys/arch/x86/x86/efi.c diff -u src/sys/arch/x86/x86/efi.c:1.4 src/sys/arch/x86/x86/efi.c:1.5 --- src/sys/arch/x86/x86/efi.c:1.4 Wed Aug 24 10:27:23 2016 +++ src/sys/arch/x86/x86/efi.c Tue Jan 24 11:09:14 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: efi.c,v 1.4 2016/08/24 10:27:23 nonaka Exp $ */ +/* $NetBSD: efi.c,v 1.5 2017/01/24 11:09:14 nonaka Exp $ */ /*- * Copyright (c) 2016 The NetBSD Foundation, Inc. * All rights reserved. @@ -25,7 +25,7 @@ * POSSIBILITY OF SUCH DAMAGE. */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: efi.c,v 1.4 2016/08/24 10:27:23 nonaka Exp $"); +__KERNEL_RCSID(0, "$NetBSD: efi.c,v 1.5 2017/01/24 11:09:14 nonaka Exp $"); #include <sys/kmem.h> #include <sys/param.h> #include <sys/systm.h> @@ -62,6 +62,7 @@ void efi_aprintcfgtbl(void); void efi_aprintuuid(const struct uuid *); bool efi_uuideq(const struct uuid *, const struct uuid *); +static bool efi_is32bit = false; static struct efi_systbl *efi_systbl_va = NULL; static struct efi_cfgtbl *efi_cfgtblhead_va = NULL; @@ -173,7 +174,7 @@ efi_aprintcfgtbl(void) count = efi_systbl_va->st_entries; aprint_debug("efi: %lu cfgtbl entries:\n", count); for (; count; count--, ct++) { - aprint_debug("efi: %16" PRIx64 "", ct->ct_data); + aprint_debug("efi: %p", ct->ct_data); efi_aprintuuid(&ct->ct_uuid); aprint_debug("\n"); } @@ -226,7 +227,15 @@ efi_getsystblpa(void) /* Unable to locate the EFI System Table. */ return 0; } - pa = bi->bi_systbl; + if (bi->common.len > 16 && (bi->flags & BI_EFI_32BIT)) { + /* 32Bit UEFI */ + if (sizeof(paddr_t) == 4 && + (bi->systblpa & 0xffffffff00000000ULL)) + /* Unable to access EFI System Table. */ + return 0; + efi_is32bit = true; + } + pa = (paddr_t)bi->systblpa; return pa; } @@ -259,7 +268,7 @@ efi_getsystbl(void) * XXX Also print fwvendor, which is an UCS-2 string (use * some UTF-16 routine?) */ - aprint_debug("efi: runtime services at pa %" PRIx64 "\n", + aprint_debug("efi: runtime services at pa %p\n", systbl->st_rt); aprint_debug("efi: boot services at pa %p\n", systbl->st_bs); @@ -285,3 +294,58 @@ efi_probe(void) } return true; } + +int +efi_getbiosmemtype(uint32_t type, uint64_t attr) +{ + + switch (type) { + case EFI_MD_TYPE_CODE: + case EFI_MD_TYPE_DATA: + case EFI_MD_TYPE_BS_CODE: + case EFI_MD_TYPE_BS_DATA: + case EFI_MD_TYPE_FREE: + return (attr & EFI_MD_ATTR_WB) ? BIM_Memory : BIM_Reserved; + + case EFI_MD_TYPE_RECLAIM: + return BIM_ACPI; + + case EFI_MD_TYPE_FIRMWARE: + return BIM_NVS; + + case EFI_MD_TYPE_NULL: + case EFI_MD_TYPE_RT_CODE: + case EFI_MD_TYPE_RT_DATA: + case EFI_MD_TYPE_BAD: + case EFI_MD_TYPE_IOMEM: + case EFI_MD_TYPE_IOPORT: + case EFI_MD_TYPE_PALCODE: + return BIM_Reserved; + } + return BIM_Reserved; +} + +const char * +efi_getmemtype_str(uint32_t type) +{ + static const char *efimemtypes[] = { + "Reserved", + "LoaderCode", + "LoaderData", + "BootServicesCode", + "BootServicesData", + "RuntimeServicesCode", + "RuntimeServicesData", + "ConventionalMemory", + "UnusableMemory", + "ACPIReclaimMemory", + "ACPIMemoryNVS", + "MemoryMappedIO", + "MemoryMappedIOPortSpace", + "PalCode", + }; + + if (type < __arraycount(efimemtypes)) + return efimemtypes[type]; + return "unknown"; +} Index: src/sys/arch/x86/x86/x86_machdep.c diff -u src/sys/arch/x86/x86/x86_machdep.c:1.81 src/sys/arch/x86/x86/x86_machdep.c:1.82 --- src/sys/arch/x86/x86/x86_machdep.c:1.81 Tue Jan 10 09:48:22 2017 +++ src/sys/arch/x86/x86/x86_machdep.c Tue Jan 24 11:09:14 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: x86_machdep.c,v 1.81 2017/01/10 09:48:22 cherry Exp $ */ +/* $NetBSD: x86_machdep.c,v 1.82 2017/01/24 11:09:14 nonaka Exp $ */ /*- * Copyright (c) 2002, 2006, 2007 YAMAMOTO Takashi, @@ -31,7 +31,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: x86_machdep.c,v 1.81 2017/01/10 09:48:22 cherry Exp $"); +__KERNEL_RCSID(0, "$NetBSD: x86_machdep.c,v 1.82 2017/01/24 11:09:14 nonaka Exp $"); #include "opt_modular.h" #include "opt_physmem.h" @@ -54,6 +54,7 @@ __KERNEL_RCSID(0, "$NetBSD: x86_machdep. #include <x86/cpuvar.h> #include <x86/cputypes.h> +#include <x86/efi.h> #include <x86/machdep.h> #include <x86/nmi.h> #include <x86/pio.h> @@ -628,28 +629,63 @@ x86_add_cluster(struct extent *iomem_ex, } static int -x86_parse_clusters(struct btinfo_memmap *bim, struct extent *iomem_ex) +x86_parse_clusters(struct btinfo_common *bi, struct extent *iomem_ex) { + union { + struct btinfo_common *common; + struct btinfo_memmap *bios; + struct btinfo_efimemmap *efi; + } bim; uint64_t seg_start, seg_end; uint64_t addr, size; uint32_t type; - int x; + int x, num; + bool efimemmap; - KASSERT(bim != NULL); - KASSERT(bim->num > 0); + KASSERT(bi != NULL); + bim.common = bi; + efimemmap = bi->type == BTINFO_EFIMEMMAP; + num = efimemmap ? bim.efi->num : bim.bios->num; + KASSERT(num > 0); #ifdef DEBUG_MEMLOAD - printf("BIOS MEMORY MAP (%d ENTRIES):\n", bim->num); + printf("MEMMAP: %s MEMORY MAP (%d ENTRIES):\n", + efimemmap ? "UEFI" : "BIOS", num); #endif - for (x = 0; x < bim->num; x++) { - addr = bim->entry[x].addr; - size = bim->entry[x].size; - type = bim->entry[x].type; + for (x = 0; x < num; x++) { + if (efimemmap) { + struct efi_md *md = (struct efi_md *) + (bim.efi->memmap + bim.efi->size * x); + addr = md->md_phys; + size = md->md_pages * EFI_PAGE_SIZE; + type = efi_getbiosmemtype(md->md_type, md->md_attr); #ifdef DEBUG_MEMLOAD - printf(" addr 0x%"PRIx64" size 0x%"PRIx64" type 0x%x\n", - addr, size, type); + printf("MEMMAP: p0x%016" PRIx64 "-0x%016" PRIx64 + ", v0x%016" PRIx64 "-0x%016" PRIx64 + ", size=0x%016" PRIx64 ", attr=0x%016" PRIx64 + ", type=%d(%s)\n", + addr, addr + size - 1, + (uint64_t)md->md_virt, + (uint64_t)md->md_virt + size - 1, + size, md->md_attr, md->md_type, + efi_getmemtype_str(md->md_type)); #endif + } else { + addr = bim.bios->entry[x].addr; + size = bim.bios->entry[x].size; + type = bim.bios->entry[x].type; +#ifdef DEBUG_MEMLOAD + printf("MEMMAP: 0x%016" PRIx64 "-0x%016" PRIx64 + ", size=0x%016" PRIx64 ", type=%d(%s)\n", + addr, addr + size - 1, size, type, + (type == BIM_Memory) ? "Memory" : + (type == BIM_Reserved) ? "Reserved" : + (type == BIM_ACPI) ? "ACPI" : + (type == BIM_NVS) ? "NVS" : + "unknown"); +#endif + } /* If the segment is not memory, skip it. */ switch (type) { @@ -808,7 +844,8 @@ void init_x86_clusters(void) { extern struct extent *iomem_ex; - struct btinfo_memmap *bim; + struct btinfo_memmap *bim = NULL; + struct btinfo_efimemmap *biem; /* * Check to see if we have a memory map from the BIOS (passed to us by @@ -816,17 +853,23 @@ init_x86_clusters(void) */ #ifdef i386 extern int biosmem_implicit; - bim = lookup_bootinfo(BTINFO_MEMMAP); + biem = lookup_bootinfo(BTINFO_EFIMEMMAP); + if (biem == NULL) + bim = lookup_bootinfo(BTINFO_MEMMAP); if ((biosmem_implicit || (biosbasemem == 0 && biosextmem == 0)) && - bim != NULL && bim->num > 0) - x86_parse_clusters(bim, iomem_ex); + ((bim != NULL && bim->num > 0) || (biem != NULL && biem->num > 0))) + x86_parse_clusters(biem != NULL ? &biem->common : &bim->common, + iomem_ex); #else #if !defined(REALBASEMEM) && !defined(REALEXTMEM) - bim = lookup_bootinfo(BTINFO_MEMMAP); - if (bim != NULL && bim->num > 0) - x86_parse_clusters(bim, iomem_ex); + biem = lookup_bootinfo(BTINFO_EFIMEMMAP); + if (biem == NULL) + bim = lookup_bootinfo(BTINFO_MEMMAP); + if ((bim != NULL && bim->num > 0) || (biem != NULL && biem->num > 0)) + x86_parse_clusters(biem != NULL ? &biem->common : &bim->common, + iomem_ex); #else - (void)bim, (void)iomem_ex; + (void)bim, (void)biem, (void)iomem_ex; #endif #endif Index: src/sys/lib/libgnuefi/Makefile diff -u src/sys/lib/libgnuefi/Makefile:1.4 src/sys/lib/libgnuefi/Makefile:1.5 --- src/sys/lib/libgnuefi/Makefile:1.4 Tue Mar 22 08:25:23 2016 +++ src/sys/lib/libgnuefi/Makefile Tue Jan 24 11:09:14 2017 @@ -1,4 +1,4 @@ -# $NetBSD: Makefile,v 1.4 2016/03/22 08:25:23 mrg Exp $ +# $NetBSD: Makefile,v 1.5 2017/01/24 11:09:14 nonaka Exp $ LIB= gnuefi LIBISPRIVATE?= yes @@ -8,21 +8,47 @@ GNUEFI_INCLUDE_NET?= yes # Netboot via GNUEFI_USE_LOADFILE?= no # Generic executable loading support GNUEFI_ENABLE_LS_OP?= no # Filesystems ls operation +GNUEFIDIST= ${GNUEFIDIR}/../../external/bsd/gnu-efi/dist + CPPFLAGS= -I${GNUEFIDIR} ${GNUEFICPPFLAGS} ${GNUEFIMISCCPPFLAGS} -.if ${MACHINE_ARCH} == "i386" +.if defined(GNUEFI_EXTRADIR) +.-include "${GNUEFI_EXTRADIR}/Makefile.inc" +.endif + +.include <bsd.own.mk> + +LIBGNUEFI_ARCH?= ${MACHINE_ARCH} +LIBGNUEFI_CPU?= ${MACHINE_CPU} + +.if ${LIBGNUEFI_ARCH} == "i386" GNUEFIARCH=ia32 .else -GNUEFIARCH=${MACHINE_ARCH} +GNUEFIARCH=${LIBGNUEFI_ARCH} .endif -.if defined(GNUEFI_EXTRADIR) -.-include "${GNUEFI_EXTRADIR}/Makefile.inc" +.if defined(LIBGNUEFI_ARCH) && !empty(LIBGNUEFI_ARCH) && \ + exists(${GNUEFIDIR}/arch/${LIBGNUEFI_ARCH}) +ARCHSUBDIR= ${LIBGNUEFI_ARCH} +.elif defined(MACHINE_ARCH) && !empty(MACHINE_ARCH) && \ + exists(${GNUEFIDIR}/arch/${MACHINE_ARCH}) +ARCHSUBDIR= ${MACHINE_ARCH} +.elif defined(MACHINE_CPU) && !empty(MACHINE_CPU) && \ + exists(${GNUEFIDIR}/arch/${MACHINE_CPU}) +ARCHSUBDIR= ${MACHINE_CPU} .endif -.include <bsd.own.mk> +M= ${GNUEFIDIR}/arch/${ARCHSUBDIR} + +.if exists($M/Makefile.inc) +CPPFLAGS+= -I$M +.PATH.c: $M +.PATH.S: $M +.include "$M/Makefile.inc" +.endif -.PATH.c: ${GNUEFIDIR} ${GNUEFIDIR}/../../external/bsd/gnu-efi/dist/lib/${GNUEFIARCH} ${GNUEFIDIR}/../../external/bsd/gnu-efi/dist/lib ${GNUEFIDIR}/../../external/bsd/gnu-efi/dist/lib/runtime +.PATH.c: ${GNUEFIDIR} ${GNUEFIDIST}/lib/${GNUEFIARCH} ${GNUEFIDIST}/lib ${GNUEFIDIST}/lib/runtime +.PATH.S: ${GNUEFIDIR} ${GNUEFIDIST}/lib/${GNUEFIARCH} ${GNUEFIDIST}/lib ${GNUEFIDIST}/lib/runtime SRCS+= boxdraw.c smbios.c console.c crc.c data.c debug.c dpath.c \ error.c event.c guid.c hand.c hw.c init.c lock.c \ @@ -33,9 +59,11 @@ SRCS+= boxdraw.c smbios.c console.c crc. COPTS.boxdraw.c= -Wno-missing-field-initializers COPTS.guid.c= -Wno-missing-field-initializers COPTS.smbios.c= -Wno-int-to-pointer-cast -COPTS.dpath.c= -Wno-missing-prototypes +COPTS.dpath.c= -Wno-missing-prototypes -Wno-unused-but-set-variable COPTS.print.c= -Wno-missing-prototypes -COPTS.hw.c= -Wno-shadow +COPTS.hw.c= -Wno-shadow -Wno-unused-but-set-variable +COPTS.event.c= -Wno-unused-but-set-variable +COPTS.hand.c= -Wno-unused-but-set-variable .include <bsd.lib.mk> Index: src/sys/lib/libgnuefi/Makefile.inc diff -u src/sys/lib/libgnuefi/Makefile.inc:1.3 src/sys/lib/libgnuefi/Makefile.inc:1.4 --- src/sys/lib/libgnuefi/Makefile.inc:1.3 Tue Mar 22 08:25:23 2016 +++ src/sys/lib/libgnuefi/Makefile.inc Tue Jan 24 11:09:14 2017 @@ -1,4 +1,4 @@ -# $NetBSD: Makefile.inc,v 1.3 2016/03/22 08:25:23 mrg Exp $ +# $NetBSD: Makefile.inc,v 1.4 2017/01/24 11:09:14 nonaka Exp $ # # Configuration variables (default values are below): # @@ -47,6 +47,7 @@ GNUEFIMAKE= \ MACHINE=${MACHINE} MACHINE_ARCH=${MACHINE_ARCH:Q} \ GNUEFICPPFLAGS=${CPPFLAGS:S@^-I.@-I${GNUEFIDOTDIR}@g:Q} \ GNUEFIMISCCPPFLAGS=${GNUEFIMISCCPPFLAGS:Q} \ + LIBGNUEFI_ARCH=${LIBGNUEFI_ARCH:Q} \ ${GNUEFIMISCMAKEFLAGS} ${GNUEFILIB}: .NOTMAIN .MAKE __always_make_gnuefilib Added files: Index: src/sys/arch/i386/stand/efiboot/Makefile diff -u /dev/null src/sys/arch/i386/stand/efiboot/Makefile:1.1 --- /dev/null Tue Jan 24 11:09:15 2017 +++ src/sys/arch/i386/stand/efiboot/Makefile Tue Jan 24 11:09:14 2017 @@ -0,0 +1,6 @@ +# $NetBSD: Makefile,v 1.1 2017/01/24 11:09:14 nonaka Exp $ + +SUBDIR= bootx64 +SUBDIR+= bootia32 + +.include <bsd.subdir.mk> Index: src/sys/arch/i386/stand/efiboot/Makefile.efiboot diff -u /dev/null src/sys/arch/i386/stand/efiboot/Makefile.efiboot:1.1 --- /dev/null Tue Jan 24 11:09:15 2017 +++ src/sys/arch/i386/stand/efiboot/Makefile.efiboot Tue Jan 24 11:09:14 2017 @@ -0,0 +1,133 @@ +# $NetBSD: Makefile.efiboot,v 1.1 2017/01/24 11:09:14 nonaka Exp $ + +S= ${.CURDIR}/../../../../.. + +NOMAN= # defined +PROG?= boot.efi +NEWVERSWHAT?= "EFI Boot" +VERSIONFILE?= ${.CURDIR}/../version + +AFLAGS.start.S= ${${ACTIVE_CC} == "clang":?-no-integrated-as:} + +SOURCES?= start.S conf.c devopen.c efiboot.c self_reloc.c +LIBI386SRCS= boot.c biosdisk.c bootinfo.c bootinfo_biosgeom.c +LIBI386SRCS+= bootmenu.c boot_params.S diskbuf.c exec.c menuutils.c +LIBI386SRCS+= panic.c parseutils.c pread.c +LIBI386SRCS+= eficons.c efidelay.c efidisk.c efidisk_ll.c efigetsecs.c +LIBI386SRCS+= efimemory.c +SRCS= ${SOURCES} ${EXTRA_SOURCES} ${LIBI386SRCS} +.if !make(depend) +SRCS+= vers.c +.endif + +PIE_CFLAGS= +PIE_LDFLAGS= +PIE_AFLAGS= + +.include <bsd.own.mk> + +STRIPFLAG= # nothing + +LIBCRT0= # nothing +LIBCRTI= # nothing +LIBCRTBEGIN= # nothing +LIBCRTEND= # nothing +LIBC= # nothing + +BINDIR=/usr/mdec +BINMODE=444 + +.PATH: ${.CURDIR} ${.CURDIR}/.. +.PATH: ${.CURDIR}/../../lib + +LDSCRIPT?= ${.CURDIR}/ldscript +LDFLAGS+= -nostdlib -T${LDSCRIPT} -Bsymbolic -shared -nocombreloc +CPPFLAGS+= -I$S -I${.CURDIR} -I${.CURDIR}/.. -I$S/lib/libsa +CPPFLAGS+= -I${.OBJDIR} +CPPFLAGS+= -I${.CURDIR}/../../lib + +COPTS+= -ffreestanding -fPIC -fshort-wchar -fno-strict-aliasing -fno-builtin +COPTS+= -fno-stack-protector -falign-functions=16 +CPPFLAGS+= -nostdinc -D_STANDALONE +CPPFLAGS+= -DEFIBOOT + +CPPFLAGS+= -Wall -Wmissing-prototypes +CPPFLAGS+= -Wno-pointer-sign + +CPPFLAGS+= -DEFI_ALLOCATE_MAX_ADDRESS=0x100000000ULL +CPPFLAGS+= -DHEAP_VARIABLE +CPPFLAGS+= -DSUPPORT_CD9660 +CPPFLAGS+= -DSUPPORT_DOSFS +CPPFLAGS+= -DSUPPORT_EXT2FS +CPPFLAGS+= -DPASS_BIOSGEOM +CPPFLAGS+= -DPASS_MEMMAP +CPPFLAGS+= -DLIBSA_ENABLE_LS_OP + +EFIDIR= ${S}/external/bsd/gnu-efi/dist +GNUEFIARCH?= ${MACHINE_CPU} +CPPFLAGS+= -I${EFIDIR}/inc -I${EFIDIR}/inc/${GNUEFIARCH} +CPPFLAGS+= -I${EFIDIR}/inc/protocol + +SAMISCCPPFLAGS+= -DLIBSA_PRINTF_LONGLONG_SUPPORT +SAMISCCPPFLAGS+= -DLIBSA_PRINTF_WIDTH_SUPPORT +SAMISCMAKEFLAGS+= SA_USE_CREAD=yes # Read compressed kernels +SAMISCMAKEFLAGS+= SA_INCLUDE_NET=no # Netboot via TFTP, NFS + +### find out what to use for libsa +SA_AS= library +SAMISCMAKEFLAGS+="SA_USE_LOADFILE=yes" +SAMISCMAKEFLAGS+="SA_ENABLE_LS_OP=yes" +.include "${S}/lib/libsa/Makefile.inc" +LIBSA= ${SALIB} + +### find out what to use for libkern +KERN_AS= library +LIBKERN_ARCH?= ${MACHINE_ARCH} +KERNMISCMAKEFLAGS+="LIBKERN_ARCH=${LIBKERN_ARCH}" +.include "${S}/lib/libkern/Makefile.inc" +LIBKERN= ${KERNLIB} + +### find out what to use for libz +Z_AS= library +.include "${S}/lib/libz/Makefile.inc" +LIBZ= ${ZLIB} + +### find out what to use for libgnuefi +GNUEFI_AS= library +LIBGNUEFI_ARCH?= ${MACHINE_ARCH} +GNUEFIMISCMAKEFLAGS+="LIBGNUEFI_ARCH=${LIBGNUEFI_ARCH}" +GNUEFIMISCCPPFLAGS+= -I${EFIDIR}/lib +.include "${S}/lib/libgnuefi/Makefile.inc" +LIBGNUEFI= ${GNUEFILIB} + +cleandir distclean: .WAIT cleanlibdir + +cleanlibdir: + -rm -rf lib + +LIBLIST= ${LIBGNUEFI} ${LIBSA} ${LIBZ} ${LIBKERN} ${LIBSA} + +CLEANFILES+= vers.c + +vers.c: ${VERSIONFILE} ${SOURCES} ${LIBLIST} ${.CURDIR}/../Makefile.efiboot + ${HOST_SH} ${S}/conf/newvers_stand.sh ${VERSIONFILE} x86 ${NEWVERSWHAT} + +CLEANFILES+= ${PROG}.so ${PROG}.tmp + +${PROG}: ${PROG}.so + ${OBJCOPY} -j .text -j .sdata -j .data -j .dynamic -j .dynsym \ + -j .rel -j .rel.* -j .rela -j .rela.* -j .reloc \ + --subsystem efi-app --target=${OBJFMT} ${PROG}.so ${.TARGET} + +.include <bsd.prog.mk> + +${PROG}.so: ${OBJS} ${LIBLIST} ${LDSCRIPT} ${.CURDIR}/../Makefile.efiboot + ${LD} ${LDFLAGS} -o ${.TARGET}.tmp ${OBJS} ${LIBLIST} + @if ${OBJDUMP} -t ${.TARGET}.tmp | grep 'UND'; then \ + (echo Undefined symbols; false); \ + fi + rm -f ${.TARGET} + mv ${.TARGET}.tmp ${.TARGET} + +KLINK_MACHINE?= ${MACHINE} +.include <bsd.klinks.mk> Index: src/sys/arch/i386/stand/efiboot/boot.c diff -u /dev/null src/sys/arch/i386/stand/efiboot/boot.c:1.1 --- /dev/null Tue Jan 24 11:09:15 2017 +++ src/sys/arch/i386/stand/efiboot/boot.c Tue Jan 24 11:09:14 2017 @@ -0,0 +1,619 @@ +/* $NetBSD: boot.c,v 1.1 2017/01/24 11:09:14 nonaka Exp $ */ + +/*- + * Copyright (c) 2016 Kimihiro Nonaka <non...@netbsd.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "efiboot.h" + +#include <sys/bootblock.h> +#include <sys/boot_flag.h> + +#include <lib/libsa/bootcfg.h> + +#include <bootmod.h> +#include <bootmenu.h> +#include "devopen.h" + +int errno; +int boot_biosdev; +daddr_t boot_biossector; + +extern const char bootprog_name[], bootprog_rev[], bootprog_kernrev[]; + +extern struct x86_boot_params boot_params; +extern char twiddle_toggle; + +static const char * const names[][2] = { + { "netbsd", "netbsd.gz" }, + { "onetbsd", "onetbsd.gz" }, + { "netbsd.old", "netbsd.old.gz" }, +}; + +#define NUMNAMES __arraycount(names) +#define DEFFILENAME names[0][0] + +#define MAXDEVNAME 16 + +void command_help(char *); +void command_quit(char *); +void command_boot(char *); +void command_consdev(char *); +void command_dev(char *); +void command_devpath(char *); +void command_efivar(char *); +void command_gop(char *); +#if LIBSA_ENABLE_LS_OP +void command_ls(char *); +#endif +void command_memmap(char *); +#ifndef SMALL +void command_menu(char *); +#endif +void command_modules(char *); +void command_multiboot(char *); +void command_text(char *); +void command_version(char *); + +const struct bootblk_command commands[] = { + { "help", command_help }, + { "?", command_help }, + { "quit", command_quit }, + { "boot", command_boot }, + { "consdev", command_consdev }, + { "dev", command_dev }, + { "devpath", command_devpath }, + { "efivar", command_efivar }, + { "fs", fs_add }, + { "gop", command_gop }, + { "load", module_add }, +#if LIBSA_ENABLE_LS_OP + { "ls", command_ls }, +#endif + { "memmap", command_memmap }, +#ifndef SMALL + { "menu", command_menu }, +#endif + { "modules", command_modules }, + { "multiboot", command_multiboot }, + { "rndseed", rnd_add }, + { "splash", splash_add }, + { "text", command_text }, + { "userconf", userconf_add }, + { "version", command_version }, + { NULL, NULL }, +}; + +static char *default_devname; +static int default_unit, default_partition; +static const char *default_filename; + +static char *sprint_bootsel(const char *); +static void bootit(const char *, int); + +int +parsebootfile(const char *fname, char **fsname, char **devname, int *unit, + int *partition, const char **file) +{ + const char *col; + + *fsname = "ufs"; + *devname = default_devname; + *unit = default_unit; + *partition = default_partition; + *file = default_filename; + + if (fname == NULL) + return 0; + + if ((col = strchr(fname, ':')) != NULL) { /* device given */ + static char savedevname[MAXDEVNAME+1]; + int devlen; + int u = 0, p = 0; + int i = 0; + + devlen = col - fname; + if (devlen > MAXDEVNAME) + return EINVAL; + +#define isvalidname(c) ((c) >= 'a' && (c) <= 'z') + if (!isvalidname(fname[i])) + return EINVAL; + do { + savedevname[i] = fname[i]; + i++; + } while (isvalidname(fname[i])); + savedevname[i] = '\0'; + +#define isnum(c) ((c) >= '0' && (c) <= '9') + if (i < devlen) { + if (!isnum(fname[i])) + return EUNIT; + do { + u *= 10; + u += fname[i++] - '0'; + } while (isnum(fname[i])); + } + +#define isvalidpart(c) ((c) >= 'a' && (c) <= 'z') + if (i < devlen) { + if (!isvalidpart(fname[i])) + return EPART; + p = fname[i++] - 'a'; + } + + if (i != devlen) + return ENXIO; + + *devname = savedevname; + *unit = u; + *partition = p; + fname = col + 1; + } + + if (*fname) + *file = fname; + + return 0; +} + +static char * +sprint_bootsel(const char *filename) +{ + char *fsname, *devname; + int unit, partition; + const char *file; + static char buf[80]; + + if (parsebootfile(filename, &fsname, &devname, &unit, + &partition, &file) == 0) { + snprintf(buf, sizeof(buf), "%s%d%c:%s", devname, unit, + 'a' + partition, file); + return buf; + } + return "(invalid)"; +} + +void +clearit(void) +{ + + if (bootcfg_info.clear) + clear_pc_screen(); +} + +static void +bootit(const char *filename, int howto) +{ + + 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) + printf("boot: %s: %s\n", sprint_bootsel(filename), + strerror(errno)); + else + printf("boot returned\n"); +} + +void +print_banner(void) +{ + int n; + + clearit(); + if (bootcfg_info.banner[0]) { + for (n = 0; n < BOOTCFG_MAXBANNER && bootcfg_info.banner[n]; + n++) + printf("%s\n", bootcfg_info.banner[n]); + } else + command_version("short"); +} + +void +boot(void) +{ + int currname; + int c; + + boot_modules_enabled = !(boot_params.bp_flags & X86_BP_FLAGS_NOMODULES); + + /* try to set default device to what BIOS tells us */ + bios2dev(boot_biosdev, boot_biossector, &default_devname, &default_unit, + &default_partition); + + /* if the user types "boot" without filename */ + default_filename = DEFFILENAME; + + if (!(boot_params.bp_flags & X86_BP_FLAGS_NOBOOTCONF)) { + parsebootconf(BOOTCFG_FILENAME); + } else { + bootcfg_info.timeout = boot_params.bp_timeout; + } + + /* + * If console set in boot.cfg, switch to it. + * This will print the banner, so we don't need to explicitly do it + */ + if (bootcfg_info.consdev) + command_consdev(bootcfg_info.consdev); + else + print_banner(); + + /* Display the menu, if applicable */ + twiddle_toggle = 0; + if (bootcfg_info.nummenu > 0) { + /* Does not return */ + doboottypemenu(); + } + + printf("Press return to boot now, any other key for boot menu\n"); + for (currname = 0; currname < NUMNAMES; currname++) { + printf("booting %s - starting in ", + sprint_bootsel(names[currname][0])); + + c = awaitkey((bootcfg_info.timeout < 0) ? 0 + : bootcfg_info.timeout, 1); + if ((c != '\r') && (c != '\n') && (c != '\0')) { + if ((boot_params.bp_flags & X86_BP_FLAGS_PASSWORD) == 0) { + /* do NOT ask for password */ + bootmenu(); /* does not return */ + } else { + /* DO ask for password */ + if (check_password((char *)boot_params.bp_password)) { + /* password ok */ + printf("type \"?\" or \"help\" for help.\n"); + bootmenu(); /* does not return */ + } else { + /* bad password */ + printf("Wrong password.\n"); + currname = 0; + continue; + } + } + } + + /* + * try pairs of names[] entries, foo and foo.gz + */ + /* don't print "booting..." again */ + bootit(names[currname][0], 0); + /* since it failed, try compressed bootfile. */ + bootit(names[currname][1], AB_VERBOSE); + } + + bootmenu(); /* does not return */ +} + +/* ARGSUSED */ +void +command_help(char *arg) +{ + + printf("commands are:\n" + "boot [xdNx:][filename] [-12acdqsvxz]\n" + " (ex. \"hd0a:netbsd.old -s\"\n" + "dev [xd[N[x]]:]\n" + "consdev {pc|com[0123]|com[0123]kbd|auto}\n" + "devpath\n" + "efivar\n" + "gop [{modenum|list}]\n" + "load {path_to_module}\n" +#if LIBSA_ENABLE_LS_OP + "ls [path]\n" +#endif + "memmap [{sorted|unsorted}]\n" +#ifndef SMALL + "menu (reenters boot menu, if defined in boot.cfg)\n" +#endif + "modules {on|off|enabled|disabled}\n" + "multiboot [xdNx:][filename] [<args>]\n" + "rndseed {path_to_rndseed_file}\n" + "splash {path_to_image_file}\n" + "text [{modenum|list}]\n" + "userconf {command}\n" + "version\n" + "help|?\n" + "quit\n"); +} + +#if LIBSA_ENABLE_LS_OP +void +command_ls(char *arg) +{ + const char *save = default_filename; + + default_filename = "/"; + ls(arg); + default_filename = save; +} +#endif + +/* ARGSUSED */ +void +command_quit(char *arg) +{ + + printf("Exiting...\n"); + delay(1 * 1000 * 1000); + reboot(); + /* Note: we shouldn't get to this point! */ + panic("Could not reboot!"); +} + +void +command_boot(char *arg) +{ + char *filename; + int howto; + + if (!parseboot(arg, &filename, &howto)) + return; + + if (filename != NULL) { + bootit(filename, howto); + } else { + int i; + + if (howto == 0) + bootdefault(); + for (i = 0; i < NUMNAMES; i++) { + bootit(names[i][0], howto); + bootit(names[i][1], howto); + } + } +} + +void +command_dev(char *arg) +{ + static char savedevname[MAXDEVNAME + 1]; + char *fsname, *devname; + const char *file; /* dummy */ + + if (*arg == '\0') { + biosdisk_probe(); + printf("default %s%d%c\n", default_devname, default_unit, + 'a' + default_partition); + return; + } + + if (strchr(arg, ':') == NULL || + parsebootfile(arg, &fsname, &devname, &default_unit, + &default_partition, &file)) { + command_help(NULL); + return; + } + + /* put to own static storage */ + strncpy(savedevname, devname, MAXDEVNAME + 1); + default_devname = savedevname; +} + +/* ARGSUSED */ +void +command_consdev(char *arg) +{ + + /* XXX not implemented yet */ +} + +#ifndef SMALL +/* ARGSUSED */ +void +command_menu(char *arg) +{ + + if (bootcfg_info.nummenu > 0) { + /* Does not return */ + doboottypemenu(); + } else + printf("No menu defined in boot.cfg\n"); +} +#endif /* !SMALL */ + +void +command_modules(char *arg) +{ + + if (strcmp(arg, "enabled") == 0 || + strcmp(arg, "on") == 0) + boot_modules_enabled = true; + else if (strcmp(arg, "disabled") == 0 || + strcmp(arg, "off") == 0) + boot_modules_enabled = false; + else + printf("invalid flag, must be 'enabled' or 'disabled'.\n"); +} + +void +command_multiboot(char *arg) +{ + char *filename; + + filename = arg; + if (exec_multiboot(filename, gettrailer(arg)) < 0) + printf("multiboot: %s: %s\n", sprint_bootsel(filename), + strerror(errno)); + else + printf("boot returned\n"); +} + +void +command_version(char *arg) +{ + + if (strcmp(arg, "full") == 0) { + printf("ImageBase: 0x%" PRIxPTR "\n", + (uintptr_t)efi_li->ImageBase); + printf("Stack: 0x%" PRIxPTR "\n", efi_main_sp); + printf("EFI version: %d.%02d\n", + ST->Hdr.Revision >> 16, ST->Hdr.Revision & 0xffff); + Print(L"EFI Firmware: %s (rev %d.%02d)\n", ST->FirmwareVendor, + ST->FirmwareRevision >> 16, ST->FirmwareRevision & 0xffff); + } + + printf("\n" + ">> %s, Revision %s (from NetBSD %s)\n" + ">> Memory: %d/%d k\n", + bootprog_name, bootprog_rev, bootprog_kernrev, + getbasemem(), getextmem()); +} + +void +command_memmap(char *arg) +{ + bool sorted = true; + + if (*arg == '\0' || strcmp(arg, "sorted") == 0) + /* Already sorted is true. */; + else if (strcmp(arg, "unsorted") == 0) + sorted = false; + else { + printf("invalid flag, " + "must be 'sorted' or 'unsorted'.\n"); + return; + } + + efi_memory_show_map(sorted); +} + +void +command_devpath(char *arg) +{ + EFI_STATUS status; + UINTN i, nhandles; + EFI_HANDLE *handles; + EFI_DEVICE_PATH *dp0, *dp; + CHAR16 *path; + UINTN cols, rows, row = 0; + + status = uefi_call_wrapper(ST->ConOut->QueryMode, 4, ST->ConOut, + ST->ConOut->Mode->Mode, &cols, &rows); + if (EFI_ERROR(status) || rows <= 2) + rows = 0; + else + rows -= 2; + + /* + * all devices. + */ + status = LibLocateHandle(ByProtocol, &DevicePathProtocol, NULL, + &nhandles, &handles); + if (EFI_ERROR(status)) + return; + + for (i = 0; i < nhandles; i++) { + status = uefi_call_wrapper(BS->HandleProtocol, 3, handles[i], + &DevicePathProtocol, (void **)&dp0); + if (EFI_ERROR(status)) + break; + + Print(L"DevicePathType %d\n", DevicePathType(dp0)); + for (dp = dp0; + !IsDevicePathEnd(dp); + dp = NextDevicePathNode(dp)) { + path = DevicePathToStr(dp); + Print(L"%d:%d:%s\n", DevicePathType(dp), DevicePathSubType(dp), path); + FreePool(path); + + if (rows >= 0 && ++row >= rows) { + row = 0; + Print(L"Press Any Key to continue :"); + (void) awaitkey(-1, 0); + Print(L"\n"); + } + } + } +} + +void +command_efivar(char *arg) +{ + static const CHAR16 header[] = + L"GUID Variable Name Value\n" + L"=================================== ==================== ========\n"; + EFI_STATUS status; + UINTN sz = 64; + CHAR16 *name = NULL, *tmp, *val; + EFI_GUID vendor; + UINTN cols, rows, row = 0; + + status = uefi_call_wrapper(ST->ConOut->QueryMode, 4, ST->ConOut, + ST->ConOut->Mode->Mode, &cols, &rows); + if (EFI_ERROR(status) || rows <= 2) + rows = 0; + else + rows -= 2; + + name = AllocatePool(sz); + if (name == NULL) { + Print(L"memory allocation failed: %ld bytes\n", + (UINT64)sz); + return; + } + + name[0] = 0; + vendor = NullGuid; + + Print(L"%s", header); + for (;;) { + status = uefi_call_wrapper(RT->GetNextVariableName, 3, + &sz, name, &vendor); + if (EFI_ERROR(status)) { + if (status == EFI_NOT_FOUND) + break; + if (status != EFI_BUFFER_TOO_SMALL) { + Print(L"GetNextVariableName failed: %r\n", + status); + break; + } + + tmp = AllocatePool(sz); + if (tmp == NULL) { + Print(L"memory allocation failed: %ld bytes\n", + (UINT64)sz); + break; + } + FreePool(name); + name = tmp; + } + + val = LibGetVariable(name, &vendor); + Print(L"%.-35g %.-20s %s\n", &vendor, name, + val ? val : L"(null)"); + FreePool(val); + + if (rows >= 0 && ++row >= rows) { + row = 0; + Print(L"Press Any Key to continue :"); + (void) awaitkey(-1, 0); + Print(L"\n"); + } + } + + FreePool(name); +} Index: src/sys/arch/i386/stand/efiboot/conf.c diff -u /dev/null src/sys/arch/i386/stand/efiboot/conf.c:1.1 --- /dev/null Tue Jan 24 11:09:15 2017 +++ src/sys/arch/i386/stand/efiboot/conf.c Tue Jan 24 11:09:14 2017 @@ -0,0 +1,69 @@ +/* $NetBSD: conf.c,v 1.1 2017/01/24 11:09:14 nonaka Exp $ */ + +/* + * Copyright (c) 1997 + * Matthias Drochner. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/cdefs.h> +#include <sys/types.h> + +#include <lib/libsa/stand.h> +#include <lib/libsa/ufs.h> +#include <lib/libsa/lfs.h> +#ifdef SUPPORT_EXT2FS +#include <lib/libsa/ext2fs.h> +#endif +#ifdef SUPPORT_MINIXFS3 +#include <lib/libsa/minixfs3.h> +#endif +#ifdef SUPPORT_DOSFS +#include <lib/libsa/dosfs.h> +#endif +#ifdef SUPPORT_CD9660 +#include <lib/libsa/cd9660.h> +#endif +#include <biosdisk.h> + +struct devsw devsw[] = { + { "disk", biosdisk_strategy, biosdisk_open, biosdisk_close, biosdisk_ioctl }, +}; +int ndevs = __arraycount(devsw); + +struct fs_ops file_system[] = { +#ifdef SUPPORT_CD9660 + FS_OPS(cd9660), +#endif + FS_OPS(ffsv1), FS_OPS(ffsv2), + FS_OPS(lfsv1), FS_OPS(lfsv2), +#ifdef SUPPORT_EXT2FS + FS_OPS(ext2fs), +#endif +#ifdef SUPPORT_MINIXFS3 + FS_OPS(minixfs3), +#endif +#ifdef SUPPORT_DOSFS + FS_OPS(dosfs), +#endif +}; +int nfsys = __arraycount(file_system); Index: src/sys/arch/i386/stand/efiboot/devopen.c diff -u /dev/null src/sys/arch/i386/stand/efiboot/devopen.c:1.1 --- /dev/null Tue Jan 24 11:09:15 2017 +++ src/sys/arch/i386/stand/efiboot/devopen.c Tue Jan 24 11:09:14 2017 @@ -0,0 +1,110 @@ +/* $NetBSD: devopen.c,v 1.1 2017/01/24 11:09:14 nonaka Exp $ */ + +/*- + * Copyright (c) 2005 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Bang Jun-Young. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Copyright (c) 1996, 1997 + * Matthias Drochner. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "efiboot.h" + +#include <biosdisk.h> +#include "devopen.h" +#include <bootinfo.h> + +static int +dev2bios(char *devname, int unit, int *biosdev) +{ + + if (strcmp(devname, "hd") == 0) + *biosdev = 0x80 + unit; + else + return ENXIO; + return 0; +} + +void +bios2dev(int biosdev, daddr_t sector, char **devname, int *unit, int *partition) +{ + + *unit = biosdev & 0x7f; + *devname = "hd"; + *partition = biosdisk_findpartition(biosdev, sector); +} + +struct btinfo_bootpath bibp; +extern bool kernel_loaded; + +/* + * Open the EFI disk device + */ +int +devopen(struct open_file *f, const char *fname, char **file) +{ + char *fsname, *devname; + int unit, partition; + int biosdev; + int error; + + if ((error = parsebootfile(fname, &fsname, &devname, + &unit, &partition, (const char **) file)) + || (error = dev2bios(devname, unit, &biosdev))) + return error; + + f->f_dev = &devsw[0]; /* must be biosdisk */ + + if (!kernel_loaded) { + strncpy(bibp.bootpath, *file, sizeof(bibp.bootpath)); + BI_ADD(&bibp, BTINFO_BOOTPATH, sizeof(bibp)); + } + + return biosdisk_open(f, biosdev, partition); +} Index: src/sys/arch/i386/stand/efiboot/devopen.h diff -u /dev/null src/sys/arch/i386/stand/efiboot/devopen.h:1.1 --- /dev/null Tue Jan 24 11:09:15 2017 +++ src/sys/arch/i386/stand/efiboot/devopen.h Tue Jan 24 11:09:14 2017 @@ -0,0 +1,31 @@ +/* $NetBSD: devopen.h,v 1.1 2017/01/24 11:09:14 nonaka Exp $ */ + +/*- + * Copyright (c) 2016 Kimihiro Nonaka <non...@netbsd.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +extern int boot_biosdev; + +void bios2dev(int, daddr_t, char **, int *, int *); Index: src/sys/arch/i386/stand/efiboot/efiboot.c diff -u /dev/null src/sys/arch/i386/stand/efiboot/efiboot.c:1.1 --- /dev/null Tue Jan 24 11:09:15 2017 +++ src/sys/arch/i386/stand/efiboot/efiboot.c Tue Jan 24 11:09:14 2017 @@ -0,0 +1,137 @@ +/* $NetBSD: efiboot.c,v 1.1 2017/01/24 11:09:14 nonaka Exp $ */ + +/*- + * Copyright (c) 2016 Kimihiro Nonaka <non...@netbsd.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "efiboot.h" + +#include "bootinfo.h" +#include "devopen.h" + +EFI_HANDLE IH; +EFI_DEVICE_PATH *efi_bootdp; +EFI_LOADED_IMAGE *efi_li; +uintptr_t efi_main_sp; + +static EFI_PHYSICAL_ADDRESS heap_start = EFI_ALLOCATE_MAX_ADDRESS; +static UINTN heap_size = 1 * 1024 * 1024; /* 1MB */ +static struct btinfo_efi btinfo_efi; + +static void efi_heap_init(void); + +EFI_STATUS EFIAPI efi_main(EFI_HANDLE, EFI_SYSTEM_TABLE *); +EFI_STATUS EFIAPI +efi_main(EFI_HANDLE imageHandle, EFI_SYSTEM_TABLE *systemTable) +{ + EFI_STATUS status; + EFI_DEVICE_PATH *dp0, *dp; + extern char twiddle_toggle; + + IH = imageHandle; + InitializeLib(IH, systemTable); + + efi_main_sp = (uintptr_t)&status; + twiddle_toggle = 1; /* no twiddling until we're ready */ + + cninit(); + efi_heap_init(); + efi_md_init(); + + status = uefi_call_wrapper(BS->HandleProtocol, 3, IH, + &LoadedImageProtocol, (void **)&efi_li); + if (EFI_ERROR(status)) + Panic(L"HandleProtocol(LoadedImageProtocol): %r", status); + status = uefi_call_wrapper(BS->HandleProtocol, 3, efi_li->DeviceHandle, + &DevicePathProtocol, (void **)&dp0); + if (EFI_ERROR(status)) + Panic(L"HandleProtocol(DevicePathProtocol): %r", status); + for (dp = dp0; !IsDevicePathEnd(dp); dp = NextDevicePathNode(dp)) { + if (DevicePathType(dp) == MEDIA_DEVICE_PATH) + continue; + if (DevicePathSubType(dp) == MEDIA_HARDDRIVE_DP) { + boot_biosdev = 0x80; + efi_bootdp = dp; + break; + } + break; + } + + efi_disk_probe(); + + status = uefi_call_wrapper(BS->SetWatchdogTimer, 4, 0, 0, 0, NULL); + if (EFI_ERROR(status)) + Panic(L"SetWatchdogTimer: %r", status); + + boot(); + + return EFI_SUCCESS; +} + +void +efi_cleanup(void) +{ + EFI_STATUS status; + EFI_MEMORY_DESCRIPTOR *desc; + UINTN NoEntries, MapKey, DescriptorSize; + UINT32 DescriptorVersion; + + clearit(); + + memset(&btinfo_efi, 0, sizeof(btinfo_efi)); + btinfo_efi.systblpa = (intptr_t)ST; +#ifdef __i386__ /* bootia32.efi */ + btinfo_efi.flags |= BI_EFI_32BIT; +#endif + BI_ADD(&btinfo_efi, BTINFO_EFI, sizeof(btinfo_efi)); + + NoEntries = 0; + desc = LibMemoryMap(&NoEntries, &MapKey, &DescriptorSize, + &DescriptorVersion); + status = uefi_call_wrapper(BS->ExitBootServices, 2, IH, MapKey); + if (EFI_ERROR(status)) { + FreePool(desc); + desc = LibMemoryMap(&NoEntries, &MapKey, &DescriptorSize, + &DescriptorVersion); + status = uefi_call_wrapper(BS->ExitBootServices, 2, IH, MapKey); + if (EFI_ERROR(status)) + Panic(L"ExitBootServices failed"); + } +} + +static void +efi_heap_init(void) +{ + EFI_STATUS status; + u_int sz = EFI_SIZE_TO_PAGES(heap_size); + + status = uefi_call_wrapper(BS->AllocatePages, 4, AllocateMaxAddress, + EfiLoaderData, sz, &heap_start); + if (EFI_ERROR(status)) + Panic(L"%a: AllocatePages() failed: %d page(s): %r", + __func__, sz, status); + setheap((void *)(UINTN)heap_start, + (void *)(UINTN)(heap_start + heap_size)); +} Index: src/sys/arch/i386/stand/efiboot/efiboot.h diff -u /dev/null src/sys/arch/i386/stand/efiboot/efiboot.h:1.1 --- /dev/null Tue Jan 24 11:09:15 2017 +++ src/sys/arch/i386/stand/efiboot/efiboot.h Tue Jan 24 11:09:14 2017 @@ -0,0 +1,66 @@ +/* $NetBSD: efiboot.h,v 1.1 2017/01/24 11:09:14 nonaka Exp $ */ + +/*- + * Copyright (c) 2016 Kimihiro Nonaka <non...@netbsd.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <efi.h> +#include <efilib.h> + +#include <lib/libsa/stand.h> +#include <lib/libkern/libkern.h> + +#include "libi386.h" + +#include "efiboot_machdep.h" + +extern EFI_GUID GraphicsOutputProtocol; + +/* boot.c */ +void boot(void); +void clearit(void); +void print_banner(void); + +/* efiboot.c */ +extern EFI_HANDLE IH; +extern EFI_DEVICE_PATH *efi_bootdp; +extern EFI_LOADED_IMAGE *efi_li; +extern uintptr_t efi_main_sp; +void efi_cleanup(void); + +/* eficons.c */ +int cninit(void); +void command_text(char *); +void command_gop(char *); + +/* efidisk.c */ +void efi_disk_probe(void); + +/* efimemory.c */ +void efi_memory_probe(void); +void efi_memory_show_map(bool); + +/* panic.c */ +__dead VOID Panic(IN CHAR16 *, ...); Index: src/sys/arch/i386/stand/efiboot/eficons.c diff -u /dev/null src/sys/arch/i386/stand/efiboot/eficons.c:1.1 --- /dev/null Tue Jan 24 11:09:15 2017 +++ src/sys/arch/i386/stand/efiboot/eficons.c Tue Jan 24 11:09:14 2017 @@ -0,0 +1,557 @@ +/* $NetBSD: eficons.c,v 1.1 2017/01/24 11:09:14 nonaka Exp $ */ + +/*- + * Copyright (c) 2016 Kimihiro Nonaka <non...@netbsd.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <sys/bitops.h> +#include <sys/stdint.h> + +#include "efiboot.h" + +#include "bootinfo.h" +#include "vbe.h" + +struct btinfo_console btinfo_console; + +static EFI_GRAPHICS_OUTPUT_PROTOCOL *efi_gop; +static int efi_gop_mode = -1; + +static CHAR16 keybuf[16]; +static int keybuf_read = 0; +static int keybuf_write = 0; + +static void eficons_init_video(void); +static void efi_switch_video_to_text_mode(void); + +int +cninit(void) +{ + + efi_switch_video_to_text_mode(); + eficons_init_video(); + + /* XXX serial console */ + btinfo_console.devname[0] = 'p'; + btinfo_console.devname[1] = 'c'; + btinfo_console.devname[2] = 0; + + return 0; +} + +int +getchar(void) +{ + EFI_STATUS status; + EFI_INPUT_KEY key; + int c; + + if (keybuf_read != keybuf_write) { + c = keybuf[keybuf_read]; + keybuf_read = (keybuf_read + 1) % __arraycount(keybuf); + return c; + } + + status = uefi_call_wrapper(ST->ConIn->ReadKeyStroke, 2, ST->ConIn, + &key); + while (status == EFI_NOT_READY) { + WaitForSingleEvent(ST->ConIn->WaitForKey, 0); + status = uefi_call_wrapper(ST->ConIn->ReadKeyStroke, 2, + ST->ConIn, &key); + } + return key.UnicodeChar; +} + +void +putchar(int c) +{ + CHAR16 buf[2]; + + buf[1] = 0; + if (c == '\n') { + buf[0] = '\r'; + Output(buf); + } + buf[0] = c; + Output(buf); +} + +/*ARGSUSED*/ +int +iskey(int intr) +{ + EFI_STATUS status; + EFI_INPUT_KEY key; + + if (keybuf_read != keybuf_write) + return 1; + + status = uefi_call_wrapper(ST->ConIn->ReadKeyStroke, 2, ST->ConIn, + &key); + if (EFI_ERROR(status)) + return 0; + + keybuf[keybuf_write] = key.UnicodeChar; + keybuf_write = (keybuf_write + 1) % __arraycount(keybuf); + return 1; +} + +char +awaitkey(int timeout, int tell) +{ + char c = 0; + + for (;;) { + if (tell) { + char numbuf[32]; + int len; + + len = snprintf(numbuf, sizeof(numbuf), "%d seconds. ", + timeout); + if (len > 0 && len < sizeof(numbuf)) { + char *p = numbuf; + + printf("%s", numbuf); + while (*p) + *p++ = '\b'; + printf("%s", numbuf); + } + } + if (iskey(1)) { + /* flush input buffer */ + while (iskey(0)) + c = getchar(); + if (c == 0) + c = -1; + goto out; + } + if (timeout--) + WaitForSingleEvent(ST->ConIn->WaitForKey, 10000000); + else + break; + } + +out: + if (tell) + printf("0 seconds. \n"); + + return c; +} + +void +clear_pc_screen(void) +{ + + uefi_call_wrapper(ST->ConOut->ClearScreen, 1, ST->ConOut); +} + +static uint8_t +getdepth(const EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *info) +{ + + switch (info->PixelFormat) { + case PixelBlueGreenRedReserved8BitPerColor: + case PixelRedGreenBlueReserved8BitPerColor: + return 32; + + case PixelBitMask: + return fls32(info->PixelInformation.RedMask + | info->PixelInformation.GreenMask + | info->PixelInformation.BlueMask + | info->PixelInformation.ReservedMask); + + case PixelBltOnly: + case PixelFormatMax: + return 0; + } + return 0; +} + +static void +setpixelformat(UINT32 mask, uint8_t *num, uint8_t *pos) +{ + uint8_t n, p; + + n = popcount32(mask); + p = ffs32(mask); + if (p > 0) + p--; + + *num = n; + *pos = p; +} + +static void +bi_framebuffer(void) +{ + EFI_STATUS status; + EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *info; + struct btinfo_framebuffer fb; + UINT64 res, bestres = 0; + UINTN sz; + UINT32 i; + INT32 bestmode = -1; + + if (efi_gop == NULL) { + framebuffer_configure(NULL); + return; + } + + if (efi_gop_mode >= 0) { + bestmode = efi_gop_mode; + } else { + /* XXX EDID? EFI_EDID_DISCOVERD_PROTOCOL */ + for (i = 0; i < efi_gop->Mode->MaxMode; i++) { + status = uefi_call_wrapper(efi_gop->QueryMode, 4, + efi_gop, i, &sz, &info); + if (EFI_ERROR(status)) + continue; + + res = (UINT64)info->HorizontalResolution * + (UINT64)info->VerticalResolution * + (UINT64)getdepth(info); + if (res > bestres) { + bestmode = i; + bestres = res; + } + } + } + if (bestmode >= 0) { + status = uefi_call_wrapper(efi_gop->SetMode, 2, efi_gop, + bestmode); + if (EFI_ERROR(status) || efi_gop->Mode->Mode != bestmode) + Print(L"GOP setmode failed: %r\n", status); + } + + info = efi_gop->Mode->Info; + memset(&fb, 0, sizeof(fb)); + fb.physaddr = efi_gop->Mode->FrameBufferBase; + fb.flags = 0; + fb.width = info->HorizontalResolution; + fb.height = info->VerticalResolution; + fb.depth = getdepth(info); + fb.stride = info->PixelsPerScanLine * ((fb.depth + 7) / 8); + fb.vbemode = 0; /* XXX */ + + switch (info->PixelFormat) { + case PixelBlueGreenRedReserved8BitPerColor: + fb.rnum = 8; + fb.gnum = 8; + fb.bnum = 8; + fb.rpos = 16; + fb.gpos = 8; + fb.bpos = 0; + break; + + case PixelRedGreenBlueReserved8BitPerColor: + fb.rnum = 8; + fb.gnum = 8; + fb.bnum = 8; + fb.rpos = 0; + fb.gpos = 8; + fb.bpos = 16; + break; + + case PixelBitMask: + setpixelformat(info->PixelInformation.RedMask, + &fb.rnum, &fb.rpos); + setpixelformat(info->PixelInformation.GreenMask, + &fb.gnum, &fb.gpos); + setpixelformat(info->PixelInformation.BlueMask, + &fb.bnum, &fb.bpos); + break; + + case PixelBltOnly: + case PixelFormatMax: + Panic(L"Error: invalid pixel format (%d)", info->PixelFormat); + break; + } + + framebuffer_configure(&fb); +} + +int +vbe_commit(void) +{ + + bi_framebuffer(); + return 0; +} + +static void +print_text_modes(void) +{ + EFI_STATUS status; + UINTN cols, rows; + INT32 i, curmode; + + curmode = ST->ConOut->Mode->Mode; + for (i = 0; i < ST->ConOut->Mode->MaxMode; i++) { + status = uefi_call_wrapper(ST->ConOut->QueryMode, 4, + ST->ConOut, i, &cols, &rows); + if (EFI_ERROR(status)) + continue; + Print(L"%c%d: %dx%d\n", i == curmode ? '*' : ' ', + i, cols, rows); + } +} + +static int +efi_find_text_mode(char *arg) +{ + EFI_STATUS status; + UINTN cols, rows; + INT32 i; + char mode[32]; + + for (i = 0; i < ST->ConOut->Mode->MaxMode; i++) { + status = uefi_call_wrapper(ST->ConOut->QueryMode, 4, + ST->ConOut, i, &cols, &rows); + if (EFI_ERROR(status)) + continue; + snprintf(mode, sizeof(mode), "%lux%lu", (long)cols, (long)rows); + if (strcmp(arg, mode) == 0) + return i; + } + return -1; +} + +void +command_text(char *arg) +{ + EFI_STATUS status; + INT32 modenum; + + if (*arg == '\0' || strcmp(arg, "list") == 0) { + print_text_modes(); + return; + } + + if (strchr(arg, 'x') != NULL) { + modenum = efi_find_text_mode(arg); + if (modenum == -1) { + printf("mode %s not supported by firmware\n", arg); + return; + } + } else { + modenum = strtoul(arg, NULL, 0); + } + + status = uefi_call_wrapper(ST->ConOut->SetMode, 2, ST->ConOut, modenum); + if (!EFI_ERROR(status)) + return; + + printf("invalid flag, must be 'list', a display mode, " + "or a mode number\n"); +} + +static int +print_gop_modes(void) +{ + EFI_STATUS status; + EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *info; + UINTN sz; + UINT32 i; + uint8_t depth; + + if (efi_gop == NULL) + return 1; + + for (i = 0; i < efi_gop->Mode->MaxMode; i++) { + status = uefi_call_wrapper(efi_gop->QueryMode, 4, efi_gop, i, + &sz, &info); + if (EFI_ERROR(status) && status == EFI_NOT_STARTED) { + status = uefi_call_wrapper(efi_gop->SetMode, 2, + efi_gop, efi_gop->Mode->Mode); + status = uefi_call_wrapper(efi_gop->QueryMode, 4, + efi_gop, i, &sz, &info); + } + if (EFI_ERROR(status)) + continue; + + Print(L"%c%d: %dx%d ", + memcmp(info, efi_gop->Mode->Info, sizeof(*info)) == 0 ? + '*' : ' ', + i, info->HorizontalResolution, info->VerticalResolution); + switch (info->PixelFormat) { + case PixelRedGreenBlueReserved8BitPerColor: + Print(L"RGBR"); + break; + case PixelBlueGreenRedReserved8BitPerColor: + Print(L"BGRR"); + break; + case PixelBitMask: + Print(L"R:%08x G:%08x B:%08x X:%08x", + info->PixelInformation.RedMask, + info->PixelInformation.GreenMask, + info->PixelInformation.BlueMask, + info->PixelInformation.ReservedMask); + break; + case PixelBltOnly: + Print(L"(blt only)"); + break; + default: + Print(L"(Invalid pixel format)"); + break; + } + Print(L" pitch %d", info->PixelsPerScanLine); + depth = getdepth(info); + if (depth > 0) + Print(L" bpp %d", depth); + Print(L"\n"); + } + + return 0; +} + +static int +efi_find_gop_mode(char *arg) +{ + EFI_STATUS status; + EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *info; + UINTN sz; + UINT32 i; + char mode[32]; + uint8_t depth; + + for (i = 0; i < efi_gop->Mode->MaxMode; i++) { + status = uefi_call_wrapper(efi_gop->QueryMode, 4, efi_gop, i, + &sz, &info); + if (EFI_ERROR(status)) + continue; + + depth = getdepth(info); + if (depth == 0) + continue; + + snprintf(mode, sizeof(mode), "%lux%lux%u", + (long)info->HorizontalResolution, + (long)info->HorizontalResolution, + depth); + if (strcmp(arg, mode) == 0) + return i; + } + return -1; +} + +void +command_gop(char *arg) +{ + EFI_STATUS status; + INT32 modenum; + + if (efi_gop == NULL) { + printf("GOP not supported by firmware\n"); + return; + } + + if (*arg == '\0' || strcmp(arg, "list") == 0) { + print_gop_modes(); + return; + } + + if (strchr(arg, 'x') != NULL) { + modenum = efi_find_gop_mode(arg); + if (modenum == -1) { + printf("mode %s not supported by firmware\n", arg); + return; + } + } else { + modenum = strtoul(arg, NULL, 0); + } + + status = uefi_call_wrapper(efi_gop->SetMode, 2, efi_gop, modenum); + if (!EFI_ERROR(status) && efi_gop->Mode->Mode == modenum) { + efi_gop_mode = modenum; + return; + } + + printf("invalid flag, must be 'list', a display mode, " + "or a mode number\n"); +} + +static void +eficons_init_video(void) +{ + EFI_STATUS status; + UINTN cols, rows, dim = 0; + INT32 i, best = -1; + + /* + * Setup text mode + */ + uefi_call_wrapper(ST->ConOut->Reset, 2, ST->ConOut, TRUE); + + for (i = 0; i < ST->ConOut->Mode->MaxMode; i++) { + status = uefi_call_wrapper(ST->ConOut->QueryMode, 4, + ST->ConOut, i, &cols, &rows); + if (EFI_ERROR(status)) + continue; + if (dim < cols * rows) { + dim = cols * rows; + best = i; + } + } + if (best >= 0) + uefi_call_wrapper(ST->ConOut->SetMode, 2, ST->ConOut, best); + uefi_call_wrapper(ST->ConOut->EnableCursor, 2, ST->ConOut, TRUE); + uefi_call_wrapper(ST->ConOut->ClearScreen, 1, ST->ConOut); + + LibLocateProtocol(&GraphicsOutputProtocol, (void **)&efi_gop); +} + +/* + * for Apple EFI + */ +#define CONSOLE_CONTROL_PROTOCOL \ + {0xf42f7782, 0x12e, 0x4c12, {0x99, 0x56, 0x49, 0xf9, 0x43, 0x4, 0xf7, 0x21}} +static EFI_GUID ConsoleControlProtocol = CONSOLE_CONTROL_PROTOCOL; + +struct _EFI_CONSOLE_CONTROL_INTERFACE; +typedef struct _EFI_CONSOLE_CONTROL_INTERFACE EFI_CONSOLE_CONTROL_INTERFACE; +typedef enum { EfiConsoleControlScreenText } EFI_CONSOLE_CONTROL_SCREEN_MODE; +typedef EFI_STATUS (EFIAPI *EFI_CONSOLE_CONTROL_PROTOCOL_SET_MODE) ( + IN EFI_CONSOLE_CONTROL_INTERFACE *This, + IN EFI_CONSOLE_CONTROL_SCREEN_MODE Mode +); +struct _EFI_CONSOLE_CONTROL_INTERFACE { + VOID *GetMode; + EFI_CONSOLE_CONTROL_PROTOCOL_SET_MODE SetMode; + VOID *LockStdIn; +}; + +static void +efi_switch_video_to_text_mode(void) +{ + EFI_STATUS status; + EFI_CONSOLE_CONTROL_INTERFACE *cci; + + /* Set up the console, so printf works. */ + status = LibLocateProtocol(&ConsoleControlProtocol, (void **)&cci); + if (!EFI_ERROR(status)) { + uefi_call_wrapper(cci->SetMode, 2, cci, + EfiConsoleControlScreenText); + } +} Index: src/sys/arch/i386/stand/efiboot/efidelay.c diff -u /dev/null src/sys/arch/i386/stand/efiboot/efidelay.c:1.1 --- /dev/null Tue Jan 24 11:09:15 2017 +++ src/sys/arch/i386/stand/efiboot/efidelay.c Tue Jan 24 11:09:14 2017 @@ -0,0 +1,46 @@ +/* $NetBSD: efidelay.c,v 1.1 2017/01/24 11:09:14 nonaka Exp $ */ + +/*- + * Copyright (c) 2016 Kimihiro Nonaka <non...@netbsd.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "efiboot.h" + +void +delay(int us) +{ + EFI_STATUS status; + + status = uefi_call_wrapper(BS->Stall, 1, us); + if (EFI_ERROR(status)) + Panic(L"%a: couldn't delay %d us: %r\n", __func__, us, status); +} + +void +wait_sec(int sec) +{ + while (sec-- > 0) + delay(1000 * 1000); +} Index: src/sys/arch/i386/stand/efiboot/efidisk.c diff -u /dev/null src/sys/arch/i386/stand/efiboot/efidisk.c:1.1 --- /dev/null Tue Jan 24 11:09:15 2017 +++ src/sys/arch/i386/stand/efiboot/efidisk.c Tue Jan 24 11:09:14 2017 @@ -0,0 +1,127 @@ +/* $NetBSD: efidisk.c,v 1.1 2017/01/24 11:09:14 nonaka Exp $ */ + +/*- + * Copyright (c) 2016 Kimihiro Nonaka <non...@netbsd.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "efiboot.h" + +#include "efidisk.h" + +static struct efidiskinfo_lh efi_disklist; +static int nefidisks; + +void +efi_disk_probe(void) +{ + EFI_STATUS status; + UINTN i, nhandles; + EFI_HANDLE *handles; + EFI_BLOCK_IO *bio; + EFI_BLOCK_IO_MEDIA *media; + struct efidiskinfo *edi; + EFI_DEVICE_PATH *dp, *bdp; + bool bootdev; + int dev; + + TAILQ_INIT(&efi_disklist); + + status = LibLocateHandle(ByProtocol, &BlockIoProtocol, NULL, + &nhandles, &handles); + if (EFI_ERROR(status)) + Panic(L"LocateHandle(BlockIoProtocol): %r", status); + + for (i = 0; i < nhandles; i++) { + status = uefi_call_wrapper(BS->HandleProtocol, 3, handles[i], + &BlockIoProtocol, (void **)&bio); + if (EFI_ERROR(status)) + Panic(L"HandleProtocol(BlockIoProtocol): %r", status); + + media = bio->Media; + if (media->LogicalPartition || !media->MediaPresent) + continue; + + edi = alloc(sizeof(struct efidiskinfo)); + memset(edi, 0, sizeof(*edi)); + edi->bio = bio; + edi->media_id = media->MediaId; + + bootdev = false; + if (efi_bootdp == NULL) + goto next; + + status = uefi_call_wrapper(BS->HandleProtocol, 3, handles[i], + &DevicePathProtocol, (void **)&dp); + if (EFI_ERROR(status)) + goto next; + + bdp = efi_bootdp; + for (;;) { + if (IsDevicePathEnd(dp)) { + bootdev = true; + break; + } + if (memcmp(dp, bdp, sizeof(EFI_DEVICE_PATH)) != 0 || + memcmp(dp, bdp, DevicePathNodeLength(dp)) != 0) + break; + dp = NextDevicePathNode(dp); + bdp = NextDevicePathNode(bdp); + } +next: + if (bootdev) + TAILQ_INSERT_HEAD(&efi_disklist, edi, list); + else + TAILQ_INSERT_TAIL(&efi_disklist, edi, list); + } + + FreePool(handles); + + dev = 0x80; + TAILQ_FOREACH(edi, &efi_disklist, list) { + edi->dev = dev++; + nefidisks++; + } +} + +const struct efidiskinfo * +efidisk_getinfo(int dev) +{ + const struct efidiskinfo *edi; + + TAILQ_FOREACH(edi, &efi_disklist, list) { + if (dev == edi->dev) + return edi; + } + return NULL; +} + +/* + * Return the number of hard disk drives. + */ +int +get_harddrives(void) +{ + return nefidisks; +} Index: src/sys/arch/i386/stand/efiboot/efidisk.h diff -u /dev/null src/sys/arch/i386/stand/efiboot/efidisk.h:1.1 --- /dev/null Tue Jan 24 11:09:15 2017 +++ src/sys/arch/i386/stand/efiboot/efidisk.h Tue Jan 24 11:09:14 2017 @@ -0,0 +1,40 @@ +/* $NetBSD: efidisk.h,v 1.1 2017/01/24 11:09:14 nonaka Exp $ */ + +/*- + * Copyright (c) 2016 Kimihiro Nonaka <non...@netbsd.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <sys/queue.h> + +struct efidiskinfo { + TAILQ_ENTRY(efidiskinfo) list; + + int dev; + EFI_BLOCK_IO *bio; + UINT32 media_id; +}; +TAILQ_HEAD(efidiskinfo_lh, efidiskinfo); + +const struct efidiskinfo *efidisk_getinfo(int); Index: src/sys/arch/i386/stand/efiboot/efidisk_ll.c diff -u /dev/null src/sys/arch/i386/stand/efiboot/efidisk_ll.c:1.1 --- /dev/null Tue Jan 24 11:09:15 2017 +++ src/sys/arch/i386/stand/efiboot/efidisk_ll.c Tue Jan 24 11:09:14 2017 @@ -0,0 +1,200 @@ +/* $NetBSD: efidisk_ll.c,v 1.1 2017/01/24 11:09:14 nonaka Exp $ */ +/* NetBSD: biosdisk_ll.c,v 1.31 2011/02/21 02:58:02 jakllsch Exp */ + +/*- + * Copyright (c) 2005 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Bang Jun-Young. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Copyright (c) 1996 + * Matthias Drochner. All rights reserved. + * Copyright (c) 1996 + * Perry E. Metzger. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgements: + * This product includes software developed for the NetBSD Project + * by Matthias Drochner. + * This product includes software developed for the NetBSD Project + * by Perry E. Metzger. + * 4. The names of the authors may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * shared by bootsector startup (bootsectmain) and biosdisk.c + * needs lowlevel parts from bios_disk.S + */ + +#include "efiboot.h" + +#include "biosdisk_ll.h" +#include "diskbuf.h" +#include "efidisk.h" + +static int do_read(struct biosdisk_ll *, daddr_t, int, char *); + +#ifndef BIOSDISK_RETRIES +#define BIOSDISK_RETRIES 5 +#endif + +int +set_geometry(struct biosdisk_ll *d, struct biosdisk_extinfo *ed) +{ + const struct efidiskinfo *edi; + EFI_BLOCK_IO_MEDIA *media; + + edi = efidisk_getinfo(d->dev); + if (edi == NULL) + return 1; + + media = edi->bio->Media; + + d->secsize = media->BlockSize; + d->type = BIOSDISK_TYPE_HD; + d->flags = BIOSDISK_INT13EXT; + + ed->totsec = media->LastBlock + 1; + ed->sbytes = media->BlockSize; + ed->flags = 0; + if (media->RemovableMedia) + ed->flags |= EXTINFO_REMOVABLE; + + return 0; +} + +/* + * Global shared "diskbuf" is used as read ahead buffer. For reading from + * floppies, the bootstrap has to be loaded on a 64K boundary to ensure that + * this buffer doesn't cross a 64K DMA boundary. + */ +static int ra_dev; +static daddr_t ra_end; +static daddr_t ra_first; + +static int +do_read(struct biosdisk_ll *d, daddr_t dblk, int num, char *buf) +{ + EFI_STATUS status; + const struct efidiskinfo *edi; + + edi = efidisk_getinfo(d->dev); + if (edi == NULL) + return -1; + + status = uefi_call_wrapper(edi->bio->ReadBlocks, 5, edi->bio, + edi->media_id, dblk, num * d->secsize, buf); + if (EFI_ERROR(status)) + return -1; + return num; +} + +/* + * NB if 'cold' is set below not all of the program is loaded, so + * mustn't use data segment, bss, call library functions or do read-ahead. + */ +int +readsects(struct biosdisk_ll *d, daddr_t dblk, int num, char *buf, int cold) +{ + while (num) { + int nsec; + + /* check for usable data in read-ahead buffer */ + if (cold || diskbuf_user != &ra_dev || d->dev != ra_dev + || dblk < ra_first || dblk >= ra_end) { + + /* no, read from disk */ + char *trbuf; + int maxsecs; + int retries = BIOSDISK_RETRIES; + + if (cold) { + /* transfer directly to buffer */ + trbuf = buf; + maxsecs = num; + } else { + /* fill read-ahead buffer */ + trbuf = alloc_diskbuf(0); /* no data yet */ + maxsecs = DISKBUFSIZE / d->secsize; + } + + while ((nsec = do_read(d, dblk, maxsecs, trbuf)) < 0) { +#ifdef DISK_DEBUG + if (!cold) + printf("read error dblk %"PRId64"-%"PRId64"\n", + dblk, (dblk + maxsecs - 1)); +#endif + if (--retries >= 0) + continue; + return -1; /* XXX cannot output here if + * (cold) */ + } + if (!cold) { + ra_dev = d->dev; + ra_first = dblk; + ra_end = dblk + nsec; + diskbuf_user = &ra_dev; + } + } else /* can take blocks from end of read-ahead + * buffer */ + nsec = ra_end - dblk; + + if (!cold) { + /* copy data from read-ahead to user buffer */ + if (nsec > num) + nsec = num; + memcpy(buf, + diskbufp + (dblk - ra_first) * d->secsize, + nsec * d->secsize); + } + buf += nsec * d->secsize; + num -= nsec; + dblk += nsec; + } + + return 0; +} Index: src/sys/arch/i386/stand/efiboot/efigetsecs.c diff -u /dev/null src/sys/arch/i386/stand/efiboot/efigetsecs.c:1.1 --- /dev/null Tue Jan 24 11:09:15 2017 +++ src/sys/arch/i386/stand/efiboot/efigetsecs.c Tue Jan 24 11:09:14 2017 @@ -0,0 +1,52 @@ +/* $NetBSD: efigetsecs.c,v 1.1 2017/01/24 11:09:14 nonaka Exp $ */ + +/* + * Copyright (c) 2015 YASUOKA Masahiko <yasu...@yasuoka.net> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "efiboot.h" + +#include <lib/libsa/net.h> + +satime_t +getsecs(void) +{ + static const int daytab[][14] = { + { 0, -1, 30, 58, 89, 119, 150, 180, 211, 242, 272, 303, 333, 364 }, + { 0, -1, 30, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 }, + }; + EFI_TIME t; + satime_t r; + int y; +#define isleap(_y) (((_y) % 4) == 0 && (((_y) % 100) != 0 || ((_y) % 400) == 0)) + + uefi_call_wrapper(RT->GetTime, 2, &t, NULL); + + /* Calc days from UNIX epoch */ + r = (t.Year - 1970) * 365; + for (y = 1970; y < t.Year; y++) { + if (isleap(y)) + r++; + } + r += daytab[isleap(t.Year) ? 1 : 0][t.Month] + t.Day; + + /* Calc secs */ + r *= 60 * 60 * 24; + r += ((t.Hour * 60) + t.Minute) * 60 + t.Second; + if (-24 * 60 < t.TimeZone && t.TimeZone < 24 * 60) + r += t.TimeZone * 60; + + return r; +} Index: src/sys/arch/i386/stand/efiboot/efimemory.c diff -u /dev/null src/sys/arch/i386/stand/efiboot/efimemory.c:1.1 --- /dev/null Tue Jan 24 11:09:15 2017 +++ src/sys/arch/i386/stand/efiboot/efimemory.c Tue Jan 24 11:09:14 2017 @@ -0,0 +1,350 @@ +/* $NetBSD: efimemory.c,v 1.1 2017/01/24 11:09:14 nonaka Exp $ */ + +/*- + * Copyright (c) 2016 Kimihiro Nonaka <non...@netbsd.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "efiboot.h" + +#include <bootinfo.h> + +static const char *memtypes[] = { + "unknown", + "available", + "reserved", + "ACPI reclaimable", + "ACPI NVS" +}; + +static const char *efimemtypes[] = { + "Reserved", + "LoaderCode", + "LoaderData", + "BootServicesCode", + "BootServicesData", + "RuntimeServicesCode", + "RuntimeServicesData", + "ConventionalMemory", + "UnusableMemory", + "ACPIReclaimMemory", + "ACPIMemoryNVS", + "MemoryMappedIO", + "MemoryMappedIOPortSpace", + "PalCode", +}; + +static int +getmemtype(EFI_MEMORY_DESCRIPTOR *md) +{ + + switch (md->Type) { + case EfiLoaderCode: + case EfiLoaderData: + case EfiBootServicesCode: + case EfiBootServicesData: + case EfiConventionalMemory: + return (md->Attribute & EFI_MEMORY_WB) ? + BIM_Memory : BIM_Reserved; + + case EfiACPIReclaimMemory: + return BIM_ACPI; + + case EfiACPIMemoryNVS: + return BIM_NVS; + + case EfiReservedMemoryType: + case EfiRuntimeServicesCode: + case EfiRuntimeServicesData: + case EfiUnusableMemory: + case EfiMemoryMappedIO: + case EfiMemoryMappedIOPortSpace: + case EfiPalCode: + case EfiMaxMemoryType: + return BIM_Reserved; + } + return BIM_Reserved; +} + +static EFI_MEMORY_DESCRIPTOR * +GetMemoryMap(OUT UINTN *NoEntries, OUT UINTN *MapKey, OUT UINTN *DescriptorSize, + OUT UINT32 *DescriptorVersion, bool sorted) +{ + EFI_MEMORY_DESCRIPTOR *desc, *md, *next, *target, tmp; + UINTN i, j; + + *NoEntries = 0; + desc = LibMemoryMap(NoEntries, MapKey, DescriptorSize, + DescriptorVersion); + if (desc == NULL) + Panic(L"LibMemoryMap failed"); + + if (!sorted) + return desc; + + for (i = 0, md = desc; i < *NoEntries - 1; i++, md = next) { + target = next = NextMemoryDescriptor(md, *DescriptorSize); + for (j = i + 1; j < *NoEntries; j++) { + if (md->PhysicalStart > target->PhysicalStart) { + CopyMem(&tmp, md, sizeof(*md)); + CopyMem(md, target, sizeof(*md)); + CopyMem(target, &tmp, sizeof(*md)); + } + target = NextMemoryDescriptor(target, *DescriptorSize); + } + } + return desc; +} + +/* + * get memory size below 1MB + */ +int +getbasemem(void) +{ + EFI_MEMORY_DESCRIPTOR *mdtop, *md, *next; + UINTN i, NoEntries, MapKey, DescriptorSize, MappingSize; + UINT32 DescriptorVersion; + EFI_PHYSICAL_ADDRESS basemem = 0, epa; + + mdtop = GetMemoryMap(&NoEntries, &MapKey, &DescriptorSize, + &DescriptorVersion, true); + + for (i = 0, md = mdtop; i < NoEntries; i++, md = next) { + next = NextMemoryDescriptor(md, DescriptorSize); + if (getmemtype(md) != BIM_Memory) + continue; + if (md->PhysicalStart >= 1 * 1024 * 1024) + continue; + if (basemem != md->PhysicalStart) + continue; + + MappingSize = md->NumberOfPages * EFI_PAGE_SIZE; + epa = md->PhysicalStart + MappingSize; + if (epa == 0 || epa > 1 * 1024 * 1024) + epa = 1 * 1024 * 1024; + basemem = epa; + } + + FreePool(mdtop); + + return basemem / 1024; /* KiB */ +} + +/* + * get memory size above 1MB below 4GB + */ +int +getextmemx(void) +{ + EFI_MEMORY_DESCRIPTOR *mdtop, *md, *next; + UINTN i, NoEntries, MapKey, DescriptorSize, MappingSize; + UINT32 DescriptorVersion; + EFI_PHYSICAL_ADDRESS extmem16m = 0; /* 0-16MB */ + EFI_PHYSICAL_ADDRESS extmem4g = 0; /* 16MB-4GB */ + EFI_PHYSICAL_ADDRESS pa, epa; + bool first16m = true, first4g = true; + int extmem; + + mdtop = GetMemoryMap(&NoEntries, &MapKey, &DescriptorSize, + &DescriptorVersion, true); + + for (i = 0, md = mdtop; i < NoEntries; i++, md = next) { + next = NextMemoryDescriptor(md, DescriptorSize); + if (getmemtype(md) == BIM_Reserved) + continue; + if (md->PhysicalStart >= 4 * 1024 * 1024 * 1024ULL) + continue; + + MappingSize = md->NumberOfPages * EFI_PAGE_SIZE; + epa = md->PhysicalStart + MappingSize; + if (epa == 0 || epa > 4 * 1024 * 1024 * 1024LL) + epa = 4 * 1024 * 1024 * 1024LL; + + if (epa <= 1 * 1024 * 1024) + continue; + + pa = md->PhysicalStart; + if (pa < 16 * 1024 * 1024) { + if (first16m || extmem16m == pa) { + first16m = false; + if (epa >= 16 * 1024 * 1024) { + extmem16m = 16 * 1024 * 1024; + pa = 16 * 1024 * 1024; + } else + extmem16m = epa; + } + } + if (pa >= 16 * 1024 * 1024) { + if (first4g || extmem4g == pa) { + first4g = false; + extmem4g = epa; + } + } + } + + FreePool(mdtop); + + if (extmem16m > 1 * 1024 * 1024) + extmem16m -= 1 * 1024 * 1024; /* below 1MB */ + + extmem = extmem16m / 1024; + if (extmem == 15 * 1024) + extmem += extmem4g / 1024; + return extmem; +} + +void +efi_memory_probe(void) +{ + EFI_MEMORY_DESCRIPTOR *mdtop, *md, *next; + UINTN i, n, NoEntries, MapKey, DescriptorSize, MappingSize; + UINT32 DescriptorVersion; + int memtype; + + mdtop = GetMemoryMap(&NoEntries, &MapKey, &DescriptorSize, + &DescriptorVersion, false); + + Print(L" mem["); + for (i = 0, n = 0, md = mdtop; i < NoEntries; i++, md = next) { + next = NextMemoryDescriptor(md, DescriptorSize); + + memtype = getmemtype(md); + if (memtype != BIM_Memory) + continue; + + MappingSize = md->NumberOfPages * EFI_PAGE_SIZE; + if (MappingSize < 12 * 1024) /* XXX Why? from OpenBSD */ + continue; + + if (n++ > 0) + Print(L" "); + Print(L"0x%lx-0x%lx", md->PhysicalStart, + md->PhysicalStart + MappingSize - 1); + } + Print(L"]"); + + FreePool(mdtop); +} + +void +efi_memory_show_map(bool sorted) +{ + EFI_STATUS status; + EFI_MEMORY_DESCRIPTOR *mdtop, *md, *next; + UINTN i, NoEntries, MapKey, DescriptorSize; + UINT32 DescriptorVersion; + char memstr[32], efimemstr[32]; + int memtype; + UINTN cols, rows, row = 0; + + status = uefi_call_wrapper(ST->ConOut->QueryMode, 4, ST->ConOut, + ST->ConOut->Mode->Mode, &cols, &rows); + if (EFI_ERROR(status) || rows <= 2) + rows = 0; + else + rows -= 2; + + mdtop = GetMemoryMap(&NoEntries, &MapKey, &DescriptorSize, + &DescriptorVersion, sorted); + + for (i = 0, md = mdtop; i < NoEntries; i++, md = next) { + next = NextMemoryDescriptor(md, DescriptorSize); + + memtype = getmemtype(md); + if (memtype >= __arraycount(memtypes)) + snprintf(memstr, sizeof(memstr), "unknown (%d)", + memtype); + if (md->Type >= __arraycount(efimemtypes)) + snprintf(efimemstr, sizeof(efimemstr), "unknown (%d)", + md->Type); + printf("%016" PRIxMAX "/%016" PRIxMAX ": %s [%s]\n", + (uintmax_t)md->PhysicalStart, + (uintmax_t)md->PhysicalStart + + md->NumberOfPages * EFI_PAGE_SIZE - 1, + memtype >= __arraycount(memtypes) ? + memstr : memtypes[memtype], + md->Type >= __arraycount(efimemtypes) ? + efimemstr : efimemtypes[md->Type]); + + if (rows >= 0 && ++row >= rows) { + row = 0; + Print(L"Press Any Key to continue :"); + (void) awaitkey(-1, 0); + Print(L"\n"); + } + } + + FreePool(mdtop); +} + +void +bi_getmemmap(void) +{ + EFI_MEMORY_DESCRIPTOR *md; + UINTN NoEntries, MapKey, DescriptorSize; + UINT32 DescriptorVersion; + struct btinfo_efimemmap *bim; + size_t allocsz; + + md = GetMemoryMap(&NoEntries, &MapKey, &DescriptorSize, + &DescriptorVersion, true); + + allocsz = sizeof(struct btinfo_efimemmap) - 1 + + NoEntries * DescriptorSize; + bim = alloc(allocsz); + + bim->num = NoEntries; + bim->version = DescriptorVersion; + bim->size = DescriptorSize; + memcpy(bim->memmap, md, NoEntries * DescriptorSize); + + FreePool(md); + + BI_ADD(bim, BTINFO_EFIMEMMAP, allocsz); +} + +void +vpbcopy(const void *va, void *pa, size_t n) +{ + memmove(pa, va, n); +} + +void +pvbcopy(const void *pa, void *va, size_t n) +{ + memmove(va, pa, n); +} + +void +pbzero(void *pa, size_t n) +{ + memset(pa, 0, n); +} + +physaddr_t +vtophys(void *va) +{ + return (physaddr_t)va; +} Index: src/sys/arch/i386/stand/efiboot/panic.c diff -u /dev/null src/sys/arch/i386/stand/efiboot/panic.c:1.1 --- /dev/null Tue Jan 24 11:09:15 2017 +++ src/sys/arch/i386/stand/efiboot/panic.c Tue Jan 24 11:09:14 2017 @@ -0,0 +1,69 @@ +/* $NetBSD: panic.c,v 1.1 2017/01/24 11:09:14 nonaka Exp $ */ + +/*- + * Copyright (c) 2016 Kimihiro Nonaka <non...@netbsd.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "efiboot.h" + +#include <efistdarg.h> + +/* from sys/external/bsd/gnu-efi/dist/lib/print.c */ +UINTN VPrint (IN CHAR16 *, va_list); + +__dead VOID +Panic( + IN CHAR16 *fmt, + ... + ) +{ + va_list args; + + va_start(args, fmt); + VPrint(fmt, args); + Print(L"\n"); + va_end(args); + reboot(); + /*NOTREACHED*/ +} + +void +reboot(void) +{ + + WaitForSingleEvent(ST->ConIn->WaitForKey, 0); + + uefi_call_wrapper(RT->ResetSystem, 4, EfiResetCold, EFI_SUCCESS, + 0, NULL); + for (;;) + continue; +} + +void +_rtt(void) +{ + + reboot(); +} Index: src/sys/arch/i386/stand/efiboot/self_reloc.c diff -u /dev/null src/sys/arch/i386/stand/efiboot/self_reloc.c:1.1 --- /dev/null Tue Jan 24 11:09:15 2017 +++ src/sys/arch/i386/stand/efiboot/self_reloc.c Tue Jan 24 11:09:14 2017 @@ -0,0 +1,99 @@ +/* $NetBSD: self_reloc.c,v 1.1 2017/01/24 11:09:14 nonaka Exp $ */ + +/*- + * Copyright (c) 2008-2010 Rui Paulo <rpa...@freebsd.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <sys/types.h> +#include <sys/exec_elf.h> + +#include <efi.h> + +void self_reloc(Elf_Addr, Elf_Dyn *); + +#if defined(__aarch64__) +#define USE_RELA +#endif + +/* + * A simple elf relocator. + */ +void +self_reloc(Elf_Addr baseaddr, Elf_Dyn *dynamic) +{ + Elf_Word relsz, relent; + Elf_Addr *newaddr; + Elf_Rel *rel = NULL; + Elf_Dyn *dynp; + + /* + * Find the relocation address, its size and the relocation entry. + */ + relsz = 0; + relent = 0; + for (dynp = dynamic; dynp->d_tag != DT_NULL; dynp++) { + switch (dynp->d_tag) { + case DT_REL: + case DT_RELA: + rel = (Elf_Rel *)(dynp->d_un.d_ptr + baseaddr); + break; + case DT_RELSZ: + case DT_RELASZ: + relsz = dynp->d_un.d_val; + break; + case DT_RELENT: + case DT_RELAENT: + relent = dynp->d_un.d_val; + break; + default: + break; + } + } + + /* + * Perform the actual relocation. + */ + for (; relsz > 0; relsz -= relent) { + switch (ELF_R_TYPE(rel->r_info)) { + case R_TYPE(NONE): + /* No relocation needs be performed. */ + break; + + case R_TYPE(RELATIVE): + /* Address relative to the base address. */ + newaddr = (Elf_Addr *)(rel->r_offset + baseaddr); + *newaddr += baseaddr; +#ifdef USE_RELA + /* Add the addend when the ABI uses them */ + *newaddr += ((Elf_Rela *)rel)->r_addend; +#endif + break; + default: + /* XXX: do we need other relocations ? */ + break; + } + rel = (Elf_Rel *) ((char *) rel + relent); + } +} Index: src/sys/arch/i386/stand/efiboot/version diff -u /dev/null src/sys/arch/i386/stand/efiboot/version:1.1 --- /dev/null Tue Jan 24 11:09:15 2017 +++ src/sys/arch/i386/stand/efiboot/version Tue Jan 24 11:09:14 2017 @@ -0,0 +1,7 @@ +$NetBSD: version,v 1.1 2017/01/24 11:09:14 nonaka Exp $ + +NOTE ANY CHANGES YOU MAKE TO THE EFI BOOTLOADER HERE. The format of this +file is important - make sure the entries are appended on end, last item +is taken as the current. + +1.0: Initial version. Index: src/sys/arch/i386/stand/efiboot/bootia32/Makefile diff -u /dev/null src/sys/arch/i386/stand/efiboot/bootia32/Makefile:1.1 --- /dev/null Tue Jan 24 11:09:15 2017 +++ src/sys/arch/i386/stand/efiboot/bootia32/Makefile Tue Jan 24 11:09:14 2017 @@ -0,0 +1,17 @@ +# $NetBSD: Makefile,v 1.1 2017/01/24 11:09:14 nonaka Exp $ + +PROG= bootia32.efi +OBJFMT= pei-i386 + +EXTRA_SOURCES= efibootia32.c + +CPUFLAGS= -march=i686 -mtune=i686 +GNUEFIARCH= ia32 +LIBKERN_ARCH= i386 +LIBGNUEFI_ARCH= i386 +KLINK_MACHINE= i386 + +CFLAGS+= -m32 +AFLAGS+= -m32 + +.include "${.CURDIR}/../Makefile.efiboot" Index: src/sys/arch/i386/stand/efiboot/bootia32/efiboot_machdep.h diff -u /dev/null src/sys/arch/i386/stand/efiboot/bootia32/efiboot_machdep.h:1.1 --- /dev/null Tue Jan 24 11:09:15 2017 +++ src/sys/arch/i386/stand/efiboot/bootia32/efiboot_machdep.h Tue Jan 24 11:09:14 2017 @@ -0,0 +1,29 @@ +/* $NetBSD: efiboot_machdep.h,v 1.1 2017/01/24 11:09:14 nonaka Exp $ */ + +/*- + * Copyright (c) 2016 Kimihiro Nonaka <non...@netbsd.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +void efi_md_init(void); Index: src/sys/arch/i386/stand/efiboot/bootia32/efibootia32.c diff -u /dev/null src/sys/arch/i386/stand/efiboot/bootia32/efibootia32.c:1.1 --- /dev/null Tue Jan 24 11:09:15 2017 +++ src/sys/arch/i386/stand/efiboot/bootia32/efibootia32.c Tue Jan 24 11:09:14 2017 @@ -0,0 +1,51 @@ +/* $NetBSD: efibootia32.c,v 1.1 2017/01/24 11:09:14 nonaka Exp $ */ + +/*- + * Copyright (c) 2016 Kimihiro Nonaka <non...@netbsd.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "efiboot.h" + +#include <sys/bootblock.h> + +struct x86_boot_params boot_params; + +void +efi_md_init(void) +{ + /* Nothing to do */ +} + +void +startprog(physaddr_t entry, uint32_t argc, uint32_t *argv, physaddr_t sp) +{ + Panic(L"%a: not implemented", __func__); +} + +void +multiboot(physaddr_t entry, physaddr_t header, physaddr_t sp) +{ + Panic(L"%a: not implemented", __func__); +} Index: src/sys/arch/i386/stand/efiboot/bootia32/ldscript diff -u /dev/null src/sys/arch/i386/stand/efiboot/bootia32/ldscript:1.1 --- /dev/null Tue Jan 24 11:09:15 2017 +++ src/sys/arch/i386/stand/efiboot/bootia32/ldscript Tue Jan 24 11:09:14 2017 @@ -0,0 +1,76 @@ +/* $NetBSD: ldscript,v 1.1 2017/01/24 11:09:14 nonaka Exp $ */ +OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386") +OUTPUT_ARCH(i386) +ENTRY(_start) +SECTIONS +{ + . = 0; + ImageBase = .; + .hash : { *(.hash) } /* this MUST come first! */ + . = ALIGN(4096); + .text : + { + *(.text) + *(.text.*) + *(.gnu.linkonce.t.*) + } + . = ALIGN(4096); + .sdata : + { + *(.got.plt) + *(.got) + *(.srodata) + *(.sdata) + *(.sbss) + *(.scommon) + } + . = ALIGN(4096); + .data : + { + *(.rodata*) + *(.data) + *(.data1) + *(.data.*) + *(.sdata) + *(.got.plt) + *(.got) + /* the EFI loader doesn't seem to like a .bss section, so we stick + it all into .data: */ + *(.sbss) + *(.scommon) + *(.dynbss) + *(.bss) + *(COMMON) + } + . = ALIGN(4096); + .dynamic : { *(.dynamic) } + . = ALIGN(4096); + .rel : + { + *(.rel.data) + *(.rel.data.*) + *(.rel.got) + *(.rel.stab) + *(.data.rel.ro.local) + *(.data.rel.local) + *(.data.rel.ro) + *(.data.rel*) + } + . = ALIGN(4096); + .reloc : /* This is the PECOFF .reloc section! */ + { + *(.reloc) + } + . = ALIGN(4096); + .dynsym : { *(.dynsym) } + . = ALIGN(4096); + .dynstr : { *(.dynstr) } + . = ALIGN(4096); + /DISCARD/ : + { + *(.rel.reloc) + *(.eh_frame) + *(.note.GNU-stack) + } + .comment 0 : { *(.comment) } +} Index: src/sys/arch/i386/stand/efiboot/bootia32/start.S diff -u /dev/null src/sys/arch/i386/stand/efiboot/bootia32/start.S:1.1 --- /dev/null Tue Jan 24 11:09:15 2017 +++ src/sys/arch/i386/stand/efiboot/bootia32/start.S Tue Jan 24 11:09:14 2017 @@ -0,0 +1,74 @@ +/* $NetBSD: start.S,v 1.1 2017/01/24 11:09:14 nonaka Exp $ */ + +/*- + * Copyright (c) 2008-2010 Rui Paulo <rpa...@freebsd.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: head/sys/boot/efi/loader/arch/i386/start.S 282728 2015-05-10 13:30:21Z ian $ + */ + +#include <machine/asm.h> + + .text + .align 16 + +/* + * EFI entry point. + * _start(EFI_IMAGE image_handle, EFI_SYSTEM_TABLE *system_table); + * + * We calculate the base address along with _DYNAMIC, relocate us and finally + * pass control to efi_main. + */ + +ENTRY(_start) + pushl %ebp + movl %esp, %ebp + + pushl 12(%ebp) /* image_handle */ + pushl 8(%ebp) /* system_table */ + call 0f +0: popl %eax + movl %eax, %ebx + addl $ImageBase-0b, %eax + addl $_DYNAMIC-0b, %ebx + pushl %ebx /* dynamic */ + pushl %eax /* ImageBase */ + call _C_LABEL(self_reloc) + popl %ebx /* remove ImageBase from the stack */ + popl %ebx /* remove dynamic from the stack */ + call _C_LABEL(efi_main) +1: leave + ret +END(_start) + + /* + * hand-craft a dummy .reloc section so EFI knows it's a relocatable + * executable: + */ + + .data + .section .reloc, "a" + .long 0 + .long 10 + .word 0 Index: src/sys/arch/i386/stand/efiboot/bootx64/Makefile diff -u /dev/null src/sys/arch/i386/stand/efiboot/bootx64/Makefile:1.1 --- /dev/null Tue Jan 24 11:09:15 2017 +++ src/sys/arch/i386/stand/efiboot/bootx64/Makefile Tue Jan 24 11:09:14 2017 @@ -0,0 +1,12 @@ +# $NetBSD: Makefile,v 1.1 2017/01/24 11:09:14 nonaka Exp $ + +PROG= bootx64.efi +OBJFMT= pei-x86-64 +NEWVERSWHAT= "EFI Boot (x64)" + +EXTRA_SOURCES= efibootx64.c startprog64.S + +COPTS+= -mno-red-zone +CPPFLAGS+= -DEFI_FUNCTION_WRAPPER + +.include "${.CURDIR}/../Makefile.efiboot" Index: src/sys/arch/i386/stand/efiboot/bootx64/efiboot_machdep.h diff -u /dev/null src/sys/arch/i386/stand/efiboot/bootx64/efiboot_machdep.h:1.1 --- /dev/null Tue Jan 24 11:09:15 2017 +++ src/sys/arch/i386/stand/efiboot/bootx64/efiboot_machdep.h Tue Jan 24 11:09:14 2017 @@ -0,0 +1,29 @@ +/* $NetBSD: efiboot_machdep.h,v 1.1 2017/01/24 11:09:14 nonaka Exp $ */ + +/*- + * Copyright (c) 2016 Kimihiro Nonaka <non...@netbsd.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +void efi_md_init(void); Index: src/sys/arch/i386/stand/efiboot/bootx64/efibootx64.c diff -u /dev/null src/sys/arch/i386/stand/efiboot/bootx64/efibootx64.c:1.1 --- /dev/null Tue Jan 24 11:09:15 2017 +++ src/sys/arch/i386/stand/efiboot/bootx64/efibootx64.c Tue Jan 24 11:09:14 2017 @@ -0,0 +1,75 @@ +/* $NetBSD: efibootx64.c,v 1.1 2017/01/24 11:09:14 nonaka Exp $ */ + +/*- + * Copyright (c) 2016 Kimihiro Nonaka <non...@netbsd.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "efiboot.h" + +#include <sys/bootblock.h> + +struct x86_boot_params boot_params; + +void startprog64_start(void *, physaddr_t, physaddr_t); +extern void (*startprog64)(void *, physaddr_t, physaddr_t); +extern u_int startprog64_size; + +void +efi_md_init(void) +{ + EFI_STATUS status; + EFI_PHYSICAL_ADDRESS addr = EFI_ALLOCATE_MAX_ADDRESS; + u_int sz = EFI_SIZE_TO_PAGES(startprog64_size); + + status = uefi_call_wrapper(BS->AllocatePages, 4, AllocateMaxAddress, + EfiLoaderData, sz, &addr); + if (EFI_ERROR(status)) + Panic(L"%a: AllocatePages() failed: %d page(s): %r", + __func__, sz, status); + startprog64 = (void *)addr; + CopyMem(startprog64, startprog64_start, startprog64_size); +} + +/* ARGSUSED */ +void +startprog(physaddr_t entry, uint32_t argc, uint32_t *argv, physaddr_t sp) +{ + uint32_t *newsp = (void *)((char *)startprog64 + startprog64_size); + + /* Copy argv to new stack pointer */ + if (argc > 0) { + newsp -= argc; + memcpy(newsp, argv, sizeof(*argv) * argc); + } + + (*startprog64)(startprog64, entry, (physaddr_t)newsp); +} + +/* ARGSUSED */ +void +multiboot(physaddr_t entry, physaddr_t header, physaddr_t sp) +{ + Panic(L"%a: not implemented", __func__); +} Index: src/sys/arch/i386/stand/efiboot/bootx64/ldscript diff -u /dev/null src/sys/arch/i386/stand/efiboot/bootx64/ldscript:1.1 --- /dev/null Tue Jan 24 11:09:15 2017 +++ src/sys/arch/i386/stand/efiboot/bootx64/ldscript Tue Jan 24 11:09:14 2017 @@ -0,0 +1,66 @@ +/* $NetBSD: ldscript,v 1.1 2017/01/24 11:09:14 nonaka Exp $ */ +/* Same as elf_x86_64_fbsd_efi.lds, except for OUTPUT_FORMAT below - KEEP IN SYNC */ +OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64", "elf64-x86-64") +OUTPUT_ARCH(i386:x86-64) +ENTRY(_start) +SECTIONS +{ + . = 0; + ImageBase = .; + .hash : { *(.hash) } /* this MUST come first! */ + . = ALIGN(4096); + .eh_frame : + { + *(.eh_frame) + } + . = ALIGN(4096); + .text : + { + *(.text) + *(.text.*) + *(.gnu.linkonce.t.*) + } + . = ALIGN(4096); + .reloc : + { + *(.reloc) + } + . = ALIGN(4096); + .data : + { + *(.rodata*) + *(.got.plt) + *(.got) + *(.data*) + *(.sdata) + /* the EFI loader doesn't seem to like a .bss section, so we stick + it all into .data: */ + *(.sbss) + *(.scommon) + *(.dynbss) + *(.bss) + *(COMMON) + *(.rel.local) + } + . = ALIGN(4096); + .dynamic : { *(.dynamic) } + . = ALIGN(4096); + .rela : + { + *(.rela.data*) + *(.rela.got) + *(.rela.stab) + } + . = ALIGN(4096); + .dynsym : { *(.dynsym) } + . = ALIGN(4096); + .dynstr : { *(.dynstr) } + . = ALIGN(4096); + .ignored.reloc : + { + *(.rela.reloc) + *(.eh_frame) + *(.note.GNU-stack) + } + .comment 0 : { *(.comment) } +} Index: src/sys/arch/i386/stand/efiboot/bootx64/start.S diff -u /dev/null src/sys/arch/i386/stand/efiboot/bootx64/start.S:1.1 --- /dev/null Tue Jan 24 11:09:15 2017 +++ src/sys/arch/i386/stand/efiboot/bootx64/start.S Tue Jan 24 11:09:14 2017 @@ -0,0 +1,79 @@ +/* $NetBSD: start.S,v 1.1 2017/01/24 11:09:14 nonaka Exp $ */ + +/*- + * Copyright (C) 1999 Hewlett-Packard Co. + * Contributed by David Mosberger <dav...@hpl.hp.com>. + * Copyright (C) 2005 Intel Co. + * Contributed by Fenghua Yu <fenghua...@intel.com>. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Hewlett-Packard Co. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * crt0-efi-x86_64.S - x86_64 EFI startup code. + * $FreeBSD: head/sys/boot/efi/loader/arch/amd64/start.S 282727 2015-05-10 13:24:26Z ian $ + */ + +#include <machine/asm.h> + + .text + .align 16 + .globl _start +_start: + subq $8, %rsp + pushq %rcx + pushq %rdx + +0: + lea ImageBase(%rip), %rdi + lea _DYNAMIC(%rip), %rsi + + popq %rcx + popq %rdx + pushq %rcx + pushq %rdx + call _C_LABEL(self_reloc) + + popq %rdi + popq %rsi + + call _C_LABEL(efi_main) + addq $8, %rsp + +.Lexit: + ret + + /* + * hand-craft a dummy .reloc section so EFI knows it's a relocatable + * executable: + */ + + .data + .section .reloc, "a" + .long 0 + .long 10 + .word 0 Index: src/sys/arch/i386/stand/efiboot/bootx64/startprog64.S diff -u /dev/null src/sys/arch/i386/stand/efiboot/bootx64/startprog64.S:1.1 --- /dev/null Tue Jan 24 11:09:15 2017 +++ src/sys/arch/i386/stand/efiboot/bootx64/startprog64.S Tue Jan 24 11:09:14 2017 @@ -0,0 +1,155 @@ +/* $NetBSD: startprog64.S,v 1.1 2017/01/24 11:09:14 nonaka Exp $ */ +/* NetBSD: startprog.S,v 1.3 2003/02/01 14:48:18 dsl Exp */ + +/* starts program in protected mode / flat space + with given stackframe + needs global variables flatcodeseg and flatdataseg + (gdt offsets) + derived from: NetBSD:sys/arch/i386/boot/asm.S + */ + +/* + * Ported to boot 386BSD by Julian Elischer (jul...@tfs.com) Sept 1992 + * + * Mach Operating System + * Copyright (c) 1992, 1991 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or software.distribut...@cs.cmu.edu + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie Mellon + * the rights to redistribute these changes. + */ + +/* + Copyright 1988, 1989, 1990, 1991, 1992 + by Intel Corporation, Santa Clara, California. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and +its documentation for any purpose and without fee is hereby +granted, provided that the above copyright notice appears in all +copies and that both the copyright notice and this permission notice +appear in supporting documentation, and that the name of Intel +not be used in advertising or publicity pertaining to distribution +of the software without specific, written prior permission. + +INTEL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE +INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, +IN NO EVENT SHALL INTEL BE LIABLE FOR ANY SPECIAL, INDIRECT, OR +CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT, +NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION +WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +#include <machine/asm.h> +#include <machine/specialreg.h> + +#define CODE_SEGMENT 0x08 +#define DATA_SEGMENT 0x10 + + .align 16 + .globl _C_LABEL(startprog64) +_C_LABEL(startprog64): + .quad 0 + + .globl _C_LABEL(startprog64_size) +_C_LABEL(startprog64_size): + .long startprog64_end - _C_LABEL(startprog64_start) + + .text + .p2align 4,,15 + +/* + * startprog64(loadddr,entry,stack) + */ +ENTRY(startprog64_start) +start: + /* + * This function is to call the loaded kernel's start() with + * 32bit segment mode from x64 mode. + * %rdi: loaded start address + * %rsi: kernel entry address + * %rdx: stack address + */ + + cld # LynxOS depends on it + + /* Prepare jump address */ + lea (start32a - start)(%rdi), %rax + movl %eax, (start32r - start)(%rdi) + + cli + + /* Setup GDT */ + lea (gdt - start)(%rdi), %rax + mov %rax, (gdtrr - start)(%rdi) + lgdt (gdtr - start)(%rdi) + + /* Jump to set %cs */ + ljmp *(start32r - start)(%rdi) + + .align 4 + .code32 +start32a: + movl $DATA_SEGMENT, %eax + movw %eax, %ds + movw %eax, %es + movw %eax, %fs + movw %eax, %gs + movw %eax, %ss + + movl %edx, %esp + + /* Disable Paging in CR0 */ + movl %cr0, %eax + andl $(~CR0_PG), %eax + movl %eax, %cr0 + + /* Disable PAE in CR4 */ + movl %cr4, %eax + andl $(~CR4_PAE), %eax + movl %eax, %cr4 + + jmp start32b + + .align 4 +start32b: + xor %eax, %eax + call *%esi + + .align 16 +start32r: + .long 0 + .long CODE_SEGMENT + .align 16 +gdt: + .long 0, 0 + .byte 0xff, 0xff, 0x00, 0x00, 0x00, 0x9f, 0xcf, 0x00 + .byte 0xff, 0xff, 0x00, 0x00, 0x00, 0x93, 0xcf, 0x00 +gdtr: + .word gdtr - gdt +gdtrr: + .quad +start32end: + /* Space for the stack */ + .align 16 + .space 8192 +startprog64_end: Index: src/sys/lib/libgnuefi/arch/i386/Makefile.inc diff -u /dev/null src/sys/lib/libgnuefi/arch/i386/Makefile.inc:1.1 --- /dev/null Tue Jan 24 11:09:15 2017 +++ src/sys/lib/libgnuefi/arch/i386/Makefile.inc Tue Jan 24 11:09:15 2017 @@ -0,0 +1,3 @@ +# $NetBSD: Makefile.inc,v 1.1 2017/01/24 11:09:15 nonaka Exp $ + +SRCS+= efi_stub.S Index: src/sys/lib/libgnuefi/arch/x86_64/Makefile.inc diff -u /dev/null src/sys/lib/libgnuefi/arch/x86_64/Makefile.inc:1.1 --- /dev/null Tue Jan 24 11:09:15 2017 +++ src/sys/lib/libgnuefi/arch/x86_64/Makefile.inc Tue Jan 24 11:09:15 2017 @@ -0,0 +1,3 @@ +# $NetBSD: Makefile.inc,v 1.1 2017/01/24 11:09:15 nonaka Exp $ + +SRCS+= callwrap.c efi_stub.S