From fed7f0583181fd763e555f2a9b62aab2f48c3354 Mon Sep 17 00:00:00 2001 From: niklascfw Date: Fri, 20 Feb 2026 20:49:48 +0100 Subject: [PATCH] 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 --- Makefile | 102 +- bdk/display/di.h | 7 +- bdk/ianos/ianos.c | 3 +- bdk/libs/fatfs/diskio.h | 9 +- bdk/libs/fatfs/ff.c | 33 +- bdk/power/max7762x.c | 2 +- bdk/sec/se.c | 357 +- bdk/sec/se.h | 33 +- bdk/storage/boot_storage.c | 275 ++ bdk/storage/boot_storage.h | 24 + bdk/storage/emmc.c | 82 +- bdk/storage/emmc.h | 5 + bdk/storage/emummc_file_based.c | 233 ++ bdk/storage/emummc_file_based.h | 14 + bdk/storage/file_based_storage.c | 184 + bdk/storage/file_based_storage.h | 15 + bdk/storage/mbr_gpt.c | 39 + bdk/storage/mbr_gpt.h | 6 + bdk/storage/nx_emmc_bis.c | 67 +- bdk/storage/nx_emmc_bis.h | 5 +- bdk/storage/ramdisk.c | 2 +- bdk/storage/sd.c | 46 +- bdk/storage/sdmmc.h | 9 +- bdk/usb/usb_gadget_ums.c | 127 +- bdk/utils/dirlist.c | 16 +- bdk/utils/dirlist.h | 8 +- bdk/utils/ini.c | 2 +- bdk/utils/types.h | 9 +- bdk/utils/util.c | 2 + bootloader/config.c | 1 - bootloader/config.h | 1 - bootloader/frontend/fe_info.c | 12 +- bootloader/hos/hos.c | 66 +- bootloader/hos/hos_config.c | 21 +- bootloader/hos/pkg1.c | 6 +- bootloader/hos/pkg2.c | 25 +- bootloader/hos/pkg2.h | 6 +- bootloader/hos/pkg3.c | 29 +- bootloader/hos/secmon_exo.c | 105 +- bootloader/l4t/l4t.c | 5 +- bootloader/libs/fatfs/diskio.c | 85 +- bootloader/libs/fatfs/ffconf.h | 15 +- bootloader/main.c | 184 +- bootloader/storage/emummc.c | 241 +- bootloader/storage/emummc.h | 14 +- bootloader/storage/emusd.c | 295 ++ bootloader/storage/emusd.h | 49 + loader/Makefile | 20 +- modules/hekate_libsys_lp0/Makefile | 36 +- modules/hekate_libsys_minerva/Makefile | 36 +- modules/simple_sample/Makefile | 38 +- modules/simple_sample/module_sample.c | 2 +- nyx/Makefile | 114 +- nyx/nyx_gui/config.c | 8 +- nyx/nyx_gui/config.h | 1 - nyx/nyx_gui/frontend/fe_emmc_tools.c | 186 +- nyx/nyx_gui/frontend/fe_emummc_tools.c | 740 ++-- nyx/nyx_gui/frontend/fe_emummc_tools.h | 8 +- nyx/nyx_gui/frontend/gui.c | 76 +- nyx/nyx_gui/frontend/gui.h | 3 - nyx/nyx_gui/frontend/gui_emmc_tools.c | 25 +- nyx/nyx_gui/frontend/gui_emu_tools.c | 50 + nyx/nyx_gui/frontend/gui_emu_tools.h | 8 + nyx/nyx_gui/frontend/gui_emummc_tools.c | 1102 +++++- nyx/nyx_gui/frontend/gui_emummc_tools.h | 2 +- nyx/nyx_gui/frontend/gui_info.c | 75 +- nyx/nyx_gui/frontend/gui_options.c | 14 +- nyx/nyx_gui/frontend/gui_tools.c | 1148 +++--- nyx/nyx_gui/frontend/gui_tools.h | 1 + .../frontend/gui_tools_partition_manager.c | 3334 ++++++++++------- .../frontend/gui_tools_partition_manager.h | 5 +- nyx/nyx_gui/hos/hos.c | 58 +- nyx/nyx_gui/hos/pkg1.c | 4 +- nyx/nyx_gui/hos/pkg1.h | 6 - nyx/nyx_gui/hos/pkg2.c | 12 +- nyx/nyx_gui/hos/pkg2.h | 6 +- nyx/nyx_gui/libs/fatfs/diskio.c | 260 +- nyx/nyx_gui/libs/fatfs/ffconf.h | 17 +- nyx/nyx_gui/nyx.c | 21 +- nyx/nyx_gui/storage/sfd.c | 86 + nyx/nyx_gui/storage/sfd.h | 16 + 81 files changed, 6932 insertions(+), 3462 deletions(-) create mode 100644 bdk/storage/boot_storage.c create mode 100644 bdk/storage/boot_storage.h create mode 100644 bdk/storage/emummc_file_based.c create mode 100644 bdk/storage/emummc_file_based.h create mode 100644 bdk/storage/file_based_storage.c create mode 100644 bdk/storage/file_based_storage.h create mode 100644 bdk/storage/mbr_gpt.c create mode 100644 bootloader/storage/emusd.c create mode 100644 bootloader/storage/emusd.h create mode 100644 nyx/nyx_gui/frontend/gui_emu_tools.c create mode 100644 nyx/nyx_gui/frontend/gui_emu_tools.h create mode 100644 nyx/nyx_gui/storage/sfd.c create mode 100644 nyx/nyx_gui/storage/sfd.h diff --git a/Makefile b/Makefile index 3b5ee1d3..1d1b89e8 100755 --- a/Makefile +++ b/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) diff --git a/bdk/display/di.h b/bdk/display/di.h index 66eaa9ad..6050bca1 100644 --- a/bdk/display/di.h +++ b/bdk/display/di.h @@ -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. diff --git a/bdk/ianos/ianos.c b/bdk/ianos/ianos.c index 99a996df..bffe2cbe 100644 --- a/bdk/ianos/ianos.c +++ b/bdk/ianos/ianos.c @@ -15,6 +15,7 @@ * along with this program. If not, see . */ +#include #include #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; diff --git a/bdk/libs/fatfs/diskio.h b/bdk/libs/fatfs/diskio.h index d4357eb9..a8a2992a 100644 --- a/bdk/libs/fatfs/diskio.h +++ b/bdk/libs/fatfs/diskio.h @@ -10,6 +10,7 @@ extern "C" { #endif #include +#include /* 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 */ diff --git a/bdk/libs/fatfs/ff.c b/bdk/libs/fatfs/ff.c index c6b05e3c..0f05af88 100644 --- a/bdk/libs/fatfs/ff.c +++ b/bdk/libs/fatfs/ff.c @@ -42,8 +42,8 @@ #include #include -#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 diff --git a/bdk/power/max7762x.c b/bdk/power/max7762x.c index f0aefb5a..12c4a5af 100644 --- a/bdk/power/max7762x.c +++ b/bdk/power/max7762x.c @@ -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 }} }, diff --git a/bdk/sec/se.c b/bdk/sec/se.c index ceabd8ca..04495d07 100644 --- a/bdk/sec/se.c +++ b/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; } diff --git a/bdk/sec/se.h b/bdk/sec/se.h index e727f328..9652931b 100644 --- a/bdk/sec/se.h +++ b/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 diff --git a/bdk/storage/boot_storage.c b/bdk/storage/boot_storage.c new file mode 100644 index 00000000..a8b57eae --- /dev/null +++ b/bdk/storage/boot_storage.c @@ -0,0 +1,275 @@ +#include "boot_storage.h" +#include +#include +#include +#include +#include +#include +#include + +#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; +} \ No newline at end of file diff --git a/bdk/storage/boot_storage.h b/bdk/storage/boot_storage.h new file mode 100644 index 00000000..0bd529a2 --- /dev/null +++ b/bdk/storage/boot_storage.h @@ -0,0 +1,24 @@ +#ifndef _BOOT_STORAGE_H +#define _BOOT_STORAGE_H + +#include +#include + +// check if boot1 (1mb), boot1, gpp, sd (in that order) have fat32 partition, +// mount the partition and set the current drive to it +bool boot_storage_mount(); + +void boot_storage_unmount(); +void boot_storage_end(); + +bool boot_storage_get_mounted(); +bool boot_storage_get_initialized(); + +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 \ No newline at end of file diff --git a/bdk/storage/emmc.c b/bdk/storage/emmc.c index b1ab03d2..75c3e83e 100644 --- a/bdk/storage/emmc.c +++ b/bdk/storage/emmc.c @@ -21,10 +21,14 @@ #include #include #include +#include #include +#include 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); } \ No newline at end of file diff --git a/bdk/storage/emmc.h b/bdk/storage/emmc.h index 904852d0..588192bf 100644 --- a/bdk/storage/emmc.h +++ b/bdk/storage/emmc.h @@ -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); diff --git a/bdk/storage/emummc_file_based.c b/bdk/storage/emummc_file_based.c new file mode 100644 index 00000000..6241a397 --- /dev/null +++ b/bdk/storage/emummc_file_based.c @@ -0,0 +1,233 @@ +#include "emummc_file_based.h" +#include +#include +#include +#include + +// 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; +} \ No newline at end of file diff --git a/bdk/storage/emummc_file_based.h b/bdk/storage/emummc_file_based.h new file mode 100644 index 00000000..c78e0504 --- /dev/null +++ b/bdk/storage/emummc_file_based.h @@ -0,0 +1,14 @@ +#ifndef _EMUMMC_FILE_BASED_H +#define _EMUMMC_FILE_BASED_H + +#include + +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 \ No newline at end of file diff --git a/bdk/storage/file_based_storage.c b/bdk/storage/file_based_storage.c new file mode 100644 index 00000000..27692bc8 --- /dev/null +++ b/bdk/storage/file_based_storage.c @@ -0,0 +1,184 @@ +#include "file_based_storage.h" +#include +#include +#include + +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; +} \ No newline at end of file diff --git a/bdk/storage/file_based_storage.h b/bdk/storage/file_based_storage.h new file mode 100644 index 00000000..3de29b4b --- /dev/null +++ b/bdk/storage/file_based_storage.h @@ -0,0 +1,15 @@ +#ifndef _FILE_BASED_STORAGE_H +#define _FILE_BASED_STORAGE_H + +#include + + +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 \ No newline at end of file diff --git a/bdk/storage/mbr_gpt.c b/bdk/storage/mbr_gpt.c new file mode 100644 index 00000000..09e6f331 --- /dev/null +++ b/bdk/storage/mbr_gpt.c @@ -0,0 +1,39 @@ +#include "mbr_gpt.h" +#include +#include + +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; +} \ No newline at end of file diff --git a/bdk/storage/mbr_gpt.h b/bdk/storage/mbr_gpt.h index 7f381083..e90fb28a 100644 --- a/bdk/storage/mbr_gpt.h +++ b/bdk/storage/mbr_gpt.h @@ -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 diff --git a/bdk/storage/nx_emmc_bis.c b/bdk/storage/nx_emmc_bis.c index d9a02c28..a6780e9e 100644 --- a/bdk/storage/nx_emmc_bis.c +++ b/bdk/storage/nx_emmc_bis.c @@ -17,6 +17,9 @@ * along with this program. If not, see . */ +#include +#include +#include #include #include @@ -26,6 +29,7 @@ #include #include #include +#include #include #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(); + } +} \ No newline at end of file diff --git a/bdk/storage/nx_emmc_bis.h b/bdk/storage/nx_emmc_bis.h index 58413588..4cca8410 100644 --- a/bdk/storage/nx_emmc_bis.h +++ b/bdk/storage/nx_emmc_bis.h @@ -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 diff --git a/bdk/storage/ramdisk.c b/bdk/storage/ramdisk.c index 90ebb94c..3a86ebf9 100644 --- a/bdk/storage/ramdisk.c +++ b/bdk/storage/ramdisk.c @@ -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); diff --git a/bdk/storage/sd.c b/bdk/storage/sd.c index 2a61bbda..42fc5d27 100644 --- a/bdk/storage/sd.c +++ b/bdk/storage/sd.c @@ -199,7 +199,7 @@ bool sd_mount() else { if (!sd_mounted) - res = f_mount(&sd_fs, "0:", 1); // Volume 0 is SD. + res = f_mount(&sd_fs, "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); diff --git a/bdk/storage/sdmmc.h b/bdk/storage/sdmmc.h index e1b3fcda..00d2c97a 100644 --- a/bdk/storage/sdmmc.h +++ b/bdk/storage/sdmmc.h @@ -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, diff --git a/bdk/usb/usb_gadget_ums.c b/bdk/usb/usb_gadget_ums.c index 4b06ed67..39acaa82 100644 --- a/bdk/usb/usb_gadget_ums.c +++ b/bdk/usb/usb_gadget_ums.c @@ -19,6 +19,9 @@ * along with this program. If not, see . */ +#include +#include +#include #include #include @@ -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 diff --git a/bdk/utils/dirlist.c b/bdk/utils/dirlist.c index bed20044..b1de1401 100644 --- a/bdk/utils/dirlist.c +++ b/bdk/utils/dirlist.c @@ -22,15 +22,12 @@ #include #include -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]; diff --git a/bdk/utils/dirlist.h b/bdk/utils/dirlist.h index cf702469..cb250c3c 100644 --- a/bdk/utils/dirlist.h +++ b/bdk/utils/dirlist.h @@ -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); diff --git a/bdk/utils/ini.c b/bdk/utils/ini.c index b5a2df8a..6832bdc7 100644 --- a/bdk/utils/ini.c +++ b/bdk/utils/ini.c @@ -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); diff --git a/bdk/utils/types.h b/bdk/utils/types.h index 563d070d..60613d41 100644 --- a/bdk/utils/types.h +++ b/bdk/utils/types.h @@ -105,6 +105,9 @@ typedef unsigned long uptr; #define likely(x) (__builtin_expect((x) != 0, 1)) #define unlikely(x) (__builtin_expect((x) != 0, 0)) +#define XSTR(a) STR(a) +#define STR(a) #a + /* Bootloader/Nyx */ #define BOOT_CFG_AUTOBOOT_EN BIT(0) #define BOOT_CFG_FROM_LAUNCH BIT(1) @@ -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 diff --git a/bdk/utils/util.c b/bdk/utils/util.c index d393c5e7..a1b815d9 100644 --- a/bdk/utils/util.c +++ b/bdk/utils/util.c @@ -15,6 +15,7 @@ * along with this program. If not, see . */ +#include #include #include @@ -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. diff --git a/bootloader/config.c b/bootloader/config.c index f627f2de..1fdfe9cc 100644 --- a/bootloader/config.c +++ b/bootloader/config.c @@ -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; diff --git a/bootloader/config.h b/bootloader/config.h index c5792e97..07d5986b 100644 --- a/bootloader/config.h +++ b/bootloader/config.h @@ -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; diff --git a/bootloader/frontend/fe_info.c b/bootloader/frontend/fe_info.c index db1182af..16ea42d8 100644 --- a/bootloader/frontend/fe_info.c +++ b/bootloader/frontend/fe_info.c @@ -15,6 +15,7 @@ * along with this program. If not, see . */ +#include #include #include @@ -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(); diff --git a/bootloader/hos/hos.c b/bootloader/hos/hos.c index 588be8db..713aaa71 100644 --- a/bootloader/hos/hos.c +++ b/bootloader/hos/hos.c @@ -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 //#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!"); diff --git a/bootloader/hos/hos_config.c b/bootloader/hos/hos_config.c index eb64ae1f..05822b77 100644 --- a/bootloader/hos/hos_config.c +++ b/bootloader/hos/hos_config.c @@ -15,6 +15,8 @@ * along with this program. If not, see . */ +#include +#include "../storage/emusd.h" #include #include @@ -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; diff --git a/bootloader/hos/pkg1.c b/bootloader/hos/pkg1.c index 81ddfab6..cc310338 100644 --- a/bootloader/hos/pkg1.c +++ b/bootloader/hos/pkg1.c @@ -17,6 +17,8 @@ * along with this program. If not, see . */ +#include +#include "../storage/emusd.h" #include #include @@ -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. diff --git a/bootloader/hos/pkg2.c b/bootloader/hos/pkg2.c index a6365e52..35d937a7 100644 --- a/bootloader/hos/pkg2.c +++ b/bootloader/hos/pkg2.c @@ -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 . */ +#include #include #include @@ -27,6 +28,7 @@ #include #include #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; diff --git a/bootloader/hos/pkg2.h b/bootloader/hos/pkg2.h index c6ee4dfb..e0bc1b59 100644 --- a/bootloader/hos/pkg2.h +++ b/bootloader/hos/pkg2.h @@ -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; diff --git a/bootloader/hos/pkg3.c b/bootloader/hos/pkg3.c index 2dab4089..ffb743a7 100644 --- a/bootloader/hos/pkg3.c +++ b/bootloader/hos/pkg3.c @@ -16,6 +16,8 @@ * along with this program. If not, see . */ +#include +#include "../storage/emusd.h" #include #include @@ -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; } diff --git a/bootloader/hos/secmon_exo.c b/bootloader/hos/secmon_exo.c index 80ae1ba2..834b3e7f 100644 --- a/bootloader/hos/secmon_exo.c +++ b/bootloader/hos/secmon_exo.c @@ -24,12 +24,15 @@ #include "../config.h" #include #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. diff --git a/bootloader/l4t/l4t.c b/bootloader/l4t/l4t.c index 72efd479..45162268 100644 --- a/bootloader/l4t/l4t.c +++ b/bootloader/l4t/l4t.c @@ -25,6 +25,7 @@ #include "../hos/pkg1.h" #include "l4t.h" #include "l4t_config.inl" +#include /* * 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(); diff --git a/bootloader/libs/fatfs/diskio.c b/bootloader/libs/fatfs/diskio.c index d207d968..df8f3371 100644 --- a/bootloader/libs/fatfs/diskio.c +++ b/bootloader/libs/fatfs/diskio.c @@ -7,11 +7,39 @@ /* storage control modules to the FatFs module with a defined API. */ /*-----------------------------------------------------------------------*/ -#include +#include "../../storage/emusd.h" +#include +#include #include #include /* FatFs lower layer API */ +#include + +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; } /*-----------------------------------------------------------------------*/ diff --git a/bootloader/libs/fatfs/ffconf.h b/bootloader/libs/fatfs/ffconf.h index 03c748a9..60caac66 100644 --- a/bootloader/libs/fatfs/ffconf.h +++ b/bootloader/libs/fatfs/ffconf.h @@ -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 ---*/ diff --git a/bootloader/main.c b/bootloader/main.c index 774403a3..0d2ead71 100644 --- a/bootloader/main.c +++ b/bootloader/main.c @@ -22,6 +22,7 @@ #include #include "config.h" +#include "gfx/gfx.h" #include "gfx/logos.h" #include "gfx/tui.h" #include "hos/hos.h" @@ -31,9 +32,11 @@ #include #include #include "storage/emummc.h" +#include #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); diff --git a/bootloader/storage/emummc.c b/bootloader/storage/emummc.c index 82072441..6c9ebaa6 100644 --- a/bootloader/storage/emummc.c +++ b/bootloader/storage/emummc.c @@ -14,6 +14,9 @@ * along with this program. If not, see . */ +#include +#include +#include #include #include @@ -22,6 +25,7 @@ #include "emummc.h" #include "../config.h" #include +#include 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; +} diff --git a/bootloader/storage/emummc.h b/bootloader/storage/emummc.h index 617b36bc..f44dea30 100644 --- a/bootloader/storage/emummc.h +++ b/bootloader/storage/emummc.h @@ -19,19 +19,6 @@ #include -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 \ No newline at end of file diff --git a/bootloader/storage/emusd.c b/bootloader/storage/emusd.c new file mode 100644 index 00000000..0f5a98d3 --- /dev/null +++ b/bootloader/storage/emusd.c @@ -0,0 +1,295 @@ +#include "emusd.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#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); + } +} \ No newline at end of file diff --git a/bootloader/storage/emusd.h b/bootloader/storage/emusd.h new file mode 100644 index 00000000..1ae7a9bb --- /dev/null +++ b/bootloader/storage/emusd.h @@ -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 . + */ + +#ifndef _EMUSD_H +#define _EMUSD_H + +#include + +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 \ No newline at end of file diff --git a/loader/Makefile b/loader/Makefile index b88ad38e..c2a12c02 100644 --- a/loader/Makefile +++ b/loader/Makefile @@ -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)" diff --git a/modules/hekate_libsys_lp0/Makefile b/modules/hekate_libsys_lp0/Makefile index 40111e53..a6e29b0f 100644 --- a/modules/hekate_libsys_lp0/Makefile +++ b/modules/hekate_libsys_lp0/Makefile @@ -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 diff --git a/modules/hekate_libsys_minerva/Makefile b/modules/hekate_libsys_minerva/Makefile index 4c5de590..65915f33 100644 --- a/modules/hekate_libsys_minerva/Makefile +++ b/modules/hekate_libsys_minerva/Makefile @@ -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 diff --git a/modules/simple_sample/Makefile b/modules/simple_sample/Makefile index 2e090dba..2c0d7d7c 100644 --- a/modules/simple_sample/Makefile +++ b/modules/simple_sample/Makefile @@ -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 diff --git a/modules/simple_sample/module_sample.c b/modules/simple_sample/module_sample.c index d2bbfed8..a113644f 100644 --- a/modules/simple_sample/module_sample.c +++ b/modules/simple_sample/module_sample.c @@ -6,7 +6,7 @@ #include #include -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)); diff --git a/nyx/Makefile b/nyx/Makefile index 24c75b3e..179881ff 100644 --- a/nyx/Makefile +++ b/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) diff --git a/nyx/nyx_gui/config.c b/nyx/nyx_gui/config.c index 3474350b..2ae6d4de 100644 --- a/nyx/nyx_gui/config.c +++ b/nyx/nyx_gui/config.c @@ -21,11 +21,11 @@ #include "config.h" #include +#include 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; } diff --git a/nyx/nyx_gui/config.h b/nyx/nyx_gui/config.h index 8f846f19..f05b37a3 100644 --- a/nyx/nyx_gui/config.h +++ b/nyx/nyx_gui/config.h @@ -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; diff --git a/nyx/nyx_gui/frontend/fe_emmc_tools.c b/nyx/nyx_gui/frontend/fe_emmc_tools.c index 98ed370a..dfeeffae 100644 --- a/nyx/nyx_gui/frontend/fe_emmc_tools.c +++ b/nyx/nyx_gui/frontend/fe_emmc_tools.c @@ -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 #include #include @@ -29,10 +30,6 @@ #include "../config.h" #include -#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); diff --git a/nyx/nyx_gui/frontend/fe_emummc_tools.c b/nyx/nyx_gui/frontend/fe_emummc_tools.c index d44e724c..068d650b 100644 --- a/nyx/nyx_gui/frontend/fe_emummc_tools.c +++ b/nyx/nyx_gui/frontend/fe_emummc_tools.c @@ -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,16 @@ //! fix the dram stuff and the pop ups +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include #include @@ -26,15 +36,176 @@ #include "gui.h" #include "fe_emummc_tools.h" #include "../config.h" -#include "../hos/hos.h" #include #include +#include -#define OUT_FILENAME_SZ 128 +#define OUT_FILENAME_SZ 128 +#define NAND_PATROL_SECTOR 0xC20 #define NUM_SECTORS_PER_ITER 8192 // 4MB Cache. extern volatile boot_cfg_t *b_cfg; +static int _emummc_resize_user(emmc_tool_gui_t *gui, u32 user_offset, u32 resized_cnt, sdmmc_storage_t *raw_based_storage, u32 raw_based_sector_offset, const char *file_based_path, u8 drive){ + bool file_based = file_based_path != NULL; + + if(drive == DRIVE_SD){ + sd_mount(); + }else{ + emmc_mount(); + } + + s_printf(gui->txt_buf, "\nFormatting USER... "); + lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf); + manual_system_maintenance(true); + + + u32 user_sectors = resized_cnt - user_offset - 33; + user_sectors = ALIGN_DOWN(user_sectors, 0x20); + disk_set_info(DRIVE_EMU, SET_SECTOR_COUNT, &user_sectors); + + emmc_part_t user_part = {0}; + user_part.lba_start = user_offset; + user_part.lba_end = user_offset + user_sectors - 1; + strcpy(user_part.name, "USER"); + + if(file_based){ + nx_emmc_bis_init_file_based(&user_part, true, file_based_path); + }else{ + nx_emmc_bis_init(&user_part, true, raw_based_storage, raw_based_sector_offset); + } + + u8 *buf = malloc(SZ_4M); + int res = f_mkfs("emu:", FM_FAT32 | FM_SFD | FM_PRF2, 16384, buf, SZ_4M); + + nx_emmc_bis_end(); + hos_bis_keys_clear(); + + if(res != FR_OK){ + s_printf(gui->txt_buf, "#FF0000 Failed (%d)!#\nPlease try again...\n", res); + lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf); + free(buf); + return res; + } + + s_printf(gui->txt_buf, "Done!\nWriting new GPT... "); + lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf); + manual_system_maintenance(true); + + mbr_t mbr = {0}; + mbr.boot_signature = 0xaa55; + mbr.partitions[0].type = 0xee; + mbr.partitions[0].start_sct = 1; + mbr.partitions[0].start_sct_chs.sector = 0x02; + mbr.partitions[0].end_sct_chs.sector = 0xff; + mbr.partitions[0].end_sct_chs.cylinder = 0xff; + mbr.partitions[0].end_sct_chs.head = 0xff; + mbr.partitions[0].size_sct = 0xffffffff; + + gpt_t *gpt = zalloc(sizeof(*gpt)); + gpt_header_t gpt_hdr_backup = {0}; + + if(file_based){ + emummc_storage_file_based_init(file_based_path); + } + + res = 1; + res &= sdmmc_storage_read(&emmc_storage, 1, sizeof(*gpt) / 0x200, gpt); + res &= sdmmc_storage_read(&emmc_storage, gpt->header.alt_lba, 1, &gpt_hdr_backup); + + if(!res){ + s_printf(gui->txt_buf, "\n#FF0000 Failed to read original GPT...#\nPlease try again...\n"); + lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf); + free(gpt); + free(buf); + emummc_storage_file_based_end(); + + return FR_DISK_ERR; + } + + u32 gpt_entry_idx = 0; + for (gpt_entry_idx = 0; gpt_entry_idx < gpt->header.num_part_ents; gpt_entry_idx++) + if (!memcmp(gpt->entries[gpt_entry_idx].name, (char[]) { 'U', 0, 'S', 0, 'E', 0, 'R', 0 }, 8)) + break; + + if (gpt_entry_idx >= gpt->header.num_part_ents) + { + s_printf(gui->txt_buf, "\n#FF0000 No USER partition...#\nPlease try again...\n"); + lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf); + free(gpt); + free(buf); + emummc_storage_file_based_end(); + + return FR_DISK_ERR; + } + + // clear out all partition entries after user + memset(&gpt->entries[gpt_entry_idx + 1], 0, sizeof(gpt->entries[0]) * (128 - (gpt_entry_idx + 1))); + + // Set new emuMMC size and USER size. + mbr.partitions[0].size_sct = resized_cnt; + gpt->entries[gpt_entry_idx].lba_end = user_part.lba_end; + + // Update Main GPT. + gpt->header.num_part_ents = gpt_entry_idx + 1; + gpt->header.alt_lba = resized_cnt - 1; + gpt->header.last_use_lba = resized_cnt - 34; + gpt->header.part_ents_crc32 = crc32_calc(0, (const u8 *)gpt->entries, sizeof(gpt_entry_t) * gpt->header.num_part_ents); + gpt->header.crc32 = 0; // Set to 0 for calculation. + gpt->header.crc32 = crc32_calc(0, (const u8 *)&gpt->header, gpt->header.size); + + // Update Backup GPT. + gpt_hdr_backup.my_lba = resized_cnt - 1; + gpt_hdr_backup.part_ent_lba = resized_cnt - 33; + gpt_hdr_backup.part_ents_crc32 = gpt->header.part_ents_crc32; + gpt_hdr_backup.last_use_lba = gpt->header.last_use_lba; + gpt_hdr_backup.crc32 = 0; // Set to 0 for calculation. + gpt_hdr_backup.crc32 = crc32_calc(0, (const u8 *)&gpt_hdr_backup, gpt_hdr_backup.size); + + res = 1; + if(file_based){ + // Write main GPT + res &= emummc_storage_file_based_write(gpt->header.my_lba, sizeof(gpt_t) >> 9, gpt); + // Write backup GPT partition table. + res &= emummc_storage_file_based_write(gpt_hdr_backup.part_ent_lba, ((sizeof(gpt_entry_t) * 128) >> 9), gpt->entries); + // Write backup GPT header. + res &= emummc_storage_file_based_write(gpt_hdr_backup.my_lba, 1, &gpt_hdr_backup); + // Write MBR. + res &= emummc_storage_file_based_write(0, 1, &mbr); + // Clear nand patrol. + memset(buf, 0, EMMC_BLOCKSIZE); + res &= emummc_storage_file_based_write(NAND_PATROL_SECTOR, 1, buf); + }else{ + // Write main GPT. + res &= sdmmc_storage_write(raw_based_storage, raw_based_sector_offset + gpt->header.my_lba, sizeof(gpt_t) >> 9, gpt); + // Write backup GPT partition table. + res &= sdmmc_storage_write(raw_based_storage, raw_based_sector_offset + gpt_hdr_backup.part_ent_lba, ((sizeof(gpt_entry_t) * 128) >> 9), gpt->entries); + // Write backup GPT header. + res &= sdmmc_storage_write(raw_based_storage, raw_based_sector_offset + gpt_hdr_backup.my_lba, 1, &gpt_hdr_backup); + // Write MBR. + res &= sdmmc_storage_write(raw_based_storage, raw_based_sector_offset, 1, &mbr); + // Clear nand patrol. + memset(buf, 0, EMMC_BLOCKSIZE); + res &= sdmmc_storage_write(raw_based_storage, raw_based_sector_offset + NAND_PATROL_SECTOR, 1, buf); + } + + if(!res){ + s_printf(gui->txt_buf, "\n#FF0000 Failed to write GPT...#\nPlease try again...\n"); + lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf); + free(gpt); + free(buf); + emummc_storage_file_based_end(); + + return FR_DISK_ERR; + } + + emummc_storage_file_based_end(); + + free(gpt); + free(buf); + return FR_OK; +} + void load_emummc_cfg(emummc_cfg_t *emu_info) { memset(emu_info, 0, sizeof(emummc_cfg_t)); @@ -75,26 +246,45 @@ void load_emummc_cfg(emummc_cfg_t *emu_info) ini_free(&ini_sections); } -void save_emummc_cfg(u32 part_idx, u32 sector_start, const char *path) +void save_emummc_cfg(u32 part_idx, u32 sector_start, const char *path, u8 drive) { - sd_mount(); + boot_storage_mount(); char lbuf[16]; FIL fp; - if (f_open(&fp, "emuMMC/emummc.ini", FA_WRITE | FA_CREATE_ALWAYS) != FR_OK) + int res = 0; + + res = f_mkdir("emuMMC"); + if(res != FR_OK && res != FR_EXIST){ return; + } + + res = f_open(&fp, "emuMMC/emummc.ini", FA_WRITE | FA_CREATE_ALWAYS); + if (res != FR_OK){ + return; + } // Add config entry. - f_puts("[emummc]\nenabled=", &fp); - if (part_idx && sector_start) + res = f_puts("[emummc]\nenabled=", &fp); + gfx_printf("puts %d\n", res); + if (part_idx && sector_start && drive == DRIVE_SD) { + // 1: part. 1, 2: part. 2, 3: part. 3 itoa(part_idx, lbuf, 10); f_puts(lbuf, &fp); + }else if(drive == DRIVE_EMMC && sector_start && part_idx){ + // 4: emmc raw based + f_puts("4", &fp); } - else if (path) + else if (path && drive == DRIVE_SD) + // 1: enabled, file based f_puts("1", &fp); - else + else if(path && drive == DRIVE_EMMC){ + // 4: enabled, emmc file based + f_puts("4", &fp); + }else + // 0: disable f_puts("0", &fp); if (!sector_start) @@ -113,8 +303,9 @@ void save_emummc_cfg(u32 part_idx, u32 sector_start, const char *path) // Get ID from path. u32 id_from_path = 0; - if (path && strlen(path) >= 4) + if (path && strlen(path) >= 4){ memcpy(&id_from_path, path + strlen(path) - 4, 4); + } f_puts("\nid=0x", &fp); itoa(id_from_path, lbuf, 16); f_puts(lbuf, &fp); @@ -142,22 +333,109 @@ void update_emummc_base_folder(char *outFilename, u32 sdPathLen, u32 currPartIdx itoa(currPartIdx, &outFilename[sdPathLen], 10); } -static int _dump_emummc_file_part(emmc_tool_gui_t *gui, char *sd_path, sdmmc_storage_t *storage, const emmc_part_t *part) +static int _emummc_raw_derive_bis_keys(emmc_tool_gui_t *gui, u32 resized_count) +{ + if (!resized_count) + return 1; + + bool error = false; + + char *txt_buf = (char *)malloc(SZ_16K); + txt_buf[0] = 0; + + // Generate BIS keys. + hos_bis_keygen(); + + u8 *cal0_buff = malloc(SZ_64K); + + // Read and decrypt CAL0 for validation of working BIS keys. + emmc_set_partition(EMMC_GPP); + LIST_INIT(gpt); + emmc_gpt_parse(&gpt); + // reads from emummc, if enabled + emmc_part_t *cal0_part = emmc_part_find(&gpt, "PRODINFO"); // check if null + nx_emmc_bis_init(cal0_part, false, NULL, 0); + nx_emmc_bis_read(0, 0x40, cal0_buff); + nx_emmc_bis_end(); + emmc_gpt_free(&gpt); + + nx_emmc_cal0_t *cal0 = (nx_emmc_cal0_t *)cal0_buff; + + // Check keys validity. + if (memcmp(&cal0->magic, "CAL0", 4)) + { + // Clear EKS keys. + hos_eks_clear(HOS_MKEY_VER_MAX); + + strcpy(txt_buf, "#FFDD00 BIS keys validation failed!#\n"); + error = true; + } + + free(cal0_buff); + + if (error) + { + 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); + + static const char * mbox_btn_map[] = { "\251", "\222Close", "\251", "" }; + lv_obj_t * mbox = lv_mbox_create(dark_bg, NULL); + lv_mbox_set_recolor_text(mbox, true); + lv_obj_set_width(mbox, LV_HOR_RES / 9 * 5); + + lv_mbox_set_text(mbox, "#C7EA46 BIS Keys Generation#"); + + lv_obj_t * lb_desc = lv_label_create(mbox, NULL); + lv_label_set_long_mode(lb_desc, LV_LABEL_LONG_BREAK); + lv_label_set_recolor(lb_desc, true); + lv_label_set_style(lb_desc, &monospace_text); + lv_obj_set_width(lb_desc, LV_HOR_RES / 9 * 4); + + lv_label_set_text(lb_desc, txt_buf); + lv_mbox_add_btns(mbox, mbox_btn_map, mbox_action); + + lv_obj_align(mbox, NULL, LV_ALIGN_CENTER, 0, 0); + lv_obj_set_top(mbox, true); + + free(txt_buf); + + return 0; + } + + free(txt_buf); + + return 1; +} + +static int _dump_emummc_file_part(emmc_tool_gui_t *gui, char *sd_path, sdmmc_storage_t *storage, emmc_part_t *part, u32 resized_cnt, u8 drive) { static const u32 FAT32_FILESIZE_LIMIT = 0xFFFFFFFF; static const u32 SECTORS_TO_MIB_COEFF = 11; u32 multipartSplitSize = 0xFE000000; - u32 totalSectors = part->lba_end - part->lba_start + 1; + u32 sectors_left = resized_cnt ? resized_cnt : part->lba_end - part->lba_start + 1; + u32 total_sectors = sectors_left; u32 currPartIdx = 0; u32 numSplitParts = 0; int res = 0; char *outFilename = sd_path; u32 sdPathLen = strlen(sd_path); + u32 free_space; + + FATFS *fs = drive == DRIVE_SD ? &sd_fs : &emmc_fs; + if(drive == DRIVE_SD){ + free_space = (u32)((fs->free_clst * fs->csize) >> SECTORS_TO_MIB_COEFF); + s_printf(gui->txt_buf, "#96FF00 SD Card free space:# %d MiB\n#96FF00 Total size:# %d MiB\n\n", + free_space, + sectors_left >> SECTORS_TO_MIB_COEFF); + }else{ + free_space = (u32)((fs->free_clst * fs->csize) >> SECTORS_TO_MIB_COEFF); + s_printf(gui->txt_buf, "#96FF00 eMMC free space:# %d MiB\n#96FF00 Total size:# %d MiB\n\n", + free_space, + sectors_left >> SECTORS_TO_MIB_COEFF); + } - s_printf(gui->txt_buf, "#96FF00 SD Card free space:# %d MiB\n#96FF00 Total size:# %d MiB\n\n", - (u32)(sd_fs.free_clst * sd_fs.csize >> SECTORS_TO_MIB_COEFF), - totalSectors >> SECTORS_TO_MIB_COEFF); lv_label_ins_text(gui->label_info, LV_LABEL_POS_LAST, gui->txt_buf); manual_system_maintenance(true); @@ -166,7 +444,7 @@ static int _dump_emummc_file_part(emmc_tool_gui_t *gui, char *sd_path, sdmmc_sto manual_system_maintenance(true); // Check if the USER partition or the RAW eMMC fits the sd card free space. - if (totalSectors > (sd_fs.free_clst * sd_fs.csize)) + if (sectors_left > (fs->free_clst * fs->csize)) { s_printf(gui->txt_buf, "\n#FFDD00 Not enough free space for file based emuMMC!#\n"); lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf); @@ -176,15 +454,16 @@ static int _dump_emummc_file_part(emmc_tool_gui_t *gui, char *sd_path, sdmmc_sto } // Check if filesystem is FAT32 or the free space is smaller and dump in parts. - if (totalSectors > (FAT32_FILESIZE_LIMIT / EMMC_BLOCKSIZE)) + if (sectors_left > (FAT32_FILESIZE_LIMIT / EMMC_BLOCKSIZE)) { u32 multipartSplitSectors = multipartSplitSize / EMMC_BLOCKSIZE; - numSplitParts = (totalSectors + multipartSplitSectors - 1) / multipartSplitSectors; + numSplitParts = (sectors_left + multipartSplitSectors - 1) / multipartSplitSectors; // Get first part filename. update_emummc_base_folder(outFilename, sdPathLen, 0); } + FIL fp; s_printf(gui->txt_buf, "#96FF00 Filepath:#\n%s\n#96FF00 Filename:# #FF8000 %s#", gui->base_path, outFilename + strlen(gui->base_path)); @@ -201,6 +480,25 @@ static int _dump_emummc_file_part(emmc_tool_gui_t *gui, char *sd_path, sdmmc_sto return 0; } + u32 user_offset = 0; + if(resized_cnt){ + gpt_t *gpt = zalloc(sizeof(*gpt)); + sdmmc_storage_read(&emmc_storage, 1, sizeof(*gpt) / 0x200, gpt); + + s32 gpt_idx = gpt_get_part_by_name(gpt, "USER", -1); + + if(gpt_idx == -1){ + s_printf(gui->txt_buf, "\n#FFDD00 USER partition not found!#\n"); + lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf); + manual_system_maintenance(true); + free(gpt); + return 0; + } + user_offset = gpt->entries[gpt_idx].lba_start; + part->lba_end = user_offset - 1; + free(gpt); + } + u8 *buf = (u8 *)MIXD_BUF_ALIGNED; u32 lba_curr = part->lba_start; @@ -209,18 +507,25 @@ static int _dump_emummc_file_part(emmc_tool_gui_t *gui, char *sd_path, sdmmc_sto int retryCount = 0; DWORD *clmt = NULL; - u64 totalSize = (u64)((u64)totalSectors << 9); - if (totalSize <= FAT32_FILESIZE_LIMIT) - clmt = f_expand_cltbl(&fp, SZ_4M, totalSize); + // total size to copy from emmc, excludes USER, if resize_cnt is set + u32 copy_sectors = part->lba_end - part->lba_start + 1; + // u64 copy_size = (u64)copy_sectors << (u64)9; + + u64 total_size = (u64)sectors_left << (u64)9; + + // use total sectors (includes USER) + if (total_size <= FAT32_FILESIZE_LIMIT) + clmt = f_expand_cltbl(&fp, SZ_4M, total_size); else - clmt = f_expand_cltbl(&fp, SZ_4M, MIN(totalSize, multipartSplitSize)); + clmt = f_expand_cltbl(&fp, SZ_4M, MIN(total_size, multipartSplitSize)); u32 num = 0; u32 pct = 0; + lv_obj_set_opa_scale(gui->bar, LV_OPA_COVER); lv_obj_set_opa_scale(gui->label_pct, LV_OPA_COVER); - while (totalSectors > 0) + while (sectors_left > 0) { if (numSplitParts != 0 && bytesWritten >= multipartSplitSize) { @@ -249,8 +554,8 @@ static int _dump_emummc_file_part(emmc_tool_gui_t *gui, char *sd_path, sdmmc_sto bytesWritten = 0; - totalSize = (u64)((u64)totalSectors << 9); - clmt = f_expand_cltbl(&fp, SZ_4M, MIN(totalSize, multipartSplitSize)); + total_size = (u64)((u64)sectors_left << 9); + clmt = f_expand_cltbl(&fp, SZ_4M, MIN(total_size, multipartSplitSize)); } // Check for cancellation combo. @@ -269,22 +574,49 @@ static int _dump_emummc_file_part(emmc_tool_gui_t *gui, char *sd_path, sdmmc_sto return 0; } - retryCount = 0; - num = MIN(totalSectors, NUM_SECTORS_PER_ITER); + if(copy_sectors){ + retryCount = 0; + num = MIN(copy_sectors, NUM_SECTORS_PER_ITER); - while (!sdmmc_storage_read(storage, lba_curr, num, buf)) - { - s_printf(gui->txt_buf, - "\n#FFDD00 Error reading %d blocks @ LBA %08X,#\n" - "#FFDD00 from eMMC (try %d). #", - num, lba_curr, ++retryCount); - lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf); - manual_system_maintenance(true); - - msleep(150); - if (retryCount >= 3) + while (!sdmmc_storage_read(storage, lba_curr, num, buf)) { - s_printf(gui->txt_buf, "#FF0000 Aborting...#\nPlease try again...\n"); + s_printf(gui->txt_buf, + "\n#FFDD00 Error reading %d blocks @ LBA %08X,#\n" + "#FFDD00 from eMMC (try %d). #", + num, lba_curr, ++retryCount); + lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf); + manual_system_maintenance(true); + + msleep(150); + if (retryCount >= 3) + { + 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); + + f_close(&fp); + free(clmt); + f_unlink(outFilename); + + return 0; + } + else + { + s_printf(gui->txt_buf, "#FFDD00 Retrying...#"); + lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf); + manual_system_maintenance(true); + } + } + + manual_system_maintenance(false); + + res = f_write_fast(&fp, buf, EMMC_BLOCKSIZE * num); + + manual_system_maintenance(false); + + if (res) + { + s_printf(gui->txt_buf, "\n#FF0000 Fatal error (%d) when writing to %s#\nPlease try again...\n", res, drive == DRIVE_SD ? "SD Card" : "eMMC"); lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf); manual_system_maintenance(true); @@ -294,33 +626,16 @@ static int _dump_emummc_file_part(emmc_tool_gui_t *gui, char *sd_path, sdmmc_sto return 0; } - else - { - s_printf(gui->txt_buf, "#FFDD00 Retrying...#"); - lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf); - manual_system_maintenance(true); - } + + copy_sectors -= num; + }else{ + // no more data to copy, keep seeking + u32 multipartSplitSizeSct = multipartSplitSize >> 9; + num = multipartSplitSizeSct - (lba_curr % multipartSplitSizeSct); + num = MIN(sectors_left, num); } - manual_system_maintenance(false); - - res = f_write_fast(&fp, buf, EMMC_BLOCKSIZE * num); - - manual_system_maintenance(false); - - if (res) - { - s_printf(gui->txt_buf, "\n#FF0000 Fatal error (%d) when writing to SD Card#\nPlease try again...\n", res); - lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf); - manual_system_maintenance(true); - - f_close(&fp); - free(clmt); - f_unlink(outFilename); - - return 0; - } - pct = (u64)((u64)(lba_curr - part->lba_start) * 100u) / (u64)(part->lba_end - part->lba_start); + pct = (u64)((u64)(lba_curr - part->lba_start) * 100u) / (u64)(total_sectors); if (pct != prevPct) { lv_bar_set_value(gui->bar, pct); @@ -332,7 +647,7 @@ static int _dump_emummc_file_part(emmc_tool_gui_t *gui, char *sd_path, sdmmc_sto } lba_curr += num; - totalSectors -= num; + sectors_left -= num; bytesWritten += num * EMMC_BLOCKSIZE; // Force a flush after a lot of data if not splitting. @@ -344,18 +659,26 @@ static int _dump_emummc_file_part(emmc_tool_gui_t *gui, char *sd_path, sdmmc_sto manual_system_maintenance(false); } + // Operation ended successfully. + f_close(&fp); + free(clmt); lv_bar_set_value(gui->bar, 100); lv_label_set_text(gui->label_pct, " "SYMBOL_DOT" 100%"); manual_system_maintenance(true); - // Operation ended successfully. - f_close(&fp); - free(clmt); + if(resized_cnt){ + lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, "Done!"); + manual_system_maintenance(true); + sd_path[sdPathLen] = '\0'; + if(_emummc_resize_user(gui, user_offset, resized_cnt, NULL, 0, sd_path, drive) != FR_OK){ + return 0; + } + } return 1; } -void dump_emummc_file(emmc_tool_gui_t *gui) +void dump_emummc_file(emmc_tool_gui_t *gui, u32 resized_cnt, u8 drive) { int res = 0; int base_len = 0; @@ -370,17 +693,28 @@ void dump_emummc_file(emmc_tool_gui_t *gui) manual_system_maintenance(true); - if (!sd_mount()) - { - lv_label_set_text(gui->label_info, "#FFDD00 Failed to init SD!#"); - goto out; + boot_storage_mount(); + + if(drive == DRIVE_SD){ + if (!sd_mount()) + { + lv_label_set_text(gui->label_info, "#FFDD00 Failed to init SD!#"); + goto out; + } + }else{ + if (!emmc_mount()) + { + lv_label_set_text(gui->label_info, "#FFDD00 Failed to init eMMC!#"); + goto out; + } } lv_label_set_text(gui->label_info, "Checking for available free space..."); manual_system_maintenance(true); // Get SD Card free space for file based emuMMC. - f_getfree("", &sd_fs.free_clst, NULL); + // already done right before + // f_getfree("sd:", &sd_fs.free_clst, NULL); if (!emmc_initialize(false)) { @@ -388,23 +722,42 @@ void dump_emummc_file(emmc_tool_gui_t *gui) goto out; } + if (!_emummc_raw_derive_bis_keys(gui, resized_cnt)) + { + s_printf(gui->txt_buf, "#FFDD00 For formatting USER partition,#\n#FFDD00 BIS keys are needed!#\n"); + lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf); + emmc_end(); + goto out; + } + int i = 0; char sdPath[OUT_FILENAME_SZ]; // Create Restore folders, if they do not exist. - f_mkdir("emuMMC"); - strcpy(sdPath, "emuMMC/SD"); - base_len = strlen(sdPath); + if(drive == DRIVE_SD){ + strcpy(sdPath, "sd:emuMMC/SD"); + f_mkdir("sd:emuMMC"); + }else{ + strcpy(sdPath, "emmc:emuMMC/EMMC"); + f_mkdir("emmc:emuMMC"); + } + + //also create on boot storage + f_mkdir("emuMMC"); + + base_len = strlen(sdPath); for (int j = 0; j < 100; j++) { update_emummc_base_folder(sdPath, base_len, j); if (f_stat(sdPath, NULL) == FR_NO_FILE) break; } - f_mkdir(sdPath); + f_mkdir(sdPath + (drive == DRIVE_SD ? 3 : 5)); + strcat(sdPath, "/eMMC"); f_mkdir(sdPath); + strcat(sdPath, "/"); strcpy(gui->base_path, sdPath); @@ -432,7 +785,7 @@ void dump_emummc_file(emmc_tool_gui_t *gui) emmc_set_partition(i + 1); strcat(sdPath, bootPart.name); - res = _dump_emummc_file_part(gui, sdPath, &emmc_storage, &bootPart); + res = _dump_emummc_file_part(gui, sdPath, &emmc_storage, &bootPart, 0, drive); if (!res) { @@ -452,22 +805,22 @@ void dump_emummc_file(emmc_tool_gui_t *gui) emmc_set_partition(EMMC_GPP); // Get GP partition size dynamically. - const u32 RAW_AREA_NUM_SECTORS = emmc_storage.sec_cnt; + u32 raw_num_sectors = emmc_storage.sec_cnt; emmc_part_t rawPart; memset(&rawPart, 0, sizeof(rawPart)); rawPart.lba_start = 0; - rawPart.lba_end = RAW_AREA_NUM_SECTORS - 1; + rawPart.lba_end = raw_num_sectors - 1; strcpy(rawPart.name, "GPP"); s_printf(txt_buf, "#00DDFF %02d: %s#\n#00DDFF Range: 0x%08X - 0x%08X#\n\n", - i, rawPart.name, rawPart.lba_start, rawPart.lba_end); + i, rawPart.name, resized_cnt ? resized_cnt : rawPart.lba_start, rawPart.lba_end); lv_label_set_text(gui->label_info, txt_buf); s_printf(txt_buf, "%02d: %s... ", i, rawPart.name); lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, txt_buf); manual_system_maintenance(true); - res = _dump_emummc_file_part(gui, sdPath, &emmc_storage, &rawPart); + res = _dump_emummc_file_part(gui, sdPath, &emmc_storage, &rawPart, resized_cnt, drive); if (!res) s_printf(txt_buf, "#FFDD00 Failed!#\n"); @@ -479,20 +832,23 @@ void dump_emummc_file(emmc_tool_gui_t *gui) out_failed: timer = get_tmr_s() - timer; - emmc_end(); if (res) { s_printf(txt_buf, "Time taken: %dm %ds.\nFinished!", timer / 60, timer % 60); gui->base_path[strlen(gui->base_path) - 5] = '\0'; strcpy(sdPath, gui->base_path); - strcat(sdPath, "file_based"); + if(drive == DRIVE_SD){ + strcat(sdPath, "file_based"); + }else{ + strcat(sdPath, "file_emmc_based"); + } FIL fp; - f_open(&fp, sdPath, FA_CREATE_ALWAYS | FA_WRITE); + f_open(&fp, sdPath + (drive == DRIVE_SD ? 3 : 5) /* strip drive prefix*/, FA_CREATE_ALWAYS | FA_WRITE); f_close(&fp); gui->base_path[strlen(gui->base_path) - 1] = 0; - save_emummc_cfg(0, 0, gui->base_path); + save_emummc_cfg(0, 0, gui->base_path + (drive == DRIVE_SD ? 3 : 5), drive); } else s_printf(txt_buf, "Time taken: %dm %ds.", timer / 60, timer % 60); @@ -503,9 +859,10 @@ out: free(txt_buf); free(gui->base_path); sd_unmount(); + emmc_end(); } -static int _dump_emummc_raw_part(emmc_tool_gui_t *gui, int active_part, int part_idx, u32 sd_part_off, emmc_part_t *part, u32 resized_count) +static int _dump_emummc_raw_part(emmc_tool_gui_t *gui, int active_part, int part_idx, u32 sd_part_off, emmc_part_t *part, u32 resized_count, u8 drive) { u32 num = 0; u32 pct = 0; @@ -515,6 +872,10 @@ static int _dump_emummc_raw_part(emmc_tool_gui_t *gui, int active_part, int part u32 lba_curr = part->lba_start; u8 *buf = (u8 *)MIXD_BUF_ALIGNED; + u32 cur_emmc_part = emmc_storage.partition; + + sdmmc_storage_t *emu_storge = drive == DRIVE_SD ? &sd_storage : &emmc_storage; + s_printf(gui->txt_buf, "\n\n\n"); lv_label_ins_text(gui->label_info, LV_LABEL_POS_LAST, gui->txt_buf); manual_system_maintenance(true); @@ -537,6 +898,7 @@ static int _dump_emummc_raw_part(emmc_tool_gui_t *gui, int active_part, int part { // Get USER partition info. LIST_INIT(gpt_parsed); + // NOTE: reads from emummc, if enabled emmc_gpt_parse(&gpt_parsed); emmc_part_t *user_part = emmc_part_find(&gpt_parsed, "USER"); if (!user_part) @@ -572,6 +934,9 @@ static int _dump_emummc_raw_part(emmc_tool_gui_t *gui, int active_part, int part num = MIN(totalSectors, NUM_SECTORS_PER_ITER); // Read data from eMMC. + if(emmc_storage.partition != cur_emmc_part){ + emmc_set_partition(cur_emmc_part); + } while (!sdmmc_storage_read(&emmc_storage, lba_curr, num, buf)) { s_printf(gui->txt_buf, @@ -602,12 +967,17 @@ static int _dump_emummc_raw_part(emmc_tool_gui_t *gui, int active_part, int part // Write data to SD card. retryCount = 0; - while (!sdmmc_storage_write(&sd_storage, sd_sector_off + lba_curr, num, buf)) + if(drive == DRIVE_EMMC){ + if(emmc_storage.partition != EMMC_GPP){ + emmc_set_partition(EMMC_GPP); + } + } + while (!sdmmc_storage_write(emu_storge, sd_sector_off + lba_curr, num, buf)) { s_printf(gui->txt_buf, "\n#FFDD00 Error writing %d blocks @LBA %08X,#\n" - "#FFDD00 to SD (try %d). #", - num, lba_curr, ++retryCount); + "#FFDD00 to %s (try %d). #", + num, lba_curr, drive == DRIVE_SD ? "SD" : "eMMC", ++retryCount); lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf); manual_system_maintenance(true); @@ -649,7 +1019,7 @@ static int _dump_emummc_raw_part(emmc_tool_gui_t *gui, int active_part, int part manual_system_maintenance(true); // Set partition type to emuMMC (0xE0). - if (active_part == 2) + if (active_part == 2 && drive == DRIVE_SD) { mbr_t mbr; sdmmc_storage_read(&sd_storage, 0, 1, &mbr); @@ -661,169 +1031,15 @@ static int _dump_emummc_raw_part(emmc_tool_gui_t *gui, int active_part, int part { lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, "Done!\n"); - // Calculate USER size and set it for FatFS. - u32 user_sectors = resized_count - user_offset - 33; - user_sectors = ALIGN_DOWN(user_sectors, 0x20); // Align down to cluster size. - disk_set_info(DRIVE_EMU, SET_SECTOR_COUNT, &user_sectors); - - // Initialize BIS for emuMMC. BIS keys should be already in place. - emmc_part_t user_part = {0}; - user_part.lba_start = user_offset; - user_part.lba_end = user_offset + user_sectors - 1; - strcpy(user_part.name, "USER"); - nx_emmc_bis_init(&user_part, true, sd_sector_off); - - s_printf(gui->txt_buf, "Formatting USER... "); - lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf); - manual_system_maintenance(true); - - // Format USER partition as FAT32 with 16KB cluster and PRF2SAFE. - u8 *buff = malloc(SZ_4M); - int mkfs_error = f_mkfs("emu:", FM_FAT32 | FM_SFD | FM_PRF2, 16384, buff, SZ_4M); - free(buff); - - // Mount sd card back. - sd_mount(); - - if (mkfs_error) - { - s_printf(gui->txt_buf, "#FF0000 Failed (%d)!#\nPlease try again...\n", mkfs_error); - lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf); - + if(_emummc_resize_user(gui, user_offset, resized_count, emu_storge, sd_sector_off, NULL, drive) != FR_OK){ return 0; } - lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, "Done!\n"); - - // Flush BIS cache, deinit, clear BIS keys slots and reinstate SBK. - nx_emmc_bis_end(); - hos_bis_keys_clear(); - - s_printf(gui->txt_buf, "Writing new GPT... "); - lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf); - manual_system_maintenance(true); - - // Read MBR, GPT and backup GPT. - mbr_t mbr; - gpt_t *gpt = zalloc(sizeof(gpt_t)); - gpt_header_t gpt_hdr_backup; - sdmmc_storage_read(&emmc_storage, 0, 1, &mbr); - sdmmc_storage_read(&emmc_storage, 1, sizeof(gpt_t) >> 9, gpt); - sdmmc_storage_read(&emmc_storage, gpt->header.alt_lba, 1, &gpt_hdr_backup); - - // Find USER partition. - u32 gpt_entry_idx = 0; - for (gpt_entry_idx = 0; gpt_entry_idx < gpt->header.num_part_ents; gpt_entry_idx++) - if (!memcmp(gpt->entries[gpt_entry_idx].name, (char[]) { 'U', 0, 'S', 0, 'E', 0, 'R', 0 }, 8)) - break; - - if (gpt_entry_idx >= gpt->header.num_part_ents) - { - s_printf(gui->txt_buf, "\n#FF0000 No USER partition...#\nPlease try again...\n"); - lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf); - free(gpt); - - return 0; - } - - // Set new emuMMC size and USER size. - mbr.partitions[0].size_sct = resized_count - 1; // Exclude MBR sector. - gpt->entries[gpt_entry_idx].lba_end = user_part.lba_end; - - // Update Main GPT. - gpt->header.alt_lba = resized_count - 1; - gpt->header.last_use_lba = resized_count - 34; - gpt->header.part_ents_crc32 = crc32_calc(0, (const u8 *)gpt->entries, sizeof(gpt_entry_t) * gpt->header.num_part_ents); - gpt->header.crc32 = 0; // Set to 0 for calculation. - gpt->header.crc32 = crc32_calc(0, (const u8 *)&gpt->header, gpt->header.size); - - // Update Backup GPT. - memcpy(&gpt_hdr_backup, &gpt->header, sizeof(gpt_header_t)); - gpt_hdr_backup.my_lba = resized_count - 1; - gpt_hdr_backup.alt_lba = 1; - gpt_hdr_backup.part_ent_lba = resized_count - 33; - gpt_hdr_backup.crc32 = 0; // Set to 0 for calculation. - gpt_hdr_backup.crc32 = crc32_calc(0, (const u8 *)&gpt_hdr_backup, gpt_hdr_backup.size); - - // Write main GPT. - sdmmc_storage_write(&sd_storage, sd_sector_off + gpt->header.my_lba, sizeof(gpt_t) >> 9, gpt); - - // Write backup GPT partition table. - sdmmc_storage_write(&sd_storage, sd_sector_off + gpt_hdr_backup.part_ent_lba, ((sizeof(gpt_entry_t) * 128) >> 9), gpt->entries); - - // Write backup GPT header. - sdmmc_storage_write(&sd_storage, sd_sector_off + gpt_hdr_backup.my_lba, 1, &gpt_hdr_backup); - - // Write MBR. - sdmmc_storage_write(&sd_storage, sd_sector_off, 1, &mbr); - - // Clear nand patrol. - memset(buf, 0, EMMC_BLOCKSIZE); - sdmmc_storage_write(&sd_storage, sd_part_off + NAND_PATROL_SECTOR, 1, buf); - - free(gpt); } return 1; } -int emummc_raw_derive_bis_keys() -{ - // Generate BIS keys. - hos_bis_keygen(); - - u8 *cal0_buff = malloc(SZ_64K); - - // Read and decrypt CAL0 for validation of working BIS keys. - emmc_set_partition(EMMC_GPP); - 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_read(0, 0x40, cal0_buff); - nx_emmc_bis_end(); - emmc_gpt_free(&gpt); - - nx_emmc_cal0_t *cal0 = (nx_emmc_cal0_t *)cal0_buff; - - // Check keys validity. - if (memcmp(&cal0->magic, "CAL0", 4)) - { - // Clear EKS keys. - hos_eks_clear(HOS_MKEY_VER_MAX); - - 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); - - static const char * mbox_btn_map[] = { "\251", "\222Close", "\251", "" }; - lv_obj_t * mbox = lv_mbox_create(dark_bg, NULL); - lv_mbox_set_recolor_text(mbox, true); - lv_obj_set_width(mbox, LV_HOR_RES / 9 * 5); - - lv_mbox_set_text(mbox, "#C7EA46 BIS Keys Generation#"); - - lv_obj_t * lb_desc = lv_label_create(mbox, NULL); - lv_label_set_long_mode(lb_desc, LV_LABEL_LONG_BREAK); - lv_label_set_recolor(lb_desc, true); - lv_label_set_style(lb_desc, &monospace_text); - lv_obj_set_width(lb_desc, LV_HOR_RES / 9 * 4); - - lv_label_set_text(lb_desc, "#FFDD00 BIS keys validation failed!#\n"); - lv_mbox_add_btns(mbox, mbox_btn_map, mbox_action); - - lv_obj_align(mbox, NULL, LV_ALIGN_CENTER, 0, 0); - lv_obj_set_top(mbox, true); - - free(cal0_buff); - return 0; - } - - free(cal0_buff); - - return 1; -} - -void dump_emummc_raw(emmc_tool_gui_t *gui, int part_idx, u32 sector_start, u32 resized_count) +void dump_emummc_raw(emmc_tool_gui_t *gui, int part_idx, u32 sector_start, u32 resized_count, u8 drive) { int res = 0; u32 timer = 0; @@ -837,7 +1053,11 @@ void dump_emummc_raw(emmc_tool_gui_t *gui, int part_idx, u32 sector_start, u32 r manual_system_maintenance(true); - if (!sd_mount()) + sdmmc_storage_t *emu_storage = drive == DRIVE_SD ? &sd_storage : &emmc_storage; + + boot_storage_mount(); + + if (drive == DRIVE_SD && !sd_initialize(false)) { lv_label_set_text(gui->label_info, "#FFDD00 Failed to init SD!#"); goto out; @@ -849,7 +1069,7 @@ void dump_emummc_raw(emmc_tool_gui_t *gui, int part_idx, u32 sector_start, u32 r goto out; } - if (resized_count && !emummc_raw_derive_bis_keys()) + if (!_emummc_raw_derive_bis_keys(gui, resized_count)) { s_printf(gui->txt_buf, "#FFDD00 For formatting USER partition,#\n#FFDD00 BIS keys are needed!#\n"); lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf); @@ -859,9 +1079,9 @@ void dump_emummc_raw(emmc_tool_gui_t *gui, int part_idx, u32 sector_start, u32 r int i = 0; char sdPath[OUT_FILENAME_SZ]; - // Create Restore folders, if they do not exist. + // Create folders, if they do not exist. f_mkdir("emuMMC"); - s_printf(sdPath, "emuMMC/RAW%d", part_idx); + s_printf(sdPath, drive == DRIVE_SD ? "emuMMC/RAW%d" : "emuMMC/RAW_EMMC%d", part_idx); f_mkdir(sdPath); strcat(sdPath, "/"); strcpy(gui->base_path, sdPath); @@ -876,7 +1096,7 @@ void dump_emummc_raw(emmc_tool_gui_t *gui, int part_idx, u32 sector_start, u32 r // Clear partition start. memset((u8 *)MIXD_BUF_ALIGNED, 0, SZ_16M); - sdmmc_storage_write(&sd_storage, sector_start - 0x8000, 0x8000, (u8 *)MIXD_BUF_ALIGNED); + sdmmc_storage_write(emu_storage, sector_start - 0x8000, 0x8000, (u8 *)MIXD_BUF_ALIGNED); for (i = 0; i < 2; i++) { @@ -894,7 +1114,7 @@ void dump_emummc_raw(emmc_tool_gui_t *gui, int part_idx, u32 sector_start, u32 r emmc_set_partition(i + 1); strcat(sdPath, bootPart.name); - res = _dump_emummc_raw_part(gui, i, part_idx, sector_start, &bootPart, 0); + res = _dump_emummc_raw_part(gui, i, part_idx, sector_start, &bootPart, 0, drive); if (!res) { @@ -928,7 +1148,7 @@ void dump_emummc_raw(emmc_tool_gui_t *gui, int part_idx, u32 sector_start, u32 r lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, txt_buf); manual_system_maintenance(true); - res = _dump_emummc_raw_part(gui, 2, part_idx, sector_start, &rawPart, resized_count); + res = _dump_emummc_raw_part(gui, 2, part_idx, sector_start, &rawPart, resized_count, drive); if (!res) s_printf(txt_buf, "#FFDD00 Failed!#\n"); @@ -941,20 +1161,19 @@ void dump_emummc_raw(emmc_tool_gui_t *gui, int part_idx, u32 sector_start, u32 r out_failed: timer = get_tmr_s() - timer; - emmc_end(); if (res) { s_printf(txt_buf, "Time taken: %dm %ds.\nFinished!", timer / 60, timer % 60); strcpy(sdPath, gui->base_path); - strcat(sdPath, "raw_based"); + strcat(sdPath, drive == DRIVE_SD ? "raw_based" : "raw_emmc_based"); FIL fp; f_open(&fp, sdPath, FA_CREATE_ALWAYS | FA_WRITE); f_write(&fp, §or_start, 4, NULL); f_close(&fp); gui->base_path[strlen(gui->base_path) - 1] = 0; - save_emummc_cfg(part_idx, sector_start, gui->base_path); + save_emummc_cfg(part_idx, sector_start, gui->base_path, drive); } else s_printf(txt_buf, "Time taken: %dm %ds.", timer / 60, timer % 60); @@ -964,5 +1183,6 @@ out_failed: out: free(txt_buf); free(gui->base_path); - sd_unmount(); + boot_storage_unmount(); + emmc_end(); } diff --git a/nyx/nyx_gui/frontend/fe_emummc_tools.h b/nyx/nyx_gui/frontend/fe_emummc_tools.h index 784af8fa..6bb15b9f 100644 --- a/nyx/nyx_gui/frontend/fe_emummc_tools.h +++ b/nyx/nyx_gui/frontend/fe_emummc_tools.h @@ -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 diff --git a/nyx/nyx_gui/frontend/gui.c b/nyx/nyx_gui/frontend/gui.c index 2bb2b3e4..231efaf3 100644 --- a/nyx/nyx_gui/frontend/gui.c +++ b/nyx/nyx_gui/frontend/gui.c @@ -19,6 +19,7 @@ #include #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 +#include 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; } diff --git a/nyx/nyx_gui/frontend/gui.h b/nyx/nyx_gui/frontend/gui.h index 2db45c52..dd864d91 100644 --- a/nyx/nyx_gui/frontend/gui.h +++ b/nyx/nyx_gui/frontend/gui.h @@ -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; diff --git a/nyx/nyx_gui/frontend/gui_emmc_tools.c b/nyx/nyx_gui/frontend/gui_emmc_tools.c index 775002fc..4c3aa2a7 100644 --- a/nyx/nyx_gui/frontend/gui_emmc_tools.c +++ b/nyx/nyx_gui/frontend/gui_emmc_tools.c @@ -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; diff --git a/nyx/nyx_gui/frontend/gui_emu_tools.c b/nyx/nyx_gui/frontend/gui_emu_tools.c new file mode 100644 index 00000000..fc34fdc1 --- /dev/null +++ b/nyx/nyx_gui/frontend/gui_emu_tools.c @@ -0,0 +1,50 @@ +#include "gui_emu_tools.h" +#include "gui.h" +#include "gui_emummc_tools.h" +#include +#include +#include +#include + +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; +} + diff --git a/nyx/nyx_gui/frontend/gui_emu_tools.h b/nyx/nyx_gui/frontend/gui_emu_tools.h new file mode 100644 index 00000000..7efc7970 --- /dev/null +++ b/nyx/nyx_gui/frontend/gui_emu_tools.h @@ -0,0 +1,8 @@ +#ifndef _GUI_EMU_TOOLS_H_ +#define _GUI_EMU_TOOLS_H_ + +#include + +lv_res_t create_win_emu_tools(lv_obj_t *btn); + +#endif \ No newline at end of file diff --git a/nyx/nyx_gui/frontend/gui_emummc_tools.c b/nyx/nyx_gui/frontend/gui_emummc_tools.c index efa17c53..b8061227 100644 --- a/nyx/nyx_gui/frontend/gui_emummc_tools.c +++ b/nyx/nyx_gui/frontend/gui_emummc_tools.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019-2025 CTCaer + * Copyright (c) 2019-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, @@ -14,6 +14,17 @@ * along with this program. If not, see . */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include #include @@ -22,31 +33,59 @@ #include "fe_emummc_tools.h" #include "gui_tools_partition_manager.h" #include +#include +#include +#include +#include +#include +#include extern char *emmcsn_path_impl(char *path, char *sub_dir, char *filename, sdmmc_storage_t *storage); +typedef struct _emummc_part_cfg_t{ + u8 drive; + bool file_based; + u32 sector; + u32 resized_cnt; + u32 part_idx; +} emummc_part_cfg_t; + typedef struct _mbr_ctxt_t { u32 available; u32 sector[3]; u32 resized_cnt[3]; + u32 part_size[3]; int part_idx; u32 sector_start; } mbr_ctxt_t; +typedef struct _gpt_ctxt_t +{ + s32 emmc_part_idx[3]; + u32 emmc_part_size[3]; + u32 emmc_part_offset[3]; + u32 emmc_part_resize_cnt[3]; + u8 emmc_part_cnt; +} gpt_ctxt_t; + + +static u32 emmc_safe_size; static bool emummc_backup; static mbr_ctxt_t mbr_ctx; -static lv_obj_t *emummc_manage_window; -static lv_res_t (*emummc_tools)(lv_obj_t *btn); +static lv_obj_t *emummc_parent_cont; +static lv_res_t (*emummc_tools)(lv_obj_t *parent); +static gpt_ctxt_t gpt_ctx; +static emummc_part_cfg_t emummc_part_cfg; static lv_res_t _action_emummc_window_close(lv_obj_t *btn) { nyx_win_close_action_custom(btn); // Delete and relaunch main emuMMC window. - lv_obj_del(emummc_manage_window); - (*emummc_tools)(NULL); + lv_obj_clean(emummc_parent_cont); + (*emummc_tools)(emummc_parent_cont); return LV_RES_INV; } @@ -56,7 +95,7 @@ static void _create_window_emummc() emmc_tool_gui_t emmc_tool_gui_ctxt; lv_obj_t *win; - if (!mbr_ctx.part_idx) + if (emummc_part_cfg.file_based) win = nyx_create_window_custom_close_btn(SYMBOL_DRIVE" Create SD File emuMMC", _action_emummc_window_close); else win = nyx_create_window_custom_close_btn(SYMBOL_DRIVE" Create SD Partition emuMMC", _action_emummc_window_close); @@ -131,10 +170,10 @@ static void _create_window_emummc() lv_obj_align(label_finish, bar, LV_ALIGN_OUT_BOTTOM_LEFT, 0, LV_DPI * 9 / 20); emmc_tool_gui_ctxt.label_finish = label_finish; - if (!mbr_ctx.part_idx) - dump_emummc_file(&emmc_tool_gui_ctxt); + if (emummc_part_cfg.file_based) + dump_emummc_file(&emmc_tool_gui_ctxt, emummc_part_cfg.resized_cnt, emummc_part_cfg.drive); else - dump_emummc_raw(&emmc_tool_gui_ctxt, mbr_ctx.part_idx, mbr_ctx.sector_start, mbr_ctx.resized_cnt[mbr_ctx.part_idx - 1]); + dump_emummc_raw(&emmc_tool_gui_ctxt, emummc_part_cfg.part_idx, emummc_part_cfg.sector, emummc_part_cfg.resized_cnt, emummc_part_cfg.drive); nyx_window_toggle_buttons(win, false); } @@ -148,53 +187,186 @@ static lv_res_t _create_emummc_raw_format(lv_obj_t * btns, const char * txt) // Create partition window. if (!btn_idx) - create_window_sd_partition_manager(btns); + create_window_partition_manager(btns, DRIVE_SD); - mbr_ctx.part_idx = 0; - mbr_ctx.sector_start = 0; + memset(&emummc_part_cfg, 0, sizeof(emummc_part_cfg)); return LV_RES_INV; } -static lv_res_t _create_emummc_raw_action(lv_obj_t * btns, const char * txt) -{ - int btn_idx = lv_btnm_get_pressed(btns); - lv_obj_t *bg = lv_obj_get_parent(lv_obj_get_parent(btns)); +static int idx_selected; - mbr_ctx.sector_start = 0x8000; // Protective offset. +static void _create_emummc(u8 btn_idx){ + emummc_part_cfg.sector = 0x8000; // Protective offset. - switch (btn_idx) - { - case 0: - mbr_ctx.part_idx = 1; - mbr_ctx.sector_start += mbr_ctx.sector[0]; - break; - case 1: - mbr_ctx.part_idx = 2; - mbr_ctx.sector_start += mbr_ctx.sector[1]; - break; - case 2: - mbr_ctx.part_idx = 3; - mbr_ctx.sector_start += mbr_ctx.sector[2]; - break; - default: - break; - } - - if (btn_idx < 3) - { - lv_obj_set_style(bg, &lv_style_transp); + if(btn_idx < 3){ + emummc_part_cfg.drive = DRIVE_SD; + emummc_part_cfg.part_idx = btn_idx + 1; + emummc_part_cfg.resized_cnt = mbr_ctx.resized_cnt[btn_idx]; + emummc_part_cfg.sector += mbr_ctx.sector[btn_idx]; _create_window_emummc(); } - mbr_ctx.part_idx = 0; - mbr_ctx.sector_start = 0; + memset(&emummc_part_cfg, 0, sizeof(emummc_part_cfg)); +} + +static lv_res_t _ask_resize_action(lv_obj_t *btns, const char *txt){ + int btn_idx = lv_btnm_get_pressed(btns); + + switch(btn_idx){ + case 0: + // Yes resize + mbr_ctx.resized_cnt[idx_selected] = mbr_ctx.part_size[idx_selected] - 0xc000; + _create_emummc(idx_selected); + break; + case 1: + // No resize + _create_emummc(idx_selected); + break; + case 2: + // cancel + memset(&emummc_part_cfg, 0, sizeof(emummc_part_cfg)); + break; + } mbox_action(btns, txt); return LV_RES_INV; } +static void _create_mbox_ask_resize(){ + 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); + + lv_obj_t * mbox = lv_mbox_create(dark_bg, NULL); + lv_mbox_set_recolor_text(mbox, true); + lv_obj_set_width(mbox, LV_HOR_RES / 9 * 6); + + static const char *mbox_btns[] = { "\222Yes", "\222No", "\222Cancel", "" }; + lv_mbox_add_btns(mbox, mbox_btns, _ask_resize_action); + + lv_mbox_set_text(mbox, "#C7EA46 Selected partition is larger than required!#\n" + "Resize USER to use all available space?\n\n" + "#FFDD00 Note:# This will format USER"); + + lv_obj_align(mbox, NULL, LV_ALIGN_CENTER, 0, 0); +} + +static lv_res_t _create_emummc_raw_action(lv_obj_t * btns, const char * txt) +{ + idx_selected = lv_btnm_get_pressed(btns); + + if(idx_selected < 3){ + if(mbr_ctx.part_size[idx_selected] > emmc_safe_size + (0x8000 * 8)){ + // partition larger than required for full emmc, ask to resize + _create_mbox_ask_resize(); + }else{ + _create_emummc(idx_selected); + } + }else{ + // cancel + memset(&emummc_part_cfg, 0, sizeof(emummc_part_cfg)); + } + + mbox_action(btns, txt); + + return LV_RES_INV; +} + +static void _create_emummc_emmc(u8 btn_idx){ + emummc_part_cfg.sector = 0x8000; // Protective offset. + + if(btn_idx < gpt_ctx.emmc_part_cnt){ + emummc_part_cfg.part_idx = gpt_ctx.emmc_part_idx[btn_idx]; + emummc_part_cfg.drive = DRIVE_EMMC; + emummc_part_cfg.resized_cnt = gpt_ctx.emmc_part_resize_cnt[btn_idx]; + emummc_part_cfg.sector += gpt_ctx.emmc_part_offset[btn_idx]; + _create_window_emummc(); + } + + memset(&emummc_part_cfg, 0, sizeof(emummc_part_cfg)); +} + +static lv_res_t _ask_resize_action_emmc(lv_obj_t *btns, const char *txt){ + int btn_idx = lv_btnm_get_pressed(btns); + + switch(btn_idx){ + case 0: + // Yes resize + gpt_ctx.emmc_part_resize_cnt[idx_selected] = gpt_ctx.emmc_part_size[idx_selected] - 0xc000; + _create_emummc_emmc(idx_selected); + break; + case 1: + // No resize + _create_emummc_emmc(idx_selected); + break; + case 2: + // cancel + memset(&emummc_part_cfg, 0, sizeof(emummc_part_cfg)); + break; + } + + mbox_action(btns, txt); + + return LV_RES_INV; +} + +static void _create_mbox_ask_resize_emmc(){ + 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); + + lv_obj_t * mbox = lv_mbox_create(dark_bg, NULL); + lv_mbox_set_recolor_text(mbox, true); + lv_obj_set_width(mbox, LV_HOR_RES / 9 * 6); + + static const char *mbox_btns[] = { "\222Yes", "\222No", "\222Cancel", "" }; + lv_mbox_add_btns(mbox, mbox_btns, _ask_resize_action_emmc); + + lv_mbox_set_text(mbox, "#C7EA46 Selected partition is larger than required!#\n" + "Resize USER to use all available space?\n\n" + "#FFDD00 Note:# This will format USER"); + + lv_obj_align(mbox, NULL, LV_ALIGN_CENTER, 0, 0); +} + +static lv_res_t _create_emummc_emmc_raw_action(lv_obj_t *btns, const char *txt){ + idx_selected = lv_btnm_get_pressed(btns); + + if(idx_selected < gpt_ctx.emmc_part_cnt){ + if(gpt_ctx.emmc_part_size[idx_selected] > emmc_safe_size + (0x8000 * 8)){ + // partition larger than required for full emmc, ask to resize + _create_mbox_ask_resize_emmc(); + }else{ + _create_emummc_emmc(idx_selected); + } + }else{ + // cancel + memset(&emummc_part_cfg, 0, sizeof(emummc_part_cfg)); + } + + mbox_action(btns, txt); + + return LV_RES_INV; +} + +static lv_res_t _create_emummc_emmc_raw_format(lv_obj_t * btns, const char * txt) +{ + int btn_idx = lv_btnm_get_pressed(btns); + + // Delete parent mbox. + mbox_action(btns, txt); + + // Create partition window. + if (!btn_idx) + create_window_partition_manager(btns, DRIVE_EMMC); + + memset(&emummc_part_cfg, 0, sizeof(emummc_part_cfg)); + + return LV_RES_INV; +} + static void _create_mbox_emummc_raw() { lv_obj_t *dark_bg = lv_obj_create(lv_scr_act(), NULL); @@ -218,7 +390,7 @@ static void _create_mbox_emummc_raw() emmc_initialize(false); - u32 emmc_size_safe = emmc_storage.sec_cnt + 0xC000; // eMMC GPP size + BOOT0/1. + emmc_safe_size = emmc_storage.sec_cnt + 0xC000; // eMMC GPP size + BOOT0/1 + 16mb safety offset. emmc_end(); @@ -232,15 +404,17 @@ static void _create_mbox_emummc_raw() bool valid_part = (part_type != 0x83) && (part_type != 0xEE) && (part_type != 0xFF); // Check if at least 4GB and start above 16MB. - if ((part_size >= 0x80F000) && part_start > 0x8000 && valid_part) + if ((part_size >= 0x80F000) && part_start >= 0x8000 && valid_part) { mbr_ctx.available |= BIT(i - 1); mbr_ctx.sector[i - 1] = part_start; + mbr_ctx.part_size[i - 1] = part_size; - // Only allow up to 28GB resized emuMMC. - if (part_size <= 0x3810000) + // *Why?* Only allow up to 16GB resized emuMMC. + // if (part_size < 0x2010000) + if (part_size < emmc_safe_size) mbr_ctx.resized_cnt[i - 1] = part_size - 0xC000; // Save sectors count without protective size and BOOT0/1. - else if (part_size >= emmc_size_safe) + else if (part_size >= emmc_safe_size) mbr_ctx.resized_cnt[i - 1] = 0; else { @@ -309,23 +483,140 @@ static void _create_mbox_emummc_raw() lv_obj_set_top(mbox, true); } -static lv_res_t _create_emummc_action(lv_obj_t * btns, const char * txt) +static void _create_mbox_emummc_emmc_raw() { - int btn_idx = lv_btnm_get_pressed(btns); - lv_obj_t *bg = lv_obj_get_parent(lv_obj_get_parent(btns)); + // On SD, emummc partitions always have an MBR entry - mbr_ctx.part_idx = 0; - mbr_ctx.sector_start = 0; + 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); - switch (btn_idx) - { - case 0: - lv_obj_set_style(bg, &lv_style_transp); + static const char *mbox_btn_format[] = { "\222Continue", "\222Cancel", "" }; + lv_obj_t * mbox = lv_mbox_create(dark_bg, NULL); + lv_mbox_set_recolor_text(mbox, true); + lv_obj_set_width(mbox, LV_HOR_RES / 9 * 6); + + char *txt_buf = (char *)malloc(SZ_16K); + mbr_t *mbr = (mbr_t *)malloc(sizeof(mbr_t)); + gpt_t *gpt = zalloc(sizeof *gpt); + + memset(&gpt_ctx, 0, sizeof(gpt_ctx)); + + emmc_mount(); + emmc_safe_size = emmc_storage.sec_cnt + 0xc000; + + sdmmc_storage_read(&emmc_storage, 0, 1, mbr); + + bool has_gpt = mbr_has_gpt(mbr); + + if(has_gpt){ + sdmmc_storage_read(&emmc_storage, 1, sizeof(*gpt) / 0x200, gpt); + + // TODO: should check for emummc guid instead + // TODO: currently hard limited to 3 entries + s32 gpt_idx = gpt_get_part_by_name(gpt, "emummc", -1); + while(gpt_idx != -1){ + u32 offset = gpt->entries[gpt_idx].lba_start; + u32 size = gpt->entries[gpt_idx].lba_end - gpt->entries[gpt_idx].lba_start + 1; + + if(size >= 0x80f000 && offset >= 0x8000){ + gpt_ctx.emmc_part_idx[gpt_ctx.emmc_part_cnt] = gpt_idx; + gpt_ctx.emmc_part_size[gpt_ctx.emmc_part_cnt] = size; + gpt_ctx.emmc_part_offset[gpt_ctx.emmc_part_cnt] = offset; + + if(size < emmc_safe_size){ + gpt_ctx.emmc_part_resize_cnt[gpt_ctx.emmc_part_cnt] = size - 0xc000; + } + + gpt_ctx.emmc_part_cnt++; + } + + gpt_idx = gpt_get_part_by_name(gpt, "emummc", gpt_idx); + } + } + + emmc_end(); + + static char mbox_btn_parts_strs[5][16]; + static char *mbox_btn_parts[] = {(char*)&mbox_btn_parts_strs[0], (char*)&mbox_btn_parts_strs[1], (char*)&mbox_btn_parts_strs[2], (char*)&mbox_btn_parts_strs[3], (char*)&mbox_btn_parts_strs[4]}; + + if(gpt_ctx.emmc_part_cnt){ + s_printf(txt_buf, "#C7EA46 Found applicable partition(s)!#\n" + "#FF8000 Choose a partition to continue:#\n\n"); + for(u32 i = 0; i < gpt_ctx.emmc_part_cnt; i++){ + char name[36]; + wctombs(gpt->entries[gpt_ctx.emmc_part_idx[i]].name, name, 36); + s_printf(txt_buf + strlen(txt_buf), "#%s Part. %d (%s): Start: 0x%x, Size. 0x%x#\n", gpt_ctx.emmc_part_resize_cnt[i] ? "FFDD00" : "C0C0C0", gpt_ctx.emmc_part_idx[i], name, gpt_ctx.emmc_part_offset[i], gpt_ctx.emmc_part_size[i]); + s_printf(mbox_btn_parts[i], "\222Part. %d", gpt_ctx.emmc_part_idx[i]); + } + s_printf(mbox_btn_parts[gpt_ctx.emmc_part_cnt], "Cancel"); + mbox_btn_parts[gpt_ctx.emmc_part_cnt + 1][0] = '\0'; + strcat(txt_buf, "\n#FFDD00 Note:# Yellow entries have USER partition resized."); + + lv_mbox_add_btns(mbox, (const char **)mbox_btn_parts, _create_emummc_emmc_raw_action); + }else{ + s_printf(txt_buf, "#FFDD00 Failed to find applicable partition!#\n\n" + "#FF8000 Do you want to partition the eMMC?#\n" + "#FF8000 (You will be asked on how to proceed)#"); + + lv_mbox_add_btns(mbox, mbox_btn_format, _create_emummc_emmc_raw_format); + } + + + lv_mbox_set_text(mbox, txt_buf); + free(txt_buf); + free(mbr); + free(gpt); + + lv_obj_align(mbox, NULL, LV_ALIGN_CENTER, 0, 0); + lv_obj_set_top(mbox, true); +} + +#define SECTORS_PER_GB 0x200000 + +typedef struct _slider_ctx_t{ + lv_obj_t *label; + u32 emu_size; // mb + u32 full_size; // mb +} slider_ctx_t; + +static slider_ctx_t slider_ctx; + +static lv_res_t _action_slider_emummc_file(lv_obj_t *slider){ + u32 slider_val = lv_slider_get_value(slider); + u32 size = slider_val <<= 10; + + gfx_printf("sz %d\n", size); + + if(size >= (slider_ctx.full_size > (3 * 1024) ? slider_ctx.full_size - (3 * 1024) : 0) && size <= slider_ctx.full_size + (3 * 1024)){ + gfx_printf("reset full lth: %d uth %d\n",(slider_ctx.full_size > (3 * 1024) ? slider_ctx.full_size - (3 * 1024) : 0),slider_ctx.full_size + (3 * 1024)); + size = slider_ctx.full_size; + + lv_slider_set_value(slider, size >> 10); + } + + slider_ctx.emu_size = size; + + char txt_buf[0x20]; + + if(size == slider_ctx.full_size){ + s_printf(txt_buf, "#FF3C28 %d FULL#", size >> 10); + }else{ + s_printf(txt_buf, "#FF3C28 %d GiB#", size >> 10); + } + + lv_label_set_text(slider_ctx.label, txt_buf); + + return LV_RES_OK; +} + +static lv_res_t _create_emummc_file_based_action(lv_obj_t *btns, const char *txt){ + int idx = lv_btnm_get_pressed(btns); + + if(!idx && slider_ctx.emu_size){ + if(slider_ctx.emu_size != slider_ctx.full_size) + emummc_part_cfg.resized_cnt = slider_ctx.emu_size << 11; _create_window_emummc(); - break; - case 1: - _create_mbox_emummc_raw(); - break; } mbox_action(btns, txt); @@ -333,6 +624,228 @@ static lv_res_t _create_emummc_action(lv_obj_t * btns, const char * txt) return LV_RES_INV; } +static void _create_mbox_emummc_file_based(){ + char *txt_buf = malloc(SZ_4K); + + 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); + + lv_obj_t * mbox = lv_mbox_create(dark_bg, NULL); + lv_mbox_set_recolor_text(mbox, true); + lv_obj_set_width(mbox, LV_HOR_RES / 9 * 6); + + static const char *mbox_btns[] = { "\222Continue", "\222Cancel", "" }; + static const char *mbox_btns_ok[] = { "\251", "\222OK", "\251", "" }; + + lv_mbox_set_text(mbox, "#C7EA46 Select emuMMC size!#\n\n" + "#00DDFF Status:# Checking for available free space..."); + lv_obj_align(mbox, NULL, LV_ALIGN_CENTER, 0, 0); + manual_system_maintenance(true); + + u32 value_full = emmc_storage.sec_cnt >> 11; + + gfx_printf("full: 0x%x\n", emmc_storage.sec_cnt); + + FATFS *fs; + if(emummc_part_cfg.drive == DRIVE_SD){ + sd_mount(); + fs = &sd_fs; + f_getfree("sd:", &fs->free_clst, NULL); + }else{ + emmc_mount(); + fs = &emmc_fs; + f_getfree("emmc:", &fs->free_clst, NULL); + } + emmc_initialize(false); + if(emummc_part_cfg.drive == DRIVE_SD){ + sd_unmount(); + }else{ + emmc_unmount(); + } + + + + // leave 1gb free + u32 available = fs->free_clst * fs->csize; + available >>= 11; + available = available > (5 * 1024) ? available - (1 * 1024) : 0; + + if(available == 0){ + s_printf(txt_buf, "#C7EA46 Select emuMMC size!#\n\n" + "#FFDD00 Note:# Not enough free space on %s", emummc_part_cfg.drive == DRIVE_SD ? "SD" : "eMMC"); + lv_mbox_set_text(mbox, txt_buf); + + }else if(value_full > available){ + s_printf(txt_buf, "#C7EA46 Select emuMMC size!#\n\n" + "#FFDD00 Note:# Not enough space on %s for for full eMMC, \nUSER will be resized and formatted", emummc_part_cfg.drive == DRIVE_SD ? "SD" : "eMMC"); + lv_mbox_set_text(mbox, txt_buf); + }else{ + lv_mbox_set_text(mbox, "#C7EA46 Select emuMMC size!#\n\n" + "#FFDD00 Note:# Any value other than \"FULL\" will format USER"); + } + lv_obj_align(mbox, NULL, LV_ALIGN_CENTER, 0, 0); + + slider_ctx.full_size = value_full; + slider_ctx.emu_size = slider_ctx.full_size > available ? available : slider_ctx.full_size; + if(available){ + + lv_coord_t pad = lv_mbox_get_style(mbox, LV_MBOX_STYLE_BG)->body.padding.hor; + lv_coord_t w = lv_obj_get_width(mbox) - 2 * pad - 2 * LV_DPI; + + // Set eMUMMC bar styles. + static lv_style_t bar_emu_bg, bar_emu_ind, bar_emu_btn; + lv_style_copy(&bar_emu_bg, lv_theme_get_current()->bar.bg); + bar_emu_bg.body.main_color = LV_COLOR_HEX(0x940F00); + bar_emu_bg.body.grad_color = bar_emu_bg.body.main_color; + lv_style_copy(&bar_emu_ind, lv_theme_get_current()->bar.indic); + bar_emu_ind.body.main_color = LV_COLOR_HEX(0xFF3C28); + bar_emu_ind.body.grad_color = bar_emu_ind.body.main_color; + lv_style_copy(&bar_emu_btn, lv_theme_get_current()->slider.knob); + bar_emu_btn.body.main_color = LV_COLOR_HEX(0xB31200); + bar_emu_btn.body.grad_color = bar_emu_btn.body.main_color; + + lv_obj_t *slider_cont = lv_cont_create(mbox, NULL); + lv_cont_set_fit(slider_cont, false, true); + lv_cont_set_style(slider_cont, &lv_style_transp); + lv_obj_set_width(slider_cont, lv_obj_get_width(mbox)); + + lv_obj_t *slider = lv_slider_create(slider_cont, NULL); + lv_obj_set_size(slider, w, LV_DPI / 3); + lv_slider_set_range(slider, 4, available >> 10); + lv_slider_set_value(slider, slider_ctx.emu_size >> 10); + lv_slider_set_style(slider, LV_SLIDER_STYLE_BG, &bar_emu_bg); + lv_slider_set_style(slider, LV_SLIDER_STYLE_INDIC, &bar_emu_ind); + lv_slider_set_style(slider, LV_SLIDER_STYLE_KNOB, &bar_emu_btn); + lv_slider_set_action(slider, _action_slider_emummc_file); + lv_obj_align(slider, slider_cont, LV_ALIGN_CENTER, - (LV_DPI / 2), 0); + + lv_obj_t *label = lv_label_create(slider_cont, NULL); + lv_label_set_recolor(label, true); + if(slider_ctx.emu_size == value_full){ + s_printf(txt_buf, "#FF3C28 %d FULL#", slider_ctx.emu_size >> 10); + }else{ + s_printf(txt_buf, "#FF3C28 %d GiB#", slider_ctx.emu_size >> 10); + } + lv_label_set_text(label, txt_buf); + lv_obj_align(label, slider, LV_ALIGN_OUT_RIGHT_MID, LV_DPI * 2 / 5, 0); + + slider_ctx.label = label; + } + + if(available){ + lv_mbox_add_btns(mbox, mbox_btns, _create_emummc_file_based_action); + }else{ + lv_mbox_add_btns(mbox, mbox_btns_ok, _create_emummc_file_based_action); + } + + lv_obj_align(mbox, NULL, LV_ALIGN_CENTER, 0, 0); + emummc_part_cfg.file_based = true; +} + +static lv_res_t _create_emummc_select_file_type_action(lv_obj_t *btns, const char *txt){ + int btn_idx = lv_btnm_get_pressed(btns); + + mbox_action(btns, txt); + + memset(&emummc_part_cfg, 0, sizeof(emummc_part_cfg)); + + switch(btn_idx){ + case 0: + emummc_part_cfg.drive = DRIVE_SD; + _create_mbox_emummc_file_based(); + break; + case 1: + emummc_part_cfg.drive = DRIVE_EMMC; + _create_mbox_emummc_file_based(); + break; + case 2: + break; + } + + return LV_RES_INV; +} + +static lv_res_t _create_emummc_select_raw_type_action(lv_obj_t *btns, const char *txt){ + int btn_idx = lv_btnm_get_pressed(btns); + + mbox_action(btns, txt); + + memset(&emummc_part_cfg, 0, sizeof(emummc_part_cfg)); + + switch(btn_idx){ + case 0: + _create_mbox_emummc_raw(); + break; + case 1: + _create_mbox_emummc_emmc_raw(); + break; + case 2: + break; + } + + return LV_RES_INV; +} + +static void _create_mbox_emummc_select_raw_type(){ + 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); + + static const char * mbox_btn_map[] = { "\222SD partition", "\222eMMC partition", "\222Cancel", "" }; + lv_obj_t * mbox = lv_mbox_create(dark_bg, NULL); + lv_mbox_set_recolor_text(mbox, true); + lv_obj_set_width(mbox, LV_HOR_RES / 9 * 6); + + lv_mbox_set_text(mbox, + "Welcome to #C7EA46 emuMMC# creation tool!\n\n" + "Please choose what type of partition based emuMMC to create."); + + lv_mbox_add_btns(mbox, mbox_btn_map, _create_emummc_select_raw_type_action); + + lv_obj_align(mbox, NULL, LV_ALIGN_CENTER, 0, 0); + lv_obj_set_top(mbox, true); +} + +static void _create_mbox_emummc_select_file_type(){ + 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); + + static const char * mbox_btn_map[] = { "\222SD file", "\222eMMC file", "\222Cancel", "" }; + lv_obj_t * mbox = lv_mbox_create(dark_bg, NULL); + lv_mbox_set_recolor_text(mbox, true); + lv_obj_set_width(mbox, LV_HOR_RES / 9 * 6); + + lv_mbox_set_text(mbox, + "Welcome to #C7EA46 emuMMC# creation tool!\n\n" + "Please choose what type of file based emuMMC to create."); + + lv_mbox_add_btns(mbox, mbox_btn_map, _create_emummc_select_file_type_action); + + lv_obj_align(mbox, NULL, LV_ALIGN_CENTER, 0, 0); + lv_obj_set_top(mbox, true); +} + +static lv_res_t _create_emummc_select_type_action(lv_obj_t *btns, const char *txt){ + int btn_idx = lv_btnm_get_pressed(btns); + + mbox_action(btns, txt); + + switch(btn_idx){ + case 0: + _create_mbox_emummc_select_file_type(); + break; + case 1: + _create_mbox_emummc_select_raw_type(); + break; + case 2: + break; + } + + return LV_RES_INV; +} + static lv_res_t _create_mbox_emummc_create(lv_obj_t *btn) { if (!nyx_emmc_check_battery_enough()) @@ -342,7 +855,7 @@ static lv_res_t _create_mbox_emummc_create(lv_obj_t *btn) lv_obj_set_style(dark_bg, &mbox_darken); lv_obj_set_size(dark_bg, LV_HOR_RES, LV_VER_RES); - static const char * mbox_btn_map[] = { "\222SD File", "\222SD Partition", "\222Cancel", "" }; + static const char * mbox_btn_map[] = { "\222File based", "\222Partition Based", "\222Cancel", "" }; lv_obj_t * mbox = lv_mbox_create(dark_bg, NULL); lv_mbox_set_recolor_text(mbox, true); lv_obj_set_width(mbox, LV_HOR_RES / 9 * 6); @@ -350,10 +863,10 @@ static lv_res_t _create_mbox_emummc_create(lv_obj_t *btn) lv_mbox_set_text(mbox, "Welcome to #C7EA46 emuMMC# creation tool!\n\n" "Please choose what type of emuMMC you want to create.\n" - "#FF8000 SD File# is saved as files in the FAT partition.\n" - "#FF8000 SD Partition# is saved as raw image in an available partition."); + "#FF8000 File based# is saved as files in\nthe SD or eMMC FAT partition.\n" + "#FF8000 Partition based# is saved as raw image in an\navailable SD or eMMC partition."); - lv_mbox_add_btns(mbox, mbox_btn_map, _create_emummc_action); + lv_mbox_add_btns(mbox, mbox_btn_map, _create_emummc_select_type_action); lv_obj_align(mbox, NULL, LV_ALIGN_CENTER, 0, 0); lv_obj_set_top(mbox, true); @@ -363,20 +876,23 @@ static lv_res_t _create_mbox_emummc_create(lv_obj_t *btn) static void _change_raw_emummc_part_type() { - mbr_t *mbr = (mbr_t *)malloc(sizeof(mbr_t)); - sdmmc_storage_read(&sd_storage, 0, 1, mbr); - mbr->partitions[mbr_ctx.part_idx].type = 0xE0; - sdmmc_storage_write(&sd_storage, 0, 1, mbr); - free(mbr); + // On eMMC, we only consider partitions with the right type GUID to begin with + if(emummc_part_cfg.drive == DRIVE_SD){ + mbr_t *mbr = (mbr_t *)malloc(sizeof(mbr_t)); + sdmmc_storage_read(&sd_storage, 0, 1, mbr); + mbr->partitions[mbr_ctx.part_idx].type = 0xE0; + sdmmc_storage_write(&sd_storage, 0, 1, mbr); + free(mbr); + } } static lv_res_t _save_emummc_cfg_mig_mbox_action(lv_obj_t *btns, const char *txt) { // Delete main emuMMC and popup windows and relaunch main emuMMC window. - lv_obj_del(emummc_manage_window); + lv_obj_clean(emummc_parent_cont); mbox_action(btns, txt); - (*emummc_tools)(NULL); + (*emummc_tools)(emummc_parent_cont); return LV_RES_INV; } @@ -394,7 +910,7 @@ static void _create_emummc_migrated_mbox() lv_mbox_set_text(mbox, "#FF8000 emuMMC Configuration#\n\n" - "#96FF00 The emuMMC configuration#\n#96FF00 was saved to sd card!#"); + "#96FF00 The emuMMC configuration#\n#96FF00 was saved!#"); lv_mbox_add_btns(mbox, mbox_btn_map, _save_emummc_cfg_mig_mbox_action); @@ -406,7 +922,7 @@ static void _migrate_sd_raw_based() { mbr_ctx.sector_start = 2; - sd_mount(); + boot_storage_mount(); f_mkdir("emuMMC"); f_mkdir("emuMMC/ER00"); @@ -416,16 +932,17 @@ static void _migrate_sd_raw_based() f_write(&fp, &mbr_ctx.sector_start, 4, NULL); f_close(&fp); - save_emummc_cfg(1, mbr_ctx.sector_start, "emuMMC/ER00"); + save_emummc_cfg(1, emummc_part_cfg.sector, "emuMMC/ER00", 0); _create_emummc_migrated_mbox(); - sd_unmount(); + boot_storage_unmount(); } static void _migrate_sd_raw_emummc_based() { char *tmp = (char *)malloc(0x80); - s_printf(tmp, "emuMMC/RAW%d", mbr_ctx.part_idx); + s_printf(tmp, "emuMMC/RAW%d", emummc_part_cfg.part_idx); + boot_storage_mount(); sd_mount(); f_mkdir("emuMMC"); f_mkdir(tmp); @@ -434,56 +951,116 @@ static void _migrate_sd_raw_emummc_based() FIL fp; if (!f_open(&fp, tmp, FA_CREATE_ALWAYS | FA_WRITE)) { - f_write(&fp, &mbr_ctx.sector_start, 4, NULL); + f_write(&fp, &emummc_part_cfg.sector, 4, NULL); f_close(&fp); } - s_printf(tmp, "emuMMC/RAW%d", mbr_ctx.part_idx); + s_printf(tmp, "emuMMC/RAW%d", emummc_part_cfg.part_idx); _change_raw_emummc_part_type(); - save_emummc_cfg(mbr_ctx.part_idx, mbr_ctx.sector_start, tmp); + save_emummc_cfg(emummc_part_cfg.part_idx, emummc_part_cfg.sector, tmp, DRIVE_SD); _create_emummc_migrated_mbox(); free(tmp); + boot_storage_unmount(); sd_unmount(); } static void _migrate_sd_file_based() { sd_mount(); + boot_storage_mount(); + f_mkdir("sd:emuMMC"); + f_mkdir("sd:emuMMC/EF00"); + + f_rename("sd:Emutendo", "sd:emuMMC/EF00/Nintendo"); + FIL fp; + f_mkdir("emuMMC"); f_mkdir("emuMMC/EF00"); - - f_rename("Emutendo", "emuMMC/EF00/Nintendo"); - FIL fp; f_open(&fp, "emuMMC/EF00/file_based", FA_CREATE_ALWAYS | FA_WRITE); f_close(&fp); char *path = (char *)malloc(128); char *path2 = (char *)malloc(128); - s_printf(path, "%c%c%c%c%s", 's', 'x', 'o', 's', "/emunand"); - f_rename(path, "emuMMC/EF00/eMMC"); + s_printf(path, "sd:%c%c%c%c%s", 's', 'x', 'o', 's', "/emunand"); + f_rename(path, "sd:emuMMC/EF00/eMMC"); for (int i = 0; i < 2; i++) { - s_printf(path, "emuMMC/EF00/eMMC/boot%d.bin", i); - s_printf(path2, "emuMMC/EF00/eMMC/BOOT%d", i); + s_printf(path, "sd:emuMMC/EF00/eMMC/boot%d.bin", i); + s_printf(path2, "sd:emuMMC/EF00/eMMC/BOOT%d", i); f_rename(path, path2); } for (int i = 0; i < 8; i++) { - s_printf(path, "emuMMC/EF00/eMMC/full.%02d.bin", i); - s_printf(path2, "emuMMC/EF00/eMMC/%02d", i); + s_printf(path, "sd:emuMMC/EF00/eMMC/full.%02d.bin", i); + s_printf(path2, "sd:emuMMC/EF00/eMMC/%02d", i); f_rename(path, path2); } free(path); free(path2); - save_emummc_cfg(0, 0, "emuMMC/EF00"); + save_emummc_cfg(0, 0, "emuMMC/EF00",0 ); _create_emummc_migrated_mbox(); sd_unmount(); + boot_storage_unmount(); +} + +static u32 _copy_file(const char *src, const char* dest){ + u32 res = FR_OK; + u8 *buf = (u8*)MIXD_BUF_ALIGNED; + FIL fs; + FIL fd; + DWORD *clmnt_s = NULL; + DWORD *clmnt_d = NULL; + + res = f_open(&fs, src, FA_READ); + if(res != FR_OK){ + goto error; + } + + res = f_open(&fd, src, FA_WRITE | FA_CREATE_ALWAYS); + if(res != FR_OK){ + f_close(&fs); + goto error; + } + + u32 sz = f_size(&fs); + + clmnt_d = f_expand_cltbl(&fd, SZ_4M, sz); + clmnt_s = f_expand_cltbl(&fs, SZ_4M, sz); + + for(u32 i = 0; i < sz; i += SZ_4M){ + // 4M at a time + u32 btr = MIN(SZ_4M, sz - i); + + res = f_read_fast(&fs, buf, btr); + + if(res != FR_OK){ + res = f_write_fast(&fd, buf, btr); + } + + if(res != FR_OK){ + break; + } + } + + if(res != FR_OK){ + f_close(&fd); + f_unlink(dest); + }else{ + f_close(&fd); + } + + f_close(&fs); + free(clmnt_s); + free(clmnt_d); + + error: + return res; } static void _migrate_sd_backup_file_based() @@ -494,9 +1071,11 @@ static void _migrate_sd_backup_file_based() char *backup_file_path = (char *)malloc(128); sd_mount(); + boot_storage_mount(); + f_mkdir("sd:emuMMC"); f_mkdir("emuMMC"); - strcpy(emu_path, "emuMMC/BK"); + strcpy(emu_path, "sd:emuMMC/BK"); u32 base_len = strlen(emu_path); for (int j = 0; j < 100; j++) @@ -508,13 +1087,14 @@ static void _migrate_sd_backup_file_based() base_len = strlen(emu_path); f_mkdir(emu_path); + f_mkdir(emu_path + 3); strcat(emu_path, "/eMMC"); f_mkdir(emu_path); FIL fp; // Create file based flag. strcpy(emu_path + base_len, "/file_based"); - f_open(&fp, "emuMMC/BK00/file_based", FA_CREATE_ALWAYS | FA_WRITE); + f_open(&fp, (emu_path + 3), FA_CREATE_ALWAYS | FA_WRITE); f_close(&fp); if (!emummc_backup) @@ -522,15 +1102,24 @@ static void _migrate_sd_backup_file_based() else emmcsn_path_impl(backup_path, "/emummc", "", NULL); - // Move BOOT0. + // rename if on sd, copy otherwise s_printf(backup_file_path, "%s/BOOT0", backup_path); strcpy(emu_path + base_len, "/eMMC/BOOT0"); - f_rename(backup_file_path, emu_path); + if(boot_storage_get_drive() == DRIVE_SD){ + f_rename(backup_file_path, emu_path); + }else{ + _copy_file(backup_file_path, emu_path); + } - // Move BOOT1. + // rename if on sd, copy otherwise s_printf(backup_file_path, "%s/BOOT1", backup_path); strcpy(emu_path + base_len, "/eMMC/BOOT1"); - f_rename(backup_file_path, emu_path); + if(boot_storage_get_drive() == DRIVE_SD){ + f_rename(backup_file_path, emu_path); + }else{ + _copy_file(backup_file_path, emu_path); + } + // Move raw GPP. bool multipart = false; @@ -542,7 +1131,11 @@ static void _migrate_sd_backup_file_based() if (!multipart) { strcpy(emu_path + base_len, "/eMMC/00"); - f_rename(backup_file_path, emu_path); + if(boot_storage_get_drive() == DRIVE_SD){ + f_rename(backup_file_path, emu_path); + }else{ + _copy_file(backup_file_path, emu_path); + } } else { @@ -551,8 +1144,15 @@ static void _migrate_sd_backup_file_based() { s_printf(backup_file_path, "%s/rawnand.bin.%02d", backup_path, i); s_printf(parts_path, "%s/eMMC/%02d", emu_path, i); - if (f_rename(backup_file_path, parts_path)) + u32 res; + if(boot_storage_get_drive() == DRIVE_SD){ + res = f_rename(backup_file_path, parts_path); + }else{ + res = _copy_file(backup_file_path, parts_path); + } + if(res != FR_OK){ break; + } } } @@ -561,9 +1161,10 @@ static void _migrate_sd_backup_file_based() free(backup_path); free(backup_file_path); - save_emummc_cfg(0, 0, "emuMMC/BK00"); + save_emummc_cfg(0, 0, "emuMMC/BK00", 0); _create_emummc_migrated_mbox(); sd_unmount(); + boot_storage_unmount(); } static lv_res_t _create_emummc_mig1_action(lv_obj_t * btns, const char * txt) @@ -578,8 +1179,7 @@ static lv_res_t _create_emummc_mig1_action(lv_obj_t * btns, const char * txt) break; } - mbr_ctx.part_idx = 0; - mbr_ctx.sector_start = 0; + memset(&emummc_part_cfg, 0, sizeof(emummc_part_cfg)); mbox_action(btns, txt); @@ -595,8 +1195,7 @@ static lv_res_t _create_emummc_mig0_action(lv_obj_t * btns, const char * txt) break; } - mbr_ctx.part_idx = 0; - mbr_ctx.sector_start = 0; + memset(&emummc_part_cfg, 0, sizeof(emummc_part_cfg)); mbox_action(btns, txt); @@ -612,8 +1211,7 @@ static lv_res_t _create_emummc_mig2_action(lv_obj_t * btns, const char * txt) break; } - mbr_ctx.part_idx = 0; - mbr_ctx.sector_start = 0; + memset(&emummc_part_cfg, 0, sizeof(emummc_part_cfg)); mbox_action(btns, txt); @@ -629,8 +1227,7 @@ static lv_res_t _create_emummc_mig3_action(lv_obj_t * btns, const char * txt) break; } - mbr_ctx.part_idx = 0; - mbr_ctx.sector_start = 0; + memset(&emummc_part_cfg, 0, sizeof(emummc_part_cfg)); mbox_action(btns, txt); @@ -646,8 +1243,7 @@ static lv_res_t _create_emummc_mig4_action(lv_obj_t * btns, const char * txt) break; } - mbr_ctx.part_idx = 0; - mbr_ctx.sector_start = 0; + memset(&emummc_part_cfg, 0, sizeof(emummc_part_cfg)); mbox_action(btns, txt); @@ -749,6 +1345,12 @@ static lv_res_t _create_emummc_migrate_action(lv_obj_t * btns, const char * txt) typedef struct _emummc_images_t { dirlist_t *dirlist; + + u32 emmc_part_sector[3]; + u32 emmc_part_end[3]; + u32 emmc_part_idx[3]; + char emmc_part_path[3][128]; + u32 part_sector[3]; u32 part_type[3]; u32 part_end[3]; @@ -777,6 +1379,7 @@ static lv_res_t _create_mbox_emummc_migrate(lv_obj_t *btn) u8 *efi_part = (u8 *)malloc(0x200); sd_mount(); + boot_storage_mount(); sdmmc_storage_read(&sd_storage, 0, 1, mbr); emmc_initialize(false); @@ -787,8 +1390,7 @@ static lv_res_t _create_mbox_emummc_migrate(lv_obj_t *btn) bool emummc = false; bool rawnand_backup = false; - mbr_ctx.sector_start = 0; - mbr_ctx.part_idx = 0; + memset(&emummc_part_cfg, 0, sizeof(emummc_part_cfg)); // Try to find a partition based emuMMC. for (int i = 1; i < 4; i++) @@ -801,9 +1403,9 @@ static lv_res_t _create_mbox_emummc_migrate(lv_obj_t *btn) sdmmc_storage_read(&sd_storage, mbr_ctx.sector_start + 0xC001, 1, efi_part); if (!memcmp(efi_part, "EFI PART", 8)) { - mbr_ctx.sector_start += 0x8000; emummc = true; - mbr_ctx.part_idx = i; + emummc_part_cfg.sector += 0x8000; + emummc_part_cfg.part_idx = i; break; } else @@ -812,7 +1414,7 @@ static lv_res_t _create_mbox_emummc_migrate(lv_obj_t *btn) if (!memcmp(efi_part, "EFI PART", 8)) { emummc = true; - mbr_ctx.part_idx = i; + emummc_part_cfg.part_idx = i; break; } } @@ -825,7 +1427,7 @@ static lv_res_t _create_mbox_emummc_migrate(lv_obj_t *btn) em_raw = true; } - s_printf(path_buf, "%c%c%c%c%s", 's', 'x', 'o','s', "/emunand/boot0.bin"); + s_printf(path_buf, "sd:%c%c%c%c%s", 's', 'x', 'o','s', "/emunand/boot0.bin"); if (!f_stat(path_buf, NULL)) em_file = true; @@ -867,6 +1469,7 @@ static lv_res_t _create_mbox_emummc_migrate(lv_obj_t *btn) } sd_unmount(); + boot_storage_unmount(); emmc_end(); // Check available types and enable the corresponding buttons. @@ -900,14 +1503,14 @@ static emummc_images_t *emummc_img; static lv_res_t _save_emummc_cfg_mbox_action(lv_obj_t *btns, const char *txt) { // Free components, delete main emuMMC and popup windows and relaunch main emuMMC window. - lv_obj_del(emummc_img->win); - lv_obj_del(emummc_manage_window); free(emummc_img->dirlist); + lv_obj_del(emummc_img->win); + lv_obj_clean(emummc_parent_cont); free(emummc_img); mbox_action(btns, txt); - (*emummc_tools)(NULL); + (*emummc_tools)(emummc_parent_cont); return LV_RES_INV; } @@ -939,13 +1542,35 @@ static lv_res_t _save_raw_emummc_cfg_action(lv_obj_t * btn) switch (ext->idx) { case 0: - save_emummc_cfg(1, emummc_img->part_sector[0], &emummc_img->part_path[0]); + save_emummc_cfg(1, emummc_img->part_sector[0], &emummc_img->part_path[0], DRIVE_SD); break; case 1: - save_emummc_cfg(2, emummc_img->part_sector[1], &emummc_img->part_path[128]); + save_emummc_cfg(2, emummc_img->part_sector[1], &emummc_img->part_path[128], DRIVE_SD); break; case 2: - save_emummc_cfg(3, emummc_img->part_sector[2], &emummc_img->part_path[256]); + save_emummc_cfg(3, emummc_img->part_sector[2], &emummc_img->part_path[256], DRIVE_SD); + break; + } + + _create_emummc_saved_mbox(); + sd_unmount(); + + return LV_RES_INV; +} + +static lv_res_t _save_emmc_raw_emummc_cfg_action(lv_obj_t * btn) +{ + lv_btn_ext_t *ext = lv_obj_get_ext_attr(btn); + switch (ext->idx) + { + case 0: + save_emummc_cfg(1, emummc_img->emmc_part_sector[0], (char*)&emummc_img->emmc_part_path[0], DRIVE_EMMC); + break; + case 1: + save_emummc_cfg(2, emummc_img->emmc_part_sector[1], (char*)&emummc_img->emmc_part_path[1], DRIVE_EMMC); + break; + case 2: + save_emummc_cfg(3, emummc_img->emmc_part_sector[2], (char*)&emummc_img->emmc_part_path[2], DRIVE_EMMC); break; } @@ -957,41 +1582,52 @@ static lv_res_t _save_raw_emummc_cfg_action(lv_obj_t * btn) static lv_res_t _save_disable_emummc_cfg_action(lv_obj_t * btn) { - save_emummc_cfg(0, 0, NULL); + save_emummc_cfg(0, 0, NULL, 0); _create_emummc_saved_mbox(); sd_unmount(); + boot_storage_unmount(); + + return LV_RES_INV; +} + +static lv_res_t _save_file_emummc_emmc_cfg_action(lv_obj_t *btn) +{ + const char *btn_txt = lv_list_get_btn_text(btn); + gfx_printf("save emu %s\n", btn_txt); + save_emummc_cfg(0, 0, btn_txt, DRIVE_EMMC); + _create_emummc_saved_mbox(); + sd_unmount(); + boot_storage_unmount(); return LV_RES_INV; } static lv_res_t _save_file_emummc_cfg_action(lv_obj_t *btn) { - save_emummc_cfg(0, 0, lv_list_get_btn_text(btn)); + const char *btn_txt = lv_list_get_btn_text(btn); + gfx_printf("save sd %s\n", btn_txt); + save_emummc_cfg(0, 0, btn_txt, DRIVE_SD); _create_emummc_saved_mbox(); sd_unmount(); + boot_storage_unmount(); return LV_RES_INV; } -static lv_res_t _action_win_change_emummc_close(lv_obj_t *btn) -{ - free(emummc_img->dirlist); - free(emummc_img); - - return nyx_win_close_action_custom(btn); -} - static lv_res_t _create_change_emummc_window(lv_obj_t *btn_caller) { - lv_obj_t *win = nyx_create_window_custom_close_btn(SYMBOL_SETTINGS" Change emuMMC", _action_win_change_emummc_close); + lv_obj_t *win = nyx_create_standard_window(SYMBOL_SETTINGS" Change emuMMC"); lv_win_add_btn(win, NULL, SYMBOL_POWER" Disable", _save_disable_emummc_cfg_action); + boot_storage_mount(); sd_mount(); + emmc_mount(); - emummc_img = malloc(sizeof(emummc_images_t)); + emummc_img = zalloc(sizeof(emummc_images_t)); emummc_img->win = win; mbr_t *mbr = (mbr_t *)malloc(sizeof(mbr_t)); + gpt_t *gpt = (gpt_t*)malloc(sizeof(gpt_t)); char *path = malloc(512); sdmmc_storage_read(&sd_storage, 0, 1, mbr); @@ -1001,12 +1637,11 @@ static lv_res_t _create_change_emummc_window(lv_obj_t *btn_caller) for (int i = 1; i < 4; i++) { emummc_img->part_sector[i - 1] = mbr->partitions[i].start_sct; - emummc_img->part_end[i - 1] = emummc_img->part_sector[i - 1] + mbr->partitions[i].size_sct - 1; - emummc_img->part_type[i - 1] = mbr->partitions[i].type; + emummc_img->part_end[i - 1] = emummc_img->part_sector[i - 1] + mbr->partitions[i].size_sct - 1; + emummc_img->part_type[i - 1] = mbr->partitions[i].type; } - free(mbr); - emummc_img->dirlist = dirlist("emuMMC", NULL, DIR_SHOW_DIRS); + emummc_img->dirlist = dirlist("emuMMC", NULL, false, true); if (!emummc_img->dirlist) goto out0; @@ -1033,30 +1668,75 @@ static lv_res_t _create_change_emummc_window(lv_obj_t *btn_caller) { s_printf(&emummc_img->part_path[0], "emuMMC/%s", emummc_img->dirlist->name[emummc_idx]); emummc_img->part_sector[0] = curr_list_sector; - emummc_img->part_end[0] = 0; + emummc_img->part_end[0] = 0; } else if (emummc_img->part_sector[1] && curr_list_sector >= emummc_img->part_sector[1] && curr_list_sector < emummc_img->part_end[1] && emummc_img->part_type[1] != 0x83) { s_printf(&emummc_img->part_path[1 * 128], "emuMMC/%s", emummc_img->dirlist->name[emummc_idx]); emummc_img->part_sector[1] = curr_list_sector; - emummc_img->part_end[1] = 0; + emummc_img->part_end[1] = 0; } else if (emummc_img->part_sector[2] && curr_list_sector >= emummc_img->part_sector[2] && curr_list_sector < emummc_img->part_end[2] && emummc_img->part_type[2] != 0x83) { s_printf(&emummc_img->part_path[2 * 128], "emuMMC/%s", emummc_img->dirlist->name[emummc_idx]); emummc_img->part_sector[2] = curr_list_sector; - emummc_img->part_end[2] = 0; + emummc_img->part_end[2] = 0; } } emummc_idx++; } + + u32 emmc_cnt = 0; + sdmmc_storage_read(&emmc_storage, 0, 1, mbr); + if(mbr_has_gpt(mbr)){ + sdmmc_storage_read(&emmc_storage, 1, sizeof(gpt_t) / 0x200, gpt); + + s32 gpt_idx = gpt_get_part_by_name(gpt, "emummc", -1); + while(gpt_idx != -1 && emmc_cnt < 3){ + emummc_img->emmc_part_sector[emmc_cnt] = gpt->entries[gpt_idx].lba_start; + emummc_img->emmc_part_end[emmc_cnt] = gpt->entries[gpt_idx].lba_end; + emummc_img->emmc_part_idx[emmc_cnt] = gpt_idx; + + emmc_cnt++; + gpt_idx = gpt_get_part_by_name(gpt, "emummc", gpt_idx); + } + } + + free(gpt); + free(mbr); + + emummc_idx = 0; + + // Check for eMMC raw partitions, based on the folders in /emuMMC + while(emummc_img->dirlist->name[emummc_idx]){ + s_printf(path, "emuMMC/%s/raw_emmc_based", emummc_img->dirlist->name[emummc_idx]); + + if(!f_stat(path, NULL)){ + f_open(&fp, path, FA_READ); + u32 sector = 0; + f_read(&fp, §or, 4, NULL); + f_close(&fp); + + for(u32 i = 0; i < emmc_cnt; i++){ + if(sector && sector >= emummc_img->emmc_part_sector[i] && sector <= emummc_img->emmc_part_end[i]){ + emummc_img->emmc_part_sector[i] = sector; + emummc_img->emmc_part_end[i] = 0; + s_printf((char*)&emummc_img->emmc_part_path[i], "emuMMC/%s", emummc_img->dirlist->name[emummc_idx]); + } + } + } + emummc_idx++; + } + + emummc_idx = 0; u32 file_based_idx = 0; // Sanitize the directory list with sd file based ones. + u8 file_based_drives[DIR_MAX_ENTRIES]; while (emummc_img->dirlist->name[emummc_idx]) { s_printf(path, "emuMMC/%s/file_based", emummc_img->dirlist->name[emummc_idx]); @@ -1065,6 +1745,16 @@ static lv_res_t _create_change_emummc_window(lv_obj_t *btn_caller) { char *tmp = emummc_img->dirlist->name[emummc_idx]; memcpy(emummc_img->dirlist->name[file_based_idx], tmp, strlen(tmp) + 1); + file_based_drives[file_based_idx] = DRIVE_SD; + file_based_idx++; + } + + s_printf(path, "emuMMC/%s/file_emmc_based", emummc_img->dirlist->name[emummc_idx]); + if (!f_stat(path, NULL)) + { + char *tmp = emummc_img->dirlist->name[emummc_idx]; + memcpy(emummc_img->dirlist->name[file_based_idx], tmp, strlen(tmp) + 1); + file_based_drives[file_based_idx] = DRIVE_EMMC; file_based_idx++; } emummc_idx++; @@ -1082,7 +1772,7 @@ out0:; lv_obj_t *h1 = lv_cont_create(win, NULL); lv_cont_set_style(h1, &h_style); lv_cont_set_fit(h1, false, true); - lv_obj_set_width(h1, (LV_HOR_RES / 9) * 4); + lv_obj_set_width(h1, (LV_HOR_RES / 17) * 4); lv_obj_set_click(h1, false); lv_cont_set_layout(h1, LV_LAYOUT_OFF); @@ -1095,7 +1785,7 @@ out0:; lv_obj_align(label_txt, label_sep, LV_ALIGN_OUT_BOTTOM_LEFT, LV_DPI / 4, -(LV_DPI / 2)); lv_obj_t *line_sep = lv_line_create(h1, NULL); - static const lv_point_t line_pp[] = { {0, 0}, { LV_HOR_RES - (LV_DPI - (LV_DPI / 4)) * 2, 0} }; + static const lv_point_t line_pp[] = { {0, 0}, { LV_HOR_RES - (LV_DPI - (LV_DPI / 2)) * 2, 0} }; lv_line_set_points(line_sep, line_pp, 2); lv_line_set_style(line_sep, lv_theme_get_current()->line.decor); lv_obj_align(line_sep, label_txt, LV_ALIGN_OUT_BOTTOM_LEFT, -(LV_DPI / 4), LV_DPI / 8); @@ -1135,8 +1825,8 @@ out0:; if (!raw_btn_idx) { lv_btn_set_fit(btn, false, true); - lv_obj_set_width(btn, LV_DPI * 3); - lv_obj_align(btn, line_sep, LV_ALIGN_OUT_BOTTOM_LEFT, LV_DPI / 2, LV_DPI / 5); + lv_obj_set_width(btn, LV_DPI * 2 + LV_DPI / 2); + lv_obj_align(btn, line_sep, LV_ALIGN_OUT_BOTTOM_LEFT, LV_DPI / 3, LV_DPI / 5); } else lv_obj_align(btn, lv_desc, LV_ALIGN_OUT_BOTTOM_LEFT, 0, LV_DPI / 3); @@ -1151,24 +1841,86 @@ out0:; lv_label_set_text(lv_desc, txt_buf); lv_obj_align(lv_desc, btn, LV_ALIGN_OUT_BOTTOM_LEFT, 0, LV_DPI / 5); } + + + // Create eMMC Raw container + lv_obj_t *h3 = lv_cont_create(win, NULL); + lv_cont_set_style(h3, &h_style); + lv_cont_set_fit(h3, false, true); + lv_obj_set_width(h3, (LV_HOR_RES / 17) * 4); + lv_obj_set_click(h3, false); + lv_cont_set_layout(h3, LV_LAYOUT_OFF); + + label_sep = lv_label_create(h3, NULL); + lv_label_set_static_text(label_sep, ""); + + lv_obj_t *label_txt2 = lv_label_create(h3, NULL); + lv_label_set_static_text(label_txt2, "eMMC Raw Partitions"); + lv_obj_set_style(label_txt2, lv_theme_get_current()->label.prim); + lv_obj_align(label_txt2, label_sep, LV_ALIGN_OUT_BOTTOM_LEFT, LV_DPI * 2 / 9, -(LV_DPI / 2)); + + line_sep = lv_line_create(h3, line_sep); + lv_obj_align(line_sep, label_txt2, LV_ALIGN_OUT_BOTTOM_LEFT, -(LV_DPI / 4), LV_DPI / 8); + lv_line_set_style(line_sep, lv_theme_get_current()->line.decor); + + for (u32 i = 0; i < 3; i++){ + btn = lv_btn_create(h3, btn); + ext = lv_obj_get_ext_attr(btn); + ext->idx = i; + btn_label = lv_label_create(btn, btn_label); + + lv_btn_set_state(btn, LV_BTN_STATE_REL); + lv_obj_set_click(btn, true); + + s_printf(txt_buf, "eMMC RAW %d", i + 1); + lv_label_set_text(btn_label, txt_buf); + + if (!emummc_img->emmc_part_sector[i] || !emummc_img->emmc_part_path[i][0]) + { + lv_btn_set_state(btn, LV_BTN_STATE_INA); + lv_obj_set_click(btn, false); + } + + if (!i) + { + lv_btn_set_fit(btn, false, true); + lv_obj_set_width(btn, LV_DPI * 2 + LV_DPI / 2); + lv_obj_align(btn, line_sep, LV_ALIGN_OUT_BOTTOM_LEFT, LV_DPI / 3, LV_DPI / 5); + } + else + lv_obj_align(btn, lv_desc, LV_ALIGN_OUT_BOTTOM_LEFT, 0, LV_DPI / 3); + + lv_btn_set_action(btn, LV_BTN_ACTION_CLICK, _save_emmc_raw_emummc_cfg_action); + + lv_desc = lv_label_create(h3, lv_desc); + lv_label_set_recolor(lv_desc, true); + lv_obj_set_style(lv_desc, &hint_small_style); + + s_printf(txt_buf, "Sector start: 0x%08X\nFolder: %s", emummc_img->emmc_part_sector[i], (char*)&emummc_img->emmc_part_path[i]); + lv_label_set_text(lv_desc, txt_buf); + lv_obj_align(lv_desc, btn, LV_ALIGN_OUT_BOTTOM_LEFT, 0, LV_DPI / 5); + } + + lv_obj_align(h3, h1, LV_ALIGN_OUT_RIGHT_TOP, LV_DPI / 2, 0); + free(txt_buf); // Create SD File Based container. lv_obj_t *h2 = lv_cont_create(win, NULL); lv_cont_set_style(h2, &h_style); lv_cont_set_fit(h2, false, true); - lv_obj_set_width(h2, (LV_HOR_RES / 9) * 4); + lv_obj_set_width(h2, LV_HOR_RES * 2 / 5); lv_obj_set_click(h2, false); lv_cont_set_layout(h2, LV_LAYOUT_OFF); - lv_obj_align(h2, h1, LV_ALIGN_OUT_RIGHT_TOP, LV_DPI * 17 / 29, 0); + lv_obj_align(h2, h3, LV_ALIGN_OUT_RIGHT_TOP, LV_DPI / 2, 0); label_sep = lv_label_create(h2, NULL); lv_label_set_static_text(label_sep, ""); lv_obj_t *label_txt3 = lv_label_create(h2, NULL); - lv_label_set_static_text(label_txt3, "SD File Based"); + lv_label_set_static_text(label_txt3, "SD/eMMC File Based"); lv_obj_set_style(label_txt3, lv_theme_get_current()->label.prim); - lv_obj_align(label_txt3, label_sep, LV_ALIGN_OUT_BOTTOM_LEFT, LV_DPI / 4, -LV_DPI / 7); + lv_obj_align(label_txt3, label_sep, LV_ALIGN_OUT_BOTTOM_LEFT, LV_DPI * 2 / 9, -LV_DPI / 7); line_sep = lv_line_create(h2, line_sep); lv_obj_align(line_sep, label_txt3, LV_ALIGN_OUT_BOTTOM_LEFT, -(LV_DPI / 2), LV_DPI / 8); @@ -1177,7 +1929,7 @@ out0:; lv_obj_t *list_sd_based = lv_list_create(h2, NULL); lv_obj_align(list_sd_based, line_sep, LV_ALIGN_OUT_BOTTOM_LEFT, LV_DPI / 2, LV_DPI / 4); - lv_obj_set_size(list_sd_based, LV_HOR_RES * 4 / 10, LV_VER_RES * 6 / 10); + lv_obj_set_size(list_sd_based, LV_HOR_RES * 4 / 10 - (LV_DPI / 2), LV_VER_RES * 6 / 10); lv_list_set_single_mode(list_sd_based, true); if (!emummc_img->dirlist) @@ -1190,7 +1942,11 @@ out0:; { s_printf(path, "emuMMC/%s", emummc_img->dirlist->name[emummc_idx]); - lv_list_add(list_sd_based, NULL, path, _save_file_emummc_cfg_action); + if(file_based_drives[emummc_idx] == DRIVE_SD){ + lv_list_add(list_sd_based, NULL, path, _save_file_emummc_cfg_action); + }else{ + lv_list_add(list_sd_based, NULL, path, _save_file_emummc_emmc_cfg_action); + } emummc_idx++; } @@ -1198,24 +1954,22 @@ out0:; out1: free(path); sd_unmount(); + boot_storage_unmount(); return LV_RES_OK; } -lv_res_t create_win_emummc_tools(lv_obj_t *btn) +lv_res_t create_tab_emummc_tools(lv_obj_t *parent) { - lv_obj_t *win = nyx_create_standard_window(SYMBOL_EDIT" emuMMC Manage"); + emummc_parent_cont = parent; + emummc_tools = &create_tab_emummc_tools; - // Set resources to be managed by other windows. - emummc_manage_window = win; - emummc_tools = (void *)create_win_emummc_tools; - - sd_mount(); + boot_storage_mount(); emummc_cfg_t emu_info; load_emummc_cfg(&emu_info); - sd_unmount(); + boot_storage_unmount(); static lv_style_t h_style; lv_style_copy(&h_style, &lv_style_transp); @@ -1224,7 +1978,7 @@ lv_res_t create_win_emummc_tools(lv_obj_t *btn) h_style.body.padding.ver = LV_DPI / 9; // Create emuMMC Info & Selection container. - lv_obj_t *h1 = lv_cont_create(win, NULL); + 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 / 9) * 4); @@ -1237,7 +1991,7 @@ lv_res_t create_win_emummc_tools(lv_obj_t *btn) lv_obj_t *label_txt = lv_label_create(h1, NULL); lv_label_set_static_text(label_txt, "emuMMC Info & Selection"); lv_obj_set_style(label_txt, lv_theme_get_current()->label.prim); - lv_obj_align(label_txt, label_sep, LV_ALIGN_OUT_BOTTOM_LEFT, LV_DPI / 4, -LV_DPI / 9); + lv_obj_align(label_txt, h1, LV_ALIGN_IN_TOP_LEFT, LV_DPI / 4, -LV_DPI / 9); lv_obj_t *line_sep = lv_line_create(h1, NULL); static const lv_point_t line_pp[] = { {0, 0}, { LV_HOR_RES - (LV_DPI - (LV_DPI / 4)) * 2, 0} }; @@ -1257,12 +2011,23 @@ lv_res_t create_win_emummc_tools(lv_obj_t *btn) if (emu_info.enabled) { - if (emu_info.sector) - s_printf(txt_buf, "#00DDFF Type:# SD Raw Partition\n#00DDFF Sector:# 0x%08X\n#00DDFF Nintendo folder:# %s", - emu_info.sector, emu_info.nintendo_path ? emu_info.nintendo_path : ""); - else - s_printf(txt_buf, "#00DDFF Type:# SD File\n#00DDFF Base folder:# %s\n#00DDFF Nintendo folder:# %s", - emu_info.path ? emu_info.path : "", emu_info.nintendo_path ? emu_info.nintendo_path : ""); + if(emu_info.enabled == 4){ + if(emu_info.sector){ + s_printf(txt_buf, "#00DDFF Type:# eMMC Raw Partition\n#00DDFF Sector:# 0x%08X\n#00DDFF Nintendo folder:# %s", + emu_info.sector, emu_info.nintendo_path ? emu_info.nintendo_path : ""); + }else{ + s_printf(txt_buf, "#00DDFF Type:# eMMC File\n#00DDFF Base folder:# %s\n#00DDFF Nintendo folder:# %s", + emu_info.path ? emu_info.path : "", emu_info.nintendo_path ? emu_info.nintendo_path : ""); + } + }else{ + if (emu_info.sector){ + s_printf(txt_buf, "#00DDFF Type:# SD Raw Partition\n#00DDFF Sector:# 0x%08X\n#00DDFF Nintendo folder:# %s", + emu_info.sector, emu_info.nintendo_path ? emu_info.nintendo_path : ""); + }else{ + s_printf(txt_buf, "#00DDFF Type:# SD File\n#00DDFF Base folder:# %s\n#00DDFF Nintendo folder:# %s", + emu_info.path ? emu_info.path : "", emu_info.nintendo_path ? emu_info.nintendo_path : ""); + } + } lv_label_set_text(label_txt2, txt_buf); } @@ -1299,7 +2064,7 @@ lv_res_t create_win_emummc_tools(lv_obj_t *btn) lv_obj_align(label_txt2, btn2, LV_ALIGN_OUT_BOTTOM_LEFT, 0, LV_DPI / 3); // Create emuMMC Tools container. - lv_obj_t *h2 = lv_cont_create(win, NULL); + lv_obj_t *h2 = lv_cont_create(parent, NULL); lv_cont_set_style(h2, &h_style); lv_cont_set_fit(h2, false, true); lv_obj_set_width(h2, (LV_HOR_RES / 9) * 4); @@ -1313,7 +2078,7 @@ lv_res_t create_win_emummc_tools(lv_obj_t *btn) lv_obj_t *label_txt3 = lv_label_create(h2, NULL); lv_label_set_static_text(label_txt3, "emuMMC Tools"); lv_obj_set_style(label_txt3, lv_theme_get_current()->label.prim); - lv_obj_align(label_txt3, label_sep, LV_ALIGN_OUT_BOTTOM_LEFT, LV_DPI / 4, 0); + lv_obj_align(label_txt3, h2, LV_ALIGN_IN_TOP_LEFT, LV_DPI / 4, 0); line_sep = lv_line_create(h2, line_sep); lv_obj_align(line_sep, label_txt3, LV_ALIGN_OUT_BOTTOM_LEFT, -(LV_DPI / 4), LV_DPI / 8); @@ -1329,7 +2094,7 @@ lv_res_t create_win_emummc_tools(lv_obj_t *btn) lv_obj_t *label_txt4 = lv_label_create(h2, NULL); lv_label_set_recolor(label_txt4, true); lv_label_set_static_text(label_txt4, - "Allows you to create a new #C7EA46 SD File# or #C7EA46 SD Raw Partition#\n" + "Allow you to create a new #C7EA46 SD File#, #C7EA46 SD -# or #C7EA46 eMMC Raw Partition#\n" "emuMMC. You can create it from eMMC or a eMMC Backup."); lv_obj_set_style(label_txt4, &hint_small_style); @@ -1351,5 +2116,10 @@ lv_res_t create_win_emummc_tools(lv_obj_t *btn) lv_obj_set_style(label_txt4, &hint_small_style); lv_obj_align(label_txt4, btn4, LV_ALIGN_OUT_BOTTOM_LEFT, 0, LV_DPI / 3); + + lv_obj_align(h1, parent, LV_ALIGN_IN_TOP_LEFT, 0, 0); + lv_obj_align(h2, h1, LV_ALIGN_OUT_RIGHT_TOP, LV_DPI * 17 / 29, 0); + + return LV_RES_OK; } diff --git a/nyx/nyx_gui/frontend/gui_emummc_tools.h b/nyx/nyx_gui/frontend/gui_emummc_tools.h index d25bb325..2cb8bc36 100644 --- a/nyx/nyx_gui/frontend/gui_emummc_tools.h +++ b/nyx/nyx_gui/frontend/gui_emummc_tools.h @@ -19,6 +19,6 @@ #include -lv_res_t create_win_emummc_tools(lv_obj_t *btn); +lv_res_t create_tab_emummc_tools(lv_obj_t *parent); #endif diff --git a/nyx/nyx_gui/frontend/gui_info.c b/nyx/nyx_gui/frontend/gui_info.c index 0b4241f6..286b99b0 100644 --- a/nyx/nyx_gui/frontend/gui_info.c +++ b/nyx/nyx_gui/frontend/gui_info.c @@ -23,6 +23,7 @@ #include "../hos/hos.h" #include "../hos/pkg1.h" #include +#include #include @@ -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; } diff --git a/nyx/nyx_gui/frontend/gui_options.c b/nyx/nyx_gui/frontend/gui_options.c index 983639c8..0082bc2f 100644 --- a/nyx/nyx_gui/frontend/gui_options.c +++ b/nyx/nyx_gui/frontend/gui_options.c @@ -23,6 +23,7 @@ #include "../config.h" #include #include +#include #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:; diff --git a/nyx/nyx_gui/frontend/gui_tools.c b/nyx/nyx_gui/frontend/gui_tools.c index 113a03eb..25dbe6a3 100644 --- a/nyx/nyx_gui/frontend/gui_tools.c +++ b/nyx/nyx_gui/frontend/gui_tools.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2018 naehrwert - * 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, @@ -15,6 +15,12 @@ * along with this program. If not, see . */ +#include +#include +#include +#include +#include +#include #include #include @@ -28,8 +34,17 @@ #include "../hos/pkg1.h" #include "../hos/pkg2.h" #include "../hos/hos.h" -#include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include extern volatile boot_cfg_t *b_cfg; @@ -217,7 +232,7 @@ static lv_res_t _create_mbox_hid(usb_ctxt_t *usbs) return LV_RES_OK; } -static lv_res_t _create_mbox_ums(usb_ctxt_t *usbs) +static lv_res_t _create_mbox_ums(usb_ctxt_t *usbs, u32 part) { lv_obj_t *dark_bg = lv_obj_create(lv_scr_act(), NULL); lv_obj_set_style(dark_bg, &mbox_darken); @@ -232,38 +247,38 @@ static lv_res_t _create_mbox_ums(usb_ctxt_t *usbs) s_printf(txt_buf, "#FF8000 USB Mass Storage#\n\n#C7EA46 Device:# "); - if (usbs->type == MMC_SD) - { - switch (usbs->partition) - { - case 0: - strcat(txt_buf, "SD Card"); - break; - case EMMC_GPP + 1: - strcat(txt_buf, "emuMMC GPP"); - break; - case EMMC_BOOT0 + 1: - strcat(txt_buf, "emuMMC BOOT0"); - break; - case EMMC_BOOT1 + 1: - strcat(txt_buf, "emuMMC BOOT1"); - break; - } - } - else - { - switch (usbs->partition) - { - case EMMC_GPP + 1: - strcat(txt_buf, "eMMC GPP"); - break; - case EMMC_BOOT0 + 1: + switch(part){ + case NYX_UMS_EMMC_BOOT0: strcat(txt_buf, "eMMC BOOT0"); break; - case EMMC_BOOT1 + 1: + case NYX_UMS_EMMC_BOOT1: strcat(txt_buf, "eMMC BOOT1"); break; - } + case NYX_UMS_EMMC_GPP: + strcat(txt_buf, "eMMC GPP"); + break; + case NYX_UMS_EMUMMC_GPP: + strcat(txt_buf, "emuMMC GPP"); + break; + case NYX_UMS_EMUMMC_BOOT0: + strcat(txt_buf, "emuMMC BOOT0"); + break; + case NYX_UMS_EMUMMC_BOOT1: + strcat(txt_buf, "emuMMC BOOT1"); + break; + case NYX_UMS_SD_CARD: + strcat(txt_buf, "SD Card"); + break; + case NYX_UMS_BOOT_STRG_GPP: + strcat(txt_buf, "Boot drive (eMMC GPP)"); + break; + case NYX_UMS_BOOT_STRG_BOOT1: + case NYX_UMS_BOOT_STRG_BOOT1_1MB: + strcat(txt_buf, "Boot drive (eMMC BOOT1)"); + break; + case NYX_UMS_BOOT_STRG_SD: + strcat(txt_buf, "Boot drive (SD Card)"); + break; } lv_mbox_set_text(mbox, txt_buf); @@ -325,6 +340,13 @@ static lv_res_t _create_mbox_ums_error(int error) lv_obj_set_style(dark_bg, &mbox_darken); lv_obj_set_size(dark_bg, LV_HOR_RES, LV_VER_RES); + + // 1: boot storage fail + // 2: no emu active + // 3: emmc fail + // 4: sd fail + // 5: file based + static const char *mbox_btn_map[] = { "\251", "\222OK", "\251", "" }; lv_obj_t * mbox = lv_mbox_create(dark_bg, NULL); lv_mbox_set_recolor_text(mbox, true); @@ -332,14 +354,26 @@ static lv_res_t _create_mbox_ums_error(int error) switch (error) { case 1: - lv_mbox_set_text(mbox, "#FF8000 USB Mass Storage#\n\n#FFFF00 Error mounting SD Card!#"); + lv_mbox_set_text(mbox, "#FF8000 USB Mass Storage#\n\n#FFFF00 Error mounting boot drive!#"); break; case 2: lv_mbox_set_text(mbox, "#FF8000 USB Mass Storage#\n\n#FFFF00 No emuMMC found active!#"); break; case 3: + lv_mbox_set_text(mbox, "#FF8000 USB Mass Storage#\n\n#FFFF00 Failed to initialize eMMC!#"); + break; + case 4: + lv_mbox_set_text(mbox, "#FF8000 USB Mass Storage#\n\n#FFFF00 Failed to initialize SD Card!#"); + break; + case 5: lv_mbox_set_text(mbox, "#FF8000 USB Mass Storage#\n\n#FFFF00 Active emuMMC is not partition based!#"); break; + case 6: + lv_mbox_set_text(mbox, "#FF8000 USB Mass Storage#\n\n#FFFF00 Corrupt emuMMC partition!#"); + break; + case 8: + lv_mbox_set_text(mbox, "#FF8000 USB Mass Storage#\n\n#FFFF00 Failed to initialize file based emuMMC!#"); + break; } lv_mbox_add_btns(mbox, mbox_btn_map, mbox_action); @@ -416,216 +450,270 @@ lv_res_t action_ums_sd(lv_obj_t *btn) usbs.system_maintenance = &manual_system_maintenance; usbs.set_text = &usb_gadget_set_text; - _create_mbox_ums(&usbs); + _create_mbox_ums(&usbs, NYX_UMS_SD_CARD); return LV_RES_OK; } +static lv_res_t _action_ums_boot_storage(lv_obj_t *btn){ + if(!nyx_emmc_check_battery_enough()){ + return LV_RES_OK; + } + + boot_storage_mount(); + + u8 drive = boot_storage_get_drive(); + + u32 part; + + usb_ctxt_t usbs; + usbs.type = drive == DRIVE_SD ? MMC_SD : MMC_EMMC; + switch(drive){ + case DRIVE_EMMC: + part = NYX_UMS_BOOT_STRG_GPP; + usbs.partition = EMMC_GPP + 1; + break; + case DRIVE_BOOT1: + part = NYX_UMS_BOOT_STRG_BOOT1; + usbs.partition = EMMC_BOOT1 + 1; + break; + case DRIVE_BOOT1_1MB: + part = NYX_UMS_BOOT_STRG_BOOT1_1MB; + usbs.partition = EMMC_BOOT1 + 1; + break; + case DRIVE_SD: + part = NYX_UMS_BOOT_STRG_SD; + usbs.partition = 0; + break; + default: + boot_storage_unmount(); + return LV_RES_OK; + } + + usbs.offset = drive == DRIVE_BOOT1_1MB ? (0x100000 / 0x200) : 0; + usbs.sectors = 0; + usbs.ro = false; + usbs.system_maintenance = &manual_system_maintenance; + usbs.set_text = &usb_gadget_set_text; + + _create_mbox_ums(&usbs, part); + + boot_storage_unmount(); + + return LV_RES_OK; +} + +static lv_res_t _ums_emmc(u32 part){ + if (!nyx_emmc_check_battery_enough()) + return LV_RES_OK; + + usb_ctxt_t usbs; + usbs.type = MMC_EMMC; + + switch(part){ + case NYX_UMS_EMMC_BOOT0: + usbs.partition = EMMC_BOOT0 + 1; + break; + case NYX_UMS_EMMC_BOOT1: + usbs.partition = EMMC_BOOT1 + 1; + break; + case NYX_UMS_EMMC_GPP: + usbs.partition = EMMC_GPP + 1; + break; + } + + usbs.offset = 0; + usbs.sectors = 0; + usbs.ro = usb_msc_emmc_read_only; + usbs.system_maintenance = &manual_system_maintenance; + usbs.set_text = &usb_gadget_set_text; + + return _create_mbox_ums(&usbs, part); +} + static lv_res_t _action_ums_emmc_boot0(lv_obj_t *btn) { - if (!nyx_emmc_check_battery_enough()) - return LV_RES_OK; - - usb_ctxt_t usbs; - usbs.type = MMC_EMMC; - usbs.partition = EMMC_BOOT0 + 1; - usbs.offset = 0; - usbs.sectors = 0; - usbs.ro = usb_msc_emmc_read_only; - usbs.system_maintenance = &manual_system_maintenance; - usbs.set_text = &usb_gadget_set_text; - - _create_mbox_ums(&usbs); - - return LV_RES_OK; + return _ums_emmc(NYX_UMS_EMMC_BOOT0); } static lv_res_t _action_ums_emmc_boot1(lv_obj_t *btn) { - if (!nyx_emmc_check_battery_enough()) - return LV_RES_OK; - - usb_ctxt_t usbs; - usbs.type = MMC_EMMC; - usbs.partition = EMMC_BOOT1 + 1; - usbs.offset = 0; - usbs.sectors = 0; - usbs.ro = usb_msc_emmc_read_only; - usbs.system_maintenance = &manual_system_maintenance; - usbs.set_text = &usb_gadget_set_text; - - _create_mbox_ums(&usbs); - - return LV_RES_OK; + return _ums_emmc(NYX_UMS_EMMC_BOOT1); } -static lv_res_t _action_ums_emmc_gpp(lv_obj_t *btn) +lv_res_t action_ums_emmc_gpp(lv_obj_t *btn) { + return _ums_emmc(NYX_UMS_EMMC_GPP); +} + +static lv_res_t _ums_emummc(u32 part){ if (!nyx_emmc_check_battery_enough()) return LV_RES_OK; usb_ctxt_t usbs; - usbs.type = MMC_EMMC; - usbs.partition = EMMC_GPP + 1; - usbs.offset = 0; - usbs.sectors = 0; - usbs.ro = usb_msc_emmc_read_only; - usbs.system_maintenance = &manual_system_maintenance; - usbs.set_text = &usb_gadget_set_text; + sdmmc_storage_t *storage; + emummc_cfg_t emu_info; - _create_mbox_ums(&usbs); + int error = !boot_storage_mount(); + bool file_based = false; + char path[0x80]; + + if(!error){ + load_emummc_cfg(&emu_info); + if(emu_info.enabled){ + error = 0; + if(emu_info.enabled == 4 && emu_info.sector){ + // emmc raw based + if(!emmc_initialize(false)){ + error = 3; + } + storage = &emmc_storage; + }else if(emu_info.enabled == 1 && emu_info.sector){ + // sd raw based + if(!sd_initialize(false)){ + error = 4; + } + storage = &sd_storage; + }else if((emu_info.enabled == 1 || emu_info.enabled == 4) && !emu_info.sector){ + // sd file based + if(emu_info.enabled == 1){ + if(!sd_mount()){ + error = 4; + } + }else{ + if(!emmc_mount()){ + error = 3; + } + } + if(error == 0){ + file_based = true; + if(emu_info.enabled == 1){ + strcpy(path, "sd:"); + }else{ + strcpy(path, "emmc:"); + } + strcat(path, emu_info.path); + strcat(path, "/eMMC/"); + if(!emummc_storage_file_based_init(path)){ + error = 8; + }else{ + switch(part){ + case NYX_UMS_EMUMMC_BOOT0: + emummc_storage_file_base_set_partition(1); + break; + case NYX_UMS_EMUMMC_BOOT1: + emummc_storage_file_base_set_partition(2); + break; + case NYX_UMS_EMUMMC_GPP: + emummc_storage_file_base_set_partition(0); + break; + } + } + } + }else{ + error = 2; + } + }else{ + error = 2; + } + + if(error == 0 && emu_info.enabled){ + error = 6; + if(file_based){ + usbs.offset = 0; + }else{ + usbs.offset = emu_info.sector; + switch(part){ + case NYX_UMS_EMUMMC_BOOT0: + usbs.offset += 0; + break; + case NYX_UMS_EMUMMC_BOOT1: + usbs.offset += 0x2000; + break; + case NYX_UMS_EMUMMC_GPP: + usbs.offset += 0x4000; + break; + } + } + + if(part == NYX_UMS_EMUMMC_GPP){ + if(file_based){ + error = 8; + u32 sz = emummc_storage_file_based_get_total_gpp_size(path); + if(sz){ + error = 0; + } + usbs.sectors = sz; + }else{ + int res; + gpt_header_t *gpt_hdr = malloc(sizeof(*gpt_hdr)); + res = sdmmc_storage_read(storage, usbs.offset + 1, 1, gpt_hdr); + if(res){ + if(!memcmp(&gpt_hdr->signature, "EFI PART", 8)){ + error = 0; + usbs.sectors = gpt_hdr->alt_lba + 1; + } + } + free(gpt_hdr); + } + }else{ + error = 0; + usbs.sectors = 0x2000; + } + } + + if(emu_info.path){ + free(emu_info.path); + } + if(emu_info.nintendo_path){ + free(emu_info.nintendo_path); + } + } + + if(error){ + _create_mbox_ums_error(error); + }else{ + if(file_based){ + usbs.type = emu_info.enabled == 4 ? MMC_EMUMMC_FILE_EMMC : MMC_EMUMMC_FILE; + }else{ + usbs.type = emu_info.enabled == 4 ? MMC_EMUMMC_RAW_EMMC : MMC_EMUMMC_RAW_SD; + } + switch(part){ + case NYX_UMS_EMUMMC_BOOT0: + usbs.partition = EMMC_GPP + 1; + break; + case NYX_UMS_EMUMMC_BOOT1: + usbs.partition = EMMC_BOOT1 + 1; + break; + case NYX_UMS_EMUMMC_GPP: + usbs.partition = EMMC_BOOT0 + 1; + break; + } + usbs.ro = usb_msc_emmc_read_only; + usbs.system_maintenance = &manual_system_maintenance; + usbs.set_text = &usb_gadget_set_text; + _create_mbox_ums(&usbs, part); + } + + emummc_storage_file_based_end(); + boot_storage_unmount(); return LV_RES_OK; } static lv_res_t _action_ums_emuemmc_boot0(lv_obj_t *btn) { - if (!nyx_emmc_check_battery_enough()) - return LV_RES_OK; - - usb_ctxt_t usbs; - - int error = !sd_mount(); - if (!error) - { - emummc_cfg_t emu_info; - load_emummc_cfg(&emu_info); - - error = 2; - if (emu_info.enabled) - { - error = 3; - if (emu_info.sector) - { - error = 0; - usbs.offset = emu_info.sector; - } - } - - if (emu_info.path) - free(emu_info.path); - if (emu_info.nintendo_path) - free(emu_info.nintendo_path); - } - sd_unmount(); - - if (error) - _create_mbox_ums_error(error); - else - { - usbs.type = MMC_SD; - usbs.partition = EMMC_BOOT0 + 1; - usbs.sectors = 0x2000; // Forced 4MB. - usbs.ro = usb_msc_emmc_read_only; - usbs.system_maintenance = &manual_system_maintenance; - usbs.set_text = &usb_gadget_set_text; - _create_mbox_ums(&usbs); - } - - return LV_RES_OK; + return _ums_emummc(NYX_UMS_EMUMMC_BOOT0); } static lv_res_t _action_ums_emuemmc_boot1(lv_obj_t *btn) { - if (!nyx_emmc_check_battery_enough()) - return LV_RES_OK; - - usb_ctxt_t usbs; - - int error = !sd_mount(); - if (!error) - { - emummc_cfg_t emu_info; - load_emummc_cfg(&emu_info); - - error = 2; - if (emu_info.enabled) - { - error = 3; - if (emu_info.sector) - { - error = 0; - usbs.offset = emu_info.sector + 0x2000; - } - } - - if (emu_info.path) - free(emu_info.path); - if (emu_info.nintendo_path) - free(emu_info.nintendo_path); - } - sd_unmount(); - - if (error) - _create_mbox_ums_error(error); - else - { - usbs.type = MMC_SD; - usbs.partition = EMMC_BOOT1 + 1; - usbs.sectors = 0x2000; // Forced 4MB. - usbs.ro = usb_msc_emmc_read_only; - usbs.system_maintenance = &manual_system_maintenance; - usbs.set_text = &usb_gadget_set_text; - _create_mbox_ums(&usbs); - } - - return LV_RES_OK; + return _ums_emummc(NYX_UMS_EMUMMC_BOOT1); } static lv_res_t _action_ums_emuemmc_gpp(lv_obj_t *btn) { - if (!nyx_emmc_check_battery_enough()) - return LV_RES_OK; - - usb_ctxt_t usbs; - - int error = !sd_mount(); - if (!error) - { - emummc_cfg_t emu_info; - load_emummc_cfg(&emu_info); - - error = 2; - if (emu_info.enabled) - { - error = 3; - if (emu_info.sector) - { - error = 1; - usbs.offset = emu_info.sector + 0x4000; - - u8 *gpt = malloc(SD_BLOCKSIZE); - if (sdmmc_storage_read(&sd_storage, usbs.offset + 1, 1, gpt)) - { - if (!memcmp(gpt, "EFI PART", 8)) - { - error = 0; - usbs.sectors = *(u32 *)(gpt + 0x20) + 1; // Backup LBA + 1. - } - } - } - } - - if (emu_info.path) - free(emu_info.path); - if (emu_info.nintendo_path) - free(emu_info.nintendo_path); - } - sd_unmount(); - - if (error) - _create_mbox_ums_error(error); - else - { - usbs.type = MMC_SD; - usbs.partition = EMMC_GPP + 1; - usbs.ro = usb_msc_emmc_read_only; - usbs.system_maintenance = &manual_system_maintenance; - usbs.set_text = &usb_gadget_set_text; - _create_mbox_ums(&usbs); - } - - return LV_RES_OK; + return _ums_emummc(NYX_UMS_EMUMMC_GPP); } void nyx_run_ums(void *param) @@ -650,7 +738,7 @@ void nyx_run_ums(void *param) _action_ums_emmc_boot1(NULL); break; case NYX_UMS_EMMC_GPP: - _action_ums_emmc_gpp(NULL); + action_ums_emmc_gpp(NULL); break; case NYX_UMS_EMUMMC_BOOT0: _action_ums_emuemmc_boot0(NULL); @@ -717,18 +805,33 @@ static lv_res_t _create_window_usb_tools(lv_obj_t *parent) lv_obj_t *label_txt2 = lv_label_create(h1, NULL); lv_label_set_recolor(label_txt2, true); lv_label_set_static_text(label_txt2, - "Allows you to mount the SD Card to a PC/Phone.\n" + "Allows you to mount the SD Card or boot drive to a PC/Phone.\n" "#C7EA46 All operating systems are supported. Access is# #FF8000 Read/Write.#"); lv_obj_set_style(label_txt2, &hint_small_style); lv_obj_align(label_txt2, btn1, LV_ALIGN_OUT_BOTTOM_LEFT, 0, LV_DPI / 3); + // Create Boot Storage UMS button + lv_obj_t *btn_boot_strg = lv_btn_create(h1, btn1); + label_btn = lv_label_create(btn_boot_strg, NULL); + lv_label_set_text(label_btn, boot_storage_get_drive() == DRIVE_SD ? SYMBOL_SD " Boot Drive" : SYMBOL_CHIP " Boot Drive"); + lv_obj_align(btn_boot_strg, btn1, LV_ALIGN_OUT_RIGHT_MID, LV_DPI / 10, 0); + lv_btn_set_action(btn_boot_strg, LV_BTN_ACTION_CLICK, _action_ums_boot_storage); + + if(!boot_storage_mount()){ + lv_obj_set_click(btn_boot_strg, false); + lv_btn_set_state(btn_boot_strg, LV_BTN_STATE_INA); + } + boot_storage_unmount(); + + + // Create RAW GPP button. lv_obj_t *btn_gpp = lv_btn_create(h1, btn1); label_btn = lv_label_create(btn_gpp, NULL); lv_label_set_static_text(label_btn, SYMBOL_CHIP" eMMC RAW GPP"); lv_obj_align(btn_gpp, label_txt2, LV_ALIGN_OUT_BOTTOM_LEFT, 0, LV_DPI / 2); - lv_btn_set_action(btn_gpp, LV_BTN_ACTION_CLICK, _action_ums_emmc_gpp); + lv_btn_set_action(btn_gpp, LV_BTN_ACTION_CLICK, action_ums_emmc_gpp); // Create BOOT0 button. lv_obj_t *btn_boot0 = lv_btn_create(h1, btn1); @@ -926,6 +1029,7 @@ out: return res; } + static lv_res_t _create_window_unset_abit_tool(lv_obj_t *btn) { lv_obj_t *win = nyx_create_standard_window(SYMBOL_COPY" Fix Archive Bit (All folders)"); @@ -956,7 +1060,8 @@ static lv_res_t _create_window_unset_abit_tool(lv_obj_t *btn) lv_obj_t * lb_val = lv_label_create(val, lb_desc); char *path = malloc(0x1000); - path[0] = 0; + strcpy(path, "sd:"); + // path[0] = 0; lv_label_set_text(lb_val, ""); lv_obj_set_width(lb_val, lv_obj_get_width(val)); @@ -1128,23 +1233,15 @@ static lv_res_t _create_window_dump_pk12_tool(lv_obj_t *btn) lv_obj_t *desc = lv_cont_create(win, NULL); lv_obj_set_size(desc, LV_HOR_RES * 10 / 11, LV_VER_RES - (LV_DPI * 12 / 7)); - lv_obj_t *lb_desc = lv_label_create(desc, NULL); + lv_obj_t * lb_desc = lv_label_create(desc, NULL); lv_obj_set_style(lb_desc, &monospace_text); lv_label_set_long_mode(lb_desc, LV_LABEL_LONG_BREAK); lv_label_set_recolor(lb_desc, true); - lv_obj_set_width(lb_desc, lv_obj_get_width(desc) / 2); + lv_obj_set_width(lb_desc, lv_obj_get_width(desc)); - lv_obj_t *lb_desc2 = lv_label_create(desc, NULL); - lv_obj_set_style(lb_desc2, &monospace_text); - lv_label_set_long_mode(lb_desc2, LV_LABEL_LONG_BREAK); - lv_label_set_recolor(lb_desc2, true); - lv_obj_set_width(lb_desc2, lv_obj_get_width(desc) / 2); - lv_label_set_text(lb_desc2, " "); - - lv_obj_align(lb_desc2, lb_desc, LV_ALIGN_OUT_RIGHT_TOP, 0, 0); - - if (!sd_mount()) + if (!boot_storage_mount()) { + // may not be sd, fix error lv_label_set_text(lb_desc, "#FFDD00 Failed to init SD!#"); goto out_end; @@ -1157,7 +1254,7 @@ static lv_res_t _create_window_dump_pk12_tool(lv_obj_t *btn) u8 *warmboot = (u8 *)zalloc(SZ_256K); u8 *secmon = (u8 *)zalloc(SZ_256K); u8 *loader = (u8 *)zalloc(SZ_256K); - u8 *pkg2 = (u8 *)zalloc(SZ_8M); + u8 *pkg2 = NULL; char *txt_buf = (char *)malloc(SZ_16K); @@ -1168,332 +1265,267 @@ static lv_res_t _create_window_dump_pk12_tool(lv_obj_t *btn) goto out_free; } - char *bct_paths[2] = { - "/pkg/main", - "/pkg/safe" - }; + emmc_set_partition(EMMC_BOOT0); - char *pkg1_paths[2] = { - "/pkg/main/pkg1", - "/pkg/safe/pkg1" - }; + // Read package1. + static const u32 BOOTLOADER_SIZE = SZ_256K; + static const u32 BOOTLOADER_MAIN_OFFSET = 0x100000; + static const u32 HOS_EKS_OFFSET = 0x180000; - char *pkg2_partitions[2] = { - "BCPKG2-1-Normal-Main", - "BCPKG2-3-SafeMode-Main" - }; + char *build_date = malloc(32); + u32 pk1_offset = h_cfg.t210b01 ? sizeof(bl_hdr_t210b01_t) : 0; // Skip T210B01 OEM header. + sdmmc_storage_read(&emmc_storage, BOOTLOADER_MAIN_OFFSET / EMMC_BLOCKSIZE, BOOTLOADER_SIZE / EMMC_BLOCKSIZE, pkg1); - char *pkg2_paths[2] = { - "/pkg/main/pkg2", - "/pkg/safe/pkg2" - }; + const pkg1_id_t *pkg1_id = pkg1_identify(pkg1 + pk1_offset, build_date); - char *pkg2ini_paths[2] = { - "/pkg/main/pkg2/ini", - "/pkg/safe/pkg2/ini" - }; + s_printf(txt_buf, "#00DDFF Found pkg1 ('%s')#\n\n", build_date); + free(build_date); + lv_label_set_text(lb_desc, txt_buf); + manual_system_maintenance(true); - // Create main directories. - emmcsn_path_impl(path, "/pkg", "", &emmc_storage); - emmcsn_path_impl(path, "/pkg/main", "", &emmc_storage); - emmcsn_path_impl(path, "/pkg/safe", "", &emmc_storage); + // Dump package1 in its encrypted state. + emmcsn_path_impl(path, "/pkg1", "pkg1_enc.bin", &emmc_storage); + bool res = boot_storage_save_to_file(pkg1, BOOTLOADER_SIZE, path); - // Parse eMMC GPT. - emmc_set_partition(EMMC_GPP); - LIST_INIT(gpt); - emmc_gpt_parse(&gpt); - - lv_obj_t *lb_log = lb_desc; - for (u32 idx = 0; idx < 2; idx++) + // Exit if unknown. + if (!pkg1_id) { - if (idx) - lb_log = lb_desc2; - - // Read package1. - char *build_date = malloc(32); - u32 pk1_offset = h_cfg.t210b01 ? sizeof(bl_hdr_t210b01_t) : 0; // Skip T210B01 OEM header. - emmc_set_partition(!idx ? EMMC_BOOT0 : EMMC_BOOT1); - sdmmc_storage_read(&emmc_storage, - !idx ? PKG1_BOOTLOADER_MAIN_OFFSET : PKG1_BOOTLOADER_SAFE_OFFSET, PKG1_BOOTLOADER_SIZE / EMMC_BLOCKSIZE, pkg1); - - const pkg1_id_t *pkg1_id = pkg1_identify(pkg1 + pk1_offset, build_date); - - s_printf(txt_buf, "#00DDFF Found %s pkg1 ('%s')#\n\n", !idx ? "Main" : "Safe", build_date); - lv_label_set_text(lb_log, txt_buf); + strcat(txt_buf, "#FFDD00 Unknown pkg1 version!#"); + lv_label_set_text(lb_desc, txt_buf); manual_system_maintenance(true); - free(build_date); - // Dump package1 in its encrypted state. - emmcsn_path_impl(path, pkg1_paths[idx], "pkg1_enc.bin", &emmc_storage); - bool res = sd_save_to_file(pkg1, PKG1_BOOTLOADER_SIZE, path); - - // Exit if unknown. - if (!pkg1_id) + if (!res) { - strcat(txt_buf, "#FFDD00 Unknown pkg1 version!#"); - lv_label_set_text(lb_log, txt_buf); + strcat(txt_buf, "\nEncrypted pkg1 dumped to pkg1_enc.bin"); + lv_label_set_text(lb_desc, txt_buf); manual_system_maintenance(true); - - if (!res) - { - strcat(txt_buf, "\nEncrypted pkg1 extracted to pkg1_enc.bin"); - lv_label_set_text(lb_log, txt_buf); - manual_system_maintenance(true); - } - - goto out; } - mkey = pkg1_id->mkey; + goto out_free; + } - tsec_ctxt_t tsec_ctxt = {0}; - tsec_ctxt.fw = (void *)(pkg1 + pkg1_id->tsec_off); - tsec_ctxt.pkg1 = (void *)pkg1; - tsec_ctxt.pkg11_off = pkg1_id->pkg11_off; + mkey = pkg1_id->mkey; - // Read the correct eks for older HOS versions. - const u32 eks_size = sizeof(pkg1_eks_t); - pkg1_eks_t *eks = (pkg1_eks_t *)malloc(eks_size); - emmc_set_partition(EMMC_BOOT0); - sdmmc_storage_read(&emmc_storage, PKG1_HOS_EKS_OFFSET + (mkey * eks_size) / EMMC_BLOCKSIZE, - eks_size / EMMC_BLOCKSIZE, eks); + tsec_ctxt_t tsec_ctxt = {0}; + tsec_ctxt.fw = (void *)(pkg1 + pkg1_id->tsec_off); + tsec_ctxt.pkg1 = (void *)pkg1; + tsec_ctxt.pkg11_off = pkg1_id->pkg11_off; - // Generate keys. - hos_keygen(eks, mkey, &tsec_ctxt); - free(eks); + // Read the correct eks for older HOS versions. + const u32 eks_size = sizeof(pkg1_eks_t); + pkg1_eks_t *eks = (pkg1_eks_t *)malloc(eks_size); + emmc_set_partition(EMMC_BOOT0); + sdmmc_storage_read(&emmc_storage, HOS_EKS_OFFSET + (mkey * eks_size) / EMMC_BLOCKSIZE, + eks_size / EMMC_BLOCKSIZE, eks); - // Decrypt. - if (h_cfg.t210b01 || mkey <= HOS_MKEY_VER_600) + // Generate keys. + hos_keygen(eks, mkey, &tsec_ctxt); + free(eks); + + if (h_cfg.t210b01 || mkey <= HOS_MKEY_VER_600) + { + if (!pkg1_decrypt(pkg1_id, pkg1)) { - if (!pkg1_decrypt(pkg1_id, pkg1)) - { - strcat(txt_buf, "#FFDD00 Pkg1 decryption failed!#\n"); - if (h_cfg.t210b01) - strcat(txt_buf, "#FFDD00 Is BEK missing?#\n"); - lv_label_set_text(lb_log, txt_buf); - goto out; - } - } - - // Dump the BCTs from blocks 2/3 (backup) which are normally valid. - static const u32 BCT_SIZE = 0x2800; - static const u32 BLK_SIZE = SZ_16K / EMMC_BLOCKSIZE; - u8 *bct = (u8 *)zalloc(BCT_SIZE); - sdmmc_storage_read(&emmc_storage, BLK_SIZE * 2 + BLK_SIZE * idx, BCT_SIZE / EMMC_BLOCKSIZE, bct); - emmcsn_path_impl(path, bct_paths[idx], "bct.bin", &emmc_storage); - if (sd_save_to_file(bct, 0x2800, path)) - goto out; - if (h_cfg.t210b01) - { - se_aes_iv_clear(13); - se_aes_crypt_cbc(13, DECRYPT, bct + 0x480, bct + 0x480, BCT_SIZE - 0x480); - emmcsn_path_impl(path, bct_paths[idx], "bct_decr.bin", &emmc_storage); - if (sd_save_to_file(bct, 0x2800, path)) - goto out; - } - - // Dump package1.1 contents. - if (h_cfg.t210b01 || mkey <= HOS_MKEY_VER_620) - { - pkg1_unpack(warmboot, secmon, loader, pkg1_id, pkg1 + pk1_offset); - pk11_hdr_t *hdr_pk11 = (pk11_hdr_t *)(pkg1 + pk1_offset + pkg1_id->pkg11_off + 0x20); - - // Display info. - s_printf(txt_buf + strlen(txt_buf), - "#C7EA46 NX Bootloader size: #0x%05X\n" - "#C7EA46 Secure monitor size: #0x%05X\n" - "#C7EA46 Warmboot size: #0x%05X\n\n", - hdr_pk11->ldr_size, hdr_pk11->sm_size, hdr_pk11->wb_size); - - lv_label_set_text(lb_log, txt_buf); - manual_system_maintenance(true); - - // Dump package1.1. - emmcsn_path_impl(path, pkg1_paths[idx], "pkg1_decr.bin", &emmc_storage); - if (sd_save_to_file(pkg1, SZ_256K, path)) - goto out; - strcat(txt_buf, "Package1 extracted to pkg1_decr.bin\n"); - lv_label_set_text(lb_log, txt_buf); - manual_system_maintenance(true); - - // Dump nxbootloader. - emmcsn_path_impl(path, pkg1_paths[idx], "nxloader.bin", &emmc_storage); - if (sd_save_to_file(loader, hdr_pk11->ldr_size, path)) - goto out; - strcat(txt_buf, "NX Bootloader extracted to nxloader.bin\n"); - lv_label_set_text(lb_log, txt_buf); - manual_system_maintenance(true); - - // Dump secmon. - emmcsn_path_impl(path, pkg1_paths[idx], "secmon.bin", &emmc_storage); - if (sd_save_to_file(secmon, hdr_pk11->sm_size, path)) - goto out; - strcat(txt_buf, "Secure Monitor extracted to secmon.bin\n"); - lv_label_set_text(lb_log, txt_buf); - manual_system_maintenance(true); - - // Dump warmboot. - emmcsn_path_impl(path, pkg1_paths[idx], "warmboot.bin", &emmc_storage); - if (sd_save_to_file(warmboot, hdr_pk11->wb_size, path)) - goto out; - // If T210B01, save a copy of decrypted warmboot binary also. + strcat(txt_buf, "#FFDD00 Pkg1 decryption failed!#\n"); if (h_cfg.t210b01) - { - - se_aes_iv_clear(13); - se_aes_crypt_cbc(13, DECRYPT, warmboot + 0x330, warmboot + 0x330, hdr_pk11->wb_size - 0x330); - emmcsn_path_impl(path, pkg1_paths[idx], "warmboot_dec.bin", &emmc_storage); - if (sd_save_to_file(warmboot, hdr_pk11->wb_size, path)) - goto out; - } - strcat(txt_buf, "Warmboot extracted to warmboot.bin\n\n"); - lv_label_set_text(lb_log, txt_buf); - manual_system_maintenance(true); + strcat(txt_buf, "#FFDD00 Is BEK missing?#\n"); + lv_label_set_text(lb_desc, txt_buf); + goto out_free; } + } - // Find and dump package2 partition. - emmc_set_partition(EMMC_GPP); - emmc_part_t *pkg2_part = emmc_part_find(&gpt, pkg2_partitions[idx]); - if (!pkg2_part) - goto out; - - // Read in package2 header and get package2 real size. - static const u32 PKG2_OFFSET = 0x4000; - u8 *tmp = (u8 *)malloc(EMMC_BLOCKSIZE); - emmc_part_read(pkg2_part, PKG2_OFFSET / EMMC_BLOCKSIZE, 1, tmp); - u32 *hdr_pkg2_raw = (u32 *)(tmp + 0x100); - u32 pkg2_size = hdr_pkg2_raw[0] ^ hdr_pkg2_raw[2] ^ hdr_pkg2_raw[3]; - free(tmp); - - // Read in package2. - u32 pkg2_size_aligned = ALIGN(pkg2_size, EMMC_BLOCKSIZE); - emmc_part_read(pkg2_part, PKG2_OFFSET / EMMC_BLOCKSIZE, pkg2_size_aligned / EMMC_BLOCKSIZE, pkg2); - - // Dump encrypted package2. - emmcsn_path_impl(path, pkg2_paths[idx], "pkg2_encr.bin", &emmc_storage); - res = sd_save_to_file(pkg2, pkg2_size, path); - - // Decrypt package2 and parse KIP1 blobs in INI1 section. - pkg2_hdr_t *pkg2_hdr = pkg2_decrypt(pkg2, mkey); - if (!pkg2_hdr) - { - strcat(txt_buf, "#FFDD00 Pkg2 decryption failed!#"); - lv_label_set_text(lb_log, txt_buf); - manual_system_maintenance(true); - - if (!res) - { - strcat(txt_buf, "\npkg2 encrypted extracted to pkg2_encr.bin\n"); - lv_label_set_text(lb_log, txt_buf); - manual_system_maintenance(true); - } - - // Clear EKS slot, in case something went wrong with tsec keygen. - hos_eks_clear(mkey); - - goto out; - } + if (h_cfg.t210b01 || mkey <= HOS_MKEY_VER_620) + { + pkg1_unpack(warmboot, secmon, loader, pkg1_id, pkg1 + pk1_offset); + pk11_hdr_t *hdr_pk11 = (pk11_hdr_t *)(pkg1 + pk1_offset + pkg1_id->pkg11_off + 0x20); // Display info. s_printf(txt_buf + strlen(txt_buf), - "#C7EA46 Kernel size: #0x%06X\n" - "#C7EA46 INI1 size: #0x%06X\n\n", - pkg2_hdr->sec_size[PKG2_SEC_KERNEL], pkg2_hdr->sec_size[PKG2_SEC_INI1]); + "#C7EA46 NX Bootloader size: #0x%05X\n" + "#C7EA46 Secure monitor addr: #0x%05X\n" + "#C7EA46 Secure monitor size: #0x%05X\n" + "#C7EA46 Warmboot addr: #0x%05X\n" + "#C7EA46 Warmboot size: #0x%05X\n\n", + hdr_pk11->ldr_size, pkg1_id->secmon_base, hdr_pk11->sm_size, pkg1_id->warmboot_base, hdr_pk11->wb_size); - lv_label_set_text(lb_log, txt_buf); + lv_label_set_text(lb_desc, txt_buf); manual_system_maintenance(true); - // Dump pkg2.1. - emmcsn_path_impl(path, pkg2_paths[idx], "pkg2_decr.bin", &emmc_storage); - if (sd_save_to_file(pkg2, pkg2_hdr->sec_size[PKG2_SEC_KERNEL] + pkg2_hdr->sec_size[PKG2_SEC_INI1], path)) - goto out; - strcat(txt_buf, "Package2 extracted to pkg2_decr.bin\n"); - lv_label_set_text(lb_log, txt_buf); + // Dump package1.1. + emmcsn_path_impl(path, "/pkg1", "pkg1_decr.bin", &emmc_storage); + if (boot_storage_save_to_file(pkg1, SZ_256K, path)) + goto out_free; + strcat(txt_buf, "pkg1 dumped to pkg1_decr.bin\n"); + lv_label_set_text(lb_desc, txt_buf); manual_system_maintenance(true); - // Dump kernel. - emmcsn_path_impl(path, pkg2_paths[idx], "kernel.bin", &emmc_storage); - if (sd_save_to_file(pkg2_hdr->data, pkg2_hdr->sec_size[PKG2_SEC_KERNEL], path)) - goto out; - strcat(txt_buf, "Kernel extracted to kernel.bin\n"); - lv_label_set_text(lb_log, txt_buf); + // Dump nxbootloader. + emmcsn_path_impl(path, "/pkg1", "nxloader.bin", &emmc_storage); + if (boot_storage_save_to_file(loader, hdr_pk11->ldr_size, path)) + goto out_free; + strcat(txt_buf, "NX Bootloader dumped to nxloader.bin\n"); + lv_label_set_text(lb_desc, txt_buf); manual_system_maintenance(true); - // Dump INI1. - u32 ini1_off = pkg2_hdr->sec_size[PKG2_SEC_KERNEL]; - u32 ini1_size = pkg2_hdr->sec_size[PKG2_SEC_INI1]; - if (!ini1_size) + // Dump secmon. + emmcsn_path_impl(path, "/pkg1", "secmon.bin", &emmc_storage); + if (boot_storage_save_to_file(secmon, hdr_pk11->sm_size, path)) + goto out_free; + strcat(txt_buf, "Secure Monitor dumped to secmon.bin\n"); + lv_label_set_text(lb_desc, txt_buf); + manual_system_maintenance(true); + + // Dump warmboot. + emmcsn_path_impl(path, "/pkg1", "warmboot.bin", &emmc_storage); + if (boot_storage_save_to_file(warmboot, hdr_pk11->wb_size, path)) + goto out_free; + // If T210B01, save a copy of decrypted warmboot binary also. + if (h_cfg.t210b01) { - pkg2_get_newkern_info(pkg2_hdr->data); - ini1_off = pkg2_newkern_ini1_start; - ini1_size = pkg2_newkern_ini1_end - pkg2_newkern_ini1_start; + + se_aes_iv_clear(13); + se_aes_crypt_cbc(13, DECRYPT, warmboot + 0x330, hdr_pk11->wb_size - 0x330, + warmboot + 0x330, hdr_pk11->wb_size - 0x330); + emmcsn_path_impl(path, "/pkg1", "warmboot_dec.bin", &emmc_storage); + if (boot_storage_save_to_file(warmboot, hdr_pk11->wb_size, path)) + goto out_free; } - - if (!ini1_off) - { - strcat(txt_buf, "#FFDD00 Failed to dump INI1 and kips!#\n"); - goto out; - } - - pkg2_ini1_t *ini1 = (pkg2_ini1_t *)(pkg2_hdr->data + ini1_off); - emmcsn_path_impl(path, pkg2_paths[idx], "ini1.bin", &emmc_storage); - if (sd_save_to_file(ini1, ini1_size, path)) - goto out; - - strcat(txt_buf, "INI1 extracted to ini1.bin\n"); - lv_label_set_text(lb_log, txt_buf); + strcat(txt_buf, "Warmboot dumped to warmboot.bin\n\n"); + lv_label_set_text(lb_desc, txt_buf); manual_system_maintenance(true); - - char filename[32]; - u8 *ptr = (u8 *)ini1; - ptr += sizeof(pkg2_ini1_t); - - // Dump all kips. - for (u32 i = 0; i < ini1->num_procs; i++) - { - pkg2_kip1_t *kip1 = (pkg2_kip1_t *)ptr; - u32 kip1_size = pkg2_calc_kip1_size(kip1); - char *kip_name = kip1->name; - - // Check if FS supports exFAT. - if (!strcmp("FS", kip_name)) - { - u8 *ro_data = malloc(SZ_4M); - u32 offset = (kip1->flags & BIT(KIP_TEXT)) ? kip1->sections[KIP_TEXT].size_comp : - kip1->sections[KIP_TEXT].size_decomp; - u32 size_comp = kip1->sections[KIP_RODATA].size_comp; - u32 size_decomp = kip1->sections[KIP_RODATA].size_decomp; - if (kip1->flags & BIT(KIP_RODATA)) - blz_uncompress_srcdest(&kip1->data[offset], size_comp, ro_data, size_decomp); - else - memcpy(ro_data, &kip1->data[offset], size_decomp); - - for (u32 i = 0; i < 0x100; i+= sizeof(u32)) - { - // Check size and name of nss matches. - if (*(u32 *)&ro_data[i] == 8 && !memcmp("fs.exfat", &ro_data[i + 4], 8)) - { - kip_name = "FS_exfat"; - break; - } - } - - free(ro_data); - } - - s_printf(filename, "%s.kip1", kip_name); - emmcsn_path_impl(path, pkg2ini_paths[idx], filename, &emmc_storage); - if (sd_save_to_file(kip1, kip1_size, path)) - goto out; - - s_printf(txt_buf + strlen(txt_buf), "- Extracted %s.kip1\n", kip_name); - lv_label_set_text(lb_log, txt_buf); - manual_system_maintenance(true); - - ptr += kip1_size; - } } + // Dump package2.1. + emmc_set_partition(EMMC_GPP); + // Parse eMMC GPT. + LIST_INIT(gpt); + emmc_gpt_parse(&gpt); + // Find package2 partition. + emmc_part_t *pkg2_part = emmc_part_find(&gpt, "BCPKG2-1-Normal-Main"); + if (!pkg2_part) + goto out; + + // Read in package2 header and get package2 real size. + u8 *tmp = (u8 *)malloc(EMMC_BLOCKSIZE); + emmc_part_read(pkg2_part, 0x4000 / EMMC_BLOCKSIZE, 1, tmp); + u32 *hdr_pkg2_raw = (u32 *)(tmp + 0x100); + u32 pkg2_size = hdr_pkg2_raw[0] ^ hdr_pkg2_raw[2] ^ hdr_pkg2_raw[3]; + free(tmp); + // Read in package2. + u32 pkg2_size_aligned = ALIGN(pkg2_size, EMMC_BLOCKSIZE); + pkg2 = malloc(pkg2_size_aligned); + emmc_part_read(pkg2_part, 0x4000 / EMMC_BLOCKSIZE, + pkg2_size_aligned / EMMC_BLOCKSIZE, pkg2); + + // Dump encrypted package2. + emmcsn_path_impl(path, "/pkg2", "pkg2_encr.bin", &emmc_storage); + res = boot_storage_save_to_file(pkg2, pkg2_size, path); + + // Decrypt package2 and parse KIP1 blobs in INI1 section. + pkg2_hdr_t *pkg2_hdr = pkg2_decrypt(pkg2, mkey); + if (!pkg2_hdr) + { + strcat(txt_buf, "#FFDD00 Pkg2 decryption failed!#"); + lv_label_set_text(lb_desc, txt_buf); + manual_system_maintenance(true); + + if (!res) + { + strcat(txt_buf, "\npkg2 encrypted dumped to pkg2_encr.bin\n"); + lv_label_set_text(lb_desc, txt_buf); + manual_system_maintenance(true); + } + + // Clear EKS slot, in case something went wrong with tsec keygen. + hos_eks_clear(mkey); + + goto out; + } + + // Display info. + s_printf(txt_buf + strlen(txt_buf), + "#C7EA46 Kernel size: #0x%05X\n" + "#C7EA46 INI1 size: #0x%05X\n\n", + pkg2_hdr->sec_size[PKG2_SEC_KERNEL], pkg2_hdr->sec_size[PKG2_SEC_INI1]); + + lv_label_set_text(lb_desc, txt_buf); + manual_system_maintenance(true); + + // Dump pkg2.1. + emmcsn_path_impl(path, "/pkg2", "pkg2_decr.bin", &emmc_storage); + if (boot_storage_save_to_file(pkg2, pkg2_hdr->sec_size[PKG2_SEC_KERNEL] + pkg2_hdr->sec_size[PKG2_SEC_INI1], path)) + goto out; + strcat(txt_buf, "pkg2 dumped to pkg2_decr.bin\n"); + lv_label_set_text(lb_desc, txt_buf); + manual_system_maintenance(true); + + // Dump kernel. + emmcsn_path_impl(path, "/pkg2", "kernel.bin", &emmc_storage); + if (boot_storage_save_to_file(pkg2_hdr->data, pkg2_hdr->sec_size[PKG2_SEC_KERNEL], path)) + goto out; + strcat(txt_buf, "Kernel dumped to kernel.bin\n"); + lv_label_set_text(lb_desc, txt_buf); + manual_system_maintenance(true); + + // Dump INI1. + u32 ini1_off = pkg2_hdr->sec_size[PKG2_SEC_KERNEL]; + u32 ini1_size = pkg2_hdr->sec_size[PKG2_SEC_INI1]; + if (!ini1_size) + { + pkg2_get_newkern_info(pkg2_hdr->data); + ini1_off = pkg2_newkern_ini1_start; + ini1_size = pkg2_newkern_ini1_end - pkg2_newkern_ini1_start; + } + + if (!ini1_off) + { + strcat(txt_buf, "#FFDD00 Failed to dump INI1 and kips!#\n"); + goto out; + } + + pkg2_ini1_t *ini1 = (pkg2_ini1_t *)(pkg2_hdr->data + ini1_off); + emmcsn_path_impl(path, "/pkg2", "ini1.bin", &emmc_storage); + if (boot_storage_save_to_file(ini1, ini1_size, path)) + goto out; + + strcat(txt_buf, "INI1 dumped to ini1.bin\n\n"); + lv_label_set_text(lb_desc, txt_buf); + manual_system_maintenance(true); + + char filename[32]; + u8 *ptr = (u8 *)ini1; + ptr += sizeof(pkg2_ini1_t); + + // Dump all kips. + u8 *kip_buffer = (u8 *)malloc(SZ_4M); + + for (u32 i = 0; i < ini1->num_procs; i++) + { + pkg2_kip1_t *kip1 = (pkg2_kip1_t *)ptr; + u32 kip1_size = pkg2_calc_kip1_size(kip1); + + s_printf(filename, "%s.kip1", kip1->name); + if ((u32)kip1 % 8) + { + memcpy(kip_buffer, kip1, kip1_size); + kip1 = (pkg2_kip1_t *)kip_buffer; + } + + emmcsn_path_impl(path, "/pkg2/ini1", filename, &emmc_storage); + if (boot_storage_save_to_file(kip1, kip1_size, path)) + { + free(kip_buffer); + goto out; + } + + s_printf(txt_buf + strlen(txt_buf), "%s kip dumped to %s.kip1\n", kip1->name, kip1->name); + lv_label_set_text(lb_desc, txt_buf); + manual_system_maintenance(true); + + ptr += kip1_size; + } + free(kip_buffer); + out: emmc_gpt_free(&gpt); out_free: @@ -1505,6 +1537,7 @@ out_free: free(txt_buf); emmc_end(); sd_unmount(); + boot_storage_unmount(); if (mkey >= HOS_MKEY_VER_620) se_aes_key_clear(8); @@ -1515,6 +1548,49 @@ out_end: return LV_RES_OK; } +#define PARTITION_HOLD_MS 3000 + +static lv_task_t *partition_hold_task; +static lv_obj_t *partition_hold_btn; +static bool partition_hold_triggered; +static lv_signal_func_t partition_btn_signal_ancestor; + +static void partition_hold_task_cb(void *param) +{ + (void)param; + if (partition_hold_task && partition_hold_btn) { + partition_hold_triggered = true; + create_window_partition_manager(partition_hold_btn, DRIVE_EMMC); + lv_task_del(partition_hold_task); + partition_hold_task = NULL; + partition_hold_btn = NULL; + } +} + +static lv_res_t partition_btn_signal(lv_obj_t *obj, lv_signal_t sign, void *param) +{ + if (sign == LV_SIGNAL_PRESSED) { + partition_hold_btn = obj; + partition_hold_task = lv_task_create(partition_hold_task_cb, PARTITION_HOLD_MS, LV_TASK_PRIO_MID, NULL); + lv_task_once(partition_hold_task); + } else if (sign == LV_SIGNAL_RELEASED && partition_hold_task) { + lv_task_del(partition_hold_task); + partition_hold_task = NULL; + partition_hold_btn = NULL; + } + return partition_btn_signal_ancestor ? partition_btn_signal_ancestor(obj, sign, param) : LV_RES_OK; +} + +static lv_res_t _partition_btn_click(lv_obj_t *btn) +{ + if (partition_hold_triggered) { + partition_hold_triggered = false; + return LV_RES_OK; + } + create_window_partition_manager(btn, DRIVE_SD); + return LV_RES_OK; +} + static void _create_tab_tools_emmc_pkg12(lv_theme_t *th, lv_obj_t *parent) { lv_page_set_scrl_layout(parent, LV_LAYOUT_PRETTY); @@ -1584,42 +1660,50 @@ static void _create_tab_tools_emmc_pkg12(lv_theme_t *th, lv_obj_t *parent) lv_label_set_static_text(label_sep, ""); lv_obj_t *label_txt3 = lv_label_create(h2, NULL); - lv_label_set_static_text(label_txt3, "SD Partitions & USB"); + lv_label_set_static_text(label_txt3, "Partitions & USB"); lv_obj_set_style(label_txt3, th->label.prim); lv_obj_align(label_txt3, label_sep, LV_ALIGN_OUT_BOTTOM_LEFT, LV_DPI / 4, -LV_DPI * 3 / 10); line_sep = lv_line_create(h2, line_sep); lv_obj_align(line_sep, label_txt3, LV_ALIGN_OUT_BOTTOM_LEFT, -(LV_DPI / 4), LV_DPI / 8); - // Create Partition SD Card button. - lv_obj_t *btn3 = lv_btn_create(h2, NULL); + // Create Partition SD Card button. Hold 3 seconds for eMMC. + lv_obj_t *btn_partition = lv_btn_create(h2, NULL); if (hekate_bg || hekate_bg_etc) { - lv_btn_set_style(btn3, LV_BTN_STYLE_REL, &btn_transp_rel); - lv_btn_set_style(btn3, LV_BTN_STYLE_PR, &btn_transp_pr); + lv_btn_set_style(btn_partition, LV_BTN_STYLE_REL, &btn_transp_rel); + lv_btn_set_style(btn_partition, LV_BTN_STYLE_PR, &btn_transp_pr); } - label_btn = lv_label_create(btn3, NULL); - lv_btn_set_fit(btn3, true, true); - lv_label_set_static_text(label_btn, SYMBOL_SD" Partition SD Card"); - lv_obj_align(btn3, line_sep, LV_ALIGN_OUT_BOTTOM_LEFT, LV_DPI / 4, LV_DPI / 4); - lv_btn_set_action(btn3, LV_BTN_ACTION_CLICK, create_window_sd_partition_manager); - lv_btn_set_action(btn3, LV_BTN_ACTION_LONG_PR, create_window_emmc_partition_manager); + lv_btn_set_fit(btn_partition, true, true); + lv_obj_t *label_partition = lv_label_create(btn_partition, NULL); + lv_label_set_static_text(label_partition, SYMBOL_SD " Partition SD Card"); + lv_obj_align(btn_partition, line_sep, LV_ALIGN_OUT_BOTTOM_LEFT, LV_DPI / 4, LV_DPI / 4 - th->bg->body.padding.ver); + lv_btn_set_action(btn_partition, LV_BTN_ACTION_CLICK, _partition_btn_click); + partition_btn_signal_ancestor = lv_obj_get_signal_func(btn_partition); + lv_obj_set_signal_func(btn_partition, partition_btn_signal); lv_obj_t *label_txt4 = lv_label_create(h2, NULL); lv_label_set_recolor(label_txt4, true); lv_label_set_static_text(label_txt4, - "Allows you to partition the SD Card for using it with #C7EA46 emuMMC#,\n" - "#C7EA46 Android# and #C7EA46 Linux#. You can also flash Linux and Android.\n"); + "Allows you to partition the SD Card or the eMMC \n" + "for using it with #C7EA46 emuMMC#, #C7EA46 Android# and #C7EA46 Linux#." + "\nYou can also flash Linux and Android. #C7EA46 Hold 3s for eMMC.#"); lv_obj_set_style(label_txt4, &hint_small_style); - lv_obj_align(label_txt4, btn3, LV_ALIGN_OUT_BOTTOM_LEFT, 0, LV_DPI / 3); + lv_obj_align(label_txt4, btn_partition, LV_ALIGN_OUT_BOTTOM_LEFT, 0, LV_DPI / 3 - th->bg->body.padding.ver); label_sep = lv_label_create(h2, NULL); lv_label_set_static_text(label_sep, ""); lv_obj_align(label_sep, label_txt4, LV_ALIGN_OUT_BOTTOM_LEFT, 0, LV_DPI * 11 / 7); // Create USB Tools button. - lv_obj_t *btn4 = lv_btn_create(h2, btn3); + lv_obj_t *btn4 = lv_btn_create(h2, NULL); label_btn = lv_label_create(btn4, NULL); + if (hekate_bg || hekate_bg_etc) + { + lv_btn_set_style(btn4, LV_BTN_STYLE_REL, &btn_transp_rel); + lv_btn_set_style(btn4, LV_BTN_STYLE_PR, &btn_transp_pr); + } + lv_btn_set_fit(btn4, true, true); lv_label_set_static_text(label_btn, SYMBOL_USB" USB Tools"); lv_obj_align(btn4, label_txt4, LV_ALIGN_OUT_BOTTOM_LEFT, 0, LV_DPI / 2); lv_btn_set_action(btn4, LV_BTN_ACTION_CLICK, _create_window_usb_tools); diff --git a/nyx/nyx_gui/frontend/gui_tools.h b/nyx/nyx_gui/frontend/gui_tools.h index ae4bbf1f..af3729e8 100644 --- a/nyx/nyx_gui/frontend/gui_tools.h +++ b/nyx/nyx_gui/frontend/gui_tools.h @@ -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 diff --git a/nyx/nyx_gui/frontend/gui_tools_partition_manager.c b/nyx/nyx_gui/frontend/gui_tools_partition_manager.c index 7c475654..5a2a0822 100644 --- a/nyx/nyx_gui/frontend/gui_tools_partition_manager.c +++ b/nyx/nyx_gui/frontend/gui_tools_partition_manager.c @@ -14,63 +14,89 @@ * along with this program. If not, see . */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include #include #include "gui.h" #include "gui_tools.h" -#include "fe_emummc_tools.h" #include "gui_tools_partition_manager.h" -#include "../hos/hos.h" #include #include - -#define SECTORS_PER_GB 0x200000 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "../hos/hos.h" +#include "../storage/sfd.h" #define AU_ALIGN_SECTORS 0x8000 // 16MB. #define AU_ALIGN_BYTES (AU_ALIGN_SECTORS * SD_BLOCKSIZE) -#define HOS_USER_SECTOR 0x53C000 -#define HOS_FAT_MIN_SIZE_MB 2048 -#define HOS_USER_MIN_SIZE_MB 1024 +#define SECTORS_PER_GB 0x200000 -#define EMU_SLIDER_MIN 0 -#define EMU_SLIDER_MAX 44 // 24 GB. Always an even number. -#define EMU_SLIDER_1X_MAX (EMU_SLIDER_MAX / 2) -#define EMU_SLIDER_1X_FULL EMU_SLIDER_1X_MAX -#define EMU_SLIDER_2X_MIN (EMU_SLIDER_1X_MAX + 1) -#define EMU_SLIDER_2X_FULL EMU_SLIDER_MAX -#define EMU_SLIDER_OFFSET 3 // Min 4GB. -#define EMU_RSVD_MB (4 + 4 + 16 + 8) // BOOT0 + BOOT1 + 16MB offset + 8MB alignment. +#define HOS_MIN_SIZE_MB 2048 +#define ANDROID_SYSTEM_SIZE_MB 6144 // 6 GB. Fits both Legacy (4912MB) and Dynamic (6144MB) partition schemes. +#define ANDROID_SYSTEM_SIZE_LEGACY_MB 4912 -#define EMU_32GB_FULL 29856 // Actual: 29820 MB. -#define EMU_64GB_FULL 59680 // Actual: 59640 MB. - -#define AND_SYS_SIZE_MB 6144 // 6 GB. Fits both Legacy (4912MB) and Dynamic (6144MB) partition schemes. +#define ENABLE_DUAL_ANDROID 1 extern volatile boot_cfg_t *b_cfg; extern volatile nyx_storage_t *nyx_str; +// #define DBG_PRINT(msg) gfx_printf(msg); gfx_putc('\n'); +#define DBG_PRINT(msg) +// #define DBG_PRINT_ARGS(msg, ...) gfx_printf(msg, __VA_ARGS__); gfx_putc('\n'); +#define DBG_PRINT_ARGS(msg, ...) + + typedef struct _partition_ctxt_t { - bool emmc; - sdmmc_storage_t *storage; - u32 total_sct; - u32 alignment; - u32 emmc_size_mb; - int backup_possible; + // total sectors available for partitions (e.g. total sectors - gpt - backup gpt, and aligned to 16mb) + u32 total_sct_available; - s32 hos_min_size; + u32 alignment; + int backup_possible; + bool skip_backup; + u8 drive; + + u32 hos_os_og_size; s32 hos_size; u32 emu_size; u32 l4t_size; u32 and_size; + u32 hos_os_size; + u32 emu_sd_size; + + u32 hos_os_align; + + u32 hos_sys_size_mb; + s32 hos_min_size_mb; bool emu_double; + bool and_double; + bool emu_sd_double; bool emmc_is_64gb; + bool auto_assign_free_storage; bool and_dynamic; @@ -80,21 +106,30 @@ typedef struct _partition_ctxt_t lv_obj_t *bar_emu; lv_obj_t *bar_l4t; lv_obj_t *bar_and; + lv_obj_t *bar_hos_os; + lv_obj_t *bar_remaining; + lv_obj_t *bar_emu_sd; lv_obj_t *sep_emu; lv_obj_t *sep_l4t; lv_obj_t *sep_and; + lv_obj_t *sep_hos; + lv_obj_t *sep_hos_os; + lv_obj_t *sep_emu_sd; lv_obj_t *slider_bar_hos; - - lv_obj_t *cont_lbl; + lv_obj_t *slider_emu; + lv_obj_t *slider_l4t; + lv_obj_t *slider_and; + lv_obj_t *slider_hos_os; + lv_obj_t *slider_emu_sd; lv_obj_t *lbl_hos; lv_obj_t *lbl_emu; lv_obj_t *lbl_l4t; lv_obj_t *lbl_and; - - lv_obj_t *partition_button; + lv_obj_t *lbl_hos_os; + lv_obj_t *lbl_emu_sd; } partition_ctxt_t; typedef struct _l4t_flasher_ctxt_t @@ -103,17 +138,47 @@ typedef struct _l4t_flasher_ctxt_t u32 image_size_sct; } l4t_flasher_ctxt_t; +typedef struct _android_flasher_ctxt_t{ + u32 slot; +} android_flasher_ctxt_t; + partition_ctxt_t part_info; l4t_flasher_ctxt_t l4t_flash_ctxt; +android_flasher_ctxt_t android_flash_ctxt; lv_obj_t *btn_flash_l4t; lv_obj_t *btn_flash_android; -static FRESULT _copy_file(const char *src, const char *dst, const char *path) +static void _wctombs(const u16 *src, char *dest, u32 len_max){ + const u16 *cur = src; + do{ + *dest++ = *cur & 0xff; + len_max--; + }while(*cur++ && len_max); +} + +static void _ctowcs(const char *src, u16 *dest, u32 len_max){ + const char *cur = src; + do{ + *dest++ = *cur; + len_max--; + }while(*cur++ && len_max); +} + +static bool _has_gpt(const mbr_t *mbr){ + for(u32 i = 0; i < 4; i++){ + if(mbr->partitions[i].type == 0xee){ + return true; + } + } + return false; +} + +int _copy_file(const char *src, const char *dst, const char *path) { FIL fp_src; FIL fp_dst; - FRESULT res; + int res; // Open file for reading. f_chdrive(src); @@ -151,6 +216,8 @@ static FRESULT _copy_file(const char *src, const char *dst, const char *path) static int _stat_and_copy_files(const char *src, const char *dst, char *path, u32 *total_files, u32 *total_size, lv_obj_t **labels) { FRESULT res; + FIL fp_src; + FIL fp_dst; DIR dir; u32 dirLength = 0; static FILINFO fno; @@ -159,8 +226,12 @@ static int _stat_and_copy_files(const char *src, const char *dst, char *path, u3 // Open directory. res = f_opendir(&dir, path); - if (res != FR_OK) + if (res != FR_OK){ + if(res == FR_NO_PATH){ + return FR_OK; + } return res; + } if (labels) lv_label_set_text(labels[0], path); @@ -213,8 +284,6 @@ static int _stat_and_copy_files(const char *src, const char *dst, char *path, u3 // Create a copy to destination. if (dst) { - FIL fp_src; - FIL fp_dst; u32 file_bytes_left = fno.fsize; // Open file for writing. @@ -238,6 +307,7 @@ static int _stat_and_copy_files(const char *src, const char *dst, char *path, u3 // Write file to disk. f_write(&fp_dst, (void *)SDXC_BUF_ALIGNED, chunk_size, NULL); + } // Finalize copied file. @@ -249,8 +319,8 @@ static int _stat_and_copy_files(const char *src, const char *dst, char *path, u3 f_close(&fp_src); } - // If total is > 1.2GB exit. - if (*total_size > (RAM_DISK_SZ - SZ_16M)) // Account for alignment. + // If total is > 1GB exit. + if (*total_size > (RAM_DISK_SZ - SZ_16M)) // 0x2400000. { // Skip next folders and return. res = -1; @@ -290,417 +360,357 @@ out: return res; } -static void _create_gpt_partition(gpt_t *gpt, u8 *gpt_idx, u32 *curr_part_lba, u32 size_lba, const char *name, int name_size) -{ - static const u8 linux_part_guid[] = { 0xAF, 0x3D, 0xC6, 0x0F, 0x83, 0x84, 0x72, 0x47, 0x8E, 0x79, 0x3D, 0x69, 0xD8, 0x47, 0x7D, 0xE4 }; +static void _create_gpt_partition(gpt_t *gpt, u32 *gpt_idx, u32 *curr_part_lba, u32 size_lba, bool align, const char *name, const u8 type_guid[16], const u8 guid[16], bool clear){ + memcpy(gpt->entries[*gpt_idx].type_guid, type_guid, 16); - // Reset partition. - memset(&gpt->entries[*gpt_idx], 0, sizeof(gpt_entry_t)); + if(!guid){ + u8 random_number[16]; + se_gen_prng128(random_number); + memcpy(gpt->entries[*gpt_idx].part_guid, random_number, 16); + }else{ + memcpy(gpt->entries[*gpt_idx].part_guid, guid, 16); + } - // Create GPT partition. - memcpy(gpt->entries[*gpt_idx].type_guid, linux_part_guid, 16); + if(align){ + (*curr_part_lba) = ALIGN(*curr_part_lba, AU_ALIGN_SECTORS); + } - // Set randomly created GUID. - u8 random_number[SE_RNG_BLOCK_SIZE]; - se_rng_pseudo(random_number, SE_RNG_BLOCK_SIZE); - memcpy(gpt->entries[*gpt_idx].part_guid, random_number, SE_RNG_BLOCK_SIZE); - - // Set partition start and end. gpt->entries[*gpt_idx].lba_start = *curr_part_lba; gpt->entries[*gpt_idx].lba_end = *curr_part_lba + size_lba - 1; - // Set name. - u16 name_utf16[36] = {0}; - u32 name_lenth = strlen(name); - for (u32 i = 0; i < name_lenth; i++) - name_utf16[i] = name[i]; - memcpy(gpt->entries[*gpt_idx].name, name_utf16, name_lenth * sizeof(u16)); + _ctowcs(name, gpt->entries[*gpt_idx].name, 36); - // Wipe the first 1MB to sanitize it as raw-empty partition. - sdmmc_storage_write(part_info.storage, *curr_part_lba, 0x800, (void *)SDMMC_UPPER_BUFFER); + if(clear){ + sdmmc_storage_t *storage = part_info.drive == DRIVE_SD ? &sd_storage : &emmc_storage; + sdmmc_storage_write(storage, *curr_part_lba, 0x800, (void *)SDMMC_UPPER_BUFFER); + } - // Prepare for next. (*curr_part_lba) += size_lba; + (*gpt_idx)++; } -static void _sd_prepare_and_flash_mbr_gpt() -{ - mbr_t mbr; - u8 random_number[SE_RNG_BLOCK_SIZE]; - - // Read current MBR. - sdmmc_storage_read(&sd_storage, 0, 1, &mbr); - - // Copy over metadata if they exist. - if (*(u32 *)&part_info.mbr_old.bootstrap[0x80]) - memcpy(&mbr.bootstrap[0x80], &part_info.mbr_old.bootstrap[0x80], 64); - if (*(u32 *)&part_info.mbr_old.bootstrap[0xE0]) - memcpy(&mbr.bootstrap[0xE0], &part_info.mbr_old.bootstrap[0xE0], 208); - - // Clear the first 16MB. - memset((void *)SDMMC_UPPER_BUFFER, 0, AU_ALIGN_BYTES); - sdmmc_storage_write(&sd_storage, 0, AU_ALIGN_SECTORS, (void *)SDMMC_UPPER_BUFFER); - - // Set disk signature. - se_rng_pseudo(random_number, sizeof(u32)); - memcpy(&mbr.signature, random_number, sizeof(u32)); - - // FAT partition as first. - u8 mbr_idx = 1; - - // Apply L4T Linux second to MBR if no Android. - if (part_info.l4t_size && !part_info.and_size) - { - mbr.partitions[mbr_idx].type = 0x83; // Linux system partition. - mbr.partitions[mbr_idx].start_sct = AU_ALIGN_SECTORS + ((u32)part_info.hos_size << 11); - mbr.partitions[mbr_idx].size_sct = part_info.l4t_size << 11; - sdmmc_storage_write(&sd_storage, mbr.partitions[mbr_idx].start_sct, 0x800, (void *)SDMMC_UPPER_BUFFER); // Clear the first 1MB. - mbr_idx++; +static void _make_part_name(char *buf, const char* base_name, u32 idx){ + if(idx > 1){ + s_printf(buf, "%s%d", base_name, idx); + }else{ + strcpy(buf, base_name); } - - // emuMMC goes second or third. Next to L4T if no Android. - if (part_info.emu_size) - { - mbr.partitions[mbr_idx].type = 0xE0; // emuMMC partition. - mbr.partitions[mbr_idx].start_sct = AU_ALIGN_SECTORS + ((u32)part_info.hos_size << 11) + (part_info.l4t_size << 11) + (part_info.and_size << 11); - - if (!part_info.emu_double) - mbr.partitions[mbr_idx].size_sct = (part_info.emu_size << 11) - 0x800; // Reserve 1MB. - else - { - mbr.partitions[mbr_idx].size_sct = part_info.emu_size << 10; - mbr_idx++; - - // 2nd emuMMC. - mbr.partitions[mbr_idx].type = 0xE0; // emuMMC partition. - mbr.partitions[mbr_idx].start_sct = mbr.partitions[mbr_idx - 1].start_sct + (part_info.emu_size << 10); - mbr.partitions[mbr_idx].size_sct = (part_info.emu_size << 10) - 0x800; // Reserve 1MB. - } - mbr_idx++; - } - - if (part_info.and_size) - { - gpt_t *gpt = zalloc(sizeof(gpt_t)); - gpt_header_t gpt_hdr_backup = { 0 }; - - // Set GPT protective partition in MBR. - mbr.partitions[mbr_idx].type = 0xEE; - mbr.partitions[mbr_idx].start_sct = 1; - mbr.partitions[mbr_idx].size_sct = sd_storage.sec_cnt - 1; - mbr_idx++; - - // Set GPT header. - memcpy(&gpt->header.signature, "EFI PART", 8); - gpt->header.revision = 0x10000; - gpt->header.size = 92; - gpt->header.my_lba = 1; - gpt->header.alt_lba = sd_storage.sec_cnt - 1; - gpt->header.first_use_lba = (sizeof(mbr_t) + sizeof(gpt_t)) >> 9; - gpt->header.last_use_lba = sd_storage.sec_cnt - 0x800 - 1; // sd_storage.sec_cnt - 33 is start of backup gpt partition entries. - se_rng_pseudo(random_number, SE_RNG_BLOCK_SIZE); - memcpy(gpt->header.disk_guid, random_number, 10); - memcpy(gpt->header.disk_guid + 10, "NYXGPT", 6); - gpt->header.part_ent_lba = 2; - gpt->header.part_ent_size = 128; - - // Set FAT GPT partition manually. - const u8 basic_part_guid[] = { 0xA2, 0xA0, 0xD0, 0xEB, 0xE5, 0xB9, 0x33, 0x44, 0x87, 0xC0, 0x68, 0xB6, 0xB7, 0x26, 0x99, 0xC7 }; - memcpy(gpt->entries[0].type_guid, basic_part_guid, 16); - se_rng_pseudo(random_number, SE_RNG_BLOCK_SIZE); - memcpy(gpt->entries[0].part_guid, random_number, SE_RNG_BLOCK_SIZE); - - // Clear non-standard Windows MBR attributes. bit4: Read only, bit5: Shadow copy, bit6: Hidden, bit7: No drive letter. - gpt->entries[0].part_guid[7] = 0; - - gpt->entries[0].lba_start = mbr.partitions[0].start_sct; - gpt->entries[0].lba_end = mbr.partitions[0].start_sct + mbr.partitions[0].size_sct - 1; - memcpy(gpt->entries[0].name, (u16[]) { 'h', 'o', 's', '_', 'd', 'a', 't', 'a' }, 16); - - // Set the rest of GPT partitions. - u8 gpt_idx = 1; - u32 curr_part_lba = AU_ALIGN_SECTORS + ((u32)part_info.hos_size << 11); - - // L4T partition. - if (part_info.l4t_size) - _create_gpt_partition(gpt, &gpt_idx, &curr_part_lba, part_info.l4t_size << 11, "l4t", 6); - - if (part_info.and_dynamic) - { - // Android Linux Kernel partition. 64MB. - _create_gpt_partition(gpt, &gpt_idx, &curr_part_lba, 0x20000, "boot", 8); - - // Android Recovery partition. 64MB. - _create_gpt_partition(gpt, &gpt_idx, &curr_part_lba, 0x20000, "recovery", 16); - - // Android Device Tree Reference partition. 1MB. - _create_gpt_partition(gpt, &gpt_idx, &curr_part_lba, 0x800, "dtb", 6); - - // Android Misc partition. 3MB. - _create_gpt_partition(gpt, &gpt_idx, &curr_part_lba, 0x1800, "misc", 8); - - // Android Cache partition. 60MB. - _create_gpt_partition(gpt, &gpt_idx, &curr_part_lba, 0x1E000, "cache", 10); - - // Android Super dynamic partition. 5952MB. - _create_gpt_partition(gpt, &gpt_idx, &curr_part_lba, 0xBA0000, "super", 10); - - // Android Userdata partition. - u32 uda_size = (part_info.and_size << 11) - 0xC00000; // Subtract the other partitions (6144MB). - if (!part_info.emu_size) - uda_size -= 0x800; // Reserve 1MB. - _create_gpt_partition(gpt, &gpt_idx, &curr_part_lba, uda_size, "userdata", 16); - } - else - { - // Android Vendor partition. 1GB - _create_gpt_partition(gpt, &gpt_idx, &curr_part_lba, 0x200000, "vendor", 12); - - // Android System partition. 3GB. - _create_gpt_partition(gpt, &gpt_idx, &curr_part_lba, 0x600000, "APP", 6); - - // Android Linux Kernel partition. 32MB. - _create_gpt_partition(gpt, &gpt_idx, &curr_part_lba, 0x10000, "LNX", 6); - - // Android Recovery partition. 64MB. - _create_gpt_partition(gpt, &gpt_idx, &curr_part_lba, 0x20000, "SOS", 6); - - // Android Device Tree Reference partition. 1MB. - _create_gpt_partition(gpt, &gpt_idx, &curr_part_lba, 0x800, "DTB", 6); - - // Android Encryption partition. 16MB. - // Note: 16MB size is for aligning UDA. If any other tiny partition must be added, it should split the MDA one. - sdmmc_storage_write(&sd_storage, curr_part_lba, 0x8000, (void *)SDMMC_UPPER_BUFFER); // Clear the whole of it. - _create_gpt_partition(gpt, &gpt_idx, &curr_part_lba, 0x8000, "MDA", 6); - - // Android Cache partition. 700MB. - _create_gpt_partition(gpt, &gpt_idx, &curr_part_lba, 0x15E000, "CAC", 6); - - // Android Misc partition. 3MB. - _create_gpt_partition(gpt, &gpt_idx, &curr_part_lba, 0x1800, "MSC", 6); - - // Android Userdata partition. - u32 uda_size = (part_info.and_size << 11) - 0x998000; // Subtract the other partitions (4912MB). - if (!part_info.emu_size) - uda_size -= 0x800; // Reserve 1MB. - _create_gpt_partition(gpt, &gpt_idx, &curr_part_lba, uda_size, "UDA", 6); - } - - // Handle emuMMC partitions manually. - if (part_info.emu_size) - { - // Set 1st emuMMC. - u8 emu_part_guid[] = { 0x00, 0x7E, 0xCA, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 'e', 'm', 'u', 'M', 'M', 'C' }; - memcpy(gpt->entries[gpt_idx].type_guid, emu_part_guid, 16); - se_rng_pseudo(random_number, SE_RNG_BLOCK_SIZE); - memcpy(gpt->entries[gpt_idx].part_guid, random_number, SE_RNG_BLOCK_SIZE); - gpt->entries[gpt_idx].lba_start = curr_part_lba; - if (!part_info.emu_double) - gpt->entries[gpt_idx].lba_end = curr_part_lba + (part_info.emu_size << 11) - 0x800 - 1; // Reserve 1MB. - else - gpt->entries[gpt_idx].lba_end = curr_part_lba + (part_info.emu_size << 10) - 1; - memcpy(gpt->entries[gpt_idx].name, (u16[]) { 'e', 'm', 'u', 'm', 'm', 'c' }, 12); - gpt_idx++; - - // Set 2nd emuMMC. - if (part_info.emu_double) - { - curr_part_lba += (part_info.emu_size << 10); - memcpy(gpt->entries[gpt_idx].type_guid, emu_part_guid, 16); - se_rng_pseudo(random_number, SE_RNG_BLOCK_SIZE); - memcpy(gpt->entries[gpt_idx].part_guid, random_number, SE_RNG_BLOCK_SIZE); - gpt->entries[gpt_idx].lba_start = curr_part_lba; - gpt->entries[gpt_idx].lba_end = curr_part_lba + (part_info.emu_size << 10) - 0x800 - 1; // Reserve 1MB. - memcpy(gpt->entries[gpt_idx].name, (u16[]) { 'e', 'm', 'u', 'm', 'm', 'c', '2' }, 14); - gpt_idx++; - } - } - - // Set final GPT header parameters. - gpt->header.num_part_ents = gpt_idx; - gpt->header.part_ents_crc32 = crc32_calc(0, (const u8 *)gpt->entries, sizeof(gpt_entry_t) * gpt->header.num_part_ents); - gpt->header.crc32 = 0; // Set to 0 for calculation. - gpt->header.crc32 = crc32_calc(0, (const u8 *)&gpt->header, gpt->header.size); - - // Set final backup GPT header parameters. - memcpy(&gpt_hdr_backup, &gpt->header, sizeof(gpt_header_t)); - gpt_hdr_backup.my_lba = sd_storage.sec_cnt - 1; - gpt_hdr_backup.alt_lba = 1; - gpt_hdr_backup.part_ent_lba = sd_storage.sec_cnt - 33; - gpt_hdr_backup.crc32 = 0; // Set to 0 for calculation. - gpt_hdr_backup.crc32 = crc32_calc(0, (const u8 *)&gpt_hdr_backup, gpt_hdr_backup.size); - - // Write main GPT. - sdmmc_storage_write(&sd_storage, gpt->header.my_lba, sizeof(gpt_t) >> 9, gpt); - - // Write backup GPT partition table. - sdmmc_storage_write(&sd_storage, gpt_hdr_backup.part_ent_lba, ((sizeof(gpt_entry_t) * 128) >> 9), gpt->entries); - - // Write backup GPT header. - sdmmc_storage_write(&sd_storage, gpt_hdr_backup.my_lba, 1, &gpt_hdr_backup); - - free(gpt); - } - - // Write MBR. - sdmmc_storage_write(&sd_storage, 0, 1, &mbr); } -static int _emmc_prepare_and_flash_mbr_gpt() +static s32 _get_gpt_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; +} + +static void _prepare_and_flash_mbr_gpt() { - gpt_t *gpt = zalloc(sizeof(gpt_t)); - gpt_header_t gpt_hdr_backup = { 0 }; + sdmmc_storage_t *storage = part_info.drive == DRIVE_SD ? &sd_storage : &emmc_storage; - // Read main GPT. - sdmmc_storage_read(&emmc_storage, 1, sizeof(gpt_t) >> 9, gpt); + mbr_t mbr; + u8 random_number[16]; - // Set GPT header. - gpt->header.alt_lba = emmc_storage.sec_cnt - 1; - gpt->header.last_use_lba = emmc_storage.sec_cnt - 0x800 - 1; // emmc_storage.sec_cnt - 33 is start of backup gpt partition entries. + memset((void *)SDMMC_UPPER_BUFFER, 0, AU_ALIGN_BYTES); - // Calculate HOS USER partition - u32 part_rsvd_size = (part_info.l4t_size << 11) + (part_info.and_size << 11); - part_rsvd_size += part_rsvd_size ? part_info.alignment : 0x800; // Only reserve 1MB if no extra partitions. - u32 hos_user_size = emmc_storage.sec_cnt - HOS_USER_SECTOR - part_rsvd_size; + s32 l4t_idx = -1; + s32 emu_idx[2] = {-1, -1}; + s32 hos_idx = -1; - // Get HOS USER partition index. - LIST_INIT(gpt_emmc); - emmc_gpt_parse(&gpt_emmc); - emmc_part_t *user_part = emmc_part_find(&gpt_emmc, "USER"); - if (!user_part) - { - emmc_gpt_free(&gpt_emmc); - free(gpt); + // Create new GPT + gpt_t *gpt = zalloc(sizeof(*gpt)); + memcpy(&gpt->header.signature, "EFI PART", 8); + gpt->header.revision = 0x10000; + gpt->header.size = 92; + gpt->header.my_lba = 1; + gpt->header.alt_lba = storage->sec_cnt - 1; + gpt->header.first_use_lba = (sizeof(mbr_t) + sizeof(gpt_t)) >> 9; + gpt->header.last_use_lba = storage->sec_cnt - 0x800 - 1; + gpt->header.part_ent_lba = 2; + gpt->header.part_ent_size = 128; + se_gen_prng128(random_number); + memcpy(gpt->header.disk_guid, random_number, 10); + memcpy(gpt->header.disk_guid + 10, "NYXGPT", 6); - return 1; - } - u8 gpt_idx = user_part->index; - emmc_gpt_free(&gpt_emmc); + u32 gpt_idx = 0; + u32 gpt_next_lba = AU_ALIGN_SECTORS; + if(part_info.hos_os_size){ + gpt_t *old_gpt = zalloc(sizeof(*old_gpt)); + sdmmc_storage_read(storage, 1, sizeof(*old_gpt) / 0x200, old_gpt); - // HOS USER partition. - u32 curr_part_lba = gpt->entries[gpt_idx].lba_start; - gpt->entries[gpt_idx].lba_end = curr_part_lba + hos_user_size - 1; + // Used by HOS for backup of first 3 partition entries + memcpy(gpt->header.res2, old_gpt->header.res2, sizeof(gpt->header.res2)); - curr_part_lba += hos_user_size; - gpt_idx++; + // user original disk guid + memcpy(gpt->header.disk_guid, old_gpt->header.disk_guid, sizeof(gpt->header.disk_guid)); - // L4T partition. - if (part_info.l4t_size) - { - u32 l4t_size = part_info.l4t_size << 11; - if (!part_info.and_size) - l4t_size -= 0x800; // Reserve 1MB. - _create_gpt_partition(gpt, &gpt_idx, &curr_part_lba, l4t_size, "l4t", 6); + // Copy HOS OS partition entries + for(u32 i = 0; i < 11; i++){ + gpt->entries[i] = old_gpt->entries[i]; + } + + // Update HOS USER size + gpt->entries[10].lba_end = gpt->entries[10].lba_start + ((part_info.hos_os_size - part_info.hos_sys_size_mb - part_info.hos_os_align) << 11) - 1; + gpt_next_lba = ALIGN(gpt->entries[10].lba_end + 1, AU_ALIGN_SECTORS); + + gpt_idx = 11; + + free(old_gpt); } - if (part_info.and_size && part_info.and_dynamic) - { - // Android Linux Kernel partition. 64MB. - _create_gpt_partition(gpt, &gpt_idx, &curr_part_lba, 0x20000, "boot", 8); + static const u8 basic_part_guid[] = { 0xA2, 0xA0, 0xD0, 0xEB, 0xE5, 0xB9, 0x33, 0x44, 0x87, 0xC0, 0x68, 0xB6, 0xB7, 0x26, 0x99, 0xC7 }; + static const u8 linux_part_guid[] = { 0xAF, 0x3D, 0xC6, 0x0F, 0x83, 0x84, 0x72, 0x47, 0x8E, 0x79, 0x3D, 0x69, 0xD8, 0x47, 0x7D, 0xE4 }; + static const u8 emu_part_guid[] = { 0x00, 0x7E, 0xCA, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 'e', 'm', 'u', 'M', 'M', 'C' }; - // Android Recovery partition. 64MB. - _create_gpt_partition(gpt, &gpt_idx, &curr_part_lba, 0x20000, "recovery", 16); - - // Android Device Tree Reference partition. 1MB. - _create_gpt_partition(gpt, &gpt_idx, &curr_part_lba, 0x800, "dtb", 6); - - // Android Misc partition. 3MB. - _create_gpt_partition(gpt, &gpt_idx, &curr_part_lba, 0x1800, "misc", 8); - - // Android Cache partition. 60MB. - _create_gpt_partition(gpt, &gpt_idx, &curr_part_lba, 0x1E000, "cache", 10); - - // Android Super dynamic partition. 5952MB. - _create_gpt_partition(gpt, &gpt_idx, &curr_part_lba, 0xBA0000, "super", 10); - - // Android Userdata partition. - u32 uda_size = (part_info.and_size << 11) - 0xC00000; // Subtract the other partitions (6144MB). - uda_size -= 0x800; // Reserve 1MB. - _create_gpt_partition(gpt, &gpt_idx, &curr_part_lba, uda_size, "userdata", 16); - } - else if (part_info.and_size) - { - // Android Vendor partition. 1GB - _create_gpt_partition(gpt, &gpt_idx, &curr_part_lba, 0x200000, "vendor", 12); - - // Android System partition. 3GB. - _create_gpt_partition(gpt, &gpt_idx, &curr_part_lba, 0x600000, "APP", 6); - - // Android Linux Kernel partition. 32MB. - _create_gpt_partition(gpt, &gpt_idx, &curr_part_lba, 0x10000, "LNX", 6); - - // Android Recovery partition. 64MB. - _create_gpt_partition(gpt, &gpt_idx, &curr_part_lba, 0x20000, "SOS", 6); - - // Android Device Tree Reference partition. 1MB. - _create_gpt_partition(gpt, &gpt_idx, &curr_part_lba, 0x800, "DTB", 6); - - // Android Encryption partition. 16MB. - // Note: 16MB size is for aligning UDA. If any other tiny partition must be added, it should split the MDA one. - sdmmc_storage_write(&emmc_storage, curr_part_lba, 0x8000, (void *)SDMMC_UPPER_BUFFER); // Clear the whole of it. - _create_gpt_partition(gpt, &gpt_idx, &curr_part_lba, 0x8000, "MDA", 6); - - // Android Cache partition. 700MB. - _create_gpt_partition(gpt, &gpt_idx, &curr_part_lba, 0x15E000, "CAC", 6); - - // Android Misc partition. 3MB. - _create_gpt_partition(gpt, &gpt_idx, &curr_part_lba, 0x1800, "MSC", 6); - - // Android Userdata partition. - u32 uda_size = (part_info.and_size << 11) - 0x998000; // Subtract the other partitions (4912MB). - uda_size -= 0x800; // Reserve 1MB. - _create_gpt_partition(gpt, &gpt_idx, &curr_part_lba, uda_size, "UDA", 6); + if(part_info.l4t_size){ + l4t_idx = gpt_idx; + _create_gpt_partition(gpt, &gpt_idx, &gpt_next_lba, part_info.l4t_size << 11, true, "l4t", linux_part_guid, NULL, true); } - // Clear the rest of GPT partition table. - for (u32 i = gpt_idx; i < 128; i++) - memset(&gpt->entries[i], 0, sizeof(gpt_entry_t)); + if(part_info.and_size){ + u32 and_system_size; + if(part_info.and_dynamic){ + and_system_size = ANDROID_SYSTEM_SIZE_MB; + }else{ + and_system_size = ANDROID_SYSTEM_SIZE_LEGACY_MB; + } + + u32 user_size; + if(part_info.and_double){ + user_size = (part_info.and_size / 2) - and_system_size; + }else{ + user_size = part_info.and_size - and_system_size; + } + + for(u32 i = 1; i <= (part_info.and_double ? 2 : 1); i++){ + char part_name[36]; + if(part_info.and_dynamic){ + // Android Kernel, 64MB + _make_part_name(part_name, "boot", i); + _create_gpt_partition(gpt, &gpt_idx, &gpt_next_lba, 0x20000, false, part_name, linux_part_guid, NULL, true); + + // Android Recovery, 64MB + _make_part_name(part_name, "recovery", i); + _create_gpt_partition(gpt, &gpt_idx, &gpt_next_lba, 0x20000, false, part_name, linux_part_guid, NULL, true); + + // Android DTB, 1MB + _make_part_name(part_name, "dtb", i); + _create_gpt_partition(gpt, &gpt_idx, &gpt_next_lba, 0x800, false, part_name, linux_part_guid, NULL, true); + + // Android Misc, 3MB + _make_part_name(part_name, "misc", i); + _create_gpt_partition(gpt, &gpt_idx, &gpt_next_lba, 0x1800, false, part_name, linux_part_guid, NULL, true); + + // Android Cache, 60MB + _make_part_name(part_name, "cache", i); + _create_gpt_partition(gpt, &gpt_idx, &gpt_next_lba, 0x1E000, false, part_name, linux_part_guid, NULL, true); + + // Android Dynamic, 5922MB + _make_part_name(part_name, "super", i); + _create_gpt_partition(gpt, &gpt_idx, &gpt_next_lba, 0xB91000, true, part_name, linux_part_guid, NULL, true); + + // Android Userdata + _make_part_name(part_name, "userdata", i); + _create_gpt_partition(gpt, &gpt_idx, &gpt_next_lba, user_size << 11, true, part_name, linux_part_guid, NULL, true); + }else{ + // Android Vendor, 1GB + _make_part_name(part_name, "vendor", i); + _create_gpt_partition(gpt, &gpt_idx, &gpt_next_lba, 0x200000, false, part_name, linux_part_guid, NULL, true); + + // Android System, 3GB + _make_part_name(part_name, "APP", i); + _create_gpt_partition(gpt, &gpt_idx, &gpt_next_lba, 0x600000, false, part_name, linux_part_guid, NULL, true); + + // Android Kernel, 32MB + _make_part_name(part_name, "LNX", i); + _create_gpt_partition(gpt, &gpt_idx, &gpt_next_lba, 0x10000, false, part_name, linux_part_guid, NULL, true); + + // Android Recovery, 64MB + _make_part_name(part_name, "SOS", i); + _create_gpt_partition(gpt, &gpt_idx, &gpt_next_lba, 0x20000, false, part_name, linux_part_guid, NULL, true); + + // Android DTB, 1MB + _make_part_name(part_name, "DTB", i); + _create_gpt_partition(gpt, &gpt_idx, &gpt_next_lba, 0x800, false, part_name, linux_part_guid, NULL, true); + + // Android encrypted metadata partition, 16MB to ensure alignment of following partitions. + // If more, tiny partitions must be added, split off from MDA + _make_part_name(part_name, "MDA", i); + // clear out entire partition + // sdmmc_storage_write(storage, gpt_next_lba, 0x8000, (void*)SDMMC_UPPER_BUFFER); + _create_gpt_partition(gpt, &gpt_idx, &gpt_next_lba, 0x8000, false, part_name, linux_part_guid, NULL, true); + + // Android Cache, 700MB + _make_part_name(part_name, "CAC", i); + _create_gpt_partition(gpt, &gpt_idx, &gpt_next_lba, 0x15E000, false, part_name, linux_part_guid, NULL, true); + + // Android Misc, 3MB + _make_part_name(part_name, "MSC", i); + _create_gpt_partition(gpt, &gpt_idx, &gpt_next_lba, 0x1800, false, part_name, linux_part_guid, NULL, true); + + // Android Userdata + _make_part_name(part_name, "UDA", i); + _create_gpt_partition(gpt, &gpt_idx, &gpt_next_lba, user_size << 11, true, part_name, linux_part_guid, NULL, true); + } + } + } + + if(part_info.emu_size){ + u32 emu_size; + if(part_info.emu_double){ + emu_size = part_info.emu_size / 2; + }else{ + emu_size = part_info.emu_size; + } + + char part_name[36]; + for(u32 i = 1; i <= (part_info.emu_double ? 2 : 1); i++){ + emu_idx[i - 1] = gpt_idx; + _make_part_name(part_name, "emummc", i); + _create_gpt_partition(gpt, &gpt_idx, &gpt_next_lba, emu_size << 11, true, part_name, emu_part_guid, NULL, true); + } + } + + if(part_info.hos_size){ + hos_idx = gpt_idx; + _create_gpt_partition(gpt, &gpt_idx, &gpt_next_lba, part_info.hos_size << 11, true, "hos_data", basic_part_guid, NULL, true); + // Clear non-standard Windows MBR attributes. bit4: Read only, bit5: Shadow copy, bit6: Hidden, bit7: No drive letter. + gpt->entries[gpt_idx - 1].part_guid[7] = 0; + if (part_info.and_size || part_info.l4t_size) { + // Set legacy bootable attribute, necessary for uboot to consider this partition + gpt->entries[gpt_idx - 1].attrs = 4; + } + } - // Set final GPT header parameters. gpt->header.num_part_ents = gpt_idx; gpt->header.part_ents_crc32 = crc32_calc(0, (const u8 *)gpt->entries, sizeof(gpt_entry_t) * gpt->header.num_part_ents); gpt->header.crc32 = 0; // Set to 0 for calculation. gpt->header.crc32 = crc32_calc(0, (const u8 *)&gpt->header, gpt->header.size); - // Set final backup GPT header parameters. - memcpy(&gpt_hdr_backup, &gpt->header, sizeof(gpt_header_t)); - gpt_hdr_backup.my_lba = emmc_storage.sec_cnt - 1; - gpt_hdr_backup.alt_lba = 1; - gpt_hdr_backup.part_ent_lba = emmc_storage.sec_cnt - 33; - gpt_hdr_backup.crc32 = 0; // Set to 0 for calculation. - gpt_hdr_backup.crc32 = crc32_calc(0, (const u8 *)&gpt_hdr_backup, gpt_hdr_backup.size); + gpt_header_t gpt_backup_header = {0}; + memcpy(&gpt_backup_header, &gpt->header, sizeof(gpt_backup_header)); + gpt_backup_header.my_lba = storage->sec_cnt - 1; + gpt_backup_header.alt_lba = 1; + gpt_backup_header.part_ent_lba = storage->sec_cnt - 33; + gpt_backup_header.crc32 = 0; // Set to 0 for calculation. + gpt_backup_header.crc32 = crc32_calc(0, (const u8 *)&gpt_backup_header, gpt_backup_header.size); - // Write main GPT. - sdmmc_storage_write(&emmc_storage, gpt->header.my_lba, sizeof(gpt_t) >> 9, gpt); + bool need_gpt = gpt_idx > 4 || part_info.drive == DRIVE_EMMC; - // Write backup GPT partition table. - sdmmc_storage_write(&emmc_storage, gpt_hdr_backup.part_ent_lba, ((sizeof(gpt_entry_t) * 128) >> 9), gpt->entries); + // Create new MBR + if(part_info.drive == DRIVE_SD){ + // on sd, add hos_data, l4t and emummc partitions to mbr, if possible + memset(&mbr, 0, sizeof(mbr)); + se_gen_prng128(random_number); + memcpy(&mbr.signature, random_number, 4); - // Write backup GPT header. - sdmmc_storage_write(&emmc_storage, gpt_hdr_backup.my_lba, 1, &gpt_hdr_backup); + mbr.boot_signature = 0xaa55; - // Clear nand patrol. - u8 *buf = (u8 *)gpt; - memset(buf, 0, EMMC_BLOCKSIZE); - emmc_set_partition(EMMC_BOOT0); - sdmmc_storage_write(&emmc_storage, NAND_PATROL_SECTOR, 1, buf); - emmc_set_partition(EMMC_GPP); + u32 mbr_idx = 0; + + if(hos_idx != -1){ + mbr.partitions[mbr_idx].type = 0x0c; // fat32 + mbr.partitions[mbr_idx].start_sct = gpt->entries[hos_idx].lba_start; + mbr.partitions[mbr_idx].size_sct = gpt->entries[hos_idx].lba_end - gpt->entries[hos_idx].lba_start + 1; + mbr_idx++; + } + + if(!need_gpt && l4t_idx != -1){ + mbr.partitions[mbr_idx].type = 0x83; // linux partition + mbr.partitions[mbr_idx].start_sct = gpt->entries[l4t_idx].lba_start; + mbr.partitions[mbr_idx].size_sct = gpt->entries[l4t_idx].lba_end - gpt->entries[l4t_idx].lba_start + 1; + mbr_idx++; + } + + for(u32 i = 0; i < 2; i++){ + if(emu_idx[i] != -1){ + mbr.partitions[mbr_idx].type = 0xe0; // emummc partition + mbr.partitions[mbr_idx].start_sct = gpt->entries[emu_idx[i]].lba_start; + mbr.partitions[mbr_idx].size_sct = gpt->entries[emu_idx[i]].lba_end - gpt->entries[emu_idx[i]].lba_start + 1; + mbr_idx++; + } + } + + if(need_gpt){ + mbr.partitions[mbr_idx].type = 0xee; + mbr.partitions[mbr_idx].start_sct = 1; + mbr.partitions[mbr_idx].size_sct = 0xffffffff; + } + + }else{ + // For eMMC, only gpt protective partition spanning entire disk and fat32 partition + memset(&mbr, 0, sizeof(mbr)); + + if(hos_idx != -1){ + se_gen_prng128(random_number); + memcpy(&mbr.signature, random_number, 4); + } + + u32 mbr_idx = 0; + + if(hos_idx != -1){ + mbr.partitions[mbr_idx].start_sct = gpt->entries[hos_idx].lba_start; + mbr.partitions[mbr_idx].size_sct = gpt->entries[hos_idx].lba_end - gpt->entries[hos_idx].lba_start + 1; + mbr.partitions[mbr_idx].type = 0x0c; + mbr_idx++; + } + + mbr.partitions[mbr_idx].type = 0xee; + mbr.partitions[mbr_idx].start_sct = 0x1; + mbr.partitions[mbr_idx].start_sct_chs.sector = 0x02; + mbr.boot_signature = 0xaa55; + mbr.partitions[mbr_idx].size_sct = 0xffffffff; + mbr.partitions[mbr_idx].end_sct_chs.sector = 0xff; + mbr.partitions[mbr_idx].end_sct_chs.cylinder = 0xff; + mbr.partitions[mbr_idx].end_sct_chs.head = 0xff; + } + + if(!part_info.hos_os_size){ + // only clear first 16mb if not keeping hos + sdmmc_storage_write(storage, 0, 0x800, (void*)SDMMC_UPPER_BUFFER); + } + + // write mbr + sdmmc_storage_write(storage, 0, 1, &mbr); + + if(need_gpt){ + // write primary gpt + sdmmc_storage_write(storage, 1, sizeof(*gpt) / 0x200, gpt); + // write backup gpt entries + sdmmc_storage_write(storage, gpt_backup_header.part_ent_lba, (sizeof(gpt_entry_t) * 128) / 0x200, gpt->entries); + // write backup gpt header + sdmmc_storage_write(storage, gpt_backup_header.my_lba, sizeof(gpt_backup_header) / 0x200, &gpt_backup_header); + } free(gpt); - - return 0; } static lv_res_t _action_part_manager_ums_sd(lv_obj_t *btn) { - action_ums_sd(NULL); + action_ums_sd(btn); // Close and reopen partition manager. lv_action_t close_btn_action = lv_btn_get_action(close_btn, LV_BTN_ACTION_CLICK); close_btn_action(close_btn); lv_obj_del(ums_mbox); - create_window_sd_partition_manager(NULL); + create_window_partition_manager(NULL, DRIVE_SD); + + return LV_RES_INV; +} + +static lv_res_t _action_part_manager_ums_emmc(lv_obj_t *btn){ + action_ums_emmc_gpp(btn); + + // Close and reopen partition manager. + lv_action_t close_btn_action = lv_btn_get_action(close_btn, LV_BTN_ACTION_CLICK); + close_btn_action(close_btn); + lv_obj_del(ums_mbox); + create_window_partition_manager(NULL, DRIVE_EMMC); return LV_RES_INV; } @@ -718,7 +728,7 @@ static lv_res_t _action_delete_linux_installer_files(lv_obj_t * btns, const char { char path[128]; - sd_mount(); + boot_storage_mount(); strcpy(path, "switchroot/install/l4t."); @@ -744,7 +754,7 @@ static lv_res_t _action_delete_linux_installer_files(lv_obj_t * btns, const char idx++; } - sd_unmount(); + boot_storage_unmount(); } return LV_RES_INV; @@ -752,6 +762,13 @@ static lv_res_t _action_delete_linux_installer_files(lv_obj_t * btns, const char static lv_res_t _action_flash_linux_data(lv_obj_t * btns, const char * txt) { + boot_storage_mount(); + if(part_info.drive == DRIVE_SD){ + sd_mount(); + }else{ + emmc_mount(); + } + int btn_idx = lv_btnm_get_pressed(btns); // Delete parent mbox. @@ -798,10 +815,6 @@ static lv_res_t _action_flash_linux_data(lv_obj_t * btns, const char * txt) lv_obj_align(mbox, NULL, LV_ALIGN_CENTER, 0, 0); lv_obj_set_top(mbox, true); - sd_mount(); - if (part_info.emmc) - emmc_initialize(false); - int res = 0; char *path = malloc(1024); char *txt_buf = malloc(SZ_4K); @@ -813,6 +826,7 @@ static lv_res_t _action_flash_linux_data(lv_obj_t * btns, const char * txt) res = f_open(&fp, path, FA_READ); if (res) { + gfx_printf("fopen res: %d\n", res); lv_label_set_text(lbl_status, "#FFDD00 Error:# Failed to open 1st part!"); goto exit; @@ -832,6 +846,8 @@ static lv_res_t _action_flash_linux_data(lv_obj_t * btns, const char * txt) u8 *buf = (u8 *)MIXD_BUF_ALIGNED; DWORD *clmt = f_expand_cltbl(&fp, SZ_4M, 0); + sdmmc_storage_t *storage = part_info.drive == DRIVE_SD ? &sd_storage : &emmc_storage; + // Start flashing L4T. while (total_size_sct > 0) { @@ -876,7 +892,9 @@ static lv_res_t _action_flash_linux_data(lv_obj_t * btns, const char * txt) if (res) { - lv_label_set_text(lbl_status, "#FFDD00 Error:# Reading from SD!"); + char msg[0x30]; + s_printf(msg, "#FFDD00 Error:# Reading from %s!", part_info.drive == DRIVE_SD ? "SD" : "eMMC"); + lv_label_set_text(lbl_status, msg); manual_system_maintenance(true); f_close(&fp); @@ -885,7 +903,7 @@ static lv_res_t _action_flash_linux_data(lv_obj_t * btns, const char * txt) } // Write data block to L4T partition. - res = !sdmmc_storage_write(part_info.storage, lba_curr + l4t_flash_ctxt.offset_sct, num, buf); + res = !sdmmc_storage_write(storage, lba_curr + l4t_flash_ctxt.offset_sct, num, buf); manual_system_maintenance(false); @@ -905,7 +923,7 @@ static lv_res_t _action_flash_linux_data(lv_obj_t * btns, const char * txt) goto exit; } - res = !sdmmc_storage_write(part_info.storage, lba_curr + l4t_flash_ctxt.offset_sct, num, buf); + res = !sdmmc_storage_write(storage, lba_curr + l4t_flash_ctxt.offset_sct, num, buf); manual_system_maintenance(false); } @@ -938,31 +956,36 @@ exit: free(path); free(txt_buf); + boot_storage_unmount(); + if(part_info.drive == DRIVE_SD){ + sd_unmount(); + }else{ + emmc_unmount(); + } + if (!succeeded) lv_mbox_add_btns(mbox, mbox_btn_map, mbox_action); else lv_mbox_add_btns(mbox, mbox_btn_map2, _action_delete_linux_installer_files); lv_obj_align(mbox, NULL, LV_ALIGN_CENTER, 0, 0); - sd_unmount(); - if (part_info.emmc) - emmc_end(); - return LV_RES_INV; } static u32 _get_available_l4t_partition() { + sdmmc_storage_t *storage = part_info.drive == DRIVE_SD ? &sd_storage : &emmc_storage; + mbr_t mbr = { 0 }; gpt_t *gpt = zalloc(sizeof(gpt_t)); memset(&l4t_flash_ctxt, 0, sizeof(l4t_flasher_ctxt_t)); // Read MBR. - sdmmc_storage_read(part_info.storage, 0, 1, &mbr); + sdmmc_storage_read(storage, 0, 1, &mbr); // Read main GPT. - sdmmc_storage_read(part_info.storage, 1, sizeof(gpt_t) >> 9, gpt); + sdmmc_storage_read(storage, 1, sizeof(gpt_t) >> 9, gpt); // Search for a suitable partition. u32 size_sct = 0; @@ -970,12 +993,15 @@ static u32 _get_available_l4t_partition() { for (u32 i = 0; i < gpt->header.num_part_ents; i++) { - if (!memcmp(gpt->entries[i].name, (u16[]) { 'l', '4', 't' }, 6)) + if (!memcmp(gpt->entries[i].name, (char[]) { 'l', 0, '4', 0, 't', 0 }, 6)) { l4t_flash_ctxt.offset_sct = gpt->entries[i].lba_start; size_sct = (gpt->entries[i].lba_end + 1) - gpt->entries[i].lba_start; break; } + + if (i > 126) + break; } } else @@ -1001,7 +1027,8 @@ static int _get_available_android_partition() gpt_t *gpt = zalloc(sizeof(gpt_t)); // Read main GPT. - sdmmc_storage_read(part_info.storage, 1, sizeof(gpt_t) >> 9, gpt); + sdmmc_storage_t *storage = part_info.drive == DRIVE_SD ? &sd_storage : &emmc_storage; + sdmmc_storage_read(storage, 1, sizeof(gpt_t) >> 9, gpt); // Check if GPT. if (memcmp(&gpt->header.signature, "EFI PART", 8) || gpt->header.num_part_ents > 128) @@ -1012,8 +1039,8 @@ static int _get_available_android_partition() { if (gpt->entries[i].lba_start) { - int found = !memcmp(gpt->entries[i].name, (u16[]) { 'b', 'o', 'o', 't' }, 8) ? 2 : 0; - found |= !memcmp(gpt->entries[i].name, (u16[]) { 'L', 'N', 'X' }, 6) ? 1 : 0; + int found = !memcmp(gpt->entries[i].name, (char[]) { 'b', 0, 'o', 0, 'o', 0, 't', 0 }, 8) ? 2 : 0; + found |= !memcmp(gpt->entries[i].name, (char[]) { 'L', 0, 'N', 0, 'X', 0 }, 6) ? 1 : 0; if (found) { @@ -1022,6 +1049,9 @@ static int _get_available_android_partition() return found; } } + + if (i > 126) + break; } out: @@ -1056,9 +1086,12 @@ static lv_res_t _action_check_flash_linux(lv_obj_t *btn) manual_system_maintenance(true); - sd_mount(); - if (part_info.emmc) - emmc_initialize(false); + boot_storage_mount(); + if(part_info.drive == DRIVE_SD){ + sd_mount(); + }else{ + emmc_mount(); + } // Check if L4T image exists. strcpy(path, "switchroot/install/l4t.00"); @@ -1144,11 +1177,16 @@ error: lv_mbox_add_btns(mbox, mbox_btn_map, mbox_action); exit: + boot_storage_unmount(); + if(part_info.drive == DRIVE_SD){ + sd_unmount(); + }else{ + emmc_unmount(); + } + lv_obj_align(mbox, NULL, LV_ALIGN_CENTER, 0, 0); - sd_unmount(); - if (part_info.emmc) - emmc_end(); + boot_storage_unmount(); return LV_RES_OK; } @@ -1170,11 +1208,16 @@ static lv_res_t _action_reboot_recovery(lv_obj_t * btns, const char * txt) // Set id to Android. strcpy((char *)b_cfg->id, "SWANDR"); + if(android_flash_ctxt.slot > 1 && android_flash_ctxt.slot < 10){ + s_printf((char*)(b_cfg->id + strlen((char*)b_cfg->id)), "%d", android_flash_ctxt.slot); + } void (*main_ptr)() = (void *)nyx_str->hekate; // Deinit hardware. sd_end(); + emmc_end(); + boot_storage_end(); hw_deinit(false); // Chainload to hekate main. @@ -1219,14 +1262,19 @@ static lv_res_t _action_flash_android_data(lv_obj_t * btns, const char * txt) lv_obj_align(mbox, NULL, LV_ALIGN_CENTER, 0, 0); lv_obj_set_top(mbox, true); + sdmmc_storage_t *storage = part_info.drive == DRIVE_SD ? &sd_storage : &emmc_storage; + manual_system_maintenance(true); - sd_mount(); - if (part_info.emmc) - emmc_initialize(false); + if(part_info.drive == DRIVE_SD){ + sd_mount(); + }else{ + emmc_mount(); + } + boot_storage_mount(); // Read main GPT. - sdmmc_storage_read(part_info.storage, 1, sizeof(gpt_t) >> 9, gpt); + sdmmc_storage_read(storage, 1, sizeof(gpt_t) >> 9, gpt); // Validate GPT header. if (memcmp(&gpt->header.signature, "EFI PART", 8) || gpt->header.num_part_ents > 128) @@ -1237,6 +1285,8 @@ static lv_res_t _action_flash_android_data(lv_obj_t * btns, const char * txt) u32 offset_sct = 0; u32 size_sct = 0; + s32 gpt_idx = 0; + char name[36]; // Check if Kernel image should be flashed. strcpy(path, "switchroot/install/boot.img"); @@ -1246,23 +1296,25 @@ static lv_res_t _action_flash_android_data(lv_obj_t * btns, const char * txt) goto boot_img_not_found; } - // Find Kernel partition. - for (u32 i = 0; i < gpt->header.num_part_ents; i++) - { - if (!memcmp(gpt->entries[i].name, (u16[]) { 'L', 'N', 'X' }, 6) || - !memcmp(gpt->entries[i].name, (u16[]) { 'b', 'o', 'o', 't' }, 8)) - { - offset_sct = gpt->entries[i].lba_start; - size_sct = (gpt->entries[i].lba_end + 1) - gpt->entries[i].lba_start; - break; - } + + // find kernel partition + // look for dynamic boot partition + _make_part_name(name, "boot", android_flash_ctxt.slot); + gpt_idx = _get_gpt_part_by_name(gpt, name, -1); + if(gpt_idx == -1){ + _make_part_name(name, "LNX", android_flash_ctxt.slot); + gpt_idx = _get_gpt_part_by_name(gpt, name, -1); + } + if(gpt_idx != -1){ + offset_sct = gpt->entries[gpt_idx].lba_start; + size_sct = (gpt->entries[gpt_idx].lba_end + 1) - gpt->entries[gpt_idx].lba_start; } // Flash Kernel. if (offset_sct && size_sct) { u32 file_size = 0; - u8 *buf = sd_file_read(path, &file_size); + u8 *buf = boot_storage_file_read(path, &file_size); if (file_size % 0x200) { @@ -1277,7 +1329,7 @@ static lv_res_t _action_flash_android_data(lv_obj_t * btns, const char * txt) s_printf(txt_buf, "#FF8000 Warning:# Kernel image too big!\n"); else { - sdmmc_storage_write(part_info.storage, offset_sct, file_size >> 9, buf); + sdmmc_storage_write(storage, offset_sct, file_size >> 9, buf); s_printf(txt_buf, "#C7EA46 Success:# Kernel image flashed!\n"); f_unlink(path); @@ -1308,23 +1360,23 @@ boot_img_not_found: offset_sct = 0; size_sct = 0; - // Find Recovery partition. - for (u32 i = 0; i < gpt->header.num_part_ents; i++) - { - if (!memcmp(gpt->entries[i].name, (u16[]) { 'S', 'O', 'S' }, 6) || - !memcmp(gpt->entries[i].name, (u16[]) { 'r', 'e', 'c', 'o', 'v', 'e', 'r', 'y' }, 16)) - { - offset_sct = gpt->entries[i].lba_start; - size_sct = (gpt->entries[i].lba_end + 1) - gpt->entries[i].lba_start; - break; - } + // find recovery parititon + _make_part_name(name, "recovery", android_flash_ctxt.slot); + gpt_idx = _get_gpt_part_by_name(gpt, name, -1); + if(gpt_idx == -1){ + _make_part_name(name, "SOS", android_flash_ctxt.slot); + gpt_idx = _get_gpt_part_by_name(gpt, name, -1); + } + if(gpt_idx != -1){ + offset_sct = gpt->entries[gpt_idx].lba_start; + size_sct = (gpt->entries[gpt_idx].lba_end + 1) - gpt->entries[gpt_idx].lba_start; } // Flash Recovery. if (offset_sct && size_sct) { u32 file_size = 0; - u8 *buf = sd_file_read(path, &file_size); + u8 *buf = boot_storage_file_read(path, &file_size); if (file_size % 0x200) { @@ -1339,7 +1391,7 @@ boot_img_not_found: strcat(txt_buf, "#FF8000 Warning:# Recovery image too big!\n"); else { - sdmmc_storage_write(part_info.storage, offset_sct, file_size >> 9, buf); + sdmmc_storage_write(storage, offset_sct, file_size >> 9, buf); strcat(txt_buf, "#C7EA46 Success:# Recovery image flashed!\n"); f_unlink(path); } @@ -1368,23 +1420,23 @@ recovery_not_found: offset_sct = 0; size_sct = 0; - // Find Device Tree partition. - for (u32 i = 0; i < gpt->header.num_part_ents; i++) - { - if (!memcmp(gpt->entries[i].name, (u16[]) { 'D', 'T', 'B' }, 6) || - !memcmp(gpt->entries[i].name, (u16[]) { 'd', 't', 'b' }, 6)) - { - offset_sct = gpt->entries[i].lba_start; - size_sct = (gpt->entries[i].lba_end + 1) - gpt->entries[i].lba_start; - break; - } + // find dtb partition + _make_part_name(name, "dtb", android_flash_ctxt.slot); + gpt_idx = _get_gpt_part_by_name(gpt, name, -1); + if(gpt_idx == -1){ + _make_part_name(name, "DTB", android_flash_ctxt.slot); + gpt_idx = _get_gpt_part_by_name(gpt, name, -1); + } + if(gpt_idx != -1){ + offset_sct = gpt->entries[gpt_idx].lba_start; + size_sct = (gpt->entries[gpt_idx].lba_end + 1) - gpt->entries[gpt_idx].lba_start; } // Flash Device Tree. if (offset_sct && size_sct) { u32 file_size = 0; - u8 *buf = sd_file_read(path, &file_size); + u8 *buf = boot_storage_file_read(path, &file_size); if (file_size % 0x200) { @@ -1399,7 +1451,7 @@ recovery_not_found: strcat(txt_buf, "#FF8000 Warning:# DTB image too big!"); else { - sdmmc_storage_write(part_info.storage, offset_sct, file_size >> 9, buf); + sdmmc_storage_write(storage, offset_sct, file_size >> 9, buf); strcat(txt_buf, "#C7EA46 Success:# DTB image flashed!"); f_unlink(path); } @@ -1412,20 +1464,28 @@ recovery_not_found: dtb_not_found: lv_label_set_text(lbl_status, txt_buf); - // Check if Recovery is flashed unconditionally. - u8 *rec = malloc(SD_BLOCKSIZE); - for (u32 i = 0; i < gpt->header.num_part_ents; i++) - { - if (!memcmp(gpt->entries[i].name, (u16[]) { 'S', 'O', 'S' }, 6) || - !memcmp(gpt->entries[i].name, (u16[]) { 'r', 'e', 'c', 'o', 'v', 'e', 'r', 'y' }, 16)) - { - sdmmc_storage_read(part_info.storage, gpt->entries[i].lba_start, 1, rec); - if (!memcmp(rec, "ANDROID", 7)) - boot_recovery = true; - break; - } + offset_sct = 0; + + // find recovery parititon + _make_part_name(name, "recovery", android_flash_ctxt.slot); + gpt_idx = _get_gpt_part_by_name(gpt, name, -1); + if(gpt_idx == -1){ + _make_part_name(name, "SOS", android_flash_ctxt.slot); + gpt_idx = _get_gpt_part_by_name(gpt, name, -1); + } + if(gpt_idx != -1){ + offset_sct = gpt->entries[gpt_idx].lba_start; + } + + // unconditionally check for valid recovery + if(offset_sct){ + u8 *buf = malloc(SD_BLOCKSIZE); + sdmmc_storage_read(storage, offset_sct, 1, buf); + if(!memcmp(buf, "ANDROID", 7)){ + boot_recovery = true; + } + free(buf); } - free(rec); error: if (boot_recovery) @@ -1443,9 +1503,12 @@ error: free(txt_buf); free(gpt); - sd_unmount(); - if (part_info.emmc) - emmc_end(); + if(part_info.drive == DRIVE_SD){ + sd_unmount(); + }else{ + emmc_unmount(); + } + boot_storage_unmount(); return LV_RES_INV; } @@ -1470,7 +1533,116 @@ static lv_res_t _action_flash_android(lv_obj_t *btn) "These will be deleted after a successful flash.\n" "Do you want to continue?"); - lv_mbox_add_btns(mbox, mbox_btn_map, _action_flash_android_data); + lv_mbox_add_btns(mbox, mbox_btn_map, _action_flash_android_data); + lv_obj_align(mbox, NULL, LV_ALIGN_CENTER, 0, 0); + lv_obj_set_top(mbox, true); + + return LV_RES_OK; +} + +static u32 _get_num_slots_android(){ + sdmmc_storage_t *storage = part_info.drive == DRIVE_SD ? &sd_storage : &emmc_storage; + + u32 res = 0; + + mbr_t mbr; + gpt_t *gpt = NULL; + sdmmc_storage_read(storage, 0, 1, &mbr); + + if(!_has_gpt(&mbr)){ + goto out; + } + + gpt = zalloc(sizeof(*gpt)); + + sdmmc_storage_read(storage, 1, sizeof(*gpt) / 0x200, gpt); + + if(memcmp(&gpt->header.signature, "EFI PART", 8)){ + goto out; + } + + s32 gpt_idx = -1; + // check for dynamic + gpt_idx = _get_gpt_part_by_name(gpt, "boot", gpt_idx); + if(gpt_idx != -1){ + res++; + gpt_idx = _get_gpt_part_by_name(gpt, "boot", gpt_idx); + if(gpt_idx != -1){ + res++; + } + goto out; + } + + gpt_idx = -1; + // check for legacy + gpt_idx = _get_gpt_part_by_name(gpt, "LNX", gpt_idx); + if(gpt_idx != -1){ + res++; + gpt_idx = _get_gpt_part_by_name(gpt, "LNX", gpt_idx); + if(gpt_idx != -1){ + res++; + } + goto out; + } + + out: + free(gpt); + return res; +} + +static lv_res_t _action_flash_android_slot_select1(lv_obj_t *btns, const char *txt){ + int btn_idx = lv_btnm_get_pressed(btns); + + switch(btn_idx){ + case 0: + android_flash_ctxt.slot = 1; + break; + case 1: + android_flash_ctxt.slot = 2; + break; + } + + mbox_action(btns, txt); + + return _action_flash_android(NULL); +} + +static lv_res_t _action_flash_android_slot_select(lv_obj_t *btn){ + u32 n_slots = _get_num_slots_android(); + + if(n_slots == 1){ + android_flash_ctxt.slot = 1; + return _action_flash_android(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); + + static const char *mbox_btn_map[] = { "\222Slot 1", "\222Slot 2", "" }; + static const char *mbox_btn_map2[] = { "\222OK", ""}; + + lv_obj_t * mbox = lv_mbox_create(dark_bg, NULL); + lv_mbox_set_recolor_text(mbox, true); + + lv_obj_set_width(mbox, LV_HOR_RES / 10 * 5); + lv_mbox_set_text(mbox, "#FF8000 Android Flasher#"); + + lv_obj_t *lbl_status = lv_label_create(mbox, NULL); + lv_label_set_recolor(lbl_status, true); + + + if(n_slots == 0){ + lv_label_set_text(lbl_status, + "No Android partitions found!\n"); + lv_mbox_add_btns(mbox, mbox_btn_map2, mbox_action); + }else{ + lv_label_set_text(lbl_status, + "Found multible sets of Android partitions.\n" + "Please select the slot to use\n"); + lv_mbox_add_btns(mbox, mbox_btn_map, _action_flash_android_slot_select1); + } + lv_obj_align(mbox, NULL, LV_ALIGN_CENTER, 0, 0); lv_obj_set_top(mbox, true); @@ -1484,14 +1656,18 @@ static lv_res_t _action_part_manager_flash_options0(lv_obj_t *btns, const char * switch (btn_idx) { case 0: - action_ums_sd(NULL); + if(part_info.drive == DRIVE_SD){ + action_ums_sd(btns); + }else{ + action_ums_emmc_gpp(btns); + } lv_obj_del(ums_mbox); break; case 1: - _action_check_flash_linux(NULL); + _action_check_flash_linux(btns); break; case 2: - _action_flash_android(NULL); + _action_flash_android_slot_select(btns); break; case 3: mbox_action(btns, txt); @@ -1508,7 +1684,11 @@ static lv_res_t _action_part_manager_flash_options1(lv_obj_t *btns, const char * switch (btn_idx) { case 0: - action_ums_sd(NULL); + if(part_info.drive == DRIVE_SD){ + action_ums_sd(btns); + }else{ + action_ums_emmc_gpp(btns); + } lv_obj_del(ums_mbox); break; case 1: @@ -1530,12 +1710,16 @@ static lv_res_t _action_part_manager_flash_options2(lv_obj_t *btns, const char * switch (btn_idx) { case 0: - action_ums_sd(NULL); + if(part_info.drive == DRIVE_SD){ + action_ums_sd(btns); + }else{ + action_ums_emmc_gpp(btns); + } lv_obj_del(ums_mbox); break; case 1: mbox_action(btns, txt); - _action_flash_android(NULL); + _action_flash_android_slot_select(NULL); return LV_RES_INV; case 2: mbox_action(btns, txt); @@ -1545,10 +1729,10 @@ static lv_res_t _action_part_manager_flash_options2(lv_obj_t *btns, const char * return LV_RES_OK; } -static int _backup_and_restore_files(bool backup, lv_obj_t **labels) +static int _backup_and_restore_files(bool backup, const char *drive, lv_obj_t **labels) { - const char *src_drv = backup ? "sd:" : "ram:"; - const char *dst_drv = backup ? "ram:" : "sd:"; + const char *src_drv = backup ? drive : "ram:"; + const char *dst_drv = backup ? "ram:" : drive; int res = 0; u32 total_size = 0; @@ -1571,8 +1755,12 @@ static int _backup_and_restore_files(bool backup, lv_obj_t **labels) } // Copy all or hekate/Nyx files. + DBG_PRINT("start stat"); + gfx_printf("src %s\ndst %s\npath %s\n", src_drv, dst_drv, path); res = _stat_and_copy_files(src_drv, dst_drv, path, &total_files, &total_size, labels); + gfx_printf("bkup res %d mws %d pld %d tot %d\n", res, (u32)backup_pld, total_files); + // If incomplete backup mode, copy MWS and payload.bin also. if (!res) { @@ -1588,8 +1776,71 @@ static int _backup_and_restore_files(bool backup, lv_obj_t **labels) return res; } -static lv_res_t _sd_create_mbox_start_partitioning() +static DWORD _format_fat_partition(const char* path, u8 flags){ + // Set cluster size to 64KB and try to format. + u8 *buf = malloc(SZ_4M); + u32 cluster_size = 65536; + u32 mkfs_error = f_mkfs(path, flags, cluster_size, buf, SZ_4M); + + // Retry formatting by halving cluster size, until one succeeds. + while (mkfs_error != FR_OK && cluster_size > 4096) + { + cluster_size /= 2; + mkfs_error = f_mkfs(path, flags, cluster_size, buf, SZ_4M); + } + + free(buf); + + return mkfs_error; +} + +static bool _derive_bis_keys(gpt_t *gpt) { + bool res = true; + + // Read and decrypt CAL0 for validation of working BIS keys. + s32 gpt_idx = _get_gpt_part_by_name(gpt, "PRODINFO", -1); + if(gpt_idx == -1){ + return false; + } + + emmc_part_t cal0_part = {0}; + cal0_part.lba_start = gpt->entries[gpt_idx].lba_start; + cal0_part.lba_end = gpt->entries[gpt_idx].lba_end; + strcpy(cal0_part.name, "PRODINFO"); + + // Generate BIS keys. + hos_bis_keygen(); + + u8 *cal0_buff = malloc(SZ_64K); + + nx_emmc_bis_init(&cal0_part, false, part_info.drive == DRIVE_SD ? &sd_storage : &emmc_storage, 0); + nx_emmc_bis_read(0, 0x40, cal0_buff); + nx_emmc_bis_end(); + + nx_emmc_cal0_t *cal0 = (nx_emmc_cal0_t *)cal0_buff; + + // Check keys validity. + if (memcmp(&cal0->magic, "CAL0", 4)) + { + // Clear EKS keys. + hos_eks_clear(HOS_MKEY_VER_MAX); + res = false; + } + + free(cal0_buff); + + return res; +} + +static lv_res_t _create_mbox_start_partitioning(lv_obj_t *btn) +{ + char cwd[0x200]; + gpt_t *new_gpt = NULL; + + // TODO: remove the cwd stuff + f_getcwd(cwd, sizeof(cwd)); + 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); @@ -1598,11 +1849,18 @@ static lv_res_t _sd_create_mbox_start_partitioning() static const char *mbox_btn_map1[] = { "\222SD UMS", "\222Flash Linux", "\222Flash Android", "\221OK", "" }; static const char *mbox_btn_map2[] = { "\222SD UMS", "\222Flash Linux", "\221OK", "" }; static const char *mbox_btn_map3[] = { "\222SD UMS", "\222Flash Android", "\221OK", "" }; + + static const char *mbox_btn_map1_emmc[] = { "\222eMMC UMS", "\222Flash Linux", "\222Flash Android", "\221OK", "" }; + static const char *mbox_btn_map2_emmc[] = { "\222eMMC UMS", "\222Flash Linux", "\221OK", "" }; + static const char *mbox_btn_map3_emmc[] = { "\222eMMC UMS", "\222Flash Android", "\221OK", "" }; + + sdmmc_storage_t *storage = part_info.drive == DRIVE_SD ? &sd_storage : &emmc_storage; + lv_obj_t *mbox = lv_mbox_create(dark_bg, NULL); lv_mbox_set_recolor_text(mbox, true); lv_obj_set_width(mbox, LV_HOR_RES / 9 * 6); - lv_mbox_set_text(mbox, "#FF8000 SD Partition Manager#"); + lv_mbox_set_text(mbox, "#FF8000 Partition Manager#"); lv_obj_align(mbox, NULL, LV_ALIGN_CENTER, 0, 0); lv_obj_set_top(mbox, true); @@ -1610,7 +1868,7 @@ static lv_res_t _sd_create_mbox_start_partitioning() // Use safety wait if backup is not possible. char *txt_buf = malloc(SZ_4K); - strcpy(txt_buf, "#FF8000 SD Partition Manager#\n\nSafety wait ends in "); + strcpy(txt_buf, "#FF8000 Partition Manager#\n\nSafety wait ends in "); lv_mbox_set_text(mbox, txt_buf); u32 seconds = 5; @@ -1625,7 +1883,7 @@ static lv_res_t _sd_create_mbox_start_partitioning() } lv_mbox_set_text(mbox, - "#FF8000 SD Partition Manager#\n\n" + "#FF8000 Partition Manager#\n\n" "#FFDD00 Warning: Do you really want to continue?!#\n\n" "Press #FF8000 POWER# to Continue.\nPress #FF8000 VOL# to abort."); lv_obj_align(mbox, NULL, LV_ALIGN_CENTER, 0, 0); @@ -1636,8 +1894,7 @@ static lv_res_t _sd_create_mbox_start_partitioning() if (!(btn_wait() & BTN_POWER)) goto exit; - // Start partitioning. - lv_mbox_set_text(mbox, "#FF8000 SD Partition Manager#"); + lv_mbox_set_text(mbox, "#FF8000 Partition Manager#"); lv_obj_align(mbox, NULL, LV_ALIGN_CENTER, 0, 0); manual_system_maintenance(true); @@ -1660,140 +1917,221 @@ static lv_res_t _sd_create_mbox_start_partitioning() lv_obj_set_width(lbl_paths[1], (LV_HOR_RES / 9 * 6) - LV_DPI / 2); lv_label_set_align(lbl_paths[1], LV_LABEL_ALIGN_CENTER); - sd_mount(); - FATFS ram_fs; - // Read current MBR. - sdmmc_storage_read(part_info.storage, 0, 1, &part_info.mbr_old); - - lv_label_set_text(lbl_status, "#00DDFF Status:# Initializing Ramdisk..."); - lv_label_set_text(lbl_paths[0], "Please wait..."); - lv_obj_align(mbox, NULL, LV_ALIGN_CENTER, 0, 0); - manual_system_maintenance(true); - - // Initialize RAM disk. - if (ram_disk_init(&ram_fs, RAM_DISK_SZ)) - { - lv_label_set_text(lbl_status, "#FFDD00 Error:# Failed to initialize Ramdisk!"); - goto error; - } - - lv_label_set_text(lbl_status, "#00DDFF Status:# Backing up files..."); - manual_system_maintenance(true); - - // Do full or hekate/Nyx backup. - if (_backup_and_restore_files(true, lbl_paths)) - { - if (part_info.backup_possible) - lv_label_set_text(lbl_status, "#FFDD00 Error:# Failed to back up files!"); - else - lv_label_set_text(lbl_status, "#FFDD00 Error:# Failed to back up files!\nBootloader folder exceeds 1.2GB or corrupt!"); - - goto error; - } - - f_unmount("sd:"); // Unmount SD card. - - lv_label_set_text(lbl_status, "#00DDFF Status:# Formatting FAT32 partition..."); - lv_label_set_text(lbl_paths[0], "Please wait..."); - lv_label_set_text(lbl_paths[1], " "); - manual_system_maintenance(true); - - // Set reserved size. - u32 part_rsvd_size = (part_info.emu_size << 11) + (part_info.l4t_size << 11) + (part_info.and_size << 11); - part_rsvd_size += part_rsvd_size ? part_info.alignment : 0; // Do not reserve alignment space if no extra partitions. - disk_set_info(DRIVE_SD, SET_SECTOR_COUNT, &part_rsvd_size); - u8 *buf = malloc(SZ_4M); - - // Set cluster size to 64KB and try to format. - u32 cluster_size = 65536; - u32 mkfs_error = f_mkfs("sd:", FM_FAT32, cluster_size, buf, SZ_4M); - - if (!mkfs_error) - goto mkfs_no_error; - - // Retry formatting by halving cluster size, until one succeeds. - while (cluster_size > 4096) - { - cluster_size /= 2; - mkfs_error = f_mkfs("sd:", FM_FAT32, cluster_size, buf, SZ_4M); - - if (!mkfs_error) - break; - } - - if (mkfs_error) - { - // Failed to format. - s_printf((char *)buf, "#FFDD00 Error:# Failed to format disk (%d)!\n\n" - "Remove the SD card and check that is OK.\nIf not, format it, reinsert it and\npress #FF8000 POWER#!", mkfs_error); - - lv_label_set_text(lbl_status, (char *)buf); - lv_label_set_text(lbl_paths[0], " "); - manual_system_maintenance(true); - - sd_end(); - - while (!(btn_wait() & BTN_POWER)); - + if(part_info.drive == DRIVE_SD){ sd_mount(); + }else{ + emmc_mount(); + } - lv_label_set_text(lbl_status, "#00DDFF Status:# Restoring files..."); + // Read current MBR. + sdmmc_storage_read(storage, 0, 1, &part_info.mbr_old); + + if(!part_info.skip_backup && part_info.hos_size){ + // can't backup / restore if new scheme has no fat partition. dialog will have warned about this + lv_label_set_text(lbl_status, "#00DDFF Status:# Initializing Ramdisk..."); + lv_label_set_text(lbl_paths[0], "Please wait..."); + lv_obj_align(mbox, NULL, LV_ALIGN_CENTER, 0, 0); manual_system_maintenance(true); - // Restore backed up files back to SD. - if (_backup_and_restore_files(false, lbl_paths)) + // Initialize RAM disk. + if (ram_disk_init(&ram_fs, RAM_DISK_SZ)) { - // Failed to restore files. Try again once more. - if (_backup_and_restore_files(false, lbl_paths)) - { - lv_label_set_text(lbl_status, "#FFDD00 Error:# Failed to restore files!"); - free(buf); - goto error; - } + lv_label_set_text(lbl_status, "#FFDD00 Error:# Failed to initialize Ramdisk!"); + goto error; } - lv_label_set_text(lbl_status, "#00DDFF Status:# Restored files but the operation failed!"); - f_unmount("ram:"); - free(buf); - goto error; - } + lv_label_set_text(lbl_status, "#00DDFF Status:# Backing up files..."); + manual_system_maintenance(true); -mkfs_no_error: - free(buf); - - // Remount sd card as it was unmounted from formatting it. - f_mount(&sd_fs, "sd:", 1); // Mount SD card. - - lv_label_set_text(lbl_status, "#00DDFF Status:# Restoring files..."); - manual_system_maintenance(true); - - // Restore backed up files back to SD. - if (_backup_and_restore_files(false, lbl_paths)) - { - // Failed to restore files. Try again once more. - if (_backup_and_restore_files(false, lbl_paths)) + // Do full or hekate/Nyx backup. + if (_backup_and_restore_files(true, part_info.drive == DRIVE_SD ? "sd:" : "emmc:", lbl_paths)) { - lv_label_set_text(lbl_status, "#FFDD00 Error:# Failed to restore files!"); + if (part_info.backup_possible) + lv_label_set_text(lbl_status, "#FFDD00 Error:# Failed to back up files!"); + else + lv_label_set_text(lbl_status, "#FFDD00 Error:# Failed to back up files!\nBootloader folder exceeds 1GB or corrupt!"); + manual_system_maintenance(true); + goto error; } } - // Unmount ramdisk. - f_unmount("ram:"); - f_chdrive("sd:"); + if(part_info.drive == DRIVE_SD){ + sd_unmount(); + }else{ + emmc_unmount(); + } - // Set Volume label. - f_setlabel("0:SWITCH SD"); - - lv_label_set_text(lbl_status, "#00DDFF Status:# Flashing partition table..."); + lv_label_set_text(lbl_status, "#00ddff Status:# Writing new partition table..."); lv_label_set_text(lbl_paths[0], "Please wait..."); lv_label_set_text(lbl_paths[1], " "); manual_system_maintenance(true); - // Prepare MBR and GPT header and partition entries and flash them. - _sd_prepare_and_flash_mbr_gpt(); + _prepare_and_flash_mbr_gpt(); + + mbr_t new_mbr; + + sdmmc_storage_read(storage, 0, 1, &new_mbr); + + bool has_gpt = _has_gpt(&new_mbr); + + if(has_gpt){ + new_gpt = zalloc(sizeof(*new_gpt)); + sdmmc_storage_read(storage, 1, sizeof(*new_gpt) / 0x200, new_gpt); + } + + + // Restore backed up files if we made a fat32 partition + if(part_info.hos_size){ + u32 hos_start = 0; + u32 hos_size = 0; + if(!has_gpt){ + // FAT32 partition is first in mbr if we don't have gpt + hos_size = new_mbr.partitions[0].size_sct; + hos_start = new_mbr.partitions[0].start_sct; + }else{ + int hos_idx = _get_gpt_part_by_name(new_gpt, "hos_data", -1); + if(hos_idx != -1){ + hos_size = new_gpt->entries[hos_idx].lba_end - new_gpt->entries[hos_idx].lba_start + 1; + hos_start = new_gpt->entries[hos_idx].lba_start; + } + } + + lv_label_set_text(lbl_status, "#00ddff Status:# Formatting FAT32 partition..."); + manual_system_maintenance(true); + + sfd_init(storage, hos_start, hos_size); + u32 mkfs_error = _format_fat_partition("sfd:", FM_FAT32 | FM_SFD); + + u8 *buf = malloc(0x200); + + if(mkfs_error != FR_OK){ + // Error + s_printf((char*)buf, "#FFDD00 Error:# Failed to format disk (%d)!\n\n", mkfs_error); + if(part_info.drive == DRIVE_SD && !part_info.skip_backup){ + // When SD and not skipping backup, ask to manually format sd and try to restore backed up files + strcat((char*)buf, "\n\nRemove the SD card and check that it is OK.\nIf not, format it, reinsert it and\npress #FF8000 POWER# to continue!"); + } + + lv_label_set_text(lbl_status, (char *)buf); + lv_label_set_text(lbl_paths[0], " "); + manual_system_maintenance(true); + + if(part_info.drive == DRIVE_SD && !part_info.skip_backup){ + sd_end(); + while((!btn_wait()) & BTN_POWER){} + sd_mount(); + + lv_label_set_text(lbl_status, "#00DDFF Status:# Restoring files..."); + manual_system_maintenance(true); + + if(boot_storage_get_drive() != DRIVE_SD){ + FIL f; + f_open(&f, part_info.drive == DRIVE_SD ? "sd:.no_boot_storage" : "emmc:.no_boot_storage", FA_WRITE | FA_CREATE_ALWAYS); + f_close(&f); + } + + // Try twice to restore files + if (_backup_and_restore_files(false, "sd:", lbl_paths) == FR_OK || + _backup_and_restore_files(false, "sd:", lbl_paths) == FR_OK){ + lv_label_set_text(lbl_status, "#00DDFF Status:# Restored files but the operation failed!"); + }else{ + lv_label_set_text(lbl_status, "#FFDD00 Error:# Failed to restore files!"); + } + manual_system_maintenance(true); + } + f_mount(NULL, "ram:", 0); + sfd_end(); + free(buf); + goto error; + }else{ + // No error + // remount + if(part_info.drive == DRIVE_SD){ + sd_mount(); + }else{ + emmc_mount(); + } + + int res = f_setlabel(part_info.drive == DRIVE_SD ? "sd:SWITCH SD" : "emmc:SWITCH EMMC"); + gfx_printf("setlabel %d\n", res); + + if(boot_storage_get_drive() != part_info.drive){ + // if we havent booted from the drive currently being formatted, create .no_boot_storage + FIL f; + f_open(&f, part_info.drive == DRIVE_SD ? "sd:.no_boot_storage" : "emmc:.no_boot_storage", FA_WRITE | FA_CREATE_ALWAYS); + f_close(&f); + } + + if(!part_info.skip_backup){ + lv_label_set_text(lbl_status, "#00DDFF Status:# Restoring files..."); + manual_system_maintenance(true); + // Try twice to restroe files + DBG_PRINT("start restore"); + if (_backup_and_restore_files(false, part_info.drive == DRIVE_SD ? "sd:" : "emmc:", lbl_paths) != FR_OK && + _backup_and_restore_files(false, part_info.drive == DRIVE_SD ? "sd:" : "emmc:", lbl_paths) != FR_OK) + { + // Restore failed + lv_label_set_text(lbl_status, "#FFDD00 Error:# Failed to restore files!"); + manual_system_maintenance(true); + f_mount(NULL, "ram:", 0); + sfd_end(); + free(buf); + goto error; + } + } + + f_mount(NULL, "ram:", 0); + free(buf); + } + sfd_end(); + } + + // Format HOS USER if size changed + if(has_gpt){ + s32 gpt_idx = _get_gpt_part_by_name(new_gpt, "USER", -1); + if(gpt_idx != -1){ + // resize user if necessary + gpt_entry_t *entry = &new_gpt->entries[gpt_idx]; + u32 user_size = entry->lba_end - new_gpt->entries[gpt_idx].lba_start + 1; + + if(user_size != (part_info.hos_os_og_size - part_info.hos_sys_size_mb) << 11){ + lv_label_set_text(lbl_status, "#00DDFF Status:# Resizing HOS USER partition..."); + manual_system_maintenance(true); + + // size changed + emmc_part_t user_part = { 0 }; + user_part.lba_end = entry->lba_end; + user_part.lba_start = entry->lba_start; + strcpy(user_part.name, "USER"); + + user_size = ALIGN(user_size, 0x20); + disk_set_info(DRIVE_EMU, SET_SECTOR_COUNT, &user_size); + + if(!_derive_bis_keys(new_gpt)){ + lv_label_set_text(lbl_status, "#FFDD00 Error:# BIS key generation failed!"); + manual_system_maintenance(true); + goto error; + } + + nx_emmc_bis_init(&user_part, true, storage, 0); + + u8 *buf = malloc(SZ_4M); + u32 mkfs_res = f_mkfs("emu:", FM_FAT32 | FM_SFD | FM_PRF2, 16384, buf, SZ_4M); + + nx_emmc_bis_end(); + hos_bis_keys_clear(); + + if(mkfs_res != FR_OK){ + lv_label_set_text(lbl_status, "#FFDD00 Error:# Failed to format HOS USER partition!"); + manual_system_maintenance(true); + goto error; + } + } + } + } // Enable/Disable buttons depending on partition layout. if (part_info.l4t_size) @@ -1819,238 +2157,40 @@ mkfs_no_error: lv_btn_set_state(btn_flash_android, LV_BTN_STATE_INA); } - sd_unmount(); lv_label_set_text(lbl_status, "#00DDFF Status:# Done!"); manual_system_maintenance(true); // Set buttons depending on what user chose to create. if (part_info.l4t_size && part_info.and_size) - lv_mbox_add_btns(mbox, mbox_btn_map1, _action_part_manager_flash_options0); + lv_mbox_add_btns(mbox, part_info.drive == DRIVE_SD ? mbox_btn_map1 : mbox_btn_map1_emmc, _action_part_manager_flash_options0); else if (part_info.l4t_size) - lv_mbox_add_btns(mbox, mbox_btn_map2, _action_part_manager_flash_options1); + lv_mbox_add_btns(mbox, part_info.drive == DRIVE_SD ? mbox_btn_map2 : mbox_btn_map2_emmc, _action_part_manager_flash_options1); else if (part_info.and_size) - lv_mbox_add_btns(mbox, mbox_btn_map3, _action_part_manager_flash_options2); + lv_mbox_add_btns(mbox, part_info.drive == DRIVE_SD ? mbox_btn_map3 : mbox_btn_map3_emmc, _action_part_manager_flash_options2); if (part_info.l4t_size || part_info.and_size) buttons_set = true; - goto out; error: - f_chdrive("sd:"); + DBG_PRINT("Done format"); -out: lv_obj_del(lbl_paths[0]); lv_obj_del(lbl_paths[1]); + exit: - if (!buttons_set) + if(!buttons_set){ lv_mbox_add_btns(mbox, mbox_btn_map, mbox_action); + } lv_obj_align(mbox, NULL, LV_ALIGN_CENTER, 0, 0); lv_obj_set_top(mbox, true); // Disable partitioning button. - if (part_info.partition_button) - lv_btn_set_state(part_info.partition_button, LV_BTN_STATE_INA); - - return LV_RES_OK; -} - -static lv_res_t _emmc_create_mbox_start_partitioning() -{ - 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); - - static const char *mbox_btn_map[] = { "\251", "\222OK", "\251", "" }; - static const char *mbox_btn_map1[] = { "\222Flash Linux", "\222Flash Android", "\221OK", "" }; - static const char *mbox_btn_map2[] = { "\222Flash Linux", "\221OK", "" }; - static const char *mbox_btn_map3[] = { "\222Flash Android", "\221OK", "" }; - lv_obj_t *mbox = lv_mbox_create(dark_bg, NULL); - lv_mbox_set_recolor_text(mbox, true); - lv_obj_set_width(mbox, LV_HOR_RES / 9 * 6); - - lv_mbox_set_text(mbox, "#FF8000 eMMC Partition Manager#"); - lv_obj_align(mbox, NULL, LV_ALIGN_CENTER, 0, 0); - lv_obj_set_top(mbox, true); - - bool buttons_set = false; - - // Use safety wait if backup is not possible. - char *txt_buf = malloc(SZ_4K); - strcpy(txt_buf, "#FF8000 eMMC Partition Manager#\n\nSafety wait ends in "); - lv_mbox_set_text(mbox, txt_buf); - - u32 seconds = 5; - u32 text_idx = strlen(txt_buf); - while (seconds) - { - s_printf(txt_buf + text_idx, "%d seconds...", seconds); - lv_mbox_set_text(mbox, txt_buf); - manual_system_maintenance(true); - msleep(1000); - seconds--; + if (btn){ + lv_btn_set_state(btn, LV_BTN_STATE_INA); } - lv_mbox_set_text(mbox, - "#FF8000 eMMC Partition Manager#\n\n" - "#FFDD00 Warning: Do you really want to continue?!#\n\n" - "Press #FF8000 POWER# to Continue.\nPress #FF8000 VOL# to abort."); - lv_obj_align(mbox, NULL, LV_ALIGN_CENTER, 0, 0); - manual_system_maintenance(true); - - if (!(btn_wait() & BTN_POWER)) - goto exit; - - // Start partitioning. - lv_mbox_set_text(mbox, "#FF8000 eMMC Partition Manager#"); - lv_obj_align(mbox, NULL, LV_ALIGN_CENTER, 0, 0); - manual_system_maintenance(true); - - lv_obj_t *lbl_status = lv_label_create(mbox, NULL); - lv_label_set_recolor(lbl_status, true); - - lv_obj_t *lbl_extra = lv_label_create(mbox, NULL); - lv_label_set_long_mode(lbl_extra, LV_LABEL_LONG_DOT); - lv_cont_set_fit(lbl_extra, false, true); - lv_obj_set_width(lbl_extra, (LV_HOR_RES / 9 * 6) - LV_DPI / 2); - lv_label_set_align(lbl_extra, LV_LABEL_ALIGN_CENTER); - - lv_label_set_text(lbl_status, "#00DDFF Status:# Initializing..."); - lv_label_set_text(lbl_extra, "Please wait..."); - lv_obj_align(mbox, NULL, LV_ALIGN_CENTER, 0, 0); - manual_system_maintenance(true); - - if (!emmc_initialize(false)) - { - lv_label_set_text(lbl_extra, "#FFDD00 Failed to init eMMC!#"); - goto exit; - } - - emmc_set_partition(EMMC_GPP); - - if (!emummc_raw_derive_bis_keys()) - { - lv_label_set_text(lbl_extra, "#FFDD00 For formatting USER partition,#\n#FFDD00 BIS keys are needed!#"); - emmc_end(); - goto exit; - } - - lv_label_set_text(lbl_status, "#00DDFF Status:# Flashing partition table..."); - lv_label_set_text(lbl_extra, "Please wait..."); - manual_system_maintenance(true); - - // Prepare MBR and GPT header and partition entries and flash them. - if (_emmc_prepare_and_flash_mbr_gpt()) - goto no_hos_user_part; - - lv_label_set_text(lbl_status, "#00DDFF Status:# Formatting USER partition..."); - lv_label_set_text(lbl_extra, "Please wait..."); - manual_system_maintenance(true); - - // Get USER partition and configure BIS and FatFS. - LIST_INIT(gpt); - emmc_gpt_parse(&gpt); - emmc_part_t *user_part = emmc_part_find(&gpt, "USER"); - - if (!user_part) - { -no_hos_user_part: - s_printf(txt_buf, "#FF0000 HOS USER partition doesn't exist!#\nRestore HOS backup first..."); - lv_label_set_text(lbl_extra, txt_buf); - - emmc_gpt_free(&gpt); - emmc_end(); - - goto exit; - } - - // Initialize BIS for eMMC. BIS keys should be already in place. - nx_emmc_bis_init(user_part, true, 0); - - // Set BIS size for FatFS. - u32 user_sectors = user_part->lba_end - user_part->lba_start + 1; - disk_set_info(DRIVE_BIS, SET_SECTOR_COUNT, &user_sectors); - - // Enable writing. - bool allow_writes = true; - disk_set_info(DRIVE_BIS, SET_WRITE_PROTECT, &allow_writes); - - // Format USER partition as FAT32 with 16KB cluster and PRF2SAFE. - u8 *buff = malloc(SZ_4M); - int mkfs_error = f_mkfs("bis:", FM_FAT32 | FM_SFD | FM_PRF2, 16384, buff, SZ_4M); - - if (mkfs_error) - { - s_printf(txt_buf, "#FF0000 Failed (%d)!#\nPlease try again...\n", mkfs_error); - lv_label_set_text(lbl_extra, txt_buf); - - free(buff); - emmc_end(); - - goto exit; - } - - // Disable writes to BIS. - allow_writes = false; - disk_set_info(DRIVE_BIS, SET_WRITE_PROTECT, &allow_writes); - - // Flush BIS cache, deinit, clear BIS keys slots and reinstate SBK. - nx_emmc_bis_end(); - hos_bis_keys_clear(); - emmc_gpt_free(&gpt); - emmc_end(); - - // Enable/Disable buttons depending on partition layout. - if (part_info.l4t_size) - { - lv_obj_set_click(btn_flash_l4t, true); - lv_btn_set_state(btn_flash_l4t, LV_BTN_STATE_REL); - } - else - { - lv_obj_set_click(btn_flash_l4t, false); - lv_btn_set_state(btn_flash_l4t, LV_BTN_STATE_INA); - } - - // Enable/Disable buttons depending on partition layout. - if (part_info.and_size) - { - lv_obj_set_click(btn_flash_android, true); - lv_btn_set_state(btn_flash_android, LV_BTN_STATE_REL); - } - else - { - lv_obj_set_click(btn_flash_android, false); - lv_btn_set_state(btn_flash_android, LV_BTN_STATE_INA); - } - - lv_label_set_text(lbl_status, "#00DDFF Status:# Done!"); - manual_system_maintenance(true); - - // Set buttons depending on what user chose to create. - if (part_info.l4t_size && part_info.and_size) - lv_mbox_add_btns(mbox, mbox_btn_map1, _action_part_manager_flash_options0); - else if (part_info.l4t_size) - lv_mbox_add_btns(mbox, mbox_btn_map2, _action_part_manager_flash_options1); - else if (part_info.and_size) - lv_mbox_add_btns(mbox, mbox_btn_map3, _action_part_manager_flash_options2); - - if (part_info.l4t_size || part_info.and_size) - buttons_set = true; - - lv_obj_del(lbl_extra); - -exit: - free(txt_buf); - - if (!buttons_set) - lv_mbox_add_btns(mbox, mbox_btn_map, mbox_action); - lv_obj_align(mbox, NULL, LV_ALIGN_CENTER, 0, 0); - lv_obj_set_top(mbox, true); - - // Disable partitioning button. - if (part_info.partition_button) - lv_btn_set_state(part_info.partition_button, LV_BTN_STATE_INA); + free(new_gpt); return LV_RES_OK; } @@ -2062,11 +2202,15 @@ static lv_res_t _create_mbox_partitioning_option0(lv_obj_t *btns, const char *tx switch (btn_idx) { case 0: - action_ums_sd(NULL); + if(part_info.drive == DRIVE_SD){ + action_ums_sd(btns); + }else{ + action_ums_emmc_gpp(btns); + } return LV_RES_OK; case 1: mbox_action(btns, txt); - _sd_create_mbox_start_partitioning(); + _create_mbox_start_partitioning(NULL); break; case 2: mbox_action(btns, txt); @@ -2085,23 +2229,21 @@ static lv_res_t _create_mbox_partitioning_option1(lv_obj_t *btns, const char *tx if (!btn_idx) { mbox_action(btns, txt); - if (!part_info.emmc) - _sd_create_mbox_start_partitioning(); - else - _emmc_create_mbox_start_partitioning(); + _create_mbox_start_partitioning(NULL); return LV_RES_INV; } return LV_RES_OK; } -static lv_res_t _create_mbox_partitioning_warn() +static lv_res_t _create_mbox_partitioning_warn(lv_obj_t *btn) { 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); static const char *mbox_btn_map[] = { "\222SD UMS", "\222Start", "\222Cancel", "" }; + static const char *mbox_btn_map3[] = { "\222eMMC UMS", "\222Start", "\222Cancel", "" }; static const char *mbox_btn_map2[] = { "\222Start", "\222Cancel", "" }; lv_obj_t * mbox = lv_mbox_create(dark_bg, NULL); lv_mbox_set_recolor_text(mbox, true); @@ -2113,36 +2255,50 @@ static lv_res_t _create_mbox_partitioning_warn() lv_obj_t *lbl_status = lv_label_create(mbox, NULL); lv_label_set_recolor(lbl_status, true); - if (!part_info.emmc) - { + if(part_info.drive == DRIVE_SD){ s_printf(txt_buf, "#FFDD00 Warning: This will partition the SD Card!#\n\n"); - - if (part_info.backup_possible) - { - strcat(txt_buf, "#C7EA46 Your files will be backed up and restored!#\n" - "#FFDD00 Any other partition will be wiped!#"); - } - else - { - strcat(txt_buf, "#FFDD00 Your files will be wiped!#\n" - "#FFDD00 Any other partition will be also wiped!#\n" - "#FFDD00 Use USB UMS to copy them over!#"); - } - - lv_label_set_text(lbl_status, txt_buf); - - if (part_info.backup_possible) - lv_mbox_add_btns(mbox, mbox_btn_map2, _create_mbox_partitioning_option1); - else - lv_mbox_add_btns(mbox, mbox_btn_map, _create_mbox_partitioning_option0); + }else{ + s_printf(txt_buf, "#FFDD00 Warning: This will partition the eMMC!#\n\n"); } - else + + if (part_info.backup_possible && part_info.hos_size) { - s_printf(txt_buf, "#FFDD00 Warning: This will partition the eMMC!#\n\n" - "#FFDD00 The USER partition will also be formatted!#"); - lv_label_set_text(lbl_status, txt_buf); - lv_mbox_add_btns(mbox, mbox_btn_map2, _create_mbox_partitioning_option1); + strcat(txt_buf, "#C7EA46 Your files will be backed up and restored!#\n" + "#FFDD00 Any other partition will be wiped!#"); } + else if(part_info.skip_backup) + { + // We have no files to back up + if(part_info.drive == DRIVE_SD){ + strcat(txt_buf, "#FFDD00 All partitions will be wiped!#\n"); + }else{ + if(part_info.hos_os_size){ + strcat(txt_buf, "#FFDD00 All partitions (except HOS ones) will be wiped!#\n"); + }else{ + strcat(txt_buf, "#FFDD00 All partitions will be wiped!#\n"); + } + } + }else{ + // Have files, can't back up + strcat(txt_buf, "#FFDD00 Your files will be wiped!#\n"); + if(part_info.drive == DRIVE_SD){ + strcat(txt_buf, "#FFDD00 All partitions will be also wiped!#\n"); + }else{ + if(part_info.hos_os_size){ + strcat(txt_buf, "#FFDD00 All partitions (except HOS ones) will also be wiped!#\n"); + }else{ + strcat(txt_buf, "#FFDD00 All partitions will also be wiped!#\n"); + } + } + strcat(txt_buf, "#FFDD00 Use USB UMS to copy them over!#"); + } + + lv_label_set_text(lbl_status, txt_buf); + + if ((part_info.backup_possible && part_info.hos_size) || part_info.skip_backup) + lv_mbox_add_btns(mbox, mbox_btn_map2, _create_mbox_partitioning_option1); + else + lv_mbox_add_btns(mbox, part_info.drive == DRIVE_SD ? mbox_btn_map : mbox_btn_map3, _create_mbox_partitioning_option0); lv_obj_align(mbox, NULL, LV_ALIGN_CENTER, 0, 0); lv_obj_set_top(mbox, true); @@ -2159,12 +2315,12 @@ static lv_res_t _create_mbox_partitioning_android(lv_obj_t *btns, const char *tx mbox_action(btns, txt); part_info.and_dynamic = !btn_idx; - _create_mbox_partitioning_warn(); + _create_mbox_partitioning_warn(NULL); return LV_RES_INV; } -static lv_res_t _create_mbox_partitioning_andr_part() +static lv_res_t _create_mbox_partitioning_andr_part(lv_obj_t *btn) { lv_obj_t *dark_bg = lv_obj_create(lv_scr_act(), NULL); lv_obj_set_style(dark_bg, &mbox_darken); @@ -2194,9 +2350,9 @@ static lv_res_t _create_mbox_partitioning_andr_part() static lv_res_t _create_mbox_partitioning_next(lv_obj_t *btn) { if (part_info.and_size) - return _create_mbox_partitioning_andr_part(); + return _create_mbox_partitioning_andr_part(NULL); else - return _create_mbox_partitioning_warn(); + return _create_mbox_partitioning_warn(NULL); } static void _update_partition_bar() @@ -2204,142 +2360,243 @@ static void _update_partition_bar() lv_obj_t *h1 = lv_obj_get_parent(part_info.bar_hos); // Set widths based on max bar width. - u32 total_size = (part_info.total_sct - AU_ALIGN_SECTORS) / SECTORS_PER_GB; - u32 bar_hos_size = lv_obj_get_width(h1) * (part_info.hos_size >> 10) / total_size; - u32 bar_emu_size = lv_obj_get_width(h1) * (part_info.emu_size >> 10) / total_size; - u32 bar_l4t_size = lv_obj_get_width(h1) * (part_info.l4t_size >> 10) / total_size; - u32 bar_and_size = lv_obj_get_width(h1) * (part_info.and_size >> 10) / total_size; + lv_coord_t w = lv_obj_get_width(h1); + + // account for alignment + 1mb for backup gpt + u32 total_size = part_info.total_sct_available / SECTORS_PER_GB; + + u32 bar_hos_size = w * (part_info.hos_size >> 10) / total_size; + u32 bar_emu_size = w * (part_info.emu_size >> 10) / total_size; + u32 bar_l4t_size = w * (part_info.l4t_size >> 10) / total_size; + u32 bar_and_size = w * (part_info.and_size >> 10) / total_size; + u32 bar_hos_os_size = w * (part_info.hos_os_size >> 10) / total_size; + + u32 bar_remaining_size = w - (bar_hos_size + bar_emu_size + bar_l4t_size + bar_and_size + bar_hos_os_size); + bar_remaining_size = bar_remaining_size <= 7 ? 0 : bar_remaining_size; // Update bar widths. - lv_obj_set_width(part_info.bar_hos, bar_hos_size); - lv_obj_set_width(part_info.bar_emu, bar_emu_size); - lv_obj_set_width(part_info.bar_l4t, bar_l4t_size); - lv_obj_set_width(part_info.bar_and, bar_and_size); + lv_obj_set_size(part_info.bar_hos, bar_hos_size, LV_DPI / 2); + lv_obj_set_size(part_info.bar_emu, bar_emu_size, LV_DPI / 2); + lv_obj_set_size(part_info.bar_l4t, bar_l4t_size, LV_DPI / 2); + lv_obj_set_size(part_info.bar_and, bar_and_size, LV_DPI / 2); + lv_obj_set_size(part_info.bar_hos_os, bar_hos_os_size, LV_DPI / 2); + lv_obj_set_size(part_info.bar_remaining, bar_remaining_size, LV_DPI / 2); // Re-align bars. - lv_obj_realign(part_info.bar_emu); - lv_obj_realign(part_info.bar_l4t); - lv_obj_realign(part_info.bar_and); + lv_obj_align(part_info.bar_hos, part_info.bar_hos_os, LV_ALIGN_OUT_RIGHT_MID, 0, 0); + lv_obj_align(part_info.bar_emu, part_info.bar_hos, LV_ALIGN_OUT_RIGHT_MID, 0, 0); + lv_obj_align(part_info.bar_l4t, part_info.bar_emu, LV_ALIGN_OUT_RIGHT_MID, 0, 0); + lv_obj_align(part_info.bar_and, part_info.bar_l4t, LV_ALIGN_OUT_RIGHT_MID, 0, 0); + lv_obj_align(part_info.bar_remaining, part_info.bar_and, LV_ALIGN_OUT_RIGHT_MID, 0, 0); + + // Set HOS OS blending separator sizes and realign. + lv_obj_set_size(part_info.sep_hos_os, bar_hos_os_size && (bar_remaining_size || bar_hos_size || bar_and_size || bar_l4t_size || bar_emu_size) ? 8 : 0, LV_DPI / 2); + lv_obj_align(part_info.sep_hos_os, part_info.bar_hos_os, LV_ALIGN_OUT_RIGHT_MID, -4, 0); + + // Set hos separator + lv_obj_set_size(part_info.sep_hos, bar_hos_size && (bar_remaining_size || bar_and_size || bar_l4t_size || bar_emu_size) ? 8 : 0, LV_DPI / 2); + lv_obj_align(part_info.sep_hos, part_info.bar_hos, LV_ALIGN_OUT_RIGHT_MID, -4, 0); // Set emuMMC blending separator sizes and realign. - lv_obj_set_width(part_info.sep_emu, bar_emu_size ? 8 : 0); - lv_obj_realign(part_info.sep_emu); + lv_obj_set_size(part_info.sep_emu, bar_emu_size && (bar_remaining_size || bar_and_size || bar_l4t_size) ? 8 : 0, LV_DPI / 2); + lv_obj_align(part_info.sep_emu, part_info.bar_emu, LV_ALIGN_OUT_RIGHT_MID, -4, 0); // Set L4T blending separator sizes and realign. - lv_obj_set_width(part_info.sep_l4t, bar_l4t_size ? 8 : 0); - lv_obj_realign(part_info.sep_l4t); + lv_obj_set_size(part_info.sep_l4t, bar_l4t_size && (bar_remaining_size || bar_and_size) ? 8 : 0, LV_DPI / 2); + lv_obj_align(part_info.sep_l4t, part_info.bar_l4t, LV_ALIGN_OUT_RIGHT_MID, -4, 0); // Set Android blending separator sizes and realign. - lv_obj_set_width(part_info.sep_and, bar_and_size ? 8 : 0); - lv_obj_realign(part_info.sep_and); + lv_obj_set_size(part_info.sep_and, bar_and_size && bar_remaining_size ? 8 : 0, LV_DPI / 2); + lv_obj_align(part_info.sep_and, part_info.bar_and, LV_ALIGN_OUT_RIGHT_MID, -4, 0); +} - // Re-align size labels. - lv_obj_realign(part_info.lbl_hos); - lv_obj_realign(part_info.lbl_emu); - lv_obj_realign(part_info.lbl_l4t); - lv_obj_realign(part_info.lbl_and); - lv_obj_align(part_info.cont_lbl, part_info.bar_hos, LV_ALIGN_OUT_BOTTOM_LEFT, LV_DPI * 11 - LV_DPI / 2, LV_DPI * 9 / 23); +static lv_res_t _action_slider_hos(lv_obj_t *slider){ + char lbl_text[64]; + + u32 size = (u32)lv_slider_get_value(slider) << 10; + + if(size < (u32)part_info.hos_min_size_mb / 2){ + size = 0; + }else if(size < (u32)part_info.hos_min_size_mb){ + size = part_info.hos_min_size_mb; + } + + part_info.auto_assign_free_storage = size != 0; + + if(size){ + // account for alignment and 1mb for backup gpt + size = (part_info.total_sct_available >> 11) - part_info.and_size - part_info.emu_size - part_info.hos_os_size - part_info.l4t_size - part_info.emu_sd_size; + } + + part_info.hos_size = size; + lv_slider_set_value(slider, size >> 10); + + + s_printf(lbl_text, "#96FF00 %d GiB#", size >> 10); + lv_label_set_text(part_info.lbl_hos, lbl_text); + + _update_partition_bar(); + + return LV_RES_OK; +} + +static lv_res_t _action_slider_hos_os(lv_obj_t *slider){ + char lbl_text[64]; + + u32 user_size = (u32)lv_slider_get_value(slider) << 10; + u32 user_size_og = part_info.hos_os_og_size - part_info.hos_sys_size_mb; + + // min. 4Gb for HOS USER + if (user_size < 2048) + user_size = 0; + else if (user_size < 4096) + user_size = 4096; + else if(user_size >= user_size_og - 3072 && user_size <= user_size_og + 3072){ + user_size = user_size_og; + } + + u32 hos_os_size = user_size ? (user_size + part_info.hos_sys_size_mb) : 0; + + u32 align = ALIGN(hos_os_size, AU_ALIGN_SECTORS >> 11) - hos_os_size; + hos_os_size += align; + + s32 hos_size = (part_info.total_sct_available >> 11) - part_info.emu_size - part_info.l4t_size - part_info.and_size - hos_os_size - part_info.emu_sd_size; + + // Sanitize sizes based on new HOS OS size. + if(!part_info.auto_assign_free_storage){ + u32 total = part_info.and_size + part_info.hos_size + part_info.emu_size + part_info.l4t_size + hos_os_size + part_info.emu_sd_size; + if(total > part_info.total_sct_available >> 11){ + hos_os_size = (part_info.total_sct_available >> 11) - part_info.l4t_size - part_info.and_size - part_info.emu_size - part_info.hos_size - part_info.emu_sd_size; + // other partitions and size are aligned + align = 0; + user_size = hos_os_size - part_info.hos_sys_size_mb; + lv_slider_set_value(slider, (hos_os_size - part_info.hos_sys_size_mb) >> 10); + } + }else if (hos_size > part_info.hos_min_size_mb) + { + if (user_size <= 4096) + lv_slider_set_value(slider, user_size >> 10); + } + else + { + hos_os_size = (part_info.total_sct_available >> 11) - part_info.emu_size - part_info.l4t_size - part_info.and_size - part_info.hos_min_size_mb - part_info.emu_sd_size; + hos_size = (part_info.total_sct_available >> 11) - part_info.emu_size - part_info.l4t_size - part_info.and_size - hos_os_size - part_info.emu_sd_size; + align = 0; + if (hos_size < part_info.hos_min_size_mb || hos_os_size < part_info.hos_sys_size_mb + 4096) + { + lv_slider_set_value(slider, (part_info.hos_os_size - part_info.hos_sys_size_mb) >> 10); + goto out; + } + user_size = hos_os_size - part_info.hos_sys_size_mb; + lv_slider_set_value(slider, user_size >> 10); + } + + part_info.hos_os_size = hos_os_size; + part_info.hos_os_align = align; + + if(part_info.auto_assign_free_storage){ + part_info.hos_size = hos_size; + s_printf(lbl_text, "#96FF00 %d GiB#", hos_size >> 10); + lv_label_set_text(part_info.lbl_hos, lbl_text); + lv_bar_set_value(part_info.slider_bar_hos, hos_size >> 10); + } + + if(user_size == user_size_og){ + s_printf(lbl_text, "#FFD300 %d FULL#", user_size >> 10); + }else{ + s_printf(lbl_text, "#FFD300 %d GiB#", user_size >> 10); + } + lv_label_set_text(part_info.lbl_hos_os, lbl_text); + + _update_partition_bar(); + +out: + return LV_RES_OK; } static lv_res_t _action_slider_emu(lv_obj_t *slider) { + #define EMUMMC_32GB_FULL 29856 + #define EMUMMC_64GB_FULL 59664 + + static const u32 rsvd_mb = 4 + 4 + 16 + 8; // BOOT0 + BOOT1 + 16MB protective offset + 8MB alignment. + u32 max_emmc_size = !part_info.emmc_is_64gb ? EMUMMC_32GB_FULL : EMUMMC_64GB_FULL; + u32 size; char lbl_text[64]; - bool prev_emu_double = part_info.emu_double; int slide_val = lv_slider_get_value(slider); - u32 max_emmc_size = !part_info.emmc_is_64gb ? EMU_32GB_FULL : EMU_64GB_FULL; - part_info.emu_double = false; + int max_slider = lv_slider_get_max_value(slider); - // Check that eMMC exists. - if (!part_info.emmc_size_mb) - { - lv_slider_set_value(slider, 0); - return LV_RES_OK; - } + size = slide_val > (max_slider / 2) ? slide_val - (max_slider / 2) : slide_val; + size <<= 10; - // In case of upgraded eMMC, do not allow FULL sizes. Max size is always bigger than official eMMCs. - if (max_emmc_size < part_info.emmc_size_mb) - { - if (slide_val == EMU_SLIDER_1X_FULL) - { - if (prev_emu_double) - slide_val--; - else - slide_val++; - lv_slider_set_value(slider, slide_val); - } - else if (slide_val == EMU_SLIDER_2X_FULL) - { - slide_val--; - lv_slider_set_value(slider, slide_val); - } - } + bool is_full = false; - size = (slide_val > EMU_SLIDER_1X_MAX ? (slide_val - EMU_SLIDER_1X_MAX) : slide_val) + EMU_SLIDER_OFFSET; - size *= 1024; // Convert to GB. - size += EMU_RSVD_MB; // Add reserved size. - - if (slide_val == EMU_SLIDER_MIN) - size = 0; // Reset if 0. - else if (slide_val >= EMU_SLIDER_2X_MIN) - { - size *= 2; - part_info.emu_double = true; - } - - // Handle special cases. 2nd value is for 64GB Aula. Values already include reserved space. - if (slide_val == EMU_SLIDER_1X_FULL) + // min 4Gb for emuMMC + if(size < 4096 / 2){ + size = 0; + }else if(size < 4096){ + size = 4096; + }else if(size <= max_emmc_size + 3072 && size >= max_emmc_size - 3072){ size = max_emmc_size; - else if (slide_val == EMU_SLIDER_2X_FULL) - size = 2 * max_emmc_size; + is_full = true; + } + + bool emu_double = slide_val > max_slider / 2 && size; + + if(size){ + size += rsvd_mb; // Add reserved size. + } + + if(emu_double){ + size *= 2; + } // Sanitize sizes based on new HOS size. - s32 hos_size = (part_info.total_sct >> 11) - 16 - size - part_info.l4t_size - part_info.and_size; - if (hos_size > part_info.hos_min_size) + s32 hos_size = (part_info.total_sct_available >> 11) - size - part_info.emu_sd_size - part_info.l4t_size - part_info.and_size - part_info.hos_os_size; + u32 total = part_info.l4t_size + part_info.and_size + part_info.hos_size + part_info.hos_os_size + part_info.emu_sd_size + size; + + if ((part_info.auto_assign_free_storage && hos_size > part_info.hos_min_size_mb) || (!part_info.auto_assign_free_storage && total <= part_info.total_sct_available >> 11)) { part_info.emu_size = size; - part_info.hos_size = hos_size; + part_info.emu_double = emu_double; - s_printf(lbl_text, "#96FF00 %4d GiB#", hos_size >> 10); - lv_label_set_text(part_info.lbl_hos, lbl_text); - lv_bar_set_value(part_info.slider_bar_hos, hos_size >> 10); - - if (!part_info.emu_double) - { - if (slide_val != EMU_SLIDER_1X_FULL) - s_printf(lbl_text, "#FF3C28 %4d GiB#", size >> 10); - else - s_printf(lbl_text, "#FF3C28 %d FULL#", size >> 10); + u32 temp_size = emu_double ? size / 2 : size; + // set slider value again manually if in the snapping region + if(temp_size <= 4096){ + u32 new_val = part_info.emu_double ? ((max_slider << 10) + part_info.emu_size) / 2 : part_info.emu_size; + lv_slider_set_value(slider, new_val >> 10); + } + + if(part_info.auto_assign_free_storage){ + part_info.hos_size = hos_size; + s_printf(lbl_text, "#96FF00 %d GiB#", hos_size >> 10); + lv_label_set_text(part_info.lbl_hos, lbl_text); + lv_bar_set_value(part_info.slider_bar_hos, hos_size >> 10); + } + + if (!emu_double) + { + if(is_full){ + s_printf(lbl_text, "#FF3C28 %d FULL#", size >> 10); + }else{ + s_printf(lbl_text, "#FF3C28 %d GiB#", size >> 10); + } + }else{ + if(is_full){ + s_printf(lbl_text, "#FFDD00 2x##FF3C28 %d FULL#", size >> 11); + }else{ + s_printf(lbl_text, "#FFDD00 2x##FF3C28 %d GiB#", size >> 11); + } } - else - s_printf(lbl_text, "#FFDD00 2x##FF3C28 %d GiB#", size >> 11); lv_label_set_text(part_info.lbl_emu, lbl_text); } else { - u32 emu_size = part_info.emu_size; - - if (emu_size == max_emmc_size) - emu_size = EMU_SLIDER_1X_FULL; - else if (emu_size == 2 * max_emmc_size) - emu_size = EMU_SLIDER_2X_FULL; - else if (emu_size) - { - if (prev_emu_double) - emu_size /= 2; - emu_size -= EMU_RSVD_MB; - emu_size /= 1024; - emu_size -= EMU_SLIDER_OFFSET; - - if (prev_emu_double) - emu_size += EMU_SLIDER_2X_MIN; - } - - int new_slider_val = emu_size; - part_info.emu_double = prev_emu_double ? true : false; - - lv_slider_set_value(slider, new_slider_val); + // reset slider to old value + u32 old_val = part_info.emu_double ? ((max_slider << 10) + part_info.emu_size) / 2 : part_info.emu_size; + lv_slider_set_value(slider, old_val >> 10); } _update_partition_bar(); @@ -2357,19 +2614,25 @@ static lv_res_t _action_slider_l4t(lv_obj_t *slider) else if (size < 8192) size = 8192; - s32 hos_size = (part_info.total_sct >> 11) - 16 - part_info.emu_size - size - part_info.and_size; + s32 hos_size = (part_info.total_sct_available >> 11) - part_info.hos_os_size - part_info.emu_size - size - part_info.and_size - part_info.emu_sd_size; // Sanitize sizes based on new HOS size. - if (hos_size > part_info.hos_min_size) + if(!part_info.auto_assign_free_storage){ + u32 total = part_info.and_size + part_info.hos_os_size + part_info.emu_size + part_info.hos_size + size + part_info.emu_sd_size; + if(total > part_info.total_sct_available >> 11){ + size = (part_info.total_sct_available >> 11) - part_info.hos_os_size - part_info.and_size - part_info.emu_size - part_info.hos_size - part_info.emu_sd_size; + lv_slider_set_value(slider, size >> 10); + } + }else if (hos_size > part_info.hos_min_size_mb) { if (size <= 8192) lv_slider_set_value(slider, size >> 10); } else { - size = (part_info.total_sct >> 11) - 16 - part_info.emu_size - part_info.and_size - 2048; - hos_size = (part_info.total_sct >> 11) - 16 - part_info.emu_size - part_info.and_size - size; - if (hos_size < part_info.hos_min_size || size < 8192) + size = (part_info.total_sct_available >> 11) - part_info.emu_size - part_info.hos_os_size - part_info.and_size - part_info.emu_sd_size - 2048; + hos_size = (part_info.total_sct_available >> 11) - part_info.emu_size - part_info.hos_os_size - part_info.and_size - size - part_info.emu_sd_size; + if (hos_size < part_info.hos_min_size_mb || size < 8192) { lv_slider_set_value(slider, part_info.l4t_size >> 10); goto out; @@ -2377,13 +2640,16 @@ static lv_res_t _action_slider_l4t(lv_obj_t *slider) lv_slider_set_value(slider, size >> 10); } - part_info.l4t_size = size; - part_info.hos_size = hos_size; + if(part_info.auto_assign_free_storage){ + part_info.hos_size = hos_size; + s_printf(lbl_text, "#96FF00 %d GiB#", hos_size >> 10); + lv_label_set_text(part_info.lbl_hos, lbl_text); + lv_bar_set_value(part_info.slider_bar_hos, hos_size >> 10); + } - s_printf(lbl_text, "#96FF00 %4d GiB#", hos_size >> 10); - lv_label_set_text(part_info.lbl_hos, lbl_text); - lv_bar_set_value(part_info.slider_bar_hos, hos_size >> 10); - s_printf(lbl_text, "#00DDFF %4d GiB#", size >> 10); + part_info.l4t_size = size; + + s_printf(lbl_text, "#00DDFF %d GiB#", size >> 10); lv_label_set_text(part_info.lbl_l4t, lbl_text); _update_partition_bar(); @@ -2394,48 +2660,80 @@ out: static lv_res_t _action_slider_and(lv_obj_t *slider) { + u32 user_size; + u32 and_size; char lbl_text[64]; + int slide_val = lv_slider_get_value(slider); - u32 user_size = (u32)lv_slider_get_value(slider) << 10; - if (user_size < 2048) + int max_slider = lv_slider_get_max_value(slider); + + #ifdef ENABLE_DUAL_ANDROID + user_size = slide_val > (max_slider / 2) ? slide_val - (max_slider / 2) : slide_val; + #else + user_size = slide_val; + #endif + user_size <<= 10; + + if(user_size < 4096 / 2){ user_size = 0; - else if (user_size < 4096) + }else if(user_size < 4096){ user_size = 4096; + } - u32 and_size = user_size ? (user_size + AND_SYS_SIZE_MB) : 0; - s32 hos_size = (part_info.total_sct >> 11) - 16 - part_info.emu_size - part_info.l4t_size - and_size; + #ifdef ENABLE_DUAL_ANDROID + bool and_double = slide_val > max_slider / 2 && user_size; + #else + bool and_double = false; + #endif + + and_size = 0; + if(user_size){ + and_size = user_size + ANDROID_SYSTEM_SIZE_MB; + } + + if(and_double){ + and_size *= 2; + }; // Sanitize sizes based on new HOS size. - if (hos_size > part_info.hos_min_size) + s32 hos_size = (part_info.total_sct_available >> 11) - and_size - part_info.hos_os_size - part_info.emu_size- part_info.l4t_size - part_info.emu_sd_size ; + u32 total = part_info.l4t_size + part_info.emu_sd_size + part_info.hos_size + part_info.hos_os_size + part_info.emu_size + and_size; + + if ((part_info.auto_assign_free_storage && hos_size > part_info.hos_min_size_mb) || (!part_info.auto_assign_free_storage && total <= part_info.total_sct_available >> 11)) { - if (user_size <= 4096) - lv_slider_set_value(slider, user_size >> 10); + part_info.and_size = and_size; + part_info.and_double = and_double; + + if(user_size <= 4096){ + u32 new_val = part_info.and_double ? (max_slider << 10) / 2 + user_size : user_size; + lv_slider_set_value(slider, new_val >> 10); + } + + if(part_info.auto_assign_free_storage){ + part_info.hos_size = hos_size; + s_printf(lbl_text, "#96FF00 %d GiB#", hos_size >> 10); + lv_label_set_text(part_info.lbl_hos, lbl_text); + lv_bar_set_value(part_info.slider_bar_hos, hos_size >> 10); + } + + if (!and_double) + { + s_printf(lbl_text, "#FF8000 %d GiB#", user_size >> 10); + }else{ + s_printf(lbl_text, "#FFDD00 2x##FF8000 %d GiB#", user_size >> 10); + } + lv_label_set_text(part_info.lbl_and, lbl_text); } else { - and_size = (part_info.total_sct >> 11) - 16 - part_info.emu_size - part_info.l4t_size - 2048; - hos_size = (part_info.total_sct >> 11) - 16 - part_info.emu_size - part_info.l4t_size - and_size; - if (hos_size < part_info.hos_min_size || and_size < 8192) - { - lv_slider_set_value(slider, part_info.and_size >> 10); - goto out; - } - user_size = and_size - AND_SYS_SIZE_MB; - lv_slider_set_value(slider, user_size >> 10); + // reset slider to old value + u32 old_val = part_info.and_double ? ((max_slider << 10) + part_info.and_size) / 2 : part_info.and_size; + old_val -= ANDROID_SYSTEM_SIZE_MB; + lv_slider_set_value(slider, old_val >> 10); } - part_info.and_size = and_size; - part_info.hos_size = hos_size; - - s_printf(lbl_text, "#96FF00 %4d GiB#", hos_size >> 10); - lv_label_set_text(part_info.lbl_hos, lbl_text); - lv_bar_set_value(part_info.slider_bar_hos, hos_size >> 10); - s_printf(lbl_text, "#FF8000 %4d GiB#", user_size >> 10); - lv_label_set_text(part_info.lbl_and, lbl_text); - _update_partition_bar(); -out: return LV_RES_OK; } @@ -2450,10 +2748,10 @@ static lv_res_t _mbox_check_files_total_size_option(lv_obj_t *btns, const char * return LV_RES_INV; } -static void _create_mbox_check_files_total_size() +static void _create_mbox_check_files_total_size(u8 drive) { - static lv_style_t bar_hos_ind, bar_emu_ind, bar_l4t_ind, bar_and_ind; - static lv_style_t sep_emu_bg, sep_l4t_bg, sep_and_bg; + static lv_style_t bar_hos_os_ind, bar_hos_ind, bar_emu_ind, bar_l4t_ind, bar_and_ind, bar_emu_sd_ind, bar_remaining_ind; + static lv_style_t sep_hos_os_bg, sep_hos_bg, sep_emu_bg, sep_l4t_bg, sep_emu_sd_bg, sep_and_bg; // Set HOS bar style. lv_style_copy(&bar_hos_ind, lv_theme_get_current()->bar.indic); @@ -2470,22 +2768,51 @@ static void _create_mbox_check_files_total_size() bar_l4t_ind.body.main_color = LV_COLOR_HEX(0x00DDFF); bar_l4t_ind.body.grad_color = bar_l4t_ind.body.main_color; - // Set GPT bar style. + // Set Android bar style. lv_style_copy(&bar_and_ind, lv_theme_get_current()->bar.indic); - bar_and_ind.body.main_color = LV_COLOR_HEX(0xC000FF); + bar_and_ind.body.main_color = LV_COLOR_HEX(0xff8000); bar_and_ind.body.grad_color = bar_and_ind.body.main_color; + // Set HOS OS bar style. + lv_style_copy(&bar_hos_os_ind, lv_theme_get_current()->bar.indic); + bar_hos_os_ind.body.main_color = LV_COLOR_HEX(0xffd300); + bar_hos_os_ind.body.grad_color = bar_hos_os_ind.body.main_color; + + // Set Remaining bar style. + lv_style_copy(&bar_remaining_ind, lv_theme_get_current()->bar.indic); + bar_remaining_ind.body.main_color = LV_COLOR_HEX(0xc9c9c9); + bar_remaining_ind.body.grad_color = bar_remaining_ind.body.main_color; + + // Set emu sd bar style. + lv_style_copy(&bar_emu_sd_ind, lv_theme_get_current()->bar.indic); + bar_emu_sd_ind.body.main_color = LV_COLOR_HEX(0xff00d6); + bar_emu_sd_ind.body.grad_color = bar_emu_sd_ind.body.main_color; + // Set separator styles. - lv_style_copy(&sep_emu_bg, lv_theme_get_current()->cont); + lv_style_copy(&sep_hos_os_bg, lv_theme_get_current()->cont); + sep_hos_os_bg.body.main_color = LV_COLOR_HEX(0xffd300); + sep_hos_os_bg.body.grad_color = sep_hos_os_bg.body.main_color; + sep_hos_os_bg.body.radius = 0; + + lv_style_copy(&sep_hos_bg, &sep_hos_os_bg); + sep_hos_bg.body.main_color = LV_COLOR_HEX(0x96FF00); + sep_hos_bg.body.grad_color = sep_hos_bg.body.main_color; + + lv_style_copy(&sep_and_bg, &sep_hos_os_bg); + sep_and_bg.body.main_color = LV_COLOR_HEX(0xff8000); + sep_and_bg.body.grad_color = sep_and_bg.body.main_color; + + lv_style_copy(&sep_emu_bg, &sep_hos_os_bg); sep_emu_bg.body.main_color = LV_COLOR_HEX(0xFF3C28); sep_emu_bg.body.grad_color = sep_emu_bg.body.main_color; - sep_emu_bg.body.radius = 0; - lv_style_copy(&sep_l4t_bg, &sep_emu_bg); + + lv_style_copy(&sep_l4t_bg, &sep_hos_os_bg); sep_l4t_bg.body.main_color = LV_COLOR_HEX(0x00DDFF); sep_l4t_bg.body.grad_color = sep_l4t_bg.body.main_color; - lv_style_copy(&sep_and_bg, &sep_emu_bg); - sep_and_bg.body.main_color = LV_COLOR_HEX(0xC000FF); - sep_and_bg.body.grad_color = sep_and_bg.body.main_color; + + lv_style_copy(&sep_emu_sd_bg, &sep_hos_os_bg); + sep_emu_sd_bg.body.main_color = LV_COLOR_HEX(0xff00d6); + sep_emu_sd_bg.body.grad_color = sep_emu_sd_bg.body.main_color; char *txt_buf = malloc(SZ_8K); @@ -2499,7 +2826,7 @@ static void _create_mbox_check_files_total_size() lv_mbox_set_recolor_text(mbox, true); lv_obj_set_width(mbox, LV_HOR_RES / 9 * 6); - lv_mbox_set_text(mbox, "Analyzing SD card usage. This might take a while..."); + lv_mbox_set_text(mbox, drive == DRIVE_SD ? "Analyzing SD card usage. This might take a while..." : "Analyzing eMMC usage. This might take a while..."); lv_obj_align(mbox, NULL, LV_ALIGN_CENTER, 0, 0); lv_obj_set_top(mbox, true); @@ -2510,26 +2837,85 @@ static void _create_mbox_check_files_total_size() u32 total_size = 0; path[0] = 0; - // Check total size of files. - int res = _stat_and_copy_files("sd:", NULL, path, &total_files, &total_size, NULL); + mbr_t *mbr = zalloc(sizeof(*mbr)); + gpt_t *gpt = NULL; + bool has_gpt = false; + bool has_hos_data = false; - // Not more than 1.2GB. - part_info.backup_possible = !res && !(total_size > (RAM_DISK_SZ - SZ_16M)); // Account for alignment. + sdmmc_storage_t *storage = drive == DRIVE_SD ? &sd_storage : &emmc_storage; + + // Read current MBR. + sdmmc_storage_read(storage, 0, 1, mbr); + + // check if we have gpt + has_gpt = _has_gpt(mbr); + + if(has_gpt){ + // Calculate GPT part size. + gpt = zalloc(sizeof(*gpt)); + sdmmc_storage_read(storage, 1, sizeof(*gpt) >> 9, gpt); + } + + if(has_gpt){ + if(_get_gpt_part_by_name(gpt, "hos_data", -1) != -1){ + gfx_printf("yes hos data\n"); + has_hos_data = true; + } + } + + int res; + if(part_info.drive == DRIVE_EMMC && !has_hos_data){ + gfx_printf("emmc !hos data\n"); + // if we are on emmc, and dont have a partition named hos_data, dont even check files + // we might find an emusd fat32 partition instead + part_info.skip_backup = true; + res = FR_NO_FILESYSTEM; + }else{ + // Check total size of files. + res = _stat_and_copy_files(drive == DRIVE_SD ? "sd:" : "emmc:", NULL, path, &total_files, &total_size, NULL); + } + + gfx_printf("stat res %d\n", res); + + + if(res == FR_NO_FILESYSTEM){ + // no fat system on selected storage, nothing to backup + part_info.skip_backup = true; + } + + // Not more than 1.0GB. + part_info.backup_possible = !res && !(total_size > (RAM_DISK_SZ - SZ_16M)); if (part_info.backup_possible) { s_printf(txt_buf, - "#96FF00 The SD Card files will be backed up automatically!#\n" - "#FFDD00 Any other partition will be wiped!#\n" - "#00DDFF Total files:# %d, #00DDFF Total size:# %d MiB", total_files, total_size >> 20); + "#96FF00 The %s files will be backed up automatically!#\n" + "#FFDD00 Any other partitions %swill be wiped!#\n" + "#00DDFF Total files:# %d, #00DDFF Total size:# %d MiB", + drive == DRIVE_SD ? "SD card" : "eMMC", + drive == DRIVE_SD ? "" : "(except HOS ones) ", + total_files, + total_size >> 20); lv_mbox_set_text(mbox, txt_buf); } else { - lv_mbox_set_text(mbox, - "#FFDD00 The SD Card cannot be backed up automatically!#\n" - "#FFDD00 Any other partition will be also wiped!#\n\n" - "You will be asked to back up your files later via UMS."); + if(res == FR_NO_FILESYSTEM){ + // cant backup files because no filesystem + s_printf(txt_buf, + "#96FF00 No %s files to be backed up!#\n" + "#FFDD00 Any other partitions %swill be wiped!#\n", + drive == DRIVE_SD ? "SD card" : "eMMC", drive == DRIVE_SD ? "" : "(except HOS ones) "); + }else{ + // cant backup for some other reason + s_printf(txt_buf, + "#FFDD00 The %s files cannot be backed up automatically!#\n" + "#FFDD00 Any other partitions %swill be wiped!#\n\n" + "You will be asked to back up your files later via UMS.", + drive == DRIVE_SD ? "SD card" : "eMMC", + drive == DRIVE_SD ? "" : "(except HOS ones) "); + } + lv_mbox_set_text(mbox, txt_buf); } // Create container to keep content inside. @@ -2538,90 +2924,194 @@ static void _create_mbox_check_files_total_size() lv_cont_set_style(h1, &lv_style_transp_tight); lv_obj_set_width(h1, lv_obj_get_width(mbox) - LV_DPI * 3); + + total_size = storage->sec_cnt; + + u32 bar_hos_size = 0; + u32 bar_emu_size = 0; + u32 bar_l4t_size = 0; + u32 bar_and_size = 0; + u32 bar_hos_os_size = 0; + u32 bar_remaining_size = 0; + + lv_obj_t *lbl_part = lv_label_create(h1, NULL); lv_label_set_recolor(lbl_part, true); - lv_label_set_text(lbl_part, "#00DDFF Current MBR partition layout:#"); + s_printf(txt_buf, "#00DDFF Current %s partition layout:#", has_gpt ? "GPT" : "MBR"); + lv_label_set_text(lbl_part, txt_buf); + + if(!has_gpt){ + // Calculate MBR partitions size. + bar_hos_size = mbr->partitions[0].size_sct; + for (u32 i = 1; i < 4; i++) + if (mbr->partitions[i].type == 0xE0) + bar_emu_size += mbr->partitions[i].size_sct; - // Read current MBR. - mbr_t mbr = { 0 }; - sdmmc_storage_read(&sd_storage, 0, 1, &mbr); + for (u32 i = 1; i < 4; i++) + if (mbr->partitions[i].type == 0x83) + bar_l4t_size += mbr->partitions[i].size_sct; + }else{ + u32 i = 0; + if(!memcmp(gpt->entries[10].name, (char[]){'U', 0, 'S', 0, 'E', 0, 'R', 0}, 8)){ + bar_hos_os_size += gpt->entries[10].lba_end - gpt->entries[0].lba_start + 1; + i = 11; + } - // Calculate MBR partitions size. - total_size = (sd_storage.sec_cnt - AU_ALIGN_SECTORS) / SECTORS_PER_GB; - u32 bar_hos_size = lv_obj_get_width(h1) * (mbr.partitions[0].size_sct / SECTORS_PER_GB) / total_size; - u32 bar_emu_size = 0; - for (u32 i = 1; i < 4; i++) - if (mbr.partitions[i].type == 0xE0) - bar_emu_size += mbr.partitions[i].size_sct; - bar_emu_size = lv_obj_get_width(h1) * (bar_emu_size / SECTORS_PER_GB) / total_size; + for(; i < gpt->header.num_part_ents && i < 128; i++){ + gpt_entry_t *entry = &gpt->entries[i]; - u32 bar_l4t_size = 0; - for (u32 i = 1; i < 4; i++) - if (mbr.partitions[i].type == 0x83) - bar_l4t_size += mbr.partitions[i].size_sct; - bar_l4t_size = lv_obj_get_width(h1) * (bar_l4t_size / SECTORS_PER_GB) / total_size; + if(!memcmp(entry->name, (char[]){ 'e', 0, 'm', 0, 'u', 0, 'm', 0, 'm', 0, 'c', 0 }, 12)){ + bar_emu_size += entry->lba_end - entry->lba_start + 1; + } - u32 bar_and_size = lv_obj_get_width(h1) - bar_hos_size - bar_emu_size - bar_l4t_size; + if(!memcmp(entry->name, (char[]){ 'b', 0, 'o', 0, 'o', 0, 't', 0 }, 8)){ + if((i + 6) < gpt->header.num_part_ents && (i + 6) < 128){ + if(!memcmp(gpt->entries[i + 6].name, (char[]){ 'u', 0, 's', 0, 'e', 0, 'r', 0, 'd', 0, 'a', 0, 't', 0, 'a', 0 }, 16)){ + // found android dynamic + bar_and_size += gpt->entries[i + 6].lba_end - gpt->entries[i].lba_start + 1; + i += 6; + } + } + } + + if(!memcmp(entry->name, (char[]){ 'v', 0, 'e', 0, 'n', 0, 'd', 0, 'o', 0, 'r', 0 }, 12)){ + if(i + 8 < gpt->header.num_part_ents && i + 8 < 128){ + if(!memcmp(gpt->entries[i + 8].name, (char[]){ 'U', 0, 'D', 0, 'A', 0 }, 6)){ + // found android regular + bar_and_size += gpt->entries[i + 8].lba_end - gpt->entries[i].lba_start + 1; + i += 8; + } + } + } + + if(!memcmp(entry->name, (char[]){ 'l', 0, '4', 0, 't', 0 }, 6)){ + bar_l4t_size += entry->lba_end - entry->lba_start + 1; + } + + if(!memcmp(entry->name, (char[]){ 'h', 0, 'o', 0, 's', 0, '_', 0, 'd', 0, 'a', 0, 't', 0, 'a', 0 }, 16)){ + bar_hos_size += entry->lba_end - entry->lba_start + 1; + } + + } + } + + // bar_remaining_size = total_size - (bar_l4t_size + bar_and_size + bar_hos_os_size + bar_hos_size + bar_emu_size + bar_emu_sd_size); + + const u32 total_size_gb = total_size / SECTORS_PER_GB; + lv_coord_t w = lv_obj_get_width(h1); + bar_l4t_size = w * (bar_l4t_size / SECTORS_PER_GB) / total_size_gb; + bar_and_size = w * (bar_and_size / SECTORS_PER_GB) / total_size_gb; + bar_hos_os_size = w * (bar_hos_os_size / SECTORS_PER_GB) / total_size_gb; + bar_hos_size = w * (bar_hos_size / SECTORS_PER_GB) / total_size_gb; + bar_emu_size = w * (bar_emu_size / SECTORS_PER_GB) / total_size_gb; + // bar_remaining_size = w * (bar_remaining_size / SECTORS_PER_GB) / (total_size / SECTORS_PER_GB); + bar_remaining_size = w - bar_emu_size - bar_hos_size - bar_hos_os_size - bar_and_size - bar_l4t_size; + bar_remaining_size = bar_remaining_size <= 7 ? 0 : bar_remaining_size; + + // Create HOS OS bar. + lv_obj_t *bar_hos_os = lv_bar_create(h1, NULL); + lv_obj_set_size(bar_hos_os, bar_hos_os_size, LV_DPI / 3); + lv_bar_set_range(bar_hos_os, 0, 1); + lv_bar_set_value(bar_hos_os, 1); + lv_bar_set_style(bar_hos_os, LV_BAR_STYLE_INDIC, &bar_hos_os_ind); + lv_obj_align(bar_hos_os, lbl_part, LV_ALIGN_OUT_BOTTOM_LEFT, 0, LV_DPI / 6); // Create HOS bar. - lv_obj_t *bar_mbr_hos = lv_bar_create(h1, NULL); - lv_obj_set_size(bar_mbr_hos, bar_hos_size, LV_DPI / 3); - lv_bar_set_range(bar_mbr_hos, 0, 1); - lv_bar_set_value(bar_mbr_hos, 1); - lv_bar_set_style(bar_mbr_hos, LV_BAR_STYLE_INDIC, &bar_hos_ind); - lv_obj_align(bar_mbr_hos, lbl_part, LV_ALIGN_OUT_BOTTOM_LEFT, 0, LV_DPI / 6); + lv_obj_t *bar_hos = lv_bar_create(h1, bar_hos_os); + lv_obj_set_size(bar_hos, bar_hos_size, LV_DPI / 3); + lv_bar_set_style(bar_hos, LV_BAR_STYLE_INDIC, &bar_hos_ind); + lv_obj_align(bar_hos, bar_hos_os, LV_ALIGN_OUT_RIGHT_MID, 0, 0); // Create emuMMC bar. - lv_obj_t *bar_mbr_emu = lv_bar_create(h1, bar_mbr_hos); - lv_obj_set_size(bar_mbr_emu, bar_emu_size, LV_DPI / 3); - lv_bar_set_style(bar_mbr_emu, LV_BAR_STYLE_INDIC, &bar_emu_ind); - lv_obj_align(bar_mbr_emu, bar_mbr_hos, LV_ALIGN_OUT_RIGHT_MID, 0, 0); + lv_obj_t *bar_emu = lv_bar_create(h1, bar_hos_os); + lv_obj_set_size(bar_emu, bar_emu_size, LV_DPI / 3); + lv_bar_set_style(bar_emu, LV_BAR_STYLE_INDIC, &bar_emu_ind); + lv_obj_align(bar_emu, bar_hos, LV_ALIGN_OUT_RIGHT_MID, 0, 0); // Create L4T bar. - lv_obj_t *bar_mbr_l4t = lv_bar_create(h1, bar_mbr_hos); - lv_obj_set_size(bar_mbr_l4t, bar_l4t_size, LV_DPI / 3); - lv_bar_set_style(bar_mbr_l4t, LV_BAR_STYLE_INDIC, &bar_l4t_ind); - lv_obj_align(bar_mbr_l4t, bar_mbr_emu, LV_ALIGN_OUT_RIGHT_MID, 0, 0); + lv_obj_t *bar_l4t = lv_bar_create(h1, bar_hos_os); + lv_obj_set_size(bar_l4t, bar_l4t_size, LV_DPI / 3); + lv_bar_set_style(bar_l4t, LV_BAR_STYLE_INDIC, &bar_l4t_ind); + lv_obj_align(bar_l4t, bar_emu, LV_ALIGN_OUT_RIGHT_MID, 0, 0); - // Create GPT bar. - lv_obj_t *bar_mbr_gpt = lv_bar_create(h1, bar_mbr_hos); - lv_obj_set_size(bar_mbr_gpt, bar_and_size > 1 ? bar_and_size : 0, LV_DPI / 3); - lv_bar_set_style(bar_mbr_gpt, LV_BAR_STYLE_INDIC, &bar_and_ind); - lv_obj_align(bar_mbr_gpt, bar_mbr_l4t, LV_ALIGN_OUT_RIGHT_MID, 0, 0); + // Create android bar. + lv_obj_t *bar_and = lv_bar_create(h1, bar_hos_os); + lv_obj_set_size(bar_and, bar_and_size, LV_DPI / 3); + lv_bar_set_style(bar_and, LV_BAR_STYLE_INDIC, &bar_and_ind); + lv_obj_align(bar_and, bar_l4t, LV_ALIGN_OUT_RIGHT_MID, 0, 0); + + //Create Remaining bar. + lv_obj_t *bar_remaining = lv_bar_create(h1, bar_hos_os); + lv_obj_set_size(bar_remaining, bar_remaining_size, LV_DPI / 3); + lv_bar_set_style(bar_remaining, LV_BAR_STYLE_INDIC, &bar_remaining_ind); + lv_obj_align(bar_remaining, bar_and, LV_ALIGN_OUT_RIGHT_MID, 0, 0); + + + // Create HOS OS separator. + lv_obj_t *sep_hos_os = lv_cont_create(h1, NULL); + lv_obj_set_size(sep_hos_os, bar_hos_os_size && (bar_and_size || bar_remaining_size || bar_l4t_size || bar_emu_size || bar_hos_size) ? 8 : 0, LV_DPI / 3); + lv_obj_set_style(sep_hos_os, &sep_hos_os_bg); + lv_obj_align(sep_hos_os, bar_hos_os, LV_ALIGN_OUT_RIGHT_MID, -4, 0); + + // Create HOS separator. + lv_obj_t *sep_hos = lv_cont_create(h1, NULL); + lv_obj_set_size(sep_hos, bar_hos_size && (bar_and_size || bar_remaining_size || bar_l4t_size || bar_emu_size)? 8 : 0, LV_DPI / 3); + lv_obj_set_style(sep_hos, &sep_hos_bg); + lv_obj_align(sep_hos, bar_hos, LV_ALIGN_OUT_RIGHT_MID, -4, 0); // Create emuMMC separator. - lv_obj_t *sep_mbr_emu = lv_cont_create(h1, NULL); - lv_obj_set_size(sep_mbr_emu, bar_emu_size ? 8 : 0, LV_DPI / 3); - lv_obj_set_style(sep_mbr_emu, &sep_emu_bg); - lv_obj_align(sep_mbr_emu, bar_mbr_hos, LV_ALIGN_OUT_RIGHT_MID, -4, 0); + lv_obj_t *sep_emu = lv_cont_create(h1, NULL); + lv_obj_set_size(sep_emu, bar_emu_size && (bar_and_size || bar_remaining_size || bar_l4t_size)? 8 : 0, LV_DPI / 3); + lv_obj_set_style(sep_emu, &sep_emu_bg); + lv_obj_align(sep_emu, bar_emu, LV_ALIGN_OUT_RIGHT_MID, -4, 0); // Create L4T separator. - lv_obj_t *sep_mbr_l4t = lv_cont_create(h1, sep_mbr_emu); - lv_obj_set_size(sep_mbr_l4t, bar_l4t_size ? 8 : 0, LV_DPI / 3); - lv_obj_set_style(sep_mbr_l4t, &sep_l4t_bg); - lv_obj_align(sep_mbr_l4t, bar_mbr_emu, LV_ALIGN_OUT_RIGHT_MID, -4, 0); + lv_obj_t *sep_l4t = lv_cont_create(h1, NULL); + lv_obj_set_size(sep_l4t, bar_l4t_size && (bar_and_size || bar_remaining_size) ? 8 : 0, LV_DPI / 3); + lv_obj_set_style(sep_l4t, &sep_l4t_bg); + lv_obj_align(sep_l4t, bar_l4t, LV_ALIGN_OUT_RIGHT_MID, -4, 0); - // Create GPT separator. - lv_obj_t *sep_mbr_gpt = lv_cont_create(h1, sep_mbr_emu); - lv_obj_set_size(sep_mbr_gpt, bar_and_size ? (bar_and_size > 1 ? 8 : 0) : 0, LV_DPI / 3); - lv_obj_set_style(sep_mbr_gpt, &sep_and_bg); - lv_obj_align(sep_mbr_gpt, bar_mbr_l4t, LV_ALIGN_OUT_RIGHT_MID, -4, 0); + // Create Android separator. + lv_obj_t *sep_and = lv_cont_create(h1, NULL); + lv_obj_set_size(sep_and, bar_and_size && bar_remaining_size ? 8 : 0, LV_DPI / 3); + lv_obj_set_style(sep_and, &sep_and_bg); + lv_obj_align(sep_and, bar_and, LV_ALIGN_OUT_RIGHT_MID, -4, 0); // Print partition table info. - s_printf(txt_buf, - "Partition 0 - Type: %02x, Start: %08x, Size: %08x\n" - "Partition 1 - Type: %02x, Start: %08x, Size: %08x\n" - "Partition 2 - Type: %02x, Start: %08x, Size: %08x\n" - "Partition 3 - Type: %02x, Start: %08x, Size: %08x", - mbr.partitions[0].type, mbr.partitions[0].start_sct, mbr.partitions[0].size_sct, - mbr.partitions[1].type, mbr.partitions[1].start_sct, mbr.partitions[1].size_sct, - mbr.partitions[2].type, mbr.partitions[2].start_sct, mbr.partitions[2].size_sct, - mbr.partitions[3].type, mbr.partitions[3].start_sct, mbr.partitions[3].size_sct); + if(!has_gpt){ + // print mbr table + s_printf(txt_buf, + "Part. 0 - Type: %02x, Start: %08x, Size: %08x\n" + "Part. 1 - Type: %02x, Start: %08x, Size: %08x\n" + "Part. 2 - Type: %02x, Start: %08x, Size: %08x\n" + "Part. 3 - Type: %02x, Start: %08x, Size: %08x", + mbr->partitions[0].type, mbr->partitions[0].start_sct, mbr->partitions[0].size_sct, + mbr->partitions[1].type, mbr->partitions[1].start_sct, mbr->partitions[1].size_sct, + mbr->partitions[2].type, mbr->partitions[2].start_sct, mbr->partitions[2].size_sct, + mbr->partitions[3].type, mbr->partitions[3].start_sct, mbr->partitions[3].size_sct); + }else{ + strcpy(txt_buf, ""); + for(u32 i = 0; i < gpt->header.num_part_ents && i < 128; i++){ + char txt_buf2[36]; + _wctombs((u16*)&gpt->entries[i].name, txt_buf2, 36); + if(gpt->header.num_part_ents > 9){ + s_printf(txt_buf + strlen(txt_buf), "Part. %02d - Name : %s\n Start: %08x, Size: %08x%c", i, txt_buf2, (u32)gpt->entries[i].lba_start, (u32)(gpt->entries[i].lba_end - gpt->entries[i].lba_start + 1), i == gpt->header.num_part_ents || i == 127 ? '\0' : '\n'); + }else{ + s_printf(txt_buf + strlen(txt_buf), "Part. %d - Name: %s\n Start: %08x, Size: %08x%c", i, txt_buf2, (u32)gpt->entries[i].lba_start, (u32)(gpt->entries[i].lba_end - gpt->entries[i].lba_start + 1), i == gpt->header.num_part_ents || i == 127 ? '\0' : '\n'); + } + } + } + + + lv_obj_t *ta_table = lv_ta_create(h1, NULL); + lv_ta_set_cursor_type(ta_table, LV_CURSOR_NONE); + lv_ta_set_text_align(ta_table, LV_LABEL_ALIGN_LEFT); + lv_ta_set_sb_mode(ta_table, LV_SB_MODE_AUTO); + lv_ta_set_style(ta_table, LV_TA_STYLE_BG, &monospace_text); + lv_obj_set_size(ta_table, w, w * 2 / 7); + lv_ta_set_text(ta_table, txt_buf); + lv_obj_align(ta_table, h1, LV_ALIGN_IN_TOP_MID, 0, LV_DPI); - lv_obj_t *lbl_table = lv_label_create(h1, NULL); - lv_label_set_style(lbl_table, &monospace_text); - lv_label_set_text(lbl_table, txt_buf); - lv_obj_align(lbl_table, h1, LV_ALIGN_IN_TOP_MID, 0, LV_DPI); if (!part_info.backup_possible) lv_mbox_add_btns(mbox, mbox_btn_map, mbox_action); @@ -2632,9 +3122,11 @@ static void _create_mbox_check_files_total_size() free(txt_buf); free(path); + free(mbr); + free(gpt); } -static lv_res_t _action_fix_mbr_gpt(lv_obj_t *btn) +static lv_res_t _action_fix_mbr(lv_obj_t *btn) { lv_obj_t *dark_bg = lv_obj_create(lv_scr_act(), NULL); lv_obj_set_style(dark_bg, &mbox_darken); @@ -2654,11 +3146,9 @@ static lv_res_t _action_fix_mbr_gpt(lv_obj_t *btn) gpt_t *gpt = zalloc(sizeof(gpt_t)); gpt_header_t gpt_hdr_backup = { 0 }; - bool has_mbr_attributes = false; - bool hybrid_mbr_changed = false; + bool has_mbr_attributes = false; + bool hybrid_mbr_changed = false; bool gpt_partition_exists = false; - int gpt_oob_empty_part_no = 0; - int gpt_emummc_migrate_no = 0; // Try to init sd card. No need for valid MBR. if (!sd_mount() && !sd_get_card_initialized()) @@ -2704,17 +3194,11 @@ static lv_res_t _action_fix_mbr_gpt(lv_obj_t *btn) LIST_INIT(gpt_parsed); for (u32 i = 0; i < gpt->header.num_part_ents; i++) { - // Check if partition is out of bounds or empty. - if ( gpt->entries[i].lba_start < gpt->header.first_use_lba || - gpt->entries[i].lba_start >= gpt->entries[i].lba_end || - !gpt->entries[i].lba_end) - { - gpt_oob_empty_part_no++; - continue; - } - emmc_part_t *part = (emmc_part_t *)zalloc(sizeof(emmc_part_t)); + if (gpt->entries[i].lba_start < gpt->header.first_use_lba) + continue; + part->index = i; part->lba_start = gpt->entries[i].lba_start; part->lba_end = gpt->entries[i].lba_end; @@ -2730,7 +3214,6 @@ static lv_res_t _action_fix_mbr_gpt(lv_obj_t *btn) // Set FAT and emuMMC partitions. u32 mbr_idx = 1; bool found_hos_data = false; - u32 emummc_mbr_part_idx[2] = {0}; LIST_FOREACH_ENTRY(emmc_part_t, part, &gpt_parsed, link) { // FatFS simple GPT found a fat partition, set it. @@ -2738,7 +3221,7 @@ static lv_res_t _action_fix_mbr_gpt(lv_obj_t *btn) { mbr[1].partitions[0].type = sd_fs.fs_type == FS_EXFAT ? 0x7 : 0xC; mbr[1].partitions[0].start_sct = part->lba_start; - mbr[1].partitions[0].size_sct = part->lba_end - part->lba_start + 1; + mbr[1].partitions[0].size_sct = (part->lba_end - part->lba_start + 1); } // FatFS simple GPT didn't find a fat partition as the first one. @@ -2746,7 +3229,7 @@ static lv_res_t _action_fix_mbr_gpt(lv_obj_t *btn) { mbr[1].partitions[0].type = 0xC; mbr[1].partitions[0].start_sct = part->lba_start; - mbr[1].partitions[0].size_sct = part->lba_end - part->lba_start + 1; + mbr[1].partitions[0].size_sct = (part->lba_end - part->lba_start + 1); found_hos_data = true; } @@ -2755,11 +3238,7 @@ static lv_res_t _action_fix_mbr_gpt(lv_obj_t *btn) { mbr[1].partitions[mbr_idx].type = 0xE0; mbr[1].partitions[mbr_idx].start_sct = part->lba_start; - mbr[1].partitions[mbr_idx].size_sct = part->lba_end - part->lba_start + 1; - if (!strcmp(part->name, "emummc")) - emummc_mbr_part_idx[0] = mbr_idx; - else - emummc_mbr_part_idx[1] = mbr_idx; + mbr[1].partitions[mbr_idx].size_sct = (part->lba_end - part->lba_start + 1); mbr_idx++; } @@ -2782,21 +3261,13 @@ static lv_res_t _action_fix_mbr_gpt(lv_obj_t *btn) (mbr[0].partitions[i].start_sct != mbr[1].partitions[i].start_sct) || (mbr[0].partitions[i].size_sct != mbr[1].partitions[i].size_sct)) { - // Check if original MBR already has an emuMMC and use it as source of truth. - if (mbr[0].partitions[i].type == 0xE0) - { - memcpy(&mbr[1].partitions[i], &mbr[0].partitions[i], sizeof(mbr_part_t)); - gpt_emummc_migrate_no++; - continue; - } - else - hybrid_mbr_changed = true; + hybrid_mbr_changed = true; break; } } check_changes: - if (!hybrid_mbr_changed && !has_mbr_attributes && !gpt_emummc_migrate_no) + if (!hybrid_mbr_changed && !has_mbr_attributes) { lv_label_set_text(lbl_status, "#96FF00 Warning:# The Hybrid MBR needs no change!#"); goto out; @@ -2804,42 +3275,29 @@ check_changes: char *txt_buf = malloc(SZ_16K); - if (hybrid_mbr_changed) - { - // Current MBR info. - s_printf(txt_buf, "#00DDFF Current MBR Layout:#\n"); - s_printf(txt_buf + strlen(txt_buf), - "Partition 0 - Type: %02x, Start: %08x, Size: %08x\n" - "Partition 1 - Type: %02x, Start: %08x, Size: %08x\n" - "Partition 2 - Type: %02x, Start: %08x, Size: %08x\n" - "Partition 3 - Type: %02x, Start: %08x, Size: %08x\n\n", - mbr[0].partitions[0].type, mbr[0].partitions[0].start_sct, mbr[0].partitions[0].size_sct, - mbr[0].partitions[1].type, mbr[0].partitions[1].start_sct, mbr[0].partitions[1].size_sct, - mbr[0].partitions[2].type, mbr[0].partitions[2].start_sct, mbr[0].partitions[2].size_sct, - mbr[0].partitions[3].type, mbr[0].partitions[3].start_sct, mbr[0].partitions[3].size_sct); + // Current MBR info. + s_printf(txt_buf, "#00DDFF Current MBR Layout:#\n"); + s_printf(txt_buf + strlen(txt_buf), + "Partition 0 - Type: %02x, Start: %08x, Size: %08x\n" + "Partition 1 - Type: %02x, Start: %08x, Size: %08x\n" + "Partition 2 - Type: %02x, Start: %08x, Size: %08x\n" + "Partition 3 - Type: %02x, Start: %08x, Size: %08x\n\n", + mbr[0].partitions[0].type, mbr[0].partitions[0].start_sct, mbr[0].partitions[0].size_sct, + mbr[0].partitions[1].type, mbr[0].partitions[1].start_sct, mbr[0].partitions[1].size_sct, + mbr[0].partitions[2].type, mbr[0].partitions[2].start_sct, mbr[0].partitions[2].size_sct, + mbr[0].partitions[3].type, mbr[0].partitions[3].start_sct, mbr[0].partitions[3].size_sct); - // New MBR info. - s_printf(txt_buf + strlen(txt_buf), "#00DDFF New MBR Layout:#\n"); - s_printf(txt_buf + strlen(txt_buf), - "Partition 0 - Type: %02x, Start: %08x, Size: %08x\n" - "Partition 1 - Type: %02x, Start: %08x, Size: %08x\n" - "Partition 2 - Type: %02x, Start: %08x, Size: %08x\n" - "Partition 3 - Type: %02x, Start: %08x, Size: %08x", - mbr[1].partitions[0].type, mbr[1].partitions[0].start_sct, mbr[1].partitions[0].size_sct, - mbr[1].partitions[1].type, mbr[1].partitions[1].start_sct, mbr[1].partitions[1].size_sct, - mbr[1].partitions[2].type, mbr[1].partitions[2].start_sct, mbr[1].partitions[2].size_sct, - mbr[1].partitions[3].type, mbr[1].partitions[3].start_sct, mbr[1].partitions[3].size_sct); - } - else if (has_mbr_attributes || gpt_emummc_migrate_no || gpt_oob_empty_part_no) - { - s_printf(txt_buf, "#00DDFF The following need to be corrected:#\n"); - if (has_mbr_attributes) - s_printf(txt_buf + strlen(txt_buf), "- MBR attributes\n"); - if (gpt_emummc_migrate_no) - s_printf(txt_buf + strlen(txt_buf), "- emuMMC GPT Partition address and size\n"); - if (gpt_oob_empty_part_no) - s_printf(txt_buf + strlen(txt_buf), "- GPT OOB/Empty Partitions (removal)\n"); - } + // New MBR info. + s_printf(txt_buf + strlen(txt_buf), "#00DDFF New MBR Layout:#\n"); + s_printf(txt_buf + strlen(txt_buf), + "Partition 0 - Type: %02x, Start: %08x, Size: %08x\n" + "Partition 1 - Type: %02x, Start: %08x, Size: %08x\n" + "Partition 2 - Type: %02x, Start: %08x, Size: %08x\n" + "Partition 3 - Type: %02x, Start: %08x, Size: %08x", + mbr[1].partitions[0].type, mbr[1].partitions[0].start_sct, mbr[1].partitions[0].size_sct, + mbr[1].partitions[1].type, mbr[1].partitions[1].start_sct, mbr[1].partitions[1].size_sct, + mbr[1].partitions[2].type, mbr[1].partitions[2].start_sct, mbr[1].partitions[2].size_sct, + mbr[1].partitions[3].type, mbr[1].partitions[3].start_sct, mbr[1].partitions[3].size_sct); lv_label_set_text(lbl_status, txt_buf); lv_label_set_style(lbl_status, &monospace_text); @@ -2861,8 +3319,6 @@ check_changes: if (btn_wait() & BTN_POWER) { - bool has_gpt_changes = false; - sd_mount(); // Write MBR. @@ -2874,79 +3330,36 @@ check_changes: { // Clear secret attributes. gpt->entries[0].part_guid[7] = 0; - has_gpt_changes = gpt_partition_exists; - if (!has_gpt_changes) + if (gpt_partition_exists) + { + // Fix CRC32s. + u32 entries_size = sizeof(gpt_entry_t) * gpt->header.num_part_ents; + gpt->header.part_ents_crc32 = crc32_calc(0, (const u8 *)gpt->entries, entries_size); + gpt->header.crc32 = 0; // Set to 0 for calculation. + gpt->header.crc32 = crc32_calc(0, (const u8 *)&gpt->header, gpt->header.size); + + gpt_hdr_backup.part_ents_crc32 = gpt->header.part_ents_crc32; + gpt_hdr_backup.crc32 = 0; // Set to 0 for calculation. + gpt_hdr_backup.crc32 = crc32_calc(0, (const u8 *)&gpt_hdr_backup, gpt_hdr_backup.size); + + // Write main GPT. + u32 aligned_entries_size = ALIGN(entries_size, SD_BLOCKSIZE); + sdmmc_storage_write(&sd_storage, gpt->header.my_lba, (sizeof(gpt_header_t) + aligned_entries_size) >> 9, gpt); + + // Write backup GPT partition table. + sdmmc_storage_write(&sd_storage, gpt_hdr_backup.part_ent_lba, aligned_entries_size >> 9, gpt->entries); + + // Write backup GPT header. + sdmmc_storage_write(&sd_storage, gpt_hdr_backup.my_lba, 1, &gpt_hdr_backup); + } + else { // Only write the relevant sector if the only change is MBR attributes. sdmmc_storage_write(&sd_storage, 2, 1, &gpt->entries[0]); } } - if (gpt_emummc_migrate_no) - { - u32 emu_idx = 0; - for (u32 i = 0; i < gpt->header.num_part_ents; i++) - { - if (!memcmp(gpt->entries[i].name, (u16[]) { 'e', 'm', 'u', 'm', 'm', 'c' }, 12)) - { - u32 idx = emummc_mbr_part_idx[emu_idx]; - gpt->entries[i].lba_start = mbr[0].partitions[idx].start_sct; - gpt->entries[i].lba_end = mbr[0].partitions[idx].start_sct + mbr[0].partitions[idx].size_sct - 1; - gpt_emummc_migrate_no--; - emu_idx++; - - has_gpt_changes = true; - } - - if (i > 126 || !gpt_emummc_migrate_no) - break; - } - } - - if (gpt_oob_empty_part_no) - { - u32 part_idx = 0; - for (u32 i = 0; i < gpt->header.num_part_ents; i++) - { - if ( gpt->entries[i].lba_start < gpt->header.first_use_lba || - gpt->entries[i].lba_start >= gpt->entries[i].lba_end || - !gpt->entries[i].lba_end) - { - continue; - } - - if (part_idx != i) - memcpy(&gpt->entries[part_idx], &gpt->entries[i], sizeof(gpt_entry_t)); - part_idx++; - } - gpt->header.num_part_ents -= gpt_oob_empty_part_no; - has_gpt_changes = true; - } - - if (has_gpt_changes) - { - // Fix GPT CRC32s. - u32 entries_size = sizeof(gpt_entry_t) * gpt->header.num_part_ents; - gpt->header.part_ents_crc32 = crc32_calc(0, (const u8 *)gpt->entries, entries_size); - gpt->header.crc32 = 0; // Set to 0 for calculation. - gpt->header.crc32 = crc32_calc(0, (const u8 *)&gpt->header, gpt->header.size); - - gpt_hdr_backup.part_ents_crc32 = gpt->header.part_ents_crc32; - gpt_hdr_backup.crc32 = 0; // Set to 0 for calculation. - gpt_hdr_backup.crc32 = crc32_calc(0, (const u8 *)&gpt_hdr_backup, gpt_hdr_backup.size); - - // Write main GPT. - u32 aligned_entries_size = ALIGN(entries_size, SD_BLOCKSIZE); - sdmmc_storage_write(&sd_storage, gpt->header.my_lba, (sizeof(gpt_header_t) + aligned_entries_size) >> 9, gpt); - - // Write backup GPT partition table. - sdmmc_storage_write(&sd_storage, gpt_hdr_backup.part_ent_lba, aligned_entries_size >> 9, gpt->entries); - - // Write backup GPT header. - sdmmc_storage_write(&sd_storage, gpt_hdr_backup.my_lba, 1, &gpt_hdr_backup); - } - sd_unmount(); lv_label_set_text(lbl_status, "#96FF00 The new Hybrid MBR was written successfully!#"); @@ -2965,22 +3378,20 @@ out: return LV_RES_OK; } -lv_res_t create_window_partition_manager(bool emmc) +lv_res_t create_window_partition_manager(lv_obj_t *btn, u8 drive) { - lv_obj_t *win; + char title_str[0x20]; + s_printf(title_str, "%s %s Partition Manager", drive == DRIVE_SD ? SYMBOL_SD : SYMBOL_CHIP, drive == DRIVE_SD ? "SD" : "eMMC"); + lv_obj_t *win = nyx_create_standard_window(title_str); - if (!emmc) - { - win = nyx_create_standard_window(SYMBOL_SD" SD Partition Manager"); - lv_win_add_btn(win, NULL, SYMBOL_MODULES_ALT" Fix Hybrid MBR/GPT", _action_fix_mbr_gpt); + if(drive == DRIVE_SD){ + lv_win_add_btn(win, NULL, SYMBOL_MODULES_ALT" Fix Hybrid MBR", _action_fix_mbr); } - else - win = nyx_create_standard_window(SYMBOL_CHIP" eMMC Partition Manager"); - static lv_style_t bar_hos_bg, bar_emu_bg, bar_l4t_bg, bar_and_bg; - static lv_style_t bar_hos_ind, bar_emu_ind, bar_l4t_ind, bar_and_ind; - static lv_style_t bar_emu_btn, bar_l4t_btn, bar_and_btn; - static lv_style_t sep_emu_bg, sep_l4t_bg, sep_and_bg; + static lv_style_t bar_hos_os_bg, bar_hos_bg, bar_emu_bg, bar_l4t_bg, bar_and_bg, bar_emu_sd_bg; + static lv_style_t bar_hos_os_ind, bar_hos_ind, bar_emu_ind, bar_l4t_ind, bar_and_ind, bar_remaining_ind, bar_emu_sd_ind; + static lv_style_t bar_hos_os_btn, bar_hos_btn, bar_emu_btn, bar_l4t_btn, bar_and_btn, bar_emu_sd_btn; + static lv_style_t sep_emu_bg, sep_l4t_bg, sep_and_bg, sep_hos_bg, sep_hos_os_bg, sep_emu_sd_bg; // Set HOS bar styles. lv_style_copy(&bar_hos_bg, lv_theme_get_current()->bar.bg); @@ -2989,6 +3400,18 @@ lv_res_t create_window_partition_manager(bool emmc) lv_style_copy(&bar_hos_ind, lv_theme_get_current()->bar.indic); bar_hos_ind.body.main_color = LV_COLOR_HEX(0x96FF00); bar_hos_ind.body.grad_color = bar_hos_ind.body.main_color; + lv_style_copy(&bar_hos_btn, lv_theme_get_current()->slider.knob); + bar_hos_btn.body.main_color = LV_COLOR_HEX(0x77CC00); + bar_hos_btn.body.grad_color = bar_hos_btn.body.main_color; + lv_style_copy(&sep_hos_bg, lv_theme_get_current()->cont); + sep_hos_bg.body.main_color = LV_COLOR_HEX(0x96FF00); + sep_hos_bg.body.grad_color = sep_hos_bg.body.main_color; + sep_hos_bg.body.radius = 0; + + // Set Remaining Space style + lv_style_copy(&bar_remaining_ind, lv_theme_get_current()->bar.indic); + bar_remaining_ind.body.main_color = LV_COLOR_HEX(0xc9c9c9); + bar_remaining_ind.body.grad_color = bar_remaining_ind.body.main_color; // Set eMUMMC bar styles. lv_style_copy(&bar_emu_bg, lv_theme_get_current()->bar.bg); @@ -3000,7 +3423,7 @@ lv_res_t create_window_partition_manager(bool emmc) lv_style_copy(&bar_emu_btn, lv_theme_get_current()->slider.knob); bar_emu_btn.body.main_color = LV_COLOR_HEX(0xB31200); bar_emu_btn.body.grad_color = bar_emu_btn.body.main_color; - lv_style_copy(&sep_emu_bg, lv_theme_get_current()->cont); + lv_style_copy(&sep_emu_bg, &sep_hos_bg); sep_emu_bg.body.main_color = LV_COLOR_HEX(0xFF3C28); sep_emu_bg.body.grad_color = sep_emu_bg.body.main_color; sep_emu_bg.body.radius = 0; @@ -3015,7 +3438,7 @@ lv_res_t create_window_partition_manager(bool emmc) lv_style_copy(&bar_l4t_btn, lv_theme_get_current()->slider.knob); bar_l4t_btn.body.main_color = LV_COLOR_HEX(0x00B1CC); bar_l4t_btn.body.grad_color = bar_l4t_btn.body.main_color; - lv_style_copy(&sep_l4t_bg, &sep_emu_bg); + lv_style_copy(&sep_l4t_bg, &sep_hos_bg); sep_l4t_bg.body.main_color = LV_COLOR_HEX(0x00DDFF); sep_l4t_bg.body.grad_color = sep_l4t_bg.body.main_color; @@ -3029,10 +3452,38 @@ lv_res_t create_window_partition_manager(bool emmc) lv_style_copy(&bar_and_btn, lv_theme_get_current()->slider.knob); bar_and_btn.body.main_color = LV_COLOR_HEX(0xCC6600); bar_and_btn.body.grad_color = bar_and_btn.body.main_color; - lv_style_copy(&sep_and_bg, &sep_emu_bg); + lv_style_copy(&sep_and_bg, &sep_hos_bg); sep_and_bg.body.main_color = LV_COLOR_HEX(0xFF8000); sep_and_bg.body.grad_color = sep_and_bg.body.main_color; + // Set HOS OS bar styles. + lv_style_copy(&bar_hos_os_bg, lv_theme_get_current()->bar.bg); + bar_hos_os_bg.body.main_color = LV_COLOR_HEX(0xb89900); + bar_hos_os_bg.body.grad_color = bar_hos_os_bg.body.main_color; + lv_style_copy(&bar_hos_os_ind, lv_theme_get_current()->bar.indic); + bar_hos_os_ind.body.main_color = LV_COLOR_HEX(0xffd300); + bar_hos_os_ind.body.grad_color = bar_hos_os_ind.body.main_color; + lv_style_copy(&bar_hos_os_btn, lv_theme_get_current()->slider.knob); + bar_hos_os_btn.body.main_color = LV_COLOR_HEX(0xe6bf00); + bar_hos_os_btn.body.grad_color = bar_hos_os_btn.body.main_color; + lv_style_copy(&sep_hos_os_bg, &sep_hos_bg); + sep_hos_os_bg.body.main_color = LV_COLOR_HEX(0xffd300); + sep_hos_os_bg.body.grad_color = sep_hos_os_bg.body.main_color; + + // Set emuSD bar styles. + lv_style_copy(&bar_emu_sd_bg, lv_theme_get_current()->bar.bg); + bar_emu_sd_bg.body.main_color = LV_COLOR_HEX(0x96007e); + bar_emu_sd_bg.body.grad_color = bar_emu_sd_bg.body.main_color; + lv_style_copy(&bar_emu_sd_ind, lv_theme_get_current()->bar.indic); + bar_emu_sd_ind.body.main_color = LV_COLOR_HEX(0xff00d6); + bar_emu_sd_ind.body.grad_color = bar_emu_sd_ind.body.main_color; + lv_style_copy(&bar_emu_sd_btn, lv_theme_get_current()->slider.knob); + bar_emu_sd_btn.body.main_color = LV_COLOR_HEX(0xc700a7); + bar_emu_sd_btn.body.grad_color = bar_emu_sd_btn.body.main_color; + lv_style_copy(&sep_emu_sd_bg, &sep_hos_bg); + sep_emu_sd_bg.body.main_color = LV_COLOR_HEX(0xff00d6); + sep_emu_sd_bg.body.grad_color = sep_emu_sd_bg.body.main_color; + lv_obj_t *sep = lv_label_create(win, NULL); lv_label_set_static_text(sep, ""); lv_obj_align(sep, NULL, LV_ALIGN_IN_TOP_MID, 0, 0); @@ -3041,284 +3492,360 @@ lv_res_t create_window_partition_manager(bool emmc) lv_obj_t *h1 = lv_cont_create(win, NULL); lv_obj_set_size(h1, LV_HOR_RES - (LV_DPI * 8 / 10), LV_VER_RES - LV_DPI); - u32 emmc_size = 0; - if (!emmc) - { - if (!sd_mount()) - { - lv_obj_t *lbl = lv_label_create(h1, NULL); - lv_label_set_recolor(lbl, true); - lv_label_set_text(lbl, "#FFDD00 Failed to init SD!#"); - return LV_RES_OK; - } - if (emmc_initialize(false)) - { - emmc_set_partition(EMMC_GPP); - emmc_size = emmc_storage.sec_cnt >> 11; - emmc_end(); - } + sdmmc_storage_t *storage = drive == DRIVE_SD ? &sd_storage : &emmc_storage; + bool res = false; + if(drive == DRIVE_SD){ + res = sd_mount() || sd_initialize(false); + }else{ + res = emmc_mount() || emmc_initialize(false); } - else + + if (!res) { - if (!emmc_initialize(false)) - { - lv_obj_t *lbl = lv_label_create(h1, NULL); - lv_label_set_recolor(lbl, true); - lv_label_set_text(lbl, "#FFDD00 Failed to init eMMC!#"); - return LV_RES_OK; - } - emmc_set_partition(EMMC_GPP); + lv_obj_t *lbl = lv_label_create(h1, NULL); + lv_label_set_recolor(lbl, true); + lv_label_set_text(lbl, drive == DRIVE_SD ? "#FFDD00 Failed to init SD!#" : "#FFDD00 Failed to init eMMC!#"); + return LV_RES_OK; } memset(&part_info, 0, sizeof(partition_ctxt_t)); - if (!emmc) - _create_mbox_check_files_total_size(); + part_info.drive = drive; + _create_mbox_check_files_total_size(drive); char *txt_buf = malloc(SZ_8K); - part_info.emmc = emmc; - part_info.storage = !emmc ? &sd_storage : &emmc_storage; - part_info.total_sct = part_info.storage->sec_cnt; - if (emmc) - part_info.total_sct -= HOS_USER_SECTOR; // Reserved HOS partitions. + part_info.total_sct = storage->sec_cnt; + // reserve 16mb for alignment + last 1mb for backup gpt + part_info.total_sct_available = ALIGN_DOWN(part_info.total_sct - AU_ALIGN_SECTORS - (1 << 11), AU_ALIGN_SECTORS); + part_info.alignment = part_info.total_sct - part_info.total_sct_available; - // Align down total size to ensure alignment of all partitions after HOS one. - part_info.alignment = part_info.total_sct - ALIGN_DOWN(part_info.total_sct, AU_ALIGN_SECTORS); - part_info.total_sct -= part_info.alignment; - - u32 extra_sct = AU_ALIGN_SECTORS + 0x400000; // Reserved 16MB alignment for FAT partition + 2GB. + // Reserved 16MB for alignment + u32 extra_sct = 0; + if(drive == DRIVE_SD){ + // On SD, also Reserve 2GB for FAT partition + extra_sct += 0x400000; + } // Set initial HOS partition size, so the correct cluster size can be selected. - part_info.hos_size = (part_info.total_sct >> 11) - 16; // Important if there's no slider change. + if(drive == DRIVE_SD){ + part_info.hos_size = (part_info.total_sct_available >> 11); // Important if there's no slider change. + }else{ + // On eMMC, default is to not have a FAT32 partition + part_info.hos_size = 0; + } + // Check if eMMC should be 64GB (Aula). part_info.emmc_is_64gb = fuse_read_hw_type() == FUSE_NX_HW_TYPE_AULA; + part_info.auto_assign_free_storage = drive == DRIVE_SD ? true : false; - // Set actual eMMC size. - part_info.emmc_size_mb = emmc_size; - - // Set HOS FAT or USER minimum size. - part_info.hos_min_size = !emmc? HOS_FAT_MIN_SIZE_MB : HOS_USER_MIN_SIZE_MB; + part_info.hos_min_size_mb = HOS_MIN_SIZE_MB; // Read current MBR. mbr_t mbr = { 0 }; - sdmmc_storage_read(part_info.storage, 0, 1, &mbr); + gpt_t *gpt = NULL; + bool has_gpt = false; + bool has_hos_os = false; + sdmmc_storage_read(storage, 0, 1, &mbr); + has_gpt = _has_gpt(&mbr); + if(has_gpt){ + gpt = zalloc(sizeof(*gpt)); + sdmmc_storage_read(storage, 1, sizeof(*gpt) >> 9, gpt); - u32 bar_hos_size = lv_obj_get_width(h1); - u32 bar_emu_size = 0; - u32 bar_l4t_size = 0; - u32 bar_and_size = 0; + if(gpt->header.num_part_ents >= 10 && drive == DRIVE_EMMC){ + if(!memcmp(gpt->entries[10].name, (char[]){'U', 0, 'S', 0, 'E', 0, 'R', 0}, 8)){ + // Found HOS USER partition + has_hos_os = true; + // system only size (excl. user) + // part_info.hos_sys_size_mb = (gpt->entries[10].lba_start - gpt->entries[0].lba_start) >> 11; + + // We assume first partition is 16mb aligned and starts at 0x800 + part_info.hos_sys_size_mb = (gpt->entries[10].lba_start - 0x800) >> 11; + + part_info.hos_os_size = (gpt->entries[10].lba_end - 0x800 + 1) >> 11; + // original hos size + part_info.hos_os_og_size = part_info.hos_os_size; + + part_info.hos_os_align = ALIGN(part_info.hos_os_size, AU_ALIGN_SECTORS >> 11) - part_info.hos_os_size; + + part_info.hos_os_size += part_info.hos_os_align; + } + } + } + + + // account for alignment + 1mb for backup gpt + u32 total_size = part_info.total_sct_available / SECTORS_PER_GB; + u32 bar_hos_size = lv_obj_get_width(h1) * (part_info.hos_size >> 10) / total_size; + u32 bar_emu_size = lv_obj_get_width(h1) * (part_info.emu_size >> 10) / total_size; + u32 bar_l4t_size = lv_obj_get_width(h1) * (part_info.l4t_size >> 10) / total_size; + u32 bar_and_size = lv_obj_get_width(h1) * (part_info.and_size >> 10) / total_size; + u32 bar_hos_os_size = lv_obj_get_width(h1) * (part_info.hos_os_size >> 10) / total_size; + u32 bar_remaining_size = lv_obj_get_width(h1) - (bar_hos_size + bar_hos_os_size + bar_emu_size + bar_l4t_size + bar_and_size); + bar_remaining_size = bar_remaining_size <= 7 ? 0 : bar_remaining_size; lv_obj_t *lbl = lv_label_create(h1, NULL); lv_label_set_recolor(lbl, true); lv_label_set_text(lbl, "Choose #FFDD00 new# partition layout:"); // Create disk layout blocks. + // HOS OS partition block + lv_obj_t *bar_hos_os = lv_bar_create(h1, NULL); + lv_obj_set_size(bar_hos_os, bar_hos_os_size, LV_DPI / 2); + lv_bar_set_range(bar_hos_os, 0, 1); + lv_bar_set_value(bar_hos_os, 1); + lv_bar_set_style(bar_hos_os, LV_BAR_STYLE_INDIC, &bar_hos_os_ind); + lv_obj_align(bar_hos_os, lbl, LV_ALIGN_OUT_BOTTOM_LEFT, 0, LV_DPI / 6); + part_info.bar_hos_os = bar_hos_os; + // HOS partition block. - lv_obj_t *bar_hos = lv_bar_create(h1, NULL); + lv_obj_t *bar_hos = lv_bar_create(h1, bar_hos_os); lv_obj_set_size(bar_hos, bar_hos_size, LV_DPI / 2); - lv_bar_set_range(bar_hos, 0, 1); - lv_bar_set_value(bar_hos, 1); lv_bar_set_style(bar_hos, LV_BAR_STYLE_INDIC, &bar_hos_ind); - lv_obj_align(bar_hos, lbl, LV_ALIGN_OUT_BOTTOM_LEFT, 0, LV_DPI / 6); + lv_obj_align(bar_hos, bar_hos_os, LV_ALIGN_OUT_RIGHT_MID, 0, 0); part_info.bar_hos = bar_hos; // emuMMC partition block. - lv_obj_t *bar_emu = lv_bar_create(h1, bar_hos); + lv_obj_t *bar_emu = lv_bar_create(h1, bar_hos_os); lv_obj_set_size(bar_emu, bar_emu_size, LV_DPI / 2); lv_bar_set_style(bar_emu, LV_BAR_STYLE_INDIC, &bar_emu_ind); lv_obj_align(bar_emu, bar_hos, LV_ALIGN_OUT_RIGHT_MID, 0, 0); part_info.bar_emu = bar_emu; // L4T partition block. - lv_obj_t *bar_l4t = lv_bar_create(h1, bar_hos); + lv_obj_t *bar_l4t = lv_bar_create(h1, bar_hos_os); lv_obj_set_size(bar_l4t, bar_l4t_size, LV_DPI / 2); lv_bar_set_style(bar_l4t, LV_BAR_STYLE_INDIC, &bar_l4t_ind); lv_obj_align(bar_l4t, bar_emu, LV_ALIGN_OUT_RIGHT_MID, 0, 0); part_info.bar_l4t = bar_l4t; // Android partition block. - lv_obj_t *bar_and = lv_bar_create(h1, bar_hos); + lv_obj_t *bar_and = lv_bar_create(h1, bar_hos_os); lv_obj_set_size(bar_and, bar_and_size, LV_DPI / 2); lv_bar_set_style(bar_and, LV_BAR_STYLE_INDIC, &bar_and_ind); lv_obj_align(bar_and, bar_l4t, LV_ALIGN_OUT_RIGHT_MID, 0, 0); part_info.bar_and = bar_and; - // HOS partition block. - lv_obj_t *sep_emu = lv_cont_create(h1, NULL); - lv_cont_set_fit(sep_emu, false, false); - lv_obj_set_size(sep_emu, 0, LV_DPI / 2); // 8. + // Remaining space + lv_obj_t *bar_remaining = lv_bar_create(h1, bar_hos_os); + lv_obj_set_size(bar_remaining, bar_remaining_size, LV_DPI / 2); + lv_bar_set_style(bar_remaining, LV_BAR_STYLE_INDIC, &bar_remaining_ind); + lv_obj_align(bar_remaining, bar_and, LV_ALIGN_OUT_RIGHT_MID, 0, 0); + part_info.bar_remaining = bar_remaining; + + // ------------------------------------------------------------------------- + // Create disk layout blending separators. + lv_obj_t *sep_hos_os = lv_cont_create(h1, NULL); + lv_cont_set_fit(sep_hos_os, false, false); + lv_obj_set_size(sep_hos_os, 0, LV_DPI / 2); + lv_obj_set_style(sep_hos_os, &sep_hos_os_bg); + lv_obj_align(sep_hos_os, bar_hos_os, LV_ALIGN_OUT_RIGHT_MID, -4, 0); + part_info.sep_hos_os = sep_hos_os; + + lv_obj_t *sep_hos = lv_cont_create(h1, NULL); + lv_cont_set_fit(sep_hos, false, false); + lv_obj_set_size(sep_hos, 0, LV_DPI / 2); + lv_obj_set_style(sep_hos, &sep_hos_bg); + lv_obj_align(sep_hos, bar_hos, LV_ALIGN_OUT_RIGHT_MID, -4, 0); + part_info.sep_hos = sep_hos; + + lv_obj_t *sep_emu = lv_cont_create(h1, sep_hos); lv_obj_set_style(sep_emu, &sep_emu_bg); - lv_obj_align(sep_emu, bar_hos, LV_ALIGN_OUT_RIGHT_MID, -4, 0); + lv_obj_align(sep_emu, bar_emu, LV_ALIGN_OUT_RIGHT_MID, -4, 0); part_info.sep_emu = sep_emu; - // Create disk layout blending separators. lv_obj_t *sep_l4t = lv_cont_create(h1, sep_emu); lv_obj_set_style(sep_l4t, &sep_l4t_bg); - lv_obj_align(sep_l4t, bar_emu, LV_ALIGN_OUT_RIGHT_MID, -4, 0); + lv_obj_align(sep_l4t, bar_l4t, LV_ALIGN_OUT_RIGHT_MID, -4, 0); part_info.sep_l4t = sep_l4t; lv_obj_t *sep_and = lv_cont_create(h1, sep_emu); lv_obj_set_style(sep_and, &sep_and_bg); - lv_obj_align(sep_and, bar_l4t, LV_ALIGN_OUT_RIGHT_MID, -4, 0); + lv_obj_align(sep_and, bar_and, LV_ALIGN_OUT_RIGHT_MID, -4, 0); part_info.sep_and = sep_and; // Create slider type labels. - lv_obj_t *cont_lbl_hos = lv_cont_create(h1, NULL); - lv_cont_set_fit(cont_lbl_hos, false, true); - lv_obj_set_width(cont_lbl_hos, LV_DPI * 17 / 7); - lv_obj_t *lbl_hos = lv_label_create(cont_lbl_hos, NULL); - lv_label_set_recolor(lbl_hos, true); - lv_label_set_static_text(lbl_hos, !emmc ? "#96FF00 "SYMBOL_DOT" HOS (FAT32):#" : - "#96FF00 "SYMBOL_DOT" eMMC (USER):#"); - lv_obj_align(lbl_hos, bar_hos, LV_ALIGN_OUT_BOTTOM_LEFT, 0, LV_DPI / 2); + lv_obj_t *lbl_hos_os = lv_label_create(h1, NULL); + lv_label_set_recolor(lbl_hos_os, true); + lv_label_set_static_text(lbl_hos_os, "#FFD300 "SYMBOL_DOT" HOS (USER):#"); + lv_obj_align(lbl_hos_os, bar_hos_os, LV_ALIGN_OUT_BOTTOM_LEFT, 0, LV_DPI / 2); + lv_obj_set_hidden(lbl_hos_os, !has_hos_os); - lv_obj_t *lbl_emu = lbl_hos; - if (!emmc) - { - lbl_emu = lv_label_create(h1, lbl_hos); - lv_label_set_static_text(lbl_emu, "#FF3C28 "SYMBOL_DOT" emuMMC (RAW):#"); - lv_obj_align(lbl_emu, lbl_hos, LV_ALIGN_OUT_BOTTOM_LEFT, 0, LV_DPI / 3); + lv_coord_t spacing; + if(drive == DRIVE_EMMC){ + if(has_hos_os){ + // adjust spacing when we have 5 sliders + spacing = (LV_DPI / 3) - (lv_obj_get_height(lbl_hos_os) + LV_DPI / 3) / 3; + }else{ + spacing = (LV_DPI / 3) - (lv_obj_get_height(lbl_hos_os) + LV_DPI / 3) / 4; + } + }else{ + spacing = LV_DPI / 3; } + + lv_obj_t *lbl_hos = lv_label_create(h1, NULL); + lv_label_set_recolor(lbl_hos, true); + lv_label_set_static_text(lbl_hos, "#96FF00 "SYMBOL_DOT" HOS (FAT32):#"); + lv_obj_align(lbl_hos, has_hos_os ? lbl_hos_os : bar_hos_os, LV_ALIGN_OUT_BOTTOM_LEFT, 0, has_hos_os ? spacing : LV_DPI / 2); + + lv_obj_t *lbl_emu = lv_label_create(h1, lbl_hos); + lv_label_set_static_text(lbl_emu, "#FF3C28 "SYMBOL_DOT" emuMMC (RAW):#"); + lv_obj_align(lbl_emu, lbl_hos, LV_ALIGN_OUT_BOTTOM_LEFT, 0, spacing); lv_obj_t *lbl_l4t = lv_label_create(h1, lbl_hos); lv_label_set_static_text(lbl_l4t, "#00DDFF "SYMBOL_DOT" Linux (EXT4):#"); - lv_obj_align(lbl_l4t, lbl_emu, LV_ALIGN_OUT_BOTTOM_LEFT, 0, LV_DPI / 3); + lv_obj_align(lbl_l4t, lbl_emu, LV_ALIGN_OUT_BOTTOM_LEFT, 0, spacing); lv_obj_t *lbl_and = lv_label_create(h1, lbl_hos); lv_label_set_static_text(lbl_and, "#FF8000 "SYMBOL_DOT" Android (USER):#"); - lv_obj_align(lbl_and, lbl_l4t, LV_ALIGN_OUT_BOTTOM_LEFT, 0, LV_DPI / 3); + lv_obj_align(lbl_and, lbl_l4t, LV_ALIGN_OUT_BOTTOM_LEFT, 0, spacing); + + + // Create HOS OS size slider + lv_obj_t *slider_hos_os = lv_slider_create(h1, NULL); + lv_obj_set_size(slider_hos_os, LV_DPI * 7, LV_DPI / 3); + lv_slider_set_range(slider_hos_os, 0, (part_info.total_sct_available - extra_sct - (part_info.hos_sys_size_mb << 10)) / SECTORS_PER_GB); + lv_slider_set_value(slider_hos_os, (part_info.hos_os_size - part_info.hos_sys_size_mb) >> 10); + lv_slider_set_style(slider_hos_os, LV_SLIDER_STYLE_BG, &bar_hos_os_bg); + lv_slider_set_style(slider_hos_os, LV_SLIDER_STYLE_INDIC, &bar_hos_os_ind); + lv_slider_set_style(slider_hos_os, LV_SLIDER_STYLE_KNOB, &bar_hos_os_btn); + lv_obj_align(slider_hos_os, lbl_hos_os, LV_ALIGN_IN_LEFT_MID, LV_DPI * 3, 0); + lv_slider_set_action(slider_hos_os, _action_slider_hos_os); + lv_obj_set_hidden(slider_hos_os, !has_hos_os); + part_info.slider_hos_os = slider_hos_os; // Create HOS size slider. Non-interactive. - lv_obj_t *slider_bar_hos = lv_bar_create(h1, NULL); - lv_obj_set_size(slider_bar_hos, LV_DPI * 7, LV_DPI * 3 / 17); - lv_bar_set_range(slider_bar_hos, 0, (part_info.total_sct - AU_ALIGN_SECTORS) / SECTORS_PER_GB); - lv_bar_set_value(slider_bar_hos, (part_info.total_sct - AU_ALIGN_SECTORS) / SECTORS_PER_GB); - lv_bar_set_style(slider_bar_hos, LV_SLIDER_STYLE_BG, &bar_hos_bg); - lv_bar_set_style(slider_bar_hos, LV_SLIDER_STYLE_INDIC, &bar_hos_ind); - lv_obj_align(slider_bar_hos, cont_lbl_hos, LV_ALIGN_OUT_RIGHT_MID, LV_DPI, 0); - part_info.slider_bar_hos = slider_bar_hos; - - lv_obj_t *slider_emu = slider_bar_hos; - if (!emmc) - { - // Create emuMMC size slider. - slider_emu = lv_slider_create(h1, NULL); - lv_obj_set_size(slider_emu, LV_DPI * 7, LV_DPI / 3); - lv_slider_set_range(slider_emu, EMU_SLIDER_MIN, EMU_SLIDER_MAX); - lv_slider_set_value(slider_emu, EMU_SLIDER_MIN); - lv_slider_set_style(slider_emu, LV_SLIDER_STYLE_BG, &bar_emu_bg); - lv_slider_set_style(slider_emu, LV_SLIDER_STYLE_INDIC, &bar_emu_ind); - lv_slider_set_style(slider_emu, LV_SLIDER_STYLE_KNOB, &bar_emu_btn); - lv_obj_align(slider_emu, slider_bar_hos, LV_ALIGN_OUT_BOTTOM_LEFT, 0, LV_DPI / 3 + 5); - lv_slider_set_action(slider_emu, _action_slider_emu); + lv_obj_t *slider_hos; + if(drive == DRIVE_EMMC){ + // Allow adjustment of fat partition on emmc + slider_hos = lv_slider_create(h1, NULL); + lv_obj_set_size(slider_hos, LV_DPI * 7, LV_DPI / 3); + lv_slider_set_style(slider_hos, LV_SLIDER_STYLE_KNOB, &bar_hos_btn); + lv_slider_set_action(slider_hos, _action_slider_hos); + }else{ + slider_hos = lv_bar_create(h1, NULL); + lv_obj_set_size(slider_hos, LV_DPI * 7, LV_DPI * 3 / 17); } + lv_bar_set_range(slider_hos, 0, (part_info.total_sct_available - extra_sct) / SECTORS_PER_GB); + lv_bar_set_value(slider_hos, part_info.hos_size >> 10); + lv_bar_set_style(slider_hos, LV_SLIDER_STYLE_BG, &bar_hos_bg); + lv_bar_set_style(slider_hos, LV_SLIDER_STYLE_INDIC, &bar_hos_ind); + lv_obj_align(slider_hos, lbl_hos, LV_ALIGN_IN_LEFT_MID, LV_DPI * 3, 0); + + part_info.slider_bar_hos = slider_hos; + + // Create emuMMC size slider. + lv_obj_t *slider_emu = lv_slider_create(h1, NULL); + lv_obj_set_size(slider_emu, LV_DPI * 7, LV_DPI / 3); + lv_slider_set_range(slider_emu, 0, ((part_info.total_sct_available - extra_sct) / SECTORS_PER_GB) * 2); + lv_slider_set_value(slider_emu, part_info.emu_size >> 10); + lv_slider_set_style(slider_emu, LV_SLIDER_STYLE_BG, &bar_emu_bg); + lv_slider_set_style(slider_emu, LV_SLIDER_STYLE_INDIC, &bar_emu_ind); + lv_slider_set_style(slider_emu, LV_SLIDER_STYLE_KNOB, &bar_emu_btn); + lv_obj_align(slider_emu, lbl_emu, LV_ALIGN_IN_LEFT_MID, LV_DPI * 3,0); + lv_slider_set_action(slider_emu, _action_slider_emu); + part_info.slider_emu = slider_hos; // Create L4T size slider. lv_obj_t *slider_l4t = lv_slider_create(h1, NULL); lv_obj_set_size(slider_l4t, LV_DPI * 7, LV_DPI / 3); - lv_slider_set_range(slider_l4t, 0, (part_info.total_sct - extra_sct) / SECTORS_PER_GB); - lv_slider_set_value(slider_l4t, 0); + lv_slider_set_range(slider_l4t, 0, (part_info.total_sct_available - extra_sct) / SECTORS_PER_GB); + lv_slider_set_value(slider_l4t, part_info.l4t_size >> 10); lv_slider_set_style(slider_l4t, LV_SLIDER_STYLE_BG, &bar_l4t_bg); lv_slider_set_style(slider_l4t, LV_SLIDER_STYLE_INDIC, &bar_l4t_ind); lv_slider_set_style(slider_l4t, LV_SLIDER_STYLE_KNOB, &bar_l4t_btn); - lv_obj_align(slider_l4t, slider_emu, LV_ALIGN_OUT_BOTTOM_LEFT, 0, !emmc ? (LV_DPI / 3 - 3) : (LV_DPI / 3 + 5)); + lv_obj_align(slider_l4t, lbl_l4t, LV_ALIGN_IN_LEFT_MID, LV_DPI * 3, 0); lv_slider_set_action(slider_l4t, _action_slider_l4t); + part_info.slider_l4t = slider_l4t; // Create Android size slider. lv_obj_t *slider_and = lv_slider_create(h1, NULL); lv_obj_set_size(slider_and, LV_DPI * 7, LV_DPI / 3); - lv_slider_set_range(slider_and, 0, (part_info.total_sct - extra_sct) / SECTORS_PER_GB - (AND_SYS_SIZE_MB / 1024)); // Subtract android reserved size. - lv_slider_set_value(slider_and, 0); + #ifdef ENABLE_DUAL_ANDROID + lv_slider_set_range(slider_and, 0, ((part_info.total_sct_available - extra_sct) / SECTORS_PER_GB - (ANDROID_SYSTEM_SIZE_MB / 1024)) * 2); // Subtract android reserved size. + #else + lv_slider_set_range(slider_and, 0, (part_info.total_sct_available - extra_sct) / SECTORS_PER_GB - (ANDROID_SYSTEM_SIZE_MB / 1024)); // Subtract android reserved size. + #endif + lv_slider_set_value(slider_and, part_info.and_size >> 10); lv_slider_set_style(slider_and, LV_SLIDER_STYLE_BG, &bar_and_bg); lv_slider_set_style(slider_and, LV_SLIDER_STYLE_INDIC, &bar_and_ind); lv_slider_set_style(slider_and, LV_SLIDER_STYLE_KNOB, &bar_and_btn); - lv_obj_align(slider_and, slider_l4t, LV_ALIGN_OUT_BOTTOM_LEFT, 0, LV_DPI / 3 - 3); + lv_obj_align(slider_and, lbl_and, LV_ALIGN_IN_LEFT_MID, LV_DPI * 3, 0); lv_slider_set_action(slider_and, _action_slider_and); + part_info.slider_and = slider_and; - // Create container for the labels. - lv_obj_t *cont_lbl = lv_cont_create(h1, NULL); - lv_cont_set_fit(cont_lbl, false, true); - lv_obj_set_width(cont_lbl, LV_DPI * 3 / 2); - part_info.cont_lbl = cont_lbl; + // Create HOS OS size lable + lv_obj_t *lbl_sl_hos_os = lv_label_create(h1, NULL); + lv_label_set_recolor(lbl_sl_hos_os, true); + if(part_info.hos_os_size - part_info.hos_os_align == part_info.hos_os_og_size){ + s_printf(txt_buf, "#E6BF00 %d FULL#", (part_info.hos_os_size - part_info.hos_sys_size_mb) >> 10); + }else{ + s_printf(txt_buf, "#E6BF00 %d GiB#", (part_info.hos_os_size - part_info.hos_sys_size_mb) >> 10); + } + lv_label_set_text(lbl_sl_hos_os, txt_buf); + lv_obj_align(lbl_sl_hos_os, slider_hos_os, LV_ALIGN_OUT_RIGHT_MID, LV_DPI * 4 / 7, 0); + lv_obj_set_hidden(lbl_sl_hos_os, !has_hos_os); + part_info.lbl_hos_os = lbl_sl_hos_os; // Create HOS size label. - lv_obj_t *lbl_sl_hos = lv_label_create(cont_lbl, NULL); + lv_obj_t *lbl_sl_hos = lv_label_create(h1, NULL); lv_label_set_recolor(lbl_sl_hos, true); - lv_label_set_align(lbl_sl_hos, LV_LABEL_ALIGN_RIGHT); - s_printf(txt_buf, "#96FF00 %4d GiB#", (part_info.total_sct - AU_ALIGN_SECTORS) >> 11 >> 10); + s_printf(txt_buf, "#96FF00 %d GiB#", part_info.hos_size >> 10); lv_label_set_text(lbl_sl_hos, txt_buf); - lv_obj_align(lbl_sl_hos, cont_lbl, LV_ALIGN_IN_TOP_RIGHT, 0, 0); + lv_obj_align(lbl_sl_hos, slider_hos, LV_ALIGN_OUT_RIGHT_MID, LV_DPI * 4 / 7, 0); part_info.lbl_hos = lbl_sl_hos; // Create emuMMC size label. - part_info.lbl_emu = lbl_sl_hos; - if (!emmc) - { - lv_obj_t *lbl_sl_emu = lv_label_create(cont_lbl, lbl_sl_hos); - lv_label_set_text(lbl_sl_emu, "#FF3C28 0 GiB#"); - lv_obj_align(lbl_sl_emu, lbl_sl_hos, LV_ALIGN_OUT_BOTTOM_RIGHT, 0, LV_DPI / 3); - part_info.lbl_emu = lbl_sl_emu; - } + lv_obj_t *lbl_sl_emu = lv_label_create(h1, lbl_sl_hos); + lv_label_set_text(lbl_sl_emu, "#FF3C28 0 GiB#"); + lv_obj_align(lbl_sl_emu, slider_emu, LV_ALIGN_OUT_RIGHT_MID, LV_DPI * 4 / 7, 0); + part_info.lbl_emu = lbl_sl_emu; // Create L4T size label. - lv_obj_t *lbl_sl_l4t = lv_label_create(cont_lbl, lbl_sl_hos); - lv_label_set_text(lbl_sl_l4t, "#00DDFF 0 GiB#"); - lv_obj_align(lbl_sl_l4t, part_info.lbl_emu, LV_ALIGN_OUT_BOTTOM_RIGHT, 0, LV_DPI / 3); + lv_obj_t *lbl_sl_l4t = lv_label_create(h1, lbl_sl_hos); + lv_label_set_text(lbl_sl_l4t, "#00DDFF 0 GiB#"); + lv_obj_align(lbl_sl_l4t, slider_l4t, LV_ALIGN_OUT_RIGHT_MID, LV_DPI * 4 / 7, 0); part_info.lbl_l4t = lbl_sl_l4t; // Create Android size label. - lv_obj_t *lbl_sl_and = lv_label_create(cont_lbl, lbl_sl_hos); - lv_label_set_text(lbl_sl_and, "#FF8000 0 GiB#"); - lv_obj_align(lbl_sl_and, lbl_sl_l4t, LV_ALIGN_OUT_BOTTOM_RIGHT, 0, LV_DPI / 3); + lv_obj_t *lbl_sl_and = lv_label_create(h1, lbl_sl_hos); + lv_label_set_text(lbl_sl_and, "#FF8000 0 GiB#"); + lv_obj_align(lbl_sl_and, slider_and, LV_ALIGN_OUT_RIGHT_MID, LV_DPI * 4 / 7, 0); part_info.lbl_and = lbl_sl_and; - lv_obj_align(cont_lbl, bar_hos, LV_ALIGN_OUT_BOTTOM_LEFT, LV_DPI * 11 - LV_DPI / 2, LV_DPI * 9 / 23); - // Set partition manager notes. + const char *sd_notes = + "Note 1: Only up to #C7EA46 1GB# can be backed up. If more, you will be asked to back them manually at the next step.\n" + "Note 2: Resized emuMMC formats the USER partition. A save data manager can be used to move them over.\n" + "Note 3: The #C7EA46 Flash Linux# and #C7EA46 Flash Android# will flash files if suitable partitions and installer files are found.\n"; + + const char *emmc_notes = + "Note 1: Resizing the #C7EA46 HOS USER# partition will format it, setting it to 0 will #C7EA46 remove# HOS from eMMC.\n" + "Note 2: Resized emuMMC formats the USER partition. A save data manager can be used to move them over.\n" + "Note 3: The #C7EA46 Flash Linux# and #C7EA46 Flash Android# will flash files if suitable partitions and installer files are found.\n" + "Note 4: When creating a #C7EA46 FAT32# partition, all unused storage will be assigned to it.\n"; + lv_obj_t *lbl_notes = lv_label_create(h1, NULL); lv_label_set_recolor(lbl_notes, true); + lv_label_set_static_text(lbl_notes, drive == DRIVE_SD ? sd_notes : emmc_notes); lv_label_set_style(lbl_notes, &hint_small_style); - if (!emmc) - { - lv_label_set_static_text(lbl_notes, - "Note 1: Only up to #C7EA46 1.2GB# can be backed up. If more, you will be asked to back them manually at the next step.\n" - "Note 2: Resized emuMMC formats the USER partition. A save data manager can be used to move them over.\n" - "Note 3: The #C7EA46 Flash Linux# and #C7EA46 Flash Android# will flash files if suitable partitions and installer files are found.\n"); - lv_obj_align(lbl_notes, lbl_and, LV_ALIGN_OUT_BOTTOM_LEFT, 0, LV_DPI / 6 * 2); - } - else - { - lv_label_set_static_text(lbl_notes, - "Note 1: Any partition existing after the selected ones gets removed from the table.\n" - "Note 2: The HOS USER partition gets formatted. A save data manager can be used to move them over.\n" - "Note 3: The #C7EA46 Flash Linux# and #C7EA46 Flash Android# will flash files if suitable partitions and installer files are found.\n"); - lv_obj_align(lbl_notes, lbl_and, LV_ALIGN_OUT_BOTTOM_LEFT, 0, LV_DPI / 6 * 4); - } + lv_obj_align(lbl_notes, lbl_and, LV_ALIGN_OUT_BOTTOM_LEFT, 0, LV_DPI / 5); - lv_obj_t *btn1 = NULL; - lv_obj_t *label_btn = NULL; - if (!emmc) - { - // Create UMS button. - btn1 = lv_btn_create(h1, NULL); - lv_obj_t *label_btn = lv_label_create(btn1, NULL); - lv_btn_set_fit(btn1, true, true); - lv_label_set_static_text(label_btn, SYMBOL_USB" SD UMS"); - lv_obj_align(btn1, h1, LV_ALIGN_IN_TOP_LEFT, 0, LV_DPI * 5); - lv_btn_set_action(btn1, LV_BTN_ACTION_CLICK, _action_part_manager_ums_sd); - } + // Create UMS button. + lv_obj_t *btn1 = lv_btn_create(h1, NULL); + lv_obj_t *label_btn = lv_label_create(btn1, NULL); + lv_btn_set_fit(btn1, true, true); + lv_label_set_static_text(label_btn, drive == DRIVE_SD ? SYMBOL_USB" SD UMS" : SYMBOL_CHIP " eMMC UMS"); + lv_obj_align(btn1, h1, LV_ALIGN_IN_TOP_LEFT, 0, LV_DPI * 5); + lv_btn_set_action(btn1, LV_BTN_ACTION_CLICK, drive == DRIVE_SD ? _action_part_manager_ums_sd : _action_part_manager_ums_emmc); // Create Flash Linux button. btn_flash_l4t = lv_btn_create(h1, NULL); - label_btn = lv_label_create(btn_flash_l4t, NULL); + lv_obj_t *label_btn2 = lv_label_create(btn_flash_l4t, NULL); lv_btn_set_fit(btn_flash_l4t, true, true); - lv_label_set_static_text(label_btn, SYMBOL_DOWNLOAD" Flash Linux"); - if (!emmc) - lv_obj_align(btn_flash_l4t, btn1, LV_ALIGN_OUT_RIGHT_MID, LV_DPI / 3, 0); - else - lv_obj_align(btn_flash_l4t, h1, LV_ALIGN_IN_TOP_LEFT, 0, LV_DPI * 5); + lv_label_set_static_text(label_btn2, SYMBOL_DOWNLOAD" Flash Linux"); + lv_obj_align(btn_flash_l4t, btn1, LV_ALIGN_OUT_RIGHT_MID, LV_DPI / 3, 0); lv_btn_set_action(btn_flash_l4t, LV_BTN_ACTION_CLICK, _action_check_flash_linux); // Disable Flash Linux button if partition not found. @@ -3329,6 +3856,7 @@ lv_res_t create_window_partition_manager(bool emmc) lv_btn_set_state(btn_flash_l4t, LV_BTN_STATE_INA); } + // TODO: check for multiple android slots, if multiple, add another mbox to first select which slot to use int part_type_and = _get_available_android_partition(); // Create Flash Android button. @@ -3350,7 +3878,7 @@ lv_res_t create_window_partition_manager(bool emmc) break; } lv_obj_align(btn_flash_android, btn_flash_l4t, LV_ALIGN_OUT_RIGHT_MID, LV_DPI / 3, 0); - lv_btn_set_action(btn_flash_android, LV_BTN_ACTION_CLICK, _action_flash_android); + lv_btn_set_action(btn_flash_android, LV_BTN_ACTION_CLICK, _action_flash_android_slot_select); // Create next step button. btn1 = lv_btn_create(h1, NULL); @@ -3359,17 +3887,11 @@ lv_res_t create_window_partition_manager(bool emmc) lv_label_set_static_text(label_btn, SYMBOL_SD" Next Step"); lv_obj_align(btn1, h1, LV_ALIGN_IN_TOP_RIGHT, 0, LV_DPI * 5); lv_btn_set_action(btn1, LV_BTN_ACTION_CLICK, _create_mbox_partitioning_next); - part_info.partition_button = btn1; free(txt_buf); + free(gpt); - if (!emmc) - sd_unmount(); - else - emmc_end(); + _update_partition_bar(); return LV_RES_OK; } - -lv_res_t create_window_sd_partition_manager(lv_obj_t *btn) { return create_window_partition_manager(false); } -lv_res_t create_window_emmc_partition_manager(lv_obj_t *btn) { return create_window_partition_manager(true); } diff --git a/nyx/nyx_gui/frontend/gui_tools_partition_manager.h b/nyx/nyx_gui/frontend/gui_tools_partition_manager.h index 960af9cc..f0db70eb 100644 --- a/nyx/nyx_gui/frontend/gui_tools_partition_manager.h +++ b/nyx/nyx_gui/frontend/gui_tools_partition_manager.h @@ -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 diff --git a/nyx/nyx_gui/hos/hos.c b/nyx/nyx_gui/hos/hos.c index e08db65f..3e54cd6e 100644 --- a/nyx/nyx_gui/hos/hos.c +++ b/nyx/nyx_gui/hos/hos.c @@ -23,6 +23,7 @@ #include #include "hos.h" +#include #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; diff --git a/nyx/nyx_gui/hos/pkg1.c b/nyx/nyx_gui/hos/pkg1.c index 5d52300e..4617f63e 100644 --- a/nyx/nyx_gui/hos/pkg1.c +++ b/nyx/nyx_gui/hos/pkg1.c @@ -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. diff --git a/nyx/nyx_gui/hos/pkg1.h b/nyx/nyx_gui/hos/pkg1.h index 4d3ab894..f0b5cb52 100644 --- a/nyx/nyx_gui/hos/pkg1.h +++ b/nyx/nyx_gui/hos/pkg1.h @@ -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]; diff --git a/nyx/nyx_gui/hos/pkg2.c b/nyx/nyx_gui/hos/pkg2.c index 6bc6faa5..48ecf0a8 100644 --- a/nyx/nyx_gui/hos/pkg2.c +++ b/nyx/nyx_gui/hos/pkg2.c @@ -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]; } diff --git a/nyx/nyx_gui/hos/pkg2.h b/nyx/nyx_gui/hos/pkg2.h index 4c12dc38..6b153543 100644 --- a/nyx/nyx_gui/hos/pkg2.h +++ b/nyx/nyx_gui/hos/pkg2.h @@ -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; diff --git a/nyx/nyx_gui/libs/fatfs/diskio.c b/nyx/nyx_gui/libs/fatfs/diskio.c index 1eb38924..355637bb 100644 --- a/nyx/nyx_gui/libs/fatfs/diskio.c +++ b/nyx/nyx_gui/libs/fatfs/diskio.c @@ -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 #include #include #include /* FatFs lower layer API */ +#include +#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; } diff --git a/nyx/nyx_gui/libs/fatfs/ffconf.h b/nyx/nyx_gui/libs/fatfs/ffconf.h index a8170df0..62497c05 100644 --- a/nyx/nyx_gui/libs/fatfs/ffconf.h +++ b/nyx/nyx_gui/libs/fatfs/ffconf.h @@ -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 ---*/ diff --git a/nyx/nyx_gui/nyx.c b/nyx/nyx_gui/nyx.c index a5cc7855..ca33483c 100644 --- a/nyx/nyx_gui/nyx.c +++ b/nyx/nyx_gui/nyx.c @@ -26,6 +26,7 @@ #include #include #include +#include #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() diff --git a/nyx/nyx_gui/storage/sfd.c b/nyx/nyx_gui/storage/sfd.c new file mode 100644 index 00000000..20f75808 --- /dev/null +++ b/nyx/nyx_gui/storage/sfd.c @@ -0,0 +1,86 @@ +#include "sfd.h" +#include +#include +#include +#include +#include + + +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); +} \ No newline at end of file diff --git a/nyx/nyx_gui/storage/sfd.h b/nyx/nyx_gui/storage/sfd.h new file mode 100644 index 00000000..30549f94 --- /dev/null +++ b/nyx/nyx_gui/storage/sfd.h @@ -0,0 +1,16 @@ +#ifndef _SFD_H +#define _SFD_H + +#include +#include + +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 \ No newline at end of file