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:
102
Makefile
102
Makefile
@@ -14,7 +14,6 @@ include ./Versions.inc
|
||||
|
||||
TARGET := hekate
|
||||
BUILDDIR := build
|
||||
BUILDTDIR := build/$(TARGET)
|
||||
OUTPUTDIR := output
|
||||
SOURCEDIR = bootloader
|
||||
BDKDIR := bdk
|
||||
@@ -22,33 +21,42 @@ BDKINC := -I./$(BDKDIR)
|
||||
VPATH = $(dir ./$(SOURCEDIR)/) $(dir $(wildcard ./$(SOURCEDIR)/*/)) $(dir $(wildcard ./$(SOURCEDIR)/*/*/))
|
||||
VPATH += $(dir $(wildcard ./$(BDKDIR)/)) $(dir $(wildcard ./$(BDKDIR)/*/)) $(dir $(wildcard ./$(BDKDIR)/*/*/))
|
||||
|
||||
# Track compiler flags
|
||||
TRACK_CFLAGS = $(BUILDTDIR)/.cflags
|
||||
TRACK_LDFLAGS = $(BUILDTDIR)/.ldflags
|
||||
|
||||
# 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.
|
||||
OBJS += bpmp ccplex clock di i2c irq timer \
|
||||
mc sdram minerva smmu \
|
||||
gpio pinmux pmc se tsec uart \
|
||||
fuse kfuse \
|
||||
sdmmc sdmmc_driver emmc sd emummc \
|
||||
bq24193 max17050 max7762x max77620-rtc \
|
||||
hw_init
|
||||
OBJS += $(addprefix $(BUILDDIR)/$(TARGET)/, \
|
||||
bpmp.o ccplex.o clock.o di.o i2c.o irq.o timer.o \
|
||||
mc.o sdram.o minerva.o \
|
||||
gpio.o pinmux.o pmc.o se.o smmu.o tsec.o uart.o \
|
||||
fuse.o kfuse.o \
|
||||
sdmmc.o sdmmc_driver.o emmc.o sd.o emummc.o emummc_file_based.o emusd.o \
|
||||
bq24193.o max17050.o max7762x.o max77620-rtc.o \
|
||||
hw_init.o boot_storage.o emusd.o file_based_storage.o \
|
||||
)
|
||||
|
||||
# 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.
|
||||
OBJS += l4t hos hos_config pkg1 pkg2 pkg3 pkg2_ini_kippatch secmon_exo
|
||||
# Horizon.
|
||||
OBJS += $(addprefix $(BUILDDIR)/$(TARGET)/, \
|
||||
hos.o hos_config.o pkg1.o pkg2.o pkg3.o pkg2_ini_kippatch.o secmon_exo.o \
|
||||
)
|
||||
|
||||
# Libraries.
|
||||
OBJS += lz lz4 blz diskio ff ffunicode ffsystem elfload elfreloc_arm
|
||||
|
||||
OBJS := $(addsuffix .o, $(OBJS))
|
||||
OBJS := $(addprefix $(BUILDTDIR)/, $(OBJS))
|
||||
OBJS += $(addprefix $(BUILDDIR)/$(TARGET)/, \
|
||||
lz.o lz4.o blz.o \
|
||||
diskio.o ff.o ffunicode.o ffsystem.o \
|
||||
elfload.o elfreloc_arm.o \
|
||||
)
|
||||
|
||||
GFX_INC := '"../$(SOURCEDIR)/gfx/gfx.h"'
|
||||
FFCFG_INC := '"../$(SOURCEDIR)/libs/fatfs/ffconf.h"'
|
||||
@@ -86,17 +94,9 @@ TOOLSLZ := $(wildcard tools/lz)
|
||||
TOOLSB2C := $(wildcard tools/bin2c)
|
||||
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)
|
||||
@printf ICTC49 >> $(OUTPUTDIR)/$(TARGET).bin
|
||||
@@ -113,18 +113,17 @@ all: $(TARGET).bin $(LDRDIR)
|
||||
@echo "--------------------------------------"
|
||||
|
||||
clean: $(TOOLS)
|
||||
@rm -rf $(OBJS)
|
||||
@rm -rf $(BUILDDIR)
|
||||
@rm -rf $(OUTPUTDIR)
|
||||
@$(MAKE) --no-print-directory -C $(LDRDIR) $(MAKECMDGOALS) -$(MAKEFLAGS)
|
||||
|
||||
$(MODULEDIRS): $(BUILDTDIR)/$(TARGET).elf
|
||||
$(MODULEDIRS):
|
||||
@$(MAKE) --no-print-directory -C $@ $(MAKECMDGOALS) -$(MAKEFLAGS)
|
||||
|
||||
$(NYXDIR): $(BUILDTDIR)/$(TARGET).elf $(MODULEDIRS)
|
||||
@echo --------------------------------------
|
||||
$(NYXDIR):
|
||||
@$(MAKE) --no-print-directory -C $@ $(MAKECMDGOALS) -$(MAKEFLAGS)
|
||||
|
||||
$(LDRDIR): $(TARGET).bin $(TOOLS) $(NYXDIR) $(MODULEDIRS)
|
||||
$(LDRDIR): $(TARGET).bin
|
||||
@$(TOOLSLZ)/lz77 $(OUTPUTDIR)/$(TARGET).bin
|
||||
@mv $(OUTPUTDIR)/$(TARGET).bin $(OUTPUTDIR)/$(TARGET)_unc.bin
|
||||
@mv $(OUTPUTDIR)/$(TARGET).bin.00.lz payload_00
|
||||
@@ -138,31 +137,24 @@ $(LDRDIR): $(TARGET).bin $(TOOLS) $(NYXDIR) $(MODULEDIRS)
|
||||
$(TOOLS):
|
||||
@$(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)/$@
|
||||
@echo --------------------------------------
|
||||
|
||||
$(BUILDTDIR)/$(TARGET).elf: $(OBJS) $(TRACK_LDFLAGS)
|
||||
@echo -ne "\r[100%] Linking $(TARGET).elf\033[K"
|
||||
@$(CC) $(LDFLAGS) -T $(SOURCEDIR)/link.ld $(OBJS) -o $@
|
||||
@printf "\n$(TARGET) was built with the following flags:\nCFLAGS: $(CFLAGS)\nLDFLAGS: $(LDFLAGS)\n"
|
||||
$(BUILDDIR)/$(TARGET)/$(TARGET).elf: $(OBJS)
|
||||
@$(CC) $(LDFLAGS) -T $(SOURCEDIR)/link.ld $^ -o $@
|
||||
@printf "$(TARGET) was built with the following flags:\nCFLAGS: $(CFLAGS)\nLDFLAGS: $(LDFLAGS)\n"
|
||||
|
||||
$(BUILDTDIR)/%.o: %.c $(TRACK_CFLAGS) | $(BUILDTDIR)
|
||||
@$(IPLECHO) Building $@
|
||||
@$(CC) $(CFLAGS) $(BDKINC) -MMD -MP -c $< -o $@
|
||||
$(BUILDDIR)/$(TARGET)/%.o: %.c
|
||||
@echo Building $@
|
||||
@$(CC) $(CFLAGS) $(BDKINC) -c $< -o $@
|
||||
|
||||
$(BUILDTDIR)/%.o: %.S $(TRACK_CFLAGS) | $(BUILDTDIR)
|
||||
@$(IPLECHO) Building $@
|
||||
@$(CC) $(CFLAGS) -MMD -MP -c $< -o $@
|
||||
$(BUILDDIR)/$(TARGET)/%.o: %.S
|
||||
@echo Building $@
|
||||
@$(CC) $(CFLAGS) -c $< -o $@
|
||||
|
||||
$(BUILDTDIR):
|
||||
$(OBJS): $(BUILDDIR)/$(TARGET)
|
||||
|
||||
$(BUILDDIR)/$(TARGET):
|
||||
@mkdir -p "$(BUILDDIR)"
|
||||
@mkdir -p "$(BUILDTDIR)"
|
||||
@mkdir -p "$(BUILDDIR)/$(TARGET)"
|
||||
@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)
|
||||
|
||||
@@ -818,7 +818,8 @@
|
||||
* [30] 94 [10]: AUO A055TAN02 (59.05A30.002)
|
||||
* [30] 95 [10]: AUO A055TAN03 (59.05A30.003)
|
||||
* [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:
|
||||
* [50] 9B [20]: Samsung AMS699VC01-0 (Rev 2.5)
|
||||
@@ -836,6 +837,8 @@
|
||||
* 30h: AU Optronics
|
||||
* 40h: Sharp
|
||||
* 50h: Samsung
|
||||
* E0h: Retro Remake
|
||||
* E1h: Retro Remake
|
||||
*
|
||||
* Boards, Panel Size:
|
||||
* 0Fh: Icosa/Iowa, 6.2"
|
||||
@@ -854,6 +857,8 @@ enum
|
||||
PANEL_AUO_A055TAN01 = 0x1030,
|
||||
PANEL_SHP_LQ055T1SW10 = 0x1040,
|
||||
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.
|
||||
// Quality seems JDI like. Has bad low backlight scaling. ID: [83] 94 [0F]. Sometimes reports [30] 94 [0F]. Both IDs have correct CRC16.
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <storage/boot_storage.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "ianos.h"
|
||||
@@ -75,7 +76,7 @@ uintptr_t ianos_loader(char *path, elfType_t type, void *moduleConfig)
|
||||
uintptr_t epaddr = 0;
|
||||
|
||||
// Read library.
|
||||
fileBuf = sd_file_read(path, NULL);
|
||||
fileBuf = boot_storage_file_read(path, NULL);
|
||||
|
||||
if (!fileBuf)
|
||||
goto out;
|
||||
|
||||
@@ -10,6 +10,7 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
#include <utils/types.h>
|
||||
#include <fatfs_cfg.h>
|
||||
|
||||
/* Status of Disk Functions */
|
||||
typedef BYTE DSTATUS;
|
||||
@@ -23,14 +24,6 @@ typedef enum {
|
||||
RES_PARERR /* 4: Invalid Parameter */
|
||||
} DRESULT;
|
||||
|
||||
typedef enum {
|
||||
DRIVE_SD = 0,
|
||||
DRIVE_RAM = 1,
|
||||
DRIVE_EMMC = 2,
|
||||
DRIVE_BIS = 3,
|
||||
DRIVE_EMU = 4
|
||||
} DDRIVE;
|
||||
|
||||
|
||||
/*---------------------------------------*/
|
||||
/* Prototypes for disk control functions */
|
||||
|
||||
@@ -42,8 +42,8 @@
|
||||
#include <utils/util.h>
|
||||
#include <gfx_utils.h>
|
||||
|
||||
#define EFSPRINTF(text, ...) print_error(); gfx_printf("%k"text"%k\n", 0xFFFFFF00, 0xFFFFFFFF);
|
||||
//#define EFSPRINTF(...)
|
||||
// #define EFSPRINTF(text, ...) print_error(); gfx_printf("%k"text"%k\n", 0xFFFFFF00, 0xFFFFFFFF);
|
||||
#define EFSPRINTF(...)
|
||||
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@@ -474,6 +474,10 @@ static const char* const VolumeStr[FF_VOLUMES] = {FF_VOLUME_STRS}; /* Pre-define
|
||||
#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 */
|
||||
@@ -3320,15 +3324,28 @@ static FRESULT find_volume ( /* FR_OK(0): successful, !=0: an error occurred */
|
||||
}
|
||||
#if FF_SIMPLE_GPT
|
||||
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;
|
||||
if (move_window(fs, 1) != FR_OK) return FR_DISK_ERR;
|
||||
if (!mem_cmp(&gpt_header->signature, "EFI PART", 8)) {
|
||||
if (move_window(fs, gpt_header->part_ent_lba) != FR_OK) return FR_DISK_ERR;
|
||||
gpt_entry_t *gpt_entry = (gpt_entry_t *)fs->win;
|
||||
fs->part_type = 1;
|
||||
bsect = gpt_entry->lba_start;
|
||||
fmt = bsect ? check_fs(fs, bsect) : 3; /* Check the partition */
|
||||
DWORD cur_entry, ofs, part;
|
||||
part = LD2PT(vol);
|
||||
cur_entry = 0;
|
||||
for(i = 0; i < gpt_header->num_part_ents; i++){
|
||||
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
|
||||
|
||||
@@ -75,7 +75,7 @@ typedef struct _max77620_regulator_t
|
||||
|
||||
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 }} },
|
||||
{ "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 }} },
|
||||
{ "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 }} },
|
||||
|
||||
357
bdk/sec/se.c
357
bdk/sec/se.c
@@ -91,33 +91,28 @@ static int _se_op_wait()
|
||||
return 0;
|
||||
}
|
||||
|
||||
// WAR: Coherency flushing.
|
||||
if (ll_dst_ptr)
|
||||
// T210B01: IRAM/TZRAM/DRAM AHB coherency WAR.
|
||||
if (!tegra_t210 && ll_dst_ptr)
|
||||
{
|
||||
u32 timeout = get_tmr_us() + 1000000;
|
||||
// Ensure data is out from SE.
|
||||
if (tegra_t210)
|
||||
usleep(15); // Worst case scenario.
|
||||
else
|
||||
while (SE(SE_STATUS_REG) & SE_STATUS_MEM_IF_BUSY)
|
||||
{
|
||||
// T210B01 has a status bit for that.
|
||||
u32 retries = 500000;
|
||||
while (SE(SE_STATUS_REG) & SE_STATUS_MEM_IF_BUSY)
|
||||
{
|
||||
if (!retries)
|
||||
return 0;
|
||||
usleep(1);
|
||||
retries--;
|
||||
}
|
||||
if (get_tmr_us() > timeout)
|
||||
return 0;
|
||||
usleep(1);
|
||||
}
|
||||
|
||||
// Ensure data is out from AHB.
|
||||
u32 retries = 500000;
|
||||
while (AHB_GIZMO(AHB_ARBITRATION_AHB_MEM_WRQUE_MST_ID) & MEM_WRQUE_SE_MST_ID)
|
||||
if (ll_dst_ptr->addr >= DRAM_START)
|
||||
{
|
||||
if (!retries)
|
||||
return 0;
|
||||
usleep(1);
|
||||
retries--;
|
||||
timeout = get_tmr_us() + 200000;
|
||||
while (AHB_GIZMO(AHB_ARBITRATION_AHB_MEM_WRQUE_MST_ID) & MEM_WRQUE_SE_MST_ID)
|
||||
{
|
||||
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)
|
||||
{
|
||||
if (dst_size > SE_LL_MAX_SIZE || src_size > SE_LL_MAX_SIZE)
|
||||
return 0;
|
||||
|
||||
ll_src_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);
|
||||
}
|
||||
|
||||
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 (dst >= (void *)DRAM_START && src >= (void *)DRAM_START)
|
||||
SE(SE_CRYPTO_CONFIG_REG) |= SE_CRYPTO_MEMIF(MEMIF_MCCIF);
|
||||
if (!src || !dst)
|
||||
return 0;
|
||||
|
||||
u32 size_aligned = ALIGN_DOWN(size, SE_AES_BLOCK_SIZE);
|
||||
u32 size_residue = size % SE_AES_BLOCK_SIZE;
|
||||
int res = 1;
|
||||
u32 block[SE_AES_BLOCK_SIZE / sizeof(u32)] = {0};
|
||||
|
||||
// Handle initial aligned message.
|
||||
if (size_aligned)
|
||||
{
|
||||
SE(SE_CRYPTO_LAST_BLOCK_REG) = (size >> 4) - 1;
|
||||
SE(SE_CRYPTO_LAST_BLOCK_REG) = 1 - 1;
|
||||
|
||||
res = _se_execute_oneshot(SE_OP_START, dst, size_aligned, src, size_aligned);
|
||||
}
|
||||
|
||||
// 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);
|
||||
}
|
||||
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);
|
||||
|
||||
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)];
|
||||
memcpy(data, iv, size);
|
||||
u32 data[SE_AES_IV_SIZE / sizeof(u32)];
|
||||
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_DATA_REG) = data[i];
|
||||
}
|
||||
@@ -301,14 +269,22 @@ void se_aes_key_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_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)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
@@ -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_CRYPTO_XOR_POS(XOR_BYPASS);
|
||||
}
|
||||
|
||||
return _se_execute_aes_oneshot(dst, src, size);
|
||||
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_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)
|
||||
{
|
||||
@@ -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_CRYPTO_CORE_SEL(CORE_DECRYPT) | SE_CRYPTO_XOR_POS(XOR_BOTTOM);
|
||||
}
|
||||
|
||||
return _se_execute_aes_oneshot(dst, src, size);
|
||||
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_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;
|
||||
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);
|
||||
return se_aes_crypt_ecb(ks, enc, dst, SE_AES_BLOCK_SIZE, src, SE_AES_BLOCK_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_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);
|
||||
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
|
||||
// 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++)
|
||||
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;
|
||||
for (u32 j = 0; j < SE_AES_BLOCK_SIZE; j++)
|
||||
pdst[j] = pdst[j] ^ tweak[j];
|
||||
@@ -415,7 +421,7 @@ out:
|
||||
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 *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;
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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 *psrc = (u8 *)src;
|
||||
|
||||
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 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.
|
||||
u32 hash32[SE_SHA_256_SIZE / sizeof(u32)];
|
||||
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);
|
||||
}
|
||||
|
||||
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.
|
||||
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;
|
||||
}
|
||||
|
||||
// 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.
|
||||
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_1_REG) = (u32)(total_size >> 29);
|
||||
SE(SE_SHA_MSG_LENGTH_2_REG) = 0;
|
||||
SE(SE_SHA_MSG_LENGTH_3_REG) = 0;
|
||||
|
||||
// Set leftover size: BITS(src_size).
|
||||
SE(SE_SHA_MSG_LEFT_0_REG) = (u32)(msg_left << 3);
|
||||
SE(SE_SHA_MSG_LEFT_1_REG) = (u32)(msg_left >> 29);
|
||||
// Set size left to hash.
|
||||
SE(SE_SHA_MSG_LEFT_0_REG) = (u32)(total_size << 3);
|
||||
SE(SE_SHA_MSG_LEFT_1_REG) = (u32)(total_size >> 29);
|
||||
SE(SE_SHA_MSG_LEFT_2_REG) = 0;
|
||||
SE(SE_SHA_MSG_LEFT_3_REG) = 0;
|
||||
|
||||
// Set config based on init or partial continuation.
|
||||
if (total_size == src_size || !total_size)
|
||||
SE(SE_SHA_CONFIG_REG) = SHA_INIT_HASH;
|
||||
else
|
||||
SE(SE_SHA_CONFIG_REG) = SHA_CONTINUE;
|
||||
// If we hash in chunks, copy over the intermediate.
|
||||
if (sha_cfg == SHA_CONTINUE && msg_left)
|
||||
{
|
||||
// Restore message left to process.
|
||||
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.
|
||||
int res = _se_execute(SE_OP_START, NULL, 0, src, src_size, is_oneshot);
|
||||
// Restore hash reg.
|
||||
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)
|
||||
_se_sha_hash_256_get_hash(hash);
|
||||
// Trigger the operation.
|
||||
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;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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 se_calc_sha256_finalize(void *hash, u32 *msg_left)
|
||||
{
|
||||
int res = _se_execute_finalize();
|
||||
|
||||
_se_sha_hash_256_get_hash(hash);
|
||||
se_calc_sha256_get_hash(hash, msg_left);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int se_rng_pseudo(void *dst, u32 size)
|
||||
int se_gen_prng128(void *dst)
|
||||
{
|
||||
// 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_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_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_SRC_CONFIG_REG) |= SE_RNG_SRC_CONFIG_ENTR_SRC(RO_ENTR_ENABLE); // DRBG. Depends on ENTROPY clock.
|
||||
SE(SE_RNG_RESEED_INTERVAL_REG) = 1;
|
||||
|
||||
u32 size_aligned = ALIGN_DOWN(size, SE_RNG_BLOCK_SIZE);
|
||||
u32 size_residue = size % SE_RNG_BLOCK_SIZE;
|
||||
int res = 0;
|
||||
SE(SE_CRYPTO_LAST_BLOCK_REG) = (16 >> 4) - 1;
|
||||
|
||||
// Handle initial aligned message.
|
||||
if (size_aligned)
|
||||
{
|
||||
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;
|
||||
// Trigger the operation.
|
||||
return _se_execute_oneshot(SE_OP_START, dst, 16, NULL, 0);
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
@@ -668,13 +644,16 @@ void se_aes_ctx_get_keys(u8 *buf, u8 *keys, u32 keysize)
|
||||
srk[3] = PMC(APBDEV_PMC_SECURE_SCRATCH7);
|
||||
|
||||
// Decrypt context.
|
||||
se_aes_key_clear(3);
|
||||
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);
|
||||
}
|
||||
|
||||
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 tmp2[SE_AES_BLOCK_SIZE / sizeof(u32)] = {0};
|
||||
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).
|
||||
se_aes_iv_clear(ks);
|
||||
if (!se_aes_crypt_cbc(ks, ENCRYPT, subkey, subkey, SE_KEY_128_SIZE))
|
||||
return 0;
|
||||
se_aes_iv_updated_clear(ks);
|
||||
if (!se_aes_crypt_hash(ks, ENCRYPT, subkey, SE_KEY_128_SIZE, subkey, SE_KEY_128_SIZE))
|
||||
goto out;
|
||||
|
||||
// Generate K1 subkey.
|
||||
_se_ls_1bit(subkey);
|
||||
if (size & 0xF)
|
||||
_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_DST(DST_HASHREG);
|
||||
SE(SE_CRYPTO_CONFIG_REG) |= SE_CRYPTO_HASH(HASH_ENABLE);
|
||||
SE(SE_CONFIG_REG) = SE_CONFIG_ENC_MODE(MODE_KEY128) | SE_CONFIG_ENC_ALG(ALG_AES_ENC) | SE_CONFIG_DST(DST_HASHREG);
|
||||
SE(SE_CRYPTO_CONFIG_REG) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_INPUT_SEL(INPUT_MEMORY) |
|
||||
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;
|
||||
if (num_blocks > 1)
|
||||
{
|
||||
SE(SE_CRYPTO_LAST_BLOCK_REG) = num_blocks - 2;
|
||||
|
||||
if (!_se_execute_oneshot(SE_OP_START, NULL, 0, src, size))
|
||||
return 0;
|
||||
|
||||
// Use updated IV for next OP as a continuation.
|
||||
goto out;
|
||||
SE(SE_CRYPTO_CONFIG_REG) |= SE_CRYPTO_IV_SEL(IV_UPDATED);
|
||||
}
|
||||
|
||||
// Last block.
|
||||
if (size & 0xF)
|
||||
{
|
||||
memcpy(last_block, src + (size & (~0xF)), size & 0xF);
|
||||
memcpy(last_block, src + (size & ~0xF), size & 0xF);
|
||||
last_block[size & 0xF] = 0x80;
|
||||
}
|
||||
else if (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++)
|
||||
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.
|
||||
if (res)
|
||||
{
|
||||
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);
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
33
bdk/sec/se.h
33
bdk/sec/se.h
@@ -27,29 +27,28 @@ u32 se_key_acc_ctrl_get(u32 ks);
|
||||
|
||||
/*! AES Key Management Functions */
|
||||
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_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);
|
||||
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 */
|
||||
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, const void *src, u32 size);
|
||||
int se_aes_crypt_ofb(u32 ks, void *dst, const void *src, u32 size);
|
||||
int se_aes_crypt_ctr(u32 ks, void *dst, const void *src, u32 size, void *ctr);
|
||||
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_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_crypt_xts(u32 tweak_ks, u32 crypt_ks, int enc, u64 sec, void *dst, void *src, u32 secsize, u32 num_secs);
|
||||
int se_aes_crypt_cbc(u32 ks, int enc, void *dst, u32 dst_size, const void *src, u32 src_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_block_ecb(u32 ks, int enc, void *dst, const void *src);
|
||||
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_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_xts_crypt(u32 tweak_ks, u32 crypt_ks, int enc, u64 sec, void *dst, void *src, u32 secsize, u32 num_secs);
|
||||
/*! Hashing Functions */
|
||||
int se_sha_hash_256_async(void *hash, const void *src, u32 size);
|
||||
int se_sha_hash_256_oneshot(void *hash, const void *src, u32 size);
|
||||
int se_sha_hash_256_partial_start(void *hash, const void *src, u32 size, bool is_oneshot);
|
||||
int se_sha_hash_256_partial_update(void *hash, const void *src, u32 size, bool is_oneshot);
|
||||
int se_sha_hash_256_partial_end(void *hash, u64 total_size, const void *src, u32 src_size, bool is_oneshot);
|
||||
int se_sha_hash_256_finalize(void *hash);
|
||||
int se_aes_hash_cmac(u32 ks, 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_aes_crypt_ctr(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_size, void *ctr);
|
||||
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_calc_sha256_oneshot(void *hash, const void *src, u32 src_size);
|
||||
int se_calc_sha256_finalize(void *hash, u32 *msg_left);
|
||||
int se_aes_cmac_128(u32 ks, void *hash, const void *src, u32 size);
|
||||
/*! Random Functions */
|
||||
int se_rng_pseudo(void *dst, u32 size);
|
||||
int se_gen_prng128(void *dst);
|
||||
|
||||
#endif
|
||||
|
||||
275
bdk/storage/boot_storage.c
Normal file
275
bdk/storage/boot_storage.c
Normal 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;
|
||||
}
|
||||
24
bdk/storage/boot_storage.h
Normal file
24
bdk/storage/boot_storage.h
Normal 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
|
||||
@@ -21,10 +21,14 @@
|
||||
#include <mem/heap.h>
|
||||
#include <soc/fuse.h>
|
||||
#include <storage/mbr_gpt.h>
|
||||
#include <gfx_utils.h>
|
||||
#include <utils/list.h>
|
||||
#include <storage/emummc_file_based.h>
|
||||
|
||||
static u16 emmc_errors[3] = { 0 }; // Init and Read/Write errors.
|
||||
static u32 emmc_mode = EMMC_MMC_HS400;
|
||||
static bool emmc_init_done = false;
|
||||
static bool emmc_mounted = false;
|
||||
|
||||
sdmmc_t emmc_sdmmc;
|
||||
sdmmc_storage_t emmc_storage;
|
||||
@@ -61,7 +65,26 @@ u32 emmc_get_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)
|
||||
{
|
||||
@@ -97,7 +120,13 @@ int emmc_init_retry(bool power_cycle)
|
||||
emmc_mode = EMMC_MMC_HS400;
|
||||
}
|
||||
|
||||
return sdmmc_storage_init_mmc(&emmc_storage, &emmc_sdmmc, bus_width, type);
|
||||
int res = sdmmc_storage_init_mmc(&emmc_storage, &emmc_sdmmc, bus_width, type);
|
||||
if(res){
|
||||
emmc_init_done = true;
|
||||
}else{
|
||||
emmc_init_done = false;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
bool emmc_initialize(bool power_cycle)
|
||||
@@ -212,6 +241,14 @@ int emmc_part_write(emmc_part_t *part, u32 sector_off, u32 num_sectors, void *bu
|
||||
#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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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); }
|
||||
@@ -65,12 +65,17 @@ int emmc_init_retry(bool power_cycle);
|
||||
bool emmc_initialize(bool power_cycle);
|
||||
int emmc_set_partition(u32 partition);
|
||||
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_free(link_t *gpt);
|
||||
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_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);
|
||||
|
||||
|
||||
233
bdk/storage/emummc_file_based.c
Normal file
233
bdk/storage/emummc_file_based.c
Normal 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;
|
||||
}
|
||||
14
bdk/storage/emummc_file_based.h
Normal file
14
bdk/storage/emummc_file_based.h
Normal 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
|
||||
184
bdk/storage/file_based_storage.c
Normal file
184
bdk/storage/file_based_storage.c
Normal 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;
|
||||
}
|
||||
15
bdk/storage/file_based_storage.h
Normal file
15
bdk/storage/file_based_storage.h
Normal 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
39
bdk/storage/mbr_gpt.c
Normal 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;
|
||||
}
|
||||
@@ -81,4 +81,10 @@ typedef struct _gpt_t
|
||||
gpt_entry_t entries[128];
|
||||
} 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
|
||||
|
||||
@@ -17,6 +17,9 @@
|
||||
* 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 <memory_map.h>
|
||||
@@ -26,6 +29,7 @@
|
||||
#include <storage/emmc.h>
|
||||
#include <storage/sd.h>
|
||||
#include <storage/sdmmc.h>
|
||||
#include <storage/emummc_file_based.h>
|
||||
#include <utils/types.h>
|
||||
|
||||
#define BIS_CLUSTER_SECTORS 32
|
||||
@@ -56,6 +60,8 @@ static u32 emu_offset = 0;
|
||||
static emmc_part_t *system_part = NULL;
|
||||
static u32 *cache_lookup_tbl = (u32 *)NX_BIS_LOOKUP_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)
|
||||
{
|
||||
@@ -91,14 +97,18 @@ static int nx_emmc_bis_write_block(u32 sector, u32 count, void *buff, bool flush
|
||||
}
|
||||
|
||||
// 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.
|
||||
|
||||
// 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);
|
||||
else
|
||||
res = sdmmc_storage_write(&sd_storage, emu_offset + system_part->lba_start + sector, count, bis_cache->dma_buff);
|
||||
}
|
||||
|
||||
if (!res)
|
||||
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;
|
||||
|
||||
// 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);
|
||||
else
|
||||
res = sdmmc_storage_read(&sd_storage, emu_offset + system_part->lba_start + sector, count, bis_cache->dma_buff);
|
||||
}
|
||||
if (!res)
|
||||
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;
|
||||
|
||||
// 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.
|
||||
|
||||
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;
|
||||
|
||||
// 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);
|
||||
else
|
||||
res = sdmmc_storage_read(&sd_storage, emu_offset + system_part->lba_start + cluster_sector, BIS_CLUSTER_SECTORS, bis_cache->dma_buff);
|
||||
}
|
||||
|
||||
if (!res)
|
||||
return 1; // R/W error.
|
||||
|
||||
// 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.
|
||||
|
||||
// Copy to cluster cache.
|
||||
@@ -292,10 +309,11 @@ int nx_emmc_bis_write(u32 sector, u32 count, void *buff)
|
||||
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;
|
||||
emu_offset = emummc_offset;
|
||||
emu_storage = storage;
|
||||
|
||||
_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;
|
||||
}
|
||||
|
||||
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()
|
||||
{
|
||||
_nx_emmc_bis_flush_cache();
|
||||
|
||||
if(file_based){
|
||||
emummc_storage_file_based_end();
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
@@ -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_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();
|
||||
sdmmc_storage_t *nx_emmc_bis_get_storage();
|
||||
|
||||
#endif
|
||||
|
||||
@@ -44,7 +44,7 @@ int ram_disk_init(void *ram_fs, u32 ramdisk_size)
|
||||
disk_set_info(DRIVE_RAM, SET_SECTOR_COUNT, &ramdisk_size);
|
||||
|
||||
// Unmount ramdisk.
|
||||
f_unmount("ram:");
|
||||
f_mount(NULL, "ram:", 1);
|
||||
|
||||
// Format as exFAT w/ 32KB cluster with no MBR.
|
||||
res = f_mkfs("ram:", FM_EXFAT | FM_SFD, RAMDISK_CLUSTER_SZ, buf, 0x400000);
|
||||
|
||||
@@ -199,7 +199,7 @@ bool sd_mount()
|
||||
else
|
||||
{
|
||||
if (!sd_mounted)
|
||||
res = f_mount(&sd_fs, "0:", 1); // Volume 0 is SD.
|
||||
res = f_mount(&sd_fs, "sd:", 1); // Volume 0 is SD.
|
||||
if (res == FR_OK)
|
||||
{
|
||||
sd_mounted = true;
|
||||
@@ -227,7 +227,7 @@ static void _sd_deinit(bool deinit)
|
||||
if (sd_init_done)
|
||||
{
|
||||
if (sd_mounted)
|
||||
f_unmount("0:"); // Volume 0 is SD.
|
||||
f_mount(NULL, "sd:", 1); // Volume 0 is SD.
|
||||
|
||||
if (deinit)
|
||||
{
|
||||
@@ -246,14 +246,30 @@ bool sd_is_gpt()
|
||||
return sd_fs.part_type;
|
||||
}
|
||||
|
||||
|
||||
void *sd_file_read(const char *path, u32 *fsize)
|
||||
{
|
||||
FIL fp;
|
||||
if (!sd_get_card_mounted())
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
if (fsize)
|
||||
@@ -263,13 +279,17 @@ void *sd_file_read(const char *path, u32 *fsize)
|
||||
|
||||
if (f_read(&fp, buf, size, NULL) != FR_OK)
|
||||
{
|
||||
f_chdrive(cwd);
|
||||
free(buf);
|
||||
free(cwd);
|
||||
f_close(&fp);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
f_chdrive(cwd);
|
||||
f_close(&fp);
|
||||
free(cwd);
|
||||
|
||||
return buf;
|
||||
}
|
||||
@@ -281,13 +301,33 @@ int sd_save_to_file(const void *buf, u32 size, const char *filename)
|
||||
if (!sd_get_card_mounted())
|
||||
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);
|
||||
if (res)
|
||||
{
|
||||
EPRINTFARGS("Error (%d) creating file\n%s.\n", res, filename);
|
||||
f_chdrive(cwd);
|
||||
free(cwd);
|
||||
return res;
|
||||
}
|
||||
|
||||
f_chdrive(cwd);
|
||||
free(cwd);
|
||||
f_write(&fp, buf, size, NULL);
|
||||
f_close(&fp);
|
||||
|
||||
|
||||
@@ -31,8 +31,13 @@ extern u32 sd_power_cycle_time_start;
|
||||
|
||||
typedef enum _sdmmc_type
|
||||
{
|
||||
MMC_SD = 0,
|
||||
MMC_EMMC = 1,
|
||||
MMC_SD = 0,
|
||||
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_BOOT0 = 1,
|
||||
|
||||
@@ -19,6 +19,9 @@
|
||||
* 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 <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.
|
||||
if (!sdmmc_storage_read(ums->lun.storage, ums->lun.offset + lba_offset, amount, sdmmc_buf))
|
||||
amount = 0;
|
||||
if(ums->lun.storage){
|
||||
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.
|
||||
if (!first_read)
|
||||
@@ -650,9 +663,19 @@ static int _scsi_write(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
|
||||
goto empty_write;
|
||||
|
||||
// Perform the write.
|
||||
if (!sdmmc_storage_write(ums->lun.storage, ums->lun.offset + lba_offset,
|
||||
amount >> UMS_DISK_LBA_SHIFT, (u8 *)bulk_ctxt->bulk_out_buf))
|
||||
amount = 0;
|
||||
if(ums->lun.storage){
|
||||
if (!sdmmc_storage_write(ums->lun.storage, ums->lun.offset + lba_offset,
|
||||
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);
|
||||
|
||||
@@ -722,8 +745,18 @@ static int _scsi_verify(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
|
||||
break;
|
||||
}
|
||||
|
||||
if (!sdmmc_storage_read(ums->lun.storage, ums->lun.offset + lba_offset, amount, bulk_ctxt->bulk_in_buf))
|
||||
amount = 0;
|
||||
if(ums->lun.storage){
|
||||
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);
|
||||
|
||||
@@ -756,8 +789,12 @@ static int _scsi_inquiry(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
|
||||
buf[3] = 20; // Additional length.
|
||||
|
||||
buf += 4;
|
||||
s_printf((char *)buf, "%04X%s",
|
||||
ums->lun.storage->cid.serial, ums->lun.type == MMC_SD ? " SD " : " eMMC ");
|
||||
if(ums->lun.storage){
|
||||
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)
|
||||
{
|
||||
@@ -1861,7 +1898,7 @@ int usb_device_gadget_ums(usb_ctxt_t *usbs)
|
||||
if (usbs->type == MMC_SD)
|
||||
{
|
||||
sd_end();
|
||||
if (!sd_mount())
|
||||
if (!sd_mount() && !sd_get_card_initialized())
|
||||
{
|
||||
ums.set_text(ums.label, "#FFDD00 Failed to init SD!#");
|
||||
res = 1;
|
||||
@@ -1871,9 +1908,50 @@ int usb_device_gadget_ums(usb_ctxt_t *usbs)
|
||||
|
||||
ums.lun.sdmmc = &sd_sdmmc;
|
||||
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))
|
||||
{
|
||||
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 (!ums.lun.num_sectors)
|
||||
{
|
||||
if (usbs->type == MMC_EMMC && (ums.lun.partition - 1)) // eMMC BOOT0/1.
|
||||
ums.lun.num_sectors = emmc_storage.ext_csd.boot_mult << 8;
|
||||
else
|
||||
ums.lun.num_sectors = ums.lun.storage->sec_cnt; // eMMC GPP or SD.
|
||||
switch(usbs->type){
|
||||
case MMC_EMMC:
|
||||
if(ums.lun.partition - 1){
|
||||
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
|
||||
|
||||
@@ -22,15 +22,12 @@
|
||||
#include <mem/heap.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;
|
||||
u32 k = 0;
|
||||
DIR dir;
|
||||
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));
|
||||
|
||||
@@ -46,11 +43,11 @@ dirlist_t *dirlist(const char *directory, const char *pattern, u32 flags)
|
||||
if (res || !fno.fname[0])
|
||||
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 ((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);
|
||||
if (++k >= DIR_MAX_ENTRIES)
|
||||
@@ -64,7 +61,7 @@ dirlist_t *dirlist(const char *directory, const char *pattern, u32 flags)
|
||||
{
|
||||
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);
|
||||
if (++k >= DIR_MAX_ENTRIES)
|
||||
@@ -85,15 +82,12 @@ dirlist_t *dirlist(const char *directory, const char *pattern, u32 flags)
|
||||
// Terminate name list.
|
||||
dir_entries->name[k] = NULL;
|
||||
|
||||
// Choose list ordering.
|
||||
int (*strcmpex)(const char* str1, const char* str2) = ascii_order ? strcmp : strcasecmp;
|
||||
|
||||
// Reorder ini files Alphabetically.
|
||||
for (u32 i = 0; i < k - 1 ; i++)
|
||||
{
|
||||
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];
|
||||
dir_entries->name[i] = dir_entries->name[j];
|
||||
|
||||
@@ -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
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
@@ -18,14 +18,10 @@
|
||||
|
||||
#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
|
||||
{
|
||||
char *name[DIR_MAX_ENTRIES];
|
||||
char data[DIR_MAX_ENTRIES * 256];
|
||||
} 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);
|
||||
|
||||
@@ -70,7 +70,7 @@ int ini_parse(link_t *dst, const char *ini_path, bool is_dir)
|
||||
// Get all ini filenames.
|
||||
if (is_dir)
|
||||
{
|
||||
filelist = dirlist(filename, "*.ini", DIR_ASCII_ORDER);
|
||||
filelist = dirlist(filename, "*.ini", false, false);
|
||||
if (!filelist)
|
||||
{
|
||||
free(filename);
|
||||
|
||||
@@ -105,6 +105,9 @@ typedef unsigned long uptr;
|
||||
#define likely(x) (__builtin_expect((x) != 0, 1))
|
||||
#define unlikely(x) (__builtin_expect((x) != 0, 0))
|
||||
|
||||
#define XSTR(a) STR(a)
|
||||
#define STR(a) #a
|
||||
|
||||
/* Bootloader/Nyx */
|
||||
#define BOOT_CFG_AUTOBOOT_EN BIT(0)
|
||||
#define BOOT_CFG_FROM_LAUNCH BIT(1)
|
||||
@@ -126,7 +129,11 @@ typedef enum _nyx_ums_type
|
||||
NYX_UMS_EMMC_GPP,
|
||||
NYX_UMS_EMUMMC_BOOT0,
|
||||
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;
|
||||
|
||||
typedef struct __attribute__((__packed__)) _boot_cfg_t
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <storage/boot_storage.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <mem/heap.h>
|
||||
@@ -273,6 +274,7 @@ void power_set_state(power_state_t state)
|
||||
u8 reg;
|
||||
|
||||
// Unmount and power down sd card.
|
||||
boot_storage_end();
|
||||
sd_end();
|
||||
|
||||
// De-initialize and power down various hardware.
|
||||
|
||||
@@ -25,7 +25,6 @@
|
||||
void set_default_configuration()
|
||||
{
|
||||
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_list = 0;
|
||||
|
||||
@@ -35,7 +35,6 @@ typedef struct _hekate_config
|
||||
u32 bootprotect;
|
||||
// Global temporary config.
|
||||
bool t210b01;
|
||||
bool devmode;
|
||||
bool emummc_force_disable;
|
||||
bool rcm_patched;
|
||||
u32 errors;
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <storage/sd.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <bdk.h>
|
||||
@@ -37,7 +38,7 @@ void print_fuseinfo()
|
||||
gfx_con_setpos(0, 0);
|
||||
|
||||
gfx_printf("\nSKU: %X - ", FUSE(FUSE_SKU_INFO));
|
||||
switch (h_cfg.devmode)
|
||||
switch (fuse_read_hw_state())
|
||||
{
|
||||
case FUSE_NX_HW_STATE_PROD:
|
||||
gfx_printf("Retail\n");
|
||||
@@ -230,19 +231,18 @@ void print_sdcard_info()
|
||||
sd_storage.ssr.app_class, sd_storage.csd.write_protect,
|
||||
sd_errors[0], sd_errors[1], sd_errors[2]); // SD_ERROR_INIT_FAIL, SD_ERROR_RW_FAIL, SD_ERROR_RW_RETRY.
|
||||
|
||||
int res = f_mount(&sd_fs, "", 1);
|
||||
if (!res)
|
||||
if (sd_mount())
|
||||
{
|
||||
gfx_puts("Acquiring FAT volume info...\n\n");
|
||||
gfx_printf("%kFound %s volume:%k\n Free: %d MiB\n Cluster: %d KiB\n",
|
||||
TXT_CLR_CYAN_L, sd_fs.fs_type == FS_EXFAT ? "exFAT" : "FAT32", TXT_CLR_DEFAULT,
|
||||
sd_fs.free_clst * sd_fs.csize >> SECTORS_TO_MIB_COEFF, (sd_fs.csize > 1) ? (sd_fs.csize >> 1) : 512);
|
||||
f_unmount("");
|
||||
sd_end();
|
||||
}
|
||||
else
|
||||
{
|
||||
EPRINTFARGS("Failed to mount SD card (FatFS Error %d).\n"
|
||||
"Make sure that a FAT partition exists..", res);
|
||||
EPRINTF("Failed to mount SD card.\n"
|
||||
"Make sure that a FAT partition exists..");
|
||||
}
|
||||
|
||||
sd_end();
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2018 st4rk
|
||||
* Copyright (c) 2018 Ced2911
|
||||
* Copyright (c) 2018-2026 CTCaer
|
||||
* Copyright (c) 2018-2025 CTCaer
|
||||
* Copyright (c) 2018 balika011
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
@@ -28,6 +28,8 @@
|
||||
#include "../frontend/fe_tools.h"
|
||||
#include "../config.h"
|
||||
#include "../storage/emummc.h"
|
||||
#include "../storage/emusd.h"
|
||||
#include <storage/boot_storage.h>
|
||||
|
||||
//#define DPRINTF(...) gfx_printf(__VA_ARGS__)
|
||||
#define DPRINTF(...)
|
||||
@@ -166,7 +168,7 @@ static void _hos_eks_get()
|
||||
|
||||
// Decrypt EKS blob.
|
||||
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.
|
||||
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.
|
||||
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.
|
||||
h_cfg.eks->magic = HOS_EKS_MAGIC;
|
||||
@@ -227,7 +229,7 @@ static void _hos_eks_save()
|
||||
// Encrypt EKS blob.
|
||||
u8 *eks = malloc(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.
|
||||
memcpy(mbr + 0x80, eks, sizeof(hos_eks_mbr_t));
|
||||
@@ -262,7 +264,7 @@ static void _hos_eks_clear(u32 mkey)
|
||||
// Encrypt EKS blob.
|
||||
u8 *eks = malloc(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.
|
||||
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.
|
||||
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)
|
||||
{
|
||||
_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
|
||||
{
|
||||
// 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);
|
||||
|
||||
// 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
|
||||
{
|
||||
// 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);
|
||||
|
||||
// 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);
|
||||
|
||||
// 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_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);
|
||||
|
||||
// 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.
|
||||
u8 cmac[SE_KEY_128_SIZE];
|
||||
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))
|
||||
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);
|
||||
|
||||
// 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(12, 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)
|
||||
{
|
||||
@@ -666,7 +668,7 @@ static bool _get_fs_exfat_compatible(link_t *info, u32 *hos_revision)
|
||||
if (strcmp((char *)ki->kip1->name, "FS"))
|
||||
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;
|
||||
|
||||
pkg2_get_ids(&kip_ids, &fs_ids_cnt);
|
||||
@@ -726,8 +728,14 @@ void hos_launch(ini_sec_t *cfg)
|
||||
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.
|
||||
if (sd_is_gpt())
|
||||
if (emusd_is_gpt())
|
||||
{
|
||||
_hos_crit_error("SD has GPT only! Run Fix Hybrid MBR!");
|
||||
goto error;
|
||||
@@ -746,6 +754,8 @@ void hos_launch(ini_sec_t *cfg)
|
||||
// Check if stock is enabled and device can boot in OFW.
|
||||
if (ctxt.stock && (h_cfg.t210b01 || !tools_autorcm_enabled()))
|
||||
{
|
||||
emusd_storage_end();
|
||||
emummc_storage_end();
|
||||
emmc_end();
|
||||
|
||||
WPRINTF("\nRebooting to OFW in 5s...");
|
||||
@@ -758,7 +768,8 @@ void hos_launch(ini_sec_t *cfg)
|
||||
|
||||
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.
|
||||
if (emummc_enabled)
|
||||
@@ -839,7 +850,7 @@ void hos_launch(ini_sec_t *cfg)
|
||||
if (h_cfg.t210b01)
|
||||
{
|
||||
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.
|
||||
EPRINTF("Pkg1 corrupt?");
|
||||
else
|
||||
@@ -947,9 +958,9 @@ void hos_launch(ini_sec_t *cfg)
|
||||
// Hash only Kernel when it embeds INI1.
|
||||
u8 kernel_hash[0x20];
|
||||
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
|
||||
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);
|
||||
|
||||
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)
|
||||
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))
|
||||
{
|
||||
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!");
|
||||
|
||||
@@ -1008,14 +1019,14 @@ void hos_launch(ini_sec_t *cfg)
|
||||
{
|
||||
EHPRINTFARGS("Failed to apply '%s'!", failed_patch);
|
||||
|
||||
bool emu_patch_failed = !strcmp(failed_patch, "emummc");
|
||||
if (!emu_patch_failed)
|
||||
bool emmc_patch_failed = !strcmp(failed_patch, "emummc");
|
||||
if (!emmc_patch_failed)
|
||||
{
|
||||
gfx_puts("\nPress POWER to continue.\nPress VOL to go to the menu.\n");
|
||||
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!
|
||||
}
|
||||
|
||||
@@ -1027,6 +1038,9 @@ void hos_launch(ini_sec_t *cfg)
|
||||
config_exosphere(&ctxt, warmboot_base);
|
||||
|
||||
// Unmount SD card and eMMC.
|
||||
emummc_storage_end();
|
||||
emusd_storage_end();
|
||||
boot_storage_end();
|
||||
sd_end();
|
||||
emmc_end();
|
||||
|
||||
@@ -1127,6 +1141,8 @@ void hos_launch(ini_sec_t *cfg)
|
||||
|
||||
error:
|
||||
_free_launch_components(&ctxt);
|
||||
emummc_storage_end();
|
||||
emusd_storage_end();
|
||||
emmc_end();
|
||||
|
||||
EPRINTF("\nFailed to launch HOS!");
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
* 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 <bdk.h>
|
||||
@@ -29,7 +31,7 @@
|
||||
|
||||
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)
|
||||
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)
|
||||
{
|
||||
ctxt->secmon = sd_file_read(value, &ctxt->secmon_size);
|
||||
ctxt->secmon = emusd_file_read(value, &ctxt->secmon_size);
|
||||
if (!ctxt->secmon)
|
||||
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)
|
||||
{
|
||||
ctxt->kernel = sd_file_read(value, &ctxt->kernel_size);
|
||||
ctxt->kernel = emusd_file_read(value, &ctxt->kernel_size);
|
||||
if (!ctxt->kernel)
|
||||
return 0;
|
||||
|
||||
@@ -61,11 +63,12 @@ static int _config_kip1(launch_ctxt_t *ctxt, const char *value)
|
||||
if (value[strlen(value) - 1] == '*')
|
||||
{
|
||||
char *dir = (char *)malloc(256);
|
||||
strcpy(dir, value);
|
||||
strcpy(dir, "emusd:");
|
||||
strcat(dir, value);
|
||||
|
||||
u32 dirlen = 0;
|
||||
dir[strlen(dir) - 2] = 0;
|
||||
dirlist_t *filelist = dirlist(dir, "*.kip*", 0);
|
||||
dirlist_t *filelist = dirlist(dir, "*.kip*", false, false);
|
||||
|
||||
strcat(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]);
|
||||
|
||||
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)
|
||||
{
|
||||
free(mkip1);
|
||||
@@ -103,7 +106,7 @@ static int _config_kip1(launch_ctxt_t *ctxt, const char *value)
|
||||
else
|
||||
{
|
||||
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)
|
||||
{
|
||||
free(mkip1);
|
||||
@@ -169,7 +172,7 @@ static int _config_stock(launch_ctxt_t *ctxt, const char *value)
|
||||
{
|
||||
if (*value == '1')
|
||||
{
|
||||
DPRINTF("Enabled stock mode\n");
|
||||
DPRINTF("Disabled all patching\n");
|
||||
ctxt->stock = true;
|
||||
}
|
||||
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)
|
||||
{
|
||||
ctxt->exofatal = sd_file_read(value, &ctxt->exofatal_size);
|
||||
ctxt->exofatal = emusd_file_read(value, &ctxt->exofatal_size);
|
||||
if (!ctxt->exofatal)
|
||||
return 0;
|
||||
|
||||
|
||||
@@ -17,6 +17,8 @@
|
||||
* 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 <stdlib.h>
|
||||
|
||||
@@ -205,7 +207,7 @@ int pkg1_decrypt(const pkg1_id_t *id, u8 *pkg1)
|
||||
u8 *pkg11 = pkg1 + id->pkg11_off;
|
||||
u32 pkg11_size = *(u32 *)pkg11;
|
||||
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
|
||||
{
|
||||
@@ -216,7 +218,7 @@ int pkg1_decrypt(const pkg1_id_t *id, u8 *pkg1)
|
||||
// Use BEK for T210B01.
|
||||
// Additionally, skip 0x20 bytes from decryption to maintain the header.
|
||||
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.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* 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
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
#include <storage/boot_storage.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <bdk.h>
|
||||
@@ -27,6 +28,7 @@
|
||||
#include <libs/compr/blz.h>
|
||||
#include <libs/fatfs/ff.h>
|
||||
#include "../storage/emummc.h"
|
||||
#include "../storage/emusd.h"
|
||||
|
||||
//#define DPRINTF(...) gfx_printf(__VA_ARGS__)
|
||||
#define DPRINTF(...)
|
||||
@@ -64,6 +66,7 @@ static void parse_external_kip_patches()
|
||||
return;
|
||||
|
||||
LIST_INIT(ini_kip_sections);
|
||||
// TODO: load frome emusd?
|
||||
if (ini_patch_parse(&ini_kip_sections, "bootloader/patches.ini"))
|
||||
{
|
||||
// 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))
|
||||
{
|
||||
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)
|
||||
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.
|
||||
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));
|
||||
|
||||
// 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)
|
||||
emu_cfg.fs_ver -= 2;
|
||||
|
||||
emu_sd_cfg.fs_ver = emu_cfg.fs_ver;
|
||||
|
||||
// Inject emuMMC code.
|
||||
gfx_printf("Injecting emuMMC. FS ID: %d\n", emu_cfg.fs_ver);
|
||||
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];
|
||||
|
||||
// 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.
|
||||
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.
|
||||
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)
|
||||
return NULL;
|
||||
@@ -730,7 +735,7 @@ DPRINTF("sec %d has size %08X\n", i, hdr->sec_size[i]);
|
||||
if (!hdr->sec_size[i])
|
||||
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];
|
||||
}
|
||||
@@ -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_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
|
||||
{
|
||||
@@ -854,7 +859,7 @@ DPRINTF("%s @ %08X (%08X)\n", is_meso ? "Mesosphere": "kernel",(u32)ctxt->kernel
|
||||
kernel_size += ini1_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;
|
||||
DPRINTF("kernel encrypted\n");
|
||||
|
||||
@@ -870,7 +875,7 @@ DPRINTF("INI1 encrypted\n");
|
||||
u8 *pk2_hash_data = (u8 *)dst + 0x100 + sizeof(pkg2_hdr_t);
|
||||
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];
|
||||
}
|
||||
}
|
||||
@@ -878,7 +883,7 @@ DPRINTF("INI1 encrypted\n");
|
||||
// Encrypt header.
|
||||
*(u32 *)hdr->ctr = 0x100 + sizeof(pkg2_hdr_t) + kernel_size + ini1_size;
|
||||
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);
|
||||
*(u32 *)hdr->ctr = 0x100 + sizeof(pkg2_hdr_t) + kernel_size + ini1_size;
|
||||
hdr->ctr[4] = key_ver;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* 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
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
@@ -71,7 +71,7 @@ enum
|
||||
typedef struct _pkg2_hdr_t
|
||||
{
|
||||
/* 0x000 */ u8 ctr[0x10];
|
||||
/* 0x010 */ u8 sec_ctr[4][SE_AES_IV_SIZE];
|
||||
/* 0x010 */ u8 sec_ctr[0x40];
|
||||
/* 0x050 */ u32 magic;
|
||||
/* 0x054 */ u32 base;
|
||||
/* 0x058 */ u32 pad0;
|
||||
@@ -80,7 +80,7 @@ typedef struct _pkg2_hdr_t
|
||||
/* 0x05E */ u16 pad1;
|
||||
/* 0x060 */ u32 sec_size[4];
|
||||
/* 0x070 */ u32 sec_off[4];
|
||||
/* 0x080 */ u8 sec_sha256[4][SE_SHA_256_SIZE];
|
||||
/* 0x080 */ u8 sec_sha256[0x80];
|
||||
/* 0x100 */ u8 data[];
|
||||
} pkg2_hdr_t;
|
||||
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
* 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 <bdk.h>
|
||||
@@ -29,7 +31,7 @@
|
||||
//#define DPRINTF(...) gfx_printf(__VA_ARGS__)
|
||||
#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
|
||||
|
||||
@@ -84,10 +86,9 @@ typedef struct _pkg3_content_t
|
||||
|
||||
static void _pkg3_update_r2p()
|
||||
{
|
||||
u32 size = 0;
|
||||
u8 *r2p_payload = sd_file_read("atmosphere/reboot_payload.bin", &size);
|
||||
u8 *r2p_payload = emusd_file_read("atmosphere/reboot_payload.bin", NULL);
|
||||
|
||||
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);
|
||||
}
|
||||
@@ -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)
|
||||
{
|
||||
char *path1 = (char *)malloc(256);
|
||||
strcpy(path1, "emusd:");
|
||||
strcat(path1, path);
|
||||
|
||||
FIL fp;
|
||||
|
||||
char **pkg3_kip1_skip = NULL;
|
||||
@@ -152,16 +157,25 @@ int parse_pkg3(launch_ctxt_t *ctxt, const char *path)
|
||||
}
|
||||
|
||||
#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;
|
||||
}
|
||||
|
||||
#else
|
||||
if (stock && emummc_disabled && pkg1_old)
|
||||
if (stock && emummc_disabled && pkg1_old) {
|
||||
free(path1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
|
||||
void *pkg3 = malloc(f_size(&fp));
|
||||
|
||||
@@ -267,6 +281,7 @@ int parse_pkg3(launch_ctxt_t *ctxt, const char *path)
|
||||
_pkg3_update_r2p();
|
||||
|
||||
free(pkg3_kip1_skip);
|
||||
free(path1);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -24,12 +24,15 @@
|
||||
#include "../config.h"
|
||||
#include <libs/fatfs/ff.h>
|
||||
#include "../storage/emummc.h"
|
||||
#include "../storage/emusd.h"
|
||||
|
||||
enum emuMMC_Type
|
||||
{
|
||||
emuMMC_None = 0,
|
||||
emuMMC_Partition,
|
||||
emuMMC_File,
|
||||
EmummcType_None = 0,
|
||||
EmummcType_Partition_Sd = 1,
|
||||
EmummcType_File_Sd = 2,
|
||||
EmummcType_Partition_Emmc = 3,
|
||||
EmummcType_File_Emmc = 4,
|
||||
emuMMC_MAX
|
||||
};
|
||||
|
||||
@@ -64,6 +67,22 @@ typedef struct
|
||||
emummc_file_config_t file_cfg;
|
||||
};
|
||||
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;
|
||||
|
||||
typedef struct _exo_cfg_t
|
||||
@@ -75,7 +94,8 @@ typedef struct _exo_cfg_t
|
||||
u8 uart_port;
|
||||
u8 uart_invert;
|
||||
u32 uart_baudrate;
|
||||
u32 rsvd1[2];
|
||||
u8 memory_mode_auto;
|
||||
u8 rsvd1[7];
|
||||
exo_emummc_config_t emummc_cfg;
|
||||
} exo_cfg_t;
|
||||
|
||||
@@ -206,7 +226,7 @@ void config_exosphere(launch_ctxt_t *ctxt, u32 warmboot_base)
|
||||
if (!ctxt->stock)
|
||||
{
|
||||
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)
|
||||
{
|
||||
@@ -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"))
|
||||
continue;
|
||||
|
||||
|
||||
LIST_FOREACH_ENTRY(ini_kv_t, kv, &ini_sec->kvs, link)
|
||||
{
|
||||
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);
|
||||
else if (!strcmp("log_baud_rate", kv->key))
|
||||
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)
|
||||
{
|
||||
if (!strcmp("blank_prodinfo_emummc", kv->key))
|
||||
cal0_blanking = atoi(kv->val);
|
||||
}
|
||||
else
|
||||
} else
|
||||
{
|
||||
if (!strcmp("blank_prodinfo_sysmmc", kv->key))
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
@@ -314,22 +337,72 @@ void config_exosphere(launch_ctxt_t *ctxt, u32 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)
|
||||
{
|
||||
exo_cfg->emummc_cfg.base_cfg.magic = EMUMMC_MAGIC;
|
||||
exo_cfg->emummc_cfg.base_cfg.type = emu_cfg.sector ? emuMMC_Partition : emuMMC_File;
|
||||
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.fs_ver = emu_cfg.fs_ver;
|
||||
exo_cfg->emummc_cfg.sd_cfg.base_cfg.fs_ver = emu_sd_cfg.fs_ver;
|
||||
|
||||
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)
|
||||
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
|
||||
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])
|
||||
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
|
||||
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.
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include "../hos/pkg1.h"
|
||||
#include "l4t.h"
|
||||
#include "l4t_config.inl"
|
||||
#include <storage/boot_storage.h>
|
||||
|
||||
/*
|
||||
* API Revision info
|
||||
@@ -283,7 +284,7 @@ typedef struct _l4t_ctxt_t
|
||||
} l4t_ctxt_t;
|
||||
|
||||
#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_VDDQ_OC_MIN_VOLTAGE 550
|
||||
#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;
|
||||
|
||||
// Done loading bootloaders/firmware.
|
||||
boot_storage_end();
|
||||
sd_end();
|
||||
emmc_end();
|
||||
|
||||
// We don't need AHB aperture open.
|
||||
mc_disable_ahb_redirect();
|
||||
|
||||
@@ -7,11 +7,39 @@
|
||||
/* 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 <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 */
|
||||
@@ -43,7 +71,33 @@ DRESULT disk_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 */
|
||||
)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
|
||||
@@ -168,7 +168,7 @@
|
||||
*/
|
||||
|
||||
|
||||
#define FF_FS_RPATH 0
|
||||
#define FF_FS_RPATH 2
|
||||
/* This option configures support for relative path.
|
||||
/
|
||||
/ 0: Disable relative path and remove related functions.
|
||||
@@ -181,12 +181,12 @@
|
||||
/ Drive/Volume Configurations
|
||||
/---------------------------------------------------------------------------*/
|
||||
|
||||
#define FF_VOLUMES 1
|
||||
#define FF_VOLUMES 5
|
||||
/* Number of volumes (logical drives) to be used. (1-10) */
|
||||
|
||||
|
||||
#define FF_STR_VOLUME_ID 0
|
||||
#define FF_VOLUME_STRS "sd"
|
||||
#define FF_STR_VOLUME_ID 1
|
||||
#define FF_VOLUME_STRS "sd", "boot1", "boot1_1mb", "emmc", "emusd"
|
||||
/* FF_STR_VOLUME_ID switches support for volume ID in arbitrary strings.
|
||||
/ When FF_STR_VOLUME_ID is set to 1 or 2, arbitrary strings can be used as drive
|
||||
/ number in the path name. FF_VOLUME_STRS defines the volume ID strings for each
|
||||
@@ -303,5 +303,12 @@
|
||||
/ 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 ---*/
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include <bdk.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "gfx/gfx.h"
|
||||
#include "gfx/logos.h"
|
||||
#include "gfx/tui.h"
|
||||
#include "hos/hos.h"
|
||||
@@ -31,9 +32,11 @@
|
||||
#include <libs/compr/blz.h>
|
||||
#include <libs/fatfs/ff.h>
|
||||
#include "storage/emummc.h"
|
||||
#include <storage/boot_storage.h>
|
||||
|
||||
#include "frontend/fe_tools.h"
|
||||
#include "frontend/fe_info.h"
|
||||
#include "storage/emusd.h"
|
||||
|
||||
hekate_config h_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.
|
||||
#define RELOC_META_OFF 0x7C
|
||||
#define PATCHED_RELOC_SZ 0x94
|
||||
#define VERSION_RCFG_OFF 0x120
|
||||
#define PATCHED_RELOC_STACK 0x40007000
|
||||
#define PATCHED_RELOC_ENTRY 0x40010000
|
||||
#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;
|
||||
}
|
||||
|
||||
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));
|
||||
|
||||
@@ -120,32 +122,28 @@ bool is_ipl_updated(void *buf, u32 size, const char *path, bool force)
|
||||
|
||||
// Check if newer version.
|
||||
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))
|
||||
return false;
|
||||
}
|
||||
|
||||
// Update if old or broken.
|
||||
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);
|
||||
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.
|
||||
memcpy(&tmp_cfg, (u8 *)(reloc->start + PATCHED_RELOC_SZ), sizeof(boot_cfg_t));
|
||||
memset((u8 *)(reloc->start + PATCHED_RELOC_SZ), 0, sizeof(boot_cfg_t));
|
||||
f_lseek(&fp, PATCHED_RELOC_SZ);
|
||||
f_write(&fp, tmp_cfg, sizeof(boot_cfg_t), NULL);
|
||||
|
||||
sd_save_to_file((u8 *)reloc->start, reloc->end - reloc->start, path);
|
||||
|
||||
// Restore boot storage configuration.
|
||||
memcpy((u8 *)(reloc->start + PATCHED_RELOC_SZ), &tmp_cfg, sizeof(boot_cfg_t));
|
||||
f_close(&fp);
|
||||
free(tmp_cfg);
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -157,10 +155,8 @@ static void _launch_payload(char *path, bool update, bool clear_screen)
|
||||
gfx_clear_grey(0x1B);
|
||||
gfx_con_setpos(0, 0);
|
||||
|
||||
// Read payload.
|
||||
u32 size = 0;
|
||||
void *buf = sd_file_read(path, &size);
|
||||
if (!buf)
|
||||
FIL fp;
|
||||
if (f_open(&fp, path, FA_READ))
|
||||
{
|
||||
gfx_con.mute = false;
|
||||
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;
|
||||
}
|
||||
|
||||
if (update && is_ipl_updated(buf, size, path, false))
|
||||
goto out;
|
||||
// Read and copy the payload to our chosen address
|
||||
void *buf;
|
||||
u32 size = f_size(&fp);
|
||||
|
||||
// Check if it safely fits IRAM.
|
||||
if (size > 0x30000)
|
||||
@@ -180,7 +177,21 @@ static void _launch_payload(char *path, bool update, bool clear_screen)
|
||||
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();
|
||||
emmc_end();
|
||||
|
||||
// Copy the payload to our chosen address.
|
||||
memcpy((void *)RCM_PAYLOAD_ADDR, buf, size);
|
||||
@@ -209,7 +220,6 @@ static void _launch_payload(char *path, bool update, bool clear_screen)
|
||||
(*payload_ptr)();
|
||||
|
||||
out:
|
||||
free(buf);
|
||||
if (!update)
|
||||
{
|
||||
gfx_con.mute = false;
|
||||
@@ -228,15 +238,15 @@ static void _launch_payloads()
|
||||
gfx_clear_grey(0x1B);
|
||||
gfx_con_setpos(0, 0);
|
||||
|
||||
if (!sd_mount())
|
||||
goto failed_sd_mount;
|
||||
if (!boot_storage_mount())
|
||||
goto failed_boot_storage_mount;
|
||||
|
||||
ments = (ment_t *)malloc(sizeof(ment_t) * (max_entries + 3));
|
||||
|
||||
dir = (char *)malloc(256);
|
||||
memcpy(dir, "bootloader/payloads", 20);
|
||||
|
||||
filelist = dirlist(dir, NULL, 0);
|
||||
filelist = dirlist(dir, NULL, false, false);
|
||||
|
||||
u32 i = 0;
|
||||
|
||||
@@ -272,7 +282,7 @@ static void _launch_payloads()
|
||||
free(ments);
|
||||
free(dir);
|
||||
free(filelist);
|
||||
sd_end();
|
||||
boot_storage_end();
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -288,11 +298,11 @@ static void _launch_payloads()
|
||||
_launch_payload(dir, false, true);
|
||||
}
|
||||
|
||||
failed_sd_mount:
|
||||
failed_boot_storage_mount:
|
||||
free(dir);
|
||||
free(ments);
|
||||
free(filelist);
|
||||
sd_end();
|
||||
boot_storage_end();
|
||||
|
||||
btn_wait();
|
||||
}
|
||||
@@ -302,6 +312,7 @@ static void _launch_ini_list()
|
||||
u8 max_entries = 61;
|
||||
char *special_path = NULL;
|
||||
char *emummc_path = NULL;
|
||||
char *emusd_path = NULL;
|
||||
ment_t *ments = NULL;
|
||||
ini_sec_t *cfg_sec = NULL;
|
||||
|
||||
@@ -310,7 +321,7 @@ static void _launch_ini_list()
|
||||
gfx_clear_grey(0x1B);
|
||||
gfx_con_setpos(0, 0);
|
||||
|
||||
if (!sd_mount())
|
||||
if (!boot_storage_mount())
|
||||
goto parse_failed;
|
||||
|
||||
// Check that ini files exist and parse them.
|
||||
@@ -366,13 +377,22 @@ static void _launch_ini_list()
|
||||
h_cfg.emummc_force_disable = atoi(kv->val);
|
||||
else if (!strcmp("emupath", kv->key))
|
||||
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))
|
||||
{
|
||||
EPRINTF("emupath is wrong!");
|
||||
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)
|
||||
@@ -415,9 +435,15 @@ parse_failed:
|
||||
wrong_emupath:
|
||||
if (emummc_path)
|
||||
{
|
||||
sd_mount();
|
||||
boot_storage_mount();
|
||||
emummc_load_cfg(); // Reload emuMMC config in case of emupath.
|
||||
}
|
||||
|
||||
if (emusd_path)
|
||||
{
|
||||
boot_storage_mount();
|
||||
emusd_load_cfg();
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
@@ -431,6 +457,7 @@ static void _launch_config()
|
||||
u8 max_entries = 61;
|
||||
char *special_path = NULL;
|
||||
char *emummc_path = NULL;
|
||||
char *emusd_path = NULL;
|
||||
|
||||
ment_t *ments = NULL;
|
||||
ini_sec_t *cfg_sec = NULL;
|
||||
@@ -440,11 +467,12 @@ static void _launch_config()
|
||||
gfx_clear_grey(0x1B);
|
||||
gfx_con_setpos(0, 0);
|
||||
|
||||
if (!sd_mount())
|
||||
if (!boot_storage_mount())
|
||||
goto parse_failed;
|
||||
|
||||
// Load emuMMC configuration.
|
||||
emummc_load_cfg();
|
||||
emusd_load_cfg();
|
||||
|
||||
// Parse main configuration.
|
||||
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);
|
||||
if (!strcmp("emupath", kv->key))
|
||||
emummc_path = kv->val;
|
||||
if (!strcmp("emusdpath", kv->key))
|
||||
emusd_path = kv->val;
|
||||
}
|
||||
|
||||
if (emummc_path && !emummc_set_path(emummc_path))
|
||||
@@ -518,12 +548,19 @@ static void _launch_config()
|
||||
EPRINTF("emupath is wrong!");
|
||||
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)
|
||||
{
|
||||
free(ments);
|
||||
sd_end();
|
||||
boot_storage_end();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -560,13 +597,19 @@ parse_failed:
|
||||
wrong_emupath:
|
||||
if (emummc_path)
|
||||
{
|
||||
sd_mount();
|
||||
boot_storage_mount();
|
||||
emummc_load_cfg(); // Reload emuMMC config in case of emupath.
|
||||
}
|
||||
|
||||
if (emusd_path)
|
||||
{
|
||||
boot_storage_mount();
|
||||
emusd_load_cfg();
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
sd_end();
|
||||
boot_storage_end();
|
||||
|
||||
free(ments);
|
||||
|
||||
@@ -579,11 +622,13 @@ out:
|
||||
|
||||
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)
|
||||
return;
|
||||
|
||||
boot_storage_end();
|
||||
sd_end();
|
||||
emmc_end();
|
||||
|
||||
render_static_bootlogo();
|
||||
display_backlight_brightness(h_cfg.backlight, 1000);
|
||||
@@ -652,13 +697,7 @@ static void _nyx_load_run()
|
||||
(*nyx_ptr)();
|
||||
}
|
||||
|
||||
void launch_nyx()
|
||||
{
|
||||
sd_mount();
|
||||
_nyx_load_run();
|
||||
}
|
||||
|
||||
static ini_sec_t *_get_ini_sec_from_id(ini_sec_t *ini_sec, char **bootlogoCustomEntry, char **emummc_path)
|
||||
static ini_sec_t *_get_ini_sec_from_id(ini_sec_t *ini_sec, char **bootlogoCustomEntry, char **emummc_path, char **emusd_path)
|
||||
{
|
||||
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;
|
||||
else if (!strcmp("emummc_force_disable", kv->key))
|
||||
h_cfg.emummc_force_disable = atoi(kv->val);
|
||||
else if (!strcmp("emusdpath", kv->key))
|
||||
*emusd_path = kv->val;
|
||||
}
|
||||
if (!cfg_sec)
|
||||
{
|
||||
*emummc_path = NULL;
|
||||
*emusd_path = NULL;
|
||||
*bootlogoCustomEntry = NULL;
|
||||
h_cfg.emummc_force_disable = false;
|
||||
}
|
||||
@@ -713,7 +755,7 @@ static void _check_for_updated_bootloader()
|
||||
else
|
||||
{
|
||||
u8 *buf = zalloc(0x200);
|
||||
is_ipl_updated(buf, 0, "bootloader/update.bin", true);
|
||||
is_ipl_updated(buf, "bootloader/update.bin", true);
|
||||
free(buf);
|
||||
}
|
||||
}
|
||||
@@ -735,9 +777,12 @@ static void _auto_launch()
|
||||
u32 boot_entry_id = 0;
|
||||
ini_sec_t *cfg_sec = NULL;
|
||||
char *emummc_path = NULL;
|
||||
char *emusd_path = NULL;
|
||||
char *bootlogoCustomEntry = NULL;
|
||||
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);
|
||||
if (boot_from_id)
|
||||
b_cfg.id[7] = 0;
|
||||
@@ -750,6 +795,7 @@ static void _auto_launch()
|
||||
|
||||
// Load emuMMC configuration.
|
||||
emummc_load_cfg();
|
||||
emusd_load_cfg();
|
||||
|
||||
// Parse hekate main configuration.
|
||||
if (!ini_parse(&ini_sections, "bootloader/hekate_ipl.ini", false))
|
||||
@@ -805,7 +851,7 @@ static void _auto_launch()
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
cfg_sec = ini_sec;
|
||||
@@ -815,6 +861,8 @@ static void _auto_launch()
|
||||
bootlogoCustomEntry = kv->val;
|
||||
else if (!strcmp("emupath", kv->key))
|
||||
emummc_path = kv->val;
|
||||
else if (!strcmp("emusdpath", kv->key))
|
||||
emusd_path = kv->val;
|
||||
else if (!strcmp("emummc_force_disable", kv->key))
|
||||
h_cfg.emummc_force_disable = atoi(kv->val);
|
||||
else if (!strcmp("bootwait", kv->key))
|
||||
@@ -851,7 +899,7 @@ static void _auto_launch()
|
||||
continue;
|
||||
|
||||
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)
|
||||
{
|
||||
h_cfg.emummc_force_disable = false;
|
||||
@@ -862,6 +910,8 @@ static void _auto_launch()
|
||||
bootlogoCustomEntry = kv->val;
|
||||
else if (!strcmp("emupath", kv->key))
|
||||
emummc_path = kv->val;
|
||||
else if (!strcmp("emusdpath", kv->key))
|
||||
emusd_path = kv->val;
|
||||
else if (!strcmp("emummc_force_disable", kv->key))
|
||||
h_cfg.emummc_force_disable = atoi(kv->val);
|
||||
else if (!strcmp("bootwait", kv->key))
|
||||
@@ -892,11 +942,11 @@ skip_list:
|
||||
|
||||
// Check if user set custom logo path at the boot entry.
|
||||
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.
|
||||
if (!bitmap)
|
||||
bitmap = (u8 *)sd_file_read("bootloader/bootlogo.bmp", &fsize);
|
||||
bitmap = (u8 *)boot_storage_file_read("bootloader/bootlogo.bmp", &fsize);
|
||||
|
||||
if (bitmap)
|
||||
{
|
||||
@@ -975,6 +1025,7 @@ skip_list:
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: add boot_cfg for emusd
|
||||
if (b_cfg.boot_cfg & BOOT_CFG_TO_EMUMMC)
|
||||
emummc_set_path(b_cfg.emummc_path);
|
||||
else if (emummc_path && !emummc_set_path(emummc_path))
|
||||
@@ -984,15 +1035,29 @@ skip_list:
|
||||
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);
|
||||
|
||||
wrong_emupath:
|
||||
if (emummc_path || b_cfg.boot_cfg & BOOT_CFG_TO_EMUMMC)
|
||||
{
|
||||
sd_mount();
|
||||
boot_storage_mount();
|
||||
emummc_load_cfg(); // Reload emuMMC config in case of emupath.
|
||||
}
|
||||
|
||||
if (emusd_path)
|
||||
{
|
||||
boot_storage_mount();
|
||||
emusd_load_cfg();
|
||||
}
|
||||
|
||||
error:
|
||||
gfx_con.mute = false;
|
||||
gfx_printf("\nPress any key...\n");
|
||||
@@ -1157,7 +1222,7 @@ static void _show_errors()
|
||||
|
||||
static void _check_low_battery()
|
||||
{
|
||||
if (h_cfg.devmode)
|
||||
if (fuse_read_hw_state() == FUSE_NX_HW_STATE_DEV)
|
||||
goto out;
|
||||
|
||||
int enough_battery;
|
||||
@@ -1417,7 +1482,6 @@ ment_t ment_top[] = {
|
||||
MDEF_MENU("Console info", &menu_cinfo),
|
||||
MDEF_CAPTION("---------------", TXT_CLR_GREY_DM),
|
||||
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 (RCM)", &STATE_REBOOT_RCM, 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);
|
||||
#endif
|
||||
|
||||
// Set bootloader's default configuration.
|
||||
set_default_configuration();
|
||||
|
||||
// Check if battery is enough.
|
||||
_check_low_battery();
|
||||
|
||||
// Set bootloader's default configuration.
|
||||
set_default_configuration();
|
||||
|
||||
// Prep RTC regs for read. Needed for T210B01 R2C.
|
||||
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);
|
||||
|
||||
// Mount SD Card.
|
||||
h_cfg.errors |= !sd_mount() ? ERR_SD_BOOT_EN : 0;
|
||||
// TODO: boot storage may not be sd card -> set proper error
|
||||
h_cfg.errors |= !boot_storage_mount() ? ERR_SD_BOOT_EN : 0;
|
||||
|
||||
// Check if watchdog was fired previously.
|
||||
if (watchdog_fired())
|
||||
@@ -1506,13 +1571,10 @@ skip_lp0_minerva_config:
|
||||
|
||||
// Load saved configuration and auto boot if enabled.
|
||||
if (!(h_cfg.errors & ERR_SD_BOOT_EN))
|
||||
{
|
||||
_check_for_updated_bootloader();
|
||||
_auto_launch();
|
||||
}
|
||||
|
||||
// Failed to launch Nyx, unmount SD Card.
|
||||
sd_end();
|
||||
boot_storage_end();
|
||||
|
||||
// Set ram to a freq that doesn't need periodic training.
|
||||
minerva_change_freq(FREQ_800);
|
||||
|
||||
@@ -14,6 +14,9 @@
|
||||
* 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 <stdlib.h>
|
||||
|
||||
@@ -22,6 +25,7 @@
|
||||
#include "emummc.h"
|
||||
#include "../config.h"
|
||||
#include <libs/fatfs/ff.h>
|
||||
#include <storage/emummc_file_based.h>
|
||||
|
||||
emummc_cfg_t emu_cfg = { 0 };
|
||||
|
||||
@@ -76,33 +80,68 @@ bool emummc_set_path(char *path)
|
||||
FIL fp;
|
||||
bool found = false;
|
||||
|
||||
strcpy(emu_cfg.emummc_file_based_path, path);
|
||||
// strcpy(emu_cfg.emummc_file_based_path, "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");
|
||||
|
||||
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)
|
||||
if (!f_read(&fp, &emu_cfg.sector, 4, NULL)){
|
||||
if (emu_cfg.sector){
|
||||
found = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
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;
|
||||
emu_cfg.enabled = 1;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
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.
|
||||
u32 id_from_path = 0;
|
||||
u32 path_size = strlen(path);
|
||||
@@ -133,7 +172,7 @@ static int emummc_raw_get_part_off(int part_idx)
|
||||
|
||||
int emummc_storage_init_mmc()
|
||||
{
|
||||
FILINFO fno;
|
||||
// FILINFO fno;
|
||||
emu_cfg.active_part = 0;
|
||||
|
||||
// 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)
|
||||
return 0;
|
||||
|
||||
if (!sd_mount())
|
||||
goto out;
|
||||
bool file_based = false;
|
||||
|
||||
if (!emu_cfg.sector)
|
||||
{
|
||||
strcpy(emu_cfg.emummc_file_based_path, emu_cfg.path);
|
||||
strcat(emu_cfg.emummc_file_based_path, "/eMMC");
|
||||
|
||||
if (f_stat(emu_cfg.emummc_file_based_path, &fno))
|
||||
{
|
||||
EPRINTF("Failed to open eMMC folder.");
|
||||
goto out;
|
||||
if(emu_cfg.enabled == 4){
|
||||
// emmc based
|
||||
if(!emu_cfg.sector){
|
||||
// file based
|
||||
if(!emmc_mount()){
|
||||
gfx_printf("emmc mount fail\n");
|
||||
return 1;
|
||||
}
|
||||
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);
|
||||
|
||||
strcat(emu_cfg.emummc_file_based_path, "/00");
|
||||
if (f_stat(emu_cfg.emummc_file_based_path, &fno))
|
||||
{
|
||||
EPRINTF("Failed to open emuMMC rawnand.");
|
||||
goto out;
|
||||
}else{
|
||||
// sd based
|
||||
if(!emu_cfg.sector){
|
||||
// file based
|
||||
if(!sd_mount()){
|
||||
return 1;
|
||||
}
|
||||
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;
|
||||
|
||||
out:
|
||||
return 1;
|
||||
}
|
||||
|
||||
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();
|
||||
else
|
||||
}else{
|
||||
sd_end();
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
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)
|
||||
return sdmmc_storage_read(&emmc_storage, sector, num_sectors, buf);
|
||||
else if (emu_cfg.sector)
|
||||
{
|
||||
sector += emu_cfg.sector;
|
||||
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
|
||||
{
|
||||
if (!emu_cfg.active_part)
|
||||
{
|
||||
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 emummc_storage_file_based_read(sector, num_sectors, buf);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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)
|
||||
return sdmmc_storage_write(&emmc_storage, sector, num_sectors, buf);
|
||||
else if (emu_cfg.sector)
|
||||
{
|
||||
sector += emu_cfg.sector;
|
||||
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
|
||||
{
|
||||
if (!emu_cfg.active_part)
|
||||
{
|
||||
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;
|
||||
return emummc_storage_file_based_write(sector, num_sectors, buf);
|
||||
}
|
||||
}
|
||||
|
||||
int emummc_storage_set_mmc_partition(u32 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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
sdmmc_storage_t *emummc_get_storage(){
|
||||
return emu_cfg.enabled == 4 ? &emmc_storage : &sd_storage;
|
||||
}
|
||||
|
||||
@@ -19,19 +19,6 @@
|
||||
|
||||
#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
|
||||
{
|
||||
int enabled;
|
||||
@@ -55,5 +42,6 @@ int emummc_storage_end();
|
||||
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_set_mmc_partition(u32 partition);
|
||||
sdmmc_storage_t *emummc_get_storage();
|
||||
|
||||
#endif
|
||||
295
bootloader/storage/emusd.c
Normal file
295
bootloader/storage/emusd.c
Normal 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);
|
||||
}
|
||||
}
|
||||
49
bootloader/storage/emusd.h
Normal file
49
bootloader/storage/emusd.h
Normal 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
|
||||
@@ -13,14 +13,14 @@ include ../Versions.inc
|
||||
################################################################################
|
||||
|
||||
TARGET := loader
|
||||
BUILDDIR := ../build/$(TARGET)
|
||||
BUILDDIR := ../build
|
||||
OUTPUTDIR := ../output
|
||||
BDKDIR := bdk
|
||||
BDKINC := -I../$(BDKDIR)
|
||||
VPATH += $(dir $(wildcard ../$(BDKDIR)/*/)) $(dir $(wildcard ../$(BDKDIR)/*/*/))
|
||||
|
||||
# Main and graphics.
|
||||
OBJS = $(addprefix $(BUILDDIR)/, \
|
||||
OBJS = $(addprefix $(BUILDDIR)/$(TARGET)/, \
|
||||
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)
|
||||
|
||||
clean:
|
||||
@rm -f payload_00.h
|
||||
@rm -f payload_01.h
|
||||
@rm -rf $(OBJS)
|
||||
|
||||
$(TARGET).bin: $(BUILDDIR)/$(TARGET).elf
|
||||
$(TARGET).bin: $(BUILDDIR)/$(TARGET)/$(TARGET).elf
|
||||
@$(OBJCOPY) -S -O binary $< $(OUTPUTDIR)/$(PAYLOAD_NAME).bin
|
||||
|
||||
$(BUILDDIR)/$(TARGET).elf: $(OBJS)
|
||||
$(BUILDDIR)/$(TARGET)/$(TARGET).elf: $(OBJS)
|
||||
@$(CC) $(LDFLAGS) -T link.ld $^ -o $@
|
||||
|
||||
$(BUILDDIR)/%.o: %.c
|
||||
$(BUILDDIR)/$(TARGET)/%.o: %.c
|
||||
@$(CC) $(CFLAGS) $(BDKINC) -c $< -o $@
|
||||
|
||||
$(BUILDDIR)/%.o: %.S
|
||||
$(BUILDDIR)/$(TARGET)/%.o: %.S
|
||||
@$(CC) $(CFLAGS) -c $< -o $@
|
||||
|
||||
$(OBJS): $(BUILDDIR)
|
||||
$(OBJS): $(BUILDDIR)/$(TARGET)
|
||||
|
||||
$(BUILDDIR):
|
||||
$(BUILDDIR)/$(TARGET):
|
||||
@mkdir -p "$(BUILDDIR)"
|
||||
@mkdir -p "$(BUILDDIR)/$(TARGET)"
|
||||
@mkdir -p "$(OUTPUTDIR)"
|
||||
|
||||
@@ -5,16 +5,12 @@ endif
|
||||
include $(DEVKITARM)/base_rules
|
||||
|
||||
TARGET := libsys_lp0
|
||||
BUILDDIR := ../../build/$(TARGET)
|
||||
OUTPUTDIR := ../../output
|
||||
BUILD := ../../build/$(TARGET)
|
||||
OUTPUT := ../../output
|
||||
BDKDIR := bdk
|
||||
BDKINC := -I../../$(BDKDIR)
|
||||
|
||||
# Track compiler flags
|
||||
TRACK_CFLAGS = $(BUILDDIR)/.cflags
|
||||
TRACK_LDFLAGS = $(BUILDDIR)/.ldflags
|
||||
|
||||
OBJS = $(addprefix $(BUILDDIR)/,\
|
||||
OBJS = $(addprefix $(BUILD)/,\
|
||||
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)
|
||||
LDFLAGS = $(ARCH) -fpie -pie -nostartfiles -lgcc
|
||||
|
||||
.PHONY: all
|
||||
.PHONY: clean all
|
||||
|
||||
all: $(TARGET).bso
|
||||
$(BUILDDIR)/%.o: ./%.c $(TRACK_CFLAGS)
|
||||
@$(CC) $(CFLAGS) $(BDKINC) -MMD -MP -c $< -o $@
|
||||
$(BUILD)/%.o: ./%.c
|
||||
@mkdir -p "$(BUILD)"
|
||||
@$(CC) $(CFLAGS) $(BDKINC) -c $< -o $@
|
||||
|
||||
$(TARGET).bso: $(OBJS) $(TRACK_LDFLAGS)
|
||||
@$(CC) $(LDFLAGS) -e sdram_lp0_entry $(OBJS) -o $(OUTPUTDIR)/$(TARGET).bso
|
||||
@$(STRIP) -g $(OUTPUTDIR)/$(TARGET).bso
|
||||
@echo "Built module: "$(TARGET)".bso"
|
||||
$(TARGET).bso: $(OBJS)
|
||||
@$(CC) $(LDFLAGS) -e sdram_lp0_entry $^ -o $(OUTPUT)/$(TARGET).bso
|
||||
@$(STRIP) -g $(OUTPUT)/$(TARGET).bso
|
||||
@echo -e "-------------\nBuilt module: "$(TARGET)".bso\n-------------"
|
||||
|
||||
$(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)
|
||||
clean:
|
||||
@rm -rf $(OUTPUT)/$(TARGET).bso
|
||||
|
||||
@@ -5,16 +5,12 @@ endif
|
||||
include $(DEVKITARM)/base_rules
|
||||
|
||||
TARGET := libsys_minerva
|
||||
BUILDDIR := ../../build/$(TARGET)
|
||||
OUTPUTDIR := ../../output
|
||||
BUILD := ../../build/$(TARGET)
|
||||
OUTPUT := ../../output
|
||||
BDKDIR := bdk
|
||||
BDKINC := -I../../$(BDKDIR)
|
||||
|
||||
# Track compiler flags
|
||||
TRACK_CFLAGS = $(BUILDDIR)/.cflags
|
||||
TRACK_LDFLAGS = $(BUILDDIR)/.ldflags
|
||||
|
||||
OBJS = $(addprefix $(BUILDDIR)/,\
|
||||
OBJS = $(addprefix $(BUILD)/,\
|
||||
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)
|
||||
LDFLAGS = $(ARCH) -fpie -pie -nostartfiles -lgcc
|
||||
|
||||
.PHONY: all
|
||||
.PHONY: clean all
|
||||
|
||||
all: $(TARGET).bso
|
||||
$(BUILDDIR)/%.o: ./%.c $(TRACK_CFLAGS)
|
||||
@$(CC) $(CFLAGS) $(BDKINC) -MMD -MP -c $< -o $@
|
||||
$(BUILD)/%.o: ./%.c
|
||||
@mkdir -p "$(BUILD)"
|
||||
@$(CC) $(CFLAGS) $(BDKINC) -c $< -o $@
|
||||
|
||||
$(TARGET).bso: $(OBJS) $(TRACK_LDFLAGS)
|
||||
@$(CC) $(LDFLAGS) -e minerva_entry $(OBJS) -o $(OUTPUTDIR)/$(TARGET).bso
|
||||
@$(STRIP) -g $(OUTPUTDIR)/$(TARGET).bso
|
||||
@echo "Built module: "$(TARGET)".bso"
|
||||
$(TARGET).bso: $(OBJS)
|
||||
@$(CC) $(LDFLAGS) -e minerva_entry $^ -o $(OUTPUT)/$(TARGET).bso
|
||||
@$(STRIP) -g $(OUTPUT)/$(TARGET).bso
|
||||
@echo -e "-------------\nBuilt module: "$(TARGET)".bso\n-------------"
|
||||
|
||||
$(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)
|
||||
clean:
|
||||
@rm -rf $(OUTPUT)/$(TARGET).bso
|
||||
|
||||
@@ -5,18 +5,14 @@ endif
|
||||
include $(DEVKITARM)/base_rules
|
||||
|
||||
TARGET := module_sample
|
||||
BUILDDIR := ../../build/$(TARGET)
|
||||
OUTPUTDIR := ../../output
|
||||
BUILD := ../../build/$(TARGET)
|
||||
OUTPUT := ../../output
|
||||
SOURCEDIR = simple_sample
|
||||
BDKDIR := bdk
|
||||
BDKINC := -I../../$(BDKDIR)
|
||||
VPATH = $(dir ./) $(dir $(wildcard ./*/))
|
||||
|
||||
# Track compiler flags
|
||||
TRACK_CFLAGS = $(BUILDDIR)/.cflags
|
||||
TRACK_LDFLAGS = $(BUILDDIR)/.ldflags
|
||||
|
||||
OBJS = $(addprefix $(BUILDDIR)/,\
|
||||
OBJS = $(addprefix $(BUILD)/,\
|
||||
module_sample.o \
|
||||
gfx.o \
|
||||
)
|
||||
@@ -26,30 +22,20 @@ GFX_INC := '"../modules/$(SOURCEDIR)/gfx/gfx.h"'
|
||||
CUSTOMDEFINES := -DGFX_INC=$(GFX_INC)
|
||||
|
||||
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
|
||||
|
||||
.PHONY: clean all
|
||||
|
||||
all: $(TARGET).bso
|
||||
$(BUILDDIR)/%.o: ./%.c $(TRACK_CFLAGS)
|
||||
@$(CC) $(CFLAGS) $(BDKINC) -MMD -MP -c $< -o $@
|
||||
$(BUILD)/%.o: ./%.c
|
||||
@mkdir -p "$(BUILD)"
|
||||
@$(CC) $(CFLAGS) $(BDKINC) -c $< -o $@
|
||||
|
||||
$(TARGET).bso: $(OBJS) $(TRACK_LDFLAGS)
|
||||
@$(CC) $(LDFLAGS) -e mod_entry $(OBJS) -o $(OUTPUTDIR)/$(TARGET).bso
|
||||
@$(STRIP) -g $(OUTPUTDIR)/$(TARGET).bso
|
||||
@echo "Built module: "$(TARGET)".bso"
|
||||
$(TARGET).bso: $(OBJS)
|
||||
@$(CC) $(LDFLAGS) -e _modInit $^ -o $(OUTPUT)/$(TARGET).bso
|
||||
@$(STRIP) -g $(OUTPUT)/$(TARGET).bso
|
||||
@echo -e "-------------\nBuilt module: "$(TARGET)".bso\n-------------"
|
||||
|
||||
clean:
|
||||
@rm -rf $(BUILDDIR)/$(TARGET)
|
||||
@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)
|
||||
@rm -rf $(OUTPUT)/$(TARGET).bso
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
#include <module.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_ctxt, bp->gfxCtx, sizeof(gfx_ctxt_t));
|
||||
|
||||
114
nyx/Makefile
114
nyx/Makefile
@@ -13,7 +13,7 @@ include ./../Versions.inc
|
||||
################################################################################
|
||||
|
||||
TARGET := nyx
|
||||
BUILDDIR := ./../build/$(TARGET)
|
||||
BUILDDIR := ./../build
|
||||
OUTPUTDIR := ./../output
|
||||
SOURCEDIR = nyx_gui
|
||||
BDKDIR := bdk
|
||||
@@ -22,47 +22,54 @@ 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)/*/*/*/))
|
||||
|
||||
# Track compiler flags
|
||||
TRACK_CFLAGS = $(BUILDDIR)/.cflags
|
||||
TRACK_LDFLAGS = $(BUILDDIR)/.ldflags
|
||||
|
||||
# Main and graphics.
|
||||
OBJS = start exception_handlers nyx heap gfx \
|
||||
gui gui_info gui_tools gui_options gui_emmc_tools gui_emummc_tools gui_tools_partition_manager \
|
||||
fe_emummc_tools fe_emmc_tools
|
||||
OBJS = $(addprefix $(BUILDDIR)/$(TARGET)/, \
|
||||
start.o exception_handlers.o \
|
||||
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.
|
||||
OBJS += actmon bpmp ccplex clock di vic i2c irq timer \
|
||||
gpio pinmux pmc se smmu tsec uart \
|
||||
fuse kfuse \
|
||||
mc sdram minerva ramdisk \
|
||||
sdmmc sdmmc_driver emmc sd nx_emmc_bis \
|
||||
bm92t36 bq24193 max17050 max7762x max77620-rtc regulator_5v \
|
||||
touch joycon tmp451 fan \
|
||||
usbd xusbd usb_descriptors usb_gadget_ums usb_gadget_hid \
|
||||
hw_init
|
||||
OBJS += $(addprefix $(BUILDDIR)/$(TARGET)/, \
|
||||
bpmp.o ccplex.o clock.o di.o vic.o i2c.o irq.o timer.o \
|
||||
gpio.o pinmux.o pmc.o se.o smmu.o tsec.o uart.o \
|
||||
fuse.o kfuse.o \
|
||||
mc.o sdram.o minerva.o ramdisk.o \
|
||||
sdmmc.o sdmmc_driver.o emmc.o sd.o nx_emmc_bis.o \
|
||||
bm92t36.o bq24193.o max17050.o max7762x.o max77620-rtc.o regulator_5v.o \
|
||||
touch.o joycon.o tmp451.o fan.o \
|
||||
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.
|
||||
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.
|
||||
OBJS += hos pkg1 pkg2
|
||||
OBJS += $(addprefix $(BUILDDIR)/$(TARGET)/, \
|
||||
hos.o pkg1.o pkg2.o \
|
||||
)
|
||||
|
||||
# Libraries.
|
||||
OBJS += diskio ff ffunicode ffsystem \
|
||||
elfload elfreloc_arm blz \
|
||||
lv_group lv_indev lv_obj lv_refr lv_style lv_vdb \
|
||||
lv_draw lv_draw_rbasic lv_draw_vbasic lv_draw_arc lv_draw_img \
|
||||
lv_draw_label lv_draw_line lv_draw_rect lv_draw_triangle \
|
||||
lv_hal_disp lv_hal_indev lv_hal_tick \
|
||||
interui_20 interui_30 ubuntu_mono hekate_symbol_20 hekate_symbol_30 hekate_symbol_120 lv_font_builtin \
|
||||
lv_anim lv_area lv_circ lv_color lv_font lv_ll lv_math lv_mem lv_task lv_txt lv_gc \
|
||||
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_page lv_roller lv_slider lv_sw lv_tabview lv_ta lv_win lv_log lv_imgbtn \
|
||||
lv_theme lv_theme_hekate
|
||||
|
||||
OBJS := $(addsuffix .o, $(OBJS))
|
||||
OBJS := $(addprefix $(BUILDDIR)/, $(OBJS))
|
||||
OBJS += $(addprefix $(BUILDDIR)/$(TARGET)/, \
|
||||
diskio.o ff.o ffunicode.o ffsystem.o \
|
||||
elfload.o elfreloc_arm.o blz.o \
|
||||
lv_group.o lv_indev.o lv_obj.o lv_refr.o lv_style.o lv_vdb.o \
|
||||
lv_draw.o lv_draw_rbasic.o lv_draw_vbasic.o lv_draw_arc.o lv_draw_img.o \
|
||||
lv_draw_label.o lv_draw_line.o lv_draw_rect.o lv_draw_triangle.o \
|
||||
lv_hal_disp.o lv_hal_indev.o lv_hal_tick.o \
|
||||
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_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_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_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 \
|
||||
)
|
||||
|
||||
GFX_INC := '"../nyx/$(SOURCEDIR)/gfx/gfx.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)
|
||||
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
|
||||
@@ -118,29 +117,24 @@ clean:
|
||||
@rm -rf $(BUILDDIR)
|
||||
@rm -rf $(OUTPUTDIR)
|
||||
|
||||
$(TARGET).bin: $(BUILDDIR)/$(TARGET).elf
|
||||
$(TARGET).bin: $(BUILDDIR)/$(TARGET)/$(TARGET).elf
|
||||
@$(OBJCOPY) -S -O binary $< $(OUTPUTDIR)/$@
|
||||
|
||||
$(BUILDDIR)/$(TARGET).elf: $(OBJS) $(TRACK_LDFLAGS)
|
||||
@echo -ne "\r[100%] Linking $(TARGET).elf\033[K"
|
||||
@$(CC) $(LDFLAGS) -T $(SOURCEDIR)/link.ld $(OBJS) -o $@
|
||||
@printf "\n$(TARGET) was built with the following flags:\nCFLAGS: $(CFLAGS)\nLDFLAGS: $(LDFLAGS)\n"
|
||||
$(BUILDDIR)/$(TARGET)/$(TARGET).elf: $(OBJS)
|
||||
@$(CC) $(LDFLAGS) -T $(SOURCEDIR)/link.ld $^ -o $@
|
||||
@printf "$(TARGET) was built with the following flags:\nCFLAGS: $(CFLAGS)\nLDFLAGS: $(LDFLAGS)\n"
|
||||
|
||||
$(BUILDDIR)/%.o: %.c $(TRACK_CFLAGS) | $(BUILDDIR)
|
||||
@$(NYXECHO) Building $@
|
||||
@$(CC) $(CFLAGS) $(BDKINC) -MMD -MP -c $< -o $@
|
||||
$(BUILDDIR)/$(TARGET)/%.o: %.c
|
||||
@echo Building $@
|
||||
@$(CC) $(CFLAGS) $(BDKINC) -c $< -o $@
|
||||
|
||||
$(BUILDDIR)/%.o: %.S $(TRACK_CFLAGS) | $(BUILDDIR)
|
||||
@$(NYXECHO) Building $@
|
||||
@$(CC) $(CFLAGS) -MMD -MP -c $< -o $@
|
||||
$(BUILDDIR)/$(TARGET)/%.o: %.S
|
||||
@echo Building $@
|
||||
@$(CC) $(CFLAGS) -c $< -o $@
|
||||
|
||||
$(BUILDDIR):
|
||||
$(OBJS): $(BUILDDIR)/$(TARGET)
|
||||
|
||||
$(BUILDDIR)/$(TARGET):
|
||||
@mkdir -p "$(BUILDDIR)"
|
||||
@mkdir -p "$(BUILDDIR)/$(TARGET)"
|
||||
@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)
|
||||
|
||||
@@ -21,11 +21,11 @@
|
||||
|
||||
#include "config.h"
|
||||
#include <libs/fatfs/ff.h>
|
||||
#include <storage/boot_storage.h>
|
||||
|
||||
void set_default_configuration()
|
||||
{
|
||||
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_list = 0;
|
||||
@@ -186,9 +186,9 @@ int create_config_entry()
|
||||
|
||||
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;
|
||||
|
||||
char lbuf[64];
|
||||
@@ -250,7 +250,7 @@ int create_nyx_config_entry(bool force_unmount)
|
||||
f_close(&fp);
|
||||
|
||||
if (force_unmount || !sd_mounted)
|
||||
sd_unmount();
|
||||
boot_storage_unmount();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -35,7 +35,6 @@ typedef struct _hekate_config
|
||||
u32 bootprotect;
|
||||
// Global temporary config.
|
||||
bool t210b01;
|
||||
bool devmode;
|
||||
bool emummc_force_disable;
|
||||
bool rcm_patched;
|
||||
bool autorcm_enabled;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* 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
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
@@ -18,6 +18,7 @@
|
||||
|
||||
//! fix the dram stuff and the pop ups
|
||||
|
||||
#include <storage/boot_storage.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
@@ -29,10 +30,6 @@
|
||||
#include "../config.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 OUT_FILENAME_SZ 128
|
||||
#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);
|
||||
}
|
||||
|
||||
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 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);
|
||||
manual_system_maintenance(true);
|
||||
|
||||
return VERIF_STATUS_ERROR;
|
||||
return 1;
|
||||
}
|
||||
|
||||
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)
|
||||
f_close(&hashFp);
|
||||
|
||||
return VERIF_STATUS_ERROR;
|
||||
return 1;
|
||||
}
|
||||
manual_system_maintenance(false);
|
||||
|
||||
se_sha_hash_256_async(hashEm, bufEm, num << 9);
|
||||
se_calc_sha256(hashEm, NULL, bufEm, num << 9, 0, SHA_INIT_HASH, false);
|
||||
|
||||
f_lseek(&fp, (u64)sdFileSector << (u64)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)
|
||||
f_close(&hashFp);
|
||||
|
||||
return VERIF_STATUS_ERROR;
|
||||
return 1;
|
||||
}
|
||||
manual_system_maintenance(false);
|
||||
se_sha_hash_256_finalize(hashEm);
|
||||
se_sha_hash_256_oneshot(hashSd, bufSd, num << 9);
|
||||
se_calc_sha256_finalize(hashEm, NULL);
|
||||
se_calc_sha256_oneshot(hashSd, bufSd, num << 9);
|
||||
res = memcmp(hashEm, hashSd, SE_SHA_256_SIZE / 2);
|
||||
|
||||
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)
|
||||
f_close(&hashFp);
|
||||
|
||||
return VERIF_STATUS_ERROR;
|
||||
return 1;
|
||||
}
|
||||
|
||||
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.
|
||||
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);
|
||||
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(&hashFp);
|
||||
|
||||
return VERIF_STATUS_ABORT;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
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);
|
||||
manual_system_maintenance(true);
|
||||
|
||||
return VERIF_STATUS_OK;
|
||||
return 0;
|
||||
}
|
||||
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);
|
||||
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;
|
||||
|
||||
u32 verification = n_cfg.verification;
|
||||
u32 multipartSplitSize = (1u << 31);
|
||||
u32 lba_end = part->lba_end;
|
||||
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(§or_start, §or_size, &part_idx, true);
|
||||
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);
|
||||
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_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);
|
||||
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;
|
||||
|
||||
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);
|
||||
manual_system_maintenance(true);
|
||||
|
||||
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);
|
||||
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.
|
||||
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);
|
||||
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)
|
||||
{
|
||||
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);
|
||||
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));
|
||||
currPartIdx++;
|
||||
|
||||
if (verification && !gui->raw_emummc)
|
||||
if (n_cfg.verification && !gui->raw_emummc)
|
||||
{
|
||||
// Verify part.
|
||||
res = _emmc_sd_copy_verify(gui, storage, lbaStartPart, outFilename, part);
|
||||
switch (res)
|
||||
if (_dump_emmc_verify(gui, storage, lbaStartPart, outFilename, part))
|
||||
{
|
||||
case VERIF_STATUS_OK:
|
||||
break;
|
||||
case VERIF_STATUS_ERROR:
|
||||
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);
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -576,7 +564,7 @@ static int _dump_emmc_part(emmc_tool_gui_t *gui, char *sd_path, int active_part,
|
||||
}
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
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
|
||||
{
|
||||
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);
|
||||
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);
|
||||
lv_label_set_text(gui->label_pct, gui->txt_buf);
|
||||
manual_system_maintenance(true);
|
||||
|
||||
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.
|
||||
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);
|
||||
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);
|
||||
free(clmt);
|
||||
|
||||
if (verification && !gui->raw_emummc)
|
||||
if (n_cfg.verification && !gui->raw_emummc)
|
||||
{
|
||||
// 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);
|
||||
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...");
|
||||
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;
|
||||
}
|
||||
|
||||
// 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))
|
||||
{
|
||||
@@ -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);
|
||||
|
||||
if (!res)
|
||||
strcpy(txt_buf, "#FFDD00 Failed!#\n");
|
||||
s_printf(txt_buf, "#FFDD00 Failed!#\n");
|
||||
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);
|
||||
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 (!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);
|
||||
break;
|
||||
}
|
||||
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);
|
||||
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);
|
||||
|
||||
if (!res)
|
||||
strcpy(txt_buf, "#FFDD00 Failed!#\n");
|
||||
s_printf(txt_buf, "#FFDD00 Failed!#\n");
|
||||
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);
|
||||
manual_system_maintenance(true);
|
||||
@@ -954,11 +945,11 @@ out:
|
||||
free(txt_buf);
|
||||
free(gui->base_path);
|
||||
if (!partial_sd_full_unmount)
|
||||
sd_unmount();
|
||||
boot_storage_unmount();
|
||||
else
|
||||
{
|
||||
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;
|
||||
|
||||
u32 verification = n_cfg.verification;
|
||||
u32 lba_end = part->lba_end;
|
||||
u32 totalSectors = part->lba_end - part->lba_start + 1;
|
||||
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_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_INDIC, gui->bar_orange_ind);
|
||||
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);
|
||||
manual_system_maintenance(true);
|
||||
|
||||
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 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);
|
||||
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)
|
||||
{
|
||||
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);
|
||||
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.
|
||||
totalSectors = (u32)((u64)totalCheckFileSize >> (u64)9);
|
||||
part->lba_end = totalSectors + part->lba_start - 1;
|
||||
lba_end = part->lba_end;
|
||||
lba_end = totalSectors + part->lba_start - 1;
|
||||
}
|
||||
|
||||
// Restore folder is empty.
|
||||
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);
|
||||
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))
|
||||
{
|
||||
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);
|
||||
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))
|
||||
{
|
||||
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);
|
||||
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.
|
||||
totalSectors = (u32)((u64)totalCheckFileSize >> (u64)9);
|
||||
part->lba_end = totalSectors + part->lba_start - 1;
|
||||
lba_end = part->lba_end;
|
||||
lba_end = totalSectors + part->lba_start - 1;
|
||||
}
|
||||
use_multipart = true;
|
||||
_update_filename(outFilename, sdPathLen, 0);
|
||||
@@ -1149,7 +1137,7 @@ multipart_not_allowed:
|
||||
{
|
||||
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);
|
||||
manual_system_maintenance(true);
|
||||
|
||||
@@ -1168,7 +1156,7 @@ multipart_not_allowed:
|
||||
if (!(btn_wait() & BTN_POWER))
|
||||
{
|
||||
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);
|
||||
manual_system_maintenance(true);
|
||||
|
||||
@@ -1212,7 +1200,7 @@ multipart_not_allowed:
|
||||
_get_valid_partition(§or_start, §or_size, &part_idx, false);
|
||||
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);
|
||||
manual_system_maintenance(true);
|
||||
|
||||
@@ -1234,25 +1222,17 @@ multipart_not_allowed:
|
||||
memset(&fp, 0, sizeof(fp));
|
||||
currPartIdx++;
|
||||
|
||||
if (verification && !gui->raw_emummc)
|
||||
if (n_cfg.verification && !gui->raw_emummc)
|
||||
{
|
||||
// Verify part.
|
||||
res = _emmc_sd_copy_verify(gui, storage, lbaStartPart, outFilename, part);
|
||||
switch (res)
|
||||
if (_dump_emmc_verify(gui, storage, lbaStartPart, outFilename, part))
|
||||
{
|
||||
case VERIF_STATUS_OK:
|
||||
break;
|
||||
case VERIF_STATUS_ERROR:
|
||||
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);
|
||||
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_orange_bg);
|
||||
lv_bar_set_style(gui->bar, LV_BAR_STYLE_INDIC, gui->bar_orange_ind);
|
||||
}
|
||||
|
||||
_update_filename(outFilename, sdPathLen, currPartIdx);
|
||||
@@ -1320,7 +1300,7 @@ multipart_not_allowed:
|
||||
msleep(150);
|
||||
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"
|
||||
"#FFDD00 Please try again now!#\n");
|
||||
lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf);
|
||||
@@ -1332,7 +1312,7 @@ multipart_not_allowed:
|
||||
}
|
||||
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);
|
||||
manual_system_maintenance(true);
|
||||
}
|
||||
@@ -1364,12 +1344,12 @@ multipart_not_allowed:
|
||||
f_close(&fp);
|
||||
free(clmt);
|
||||
|
||||
if (verification && !gui->raw_emummc)
|
||||
if (n_cfg.verification && !gui->raw_emummc)
|
||||
{
|
||||
// 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);
|
||||
manual_system_maintenance(true);
|
||||
|
||||
@@ -1394,7 +1374,7 @@ multipart_not_allowed:
|
||||
f_close(&fp_raw);
|
||||
|
||||
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;
|
||||
@@ -1413,18 +1393,12 @@ void restore_emmc_selected(emmcPartType_t restoreType, emmc_tool_gui_t *gui)
|
||||
|
||||
manual_system_maintenance(true);
|
||||
|
||||
if (!gui->raw_emummc)
|
||||
strcpy(txt_buf, "#FFDD00 This may render the device inoperative!#");
|
||||
else
|
||||
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!");
|
||||
|
||||
s_printf(txt_buf,
|
||||
"#FFDD00 This may render the device inoperative!#\n\n"
|
||||
"#FFDD00 Are you really sure?#");
|
||||
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"
|
||||
"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);
|
||||
|
||||
if (!res)
|
||||
strcpy(txt_buf, "#FFDD00 Failed!#\n");
|
||||
s_printf(txt_buf, "#FFDD00 Failed!#\n");
|
||||
else if (res > 0)
|
||||
strcpy(txt_buf, "Done!\n");
|
||||
s_printf(txt_buf, "Done!\n");
|
||||
|
||||
if (res >= 0)
|
||||
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);
|
||||
|
||||
if (!res)
|
||||
strcpy(txt_buf, "#FFDD00 Failed!#\n");
|
||||
s_printf(txt_buf, "#FFDD00 Failed!#\n");
|
||||
else if (res > 0)
|
||||
strcpy(txt_buf, "Done!\n");
|
||||
s_printf(txt_buf, "Done!\n");
|
||||
|
||||
if (res >= 0)
|
||||
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);
|
||||
|
||||
if (!res)
|
||||
strcpy(txt_buf, "#FFDD00 Failed!#\n");
|
||||
s_printf(txt_buf, "#FFDD00 Failed!#\n");
|
||||
else if (res > 0)
|
||||
strcpy(txt_buf, "Done!\n");
|
||||
s_printf(txt_buf, "Done!\n");
|
||||
|
||||
if (res >= 0)
|
||||
lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, txt_buf);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -30,11 +30,9 @@ typedef struct _emummc_cfg_t
|
||||
} emummc_cfg_t;
|
||||
|
||||
void load_emummc_cfg(emummc_cfg_t *emu_info);
|
||||
void save_emummc_cfg(u32 part_idx, u32 sector_start, const char *path);
|
||||
void dump_emummc_file(emmc_tool_gui_t *gui);
|
||||
void dump_emummc_raw(emmc_tool_gui_t *gui, int part_idx, u32 sector_start, u32 resized_count);
|
||||
void save_emummc_cfg(u32 part_idx, u32 sector_start, const char *path, u8 drive);
|
||||
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, u8 drive);
|
||||
void update_emummc_base_folder(char *outFilename, u32 sdPathLen, u32 currPartIdx);
|
||||
|
||||
int emummc_raw_derive_bis_keys();
|
||||
|
||||
#endif
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include <bdk.h>
|
||||
|
||||
#include "gui.h"
|
||||
#include "gui_emu_tools.h"
|
||||
#include "gui_emummc_tools.h"
|
||||
#include "gui_tools.h"
|
||||
#include "gui_info.h"
|
||||
@@ -29,6 +30,7 @@
|
||||
|
||||
#include "../config.h"
|
||||
#include <libs/fatfs/ff.h>
|
||||
#include <storage/boot_storage.h>
|
||||
|
||||
extern volatile boot_cfg_t *b_cfg;
|
||||
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);
|
||||
|
||||
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_white;
|
||||
@@ -187,7 +189,7 @@ static void _save_log_to_bmp(char *fname)
|
||||
char path[0x80];
|
||||
strcpy(path, "bootloader/screenshots");
|
||||
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(fb);
|
||||
@@ -200,8 +202,8 @@ static void _save_fb_to_bmp()
|
||||
if (get_tmr_ms() < timer)
|
||||
return;
|
||||
|
||||
if (do_auto_reload)
|
||||
goto exit;
|
||||
if (do_reload)
|
||||
return;
|
||||
|
||||
// Invalidate data.
|
||||
bpmp_mmu_maintenance(BPMP_MMU_MAINT_INVALID_WAY, false);
|
||||
@@ -271,7 +273,7 @@ static void _save_fb_to_bmp()
|
||||
bmp->res_v = 2834;
|
||||
bmp->rsvd2 = 0;
|
||||
|
||||
sd_mount();
|
||||
boot_storage_mount();
|
||||
|
||||
char path[0x80];
|
||||
|
||||
@@ -288,7 +290,7 @@ static void _save_fb_to_bmp()
|
||||
s_printf(path + strlen(path), "/nyx%s.bmp", fname);
|
||||
|
||||
// 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)
|
||||
_save_log_to_bmp(fname);
|
||||
|
||||
@@ -304,7 +306,6 @@ static void _save_fb_to_bmp()
|
||||
manual_system_maintenance(true);
|
||||
lv_mbox_start_auto_close(mbox, 4000);
|
||||
|
||||
exit:
|
||||
// Set timer to 2s.
|
||||
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)
|
||||
{
|
||||
u32 fsize;
|
||||
u8 *bitmap = sd_file_read(path, &fsize);
|
||||
u8 *bitmap = boot_storage_file_read(path, &fsize);
|
||||
if (!bitmap)
|
||||
return NULL;
|
||||
|
||||
@@ -794,7 +795,7 @@ lv_res_t mbox_action(lv_obj_t *btns, const char *txt)
|
||||
|
||||
bool nyx_emmc_check_battery_enough()
|
||||
{
|
||||
if (h_cfg.devmode)
|
||||
if (fuse_read_hw_state() == FUSE_NX_HW_STATE_DEV)
|
||||
return true;
|
||||
|
||||
int batt_volt = 0;
|
||||
@@ -934,34 +935,17 @@ static void _launch_hos(u8 autoboot, u8 autoboot_list)
|
||||
|
||||
void (*main_ptr)() = (void *)nyx_str->hekate;
|
||||
|
||||
boot_storage_end();
|
||||
sd_end();
|
||||
emmc_end();
|
||||
|
||||
hw_deinit(false);
|
||||
|
||||
(*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->autoboot = 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;
|
||||
|
||||
// TODO:
|
||||
boot_storage_end();
|
||||
emmc_end();
|
||||
sd_end();
|
||||
|
||||
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)
|
||||
{
|
||||
if (!lv_btnm_get_pressed(btns))
|
||||
reload_nyx(NULL, false);
|
||||
reload_nyx();
|
||||
|
||||
return mbox_action(btns, txt);
|
||||
}
|
||||
@@ -1001,7 +988,7 @@ static lv_res_t _removed_sd_action(lv_obj_t *btns, const char *txt)
|
||||
break;
|
||||
case 2:
|
||||
sd_end();
|
||||
do_auto_reload = false;
|
||||
do_reload = false;
|
||||
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 lv_obj_t *dark_bg = NULL;
|
||||
|
||||
// The following checks if SDMMC_1 is initialized.
|
||||
// If yes and card was removed, shows a message box,
|
||||
// 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_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_set_top(mbox, true);
|
||||
|
||||
do_auto_reload = true;
|
||||
do_reload = true;
|
||||
}
|
||||
|
||||
// If in reload state and card was inserted, reload nyx.
|
||||
if (do_auto_reload && !sd_get_card_removed())
|
||||
reload_nyx(dark_bg, false);
|
||||
if (do_reload && !sd_get_card_removed() && boot_storage_get_drive() == DRIVE_SD)
|
||||
reload_nyx();
|
||||
}
|
||||
|
||||
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_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!#");
|
||||
|
||||
goto out_end;
|
||||
}
|
||||
|
||||
dirlist_t *filelist = dirlist("bootloader/payloads", NULL, 0);
|
||||
dirlist_t *filelist = dirlist("bootloader/payloads", NULL, false, false);
|
||||
sd_unmount();
|
||||
|
||||
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.
|
||||
LIST_INIT(ini_sections);
|
||||
|
||||
if (!sd_mount())
|
||||
if (!boot_storage_mount())
|
||||
goto failed_sd_mount;
|
||||
|
||||
// Check if we use custom system icons.
|
||||
@@ -1980,7 +1966,7 @@ failed_sd_mount:
|
||||
if (curr_btn_idx < 1)
|
||||
no_boot_entries = true;
|
||||
|
||||
sd_unmount();
|
||||
boot_storage_unmount();
|
||||
|
||||
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);
|
||||
s_printf(btn_colored_text, "%s%s", text_color, " "SYMBOL_LIST"#");
|
||||
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_obj_align(label_btn, NULL, LV_ALIGN_CENTER, 0, -28);
|
||||
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;
|
||||
|
||||
if (sd_mount())
|
||||
if (boot_storage_mount())
|
||||
res = !create_config_entry();
|
||||
|
||||
if (res)
|
||||
@@ -2191,7 +2177,7 @@ static lv_res_t _save_options_action(lv_obj_t *btn)
|
||||
|
||||
nyx_options_clear_ini_changes_made();
|
||||
|
||||
sd_unmount();
|
||||
boot_storage_unmount();
|
||||
|
||||
return LV_RES_OK;
|
||||
}
|
||||
|
||||
@@ -28,10 +28,7 @@ typedef struct _emmc_tool_gui_t
|
||||
lv_obj_t *bar;
|
||||
lv_style_t *bar_teal_bg;
|
||||
lv_style_t *bar_teal_ind;
|
||||
lv_style_t *bar_white_bg;
|
||||
lv_style_t *bar_white_ind;
|
||||
lv_style_t *bar_orange_bg;
|
||||
lv_style_t *bar_orange_ind;
|
||||
char *txt_buf;
|
||||
char *base_path;
|
||||
bool raw_emummc;
|
||||
|
||||
@@ -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
|
||||
* 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);
|
||||
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);
|
||||
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.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);
|
||||
bar_white_ind.body.main_color = LV_COLOR_HEX(0xF0F0F0);
|
||||
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_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;
|
||||
|
||||
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.
|
||||
{
|
||||
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
|
||||
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);
|
||||
|
||||
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
|
||||
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_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);
|
||||
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;
|
||||
|
||||
return LV_RES_OK;
|
||||
|
||||
50
nyx/nyx_gui/frontend/gui_emu_tools.c
Normal file
50
nyx/nyx_gui/frontend/gui_emu_tools.c
Normal 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;
|
||||
}
|
||||
|
||||
8
nyx/nyx_gui/frontend/gui_emu_tools.h
Normal file
8
nyx/nyx_gui/frontend/gui_emu_tools.h
Normal 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
@@ -19,6 +19,6 @@
|
||||
|
||||
#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
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include "../hos/hos.h"
|
||||
#include "../hos/pkg1.h"
|
||||
#include <libs/fatfs/ff.h>
|
||||
#include <storage/boot_storage.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)
|
||||
{
|
||||
int error = !sd_mount();
|
||||
int error = !boot_storage_mount();
|
||||
|
||||
if (!error)
|
||||
{
|
||||
char path[64];
|
||||
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");
|
||||
@@ -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)
|
||||
{
|
||||
int error = !sd_mount();
|
||||
int error = !boot_storage_mount();
|
||||
|
||||
if (!error)
|
||||
{
|
||||
@@ -105,9 +106,9 @@ static lv_res_t _battery_dump_window_action(lv_obj_t * btn)
|
||||
max17050_dump_regs(buf);
|
||||
|
||||
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");
|
||||
@@ -119,7 +120,7 @@ static lv_res_t _bootrom_dump_window_action(lv_obj_t * btn)
|
||||
{
|
||||
static const u32 BOOTROM_SIZE = 0x18000;
|
||||
|
||||
int error = !sd_mount();
|
||||
int error = !boot_storage_mount();
|
||||
if (!error)
|
||||
{
|
||||
char path[64];
|
||||
@@ -129,13 +130,13 @@ static lv_res_t _bootrom_dump_window_action(lv_obj_t * btn)
|
||||
if (!error)
|
||||
{
|
||||
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
|
||||
error = 255;
|
||||
|
||||
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)
|
||||
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.
|
||||
|
||||
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)
|
||||
error = res;
|
||||
|
||||
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");
|
||||
|
||||
@@ -180,14 +181,14 @@ static void _unlock_reserved_odm_fuses(bool lock)
|
||||
|
||||
static lv_res_t _fuse_dump_window_action(lv_obj_t * btn)
|
||||
{
|
||||
int error = !sd_mount();
|
||||
int error = !boot_storage_mount();
|
||||
if (!error)
|
||||
{
|
||||
char path[128];
|
||||
if (!h_cfg.t210b01)
|
||||
{
|
||||
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);
|
||||
}
|
||||
else
|
||||
@@ -196,10 +197,10 @@ static lv_res_t _fuse_dump_window_action(lv_obj_t * btn)
|
||||
_unlock_reserved_odm_fuses(false);
|
||||
|
||||
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);
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -214,7 +215,7 @@ static lv_res_t _fuse_dump_window_action(lv_obj_t * btn)
|
||||
if (h_cfg.t210b01)
|
||||
_unlock_reserved_odm_fuses(true);
|
||||
|
||||
sd_unmount();
|
||||
boot_storage_unmount();
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
if (!error)
|
||||
error = !sd_mount();
|
||||
error = !boot_storage_mount();
|
||||
|
||||
if (!error)
|
||||
{
|
||||
char path[64];
|
||||
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");
|
||||
@@ -269,7 +270,7 @@ static lv_res_t _create_mbox_cal0(lv_obj_t *btn)
|
||||
lv_label_set_style(lb_desc, &monospace_text);
|
||||
lv_obj_set_width(lb_desc, LV_HOR_RES / 9 * 4);
|
||||
|
||||
sd_mount();
|
||||
boot_storage_mount();
|
||||
|
||||
// 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;
|
||||
|
||||
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,
|
||||
"#FF8000 CAL0 Version:# %d\n"
|
||||
@@ -369,7 +370,7 @@ static lv_res_t _create_mbox_cal0(lv_obj_t *btn)
|
||||
|
||||
out:
|
||||
free(txt_buf);
|
||||
sd_unmount();
|
||||
boot_storage_unmount();
|
||||
|
||||
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)
|
||||
{
|
||||
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:
|
||||
strcat(txt_buf, "JDI LAM062M109A");
|
||||
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)
|
||||
{
|
||||
// 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.
|
||||
random_offsets[i + 0] = random_numbers[0] % sct_rem_4kb;
|
||||
@@ -2881,7 +2906,7 @@ static bool _lockpick_exists_check()
|
||||
|
||||
bool found = false;
|
||||
void *buf = malloc(0x200);
|
||||
if (sd_mount())
|
||||
if (boot_storage_mount())
|
||||
{
|
||||
FIL fp;
|
||||
if (f_open(&fp, "bootloader/payloads/Lockpick_RCM.bin", FA_READ))
|
||||
@@ -2906,7 +2931,7 @@ static bool _lockpick_exists_check()
|
||||
|
||||
out:
|
||||
free(buf);
|
||||
sd_unmount();
|
||||
boot_storage_unmount();
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include "../config.h"
|
||||
#include <libs/lvgl/lv_themes/lv_theme_hekate.h>
|
||||
#include <libs/lvgl/lvgl.h>
|
||||
#include <storage/boot_storage.h>
|
||||
|
||||
#define CLOCK_MIN_YEAR 2025
|
||||
#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_list_set_single_mode(list_main, true);
|
||||
|
||||
sd_mount();
|
||||
boot_storage_mount();
|
||||
|
||||
// Parse hekate main configuration.
|
||||
LIST_INIT(ini_sections);
|
||||
@@ -285,7 +286,7 @@ static void _create_autoboot_window()
|
||||
ini_free(&ini_list_sections);
|
||||
}
|
||||
|
||||
sd_unmount();
|
||||
boot_storage_unmount();
|
||||
}
|
||||
|
||||
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.
|
||||
create_nyx_config_entry(true);
|
||||
|
||||
reload_nyx(NULL, false);
|
||||
reload_nyx();
|
||||
|
||||
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;
|
||||
|
||||
save_data:
|
||||
error = !sd_mount() ? 5 : 0;
|
||||
error = !boot_storage_mount() ? 5 : 0;
|
||||
|
||||
if (!error)
|
||||
{
|
||||
@@ -958,7 +959,8 @@ save_data:
|
||||
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));
|
||||
|
||||
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.
|
||||
data[0] = 0;
|
||||
@@ -1080,7 +1082,7 @@ save_data:
|
||||
}
|
||||
}
|
||||
|
||||
sd_unmount();
|
||||
boot_storage_unmount();
|
||||
}
|
||||
|
||||
disabled_or_cal0_issue:;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -25,5 +25,6 @@ void create_tab_tools(lv_theme_t *th, lv_obj_t *parent);
|
||||
void nyx_run_ums(void *param);
|
||||
bool get_set_autorcm_status(bool change);
|
||||
lv_res_t action_ums_sd(lv_obj_t *btn);
|
||||
lv_res_t action_ums_emmc_gpp(lv_obj_t *btn);
|
||||
|
||||
#endif
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
@@ -17,7 +17,6 @@
|
||||
#ifndef _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_emmc_partition_manager(lv_obj_t *btn);
|
||||
lv_res_t create_window_partition_manager(lv_obj_t *btn, u8 drive);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include <bdk.h>
|
||||
|
||||
#include "hos.h"
|
||||
#include <storage/boot_storage.h>
|
||||
#include "../config.h"
|
||||
|
||||
u8 *cal0_buf = NULL;
|
||||
@@ -208,7 +209,7 @@ static void _hos_eks_get()
|
||||
|
||||
// Decrypt EKS blob.
|
||||
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.
|
||||
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.
|
||||
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.
|
||||
h_cfg.eks->magic = HOS_EKS_MAGIC;
|
||||
@@ -269,7 +270,7 @@ static void _hos_eks_save()
|
||||
// Encrypt EKS blob.
|
||||
u8 *eks = malloc(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.
|
||||
memcpy(mbr + 0x80, eks, sizeof(hos_eks_mbr_t));
|
||||
@@ -304,7 +305,7 @@ void hos_eks_clear(u32 mkey)
|
||||
// Encrypt EKS blob.
|
||||
u8 *eks = malloc(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.
|
||||
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.
|
||||
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)
|
||||
{
|
||||
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.
|
||||
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);
|
||||
|
||||
// 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);
|
||||
|
||||
// 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);
|
||||
|
||||
// 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);
|
||||
|
||||
// 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_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);
|
||||
|
||||
/*
|
||||
// Verify eks CMAC.
|
||||
u8 cmac[SE_KEY_128_SIZE];
|
||||
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))
|
||||
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);
|
||||
|
||||
// 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(12, 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)
|
||||
{
|
||||
@@ -531,11 +532,12 @@ static void _hos_validate_mkey()
|
||||
do
|
||||
{
|
||||
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++)
|
||||
{
|
||||
se_aes_key_clear(2);
|
||||
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))
|
||||
@@ -592,17 +594,19 @@ int hos_bis_keygen()
|
||||
do
|
||||
{
|
||||
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++)
|
||||
{
|
||||
se_aes_key_clear(2);
|
||||
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));
|
||||
|
||||
// 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_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, 1, tmp_mkey);
|
||||
|
||||
@@ -610,27 +614,29 @@ int hos_bis_keygen()
|
||||
}
|
||||
|
||||
// Generate generic key.
|
||||
se_aes_key_clear(2);
|
||||
se_aes_unwrap_key(2, console_key_slot, gen_keyseed_retail);
|
||||
|
||||
// Clear bis keys storage.
|
||||
memset(bis_keys, 0, SE_KEY_128_SIZE * 6);
|
||||
|
||||
// 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_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 + (0 * SE_KEY_128_SIZE), bis_keyseed[0]);
|
||||
se_aes_crypt_block_ecb(2, DECRYPT, bis_keys + (1 * SE_KEY_128_SIZE), bis_keyseed[1]);
|
||||
|
||||
// Generate generic kek.
|
||||
se_aes_key_clear(2);
|
||||
se_aes_unwrap_key(2, console_key_slot, gen_kekseed);
|
||||
se_aes_unwrap_key(2, 2, bis_kekseed);
|
||||
se_aes_unwrap_key(2, 2, gen_keyseed);
|
||||
|
||||
// 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_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 + (2 * SE_KEY_128_SIZE), bis_keyseed[2]);
|
||||
se_aes_crypt_block_ecb(2, DECRYPT, bis_keys + (3 * SE_KEY_128_SIZE), bis_keyseed[3]);
|
||||
|
||||
// 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_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 + (4 * SE_KEY_128_SIZE), bis_keyseed[4]);
|
||||
se_aes_crypt_block_ecb(2, DECRYPT, bis_keys + (5 * SE_KEY_128_SIZE), bis_keyseed[5]);
|
||||
|
||||
// Validate key because HOS_MKEY_VER_MAX.
|
||||
if (!h_cfg.t210b01)
|
||||
@@ -682,7 +688,7 @@ int hos_dump_cal0()
|
||||
LIST_INIT(gpt);
|
||||
emmc_gpt_parse(&gpt);
|
||||
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_end();
|
||||
emmc_gpt_free(&gpt);
|
||||
@@ -707,7 +713,7 @@ int hos_dump_cal0()
|
||||
}
|
||||
|
||||
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))
|
||||
return 3;
|
||||
|
||||
|
||||
@@ -96,7 +96,7 @@ int pkg1_decrypt(const pkg1_id_t *id, u8 *pkg1)
|
||||
u8 *pkg11 = pkg1 + id->pkg11_off;
|
||||
u32 pkg11_size = *(u32 *)pkg11;
|
||||
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
|
||||
{
|
||||
@@ -107,7 +107,7 @@ int pkg1_decrypt(const pkg1_id_t *id, u8 *pkg1)
|
||||
// Use BEK for T210B01.
|
||||
// Additionally, skip 0x20 bytes from decryption to maintain the header.
|
||||
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.
|
||||
|
||||
@@ -26,12 +26,6 @@
|
||||
#define PK11_SECTION_LD 1
|
||||
#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
|
||||
{
|
||||
/* 0x000 */ u8 aes_mac[0x10];
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* 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
|
||||
* 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)
|
||||
{
|
||||
// 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.
|
||||
se_aes_key_set(9, mkey, SE_KEY_128_SIZE);
|
||||
se_aes_unwrap_key(9, 9, package2_keyseed);
|
||||
|
||||
// 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 (tmp_test->magic == PKG2_MAGIC);
|
||||
@@ -150,7 +150,7 @@ pkg2_hdr_t *pkg2_decrypt(void *data, u8 mkey)
|
||||
pdata += sizeof(pkg2_hdr_t);
|
||||
|
||||
// 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)
|
||||
goto key_found;
|
||||
@@ -197,7 +197,7 @@ pkg2_hdr_t *pkg2_decrypt(void *data, u8 mkey)
|
||||
|
||||
key_found:
|
||||
// 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)
|
||||
return NULL;
|
||||
@@ -209,7 +209,7 @@ DPRINTF("sec %d has size %08X\n", i, hdr->sec_size[i]);
|
||||
if (!hdr->sec_size[i])
|
||||
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];
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* 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
|
||||
* 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
|
||||
{
|
||||
/* 0x000 */ u8 ctr[0x10];
|
||||
/* 0x010 */ u8 sec_ctr[4][SE_AES_IV_SIZE];
|
||||
/* 0x010 */ u8 sec_ctr[0x40];
|
||||
/* 0x050 */ u32 magic;
|
||||
/* 0x054 */ u32 base;
|
||||
/* 0x058 */ u32 pad0;
|
||||
@@ -48,7 +48,7 @@ typedef struct _pkg2_hdr_t
|
||||
/* 0x05E */ u16 pad1;
|
||||
/* 0x060 */ u32 sec_size[4];
|
||||
/* 0x070 */ u32 sec_off[4];
|
||||
/* 0x080 */ u8 sec_sha256[4][SE_SHA_256_SIZE];
|
||||
/* 0x080 */ u8 sec_sha256[0x80];
|
||||
/* 0x100 */ u8 data[];
|
||||
} pkg2_hdr_t;
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* Low level disk I/O module skeleton for FatFs */
|
||||
/* (C) ChaN, 2016 */
|
||||
/* (C) CTCaer, 2018-2025 */
|
||||
/* (C) CTCaer, 2018-2020 */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* If a working storage control module is available, it should be */
|
||||
/* 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. */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
|
||||
#include <storage/emmc.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <bdk.h>
|
||||
|
||||
#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 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 */
|
||||
@@ -52,20 +147,45 @@ DRESULT disk_read (
|
||||
UINT count /* Number of sectors to read */
|
||||
)
|
||||
{
|
||||
switch (pdrv)
|
||||
{
|
||||
case DRIVE_SD:
|
||||
return sdmmc_storage_read(&sd_storage, sector, count, (void *)buff) ? RES_OK : RES_ERROR;
|
||||
case DRIVE_RAM:
|
||||
return ram_disk_read(sector, count, (void *)buff);
|
||||
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;
|
||||
DRESULT res = RES_OK;
|
||||
|
||||
save_cur_partition(pdrv);
|
||||
|
||||
if(!ensure_partition(pdrv)){
|
||||
res = 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 */
|
||||
)
|
||||
{
|
||||
switch (pdrv)
|
||||
{
|
||||
case DRIVE_SD:
|
||||
return sdmmc_storage_write(&sd_storage, sector, count, (void *)buff) ? RES_OK : RES_ERROR;
|
||||
case DRIVE_RAM:
|
||||
return ram_disk_write(sector, count, (void *)buff);
|
||||
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;
|
||||
DRESULT res = RES_OK;
|
||||
|
||||
save_cur_partition(pdrv);
|
||||
|
||||
if(!ensure_partition(pdrv)){
|
||||
res = 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;
|
||||
|
||||
switch (pdrv)
|
||||
if (pdrv == DRIVE_SD)
|
||||
{
|
||||
case DRIVE_SD:
|
||||
switch (cmd)
|
||||
{
|
||||
case GET_SECTOR_COUNT:
|
||||
@@ -119,9 +263,9 @@ DRESULT disk_ioctl (
|
||||
*buf = 32768; // Align to 16MB.
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case DRIVE_RAM:
|
||||
}
|
||||
else if (pdrv == DRIVE_RAM)
|
||||
{
|
||||
switch (cmd)
|
||||
{
|
||||
case GET_SECTOR_COUNT:
|
||||
@@ -131,33 +275,29 @@ DRESULT disk_ioctl (
|
||||
*buf = 2048; // Align to 1MB.
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
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:
|
||||
}
|
||||
else if (pdrv == DRIVE_EMU)
|
||||
{
|
||||
switch (cmd)
|
||||
{
|
||||
case GET_SECTOR_COUNT:
|
||||
*buf = emummc_sectors;
|
||||
break;
|
||||
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;
|
||||
|
||||
default: // Catch all for unknown devices.
|
||||
}else if(pdrv == DRIVE_SFD){
|
||||
switch(cmd){
|
||||
case GET_SECTOR_COUNT:
|
||||
*buf = sfd_sectors;
|
||||
break;
|
||||
case GET_BLOCK_SIZE:
|
||||
*buf = 32768;
|
||||
break;
|
||||
}
|
||||
}else // Catch all for unknown devices.
|
||||
{
|
||||
switch (cmd)
|
||||
{
|
||||
case CTRL_SYNC:
|
||||
@@ -167,7 +307,6 @@ DRESULT disk_ioctl (
|
||||
*buf = 0; // Zero value to force default or abort.
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return RES_OK;
|
||||
@@ -188,22 +327,17 @@ DRESULT disk_set_info (
|
||||
case DRIVE_SD:
|
||||
sd_rsvd_sectors = *buf;
|
||||
break;
|
||||
|
||||
case DRIVE_RAM:
|
||||
ramdisk_sectors = *buf;
|
||||
break;
|
||||
|
||||
case DRIVE_BIS:
|
||||
bis_sectors = *buf;
|
||||
break;
|
||||
|
||||
case DRIVE_EMU:
|
||||
emummc_sectors = *buf;
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -168,7 +168,7 @@
|
||||
*/
|
||||
|
||||
|
||||
#define FF_FS_RPATH 1
|
||||
#define FF_FS_RPATH 2
|
||||
/* This option configures support for relative path.
|
||||
/
|
||||
/ 0: Disable relative path and remove related functions.
|
||||
@@ -181,12 +181,12 @@
|
||||
/ Drive/Volume Configurations
|
||||
/---------------------------------------------------------------------------*/
|
||||
|
||||
#define FF_VOLUMES 5
|
||||
#define FF_VOLUMES 8
|
||||
/* Number of volumes (logical drives) to be used. (1-10) */
|
||||
|
||||
|
||||
#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.
|
||||
/ 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
|
||||
@@ -302,6 +302,15 @@
|
||||
/ SemaphoreHandle_t and etc. A header file for O/S definitions needs to be
|
||||
/ 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 ---*/
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#include <ianos/ianos.h>
|
||||
#include <libs/compr/blz.h>
|
||||
#include <libs/fatfs/ff.h>
|
||||
#include <storage/boot_storage.h>
|
||||
|
||||
#include "frontend/fe_emmc_tools.h"
|
||||
#include "frontend/gui.h"
|
||||
@@ -34,7 +35,7 @@ nyx_config n_cfg;
|
||||
hekate_config h_cfg;
|
||||
|
||||
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),
|
||||
};
|
||||
|
||||
@@ -121,7 +122,7 @@ lv_res_t launch_payload(lv_obj_t *list)
|
||||
strcpy(path,"bootloader/payloads/");
|
||||
strcat(path, filename);
|
||||
|
||||
if (!sd_mount())
|
||||
if (!boot_storage_mount())
|
||||
goto out;
|
||||
|
||||
// Read payload.
|
||||
@@ -142,7 +143,7 @@ lv_res_t launch_payload(lv_obj_t *list)
|
||||
goto out;
|
||||
}
|
||||
|
||||
sd_end();
|
||||
boot_storage_end();
|
||||
|
||||
// Copy the payload to our chosen address.
|
||||
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)
|
||||
{
|
||||
gfx_clear_grey(0);
|
||||
gfx_con_setpos(0, 0, 0);
|
||||
// gfx_clear_grey(0);
|
||||
// gfx_con_setpos(0, 0, 0);
|
||||
display_backlight_brightness(150, 1000);
|
||||
display_init_window_d_console();
|
||||
display_window_d_console_enable();
|
||||
@@ -380,7 +381,7 @@ error_occured:
|
||||
msleep(1000);
|
||||
btn_wait();
|
||||
|
||||
reload_nyx(NULL, true);
|
||||
reload_nyx();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -427,13 +428,13 @@ void nyx_init_load_res()
|
||||
_show_errors(SD_NO_ERROR);
|
||||
|
||||
// Try 2 times to mount SD card.
|
||||
if (!sd_mount())
|
||||
if (!boot_storage_mount())
|
||||
{
|
||||
// Restore speed to SDR104.
|
||||
sd_end();
|
||||
boot_storage_end();
|
||||
|
||||
// Retry.
|
||||
if (!sd_mount())
|
||||
if (!boot_storage_mount())
|
||||
_show_errors(SD_MOUNT_ERROR); // Fatal.
|
||||
}
|
||||
|
||||
@@ -490,7 +491,7 @@ void nyx_init_load_res()
|
||||
nyx_load_bg_icons();
|
||||
|
||||
// Unmount FAT partition.
|
||||
sd_unmount();
|
||||
boot_storage_unmount();
|
||||
}
|
||||
|
||||
void ipl_main()
|
||||
|
||||
86
nyx/nyx_gui/storage/sfd.c
Normal file
86
nyx/nyx_gui/storage/sfd.c
Normal 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
16
nyx/nyx_gui/storage/sfd.h
Normal 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
|
||||
Reference in New Issue
Block a user