xref: /DragonStub/apps/riscv-stub.c (revision 823f04931913f01ee1fc0dc0c7876156ad150388)
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 }