Hi, Patch adds armv8/aarch64 EFI payload image build support. With patrick@'s aarch64-none-elf- toolchain referenced in my last mail on this list, you can build it via...
$ MACHINE=armv8 armmake64-aarch64 -f Makefile.arm64 ...where armmake64-aarch64 is a simple env wrapper for the toolchain, uploaded here: https://ce.gl/armmake64-aarch64.txt I've tested this on the pine64, it works up until boot(0) is called which fails as there is no bootable disk/aarch64 kernel yet. I've put this in the armv7 directory pending a proper armv8/aarch64/arm64 one. Ian Index: sys/arch/arm/include/reloc.h =================================================================== RCS file: /cvs/src/sys/arch/arm/include/reloc.h,v retrieving revision 1.2 diff -u -p -r1.2 reloc.h --- sys/arch/arm/include/reloc.h 26 May 2006 20:22:04 -0000 1.2 +++ sys/arch/arm/include/reloc.h 23 Nov 2016 03:54:28 -0000 @@ -52,3 +52,19 @@ #define R_ARM_RPC24 254 #define R_ARM_RBASE 255 +#define R_AARCH64_NONE 0 /* No relocation */ +#define R_AARCH64_ABS64 257 /* Absolute offset */ +#define R_AARCH64_ABS32 258 /* Absolute, 32-bit overflow check */ +#define R_AARCH64_ABS16 259 /* Absolute, 16-bit overflow check */ +#define R_AARCH64_PREL64 260 /* PC relative */ +#define R_AARCH64_PREL32 261 /* PC relative, 32-bit overflow check */ +#define R_AARCH64_PREL16 262 /* PC relative, 16-bit overflow check */ +#define R_AARCH64_COPY 1024 /* Copy data from shared object */ +#define R_AARCH64_GLOB_DAT 1025 /* Set GOT entry to data address */ +#define R_AARCH64_JUMP_SLOT 1026 /* Set GOT entry to code address */ +#define R_AARCH64_RELATIVE 1027 /* Add load address of shared object */ +#define R_AARCH64_TLS_DTPREL64 1028 +#define R_AARCH64_TLS_DTPMOD64 1029 +#define R_AARCH64_TLS_TPREL64 1030 +#define R_AARCH64_TLSDESC 1031 /* Identify the TLS descriptor */ +#define R_AARCH64_IRELATIVE 1032 Index: sys/arch/armv7/stand/efiboot/Makefile.arm64 =================================================================== RCS file: sys/arch/armv7/stand/efiboot/Makefile.arm64 diff -N sys/arch/armv7/stand/efiboot/Makefile.arm64 --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ sys/arch/armv7/stand/efiboot/Makefile.arm64 23 Nov 2016 03:54:28 -0000 @@ -0,0 +1,80 @@ +# $OpenBSD: Makefile,v 1.6 2016/11/06 16:42:00 tb Exp $ + +NOMAN= # + +.if ${MACHINE} == "armv8" + +PROG= BOOTAA64.EFI +OBJFMT= binary +INSTALL_STRIP= +BINDIR= /usr/mdec +SRCS= start64.S self_reloc.c efiboot64.c conf.c exec64.c efidev64.c fdt.c + +S= ${.CURDIR}/../../../.. +EFIDIR= ${S}/stand/efi + +OBJCOPY?= objcopy +OBJDUMP?= objdump + +LDFLAGS+=-nostdlib -T ${.CURDIR}/ldscript.arm64 -Bsymbolic -shared + +.PATH: ${S}/stand/boot +SRCS+= boot.c cmd.c vars.c + +.PATH: ${S}/lib/libsa +SRCS+= alloc.c ctime.c exit.c getchar.c memcmp.o memcpy.o memmove.c memset.c \ + printf.c putchar.c snprintf.c strchr.c strcmp.c strerror.c strncmp.c \ + strncpy.c strtol.c +SRCS+= close.c closeall.c cons.c cread.c dev.c disklabel.c dkcksum.c fstat.c \ + lseek.c open.c read.c readdir.c stat.c +SRCS+= loadfile.c +SRCS+= ufs.c + +.PATH: ${S}/lib/libkern/arch/arm ${S}/lib/libkern +#SRCS+= divsi3.S divdi3.c moddi3.c qdivrem.c strlcpy.c strlen.c +SRCS+= divdi3.c moddi3.c qdivrem.c strlcpy.c strlen.c + +.PATH: ${S}/lib/libz +SRCS+= adler32.c crc32.c inflate.c inftrees.c + +CPPFLAGS+= -nostdinc +CPPFLAGS+= -I${S} -I. -I${.CURDIR} +CPPFLAGS+= -I${EFIDIR}/include -I${EFIDIR}/include/arm +CPPFLAGS+= -D_STANDALONE +CPPFLAGS+= -DSMALL -DSLOW -DNOBYFOUR -D__INTERNAL_LIBSA_CREAD +CPPFLAGS+= -DNEEDS_HEAP_H +COPTS+= -Wno-attributes -Wno-format +COPTS+= -ffreestanding -fno-stack-protector +COPTS+= -fshort-wchar -fPIC -fno-builtin +COPTS+= -Wall -Werror + +PROG.elf= ${PROG:S/.EFI/.elf/} +CLEANFILES+= ${PROG.elf} ${PROG.elf}.tmp + +${PROG}: ${PROG.elf} + ${OBJCOPY} -j .peheader -j .text -j .sdata -j .data \ + -j .dynamic -j .dynsym -j .dynstr -j .rel -j .rel.dyn \ + -j .rela -j .rela.dyn -j .reloc \ + --output-target=${OBJFMT} ${PROG.elf} ${.TARGET} + +.include <bsd.prog.mk> + +${PROG.elf}: ${OBJS} + ${LD} ${LDFLAGS} -o ${.TARGET}.tmp ${OBJS} ${LDADD} + @if ${OBJDUMP} -t ${.TARGET}.tmp | grep 'UND'; then \ + (echo Undefined symbols; false); \ + fi + mv ${.TARGET}.tmp ${.TARGET} + +.if !make(clean) && !make(cleandir) && !make(includes) && !make(obj) +.BEGIN: + @([ -h machine ] || ln -s ${.CURDIR}/../../../${MACHINE}/include machine) + @([ -h arm ] || ln -s ${.CURDIR}/../../../arm/include arm) +.NOPATH: machine arm +CLEANFILES+= machine arm +.endif + +.else +NOPROG=yes +.include <bsd.prog.mk> +.endif Index: sys/arch/armv7/stand/efiboot/efiboot64.c =================================================================== RCS file: sys/arch/armv7/stand/efiboot/efiboot64.c diff -N sys/arch/armv7/stand/efiboot/efiboot64.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ sys/arch/armv7/stand/efiboot/efiboot64.c 23 Nov 2016 03:54:28 -0000 @@ -0,0 +1,505 @@ +/* $OpenBSD: efiboot.c,v 1.13 2016/10/23 19:06:08 kettenis Exp $ */ + +/* + * Copyright (c) 2015 YASUOKA Masahiko <yasu...@yasuoka.net> + * Copyright (c) 2016 Mark Kettenis + * + * 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 <sys/param.h> +#include <sys/queue.h> +#include <dev/cons.h> +#include <sys/disklabel.h> + +#include <efi.h> +#include <efiapi.h> +#include <efiprot.h> +#include <eficonsctl.h> + +#include <lib/libkern/libkern.h> +#include <stand/boot/cmd.h> + +#include "disk.h" +#include "eficall.h" +#include "fdt.h" +#include "libsa.h" + +EFI_SYSTEM_TABLE *ST; +EFI_BOOT_SERVICES *BS; +EFI_RUNTIME_SERVICES *RS; +EFI_HANDLE IH; + +EFI_HANDLE efi_bootdp; + +static EFI_GUID imgp_guid = LOADED_IMAGE_PROTOCOL; +static EFI_GUID blkio_guid = BLOCK_IO_PROTOCOL; +static EFI_GUID devp_guid = DEVICE_PATH_PROTOCOL; + +static void efi_timer_init(void); +static void efi_timer_cleanup(void); + +EFI_STATUS +efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *systab) +{ + extern char *progname; + EFI_LOADED_IMAGE *imgp; + EFI_DEVICE_PATH *dp = NULL; + EFI_STATUS status; + + ST = systab; + BS = ST->BootServices; + IH = image; + + status = EFI_CALL(BS->HandleProtocol, image, &imgp_guid, + (void **)&imgp); + + if (status == EFI_SUCCESS) + status = EFI_CALL(BS->HandleProtocol, imgp->DeviceHandle, + &devp_guid, (void **)&dp); + if (status == EFI_SUCCESS) + efi_bootdp = dp; + + progname = "BOOTAA64"; + + boot(0); + + return (EFI_SUCCESS); +} + +static SIMPLE_TEXT_OUTPUT_INTERFACE *conout; +static SIMPLE_INPUT_INTERFACE *conin; + +void +efi_cons_probe(struct consdev *cn) +{ + cn->cn_pri = CN_MIDPRI; + cn->cn_dev = makedev(12, 0); +} + +void +efi_cons_init(struct consdev *cp) +{ + conin = ST->ConIn; + conout = ST->ConOut; +} + +int +efi_cons_getc(dev_t dev) +{ + EFI_INPUT_KEY key; + EFI_STATUS status; +#if 0 + UINTN dummy; +#endif + static int lastchar = 0; + + if (lastchar) { + int r = lastchar; + if ((dev & 0x80) == 0) + lastchar = 0; + return (r); + } + + status = conin->ReadKeyStroke(conin, &key); + while (status == EFI_NOT_READY) { + if (dev & 0x80) + return (0); + /* + * XXX The implementation of WaitForEvent() in U-boot + * is broken and neverreturns. + */ +#if 0 + BS->WaitForEvent(1, &conin->WaitForKey, &dummy); +#endif + status = conin->ReadKeyStroke(conin, &key); + } + + if (dev & 0x80) + lastchar = key.UnicodeChar; + + return (key.UnicodeChar); +} + +void +efi_cons_putc(dev_t dev, int c) +{ + CHAR16 buf[2]; + + if (c == '\n') + efi_cons_putc(dev, '\r'); + + buf[0] = c; + buf[1] = 0; + + conout->OutputString(conout, buf); +} + +EFI_PHYSICAL_ADDRESS heap; +UINTN heapsiz = 1 * 1024 * 1024; + +static void +efi_heap_init(void) +{ + EFI_STATUS status; + + status = EFI_CALL(BS->AllocatePages, AllocateAnyPages, EfiLoaderData, + EFI_SIZE_TO_PAGES(heapsiz), &heap); + if (status != EFI_SUCCESS) + panic("BS->AllocatePages()"); +} + +EFI_BLOCK_IO *disk; + +void +efi_diskprobe(void) +{ + int i, bootdev; + UINTN sz; + EFI_STATUS status; + EFI_HANDLE *handles = NULL; + EFI_BLOCK_IO *blkio; + EFI_BLOCK_IO_MEDIA *media; + EFI_DEVICE_PATH *dp, *bp; + + sz = 0; + status = EFI_CALL(BS->LocateHandle, ByProtocol, &blkio_guid, 0, &sz, 0); + if (status == EFI_BUFFER_TOO_SMALL) { + handles = alloc(sz); + status = EFI_CALL(BS->LocateHandle, ByProtocol, &blkio_guid, + 0, &sz, handles); + } + if (handles == NULL || EFI_ERROR(status)) + panic("BS->LocateHandle() returns %d", status); + + for (i = 0; i < sz / sizeof(EFI_HANDLE); i++) { + bootdev = 0; + status = EFI_CALL(BS->HandleProtocol, handles[i], &blkio_guid, + (void **)&blkio); + if (EFI_ERROR(status)) + panic("BS->HandleProtocol() returns %d", status); + + media = blkio->Media; + if (media->LogicalPartition || !media->MediaPresent) + continue; + + if (efi_bootdp == NULL) + goto next; + status = EFI_CALL(BS->HandleProtocol, handles[i], &devp_guid, + (void **)&dp); + if (EFI_ERROR(status)) + goto next; + bp = efi_bootdp; + while (1) { + if (IsDevicePathEnd(dp)) { + bootdev = 1; + break; + } + if (memcmp(dp, bp, sizeof(EFI_DEVICE_PATH)) != 0 || + memcmp(dp, bp, DevicePathNodeLength(dp)) != 0) + break; + dp = NextDevicePathNode(dp); + bp = NextDevicePathNode(bp); + } +next: + if (bootdev) { + disk = blkio; + break; + } + } + + free(handles, sz); +} + +struct board_id { + const char *name; + uint32_t board_id; +}; + +struct board_id board_id_table[] = { + { "arm,vexpress", 2272 }, + { "google,snow", 3774 }, + { "google,spring", 3774 }, + { "samsung,universal_c210", 2838 }, + { "ti,am335x-bone", 3589 }, + { "ti,omap3-beagle", 1546 }, + { "ti,omap3-beagle-xm", 1546 }, + { "ti,omap4-panda", 2791 }, +}; + +static EFI_GUID fdt_guid = FDT_TABLE_GUID; + +#define efi_guidcmp(_a, _b) memcmp((_a), (_b), sizeof(EFI_GUID)) + +void * +efi_makebootargs(char *bootargs, uint32_t *board_id) +{ + void *fdt = NULL; + char bootduid[8]; + u_char zero[8]; + void *node; + size_t len; + int i; + + for (i = 0; i < ST->NumberOfTableEntries; i++) { + if (efi_guidcmp(&fdt_guid, + &ST->ConfigurationTable[i].VendorGuid) == 0) + fdt = ST->ConfigurationTable[i].VendorTable; + } + + if (!fdt_init(fdt)) + return NULL; + + node = fdt_find_node("/chosen"); + if (!node) + return NULL; + + len = strlen(bootargs) + 1; + fdt_node_add_property(node, "bootargs", bootargs, len); + + /* Pass DUID of the boot disk. */ + memset(&zero, 0, sizeof(zero)); + memcpy(&bootduid, diskinfo.disklabel.d_uid, sizeof(bootduid)); + if (memcmp(bootduid, zero, sizeof(bootduid)) != 0) { + fdt_node_add_property(node, "openbsd,bootduid", bootduid, + sizeof(bootduid)); + } + + fdt_finalize(); + + node = fdt_find_node("/"); + for (i = 0; i < nitems(board_id_table); i++) { + if (fdt_node_is_compatible(node, board_id_table[i].name)) { + *board_id = board_id_table[i].board_id; + break; + } + } + + return fdt; +} + +u_long efi_loadaddr; + +void +machdep(void) +{ + EFI_PHYSICAL_ADDRESS addr; + EFI_STATUS status; + + cninit(); + + /* + * The kernel expects to be loaded at offset 0x00300000 into a + * block of memory aligned on a 256MB boundary. We allocate a + * block of 32MB of memory, which gives us plenty of room for + * growth. + */ + for (addr = 0x10000000; addr <= 0xf0000000; addr += 0x10000000) { + status = BS->AllocatePages(AllocateAddress, EfiLoaderData, + EFI_SIZE_TO_PAGES(32 * 1024 * 1024), &addr); + if (status == EFI_SUCCESS) { + efi_loadaddr = addr; + break; + } + } + if (efi_loadaddr == 0) + printf("Can't allocate memory\n"); + + efi_heap_init(); + efi_timer_init(); + efi_diskprobe(); +} + +void +efi_cleanup(void) +{ + efi_timer_cleanup(); + + BS->ExitBootServices(NULL, 0); +} + +void +_rtt(void) +{ +#ifdef EFI_DEBUG + printf("Hit any key to reboot\n"); + efi_cons_getc(0); +#endif + /* + * XXX ResetSystem doesn't seem to work on U-Boot 2016.05 on + * the CuBox-i. So trigger an unimplemented instruction trap + * instead. + */ +#if 1 + asm volatile(".word 0xa000f7f0\n"); +#else + RS->ResetSystem(EfiResetCold, EFI_SUCCESS, 0, NULL); +#endif + while (1) { } +} + +/* + * U-Boot only implements the GetTime() Runtime Service if it has been + * configured with CONFIG_DM_RTC. Most board configurations don't + * include that option, so we can't use it to implement our boot + * prompt timeout. Instead we use timer events to simulate a clock + * that ticks ever second. + */ + +EFI_EVENT timer; +int ticks; + +static VOID +efi_timer(EFI_EVENT event, VOID *context) +{ + ticks++; +} + +static void +efi_timer_init(void) +{ + EFI_STATUS status; + + status = BS->CreateEvent(EVT_TIMER, TPL_CALLBACK, + efi_timer, NULL, &timer); + if (status == EFI_SUCCESS) + status = BS->SetTimer(timer, TimerPeriodic, 10000000); + if (EFI_ERROR(status)) + printf("Can't create timer\n"); +} + +static void +efi_timer_cleanup(void) +{ + BS->CloseEvent(timer); +} + +time_t +getsecs(void) +{ + return ticks; +} + +/* + * Various device-related bits. + */ + +void +devboot(dev_t dev, char *p) +{ + strlcpy(p, "sd0a", 5); +} + +int +cnspeed(dev_t dev, int sp) +{ + return 115200; +} + +char * +ttyname(int fd) +{ + return "com0"; +} + +dev_t +ttydev(char *name) +{ + return NODEV; +} + +#define MAXDEVNAME 16 + +/* + * Parse a device spec. + * + * [A-Za-z]*[0-9]*[A-Za-z]:file + * dev uint part + */ +int +devparse(const char *fname, int *dev, int *unit, int *part, const char **file) +{ + const char *s; + + *unit = 0; /* default to wd0a */ + *part = 0; + *dev = 0; + + s = strchr(fname, ':'); + if (s != NULL) { + int devlen; + int i, u, p = 0; + struct devsw *dp; + char devname[MAXDEVNAME]; + + devlen = s - fname; + if (devlen > MAXDEVNAME) + return (EINVAL); + + /* extract device name */ + for (i = 0; isalpha(fname[i]) && (i < devlen); i++) + devname[i] = fname[i]; + devname[i] = 0; + + if (!isdigit(fname[i])) + return (EUNIT); + + /* device number */ + for (u = 0; isdigit(fname[i]) && (i < devlen); i++) + u = u * 10 + (fname[i] - '0'); + + if (!isalpha(fname[i])) + return (EPART); + + /* partition number */ + if (i < devlen) + p = fname[i++] - 'a'; + + if (i != devlen) + return (ENXIO); + + /* check device name */ + for (dp = devsw, i = 0; i < ndevs; dp++, i++) { + if (dp->dv_name && !strcmp(devname, dp->dv_name)) + break; + } + + if (i >= ndevs) + return (ENXIO); + + *unit = u; + *part = p; + *dev = i; + fname = ++s; + } + + *file = fname; + + return (0); +} + +int +devopen(struct open_file *f, const char *fname, char **file) +{ + struct devsw *dp; + int dev, unit, part, error; + + error = devparse(fname, &dev, &unit, &part, (const char **)file); + if (error) + return (error); + + dp = &devsw[0]; + f->f_dev = dp; + + return (*dp->dv_open)(f, unit, part); +} Index: sys/arch/armv7/stand/efiboot/efidev64.c =================================================================== RCS file: sys/arch/armv7/stand/efiboot/efidev64.c diff -N sys/arch/armv7/stand/efiboot/efidev64.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ sys/arch/armv7/stand/efiboot/efidev64.c 23 Nov 2016 03:54:28 -0000 @@ -0,0 +1,232 @@ +/* $OpenBSD: efidev.c,v 1.2 2016/05/20 11:53:19 kettenis Exp $ */ + +/* + * Copyright (c) 2015 YASUOKA Masahiko <yasu...@yasuoka.net> + * Copyright (c) 2016 Mark Kettenis + * 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 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/param.h> +#include <sys/reboot.h> +#include <sys/disklabel.h> +#include <lib/libz/zlib.h> + +#include "libsa.h" + +#include <efi.h> +#include "eficall.h" + +extern EFI_BOOT_SERVICES *BS; + +extern int debug; + +#include "disk.h" +#include "efidev.h" + +#define EFI_BLKSPERSEC(_ed) ((_ed)->blkio->Media->BlockSize / DEV_BSIZE) +#define EFI_SECTOBLK(_ed, _n) ((_n) * EFI_BLKSPERSEC(_ed)) + +extern EFI_BLOCK_IO *disk; +struct diskinfo diskinfo; + +static EFI_STATUS + efid_io(int, efi_diskinfo_t, u_int, int, void *); +static int efid_diskio(int, struct diskinfo *, u_int, int, void *); + +static EFI_STATUS +efid_io(int rw, efi_diskinfo_t ed, u_int off, int nsect, void *buf) +{ + EFI_STATUS status = EFI_SUCCESS; + EFI_PHYSICAL_ADDRESS addr; + caddr_t data; + + if (ed->blkio->Media->BlockSize != DEV_BSIZE) + return (EFI_UNSUPPORTED); + + status = BS->AllocatePages(AllocateAnyPages, EfiLoaderData, + EFI_SIZE_TO_PAGES(nsect * DEV_BSIZE), &addr); + if (EFI_ERROR(status)) + goto on_eio; + data = (caddr_t)(uintptr_t)addr; + + switch (rw) { + case F_READ: + status = EFI_CALL(ed->blkio->ReadBlocks, + ed->blkio, ed->mediaid, off, + nsect * DEV_BSIZE, data); + if (EFI_ERROR(status)) + goto on_eio; + memcpy(buf, data, nsect * DEV_BSIZE); + break; + case F_WRITE: + if (ed->blkio->Media->ReadOnly) + goto on_eio; + /* XXX not yet */ + goto on_eio; + break; + } + return (EFI_SUCCESS); + +on_eio: + BS->FreePages(addr, EFI_SIZE_TO_PAGES(nsect * DEV_BSIZE)); + + return (status); +} + +static int +efid_diskio(int rw, struct diskinfo *dip, u_int off, int nsect, void *buf) +{ + EFI_STATUS status; + + status = efid_io(rw, &dip->ed, off, nsect, buf); + + return ((EFI_ERROR(status))? -1 : 0); +} + +/* + * Read disk label from the device. + */ +int +efi_getdisklabel(struct diskinfo *dip) +{ + char *msg; + int sector; + size_t rsize; + struct disklabel *lp; + char buf[DEV_BSIZE]; + uint16_t buf_sighold; + + /* + * Find OpenBSD Partition in DOS partition table. + */ + sector = 0; + if (efistrategy(dip, F_READ, DOSBBSECTOR, DEV_BSIZE, buf, &rsize)) + return EOFFSET; + + memcpy(&buf_sighold, &(buf[DOSMBR_SIGNATURE_OFF]), sizeof(uint16_t)); + + if (buf_sighold == DOSMBR_SIGNATURE) { + int i; + struct dos_partition *dp = (struct dos_partition *)buf; + + /* + * Lookup OpenBSD slice. If there is none, go ahead + * and try to read the disklabel off sector #0. + */ + + memcpy(dp, &buf[DOSPARTOFF], NDOSPART * sizeof(*dp)); + for (i = 0; i < NDOSPART; i++) { + if (dp[i].dp_typ == DOSPTYP_OPENBSD) { + sector = letoh32(dp[i].dp_start); + break; + } + } + } + + if (efistrategy(dip, F_READ, sector + DOS_LABELSECTOR, DEV_BSIZE, + buf, &rsize)) + return EOFFSET; + + if ((msg = getdisklabel(buf + LABELOFFSET, &dip->disklabel))) + printf("sd%d: getdisklabel: %s\n", 0, msg); + + lp = &dip->disklabel; + + /* check partition */ + if ((dip->sc_part >= lp->d_npartitions) || + (lp->d_partitions[dip->sc_part].p_fstype == FS_UNUSED)) { + DPRINTF(("illegal partition\n")); + return (EPART); + } + + return (0); +} + +int +efiopen(struct open_file *f, ...) +{ + struct diskinfo *dip = &diskinfo; + va_list ap; + u_int unit, part; + int error; + + if (disk == NULL) + return (ENXIO); + + va_start(ap, f); + unit = va_arg(ap, u_int); + part = va_arg(ap, u_int); + va_end(ap); + + if (unit != 0) + return (ENXIO); + + diskinfo.ed.blkio = disk; + diskinfo.ed.mediaid = disk->Media->MediaId; + diskinfo.sc_part = part; + + error = efi_getdisklabel(&diskinfo); + if (error) + return (error); + + f->f_devdata = dip; + + return 0; +} + +int +efistrategy(void *devdata, int rw, daddr32_t blk, size_t size, void *buf, + size_t *rsize) +{ + struct diskinfo *dip = (struct diskinfo *)devdata; + int error = 0; + size_t nsect; + + nsect = (size + DEV_BSIZE - 1) / DEV_BSIZE; + blk += dip->disklabel.d_partitions[B_PARTITION(dip->sc_part)].p_offset; + + if (blk < 0) + error = EINVAL; + else + error = efid_diskio(rw, dip, blk, nsect, buf); + + if (rsize != NULL) + *rsize = nsect * DEV_BSIZE; + + return (error); +} + +int +eficlose(struct open_file *f) +{ + f->f_devdata = NULL; + + return 0; +} + +int +efiioctl(struct open_file *f, u_long cmd, void *data) +{ + return 0; +} Index: sys/arch/armv7/stand/efiboot/exec64.c =================================================================== RCS file: sys/arch/armv7/stand/efiboot/exec64.c diff -N sys/arch/armv7/stand/efiboot/exec64.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ sys/arch/armv7/stand/efiboot/exec64.c 23 Nov 2016 03:54:28 -0000 @@ -0,0 +1,91 @@ +/* $OpenBSD: exec.c,v 1.10 2016/10/06 18:15:44 kettenis Exp $ */ + +/* + * Copyright (c) 2006, 2016 Mark Kettenis + * + * 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 <sys/param.h> +#include <sys/reboot.h> +#include <dev/cons.h> + +#include <lib/libkern/libkern.h> +#include <lib/libsa/loadfile.h> +#include <sys/exec_elf.h> + +#include <efi.h> +#include <stand/boot/cmd.h> + +#include "efiboot.h" +#include "libsa.h" + +typedef void (*startfuncp)(void *, void *, void *) __attribute__ ((noreturn)); + +void +run_loadfile(u_long *marks, int howto) +{ + Elf_Ehdr *elf = (Elf_Ehdr *)marks[MARK_SYM]; + Elf_Shdr *shp = (Elf_Shdr *)(marks[MARK_SYM] + elf->e_shoff); + u_long esym = marks[MARK_END] & 0x0fffffff; + u_long offset = 0; + char args[256]; + char *cp; + void *fdt; + uint32_t board_id = 0; + uint64_t board_id_pad = 0; + int i; + + /* + * Tell locore.S where the symbol table ends by setting + * 'esym', which should be the first word in the .data + * section. + */ + for (i = 0; i < elf->e_shnum; i++) { + /* XXX Assume .data is the first writable segment. */ + if (shp[i].sh_flags & SHF_WRITE) { + /* XXX We have to store the virtual address. */ + esym |= shp[i].sh_addr & 0xf0000000; + *(u_long *)(LOADADDR(shp[i].sh_addr)) = esym; + break; + } + } + + snprintf(args, sizeof(args) - 8, "%s:%s", cmd.bootdev, cmd.image); + cp = args + strlen(args); + + *cp++ = ' '; + *cp = '-'; + if (howto & RB_ASKNAME) + *++cp = 'a'; + if (howto & RB_CONFIG) + *++cp = 'c'; + if (howto & RB_SINGLE) + *++cp = 's'; + if (howto & RB_KDB) + *++cp = 'd'; + if (*cp == '-') + *--cp = 0; + else + *++cp = 0; + + fdt = efi_makebootargs(args, &board_id); + + efi_cleanup(); + + memcpy(&board_id_pad, &board_id, sizeof(board_id)); + + (*(startfuncp)(marks[MARK_ENTRY]))((void *)esym, (void *)board_id_pad, fdt); + + /* NOTREACHED */ +} Index: sys/arch/armv7/stand/efiboot/ldscript.arm64 =================================================================== RCS file: sys/arch/armv7/stand/efiboot/ldscript.arm64 diff -N sys/arch/armv7/stand/efiboot/ldscript.arm64 --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ sys/arch/armv7/stand/efiboot/ldscript.arm64 23 Nov 2016 03:54:28 -0000 @@ -0,0 +1,64 @@ +/* $FreeBSD: head/sys/boot/efi/loader/arch/arm/ldscript.arm 295420 2016-02-09 00:01:43Z andrew $ */ +OUTPUT_ARCH(aarch64) +ENTRY(_start) +SECTIONS +{ + /* Read-only sections, merged into text segment: */ + . = 0; + ImageBase = .; + .text : { + *(.peheader) + *(.text .stub .text.* .gnu.linkonce.t.*) + /* .gnu.warning sections are handled specially by elf32.em. */ + *(.gnu.warning) + *(.gnu.linkonce.t*) + } =0 + _etext = .; + PROVIDE (etext = .); +/* . = ALIGN(16); */ + . = ALIGN(0x1000) + (. & (0x1000 - 1)) ; + .data : + { + *(.data .data.*) + *(.gnu.linkonce.d*) + *(.rodata) + *(.rodata.*) + CONSTRUCTORS + + . = ALIGN(4); + PROVIDE (__bss_start = .); + *(.sbss) + *(.scommon) + *(.dynsbss) + *(.dynbss) + *(.bss) + *(COMMON) + . = ALIGN(4); + PROVIDE (__bss_end = .); + } + /* We want the small data sections together, so single-instruction offsets + can access them all, and initialized data all before uninitialized, so + we can shorten the on-disk segment size. */ + .sdata : { + *(.got.plt .got) + *(.sdata*.sdata.* .gnu.linkonce.s.*) + } + set_Xcommand_set : { + __start_set_Xcommand_set = .; + *(set_Xcommand_set) + __stop_set_Xcommand_set = .; + } + __gp = .; + .plt : { *(.plt) } + .dynamic : { *(.dynamic) } + .reloc : { *(.reloc) } + .dynsym : { *(.dynsym) } + .dynstr : { *(.dynstr) } + .rel.dyn : { + *(.rel.*) + *(.relset_*) + } + _edata = .; + PROVIDE (end = .); + .hash : { *(.hash) } +} Index: sys/arch/armv7/stand/efiboot/start64.S =================================================================== RCS file: sys/arch/armv7/stand/efiboot/start64.S diff -N sys/arch/armv7/stand/efiboot/start64.S --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ sys/arch/armv7/stand/efiboot/start64.S 23 Nov 2016 03:54:28 -0000 @@ -0,0 +1,165 @@ +/*- + * Copyright (c) 2014 Andrew Turner + * 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$ + */ + +/* + * We need to be a PE32+ file for EFI. On some architectures we can use + * objcopy to create the correct file, however on arm64 we need to do + * it ourselves. + */ + +#define IMAGE_FILE_MACHINE_ARM64 0xaa64 + +#define IMAGE_SCN_CNT_CODE 0x00000020 +#define IMAGE_SCN_CNT_INITIALIZED_DATA 0x00000040 +#define IMAGE_SCN_MEM_DISCARDABLE 0x02000000 +#define IMAGE_SCN_MEM_EXECUTE 0x20000000 +#define IMAGE_SCN_MEM_READ 0x40000000 + + .section .peheader +efi_start: + /* The MS-DOS Stub, only used to get the offset of the COFF header */ + .ascii "MZ" + .short 0 + .space 0x38 + .long pe_sig - efi_start + + /* The PE32 Signature. Needs to be 8-byte aligned */ + .align 3 +pe_sig: + .ascii "PE" + .short 0 +coff_head: + .short IMAGE_FILE_MACHINE_ARM64 /* AArch64 file */ + .short 2 /* 2 Sections */ + .long 0 /* Timestamp */ + .long 0 /* No symbol table */ + .long 0 /* No symbols */ + .short section_table - optional_header /* Optional header size */ + .short 0 /* Characteristics TODO: Fill in */ + +optional_header: + .short 0x020b /* PE32+ (64-bit addressing) */ + .byte 0 /* Major linker version */ + .byte 0 /* Minor linker version */ + .long _edata - _end_header /* Code size */ + .long 0 /* No initialized data */ + .long 0 /* No uninitialized data */ + .long _start - efi_start /* Entry point */ + .long _end_header - efi_start /* Start of code */ + +optional_windows_header: + .quad 0 /* Image base */ + .long 32 /* Section Alignment */ + .long 8 /* File alignment */ + .short 0 /* Major OS version */ + .short 0 /* Minor OS version */ + .short 0 /* Major image version */ + .short 0 /* Minor image version */ + .short 0 /* Major subsystem version */ + .short 0 /* Minor subsystem version */ + .long 0 /* Win32 version */ + .long _edata - efi_start /* Image size */ + .long _end_header - efi_start /* Header size */ + .long 0 /* Checksum */ + .short 0xa /* Subsystem (EFI app) */ + .short 0 /* DLL Characteristics */ + .quad 0 /* Stack reserve */ + .quad 0 /* Stack commit */ + .quad 0 /* Heap reserve */ + .quad 0 /* Heap commit */ + .long 0 /* Loader flags */ + .long 6 /* Number of RVAs */ + + /* RVAs: */ + .quad 0 + .quad 0 + .quad 0 + .quad 0 + .quad 0 + .quad 0 + +section_table: + /* We need a .reloc section for EFI */ + .ascii ".reloc" + .byte 0 + .byte 0 /* Pad to 8 bytes */ + .long 0 /* Virtual size */ + .long 0 /* Virtual address */ + .long 0 /* Size of raw data */ + .long 0 /* Pointer to raw data */ + .long 0 /* Pointer to relocations */ + .long 0 /* Pointer to line numbers */ + .short 0 /* Number of relocations */ + .short 0 /* Number of line numbers */ + .long (IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | \ + IMAGE_SCN_MEM_DISCARDABLE) /* Characteristics */ + + /* The contents of the loader */ + .ascii ".text" + .byte 0 + .byte 0 + .byte 0 /* Pad to 8 bytes */ + .long _edata - _end_header /* Virtual size */ + .long _end_header - efi_start /* Virtual address */ + .long _edata - _end_header /* Size of raw data */ + .long _end_header - efi_start /* Pointer to raw data */ + .long 0 /* Pointer to relocations */ + .long 0 /* Pointer to line numbers */ + .short 0 /* Number of relocations */ + .short 0 /* Number of line numbers */ + .long (IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_EXECUTE | \ + IMAGE_SCN_MEM_READ) /* Characteristics */ +_end_header: + + .text + .globl _start +_start: + /* Save the boot params to the stack */ + stp x0, x1, [sp, #-16]! + + adr x0, __bss_start + adr x1, __bss_end + + b 2f + +1: + stp xzr, xzr, [x0], #16 +2: + cmp x0, x1 + b.lo 1b + + adr x0, ImageBase + adr x1, _DYNAMIC + + bl self_reloc + + ldp x0, x1, [sp], #16 + + bl efi_main + +1: b 1b