diff --git a/fusee/fusee-primary/src/lib/fatfs/diskio.c b/fusee/fusee-primary/src/lib/fatfs/diskio.c index 9de072b9e..3b32b59ee 100644 --- a/fusee/fusee-primary/src/lib/fatfs/diskio.c +++ b/fusee/fusee-primary/src/lib/fatfs/diskio.c @@ -15,15 +15,8 @@ static bool g_ahb_redirect_enabled = false; -// Only use voltage switching in stage2 and later. -#ifdef FUSEE_STAGE1_SRC -#define MMC_VOLTAGE_SWITCHING_ALLOWED false -#else -#define MMC_VOLTAGE_SWITCHING_ALLOWED true -#endif - /* Global sd struct. */ -static struct mmc g_sd_mmc = {0}; +struct mmc g_sd_mmc = {0}; static bool g_sd_initialized = false; int initialize_sd_mmc(void) { @@ -33,7 +26,7 @@ int initialize_sd_mmc(void) { } if (!g_sd_initialized) { - int rc = sdmmc_init(&g_sd_mmc, SWITCH_MICROSD, MMC_VOLTAGE_SWITCHING_ALLOWED); + int rc = sdmmc_init(&g_sd_mmc, SWITCH_MICROSD, false); if (rc == 0) { g_sd_initialized = true; return 0; diff --git a/fusee/fusee-primary/src/main.c b/fusee/fusee-primary/src/main.c index 568dfec13..239251ad9 100644 --- a/fusee/fusee-primary/src/main.c +++ b/fusee/fusee-primary/src/main.c @@ -108,7 +108,9 @@ int main(void) { const char *stage2_path; stage2_args_t *stage2_args; uint32_t stage2_version = 0; + extern struct mmc g_sd_mmc; + sdmmc_set_loglevel(2); /* Initialize the display, console, etc. */ setup_env(); @@ -134,6 +136,8 @@ int main(void) { strcpy(g_chainloader_arg_data, stage2_path); stage2_args = (stage2_args_t *)(g_chainloader_arg_data + strlen(stage2_path) + 1); /* May be unaligned. */ memcpy(&stage2_args->version, &stage2_version, 4); + stage2_args->display_initialized = false; + memcpy(&stage2_args->sd_mmc, &g_sd_mmc, sizeof(g_sd_mmc)); strcpy(stage2_args->bct0, bct0); g_chainloader_argc = 2; diff --git a/fusee/fusee-primary/src/sdmmc.c b/fusee/fusee-primary/src/sdmmc.c index 40abccba4..6f377e8ca 100644 --- a/fusee/fusee-primary/src/sdmmc.c +++ b/fusee/fusee-primary/src/sdmmc.c @@ -2259,7 +2259,7 @@ static int sdmmc_send_app_command(struct mmc *mmc, enum sdmmc_command command, } // And issue the body of the command. - return sdmmc_send_command(mmc, command, response_type, checks, argument, response_buffer, + return sdmmc_send_command(mmc, command, response_type, checks, argument, response_buffer, blocks_to_transfer, false, auto_terminate, data_buffer); } @@ -3382,8 +3382,8 @@ static int sdmmc_initialize_defaults(struct mmc *mmc) * @param controler The controller description to be used; usually SWITCH_EMMC * or SWITCH_MICROSD. * @param allow_voltage_switching True if we should allow voltage switching, - * which may not make sense if we're about to chainload to another component, - * a la fusee stage1. + * which may not make sense if we're about to chainload to another component without + * preseving the overall structure. */ int sdmmc_init(struct mmc *mmc, enum sdmmc_controller controller, bool allow_voltage_switching) { @@ -3445,6 +3445,29 @@ int sdmmc_init(struct mmc *mmc, enum sdmmc_controller controller, bool allow_vol } +/** + * Imports a SDMMC driver struct from another program. This mainly intended for stage2, + * so that it can reuse stage1's SDMMC struct instance(s). + * + * @param mmc The SDMMC structure to be imported. + */ +int sdmmc_import_struct(struct mmc *mmc) +{ + int rc; + bool uses_block_addressing = mmc->uses_block_addressing; + mmc->regs = sdmmc_get_regs(mmc->controller); + + rc = sdmmc_initialize_defaults(mmc); + if (rc) { + printk("ERROR: controller SDMMC%d not currently supported!\n", mmc->controller + 1); + return rc; + } + + mmc->uses_block_addressing = uses_block_addressing; + return 0; +} + + /** * Selects the active MMC partition. Can be used to select * boot partitions for access. Affects all operations going forward. diff --git a/fusee/fusee-primary/src/sdmmc.h b/fusee/fusee-primary/src/sdmmc.h index 67952b401..7feeb8522 100644 --- a/fusee/fusee-primary/src/sdmmc.h +++ b/fusee/fusee-primary/src/sdmmc.h @@ -234,12 +234,21 @@ int sdmmc_set_loglevel(int loglevel); * @param controler The controller description to be used; usually SWITCH_EMMC * or SWITCH_MICROSD. * @param allow_voltage_switching True if we should allow voltage switching, - * which may not make sense if we're about to chainload to another component, - * a la fusee stage1. + * which may not make sense if we're about to chainload to another component without + * preseving the overall structure. */ int sdmmc_init(struct mmc *mmc, enum sdmmc_controller controller, bool allow_voltage_switching); +/** + * Imports a SDMMC driver struct from another program. This mainly intended for stage2, + * so that it can reuse stage1's SDMMC struct instance(s). + * + * @param mmc The SDMMC structure to be imported. + */ +int sdmmc_import_struct(struct mmc *mmc); + + /** * Selects the active MMC partition. Can be used to select * boot partitions for access. Affects all operations going forward. diff --git a/fusee/fusee-primary/src/stage2.h b/fusee/fusee-primary/src/stage2.h index 632bacd29..50e001c02 100644 --- a/fusee/fusee-primary/src/stage2.h +++ b/fusee/fusee-primary/src/stage2.h @@ -2,6 +2,7 @@ #define FUSEE_STAGE2_H #include "utils.h" +#include "sdmmc.h" /* TODO: Is there a more concise way to do this? */ #define STAGE2_ARGV_PROGRAM_PATH 0 @@ -11,7 +12,7 @@ #define STAGE2_NAME_KEY "stage2_path" #define STAGE2_ADDRESS_KEY "stage2_addr" #define STAGE2_ENTRYPOINT_KEY "stage2_entrypoint" -#define BCTO_MAX_SIZE 0x6000 +#define BCTO_MAX_SIZE 0x5800 typedef struct { char path[0x100]; @@ -21,6 +22,8 @@ typedef struct { typedef struct { uint32_t version; + struct mmc sd_mmc; + bool display_initialized; char bct0[BCTO_MAX_SIZE]; } stage2_args_t; diff --git a/fusee/fusee-secondary/src/console.c b/fusee/fusee-secondary/src/console.c index 0259e8016..4d26d9601 100644 --- a/fusee/fusee-secondary/src/console.c +++ b/fusee/fusee-secondary/src/console.c @@ -87,15 +87,19 @@ static ssize_t decode_utf8(uint32_t *out, const uint8_t *in) { } static void console_init_display(void) { - /* Initialize the display. */ - display_init(); + if (!g_display_initialized) { + /* Initialize the display. */ + display_init(); + } /* Set the framebuffer. */ display_init_framebuffer(g_framebuffer); /* Turn on the backlight after initializing the lfb */ /* to avoid flickering. */ - display_enable_backlight(true); + if (!g_display_initialized) { + display_enable_backlight(true); + } g_display_initialized = true; } @@ -140,7 +144,10 @@ static int console_create(void) { return 0; } -int console_init(void) { + +int console_init(bool display_initialized) { + g_display_initialized = display_initialized; + if (console_create() == -1) { return -1; } diff --git a/fusee/fusee-secondary/src/console.h b/fusee/fusee-secondary/src/console.h index f73424003..07d26adbb 100644 --- a/fusee/fusee-secondary/src/console.h +++ b/fusee/fusee-secondary/src/console.h @@ -1,7 +1,7 @@ #ifndef FUSEE_CONSOLE_H #define FUSEE_CONSOLE_H -int console_init(void); +int console_init(bool display_initialized); void *console_get_framebuffer(bool enable_display); int console_display(const void *framebuffer); /* Must be page-aligned */ int console_resume(void); diff --git a/fusee/fusee-secondary/src/main.c b/fusee/fusee-secondary/src/main.c index 10811e614..6246a0f76 100644 --- a/fusee/fusee-secondary/src/main.c +++ b/fusee/fusee-secondary/src/main.c @@ -23,14 +23,14 @@ static bool g_do_nxboot; static void setup_env(void) { /* Set the console up. */ - if (console_init() == -1) { + if (console_init(g_stage2_args->display_initialized) == -1) { generic_panic(); } /* Set up exception handlers. */ setup_exception_handlers(); - if(switchfs_mount_all() == -1) { + if(switchfs_import_mmc_structs(&g_stage2_args->sd_mmc, NULL) == -1 || switchfs_mount_all() == -1) { fatal_error("Failed to mount at least one parition: %s\n", strerror(errno)); } diff --git a/fusee/fusee-secondary/src/sdmmc.c b/fusee/fusee-secondary/src/sdmmc.c index 40abccba4..6f377e8ca 100644 --- a/fusee/fusee-secondary/src/sdmmc.c +++ b/fusee/fusee-secondary/src/sdmmc.c @@ -2259,7 +2259,7 @@ static int sdmmc_send_app_command(struct mmc *mmc, enum sdmmc_command command, } // And issue the body of the command. - return sdmmc_send_command(mmc, command, response_type, checks, argument, response_buffer, + return sdmmc_send_command(mmc, command, response_type, checks, argument, response_buffer, blocks_to_transfer, false, auto_terminate, data_buffer); } @@ -3382,8 +3382,8 @@ static int sdmmc_initialize_defaults(struct mmc *mmc) * @param controler The controller description to be used; usually SWITCH_EMMC * or SWITCH_MICROSD. * @param allow_voltage_switching True if we should allow voltage switching, - * which may not make sense if we're about to chainload to another component, - * a la fusee stage1. + * which may not make sense if we're about to chainload to another component without + * preseving the overall structure. */ int sdmmc_init(struct mmc *mmc, enum sdmmc_controller controller, bool allow_voltage_switching) { @@ -3445,6 +3445,29 @@ int sdmmc_init(struct mmc *mmc, enum sdmmc_controller controller, bool allow_vol } +/** + * Imports a SDMMC driver struct from another program. This mainly intended for stage2, + * so that it can reuse stage1's SDMMC struct instance(s). + * + * @param mmc The SDMMC structure to be imported. + */ +int sdmmc_import_struct(struct mmc *mmc) +{ + int rc; + bool uses_block_addressing = mmc->uses_block_addressing; + mmc->regs = sdmmc_get_regs(mmc->controller); + + rc = sdmmc_initialize_defaults(mmc); + if (rc) { + printk("ERROR: controller SDMMC%d not currently supported!\n", mmc->controller + 1); + return rc; + } + + mmc->uses_block_addressing = uses_block_addressing; + return 0; +} + + /** * Selects the active MMC partition. Can be used to select * boot partitions for access. Affects all operations going forward. diff --git a/fusee/fusee-secondary/src/sdmmc.h b/fusee/fusee-secondary/src/sdmmc.h index 67952b401..7feeb8522 100644 --- a/fusee/fusee-secondary/src/sdmmc.h +++ b/fusee/fusee-secondary/src/sdmmc.h @@ -234,12 +234,21 @@ int sdmmc_set_loglevel(int loglevel); * @param controler The controller description to be used; usually SWITCH_EMMC * or SWITCH_MICROSD. * @param allow_voltage_switching True if we should allow voltage switching, - * which may not make sense if we're about to chainload to another component, - * a la fusee stage1. + * which may not make sense if we're about to chainload to another component without + * preseving the overall structure. */ int sdmmc_init(struct mmc *mmc, enum sdmmc_controller controller, bool allow_voltage_switching); +/** + * Imports a SDMMC driver struct from another program. This mainly intended for stage2, + * so that it can reuse stage1's SDMMC struct instance(s). + * + * @param mmc The SDMMC structure to be imported. + */ +int sdmmc_import_struct(struct mmc *mmc); + + /** * Selects the active MMC partition. Can be used to select * boot partitions for access. Affects all operations going forward. diff --git a/fusee/fusee-secondary/src/stage2.h b/fusee/fusee-secondary/src/stage2.h index 7ec36e9ba..a05db15cb 100644 --- a/fusee/fusee-secondary/src/stage2.h +++ b/fusee/fusee-secondary/src/stage2.h @@ -2,16 +2,19 @@ #define FUSEE_STAGE2_H #include "utils.h" +#include "sdmmc.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 BCTO_MAX_SIZE 0x6000 +#define BCTO_MAX_SIZE 0x5800 typedef struct { uint32_t version; + struct mmc sd_mmc; + bool display_initialized; char bct0[BCTO_MAX_SIZE]; } stage2_args_t; diff --git a/fusee/fusee-secondary/src/switch_fs.c b/fusee/fusee-secondary/src/switch_fs.c index aeeb24a96..50f5a0a67 100644 --- a/fusee/fusee-secondary/src/switch_fs.c +++ b/fusee/fusee-secondary/src/switch_fs.c @@ -12,6 +12,9 @@ static bool g_ahb_redirect_enabled = false; static bool g_sd_mmc_initialized = false; static bool g_nand_mmc_initialized = false; +static bool g_sd_mmc_imported = false; +static bool g_nand_mmc_imported = false; + static struct mmc g_sd_mmc = {0}; static struct mmc g_nand_mmc = {0}; @@ -43,7 +46,7 @@ static int mmc_partition_initialize(device_partition_t *devpart) { if (mmcpart->mmc == &g_sd_mmc) { if (!g_sd_mmc_initialized) { - int rc = sdmmc_init(mmcpart->mmc, mmcpart->controller, true); + int rc = g_sd_mmc_imported ? 0 : sdmmc_init(mmcpart->mmc, mmcpart->controller, true); if (rc == 0) { sdmmc_set_write_enable(mmcpart->mmc, SDMMC_WRITE_ENABLED); g_sd_mmc_initialized = true; @@ -56,7 +59,7 @@ static int mmc_partition_initialize(device_partition_t *devpart) { return 0; } else if (mmcpart->mmc == &g_nand_mmc) { if (!g_nand_mmc_initialized) { - int rc = sdmmc_init(mmcpart->mmc, mmcpart->controller, true); + int rc = g_nand_mmc_imported ? 0 : sdmmc_init(mmcpart->mmc, mmcpart->controller, true); if (rc == 0) { g_nand_mmc_initialized = true; } else { @@ -235,6 +238,36 @@ static int switchfs_mount_partition_gpt_callback(const efi_entry_t *entry, void return 0; } +int switchfs_import_mmc_structs(void *sd, void *nand) { + if (sd != NULL) { + int rc = 0; + memcpy(&g_sd_mmc, sd, sizeof(g_sd_mmc)); + rc = sdmmc_import_struct(&g_sd_mmc); + if (rc != 0) { + memset(&g_sd_mmc, 0, sizeof(g_sd_mmc)); + errno = rc; + return -1; + } else { + g_sd_mmc_imported = true; + } + } + + if (nand != NULL) { + int rc = 0; + memcpy(&g_nand_mmc, nand, sizeof(g_nand_mmc)); + rc = sdmmc_import_struct(&g_nand_mmc); + if (rc != 0) { + memset(&g_nand_mmc, 0, sizeof(g_nand_mmc)); + errno = rc; + return -1; + } else { + g_nand_mmc_imported = true; + } + } + + return 0; +} + int switchfs_mount_all(void) { device_partition_t model; int rc; diff --git a/fusee/fusee-secondary/src/switch_fs.h b/fusee/fusee-secondary/src/switch_fs.h index 376694edc..0cc256797 100644 --- a/fusee/fusee-secondary/src/switch_fs.h +++ b/fusee/fusee-secondary/src/switch_fs.h @@ -4,6 +4,8 @@ #include "fs_dev.h" #include "raw_dev.h" +int switchfs_import_mmc_structs(void *sd, void *nand); + int switchfs_mount_all(void); int switchfs_unmount_all(void);