1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Author: Yun Liu <liuyun@loongson.cn> 4 * Huacai Chen <chenhuacai@loongson.cn> 5 * Copyright (C) 2020-2022 Loongson Technology Corporation Limited 6 */ 7 8 #include <asm/efi.h> 9 #include <asm/addrspace.h> 10 #include "efistub.h" 11 12 typedef void __noreturn (*kernel_entry_t)(bool efi, unsigned long cmdline, 13 unsigned long systab); 14 15 extern int kernel_asize; 16 extern int kernel_fsize; 17 extern int kernel_offset; 18 extern kernel_entry_t kernel_entry; 19 20 efi_status_t check_platform_features(void) 21 { 22 return EFI_SUCCESS; 23 } 24 25 efi_status_t handle_kernel_image(unsigned long *image_addr, 26 unsigned long *image_size, 27 unsigned long *reserve_addr, 28 unsigned long *reserve_size, 29 efi_loaded_image_t *image, 30 efi_handle_t image_handle) 31 { 32 efi_status_t status; 33 unsigned long kernel_addr = 0; 34 35 kernel_addr = (unsigned long)&kernel_offset - kernel_offset; 36 37 status = efi_relocate_kernel(&kernel_addr, kernel_fsize, kernel_asize, 38 PHYSADDR(VMLINUX_LOAD_ADDRESS), SZ_2M, 0x0); 39 40 *image_addr = kernel_addr; 41 *image_size = kernel_asize; 42 43 return status; 44 } 45 46 struct exit_boot_struct { 47 efi_memory_desc_t *runtime_map; 48 int runtime_entry_count; 49 }; 50 51 static efi_status_t exit_boot_func(struct efi_boot_memmap *map, void *priv) 52 { 53 struct exit_boot_struct *p = priv; 54 55 /* 56 * Update the memory map with virtual addresses. The function will also 57 * populate @runtime_map with copies of just the EFI_MEMORY_RUNTIME 58 * entries so that we can pass it straight to SetVirtualAddressMap() 59 */ 60 efi_get_virtmap(map->map, map->map_size, map->desc_size, 61 p->runtime_map, &p->runtime_entry_count); 62 63 return EFI_SUCCESS; 64 } 65 66 efi_status_t efi_boot_kernel(void *handle, efi_loaded_image_t *image, 67 unsigned long kernel_addr, char *cmdline_ptr) 68 { 69 kernel_entry_t real_kernel_entry; 70 struct exit_boot_struct priv; 71 unsigned long desc_size; 72 efi_status_t status; 73 u32 desc_ver; 74 75 status = efi_alloc_virtmap(&priv.runtime_map, &desc_size, &desc_ver); 76 if (status != EFI_SUCCESS) { 77 efi_err("Unable to retrieve UEFI memory map.\n"); 78 return status; 79 } 80 81 efi_info("Exiting boot services\n"); 82 83 efi_novamap = false; 84 status = efi_exit_boot_services(handle, &priv, exit_boot_func); 85 if (status != EFI_SUCCESS) 86 return status; 87 88 /* Install the new virtual address map */ 89 efi_rt_call(set_virtual_address_map, 90 priv.runtime_entry_count * desc_size, desc_size, 91 desc_ver, priv.runtime_map); 92 93 /* Config Direct Mapping */ 94 csr_write64(CSR_DMW0_INIT, LOONGARCH_CSR_DMWIN0); 95 csr_write64(CSR_DMW1_INIT, LOONGARCH_CSR_DMWIN1); 96 97 real_kernel_entry = (kernel_entry_t) 98 ((unsigned long)&kernel_entry - kernel_addr + VMLINUX_LOAD_ADDRESS); 99 100 real_kernel_entry(true, (unsigned long)cmdline_ptr, 101 (unsigned long)efi_system_table); 102 } 103