diff --git a/Makefile b/Makefile index f2ba8bb5..842218c4 100755 --- a/Makefile +++ b/Makefile @@ -37,7 +37,7 @@ OBJS += $(addprefix $(BUILDDIR)/$(TARGET)/, \ fuse.o kfuse.o \ sdmmc.o sdmmc_driver.o emmc.o sd.o emummc.o \ bq24193.o max17050.o max7762x.o max77620-rtc.o \ - hw_init.o \ + hw_init.o boot_storage.o \ ) # Utilities. diff --git a/bdk/storage/emmc.c b/bdk/storage/emmc.c index b1ab03d2..4b1a4115 100644 --- a/bdk/storage/emmc.c +++ b/bdk/storage/emmc.c @@ -25,6 +25,7 @@ static u16 emmc_errors[3] = { 0 }; // Init and Read/Write errors. static u32 emmc_mode = EMMC_MMC_HS400; +static bool emmc_init_done = false; sdmmc_t emmc_sdmmc; sdmmc_storage_t emmc_storage; @@ -61,7 +62,18 @@ u32 emmc_get_mode() return emmc_mode; } -void emmc_end() { sdmmc_storage_end(&emmc_storage); } +static void _emmc_deinit(){ + if(emmc_init_done){ + sdmmc_storage_end(&emmc_storage); + emmc_init_done = false; + } +} + +void emmc_end() { _emmc_deinit(); } + +bool emmc_get_initialized(){ + return emmc_init_done; +} int emmc_init_retry(bool power_cycle) { @@ -97,7 +109,13 @@ int emmc_init_retry(bool power_cycle) emmc_mode = EMMC_MMC_HS400; } - return sdmmc_storage_init_mmc(&emmc_storage, &emmc_sdmmc, bus_width, type); + int res = sdmmc_storage_init_mmc(&emmc_storage, &emmc_sdmmc, bus_width, type); + if(res){ + emmc_init_done = true; + }else{ + emmc_init_done = false; + } + return res; } bool emmc_initialize(bool power_cycle) diff --git a/bdk/storage/emmc.h b/bdk/storage/emmc.h index 904852d0..3b591683 100644 --- a/bdk/storage/emmc.h +++ b/bdk/storage/emmc.h @@ -65,6 +65,7 @@ int emmc_init_retry(bool power_cycle); bool emmc_initialize(bool power_cycle); int emmc_set_partition(u32 partition); void emmc_end(); +bool emmc_get_initialized(); void emmc_gpt_parse(link_t *gpt); void emmc_gpt_free(link_t *gpt); diff --git a/bdk/storage/sd.c b/bdk/storage/sd.c index 3ad31faa..cf1caf29 100644 --- a/bdk/storage/sd.c +++ b/bdk/storage/sd.c @@ -199,7 +199,7 @@ bool sd_mount() else { if (!sd_mounted) - res = f_mount(&sd_fs, "0:", 1); // Volume 0 is SD. + res = f_mount(&sd_fs, XSTR(FF_DEV_SD) ":", 1); // Volume 0 is SD. if (res == FR_OK) { sd_mounted = true; @@ -227,7 +227,7 @@ static void _sd_deinit(bool deinit) if (sd_init_done) { if (sd_mounted) - f_mount(NULL, "0:", 1); // Volume 0 is SD. + f_mount(NULL, XSTR(FF_DEV_SD) ":", 1); // Volume 0 is SD. if (deinit) { diff --git a/bdk/utils/types.h b/bdk/utils/types.h index 66c5d60c..e15fadbf 100644 --- a/bdk/utils/types.h +++ b/bdk/utils/types.h @@ -105,6 +105,9 @@ typedef unsigned long uptr; #define likely(x) (__builtin_expect((x) != 0, 1)) #define unlikely(x) (__builtin_expect((x) != 0, 0)) +#define XSTR(a) STR(a) +#define STR(a) #a + /* Bootloader/Nyx */ #define BOOT_CFG_AUTOBOOT_EN BIT(0) #define BOOT_CFG_FROM_LAUNCH BIT(1) diff --git a/bootloader/frontend/fe_info.c b/bootloader/frontend/fe_info.c index 67bcfba9..0af7b88c 100644 --- a/bootloader/frontend/fe_info.c +++ b/bootloader/frontend/fe_info.c @@ -15,6 +15,7 @@ * along with this program. If not, see . */ +#include #include #include @@ -232,20 +233,19 @@ void print_sdcard_info() sd_storage.ssr.app_class, sd_storage.csd.write_protect, sd_errors[0], sd_errors[1], sd_errors[2]); // SD_ERROR_INIT_FAIL, SD_ERROR_RW_FAIL, SD_ERROR_RW_RETRY. - int res = f_mount(&sd_fs, "", 1); - if (!res) + if (sd_mount()) { gfx_puts("Acquiring FAT volume info...\n\n"); - f_getfree("", &sd_fs.free_clst, NULL); + f_getfree(XSTR(FF_DEV_SD) ":", &sd_fs.free_clst, NULL); gfx_printf("%kFound %s volume:%k\n Free: %d MiB\n Cluster: %d KiB\n", TXT_CLR_CYAN_L, sd_fs.fs_type == FS_EXFAT ? "exFAT" : "FAT32", TXT_CLR_DEFAULT, sd_fs.free_clst * sd_fs.csize >> SECTORS_TO_MIB_COEFF, (sd_fs.csize > 1) ? (sd_fs.csize >> 1) : 512); - f_mount(NULL, "", 1); + sd_end(); } else { - EPRINTFARGS("Failed to mount SD card (FatFS Error %d).\n" - "Make sure that a FAT partition exists..", res); + EPRINTF("Failed to mount SD card.\n" + "Make sure that a FAT partition exists.."); } sd_end(); diff --git a/bootloader/hos/hos.c b/bootloader/hos/hos.c index a0bbed6d..54017371 100644 --- a/bootloader/hos/hos.c +++ b/bootloader/hos/hos.c @@ -28,6 +28,7 @@ #include "../frontend/fe_tools.h" #include "../config.h" #include "../storage/emummc.h" +#include "../storage/boot_storage.h" extern hekate_config h_cfg; @@ -1086,6 +1087,7 @@ int hos_launch(ini_sec_t *cfg) config_exosphere(&ctxt, warmboot_base); // Unmount SD card and eMMC. + boot_storage_end(); sd_end(); emmc_end(); diff --git a/bootloader/l4t/l4t.c b/bootloader/l4t/l4t.c index bce3fa19..f4da3b29 100644 --- a/bootloader/l4t/l4t.c +++ b/bootloader/l4t/l4t.c @@ -25,6 +25,7 @@ #include "../hos/pkg1.h" #include "l4t.h" #include "l4t_config.inl" +#include "../storage/boot_storage.h" /* * API Revision info @@ -1025,7 +1026,7 @@ void launch_l4t(const ini_sec_t *ini_sec, int entry_idx, int is_list, bool t210b return; // Done loading bootloaders/firmware. - sd_end(); + boot_storage_end(); // We don't need AHB aperture open. mc_disable_ahb_redirect(); diff --git a/bootloader/libs/fatfs/diskio.c b/bootloader/libs/fatfs/diskio.c index d207d968..01738e89 100644 --- a/bootloader/libs/fatfs/diskio.c +++ b/bootloader/libs/fatfs/diskio.c @@ -7,11 +7,37 @@ /* storage control modules to the FatFs module with a defined API. */ /*-----------------------------------------------------------------------*/ +#include +#include #include #include #include /* FatFs lower layer API */ +#include "ffconf.h" + +static bool ensure_partition(BYTE pdrv){ + u8 part; + switch(pdrv){ + case FF_DEV_SD: + return true; + case FF_DEV_BOOT1: + case FF_DEV_BOOT1_1MB: + part = EMMC_BOOT1; + break; + case FF_DEV_GPP: + part = EMMC_GPP; + break; + default: + return false; + } + + if(emmc_storage.partition != part){ + return emmc_set_partition(part); + } + + return true; +} /*-----------------------------------------------------------------------*/ /* Get Drive Status */ @@ -43,7 +69,27 @@ DRESULT disk_read ( UINT count /* Number of sectors to read */ ) { - return sdmmc_storage_read(&sd_storage, sector, count, buff) ? RES_OK : RES_ERROR; + sdmmc_storage_t *storage = &sd_storage; + u32 actual_sector = sector; + switch(pdrv){ + case FF_DEV_SD: + break; + case FF_DEV_BOOT1: + case FF_DEV_GPP: + storage = &emmc_storage; + break; + case FF_DEV_BOOT1_1MB: + storage = &emmc_storage; + actual_sector = sector + (0x100000 / 512); + break; + default: + return RES_ERROR; + + } + + ensure_partition(pdrv); + + return sdmmc_storage_read(storage, actual_sector, count, buff) ? RES_OK : RES_ERROR; } /*-----------------------------------------------------------------------*/ @@ -56,7 +102,27 @@ DRESULT disk_write ( UINT count /* Number of sectors to write */ ) { - return sdmmc_storage_write(&sd_storage, sector, count, (void *)buff) ? RES_OK : RES_ERROR; + sdmmc_storage_t *storage = &sd_storage; + u32 actual_sector = sector; + switch(pdrv){ + case FF_DEV_SD: + break; + case FF_DEV_BOOT1: + case FF_DEV_GPP: + storage = &emmc_storage; + break; + case FF_DEV_BOOT1_1MB: + storage = &emmc_storage; + actual_sector = sector + (0x100000 / 512); + break; + default: + return RES_ERROR; + + } + + ensure_partition(pdrv); + + return sdmmc_storage_write(storage, actual_sector, count, (void*)buff) ? RES_OK : RES_ERROR; } /*-----------------------------------------------------------------------*/ diff --git a/bootloader/libs/fatfs/ffconf.h b/bootloader/libs/fatfs/ffconf.h index 33516fe3..3efdad30 100644 --- a/bootloader/libs/fatfs/ffconf.h +++ b/bootloader/libs/fatfs/ffconf.h @@ -166,7 +166,7 @@ */ -#define FF_FS_RPATH 0 +#define FF_FS_RPATH 1 /* This option configures support for relative path. / / 0: Disable relative path and remove related functions. @@ -179,12 +179,12 @@ / Drive/Volume Configurations /---------------------------------------------------------------------------*/ -#define FF_VOLUMES 1 +#define FF_VOLUMES 4 /* Number of volumes (logical drives) to be used. (1-10) */ #define FF_STR_VOLUME_ID 0 -#define FF_VOLUME_STRS "sd" +#define FF_VOLUME_STRS "sd", "boot1", "boot1_1mb", "gpp" /* FF_STR_VOLUME_ID switches support for volume ID in arbitrary strings. / When FF_STR_VOLUME_ID is set to 1 or 2, arbitrary strings can be used as drive / number in the path name. FF_VOLUME_STRS defines the volume ID strings for each @@ -300,6 +300,9 @@ / SemaphoreHandle_t and etc. A header file for O/S definitions needs to be / included somewhere in the scope of ff.h. */ - +#define FF_DEV_BOOT1 1 +#define FF_DEV_BOOT1_1MB 2 +#define FF_DEV_SD 0 +#define FF_DEV_GPP 3 /*--- End of configuration options ---*/ diff --git a/bootloader/main.c b/bootloader/main.c index 861b7575..0f41cdf3 100644 --- a/bootloader/main.c +++ b/bootloader/main.c @@ -31,6 +31,7 @@ #include #include #include "storage/emummc.h" +#include "storage/boot_storage.h" #include "frontend/fe_tools.h" #include "frontend/fe_info.h" @@ -205,7 +206,7 @@ static void _launch_payload(char *path, bool update, bool clear_screen) if (update && is_ipl_updated(buf, path, false)) goto out; - sd_end(); + boot_storage_end(); if (size < 0x30000) { @@ -264,8 +265,8 @@ static void _launch_payloads() gfx_clear_grey(0x1B); gfx_con_setpos(0, 0); - if (!sd_mount()) - goto failed_sd_mount; + if (!boot_storage_mount()) + goto failed_boot_storage_mount; ments = (ment_t *)malloc(sizeof(ment_t) * (max_entries + 3)); @@ -308,7 +309,7 @@ static void _launch_payloads() free(ments); free(dir); free(filelist); - sd_end(); + boot_storage_end(); return; } @@ -324,11 +325,11 @@ static void _launch_payloads() _launch_payload(dir, false, true); } -failed_sd_mount: +failed_boot_storage_mount: free(dir); free(ments); free(filelist); - sd_end(); + boot_storage_end(); btn_wait(); } @@ -346,7 +347,7 @@ static void _launch_ini_list() gfx_clear_grey(0x1B); gfx_con_setpos(0, 0); - if (!sd_mount()) + if (!boot_storage_mount()) goto parse_failed; // Check that ini files exist and parse them. @@ -449,7 +450,7 @@ parse_failed: wrong_emupath: if (emummc_path) { - sd_mount(); + boot_storage_mount(); emummc_load_cfg(); // Reload emuMMC config in case of emupath. } } @@ -474,7 +475,7 @@ static void _launch_config() gfx_clear_grey(0x1B); gfx_con_setpos(0, 0); - if (!sd_mount()) + if (!boot_storage_mount()) goto parse_failed; // Load emuMMC configuration. @@ -557,7 +558,7 @@ static void _launch_config() if (!cfg_sec) { free(ments); - sd_end(); + boot_storage_end(); return; } @@ -592,13 +593,13 @@ parse_failed: wrong_emupath: if (emummc_path) { - sd_mount(); + boot_storage_mount(); emummc_load_cfg(); // Reload emuMMC config in case of emupath. } } out: - sd_end(); + boot_storage_end(); free(ments); @@ -615,7 +616,7 @@ static void _nyx_load_run() if (!nyx) return; - sd_end(); + boot_storage_end(); render_static_bootlogo(); display_backlight_brightness(h_cfg.backlight, 1000); @@ -1010,7 +1011,7 @@ skip_list: wrong_emupath: if (emummc_path || b_cfg.boot_cfg & BOOT_CFG_TO_EMUMMC) { - sd_mount(); + boot_storage_mount(); emummc_load_cfg(); // Reload emuMMC config in case of emupath. } @@ -1482,7 +1483,8 @@ void ipl_main() bpmp_clk_rate_set(h_cfg.t210b01 ? BPMP_CLK_DEFAULT_BOOST : BPMP_CLK_LOWER_BOOST); // Mount SD Card. - h_cfg.errors |= !sd_mount() ? ERR_SD_BOOT_EN : 0; + // TODO: boot storage may not be sd card -> set proper error + h_cfg.errors |= !boot_storage_mount() ? ERR_SD_BOOT_EN : 0; // Check if watchdog was fired previously. if (watchdog_fired()) @@ -1525,7 +1527,7 @@ skip_lp0_minerva_config: _auto_launch(); // Failed to launch Nyx, unmount SD Card. - sd_end(); + boot_storage_end(); // Set ram to a freq that doesn't need periodic training. minerva_change_freq(FREQ_800); diff --git a/bootloader/storage/boot_storage.c b/bootloader/storage/boot_storage.c new file mode 100644 index 00000000..6c67524f --- /dev/null +++ b/bootloader/storage/boot_storage.c @@ -0,0 +1,154 @@ +#include "boot_storage.h" +#include +#include "../libs/fatfs/ffconf.h" +#include +#include +#include + +#define DEV_INVALID 0xff + +static FATFS boot_storage_fs; +static BYTE drive = -1; + +static const char* drive_base_paths[] = { + [FF_DEV_SD] = XSTR(FF_DEV_SD) ":", + [FF_DEV_BOOT1] = XSTR(FF_DEV_BOOT1) ":", + [FF_DEV_BOOT1_1MB] = XSTR(FF_DEV_BOOT1_1MB) ":", + [FF_DEV_GPP] = XSTR(FF_DEV_GPP) ":", +}; + +static bool _is_eligible(){ + if(f_stat(".no_boot_storage", NULL) == FR_OK){ + return false; + } + return true; +} + +bool boot_storage_get_mounted(){ + return drive != DEV_INVALID; +} + +bool boot_storage_get_initialized(){ + switch(drive){ + case FF_DEV_BOOT1: + case FF_DEV_GPP: + case FF_DEV_BOOT1_1MB: + return emmc_get_initialized(); + case FF_DEV_SD: + return sd_get_card_initialized(); + } + return false; +} + +static bool _boot_storage_initialize(){ + switch(drive){ + case FF_DEV_BOOT1: + case FF_DEV_GPP: + case FF_DEV_BOOT1_1MB: + return emmc_initialize(false); + case FF_DEV_SD: + return sd_initialize(false); + } + return false; +} + +static void _boot_storage_end(bool deinit){ + if(boot_storage_get_mounted()){ + if(drive == FF_DEV_SD){ + sd_unmount(); + }else{ + f_mount(NULL, drive_base_paths[drive], false); + } + drive = DEV_INVALID; + } + if(deinit){ + if(drive == FF_DEV_SD){ + sd_end(); + }else{ + emmc_end(); + } + } +} + +void boot_storage_unmount(){ + _boot_storage_end(false); +} + +void boot_storage_end(){ + _boot_storage_end(true); +} + +static bool _boot_storage_mount(){ + // may want to check sd card first and prioritize it + + FRESULT res; + + if(!emmc_get_initialized() && !emmc_initialize(false)){ + goto emmc_init_fail; + } + + static const BYTE emmc_drives[] = {FF_DEV_BOOT1_1MB, FF_DEV_BOOT1, FF_DEV_GPP}; + + for(BYTE i = 0; i < ARRAY_SIZE(emmc_drives); i++){ + res = f_mount(&boot_storage_fs, drive_base_paths[i], true); + if(res == FR_OK){ + res = f_chdrive(drive_base_paths[i]); + if(res == FR_OK && _is_eligible()){ + drive = i; + break; + }else{ + f_mount(NULL, drive_base_paths[i],false); + res = FR_INVALID_DRIVE; + } + } + } + + if(res != FR_OK){ + emmc_end(); + } + + if(res == FR_OK){ + return true; + } + +emmc_init_fail: + if(!sd_initialize(false)){ + goto out; + } + + if(!sd_mount()){ + sd_end(); + goto out; + } + + res = f_chdrive(drive_base_paths[FF_DEV_SD]); + + if(res == FR_OK && _is_eligible()){ + drive = FF_DEV_SD; + return true; + } + + sd_end(); + +out: + return false; +} + +bool boot_storage_mount(){ + bool mounted = boot_storage_get_mounted(); + bool initialized = boot_storage_get_initialized(); + if(mounted && initialized){ + return true; + } + + if(!mounted){ + // not mounted. mounting will also initialize. + return _boot_storage_mount(); + } + + if(!initialized){ + return _boot_storage_initialize(); + } + + return true; +} \ No newline at end of file diff --git a/bootloader/storage/boot_storage.h b/bootloader/storage/boot_storage.h new file mode 100644 index 00000000..a1fce76c --- /dev/null +++ b/bootloader/storage/boot_storage.h @@ -0,0 +1,16 @@ +#ifndef _BOOT_STORAGE_H +#define _BOOT_STORAGE_H + +#include + +// check if boot1 (1mb), boot1, gpp, sd (in that order) have fat32 partition, +// mount the partition and set the current drive to it +bool boot_storage_mount(); + +void boot_storage_unmount(); +void boot_storage_end(); + +bool boot_storage_get_mounted(); +bool boot_storage_get_initialized(); + +#endif \ No newline at end of file diff --git a/bootloader/storage/emummc.c b/bootloader/storage/emummc.c index 64fe907c..21219e6c 100644 --- a/bootloader/storage/emummc.c +++ b/bootloader/storage/emummc.c @@ -23,6 +23,8 @@ #include "../config.h" #include +#define DEV_SD_BASE_PATH XSTR(FF_DEV_SD) ":" + extern hekate_config h_cfg; emummc_cfg_t emu_cfg = { 0 }; @@ -77,7 +79,8 @@ bool emummc_set_path(char *path) FIL fp; bool found = false; - strcpy(emu_cfg.emummc_file_based_path, path); + strcpy(emu_cfg.emummc_file_based_path, DEV_SD_BASE_PATH); + strcat(emu_cfg.emummc_file_based_path, path); strcat(emu_cfg.emummc_file_based_path, "/raw_based"); if (!f_open(&fp, emu_cfg.emummc_file_based_path, FA_READ)) @@ -88,7 +91,8 @@ bool emummc_set_path(char *path) } else { - strcpy(emu_cfg.emummc_file_based_path, path); + strcpy(emu_cfg.emummc_file_based_path, DEV_SD_BASE_PATH); + strcat(emu_cfg.emummc_file_based_path, path); strcat(emu_cfg.emummc_file_based_path, "/file_based"); if (!f_stat(emu_cfg.emummc_file_based_path, NULL)) @@ -149,7 +153,8 @@ int emummc_storage_init_mmc() if (!emu_cfg.sector) { - strcpy(emu_cfg.emummc_file_based_path, emu_cfg.path); + strcpy(emu_cfg.emummc_file_based_path, DEV_SD_BASE_PATH); + strcat(emu_cfg.emummc_file_based_path, emu_cfg.path); strcat(emu_cfg.emummc_file_based_path, "/eMMC"); if (f_stat(emu_cfg.emummc_file_based_path, &fno)) @@ -279,7 +284,8 @@ int emummc_storage_set_mmc_partition(u32 partition) return 1; else { - strcpy(emu_cfg.emummc_file_based_path, emu_cfg.path); + strcpy(emu_cfg.emummc_file_based_path, DEV_SD_BASE_PATH); + strcat(emu_cfg.emummc_file_based_path, emu_cfg.path); strcat(emu_cfg.emummc_file_based_path, "/eMMC"); switch (partition)