run_tcc_ipxe.c 20 KB

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