From 92816be0551130143a9db7fe6b5b9f733a831dc5 Mon Sep 17 00:00:00 2001 From: hexkyz Date: Sun, 7 Apr 2019 19:02:01 +0100 Subject: [PATCH] emunand: Move all emulation code to fusee-secondary and simplify logic --- fusee/fusee-primary/src/main.c | 38 +-- fusee/fusee-primary/src/stage2.h | 4 +- fusee/fusee-secondary/src/main.c | 7 +- fusee/fusee-secondary/src/nxboot.c | 67 +++++- fusee/fusee-secondary/src/nxboot.h | 8 + fusee/fusee-secondary/src/nxfs.c | 369 +++++++++++++++++------------ fusee/fusee-secondary/src/nxfs.h | 11 +- fusee/fusee-secondary/src/stage2.h | 4 +- 8 files changed, 315 insertions(+), 193 deletions(-) diff --git a/fusee/fusee-primary/src/main.c b/fusee/fusee-primary/src/main.c index 95e599d16..b8ee70c58 100644 --- a/fusee/fusee-primary/src/main.c +++ b/fusee/fusee-primary/src/main.c @@ -35,14 +35,7 @@ extern void (*__program_exit_callback)(int rc); static void *g_framebuffer; static char g_bct0_buffer[BCTO_MAX_SIZE]; -typedef struct { - bool enabled; - char path[0x100]; -} emunand_config_t; - #define CONFIG_LOG_LEVEL_KEY "log_level" -#define EMUNAND_ENABLED_KEY "emunand_enabled" -#define EMUNAND_PATH_KEY "emunand_path" #define DEFAULT_BCT0_FOR_DEBUG \ "BCT0\n"\ @@ -91,26 +84,6 @@ static int config_ini_handler(void *user, const char *section, const char *name, return 1; } -static int emunand_ini_handler(void *user, const char *section, const char *name, const char *value) { - emunand_config_t *emunand_cfg = (emunand_config_t *)user; - if (strcmp(section, "emunand") == 0) { - if (strcmp(name, EMUNAND_ENABLED_KEY) == 0) { - int tmp = 0; - sscanf(value, "%d", &tmp); - emunand_cfg->enabled = (tmp != 0); - } - if (strcmp(name, EMUNAND_PATH_KEY) == 0) { - strncpy(emunand_cfg->path, value, sizeof(emunand_cfg->path) - 1); - emunand_cfg->path[sizeof(emunand_cfg->path) - 1] = '\0'; - } else { - return 0; - } - } else { - return 0; - } - return 1; -} - static void setup_env(void) { g_framebuffer = (void *)0xC0000000; @@ -159,7 +132,6 @@ int main(void) { stage2_args_t *stage2_args; uint32_t stage2_version = 0; ScreenLogLevel log_level = SCREEN_LOG_LEVEL_MANDATORY; - emunand_config_t emunand_cfg = {.enabled = false, .path = ""}; /* Override the global logging level. */ log_set_log_level(log_level); @@ -170,9 +142,8 @@ int main(void) { /* Load the BCT0 configuration ini off of the SD. */ bct0 = load_config(); - /* Extract the logging level and emunand settings from the BCT.ini file. */ - if ((ini_parse_string(bct0, config_ini_handler, &log_level) < 0) || - (ini_parse_string(bct0, emunand_ini_handler, &emunand_cfg) < 0)) { + /* Extract the logging level from the BCT.ini file. */ + if (ini_parse_string(bct0, config_ini_handler, &log_level) < 0) { fatal_error("Failed to parse BCT.ini!\n"); } @@ -190,9 +161,6 @@ int main(void) { memcpy(&stage2_args->version, &stage2_version, 4); memcpy(&stage2_args->log_level, &log_level, sizeof(log_level)); stage2_args->display_initialized = false; - stage2_args->emunand_enabled = emunand_cfg.enabled; - strncpy(stage2_args->emunand_path, emunand_cfg.path, sizeof(stage2_args->emunand_path) - 1); - stage2_args->emunand_path[sizeof(stage2_args->emunand_path) - 1] = '\0'; strcpy(stage2_args->bct0, bct0); g_chainloader_argc = 2; @@ -205,4 +173,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.h b/fusee/fusee-primary/src/stage2.h index 88dbc0b01..c1a7bf582 100644 --- a/fusee/fusee-primary/src/stage2.h +++ b/fusee/fusee-primary/src/stage2.h @@ -46,12 +46,10 @@ typedef struct { uint32_t version; ScreenLogLevel log_level; bool display_initialized; - bool emunand_enabled; - char emunand_path[0x100]; char bct0[BCTO_MAX_SIZE]; } stage2_args_t; const char *stage2_get_program_path(void); void load_stage2(const char *bct0); -#endif +#endif \ No newline at end of file diff --git a/fusee/fusee-secondary/src/main.c b/fusee/fusee-secondary/src/main.c index 84779fbf0..a21626dce 100644 --- a/fusee/fusee-secondary/src/main.c +++ b/fusee/fusee-secondary/src/main.c @@ -51,8 +51,9 @@ static void setup_env(void) { /* Set up exception handlers. */ setup_exception_handlers(); - if (nxfs_mount_all(g_stage2_args->emunand_enabled, g_stage2_args->emunand_path) < 0) { - fatal_error("Failed to mount at least one partition: %s\n", strerror(errno)); + /* Initialize the file system by mounting the SD card. */ + if (nxfs_init() < 0) { + fatal_error("Failed to initialize the file system: %s\n", strerror(errno)); } /* Train DRAM. */ @@ -61,7 +62,7 @@ static void setup_env(void) { static void cleanup_env(void) { /* Unmount everything (this causes all open files to be flushed and closed) */ - nxfs_unmount_all(); + nxfs_end(); //console_end(); } diff --git a/fusee/fusee-secondary/src/nxboot.c b/fusee/fusee-secondary/src/nxboot.c index f9c50f77f..572a541f1 100644 --- a/fusee/fusee-secondary/src/nxboot.c +++ b/fusee/fusee-secondary/src/nxboot.c @@ -100,6 +100,26 @@ static const uint8_t dev_pkc_modulus[0x100] = { 0xD5, 0x52, 0xDA, 0xEC, 0x41, 0xA4, 0xAD, 0x7B, 0x36, 0x86, 0x18, 0xB4, 0x5B, 0xD1, 0x30, 0xBB }; +static int emunand_ini_handler(void *user, const char *section, const char *name, const char *value) { + emunand_config_t *emunand_cfg = (emunand_config_t *)user; + if (strcmp(section, "emunand") == 0) { + if (strcmp(name, EMUNAND_ENABLED_KEY) == 0) { + int tmp = 0; + sscanf(value, "%d", &tmp); + emunand_cfg->enabled = (tmp != 0); + } + if (strcmp(name, EMUNAND_PATH_KEY) == 0) { + strncpy(emunand_cfg->path, value, sizeof(emunand_cfg->path) - 1); + emunand_cfg->path[sizeof(emunand_cfg->path) - 1] = '\0'; + } else { + return 0; + } + } else { + return 0; + } + return 1; +} + static int exosphere_ini_handler(void *user, const char *section, const char *name, const char *value) { exosphere_config_t *exo_cfg = (exosphere_config_t *)user; int tmp = 0; @@ -177,6 +197,44 @@ static uint32_t nxboot_get_target_firmware(const void *package1loader) { } } +static bool nxboot_configure_emunand() { + emunand_config_t emunand_cfg = {.enabled = false, .path = ""}; + + /* Load emunand settings from BCT.ini file. */ + if (ini_parse_string(get_loader_ctx()->bct0, emunand_ini_handler, &emunand_cfg) < 0) { + fatal_error("[NXBOOT]: Failed to parse BCT.ini!\n"); + } + + if (emunand_cfg.enabled) { + bool do_nand_backup = false; + + /* TODO: Check if the supplied path is valid. */ + + /* TODO: Check if all emunand image files are present. */ + + if (do_nand_backup) { + /* Mount real NAND. */ + if (nxfs_mount_emmc() < 0) { + fatal_error("[NXBOOT]: Failed to mount eMMC!\n"); + } + + /* TODO: Read real NAND and create a backup image. */ + + /* Unmount real NAND. */ + if (nxfs_unmount_emmc() < 0) { + fatal_error("[NXBOOT]: Failed to unmount eMMC!\n"); + } + } + + /* Mount emulated NAND. */ + if (nxfs_mount_emu_emmc(emunand_cfg.path) < 0) { + fatal_error("[NXBOOT]: Failed to mount emulated eMMC!\n"); + } + } + + return emunand_cfg.enabled; +} + static void nxboot_configure_exosphere(uint32_t target_firmware, unsigned int keygen_type) { exosphere_config_t exo_cfg = {0}; @@ -334,6 +392,13 @@ uint32_t nxboot_main(void) { uint32_t available_revision; FILE *boot0, *pk2file; void *exosphere_memaddr; + + /* Configure emunand or mount the real NAND. */ + if (!nxboot_configure_emunand()) { + if (nxfs_mount_emmc() < 0) { + fatal_error("[NXBOOT]: Failed to mount eMMC!\n"); + } + } /* Allocate memory for reading Package2. */ package2 = memalign(0x1000, PACKAGE2_SIZE_MAX); @@ -601,7 +666,7 @@ uint32_t nxboot_main(void) { print(SCREEN_LOG_LEVEL_INFO, "[NXBOOT]: Powering on the CCPLEX...\n"); /* Unmount everything. */ - nxfs_unmount_all(); + nxfs_end(); /* Return the memory address for booting CPU0. */ return (uint32_t)exosphere_memaddr; diff --git a/fusee/fusee-secondary/src/nxboot.h b/fusee/fusee-secondary/src/nxboot.h index 15d31d88a..93348083a 100644 --- a/fusee/fusee-secondary/src/nxboot.h +++ b/fusee/fusee-secondary/src/nxboot.h @@ -19,6 +19,14 @@ #include "utils.h" +#define EMUNAND_ENABLED_KEY "emunand_enabled" +#define EMUNAND_PATH_KEY "emunand_path" + +typedef struct { + bool enabled; + char path[0x100]; +} emunand_config_t; + #define MAILBOX_NX_BOOTLOADER_BASE_100_620 0x40002E00 #define MAILBOX_NX_BOOTLOADER_BASE_700 0x40000000 #define MAILBOX_NX_BOOTLOADER_BASE(targetfw) ((targetfw >= ATMOSPHERE_TARGET_FIRMWARE_700) ? (MAILBOX_NX_BOOTLOADER_BASE_700) : (MAILBOX_NX_BOOTLOADER_BASE_100_620)) diff --git a/fusee/fusee-secondary/src/nxfs.c b/fusee/fusee-secondary/src/nxfs.c index c57288099..781ac97ca 100644 --- a/fusee/fusee-secondary/src/nxfs.c +++ b/fusee/fusee-secondary/src/nxfs.c @@ -30,6 +30,10 @@ static bool g_ahb_redirect_enabled = false; static bool g_sd_device_initialized = false; static bool g_emmc_device_initialized = false; +static bool g_fsdev_ready = false; +static bool g_rawdev_ready = false; +static bool g_emudev_ready = false; + static sdmmc_t g_sd_sdmmc = {0}; static sdmmc_t g_emmc_sdmmc = {0}; @@ -264,10 +268,9 @@ static int nxfs_mount_partition_gpt_callback(const efi_entry_t *entry, void *par return 0; } -int nxfs_mount_all(bool emunand_enabled, const char *emunand_path) { +int nxfs_mount_sd() { device_partition_t model; int rc; - FILE *rawnand; /* Setup a template for the SD card. */ model = g_mmc_devpart_template; @@ -288,152 +291,226 @@ int nxfs_mount_all(bool emunand_enabled, const char *emunand_path) { if (rc == -1) { return -1; } - - if (emunand_enabled) { - /* Setup emunand paths. */ - char emu_boot0_path[0x100]; - char emu_boot1_path[0x100]; - char emu_rawnand_path[0x100]; - memset(emu_boot0_path, 0, sizeof(emu_boot0_path)); - memset(emu_boot1_path, 0, sizeof(emu_boot1_path)); - memset(emu_rawnand_path, 0, sizeof(emu_rawnand_path)); - snprintf(emu_boot0_path, sizeof(emu_boot0_path), "sdmc:/%s/%s", emunand_path, "boot0"); - snprintf(emu_boot1_path, sizeof(emu_boot1_path), "sdmc:/%s/%s", emunand_path, "boot1"); - snprintf(emu_rawnand_path, sizeof(emu_rawnand_path), "sdmc:/%s/%s", emunand_path, "rawnand"); - /* Setup an emulation template for boot0. */ - model = g_emummc_devpart_template; - model.start_sector = 0; - model.num_sectors = 0x184000 / model.sector_size; - - /* Mount emulated boot0 device. */ - rc = emudev_mount_device("boot0", emu_boot0_path, &model); - - if (rc == -1) { - return -1; - } - - /* Register emulated boot0 device. */ - rc = emudev_register_device("boot0"); - - if (rc == -1) { - return -1; - } - - /* Setup an emulation template for boot1. */ - model = g_emummc_devpart_template; - model.start_sector = 0; - model.num_sectors = 0x80000 / model.sector_size; - - /* Mount emulated boot1 device. */ - rc = emudev_mount_device("boot1", emu_boot1_path, &model); - - if (rc == -1) { - return -1; - } + /* All fs devices are ready. */ + if (rc == 0) { + g_fsdev_ready = true; + } + + return rc; +} - /* Don't register emulated boot1 for now. */ - - /* Setup a template for raw NAND. */ - model = g_emummc_devpart_template; - model.start_sector = 0; - model.num_sectors = (256ull << 30) / model.sector_size; - - /* Mount emulated raw NAND device. */ - rc = emudev_mount_device("rawnand", emu_rawnand_path, &model); - - if (rc == -1) { - return -1; - } - - /* Register emulated raw NAND device. */ - rc = emudev_register_device("rawnand"); - if (rc == -1) { - return -1; - } - - /* Open emulated raw NAND device. */ - rawnand = fopen("rawnand:/", "rb"); - - if (rawnand == NULL) { - return -1; - } - - /* Iterate the GPT and mount each emulated raw NAND partition. */ - rc = gpt_iterate_through_entries(rawnand, model.sector_size, nxfs_mount_partition_gpt_callback, &model); - - /* Close emulated raw NAND device. */ - fclose(rawnand); - } else { - /* Setup a template for boot0. */ - model = g_mmc_devpart_template; - model.device_struct = &g_emmc_boot0_mmcpart; - model.start_sector = 0; - model.num_sectors = 0x184000 / model.sector_size; - - /* Mount boot0 device. */ - rc = rawdev_mount_device("boot0", &model, true); - - if (rc == -1) { - return -1; - } - - /* Register boot0 device. */ - rc = rawdev_register_device("boot0"); - - if (rc == -1) { - return -1; - } - - /* Setup a template for boot1. */ - model = g_mmc_devpart_template; - model.device_struct = &g_emmc_boot1_mmcpart; - model.start_sector = 0; - model.num_sectors = 0x80000 / model.sector_size; - - /* Mount boot1 device. */ - rc = rawdev_mount_device("boot1", &model, false); - - if (rc == -1) { - return -1; - } - - /* Don't register boot1 for now. */ - - /* Setup a template for raw NAND. */ - model = g_mmc_devpart_template; - model.device_struct = &g_emmc_user_mmcpart; - model.start_sector = 0; - model.num_sectors = (256ull << 30) / model.sector_size; - - /* Mount raw NAND device. */ - rc = rawdev_mount_device("rawnand", &model, false); - - if (rc == -1) { - return -1; - } - - /* Register raw NAND device. */ - rc = rawdev_register_device("rawnand"); - if (rc == -1) { - return -1; - } - - /* Open raw NAND device. */ - rawnand = fopen("rawnand:/", "rb"); - - if (rawnand == NULL) { - return -1; - } - - /* Iterate the GPT and mount each raw NAND partition. */ - rc = gpt_iterate_through_entries(rawnand, model.sector_size, nxfs_mount_partition_gpt_callback, &model); - - /* Close raw NAND device. */ - fclose(rawnand); +int nxfs_mount_emmc() { + device_partition_t model; + int rc; + FILE *rawnand; + + /* Setup a template for boot0. */ + model = g_mmc_devpart_template; + model.device_struct = &g_emmc_boot0_mmcpart; + model.start_sector = 0; + model.num_sectors = 0x184000 / model.sector_size; + + /* Mount boot0 device. */ + rc = rawdev_mount_device("boot0", &model, true); + + if (rc == -1) { + return -1; + } + + /* Register boot0 device. */ + rc = rawdev_register_device("boot0"); + + if (rc == -1) { + return -1; + } + + /* Setup a template for boot1. */ + model = g_mmc_devpart_template; + model.device_struct = &g_emmc_boot1_mmcpart; + model.start_sector = 0; + model.num_sectors = 0x80000 / model.sector_size; + + /* Mount boot1 device. */ + rc = rawdev_mount_device("boot1", &model, false); + + if (rc == -1) { + return -1; } - /* Set the default file system device. */ + /* Don't register boot1 for now. */ + + /* Setup a template for raw NAND. */ + model = g_mmc_devpart_template; + model.device_struct = &g_emmc_user_mmcpart; + model.start_sector = 0; + model.num_sectors = (256ull << 30) / model.sector_size; + + /* Mount raw NAND device. */ + rc = rawdev_mount_device("rawnand", &model, false); + + if (rc == -1) { + return -1; + } + + /* Register raw NAND device. */ + rc = rawdev_register_device("rawnand"); + if (rc == -1) { + return -1; + } + + /* Open raw NAND device. */ + rawnand = fopen("rawnand:/", "rb"); + + if (rawnand == NULL) { + return -1; + } + + /* Iterate the GPT and mount each raw NAND partition. */ + rc = gpt_iterate_through_entries(rawnand, model.sector_size, nxfs_mount_partition_gpt_callback, &model); + + /* Close raw NAND device. */ + fclose(rawnand); + + /* All raw devices are ready. */ + if (rc == 0) { + g_rawdev_ready = true; + } + + return rc; +} + +int nxfs_mount_emu_emmc(const char *emunand_path) { + device_partition_t model; + int rc; + FILE *rawnand; + + /* Setup emunand paths. */ + char emu_boot0_path[0x100]; + char emu_boot1_path[0x100]; + char emu_rawnand_path[0x100]; + memset(emu_boot0_path, 0, sizeof(emu_boot0_path)); + memset(emu_boot1_path, 0, sizeof(emu_boot1_path)); + memset(emu_rawnand_path, 0, sizeof(emu_rawnand_path)); + snprintf(emu_boot0_path, sizeof(emu_boot0_path), "sdmc:/%s/%s", emunand_path, "boot0"); + snprintf(emu_boot1_path, sizeof(emu_boot1_path), "sdmc:/%s/%s", emunand_path, "boot1"); + snprintf(emu_rawnand_path, sizeof(emu_rawnand_path), "sdmc:/%s/%s", emunand_path, "rawnand"); + + /* Setup an emulation template for boot0. */ + model = g_emummc_devpart_template; + model.start_sector = 0; + model.num_sectors = 0x184000 / model.sector_size; + + /* Mount emulated boot0 device. */ + rc = emudev_mount_device("boot0", emu_boot0_path, &model); + + if (rc == -1) { + return -1; + } + + /* Register emulated boot0 device. */ + rc = emudev_register_device("boot0"); + + if (rc == -1) { + return -1; + } + + /* Setup an emulation template for boot1. */ + model = g_emummc_devpart_template; + model.start_sector = 0; + model.num_sectors = 0x80000 / model.sector_size; + + /* Mount emulated boot1 device. */ + rc = emudev_mount_device("boot1", emu_boot1_path, &model); + + if (rc == -1) { + return -1; + } + + /* Don't register emulated boot1 for now. */ + + /* Setup a template for raw NAND. */ + model = g_emummc_devpart_template; + model.start_sector = 0; + model.num_sectors = (256ull << 30) / model.sector_size; + + /* Mount emulated raw NAND device. */ + rc = emudev_mount_device("rawnand", emu_rawnand_path, &model); + + if (rc == -1) { + return -1; + } + + /* Register emulated raw NAND device. */ + rc = emudev_register_device("rawnand"); + if (rc == -1) { + return -1; + } + + /* Open emulated raw NAND device. */ + rawnand = fopen("rawnand:/", "rb"); + + if (rawnand == NULL) { + return -1; + } + + /* Iterate the GPT and mount each emulated raw NAND partition. */ + rc = gpt_iterate_through_entries(rawnand, model.sector_size, nxfs_mount_partition_gpt_callback, &model); + + /* Close emulated raw NAND device. */ + fclose(rawnand); + + /* All emulated devices are ready. */ + if (rc == 0) { + g_emudev_ready = true; + } + + return rc; +} + +int nxfs_unmount_sd() { + int rc = 0; + + /* Unmount all fs devices. */ + if (g_fsdev_ready) { + rc = fsdev_unmount_all(); + g_fsdev_ready = false; + } + + return rc; +} + +int nxfs_unmount_emmc() { + int rc = 0; + + /* Unmount all raw devices. */ + if (g_rawdev_ready) { + rc = rawdev_unmount_all(); + g_rawdev_ready = false; + } + + return rc; +} + +int nxfs_unmount_emu_emmc() { + int rc = 0; + + /* Unmount all emulated devices. */ + if (g_emudev_ready) { + rc = emudev_unmount_all(); + g_emudev_ready = false; + } + + return rc; +} + +int nxfs_init() { + int rc; + + /* Mount and register the SD card. */ + rc = nxfs_mount_sd(); + + /* Set the SD card as the default file system device. */ if (rc == 0) { rc = fsdev_set_default_device("sdmc"); } @@ -441,6 +518,6 @@ int nxfs_mount_all(bool emunand_enabled, const char *emunand_path) { return rc; } -int nxfs_unmount_all() { - return ((fsdev_unmount_all() || rawdev_unmount_all() || emudev_unmount_all()) ? -1 : 0); +int nxfs_end() { + return ((nxfs_unmount_sd() || nxfs_unmount_emmc() || nxfs_unmount_emu_emmc()) ? -1 : 0); } diff --git a/fusee/fusee-secondary/src/nxfs.h b/fusee/fusee-secondary/src/nxfs.h index 6578b2b80..77fc4f406 100644 --- a/fusee/fusee-secondary/src/nxfs.h +++ b/fusee/fusee-secondary/src/nxfs.h @@ -21,7 +21,14 @@ #include "raw_dev.h" #include "emu_dev.h" -int nxfs_mount_all(bool emunand_enabled, const char *emunand_path); -int nxfs_unmount_all(); +int nxfs_init(); +int nxfs_end(); + +int nxfs_mount_sd(); +int nxfs_mount_emmc(); +int nxfs_mount_emu_emmc(const char *emunand_path); +int nxfs_unmount_sd(); +int nxfs_unmount_emmc(); +int nxfs_unmount_emu_emmc(); #endif diff --git a/fusee/fusee-secondary/src/stage2.h b/fusee/fusee-secondary/src/stage2.h index ffb583e01..250b7600c 100644 --- a/fusee/fusee-secondary/src/stage2.h +++ b/fusee/fusee-secondary/src/stage2.h @@ -32,9 +32,7 @@ typedef struct { uint32_t version; ScreenLogLevel log_level; bool display_initialized; - bool emunand_enabled; - char emunand_path[0x100]; char bct0[BCTO_MAX_SIZE]; } stage2_args_t; -#endif +#endif \ No newline at end of file