Add support for reading boot files from FAT partition on BOOT1/GPP/SD in that order

Emummc config is read from boot partition, file based files still read from SD
This commit is contained in:
Christoph Baumann
2025-04-22 13:42:20 +02:00
parent 9d2ec42a9f
commit 5798dcde0d
14 changed files with 310 additions and 38 deletions

View File

@@ -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.

View File

@@ -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)

View File

@@ -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);

View File

@@ -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)
{

View File

@@ -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)

View File

@@ -15,6 +15,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <storage/sd.h>
#include <string.h>
#include <bdk.h>
@@ -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();

View File

@@ -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();

View File

@@ -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();

View File

@@ -7,11 +7,37 @@
/* storage control modules to the FatFs module with a defined API. */
/*-----------------------------------------------------------------------*/
#include <storage/sd.h>
#include <storage/sdmmc.h>
#include <string.h>
#include <bdk.h>
#include <libs/fatfs/diskio.h> /* 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;
}
/*-----------------------------------------------------------------------*/

View File

@@ -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 ---*/

View File

@@ -31,6 +31,7 @@
#include <libs/compr/blz.h>
#include <libs/fatfs/ff.h>
#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);

View File

@@ -0,0 +1,154 @@
#include "boot_storage.h"
#include <libs/fatfs/ff.h>
#include "../libs/fatfs/ffconf.h"
#include <storage/sd.h>
#include <storage/emmc.h>
#include <utils/types.h>
#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;
}

View File

@@ -0,0 +1,16 @@
#ifndef _BOOT_STORAGE_H
#define _BOOT_STORAGE_H
#include <utils/types.h>
// 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

View File

@@ -23,6 +23,8 @@
#include "../config.h"
#include <libs/fatfs/ff.h>
#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)