diff options
author | Ard Biesheuvel <ardb@kernel.org> | 2022-11-18 09:13:57 +0100 |
---|---|---|
committer | Ard Biesheuvel <ardb@kernel.org> | 2022-11-18 09:13:57 +0100 |
commit | 977122898ea5e3d568014ec9fe089cfba7c73e76 (patch) | |
tree | 19a43e45225aa0a20d72e841cc5c37e45f5a76af /drivers/firmware/efi/libstub/loongarch-stub.c | |
parent | 094226ad94f471a9f19e8f8e7140a09c2625abaa (diff) | |
parent | c51e97e7f1295d3cf42682565506047f08dfc99b (diff) |
Merge tag 'efi-zboot-direct-for-v6.2' into efi/next
Diffstat (limited to 'drivers/firmware/efi/libstub/loongarch-stub.c')
-rw-r--r-- | drivers/firmware/efi/libstub/loongarch-stub.c | 89 |
1 files changed, 20 insertions, 69 deletions
diff --git a/drivers/firmware/efi/libstub/loongarch-stub.c b/drivers/firmware/efi/libstub/loongarch-stub.c index 32329f2a92f9..eee7ed43cdfb 100644 --- a/drivers/firmware/efi/libstub/loongarch-stub.c +++ b/drivers/firmware/efi/libstub/loongarch-stub.c @@ -9,18 +9,10 @@ #include <asm/addrspace.h> #include "efistub.h" -typedef void __noreturn (*kernel_entry_t)(bool efi, unsigned long cmdline, - unsigned long systab); - extern int kernel_asize; extern int kernel_fsize; extern int kernel_offset; -extern kernel_entry_t kernel_entry; - -efi_status_t check_platform_features(void) -{ - return EFI_SUCCESS; -} +extern int kernel_entry; efi_status_t handle_kernel_image(unsigned long *image_addr, unsigned long *image_size, @@ -29,74 +21,33 @@ efi_status_t handle_kernel_image(unsigned long *image_addr, efi_loaded_image_t *image, efi_handle_t image_handle) { + int nr_pages = round_up(kernel_asize, EFI_ALLOC_ALIGN) / EFI_PAGE_SIZE; + efi_physical_addr_t kernel_addr = EFI_KIMG_PREFERRED_ADDRESS; efi_status_t status; - unsigned long kernel_addr = 0; - - kernel_addr = (unsigned long)&kernel_offset - kernel_offset; - - status = efi_relocate_kernel(&kernel_addr, kernel_fsize, kernel_asize, - PHYSADDR(VMLINUX_LOAD_ADDRESS), SZ_2M, 0x0); - - *image_addr = kernel_addr; - *image_size = kernel_asize; - - return status; -} - -struct exit_boot_struct { - efi_memory_desc_t *runtime_map; - int runtime_entry_count; -}; - -static efi_status_t exit_boot_func(struct efi_boot_memmap *map, void *priv) -{ - struct exit_boot_struct *p = priv; /* - * Update the memory map with virtual addresses. The function will also - * populate @runtime_map with copies of just the EFI_MEMORY_RUNTIME - * entries so that we can pass it straight to SetVirtualAddressMap() + * Allocate space for the kernel image at the preferred offset. This is + * the only location in memory from where we can execute the image, so + * no point in falling back to another allocation. */ - efi_get_virtmap(map->map, map->map_size, map->desc_size, - p->runtime_map, &p->runtime_entry_count); - - return EFI_SUCCESS; -} - -efi_status_t efi_boot_kernel(void *handle, efi_loaded_image_t *image, - unsigned long kernel_addr, char *cmdline_ptr) -{ - kernel_entry_t real_kernel_entry; - struct exit_boot_struct priv; - unsigned long desc_size; - efi_status_t status; - u32 desc_ver; - - status = efi_alloc_virtmap(&priv.runtime_map, &desc_size, &desc_ver); - if (status != EFI_SUCCESS) { - efi_err("Unable to retrieve UEFI memory map.\n"); - return status; - } - - efi_info("Exiting boot services\n"); - - efi_novamap = false; - status = efi_exit_boot_services(handle, &priv, exit_boot_func); + status = efi_bs_call(allocate_pages, EFI_ALLOCATE_ADDRESS, + EFI_LOADER_DATA, nr_pages, &kernel_addr); if (status != EFI_SUCCESS) return status; - /* Install the new virtual address map */ - efi_rt_call(set_virtual_address_map, - priv.runtime_entry_count * desc_size, desc_size, - desc_ver, priv.runtime_map); + *image_addr = EFI_KIMG_PREFERRED_ADDRESS; + *image_size = kernel_asize; - /* Config Direct Mapping */ - csr_write64(CSR_DMW0_INIT, LOONGARCH_CSR_DMWIN0); - csr_write64(CSR_DMW1_INIT, LOONGARCH_CSR_DMWIN1); + memcpy((void *)EFI_KIMG_PREFERRED_ADDRESS, + (void *)&kernel_offset - kernel_offset, + kernel_fsize); - real_kernel_entry = (kernel_entry_t) - ((unsigned long)&kernel_entry - kernel_addr + VMLINUX_LOAD_ADDRESS); + return status; +} + +unsigned long kernel_entry_address(void) +{ + unsigned long base = (unsigned long)&kernel_offset - kernel_offset; - real_kernel_entry(true, (unsigned long)cmdline_ptr, - (unsigned long)efi_system_table); + return (unsigned long)&kernel_entry - base + VMLINUX_LOAD_ADDRESS; } |