Index: sys/arm64/include/psl.h =================================================================== --- /dev/null +++ sys/arm64/include/psl.h @@ -0,0 +1 @@ +/* $FreeBSD$ */ Index: sys/boot/Makefile.arm64 =================================================================== --- /dev/null +++ sys/boot/Makefile.arm64 @@ -0,0 +1,7 @@ +# $FreeBSD$ + +.if ${MK_FDT} != "no" +SUBDIR+= fdt +.endif + +SUBDIR+= efi Index: sys/boot/arm64/Makefile =================================================================== --- /dev/null +++ sys/boot/arm64/Makefile @@ -0,0 +1,3 @@ +# $FreeBSD$ + +.include Index: sys/boot/arm64/libarm64/cache.h =================================================================== --- /dev/null +++ sys/boot/arm64/libarm64/cache.h @@ -0,0 +1,36 @@ +/*- + * Copyright (c) 2014 The FreeBSD Foundation + * All rights reserved. + * + * This software was developed by Semihalf under + * the sponsorship of the FreeBSD Foundation. + * 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. + */ + +#ifndef _CACHE_H_ +#define _CACHE_H_ + +/* cache.c */ +void cpu_flush_dcache(const void *, size_t); +void cpu_inval_icache(const void *, size_t); + +#endif /* _CACHE_H_ */ Index: sys/boot/arm64/libarm64/cache.c =================================================================== --- /dev/null +++ sys/boot/arm64/libarm64/cache.c @@ -0,0 +1,95 @@ +/*- + * Copyright (c) 2014 The FreeBSD Foundation + * All rights reserved. + * + * This software was developed by Semihalf under + * the sponsorship of the FreeBSD Foundation. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include + +#include + +#include +#include + +#include "cache.h" + +static unsigned int +get_dcache_line_size(void) +{ + uint64_t ctr; + unsigned int dcl_size; + + /* Accessible from all security levels */ + ctr = READ_SPECIALREG(ctr_el0); + + /* + * Relevant field [19:16] is LOG2 + * of the number of words in DCache line + */ + dcl_size = CTR_DLINE_SIZE(ctr); + + /* Size of word shifted by cache line size */ + return (sizeof(int) << dcl_size); +} + +void +cpu_flush_dcache(const void *ptr, size_t len) +{ + + uint64_t cl_size; + vm_offset_t addr, end; + + cl_size = get_dcache_line_size(); + + /* Calculate end address to clean */ + end = (vm_offset_t)(ptr + len); + /* Align start address to cache line */ + addr = (vm_offset_t)ptr; + addr = rounddown2(addr, cl_size); + + for (; addr < end; addr += cl_size) + __asm __volatile("dc civac, %0" : : "r" (addr) : "memory"); + /* Full system DSB */ + __asm __volatile("dsb sy" : : : "memory"); +} + +void +cpu_inval_icache(const void *ptr, size_t len) +{ + + /* NULL ptr or 0 len means all */ + if (ptr == NULL || len == 0) { + __asm __volatile( + "ic ialluis \n" + "dsb ish \n" + : : : "memory"); + return; + } + + /* TODO: Other cache ranges if necessary */ +} Index: sys/boot/common/Makefile.inc =================================================================== --- sys/boot/common/Makefile.inc +++ sys/boot/common/Makefile.inc @@ -9,6 +9,8 @@ SRCS+= load_elf64.c load_elf64_obj.c reloc_elf64.c .elif ${MACHINE} == "pc98" SRCS+= load_elf32.c load_elf32_obj.c reloc_elf32.c +.elif ${MACHINE_CPUARCH} == "aarch64" +SRCS+= load_elf64.c reloc_elf64.c .elif ${MACHINE_CPUARCH} == "arm" SRCS+= load_elf32.c reloc_elf32.c .elif ${MACHINE_CPUARCH} == "powerpc" Index: sys/boot/efi/Makefile =================================================================== --- sys/boot/efi/Makefile +++ sys/boot/efi/Makefile @@ -10,7 +10,9 @@ .endif .endif -.if ${MACHINE_CPUARCH} == "amd64" || ${MACHINE_CPUARCH} == "arm" +.if ${MACHINE_CPUARCH} == "aarch64" || \ + ${MACHINE_CPUARCH} == "amd64" || \ + ${MACHINE_CPUARCH} == "arm" SUBDIR+= loader boot1 .endif Index: sys/boot/efi/boot1/fat-arm64.tmpl.bz2.uu =================================================================== --- /dev/null +++ sys/boot/efi/boot1/fat-arm64.tmpl.bz2.uu @@ -0,0 +1,26 @@ +FAT template boot filesystem created by generate-fat.sh +DO NOT EDIT +$FreeBSD: head/sys/boot/efi/boot1/generate-fat.sh 281238 2015-04-07 21:41:26Z emaste $ +begin 644 fat-arm64.tmpl.bz2 +M0EIH.3%!62936:2BH:(`&T#_____ZZKJ[_^N_ZO_J_Z[OJ_NJ^JK^KZNKNNJ +MZNKNZOJ^P`+\```"``:`9,@T&F3$,@!B`,AIHP$#0-`T``,09--&31IH9#)D +M,(#$T&)B!A``-`,F0:#3)B&0`Q`&0TT8"!H&@:``&(,FFC)HTT,ADR&$!B:# +M$Q`P@`&@&3(-!IDQ#(`8@#(::,!`T#0-``#$&331DT::&0R9#"`Q-!B8@8"J +M*0GY$I&GH"-&AZ@T```T`:`!HT```&@&@-,C0`-`#U,(-`&)ZF(PGIJ>IO;U +M^=&QL3`-\E@Q+$(RTHB$7I"(B(-W:73$0@A#;S##$3$`A#FL\LAF,;&8;[CE +M&D=@ON\:9IWHO):QK7LL=LFN;1M6Y:%F>-1G^&O-A*(@0AQ,\#H*KRCJF>9Q +MFF_,RWU4X-,R6K5EJU:M6L"JMB5555555JVJU*U-JU:M6MUB*I555555;XHJ +ME555555YM='L;(N7+ERY_!^S^F[=KA#3YJ.S-)`!>O]K)`#-ZO +MU=9T,X(@!H',-+,1Q'-6'#ZNQORGURS=]_O%.6SF5G,PC`G#X_@7W$RC>2Q) +M9MW3P&G:AJFA?`^AKWXOV?R_QDL9F^`=5H>$UWWT9K&Q/HS.!KXB)U)9$6,) +M*/!EJ7>+W2L65_C\&LP69G$?'M$18.(LL.G:AZ;%>TUKYF.V+9/W9AMF[&^]HFB?J_AM6V;ANF2RG7,61I)?])L352^EX5C12BSAX@$(3`!EWEZ6P2R$9#_Q=R13A0D*2B +"H:(` +` +end Index: sys/boot/efi/boot1/generate-fat.sh =================================================================== --- sys/boot/efi/boot1/generate-fat.sh +++ sys/boot/efi/boot1/generate-fat.sh @@ -18,7 +18,7 @@ # # Known filenames # amd64: BOOTx64.efi -# aarch64: BOOTaa64.efi +# arm64: BOOTaa64.efi # arm: BOOTarm.efi # i386: BOOTia32.efi # Index: sys/boot/efi/include/arm64/efibind.h =================================================================== --- /dev/null +++ sys/boot/efi/include/arm64/efibind.h @@ -0,0 +1,219 @@ +/* $FreeBSD$ */ +/*++ + +Copyright (c) 1999 - 2003 Intel Corporation. All rights reserved +This software and associated documentation (if any) is furnished +under a license and may only be used or copied in accordance +with the terms of the license. Except as permitted by such +license, no part of this software or documentation may be +reproduced, stored in a retrieval system, or transmitted in any +form or by any means without the express written consent of +Intel Corporation. + +Module Name: + + efefind.h + +Abstract: + + EFI to compile bindings + + + + +Revision History + +--*/ + +#pragma pack() + + +#ifdef __FreeBSD__ +#include +#else +// +// Basic int types of various widths +// + +#if (__STDC_VERSION__ < 199901L ) + + // No ANSI C 1999/2000 stdint.h integer width declarations + + #if _MSC_EXTENSIONS + + // Use Microsoft C compiler integer width declarations + + typedef unsigned __int64 uint64_t; + typedef __int64 int64_t; + typedef unsigned __int32 uint32_t; + typedef __int32 int32_t; + typedef unsigned __int16 uint16_t; + typedef __int16 int16_t; + typedef unsigned __int8 uint8_t; + typedef __int8 int8_t; + #else + #ifdef UNIX_LP64 + + // Use LP64 programming model from C_FLAGS for integer width declarations + + typedef unsigned long uint64_t; + typedef long int64_t; + typedef unsigned int uint32_t; + typedef int int32_t; + typedef unsigned short uint16_t; + typedef short int16_t; + typedef unsigned char uint8_t; + typedef char int8_t; + #else + + // Assume P64 programming model from C_FLAGS for integer width declarations + + typedef unsigned long long uint64_t; + typedef long long int64_t; + typedef unsigned int uint32_t; + typedef int int32_t; + typedef unsigned short uint16_t; + typedef short int16_t; + typedef unsigned char uint8_t; + typedef char int8_t; + #endif + #endif +#endif +#endif /* __FreeBSD__ */ + +// +// Basic EFI types of various widths +// + + +typedef uint64_t UINT64; +typedef int64_t INT64; +typedef uint32_t UINT32; +typedef int32_t INT32; +typedef uint16_t UINT16; +typedef int16_t INT16; +typedef uint8_t UINT8; +typedef int8_t INT8; + + +#undef VOID +#define VOID void + + +typedef int64_t INTN; +typedef uint64_t UINTN; + +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// BugBug: Code to debug +// +#define BIT63 0x8000000000000000 + +#define PLATFORM_IOBASE_ADDRESS (0xffffc000000 | BIT63) +#define PORT_TO_MEMD(_Port) (PLATFORM_IOBASE_ADDRESS | ( ( ( (_Port) & 0xfffc) << 10 ) | ( (_Port) & 0x0fff) ) ) + +// +// Macro's with casts make this much easier to use and read. +// +#define PORT_TO_MEM8D(_Port) (*(UINT8 *)(PORT_TO_MEMD(_Port))) +#define POST_CODE(_Data) (PORT_TO_MEM8D(0x80) = (_Data)) +// +// BugBug: End Debug Code!!! +//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +#define EFIERR(a) (0x8000000000000000 | a) +#define EFI_ERROR_MASK 0x8000000000000000 +#define EFIERR_OEM(a) (0xc000000000000000 | a) + +#define BAD_POINTER 0xFBFBFBFBFBFBFBFB +#define MAX_ADDRESS 0xFFFFFFFFFFFFFFFF + +#pragma intrinsic (__break) +#define BREAKPOINT() __break(0) + +// +// Pointers must be aligned to these address to function +// you will get an alignment fault if this value is less than 8 +// +#define MIN_ALIGNMENT_SIZE 8 + +#define ALIGN_VARIABLE(Value , Adjustment) \ + (UINTN) Adjustment = 0; \ + if((UINTN)Value % MIN_ALIGNMENT_SIZE) \ + (UINTN)Adjustment = MIN_ALIGNMENT_SIZE - ((UINTN)Value % MIN_ALIGNMENT_SIZE); \ + Value = (UINTN)Value + (UINTN)Adjustment + +// +// Define macros to create data structure signatures. +// + +#define EFI_SIGNATURE_16(A,B) ((A) | (B<<8)) +#define EFI_SIGNATURE_32(A,B,C,D) (EFI_SIGNATURE_16(A,B) | (EFI_SIGNATURE_16(C,D) << 16)) +#define EFI_SIGNATURE_64(A,B,C,D,E,F,G,H) (EFI_SIGNATURE_32(A,B,C,D) | ((UINT64)(EFI_SIGNATURE_32(E,F,G,H)) << 32)) + +// +// EFIAPI - prototype calling convention for EFI function pointers +// BOOTSERVICE - prototype for implementation of a boot service interface +// RUNTIMESERVICE - prototype for implementation of a runtime service interface +// RUNTIMEFUNCTION - prototype for implementation of a runtime function that is not a service +// RUNTIME_CODE - pragma macro for declaring runtime code +// + +#ifndef EFIAPI // Forces EFI calling conventions reguardless of compiler options + #if _MSC_EXTENSIONS + #define EFIAPI __cdecl // Force C calling convention for Microsoft C compiler + #else + #define EFIAPI // Substitute expresion to force C calling convention + #endif +#endif + +#define BOOTSERVICE +#define RUNTIMESERVICE +#define RUNTIMEFUNCTION + +#define RUNTIME_CODE(a) alloc_text("rtcode", a) +#define BEGIN_RUNTIME_DATA() data_seg("rtdata") +#define END_RUNTIME_DATA() data_seg() + +#define VOLATILE volatile + +// +// BugBug: Need to find out if this is portable accross compliers. +// +void __mfa (void); +#pragma intrinsic (__mfa) +#define MEMORY_FENCE() __mfa() + +#ifdef EFI_NO_INTERFACE_DECL + #define EFI_FORWARD_DECLARATION(x) + #define EFI_INTERFACE_DECL(x) +#else + #define EFI_FORWARD_DECLARATION(x) typedef struct _##x x + #define EFI_INTERFACE_DECL(x) typedef struct x +#endif + +// +// When build similiar to FW, then link everything together as +// one big module. +// + +#define EFI_DRIVER_ENTRY_POINT(InitFunction) + +#define LOAD_INTERNAL_DRIVER(_if, type, name, entry) \ + (_if)->LoadInternal(type, name, entry) +// entry(NULL, ST) + +#ifdef __FreeBSD__ +#define INTERFACE_DECL(x) struct x +#else +// +// Some compilers don't support the forward reference construct: +// typedef struct XXXXX +// +// The following macro provide a workaround for such cases. +// +#ifdef NO_INTERFACE_DECL +#define INTERFACE_DECL(x) +#else +#define INTERFACE_DECL(x) typedef struct x +#endif +#endif Index: sys/boot/efi/loader/Makefile =================================================================== --- sys/boot/efi/loader/Makefile +++ sys/boot/efi/loader/Makefile @@ -42,7 +42,7 @@ BOOT_FORTH= yes CFLAGS+= -DBOOT_FORTH CFLAGS+= -I${.CURDIR}/../../ficl -CFLAGS+= -I${.CURDIR}/../../ficl/${MACHINE} +CFLAGS+= -I${.CURDIR}/../../ficl/${MACHINE_CPUARCH} LIBFICL= ${.OBJDIR}/../../ficl/libficl.a .endif Index: sys/boot/efi/loader/arch/arm64/Makefile.inc =================================================================== --- /dev/null +++ sys/boot/efi/loader/arch/arm64/Makefile.inc @@ -0,0 +1,9 @@ +# $FreeBSD$ + +LOADER_FDT_SUPPORT=yes +SRCS+= exec.c \ + start.S + +.PATH: ${.CURDIR}/../../arm64/libarm64 +CFLAGS+=-I${.CURDIR}/../../arm64/libarm64 +SRCS+= cache.c Index: sys/boot/efi/loader/arch/arm64/exec.c =================================================================== --- /dev/null +++ sys/boot/efi/loader/arch/arm64/exec.c @@ -0,0 +1,109 @@ +/*- + * Copyright (c) 2006 Marcel Moolenaar + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include + +#include +#include +#include + +#include + +#include +#include + +#include "loader_efi.h" +#include "cache.h" + +static int elf64_exec(struct preloaded_file *amp); +static int elf64_obj_exec(struct preloaded_file *amp); + +int bi_load(char *args, vm_offset_t *modulep, vm_offset_t *kernendp); + +static struct file_format arm64_elf = { + elf64_loadfile, + elf64_exec +}; + +struct file_format *file_formats[] = { + &arm64_elf, + NULL +}; + +static int +elf64_exec(struct preloaded_file *fp) +{ + vm_offset_t modulep, kernendp; + vm_offset_t clean_addr; + size_t clean_size; + struct file_metadata *md; + EFI_STATUS status; + EFI_PHYSICAL_ADDRESS addr; + Elf_Ehdr *ehdr; + int err; + void (*entry)(vm_offset_t); + + if ((md = file_findmetadata(fp, MODINFOMD_ELFHDR)) == NULL) + return(EFTYPE); + + ehdr = (Elf_Ehdr *)&(md->md_data); + entry = efi_translate(ehdr->e_entry); + + err = bi_load(fp->f_args, &modulep, &kernendp); + if (err != 0) + return (err); + + status = BS->ExitBootServices(IH, efi_mapkey); + if (EFI_ERROR(status)) { + printf("%s: ExitBootServices() returned 0x%lx\n", __func__, + (long)status); + return (EINVAL); + } + + /* Clean D-cache under kernel area and invalidate whole I-cache */ + clean_addr = efi_translate(fp->f_addr); + clean_size = efi_translate(kernendp) - clean_addr; + + cpu_flush_dcache((void *)clean_addr, clean_size); + cpu_inval_icache(NULL, 0); + + (*entry)(modulep); + panic("exec returned"); +} + +static int +elf64_obj_exec(struct preloaded_file *fp) +{ + + printf("%s called for preloaded file %p (=%s):\n", __func__, fp, + fp->f_name); + return (ENOSYS); +} + Index: sys/boot/efi/loader/arch/arm64/ldscript.arm64 =================================================================== --- /dev/null +++ sys/boot/efi/loader/arch/arm64/ldscript.arm64 @@ -0,0 +1,80 @@ +/* $FreeBSD$ */ +/* +OUTPUT_FORMAT("elf64-aarch64-freebsd", "elf64-aarch64-freebsd", "elf64-aarch64-freebsd") +*/ +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) + *(.plt) + } =0x00300000010070000002000001000400 + . = ALIGN(16); + .data : { + *(.rodata .rodata.* .gnu.linkonce.r.*) + *(.rodata1) + *(.sdata2 .sdata2.* .gnu.linkonce.s2.*) + *(.sbss2 .sbss2.* .gnu.linkonce.sb2.*) + *(.opd) + *(.data .data.* .gnu.linkonce.d.*) + *(.data1) + *(.plabel) + + . = ALIGN(16); + __bss_start = .; + *(.sbss .sbss.* .gnu.linkonce.sb.*) + *(.scommon) + *(.dynbss) + *(.bss *.bss.*) + *(COMMON) + . = ALIGN(16); + __bss_end = .; + } + . = ALIGN(16); + set_Xcommand_set : { + __start_set_Xcommand_set = .; + *(set_Xcommand_set) + __stop_set_Xcommand_set = .; + } + . = ALIGN(16); + __gp = .; + .sdata : { + *(.got.plt .got) + *(.sdata .sdata.* .gnu.linkonce.s.*) + *(dynsbss) + *(.scommon) + } + . = ALIGN(16); + .dynamic : { *(.dynamic) } + . = ALIGN(16); + .rela.dyn : { + *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*) + *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*) + *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*) + *(.rela.got) + *(.rela.sdata .rela.sdata.* .rela.gnu.linkonce.s.*) + *(.rela.sbss .rela.sbss.* .rela.gnu.linkonce.sb.*) + *(.rela.sdata2 .rela.sdata2.* .rela.gnu.linkonce.s2.*) + *(.rela.sbss2 .rela.sbss2.* .rela.gnu.linkonce.sb2.*) + *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*) + *(.rela.plt) + *(.relset_*) + *(.rela.dyn .rela.dyn.*) + } + . = ALIGN(16); + .reloc : { *(.reloc) } + . = ALIGN(16); + .dynsym : { *(.dynsym) } + _edata = .; + + /* Unused sections */ + .dynstr : { *(.dynstr) } + .hash : { *(.hash) } +} Index: sys/boot/efi/loader/arch/arm64/start.S =================================================================== --- /dev/null +++ sys/boot/efi/loader/arch/arm64/start.S @@ -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 _reloc + + ldp x0, x1, [sp], #16 + + bl efi_main + +1: b 1b Index: sys/boot/efi/loader/copy.c =================================================================== --- sys/boot/efi/loader/copy.c +++ sys/boot/efi/loader/copy.c @@ -61,8 +61,14 @@ } staging_end = staging + STAGE_PAGES * 4096; -#ifdef __arm__ - /* Round the kernel load address to a 2MiB value */ +#if defined(__aarch64__) || defined(__arm__) + /* + * Round the kernel load address to a 2MiB value. This is needed + * because the kernel builds a page table based on where it has + * been loaded in physical address space. As the kernel will use + * either a 1MiB or 2MiB page for this we need to make sure it + * is correctly aligned for both cases. + */ staging = roundup2(staging, 2 * 1024 * 1024); #endif