diff --git a/fusee/fusee-primary/src/bct0.c b/fusee/fusee-primary/src/bct0.c new file mode 100644 index 000000000..523071685 --- /dev/null +++ b/fusee/fusee-primary/src/bct0.c @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2018-2020 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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 . + */ + +#include "bct0.h" + +#include "lib/ini.h" + +#include + +#define STAGE2_NAME_KEY "stage2_path" +#define STAGE2_MTC_NAME_KEY "stage2_mtc_path" +#define STAGE2_ADDRESS_KEY "stage2_addr" +#define STAGE2_ENTRYPOINT_KEY "stage2_entrypoint" + +#define CONFIG_LOG_LEVEL_KEY "log_level" + +static int bct0_ini_handler(void *user, const char *section, const char *name, const char *value) { + bct0_t *bct0 = (bct0_t*) user; + + if (strcmp(section, "config") == 0) { + if (strcmp(name, CONFIG_LOG_LEVEL_KEY) == 0) { + int log_level = bct0->log_level; + sscanf(value, "%d", &log_level); + bct0->log_level = (ScreenLogLevel) log_level; + } else { + return 0; + } + } else if (strcmp(section, "stage1") == 0) { + if (strcmp(name, STAGE2_NAME_KEY) == 0) { + strncpy(bct0->stage2_path, value, sizeof(bct0->stage2_path) - 1); + bct0->stage2_path[sizeof(bct0->stage2_path) - 1] = '\0'; + } else if (strcmp(name, STAGE2_MTC_NAME_KEY) == 0) { + strncpy(bct0->stage2_mtc_path, value, sizeof(bct0->stage2_mtc_path) - 1); + bct0->stage2_mtc_path[sizeof(bct0->stage2_mtc_path) - 1] = '\0'; + } else if (strcmp(name, STAGE2_ADDRESS_KEY) == 0) { + /* Read in load address as a hex string. */ + uintptr_t x; + sscanf(value, "%x", &x); + bct0->stage2_load_address = x; + if (bct0->stage2_entrypoint == 0) { + bct0->stage2_entrypoint = bct0->stage2_load_address; + } + } else if (strcmp(name, STAGE2_ENTRYPOINT_KEY) == 0) { + /* Read in entrypoint as a hex string. */ + uintptr_t x; + sscanf(value, "%x", &x); + bct0->stage2_entrypoint = x; + } else { + return 0; + } + } else { + return 0; + } + + return 1; +} + +int bct0_parse(const char *ini, bct0_t *out) { + /* Initialize some default configuration. */ + out->log_level = SCREEN_LOG_LEVEL_NONE; + + strcpy(out->stage2_path, "atmosphere/fusee-secondary.bin"); + strcpy(out->stage2_mtc_path, "atmosphere/fusee-mtc.bin"); + out->stage2_load_address = 0xf0000000; + out->stage2_entrypoint = 0xf0000000; + + return ini_parse_string(ini, bct0_ini_handler, out); +} diff --git a/fusee/fusee-primary/src/bct0.h b/fusee/fusee-primary/src/bct0.h new file mode 100644 index 000000000..ebb86e2ee --- /dev/null +++ b/fusee/fusee-primary/src/bct0.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2018-2020 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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 . + */ + +#ifndef FUSEE_BCT0_H +#define FUSEE_BCT0_H + +#include +#include + +#include "lib/log.h" + +#define BCTO_MAX_SIZE 0x5800 + +typedef struct { + /* [config] */ + ScreenLogLevel log_level; + + /* [stage1] */ + char stage2_path[0x100]; + char stage2_mtc_path[0x100]; + uintptr_t stage2_load_address; + uintptr_t stage2_entrypoint; +} bct0_t; + +int bct0_parse(const char *ini, bct0_t *out); + +#endif diff --git a/fusee/fusee-primary/src/main.c b/fusee/fusee-primary/src/main.c index d204885d2..503256187 100644 --- a/fusee/fusee-primary/src/main.c +++ b/fusee/fusee-primary/src/main.c @@ -27,7 +27,6 @@ #include "lib/fatfs/ff.h" #include "lib/log.h" #include "lib/vsprintf.h" -#include "lib/ini.h" #include "display/video_fb.h" extern void (*__program_exit_callback)(int rc); @@ -35,8 +34,6 @@ extern void (*__program_exit_callback)(int rc); static uint32_t g_framebuffer[1280*768] __attribute__((section(".framebuffer"))) = {0}; static char g_bct0_buffer[BCTO_MAX_SIZE] __attribute__((section(".dram"))) = {0}; -#define CONFIG_LOG_LEVEL_KEY "log_level" - #define DEFAULT_BCT0 \ "BCT0\n"\ "[stage1]\n"\ @@ -74,22 +71,6 @@ static const char *load_config(void) { return bct0; } -static int config_ini_handler(void *user, const char *section, const char *name, const char *value) { - if (strcmp(section, "config") == 0) { - if (strcmp(name, CONFIG_LOG_LEVEL_KEY) == 0) { - ScreenLogLevel *config_log_level = (ScreenLogLevel *)user; - int log_level = 0; - sscanf(value, "%d", &log_level); - *config_log_level = (ScreenLogLevel)log_level; - } else { - return 0; - } - } else { - return 0; - } - return 1; -} - static void setup_display(void) { /* Zero-fill the framebuffer and register it as printk provider. */ video_init(g_framebuffer); @@ -134,12 +115,11 @@ static void exit_callback(int rc) { relocate_and_chainload(); } -int main(void) { - const char *bct0; - const char *stage2_path; +int main(void) { + const char *bct0_string; stage2_args_t *stage2_args; uint32_t stage2_version = 0; - ScreenLogLevel log_level = SCREEN_LOG_LEVEL_NONE; + bct0_t bct0; /* Initialize the boot environment. */ setup_env(); @@ -148,17 +128,17 @@ int main(void) { check_and_display_panic(); /* Load the BCT0 configuration ini off of the SD. */ - bct0 = load_config(); + bct0_string = load_config(); - /* Extract the logging level from the BCT.ini file. */ - if (ini_parse_string(bct0, config_ini_handler, &log_level) < 0) { + /* Parse the BCT0 configuration ini. */ + if (bct0_parse(bct0_string, &bct0) < 0) { fatal_error("Failed to parse BCT.ini!\n"); } /* Override the global logging level. */ - log_set_log_level(log_level); + log_set_log_level(bct0.log_level); - if (log_level != SCREEN_LOG_LEVEL_NONE) { + if (bct0.log_level != SCREEN_LOG_LEVEL_NONE) { /* Initialize the display for debugging. */ setup_display(); } @@ -168,21 +148,20 @@ int main(void) { print(SCREEN_LOG_LEVEL_DEBUG, "Using color linear framebuffer at 0x%p!\n", g_framebuffer); /* Load the loader payload into DRAM. */ - load_stage2(bct0); + load_stage2(&bct0); /* Setup argument data. */ - stage2_path = stage2_get_program_path(); - strcpy(g_chainloader_arg_data, stage2_path); - stage2_args = (stage2_args_t *)(g_chainloader_arg_data + strlen(stage2_path) + 1); /* May be unaligned. */ + strcpy(g_chainloader_arg_data, bct0.stage2_path); + stage2_args = (stage2_args_t *)(g_chainloader_arg_data + strlen(bct0.stage2_path) + 1); /* May be unaligned. */ memcpy(&stage2_args->version, &stage2_version, 4); - memcpy(&stage2_args->log_level, &log_level, sizeof(log_level)); - strcpy(stage2_args->bct0, bct0); + memcpy(&stage2_args->log_level, &bct0.log_level, sizeof(bct0.log_level)); + strcpy(stage2_args->bct0, bct0_string); g_chainloader_argc = 2; /* Terminate the boot environment. */ cleanup_env(); - if (log_level != SCREEN_LOG_LEVEL_NONE) { + if (bct0.log_level != SCREEN_LOG_LEVEL_NONE) { /* Wait a while for debugging. */ mdelay(1000); @@ -193,4 +172,4 @@ int main(void) { /* Finally, after the cleanup routines (__libc_fini_array, etc.) are called, jump to Stage2. */ __program_exit_callback = exit_callback; return 0; -} \ No newline at end of file +} diff --git a/fusee/fusee-primary/src/stage2.c b/fusee/fusee-primary/src/stage2.c index 150fcb310..12a6e10d1 100644 --- a/fusee/fusee-primary/src/stage2.c +++ b/fusee/fusee-primary/src/stage2.c @@ -19,42 +19,6 @@ #include "fs_utils.h" #include "utils.h" -char g_stage2_path[0x100] = {0}; - -const char *stage2_get_program_path(void) { - return g_stage2_path; -} - -static int stage2_ini_handler(void *user, const char *section, const char *name, const char *value) { - stage2_config_t *config = (stage2_config_t *)user; - uintptr_t x = 0; - if (strcmp(section, "stage1") == 0) { - if (strcmp(name, STAGE2_NAME_KEY) == 0) { - strncpy(config->path, value, sizeof(config->path) - 1); - config->path[sizeof(config->path) - 1] = '\0'; - } else if (strcmp(name, STAGE2_MTC_NAME_KEY) == 0) { - strncpy(config->mtc_path, value, sizeof(config->mtc_path) - 1); - config->mtc_path[sizeof(config->mtc_path) - 1] = '\0'; - } else if (strcmp(name, STAGE2_ADDRESS_KEY) == 0) { - /* Read in load address as a hex string. */ - sscanf(value, "%x", &x); - config->load_address = x; - if (config->entrypoint == 0) { - config->entrypoint = config->load_address; - } - } else if (strcmp(name, STAGE2_ENTRYPOINT_KEY) == 0) { - /* Read in entrypoint as a hex string. */ - sscanf(value, "%x", &x); - config->entrypoint = x; - } else { - return 0; - } - } else { - return 0; - } - return 1; -} - static bool run_mtc(const char *mtc_path, uintptr_t mtc_address) { FILINFO info; size_t size; @@ -91,45 +55,40 @@ static bool run_mtc(const char *mtc_path, uintptr_t mtc_address) { return mtc_res; } -void load_stage2(const char *bct0) { - stage2_config_t config = {0}; +void load_stage2(const bct0_t *bct0) { FILINFO info; size_t size; uintptr_t tmp_addr; - if (ini_parse_string(bct0, stage2_ini_handler, &config) < 0) { - fatal_error("Failed to parse BCT.ini!\n"); - } - - if (config.load_address == 0 || config.path[0] == '\x00') { + if (bct0->stage2_load_address == 0 || bct0->stage2_path[0] == '\x00') { fatal_error("Failed to determine where to load stage2!\n"); } - if (strlen(config.path) + 1 + sizeof(stage2_args_t) > CHAINLOADER_ARG_DATA_MAX_SIZE) { + if (strlen(bct0->stage2_path) + 1 + sizeof(stage2_args_t) > CHAINLOADER_ARG_DATA_MAX_SIZE) { fatal_error("Stage2's path name is too big!\n"); } - if (!check_32bit_address_loadable(config.entrypoint)) { + if (!check_32bit_address_loadable(bct0->stage2_entrypoint)) { fatal_error("Stage2's entrypoint is invalid!\n"); } - if (!check_32bit_address_loadable(config.load_address)) { + if (!check_32bit_address_loadable(bct0->stage2_load_address)) { fatal_error("Stage2's load address is invalid!\n"); } print(SCREEN_LOG_LEVEL_DEBUG, "Stage 2 Config:\n"); - print(SCREEN_LOG_LEVEL_DEBUG | SCREEN_LOG_LEVEL_NO_PREFIX, " File Path: %s\n", config.path); - print(SCREEN_LOG_LEVEL_DEBUG | SCREEN_LOG_LEVEL_NO_PREFIX, " MTC File Path: %s\n", config.mtc_path); - print(SCREEN_LOG_LEVEL_DEBUG | SCREEN_LOG_LEVEL_NO_PREFIX, " Load Address: 0x%08x\n", config.load_address); - print(SCREEN_LOG_LEVEL_DEBUG | SCREEN_LOG_LEVEL_NO_PREFIX, " Entrypoint: 0x%p\n", config.entrypoint); + print(SCREEN_LOG_LEVEL_DEBUG | SCREEN_LOG_LEVEL_NO_PREFIX, " File Path: %s\n", bct0->stage2_path); + print(SCREEN_LOG_LEVEL_DEBUG | SCREEN_LOG_LEVEL_NO_PREFIX, " MTC File Path: %s\n", bct0->stage2_mtc_path); + print(SCREEN_LOG_LEVEL_DEBUG | SCREEN_LOG_LEVEL_NO_PREFIX, " Load Address: 0x%08x\n", bct0->stage2_load_address); + print(SCREEN_LOG_LEVEL_DEBUG | SCREEN_LOG_LEVEL_NO_PREFIX, " Entrypoint: 0x%p\n", bct0->stage2_entrypoint); /* Run the MTC binary. */ - if (!run_mtc(config.mtc_path, config.load_address)) { + if (!run_mtc(bct0->stage2_mtc_path, bct0->stage2_load_address)) { print(SCREEN_LOG_LEVEL_WARNING, "DRAM training failed! Continuing with untrained DRAM.\n"); } - if (f_stat(config.path, &info) != FR_OK) { - fatal_error("Failed to stat stage2 (%s)!\n", config.path); + if (f_stat(bct0->stage2_path, &info) != FR_OK) { + fatal_error("Failed to stat stage2 (%s)!\n", bct0->stage2_path); } size = (size_t)info.fsize; @@ -139,32 +98,29 @@ void load_stage2(const char *bct0) { fatal_error("Stage2 is way too big!\n"); } - if (!check_32bit_address_range_loadable(config.load_address, size)) { - fatal_error("Stage2 has an invalid load address & size combination (0x%08x 0x%08x)!\n", config.load_address, size); + if (!check_32bit_address_range_loadable(bct0->stage2_load_address, size)) { + fatal_error("Stage2 has an invalid load address & size combination (0x%08x 0x%08x)!\n", bct0->stage2_load_address, size); } - if (config.entrypoint < config.load_address || config.entrypoint >= config.load_address + size) { + if (bct0->stage2_entrypoint < bct0->stage2_load_address || bct0->stage2_entrypoint >= bct0->stage2_load_address + size) { fatal_error("Stage2's entrypoint is outside Stage2!\n"); } - if (check_32bit_address_range_in_program(config.load_address, size)) { + if (check_32bit_address_range_in_program(bct0->stage2_load_address, size)) { tmp_addr = 0x80000000u; } else { - tmp_addr = config.load_address; + tmp_addr = bct0->stage2_load_address; } /* Try to read stage2. */ - if (read_from_file((void *)tmp_addr, size, config.path) != size) { - fatal_error("Failed to read stage2 (%s)!\n", config.path); + if (read_from_file((void *)tmp_addr, size, bct0->stage2_path) != size) { + fatal_error("Failed to read stage2 (%s)!\n", bct0->stage2_path); } g_chainloader_num_entries = 1; - g_chainloader_entries[0].load_address = config.load_address; + g_chainloader_entries[0].load_address = bct0->stage2_load_address; g_chainloader_entries[0].src_address = tmp_addr; g_chainloader_entries[0].size = size; g_chainloader_entries[0].num = 0; - g_chainloader_entrypoint = config.entrypoint; - - strncpy(g_stage2_path, config.path, sizeof(g_stage2_path) - 1); - g_stage2_path[sizeof(g_stage2_path) - 1] = '\0'; + g_chainloader_entrypoint = bct0->stage2_entrypoint; } diff --git a/fusee/fusee-primary/src/stage2.h b/fusee/fusee-primary/src/stage2.h index 27a399e44..f9d0dfdea 100644 --- a/fusee/fusee-primary/src/stage2.h +++ b/fusee/fusee-primary/src/stage2.h @@ -26,25 +26,13 @@ #include "lib/ini.h" #include "lib/fatfs/ff.h" +#include "bct0.h" + /* TODO: Is there a more concise way to do this? */ #define STAGE2_ARGV_PROGRAM_PATH 0 #define STAGE2_ARGV_ARGUMENT_STRUCT 1 #define STAGE2_ARGC 2 -#define STAGE2_NAME_KEY "stage2_path" -#define STAGE2_MTC_NAME_KEY "stage2_mtc_path" -#define STAGE2_ADDRESS_KEY "stage2_addr" -#define STAGE2_ENTRYPOINT_KEY "stage2_entrypoint" - -#define BCTO_MAX_SIZE 0x5800 - -typedef struct { - char path[0x100]; - char mtc_path[0x100]; - uintptr_t load_address; - uintptr_t entrypoint; -} stage2_config_t; - typedef struct { uint32_t version; ScreenLogLevel log_level; @@ -55,7 +43,6 @@ typedef struct { ScreenLogLevel log_level; } stage2_mtc_args_t; -const char *stage2_get_program_path(void); -void load_stage2(const char *bct0); +void load_stage2(const bct0_t *bct0); -#endif \ No newline at end of file +#endif