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