123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510 |
- /* This file is part of asmc, a bootstrapping OS with minimal seed
- Copyright (C) 2019 Giovanni Mascellani <gio@debian.org>
- https://gitlab.com/giomasce/asmc
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <https://www.gnu.org/licenses/>. */
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <assert.h>
- #include "coros.h"
- #define TCC_TARGET_I386 1
- #define __i386__ 1
- #define USE_SOFTFLOAT 1
- #define ONE_SOURCE 1
- #include "tcc.h"
- #define ASMC_PREFIX "/disk1"
- #define IPXE_PREFIX ASMC_PREFIX "/ipxe/src"
- #define IPXE_TEMP "/ram/ipxe"
- const char *includes[] = {
- ASMC_PREFIX,
- IPXE_PREFIX,
- IPXE_PREFIX "/include",
- IPXE_PREFIX "/arch/x86/include",
- IPXE_PREFIX "/arch/i386/include",
- IPXE_PREFIX "/arch/i386/include/pcbios",
- };
- const char *includes2[] = {
- ASMC_PREFIX,
- ASMC_PREFIX "/stdlib",
- };
- const char *sources[][2] = {
- {ASMC_PREFIX "/run_ipxe.c", IPXE_TEMP "/run_ipxe.o"},
- {ASMC_PREFIX "/tinycc/lib/libtcc1.c", IPXE_TEMP "/libtcc1.o"},
- {IPXE_PREFIX "/core/main.c", IPXE_TEMP "/main.o"},
- {IPXE_PREFIX "/core/init.c", IPXE_TEMP "/init.o"},
- {IPXE_PREFIX "/core/vsprintf.c", IPXE_TEMP "/vsprintf.o"},
- {IPXE_PREFIX "/core/console.c", IPXE_TEMP "/console.o"},
- {IPXE_PREFIX "/arch/x86/interface/pcbios/bios_nap.c", IPXE_TEMP "/bios_nap.o"},
- {IPXE_PREFIX "/core/process.c", IPXE_TEMP "/process.o"},
- {IPXE_PREFIX "/core/refcnt.c", IPXE_TEMP "/refcnt.o"},
- {IPXE_PREFIX "/core/list.c", IPXE_TEMP "/list.o"},
- {IPXE_PREFIX "/core/malloc.c", IPXE_TEMP "/malloc.o"},
- {IPXE_PREFIX "/arch/x86/core/x86_string.c", IPXE_TEMP "/x86_string.o"},
- {IPXE_PREFIX "/core/serial.c", IPXE_TEMP "/serial.o"},
- {IPXE_PREFIX "/core/uart.c", IPXE_TEMP "/uart.o"},
- {IPXE_PREFIX "/arch/x86/core/x86_uart.c", IPXE_TEMP "/x86_uart.o"},
- {IPXE_PREFIX "/core/interface.c", IPXE_TEMP "/interface.o"},
- {IPXE_PREFIX "/core/device.c", IPXE_TEMP "/device.o"},
- {IPXE_PREFIX "/drivers/bus/pci.c", IPXE_TEMP "/pci.o"},
- {IPXE_PREFIX "/arch/x86/core/pcidirect.c", IPXE_TEMP "/pcidirect.o"},
- {IPXE_PREFIX "/core/debug.c", IPXE_TEMP "/debug.o"},
- {IPXE_PREFIX "/core/timer.c", IPXE_TEMP "/timer.o"},
- {IPXE_PREFIX "/arch/x86/core/rdtsc_timer.c", IPXE_TEMP "/rdtsc_timer.o"},
- {IPXE_PREFIX "/arch/x86/core/pit8254.c", IPXE_TEMP "/pit8254.o"},
- {IPXE_PREFIX "/arch/x86/core/cpuid.c", IPXE_TEMP "/cpuid.o"},
- {IPXE_PREFIX "/arch/x86/interface/pcbios/acpi_timer.c", IPXE_TEMP "/acpi_timer.o"},
- {IPXE_PREFIX "/core/acpi.c", IPXE_TEMP "/acpi.o"},
- {IPXE_PREFIX "/arch/x86/interface/pcbios/rsdp.c", IPXE_TEMP "/rsdp.o"},
- {IPXE_PREFIX "/core/string.c", IPXE_TEMP "/string.o"},
- {IPXE_PREFIX "/core/ctype.c", IPXE_TEMP "/ctype.o"},
- {IPXE_PREFIX "/drivers/net/intel.c", IPXE_TEMP "/intel.o"},
- {IPXE_PREFIX "/drivers/nvs/nvs.c", IPXE_TEMP "/nvs.o"},
- {IPXE_PREFIX "/core/iobuf.c", IPXE_TEMP "/iobuf.o"},
- {IPXE_PREFIX "/net/netdevice.c", IPXE_TEMP "/netdevice.o"},
- {IPXE_PREFIX "/core/settings.c", IPXE_TEMP "/settings.o"},
- {IPXE_PREFIX "/net/ethernet.c", IPXE_TEMP "/ethernet.o"},
- {IPXE_PREFIX "/core/uri.c", IPXE_TEMP "/uri.o"},
- {IPXE_PREFIX "/core/base16.c", IPXE_TEMP "/base16.o"},
- {IPXE_PREFIX "/core/base64.c", IPXE_TEMP "/base64.o"},
- {IPXE_PREFIX "/net/socket.c", IPXE_TEMP "/socket.o"},
- {IPXE_PREFIX "/core/basename.c", IPXE_TEMP "/basename.o"},
- {IPXE_PREFIX "/core/uuid.c", IPXE_TEMP "/uuid.o"},
- {IPXE_PREFIX "/core/random.c", IPXE_TEMP "/random.o"},
- {IPXE_PREFIX "/core/asprintf.c", IPXE_TEMP "/asprintf.o"},
- {IPXE_PREFIX "/arch/x86/interface/pcbios/rtc_time.c", IPXE_TEMP "/rtc_time.o"},
- {IPXE_PREFIX "/core/time.c", IPXE_TEMP "/time.o"},
- {IPXE_PREFIX "/net/nullnet.c", IPXE_TEMP "/nullnet.o"},
- {IPXE_PREFIX "/net/retry.c", IPXE_TEMP "/retry.o"},
- {IPXE_PREFIX "/core/fault.c", IPXE_TEMP "/fault.o"},
- {IPXE_PREFIX "/core/params.c", IPXE_TEMP "/params.o"},
- {IPXE_PREFIX "/net/netdev_settings.c", IPXE_TEMP "/netdev_settings.o"},
- {IPXE_PREFIX "/core/errno.c", IPXE_TEMP "/errno.o"},
- {IPXE_PREFIX "/net/udp/dhcp.c", IPXE_TEMP "/dhcp.o"},
- {IPXE_PREFIX "/net/dhcppkt.c", IPXE_TEMP "/dhcppkt.o"},
- {IPXE_PREFIX "/net/dhcpopts.c", IPXE_TEMP "/dhcpopts.o"},
- {IPXE_PREFIX "/net/udp.c", IPXE_TEMP "/udp.o"},
- {IPXE_PREFIX "/net/tcpip.c", IPXE_TEMP "/tcpip.o"},
- {IPXE_PREFIX "/net/ipv4.c", IPXE_TEMP "/ipv4.o"},
- {IPXE_PREFIX "/net/icmpv4.c", IPXE_TEMP "/icmpv4.o"},
- {IPXE_PREFIX "/net/fragment.c", IPXE_TEMP "/fragment.o"},
- {IPXE_PREFIX "/net/neighbour.c", IPXE_TEMP "/neighbour.o"},
- {IPXE_PREFIX "/net/arp.c", IPXE_TEMP "/arp.o"},
- {IPXE_PREFIX "/net/icmp.c", IPXE_TEMP "/icmp.o"},
- {IPXE_PREFIX "/crypto/crc32.c", IPXE_TEMP "/crc32.o"},
- {IPXE_PREFIX "/core/xfer.c", IPXE_TEMP "/xfer.o"},
- {IPXE_PREFIX "/core/open.c", IPXE_TEMP "/open.o"},
- {IPXE_PREFIX "/core/resolv.c", IPXE_TEMP "/resolv.o"},
- {IPXE_PREFIX "/net/ping.c", IPXE_TEMP "/ping.o"},
- {IPXE_PREFIX "/net/tcp.c", IPXE_TEMP "/tcp.o"},
- {IPXE_PREFIX "/core/cwuri.c", IPXE_TEMP "/cwuri.o"},
- {IPXE_PREFIX "/core/pending.c", IPXE_TEMP "/pending.o"},
- {IPXE_PREFIX "/interface/smbios/smbios_settings.c", IPXE_TEMP "/smbios_settings.o"},
- {IPXE_PREFIX "/interface/smbios/smbios.c", IPXE_TEMP "/smbios.o"},
- {IPXE_PREFIX "/arch/x86/interface/pcbios/bios_smbios.c", IPXE_TEMP "/bios_smbios.o"},
- {IPXE_PREFIX "/usr/ifmgmt.c", IPXE_TEMP "/ifmgmt.o"},
- {IPXE_PREFIX "/core/job.c", IPXE_TEMP "/job.o"},
- {IPXE_PREFIX "/core/monojob.c", IPXE_TEMP "/monojob.o"},
- {IPXE_PREFIX "/arch/x86/interface/pcbios/acpipwr.c", IPXE_TEMP "/acpipwr.o"},
- {IPXE_PREFIX "/drivers/net/virtio-net.c", IPXE_TEMP "/virtio-net.o"},
- {IPXE_PREFIX "/drivers/bus/virtio-pci.c", IPXE_TEMP "/virtio-pci.o"},
- {IPXE_PREFIX "/drivers/bus/virtio-ring.c", IPXE_TEMP "/virtio-ring.o"},
- {IPXE_PREFIX "/drivers/bus/pciextra.c", IPXE_TEMP "/pciextra.o"},
- /* {IPXE_PREFIX "/usr/autoboot.c", IPXE_TEMP "/autoboot.o"}, */
- /* {IPXE_PREFIX "/usr/prompt.c", IPXE_TEMP "/prompt.o"}, */
- /* {IPXE_PREFIX "/usr/route.c", IPXE_TEMP "/route.o"}, */
- /* {IPXE_PREFIX "/usr/route_ipv4.c", IPXE_TEMP "/route_ipv4.o"}, */
- /* {IPXE_PREFIX "/usr/imgmgmt.c", IPXE_TEMP "/imgmgmt.o"}, */
- /* {IPXE_PREFIX "/hci/shell.c", IPXE_TEMP "/shell.o"}, */
- /* {IPXE_PREFIX "/hci/readline.c", IPXE_TEMP "/readline.o"}, */
- /* {IPXE_PREFIX "/hci/editstring.c", IPXE_TEMP "/editstring.o"}, */
- /* {IPXE_PREFIX "/core/getkey.c", IPXE_TEMP "/getkey.o"}, */
- /* {IPXE_PREFIX "/core/exec.c", IPXE_TEMP "/exec.o"}, */
- /* {IPXE_PREFIX "/core/parseopt.c", IPXE_TEMP "/parseopt.o"}, */
- /* {IPXE_PREFIX "/core/getopt.c", IPXE_TEMP "/getopt.o"}, */
- /* {IPXE_PREFIX "/core/image.c", IPXE_TEMP "/image.o"}, */
- /* {IPXE_PREFIX "/core/downloader.c", IPXE_TEMP "/downloader.o"}, */
- /* {IPXE_PREFIX "/core/xferbuf.c", IPXE_TEMP "/xferbuf.o"}, */
- /* {IPXE_PREFIX "/core/menu.c", IPXE_TEMP "/menu.o"}, */
- /* {IPXE_PREFIX "/core/null_sanboot.c", IPXE_TEMP "/null_sanboot.o"}, */
- /* {IPXE_PREFIX "/core/sanboot.c", IPXE_TEMP "/sanboot.o"}, */
- /* {IPXE_PREFIX "/drivers/block/ata.c", IPXE_TEMP "/ata.o"}, */
- /* {IPXE_PREFIX "/core/blockdev.c", IPXE_TEMP "/blockdev.o"}, */
- /* {IPXE_PREFIX "/core/edd.c", IPXE_TEMP "/edd.o"}, */
- /* {IPXE_PREFIX "/core/quiesce.c", IPXE_TEMP "/quiesce.o"}, */
- {IPXE_PREFIX "/net/tcp/http.c", IPXE_TEMP "/http.o"},
- {IPXE_PREFIX "/net/tcp/httpcore.c", IPXE_TEMP "/httpcore.o"},
- {IPXE_PREFIX "/net/tcp/httpconn.c", IPXE_TEMP "/httpconn.o"},
- {IPXE_PREFIX "/core/pool.c", IPXE_TEMP "/pool.o"},
- {IPXE_PREFIX "/core/blockdev.c", IPXE_TEMP "/blockdev.o"},
- {IPXE_PREFIX "/core/linebuf.c", IPXE_TEMP "/linebuf.o"},
- {IPXE_PREFIX "/core/xferbuf.c", IPXE_TEMP "/xferbuf.o"},
- {IPXE_PREFIX "/usr/imgmgmt.c", IPXE_TEMP "/imgmgmt.o"},
- {IPXE_PREFIX "/core/image.c", IPXE_TEMP "/image.o"},
- {IPXE_PREFIX "/core/downloader.c", IPXE_TEMP "/downloader.o"},
- {IPXE_PREFIX "/net/udp/dns.c", IPXE_TEMP "/dns.o"},
- };
- #include "ipxe_handover.h"
- #include "asmc_api.h"
- #include "sha-2/sha-256.c"
- void *read_whole_file(FILE *fin, size_t *size) {
- size_t buf_size = 16;
- char *buf = malloc(buf_size);
- size_t buf_pos = 0;
- while (1) {
- size_t res = fread(buf + buf_pos, 1, buf_size - buf_pos, fin);
- buf_pos += res;
- if (buf_pos < buf_size) {
- break;
- } else {
- buf_size *= 2;
- buf = realloc(buf, buf_size);
- }
- }
- if (size) {
- *size = buf_pos;
- }
- return buf;
- }
- void compute_file_sha256(const char *filename, uint8_t hash[32]) {
- FILE *fin = fopen(filename, "rb");
- size_t size;
- void *buf = read_whole_file(fin, &size);
- fclose(fin);
- calc_sha_256(hash, buf, size);
- free(buf);
- }
- int table_comp(void *t1, void *t2) {
- table_sect *s1 = t1;
- table_sect *s2 = t2;
- return strcmp(s1->name, s2->name);
- }
- char *memdup(void *data, size_t len) {
- char *ret = malloc(len);
- memcpy(ret, data, len);
- return ret;
- }
- char *memappend(char *dest, size_t dest_size, char *src, size_t src_size) {
- dest = realloc(dest, dest_size + src_size);
- memcpy(dest + dest_size, src, src_size);
- return dest;
- }
- // This function manually performs the linker script trick used by
- // iPXE to support linking-time tables, which the tcc linker is not
- // powerful enough to do for us
- void prepare_tables(TCCState *state, ipxe_handover *ih) {
- int i;
- table_sect *subsects = malloc(sizeof(table_sect) * state->nb_sections);
- int subsects_num = 0;
- for (i = 1; i < state->nb_sections; i++) {
- char *name = state->sections[i]->name;
- if (strncmp(name, ".tbl.", 5) == 0) {
- subsects[subsects_num].name = strdup(name + 5);
- subsects[subsects_num].data = (char*) state->sections[i]->sh_addr;
- subsects[subsects_num].len = state->sections[i]->data_offset;
- subsects_num++;
- }
- }
- // Funny cast to acquiesce tcc warning about incompatible pointers
- qsort(subsects, subsects_num, sizeof(table_sect), (int (*)(const void *, const void *))table_comp);
- /*printf("Subsections:\n");
- for (i = 0; i < subsects_num; i++) {
- printf(" * %s (addr: %x, size: %d)\n", subsects[i].name, subsects[i].data, subsects[i].len);
- }*/
- table_sect *sects = malloc(sizeof(table_sect) * subsects_num);
- int sects_num = 0;
- for (i = 0; i < subsects_num; i++) {
- char *subsect_name = subsects[i].name;
- char *dot_pos = strchr(subsect_name, '.');
- assert(dot_pos);
- size_t name_len = dot_pos - subsect_name;
- // We also check the dot in order not to be fooled by prefixes
- if (sects_num == 0 || strncmp(subsect_name, sects[sects_num-1].name, name_len + 1) != 0) {
- // New section
- sects[sects_num].name = subsects[i].name;
- sects[sects_num].name[name_len+1] = '\0';
- sects[sects_num].data = memappend(NULL, 0, subsects[i].data, subsects[i].len);
- sects[sects_num].len = subsects[i].len;
- sects_num++;
- } else {
- // Continuing previous section
- sects[sects_num-1].data = memappend(sects[sects_num-1].data, sects[sects_num-1].len,
- subsects[i].data, subsects[i].len);
- sects[sects_num-1].len += subsects[i].len;
- free(subsects[i].name);
- }
- }
- free(subsects);
- printf("Sections:\n");
- for (i = 0; i < sects_num; i++) {
- // Finally cut away the dot
- sects[i].name[strlen(sects[i].name)-1] = '\0';
- printf(" * %s (addr: %x, size: %d)\n", sects[i].name, sects[i].data, sects[i].len);
- /* if (strcmp(sects[i].name, "timers") == 0) { */
- /* printf("%s\n", *(char**)sects[i].data); */
- /* } */
- }
- ih->sects_num = sects_num;
- ih->sects = sects;
- }
- void free_handover(ipxe_handover *ih) {
- int i;
- for (i = 0; i < ih->sects_num; i++) {
- free(ih->sects[i].name);
- free(ih->sects[i].data);
- }
- free(ih->sects);
- }
- ipxe_handover ih;
- void push_to_ipxe(void *msg) {
- ipxe_list_push(&ih, &ih.to_ipxe, msg);
- }
- void *pop_from_ipxe() {
- return ipxe_list_pop(&ih, &ih.from_ipxe);
- }
- coro_t *coro_ipxe;
- void download_file(const char *url, const char *dest_file) {
- push_to_ipxe(strdup("download"));
- push_to_ipxe(strdup(url));
- coro_enter(coro_ipxe);
- downloaded_file *df = pop_from_ipxe();
- assert(df->size > 0);
- FILE *fout = fopen(dest_file, "wb");
- fwrite(df->data, 1, df->size, fout);
- fclose(fout);
- free(df->data);
- free(df);
- }
- void download_check_file(const char *url, const char *dest_file, const uint8_t hash[32]) {
- push_to_ipxe(strdup("download"));
- push_to_ipxe(strdup(url));
- coro_enter(coro_ipxe);
- downloaded_file *df = pop_from_ipxe();
- assert(df->size > 0);
- uint8_t computed_hash[32];
- calc_sha_256(computed_hash, df->data, df->size);
- printf("Computed hash:");
- size_t i;
- for (i = 0; i < 32; i++) {
- printf(" %02x", computed_hash[i]);
- }
- printf("\n");
- for (i = 0; i < 32; i++) {
- assert(computed_hash[i] == hash[i]);
- }
- FILE *fout = fopen(dest_file, "wb");
- fwrite(df->data, 1, df->size, fout);
- fclose(fout);
- free(df->data);
- free(df);
- }
- void *compile_file(const char *filename, const char *symbol, void **buffer) {
- TCCState *state = tcc_new();
- tcc_set_options(state, "-nostdinc -nostdlib");
- tcc_set_output_type(state, TCC_OUTPUT_OBJ);
- char buf[1024];
- sprintf(buf, "%d", __get_handles());
- tcc_define_symbol(state, "__HANDLES", buf);
- tcc_add_symbol(state, "tcc_new", tcc_new);
- tcc_add_symbol(state, "tcc_delete", tcc_delete);
- tcc_add_symbol(state, "tcc_set_lib_path", tcc_set_lib_path);
- tcc_add_symbol(state, "tcc_set_error_func", tcc_set_error_func);
- tcc_add_symbol(state, "tcc_set_options", tcc_set_options);
- tcc_add_symbol(state, "tcc_add_include_path", tcc_add_include_path);
- tcc_add_symbol(state, "tcc_add_sysinclude_path", tcc_add_sysinclude_path);
- tcc_add_symbol(state, "tcc_define_symbol", tcc_define_symbol);
- tcc_add_symbol(state, "tcc_undefine_symbol", tcc_undefine_symbol);
- tcc_add_symbol(state, "tcc_add_file", tcc_add_file);
- tcc_add_symbol(state, "tcc_compile_string", tcc_compile_string);
- tcc_add_symbol(state, "tcc_set_output_type", tcc_set_output_type);
- tcc_add_symbol(state, "tcc_add_library_path", tcc_add_library_path);
- tcc_add_symbol(state, "tcc_add_library", tcc_add_library);
- tcc_add_symbol(state, "tcc_add_symbol", tcc_add_symbol);
- tcc_add_symbol(state, "tcc_output_file", tcc_output_file);
- tcc_add_symbol(state, "tcc_run", tcc_run);
- tcc_add_symbol(state, "tcc_relocate", tcc_relocate);
- tcc_add_symbol(state, "tcc_get_symbol", tcc_get_symbol);
- tcc_add_symbol(state, "download_file", download_file);
- tcc_add_symbol(state, "compile_file", compile_file);
- tcc_add_symbol(state, "calc_sha_256", calc_sha_256);
- tcc_add_symbol(state, "read_whole_file", read_whole_file);
- tcc_add_symbol(state, "compute_file_sha256", compute_file_sha256);
- int res;
- for (int i = 0; i < sizeof(includes2) / sizeof(includes2[0]); i++) {
- res = tcc_add_include_path(state, includes2[i]);
- if (res) {
- printf("tcc_add_include_path() failed...\n");
- return 0;
- }
- }
- res = tcc_add_file(state, filename);
- if (res) {
- printf("tcc_add_file() failed...\n");
- return 0;
- }
- int size = tcc_relocate(state, NULL);
- if (size < 0) {
- printf("tcc_relocate() failed...\n");
- return 0;
- }
- *buffer = malloc(size);
- size = tcc_relocate(state, *buffer);
- if (size < 0) {
- printf("second tcc_relocate() failed...\n");
- return 0;
- }
- void *symb = tcc_get_symbol(state, symbol);
- tcc_delete(state);
- return symb;
- }
- int main(int argc, char *argv[]) {
- printf("Here is where we compile iPXE!\n");
- int res;
- TCCState *state;
- // First compile all files
- for (int j = 0; j < sizeof(sources) / sizeof(sources[0]); j++) {
- printf("Compiling %s to %s...", sources[j][0], sources[j][1]);
- state = tcc_new();
- tcc_set_options(state, "-nostdinc -nostdlib -include " IPXE_PREFIX "/include/compiler.h");
- tcc_set_output_type(state, TCC_OUTPUT_OBJ);
- tcc_define_symbol(state, "ARCH", "i386");
- tcc_define_symbol(state, "PLATFORM", "pcbios");
- tcc_define_symbol(state, "SECUREBOOT", "0");
- char buf[1024];
- sprintf(buf, "%d", __get_handles());
- tcc_define_symbol(state, "__HANDLES", buf);
- for (int i = 0; i < sizeof(includes) / sizeof(includes[0]); i++) {
- res = tcc_add_include_path(state, includes[i]);
- if (res) {
- printf("tcc_add_include_path() failed...\n");
- return 1;
- }
- }
- res = tcc_add_file(state, sources[j][0]);
- if (res) {
- printf("tcc_add_file() failed...\n");
- return 1;
- }
- res = tcc_output_file(state, sources[j][1]);
- if (res) {
- printf("tcc_output_file() failed...\n");
- return 1;
- }
- tcc_delete(state);
- printf(" done!\n");
- }
- // Then link everything together
- printf("Linking IPXE...");
- state = tcc_new();
- tcc_set_options(state, "-nostdinc -nostdlib");
- tcc_set_output_type(state, TCC_OUTPUT_MEMORY);
- for (int i = 0; i < sizeof(sources) / sizeof(sources[0]); i++) {
- res = tcc_add_file(state, sources[i][1]);
- if (res) {
- printf("tcc_add_file() failed...\n");
- return 1;
- }
- }
- size_t ipxe_size = tcc_relocate(state, NULL);
- void *ipxe_buf = malloc(ipxe_size);
- res = tcc_relocate(state, ipxe_buf);
- if (res) {
- printf("tcc_relocate() failed...\n");
- return 1;
- }
- printf(" done!\n");
- printf("iPXE compiled to %x:%x\n", ipxe_buf, ipxe_buf + ipxe_size);
- // Start iPXE in a dedicated coroutine
- void (*main_symb)(void*) = tcc_get_symbol(state, "pre_main");
- if (!main_symb) {
- printf("tcc_get_symbol() failed...\n");
- return 1;
- }
- prepare_tables(state, &ih);
- ipxe_list_reset(&ih.to_ipxe);
- ipxe_list_reset(&ih.from_ipxe);
- ih.coro_yield = coro_yield;
- ih.malloc = malloc;
- ih.free = free;
- ih.realloc = realloc;
- printf("Starting iPXE coroutine!\n");
- coro_ipxe = coro_init(main_symb, &ih);
- coro_enter(coro_ipxe);
- // Download the continuation program
- const char *url = "http://10.0.2.2:8080/continue.c";
- printf("Request to download %s...\n", url);
- const uint32_t hash[32] = {0xEB, 0x42, 0xD9, 0x44, 0xC2, 0x2E, 0x46, 0x4F, 0x39, 0xAF, 0x75, 0x31, 0xED, 0x74, 0x99, 0xA1,
- 0x1D, 0xC5, 0xDC, 0x6E, 0x34, 0x77, 0x3C, 0x35, 0xFE, 0x14, 0x1B, 0xAC, 0x5D, 0x53, 0x3D, 0x5D};
- download_file(url, "/ram/continue.c");
- //download_check_file(url, "/ram/continue.c", hash);
- void *cont_buf;
- int (*cont_symb)(int, char*[]) = compile_file("/ram/continue.c", "_start", &cont_buf);
- if (!cont_symb) {
- printf("Compilation failed...\n");
- return 1;
- }
- char *cont_argv[] = {"_main"};
- cont_symb(sizeof(cont_argv) / sizeof(cont_argv[0]), cont_argv);
- free(cont_buf);
- printf("Request to exit iPXE\n");
- push_to_ipxe(strdup("exit"));
- coro_enter(coro_ipxe);
- //res = main_symb(&ih);
- printf("iPXE exited!\n");
- coro_destroy(coro_ipxe);
- free_handover(&ih);
- free(ipxe_buf);
- tcc_delete(state);
- return res;
- }
|