On Tue, Nov 22, 2016 at 11:02:55PM -0500, Ian Sutton wrote:
> 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...

Great!

> 
> $ MACHINE=armv8 armmake64-aarch64 -f Makefile.arm64

Please call it arm64.  We should distinquish between 32 and 64-bit ARMs
now.  Yes, the other one is called armv7, but that's just how it is.

Typically the ports are called arm64, while the compiler toolchain
targets are aarch64.

MACHINE -> arm64
MACHINE_ARCH -> aarch64

> 
> ...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.

Sounds good.

> 
> I've put this in the armv7 directory pending a proper
> armv8/aarch64/arm64 one.

Yes, as long as there's no sys/arch/arm64 this would be the only place
it could really be.  I would be okay with having this in that directory
for now.

Is there a reason you copied the C files to a 64-bit version?

Patrick

> 
> 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 <[email protected]>
> + * 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 <[email protected]>
> + * 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