181a0bc39SRoy Franz /* 281a0bc39SRoy Franz * Copyright (C) 2013 Linaro Ltd; <roy.franz@linaro.org> 381a0bc39SRoy Franz * 481a0bc39SRoy Franz * This program is free software; you can redistribute it and/or modify 581a0bc39SRoy Franz * it under the terms of the GNU General Public License version 2 as 681a0bc39SRoy Franz * published by the Free Software Foundation. 781a0bc39SRoy Franz * 881a0bc39SRoy Franz */ 981a0bc39SRoy Franz #include <linux/efi.h> 1081a0bc39SRoy Franz #include <asm/efi.h> 1181a0bc39SRoy Franz 122ec0f0a3SArd Biesheuvel efi_status_t check_platform_features(efi_system_table_t *sys_table_arg) 132ec0f0a3SArd Biesheuvel { 142ec0f0a3SArd Biesheuvel int block; 152ec0f0a3SArd Biesheuvel 162ec0f0a3SArd Biesheuvel /* non-LPAE kernels can run anywhere */ 172ec0f0a3SArd Biesheuvel if (!IS_ENABLED(CONFIG_ARM_LPAE)) 182ec0f0a3SArd Biesheuvel return EFI_SUCCESS; 192ec0f0a3SArd Biesheuvel 202ec0f0a3SArd Biesheuvel /* LPAE kernels need compatible hardware */ 212ec0f0a3SArd Biesheuvel block = cpuid_feature_extract(CPUID_EXT_MMFR0, 0); 222ec0f0a3SArd Biesheuvel if (block < 5) { 232ec0f0a3SArd Biesheuvel pr_efi_err(sys_table_arg, "This LPAE kernel is not supported by your CPU\n"); 242ec0f0a3SArd Biesheuvel return EFI_UNSUPPORTED; 252ec0f0a3SArd Biesheuvel } 262ec0f0a3SArd Biesheuvel return EFI_SUCCESS; 272ec0f0a3SArd Biesheuvel } 282ec0f0a3SArd Biesheuvel 2981a0bc39SRoy Franz efi_status_t handle_kernel_image(efi_system_table_t *sys_table, 3081a0bc39SRoy Franz unsigned long *image_addr, 3181a0bc39SRoy Franz unsigned long *image_size, 3281a0bc39SRoy Franz unsigned long *reserve_addr, 3381a0bc39SRoy Franz unsigned long *reserve_size, 3481a0bc39SRoy Franz unsigned long dram_base, 3581a0bc39SRoy Franz efi_loaded_image_t *image) 3681a0bc39SRoy Franz { 3781a0bc39SRoy Franz unsigned long nr_pages; 3881a0bc39SRoy Franz efi_status_t status; 3981a0bc39SRoy Franz /* Use alloc_addr to tranlsate between types */ 4081a0bc39SRoy Franz efi_physical_addr_t alloc_addr; 4181a0bc39SRoy Franz 4281a0bc39SRoy Franz /* 4381a0bc39SRoy Franz * Verify that the DRAM base address is compatible with the ARM 4481a0bc39SRoy Franz * boot protocol, which determines the base of DRAM by masking 4581a0bc39SRoy Franz * off the low 27 bits of the address at which the zImage is 4681a0bc39SRoy Franz * loaded. These assumptions are made by the decompressor, 4781a0bc39SRoy Franz * before any memory map is available. 4881a0bc39SRoy Franz */ 4981a0bc39SRoy Franz dram_base = round_up(dram_base, SZ_128M); 5081a0bc39SRoy Franz 5181a0bc39SRoy Franz /* 5281a0bc39SRoy Franz * Reserve memory for the uncompressed kernel image. This is 5381a0bc39SRoy Franz * all that prevents any future allocations from conflicting 5481a0bc39SRoy Franz * with the kernel. Since we can't tell from the compressed 5581a0bc39SRoy Franz * image how much DRAM the kernel actually uses (due to BSS 5681a0bc39SRoy Franz * size uncertainty) we allocate the maximum possible size. 5781a0bc39SRoy Franz * Do this very early, as prints can cause memory allocations 5881a0bc39SRoy Franz * that may conflict with this. 5981a0bc39SRoy Franz */ 6081a0bc39SRoy Franz alloc_addr = dram_base; 6181a0bc39SRoy Franz *reserve_size = MAX_UNCOMP_KERNEL_SIZE; 6281a0bc39SRoy Franz nr_pages = round_up(*reserve_size, EFI_PAGE_SIZE) / EFI_PAGE_SIZE; 6381a0bc39SRoy Franz status = sys_table->boottime->allocate_pages(EFI_ALLOCATE_ADDRESS, 6481a0bc39SRoy Franz EFI_LOADER_DATA, 6581a0bc39SRoy Franz nr_pages, &alloc_addr); 6681a0bc39SRoy Franz if (status != EFI_SUCCESS) { 6781a0bc39SRoy Franz *reserve_size = 0; 6881a0bc39SRoy Franz pr_efi_err(sys_table, "Unable to allocate memory for uncompressed kernel.\n"); 6981a0bc39SRoy Franz return status; 7081a0bc39SRoy Franz } 7181a0bc39SRoy Franz *reserve_addr = alloc_addr; 7281a0bc39SRoy Franz 7381a0bc39SRoy Franz /* 7481a0bc39SRoy Franz * Relocate the zImage, so that it appears in the lowest 128 MB 7581a0bc39SRoy Franz * memory window. 7681a0bc39SRoy Franz */ 7781a0bc39SRoy Franz *image_size = image->image_size; 7881a0bc39SRoy Franz status = efi_relocate_kernel(sys_table, image_addr, *image_size, 7981a0bc39SRoy Franz *image_size, 8081a0bc39SRoy Franz dram_base + MAX_UNCOMP_KERNEL_SIZE, 0); 8181a0bc39SRoy Franz if (status != EFI_SUCCESS) { 8281a0bc39SRoy Franz pr_efi_err(sys_table, "Failed to relocate kernel.\n"); 8381a0bc39SRoy Franz efi_free(sys_table, *reserve_size, *reserve_addr); 8481a0bc39SRoy Franz *reserve_size = 0; 8581a0bc39SRoy Franz return status; 8681a0bc39SRoy Franz } 8781a0bc39SRoy Franz 8881a0bc39SRoy Franz /* 8981a0bc39SRoy Franz * Check to see if we were able to allocate memory low enough 9081a0bc39SRoy Franz * in memory. The kernel determines the base of DRAM from the 9181a0bc39SRoy Franz * address at which the zImage is loaded. 9281a0bc39SRoy Franz */ 9381a0bc39SRoy Franz if (*image_addr + *image_size > dram_base + ZIMAGE_OFFSET_LIMIT) { 9481a0bc39SRoy Franz pr_efi_err(sys_table, "Failed to relocate kernel, no low memory available.\n"); 9581a0bc39SRoy Franz efi_free(sys_table, *reserve_size, *reserve_addr); 9681a0bc39SRoy Franz *reserve_size = 0; 9781a0bc39SRoy Franz efi_free(sys_table, *image_size, *image_addr); 9881a0bc39SRoy Franz *image_size = 0; 9981a0bc39SRoy Franz return EFI_LOAD_ERROR; 10081a0bc39SRoy Franz } 10181a0bc39SRoy Franz return EFI_SUCCESS; 10281a0bc39SRoy Franz } 103