14febfb8dSArd Biesheuvel // SPDX-License-Identifier: GPL-2.0 2bf457786SArd Biesheuvel /* 3bf457786SArd Biesheuvel * Copyright (C) 2013, 2014 Linaro Ltd; <roy.franz@linaro.org> 4bf457786SArd Biesheuvel * 5bf457786SArd Biesheuvel * This file implements the EFI boot stub for the arm64 kernel. 6bf457786SArd Biesheuvel * Adapted from ARM version by Mark Salter <msalter@redhat.com> 7bf457786SArd Biesheuvel */ 80426a4e6SArd Biesheuvel 90426a4e6SArd Biesheuvel 10bf457786SArd Biesheuvel #include <linux/efi.h> 11bf457786SArd Biesheuvel #include <asm/efi.h> 12170976bcSMark Rutland #include <asm/memory.h> 136f05106eSArd Biesheuvel #include <asm/sections.h> 1442b55734SArd Biesheuvel #include <asm/sysreg.h> 15bf457786SArd Biesheuvel 162b5fe07aSArd Biesheuvel #include "efistub.h" 172b5fe07aSArd Biesheuvel 18cd33a5c1SArd Biesheuvel efi_status_t check_platform_features(void) 1942b55734SArd Biesheuvel { 2042b55734SArd Biesheuvel u64 tg; 2142b55734SArd Biesheuvel 2242b55734SArd Biesheuvel /* UEFI mandates support for 4 KB granularity, no need to check */ 2342b55734SArd Biesheuvel if (IS_ENABLED(CONFIG_ARM64_4K_PAGES)) 2442b55734SArd Biesheuvel return EFI_SUCCESS; 2542b55734SArd Biesheuvel 2642b55734SArd Biesheuvel tg = (read_cpuid(ID_AA64MMFR0_EL1) >> ID_AA64MMFR0_TGRAN_SHIFT) & 0xf; 27*26f55386SJames Morse if (tg < ID_AA64MMFR0_TGRAN_SUPPORTED_MIN || tg > ID_AA64MMFR0_TGRAN_SUPPORTED_MAX) { 2842b55734SArd Biesheuvel if (IS_ENABLED(CONFIG_ARM64_64K_PAGES)) 29793473c2SArvind Sankar efi_err("This 64 KB granular kernel is not supported by your CPU\n"); 3042b55734SArd Biesheuvel else 31793473c2SArvind Sankar efi_err("This 16 KB granular kernel is not supported by your CPU\n"); 3242b55734SArd Biesheuvel return EFI_UNSUPPORTED; 3342b55734SArd Biesheuvel } 3442b55734SArd Biesheuvel return EFI_SUCCESS; 3542b55734SArd Biesheuvel } 36bf457786SArd Biesheuvel 3782046702SArd Biesheuvel /* 387c116db2SWill Deacon * Although relocatable kernels can fix up the misalignment with respect to 397c116db2SWill Deacon * MIN_KIMG_ALIGN, the resulting virtual text addresses are subtly out of 407c116db2SWill Deacon * sync with those recorded in the vmlinux when kaslr is disabled but the 417c116db2SWill Deacon * image required relocation anyway. Therefore retain 2M alignment unless 427c116db2SWill Deacon * KASLR is in use. 4382046702SArd Biesheuvel */ 447c116db2SWill Deacon static u64 min_kimg_align(void) 457c116db2SWill Deacon { 467c116db2SWill Deacon return efi_nokaslr ? MIN_KIMG_ALIGN : EFI_KIMG_ALIGN; 477c116db2SWill Deacon } 4882046702SArd Biesheuvel 49cd33a5c1SArd Biesheuvel efi_status_t handle_kernel_image(unsigned long *image_addr, 50bf457786SArd Biesheuvel unsigned long *image_size, 51bf457786SArd Biesheuvel unsigned long *reserve_addr, 52bf457786SArd Biesheuvel unsigned long *reserve_size, 53bf457786SArd Biesheuvel efi_loaded_image_t *image) 54bf457786SArd Biesheuvel { 55bf457786SArd Biesheuvel efi_status_t status; 56bf457786SArd Biesheuvel unsigned long kernel_size, kernel_memsize = 0; 575d12da9dSArd Biesheuvel u32 phys_seed = 0; 582b5fe07aSArd Biesheuvel 592b5fe07aSArd Biesheuvel if (IS_ENABLED(CONFIG_RANDOMIZE_BASE)) { 60980771f6SArd Biesheuvel if (!efi_nokaslr) { 61cd33a5c1SArd Biesheuvel status = efi_get_random_bytes(sizeof(phys_seed), 622b5fe07aSArd Biesheuvel (u8 *)&phys_seed); 632b5fe07aSArd Biesheuvel if (status == EFI_NOT_FOUND) { 641c761ee9SMark Brown efi_info("EFI_RNG_PROTOCOL unavailable\n"); 65d32de913SArd Biesheuvel efi_nokaslr = true; 662b5fe07aSArd Biesheuvel } else if (status != EFI_SUCCESS) { 671c761ee9SMark Brown efi_err("efi_get_random_bytes() failed (0x%lx)\n", 68d32de913SArd Biesheuvel status); 69d32de913SArd Biesheuvel efi_nokaslr = true; 702b5fe07aSArd Biesheuvel } 712b5fe07aSArd Biesheuvel } else { 72793473c2SArvind Sankar efi_info("KASLR disabled on kernel command line\n"); 732b5fe07aSArd Biesheuvel } 742b5fe07aSArd Biesheuvel } 752dc10ad8SLinus Torvalds 7682046702SArd Biesheuvel if (image->image_base != _text) 77793473c2SArvind Sankar efi_err("FIRMWARE BUG: efi_loaded_image_t::image_base has bogus value\n"); 78bf457786SArd Biesheuvel 79bf457786SArd Biesheuvel kernel_size = _edata - _text; 80bf457786SArd Biesheuvel kernel_memsize = kernel_size + (_end - _edata); 81120dc60dSArd Biesheuvel *reserve_size = kernel_memsize; 82bf457786SArd Biesheuvel 832b5fe07aSArd Biesheuvel if (IS_ENABLED(CONFIG_RANDOMIZE_BASE) && phys_seed != 0) { 84bf457786SArd Biesheuvel /* 852b5fe07aSArd Biesheuvel * If KASLR is enabled, and we have some randomness available, 862b5fe07aSArd Biesheuvel * locate the kernel at a randomized offset in physical memory. 872b5fe07aSArd Biesheuvel */ 887c116db2SWill Deacon status = efi_random_alloc(*reserve_size, min_kimg_align(), 895d12da9dSArd Biesheuvel reserve_addr, phys_seed); 902b5fe07aSArd Biesheuvel } else { 9182046702SArd Biesheuvel status = EFI_OUT_OF_RESOURCES; 922b5fe07aSArd Biesheuvel } 932b5fe07aSArd Biesheuvel 94bf457786SArd Biesheuvel if (status != EFI_SUCCESS) { 95120dc60dSArd Biesheuvel if (IS_ALIGNED((u64)_text, min_kimg_align())) { 9682046702SArd Biesheuvel /* 9782046702SArd Biesheuvel * Just execute from wherever we were loaded by the 9882046702SArd Biesheuvel * UEFI PE/COFF loader if the alignment is suitable. 9982046702SArd Biesheuvel */ 10082046702SArd Biesheuvel *image_addr = (u64)_text; 10182046702SArd Biesheuvel *reserve_size = 0; 10282046702SArd Biesheuvel return EFI_SUCCESS; 10382046702SArd Biesheuvel } 10482046702SArd Biesheuvel 105e71356feSArd Biesheuvel status = efi_allocate_pages_aligned(*reserve_size, reserve_addr, 1067c116db2SWill Deacon ULONG_MAX, min_kimg_align()); 107bf457786SArd Biesheuvel 108bf457786SArd Biesheuvel if (status != EFI_SUCCESS) { 109793473c2SArvind Sankar efi_err("Failed to relocate kernel\n"); 1102b5fe07aSArd Biesheuvel *reserve_size = 0; 111bf457786SArd Biesheuvel return status; 112bf457786SArd Biesheuvel } 113bf457786SArd Biesheuvel } 114c2136dceSArd Biesheuvel 115120dc60dSArd Biesheuvel *image_addr = *reserve_addr; 116c2136dceSArd Biesheuvel memcpy((void *)*image_addr, _text, kernel_size); 117bf457786SArd Biesheuvel 118bf457786SArd Biesheuvel return EFI_SUCCESS; 119bf457786SArd Biesheuvel } 120