Linux Audio

Check our new training course

Loading...
v6.8
 1// SPDX-License-Identifier: GPL-2.0
 2/*
 3 * Copyright (C) 2020 Western Digital Corporation or its affiliates.
 4 */
 5
 6#include <linux/efi.h>
 
 7
 8#include <asm/efi.h>
 9#include <asm/sections.h>
10#include <asm/unaligned.h>
11
12#include "efistub.h"
13
14unsigned long stext_offset(void)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
15{
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
16	/*
17	 * When built as part of the kernel, the EFI stub cannot branch to the
18	 * kernel proper via the image header, as the PE/COFF header is
19	 * strictly not part of the in-memory presentation of the image, only
20	 * of the file representation. So instead, we need to jump to the
21	 * actual entrypoint in the .text region of the image.
22	 */
23	return _start_kernel - _start;
 
24}
25
26efi_status_t handle_kernel_image(unsigned long *image_addr,
27				 unsigned long *image_size,
28				 unsigned long *reserve_addr,
29				 unsigned long *reserve_size,
30				 efi_loaded_image_t *image,
31				 efi_handle_t image_handle)
32{
33	unsigned long kernel_size, kernel_codesize, kernel_memsize;
 
34	efi_status_t status;
35
36	kernel_size = _edata - _start;
37	kernel_codesize = __init_text_end - _start;
38	kernel_memsize = kernel_size + (_end - _edata);
39	*image_addr = (unsigned long)_start;
40	*image_size = kernel_memsize;
41	*reserve_size = *image_size;
 
 
 
 
 
 
 
 
 
 
 
 
 
42
43	status = efi_kaslr_relocate_kernel(image_addr,
44					   reserve_addr, reserve_size,
45					   kernel_size, kernel_codesize, kernel_memsize,
46					   efi_kaslr_get_phys_seed(image_handle));
47	if (status != EFI_SUCCESS) {
48		efi_err("Failed to relocate kernel\n");
49		*image_size = 0;
50	}
51
52	return status;
53}
54
55void efi_icache_sync(unsigned long start, unsigned long end)
56{
57	asm volatile ("fence.i" ::: "memory");
58}
v5.14.15
  1// SPDX-License-Identifier: GPL-2.0
  2/*
  3 * Copyright (C) 2020 Western Digital Corporation or its affiliates.
  4 */
  5
  6#include <linux/efi.h>
  7#include <linux/libfdt.h>
  8
  9#include <asm/efi.h>
 10#include <asm/sections.h>
 
 11
 12#include "efistub.h"
 13
 14/*
 15 * RISC-V requires the kernel image to placed 2 MB aligned base for 64 bit and
 16 * 4MB for 32 bit.
 17 */
 18#ifdef CONFIG_64BIT
 19#define MIN_KIMG_ALIGN		SZ_2M
 20#else
 21#define MIN_KIMG_ALIGN		SZ_4M
 22#endif
 23
 24typedef void __noreturn (*jump_kernel_func)(unsigned int, unsigned long);
 25
 26static u32 hartid;
 27
 28static u32 get_boot_hartid_from_fdt(void)
 29{
 30	const void *fdt;
 31	int chosen_node, len;
 32	const fdt32_t *prop;
 33
 34	fdt = get_efi_config_table(DEVICE_TREE_GUID);
 35	if (!fdt)
 36		return U32_MAX;
 37
 38	chosen_node = fdt_path_offset(fdt, "/chosen");
 39	if (chosen_node < 0)
 40		return U32_MAX;
 41
 42	prop = fdt_getprop((void *)fdt, chosen_node, "boot-hartid", &len);
 43	if (!prop || len != sizeof(u32))
 44		return U32_MAX;
 45
 46	return fdt32_to_cpu(*prop);
 47}
 48
 49efi_status_t check_platform_features(void)
 50{
 51	hartid = get_boot_hartid_from_fdt();
 52	if (hartid == U32_MAX) {
 53		efi_err("/chosen/boot-hartid missing or invalid!\n");
 54		return EFI_UNSUPPORTED;
 55	}
 56	return EFI_SUCCESS;
 57}
 58
 59void __noreturn efi_enter_kernel(unsigned long entrypoint, unsigned long fdt,
 60				 unsigned long fdt_size)
 61{
 62	unsigned long stext_offset = _start_kernel - _start;
 63	unsigned long kernel_entry = entrypoint + stext_offset;
 64	jump_kernel_func jump_kernel = (jump_kernel_func)kernel_entry;
 65
 66	/*
 67	 * Jump to real kernel here with following constraints.
 68	 * 1. MMU should be disabled.
 69	 * 2. a0 should contain hartid
 70	 * 3. a1 should DT address
 
 71	 */
 72	csr_write(CSR_SATP, 0);
 73	jump_kernel(hartid, fdt);
 74}
 75
 76efi_status_t handle_kernel_image(unsigned long *image_addr,
 77				 unsigned long *image_size,
 78				 unsigned long *reserve_addr,
 79				 unsigned long *reserve_size,
 80				 efi_loaded_image_t *image)
 
 81{
 82	unsigned long kernel_size = 0;
 83	unsigned long preferred_addr;
 84	efi_status_t status;
 85
 86	kernel_size = _edata - _start;
 
 
 87	*image_addr = (unsigned long)_start;
 88	*image_size = kernel_size + (_end - _edata);
 89
 90	/*
 91	 * RISC-V kernel maps PAGE_OFFSET virtual address to the same physical
 92	 * address where kernel is booted. That's why kernel should boot from
 93	 * as low as possible to avoid wastage of memory. Currently, dram_base
 94	 * is occupied by the firmware. So the preferred address for kernel to
 95	 * boot is next aligned address. If preferred address is not available,
 96	 * relocate_kernel will fall back to efi_low_alloc_above to allocate
 97	 * lowest possible memory region as long as the address and size meets
 98	 * the alignment constraints.
 99	 */
100	preferred_addr = MIN_KIMG_ALIGN;
101	status = efi_relocate_kernel(image_addr, kernel_size, *image_size,
102				     preferred_addr, MIN_KIMG_ALIGN, 0x0);
103
 
 
 
 
104	if (status != EFI_SUCCESS) {
105		efi_err("Failed to relocate kernel\n");
106		*image_size = 0;
107	}
 
108	return status;
 
 
 
 
 
109}