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

Reply via email to