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 >
