Nyx: emuMMC Manage window, Tools UI, and misc updates

- Add gui_emu_tools: emuMMC Manage window with correct positioning (LV_PROTECT_PARENT + re-parent to win)
- Tools: single SD button (tap = SD partition manager, 3s hold = eMMC)
- Remove emuSD from Nyx UI (tabs, UMS, partition manager); keep bootloader emusd
- Shorten Create emuMMC description text by one character
- Storage/build/config and dependency updates

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-02-20 20:49:48 +01:00
parent 4eead2c14d
commit fed7f05831
81 changed files with 6932 additions and 3462 deletions

102
Makefile
View File

@@ -14,7 +14,6 @@ include ./Versions.inc
TARGET := hekate TARGET := hekate
BUILDDIR := build BUILDDIR := build
BUILDTDIR := build/$(TARGET)
OUTPUTDIR := output OUTPUTDIR := output
SOURCEDIR = bootloader SOURCEDIR = bootloader
BDKDIR := bdk BDKDIR := bdk
@@ -22,33 +21,42 @@ BDKINC := -I./$(BDKDIR)
VPATH = $(dir ./$(SOURCEDIR)/) $(dir $(wildcard ./$(SOURCEDIR)/*/)) $(dir $(wildcard ./$(SOURCEDIR)/*/*/)) VPATH = $(dir ./$(SOURCEDIR)/) $(dir $(wildcard ./$(SOURCEDIR)/*/)) $(dir $(wildcard ./$(SOURCEDIR)/*/*/))
VPATH += $(dir $(wildcard ./$(BDKDIR)/)) $(dir $(wildcard ./$(BDKDIR)/*/)) $(dir $(wildcard ./$(BDKDIR)/*/*/)) VPATH += $(dir $(wildcard ./$(BDKDIR)/)) $(dir $(wildcard ./$(BDKDIR)/*/)) $(dir $(wildcard ./$(BDKDIR)/*/*/))
# Track compiler flags
TRACK_CFLAGS = $(BUILDTDIR)/.cflags
TRACK_LDFLAGS = $(BUILDTDIR)/.ldflags
# Main and graphics. # Main and graphics.
OBJS = start exception_handlers main heap gfx logos tui fe_info fe_tools OBJS = $(addprefix $(BUILDDIR)/$(TARGET)/, \
start.o exception_handlers.o \
main.o heap.o \
gfx.o logos.o tui.o \
l4t.o fe_info.o fe_tools.o \
)
# Hardware. # Hardware.
OBJS += bpmp ccplex clock di i2c irq timer \ OBJS += $(addprefix $(BUILDDIR)/$(TARGET)/, \
mc sdram minerva smmu \ bpmp.o ccplex.o clock.o di.o i2c.o irq.o timer.o \
gpio pinmux pmc se tsec uart \ mc.o sdram.o minerva.o \
fuse kfuse \ gpio.o pinmux.o pmc.o se.o smmu.o tsec.o uart.o \
sdmmc sdmmc_driver emmc sd emummc \ fuse.o kfuse.o \
bq24193 max17050 max7762x max77620-rtc \ sdmmc.o sdmmc_driver.o emmc.o sd.o emummc.o emummc_file_based.o emusd.o \
hw_init bq24193.o max17050.o max7762x.o max77620-rtc.o \
hw_init.o boot_storage.o emusd.o file_based_storage.o \
)
# Utilities. # Utilities.
OBJS += btn dirlist ianos ini util config OBJS += $(addprefix $(BUILDDIR)/$(TARGET)/, \
btn.o dirlist.o ianos.o util.o \
config.o ini.o \
)
# OS loaders. # Horizon.
OBJS += l4t hos hos_config pkg1 pkg2 pkg3 pkg2_ini_kippatch secmon_exo OBJS += $(addprefix $(BUILDDIR)/$(TARGET)/, \
hos.o hos_config.o pkg1.o pkg2.o pkg3.o pkg2_ini_kippatch.o secmon_exo.o \
)
# Libraries. # Libraries.
OBJS += lz lz4 blz diskio ff ffunicode ffsystem elfload elfreloc_arm OBJS += $(addprefix $(BUILDDIR)/$(TARGET)/, \
lz.o lz4.o blz.o \
OBJS := $(addsuffix .o, $(OBJS)) diskio.o ff.o ffunicode.o ffsystem.o \
OBJS := $(addprefix $(BUILDTDIR)/, $(OBJS)) elfload.o elfreloc_arm.o \
)
GFX_INC := '"../$(SOURCEDIR)/gfx/gfx.h"' GFX_INC := '"../$(SOURCEDIR)/gfx/gfx.h"'
FFCFG_INC := '"../$(SOURCEDIR)/libs/fatfs/ffconf.h"' FFCFG_INC := '"../$(SOURCEDIR)/libs/fatfs/ffconf.h"'
@@ -86,17 +94,9 @@ TOOLSLZ := $(wildcard tools/lz)
TOOLSB2C := $(wildcard tools/bin2c) TOOLSB2C := $(wildcard tools/bin2c)
TOOLS := $(TOOLSLZ) $(TOOLSB2C) TOOLS := $(TOOLSLZ) $(TOOLSB2C)
ifndef IPLECHO
T := $(shell $(MAKE) $(BUILDTDIR)/$(TARGET).elf --no-print-directory -nrRf $(firstword $(MAKEFILE_LIST)) IPLECHO="IPLOBJ" | grep -c "IPLOBJ")
N := x
C = $(words $N)$(eval N := x $N)
IPLECHO = echo -ne "\r`expr " [\`expr $C '*' 100 / $T\`" : '.*\(....\)$$'`%]\033[K"
endif
################################################################################ ################################################################################
.PHONY: all clean $(LDRDIR) $(TOOLS) $(NYXDIR) $(MODULEDIRS) .PHONY: all clean $(MODULEDIRS) $(NYXDIR) $(LDRDIR) $(TOOLS)
all: $(TARGET).bin $(LDRDIR) all: $(TARGET).bin $(LDRDIR)
@printf ICTC49 >> $(OUTPUTDIR)/$(TARGET).bin @printf ICTC49 >> $(OUTPUTDIR)/$(TARGET).bin
@@ -113,18 +113,17 @@ all: $(TARGET).bin $(LDRDIR)
@echo "--------------------------------------" @echo "--------------------------------------"
clean: $(TOOLS) clean: $(TOOLS)
@rm -rf $(OBJS)
@rm -rf $(BUILDDIR) @rm -rf $(BUILDDIR)
@rm -rf $(OUTPUTDIR) @rm -rf $(OUTPUTDIR)
@$(MAKE) --no-print-directory -C $(LDRDIR) $(MAKECMDGOALS) -$(MAKEFLAGS)
$(MODULEDIRS): $(BUILDTDIR)/$(TARGET).elf $(MODULEDIRS):
@$(MAKE) --no-print-directory -C $@ $(MAKECMDGOALS) -$(MAKEFLAGS) @$(MAKE) --no-print-directory -C $@ $(MAKECMDGOALS) -$(MAKEFLAGS)
$(NYXDIR): $(BUILDTDIR)/$(TARGET).elf $(MODULEDIRS) $(NYXDIR):
@echo --------------------------------------
@$(MAKE) --no-print-directory -C $@ $(MAKECMDGOALS) -$(MAKEFLAGS) @$(MAKE) --no-print-directory -C $@ $(MAKECMDGOALS) -$(MAKEFLAGS)
$(LDRDIR): $(TARGET).bin $(TOOLS) $(NYXDIR) $(MODULEDIRS) $(LDRDIR): $(TARGET).bin
@$(TOOLSLZ)/lz77 $(OUTPUTDIR)/$(TARGET).bin @$(TOOLSLZ)/lz77 $(OUTPUTDIR)/$(TARGET).bin
@mv $(OUTPUTDIR)/$(TARGET).bin $(OUTPUTDIR)/$(TARGET)_unc.bin @mv $(OUTPUTDIR)/$(TARGET).bin $(OUTPUTDIR)/$(TARGET)_unc.bin
@mv $(OUTPUTDIR)/$(TARGET).bin.00.lz payload_00 @mv $(OUTPUTDIR)/$(TARGET).bin.00.lz payload_00
@@ -138,31 +137,24 @@ $(LDRDIR): $(TARGET).bin $(TOOLS) $(NYXDIR) $(MODULEDIRS)
$(TOOLS): $(TOOLS):
@$(MAKE) --no-print-directory -C $@ $(MAKECMDGOALS) -$(MAKEFLAGS) @$(MAKE) --no-print-directory -C $@ $(MAKECMDGOALS) -$(MAKEFLAGS)
$(TARGET).bin: $(BUILDTDIR)/$(TARGET).elf $(TARGET).bin: $(BUILDDIR)/$(TARGET)/$(TARGET).elf $(MODULEDIRS) $(NYXDIR) $(TOOLS)
@$(OBJCOPY) -S -O binary $< $(OUTPUTDIR)/$@ @$(OBJCOPY) -S -O binary $< $(OUTPUTDIR)/$@
@echo --------------------------------------
$(BUILDTDIR)/$(TARGET).elf: $(OBJS) $(TRACK_LDFLAGS) $(BUILDDIR)/$(TARGET)/$(TARGET).elf: $(OBJS)
@echo -ne "\r[100%] Linking $(TARGET).elf\033[K" @$(CC) $(LDFLAGS) -T $(SOURCEDIR)/link.ld $^ -o $@
@$(CC) $(LDFLAGS) -T $(SOURCEDIR)/link.ld $(OBJS) -o $@ @printf "$(TARGET) was built with the following flags:\nCFLAGS: $(CFLAGS)\nLDFLAGS: $(LDFLAGS)\n"
@printf "\n$(TARGET) was built with the following flags:\nCFLAGS: $(CFLAGS)\nLDFLAGS: $(LDFLAGS)\n"
$(BUILDTDIR)/%.o: %.c $(TRACK_CFLAGS) | $(BUILDTDIR) $(BUILDDIR)/$(TARGET)/%.o: %.c
@$(IPLECHO) Building $@ @echo Building $@
@$(CC) $(CFLAGS) $(BDKINC) -MMD -MP -c $< -o $@ @$(CC) $(CFLAGS) $(BDKINC) -c $< -o $@
$(BUILDTDIR)/%.o: %.S $(TRACK_CFLAGS) | $(BUILDTDIR) $(BUILDDIR)/$(TARGET)/%.o: %.S
@$(IPLECHO) Building $@ @echo Building $@
@$(CC) $(CFLAGS) -MMD -MP -c $< -o $@ @$(CC) $(CFLAGS) -c $< -o $@
$(BUILDTDIR): $(OBJS): $(BUILDDIR)/$(TARGET)
$(BUILDDIR)/$(TARGET):
@mkdir -p "$(BUILDDIR)" @mkdir -p "$(BUILDDIR)"
@mkdir -p "$(BUILDTDIR)" @mkdir -p "$(BUILDDIR)/$(TARGET)"
@mkdir -p "$(OUTPUTDIR)" @mkdir -p "$(OUTPUTDIR)"
# Non objects change detectors.
$(TRACK_CFLAGS): $(BUILDTDIR)
@echo '$(CFLAGS)' | cmp -s - $@ || echo '$(CFLAGS)' > $@
$(TRACK_LDFLAGS): $(BUILDTDIR)
@echo '$(LDFLAGS)' | cmp -s - $@ || echo '$(LDFLAGS)' > $@
-include $(OBJS:.o=.d)

View File

@@ -818,7 +818,8 @@
* [30] 94 [10]: AUO A055TAN02 (59.05A30.002) * [30] 94 [10]: AUO A055TAN02 (59.05A30.002)
* [30] 95 [10]: AUO A055TAN03 (59.05A30.003) * [30] 95 [10]: AUO A055TAN03 (59.05A30.003)
* [40] 94 [10]: Sharp LQ055T1SW10 (Rev P) * [40] 94 [10]: Sharp LQ055T1SW10 (Rev P)
* * [E0] 01 [10]: Retro Remake SUPER5 OLED (Rev 01)
* [E1] 01 [10]: Retro Remake SUPER5 OLED HD (Rev 01)
* *
* 7.0" OLED panels for Aula SKU: * 7.0" OLED panels for Aula SKU:
* [50] 9B [20]: Samsung AMS699VC01-0 (Rev 2.5) * [50] 9B [20]: Samsung AMS699VC01-0 (Rev 2.5)
@@ -836,6 +837,8 @@
* 30h: AU Optronics * 30h: AU Optronics
* 40h: Sharp * 40h: Sharp
* 50h: Samsung * 50h: Samsung
* E0h: Retro Remake
* E1h: Retro Remake
* *
* Boards, Panel Size: * Boards, Panel Size:
* 0Fh: Icosa/Iowa, 6.2" * 0Fh: Icosa/Iowa, 6.2"
@@ -854,6 +857,8 @@ enum
PANEL_AUO_A055TAN01 = 0x1030, PANEL_AUO_A055TAN01 = 0x1030,
PANEL_SHP_LQ055T1SW10 = 0x1040, PANEL_SHP_LQ055T1SW10 = 0x1040,
PANEL_SAM_AMS699VC01 = 0x2050, PANEL_SAM_AMS699VC01 = 0x2050,
PANEL_RR_SUPER5_OLED_V1 = 0x10E0,
PANEL_RR_SUPER5_OLED_HD_V1 = 0x10E1,
// Found on 6/2" clones. Unknown markings. Clone of AUO A062TAN01. // Found on 6/2" clones. Unknown markings. Clone of AUO A062TAN01.
// Quality seems JDI like. Has bad low backlight scaling. ID: [83] 94 [0F]. Sometimes reports [30] 94 [0F]. Both IDs have correct CRC16. // Quality seems JDI like. Has bad low backlight scaling. ID: [83] 94 [0F]. Sometimes reports [30] 94 [0F]. Both IDs have correct CRC16.

View File

@@ -15,6 +15,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <storage/boot_storage.h>
#include <string.h> #include <string.h>
#include "ianos.h" #include "ianos.h"
@@ -75,7 +76,7 @@ uintptr_t ianos_loader(char *path, elfType_t type, void *moduleConfig)
uintptr_t epaddr = 0; uintptr_t epaddr = 0;
// Read library. // Read library.
fileBuf = sd_file_read(path, NULL); fileBuf = boot_storage_file_read(path, NULL);
if (!fileBuf) if (!fileBuf)
goto out; goto out;

View File

@@ -10,6 +10,7 @@ extern "C" {
#endif #endif
#include <utils/types.h> #include <utils/types.h>
#include <fatfs_cfg.h>
/* Status of Disk Functions */ /* Status of Disk Functions */
typedef BYTE DSTATUS; typedef BYTE DSTATUS;
@@ -23,14 +24,6 @@ typedef enum {
RES_PARERR /* 4: Invalid Parameter */ RES_PARERR /* 4: Invalid Parameter */
} DRESULT; } DRESULT;
typedef enum {
DRIVE_SD = 0,
DRIVE_RAM = 1,
DRIVE_EMMC = 2,
DRIVE_BIS = 3,
DRIVE_EMU = 4
} DDRIVE;
/*---------------------------------------*/ /*---------------------------------------*/
/* Prototypes for disk control functions */ /* Prototypes for disk control functions */

View File

@@ -42,8 +42,8 @@
#include <utils/util.h> #include <utils/util.h>
#include <gfx_utils.h> #include <gfx_utils.h>
#define EFSPRINTF(text, ...) print_error(); gfx_printf("%k"text"%k\n", 0xFFFFFF00, 0xFFFFFFFF); // #define EFSPRINTF(text, ...) print_error(); gfx_printf("%k"text"%k\n", 0xFFFFFF00, 0xFFFFFFFF);
//#define EFSPRINTF(...) #define EFSPRINTF(...)
/*-------------------------------------------------------------------------- /*--------------------------------------------------------------------------
@@ -474,6 +474,10 @@ static const char* const VolumeStr[FF_VOLUMES] = {FF_VOLUME_STRS}; /* Pre-define
#endif #endif
#endif #endif
#if FF_SIMPLE_GPT
static const BYTE GUID_MS_Basic[16] = {0xA2,0xA0,0xD0,0xEB,0xE5,0xB9,0x33,0x44,0x87,0xC0,0x68,0xB6,0xB7,0x26,0x99,0xC7};
#endif
/*--------------------------------*/ /*--------------------------------*/
/* LFN/Directory working buffer */ /* LFN/Directory working buffer */
@@ -3320,15 +3324,28 @@ static FRESULT find_volume ( /* FR_OK(0): successful, !=0: an error occurred */
} }
#if FF_SIMPLE_GPT #if FF_SIMPLE_GPT
if (fmt >= 2) { if (fmt >= 2) {
/* If GPT Check the first partition */ /* If GPT, iterate over all part entries and check MS Basic partitions */
gpt_header_t *gpt_header = (gpt_header_t *)fs->win; gpt_header_t *gpt_header = (gpt_header_t *)fs->win;
if (move_window(fs, 1) != FR_OK) return FR_DISK_ERR; if (move_window(fs, 1) != FR_OK) return FR_DISK_ERR;
if (!mem_cmp(&gpt_header->signature, "EFI PART", 8)) { if (!mem_cmp(&gpt_header->signature, "EFI PART", 8)) {
if (move_window(fs, gpt_header->part_ent_lba) != FR_OK) return FR_DISK_ERR; DWORD cur_entry, ofs, part;
gpt_entry_t *gpt_entry = (gpt_entry_t *)fs->win; part = LD2PT(vol);
fs->part_type = 1; cur_entry = 0;
bsect = gpt_entry->lba_start; for(i = 0; i < gpt_header->num_part_ents; i++){
fmt = bsect ? check_fs(fs, bsect) : 3; /* Check the partition */ if (move_window(fs, gpt_header->part_ent_lba + i * sizeof(gpt_entry_t) / SS(fs))) return FR_DISK_ERR;
ofs = i * sizeof(gpt_entry_t) % SS(fs);
gpt_entry_t *gpt_entry = (gpt_entry_t *)fs->win + ofs;
if (!mem_cmp(gpt_entry->type_guid, GUID_MS_Basic, 16)){
cur_entry++;
bsect = gpt_entry->lba_start;
fmt = bsect ? check_fs(fs, bsect) : 3;
if(part == 0 && fmt <= 1) break;
if(part != 0 && cur_entry == part) break;
}
}
if(part && part != cur_entry){
fmt = 3;
}
} }
} }
#endif #endif

View File

@@ -75,7 +75,7 @@ typedef struct _max77620_regulator_t
static const max77620_regulator_t _pmic_regulators[] = { static const max77620_regulator_t _pmic_regulators[] = {
{ "sd0", 12500, 600000, 625000, 1400000, REGULATOR_SD, MAX77620_REG_SD0, MAX77620_REG_SD0_CFG, MAX77620_SD0_VOLT_MASK, {{ MAX77620_REG_FPS_SD0, 1, 7, 1 }} }, { "sd0", 12500, 600000, 625000, 1400000, REGULATOR_SD, MAX77620_REG_SD0, MAX77620_REG_SD0_CFG, MAX77620_SD0_VOLT_MASK, {{ MAX77620_REG_FPS_SD0, 1, 7, 1 }} },
{ "sd1", 12500, 600000, 1125000, 1237500, REGULATOR_SD, MAX77620_REG_SD1, MAX77620_REG_SD1_CFG, MAX77620_SD1_VOLT_MASK, {{ MAX77620_REG_FPS_SD1, 0, 1, 5 }} }, { "sd1", 12500, 600000, 1125000, 1250000, REGULATOR_SD, MAX77620_REG_SD1, MAX77620_REG_SD1_CFG, MAX77620_SD1_VOLT_MASK, {{ MAX77620_REG_FPS_SD1, 0, 1, 5 }} },
{ "sd2", 12500, 600000, 1325000, 1350000, REGULATOR_SD, MAX77620_REG_SD2, MAX77620_REG_SD2_CFG, MAX77620_SDX_VOLT_MASK, {{ MAX77620_REG_FPS_SD2, 1, 5, 2 }} }, { "sd2", 12500, 600000, 1325000, 1350000, REGULATOR_SD, MAX77620_REG_SD2, MAX77620_REG_SD2_CFG, MAX77620_SDX_VOLT_MASK, {{ MAX77620_REG_FPS_SD2, 1, 5, 2 }} },
{ "sd3", 12500, 600000, 1800000, 1800000, REGULATOR_SD, MAX77620_REG_SD3, MAX77620_REG_SD3_CFG, MAX77620_SDX_VOLT_MASK, {{ MAX77620_REG_FPS_SD3, 0, 3, 3 }} }, { "sd3", 12500, 600000, 1800000, 1800000, REGULATOR_SD, MAX77620_REG_SD3, MAX77620_REG_SD3_CFG, MAX77620_SDX_VOLT_MASK, {{ MAX77620_REG_FPS_SD3, 0, 3, 3 }} },
{ "ldo0", 25000, 800000, 1200000, 1200000, REGULATOR_LDO, MAX77620_REG_LDO0_CFG, MAX77620_REG_LDO0_CFG2, MAX77620_LDO_VOLT_MASK, {{ MAX77620_REG_FPS_LDO0, 3, 7, 0 }} }, { "ldo0", 25000, 800000, 1200000, 1200000, REGULATOR_LDO, MAX77620_REG_LDO0_CFG, MAX77620_REG_LDO0_CFG2, MAX77620_LDO_VOLT_MASK, {{ MAX77620_REG_FPS_LDO0, 3, 7, 0 }} },

View File

@@ -91,33 +91,28 @@ static int _se_op_wait()
return 0; return 0;
} }
// WAR: Coherency flushing. // T210B01: IRAM/TZRAM/DRAM AHB coherency WAR.
if (ll_dst_ptr) if (!tegra_t210 && ll_dst_ptr)
{ {
u32 timeout = get_tmr_us() + 1000000;
// Ensure data is out from SE. // Ensure data is out from SE.
if (tegra_t210) while (SE(SE_STATUS_REG) & SE_STATUS_MEM_IF_BUSY)
usleep(15); // Worst case scenario.
else
{ {
// T210B01 has a status bit for that. if (get_tmr_us() > timeout)
u32 retries = 500000; return 0;
while (SE(SE_STATUS_REG) & SE_STATUS_MEM_IF_BUSY) usleep(1);
{
if (!retries)
return 0;
usleep(1);
retries--;
}
} }
// Ensure data is out from AHB. // Ensure data is out from AHB.
u32 retries = 500000; if (ll_dst_ptr->addr >= DRAM_START)
while (AHB_GIZMO(AHB_ARBITRATION_AHB_MEM_WRQUE_MST_ID) & MEM_WRQUE_SE_MST_ID)
{ {
if (!retries) timeout = get_tmr_us() + 200000;
return 0; while (AHB_GIZMO(AHB_ARBITRATION_AHB_MEM_WRQUE_MST_ID) & MEM_WRQUE_SE_MST_ID)
usleep(1); {
retries--; if (get_tmr_us() > timeout)
return 0;
usleep(1);
}
} }
} }
@@ -136,9 +131,6 @@ static int _se_execute_finalize()
static int _se_execute(u32 op, void *dst, u32 dst_size, const void *src, u32 src_size, bool is_oneshot) static int _se_execute(u32 op, void *dst, u32 dst_size, const void *src, u32 src_size, bool is_oneshot)
{ {
if (dst_size > SE_LL_MAX_SIZE || src_size > SE_LL_MAX_SIZE)
return 0;
ll_src_ptr = NULL; ll_src_ptr = NULL;
ll_dst_ptr = NULL; ll_dst_ptr = NULL;
@@ -178,41 +170,18 @@ static int _se_execute_oneshot(u32 op, void *dst, u32 dst_size, const void *src,
return _se_execute(op, dst, dst_size, src, src_size, true); return _se_execute(op, dst, dst_size, src, src_size, true);
} }
static int _se_execute_aes_oneshot(void *dst, const void *src, u32 size) static int _se_execute_one_block(u32 op, void *dst, u32 dst_size, const void *src, u32 src_size)
{ {
// Set optional memory interface. if (!src || !dst)
if (dst >= (void *)DRAM_START && src >= (void *)DRAM_START) return 0;
SE(SE_CRYPTO_CONFIG_REG) |= SE_CRYPTO_MEMIF(MEMIF_MCCIF);
u32 size_aligned = ALIGN_DOWN(size, SE_AES_BLOCK_SIZE); u32 block[SE_AES_BLOCK_SIZE / sizeof(u32)] = {0};
u32 size_residue = size % SE_AES_BLOCK_SIZE;
int res = 1;
// Handle initial aligned message. SE(SE_CRYPTO_LAST_BLOCK_REG) = 1 - 1;
if (size_aligned)
{
SE(SE_CRYPTO_LAST_BLOCK_REG) = (size >> 4) - 1;
res = _se_execute_oneshot(SE_OP_START, dst, size_aligned, src, size_aligned); memcpy(block, src, src_size);
} int res = _se_execute_oneshot(op, block, SE_AES_BLOCK_SIZE, block, SE_AES_BLOCK_SIZE);
memcpy(dst, block, dst_size);
// Handle leftover partial message.
if (res && size_residue)
{
// Copy message to a block sized buffer in case it's partial.
u32 block[SE_AES_BLOCK_SIZE / sizeof(u32)] = {0};
memcpy(block, src + size_aligned, size_residue);
// Use updated IV for CBC and OFB. Ignored on others.
SE(SE_CRYPTO_CONFIG_REG) |= SE_CRYPTO_IV_SEL(IV_UPDATED);
SE(SE_CRYPTO_LAST_BLOCK_REG) = (SE_AES_BLOCK_SIZE >> 4) - 1;
res = _se_execute_oneshot(SE_OP_START, block, SE_AES_BLOCK_SIZE, block, SE_AES_BLOCK_SIZE);
// Copy result back.
memcpy(dst + size_aligned, block, size_residue);
}
return res; return res;
} }
@@ -262,14 +231,13 @@ void se_aes_key_set(u32 ks, const void *key, u32 size)
} }
} }
void se_aes_iv_set(u32 ks, const void *iv, u32 size) void se_aes_iv_set(u32 ks, const void *iv)
{ {
u32 data[SE_AES_MAX_KEY_SIZE / sizeof(u32)]; u32 data[SE_AES_IV_SIZE / sizeof(u32)];
memcpy(data, iv, size); memcpy(data, iv, SE_AES_IV_SIZE);
for (u32 i = 0; i < (size / sizeof(u32)); i++) for (u32 i = 0; i < (SE_AES_IV_SIZE / sizeof(u32)); i++)
{ {
// QUAD UPDATED_IV bit is automatically set by PKT macro.
SE(SE_CRYPTO_KEYTABLE_ADDR_REG) = SE_KEYTABLE_SLOT(ks) | SE_KEYTABLE_QUAD(ORIGINAL_IV) | SE_KEYTABLE_PKT(i); SE(SE_CRYPTO_KEYTABLE_ADDR_REG) = SE_KEYTABLE_SLOT(ks) | SE_KEYTABLE_QUAD(ORIGINAL_IV) | SE_KEYTABLE_PKT(i);
SE(SE_CRYPTO_KEYTABLE_DATA_REG) = data[i]; SE(SE_CRYPTO_KEYTABLE_DATA_REG) = data[i];
} }
@@ -301,14 +269,22 @@ void se_aes_key_clear(u32 ks)
void se_aes_iv_clear(u32 ks) void se_aes_iv_clear(u32 ks)
{ {
for (u32 i = 0; i < (SE_AES_MAX_KEY_SIZE / sizeof(u32)); i++) for (u32 i = 0; i < (SE_AES_IV_SIZE / sizeof(u32)); i++)
{ {
// QUAD UPDATED_IV bit is automatically set by PKT macro.
SE(SE_CRYPTO_KEYTABLE_ADDR_REG) = SE_KEYTABLE_SLOT(ks) | SE_KEYTABLE_QUAD(ORIGINAL_IV) | SE_KEYTABLE_PKT(i); SE(SE_CRYPTO_KEYTABLE_ADDR_REG) = SE_KEYTABLE_SLOT(ks) | SE_KEYTABLE_QUAD(ORIGINAL_IV) | SE_KEYTABLE_PKT(i);
SE(SE_CRYPTO_KEYTABLE_DATA_REG) = 0; SE(SE_CRYPTO_KEYTABLE_DATA_REG) = 0;
} }
} }
void se_aes_iv_updated_clear(u32 ks)
{
for (u32 i = 0; i < (SE_AES_IV_SIZE / 4); i++)
{
SE(SE_CRYPTO_KEYTABLE_ADDR_REG) = SE_KEYTABLE_SLOT(ks) | SE_KEYTABLE_QUAD(UPDATED_IV) | SE_KEYTABLE_PKT(i);
SE(SE_CRYPTO_KEYTABLE_DATA_REG) = 0;
}
}
int se_aes_unwrap_key(u32 ks_dst, u32 ks_src, const void *seed) int se_aes_unwrap_key(u32 ks_dst, u32 ks_src, const void *seed)
{ {
SE(SE_CONFIG_REG) = SE_CONFIG_DEC_MODE(MODE_KEY128) | SE_CONFIG_DEC_ALG(ALG_AES_DEC) | SE_CONFIG_DST(DST_KEYTABLE); SE(SE_CONFIG_REG) = SE_CONFIG_DEC_MODE(MODE_KEY128) | SE_CONFIG_DEC_ALG(ALG_AES_DEC) | SE_CONFIG_DST(DST_KEYTABLE);
@@ -319,7 +295,27 @@ int se_aes_unwrap_key(u32 ks_dst, u32 ks_src, const void *seed)
return _se_execute_oneshot(SE_OP_START, NULL, 0, seed, SE_KEY_128_SIZE); return _se_execute_oneshot(SE_OP_START, NULL, 0, seed, SE_KEY_128_SIZE);
} }
int se_aes_crypt_ecb(u32 ks, int enc, void *dst, const void *src, u32 size) int se_aes_crypt_hash(u32 ks, int enc, void *dst, u32 dst_size, const void *src, u32 src_size)
{
if (enc)
{
SE(SE_CONFIG_REG) = SE_CONFIG_ENC_ALG(ALG_AES_ENC) | SE_CONFIG_DST(DST_MEMORY);
SE(SE_CRYPTO_CONFIG_REG) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_VCTRAM_SEL(VCTRAM_AESOUT) |
SE_CRYPTO_CORE_SEL(CORE_ENCRYPT) | SE_CRYPTO_XOR_POS(XOR_TOP) |
SE_CRYPTO_HASH(HASH_ENABLE);
}
else
{
SE(SE_CONFIG_REG) = SE_CONFIG_DEC_ALG(ALG_AES_DEC) | SE_CONFIG_DST(DST_MEMORY);
SE(SE_CRYPTO_CONFIG_REG) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_VCTRAM_SEL(VCTRAM_PREVMEM) |
SE_CRYPTO_CORE_SEL(CORE_DECRYPT) | SE_CRYPTO_XOR_POS(XOR_BOTTOM) |
SE_CRYPTO_HASH(HASH_ENABLE);
}
SE(SE_CRYPTO_LAST_BLOCK_REG) = (src_size >> 4) - 1;
return _se_execute_oneshot(SE_OP_START, dst, dst_size, src, src_size);
}
int se_aes_crypt_ecb(u32 ks, int enc, void *dst, u32 dst_size, const void *src, u32 src_size)
{ {
if (enc) if (enc)
{ {
@@ -333,11 +329,11 @@ int se_aes_crypt_ecb(u32 ks, int enc, void *dst, const void *src, u32 size)
SE(SE_CRYPTO_CONFIG_REG) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_CORE_SEL(CORE_DECRYPT) | SE(SE_CRYPTO_CONFIG_REG) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_CORE_SEL(CORE_DECRYPT) |
SE_CRYPTO_XOR_POS(XOR_BYPASS); SE_CRYPTO_XOR_POS(XOR_BYPASS);
} }
SE(SE_CRYPTO_LAST_BLOCK_REG) = (src_size >> 4) - 1;
return _se_execute_aes_oneshot(dst, src, size); return _se_execute_oneshot(SE_OP_START, dst, dst_size, src, src_size);
} }
int se_aes_crypt_cbc(u32 ks, int enc, void *dst, const void *src, u32 size) int se_aes_crypt_cbc(u32 ks, int enc, void *dst, u32 dst_size, const void *src, u32 src_size)
{ {
if (enc) if (enc)
{ {
@@ -351,21 +347,16 @@ int se_aes_crypt_cbc(u32 ks, int enc, void *dst, const void *src, u32 size)
SE(SE_CRYPTO_CONFIG_REG) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_VCTRAM_SEL(VCTRAM_PREVMEM) | SE(SE_CRYPTO_CONFIG_REG) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_VCTRAM_SEL(VCTRAM_PREVMEM) |
SE_CRYPTO_CORE_SEL(CORE_DECRYPT) | SE_CRYPTO_XOR_POS(XOR_BOTTOM); SE_CRYPTO_CORE_SEL(CORE_DECRYPT) | SE_CRYPTO_XOR_POS(XOR_BOTTOM);
} }
SE(SE_CRYPTO_LAST_BLOCK_REG) = (src_size >> 4) - 1;
return _se_execute_aes_oneshot(dst, src, size); return _se_execute_oneshot(SE_OP_START, dst, dst_size, src, src_size);
} }
int se_aes_crypt_ofb(u32 ks, void *dst, const void *src, u32 size) int se_aes_crypt_block_ecb(u32 ks, int enc, void *dst, const void *src)
{ {
SE(SE_SPARE_REG) = SE_INPUT_NONCE_LE; return se_aes_crypt_ecb(ks, enc, dst, SE_AES_BLOCK_SIZE, src, SE_AES_BLOCK_SIZE);
SE(SE_CONFIG_REG) = SE_CONFIG_ENC_MODE(MODE_KEY128) | SE_CONFIG_ENC_ALG(ALG_AES_ENC) | SE_CONFIG_DST(DST_MEMORY);
SE(SE_CRYPTO_CONFIG_REG) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_INPUT_SEL(INPUT_AESOUT) |
SE_CRYPTO_CORE_SEL(CORE_ENCRYPT) | SE_CRYPTO_XOR_POS(XOR_BOTTOM);
return _se_execute_aes_oneshot(dst, src, size);
} }
int se_aes_crypt_ctr(u32 ks, void *dst, const void *src, u32 size, void *ctr) int se_aes_crypt_ctr(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_size, void *ctr)
{ {
SE(SE_SPARE_REG) = SE_INPUT_NONCE_LE; SE(SE_SPARE_REG) = SE_INPUT_NONCE_LE;
SE(SE_CONFIG_REG) = SE_CONFIG_ENC_MODE(MODE_KEY128) | SE_CONFIG_ENC_ALG(ALG_AES_ENC) | SE_CONFIG_DST(DST_MEMORY); SE(SE_CONFIG_REG) = SE_CONFIG_ENC_MODE(MODE_KEY128) | SE_CONFIG_ENC_ALG(ALG_AES_ENC) | SE_CONFIG_DST(DST_MEMORY);
@@ -375,10 +366,25 @@ int se_aes_crypt_ctr(u32 ks, void *dst, const void *src, u32 size, void *ctr)
_se_aes_counter_set(ctr); _se_aes_counter_set(ctr);
return _se_execute_aes_oneshot(dst, src, size); u32 src_size_aligned = src_size & 0xFFFFFFF0;
u32 src_size_delta = src_size & 0xF;
if (src_size_aligned)
{
SE(SE_CRYPTO_LAST_BLOCK_REG) = (src_size >> 4) - 1;
if (!_se_execute_oneshot(SE_OP_START, dst, dst_size, src, src_size_aligned))
return 0;
}
if (src_size - src_size_aligned && src_size_aligned < dst_size)
return _se_execute_one_block(SE_OP_START, dst + src_size_aligned,
MIN(src_size_delta, dst_size - src_size_aligned),
src + src_size_aligned, src_size_delta);
return 1;
} }
int se_aes_crypt_xts_sec(u32 tweak_ks, u32 crypt_ks, int enc, u64 sec, void *dst, void *src, u32 secsize) int se_aes_xts_crypt_sec(u32 tweak_ks, u32 crypt_ks, int enc, u64 sec, void *dst, void *src, u32 secsize)
{ {
int res = 0; int res = 0;
u32 tmp[SE_AES_BLOCK_SIZE / sizeof(u32)]; u32 tmp[SE_AES_BLOCK_SIZE / sizeof(u32)];
@@ -392,7 +398,7 @@ int se_aes_crypt_xts_sec(u32 tweak_ks, u32 crypt_ks, int enc, u64 sec, void *dst
tweak[i] = sec & 0xFF; tweak[i] = sec & 0xFF;
sec >>= 8; sec >>= 8;
} }
if (!se_aes_crypt_ecb(tweak_ks, ENCRYPT, tweak, tweak, SE_AES_BLOCK_SIZE)) if (!se_aes_crypt_block_ecb(tweak_ks, ENCRYPT, tweak, tweak))
goto out; goto out;
// We are assuming a 0x10-aligned sector size in this implementation. // We are assuming a 0x10-aligned sector size in this implementation.
@@ -400,7 +406,7 @@ int se_aes_crypt_xts_sec(u32 tweak_ks, u32 crypt_ks, int enc, u64 sec, void *dst
{ {
for (u32 j = 0; j < SE_AES_BLOCK_SIZE; j++) for (u32 j = 0; j < SE_AES_BLOCK_SIZE; j++)
pdst[j] = psrc[j] ^ tweak[j]; pdst[j] = psrc[j] ^ tweak[j];
if (!se_aes_crypt_ecb(crypt_ks, enc, pdst, pdst, SE_AES_BLOCK_SIZE)) if (!se_aes_crypt_block_ecb(crypt_ks, enc, pdst, pdst))
goto out; goto out;
for (u32 j = 0; j < SE_AES_BLOCK_SIZE; j++) for (u32 j = 0; j < SE_AES_BLOCK_SIZE; j++)
pdst[j] = pdst[j] ^ tweak[j]; pdst[j] = pdst[j] ^ tweak[j];
@@ -415,7 +421,7 @@ out:
return res; return res;
} }
int se_aes_crypt_xts_sec_nx(u32 tweak_ks, u32 crypt_ks, int enc, u64 sec, u8 *tweak, bool regen_tweak, u32 tweak_exp, void *dst, void *src, u32 sec_size) int se_aes_xts_crypt_sec_nx(u32 tweak_ks, u32 crypt_ks, int enc, u64 sec, u8 *tweak, bool regen_tweak, u32 tweak_exp, void *dst, void *src, u32 sec_size)
{ {
u32 *pdst = (u32 *)dst; u32 *pdst = (u32 *)dst;
u32 *psrc = (u32 *)src; u32 *psrc = (u32 *)src;
@@ -428,7 +434,7 @@ int se_aes_crypt_xts_sec_nx(u32 tweak_ks, u32 crypt_ks, int enc, u64 sec, u8 *tw
tweak[i] = sec & 0xFF; tweak[i] = sec & 0xFF;
sec >>= 8; sec >>= 8;
} }
if (!se_aes_crypt_ecb(tweak_ks, ENCRYPT, tweak, tweak, SE_AES_BLOCK_SIZE)) if (!se_aes_crypt_block_ecb(tweak_ks, ENCRYPT, tweak, tweak))
return 0; return 0;
} }
@@ -450,7 +456,7 @@ int se_aes_crypt_xts_sec_nx(u32 tweak_ks, u32 crypt_ks, int enc, u64 sec, u8 *tw
pdst += sizeof(u32); pdst += sizeof(u32);
} }
if (!se_aes_crypt_ecb(crypt_ks, enc, dst, dst, sec_size)) if (!se_aes_crypt_ecb(crypt_ks, enc, dst, sec_size, dst, sec_size))
return 0; return 0;
pdst = (u32 *)dst; pdst = (u32 *)dst;
@@ -467,20 +473,27 @@ int se_aes_crypt_xts_sec_nx(u32 tweak_ks, u32 crypt_ks, int enc, u64 sec, u8 *tw
return 1; return 1;
} }
int se_aes_crypt_xts(u32 tweak_ks, u32 crypt_ks, int enc, u64 sec, void *dst, void *src, u32 secsize, u32 num_secs) int se_aes_xts_crypt(u32 tweak_ks, u32 crypt_ks, int enc, u64 sec, void *dst, void *src, u32 secsize, u32 num_secs)
{ {
u8 *pdst = (u8 *)dst; u8 *pdst = (u8 *)dst;
u8 *psrc = (u8 *)src; u8 *psrc = (u8 *)src;
for (u32 i = 0; i < num_secs; i++) for (u32 i = 0; i < num_secs; i++)
if (!se_aes_crypt_xts_sec(tweak_ks, crypt_ks, enc, sec + i, pdst + secsize * i, psrc + secsize * i, secsize)) if (!se_aes_xts_crypt_sec(tweak_ks, crypt_ks, enc, sec + i, pdst + secsize * i, psrc + secsize * i, secsize))
return 0; return 0;
return 1; return 1;
} }
static void _se_sha_hash_256_get_hash(void *hash) static void se_calc_sha256_get_hash(void *hash, u32 *msg_left)
{ {
// Backup message left.
if (msg_left)
{
msg_left[0] = SE(SE_SHA_MSG_LEFT_0_REG);
msg_left[1] = SE(SE_SHA_MSG_LEFT_1_REG);
}
// Copy output hash. // Copy output hash.
u32 hash32[SE_SHA_256_SIZE / sizeof(u32)]; u32 hash32[SE_SHA_256_SIZE / sizeof(u32)];
for (u32 i = 0; i < (SE_SHA_256_SIZE / sizeof(u32)); i++) for (u32 i = 0; i < (SE_SHA_256_SIZE / sizeof(u32)); i++)
@@ -488,8 +501,15 @@ static void _se_sha_hash_256_get_hash(void *hash)
memcpy(hash, hash32, SE_SHA_256_SIZE); memcpy(hash, hash32, SE_SHA_256_SIZE);
} }
static int _se_sha_hash_256(void *hash, u64 total_size, const void *src, u32 src_size, bool is_oneshot) int se_calc_sha256(void *hash, u32 *msg_left, const void *src, u32 src_size, u64 total_size, u32 sha_cfg, bool is_oneshot)
{ {
int res;
u32 hash32[SE_SHA_256_SIZE / 4];
//! TODO: src_size must be 512 bit aligned if continuing and not last block for SHA256.
if (src_size > 0xFFFFFF || !hash) // Max 16MB - 1 chunks and aligned x4 hash buffer.
return 0;
// Src size of 0 is not supported, so return null string sha256. // Src size of 0 is not supported, so return null string sha256.
if (!src_size) if (!src_size)
{ {
@@ -501,123 +521,79 @@ static int _se_sha_hash_256(void *hash, u64 total_size, const void *src, u32 src
return 1; return 1;
} }
// Increase leftover size if not last message. (Engine will always stop at src_size.)
u32 msg_left = src_size;
if (total_size < src_size)
msg_left++;
// Setup config for SHA256. // Setup config for SHA256.
SE(SE_CONFIG_REG) = SE_CONFIG_ENC_MODE(MODE_SHA256) | SE_CONFIG_ENC_ALG(ALG_SHA) | SE_CONFIG_DST(DST_HASHREG); SE(SE_CONFIG_REG) = SE_CONFIG_ENC_MODE(MODE_SHA256) | SE_CONFIG_ENC_ALG(ALG_SHA) | SE_CONFIG_DST(DST_HASHREG);
SE(SE_SHA_CONFIG_REG) = sha_cfg;
SE(SE_CRYPTO_LAST_BLOCK_REG) = 1 - 1;
// Set total size: BITS(total_size), up to 2 EB. // Set total size to current buffer size if empty.
if (!total_size)
total_size = src_size;
// Set total size: BITS(src_size), up to 2 EB.
SE(SE_SHA_MSG_LENGTH_0_REG) = (u32)(total_size << 3); SE(SE_SHA_MSG_LENGTH_0_REG) = (u32)(total_size << 3);
SE(SE_SHA_MSG_LENGTH_1_REG) = (u32)(total_size >> 29); SE(SE_SHA_MSG_LENGTH_1_REG) = (u32)(total_size >> 29);
SE(SE_SHA_MSG_LENGTH_2_REG) = 0; SE(SE_SHA_MSG_LENGTH_2_REG) = 0;
SE(SE_SHA_MSG_LENGTH_3_REG) = 0; SE(SE_SHA_MSG_LENGTH_3_REG) = 0;
// Set leftover size: BITS(src_size). // Set size left to hash.
SE(SE_SHA_MSG_LEFT_0_REG) = (u32)(msg_left << 3); SE(SE_SHA_MSG_LEFT_0_REG) = (u32)(total_size << 3);
SE(SE_SHA_MSG_LEFT_1_REG) = (u32)(msg_left >> 29); SE(SE_SHA_MSG_LEFT_1_REG) = (u32)(total_size >> 29);
SE(SE_SHA_MSG_LEFT_2_REG) = 0; SE(SE_SHA_MSG_LEFT_2_REG) = 0;
SE(SE_SHA_MSG_LEFT_3_REG) = 0; SE(SE_SHA_MSG_LEFT_3_REG) = 0;
// Set config based on init or partial continuation. // If we hash in chunks, copy over the intermediate.
if (total_size == src_size || !total_size) if (sha_cfg == SHA_CONTINUE && msg_left)
SE(SE_SHA_CONFIG_REG) = SHA_INIT_HASH; {
else // Restore message left to process.
SE(SE_SHA_CONFIG_REG) = SHA_CONTINUE; SE(SE_SHA_MSG_LEFT_0_REG) = msg_left[0];
SE(SE_SHA_MSG_LEFT_1_REG) = msg_left[1];
// Trigger the operation. src vs total size decides if it's partial. // Restore hash reg.
int res = _se_execute(SE_OP_START, NULL, 0, src, src_size, is_oneshot); memcpy(hash32, hash, SE_SHA_256_SIZE);
for (u32 i = 0; i < (SE_SHA_256_SIZE / 4); i++)
SE(SE_HASH_RESULT_REG + (i * 4)) = byte_swap_32(hash32[i]);
}
if (res && is_oneshot) // Trigger the operation.
_se_sha_hash_256_get_hash(hash); res = _se_execute(SE_OP_START, NULL, 0, src, src_size, is_oneshot);
if (is_oneshot)
se_calc_sha256_get_hash(hash, msg_left);
return res; return res;
} }
int se_sha_hash_256_async(void *hash, const void *src, u32 size) int se_calc_sha256_oneshot(void *hash, const void *src, u32 src_size)
{ {
return _se_sha_hash_256(hash, size, src, size, false); return se_calc_sha256(hash, NULL, src, src_size, 0, SHA_INIT_HASH, true);
} }
int se_sha_hash_256_oneshot(void *hash, const void *src, u32 size) int se_calc_sha256_finalize(void *hash, u32 *msg_left)
{
return _se_sha_hash_256(hash, size, src, size, true);
}
int se_sha_hash_256_partial_start(void *hash, const void *src, u32 size, bool is_oneshot)
{
// Check if aligned SHA256 block size.
if (size % SE_SHA2_MIN_BLOCK_SIZE)
return 0;
return _se_sha_hash_256(hash, 0, src, size, is_oneshot);
}
int se_sha_hash_256_partial_update(void *hash, const void *src, u32 size, bool is_oneshot)
{
// Check if aligned to SHA256 block size.
if (size % SE_SHA2_MIN_BLOCK_SIZE)
return 0;
return _se_sha_hash_256(hash, size - 1, src, size, is_oneshot);
}
int se_sha_hash_256_partial_end(void *hash, u64 total_size, const void *src, u32 src_size, bool is_oneshot)
{
return _se_sha_hash_256(hash, total_size, src, src_size, is_oneshot);
}
int se_sha_hash_256_finalize(void *hash)
{ {
int res = _se_execute_finalize(); int res = _se_execute_finalize();
_se_sha_hash_256_get_hash(hash); se_calc_sha256_get_hash(hash, msg_left);
return res; return res;
} }
int se_rng_pseudo(void *dst, u32 size) int se_gen_prng128(void *dst)
{ {
// Setup config for SP 800-90 PRNG. // Setup config for SP 800-90 PRNG.
SE(SE_CONFIG_REG) = SE_CONFIG_ENC_MODE(MODE_KEY128) | SE_CONFIG_ENC_ALG(ALG_RNG) | SE_CONFIG_DST(DST_MEMORY); SE(SE_CONFIG_REG) = SE_CONFIG_ENC_MODE(MODE_KEY128) | SE_CONFIG_ENC_ALG(ALG_RNG) | SE_CONFIG_DST(DST_MEMORY);
SE(SE_CRYPTO_CONFIG_REG) = SE_CRYPTO_XOR_POS(XOR_BYPASS) | SE_CRYPTO_INPUT_SEL(INPUT_RANDOM); SE(SE_CRYPTO_CONFIG_REG) = SE_CRYPTO_XOR_POS(XOR_BYPASS) | SE_CRYPTO_INPUT_SEL(INPUT_RANDOM);
SE(SE_RNG_CONFIG_REG) = SE_RNG_CONFIG_SRC(SRC_ENTROPY) | SE_RNG_CONFIG_MODE(MODE_NORMAL); SE(SE_RNG_CONFIG_REG) = SE_RNG_CONFIG_SRC(SRC_ENTROPY) | SE_RNG_CONFIG_MODE(MODE_NORMAL);
SE(SE_RNG_SRC_CONFIG_REG) |= SE_RNG_SRC_CONFIG_ENTR_SRC(RO_ENTR_ENABLE); // DRBG. Depends on ENTROPY clock. //SE(SE_RNG_SRC_CONFIG_REG) |= SE_RNG_SRC_CONFIG_ENTR_SRC(RO_ENTR_ENABLE); // DRBG. Depends on ENTROPY clock.
SE(SE_RNG_RESEED_INTERVAL_REG) = 4096; SE(SE_RNG_RESEED_INTERVAL_REG) = 1;
u32 size_aligned = ALIGN_DOWN(size, SE_RNG_BLOCK_SIZE); SE(SE_CRYPTO_LAST_BLOCK_REG) = (16 >> 4) - 1;
u32 size_residue = size % SE_RNG_BLOCK_SIZE;
int res = 0;
// Handle initial aligned message. // Trigger the operation.
if (size_aligned) return _se_execute_oneshot(SE_OP_START, dst, 16, NULL, 0);
{
SE(SE_CRYPTO_LAST_BLOCK_REG) = (size >> 4) - 1;
res = _se_execute_oneshot(SE_OP_START, dst, size_aligned, NULL, 0);
}
// Handle leftover partial message.
if (res && size_residue)
{
// Copy message to a block sized buffer in case it's partial.
u32 block[SE_RNG_BLOCK_SIZE / sizeof(u32)] = {0};
SE(SE_CRYPTO_LAST_BLOCK_REG) = (SE_AES_BLOCK_SIZE >> 4) - 1;
res = _se_execute_oneshot(SE_OP_START, block, SE_RNG_BLOCK_SIZE, NULL, 0);
// Copy result back.
if (res)
memcpy(dst + size_aligned, block, size_residue);
}
return res;
} }
void se_aes_ctx_get_keys(u8 *buf, u8 *keys, u32 keysize) void se_get_aes_keys(u8 *buf, u8 *keys, u32 keysize)
{ {
u8 *aligned_buf = (u8 *)ALIGN((u32)buf, 0x40); u8 *aligned_buf = (u8 *)ALIGN((u32)buf, 0x40);
@@ -668,13 +644,16 @@ void se_aes_ctx_get_keys(u8 *buf, u8 *keys, u32 keysize)
srk[3] = PMC(APBDEV_PMC_SECURE_SCRATCH7); srk[3] = PMC(APBDEV_PMC_SECURE_SCRATCH7);
// Decrypt context. // Decrypt context.
se_aes_key_clear(3);
se_aes_key_set(3, srk, SE_KEY_128_SIZE); se_aes_key_set(3, srk, SE_KEY_128_SIZE);
se_aes_crypt_cbc(3, DECRYPT, keys, keys, SE_AES_KEYSLOT_COUNT * keysize); se_aes_crypt_cbc(3, DECRYPT, keys, SE_AES_KEYSLOT_COUNT * keysize, keys, SE_AES_KEYSLOT_COUNT * keysize);
se_aes_key_clear(3); se_aes_key_clear(3);
} }
int se_aes_hash_cmac(u32 ks, void *hash, const void *src, u32 size) int se_aes_cmac_128(u32 ks, void *hash, const void *src, u32 size)
{ {
int res = 0;
u32 tmp1[SE_KEY_128_SIZE / sizeof(u32)] = {0}; u32 tmp1[SE_KEY_128_SIZE / sizeof(u32)] = {0};
u32 tmp2[SE_AES_BLOCK_SIZE / sizeof(u32)] = {0}; u32 tmp2[SE_AES_BLOCK_SIZE / sizeof(u32)] = {0};
u8 *subkey = (u8 *)tmp1; u8 *subkey = (u8 *)tmp1;
@@ -682,54 +661,52 @@ int se_aes_hash_cmac(u32 ks, void *hash, const void *src, u32 size)
// Generate sub key (CBC with zeroed IV, basically ECB). // Generate sub key (CBC with zeroed IV, basically ECB).
se_aes_iv_clear(ks); se_aes_iv_clear(ks);
if (!se_aes_crypt_cbc(ks, ENCRYPT, subkey, subkey, SE_KEY_128_SIZE)) se_aes_iv_updated_clear(ks);
return 0; if (!se_aes_crypt_hash(ks, ENCRYPT, subkey, SE_KEY_128_SIZE, subkey, SE_KEY_128_SIZE))
goto out;
// Generate K1 subkey. // Generate K1 subkey.
_se_ls_1bit(subkey); _se_ls_1bit(subkey);
if (size & 0xF) if (size & 0xF)
_se_ls_1bit(subkey); // Convert to K2. _se_ls_1bit(subkey); // Convert to K2.
// Switch to hash register. The rest of the config is already set. SE(SE_CONFIG_REG) = SE_CONFIG_ENC_MODE(MODE_KEY128) | SE_CONFIG_ENC_ALG(ALG_AES_ENC) | SE_CONFIG_DST(DST_HASHREG);
SE(SE_CONFIG_REG) |= SE_CONFIG_DST(DST_HASHREG); SE(SE_CRYPTO_CONFIG_REG) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_INPUT_SEL(INPUT_MEMORY) |
SE(SE_CRYPTO_CONFIG_REG) |= SE_CRYPTO_HASH(HASH_ENABLE); SE_CRYPTO_XOR_POS(XOR_TOP) | SE_CRYPTO_VCTRAM_SEL(VCTRAM_AESOUT) | SE_CRYPTO_HASH(HASH_ENABLE) |
SE_CRYPTO_CORE_SEL(CORE_ENCRYPT);
se_aes_iv_clear(ks);
se_aes_iv_updated_clear(ks);
// Initial blocks.
u32 num_blocks = (size + 0xF) >> 4; u32 num_blocks = (size + 0xF) >> 4;
if (num_blocks > 1) if (num_blocks > 1)
{ {
SE(SE_CRYPTO_LAST_BLOCK_REG) = num_blocks - 2; SE(SE_CRYPTO_LAST_BLOCK_REG) = num_blocks - 2;
if (!_se_execute_oneshot(SE_OP_START, NULL, 0, src, size)) if (!_se_execute_oneshot(SE_OP_START, NULL, 0, src, size))
return 0; goto out;
// Use updated IV for next OP as a continuation.
SE(SE_CRYPTO_CONFIG_REG) |= SE_CRYPTO_IV_SEL(IV_UPDATED); SE(SE_CRYPTO_CONFIG_REG) |= SE_CRYPTO_IV_SEL(IV_UPDATED);
} }
// Last block.
if (size & 0xF) if (size & 0xF)
{ {
memcpy(last_block, src + (size & (~0xF)), size & 0xF); memcpy(last_block, src + (size & ~0xF), size & 0xF);
last_block[size & 0xF] = 0x80; last_block[size & 0xF] = 0x80;
} }
else if (size >= SE_AES_BLOCK_SIZE) else if (size >= SE_AES_BLOCK_SIZE)
{
memcpy(last_block, src + size - SE_AES_BLOCK_SIZE, SE_AES_BLOCK_SIZE); memcpy(last_block, src + size - SE_AES_BLOCK_SIZE, SE_AES_BLOCK_SIZE);
}
for (u32 i = 0; i < SE_KEY_128_SIZE; i++) for (u32 i = 0; i < SE_KEY_128_SIZE; i++)
last_block[i] ^= subkey[i]; last_block[i] ^= subkey[i];
SE(SE_CRYPTO_LAST_BLOCK_REG) = (SE_AES_BLOCK_SIZE >> 4) - 1; SE(SE_CRYPTO_LAST_BLOCK_REG) = 0;
int res = _se_execute_oneshot(SE_OP_START, NULL, 0, last_block, SE_AES_BLOCK_SIZE); res = _se_execute_oneshot(SE_OP_START, NULL, 0, last_block, SE_AES_BLOCK_SIZE);
// Copy output hash. u32 *hash32 = (u32 *)hash;
if (res) for (u32 i = 0; i < (SE_AES_CMAC_DIGEST_SIZE / sizeof(u32)); i++)
{ hash32[i] = SE(SE_HASH_RESULT_REG + sizeof(u32) * i);
u32 *hash32 = (u32 *)hash;
for (u32 i = 0; i < (SE_AES_CMAC_DIGEST_SIZE / sizeof(u32)); i++)
hash32[i] = SE(SE_HASH_RESULT_REG + sizeof(u32) * i);
}
out:
return res; return res;
} }

View File

@@ -27,29 +27,28 @@ u32 se_key_acc_ctrl_get(u32 ks);
/*! AES Key Management Functions */ /*! AES Key Management Functions */
void se_aes_key_set(u32 ks, const void *key, u32 size); void se_aes_key_set(u32 ks, const void *key, u32 size);
void se_aes_iv_set(u32 ks, const void *iv, u32 size); void se_aes_iv_set(u32 ks, const void *iv);
void se_aes_key_get(u32 ks, void *key, u32 size); void se_aes_key_get(u32 ks, void *key, u32 size);
void se_aes_key_clear(u32 ks); void se_aes_key_clear(u32 ks);
void se_aes_iv_clear(u32 ks); void se_aes_iv_clear(u32 ks);
void se_aes_iv_updated_clear(u32 ks);
int se_aes_unwrap_key(u32 ks_dst, u32 ks_src, const void *seed); int se_aes_unwrap_key(u32 ks_dst, u32 ks_src, const void *seed);
void se_aes_ctx_get_keys(u8 *buf, u8 *keys, u32 keysize); void se_get_aes_keys(u8 *buf, u8 *keys, u32 keysize);
/*! Encryption Functions */ /*! Encryption Functions */
int se_aes_crypt_ecb(u32 ks, int enc, void *dst, const void *src, u32 size); int se_aes_crypt_cbc(u32 ks, int enc, void *dst, u32 dst_size, const void *src, u32 src_size);
int se_aes_crypt_cbc(u32 ks, int enc, void *dst, const void *src, u32 size); int se_aes_crypt_ecb(u32 ks, int enc, void *dst, u32 dst_size, const void *src, u32 src_size);
int se_aes_crypt_ofb(u32 ks, void *dst, const void *src, u32 size); int se_aes_crypt_block_ecb(u32 ks, int enc, void *dst, const void *src);
int se_aes_crypt_ctr(u32 ks, void *dst, const void *src, u32 size, void *ctr); int se_aes_xts_crypt_sec(u32 tweak_ks, u32 crypt_ks, int enc, u64 sec, void *dst, void *src, u32 secsize);
int se_aes_crypt_xts_sec(u32 tweak_ks, u32 crypt_ks, int enc, u64 sec, void *dst, void *src, u32 secsize); int se_aes_xts_crypt_sec_nx(u32 tweak_ks, u32 crypt_ks, int enc, u64 sec, u8 *tweak, bool regen_tweak, u32 tweak_exp, void *dst, void *src, u32 sec_size);
int se_aes_crypt_xts_sec_nx(u32 tweak_ks, u32 crypt_ks, int enc, u64 sec, u8 *tweak, bool regen_tweak, u32 tweak_exp, void *dst, void *src, u32 sec_size); int se_aes_xts_crypt(u32 tweak_ks, u32 crypt_ks, int enc, u64 sec, void *dst, void *src, u32 secsize, u32 num_secs);
int se_aes_crypt_xts(u32 tweak_ks, u32 crypt_ks, int enc, u64 sec, void *dst, void *src, u32 secsize, u32 num_secs);
/*! Hashing Functions */ /*! Hashing Functions */
int se_sha_hash_256_async(void *hash, const void *src, u32 size); int se_aes_crypt_hash(u32 ks, int enc, void *dst, u32 dst_size, const void *src, u32 src_size);
int se_sha_hash_256_oneshot(void *hash, const void *src, u32 size); int se_aes_crypt_ctr(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_size, void *ctr);
int se_sha_hash_256_partial_start(void *hash, const void *src, u32 size, bool is_oneshot); int se_calc_sha256(void *hash, u32 *msg_left, const void *src, u32 src_size, u64 total_size, u32 sha_cfg, bool is_oneshot);
int se_sha_hash_256_partial_update(void *hash, const void *src, u32 size, bool is_oneshot); int se_calc_sha256_oneshot(void *hash, const void *src, u32 src_size);
int se_sha_hash_256_partial_end(void *hash, u64 total_size, const void *src, u32 src_size, bool is_oneshot); int se_calc_sha256_finalize(void *hash, u32 *msg_left);
int se_sha_hash_256_finalize(void *hash); int se_aes_cmac_128(u32 ks, void *hash, const void *src, u32 size);
int se_aes_hash_cmac(u32 ks, void *hash, const void *src, u32 size);
/*! Random Functions */ /*! Random Functions */
int se_rng_pseudo(void *dst, u32 size); int se_gen_prng128(void *dst);
#endif #endif

275
bdk/storage/boot_storage.c Normal file
View File

@@ -0,0 +1,275 @@
#include "boot_storage.h"
#include <libs/fatfs/ff.h>
#include <fatfs_cfg.h>
#include <storage/sd.h>
#include <storage/emmc.h>
#include <utils/types.h>
#include <gfx_utils.h>
#include <stdlib.h>
#define DEV_INVALID 0xff
static FATFS boot_storage_fs;
static BYTE drive_cur = -1;
static BYTE drive = -1;
static const char* drive_base_paths[] = {
[DRIVE_SD] = "sd:",
[DRIVE_BOOT1] = "boot1_:",
[DRIVE_BOOT1_1MB] = "boot1_1mb:",
[DRIVE_EMMC] = "emmc:",
};
static bool _is_eligible(){
if(f_stat(".no_boot_storage", NULL) == FR_OK){
return false;
}
return true;
}
bool boot_storage_get_mounted(){
switch(drive_cur){
case DRIVE_SD:
return sd_get_card_mounted();
case DRIVE_EMMC:
return emmc_get_mounted();
case DRIVE_BOOT1:
case DRIVE_BOOT1_1MB:
return drive_cur != DEV_INVALID;
}
return false;
}
bool boot_storage_get_initialized(){
switch(drive_cur){
case DRIVE_BOOT1:
case DRIVE_EMMC:
case DRIVE_BOOT1_1MB:
return emmc_get_initialized();
case DRIVE_SD:
return sd_get_card_initialized();
}
return false;
}
static bool _boot_storage_initialize(){
switch(drive_cur){
case DRIVE_BOOT1:
case DRIVE_EMMC:
case DRIVE_BOOT1_1MB:
return emmc_initialize(false);
case DRIVE_SD:
return sd_initialize(false);
}
return false;
}
static void _boot_storage_end(bool deinit){
if(boot_storage_get_mounted()){
switch(drive_cur){
case DRIVE_SD:
sd_unmount();
break;
case DRIVE_EMMC:
emmc_unmount();
break;
case DRIVE_BOOT1:
case DRIVE_BOOT1_1MB:
f_mount(NULL, drive_base_paths[drive_cur], 0);
}
drive_cur = DEV_INVALID;
}
if(deinit){
switch(drive_cur){
case DRIVE_SD:
sd_end();
break;
case DRIVE_EMMC:
case DRIVE_BOOT1:
case DRIVE_BOOT1_1MB:
emmc_end();
break;
}
}
}
void boot_storage_unmount(){
_boot_storage_end(false);
}
void boot_storage_end(){
_boot_storage_end(true);
}
u8 boot_storage_get_drive(){
return drive;
}
static bool _boot_storage_mount(){
// may want to check sd card first and prioritize it
FRESULT res;
bool prev_emmc_initialized = emmc_get_initialized();
bool prev_sd_initialized = sd_get_card_initialized();
if(!prev_emmc_initialized && !emmc_initialize(false)){
goto emmc_init_fail;
}
static const BYTE emmc_drives[] = {DRIVE_BOOT1_1MB, DRIVE_BOOT1};
for(BYTE i = 0; i < ARRAY_SIZE(emmc_drives); i++){
res = f_mount(&boot_storage_fs, drive_base_paths[emmc_drives[i]], true);
if(res == FR_OK){
res = f_chdrive(drive_base_paths[emmc_drives[i]]);
if(res == FR_OK && _is_eligible()){
drive_cur = emmc_drives[i];
drive = drive_cur;
break;
}else{
f_mount(NULL, drive_base_paths[emmc_drives[i]],false);
res = FR_INVALID_DRIVE;
}
}
}
if(res != FR_OK){
if(!prev_emmc_initialized) {
emmc_end();
}
}
if(res == FR_OK){
return true;
}
emmc_init_fail:
if(!emmc_initialize(false)){
goto emmc_init_fail2;
}
if(!emmc_mount()){
if(!prev_emmc_initialized) {
emmc_end();
}
goto emmc_init_fail2;
}
res = f_chdrive(drive_base_paths[DRIVE_EMMC]);
if(res == FR_OK && _is_eligible()){
drive_cur = DRIVE_EMMC;
drive = drive_cur;
return true;
}
emmc_init_fail2:
if(!sd_initialize(false)){
goto out;
}
if(!sd_mount()){
if(!prev_sd_initialized) {
sd_end();
}
goto out;
}
res = f_chdrive(drive_base_paths[DRIVE_SD]);
if(res == FR_OK && _is_eligible()){
drive_cur = DRIVE_SD;
drive = drive_cur;
return true;
}
if(!prev_sd_initialized) {
sd_end();
}
out:
return false;
}
bool boot_storage_mount(){
bool mounted = boot_storage_get_mounted();
bool initialized = boot_storage_get_initialized();
bool res = mounted && initialized;
if(!mounted){
// not mounted. mounting will also initialize.
res = _boot_storage_mount();
}else if(!initialized){
res = _boot_storage_initialize();
}
if(res){
res = f_chdrive(drive_base_paths[drive_cur]) == FR_OK;
}
return res;
}
void *boot_storage_file_read(const char *path, u32 *fsize)
{
FIL fp;
if (!boot_storage_get_mounted())
return NULL;
if (f_open(&fp, path, FA_READ) != FR_OK)
return NULL;
u32 size = f_size(&fp);
if (fsize)
*fsize = size;
void *buf = malloc(size);
if (f_read(&fp, buf, size, NULL) != FR_OK)
{
free(buf);
f_close(&fp);
return NULL;
}
f_close(&fp);
return buf;
}
int boot_storage_save_to_file(const void *buf, u32 size, const char *filename)
{
FIL fp;
u32 res = 0;
if (!boot_storage_get_mounted())
return FR_DISK_ERR;
res = f_open(&fp, filename, FA_CREATE_ALWAYS | FA_WRITE);
if (res)
{
EPRINTFARGS("Error (%d) creating file\n%s.\n", res, filename);
return res;
}
f_write(&fp, buf, size, NULL);
f_close(&fp);
return 0;
}
FATFS *boot_storage_get_fs() {
switch(drive_cur){
case DRIVE_BOOT1:
return &boot_storage_fs;
case DRIVE_EMMC:
return &emmc_fs;
case DRIVE_BOOT1_1MB:
return &boot_storage_fs;
case DRIVE_SD:
return &sd_fs;
}
return NULL;
}

View File

@@ -0,0 +1,24 @@
#ifndef _BOOT_STORAGE_H
#define _BOOT_STORAGE_H
#include <libs/fatfs/ff.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();
void *boot_storage_file_read(const char *path, u32 *fsize);
int boot_storage_save_to_file(const void *buf, u32 size, const char *filename);
FATFS *boot_storage_get_fs();
u8 boot_storage_get_drive();
#endif

View File

@@ -21,10 +21,14 @@
#include <mem/heap.h> #include <mem/heap.h>
#include <soc/fuse.h> #include <soc/fuse.h>
#include <storage/mbr_gpt.h> #include <storage/mbr_gpt.h>
#include <gfx_utils.h>
#include <utils/list.h> #include <utils/list.h>
#include <storage/emummc_file_based.h>
static u16 emmc_errors[3] = { 0 }; // Init and Read/Write errors. static u16 emmc_errors[3] = { 0 }; // Init and Read/Write errors.
static u32 emmc_mode = EMMC_MMC_HS400; static u32 emmc_mode = EMMC_MMC_HS400;
static bool emmc_init_done = false;
static bool emmc_mounted = false;
sdmmc_t emmc_sdmmc; sdmmc_t emmc_sdmmc;
sdmmc_storage_t emmc_storage; sdmmc_storage_t emmc_storage;
@@ -61,7 +65,26 @@ u32 emmc_get_mode()
return emmc_mode; return emmc_mode;
} }
void emmc_end() { sdmmc_storage_end(&emmc_storage); } static void _emmc_deinit(bool deinit){
if(emmc_init_done){
// TODO: Allow unmount even when not init'd?
if(emmc_mounted){
f_mount(NULL, "emmc:", 0);
}
if(deinit){
sdmmc_storage_end(&emmc_storage);
emmc_init_done = false;
}
}
emmc_mounted = false;
}
void emmc_end() { _emmc_deinit(true); }
bool emmc_get_initialized(){
return emmc_init_done;
}
int emmc_init_retry(bool power_cycle) int emmc_init_retry(bool power_cycle)
{ {
@@ -97,7 +120,13 @@ int emmc_init_retry(bool power_cycle)
emmc_mode = EMMC_MMC_HS400; 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) bool emmc_initialize(bool power_cycle)
@@ -212,6 +241,14 @@ int emmc_part_write(emmc_part_t *part, u32 sector_off, u32 num_sectors, void *bu
#endif #endif
} }
sdmmc_storage_t *emmc_part_get_storage(){
#ifdef BDK_EMUMMC_ENABLE
return emummc_get_storage();
#else
return &emmc_storage;
#endif
}
void nx_emmc_get_autorcm_masks(u8 *mod0, u8 *mod1) void nx_emmc_get_autorcm_masks(u8 *mod0, u8 *mod1)
{ {
if (fuse_read_hw_state() == FUSE_NX_HW_STATE_PROD) if (fuse_read_hw_state() == FUSE_NX_HW_STATE_PROD)
@@ -225,3 +262,44 @@ void nx_emmc_get_autorcm_masks(u8 *mod0, u8 *mod1)
*mod1 = 0x84; *mod1 = 0x84;
} }
} }
bool emmc_mount()
{
if (emmc_init_done && emmc_mounted)
return true;
int res = 0;
if (!emmc_init_done)
res = !emmc_initialize(false);
if (res)
{
gfx_con.mute = false;
EPRINTF("Failed to init eMMC.");
}
else
{
if (!emmc_mounted)
res = f_mount(&emmc_fs, "emmc:", 1); // Volume 0 is SD.
if (res == FR_OK)
{
emmc_mounted = true;
return true;
}
else
{
gfx_con.mute = false;
EPRINTFARGS("Failed to mount eMMC (FatFS Error %d).\nMake sure that a FAT partition exists..", res);
}
}
return false;
}
bool emmc_get_mounted(){
return emmc_mounted;
}
void emmc_unmount() { _emmc_deinit(false); }

View File

@@ -65,12 +65,17 @@ int emmc_init_retry(bool power_cycle);
bool emmc_initialize(bool power_cycle); bool emmc_initialize(bool power_cycle);
int emmc_set_partition(u32 partition); int emmc_set_partition(u32 partition);
void emmc_end(); void emmc_end();
bool emmc_mount();
void emmc_unmount();
bool emmc_get_initialized();
bool emmc_get_mounted();
void emmc_gpt_parse(link_t *gpt); void emmc_gpt_parse(link_t *gpt);
void emmc_gpt_free(link_t *gpt); void emmc_gpt_free(link_t *gpt);
emmc_part_t *emmc_part_find(link_t *gpt, const char *name); emmc_part_t *emmc_part_find(link_t *gpt, const char *name);
int emmc_part_read(emmc_part_t *part, u32 sector_off, u32 num_sectors, void *buf); int emmc_part_read(emmc_part_t *part, u32 sector_off, u32 num_sectors, void *buf);
int emmc_part_write(emmc_part_t *part, u32 sector_off, u32 num_sectors, void *buf); int emmc_part_write(emmc_part_t *part, u32 sector_off, u32 num_sectors, void *buf);
sdmmc_storage_t *emmc_part_get_storage();
void nx_emmc_get_autorcm_masks(u8 *mod0, u8 *mod1); void nx_emmc_get_autorcm_masks(u8 *mod0, u8 *mod1);

View File

@@ -0,0 +1,233 @@
#include "emummc_file_based.h"
#include <string.h>
#include <stdlib.h>
#include <libs/fatfs/ff.h>
#include <gfx_utils.h>
// TODO: fast read/writes
static FIL active_file;
// -0xff: none, -1: boot 0, -2: boot1, 0+: gpp
static s32 active_file_idx;
static char file_based_base_path[0x80];
static u32 file_part_sz_sct;
static u32 active_part;
static u32 file_based_base_path_len;
static int _emummc_storage_file_based_read_write_single(u32 sector, u32 num_sectors, void *buf, bool is_write){
#if FF_FS_READONLY == 1
if(is_write){
return FR_WRITE_PROTECTED;
}
#endif
int res = f_lseek(&active_file, (u64)sector << 9);
if(res != FR_OK){
return res;
}
if(is_write){
res = f_write(&active_file, buf, (u64)num_sectors << 9, NULL);
}else{
res = f_read(&active_file, buf, (u64)num_sectors << 9, NULL);
}
if(res != FR_OK){
return res;
}
return FR_OK;
}
static int _emummc_storage_file_based_change_file(const char *name, s32 idx){
int res;
if(active_file_idx == idx){
return FR_OK;
}
if(active_file_idx != -0xff){
f_close(&active_file);
active_file_idx = -0xff;
}
strcpy(file_based_base_path + file_based_base_path_len, name);
#if FF_FS_READONLY == 1
res = f_open(&active_file, file_based_base_path, FA_READ);
#else
res = f_open(&active_file, file_based_base_path, FA_READ | FA_WRITE);
#endif
if(res != FR_OK){
return res;
}
active_file_idx = idx;
return FR_OK;
}
static int _emummc_storage_file_based_read_write(u32 sector, u32 num_sectors, void *buf, bool is_write){
#if FF_FS_READONLY == 1
if(is_write){
return 0;
}
#endif
if(file_part_sz_sct == 0){
return 0;
}
int res;
if(active_part == 1){
// boot0
res = _emummc_storage_file_based_change_file("BOOT0", -1);
if(res != FR_OK){
return 0;
}
res = _emummc_storage_file_based_read_write_single(sector, num_sectors, buf, is_write);
if(res != FR_OK){
return 0;
}
f_sync(&active_file);
return 1;
}else if(active_part == 2){
// boot1
res = _emummc_storage_file_based_change_file("BOOT1", -2);
if(res != FR_OK){
return 0;
}
res = _emummc_storage_file_based_read_write_single(sector, num_sectors, buf, is_write) == FR_OK;
if(res != FR_OK){
return 0;
}
f_sync(&active_file);
return 1;
}else if(active_part == 0){
// GPP
if(file_part_sz_sct == 0){
return 0;
}
u32 scts_left = num_sectors;
u32 cur_sct = sector;
while(scts_left){
// offset within file
u32 offset = cur_sct % file_part_sz_sct;
// read up to start of next file or sectors left, whatever is less
u32 sct_cnt = file_part_sz_sct - offset;
sct_cnt = MIN(sct_cnt, scts_left);
u32 file_idx = cur_sct / file_part_sz_sct;
if((s32)file_idx != active_file_idx){
char name[3] = "";
if(file_idx < 10){
strcpy(name, "0");
}
itoa(file_idx, name + strlen(name), 10);
res = _emummc_storage_file_based_change_file(name, file_idx);
if(res != FR_OK){
return 0;
}
}
res = _emummc_storage_file_based_read_write_single(offset, sct_cnt, buf + ((u64)(num_sectors - scts_left) << 9), is_write);
if(res != FR_OK){
return 0;
}
cur_sct += sct_cnt;
scts_left -= sct_cnt;
}
if(res != FR_OK){
return 0;
}
f_sync(&active_file);
return 1;
}
return 0;
}
int emummc_storage_file_base_set_partition(u32 partition){
active_part = partition;
return 1;
}
int emummc_storage_file_based_init(const char *path){
strcpy(file_based_base_path, path);
file_based_base_path_len = strlen(file_based_base_path);
strcat(file_based_base_path + file_based_base_path_len, "00");
active_part = 0;
FILINFO fi;
if(f_stat(file_based_base_path, &fi) != FR_OK){
return 0;
}
file_part_sz_sct = 0;
if(fi.fsize){
file_part_sz_sct = fi.fsize >> 9;
}
active_file_idx = -0xff;
return 1;
}
void emummc_storage_file_based_end(){
if(active_file_idx != -0xff){
f_close(&active_file);
}
active_file_idx = -0xff;
file_based_base_path[0] = '\0';
file_part_sz_sct = 0;
}
#if FF_FS_READONLY == 0
int emummc_storage_file_based_write(u32 sector, u32 num_sectors, void *buf){
return _emummc_storage_file_based_read_write(sector, num_sectors, buf, true);
}
#endif
int emummc_storage_file_based_read(u32 sector, u32 num_sectors, void *buf){
return _emummc_storage_file_based_read_write(sector, num_sectors, buf, false);
}
u32 emummc_storage_file_based_get_total_gpp_size(const char *path){
u32 path_len = strlen(path);
u32 total_size_sct = 0;
char file_path[0x80];
u32 cur_idx = 0;
int res;
strcpy(file_path, path);
strcpy(file_path + path_len, "00");
FILINFO fi;
res = f_stat(file_path, &fi);
while(res == FR_OK){
cur_idx++;
total_size_sct += fi.fsize >> 9;
char name[3] = "0";
if(cur_idx >= 10){
name[0] = '\0';
}
itoa(cur_idx, name + strlen(name), 10);
strcpy(file_path + path_len, name);
res = f_stat(file_path, &fi);
}
return total_size_sct;
}

View File

@@ -0,0 +1,14 @@
#ifndef _EMUMMC_FILE_BASED_H
#define _EMUMMC_FILE_BASED_H
#include <bdk.h>
int emummc_storage_file_base_set_partition(u32 partition);
int emummc_storage_file_based_init(const char *path);
void emummc_storage_file_based_end();
int emummc_storage_file_based_write(u32 sector, u32 num_sectors, void *buf);
int emummc_storage_file_based_read(u32 sector, u32 num_sectors, void *buf);
u32 emummc_storage_file_based_get_total_gpp_size(const char *path);
sdmmc_storage_t *emummc_get_storage();
#endif

View File

@@ -0,0 +1,184 @@
#include "file_based_storage.h"
#include <libs/fatfs/ff.h>
#include <stdlib.h>
#include <string.h>
typedef struct{
FIL active_file;
s32 active_file_idx;
char base_path[0x80];
u32 part_sz_sct;
u32 base_path_len;
}file_based_storage_ctxt_t;
static file_based_storage_ctxt_t ctx;
int file_based_storage_init(const char *base_path) {
ctx.active_file_idx = -0xff;
ctx.base_path_len = strlen(base_path);
strcpy(ctx.base_path, base_path);
strcat(ctx.base_path, "00");
FILINFO fi;
if(f_stat(ctx.base_path, &fi) != FR_OK) {
return 0;
}
if(fi.fsize) {
ctx.part_sz_sct = fi.fsize >> 9;
}else{
return 0;
}
ctx.part_sz_sct = fi.fsize;
return 1;
}
void file_based_storage_end() {
if(ctx.active_file_idx != -0xff) {
f_close(&ctx.active_file);
}
ctx.active_file_idx = -0xff;
ctx.part_sz_sct = 0;
}
static int file_based_storage_change_file(const char *name, s32 idx) {
int res;
if(ctx.active_file_idx == idx){
return FR_OK;
}
if(ctx.active_file_idx != -0xff){
f_close(&ctx.active_file);
ctx.active_file_idx = -0xff;
}
strcpy(ctx.base_path + ctx.base_path_len, name);
#if FF_FS_READONLY == 1
res = f_open(&ctx.active_file, ctx.base_path, FA_READ);
#else
res = f_open(&ctx.active_file, ctx.base_path, FA_READ | FA_WRITE);
#endif
if(res != FR_OK){
return res;
}
ctx.active_file_idx = idx;
return FR_OK;
}
static int file_based_storage_readwrite_single(u32 sector, u32 num_sectors, void *buf, bool is_write){
#if FF_FS_READONLY == 1
if(is_write){
return FR_WRITE_PROTECTED;
}
#endif
int res = f_lseek(&ctx.active_file, (u64)sector << 9);
if(res != FR_OK){
return res;
}
if(is_write){
res = f_write(&ctx.active_file, buf, (u64)num_sectors << 9, NULL);
}else{
res = f_read(&ctx.active_file, buf, (u64)num_sectors << 9, NULL);
}
if(res != FR_OK){
return res;
}
return FR_OK;
}
int file_based_storage_readwrite(u32 sector, u32 num_sectors, void *buf, bool is_write) {
#if FF_FS_READONLY == 1
if(is_write){
return 0;
}
#endif
if(ctx.part_sz_sct == 0){
return 0;
}
int res;
u32 scts_left = num_sectors;
u32 cur_sct = sector;
while(scts_left){
u32 offset = cur_sct % ctx.part_sz_sct;
u32 sct_cnt = ctx.part_sz_sct - offset;
sct_cnt = MIN(scts_left, sct_cnt);
u32 file_idx = cur_sct / ctx.part_sz_sct;
if((s32) file_idx != ctx.active_file_idx) {
char name[3];
if(file_idx < 10){
strcpy(name, "0");
}
itoa(file_idx, name + strlen(name), 10);
res = file_based_storage_change_file(name, file_idx);
if(res != FR_OK){
return 0;
}
}
res = file_based_storage_readwrite_single(offset, sct_cnt, buf + ((u64)(num_sectors - scts_left) << 9), is_write);
if(res != FR_OK){
return 0;
}
cur_sct += sct_cnt;
scts_left -= sct_cnt;
}
f_sync(&ctx.active_file);
return 1;
}
int file_based_storage_read(u32 sector, u32 num_sectors, void *buf) {
return file_based_storage_readwrite(sector, num_sectors, buf, false);
}
int file_based_storage_write(u32 sector, u32 num_sectors, void *buf) {
return file_based_storage_readwrite(sector, num_sectors, buf, true);
}
u32 file_based_storage_get_total_size() {
u32 total_size_sct = 0;
char file_path[0x80];
u32 cur_idx = 0;
int res;
strcpy(file_path, ctx.base_path);
strcpy(file_path + ctx.base_path_len, "00");
FILINFO fi;
res = f_stat(file_path, &fi);
while(res == FR_OK){
cur_idx++;
total_size_sct += fi.fsize >> 9;
char name[3] = "0";
if(cur_idx >= 10){
name[0] = '\0';
}
itoa(cur_idx, name + strlen(name), 10);
strcpy(file_path + ctx.base_path_len, name);
res = f_stat(file_path, &fi);
}
return total_size_sct;
}

View File

@@ -0,0 +1,15 @@
#ifndef _FILE_BASED_STORAGE_H
#define _FILE_BASED_STORAGE_H
#include <bdk.h>
int file_based_storage_init(const char *base_path);
void file_based_storage_end();
int file_based_storage_read(u32 sector, u32 num_sectors, void *buf);
int file_based_storage_write(u32 sector, u32 num_sectors, void *buf);
u32 file_based_storage_get_total_size();
#endif

39
bdk/storage/mbr_gpt.c Normal file
View File

@@ -0,0 +1,39 @@
#include "mbr_gpt.h"
#include <utils/types.h>
#include <string.h>
bool mbr_has_gpt(const mbr_t *mbr){
for(u32 i = 0; i < 4; i++){
if(mbr->partitions[i].type == 0xee){
return true;
}
}
return false;
}
void wctombs(const u16 *src, char *dest, u32 len_max){
const u16 *cur = src;
do{
*dest++ = *cur & 0xff;
len_max--;
}while(*cur++ && len_max);
}
void ctowcs(const char *src, u16 *dest, u32 len_max){
const char *cur = src;
do{
*dest++ = *cur;
len_max--;
}while(*cur++ && len_max);
}
s32 gpt_get_part_by_name(gpt_t *gpt, const char* name, s32 prev){
u16 wc_name[36];
ctowcs(name, wc_name, 36);
for(s32 i = prev + 1; i < (s32)gpt->header.num_part_ents && i < 128; i++){
if(!memcmp(wc_name, gpt->entries[i].name, strlen(name) * 2)){
return i;
}
}
return -1;
}

View File

@@ -81,4 +81,10 @@ typedef struct _gpt_t
gpt_entry_t entries[128]; gpt_entry_t entries[128];
} gpt_t; } gpt_t;
bool mbr_has_gpt(const mbr_t *mbr);
void wctombs(const u16 *src, char *dest, u32 len_max);
void ctowcs(const char *src, u16 *dest, u32 len_max);
s32 gpt_get_part_by_name(gpt_t *gpt, const char* name, s32 prev);
#endif #endif

View File

@@ -17,6 +17,9 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <libs/fatfs/ff.h>
#include <stdlib.h>
#include <storage/nx_emmc_bis.h>
#include <string.h> #include <string.h>
#include <memory_map.h> #include <memory_map.h>
@@ -26,6 +29,7 @@
#include <storage/emmc.h> #include <storage/emmc.h>
#include <storage/sd.h> #include <storage/sd.h>
#include <storage/sdmmc.h> #include <storage/sdmmc.h>
#include <storage/emummc_file_based.h>
#include <utils/types.h> #include <utils/types.h>
#define BIS_CLUSTER_SECTORS 32 #define BIS_CLUSTER_SECTORS 32
@@ -56,6 +60,8 @@ static u32 emu_offset = 0;
static emmc_part_t *system_part = NULL; static emmc_part_t *system_part = NULL;
static u32 *cache_lookup_tbl = (u32 *)NX_BIS_LOOKUP_ADDR; static u32 *cache_lookup_tbl = (u32 *)NX_BIS_LOOKUP_ADDR;
static bis_cache_t *bis_cache = (bis_cache_t *)NX_BIS_CACHE_ADDR; static bis_cache_t *bis_cache = (bis_cache_t *)NX_BIS_CACHE_ADDR;
static sdmmc_storage_t *emu_storage = NULL;
static bool file_based = false;
static int nx_emmc_bis_write_block(u32 sector, u32 count, void *buff, bool flush) static int nx_emmc_bis_write_block(u32 sector, u32 count, void *buff, bool flush)
{ {
@@ -91,14 +97,18 @@ static int nx_emmc_bis_write_block(u32 sector, u32 count, void *buff, bool flush
} }
// Encrypt cluster. // Encrypt cluster.
if (!se_aes_crypt_xts_sec_nx(ks_tweak, ks_crypt, ENCRYPT, cluster, tweak, true, sector_in_cluster, bis_cache->dma_buff, buff, count * EMMC_BLOCKSIZE)) if (!se_aes_xts_crypt_sec_nx(ks_tweak, ks_crypt, ENCRYPT, cluster, tweak, true, sector_in_cluster, bis_cache->dma_buff, buff, count * EMMC_BLOCKSIZE))
return 1; // Encryption error. return 1; // Encryption error.
// If not reading from cache, do a regular read and decrypt. // If not reading from cache, do a regular read and decrypt.
if (!emu_offset) if(emu_storage){
res = sdmmc_storage_write(emu_storage, emu_offset + system_part->lba_start + sector, count, bis_cache->dma_buff);
}else if(file_based){
res = emummc_storage_file_based_write(system_part->lba_start + sector, count, bis_cache->dma_buff);
}else{
res = emmc_part_write(system_part, sector, count, bis_cache->dma_buff); res = emmc_part_write(system_part, sector, count, bis_cache->dma_buff);
else }
res = sdmmc_storage_write(&sd_storage, emu_offset + system_part->lba_start + sector, count, bis_cache->dma_buff);
if (!res) if (!res)
return 1; // R/W error. return 1; // R/W error.
@@ -155,10 +165,13 @@ static int nx_emmc_bis_read_block_normal(u32 sector, u32 count, void *buff)
u32 sector_in_cluster = sector % BIS_CLUSTER_SECTORS; u32 sector_in_cluster = sector % BIS_CLUSTER_SECTORS;
// If not reading from cache, do a regular read and decrypt. // If not reading from cache, do a regular read and decrypt.
if (!emu_offset) if(emu_storage){
res = sdmmc_storage_read(emu_storage, emu_offset + system_part->lba_start + sector, count, bis_cache->dma_buff);
}else if(file_based){
res = emummc_storage_file_based_read(system_part->lba_start + sector, count, bis_cache->dma_buff);
}else{
res = emmc_part_read(system_part, sector, count, bis_cache->dma_buff); res = emmc_part_read(system_part, sector, count, bis_cache->dma_buff);
else }
res = sdmmc_storage_read(&sd_storage, emu_offset + system_part->lba_start + sector, count, bis_cache->dma_buff);
if (!res) if (!res)
return 1; // R/W error. return 1; // R/W error.
@@ -177,7 +190,7 @@ static int nx_emmc_bis_read_block_normal(u32 sector, u32 count, void *buff)
tweak_exp = sector_in_cluster; tweak_exp = sector_in_cluster;
// Maximum one cluster (1 XTS crypto block 16KB). // Maximum one cluster (1 XTS crypto block 16KB).
if (!se_aes_crypt_xts_sec_nx(ks_tweak, ks_crypt, DECRYPT, prev_cluster, tweak, regen_tweak, tweak_exp, buff, bis_cache->dma_buff, count * EMMC_BLOCKSIZE)) if (!se_aes_xts_crypt_sec_nx(ks_tweak, ks_crypt, DECRYPT, prev_cluster, tweak, regen_tweak, tweak_exp, buff, bis_cache->dma_buff, count * EMMC_BLOCKSIZE))
return 1; // R/W error. return 1; // R/W error.
prev_sector = sector + count - 1; prev_sector = sector + count - 1;
@@ -212,15 +225,19 @@ static int nx_emmc_bis_read_block_cached(u32 sector, u32 count, void *buff)
cache_lookup_tbl[cluster] = bis_cache->top_idx; cache_lookup_tbl[cluster] = bis_cache->top_idx;
// Read the whole cluster the sector resides in. // Read the whole cluster the sector resides in.
if (!emu_offset) if (emu_storage){
res = sdmmc_storage_read(emu_storage, emu_offset + system_part->lba_start + cluster_sector, BIS_CLUSTER_SECTORS, bis_cache->dma_buff);
}else if(file_based){
res = emummc_storage_file_based_read(system_part->lba_start + cluster_sector, BIS_CLUSTER_SECTORS, bis_cache->dma_buff);
}else{
res = emmc_part_read(system_part, cluster_sector, BIS_CLUSTER_SECTORS, bis_cache->dma_buff); res = emmc_part_read(system_part, cluster_sector, BIS_CLUSTER_SECTORS, bis_cache->dma_buff);
else }
res = sdmmc_storage_read(&sd_storage, emu_offset + system_part->lba_start + cluster_sector, BIS_CLUSTER_SECTORS, bis_cache->dma_buff);
if (!res) if (!res)
return 1; // R/W error. return 1; // R/W error.
// Decrypt cluster. // Decrypt cluster.
if (!se_aes_crypt_xts_sec_nx(ks_tweak, ks_crypt, DECRYPT, cluster, cache_tweak, true, 0, bis_cache->dma_buff, bis_cache->dma_buff, BIS_CLUSTER_SIZE)) if (!se_aes_xts_crypt_sec_nx(ks_tweak, ks_crypt, DECRYPT, cluster, cache_tweak, true, 0, bis_cache->dma_buff, bis_cache->dma_buff, BIS_CLUSTER_SIZE))
return 1; // Decryption error. return 1; // Decryption error.
// Copy to cluster cache. // Copy to cluster cache.
@@ -292,10 +309,11 @@ int nx_emmc_bis_write(u32 sector, u32 count, void *buff)
return 1; return 1;
} }
void nx_emmc_bis_init(emmc_part_t *part, bool enable_cache, u32 emummc_offset) void nx_emmc_bis_init(emmc_part_t *part, bool enable_cache, sdmmc_storage_t *storage, u32 emummc_offset)
{ {
system_part = part; system_part = part;
emu_offset = emummc_offset; emu_offset = emummc_offset;
emu_storage = storage;
_nx_emmc_bis_cluster_cache_init(enable_cache); _nx_emmc_bis_cluster_cache_init(enable_cache);
@@ -318,8 +336,31 @@ void nx_emmc_bis_init(emmc_part_t *part, bool enable_cache, u32 emummc_offset)
system_part = NULL; system_part = NULL;
} }
void nx_emmc_bis_init_file_based(emmc_part_t *part, bool enable_cache, const char *base_path){
emummc_storage_file_based_init(base_path);
file_based = true;
nx_emmc_bis_init(part, enable_cache, NULL, 0);
}
void nx_emmc_bis_end() void nx_emmc_bis_end()
{ {
_nx_emmc_bis_flush_cache(); _nx_emmc_bis_flush_cache();
if(file_based){
emummc_storage_file_based_end();
}
system_part = NULL; system_part = NULL;
emu_storage = NULL;
emu_offset = 0;
file_based = false;
}
sdmmc_storage_t *nx_emmc_bis_get_storage(){
if(emu_storage == &emmc_storage){
return &emmc_storage;
}else{
return emmc_part_get_storage();
}
} }

View File

@@ -237,7 +237,10 @@ typedef struct _nx_emmc_cal0_t
int nx_emmc_bis_read(u32 sector, u32 count, void *buff); int nx_emmc_bis_read(u32 sector, u32 count, void *buff);
int nx_emmc_bis_write(u32 sector, u32 count, void *buff); int nx_emmc_bis_write(u32 sector, u32 count, void *buff);
void nx_emmc_bis_init(emmc_part_t *part, bool enable_cache, u32 emummc_offset); // when storage == NULL, use active emummc config, otherwise, access storage at offset
void nx_emmc_bis_init(emmc_part_t *part, bool enable_cache, sdmmc_storage_t *storage, u32 emummc_offset);
void nx_emmc_bis_init_file_based(emmc_part_t *part, bool enable_cache, const char *base_path);
void nx_emmc_bis_end(); void nx_emmc_bis_end();
sdmmc_storage_t *nx_emmc_bis_get_storage();
#endif #endif

View File

@@ -44,7 +44,7 @@ int ram_disk_init(void *ram_fs, u32 ramdisk_size)
disk_set_info(DRIVE_RAM, SET_SECTOR_COUNT, &ramdisk_size); disk_set_info(DRIVE_RAM, SET_SECTOR_COUNT, &ramdisk_size);
// Unmount ramdisk. // Unmount ramdisk.
f_unmount("ram:"); f_mount(NULL, "ram:", 1);
// Format as exFAT w/ 32KB cluster with no MBR. // Format as exFAT w/ 32KB cluster with no MBR.
res = f_mkfs("ram:", FM_EXFAT | FM_SFD, RAMDISK_CLUSTER_SZ, buf, 0x400000); res = f_mkfs("ram:", FM_EXFAT | FM_SFD, RAMDISK_CLUSTER_SZ, buf, 0x400000);

View File

@@ -199,7 +199,7 @@ bool sd_mount()
else else
{ {
if (!sd_mounted) if (!sd_mounted)
res = f_mount(&sd_fs, "0:", 1); // Volume 0 is SD. res = f_mount(&sd_fs, "sd:", 1); // Volume 0 is SD.
if (res == FR_OK) if (res == FR_OK)
{ {
sd_mounted = true; sd_mounted = true;
@@ -227,7 +227,7 @@ static void _sd_deinit(bool deinit)
if (sd_init_done) if (sd_init_done)
{ {
if (sd_mounted) if (sd_mounted)
f_unmount("0:"); // Volume 0 is SD. f_mount(NULL, "sd:", 1); // Volume 0 is SD.
if (deinit) if (deinit)
{ {
@@ -246,14 +246,30 @@ bool sd_is_gpt()
return sd_fs.part_type; return sd_fs.part_type;
} }
void *sd_file_read(const char *path, u32 *fsize) void *sd_file_read(const char *path, u32 *fsize)
{ {
FIL fp; FIL fp;
if (!sd_get_card_mounted()) if (!sd_get_card_mounted())
return NULL; return NULL;
if (f_open(&fp, path, FA_READ) != FR_OK) char *cwd = (char*)malloc(0x200);
if(f_getcwd(cwd, 0x200) != FR_OK){
free(cwd);
return NULL; return NULL;
}
if(f_chdrive("sd:") != FR_OK){
free(cwd);
return NULL;
}
if (f_open(&fp, path, FA_READ) != FR_OK){
f_chdrive(cwd);
free(cwd);
return NULL;
}
u32 size = f_size(&fp); u32 size = f_size(&fp);
if (fsize) if (fsize)
@@ -263,13 +279,17 @@ void *sd_file_read(const char *path, u32 *fsize)
if (f_read(&fp, buf, size, NULL) != FR_OK) if (f_read(&fp, buf, size, NULL) != FR_OK)
{ {
f_chdrive(cwd);
free(buf); free(buf);
free(cwd);
f_close(&fp); f_close(&fp);
return NULL; return NULL;
} }
f_chdrive(cwd);
f_close(&fp); f_close(&fp);
free(cwd);
return buf; return buf;
} }
@@ -281,13 +301,33 @@ int sd_save_to_file(const void *buf, u32 size, const char *filename)
if (!sd_get_card_mounted()) if (!sd_get_card_mounted())
return FR_DISK_ERR; return FR_DISK_ERR;
char *cwd = malloc(0x200);
res = f_getcwd(cwd, 0x200);
if(res != FR_OK){
free(cwd);
return res;
}
res = f_chdrive("sd:");
if(res != FR_OK){
free(cwd);
return res;
}
res = f_open(&fp, filename, FA_CREATE_ALWAYS | FA_WRITE); res = f_open(&fp, filename, FA_CREATE_ALWAYS | FA_WRITE);
if (res) if (res)
{ {
EPRINTFARGS("Error (%d) creating file\n%s.\n", res, filename); EPRINTFARGS("Error (%d) creating file\n%s.\n", res, filename);
f_chdrive(cwd);
free(cwd);
return res; return res;
} }
f_chdrive(cwd);
free(cwd);
f_write(&fp, buf, size, NULL); f_write(&fp, buf, size, NULL);
f_close(&fp); f_close(&fp);

View File

@@ -31,8 +31,13 @@ extern u32 sd_power_cycle_time_start;
typedef enum _sdmmc_type typedef enum _sdmmc_type
{ {
MMC_SD = 0, MMC_SD = 0,
MMC_EMMC = 1, MMC_EMMC = 1,
MMC_EMUMMC_FILE = 2,
MMC_EMUMMC_RAW_SD = 3,
MMC_EMUMMC_RAW_EMMC = 4,
MMC_EMUMMC_FILE_EMMC = 5,
MMC_FILE_BASED = 6,
EMMC_GPP = 0, EMMC_GPP = 0,
EMMC_BOOT0 = 1, EMMC_BOOT0 = 1,

View File

@@ -19,6 +19,9 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <storage/emmc.h>
#include <storage/emummc_file_based.h>
#include <storage/file_based_storage.h>
#include <string.h> #include <string.h>
#include <usb/usbd.h> #include <usb/usbd.h>
@@ -495,8 +498,18 @@ static int _scsi_read(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
} }
// Do the SDMMC read. // Do the SDMMC read.
if (!sdmmc_storage_read(ums->lun.storage, ums->lun.offset + lba_offset, amount, sdmmc_buf)) if(ums->lun.storage){
amount = 0; if (!sdmmc_storage_read(ums->lun.storage, ums->lun.offset + lba_offset, amount, sdmmc_buf))
amount = 0;
}else if (ums->lun.type == MMC_FILE_BASED) {
if(!file_based_storage_read(ums->lun.offset + lba_offset, amount, sdmmc_buf)){
amount = 0;
}
}else{
if(!emummc_storage_file_based_read(ums->lun.offset + lba_offset, amount, sdmmc_buf)){
amount = 0;
}
}
// Wait for the async USB transfer to finish. // Wait for the async USB transfer to finish.
if (!first_read) if (!first_read)
@@ -650,9 +663,19 @@ static int _scsi_write(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
goto empty_write; goto empty_write;
// Perform the write. // Perform the write.
if (!sdmmc_storage_write(ums->lun.storage, ums->lun.offset + lba_offset, if(ums->lun.storage){
amount >> UMS_DISK_LBA_SHIFT, (u8 *)bulk_ctxt->bulk_out_buf)) if (!sdmmc_storage_write(ums->lun.storage, ums->lun.offset + lba_offset,
amount = 0; amount >> UMS_DISK_LBA_SHIFT, (u8 *)bulk_ctxt->bulk_out_buf))
amount = 0;
}else if(ums->lun.type == MMC_FILE_BASED){
if(!file_based_storage_write(ums->lun.offset + lba_offset, amount >> UMS_DISK_LBA_SHIFT, (u8*)bulk_ctxt->bulk_out_buf)){
amount = 0;
}
}else{
if(!emummc_storage_file_based_write(ums->lun.offset + lba_offset, amount >> UMS_DISK_LBA_SHIFT, (u8*)bulk_ctxt->bulk_out_buf)){
amount = 0;
}
}
DPRINTF("file write %X @ %X\n", amount, lba_offset); DPRINTF("file write %X @ %X\n", amount, lba_offset);
@@ -722,8 +745,18 @@ static int _scsi_verify(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
break; break;
} }
if (!sdmmc_storage_read(ums->lun.storage, ums->lun.offset + lba_offset, amount, bulk_ctxt->bulk_in_buf)) if(ums->lun.storage){
amount = 0; if (!sdmmc_storage_read(ums->lun.storage, ums->lun.offset + lba_offset, amount, bulk_ctxt->bulk_in_buf))
amount = 0;
}else if(ums->lun.type == MMC_FILE_BASED){
if(!file_based_storage_read(ums->lun.offset + lba_offset, amount, bulk_ctxt->bulk_in_buf)){
amount = 0;
}
}else{
if(!emummc_storage_file_based_read(ums->lun.offset + lba_offset, amount, bulk_ctxt->bulk_in_buf)){
amount = 0;
}
}
DPRINTF("File read %X @ %X\n", amount, lba_offset); DPRINTF("File read %X @ %X\n", amount, lba_offset);
@@ -756,8 +789,12 @@ static int _scsi_inquiry(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
buf[3] = 20; // Additional length. buf[3] = 20; // Additional length.
buf += 4; buf += 4;
s_printf((char *)buf, "%04X%s", if(ums->lun.storage){
ums->lun.storage->cid.serial, ums->lun.type == MMC_SD ? " SD " : " eMMC "); s_printf((char *)buf, "%04X%s",
ums->lun.storage->cid.serial, ums->lun.type == MMC_SD ? " SD " : " eMMC ");
}else{
strcpy((char*)buf, "0000 emuMMC");
}
switch (ums->lun.partition) switch (ums->lun.partition)
{ {
@@ -1861,7 +1898,7 @@ int usb_device_gadget_ums(usb_ctxt_t *usbs)
if (usbs->type == MMC_SD) if (usbs->type == MMC_SD)
{ {
sd_end(); sd_end();
if (!sd_mount()) if (!sd_mount() && !sd_get_card_initialized())
{ {
ums.set_text(ums.label, "#FFDD00 Failed to init SD!#"); ums.set_text(ums.label, "#FFDD00 Failed to init SD!#");
res = 1; res = 1;
@@ -1871,9 +1908,50 @@ int usb_device_gadget_ums(usb_ctxt_t *usbs)
ums.lun.sdmmc = &sd_sdmmc; ums.lun.sdmmc = &sd_sdmmc;
ums.lun.storage = &sd_storage; ums.lun.storage = &sd_storage;
}else if(usbs->type == MMC_EMUMMC_FILE){
// sd must be already mounted and emummc file based initialized
if(!sd_get_card_mounted()){
ums.set_text(ums.label, "#FFDD00 Failed to init SD!#");
res = 1;
goto init_fail;
}
ums.lun.storage = NULL;
ums.lun.sdmmc = NULL;
} }
else else if(usbs->type == MMC_EMUMMC_RAW_EMMC){
{ if (!emmc_initialize(false))
{
ums.set_text(ums.label, "#FFDD00 Failed to init eMMC!#");
res = 1;
goto init_fail;
}
emmc_set_partition(EMMC_GPP);
ums.lun.sdmmc = &emmc_sdmmc;
ums.lun.storage = &emmc_storage;
}else if(usbs->type == MMC_EMUMMC_RAW_SD){
if (!sd_initialize(false))
{
ums.set_text(ums.label, "#FFDD00 Failed to init SD!#");
res = 1;
goto init_fail;
}
ums.lun.sdmmc = &emmc_sdmmc;
ums.lun.storage = &emmc_storage;
}else if(usbs->type == MMC_EMUMMC_FILE_EMMC){
if(!emmc_get_mounted()){
ums.set_text(ums.label, "#FFDD00 Failed to init eMMC!#");
res = 1;
goto init_fail;
}
ums.lun.storage = NULL;
ums.lun.sdmmc = NULL;
}else if(usbs->type == MMC_FILE_BASED){
// file based must be initialized at this point
ums.lun.storage = NULL;
ums.lun.sdmmc = NULL;
} else{
if (!emmc_initialize(false)) if (!emmc_initialize(false))
{ {
ums.set_text(ums.label, "#FFDD00 Failed to init eMMC!#"); ums.set_text(ums.label, "#FFDD00 Failed to init eMMC!#");
@@ -1902,10 +1980,27 @@ int usb_device_gadget_ums(usb_ctxt_t *usbs)
// If partition sectors are not set get them from hardware. // If partition sectors are not set get them from hardware.
if (!ums.lun.num_sectors) if (!ums.lun.num_sectors)
{ {
if (usbs->type == MMC_EMMC && (ums.lun.partition - 1)) // eMMC BOOT0/1. switch(usbs->type){
ums.lun.num_sectors = emmc_storage.ext_csd.boot_mult << 8; case MMC_EMMC:
else if(ums.lun.partition - 1){
ums.lun.num_sectors = ums.lun.storage->sec_cnt; // eMMC GPP or SD. ums.lun.num_sectors = emmc_storage.ext_csd.boot_mult << 8;
}else{
ums.lun.num_sectors = ums.lun.storage->sec_cnt;
}
break;
case MMC_SD:
ums.lun.num_sectors = ums.lun.storage->sec_cnt;
break;
case MMC_EMUMMC_FILE:
case MMC_EMUMMC_FILE_EMMC:
case MMC_EMUMMC_RAW_SD:
case MMC_EMUMMC_RAW_EMMC:
ums.set_text(ums.label, "#FFDD00 No sector count set for emuMMC!#");
break;
case MMC_FILE_BASED:
ums.set_text(ums.label, "#FFDD00 No sector count set for emuSD!#");
break;
}
} }
do do

View File

@@ -22,15 +22,12 @@
#include <mem/heap.h> #include <mem/heap.h>
#include <utils/types.h> #include <utils/types.h>
dirlist_t *dirlist(const char *directory, const char *pattern, u32 flags) dirlist_t *dirlist(const char *directory, const char *pattern, bool includeHiddenFiles, bool parse_dirs)
{ {
int res = 0; int res = 0;
u32 k = 0; u32 k = 0;
DIR dir; DIR dir;
FILINFO fno; FILINFO fno;
bool show_hidden = !!(flags & DIR_SHOW_HIDDEN);
bool show_dirs = !!(flags & DIR_SHOW_DIRS);
bool ascii_order = !!(flags & DIR_ASCII_ORDER);
dirlist_t *dir_entries = (dirlist_t *)malloc(sizeof(dirlist_t)); dirlist_t *dir_entries = (dirlist_t *)malloc(sizeof(dirlist_t));
@@ -46,11 +43,11 @@ dirlist_t *dirlist(const char *directory, const char *pattern, u32 flags)
if (res || !fno.fname[0]) if (res || !fno.fname[0])
break; break;
bool curr_parse = show_dirs ? (fno.fattrib & AM_DIR) : !(fno.fattrib & AM_DIR); bool curr_parse = parse_dirs ? (fno.fattrib & AM_DIR) : !(fno.fattrib & AM_DIR);
if (curr_parse) if (curr_parse)
{ {
if ((fno.fname[0] != '.') && (show_hidden || !(fno.fattrib & AM_HID))) if ((fno.fname[0] != '.') && (includeHiddenFiles || !(fno.fattrib & AM_HID)))
{ {
strcpy(&dir_entries->data[k * 256], fno.fname); strcpy(&dir_entries->data[k * 256], fno.fname);
if (++k >= DIR_MAX_ENTRIES) if (++k >= DIR_MAX_ENTRIES)
@@ -64,7 +61,7 @@ dirlist_t *dirlist(const char *directory, const char *pattern, u32 flags)
{ {
do do
{ {
if (!(fno.fattrib & AM_DIR) && (fno.fname[0] != '.') && (show_hidden || !(fno.fattrib & AM_HID))) if (!(fno.fattrib & AM_DIR) && (fno.fname[0] != '.') && (includeHiddenFiles || !(fno.fattrib & AM_HID)))
{ {
strcpy(&dir_entries->data[k * 256], fno.fname); strcpy(&dir_entries->data[k * 256], fno.fname);
if (++k >= DIR_MAX_ENTRIES) if (++k >= DIR_MAX_ENTRIES)
@@ -85,15 +82,12 @@ dirlist_t *dirlist(const char *directory, const char *pattern, u32 flags)
// Terminate name list. // Terminate name list.
dir_entries->name[k] = NULL; dir_entries->name[k] = NULL;
// Choose list ordering.
int (*strcmpex)(const char* str1, const char* str2) = ascii_order ? strcmp : strcasecmp;
// Reorder ini files Alphabetically. // Reorder ini files Alphabetically.
for (u32 i = 0; i < k - 1 ; i++) for (u32 i = 0; i < k - 1 ; i++)
{ {
for (u32 j = i + 1; j < k; j++) for (u32 j = i + 1; j < k; j++)
{ {
if (strcmpex(dir_entries->name[i], dir_entries->name[j]) > 0) if (strcasecmp(dir_entries->name[i], dir_entries->name[j]) > 0)
{ {
char *tmp = dir_entries->name[i]; char *tmp = dir_entries->name[i];
dir_entries->name[i] = dir_entries->name[j]; dir_entries->name[i] = dir_entries->name[j];

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2018-2025 CTCaer * Copyright (c) 2018-2024 CTCaer
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@@ -18,14 +18,10 @@
#define DIR_MAX_ENTRIES 64 #define DIR_MAX_ENTRIES 64
#define DIR_SHOW_HIDDEN BIT(0)
#define DIR_SHOW_DIRS BIT(1)
#define DIR_ASCII_ORDER BIT(2)
typedef struct _dirlist_t typedef struct _dirlist_t
{ {
char *name[DIR_MAX_ENTRIES]; char *name[DIR_MAX_ENTRIES];
char data[DIR_MAX_ENTRIES * 256]; char data[DIR_MAX_ENTRIES * 256];
} dirlist_t; } dirlist_t;
dirlist_t *dirlist(const char *directory, const char *pattern, u32 flags); dirlist_t *dirlist(const char *directory, const char *pattern, bool includeHiddenFiles, bool parse_dirs);

View File

@@ -70,7 +70,7 @@ int ini_parse(link_t *dst, const char *ini_path, bool is_dir)
// Get all ini filenames. // Get all ini filenames.
if (is_dir) if (is_dir)
{ {
filelist = dirlist(filename, "*.ini", DIR_ASCII_ORDER); filelist = dirlist(filename, "*.ini", false, false);
if (!filelist) if (!filelist)
{ {
free(filename); free(filename);

View File

@@ -105,6 +105,9 @@ typedef unsigned long uptr;
#define likely(x) (__builtin_expect((x) != 0, 1)) #define likely(x) (__builtin_expect((x) != 0, 1))
#define unlikely(x) (__builtin_expect((x) != 0, 0)) #define unlikely(x) (__builtin_expect((x) != 0, 0))
#define XSTR(a) STR(a)
#define STR(a) #a
/* Bootloader/Nyx */ /* Bootloader/Nyx */
#define BOOT_CFG_AUTOBOOT_EN BIT(0) #define BOOT_CFG_AUTOBOOT_EN BIT(0)
#define BOOT_CFG_FROM_LAUNCH BIT(1) #define BOOT_CFG_FROM_LAUNCH BIT(1)
@@ -126,7 +129,11 @@ typedef enum _nyx_ums_type
NYX_UMS_EMMC_GPP, NYX_UMS_EMMC_GPP,
NYX_UMS_EMUMMC_BOOT0, NYX_UMS_EMUMMC_BOOT0,
NYX_UMS_EMUMMC_BOOT1, NYX_UMS_EMUMMC_BOOT1,
NYX_UMS_EMUMMC_GPP NYX_UMS_EMUMMC_GPP,
NYX_UMS_BOOT_STRG_SD,
NYX_UMS_BOOT_STRG_BOOT1,
NYX_UMS_BOOT_STRG_BOOT1_1MB,
NYX_UMS_BOOT_STRG_GPP,
} nyx_ums_type; } nyx_ums_type;
typedef struct __attribute__((__packed__)) _boot_cfg_t typedef struct __attribute__((__packed__)) _boot_cfg_t

View File

@@ -15,6 +15,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <storage/boot_storage.h>
#include <string.h> #include <string.h>
#include <mem/heap.h> #include <mem/heap.h>
@@ -273,6 +274,7 @@ void power_set_state(power_state_t state)
u8 reg; u8 reg;
// Unmount and power down sd card. // Unmount and power down sd card.
boot_storage_end();
sd_end(); sd_end();
// De-initialize and power down various hardware. // De-initialize and power down various hardware.

View File

@@ -25,7 +25,6 @@
void set_default_configuration() void set_default_configuration()
{ {
h_cfg.t210b01 = hw_get_chip_id() == GP_HIDREV_MAJOR_T210B01; h_cfg.t210b01 = hw_get_chip_id() == GP_HIDREV_MAJOR_T210B01;
h_cfg.devmode = fuse_read_hw_state();
h_cfg.autoboot = 0; h_cfg.autoboot = 0;
h_cfg.autoboot_list = 0; h_cfg.autoboot_list = 0;

View File

@@ -35,7 +35,6 @@ typedef struct _hekate_config
u32 bootprotect; u32 bootprotect;
// Global temporary config. // Global temporary config.
bool t210b01; bool t210b01;
bool devmode;
bool emummc_force_disable; bool emummc_force_disable;
bool rcm_patched; bool rcm_patched;
u32 errors; u32 errors;

View File

@@ -15,6 +15,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <storage/sd.h>
#include <string.h> #include <string.h>
#include <bdk.h> #include <bdk.h>
@@ -37,7 +38,7 @@ void print_fuseinfo()
gfx_con_setpos(0, 0); gfx_con_setpos(0, 0);
gfx_printf("\nSKU: %X - ", FUSE(FUSE_SKU_INFO)); gfx_printf("\nSKU: %X - ", FUSE(FUSE_SKU_INFO));
switch (h_cfg.devmode) switch (fuse_read_hw_state())
{ {
case FUSE_NX_HW_STATE_PROD: case FUSE_NX_HW_STATE_PROD:
gfx_printf("Retail\n"); gfx_printf("Retail\n");
@@ -230,19 +231,18 @@ void print_sdcard_info()
sd_storage.ssr.app_class, sd_storage.csd.write_protect, 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. 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 (sd_mount())
if (!res)
{ {
gfx_puts("Acquiring FAT volume info...\n\n"); gfx_puts("Acquiring FAT volume info...\n\n");
gfx_printf("%kFound %s volume:%k\n Free: %d MiB\n Cluster: %d KiB\n", 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, 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); sd_fs.free_clst * sd_fs.csize >> SECTORS_TO_MIB_COEFF, (sd_fs.csize > 1) ? (sd_fs.csize >> 1) : 512);
f_unmount(""); sd_end();
} }
else else
{ {
EPRINTFARGS("Failed to mount SD card (FatFS Error %d).\n" EPRINTF("Failed to mount SD card.\n"
"Make sure that a FAT partition exists..", res); "Make sure that a FAT partition exists..");
} }
sd_end(); sd_end();

View File

@@ -2,7 +2,7 @@
* Copyright (c) 2018 naehrwert * Copyright (c) 2018 naehrwert
* Copyright (c) 2018 st4rk * Copyright (c) 2018 st4rk
* Copyright (c) 2018 Ced2911 * Copyright (c) 2018 Ced2911
* Copyright (c) 2018-2026 CTCaer * Copyright (c) 2018-2025 CTCaer
* Copyright (c) 2018 balika011 * Copyright (c) 2018 balika011
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
@@ -28,6 +28,8 @@
#include "../frontend/fe_tools.h" #include "../frontend/fe_tools.h"
#include "../config.h" #include "../config.h"
#include "../storage/emummc.h" #include "../storage/emummc.h"
#include "../storage/emusd.h"
#include <storage/boot_storage.h>
//#define DPRINTF(...) gfx_printf(__VA_ARGS__) //#define DPRINTF(...) gfx_printf(__VA_ARGS__)
#define DPRINTF(...) #define DPRINTF(...)
@@ -166,7 +168,7 @@ static void _hos_eks_get()
// Decrypt EKS blob. // Decrypt EKS blob.
hos_eks_mbr_t *eks = (hos_eks_mbr_t *)(mbr + 0x80); hos_eks_mbr_t *eks = (hos_eks_mbr_t *)(mbr + 0x80);
se_aes_crypt_ecb(14, DECRYPT, eks, eks, sizeof(hos_eks_mbr_t)); se_aes_crypt_ecb(14, DECRYPT, eks, sizeof(hos_eks_mbr_t), eks, sizeof(hos_eks_mbr_t));
// Check if valid and for this unit. // Check if valid and for this unit.
if (eks->magic == HOS_EKS_MAGIC && eks->lot0 == FUSE(FUSE_OPT_LOT_CODE_0)) if (eks->magic == HOS_EKS_MAGIC && eks->lot0 == FUSE(FUSE_OPT_LOT_CODE_0))
@@ -212,7 +214,7 @@ static void _hos_eks_save()
// Get keys. // Get keys.
u8 *keys = (u8 *)zalloc(SZ_8K); u8 *keys = (u8 *)zalloc(SZ_8K);
se_aes_ctx_get_keys(keys + SZ_4K, keys, SE_KEY_128_SIZE); se_get_aes_keys(keys + SZ_4K, keys, SE_KEY_128_SIZE);
// Set magic and personalized info. // Set magic and personalized info.
h_cfg.eks->magic = HOS_EKS_MAGIC; h_cfg.eks->magic = HOS_EKS_MAGIC;
@@ -227,7 +229,7 @@ static void _hos_eks_save()
// Encrypt EKS blob. // Encrypt EKS blob.
u8 *eks = malloc(sizeof(hos_eks_mbr_t)); u8 *eks = malloc(sizeof(hos_eks_mbr_t));
memcpy(eks, h_cfg.eks, sizeof(hos_eks_mbr_t)); memcpy(eks, h_cfg.eks, sizeof(hos_eks_mbr_t));
se_aes_crypt_ecb(14, ENCRYPT, eks, eks, sizeof(hos_eks_mbr_t)); se_aes_crypt_ecb(14, ENCRYPT, eks, sizeof(hos_eks_mbr_t), eks, sizeof(hos_eks_mbr_t));
// Write EKS blob to SD. // Write EKS blob to SD.
memcpy(mbr + 0x80, eks, sizeof(hos_eks_mbr_t)); memcpy(mbr + 0x80, eks, sizeof(hos_eks_mbr_t));
@@ -262,7 +264,7 @@ static void _hos_eks_clear(u32 mkey)
// Encrypt EKS blob. // Encrypt EKS blob.
u8 *eks = malloc(sizeof(hos_eks_mbr_t)); u8 *eks = malloc(sizeof(hos_eks_mbr_t));
memcpy(eks, h_cfg.eks, sizeof(hos_eks_mbr_t)); memcpy(eks, h_cfg.eks, sizeof(hos_eks_mbr_t));
se_aes_crypt_ecb(14, ENCRYPT, eks, eks, sizeof(hos_eks_mbr_t)); se_aes_crypt_ecb(14, ENCRYPT, eks, sizeof(hos_eks_mbr_t), eks, sizeof(hos_eks_mbr_t));
// Write EKS blob to SD. // Write EKS blob to SD.
memcpy(mbr + 0x80, eks, sizeof(hos_eks_mbr_t)); memcpy(mbr + 0x80, eks, sizeof(hos_eks_mbr_t));
@@ -350,7 +352,7 @@ static int _hos_keygen(pkg1_eks_t *eks, u32 mkey, tsec_ctxt_t *tsec_ctxt, bool s
*/ */
// Use custom TSEC Hovi Keygen firmware. // Use custom TSEC Hovi Keygen firmware.
tsec_ctxt->fw = sd_file_read("bootloader/sys/thk.bin", NULL); tsec_ctxt->fw = boot_storage_file_read("bootloader/sys/thk.bin", NULL);
if (!tsec_ctxt->fw) if (!tsec_ctxt->fw)
{ {
_hos_crit_error("Failed to load thk.bin"); _hos_crit_error("Failed to load thk.bin");
@@ -406,7 +408,7 @@ static int _hos_keygen(pkg1_eks_t *eks, u32 mkey, tsec_ctxt_t *tsec_ctxt, bool s
else else
{ {
// Decrypt eks and set keyslots. // Decrypt eks and set keyslots.
se_aes_crypt_ecb(12, DECRYPT, tsec_keys.tmp, eks_keyseeds[0], SE_KEY_128_SIZE); se_aes_crypt_block_ecb(12, DECRYPT, tsec_keys.tmp, eks_keyseeds[0]);
se_aes_unwrap_key(15, 14, tsec_keys.tmp); se_aes_unwrap_key(15, 14, tsec_keys.tmp);
// Derive device keys. // Derive device keys.
@@ -442,7 +444,7 @@ static int _hos_keygen(pkg1_eks_t *eks, u32 mkey, tsec_ctxt_t *tsec_ctxt, bool s
else else
{ {
// Decrypt eks and set keyslots for Exosphere 2. // Decrypt eks and set keyslots for Exosphere 2.
se_aes_crypt_ecb(12, DECRYPT, tsec_keys.tmp, eks_keyseeds[0], SE_KEY_128_SIZE); se_aes_crypt_block_ecb(12, DECRYPT, tsec_keys.tmp, eks_keyseeds[0]);
se_aes_unwrap_key(15, 14, tsec_keys.tmp); se_aes_unwrap_key(15, 14, tsec_keys.tmp);
// Derive device keys. // Derive device keys.
@@ -469,9 +471,9 @@ static int _hos_keygen(pkg1_eks_t *eks, u32 mkey, tsec_ctxt_t *tsec_ctxt, bool s
se_aes_key_set(13, tsec_keys.tsec, SE_KEY_128_SIZE); se_aes_key_set(13, tsec_keys.tsec, SE_KEY_128_SIZE);
// Derive eks keys from TSEC+SBK. // Derive eks keys from TSEC+SBK.
se_aes_crypt_ecb(13, DECRYPT, tsec_keys.tsec, eks_keyseeds[0], SE_KEY_128_SIZE); se_aes_crypt_block_ecb(13, DECRYPT, tsec_keys.tsec, eks_keyseeds[0]);
se_aes_unwrap_key(15, 14, tsec_keys.tsec); se_aes_unwrap_key(15, 14, tsec_keys.tsec);
se_aes_crypt_ecb(13, DECRYPT, tsec_keys.tsec, eks_keyseeds[mkey], SE_KEY_128_SIZE); se_aes_crypt_block_ecb(13, DECRYPT, tsec_keys.tsec, eks_keyseeds[mkey]);
se_aes_unwrap_key(13, 14, tsec_keys.tsec); se_aes_unwrap_key(13, 14, tsec_keys.tsec);
// Clear SBK. // Clear SBK.
@@ -481,21 +483,21 @@ static int _hos_keygen(pkg1_eks_t *eks, u32 mkey, tsec_ctxt_t *tsec_ctxt, bool s
// Verify eks CMAC. // Verify eks CMAC.
u8 cmac[SE_KEY_128_SIZE]; u8 cmac[SE_KEY_128_SIZE];
se_aes_unwrap_key(11, 13, cmac_keyseed); se_aes_unwrap_key(11, 13, cmac_keyseed);
se_aes_hash_cmac(cmac, SE_KEY_128_SIZE, 11, (void *)eks->ctr, sizeof(eks->ctr) + sizeof(eks->keys)); se_aes_cmac(cmac, SE_KEY_128_SIZE, 11, (void *)eks->ctr, sizeof(eks->ctr) + sizeof(eks->keys));
if (!memcmp(eks->cmac, cmac, SE_KEY_128_SIZE)) if (!memcmp(eks->cmac, cmac, SE_KEY_128_SIZE))
return 0; return 0;
*/ */
se_aes_crypt_ecb(13, DECRYPT, tsec_keys.tsec, cmac_keyseed, SE_KEY_128_SIZE); se_aes_crypt_block_ecb(13, DECRYPT, tsec_keys.tsec, cmac_keyseed);
se_aes_unwrap_key(11, 13, cmac_keyseed); se_aes_unwrap_key(11, 13, cmac_keyseed);
// Decrypt eks and set keyslots. // Decrypt eks and set keyslots.
se_aes_crypt_ctr(13, &eks->keys, &eks->keys, sizeof(eks_keys_t), eks->ctr); se_aes_crypt_ctr(13, &eks->keys, sizeof(eks_keys_t), &eks->keys, sizeof(eks_keys_t), eks->ctr);
se_aes_key_set(11, eks->keys.package1_key, SE_KEY_128_SIZE); se_aes_key_set(11, eks->keys.package1_key, SE_KEY_128_SIZE);
se_aes_key_set(12, eks->keys.master_kekseed, SE_KEY_128_SIZE); se_aes_key_set(12, eks->keys.master_kekseed, SE_KEY_128_SIZE);
se_aes_key_set(13, eks->keys.master_kekseed, SE_KEY_128_SIZE); se_aes_key_set(13, eks->keys.master_kekseed, SE_KEY_128_SIZE);
se_aes_crypt_ecb(12, DECRYPT, tsec_keys.tsec, master_keyseed_retail, SE_KEY_128_SIZE); se_aes_crypt_block_ecb(12, DECRYPT, tsec_keys.tsec, master_keyseed_retail);
if (!is_exo) if (!is_exo)
{ {
@@ -666,7 +668,7 @@ static bool _get_fs_exfat_compatible(link_t *info, u32 *hos_revision)
if (strcmp((char *)ki->kip1->name, "FS")) if (strcmp((char *)ki->kip1->name, "FS"))
continue; continue;
if (!se_sha_hash_256_oneshot(sha_buf, ki->kip1, ki->size)) if (!se_calc_sha256_oneshot(sha_buf, ki->kip1, ki->size))
break; break;
pkg2_get_ids(&kip_ids, &fs_ids_cnt); pkg2_get_ids(&kip_ids, &fs_ids_cnt);
@@ -726,8 +728,14 @@ void hos_launch(ini_sec_t *cfg)
goto error; goto error;
} }
if (emusd_storage_init_mmc() || !emusd_mount()) {
_hos_crit_error("error: Failed to init emuSD.");
goto error;
}
// Check if SD Card is GPT. // Check if SD Card is GPT.
if (sd_is_gpt()) if (emusd_is_gpt())
{ {
_hos_crit_error("SD has GPT only! Run Fix Hybrid MBR!"); _hos_crit_error("SD has GPT only! Run Fix Hybrid MBR!");
goto error; goto error;
@@ -746,6 +754,8 @@ void hos_launch(ini_sec_t *cfg)
// Check if stock is enabled and device can boot in OFW. // Check if stock is enabled and device can boot in OFW.
if (ctxt.stock && (h_cfg.t210b01 || !tools_autorcm_enabled())) if (ctxt.stock && (h_cfg.t210b01 || !tools_autorcm_enabled()))
{ {
emusd_storage_end();
emummc_storage_end();
emmc_end(); emmc_end();
WPRINTF("\nRebooting to OFW in 5s..."); WPRINTF("\nRebooting to OFW in 5s...");
@@ -758,7 +768,8 @@ void hos_launch(ini_sec_t *cfg)
mkey = ctxt.pkg1_id->mkey; mkey = ctxt.pkg1_id->mkey;
bool emummc_enabled = emu_cfg.enabled && !h_cfg.emummc_force_disable; // TODO: separate force_disable for emuSD?
bool emummc_enabled = (emu_cfg.enabled || emu_sd_cfg.enabled) && !h_cfg.emummc_force_disable;
// Enable emummc patching. // Enable emummc patching.
if (emummc_enabled) if (emummc_enabled)
@@ -839,7 +850,7 @@ void hos_launch(ini_sec_t *cfg)
if (h_cfg.t210b01) if (h_cfg.t210b01)
{ {
u32 bek_vector[4] = {0}; u32 bek_vector[4] = {0};
se_aes_crypt_ecb(13, ENCRYPT, bek_vector, bek_vector, SE_KEY_128_SIZE); se_aes_crypt_ecb(13, ENCRYPT, bek_vector, SE_KEY_128_SIZE, bek_vector, SE_KEY_128_SIZE);
if (bek_vector[0] == 0x59C14895) // Encrypted zeroes first 32bits. if (bek_vector[0] == 0x59C14895) // Encrypted zeroes first 32bits.
EPRINTF("Pkg1 corrupt?"); EPRINTF("Pkg1 corrupt?");
else else
@@ -947,9 +958,9 @@ void hos_launch(ini_sec_t *cfg)
// Hash only Kernel when it embeds INI1. // Hash only Kernel when it embeds INI1.
u8 kernel_hash[0x20]; u8 kernel_hash[0x20];
if (!ctxt.new_pkg2) if (!ctxt.new_pkg2)
se_sha_hash_256_oneshot(kernel_hash, ctxt.kernel, ctxt.kernel_size); se_calc_sha256_oneshot(kernel_hash, ctxt.kernel, ctxt.kernel_size);
else else
se_sha_hash_256_oneshot(kernel_hash, ctxt.kernel + PKG2_NEWKERN_START, se_calc_sha256_oneshot(kernel_hash, ctxt.kernel + PKG2_NEWKERN_START,
pkg2_newkern_ini1_start - PKG2_NEWKERN_START); pkg2_newkern_ini1_start - PKG2_NEWKERN_START);
ctxt.pkg2_kernel_id = pkg2_identify(kernel_hash); ctxt.pkg2_kernel_id = pkg2_identify(kernel_hash);
@@ -989,12 +1000,12 @@ void hos_launch(ini_sec_t *cfg)
LIST_FOREACH_ENTRY(merge_kip_t, mki, &ctxt.kip1_list, link) LIST_FOREACH_ENTRY(merge_kip_t, mki, &ctxt.kip1_list, link)
pkg2_merge_kip(&kip1_info, (pkg2_kip1_t *)mki->kip1); pkg2_merge_kip(&kip1_info, (pkg2_kip1_t *)mki->kip1);
// Check if FS is compatible with exFAT and if 5.1.0 or 10.2.0. // Check if FS is compatible with exFAT and if 5.1.0.
if (!ctxt.stock && (sd_fs.fs_type == FS_EXFAT || mkey == HOS_MKEY_VER_500 || ctxt.pkg1_id->fuses == 13)) if (!ctxt.stock && (sd_fs.fs_type == FS_EXFAT || mkey == HOS_MKEY_VER_500 || ctxt.pkg1_id->fuses == 13))
{ {
bool exfat_compat = _get_fs_exfat_compatible(&kip1_info, &ctxt.exo_ctx.hos_revision); bool exfat_compat = _get_fs_exfat_compatible(&kip1_info, &ctxt.exo_ctx.hos_revision);
if (sd_fs.fs_type == FS_EXFAT && !exfat_compat) if (emusd_get_fs_type() == FS_EXFAT && !exfat_compat)
{ {
_hos_crit_error("SD Card is exFAT but installed HOS driver\nonly supports FAT32!"); _hos_crit_error("SD Card is exFAT but installed HOS driver\nonly supports FAT32!");
@@ -1008,14 +1019,14 @@ void hos_launch(ini_sec_t *cfg)
{ {
EHPRINTFARGS("Failed to apply '%s'!", failed_patch); EHPRINTFARGS("Failed to apply '%s'!", failed_patch);
bool emu_patch_failed = !strcmp(failed_patch, "emummc"); bool emmc_patch_failed = !strcmp(failed_patch, "emummc");
if (!emu_patch_failed) if (!emmc_patch_failed)
{ {
gfx_puts("\nPress POWER to continue.\nPress VOL to go to the menu.\n"); gfx_puts("\nPress POWER to continue.\nPress VOL to go to the menu.\n");
display_backlight_brightness(h_cfg.backlight, 1000); display_backlight_brightness(h_cfg.backlight, 1000);
} }
if (emu_patch_failed || !(btn_wait() & BTN_POWER)) if (emmc_patch_failed || !(btn_wait() & BTN_POWER))
goto error; // MUST stop here, because if user requests 'nogc' but it's not applied, their GC controller gets updated! goto error; // MUST stop here, because if user requests 'nogc' but it's not applied, their GC controller gets updated!
} }
@@ -1027,6 +1038,9 @@ void hos_launch(ini_sec_t *cfg)
config_exosphere(&ctxt, warmboot_base); config_exosphere(&ctxt, warmboot_base);
// Unmount SD card and eMMC. // Unmount SD card and eMMC.
emummc_storage_end();
emusd_storage_end();
boot_storage_end();
sd_end(); sd_end();
emmc_end(); emmc_end();
@@ -1127,6 +1141,8 @@ void hos_launch(ini_sec_t *cfg)
error: error:
_free_launch_components(&ctxt); _free_launch_components(&ctxt);
emummc_storage_end();
emusd_storage_end();
emmc_end(); emmc_end();
EPRINTF("\nFailed to launch HOS!"); EPRINTF("\nFailed to launch HOS!");

View File

@@ -15,6 +15,8 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <storage/boot_storage.h>
#include "../storage/emusd.h"
#include <string.h> #include <string.h>
#include <bdk.h> #include <bdk.h>
@@ -29,7 +31,7 @@
static int _config_warmboot(launch_ctxt_t *ctxt, const char *value) static int _config_warmboot(launch_ctxt_t *ctxt, const char *value)
{ {
ctxt->warmboot = sd_file_read(value, &ctxt->warmboot_size); ctxt->warmboot = emusd_file_read(value, &ctxt->warmboot_size);
if (!ctxt->warmboot) if (!ctxt->warmboot)
return 0; return 0;
@@ -38,7 +40,7 @@ static int _config_warmboot(launch_ctxt_t *ctxt, const char *value)
static int _config_secmon(launch_ctxt_t *ctxt, const char *value) static int _config_secmon(launch_ctxt_t *ctxt, const char *value)
{ {
ctxt->secmon = sd_file_read(value, &ctxt->secmon_size); ctxt->secmon = emusd_file_read(value, &ctxt->secmon_size);
if (!ctxt->secmon) if (!ctxt->secmon)
return 0; return 0;
@@ -47,7 +49,7 @@ static int _config_secmon(launch_ctxt_t *ctxt, const char *value)
static int _config_kernel(launch_ctxt_t *ctxt, const char *value) static int _config_kernel(launch_ctxt_t *ctxt, const char *value)
{ {
ctxt->kernel = sd_file_read(value, &ctxt->kernel_size); ctxt->kernel = emusd_file_read(value, &ctxt->kernel_size);
if (!ctxt->kernel) if (!ctxt->kernel)
return 0; return 0;
@@ -61,11 +63,12 @@ static int _config_kip1(launch_ctxt_t *ctxt, const char *value)
if (value[strlen(value) - 1] == '*') if (value[strlen(value) - 1] == '*')
{ {
char *dir = (char *)malloc(256); char *dir = (char *)malloc(256);
strcpy(dir, value); strcpy(dir, "emusd:");
strcat(dir, value);
u32 dirlen = 0; u32 dirlen = 0;
dir[strlen(dir) - 2] = 0; dir[strlen(dir) - 2] = 0;
dirlist_t *filelist = dirlist(dir, "*.kip*", 0); dirlist_t *filelist = dirlist(dir, "*.kip*", false, false);
strcat(dir, "/"); strcat(dir, "/");
dirlen = strlen(dir); dirlen = strlen(dir);
@@ -81,7 +84,7 @@ static int _config_kip1(launch_ctxt_t *ctxt, const char *value)
strcpy(dir + dirlen, filelist->name[i]); strcpy(dir + dirlen, filelist->name[i]);
merge_kip_t *mkip1 = (merge_kip_t *)malloc(sizeof(merge_kip_t)); merge_kip_t *mkip1 = (merge_kip_t *)malloc(sizeof(merge_kip_t));
mkip1->kip1 = sd_file_read(dir, &size); mkip1->kip1 = emusd_file_read(dir + 6, &size);
if (!mkip1->kip1) if (!mkip1->kip1)
{ {
free(mkip1); free(mkip1);
@@ -103,7 +106,7 @@ static int _config_kip1(launch_ctxt_t *ctxt, const char *value)
else else
{ {
merge_kip_t *mkip1 = (merge_kip_t *)malloc(sizeof(merge_kip_t)); merge_kip_t *mkip1 = (merge_kip_t *)malloc(sizeof(merge_kip_t));
mkip1->kip1 = sd_file_read(value, &size); mkip1->kip1 = emusd_file_read(value, &size);
if (!mkip1->kip1) if (!mkip1->kip1)
{ {
free(mkip1); free(mkip1);
@@ -169,7 +172,7 @@ static int _config_stock(launch_ctxt_t *ctxt, const char *value)
{ {
if (*value == '1') if (*value == '1')
{ {
DPRINTF("Enabled stock mode\n"); DPRINTF("Disabled all patching\n");
ctxt->stock = true; ctxt->stock = true;
} }
return 1; return 1;
@@ -262,7 +265,7 @@ static int _config_pkg3(launch_ctxt_t *ctxt, const char *value)
static int _config_exo_fatal_payload(launch_ctxt_t *ctxt, const char *value) static int _config_exo_fatal_payload(launch_ctxt_t *ctxt, const char *value)
{ {
ctxt->exofatal = sd_file_read(value, &ctxt->exofatal_size); ctxt->exofatal = emusd_file_read(value, &ctxt->exofatal_size);
if (!ctxt->exofatal) if (!ctxt->exofatal)
return 0; return 0;

View File

@@ -17,6 +17,8 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <storage/boot_storage.h>
#include "../storage/emusd.h"
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
@@ -205,7 +207,7 @@ int pkg1_decrypt(const pkg1_id_t *id, u8 *pkg1)
u8 *pkg11 = pkg1 + id->pkg11_off; u8 *pkg11 = pkg1 + id->pkg11_off;
u32 pkg11_size = *(u32 *)pkg11; u32 pkg11_size = *(u32 *)pkg11;
hdr = (pk11_hdr_t *)(pkg11 + 0x20); hdr = (pk11_hdr_t *)(pkg11 + 0x20);
se_aes_crypt_ctr(11, hdr, hdr, pkg11_size, pkg11 + 0x10); se_aes_crypt_ctr(11, hdr, pkg11_size, hdr, pkg11_size, pkg11 + 0x10);
} }
else else
{ {
@@ -216,7 +218,7 @@ int pkg1_decrypt(const pkg1_id_t *id, u8 *pkg1)
// Use BEK for T210B01. // Use BEK for T210B01.
// Additionally, skip 0x20 bytes from decryption to maintain the header. // Additionally, skip 0x20 bytes from decryption to maintain the header.
se_aes_iv_clear(13); se_aes_iv_clear(13);
se_aes_crypt_cbc(13, DECRYPT, pkg1 + 0x20, pkg1 + 0x20, oem_hdr->size - 0x20); se_aes_crypt_cbc(13, DECRYPT, pkg1 + 0x20, oem_hdr->size - 0x20, pkg1 + 0x20, oem_hdr->size - 0x20);
} }
// Return if header is valid. // Return if header is valid.

View File

@@ -1,6 +1,6 @@
/* /*
* Copyright (c) 2018 naehrwert * Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2026 CTCaer * Copyright (c) 2018-2025 CTCaer
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@@ -15,6 +15,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <storage/boot_storage.h>
#include <string.h> #include <string.h>
#include <bdk.h> #include <bdk.h>
@@ -27,6 +28,7 @@
#include <libs/compr/blz.h> #include <libs/compr/blz.h>
#include <libs/fatfs/ff.h> #include <libs/fatfs/ff.h>
#include "../storage/emummc.h" #include "../storage/emummc.h"
#include "../storage/emusd.h"
//#define DPRINTF(...) gfx_printf(__VA_ARGS__) //#define DPRINTF(...) gfx_printf(__VA_ARGS__)
#define DPRINTF(...) #define DPRINTF(...)
@@ -64,6 +66,7 @@ static void parse_external_kip_patches()
return; return;
LIST_INIT(ini_kip_sections); LIST_INIT(ini_kip_sections);
// TODO: load frome emusd?
if (ini_patch_parse(&ini_kip_sections, "bootloader/patches.ini")) if (ini_patch_parse(&ini_kip_sections, "bootloader/patches.ini"))
{ {
// Copy ids into a new patchset. // Copy ids into a new patchset.
@@ -374,7 +377,7 @@ static int _kipm_inject(const char *kipm_path, char *target_name, pkg2_kip1_info
if (!strcmp((char *)ki->kip1->name, target_name)) if (!strcmp((char *)ki->kip1->name, target_name))
{ {
u32 size = 0; u32 size = 0;
u8 *kipm_data = (u8 *)sd_file_read(kipm_path, &size); u8 *kipm_data = (u8 *)boot_storage_file_read(kipm_path, &size);
if (!kipm_data) if (!kipm_data)
return 1; return 1;
@@ -544,7 +547,7 @@ const char *pkg2_patch_kips(link_t *info, char *patch_names)
// Check if current KIP not hashed and hash it. // Check if current KIP not hashed and hash it.
if (kip_hash[0] == 0) if (kip_hash[0] == 0)
if (!se_sha_hash_256_oneshot(kip_hash, ki->kip1, ki->size)) if (!se_calc_sha256_oneshot(kip_hash, ki->kip1, ki->size))
memset(kip_hash, 0, sizeof(kip_hash)); memset(kip_hash, 0, sizeof(kip_hash));
// Check if kip is the expected version. // Check if kip is the expected version.
@@ -656,6 +659,8 @@ const char *pkg2_patch_kips(link_t *info, char *patch_names)
if (kip_id_idx > 17) if (kip_id_idx > 17)
emu_cfg.fs_ver -= 2; emu_cfg.fs_ver -= 2;
emu_sd_cfg.fs_ver = emu_cfg.fs_ver;
// Inject emuMMC code. // Inject emuMMC code.
gfx_printf("Injecting emuMMC. FS ID: %d\n", emu_cfg.fs_ver); gfx_printf("Injecting emuMMC. FS ID: %d\n", emu_cfg.fs_ver);
if (_kipm_inject("bootloader/sys/emummc.kipm", "FS", ki)) if (_kipm_inject("bootloader/sys/emummc.kipm", "FS", ki))
@@ -708,7 +713,7 @@ pkg2_hdr_t *pkg2_decrypt(void *data, u8 mkey, bool is_exo)
u8 tmp_mkey[SE_KEY_128_SIZE]; u8 tmp_mkey[SE_KEY_128_SIZE];
// Decrypt 7.0.0 encrypted mkey. // Decrypt 7.0.0 encrypted mkey.
se_aes_crypt_ecb(!is_exo ? 7 : 13, DECRYPT, tmp_mkey, mkey_vector_7xx, SE_KEY_128_SIZE); se_aes_crypt_ecb(!is_exo ? 7 : 13, DECRYPT, tmp_mkey, SE_KEY_128_SIZE, mkey_vector_7xx, SE_KEY_128_SIZE);
// Set and unwrap pkg2 key. // Set and unwrap pkg2 key.
se_aes_key_set(9, tmp_mkey, SE_KEY_128_SIZE); se_aes_key_set(9, tmp_mkey, SE_KEY_128_SIZE);
@@ -718,7 +723,7 @@ pkg2_hdr_t *pkg2_decrypt(void *data, u8 mkey, bool is_exo)
} }
// Decrypt header. // Decrypt header.
se_aes_crypt_ctr(pkg2_keyslot, hdr, hdr, sizeof(pkg2_hdr_t), hdr); se_aes_crypt_ctr(pkg2_keyslot, hdr, sizeof(pkg2_hdr_t), hdr, sizeof(pkg2_hdr_t), hdr);
if (hdr->magic != PKG2_MAGIC) if (hdr->magic != PKG2_MAGIC)
return NULL; return NULL;
@@ -730,7 +735,7 @@ DPRINTF("sec %d has size %08X\n", i, hdr->sec_size[i]);
if (!hdr->sec_size[i]) if (!hdr->sec_size[i])
continue; continue;
se_aes_crypt_ctr(pkg2_keyslot, pdata, pdata, hdr->sec_size[i], hdr->sec_ctr[i]); se_aes_crypt_ctr(pkg2_keyslot, pdata, hdr->sec_size[i], pdata, hdr->sec_size[i], &hdr->sec_ctr[i * SE_AES_IV_SIZE]);
pdata += hdr->sec_size[i]; pdata += hdr->sec_size[i];
} }
@@ -776,7 +781,7 @@ DPRINTF("adding kip1 '%s' @ %08X (%08X)\n", (char *)ki->kip1->name, (u32)ki->kip
{ {
hdr->sec_size[PKG2_SEC_INI1] = ini1_size; hdr->sec_size[PKG2_SEC_INI1] = ini1_size;
hdr->sec_off[PKG2_SEC_INI1] = 0x14080000; hdr->sec_off[PKG2_SEC_INI1] = 0x14080000;
se_aes_crypt_ctr(8, ini1, ini1, ini1_size, hdr->sec_ctr[PKG2_SEC_INI1]); se_aes_crypt_ctr(8, ini1, ini1_size, ini1, ini1_size, &hdr->sec_ctr[PKG2_SEC_INI1 * SE_AES_IV_SIZE]);
} }
else else
{ {
@@ -854,7 +859,7 @@ DPRINTF("%s @ %08X (%08X)\n", is_meso ? "Mesosphere": "kernel",(u32)ctxt->kernel
kernel_size += ini1_size; kernel_size += ini1_size;
} }
hdr->sec_size[PKG2_SEC_KERNEL] = kernel_size; hdr->sec_size[PKG2_SEC_KERNEL] = kernel_size;
se_aes_crypt_ctr(pkg2_keyslot, pdst, pdst, kernel_size, hdr->sec_ctr[PKG2_SEC_KERNEL]); se_aes_crypt_ctr(pkg2_keyslot, pdst, kernel_size, pdst, kernel_size, &hdr->sec_ctr[PKG2_SEC_KERNEL * SE_AES_IV_SIZE]);
pdst += kernel_size; pdst += kernel_size;
DPRINTF("kernel encrypted\n"); DPRINTF("kernel encrypted\n");
@@ -870,7 +875,7 @@ DPRINTF("INI1 encrypted\n");
u8 *pk2_hash_data = (u8 *)dst + 0x100 + sizeof(pkg2_hdr_t); u8 *pk2_hash_data = (u8 *)dst + 0x100 + sizeof(pkg2_hdr_t);
for (u32 i = PKG2_SEC_KERNEL; i <= PKG2_SEC_UNUSED; i++) for (u32 i = PKG2_SEC_KERNEL; i <= PKG2_SEC_UNUSED; i++)
{ {
se_sha_hash_256_oneshot(hdr->sec_sha256[i], (void *)pk2_hash_data, hdr->sec_size[i]); se_calc_sha256_oneshot(&hdr->sec_sha256[SE_SHA_256_SIZE * i], (void *)pk2_hash_data, hdr->sec_size[i]);
pk2_hash_data += hdr->sec_size[i]; pk2_hash_data += hdr->sec_size[i];
} }
} }
@@ -878,7 +883,7 @@ DPRINTF("INI1 encrypted\n");
// Encrypt header. // Encrypt header.
*(u32 *)hdr->ctr = 0x100 + sizeof(pkg2_hdr_t) + kernel_size + ini1_size; *(u32 *)hdr->ctr = 0x100 + sizeof(pkg2_hdr_t) + kernel_size + ini1_size;
hdr->ctr[4] = key_ver; hdr->ctr[4] = key_ver;
se_aes_crypt_ctr(pkg2_keyslot, hdr, hdr, sizeof(pkg2_hdr_t), hdr); se_aes_crypt_ctr(pkg2_keyslot, hdr, sizeof(pkg2_hdr_t), hdr, sizeof(pkg2_hdr_t), hdr);
memset(hdr->ctr, 0 , SE_AES_IV_SIZE); memset(hdr->ctr, 0 , SE_AES_IV_SIZE);
*(u32 *)hdr->ctr = 0x100 + sizeof(pkg2_hdr_t) + kernel_size + ini1_size; *(u32 *)hdr->ctr = 0x100 + sizeof(pkg2_hdr_t) + kernel_size + ini1_size;
hdr->ctr[4] = key_ver; hdr->ctr[4] = key_ver;

View File

@@ -1,6 +1,6 @@
/* /*
* Copyright (c) 2018 naehrwert * Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2026 CTCaer * Copyright (c) 2018-2025 CTCaer
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@@ -71,7 +71,7 @@ enum
typedef struct _pkg2_hdr_t typedef struct _pkg2_hdr_t
{ {
/* 0x000 */ u8 ctr[0x10]; /* 0x000 */ u8 ctr[0x10];
/* 0x010 */ u8 sec_ctr[4][SE_AES_IV_SIZE]; /* 0x010 */ u8 sec_ctr[0x40];
/* 0x050 */ u32 magic; /* 0x050 */ u32 magic;
/* 0x054 */ u32 base; /* 0x054 */ u32 base;
/* 0x058 */ u32 pad0; /* 0x058 */ u32 pad0;
@@ -80,7 +80,7 @@ typedef struct _pkg2_hdr_t
/* 0x05E */ u16 pad1; /* 0x05E */ u16 pad1;
/* 0x060 */ u32 sec_size[4]; /* 0x060 */ u32 sec_size[4];
/* 0x070 */ u32 sec_off[4]; /* 0x070 */ u32 sec_off[4];
/* 0x080 */ u8 sec_sha256[4][SE_SHA_256_SIZE]; /* 0x080 */ u8 sec_sha256[0x80];
/* 0x100 */ u8 data[]; /* 0x100 */ u8 data[];
} pkg2_hdr_t; } pkg2_hdr_t;

View File

@@ -16,6 +16,8 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <storage/boot_storage.h>
#include "../storage/emusd.h"
#include <string.h> #include <string.h>
#include <bdk.h> #include <bdk.h>
@@ -29,7 +31,7 @@
//#define DPRINTF(...) gfx_printf(__VA_ARGS__) //#define DPRINTF(...) gfx_printf(__VA_ARGS__)
#define DPRINTF(...) #define DPRINTF(...)
extern bool is_ipl_updated(void *buf, u32 size, const char *path, bool force); extern bool is_ipl_updated(void *buf, const char *path, bool force);
#define PKG3_KIP_SKIP_MAX 16 #define PKG3_KIP_SKIP_MAX 16
@@ -84,10 +86,9 @@ typedef struct _pkg3_content_t
static void _pkg3_update_r2p() static void _pkg3_update_r2p()
{ {
u32 size = 0; u8 *r2p_payload = emusd_file_read("atmosphere/reboot_payload.bin", NULL);
u8 *r2p_payload = sd_file_read("atmosphere/reboot_payload.bin", &size);
is_ipl_updated(r2p_payload, size, "atmosphere/reboot_payload.bin", h_cfg.updater2p ? true : false); is_ipl_updated(r2p_payload, "emusd:atmosphere/reboot_payload.bin", h_cfg.updater2p ? true : false);
free(r2p_payload); free(r2p_payload);
} }
@@ -125,6 +126,10 @@ static int _pkg3_kip1_skip(char ***pkg3_kip1_skip, u32 *pkg3_kip1_skip_num, char
int parse_pkg3(launch_ctxt_t *ctxt, const char *path) int parse_pkg3(launch_ctxt_t *ctxt, const char *path)
{ {
char *path1 = (char *)malloc(256);
strcpy(path1, "emusd:");
strcat(path1, path);
FIL fp; FIL fp;
char **pkg3_kip1_skip = NULL; char **pkg3_kip1_skip = NULL;
@@ -152,16 +157,25 @@ int parse_pkg3(launch_ctxt_t *ctxt, const char *path)
} }
#ifdef HOS_MARIKO_STOCK_SECMON #ifdef HOS_MARIKO_STOCK_SECMON
if (stock && emummc_disabled && (pkg1_old || h_cfg.t210b01)) if (stock && emummc_disabled && (pkg1_old || h_cfg.t210b01)) {
free(path1);
return 1; return 1;
}
#else #else
if (stock && emummc_disabled && pkg1_old) if (stock && emummc_disabled && pkg1_old) {
free(path1);
return 1; return 1;
}
#endif #endif
// Try to open PKG3. // Try to open PKG3.
if (f_open(&fp, path, FA_READ) != FR_OK) if (f_open(&fp, path1, FA_READ) != FR_OK) {
free(path1);
return 0; return 0;
}
void *pkg3 = malloc(f_size(&fp)); void *pkg3 = malloc(f_size(&fp));
@@ -267,6 +281,7 @@ int parse_pkg3(launch_ctxt_t *ctxt, const char *path)
_pkg3_update_r2p(); _pkg3_update_r2p();
free(pkg3_kip1_skip); free(pkg3_kip1_skip);
free(path1);
return 1; return 1;
} }

View File

@@ -24,12 +24,15 @@
#include "../config.h" #include "../config.h"
#include <libs/fatfs/ff.h> #include <libs/fatfs/ff.h>
#include "../storage/emummc.h" #include "../storage/emummc.h"
#include "../storage/emusd.h"
enum emuMMC_Type enum emuMMC_Type
{ {
emuMMC_None = 0, EmummcType_None = 0,
emuMMC_Partition, EmummcType_Partition_Sd = 1,
emuMMC_File, EmummcType_File_Sd = 2,
EmummcType_Partition_Emmc = 3,
EmummcType_File_Emmc = 4,
emuMMC_MAX emuMMC_MAX
}; };
@@ -64,6 +67,22 @@ typedef struct
emummc_file_config_t file_cfg; emummc_file_config_t file_cfg;
}; };
char nintendo_path[EMUMMC_FILE_PATH_MAX]; char nintendo_path[EMUMMC_FILE_PATH_MAX];
} emummc_emmc_config_t;
typedef struct
{
emummc_base_config_t base_cfg;
union
{
emummc_partition_config_t partition_cfg;
emummc_file_config_t file_cfg;
};
} emummc_sd_config_t;
typedef struct
{
emummc_emmc_config_t emmc_cfg;
emummc_sd_config_t sd_cfg;
} exo_emummc_config_t; } exo_emummc_config_t;
typedef struct _exo_cfg_t typedef struct _exo_cfg_t
@@ -75,7 +94,8 @@ typedef struct _exo_cfg_t
u8 uart_port; u8 uart_port;
u8 uart_invert; u8 uart_invert;
u32 uart_baudrate; u32 uart_baudrate;
u32 rsvd1[2]; u8 memory_mode_auto;
u8 rsvd1[7];
exo_emummc_config_t emummc_cfg; exo_emummc_config_t emummc_cfg;
} exo_cfg_t; } exo_cfg_t;
@@ -206,7 +226,7 @@ void config_exosphere(launch_ctxt_t *ctxt, u32 warmboot_base)
if (!ctxt->stock) if (!ctxt->stock)
{ {
LIST_INIT(ini_exo_sections); LIST_INIT(ini_exo_sections);
if (ini_parse(&ini_exo_sections, "exosphere.ini", false)) if (ini_parse(&ini_exo_sections, "emusd:exosphere.ini", false))
{ {
LIST_FOREACH_ENTRY(ini_sec_t, ini_sec, &ini_exo_sections, link) LIST_FOREACH_ENTRY(ini_sec_t, ini_sec, &ini_exo_sections, link)
{ {
@@ -214,6 +234,7 @@ void config_exosphere(launch_ctxt_t *ctxt, u32 warmboot_base)
if (!(ini_sec->type == INI_CHOICE) || strcmp(ini_sec->name, "exosphere")) if (!(ini_sec->type == INI_CHOICE) || strcmp(ini_sec->name, "exosphere"))
continue; continue;
LIST_FOREACH_ENTRY(ini_kv_t, kv, &ini_sec->kvs, link) LIST_FOREACH_ENTRY(ini_kv_t, kv, &ini_sec->kvs, link)
{ {
if (!strcmp("debugmode_user", kv->key)) if (!strcmp("debugmode_user", kv->key))
@@ -224,12 +245,14 @@ void config_exosphere(launch_ctxt_t *ctxt, u32 warmboot_base)
exo_cfg->uart_invert = atoi(kv->val); exo_cfg->uart_invert = atoi(kv->val);
else if (!strcmp("log_baud_rate", kv->key)) else if (!strcmp("log_baud_rate", kv->key))
exo_cfg->uart_baudrate = atoi(kv->val); exo_cfg->uart_baudrate = atoi(kv->val);
else if (!strcmp("memory_mode_auto", kv->key)) {
exo_cfg->memory_mode_auto = atoi(kv->val);
}
else if (emu_cfg.enabled && !h_cfg.emummc_force_disable) else if (emu_cfg.enabled && !h_cfg.emummc_force_disable)
{ {
if (!strcmp("blank_prodinfo_emummc", kv->key)) if (!strcmp("blank_prodinfo_emummc", kv->key))
cal0_blanking = atoi(kv->val); cal0_blanking = atoi(kv->val);
} } else
else
{ {
if (!strcmp("blank_prodinfo_sysmmc", kv->key)) if (!strcmp("blank_prodinfo_sysmmc", kv->key))
cal0_blanking = atoi(kv->val); cal0_blanking = atoi(kv->val);
@@ -245,7 +268,7 @@ void config_exosphere(launch_ctxt_t *ctxt, u32 warmboot_base)
if (!ctxt->exo_ctx.usb3_force) if (!ctxt->exo_ctx.usb3_force)
{ {
LIST_INIT(ini_sys_sections); LIST_INIT(ini_sys_sections);
if (ini_parse(&ini_sys_sections, "atmosphere/config/system_settings.ini", false)) if (ini_parse(&ini_sys_sections, "emusd:atmosphere/config/system_settings.ini", false))
{ {
LIST_FOREACH_ENTRY(ini_sec_t, ini_sec, &ini_sys_sections, link) LIST_FOREACH_ENTRY(ini_sec_t, ini_sec, &ini_sys_sections, link)
{ {
@@ -314,22 +337,72 @@ void config_exosphere(launch_ctxt_t *ctxt, u32 warmboot_base)
pkg1_warmboot_rsa_mod(warmboot_base); pkg1_warmboot_rsa_mod(warmboot_base);
} }
// By default, disable emuMMC
exo_cfg->emummc_cfg.emmc_cfg.base_cfg.magic = EMUMMC_MAGIC;
exo_cfg->emummc_cfg.emmc_cfg.base_cfg.type = EmummcType_None;
if (emu_cfg.enabled && !h_cfg.emummc_force_disable) if (emu_cfg.enabled && !h_cfg.emummc_force_disable)
{ {
exo_cfg->emummc_cfg.base_cfg.magic = EMUMMC_MAGIC; exo_cfg->emummc_cfg.emmc_cfg.base_cfg.fs_ver = emu_cfg.fs_ver;
exo_cfg->emummc_cfg.base_cfg.type = emu_cfg.sector ? emuMMC_Partition : emuMMC_File; exo_cfg->emummc_cfg.sd_cfg.base_cfg.fs_ver = emu_sd_cfg.fs_ver;
exo_cfg->emummc_cfg.base_cfg.fs_ver = emu_cfg.fs_ver;
exo_cfg->emummc_cfg.base_cfg.id = emu_cfg.id; exo_cfg->emummc_cfg.emmc_cfg.base_cfg.id = emu_cfg.id;
if (emu_cfg.enabled == 4 && emu_cfg.sector) {
// emmc partition based
exo_cfg->emummc_cfg.emmc_cfg.base_cfg.type = EmummcType_Partition_Emmc;
} else if (emu_cfg.enabled == 4 && !emu_cfg.sector) {
// emmc file based
exo_cfg->emummc_cfg.emmc_cfg.base_cfg.type = EmummcType_File_Emmc;
} else if (emu_cfg.enabled == 1 && emu_cfg.sector) {
// sd partition based
exo_cfg->emummc_cfg.emmc_cfg.base_cfg.type = EmummcType_Partition_Sd;
} else if (emu_cfg.enabled == 1 && !emu_cfg.sector) {
// sd file based
exo_cfg->emummc_cfg.emmc_cfg.base_cfg.type = EmummcType_File_Sd;
} else {
// disabled
exo_cfg->emummc_cfg.emmc_cfg.base_cfg.type = EmummcType_None;
}
if (emu_cfg.sector) if (emu_cfg.sector)
exo_cfg->emummc_cfg.partition_cfg.start_sector = emu_cfg.sector; exo_cfg->emummc_cfg.emmc_cfg.partition_cfg.start_sector = emu_cfg.sector;
else else
strcpy((char *)exo_cfg->emummc_cfg.file_cfg.path, emu_cfg.path); strcpy((char *)exo_cfg->emummc_cfg.emmc_cfg.file_cfg.path, emu_cfg.path);
if (!ctxt->stock && emu_cfg.nintendo_path && emu_cfg.nintendo_path[0]) if (!ctxt->stock && emu_cfg.nintendo_path && emu_cfg.nintendo_path[0])
strcpy((char *)exo_cfg->emummc_cfg.nintendo_path, emu_cfg.nintendo_path); strcpy((char *)exo_cfg->emummc_cfg.emmc_cfg.nintendo_path, emu_cfg.nintendo_path);
else else
strcpy((char *)exo_cfg->emummc_cfg.nintendo_path, "Nintendo"); strcpy((char *)exo_cfg->emummc_cfg.emmc_cfg.nintendo_path, "Nintendo");
}
exo_cfg->emummc_cfg.sd_cfg.base_cfg.magic = EMUMMC_MAGIC;
exo_cfg->emummc_cfg.sd_cfg.base_cfg.type = EmummcType_None;
if (emu_sd_cfg.enabled)
{
exo_cfg->emummc_cfg.sd_cfg.base_cfg.fs_ver = emu_sd_cfg.fs_ver;
exo_cfg->emummc_cfg.emmc_cfg.base_cfg.fs_ver = emu_sd_cfg.fs_ver;
exo_cfg->emummc_cfg.sd_cfg.base_cfg.id = emu_sd_cfg.id;
if (emu_sd_cfg.enabled == 4 && emu_sd_cfg.sector) {
// emmc partition based
exo_cfg->emummc_cfg.sd_cfg.base_cfg.type = EmummcType_Partition_Emmc;
} else if (emu_sd_cfg.enabled == 4 && !emu_sd_cfg.sector) {
// emmc file based
exo_cfg->emummc_cfg.sd_cfg.base_cfg.type = EmummcType_File_Emmc;
} else if (emu_sd_cfg.enabled == 1 && emu_sd_cfg.sector) {
// sd partition based
exo_cfg->emummc_cfg.sd_cfg.base_cfg.type = EmummcType_Partition_Sd;
} else if (emu_sd_cfg.enabled == 1 && !emu_sd_cfg.sector) {
// sd file based
exo_cfg->emummc_cfg.sd_cfg.base_cfg.type = EmummcType_File_Sd;
} else {
// disabled
exo_cfg->emummc_cfg.sd_cfg.base_cfg.type = EmummcType_None;
}
if (emu_sd_cfg.sector)
exo_cfg->emummc_cfg.sd_cfg.partition_cfg.start_sector = emu_sd_cfg.sector;
else
strcpy((char *)exo_cfg->emummc_cfg.sd_cfg.file_cfg.path, emu_sd_cfg.path);
} }
// Copy over exosphere fatal for Mariko. // Copy over exosphere fatal for Mariko.

View File

@@ -25,6 +25,7 @@
#include "../hos/pkg1.h" #include "../hos/pkg1.h"
#include "l4t.h" #include "l4t.h"
#include "l4t_config.inl" #include "l4t_config.inl"
#include <storage/boot_storage.h>
/* /*
* API Revision info * API Revision info
@@ -283,7 +284,7 @@ typedef struct _l4t_ctxt_t
} l4t_ctxt_t; } l4t_ctxt_t;
#define DRAM_VDD2_OC_MIN_VOLTAGE 1050 #define DRAM_VDD2_OC_MIN_VOLTAGE 1050
#define DRAM_VDD2_OC_MAX_VOLTAGE 1175 #define DRAM_VDD2_OC_MAX_VOLTAGE 1250
#define DRAM_VDD2Q_OC_MAX_VOLTAGE 1237 #define DRAM_VDD2Q_OC_MAX_VOLTAGE 1237
#define DRAM_VDDQ_OC_MIN_VOLTAGE 550 #define DRAM_VDDQ_OC_MIN_VOLTAGE 550
#define DRAM_VDDQ_OC_MAX_VOLTAGE 650 #define DRAM_VDDQ_OC_MAX_VOLTAGE 650
@@ -1026,7 +1027,9 @@ void launch_l4t(const ini_sec_t *ini_sec, int entry_idx, int is_list, bool t210b
return; return;
// Done loading bootloaders/firmware. // Done loading bootloaders/firmware.
boot_storage_end();
sd_end(); sd_end();
emmc_end();
// We don't need AHB aperture open. // We don't need AHB aperture open.
mc_disable_ahb_redirect(); mc_disable_ahb_redirect();

View File

@@ -7,11 +7,39 @@
/* storage control modules to the FatFs module with a defined API. */ /* storage control modules to the FatFs module with a defined API. */
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
#include <string.h> #include "../../storage/emusd.h"
#include <storage/sd.h>
#include <storage/sdmmc.h>
#include <bdk.h> #include <bdk.h>
#include <libs/fatfs/diskio.h> /* FatFs lower layer API */ #include <libs/fatfs/diskio.h> /* FatFs lower layer API */
#include <fatfs_cfg.h>
static bool ensure_partition(BYTE pdrv){
u8 part;
switch(pdrv){
case DRIVE_SD:
return true;
case DRIVE_BOOT1:
case DRIVE_BOOT1_1MB:
part = EMMC_BOOT1;
break;
case DRIVE_EMMC:
part = EMMC_GPP;
break;
case DRIVE_EMUSD:
return true;
default:
return false;
}
if(emmc_storage.partition != part){
return emmc_set_partition(part);
}
return true;
}
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
/* Get Drive Status */ /* Get Drive Status */
@@ -43,7 +71,33 @@ DRESULT disk_read (
UINT count /* Number of sectors to read */ UINT count /* Number of sectors to read */
) )
{ {
return sdmmc_storage_read(&sd_storage, sector, count, buff) ? RES_OK : RES_ERROR; if(!ensure_partition(pdrv)){
return RES_ERROR;
}
sdmmc_storage_t *storage = &sd_storage;
u32 actual_sector = sector;
switch(pdrv){
case DRIVE_SD:
break;
case DRIVE_BOOT1:
case DRIVE_EMMC:
storage = &emmc_storage;
break;
case DRIVE_BOOT1_1MB:
storage = &emmc_storage;
actual_sector = sector + (0x100000 / 512);
break;
case DRIVE_EMUSD:
return emusd_storage_read(sector, count, buff) ? RES_OK : RES_ERROR;
break;
default:
return RES_ERROR;
}
return sdmmc_storage_read(storage, actual_sector, count, buff) ? RES_OK : RES_ERROR;
} }
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
@@ -56,7 +110,32 @@ DRESULT disk_write (
UINT count /* Number of sectors to write */ UINT count /* Number of sectors to write */
) )
{ {
return sdmmc_storage_write(&sd_storage, sector, count, (void *)buff) ? RES_OK : RES_ERROR; if(!ensure_partition(pdrv)){
return RES_ERROR;
}
sdmmc_storage_t *storage = &sd_storage;
u32 actual_sector = sector;
switch(pdrv){
case DRIVE_SD:
break;
case DRIVE_BOOT1:
case DRIVE_EMMC:
storage = &emmc_storage;
break;
case DRIVE_BOOT1_1MB:
storage = &emmc_storage;
actual_sector = sector + (0x100000 / 512);
break;
case DRIVE_EMUSD:
return emusd_storage_write(sector, count, (void*)buff) ? RES_OK : RES_ERROR;
default:
return RES_ERROR;
}
return sdmmc_storage_write(storage, actual_sector, count, (void*)buff) ? RES_OK : RES_ERROR;
} }
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/

View File

@@ -168,7 +168,7 @@
*/ */
#define FF_FS_RPATH 0 #define FF_FS_RPATH 2
/* This option configures support for relative path. /* This option configures support for relative path.
/ /
/ 0: Disable relative path and remove related functions. / 0: Disable relative path and remove related functions.
@@ -181,12 +181,12 @@
/ Drive/Volume Configurations / Drive/Volume Configurations
/---------------------------------------------------------------------------*/ /---------------------------------------------------------------------------*/
#define FF_VOLUMES 1 #define FF_VOLUMES 5
/* Number of volumes (logical drives) to be used. (1-10) */ /* Number of volumes (logical drives) to be used. (1-10) */
#define FF_STR_VOLUME_ID 0 #define FF_STR_VOLUME_ID 1
#define FF_VOLUME_STRS "sd" #define FF_VOLUME_STRS "sd", "boot1", "boot1_1mb", "emmc", "emusd"
/* FF_STR_VOLUME_ID switches support for volume ID in arbitrary strings. /* 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 / 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 / number in the path name. FF_VOLUME_STRS defines the volume ID strings for each
@@ -303,5 +303,12 @@
/ included somewhere in the scope of ff.h. */ / included somewhere in the scope of ff.h. */
typedef enum {
DRIVE_SD = 0,
DRIVE_BOOT1 = 1,
DRIVE_BOOT1_1MB = 2,
DRIVE_EMMC = 3,
DRIVE_EMUSD = 4,
} DDRIVE;
/*--- End of configuration options ---*/ /*--- End of configuration options ---*/

View File

@@ -22,6 +22,7 @@
#include <bdk.h> #include <bdk.h>
#include "config.h" #include "config.h"
#include "gfx/gfx.h"
#include "gfx/logos.h" #include "gfx/logos.h"
#include "gfx/tui.h" #include "gfx/tui.h"
#include "hos/hos.h" #include "hos/hos.h"
@@ -31,9 +32,11 @@
#include <libs/compr/blz.h> #include <libs/compr/blz.h>
#include <libs/fatfs/ff.h> #include <libs/fatfs/ff.h>
#include "storage/emummc.h" #include "storage/emummc.h"
#include <storage/boot_storage.h>
#include "frontend/fe_tools.h" #include "frontend/fe_tools.h"
#include "frontend/fe_info.h" #include "frontend/fe_info.h"
#include "storage/emusd.h"
hekate_config h_cfg; hekate_config h_cfg;
boot_cfg_t __attribute__((section ("._boot_cfg"))) b_cfg; boot_cfg_t __attribute__((section ("._boot_cfg"))) b_cfg;
@@ -92,7 +95,6 @@ static void _check_power_off_from_hos()
// This is a safe and unused DRAM region for our payloads. // This is a safe and unused DRAM region for our payloads.
#define RELOC_META_OFF 0x7C #define RELOC_META_OFF 0x7C
#define PATCHED_RELOC_SZ 0x94 #define PATCHED_RELOC_SZ 0x94
#define VERSION_RCFG_OFF 0x120
#define PATCHED_RELOC_STACK 0x40007000 #define PATCHED_RELOC_STACK 0x40007000
#define PATCHED_RELOC_ENTRY 0x40010000 #define PATCHED_RELOC_ENTRY 0x40010000
#define EXT_PAYLOAD_ADDR 0xC0000000 #define EXT_PAYLOAD_ADDR 0xC0000000
@@ -110,7 +112,7 @@ static void _reloc_append(u32 payload_dst, u32 payload_src, u32 payload_size)
relocator->ep = payload_dst; relocator->ep = payload_dst;
} }
bool is_ipl_updated(void *buf, u32 size, const char *path, bool force) bool is_ipl_updated(void *buf, const char *path, bool force)
{ {
ipl_ver_meta_t *update_ft = (ipl_ver_meta_t *)(buf + PATCHED_RELOC_SZ + sizeof(boot_cfg_t)); ipl_ver_meta_t *update_ft = (ipl_ver_meta_t *)(buf + PATCHED_RELOC_SZ + sizeof(boot_cfg_t));
@@ -120,32 +122,28 @@ bool is_ipl_updated(void *buf, u32 size, const char *path, bool force)
// Check if newer version. // Check if newer version.
if (!force && magic_valid) if (!force && magic_valid)
{
// Copy reserved config.
if (size && !is_valid_old && memcmp((u8 *)(IPL_LOAD_ADDR + VERSION_RCFG_OFF), (u8 *)(buf + VERSION_RCFG_OFF), sizeof(rsvd_cfg_t)))
{
memcpy((u8 *)(buf + VERSION_RCFG_OFF), (u8 *)(IPL_LOAD_ADDR + VERSION_RCFG_OFF), sizeof(rsvd_cfg_t));
sd_save_to_file(buf, size, path);
}
if (byte_swap_32(update_ft->version) > byte_swap_32(ipl_ver.version)) if (byte_swap_32(update_ft->version) > byte_swap_32(ipl_ver.version))
return false; return false;
}
// Update if old or broken. // Update if old or broken.
if (force_update || is_valid_old) if (force_update || is_valid_old)
{ {
boot_cfg_t tmp_cfg; FIL fp;
reloc_meta_t *reloc = (reloc_meta_t *)(IPL_LOAD_ADDR + RELOC_META_OFF); reloc_meta_t *reloc = (reloc_meta_t *)(IPL_LOAD_ADDR + RELOC_META_OFF);
boot_cfg_t *tmp_cfg = zalloc(sizeof(boot_cfg_t));
f_open(&fp, path, FA_WRITE | FA_CREATE_ALWAYS);
f_write(&fp, (u8 *)reloc->start, reloc->end - reloc->start, NULL);
// Write needed tag in case injected ipl uses old versioning.
f_write(&fp, "ICTC49", 6, NULL);
// Reset boot storage configuration. // Reset boot storage configuration.
memcpy(&tmp_cfg, (u8 *)(reloc->start + PATCHED_RELOC_SZ), sizeof(boot_cfg_t)); f_lseek(&fp, PATCHED_RELOC_SZ);
memset((u8 *)(reloc->start + PATCHED_RELOC_SZ), 0, sizeof(boot_cfg_t)); f_write(&fp, tmp_cfg, sizeof(boot_cfg_t), NULL);
sd_save_to_file((u8 *)reloc->start, reloc->end - reloc->start, path); f_close(&fp);
free(tmp_cfg);
// Restore boot storage configuration.
memcpy((u8 *)(reloc->start + PATCHED_RELOC_SZ), &tmp_cfg, sizeof(boot_cfg_t));
} }
return true; return true;
@@ -157,10 +155,8 @@ static void _launch_payload(char *path, bool update, bool clear_screen)
gfx_clear_grey(0x1B); gfx_clear_grey(0x1B);
gfx_con_setpos(0, 0); gfx_con_setpos(0, 0);
// Read payload. FIL fp;
u32 size = 0; if (f_open(&fp, path, FA_READ))
void *buf = sd_file_read(path, &size);
if (!buf)
{ {
gfx_con.mute = false; gfx_con.mute = false;
EPRINTFARGS("Payload file is missing!\n(%s)", path); EPRINTFARGS("Payload file is missing!\n(%s)", path);
@@ -168,8 +164,9 @@ static void _launch_payload(char *path, bool update, bool clear_screen)
goto out; goto out;
} }
if (update && is_ipl_updated(buf, size, path, false)) // Read and copy the payload to our chosen address
goto out; void *buf;
u32 size = f_size(&fp);
// Check if it safely fits IRAM. // Check if it safely fits IRAM.
if (size > 0x30000) if (size > 0x30000)
@@ -180,7 +177,21 @@ static void _launch_payload(char *path, bool update, bool clear_screen)
goto out; goto out;
} }
if (f_read(&fp, buf, size, NULL))
{
f_close(&fp);
goto out;
}
f_close(&fp);
if (update && is_ipl_updated(buf, path, false))
goto out;
boot_storage_end();
sd_end(); sd_end();
emmc_end();
// Copy the payload to our chosen address. // Copy the payload to our chosen address.
memcpy((void *)RCM_PAYLOAD_ADDR, buf, size); memcpy((void *)RCM_PAYLOAD_ADDR, buf, size);
@@ -209,7 +220,6 @@ static void _launch_payload(char *path, bool update, bool clear_screen)
(*payload_ptr)(); (*payload_ptr)();
out: out:
free(buf);
if (!update) if (!update)
{ {
gfx_con.mute = false; gfx_con.mute = false;
@@ -228,15 +238,15 @@ static void _launch_payloads()
gfx_clear_grey(0x1B); gfx_clear_grey(0x1B);
gfx_con_setpos(0, 0); gfx_con_setpos(0, 0);
if (!sd_mount()) if (!boot_storage_mount())
goto failed_sd_mount; goto failed_boot_storage_mount;
ments = (ment_t *)malloc(sizeof(ment_t) * (max_entries + 3)); ments = (ment_t *)malloc(sizeof(ment_t) * (max_entries + 3));
dir = (char *)malloc(256); dir = (char *)malloc(256);
memcpy(dir, "bootloader/payloads", 20); memcpy(dir, "bootloader/payloads", 20);
filelist = dirlist(dir, NULL, 0); filelist = dirlist(dir, NULL, false, false);
u32 i = 0; u32 i = 0;
@@ -272,7 +282,7 @@ static void _launch_payloads()
free(ments); free(ments);
free(dir); free(dir);
free(filelist); free(filelist);
sd_end(); boot_storage_end();
return; return;
} }
@@ -288,11 +298,11 @@ static void _launch_payloads()
_launch_payload(dir, false, true); _launch_payload(dir, false, true);
} }
failed_sd_mount: failed_boot_storage_mount:
free(dir); free(dir);
free(ments); free(ments);
free(filelist); free(filelist);
sd_end(); boot_storage_end();
btn_wait(); btn_wait();
} }
@@ -302,6 +312,7 @@ static void _launch_ini_list()
u8 max_entries = 61; u8 max_entries = 61;
char *special_path = NULL; char *special_path = NULL;
char *emummc_path = NULL; char *emummc_path = NULL;
char *emusd_path = NULL;
ment_t *ments = NULL; ment_t *ments = NULL;
ini_sec_t *cfg_sec = NULL; ini_sec_t *cfg_sec = NULL;
@@ -310,7 +321,7 @@ static void _launch_ini_list()
gfx_clear_grey(0x1B); gfx_clear_grey(0x1B);
gfx_con_setpos(0, 0); gfx_con_setpos(0, 0);
if (!sd_mount()) if (!boot_storage_mount())
goto parse_failed; goto parse_failed;
// Check that ini files exist and parse them. // Check that ini files exist and parse them.
@@ -366,13 +377,22 @@ static void _launch_ini_list()
h_cfg.emummc_force_disable = atoi(kv->val); h_cfg.emummc_force_disable = atoi(kv->val);
else if (!strcmp("emupath", kv->key)) else if (!strcmp("emupath", kv->key))
emummc_path = kv->val; emummc_path = kv->val;
else if (!strcmp("emusdpath", kv->key))
emusd_path = kv->val;
} }
// TODO: also check emuSD path
if (emummc_path && !emummc_set_path(emummc_path)) if (emummc_path && !emummc_set_path(emummc_path))
{ {
EPRINTF("emupath is wrong!"); EPRINTF("emupath is wrong!");
goto wrong_emupath; goto wrong_emupath;
} }
if (emusd_path && !emusd_set_path(emusd_path)){
EPRINTFARGS("path: %s", emusd_path);
EPRINTF("error: emusdpath is wrong!");
goto wrong_emupath;
}
} }
if (!cfg_sec) if (!cfg_sec)
@@ -415,9 +435,15 @@ parse_failed:
wrong_emupath: wrong_emupath:
if (emummc_path) if (emummc_path)
{ {
sd_mount(); boot_storage_mount();
emummc_load_cfg(); // Reload emuMMC config in case of emupath. emummc_load_cfg(); // Reload emuMMC config in case of emupath.
} }
if (emusd_path)
{
boot_storage_mount();
emusd_load_cfg();
}
} }
out: out:
@@ -431,6 +457,7 @@ static void _launch_config()
u8 max_entries = 61; u8 max_entries = 61;
char *special_path = NULL; char *special_path = NULL;
char *emummc_path = NULL; char *emummc_path = NULL;
char *emusd_path = NULL;
ment_t *ments = NULL; ment_t *ments = NULL;
ini_sec_t *cfg_sec = NULL; ini_sec_t *cfg_sec = NULL;
@@ -440,11 +467,12 @@ static void _launch_config()
gfx_clear_grey(0x1B); gfx_clear_grey(0x1B);
gfx_con_setpos(0, 0); gfx_con_setpos(0, 0);
if (!sd_mount()) if (!boot_storage_mount())
goto parse_failed; goto parse_failed;
// Load emuMMC configuration. // Load emuMMC configuration.
emummc_load_cfg(); emummc_load_cfg();
emusd_load_cfg();
// Parse main configuration. // Parse main configuration.
ini_parse(&ini_sections, "bootloader/hekate_ipl.ini", false); ini_parse(&ini_sections, "bootloader/hekate_ipl.ini", false);
@@ -511,6 +539,8 @@ static void _launch_config()
h_cfg.emummc_force_disable = atoi(kv->val); h_cfg.emummc_force_disable = atoi(kv->val);
if (!strcmp("emupath", kv->key)) if (!strcmp("emupath", kv->key))
emummc_path = kv->val; emummc_path = kv->val;
if (!strcmp("emusdpath", kv->key))
emusd_path = kv->val;
} }
if (emummc_path && !emummc_set_path(emummc_path)) if (emummc_path && !emummc_set_path(emummc_path))
@@ -518,12 +548,19 @@ static void _launch_config()
EPRINTF("emupath is wrong!"); EPRINTF("emupath is wrong!");
goto wrong_emupath; goto wrong_emupath;
} }
if (emusd_path && !emusd_set_path(emusd_path))
{
EPRINTFARGS("path: %s", emusd_path);
EPRINTF("error: emusdpath is wrong!");
goto wrong_emupath;
}
} }
if (!cfg_sec) if (!cfg_sec)
{ {
free(ments); free(ments);
sd_end(); boot_storage_end();
return; return;
} }
@@ -560,13 +597,19 @@ parse_failed:
wrong_emupath: wrong_emupath:
if (emummc_path) if (emummc_path)
{ {
sd_mount(); boot_storage_mount();
emummc_load_cfg(); // Reload emuMMC config in case of emupath. emummc_load_cfg(); // Reload emuMMC config in case of emupath.
} }
if (emusd_path)
{
boot_storage_mount();
emusd_load_cfg();
}
} }
out: out:
sd_end(); boot_storage_end();
free(ments); free(ments);
@@ -579,11 +622,13 @@ out:
static void _nyx_load_run() static void _nyx_load_run()
{ {
u8 *nyx = sd_file_read("bootloader/sys/nyx.bin", NULL); u8 *nyx = boot_storage_file_read("bootloader/sys/nyx.bin", NULL);
if (!nyx) if (!nyx)
return; return;
boot_storage_end();
sd_end(); sd_end();
emmc_end();
render_static_bootlogo(); render_static_bootlogo();
display_backlight_brightness(h_cfg.backlight, 1000); display_backlight_brightness(h_cfg.backlight, 1000);
@@ -652,13 +697,7 @@ static void _nyx_load_run()
(*nyx_ptr)(); (*nyx_ptr)();
} }
void launch_nyx() static ini_sec_t *_get_ini_sec_from_id(ini_sec_t *ini_sec, char **bootlogoCustomEntry, char **emummc_path, char **emusd_path)
{
sd_mount();
_nyx_load_run();
}
static ini_sec_t *_get_ini_sec_from_id(ini_sec_t *ini_sec, char **bootlogoCustomEntry, char **emummc_path)
{ {
ini_sec_t *cfg_sec = NULL; ini_sec_t *cfg_sec = NULL;
@@ -677,10 +716,13 @@ static ini_sec_t *_get_ini_sec_from_id(ini_sec_t *ini_sec, char **bootlogoCustom
*bootlogoCustomEntry = kv->val; *bootlogoCustomEntry = kv->val;
else if (!strcmp("emummc_force_disable", kv->key)) else if (!strcmp("emummc_force_disable", kv->key))
h_cfg.emummc_force_disable = atoi(kv->val); h_cfg.emummc_force_disable = atoi(kv->val);
else if (!strcmp("emusdpath", kv->key))
*emusd_path = kv->val;
} }
if (!cfg_sec) if (!cfg_sec)
{ {
*emummc_path = NULL; *emummc_path = NULL;
*emusd_path = NULL;
*bootlogoCustomEntry = NULL; *bootlogoCustomEntry = NULL;
h_cfg.emummc_force_disable = false; h_cfg.emummc_force_disable = false;
} }
@@ -713,7 +755,7 @@ static void _check_for_updated_bootloader()
else else
{ {
u8 *buf = zalloc(0x200); u8 *buf = zalloc(0x200);
is_ipl_updated(buf, 0, "bootloader/update.bin", true); is_ipl_updated(buf, "bootloader/update.bin", true);
free(buf); free(buf);
} }
} }
@@ -735,9 +777,12 @@ static void _auto_launch()
u32 boot_entry_id = 0; u32 boot_entry_id = 0;
ini_sec_t *cfg_sec = NULL; ini_sec_t *cfg_sec = NULL;
char *emummc_path = NULL; char *emummc_path = NULL;
char *emusd_path = NULL;
char *bootlogoCustomEntry = NULL; char *bootlogoCustomEntry = NULL;
bool config_entry_found = false; bool config_entry_found = false;
_check_for_updated_bootloader();
bool boot_from_id = (b_cfg.boot_cfg & BOOT_CFG_FROM_ID) && (b_cfg.boot_cfg & BOOT_CFG_AUTOBOOT_EN); bool boot_from_id = (b_cfg.boot_cfg & BOOT_CFG_FROM_ID) && (b_cfg.boot_cfg & BOOT_CFG_AUTOBOOT_EN);
if (boot_from_id) if (boot_from_id)
b_cfg.id[7] = 0; b_cfg.id[7] = 0;
@@ -750,6 +795,7 @@ static void _auto_launch()
// Load emuMMC configuration. // Load emuMMC configuration.
emummc_load_cfg(); emummc_load_cfg();
emusd_load_cfg();
// Parse hekate main configuration. // Parse hekate main configuration.
if (!ini_parse(&ini_sections, "bootloader/hekate_ipl.ini", false)) if (!ini_parse(&ini_sections, "bootloader/hekate_ipl.ini", false))
@@ -805,7 +851,7 @@ static void _auto_launch()
} }
if (boot_from_id) if (boot_from_id)
cfg_sec = _get_ini_sec_from_id(ini_sec, &bootlogoCustomEntry, &emummc_path); cfg_sec = _get_ini_sec_from_id(ini_sec, &bootlogoCustomEntry, &emummc_path, &emusd_path);
else if (h_cfg.autoboot == boot_entry_id && config_entry_found) else if (h_cfg.autoboot == boot_entry_id && config_entry_found)
{ {
cfg_sec = ini_sec; cfg_sec = ini_sec;
@@ -815,6 +861,8 @@ static void _auto_launch()
bootlogoCustomEntry = kv->val; bootlogoCustomEntry = kv->val;
else if (!strcmp("emupath", kv->key)) else if (!strcmp("emupath", kv->key))
emummc_path = kv->val; emummc_path = kv->val;
else if (!strcmp("emusdpath", kv->key))
emusd_path = kv->val;
else if (!strcmp("emummc_force_disable", kv->key)) else if (!strcmp("emummc_force_disable", kv->key))
h_cfg.emummc_force_disable = atoi(kv->val); h_cfg.emummc_force_disable = atoi(kv->val);
else if (!strcmp("bootwait", kv->key)) else if (!strcmp("bootwait", kv->key))
@@ -851,7 +899,7 @@ static void _auto_launch()
continue; continue;
if (boot_from_id) if (boot_from_id)
cfg_sec = _get_ini_sec_from_id(ini_sec_list, &bootlogoCustomEntry, &emummc_path); cfg_sec = _get_ini_sec_from_id(ini_sec_list, &bootlogoCustomEntry, &emummc_path, &emusd_path);
else if (h_cfg.autoboot == boot_entry_id) else if (h_cfg.autoboot == boot_entry_id)
{ {
h_cfg.emummc_force_disable = false; h_cfg.emummc_force_disable = false;
@@ -862,6 +910,8 @@ static void _auto_launch()
bootlogoCustomEntry = kv->val; bootlogoCustomEntry = kv->val;
else if (!strcmp("emupath", kv->key)) else if (!strcmp("emupath", kv->key))
emummc_path = kv->val; emummc_path = kv->val;
else if (!strcmp("emusdpath", kv->key))
emusd_path = kv->val;
else if (!strcmp("emummc_force_disable", kv->key)) else if (!strcmp("emummc_force_disable", kv->key))
h_cfg.emummc_force_disable = atoi(kv->val); h_cfg.emummc_force_disable = atoi(kv->val);
else if (!strcmp("bootwait", kv->key)) else if (!strcmp("bootwait", kv->key))
@@ -892,11 +942,11 @@ skip_list:
// Check if user set custom logo path at the boot entry. // Check if user set custom logo path at the boot entry.
if (bootlogoCustomEntry) if (bootlogoCustomEntry)
bitmap = (u8 *)sd_file_read(bootlogoCustomEntry, &fsize); bitmap = (u8 *)boot_storage_file_read(bootlogoCustomEntry, &fsize);
// Custom entry bootlogo not found, trying default custom one. // Custom entry bootlogo not found, trying default custom one.
if (!bitmap) if (!bitmap)
bitmap = (u8 *)sd_file_read("bootloader/bootlogo.bmp", &fsize); bitmap = (u8 *)boot_storage_file_read("bootloader/bootlogo.bmp", &fsize);
if (bitmap) if (bitmap)
{ {
@@ -975,6 +1025,7 @@ skip_list:
} }
else else
{ {
// TODO: add boot_cfg for emusd
if (b_cfg.boot_cfg & BOOT_CFG_TO_EMUMMC) if (b_cfg.boot_cfg & BOOT_CFG_TO_EMUMMC)
emummc_set_path(b_cfg.emummc_path); emummc_set_path(b_cfg.emummc_path);
else if (emummc_path && !emummc_set_path(emummc_path)) else if (emummc_path && !emummc_set_path(emummc_path))
@@ -984,15 +1035,29 @@ skip_list:
goto wrong_emupath; goto wrong_emupath;
} }
if (emusd_path && !emusd_set_path(emusd_path))
{
gfx_con.mute = false;
EPRINTFARGS("path: %s", emusd_path);
EPRINTF("error: emusdpath is wrong!");
goto wrong_emupath;
}
hos_launch(cfg_sec); hos_launch(cfg_sec);
wrong_emupath: wrong_emupath:
if (emummc_path || b_cfg.boot_cfg & BOOT_CFG_TO_EMUMMC) 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. emummc_load_cfg(); // Reload emuMMC config in case of emupath.
} }
if (emusd_path)
{
boot_storage_mount();
emusd_load_cfg();
}
error: error:
gfx_con.mute = false; gfx_con.mute = false;
gfx_printf("\nPress any key...\n"); gfx_printf("\nPress any key...\n");
@@ -1157,7 +1222,7 @@ static void _show_errors()
static void _check_low_battery() static void _check_low_battery()
{ {
if (h_cfg.devmode) if (fuse_read_hw_state() == FUSE_NX_HW_STATE_DEV)
goto out; goto out;
int enough_battery; int enough_battery;
@@ -1417,7 +1482,6 @@ ment_t ment_top[] = {
MDEF_MENU("Console info", &menu_cinfo), MDEF_MENU("Console info", &menu_cinfo),
MDEF_CAPTION("---------------", TXT_CLR_GREY_DM), MDEF_CAPTION("---------------", TXT_CLR_GREY_DM),
MDEF_HANDLER("Reload", _ipl_reload), MDEF_HANDLER("Reload", _ipl_reload),
MDEF_HANDLER("Load Nyx", launch_nyx),
MDEF_HANDLER_EX("Reboot (OFW)", &STATE_REBOOT_BYPASS_FUSES, power_set_state_ex), MDEF_HANDLER_EX("Reboot (OFW)", &STATE_REBOOT_BYPASS_FUSES, power_set_state_ex),
MDEF_HANDLER_EX("Reboot (RCM)", &STATE_REBOOT_RCM, power_set_state_ex), MDEF_HANDLER_EX("Reboot (RCM)", &STATE_REBOOT_RCM, power_set_state_ex),
MDEF_HANDLER_EX("Power off", &STATE_POWER_OFF, power_set_state_ex), MDEF_HANDLER_EX("Power off", &STATE_POWER_OFF, power_set_state_ex),
@@ -1450,12 +1514,12 @@ void ipl_main()
uart_wait_xfer(DEBUG_UART_PORT, UART_TX_IDLE); uart_wait_xfer(DEBUG_UART_PORT, UART_TX_IDLE);
#endif #endif
// Set bootloader's default configuration.
set_default_configuration();
// Check if battery is enough. // Check if battery is enough.
_check_low_battery(); _check_low_battery();
// Set bootloader's default configuration.
set_default_configuration();
// Prep RTC regs for read. Needed for T210B01 R2C. // Prep RTC regs for read. Needed for T210B01 R2C.
max77620_rtc_prep_read(); max77620_rtc_prep_read();
@@ -1466,7 +1530,8 @@ void ipl_main()
bpmp_clk_rate_set(h_cfg.t210b01 ? ipl_ver.rcfg.bclk_t210b01 : ipl_ver.rcfg.bclk_t210); bpmp_clk_rate_set(h_cfg.t210b01 ? ipl_ver.rcfg.bclk_t210b01 : ipl_ver.rcfg.bclk_t210);
// Mount SD Card. // 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. // Check if watchdog was fired previously.
if (watchdog_fired()) if (watchdog_fired())
@@ -1506,13 +1571,10 @@ skip_lp0_minerva_config:
// Load saved configuration and auto boot if enabled. // Load saved configuration and auto boot if enabled.
if (!(h_cfg.errors & ERR_SD_BOOT_EN)) if (!(h_cfg.errors & ERR_SD_BOOT_EN))
{
_check_for_updated_bootloader();
_auto_launch(); _auto_launch();
}
// Failed to launch Nyx, unmount SD Card. // Failed to launch Nyx, unmount SD Card.
sd_end(); boot_storage_end();
// Set ram to a freq that doesn't need periodic training. // Set ram to a freq that doesn't need periodic training.
minerva_change_freq(FREQ_800); minerva_change_freq(FREQ_800);

View File

@@ -14,6 +14,9 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <storage/emmc.h>
#include <storage/sd.h>
#include <storage/sdmmc.h>
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
@@ -22,6 +25,7 @@
#include "emummc.h" #include "emummc.h"
#include "../config.h" #include "../config.h"
#include <libs/fatfs/ff.h> #include <libs/fatfs/ff.h>
#include <storage/emummc_file_based.h>
emummc_cfg_t emu_cfg = { 0 }; emummc_cfg_t emu_cfg = { 0 };
@@ -76,33 +80,68 @@ bool emummc_set_path(char *path)
FIL fp; FIL fp;
bool found = false; bool found = false;
strcpy(emu_cfg.emummc_file_based_path, path); // strcpy(emu_cfg.emummc_file_based_path, "sd:");
strcpy(emu_cfg.emummc_file_based_path, "");
strcat(emu_cfg.emummc_file_based_path, path);
strcat(emu_cfg.emummc_file_based_path, "/raw_based"); strcat(emu_cfg.emummc_file_based_path, "/raw_based");
if (!f_open(&fp, emu_cfg.emummc_file_based_path, FA_READ)) if (!f_open(&fp, emu_cfg.emummc_file_based_path, FA_READ))
{ {
if (!f_read(&fp, &emu_cfg.sector, 4, NULL)) if (!f_read(&fp, &emu_cfg.sector, 4, NULL)){
if (emu_cfg.sector) if (emu_cfg.sector){
found = true; found = true;
} emu_cfg.enabled = 1;
else goto out;
{ }
strcpy(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))
{
emu_cfg.sector = 0;
emu_cfg.path = path;
found = true;
} }
} }
if (found) strcpy(emu_cfg.emummc_file_based_path, "");
strcat(emu_cfg.emummc_file_based_path, path);
strcat(emu_cfg.emummc_file_based_path, "/raw_emmc_based");
if (!f_open(&fp, emu_cfg.emummc_file_based_path, FA_READ))
{ {
if (!f_read(&fp, &emu_cfg.sector, 4, NULL)){
if (emu_cfg.sector){
found = true;
emu_cfg.enabled = 4;
goto out;
}
}
}
// strcpy(emu_cfg.emummc_file_based_path, "sd:");
strcpy(emu_cfg.emummc_file_based_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))
{
emu_cfg.sector = 0;
emu_cfg.path = path;
emu_cfg.enabled = 1; emu_cfg.enabled = 1;
found = true;
goto out;
}
// strcpy(emu_cfg.emummc_file_based_path, "sd:");
strcpy(emu_cfg.emummc_file_based_path, "");
strcat(emu_cfg.emummc_file_based_path, path);
strcat(emu_cfg.emummc_file_based_path, "/file_emmc_based");
if (!f_stat(emu_cfg.emummc_file_based_path, NULL))
{
emu_cfg.sector = 0;
emu_cfg.path = path;
emu_cfg.enabled = 4;
found = true;
goto out;
}
out:
if (found)
{
// Get ID from path. // Get ID from path.
u32 id_from_path = 0; u32 id_from_path = 0;
u32 path_size = strlen(path); u32 path_size = strlen(path);
@@ -133,7 +172,7 @@ static int emummc_raw_get_part_off(int part_idx)
int emummc_storage_init_mmc() int emummc_storage_init_mmc()
{ {
FILINFO fno; // FILINFO fno;
emu_cfg.active_part = 0; emu_cfg.active_part = 0;
// Always init eMMC even when in emuMMC. eMMC is needed from the emuMMC driver anyway. // Always init eMMC even when in emuMMC. eMMC is needed from the emuMMC driver anyway.
@@ -143,86 +182,80 @@ int emummc_storage_init_mmc()
if (!emu_cfg.enabled || h_cfg.emummc_force_disable) if (!emu_cfg.enabled || h_cfg.emummc_force_disable)
return 0; return 0;
if (!sd_mount()) bool file_based = false;
goto out;
if (!emu_cfg.sector) if(emu_cfg.enabled == 4){
{ // emmc based
strcpy(emu_cfg.emummc_file_based_path, emu_cfg.path); if(!emu_cfg.sector){
strcat(emu_cfg.emummc_file_based_path, "/eMMC"); // file based
if(!emmc_mount()){
if (f_stat(emu_cfg.emummc_file_based_path, &fno)) gfx_printf("emmc mount fail\n");
{ return 1;
EPRINTF("Failed to open eMMC folder."); }
goto out; strcpy(emu_cfg.emummc_file_based_path, "emmc:");
strcat(emu_cfg.emummc_file_based_path, emu_cfg.path);
strcat(emu_cfg.emummc_file_based_path, "/eMMC/");
file_based = true;
}else{
// raw based
// emmc already initialized
} }
f_chmod(emu_cfg.emummc_file_based_path, AM_ARC, AM_ARC); }else{
// sd based
strcat(emu_cfg.emummc_file_based_path, "/00"); if(!emu_cfg.sector){
if (f_stat(emu_cfg.emummc_file_based_path, &fno)) // file based
{ if(!sd_mount()){
EPRINTF("Failed to open emuMMC rawnand."); return 1;
goto out; }
strcpy(emu_cfg.emummc_file_based_path, "sd:");
strcat(emu_cfg.emummc_file_based_path, emu_cfg.path);
strcat(emu_cfg.emummc_file_based_path, "/eMMC/");
file_based = true;
}else{
// raw based
if(!sd_initialize(false)){
return 1;
}
} }
emu_cfg.file_based_part_size = fno.fsize >> 9; }
if(file_based){
gfx_printf("file based\n");
return emummc_storage_file_based_init(emu_cfg.emummc_file_based_path) == 0;
} }
return 0; return 0;
out:
return 1;
} }
int emummc_storage_end() int emummc_storage_end()
{ {
if (!emu_cfg.enabled || h_cfg.emummc_force_disable) if(!h_cfg.emummc_force_disable && emu_cfg.enabled && !emu_cfg.sector){
emummc_storage_file_based_end();
}
if(!emu_cfg.enabled || h_cfg.emummc_force_disable || emu_cfg.enabled == 4){
emmc_end(); emmc_end();
else }else{
sd_end(); sd_end();
}
return 1; return 1;
} }
int emummc_storage_read(u32 sector, u32 num_sectors, void *buf) int emummc_storage_read(u32 sector, u32 num_sectors, void *buf)
{ {
FIL fp; sdmmc_storage_t *storage = emu_cfg.enabled == 4 ? &emmc_storage : &sd_storage;
// FIL fp;
if (!emu_cfg.enabled || h_cfg.emummc_force_disable) if (!emu_cfg.enabled || h_cfg.emummc_force_disable)
return sdmmc_storage_read(&emmc_storage, sector, num_sectors, buf); return sdmmc_storage_read(&emmc_storage, sector, num_sectors, buf);
else if (emu_cfg.sector) else if (emu_cfg.sector)
{ {
sector += emu_cfg.sector; sector += emu_cfg.sector;
sector += emummc_raw_get_part_off(emu_cfg.active_part) * 0x2000; sector += emummc_raw_get_part_off(emu_cfg.active_part) * 0x2000;
return sdmmc_storage_read(&sd_storage, sector, num_sectors, buf); return sdmmc_storage_read(storage, sector, num_sectors, buf);
} }
else else
{ {
if (!emu_cfg.active_part) return emummc_storage_file_based_read(sector, num_sectors, buf);
{
u32 file_part = sector / emu_cfg.file_based_part_size;
sector = sector % emu_cfg.file_based_part_size;
if (file_part >= 10)
itoa(file_part, emu_cfg.emummc_file_based_path + strlen(emu_cfg.emummc_file_based_path) - 2, 10);
else
{
emu_cfg.emummc_file_based_path[strlen(emu_cfg.emummc_file_based_path) - 2] = '0';
itoa(file_part, emu_cfg.emummc_file_based_path + strlen(emu_cfg.emummc_file_based_path) - 1, 10);
}
}
if (f_open(&fp, emu_cfg.emummc_file_based_path, FA_READ))
{
EPRINTF("Failed to open emuMMC image.");
return 0;
}
f_lseek(&fp, (u64)sector << 9);
if (f_read(&fp, buf, (u64)num_sectors << 9, NULL))
{
EPRINTF("Failed to read emuMMC image.");
f_close(&fp);
return 0;
}
f_close(&fp);
return 1;
} }
return 1; return 1;
@@ -230,72 +263,44 @@ int emummc_storage_read(u32 sector, u32 num_sectors, void *buf)
int emummc_storage_write(u32 sector, u32 num_sectors, void *buf) int emummc_storage_write(u32 sector, u32 num_sectors, void *buf)
{ {
FIL fp; sdmmc_storage_t *storage = emu_cfg.enabled == 4 ? &emmc_storage : &sd_storage;
// FIL fp;
if (!emu_cfg.enabled || h_cfg.emummc_force_disable) if (!emu_cfg.enabled || h_cfg.emummc_force_disable)
return sdmmc_storage_write(&emmc_storage, sector, num_sectors, buf); return sdmmc_storage_write(&emmc_storage, sector, num_sectors, buf);
else if (emu_cfg.sector) else if (emu_cfg.sector)
{ {
sector += emu_cfg.sector; sector += emu_cfg.sector;
sector += emummc_raw_get_part_off(emu_cfg.active_part) * 0x2000; sector += emummc_raw_get_part_off(emu_cfg.active_part) * 0x2000;
return sdmmc_storage_write(&sd_storage, sector, num_sectors, buf); return sdmmc_storage_write(storage, sector, num_sectors, buf);
} }
else else
{ {
if (!emu_cfg.active_part) return emummc_storage_file_based_write(sector, num_sectors, buf);
{
u32 file_part = sector / emu_cfg.file_based_part_size;
sector = sector % emu_cfg.file_based_part_size;
if (file_part >= 10)
itoa(file_part, emu_cfg.emummc_file_based_path + strlen(emu_cfg.emummc_file_based_path) - 2, 10);
else
{
emu_cfg.emummc_file_based_path[strlen(emu_cfg.emummc_file_based_path) - 2] = '0';
itoa(file_part, emu_cfg.emummc_file_based_path + strlen(emu_cfg.emummc_file_based_path) - 1, 10);
}
}
if (f_open(&fp, emu_cfg.emummc_file_based_path, FA_WRITE))
return 0;
f_lseek(&fp, (u64)sector << 9);
if (f_write(&fp, buf, (u64)num_sectors << 9, NULL))
{
f_close(&fp);
return 0;
}
f_close(&fp);
return 1;
} }
} }
int emummc_storage_set_mmc_partition(u32 partition) int emummc_storage_set_mmc_partition(u32 partition)
{ {
emu_cfg.active_part = partition; emu_cfg.active_part = partition;
emmc_set_partition(partition);
if (!emu_cfg.enabled || h_cfg.emummc_force_disable || emu_cfg.sector)
return 1;
else
{
strcpy(emu_cfg.emummc_file_based_path, emu_cfg.path);
strcat(emu_cfg.emummc_file_based_path, "/eMMC");
switch (partition)
{
case 0:
strcat(emu_cfg.emummc_file_based_path, "/00");
break;
case 1:
strcat(emu_cfg.emummc_file_based_path, "/BOOT0");
break;
case 2:
strcat(emu_cfg.emummc_file_based_path, "/BOOT1");
break;
}
if(h_cfg.emummc_force_disable || !emu_cfg.enabled){
emmc_set_partition(partition);
return 1; return 1;
} }
if(!emu_cfg.sector){
emummc_storage_file_base_set_partition(partition);
return 1;
}
if(emu_cfg.enabled != 4){
emmc_set_partition(partition);
}else{
emmc_set_partition(EMMC_GPP);
}
return 1; return 1;
} }
sdmmc_storage_t *emummc_get_storage(){
return emu_cfg.enabled == 4 ? &emmc_storage : &sd_storage;
}

View File

@@ -19,19 +19,6 @@
#include <bdk.h> #include <bdk.h>
typedef enum
{
EMUMMC_TYPE_NONE = 0,
EMUMMC_TYPE_PARTITION = 1,
EMUMMC_TYPE_FILES = 2,
} emummc_type_t;
typedef enum {
EMUMMC_MMC_NAND = 0,
EMUMMC_MMC_SD = 1,
EMUMMC_MMC_GC = 2,
} emummc_mmc_t;
typedef struct _emummc_cfg_t typedef struct _emummc_cfg_t
{ {
int enabled; int enabled;
@@ -55,5 +42,6 @@ int emummc_storage_end();
int emummc_storage_read(u32 sector, u32 num_sectors, void *buf); int emummc_storage_read(u32 sector, u32 num_sectors, void *buf);
int emummc_storage_write(u32 sector, u32 num_sectors, void *buf); int emummc_storage_write(u32 sector, u32 num_sectors, void *buf);
int emummc_storage_set_mmc_partition(u32 partition); int emummc_storage_set_mmc_partition(u32 partition);
sdmmc_storage_t *emummc_get_storage();
#endif #endif

295
bootloader/storage/emusd.c Normal file
View File

@@ -0,0 +1,295 @@
#include "emusd.h"
#include <bdk.h>
#include <storage/boot_storage.h>
#include <storage/emmc.h>
#include <storage/file_based_storage.h>
#include <storage/sd.h>
#include <storage/sdmmc.h>
#include <string.h>
#include <utils/ini.h>
#include <libs/fatfs/ff.h>
#include "../config.h"
#include "gfx_utils.h"
FATFS emusd_fs;
bool emusd_mounted = false;
bool emusd_initialized = false;
emusd_cfg_t emu_sd_cfg = {0};
extern hekate_config h_cfg;
static bool emusd_get_mounted() {
return emusd_mounted;
}
void emusd_load_cfg()
{
emu_sd_cfg.enabled = 0;
emu_sd_cfg.fs_ver = 0;
emu_sd_cfg.id = 0;
emu_sd_cfg.sector = 0;
if(!emu_sd_cfg.path) {
emu_sd_cfg.path = (char*)malloc(0x200);
}
if(!emu_sd_cfg.emummc_file_based_path){
emu_sd_cfg.emummc_file_based_path = (char*)malloc(0x200);
}
LIST_INIT(ini_sections);
if(ini_parse(&ini_sections, "emuSD/emusd.ini", false))
{
LIST_FOREACH_ENTRY(ini_sec_t, ini_sec, &ini_sections, link)
{
if(ini_sec->type == INI_CHOICE)
{
if(strcmp(ini_sec->name, "emusd")){
continue;
}
LIST_FOREACH_ENTRY(ini_kv_t, kv, &ini_sec->kvs, link)
{
if(!strcmp(kv->key, "enabled")){
emu_sd_cfg.enabled = atoi(kv->val);
} else if(!strcmp(kv->key, "sector")){
emu_sd_cfg.sector = strtol(kv->val, NULL, 16);
} else if(!strcmp(kv->key, "path")){
emu_sd_cfg.path = kv->val;
}
}
break;
}
}
}
}
bool emusd_mount() {
if (emusd_mounted) {
return true;
}
if (emusd_storage_init_mmc()){
return false;
}
int res = f_mount(&emusd_fs, "emusd:", 1);
if(res) {
EPRINTFARGS("emusd mount fail %d", res);
return false;
}
return true;
}
bool emusd_unmount() {
f_mount(NULL, "emusd:", 1);
emusd_mounted = false;
return true;
}
bool emusd_set_path(char *path) {
FIL fp;
bool found = false;
// TODO: use emu_sd.file_path instead
strcat(emu_sd_cfg.emummc_file_based_path, "");
strcpy(emu_sd_cfg.emummc_file_based_path, path);
strcat(emu_sd_cfg.emummc_file_based_path, "/raw_emmc_based");
if(!f_open(&fp, emu_sd_cfg.emummc_file_based_path, FA_READ))
{
if(!f_read(&fp, &emu_sd_cfg.sector, 4, NULL)){
if(emu_sd_cfg.sector){
found = true;
emu_sd_cfg.enabled = 4;
goto out;
}
}
}
strcpy(emu_sd_cfg.emummc_file_based_path, "");
strcat(emu_sd_cfg.emummc_file_based_path, path);
strcat(emu_sd_cfg.emummc_file_based_path, "/raw_emmc_based");
if (!f_open(&fp, emu_sd_cfg.emummc_file_based_path, FA_READ))
{
if (!f_read(&fp, &emu_sd_cfg.sector, 4, NULL)){
if (emu_sd_cfg.sector){
found = true;
emu_sd_cfg.enabled = 4;
goto out;
}
}
}
// strcpy(emu_sd_cfg.emummc_file_based_path, "sd:");
strcpy(emu_sd_cfg.emummc_file_based_path, "");
strcat(emu_sd_cfg.emummc_file_based_path, path);
strcat(emu_sd_cfg.emummc_file_based_path, "/file_based");
if (!f_stat(emu_sd_cfg.emummc_file_based_path, NULL))
{
emu_sd_cfg.sector = 0;
emu_sd_cfg.path = path;
emu_sd_cfg.enabled = 1;
found = true;
goto out;
}
// strcpy(emu_sd_cfg.emummc_file_based_path, "sd:");
strcpy(emu_sd_cfg.emummc_file_based_path, "");
strcat(emu_sd_cfg.emummc_file_based_path, path);
strcat(emu_sd_cfg.emummc_file_based_path, "/file_emmc_based");
if (!f_stat(emu_sd_cfg.emummc_file_based_path, NULL))
{
emu_sd_cfg.sector = 0;
emu_sd_cfg.path = path;
emu_sd_cfg.enabled = 4;
found = true;
goto out;
}
out:
return found;
}
int emusd_storage_init_mmc() {
if(!emusd_initialized) {
if (!emu_sd_cfg.enabled || h_cfg.emummc_force_disable) {
if(!sd_initialize(false)){
return 1;
}
emusd_initialized = true;
return 0;
}
bool file_based = false;
if(emu_sd_cfg.enabled == 4){
if(!emu_sd_cfg.sector){
//file based
if(!emmc_mount()){
return 1;
}
strcpy(emu_sd_cfg.emummc_file_based_path, "emmc:");
strcat(emu_sd_cfg.emummc_file_based_path, emu_sd_cfg.path);
strcat(emu_sd_cfg.emummc_file_based_path, "/SD/");
file_based = true;
}else{
if(!emmc_initialize(false)){
return 1;
}
}
}else{
if(!emu_sd_cfg.sector){
//file based
if(!sd_mount()){
return 1;
}
strcpy(emu_sd_cfg.emummc_file_based_path, "sd:");
strcat(emu_sd_cfg.emummc_file_based_path, emu_sd_cfg.path);
strcat(emu_sd_cfg.emummc_file_based_path, "/SD/");
file_based = true;
}else{
if(!sd_initialize(false)){
return 1;
}
}
}
if(file_based){
return file_based_storage_init(emu_sd_cfg.emummc_file_based_path) == 0;
}
emusd_initialized = true;
}
return 0;
}
int emusd_storage_end() {
if(!h_cfg.emummc_force_disable && emu_sd_cfg.enabled && !emu_sd_cfg.sector){
file_based_storage_end();
}
if(!emu_sd_cfg.enabled || h_cfg.emummc_force_disable || emu_sd_cfg.enabled == 1){
sd_unmount();
}else{
emmc_unmount();
}
emusd_initialized = false;
return 0;
}
int emusd_storage_write(u32 sector, u32 num_sectors, void *buf) {
if(!emu_sd_cfg.enabled || h_cfg.emummc_force_disable){
return sdmmc_storage_write(&sd_storage, sector, num_sectors, buf);
}else if(emu_sd_cfg.sector){
sdmmc_storage_t *storage = emu_sd_cfg.enabled == 1 ? &sd_storage : &emmc_storage;
sector += emu_sd_cfg.sector;
return sdmmc_storage_write(storage, sector, num_sectors, buf);
}else{
return file_based_storage_write(sector, num_sectors, buf);
}
}
int emusd_storage_read(u32 sector, u32 num_sectors, void *buf) {
if(!emu_sd_cfg.enabled || h_cfg.emummc_force_disable){
return sdmmc_storage_read(&sd_storage, sector, num_sectors, buf);
}else if(emu_sd_cfg.sector){
sdmmc_storage_t *storage = emu_sd_cfg.enabled == 1 ? &sd_storage : &emmc_storage;
sector += emu_sd_cfg.sector;
return sdmmc_storage_read(storage, sector, num_sectors, buf);
}else{
return file_based_storage_read(sector, num_sectors, buf);
}
}
sdmmc_storage_t *emusd_get_storage() {
return emu_sd_cfg.enabled == 4 ? &emmc_storage : &sd_storage;
}
bool emusd_is_gpt() {
if(emu_sd_cfg.enabled) {
return emusd_fs.part_type;
} else {
return sd_fs.part_type;
}
}
int emusd_get_fs_type() {
if(emu_sd_cfg.enabled) {
return emusd_fs.fs_type;
} else {
return sd_fs.fs_type;
}
}
void *emusd_file_read(const char *path, u32 *fsize) {
if(emu_sd_cfg.enabled) {
char *path1 = malloc(0x100);
strcpy(path1, "emusd:");
strcat(path1, path);
FIL fp;
if (!emusd_get_mounted())
return NULL;
if (f_open(&fp, path, FA_READ) != FR_OK)
return NULL;
u32 size = f_size(&fp);
if (fsize)
*fsize = size;
void *buf = malloc(size);
if (f_read(&fp, buf, size, NULL) != FR_OK)
{
free(buf);
f_close(&fp);
return NULL;
}
f_close(&fp);
return buf;
} else {
return boot_storage_file_read(path, fsize);
}
}

View File

@@ -0,0 +1,49 @@
/*
* Copyright (c) 2019-2021 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _EMUSD_H
#define _EMUSD_H
#include <bdk.h>
typedef struct _emusd_cfg_t
{
int enabled;
u64 sector;
u32 id;
char *path;
// Internal.
int fs_ver;
char *emummc_file_based_path;
} emusd_cfg_t;
extern emusd_cfg_t emu_sd_cfg;
void emusd_load_cfg();
bool emusd_set_path(char *path);
int emusd_storage_init_mmc();
int emusd_storage_end();
int emusd_storage_read(u32 sector, u32 num_sectors, void *buf);
int emusd_storage_write(u32 sector, u32 num_sectors, void *buf);
sdmmc_storage_t *emusd_get_storage();
bool emusd_is_gpt();
int emusd_get_fs_type();
bool emusd_mount();
bool emusd_unmount();
void *emusd_file_read(const char *path, u32 *fsize);
#endif

View File

@@ -13,14 +13,14 @@ include ../Versions.inc
################################################################################ ################################################################################
TARGET := loader TARGET := loader
BUILDDIR := ../build/$(TARGET) BUILDDIR := ../build
OUTPUTDIR := ../output OUTPUTDIR := ../output
BDKDIR := bdk BDKDIR := bdk
BDKINC := -I../$(BDKDIR) BDKINC := -I../$(BDKDIR)
VPATH += $(dir $(wildcard ../$(BDKDIR)/*/)) $(dir $(wildcard ../$(BDKDIR)/*/*/)) VPATH += $(dir $(wildcard ../$(BDKDIR)/*/)) $(dir $(wildcard ../$(BDKDIR)/*/*/))
# Main and graphics. # Main and graphics.
OBJS = $(addprefix $(BUILDDIR)/, \ OBJS = $(addprefix $(BUILDDIR)/$(TARGET)/, \
start.o loader.o lz.o \ start.o loader.o lz.o \
) )
@@ -43,23 +43,23 @@ LDFLAGS = $(ARCH) -nostartfiles -lgcc -Wl,--nmagic,--gc-sections -Xlinker --defs
all: $(TARGET).bin $(TOOLSLZ) $(TOOLSB2C) all: $(TARGET).bin $(TOOLSLZ) $(TOOLSB2C)
clean: clean:
@rm -f payload_00.h @rm -rf $(OBJS)
@rm -f payload_01.h
$(TARGET).bin: $(BUILDDIR)/$(TARGET).elf $(TARGET).bin: $(BUILDDIR)/$(TARGET)/$(TARGET).elf
@$(OBJCOPY) -S -O binary $< $(OUTPUTDIR)/$(PAYLOAD_NAME).bin @$(OBJCOPY) -S -O binary $< $(OUTPUTDIR)/$(PAYLOAD_NAME).bin
$(BUILDDIR)/$(TARGET).elf: $(OBJS) $(BUILDDIR)/$(TARGET)/$(TARGET).elf: $(OBJS)
@$(CC) $(LDFLAGS) -T link.ld $^ -o $@ @$(CC) $(LDFLAGS) -T link.ld $^ -o $@
$(BUILDDIR)/%.o: %.c $(BUILDDIR)/$(TARGET)/%.o: %.c
@$(CC) $(CFLAGS) $(BDKINC) -c $< -o $@ @$(CC) $(CFLAGS) $(BDKINC) -c $< -o $@
$(BUILDDIR)/%.o: %.S $(BUILDDIR)/$(TARGET)/%.o: %.S
@$(CC) $(CFLAGS) -c $< -o $@ @$(CC) $(CFLAGS) -c $< -o $@
$(OBJS): $(BUILDDIR) $(OBJS): $(BUILDDIR)/$(TARGET)
$(BUILDDIR): $(BUILDDIR)/$(TARGET):
@mkdir -p "$(BUILDDIR)" @mkdir -p "$(BUILDDIR)"
@mkdir -p "$(BUILDDIR)/$(TARGET)"
@mkdir -p "$(OUTPUTDIR)" @mkdir -p "$(OUTPUTDIR)"

View File

@@ -5,16 +5,12 @@ endif
include $(DEVKITARM)/base_rules include $(DEVKITARM)/base_rules
TARGET := libsys_lp0 TARGET := libsys_lp0
BUILDDIR := ../../build/$(TARGET) BUILD := ../../build/$(TARGET)
OUTPUTDIR := ../../output OUTPUT := ../../output
BDKDIR := bdk BDKDIR := bdk
BDKINC := -I../../$(BDKDIR) BDKINC := -I../../$(BDKDIR)
# Track compiler flags OBJS = $(addprefix $(BUILD)/,\
TRACK_CFLAGS = $(BUILDDIR)/.cflags
TRACK_LDFLAGS = $(BUILDDIR)/.ldflags
OBJS = $(addprefix $(BUILDDIR)/,\
sys_sdramlp0.o \ sys_sdramlp0.o \
) )
@@ -22,23 +18,17 @@ ARCH := -march=armv4t -mtune=arm7tdmi -mthumb-interwork
CFLAGS = $(ARCH) -O2 -nostdlib -fpie -ffunction-sections -fdata-sections -fomit-frame-pointer -std=gnu11 -Wall -Wsign-compare $(CUSTOMDEFINES) CFLAGS = $(ARCH) -O2 -nostdlib -fpie -ffunction-sections -fdata-sections -fomit-frame-pointer -std=gnu11 -Wall -Wsign-compare $(CUSTOMDEFINES)
LDFLAGS = $(ARCH) -fpie -pie -nostartfiles -lgcc LDFLAGS = $(ARCH) -fpie -pie -nostartfiles -lgcc
.PHONY: all .PHONY: clean all
all: $(TARGET).bso all: $(TARGET).bso
$(BUILDDIR)/%.o: ./%.c $(TRACK_CFLAGS) $(BUILD)/%.o: ./%.c
@$(CC) $(CFLAGS) $(BDKINC) -MMD -MP -c $< -o $@ @mkdir -p "$(BUILD)"
@$(CC) $(CFLAGS) $(BDKINC) -c $< -o $@
$(TARGET).bso: $(OBJS) $(TRACK_LDFLAGS) $(TARGET).bso: $(OBJS)
@$(CC) $(LDFLAGS) -e sdram_lp0_entry $(OBJS) -o $(OUTPUTDIR)/$(TARGET).bso @$(CC) $(LDFLAGS) -e sdram_lp0_entry $^ -o $(OUTPUT)/$(TARGET).bso
@$(STRIP) -g $(OUTPUTDIR)/$(TARGET).bso @$(STRIP) -g $(OUTPUT)/$(TARGET).bso
@echo "Built module: "$(TARGET)".bso" @echo -e "-------------\nBuilt module: "$(TARGET)".bso\n-------------"
$(BUILDDIR): clean:
@mkdir -p "$(BUILDDIR)" @rm -rf $(OUTPUT)/$(TARGET).bso
# Non objects change detectors.
$(TRACK_CFLAGS): $(BUILDDIR)
@echo '$(CFLAGS)' | cmp -s - $@ || echo '$(CFLAGS)' > $@
$(TRACK_LDFLAGS): $(BUILDDIR)
@echo '$(LDFLAGS)' | cmp -s - $@ || echo '$(LDFLAGS)' > $@
-include $(OBJS:.o=.d)

View File

@@ -5,16 +5,12 @@ endif
include $(DEVKITARM)/base_rules include $(DEVKITARM)/base_rules
TARGET := libsys_minerva TARGET := libsys_minerva
BUILDDIR := ../../build/$(TARGET) BUILD := ../../build/$(TARGET)
OUTPUTDIR := ../../output OUTPUT := ../../output
BDKDIR := bdk BDKDIR := bdk
BDKINC := -I../../$(BDKDIR) BDKINC := -I../../$(BDKDIR)
# Track compiler flags OBJS = $(addprefix $(BUILD)/,\
TRACK_CFLAGS = $(BUILDDIR)/.cflags
TRACK_LDFLAGS = $(BUILDDIR)/.ldflags
OBJS = $(addprefix $(BUILDDIR)/,\
sys_sdrammtc.o \ sys_sdrammtc.o \
) )
@@ -22,23 +18,17 @@ ARCH := -march=armv4t -mtune=arm7tdmi -mthumb-interwork
CFLAGS = $(ARCH) -O2 -nostdlib -fpie -ffunction-sections -fdata-sections -fomit-frame-pointer -std=gnu11 -Wall -Wsign-compare $(CUSTOMDEFINES) CFLAGS = $(ARCH) -O2 -nostdlib -fpie -ffunction-sections -fdata-sections -fomit-frame-pointer -std=gnu11 -Wall -Wsign-compare $(CUSTOMDEFINES)
LDFLAGS = $(ARCH) -fpie -pie -nostartfiles -lgcc LDFLAGS = $(ARCH) -fpie -pie -nostartfiles -lgcc
.PHONY: all .PHONY: clean all
all: $(TARGET).bso all: $(TARGET).bso
$(BUILDDIR)/%.o: ./%.c $(TRACK_CFLAGS) $(BUILD)/%.o: ./%.c
@$(CC) $(CFLAGS) $(BDKINC) -MMD -MP -c $< -o $@ @mkdir -p "$(BUILD)"
@$(CC) $(CFLAGS) $(BDKINC) -c $< -o $@
$(TARGET).bso: $(OBJS) $(TRACK_LDFLAGS) $(TARGET).bso: $(OBJS)
@$(CC) $(LDFLAGS) -e minerva_entry $(OBJS) -o $(OUTPUTDIR)/$(TARGET).bso @$(CC) $(LDFLAGS) -e minerva_entry $^ -o $(OUTPUT)/$(TARGET).bso
@$(STRIP) -g $(OUTPUTDIR)/$(TARGET).bso @$(STRIP) -g $(OUTPUT)/$(TARGET).bso
@echo "Built module: "$(TARGET)".bso" @echo -e "-------------\nBuilt module: "$(TARGET)".bso\n-------------"
$(BUILDDIR): clean:
@mkdir -p "$(BUILDDIR)" @rm -rf $(OUTPUT)/$(TARGET).bso
# Non objects change detectors.
$(TRACK_CFLAGS): $(BUILDDIR)
@echo '$(CFLAGS)' | cmp -s - $@ || echo '$(CFLAGS)' > $@
$(TRACK_LDFLAGS): $(BUILDDIR)
@echo '$(LDFLAGS)' | cmp -s - $@ || echo '$(LDFLAGS)' > $@
-include $(OBJS:.o=.d)

View File

@@ -5,18 +5,14 @@ endif
include $(DEVKITARM)/base_rules include $(DEVKITARM)/base_rules
TARGET := module_sample TARGET := module_sample
BUILDDIR := ../../build/$(TARGET) BUILD := ../../build/$(TARGET)
OUTPUTDIR := ../../output OUTPUT := ../../output
SOURCEDIR = simple_sample SOURCEDIR = simple_sample
BDKDIR := bdk BDKDIR := bdk
BDKINC := -I../../$(BDKDIR) BDKINC := -I../../$(BDKDIR)
VPATH = $(dir ./) $(dir $(wildcard ./*/)) VPATH = $(dir ./) $(dir $(wildcard ./*/))
# Track compiler flags OBJS = $(addprefix $(BUILD)/,\
TRACK_CFLAGS = $(BUILDDIR)/.cflags
TRACK_LDFLAGS = $(BUILDDIR)/.ldflags
OBJS = $(addprefix $(BUILDDIR)/,\
module_sample.o \ module_sample.o \
gfx.o \ gfx.o \
) )
@@ -26,30 +22,20 @@ GFX_INC := '"../modules/$(SOURCEDIR)/gfx/gfx.h"'
CUSTOMDEFINES := -DGFX_INC=$(GFX_INC) CUSTOMDEFINES := -DGFX_INC=$(GFX_INC)
ARCH := -march=armv4t -mtune=arm7tdmi -mthumb-interwork ARCH := -march=armv4t -mtune=arm7tdmi -mthumb-interwork
CFLAGS = $(ARCH) -O2 -nostdlib -fpie -ffunction-sections -fdata-sections -fomit-frame-pointer -std=gnu11 -Wall -Wsign-compare $(CUSTOMDEFINES) CFLAGS = $(ARCH) -O2 -nostdlib -fpie -ffunction-sections -fdata-sections -fomit-frame-pointer -std=gnu11 -Wall $(CUSTOMDEFINES)
LDFLAGS = $(ARCH) -fpie -pie -nostartfiles -lgcc LDFLAGS = $(ARCH) -fpie -pie -nostartfiles -lgcc
.PHONY: clean all .PHONY: clean all
all: $(TARGET).bso all: $(TARGET).bso
$(BUILDDIR)/%.o: ./%.c $(TRACK_CFLAGS) $(BUILD)/%.o: ./%.c
@$(CC) $(CFLAGS) $(BDKINC) -MMD -MP -c $< -o $@ @mkdir -p "$(BUILD)"
@$(CC) $(CFLAGS) $(BDKINC) -c $< -o $@
$(TARGET).bso: $(OBJS) $(TRACK_LDFLAGS) $(TARGET).bso: $(OBJS)
@$(CC) $(LDFLAGS) -e mod_entry $(OBJS) -o $(OUTPUTDIR)/$(TARGET).bso @$(CC) $(LDFLAGS) -e _modInit $^ -o $(OUTPUT)/$(TARGET).bso
@$(STRIP) -g $(OUTPUTDIR)/$(TARGET).bso @$(STRIP) -g $(OUTPUT)/$(TARGET).bso
@echo "Built module: "$(TARGET)".bso" @echo -e "-------------\nBuilt module: "$(TARGET)".bso\n-------------"
clean: clean:
@rm -rf $(BUILDDIR)/$(TARGET) @rm -rf $(OUTPUT)/$(TARGET).bso
@rm -rf $(OUTPUTDIR)/$(TARGET).bso
$(BUILDDIR):
@mkdir -p "$(BUILDDIR)"
# Non objects change detectors.
$(TRACK_CFLAGS): $(BUILDDIR)
@echo '$(CFLAGS)' | cmp -s - $@ || echo '$(CFLAGS)' > $@
$(TRACK_LDFLAGS): $(BUILDDIR)
@echo '$(LDFLAGS)' | cmp -s - $@ || echo '$(LDFLAGS)' > $@
-include $(OBJS:.o=.d)

View File

@@ -6,7 +6,7 @@
#include <module.h> #include <module.h>
#include <gfx_utils.h> #include <gfx_utils.h>
void mod_entry(void *moduleConfig, bdkParams_t bp) void _modInit(void *moduleConfig, bdkParams_t bp)
{ {
memcpy(&gfx_con, bp->gfxCon, sizeof(gfx_con_t)); memcpy(&gfx_con, bp->gfxCon, sizeof(gfx_con_t));
memcpy(&gfx_ctxt, bp->gfxCtx, sizeof(gfx_ctxt_t)); memcpy(&gfx_ctxt, bp->gfxCtx, sizeof(gfx_ctxt_t));

View File

@@ -13,7 +13,7 @@ include ./../Versions.inc
################################################################################ ################################################################################
TARGET := nyx TARGET := nyx
BUILDDIR := ./../build/$(TARGET) BUILDDIR := ./../build
OUTPUTDIR := ./../output OUTPUTDIR := ./../output
SOURCEDIR = nyx_gui SOURCEDIR = nyx_gui
BDKDIR := bdk BDKDIR := bdk
@@ -22,47 +22,54 @@ VPATH = $(dir $(wildcard ./$(SOURCEDIR)/)) $(dir $(wildcard ./$(SOURCEDIR)/*/))
VPATH += $(dir $(wildcard ./$(SOURCEDIR)/*/*/*/)) $(dir $(wildcard ./$(SOURCEDIR)/*/*/*/*/)) VPATH += $(dir $(wildcard ./$(SOURCEDIR)/*/*/*/)) $(dir $(wildcard ./$(SOURCEDIR)/*/*/*/*/))
VPATH += $(dir $(wildcard ../$(BDKDIR)/)) $(dir $(wildcard ../$(BDKDIR)/*/)) $(dir $(wildcard ../$(BDKDIR)/*/*/)) $(dir $(wildcard ../$(BDKDIR)/*/*/*/)) VPATH += $(dir $(wildcard ../$(BDKDIR)/)) $(dir $(wildcard ../$(BDKDIR)/*/)) $(dir $(wildcard ../$(BDKDIR)/*/*/)) $(dir $(wildcard ../$(BDKDIR)/*/*/*/))
# Track compiler flags
TRACK_CFLAGS = $(BUILDDIR)/.cflags
TRACK_LDFLAGS = $(BUILDDIR)/.ldflags
# Main and graphics. # Main and graphics.
OBJS = start exception_handlers nyx heap gfx \ OBJS = $(addprefix $(BUILDDIR)/$(TARGET)/, \
gui gui_info gui_tools gui_options gui_emmc_tools gui_emummc_tools gui_tools_partition_manager \ start.o exception_handlers.o \
fe_emummc_tools fe_emmc_tools nyx.o heap.o \
gfx.o \
gui.o gui_info.o gui_tools.o gui_options.o gui_emmc_tools.o gui_emummc_tools.o gui_tools_partition_manager.o gui_emu_tools.o \
fe_emummc_tools.o fe_emmc_tools.o \
)
# Hardware. # Hardware.
OBJS += actmon bpmp ccplex clock di vic i2c irq timer \ OBJS += $(addprefix $(BUILDDIR)/$(TARGET)/, \
gpio pinmux pmc se smmu tsec uart \ bpmp.o ccplex.o clock.o di.o vic.o i2c.o irq.o timer.o \
fuse kfuse \ gpio.o pinmux.o pmc.o se.o smmu.o tsec.o uart.o \
mc sdram minerva ramdisk \ fuse.o kfuse.o \
sdmmc sdmmc_driver emmc sd nx_emmc_bis \ mc.o sdram.o minerva.o ramdisk.o \
bm92t36 bq24193 max17050 max7762x max77620-rtc regulator_5v \ sdmmc.o sdmmc_driver.o emmc.o sd.o nx_emmc_bis.o \
touch joycon tmp451 fan \ bm92t36.o bq24193.o max17050.o max7762x.o max77620-rtc.o regulator_5v.o \
usbd xusbd usb_descriptors usb_gadget_ums usb_gadget_hid \ touch.o joycon.o tmp451.o fan.o \
hw_init usbd.o xusbd.o usb_descriptors.o usb_gadget_ums.o usb_gadget_hid.o \
hw_init.o boot_storage.o sfd.o mbr_gpt.o emummc_file_based.o file_based_storage.o \
)
# Utilities. # Utilities.
OBJS += btn dirlist ianos ini util config sprintf OBJS += $(addprefix $(BUILDDIR)/$(TARGET)/, \
btn.o dirlist.o ianos.o util.o \
config.o ini.o \
sprintf.o \
)
# Horizon. # Horizon.
OBJS += hos pkg1 pkg2 OBJS += $(addprefix $(BUILDDIR)/$(TARGET)/, \
hos.o pkg1.o pkg2.o \
)
# Libraries. # Libraries.
OBJS += diskio ff ffunicode ffsystem \ OBJS += $(addprefix $(BUILDDIR)/$(TARGET)/, \
elfload elfreloc_arm blz \ diskio.o ff.o ffunicode.o ffsystem.o \
lv_group lv_indev lv_obj lv_refr lv_style lv_vdb \ elfload.o elfreloc_arm.o blz.o \
lv_draw lv_draw_rbasic lv_draw_vbasic lv_draw_arc lv_draw_img \ lv_group.o lv_indev.o lv_obj.o lv_refr.o lv_style.o lv_vdb.o \
lv_draw_label lv_draw_line lv_draw_rect lv_draw_triangle \ lv_draw.o lv_draw_rbasic.o lv_draw_vbasic.o lv_draw_arc.o lv_draw_img.o \
lv_hal_disp lv_hal_indev lv_hal_tick \ lv_draw_label.o lv_draw_line.o lv_draw_rect.o lv_draw_triangle.o \
interui_20 interui_30 ubuntu_mono hekate_symbol_20 hekate_symbol_30 hekate_symbol_120 lv_font_builtin \ lv_hal_disp.o lv_hal_indev.o lv_hal_tick.o \
lv_anim lv_area lv_circ lv_color lv_font lv_ll lv_math lv_mem lv_task lv_txt lv_gc \ interui_20.o interui_30.o ubuntu_mono.o hekate_symbol_20.o hekate_symbol_30.o hekate_symbol_120.o lv_font_builtin.o \
lv_bar lv_btn lv_btnm lv_cb lv_cont lv_ddlist lv_img lv_label lv_line lv_list lv_lmeter lv_mbox \ lv_anim.o lv_area.o lv_circ.o lv_color.o lv_font.o lv_ll.o lv_math.o lv_mem.o lv_task.o lv_txt.o lv_gc.o \
lv_page lv_roller lv_slider lv_sw lv_tabview lv_ta lv_win lv_log lv_imgbtn \ lv_bar.o lv_btn.o lv_btnm.o lv_cb.o lv_cont.o lv_ddlist.o lv_img.o lv_label.o lv_line.o lv_list.o lv_lmeter.o lv_mbox.o \
lv_theme lv_theme_hekate lv_page.o lv_roller.o lv_slider.o lv_sw.o lv_tabview.o lv_ta.o lv_win.o lv_log.o lv_imgbtn.o \
lv_theme.o lv_theme_hekate.o \
OBJS := $(addsuffix .o, $(OBJS)) )
OBJS := $(addprefix $(BUILDDIR)/, $(OBJS))
GFX_INC := '"../nyx/$(SOURCEDIR)/gfx/gfx.h"' GFX_INC := '"../nyx/$(SOURCEDIR)/gfx/gfx.h"'
FFCFG_INC := '"../nyx/$(SOURCEDIR)/libs/fatfs/ffconf.h"' FFCFG_INC := '"../nyx/$(SOURCEDIR)/libs/fatfs/ffconf.h"'
@@ -94,14 +101,6 @@ ARCH := -march=armv4t -mtune=arm7tdmi -mthumb-interwork $(WARNINGS)
CFLAGS = $(ARCH) -O2 -g -gdwarf-4 -nostdlib -ffunction-sections -fdata-sections -fomit-frame-pointer -std=gnu11 $(CUSTOMDEFINES) CFLAGS = $(ARCH) -O2 -g -gdwarf-4 -nostdlib -ffunction-sections -fdata-sections -fomit-frame-pointer -std=gnu11 $(CUSTOMDEFINES)
LDFLAGS = $(ARCH) -nostartfiles -lgcc -Wl,--nmagic,--gc-sections -Xlinker --defsym=NYX_LOAD_ADDR=$(NYX_LOAD_ADDR) LDFLAGS = $(ARCH) -nostartfiles -lgcc -Wl,--nmagic,--gc-sections -Xlinker --defsym=NYX_LOAD_ADDR=$(NYX_LOAD_ADDR)
ifndef NYXECHO
T := $(shell $(MAKE) $(BUILDDIR)/$(TARGET).elf --no-print-directory -nrRf $(firstword $(MAKEFILE_LIST)) NYXECHO="NYXOBJ" | grep -c "NYXOBJ")
N := x
C = $(words $N)$(eval N := x $N)
NYXECHO = echo -ne "\r`expr " [\`expr $C '*' 100 / $T\`" : '.*\(....\)$$'`%]\033[K"
endif
################################################################################ ################################################################################
.PHONY: all clean .PHONY: all clean
@@ -118,29 +117,24 @@ clean:
@rm -rf $(BUILDDIR) @rm -rf $(BUILDDIR)
@rm -rf $(OUTPUTDIR) @rm -rf $(OUTPUTDIR)
$(TARGET).bin: $(BUILDDIR)/$(TARGET).elf $(TARGET).bin: $(BUILDDIR)/$(TARGET)/$(TARGET).elf
@$(OBJCOPY) -S -O binary $< $(OUTPUTDIR)/$@ @$(OBJCOPY) -S -O binary $< $(OUTPUTDIR)/$@
$(BUILDDIR)/$(TARGET).elf: $(OBJS) $(TRACK_LDFLAGS) $(BUILDDIR)/$(TARGET)/$(TARGET).elf: $(OBJS)
@echo -ne "\r[100%] Linking $(TARGET).elf\033[K" @$(CC) $(LDFLAGS) -T $(SOURCEDIR)/link.ld $^ -o $@
@$(CC) $(LDFLAGS) -T $(SOURCEDIR)/link.ld $(OBJS) -o $@ @printf "$(TARGET) was built with the following flags:\nCFLAGS: $(CFLAGS)\nLDFLAGS: $(LDFLAGS)\n"
@printf "\n$(TARGET) was built with the following flags:\nCFLAGS: $(CFLAGS)\nLDFLAGS: $(LDFLAGS)\n"
$(BUILDDIR)/%.o: %.c $(TRACK_CFLAGS) | $(BUILDDIR) $(BUILDDIR)/$(TARGET)/%.o: %.c
@$(NYXECHO) Building $@ @echo Building $@
@$(CC) $(CFLAGS) $(BDKINC) -MMD -MP -c $< -o $@ @$(CC) $(CFLAGS) $(BDKINC) -c $< -o $@
$(BUILDDIR)/%.o: %.S $(TRACK_CFLAGS) | $(BUILDDIR) $(BUILDDIR)/$(TARGET)/%.o: %.S
@$(NYXECHO) Building $@ @echo Building $@
@$(CC) $(CFLAGS) -MMD -MP -c $< -o $@ @$(CC) $(CFLAGS) -c $< -o $@
$(BUILDDIR): $(OBJS): $(BUILDDIR)/$(TARGET)
$(BUILDDIR)/$(TARGET):
@mkdir -p "$(BUILDDIR)" @mkdir -p "$(BUILDDIR)"
@mkdir -p "$(BUILDDIR)/$(TARGET)"
@mkdir -p "$(OUTPUTDIR)" @mkdir -p "$(OUTPUTDIR)"
# Non objects change detectors.
$(TRACK_CFLAGS): $(BUILDDIR)
@echo '$(CFLAGS)' | cmp -s - $@ || echo '$(CFLAGS)' > $@
$(TRACK_LDFLAGS): $(BUILDDIR)
@echo '$(LDFLAGS)' | cmp -s - $@ || echo '$(LDFLAGS)' > $@
-include $(OBJS:.o=.d)

View File

@@ -21,11 +21,11 @@
#include "config.h" #include "config.h"
#include <libs/fatfs/ff.h> #include <libs/fatfs/ff.h>
#include <storage/boot_storage.h>
void set_default_configuration() void set_default_configuration()
{ {
h_cfg.t210b01 = hw_get_chip_id() == GP_HIDREV_MAJOR_T210B01; h_cfg.t210b01 = hw_get_chip_id() == GP_HIDREV_MAJOR_T210B01;
h_cfg.devmode = fuse_read_hw_state();
h_cfg.autoboot = 0; h_cfg.autoboot = 0;
h_cfg.autoboot_list = 0; h_cfg.autoboot_list = 0;
@@ -186,9 +186,9 @@ int create_config_entry()
int create_nyx_config_entry(bool force_unmount) int create_nyx_config_entry(bool force_unmount)
{ {
bool sd_mounted = sd_get_card_mounted(); bool sd_mounted = boot_storage_get_mounted();
if (!sd_mount()) if (!boot_storage_mount())
return 1; return 1;
char lbuf[64]; char lbuf[64];
@@ -250,7 +250,7 @@ int create_nyx_config_entry(bool force_unmount)
f_close(&fp); f_close(&fp);
if (force_unmount || !sd_mounted) if (force_unmount || !sd_mounted)
sd_unmount(); boot_storage_unmount();
return 0; return 0;
} }

View File

@@ -35,7 +35,6 @@ typedef struct _hekate_config
u32 bootprotect; u32 bootprotect;
// Global temporary config. // Global temporary config.
bool t210b01; bool t210b01;
bool devmode;
bool emummc_force_disable; bool emummc_force_disable;
bool rcm_patched; bool rcm_patched;
bool autorcm_enabled; bool autorcm_enabled;

View File

@@ -1,7 +1,7 @@
/* /*
* Copyright (c) 2018 naehrwert * Copyright (c) 2018 naehrwert
* Copyright (c) 2018 Rajko Stojadinovic * Copyright (c) 2018 Rajko Stojadinovic
* Copyright (c) 2018-2025 CTCaer * Copyright (c) 2018-2024 CTCaer
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@@ -18,6 +18,7 @@
//! fix the dram stuff and the pop ups //! fix the dram stuff and the pop ups
#include <storage/boot_storage.h>
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
@@ -29,10 +30,6 @@
#include "../config.h" #include "../config.h"
#include <libs/fatfs/ff.h> #include <libs/fatfs/ff.h>
#define VERIF_STATUS_OK 0
#define VERIF_STATUS_ERROR 1
#define VERIF_STATUS_ABORT 2
#define NUM_SECTORS_PER_ITER 8192 // 4MB Cache. #define NUM_SECTORS_PER_ITER 8192 // 4MB Cache.
#define OUT_FILENAME_SZ 128 #define OUT_FILENAME_SZ 128
#define HASH_FILENAME_SZ (OUT_FILENAME_SZ + 11) // 11 == strlen(".sha256sums") #define HASH_FILENAME_SZ (OUT_FILENAME_SZ + 11) // 11 == strlen(".sha256sums")
@@ -141,7 +138,7 @@ static void _update_filename(char *outFilename, u32 sdPathLen, u32 currPartIdx)
itoa(currPartIdx, &outFilename[sdPathLen], 10); itoa(currPartIdx, &outFilename[sdPathLen], 10);
} }
static int _emmc_sd_copy_verify(emmc_tool_gui_t *gui, sdmmc_storage_t *storage, u32 lba_curr, const char *outFilename, const emmc_part_t *part) static int _dump_emmc_verify(emmc_tool_gui_t *gui, sdmmc_storage_t *storage, u32 lba_curr, const char *outFilename, const emmc_part_t *part)
{ {
FIL fp; FIL fp;
FIL hashFp; FIL hashFp;
@@ -174,7 +171,7 @@ static int _emmc_sd_copy_verify(emmc_tool_gui_t *gui, sdmmc_storage_t *storage,
lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf); lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf);
manual_system_maintenance(true); manual_system_maintenance(true);
return VERIF_STATUS_ERROR; return 1;
} }
char chunkSizeAscii[10]; char chunkSizeAscii[10];
@@ -225,11 +222,10 @@ static int _emmc_sd_copy_verify(emmc_tool_gui_t *gui, sdmmc_storage_t *storage,
if (n_cfg.verification == 3) if (n_cfg.verification == 3)
f_close(&hashFp); f_close(&hashFp);
return VERIF_STATUS_ERROR; return 1;
} }
manual_system_maintenance(false); manual_system_maintenance(false);
se_calc_sha256(hashEm, NULL, bufEm, num << 9, 0, SHA_INIT_HASH, false);
se_sha_hash_256_async(hashEm, bufEm, num << 9);
f_lseek(&fp, (u64)sdFileSector << (u64)9); f_lseek(&fp, (u64)sdFileSector << (u64)9);
if (f_read_fast(&fp, bufSd, num << 9)) if (f_read_fast(&fp, bufSd, num << 9))
@@ -246,11 +242,11 @@ static int _emmc_sd_copy_verify(emmc_tool_gui_t *gui, sdmmc_storage_t *storage,
if (n_cfg.verification == 3) if (n_cfg.verification == 3)
f_close(&hashFp); f_close(&hashFp);
return VERIF_STATUS_ERROR; return 1;
} }
manual_system_maintenance(false); manual_system_maintenance(false);
se_sha_hash_256_finalize(hashEm); se_calc_sha256_finalize(hashEm, NULL);
se_sha_hash_256_oneshot(hashSd, bufSd, num << 9); se_calc_sha256_oneshot(hashSd, bufSd, num << 9);
res = memcmp(hashEm, hashSd, SE_SHA_256_SIZE / 2); res = memcmp(hashEm, hashSd, SE_SHA_256_SIZE / 2);
if (res) if (res)
@@ -267,7 +263,7 @@ static int _emmc_sd_copy_verify(emmc_tool_gui_t *gui, sdmmc_storage_t *storage,
if (n_cfg.verification == 3) if (n_cfg.verification == 3)
f_close(&hashFp); f_close(&hashFp);
return VERIF_STATUS_ERROR; return 1;
} }
if (n_cfg.verification == 3) if (n_cfg.verification == 3)
@@ -307,7 +303,7 @@ static int _emmc_sd_copy_verify(emmc_tool_gui_t *gui, sdmmc_storage_t *storage,
// Check for cancellation combo. // Check for cancellation combo.
if (btn_read_vol() == (BTN_VOL_UP | BTN_VOL_DOWN)) if (btn_read_vol() == (BTN_VOL_UP | BTN_VOL_DOWN))
{ {
strcpy(gui->txt_buf, "#FFDD00 Verification was cancelled!#\n"); s_printf(gui->txt_buf, "#FFDD00 Verification was cancelled!#\n");
lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf); lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf);
manual_system_maintenance(true); manual_system_maintenance(true);
@@ -317,7 +313,7 @@ static int _emmc_sd_copy_verify(emmc_tool_gui_t *gui, sdmmc_storage_t *storage,
f_close(&fp); f_close(&fp);
f_close(&hashFp); f_close(&hashFp);
return VERIF_STATUS_ABORT; return 0;
} }
} }
free(clmt); free(clmt);
@@ -329,15 +325,15 @@ static int _emmc_sd_copy_verify(emmc_tool_gui_t *gui, sdmmc_storage_t *storage,
lv_label_set_text(gui->label_pct, gui->txt_buf); lv_label_set_text(gui->label_pct, gui->txt_buf);
manual_system_maintenance(true); manual_system_maintenance(true);
return VERIF_STATUS_OK; return 0;
} }
else else
{ {
strcpy(gui->txt_buf, "\n#FFDD00 File not found or could not be loaded!#\n#FFDD00 Verification failed..#\n"); s_printf(gui->txt_buf, "\n#FFDD00 File not found or could not be loaded!#\n#FFDD00 Verification failed..#\n");
lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf); lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf);
manual_system_maintenance(true); manual_system_maintenance(true);
return VERIF_STATUS_ERROR; return 1;
} }
} }
@@ -350,7 +346,6 @@ static int _dump_emmc_part(emmc_tool_gui_t *gui, char *sd_path, int active_part,
partial_sd_full_unmount = false; partial_sd_full_unmount = false;
u32 verification = n_cfg.verification;
u32 multipartSplitSize = (1u << 31); u32 multipartSplitSize = (1u << 31);
u32 lba_end = part->lba_end; u32 lba_end = part->lba_end;
u32 totalSectors = part->lba_end - part->lba_start + 1; u32 totalSectors = part->lba_end - part->lba_start + 1;
@@ -376,7 +371,7 @@ static int _dump_emmc_part(emmc_tool_gui_t *gui, char *sd_path, int active_part,
_get_valid_partition(&sector_start, &sector_size, &part_idx, true); _get_valid_partition(&sector_start, &sector_size, &part_idx, true);
if (!part_idx || !sector_size) if (!part_idx || !sector_size)
{ {
strcpy(gui->txt_buf, "\n#FFDD00 Failed to find a partition...#\n"); s_printf(gui->txt_buf, "\n#FFDD00 Failed to find a partition...#\n");
lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf); lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf);
manual_system_maintenance(true); manual_system_maintenance(true);
@@ -399,7 +394,7 @@ static int _dump_emmc_part(emmc_tool_gui_t *gui, char *sd_path, int active_part,
lv_bar_set_value(gui->bar, 0); lv_bar_set_value(gui->bar, 0);
lv_label_set_text(gui->label_pct, " "SYMBOL_DOT" 0%"); lv_label_set_text(gui->label_pct, " "SYMBOL_DOT" 0%");
lv_bar_set_style(gui->bar, LV_BAR_STYLE_BG, gui->bar_white_bg); lv_bar_set_style(gui->bar, LV_BAR_STYLE_BG, lv_theme_get_current()->bar.bg);
lv_bar_set_style(gui->bar, LV_BAR_STYLE_INDIC, gui->bar_white_ind); lv_bar_set_style(gui->bar, LV_BAR_STYLE_INDIC, gui->bar_white_ind);
manual_system_maintenance(true); manual_system_maintenance(true);
@@ -414,13 +409,13 @@ static int _dump_emmc_part(emmc_tool_gui_t *gui, char *sd_path, int active_part,
{ {
isSmallSdCard = true; isSmallSdCard = true;
strcpy(gui->txt_buf, "\n#FFBA00 Free space is smaller than backup size.#\n"); s_printf(gui->txt_buf, "\n#FFBA00 Free space is smaller than backup size.#\n");
lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf); lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf);
manual_system_maintenance(true); manual_system_maintenance(true);
if (!maxSplitParts) if (!maxSplitParts)
{ {
strcpy(gui->txt_buf, "#FFDD00 Not enough free space for Partial Backup!#\n"); s_printf(gui->txt_buf, "#FFDD00 Not enough free space for Partial Backup!#\n");
lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf); lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf);
manual_system_maintenance(true); manual_system_maintenance(true);
@@ -430,7 +425,7 @@ static int _dump_emmc_part(emmc_tool_gui_t *gui, char *sd_path, int active_part,
// Check if we are continuing a previous raw eMMC or USER partition backup in progress. // Check if we are continuing a previous raw eMMC or USER partition backup in progress.
if (f_open(&partialIdxFp, partialIdxFilename, FA_READ) == FR_OK && totalSectors > (FAT32_FILESIZE_LIMIT / EMMC_BLOCKSIZE)) if (f_open(&partialIdxFp, partialIdxFilename, FA_READ) == FR_OK && totalSectors > (FAT32_FILESIZE_LIMIT / EMMC_BLOCKSIZE))
{ {
strcpy(gui->txt_buf, "\n#AEFD14 Partial Backup in progress. Continuing...#\n"); s_printf(gui->txt_buf, "\n#AEFD14 Partial Backup in progress. Continuing...#\n");
lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf); lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf);
manual_system_maintenance(true); manual_system_maintenance(true);
@@ -443,7 +438,7 @@ static int _dump_emmc_part(emmc_tool_gui_t *gui, char *sd_path, int active_part,
if (!maxSplitParts) if (!maxSplitParts)
{ {
strcpy(gui->txt_buf, "\n#FFDD00 Not enough free space for Partial Backup!#\n"); s_printf(gui->txt_buf, "\n#FFDD00 Not enough free space for Partial Backup!#\n");
lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf); lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf);
manual_system_maintenance(true); manual_system_maintenance(true);
@@ -541,25 +536,18 @@ static int _dump_emmc_part(emmc_tool_gui_t *gui, char *sd_path, int active_part,
memset(&fp, 0, sizeof(fp)); memset(&fp, 0, sizeof(fp));
currPartIdx++; currPartIdx++;
if (verification && !gui->raw_emummc) if (n_cfg.verification && !gui->raw_emummc)
{ {
// Verify part. // Verify part.
res = _emmc_sd_copy_verify(gui, storage, lbaStartPart, outFilename, part); if (_dump_emmc_verify(gui, storage, lbaStartPart, outFilename, part))
switch (res)
{ {
case VERIF_STATUS_OK: s_printf(gui->txt_buf, "#FFDD00 Please try again...#\n");
break;
case VERIF_STATUS_ERROR:
strcpy(gui->txt_buf, "\n#FFDD00 Please try again...#\n");
lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf); lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf);
manual_system_maintenance(true); manual_system_maintenance(true);
return 0;
case VERIF_STATUS_ABORT:
verification = 0;
break;
}
lv_bar_set_style(gui->bar, LV_BAR_STYLE_BG, gui->bar_white_bg); return 0;
}
lv_bar_set_style(gui->bar, LV_BAR_STYLE_BG, lv_theme_get_current()->bar.bg);
lv_bar_set_style(gui->bar, LV_BAR_STYLE_INDIC, gui->bar_white_ind); lv_bar_set_style(gui->bar, LV_BAR_STYLE_INDIC, gui->bar_white_ind);
} }
@@ -576,7 +564,7 @@ static int _dump_emmc_part(emmc_tool_gui_t *gui, char *sd_path, int active_part,
} }
else else
{ {
strcpy(gui->txt_buf, "\n#FF0000 Error creating partial.idx file!#\n"); s_printf(gui->txt_buf, "\n#FF0000 Error creating partial.idx file!#\n");
lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf); lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf);
manual_system_maintenance(true); manual_system_maintenance(true);
@@ -655,7 +643,7 @@ static int _dump_emmc_part(emmc_tool_gui_t *gui, char *sd_path, int active_part,
msleep(150); msleep(150);
if (retryCount >= 3) if (retryCount >= 3)
{ {
strcpy(gui->txt_buf, "#FF0000 Aborting...#\nPlease try again...\n"); s_printf(gui->txt_buf, "#FF0000 Aborting...#\nPlease try again...\n");
lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf); lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf);
manual_system_maintenance(true); manual_system_maintenance(true);
@@ -667,7 +655,7 @@ static int _dump_emmc_part(emmc_tool_gui_t *gui, char *sd_path, int active_part,
} }
else else
{ {
strcpy(gui->txt_buf, "#FFDD00 Retrying...#\n"); s_printf(gui->txt_buf, "#FFDD00 Retrying...#\n");
lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf); lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf);
manual_system_maintenance(true); manual_system_maintenance(true);
} }
@@ -698,6 +686,7 @@ static int _dump_emmc_part(emmc_tool_gui_t *gui, char *sd_path, int active_part,
s_printf(gui->txt_buf, " "SYMBOL_DOT" %d%%", pct); s_printf(gui->txt_buf, " "SYMBOL_DOT" %d%%", pct);
lv_label_set_text(gui->label_pct, gui->txt_buf); lv_label_set_text(gui->label_pct, gui->txt_buf);
manual_system_maintenance(true); manual_system_maintenance(true);
prevPct = pct; prevPct = pct;
} }
@@ -715,7 +704,7 @@ static int _dump_emmc_part(emmc_tool_gui_t *gui, char *sd_path, int active_part,
// Check for cancellation combo. // Check for cancellation combo.
if (btn_read_vol() == (BTN_VOL_UP | BTN_VOL_DOWN)) if (btn_read_vol() == (BTN_VOL_UP | BTN_VOL_DOWN))
{ {
strcpy(gui->txt_buf, "\n#FFDD00 The backup was cancelled!#\n"); s_printf(gui->txt_buf, "\n#FFDD00 The backup was cancelled!#\n");
lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf); lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf);
manual_system_maintenance(true); manual_system_maintenance(true);
@@ -736,12 +725,12 @@ static int _dump_emmc_part(emmc_tool_gui_t *gui, char *sd_path, int active_part,
f_close(&fp); f_close(&fp);
free(clmt); free(clmt);
if (verification && !gui->raw_emummc) if (n_cfg.verification && !gui->raw_emummc)
{ {
// Verify last part or single file backup. // Verify last part or single file backup.
if (_emmc_sd_copy_verify(gui, storage, lbaStartPart, outFilename, part) == VERIF_STATUS_ERROR) if (_dump_emmc_verify(gui, storage, lbaStartPart, outFilename, part))
{ {
strcpy(gui->txt_buf, "\n#FFDD00 Please try again...#\n"); s_printf(gui->txt_buf, "\n#FFDD00 Please try again...#\n");
lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf); lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf);
manual_system_maintenance(true); manual_system_maintenance(true);
@@ -781,14 +770,16 @@ void dump_emmc_selected(emmcPartType_t dumpType, emmc_tool_gui_t *gui)
lv_label_set_text(gui->label_info, "Checking for available free space..."); lv_label_set_text(gui->label_info, "Checking for available free space...");
manual_system_maintenance(true); manual_system_maintenance(true);
if (!sd_mount()) if (!boot_storage_mount())
{ {
lv_label_set_text(gui->label_info, "#FFDD00 Failed to init SD!#"); lv_label_set_text(gui->label_info, "#FFDD00 Failed to storage!#");
goto out; goto out;
} }
// Get SD Card free space for Partial Backup. // Get SD Card free space for Partial Backup.
f_getfree("", &sd_fs.free_clst, NULL); FATFS *fs = boot_storage_get_fs();
f_getfree("", &fs->free_clst, NULL);
if (!emmc_initialize(false)) if (!emmc_initialize(false))
{ {
@@ -845,9 +836,9 @@ void dump_emmc_selected(emmcPartType_t dumpType, emmc_tool_gui_t *gui)
res = _dump_emmc_part(gui, sdPath, i, &emmc_storage, &bootPart); res = _dump_emmc_part(gui, sdPath, i, &emmc_storage, &bootPart);
if (!res) if (!res)
strcpy(txt_buf, "#FFDD00 Failed!#\n"); s_printf(txt_buf, "#FFDD00 Failed!#\n");
else else
strcpy(txt_buf, "Done!\n"); s_printf(txt_buf, "Done!\n");
lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, txt_buf); lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, txt_buf);
manual_system_maintenance(true); manual_system_maintenance(true);
@@ -886,12 +877,12 @@ void dump_emmc_selected(emmcPartType_t dumpType, emmc_tool_gui_t *gui)
// If a part failed, don't continue. // If a part failed, don't continue.
if (!res) if (!res)
{ {
strcpy(txt_buf, "#FFDD00 Failed!#\n"); s_printf(txt_buf, "#FFDD00 Failed!#\n");
lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, txt_buf); lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, txt_buf);
break; break;
} }
else else
strcpy(txt_buf, "Done!\n"); s_printf(txt_buf, "Done!\n");
lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, txt_buf); lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, txt_buf);
manual_system_maintenance(true); manual_system_maintenance(true);
@@ -928,9 +919,9 @@ void dump_emmc_selected(emmcPartType_t dumpType, emmc_tool_gui_t *gui)
res = _dump_emmc_part(gui, sdPath, 2, &emmc_storage, &rawPart); res = _dump_emmc_part(gui, sdPath, 2, &emmc_storage, &rawPart);
if (!res) if (!res)
strcpy(txt_buf, "#FFDD00 Failed!#\n"); s_printf(txt_buf, "#FFDD00 Failed!#\n");
else else
strcpy(txt_buf, "Done!\n"); s_printf(txt_buf, "Done!\n");
lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, txt_buf); lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, txt_buf);
manual_system_maintenance(true); manual_system_maintenance(true);
@@ -954,11 +945,11 @@ out:
free(txt_buf); free(txt_buf);
free(gui->base_path); free(gui->base_path);
if (!partial_sd_full_unmount) if (!partial_sd_full_unmount)
sd_unmount(); boot_storage_unmount();
else else
{ {
partial_sd_full_unmount = false; partial_sd_full_unmount = false;
sd_end(); boot_storage_end();
} }
} }
@@ -966,7 +957,6 @@ static int _restore_emmc_part(emmc_tool_gui_t *gui, char *sd_path, int active_pa
{ {
static const u32 SECTORS_TO_MIB_COEFF = 11; static const u32 SECTORS_TO_MIB_COEFF = 11;
u32 verification = n_cfg.verification;
u32 lba_end = part->lba_end; u32 lba_end = part->lba_end;
u32 totalSectors = part->lba_end - part->lba_start + 1; u32 totalSectors = part->lba_end - part->lba_start + 1;
u32 currPartIdx = 0; u32 currPartIdx = 0;
@@ -983,8 +973,8 @@ static int _restore_emmc_part(emmc_tool_gui_t *gui, char *sd_path, int active_pa
lv_bar_set_value(gui->bar, 0); lv_bar_set_value(gui->bar, 0);
lv_label_set_text(gui->label_pct, " "SYMBOL_DOT" 0%"); lv_label_set_text(gui->label_pct, " "SYMBOL_DOT" 0%");
lv_bar_set_style(gui->bar, LV_BAR_STYLE_BG, gui->bar_orange_bg); lv_bar_set_style(gui->bar, LV_BAR_STYLE_BG, lv_theme_get_current()->bar.bg);
lv_bar_set_style(gui->bar, LV_BAR_STYLE_INDIC, gui->bar_orange_ind); lv_bar_set_style(gui->bar, LV_BAR_STYLE_INDIC, gui->bar_white_ind);
manual_system_maintenance(true); manual_system_maintenance(true);
bool use_multipart = false; bool use_multipart = false;
@@ -997,7 +987,7 @@ static int _restore_emmc_part(emmc_tool_gui_t *gui, char *sd_path, int active_pa
if (f_stat(outFilename, &fno)) if (f_stat(outFilename, &fno))
{ {
// If not, check if there are partial files and the total size matches. // If not, check if there are partial files and the total size matches.
strcpy(gui->txt_buf, "\nNo single file, checking for part files...\n"); s_printf(gui->txt_buf, "\nNo single file, checking for part files...\n");
lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf); lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf);
manual_system_maintenance(true); manual_system_maintenance(true);
@@ -1023,7 +1013,7 @@ static int _restore_emmc_part(emmc_tool_gui_t *gui, char *sd_path, int active_pa
if ((u32)((u64)totalCheckFileSize >> (u64)9) > totalSectors) if ((u32)((u64)totalCheckFileSize >> (u64)9) > totalSectors)
{ {
strcpy(gui->txt_buf, "\n#FF8000 Size of SD Card split backup exceeds#\n#FF8000 eMMC's selected part size!#\n#FFDD00 Aborting...#"); s_printf(gui->txt_buf, "\n#FF8000 Size of SD Card split backup exceeds#\n#FF8000 eMMC's selected part size!#\n#FFDD00 Aborting...#");
lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf); lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf);
manual_system_maintenance(true); manual_system_maintenance(true);
@@ -1045,14 +1035,13 @@ static int _restore_emmc_part(emmc_tool_gui_t *gui, char *sd_path, int active_pa
{ {
// Set new total sectors and lba end sector for percentage calculations. // Set new total sectors and lba end sector for percentage calculations.
totalSectors = (u32)((u64)totalCheckFileSize >> (u64)9); totalSectors = (u32)((u64)totalCheckFileSize >> (u64)9);
part->lba_end = totalSectors + part->lba_start - 1; lba_end = totalSectors + part->lba_start - 1;
lba_end = part->lba_end;
} }
// Restore folder is empty. // Restore folder is empty.
if (!numSplitParts) if (!numSplitParts)
{ {
strcpy(gui->txt_buf, "\n#FFDD00 Restore folder is empty.#\n\n"); s_printf(gui->txt_buf, "\n#FFDD00 Restore folder is empty.#\n\n");
lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf); lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf);
manual_system_maintenance(true); manual_system_maintenance(true);
@@ -1065,7 +1054,7 @@ static int _restore_emmc_part(emmc_tool_gui_t *gui, char *sd_path, int active_pa
if (check_4MB_aligned && (((u64)fno.fsize) % SZ_4M)) if (check_4MB_aligned && (((u64)fno.fsize) % SZ_4M))
{ {
strcpy(gui->txt_buf, "\n#FFDD00 The split file must be a#\n#FFDD00 multiple of 4 MiB.#\n#FFDD00 Aborting...#"); s_printf(gui->txt_buf, "\n#FFDD00 The split file must be a#\n#FFDD00 multiple of 4 MiB.#\n#FFDD00 Aborting...#");
lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf); lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf);
manual_system_maintenance(true); manual_system_maintenance(true);
@@ -1093,7 +1082,7 @@ static int _restore_emmc_part(emmc_tool_gui_t *gui, char *sd_path, int active_pa
if (!(btn_wait() & BTN_POWER)) if (!(btn_wait() & BTN_POWER))
{ {
lv_obj_del(warn_mbox_bg); lv_obj_del(warn_mbox_bg);
strcpy(gui->txt_buf, "\n#FF0000 Size of SD Card split backup does not match#\n#FF0000 eMMC's selected part size!#\n"); s_printf(gui->txt_buf, "\n#FF0000 Size of SD Card split backup does not match#\n#FF0000 eMMC's selected part size!#\n");
lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf); lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf);
manual_system_maintenance(true); manual_system_maintenance(true);
@@ -1103,8 +1092,7 @@ static int _restore_emmc_part(emmc_tool_gui_t *gui, char *sd_path, int active_pa
// Set new total sectors and lba end sector for percentage calculations. // Set new total sectors and lba end sector for percentage calculations.
totalSectors = (u32)((u64)totalCheckFileSize >> (u64)9); totalSectors = (u32)((u64)totalCheckFileSize >> (u64)9);
part->lba_end = totalSectors + part->lba_start - 1; lba_end = totalSectors + part->lba_start - 1;
lba_end = part->lba_end;
} }
use_multipart = true; use_multipart = true;
_update_filename(outFilename, sdPathLen, 0); _update_filename(outFilename, sdPathLen, 0);
@@ -1149,7 +1137,7 @@ multipart_not_allowed:
{ {
if (((u32)((u64)f_size(&fp) >> (u64)9)) > totalSectors) if (((u32)((u64)f_size(&fp) >> (u64)9)) > totalSectors)
{ {
strcpy(gui->txt_buf, "\n#FF8000 Size of SD Card backup exceeds#\n#FF8000 eMMC's selected part size!#\n#FFDD00 Aborting...#"); s_printf(gui->txt_buf, "\n#FF8000 Size of SD Card backup exceeds#\n#FF8000 eMMC's selected part size!#\n#FFDD00 Aborting...#");
lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf); lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf);
manual_system_maintenance(true); manual_system_maintenance(true);
@@ -1168,7 +1156,7 @@ multipart_not_allowed:
if (!(btn_wait() & BTN_POWER)) if (!(btn_wait() & BTN_POWER))
{ {
lv_obj_del(warn_mbox_bg); lv_obj_del(warn_mbox_bg);
strcpy(gui->txt_buf, "\n#FF0000 Size of the SD Card backup does not match#\n#FF0000 eMMC's selected part size.#\n"); s_printf(gui->txt_buf, "\n#FF0000 Size of the SD Card backup does not match#\n#FF0000 eMMC's selected part size.#\n");
lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf); lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf);
manual_system_maintenance(true); manual_system_maintenance(true);
@@ -1212,7 +1200,7 @@ multipart_not_allowed:
_get_valid_partition(&sector_start, &sector_size, &part_idx, false); _get_valid_partition(&sector_start, &sector_size, &part_idx, false);
if (!part_idx || !sector_size) if (!part_idx || !sector_size)
{ {
strcpy(gui->txt_buf, "\n#FFDD00 Failed to find a partition...#\n"); s_printf(gui->txt_buf, "\n#FFDD00 Failed to find a partition...#\n");
lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf); lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf);
manual_system_maintenance(true); manual_system_maintenance(true);
@@ -1234,25 +1222,17 @@ multipart_not_allowed:
memset(&fp, 0, sizeof(fp)); memset(&fp, 0, sizeof(fp));
currPartIdx++; currPartIdx++;
if (verification && !gui->raw_emummc) if (n_cfg.verification && !gui->raw_emummc)
{ {
// Verify part. // Verify part.
res = _emmc_sd_copy_verify(gui, storage, lbaStartPart, outFilename, part); if (_dump_emmc_verify(gui, storage, lbaStartPart, outFilename, part))
switch (res)
{ {
case VERIF_STATUS_OK: s_printf(gui->txt_buf, "\n#FFDD00 Please try again...#\n");
break;
case VERIF_STATUS_ERROR:
strcpy(gui->txt_buf, "\n#FFDD00 Please try again...#\n");
lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf); lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf);
manual_system_maintenance(true); manual_system_maintenance(true);
return 0; return 0;
case VERIF_STATUS_ABORT:
verification = 0;
break;
} }
lv_bar_set_style(gui->bar, LV_BAR_STYLE_BG, gui->bar_orange_bg);
lv_bar_set_style(gui->bar, LV_BAR_STYLE_INDIC, gui->bar_orange_ind);
} }
_update_filename(outFilename, sdPathLen, currPartIdx); _update_filename(outFilename, sdPathLen, currPartIdx);
@@ -1320,7 +1300,7 @@ multipart_not_allowed:
msleep(150); msleep(150);
if (retryCount >= 3) if (retryCount >= 3)
{ {
strcpy(gui->txt_buf, "#FF0000 Aborting...#\n" s_printf(gui->txt_buf, "#FF0000 Aborting...#\n"
"#FF0000 This device may be in an inoperative state!#\n" "#FF0000 This device may be in an inoperative state!#\n"
"#FFDD00 Please try again now!#\n"); "#FFDD00 Please try again now!#\n");
lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf); lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf);
@@ -1332,7 +1312,7 @@ multipart_not_allowed:
} }
else else
{ {
strcpy(gui->txt_buf, "#FFDD00 Retrying...#\n"); s_printf(gui->txt_buf, "#FFDD00 Retrying...#\n");
lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf); lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf);
manual_system_maintenance(true); manual_system_maintenance(true);
} }
@@ -1364,12 +1344,12 @@ multipart_not_allowed:
f_close(&fp); f_close(&fp);
free(clmt); free(clmt);
if (verification && !gui->raw_emummc) if (n_cfg.verification && !gui->raw_emummc)
{ {
// Verify restored data. // Verify restored data.
if (_emmc_sd_copy_verify(gui, storage, lbaStartPart, outFilename, part) == VERIF_STATUS_ERROR) if (_dump_emmc_verify(gui, storage, lbaStartPart, outFilename, part))
{ {
strcpy(gui->txt_buf, "\n#FFDD00 Please try again...#\n"); s_printf(gui->txt_buf, "#FFDD00 Please try again...#\n");
lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf); lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf);
manual_system_maintenance(true); manual_system_maintenance(true);
@@ -1394,7 +1374,7 @@ multipart_not_allowed:
f_close(&fp_raw); f_close(&fp_raw);
s_printf(sdPath, "emuMMC/RAW%d", part_idx); s_printf(sdPath, "emuMMC/RAW%d", part_idx);
save_emummc_cfg(part_idx, sector_start, sdPath); save_emummc_cfg(part_idx, sector_start, sdPath, DRIVE_SD);
} }
return 1; return 1;
@@ -1413,18 +1393,12 @@ void restore_emmc_selected(emmcPartType_t restoreType, emmc_tool_gui_t *gui)
manual_system_maintenance(true); manual_system_maintenance(true);
if (!gui->raw_emummc) s_printf(txt_buf,
strcpy(txt_buf, "#FFDD00 This may render the device inoperative!#"); "#FFDD00 This may render the device inoperative!#\n\n"
else "#FFDD00 Are you really sure?#");
strcpy(txt_buf, "#FFDD00 This may render the emuMMC inoperative!#");
strcat(txt_buf, "\n\n#FFDD00 Are you really sure?#");
if (gui->raw_emummc)
strcat(txt_buf, "\n\nOnly the 1st emuMMC found can be restored!");
if ((restoreType & PART_BOOT) || (restoreType & PART_GP_ALL)) if ((restoreType & PART_BOOT) || (restoreType & PART_GP_ALL))
{ {
strcat(txt_buf, s_printf(txt_buf + strlen(txt_buf),
"\n\nThe mode you selected will only restore\nthe partitions that it can find.\n" "\n\nThe mode you selected will only restore\nthe partitions that it can find.\n"
"If it is not found, it will be skipped\nand continue with the next."); "If it is not found, it will be skipped\nand continue with the next.");
} }
@@ -1513,9 +1487,9 @@ void restore_emmc_selected(emmcPartType_t restoreType, emmc_tool_gui_t *gui)
res = _restore_emmc_part(gui, sdPath, i, &emmc_storage, &bootPart, false); res = _restore_emmc_part(gui, sdPath, i, &emmc_storage, &bootPart, false);
if (!res) if (!res)
strcpy(txt_buf, "#FFDD00 Failed!#\n"); s_printf(txt_buf, "#FFDD00 Failed!#\n");
else if (res > 0) else if (res > 0)
strcpy(txt_buf, "Done!\n"); s_printf(txt_buf, "Done!\n");
if (res >= 0) if (res >= 0)
lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, txt_buf); lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, txt_buf);
@@ -1549,9 +1523,9 @@ void restore_emmc_selected(emmcPartType_t restoreType, emmc_tool_gui_t *gui)
res = _restore_emmc_part(gui, sdPath, 0, &emmc_storage, part, false); res = _restore_emmc_part(gui, sdPath, 0, &emmc_storage, part, false);
if (!res) if (!res)
strcpy(txt_buf, "#FFDD00 Failed!#\n"); s_printf(txt_buf, "#FFDD00 Failed!#\n");
else if (res > 0) else if (res > 0)
strcpy(txt_buf, "Done!\n"); s_printf(txt_buf, "Done!\n");
if (res >= 0) if (res >= 0)
lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, txt_buf); lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, txt_buf);
@@ -1588,9 +1562,9 @@ void restore_emmc_selected(emmcPartType_t restoreType, emmc_tool_gui_t *gui)
res = _restore_emmc_part(gui, sdPath, 2, &emmc_storage, &rawPart, true); res = _restore_emmc_part(gui, sdPath, 2, &emmc_storage, &rawPart, true);
if (!res) if (!res)
strcpy(txt_buf, "#FFDD00 Failed!#\n"); s_printf(txt_buf, "#FFDD00 Failed!#\n");
else if (res > 0) else if (res > 0)
strcpy(txt_buf, "Done!\n"); s_printf(txt_buf, "Done!\n");
if (res >= 0) if (res >= 0)
lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, txt_buf); lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, txt_buf);

File diff suppressed because it is too large Load Diff

View File

@@ -30,11 +30,9 @@ typedef struct _emummc_cfg_t
} emummc_cfg_t; } emummc_cfg_t;
void load_emummc_cfg(emummc_cfg_t *emu_info); void load_emummc_cfg(emummc_cfg_t *emu_info);
void save_emummc_cfg(u32 part_idx, u32 sector_start, const char *path); void save_emummc_cfg(u32 part_idx, u32 sector_start, const char *path, u8 drive);
void dump_emummc_file(emmc_tool_gui_t *gui); void dump_emummc_file(emmc_tool_gui_t *gui, u32 resized_cnt, u8 drive);
void dump_emummc_raw(emmc_tool_gui_t *gui, int part_idx, u32 sector_start, u32 resized_count); void dump_emummc_raw(emmc_tool_gui_t *gui, int part_idx, u32 sector_start, u32 resized_count, u8 drive);
void update_emummc_base_folder(char *outFilename, u32 sdPathLen, u32 currPartIdx); void update_emummc_base_folder(char *outFilename, u32 sdPathLen, u32 currPartIdx);
int emummc_raw_derive_bis_keys();
#endif #endif

View File

@@ -19,6 +19,7 @@
#include <bdk.h> #include <bdk.h>
#include "gui.h" #include "gui.h"
#include "gui_emu_tools.h"
#include "gui_emummc_tools.h" #include "gui_emummc_tools.h"
#include "gui_tools.h" #include "gui_tools.h"
#include "gui_info.h" #include "gui_info.h"
@@ -29,6 +30,7 @@
#include "../config.h" #include "../config.h"
#include <libs/fatfs/ff.h> #include <libs/fatfs/ff.h>
#include <storage/boot_storage.h>
extern volatile boot_cfg_t *b_cfg; extern volatile boot_cfg_t *b_cfg;
extern volatile nyx_storage_t *nyx_str; extern volatile nyx_storage_t *nyx_str;
@@ -36,7 +38,7 @@ extern volatile nyx_storage_t *nyx_str;
extern lv_res_t launch_payload(lv_obj_t *list); extern lv_res_t launch_payload(lv_obj_t *list);
static bool disp_init_done = false; static bool disp_init_done = false;
static bool do_auto_reload = false; static bool do_reload = false;
lv_style_t hint_small_style; lv_style_t hint_small_style;
lv_style_t hint_small_style_white; lv_style_t hint_small_style_white;
@@ -187,7 +189,7 @@ static void _save_log_to_bmp(char *fname)
char path[0x80]; char path[0x80];
strcpy(path, "bootloader/screenshots"); strcpy(path, "bootloader/screenshots");
s_printf(path + strlen(path), "/nyx%s_log.bmp", fname); s_printf(path + strlen(path), "/nyx%s_log.bmp", fname);
sd_save_to_file(bitmap, file_size, path); boot_storage_save_to_file(bitmap, file_size, path);
free(bitmap); free(bitmap);
free(fb); free(fb);
@@ -200,8 +202,8 @@ static void _save_fb_to_bmp()
if (get_tmr_ms() < timer) if (get_tmr_ms() < timer)
return; return;
if (do_auto_reload) if (do_reload)
goto exit; return;
// Invalidate data. // Invalidate data.
bpmp_mmu_maintenance(BPMP_MMU_MAINT_INVALID_WAY, false); bpmp_mmu_maintenance(BPMP_MMU_MAINT_INVALID_WAY, false);
@@ -271,7 +273,7 @@ static void _save_fb_to_bmp()
bmp->res_v = 2834; bmp->res_v = 2834;
bmp->rsvd2 = 0; bmp->rsvd2 = 0;
sd_mount(); boot_storage_mount();
char path[0x80]; char path[0x80];
@@ -288,7 +290,7 @@ static void _save_fb_to_bmp()
s_printf(path + strlen(path), "/nyx%s.bmp", fname); s_printf(path + strlen(path), "/nyx%s.bmp", fname);
// Save screenshot and log. // Save screenshot and log.
int res = sd_save_to_file(bitmap, file_size, path); int res = boot_storage_save_to_file(bitmap, file_size, path);
if (!res) if (!res)
_save_log_to_bmp(fname); _save_log_to_bmp(fname);
@@ -304,7 +306,6 @@ static void _save_fb_to_bmp()
manual_system_maintenance(true); manual_system_maintenance(true);
lv_mbox_start_auto_close(mbox, 4000); lv_mbox_start_auto_close(mbox, 4000);
exit:
// Set timer to 2s. // Set timer to 2s.
timer = get_tmr_ms() + 2000; timer = get_tmr_ms() + 2000;
} }
@@ -664,7 +665,7 @@ void manual_system_maintenance(bool refresh)
lv_img_dsc_t *bmp_to_lvimg_obj(const char *path) lv_img_dsc_t *bmp_to_lvimg_obj(const char *path)
{ {
u32 fsize; u32 fsize;
u8 *bitmap = sd_file_read(path, &fsize); u8 *bitmap = boot_storage_file_read(path, &fsize);
if (!bitmap) if (!bitmap)
return NULL; return NULL;
@@ -794,7 +795,7 @@ lv_res_t mbox_action(lv_obj_t *btns, const char *txt)
bool nyx_emmc_check_battery_enough() bool nyx_emmc_check_battery_enough()
{ {
if (h_cfg.devmode) if (fuse_read_hw_state() == FUSE_NX_HW_STATE_DEV)
return true; return true;
int batt_volt = 0; int batt_volt = 0;
@@ -934,34 +935,17 @@ static void _launch_hos(u8 autoboot, u8 autoboot_list)
void (*main_ptr)() = (void *)nyx_str->hekate; void (*main_ptr)() = (void *)nyx_str->hekate;
boot_storage_end();
sd_end(); sd_end();
emmc_end();
hw_deinit(false); hw_deinit(false);
(*main_ptr)(); (*main_ptr)();
} }
void reload_nyx(lv_obj_t *obj, bool force) void reload_nyx()
{ {
if (!force)
{
sd_mount();
// Check that Nyx still exists.
if (f_stat("bootloader/sys/nyx.bin", NULL))
{
sd_unmount();
// Remove lvgl object in case of being invoked from a window.
if (obj)
lv_obj_del(obj);
do_auto_reload = false;
return;
}
}
b_cfg->boot_cfg = BOOT_CFG_AUTOBOOT_EN; b_cfg->boot_cfg = BOOT_CFG_AUTOBOOT_EN;
b_cfg->autoboot = 0; b_cfg->autoboot = 0;
b_cfg->autoboot_list = 0; b_cfg->autoboot_list = 0;
@@ -969,6 +953,9 @@ void reload_nyx(lv_obj_t *obj, bool force)
void (*main_ptr)() = (void *)nyx_str->hekate; void (*main_ptr)() = (void *)nyx_str->hekate;
// TODO:
boot_storage_end();
emmc_end();
sd_end(); sd_end();
hw_deinit(false); hw_deinit(false);
@@ -979,7 +966,7 @@ void reload_nyx(lv_obj_t *obj, bool force)
static lv_res_t reload_action(lv_obj_t *btns, const char *txt) static lv_res_t reload_action(lv_obj_t *btns, const char *txt)
{ {
if (!lv_btnm_get_pressed(btns)) if (!lv_btnm_get_pressed(btns))
reload_nyx(NULL, false); reload_nyx();
return mbox_action(btns, txt); return mbox_action(btns, txt);
} }
@@ -1001,7 +988,7 @@ static lv_res_t _removed_sd_action(lv_obj_t *btns, const char *txt)
break; break;
case 2: case 2:
sd_end(); sd_end();
do_auto_reload = false; do_reload = false;
break; break;
} }
@@ -1010,14 +997,12 @@ static lv_res_t _removed_sd_action(lv_obj_t *btns, const char *txt)
static void _check_sd_card_removed(void *params) static void _check_sd_card_removed(void *params)
{ {
static lv_obj_t *dark_bg = NULL;
// The following checks if SDMMC_1 is initialized. // The following checks if SDMMC_1 is initialized.
// If yes and card was removed, shows a message box, // If yes and card was removed, shows a message box,
// that will reload Nyx, when the card is inserted again. // that will reload Nyx, when the card is inserted again.
if (!do_auto_reload && sd_get_card_removed()) if (!do_reload && sd_get_card_removed() && boot_storage_get_drive() == DRIVE_SD)
{ {
dark_bg = lv_obj_create(lv_scr_act(), NULL); lv_obj_t *dark_bg = lv_obj_create(lv_scr_act(), NULL);
lv_obj_set_style(dark_bg, &mbox_darken); lv_obj_set_style(dark_bg, &mbox_darken);
lv_obj_set_size(dark_bg, LV_HOR_RES, LV_VER_RES); lv_obj_set_size(dark_bg, LV_HOR_RES, LV_VER_RES);
@@ -1033,12 +1018,12 @@ static void _check_sd_card_removed(void *params)
lv_obj_align(mbox, NULL, LV_ALIGN_CENTER, 0, 0); lv_obj_align(mbox, NULL, LV_ALIGN_CENTER, 0, 0);
lv_obj_set_top(mbox, true); lv_obj_set_top(mbox, true);
do_auto_reload = true; do_reload = true;
} }
// If in reload state and card was inserted, reload nyx. // If in reload state and card was inserted, reload nyx.
if (do_auto_reload && !sd_get_card_removed()) if (do_reload && !sd_get_card_removed() && boot_storage_get_drive() == DRIVE_SD)
reload_nyx(dark_bg, false); reload_nyx();
} }
lv_task_t *task_emmc_errors; lv_task_t *task_emmc_errors;
@@ -1472,14 +1457,15 @@ static lv_res_t _create_mbox_payloads(lv_obj_t *btn)
lv_obj_set_size(list, LV_HOR_RES * 3 / 7, LV_VER_RES * 3 / 7); lv_obj_set_size(list, LV_HOR_RES * 3 / 7, LV_VER_RES * 3 / 7);
lv_list_set_single_mode(list, true); lv_list_set_single_mode(list, true);
if (!sd_mount()) if (!boot_storage_mount())
{ {
// TODO: may not be SD, change error
lv_mbox_set_text(mbox, "#FFDD00 Failed to init SD!#"); lv_mbox_set_text(mbox, "#FFDD00 Failed to init SD!#");
goto out_end; goto out_end;
} }
dirlist_t *filelist = dirlist("bootloader/payloads", NULL, 0); dirlist_t *filelist = dirlist("bootloader/payloads", NULL, false, false);
sd_unmount(); sd_unmount();
u32 i = 0; u32 i = 0;
@@ -1784,7 +1770,7 @@ static lv_res_t _create_window_home_launch(lv_obj_t *btn)
u32 curr_btn_idx = 0; // Active buttons. u32 curr_btn_idx = 0; // Active buttons.
LIST_INIT(ini_sections); LIST_INIT(ini_sections);
if (!sd_mount()) if (!boot_storage_mount())
goto failed_sd_mount; goto failed_sd_mount;
// Check if we use custom system icons. // Check if we use custom system icons.
@@ -1980,7 +1966,7 @@ failed_sd_mount:
if (curr_btn_idx < 1) if (curr_btn_idx < 1)
no_boot_entries = true; no_boot_entries = true;
sd_unmount(); boot_storage_unmount();
free(tmp_path); free(tmp_path);
@@ -2147,7 +2133,7 @@ static void _create_tab_home(lv_theme_t *th, lv_obj_t *parent)
label_btn = lv_label_create(btn_emummc, label_btn); label_btn = lv_label_create(btn_emummc, label_btn);
s_printf(btn_colored_text, "%s%s", text_color, " "SYMBOL_LIST"#"); s_printf(btn_colored_text, "%s%s", text_color, " "SYMBOL_LIST"#");
lv_label_set_text(label_btn, btn_colored_text); lv_label_set_text(label_btn, btn_colored_text);
lv_btn_set_action(btn_emummc, LV_BTN_ACTION_CLICK, create_win_emummc_tools); lv_btn_set_action(btn_emummc, LV_BTN_ACTION_CLICK, create_win_emu_tools);
lv_btn_set_layout(btn_emummc, LV_LAYOUT_OFF); lv_btn_set_layout(btn_emummc, LV_LAYOUT_OFF);
lv_obj_align(label_btn, NULL, LV_ALIGN_CENTER, 0, -28); lv_obj_align(label_btn, NULL, LV_ALIGN_CENTER, 0, -28);
lv_obj_set_pos(btn_emummc, 959, 160); lv_obj_set_pos(btn_emummc, 959, 160);
@@ -2179,7 +2165,7 @@ static lv_res_t _save_options_action(lv_obj_t *btn)
int res = 0; int res = 0;
if (sd_mount()) if (boot_storage_mount())
res = !create_config_entry(); res = !create_config_entry();
if (res) if (res)
@@ -2191,7 +2177,7 @@ static lv_res_t _save_options_action(lv_obj_t *btn)
nyx_options_clear_ini_changes_made(); nyx_options_clear_ini_changes_made();
sd_unmount(); boot_storage_unmount();
return LV_RES_OK; return LV_RES_OK;
} }

View File

@@ -28,10 +28,7 @@ typedef struct _emmc_tool_gui_t
lv_obj_t *bar; lv_obj_t *bar;
lv_style_t *bar_teal_bg; lv_style_t *bar_teal_bg;
lv_style_t *bar_teal_ind; lv_style_t *bar_teal_ind;
lv_style_t *bar_white_bg;
lv_style_t *bar_white_ind; lv_style_t *bar_white_ind;
lv_style_t *bar_orange_bg;
lv_style_t *bar_orange_ind;
char *txt_buf; char *txt_buf;
char *base_path; char *base_path;
bool raw_emummc; bool raw_emummc;

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2018-2025 CTCaer * Copyright (c) 2018-2020 CTCaer
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@@ -101,7 +101,7 @@ static void _create_window_backup_restore(emmcPartType_t type, const char* win_l
lv_obj_align(label_info, label_sep, LV_ALIGN_OUT_BOTTOM_LEFT, LV_DPI / 4, LV_DPI / 10); lv_obj_align(label_info, label_sep, LV_ALIGN_OUT_BOTTOM_LEFT, LV_DPI / 4, LV_DPI / 10);
emmc_tool_gui_ctxt.label_info = label_info; emmc_tool_gui_ctxt.label_info = label_info;
static lv_style_t bar_teal_bg, bar_teal_ind, bar_orange_bg, bar_orange_ind, bar_white_ind; static lv_style_t bar_teal_bg, bar_teal_ind, bar_white_ind;
lv_style_copy(&bar_teal_bg, lv_theme_get_current()->bar.bg); lv_style_copy(&bar_teal_bg, lv_theme_get_current()->bar.bg);
bar_teal_bg.body.main_color = LV_COLOR_HEX(0x005a47); bar_teal_bg.body.main_color = LV_COLOR_HEX(0x005a47);
@@ -111,23 +111,12 @@ static void _create_window_backup_restore(emmcPartType_t type, const char* win_l
bar_teal_ind.body.main_color = LV_COLOR_HEX(0x00FFC9); bar_teal_ind.body.main_color = LV_COLOR_HEX(0x00FFC9);
bar_teal_ind.body.grad_color = bar_teal_ind.body.main_color; bar_teal_ind.body.grad_color = bar_teal_ind.body.main_color;
lv_style_copy(&bar_orange_bg, lv_theme_get_current()->bar.bg);
bar_orange_bg.body.main_color = LV_COLOR_HEX(0x755000);
bar_orange_bg.body.grad_color = bar_orange_bg.body.main_color;
lv_style_copy(&bar_orange_ind, lv_theme_get_current()->bar.indic);
bar_orange_ind.body.main_color = LV_COLOR_HEX(0xFFAE00);
bar_orange_ind.body.grad_color = bar_orange_ind.body.main_color;
lv_style_copy(&bar_white_ind, lv_theme_get_current()->bar.indic); lv_style_copy(&bar_white_ind, lv_theme_get_current()->bar.indic);
bar_white_ind.body.main_color = LV_COLOR_HEX(0xF0F0F0); bar_white_ind.body.main_color = LV_COLOR_HEX(0xF0F0F0);
bar_white_ind.body.grad_color = bar_white_ind.body.main_color; bar_white_ind.body.grad_color = bar_white_ind.body.main_color;
emmc_tool_gui_ctxt.bar_teal_bg = &bar_teal_bg; emmc_tool_gui_ctxt.bar_teal_bg = &bar_teal_bg;
emmc_tool_gui_ctxt.bar_teal_ind = &bar_teal_ind; emmc_tool_gui_ctxt.bar_teal_ind = &bar_teal_ind;
emmc_tool_gui_ctxt.bar_orange_bg = &bar_orange_bg;
emmc_tool_gui_ctxt.bar_orange_ind = &bar_orange_ind;
emmc_tool_gui_ctxt.bar_white_bg = lv_theme_get_current()->bar.bg;
emmc_tool_gui_ctxt.bar_white_ind = &bar_white_ind; emmc_tool_gui_ctxt.bar_white_ind = &bar_white_ind;
lv_obj_t *bar = lv_bar_create(h1, NULL); lv_obj_t *bar = lv_bar_create(h1, NULL);
@@ -250,15 +239,15 @@ static lv_res_t _emmc_backup_buttons_raw_toggle(lv_obj_t *btn)
else // Backup/Restore from and to emuMMC. else // Backup/Restore from and to emuMMC.
{ {
if (!emmc_btn_ctxt.restore) if (!emmc_btn_ctxt.restore)
lv_label_set_static_text(lv_obj_get_child(emmc_btn_ctxt.emmc_boot, NULL), SYMBOL_UPLOAD" SD emuMMC BOOT0 & BOOT1"); lv_label_set_static_text(lv_obj_get_child(emmc_btn_ctxt.emmc_boot, NULL), SYMBOL_UPLOAD" emuMMC BOOT0 & BOOT1");
else else
lv_label_set_static_text(lv_obj_get_child(emmc_btn_ctxt.emmc_boot, NULL), SYMBOL_DOWNLOAD" SD emuMMC BOOT0 & BOOT1"); lv_label_set_static_text(lv_obj_get_child(emmc_btn_ctxt.emmc_boot, NULL), SYMBOL_DOWNLOAD" emuMMC BOOT0 & BOOT1");
lv_obj_realign(emmc_btn_ctxt.emmc_boot); lv_obj_realign(emmc_btn_ctxt.emmc_boot);
if (!emmc_btn_ctxt.restore) if (!emmc_btn_ctxt.restore)
lv_label_set_static_text(lv_obj_get_child(emmc_btn_ctxt.emmc_raw_gpp, NULL), SYMBOL_UPLOAD" SD emuMMC RAW GPP"); lv_label_set_static_text(lv_obj_get_child(emmc_btn_ctxt.emmc_raw_gpp, NULL), SYMBOL_UPLOAD" emuMMC RAW GPP");
else else
lv_label_set_static_text(lv_obj_get_child(emmc_btn_ctxt.emmc_raw_gpp, NULL), SYMBOL_DOWNLOAD" SD emuMMC RAW GPP"); lv_label_set_static_text(lv_obj_get_child(emmc_btn_ctxt.emmc_raw_gpp, NULL), SYMBOL_DOWNLOAD" emuMMC RAW GPP");
lv_obj_realign(emmc_btn_ctxt.emmc_raw_gpp); lv_obj_realign(emmc_btn_ctxt.emmc_raw_gpp);
lv_obj_set_click(emmc_btn_ctxt.emmc_sys, false); lv_obj_set_click(emmc_btn_ctxt.emmc_sys, false);
@@ -464,7 +453,7 @@ lv_res_t create_window_backup_restore_tool(lv_obj_t *btn)
lv_obj_t *sd_emummc_raw = lv_btn_create(h3, NULL); lv_obj_t *sd_emummc_raw = lv_btn_create(h3, NULL);
nyx_create_onoff_button(lv_theme_get_current(), h3, nyx_create_onoff_button(lv_theme_get_current(), h3,
sd_emummc_raw, SYMBOL_SD" SD emuMMC Raw Partition", _emmc_backup_buttons_raw_toggle, false); sd_emummc_raw, SYMBOL_SD" emuMMC Raw Partition", _emmc_backup_buttons_raw_toggle, false);
emmc_btn_ctxt.raw_emummc = false; emmc_btn_ctxt.raw_emummc = false;
return LV_RES_OK; return LV_RES_OK;

View File

@@ -0,0 +1,50 @@
#include "gui_emu_tools.h"
#include "gui.h"
#include "gui_emummc_tools.h"
#include <libs/lvgl/lv_core/lv_obj.h>
#include <libs/lvgl/lv_core/lv_style.h>
#include <libs/lvgl/lv_objx/lv_cont.h>
#include <libs/lvgl/lv_objx/lv_win.h>
static lv_obj_t *_create_container(lv_obj_t *parent){
static lv_style_t h_style;
lv_style_copy(&h_style, &lv_style_transp);
h_style.body.padding.inner = 0;
h_style.body.padding.hor = 0;
h_style.body.padding.ver = 0;
lv_obj_t *h1 = lv_cont_create(parent, NULL);
lv_cont_set_style(h1, &h_style);
lv_cont_set_fit(h1, false, true);
lv_obj_set_width(h1, LV_HOR_RES - 62);
lv_obj_set_click(h1, false);
lv_cont_set_layout(h1, LV_LAYOUT_OFF);
return h1;
}
lv_res_t create_win_emu_tools(lv_obj_t *btn){
lv_obj_t *win = nyx_create_standard_window(SYMBOL_EDIT " emuMMC Manage");
static lv_style_t win_style_no_pad;
lv_style_copy(&win_style_no_pad, lv_win_get_style(win, LV_WIN_STYLE_CONTENT_BG));
win_style_no_pad.body.padding.hor = 0;
win_style_no_pad.body.padding.inner = 0;
lv_win_set_style(win, LV_WIN_STYLE_CONTENT_BG, &win_style_no_pad);
/* Create container on window; win's CHILD_CHG moves it to the page, so we protect and re-parent to win */
lv_obj_t *cont = _create_container(win);
lv_obj_set_protect(cont, LV_PROTECT_PARENT);
lv_obj_set_parent(cont, win);
lv_obj_set_height(cont, 572);
create_tab_emummc_tools(cont);
/* Align to content area; y offset works now because cont stays on win */
lv_obj_t *content = lv_win_get_content(win);
lv_obj_align(cont, content, LV_ALIGN_IN_TOP_MID, -20, 50);
return LV_RES_OK;
}

View File

@@ -0,0 +1,8 @@
#ifndef _GUI_EMU_TOOLS_H_
#define _GUI_EMU_TOOLS_H_
#include <libs/lvgl/lvgl.h>
lv_res_t create_win_emu_tools(lv_obj_t *btn);
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -19,6 +19,6 @@
#include <libs/lvgl/lvgl.h> #include <libs/lvgl/lvgl.h>
lv_res_t create_win_emummc_tools(lv_obj_t *btn); lv_res_t create_tab_emummc_tools(lv_obj_t *parent);
#endif #endif

View File

@@ -23,6 +23,7 @@
#include "../hos/hos.h" #include "../hos/hos.h"
#include "../hos/pkg1.h" #include "../hos/pkg1.h"
#include <libs/fatfs/ff.h> #include <libs/fatfs/ff.h>
#include <storage/boot_storage.h>
#include <stdlib.h> #include <stdlib.h>
@@ -75,15 +76,15 @@ static lv_res_t _cal0_dump_window_action(lv_obj_t *btns, const char * txt)
if (btn_idx == 1) if (btn_idx == 1)
{ {
int error = !sd_mount(); int error = !boot_storage_mount();
if (!error) if (!error)
{ {
char path[64]; char path[64];
emmcsn_path_impl(path, "/dumps", "cal0.bin", NULL); emmcsn_path_impl(path, "/dumps", "cal0.bin", NULL);
error = sd_save_to_file((u8 *)cal0_buf, SZ_32K, path); error = boot_storage_save_to_file((u8 *)cal0_buf, SZ_32K, path);
sd_unmount(); boot_storage_unmount();
} }
_create_window_dump_done(error, "cal0.bin"); _create_window_dump_done(error, "cal0.bin");
@@ -95,7 +96,7 @@ static lv_res_t _cal0_dump_window_action(lv_obj_t *btns, const char * txt)
static lv_res_t _battery_dump_window_action(lv_obj_t * btn) static lv_res_t _battery_dump_window_action(lv_obj_t * btn)
{ {
int error = !sd_mount(); int error = !boot_storage_mount();
if (!error) if (!error)
{ {
@@ -105,9 +106,9 @@ static lv_res_t _battery_dump_window_action(lv_obj_t * btn)
max17050_dump_regs(buf); max17050_dump_regs(buf);
emmcsn_path_impl(path, "/dumps", "fuel_gauge.bin", NULL); emmcsn_path_impl(path, "/dumps", "fuel_gauge.bin", NULL);
error = sd_save_to_file((u8 *)buf, 0x200, path); error = boot_storage_save_to_file((u8 *)buf, 0x200, path);
sd_unmount(); boot_storage_unmount();
} }
_create_window_dump_done(error, "fuel_gauge.bin"); _create_window_dump_done(error, "fuel_gauge.bin");
@@ -119,7 +120,7 @@ static lv_res_t _bootrom_dump_window_action(lv_obj_t * btn)
{ {
static const u32 BOOTROM_SIZE = 0x18000; static const u32 BOOTROM_SIZE = 0x18000;
int error = !sd_mount(); int error = !boot_storage_mount();
if (!error) if (!error)
{ {
char path[64]; char path[64];
@@ -129,13 +130,13 @@ static lv_res_t _bootrom_dump_window_action(lv_obj_t * btn)
if (!error) if (!error)
{ {
emmcsn_path_impl(path, "/dumps", "evp_thunks.bin", NULL); emmcsn_path_impl(path, "/dumps", "evp_thunks.bin", NULL);
error = sd_save_to_file((u8 *)iram_evp_thunks, iram_evp_thunks_len, path); error = boot_storage_save_to_file((u8 *)iram_evp_thunks, iram_evp_thunks_len, path);
} }
else else
error = 255; error = 255;
emmcsn_path_impl(path, "/dumps", "bootrom_patched.bin", NULL); emmcsn_path_impl(path, "/dumps", "bootrom_patched.bin", NULL);
int res = sd_save_to_file((u8 *)IROM_BASE, BOOTROM_SIZE, path); int res = boot_storage_save_to_file((u8 *)IROM_BASE, BOOTROM_SIZE, path);
if (!error) if (!error)
error = res; error = res;
@@ -144,13 +145,13 @@ static lv_res_t _bootrom_dump_window_action(lv_obj_t * btn)
memset((void*)IPATCH_BASE, 0, sizeof(ipatch_cam)); // Zeroing valid entries is enough but zero everything. memset((void*)IPATCH_BASE, 0, sizeof(ipatch_cam)); // Zeroing valid entries is enough but zero everything.
emmcsn_path_impl(path, "/dumps", "bootrom_unpatched.bin", NULL); emmcsn_path_impl(path, "/dumps", "bootrom_unpatched.bin", NULL);
res = sd_save_to_file((u8 *)IROM_BASE, BOOTROM_SIZE, path); res = boot_storage_save_to_file((u8 *)IROM_BASE, BOOTROM_SIZE, path);
if (!error) if (!error)
error = res; error = res;
memcpy((void*)IPATCH_BASE, ipatch_cam, sizeof(ipatch_cam)); memcpy((void*)IPATCH_BASE, ipatch_cam, sizeof(ipatch_cam));
sd_unmount(); boot_storage_unmount();
} }
_create_window_dump_done(error, "evp_thunks.bin, bootrom_patched.bin, bootrom_unpatched.bin"); _create_window_dump_done(error, "evp_thunks.bin, bootrom_patched.bin, bootrom_unpatched.bin");
@@ -180,14 +181,14 @@ static void _unlock_reserved_odm_fuses(bool lock)
static lv_res_t _fuse_dump_window_action(lv_obj_t * btn) static lv_res_t _fuse_dump_window_action(lv_obj_t * btn)
{ {
int error = !sd_mount(); int error = !boot_storage_mount();
if (!error) if (!error)
{ {
char path[128]; char path[128];
if (!h_cfg.t210b01) if (!h_cfg.t210b01)
{ {
emmcsn_path_impl(path, "/dumps", "fuse_cached_t210.bin", NULL); emmcsn_path_impl(path, "/dumps", "fuse_cached_t210.bin", NULL);
error = sd_save_to_file((u8 *)0x7000F900, 0x300, path); error = boot_storage_save_to_file((u8 *)0x7000F900, 0x300, path);
emmcsn_path_impl(path, "/dumps", "fuse_array_raw_t210.bin", NULL); emmcsn_path_impl(path, "/dumps", "fuse_array_raw_t210.bin", NULL);
} }
else else
@@ -196,10 +197,10 @@ static lv_res_t _fuse_dump_window_action(lv_obj_t * btn)
_unlock_reserved_odm_fuses(false); _unlock_reserved_odm_fuses(false);
emmcsn_path_impl(path, "/dumps", "fuse_cached_t210b01_x898.bin", NULL); emmcsn_path_impl(path, "/dumps", "fuse_cached_t210b01_x898.bin", NULL);
error = sd_save_to_file((u8 *)0x7000F898, 0x68, path); error = boot_storage_save_to_file((u8 *)0x7000F898, 0x68, path);
emmcsn_path_impl(path, "/dumps", "fuse_cached_t210b01_x900.bin", NULL); emmcsn_path_impl(path, "/dumps", "fuse_cached_t210b01_x900.bin", NULL);
if (!error) if (!error)
error = sd_save_to_file((u8 *)0x7000F900, 0x300, path); error = boot_storage_save_to_file((u8 *)0x7000F900, 0x300, path);
emmcsn_path_impl(path, "/dumps", "fuse_array_raw_t210b01.bin", NULL); emmcsn_path_impl(path, "/dumps", "fuse_array_raw_t210b01.bin", NULL);
} }
@@ -214,7 +215,7 @@ static lv_res_t _fuse_dump_window_action(lv_obj_t * btn)
if (h_cfg.t210b01) if (h_cfg.t210b01)
_unlock_reserved_odm_fuses(true); _unlock_reserved_odm_fuses(true);
sd_unmount(); boot_storage_unmount();
} }
if (!h_cfg.t210b01) if (!h_cfg.t210b01)
@@ -231,15 +232,15 @@ static lv_res_t _kfuse_dump_window_action(lv_obj_t * btn)
int error = !kfuse_read(buf); int error = !kfuse_read(buf);
if (!error) if (!error)
error = !sd_mount(); error = !boot_storage_mount();
if (!error) if (!error)
{ {
char path[64]; char path[64];
emmcsn_path_impl(path, "/dumps", "kfuses.bin", NULL); emmcsn_path_impl(path, "/dumps", "kfuses.bin", NULL);
error = sd_save_to_file((u8 *)buf, KFUSE_NUM_WORDS * 4, path); error = boot_storage_save_to_file((u8 *)buf, KFUSE_NUM_WORDS * 4, path);
sd_unmount(); boot_storage_unmount();
} }
_create_window_dump_done(error, "kfuses.bin"); _create_window_dump_done(error, "kfuses.bin");
@@ -269,7 +270,7 @@ static lv_res_t _create_mbox_cal0(lv_obj_t *btn)
lv_label_set_style(lb_desc, &monospace_text); lv_label_set_style(lb_desc, &monospace_text);
lv_obj_set_width(lb_desc, LV_HOR_RES / 9 * 4); lv_obj_set_width(lb_desc, LV_HOR_RES / 9 * 4);
sd_mount(); boot_storage_mount();
// Dump CAL0. // Dump CAL0.
int cal0_res = hos_dump_cal0(); int cal0_res = hos_dump_cal0();
@@ -290,7 +291,7 @@ static lv_res_t _create_mbox_cal0(lv_obj_t *btn)
nx_emmc_cal0_t *cal0 = (nx_emmc_cal0_t *)cal0_buf; nx_emmc_cal0_t *cal0 = (nx_emmc_cal0_t *)cal0_buf;
u32 hash[8]; u32 hash[8];
se_sha_hash_256_oneshot(hash, (u8 *)&cal0->cfg_id1, cal0->body_size); se_calc_sha256_oneshot(hash, (u8 *)&cal0->cfg_id1, cal0->body_size);
s_printf(txt_buf, s_printf(txt_buf,
"#FF8000 CAL0 Version:# %d\n" "#FF8000 CAL0 Version:# %d\n"
@@ -369,7 +370,7 @@ static lv_res_t _create_mbox_cal0(lv_obj_t *btn)
out: out:
free(txt_buf); free(txt_buf);
sd_unmount(); boot_storage_unmount();
lv_mbox_add_btns(mbox, mbox_btn_map, _cal0_dump_window_action); lv_mbox_add_btns(mbox, mbox_btn_map, _cal0_dump_window_action);
@@ -1094,6 +1095,30 @@ static lv_res_t _create_window_hw_info_status(lv_obj_t *btn)
switch (display_id) switch (display_id)
{ {
case PANEL_RR_SUPER5_OLED_V1:
strcat(txt_buf, "RR SUPER5 OLED");
switch (display_rev)
{
case 0x01:
strcat(txt_buf, "-V1");
break;
default:
strcat(txt_buf, " #FFDD00 Contact me!#");
break;
}
break;
case PANEL_RR_SUPER5_OLED_HD_V1:
strcat(txt_buf, "RR SUPER5 OLED HD");
switch (display_rev)
{
case 0x01:
strcat(txt_buf, "-V1");
break;
default:
strcat(txt_buf, " #FFDD00 Contact me!#");
break;
}
break;
case PANEL_JDI_LAM062M109A: case PANEL_JDI_LAM062M109A:
strcat(txt_buf, "JDI LAM062M109A"); strcat(txt_buf, "JDI LAM062M109A");
break; break;
@@ -1811,7 +1836,7 @@ static lv_res_t _create_mbox_benchmark(bool sd_bench)
for (u32 i = 0; i < rnd_off_cnt; i += 4) for (u32 i = 0; i < rnd_off_cnt; i += 4)
{ {
// Generate new random numbers. // Generate new random numbers.
while (!se_rng_pseudo(random_numbers, SE_RNG_BLOCK_SIZE)) while (!se_gen_prng128(random_numbers))
; ;
// Clamp offsets to 256MB range. // Clamp offsets to 256MB range.
random_offsets[i + 0] = random_numbers[0] % sct_rem_4kb; random_offsets[i + 0] = random_numbers[0] % sct_rem_4kb;
@@ -2881,7 +2906,7 @@ static bool _lockpick_exists_check()
bool found = false; bool found = false;
void *buf = malloc(0x200); void *buf = malloc(0x200);
if (sd_mount()) if (boot_storage_mount())
{ {
FIL fp; FIL fp;
if (f_open(&fp, "bootloader/payloads/Lockpick_RCM.bin", FA_READ)) if (f_open(&fp, "bootloader/payloads/Lockpick_RCM.bin", FA_READ))
@@ -2906,7 +2931,7 @@ static bool _lockpick_exists_check()
out: out:
free(buf); free(buf);
sd_unmount(); boot_storage_unmount();
return found; return found;
} }

View File

@@ -23,6 +23,7 @@
#include "../config.h" #include "../config.h"
#include <libs/lvgl/lv_themes/lv_theme_hekate.h> #include <libs/lvgl/lv_themes/lv_theme_hekate.h>
#include <libs/lvgl/lvgl.h> #include <libs/lvgl/lvgl.h>
#include <storage/boot_storage.h>
#define CLOCK_MIN_YEAR 2025 #define CLOCK_MIN_YEAR 2025
#define CLOCK_MAX_YEAR (CLOCK_MIN_YEAR + 10) #define CLOCK_MAX_YEAR (CLOCK_MIN_YEAR + 10)
@@ -224,7 +225,7 @@ static void _create_autoboot_window()
lv_obj_set_size(list_main, LV_HOR_RES * 4 / 10, LV_VER_RES * 4 / 7); lv_obj_set_size(list_main, LV_HOR_RES * 4 / 10, LV_VER_RES * 4 / 7);
lv_list_set_single_mode(list_main, true); lv_list_set_single_mode(list_main, true);
sd_mount(); boot_storage_mount();
// Parse hekate main configuration. // Parse hekate main configuration.
LIST_INIT(ini_sections); LIST_INIT(ini_sections);
@@ -285,7 +286,7 @@ static void _create_autoboot_window()
ini_free(&ini_list_sections); ini_free(&ini_list_sections);
} }
sd_unmount(); boot_storage_unmount();
} }
static lv_res_t _autoboot_hide_delay_action(lv_obj_t *btn) static lv_res_t _autoboot_hide_delay_action(lv_obj_t *btn)
@@ -429,7 +430,7 @@ static lv_res_t _save_theme_color_action(lv_obj_t *btn)
// Save nyx config. // Save nyx config.
create_nyx_config_entry(true); create_nyx_config_entry(true);
reload_nyx(NULL, false); reload_nyx();
return LV_RES_OK; return LV_RES_OK;
} }
@@ -944,7 +945,7 @@ static lv_res_t _joycon_info_dump_action(lv_obj_t * btn)
jc_pad->bt_conn_r.type = is_r_hos ? jc_pad->bt_conn_r.type : 0; jc_pad->bt_conn_r.type = is_r_hos ? jc_pad->bt_conn_r.type : 0;
save_data: save_data:
error = !sd_mount() ? 5 : 0; error = !boot_storage_mount() ? 5 : 0;
if (!error) if (!error)
{ {
@@ -958,7 +959,8 @@ save_data:
memcpy(data, &jc_pad->bt_conn_l, sizeof(jc_bt_conn_t)); memcpy(data, &jc_pad->bt_conn_l, sizeof(jc_bt_conn_t));
memcpy(data + sizeof(jc_bt_conn_t), &jc_pad->bt_conn_r, sizeof(jc_bt_conn_t)); memcpy(data + sizeof(jc_bt_conn_t), &jc_pad->bt_conn_r, sizeof(jc_bt_conn_t));
error = sd_save_to_file((u8 *)data, sizeof(jc_bt_conn_t) * 2, "switchroot/joycon_mac.bin") ? 4 : 0; // TODO: JC dump should probably go to sd?
error = boot_storage_save_to_file((u8 *)data, sizeof(jc_bt_conn_t) * 2, "switchroot/joycon_mac.bin") ? 4 : 0;
// Save readable dump. // Save readable dump.
data[0] = 0; data[0] = 0;
@@ -1080,7 +1082,7 @@ save_data:
} }
} }
sd_unmount(); boot_storage_unmount();
} }
disabled_or_cal0_issue:; disabled_or_cal0_issue:;

File diff suppressed because it is too large Load Diff

View File

@@ -25,5 +25,6 @@ void create_tab_tools(lv_theme_t *th, lv_obj_t *parent);
void nyx_run_ums(void *param); void nyx_run_ums(void *param);
bool get_set_autorcm_status(bool change); bool get_set_autorcm_status(bool change);
lv_res_t action_ums_sd(lv_obj_t *btn); lv_res_t action_ums_sd(lv_obj_t *btn);
lv_res_t action_ums_emmc_gpp(lv_obj_t *btn);
#endif #endif

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2019-2025 CTCaer * Copyright (c) 2019-2020 CTCaer
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@@ -17,7 +17,6 @@
#ifndef _GUI_TOOLS_PART_MANAGER_H_ #ifndef _GUI_TOOLS_PART_MANAGER_H_
#define _GUI_TOOLS_PART_MANAGER_H_ #define _GUI_TOOLS_PART_MANAGER_H_
lv_res_t create_window_sd_partition_manager(lv_obj_t *btn); lv_res_t create_window_partition_manager(lv_obj_t *btn, u8 drive);
lv_res_t create_window_emmc_partition_manager(lv_obj_t *btn);
#endif #endif

View File

@@ -23,6 +23,7 @@
#include <bdk.h> #include <bdk.h>
#include "hos.h" #include "hos.h"
#include <storage/boot_storage.h>
#include "../config.h" #include "../config.h"
u8 *cal0_buf = NULL; u8 *cal0_buf = NULL;
@@ -208,7 +209,7 @@ static void _hos_eks_get()
// Decrypt EKS blob. // Decrypt EKS blob.
hos_eks_mbr_t *eks = (hos_eks_mbr_t *)(mbr + 0x80); hos_eks_mbr_t *eks = (hos_eks_mbr_t *)(mbr + 0x80);
se_aes_crypt_ecb(14, DECRYPT, eks, eks, sizeof(hos_eks_mbr_t)); se_aes_crypt_ecb(14, DECRYPT, eks, sizeof(hos_eks_mbr_t), eks, sizeof(hos_eks_mbr_t));
// Check if valid and for this unit. // Check if valid and for this unit.
if (eks->magic == HOS_EKS_MAGIC && eks->lot0 == FUSE(FUSE_OPT_LOT_CODE_0)) if (eks->magic == HOS_EKS_MAGIC && eks->lot0 == FUSE(FUSE_OPT_LOT_CODE_0))
@@ -254,7 +255,7 @@ static void _hos_eks_save()
// Get keys. // Get keys.
u8 *keys = (u8 *)zalloc(SZ_8K); u8 *keys = (u8 *)zalloc(SZ_8K);
se_aes_ctx_get_keys(keys + SZ_4K, keys, SE_KEY_128_SIZE); se_get_aes_keys(keys + SZ_4K, keys, SE_KEY_128_SIZE);
// Set magic and personalized info. // Set magic and personalized info.
h_cfg.eks->magic = HOS_EKS_MAGIC; h_cfg.eks->magic = HOS_EKS_MAGIC;
@@ -269,7 +270,7 @@ static void _hos_eks_save()
// Encrypt EKS blob. // Encrypt EKS blob.
u8 *eks = malloc(sizeof(hos_eks_mbr_t)); u8 *eks = malloc(sizeof(hos_eks_mbr_t));
memcpy(eks, h_cfg.eks, sizeof(hos_eks_mbr_t)); memcpy(eks, h_cfg.eks, sizeof(hos_eks_mbr_t));
se_aes_crypt_ecb(14, ENCRYPT, eks, eks, sizeof(hos_eks_mbr_t)); se_aes_crypt_ecb(14, ENCRYPT, eks, sizeof(hos_eks_mbr_t), eks, sizeof(hos_eks_mbr_t));
// Write EKS blob to SD. // Write EKS blob to SD.
memcpy(mbr + 0x80, eks, sizeof(hos_eks_mbr_t)); memcpy(mbr + 0x80, eks, sizeof(hos_eks_mbr_t));
@@ -304,7 +305,7 @@ void hos_eks_clear(u32 mkey)
// Encrypt EKS blob. // Encrypt EKS blob.
u8 *eks = malloc(sizeof(hos_eks_mbr_t)); u8 *eks = malloc(sizeof(hos_eks_mbr_t));
memcpy(eks, h_cfg.eks, sizeof(hos_eks_mbr_t)); memcpy(eks, h_cfg.eks, sizeof(hos_eks_mbr_t));
se_aes_crypt_ecb(14, ENCRYPT, eks, eks, sizeof(hos_eks_mbr_t)); se_aes_crypt_ecb(14, ENCRYPT, eks, sizeof(hos_eks_mbr_t), eks, sizeof(hos_eks_mbr_t));
// Write EKS blob to SD. // Write EKS blob to SD.
memcpy(mbr + 0x80, eks, sizeof(hos_eks_mbr_t)); memcpy(mbr + 0x80, eks, sizeof(hos_eks_mbr_t));
@@ -381,7 +382,7 @@ int hos_keygen(pkg1_eks_t *eks, u32 mkey, tsec_ctxt_t *tsec_ctxt)
*/ */
// Use custom TSEC Hovi Keygen firmware. // Use custom TSEC Hovi Keygen firmware.
tsec_ctxt->fw = sd_file_read("bootloader/sys/thk.bin", NULL); tsec_ctxt->fw = boot_storage_file_read("bootloader/sys/thk.bin", NULL);
if (!tsec_ctxt->fw) if (!tsec_ctxt->fw)
{ {
EPRINTF("\nFailed to load thk.bin"); EPRINTF("\nFailed to load thk.bin");
@@ -423,7 +424,7 @@ int hos_keygen(pkg1_eks_t *eks, u32 mkey, tsec_ctxt_t *tsec_ctxt)
} }
// Decrypt eks and set keyslots. // Decrypt eks and set keyslots.
se_aes_crypt_ecb(12, DECRYPT, tsec_keys.tmp, eks_keyseeds[0], SE_KEY_128_SIZE); se_aes_crypt_block_ecb(12, DECRYPT, tsec_keys.tmp, eks_keyseeds[0]);
se_aes_unwrap_key(15, 14, tsec_keys.tmp); se_aes_unwrap_key(15, 14, tsec_keys.tmp);
// Derive device keys. // Derive device keys.
@@ -447,7 +448,7 @@ int hos_keygen(pkg1_eks_t *eks, u32 mkey, tsec_ctxt_t *tsec_ctxt)
se_aes_key_set(13, tsec_keys.tsec_root, SE_KEY_128_SIZE); se_aes_key_set(13, tsec_keys.tsec_root, SE_KEY_128_SIZE);
// Decrypt eks and set keyslots. // Decrypt eks and set keyslots.
se_aes_crypt_ecb(12, DECRYPT, tsec_keys.tmp, eks_keyseeds[0], SE_KEY_128_SIZE); se_aes_crypt_block_ecb(12, DECRYPT, tsec_keys.tmp, eks_keyseeds[0]);
se_aes_unwrap_key(15, 14, tsec_keys.tmp); se_aes_unwrap_key(15, 14, tsec_keys.tmp);
// Derive device keys. // Derive device keys.
@@ -469,30 +470,30 @@ int hos_keygen(pkg1_eks_t *eks, u32 mkey, tsec_ctxt_t *tsec_ctxt)
se_aes_key_set(13, tsec_keys.tsec, SE_KEY_128_SIZE); se_aes_key_set(13, tsec_keys.tsec, SE_KEY_128_SIZE);
// Derive eks keys from TSEC+SBK. // Derive eks keys from TSEC+SBK.
se_aes_crypt_ecb(13, DECRYPT, tsec_keys.tsec, eks_keyseeds[0], SE_KEY_128_SIZE); se_aes_crypt_block_ecb(13, DECRYPT, tsec_keys.tsec, eks_keyseeds[0]);
se_aes_unwrap_key(15, 14, tsec_keys.tsec); se_aes_unwrap_key(15, 14, tsec_keys.tsec);
se_aes_crypt_ecb(13, DECRYPT, tsec_keys.tsec, eks_keyseeds[mkey], SE_KEY_128_SIZE); se_aes_crypt_block_ecb(13, DECRYPT, tsec_keys.tsec, eks_keyseeds[mkey]);
se_aes_unwrap_key(13, 14, tsec_keys.tsec); se_aes_unwrap_key(13, 14, tsec_keys.tsec);
/* /*
// Verify eks CMAC. // Verify eks CMAC.
u8 cmac[SE_KEY_128_SIZE]; u8 cmac[SE_KEY_128_SIZE];
se_aes_unwrap_key(11, 13, cmac_keyseed); se_aes_unwrap_key(11, 13, cmac_keyseed);
se_aes_hash_cmac(cmac, SE_KEY_128_SIZE, 11, (void *)eks->ctr, sizeof(eks->ctr) + sizeof(eks->keys)); se_aes_cmac(cmac, SE_KEY_128_SIZE, 11, (void *)eks->ctr, sizeof(eks->ctr) + sizeof(eks->keys));
if (!memcmp(eks->cmac, cmac, SE_KEY_128_SIZE)) if (!memcmp(eks->cmac, cmac, SE_KEY_128_SIZE))
return 0; return 0;
*/ */
se_aes_crypt_ecb(13, DECRYPT, tsec_keys.tsec, cmac_keyseed, SE_KEY_128_SIZE); se_aes_crypt_block_ecb(13, DECRYPT, tsec_keys.tsec, cmac_keyseed);
se_aes_unwrap_key(11, 13, cmac_keyseed); se_aes_unwrap_key(11, 13, cmac_keyseed);
// Decrypt eks and set keyslots. // Decrypt eks and set keyslots.
se_aes_crypt_ctr(13, &eks->keys, &eks->keys, sizeof(eks_keys_t), eks->ctr); se_aes_crypt_ctr(13, &eks->keys, sizeof(eks_keys_t), &eks->keys, sizeof(eks_keys_t), eks->ctr);
se_aes_key_set(11, eks->keys.package1_key, SE_KEY_128_SIZE); se_aes_key_set(11, eks->keys.package1_key, SE_KEY_128_SIZE);
se_aes_key_set(12, eks->keys.master_kekseed, SE_KEY_128_SIZE); se_aes_key_set(12, eks->keys.master_kekseed, SE_KEY_128_SIZE);
se_aes_key_set(13, eks->keys.master_kekseed, SE_KEY_128_SIZE); se_aes_key_set(13, eks->keys.master_kekseed, SE_KEY_128_SIZE);
se_aes_crypt_ecb(12, DECRYPT, tsec_keys.tsec, master_keyseed_retail, SE_KEY_128_SIZE); se_aes_crypt_block_ecb(12, DECRYPT, tsec_keys.tsec, master_keyseed_retail);
switch (mkey) switch (mkey)
{ {
@@ -531,11 +532,12 @@ static void _hos_validate_mkey()
do do
{ {
mkey_idx--; mkey_idx--;
se_aes_crypt_ecb(7, DECRYPT, tmp_mkey, mkey_vectors[mkey_idx], SE_KEY_128_SIZE); se_aes_crypt_ecb(7, DECRYPT, tmp_mkey, SE_KEY_128_SIZE, mkey_vectors[mkey_idx], SE_KEY_128_SIZE);
for (u32 idx = 0; idx < mkey_idx; idx++) for (u32 idx = 0; idx < mkey_idx; idx++)
{ {
se_aes_key_clear(2);
se_aes_key_set(2, tmp_mkey, SE_KEY_128_SIZE); se_aes_key_set(2, tmp_mkey, SE_KEY_128_SIZE);
se_aes_crypt_ecb(2, DECRYPT, tmp_mkey, mkey_vectors[mkey_idx - 1 - idx], SE_KEY_128_SIZE); se_aes_crypt_ecb(2, DECRYPT, tmp_mkey, SE_KEY_128_SIZE, mkey_vectors[mkey_idx - 1 - idx], SE_KEY_128_SIZE);
} }
if (!memcmp(tmp_mkey, "\x00\x00\x00\x00\x00\x00\x00\x00", 8)) if (!memcmp(tmp_mkey, "\x00\x00\x00\x00\x00\x00\x00\x00", 8))
@@ -592,17 +594,19 @@ int hos_bis_keygen()
do do
{ {
mkey_idx--; mkey_idx--;
se_aes_crypt_ecb(7, DECRYPT, tmp_mkey, mkey_vectors[mkey_idx], SE_KEY_128_SIZE); se_aes_crypt_ecb(7, DECRYPT, tmp_mkey, SE_KEY_128_SIZE, mkey_vectors[mkey_idx], SE_KEY_128_SIZE);
for (u32 idx = 0; idx < mkey_idx; idx++) for (u32 idx = 0; idx < mkey_idx; idx++)
{ {
se_aes_key_clear(2);
se_aes_key_set(2, tmp_mkey, SE_KEY_128_SIZE); se_aes_key_set(2, tmp_mkey, SE_KEY_128_SIZE);
se_aes_crypt_ecb(2, DECRYPT, tmp_mkey, mkey_vectors[mkey_idx - 1 - idx], SE_KEY_128_SIZE); se_aes_crypt_ecb(2, DECRYPT, tmp_mkey, SE_KEY_128_SIZE, mkey_vectors[mkey_idx - 1 - idx], SE_KEY_128_SIZE);
} }
} while (memcmp(tmp_mkey, "\x00\x00\x00\x00\x00\x00\x00\x00", 8) != 0 && (mkey_idx - 1)); } while (memcmp(tmp_mkey, "\x00\x00\x00\x00\x00\x00\x00\x00", 8) != 0 && (mkey_idx - 1));
// Derive new device key. // Derive new device key.
se_aes_key_clear(1);
se_aes_unwrap_key(1, 10, new_console_keyseed[keygen_rev]); // Uses Device key 4x. se_aes_unwrap_key(1, 10, new_console_keyseed[keygen_rev]); // Uses Device key 4x.
se_aes_crypt_ecb(10, DECRYPT, tmp_mkey, new_console_keyseed[keygen_rev], SE_KEY_128_SIZE); // Uses Device key 4x. se_aes_crypt_ecb(10, DECRYPT, tmp_mkey, SE_KEY_128_SIZE, new_console_keyseed[keygen_rev], SE_KEY_128_SIZE); // Uses Device key 4x.
se_aes_unwrap_key(1, 2, new_console_kekseed[keygen_rev]); // Uses Master Key 0. se_aes_unwrap_key(1, 2, new_console_kekseed[keygen_rev]); // Uses Master Key 0.
se_aes_unwrap_key(1, 1, tmp_mkey); se_aes_unwrap_key(1, 1, tmp_mkey);
@@ -610,27 +614,29 @@ int hos_bis_keygen()
} }
// Generate generic key. // Generate generic key.
se_aes_key_clear(2);
se_aes_unwrap_key(2, console_key_slot, gen_keyseed_retail); se_aes_unwrap_key(2, console_key_slot, gen_keyseed_retail);
// Clear bis keys storage. // Clear bis keys storage.
memset(bis_keys, 0, SE_KEY_128_SIZE * 6); memset(bis_keys, 0, SE_KEY_128_SIZE * 6);
// Generate BIS 0 Keys. // Generate BIS 0 Keys.
se_aes_crypt_ecb(2, DECRYPT, bis_keys + (0 * SE_KEY_128_SIZE), bis_keyseed[0], SE_KEY_128_SIZE); se_aes_crypt_block_ecb(2, DECRYPT, bis_keys + (0 * SE_KEY_128_SIZE), bis_keyseed[0]);
se_aes_crypt_ecb(2, DECRYPT, bis_keys + (1 * SE_KEY_128_SIZE), bis_keyseed[1], SE_KEY_128_SIZE); se_aes_crypt_block_ecb(2, DECRYPT, bis_keys + (1 * SE_KEY_128_SIZE), bis_keyseed[1]);
// Generate generic kek. // Generate generic kek.
se_aes_key_clear(2);
se_aes_unwrap_key(2, console_key_slot, gen_kekseed); se_aes_unwrap_key(2, console_key_slot, gen_kekseed);
se_aes_unwrap_key(2, 2, bis_kekseed); se_aes_unwrap_key(2, 2, bis_kekseed);
se_aes_unwrap_key(2, 2, gen_keyseed); se_aes_unwrap_key(2, 2, gen_keyseed);
// Generate BIS 1 Keys. // Generate BIS 1 Keys.
se_aes_crypt_ecb(2, DECRYPT, bis_keys + (2 * SE_KEY_128_SIZE), bis_keyseed[2], SE_KEY_128_SIZE); se_aes_crypt_block_ecb(2, DECRYPT, bis_keys + (2 * SE_KEY_128_SIZE), bis_keyseed[2]);
se_aes_crypt_ecb(2, DECRYPT, bis_keys + (3 * SE_KEY_128_SIZE), bis_keyseed[3], SE_KEY_128_SIZE); se_aes_crypt_block_ecb(2, DECRYPT, bis_keys + (3 * SE_KEY_128_SIZE), bis_keyseed[3]);
// Generate BIS 2/3 Keys. // Generate BIS 2/3 Keys.
se_aes_crypt_ecb(2, DECRYPT, bis_keys + (4 * SE_KEY_128_SIZE), bis_keyseed[4], SE_KEY_128_SIZE); se_aes_crypt_block_ecb(2, DECRYPT, bis_keys + (4 * SE_KEY_128_SIZE), bis_keyseed[4]);
se_aes_crypt_ecb(2, DECRYPT, bis_keys + (5 * SE_KEY_128_SIZE), bis_keyseed[5], SE_KEY_128_SIZE); se_aes_crypt_block_ecb(2, DECRYPT, bis_keys + (5 * SE_KEY_128_SIZE), bis_keyseed[5]);
// Validate key because HOS_MKEY_VER_MAX. // Validate key because HOS_MKEY_VER_MAX.
if (!h_cfg.t210b01) if (!h_cfg.t210b01)
@@ -682,7 +688,7 @@ int hos_dump_cal0()
LIST_INIT(gpt); LIST_INIT(gpt);
emmc_gpt_parse(&gpt); emmc_gpt_parse(&gpt);
emmc_part_t *cal0_part = emmc_part_find(&gpt, "PRODINFO"); // check if null emmc_part_t *cal0_part = emmc_part_find(&gpt, "PRODINFO"); // check if null
nx_emmc_bis_init(cal0_part, false, 0); nx_emmc_bis_init(cal0_part, false, NULL, 0);
nx_emmc_bis_read(0, 0x40, cal0_buf); nx_emmc_bis_read(0, 0x40, cal0_buf);
nx_emmc_bis_end(); nx_emmc_bis_end();
emmc_gpt_free(&gpt); emmc_gpt_free(&gpt);
@@ -707,7 +713,7 @@ int hos_dump_cal0()
} }
u32 hash[8]; u32 hash[8];
se_sha_hash_256_oneshot(hash, (u8 *)&cal0->cfg_id1, cal0->body_size); se_calc_sha256_oneshot(hash, (u8 *)&cal0->cfg_id1, cal0->body_size);
if (memcmp(hash, cal0->body_sha256, 0x20)) if (memcmp(hash, cal0->body_sha256, 0x20))
return 3; return 3;

View File

@@ -96,7 +96,7 @@ int pkg1_decrypt(const pkg1_id_t *id, u8 *pkg1)
u8 *pkg11 = pkg1 + id->pkg11_off; u8 *pkg11 = pkg1 + id->pkg11_off;
u32 pkg11_size = *(u32 *)pkg11; u32 pkg11_size = *(u32 *)pkg11;
hdr = (pk11_hdr_t *)(pkg11 + 0x20); hdr = (pk11_hdr_t *)(pkg11 + 0x20);
se_aes_crypt_ctr(11, hdr, hdr, pkg11_size, pkg11 + 0x10); se_aes_crypt_ctr(11, hdr, pkg11_size, hdr, pkg11_size, pkg11 + 0x10);
} }
else else
{ {
@@ -107,7 +107,7 @@ int pkg1_decrypt(const pkg1_id_t *id, u8 *pkg1)
// Use BEK for T210B01. // Use BEK for T210B01.
// Additionally, skip 0x20 bytes from decryption to maintain the header. // Additionally, skip 0x20 bytes from decryption to maintain the header.
se_aes_iv_clear(13); se_aes_iv_clear(13);
se_aes_crypt_cbc(13, DECRYPT, pkg1 + 0x20, pkg1 + 0x20, oem_hdr->size - 0x20); se_aes_crypt_cbc(13, DECRYPT, pkg1 + 0x20, oem_hdr->size - 0x20, pkg1 + 0x20, oem_hdr->size - 0x20);
} }
// Return if header is valid. // Return if header is valid.

View File

@@ -26,12 +26,6 @@
#define PK11_SECTION_LD 1 #define PK11_SECTION_LD 1
#define PK11_SECTION_SM 2 #define PK11_SECTION_SM 2
#define PKG1_BOOTLOADER_SIZE SZ_256K
#define PKG1_BOOTLOADER_MAIN_OFFSET (0x100000 / EMMC_BLOCKSIZE)
#define PKG1_BOOTLOADER_BACKUP_OFFSET (0x140000 / EMMC_BLOCKSIZE)
#define PKG1_BOOTLOADER_SAFE_OFFSET (0x000000 / EMMC_BLOCKSIZE)
#define PKG1_HOS_EKS_OFFSET (0x180000 / EMMC_BLOCKSIZE)
typedef struct _bl_hdr_t210b01_t typedef struct _bl_hdr_t210b01_t
{ {
/* 0x000 */ u8 aes_mac[0x10]; /* 0x000 */ u8 aes_mac[0x10];

View File

@@ -1,6 +1,6 @@
/* /*
* Copyright (c) 2018 naehrwert * Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2026 CTCaer * Copyright (c) 2018-2025 CTCaer
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@@ -123,13 +123,13 @@ static const u8 mkey_vector_7xx[HOS_MKEY_VER_MAX - HOS_MKEY_VER_810 + 1][SE_KEY_
static bool _pkg2_key_unwrap_validate(pkg2_hdr_t *tmp_test, pkg2_hdr_t *hdr, u8 src_slot, u8 *mkey, const u8 *key_seed) static bool _pkg2_key_unwrap_validate(pkg2_hdr_t *tmp_test, pkg2_hdr_t *hdr, u8 src_slot, u8 *mkey, const u8 *key_seed)
{ {
// Decrypt older encrypted mkey. // Decrypt older encrypted mkey.
se_aes_crypt_ecb(src_slot, DECRYPT, mkey, key_seed, SE_KEY_128_SIZE); se_aes_crypt_ecb(src_slot, DECRYPT, mkey, SE_KEY_128_SIZE, key_seed, SE_KEY_128_SIZE);
// Set and unwrap pkg2 key. // Set and unwrap pkg2 key.
se_aes_key_set(9, mkey, SE_KEY_128_SIZE); se_aes_key_set(9, mkey, SE_KEY_128_SIZE);
se_aes_unwrap_key(9, 9, package2_keyseed); se_aes_unwrap_key(9, 9, package2_keyseed);
// Decrypt header. // Decrypt header.
se_aes_crypt_ctr(9, tmp_test, hdr, sizeof(pkg2_hdr_t), hdr); se_aes_crypt_ctr(9, tmp_test, sizeof(pkg2_hdr_t), hdr, sizeof(pkg2_hdr_t), hdr);
// Return if header is valid. // Return if header is valid.
return (tmp_test->magic == PKG2_MAGIC); return (tmp_test->magic == PKG2_MAGIC);
@@ -150,7 +150,7 @@ pkg2_hdr_t *pkg2_decrypt(void *data, u8 mkey)
pdata += sizeof(pkg2_hdr_t); pdata += sizeof(pkg2_hdr_t);
// Check if we need to decrypt with newer mkeys. Valid for THK for 7.0.0 and up. // Check if we need to decrypt with newer mkeys. Valid for THK for 7.0.0 and up.
se_aes_crypt_ctr(8, &mkey_test, hdr, sizeof(pkg2_hdr_t), hdr); se_aes_crypt_ctr(8, &mkey_test, sizeof(pkg2_hdr_t), hdr, sizeof(pkg2_hdr_t), hdr);
if (mkey_test.magic == PKG2_MAGIC) if (mkey_test.magic == PKG2_MAGIC)
goto key_found; goto key_found;
@@ -197,7 +197,7 @@ pkg2_hdr_t *pkg2_decrypt(void *data, u8 mkey)
key_found: key_found:
// Decrypt header. // Decrypt header.
se_aes_crypt_ctr(pkg2_keyslot, hdr, hdr, sizeof(pkg2_hdr_t), hdr); se_aes_crypt_ctr(pkg2_keyslot, hdr, sizeof(pkg2_hdr_t), hdr, sizeof(pkg2_hdr_t), hdr);
if (hdr->magic != PKG2_MAGIC) if (hdr->magic != PKG2_MAGIC)
return NULL; return NULL;
@@ -209,7 +209,7 @@ DPRINTF("sec %d has size %08X\n", i, hdr->sec_size[i]);
if (!hdr->sec_size[i]) if (!hdr->sec_size[i])
continue; continue;
se_aes_crypt_ctr(pkg2_keyslot, pdata, pdata, hdr->sec_size[i], hdr->sec_ctr[i]); se_aes_crypt_ctr(pkg2_keyslot, pdata, hdr->sec_size[i], pdata, hdr->sec_size[i], &hdr->sec_ctr[i * SE_AES_IV_SIZE]);
pdata += hdr->sec_size[i]; pdata += hdr->sec_size[i];
} }

View File

@@ -1,6 +1,6 @@
/* /*
* Copyright (c) 2018 naehrwert * Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2026 CTCaer * Copyright (c) 2018-2025 CTCaer
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@@ -39,7 +39,7 @@ extern u32 pkg2_newkern_ini1_end;
typedef struct _pkg2_hdr_t typedef struct _pkg2_hdr_t
{ {
/* 0x000 */ u8 ctr[0x10]; /* 0x000 */ u8 ctr[0x10];
/* 0x010 */ u8 sec_ctr[4][SE_AES_IV_SIZE]; /* 0x010 */ u8 sec_ctr[0x40];
/* 0x050 */ u32 magic; /* 0x050 */ u32 magic;
/* 0x054 */ u32 base; /* 0x054 */ u32 base;
/* 0x058 */ u32 pad0; /* 0x058 */ u32 pad0;
@@ -48,7 +48,7 @@ typedef struct _pkg2_hdr_t
/* 0x05E */ u16 pad1; /* 0x05E */ u16 pad1;
/* 0x060 */ u32 sec_size[4]; /* 0x060 */ u32 sec_size[4];
/* 0x070 */ u32 sec_off[4]; /* 0x070 */ u32 sec_off[4];
/* 0x080 */ u8 sec_sha256[4][SE_SHA_256_SIZE]; /* 0x080 */ u8 sec_sha256[0x80];
/* 0x100 */ u8 data[]; /* 0x100 */ u8 data[];
} pkg2_hdr_t; } pkg2_hdr_t;

View File

@@ -1,7 +1,7 @@
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
/* Low level disk I/O module skeleton for FatFs */ /* Low level disk I/O module skeleton for FatFs */
/* (C) ChaN, 2016 */ /* (C) ChaN, 2016 */
/* (C) CTCaer, 2018-2025 */ /* (C) CTCaer, 2018-2020 */
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
/* If a working storage control module is available, it should be */ /* If a working storage control module is available, it should be */
/* attached to the FatFs via a glue function rather than modifying it. */ /* attached to the FatFs via a glue function rather than modifying it. */
@@ -9,18 +9,113 @@
/* storage control modules to the FatFs module with a defined API. */ /* storage control modules to the FatFs module with a defined API. */
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
#include <storage/emmc.h>
#include <string.h> #include <string.h>
#include <bdk.h> #include <bdk.h>
#include <libs/fatfs/diskio.h> /* FatFs lower layer API */ #include <libs/fatfs/diskio.h> /* FatFs lower layer API */
#include <fatfs_cfg.h>
#include "../../storage/sfd.h"
static u32 sd_rsvd_sectors = 0; static u32 sd_rsvd_sectors = 0;
static u32 ramdisk_sectors = 0; static u32 ramdisk_sectors = 0;
static u32 bis_sectors = 0; static u32 emummc_sectors = 0;
static u32 emummc_sectors = 0; static u32 sfd_sectors = 0;
static bool bis_write_allowed = false; static u32 cur_partition;
static void save_cur_partition(BYTE pdrv){
bool save = false;
switch(pdrv){
case DRIVE_BOOT1:
case DRIVE_BOOT1_1MB:
case DRIVE_EMMC:
save = true;
break;
case DRIVE_SD:
case DRIVE_RAM:
break;
case DRIVE_BIS:
case DRIVE_EMU:
if(nx_emmc_bis_get_storage() == &emmc_storage){
save = true;
}
break;
case DRIVE_SFD:
if(sfd_get_storage() == &emmc_storage){
save = true;
}
break;
default:
break;
}
if(save){
cur_partition = emmc_storage.partition;
}
}
static void restore_cur_partition(BYTE pdrv){
bool restore = false;
switch(pdrv){
case DRIVE_BOOT1:
case DRIVE_BOOT1_1MB:
case DRIVE_EMMC:
restore = true;
break;
case DRIVE_SD:
case DRIVE_RAM:
break;
case DRIVE_BIS:
case DRIVE_EMU:
if(nx_emmc_bis_get_storage() == &emmc_storage){
restore = true;
}
break;
case DRIVE_SFD:
if(sfd_get_storage() == &emmc_storage){
restore = true;
}
break;
default:
break;
}
if(restore){
if(emmc_storage.partition != cur_partition){
emmc_set_partition(cur_partition);
}
}
}
static bool ensure_partition(BYTE pdrv){
u8 part;
switch(pdrv){
case DRIVE_BOOT1:
case DRIVE_BOOT1_1MB:
part = EMMC_BOOT1;
break;
case DRIVE_EMMC:
part = EMMC_GPP;
break;
case DRIVE_SD:
case DRIVE_RAM:
return true;
case DRIVE_BIS:
case DRIVE_EMU:
case DRIVE_SFD:
return true;
default:
return false;
}
if(emmc_storage.partition != part){
return emmc_set_partition(part);
}
return true;
}
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
/* Get Drive Status */ /* Get Drive Status */
@@ -52,20 +147,45 @@ DRESULT disk_read (
UINT count /* Number of sectors to read */ UINT count /* Number of sectors to read */
) )
{ {
switch (pdrv) DRESULT res = RES_OK;
{
case DRIVE_SD: save_cur_partition(pdrv);
return sdmmc_storage_read(&sd_storage, sector, count, (void *)buff) ? RES_OK : RES_ERROR;
case DRIVE_RAM: if(!ensure_partition(pdrv)){
return ram_disk_read(sector, count, (void *)buff); res = RES_ERROR;
case DRIVE_EMMC:
return sdmmc_storage_read(&emmc_storage, sector, count, (void *)buff) ? RES_OK : RES_ERROR;
case DRIVE_BIS:
case DRIVE_EMU:
return nx_emmc_bis_read(sector, count, (void *)buff) ? RES_OK : RES_ERROR;
} }
return RES_ERROR; if(res == RES_OK){
switch (pdrv)
{
case DRIVE_SD:
res = sdmmc_storage_read(&sd_storage, sector, count, (void *)buff) ? RES_OK : RES_ERROR;
break;
case DRIVE_RAM:
res = ram_disk_read(sector, count, (void *)buff);
break;
case DRIVE_EMMC:
res = sdmmc_storage_read(&emmc_storage, sector, count, (void *)buff) ? RES_OK : RES_ERROR;
break;
case DRIVE_BIS:
case DRIVE_EMU:
res = nx_emmc_bis_read(sector, count, (void *)buff) ? RES_OK : RES_ERROR;
break;
case DRIVE_BOOT1_1MB:
res = sdmmc_storage_read(&emmc_storage, sector + (0x100000 / 512), count, buff) ? RES_OK : RES_ERROR;
break;
case DRIVE_BOOT1:
res = sdmmc_storage_read(&emmc_storage, sector, count, buff) ? RES_OK : RES_ERROR;
break;
case DRIVE_SFD:
res = sfd_read(sector, count, buff) ? RES_OK : RES_ERROR;
break;
}
}
restore_cur_partition(pdrv);
return res;
} }
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
@@ -78,22 +198,47 @@ DRESULT disk_write (
UINT count /* Number of sectors to write */ UINT count /* Number of sectors to write */
) )
{ {
switch (pdrv) DRESULT res = RES_OK;
{
case DRIVE_SD: save_cur_partition(pdrv);
return sdmmc_storage_write(&sd_storage, sector, count, (void *)buff) ? RES_OK : RES_ERROR;
case DRIVE_RAM: if(!ensure_partition(pdrv)){
return ram_disk_write(sector, count, (void *)buff); res = RES_ERROR;
case DRIVE_EMMC:
return RES_WRPRT;
case DRIVE_BIS:
case DRIVE_EMU:
if (pdrv == DRIVE_BIS && !bis_write_allowed)
return RES_WRPRT;
return nx_emmc_bis_write(sector, count, (void *)buff) ? RES_OK : RES_ERROR;
} }
return RES_ERROR; if(res == RES_OK){
switch (pdrv)
{
case DRIVE_SD:
res = sdmmc_storage_write(&sd_storage, sector, count, (void *)buff) ? RES_OK : RES_ERROR;
break;
case DRIVE_RAM:
res = ram_disk_write(sector, count, (void *)buff);
break;
case DRIVE_EMMC:
res = sdmmc_storage_write(&emmc_storage, sector, count, (void*)buff) ? RES_OK : RES_ERROR;
break;
case DRIVE_BIS:
res = RES_WRPRT;
break;
case DRIVE_EMU:
res = nx_emmc_bis_write(sector, count, (void *)buff) ? RES_OK : RES_ERROR;
break;
case DRIVE_BOOT1_1MB:
res = sdmmc_storage_write(&emmc_storage, sector + (0x100000 / 512), count, (void*)buff) ? RES_OK : RES_ERROR;
break;
case DRIVE_BOOT1:
res = sdmmc_storage_write(&emmc_storage, sector, count, (void*)buff) ? RES_OK : RES_ERROR;
break;
case DRIVE_SFD:
res = sfd_write(sector, count, (void*)buff) ? RES_OK : RES_ERROR;
break;
}
}
restore_cur_partition(pdrv);
return res;
} }
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
@@ -107,9 +252,8 @@ DRESULT disk_ioctl (
{ {
DWORD *buf = (DWORD *)buff; DWORD *buf = (DWORD *)buff;
switch (pdrv) if (pdrv == DRIVE_SD)
{ {
case DRIVE_SD:
switch (cmd) switch (cmd)
{ {
case GET_SECTOR_COUNT: case GET_SECTOR_COUNT:
@@ -119,9 +263,9 @@ DRESULT disk_ioctl (
*buf = 32768; // Align to 16MB. *buf = 32768; // Align to 16MB.
break; break;
} }
break; }
else if (pdrv == DRIVE_RAM)
case DRIVE_RAM: {
switch (cmd) switch (cmd)
{ {
case GET_SECTOR_COUNT: case GET_SECTOR_COUNT:
@@ -131,33 +275,29 @@ DRESULT disk_ioctl (
*buf = 2048; // Align to 1MB. *buf = 2048; // Align to 1MB.
break; break;
} }
break; }
else if (pdrv == DRIVE_EMU)
case DRIVE_BIS: {
switch (cmd)
{
case GET_SECTOR_COUNT:
*buf = bis_sectors;
break;
case GET_BLOCK_SIZE:
*buf = 32768; // Align to 16MB.
break;
}
break;
case DRIVE_EMU:
switch (cmd) switch (cmd)
{ {
case GET_SECTOR_COUNT: case GET_SECTOR_COUNT:
*buf = emummc_sectors; *buf = emummc_sectors;
break; break;
case GET_BLOCK_SIZE: case GET_BLOCK_SIZE:
*buf = 16384; // Align to 8MB (With BOOT0/1 data will be at 16MB BU). *buf = 32768; // Align to 16MB.
break; break;
} }
break; }else if(pdrv == DRIVE_SFD){
switch(cmd){
default: // Catch all for unknown devices. case GET_SECTOR_COUNT:
*buf = sfd_sectors;
break;
case GET_BLOCK_SIZE:
*buf = 32768;
break;
}
}else // Catch all for unknown devices.
{
switch (cmd) switch (cmd)
{ {
case CTRL_SYNC: case CTRL_SYNC:
@@ -167,7 +307,6 @@ DRESULT disk_ioctl (
*buf = 0; // Zero value to force default or abort. *buf = 0; // Zero value to force default or abort.
break; break;
} }
break;
} }
return RES_OK; return RES_OK;
@@ -188,22 +327,17 @@ DRESULT disk_set_info (
case DRIVE_SD: case DRIVE_SD:
sd_rsvd_sectors = *buf; sd_rsvd_sectors = *buf;
break; break;
case DRIVE_RAM: case DRIVE_RAM:
ramdisk_sectors = *buf; ramdisk_sectors = *buf;
break; break;
case DRIVE_BIS:
bis_sectors = *buf;
break;
case DRIVE_EMU: case DRIVE_EMU:
emummc_sectors = *buf; emummc_sectors = *buf;
break; break;
case DRIVE_SFD:
sfd_sectors = *buf;
break;
} }
} }
else if (cmd == SET_WRITE_PROTECT && pdrv == DRIVE_BIS)
bis_write_allowed = *(bool *)buff;
return RES_OK; return RES_OK;
} }

View File

@@ -168,7 +168,7 @@
*/ */
#define FF_FS_RPATH 1 #define FF_FS_RPATH 2
/* This option configures support for relative path. /* This option configures support for relative path.
/ /
/ 0: Disable relative path and remove related functions. / 0: Disable relative path and remove related functions.
@@ -181,12 +181,12 @@
/ Drive/Volume Configurations / Drive/Volume Configurations
/---------------------------------------------------------------------------*/ /---------------------------------------------------------------------------*/
#define FF_VOLUMES 5 #define FF_VOLUMES 8
/* Number of volumes (logical drives) to be used. (1-10) */ /* Number of volumes (logical drives) to be used. (1-10) */
#define FF_STR_VOLUME_ID 1 #define FF_STR_VOLUME_ID 1
#define FF_VOLUME_STRS "sd","ram","emmc","bis","emu" #define FF_VOLUME_STRS "sd","ram","emmc","bis","emu", "boot1", "boot1_1mb", "sfd"
/* FF_STR_VOLUME_ID switches support for volume ID in arbitrary strings. /* 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 / 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 / number in the path name. FF_VOLUME_STRS defines the volume ID strings for each
@@ -302,6 +302,15 @@
/ SemaphoreHandle_t and etc. A header file for O/S definitions needs to be / SemaphoreHandle_t and etc. A header file for O/S definitions needs to be
/ included somewhere in the scope of ff.h. */ / included somewhere in the scope of ff.h. */
typedef enum {
DRIVE_SD = 0,
DRIVE_RAM = 1,
DRIVE_EMMC = 2,
DRIVE_BIS = 3,
DRIVE_EMU = 4,
DRIVE_BOOT1 = 5,
DRIVE_BOOT1_1MB = 6,
DRIVE_SFD = 7,
} DDRIVE;
/*--- End of configuration options ---*/ /*--- End of configuration options ---*/

View File

@@ -26,6 +26,7 @@
#include <ianos/ianos.h> #include <ianos/ianos.h>
#include <libs/compr/blz.h> #include <libs/compr/blz.h>
#include <libs/fatfs/ff.h> #include <libs/fatfs/ff.h>
#include <storage/boot_storage.h>
#include "frontend/fe_emmc_tools.h" #include "frontend/fe_emmc_tools.h"
#include "frontend/gui.h" #include "frontend/gui.h"
@@ -34,7 +35,7 @@ nyx_config n_cfg;
hekate_config h_cfg; hekate_config h_cfg;
const volatile ipl_ver_meta_t __attribute__((section ("._ipl_version"))) ipl_ver = { const volatile ipl_ver_meta_t __attribute__((section ("._ipl_version"))) ipl_ver = {
.magic = NYX_MAGIC, .magic = NYX_MAGIC,
.version = (NYX_VER_MJ + '0') | ((NYX_VER_MN + '0') << 8) | ((NYX_VER_HF + '0') << 16) | ((NYX_VER_RL) << 24), .version = (NYX_VER_MJ + '0') | ((NYX_VER_MN + '0') << 8) | ((NYX_VER_HF + '0') << 16) | ((NYX_VER_RL) << 24),
}; };
@@ -121,7 +122,7 @@ lv_res_t launch_payload(lv_obj_t *list)
strcpy(path,"bootloader/payloads/"); strcpy(path,"bootloader/payloads/");
strcat(path, filename); strcat(path, filename);
if (!sd_mount()) if (!boot_storage_mount())
goto out; goto out;
// Read payload. // Read payload.
@@ -142,7 +143,7 @@ lv_res_t launch_payload(lv_obj_t *list)
goto out; goto out;
} }
sd_end(); boot_storage_end();
// Copy the payload to our chosen address. // Copy the payload to our chosen address.
memcpy((void *)RCM_PAYLOAD_ADDR, buf, size); memcpy((void *)RCM_PAYLOAD_ADDR, buf, size);
@@ -329,8 +330,8 @@ static void _show_errors(int sd_error)
if (*excp_enabled == EXCP_MAGIC || sd_error) if (*excp_enabled == EXCP_MAGIC || sd_error)
{ {
gfx_clear_grey(0); // gfx_clear_grey(0);
gfx_con_setpos(0, 0, 0); // gfx_con_setpos(0, 0, 0);
display_backlight_brightness(150, 1000); display_backlight_brightness(150, 1000);
display_init_window_d_console(); display_init_window_d_console();
display_window_d_console_enable(); display_window_d_console_enable();
@@ -380,7 +381,7 @@ error_occured:
msleep(1000); msleep(1000);
btn_wait(); btn_wait();
reload_nyx(NULL, true); reload_nyx();
} }
} }
@@ -427,13 +428,13 @@ void nyx_init_load_res()
_show_errors(SD_NO_ERROR); _show_errors(SD_NO_ERROR);
// Try 2 times to mount SD card. // Try 2 times to mount SD card.
if (!sd_mount()) if (!boot_storage_mount())
{ {
// Restore speed to SDR104. // Restore speed to SDR104.
sd_end(); boot_storage_end();
// Retry. // Retry.
if (!sd_mount()) if (!boot_storage_mount())
_show_errors(SD_MOUNT_ERROR); // Fatal. _show_errors(SD_MOUNT_ERROR); // Fatal.
} }
@@ -490,7 +491,7 @@ void nyx_init_load_res()
nyx_load_bg_icons(); nyx_load_bg_icons();
// Unmount FAT partition. // Unmount FAT partition.
sd_unmount(); boot_storage_unmount();
} }
void ipl_main() void ipl_main()

86
nyx/nyx_gui/storage/sfd.c Normal file
View File

@@ -0,0 +1,86 @@
#include "sfd.h"
#include <storage/emmc.h>
#include <storage/sdmmc.h>
#include <storage/file_based_storage.h>
#include <libs/fatfs/diskio.h>
#include <string.h>
static bool file_based;
static sdmmc_storage_t *_storage;
static u32 _offset;
static u32 _size;
static void ensure_partition(){
if(_storage == &emmc_storage){
emmc_set_partition(EMMC_GPP);
}
}
sdmmc_storage_t *sfd_get_storage(){
if(file_based){
return NULL;
}else{
return _storage;
}
}
int sfd_read(u32 sector, u32 count, void *buff){
int res;
if(sector + count > _size){
return 0;
}
if(file_based){
res = file_based_storage_read(sector, count, buff);
}else{
ensure_partition();
res = sdmmc_storage_read(_storage, sector + _offset, count, buff);
}
return res;
}
int sfd_write(u32 sector, u32 count, void *buff){
int res;
if(sector + count > _size){
return 0;
}
if(file_based){
res = file_based_storage_write(sector, count, buff);
}else{
ensure_partition();
res = sdmmc_storage_write(_storage, sector + _offset, count, buff);
}
return res;
}
bool sfd_init(sdmmc_storage_t *storage, u32 offset, u32 size){
_storage = storage;
_offset = offset;
_size = size;
disk_set_info(DRIVE_SFD, SET_SECTOR_COUNT, &size);
return true;
}
bool sfd_file_based_init(const char *base_path) {
file_based = true;
if(!file_based_storage_init(base_path)){
gfx_printf("file based init fail\n");
return 0;
}
_size = file_based_storage_get_total_size();
disk_set_info(DRIVE_SFD, SET_SECTOR_COUNT, &_size);
return 1;
}
void sfd_end(){
_storage = NULL;
_offset = 0;
_size = 0;
u32 size = 0;
file_based = false;
disk_set_info(DRIVE_SFD, SET_SECTOR_COUNT, &size);
}

16
nyx/nyx_gui/storage/sfd.h Normal file
View File

@@ -0,0 +1,16 @@
#ifndef _SFD_H
#define _SFD_H
#include <storage/sdmmc.h>
#include <utils/types.h>
int sfd_read(u32 sector, u32 count, void *buff);
int sfd_write(u32 sector, u32 count, void *buff);
bool sfd_file_based_init(const char *base_path);
bool sfd_init(sdmmc_storage_t *storage, u32 offset, u32 size);
void sfd_end();
sdmmc_storage_t *sfd_get_storage();
#endif