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 EFI_KIMG_PREFERRED_ADDRESS, 39 efi_get_kimg_min_align(), 0x0); 40 41 *image_addr = kernel_addr; 42 *image_size = kernel_asize; 43 44 return status; 45 } 46 47 struct exit_boot_struct { 48 efi_memory_desc_t *runtime_map; 49 int runtime_entry_count; 50 }; 51 52 static efi_status_t exit_boot_func(struct efi_boot_memmap *map, void *priv) 53 { 54 struct exit_boot_struct *p = priv; 55 56 /* 57 * Update the memory map with virtual addresses. The function will also 58 * populate @runtime_map with copies of just the EFI_MEMORY_RUNTIME 59 * entries so that we can pass it straight to SetVirtualAddressMap() 60 */ 61 efi_get_virtmap(map->map, map->map_size, map->desc_size, 62 p->runtime_map, &p->runtime_entry_count); 63 64 return EFI_SUCCESS; 65 } 66 67 efi_status_t efi_boot_kernel(void *handle, efi_loaded_image_t *image, 68 unsigned long kernel_addr, char *cmdline_ptr) 69 { 70 kernel_entry_t real_kernel_entry; 71 struct exit_boot_struct priv; 72 unsigned long desc_size; 73 efi_status_t status; 74 u32 desc_ver; 75 76 status = efi_alloc_virtmap(&priv.runtime_map, &desc_size, &desc_ver); 77 if (status != EFI_SUCCESS) { 78 efi_err("Unable to retrieve UEFI memory map.\n"); 79 return status; 80 } 81 82 efi_info("Exiting boot services\n"); 83 84 efi_novamap = false; 85 status = efi_exit_boot_services(handle, &priv, exit_boot_func); 86 if (status != EFI_SUCCESS) 87 return status; 88 89 /* Install the new virtual address map */ 90 efi_rt_call(set_virtual_address_map, 91 priv.runtime_entry_count * desc_size, desc_size, 92 desc_ver, priv.runtime_map); 93 94 /* Config Direct Mapping */ 95 csr_write64(CSR_DMW0_INIT, LOONGARCH_CSR_DMWIN0); 96 csr_write64(CSR_DMW1_INIT, LOONGARCH_CSR_DMWIN1); 97 98 real_kernel_entry = (kernel_entry_t) 99 ((unsigned long)&kernel_entry - kernel_addr + VMLINUX_LOAD_ADDRESS); 100 101 real_kernel_entry(true, (unsigned long)cmdline_ptr, 102 (unsigned long)efi_system_table); 103 } 104