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)