1ead384d9SHuacai Chen // SPDX-License-Identifier: GPL-2.0 2ead384d9SHuacai Chen /* 3ead384d9SHuacai Chen * Author: Yun Liu <liuyun@loongson.cn> 4ead384d9SHuacai Chen * Huacai Chen <chenhuacai@loongson.cn> 5ead384d9SHuacai Chen * Copyright (C) 2020-2022 Loongson Technology Corporation Limited 6ead384d9SHuacai Chen */ 7ead384d9SHuacai Chen 8ead384d9SHuacai Chen #include <asm/efi.h> 9ead384d9SHuacai Chen #include <asm/addrspace.h> 10ead384d9SHuacai Chen #include "efistub.h" 11ead384d9SHuacai Chen 12ead384d9SHuacai Chen extern int kernel_asize; 13ead384d9SHuacai Chen extern int kernel_fsize; 14ead384d9SHuacai Chen extern int kernel_offset; 15*d729b554SArd Biesheuvel extern int kernel_entry; 16ead384d9SHuacai Chen 17ead384d9SHuacai Chen efi_status_t handle_kernel_image(unsigned long *image_addr, 18ead384d9SHuacai Chen unsigned long *image_size, 19ead384d9SHuacai Chen unsigned long *reserve_addr, 20ead384d9SHuacai Chen unsigned long *reserve_size, 21ead384d9SHuacai Chen efi_loaded_image_t *image, 22ead384d9SHuacai Chen efi_handle_t image_handle) 23ead384d9SHuacai Chen { 240efb61c8SArd Biesheuvel int nr_pages = round_up(kernel_asize, EFI_ALLOC_ALIGN) / EFI_PAGE_SIZE; 250efb61c8SArd Biesheuvel efi_physical_addr_t kernel_addr = EFI_KIMG_PREFERRED_ADDRESS; 26ead384d9SHuacai Chen efi_status_t status; 27ead384d9SHuacai Chen 280efb61c8SArd Biesheuvel /* 290efb61c8SArd Biesheuvel * Allocate space for the kernel image at the preferred offset. This is 300efb61c8SArd Biesheuvel * the only location in memory from where we can execute the image, so 310efb61c8SArd Biesheuvel * no point in falling back to another allocation. 320efb61c8SArd Biesheuvel */ 330efb61c8SArd Biesheuvel status = efi_bs_call(allocate_pages, EFI_ALLOCATE_ADDRESS, 340efb61c8SArd Biesheuvel EFI_LOADER_DATA, nr_pages, &kernel_addr); 350efb61c8SArd Biesheuvel if (status != EFI_SUCCESS) 360efb61c8SArd Biesheuvel return status; 37ead384d9SHuacai Chen 380efb61c8SArd Biesheuvel *image_addr = EFI_KIMG_PREFERRED_ADDRESS; 39ead384d9SHuacai Chen *image_size = kernel_asize; 40ead384d9SHuacai Chen 410efb61c8SArd Biesheuvel memcpy((void *)EFI_KIMG_PREFERRED_ADDRESS, 420efb61c8SArd Biesheuvel (void *)&kernel_offset - kernel_offset, 430efb61c8SArd Biesheuvel kernel_fsize); 440efb61c8SArd Biesheuvel 45ead384d9SHuacai Chen return status; 46ead384d9SHuacai Chen } 47ead384d9SHuacai Chen 480efb61c8SArd Biesheuvel unsigned long kernel_entry_address(void) 490efb61c8SArd Biesheuvel { 500efb61c8SArd Biesheuvel unsigned long base = (unsigned long)&kernel_offset - kernel_offset; 510efb61c8SArd Biesheuvel 520efb61c8SArd Biesheuvel return (unsigned long)&kernel_entry - base + VMLINUX_LOAD_ADDRESS; 530efb61c8SArd Biesheuvel } 54