run_tcc_ipxe.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515
  1. /* This file is part of asmc, a bootstrapping OS with minimal seed
  2. Copyright (C) 2019 Giovanni Mascellani <gio@debian.org>
  3. https://gitlab.com/giomasce/asmc
  4. This program 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. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program. If not, see <https://www.gnu.org/licenses/>. */
  14. #include <stdio.h>
  15. #include <stdlib.h>
  16. #include <string.h>
  17. #include <assert.h>
  18. #include "coros.h"
  19. #define TCC_TARGET_I386 1
  20. #define __i386__ 1
  21. #define USE_SOFTFLOAT 1
  22. #define ONE_SOURCE 1
  23. #include "tcc.h"
  24. // Silence some internal tcc warnings
  25. #undef free
  26. #undef malloc
  27. #undef realloc
  28. #undef strdup
  29. #define ASMC_PREFIX "/disk1"
  30. #define IPXE_PREFIX ASMC_PREFIX "/ipxe/src"
  31. #define IPXE_TEMP "/ram/ipxe"
  32. const char *includes[] = {
  33. ASMC_PREFIX,
  34. IPXE_PREFIX,
  35. IPXE_PREFIX "/include",
  36. IPXE_PREFIX "/arch/x86/include",
  37. IPXE_PREFIX "/arch/i386/include",
  38. IPXE_PREFIX "/arch/i386/include/pcbios",
  39. };
  40. const char *includes2[] = {
  41. ASMC_PREFIX,
  42. ASMC_PREFIX "/stdlib",
  43. };
  44. const char *sources[][2] = {
  45. {ASMC_PREFIX "/run_ipxe.c", IPXE_TEMP "/run_ipxe.o"},
  46. {ASMC_PREFIX "/tinycc/lib/libtcc1.c", IPXE_TEMP "/libtcc1.o"},
  47. {IPXE_PREFIX "/core/main.c", IPXE_TEMP "/main.o"},
  48. {IPXE_PREFIX "/core/init.c", IPXE_TEMP "/init.o"},
  49. {IPXE_PREFIX "/core/vsprintf.c", IPXE_TEMP "/vsprintf.o"},
  50. {IPXE_PREFIX "/core/console.c", IPXE_TEMP "/console.o"},
  51. {IPXE_PREFIX "/arch/x86/interface/pcbios/bios_nap.c", IPXE_TEMP "/bios_nap.o"},
  52. {IPXE_PREFIX "/core/process.c", IPXE_TEMP "/process.o"},
  53. {IPXE_PREFIX "/core/refcnt.c", IPXE_TEMP "/refcnt.o"},
  54. {IPXE_PREFIX "/core/list.c", IPXE_TEMP "/list.o"},
  55. {IPXE_PREFIX "/core/malloc.c", IPXE_TEMP "/malloc.o"},
  56. {IPXE_PREFIX "/arch/x86/core/x86_string.c", IPXE_TEMP "/x86_string.o"},
  57. {IPXE_PREFIX "/core/serial.c", IPXE_TEMP "/serial.o"},
  58. {IPXE_PREFIX "/core/uart.c", IPXE_TEMP "/uart.o"},
  59. {IPXE_PREFIX "/arch/x86/core/x86_uart.c", IPXE_TEMP "/x86_uart.o"},
  60. {IPXE_PREFIX "/core/interface.c", IPXE_TEMP "/interface.o"},
  61. {IPXE_PREFIX "/core/device.c", IPXE_TEMP "/device.o"},
  62. {IPXE_PREFIX "/drivers/bus/pci.c", IPXE_TEMP "/pci.o"},
  63. {IPXE_PREFIX "/arch/x86/core/pcidirect.c", IPXE_TEMP "/pcidirect.o"},
  64. {IPXE_PREFIX "/core/debug.c", IPXE_TEMP "/debug.o"},
  65. {IPXE_PREFIX "/core/timer.c", IPXE_TEMP "/timer.o"},
  66. {IPXE_PREFIX "/arch/x86/core/rdtsc_timer.c", IPXE_TEMP "/rdtsc_timer.o"},
  67. {IPXE_PREFIX "/arch/x86/core/pit8254.c", IPXE_TEMP "/pit8254.o"},
  68. {IPXE_PREFIX "/arch/x86/core/cpuid.c", IPXE_TEMP "/cpuid.o"},
  69. {IPXE_PREFIX "/arch/x86/interface/pcbios/acpi_timer.c", IPXE_TEMP "/acpi_timer.o"},
  70. {IPXE_PREFIX "/core/acpi.c", IPXE_TEMP "/acpi.o"},
  71. {IPXE_PREFIX "/arch/x86/interface/pcbios/rsdp.c", IPXE_TEMP "/rsdp.o"},
  72. {IPXE_PREFIX "/core/string.c", IPXE_TEMP "/string.o"},
  73. {IPXE_PREFIX "/core/ctype.c", IPXE_TEMP "/ctype.o"},
  74. {IPXE_PREFIX "/drivers/net/intel.c", IPXE_TEMP "/intel.o"},
  75. {IPXE_PREFIX "/drivers/nvs/nvs.c", IPXE_TEMP "/nvs.o"},
  76. {IPXE_PREFIX "/core/iobuf.c", IPXE_TEMP "/iobuf.o"},
  77. {IPXE_PREFIX "/net/netdevice.c", IPXE_TEMP "/netdevice.o"},
  78. {IPXE_PREFIX "/core/settings.c", IPXE_TEMP "/settings.o"},
  79. {IPXE_PREFIX "/net/ethernet.c", IPXE_TEMP "/ethernet.o"},
  80. {IPXE_PREFIX "/core/uri.c", IPXE_TEMP "/uri.o"},
  81. {IPXE_PREFIX "/core/base16.c", IPXE_TEMP "/base16.o"},
  82. {IPXE_PREFIX "/core/base64.c", IPXE_TEMP "/base64.o"},
  83. {IPXE_PREFIX "/net/socket.c", IPXE_TEMP "/socket.o"},
  84. {IPXE_PREFIX "/core/basename.c", IPXE_TEMP "/basename.o"},
  85. {IPXE_PREFIX "/core/uuid.c", IPXE_TEMP "/uuid.o"},
  86. {IPXE_PREFIX "/core/random.c", IPXE_TEMP "/random.o"},
  87. {IPXE_PREFIX "/core/asprintf.c", IPXE_TEMP "/asprintf.o"},
  88. {IPXE_PREFIX "/arch/x86/interface/pcbios/rtc_time.c", IPXE_TEMP "/rtc_time.o"},
  89. {IPXE_PREFIX "/core/time.c", IPXE_TEMP "/time.o"},
  90. {IPXE_PREFIX "/net/nullnet.c", IPXE_TEMP "/nullnet.o"},
  91. {IPXE_PREFIX "/net/retry.c", IPXE_TEMP "/retry.o"},
  92. {IPXE_PREFIX "/core/fault.c", IPXE_TEMP "/fault.o"},
  93. {IPXE_PREFIX "/core/params.c", IPXE_TEMP "/params.o"},
  94. {IPXE_PREFIX "/net/netdev_settings.c", IPXE_TEMP "/netdev_settings.o"},
  95. {IPXE_PREFIX "/core/errno.c", IPXE_TEMP "/errno.o"},
  96. {IPXE_PREFIX "/net/udp/dhcp.c", IPXE_TEMP "/dhcp.o"},
  97. {IPXE_PREFIX "/net/dhcppkt.c", IPXE_TEMP "/dhcppkt.o"},
  98. {IPXE_PREFIX "/net/dhcpopts.c", IPXE_TEMP "/dhcpopts.o"},
  99. {IPXE_PREFIX "/net/udp.c", IPXE_TEMP "/udp.o"},
  100. {IPXE_PREFIX "/net/tcpip.c", IPXE_TEMP "/tcpip.o"},
  101. {IPXE_PREFIX "/net/ipv4.c", IPXE_TEMP "/ipv4.o"},
  102. {IPXE_PREFIX "/net/icmpv4.c", IPXE_TEMP "/icmpv4.o"},
  103. {IPXE_PREFIX "/net/fragment.c", IPXE_TEMP "/fragment.o"},
  104. {IPXE_PREFIX "/net/neighbour.c", IPXE_TEMP "/neighbour.o"},
  105. {IPXE_PREFIX "/net/arp.c", IPXE_TEMP "/arp.o"},
  106. {IPXE_PREFIX "/net/icmp.c", IPXE_TEMP "/icmp.o"},
  107. {IPXE_PREFIX "/crypto/crc32.c", IPXE_TEMP "/crc32.o"},
  108. {IPXE_PREFIX "/core/xfer.c", IPXE_TEMP "/xfer.o"},
  109. {IPXE_PREFIX "/core/open.c", IPXE_TEMP "/open.o"},
  110. {IPXE_PREFIX "/core/resolv.c", IPXE_TEMP "/resolv.o"},
  111. {IPXE_PREFIX "/net/ping.c", IPXE_TEMP "/ping.o"},
  112. {IPXE_PREFIX "/net/tcp.c", IPXE_TEMP "/tcp.o"},
  113. {IPXE_PREFIX "/core/cwuri.c", IPXE_TEMP "/cwuri.o"},
  114. {IPXE_PREFIX "/core/pending.c", IPXE_TEMP "/pending.o"},
  115. {IPXE_PREFIX "/interface/smbios/smbios_settings.c", IPXE_TEMP "/smbios_settings.o"},
  116. {IPXE_PREFIX "/interface/smbios/smbios.c", IPXE_TEMP "/smbios.o"},
  117. {IPXE_PREFIX "/arch/x86/interface/pcbios/bios_smbios.c", IPXE_TEMP "/bios_smbios.o"},
  118. {IPXE_PREFIX "/usr/ifmgmt.c", IPXE_TEMP "/ifmgmt.o"},
  119. {IPXE_PREFIX "/core/job.c", IPXE_TEMP "/job.o"},
  120. {IPXE_PREFIX "/core/monojob.c", IPXE_TEMP "/monojob.o"},
  121. {IPXE_PREFIX "/arch/x86/interface/pcbios/acpipwr.c", IPXE_TEMP "/acpipwr.o"},
  122. {IPXE_PREFIX "/drivers/net/virtio-net.c", IPXE_TEMP "/virtio-net.o"},
  123. {IPXE_PREFIX "/drivers/bus/virtio-pci.c", IPXE_TEMP "/virtio-pci.o"},
  124. {IPXE_PREFIX "/drivers/bus/virtio-ring.c", IPXE_TEMP "/virtio-ring.o"},
  125. {IPXE_PREFIX "/drivers/bus/pciextra.c", IPXE_TEMP "/pciextra.o"},
  126. /* {IPXE_PREFIX "/usr/autoboot.c", IPXE_TEMP "/autoboot.o"}, */
  127. /* {IPXE_PREFIX "/usr/prompt.c", IPXE_TEMP "/prompt.o"}, */
  128. /* {IPXE_PREFIX "/usr/route.c", IPXE_TEMP "/route.o"}, */
  129. /* {IPXE_PREFIX "/usr/route_ipv4.c", IPXE_TEMP "/route_ipv4.o"}, */
  130. /* {IPXE_PREFIX "/usr/imgmgmt.c", IPXE_TEMP "/imgmgmt.o"}, */
  131. /* {IPXE_PREFIX "/hci/shell.c", IPXE_TEMP "/shell.o"}, */
  132. /* {IPXE_PREFIX "/hci/readline.c", IPXE_TEMP "/readline.o"}, */
  133. /* {IPXE_PREFIX "/hci/editstring.c", IPXE_TEMP "/editstring.o"}, */
  134. /* {IPXE_PREFIX "/core/getkey.c", IPXE_TEMP "/getkey.o"}, */
  135. /* {IPXE_PREFIX "/core/exec.c", IPXE_TEMP "/exec.o"}, */
  136. /* {IPXE_PREFIX "/core/parseopt.c", IPXE_TEMP "/parseopt.o"}, */
  137. /* {IPXE_PREFIX "/core/getopt.c", IPXE_TEMP "/getopt.o"}, */
  138. /* {IPXE_PREFIX "/core/image.c", IPXE_TEMP "/image.o"}, */
  139. /* {IPXE_PREFIX "/core/downloader.c", IPXE_TEMP "/downloader.o"}, */
  140. /* {IPXE_PREFIX "/core/xferbuf.c", IPXE_TEMP "/xferbuf.o"}, */
  141. /* {IPXE_PREFIX "/core/menu.c", IPXE_TEMP "/menu.o"}, */
  142. /* {IPXE_PREFIX "/core/null_sanboot.c", IPXE_TEMP "/null_sanboot.o"}, */
  143. /* {IPXE_PREFIX "/core/sanboot.c", IPXE_TEMP "/sanboot.o"}, */
  144. /* {IPXE_PREFIX "/drivers/block/ata.c", IPXE_TEMP "/ata.o"}, */
  145. /* {IPXE_PREFIX "/core/blockdev.c", IPXE_TEMP "/blockdev.o"}, */
  146. /* {IPXE_PREFIX "/core/edd.c", IPXE_TEMP "/edd.o"}, */
  147. /* {IPXE_PREFIX "/core/quiesce.c", IPXE_TEMP "/quiesce.o"}, */
  148. {IPXE_PREFIX "/net/tcp/http.c", IPXE_TEMP "/http.o"},
  149. {IPXE_PREFIX "/net/tcp/httpcore.c", IPXE_TEMP "/httpcore.o"},
  150. {IPXE_PREFIX "/net/tcp/httpconn.c", IPXE_TEMP "/httpconn.o"},
  151. {IPXE_PREFIX "/core/pool.c", IPXE_TEMP "/pool.o"},
  152. {IPXE_PREFIX "/core/blockdev.c", IPXE_TEMP "/blockdev.o"},
  153. {IPXE_PREFIX "/core/linebuf.c", IPXE_TEMP "/linebuf.o"},
  154. {IPXE_PREFIX "/core/xferbuf.c", IPXE_TEMP "/xferbuf.o"},
  155. {IPXE_PREFIX "/usr/imgmgmt.c", IPXE_TEMP "/imgmgmt.o"},
  156. {IPXE_PREFIX "/core/image.c", IPXE_TEMP "/image.o"},
  157. {IPXE_PREFIX "/core/downloader.c", IPXE_TEMP "/downloader.o"},
  158. {IPXE_PREFIX "/net/udp/dns.c", IPXE_TEMP "/dns.o"},
  159. };
  160. #include "ipxe_handover.h"
  161. #include "asmc_api.h"
  162. #include "sha-2/sha-256.c"
  163. void *read_whole_file(FILE *fin, size_t *size) {
  164. size_t buf_size = 16;
  165. char *buf = malloc(buf_size);
  166. size_t buf_pos = 0;
  167. while (1) {
  168. size_t res = fread(buf + buf_pos, 1, buf_size - buf_pos, fin);
  169. buf_pos += res;
  170. if (buf_pos < buf_size) {
  171. break;
  172. } else {
  173. buf_size *= 2;
  174. buf = realloc(buf, buf_size);
  175. }
  176. }
  177. if (size) {
  178. *size = buf_pos;
  179. }
  180. return buf;
  181. }
  182. void compute_file_sha256(const char *filename, uint8_t hash[32]) {
  183. FILE *fin = fopen(filename, "rb");
  184. size_t size;
  185. void *buf = read_whole_file(fin, &size);
  186. fclose(fin);
  187. calc_sha_256(hash, buf, size);
  188. free(buf);
  189. }
  190. int table_comp(void *t1, void *t2) {
  191. table_sect *s1 = t1;
  192. table_sect *s2 = t2;
  193. return strcmp(s1->name, s2->name);
  194. }
  195. char *memdup(void *data, size_t len) {
  196. char *ret = malloc(len);
  197. memcpy(ret, data, len);
  198. return ret;
  199. }
  200. char *memappend(char *dest, size_t dest_size, char *src, size_t src_size) {
  201. dest = realloc(dest, dest_size + src_size);
  202. memcpy(dest + dest_size, src, src_size);
  203. return dest;
  204. }
  205. // This function manually performs the linker script trick used by
  206. // iPXE to support linking-time tables, which the tcc linker is not
  207. // powerful enough to do for us
  208. void prepare_tables(TCCState *state, ipxe_handover *ih) {
  209. int i;
  210. table_sect *subsects = malloc(sizeof(table_sect) * state->nb_sections);
  211. int subsects_num = 0;
  212. for (i = 1; i < state->nb_sections; i++) {
  213. char *name = state->sections[i]->name;
  214. if (strncmp(name, ".tbl.", 5) == 0) {
  215. subsects[subsects_num].name = strdup(name + 5);
  216. subsects[subsects_num].data = (char*) state->sections[i]->sh_addr;
  217. subsects[subsects_num].len = state->sections[i]->data_offset;
  218. subsects_num++;
  219. }
  220. }
  221. // Funny cast to acquiesce tcc warning about incompatible pointers
  222. qsort(subsects, subsects_num, sizeof(table_sect), (int (*)(const void *, const void *))table_comp);
  223. /*printf("Subsections:\n");
  224. for (i = 0; i < subsects_num; i++) {
  225. printf(" * %s (addr: %x, size: %d)\n", subsects[i].name, subsects[i].data, subsects[i].len);
  226. }*/
  227. table_sect *sects = malloc(sizeof(table_sect) * subsects_num);
  228. int sects_num = 0;
  229. for (i = 0; i < subsects_num; i++) {
  230. char *subsect_name = subsects[i].name;
  231. char *dot_pos = strchr(subsect_name, '.');
  232. assert(dot_pos);
  233. size_t name_len = dot_pos - subsect_name;
  234. // We also check the dot in order not to be fooled by prefixes
  235. if (sects_num == 0 || strncmp(subsect_name, sects[sects_num-1].name, name_len + 1) != 0) {
  236. // New section
  237. sects[sects_num].name = subsects[i].name;
  238. sects[sects_num].name[name_len+1] = '\0';
  239. sects[sects_num].data = memappend(NULL, 0, subsects[i].data, subsects[i].len);
  240. sects[sects_num].len = subsects[i].len;
  241. sects_num++;
  242. } else {
  243. // Continuing previous section
  244. sects[sects_num-1].data = memappend(sects[sects_num-1].data, sects[sects_num-1].len,
  245. subsects[i].data, subsects[i].len);
  246. sects[sects_num-1].len += subsects[i].len;
  247. free(subsects[i].name);
  248. }
  249. }
  250. free(subsects);
  251. printf("Sections:\n");
  252. for (i = 0; i < sects_num; i++) {
  253. // Finally cut away the dot
  254. sects[i].name[strlen(sects[i].name)-1] = '\0';
  255. printf(" * %s (addr: %x, size: %d)\n", sects[i].name, sects[i].data, sects[i].len);
  256. /* if (strcmp(sects[i].name, "timers") == 0) { */
  257. /* printf("%s\n", *(char**)sects[i].data); */
  258. /* } */
  259. }
  260. ih->sects_num = sects_num;
  261. ih->sects = sects;
  262. }
  263. void free_handover(ipxe_handover *ih) {
  264. int i;
  265. for (i = 0; i < ih->sects_num; i++) {
  266. free(ih->sects[i].name);
  267. free(ih->sects[i].data);
  268. }
  269. free(ih->sects);
  270. }
  271. ipxe_handover ih;
  272. void push_to_ipxe(void *msg) {
  273. ipxe_list_push(&ih, &ih.to_ipxe, msg);
  274. }
  275. void *pop_from_ipxe() {
  276. return ipxe_list_pop(&ih, &ih.from_ipxe);
  277. }
  278. coro_t *coro_ipxe;
  279. void download_file(const char *url, const char *dest_file) {
  280. push_to_ipxe(strdup("download"));
  281. push_to_ipxe(strdup(url));
  282. coro_enter(coro_ipxe);
  283. downloaded_file *df = pop_from_ipxe();
  284. assert(df->size > 0);
  285. FILE *fout = fopen(dest_file, "wb");
  286. fwrite(df->data, 1, df->size, fout);
  287. fclose(fout);
  288. free(df->data);
  289. free(df);
  290. }
  291. void download_check_file(const char *url, const char *dest_file, const uint8_t hash[32]) {
  292. push_to_ipxe(strdup("download"));
  293. push_to_ipxe(strdup(url));
  294. coro_enter(coro_ipxe);
  295. downloaded_file *df = pop_from_ipxe();
  296. assert(df->size > 0);
  297. uint8_t computed_hash[32];
  298. calc_sha_256(computed_hash, df->data, df->size);
  299. printf("Computed hash:");
  300. size_t i;
  301. for (i = 0; i < 32; i++) {
  302. printf(" %02x", computed_hash[i]);
  303. }
  304. printf("\n");
  305. for (i = 0; i < 32; i++) {
  306. assert(computed_hash[i] == hash[i]);
  307. }
  308. FILE *fout = fopen(dest_file, "wb");
  309. fwrite(df->data, 1, df->size, fout);
  310. fclose(fout);
  311. free(df->data);
  312. free(df);
  313. }
  314. void *compile_file(const char *filename, const char *symbol, void **buffer) {
  315. TCCState *state = tcc_new();
  316. tcc_set_options(state, "-nostdinc -nostdlib");
  317. tcc_set_output_type(state, TCC_OUTPUT_OBJ);
  318. char buf[1024];
  319. sprintf(buf, "%d", __get_handles());
  320. tcc_define_symbol(state, "__HANDLES", buf);
  321. tcc_add_symbol(state, "tcc_new", tcc_new);
  322. tcc_add_symbol(state, "tcc_delete", tcc_delete);
  323. tcc_add_symbol(state, "tcc_set_lib_path", tcc_set_lib_path);
  324. tcc_add_symbol(state, "tcc_set_error_func", tcc_set_error_func);
  325. tcc_add_symbol(state, "tcc_set_options", tcc_set_options);
  326. tcc_add_symbol(state, "tcc_add_include_path", tcc_add_include_path);
  327. tcc_add_symbol(state, "tcc_add_sysinclude_path", tcc_add_sysinclude_path);
  328. tcc_add_symbol(state, "tcc_define_symbol", tcc_define_symbol);
  329. tcc_add_symbol(state, "tcc_undefine_symbol", tcc_undefine_symbol);
  330. tcc_add_symbol(state, "tcc_add_file", tcc_add_file);
  331. tcc_add_symbol(state, "tcc_compile_string", tcc_compile_string);
  332. tcc_add_symbol(state, "tcc_set_output_type", tcc_set_output_type);
  333. tcc_add_symbol(state, "tcc_add_library_path", tcc_add_library_path);
  334. tcc_add_symbol(state, "tcc_add_library", tcc_add_library);
  335. tcc_add_symbol(state, "tcc_add_symbol", tcc_add_symbol);
  336. tcc_add_symbol(state, "tcc_output_file", tcc_output_file);
  337. tcc_add_symbol(state, "tcc_run", tcc_run);
  338. tcc_add_symbol(state, "tcc_relocate", tcc_relocate);
  339. tcc_add_symbol(state, "tcc_get_symbol", tcc_get_symbol);
  340. tcc_add_symbol(state, "download_file", download_file);
  341. tcc_add_symbol(state, "compile_file", compile_file);
  342. tcc_add_symbol(state, "calc_sha_256", calc_sha_256);
  343. tcc_add_symbol(state, "read_whole_file", read_whole_file);
  344. tcc_add_symbol(state, "compute_file_sha256", compute_file_sha256);
  345. int res;
  346. for (int i = 0; i < sizeof(includes2) / sizeof(includes2[0]); i++) {
  347. res = tcc_add_include_path(state, includes2[i]);
  348. if (res) {
  349. printf("tcc_add_include_path() failed...\n");
  350. return 0;
  351. }
  352. }
  353. res = tcc_add_file(state, filename);
  354. if (res) {
  355. printf("tcc_add_file() failed...\n");
  356. return 0;
  357. }
  358. int size = tcc_relocate(state, NULL);
  359. if (size < 0) {
  360. printf("tcc_relocate() failed...\n");
  361. return 0;
  362. }
  363. *buffer = malloc(size);
  364. size = tcc_relocate(state, *buffer);
  365. if (size < 0) {
  366. printf("second tcc_relocate() failed...\n");
  367. return 0;
  368. }
  369. void *symb = tcc_get_symbol(state, symbol);
  370. tcc_delete(state);
  371. return symb;
  372. }
  373. int main(int argc, char *argv[]) {
  374. printf("Here is where we compile iPXE!\n");
  375. int res;
  376. TCCState *state;
  377. // First compile all files
  378. for (int j = 0; j < sizeof(sources) / sizeof(sources[0]); j++) {
  379. printf("Compiling %s to %s...", sources[j][0], sources[j][1]);
  380. state = tcc_new();
  381. tcc_set_options(state, "-nostdinc -nostdlib -include " IPXE_PREFIX "/include/compiler.h");
  382. tcc_set_output_type(state, TCC_OUTPUT_OBJ);
  383. tcc_define_symbol(state, "ARCH", "i386");
  384. tcc_define_symbol(state, "PLATFORM", "pcbios");
  385. tcc_define_symbol(state, "SECUREBOOT", "0");
  386. char buf[1024];
  387. sprintf(buf, "%d", __get_handles());
  388. tcc_define_symbol(state, "__HANDLES", buf);
  389. for (int i = 0; i < sizeof(includes) / sizeof(includes[0]); i++) {
  390. res = tcc_add_include_path(state, includes[i]);
  391. if (res) {
  392. printf("tcc_add_include_path() failed...\n");
  393. return 1;
  394. }
  395. }
  396. res = tcc_add_file(state, sources[j][0]);
  397. if (res) {
  398. printf("tcc_add_file() failed...\n");
  399. return 1;
  400. }
  401. res = tcc_output_file(state, sources[j][1]);
  402. if (res) {
  403. printf("tcc_output_file() failed...\n");
  404. return 1;
  405. }
  406. tcc_delete(state);
  407. printf(" done!\n");
  408. }
  409. // Then link everything together
  410. printf("Linking IPXE...");
  411. state = tcc_new();
  412. tcc_set_options(state, "-nostdinc -nostdlib");
  413. tcc_set_output_type(state, TCC_OUTPUT_MEMORY);
  414. for (int i = 0; i < sizeof(sources) / sizeof(sources[0]); i++) {
  415. res = tcc_add_file(state, sources[i][1]);
  416. if (res) {
  417. printf("tcc_add_file() failed...\n");
  418. return 1;
  419. }
  420. }
  421. size_t ipxe_size = tcc_relocate(state, NULL);
  422. void *ipxe_buf = malloc(ipxe_size);
  423. res = tcc_relocate(state, ipxe_buf);
  424. if (res) {
  425. printf("tcc_relocate() failed...\n");
  426. return 1;
  427. }
  428. printf(" done!\n");
  429. printf("iPXE compiled to %x:%x\n", ipxe_buf, ipxe_buf + ipxe_size);
  430. // Start iPXE in a dedicated coroutine
  431. void (*main_symb)(void*) = tcc_get_symbol(state, "pre_main");
  432. if (!main_symb) {
  433. printf("tcc_get_symbol() failed...\n");
  434. return 1;
  435. }
  436. prepare_tables(state, &ih);
  437. ipxe_list_reset(&ih.to_ipxe);
  438. ipxe_list_reset(&ih.from_ipxe);
  439. ih.coro_yield = coro_yield;
  440. ih.malloc = malloc;
  441. ih.free = free;
  442. printf("Starting iPXE coroutine!\n");
  443. coro_ipxe = coro_init(main_symb, &ih);
  444. coro_enter(coro_ipxe);
  445. // Download the continuation program
  446. const char *url = "http://10.0.2.2:8080/continue.c";
  447. printf("Request to download %s...\n", url);
  448. const uint32_t hash[32] = {0xEB, 0x42, 0xD9, 0x44, 0xC2, 0x2E, 0x46, 0x4F, 0x39, 0xAF, 0x75, 0x31, 0xED, 0x74, 0x99, 0xA1,
  449. 0x1D, 0xC5, 0xDC, 0x6E, 0x34, 0x77, 0x3C, 0x35, 0xFE, 0x14, 0x1B, 0xAC, 0x5D, 0x53, 0x3D, 0x5D};
  450. download_file(url, "/ram/continue.c");
  451. //download_check_file(url, "/ram/continue.c", hash);
  452. void *cont_buf;
  453. int (*cont_symb)(int, char*[]) = compile_file("/ram/continue.c", "_start", &cont_buf);
  454. if (!cont_symb) {
  455. printf("Compilation failed...\n");
  456. return 1;
  457. }
  458. char *cont_argv[] = {"_main"};
  459. cont_symb(sizeof(cont_argv) / sizeof(cont_argv[0]), cont_argv);
  460. free(cont_buf);
  461. printf("Request to exit iPXE\n");
  462. push_to_ipxe(strdup("exit"));
  463. coro_enter(coro_ipxe);
  464. //res = main_symb(&ih);
  465. printf("iPXE exited!\n");
  466. coro_destroy(coro_ipxe);
  467. free_handover(&ih);
  468. free(ipxe_buf);
  469. tcc_delete(state);
  470. return res;
  471. }