Compare commits
75 Commits
2adefd112c
...
hekate_hos
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e2968c69dc | ||
|
|
bc42579f01 | ||
|
|
335b8b9a94 | ||
|
|
e1e2366684 | ||
|
|
b0690a7280 | ||
|
|
7f0835a548 | ||
|
|
5704004bc8 | ||
|
|
c7e1f5c09f | ||
|
|
50170f7cf2 | ||
|
|
52dba9a5a5 | ||
|
|
db519a454b | ||
|
|
f8436d1247 | ||
|
|
6340881f59 | ||
|
|
8405a86937 | ||
|
|
a3f5e33625 | ||
|
|
cfc2febc1b | ||
|
|
d6fda80057 | ||
|
|
37c8874930 | ||
|
|
37a016122c | ||
|
|
9b95d026f3 | ||
|
|
865b9dc1a4 | ||
|
|
7ebceb78bd | ||
|
|
154ed594fc | ||
|
|
af39c76b3a | ||
|
|
657b895aaf | ||
|
|
52a1e0ba67 | ||
|
|
f3b104e234 | ||
|
|
a5a2235b9d | ||
|
|
4c58708253 | ||
|
|
cbac787cff | ||
|
|
082490deda | ||
|
|
72b0f42514 | ||
|
|
8978ba9e54 | ||
|
|
74833e19e7 | ||
|
|
d5d0f79c38 | ||
|
|
7927cfe818 | ||
|
|
a1f48e858e | ||
|
|
fa561b70a4 | ||
|
|
567f0f66e1 | ||
|
|
b798dd1ef6 | ||
|
|
c91cf80f8b | ||
|
|
dca5df653b | ||
|
|
db08fab876 | ||
|
|
9adca44fe4 | ||
|
|
c202b4afb1 | ||
|
|
814ef14f2d | ||
|
|
eaedec7b6e | ||
|
|
e8addedd2f | ||
|
|
3c6bb75267 | ||
|
|
169c551445 | ||
|
|
7dad628dfc | ||
|
|
8ba90ae55f | ||
|
|
fe61c1a374 | ||
|
|
3412714402 | ||
|
|
2b0591e2b0 | ||
|
|
03b30a23c4 | ||
|
|
4f0bba605f | ||
|
|
4cfbef5062 | ||
|
|
02281fccf1 | ||
|
|
84078e5469 | ||
|
|
805686105d | ||
|
|
eacb4f2844 | ||
|
|
c8da71229a | ||
|
|
1a157a33f6 | ||
|
|
f093c9368b | ||
|
|
9a755b895b | ||
|
|
4c4a63795e | ||
|
|
04dc8d2a86 | ||
|
|
ed4b638545 | ||
|
|
a8a67ee775 | ||
|
|
1e54d538fd | ||
|
|
20487cb8b9 | ||
|
|
8bc14f1043 | ||
|
|
c8acea7ad5 | ||
|
|
3ea4fd81f7 |
27
Makefile
27
Makefile
@@ -35,9 +35,9 @@ OBJS += $(addprefix $(BUILDDIR)/$(TARGET)/, \
|
|||||||
mc.o sdram.o minerva.o \
|
mc.o sdram.o minerva.o \
|
||||||
gpio.o pinmux.o pmc.o se.o smmu.o tsec.o uart.o \
|
gpio.o pinmux.o pmc.o se.o smmu.o tsec.o uart.o \
|
||||||
fuse.o kfuse.o \
|
fuse.o kfuse.o \
|
||||||
sdmmc.o sdmmc_driver.o emmc.o sd.o emummc.o emummc_file_based.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 \
|
bq24193.o max17050.o max7762x.o max77620-rtc.o \
|
||||||
hw_init.o boot_storage.o \
|
hw_init.o boot_storage.o emusd.o file_based_storage.o \
|
||||||
)
|
)
|
||||||
|
|
||||||
# Utilities.
|
# Utilities.
|
||||||
@@ -48,7 +48,7 @@ OBJS += $(addprefix $(BUILDDIR)/$(TARGET)/, \
|
|||||||
|
|
||||||
# Horizon.
|
# Horizon.
|
||||||
OBJS += $(addprefix $(BUILDDIR)/$(TARGET)/, \
|
OBJS += $(addprefix $(BUILDDIR)/$(TARGET)/, \
|
||||||
hos.o hos_config.o pkg1.o pkg2.o pkg2_ini_kippatch.o fss.o secmon_exo.o \
|
hos.o hos_config.o pkg1.o pkg2.o pkg3.o pkg2_ini_kippatch.o secmon_exo.o \
|
||||||
)
|
)
|
||||||
|
|
||||||
# Libraries.
|
# Libraries.
|
||||||
@@ -76,15 +76,15 @@ CUSTOMDEFINES += -DGFX_INC=$(GFX_INC) -DFFCFG_INC=$(FFCFG_INC)
|
|||||||
|
|
||||||
# UART Logging: Max baudrate 12.5M.
|
# UART Logging: Max baudrate 12.5M.
|
||||||
# DEBUG_UART_PORT - 0: UART_A, 1: UART_B, 2: UART_C.
|
# DEBUG_UART_PORT - 0: UART_A, 1: UART_B, 2: UART_C.
|
||||||
#CUSTOMDEFINES += -DDEBUG_UART_BAUDRATE=115200 -DDEBUG_UART_INVERT=0 -DDEBUG_UART_PORT=0
|
#CUSTOMDEFINES += -DDEBUG_UART_BAUDRATE=115200 -DDEBUG_UART_INVERT=0 -DDEBUG_UART_PORT=1
|
||||||
|
|
||||||
#TODO: Considering reinstating some of these when pointer warnings have been fixed.
|
#TODO: Considering reinstating some of these when pointer warnings have been fixed.
|
||||||
WARNINGS := -Wall -Wsign-compare -Wno-array-bounds -Wno-stringop-overread -Wno-stringop-overflow
|
WARNINGS := -Wall -Wsign-compare -Wtype-limits -Wno-array-bounds -Wno-stringop-overread -Wno-stringop-overflow
|
||||||
#-fno-delete-null-pointer-checks
|
#-fno-delete-null-pointer-checks
|
||||||
#-Wstack-usage=byte-size -fstack-usage
|
#-Wstack-usage=byte-size -fstack-usage
|
||||||
|
|
||||||
ARCH := -march=armv4t -mtune=arm7tdmi -mthumb -mthumb-interwork
|
ARCH := -march=armv4t -mtune=arm7tdmi -mthumb -mthumb-interwork $(WARNINGS)
|
||||||
CFLAGS = $(ARCH) -O2 -g -gdwarf-4 -nostdlib -ffunction-sections -fdata-sections -fomit-frame-pointer -fno-inline -std=gnu11 $(WARNINGS) $(CUSTOMDEFINES)
|
CFLAGS = $(ARCH) -O2 -g -gdwarf-4 -nostdlib -ffunction-sections -fdata-sections -fomit-frame-pointer -fno-inline -std=gnu11 $(CUSTOMDEFINES)
|
||||||
LDFLAGS = $(ARCH) -nostartfiles -lgcc -Wl,--nmagic,--gc-sections -Xlinker --defsym=IPL_LOAD_ADDR=$(IPL_LOAD_ADDR)
|
LDFLAGS = $(ARCH) -nostartfiles -lgcc -Wl,--nmagic,--gc-sections -Xlinker --defsym=IPL_LOAD_ADDR=$(IPL_LOAD_ADDR)
|
||||||
|
|
||||||
MODULEDIRS := $(wildcard modules/*)
|
MODULEDIRS := $(wildcard modules/*)
|
||||||
@@ -101,15 +101,14 @@ TOOLS := $(TOOLSLZ) $(TOOLSB2C)
|
|||||||
all: $(TARGET).bin $(LDRDIR)
|
all: $(TARGET).bin $(LDRDIR)
|
||||||
@printf ICTC49 >> $(OUTPUTDIR)/$(TARGET).bin
|
@printf ICTC49 >> $(OUTPUTDIR)/$(TARGET).bin
|
||||||
@echo "--------------------------------------"
|
@echo "--------------------------------------"
|
||||||
@echo -n "Uncompr size: "
|
@echo "$(TARGET) size:"
|
||||||
|
@echo -n "Uncompr: "
|
||||||
$(eval BIN_SIZE = $(shell wc -c < $(OUTPUTDIR)/$(TARGET)_unc.bin))
|
$(eval BIN_SIZE = $(shell wc -c < $(OUTPUTDIR)/$(TARGET)_unc.bin))
|
||||||
@echo $(BIN_SIZE)" Bytes"
|
@echo $(BIN_SIZE)" Bytes"
|
||||||
@echo "Uncompr Max: 140288 Bytes + 3 KiB BSS"
|
|
||||||
@if [ ${BIN_SIZE} -gt 140288 ]; then echo "\e[1;33mUncompr size exceeds limit!\e[0m"; fi
|
@if [ ${BIN_SIZE} -gt 140288 ]; then echo "\e[1;33mUncompr size exceeds limit!\e[0m"; fi
|
||||||
@echo -n "Payload size: "
|
@echo -n "Payload: "
|
||||||
$(eval BIN_SIZE = $(shell wc -c < $(OUTPUTDIR)/$(TARGET).bin))
|
$(eval BIN_SIZE = $(shell wc -c < $(OUTPUTDIR)/$(TARGET).bin))
|
||||||
@echo $(BIN_SIZE)" Bytes"
|
@echo $(BIN_SIZE)" Bytes"
|
||||||
@echo "Payload Max: 126296 Bytes"
|
|
||||||
@if [ ${BIN_SIZE} -gt 126296 ]; then echo "\e[1;33mPayload size exceeds limit!\e[0m"; fi
|
@if [ ${BIN_SIZE} -gt 126296 ]; then echo "\e[1;33mPayload size exceeds limit!\e[0m"; fi
|
||||||
@echo "--------------------------------------"
|
@echo "--------------------------------------"
|
||||||
|
|
||||||
@@ -126,7 +125,7 @@ $(NYXDIR):
|
|||||||
|
|
||||||
$(LDRDIR): $(TARGET).bin
|
$(LDRDIR): $(TARGET).bin
|
||||||
@$(TOOLSLZ)/lz77 $(OUTPUTDIR)/$(TARGET).bin
|
@$(TOOLSLZ)/lz77 $(OUTPUTDIR)/$(TARGET).bin
|
||||||
mv $(OUTPUTDIR)/$(TARGET).bin $(OUTPUTDIR)/$(TARGET)_unc.bin
|
@mv $(OUTPUTDIR)/$(TARGET).bin $(OUTPUTDIR)/$(TARGET)_unc.bin
|
||||||
@mv $(OUTPUTDIR)/$(TARGET).bin.00.lz payload_00
|
@mv $(OUTPUTDIR)/$(TARGET).bin.00.lz payload_00
|
||||||
@mv $(OUTPUTDIR)/$(TARGET).bin.01.lz payload_01
|
@mv $(OUTPUTDIR)/$(TARGET).bin.01.lz payload_01
|
||||||
@$(TOOLSB2C)/bin2c payload_00 > $(LDRDIR)/payload_00.h
|
@$(TOOLSB2C)/bin2c payload_00 > $(LDRDIR)/payload_00.h
|
||||||
@@ -139,11 +138,11 @@ $(TOOLS):
|
|||||||
@$(MAKE) --no-print-directory -C $@ $(MAKECMDGOALS) -$(MAKEFLAGS)
|
@$(MAKE) --no-print-directory -C $@ $(MAKECMDGOALS) -$(MAKEFLAGS)
|
||||||
|
|
||||||
$(TARGET).bin: $(BUILDDIR)/$(TARGET)/$(TARGET).elf $(MODULEDIRS) $(NYXDIR) $(TOOLS)
|
$(TARGET).bin: $(BUILDDIR)/$(TARGET)/$(TARGET).elf $(MODULEDIRS) $(NYXDIR) $(TOOLS)
|
||||||
$(OBJCOPY) -S -O binary $< $(OUTPUTDIR)/$@
|
@$(OBJCOPY) -S -O binary $< $(OUTPUTDIR)/$@
|
||||||
|
|
||||||
$(BUILDDIR)/$(TARGET)/$(TARGET).elf: $(OBJS)
|
$(BUILDDIR)/$(TARGET)/$(TARGET).elf: $(OBJS)
|
||||||
@$(CC) $(LDFLAGS) -T $(SOURCEDIR)/link.ld $^ -o $@
|
@$(CC) $(LDFLAGS) -T $(SOURCEDIR)/link.ld $^ -o $@
|
||||||
@echo "hekate was built with the following flags:\nCFLAGS: "$(CFLAGS)"\nLDFLAGS: "$(LDFLAGS)
|
@printf "$(TARGET) was built with the following flags:\nCFLAGS: $(CFLAGS)\nLDFLAGS: $(LDFLAGS)\n"
|
||||||
|
|
||||||
$(BUILDDIR)/$(TARGET)/%.o: %.c
|
$(BUILDDIR)/$(TARGET)/%.o: %.c
|
||||||
@echo Building $@
|
@echo Building $@
|
||||||
|
|||||||
46
README.md
46
README.md
@@ -50,13 +50,14 @@ Custom Graphical Nintendo Switch bootloader, firmware patcher, tools, and many m
|
|||||||
| \|__ background.bmp | Nyx - Custom background. User provided. |
|
| \|__ background.bmp | Nyx - Custom background. User provided. |
|
||||||
| \|__ icon_switch.bmp | Nyx - Default icon for CFWs. |
|
| \|__ icon_switch.bmp | Nyx - Default icon for CFWs. |
|
||||||
| \|__ icon_payload.bmp | Nyx - Default icon for Payloads. |
|
| \|__ icon_payload.bmp | Nyx - Default icon for Payloads. |
|
||||||
| bootloader/sys/ | hekate and Nyx system modules folder. |
|
| bootloader/sys/ | hekate and Nyx system modules folder. !Important! |
|
||||||
| \|__ emummc.kipm | emuMMC KIP1 module. !Important! |
|
| \|__ emummc.kipm | emuMMC KIP1 module. |
|
||||||
| \|__ libsys_lp0.bso | LP0 (sleep mode) module. Important! |
|
| \|__ libsys_lp0.bso | LP0 (sleep mode) module. |
|
||||||
| \|__ libsys_minerva.bso | Minerva Training Cell. Used for DRAM Frequency training. !Important! |
|
| \|__ libsys_minerva.bso | Minerva Training Cell. Used for DRAM Frequency training. |
|
||||||
| \|__ nyx.bin | Nyx - hekate's GUI. !Important! |
|
| \|__ nyx.bin | Nyx - hekate's GUI. |
|
||||||
| \|__ res.pak | Nyx resources package. !Important! |
|
| \|__ res.pak | Nyx resources package. |
|
||||||
| \|__ thk.bin | Atmosphère Tsec Hovi Keygen. !Important! |
|
| \|__ thk.bin | Atmosphère Tsec Hovi Keygen. |
|
||||||
|
| \|__ /l4t/ | Folder with firmware relevant to L4T (Linux/Android). |
|
||||||
| bootloader/screenshots/ | Folder where Nyx screenshots are saved |
|
| bootloader/screenshots/ | Folder where Nyx screenshots are saved |
|
||||||
| bootloader/payloads/ | For the `Payloads` menu. All CFW bootloaders, tools, Linux payloads are supported. Autoboot only supported by including them into an ini. |
|
| bootloader/payloads/ | For the `Payloads` menu. All CFW bootloaders, tools, Linux payloads are supported. Autoboot only supported by including them into an ini. |
|
||||||
| bootloader/libtools/ | Reserved |
|
| bootloader/libtools/ | Reserved |
|
||||||
@@ -76,9 +77,9 @@ There are four possible type of entries. "**[ ]**": Boot entry, "**{ }**": Capti
|
|||||||
|
|
||||||
### hekate Global Configuration keys/values (when entry is *[config]*):
|
### hekate Global Configuration keys/values (when entry is *[config]*):
|
||||||
|
|
||||||
| Config option | Description |
|
| Config option | Description |
|
||||||
| ------------------ | ---------------------------------------------------------- |
|
| ------------------ | -------------------------------------------------------------- |
|
||||||
| autoboot=0 | 0: Disable, #: Boot entry number to auto boot. |
|
| autoboot=0 | 0: Disable, #: Boot entry number to auto boot. |
|
||||||
| autoboot_list=0 | 0: Read `autoboot` boot entry from hekate_ipl.ini, 1: Read from ini folder (ini files are ASCII ordered). |
|
| autoboot_list=0 | 0: Read `autoboot` boot entry from hekate_ipl.ini, 1: Read from ini folder (ini files are ASCII ordered). |
|
||||||
| bootwait=3 | 0: Disable (It also disables bootlogo. Having **VOL-** pressed since injection goes to menu.), #: Time to wait for **VOL-** to enter menu. Max: 20s. |
|
| bootwait=3 | 0: Disable (It also disables bootlogo. Having **VOL-** pressed since injection goes to menu.), #: Time to wait for **VOL-** to enter menu. Max: 20s. |
|
||||||
| noticker=0 | 0: Animated line is drawn during custom bootlogo, signifying time left to skip to menu. 1: Disable. |
|
| noticker=0 | 0: Animated line is drawn during custom bootlogo, signifying time left to skip to menu. 1: Disable. |
|
||||||
@@ -86,7 +87,7 @@ There are four possible type of entries. "**[ ]**": Boot entry, "**{ }**": Capti
|
|||||||
| autonogc=1 | 0: Disable, 1: Automatically applies nogc patch if unburnt fuses found and a >= 4.0.0 HOS is booted. |
|
| autonogc=1 | 0: Disable, 1: Automatically applies nogc patch if unburnt fuses found and a >= 4.0.0 HOS is booted. |
|
||||||
| bootprotect=0 | 0: Disable, 1: Protect bootloader folder from being corrupted by disallowing reading or editing in HOS. |
|
| bootprotect=0 | 0: Disable, 1: Protect bootloader folder from being corrupted by disallowing reading or editing in HOS. |
|
||||||
| updater2p=0 | 0: Disable, 1: Force updates (if needed) the reboot2payload binary to be hekate. |
|
| updater2p=0 | 0: Disable, 1: Force updates (if needed) the reboot2payload binary to be hekate. |
|
||||||
| backlight=100 | Screen backlight level. 0-255. |
|
| backlight=100 | Screen backlight level. 0-255. |
|
||||||
|
|
||||||
|
|
||||||
### Boot entry key/value combinations:
|
### Boot entry key/value combinations:
|
||||||
@@ -98,18 +99,20 @@ There are four possible type of entries. "**[ ]**": Boot entry, "**{ }**": Capti
|
|||||||
| kernel={FILE path} | Replaces the kernel binary |
|
| kernel={FILE path} | Replaces the kernel binary |
|
||||||
| kip1={FILE path} | Replaces/Adds kernel initial process. Multiple can be set. |
|
| kip1={FILE path} | Replaces/Adds kernel initial process. Multiple can be set. |
|
||||||
| kip1={FOLDER path}/* | Loads every .kip/.kip1 inside a folder. Compatible with single kip1 keys. |
|
| kip1={FOLDER path}/* | Loads every .kip/.kip1 inside a folder. Compatible with single kip1 keys. |
|
||||||
| fss0={FILE path} | Takes an Atmosphere `package3` binary (formerly fusee-secondary.bin) and `extracts` all needed parts from it. kips, exosphere, warmboot and mesophere if enabled. |
|
| pkg3={FILE path} | Takes an Atmosphere `package3` binary and `extracts` all needed parts from it. kips, exosphere, warmboot and mesophere. |
|
||||||
| fss0experimental=1 | Enables loading of experimental content from a FSS0 storage |
|
| fss0={FILE path} | Same as above. !Deprecated! |
|
||||||
|
| pkg3ex=1 | Enables loading of experimental content from a PKG3/FSS0 storage |
|
||||||
|
| pkg3kip1skip={KIP name} | Skips loading a kip from `pkg3`/`fss0`. Allows multiple and `,` as separator. The name must exactly match the name in `PKG3`. |
|
||||||
| exofatal={FILE path} | Replaces the exosphere fatal binary for Mariko |
|
| exofatal={FILE path} | Replaces the exosphere fatal binary for Mariko |
|
||||||
| ---------------------- | ---------------------------------------------------------- |
|
| ---------------------- | ---------------------------------------------------------- |
|
||||||
| kip1patch=patchname | Enables a kip1 patch. Specify with multiple lines and/or in one line with `,` as separator. If actual patch is not found, a warning will show up |
|
| kip1patch=patchname | Enables a kip1 patch. Allows multiple and `,` as separator. If actual patch is not found, a warning will show up. |
|
||||||
| emupath={FOLDER path} | Forces emuMMC to use the selected one. (=emuMMC/RAW1, =emuMMC/SD00, etc). emuMMC must be created by hekate because it uses the raw_based/file_based files. |
|
| emupath={FOLDER path} | Forces emuMMC to use the selected one. (=emuMMC/RAW1, =emuMMC/SD00, etc). emuMMC must be created by hekate because it uses the raw_based/file_based files. |
|
||||||
| emummcforce=1 | Forces the use of emuMMC. If emummc.ini is disabled or not found, then it causes an error. |
|
| emummcforce=1 | Forces the use of emuMMC. If emummc.ini is disabled or not found, then it causes an error. |
|
||||||
| emummc_force_disable=1 | Disables emuMMC, if it's enabled. |
|
| emummc_force_disable=1 | Disables emuMMC, if it's enabled. |
|
||||||
| stock=1 | OFW via hekate bootloader. Disables unneeded kernel patching and CFW kips when running stock. `If emuMMC is enabled, emummc_force_disable=1` is required. emuMMC is not supported on stock. If additional KIPs are needed other than OFW's, you can define them with `kip1` key. No kip should be used that relies on Atmosphère patching, because it will hang. If `NOGC` is needed, use `kip1patch=nogc`. |
|
| stock=1 | OFW via hekate bootloader. Disables unneeded kernel patching and CFW kips when running stock. `If emuMMC is enabled, emummc_force_disable=1` is required. emuMMC is not supported on stock. If additional KIPs are needed other than OFW's, you can define them with `kip1` key. No kip should be used that relies on Atmosphère patching, because it will hang. If `NOGC` is needed, use `kip1patch=nogc`. |
|
||||||
| fullsvcperm=1 | Disables SVC verification (full services permission). Doesn't work with Mesosphere as kernel. |
|
| fullsvcperm=1 | Disables SVC verification (full services permission). Doesn't work with Mesosphere as kernel. |
|
||||||
| debugmode=1 | Enables Debug mode. Obsolete when used with exosphere as secmon. |
|
| debugmode=1 | Enables Debug mode. Obsolete when used with exosphere as secmon. |
|
||||||
| atmosphere=1 | Enables Atmosphère patching. Not needed when `fss0` is used. |
|
| kernelprocid=1 | Enables stock kernel process id send/recv patching. Not needed when `pkg3`/`fss0` is used. |
|
||||||
| ---------------------- | ---------------------------------------------------------- |
|
| ---------------------- | ---------------------------------------------------------- |
|
||||||
| payload={FILE path} | Payload launching. Tools, Android/Linux, CFW bootloaders, etc. Any key above when used with that, doesn't get into account. |
|
| payload={FILE path} | Payload launching. Tools, Android/Linux, CFW bootloaders, etc. Any key above when used with that, doesn't get into account. |
|
||||||
| ---------------------- | ---------------------------------------------------------- |
|
| ---------------------- | ---------------------------------------------------------- |
|
||||||
@@ -119,6 +122,7 @@ There are four possible type of entries. "**[ ]**": Boot entry, "**{ }**": Capti
|
|||||||
| ram_oc_vdd2=1100 | L4T RAM VDD2 Voltage. Set VDD2 (T210B01) or VDD2/VDDQ (T210) voltage. 1050-1175. |
|
| ram_oc_vdd2=1100 | L4T RAM VDD2 Voltage. Set VDD2 (T210B01) or VDD2/VDDQ (T210) voltage. 1050-1175. |
|
||||||
| ram_oc_vddq=600 | L4T RAM VDDQ Voltage. Set VDDQ (T210B01). 550-650. |
|
| ram_oc_vddq=600 | L4T RAM VDDQ Voltage. Set VDDQ (T210B01). 550-650. |
|
||||||
| uart_port=0 | Enables logging on serial port for L4T uboot/kernel. |
|
| uart_port=0 | Enables logging on serial port for L4T uboot/kernel. |
|
||||||
|
| sld_type=0x31444C53 | Controls the type of seamless display support. 0x0: Disable, 0x31444C53: L4T seamless display. |
|
||||||
| Additional keys | Each distro supports more keys. Check README_CONFIG.txt for more info. |
|
| Additional keys | Each distro supports more keys. Check README_CONFIG.txt for more info. |
|
||||||
| ---------------------- | ---------------------------------------------------------- |
|
| ---------------------- | ---------------------------------------------------------- |
|
||||||
| bootwait=3 | Overrides global bootwait from `[config]`. |
|
| bootwait=3 | Overrides global bootwait from `[config]`. |
|
||||||
@@ -129,11 +133,11 @@ There are four possible type of entries. "**[ ]**": Boot entry, "**{ }**": Capti
|
|||||||
|
|
||||||
**Note1**: When using the wildcard (`/*`) with `kip1` you can still use the normal `kip1` after that to load extra single kips.
|
**Note1**: When using the wildcard (`/*`) with `kip1` you can still use the normal `kip1` after that to load extra single kips.
|
||||||
|
|
||||||
**Note2**: When using FSS0 it parses exosphere, warmboot and all core kips. You can override the first 2 by using `secmon`/`warmboot` after defining `fss0`.
|
**Note2**: When using PKG3/FSS0 it parses exosphere, warmboot and all core kips. You can override the first 2 by using `secmon`/`warmboot` after defining `pkg3`/`fss0`.
|
||||||
You can define `kip1` to load an extra kip or many via the wildcard (`/*`) usage.
|
You can define `kip1` to load an extra kip or many via the wildcard (`/*`) usage.
|
||||||
|
|
||||||
**Warning**: Careful when you define *fss0 core* kips when using `fss0` or the folder (when using `/*`) includes them.
|
**Warning**: Careful when you override *pkg3/fss core* kips with `kip1`.
|
||||||
This is in case the kips are incompatible between them. If compatible, you can override `fss0` kips with no issues (useful for testing with intermediate kip changes). In such cases, the `kip1` line must be under `fss0` line.
|
That's in case the kips are incompatible between them. If compatible, you can override `pkg3`/`fss0` kips with no issues (useful for testing with intermediate kip changes). In such cases, the `kip1` line must be **after** `pkg3`/`fss0` line.
|
||||||
|
|
||||||
|
|
||||||
### Boot entry key/value combinations for Exosphère:
|
### Boot entry key/value combinations for Exosphère:
|
||||||
@@ -155,7 +159,7 @@ This is in case the kips are incompatible between them. If compatible, you can o
|
|||||||
|
|
||||||
### Payload storage:
|
### Payload storage:
|
||||||
|
|
||||||
hekate has a boot storage in the binary that helps it configure it outside of BPMP enviroment:
|
hekate has a boot storage in the binary that helps it configure it outside of BPMP environment:
|
||||||
|
|
||||||
| Offset / Name | Description |
|
| Offset / Name | Description |
|
||||||
| ----------------------- | ----------------------------------------------------------------- |
|
| ----------------------- | ----------------------------------------------------------------- |
|
||||||
@@ -188,9 +192,9 @@ hekate has a boot storage in the binary that helps it configure it outside of BP
|
|||||||
|
|
||||||
```
|
```
|
||||||
hekate (c) 2018, naehrwert, st4rk.
|
hekate (c) 2018, naehrwert, st4rk.
|
||||||
(c) 2018-2024, CTCaer.
|
(c) 2018-2025, CTCaer.
|
||||||
|
|
||||||
Nyx GUI (c) 2019-2024, CTCaer.
|
Nyx GUI (c) 2019-2025, CTCaer.
|
||||||
|
|
||||||
Thanks to: derrek, nedwill, plutoo, shuffle2, smea, thexyz, yellows8.
|
Thanks to: derrek, nedwill, plutoo, shuffle2, smea, thexyz, yellows8.
|
||||||
Greetings to: fincs, hexkyz, SciresM, Shiny Quagsire, WinterMute.
|
Greetings to: fincs, hexkyz, SciresM, Shiny Quagsire, WinterMute.
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
# IPL Version.
|
# IPL Version.
|
||||||
BLVERSION_MAJOR := 6
|
BLVERSION_MAJOR := 6
|
||||||
BLVERSION_MINOR := 2
|
BLVERSION_MINOR := 3
|
||||||
BLVERSION_HOTFX := 2
|
BLVERSION_HOTFX := 1
|
||||||
BLVERSION_REL := 0
|
BLVERSION_REL := 0
|
||||||
|
|
||||||
# Nyx Version.
|
# Nyx Version.
|
||||||
NYXVERSION_MAJOR := 1
|
NYXVERSION_MAJOR := 1
|
||||||
NYXVERSION_MINOR := 6
|
NYXVERSION_MINOR := 7
|
||||||
NYXVERSION_HOTFX := 4
|
NYXVERSION_HOTFX := 0
|
||||||
NYXVERSION_REL := 0
|
NYXVERSION_REL := 0
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2018 naehrwert
|
* Copyright (c) 2018 naehrwert
|
||||||
* Copyright (c) 2018-2024 CTCaer
|
* Copyright (c) 2018-2025 CTCaer
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
* under the terms and conditions of the GNU General Public License,
|
* under the terms and conditions of the GNU General Public License,
|
||||||
@@ -37,8 +37,8 @@
|
|||||||
extern volatile nyx_storage_t *nyx_str;
|
extern volatile nyx_storage_t *nyx_str;
|
||||||
|
|
||||||
static u32 _display_id = 0;
|
static u32 _display_id = 0;
|
||||||
static u32 _dsi_bl = -1;
|
static u32 _dsi_bl = -1;
|
||||||
static bool _nx_aula = false;
|
static bool _nx_aula = false;
|
||||||
|
|
||||||
static void _display_panel_and_hw_end(bool no_panel_deinit);
|
static void _display_panel_and_hw_end(bool no_panel_deinit);
|
||||||
|
|
||||||
@@ -265,16 +265,9 @@ int display_dsi_vblank_read(u8 cmd, u32 len, void *data)
|
|||||||
|
|
||||||
void display_dsi_write(u8 cmd, u32 len, void *data)
|
void display_dsi_write(u8 cmd, u32 len, void *data)
|
||||||
{
|
{
|
||||||
static u8 *fifo8 = NULL;
|
|
||||||
static u32 *fifo32 = NULL;
|
|
||||||
u32 host_control;
|
u32 host_control;
|
||||||
|
u32 fifo32[DSI_STATUS_TX_FIFO_SIZE] = {0};
|
||||||
// Allocate fifo buffer.
|
u8 *fifo8 = (u8 *)fifo32;
|
||||||
if (!fifo32)
|
|
||||||
{
|
|
||||||
fifo32 = malloc(DSI_STATUS_RX_FIFO_SIZE * 8 * sizeof(u32));
|
|
||||||
fifo8 = (u8 *)fifo32;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Prepare data for long write.
|
// Prepare data for long write.
|
||||||
if (len >= 2)
|
if (len >= 2)
|
||||||
@@ -319,15 +312,8 @@ void display_dsi_write(u8 cmd, u32 len, void *data)
|
|||||||
|
|
||||||
void display_dsi_vblank_write(u8 cmd, u32 len, void *data)
|
void display_dsi_vblank_write(u8 cmd, u32 len, void *data)
|
||||||
{
|
{
|
||||||
static u8 *fifo8 = NULL;
|
u32 fifo32[DSI_STATUS_TX_FIFO_SIZE] = {0};
|
||||||
static u32 *fifo32 = NULL;
|
u8 *fifo8 = (u8 *)fifo32;
|
||||||
|
|
||||||
// Allocate fifo buffer.
|
|
||||||
if (!fifo32)
|
|
||||||
{
|
|
||||||
fifo32 = malloc(DSI_STATUS_RX_FIFO_SIZE * 8 * sizeof(u32));
|
|
||||||
fifo8 = (u8 *)fifo32;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Prepare data for long write.
|
// Prepare data for long write.
|
||||||
if (len >= 2)
|
if (len >= 2)
|
||||||
@@ -571,7 +557,7 @@ void display_init()
|
|||||||
* When switching to the 16ff pad brick, the clock lane termination control
|
* When switching to the 16ff pad brick, the clock lane termination control
|
||||||
* is separated from data lane termination. This change of the mipi cal
|
* is separated from data lane termination. This change of the mipi cal
|
||||||
* brings in a bug that the DSI pad clock termination code can't be loaded
|
* brings in a bug that the DSI pad clock termination code can't be loaded
|
||||||
* in one time calibration. Trigger calibration twice.
|
* in one time calibration on T210B01. Trigger calibration twice.
|
||||||
*/
|
*/
|
||||||
reg_write_array((u32 *)MIPI_CAL_BASE, _di_mipi_pad_cal_config, ARRAY_SIZE(_di_mipi_pad_cal_config));
|
reg_write_array((u32 *)MIPI_CAL_BASE, _di_mipi_pad_cal_config, ARRAY_SIZE(_di_mipi_pad_cal_config));
|
||||||
for (u32 i = 0; i < 2; i++)
|
for (u32 i = 0; i < 2; i++)
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2018 naehrwert
|
* Copyright (c) 2018 naehrwert
|
||||||
* Copyright (c) 2018-2024 CTCaer
|
* Copyright (c) 2018-2025 CTCaer
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
* under the terms and conditions of the GNU General Public License,
|
* under the terms and conditions of the GNU General Public License,
|
||||||
@@ -520,6 +520,7 @@
|
|||||||
|
|
||||||
#define DSI_STATUS 0x15
|
#define DSI_STATUS 0x15
|
||||||
#define DSI_STATUS_RX_FIFO_SIZE 0x1F
|
#define DSI_STATUS_RX_FIFO_SIZE 0x1F
|
||||||
|
#define DSI_STATUS_TX_FIFO_SIZE 0x20 // Actual depth is 64.
|
||||||
|
|
||||||
#define DSI_INIT_SEQ_CONTROL 0x1A
|
#define DSI_INIT_SEQ_CONTROL 0x1A
|
||||||
#define DSI_INIT_SEQ_DATA_0 0x1B
|
#define DSI_INIT_SEQ_DATA_0 0x1B
|
||||||
@@ -717,7 +718,7 @@
|
|||||||
#define MIPI_DCS_READ_DDB_CONTINUE 0xA8 // 0x100 size.
|
#define MIPI_DCS_READ_DDB_CONTINUE 0xA8 // 0x100 size.
|
||||||
|
|
||||||
/*! MIPI DCS Panel Private CMDs. */
|
/*! MIPI DCS Panel Private CMDs. */
|
||||||
#define MIPI_DCS_PRIV_SM_SET_COLOR_MODE 0xA0
|
#define MIPI_DCS_PRIV_SM_SET_COLOR_MODE 0xA0 // 43 bytes.
|
||||||
#define MIPI_DCS_PRIV_SM_SET_REG_OFFSET 0xB0
|
#define MIPI_DCS_PRIV_SM_SET_REG_OFFSET 0xB0
|
||||||
#define MIPI_DCS_PRIV_SM_SET_ELVSS 0xB1 // OLED backlight tuning. Byte7: PWM transition time in frames.
|
#define MIPI_DCS_PRIV_SM_SET_ELVSS 0xB1 // OLED backlight tuning. Byte7: PWM transition time in frames.
|
||||||
#define MIPI_DCS_PRIV_SET_POWER_CONTROL 0xB1
|
#define MIPI_DCS_PRIV_SET_POWER_CONTROL 0xB1
|
||||||
@@ -727,6 +728,7 @@
|
|||||||
#define MIPI_DCS_PRIV_UNK_D6 0xD6
|
#define MIPI_DCS_PRIV_UNK_D6 0xD6
|
||||||
#define MIPI_DCS_PRIV_UNK_D8 0xD8
|
#define MIPI_DCS_PRIV_UNK_D8 0xD8
|
||||||
#define MIPI_DCS_PRIV_UNK_D9 0xD9
|
#define MIPI_DCS_PRIV_UNK_D9 0xD9
|
||||||
|
#define MIPI_DCS_PRIV_SM_DISPLAY_ID 0xDD
|
||||||
// LVL1 LVL2 LVL3 UNK0 UNK1
|
// LVL1 LVL2 LVL3 UNK0 UNK1
|
||||||
#define MIPI_DCS_PRIV_SM_SET_REGS_LOCK 0xE2 // Samsung: Lock (default): 5A5A A5A5 A5A5 A500 A500. Unlock: A5A5 5A5A 5A5A UNK UNK.
|
#define MIPI_DCS_PRIV_SM_SET_REGS_LOCK 0xE2 // Samsung: Lock (default): 5A5A A5A5 A5A5 A500 A500. Unlock: A5A5 5A5A 5A5A UNK UNK.
|
||||||
#define MIPI_DCS_PRIV_READ_EXTC_CMD_SPI 0xFE // Read EXTC Command In SPI. 1 byte. 0-6: EXT_SPI_CNT, 7:EXT_SP.
|
#define MIPI_DCS_PRIV_READ_EXTC_CMD_SPI 0xFE // Read EXTC Command In SPI. 1 byte. 0-6: EXT_SPI_CNT, 7:EXT_SP.
|
||||||
@@ -765,19 +767,21 @@
|
|||||||
|
|
||||||
#define DCS_CONTROL_DISPLAY_SM_FLASHLIGHT BIT(2)
|
#define DCS_CONTROL_DISPLAY_SM_FLASHLIGHT BIT(2)
|
||||||
#define DCS_CONTROL_DISPLAY_BACKLIGHT_CTRL BIT(2)
|
#define DCS_CONTROL_DISPLAY_BACKLIGHT_CTRL BIT(2)
|
||||||
#define DCS_CONTROL_DISPLAY_DIMMING_CTRL BIT(3)
|
#define DCS_CONTROL_DISPLAY_DIMMING_CTRL BIT(3) // Transition fading.
|
||||||
#define DCS_CONTROL_DISPLAY_BRIGHTNESS_CTRL BIT(5)
|
#define DCS_CONTROL_DISPLAY_BRIGHTNESS_CTRL BIT(5)
|
||||||
|
#define DCS_CONTROL_DISPLAY_HBM_CTRL0 BIT(6)
|
||||||
|
#define DCS_CONTROL_DISPLAY_HBM_CTRL1 BIT(7)
|
||||||
|
|
||||||
#define DCS_SM_COLOR_MODE_SATURATED 0x00 // Disabled. Similar to vivid but over-saturated. Wide gamut?
|
#define DCS_SM_COLOR_MODE_SATURATED 0x00 // Disabled. Based on Vivid but over-saturated.
|
||||||
#define DCS_SM_COLOR_MODE_WASHED 0x45
|
#define DCS_SM_COLOR_MODE_WASHED 0x45
|
||||||
#define DCS_SM_COLOR_MODE_BASIC 0x03
|
#define DCS_SM_COLOR_MODE_BASIC 0x03 // Real natural profile.
|
||||||
#define DCS_SM_COLOR_MODE_POR_RESET 0x20 // Reset value on power on.
|
#define DCS_SM_COLOR_MODE_POR_RESET 0x20 // Reset value on power on.
|
||||||
#define DCS_SM_COLOR_MODE_NATURAL 0x23 // Not actually natural..
|
#define DCS_SM_COLOR_MODE_NATURAL 0x23 // Not actually natural.. Extra saturation.
|
||||||
#define DCS_SM_COLOR_MODE_VIVID 0x65
|
#define DCS_SM_COLOR_MODE_VIVID 0x65 // Saturated.
|
||||||
#define DCS_SM_COLOR_MODE_NIGHT0 0x43 // Based on washed out.
|
#define DCS_SM_COLOR_MODE_NIGHT0 0x43 // Based on Washed Out.
|
||||||
#define DCS_SM_COLOR_MODE_NIGHT1 0x15 // Based on basic.
|
#define DCS_SM_COLOR_MODE_NIGHT1 0x15 // Based on Basic.
|
||||||
#define DCS_SM_COLOR_MODE_NIGHT2 0x35 // Based on natural.
|
#define DCS_SM_COLOR_MODE_NIGHT2 0x35 // Based on Natural.
|
||||||
#define DCS_SM_COLOR_MODE_NIGHT3 0x75 // Based on vivid.
|
#define DCS_SM_COLOR_MODE_NIGHT3 0x75 // Based on Vivid.
|
||||||
|
|
||||||
#define DCS_SM_COLOR_MODE_ENABLE BIT(0)
|
#define DCS_SM_COLOR_MODE_ENABLE BIT(0)
|
||||||
|
|
||||||
|
|||||||
@@ -70,8 +70,6 @@ void set_als_cfg(als_ctxt_t *als_ctxt, u8 gain, u8 cycle)
|
|||||||
|
|
||||||
if (!cycle)
|
if (!cycle)
|
||||||
cycle = 1;
|
cycle = 1;
|
||||||
else if (cycle > 255)
|
|
||||||
cycle = 255;
|
|
||||||
|
|
||||||
i2c_send_byte(I2C_2, BH1730_I2C_ADDR, BH1730_ADDR(BH1730_GAIN_REG), gain);
|
i2c_send_byte(I2C_2, BH1730_I2C_ADDR, BH1730_ADDR(BH1730_GAIN_REG), gain);
|
||||||
i2c_send_byte(I2C_2, BH1730_I2C_ADDR, BH1730_ADDR(BH1730_TIMING_REG), (256 - cycle));
|
i2c_send_byte(I2C_2, BH1730_I2C_ADDR, BH1730_ADDR(BH1730_TIMING_REG), (256 - cycle));
|
||||||
|
|||||||
@@ -41,8 +41,8 @@
|
|||||||
#include <storage/mbr_gpt.h>
|
#include <storage/mbr_gpt.h>
|
||||||
#include <gfx_utils.h>
|
#include <gfx_utils.h>
|
||||||
|
|
||||||
#define EFSPRINTF(text, ...) print_error(); gfx_printf("%k"text"%k\n", 0xFFFFFF00, 0xFFFFFFFF);
|
// #define EFSPRINTF(text, ...) print_error(); gfx_printf("%k"text"%k\n", 0xFFFFFF00, 0xFFFFFFFF);
|
||||||
//#define EFSPRINTF(...)
|
#define EFSPRINTF(...)
|
||||||
|
|
||||||
/*--------------------------------------------------------------------------
|
/*--------------------------------------------------------------------------
|
||||||
|
|
||||||
@@ -4715,13 +4715,20 @@ FRESULT f_lseek (
|
|||||||
|
|
||||||
DWORD *f_expand_cltbl (
|
DWORD *f_expand_cltbl (
|
||||||
FIL* fp, /* Pointer to the file object */
|
FIL* fp, /* Pointer to the file object */
|
||||||
UINT tblsz, /* Size of table */
|
UINT tblsz, /* Size of table (2 DWORDs + 2 DWORDs per fragment) */
|
||||||
FSIZE_t ofs /* File pointer from top of file */
|
FSIZE_t ofs /* File pointer from top of file */
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
|
* Cluster table structure:
|
||||||
|
* Size (DWORD)
|
||||||
|
* Padding (DWORD)
|
||||||
|
* (Cluster Offset (DWORD) + Sequential clusters (DWORD)) * Fragments
|
||||||
|
*/
|
||||||
if (fp->flag & FA_WRITE) f_lseek(fp, ofs); /* Expand file if write is enabled */
|
if (fp->flag & FA_WRITE) f_lseek(fp, ofs); /* Expand file if write is enabled */
|
||||||
if (!fp->cltbl) { /* Allocate memory for cluster link table */
|
if (!fp->cltbl) { /* Allocate memory for cluster link table */
|
||||||
fp->cltbl = (DWORD *)ff_memalloc(tblsz);
|
fp->cltbl = (DWORD *)ff_memalloc(tblsz);
|
||||||
|
if (!fp->cltbl) return (void *)0;
|
||||||
fp->cltbl[0] = tblsz;
|
fp->cltbl[0] = tblsz;
|
||||||
}
|
}
|
||||||
if (f_lseek(fp, CREATE_LINKMAP)) { /* Create cluster link table */
|
if (f_lseek(fp, CREATE_LINKMAP)) { /* Create cluster link table */
|
||||||
|
|||||||
@@ -29,127 +29,128 @@ int bq24193_get_property(enum BQ24193_reg_prop prop, int *value)
|
|||||||
{
|
{
|
||||||
u8 data;
|
u8 data;
|
||||||
|
|
||||||
switch (prop) {
|
switch (prop)
|
||||||
case BQ24193_InputVoltageLimit: // Input voltage limit (mV).
|
{
|
||||||
data = bq24193_get_reg(BQ24193_InputSource);
|
case BQ24193_InputVoltageLimit: // Input voltage limit (mV).
|
||||||
data = (data & BQ24193_INCONFIG_VINDPM_MASK) >> 3;
|
data = bq24193_get_reg(BQ24193_InputSource);
|
||||||
*value = 0;
|
data = (data & BQ24193_INCONFIG_VINDPM_MASK) >> 3;
|
||||||
*value += ((data >> 0) & 1) ? 80 : 0;
|
*value = 0;
|
||||||
*value += ((data >> 1) & 1) ? 160 : 0;
|
*value += ((data >> 0) & 1) ? 80 : 0;
|
||||||
*value += ((data >> 2) & 1) ? 320 : 0;
|
*value += ((data >> 1) & 1) ? 160 : 0;
|
||||||
*value += ((data >> 3) & 1) ? 640 : 0;
|
*value += ((data >> 2) & 1) ? 320 : 0;
|
||||||
*value += 3880;
|
*value += ((data >> 3) & 1) ? 640 : 0;
|
||||||
|
*value += 3880;
|
||||||
|
break;
|
||||||
|
case BQ24193_InputCurrentLimit: // Input current limit (mA).
|
||||||
|
data = bq24193_get_reg(BQ24193_InputSource);
|
||||||
|
data &= BQ24193_INCONFIG_INLIMIT_MASK;
|
||||||
|
switch (data)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
*value = 100;
|
||||||
break;
|
break;
|
||||||
case BQ24193_InputCurrentLimit: // Input current limit (mA).
|
case 1:
|
||||||
data = bq24193_get_reg(BQ24193_InputSource);
|
*value = 150;
|
||||||
data &= BQ24193_INCONFIG_INLIMIT_MASK;
|
|
||||||
switch (data)
|
|
||||||
{
|
|
||||||
case 0:
|
|
||||||
*value = 100;
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
*value = 150;
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
*value = 500;
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
*value = 900;
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
*value = 1200;
|
|
||||||
break;
|
|
||||||
case 5:
|
|
||||||
*value = 1500;
|
|
||||||
break;
|
|
||||||
case 6:
|
|
||||||
*value = 2000;
|
|
||||||
break;
|
|
||||||
case 7:
|
|
||||||
*value = 3000;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case BQ24193_SystemMinimumVoltage: // Minimum system voltage limit (mV).
|
case 2:
|
||||||
data = bq24193_get_reg(BQ24193_PORConfig);
|
*value = 500;
|
||||||
*value = (data & BQ24193_PORCONFIG_SYSMIN_MASK) >> 1;
|
|
||||||
*value *= 100;
|
|
||||||
*value += 3000;
|
|
||||||
break;
|
break;
|
||||||
case BQ24193_FastChargeCurrentLimit: // Fast charge current limit (mA).
|
case 3:
|
||||||
data = bq24193_get_reg(BQ24193_ChrgCurr);
|
*value = 900;
|
||||||
data = (data & BQ24193_CHRGCURR_ICHG_MASK) >> 2;
|
|
||||||
*value = 0;
|
|
||||||
*value += ((data >> 0) & 1) ? 64 : 0;
|
|
||||||
*value += ((data >> 1) & 1) ? 128 : 0;
|
|
||||||
*value += ((data >> 2) & 1) ? 256 : 0;
|
|
||||||
*value += ((data >> 3) & 1) ? 512 : 0;
|
|
||||||
*value += ((data >> 4) & 1) ? 1024 : 0;
|
|
||||||
*value += ((data >> 5) & 1) ? 2048 : 0;
|
|
||||||
*value += 512;
|
|
||||||
data = bq24193_get_reg(BQ24193_ChrgCurr);
|
|
||||||
data &= BQ24193_CHRGCURR_20PCT_MASK;
|
|
||||||
if (data)
|
|
||||||
*value = *value * 20 / 100; // Fast charge current limit is 20%.
|
|
||||||
break;
|
break;
|
||||||
case BQ24193_ChargeVoltageLimit: // Charge voltage limit (mV).
|
case 4:
|
||||||
data = bq24193_get_reg(BQ24193_ChrgVolt);
|
*value = 1200;
|
||||||
data = (data & BQ24193_CHRGVOLT_VREG) >> 2;
|
|
||||||
*value = 0;
|
|
||||||
*value += ((data >> 0) & 1) ? 16 : 0;
|
|
||||||
*value += ((data >> 1) & 1) ? 32 : 0;
|
|
||||||
*value += ((data >> 2) & 1) ? 64 : 0;
|
|
||||||
*value += ((data >> 3) & 1) ? 128 : 0;
|
|
||||||
*value += ((data >> 4) & 1) ? 256 : 0;
|
|
||||||
*value += ((data >> 5) & 1) ? 512 : 0;
|
|
||||||
*value += 3504;
|
|
||||||
break;
|
break;
|
||||||
case BQ24193_RechargeThreshold: // Recharge voltage threshold less than voltage limit (mV).
|
case 5:
|
||||||
data = bq24193_get_reg(BQ24193_ChrgVolt);
|
*value = 1500;
|
||||||
data &= BQ24193_IRTHERMAL_THERM_MASK;
|
|
||||||
if (data)
|
|
||||||
*value = 300;
|
|
||||||
else
|
|
||||||
*value = 100;
|
|
||||||
break;
|
break;
|
||||||
case BQ24193_ThermalRegulation: // Thermal regulation threshold (oC).
|
case 6:
|
||||||
data = bq24193_get_reg(BQ24193_IRCompThermal);
|
*value = 2000;
|
||||||
data &= BQ24193_IRTHERMAL_THERM_MASK;
|
|
||||||
switch (data)
|
|
||||||
{
|
|
||||||
case 0:
|
|
||||||
*value = 60;
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
*value = 80;
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
*value = 100;
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
*value = 120;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case BQ24193_ChargeStatus: // 0: Not charging, 1: Pre-charge, 2: Fast charging, 3: Charge termination done
|
case 7:
|
||||||
data = bq24193_get_reg(BQ24193_Status);
|
*value = 3000;
|
||||||
*value = (data & BQ24193_STATUS_CHRG_MASK) >> 4;
|
|
||||||
break;
|
break;
|
||||||
case BQ24193_TempStatus: // 0: Normal, 2: Warm, 3: Cool, 5: Cold, 6: Hot.
|
}
|
||||||
data = bq24193_get_reg(BQ24193_FaultReg);
|
break;
|
||||||
*value = data & BQ24193_FAULT_THERM_MASK;
|
case BQ24193_SystemMinimumVoltage: // Minimum system voltage limit (mV).
|
||||||
|
data = bq24193_get_reg(BQ24193_PORConfig);
|
||||||
|
*value = (data & BQ24193_PORCONFIG_SYSMIN_MASK) >> 1;
|
||||||
|
*value *= 100;
|
||||||
|
*value += 3000;
|
||||||
|
break;
|
||||||
|
case BQ24193_FastChargeCurrentLimit: // Fast charge current limit (mA).
|
||||||
|
data = bq24193_get_reg(BQ24193_ChrgCurr);
|
||||||
|
data = (data & BQ24193_CHRGCURR_ICHG_MASK) >> 2;
|
||||||
|
*value = 0;
|
||||||
|
*value += ((data >> 0) & 1) ? 64 : 0;
|
||||||
|
*value += ((data >> 1) & 1) ? 128 : 0;
|
||||||
|
*value += ((data >> 2) & 1) ? 256 : 0;
|
||||||
|
*value += ((data >> 3) & 1) ? 512 : 0;
|
||||||
|
*value += ((data >> 4) & 1) ? 1024 : 0;
|
||||||
|
*value += ((data >> 5) & 1) ? 2048 : 0;
|
||||||
|
*value += 512;
|
||||||
|
data = bq24193_get_reg(BQ24193_ChrgCurr);
|
||||||
|
data &= BQ24193_CHRGCURR_20PCT_MASK;
|
||||||
|
if (data)
|
||||||
|
*value = *value * 20 / 100; // Fast charge current limit is 20%.
|
||||||
|
break;
|
||||||
|
case BQ24193_ChargeVoltageLimit: // Charge voltage limit (mV).
|
||||||
|
data = bq24193_get_reg(BQ24193_ChrgVolt);
|
||||||
|
data = (data & BQ24193_CHRGVOLT_VREG) >> 2;
|
||||||
|
*value = 0;
|
||||||
|
*value += ((data >> 0) & 1) ? 16 : 0;
|
||||||
|
*value += ((data >> 1) & 1) ? 32 : 0;
|
||||||
|
*value += ((data >> 2) & 1) ? 64 : 0;
|
||||||
|
*value += ((data >> 3) & 1) ? 128 : 0;
|
||||||
|
*value += ((data >> 4) & 1) ? 256 : 0;
|
||||||
|
*value += ((data >> 5) & 1) ? 512 : 0;
|
||||||
|
*value += 3504;
|
||||||
|
break;
|
||||||
|
case BQ24193_RechargeThreshold: // Recharge voltage threshold less than voltage limit (mV).
|
||||||
|
data = bq24193_get_reg(BQ24193_ChrgVolt);
|
||||||
|
data &= BQ24193_IRTHERMAL_THERM_MASK;
|
||||||
|
if (data)
|
||||||
|
*value = 300;
|
||||||
|
else
|
||||||
|
*value = 100;
|
||||||
|
break;
|
||||||
|
case BQ24193_ThermalRegulation: // Thermal regulation threshold (oC).
|
||||||
|
data = bq24193_get_reg(BQ24193_IRCompThermal);
|
||||||
|
data &= BQ24193_IRTHERMAL_THERM_MASK;
|
||||||
|
switch (data)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
*value = 60;
|
||||||
break;
|
break;
|
||||||
case BQ24193_DevID: // Dev ID.
|
case 1:
|
||||||
data = bq24193_get_reg(BQ24193_VendorPart);
|
*value = 80;
|
||||||
*value = data & BQ24193_VENDORPART_DEV_MASK;
|
|
||||||
break;
|
break;
|
||||||
case BQ24193_ProductNumber: // Product number.
|
case 2:
|
||||||
data = bq24193_get_reg(BQ24193_VendorPart);
|
*value = 100;
|
||||||
*value = (data & BQ24193_VENDORPART_PN_MASK) >> 3;
|
|
||||||
break;
|
break;
|
||||||
default:
|
case 3:
|
||||||
return -1;
|
*value = 120;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case BQ24193_ChargeStatus: // 0: Not charging, 1: Pre-charge, 2: Fast charging, 3: Charge termination done
|
||||||
|
data = bq24193_get_reg(BQ24193_Status);
|
||||||
|
*value = (data & BQ24193_STATUS_CHRG_MASK) >> 4;
|
||||||
|
break;
|
||||||
|
case BQ24193_TempStatus: // 0: Normal, 2: Warm, 3: Cool, 5: Cold, 6: Hot.
|
||||||
|
data = bq24193_get_reg(BQ24193_FaultReg);
|
||||||
|
*value = data & BQ24193_FAULT_THERM_MASK;
|
||||||
|
break;
|
||||||
|
case BQ24193_DevID: // Dev ID.
|
||||||
|
data = bq24193_get_reg(BQ24193_VendorPart);
|
||||||
|
*value = data & BQ24193_VENDORPART_DEV_MASK;
|
||||||
|
break;
|
||||||
|
case BQ24193_ProductNumber: // Product number.
|
||||||
|
data = bq24193_get_reg(BQ24193_VendorPart);
|
||||||
|
*value = (data & BQ24193_VENDORPART_PN_MASK) >> 3;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -327,7 +327,7 @@ void max77620_config_default()
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
// Set default voltages and enable regulators.
|
// Set default voltages and enable regulators.
|
||||||
for (u32 i = 1; i <= REGULATOR_LDO8; i++)
|
for (u32 i = REGULATOR_SD1; i <= REGULATOR_LDO8; i++)
|
||||||
{
|
{
|
||||||
max77620_regulator_config_fps(i);
|
max77620_regulator_config_fps(i);
|
||||||
max7762x_regulator_set_voltage(i, _pmic_regulators[i].uv_default);
|
max7762x_regulator_set_voltage(i, _pmic_regulators[i].uv_default);
|
||||||
|
|||||||
41
bdk/sec/se.c
41
bdk/sec/se.c
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2018 naehrwert
|
* Copyright (c) 2018 naehrwert
|
||||||
* Copyright (c) 2018-2024 CTCaer
|
* Copyright (c) 2018-2025 CTCaer
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
* under the terms and conditions of the GNU General Public License,
|
* under the terms and conditions of the GNU General Public License,
|
||||||
@@ -19,7 +19,6 @@
|
|||||||
|
|
||||||
#include "se.h"
|
#include "se.h"
|
||||||
#include <memory_map.h>
|
#include <memory_map.h>
|
||||||
#include <mem/heap.h>
|
|
||||||
#include <soc/bpmp.h>
|
#include <soc/bpmp.h>
|
||||||
#include <soc/hw_init.h>
|
#include <soc/hw_init.h>
|
||||||
#include <soc/pmc.h>
|
#include <soc/pmc.h>
|
||||||
@@ -182,7 +181,7 @@ static int _se_execute_one_block(u32 op, void *dst, u32 dst_size, const void *sr
|
|||||||
if (!src || !dst)
|
if (!src || !dst)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
u8 *block = (u8 *)zalloc(SE_AES_BLOCK_SIZE);
|
u32 block[SE_AES_BLOCK_SIZE / sizeof(u32)] = {0};
|
||||||
|
|
||||||
SE(SE_CRYPTO_BLOCK_COUNT_REG) = 1 - 1;
|
SE(SE_CRYPTO_BLOCK_COUNT_REG) = 1 - 1;
|
||||||
|
|
||||||
@@ -190,7 +189,6 @@ static int _se_execute_one_block(u32 op, void *dst, u32 dst_size, const void *sr
|
|||||||
int res = _se_execute_oneshot(op, block, SE_AES_BLOCK_SIZE, block, SE_AES_BLOCK_SIZE);
|
int res = _se_execute_oneshot(op, block, SE_AES_BLOCK_SIZE, block, SE_AES_BLOCK_SIZE);
|
||||||
memcpy(dst, block, dst_size);
|
memcpy(dst, block, dst_size);
|
||||||
|
|
||||||
free(block);
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -389,7 +387,8 @@ int se_aes_crypt_ctr(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_s
|
|||||||
int se_aes_xts_crypt_sec(u32 tweak_ks, u32 crypt_ks, u32 enc, u64 sec, void *dst, void *src, u32 secsize)
|
int se_aes_xts_crypt_sec(u32 tweak_ks, u32 crypt_ks, u32 enc, u64 sec, void *dst, void *src, u32 secsize)
|
||||||
{
|
{
|
||||||
int res = 0;
|
int res = 0;
|
||||||
u8 *tweak = (u8 *)malloc(SE_AES_BLOCK_SIZE);
|
u32 tmp[SE_AES_BLOCK_SIZE / sizeof(u32)];
|
||||||
|
u8 *tweak = (u8 *)tmp;
|
||||||
u8 *pdst = (u8 *)dst;
|
u8 *pdst = (u8 *)dst;
|
||||||
u8 *psrc = (u8 *)src;
|
u8 *psrc = (u8 *)src;
|
||||||
|
|
||||||
@@ -418,8 +417,7 @@ int se_aes_xts_crypt_sec(u32 tweak_ks, u32 crypt_ks, u32 enc, u64 sec, void *dst
|
|||||||
|
|
||||||
res = 1;
|
res = 1;
|
||||||
|
|
||||||
out:;
|
out:
|
||||||
free(tweak);
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -514,15 +512,15 @@ int se_calc_sha256(void *hash, u32 *msg_left, const void *src, u32 src_size, u64
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
// Src size of 0 is not supported, so return null string sha256.
|
// Src size of 0 is not supported, so return null string sha256.
|
||||||
// if (!src_size)
|
if (!src_size)
|
||||||
// {
|
{
|
||||||
// const u8 null_hash[SE_SHA_256_SIZE] = {
|
const u8 null_hash[SE_SHA_256_SIZE] = {
|
||||||
// 0xE3, 0xB0, 0xC4, 0x42, 0x98, 0xFC, 0x1C, 0x14, 0x9A, 0xFB, 0xF4, 0xC8, 0x99, 0x6F, 0xB9, 0x24,
|
0xE3, 0xB0, 0xC4, 0x42, 0x98, 0xFC, 0x1C, 0x14, 0x9A, 0xFB, 0xF4, 0xC8, 0x99, 0x6F, 0xB9, 0x24,
|
||||||
// 0x27, 0xAE, 0x41, 0xE4, 0x64, 0x9B, 0x93, 0x4C, 0xA4, 0x95, 0x99, 0x1B, 0x78, 0x52, 0xB8, 0x55
|
0x27, 0xAE, 0x41, 0xE4, 0x64, 0x9B, 0x93, 0x4C, 0xA4, 0x95, 0x99, 0x1B, 0x78, 0x52, 0xB8, 0x55
|
||||||
// };
|
};
|
||||||
// memcpy(hash, null_hash, SE_SHA_256_SIZE);
|
memcpy(hash, null_hash, SE_SHA_256_SIZE);
|
||||||
// return 1;
|
return 1;
|
||||||
// }
|
}
|
||||||
|
|
||||||
// Setup config for SHA256.
|
// Setup config for SHA256.
|
||||||
SE(SE_CONFIG_REG) = SE_CONFIG_ENC_MODE(MODE_SHA256) | SE_CONFIG_ENC_ALG(ALG_SHA) | SE_CONFIG_DST(DST_HASHREG);
|
SE(SE_CONFIG_REG) = SE_CONFIG_ENC_MODE(MODE_SHA256) | SE_CONFIG_ENC_ALG(ALG_SHA) | SE_CONFIG_DST(DST_HASHREG);
|
||||||
@@ -657,8 +655,11 @@ void se_get_aes_keys(u8 *buf, u8 *keys, u32 keysize)
|
|||||||
int se_aes_cmac_128(u32 ks, void *dst, const void *src, u32 src_size)
|
int se_aes_cmac_128(u32 ks, void *dst, const void *src, u32 src_size)
|
||||||
{
|
{
|
||||||
int res = 0;
|
int res = 0;
|
||||||
u8 *key = (u8 *)zalloc(SE_KEY_128_SIZE);
|
|
||||||
u8 *last_block = (u8 *)zalloc(SE_AES_BLOCK_SIZE);
|
u32 tmp1[SE_KEY_128_SIZE / sizeof(u32)] = {0};
|
||||||
|
u32 tmp2[SE_AES_BLOCK_SIZE / sizeof(u32)] = {0};
|
||||||
|
u8 *key = (u8 *)tmp1;
|
||||||
|
u8 *last_block = (u8 *)tmp2;
|
||||||
|
|
||||||
se_aes_iv_clear(ks);
|
se_aes_iv_clear(ks);
|
||||||
se_aes_iv_updated_clear(ks);
|
se_aes_iv_updated_clear(ks);
|
||||||
@@ -707,8 +708,6 @@ int se_aes_cmac_128(u32 ks, void *dst, const void *src, u32 src_size)
|
|||||||
for (u32 i = 0; i < (SE_KEY_128_SIZE / 4); i++)
|
for (u32 i = 0; i < (SE_KEY_128_SIZE / 4); i++)
|
||||||
dst32[i] = SE(SE_HASH_RESULT_REG + (i * 4));
|
dst32[i] = SE(SE_HASH_RESULT_REG + (i * 4));
|
||||||
|
|
||||||
out:;
|
out:
|
||||||
free(key);
|
|
||||||
free(last_block);
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,7 +24,9 @@
|
|||||||
#include <sec/se_t210.h>
|
#include <sec/se_t210.h>
|
||||||
#include <soc/fuse.h>
|
#include <soc/fuse.h>
|
||||||
#include <soc/hw_init.h>
|
#include <soc/hw_init.h>
|
||||||
|
#include <soc/pmc.h>
|
||||||
#include <soc/t210.h>
|
#include <soc/t210.h>
|
||||||
|
#include <soc/timer.h>
|
||||||
#include <utils/types.h>
|
#include <utils/types.h>
|
||||||
|
|
||||||
static const u32 evp_thunk_template[] = {
|
static const u32 evp_thunk_template[] = {
|
||||||
|
|||||||
@@ -85,6 +85,7 @@
|
|||||||
#define AXBAR_BASE 0x702D0800
|
#define AXBAR_BASE 0x702D0800
|
||||||
#define I2S_BASE 0x702D1000
|
#define I2S_BASE 0x702D1000
|
||||||
#define ADMA_BASE 0x702E2000
|
#define ADMA_BASE 0x702E2000
|
||||||
|
#define AMC_BASE 0x702EF000
|
||||||
#define SE2_BASE 0x70412000
|
#define SE2_BASE 0x70412000
|
||||||
#define SE_PKA1_BASE 0x70420000
|
#define SE_PKA1_BASE 0x70420000
|
||||||
#define TZRAM_BASE 0x7C010000
|
#define TZRAM_BASE 0x7C010000
|
||||||
@@ -151,6 +152,7 @@
|
|||||||
#define CL_DVFS(off) MMIO_REG32(CL_DVFS_BASE, off)
|
#define CL_DVFS(off) MMIO_REG32(CL_DVFS_BASE, off)
|
||||||
#define I2S(off) MMIO_REG32(I2S_BASE, off)
|
#define I2S(off) MMIO_REG32(I2S_BASE, off)
|
||||||
#define ADMA(off) MMIO_REG32(ADMA_BASE, off)
|
#define ADMA(off) MMIO_REG32(ADMA_BASE, off)
|
||||||
|
#define AMC(off) MMIO_REG32(AMC_BASE, off)
|
||||||
#define SE2(off) MMIO_REG32(SE2_BASE, off)
|
#define SE2(off) MMIO_REG32(SE2_BASE, off)
|
||||||
#define SE_PKA1(off) MMIO_REG32(SE_PKA1_BASE, off)
|
#define SE_PKA1(off) MMIO_REG32(SE_PKA1_BASE, off)
|
||||||
#define USB(off) MMIO_REG32(USB_BASE, off)
|
#define USB(off) MMIO_REG32(USB_BASE, off)
|
||||||
@@ -199,7 +201,7 @@
|
|||||||
/*! AHB Gizmo registers. */
|
/*! AHB Gizmo registers. */
|
||||||
#define AHB_ARBITRATION_PRIORITY_CTRL 0x8
|
#define AHB_ARBITRATION_PRIORITY_CTRL 0x8
|
||||||
#define PRIORITY_CTRL_WEIGHT(x) (((x) & 7) << 29)
|
#define PRIORITY_CTRL_WEIGHT(x) (((x) & 7) << 29)
|
||||||
#define PRIORITY_SELECT_USB BIT(6) // USB-OTG.
|
#define PRIORITY_SELECT_USB BIT(6) // USB-OTG.
|
||||||
#define PRIORITY_SELECT_USB2 BIT(18) // USB-HSIC.
|
#define PRIORITY_SELECT_USB2 BIT(18) // USB-HSIC.
|
||||||
#define PRIORITY_SELECT_USB3 BIT(17) // XUSB.
|
#define PRIORITY_SELECT_USB3 BIT(17) // XUSB.
|
||||||
#define AHB_GIZMO_AHB_MEM 0x10
|
#define AHB_GIZMO_AHB_MEM 0x10
|
||||||
@@ -210,7 +212,7 @@
|
|||||||
#define AHB_GIZMO_USB 0x20
|
#define AHB_GIZMO_USB 0x20
|
||||||
#define AHB_GIZMO_SDMMC4 0x48
|
#define AHB_GIZMO_SDMMC4 0x48
|
||||||
#define AHB_GIZMO_USB2 0x7C
|
#define AHB_GIZMO_USB2 0x7C
|
||||||
#define AHB_GIZMO_USB3 0x80
|
#define AHB_GIZMO_USB3 0x80 // Doesn't exist on T21x??
|
||||||
#define AHB_GIZMO_IMMEDIATE BIT(18)
|
#define AHB_GIZMO_IMMEDIATE BIT(18)
|
||||||
#define AHB_ARBITRATION_XBAR_CTRL 0xE0
|
#define AHB_ARBITRATION_XBAR_CTRL 0xE0
|
||||||
#define AHB_AHB_MEM_PREFETCH_CFG3 0xE4
|
#define AHB_AHB_MEM_PREFETCH_CFG3 0xE4
|
||||||
@@ -219,9 +221,9 @@
|
|||||||
#define AHB_AHB_MEM_PREFETCH_CFG2 0xF4
|
#define AHB_AHB_MEM_PREFETCH_CFG2 0xF4
|
||||||
#define MST_ID(x) (((x) & 0x1F) << 26)
|
#define MST_ID(x) (((x) & 0x1F) << 26)
|
||||||
#define MEM_PREFETCH_AHBDMA_MST_ID MST_ID(5)
|
#define MEM_PREFETCH_AHBDMA_MST_ID MST_ID(5)
|
||||||
#define MEM_PREFETCH_USB_MST_ID MST_ID(6) // USB-OTG.
|
#define MEM_PREFETCH_USB_MST_ID MST_ID(6) // USB-OTG. Doesn't exist on T210B01.
|
||||||
#define MEM_PREFETCH_USB2_MST_ID MST_ID(18) // USB-HSIC.
|
#define MEM_PREFETCH_USB2_MST_ID MST_ID(18) // USB-HSIC. Doesn't exist on T210B01.
|
||||||
#define MEM_PREFETCH_USB3_MST_ID MST_ID(17) // XUSB.
|
#define MEM_PREFETCH_USB3_MST_ID MST_ID(17) // XUSB. Doesn't exist on T210B01.
|
||||||
#define MEM_PREFETCH_ADDR_BNDRY(x) (((x) & 0xF) << 21)
|
#define MEM_PREFETCH_ADDR_BNDRY(x) (((x) & 0xF) << 21)
|
||||||
#define MEM_PREFETCH_ENABLE BIT(31)
|
#define MEM_PREFETCH_ENABLE BIT(31)
|
||||||
#define AHB_ARBITRATION_AHB_MEM_WRQUE_MST_ID 0xFC
|
#define AHB_ARBITRATION_AHB_MEM_WRQUE_MST_ID 0xFC
|
||||||
|
|||||||
@@ -70,6 +70,8 @@
|
|||||||
#define UART_MCR_CTS_EN BIT(5)
|
#define UART_MCR_CTS_EN BIT(5)
|
||||||
#define UART_MCR_RTS_EN BIT(6)
|
#define UART_MCR_RTS_EN BIT(6)
|
||||||
|
|
||||||
|
#define UART_FIFO_SIZE 36
|
||||||
|
|
||||||
typedef struct _uart_t
|
typedef struct _uart_t
|
||||||
{
|
{
|
||||||
/* 0x00 */ vu32 UART_THR_DLAB;
|
/* 0x00 */ vu32 UART_THR_DLAB;
|
||||||
|
|||||||
@@ -112,7 +112,10 @@ static bool _boot_storage_mount(){
|
|||||||
|
|
||||||
FRESULT res;
|
FRESULT res;
|
||||||
|
|
||||||
if(!emmc_get_initialized() && !emmc_initialize(false)){
|
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;
|
goto emmc_init_fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -121,15 +124,12 @@ static bool _boot_storage_mount(){
|
|||||||
for(BYTE i = 0; i < ARRAY_SIZE(emmc_drives); i++){
|
for(BYTE i = 0; i < ARRAY_SIZE(emmc_drives); i++){
|
||||||
res = f_mount(&boot_storage_fs, drive_base_paths[emmc_drives[i]], true);
|
res = f_mount(&boot_storage_fs, drive_base_paths[emmc_drives[i]], true);
|
||||||
if(res == FR_OK){
|
if(res == FR_OK){
|
||||||
gfx_printf("trying %s\n", drive_base_paths[emmc_drives[i]]);
|
|
||||||
res = f_chdrive(drive_base_paths[emmc_drives[i]]);
|
res = f_chdrive(drive_base_paths[emmc_drives[i]]);
|
||||||
if(res == FR_OK && _is_eligible()){
|
if(res == FR_OK && _is_eligible()){
|
||||||
gfx_printf("%s ok\n", drive_base_paths[emmc_drives[i]]);
|
|
||||||
drive_cur = emmc_drives[i];
|
drive_cur = emmc_drives[i];
|
||||||
drive = drive_cur;
|
drive = drive_cur;
|
||||||
break;
|
break;
|
||||||
}else{
|
}else{
|
||||||
gfx_printf("%s fail\n", drive_base_paths[emmc_drives[i]]);
|
|
||||||
f_mount(NULL, drive_base_paths[emmc_drives[i]],false);
|
f_mount(NULL, drive_base_paths[emmc_drives[i]],false);
|
||||||
res = FR_INVALID_DRIVE;
|
res = FR_INVALID_DRIVE;
|
||||||
}
|
}
|
||||||
@@ -137,7 +137,9 @@ static bool _boot_storage_mount(){
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(res != FR_OK){
|
if(res != FR_OK){
|
||||||
emmc_end();
|
if(!prev_emmc_initialized) {
|
||||||
|
emmc_end();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(res == FR_OK){
|
if(res == FR_OK){
|
||||||
@@ -150,7 +152,9 @@ emmc_init_fail:
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(!emmc_mount()){
|
if(!emmc_mount()){
|
||||||
emmc_end();
|
if(!prev_emmc_initialized) {
|
||||||
|
emmc_end();
|
||||||
|
}
|
||||||
goto emmc_init_fail2;
|
goto emmc_init_fail2;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -168,7 +172,9 @@ emmc_init_fail2:
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(!sd_mount()){
|
if(!sd_mount()){
|
||||||
sd_end();
|
if(!prev_sd_initialized) {
|
||||||
|
sd_end();
|
||||||
|
}
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -180,7 +186,9 @@ emmc_init_fail2:
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
sd_end();
|
if(!prev_sd_initialized) {
|
||||||
|
sd_end();
|
||||||
|
}
|
||||||
|
|
||||||
out:
|
out:
|
||||||
return false;
|
return false;
|
||||||
@@ -250,4 +258,18 @@ int boot_storage_save_to_file(const void *buf, u32 size, const char *filename)
|
|||||||
f_close(&fp);
|
f_close(&fp);
|
||||||
|
|
||||||
return 0;
|
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;
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
#ifndef _BOOT_STORAGE_H
|
#ifndef _BOOT_STORAGE_H
|
||||||
#define _BOOT_STORAGE_H
|
#define _BOOT_STORAGE_H
|
||||||
|
|
||||||
|
#include <libs/fatfs/ff.h>
|
||||||
#include <utils/types.h>
|
#include <utils/types.h>
|
||||||
|
|
||||||
// check if boot1 (1mb), boot1, gpp, sd (in that order) have fat32 partition,
|
// check if boot1 (1mb), boot1, gpp, sd (in that order) have fat32 partition,
|
||||||
@@ -16,6 +17,8 @@ bool boot_storage_get_initialized();
|
|||||||
void *boot_storage_file_read(const char *path, u32 *fsize);
|
void *boot_storage_file_read(const char *path, u32 *fsize);
|
||||||
int boot_storage_save_to_file(const void *buf, u32 size, const char *filename);
|
int boot_storage_save_to_file(const void *buf, u32 size, const char *filename);
|
||||||
|
|
||||||
|
FATFS *boot_storage_get_fs();
|
||||||
|
|
||||||
u8 boot_storage_get_drive();
|
u8 boot_storage_get_drive();
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
184
bdk/storage/file_based_storage.c
Normal file
184
bdk/storage/file_based_storage.c
Normal file
@@ -0,0 +1,184 @@
|
|||||||
|
#include "file_based_storage.h"
|
||||||
|
#include <libs/fatfs/ff.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
typedef struct{
|
||||||
|
FIL active_file;
|
||||||
|
s32 active_file_idx;
|
||||||
|
char base_path[0x80];
|
||||||
|
u32 part_sz_sct;
|
||||||
|
u32 base_path_len;
|
||||||
|
}file_based_storage_ctxt_t;
|
||||||
|
|
||||||
|
static file_based_storage_ctxt_t ctx;
|
||||||
|
|
||||||
|
int file_based_storage_init(const char *base_path) {
|
||||||
|
ctx.active_file_idx = -0xff;
|
||||||
|
ctx.base_path_len = strlen(base_path);
|
||||||
|
|
||||||
|
strcpy(ctx.base_path, base_path);
|
||||||
|
strcat(ctx.base_path, "00");
|
||||||
|
|
||||||
|
FILINFO fi;
|
||||||
|
if(f_stat(ctx.base_path, &fi) != FR_OK) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(fi.fsize) {
|
||||||
|
ctx.part_sz_sct = fi.fsize >> 9;
|
||||||
|
}else{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
ctx.part_sz_sct = fi.fsize;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void file_based_storage_end() {
|
||||||
|
if(ctx.active_file_idx != -0xff) {
|
||||||
|
f_close(&ctx.active_file);
|
||||||
|
}
|
||||||
|
ctx.active_file_idx = -0xff;
|
||||||
|
ctx.part_sz_sct = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int file_based_storage_change_file(const char *name, s32 idx) {
|
||||||
|
int res;
|
||||||
|
|
||||||
|
if(ctx.active_file_idx == idx){
|
||||||
|
return FR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(ctx.active_file_idx != -0xff){
|
||||||
|
f_close(&ctx.active_file);
|
||||||
|
ctx.active_file_idx = -0xff;
|
||||||
|
}
|
||||||
|
|
||||||
|
strcpy(ctx.base_path + ctx.base_path_len, name);
|
||||||
|
|
||||||
|
#if FF_FS_READONLY == 1
|
||||||
|
res = f_open(&ctx.active_file, ctx.base_path, FA_READ);
|
||||||
|
#else
|
||||||
|
res = f_open(&ctx.active_file, ctx.base_path, FA_READ | FA_WRITE);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if(res != FR_OK){
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.active_file_idx = idx;
|
||||||
|
|
||||||
|
return FR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int file_based_storage_readwrite_single(u32 sector, u32 num_sectors, void *buf, bool is_write){
|
||||||
|
#if FF_FS_READONLY == 1
|
||||||
|
if(is_write){
|
||||||
|
return FR_WRITE_PROTECTED;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int res = f_lseek(&ctx.active_file, (u64)sector << 9);
|
||||||
|
if(res != FR_OK){
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(is_write){
|
||||||
|
res = f_write(&ctx.active_file, buf, (u64)num_sectors << 9, NULL);
|
||||||
|
}else{
|
||||||
|
res = f_read(&ctx.active_file, buf, (u64)num_sectors << 9, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(res != FR_OK){
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
return FR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int file_based_storage_readwrite(u32 sector, u32 num_sectors, void *buf, bool is_write) {
|
||||||
|
#if FF_FS_READONLY == 1
|
||||||
|
if(is_write){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if(ctx.part_sz_sct == 0){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int res;
|
||||||
|
|
||||||
|
u32 scts_left = num_sectors;
|
||||||
|
u32 cur_sct = sector;
|
||||||
|
|
||||||
|
while(scts_left){
|
||||||
|
u32 offset = cur_sct % ctx.part_sz_sct;
|
||||||
|
u32 sct_cnt = ctx.part_sz_sct - offset;
|
||||||
|
sct_cnt = MIN(scts_left, sct_cnt);
|
||||||
|
|
||||||
|
u32 file_idx = cur_sct / ctx.part_sz_sct;
|
||||||
|
|
||||||
|
if((s32) file_idx != ctx.active_file_idx) {
|
||||||
|
char name[3];
|
||||||
|
if(file_idx < 10){
|
||||||
|
strcpy(name, "0");
|
||||||
|
}
|
||||||
|
itoa(file_idx, name + strlen(name), 10);
|
||||||
|
|
||||||
|
res = file_based_storage_change_file(name, file_idx);
|
||||||
|
if(res != FR_OK){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
res = file_based_storage_readwrite_single(offset, sct_cnt, buf + ((u64)(num_sectors - scts_left) << 9), is_write);
|
||||||
|
if(res != FR_OK){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
cur_sct += sct_cnt;
|
||||||
|
scts_left -= sct_cnt;
|
||||||
|
}
|
||||||
|
|
||||||
|
f_sync(&ctx.active_file);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int file_based_storage_read(u32 sector, u32 num_sectors, void *buf) {
|
||||||
|
return file_based_storage_readwrite(sector, num_sectors, buf, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
int file_based_storage_write(u32 sector, u32 num_sectors, void *buf) {
|
||||||
|
return file_based_storage_readwrite(sector, num_sectors, buf, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 file_based_storage_get_total_size() {
|
||||||
|
u32 total_size_sct = 0;
|
||||||
|
char file_path[0x80];
|
||||||
|
u32 cur_idx = 0;
|
||||||
|
int res;
|
||||||
|
|
||||||
|
strcpy(file_path, ctx.base_path);
|
||||||
|
strcpy(file_path + ctx.base_path_len, "00");
|
||||||
|
|
||||||
|
FILINFO fi;
|
||||||
|
res = f_stat(file_path, &fi);
|
||||||
|
|
||||||
|
while(res == FR_OK){
|
||||||
|
cur_idx++;
|
||||||
|
total_size_sct += fi.fsize >> 9;
|
||||||
|
|
||||||
|
char name[3] = "0";
|
||||||
|
if(cur_idx >= 10){
|
||||||
|
name[0] = '\0';
|
||||||
|
}
|
||||||
|
itoa(cur_idx, name + strlen(name), 10);
|
||||||
|
|
||||||
|
strcpy(file_path + ctx.base_path_len, name);
|
||||||
|
|
||||||
|
res = f_stat(file_path, &fi);
|
||||||
|
}
|
||||||
|
|
||||||
|
return total_size_sct;
|
||||||
|
}
|
||||||
15
bdk/storage/file_based_storage.h
Normal file
15
bdk/storage/file_based_storage.h
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
#ifndef _FILE_BASED_STORAGE_H
|
||||||
|
#define _FILE_BASED_STORAGE_H
|
||||||
|
|
||||||
|
#include <bdk.h>
|
||||||
|
|
||||||
|
|
||||||
|
int file_based_storage_init(const char *base_path);
|
||||||
|
void file_based_storage_end();
|
||||||
|
|
||||||
|
int file_based_storage_read(u32 sector, u32 num_sectors, void *buf);
|
||||||
|
int file_based_storage_write(u32 sector, u32 num_sectors, void *buf);
|
||||||
|
|
||||||
|
u32 file_based_storage_get_total_size();
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2005-2007 Pierre Ossman, All Rights Reserved.
|
* Copyright (c) 2005-2007 Pierre Ossman, All Rights Reserved.
|
||||||
* Copyright (c) 2018-2023 CTCaer
|
* Copyright (c) 2018-2025 CTCaer
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -17,11 +17,16 @@
|
|||||||
#define SD_SEND_RELATIVE_ADDR 3 /* bcr R6 */
|
#define SD_SEND_RELATIVE_ADDR 3 /* bcr R6 */
|
||||||
#define SD_SEND_IF_COND 8 /* bcr [11:0] See below R7 */
|
#define SD_SEND_IF_COND 8 /* bcr [11:0] See below R7 */
|
||||||
#define SD_SWITCH_VOLTAGE 11 /* ac R1 */
|
#define SD_SWITCH_VOLTAGE 11 /* ac R1 */
|
||||||
|
/* Class 2 */
|
||||||
|
#define SD_ADDR_EXT 22 /* ac [5:0] R1 */
|
||||||
/* class 10 */
|
/* class 10 */
|
||||||
#define SD_SWITCH 6 /* adtc [31:0] See below R1 */
|
#define SD_SWITCH 6 /* adtc [31:0] See below R1 */
|
||||||
/* class 5 */
|
/* class 5 */
|
||||||
#define SD_ERASE_WR_BLK_START 32 /* ac [31:0] data addr R1 */
|
#define SD_ERASE_WR_BLK_START 32 /* ac [31:0] data addr R1 */
|
||||||
#define SD_ERASE_WR_BLK_END 33 /* ac [31:0] data addr R1 */
|
#define SD_ERASE_WR_BLK_END 33 /* ac [31:0] data addr R1 */
|
||||||
|
/* class 11 */
|
||||||
|
#define SD_READ_EXTR_SINGLE 48 /* adtc [31:0] R1 */
|
||||||
|
#define SD_WRITE_EXTR_SINGLE 49 /* adtc [31:0] R1 */
|
||||||
|
|
||||||
/* Application commands */
|
/* Application commands */
|
||||||
#define SD_APP_SET_BUS_WIDTH 6 /* ac [1:0] bus width R1 */
|
#define SD_APP_SET_BUS_WIDTH 6 /* ac [1:0] bus width R1 */
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2018 naehrwert
|
* Copyright (c) 2018 naehrwert
|
||||||
* Copyright (c) 2018-2023 CTCaer
|
* Copyright (c) 2018-2025 CTCaer
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
* under the terms and conditions of the GNU General Public License,
|
* under the terms and conditions of the GNU General Public License,
|
||||||
@@ -18,6 +18,7 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include <mem/heap.h>
|
#include <mem/heap.h>
|
||||||
|
#include <mem/mc.h>
|
||||||
#include <soc/timer.h>
|
#include <soc/timer.h>
|
||||||
#include <storage/emmc.h>
|
#include <storage/emmc.h>
|
||||||
#include <storage/sdmmc.h>
|
#include <storage/sdmmc.h>
|
||||||
@@ -27,14 +28,26 @@
|
|||||||
#include <memory_map.h>
|
#include <memory_map.h>
|
||||||
#include <gfx_utils.h>
|
#include <gfx_utils.h>
|
||||||
|
|
||||||
//#define SDMMC_DEBUG_PRINT_SD_REGS
|
|
||||||
//#define DPRINTF(...) gfx_printf(__VA_ARGS__)
|
//#define DPRINTF(...) gfx_printf(__VA_ARGS__)
|
||||||
#define DPRINTF(...)
|
#define DPRINTF(...)
|
||||||
|
|
||||||
|
//#define SDMMC_DEBUG_PRINT_SD_REGS
|
||||||
|
#ifdef SDMMC_DEBUG_PRINT_SD_REGS
|
||||||
|
#define DREGPRINTF(...) gfx_printf(__VA_ARGS__)
|
||||||
|
#else
|
||||||
|
#define DREGPRINTF(...)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef BDK_SDMMC_EXTRA_PRINT
|
||||||
|
#define ERROR_EXTRA_PRINTING
|
||||||
|
#endif
|
||||||
|
|
||||||
u32 sd_power_cycle_time_start;
|
u32 sd_power_cycle_time_start;
|
||||||
|
|
||||||
static inline u32 unstuff_bits(const u32 *resp, u32 start, u32 size)
|
static inline u32 unstuff_bits(const u32 *resp, u32 start, u32 size)
|
||||||
{
|
{
|
||||||
|
start %= 128;
|
||||||
|
|
||||||
const u32 mask = (size < 32 ? 1 << size : 0) - 1;
|
const u32 mask = (size < 32 ? 1 << size : 0) - 1;
|
||||||
const u32 off = 3 - ((start) / 32);
|
const u32 off = 3 - ((start) / 32);
|
||||||
const u32 shft = (start) & 31;
|
const u32 shft = (start) & 31;
|
||||||
@@ -52,7 +65,7 @@ static inline u32 unstuff_bits(const u32 *resp, u32 start, u32 size)
|
|||||||
static int _sdmmc_storage_check_card_status(u32 res)
|
static int _sdmmc_storage_check_card_status(u32 res)
|
||||||
{
|
{
|
||||||
//Error mask:
|
//Error mask:
|
||||||
//TODO: R1_SWITCH_ERROR can be skipped for certain card types.
|
//!WARN: R1_SWITCH_ERROR is reserved on SD. The card isn't supposed to use it.
|
||||||
if (res &
|
if (res &
|
||||||
(R1_OUT_OF_RANGE | R1_ADDRESS_ERROR | R1_BLOCK_LEN_ERROR |
|
(R1_OUT_OF_RANGE | R1_ADDRESS_ERROR | R1_BLOCK_LEN_ERROR |
|
||||||
R1_ERASE_SEQ_ERROR | R1_ERASE_PARAM | R1_WP_VIOLATION |
|
R1_ERASE_SEQ_ERROR | R1_ERASE_PARAM | R1_WP_VIOLATION |
|
||||||
@@ -73,7 +86,7 @@ static int _sdmmc_storage_execute_cmd_type1_ex(sdmmc_storage_t *storage, u32 *re
|
|||||||
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, NULL, NULL))
|
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, NULL, NULL))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
sdmmc_get_rsp(storage->sdmmc, resp, 4, SDMMC_RSP_TYPE_1);
|
sdmmc_get_cached_rsp(storage->sdmmc, resp, SDMMC_RSP_TYPE_1);
|
||||||
if (mask)
|
if (mask)
|
||||||
*resp &= ~mask;
|
*resp &= ~mask;
|
||||||
|
|
||||||
@@ -105,7 +118,7 @@ static int _sdmmc_storage_get_cid(sdmmc_storage_t *storage)
|
|||||||
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, NULL, NULL))
|
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, NULL, NULL))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
sdmmc_get_rsp(storage->sdmmc, (u32 *)storage->raw_cid, 16, SDMMC_RSP_TYPE_2);
|
sdmmc_get_cached_rsp(storage->sdmmc, (u32 *)storage->raw_cid, SDMMC_RSP_TYPE_2);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -122,7 +135,7 @@ static int _sdmmc_storage_get_csd(sdmmc_storage_t *storage)
|
|||||||
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, NULL, NULL))
|
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, NULL, NULL))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
sdmmc_get_rsp(storage->sdmmc, (u32 *)storage->raw_csd, 16, SDMMC_RSP_TYPE_2);
|
sdmmc_get_cached_rsp(storage->sdmmc, (u32 *)storage->raw_csd, SDMMC_RSP_TYPE_2);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -151,7 +164,7 @@ int sdmmc_storage_execute_vendor_cmd(sdmmc_storage_t *storage, u32 arg)
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
u32 resp;
|
u32 resp;
|
||||||
sdmmc_get_rsp(storage->sdmmc, &resp, 4, SDMMC_RSP_TYPE_1);
|
sdmmc_get_cached_rsp(storage->sdmmc, &resp, SDMMC_RSP_TYPE_1);
|
||||||
|
|
||||||
resp = -1;
|
resp = -1;
|
||||||
u32 timeout = get_tmr_ms() + 1500;
|
u32 timeout = get_tmr_ms() + 1500;
|
||||||
@@ -228,6 +241,10 @@ static int _sdmmc_storage_readwrite_ex(sdmmc_storage_t *storage, u32 *blkcnt_out
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sdmmc_get_cached_rsp(storage->sdmmc, &tmp, SDMMC_RSP_TYPE_1);
|
||||||
|
if (!_sdmmc_storage_check_card_status(tmp))
|
||||||
|
return 0;
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -245,6 +262,43 @@ int sdmmc_storage_end(sdmmc_storage_t *storage)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int _sdmmc_storage_handle_io_error(sdmmc_storage_t *storage, bool first_reinit)
|
||||||
|
{
|
||||||
|
int res = 0;
|
||||||
|
|
||||||
|
if (storage->sdmmc->id == SDMMC_1 || storage->sdmmc->id == SDMMC_4)
|
||||||
|
{
|
||||||
|
if (storage->sdmmc->id == SDMMC_1)
|
||||||
|
{
|
||||||
|
sd_error_count_increment(SD_ERROR_RW_FAIL);
|
||||||
|
|
||||||
|
if (first_reinit)
|
||||||
|
res = sd_initialize(true);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
res = sd_init_retry(true);
|
||||||
|
if (!res)
|
||||||
|
sd_error_count_increment(SD_ERROR_INIT_FAIL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (storage->sdmmc->id == SDMMC_4)
|
||||||
|
{
|
||||||
|
emmc_error_count_increment(EMMC_ERROR_RW_FAIL);
|
||||||
|
|
||||||
|
if (first_reinit)
|
||||||
|
res = emmc_initialize(true);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
res = emmc_init_retry(true);
|
||||||
|
if (!res)
|
||||||
|
emmc_error_count_increment(EMMC_ERROR_INIT_FAIL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
static int _sdmmc_storage_readwrite(sdmmc_storage_t *storage, u32 sector, u32 num_sectors, void *buf, u32 is_write)
|
static int _sdmmc_storage_readwrite(sdmmc_storage_t *storage, u32 sector, u32 num_sectors, void *buf, u32 is_write)
|
||||||
{
|
{
|
||||||
u8 *bbuf = (u8 *)buf;
|
u8 *bbuf = (u8 *)buf;
|
||||||
@@ -256,6 +310,15 @@ static int _sdmmc_storage_readwrite(sdmmc_storage_t *storage, u32 sector, u32 nu
|
|||||||
if (!storage->initialized)
|
if (!storage->initialized)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
// Check if out of bounds.
|
||||||
|
if (((u64)sector + num_sectors) > storage->sec_cnt)
|
||||||
|
{
|
||||||
|
#ifdef ERROR_EXTRA_PRINTING
|
||||||
|
EPRINTFARGS("SDMMC%d: Out of bounds!", storage->sdmmc->id + 1);
|
||||||
|
#endif
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
while (sct_total)
|
while (sct_total)
|
||||||
{
|
{
|
||||||
u32 blkcnt = 0;
|
u32 blkcnt = 0;
|
||||||
@@ -275,51 +338,18 @@ reinit_try:
|
|||||||
} while (retries);
|
} while (retries);
|
||||||
|
|
||||||
// Disk IO failure! Reinit SD/EMMC to a lower speed.
|
// Disk IO failure! Reinit SD/EMMC to a lower speed.
|
||||||
if (storage->sdmmc->id == SDMMC_1 || storage->sdmmc->id == SDMMC_4)
|
if (_sdmmc_storage_handle_io_error(storage, first_reinit))
|
||||||
{
|
{
|
||||||
int res = 0;
|
|
||||||
|
|
||||||
if (storage->sdmmc->id == SDMMC_1)
|
|
||||||
{
|
|
||||||
sd_error_count_increment(SD_ERROR_RW_FAIL);
|
|
||||||
|
|
||||||
if (first_reinit)
|
|
||||||
res = sd_initialize(true);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
res = sd_init_retry(true);
|
|
||||||
if (!res)
|
|
||||||
sd_error_count_increment(SD_ERROR_INIT_FAIL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (storage->sdmmc->id == SDMMC_4)
|
|
||||||
{
|
|
||||||
emmc_error_count_increment(EMMC_ERROR_RW_FAIL);
|
|
||||||
|
|
||||||
if (first_reinit)
|
|
||||||
res = emmc_initialize(true);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
res = emmc_init_retry(true);
|
|
||||||
if (!res)
|
|
||||||
emmc_error_count_increment(EMMC_ERROR_INIT_FAIL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reset values for a retry.
|
// Reset values for a retry.
|
||||||
blkcnt = 0;
|
blkcnt = 0;
|
||||||
retries = 3;
|
retries = 3;
|
||||||
first_reinit = false;
|
first_reinit = false;
|
||||||
|
|
||||||
// If successful reinit, restart xfer.
|
bbuf = (u8 *)buf;
|
||||||
if (res)
|
sct_off = sector;
|
||||||
{
|
sct_total = num_sectors;
|
||||||
bbuf = (u8 *)buf;
|
|
||||||
sct_off = sector;
|
|
||||||
sct_total = num_sectors;
|
|
||||||
|
|
||||||
goto reinit_try;
|
goto reinit_try;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Failed.
|
// Failed.
|
||||||
@@ -393,7 +423,7 @@ static int _mmc_storage_get_op_cond_inner(sdmmc_storage_t *storage, u32 *pout, u
|
|||||||
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, NULL, NULL))
|
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, NULL, NULL))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return sdmmc_get_rsp(storage->sdmmc, pout, 4, SDMMC_RSP_TYPE_3);
|
return sdmmc_get_cached_rsp(storage->sdmmc, pout, SDMMC_RSP_TYPE_3);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _mmc_storage_get_op_cond(sdmmc_storage_t *storage, u32 power)
|
static int _mmc_storage_get_op_cond(sdmmc_storage_t *storage, u32 power)
|
||||||
@@ -477,12 +507,12 @@ static void _mmc_storage_parse_csd(sdmmc_storage_t *storage)
|
|||||||
{
|
{
|
||||||
u32 *raw_csd = (u32 *)storage->raw_csd;
|
u32 *raw_csd = (u32 *)storage->raw_csd;
|
||||||
|
|
||||||
storage->csd.mmca_vsn = unstuff_bits(raw_csd, 122, 4);
|
storage->csd.mmca_vsn = unstuff_bits(raw_csd, 122, 4);
|
||||||
storage->csd.structure = unstuff_bits(raw_csd, 126, 2);
|
storage->csd.structure = unstuff_bits(raw_csd, 126, 2);
|
||||||
storage->csd.cmdclass = unstuff_bits(raw_csd, 84, 12);
|
storage->csd.cmdclass = unstuff_bits(raw_csd, 84, 12);
|
||||||
storage->csd.read_blkbits = unstuff_bits(raw_csd, 80, 4);
|
storage->csd.read_blkbits = unstuff_bits(raw_csd, 80, 4);
|
||||||
storage->csd.capacity = (1 + unstuff_bits(raw_csd, 62, 12)) << (unstuff_bits(raw_csd, 47, 3) + 2);
|
storage->csd.capacity = (1 + unstuff_bits(raw_csd, 62, 12)) << (unstuff_bits(raw_csd, 47, 3) + 2);
|
||||||
storage->sec_cnt = storage->csd.capacity;
|
storage->sec_cnt = storage->csd.capacity;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _mmc_storage_parse_ext_csd(sdmmc_storage_t *storage, u8 *buf)
|
static void _mmc_storage_parse_ext_csd(sdmmc_storage_t *storage, u8 *buf)
|
||||||
@@ -531,12 +561,40 @@ int mmc_storage_get_ext_csd(sdmmc_storage_t *storage, void *buf)
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
u32 tmp = 0;
|
u32 tmp = 0;
|
||||||
sdmmc_get_rsp(storage->sdmmc, &tmp, 4, SDMMC_RSP_TYPE_1);
|
sdmmc_get_cached_rsp(storage->sdmmc, &tmp, SDMMC_RSP_TYPE_1);
|
||||||
_mmc_storage_parse_ext_csd(storage, buf);
|
_mmc_storage_parse_ext_csd(storage, buf);
|
||||||
|
|
||||||
return _sdmmc_storage_check_card_status(tmp);
|
return _sdmmc_storage_check_card_status(tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int sd_storage_get_ext_reg(sdmmc_storage_t *storage, u8 fno, u8 page, u16 address, u32 len, void *buf)
|
||||||
|
{
|
||||||
|
if (!(storage->scr.cmds & BIT(2)))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
sdmmc_cmd_t cmdbuf;
|
||||||
|
|
||||||
|
u32 arg = fno << 27 | page << 18 | address << 9 | (len - 1);
|
||||||
|
|
||||||
|
sdmmc_init_cmd(&cmdbuf, SD_READ_EXTR_SINGLE, arg, SDMMC_RSP_TYPE_1, 0);
|
||||||
|
|
||||||
|
sdmmc_req_t reqbuf;
|
||||||
|
reqbuf.buf = buf;
|
||||||
|
reqbuf.blksize = SDMMC_DAT_BLOCKSIZE;
|
||||||
|
reqbuf.num_sectors = 1;
|
||||||
|
reqbuf.is_write = 0;
|
||||||
|
reqbuf.is_multi_block = 0;
|
||||||
|
reqbuf.is_auto_stop_trn = 0;
|
||||||
|
|
||||||
|
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, &reqbuf, NULL))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
u32 tmp = 0;
|
||||||
|
sdmmc_get_cached_rsp(storage->sdmmc, &tmp, SDMMC_RSP_TYPE_1);
|
||||||
|
|
||||||
|
return _sdmmc_storage_check_card_status(tmp);
|
||||||
|
}
|
||||||
|
|
||||||
static int _mmc_storage_switch(sdmmc_storage_t *storage, u32 arg)
|
static int _mmc_storage_switch(sdmmc_storage_t *storage, u32 arg)
|
||||||
{
|
{
|
||||||
return _sdmmc_storage_execute_cmd_type1(storage, MMC_SWITCH, arg, 1, R1_SKIP_STATE_CHECK);
|
return _sdmmc_storage_execute_cmd_type1(storage, MMC_SWITCH, arg, 1, R1_SKIP_STATE_CHECK);
|
||||||
@@ -813,7 +871,7 @@ void _sd_storage_debug_print_csd(const u32 *raw_csd)
|
|||||||
gfx_printf("WRITE_BLK_MISALIGN: %X\n", unstuff_bits(raw_csd, 78, 1));
|
gfx_printf("WRITE_BLK_MISALIGN: %X\n", unstuff_bits(raw_csd, 78, 1));
|
||||||
gfx_printf("READ_BLK_MISALIGN: %X\n", unstuff_bits(raw_csd, 77, 1));
|
gfx_printf("READ_BLK_MISALIGN: %X\n", unstuff_bits(raw_csd, 77, 1));
|
||||||
gfx_printf("DSR_IMP: %X\n", unstuff_bits(raw_csd, 76, 1));
|
gfx_printf("DSR_IMP: %X\n", unstuff_bits(raw_csd, 76, 1));
|
||||||
gfx_printf("C_SIZE: %06X\n", unstuff_bits(raw_csd, 48, 22));
|
gfx_printf("C_SIZE: %06X\n", unstuff_bits(raw_csd, 48, 28)); // CSD 3 (SDUC).
|
||||||
|
|
||||||
gfx_printf("ERASE_BLK_LEN: %X\n", unstuff_bits(raw_csd, 46, 1));
|
gfx_printf("ERASE_BLK_LEN: %X\n", unstuff_bits(raw_csd, 46, 1));
|
||||||
gfx_printf("SECTOR_SIZE: %02X\n", unstuff_bits(raw_csd, 39, 6));
|
gfx_printf("SECTOR_SIZE: %02X\n", unstuff_bits(raw_csd, 39, 6));
|
||||||
@@ -830,8 +888,8 @@ void _sd_storage_debug_print_csd(const u32 *raw_csd)
|
|||||||
gfx_printf("TMP_WRITE_PROTECT: %X\n", unstuff_bits(raw_csd, 12, 1));
|
gfx_printf("TMP_WRITE_PROTECT: %X\n", unstuff_bits(raw_csd, 12, 1));
|
||||||
gfx_printf("FILE_FORMAT: %X\n", unstuff_bits(raw_csd, 10, 2));
|
gfx_printf("FILE_FORMAT: %X\n", unstuff_bits(raw_csd, 10, 2));
|
||||||
|
|
||||||
gfx_printf("--RSVD-- %02X %02X %X %X %02X %X\n",
|
gfx_printf("--RSVD-- %02X %X %X %02X %X\n",
|
||||||
unstuff_bits(raw_csd, 120, 6), unstuff_bits(raw_csd, 70, 6),
|
unstuff_bits(raw_csd, 120, 6),
|
||||||
unstuff_bits(raw_csd, 47, 1), unstuff_bits(raw_csd, 29, 2),
|
unstuff_bits(raw_csd, 47, 1), unstuff_bits(raw_csd, 29, 2),
|
||||||
unstuff_bits(raw_csd, 16, 5), unstuff_bits(raw_csd, 8, 2));
|
unstuff_bits(raw_csd, 16, 5), unstuff_bits(raw_csd, 8, 2));
|
||||||
}
|
}
|
||||||
@@ -870,39 +928,39 @@ void _sd_storage_debug_print_ssr(const u8 *raw_ssr)
|
|||||||
|
|
||||||
gfx_printf("\nSD Status:\n");
|
gfx_printf("\nSD Status:\n");
|
||||||
|
|
||||||
gfx_printf("DAT_BUS_WIDTH: %X\n", unstuff_bits(raw_ssr0, 510 - 384, 2));
|
gfx_printf("DAT_BUS_WIDTH: %X\n", unstuff_bits(raw_ssr0, 510, 2));
|
||||||
gfx_printf("SECURED_MODE: %X\n", unstuff_bits(raw_ssr0, 509 - 384, 1));
|
gfx_printf("SECURED_MODE: %X\n", unstuff_bits(raw_ssr0, 509, 1));
|
||||||
gfx_printf("SECURITY_FUNCTIONS: %02X\n", unstuff_bits(raw_ssr0, 502 - 384, 6));
|
gfx_printf("SECURITY_FUNCTIONS: %02X\n", unstuff_bits(raw_ssr0, 502, 6));
|
||||||
gfx_printf("SD_CARD_TYPE: %04X\n", unstuff_bits(raw_ssr0, 480 - 384, 16));
|
gfx_printf("SD_CARD_TYPE: %04X\n", unstuff_bits(raw_ssr0, 480, 16));
|
||||||
gfx_printf("SZ_OF_PROTECTED_AREA: %08X\n", unstuff_bits(raw_ssr0, 448 - 384, 32));
|
gfx_printf("SZ_OF_PROTECTED_AREA: %08X\n", unstuff_bits(raw_ssr0, 448, 32));
|
||||||
gfx_printf("SPEED_CLASS: %02X\n", unstuff_bits(raw_ssr0, 440 - 384, 8));
|
gfx_printf("SPEED_CLASS: %02X\n", unstuff_bits(raw_ssr0, 440, 8));
|
||||||
gfx_printf("PERFORMANCE_MOVE: %02X\n", unstuff_bits(raw_ssr0, 432 - 384, 8));
|
gfx_printf("PERFORMANCE_MOVE: %02X\n", unstuff_bits(raw_ssr0, 432, 8));
|
||||||
gfx_printf("AU_SIZE: %X\n", unstuff_bits(raw_ssr0, 428 - 384, 4));
|
gfx_printf("AU_SIZE: %X\n", unstuff_bits(raw_ssr0, 428, 4));
|
||||||
gfx_printf("ERAZE_SIZE: %04X\n", unstuff_bits(raw_ssr0, 408 - 384, 16));
|
gfx_printf("ERAZE_SIZE: %04X\n", unstuff_bits(raw_ssr0, 408, 16));
|
||||||
gfx_printf("ERASE_TIMEOUT: %02X\n", unstuff_bits(raw_ssr0, 402 - 384, 6));
|
gfx_printf("ERASE_TIMEOUT: %02X\n", unstuff_bits(raw_ssr0, 402, 6));
|
||||||
gfx_printf("ERASE_OFFSET: %X\n", unstuff_bits(raw_ssr0, 400 - 384, 2));
|
gfx_printf("ERASE_OFFSET: %X\n", unstuff_bits(raw_ssr0, 400, 2));
|
||||||
gfx_printf("UHS_SPEED_GRADE: %X\n", unstuff_bits(raw_ssr0, 396 - 384, 4));
|
gfx_printf("UHS_SPEED_GRADE: %X\n", unstuff_bits(raw_ssr0, 396, 4));
|
||||||
gfx_printf("UHS_AU_SIZE: %X\n", unstuff_bits(raw_ssr0, 392 - 384, 4));
|
gfx_printf("UHS_AU_SIZE: %X\n", unstuff_bits(raw_ssr0, 392, 4));
|
||||||
gfx_printf("VIDEO_SPEED_CLASS: %02X\n", unstuff_bits(raw_ssr0, 384 - 384, 8));
|
gfx_printf("VIDEO_SPEED_CLASS: %02X\n", unstuff_bits(raw_ssr0, 384, 8));
|
||||||
|
|
||||||
gfx_printf("VSC_AU_SIZE: %03X\n", unstuff_bits(raw_ssr1, 368 - 256, 10));
|
gfx_printf("VSC_AU_SIZE: %03X\n", unstuff_bits(raw_ssr1, 368, 10));
|
||||||
gfx_printf("SUS_ADDR: %06X\n", unstuff_bits(raw_ssr1, 346 - 256, 22));
|
gfx_printf("SUS_ADDR: %06X\n", unstuff_bits(raw_ssr1, 346, 22));
|
||||||
gfx_printf("APP_PERF_CLASS: %X\n", unstuff_bits(raw_ssr1, 336 - 256, 4));
|
gfx_printf("APP_PERF_CLASS: %X\n", unstuff_bits(raw_ssr1, 336, 4));
|
||||||
gfx_printf("PERFORMANCE_ENHANCE: %02X\n", unstuff_bits(raw_ssr1, 328 - 256, 8));
|
gfx_printf("PERFORMANCE_ENHANCE: %02X\n", unstuff_bits(raw_ssr1, 328, 8));
|
||||||
gfx_printf("DISCARD_SUPPORT: %X\n", unstuff_bits(raw_ssr1, 313 - 256, 1));
|
gfx_printf("DISCARD_SUPPORT: %X\n", unstuff_bits(raw_ssr1, 313, 1));
|
||||||
gfx_printf("FULE_SUPPORT: %X\n", unstuff_bits(raw_ssr1, 312 - 256, 1));
|
gfx_printf("FULE_SUPPORT: %X\n", unstuff_bits(raw_ssr1, 312, 1));
|
||||||
|
|
||||||
gfx_printf("--RSVD-- %02X %X %02X %02X %04X\n",
|
gfx_printf("--RSVD-- %02X %X %02X %02X %04X\n",
|
||||||
unstuff_bits(raw_ssr0, 496 - 384, 6), unstuff_bits(raw_ssr0, 424 - 384, 4),
|
unstuff_bits(raw_ssr0, 496, 6), unstuff_bits(raw_ssr0, 424, 4),
|
||||||
unstuff_bits(raw_ssr1, 378 - 256, 6), unstuff_bits(raw_ssr1, 340 - 256, 6),
|
unstuff_bits(raw_ssr1, 378, 6), unstuff_bits(raw_ssr1, 340, 6),
|
||||||
unstuff_bits(raw_ssr1, 314 - 256, 14));
|
unstuff_bits(raw_ssr1, 314, 14));
|
||||||
|
|
||||||
gfx_printf("VENDOR_1: %06X %08X\n",
|
gfx_printf("VENDOR_1: %06X %08X\n",
|
||||||
unstuff_bits(raw_ssr1, 288 - 256, 24), unstuff_bits(raw_ssr1, 256 - 256, 32));
|
unstuff_bits(raw_ssr1, 288, 24), unstuff_bits(raw_ssr1, 256, 32));
|
||||||
|
|
||||||
gfx_printf("VENDOR_2: %08X %08X %08X %08X\n",
|
gfx_printf("VENDOR_2: %08X %08X %08X %08X\n",
|
||||||
unstuff_bits(raw_ssr2, 224 - 128, 32), unstuff_bits(raw_ssr2, 192 - 128, 32),
|
unstuff_bits(raw_ssr2, 224, 32), unstuff_bits(raw_ssr2, 192, 32),
|
||||||
unstuff_bits(raw_ssr2, 160 - 128, 32), unstuff_bits(raw_ssr2, 128 - 128, 32));
|
unstuff_bits(raw_ssr2, 160, 32), unstuff_bits(raw_ssr2, 128, 32));
|
||||||
gfx_printf("VENDOR_3: %08X %08X %08X %08X\n",
|
gfx_printf("VENDOR_3: %08X %08X %08X %08X\n",
|
||||||
unstuff_bits(raw_ssr3, 96 - 0, 32), unstuff_bits(raw_ssr3, 64, 32),
|
unstuff_bits(raw_ssr3, 96 - 0, 32), unstuff_bits(raw_ssr3, 64, 32),
|
||||||
unstuff_bits(raw_ssr3, 32 - 0, 32), unstuff_bits(raw_ssr3, 0, 32));
|
unstuff_bits(raw_ssr3, 32 - 0, 32), unstuff_bits(raw_ssr3, 0, 32));
|
||||||
@@ -916,13 +974,19 @@ static int _sd_storage_send_if_cond(sdmmc_storage_t *storage, bool *is_sdsc)
|
|||||||
sdmmc_init_cmd(&cmdbuf, SD_SEND_IF_COND, vhd_pattern, SDMMC_RSP_TYPE_5, 0);
|
sdmmc_init_cmd(&cmdbuf, SD_SEND_IF_COND, vhd_pattern, SDMMC_RSP_TYPE_5, 0);
|
||||||
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, NULL, NULL))
|
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, NULL, NULL))
|
||||||
{
|
{
|
||||||
*is_sdsc = 1; // The SD Card is version 1.X
|
// The SD Card is version 1.X (SDSC) if there is no response.
|
||||||
return 1;
|
if (storage->sdmmc->error_sts == SDHCI_ERR_INT_CMD_TIMEOUT)
|
||||||
|
{
|
||||||
|
*is_sdsc = 1;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// For Card version >= 2.0, parse results.
|
// For Card version >= 2.0, parse results.
|
||||||
u32 resp = 0;
|
u32 resp = 0;
|
||||||
sdmmc_get_rsp(storage->sdmmc, &resp, 4, SDMMC_RSP_TYPE_5);
|
sdmmc_get_cached_rsp(storage->sdmmc, &resp, SDMMC_RSP_TYPE_5);
|
||||||
|
|
||||||
// Check if VHD was accepted and pattern was properly returned.
|
// Check if VHD was accepted and pattern was properly returned.
|
||||||
if ((resp & 0xFFF) == vhd_pattern)
|
if ((resp & 0xFFF) == vhd_pattern)
|
||||||
@@ -948,7 +1012,7 @@ static int _sd_storage_get_op_cond_once(sdmmc_storage_t *storage, u32 *cond, boo
|
|||||||
if (!_sd_storage_execute_app_cmd(storage, R1_SKIP_STATE_CHECK, is_sdsc ? R1_ILLEGAL_COMMAND : 0, &cmdbuf, NULL, NULL))
|
if (!_sd_storage_execute_app_cmd(storage, R1_SKIP_STATE_CHECK, is_sdsc ? R1_ILLEGAL_COMMAND : 0, &cmdbuf, NULL, NULL))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return sdmmc_get_rsp(storage->sdmmc, cond, 4, SDMMC_RSP_TYPE_3);
|
return sdmmc_get_cached_rsp(storage->sdmmc, cond, SDMMC_RSP_TYPE_3);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _sd_storage_get_op_cond(sdmmc_storage_t *storage, bool is_sdsc, int bus_uhs_support)
|
static int _sd_storage_get_op_cond(sdmmc_storage_t *storage, bool is_sdsc, int bus_uhs_support)
|
||||||
@@ -971,7 +1035,7 @@ static int _sd_storage_get_op_cond(sdmmc_storage_t *storage, bool is_sdsc, int b
|
|||||||
storage->has_sector_access = 1;
|
storage->has_sector_access = 1;
|
||||||
|
|
||||||
// Check if card supports 1.8V signaling.
|
// Check if card supports 1.8V signaling.
|
||||||
if (cond & SD_ROCR_S18A && bus_uhs_support)
|
if (cond & SD_ROCR_S18A && bus_uhs_support && !storage->is_low_voltage)
|
||||||
{
|
{
|
||||||
// Switch to 1.8V signaling.
|
// Switch to 1.8V signaling.
|
||||||
if (_sdmmc_storage_execute_cmd_type1(storage, SD_SWITCH_VOLTAGE, 0, 0, R1_STATE_READY))
|
if (_sdmmc_storage_execute_cmd_type1(storage, SD_SWITCH_VOLTAGE, 0, 0, R1_STATE_READY))
|
||||||
@@ -1015,7 +1079,7 @@ static int _sd_storage_get_rca(sdmmc_storage_t *storage)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
u32 resp = 0;
|
u32 resp = 0;
|
||||||
if (!sdmmc_get_rsp(storage->sdmmc, &resp, 4, SDMMC_RSP_TYPE_4))
|
if (!sdmmc_get_cached_rsp(storage->sdmmc, &resp, SDMMC_RSP_TYPE_4))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (resp >> 16)
|
if (resp >> 16)
|
||||||
@@ -1046,11 +1110,17 @@ static void _sd_storage_parse_scr(sdmmc_storage_t *storage)
|
|||||||
storage->scr.sda_vsn = unstuff_bits(resp, 56, 4);
|
storage->scr.sda_vsn = unstuff_bits(resp, 56, 4);
|
||||||
storage->scr.bus_widths = unstuff_bits(resp, 48, 4);
|
storage->scr.bus_widths = unstuff_bits(resp, 48, 4);
|
||||||
|
|
||||||
/* If v2.0 is supported, check if Physical Layer Spec v3.0 is supported */
|
// If v2.0 is supported, check if Physical Layer Spec v3.0 is supported.
|
||||||
if (storage->scr.sda_vsn == SCR_SPEC_VER_2)
|
if (storage->scr.sda_vsn == SCR_SPEC_VER_2)
|
||||||
storage->scr.sda_spec3 = unstuff_bits(resp, 47, 1);
|
storage->scr.sda_spec3 = unstuff_bits(resp, 47, 1);
|
||||||
if (storage->scr.sda_spec3)
|
if (storage->scr.sda_spec3)
|
||||||
storage->scr.cmds = unstuff_bits(resp, 32, 2);
|
{
|
||||||
|
u8 sda_spec4 = unstuff_bits(resp, 42, 1);
|
||||||
|
if (sda_spec4)
|
||||||
|
storage->scr.cmds = unstuff_bits(resp, 32, 4);
|
||||||
|
else
|
||||||
|
storage->scr.cmds = unstuff_bits(resp, 32, 2);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int sd_storage_get_scr(sdmmc_storage_t *storage, u8 *buf)
|
int sd_storage_get_scr(sdmmc_storage_t *storage, u8 *buf)
|
||||||
@@ -1070,9 +1140,9 @@ int sd_storage_get_scr(sdmmc_storage_t *storage, u8 *buf)
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
u32 tmp = 0;
|
u32 tmp = 0;
|
||||||
sdmmc_get_rsp(storage->sdmmc, &tmp, 4, SDMMC_RSP_TYPE_1);
|
sdmmc_get_cached_rsp(storage->sdmmc, &tmp, SDMMC_RSP_TYPE_1);
|
||||||
//Prepare buffer for unstuff_bits
|
//Prepare buffer for unstuff_bits
|
||||||
for (int i = 0; i < 8; i+=4)
|
for (u32 i = 0; i < 8; i+=4)
|
||||||
{
|
{
|
||||||
storage->raw_scr[i + 3] = buf[i];
|
storage->raw_scr[i + 3] = buf[i];
|
||||||
storage->raw_scr[i + 2] = buf[i + 1];
|
storage->raw_scr[i + 2] = buf[i + 1];
|
||||||
@@ -1101,7 +1171,7 @@ static int _sd_storage_switch_get(sdmmc_storage_t *storage, void *buf)
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
u32 tmp = 0;
|
u32 tmp = 0;
|
||||||
sdmmc_get_rsp(storage->sdmmc, &tmp, 4, SDMMC_RSP_TYPE_1);
|
sdmmc_get_cached_rsp(storage->sdmmc, &tmp, SDMMC_RSP_TYPE_1);
|
||||||
return _sdmmc_storage_check_card_status(tmp);
|
return _sdmmc_storage_check_card_status(tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1125,7 +1195,7 @@ static int _sd_storage_switch(sdmmc_storage_t *storage, void *buf, int mode, int
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
u32 tmp = 0;
|
u32 tmp = 0;
|
||||||
sdmmc_get_rsp(storage->sdmmc, &tmp, 4, SDMMC_RSP_TYPE_1);
|
sdmmc_get_cached_rsp(storage->sdmmc, &tmp, SDMMC_RSP_TYPE_1);
|
||||||
return _sdmmc_storage_check_card_status(tmp);
|
return _sdmmc_storage_check_card_status(tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1241,7 +1311,7 @@ static int _sd_storage_enable_DDR200(sdmmc_storage_t *storage, u8 *buf)
|
|||||||
|
|
||||||
u16 total_pwr_consumption = ((u16)buf[0] << 8) | buf[1];
|
u16 total_pwr_consumption = ((u16)buf[0] << 8) | buf[1];
|
||||||
DPRINTF("[SD] max power: %d mW\n", total_pwr_consumption * 3600 / 1000);
|
DPRINTF("[SD] max power: %d mW\n", total_pwr_consumption * 3600 / 1000);
|
||||||
storage->card_power_limit = total_pwr_consumption;
|
storage->max_power = total_pwr_consumption;
|
||||||
|
|
||||||
if (total_pwr_consumption <= 800)
|
if (total_pwr_consumption <= 800)
|
||||||
{
|
{
|
||||||
@@ -1280,7 +1350,7 @@ static int _sd_storage_set_card_bus_speed(sdmmc_storage_t *storage, u32 hs_type,
|
|||||||
|
|
||||||
u16 total_pwr_consumption = ((u16)buf[0] << 8) | buf[1];
|
u16 total_pwr_consumption = ((u16)buf[0] << 8) | buf[1];
|
||||||
DPRINTF("[SD] max power: %d mW\n", total_pwr_consumption * 3600 / 1000);
|
DPRINTF("[SD] max power: %d mW\n", total_pwr_consumption * 3600 / 1000);
|
||||||
storage->card_power_limit = total_pwr_consumption;
|
storage->max_power = total_pwr_consumption;
|
||||||
|
|
||||||
if (total_pwr_consumption <= 800)
|
if (total_pwr_consumption <= 800)
|
||||||
{
|
{
|
||||||
@@ -1492,10 +1562,10 @@ static void _sd_storage_parse_ssr(sdmmc_storage_t *storage)
|
|||||||
_sd_storage_debug_print_ssr(storage->raw_ssr);
|
_sd_storage_debug_print_ssr(storage->raw_ssr);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
storage->ssr.bus_width = (unstuff_bits(raw_ssr1, 510 - 384, 2) & SD_BUS_WIDTH_4) ? 4 : 1;
|
storage->ssr.bus_width = (unstuff_bits(raw_ssr1, 510, 2) & SD_BUS_WIDTH_4) ? 4 : 1;
|
||||||
storage->ssr.protected_size = unstuff_bits(raw_ssr1, 448 - 384, 32);
|
storage->ssr.protected_size = unstuff_bits(raw_ssr1, 448, 32);
|
||||||
|
|
||||||
u32 speed_class = unstuff_bits(raw_ssr1, 440 - 384, 8);
|
u32 speed_class = unstuff_bits(raw_ssr1, 440, 8);
|
||||||
switch(speed_class)
|
switch(speed_class)
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
@@ -1513,12 +1583,94 @@ static void _sd_storage_parse_ssr(sdmmc_storage_t *storage)
|
|||||||
storage->ssr.speed_class = speed_class;
|
storage->ssr.speed_class = speed_class;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
storage->ssr.uhs_grade = unstuff_bits(raw_ssr1, 396 - 384, 4);
|
storage->ssr.uhs_grade = unstuff_bits(raw_ssr1, 396, 4);
|
||||||
storage->ssr.video_class = unstuff_bits(raw_ssr1, 384 - 384, 8);
|
storage->ssr.video_class = unstuff_bits(raw_ssr1, 384, 8);
|
||||||
storage->ssr.app_class = unstuff_bits(raw_ssr2, 336 - 256, 4);
|
storage->ssr.app_class = unstuff_bits(raw_ssr2, 336, 4);
|
||||||
|
|
||||||
storage->ssr.au_size = unstuff_bits(raw_ssr1, 428 - 384, 4);
|
storage->ssr.au_size = unstuff_bits(raw_ssr1, 428, 4);
|
||||||
storage->ssr.uhs_au_size = unstuff_bits(raw_ssr1, 392 - 384, 4);
|
storage->ssr.uhs_au_size = unstuff_bits(raw_ssr1, 392, 4);
|
||||||
|
|
||||||
|
storage->ssr.perf_enhance = unstuff_bits(raw_ssr2, 328, 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
int sd_storage_parse_perf_enhance(sdmmc_storage_t *storage, u8 fno, u8 page, u16 offset, u8 *buf)
|
||||||
|
{
|
||||||
|
// Check status reg for support.
|
||||||
|
storage->ser.cache = (storage->ssr.perf_enhance >> 2) & BIT(0);
|
||||||
|
storage->ser.cmdq = (storage->ssr.perf_enhance >> 3) & 0x1F;
|
||||||
|
|
||||||
|
if (!sd_storage_get_ext_reg(storage, fno, page, offset, 512, buf))
|
||||||
|
{
|
||||||
|
storage->ser.cache_ext = 0;
|
||||||
|
storage->ser.cmdq_ext = 0;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
storage->ser.cache_ext = buf[4] & BIT(0);
|
||||||
|
storage->ser.cmdq_ext = buf[6] & 0x1F;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _sd_storage_parse_ext_reg(sdmmc_storage_t *storage, u8 *buf, u16 *addr_next)
|
||||||
|
{
|
||||||
|
u16 addr = *addr_next;
|
||||||
|
|
||||||
|
// Address to the next extension.
|
||||||
|
*addr_next = (buf[addr + 41] << 8) | buf[addr + 40];
|
||||||
|
|
||||||
|
u16 sfc = (buf[addr + 1] << 8) | buf[addr];
|
||||||
|
|
||||||
|
u32 reg_sets = buf[addr + 42];
|
||||||
|
|
||||||
|
#ifdef SDMMC_DEBUG_PRINT_SD_REGS
|
||||||
|
for (u32 i = 0; i < reg_sets; i++)
|
||||||
|
{
|
||||||
|
u32 reg_set_addr;
|
||||||
|
memcpy(®_set_addr, &buf[addr + 44 + 4 * i], 4);
|
||||||
|
u16 off = reg_set_addr & 0x1FF;
|
||||||
|
u8 page = reg_set_addr >> 9 & 0xFF;
|
||||||
|
u8 fno = reg_set_addr >> 18 & 0xFF;
|
||||||
|
gfx_printf("Addr: %04X sfc:%02X - fno:%02X, page:%02X, off:%04X\n", addr, sfc, fno, page, off);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Parse Performance Enhance.
|
||||||
|
if (sfc == 2 && reg_sets == 1)
|
||||||
|
{
|
||||||
|
u32 reg_set0_addr;
|
||||||
|
memcpy(®_set0_addr, &buf[addr + 44], 4);
|
||||||
|
u16 off = reg_set0_addr & 0x1FF;
|
||||||
|
u8 page = reg_set0_addr >> 9 & 0xFF;
|
||||||
|
u8 fno = reg_set0_addr >> 18 & 0xFF;
|
||||||
|
|
||||||
|
if (sd_storage_parse_perf_enhance(storage, fno, page, off, buf))
|
||||||
|
storage->ser.valid = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void sd_storage_get_ext_regs(sdmmc_storage_t *storage, u8 *buf)
|
||||||
|
{
|
||||||
|
DREGPRINTF("SD Extension Registers:\n\n");
|
||||||
|
|
||||||
|
if (!(storage->scr.cmds & BIT(2)))
|
||||||
|
{
|
||||||
|
DREGPRINTF("Not Supported!\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!sd_storage_get_ext_reg(storage, 0, 0, 0, 512, buf))
|
||||||
|
{
|
||||||
|
DREGPRINTF("Failed to get general info!\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
u16 size = (buf[3] << 8) | buf[2];
|
||||||
|
u16 addr_next = 16;
|
||||||
|
u32 num_ext = buf[4];
|
||||||
|
for (u32 i = 0; i < num_ext && addr_next < size; i++)
|
||||||
|
_sd_storage_parse_ext_reg(storage, buf, &addr_next);
|
||||||
}
|
}
|
||||||
|
|
||||||
int sd_storage_get_ssr(sdmmc_storage_t *storage, u8 *buf)
|
int sd_storage_get_ssr(sdmmc_storage_t *storage, u8 *buf)
|
||||||
@@ -1544,10 +1696,10 @@ int sd_storage_get_ssr(sdmmc_storage_t *storage, u8 *buf)
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
u32 tmp = 0;
|
u32 tmp = 0;
|
||||||
sdmmc_get_rsp(storage->sdmmc, &tmp, 4, SDMMC_RSP_TYPE_1);
|
sdmmc_get_cached_rsp(storage->sdmmc, &tmp, SDMMC_RSP_TYPE_1);
|
||||||
|
|
||||||
// Convert buffer to LE.
|
// Convert buffer to LE.
|
||||||
for (int i = 0; i < SDMMC_CMD_BLOCKSIZE; i += 4)
|
for (u32 i = 0; i < SDMMC_CMD_BLOCKSIZE; i += 4)
|
||||||
{
|
{
|
||||||
storage->raw_ssr[i + 3] = buf[i];
|
storage->raw_ssr[i + 3] = buf[i];
|
||||||
storage->raw_ssr[i + 2] = buf[i + 1];
|
storage->raw_ssr[i + 2] = buf[i + 1];
|
||||||
@@ -1644,7 +1796,7 @@ void sdmmc_storage_init_wait_sd()
|
|||||||
int sdmmc_storage_init_sd(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 bus_width, u32 type)
|
int sdmmc_storage_init_sd(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 bus_width, u32 type)
|
||||||
{
|
{
|
||||||
u32 tmp = 0;
|
u32 tmp = 0;
|
||||||
int is_sdsc = 0;
|
bool is_sdsc = 0;
|
||||||
u8 *buf = (u8 *)SDMMC_UPPER_BUFFER;
|
u8 *buf = (u8 *)SDMMC_UPPER_BUFFER;
|
||||||
bool bus_uhs_support = _sdmmc_storage_get_bus_uhs_support(bus_width, type);
|
bool bus_uhs_support = _sdmmc_storage_get_bus_uhs_support(bus_width, type);
|
||||||
|
|
||||||
@@ -1789,7 +1941,7 @@ int _gc_storage_custom_cmd(sdmmc_storage_t *storage, void *buf)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!sdmmc_get_rsp(storage->sdmmc, &resp, 4, SDMMC_RSP_TYPE_1))
|
if (!sdmmc_get_cached_rsp(storage->sdmmc, &resp, SDMMC_RSP_TYPE_1))
|
||||||
return 0;
|
return 0;
|
||||||
if (!_sdmmc_storage_check_card_status(resp))
|
if (!_sdmmc_storage_check_card_status(resp))
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2018 naehrwert
|
* Copyright (c) 2018 naehrwert
|
||||||
* Copyright (c) 2018-2022 CTCaer
|
* Copyright (c) 2018-2025 CTCaer
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
* under the terms and conditions of the GNU General Public License,
|
* under the terms and conditions of the GNU General Public License,
|
||||||
@@ -35,6 +35,7 @@ typedef enum _sdmmc_type
|
|||||||
MMC_EMUMMC_RAW_SD = 3,
|
MMC_EMUMMC_RAW_SD = 3,
|
||||||
MMC_EMUMMC_RAW_EMMC = 4,
|
MMC_EMUMMC_RAW_EMMC = 4,
|
||||||
MMC_EMUMMC_FILE_EMMC = 5,
|
MMC_EMUMMC_FILE_EMMC = 5,
|
||||||
|
MMC_FILE_BASED = 6,
|
||||||
|
|
||||||
EMMC_GPP = 0,
|
EMMC_GPP = 0,
|
||||||
EMMC_BOOT0 = 1,
|
EMMC_BOOT0 = 1,
|
||||||
@@ -178,20 +179,30 @@ typedef struct _sd_ssr
|
|||||||
u8 app_class;
|
u8 app_class;
|
||||||
u8 au_size;
|
u8 au_size;
|
||||||
u8 uhs_au_size;
|
u8 uhs_au_size;
|
||||||
|
u8 perf_enhance;
|
||||||
u32 protected_size;
|
u32 protected_size;
|
||||||
} sd_ssr_t;
|
} sd_ssr_t;
|
||||||
|
|
||||||
|
typedef struct _sd_ext_reg_t
|
||||||
|
{
|
||||||
|
u8 cmdq;
|
||||||
|
u8 cmdq_ext;
|
||||||
|
u8 cache;
|
||||||
|
u8 cache_ext;
|
||||||
|
int valid;
|
||||||
|
} sd_ext_reg_t;
|
||||||
|
|
||||||
/*! SDMMC storage context. */
|
/*! SDMMC storage context. */
|
||||||
typedef struct _sdmmc_storage_t
|
typedef struct _sdmmc_storage_t
|
||||||
{
|
{
|
||||||
sdmmc_t *sdmmc;
|
sdmmc_t *sdmmc;
|
||||||
u32 rca;
|
|
||||||
int has_sector_access;
|
|
||||||
u32 sec_cnt;
|
|
||||||
int is_low_voltage;
|
|
||||||
u32 partition;
|
|
||||||
int initialized;
|
int initialized;
|
||||||
u32 card_power_limit;
|
int is_low_voltage;
|
||||||
|
int has_sector_access;
|
||||||
|
u32 rca;
|
||||||
|
u32 sec_cnt;
|
||||||
|
u32 partition;
|
||||||
|
u32 max_power;
|
||||||
u8 raw_cid[0x10];
|
u8 raw_cid[0x10];
|
||||||
u8 raw_csd[0x10];
|
u8 raw_csd[0x10];
|
||||||
u8 raw_scr[8];
|
u8 raw_scr[8];
|
||||||
@@ -201,6 +212,7 @@ typedef struct _sdmmc_storage_t
|
|||||||
mmc_ext_csd_t ext_csd;
|
mmc_ext_csd_t ext_csd;
|
||||||
sd_scr_t scr;
|
sd_scr_t scr;
|
||||||
sd_ssr_t ssr;
|
sd_ssr_t ssr;
|
||||||
|
sd_ext_reg_t ser;
|
||||||
} sdmmc_storage_t;
|
} sdmmc_storage_t;
|
||||||
|
|
||||||
typedef struct _sd_func_modes_t
|
typedef struct _sd_func_modes_t
|
||||||
@@ -225,9 +237,13 @@ int sdmmc_storage_vendor_sandisk_report(sdmmc_storage_t *storage, void *buf);
|
|||||||
|
|
||||||
int mmc_storage_get_ext_csd(sdmmc_storage_t *storage, void *buf);
|
int mmc_storage_get_ext_csd(sdmmc_storage_t *storage, void *buf);
|
||||||
|
|
||||||
|
int sd_storage_get_ext_reg(sdmmc_storage_t *storage, u8 fno, u8 page, u16 offset, u32 len, void *buf);
|
||||||
int sd_storage_get_fmodes(sdmmc_storage_t *storage, u8 *buf, sd_func_modes_t *functions);
|
int sd_storage_get_fmodes(sdmmc_storage_t *storage, u8 *buf, sd_func_modes_t *functions);
|
||||||
int sd_storage_get_scr(sdmmc_storage_t *storage, u8 *buf);
|
int sd_storage_get_scr(sdmmc_storage_t *storage, u8 *buf);
|
||||||
int sd_storage_get_ssr(sdmmc_storage_t *storage, u8 *buf);
|
int sd_storage_get_ssr(sdmmc_storage_t *storage, u8 *buf);
|
||||||
u32 sd_storage_get_ssr_au(sdmmc_storage_t *storage);
|
u32 sd_storage_get_ssr_au(sdmmc_storage_t *storage);
|
||||||
|
|
||||||
|
void sd_storage_get_ext_regs(sdmmc_storage_t *storage, u8 *buf);
|
||||||
|
int sd_storage_parse_perf_enhance(sdmmc_storage_t *storage, u8 fno, u8 page, u16 offset, u8 *buf);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2018 naehrwert
|
* Copyright (c) 2018 naehrwert
|
||||||
* Copyright (c) 2018-2024 CTCaer
|
* Copyright (c) 2018-2025 CTCaer
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
* under the terms and conditions of the GNU General Public License,
|
* under the terms and conditions of the GNU General Public License,
|
||||||
@@ -212,7 +212,7 @@ static void _sdmmc_autocal_execute(sdmmc_t *sdmmc, u32 power)
|
|||||||
// Use 0x1F mask for all.
|
// Use 0x1F mask for all.
|
||||||
u8 autocal_pu_status = sdmmc->regs->autocalsts & 0x1F;
|
u8 autocal_pu_status = sdmmc->regs->autocalsts & 0x1F;
|
||||||
if (!autocal_pu_status)
|
if (!autocal_pu_status)
|
||||||
EPRINTFARGS("SDMMC%d: Comp Pad open!", sdmmc->id + 1);
|
EPRINTFARGS("SDMMC%d: Comp Pad open!", sdmmc->id + 1); // Or resistance is extreme.
|
||||||
else if (autocal_pu_status == 0x1F)
|
else if (autocal_pu_status == 0x1F)
|
||||||
EPRINTFARGS("SDMMC%d: Comp Pad short to gnd!", sdmmc->id + 1);
|
EPRINTFARGS("SDMMC%d: Comp Pad short to gnd!", sdmmc->id + 1);
|
||||||
#endif
|
#endif
|
||||||
@@ -394,8 +394,8 @@ int sdmmc_setup_clock(sdmmc_t *sdmmc, u32 type)
|
|||||||
|
|
||||||
static void _sdmmc_card_clock_enable(sdmmc_t *sdmmc)
|
static void _sdmmc_card_clock_enable(sdmmc_t *sdmmc)
|
||||||
{
|
{
|
||||||
// Recalibrate conditionally.
|
// Recalibrate periodically if needed.
|
||||||
if (sdmmc->manual_cal && !sdmmc->powersave_enabled)
|
if (sdmmc->periodic_calibration && !sdmmc->powersave_enabled)
|
||||||
_sdmmc_autocal_execute(sdmmc, sdmmc_get_io_power(sdmmc));
|
_sdmmc_autocal_execute(sdmmc, sdmmc_get_io_power(sdmmc));
|
||||||
|
|
||||||
if (!sdmmc->powersave_enabled)
|
if (!sdmmc->powersave_enabled)
|
||||||
@@ -414,8 +414,8 @@ static void _sdmmc_card_clock_disable(sdmmc_t *sdmmc)
|
|||||||
|
|
||||||
void sdmmc_card_clock_powersave(sdmmc_t *sdmmc, int powersave_enable)
|
void sdmmc_card_clock_powersave(sdmmc_t *sdmmc, int powersave_enable)
|
||||||
{
|
{
|
||||||
// Recalibrate periodically for SDMMC1.
|
// Recalibrate periodically if needed.
|
||||||
if (sdmmc->manual_cal && !powersave_enable && sdmmc->card_clock_enabled)
|
if (sdmmc->periodic_calibration && !powersave_enable && sdmmc->card_clock_enabled)
|
||||||
_sdmmc_autocal_execute(sdmmc, sdmmc_get_io_power(sdmmc));
|
_sdmmc_autocal_execute(sdmmc, sdmmc_get_io_power(sdmmc));
|
||||||
|
|
||||||
sdmmc->powersave_enabled = powersave_enable;
|
sdmmc->powersave_enabled = powersave_enable;
|
||||||
@@ -431,7 +431,7 @@ void sdmmc_card_clock_powersave(sdmmc_t *sdmmc, int powersave_enable)
|
|||||||
sdmmc->regs->clkcon |= SDHCI_CLOCK_CARD_EN;
|
sdmmc->regs->clkcon |= SDHCI_CLOCK_CARD_EN;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _sdmmc_cache_rsp(sdmmc_t *sdmmc, u32 *rsp, u32 size, u32 type)
|
static int _sdmmc_cache_rsp(sdmmc_t *sdmmc, u32 *rsp, u32 type)
|
||||||
{
|
{
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
@@ -439,33 +439,14 @@ static int _sdmmc_cache_rsp(sdmmc_t *sdmmc, u32 *rsp, u32 size, u32 type)
|
|||||||
case SDMMC_RSP_TYPE_3:
|
case SDMMC_RSP_TYPE_3:
|
||||||
case SDMMC_RSP_TYPE_4:
|
case SDMMC_RSP_TYPE_4:
|
||||||
case SDMMC_RSP_TYPE_5:
|
case SDMMC_RSP_TYPE_5:
|
||||||
if (size < 4)
|
rsp[0] = sdmmc->regs->rspreg[0];
|
||||||
return 0;
|
|
||||||
rsp[0] = sdmmc->regs->rspreg0;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SDMMC_RSP_TYPE_2:
|
case SDMMC_RSP_TYPE_2:
|
||||||
if (size < 0x10)
|
|
||||||
return 0;
|
|
||||||
// CRC is stripped, so shifting is needed.
|
// CRC is stripped, so shifting is needed.
|
||||||
u32 tempreg;
|
for (u32 i = 0; i < 4; i++)
|
||||||
for (int i = 0; i < 4; i++)
|
|
||||||
{
|
{
|
||||||
switch(i)
|
u32 tempreg = sdmmc->regs->rspreg[3 - i];
|
||||||
{
|
|
||||||
case 0:
|
|
||||||
tempreg = sdmmc->regs->rspreg3;
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
tempreg = sdmmc->regs->rspreg2;
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
tempreg = sdmmc->regs->rspreg1;
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
tempreg = sdmmc->regs->rspreg0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
rsp[i] = tempreg << 8;
|
rsp[i] = tempreg << 8;
|
||||||
|
|
||||||
if (i != 0)
|
if (i != 0)
|
||||||
@@ -480,7 +461,7 @@ static int _sdmmc_cache_rsp(sdmmc_t *sdmmc, u32 *rsp, u32 size, u32 type)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int sdmmc_get_rsp(sdmmc_t *sdmmc, u32 *rsp, u32 size, u32 type)
|
int sdmmc_get_cached_rsp(sdmmc_t *sdmmc, u32 *rsp, u32 type)
|
||||||
{
|
{
|
||||||
if (!rsp || sdmmc->expected_rsp_type != type)
|
if (!rsp || sdmmc->expected_rsp_type != type)
|
||||||
return 0;
|
return 0;
|
||||||
@@ -491,18 +472,12 @@ int sdmmc_get_rsp(sdmmc_t *sdmmc, u32 *rsp, u32 size, u32 type)
|
|||||||
case SDMMC_RSP_TYPE_3:
|
case SDMMC_RSP_TYPE_3:
|
||||||
case SDMMC_RSP_TYPE_4:
|
case SDMMC_RSP_TYPE_4:
|
||||||
case SDMMC_RSP_TYPE_5:
|
case SDMMC_RSP_TYPE_5:
|
||||||
if (size < 4)
|
|
||||||
return 0;
|
|
||||||
rsp[0] = sdmmc->rsp[0];
|
rsp[0] = sdmmc->rsp[0];
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SDMMC_RSP_TYPE_2:
|
case SDMMC_RSP_TYPE_2:
|
||||||
if (size < 16)
|
for (u32 i = 0; i < 4; i++)
|
||||||
return 0;
|
rsp[i] = sdmmc->rsp[i];
|
||||||
rsp[0] = sdmmc->rsp[0];
|
|
||||||
rsp[1] = sdmmc->rsp[1];
|
|
||||||
rsp[2] = sdmmc->rsp[2];
|
|
||||||
rsp[3] = sdmmc->rsp[3];
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@@ -915,6 +890,7 @@ static void _sdmmc_enable_interrupts(sdmmc_t *sdmmc)
|
|||||||
sdmmc->regs->errintstsen |= SDHCI_ERR_INT_ALL_EXCEPT_ADMA_BUSPWR;
|
sdmmc->regs->errintstsen |= SDHCI_ERR_INT_ALL_EXCEPT_ADMA_BUSPWR;
|
||||||
sdmmc->regs->norintsts = sdmmc->regs->norintsts;
|
sdmmc->regs->norintsts = sdmmc->regs->norintsts;
|
||||||
sdmmc->regs->errintsts = sdmmc->regs->errintsts;
|
sdmmc->regs->errintsts = sdmmc->regs->errintsts;
|
||||||
|
sdmmc->error_sts = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _sdmmc_mask_interrupts(sdmmc_t *sdmmc)
|
static void _sdmmc_mask_interrupts(sdmmc_t *sdmmc)
|
||||||
@@ -937,8 +913,9 @@ static u32 _sdmmc_check_mask_interrupt(sdmmc_t *sdmmc, u16 *pout, u16 mask)
|
|||||||
if (norintsts & SDHCI_INT_ERROR)
|
if (norintsts & SDHCI_INT_ERROR)
|
||||||
{
|
{
|
||||||
#ifdef ERROR_EXTRA_PRINTING
|
#ifdef ERROR_EXTRA_PRINTING
|
||||||
EPRINTFARGS("SDMMC%d: norintsts %08X, errintsts %08X", sdmmc->id + 1, norintsts, errintsts);
|
EPRINTFARGS("SDMMC%d: intsts %08X, errintsts %08X", sdmmc->id + 1, norintsts, errintsts);
|
||||||
#endif
|
#endif
|
||||||
|
sdmmc->error_sts = errintsts;
|
||||||
sdmmc->regs->errintsts = errintsts;
|
sdmmc->regs->errintsts = errintsts;
|
||||||
return SDMMC_MASKINT_ERROR;
|
return SDMMC_MASKINT_ERROR;
|
||||||
}
|
}
|
||||||
@@ -993,7 +970,7 @@ static int _sdmmc_stop_transmission_inner(sdmmc_t *sdmmc, u32 *rsp)
|
|||||||
if (!result)
|
if (!result)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
_sdmmc_cache_rsp(sdmmc, rsp, 4, SDMMC_RSP_TYPE_1);
|
_sdmmc_cache_rsp(sdmmc, rsp, SDMMC_RSP_TYPE_1);
|
||||||
|
|
||||||
return _sdmmc_wait_card_busy(sdmmc);
|
return _sdmmc_wait_card_busy(sdmmc);
|
||||||
}
|
}
|
||||||
@@ -1003,8 +980,8 @@ int sdmmc_stop_transmission(sdmmc_t *sdmmc, u32 *rsp)
|
|||||||
if (!sdmmc->card_clock_enabled)
|
if (!sdmmc->card_clock_enabled)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
// Recalibrate periodically for SDMMC1.
|
// Recalibrate periodically if needed.
|
||||||
if (sdmmc->manual_cal && sdmmc->powersave_enabled)
|
if (sdmmc->periodic_calibration && sdmmc->powersave_enabled)
|
||||||
_sdmmc_autocal_execute(sdmmc, sdmmc_get_io_power(sdmmc));
|
_sdmmc_autocal_execute(sdmmc, sdmmc_get_io_power(sdmmc));
|
||||||
|
|
||||||
bool should_disable_sd_clock = false;
|
bool should_disable_sd_clock = false;
|
||||||
@@ -1120,7 +1097,7 @@ static int _sdmmc_update_sdma(sdmmc_t *sdmmc)
|
|||||||
|
|
||||||
static int _sdmmc_execute_cmd_inner(sdmmc_t *sdmmc, sdmmc_cmd_t *cmd, sdmmc_req_t *req, u32 *blkcnt_out)
|
static int _sdmmc_execute_cmd_inner(sdmmc_t *sdmmc, sdmmc_cmd_t *cmd, sdmmc_req_t *req, u32 *blkcnt_out)
|
||||||
{
|
{
|
||||||
int has_req_or_check_busy = req || cmd->check_busy;
|
bool has_req_or_check_busy = req || cmd->check_busy;
|
||||||
if (!_sdmmc_wait_cmd_data_inhibit(sdmmc, has_req_or_check_busy))
|
if (!_sdmmc_wait_cmd_data_inhibit(sdmmc, has_req_or_check_busy))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@@ -1158,13 +1135,13 @@ static int _sdmmc_execute_cmd_inner(sdmmc_t *sdmmc, sdmmc_cmd_t *cmd, sdmmc_req_
|
|||||||
EPRINTFARGS("SDMMC%d: Transfer error!", sdmmc->id + 1);
|
EPRINTFARGS("SDMMC%d: Transfer error!", sdmmc->id + 1);
|
||||||
#endif
|
#endif
|
||||||
DPRINTF("rsp(%d): %08X, %08X, %08X, %08X\n", result,
|
DPRINTF("rsp(%d): %08X, %08X, %08X, %08X\n", result,
|
||||||
sdmmc->regs->rspreg0, sdmmc->regs->rspreg1, sdmmc->regs->rspreg2, sdmmc->regs->rspreg3);
|
sdmmc->regs->rspreg[0], sdmmc->regs->rspreg[1], sdmmc->regs->rspreg[2], sdmmc->regs->rspreg[3]);
|
||||||
if (result)
|
if (result)
|
||||||
{
|
{
|
||||||
if (cmd->rsp_type)
|
if (cmd->rsp_type)
|
||||||
{
|
{
|
||||||
sdmmc->expected_rsp_type = cmd->rsp_type;
|
sdmmc->expected_rsp_type = cmd->rsp_type;
|
||||||
result = _sdmmc_cache_rsp(sdmmc, sdmmc->rsp, 0x10, cmd->rsp_type);
|
result = _sdmmc_cache_rsp(sdmmc, sdmmc->rsp, cmd->rsp_type);
|
||||||
#ifdef ERROR_EXTRA_PRINTING
|
#ifdef ERROR_EXTRA_PRINTING
|
||||||
if (!result)
|
if (!result)
|
||||||
EPRINTFARGS("SDMMC%d: Unknown response type!", sdmmc->id + 1);
|
EPRINTFARGS("SDMMC%d: Unknown response type!", sdmmc->id + 1);
|
||||||
@@ -1193,10 +1170,10 @@ static int _sdmmc_execute_cmd_inner(sdmmc_t *sdmmc, sdmmc_cmd_t *cmd, sdmmc_req_
|
|||||||
*blkcnt_out = blkcnt;
|
*blkcnt_out = blkcnt;
|
||||||
|
|
||||||
if (req->is_auto_stop_trn)
|
if (req->is_auto_stop_trn)
|
||||||
sdmmc->rsp3 = sdmmc->regs->rspreg3;
|
sdmmc->stop_trn_rsp = sdmmc->regs->rspreg[3];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cmd->check_busy || req)
|
if (has_req_or_check_busy)
|
||||||
{
|
{
|
||||||
result = _sdmmc_wait_card_busy(sdmmc);
|
result = _sdmmc_wait_card_busy(sdmmc);
|
||||||
#ifdef ERROR_EXTRA_PRINTING
|
#ifdef ERROR_EXTRA_PRINTING
|
||||||
@@ -1248,7 +1225,7 @@ static void _sdmmc_config_sdmmc1_pads(bool discharge)
|
|||||||
u32 level = GPIO_LOW;
|
u32 level = GPIO_LOW;
|
||||||
u32 output = GPIO_OUTPUT_DISABLE;
|
u32 output = GPIO_OUTPUT_DISABLE;
|
||||||
|
|
||||||
// Set values for dicharging.
|
// Set values for discharging.
|
||||||
if (discharge)
|
if (discharge)
|
||||||
{
|
{
|
||||||
function = GPIO_MODE_GPIO;
|
function = GPIO_MODE_GPIO;
|
||||||
@@ -1304,7 +1281,7 @@ static int _sdmmc_config_sdmmc1(bool t210b01)
|
|||||||
// Enable SD card power. Powers LDO2 also.
|
// Enable SD card power. Powers LDO2 also.
|
||||||
PINMUX_AUX(PINMUX_AUX_DMIC3_CLK) = PINMUX_PULL_DOWN | 2;
|
PINMUX_AUX(PINMUX_AUX_DMIC3_CLK) = PINMUX_PULL_DOWN | 2;
|
||||||
gpio_direction_output(GPIO_PORT_E, GPIO_PIN_4, GPIO_HIGH);
|
gpio_direction_output(GPIO_PORT_E, GPIO_PIN_4, GPIO_HIGH);
|
||||||
usleep(10000);
|
usleep(10000); // Minimum 3 to 10 ms.
|
||||||
|
|
||||||
// Inform IO pads that voltage is gonna be 3.3V.
|
// Inform IO pads that voltage is gonna be 3.3V.
|
||||||
PMC(APBDEV_PMC_PWR_DET_VAL) |= PMC_PWR_DET_33V_SDMMC1;
|
PMC(APBDEV_PMC_PWR_DET_VAL) |= PMC_PWR_DET_33V_SDMMC1;
|
||||||
@@ -1385,7 +1362,7 @@ int sdmmc_init(sdmmc_t *sdmmc, u32 id, u32 power, u32 bus_width, u32 type)
|
|||||||
if (sdmmc->t210b01)
|
if (sdmmc->t210b01)
|
||||||
vref_sel = 0;
|
vref_sel = 0;
|
||||||
else
|
else
|
||||||
sdmmc->manual_cal = 1;
|
sdmmc->periodic_calibration = 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SDMMC_2:
|
case SDMMC_2:
|
||||||
@@ -1419,6 +1396,8 @@ int sdmmc_init(sdmmc_t *sdmmc, u32 id, u32 power, u32 bus_width, u32 type)
|
|||||||
if (!_sdmmc_autocal_config_offset(sdmmc, power))
|
if (!_sdmmc_autocal_config_offset(sdmmc, power))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
_sdmmc_commit_changes(sdmmc);
|
||||||
|
|
||||||
// Calibrate pads.
|
// Calibrate pads.
|
||||||
_sdmmc_autocal_execute(sdmmc, power);
|
_sdmmc_autocal_execute(sdmmc, power);
|
||||||
|
|
||||||
@@ -1506,8 +1485,8 @@ int sdmmc_execute_cmd(sdmmc_t *sdmmc, sdmmc_cmd_t *cmd, sdmmc_req_t *req, u32 *b
|
|||||||
if (!sdmmc->card_clock_enabled)
|
if (!sdmmc->card_clock_enabled)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
// Recalibrate periodically for SDMMC1.
|
// Recalibrate periodically if needed.
|
||||||
if (sdmmc->manual_cal && sdmmc->powersave_enabled)
|
if (sdmmc->periodic_calibration && sdmmc->powersave_enabled)
|
||||||
_sdmmc_autocal_execute(sdmmc, sdmmc_get_io_power(sdmmc));
|
_sdmmc_autocal_execute(sdmmc, sdmmc_get_io_power(sdmmc));
|
||||||
|
|
||||||
int should_disable_sd_clock = 0;
|
int should_disable_sd_clock = 0;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2018 naehrwert
|
* Copyright (c) 2018 naehrwert
|
||||||
* Copyright (c) 2018-2023 CTCaer
|
* Copyright (c) 2018-2025 CTCaer
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
* under the terms and conditions of the GNU General Public License,
|
* under the terms and conditions of the GNU General Public License,
|
||||||
@@ -101,6 +101,7 @@
|
|||||||
#define SDHCI_CMD_TYPE_SUSPEND (1U << 6)
|
#define SDHCI_CMD_TYPE_SUSPEND (1U << 6)
|
||||||
#define SDHCI_CMD_TYPE_RESUME (2U << 6)
|
#define SDHCI_CMD_TYPE_RESUME (2U << 6)
|
||||||
#define SDHCI_CMD_TYPE_ABORT (3U << 6)
|
#define SDHCI_CMD_TYPE_ABORT (3U << 6)
|
||||||
|
#define SDHCI_CMD_SPI_CS_LOW BIT(7)
|
||||||
#define SDHCI_CMD_IDX(cmd) ((cmd) << 8)
|
#define SDHCI_CMD_IDX(cmd) ((cmd) << 8)
|
||||||
|
|
||||||
|
|
||||||
@@ -170,10 +171,10 @@
|
|||||||
#define SDHCI_INT_ERROR BIT(15)
|
#define SDHCI_INT_ERROR BIT(15)
|
||||||
|
|
||||||
/*! SDMMC error interrupt status and control. 0x32/0x36. */
|
/*! SDMMC error interrupt status and control. 0x32/0x36. */
|
||||||
#define SDHCI_ERR_INT_TIMEOUT BIT(0)
|
#define SDHCI_ERR_INT_CMD_TIMEOUT BIT(0)
|
||||||
#define SDHCI_ERR_INT_CRC BIT(1)
|
#define SDHCI_ERR_INT_CMD_CRC BIT(1)
|
||||||
#define SDHCI_ERR_INT_END_BIT BIT(2)
|
#define SDHCI_ERR_INT_CMD_END_BIT BIT(2)
|
||||||
#define SDHCI_ERR_INT_INDEX BIT(3)
|
#define SDHCI_ERR_INT_CMD_INDEX BIT(3)
|
||||||
#define SDHCI_ERR_INT_DATA_TIMEOUT BIT(4)
|
#define SDHCI_ERR_INT_DATA_TIMEOUT BIT(4)
|
||||||
#define SDHCI_ERR_INT_DATA_CRC BIT(5)
|
#define SDHCI_ERR_INT_DATA_CRC BIT(5)
|
||||||
#define SDHCI_ERR_INT_DATA_END_BIT BIT(6)
|
#define SDHCI_ERR_INT_DATA_END_BIT BIT(6)
|
||||||
@@ -190,8 +191,8 @@
|
|||||||
#define SDHCI_ERR_INT_ALL_EXCEPT_ADMA_BUSPWR \
|
#define SDHCI_ERR_INT_ALL_EXCEPT_ADMA_BUSPWR \
|
||||||
(SDHCI_ERR_INT_AUTO_CMD12 | SDHCI_ERR_INT_DATA_END_BIT | \
|
(SDHCI_ERR_INT_AUTO_CMD12 | SDHCI_ERR_INT_DATA_END_BIT | \
|
||||||
SDHCI_ERR_INT_DATA_CRC | SDHCI_ERR_INT_DATA_TIMEOUT | \
|
SDHCI_ERR_INT_DATA_CRC | SDHCI_ERR_INT_DATA_TIMEOUT | \
|
||||||
SDHCI_ERR_INT_INDEX | SDHCI_ERR_INT_END_BIT | \
|
SDHCI_ERR_INT_CMD_INDEX | SDHCI_ERR_INT_CMD_END_BIT | \
|
||||||
SDHCI_ERR_INT_CRC | SDHCI_ERR_INT_TIMEOUT)
|
SDHCI_ERR_INT_CMD_CRC | SDHCI_ERR_INT_CMD_TIMEOUT)
|
||||||
|
|
||||||
/*! Host Capability 1. 0x40. */
|
/*! Host Capability 1. 0x40. */
|
||||||
#define SDHCI_CAP_TM_CLK_FREQ_MASK 0x3F
|
#define SDHCI_CAP_TM_CLK_FREQ_MASK 0x3F
|
||||||
@@ -285,14 +286,15 @@ typedef struct _sdmmc_t
|
|||||||
u32 card_clock;
|
u32 card_clock;
|
||||||
u32 clock_stopped;
|
u32 clock_stopped;
|
||||||
int powersave_enabled;
|
int powersave_enabled;
|
||||||
int manual_cal;
|
int periodic_calibration;
|
||||||
int card_clock_enabled;
|
int card_clock_enabled;
|
||||||
int venclkctl_set;
|
int venclkctl_set;
|
||||||
u32 venclkctl_tap;
|
u32 venclkctl_tap;
|
||||||
u32 expected_rsp_type;
|
u32 expected_rsp_type;
|
||||||
u32 dma_addr_next;
|
u32 dma_addr_next;
|
||||||
u32 rsp[4];
|
u32 rsp[4];
|
||||||
u32 rsp3;
|
u32 stop_trn_rsp;
|
||||||
|
u32 error_sts;
|
||||||
int t210b01;
|
int t210b01;
|
||||||
} sdmmc_t;
|
} sdmmc_t;
|
||||||
|
|
||||||
@@ -323,7 +325,7 @@ void sdmmc_save_tap_value(sdmmc_t *sdmmc);
|
|||||||
void sdmmc_setup_drv_type(sdmmc_t *sdmmc, u32 type);
|
void sdmmc_setup_drv_type(sdmmc_t *sdmmc, u32 type);
|
||||||
int sdmmc_setup_clock(sdmmc_t *sdmmc, u32 type);
|
int sdmmc_setup_clock(sdmmc_t *sdmmc, u32 type);
|
||||||
void sdmmc_card_clock_powersave(sdmmc_t *sdmmc, int powersave_enable);
|
void sdmmc_card_clock_powersave(sdmmc_t *sdmmc, int powersave_enable);
|
||||||
int sdmmc_get_rsp(sdmmc_t *sdmmc, u32 *rsp, u32 size, u32 type);
|
int sdmmc_get_cached_rsp(sdmmc_t *sdmmc, u32 *rsp, u32 type);
|
||||||
int sdmmc_tuning_execute(sdmmc_t *sdmmc, u32 type, u32 cmd);
|
int sdmmc_tuning_execute(sdmmc_t *sdmmc, u32 type, u32 cmd);
|
||||||
int sdmmc_stop_transmission(sdmmc_t *sdmmc, u32 *rsp);
|
int sdmmc_stop_transmission(sdmmc_t *sdmmc, u32 *rsp);
|
||||||
bool sdmmc_get_sd_inserted();
|
bool sdmmc_get_sd_inserted();
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2018 naehrwert
|
* Copyright (c) 2018 naehrwert
|
||||||
* Copyright (c) 2018-2023 CTCaer
|
* Copyright (c) 2018-2025 CTCaer
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
* under the terms and conditions of the GNU General Public License,
|
* under the terms and conditions of the GNU General Public License,
|
||||||
@@ -39,10 +39,7 @@ typedef struct _t210_sdmmc_t
|
|||||||
/* 0x08 */ vu32 argument;
|
/* 0x08 */ vu32 argument;
|
||||||
/* 0x0C */ vu16 trnmod;
|
/* 0x0C */ vu16 trnmod;
|
||||||
/* 0x0E */ vu16 cmdreg;
|
/* 0x0E */ vu16 cmdreg;
|
||||||
/* 0x10 */ vu32 rspreg0;
|
/* 0x10 */ vu32 rspreg[4];
|
||||||
/* 0x14 */ vu32 rspreg1;
|
|
||||||
/* 0x18 */ vu32 rspreg2;
|
|
||||||
/* 0x1C */ vu32 rspreg3;
|
|
||||||
/* 0x20 */ vu32 bdata; // Buffer data port.
|
/* 0x20 */ vu32 bdata; // Buffer data port.
|
||||||
/* 0x24 */ vu32 prnsts;
|
/* 0x24 */ vu32 prnsts;
|
||||||
/* 0x28 */ vu8 hostctl;
|
/* 0x28 */ vu8 hostctl;
|
||||||
|
|||||||
@@ -99,7 +99,7 @@ typedef struct _usb_cfg_descr_t
|
|||||||
u8 bConfigurationValue; // Value of this configuration (1 based).
|
u8 bConfigurationValue; // Value of this configuration (1 based).
|
||||||
u8 iConfiguration; // Index of String Descriptor describing the configuration.
|
u8 iConfiguration; // Index of String Descriptor describing the configuration.
|
||||||
u8 bmAttributes; // Configuration characteristics.
|
u8 bmAttributes; // Configuration characteristics.
|
||||||
u8 bMaxPower; // Maximum power consumed by this configuration.
|
u8 bMaxPower; // Maximum power consumed by this configuration. In 2mA (usb2) or 8mA (usb3).
|
||||||
} __attribute__((packed)) usb_cfg_descr_t;
|
} __attribute__((packed)) usb_cfg_descr_t;
|
||||||
|
|
||||||
/* Interface descriptor structure */
|
/* Interface descriptor structure */
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
|
|
||||||
#include <storage/emmc.h>
|
#include <storage/emmc.h>
|
||||||
#include <storage/emummc_file_based.h>
|
#include <storage/emummc_file_based.h>
|
||||||
|
#include <storage/file_based_storage.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include <usb/usbd.h>
|
#include <usb/usbd.h>
|
||||||
@@ -500,6 +501,10 @@ static int _scsi_read(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
|
|||||||
if(ums->lun.storage){
|
if(ums->lun.storage){
|
||||||
if (!sdmmc_storage_read(ums->lun.storage, ums->lun.offset + lba_offset, amount, sdmmc_buf))
|
if (!sdmmc_storage_read(ums->lun.storage, ums->lun.offset + lba_offset, amount, sdmmc_buf))
|
||||||
amount = 0;
|
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{
|
}else{
|
||||||
if(!emummc_storage_file_based_read(ums->lun.offset + lba_offset, amount, sdmmc_buf)){
|
if(!emummc_storage_file_based_read(ums->lun.offset + lba_offset, amount, sdmmc_buf)){
|
||||||
amount = 0;
|
amount = 0;
|
||||||
@@ -662,6 +667,10 @@ static int _scsi_write(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
|
|||||||
if (!sdmmc_storage_write(ums->lun.storage, ums->lun.offset + lba_offset,
|
if (!sdmmc_storage_write(ums->lun.storage, ums->lun.offset + lba_offset,
|
||||||
amount >> UMS_DISK_LBA_SHIFT, (u8 *)bulk_ctxt->bulk_out_buf))
|
amount >> UMS_DISK_LBA_SHIFT, (u8 *)bulk_ctxt->bulk_out_buf))
|
||||||
amount = 0;
|
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{
|
}else{
|
||||||
if(!emummc_storage_file_based_write(ums->lun.offset + lba_offset, amount >> UMS_DISK_LBA_SHIFT, (u8*)bulk_ctxt->bulk_out_buf)){
|
if(!emummc_storage_file_based_write(ums->lun.offset + lba_offset, amount >> UMS_DISK_LBA_SHIFT, (u8*)bulk_ctxt->bulk_out_buf)){
|
||||||
amount = 0;
|
amount = 0;
|
||||||
@@ -739,6 +748,10 @@ static int _scsi_verify(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
|
|||||||
if(ums->lun.storage){
|
if(ums->lun.storage){
|
||||||
if (!sdmmc_storage_read(ums->lun.storage, ums->lun.offset + lba_offset, amount, bulk_ctxt->bulk_in_buf))
|
if (!sdmmc_storage_read(ums->lun.storage, ums->lun.offset + lba_offset, amount, bulk_ctxt->bulk_in_buf))
|
||||||
amount = 0;
|
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{
|
}else{
|
||||||
if(!emummc_storage_file_based_read(ums->lun.offset + lba_offset, amount, bulk_ctxt->bulk_in_buf)){
|
if(!emummc_storage_file_based_read(ums->lun.offset + lba_offset, amount, bulk_ctxt->bulk_in_buf)){
|
||||||
amount = 0;
|
amount = 0;
|
||||||
@@ -1934,6 +1947,10 @@ int usb_device_gadget_ums(usb_ctxt_t *usbs)
|
|||||||
}
|
}
|
||||||
ums.lun.storage = NULL;
|
ums.lun.storage = NULL;
|
||||||
ums.lun.sdmmc = 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{
|
} else{
|
||||||
if (!emmc_initialize(false))
|
if (!emmc_initialize(false))
|
||||||
{
|
{
|
||||||
@@ -1980,6 +1997,9 @@ int usb_device_gadget_ums(usb_ctxt_t *usbs)
|
|||||||
case MMC_EMUMMC_RAW_EMMC:
|
case MMC_EMUMMC_RAW_EMMC:
|
||||||
ums.set_text(ums.label, "#FFDD00 No sector count set for emuMMC!#");
|
ums.set_text(ums.label, "#FFDD00 No sector count set for emuMMC!#");
|
||||||
break;
|
break;
|
||||||
|
case MMC_FILE_BASED:
|
||||||
|
ums.set_text(ums.label, "#FFDD00 No sector count set for emuSD!#");
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2018-2024 CTCaer
|
* Copyright (c) 2018-2025 CTCaer
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
* under the terms and conditions of the GNU General Public License,
|
* under the terms and conditions of the GNU General Public License,
|
||||||
@@ -82,12 +82,12 @@ dirlist_t *dirlist(const char *directory, const char *pattern, bool includeHidde
|
|||||||
// Terminate name list.
|
// Terminate name list.
|
||||||
dir_entries->name[k] = NULL;
|
dir_entries->name[k] = NULL;
|
||||||
|
|
||||||
// Reorder ini files by ASCII ordering.
|
// Reorder ini files Alphabetically.
|
||||||
for (u32 i = 0; i < k - 1 ; i++)
|
for (u32 i = 0; i < k - 1 ; i++)
|
||||||
{
|
{
|
||||||
for (u32 j = i + 1; j < k; j++)
|
for (u32 j = i + 1; j < k; j++)
|
||||||
{
|
{
|
||||||
if (strcmp(dir_entries->name[i], dir_entries->name[j]) > 0)
|
if (strcasecmp(dir_entries->name[i], dir_entries->name[j]) > 0)
|
||||||
{
|
{
|
||||||
char *tmp = dir_entries->name[i];
|
char *tmp = dir_entries->name[i];
|
||||||
dir_entries->name[i] = dir_entries->name[j];
|
dir_entries->name[i] = dir_entries->name[j];
|
||||||
|
|||||||
@@ -172,14 +172,14 @@ parse_padding_dec:
|
|||||||
_s_putc(c);
|
_s_putc(c);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 's':
|
|
||||||
_s_puts(va_arg(ap, char *), fill, fcnt);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'd':
|
case 'd':
|
||||||
_s_putn(va_arg(ap, u32), 10, fill, fcnt);
|
_s_putn(va_arg(ap, u32), 10, fill, fcnt);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 's':
|
||||||
|
_s_puts(va_arg(ap, char *), fill, fcnt);
|
||||||
|
break;
|
||||||
|
|
||||||
case 'p':
|
case 'p':
|
||||||
case 'P':
|
case 'P':
|
||||||
case 'x':
|
case 'x':
|
||||||
@@ -261,14 +261,14 @@ parse_padding_dec:
|
|||||||
_s_putc(c);
|
_s_putc(c);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 's':
|
|
||||||
_s_puts(va_arg(ap, char *), fill, fcnt);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'd':
|
case 'd':
|
||||||
_s_putn(va_arg(ap, u32), 10, fill, fcnt);
|
_s_putn(va_arg(ap, u32), 10, fill, fcnt);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 's':
|
||||||
|
_s_puts(va_arg(ap, char *), fill, fcnt);
|
||||||
|
break;
|
||||||
|
|
||||||
case 'p':
|
case 'p':
|
||||||
case 'P':
|
case 'P':
|
||||||
case 'x':
|
case 'x':
|
||||||
|
|||||||
@@ -1,19 +1,19 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2018 naehrwert
|
* Copyright (c) 2018 naehrwert
|
||||||
* Copyright (c) 2018-2024 CTCaer
|
* Copyright (c) 2018-2025 CTCaer
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
* under the terms and conditions of the GNU General Public License,
|
* under the terms and conditions of the GNU General Public License,
|
||||||
* version 2, as published by the Free Software Foundation.
|
* version 2, as published by the Free Software Foundation.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
* more details.
|
* more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <storage/boot_storage.h>
|
#include <storage/boot_storage.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@@ -137,7 +137,7 @@ long strtol(const char *nptr, char **endptr, register int base)
|
|||||||
} else if (c == '+')
|
} else if (c == '+')
|
||||||
c = *s++;
|
c = *s++;
|
||||||
if ((base == 0 || base == 16) &&
|
if ((base == 0 || base == 16) &&
|
||||||
c == '0' && (*s == 'x' || *s == 'X')) {
|
c == '0' && (*s == 'x' || *s == 'X')) {
|
||||||
c = s[1];
|
c = s[1];
|
||||||
s += 2;
|
s += 2;
|
||||||
base = 16;
|
base = 16;
|
||||||
@@ -240,6 +240,21 @@ u32 crc32_calc(u32 crc, const u8 *buf, u32 len)
|
|||||||
return ~crc;
|
return ~crc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int qsort_compare_int(const void *a, const void *b)
|
||||||
|
{
|
||||||
|
return (*(int *)a - *(int *)b);
|
||||||
|
}
|
||||||
|
|
||||||
|
int qsort_compare_char(const void *a, const void *b)
|
||||||
|
{
|
||||||
|
return strcmp(*(const char **)a, *(const char **)b);
|
||||||
|
}
|
||||||
|
|
||||||
|
int qsort_compare_char_case(const void *a, const void *b)
|
||||||
|
{
|
||||||
|
return strcasecmp(*(const char **)a, *(const char **)b);
|
||||||
|
}
|
||||||
|
|
||||||
void panic(u32 val)
|
void panic(u32 val)
|
||||||
{
|
{
|
||||||
// Set panic code.
|
// Set panic code.
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2018 naehrwert
|
* Copyright (c) 2018 naehrwert
|
||||||
* Copyright (c) 2018-2024 CTCaer
|
* Copyright (c) 2018-2025 CTCaer
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
* under the terms and conditions of the GNU General Public License,
|
* under the terms and conditions of the GNU General Public License,
|
||||||
@@ -89,6 +89,10 @@ int atoi(const char *nptr);
|
|||||||
void reg_write_array(u32 *base, const reg_cfg_t *cfg, u32 num_cfg);
|
void reg_write_array(u32 *base, const reg_cfg_t *cfg, u32 num_cfg);
|
||||||
u32 crc32_calc(u32 crc, const u8 *buf, u32 len);
|
u32 crc32_calc(u32 crc, const u8 *buf, u32 len);
|
||||||
|
|
||||||
|
int qsort_compare_int(const void *a, const void *b);
|
||||||
|
int qsort_compare_char(const void *a, const void *b);
|
||||||
|
int qsort_compare_char_case(const void *a, const void *b);
|
||||||
|
|
||||||
void panic(u32 val);
|
void panic(u32 val);
|
||||||
void power_set_state(power_state_t state);
|
void power_set_state(power_state_t state);
|
||||||
void power_set_state_ex(void *param);
|
void power_set_state_ex(void *param);
|
||||||
|
|||||||
@@ -1,225 +0,0 @@
|
|||||||
/*
|
|
||||||
* Atmosphère Fusée Secondary Storage (Package3) parser.
|
|
||||||
*
|
|
||||||
* 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,
|
|
||||||
* version 2, as published by the Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
|
||||||
* more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <storage/boot_storage.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include <bdk.h>
|
|
||||||
|
|
||||||
#include "fss.h"
|
|
||||||
#include "hos.h"
|
|
||||||
#include "../config.h"
|
|
||||||
#include <libs/fatfs/ff.h>
|
|
||||||
#include "../storage/emummc.h"
|
|
||||||
|
|
||||||
//#define DPRINTF(...) gfx_printf(__VA_ARGS__)
|
|
||||||
#define DPRINTF(...)
|
|
||||||
|
|
||||||
extern hekate_config h_cfg;
|
|
||||||
|
|
||||||
extern bool is_ipl_updated(void *buf, const char *path, bool force);
|
|
||||||
|
|
||||||
// FSS0 Magic and Meta header offset.
|
|
||||||
#define FSS0_MAGIC 0x30535346
|
|
||||||
#define FSS0_META_OFFSET 0x4
|
|
||||||
#define FSS0_VERSION_0_17_0 0x110000
|
|
||||||
|
|
||||||
// FSS0 Content Types.
|
|
||||||
#define CNT_TYPE_FSP 0
|
|
||||||
#define CNT_TYPE_EXO 1 // Exosphere (Secure Monitor).
|
|
||||||
#define CNT_TYPE_WBT 2 // Warmboot (SC7Exit fw).
|
|
||||||
#define CNT_TYPE_RBT 3 // Rebootstub (Warmboot based reboot fw).
|
|
||||||
#define CNT_TYPE_SP1 4 // Sept Primary (TSEC and Sept Secondary loader).
|
|
||||||
#define CNT_TYPE_SP2 5 // Sept Secondary (Acts as pkg11 and derives keys).
|
|
||||||
#define CNT_TYPE_KIP 6 // KIP1 (Used for replacement or addition).
|
|
||||||
#define CNT_TYPE_BMP 7
|
|
||||||
#define CNT_TYPE_EMC 8
|
|
||||||
#define CNT_TYPE_KLD 9 // Kernel Loader.
|
|
||||||
#define CNT_TYPE_KRN 10 // Kernel.
|
|
||||||
#define CNT_TYPE_EXF 11 // Exosphere Mariko fatal payload.
|
|
||||||
#define CNT_TYPE_TKG 12 // Tsec Keygen.
|
|
||||||
|
|
||||||
// FSS0 Content Flags.
|
|
||||||
#define CNT_FLAG0_EXPERIMENTAL BIT(0)
|
|
||||||
|
|
||||||
// FSS0 Meta Header.
|
|
||||||
typedef struct _fss_meta_t
|
|
||||||
{
|
|
||||||
u32 magic;
|
|
||||||
u32 size;
|
|
||||||
u32 crt0_off;
|
|
||||||
u32 cnt_off;
|
|
||||||
u32 cnt_count;
|
|
||||||
u32 hos_ver;
|
|
||||||
u32 version;
|
|
||||||
u32 git_rev;
|
|
||||||
} fss_meta_t;
|
|
||||||
|
|
||||||
// FSS0 Content Header.
|
|
||||||
typedef struct _fss_content_t
|
|
||||||
{
|
|
||||||
u32 offset;
|
|
||||||
u32 size;
|
|
||||||
u8 type;
|
|
||||||
u8 flags0;
|
|
||||||
u8 flags1;
|
|
||||||
u8 flags2;
|
|
||||||
u32 rsvd1;
|
|
||||||
char name[0x10];
|
|
||||||
} fss_content_t;
|
|
||||||
|
|
||||||
static void _fss_update_r2p()
|
|
||||||
{
|
|
||||||
u8 *r2p_payload = boot_storage_file_read("atmosphere/reboot_payload.bin", NULL);
|
|
||||||
|
|
||||||
is_ipl_updated(r2p_payload, "atmosphere/reboot_payload.bin", h_cfg.updater2p ? true : false);
|
|
||||||
|
|
||||||
free(r2p_payload);
|
|
||||||
}
|
|
||||||
|
|
||||||
int parse_fss(launch_ctxt_t *ctxt, const char *path)
|
|
||||||
{
|
|
||||||
FIL fp;
|
|
||||||
|
|
||||||
bool stock = false;
|
|
||||||
bool experimental = false;
|
|
||||||
|
|
||||||
// Skip if stock and Exosphere and warmboot are not needed.
|
|
||||||
bool pkg1_old = ctxt->pkg1_id->kb <= HOS_KB_VERSION_620; // Should check if t210b01?
|
|
||||||
bool emummc_disabled = !emu_cfg.enabled || h_cfg.emummc_force_disable;
|
|
||||||
|
|
||||||
LIST_FOREACH_ENTRY(ini_kv_t, kv, &ctxt->cfg->kvs, link)
|
|
||||||
{
|
|
||||||
if (!strcmp("stock", kv->key))
|
|
||||||
if (kv->val[0] == '1')
|
|
||||||
stock = true;
|
|
||||||
|
|
||||||
if (!strcmp("fss0experimental", kv->key))
|
|
||||||
if (kv->val[0] == '1')
|
|
||||||
experimental = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef HOS_MARIKO_STOCK_SECMON
|
|
||||||
if (stock && emummc_disabled && (pkg1_old || h_cfg.t210b01))
|
|
||||||
return 1;
|
|
||||||
#else
|
|
||||||
if (stock && emummc_disabled && pkg1_old)
|
|
||||||
return 1;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Try to open FSS0.
|
|
||||||
if (f_open(&fp, path, FA_READ) != FR_OK)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
void *fss = malloc(f_size(&fp));
|
|
||||||
|
|
||||||
// Read first 1024 bytes of the FSS0 file.
|
|
||||||
f_read(&fp, fss, 1024, NULL);
|
|
||||||
|
|
||||||
// Get FSS0 Meta header offset.
|
|
||||||
u32 fss_meta_addr = *(u32 *)(fss + FSS0_META_OFFSET);
|
|
||||||
fss_meta_t *fss_meta = (fss_meta_t *)(fss + fss_meta_addr);
|
|
||||||
|
|
||||||
// Check if valid FSS0 and parse it.
|
|
||||||
if (fss_meta->magic == FSS0_MAGIC)
|
|
||||||
{
|
|
||||||
gfx_printf("Atmosphere %d.%d.%d-%08x via FSS0/PKG3\n"
|
|
||||||
"Max HOS: %d.%d.%d\n"
|
|
||||||
"Unpacking.. ",
|
|
||||||
fss_meta->version >> 24, (fss_meta->version >> 16) & 0xFF, (fss_meta->version >> 8) & 0xFF, fss_meta->git_rev,
|
|
||||||
fss_meta->hos_ver >> 24, (fss_meta->hos_ver >> 16) & 0xFF, (fss_meta->hos_ver >> 8) & 0xFF);
|
|
||||||
|
|
||||||
ctxt->atmosphere = true;
|
|
||||||
ctxt->fss0_hosver = fss_meta->hos_ver;
|
|
||||||
|
|
||||||
// Parse FSS0 contents.
|
|
||||||
fss_content_t *curr_fss_cnt = (fss_content_t *)(fss + fss_meta->cnt_off);
|
|
||||||
void *content;
|
|
||||||
for (u32 i = 0; i < fss_meta->cnt_count; i++)
|
|
||||||
{
|
|
||||||
content = (void *)(fss + curr_fss_cnt[i].offset);
|
|
||||||
|
|
||||||
// Check if offset is inside limits.
|
|
||||||
if ((curr_fss_cnt[i].offset + curr_fss_cnt[i].size) > fss_meta->size)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// If content is experimental and experimental config is not enabled, skip it.
|
|
||||||
if ((curr_fss_cnt[i].flags0 & CNT_FLAG0_EXPERIMENTAL) && !experimental)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// Prepare content.
|
|
||||||
switch (curr_fss_cnt[i].type)
|
|
||||||
{
|
|
||||||
case CNT_TYPE_KIP:
|
|
||||||
if (stock)
|
|
||||||
continue;
|
|
||||||
merge_kip_t *mkip1 = (merge_kip_t *)malloc(sizeof(merge_kip_t));
|
|
||||||
mkip1->kip1 = content;
|
|
||||||
list_append(&ctxt->kip1_list, &mkip1->link);
|
|
||||||
DPRINTF("Loaded %s.kip1 from FSS0 (size %08X)\n", curr_fss_cnt[i].name, curr_fss_cnt[i].size);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case CNT_TYPE_KRN:
|
|
||||||
if (stock)
|
|
||||||
continue;
|
|
||||||
ctxt->kernel_size = curr_fss_cnt[i].size;
|
|
||||||
ctxt->kernel = content;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case CNT_TYPE_EXO:
|
|
||||||
ctxt->secmon_size = curr_fss_cnt[i].size;
|
|
||||||
ctxt->secmon = content;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case CNT_TYPE_EXF:
|
|
||||||
ctxt->exofatal_size = curr_fss_cnt[i].size;
|
|
||||||
ctxt->exofatal = content;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case CNT_TYPE_WBT:
|
|
||||||
if (h_cfg.t210b01)
|
|
||||||
continue;
|
|
||||||
ctxt->warmboot_size = curr_fss_cnt[i].size;
|
|
||||||
ctxt->warmboot = content;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Load content to launch context.
|
|
||||||
f_lseek(&fp, curr_fss_cnt[i].offset);
|
|
||||||
f_read(&fp, content, curr_fss_cnt[i].size, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
gfx_printf("Done!\n");
|
|
||||||
f_close(&fp);
|
|
||||||
|
|
||||||
ctxt->fss0 = fss;
|
|
||||||
|
|
||||||
// Update r2p if needed.
|
|
||||||
_fss_update_r2p();
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
f_close(&fp);
|
|
||||||
free(fss);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
* Copyright (c) 2018 naehrwert
|
* Copyright (c) 2018 naehrwert
|
||||||
* Copyright (c) 2018 st4rk
|
* Copyright (c) 2018 st4rk
|
||||||
* Copyright (c) 2018 Ced2911
|
* Copyright (c) 2018 Ced2911
|
||||||
* Copyright (c) 2018-2024 CTCaer
|
* Copyright (c) 2018-2025 CTCaer
|
||||||
* Copyright (c) 2018 balika011
|
* Copyright (c) 2018 balika011
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
@@ -28,6 +28,7 @@
|
|||||||
#include "../frontend/fe_tools.h"
|
#include "../frontend/fe_tools.h"
|
||||||
#include "../config.h"
|
#include "../config.h"
|
||||||
#include "../storage/emummc.h"
|
#include "../storage/emummc.h"
|
||||||
|
#include "../storage/emusd.h"
|
||||||
#include <storage/boot_storage.h>
|
#include <storage/boot_storage.h>
|
||||||
|
|
||||||
extern hekate_config h_cfg;
|
extern hekate_config h_cfg;
|
||||||
@@ -125,6 +126,7 @@ static const u8 master_kekseed_t210_tsec_v4[HOS_KB_VERSION_MAX - HOS_KB_VERSION_
|
|||||||
{ 0x71, 0xB9, 0xA6, 0xC0, 0xFF, 0x97, 0x6B, 0x0C, 0xB4, 0x40, 0xB9, 0xD5, 0x81, 0x5D, 0x81, 0x90 }, // 17.0.0.
|
{ 0x71, 0xB9, 0xA6, 0xC0, 0xFF, 0x97, 0x6B, 0x0C, 0xB4, 0x40, 0xB9, 0xD5, 0x81, 0x5D, 0x81, 0x90 }, // 17.0.0.
|
||||||
{ 0x00, 0x04, 0x5D, 0xF0, 0x4D, 0xCD, 0x14, 0xA3, 0x1C, 0xBF, 0xDE, 0x48, 0x55, 0xBA, 0x35, 0xC1 }, // 18.0.0.
|
{ 0x00, 0x04, 0x5D, 0xF0, 0x4D, 0xCD, 0x14, 0xA3, 0x1C, 0xBF, 0xDE, 0x48, 0x55, 0xBA, 0x35, 0xC1 }, // 18.0.0.
|
||||||
{ 0xD7, 0x63, 0x74, 0x46, 0x4E, 0xBA, 0x78, 0x0A, 0x7C, 0x9D, 0xB3, 0xE8, 0x7A, 0x3D, 0x71, 0xE3 }, // 19.0.0.
|
{ 0xD7, 0x63, 0x74, 0x46, 0x4E, 0xBA, 0x78, 0x0A, 0x7C, 0x9D, 0xB3, 0xE8, 0x7A, 0x3D, 0x71, 0xE3 }, // 19.0.0.
|
||||||
|
{ 0xA1, 0x7D, 0x34, 0xDB, 0x2D, 0x9D, 0xDA, 0xE5, 0xF8, 0x15, 0x63, 0x4C, 0x8F, 0xE7, 0x6C, 0xD8 }, // 20.0.0.
|
||||||
};
|
};
|
||||||
|
|
||||||
//!TODO: Update on mkey changes.
|
//!TODO: Update on mkey changes.
|
||||||
@@ -143,6 +145,7 @@ static const u8 master_kekseed_t210b01[HOS_KB_VERSION_MAX - HOS_KB_VERSION_600 +
|
|||||||
{ 0x8D, 0xEE, 0x9E, 0x11, 0x36, 0x3A, 0x9B, 0x0A, 0x6A, 0xC7, 0xBB, 0xE9, 0xD1, 0x03, 0xF7, 0x80 }, // 17.0.0.
|
{ 0x8D, 0xEE, 0x9E, 0x11, 0x36, 0x3A, 0x9B, 0x0A, 0x6A, 0xC7, 0xBB, 0xE9, 0xD1, 0x03, 0xF7, 0x80 }, // 17.0.0.
|
||||||
{ 0x4F, 0x41, 0x3C, 0x3B, 0xFB, 0x6A, 0x01, 0x2A, 0x68, 0x9F, 0x83, 0xE9, 0x53, 0xBD, 0x16, 0xD2 }, // 18.0.0.
|
{ 0x4F, 0x41, 0x3C, 0x3B, 0xFB, 0x6A, 0x01, 0x2A, 0x68, 0x9F, 0x83, 0xE9, 0x53, 0xBD, 0x16, 0xD2 }, // 18.0.0.
|
||||||
{ 0x31, 0xBE, 0x25, 0xFB, 0xDB, 0xB4, 0xEE, 0x49, 0x5C, 0x77, 0x05, 0xC2, 0x36, 0x9F, 0x34, 0x80 }, // 19.0.0.
|
{ 0x31, 0xBE, 0x25, 0xFB, 0xDB, 0xB4, 0xEE, 0x49, 0x5C, 0x77, 0x05, 0xC2, 0x36, 0x9F, 0x34, 0x80 }, // 19.0.0.
|
||||||
|
{ 0x1A, 0x31, 0x62, 0x87, 0xA8, 0x09, 0xCA, 0xF8, 0x69, 0x15, 0x45, 0xC2, 0x6B, 0xAA, 0x5A, 0x8A }, // 20.0.0.
|
||||||
};
|
};
|
||||||
|
|
||||||
static const u8 console_keyseed[SE_KEY_128_SIZE] =
|
static const u8 console_keyseed[SE_KEY_128_SIZE] =
|
||||||
@@ -195,7 +198,7 @@ static void _se_lock(bool lock_se)
|
|||||||
gfx_hexdump(SE_BASE, (void *)SE_BASE, 0x400);*/
|
gfx_hexdump(SE_BASE, (void *)SE_BASE, 0x400);*/
|
||||||
}
|
}
|
||||||
|
|
||||||
bool hos_eks_rw_try(u8 *buf, bool write)
|
static bool _hos_eks_rw_try(u8 *buf, bool write)
|
||||||
{
|
{
|
||||||
for (u32 i = 0; i < 3; i++)
|
for (u32 i = 0; i < 3; i++)
|
||||||
{
|
{
|
||||||
@@ -225,7 +228,7 @@ static void _hos_eks_get()
|
|||||||
{
|
{
|
||||||
// Read EKS blob.
|
// Read EKS blob.
|
||||||
u8 *mbr = zalloc(SD_BLOCKSIZE);
|
u8 *mbr = zalloc(SD_BLOCKSIZE);
|
||||||
if (!hos_eks_rw_try(mbr, false))
|
if (!_hos_eks_rw_try(mbr, false))
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
// Decrypt EKS blob.
|
// Decrypt EKS blob.
|
||||||
@@ -263,7 +266,7 @@ static void _hos_eks_save()
|
|||||||
{
|
{
|
||||||
// Read EKS blob.
|
// Read EKS blob.
|
||||||
u8 *mbr = zalloc(SD_BLOCKSIZE);
|
u8 *mbr = zalloc(SD_BLOCKSIZE);
|
||||||
if (!hos_eks_rw_try(mbr, false))
|
if (!_hos_eks_rw_try(mbr, false))
|
||||||
{
|
{
|
||||||
if (new_eks)
|
if (new_eks)
|
||||||
{
|
{
|
||||||
@@ -295,7 +298,7 @@ static void _hos_eks_save()
|
|||||||
|
|
||||||
// Write EKS blob to SD.
|
// Write EKS blob to SD.
|
||||||
memcpy(mbr + 0x80, eks, sizeof(hos_eks_mbr_t));
|
memcpy(mbr + 0x80, eks, sizeof(hos_eks_mbr_t));
|
||||||
hos_eks_rw_try(mbr, true);
|
_hos_eks_rw_try(mbr, true);
|
||||||
|
|
||||||
free(eks);
|
free(eks);
|
||||||
free(keys);
|
free(keys);
|
||||||
@@ -304,7 +307,7 @@ out:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void hos_eks_clear(u32 kb)
|
static void _hos_eks_clear(u32 kb)
|
||||||
{
|
{
|
||||||
// Check if Erista based unit.
|
// Check if Erista based unit.
|
||||||
if (h_cfg.t210b01)
|
if (h_cfg.t210b01)
|
||||||
@@ -317,7 +320,7 @@ void hos_eks_clear(u32 kb)
|
|||||||
{
|
{
|
||||||
// Read EKS blob.
|
// Read EKS blob.
|
||||||
u8 *mbr = zalloc(SD_BLOCKSIZE);
|
u8 *mbr = zalloc(SD_BLOCKSIZE);
|
||||||
if (!hos_eks_rw_try(mbr, false))
|
if (!_hos_eks_rw_try(mbr, false))
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
// Disable current Master key version.
|
// Disable current Master key version.
|
||||||
@@ -330,7 +333,7 @@ void hos_eks_clear(u32 kb)
|
|||||||
|
|
||||||
// Write EKS blob to SD.
|
// Write EKS blob to SD.
|
||||||
memcpy(mbr + 0x80, eks, sizeof(hos_eks_mbr_t));
|
memcpy(mbr + 0x80, eks, sizeof(hos_eks_mbr_t));
|
||||||
hos_eks_rw_try(mbr, true);
|
_hos_eks_rw_try(mbr, true);
|
||||||
|
|
||||||
free(eks);
|
free(eks);
|
||||||
out:
|
out:
|
||||||
@@ -339,24 +342,9 @@ out:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int hos_keygen_t210b01(u32 kb)
|
static int _hos_keygen(void *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt, bool stock, bool is_exo)
|
||||||
{
|
{
|
||||||
// Use SBK as Device key 4x unsealer and KEK for mkey in T210B01 units.
|
static bool sbk_is_set = true;
|
||||||
se_aes_unwrap_key(10, 14, console_keyseed_4xx);
|
|
||||||
|
|
||||||
// Derive master key.
|
|
||||||
se_aes_unwrap_key(7, 12, master_kekseed_t210b01[kb - HOS_KB_VERSION_600]);
|
|
||||||
se_aes_unwrap_key(7, 7, master_keyseed_retail);
|
|
||||||
|
|
||||||
// Derive latest pkg2 key.
|
|
||||||
se_aes_unwrap_key(8, 7, package2_keyseed);
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int hos_keygen(void *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt, bool stock, bool is_exo)
|
|
||||||
{
|
|
||||||
static bool sbk_wiped = false;
|
|
||||||
|
|
||||||
u32 retries = 0;
|
u32 retries = 0;
|
||||||
bool use_tsec = false;
|
bool use_tsec = false;
|
||||||
@@ -366,16 +354,29 @@ int hos_keygen(void *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt, bool stock, bool i
|
|||||||
if (kb > HOS_KB_VERSION_MAX)
|
if (kb > HOS_KB_VERSION_MAX)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
// Do Mariko keygen.
|
||||||
if (h_cfg.t210b01)
|
if (h_cfg.t210b01)
|
||||||
return hos_keygen_t210b01(kb);
|
{
|
||||||
|
// Use SBK as Device key 4x unsealer and KEK for mkey in T210B01 units.
|
||||||
|
se_aes_unwrap_key(10, 14, console_keyseed_4xx);
|
||||||
|
|
||||||
|
// Derive master key.
|
||||||
|
se_aes_unwrap_key(7, 12, master_kekseed_t210b01[kb - HOS_KB_VERSION_600]);
|
||||||
|
se_aes_unwrap_key(7, 7, master_keyseed_retail);
|
||||||
|
|
||||||
|
// Derive latest pkg2 key.
|
||||||
|
se_aes_unwrap_key(8, 7, package2_keyseed);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
// Do Erista keygen.
|
// Do Erista keygen.
|
||||||
|
|
||||||
// SBK is wiped. Try to restore it from fuses.
|
// Check if SBK is wiped and try to restore it from fuses.
|
||||||
if (sbk_wiped)
|
if (!sbk_is_set)
|
||||||
{
|
{
|
||||||
if (fuse_set_sbk())
|
if (fuse_set_sbk())
|
||||||
sbk_wiped = false;
|
sbk_is_set = true;
|
||||||
else
|
else
|
||||||
return 1; // Continue with current SE keys.
|
return 1; // Continue with current SE keys.
|
||||||
}
|
}
|
||||||
@@ -413,7 +414,7 @@ int hos_keygen(void *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt, bool stock, bool i
|
|||||||
tsec_ctxt->fw = boot_storage_file_read("bootloader/sys/thk.bin", NULL);
|
tsec_ctxt->fw = boot_storage_file_read("bootloader/sys/thk.bin", NULL);
|
||||||
if (!tsec_ctxt->fw)
|
if (!tsec_ctxt->fw)
|
||||||
{
|
{
|
||||||
_hos_crit_error("\nFailed to load thk.bin");
|
_hos_crit_error("Failed to load thk.bin");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -437,7 +438,7 @@ int hos_keygen(void *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt, bool stock, bool i
|
|||||||
// We rely on racing conditions, make sure we cover even the unluckiest cases.
|
// We rely on racing conditions, make sure we cover even the unluckiest cases.
|
||||||
if (retries > 15)
|
if (retries > 15)
|
||||||
{
|
{
|
||||||
_hos_crit_error("\nFailed to get TSEC keys. Please try again.");
|
_hos_crit_error("Failed to get TSEC keys.");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -571,7 +572,7 @@ int hos_keygen(void *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt, bool stock, bool i
|
|||||||
se_aes_unwrap_key(15, 15, console_keyseed);
|
se_aes_unwrap_key(15, 15, console_keyseed);
|
||||||
se_aes_unwrap_key(14, 12, master_keyseed_4xx);
|
se_aes_unwrap_key(14, 12, master_keyseed_4xx);
|
||||||
se_aes_unwrap_key(12, 12, master_keyseed_retail);
|
se_aes_unwrap_key(12, 12, master_keyseed_retail);
|
||||||
sbk_wiped = true;
|
sbk_is_set = false;
|
||||||
break;
|
break;
|
||||||
case HOS_KB_VERSION_500:
|
case HOS_KB_VERSION_500:
|
||||||
case HOS_KB_VERSION_600:
|
case HOS_KB_VERSION_600:
|
||||||
@@ -579,7 +580,7 @@ int hos_keygen(void *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt, bool stock, bool i
|
|||||||
se_aes_unwrap_key(15, 15, console_keyseed);
|
se_aes_unwrap_key(15, 15, console_keyseed);
|
||||||
se_aes_unwrap_key(14, 12, master_keyseed_4xx);
|
se_aes_unwrap_key(14, 12, master_keyseed_4xx);
|
||||||
se_aes_unwrap_key(12, 12, master_keyseed_retail);
|
se_aes_unwrap_key(12, 12, master_keyseed_retail);
|
||||||
sbk_wiped = true;
|
sbk_is_set = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -701,7 +702,7 @@ out:
|
|||||||
static void _free_launch_components(launch_ctxt_t *ctxt)
|
static void _free_launch_components(launch_ctxt_t *ctxt)
|
||||||
{
|
{
|
||||||
// Free the malloc'ed guaranteed addresses.
|
// Free the malloc'ed guaranteed addresses.
|
||||||
free(ctxt->fss0);
|
free(ctxt->pkg3);
|
||||||
free(ctxt->keyblob);
|
free(ctxt->keyblob);
|
||||||
free(ctxt->pkg1);
|
free(ctxt->pkg1);
|
||||||
free(ctxt->pkg2);
|
free(ctxt->pkg2);
|
||||||
@@ -751,7 +752,7 @@ static bool _get_fs_exfat_compatible(link_t *info, u32 *hos_revision)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int hos_launch(ini_sec_t *cfg)
|
void hos_launch(ini_sec_t *cfg)
|
||||||
{
|
{
|
||||||
u8 kb;
|
u8 kb;
|
||||||
u32 secmon_base;
|
u32 secmon_base;
|
||||||
@@ -759,7 +760,6 @@ int hos_launch(ini_sec_t *cfg)
|
|||||||
bool is_exo = false;
|
bool is_exo = false;
|
||||||
launch_ctxt_t ctxt = {0};
|
launch_ctxt_t ctxt = {0};
|
||||||
tsec_ctxt_t tsec_ctxt = {0};
|
tsec_ctxt_t tsec_ctxt = {0};
|
||||||
volatile secmon_mailbox_t *secmon_mailbox;
|
|
||||||
|
|
||||||
minerva_change_freq(FREQ_1600);
|
minerva_change_freq(FREQ_1600);
|
||||||
sdram_src_pllc(true);
|
sdram_src_pllc(true);
|
||||||
@@ -777,24 +777,26 @@ int hos_launch(ini_sec_t *cfg)
|
|||||||
int res = emummc_storage_init_mmc();
|
int res = emummc_storage_init_mmc();
|
||||||
if (res)
|
if (res)
|
||||||
{
|
{
|
||||||
if (res == 2)
|
_hos_crit_error(res == 2 ? "Failed to init eMMC." : "Failed to init emuMMC.");
|
||||||
_hos_crit_error("Failed to init eMMC.");
|
|
||||||
else
|
goto error;
|
||||||
_hos_crit_error("Failed to init emuMMC.");
|
}
|
||||||
|
|
||||||
|
if (emusd_storage_init_mmc() || !emusd_mount()) {
|
||||||
|
_hos_crit_error("error: Failed to init emuSD.");
|
||||||
|
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if SD Card is GPT.
|
// Check if SD Card is GPT.
|
||||||
// TODO: not relevant with emuSD
|
if (emusd_is_gpt())
|
||||||
if (sd_is_gpt())
|
|
||||||
{
|
{
|
||||||
_hos_crit_error("SD has GPT only!");
|
_hos_crit_error("SD has GPT only! Run Fix Hybrid MBR!");
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try to parse config if present.
|
// Try to parse config if present.
|
||||||
if (ctxt.cfg && !parse_boot_config(&ctxt))
|
if (!parse_boot_config(&ctxt))
|
||||||
{
|
{
|
||||||
_hos_crit_error("Wrong ini cfg or missing/corrupt files!");
|
_hos_crit_error("Wrong ini cfg or missing/corrupt files!");
|
||||||
goto error;
|
goto error;
|
||||||
@@ -807,6 +809,8 @@ int hos_launch(ini_sec_t *cfg)
|
|||||||
if (ctxt.stock && (h_cfg.t210b01 || !tools_autorcm_enabled()))
|
if (ctxt.stock && (h_cfg.t210b01 || !tools_autorcm_enabled()))
|
||||||
{
|
{
|
||||||
sdram_src_pllc(false);
|
sdram_src_pllc(false);
|
||||||
|
emummc_storage_end();
|
||||||
|
emusd_storage_end();
|
||||||
emmc_end();
|
emmc_end();
|
||||||
|
|
||||||
WPRINTF("\nRebooting to OFW in 5s...");
|
WPRINTF("\nRebooting to OFW in 5s...");
|
||||||
@@ -819,7 +823,8 @@ int hos_launch(ini_sec_t *cfg)
|
|||||||
|
|
||||||
kb = ctxt.pkg1_id->kb;
|
kb = ctxt.pkg1_id->kb;
|
||||||
|
|
||||||
bool emummc_enabled = emu_cfg.enabled && !h_cfg.emummc_force_disable;
|
// TODO: separate force_disable for emuSD?
|
||||||
|
bool emummc_enabled = (emu_cfg.enabled || emu_sd_cfg.enabled) && !h_cfg.emummc_force_disable;
|
||||||
|
|
||||||
// Enable emummc patching.
|
// Enable emummc patching.
|
||||||
if (emummc_enabled)
|
if (emummc_enabled)
|
||||||
@@ -830,7 +835,7 @@ int hos_launch(ini_sec_t *cfg)
|
|||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
ctxt.atmosphere = true; // Set atmosphere patching in case of no fss0.
|
ctxt.patch_krn_proc_id = true; // Set kernel process id patching in case of no pkg3.
|
||||||
config_kip1patch(&ctxt, "emummc");
|
config_kip1patch(&ctxt, "emummc");
|
||||||
}
|
}
|
||||||
else if (!emu_cfg.enabled && ctxt.emummc_forced)
|
else if (!emu_cfg.enabled && ctxt.emummc_forced)
|
||||||
@@ -882,7 +887,7 @@ int hos_launch(ini_sec_t *cfg)
|
|||||||
tsec_ctxt.pkg11_off = ctxt.pkg1_id->pkg11_off;
|
tsec_ctxt.pkg11_off = ctxt.pkg1_id->pkg11_off;
|
||||||
|
|
||||||
// Generate keys.
|
// Generate keys.
|
||||||
if (!hos_keygen(ctxt.keyblob, kb, &tsec_ctxt, ctxt.stock, is_exo))
|
if (!_hos_keygen(ctxt.keyblob, kb, &tsec_ctxt, ctxt.stock, is_exo))
|
||||||
goto error;
|
goto error;
|
||||||
gfx_puts("Generated keys\n");
|
gfx_puts("Generated keys\n");
|
||||||
|
|
||||||
@@ -984,7 +989,7 @@ int hos_launch(ini_sec_t *cfg)
|
|||||||
_hos_crit_error("Pkg2 decryption failed!\npkg1/pkg2 mismatch or old hekate!");
|
_hos_crit_error("Pkg2 decryption failed!\npkg1/pkg2 mismatch or old hekate!");
|
||||||
|
|
||||||
// Clear EKS slot, in case something went wrong with tsec keygen.
|
// Clear EKS slot, in case something went wrong with tsec keygen.
|
||||||
hos_eks_clear(kb);
|
_hos_eks_clear(kb);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1003,7 +1008,7 @@ int hos_launch(ini_sec_t *cfg)
|
|||||||
ctxt.kernel = pkg2_hdr->data;
|
ctxt.kernel = pkg2_hdr->data;
|
||||||
ctxt.kernel_size = pkg2_hdr->sec_size[PKG2_SEC_KERNEL];
|
ctxt.kernel_size = pkg2_hdr->sec_size[PKG2_SEC_KERNEL];
|
||||||
|
|
||||||
if (!ctxt.stock && (ctxt.svcperm || ctxt.debugmode || ctxt.atmosphere))
|
if (!ctxt.stock && (ctxt.svcperm || ctxt.debugmode || ctxt.patch_krn_proc_id))
|
||||||
{
|
{
|
||||||
// Hash only Kernel when it embeds INI1.
|
// Hash only Kernel when it embeds INI1.
|
||||||
u8 kernel_hash[0x20];
|
u8 kernel_hash[0x20];
|
||||||
@@ -1030,10 +1035,10 @@ int hos_launch(ini_sec_t *cfg)
|
|||||||
for (u32 i = 0; kernel_patchset[i].id != 0xFFFFFFFF; i++)
|
for (u32 i = 0; kernel_patchset[i].id != 0xFFFFFFFF; i++)
|
||||||
{
|
{
|
||||||
if ((ctxt.svcperm && kernel_patchset[i].id == SVC_VERIFY_DS)
|
if ((ctxt.svcperm && kernel_patchset[i].id == SVC_VERIFY_DS)
|
||||||
|| (ctxt.debugmode && kernel_patchset[i].id == DEBUG_MODE_EN && !(ctxt.atmosphere && ctxt.secmon))
|
|| (ctxt.debugmode && kernel_patchset[i].id == DEBUG_MODE_EN && !(ctxt.patch_krn_proc_id && ctxt.secmon))
|
||||||
|| (ctxt.atmosphere && kernel_patchset[i].id == ATM_GEN_PATCH))
|
|| (ctxt.patch_krn_proc_id && kernel_patchset[i].id == ATM_GEN_PATCH))
|
||||||
*(vu32 *)(ctxt.kernel + kernel_patchset[i].off) = kernel_patchset[i].val;
|
*(vu32 *)(ctxt.kernel + kernel_patchset[i].off) = kernel_patchset[i].val;
|
||||||
else if (ctxt.atmosphere && kernel_patchset[i].id == ATM_ARR_PATCH)
|
else if (ctxt.patch_krn_proc_id && kernel_patchset[i].id == ATM_ARR_PATCH)
|
||||||
{
|
{
|
||||||
temp = (u32 *)kernel_patchset[i].ptr;
|
temp = (u32 *)kernel_patchset[i].ptr;
|
||||||
for (u32 j = 0; j < kernel_patchset[i].val; j++)
|
for (u32 j = 0; j < kernel_patchset[i].val; j++)
|
||||||
@@ -1055,7 +1060,7 @@ int hos_launch(ini_sec_t *cfg)
|
|||||||
{
|
{
|
||||||
bool exfat_compat = _get_fs_exfat_compatible(&kip1_info, &ctxt.exo_ctx.hos_revision);
|
bool exfat_compat = _get_fs_exfat_compatible(&kip1_info, &ctxt.exo_ctx.hos_revision);
|
||||||
|
|
||||||
if (sd_fs.fs_type == FS_EXFAT && !exfat_compat)
|
if (emusd_get_fs_type() == FS_EXFAT && !exfat_compat)
|
||||||
{
|
{
|
||||||
_hos_crit_error("SD Card is exFAT but installed HOS driver\nonly supports FAT32!");
|
_hos_crit_error("SD Card is exFAT but installed HOS driver\nonly supports FAT32!");
|
||||||
|
|
||||||
@@ -1088,6 +1093,8 @@ int hos_launch(ini_sec_t *cfg)
|
|||||||
config_exosphere(&ctxt, warmboot_base);
|
config_exosphere(&ctxt, warmboot_base);
|
||||||
|
|
||||||
// Unmount SD card and eMMC.
|
// Unmount SD card and eMMC.
|
||||||
|
emummc_storage_end();
|
||||||
|
emusd_storage_end();
|
||||||
boot_storage_end();
|
boot_storage_end();
|
||||||
sd_end();
|
sd_end();
|
||||||
emmc_end();
|
emmc_end();
|
||||||
@@ -1154,6 +1161,7 @@ int hos_launch(ini_sec_t *cfg)
|
|||||||
//pmc_scratch_lock(PMC_SEC_LOCK_LP0_PARAMS);
|
//pmc_scratch_lock(PMC_SEC_LOCK_LP0_PARAMS);
|
||||||
|
|
||||||
// Set secmon mailbox address and clear it.
|
// Set secmon mailbox address and clear it.
|
||||||
|
volatile secmon_mailbox_t *secmon_mailbox;
|
||||||
if (kb >= HOS_KB_VERSION_700 || is_exo)
|
if (kb >= HOS_KB_VERSION_700 || is_exo)
|
||||||
{
|
{
|
||||||
memset((void *)SECMON7_MAILBOX_ADDR, 0, 0x200);
|
memset((void *)SECMON7_MAILBOX_ADDR, 0, 0x200);
|
||||||
@@ -1202,9 +1210,9 @@ int hos_launch(ini_sec_t *cfg)
|
|||||||
error:
|
error:
|
||||||
_free_launch_components(&ctxt);
|
_free_launch_components(&ctxt);
|
||||||
sdram_src_pllc(false);
|
sdram_src_pllc(false);
|
||||||
|
emummc_storage_end();
|
||||||
|
emusd_storage_end();
|
||||||
emmc_end();
|
emmc_end();
|
||||||
|
|
||||||
EPRINTF("\nFailed to launch HOS!");
|
EPRINTF("\nFailed to launch HOS!");
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2018 naehrwert
|
* Copyright (c) 2018 naehrwert
|
||||||
* Copyright (c) 2018-2024 CTCaer
|
* Copyright (c) 2018-2025 CTCaer
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
* under the terms and conditions of the GNU General Public License,
|
* under the terms and conditions of the GNU General Public License,
|
||||||
@@ -46,7 +46,8 @@ enum {
|
|||||||
HOS_KB_VERSION_1700 = 16,
|
HOS_KB_VERSION_1700 = 16,
|
||||||
HOS_KB_VERSION_1800 = 17,
|
HOS_KB_VERSION_1800 = 17,
|
||||||
HOS_KB_VERSION_1900 = 18,
|
HOS_KB_VERSION_1900 = 18,
|
||||||
HOS_KB_VERSION_MAX = HOS_KB_VERSION_1900
|
HOS_KB_VERSION_2000 = 19,
|
||||||
|
HOS_KB_VERSION_MAX = HOS_KB_VERSION_2000
|
||||||
};
|
};
|
||||||
|
|
||||||
#define HOS_TSEC_VERSION 4 //! TODO: Update on TSEC Root Key changes.
|
#define HOS_TSEC_VERSION 4 //! TODO: Update on TSEC Root Key changes.
|
||||||
@@ -104,16 +105,16 @@ typedef struct _launch_ctxt_t
|
|||||||
u32 kernel_size;
|
u32 kernel_size;
|
||||||
|
|
||||||
link_t kip1_list;
|
link_t kip1_list;
|
||||||
char* kip1_patches;
|
char *kip1_patches;
|
||||||
|
|
||||||
bool svcperm;
|
bool svcperm;
|
||||||
bool debugmode;
|
bool debugmode;
|
||||||
bool stock;
|
bool stock;
|
||||||
bool emummc_forced;
|
bool emummc_forced;
|
||||||
|
|
||||||
void *fss0;
|
void *pkg3;
|
||||||
u32 fss0_hosver;
|
u32 pkg3_hosver;
|
||||||
bool atmosphere;
|
bool patch_krn_proc_id;
|
||||||
|
|
||||||
int ucid;
|
int ucid;
|
||||||
|
|
||||||
@@ -128,8 +129,6 @@ typedef struct _merge_kip_t
|
|||||||
link_t link;
|
link_t link;
|
||||||
} merge_kip_t;
|
} merge_kip_t;
|
||||||
|
|
||||||
void hos_eks_clear(u32 kb);
|
void hos_launch(ini_sec_t *cfg);
|
||||||
int hos_launch(ini_sec_t *cfg);
|
|
||||||
int hos_keygen(void *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt, bool stock, bool is_exo);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2018 naehrwert
|
* Copyright (c) 2018 naehrwert
|
||||||
* Copyright (c) 2018-2024 CTCaer
|
* Copyright (c) 2018-2025 CTCaer
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
* under the terms and conditions of the GNU General Public License,
|
* under the terms and conditions of the GNU General Public License,
|
||||||
@@ -16,13 +16,14 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <storage/boot_storage.h>
|
#include <storage/boot_storage.h>
|
||||||
|
#include "../storage/emusd.h"
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include <bdk.h>
|
#include <bdk.h>
|
||||||
|
|
||||||
#include "hos.h"
|
#include "hos.h"
|
||||||
#include "hos_config.h"
|
#include "hos_config.h"
|
||||||
#include "fss.h"
|
#include "pkg3.h"
|
||||||
#include <libs/fatfs/ff.h>
|
#include <libs/fatfs/ff.h>
|
||||||
|
|
||||||
//#define DPRINTF(...) gfx_printf(__VA_ARGS__)
|
//#define DPRINTF(...) gfx_printf(__VA_ARGS__)
|
||||||
@@ -30,7 +31,7 @@
|
|||||||
|
|
||||||
static int _config_warmboot(launch_ctxt_t *ctxt, const char *value)
|
static int _config_warmboot(launch_ctxt_t *ctxt, const char *value)
|
||||||
{
|
{
|
||||||
ctxt->warmboot = boot_storage_file_read(value, &ctxt->warmboot_size);
|
ctxt->warmboot = emusd_file_read(value, &ctxt->warmboot_size);
|
||||||
if (!ctxt->warmboot)
|
if (!ctxt->warmboot)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@@ -39,7 +40,7 @@ static int _config_warmboot(launch_ctxt_t *ctxt, const char *value)
|
|||||||
|
|
||||||
static int _config_secmon(launch_ctxt_t *ctxt, const char *value)
|
static int _config_secmon(launch_ctxt_t *ctxt, const char *value)
|
||||||
{
|
{
|
||||||
ctxt->secmon = boot_storage_file_read(value, &ctxt->secmon_size);
|
ctxt->secmon = emusd_file_read(value, &ctxt->secmon_size);
|
||||||
if (!ctxt->secmon)
|
if (!ctxt->secmon)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@@ -48,7 +49,7 @@ static int _config_secmon(launch_ctxt_t *ctxt, const char *value)
|
|||||||
|
|
||||||
static int _config_kernel(launch_ctxt_t *ctxt, const char *value)
|
static int _config_kernel(launch_ctxt_t *ctxt, const char *value)
|
||||||
{
|
{
|
||||||
ctxt->kernel = boot_storage_file_read(value, &ctxt->kernel_size);
|
ctxt->kernel = emusd_file_read(value, &ctxt->kernel_size);
|
||||||
if (!ctxt->kernel)
|
if (!ctxt->kernel)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@@ -59,10 +60,11 @@ static int _config_kip1(launch_ctxt_t *ctxt, const char *value)
|
|||||||
{
|
{
|
||||||
u32 size;
|
u32 size;
|
||||||
|
|
||||||
if (!memcmp(value + strlen(value) - 1, "*", 1))
|
if (value[strlen(value) - 1] == '*')
|
||||||
{
|
{
|
||||||
char *dir = (char *)malloc(256);
|
char *dir = (char *)malloc(256);
|
||||||
strcpy(dir, value);
|
strcpy(dir, "emusd:");
|
||||||
|
strcat(dir, value);
|
||||||
|
|
||||||
u32 dirlen = 0;
|
u32 dirlen = 0;
|
||||||
dir[strlen(dir) - 2] = 0;
|
dir[strlen(dir) - 2] = 0;
|
||||||
@@ -82,7 +84,7 @@ static int _config_kip1(launch_ctxt_t *ctxt, const char *value)
|
|||||||
strcpy(dir + dirlen, filelist->name[i]);
|
strcpy(dir + dirlen, filelist->name[i]);
|
||||||
|
|
||||||
merge_kip_t *mkip1 = (merge_kip_t *)malloc(sizeof(merge_kip_t));
|
merge_kip_t *mkip1 = (merge_kip_t *)malloc(sizeof(merge_kip_t));
|
||||||
mkip1->kip1 = boot_storage_file_read(dir, &size);
|
mkip1->kip1 = emusd_file_read(dir + 6, &size);
|
||||||
if (!mkip1->kip1)
|
if (!mkip1->kip1)
|
||||||
{
|
{
|
||||||
free(mkip1);
|
free(mkip1);
|
||||||
@@ -104,7 +106,7 @@ static int _config_kip1(launch_ctxt_t *ctxt, const char *value)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
merge_kip_t *mkip1 = (merge_kip_t *)malloc(sizeof(merge_kip_t));
|
merge_kip_t *mkip1 = (merge_kip_t *)malloc(sizeof(merge_kip_t));
|
||||||
mkip1->kip1 = boot_storage_file_read(value, &size);
|
mkip1->kip1 = emusd_file_read(value, &size);
|
||||||
if (!mkip1->kip1)
|
if (!mkip1->kip1)
|
||||||
{
|
{
|
||||||
free(mkip1);
|
free(mkip1);
|
||||||
@@ -120,9 +122,6 @@ static int _config_kip1(launch_ctxt_t *ctxt, const char *value)
|
|||||||
|
|
||||||
int config_kip1patch(launch_ctxt_t *ctxt, const char *value)
|
int config_kip1patch(launch_ctxt_t *ctxt, const char *value)
|
||||||
{
|
{
|
||||||
if (value == NULL)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
int len = strlen(value);
|
int len = strlen(value);
|
||||||
if (!len)
|
if (!len)
|
||||||
return 0;
|
return 0;
|
||||||
@@ -189,12 +188,12 @@ static int _config_emummc_forced(launch_ctxt_t *ctxt, const char *value)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _config_atmosphere(launch_ctxt_t *ctxt, const char *value)
|
static int _config_kernel_proc_id(launch_ctxt_t *ctxt, const char *value)
|
||||||
{
|
{
|
||||||
if (*value == '1')
|
if (*value == '1')
|
||||||
{
|
{
|
||||||
DPRINTF("Enabled atmosphere patching\n");
|
DPRINTF("Enabled kernel process id send/recv patching\n");
|
||||||
ctxt->atmosphere = true;
|
ctxt->patch_krn_proc_id = true;
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -259,14 +258,14 @@ static int _config_exo_cal0_writes_enable(launch_ctxt_t *ctxt, const char *value
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _config_fss(launch_ctxt_t *ctxt, const char *value)
|
static int _config_pkg3(launch_ctxt_t *ctxt, const char *value)
|
||||||
{
|
{
|
||||||
return parse_fss(ctxt, value);
|
return parse_pkg3(ctxt, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _config_exo_fatal_payload(launch_ctxt_t *ctxt, const char *value)
|
static int _config_exo_fatal_payload(launch_ctxt_t *ctxt, const char *value)
|
||||||
{
|
{
|
||||||
ctxt->exofatal = boot_storage_file_read(value, &ctxt->exofatal_size);
|
ctxt->exofatal = emusd_file_read(value, &ctxt->exofatal_size);
|
||||||
if (!ctxt->exofatal)
|
if (!ctxt->exofatal)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@@ -288,6 +287,7 @@ typedef struct _cfg_handler_t
|
|||||||
} cfg_handler_t;
|
} cfg_handler_t;
|
||||||
|
|
||||||
static const cfg_handler_t _config_handlers[] = {
|
static const cfg_handler_t _config_handlers[] = {
|
||||||
|
{ "stock", _config_stock },
|
||||||
{ "warmboot", _config_warmboot },
|
{ "warmboot", _config_warmboot },
|
||||||
{ "secmon", _config_secmon },
|
{ "secmon", _config_secmon },
|
||||||
{ "kernel", _config_kernel },
|
{ "kernel", _config_kernel },
|
||||||
@@ -295,9 +295,12 @@ static const cfg_handler_t _config_handlers[] = {
|
|||||||
{ "kip1patch", config_kip1patch },
|
{ "kip1patch", config_kip1patch },
|
||||||
{ "fullsvcperm", _config_svcperm },
|
{ "fullsvcperm", _config_svcperm },
|
||||||
{ "debugmode", _config_debugmode },
|
{ "debugmode", _config_debugmode },
|
||||||
{ "stock", _config_stock },
|
{ "kernelprocid", _config_kernel_proc_id },
|
||||||
{ "atmosphere", _config_atmosphere },
|
|
||||||
{ "fss0", _config_fss },
|
// To override elements from PKG3, it should be set before others.
|
||||||
|
{ "pkg3", _config_pkg3 },
|
||||||
|
{ "fss0", _config_pkg3 },
|
||||||
|
|
||||||
{ "exofatal", _config_exo_fatal_payload},
|
{ "exofatal", _config_exo_fatal_payload},
|
||||||
{ "emummcforce", _config_emummc_forced },
|
{ "emummcforce", _config_emummc_forced },
|
||||||
{ "nouserexceptions", _config_dis_exo_user_exceptions },
|
{ "nouserexceptions", _config_dis_exo_user_exceptions },
|
||||||
@@ -311,10 +314,15 @@ static const cfg_handler_t _config_handlers[] = {
|
|||||||
|
|
||||||
int parse_boot_config(launch_ctxt_t *ctxt)
|
int parse_boot_config(launch_ctxt_t *ctxt)
|
||||||
{
|
{
|
||||||
|
if (!ctxt->cfg)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
// Check each config key.
|
||||||
LIST_FOREACH_ENTRY(ini_kv_t, kv, &ctxt->cfg->kvs, link)
|
LIST_FOREACH_ENTRY(ini_kv_t, kv, &ctxt->cfg->kvs, link)
|
||||||
{
|
{
|
||||||
for (u32 i = 0; _config_handlers[i].key; i++)
|
for (u32 i = 0; _config_handlers[i].key; i++)
|
||||||
{
|
{
|
||||||
|
// If key matches, call its handler.
|
||||||
if (!strcmp(_config_handlers[i].key, kv->key))
|
if (!strcmp(_config_handlers[i].key, kv->key))
|
||||||
{
|
{
|
||||||
if (!_config_handlers[i].handler(ctxt, kv->val))
|
if (!_config_handlers[i].handler(ctxt, kv->val))
|
||||||
@@ -324,6 +332,8 @@ int parse_boot_config(launch_ctxt_t *ctxt)
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2018 naehrwert
|
* Copyright (c) 2018 naehrwert
|
||||||
* Copyright (c) 2018 st4rk
|
* Copyright (c) 2018 st4rk
|
||||||
* Copyright (c) 2018-2024 CTCaer
|
* Copyright (c) 2018-2025 CTCaer
|
||||||
* Copyright (c) 2018 balika011
|
* Copyright (c) 2018 balika011
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
@@ -18,6 +18,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <storage/boot_storage.h>
|
#include <storage/boot_storage.h>
|
||||||
|
#include "../storage/emusd.h"
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
@@ -34,7 +35,7 @@ extern hekate_config h_cfg;
|
|||||||
#define SM_100_ADR 0x4002B020 // Original: 0x40014020.
|
#define SM_100_ADR 0x4002B020 // Original: 0x40014020.
|
||||||
PATCHSET_DEF(_secmon_1_patchset,
|
PATCHSET_DEF(_secmon_1_patchset,
|
||||||
// Patch the relocator to be able to run from SM_100_ADR.
|
// Patch the relocator to be able to run from SM_100_ADR.
|
||||||
{ 0x1E0, _ADRP(0, 0x7C013000 - _PAGEOFF(SM_100_ADR)) },
|
{ 0x1E0, _ADRP(0, TZRAM_BASE + 0x3000 - _PAGEOFF(SM_100_ADR)) },
|
||||||
// Patch package2 signature/hash checks.
|
// Patch package2 signature/hash checks.
|
||||||
{ 0x9F0 + 0xADC, _NOP() }
|
{ 0x9F0 + 0xADC, _NOP() }
|
||||||
);
|
);
|
||||||
@@ -144,7 +145,7 @@ static const u8 sec_map_100[3] = { PK11_SECTION_SM, PK11_SECTION_LD, PK11_SECTIO
|
|||||||
static const u8 sec_map_2xx[3] = { PK11_SECTION_WB, PK11_SECTION_LD, PK11_SECTION_SM };
|
static const u8 sec_map_2xx[3] = { PK11_SECTION_WB, PK11_SECTION_LD, PK11_SECTION_SM };
|
||||||
static const u8 sec_map_4xx[3] = { PK11_SECTION_LD, PK11_SECTION_SM, PK11_SECTION_WB };
|
static const u8 sec_map_4xx[3] = { PK11_SECTION_LD, PK11_SECTION_SM, PK11_SECTION_WB };
|
||||||
|
|
||||||
// ID (Timestamp), KB, Fuses, TSEC, PK11, SECMON, Warmboot.
|
// Timestamp KB FU TSEC PK11 SECMON Warmboot
|
||||||
static const pkg1_id_t _pkg1_ids[] = {
|
static const pkg1_id_t _pkg1_ids[] = {
|
||||||
{ "20161121", 0, 1, 0x1900, 0x3FE0, SM_100_ADR, 0x8000D000, _secmon_1_patchset }, // 1.0.0 (Patched relocator).
|
{ "20161121", 0, 1, 0x1900, 0x3FE0, SM_100_ADR, 0x8000D000, _secmon_1_patchset }, // 1.0.0 (Patched relocator).
|
||||||
{ "20170210", 0, 2, 0x1900, 0x3FE0, 0x4002D000, 0x8000D000, _secmon_2_patchset }, // 2.0.0 - 2.3.0.
|
{ "20170210", 0, 2, 0x1900, 0x3FE0, 0x4002D000, 0x8000D000, _secmon_2_patchset }, // 2.0.0 - 2.3.0.
|
||||||
@@ -172,7 +173,8 @@ static const pkg1_id_t _pkg1_ids[] = {
|
|||||||
{ "20230111", 15, 18, 0x0E00, 0x6FE0, 0x40030000, 0x4003E000, NULL }, // 16.0.0 - 16.1.0.
|
{ "20230111", 15, 18, 0x0E00, 0x6FE0, 0x40030000, 0x4003E000, NULL }, // 16.0.0 - 16.1.0.
|
||||||
{ "20230906", 16, 19, 0x0E00, 0x6FE0, 0x40030000, 0x4003E000, NULL }, // 17.0.0 - 17.0.1.
|
{ "20230906", 16, 19, 0x0E00, 0x6FE0, 0x40030000, 0x4003E000, NULL }, // 17.0.0 - 17.0.1.
|
||||||
{ "20240207", 17, 19, 0x0E00, 0x6FE0, 0x40030000, 0x4003E000, NULL }, // 18.0.0 - 18.1.0.
|
{ "20240207", 17, 19, 0x0E00, 0x6FE0, 0x40030000, 0x4003E000, NULL }, // 18.0.0 - 18.1.0.
|
||||||
{ "20240808", 18, 20, 0x0E00, 0x6FE0, 0x40030000, 0x4003E000, NULL }, // 19.0.0+
|
{ "20240808", 18, 20, 0x0E00, 0x6FE0, 0x40030000, 0x4003E000, NULL }, // 19.0.0 - 19.0.1.
|
||||||
|
{ "20250206", 19, 21, 0x0E00, 0x6FE0, 0x40030000, 0x4003E000, NULL }, // 20.0.0+
|
||||||
};
|
};
|
||||||
|
|
||||||
const pkg1_id_t *pkg1_get_latest()
|
const pkg1_id_t *pkg1_get_latest()
|
||||||
@@ -369,13 +371,13 @@ int pkg1_warmboot_config(void *hos_ctxt, u32 warmboot_base, u32 fuses_fw, u8 kb)
|
|||||||
if (!ctxt->warmboot)
|
if (!ctxt->warmboot)
|
||||||
{
|
{
|
||||||
char path[128];
|
char path[128];
|
||||||
strcpy(path, "warmboot_mariko/wb_");
|
strcpy(path, "emusd:warmboot_mariko/wb_");
|
||||||
_warmboot_filename(path, fuses_fw);
|
_warmboot_filename(path, fuses_fw);
|
||||||
|
|
||||||
// Check if warmboot fw exists and save it.
|
// Check if warmboot fw exists and save it.
|
||||||
if (ctxt->warmboot_size && f_stat(path, NULL))
|
if (ctxt->warmboot_size && f_stat(path, NULL))
|
||||||
{
|
{
|
||||||
f_mkdir("warmboot_mariko");
|
f_mkdir("emusd:warmboot_mariko");
|
||||||
sd_save_to_file((void *)warmboot_base, ctxt->warmboot_size, path);
|
sd_save_to_file((void *)warmboot_base, ctxt->warmboot_size, path);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -388,7 +390,7 @@ int pkg1_warmboot_config(void *hos_ctxt, u32 warmboot_base, u32 fuses_fw, u8 kb)
|
|||||||
_warmboot_filename(path, burnt_fuses);
|
_warmboot_filename(path, burnt_fuses);
|
||||||
if (!f_stat(path, NULL))
|
if (!f_stat(path, NULL))
|
||||||
{
|
{
|
||||||
ctxt->warmboot = boot_storage_file_read(path, &ctxt->warmboot_size);
|
ctxt->warmboot = emusd_file_read(path + 6, &ctxt->warmboot_size);
|
||||||
burnt_fuses = tmp_fuses;
|
burnt_fuses = tmp_fuses;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2018 naehrwert
|
* Copyright (c) 2018 naehrwert
|
||||||
* Copyright (c) 2018-2024 CTCaer
|
* Copyright (c) 2018-2025 CTCaer
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
* under the terms and conditions of the GNU General Public License,
|
* under the terms and conditions of the GNU General Public License,
|
||||||
@@ -28,6 +28,7 @@
|
|||||||
#include <libs/compr/blz.h>
|
#include <libs/compr/blz.h>
|
||||||
#include <libs/fatfs/ff.h>
|
#include <libs/fatfs/ff.h>
|
||||||
#include "../storage/emummc.h"
|
#include "../storage/emummc.h"
|
||||||
|
#include "../storage/emusd.h"
|
||||||
|
|
||||||
//#define DPRINTF(...) gfx_printf(__VA_ARGS__)
|
//#define DPRINTF(...) gfx_printf(__VA_ARGS__)
|
||||||
#define DPRINTF(...)
|
#define DPRINTF(...)
|
||||||
@@ -38,6 +39,7 @@ extern const u8 package2_keyseed[];
|
|||||||
u32 pkg2_newkern_ini1_info;
|
u32 pkg2_newkern_ini1_info;
|
||||||
u32 pkg2_newkern_ini1_start;
|
u32 pkg2_newkern_ini1_start;
|
||||||
u32 pkg2_newkern_ini1_end;
|
u32 pkg2_newkern_ini1_end;
|
||||||
|
u32 pkg2_newkern_ini1_rela;
|
||||||
|
|
||||||
enum kip_offset_section
|
enum kip_offset_section
|
||||||
{
|
{
|
||||||
@@ -75,6 +77,7 @@ static void parse_external_kip_patches()
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
LIST_INIT(ini_kip_sections);
|
LIST_INIT(ini_kip_sections);
|
||||||
|
// TODO: load frome emusd?
|
||||||
if (ini_patch_parse(&ini_kip_sections, "bootloader/patches.ini"))
|
if (ini_patch_parse(&ini_kip_sections, "bootloader/patches.ini"))
|
||||||
{
|
{
|
||||||
// Copy ids into a new patchset.
|
// Copy ids into a new patchset.
|
||||||
@@ -189,11 +192,12 @@ static u32 _pkg2_calc_kip1_size(pkg2_kip1_t *kip1)
|
|||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
void pkg2_get_newkern_info(u8 *kern_data)
|
static void _pkg2_get_newkern_info(u8 *kern_data)
|
||||||
{
|
{
|
||||||
u32 crt_start = 0;
|
u32 crt_start = 0;
|
||||||
pkg2_newkern_ini1_info = 0;
|
pkg2_newkern_ini1_info = 0;
|
||||||
pkg2_newkern_ini1_start = 0;
|
pkg2_newkern_ini1_start = 0;
|
||||||
|
pkg2_newkern_ini1_rela = 0;
|
||||||
|
|
||||||
u32 first_op = *(u32 *)kern_data;
|
u32 first_op = *(u32 *)kern_data;
|
||||||
if ((first_op & 0xFE000000) == 0x14000000)
|
if ((first_op & 0xFE000000) == 0x14000000)
|
||||||
@@ -230,6 +234,7 @@ void pkg2_get_newkern_info(u8 *kern_data)
|
|||||||
// On v2 kernel with dynamic crt, values are relative to value address.
|
// On v2 kernel with dynamic crt, values are relative to value address.
|
||||||
if (crt_start)
|
if (crt_start)
|
||||||
{
|
{
|
||||||
|
pkg2_newkern_ini1_rela = pkg2_newkern_ini1_info;
|
||||||
pkg2_newkern_ini1_start += pkg2_newkern_ini1_info;
|
pkg2_newkern_ini1_start += pkg2_newkern_ini1_info;
|
||||||
pkg2_newkern_ini1_end += pkg2_newkern_ini1_info + 0x8;
|
pkg2_newkern_ini1_end += pkg2_newkern_ini1_info + 0x8;
|
||||||
}
|
}
|
||||||
@@ -241,7 +246,7 @@ bool pkg2_parse_kips(link_t *info, pkg2_hdr_t *pkg2, bool *new_pkg2)
|
|||||||
// Check for new pkg2 type.
|
// Check for new pkg2 type.
|
||||||
if (!pkg2->sec_size[PKG2_SEC_INI1])
|
if (!pkg2->sec_size[PKG2_SEC_INI1])
|
||||||
{
|
{
|
||||||
pkg2_get_newkern_info(pkg2->data);
|
_pkg2_get_newkern_info(pkg2->data);
|
||||||
|
|
||||||
if (!pkg2_newkern_ini1_start)
|
if (!pkg2_newkern_ini1_start)
|
||||||
return false;
|
return false;
|
||||||
@@ -665,6 +670,8 @@ const char *pkg2_patch_kips(link_t *info, char *patch_names)
|
|||||||
if (kip_id_idx > 17)
|
if (kip_id_idx > 17)
|
||||||
emu_cfg.fs_ver -= 2;
|
emu_cfg.fs_ver -= 2;
|
||||||
|
|
||||||
|
emu_sd_cfg.fs_ver = emu_cfg.fs_ver;
|
||||||
|
|
||||||
// Inject emuMMC code.
|
// Inject emuMMC code.
|
||||||
gfx_printf("Injecting emuMMC. FS ID: %d\n", emu_cfg.fs_ver);
|
gfx_printf("Injecting emuMMC. FS ID: %d\n", emu_cfg.fs_ver);
|
||||||
if (_kipm_inject("bootloader/sys/emummc.kipm", "FS", ki))
|
if (_kipm_inject("bootloader/sys/emummc.kipm", "FS", ki))
|
||||||
@@ -684,6 +691,10 @@ const char *pkg2_patch_kips(link_t *info, char *patch_names)
|
|||||||
return patches[i];
|
return patches[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check if emuMMC was applied.
|
||||||
|
if (emummc_patch_selected)
|
||||||
|
return "emummc";
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -846,10 +857,15 @@ DPRINTF("%s @ %08X (%08X)\n", is_meso ? "Mesosphere": "kernel",(u32)ctxt->kernel
|
|||||||
|
|
||||||
// Set new INI1 offset to kernel.
|
// Set new INI1 offset to kernel.
|
||||||
u32 meso_meta_offset = *(u32 *)(pdst + 8);
|
u32 meso_meta_offset = *(u32 *)(pdst + 8);
|
||||||
if (is_meso && (meso_magic & 0xF000000)) // MSS1.
|
if (is_meso && (meso_magic & 0x0F000000)) // MSS1.
|
||||||
*(u32 *)(pdst + meso_meta_offset) = kernel_size - meso_meta_offset;
|
*(u32 *)(pdst + meso_meta_offset) = kernel_size - meso_meta_offset;
|
||||||
else if (ini1_size)
|
else if (ini1_size)
|
||||||
*(u32 *)(pdst + (is_meso ? 8 : pkg2_newkern_ini1_info)) = kernel_size;
|
{
|
||||||
|
if (is_meso) // MSS0.
|
||||||
|
*(u32 *)(pdst + 8) = kernel_size;
|
||||||
|
else
|
||||||
|
*(u32 *)(pdst + pkg2_newkern_ini1_info) = kernel_size - pkg2_newkern_ini1_rela;
|
||||||
|
}
|
||||||
|
|
||||||
kernel_size += ini1_size;
|
kernel_size += ini1_size;
|
||||||
}
|
}
|
||||||
@@ -866,13 +882,13 @@ DPRINTF("INI1 encrypted\n");
|
|||||||
|
|
||||||
if (!is_exo) // Not needed on Exosphere 1.0.0 and up.
|
if (!is_exo) // Not needed on Exosphere 1.0.0 and up.
|
||||||
{
|
{
|
||||||
// Calculate SHA256 over encrypted Kernel and INI1.
|
// Calculate SHA256 over encrypted sections. Only 3 have valid hashes.
|
||||||
u8 *pk2_hash_data = (u8 *)dst + 0x100 + sizeof(pkg2_hdr_t);
|
u8 *pk2_hash_data = (u8 *)dst + 0x100 + sizeof(pkg2_hdr_t);
|
||||||
se_calc_sha256_oneshot(&hdr->sec_sha256[SE_SHA_256_SIZE * PKG2_SEC_KERNEL],
|
for (u32 i = PKG2_SEC_KERNEL; i <= PKG2_SEC_UNUSED; i++)
|
||||||
(void *)pk2_hash_data, hdr->sec_size[PKG2_SEC_KERNEL]);
|
{
|
||||||
pk2_hash_data += hdr->sec_size[PKG2_SEC_KERNEL];
|
se_calc_sha256_oneshot(&hdr->sec_sha256[SE_SHA_256_SIZE * i], (void *)pk2_hash_data, hdr->sec_size[i]);
|
||||||
se_calc_sha256_oneshot(&hdr->sec_sha256[SE_SHA_256_SIZE * PKG2_SEC_INI1],
|
pk2_hash_data += hdr->sec_size[i];
|
||||||
(void *)pk2_hash_data, hdr->sec_size[PKG2_SEC_INI1]);
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Encrypt header.
|
// Encrypt header.
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2018 naehrwert
|
* Copyright (c) 2018 naehrwert
|
||||||
* Copyright (c) 2018-2024 CTCaer
|
* Copyright (c) 2018-2025 CTCaer
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
* under the terms and conditions of the GNU General Public License,
|
* under the terms and conditions of the GNU General Public License,
|
||||||
@@ -20,16 +20,17 @@
|
|||||||
|
|
||||||
#include <bdk.h>
|
#include <bdk.h>
|
||||||
|
|
||||||
#define PKG2_MAGIC 0x31324B50
|
#define PKG2_MAGIC 0x31324B50
|
||||||
#define PKG2_SEC_BASE 0x80000000
|
#define PKG2_SEC_BASE 0x80000000
|
||||||
#define PKG2_SEC_KERNEL 0
|
#define PKG2_SEC_KERNEL 0
|
||||||
#define PKG2_SEC_INI1 1
|
#define PKG2_SEC_INI1 1
|
||||||
|
#define PKG2_SEC_UNUSED 2
|
||||||
|
|
||||||
#define INI1_MAGIC 0x31494E49
|
#define INI1_MAGIC 0x31494E49
|
||||||
|
|
||||||
//! TODO: Update on kernel change if needed.
|
//! TODO: Update on kernel change if needed.
|
||||||
// Offset of OP + 12 is the INI1 offset. On v2 with dynamic crt0 it's + 16.
|
// Offset of OP + 12 is the INI1 offset. On v2 with dynamic crt0 it's + 16.
|
||||||
#define PKG2_NEWKERN_GET_INI1_HEURISTIC 0xD2800015
|
#define PKG2_NEWKERN_GET_INI1_HEURISTIC 0xD2800015 // MOV X21, #0.
|
||||||
#define PKG2_NEWKERN_START 0x800
|
#define PKG2_NEWKERN_START 0x800
|
||||||
|
|
||||||
#define ATM_MESOSPHERE 0x3053534D
|
#define ATM_MESOSPHERE 0x3053534D
|
||||||
@@ -67,18 +68,18 @@ enum
|
|||||||
|
|
||||||
typedef struct _pkg2_hdr_t
|
typedef struct _pkg2_hdr_t
|
||||||
{
|
{
|
||||||
u8 ctr[0x10];
|
/* 0x000 */ u8 ctr[0x10];
|
||||||
u8 sec_ctr[0x40];
|
/* 0x010 */ u8 sec_ctr[0x40];
|
||||||
u32 magic;
|
/* 0x050 */ u32 magic;
|
||||||
u32 base;
|
/* 0x054 */ u32 base;
|
||||||
u32 pad0;
|
/* 0x058 */ u32 pad0;
|
||||||
u8 pkg2_ver;
|
/* 0x05C */ u8 pkg2_ver;
|
||||||
u8 bl_ver;
|
/* 0x05D */ u8 bl_ver;
|
||||||
u16 pad1;
|
/* 0x05E */ u16 pad1;
|
||||||
u32 sec_size[4];
|
/* 0x060 */ u32 sec_size[4];
|
||||||
u32 sec_off[4];
|
/* 0x070 */ u32 sec_off[4];
|
||||||
u8 sec_sha256[0x80];
|
/* 0x080 */ u8 sec_sha256[0x80];
|
||||||
u8 data[];
|
/* 0x100 */ u8 data[];
|
||||||
} pkg2_hdr_t;
|
} pkg2_hdr_t;
|
||||||
|
|
||||||
typedef struct _pkg2_ini1_t
|
typedef struct _pkg2_ini1_t
|
||||||
@@ -102,7 +103,7 @@ typedef struct _pkg2_kip1_sec_t
|
|||||||
typedef struct _pkg2_kip1_t
|
typedef struct _pkg2_kip1_t
|
||||||
{
|
{
|
||||||
/* 0x000 */ u32 magic;
|
/* 0x000 */ u32 magic;
|
||||||
/* 0x004*/ u8 name[12];
|
/* 0x004 */ u8 name[12];
|
||||||
/* 0x010 */ u64 tid;
|
/* 0x010 */ u64 tid;
|
||||||
/* 0x018 */ u32 proc_cat;
|
/* 0x018 */ u32 proc_cat;
|
||||||
/* 0x01C */ u8 main_thrd_prio;
|
/* 0x01C */ u8 main_thrd_prio;
|
||||||
@@ -150,7 +151,6 @@ typedef struct _kip1_id_t
|
|||||||
const kip1_patchset_t *patchset;
|
const kip1_patchset_t *patchset;
|
||||||
} kip1_id_t;
|
} kip1_id_t;
|
||||||
|
|
||||||
void pkg2_get_newkern_info(u8 *kern_data);
|
|
||||||
bool pkg2_parse_kips(link_t *info, pkg2_hdr_t *pkg2, bool *new_pkg2);
|
bool pkg2_parse_kips(link_t *info, pkg2_hdr_t *pkg2, bool *new_pkg2);
|
||||||
int pkg2_has_kip(link_t *info, u64 tid);
|
int pkg2_has_kip(link_t *info, u64 tid);
|
||||||
void pkg2_replace_kip(link_t *info, u64 tid, pkg2_kip1_t *kip1);
|
void pkg2_replace_kip(link_t *info, u64 tid, pkg2_kip1_t *kip1);
|
||||||
|
|||||||
@@ -818,6 +818,30 @@ static const kip1_patchset_t _fs_patches_1900_exfat[] = {
|
|||||||
{ NULL, NULL }
|
{ NULL, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const kip1_patch_t _fs_nogc_2000[] = {
|
||||||
|
{ KPS(KIP_TEXT) | 0x17C150, 8, KIP1_PATCH_SRC_NO_CHECK, "\xE0\x03\x1F\x2A\xC0\x03\x5F\xD6" },
|
||||||
|
{ KPS(KIP_TEXT) | 0x1A7D24, 4, KIP1_PATCH_SRC_NO_CHECK, "\x14\x80\x80\x52" },
|
||||||
|
{ KPS(KIP_TEXT) | 0x1A7F24, 4, KIP1_PATCH_SRC_NO_CHECK, "\x16\x80\x80\x52" },
|
||||||
|
{ 0, 0, NULL, NULL }
|
||||||
|
};
|
||||||
|
|
||||||
|
static const kip1_patchset_t _fs_patches_2000[] = {
|
||||||
|
{ "nogc", _fs_nogc_2000 },
|
||||||
|
{ NULL, NULL }
|
||||||
|
};
|
||||||
|
|
||||||
|
static const kip1_patch_t _fs_nogc_2000_exfat[] = {
|
||||||
|
{ KPS(KIP_TEXT) | 0x187A70, 8, KIP1_PATCH_SRC_NO_CHECK, "\xE0\x03\x1F\x2A\xC0\x03\x5F\xD6" },
|
||||||
|
{ KPS(KIP_TEXT) | 0x1B3644, 4, KIP1_PATCH_SRC_NO_CHECK, "\x14\x80\x80\x52" },
|
||||||
|
{ KPS(KIP_TEXT) | 0x1B3844, 4, KIP1_PATCH_SRC_NO_CHECK, "\x16\x80\x80\x52" },
|
||||||
|
{ 0, 0, NULL, NULL }
|
||||||
|
};
|
||||||
|
|
||||||
|
static const kip1_patchset_t _fs_patches_2000_exfat[] = {
|
||||||
|
{ "nogc", _fs_nogc_2000_exfat },
|
||||||
|
{ NULL, NULL }
|
||||||
|
};
|
||||||
|
|
||||||
// SHA256 hashes.
|
// SHA256 hashes.
|
||||||
static const kip1_id_t _kip_ids[] =
|
static const kip1_id_t _kip_ids[] =
|
||||||
{
|
{
|
||||||
@@ -883,4 +907,8 @@ static const kip1_id_t _kip_ids[] =
|
|||||||
{ "FS", "\x20\x4C\xBA\x86\xDE\x08\x44\x6A", _fs_patches_1800_exfat }, // FS 18.1.0 exFAT
|
{ "FS", "\x20\x4C\xBA\x86\xDE\x08\x44\x6A", _fs_patches_1800_exfat }, // FS 18.1.0 exFAT
|
||||||
{ "FS", "\xD9\x4C\x68\x15\xF8\xF5\x0A\x20", _fs_patches_1900 }, // FS 19.0.0
|
{ "FS", "\xD9\x4C\x68\x15\xF8\xF5\x0A\x20", _fs_patches_1900 }, // FS 19.0.0
|
||||||
{ "FS", "\xED\xA8\x78\x68\xA4\x49\x07\x50", _fs_patches_1900_exfat }, // FS 19.0.0 exFAT
|
{ "FS", "\xED\xA8\x78\x68\xA4\x49\x07\x50", _fs_patches_1900_exfat }, // FS 19.0.0 exFAT
|
||||||
|
{ "FS", "\x63\x54\x96\x9E\x60\xA7\x97\x7B", _fs_patches_2000 }, // FS 20.0.0
|
||||||
|
{ "FS", "\x47\x41\x07\x10\x65\x4F\xA4\x3F", _fs_patches_2000_exfat }, // FS 20.0.0 exFAT
|
||||||
|
{ "FS", "\xED\x34\xB4\x50\x58\x4A\x5B\x43", _fs_patches_2000 }, // FS 20.1.0
|
||||||
|
{ "FS", "\xA5\x1A\xA4\x92\x6C\x41\x87\x59", _fs_patches_2000_exfat }, // FS 20.1.0 exFAT
|
||||||
};
|
};
|
||||||
|
|||||||
298
bootloader/hos/pkg3.c
Normal file
298
bootloader/hos/pkg3.c
Normal file
@@ -0,0 +1,298 @@
|
|||||||
|
/*
|
||||||
|
* Atmosphère Package 3 parser.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2019-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,
|
||||||
|
* version 2, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <storage/boot_storage.h>
|
||||||
|
#include "../storage/emusd.h"
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <bdk.h>
|
||||||
|
|
||||||
|
#include "pkg3.h"
|
||||||
|
#include "hos.h"
|
||||||
|
#include "../config.h"
|
||||||
|
#include <libs/fatfs/ff.h>
|
||||||
|
#include "../storage/emummc.h"
|
||||||
|
|
||||||
|
//#define DPRINTF(...) gfx_printf(__VA_ARGS__)
|
||||||
|
#define DPRINTF(...)
|
||||||
|
|
||||||
|
extern hekate_config h_cfg;
|
||||||
|
|
||||||
|
extern bool is_ipl_updated(void *buf, const char *path, bool force);
|
||||||
|
|
||||||
|
#define PKG3_KIP_SKIP_MAX 16
|
||||||
|
|
||||||
|
// PKG3 Magic and Meta header offset.
|
||||||
|
#define PKG3_MAGIC 0x30535346 // FSS0.
|
||||||
|
#define PKG3_META_OFFSET 0x4
|
||||||
|
#define PKG3_VERSION_0_17_0 0x110000
|
||||||
|
|
||||||
|
// PKG3 Content Types.
|
||||||
|
#define CNT_TYPE_FSP 0
|
||||||
|
#define CNT_TYPE_EXO 1 // Exosphere (Secure Monitor).
|
||||||
|
#define CNT_TYPE_WBT 2 // Warmboot (SC7Exit fw).
|
||||||
|
#define CNT_TYPE_RBT 3 // Rebootstub (Warmboot based reboot fw).
|
||||||
|
#define CNT_TYPE_SP1 4 // Sept Primary (TSEC and Sept Secondary loader).
|
||||||
|
#define CNT_TYPE_SP2 5 // Sept Secondary (Acts as pkg11 and derives keys).
|
||||||
|
#define CNT_TYPE_KIP 6 // KIP1 (Used for replacement or addition).
|
||||||
|
#define CNT_TYPE_BMP 7
|
||||||
|
#define CNT_TYPE_EMC 8
|
||||||
|
#define CNT_TYPE_KLD 9 // Kernel Loader.
|
||||||
|
#define CNT_TYPE_KRN 10 // Kernel.
|
||||||
|
#define CNT_TYPE_EXF 11 // Exosphere Mariko fatal payload.
|
||||||
|
#define CNT_TYPE_TKG 12 // Tsec Keygen.
|
||||||
|
|
||||||
|
// PKG3 Content Flags.
|
||||||
|
#define CNT_FLAG0_EXPERIMENTAL BIT(0)
|
||||||
|
|
||||||
|
// PKG3 Meta Header.
|
||||||
|
typedef struct _pkg3_meta_t
|
||||||
|
{
|
||||||
|
u32 magic;
|
||||||
|
u32 size;
|
||||||
|
u32 crt0_off;
|
||||||
|
u32 cnt_off;
|
||||||
|
u32 cnt_count;
|
||||||
|
u32 hos_ver;
|
||||||
|
u32 version;
|
||||||
|
u32 git_rev;
|
||||||
|
} pkg3_meta_t;
|
||||||
|
|
||||||
|
// PKG3 Content Header.
|
||||||
|
typedef struct _pkg3_content_t
|
||||||
|
{
|
||||||
|
u32 offset;
|
||||||
|
u32 size;
|
||||||
|
u8 type;
|
||||||
|
u8 flags0;
|
||||||
|
u8 flags1;
|
||||||
|
u8 flags2;
|
||||||
|
u32 rsvd1;
|
||||||
|
char name[0x10];
|
||||||
|
} pkg3_content_t;
|
||||||
|
|
||||||
|
static void _pkg3_update_r2p()
|
||||||
|
{
|
||||||
|
u8 *r2p_payload = emusd_file_read("atmosphere/reboot_payload.bin", NULL);
|
||||||
|
|
||||||
|
is_ipl_updated(r2p_payload, "emusd:atmosphere/reboot_payload.bin", h_cfg.updater2p ? true : false);
|
||||||
|
|
||||||
|
free(r2p_payload);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _pkg3_kip1_skip(char ***pkg3_kip1_skip, u32 *pkg3_kip1_skip_num, char *value)
|
||||||
|
{
|
||||||
|
int len = strlen(value);
|
||||||
|
if (!len || (*pkg3_kip1_skip_num) >= PKG3_KIP_SKIP_MAX)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
// Allocate pointer list memory.
|
||||||
|
if (!(*pkg3_kip1_skip))
|
||||||
|
(*pkg3_kip1_skip) = calloc(PKG3_KIP_SKIP_MAX, sizeof(char *));
|
||||||
|
|
||||||
|
// Set first kip name.
|
||||||
|
(*pkg3_kip1_skip)[(*pkg3_kip1_skip_num)++] = value;
|
||||||
|
|
||||||
|
// Check if more names are set separated by comma.
|
||||||
|
for (char *c = value; *c != 0; c++)
|
||||||
|
{
|
||||||
|
if (*c == ',')
|
||||||
|
{
|
||||||
|
*c = 0; // Null termination.
|
||||||
|
|
||||||
|
// Set next kip name to the list.
|
||||||
|
(*pkg3_kip1_skip)[(*pkg3_kip1_skip_num)++] = c + 1;
|
||||||
|
|
||||||
|
if ((*pkg3_kip1_skip_num) >= PKG3_KIP_SKIP_MAX)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
u32 pkg3_kip1_skip_num = 0;
|
||||||
|
|
||||||
|
bool stock = false;
|
||||||
|
bool experimental = false;
|
||||||
|
|
||||||
|
// Skip if stock and Exosphere and warmboot are not needed.
|
||||||
|
bool pkg1_old = ctxt->pkg1_id->kb <= HOS_KB_VERSION_620; // Should check if t210b01?
|
||||||
|
bool emummc_disabled = !emu_cfg.enabled || h_cfg.emummc_force_disable;
|
||||||
|
|
||||||
|
LIST_FOREACH_ENTRY(ini_kv_t, kv, &ctxt->cfg->kvs, link)
|
||||||
|
{
|
||||||
|
if (!strcmp("stock", kv->key))
|
||||||
|
if (kv->val[0] == '1')
|
||||||
|
stock = true;
|
||||||
|
|
||||||
|
if (!strcmp("pkg3ex", kv->key))
|
||||||
|
if (kv->val[0] == '1')
|
||||||
|
experimental = true;
|
||||||
|
|
||||||
|
if (!strcmp("pkg3kip1skip", kv->key))
|
||||||
|
_pkg3_kip1_skip(&pkg3_kip1_skip, &pkg3_kip1_skip_num, kv->val);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef HOS_MARIKO_STOCK_SECMON
|
||||||
|
if (stock && emummc_disabled && (pkg1_old || h_cfg.t210b01)) {
|
||||||
|
free(path1);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
if (stock && emummc_disabled && pkg1_old) {
|
||||||
|
free(path1);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Try to open PKG3.
|
||||||
|
if (f_open(&fp, path1, FA_READ) != FR_OK) {
|
||||||
|
free(path1);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void *pkg3 = malloc(f_size(&fp));
|
||||||
|
|
||||||
|
// Read first 1024 bytes of the PKG3 file.
|
||||||
|
f_read(&fp, pkg3, 1024, NULL);
|
||||||
|
|
||||||
|
// Get PKG3 Meta header offset.
|
||||||
|
u32 pkg3_meta_addr = *(u32 *)(pkg3 + PKG3_META_OFFSET);
|
||||||
|
pkg3_meta_t *pkg3_meta = (pkg3_meta_t *)(pkg3 + pkg3_meta_addr);
|
||||||
|
|
||||||
|
// Check if valid PKG3 and parse it.
|
||||||
|
if (pkg3_meta->magic == PKG3_MAGIC)
|
||||||
|
{
|
||||||
|
gfx_printf("Atmosphere %d.%d.%d-%08x via PKG3\n"
|
||||||
|
"Max HOS: %d.%d.%d\n"
|
||||||
|
"Unpacking.. ",
|
||||||
|
pkg3_meta->version >> 24, (pkg3_meta->version >> 16) & 0xFF, (pkg3_meta->version >> 8) & 0xFF, pkg3_meta->git_rev,
|
||||||
|
pkg3_meta->hos_ver >> 24, (pkg3_meta->hos_ver >> 16) & 0xFF, (pkg3_meta->hos_ver >> 8) & 0xFF);
|
||||||
|
|
||||||
|
ctxt->patch_krn_proc_id = true;
|
||||||
|
ctxt->pkg3_hosver = pkg3_meta->hos_ver;
|
||||||
|
|
||||||
|
// Parse PKG3 contents.
|
||||||
|
pkg3_content_t *curr_pkg3_cnt = (pkg3_content_t *)(pkg3 + pkg3_meta->cnt_off);
|
||||||
|
void *content;
|
||||||
|
for (u32 i = 0; i < pkg3_meta->cnt_count; i++)
|
||||||
|
{
|
||||||
|
content = (void *)(pkg3 + curr_pkg3_cnt[i].offset);
|
||||||
|
|
||||||
|
// Check if offset is inside limits.
|
||||||
|
if ((curr_pkg3_cnt[i].offset + curr_pkg3_cnt[i].size) > pkg3_meta->size)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// If content is experimental and experimental config is not enabled, skip it.
|
||||||
|
if ((curr_pkg3_cnt[i].flags0 & CNT_FLAG0_EXPERIMENTAL) && !experimental)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Prepare content.
|
||||||
|
switch (curr_pkg3_cnt[i].type)
|
||||||
|
{
|
||||||
|
case CNT_TYPE_KIP:
|
||||||
|
if (stock)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
bool should_skip = false;
|
||||||
|
for (u32 k = 0; k < pkg3_kip1_skip_num; k++)
|
||||||
|
{
|
||||||
|
if (!strcmp(curr_pkg3_cnt[i].name, pkg3_kip1_skip[k]))
|
||||||
|
{
|
||||||
|
gfx_printf("Skipped %s.kip1 from PKG3\n", curr_pkg3_cnt[i].name);
|
||||||
|
should_skip = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (should_skip)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
merge_kip_t *mkip1 = (merge_kip_t *)malloc(sizeof(merge_kip_t));
|
||||||
|
mkip1->kip1 = content;
|
||||||
|
list_append(&ctxt->kip1_list, &mkip1->link);
|
||||||
|
DPRINTF("Loaded %s.kip1 from PKG3 (size %08X)\n", curr_pkg3_cnt[i].name, curr_pkg3_cnt[i].size);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CNT_TYPE_KRN:
|
||||||
|
if (stock)
|
||||||
|
continue;
|
||||||
|
ctxt->kernel_size = curr_pkg3_cnt[i].size;
|
||||||
|
ctxt->kernel = content;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CNT_TYPE_EXO:
|
||||||
|
ctxt->secmon_size = curr_pkg3_cnt[i].size;
|
||||||
|
ctxt->secmon = content;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CNT_TYPE_EXF:
|
||||||
|
ctxt->exofatal_size = curr_pkg3_cnt[i].size;
|
||||||
|
ctxt->exofatal = content;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CNT_TYPE_WBT:
|
||||||
|
if (h_cfg.t210b01)
|
||||||
|
continue;
|
||||||
|
ctxt->warmboot_size = curr_pkg3_cnt[i].size;
|
||||||
|
ctxt->warmboot = content;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load content to launch context.
|
||||||
|
f_lseek(&fp, curr_pkg3_cnt[i].offset);
|
||||||
|
f_read(&fp, content, curr_pkg3_cnt[i].size, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
gfx_printf("Done!\n");
|
||||||
|
f_close(&fp);
|
||||||
|
|
||||||
|
ctxt->pkg3 = pkg3;
|
||||||
|
|
||||||
|
// Update r2p if needed.
|
||||||
|
_pkg3_update_r2p();
|
||||||
|
|
||||||
|
free(pkg3_kip1_skip);
|
||||||
|
free(path1);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Failed. Close and free all.
|
||||||
|
f_close(&fp);
|
||||||
|
|
||||||
|
free(pkg3_kip1_skip);
|
||||||
|
free(pkg3);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -14,11 +14,11 @@
|
|||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _FSS_H_
|
#ifndef _PKG3_H_
|
||||||
#define _FSS_H_
|
#define _PKG3_H_
|
||||||
|
|
||||||
#include "hos.h"
|
#include "hos.h"
|
||||||
|
|
||||||
int parse_fss(launch_ctxt_t *ctxt, const char *path);
|
int parse_pkg3(launch_ctxt_t *ctxt, const char *path);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -24,14 +24,17 @@
|
|||||||
#include "../config.h"
|
#include "../config.h"
|
||||||
#include <libs/fatfs/ff.h>
|
#include <libs/fatfs/ff.h>
|
||||||
#include "../storage/emummc.h"
|
#include "../storage/emummc.h"
|
||||||
|
#include "../storage/emusd.h"
|
||||||
|
|
||||||
extern hekate_config h_cfg;
|
extern hekate_config h_cfg;
|
||||||
|
|
||||||
enum emuMMC_Type
|
enum emuMMC_Type
|
||||||
{
|
{
|
||||||
emuMMC_None = 0,
|
EmummcType_None = 0,
|
||||||
emuMMC_Partition,
|
EmummcType_Partition_Sd = 1,
|
||||||
emuMMC_File,
|
EmummcType_File_Sd = 2,
|
||||||
|
EmummcType_Partition_Emmc = 3,
|
||||||
|
EmummcType_File_Emmc = 4,
|
||||||
emuMMC_MAX
|
emuMMC_MAX
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -66,6 +69,22 @@ typedef struct
|
|||||||
emummc_file_config_t file_cfg;
|
emummc_file_config_t file_cfg;
|
||||||
};
|
};
|
||||||
char nintendo_path[EMUMMC_FILE_PATH_MAX];
|
char nintendo_path[EMUMMC_FILE_PATH_MAX];
|
||||||
|
} emummc_emmc_config_t;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
emummc_base_config_t base_cfg;
|
||||||
|
union
|
||||||
|
{
|
||||||
|
emummc_partition_config_t partition_cfg;
|
||||||
|
emummc_file_config_t file_cfg;
|
||||||
|
};
|
||||||
|
} emummc_sd_config_t;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
emummc_emmc_config_t emmc_cfg;
|
||||||
|
emummc_sd_config_t sd_cfg;
|
||||||
} exo_emummc_config_t;
|
} exo_emummc_config_t;
|
||||||
|
|
||||||
typedef struct _exo_cfg_t
|
typedef struct _exo_cfg_t
|
||||||
@@ -77,7 +96,8 @@ typedef struct _exo_cfg_t
|
|||||||
u8 uart_port;
|
u8 uart_port;
|
||||||
u8 uart_invert;
|
u8 uart_invert;
|
||||||
u32 uart_baudrate;
|
u32 uart_baudrate;
|
||||||
u32 rsvd1[2];
|
u8 memory_mode_auto;
|
||||||
|
u8 rsvd1[7];
|
||||||
exo_emummc_config_t emummc_cfg;
|
exo_emummc_config_t emummc_cfg;
|
||||||
} exo_cfg_t;
|
} exo_cfg_t;
|
||||||
|
|
||||||
@@ -199,7 +219,7 @@ void config_exosphere(launch_ctxt_t *ctxt, u32 warmboot_base)
|
|||||||
case 12:
|
case 12:
|
||||||
exo_fw_no = EXO_FW_VER(9, 1);
|
exo_fw_no = EXO_FW_VER(9, 1);
|
||||||
break;
|
break;
|
||||||
case 13 ... 22: //!TODO: Update on API changes. 22: 19.0.0.
|
case 13 ... 23: //!TODO: Update on API changes. 23: 20.0.0.
|
||||||
exo_fw_no = EXO_FW_VER(exo_fw_no - 3, ctxt->exo_ctx.hos_revision);
|
exo_fw_no = EXO_FW_VER(exo_fw_no - 3, ctxt->exo_ctx.hos_revision);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -208,7 +228,7 @@ void config_exosphere(launch_ctxt_t *ctxt, u32 warmboot_base)
|
|||||||
if (!ctxt->stock)
|
if (!ctxt->stock)
|
||||||
{
|
{
|
||||||
LIST_INIT(ini_exo_sections);
|
LIST_INIT(ini_exo_sections);
|
||||||
if (ini_parse(&ini_exo_sections, "exosphere.ini", false))
|
if (ini_parse(&ini_exo_sections, "emusd:exosphere.ini", false))
|
||||||
{
|
{
|
||||||
LIST_FOREACH_ENTRY(ini_sec_t, ini_sec, &ini_exo_sections, link)
|
LIST_FOREACH_ENTRY(ini_sec_t, ini_sec, &ini_exo_sections, link)
|
||||||
{
|
{
|
||||||
@@ -216,6 +236,7 @@ void config_exosphere(launch_ctxt_t *ctxt, u32 warmboot_base)
|
|||||||
if (!(ini_sec->type == INI_CHOICE) || strcmp(ini_sec->name, "exosphere"))
|
if (!(ini_sec->type == INI_CHOICE) || strcmp(ini_sec->name, "exosphere"))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
|
||||||
LIST_FOREACH_ENTRY(ini_kv_t, kv, &ini_sec->kvs, link)
|
LIST_FOREACH_ENTRY(ini_kv_t, kv, &ini_sec->kvs, link)
|
||||||
{
|
{
|
||||||
if (!strcmp("debugmode_user", kv->key))
|
if (!strcmp("debugmode_user", kv->key))
|
||||||
@@ -226,12 +247,14 @@ void config_exosphere(launch_ctxt_t *ctxt, u32 warmboot_base)
|
|||||||
exo_cfg->uart_invert = atoi(kv->val);
|
exo_cfg->uart_invert = atoi(kv->val);
|
||||||
else if (!strcmp("log_baud_rate", kv->key))
|
else if (!strcmp("log_baud_rate", kv->key))
|
||||||
exo_cfg->uart_baudrate = atoi(kv->val);
|
exo_cfg->uart_baudrate = atoi(kv->val);
|
||||||
|
else if (!strcmp("memory_mode_auto", kv->key)) {
|
||||||
|
exo_cfg->memory_mode_auto = atoi(kv->val);
|
||||||
|
}
|
||||||
else if (emu_cfg.enabled && !h_cfg.emummc_force_disable)
|
else if (emu_cfg.enabled && !h_cfg.emummc_force_disable)
|
||||||
{
|
{
|
||||||
if (!strcmp("blank_prodinfo_emummc", kv->key))
|
if (!strcmp("blank_prodinfo_emummc", kv->key))
|
||||||
cal0_blanking = atoi(kv->val);
|
cal0_blanking = atoi(kv->val);
|
||||||
}
|
} else
|
||||||
else
|
|
||||||
{
|
{
|
||||||
if (!strcmp("blank_prodinfo_sysmmc", kv->key))
|
if (!strcmp("blank_prodinfo_sysmmc", kv->key))
|
||||||
cal0_blanking = atoi(kv->val);
|
cal0_blanking = atoi(kv->val);
|
||||||
@@ -241,36 +264,36 @@ void config_exosphere(launch_ctxt_t *ctxt, u32 warmboot_base)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Parse usb mtim settings. Avoid parsing if it's overridden.
|
// Parse usb mtim settings. Avoid parsing if it's overridden.
|
||||||
if (!ctxt->exo_ctx.usb3_force)
|
if (!ctxt->exo_ctx.usb3_force)
|
||||||
|
{
|
||||||
|
LIST_INIT(ini_sys_sections);
|
||||||
|
if (ini_parse(&ini_sys_sections, "emusd:atmosphere/config/system_settings.ini", false))
|
||||||
{
|
{
|
||||||
LIST_INIT(ini_sys_sections);
|
LIST_FOREACH_ENTRY(ini_sec_t, ini_sec, &ini_sys_sections, link)
|
||||||
if (ini_parse(&ini_sys_sections, "atmosphere/config/system_settings.ini", false))
|
|
||||||
{
|
{
|
||||||
LIST_FOREACH_ENTRY(ini_sec_t, ini_sec, &ini_sys_sections, link)
|
// Only parse usb section.
|
||||||
{
|
if (!(ini_sec->type == INI_CHOICE) || strcmp(ini_sec->name, "usb"))
|
||||||
// Only parse usb section.
|
continue;
|
||||||
if (!(ini_sec->type == INI_CHOICE) || strcmp(ini_sec->name, "usb"))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
LIST_FOREACH_ENTRY(ini_kv_t, kv, &ini_sec->kvs, link)
|
LIST_FOREACH_ENTRY(ini_kv_t, kv, &ini_sec->kvs, link)
|
||||||
|
{
|
||||||
|
if (!strcmp("usb30_force_enabled", kv->key))
|
||||||
{
|
{
|
||||||
if (!strcmp("usb30_force_enabled", kv->key))
|
usb3_force = !strcmp("u8!0x1", kv->val);
|
||||||
{
|
break; // Only parse usb30_force_enabled key.
|
||||||
usb3_force = !strcmp("u8!0x1", kv->val);
|
|
||||||
break; // Only parse usb30_force_enabled key.
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// To avoid problems, make private debug mode always on if not semi-stock.
|
// Private debug mode always on for CFW mode.
|
||||||
if (!ctxt->stock || (emu_cfg.enabled && !h_cfg.emummc_force_disable))
|
if (!ctxt->stock)
|
||||||
exo_flags |= EXO_FLAG_DBG_PRIV;
|
exo_flags |= EXO_FLAG_DBG_PRIV;
|
||||||
|
|
||||||
// Enable user debug.
|
// Enable user debug.
|
||||||
@@ -316,22 +339,72 @@ void config_exosphere(launch_ctxt_t *ctxt, u32 warmboot_base)
|
|||||||
pkg1_warmboot_rsa_mod(warmboot_base);
|
pkg1_warmboot_rsa_mod(warmboot_base);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// By default, disable emuMMC
|
||||||
|
exo_cfg->emummc_cfg.emmc_cfg.base_cfg.magic = EMUMMC_MAGIC;
|
||||||
|
exo_cfg->emummc_cfg.emmc_cfg.base_cfg.type = EmummcType_None;
|
||||||
if (emu_cfg.enabled && !h_cfg.emummc_force_disable)
|
if (emu_cfg.enabled && !h_cfg.emummc_force_disable)
|
||||||
{
|
{
|
||||||
exo_cfg->emummc_cfg.base_cfg.magic = EMUMMC_MAGIC;
|
exo_cfg->emummc_cfg.emmc_cfg.base_cfg.fs_ver = emu_cfg.fs_ver;
|
||||||
exo_cfg->emummc_cfg.base_cfg.type = emu_cfg.sector ? emuMMC_Partition : emuMMC_File;
|
exo_cfg->emummc_cfg.sd_cfg.base_cfg.fs_ver = emu_sd_cfg.fs_ver;
|
||||||
exo_cfg->emummc_cfg.base_cfg.fs_ver = emu_cfg.fs_ver;
|
|
||||||
exo_cfg->emummc_cfg.base_cfg.id = emu_cfg.id;
|
exo_cfg->emummc_cfg.emmc_cfg.base_cfg.id = emu_cfg.id;
|
||||||
|
if (emu_cfg.enabled == 4 && emu_cfg.sector) {
|
||||||
|
// emmc partition based
|
||||||
|
exo_cfg->emummc_cfg.emmc_cfg.base_cfg.type = EmummcType_Partition_Emmc;
|
||||||
|
} else if (emu_cfg.enabled == 4 && !emu_cfg.sector) {
|
||||||
|
// emmc file based
|
||||||
|
exo_cfg->emummc_cfg.emmc_cfg.base_cfg.type = EmummcType_File_Emmc;
|
||||||
|
} else if (emu_cfg.enabled == 1 && emu_cfg.sector) {
|
||||||
|
// sd partition based
|
||||||
|
exo_cfg->emummc_cfg.emmc_cfg.base_cfg.type = EmummcType_Partition_Sd;
|
||||||
|
} else if (emu_cfg.enabled == 1 && !emu_cfg.sector) {
|
||||||
|
// sd file based
|
||||||
|
exo_cfg->emummc_cfg.emmc_cfg.base_cfg.type = EmummcType_File_Sd;
|
||||||
|
} else {
|
||||||
|
// disabled
|
||||||
|
exo_cfg->emummc_cfg.emmc_cfg.base_cfg.type = EmummcType_None;
|
||||||
|
}
|
||||||
|
|
||||||
if (emu_cfg.sector)
|
if (emu_cfg.sector)
|
||||||
exo_cfg->emummc_cfg.partition_cfg.start_sector = emu_cfg.sector;
|
exo_cfg->emummc_cfg.emmc_cfg.partition_cfg.start_sector = emu_cfg.sector;
|
||||||
else
|
else
|
||||||
strcpy((char *)exo_cfg->emummc_cfg.file_cfg.path, emu_cfg.path);
|
strcpy((char *)exo_cfg->emummc_cfg.emmc_cfg.file_cfg.path, emu_cfg.path);
|
||||||
|
|
||||||
if (!ctxt->stock && emu_cfg.nintendo_path && emu_cfg.nintendo_path[0])
|
if (!ctxt->stock && emu_cfg.nintendo_path && emu_cfg.nintendo_path[0])
|
||||||
strcpy((char *)exo_cfg->emummc_cfg.nintendo_path, emu_cfg.nintendo_path);
|
strcpy((char *)exo_cfg->emummc_cfg.emmc_cfg.nintendo_path, emu_cfg.nintendo_path);
|
||||||
else
|
else
|
||||||
strcpy((char *)exo_cfg->emummc_cfg.nintendo_path, "Nintendo");
|
strcpy((char *)exo_cfg->emummc_cfg.emmc_cfg.nintendo_path, "Nintendo");
|
||||||
|
}
|
||||||
|
|
||||||
|
exo_cfg->emummc_cfg.sd_cfg.base_cfg.magic = EMUMMC_MAGIC;
|
||||||
|
exo_cfg->emummc_cfg.sd_cfg.base_cfg.type = EmummcType_None;
|
||||||
|
if (emu_sd_cfg.enabled)
|
||||||
|
{
|
||||||
|
exo_cfg->emummc_cfg.sd_cfg.base_cfg.fs_ver = emu_sd_cfg.fs_ver;
|
||||||
|
exo_cfg->emummc_cfg.emmc_cfg.base_cfg.fs_ver = emu_sd_cfg.fs_ver;
|
||||||
|
|
||||||
|
exo_cfg->emummc_cfg.sd_cfg.base_cfg.id = emu_sd_cfg.id;
|
||||||
|
if (emu_sd_cfg.enabled == 4 && emu_sd_cfg.sector) {
|
||||||
|
// emmc partition based
|
||||||
|
exo_cfg->emummc_cfg.sd_cfg.base_cfg.type = EmummcType_Partition_Emmc;
|
||||||
|
} else if (emu_sd_cfg.enabled == 4 && !emu_sd_cfg.sector) {
|
||||||
|
// emmc file based
|
||||||
|
exo_cfg->emummc_cfg.sd_cfg.base_cfg.type = EmummcType_File_Emmc;
|
||||||
|
} else if (emu_sd_cfg.enabled == 1 && emu_sd_cfg.sector) {
|
||||||
|
// sd partition based
|
||||||
|
exo_cfg->emummc_cfg.sd_cfg.base_cfg.type = EmummcType_Partition_Sd;
|
||||||
|
} else if (emu_sd_cfg.enabled == 1 && !emu_sd_cfg.sector) {
|
||||||
|
// sd file based
|
||||||
|
exo_cfg->emummc_cfg.sd_cfg.base_cfg.type = EmummcType_File_Sd;
|
||||||
|
} else {
|
||||||
|
// disabled
|
||||||
|
exo_cfg->emummc_cfg.sd_cfg.base_cfg.type = EmummcType_None;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (emu_sd_cfg.sector)
|
||||||
|
exo_cfg->emummc_cfg.sd_cfg.partition_cfg.start_sector = emu_sd_cfg.sector;
|
||||||
|
else
|
||||||
|
strcpy((char *)exo_cfg->emummc_cfg.sd_cfg.file_cfg.path, emu_sd_cfg.path);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy over exosphere fatal for Mariko.
|
// Copy over exosphere fatal for Mariko.
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* L4T Loader for Tegra X1
|
* L4T Loader for Tegra X1
|
||||||
*
|
*
|
||||||
* Copyright (c) 2020-2024 CTCaer
|
* Copyright (c) 2020-2025 CTCaer
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
* under the terms and conditions of the GNU General Public License,
|
* under the terms and conditions of the GNU General Public License,
|
||||||
@@ -273,6 +273,8 @@ typedef struct _l4t_ctxt_t
|
|||||||
int ram_oc_opt;
|
int ram_oc_opt;
|
||||||
|
|
||||||
u32 serial_port;
|
u32 serial_port;
|
||||||
|
u32 sld_type;
|
||||||
|
|
||||||
u32 sc7entry_size;
|
u32 sc7entry_size;
|
||||||
|
|
||||||
emc_table_t *mtc_table;
|
emc_table_t *mtc_table;
|
||||||
@@ -289,18 +291,22 @@ typedef struct _l4t_ctxt_t
|
|||||||
#define DRAM_VDDQ_OC_MAX_VOLTAGE 650
|
#define DRAM_VDDQ_OC_MAX_VOLTAGE 650
|
||||||
#define DRAM_T210B01_TBL_MAX_FREQ 1600000
|
#define DRAM_T210B01_TBL_MAX_FREQ 1600000
|
||||||
|
|
||||||
//! TODO: Update on dram config changes.
|
#define NA 0 // Default to 0 for incorrect dram ids.
|
||||||
|
|
||||||
|
//!TODO: Update on dram config changes.
|
||||||
static const u8 mtc_table_idx_t210b01[] = {
|
static const u8 mtc_table_idx_t210b01[] = {
|
||||||
/* 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 */
|
/* 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 */
|
||||||
-1, -1, -1, 7, -1, 7, 7, -1, 0, 1, 2, 3, 0, 1, 2, 3, -1, 4, 5, 4, 8, 8, 8, 5, 4, 6, 6, 6, 5, 9, 9, 9, 10, 10, 10
|
NA, NA, NA, 7, NA, 7, 7, NA, 0, 1, 2, 3, 0, 1, 2, 3, NA, 4, 5, 4, 8, 8, 8, 5, 4, 6, 6, 6, 5, 9, 9, 9, 10, 10, 10
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#undef NA
|
||||||
|
|
||||||
static const l4t_fw_t l4t_fw[] = {
|
static const l4t_fw_t l4t_fw[] = {
|
||||||
{ TZDRAM_BASE, "bl31.bin" },
|
{ TZDRAM_BASE, "bl31.bin" },
|
||||||
{ BL33_LOAD_BASE, "bl33.bin" },
|
{ BL33_LOAD_BASE, "bl33.bin" },
|
||||||
{ SC7ENTRY_BASE, "sc7entry.bin" },
|
{ SC7ENTRY_BASE, "sc7entry.bin" },
|
||||||
{ SC7EXIT_BASE, "sc7exit.bin" },
|
{ SC7EXIT_BASE, "sc7exit.bin" },
|
||||||
{ SC7EXIT_B01_BASE, "sc7exit_b01.bin" },
|
{ SC7EXIT_B01_BASE, "sc7exit_b01.bin" }, //!TODO: Update on fuse burns.
|
||||||
{ BPMPFW_BASE, "bpmpfw.bin" },
|
{ BPMPFW_BASE, "bpmpfw.bin" },
|
||||||
{ BPMPFW_B01_BASE, "bpmpfw_b01.bin" },
|
{ BPMPFW_B01_BASE, "bpmpfw_b01.bin" },
|
||||||
{ BPMPFW_B01_MTC_TABLE_BASE, "mtc_tbl_b01.bin" },
|
{ BPMPFW_B01_MTC_TABLE_BASE, "mtc_tbl_b01.bin" },
|
||||||
@@ -381,7 +387,7 @@ static void _l4t_sdram_lp0_save_params(bool t210b01)
|
|||||||
s(MC_VIDEO_PROTECT_REG_CTRL, 1:0, secure_scratch14, 31:30);
|
s(MC_VIDEO_PROTECT_REG_CTRL, 1:0, secure_scratch14, 31:30);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TZD.
|
// TZDRAM.
|
||||||
s(MC_SEC_CARVEOUT_BOM, 31:20, secure_scratch53, 23:12);
|
s(MC_SEC_CARVEOUT_BOM, 31:20, secure_scratch53, 23:12);
|
||||||
s(MC_SEC_CARVEOUT_SIZE_MB, 11:0, secure_scratch54, 11:0);
|
s(MC_SEC_CARVEOUT_SIZE_MB, 11:0, secure_scratch54, 11:0);
|
||||||
if (!t210b01) {
|
if (!t210b01) {
|
||||||
@@ -523,11 +529,6 @@ static void _l4t_mc_config_carveout(bool t210b01)
|
|||||||
MC(MC_SECURITY_CARVEOUT1_CLIENT_ACCESS2) = SEC_CARVEOUT_CA2_R_TSEC | SEC_CARVEOUT_CA2_W_TSEC;
|
MC(MC_SECURITY_CARVEOUT1_CLIENT_ACCESS2) = SEC_CARVEOUT_CA2_R_TSEC | SEC_CARVEOUT_CA2_W_TSEC;
|
||||||
MC(MC_SECURITY_CARVEOUT1_CLIENT_ACCESS3) = SEC_CARVEOUT_CA3_R_NVDEC | SEC_CARVEOUT_CA3_W_NVDEC;
|
MC(MC_SECURITY_CARVEOUT1_CLIENT_ACCESS3) = SEC_CARVEOUT_CA3_R_NVDEC | SEC_CARVEOUT_CA3_W_NVDEC;
|
||||||
MC(MC_SECURITY_CARVEOUT1_CLIENT_ACCESS4) = 0;
|
MC(MC_SECURITY_CARVEOUT1_CLIENT_ACCESS4) = 0;
|
||||||
MC(MC_SECURITY_CARVEOUT1_CLIENT_FORCE_INTERNAL_ACCESS0) = 0;
|
|
||||||
MC(MC_SECURITY_CARVEOUT1_CLIENT_FORCE_INTERNAL_ACCESS1) = 0;
|
|
||||||
MC(MC_SECURITY_CARVEOUT1_CLIENT_FORCE_INTERNAL_ACCESS2) = 0;
|
|
||||||
MC(MC_SECURITY_CARVEOUT1_CLIENT_FORCE_INTERNAL_ACCESS3) = 0;
|
|
||||||
MC(MC_SECURITY_CARVEOUT1_CLIENT_FORCE_INTERNAL_ACCESS4) = 0;
|
|
||||||
MC(MC_SECURITY_CARVEOUT1_CFG0) = SEC_CARVEOUT_CFG_LOCKED |
|
MC(MC_SECURITY_CARVEOUT1_CFG0) = SEC_CARVEOUT_CFG_LOCKED |
|
||||||
SEC_CARVEOUT_CFG_UNTRANSLATED_ONLY |
|
SEC_CARVEOUT_CFG_UNTRANSLATED_ONLY |
|
||||||
SEC_CARVEOUT_CFG_RD_SEC |
|
SEC_CARVEOUT_CFG_RD_SEC |
|
||||||
@@ -559,11 +560,6 @@ static void _l4t_mc_config_carveout(bool t210b01)
|
|||||||
MC(MC_SECURITY_CARVEOUT1_CLIENT_ACCESS2) = 0;
|
MC(MC_SECURITY_CARVEOUT1_CLIENT_ACCESS2) = 0;
|
||||||
MC(MC_SECURITY_CARVEOUT1_CLIENT_ACCESS3) = 0;
|
MC(MC_SECURITY_CARVEOUT1_CLIENT_ACCESS3) = 0;
|
||||||
MC(MC_SECURITY_CARVEOUT1_CLIENT_ACCESS4) = 0;
|
MC(MC_SECURITY_CARVEOUT1_CLIENT_ACCESS4) = 0;
|
||||||
MC(MC_SECURITY_CARVEOUT1_CLIENT_FORCE_INTERNAL_ACCESS0) = 0;
|
|
||||||
MC(MC_SECURITY_CARVEOUT1_CLIENT_FORCE_INTERNAL_ACCESS1) = 0;
|
|
||||||
MC(MC_SECURITY_CARVEOUT1_CLIENT_FORCE_INTERNAL_ACCESS2) = 0;
|
|
||||||
MC(MC_SECURITY_CARVEOUT1_CLIENT_FORCE_INTERNAL_ACCESS3) = 0;
|
|
||||||
MC(MC_SECURITY_CARVEOUT1_CLIENT_FORCE_INTERNAL_ACCESS4) = 0;
|
|
||||||
MC(MC_SECURITY_CARVEOUT1_CFG0) = SEC_CARVEOUT_CFG_RD_NS |
|
MC(MC_SECURITY_CARVEOUT1_CFG0) = SEC_CARVEOUT_CFG_RD_NS |
|
||||||
SEC_CARVEOUT_CFG_RD_SEC |
|
SEC_CARVEOUT_CFG_RD_SEC |
|
||||||
SEC_CARVEOUT_CFG_WR_NS |
|
SEC_CARVEOUT_CFG_WR_NS |
|
||||||
@@ -600,11 +596,6 @@ static void _l4t_mc_config_carveout(bool t210b01)
|
|||||||
MC(MC_SECURITY_CARVEOUT2_CLIENT_ACCESS2) = SEC_CARVEOUT_CA2_R_GPU | SEC_CARVEOUT_CA2_W_GPU | SEC_CARVEOUT_CA2_R_TSEC;
|
MC(MC_SECURITY_CARVEOUT2_CLIENT_ACCESS2) = SEC_CARVEOUT_CA2_R_GPU | SEC_CARVEOUT_CA2_W_GPU | SEC_CARVEOUT_CA2_R_TSEC;
|
||||||
MC(MC_SECURITY_CARVEOUT2_CLIENT_ACCESS3) = 0;
|
MC(MC_SECURITY_CARVEOUT2_CLIENT_ACCESS3) = 0;
|
||||||
MC(MC_SECURITY_CARVEOUT2_CLIENT_ACCESS4) = SEC_CARVEOUT_CA4_R_GPU2 | SEC_CARVEOUT_CA4_W_GPU2;
|
MC(MC_SECURITY_CARVEOUT2_CLIENT_ACCESS4) = SEC_CARVEOUT_CA4_R_GPU2 | SEC_CARVEOUT_CA4_W_GPU2;
|
||||||
MC(MC_SECURITY_CARVEOUT2_CLIENT_FORCE_INTERNAL_ACCESS0) = 0;
|
|
||||||
MC(MC_SECURITY_CARVEOUT2_CLIENT_FORCE_INTERNAL_ACCESS1) = 0;
|
|
||||||
MC(MC_SECURITY_CARVEOUT2_CLIENT_FORCE_INTERNAL_ACCESS2) = 0;
|
|
||||||
MC(MC_SECURITY_CARVEOUT2_CLIENT_FORCE_INTERNAL_ACCESS3) = 0;
|
|
||||||
MC(MC_SECURITY_CARVEOUT2_CLIENT_FORCE_INTERNAL_ACCESS4) = 0;
|
|
||||||
MC(MC_SECURITY_CARVEOUT2_CFG0) = SEC_CARVEOUT_CFG_LOCKED |
|
MC(MC_SECURITY_CARVEOUT2_CFG0) = SEC_CARVEOUT_CFG_LOCKED |
|
||||||
SEC_CARVEOUT_CFG_UNTRANSLATED_ONLY |
|
SEC_CARVEOUT_CFG_UNTRANSLATED_ONLY |
|
||||||
SEC_CARVEOUT_CFG_RD_NS |
|
SEC_CARVEOUT_CFG_RD_NS |
|
||||||
@@ -633,11 +624,6 @@ static void _l4t_mc_config_carveout(bool t210b01)
|
|||||||
MC(MC_SECURITY_CARVEOUT3_CLIENT_ACCESS2) = 0; // HOS: SEC_CARVEOUT_CA2_R_GPU | SEC_CARVEOUT_CA2_W_GPU
|
MC(MC_SECURITY_CARVEOUT3_CLIENT_ACCESS2) = 0; // HOS: SEC_CARVEOUT_CA2_R_GPU | SEC_CARVEOUT_CA2_W_GPU
|
||||||
MC(MC_SECURITY_CARVEOUT3_CLIENT_ACCESS3) = 0;
|
MC(MC_SECURITY_CARVEOUT3_CLIENT_ACCESS3) = 0;
|
||||||
MC(MC_SECURITY_CARVEOUT3_CLIENT_ACCESS4) = 0; // HOS: SEC_CARVEOUT_CA4_R_GPU2 | SEC_CARVEOUT_CA4_W_GPU2
|
MC(MC_SECURITY_CARVEOUT3_CLIENT_ACCESS4) = 0; // HOS: SEC_CARVEOUT_CA4_R_GPU2 | SEC_CARVEOUT_CA4_W_GPU2
|
||||||
MC(MC_SECURITY_CARVEOUT3_CLIENT_FORCE_INTERNAL_ACCESS0) = 0;
|
|
||||||
MC(MC_SECURITY_CARVEOUT3_CLIENT_FORCE_INTERNAL_ACCESS1) = 0;
|
|
||||||
MC(MC_SECURITY_CARVEOUT3_CLIENT_FORCE_INTERNAL_ACCESS2) = 0;
|
|
||||||
MC(MC_SECURITY_CARVEOUT3_CLIENT_FORCE_INTERNAL_ACCESS3) = 0;
|
|
||||||
MC(MC_SECURITY_CARVEOUT3_CLIENT_FORCE_INTERNAL_ACCESS4) = 0;
|
|
||||||
MC(MC_SECURITY_CARVEOUT3_CFG0) = SEC_CARVEOUT_CFG_LOCKED |
|
MC(MC_SECURITY_CARVEOUT3_CFG0) = SEC_CARVEOUT_CFG_LOCKED |
|
||||||
SEC_CARVEOUT_CFG_UNTRANSLATED_ONLY |
|
SEC_CARVEOUT_CFG_UNTRANSLATED_ONLY |
|
||||||
SEC_CARVEOUT_CFG_RD_NS |
|
SEC_CARVEOUT_CFG_RD_NS |
|
||||||
@@ -867,6 +853,9 @@ static void _l4t_set_config(l4t_ctxt_t *ctxt, const ini_sec_t *ini_sec, int entr
|
|||||||
bl33_env[0] = '\0';
|
bl33_env[0] = '\0';
|
||||||
char val[4] = {0};
|
char val[4] = {0};
|
||||||
|
|
||||||
|
// Set default SLD type.
|
||||||
|
ctxt->sld_type = BL_MAGIC_L4TLDR_SLD;
|
||||||
|
|
||||||
// Parse ini section and prepare BL33 env.
|
// Parse ini section and prepare BL33 env.
|
||||||
LIST_FOREACH_ENTRY(ini_kv_t, kv, &ini_sec->kvs, link)
|
LIST_FOREACH_ENTRY(ini_kv_t, kv, &ini_sec->kvs, link)
|
||||||
{
|
{
|
||||||
@@ -897,9 +886,11 @@ static void _l4t_set_config(l4t_ctxt_t *ctxt, const ini_sec_t *ini_sec, int entr
|
|||||||
ctxt->ram_oc_vddq = 0;
|
ctxt->ram_oc_vddq = 0;
|
||||||
}
|
}
|
||||||
else if (!strcmp("ram_oc_opt", kv->key))
|
else if (!strcmp("ram_oc_opt", kv->key))
|
||||||
ctxt->ram_oc_opt = atoi(kv->val);
|
ctxt->ram_oc_opt = atoi(kv->val);
|
||||||
else if (!strcmp("uart_port", kv->key))
|
else if (!strcmp("uart_port", kv->key))
|
||||||
ctxt->serial_port = atoi(kv->val);
|
ctxt->serial_port = atoi(kv->val);
|
||||||
|
else if (!strcmp("sld_type", kv->key))
|
||||||
|
ctxt->sld_type = strtol(kv->val, NULL, 16);
|
||||||
|
|
||||||
// Set key/val to BL33 env.
|
// Set key/val to BL33 env.
|
||||||
_l4t_bl33_cfg_set_key(bl33_env, kv->key, kv->val);
|
_l4t_bl33_cfg_set_key(bl33_env, kv->key, kv->val);
|
||||||
@@ -1027,6 +1018,8 @@ void launch_l4t(const ini_sec_t *ini_sec, int entry_idx, int is_list, bool t210b
|
|||||||
|
|
||||||
// Done loading bootloaders/firmware.
|
// Done loading bootloaders/firmware.
|
||||||
boot_storage_end();
|
boot_storage_end();
|
||||||
|
sd_end();
|
||||||
|
emmc_end();
|
||||||
|
|
||||||
// We don't need AHB aperture open.
|
// We don't need AHB aperture open.
|
||||||
mc_disable_ahb_redirect();
|
mc_disable_ahb_redirect();
|
||||||
@@ -1166,7 +1159,7 @@ void launch_l4t(const ini_sec_t *ini_sec, int entry_idx, int is_list, bool t210b
|
|||||||
_l4t_mc_config_carveout(t210b01);
|
_l4t_mc_config_carveout(t210b01);
|
||||||
|
|
||||||
// Deinit any unneeded HW.
|
// Deinit any unneeded HW.
|
||||||
hw_deinit(false, BL_MAGIC_L4TLDR_SLD);
|
hw_deinit(false, ctxt->sld_type);
|
||||||
|
|
||||||
// Do late hardware config.
|
// Do late hardware config.
|
||||||
_l4t_late_hw_config(t210b01);
|
_l4t_late_hw_config(t210b01);
|
||||||
|
|||||||
@@ -7,9 +7,9 @@
|
|||||||
/* storage control modules to the FatFs module with a defined API. */
|
/* storage control modules to the FatFs module with a defined API. */
|
||||||
/*-----------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#include "../../storage/emusd.h"
|
||||||
#include <storage/sd.h>
|
#include <storage/sd.h>
|
||||||
#include <storage/sdmmc.h>
|
#include <storage/sdmmc.h>
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include <bdk.h>
|
#include <bdk.h>
|
||||||
|
|
||||||
@@ -28,6 +28,8 @@ static bool ensure_partition(BYTE pdrv){
|
|||||||
case DRIVE_EMMC:
|
case DRIVE_EMMC:
|
||||||
part = EMMC_GPP;
|
part = EMMC_GPP;
|
||||||
break;
|
break;
|
||||||
|
case DRIVE_EMUSD:
|
||||||
|
return true;
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -86,6 +88,9 @@ DRESULT disk_read (
|
|||||||
storage = &emmc_storage;
|
storage = &emmc_storage;
|
||||||
actual_sector = sector + (0x100000 / 512);
|
actual_sector = sector + (0x100000 / 512);
|
||||||
break;
|
break;
|
||||||
|
case DRIVE_EMUSD:
|
||||||
|
return emusd_storage_read(sector, count, buff) ? RES_OK : RES_ERROR;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
return RES_ERROR;
|
return RES_ERROR;
|
||||||
|
|
||||||
@@ -122,6 +127,8 @@ DRESULT disk_write (
|
|||||||
storage = &emmc_storage;
|
storage = &emmc_storage;
|
||||||
actual_sector = sector + (0x100000 / 512);
|
actual_sector = sector + (0x100000 / 512);
|
||||||
break;
|
break;
|
||||||
|
case DRIVE_EMUSD:
|
||||||
|
return emusd_storage_write(sector, count, (void*)buff) ? RES_OK : RES_ERROR;
|
||||||
default:
|
default:
|
||||||
return RES_ERROR;
|
return RES_ERROR;
|
||||||
|
|
||||||
|
|||||||
@@ -179,12 +179,12 @@
|
|||||||
/ Drive/Volume Configurations
|
/ Drive/Volume Configurations
|
||||||
/---------------------------------------------------------------------------*/
|
/---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
#define FF_VOLUMES 4
|
#define FF_VOLUMES 5
|
||||||
/* Number of volumes (logical drives) to be used. (1-10) */
|
/* Number of volumes (logical drives) to be used. (1-10) */
|
||||||
|
|
||||||
|
|
||||||
#define FF_STR_VOLUME_ID 1
|
#define FF_STR_VOLUME_ID 1
|
||||||
#define FF_VOLUME_STRS "sd", "boot1", "boot1_1mb", "emmc"
|
#define FF_VOLUME_STRS "sd", "boot1", "boot1_1mb", "emmc", "emusd"
|
||||||
/* FF_STR_VOLUME_ID switches support for volume ID in arbitrary strings.
|
/* FF_STR_VOLUME_ID switches support for volume ID in arbitrary strings.
|
||||||
/ When FF_STR_VOLUME_ID is set to 1 or 2, arbitrary strings can be used as drive
|
/ When FF_STR_VOLUME_ID is set to 1 or 2, arbitrary strings can be used as drive
|
||||||
/ number in the path name. FF_VOLUME_STRS defines the volume ID strings for each
|
/ number in the path name. FF_VOLUME_STRS defines the volume ID strings for each
|
||||||
@@ -256,7 +256,7 @@
|
|||||||
#define FF_FS_NORTC 1
|
#define FF_FS_NORTC 1
|
||||||
#define FF_NORTC_MON 1
|
#define FF_NORTC_MON 1
|
||||||
#define FF_NORTC_MDAY 1
|
#define FF_NORTC_MDAY 1
|
||||||
#define FF_NORTC_YEAR 2024
|
#define FF_NORTC_YEAR 2025
|
||||||
/* The option FF_FS_NORTC switches timestamp function. If the system does not have
|
/* The option FF_FS_NORTC switches timestamp function. If the system does not have
|
||||||
/ any RTC function or valid timestamp is not needed, set FF_FS_NORTC = 1 to disable
|
/ any RTC function or valid timestamp is not needed, set FF_FS_NORTC = 1 to disable
|
||||||
/ the timestamp function. Every object modified by FatFs will have a fixed timestamp
|
/ the timestamp function. Every object modified by FatFs will have a fixed timestamp
|
||||||
@@ -306,6 +306,7 @@ typedef enum {
|
|||||||
DRIVE_BOOT1 = 1,
|
DRIVE_BOOT1 = 1,
|
||||||
DRIVE_BOOT1_1MB = 2,
|
DRIVE_BOOT1_1MB = 2,
|
||||||
DRIVE_EMMC = 3,
|
DRIVE_EMMC = 3,
|
||||||
|
DRIVE_EMUSD = 4,
|
||||||
} DDRIVE;
|
} DDRIVE;
|
||||||
|
|
||||||
/*--- End of configuration options ---*/
|
/*--- End of configuration options ---*/
|
||||||
|
|||||||
@@ -22,6 +22,7 @@
|
|||||||
#include <bdk.h>
|
#include <bdk.h>
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
#include "gfx/gfx.h"
|
||||||
#include "gfx/logos.h"
|
#include "gfx/logos.h"
|
||||||
#include "gfx/tui.h"
|
#include "gfx/tui.h"
|
||||||
#include "hos/hos.h"
|
#include "hos/hos.h"
|
||||||
@@ -35,6 +36,7 @@
|
|||||||
|
|
||||||
#include "frontend/fe_tools.h"
|
#include "frontend/fe_tools.h"
|
||||||
#include "frontend/fe_info.h"
|
#include "frontend/fe_info.h"
|
||||||
|
#include "storage/emusd.h"
|
||||||
|
|
||||||
hekate_config h_cfg;
|
hekate_config h_cfg;
|
||||||
boot_cfg_t __attribute__((section ("._boot_cfg"))) b_cfg;
|
boot_cfg_t __attribute__((section ("._boot_cfg"))) b_cfg;
|
||||||
@@ -207,6 +209,8 @@ static void _launch_payload(char *path, bool update, bool clear_screen)
|
|||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
boot_storage_end();
|
boot_storage_end();
|
||||||
|
sd_end();
|
||||||
|
emmc_end();
|
||||||
|
|
||||||
if (size < 0x30000)
|
if (size < 0x30000)
|
||||||
{
|
{
|
||||||
@@ -339,6 +343,7 @@ static void _launch_ini_list()
|
|||||||
u8 max_entries = 61;
|
u8 max_entries = 61;
|
||||||
char *special_path = NULL;
|
char *special_path = NULL;
|
||||||
char *emummc_path = NULL;
|
char *emummc_path = NULL;
|
||||||
|
char *emusd_path = NULL;
|
||||||
ment_t *ments = NULL;
|
ment_t *ments = NULL;
|
||||||
ini_sec_t *cfg_sec = NULL;
|
ini_sec_t *cfg_sec = NULL;
|
||||||
|
|
||||||
@@ -403,13 +408,22 @@ static void _launch_ini_list()
|
|||||||
h_cfg.emummc_force_disable = atoi(kv->val);
|
h_cfg.emummc_force_disable = atoi(kv->val);
|
||||||
else if (!strcmp("emupath", kv->key))
|
else if (!strcmp("emupath", kv->key))
|
||||||
emummc_path = kv->val;
|
emummc_path = kv->val;
|
||||||
|
else if (!strcmp("emusdpath", kv->key))
|
||||||
|
emusd_path = kv->val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: also check emuSD path
|
||||||
if (emummc_path && !emummc_set_path(emummc_path))
|
if (emummc_path && !emummc_set_path(emummc_path))
|
||||||
{
|
{
|
||||||
EPRINTF("emupath is wrong!");
|
EPRINTF("emupath is wrong!");
|
||||||
goto wrong_emupath;
|
goto wrong_emupath;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (emusd_path && !emusd_set_path(emusd_path)){
|
||||||
|
EPRINTFARGS("path: %s", emusd_path);
|
||||||
|
EPRINTF("error: emusdpath is wrong!");
|
||||||
|
goto wrong_emupath;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!cfg_sec)
|
if (!cfg_sec)
|
||||||
@@ -445,14 +459,22 @@ parse_failed:
|
|||||||
launch_l4t(cfg_sec, entry_idx, 1, h_cfg.t210b01);
|
launch_l4t(cfg_sec, entry_idx, 1, h_cfg.t210b01);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (!hos_launch(cfg_sec))
|
else
|
||||||
{
|
{
|
||||||
|
hos_launch(cfg_sec);
|
||||||
|
|
||||||
wrong_emupath:
|
wrong_emupath:
|
||||||
if (emummc_path)
|
if (emummc_path)
|
||||||
{
|
{
|
||||||
boot_storage_mount();
|
boot_storage_mount();
|
||||||
emummc_load_cfg(); // Reload emuMMC config in case of emupath.
|
emummc_load_cfg(); // Reload emuMMC config in case of emupath.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (emusd_path)
|
||||||
|
{
|
||||||
|
boot_storage_mount();
|
||||||
|
emusd_load_cfg();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
out:
|
out:
|
||||||
@@ -466,6 +488,7 @@ static void _launch_config()
|
|||||||
u8 max_entries = 61;
|
u8 max_entries = 61;
|
||||||
char *special_path = NULL;
|
char *special_path = NULL;
|
||||||
char *emummc_path = NULL;
|
char *emummc_path = NULL;
|
||||||
|
char *emusd_path = NULL;
|
||||||
|
|
||||||
ment_t *ments = NULL;
|
ment_t *ments = NULL;
|
||||||
ini_sec_t *cfg_sec = NULL;
|
ini_sec_t *cfg_sec = NULL;
|
||||||
@@ -480,6 +503,7 @@ static void _launch_config()
|
|||||||
|
|
||||||
// Load emuMMC configuration.
|
// Load emuMMC configuration.
|
||||||
emummc_load_cfg();
|
emummc_load_cfg();
|
||||||
|
emusd_load_cfg();
|
||||||
|
|
||||||
// Parse main configuration.
|
// Parse main configuration.
|
||||||
ini_parse(&ini_sections, "bootloader/hekate_ipl.ini", false);
|
ini_parse(&ini_sections, "bootloader/hekate_ipl.ini", false);
|
||||||
@@ -546,6 +570,8 @@ static void _launch_config()
|
|||||||
h_cfg.emummc_force_disable = atoi(kv->val);
|
h_cfg.emummc_force_disable = atoi(kv->val);
|
||||||
if (!strcmp("emupath", kv->key))
|
if (!strcmp("emupath", kv->key))
|
||||||
emummc_path = kv->val;
|
emummc_path = kv->val;
|
||||||
|
if (!strcmp("emusdpath", kv->key))
|
||||||
|
emusd_path = kv->val;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (emummc_path && !emummc_set_path(emummc_path))
|
if (emummc_path && !emummc_set_path(emummc_path))
|
||||||
@@ -553,6 +579,13 @@ static void _launch_config()
|
|||||||
EPRINTF("emupath is wrong!");
|
EPRINTF("emupath is wrong!");
|
||||||
goto wrong_emupath;
|
goto wrong_emupath;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (emusd_path && !emusd_set_path(emusd_path))
|
||||||
|
{
|
||||||
|
EPRINTFARGS("path: %s", emusd_path);
|
||||||
|
EPRINTF("error: emusdpath is wrong!");
|
||||||
|
goto wrong_emupath;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!cfg_sec)
|
if (!cfg_sec)
|
||||||
@@ -588,14 +621,22 @@ parse_failed:
|
|||||||
launch_l4t(cfg_sec, entry_idx, 0, h_cfg.t210b01);
|
launch_l4t(cfg_sec, entry_idx, 0, h_cfg.t210b01);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (!hos_launch(cfg_sec))
|
else
|
||||||
{
|
{
|
||||||
|
hos_launch(cfg_sec);
|
||||||
|
|
||||||
wrong_emupath:
|
wrong_emupath:
|
||||||
if (emummc_path)
|
if (emummc_path)
|
||||||
{
|
{
|
||||||
boot_storage_mount();
|
boot_storage_mount();
|
||||||
emummc_load_cfg(); // Reload emuMMC config in case of emupath.
|
emummc_load_cfg(); // Reload emuMMC config in case of emupath.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (emusd_path)
|
||||||
|
{
|
||||||
|
boot_storage_mount();
|
||||||
|
emusd_load_cfg();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
out:
|
out:
|
||||||
@@ -617,6 +658,8 @@ static void _nyx_load_run()
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
boot_storage_end();
|
boot_storage_end();
|
||||||
|
sd_end();
|
||||||
|
emmc_end();
|
||||||
|
|
||||||
render_static_bootlogo();
|
render_static_bootlogo();
|
||||||
display_backlight_brightness(h_cfg.backlight, 1000);
|
display_backlight_brightness(h_cfg.backlight, 1000);
|
||||||
@@ -678,7 +721,7 @@ static void _nyx_load_run()
|
|||||||
(*nyx_ptr)();
|
(*nyx_ptr)();
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
ini_sec_t *cfg_sec = NULL;
|
||||||
|
|
||||||
@@ -697,10 +740,13 @@ static ini_sec_t *_get_ini_sec_from_id(ini_sec_t *ini_sec, char **bootlogoCustom
|
|||||||
*bootlogoCustomEntry = kv->val;
|
*bootlogoCustomEntry = kv->val;
|
||||||
else if (!strcmp("emummc_force_disable", kv->key))
|
else if (!strcmp("emummc_force_disable", kv->key))
|
||||||
h_cfg.emummc_force_disable = atoi(kv->val);
|
h_cfg.emummc_force_disable = atoi(kv->val);
|
||||||
|
else if (!strcmp("emusdpath", kv->key))
|
||||||
|
*emusd_path = kv->val;
|
||||||
}
|
}
|
||||||
if (!cfg_sec)
|
if (!cfg_sec)
|
||||||
{
|
{
|
||||||
*emummc_path = NULL;
|
*emummc_path = NULL;
|
||||||
|
*emusd_path = NULL;
|
||||||
*bootlogoCustomEntry = NULL;
|
*bootlogoCustomEntry = NULL;
|
||||||
h_cfg.emummc_force_disable = false;
|
h_cfg.emummc_force_disable = false;
|
||||||
}
|
}
|
||||||
@@ -755,6 +801,7 @@ static void _auto_launch()
|
|||||||
u32 boot_entry_id = 0;
|
u32 boot_entry_id = 0;
|
||||||
ini_sec_t *cfg_sec = NULL;
|
ini_sec_t *cfg_sec = NULL;
|
||||||
char *emummc_path = NULL;
|
char *emummc_path = NULL;
|
||||||
|
char *emusd_path = NULL;
|
||||||
char *bootlogoCustomEntry = NULL;
|
char *bootlogoCustomEntry = NULL;
|
||||||
bool config_entry_found = false;
|
bool config_entry_found = false;
|
||||||
|
|
||||||
@@ -772,6 +819,7 @@ static void _auto_launch()
|
|||||||
|
|
||||||
// Load emuMMC configuration.
|
// Load emuMMC configuration.
|
||||||
emummc_load_cfg();
|
emummc_load_cfg();
|
||||||
|
emusd_load_cfg();
|
||||||
|
|
||||||
// Parse hekate main configuration.
|
// Parse hekate main configuration.
|
||||||
if (!ini_parse(&ini_sections, "bootloader/hekate_ipl.ini", false))
|
if (!ini_parse(&ini_sections, "bootloader/hekate_ipl.ini", false))
|
||||||
@@ -827,7 +875,7 @@ static void _auto_launch()
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (boot_from_id)
|
if (boot_from_id)
|
||||||
cfg_sec = _get_ini_sec_from_id(ini_sec, &bootlogoCustomEntry, &emummc_path);
|
cfg_sec = _get_ini_sec_from_id(ini_sec, &bootlogoCustomEntry, &emummc_path, &emusd_path);
|
||||||
else if (h_cfg.autoboot == boot_entry_id && config_entry_found)
|
else if (h_cfg.autoboot == boot_entry_id && config_entry_found)
|
||||||
{
|
{
|
||||||
cfg_sec = ini_sec;
|
cfg_sec = ini_sec;
|
||||||
@@ -837,6 +885,8 @@ static void _auto_launch()
|
|||||||
bootlogoCustomEntry = kv->val;
|
bootlogoCustomEntry = kv->val;
|
||||||
else if (!strcmp("emupath", kv->key))
|
else if (!strcmp("emupath", kv->key))
|
||||||
emummc_path = kv->val;
|
emummc_path = kv->val;
|
||||||
|
else if (!strcmp("emusdpath", kv->key))
|
||||||
|
emusd_path = kv->val;
|
||||||
else if (!strcmp("emummc_force_disable", kv->key))
|
else if (!strcmp("emummc_force_disable", kv->key))
|
||||||
h_cfg.emummc_force_disable = atoi(kv->val);
|
h_cfg.emummc_force_disable = atoi(kv->val);
|
||||||
else if (!strcmp("bootwait", kv->key))
|
else if (!strcmp("bootwait", kv->key))
|
||||||
@@ -873,7 +923,7 @@ static void _auto_launch()
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (boot_from_id)
|
if (boot_from_id)
|
||||||
cfg_sec = _get_ini_sec_from_id(ini_sec_list, &bootlogoCustomEntry, &emummc_path);
|
cfg_sec = _get_ini_sec_from_id(ini_sec_list, &bootlogoCustomEntry, &emummc_path, &emusd_path);
|
||||||
else if (h_cfg.autoboot == boot_entry_id)
|
else if (h_cfg.autoboot == boot_entry_id)
|
||||||
{
|
{
|
||||||
h_cfg.emummc_force_disable = false;
|
h_cfg.emummc_force_disable = false;
|
||||||
@@ -884,6 +934,8 @@ static void _auto_launch()
|
|||||||
bootlogoCustomEntry = kv->val;
|
bootlogoCustomEntry = kv->val;
|
||||||
else if (!strcmp("emupath", kv->key))
|
else if (!strcmp("emupath", kv->key))
|
||||||
emummc_path = kv->val;
|
emummc_path = kv->val;
|
||||||
|
else if (!strcmp("emusdpath", kv->key))
|
||||||
|
emusd_path = kv->val;
|
||||||
else if (!strcmp("emummc_force_disable", kv->key))
|
else if (!strcmp("emummc_force_disable", kv->key))
|
||||||
h_cfg.emummc_force_disable = atoi(kv->val);
|
h_cfg.emummc_force_disable = atoi(kv->val);
|
||||||
else if (!strcmp("bootwait", kv->key))
|
else if (!strcmp("bootwait", kv->key))
|
||||||
@@ -997,6 +1049,7 @@ skip_list:
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
// TODO: add boot_cfg for emusd
|
||||||
if (b_cfg.boot_cfg & BOOT_CFG_TO_EMUMMC)
|
if (b_cfg.boot_cfg & BOOT_CFG_TO_EMUMMC)
|
||||||
emummc_set_path(b_cfg.emummc_path);
|
emummc_set_path(b_cfg.emummc_path);
|
||||||
else if (emummc_path && !emummc_set_path(emummc_path))
|
else if (emummc_path && !emummc_set_path(emummc_path))
|
||||||
@@ -1006,6 +1059,14 @@ skip_list:
|
|||||||
goto wrong_emupath;
|
goto wrong_emupath;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (emusd_path && !emusd_set_path(emusd_path))
|
||||||
|
{
|
||||||
|
gfx_con.mute = false;
|
||||||
|
EPRINTFARGS("path: %s", emusd_path);
|
||||||
|
EPRINTF("error: emusdpath is wrong!");
|
||||||
|
goto wrong_emupath;
|
||||||
|
}
|
||||||
|
|
||||||
hos_launch(cfg_sec);
|
hos_launch(cfg_sec);
|
||||||
|
|
||||||
wrong_emupath:
|
wrong_emupath:
|
||||||
@@ -1015,6 +1076,12 @@ wrong_emupath:
|
|||||||
emummc_load_cfg(); // Reload emuMMC config in case of emupath.
|
emummc_load_cfg(); // Reload emuMMC config in case of emupath.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (emusd_path)
|
||||||
|
{
|
||||||
|
boot_storage_mount();
|
||||||
|
emusd_load_cfg();
|
||||||
|
}
|
||||||
|
|
||||||
error:
|
error:
|
||||||
gfx_con.mute = false;
|
gfx_con.mute = false;
|
||||||
gfx_printf("\nPress any key...\n");
|
gfx_printf("\nPress any key...\n");
|
||||||
@@ -1351,7 +1418,7 @@ static void _about()
|
|||||||
{
|
{
|
||||||
static const char credits[] =
|
static const char credits[] =
|
||||||
"\nhekate (c) 2018, naehrwert, st4rk\n\n"
|
"\nhekate (c) 2018, naehrwert, st4rk\n\n"
|
||||||
" (c) 2018-2024, CTCaer\n\n"
|
" (c) 2018-2025, CTCaer\n\n"
|
||||||
" ___________________________________________\n\n"
|
" ___________________________________________\n\n"
|
||||||
"Thanks to: %kderrek, nedwill, plutoo,\n"
|
"Thanks to: %kderrek, nedwill, plutoo,\n"
|
||||||
" shuffle2, smea, thexyz, yellows8%k\n"
|
" shuffle2, smea, thexyz, yellows8%k\n"
|
||||||
@@ -1447,7 +1514,7 @@ ment_t ment_top[] = {
|
|||||||
MDEF_END()
|
MDEF_END()
|
||||||
};
|
};
|
||||||
|
|
||||||
menu_t menu_top = { ment_top, "hekate v6.2.2", 0, 0 };
|
menu_t menu_top = { ment_top, "hekate v6.3.1", 0, 0 };
|
||||||
|
|
||||||
extern void pivot_stack(u32 stack_top);
|
extern void pivot_stack(u32 stack_top);
|
||||||
|
|
||||||
|
|||||||
@@ -190,11 +190,12 @@ int emummc_storage_init_mmc()
|
|||||||
if(!emu_cfg.sector){
|
if(!emu_cfg.sector){
|
||||||
// file based
|
// file based
|
||||||
if(!emmc_mount()){
|
if(!emmc_mount()){
|
||||||
|
gfx_printf("emmc mount fail\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
strcpy(emu_cfg.emummc_file_based_path, "emmc:");
|
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, emu_cfg.path);
|
||||||
strcat(emu_cfg.emummc_file_based_path, "/eMMC");
|
strcat(emu_cfg.emummc_file_based_path, "/eMMC/");
|
||||||
file_based = true;
|
file_based = true;
|
||||||
}else{
|
}else{
|
||||||
// raw based
|
// raw based
|
||||||
@@ -209,7 +210,7 @@ int emummc_storage_init_mmc()
|
|||||||
}
|
}
|
||||||
strcpy(emu_cfg.emummc_file_based_path, "sd:");
|
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, emu_cfg.path);
|
||||||
strcat(emu_cfg.emummc_file_based_path, "/eMMC");
|
strcat(emu_cfg.emummc_file_based_path, "/eMMC/");
|
||||||
file_based = true;
|
file_based = true;
|
||||||
}else{
|
}else{
|
||||||
// raw based
|
// raw based
|
||||||
@@ -220,6 +221,7 @@ int emummc_storage_init_mmc()
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(file_based){
|
if(file_based){
|
||||||
|
gfx_printf("file based\n");
|
||||||
return emummc_storage_file_based_init(emu_cfg.emummc_file_based_path) == 0;
|
return emummc_storage_file_based_init(emu_cfg.emummc_file_based_path) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -255,33 +257,6 @@ int emummc_storage_read(u32 sector, u32 num_sectors, void *buf)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
return emummc_storage_file_based_read(sector, num_sectors, buf);
|
return emummc_storage_file_based_read(sector, num_sectors, buf);
|
||||||
// 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 1;
|
return 1;
|
||||||
@@ -302,31 +277,6 @@ int emummc_storage_write(u32 sector, u32 num_sectors, void *buf)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
return emummc_storage_file_based_write(sector, num_sectors, buf);
|
return emummc_storage_file_based_write(sector, num_sectors, buf);
|
||||||
// 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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -334,15 +284,11 @@ int emummc_storage_set_mmc_partition(u32 partition)
|
|||||||
{
|
{
|
||||||
emu_cfg.active_part = partition;
|
emu_cfg.active_part = partition;
|
||||||
|
|
||||||
if(h_cfg.emummc_force_disable){
|
if(h_cfg.emummc_force_disable || !emu_cfg.enabled){
|
||||||
emmc_set_partition(partition);
|
emmc_set_partition(partition);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!emu_cfg.enabled){
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!emu_cfg.sector){
|
if(!emu_cfg.sector){
|
||||||
emummc_storage_file_base_set_partition(partition);
|
emummc_storage_file_base_set_partition(partition);
|
||||||
return 1;
|
return 1;
|
||||||
|
|||||||
@@ -19,19 +19,6 @@
|
|||||||
|
|
||||||
#include <bdk.h>
|
#include <bdk.h>
|
||||||
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
EMUMMC_TYPE_NONE = 0,
|
|
||||||
EMUMMC_TYPE_PARTITION = 1,
|
|
||||||
EMUMMC_TYPE_FILES = 2,
|
|
||||||
} emummc_type_t;
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
EMUMMC_MMC_NAND = 0,
|
|
||||||
EMUMMC_MMC_SD = 1,
|
|
||||||
EMUMMC_MMC_GC = 2,
|
|
||||||
} emummc_mmc_t;
|
|
||||||
|
|
||||||
typedef struct _emummc_cfg_t
|
typedef struct _emummc_cfg_t
|
||||||
{
|
{
|
||||||
int enabled;
|
int enabled;
|
||||||
|
|||||||
295
bootloader/storage/emusd.c
Normal file
295
bootloader/storage/emusd.c
Normal file
@@ -0,0 +1,295 @@
|
|||||||
|
#include "emusd.h"
|
||||||
|
#include <bdk.h>
|
||||||
|
#include <storage/boot_storage.h>
|
||||||
|
#include <storage/emmc.h>
|
||||||
|
#include <storage/file_based_storage.h>
|
||||||
|
#include <storage/sd.h>
|
||||||
|
#include <storage/sdmmc.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <utils/ini.h>
|
||||||
|
#include <libs/fatfs/ff.h>
|
||||||
|
#include "../config.h"
|
||||||
|
#include "gfx_utils.h"
|
||||||
|
|
||||||
|
|
||||||
|
FATFS emusd_fs;
|
||||||
|
bool emusd_mounted = false;
|
||||||
|
bool emusd_initialized = false;
|
||||||
|
emusd_cfg_t emu_sd_cfg = {0};
|
||||||
|
extern hekate_config h_cfg;
|
||||||
|
|
||||||
|
static bool emusd_get_mounted() {
|
||||||
|
return emusd_mounted;
|
||||||
|
}
|
||||||
|
|
||||||
|
void emusd_load_cfg()
|
||||||
|
{
|
||||||
|
emu_sd_cfg.enabled = 0;
|
||||||
|
emu_sd_cfg.fs_ver = 0;
|
||||||
|
emu_sd_cfg.id = 0;
|
||||||
|
emu_sd_cfg.sector = 0;
|
||||||
|
if(!emu_sd_cfg.path) {
|
||||||
|
emu_sd_cfg.path = (char*)malloc(0x200);
|
||||||
|
}
|
||||||
|
if(!emu_sd_cfg.emummc_file_based_path){
|
||||||
|
emu_sd_cfg.emummc_file_based_path = (char*)malloc(0x200);
|
||||||
|
}
|
||||||
|
|
||||||
|
LIST_INIT(ini_sections);
|
||||||
|
if(ini_parse(&ini_sections, "emuSD/emusd.ini", false))
|
||||||
|
{
|
||||||
|
LIST_FOREACH_ENTRY(ini_sec_t, ini_sec, &ini_sections, link)
|
||||||
|
{
|
||||||
|
if(ini_sec->type == INI_CHOICE)
|
||||||
|
{
|
||||||
|
if(strcmp(ini_sec->name, "emusd")){
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
LIST_FOREACH_ENTRY(ini_kv_t, kv, &ini_sec->kvs, link)
|
||||||
|
{
|
||||||
|
if(!strcmp(kv->key, "enabled")){
|
||||||
|
emu_sd_cfg.enabled = atoi(kv->val);
|
||||||
|
} else if(!strcmp(kv->key, "sector")){
|
||||||
|
emu_sd_cfg.sector = strtol(kv->val, NULL, 16);
|
||||||
|
} else if(!strcmp(kv->key, "path")){
|
||||||
|
emu_sd_cfg.path = kv->val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool emusd_mount() {
|
||||||
|
if (emusd_mounted) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (emusd_storage_init_mmc()){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int res = f_mount(&emusd_fs, "emusd:", 1);
|
||||||
|
|
||||||
|
if(res) {
|
||||||
|
EPRINTFARGS("emusd mount fail %d", res);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool emusd_unmount() {
|
||||||
|
f_mount(NULL, "emusd:", 1);
|
||||||
|
emusd_mounted = false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool emusd_set_path(char *path) {
|
||||||
|
FIL fp;
|
||||||
|
bool found = false;
|
||||||
|
// TODO: use emu_sd.file_path instead
|
||||||
|
strcat(emu_sd_cfg.emummc_file_based_path, "");
|
||||||
|
strcpy(emu_sd_cfg.emummc_file_based_path, path);
|
||||||
|
strcat(emu_sd_cfg.emummc_file_based_path, "/raw_emmc_based");
|
||||||
|
if(!f_open(&fp, emu_sd_cfg.emummc_file_based_path, FA_READ))
|
||||||
|
{
|
||||||
|
if(!f_read(&fp, &emu_sd_cfg.sector, 4, NULL)){
|
||||||
|
if(emu_sd_cfg.sector){
|
||||||
|
found = true;
|
||||||
|
emu_sd_cfg.enabled = 4;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
strcpy(emu_sd_cfg.emummc_file_based_path, "");
|
||||||
|
strcat(emu_sd_cfg.emummc_file_based_path, path);
|
||||||
|
strcat(emu_sd_cfg.emummc_file_based_path, "/raw_emmc_based");
|
||||||
|
if (!f_open(&fp, emu_sd_cfg.emummc_file_based_path, FA_READ))
|
||||||
|
{
|
||||||
|
if (!f_read(&fp, &emu_sd_cfg.sector, 4, NULL)){
|
||||||
|
if (emu_sd_cfg.sector){
|
||||||
|
found = true;
|
||||||
|
emu_sd_cfg.enabled = 4;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// strcpy(emu_sd_cfg.emummc_file_based_path, "sd:");
|
||||||
|
strcpy(emu_sd_cfg.emummc_file_based_path, "");
|
||||||
|
strcat(emu_sd_cfg.emummc_file_based_path, path);
|
||||||
|
strcat(emu_sd_cfg.emummc_file_based_path, "/file_based");
|
||||||
|
if (!f_stat(emu_sd_cfg.emummc_file_based_path, NULL))
|
||||||
|
{
|
||||||
|
emu_sd_cfg.sector = 0;
|
||||||
|
emu_sd_cfg.path = path;
|
||||||
|
emu_sd_cfg.enabled = 1;
|
||||||
|
|
||||||
|
found = true;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
// strcpy(emu_sd_cfg.emummc_file_based_path, "sd:");
|
||||||
|
strcpy(emu_sd_cfg.emummc_file_based_path, "");
|
||||||
|
strcat(emu_sd_cfg.emummc_file_based_path, path);
|
||||||
|
strcat(emu_sd_cfg.emummc_file_based_path, "/file_emmc_based");
|
||||||
|
if (!f_stat(emu_sd_cfg.emummc_file_based_path, NULL))
|
||||||
|
{
|
||||||
|
emu_sd_cfg.sector = 0;
|
||||||
|
emu_sd_cfg.path = path;
|
||||||
|
emu_sd_cfg.enabled = 4;
|
||||||
|
|
||||||
|
found = true;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
return found;
|
||||||
|
}
|
||||||
|
|
||||||
|
int emusd_storage_init_mmc() {
|
||||||
|
if(!emusd_initialized) {
|
||||||
|
if (!emu_sd_cfg.enabled || h_cfg.emummc_force_disable) {
|
||||||
|
if(!sd_initialize(false)){
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
emusd_initialized = true;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool file_based = false;
|
||||||
|
if(emu_sd_cfg.enabled == 4){
|
||||||
|
if(!emu_sd_cfg.sector){
|
||||||
|
//file based
|
||||||
|
if(!emmc_mount()){
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
strcpy(emu_sd_cfg.emummc_file_based_path, "emmc:");
|
||||||
|
strcat(emu_sd_cfg.emummc_file_based_path, emu_sd_cfg.path);
|
||||||
|
strcat(emu_sd_cfg.emummc_file_based_path, "/SD/");
|
||||||
|
file_based = true;
|
||||||
|
}else{
|
||||||
|
if(!emmc_initialize(false)){
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
if(!emu_sd_cfg.sector){
|
||||||
|
//file based
|
||||||
|
if(!sd_mount()){
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
strcpy(emu_sd_cfg.emummc_file_based_path, "sd:");
|
||||||
|
strcat(emu_sd_cfg.emummc_file_based_path, emu_sd_cfg.path);
|
||||||
|
strcat(emu_sd_cfg.emummc_file_based_path, "/SD/");
|
||||||
|
file_based = true;
|
||||||
|
}else{
|
||||||
|
if(!sd_initialize(false)){
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(file_based){
|
||||||
|
return file_based_storage_init(emu_sd_cfg.emummc_file_based_path) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
emusd_initialized = true;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int emusd_storage_end() {
|
||||||
|
if(!h_cfg.emummc_force_disable && emu_sd_cfg.enabled && !emu_sd_cfg.sector){
|
||||||
|
file_based_storage_end();
|
||||||
|
}
|
||||||
|
if(!emu_sd_cfg.enabled || h_cfg.emummc_force_disable || emu_sd_cfg.enabled == 1){
|
||||||
|
sd_unmount();
|
||||||
|
}else{
|
||||||
|
emmc_unmount();
|
||||||
|
}
|
||||||
|
emusd_initialized = false;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int emusd_storage_write(u32 sector, u32 num_sectors, void *buf) {
|
||||||
|
if(!emu_sd_cfg.enabled || h_cfg.emummc_force_disable){
|
||||||
|
return sdmmc_storage_write(&sd_storage, sector, num_sectors, buf);
|
||||||
|
}else if(emu_sd_cfg.sector){
|
||||||
|
sdmmc_storage_t *storage = emu_sd_cfg.enabled == 1 ? &sd_storage : &emmc_storage;
|
||||||
|
sector += emu_sd_cfg.sector;
|
||||||
|
return sdmmc_storage_write(storage, sector, num_sectors, buf);
|
||||||
|
}else{
|
||||||
|
return file_based_storage_write(sector, num_sectors, buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int emusd_storage_read(u32 sector, u32 num_sectors, void *buf) {
|
||||||
|
if(!emu_sd_cfg.enabled || h_cfg.emummc_force_disable){
|
||||||
|
return sdmmc_storage_read(&sd_storage, sector, num_sectors, buf);
|
||||||
|
}else if(emu_sd_cfg.sector){
|
||||||
|
sdmmc_storage_t *storage = emu_sd_cfg.enabled == 1 ? &sd_storage : &emmc_storage;
|
||||||
|
sector += emu_sd_cfg.sector;
|
||||||
|
return sdmmc_storage_read(storage, sector, num_sectors, buf);
|
||||||
|
}else{
|
||||||
|
return file_based_storage_read(sector, num_sectors, buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sdmmc_storage_t *emusd_get_storage() {
|
||||||
|
return emu_sd_cfg.enabled == 4 ? &emmc_storage : &sd_storage;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool emusd_is_gpt() {
|
||||||
|
if(emu_sd_cfg.enabled) {
|
||||||
|
return emusd_fs.part_type;
|
||||||
|
} else {
|
||||||
|
return sd_fs.part_type;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int emusd_get_fs_type() {
|
||||||
|
if(emu_sd_cfg.enabled) {
|
||||||
|
return emusd_fs.fs_type;
|
||||||
|
} else {
|
||||||
|
return sd_fs.fs_type;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void *emusd_file_read(const char *path, u32 *fsize) {
|
||||||
|
if(emu_sd_cfg.enabled) {
|
||||||
|
char *path1 = malloc(0x100);
|
||||||
|
strcpy(path1, "emusd:");
|
||||||
|
strcat(path1, path);
|
||||||
|
FIL fp;
|
||||||
|
if (!emusd_get_mounted())
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (f_open(&fp, path, FA_READ) != FR_OK)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
u32 size = f_size(&fp);
|
||||||
|
if (fsize)
|
||||||
|
*fsize = size;
|
||||||
|
|
||||||
|
void *buf = malloc(size);
|
||||||
|
|
||||||
|
if (f_read(&fp, buf, size, NULL) != FR_OK)
|
||||||
|
{
|
||||||
|
free(buf);
|
||||||
|
f_close(&fp);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
f_close(&fp);
|
||||||
|
|
||||||
|
return buf;
|
||||||
|
} else {
|
||||||
|
return boot_storage_file_read(path, fsize);
|
||||||
|
}
|
||||||
|
}
|
||||||
49
bootloader/storage/emusd.h
Normal file
49
bootloader/storage/emusd.h
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2019-2021 CTCaer
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms and conditions of the GNU General Public License,
|
||||||
|
* version 2, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _EMUSD_H
|
||||||
|
#define _EMUSD_H
|
||||||
|
|
||||||
|
#include <bdk.h>
|
||||||
|
|
||||||
|
typedef struct _emusd_cfg_t
|
||||||
|
{
|
||||||
|
int enabled;
|
||||||
|
u64 sector;
|
||||||
|
u32 id;
|
||||||
|
char *path;
|
||||||
|
// Internal.
|
||||||
|
int fs_ver;
|
||||||
|
char *emummc_file_based_path;
|
||||||
|
|
||||||
|
} emusd_cfg_t;
|
||||||
|
|
||||||
|
extern emusd_cfg_t emu_sd_cfg;
|
||||||
|
|
||||||
|
void emusd_load_cfg();
|
||||||
|
bool emusd_set_path(char *path);
|
||||||
|
int emusd_storage_init_mmc();
|
||||||
|
int emusd_storage_end();
|
||||||
|
int emusd_storage_read(u32 sector, u32 num_sectors, void *buf);
|
||||||
|
int emusd_storage_write(u32 sector, u32 num_sectors, void *buf);
|
||||||
|
sdmmc_storage_t *emusd_get_storage();
|
||||||
|
bool emusd_is_gpt();
|
||||||
|
int emusd_get_fs_type();
|
||||||
|
bool emusd_mount();
|
||||||
|
bool emusd_unmount();
|
||||||
|
void *emusd_file_read(const char *path, u32 *fsize);
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -46,7 +46,7 @@ clean:
|
|||||||
@rm -rf $(OBJS)
|
@rm -rf $(OBJS)
|
||||||
|
|
||||||
$(TARGET).bin: $(BUILDDIR)/$(TARGET)/$(TARGET).elf
|
$(TARGET).bin: $(BUILDDIR)/$(TARGET)/$(TARGET).elf
|
||||||
$(OBJCOPY) -S -O binary $< $(OUTPUTDIR)/$(PAYLOAD_NAME).bin
|
@$(OBJCOPY) -S -O binary $< $(OUTPUTDIR)/$(PAYLOAD_NAME).bin
|
||||||
|
|
||||||
$(BUILDDIR)/$(TARGET)/$(TARGET).elf: $(OBJS)
|
$(BUILDDIR)/$(TARGET)/$(TARGET).elf: $(OBJS)
|
||||||
@$(CC) $(LDFLAGS) -T link.ld $^ -o $@
|
@$(CC) $(LDFLAGS) -T link.ld $^ -o $@
|
||||||
|
|||||||
14
nyx/Makefile
14
nyx/Makefile
@@ -41,7 +41,7 @@ OBJS += $(addprefix $(BUILDDIR)/$(TARGET)/, \
|
|||||||
bm92t36.o bq24193.o max17050.o max7762x.o max77620-rtc.o regulator_5v.o \
|
bm92t36.o bq24193.o max17050.o max7762x.o max77620-rtc.o regulator_5v.o \
|
||||||
touch.o joycon.o tmp451.o fan.o \
|
touch.o joycon.o tmp451.o fan.o \
|
||||||
usbd.o xusbd.o usb_descriptors.o usb_gadget_ums.o usb_gadget_hid.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 \
|
hw_init.o boot_storage.o sfd.o mbr_gpt.o emummc_file_based.o file_based_storage.o \
|
||||||
)
|
)
|
||||||
|
|
||||||
# Utilities.
|
# Utilities.
|
||||||
@@ -93,12 +93,12 @@ CUSTOMDEFINES += -DGFX_INC=$(GFX_INC) -DFFCFG_INC=$(FFCFG_INC)
|
|||||||
#CUSTOMDEFINES += -DDEBUG_UART_LV_LOG
|
#CUSTOMDEFINES += -DDEBUG_UART_LV_LOG
|
||||||
|
|
||||||
#TODO: Considering reinstating some of these when pointer warnings have been fixed.
|
#TODO: Considering reinstating some of these when pointer warnings have been fixed.
|
||||||
WARNINGS := -Wall -Wsign-compare -Wno-array-bounds -Wno-stringop-overread -Wno-stringop-overflow
|
WARNINGS := -Wall -Wsign-compare -Wtype-limits -Wno-array-bounds -Wno-stringop-overread -Wno-stringop-overflow
|
||||||
#-fno-delete-null-pointer-checks
|
#-fno-delete-null-pointer-checks
|
||||||
#-Wstack-usage=byte-size -fstack-usage
|
#-Wstack-usage=byte-size -fstack-usage
|
||||||
|
|
||||||
ARCH := -march=armv4t -mtune=arm7tdmi -mthumb-interwork
|
ARCH := -march=armv4t -mtune=arm7tdmi -mthumb-interwork $(WARNINGS)
|
||||||
CFLAGS = $(ARCH) -O2 -g -gdwarf-4 -nostdlib -ffunction-sections -fdata-sections -fomit-frame-pointer -std=gnu11 $(WARNINGS) $(CUSTOMDEFINES)
|
CFLAGS = $(ARCH) -O2 -g -gdwarf-4 -nostdlib -ffunction-sections -fdata-sections -fomit-frame-pointer -std=gnu11 $(CUSTOMDEFINES)
|
||||||
LDFLAGS = $(ARCH) -nostartfiles -lgcc -Wl,--nmagic,--gc-sections -Xlinker --defsym=NYX_LOAD_ADDR=$(NYX_LOAD_ADDR)
|
LDFLAGS = $(ARCH) -nostartfiles -lgcc -Wl,--nmagic,--gc-sections -Xlinker --defsym=NYX_LOAD_ADDR=$(NYX_LOAD_ADDR)
|
||||||
|
|
||||||
################################################################################
|
################################################################################
|
||||||
@@ -107,7 +107,7 @@ LDFLAGS = $(ARCH) -nostartfiles -lgcc -Wl,--nmagic,--gc-sections -Xlinker --defs
|
|||||||
|
|
||||||
all: $(TARGET).bin
|
all: $(TARGET).bin
|
||||||
@echo "--------------------------------------"
|
@echo "--------------------------------------"
|
||||||
@echo -n "Nyx size: "
|
@echo -n "Nyx size: "
|
||||||
$(eval BIN_SIZE = $(shell wc -c < $(OUTPUTDIR)/$(TARGET).bin))
|
$(eval BIN_SIZE = $(shell wc -c < $(OUTPUTDIR)/$(TARGET).bin))
|
||||||
@echo $(BIN_SIZE)" Bytes"
|
@echo $(BIN_SIZE)" Bytes"
|
||||||
@echo "--------------------------------------"
|
@echo "--------------------------------------"
|
||||||
@@ -118,11 +118,11 @@ clean:
|
|||||||
@rm -rf $(OUTPUTDIR)
|
@rm -rf $(OUTPUTDIR)
|
||||||
|
|
||||||
$(TARGET).bin: $(BUILDDIR)/$(TARGET)/$(TARGET).elf
|
$(TARGET).bin: $(BUILDDIR)/$(TARGET)/$(TARGET).elf
|
||||||
$(OBJCOPY) -S -O binary $< $(OUTPUTDIR)/$@
|
@$(OBJCOPY) -S -O binary $< $(OUTPUTDIR)/$@
|
||||||
|
|
||||||
$(BUILDDIR)/$(TARGET)/$(TARGET).elf: $(OBJS)
|
$(BUILDDIR)/$(TARGET)/$(TARGET).elf: $(OBJS)
|
||||||
@$(CC) $(LDFLAGS) -T $(SOURCEDIR)/link.ld $^ -o $@
|
@$(CC) $(LDFLAGS) -T $(SOURCEDIR)/link.ld $^ -o $@
|
||||||
@echo "Nyx was built with the following flags:\nCFLAGS: "$(CFLAGS)"\nLDFLAGS: "$(LDFLAGS)
|
@printf "$(TARGET) was built with the following flags:\nCFLAGS: $(CFLAGS)\nLDFLAGS: $(LDFLAGS)\n"
|
||||||
|
|
||||||
$(BUILDDIR)/$(TARGET)/%.o: %.c
|
$(BUILDDIR)/$(TARGET)/%.o: %.c
|
||||||
@echo Building $@
|
@echo Building $@
|
||||||
|
|||||||
@@ -54,19 +54,19 @@ static void _get_valid_partition(u32 *sector_start, u32 *sector_size, u32 *part_
|
|||||||
*sector_start = mbr->partitions[i].start_sct;
|
*sector_start = mbr->partitions[i].start_sct;
|
||||||
u8 type = mbr->partitions[i].type;
|
u8 type = mbr->partitions[i].type;
|
||||||
u32 sector_size_safe = backup ? 0x400000 : (*sector_size) + 0x8000; // 2GB min safe size for backup.
|
u32 sector_size_safe = backup ? 0x400000 : (*sector_size) + 0x8000; // 2GB min safe size for backup.
|
||||||
if ((curr_part_size >= sector_size_safe) && *sector_start && type != 0x83 && (!backup || type == 0xE0))
|
if ((curr_part_size >= sector_size_safe) && (*sector_start) && type != 0x83 && (!backup || type == 0xE0))
|
||||||
{
|
{
|
||||||
if (backup)
|
if (backup)
|
||||||
{
|
{
|
||||||
u8 gpt_check[SD_BLOCKSIZE] = { 0 };
|
u8 gpt_check[SD_BLOCKSIZE] = { 0 };
|
||||||
sdmmc_storage_read(&sd_storage, *sector_start + 0xC001, 1, gpt_check);
|
sdmmc_storage_read(&sd_storage, (*sector_start) + 0xC001, 1, gpt_check);
|
||||||
if (!memcmp(gpt_check, "EFI PART", 8))
|
if (!memcmp(gpt_check, "EFI PART", 8))
|
||||||
{
|
{
|
||||||
*sector_size = curr_part_size;
|
*sector_size = curr_part_size;
|
||||||
*sector_start = *sector_start + 0x8000;
|
*sector_start = (*sector_start) + 0x8000;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
sdmmc_storage_read(&sd_storage, *sector_start + 0x4001, 1, gpt_check);
|
sdmmc_storage_read(&sd_storage, (*sector_start) + 0x4001, 1, gpt_check);
|
||||||
if (!memcmp(gpt_check, "EFI PART", 8))
|
if (!memcmp(gpt_check, "EFI PART", 8))
|
||||||
{
|
{
|
||||||
*sector_size = curr_part_size;
|
*sector_size = curr_part_size;
|
||||||
@@ -92,7 +92,7 @@ static void _get_valid_partition(u32 *sector_start, u32 *sector_size, u32 *part_
|
|||||||
if (backup && *part_idx && *sector_size)
|
if (backup && *part_idx && *sector_size)
|
||||||
{
|
{
|
||||||
gpt_t *gpt = (gpt_t *)zalloc(sizeof(gpt_t));
|
gpt_t *gpt = (gpt_t *)zalloc(sizeof(gpt_t));
|
||||||
sdmmc_storage_read(&sd_storage, *sector_start + 0x4001, 1, gpt);
|
sdmmc_storage_read(&sd_storage, (*sector_start) + 0x4001, 1, gpt);
|
||||||
|
|
||||||
u32 new_size = gpt->header.alt_lba + 1;
|
u32 new_size = gpt->header.alt_lba + 1;
|
||||||
if (*sector_size > new_size)
|
if (*sector_size > new_size)
|
||||||
@@ -103,7 +103,7 @@ static void _get_valid_partition(u32 *sector_start, u32 *sector_size, u32 *part_
|
|||||||
free(gpt);
|
free(gpt);
|
||||||
}
|
}
|
||||||
else if (!backup && *part_idx)
|
else if (!backup && *part_idx)
|
||||||
*sector_start = *sector_start + 0x8000;
|
*sector_start = (*sector_start) + 0x8000;
|
||||||
}
|
}
|
||||||
|
|
||||||
static lv_obj_t *create_mbox_text(const char *text, bool button_ok)
|
static lv_obj_t *create_mbox_text(const char *text, bool button_ok)
|
||||||
@@ -623,10 +623,20 @@ static int _dump_emmc_part(emmc_tool_gui_t *gui, char *sd_path, int active_part,
|
|||||||
|
|
||||||
while (res_read)
|
while (res_read)
|
||||||
{
|
{
|
||||||
s_printf(gui->txt_buf,
|
if (!gui->raw_emummc)
|
||||||
"\n#FFDD00 Error reading %d blocks @ LBA %08X,#\n"
|
{
|
||||||
"#FFDD00 from eMMC (try %d). #",
|
s_printf(gui->txt_buf,
|
||||||
num, lba_curr, ++retryCount);
|
"\n#FFDD00 Error reading %d blocks @ LBA %08X,#\n"
|
||||||
|
"#FFDD00 from eMMC (try %d). #",
|
||||||
|
num, lba_curr, ++retryCount);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
s_printf(gui->txt_buf,
|
||||||
|
"\n#FFDD00 Error reading %d blocks @ LBA %08X,#\n"
|
||||||
|
"#FFDD00 from emuMMC @ %08X (try %d). #",
|
||||||
|
num, lba_curr + sd_sector_off, lba_curr, ++retryCount);
|
||||||
|
}
|
||||||
lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf);
|
lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf);
|
||||||
manual_system_maintenance(true);
|
manual_system_maintenance(true);
|
||||||
|
|
||||||
@@ -760,14 +770,16 @@ void dump_emmc_selected(emmcPartType_t dumpType, emmc_tool_gui_t *gui)
|
|||||||
lv_label_set_text(gui->label_info, "Checking for available free space...");
|
lv_label_set_text(gui->label_info, "Checking for available free space...");
|
||||||
manual_system_maintenance(true);
|
manual_system_maintenance(true);
|
||||||
|
|
||||||
if (!sd_mount())
|
if (!boot_storage_mount())
|
||||||
{
|
{
|
||||||
lv_label_set_text(gui->label_info, "#FFDD00 Failed to init SD!#");
|
lv_label_set_text(gui->label_info, "#FFDD00 Failed to storage!#");
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get SD Card free space for Partial Backup.
|
// Get SD Card free space for Partial Backup.
|
||||||
f_getfree("", &sd_fs.free_clst, NULL);
|
FATFS *fs = boot_storage_get_fs();
|
||||||
|
|
||||||
|
f_getfree("", &fs->free_clst, NULL);
|
||||||
|
|
||||||
if (!emmc_initialize(false))
|
if (!emmc_initialize(false))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -426,12 +426,12 @@ static int _dump_emummc_file_part(emmc_tool_gui_t *gui, char *sd_path, sdmmc_sto
|
|||||||
|
|
||||||
FATFS *fs = drive == DRIVE_SD ? &sd_fs : &emmc_fs;
|
FATFS *fs = drive == DRIVE_SD ? &sd_fs : &emmc_fs;
|
||||||
if(drive == DRIVE_SD){
|
if(drive == DRIVE_SD){
|
||||||
free_space = (u32)(fs->free_clst * fs->csize >> SECTORS_TO_MIB_COEFF);
|
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",
|
s_printf(gui->txt_buf, "#96FF00 SD Card free space:# %d MiB\n#96FF00 Total size:# %d MiB\n\n",
|
||||||
free_space,
|
free_space,
|
||||||
sectors_left >> SECTORS_TO_MIB_COEFF);
|
sectors_left >> SECTORS_TO_MIB_COEFF);
|
||||||
}else{
|
}else{
|
||||||
free_space = (u32)(fs->free_clst * fs->csize >> SECTORS_TO_MIB_COEFF);
|
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",
|
s_printf(gui->txt_buf, "#96FF00 eMMC free space:# %d MiB\n#96FF00 Total size:# %d MiB\n\n",
|
||||||
free_space,
|
free_space,
|
||||||
sectors_left >> SECTORS_TO_MIB_COEFF);
|
sectors_left >> SECTORS_TO_MIB_COEFF);
|
||||||
@@ -833,7 +833,6 @@ void dump_emummc_file(emmc_tool_gui_t *gui, u32 resized_cnt, u8 drive)
|
|||||||
|
|
||||||
out_failed:
|
out_failed:
|
||||||
timer = get_tmr_s() - timer;
|
timer = get_tmr_s() - timer;
|
||||||
emmc_end();
|
|
||||||
|
|
||||||
if (res)
|
if (res)
|
||||||
{
|
{
|
||||||
@@ -861,6 +860,7 @@ out:
|
|||||||
free(txt_buf);
|
free(txt_buf);
|
||||||
free(gui->base_path);
|
free(gui->base_path);
|
||||||
sd_unmount();
|
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, u8 drive)
|
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)
|
||||||
@@ -1162,7 +1162,6 @@ void dump_emummc_raw(emmc_tool_gui_t *gui, int part_idx, u32 sector_start, u32 r
|
|||||||
|
|
||||||
out_failed:
|
out_failed:
|
||||||
timer = get_tmr_s() - timer;
|
timer = get_tmr_s() - timer;
|
||||||
emmc_end();
|
|
||||||
|
|
||||||
if (res)
|
if (res)
|
||||||
{
|
{
|
||||||
@@ -1186,4 +1185,5 @@ out:
|
|||||||
free(txt_buf);
|
free(txt_buf);
|
||||||
free(gui->base_path);
|
free(gui->base_path);
|
||||||
boot_storage_unmount();
|
boot_storage_unmount();
|
||||||
|
emmc_end();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,11 +5,14 @@
|
|||||||
#include <libs/fatfs/ff.h>
|
#include <libs/fatfs/ff.h>
|
||||||
#include <storage/emmc.h>
|
#include <storage/emmc.h>
|
||||||
#include <storage/mbr_gpt.h>
|
#include <storage/mbr_gpt.h>
|
||||||
|
#include <storage/sd.h>
|
||||||
#include <storage/sdmmc.h>
|
#include <storage/sdmmc.h>
|
||||||
#include <utils/list.h>
|
#include <utils/list.h>
|
||||||
#include <utils/ini.h>
|
#include <utils/ini.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include "gfx_utils.h"
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <utils/sprintf.h>
|
||||||
|
|
||||||
void load_emusd_cfg(emusd_cfg_t *emu_info){
|
void load_emusd_cfg(emusd_cfg_t *emu_info){
|
||||||
memset(emu_info, 0, sizeof(emusd_cfg_t));
|
memset(emu_info, 0, sizeof(emusd_cfg_t));
|
||||||
@@ -29,8 +32,10 @@ void load_emusd_cfg(emusd_cfg_t *emu_info){
|
|||||||
emu_info->enabled = atoi(kv->val);
|
emu_info->enabled = atoi(kv->val);
|
||||||
else if(!strcmp("sector", kv->key))
|
else if(!strcmp("sector", kv->key))
|
||||||
emu_info->sector = strtol(kv->val, NULL, 16);
|
emu_info->sector = strtol(kv->val, NULL, 16);
|
||||||
/*else (!strcmp("id", kv->key))
|
else if(!strcmp("path", kv->key)){
|
||||||
emu_info->id = strtol(kv->val, NULL, 16);*/
|
emu_info->path =(char*)malloc(strlen(kv->val)+1);
|
||||||
|
strcpy(emu_info->path, kv->val);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@@ -40,7 +45,7 @@ void load_emusd_cfg(emusd_cfg_t *emu_info){
|
|||||||
ini_free(&ini_sections);
|
ini_free(&ini_sections);
|
||||||
}
|
}
|
||||||
|
|
||||||
void save_emusd_cfg(u32 part_idx, u32 sector_start){
|
void save_emusd_cfg(u32 part_idx, u32 sector_start, const char *path, u8 drive){
|
||||||
boot_storage_mount();
|
boot_storage_mount();
|
||||||
|
|
||||||
char lbuf[16];
|
char lbuf[16];
|
||||||
@@ -53,7 +58,9 @@ void save_emusd_cfg(u32 part_idx, u32 sector_start){
|
|||||||
|
|
||||||
// Add config entry.
|
// Add config entry.
|
||||||
f_puts("[emusd]\nenabled=", &fp);
|
f_puts("[emusd]\nenabled=", &fp);
|
||||||
if(sector_start){
|
if((sector_start || path) && drive == DRIVE_SD) {
|
||||||
|
f_puts("1", &fp);
|
||||||
|
} else if((sector_start || path) && drive == DRIVE_EMMC){
|
||||||
f_puts("4", &fp);
|
f_puts("4", &fp);
|
||||||
}else{
|
}else{
|
||||||
f_puts("0", &fp);
|
f_puts("0", &fp);
|
||||||
@@ -66,13 +73,142 @@ void save_emusd_cfg(u32 part_idx, u32 sector_start){
|
|||||||
itoa(sector_start, lbuf, 16);
|
itoa(sector_start, lbuf, 16);
|
||||||
f_puts(lbuf, &fp);
|
f_puts(lbuf, &fp);
|
||||||
}
|
}
|
||||||
f_puts("\n", &fp);
|
|
||||||
|
|
||||||
|
if(path){
|
||||||
|
f_puts("\npath=", &fp);
|
||||||
|
f_puts(path, &fp);
|
||||||
|
}
|
||||||
|
|
||||||
|
f_puts("\n", &fp);
|
||||||
f_close(&fp);
|
f_close(&fp);
|
||||||
}
|
}
|
||||||
|
|
||||||
int create_emusd(int part_idx, u32 sector_mbr, u32 sector_start, u32 sector_size, const char *name){
|
static void update_base_path(char *path, int idx, int path_len) {
|
||||||
sfd_init(&emmc_storage, sector_start, sector_size);
|
if(idx < 10){
|
||||||
|
path[path_len] = '0';
|
||||||
|
itoa(idx, path + path_len + 1, 10);
|
||||||
|
}else{
|
||||||
|
itoa(idx, path + path_len, 10);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int create_emusd_file(u32 size_sct, u8 drive) {
|
||||||
|
static const u32 file_max_scts = 0xfe000000 / 0x200;
|
||||||
|
|
||||||
|
char path[0x80];
|
||||||
|
if (drive == DRIVE_SD){
|
||||||
|
strcpy(path, "sd:emuSD/SD");
|
||||||
|
f_mkdir("sd:emuSD");
|
||||||
|
}else {
|
||||||
|
strcpy(path, "emmc:emuSD/EMMC");
|
||||||
|
f_mkdir("emmc:emuSD");
|
||||||
|
}
|
||||||
|
int path_len = strlen(path);
|
||||||
|
|
||||||
|
f_mkdir("emuSD");
|
||||||
|
|
||||||
|
for(int j = 0; j < 100; j++){
|
||||||
|
update_base_path(path, j, path_len);
|
||||||
|
if(f_stat(path, NULL) == FR_NO_FILE){
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
f_mkdir(path);
|
||||||
|
f_mkdir(path + (drive == DRIVE_SD ? 3 : 5));
|
||||||
|
|
||||||
|
u32 base_path_len = strlen(path);
|
||||||
|
|
||||||
|
strcat(path, "/SD");
|
||||||
|
f_mkdir(path);
|
||||||
|
|
||||||
|
strcat(path, "/");
|
||||||
|
path_len = strlen(path);
|
||||||
|
|
||||||
|
// allocate files for emusd
|
||||||
|
u32 sct_left = size_sct;
|
||||||
|
u32 idx = 0;
|
||||||
|
|
||||||
|
gfx_printf("sct left 0x%x\n", sct_left);
|
||||||
|
while(sct_left) {
|
||||||
|
update_base_path(path, idx, path_len);
|
||||||
|
|
||||||
|
u32 scts = MIN(sct_left, file_max_scts);
|
||||||
|
|
||||||
|
FIL f;
|
||||||
|
int res = f_open(&f, path, FA_CREATE_ALWAYS | FA_WRITE);
|
||||||
|
if(res != FR_OK) {
|
||||||
|
gfx_printf("open fail\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
FSIZE_t seek_bytes = (FSIZE_t)scts << 9;
|
||||||
|
res = f_lseek(&f, seek_bytes);
|
||||||
|
f_close(&f);
|
||||||
|
|
||||||
|
if(res != FR_OK){
|
||||||
|
f_unlink(path);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
sct_left -= scts;
|
||||||
|
idx++;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
path[path_len] = '\0';
|
||||||
|
|
||||||
|
sfd_file_based_init(path);
|
||||||
|
|
||||||
|
u8 *buf = malloc(SZ_4M);
|
||||||
|
u32 cluster_size = 65536;
|
||||||
|
|
||||||
|
int res = f_mkfs("sfd:", FM_FAT32, cluster_size, buf, SZ_4M);
|
||||||
|
|
||||||
|
while (res != FR_OK && cluster_size > 4096){
|
||||||
|
cluster_size /= 2;
|
||||||
|
res = f_mkfs("sfd:", FM_FAT32, cluster_size, buf, SZ_4M);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(res == FR_OK){
|
||||||
|
FATFS fs;
|
||||||
|
res = f_mount(&fs, "sfd:", 1);
|
||||||
|
|
||||||
|
if(res == FR_OK){
|
||||||
|
gfx_printf("mount fail %d\n", res);
|
||||||
|
char label[0x30];
|
||||||
|
strcpy(label, "sfd:emusd");
|
||||||
|
res = f_setlabel(label);
|
||||||
|
}
|
||||||
|
|
||||||
|
f_mount(NULL, "sfd:", 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
sfd_end();
|
||||||
|
|
||||||
|
free(buf);
|
||||||
|
|
||||||
|
if(res != FR_OK) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
path[base_path_len] = '\0';
|
||||||
|
s_printf(path + base_path_len, drive == DRIVE_SD ? "/file_based" : "/file_emmc_based");
|
||||||
|
FIL f;
|
||||||
|
res = f_open(&f, path + (drive == DRIVE_SD ? 3 : 5), FA_WRITE | FA_CREATE_ALWAYS);
|
||||||
|
f_close(&f);
|
||||||
|
gfx_printf("%s %d\n", path, res);
|
||||||
|
|
||||||
|
path[base_path_len] = '\0';
|
||||||
|
save_emusd_cfg(0, 0, path + (drive == DRIVE_SD ? 3 : 5), drive);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int create_emusd(int part_idx, u32 sector_mbr, u32 sector_start, u32 sector_size, const char *name, u8 drive){
|
||||||
|
sdmmc_storage_t *storage = drive == DRIVE_SD ? &sd_storage : &emmc_storage;
|
||||||
|
|
||||||
|
sfd_init(storage, sector_start, sector_size);
|
||||||
|
|
||||||
u8 *buf = malloc(SZ_4M);
|
u8 *buf = malloc(SZ_4M);
|
||||||
FIL f;
|
FIL f;
|
||||||
@@ -109,7 +245,7 @@ int create_emusd(int part_idx, u32 sector_mbr, u32 sector_start, u32 sector_size
|
|||||||
mbr.partitions[0].size_sct = sector_size;
|
mbr.partitions[0].size_sct = sector_size;
|
||||||
mbr.partitions[0].type = 0x0c;
|
mbr.partitions[0].type = 0x0c;
|
||||||
|
|
||||||
mkfs_error = sdmmc_storage_write(&emmc_storage, sector_mbr, 1, &mbr) ? FR_OK : FR_DISK_ERR;
|
mkfs_error = sdmmc_storage_write(storage, sector_mbr, 1, &mbr) ? FR_OK : FR_DISK_ERR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -119,5 +255,22 @@ int create_emusd(int part_idx, u32 sector_mbr, u32 sector_start, u32 sector_size
|
|||||||
|
|
||||||
sfd_end();
|
sfd_end();
|
||||||
|
|
||||||
return mkfs_error;
|
if(mkfs_error != FR_OK){
|
||||||
|
return mkfs_error;
|
||||||
|
}
|
||||||
|
|
||||||
|
char path[0x80];
|
||||||
|
strcpy(path, "emuSD");
|
||||||
|
f_mkdir(path);
|
||||||
|
s_printf(path + strlen(path), "/RAW_%s%d", drive == DRIVE_SD ? "SD" : "EMMC", part_idx);
|
||||||
|
f_mkdir(path);
|
||||||
|
strcat(path, "/raw_emmc_based");
|
||||||
|
|
||||||
|
f_open(&f, path, FA_CREATE_ALWAYS | FA_WRITE);
|
||||||
|
f_write(&f, §or_mbr, 4, NULL);
|
||||||
|
f_close(&f);
|
||||||
|
|
||||||
|
save_emusd_cfg(part_idx, sector_mbr, NULL, drive);
|
||||||
|
|
||||||
|
return FR_OK;
|
||||||
}
|
}
|
||||||
@@ -7,10 +7,11 @@ typedef struct _emusd_cfg_t{
|
|||||||
// 0: disabled, 1: enabled
|
// 0: disabled, 1: enabled
|
||||||
int enabled;
|
int enabled;
|
||||||
u32 sector;
|
u32 sector;
|
||||||
|
char *path;
|
||||||
} emusd_cfg_t;
|
} emusd_cfg_t;
|
||||||
|
|
||||||
void load_emusd_cfg(emusd_cfg_t *emu_info);
|
void load_emusd_cfg(emusd_cfg_t *emu_info);
|
||||||
void save_emusd_cfg(u32 part_idx, u32 sector_start);
|
void save_emusd_cfg(u32 part_idx, u32 sector_start, const char *path, u8 drive);
|
||||||
int create_emusd(int part_idx, u32 sector_mbr, u32 sector_start, u32 sector_size, const char *name);
|
int create_emusd(int part_idx, u32 sector_mbr, u32 sector_start, u32 sector_size, const char *name, u8 drive);
|
||||||
|
int create_emusd_file(u32 size_sct, u8 drive);
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2018-2024 CTCaer
|
* Copyright (c) 2018-2025 CTCaer
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
* under the terms and conditions of the GNU General Public License,
|
* under the terms and conditions of the GNU General Public License,
|
||||||
@@ -817,7 +817,7 @@ bool nyx_emmc_check_battery_enough()
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _nyx_sd_card_issues(void *param)
|
static void _nyx_sd_card_issues_warning(void *param)
|
||||||
{
|
{
|
||||||
lv_obj_t *dark_bg = lv_obj_create(lv_scr_act(), NULL);
|
lv_obj_t *dark_bg = lv_obj_create(lv_scr_act(), NULL);
|
||||||
lv_obj_set_style(dark_bg, &mbox_darken);
|
lv_obj_set_style(dark_bg, &mbox_darken);
|
||||||
@@ -828,7 +828,7 @@ static void _nyx_sd_card_issues(void *param)
|
|||||||
lv_mbox_set_recolor_text(mbox, true);
|
lv_mbox_set_recolor_text(mbox, true);
|
||||||
|
|
||||||
lv_mbox_set_text(mbox,
|
lv_mbox_set_text(mbox,
|
||||||
"#FF8000 SD Card Issues Check#\n\n"
|
"#FF8000 SD Card Issues Warning#\n\n"
|
||||||
"#FFDD00 The SD Card is initialized in 1-bit mode!#\n"
|
"#FFDD00 The SD Card is initialized in 1-bit mode!#\n"
|
||||||
"#FFDD00 This might mean detached or broken connector!#\n\n"
|
"#FFDD00 This might mean detached or broken connector!#\n\n"
|
||||||
"You might want to check\n#C7EA46 Console Info# -> #C7EA46 microSD#");
|
"You might want to check\n#C7EA46 Console Info# -> #C7EA46 microSD#");
|
||||||
@@ -868,7 +868,7 @@ void nyx_window_toggle_buttons(lv_obj_t *win, bool disable)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
lv_res_t lv_win_close_action_custom(lv_obj_t * btn)
|
lv_res_t nyx_win_close_action_custom(lv_obj_t * btn)
|
||||||
{
|
{
|
||||||
close_btn = NULL;
|
close_btn = NULL;
|
||||||
|
|
||||||
@@ -888,7 +888,7 @@ lv_obj_t *nyx_create_standard_window(const char *win_title)
|
|||||||
lv_win_set_style(win, LV_WIN_STYLE_BG, &win_bg_style);
|
lv_win_set_style(win, LV_WIN_STYLE_BG, &win_bg_style);
|
||||||
lv_obj_set_size(win, LV_HOR_RES, LV_VER_RES);
|
lv_obj_set_size(win, LV_HOR_RES, LV_VER_RES);
|
||||||
|
|
||||||
close_btn = lv_win_add_btn(win, NULL, SYMBOL_CLOSE" Close", lv_win_close_action_custom);
|
close_btn = lv_win_add_btn(win, NULL, SYMBOL_CLOSE" Close", nyx_win_close_action_custom);
|
||||||
|
|
||||||
return win;
|
return win;
|
||||||
}
|
}
|
||||||
@@ -1015,7 +1015,7 @@ static void _check_sd_card_removed(void *params)
|
|||||||
}
|
}
|
||||||
|
|
||||||
lv_task_t *task_emmc_errors;
|
lv_task_t *task_emmc_errors;
|
||||||
static void _nyx_emmc_issues(void *params)
|
static void _nyx_emmc_issues_warning(void *params)
|
||||||
{
|
{
|
||||||
if (emmc_get_mode() < EMMC_MMC_HS400)
|
if (emmc_get_mode() < EMMC_MMC_HS400)
|
||||||
{
|
{
|
||||||
@@ -1031,8 +1031,8 @@ static void _nyx_emmc_issues(void *params)
|
|||||||
lv_mbox_set_recolor_text(mbox, true);
|
lv_mbox_set_recolor_text(mbox, true);
|
||||||
|
|
||||||
lv_mbox_set_text(mbox,
|
lv_mbox_set_text(mbox,
|
||||||
"#FF8000 eMMC Issues Check#\n\n"
|
"#FF8000 eMMC Issues Warning#\n\n"
|
||||||
"#FFDD00 Your eMMC is initialized in slower mode!#\n"
|
"#FFDD00 Your eMMC is initialized in a slower mode!#\n"
|
||||||
"#FFDD00 This might mean hardware issues!#\n\n"
|
"#FFDD00 This might mean hardware issues!#\n\n"
|
||||||
"You might want to check\n#C7EA46 Console Info# -> #C7EA46 eMMC#");
|
"You might want to check\n#C7EA46 Console Info# -> #C7EA46 eMMC#");
|
||||||
|
|
||||||
@@ -1239,9 +1239,9 @@ static void _create_tab_about(lv_theme_t * th, lv_obj_t * parent)
|
|||||||
lv_label_set_recolor(lbl_credits, true);
|
lv_label_set_recolor(lbl_credits, true);
|
||||||
lv_label_set_static_text(lbl_credits,
|
lv_label_set_static_text(lbl_credits,
|
||||||
"#C7EA46 hekate# (c) 2018, #C7EA46 naehrwert#, #C7EA46 st4rk#\n"
|
"#C7EA46 hekate# (c) 2018, #C7EA46 naehrwert#, #C7EA46 st4rk#\n"
|
||||||
" (c) 2018-2024, #C7EA46 CTCaer#\n"
|
" (c) 2018-2025, #C7EA46 CTCaer#\n"
|
||||||
"\n"
|
"\n"
|
||||||
"#C7EA46 Nyx# (c) 2019-2024, #C7EA46 CTCaer#\n"
|
"#C7EA46 Nyx# (c) 2019-2025, #C7EA46 CTCaer#\n"
|
||||||
"\n"
|
"\n"
|
||||||
"Thanks to: #00CCFF derrek, nedwill, plutoo, #\n"
|
"Thanks to: #00CCFF derrek, nedwill, plutoo, #\n"
|
||||||
" #00CCFF shuffle2, smea, thexyz, yellows8 #\n"
|
" #00CCFF shuffle2, smea, thexyz, yellows8 #\n"
|
||||||
@@ -2087,6 +2087,7 @@ static void _create_status_bar(lv_theme_t * th)
|
|||||||
{
|
{
|
||||||
static lv_obj_t *status_bar_bg;
|
static lv_obj_t *status_bar_bg;
|
||||||
status_bar_bg = lv_cont_create(lv_layer_top(), NULL);
|
status_bar_bg = lv_cont_create(lv_layer_top(), NULL);
|
||||||
|
status_bar.bar_bg = status_bar_bg;
|
||||||
|
|
||||||
static lv_style_t status_bar_style;
|
static lv_style_t status_bar_style;
|
||||||
lv_style_copy(&status_bar_style, &lv_style_plain_color);
|
lv_style_copy(&status_bar_style, &lv_style_plain_color);
|
||||||
@@ -2139,9 +2140,9 @@ static void _create_status_bar(lv_theme_t * th)
|
|||||||
lv_obj_set_size(btn_mid, LV_DPI * 5 / 2, LV_DPI / 2);
|
lv_obj_set_size(btn_mid, LV_DPI * 5 / 2, LV_DPI / 2);
|
||||||
lv_obj_align(btn_mid, NULL, LV_ALIGN_CENTER, 0, 0);
|
lv_obj_align(btn_mid, NULL, LV_ALIGN_CENTER, 0, 0);
|
||||||
status_bar.mid = btn_mid;
|
status_bar.mid = btn_mid;
|
||||||
lv_obj_set_opa_scale(status_bar.mid, LV_OPA_0);
|
lv_obj_set_opa_scale(btn_mid, LV_OPA_0);
|
||||||
lv_obj_set_opa_scale_enable(status_bar.mid, true);
|
lv_obj_set_opa_scale_enable(btn_mid, true);
|
||||||
lv_obj_set_click(status_bar.mid, false);
|
lv_obj_set_click(btn_mid, false);
|
||||||
lv_btn_set_action(btn_mid, LV_BTN_ACTION_CLICK, _save_options_action);
|
lv_btn_set_action(btn_mid, LV_BTN_ACTION_CLICK, _save_options_action);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2362,7 +2363,7 @@ static void _nyx_main_menu(lv_theme_t * th)
|
|||||||
|
|
||||||
lv_task_create(_check_sd_card_removed, 2000, LV_TASK_PRIO_LOWEST, NULL);
|
lv_task_create(_check_sd_card_removed, 2000, LV_TASK_PRIO_LOWEST, NULL);
|
||||||
|
|
||||||
task_emmc_errors = lv_task_create(_nyx_emmc_issues, 2000, LV_TASK_PRIO_LOWEST, NULL);
|
task_emmc_errors = lv_task_create(_nyx_emmc_issues_warning, 2000, LV_TASK_PRIO_LOWEST, NULL);
|
||||||
lv_task_ready(task_emmc_errors);
|
lv_task_ready(task_emmc_errors);
|
||||||
|
|
||||||
// Create top level global line separators.
|
// Create top level global line separators.
|
||||||
@@ -2462,7 +2463,7 @@ void nyx_load_and_run()
|
|||||||
// Check if sd card issues.
|
// Check if sd card issues.
|
||||||
if (sd_get_mode() == SD_1BIT_HS25)
|
if (sd_get_mode() == SD_1BIT_HS25)
|
||||||
{
|
{
|
||||||
lv_task_t *task_run_sd_errors = lv_task_create(_nyx_sd_card_issues, LV_TASK_ONESHOT, LV_TASK_PRIO_LOWEST, NULL);
|
lv_task_t *task_run_sd_errors = lv_task_create(_nyx_sd_card_issues_warning, LV_TASK_ONESHOT, LV_TASK_PRIO_LOWEST, NULL);
|
||||||
lv_task_once(task_run_sd_errors);
|
lv_task_once(task_run_sd_errors);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2018-2019 CTCaer
|
* Copyright (c) 2018-2025 CTCaer
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
* under the terms and conditions of the GNU General Public License,
|
* under the terms and conditions of the GNU General Public License,
|
||||||
@@ -36,6 +36,7 @@ typedef struct _emmc_tool_gui_t
|
|||||||
|
|
||||||
typedef struct _gui_status_bar_ctx
|
typedef struct _gui_status_bar_ctx
|
||||||
{
|
{
|
||||||
|
lv_obj_t *bar_bg;
|
||||||
lv_obj_t *mid;
|
lv_obj_t *mid;
|
||||||
lv_obj_t *time_temp;
|
lv_obj_t *time_temp;
|
||||||
lv_obj_t *temp_symbol;
|
lv_obj_t *temp_symbol;
|
||||||
@@ -72,6 +73,7 @@ void reload_nyx();
|
|||||||
lv_img_dsc_t *bmp_to_lvimg_obj(const char *path);
|
lv_img_dsc_t *bmp_to_lvimg_obj(const char *path);
|
||||||
lv_res_t mbox_action(lv_obj_t * btns, const char * txt);
|
lv_res_t mbox_action(lv_obj_t * btns, const char * txt);
|
||||||
bool nyx_emmc_check_battery_enough();
|
bool nyx_emmc_check_battery_enough();
|
||||||
|
lv_res_t nyx_win_close_action_custom(lv_obj_t * btn);
|
||||||
void nyx_window_toggle_buttons(lv_obj_t *win, bool disable);
|
void nyx_window_toggle_buttons(lv_obj_t *win, bool disable);
|
||||||
lv_obj_t *nyx_create_standard_window(const char *win_title);
|
lv_obj_t *nyx_create_standard_window(const char *win_title);
|
||||||
lv_obj_t *nyx_create_window_custom_close_btn(const char *win_title, lv_action_t rel_action);
|
lv_obj_t *nyx_create_window_custom_close_btn(const char *win_title, lv_action_t rel_action);
|
||||||
|
|||||||
@@ -240,15 +240,15 @@ static lv_res_t _emmc_backup_buttons_raw_toggle(lv_obj_t *btn)
|
|||||||
else // Backup/Restore from and to emuMMC.
|
else // Backup/Restore from and to emuMMC.
|
||||||
{
|
{
|
||||||
if (!emmc_btn_ctxt.restore)
|
if (!emmc_btn_ctxt.restore)
|
||||||
lv_label_set_static_text(lv_obj_get_child(emmc_btn_ctxt.emmc_boot, NULL), SYMBOL_UPLOAD" SD emuMMC BOOT0 & BOOT1");
|
lv_label_set_static_text(lv_obj_get_child(emmc_btn_ctxt.emmc_boot, NULL), SYMBOL_UPLOAD" emuMMC BOOT0 & BOOT1");
|
||||||
else
|
else
|
||||||
lv_label_set_static_text(lv_obj_get_child(emmc_btn_ctxt.emmc_boot, NULL), SYMBOL_DOWNLOAD" SD emuMMC BOOT0 & BOOT1");
|
lv_label_set_static_text(lv_obj_get_child(emmc_btn_ctxt.emmc_boot, NULL), SYMBOL_DOWNLOAD" emuMMC BOOT0 & BOOT1");
|
||||||
lv_obj_realign(emmc_btn_ctxt.emmc_boot);
|
lv_obj_realign(emmc_btn_ctxt.emmc_boot);
|
||||||
|
|
||||||
if (!emmc_btn_ctxt.restore)
|
if (!emmc_btn_ctxt.restore)
|
||||||
lv_label_set_static_text(lv_obj_get_child(emmc_btn_ctxt.emmc_raw_gpp, NULL), SYMBOL_UPLOAD" SD emuMMC RAW GPP");
|
lv_label_set_static_text(lv_obj_get_child(emmc_btn_ctxt.emmc_raw_gpp, NULL), SYMBOL_UPLOAD" emuMMC RAW GPP");
|
||||||
else
|
else
|
||||||
lv_label_set_static_text(lv_obj_get_child(emmc_btn_ctxt.emmc_raw_gpp, NULL), SYMBOL_DOWNLOAD" SD emuMMC RAW GPP");
|
lv_label_set_static_text(lv_obj_get_child(emmc_btn_ctxt.emmc_raw_gpp, NULL), SYMBOL_DOWNLOAD" emuMMC RAW GPP");
|
||||||
lv_obj_realign(emmc_btn_ctxt.emmc_raw_gpp);
|
lv_obj_realign(emmc_btn_ctxt.emmc_raw_gpp);
|
||||||
|
|
||||||
lv_obj_set_click(emmc_btn_ctxt.emmc_sys, false);
|
lv_obj_set_click(emmc_btn_ctxt.emmc_sys, false);
|
||||||
@@ -454,7 +454,7 @@ lv_res_t create_window_backup_restore_tool(lv_obj_t *btn)
|
|||||||
|
|
||||||
lv_obj_t *sd_emummc_raw = lv_btn_create(h3, NULL);
|
lv_obj_t *sd_emummc_raw = lv_btn_create(h3, NULL);
|
||||||
nyx_create_onoff_button(lv_theme_get_current(), h3,
|
nyx_create_onoff_button(lv_theme_get_current(), h3,
|
||||||
sd_emummc_raw, SYMBOL_SD" SD emuMMC Raw Partition", _emmc_backup_buttons_raw_toggle, false);
|
sd_emummc_raw, SYMBOL_SD" emuMMC Raw Partition", _emmc_backup_buttons_raw_toggle, false);
|
||||||
emmc_btn_ctxt.raw_emummc = false;
|
emmc_btn_ctxt.raw_emummc = false;
|
||||||
|
|
||||||
return LV_RES_OK;
|
return LV_RES_OK;
|
||||||
|
|||||||
@@ -81,8 +81,7 @@ static emummc_part_cfg_t emummc_part_cfg;
|
|||||||
|
|
||||||
static lv_res_t _action_emummc_window_close(lv_obj_t *btn)
|
static lv_res_t _action_emummc_window_close(lv_obj_t *btn)
|
||||||
{
|
{
|
||||||
lv_win_close_action(btn);
|
nyx_win_close_action_custom(btn);
|
||||||
close_btn = NULL;
|
|
||||||
|
|
||||||
// Delete and relaunch main emuMMC window.
|
// Delete and relaunch main emuMMC window.
|
||||||
lv_obj_clean(emummc_parent_cont);
|
lv_obj_clean(emummc_parent_cont);
|
||||||
@@ -865,7 +864,7 @@ static lv_res_t _create_mbox_emummc_create(lv_obj_t *btn)
|
|||||||
"Welcome to #C7EA46 emuMMC# creation tool!\n\n"
|
"Welcome to #C7EA46 emuMMC# creation tool!\n\n"
|
||||||
"Please choose what type of emuMMC you want to create.\n"
|
"Please choose what type of emuMMC you want to create.\n"
|
||||||
"#FF8000 File based# is saved as files in\nthe SD or eMMC FAT partition.\n"
|
"#FF8000 File based# is saved as files in\nthe SD or eMMC FAT partition.\n"
|
||||||
"#FF8000 Partition based# is saved as raw image in a\navailable SD or eMMC partition.");
|
"#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_select_type_action);
|
lv_mbox_add_btns(mbox, mbox_btn_map, _create_emummc_select_type_action);
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2018 naehrwert
|
* Copyright (c) 2018 naehrwert
|
||||||
* Copyright (c) 2018-2024 CTCaer
|
* Copyright (c) 2018-2025 CTCaer
|
||||||
* Copyright (c) 2018 balika011
|
* Copyright (c) 2018 balika011
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
@@ -25,6 +25,8 @@
|
|||||||
#include <libs/fatfs/ff.h>
|
#include <libs/fatfs/ff.h>
|
||||||
#include <storage/boot_storage.h>
|
#include <storage/boot_storage.h>
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
#define SECTORS_TO_MIB_COEFF 11
|
#define SECTORS_TO_MIB_COEFF 11
|
||||||
|
|
||||||
extern hekate_config h_cfg;
|
extern hekate_config h_cfg;
|
||||||
@@ -352,9 +354,21 @@ out:
|
|||||||
return LV_RES_OK;
|
return LV_RES_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static lv_res_t _create_window_fuses_info_status(lv_obj_t *btn)
|
static lv_obj_t *hw_info_ver = NULL;
|
||||||
|
static lv_res_t _action_win_hw_info_status_close(lv_obj_t *btn)
|
||||||
{
|
{
|
||||||
lv_obj_t *win = nyx_create_standard_window(SYMBOL_CHIP" HW & Fuses Info");
|
if (hw_info_ver)
|
||||||
|
{
|
||||||
|
lv_obj_del(hw_info_ver);
|
||||||
|
hw_info_ver = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return nyx_win_close_action_custom(btn);
|
||||||
|
}
|
||||||
|
|
||||||
|
static lv_res_t _create_window_hw_info_status(lv_obj_t *btn)
|
||||||
|
{
|
||||||
|
lv_obj_t *win = nyx_create_window_custom_close_btn(SYMBOL_CHIP" HW & Fuses Info", _action_win_hw_info_status_close);
|
||||||
lv_win_add_btn(win, NULL, SYMBOL_DOWNLOAD" Dump fuses", _fuse_dump_window_action);
|
lv_win_add_btn(win, NULL, SYMBOL_DOWNLOAD" Dump fuses", _fuse_dump_window_action);
|
||||||
lv_win_add_btn(win, NULL, SYMBOL_INFO" CAL0 Info", _create_mbox_cal0);
|
lv_win_add_btn(win, NULL, SYMBOL_INFO" CAL0 Info", _create_mbox_cal0);
|
||||||
|
|
||||||
@@ -366,6 +380,14 @@ static lv_res_t _create_window_fuses_info_status(lv_obj_t *btn)
|
|||||||
lv_label_set_recolor(lb_desc, true);
|
lv_label_set_recolor(lb_desc, true);
|
||||||
lv_label_set_style(lb_desc, &monospace_text);
|
lv_label_set_style(lb_desc, &monospace_text);
|
||||||
|
|
||||||
|
char version[32];
|
||||||
|
s_printf(version, "%s%d.%d.%d%c", NYX_VER_RL ? "v" : "", NYX_VER_MJ, NYX_VER_MN, NYX_VER_HF, NYX_VER_RL > 'A' ? NYX_VER_RL : 0);
|
||||||
|
lv_obj_t * lbl_ver = lv_label_create(lv_scr_act(), NULL);
|
||||||
|
lv_label_set_style(lbl_ver, &hint_small_style_white);
|
||||||
|
lv_label_set_text(lbl_ver, version);
|
||||||
|
lv_obj_align(lbl_ver, status_bar.bar_bg, LV_ALIGN_OUT_TOP_RIGHT, -LV_DPI * 9 / 23, -LV_DPI * 2 / 13);
|
||||||
|
hw_info_ver = lbl_ver;
|
||||||
|
|
||||||
lv_label_set_static_text(lb_desc,
|
lv_label_set_static_text(lb_desc,
|
||||||
"#FF8000 SoC:#\n"
|
"#FF8000 SoC:#\n"
|
||||||
"#FF8000 SKU:#\n"
|
"#FF8000 SKU:#\n"
|
||||||
@@ -591,7 +613,10 @@ static lv_res_t _create_window_fuses_info_status(lv_obj_t *btn)
|
|||||||
strcpy(fuses_hos_version, "17.0.0 - 18.1.0");
|
strcpy(fuses_hos_version, "17.0.0 - 18.1.0");
|
||||||
break;
|
break;
|
||||||
case 20:
|
case 20:
|
||||||
strcpy(fuses_hos_version, "19.0.0+");
|
strcpy(fuses_hos_version, "19.0.0 - 19.0.1");
|
||||||
|
break;
|
||||||
|
case 21:
|
||||||
|
strcpy(fuses_hos_version, "20.0.0+");
|
||||||
break;
|
break;
|
||||||
case 255:
|
case 255:
|
||||||
strcpy(fuses_hos_version, "#FFD000 Overburnt#");
|
strcpy(fuses_hos_version, "#FFD000 Overburnt#");
|
||||||
@@ -664,7 +689,7 @@ static lv_res_t _create_window_fuses_info_status(lv_obj_t *btn)
|
|||||||
u32 ranks = EMC(EMC_ADR_CFG) + 1;
|
u32 ranks = EMC(EMC_ADR_CFG) + 1;
|
||||||
u32 channels = (EMC(EMC_FBIO_CFG7) >> 1) & 3;
|
u32 channels = (EMC(EMC_FBIO_CFG7) >> 1) & 3;
|
||||||
channels = (channels & 1) + ((channels & 2) >> 1);
|
channels = (channels & 1) + ((channels & 2) >> 1);
|
||||||
s_printf(txt_buf, "#00DDFF %s SDRAM ##FF8000 (Ch 0 | Ch 1):#\n#FF8000 Vendor:# ", h_cfg.t210b01 ? "LPDDR4X" : "LPDDR4");
|
s_printf(txt_buf, "#00DDFF %s SDRAM ##FF8000 (Module 0 | 1):#\n#FF8000 Vendor:# ", h_cfg.t210b01 ? "LPDDR4X" : "LPDDR4");
|
||||||
switch (ram_vendor.chip0.rank0_ch0)
|
switch (ram_vendor.chip0.rank0_ch0)
|
||||||
{
|
{
|
||||||
case 1:
|
case 1:
|
||||||
@@ -736,49 +761,76 @@ static lv_res_t _create_window_fuses_info_status(lv_obj_t *btn)
|
|||||||
s_printf(txt_buf + strlen(txt_buf), "#FF8000 Unknown# (%d)", ram_vendor.chip1.rank0_ch0);
|
s_printf(txt_buf + strlen(txt_buf), "#FF8000 Unknown# (%d)", ram_vendor.chip1.rank0_ch0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
s_printf(txt_buf + strlen(txt_buf), "\n#FF8000 Rev ID:# %X.%02X #FF8000 |# %X.%02X\n#FF8000 Density:# %d",
|
|
||||||
ram_rev0.chip0.rank0_ch0, ram_rev1.chip0.rank0_ch0, ram_rev0.chip1.rank0_ch0, ram_rev1.chip1.rank0_ch0, ranks * channels);
|
s_printf(txt_buf + strlen(txt_buf), "\n#FF8000 Rev ID:# %X.%02X #FF8000 |# %X.%02X\n#FF8000 Density:# ",
|
||||||
|
ram_rev0.chip0.rank0_ch0, ram_rev1.chip0.rank0_ch0, ram_rev0.chip1.rank0_ch0, ram_rev1.chip1.rank0_ch0);
|
||||||
|
|
||||||
|
u32 actual_ranks = (ram_vendor.chip0.rank0_ch0 == ram_vendor.chip0.rank1_ch0 &&
|
||||||
|
ram_vendor.chip0.rank0_ch1 == ram_vendor.chip0.rank1_ch1 &&
|
||||||
|
ram_rev0.chip0.rank0_ch0 == ram_rev0.chip0.rank1_ch0 &&
|
||||||
|
ram_rev0.chip0.rank0_ch1 == ram_rev0.chip0.rank1_ch1 &&
|
||||||
|
ram_rev1.chip0.rank0_ch0 == ram_rev1.chip0.rank1_ch0 &&
|
||||||
|
ram_rev1.chip0.rank0_ch1 == ram_rev1.chip0.rank1_ch1 &&
|
||||||
|
ram_density.chip0.rank0_ch0 == ram_density.chip0.rank1_ch0 &&
|
||||||
|
ram_density.chip0.rank0_ch1 == ram_density.chip0.rank1_ch1)
|
||||||
|
? 2 : 1;
|
||||||
|
bool rank_bad = ranks != actual_ranks;
|
||||||
|
s_printf(txt_buf + strlen(txt_buf), "%s %d x %s", rank_bad ? "#FFDD00" : "", actual_ranks * channels, rank_bad ? "#" : "");
|
||||||
|
|
||||||
switch ((ram_density.chip0.rank0_ch0 & 0x3C) >> 2)
|
switch ((ram_density.chip0.rank0_ch0 & 0x3C) >> 2)
|
||||||
{
|
{
|
||||||
case 2:
|
case 2:
|
||||||
strcat(txt_buf, " x 512MB");
|
strcat(txt_buf, "512MB");
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
strcat(txt_buf, " x 768MB");
|
strcat(txt_buf, "768MB");
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
strcat(txt_buf, " x 1GB");
|
strcat(txt_buf, "1GB");
|
||||||
break;
|
break;
|
||||||
case 5:
|
case 5:
|
||||||
strcat(txt_buf, " x 1.5GB");
|
strcat(txt_buf, "1.5GB");
|
||||||
break;
|
break;
|
||||||
case 6:
|
case 6:
|
||||||
strcat(txt_buf, " x 2GB");
|
strcat(txt_buf, "2GB");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
s_printf(txt_buf + strlen(txt_buf), " x Unk (%d)", (ram_density.chip0.rank0_ch0 & 0x3C) >> 2);
|
s_printf(txt_buf + strlen(txt_buf), "Unk (%d)", (ram_density.chip0.rank0_ch0 & 0x3C) >> 2);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
s_printf(txt_buf + strlen(txt_buf), " #FF8000 |# %d", ranks * channels);
|
|
||||||
|
actual_ranks = (ram_vendor.chip1.rank0_ch0 == ram_vendor.chip1.rank1_ch0 &&
|
||||||
|
ram_vendor.chip1.rank0_ch1 == ram_vendor.chip1.rank1_ch1 &&
|
||||||
|
ram_rev0.chip1.rank0_ch0 == ram_rev0.chip1.rank1_ch0 &&
|
||||||
|
ram_rev0.chip1.rank0_ch1 == ram_rev0.chip1.rank1_ch1 &&
|
||||||
|
ram_rev1.chip1.rank0_ch0 == ram_rev1.chip1.rank1_ch0 &&
|
||||||
|
ram_rev1.chip1.rank0_ch1 == ram_rev1.chip1.rank1_ch1 &&
|
||||||
|
ram_density.chip1.rank0_ch0 == ram_density.chip1.rank1_ch0 &&
|
||||||
|
ram_density.chip1.rank0_ch1 == ram_density.chip1.rank1_ch1)
|
||||||
|
? 2 : 1;
|
||||||
|
rank_bad = ranks != actual_ranks;
|
||||||
|
|
||||||
|
s_printf(txt_buf + strlen(txt_buf), " #FF8000 |# %s %d x %s", rank_bad ? "#FFDD00" : "", actual_ranks * channels, rank_bad ? "#" : "");
|
||||||
|
|
||||||
switch ((ram_density.chip1.rank0_ch0 & 0x3C) >> 2)
|
switch ((ram_density.chip1.rank0_ch0 & 0x3C) >> 2)
|
||||||
{
|
{
|
||||||
case 2:
|
case 2:
|
||||||
strcat(txt_buf, " x 512MB");
|
strcat(txt_buf, "512MB");
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
strcat(txt_buf, " x 768MB");
|
strcat(txt_buf, "768MB");
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
strcat(txt_buf, " x 1GB");
|
strcat(txt_buf, "1GB");
|
||||||
break;
|
break;
|
||||||
case 5:
|
case 5:
|
||||||
strcat(txt_buf, " x 1.5GB");
|
strcat(txt_buf, "1.5GB");
|
||||||
break;
|
break;
|
||||||
case 6:
|
case 6:
|
||||||
strcat(txt_buf, " x 2GB");
|
strcat(txt_buf, "2GB");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
s_printf(txt_buf + strlen(txt_buf), " x Unk (%d)", (ram_density.chip1.rank0_ch0 & 0x3C) >> 2);
|
s_printf(txt_buf + strlen(txt_buf), "Unk (%d)", (ram_density.chip1.rank0_ch0 & 0x3C) >> 2);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
strcat(txt_buf, "\n\n");
|
strcat(txt_buf, "\n\n");
|
||||||
@@ -941,13 +993,13 @@ static lv_res_t _create_window_fuses_info_status(lv_obj_t *btn)
|
|||||||
if (touch_panel)
|
if (touch_panel)
|
||||||
panel_ic_paired = touch_panel->idx == 0; // NISSHA NFT-K12D.
|
panel_ic_paired = touch_panel->idx == 0; // NISSHA NFT-K12D.
|
||||||
break;
|
break;
|
||||||
case 0x98000004: // New 6.2" panel?
|
// case 0x98000004: // New 6.2" panel?
|
||||||
case 0x50000001:
|
// case 0x50000001:
|
||||||
case 0x50000002:
|
// case 0x50000002:
|
||||||
strcat(txt_buf, "FST2 UNK");
|
// strcat(txt_buf, "FST2 UNK");
|
||||||
if (touch_panel)
|
// if (touch_panel)
|
||||||
panel_ic_paired = touch_panel->idx == 0;
|
// panel_ic_paired = touch_panel->idx == 0;
|
||||||
break;
|
// break;
|
||||||
case 0x001A0300:
|
case 0x001A0300:
|
||||||
case 0x32000102:
|
case 0x32000102:
|
||||||
strcat(txt_buf, "4CD60D/2");
|
strcat(txt_buf, "4CD60D/2");
|
||||||
@@ -975,7 +1027,7 @@ static lv_res_t _create_window_fuses_info_status(lv_obj_t *btn)
|
|||||||
panel_ic_paired = touch_panel->idx == 4; // Samsung BH2109.
|
panel_ic_paired = touch_panel->idx == 4; // Samsung BH2109.
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
strcat(txt_buf, "#FF8000 Unknown#");
|
strcat(txt_buf, "#FF8000 Contact me#");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1000,9 +1052,6 @@ static lv_res_t _create_window_fuses_info_status(lv_obj_t *btn)
|
|||||||
lv_obj_set_width(lb_desc2, lv_obj_get_width(desc2));
|
lv_obj_set_width(lb_desc2, lv_obj_get_width(desc2));
|
||||||
lv_obj_align(desc2, val, LV_ALIGN_OUT_RIGHT_MID, LV_DPI / 4, 0);
|
lv_obj_align(desc2, val, LV_ALIGN_OUT_RIGHT_MID, LV_DPI / 4, 0);
|
||||||
|
|
||||||
if (!btn)
|
|
||||||
_create_mbox_cal0(NULL);
|
|
||||||
|
|
||||||
return LV_RES_OK;
|
return LV_RES_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1300,12 +1349,11 @@ static lv_res_t _create_mbox_benchmark(bool sd_bench)
|
|||||||
static const char * mbox_btn_map[] = { "\251", "\222OK", "\251", "" };
|
static const char * mbox_btn_map[] = { "\251", "\222OK", "\251", "" };
|
||||||
lv_obj_t * mbox = lv_mbox_create(dark_bg, NULL);
|
lv_obj_t * mbox = lv_mbox_create(dark_bg, NULL);
|
||||||
lv_mbox_set_recolor_text(mbox, true);
|
lv_mbox_set_recolor_text(mbox, true);
|
||||||
lv_obj_set_width(mbox, LV_HOR_RES / 7 * 4);
|
lv_obj_set_width(mbox, LV_HOR_RES * 3 / 7);
|
||||||
|
|
||||||
char *txt_buf = (char *)malloc(SZ_16K);
|
char *txt_buf = (char *)malloc(SZ_16K);
|
||||||
|
|
||||||
s_printf(txt_buf, "#FF8000 %s Benchmark#\n[Raw Reads] Abort: VOL- & VOL+",
|
s_printf(txt_buf, "#FF8000 %s Benchmark#\n[Raw Reads] Abort: VOL- & VOL+", sd_bench ? "SD Card" : "eMMC");
|
||||||
sd_bench ? "SD Card" : "eMMC");
|
|
||||||
|
|
||||||
lv_mbox_set_text(mbox, txt_buf);
|
lv_mbox_set_text(mbox, txt_buf);
|
||||||
txt_buf[0] = 0;
|
txt_buf[0] = 0;
|
||||||
@@ -1354,30 +1402,60 @@ static lv_res_t _create_mbox_benchmark(bool sd_bench)
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set benchmark parameters.
|
||||||
|
const u32 sct_blk_seq = 0x8000; // 16MB. A2 spec denotes 4MB, but using older big AU.
|
||||||
|
const u32 sct_blk_4kb = 8; // 4KB.
|
||||||
|
const u32 sct_rem_seq = 0x200000; // 1GB. A2 spec.
|
||||||
|
const u32 sct_rem_4kb = 0x80000; // 256MB. A2 spec.
|
||||||
|
const u32 sct_num_1mb = 0x800; // 1MB.
|
||||||
|
const u32 size_bytes_seq = sct_rem_seq * SDMMC_DAT_BLOCKSIZE;
|
||||||
|
const u32 size_bytes_4kb = sct_rem_4kb * SDMMC_DAT_BLOCKSIZE;
|
||||||
|
|
||||||
|
// Set calculation divider. 1000 or 1024. (Does not affect IOPS).
|
||||||
|
u32 mb_div = 1000; // Unfortunately most software uses fake MB.
|
||||||
|
|
||||||
|
char *mbs_text;
|
||||||
|
switch (mb_div)
|
||||||
|
{
|
||||||
|
case 1000:
|
||||||
|
mbs_text = "MB/s";
|
||||||
|
break;
|
||||||
|
case 1024:
|
||||||
|
mbs_text = "MiB/s";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set actual div in MB/MiB.
|
||||||
|
mb_div *= mb_div;
|
||||||
|
|
||||||
int error = 0;
|
int error = 0;
|
||||||
u32 iters = 3;
|
u32 iters = 3;
|
||||||
u32 offset_chunk_start = ALIGN_DOWN(storage->sec_cnt / 3, 0x8000); // Align to 16MB.
|
u32 offset_chunk_start = ALIGN_DOWN(storage->sec_cnt / 3, sct_blk_seq); // Align to block.
|
||||||
if (storage->sec_cnt < 0xC00000)
|
if (storage->sec_cnt < 0xC00000)
|
||||||
iters -= 2; // 4GB card.
|
iters -= 2; // 4GB card.
|
||||||
|
|
||||||
|
u32 rnd_off_cnt = sct_rem_4kb / sct_blk_4kb;
|
||||||
|
u32 *random_offsets = malloc(rnd_off_cnt * sizeof(u32));
|
||||||
|
u32 *times_taken_4k = malloc(rnd_off_cnt * sizeof(u32));
|
||||||
|
|
||||||
for (u32 iter_curr = 0; iter_curr < iters; iter_curr++)
|
for (u32 iter_curr = 0; iter_curr < iters; iter_curr++)
|
||||||
{
|
{
|
||||||
u32 pct = 0;
|
u32 pct = 0;
|
||||||
u32 prevPct = 200;
|
u32 prevPct = 200;
|
||||||
u32 timer = 0;
|
u32 timer = 0;
|
||||||
u32 lba_curr = 0;
|
u32 lba_curr = 0;
|
||||||
u32 sector = offset_chunk_start * iter_curr;
|
u32 sector_off = offset_chunk_start * iter_curr;
|
||||||
u32 sector_num = 0x8000; // 16MB chunks.
|
u32 sector_num = sct_blk_seq;
|
||||||
u32 data_remaining = 0x200000; // 1GB.
|
u32 data_remaining = sct_rem_seq;
|
||||||
|
|
||||||
s_printf(txt_buf + strlen(txt_buf), "#C7EA46 %d/3# - Sector Offset #C7EA46 %08X#:\n", iter_curr + 1, sector);
|
s_printf(txt_buf + strlen(txt_buf), "#C7EA46 %d/3# - Sector Offset #C7EA46 %08X#:\n", iter_curr + 1, sector_off);
|
||||||
|
|
||||||
u32 render_min_ms = 66;
|
u32 render_min_ms = 66;
|
||||||
u32 render_timer = get_tmr_ms() + render_min_ms;
|
u32 render_timer = get_tmr_ms() + render_min_ms;
|
||||||
while (data_remaining)
|
while (data_remaining)
|
||||||
{
|
{
|
||||||
u32 time_taken = get_tmr_us();
|
u32 time_taken = get_tmr_us();
|
||||||
error = !sdmmc_storage_read(storage, sector + lba_curr, sector_num, (u8 *)MIXD_BUF_ALIGNED);
|
error = !sdmmc_storage_read(storage, sector_off + lba_curr, sector_num, (u8 *)MIXD_BUF_ALIGNED);
|
||||||
time_taken = get_tmr_us() - time_taken;
|
time_taken = get_tmr_us() - time_taken;
|
||||||
timer += time_taken;
|
timer += time_taken;
|
||||||
|
|
||||||
@@ -1385,7 +1463,7 @@ static lv_res_t _create_mbox_benchmark(bool sd_bench)
|
|||||||
data_remaining -= sector_num;
|
data_remaining -= sector_num;
|
||||||
lba_curr += sector_num;
|
lba_curr += sector_num;
|
||||||
|
|
||||||
pct = (lba_curr * 100) / 0x200000;
|
pct = (lba_curr * 100) / sct_rem_seq;
|
||||||
if (pct != prevPct && render_timer < get_tmr_ms())
|
if (pct != prevPct && render_timer < get_tmr_ms())
|
||||||
{
|
{
|
||||||
lv_bar_set_value(bar, pct);
|
lv_bar_set_value(bar, pct);
|
||||||
@@ -1403,10 +1481,10 @@ static lv_res_t _create_mbox_benchmark(bool sd_bench)
|
|||||||
}
|
}
|
||||||
lv_bar_set_value(bar, 100);
|
lv_bar_set_value(bar, 100);
|
||||||
|
|
||||||
u32 rate_1k = ((u64)1024 * 1000 * 1000 * 1000) / timer;
|
// Calculate rate for transfer.
|
||||||
s_printf(txt_buf + strlen(txt_buf),
|
u32 rate_1k = (u64)size_bytes_seq * 1000 * 1000 * 1000 / mb_div / timer;
|
||||||
" Sequential 16MiB - Rate: #C7EA46 %3d.%02d MiB/s#\n",
|
s_printf(txt_buf + strlen(txt_buf), " SEQ 16MB - Rate: #C7EA46 %3d.%02d %s#",
|
||||||
rate_1k / 1000, (rate_1k % 1000) / 10);
|
rate_1k / 1000, (rate_1k % 1000) / 10, mbs_text);
|
||||||
lv_label_set_text(lbl_status, txt_buf);
|
lv_label_set_text(lbl_status, txt_buf);
|
||||||
lv_obj_align(lbl_status, NULL, LV_ALIGN_CENTER, 0, 0);
|
lv_obj_align(lbl_status, NULL, LV_ALIGN_CENTER, 0, 0);
|
||||||
lv_obj_align(mbox, NULL, LV_ALIGN_CENTER, 0, 0);
|
lv_obj_align(mbox, NULL, LV_ALIGN_CENTER, 0, 0);
|
||||||
@@ -1416,22 +1494,25 @@ static lv_res_t _create_mbox_benchmark(bool sd_bench)
|
|||||||
prevPct = 200;
|
prevPct = 200;
|
||||||
timer = 0;
|
timer = 0;
|
||||||
lba_curr = 0;
|
lba_curr = 0;
|
||||||
sector_num = 8; // 4KB chunks.
|
sector_num = sct_blk_4kb;
|
||||||
data_remaining = 0x100000; // 512MB.
|
data_remaining = sct_rem_4kb;
|
||||||
|
|
||||||
|
u32 loop_idx = 0;
|
||||||
render_timer = get_tmr_ms() + render_min_ms;
|
render_timer = get_tmr_ms() + render_min_ms;
|
||||||
while (data_remaining)
|
while (data_remaining)
|
||||||
{
|
{
|
||||||
u32 time_taken = get_tmr_us();
|
u32 time_taken = get_tmr_us();
|
||||||
error = !sdmmc_storage_read(storage, sector + lba_curr, sector_num, (u8 *)MIXD_BUF_ALIGNED);
|
error = !sdmmc_storage_read(storage, sector_off + lba_curr, sector_num, (u8 *)MIXD_BUF_ALIGNED);
|
||||||
time_taken = get_tmr_us() - time_taken;
|
time_taken = get_tmr_us() - time_taken;
|
||||||
|
|
||||||
timer += time_taken;
|
timer += time_taken;
|
||||||
|
times_taken_4k[loop_idx++] = time_taken;
|
||||||
|
|
||||||
manual_system_maintenance(false);
|
manual_system_maintenance(false);
|
||||||
data_remaining -= sector_num;
|
data_remaining -= sector_num;
|
||||||
lba_curr += sector_num;
|
lba_curr += sector_num;
|
||||||
|
|
||||||
pct = (lba_curr * 100) / 0x100000;
|
pct = (lba_curr * 100) / sct_rem_4kb;
|
||||||
if (pct != prevPct && render_timer < get_tmr_ms())
|
if (pct != prevPct && render_timer < get_tmr_ms())
|
||||||
{
|
{
|
||||||
lv_bar_set_value(bar, pct);
|
lv_bar_set_value(bar, pct);
|
||||||
@@ -1449,49 +1530,64 @@ static lv_res_t _create_mbox_benchmark(bool sd_bench)
|
|||||||
}
|
}
|
||||||
lv_bar_set_value(bar, 100);
|
lv_bar_set_value(bar, 100);
|
||||||
|
|
||||||
rate_1k = ((u64)512 * 1000 * 1000 * 1000) / timer;
|
qsort(times_taken_4k, loop_idx, sizeof(u32), qsort_compare_int); // Use int for faster compare. Value can't exceed 2s.
|
||||||
u32 iops_1k = ((u64)512 * 1024 * 1000 * 1000 * 1000) / (4096 / 1024) / timer / 1000;
|
|
||||||
s_printf(txt_buf + strlen(txt_buf),
|
u32 pct95 = 0;
|
||||||
" Sequential 4KiB - Rate: #C7EA46 %3d.%02d MiB/s#, IOPS: #C7EA46 %4d#\n",
|
for (u32 i = 0; i < loop_idx * 95 / 100; i++)
|
||||||
rate_1k / 1000, (rate_1k % 1000) / 10, iops_1k);
|
pct95 += times_taken_4k[i];
|
||||||
|
pct95 /= loop_idx * 95 / 100;
|
||||||
|
|
||||||
|
u32 pct05 = 0;
|
||||||
|
for (u32 i = 0; i < loop_idx * 5 / 100; i++)
|
||||||
|
pct05 += times_taken_4k[loop_idx - 1 - i];
|
||||||
|
pct05 /= loop_idx * 5 / 100;
|
||||||
|
|
||||||
|
// Calculate rate and IOPS for transfer.
|
||||||
|
rate_1k = (u64)size_bytes_4kb * 1000 * 1000 * 1000 / mb_div / timer;
|
||||||
|
u32 iops = ((u64)(sct_rem_4kb / sct_num_1mb) * 1024 * 1000 * 1000 * 1000) / (4096 / 1024) / timer / 1000;
|
||||||
|
s_printf(txt_buf + strlen(txt_buf), " AVG #C7EA46 95th# #FF3C28 5th#\n");
|
||||||
|
s_printf(txt_buf + strlen(txt_buf), " SEQ 4KB - Rate: #C7EA46 %3d.%02d %s# IOPS: #C7EA46 %4d# %4d %4d \n",
|
||||||
|
rate_1k / 1000, (rate_1k % 1000) / 10, mbs_text, iops, 1000000 / pct95, 1000000 / pct05);
|
||||||
lv_label_set_text(lbl_status, txt_buf);
|
lv_label_set_text(lbl_status, txt_buf);
|
||||||
lv_obj_align(lbl_status, NULL, LV_ALIGN_CENTER, 0, 0);
|
lv_obj_align(lbl_status, NULL, LV_ALIGN_CENTER, 0, 0);
|
||||||
lv_obj_align(mbox, NULL, LV_ALIGN_CENTER, 0, 0);
|
lv_obj_align(mbox, NULL, LV_ALIGN_CENTER, 0, 0);
|
||||||
manual_system_maintenance(true);
|
manual_system_maintenance(true);
|
||||||
|
|
||||||
u32 lba_idx = 0;
|
u32 lba_idx = 0;
|
||||||
u32 *random_offsets = malloc(0x20000 * sizeof(u32));
|
u32 random_numbers[4];
|
||||||
u32 random_numbers[4];
|
for (u32 i = 0; i < rnd_off_cnt; i += 4)
|
||||||
for (u32 i = 0; i < 0x20000; i += 4)
|
|
||||||
{
|
{
|
||||||
// Generate new random numbers.
|
// Generate new random numbers.
|
||||||
while (!se_gen_prng128(random_numbers))
|
while (!se_gen_prng128(random_numbers))
|
||||||
;
|
;
|
||||||
// Clamp offsets to 512MB range.
|
// Clamp offsets to 256MB range.
|
||||||
random_offsets[i + 0] = random_numbers[0] % 0x100000;
|
random_offsets[i + 0] = random_numbers[0] % sct_rem_4kb;
|
||||||
random_offsets[i + 1] = random_numbers[1] % 0x100000;
|
random_offsets[i + 1] = random_numbers[1] % sct_rem_4kb;
|
||||||
random_offsets[i + 2] = random_numbers[2] % 0x100000;
|
random_offsets[i + 2] = random_numbers[2] % sct_rem_4kb;
|
||||||
random_offsets[i + 3] = random_numbers[3] % 0x100000;
|
random_offsets[i + 3] = random_numbers[3] % sct_rem_4kb;
|
||||||
}
|
}
|
||||||
|
|
||||||
pct = 0;
|
pct = 0;
|
||||||
prevPct = 200;
|
prevPct = 200;
|
||||||
timer = 0;
|
timer = 0;
|
||||||
data_remaining = 0x100000; // 512MB.
|
data_remaining = sct_rem_4kb;
|
||||||
|
|
||||||
|
loop_idx = 0;
|
||||||
render_timer = get_tmr_ms() + render_min_ms;
|
render_timer = get_tmr_ms() + render_min_ms;
|
||||||
while (data_remaining)
|
while (data_remaining)
|
||||||
{
|
{
|
||||||
u32 time_taken = get_tmr_us();
|
u32 time_taken = get_tmr_us();
|
||||||
error = !sdmmc_storage_read(storage, sector + random_offsets[lba_idx], sector_num, (u8 *)MIXD_BUF_ALIGNED);
|
error = !sdmmc_storage_read(storage, sector_off + random_offsets[lba_idx], sector_num, (u8 *)MIXD_BUF_ALIGNED);
|
||||||
time_taken = get_tmr_us() - time_taken;
|
time_taken = get_tmr_us() - time_taken;
|
||||||
|
|
||||||
timer += time_taken;
|
timer += time_taken;
|
||||||
|
times_taken_4k[loop_idx++] = time_taken;
|
||||||
|
|
||||||
manual_system_maintenance(false);
|
manual_system_maintenance(false);
|
||||||
data_remaining -= sector_num;
|
data_remaining -= sector_num;
|
||||||
lba_idx++;
|
lba_idx++;
|
||||||
|
|
||||||
pct = (lba_idx * 100) / 0x20000;
|
pct = (lba_idx * 100) / rnd_off_cnt;
|
||||||
if (pct != prevPct && render_timer < get_tmr_ms())
|
if (pct != prevPct && render_timer < get_tmr_ms())
|
||||||
{
|
{
|
||||||
lv_bar_set_value(bar, pct);
|
lv_bar_set_value(bar, pct);
|
||||||
@@ -1505,29 +1601,39 @@ static lv_res_t _create_mbox_benchmark(bool sd_bench)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (error)
|
if (error)
|
||||||
{
|
|
||||||
free(random_offsets);
|
|
||||||
goto error;
|
goto error;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
lv_bar_set_value(bar, 100);
|
lv_bar_set_value(bar, 100);
|
||||||
|
|
||||||
// Calculate rate and IOPS for 512MB transfer.
|
qsort(times_taken_4k, loop_idx, sizeof(u32), qsort_compare_int); // Use int for faster compare. Value can't exceed 2s.
|
||||||
rate_1k = ((u64)512 * 1000 * 1000 * 1000) / timer;
|
|
||||||
iops_1k = ((u64)512 * 1024 * 1000 * 1000 * 1000) / (4096 / 1024) / timer / 1000;
|
pct95 = 0;
|
||||||
s_printf(txt_buf + strlen(txt_buf),
|
for (u32 i = 0; i < loop_idx * 95 / 100; i++)
|
||||||
" Random 4KiB - Rate: #C7EA46 %3d.%02d MiB/s#, IOPS: #C7EA46 %4d#\n",
|
pct95 += times_taken_4k[i];
|
||||||
rate_1k / 1000, (rate_1k % 1000) / 10, iops_1k);
|
pct95 /= loop_idx * 95 / 100;
|
||||||
|
|
||||||
|
pct05 = 0;
|
||||||
|
for (u32 i = 0; i < loop_idx * 5 / 100; i++)
|
||||||
|
pct05 += times_taken_4k[loop_idx - 1 - i];
|
||||||
|
pct05 /= loop_idx * 5 / 100;
|
||||||
|
|
||||||
|
// Calculate rate and IOPS for transfer.
|
||||||
|
rate_1k = (u64)size_bytes_4kb * 1000 * 1000 * 1000 / mb_div / timer;
|
||||||
|
iops = ((u64)(sct_rem_4kb / sct_num_1mb) * 1024 * 1000 * 1000 * 1000) / (4096 / 1024) / timer / 1000;
|
||||||
|
s_printf(txt_buf + strlen(txt_buf), " RND 4KB - Rate: #C7EA46 %3d.%02d %s# IOPS: #C7EA46 %4d# %4d %4d \n",
|
||||||
|
rate_1k / 1000, (rate_1k % 1000) / 10, mbs_text, iops, 1000000 / pct95, 1000000 / pct05);
|
||||||
if (iter_curr == iters - 1)
|
if (iter_curr == iters - 1)
|
||||||
txt_buf[strlen(txt_buf) - 1] = 0; // Cut off last line change.
|
txt_buf[strlen(txt_buf) - 1] = 0; // Cut off last new line.
|
||||||
lv_label_set_text(lbl_status, txt_buf);
|
lv_label_set_text(lbl_status, txt_buf);
|
||||||
lv_obj_align(lbl_status, NULL, LV_ALIGN_CENTER, 0, 0);
|
lv_obj_align(lbl_status, NULL, LV_ALIGN_CENTER, 0, 0);
|
||||||
lv_obj_align(mbox, NULL, LV_ALIGN_CENTER, 0, 0);
|
lv_obj_align(mbox, NULL, LV_ALIGN_CENTER, 0, 0);
|
||||||
manual_system_maintenance(true);
|
manual_system_maintenance(true);
|
||||||
free(random_offsets);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
error:
|
error:
|
||||||
|
free(random_offsets);
|
||||||
|
free(times_taken_4k);
|
||||||
|
|
||||||
if (error)
|
if (error)
|
||||||
{
|
{
|
||||||
if (error == -1)
|
if (error == -1)
|
||||||
@@ -1554,6 +1660,8 @@ error:
|
|||||||
emmc_end();
|
emmc_end();
|
||||||
|
|
||||||
out:
|
out:
|
||||||
|
s_printf(txt_buf, "#FF8000 %s Benchmark#\n[Raw Reads]", sd_bench ? "SD Card" : "eMMC");
|
||||||
|
lv_mbox_set_text(mbox, txt_buf);
|
||||||
free(txt_buf);
|
free(txt_buf);
|
||||||
|
|
||||||
lv_mbox_add_btns(mbox, mbox_btn_map, mbox_action); // Important. After set_text.
|
lv_mbox_add_btns(mbox, mbox_btn_map, mbox_action); // Important. After set_text.
|
||||||
@@ -1812,8 +1920,8 @@ out_error:
|
|||||||
lv_mbox_set_recolor_text(mbox, true);
|
lv_mbox_set_recolor_text(mbox, true);
|
||||||
|
|
||||||
s_printf(txt_buf,
|
s_printf(txt_buf,
|
||||||
"#FF8000 eMMC Issues Check#\n\n"
|
"#FF8000 eMMC Issues Warning#\n\n"
|
||||||
"#FFDD00 Your eMMC is initialized in slower mode,#\n"
|
"#FFDD00 Your eMMC is initialized in a slower mode,#\n"
|
||||||
"#FFDD00 or init/read/write errors occurred!#\n"
|
"#FFDD00 or init/read/write errors occurred!#\n"
|
||||||
"#FFDD00 This might mean hardware issues!#\n\n"
|
"#FFDD00 This might mean hardware issues!#\n\n"
|
||||||
"#00DDFF Bus Speed:# %d MB/s\n\n"
|
"#00DDFF Bus Speed:# %d MB/s\n\n"
|
||||||
@@ -1845,7 +1953,7 @@ static lv_res_t _create_window_sdcard_info_status(lv_obj_t *btn)
|
|||||||
lv_win_add_btn(win, NULL, SYMBOL_SD" Benchmark", _create_mbox_sd_bench);
|
lv_win_add_btn(win, NULL, SYMBOL_SD" Benchmark", _create_mbox_sd_bench);
|
||||||
|
|
||||||
lv_obj_t *desc = lv_cont_create(win, NULL);
|
lv_obj_t *desc = lv_cont_create(win, NULL);
|
||||||
lv_obj_set_size(desc, LV_HOR_RES / 2 / 5 * 2, LV_VER_RES - (LV_DPI * 11 / 8) * 5 / 2);
|
lv_obj_set_size(desc, LV_HOR_RES / 2 / 6 * 2, LV_VER_RES - (LV_DPI * 11 / 8) * 5 / 2);
|
||||||
|
|
||||||
lv_obj_t * lb_desc = lv_label_create(desc, NULL);
|
lv_obj_t * lb_desc = lv_label_create(desc, NULL);
|
||||||
lv_label_set_long_mode(lb_desc, LV_LABEL_LONG_BREAK);
|
lv_label_set_long_mode(lb_desc, LV_LABEL_LONG_BREAK);
|
||||||
@@ -1866,7 +1974,7 @@ static lv_res_t _create_window_sdcard_info_status(lv_obj_t *btn)
|
|||||||
}
|
}
|
||||||
|
|
||||||
lv_label_set_text(lb_desc,
|
lv_label_set_text(lb_desc,
|
||||||
"#00DDFF Card IDentification:#\n"
|
"#00DDFF Card ID:#\n"
|
||||||
"Vendor ID:\n"
|
"Vendor ID:\n"
|
||||||
"Model:\n"
|
"Model:\n"
|
||||||
"OEM ID:\n"
|
"OEM ID:\n"
|
||||||
@@ -1875,11 +1983,11 @@ static lv_res_t _create_window_sdcard_info_status(lv_obj_t *btn)
|
|||||||
"S/N:\n"
|
"S/N:\n"
|
||||||
"Month/Year:\n\n"
|
"Month/Year:\n\n"
|
||||||
"Max Power:\n"
|
"Max Power:\n"
|
||||||
"Bootloader bus:"
|
"Initial bus:"
|
||||||
);
|
);
|
||||||
|
|
||||||
lv_obj_t *val = lv_cont_create(win, NULL);
|
lv_obj_t *val = lv_cont_create(win, NULL);
|
||||||
lv_obj_set_size(val, LV_HOR_RES / 9 * 2, LV_VER_RES - (LV_DPI * 11 / 8) * 5 / 2);
|
lv_obj_set_size(val, LV_HOR_RES / 12 * 3, LV_VER_RES - (LV_DPI * 11 / 8) * 5 / 2);
|
||||||
|
|
||||||
lv_obj_t * lb_val = lv_label_create(val, lb_desc);
|
lv_obj_t * lb_val = lv_label_create(val, lb_desc);
|
||||||
|
|
||||||
@@ -1986,7 +2094,7 @@ static lv_res_t _create_window_sdcard_info_status(lv_obj_t *btn)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// UHS-I max power limit is 400mA, no matter what the card says.
|
// UHS-I max power limit is 400mA, no matter what the card says.
|
||||||
u32 card_power_limit_nominal = sd_storage.card_power_limit > 400 ? 400 : sd_storage.card_power_limit;
|
u32 max_power_nominal = sd_storage.max_power > 400 ? 400 : sd_storage.max_power;
|
||||||
|
|
||||||
s_printf(txt_buf + strlen(txt_buf), "(%02X)\n%c%c%c%c%c\n%c%c (%04X)\n%X\n%X\n%08x\n%02d/%04d\n\n%d mW (%d mA)\n",
|
s_printf(txt_buf + strlen(txt_buf), "(%02X)\n%c%c%c%c%c\n%c%c (%04X)\n%X\n%X\n%08x\n%02d/%04d\n\n%d mW (%d mA)\n",
|
||||||
sd_storage.cid.manfid,
|
sd_storage.cid.manfid,
|
||||||
@@ -1995,7 +2103,7 @@ static lv_res_t _create_window_sdcard_info_status(lv_obj_t *btn)
|
|||||||
(sd_storage.cid.oemid >> 8) & 0xFF, sd_storage.cid.oemid & 0xFF, sd_storage.cid.oemid,
|
(sd_storage.cid.oemid >> 8) & 0xFF, sd_storage.cid.oemid & 0xFF, sd_storage.cid.oemid,
|
||||||
sd_storage.cid.hwrev, sd_storage.cid.fwrev, sd_storage.cid.serial,
|
sd_storage.cid.hwrev, sd_storage.cid.fwrev, sd_storage.cid.serial,
|
||||||
sd_storage.cid.month, sd_storage.cid.year,
|
sd_storage.cid.month, sd_storage.cid.year,
|
||||||
card_power_limit_nominal * 3600 / 1000, sd_storage.card_power_limit);
|
max_power_nominal * 3600 / 1000, sd_storage.max_power);
|
||||||
|
|
||||||
switch (nyx_str->info.sd_init)
|
switch (nyx_str->info.sd_init)
|
||||||
{
|
{
|
||||||
@@ -2021,7 +2129,7 @@ static lv_res_t _create_window_sdcard_info_status(lv_obj_t *btn)
|
|||||||
lv_obj_align(val, desc, LV_ALIGN_OUT_RIGHT_MID, 0, 0);
|
lv_obj_align(val, desc, LV_ALIGN_OUT_RIGHT_MID, 0, 0);
|
||||||
|
|
||||||
lv_obj_t *desc2 = lv_cont_create(win, NULL);
|
lv_obj_t *desc2 = lv_cont_create(win, NULL);
|
||||||
lv_obj_set_size(desc2, LV_HOR_RES / 2 / 4 * 2, LV_VER_RES - (LV_DPI * 11 / 8) * 5 / 2);
|
lv_obj_set_size(desc2, LV_HOR_RES / 2 / 11 * 5, LV_VER_RES - (LV_DPI * 11 / 8) * 5 / 2);
|
||||||
|
|
||||||
lv_obj_t * lb_desc2 = lv_label_create(desc2, lb_desc);
|
lv_obj_t * lb_desc2 = lv_label_create(desc2, lb_desc);
|
||||||
|
|
||||||
@@ -2038,10 +2146,10 @@ static lv_res_t _create_window_sdcard_info_status(lv_obj_t *btn)
|
|||||||
"Write Protect:"
|
"Write Protect:"
|
||||||
);
|
);
|
||||||
lv_obj_set_width(lb_desc2, lv_obj_get_width(desc2));
|
lv_obj_set_width(lb_desc2, lv_obj_get_width(desc2));
|
||||||
lv_obj_align(desc2, val, LV_ALIGN_OUT_RIGHT_MID, LV_DPI / 2, 0);
|
lv_obj_align(desc2, val, LV_ALIGN_OUT_RIGHT_MID, LV_DPI / 5 * 3, 0);
|
||||||
|
|
||||||
lv_obj_t *val2 = lv_cont_create(win, NULL);
|
lv_obj_t *val2 = lv_cont_create(win, NULL);
|
||||||
lv_obj_set_size(val2, LV_HOR_RES / 13 * 3, LV_VER_RES - (LV_DPI * 11 / 8) * 5 / 2);
|
lv_obj_set_size(val2, LV_HOR_RES / 4, LV_VER_RES - (LV_DPI * 11 / 8) * 5 / 2);
|
||||||
|
|
||||||
lv_obj_t * lb_val2 = lv_label_create(val2, lb_desc);
|
lv_obj_t * lb_val2 = lv_label_create(val2, lb_desc);
|
||||||
|
|
||||||
@@ -2085,15 +2193,64 @@ static lv_res_t _create_window_sdcard_info_status(lv_obj_t *btn)
|
|||||||
else
|
else
|
||||||
bus_speed = "SDR12";
|
bus_speed = "SDR12";
|
||||||
|
|
||||||
|
char *cpe = NULL;
|
||||||
|
if (sd_storage.ssr.app_class == 2)
|
||||||
|
{
|
||||||
|
u8 *buf = zalloc(512);
|
||||||
|
|
||||||
|
// Directly get and parse ext reg for performance enhance.
|
||||||
|
sd_storage_parse_perf_enhance(&sd_storage, 2, 0, 0, buf);
|
||||||
|
|
||||||
|
bool has_perf_enhance = sd_storage.ser.cache &&
|
||||||
|
sd_storage.ser.cmdq &&
|
||||||
|
sd_storage.ser.cache == sd_storage.ser.cache_ext &&
|
||||||
|
sd_storage.ser.cmdq == sd_storage.ser.cmdq_ext;
|
||||||
|
if (has_perf_enhance)
|
||||||
|
cpe = "#FFDD00 "; // CMDQ/CACHE support via a quirk.
|
||||||
|
else
|
||||||
|
cpe = "#FF3C28 "; // Broken.
|
||||||
|
|
||||||
|
// Get and parse ext reg for performance enhance in spec.
|
||||||
|
sd_storage_get_ext_regs(&sd_storage, buf);
|
||||||
|
|
||||||
|
if (sd_storage.ser.valid)
|
||||||
|
{
|
||||||
|
has_perf_enhance = sd_storage.ser.cache &&
|
||||||
|
sd_storage.ser.cmdq &&
|
||||||
|
sd_storage.ser.cache == sd_storage.ser.cache_ext &&
|
||||||
|
sd_storage.ser.cmdq == sd_storage.ser.cmdq_ext;
|
||||||
|
|
||||||
|
if (has_perf_enhance)
|
||||||
|
cpe = NULL; // CMDQ/CACHE support in spec.
|
||||||
|
else
|
||||||
|
cpe = "#FF3C28 "; // Broken.
|
||||||
|
}
|
||||||
|
|
||||||
|
free(buf);
|
||||||
|
}
|
||||||
|
|
||||||
s_printf(txt_buf,
|
s_printf(txt_buf,
|
||||||
"#00DDFF v%d.0#\n%02X\n%d MiB\n%X (CP %X)\n%d\n%d MB/s (%d MHz)\n%d (AU: %d %s\nU%d V%d A%d\n%s\n\n%s",
|
"#00DDFF v%d.0#\n"
|
||||||
sd_storage.csd.structure + 1, sd_storage.csd.cmdclass,
|
"%02X\n"
|
||||||
sd_storage.sec_cnt >> 11, sd_storage.sec_cnt, sd_storage.ssr.protected_size >> 9,
|
"%d MiB\n"
|
||||||
sd_storage.ssr.bus_width, sd_storage.csd.busspeed,
|
"%X (CP %X)\n"
|
||||||
|
"%d\n"
|
||||||
|
"%d MB/s (%d MHz)\n"
|
||||||
|
"%d (AU: %d %s\n"
|
||||||
|
"U%d V%d %sA%d%s\n"
|
||||||
|
"%s\n\n"
|
||||||
|
"%s",
|
||||||
|
sd_storage.csd.structure + 1,
|
||||||
|
sd_storage.csd.cmdclass,
|
||||||
|
sd_storage.sec_cnt >> 11,
|
||||||
|
sd_storage.sec_cnt, sd_storage.ssr.protected_size >> 9,
|
||||||
|
sd_storage.ssr.bus_width,
|
||||||
|
sd_storage.csd.busspeed,
|
||||||
(sd_storage.csd.busspeed > 10) ? (sd_storage.csd.busspeed * 2) : 50,
|
(sd_storage.csd.busspeed > 10) ? (sd_storage.csd.busspeed * 2) : 50,
|
||||||
sd_storage.ssr.speed_class, uhs_au_size, uhs_au_mb ? "MiB)" : "KiB)",
|
sd_storage.ssr.speed_class, uhs_au_size, uhs_au_mb ? "MiB)" : "KiB)",
|
||||||
sd_storage.ssr.uhs_grade, sd_storage.ssr.video_class, sd_storage.ssr.app_class,
|
sd_storage.ssr.uhs_grade, sd_storage.ssr.video_class, cpe ? cpe : "", sd_storage.ssr.app_class, cpe ? "#" : "",
|
||||||
bus_speed, wp_info);
|
bus_speed,
|
||||||
|
wp_info);
|
||||||
|
|
||||||
lv_label_set_text(lb_val2, txt_buf);
|
lv_label_set_text(lb_val2, txt_buf);
|
||||||
|
|
||||||
@@ -2110,47 +2267,29 @@ static lv_res_t _create_window_sdcard_info_status(lv_obj_t *btn)
|
|||||||
lv_obj_set_size(desc3, LV_HOR_RES / 2 / 2 * 2, LV_VER_RES - (LV_DPI * 11 / 8) * 4);
|
lv_obj_set_size(desc3, LV_HOR_RES / 2 / 2 * 2, LV_VER_RES - (LV_DPI * 11 / 8) * 4);
|
||||||
|
|
||||||
lv_obj_t * lb_desc3 = lv_label_create(desc3, lb_desc);
|
lv_obj_t * lb_desc3 = lv_label_create(desc3, lb_desc);
|
||||||
lv_label_set_text(lb_desc3, "#D4FF00 Acquiring FAT volume info...#");
|
lv_label_set_text(lb_desc3, "#D4FF00 Acquiring info...#");
|
||||||
lv_obj_set_width(lb_desc3, lv_obj_get_width(desc3));
|
lv_obj_set_width(lb_desc3, lv_obj_get_width(desc3));
|
||||||
|
|
||||||
lv_obj_align(desc3, desc, LV_ALIGN_OUT_BOTTOM_LEFT, 0, LV_DPI / 2);
|
lv_obj_align(desc3, desc, LV_ALIGN_OUT_BOTTOM_LEFT, 0, LV_DPI / 2);
|
||||||
|
|
||||||
manual_system_maintenance(true);
|
manual_system_maintenance(true);
|
||||||
|
|
||||||
f_getfree("", &sd_fs.free_clst, NULL);
|
lv_obj_set_size(desc3, LV_HOR_RES / 2 / 6 * 2, LV_VER_RES - (LV_DPI * 11 / 8) * 4);
|
||||||
|
|
||||||
lv_label_set_text(lb_desc3,
|
|
||||||
"#00DDFF Found FAT volume:#\n"
|
|
||||||
"Filesystem:\n"
|
|
||||||
"Cluster:\n"
|
|
||||||
"Size free/total:"
|
|
||||||
);
|
|
||||||
lv_obj_set_size(desc3, LV_HOR_RES / 2 / 5 * 2, LV_VER_RES - (LV_DPI * 11 / 8) * 4);
|
|
||||||
lv_obj_set_width(lb_desc3, lv_obj_get_width(desc3));
|
|
||||||
lv_obj_align(desc3, desc, LV_ALIGN_OUT_BOTTOM_LEFT, 0, LV_DPI / 2);
|
lv_obj_align(desc3, desc, LV_ALIGN_OUT_BOTTOM_LEFT, 0, LV_DPI / 2);
|
||||||
|
|
||||||
lv_obj_t *val3 = lv_cont_create(win, NULL);
|
lv_obj_t *val3 = lv_cont_create(win, NULL);
|
||||||
lv_obj_set_size(val3, LV_HOR_RES / 13 * 3, LV_VER_RES - (LV_DPI * 11 / 8) * 4);
|
lv_obj_set_size(val3, LV_HOR_RES / 12 * 3, LV_VER_RES - (LV_DPI * 11 / 8) * 4);
|
||||||
|
|
||||||
lv_obj_t * lb_val3 = lv_label_create(val3, lb_desc);
|
lv_obj_t * lb_val3 = lv_label_create(val3, lb_desc);
|
||||||
|
lv_label_set_text(lb_val3, "");
|
||||||
|
|
||||||
s_printf(txt_buf, "\n%s\n%d %s\n%d/%d MiB",
|
|
||||||
sd_fs.fs_type == FS_EXFAT ? ("exFAT "SYMBOL_SHRK) : ("FAT32"),
|
|
||||||
(sd_fs.csize > 1) ? (sd_fs.csize >> 1) : SD_BLOCKSIZE,
|
|
||||||
(sd_fs.csize > 1) ? "KiB" : "B",
|
|
||||||
(u32)(sd_fs.free_clst * sd_fs.csize >> SECTORS_TO_MIB_COEFF),
|
|
||||||
(u32)(sd_fs.n_fatent * sd_fs.csize >> SECTORS_TO_MIB_COEFF));
|
|
||||||
|
|
||||||
lv_label_set_text(lb_val3, txt_buf);
|
|
||||||
|
|
||||||
lv_obj_set_width(lb_val3, lv_obj_get_width(val3));
|
|
||||||
lv_obj_align(val3, desc3, LV_ALIGN_OUT_RIGHT_MID, 0, 0);
|
lv_obj_align(val3, desc3, LV_ALIGN_OUT_RIGHT_MID, 0, 0);
|
||||||
|
|
||||||
lv_obj_t *desc4 = lv_cont_create(win, NULL);
|
lv_obj_t *desc4 = lv_cont_create(win, NULL);
|
||||||
lv_obj_set_size(desc4, LV_HOR_RES / 2 / 2 * 2, LV_VER_RES - (LV_DPI * 11 / 8) * 4);
|
lv_obj_set_size(desc4, LV_HOR_RES / 2 / 2 * 2, LV_VER_RES - (LV_DPI * 11 / 8) * 4);
|
||||||
|
|
||||||
lv_obj_t * lb_desc4 = lv_label_create(desc4, lb_desc);
|
lv_obj_t * lb_desc4 = lv_label_create(desc4, lb_desc);
|
||||||
lv_label_set_text(lb_desc4, "#D4FF00 Acquiring FAT volume info...#");
|
lv_label_set_text(lb_desc4, " ");
|
||||||
lv_obj_set_width(lb_desc4, lv_obj_get_width(desc4));
|
lv_obj_set_width(lb_desc4, lv_obj_get_width(desc4));
|
||||||
|
|
||||||
lv_label_set_text(lb_desc4,
|
lv_label_set_text(lb_desc4,
|
||||||
@@ -2159,12 +2298,12 @@ static lv_res_t _create_window_sdcard_info_status(lv_obj_t *btn)
|
|||||||
"Read/Write fails:\n"
|
"Read/Write fails:\n"
|
||||||
"Read/Write errors:"
|
"Read/Write errors:"
|
||||||
);
|
);
|
||||||
lv_obj_set_size(desc4, LV_HOR_RES / 2 / 5 * 2, LV_VER_RES - (LV_DPI * 11 / 8) * 4);
|
lv_obj_set_size(desc4, LV_HOR_RES / 2 / 11 * 5, LV_VER_RES - (LV_DPI * 11 / 8) * 4);
|
||||||
lv_obj_set_width(lb_desc4, lv_obj_get_width(desc4));
|
lv_obj_set_width(lb_desc4, lv_obj_get_width(desc4));
|
||||||
lv_obj_align(desc4, val3, LV_ALIGN_OUT_RIGHT_MID, LV_DPI / 2, 0);
|
lv_obj_align(desc4, val3, LV_ALIGN_OUT_RIGHT_MID, LV_DPI / 5 * 3, 0);
|
||||||
|
|
||||||
lv_obj_t *val4 = lv_cont_create(win, NULL);
|
lv_obj_t *val4 = lv_cont_create(win, NULL);
|
||||||
lv_obj_set_size(val4, LV_HOR_RES / 13 * 3, LV_VER_RES - (LV_DPI * 11 / 8) * 4);
|
lv_obj_set_size(val4, LV_HOR_RES / 4, LV_VER_RES - (LV_DPI * 11 / 8) * 4);
|
||||||
|
|
||||||
lv_obj_t * lb_val4 = lv_label_create(val4, lb_desc);
|
lv_obj_t * lb_val4 = lv_label_create(val4, lb_desc);
|
||||||
|
|
||||||
@@ -2177,7 +2316,31 @@ static lv_res_t _create_window_sdcard_info_status(lv_obj_t *btn)
|
|||||||
lv_label_set_text(lb_val4, txt_buf);
|
lv_label_set_text(lb_val4, txt_buf);
|
||||||
|
|
||||||
lv_obj_set_width(lb_val4, lv_obj_get_width(val4));
|
lv_obj_set_width(lb_val4, lv_obj_get_width(val4));
|
||||||
lv_obj_align(val4, desc4, LV_ALIGN_OUT_RIGHT_MID, LV_DPI / 2, 0);
|
lv_obj_align(val4, desc4, LV_ALIGN_OUT_RIGHT_MID, 0, 0);
|
||||||
|
|
||||||
|
manual_system_maintenance(true);
|
||||||
|
|
||||||
|
f_getfree("", &sd_fs.free_clst, NULL);
|
||||||
|
|
||||||
|
lv_label_set_text(lb_desc3,
|
||||||
|
"#00DDFF Found FAT FS:#\n"
|
||||||
|
"Filesystem:\n"
|
||||||
|
"Cluster:\n"
|
||||||
|
"Size free/total:"
|
||||||
|
);
|
||||||
|
|
||||||
|
lv_obj_set_width(lb_desc3, lv_obj_get_width(desc3));
|
||||||
|
|
||||||
|
s_printf(txt_buf, "\n%s\n%d %s\n%d/%d MiB",
|
||||||
|
sd_fs.fs_type == FS_EXFAT ? ("exFAT "SYMBOL_SHRK) : ("FAT32"),
|
||||||
|
(sd_fs.csize > 1) ? (sd_fs.csize >> 1) : SD_BLOCKSIZE,
|
||||||
|
(sd_fs.csize > 1) ? "KiB" : "B",
|
||||||
|
(u32)(sd_fs.free_clst * sd_fs.csize >> SECTORS_TO_MIB_COEFF),
|
||||||
|
(u32)(sd_fs.n_fatent * sd_fs.csize >> SECTORS_TO_MIB_COEFF));
|
||||||
|
|
||||||
|
lv_label_set_text(lb_val3, txt_buf);
|
||||||
|
|
||||||
|
lv_obj_set_width(lb_val3, lv_obj_get_width(val3));
|
||||||
|
|
||||||
free(txt_buf);
|
free(txt_buf);
|
||||||
sd_unmount();
|
sd_unmount();
|
||||||
@@ -2552,7 +2715,7 @@ void create_tab_info(lv_theme_t *th, lv_obj_t *parent)
|
|||||||
lv_btn_set_fit(btn3, true, true);
|
lv_btn_set_fit(btn3, true, true);
|
||||||
lv_label_set_static_text(label_btn, SYMBOL_CIRCUIT" HW & Fuses");
|
lv_label_set_static_text(label_btn, SYMBOL_CIRCUIT" HW & Fuses");
|
||||||
lv_obj_align(btn3, line_sep, LV_ALIGN_OUT_BOTTOM_LEFT, LV_DPI / 4, LV_DPI / 2);
|
lv_obj_align(btn3, line_sep, LV_ALIGN_OUT_BOTTOM_LEFT, LV_DPI / 4, LV_DPI / 2);
|
||||||
lv_btn_set_action(btn3, LV_BTN_ACTION_CLICK, _create_window_fuses_info_status);
|
lv_btn_set_action(btn3, LV_BTN_ACTION_CLICK, _create_window_hw_info_status);
|
||||||
|
|
||||||
// Create KFuses button.
|
// Create KFuses button.
|
||||||
lv_obj_t *btn4 = lv_btn_create(h1, btn);
|
lv_obj_t *btn4 = lv_btn_create(h1, btn);
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2018-2024 CTCaer
|
* Copyright (c) 2018-2025 CTCaer
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
* under the terms and conditions of the GNU General Public License,
|
* under the terms and conditions of the GNU General Public License,
|
||||||
@@ -25,9 +25,9 @@
|
|||||||
#include <libs/lvgl/lvgl.h>
|
#include <libs/lvgl/lvgl.h>
|
||||||
#include <storage/boot_storage.h>
|
#include <storage/boot_storage.h>
|
||||||
|
|
||||||
#define CLOCK_MIN_YEAR 2024
|
#define CLOCK_MIN_YEAR 2025
|
||||||
#define CLOCK_MAX_YEAR (CLOCK_MIN_YEAR + 10)
|
#define CLOCK_MAX_YEAR (CLOCK_MIN_YEAR + 10)
|
||||||
#define CLOCK_YEARLIST "2024\n2025\n2026\n2027\n2028\n2029\n2030\n2031\n2032\n2033\n2034"
|
#define CLOCK_YEARLIST "2025\n2026\n2027\n2028\n2029\n2030\n2031\n2032\n2033\n2034\n2035"
|
||||||
|
|
||||||
extern hekate_config h_cfg;
|
extern hekate_config h_cfg;
|
||||||
extern nyx_config n_cfg;
|
extern nyx_config n_cfg;
|
||||||
@@ -1170,13 +1170,11 @@ static lv_res_t _action_win_nyx_options_close(lv_obj_t *btn)
|
|||||||
lv_obj_set_opa_scale(status_bar.mid, LV_OPA_0);
|
lv_obj_set_opa_scale(status_bar.mid, LV_OPA_0);
|
||||||
lv_obj_set_click(status_bar.mid, false);
|
lv_obj_set_click(status_bar.mid, false);
|
||||||
|
|
||||||
lv_win_close_action(btn);
|
lv_res_t res = nyx_win_close_action_custom(btn);
|
||||||
|
|
||||||
close_btn = NULL;
|
|
||||||
|
|
||||||
_check_nyx_changes();
|
_check_nyx_changes();
|
||||||
|
|
||||||
return LV_RES_INV;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
lv_res_t create_win_nyx_options(lv_obj_t *parrent_btn)
|
lv_res_t create_win_nyx_options(lv_obj_t *parrent_btn)
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
#include <fatfs_cfg.h>
|
#include <fatfs_cfg.h>
|
||||||
#include <libs/lvgl/lv_core/lv_obj.h>
|
#include <libs/lvgl/lv_core/lv_obj.h>
|
||||||
#include <libs/lvgl/lv_objx/lv_btn.h>
|
#include <libs/lvgl/lv_objx/lv_btn.h>
|
||||||
|
#include <libs/lvgl/lv_objx/lv_btnm.h>
|
||||||
#include <libs/lvgl/lv_objx/lv_label.h>
|
#include <libs/lvgl/lv_objx/lv_label.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
@@ -37,6 +38,7 @@
|
|||||||
#include <storage/boot_storage.h>
|
#include <storage/boot_storage.h>
|
||||||
#include <storage/emmc.h>
|
#include <storage/emmc.h>
|
||||||
#include <storage/emummc_file_based.h>
|
#include <storage/emummc_file_based.h>
|
||||||
|
#include <storage/file_based_storage.h>
|
||||||
#include <storage/mbr_gpt.h>
|
#include <storage/mbr_gpt.h>
|
||||||
#include <storage/sd.h>
|
#include <storage/sd.h>
|
||||||
#include <storage/sdmmc.h>
|
#include <storage/sdmmc.h>
|
||||||
@@ -380,6 +382,12 @@ static lv_res_t _create_mbox_ums_error(int error)
|
|||||||
case 8:
|
case 8:
|
||||||
lv_mbox_set_text(mbox, "#FF8000 USB Mass Storage#\n\n#FFFF00 Failed to initialize file based emuMMC!#");
|
lv_mbox_set_text(mbox, "#FF8000 USB Mass Storage#\n\n#FFFF00 Failed to initialize file based emuMMC!#");
|
||||||
break;
|
break;
|
||||||
|
case 9:
|
||||||
|
lv_mbox_set_text(mbox, "#FF8000 USB Mass Storage#\n\n#FFFF00 Failed to initialize file based emuSD!#");
|
||||||
|
break;
|
||||||
|
case 10:
|
||||||
|
lv_mbox_set_text(mbox, "#FF8000 USB Mass Storage#\n\n#FFFF00 No emuSD found active!#");
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
lv_mbox_add_btns(mbox, mbox_btn_map, mbox_action);
|
lv_mbox_add_btns(mbox, mbox_btn_map, mbox_action);
|
||||||
@@ -558,42 +566,103 @@ static lv_res_t _action_ums_emusd(lv_obj_t * btn){
|
|||||||
}
|
}
|
||||||
|
|
||||||
usb_ctxt_t usbs;
|
usb_ctxt_t usbs;
|
||||||
|
sdmmc_storage_t *storage;
|
||||||
emusd_cfg_t emu_info;
|
emusd_cfg_t emu_info;
|
||||||
|
|
||||||
|
bool file_based = false;
|
||||||
int error = !boot_storage_mount();
|
int error = !boot_storage_mount();
|
||||||
|
char path[0x80];
|
||||||
|
|
||||||
if(!error){
|
if(!error){
|
||||||
load_emusd_cfg(&emu_info);
|
load_emusd_cfg(&emu_info);
|
||||||
if(emu_info.enabled){
|
if(emu_info.enabled){
|
||||||
if(!emmc_initialize(false)){
|
error = 0;
|
||||||
error = 3;
|
if(emu_info.enabled == 4 && emu_info.sector){
|
||||||
}else{
|
if(!emmc_initialize(false)){
|
||||||
mbr_t mbr = {0};
|
|
||||||
|
|
||||||
if(sdmmc_storage_read(&emmc_storage, emu_info.sector, 1, &mbr)){
|
|
||||||
error = 0;
|
|
||||||
usbs.offset = emu_info.sector;
|
|
||||||
usbs.sectors = mbr.partitions[0].size_sct;
|
|
||||||
usbs.type = MMC_EMMC;
|
|
||||||
usbs.partition = EMMC_GPP + 1;
|
|
||||||
usbs.ro = false;
|
|
||||||
usbs.system_maintenance = &manual_system_maintenance;
|
|
||||||
usbs.set_text = &usb_gadget_set_text;
|
|
||||||
}else{
|
|
||||||
error = 3;
|
error = 3;
|
||||||
}
|
}
|
||||||
|
storage = &emmc_storage;
|
||||||
|
}else if(emu_info.enabled == 1 && emu_info.sector){
|
||||||
|
if(!sd_initialize(false)){
|
||||||
|
error = 4;
|
||||||
|
}
|
||||||
|
storage = &sd_storage;
|
||||||
|
}else if((emu_info.enabled == 1 || emu_info.enabled == 4) && !emu_info.sector){
|
||||||
|
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, "/SD/");
|
||||||
|
if(!file_based_storage_init(path)){
|
||||||
|
error = 9;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
error = 10;
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
error = 7;
|
error = 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(error == 0 && emu_info.enabled){
|
||||||
|
error = 6;
|
||||||
|
if(file_based){
|
||||||
|
usbs.offset = 0;
|
||||||
|
}else{
|
||||||
|
usbs.offset = emu_info.sector;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(file_based){
|
||||||
|
error = 9;
|
||||||
|
u32 sz = file_based_storage_get_total_size();
|
||||||
|
if(sz){
|
||||||
|
error = 0;
|
||||||
|
}
|
||||||
|
usbs.sectors = sz;
|
||||||
|
}else{
|
||||||
|
error = 3;
|
||||||
|
mbr_t mbr;
|
||||||
|
if(sdmmc_storage_read(storage, emu_info.sector, 1, &mbr)){
|
||||||
|
error = 0;
|
||||||
|
usbs.sectors = mbr.partitions[0].size_sct + mbr.partitions[0].start_sct;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(emu_info.path){
|
||||||
|
free(emu_info.path);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(error){
|
if(error){
|
||||||
_create_mbox_ums_error(error);
|
_create_mbox_ums_error(error);
|
||||||
}else{
|
}else{
|
||||||
|
if(file_based){
|
||||||
|
usbs.type = MMC_FILE_BASED;
|
||||||
|
}else{
|
||||||
|
usbs.type = emu_info.enabled == 1 ? MMC_SD : MMC_EMMC;
|
||||||
|
}
|
||||||
|
usbs.partition = EMMC_GPP + 1;
|
||||||
|
usbs.ro = false;
|
||||||
|
usbs.system_maintenance = &manual_system_maintenance;
|
||||||
|
usbs.set_text = &usb_gadget_set_text;
|
||||||
_create_mbox_ums(&usbs, NYX_UMS_EMUSD);
|
_create_mbox_ums(&usbs, NYX_UMS_EMUSD);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
file_based_storage_end();
|
||||||
boot_storage_unmount();
|
boot_storage_unmount();
|
||||||
|
|
||||||
return LV_RES_OK;
|
return LV_RES_OK;
|
||||||
@@ -1715,8 +1784,8 @@ static void _create_tab_tools_emmc_pkg12(lv_theme_t *th, lv_obj_t *parent)
|
|||||||
lv_btnm_set_style(btnm, LV_BTNM_STYLE_BTN_INA, th->btn.ina);
|
lv_btnm_set_style(btnm, LV_BTNM_STYLE_BTN_INA, th->btn.ina);
|
||||||
if (hekate_bg)
|
if (hekate_bg)
|
||||||
{
|
{
|
||||||
lv_btn_set_style(btnm, LV_BTN_STYLE_REL, &btn_transp_rel);
|
lv_btnm_set_style(btnm, LV_BTNM_STYLE_BTN_REL, &btn_transp_rel);
|
||||||
lv_btn_set_style(btnm, LV_BTN_STYLE_PR, &btn_transp_pr);
|
lv_btnm_set_style(btnm, LV_BTNM_STYLE_BTN_PR, &btn_transp_pr);
|
||||||
}
|
}
|
||||||
lv_coord_t font_h = lv_font_get_height(th->btn.rel->text.font);
|
lv_coord_t font_h = lv_font_get_height(th->btn.rel->text.font);
|
||||||
lv_obj_set_size(btnm, 400, font_h + 2 * th->btn.rel->body.padding.ver + 2 * th->bg->body.padding.ver);
|
lv_obj_set_size(btnm, 400, font_h + 2 * th->btn.rel->body.padding.ver + 2 * th->bg->body.padding.ver);
|
||||||
|
|||||||
@@ -61,8 +61,10 @@
|
|||||||
extern volatile boot_cfg_t *b_cfg;
|
extern volatile boot_cfg_t *b_cfg;
|
||||||
extern volatile nyx_storage_t *nyx_str;
|
extern volatile nyx_storage_t *nyx_str;
|
||||||
|
|
||||||
#define DBG_PRINT(msg) gfx_printf(msg); gfx_putc('\n');
|
// #define DBG_PRINT(msg) gfx_printf(msg); gfx_putc('\n');
|
||||||
#define DBG_PRINT_ARGS(msg, ...) gfx_printf(msg, __VA_ARGS__); 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
|
typedef struct _partition_ctxt_t
|
||||||
@@ -220,7 +222,7 @@ static int _stat_and_copy_files(const char *src, const char *dst, char *path, u3
|
|||||||
u32 dirLength = 0;
|
u32 dirLength = 0;
|
||||||
static FILINFO fno;
|
static FILINFO fno;
|
||||||
|
|
||||||
DBG_PRINT_ARGS("chdrive %d", f_chdrive(src));
|
f_chdrive(src);
|
||||||
|
|
||||||
// Open directory.
|
// Open directory.
|
||||||
res = f_opendir(&dir, path);
|
res = f_opendir(&dir, path);
|
||||||
@@ -285,9 +287,9 @@ static int _stat_and_copy_files(const char *src, const char *dst, char *path, u3
|
|||||||
|
|
||||||
// Open file for writing.
|
// Open file for writing.
|
||||||
f_chdrive(dst);
|
f_chdrive(dst);
|
||||||
DBG_PRINT_ARGS("open %d", f_open(&fp_dst, path, FA_CREATE_ALWAYS | FA_WRITE));
|
f_open(&fp_dst, path, FA_CREATE_ALWAYS | FA_WRITE);
|
||||||
DBG_PRINT_ARGS("seek1 %d", f_lseek(&fp_dst, fno.fsize));
|
f_lseek(&fp_dst, fno.fsize);
|
||||||
DBG_PRINT_ARGS("seek2 %d", f_lseek(&fp_dst, 0));
|
f_lseek(&fp_dst, 0);
|
||||||
|
|
||||||
// Open file for reading.
|
// Open file for reading.
|
||||||
f_chdrive(src);
|
f_chdrive(src);
|
||||||
@@ -298,15 +300,12 @@ static int _stat_and_copy_files(const char *src, const char *dst, char *path, u3
|
|||||||
u32 chunk_size = MIN(file_bytes_left, SZ_4M); // 4MB chunks.
|
u32 chunk_size = MIN(file_bytes_left, SZ_4M); // 4MB chunks.
|
||||||
file_bytes_left -= chunk_size;
|
file_bytes_left -= chunk_size;
|
||||||
|
|
||||||
u32 res1;
|
|
||||||
// Copy file to buffer.
|
// Copy file to buffer.
|
||||||
res1 = f_read(&fp_src, (void *)SDXC_BUF_ALIGNED, chunk_size, NULL);
|
f_read(&fp_src, (void *)SDXC_BUF_ALIGNED, chunk_size, NULL);
|
||||||
DBG_PRINT_ARGS("res read: %d", res1);
|
|
||||||
manual_system_maintenance(true);
|
manual_system_maintenance(true);
|
||||||
|
|
||||||
// Write file to disk.
|
// Write file to disk.
|
||||||
res1 = f_write(&fp_dst, (void *)SDXC_BUF_ALIGNED, chunk_size, NULL);
|
f_write(&fp_dst, (void *)SDXC_BUF_ALIGNED, chunk_size, NULL);
|
||||||
DBG_PRINT_ARGS("res write: %d", res1);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -584,6 +583,10 @@ static void _prepare_and_flash_mbr_gpt()
|
|||||||
_create_gpt_partition(gpt, &gpt_idx, &gpt_next_lba, part_info.hos_size << 11, true, "hos_data", basic_part_guid, NULL, true);
|
_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.
|
// 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;
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(part_info.emu_sd_size){
|
if(part_info.emu_sd_size){
|
||||||
@@ -610,6 +613,11 @@ static void _prepare_and_flash_mbr_gpt()
|
|||||||
_create_gpt_partition(gpt, &gpt_idx, &gpt_next_lba, (emu_sd_size - 1) << 11, false, part_name, basic_part_guid, NULL, true);
|
_create_gpt_partition(gpt, &gpt_idx, &gpt_next_lba, (emu_sd_size - 1) << 11, false, part_name, basic_part_guid, NULL, true);
|
||||||
// clear windows hidden attributes
|
// clear windows hidden attributes
|
||||||
gpt->entries[gpt_idx - 1].part_guid[7] = 0;
|
gpt->entries[gpt_idx - 1].part_guid[7] = 0;
|
||||||
|
if ((part_info.and_size || part_info.l4t_size) && !part_info.hos_size && i == 1) {
|
||||||
|
// Set legacy bootable attribute, necessary for uboot to consider this partition
|
||||||
|
// Only set if no dedicated hos_data FAT32 partition so that this partition can be used for booting
|
||||||
|
gpt->entries[gpt_idx - 1].attrs = 4;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1063,7 +1071,8 @@ static int _get_available_android_partition()
|
|||||||
gpt_t *gpt = zalloc(sizeof(gpt_t));
|
gpt_t *gpt = zalloc(sizeof(gpt_t));
|
||||||
|
|
||||||
// Read main GPT.
|
// Read main GPT.
|
||||||
sdmmc_storage_read(&sd_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.
|
// Check if GPT.
|
||||||
if (memcmp(&gpt->header.signature, "EFI PART", 8) || gpt->header.num_part_ents > 128)
|
if (memcmp(&gpt->header.signature, "EFI PART", 8) || gpt->header.num_part_ents > 128)
|
||||||
@@ -1794,8 +1803,11 @@ static int _backup_and_restore_files(bool backup, const char *drive, lv_obj_t **
|
|||||||
|
|
||||||
// Copy all or hekate/Nyx files.
|
// Copy all or hekate/Nyx files.
|
||||||
DBG_PRINT("start stat");
|
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);
|
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_mws, (u32)backup_pld, total_files);
|
||||||
|
|
||||||
// If incomplete backup mode, copy MWS and payload.bin also.
|
// If incomplete backup mode, copy MWS and payload.bin also.
|
||||||
if (!res)
|
if (!res)
|
||||||
{
|
{
|
||||||
@@ -1999,8 +2011,6 @@ static lv_res_t _create_mbox_start_partitioning(lv_obj_t *btn)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DBG_PRINT("backup done");
|
|
||||||
|
|
||||||
if(part_info.drive == DRIVE_SD){
|
if(part_info.drive == DRIVE_SD){
|
||||||
sd_unmount();
|
sd_unmount();
|
||||||
}else{
|
}else{
|
||||||
@@ -2042,7 +2052,6 @@ static lv_res_t _create_mbox_start_partitioning(lv_obj_t *btn)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
lv_label_set_text(lbl_status, "#00ddff Status:# Formatting FAT32 partition...");
|
lv_label_set_text(lbl_status, "#00ddff Status:# Formatting FAT32 partition...");
|
||||||
manual_system_maintenance(true);
|
manual_system_maintenance(true);
|
||||||
|
|
||||||
@@ -2096,10 +2105,11 @@ static lv_res_t _create_mbox_start_partitioning(lv_obj_t *btn)
|
|||||||
if(part_info.drive == DRIVE_SD){
|
if(part_info.drive == DRIVE_SD){
|
||||||
sd_mount();
|
sd_mount();
|
||||||
}else{
|
}else{
|
||||||
DBG_PRINT_ARGS("emmc mount %d", emmc_mount());
|
emmc_mount();
|
||||||
}
|
}
|
||||||
|
|
||||||
f_setlabel(part_info.drive == DRIVE_SD ? "sd:SWITCH SD" : "emmc:SWITCH EMMC");
|
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(boot_storage_get_drive() != part_info.drive){
|
||||||
// if we havent booted from the drive currently being formatted, create .no_boot_storage
|
// if we havent booted from the drive currently being formatted, create .no_boot_storage
|
||||||
@@ -3026,7 +3036,6 @@ static void _create_mbox_check_files_total_size(u8 drive)
|
|||||||
bool has_hos_data = false;
|
bool has_hos_data = false;
|
||||||
|
|
||||||
sdmmc_storage_t *storage = drive == DRIVE_SD ? &sd_storage : &emmc_storage;
|
sdmmc_storage_t *storage = drive == DRIVE_SD ? &sd_storage : &emmc_storage;
|
||||||
total_size = storage->sec_cnt;
|
|
||||||
|
|
||||||
// Read current MBR.
|
// Read current MBR.
|
||||||
sdmmc_storage_read(storage, 0, 1, mbr);
|
sdmmc_storage_read(storage, 0, 1, mbr);
|
||||||
@@ -3109,6 +3118,8 @@ static void _create_mbox_check_files_total_size(u8 drive)
|
|||||||
lv_obj_set_width(h1, lv_obj_get_width(mbox) - LV_DPI * 3);
|
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_hos_size = 0;
|
||||||
u32 bar_emu_size = 0;
|
u32 bar_emu_size = 0;
|
||||||
u32 bar_l4t_size = 0;
|
u32 bar_l4t_size = 0;
|
||||||
@@ -3186,19 +3197,20 @@ static void _create_mbox_check_files_total_size(u8 drive)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
// 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);
|
lv_coord_t w = lv_obj_get_width(h1);
|
||||||
bar_remaining_size = w * (bar_remaining_size / SECTORS_PER_GB) / (total_size / SECTORS_PER_GB);
|
bar_l4t_size = w * (bar_l4t_size / SECTORS_PER_GB) / total_size_gb;
|
||||||
bar_remaining_size = bar_remaining_size <= 7 ? 0 : bar_remaining_size;
|
bar_and_size = w * (bar_and_size / SECTORS_PER_GB) / total_size_gb;
|
||||||
bar_l4t_size = w * (bar_l4t_size / SECTORS_PER_GB) / (total_size / SECTORS_PER_GB);
|
bar_hos_os_size = w * (bar_hos_os_size / SECTORS_PER_GB) / total_size_gb;
|
||||||
bar_and_size = w * (bar_and_size / SECTORS_PER_GB) / (total_size / SECTORS_PER_GB);
|
bar_hos_size = w * (bar_hos_size / SECTORS_PER_GB) / total_size_gb;
|
||||||
bar_hos_os_size = w * (bar_hos_os_size / SECTORS_PER_GB) / (total_size / SECTORS_PER_GB);
|
bar_emu_size = w * (bar_emu_size / SECTORS_PER_GB) / total_size_gb;
|
||||||
bar_hos_size = w * (bar_hos_size / SECTORS_PER_GB) / (total_size / SECTORS_PER_GB);
|
bar_emu_sd_size = w * (bar_emu_sd_size / SECTORS_PER_GB) / total_size_gb;
|
||||||
bar_emu_size = w * (bar_emu_size / SECTORS_PER_GB) / (total_size / SECTORS_PER_GB);
|
// bar_remaining_size = w * (bar_remaining_size / SECTORS_PER_GB) / (total_size / SECTORS_PER_GB);
|
||||||
bar_emu_sd_size = w * (bar_emu_sd_size / SECTORS_PER_GB) / (total_size / SECTORS_PER_GB);
|
|
||||||
// bar_remaining_size = w - bar_emu_sd_size - 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;
|
// bar_remaining_size = bar_remaining_size <= 7 ? 0 : bar_remaining_size;
|
||||||
|
bar_remaining_size = w - bar_emu_sd_size - 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.
|
// Create HOS OS bar.
|
||||||
lv_obj_t *bar_hos_os = lv_bar_create(h1, NULL);
|
lv_obj_t *bar_hos_os = lv_bar_create(h1, NULL);
|
||||||
@@ -3265,7 +3277,7 @@ static void _create_mbox_check_files_total_size(u8 drive)
|
|||||||
|
|
||||||
// Create emuSD separator.
|
// Create emuSD separator.
|
||||||
lv_obj_t *sep_emu_sd = lv_cont_create(h1, NULL);
|
lv_obj_t *sep_emu_sd = lv_cont_create(h1, NULL);
|
||||||
lv_obj_set_size(sep_emu_sd, bar_emu_sd_size && (bar_emu_size || bar_and_size || bar_remaining_size || bar_l4t_size)? 8 : 0, LV_DPI / 3);
|
lv_obj_set_size(sep_emu_sd, bar_emu_sd_size && (bar_and_size || bar_remaining_size || bar_l4t_size)? 8 : 0, LV_DPI / 3);
|
||||||
lv_obj_set_style(sep_emu_sd, &sep_emu_sd_bg);
|
lv_obj_set_style(sep_emu_sd, &sep_emu_sd_bg);
|
||||||
lv_obj_align(sep_emu_sd, bar_emu_sd, LV_ALIGN_OUT_RIGHT_MID, -4, 0);
|
lv_obj_align(sep_emu_sd, bar_emu_sd, LV_ALIGN_OUT_RIGHT_MID, -4, 0);
|
||||||
|
|
||||||
@@ -3985,9 +3997,9 @@ lv_res_t create_window_partition_manager(lv_obj_t *btn, u8 drive)
|
|||||||
lv_obj_t *slider_and = lv_slider_create(h1, NULL);
|
lv_obj_t *slider_and = lv_slider_create(h1, NULL);
|
||||||
lv_obj_set_size(slider_and, LV_DPI * 7, LV_DPI / 3);
|
lv_obj_set_size(slider_and, LV_DPI * 7, LV_DPI / 3);
|
||||||
#ifdef ENABLE_DUAL_ANDROID
|
#ifdef ENABLE_DUAL_ANDROID
|
||||||
lv_slider_set_range(slider_and, 0, ((part_info.total_sct_available - extra_sct) / SECTORS_PER_GB - 4) * 2); // Subtract android reserved size.
|
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
|
#else
|
||||||
lv_slider_set_range(slider_and, 0, (part_info.total_sct_available - extra_sct) / SECTORS_PER_GB - 4); // Subtract android reserved size.
|
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
|
#endif
|
||||||
lv_slider_set_value(slider_and, part_info.and_size >> 10);
|
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_BG, &bar_and_bg);
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
* Copyright (c) 2018 naehrwert
|
* Copyright (c) 2018 naehrwert
|
||||||
* Copyright (c) 2018 st4rk
|
* Copyright (c) 2018 st4rk
|
||||||
* Copyright (c) 2018 Ced2911
|
* Copyright (c) 2018 Ced2911
|
||||||
* Copyright (c) 2018-2024 CTCaer
|
* Copyright (c) 2018-2025 CTCaer
|
||||||
* Copyright (c) 2018 balika011
|
* Copyright (c) 2018 balika011
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
@@ -77,7 +77,7 @@ static const u8 master_kekseed_620[SE_KEY_128_SIZE] =
|
|||||||
|
|
||||||
//!TODO: Update on mkey changes.
|
//!TODO: Update on mkey changes.
|
||||||
static const u8 master_kekseed_t210_max[SE_KEY_128_SIZE] =
|
static const u8 master_kekseed_t210_max[SE_KEY_128_SIZE] =
|
||||||
{ 0xD7, 0x63, 0x74, 0x46, 0x4E, 0xBA, 0x78, 0x0A, 0x7C, 0x9D, 0xB3, 0xE8, 0x7A, 0x3D, 0x71, 0xE3 }; // 19.0.0.
|
{ 0xA1, 0x7D, 0x34, 0xDB, 0x2D, 0x9D, 0xDA, 0xE5, 0xF8, 0x15, 0x63, 0x4C, 0x8F, 0xE7, 0x6C, 0xD8 }; // 20.0.0.
|
||||||
|
|
||||||
//!TODO: Update on mkey changes.
|
//!TODO: Update on mkey changes.
|
||||||
static const u8 master_kekseed_t210b01[HOS_KB_VERSION_MAX - HOS_KB_VERSION_600 + 1][SE_KEY_128_SIZE] = {
|
static const u8 master_kekseed_t210b01[HOS_KB_VERSION_MAX - HOS_KB_VERSION_600 + 1][SE_KEY_128_SIZE] = {
|
||||||
@@ -95,6 +95,7 @@ static const u8 master_kekseed_t210b01[HOS_KB_VERSION_MAX - HOS_KB_VERSION_600 +
|
|||||||
{ 0x8D, 0xEE, 0x9E, 0x11, 0x36, 0x3A, 0x9B, 0x0A, 0x6A, 0xC7, 0xBB, 0xE9, 0xD1, 0x03, 0xF7, 0x80 }, // 17.0.0.
|
{ 0x8D, 0xEE, 0x9E, 0x11, 0x36, 0x3A, 0x9B, 0x0A, 0x6A, 0xC7, 0xBB, 0xE9, 0xD1, 0x03, 0xF7, 0x80 }, // 17.0.0.
|
||||||
{ 0x4F, 0x41, 0x3C, 0x3B, 0xFB, 0x6A, 0x01, 0x2A, 0x68, 0x9F, 0x83, 0xE9, 0x53, 0xBD, 0x16, 0xD2 }, // 18.0.0.
|
{ 0x4F, 0x41, 0x3C, 0x3B, 0xFB, 0x6A, 0x01, 0x2A, 0x68, 0x9F, 0x83, 0xE9, 0x53, 0xBD, 0x16, 0xD2 }, // 18.0.0.
|
||||||
{ 0x31, 0xBE, 0x25, 0xFB, 0xDB, 0xB4, 0xEE, 0x49, 0x5C, 0x77, 0x05, 0xC2, 0x36, 0x9F, 0x34, 0x80 }, // 19.0.0.
|
{ 0x31, 0xBE, 0x25, 0xFB, 0xDB, 0xB4, 0xEE, 0x49, 0x5C, 0x77, 0x05, 0xC2, 0x36, 0x9F, 0x34, 0x80 }, // 19.0.0.
|
||||||
|
{ 0x1A, 0x31, 0x62, 0x87, 0xA8, 0x09, 0xCA, 0xF8, 0x69, 0x15, 0x45, 0xC2, 0x6B, 0xAA, 0x5A, 0x8A }, // 20.0.0.
|
||||||
};
|
};
|
||||||
|
|
||||||
static const u8 console_keyseed[SE_KEY_128_SIZE] =
|
static const u8 console_keyseed[SE_KEY_128_SIZE] =
|
||||||
@@ -127,6 +128,7 @@ static const u8 mkey_vectors[HOS_KB_VERSION_MAX + 1][SE_KEY_128_SIZE] = {
|
|||||||
{ 0x25, 0x12, 0x8B, 0xCB, 0xB5, 0x46, 0xA1, 0xF8, 0xE0, 0x52, 0x15, 0xB7, 0x0B, 0x57, 0x00, 0xBD }, // Mkey 15 encrypted with mkey 16.
|
{ 0x25, 0x12, 0x8B, 0xCB, 0xB5, 0x46, 0xA1, 0xF8, 0xE0, 0x52, 0x15, 0xB7, 0x0B, 0x57, 0x00, 0xBD }, // Mkey 15 encrypted with mkey 16.
|
||||||
{ 0x58, 0x15, 0xD2, 0xF6, 0x8A, 0xE8, 0x19, 0xAB, 0xFB, 0x2D, 0x52, 0x9D, 0xE7, 0x55, 0xF3, 0x93 }, // Mkey 16 encrypted with mkey 17.
|
{ 0x58, 0x15, 0xD2, 0xF6, 0x8A, 0xE8, 0x19, 0xAB, 0xFB, 0x2D, 0x52, 0x9D, 0xE7, 0x55, 0xF3, 0x93 }, // Mkey 16 encrypted with mkey 17.
|
||||||
{ 0x4A, 0x01, 0x3B, 0xC7, 0x44, 0x6E, 0x45, 0xBD, 0xE6, 0x5E, 0x2B, 0xEC, 0x07, 0x37, 0x52, 0x86 }, // Mkey 17 encrypted with mkey 18.
|
{ 0x4A, 0x01, 0x3B, 0xC7, 0x44, 0x6E, 0x45, 0xBD, 0xE6, 0x5E, 0x2B, 0xEC, 0x07, 0x37, 0x52, 0x86 }, // Mkey 17 encrypted with mkey 18.
|
||||||
|
{ 0x97, 0xE4, 0x11, 0xAB, 0x22, 0x72, 0x1A, 0x1F, 0x70, 0x5C, 0x00, 0xB3, 0x96, 0x30, 0x05, 0x28 }, // Mkey 18 encrypted with mkey 19.
|
||||||
};
|
};
|
||||||
|
|
||||||
//!TODO: Update on mkey changes.
|
//!TODO: Update on mkey changes.
|
||||||
@@ -147,6 +149,7 @@ static const u8 new_console_keyseed[HOS_KB_VERSION_MAX - HOS_KB_VERSION_400 + 1]
|
|||||||
{ 0xDA, 0xB9, 0xD6, 0x77, 0x52, 0x2D, 0x1F, 0x78, 0x73, 0xC9, 0x98, 0x5B, 0x06, 0xFE, 0xA0, 0x52 }, // 17.0.0 New Device Key Source.
|
{ 0xDA, 0xB9, 0xD6, 0x77, 0x52, 0x2D, 0x1F, 0x78, 0x73, 0xC9, 0x98, 0x5B, 0x06, 0xFE, 0xA0, 0x52 }, // 17.0.0 New Device Key Source.
|
||||||
{ 0x14, 0xF5, 0xA5, 0xD0, 0x73, 0x6D, 0x44, 0x80, 0x5F, 0x31, 0x5A, 0x8F, 0x1E, 0xD4, 0x0D, 0x63 }, // 18.0.0 New Device Key Source.
|
{ 0x14, 0xF5, 0xA5, 0xD0, 0x73, 0x6D, 0x44, 0x80, 0x5F, 0x31, 0x5A, 0x8F, 0x1E, 0xD4, 0x0D, 0x63 }, // 18.0.0 New Device Key Source.
|
||||||
{ 0x07, 0x38, 0x9A, 0xEC, 0x9C, 0xBD, 0x50, 0x4A, 0x4C, 0x1F, 0x04, 0xDA, 0x40, 0x68, 0x29, 0xE3 }, // 19.0.0 New Device Key Source.
|
{ 0x07, 0x38, 0x9A, 0xEC, 0x9C, 0xBD, 0x50, 0x4A, 0x4C, 0x1F, 0x04, 0xDA, 0x40, 0x68, 0x29, 0xE3 }, // 19.0.0 New Device Key Source.
|
||||||
|
{ 0xA3, 0x6B, 0x0A, 0xB5, 0x6F, 0x57, 0x4C, 0x5E, 0x00, 0xFD, 0x56, 0x21, 0xF5, 0x06, 0x6B, 0xD1 }, // 20.0.0 New Device Key Source.
|
||||||
};
|
};
|
||||||
|
|
||||||
//!TODO: Update on mkey changes.
|
//!TODO: Update on mkey changes.
|
||||||
@@ -167,6 +170,7 @@ static const u8 new_console_kekseed[HOS_KB_VERSION_MAX - HOS_KB_VERSION_400 + 1]
|
|||||||
{ 0x21, 0xD6, 0x35, 0xF1, 0x0F, 0x7A, 0xF0, 0x5D, 0xDF, 0x79, 0x1C, 0x7A, 0xE4, 0x32, 0x82, 0x9E }, // 17.0.0 New Device Keygen Source.
|
{ 0x21, 0xD6, 0x35, 0xF1, 0x0F, 0x7A, 0xF0, 0x5D, 0xDF, 0x79, 0x1C, 0x7A, 0xE4, 0x32, 0x82, 0x9E }, // 17.0.0 New Device Keygen Source.
|
||||||
{ 0xE7, 0x85, 0x8C, 0xA2, 0xF4, 0x49, 0xCB, 0x07, 0xD1, 0x8E, 0x48, 0x1B, 0xE8, 0x1E, 0x28, 0x3B }, // 18.0.0 New Device Keygen Source.
|
{ 0xE7, 0x85, 0x8C, 0xA2, 0xF4, 0x49, 0xCB, 0x07, 0xD1, 0x8E, 0x48, 0x1B, 0xE8, 0x1E, 0x28, 0x3B }, // 18.0.0 New Device Keygen Source.
|
||||||
{ 0x9B, 0xA5, 0xFD, 0x74, 0x7F, 0xCD, 0x23, 0xD1, 0xD9, 0xBD, 0x6C, 0x51, 0x72, 0x5F, 0x3D, 0x1F }, // 19.0.0 New Device Keygen Source.
|
{ 0x9B, 0xA5, 0xFD, 0x74, 0x7F, 0xCD, 0x23, 0xD1, 0xD9, 0xBD, 0x6C, 0x51, 0x72, 0x5F, 0x3D, 0x1F }, // 19.0.0 New Device Keygen Source.
|
||||||
|
{ 0xDA, 0xFB, 0x61, 0x39, 0x48, 0x2D, 0xC2, 0x7E, 0x0D, 0x8E, 0x8F, 0x98, 0x57, 0x20, 0xB8, 0x15 }, // 20.0.0 New Device Keygen Source.
|
||||||
};
|
};
|
||||||
|
|
||||||
static const u8 gen_keyseed[SE_KEY_128_SIZE] =
|
static const u8 gen_keyseed[SE_KEY_128_SIZE] =
|
||||||
@@ -270,7 +274,7 @@ static void _hos_eks_save()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get keys.
|
// Get keys.
|
||||||
u8 *keys = (u8 *)calloc(2, SZ_4K);
|
u8 *keys = (u8 *)zalloc(SZ_8K);
|
||||||
se_get_aes_keys(keys + SZ_4K, keys, SE_KEY_128_SIZE);
|
se_get_aes_keys(keys + SZ_4K, keys, SE_KEY_128_SIZE);
|
||||||
|
|
||||||
// Set magic and personalized info.
|
// Set magic and personalized info.
|
||||||
@@ -334,21 +338,6 @@ out:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int hos_keygen_t210b01(u32 kb)
|
|
||||||
{
|
|
||||||
// Use SBK as Device key 4x unsealer and KEK for mkey in T210B01 units.
|
|
||||||
se_aes_unwrap_key(10, 14, console_keyseed_4xx);
|
|
||||||
|
|
||||||
// Derive master key.
|
|
||||||
se_aes_unwrap_key(7, 12, master_kekseed_t210b01[kb - HOS_KB_VERSION_600]);
|
|
||||||
se_aes_unwrap_key(7, 7, master_keyseed_retail);
|
|
||||||
|
|
||||||
// Derive latest pkg2 key.
|
|
||||||
se_aes_unwrap_key(8, 7, package2_keyseed);
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int hos_keygen(void *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt)
|
int hos_keygen(void *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt)
|
||||||
{
|
{
|
||||||
u32 retries = 0;
|
u32 retries = 0;
|
||||||
@@ -359,8 +348,21 @@ int hos_keygen(void *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt)
|
|||||||
if (kb > HOS_KB_VERSION_MAX)
|
if (kb > HOS_KB_VERSION_MAX)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
// Do Mariko keygen.
|
||||||
if (h_cfg.t210b01)
|
if (h_cfg.t210b01)
|
||||||
return hos_keygen_t210b01(kb);
|
{
|
||||||
|
// Use SBK as Device key 4x unsealer and KEK for mkey in T210B01 units.
|
||||||
|
se_aes_unwrap_key(10, 14, console_keyseed_4xx);
|
||||||
|
|
||||||
|
// Derive master key.
|
||||||
|
se_aes_unwrap_key(7, 12, master_kekseed_t210b01[kb - HOS_KB_VERSION_600]);
|
||||||
|
se_aes_unwrap_key(7, 7, master_keyseed_retail);
|
||||||
|
|
||||||
|
// Derive latest pkg2 key.
|
||||||
|
se_aes_unwrap_key(8, 7, package2_keyseed);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
// Do Erista keygen.
|
// Do Erista keygen.
|
||||||
|
|
||||||
|
|||||||
@@ -46,7 +46,8 @@ enum {
|
|||||||
HOS_KB_VERSION_1700 = 16,
|
HOS_KB_VERSION_1700 = 16,
|
||||||
HOS_KB_VERSION_1800 = 17,
|
HOS_KB_VERSION_1800 = 17,
|
||||||
HOS_KB_VERSION_1900 = 18,
|
HOS_KB_VERSION_1900 = 18,
|
||||||
HOS_KB_VERSION_MAX = HOS_KB_VERSION_1900
|
HOS_KB_VERSION_2000 = 19,
|
||||||
|
HOS_KB_VERSION_MAX = HOS_KB_VERSION_2000
|
||||||
};
|
};
|
||||||
|
|
||||||
#define HOS_TSEC_VERSION 4 //! TODO: Update on TSEC Root Key changes.
|
#define HOS_TSEC_VERSION 4 //! TODO: Update on TSEC Root Key changes.
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2018 naehrwert
|
* Copyright (c) 2018 naehrwert
|
||||||
* Copyright (c) 2018 st4rk
|
* Copyright (c) 2018 st4rk
|
||||||
* Copyright (c) 2018-2024 CTCaer
|
* Copyright (c) 2018-2025 CTCaer
|
||||||
* Copyright (c) 2018 balika011
|
* Copyright (c) 2018 balika011
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
@@ -39,7 +39,7 @@ static const u8 sec_map_100[3] = { PK11_SECTION_SM, PK11_SECTION_LD, PK11_SECTIO
|
|||||||
static const u8 sec_map_2xx[3] = { PK11_SECTION_WB, PK11_SECTION_LD, PK11_SECTION_SM };
|
static const u8 sec_map_2xx[3] = { PK11_SECTION_WB, PK11_SECTION_LD, PK11_SECTION_SM };
|
||||||
static const u8 sec_map_4xx[3] = { PK11_SECTION_LD, PK11_SECTION_SM, PK11_SECTION_WB };
|
static const u8 sec_map_4xx[3] = { PK11_SECTION_LD, PK11_SECTION_SM, PK11_SECTION_WB };
|
||||||
|
|
||||||
// ID (Timestamp), KB, TSEC, PK11, SECMON, Warmboot.
|
// Timestamp KB TSEC PK11 SECMON Warmboot
|
||||||
static const pkg1_id_t _pkg1_ids[] = {
|
static const pkg1_id_t _pkg1_ids[] = {
|
||||||
{ "20161121", 0, 0x1900, 0x3FE0, 0x40014020, 0x8000D000 }, // 1.0.0.
|
{ "20161121", 0, 0x1900, 0x3FE0, 0x40014020, 0x8000D000 }, // 1.0.0.
|
||||||
{ "20170210", 0, 0x1900, 0x3FE0, 0x4002D000, 0x8000D000 }, // 2.0.0 - 2.3.0.
|
{ "20170210", 0, 0x1900, 0x3FE0, 0x4002D000, 0x8000D000 }, // 2.0.0 - 2.3.0.
|
||||||
@@ -67,7 +67,8 @@ static const pkg1_id_t _pkg1_ids[] = {
|
|||||||
{ "20230111", 15, 0x0E00, 0x6FE0, 0x40030000, 0x4003E000 }, // 16.0.0 - 16.1.0.
|
{ "20230111", 15, 0x0E00, 0x6FE0, 0x40030000, 0x4003E000 }, // 16.0.0 - 16.1.0.
|
||||||
{ "20230906", 16, 0x0E00, 0x6FE0, 0x40030000, 0x4003E000 }, // 17.0.0 - 17.0.1.
|
{ "20230906", 16, 0x0E00, 0x6FE0, 0x40030000, 0x4003E000 }, // 17.0.0 - 17.0.1.
|
||||||
{ "20240207", 17, 0x0E00, 0x6FE0, 0x40030000, 0x4003E000 }, // 18.0.0 - 18.1.0.
|
{ "20240207", 17, 0x0E00, 0x6FE0, 0x40030000, 0x4003E000 }, // 18.0.0 - 18.1.0.
|
||||||
{ "20240808", 18, 0x0E00, 0x6FE0, 0x40030000, 0x4003E000 }, // 19.0.0+
|
{ "20240808", 18, 0x0E00, 0x6FE0, 0x40030000, 0x4003E000 }, // 19.0.0 - 19.0.1.
|
||||||
|
{ "20250206", 19, 0x0E00, 0x6FE0, 0x40030000, 0x4003E000 }, // 20.0.0+
|
||||||
};
|
};
|
||||||
|
|
||||||
const pkg1_id_t *pkg1_identify(u8 *pkg1, char *build_date)
|
const pkg1_id_t *pkg1_identify(u8 *pkg1, char *build_date)
|
||||||
@@ -124,7 +125,7 @@ const u8 *pkg1_unpack(void *wm_dst, void *sm_dst, void *ldr_dst, const pkg1_id_t
|
|||||||
// Get correct header mapping.
|
// Get correct header mapping.
|
||||||
if (id->kb == HOS_KB_VERSION_100 && !memcmp(id->id, "20161121", 8))
|
if (id->kb == HOS_KB_VERSION_100 && !memcmp(id->id, "20161121", 8))
|
||||||
sec_map = sec_map_100;
|
sec_map = sec_map_100;
|
||||||
else if (id->kb >= HOS_KB_VERSION_100 && id->kb <= HOS_KB_VERSION_301)
|
else if (id->kb <= HOS_KB_VERSION_301)
|
||||||
sec_map = sec_map_2xx;
|
sec_map = sec_map_2xx;
|
||||||
else
|
else
|
||||||
sec_map = sec_map_4xx;
|
sec_map = sec_map_4xx;
|
||||||
|
|||||||
@@ -115,6 +115,8 @@ static const u8 mkey_vector_7xx[HOS_KB_VERSION_MAX - HOS_KB_VERSION_810 + 1][SE_
|
|||||||
{ 0x58, 0x15, 0xD2, 0xF6, 0x8A, 0xE8, 0x19, 0xAB, 0xFB, 0x2D, 0x52, 0x9D, 0xE7, 0x55, 0xF3, 0x93 },
|
{ 0x58, 0x15, 0xD2, 0xF6, 0x8A, 0xE8, 0x19, 0xAB, 0xFB, 0x2D, 0x52, 0x9D, 0xE7, 0x55, 0xF3, 0x93 },
|
||||||
// Master key 17 encrypted with 18. (18.0.0 with 19.0.0)
|
// Master key 17 encrypted with 18. (18.0.0 with 19.0.0)
|
||||||
{ 0x4A, 0x01, 0x3B, 0xC7, 0x44, 0x6E, 0x45, 0xBD, 0xE6, 0x5E, 0x2B, 0xEC, 0x07, 0x37, 0x52, 0x86 },
|
{ 0x4A, 0x01, 0x3B, 0xC7, 0x44, 0x6E, 0x45, 0xBD, 0xE6, 0x5E, 0x2B, 0xEC, 0x07, 0x37, 0x52, 0x86 },
|
||||||
|
// Master key 18 encrypted with 19. (19.0.0 with 20.0.0)
|
||||||
|
{ 0x97, 0xE4, 0x11, 0xAB, 0x22, 0x72, 0x1A, 0x1F, 0x70, 0x5C, 0x00, 0xB3, 0x96, 0x30, 0x05, 0x28 },
|
||||||
};
|
};
|
||||||
|
|
||||||
static bool _pkg2_key_unwrap_validate(pkg2_hdr_t *tmp_test, pkg2_hdr_t *hdr, u8 src_slot, u8 *mkey, const u8 *key_seed)
|
static bool _pkg2_key_unwrap_validate(pkg2_hdr_t *tmp_test, pkg2_hdr_t *hdr, u8 src_slot, u8 *mkey, const u8 *key_seed)
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2018 naehrwert
|
* Copyright (c) 2018 naehrwert
|
||||||
* Copyright (c) 2018-2023 CTCaer
|
* Copyright (c) 2018-2025 CTCaer
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
* under the terms and conditions of the GNU General Public License,
|
* under the terms and conditions of the GNU General Public License,
|
||||||
@@ -20,16 +20,17 @@
|
|||||||
|
|
||||||
#include <bdk.h>
|
#include <bdk.h>
|
||||||
|
|
||||||
#define PKG2_MAGIC 0x31324B50
|
#define PKG2_MAGIC 0x31324B50
|
||||||
#define PKG2_SEC_BASE 0x80000000
|
#define PKG2_SEC_BASE 0x80000000
|
||||||
#define PKG2_SEC_KERNEL 0
|
#define PKG2_SEC_KERNEL 0
|
||||||
#define PKG2_SEC_INI1 1
|
#define PKG2_SEC_INI1 1
|
||||||
|
#define PKG2_SEC_UNUSED 2
|
||||||
|
|
||||||
#define INI1_MAGIC 0x31494E49
|
#define INI1_MAGIC 0x31494E49
|
||||||
|
|
||||||
//! TODO: Update on kernel change if needed.
|
//! TODO: Update on kernel change if needed.
|
||||||
// Offset of OP + 12 is the INI1 offset. On v2 with dynamic crt0 it's + 16.
|
// Offset of OP + 12 is the INI1 offset. On v2 with dynamic crt0 it's + 16.
|
||||||
#define PKG2_NEWKERN_GET_INI1_HEURISTIC 0xD2800015
|
#define PKG2_NEWKERN_GET_INI1_HEURISTIC 0xD2800015 // MOV X21, #0.
|
||||||
#define PKG2_NEWKERN_START 0x800
|
#define PKG2_NEWKERN_START 0x800
|
||||||
|
|
||||||
extern u32 pkg2_newkern_ini1_start;
|
extern u32 pkg2_newkern_ini1_start;
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ _reloc_ipl:
|
|||||||
|
|
||||||
_real_start:
|
_real_start:
|
||||||
/* We place our stack in SDRAM. */
|
/* We place our stack in SDRAM. */
|
||||||
LDR SP, =0x83100000
|
LDR SP, =0x4003F000
|
||||||
LDR R0, =__bss_start
|
LDR R0, =__bss_start
|
||||||
EOR R1, R1, R1
|
EOR R1, R1, R1
|
||||||
LDR R2, =__bss_end
|
LDR R2, =__bss_end
|
||||||
|
|||||||
@@ -1,8 +1,12 @@
|
|||||||
#include "sfd.h"
|
#include "sfd.h"
|
||||||
#include <storage/emmc.h>
|
#include <storage/emmc.h>
|
||||||
#include <storage/sdmmc.h>
|
#include <storage/sdmmc.h>
|
||||||
|
#include <storage/file_based_storage.h>
|
||||||
#include <libs/fatfs/diskio.h>
|
#include <libs/fatfs/diskio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
|
||||||
|
static bool file_based;
|
||||||
static sdmmc_storage_t *_storage;
|
static sdmmc_storage_t *_storage;
|
||||||
static u32 _offset;
|
static u32 _offset;
|
||||||
static u32 _size;
|
static u32 _size;
|
||||||
@@ -14,7 +18,11 @@ static void ensure_partition(){
|
|||||||
}
|
}
|
||||||
|
|
||||||
sdmmc_storage_t *sfd_get_storage(){
|
sdmmc_storage_t *sfd_get_storage(){
|
||||||
return _storage;
|
if(file_based){
|
||||||
|
return NULL;
|
||||||
|
}else{
|
||||||
|
return _storage;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int sfd_read(u32 sector, u32 count, void *buff){
|
int sfd_read(u32 sector, u32 count, void *buff){
|
||||||
@@ -22,8 +30,13 @@ int sfd_read(u32 sector, u32 count, void *buff){
|
|||||||
if(sector + count > _size){
|
if(sector + count > _size){
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
ensure_partition();
|
|
||||||
res = sdmmc_storage_read(_storage, sector + _offset, count, buff);
|
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;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -32,8 +45,14 @@ int sfd_write(u32 sector, u32 count, void *buff){
|
|||||||
if(sector + count > _size){
|
if(sector + count > _size){
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
ensure_partition();
|
|
||||||
res = sdmmc_storage_write(_storage, sector + _offset, count, buff);
|
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;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -45,10 +64,23 @@ bool sfd_init(sdmmc_storage_t *storage, u32 offset, u32 size){
|
|||||||
return true;
|
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(){
|
void sfd_end(){
|
||||||
_storage = NULL;
|
_storage = NULL;
|
||||||
_offset = 0;
|
_offset = 0;
|
||||||
_size = 0;
|
_size = 0;
|
||||||
u32 size = 0;
|
u32 size = 0;
|
||||||
|
file_based = false;
|
||||||
disk_set_info(DRIVE_SFD, SET_SECTOR_COUNT, &size);
|
disk_set_info(DRIVE_SFD, SET_SECTOR_COUNT, &size);
|
||||||
}
|
}
|
||||||
@@ -7,6 +7,7 @@
|
|||||||
int sfd_read(u32 sector, u32 count, void *buff);
|
int sfd_read(u32 sector, u32 count, void *buff);
|
||||||
int sfd_write(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);
|
bool sfd_init(sdmmc_storage_t *storage, u32 offset, u32 size);
|
||||||
void sfd_end();
|
void sfd_end();
|
||||||
|
|
||||||
|
|||||||
@@ -9,10 +9,13 @@ autonogc=1
|
|||||||
updater2p=1
|
updater2p=1
|
||||||
bootprotect=0
|
bootprotect=0
|
||||||
|
|
||||||
|
# Only include above what you want to change from defaults.
|
||||||
|
# config.c in bootloader and Nyx have all the defaults.
|
||||||
|
|
||||||
|
|
||||||
{-------- Stock -------}
|
{-------- Stock -------}
|
||||||
[Stock]
|
[Stock]
|
||||||
fss0=atmosphere/package3
|
pkg3=atmosphere/package3
|
||||||
stock=1
|
stock=1
|
||||||
emummc_force_disable=1
|
emummc_force_disable=1
|
||||||
|
|
||||||
@@ -26,7 +29,7 @@ emummc_force_disable=1
|
|||||||
|
|
||||||
{-- Custom Firmwares --}
|
{-- Custom Firmwares --}
|
||||||
[Atmo Vanilla]
|
[Atmo Vanilla]
|
||||||
fss0=atmosphere/package3
|
pkg3=atmosphere/package3
|
||||||
kip1=atmosphere/kips/*
|
kip1=atmosphere/kips/*
|
||||||
|
|
||||||
# Note:
|
# Note:
|
||||||
@@ -36,11 +39,11 @@ kip1=atmosphere/kips/*
|
|||||||
|
|
||||||
|
|
||||||
[Atmo EMU]
|
[Atmo EMU]
|
||||||
fss0=atmosphere/package3
|
pkg3=atmosphere/package3
|
||||||
emummcforce=1
|
emummcforce=1
|
||||||
|
|
||||||
[Atmo SYS]
|
[Atmo SYS]
|
||||||
fss0=atmosphere/package3
|
pkg3=atmosphere/package3
|
||||||
emummc_force_disable=1
|
emummc_force_disable=1
|
||||||
|
|
||||||
# Note:
|
# Note:
|
||||||
@@ -55,7 +58,7 @@ emummc_force_disable=1
|
|||||||
|
|
||||||
|
|
||||||
[Atmo EMU2]
|
[Atmo EMU2]
|
||||||
fss0=atmosphere/package3
|
pkg3=atmosphere/package3
|
||||||
emupath=emuMMC/SD02
|
emupath=emuMMC/SD02
|
||||||
emummcforce=1
|
emummcforce=1
|
||||||
|
|
||||||
@@ -68,26 +71,26 @@ emummcforce=1
|
|||||||
|
|
||||||
|
|
||||||
[Atmo with extra kips]
|
[Atmo with extra kips]
|
||||||
fss0=atmosphere/package3
|
pkg3=atmosphere/package3
|
||||||
kip1=cfw/mods/mods_extra/*
|
kip1=cfw/mods/mods_extra/*
|
||||||
kip1=cfw/mods/mods_extra/single/extra.kip
|
kip1=cfw/mods/mods_extra/single/extra.kip
|
||||||
|
|
||||||
# Note:
|
# Note:
|
||||||
# The above can be used with any fss0 entry. Like the ones above.
|
# The above can be used with any pkg3 entry. Like the ones above.
|
||||||
# You can even override atmosphere (fss0) kips with this.
|
# You can even override atmosphere (pkg3) kips with this.
|
||||||
# The wildcard '*' like above can be used to load all kips from a selected directory.
|
# The wildcard '*' like above can be used to load all kips from a selected directory.
|
||||||
|
|
||||||
|
|
||||||
{-- Custom Firmwares Old methods --}
|
{-- Custom Firmwares Old methods --}
|
||||||
[CFW FSS0 extra kips & patches]
|
[CFW PKG3 extra kips & patches]
|
||||||
fss0=atmosphere/package3
|
pkg3=atmosphere/package3
|
||||||
kip1patch=name_of_patch
|
kip1patch=name_of_patch
|
||||||
kip1=cfw/mods/mods_extra/*
|
kip1=cfw/mods/mods_extra/*
|
||||||
kip1=cfw/mods/mods_extra/single/extra.kip
|
kip1=cfw/mods/mods_extra/single/extra.kip
|
||||||
|
|
||||||
# Note:
|
# Note:
|
||||||
# Both options for kip1 can be used. Wildcard and single.
|
# Both options for kip1 can be used. Wildcard and single.
|
||||||
# You can override kips loaded from FSS0/PKG3 if you define them after the fss0 key.
|
# You can override kips loaded from PKG3/FSS0 if you define them after the pkg3 key.
|
||||||
# If kip1 patch resides in patches.ini and that file OR the patch for
|
# If kip1 patch resides in patches.ini and that file OR the patch for
|
||||||
# current HOS version does not exist, it will error out.
|
# current HOS version does not exist, it will error out.
|
||||||
|
|
||||||
@@ -106,7 +109,7 @@ atmosphere=1
|
|||||||
|
|
||||||
# Note:
|
# Note:
|
||||||
# All kips defined method. This can be changed to what is below also.
|
# All kips defined method. This can be changed to what is below also.
|
||||||
# atmosphere=1 key is IMPORTANT when no FFS0 is defined.
|
# atmosphere=1 key is IMPORTANT when no PKG3/FSS0 is defined.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user