From 82552b5a894c581b2b06e832463d67de22532b94 Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Sun, 8 Apr 2018 05:51:57 -0600 Subject: [PATCH] Implement much of the core Stage2 loader logic for Fusee --- fusee/fusee-primary/src/main.c | 2 +- fusee/fusee-primary/src/stage2.h | 2 +- fusee/fusee-secondary/src/loader.c | 145 ++++++++++++++++++++++++++++- fusee/fusee-secondary/src/loader.h | 16 ++++ 4 files changed, 160 insertions(+), 5 deletions(-) diff --git a/fusee/fusee-primary/src/main.c b/fusee/fusee-primary/src/main.c index 6acfffa6f..f8a12c5a8 100644 --- a/fusee/fusee-primary/src/main.c +++ b/fusee/fusee-primary/src/main.c @@ -12,7 +12,7 @@ #define BCT0_LOAD_END_ADDRESS (uintptr_t)(0x4003F000) #define MAGIC_BCT0 0x30544342 -#define DEFAULT_BCT0_FOR_DEBUG "BCT0\n[stage1]\nstage2_file = stage2.bin\nstage2_addr = 0xFFF00000\nstage2_entrypoint = 0xCAFEBABE\n" +#define DEFAULT_BCT0_FOR_DEBUG "BCT0\n[stage1]\nstage2_path = stage2.bin\nstage2_addr = 0xFFF00000\nstage2_entrypoint = 0xCAFEBABE\n" const char *load_config(void) { if (!read_sd_file((void *)BCT0_LOAD_ADDRESS, BCT0_LOAD_END_ADDRESS - BCT0_LOAD_ADDRESS, "BCT.ini")) { diff --git a/fusee/fusee-primary/src/stage2.h b/fusee/fusee-primary/src/stage2.h index 0ddf9a166..536cd57f7 100644 --- a/fusee/fusee-primary/src/stage2.h +++ b/fusee/fusee-primary/src/stage2.h @@ -10,7 +10,7 @@ #define STAGE2_ARGC 3 -#define STAGE2_NAME_KEY "stage2_file" +#define STAGE2_NAME_KEY "stage2_path" #define STAGE2_ADDRESS_KEY "stage2_addr" #define STAGE2_ENTRYPOINT_KEY "stage2_entrypoint" diff --git a/fusee/fusee-secondary/src/loader.c b/fusee/fusee-secondary/src/loader.c index 12fd7d623..663698432 100644 --- a/fusee/fusee-secondary/src/loader.c +++ b/fusee/fusee-secondary/src/loader.c @@ -1,8 +1,147 @@ #include "utils.h" +#include #include "loader.h" +#include "sd_utils.h" +#include "stage2.h" +#include "lib/printk.h" +#include "lib/vsprintf.h" +#include "lib/ini.h" + +const char *g_bct0 = NULL; + +static int loadlist_entry_ini_handler(void *user, const char *section, const char *name, const char *value) { + load_file_t *load_file_ctx = (load_file_t *)user; + uintptr_t x = 0; + const char *ext = NULL; + + if (strcmp(section, "stage2") == 0) { + if (strstr(name, load_file_ctx->key) == name) { + ext = name + strlen(load_file_ctx->key); + if (strcmp(ext, "_path") == 0) { + /* Copy in the path. */ + strncpy(load_file_ctx->path, value, sizeof(load_file_ctx->path)); + } else if (strcmp(ext, "_addr") == 0) { + /* Read in load address as a hex string. */ + sscanf(value, "%x", &x); + load_file_ctx->load_address = x; + } else { + return 0; + } + } else { + return 0; + } + } else { + return 0; + } + return 1; +} + +bool validate_load_address(uintptr_t load_addr) { + /* TODO: Actually validate addresses. */ + (void)(load_addr); + return true; +} + +void load_list_entry(const char *key) { + load_file_t load_file_ctx = {0}; + load_file_ctx.key = key; + + printk("Loading %s\n", key); + + if (ini_parse_string(g_bct0, loadlist_entry_ini_handler, &load_file_ctx) < 0) { + printk("Error: Failed to parse BCT.ini!\n"); + generic_panic(); + } + + if (load_file_ctx.load_address == 0 || load_file_ctx.path[0] == '\x00') { + printk("Error: Failed to determine where to load %s!\n", key); + generic_panic(); + } + + printk("Loading %s from %s to 0x%08x\n", key, load_file_ctx.path, load_file_ctx.load_address); + + if (!validate_load_address(load_file_ctx.load_address)) { + printk("Error: Load address 0x%08x is invalid!\n"); + generic_panic(); + } + + if (!read_sd_file((void *)load_file_ctx.load_address, LOADER_FILESIZE_MAX, load_file_ctx.path)) { + printk("Error: Failed to read %s!\n", load_file_ctx.path); + } +} + +void parse_loadlist(const char *ll) { + printk("Parsing load list: %s\n", ll); + + char load_list[0x200] = {0}; + strncpy(load_list, ll, 0x200); + + char *entry, *p; + + /* entry will point to the start of the current entry. p will point to the current location in the list. */ + entry = load_list; + p = load_list; + + while (*p) { + if (*p == ' ' || *p == '\t') { + /* We're at the end of an entry. */ + *p = '\x00'; + + /* Load the entry. */ + load_list_entry(entry); + /* Skip to the next delimiter. */ + for (; *p == ' ' || *p == '\t'; p++) { } + if (*p == '\x00') { + break; + } else if (*p != '|') { + printk("Error: Load list is malformed!\n"); + generic_panic(); + } else { + /* Skip to the next entry. */ + for (; *p == ' ' || *p == '\t'; p++) { } + entry = p; + } + } + + p++; + } +} + +static int loadlist_ini_handler(void *user, const char *section, const char *name, const char *value) { + loader_ctx_t *loader_ctx = (loader_ctx_t *)user; + uintptr_t x = 0; + + if (strcmp(section, "stage2") == 0) { + if (strcmp(name, LOADER_LOADLIST_KEY) == 0) { + parse_loadlist(value); + } else if (strcmp(name, LOADER_ENTRYPOINT_KEY) == 0) { + /* Read in entrypoint as a hex string. */ + sscanf(value, "%x", &x); + loader_ctx->entrypoint = (entrypoint_t)x; + } else { + return 0; + } + } else { + return 0; + } + return 1; +} entrypoint_t load_payload(const char *bct0) { - /* TODO */ - (void)(bct0); - return (entrypoint_t)NULL; + loader_ctx_t loader_ctx = {0}; + + /* Set BCT0 global. */ + g_bct0 = bct0; + + if (ini_parse_string(g_bct0, loadlist_ini_handler, &loader_ctx) < 0) { + printk("Error: Failed to parse BCT.ini!\n"); + generic_panic(); + } + + if (loader_ctx.entrypoint == NULL) { + printk("Error: Failed to locate stage3 entrypoint!\n"); + generic_panic(); + } + + return loader_ctx.entrypoint; } \ No newline at end of file diff --git a/fusee/fusee-secondary/src/loader.h b/fusee/fusee-secondary/src/loader.h index d602f54bf..a8bc7c7f5 100644 --- a/fusee/fusee-secondary/src/loader.h +++ b/fusee/fusee-secondary/src/loader.h @@ -3,6 +3,22 @@ typedef void (*entrypoint_t)(int argc, void **argv); +typedef struct { + char path[0x300]; + const char *key; + uintptr_t load_address; +} load_file_t; + +typedef struct { + entrypoint_t entrypoint; +} loader_ctx_t; + +#define LOADER_ENTRYPOINT_KEY "entrypoint" +#define LOADER_LOADLIST_KEY "loadlist" + +/* TODO: Should we allow files bigger than 16 MB? */ +#define LOADER_FILESIZE_MAX 0x01000000 + entrypoint_t load_payload(const char *bct0); #endif \ No newline at end of file