1 #include <dragonstub/dragonstub.h>
2 #include <dragonstub/linux/unaligned.h>
3 #include "efilib.h"
4 #include <libfdt.h>
5 #include <asm/csr.h>
6
7 /// @brief 当前的hartid
8 static unsigned long hartid;
9
10 typedef void __noreturn (*jump_kernel_func)(unsigned long, unsigned long);
11
get_boot_hartid_from_fdt(void)12 static efi_status_t get_boot_hartid_from_fdt(void)
13 {
14 const void *fdt;
15 int chosen_node, len;
16 const void *prop;
17
18 // efi_guid_t device_tree_guid = *(efi_guid_t *)&tmp;
19 fdt = get_efi_config_table(DEVICE_TREE_GUID);
20 if (!fdt) {
21 efi_err("Failed to get FDT from EFI config table\n");
22 return EFI_INVALID_PARAMETER;
23 }
24
25 chosen_node = fdt_path_offset(fdt, "/chosen");
26 if (chosen_node < 0) {
27 efi_err("Failed to find /chosen node in FDT\n");
28 return EFI_INVALID_PARAMETER;
29 }
30
31 prop = fdt_getprop((void *)fdt, chosen_node, "boot-hartid", &len);
32 if (!prop) {
33 efi_err("Failed to find boot-hartid property in FDT\n");
34 return EFI_INVALID_PARAMETER;
35 }
36
37 if (len == sizeof(u32))
38 hartid = (unsigned long)fdt32_to_cpu(*(fdt32_t *)prop);
39 else if (len == sizeof(u64))
40 hartid = (unsigned long)fdt64_to_cpu(
41 __get_unaligned_t(fdt64_t, prop));
42 else {
43 efi_err("Invalid boot-hartid property in FDT\n");
44 return EFI_INVALID_PARAMETER;
45 }
46
47 return 0;
48 }
49
get_boot_hartid_from_efi(void)50 static efi_status_t get_boot_hartid_from_efi(void)
51 {
52 efi_guid_t boot_protocol_guid = RISCV_EFI_BOOT_PROTOCOL_GUID;
53 struct riscv_efi_boot_protocol *boot_protocol;
54 efi_status_t status;
55
56 status = efi_bs_call(LocateProtocol, &boot_protocol_guid, NULL,
57 (void **)&boot_protocol);
58 if (status != EFI_SUCCESS)
59 return status;
60 return efi_call_proto(boot_protocol, get_boot_hartid, &hartid);
61 }
62
check_platform_features(void)63 efi_status_t check_platform_features(void)
64 {
65 efi_info("Checking platform features...\n");
66 efi_status_t status = -1;
67 int ret;
68 efi_info("Try to get boot hartid from EFI\n");
69 status = get_boot_hartid_from_efi();
70 if (status != EFI_SUCCESS) {
71 efi_info("Try to get boot hartid from FDT\n");
72 ret = get_boot_hartid_from_fdt();
73 if (ret) {
74 efi_err("Failed to get boot hartid!\n");
75 return EFI_UNSUPPORTED;
76 }
77 }
78
79 efi_info("Boot hartid: %ld\n", hartid);
80 return EFI_SUCCESS;
81 }
82
efi_enter_kernel(struct payload_info * payload_info,unsigned long fdt,unsigned long fdt_size)83 void __noreturn efi_enter_kernel(struct payload_info *payload_info,
84 unsigned long fdt, unsigned long fdt_size)
85 {
86 unsigned long kernel_entry = payload_info->kernel_entry;
87 jump_kernel_func jump_kernel = (jump_kernel_func)kernel_entry;
88
89 /*
90 * Jump to real kernel here with following constraints.
91 * 1. MMU should be disabled.
92 * 2. a0 should contain hartid
93 * 3. a1 should DT address
94 */
95 csr_write(CSR_SATP, 0);
96 jump_kernel(hartid, fdt);
97 }