uefi.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895
  1. /* Copyright (C) 2022 Andrius Štikonas
  2. * This file is part of M2-Planet.
  3. *
  4. * M2-Planet is free software: you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation, either version 3 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * M2-Planet is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with M2-Planet. If not, see <http://www.gnu.org/licenses/>.
  16. */
  17. #define __uefi__ 1
  18. #ifndef _UEFI_C
  19. #define _UEFI_C
  20. #include <ctype.h>
  21. #include <uefi/string_p.h>
  22. #define PAGE_SIZE 4096
  23. #define USER_STACK_SIZE 8388608
  24. #define EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL 1
  25. #define EFI_FILE_MODE_READ 1
  26. #define EFI_FILE_MODE_WRITE 2
  27. #define EFI_FILE_MODE_CREATE (1 << 63)
  28. #define EFI_FILE_READ_ONLY 1
  29. #define EFI_FILE_DIRECTORY 0x10
  30. #define EFI_LOADER_DATA 2
  31. #define EFI_VARIABLE_BOOTSERVICE_ACCESS 2
  32. #define EFI_SUCCESS 0
  33. #define EFI_LOAD_ERROR (1 << 63) | 1
  34. #define EFI_INVALID_PARAMETER (1 << 63) | 2
  35. #define EFI_UNSUPPORTED (1 << 63) | 3
  36. #define EFI_BUFFER_TOO_SMALL (1 << 63) | 5
  37. #define EFI_NOT_FOUND (1 << 31) | 14
  38. #define __PATH_MAX 4096
  39. #define __ENV_NAME_MAX 4096
  40. #define HARDWARE_DEVICE_PATH 1
  41. #define MEMORY_MAPPED 3
  42. #define END_HARDWARE_DEVICE_PATH 0x7F
  43. #define END_ENTIRE_DEVICE_PATH 0xFF
  44. #define TPL_APPLICATION 4
  45. #define TPL_CALLBACK 8
  46. #define TPL_NOTIFY 16
  47. #define TPL_HIGH_LEVEL 31
  48. void* _image_handle;
  49. void* _root_device;
  50. void* __user_stack;
  51. int _argc;
  52. char** _argv;
  53. char** _envp;
  54. char* _cwd;
  55. char* _root;
  56. struct efi_simple_text_output_protocol
  57. {
  58. void* reset;
  59. void* output_string;
  60. void* test_string;
  61. void* query_mode;
  62. void* set_mode;
  63. void* set_attribute;
  64. void* clear_screen;
  65. void* set_cursor;
  66. void* enable_cursor;
  67. void* mode;
  68. };
  69. struct efi_table_header
  70. {
  71. unsigned signature;
  72. unsigned revision_and_header_size;
  73. unsigned crc32_and_reserved;
  74. };
  75. struct efi_boot_table
  76. {
  77. struct efi_table_header header;
  78. /* Task Priority Services */
  79. void* raise_tpl;
  80. void* restore_tpl;
  81. /* Memory Services */
  82. void* allocate_pages;
  83. void* free_pages;
  84. void* get_memory_map;
  85. void* allocate_pool;
  86. void* free_pool;
  87. /* Event & Timer Services */
  88. void* create_event;
  89. void* set_timer;
  90. void* wait_for_event;
  91. void* signal_event;
  92. void* close_event;
  93. void* check_event;
  94. /* Protocol Handler Services */
  95. void* install_protocol_interface;
  96. void* reinstall_protocol_interface;
  97. void* uninstall_protocol_interface;
  98. void* handle_protocol;
  99. void* reserved;
  100. void* register_protocol_notify;
  101. void* locate_handle;
  102. void* locate_device_path;
  103. void* install_configuration_table;
  104. /* Image Services */
  105. void* load_image;
  106. void* start_image;
  107. void* exit;
  108. void* unload_image;
  109. void* exit_boot_services;
  110. /* Miscellaneous Services */
  111. void* get_next_monotonic_count;
  112. void* stall;
  113. void* set_watchdog_timer;
  114. /* DriverSupport Services */
  115. void* connect_controller;
  116. void* disconnect_controller;
  117. /* Open and Close Protocol Services */
  118. void* open_protocol;
  119. void* close_protocol;
  120. void* open_protocol_information;
  121. /* Library Services */
  122. void* protocols_per_handle;
  123. void* locate_handle_buffer;
  124. void* locate_protocol;
  125. void* install_multiple_protocol_interfaces;
  126. void* uninstall_multiple_protocol_interfaces;
  127. /* 32-bit CRC Services */
  128. void* copy_mem;
  129. void* set_mem;
  130. void* create_event_ex;
  131. };
  132. struct efi_runtime_table
  133. {
  134. struct efi_table_header header;
  135. /* Time Services */
  136. void* get_time;
  137. void* set_time;
  138. void* get_wakeup_time;
  139. void* set_wakeup_time;
  140. /* Virtual Memory Services */
  141. void* set_virtual_address_map;
  142. void* convert_pointer;
  143. /* Variable Services */
  144. void* get_variable;
  145. void* get_next_variable_name;
  146. void* set_variable;
  147. /* Miscellaneous Services */
  148. void* get_next_high_monotonic_count;
  149. void* reset_system;
  150. /* UEFI 2.0 Capsule Services */
  151. void* update_capsule;
  152. void* query_capsule_capabilities;
  153. /* Miscellaneous UEFI 2.0 Services */
  154. void* query_variable_info;
  155. };
  156. struct efi_system_table
  157. {
  158. struct efi_table_header header;
  159. char* firmware_vendor;
  160. unsigned firmware_revision;
  161. void* console_in_handle;
  162. void* con_in;
  163. void* console_out_handle;
  164. struct efi_simple_text_output_protocol* con_out;
  165. void *standard_error_handle;
  166. struct efi_simple_text_output_protocol* std_err;
  167. struct efi_runtime_table* runtime_services;
  168. struct efi_boot_table* boot_services;
  169. unsigned number_table_entries;
  170. void *configuration_table;
  171. };
  172. struct efi_system_table* _system;
  173. struct efi_guid
  174. {
  175. uint32_t data1;
  176. uint16_t data2;
  177. uint16_t data3;
  178. uint8_t data4[8];
  179. };
  180. struct efi_guid EFI_LOADED_IMAGE_PROTOCOL_GUID;
  181. struct efi_guid EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID;
  182. struct efi_guid EFI_FILE_INFO_GUID;
  183. struct efi_guid EFI_SHELL_VARIABLE_GUID;
  184. struct efi_loaded_image_protocol
  185. {
  186. unsigned revision;
  187. void* parent;
  188. void* system;
  189. void* device;
  190. void* filepath;
  191. void* reserved;
  192. /* Image's load options */
  193. unsigned load_options_size;
  194. void* load_options;
  195. /* Location of the image in memory */
  196. void* image_base;
  197. unsigned image_size;
  198. unsigned image_code_type;
  199. unsigned image_data_type;
  200. void* unload;
  201. };
  202. struct efi_loaded_image_protocol* _image;
  203. struct efi_simple_file_system_protocol
  204. {
  205. unsigned revision;
  206. void* open_volume;
  207. };
  208. struct efi_file_protocol
  209. {
  210. unsigned revision;
  211. void* open;
  212. void* close;
  213. void* delete;
  214. void* read;
  215. void* write;
  216. void* get_position;
  217. void* set_position;
  218. void* get_info;
  219. void* set_info;
  220. void* flush;
  221. void* open_ex;
  222. void* read_ex;
  223. void* write_ex;
  224. void* flush_ex;
  225. };
  226. struct efi_file_protocol* _rootdir;
  227. struct efi_time
  228. {
  229. uint16_t year;
  230. uint8_t month;
  231. uint8_t day;
  232. uint8_t hour;
  233. uint8_t minute;
  234. uint8_t second;
  235. uint8_t pad1;
  236. uint32_t nanosecond;
  237. uint16_t time_zone;
  238. uint8_t daylight;
  239. uint8_t pad2;
  240. };
  241. struct efi_file_info
  242. {
  243. unsigned size;
  244. unsigned file_size;
  245. unsigned physical_size;
  246. struct efi_time create_time;
  247. struct efi_time last_access_time;
  248. struct efi_time modifiction_time;
  249. unsigned attribute;
  250. char file_name[__PATH_MAX];
  251. };
  252. struct efi_device_path_protocol
  253. {
  254. uint8_t type;
  255. uint8_t subtype;
  256. uint16_t length;
  257. uint32_t memory_type;
  258. unsigned start_address;
  259. unsigned end_address;
  260. };
  261. unsigned __uefi_1(void*, void*, FUNCTION f)
  262. {
  263. #ifdef __x86_64__
  264. asm("lea_rcx,[rbp+DWORD] %-8"
  265. "mov_rcx,[rcx]"
  266. "lea_rax,[rbp+DWORD] %-16"
  267. "mov_rax,[rax]"
  268. "push_rsp"
  269. "push_[rsp]"
  270. "and_rsp, %-16"
  271. "sub_rsp, %32"
  272. "call_rax"
  273. "mov_rsp,[rsp+BYTE] %40");
  274. #else
  275. #error unsupported arch
  276. #endif
  277. }
  278. unsigned __uefi_2(void*, void*, FUNCTION f)
  279. {
  280. #ifdef __x86_64__
  281. asm("lea_rcx,[rbp+DWORD] %-8"
  282. "mov_rcx,[rcx]"
  283. "lea_rdx,[rbp+DWORD] %-16"
  284. "mov_rdx,[rdx]"
  285. "lea_rax,[rbp+DWORD] %-24"
  286. "mov_rax,[rax]"
  287. "push_rsp"
  288. "push_[rsp]"
  289. "and_rsp, %-16"
  290. "sub_rsp, %32"
  291. "call_rax"
  292. "mov_rsp,[rsp+BYTE] %40");
  293. #else
  294. #error unsupported arch
  295. #endif
  296. }
  297. unsigned __uefi_3(void*, void*, void*, FUNCTION f)
  298. {
  299. #ifdef __x86_64__
  300. asm("lea_rcx,[rbp+DWORD] %-8"
  301. "mov_rcx,[rcx]"
  302. "lea_rdx,[rbp+DWORD] %-16"
  303. "mov_rdx,[rdx]"
  304. "lea_r8,[rbp+DWORD] %-24"
  305. "mov_r8,[r8]"
  306. "lea_rax,[rbp+DWORD] %-32"
  307. "mov_rax,[rax]"
  308. "push_rsp"
  309. "push_[rsp]"
  310. "and_rsp, %-16"
  311. "sub_rsp, %32"
  312. "call_rax"
  313. "mov_rsp,[rsp+BYTE] %40");
  314. #else
  315. #error unsupported arch
  316. #endif
  317. }
  318. unsigned __uefi_4(void*, void*, void*, void*, FUNCTION f)
  319. {
  320. #ifdef __x86_64__
  321. asm("lea_rcx,[rbp+DWORD] %-8"
  322. "mov_rcx,[rcx]"
  323. "lea_rdx,[rbp+DWORD] %-16"
  324. "mov_rdx,[rdx]"
  325. "lea_r8,[rbp+DWORD] %-24"
  326. "mov_r8,[r8]"
  327. "lea_r9,[rbp+DWORD] %-32"
  328. "mov_r9,[r9]"
  329. "lea_rax,[rbp+DWORD] %-40"
  330. "mov_rax,[rax]"
  331. "push_rsp"
  332. "push_[rsp]"
  333. "and_rsp, %-16"
  334. "sub_rsp, %32"
  335. "call_rax"
  336. "mov_rsp,[rsp+BYTE] %40");
  337. #else
  338. #error unsupported arch
  339. #endif
  340. }
  341. unsigned __uefi_5(void*, void*, void*, void*, void*, FUNCTION f)
  342. {
  343. #ifdef __x86_64__
  344. asm("lea_rcx,[rbp+DWORD] %-8"
  345. "mov_rcx,[rcx]"
  346. "lea_rdx,[rbp+DWORD] %-16"
  347. "mov_rdx,[rdx]"
  348. "lea_r8,[rbp+DWORD] %-24"
  349. "mov_r8,[r8]"
  350. "lea_r9,[rbp+DWORD] %-32"
  351. "mov_r9,[r9]"
  352. "push_rsp"
  353. "push_[rsp]"
  354. "and_rsp, %-16"
  355. "push_rax"
  356. "lea_rax,[rbp+DWORD] %-40"
  357. "mov_rax,[rax]"
  358. "push_rax"
  359. "lea_rax,[rbp+DWORD] %-48"
  360. "mov_rax,[rax]"
  361. "sub_rsp, %32"
  362. "call_rax"
  363. "mov_rsp,[rsp+BYTE] %56");
  364. #else
  365. #error unsupported arch
  366. #endif
  367. }
  368. unsigned __uefi_6(void*, void*, void*, void*, void*, void*, FUNCTION f)
  369. {
  370. #ifdef __x86_64__
  371. asm("lea_rcx,[rbp+DWORD] %-8"
  372. "mov_rcx,[rcx]"
  373. "lea_rdx,[rbp+DWORD] %-16"
  374. "mov_rdx,[rdx]"
  375. "lea_r8,[rbp+DWORD] %-24"
  376. "mov_r8,[r8]"
  377. "lea_r9,[rbp+DWORD] %-32"
  378. "mov_r9,[r9]"
  379. "push_rsp"
  380. "push_[rsp]"
  381. "and_rsp, %-16"
  382. "lea_rax,[rbp+DWORD] %-48"
  383. "mov_rax,[rax]"
  384. "push_rax"
  385. "lea_rax,[rbp+DWORD] %-40"
  386. "mov_rax,[rax]"
  387. "push_rax"
  388. "lea_rax,[rbp+DWORD] %-56"
  389. "mov_rax,[rax]"
  390. "sub_rsp, %32"
  391. "call_rax"
  392. "mov_rsp,[rsp+BYTE] %56");
  393. #else
  394. #error unsupported arch
  395. #endif
  396. }
  397. unsigned _allocate_pool(unsigned memory_type, unsigned size, void* pool)
  398. {
  399. return __uefi_3(memory_type, size, pool, _system->boot_services->allocate_pool);
  400. }
  401. void _free_pool(void* memory)
  402. {
  403. return __uefi_1(memory, _system->boot_services->free_pool);
  404. }
  405. unsigned _open_protocol(void* handle, struct efi_guid* protocol, void* agent_handle, void** interface, void* controller_handle, long attributes, FUNCTION open_protocol)
  406. {
  407. return __uefi_6(handle, protocol, agent_handle, interface, controller_handle, attributes, _system->boot_services->open_protocol);
  408. }
  409. unsigned _close_protocol(void* handle, struct efi_guid* protocol, void* agent_handle, void* controller_handle)
  410. {
  411. return __uefi_4(handle, protocol, agent_handle, controller_handle, _system->boot_services->close_protocol);
  412. }
  413. unsigned _open_volume(struct efi_simple_file_system_protocol* rootfs, struct efi_file_protocol** rootdir)
  414. {
  415. return __uefi_2(rootfs, rootdir, rootfs->open_volume);
  416. }
  417. unsigned _close(struct efi_file_protocol* file)
  418. {
  419. return __uefi_1(file, file->close);
  420. }
  421. unsigned _get_next_variable_name(unsigned* size, char* name, struct efi_guid* vendor_guid)
  422. {
  423. return __uefi_3(size, name, vendor_guid, _system->runtime_services->get_next_variable_name);
  424. }
  425. unsigned _get_variable(char* name, struct efi_guid* vendor_guid, uint32_t* attributes, unsigned* data_size, void* data)
  426. {
  427. return __uefi_5(name, vendor_guid, attributes, data_size, data, _system->runtime_services->get_variable);
  428. }
  429. char* _string2wide(char* narrow_string);
  430. size_t strlen(char const* str);
  431. void free(void* ptr);
  432. unsigned _set_variable(char* name, void* data)
  433. {
  434. char* wide_name = _string2wide(name);
  435. char* wide_data = _string2wide(data);
  436. unsigned data_size = strlen(data) * 2;
  437. uint32_t attributes = EFI_VARIABLE_BOOTSERVICE_ACCESS;
  438. unsigned rval = __uefi_5(wide_name, &EFI_SHELL_VARIABLE_GUID, attributes, data_size, wide_data, _system->runtime_services->set_variable);
  439. free(wide_name);
  440. free(wide_data);
  441. return rval;
  442. }
  443. void exit(unsigned value)
  444. {
  445. goto FUNCTION__exit;
  446. }
  447. char* strcat(char* dest, char const* src);
  448. char* strcpy(char* dest, char const* src);
  449. size_t strlen(char const* str);
  450. void* calloc(int count, int size);
  451. char* _relative_path_to_absolute(char* narrow_string)
  452. {
  453. char* absolute_path = calloc(__PATH_MAX, 1);
  454. if(narrow_string[0] != '/' && narrow_string[0] != '\\')
  455. {
  456. strcat(absolute_path, _cwd);
  457. if(_cwd[strlen(_cwd) - 1] != '/' && _cwd[strlen(_cwd) - 1] != '\\')
  458. {
  459. strcat(absolute_path, "/");
  460. }
  461. }
  462. else
  463. {
  464. strcat(absolute_path, _root);
  465. }
  466. strcat(absolute_path, narrow_string);
  467. return absolute_path;
  468. }
  469. char* _posix_path_to_uefi(char* narrow_string)
  470. {
  471. char* absolute_path = _relative_path_to_absolute(narrow_string);
  472. unsigned length = strlen(absolute_path);
  473. unsigned in = 0;
  474. unsigned out = 0;
  475. while(in < length)
  476. {
  477. if(absolute_path[in] == '/')
  478. {
  479. absolute_path[out] = '\\';
  480. // Deal with /./ in paths.
  481. if((in < (length - 1)) && (absolute_path[in + 1] == '.') && (absolute_path[in + 2] == '/'))
  482. {
  483. in += 2;
  484. }
  485. }
  486. else
  487. {
  488. absolute_path[out] = absolute_path[in];
  489. }
  490. in += 1;
  491. out += 1;
  492. }
  493. absolute_path[out] = 0;
  494. char* wide_string = _string2wide(absolute_path);
  495. free(absolute_path);
  496. return wide_string;
  497. }
  498. char* _string2wide(char* narrow_string)
  499. {
  500. unsigned length = strlen(narrow_string);
  501. char* wide_string = calloc(length + 1, 2);
  502. unsigned i;
  503. for(i = 0; i < length; i += 1)
  504. {
  505. wide_string[2 * i] = narrow_string[i];
  506. }
  507. return wide_string;
  508. }
  509. int isspace(char _c);
  510. void _process_load_options(char* load_options)
  511. {
  512. /* Determine argc */
  513. _argc = 1; /* command name */
  514. char *i = load_options;
  515. unsigned was_space = 0;
  516. do
  517. {
  518. if(isspace(i[0]))
  519. {
  520. if(!was_space)
  521. {
  522. _argc += 1;
  523. was_space = 1;
  524. }
  525. }
  526. else
  527. {
  528. was_space = 0;
  529. }
  530. i += 1;
  531. } while(i[0] != 0);
  532. /* Collect argv */
  533. _argv = calloc(_argc + 1, sizeof(char*));
  534. i = load_options;
  535. unsigned j;
  536. for(j = 0; j < _argc; j += 1)
  537. {
  538. _argv[j] = i;
  539. do
  540. {
  541. i += 1;
  542. } while(!isspace(i[0]) && i[0] != 0);
  543. i[0] = 0;
  544. do
  545. {
  546. i += 1;
  547. } while(isspace(i[0]));
  548. }
  549. }
  550. /* Function to find the length of a char**; an array of strings */
  551. unsigned _array_length(char** array)
  552. {
  553. unsigned length = 0;
  554. while(array[length] != NULL)
  555. {
  556. length += 1;
  557. }
  558. return length;
  559. }
  560. size_t wcstombs(char* dest, char* src, size_t n);
  561. char* _get_environmental_variable(struct efi_guid* vendor_guid, char* name, unsigned size)
  562. {
  563. unsigned data_size;
  564. char* data;
  565. char* variable_data;
  566. char* envp_line = NULL;
  567. /* Call with data=NULL to obtain data size that we need to allocate */
  568. _get_variable(name, vendor_guid, NULL, &data_size, NULL);
  569. data = calloc(data_size + 1, 1);
  570. _get_variable(name, vendor_guid, NULL, &data_size, data);
  571. variable_data = calloc((data_size / 2) + 1, 1);
  572. wcstombs(variable_data, data, (data_size / 2) + 1);
  573. envp_line = calloc((size / 2) + (data_size / 2) + 1, 1);
  574. wcstombs(envp_line, name, size / 2);
  575. strcat(envp_line, "=");
  576. strcat(envp_line, variable_data);
  577. free(data);
  578. free(variable_data);
  579. return envp_line;
  580. }
  581. int memcmp(void const* lhs, void const* rhs, size_t count);
  582. char** _get_environmental_variables(char** envp)
  583. {
  584. EFI_SHELL_VARIABLE_GUID.data1 = 0x158def5a;
  585. EFI_SHELL_VARIABLE_GUID.data2 = 0xf656;
  586. EFI_SHELL_VARIABLE_GUID.data3 = 0x419c;
  587. EFI_SHELL_VARIABLE_GUID.data4[0] = 0xb0;
  588. EFI_SHELL_VARIABLE_GUID.data4[1] = 0x27;
  589. EFI_SHELL_VARIABLE_GUID.data4[2] = 0x7a;
  590. EFI_SHELL_VARIABLE_GUID.data4[3] = 0x31;
  591. EFI_SHELL_VARIABLE_GUID.data4[4] = 0x92;
  592. EFI_SHELL_VARIABLE_GUID.data4[5] = 0xc0;
  593. EFI_SHELL_VARIABLE_GUID.data4[6] = 0x79;
  594. EFI_SHELL_VARIABLE_GUID.data4[7] = 0xd2;
  595. unsigned size = __ENV_NAME_MAX;
  596. unsigned rval;
  597. unsigned envc = 0;
  598. char* name = calloc(size, 1);
  599. struct efi_guid vendor_guid;
  600. /* First count the number of environmental variables */
  601. do
  602. {
  603. size = __ENV_NAME_MAX;
  604. rval = _get_next_variable_name(&size, name, &vendor_guid);
  605. if(rval == EFI_SUCCESS)
  606. {
  607. if(memcmp(&vendor_guid, &EFI_SHELL_VARIABLE_GUID, sizeof(struct efi_guid)) == 0)
  608. {
  609. envc += 1;
  610. }
  611. }
  612. } while(rval == EFI_SUCCESS);
  613. /* Now redo the search but this time populate envp array */
  614. envp = calloc(sizeof(char*), envc + 1);
  615. name[0] = 0;
  616. name[1] = 0;
  617. unsigned j = 0;
  618. do
  619. {
  620. size = __ENV_NAME_MAX;
  621. rval = _get_next_variable_name(&size, name, &vendor_guid);
  622. if(rval == EFI_SUCCESS)
  623. {
  624. if(memcmp(&vendor_guid, &EFI_SHELL_VARIABLE_GUID, sizeof(struct efi_guid)) == 0)
  625. {
  626. envp[j] = _get_environmental_variable(&vendor_guid, name, size);
  627. j += 1;
  628. }
  629. }
  630. } while(rval == EFI_SUCCESS);
  631. envp[j] = 0;
  632. free(name);
  633. return envp;
  634. }
  635. void _wipe_environment()
  636. {
  637. char** envp = _get_environmental_variables(envp);
  638. unsigned i = 0;
  639. unsigned j;
  640. char* name;
  641. while(envp[i] != 0)
  642. {
  643. j = 0;
  644. name = envp[i];
  645. while(envp[i][j] != '=')
  646. {
  647. j += 1;
  648. }
  649. envp[i][j] = 0;
  650. _set_variable(name, "");
  651. i += 1;
  652. }
  653. free(envp);
  654. }
  655. int strcmp(char const* lhs, char const* rhs);
  656. char* strchr(char const* str, int ch);
  657. void _setup_current_working_directory(char** envp)
  658. {
  659. _cwd = calloc(__PATH_MAX, 1);
  660. _root = calloc(__PATH_MAX, 1);
  661. unsigned i = 0;
  662. unsigned j;
  663. unsigned k;
  664. char* value;
  665. char* match;
  666. while(envp[i] != 0)
  667. {
  668. j = 0;
  669. while(envp[i][j] != '=')
  670. {
  671. j += 1;
  672. }
  673. envp[i][j] = 0;
  674. if(strcmp(envp[i], "root") == 0)
  675. {
  676. value = envp[i] + j + 1;
  677. match = strchr(value, ':'); /* strip uefi device, e.g. fs0: */
  678. if(match != NULL)
  679. {
  680. value = match + 1;
  681. }
  682. strcpy(_root, value);
  683. k = 0;
  684. while(_root[k] != '\0')
  685. {
  686. if(_root[k] == '\\')
  687. {
  688. _root[k] = '/';
  689. }
  690. k += 1;
  691. }
  692. }
  693. else if(strcmp(envp[i], "cwd") == 0)
  694. {
  695. value = envp[i] + j + 1;
  696. match = strchr(value, ':'); /* strip uefi device, e.g. fs0: */
  697. if(match != NULL)
  698. {
  699. value = match + 1;
  700. }
  701. strcpy(_cwd, value);
  702. k = 0;
  703. while(_cwd[k] != '\0')
  704. {
  705. if(_cwd[k] == '\\')
  706. {
  707. _cwd[k] = '/';
  708. }
  709. k += 1;
  710. }
  711. }
  712. envp[i][j] = '=';
  713. i += 1;
  714. }
  715. if(strcmp(_cwd, "") == 0)
  716. {
  717. strcpy(_cwd, "/");
  718. }
  719. }
  720. void* malloc(unsigned size);
  721. void __init_io();
  722. void _init()
  723. {
  724. /* Allocate user stack, UEFI stack is not big enough for compilers */
  725. __user_stack = malloc(USER_STACK_SIZE) + USER_STACK_SIZE;
  726. /* Process command line arguments */
  727. EFI_LOADED_IMAGE_PROTOCOL_GUID.data1 = 0x5b1b31a1;
  728. EFI_LOADED_IMAGE_PROTOCOL_GUID.data2 = 0x9562;
  729. EFI_LOADED_IMAGE_PROTOCOL_GUID.data3 = 0x11d2;
  730. EFI_LOADED_IMAGE_PROTOCOL_GUID.data4[0] = 0x8e;
  731. EFI_LOADED_IMAGE_PROTOCOL_GUID.data4[1] = 0x3f;
  732. EFI_LOADED_IMAGE_PROTOCOL_GUID.data4[2] = 0;
  733. EFI_LOADED_IMAGE_PROTOCOL_GUID.data4[3] = 0xa0;
  734. EFI_LOADED_IMAGE_PROTOCOL_GUID.data4[4] = 0xc9;
  735. EFI_LOADED_IMAGE_PROTOCOL_GUID.data4[5] = 0x69;
  736. EFI_LOADED_IMAGE_PROTOCOL_GUID.data4[6] = 0x72;
  737. EFI_LOADED_IMAGE_PROTOCOL_GUID.data4[7] = 0x3b;
  738. __init_io();
  739. _open_protocol(_image_handle, &EFI_LOADED_IMAGE_PROTOCOL_GUID, &_image, _image_handle, 0, EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL);
  740. char* load_options = calloc(_image->load_options_size, 1);
  741. wcstombs(load_options, _image->load_options, _image->load_options_size);
  742. _process_load_options(load_options);
  743. EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID.data1 = 0x964E5B22;
  744. EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID.data2 = 0x6459;
  745. EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID.data3 = 0x11d2;
  746. EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID.data4[0] = 0x8e;
  747. EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID.data4[1] = 0x39;
  748. EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID.data4[2] = 0;
  749. EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID.data4[3] = 0xa0;
  750. EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID.data4[4] = 0xc9;
  751. EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID.data4[5] = 0x69;
  752. EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID.data4[6] = 0x72;
  753. EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID.data4[7] = 0x3b;
  754. _root_device = _image->device;
  755. struct efi_simple_file_system_protocol* rootfs;
  756. _open_protocol(_root_device, &EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID, &rootfs, _image_handle, 0, EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL);
  757. _open_volume(rootfs, &_rootdir);
  758. EFI_FILE_INFO_GUID.data1 = 0x09576e92;
  759. EFI_FILE_INFO_GUID.data2 = 0x6d3f;
  760. EFI_FILE_INFO_GUID.data3 = 0x11d2;
  761. EFI_FILE_INFO_GUID.data4[0] = 0x8e;
  762. EFI_FILE_INFO_GUID.data4[1] = 0x39;
  763. EFI_FILE_INFO_GUID.data4[2] = 0;
  764. EFI_FILE_INFO_GUID.data4[3] = 0xa0;
  765. EFI_FILE_INFO_GUID.data4[4] = 0xc9;
  766. EFI_FILE_INFO_GUID.data4[5] = 0x69;
  767. EFI_FILE_INFO_GUID.data4[6] = 0x72;
  768. EFI_FILE_INFO_GUID.data4[7] = 0x3b;
  769. _envp = _get_environmental_variables(_envp);
  770. _setup_current_working_directory(_envp);
  771. }
  772. void __kill_io();
  773. void* _malloc_release_all(FUNCTION _free);
  774. void _cleanup()
  775. {
  776. __kill_io();
  777. _close(_rootdir);
  778. _close_protocol(_root_device, &EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID, _image_handle, 0);
  779. _close_protocol(_image_handle, &EFI_LOADED_IMAGE_PROTOCOL_GUID, _image_handle, 0);
  780. _malloc_release_all(_free_pool);
  781. }
  782. void* _malloc_uefi(unsigned size)
  783. {
  784. void* memory_block;
  785. if(_allocate_pool(EFI_LOADER_DATA, size, &memory_block) != EFI_SUCCESS)
  786. {
  787. return 0;
  788. }
  789. return memory_block;
  790. }
  791. #endif