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