xref: /DragonStub/apps/stub.c (revision 3e6106c4d60a23aae3c0740979c5e6fb728b63c3)
1 #include <efi.h>
2 #include <efilib.h>
3 #include <elf.h>
4 #include <dragonstub/dragonstub.h>
5 
6 extern void _image_end(void);
7 
8 static u64 image_base = 0;
9 static u64 image_size = 0;
10 static u64 image_end = 0;
11 
12 EFI_STATUS efi_handle_cmdline(EFI_LOADED_IMAGE *image, char **cmdline_ptr)
13 {
14 	int cmdline_size = 0;
15 	EFI_STATUS status;
16 	char *cmdline;
17 
18 	/*
19 	 * Get the command line from EFI, using the LOADED_IMAGE
20 	 * protocol. We are going to copy the command line into the
21 	 * device tree, so this can be allocated anywhere.
22 	 */
23 	cmdline = efi_convert_cmdline(image, &cmdline_size);
24 	if (!cmdline) {
25 		efi_err("getting command line via LOADED_IMAGE_PROTOCOL\n");
26 		return EFI_OUT_OF_RESOURCES;
27 	}
28 
29 	// 	if (IS_ENABLED(CONFIG_CMDLINE_EXTEND) ||
30 	// 	    IS_ENABLED(CONFIG_CMDLINE_FORCE) ||
31 	// 	    cmdline_size == 0) {
32 	// 		status = efi_parse_options(CONFIG_CMDLINE);
33 	// 		if (status != EFI_SUCCESS) {
34 	// 			efi_err("Failed to parse options\n");
35 	// 			goto fail_free_cmdline;
36 	// 		}
37 	// 	}
38 
39 	// if (!IS_ENABLED(CONFIG_CMDLINE_FORCE) && cmdline_size > 0) {
40 	if (cmdline_size > 0) {
41 		status = efi_parse_options(cmdline);
42 		if (status != EFI_SUCCESS) {
43 			efi_err("Failed to parse options\n");
44 			goto fail_free_cmdline;
45 		}
46 	}
47 
48 	*cmdline_ptr = cmdline;
49 	return EFI_SUCCESS;
50 
51 fail_free_cmdline:
52 	efi_bs_call(FreePool, cmdline_ptr);
53 	return status;
54 }
55 
56 static efi_status_t init_efi_program_info(efi_loaded_image_t *loaded_image)
57 {
58 	image_base = (u64)loaded_image->ImageBase;
59 	image_size = loaded_image->ImageSize;
60 	image_end = (u64)_image_end;
61 	efi_info("DragonStub loaded at 0x%p\n", image_base);
62 	efi_info("DragonStub + payload size: 0x%p\n", image_size);
63 	efi_info("DragonStub end addr: 0x%p\n", image_end);
64 	return EFI_SUCCESS;
65 }
66 
67 /// @brief payload_info的构造函数
68 static struct payload_info payload_info_new(u64 payload_addr, u64 payload_size)
69 {
70 	struct payload_info info = { .payload_addr = payload_addr,
71 				     .payload_size = payload_size };
72 	return info;
73 }
74 static efi_status_t find_elf(struct payload_info *info)
75 {
76 	extern __weak void _binary_payload_start(void);
77 	extern __weak void _binary_payload_end(void);
78 	extern __weak void _binary_payload_size(void);
79 	u64 payload_start = (u64)_binary_payload_start;
80 	u64 payload_end = (u64)_binary_payload_end;
81 
82 	u64 payload_size = payload_end - payload_start;
83 
84 	efi_info("payload_addr: %p\n", payload_start);
85 	efi_info("payload_end: %p\n", payload_end);
86 	efi_info("payload_size: %p\n", payload_size);
87 
88 	if (payload_start == 0 || payload_end <= payload_start + 4 ||
89 	    payload_size == 0) {
90 		return EFI_NOT_FOUND;
91 	}
92 
93 	efi_debug("Checking payload's ELF header...\n");
94 	bool found = true;
95 	for (int i = 0; i < 4; i++) {
96 		u8 c = *(u8 *)(payload_start + i);
97 		if (c != ELFMAG[i]) {
98 			// 不是ELF magic number,跳过
99 			found = false;
100 			break;
101 		}
102 	}
103 
104 	// 如果找到了ELF magic number,就认为找到了ELF header,稍后再验证
105 	if (found) {
106 		info->payload_addr = payload_start;
107 		info->payload_size = payload_size;
108 		return EFI_SUCCESS;
109 	}
110 
111 	return EFI_NOT_FOUND;
112 }
113 
114 /// @brief 寻找要加载的内核负载
115 /// @param handle efi_handle
116 /// @param image efi_loaded_image_t
117 /// @param ret_info 返回的负载信息
118 /// @return
119 efi_status_t find_payload(efi_handle_t handle, efi_loaded_image_t *loaded_image,
120 			  struct payload_info *ret_info)
121 {
122 	efi_info("Try to find payload to boot\n");
123 	efi_status_t status = init_efi_program_info(loaded_image);
124 	if (status != EFI_SUCCESS) {
125 		efi_err("Failed to init efi program info\n");
126 		return status;
127 	}
128 
129 	struct payload_info info = payload_info_new(0, 0);
130 
131 	status = find_elf(&info);
132 	if (status != EFI_SUCCESS) {
133 		efi_err("Payload not found: Did you forget to add the payload by setting PAYLOAD_ELF at compile time?\n"
134 			"Or the payload is not an ELF file?\n");
135 		return status;
136 	}
137 
138     *ret_info = info;
139     return EFI_SUCCESS;
140 }
141 
142 
143 efi_status_t efi_stub_common(efi_handle_t handle,
144 			     struct payload_info* payload_info,
145 			     char *cmdline_ptr)
146 {
147 	struct screen_info *si;
148 	efi_status_t status;
149 
150 	status = check_platform_features();
151 	if (status != EFI_SUCCESS)
152 		return status;
153 
154 	// si = setup_graphics();
155 
156 	// efi_retrieve_tpm2_eventlog();
157 
158 	// /* Ask the firmware to clear memory on unclean shutdown */
159 	// efi_enable_reset_attack_mitigation();
160 
161 	// efi_load_initrd(image, ULONG_MAX, efi_get_max_initrd_addr(image_addr),
162 	// 		NULL);
163 
164 	// efi_random_get_seed();
165 
166 	// /* force efi_novamap if SetVirtualAddressMap() is unsupported */
167 	// efi_novamap |= !(get_supported_rt_services() &
168 	// 		 EFI_RT_SUPPORTED_SET_VIRTUAL_ADDRESS_MAP);
169 
170 	// install_memreserve_table();
171 
172 	// status = efi_boot_kernel(handle, image, image_addr, cmdline_ptr);
173 
174 	// free_screen_info(si);
175 	return status;
176 }
177