18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Author: Yun Liu <liuyun@loongson.cn> 48c2ecf20Sopenharmony_ci * Huacai Chen <chenhuacai@loongson.cn> 58c2ecf20Sopenharmony_ci * Copyright (C) 2020-2022 Loongson Technology Corporation Limited 68c2ecf20Sopenharmony_ci */ 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci#include <asm/efi.h> 98c2ecf20Sopenharmony_ci#include <asm/addrspace.h> 108c2ecf20Sopenharmony_ci#include "efistub.h" 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_ci#define BOOT_HEAP_SIZE 0x400000 138c2ecf20Sopenharmony_ci 148c2ecf20Sopenharmony_citypedef void __noreturn (*kernel_entry_t)(bool efi, unsigned long cmdline, 158c2ecf20Sopenharmony_ci unsigned long systab, long kdump_reloc_offset); 168c2ecf20Sopenharmony_ci 178c2ecf20Sopenharmony_ciextern long kernel_entaddr; 188c2ecf20Sopenharmony_ciextern void decompress_kernel(unsigned long boot_heap_start, long kdump_reloc_offset); 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_cistatic unsigned char efi_heap[BOOT_HEAP_SIZE]; 218c2ecf20Sopenharmony_cistatic efi_guid_t screen_info_guid = LINUX_EFI_ARM_SCREEN_INFO_TABLE_GUID; 228c2ecf20Sopenharmony_cistatic kernel_entry_t kernel_entry; 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_cistruct screen_info *alloc_screen_info(void) 258c2ecf20Sopenharmony_ci{ 268c2ecf20Sopenharmony_ci efi_status_t status; 278c2ecf20Sopenharmony_ci struct screen_info *si; 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_ci status = efi_bs_call(allocate_pool, 308c2ecf20Sopenharmony_ci EFI_RUNTIME_SERVICES_DATA, sizeof(*si), (void **)&si); 318c2ecf20Sopenharmony_ci if (status != EFI_SUCCESS) 328c2ecf20Sopenharmony_ci return NULL; 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_ci memset(si, 0, sizeof(*si)); 358c2ecf20Sopenharmony_ci 368c2ecf20Sopenharmony_ci status = efi_bs_call(install_configuration_table, &screen_info_guid, si); 378c2ecf20Sopenharmony_ci if (status == EFI_SUCCESS) 388c2ecf20Sopenharmony_ci return si; 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_ci efi_bs_call(free_pool, si); 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_ci return NULL; 438c2ecf20Sopenharmony_ci} 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_civoid free_screen_info(struct screen_info *si) 468c2ecf20Sopenharmony_ci{ 478c2ecf20Sopenharmony_ci if (!si) 488c2ecf20Sopenharmony_ci return; 498c2ecf20Sopenharmony_ci 508c2ecf20Sopenharmony_ci efi_bs_call(install_configuration_table, &screen_info_guid, NULL); 518c2ecf20Sopenharmony_ci efi_bs_call(free_pool, si); 528c2ecf20Sopenharmony_ci} 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_ciefi_status_t check_platform_features(void) 558c2ecf20Sopenharmony_ci{ 568c2ecf20Sopenharmony_ci return EFI_SUCCESS; 578c2ecf20Sopenharmony_ci} 588c2ecf20Sopenharmony_ci 598c2ecf20Sopenharmony_ciefi_status_t handle_kernel_image(unsigned long *image_addr, 608c2ecf20Sopenharmony_ci unsigned long *image_size, 618c2ecf20Sopenharmony_ci unsigned long *reserve_addr, 628c2ecf20Sopenharmony_ci unsigned long *reserve_size, 638c2ecf20Sopenharmony_ci efi_loaded_image_t *image) 648c2ecf20Sopenharmony_ci{ 658c2ecf20Sopenharmony_ci /* Config Direct Mapping */ 668c2ecf20Sopenharmony_ci csr_write64(CSR_DMW0_INIT, LOONGARCH_CSR_DMWIN0); 678c2ecf20Sopenharmony_ci csr_write64(CSR_DMW1_INIT, LOONGARCH_CSR_DMWIN1); 688c2ecf20Sopenharmony_ci 698c2ecf20Sopenharmony_ci decompress_kernel((unsigned long)efi_heap, 0); 708c2ecf20Sopenharmony_ci kernel_entry = (kernel_entry_t)kernel_entaddr; 718c2ecf20Sopenharmony_ci 728c2ecf20Sopenharmony_ci return EFI_SUCCESS; 738c2ecf20Sopenharmony_ci} 748c2ecf20Sopenharmony_ci 758c2ecf20Sopenharmony_cistruct exit_boot_struct { 768c2ecf20Sopenharmony_ci efi_memory_desc_t *runtime_map; 778c2ecf20Sopenharmony_ci int runtime_entry_count; 788c2ecf20Sopenharmony_ci}; 798c2ecf20Sopenharmony_ci 808c2ecf20Sopenharmony_cistatic efi_status_t exit_boot_func(struct efi_boot_memmap *map, void *priv) 818c2ecf20Sopenharmony_ci{ 828c2ecf20Sopenharmony_ci struct exit_boot_struct *p = priv; 838c2ecf20Sopenharmony_ci 848c2ecf20Sopenharmony_ci /* 858c2ecf20Sopenharmony_ci * Update the memory map with virtual addresses. The function will also 868c2ecf20Sopenharmony_ci * populate @runtime_map with copies of just the EFI_MEMORY_RUNTIME 878c2ecf20Sopenharmony_ci * entries so that we can pass it straight to SetVirtualAddressMap() 888c2ecf20Sopenharmony_ci */ 898c2ecf20Sopenharmony_ci efi_get_virtmap(map->map, map->map_size, map->desc_size, 908c2ecf20Sopenharmony_ci p->runtime_map, &p->runtime_entry_count); 918c2ecf20Sopenharmony_ci 928c2ecf20Sopenharmony_ci return EFI_SUCCESS; 938c2ecf20Sopenharmony_ci} 948c2ecf20Sopenharmony_ci 958c2ecf20Sopenharmony_ciefi_status_t efi_boot_kernel(void *handle, efi_loaded_image_t *image, 968c2ecf20Sopenharmony_ci unsigned long kernel_addr, char *cmdline_ptr) 978c2ecf20Sopenharmony_ci{ 988c2ecf20Sopenharmony_ci struct exit_boot_struct priv; 998c2ecf20Sopenharmony_ci unsigned long desc_size; 1008c2ecf20Sopenharmony_ci efi_status_t status; 1018c2ecf20Sopenharmony_ci u32 desc_ver; 1028c2ecf20Sopenharmony_ci 1038c2ecf20Sopenharmony_ci status = efi_alloc_virtmap(&priv.runtime_map, &desc_size, &desc_ver); 1048c2ecf20Sopenharmony_ci if (status != EFI_SUCCESS) { 1058c2ecf20Sopenharmony_ci efi_err("Unable to retrieve UEFI memory map.\n"); 1068c2ecf20Sopenharmony_ci return status; 1078c2ecf20Sopenharmony_ci } 1088c2ecf20Sopenharmony_ci 1098c2ecf20Sopenharmony_ci efi_info("Exiting boot services\n"); 1108c2ecf20Sopenharmony_ci 1118c2ecf20Sopenharmony_ci efi_novamap = false; 1128c2ecf20Sopenharmony_ci status = efi_exit_boot_services(handle, &priv, exit_boot_func); 1138c2ecf20Sopenharmony_ci if (status != EFI_SUCCESS) 1148c2ecf20Sopenharmony_ci return status; 1158c2ecf20Sopenharmony_ci 1168c2ecf20Sopenharmony_ci /* Install the new virtual address map */ 1178c2ecf20Sopenharmony_ci efi_rt_call(set_virtual_address_map, 1188c2ecf20Sopenharmony_ci priv.runtime_entry_count * desc_size, desc_size, 1198c2ecf20Sopenharmony_ci desc_ver, priv.runtime_map); 1208c2ecf20Sopenharmony_ci 1218c2ecf20Sopenharmony_ci kernel_entry(true, (unsigned long)cmdline_ptr, (unsigned long)efi_system_table, 0); 1228c2ecf20Sopenharmony_ci} 123