Compare commits

..

No commits in common. "master" and "v6.2.1" have entirely different histories.

84 changed files with 1072 additions and 1632 deletions

View file

@ -48,7 +48,7 @@ OBJS += $(addprefix $(BUILDDIR)/$(TARGET)/, \
# Horizon.
OBJS += $(addprefix $(BUILDDIR)/$(TARGET)/, \
hos.o hos_config.o pkg1.o pkg2.o pkg3.o pkg2_ini_kippatch.o secmon_exo.o \
hos.o hos_config.o pkg1.o pkg2.o pkg2_ini_kippatch.o fss.o secmon_exo.o \
)
# Libraries.
@ -76,15 +76,15 @@ CUSTOMDEFINES += -DGFX_INC=$(GFX_INC) -DFFCFG_INC=$(FFCFG_INC)
# UART Logging: Max baudrate 12.5M.
# DEBUG_UART_PORT - 0: UART_A, 1: UART_B, 2: UART_C.
#CUSTOMDEFINES += -DDEBUG_UART_BAUDRATE=115200 -DDEBUG_UART_INVERT=0 -DDEBUG_UART_PORT=1
#CUSTOMDEFINES += -DDEBUG_UART_BAUDRATE=115200 -DDEBUG_UART_INVERT=0 -DDEBUG_UART_PORT=0
#TODO: Considering reinstating some of these when pointer warnings have been fixed.
WARNINGS := -Wall -Wsign-compare -Wtype-limits -Wno-array-bounds -Wno-stringop-overread -Wno-stringop-overflow
WARNINGS := -Wall -Wsign-compare -Wno-array-bounds -Wno-stringop-overread -Wno-stringop-overflow
#-fno-delete-null-pointer-checks
#-Wstack-usage=byte-size -fstack-usage
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 $(CUSTOMDEFINES)
ARCH := -march=armv4t -mtune=arm7tdmi -mthumb -mthumb-interwork
CFLAGS = $(ARCH) -O2 -g -gdwarf-4 -nostdlib -ffunction-sections -fdata-sections -fomit-frame-pointer -fno-inline -std=gnu11 $(WARNINGS) $(CUSTOMDEFINES)
LDFLAGS = $(ARCH) -nostartfiles -lgcc -Wl,--nmagic,--gc-sections -Xlinker --defsym=IPL_LOAD_ADDR=$(IPL_LOAD_ADDR)
MODULEDIRS := $(wildcard modules/*)
@ -101,14 +101,15 @@ TOOLS := $(TOOLSLZ) $(TOOLSB2C)
all: $(TARGET).bin $(LDRDIR)
@printf ICTC49 >> $(OUTPUTDIR)/$(TARGET).bin
@echo "--------------------------------------"
@echo "$(TARGET) size:"
@echo -n "Uncompr: "
@echo -n "Uncompr size: "
$(eval BIN_SIZE = $(shell wc -c < $(OUTPUTDIR)/$(TARGET)_unc.bin))
@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
@echo -n "Payload: "
@echo -n "Payload size: "
$(eval BIN_SIZE = $(shell wc -c < $(OUTPUTDIR)/$(TARGET).bin))
@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
@echo "--------------------------------------"
@ -125,7 +126,7 @@ $(NYXDIR):
$(LDRDIR): $(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.01.lz payload_01
@$(TOOLSB2C)/bin2c payload_00 > $(LDRDIR)/payload_00.h
@ -138,11 +139,11 @@ $(TOOLS):
@$(MAKE) --no-print-directory -C $@ $(MAKECMDGOALS) -$(MAKEFLAGS)
$(TARGET).bin: $(BUILDDIR)/$(TARGET)/$(TARGET).elf $(MODULEDIRS) $(NYXDIR) $(TOOLS)
@$(OBJCOPY) -S -O binary $< $(OUTPUTDIR)/$@
$(OBJCOPY) -S -O binary $< $(OUTPUTDIR)/$@
$(BUILDDIR)/$(TARGET)/$(TARGET).elf: $(OBJS)
@$(CC) $(LDFLAGS) -T $(SOURCEDIR)/link.ld $^ -o $@
@printf "$(TARGET) was built with the following flags:\nCFLAGS: $(CFLAGS)\nLDFLAGS: $(LDFLAGS)\n"
@echo "hekate was built with the following flags:\nCFLAGS: "$(CFLAGS)"\nLDFLAGS: "$(LDFLAGS)
$(BUILDDIR)/$(TARGET)/%.o: %.c
@echo Building $@

View file

@ -50,14 +50,13 @@ Custom Graphical Nintendo Switch bootloader, firmware patcher, tools, and many m
| \|__ background.bmp | Nyx - Custom background. User provided. |
| \|__ icon_switch.bmp | Nyx - Default icon for CFWs. |
| \|__ icon_payload.bmp | Nyx - Default icon for Payloads. |
| bootloader/sys/ | hekate and Nyx system modules folder. !Important! |
| \|__ emummc.kipm | emuMMC KIP1 module. |
| \|__ libsys_lp0.bso | LP0 (sleep mode) module. |
| \|__ libsys_minerva.bso | Minerva Training Cell. Used for DRAM Frequency training. |
| \|__ nyx.bin | Nyx - hekate's GUI. |
| \|__ res.pak | Nyx resources package. |
| \|__ thk.bin | Atmosphère Tsec Hovi Keygen. |
| \|__ /l4t/ | Folder with firmware relevant to L4T (Linux/Android). |
| bootloader/sys/ | hekate and Nyx system modules folder. |
| \|__ emummc.kipm | emuMMC KIP1 module. !Important! |
| \|__ libsys_lp0.bso | LP0 (sleep mode) module. Important! |
| \|__ libsys_minerva.bso | Minerva Training Cell. Used for DRAM Frequency training. !Important! |
| \|__ nyx.bin | Nyx - hekate's GUI. !Important! |
| \|__ res.pak | Nyx resources package. !Important! |
| \|__ thk.bin | Atmosphère Tsec Hovi Keygen. !Important! |
| 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/libtools/ | Reserved |
@ -78,7 +77,7 @@ There are four possible type of entries. "**[ ]**": Boot entry, "**{ }**": Capti
### hekate Global Configuration keys/values (when entry is *[config]*):
| Config option | Description |
| ------------------ | -------------------------------------------------------------- |
| ------------------ | ---------------------------------------------------------- |
| 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). |
| 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. |
@ -99,20 +98,18 @@ There are four possible type of entries. "**[ ]**": Boot entry, "**{ }**": Capti
| kernel={FILE path} | Replaces the kernel binary |
| 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. |
| pkg3={FILE path} | Takes an Atmosphere `package3` binary and `extracts` all needed parts from it. kips, exosphere, warmboot and mesophere. |
| 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`. |
| 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. |
| fss0experimental=1 | Enables loading of experimental content from a FSS0 storage |
| exofatal={FILE path} | Replaces the exosphere fatal binary for Mariko |
| ---------------------- | ---------------------------------------------------------- |
| kip1patch=patchname | Enables a kip1 patch. Allows multiple and `,` as separator. If actual patch is not found, a warning will show up. |
| 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 |
| 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. |
| 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 | Disables unneeded kernel patching and CFW kips when running stock or semi-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. |
| debugmode=1 | Enables Debug mode. Obsolete when used with exosphere as secmon. |
| kernelprocid=1 | Enables stock kernel process id send/recv patching. Not needed when `pkg3`/`fss0` is used. |
| atmosphere=1 | Enables Atmosphère patching. Not needed when `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. |
| ---------------------- | ---------------------------------------------------------- |
@ -122,7 +119,6 @@ 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_vddq=600 | L4T RAM VDDQ Voltage. Set VDDQ (T210B01). 550-650. |
| 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. |
| ---------------------- | ---------------------------------------------------------- |
| bootwait=3 | Overrides global bootwait from `[config]`. |
@ -133,11 +129,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.
**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`.
**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`.
You can define `kip1` to load an extra kip or many via the wildcard (`/*`) usage.
**Warning**: Careful when you override *pkg3/fss core* kips with `kip1`.
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.
**Warning**: Careful when you define *fss0 core* kips when using `fss0` or the folder (when using `/*`) includes them.
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.
### Boot entry key/value combinations for Exosphère:
@ -159,7 +155,7 @@ That's in case the kips are incompatible between them. If compatible, you can ov
### Payload storage:
hekate has a boot storage in the binary that helps it configure it outside of BPMP environment:
hekate has a boot storage in the binary that helps it configure it outside of BPMP enviroment:
| Offset / Name | Description |
| ----------------------- | ----------------------------------------------------------------- |
@ -192,9 +188,9 @@ hekate has a boot storage in the binary that helps it configure it outside of BP
```
hekate (c) 2018, naehrwert, st4rk.
(c) 2018-2025, CTCaer.
(c) 2018-2024, CTCaer.
Nyx GUI (c) 2019-2025, CTCaer.
Nyx GUI (c) 2019-2024, CTCaer.
Thanks to: derrek, nedwill, plutoo, shuffle2, smea, thexyz, yellows8.
Greetings to: fincs, hexkyz, SciresM, Shiny Quagsire, WinterMute.

View file

@ -1,11 +1,11 @@
# IPL Version.
BLVERSION_MAJOR := 6
BLVERSION_MINOR := 3
BLVERSION_MINOR := 2
BLVERSION_HOTFX := 1
BLVERSION_REL := 0
# Nyx Version.
NYXVERSION_MAJOR := 1
NYXVERSION_MINOR := 7
NYXVERSION_HOTFX := 0
NYXVERSION_MINOR := 6
NYXVERSION_HOTFX := 3
NYXVERSION_REL := 0

View file

@ -49,7 +49,6 @@
#include <soc/gpio.h>
#include <soc/hw_init.h>
#include <soc/i2c.h>
#include <soc/irq.h>
#include <soc/kfuse.h>
#include <soc/pinmux.h>
#include <soc/pmc.h>

View file

@ -1,6 +1,6 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2025 CTCaer
* Copyright (c) 2018-2024 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
@ -265,9 +265,16 @@ int display_dsi_vblank_read(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 fifo32[DSI_STATUS_TX_FIFO_SIZE] = {0};
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.
if (len >= 2)
@ -312,8 +319,15 @@ void display_dsi_write(u8 cmd, u32 len, void *data)
void display_dsi_vblank_write(u8 cmd, u32 len, void *data)
{
u32 fifo32[DSI_STATUS_TX_FIFO_SIZE] = {0};
u8 *fifo8 = (u8 *)fifo32;
static u8 *fifo8 = NULL;
static u32 *fifo32 = NULL;
// Allocate fifo buffer.
if (!fifo32)
{
fifo32 = malloc(DSI_STATUS_RX_FIFO_SIZE * 8 * sizeof(u32));
fifo8 = (u8 *)fifo32;
}
// Prepare data for long write.
if (len >= 2)
@ -557,7 +571,7 @@ void display_init()
* When switching to the 16ff pad brick, the clock lane termination control
* 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
* in one time calibration on T210B01. Trigger calibration twice.
* in one time calibration. Trigger calibration twice.
*/
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++)
@ -921,7 +935,7 @@ void display_move_framebuffer(u32 window, void *fb)
DISPLAY_A(_DIREG(DC_CMD_DISPLAY_WINDOW_HEADER)) = BIT(WINDOW_SELECT + window);
// Get current framebuffer address.
const void *fb_curr = (void *)DISPLAY_A(_DIREG(DC_WINBUF_START_ADDR));
void *fb_curr = (void *)DISPLAY_A(_DIREG(DC_WINBUF_START_ADDR));
u32 win_size = DISPLAY_A(_DIREG(DC_WIN_PRESCALED_SIZE));
win_size = (win_size & 0x7FFF) * ((win_size >> 16) & 0x1FFF);

View file

@ -1,6 +1,6 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2025 CTCaer
* Copyright (c) 2018-2024 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
@ -520,7 +520,6 @@
#define DSI_STATUS 0x15
#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_DATA_0 0x1B
@ -718,7 +717,7 @@
#define MIPI_DCS_READ_DDB_CONTINUE 0xA8 // 0x100 size.
/*! MIPI DCS Panel Private CMDs. */
#define MIPI_DCS_PRIV_SM_SET_COLOR_MODE 0xA0 // 43 bytes.
#define MIPI_DCS_PRIV_SM_SET_COLOR_MODE 0xA0
#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_SET_POWER_CONTROL 0xB1
@ -728,7 +727,6 @@
#define MIPI_DCS_PRIV_UNK_D6 0xD6
#define MIPI_DCS_PRIV_UNK_D8 0xD8
#define MIPI_DCS_PRIV_UNK_D9 0xD9
#define MIPI_DCS_PRIV_SM_DISPLAY_ID 0xDD
// 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_READ_EXTC_CMD_SPI 0xFE // Read EXTC Command In SPI. 1 byte. 0-6: EXT_SPI_CNT, 7:EXT_SP.
@ -767,21 +765,19 @@
#define DCS_CONTROL_DISPLAY_SM_FLASHLIGHT BIT(2)
#define DCS_CONTROL_DISPLAY_BACKLIGHT_CTRL BIT(2)
#define DCS_CONTROL_DISPLAY_DIMMING_CTRL BIT(3) // Transition fading.
#define DCS_CONTROL_DISPLAY_DIMMING_CTRL BIT(3)
#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. Based on Vivid but over-saturated.
#define DCS_SM_COLOR_MODE_SATURATED 0x00 // Disabled. Similar to vivid but over-saturated. Wide gamut?
#define DCS_SM_COLOR_MODE_WASHED 0x45
#define DCS_SM_COLOR_MODE_BASIC 0x03 // Real natural profile.
#define DCS_SM_COLOR_MODE_BASIC 0x03
#define DCS_SM_COLOR_MODE_POR_RESET 0x20 // Reset value on power on.
#define DCS_SM_COLOR_MODE_NATURAL 0x23 // Not actually natural.. Extra saturation.
#define DCS_SM_COLOR_MODE_VIVID 0x65 // Saturated.
#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_NIGHT2 0x35 // Based on Natural.
#define DCS_SM_COLOR_MODE_NIGHT3 0x75 // Based on Vivid.
#define DCS_SM_COLOR_MODE_NATURAL 0x23 // Not actually natural..
#define DCS_SM_COLOR_MODE_VIVID 0x65
#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_NIGHT2 0x35 // Based on natural.
#define DCS_SM_COLOR_MODE_NIGHT3 0x75 // Based on vivid.
#define DCS_SM_COLOR_MODE_ENABLE BIT(0)

View file

@ -390,7 +390,7 @@ static int _vic_wait_idle()
return 0;
}
void vic_set_surface(const vic_surface_t *sfc)
void vic_set_surface(vic_surface_t *sfc)
{
u32 flip_x = 0;
u32 flip_y = 0;

View file

@ -58,7 +58,7 @@ typedef struct _vic_surface_t
u32 rotation;
} vic_surface_t;
void vic_set_surface(const vic_surface_t *sfc);
void vic_set_surface(vic_surface_t *sfc);
int vic_compose();
int vic_init();
void vic_end();

View file

@ -70,6 +70,8 @@ void set_als_cfg(als_ctxt_t *als_ctxt, u8 gain, u8 cycle)
if (!cycle)
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_TIMING_REG), (256 - cycle));

View file

@ -22,6 +22,7 @@
#include <gfx_utils.h>
#include <power/max17050.h>
#include <power/regulator_5v.h>
#include <soc/bpmp.h>
#include <soc/clock.h>
#include <soc/fuse.h>
#include <soc/gpio.h>
@ -222,8 +223,8 @@ typedef struct _jc_hid_in_rpt_t
{
u8 cmd;
u8 pkt_id;
u8 conn_info:4; // Connection detect.
u8 batt_info:4; // Power info.
u8 conn_info:4;
u8 batt_info:4;
u8 btn_right;
u8 btn_shared;
u8 btn_left;
@ -316,10 +317,9 @@ typedef struct _joycon_ctxt_t
u8 uart;
u8 type;
u8 state;
u8 mac[6];
u32 last_received_time;
u32 last_status_req_time;
u8 mac[6];
u8 pkt_id;
u8 rumble_sent;
u8 connected;
u8 detected;
@ -330,10 +330,11 @@ static joycon_ctxt_t jc_l = {0};
static joycon_ctxt_t jc_r = {0};
static bool jc_init_done = false;
static u32 hid_pkt_inc = 0;
static jc_gamepad_rpt_t jc_gamepad;
static u8 _jc_crc(const u8 *data, u16 len, u8 init)
static u8 _jc_crc(u8 *data, u16 len, u8 init)
{
u8 crc = init;
for (u16 i = 0; i < len; i++)
@ -447,7 +448,7 @@ static void _jc_conn_check()
if (jc_l.connected)
_jc_power_supply(UART_C, false);
jc_l.pkt_id = 0;
hid_pkt_inc = 0;
jc_l.connected = false;
jc_l.rumble_sent = false;
@ -464,7 +465,7 @@ static void _jc_conn_check()
if (jc_r.connected)
_jc_power_supply(UART_B, false);
jc_r.pkt_id = 0;
hid_pkt_inc = 0;
jc_r.connected = false;
jc_r.rumble_sent = false;
@ -483,7 +484,7 @@ static void _joycon_send_raw(u8 uart_port, const u8 *buf, u16 size)
uart_wait_xfer(uart_port, UART_TX_IDLE);
}
static u16 _jc_packet_add_uart_hdr(jc_wired_hdr_t *out, u8 wired_cmd, const u8 *data, u16 size, bool crc)
static u16 _jc_packet_add_uart_hdr(jc_wired_hdr_t *out, u8 wired_cmd, u8 *data, u16 size, bool crc)
{
out->uart_hdr.magic[0] = 0x19;
out->uart_hdr.magic[1] = 0x01;
@ -503,7 +504,7 @@ static u16 _jc_packet_add_uart_hdr(jc_wired_hdr_t *out, u8 wired_cmd, const u8 *
return sizeof(jc_wired_hdr_t);
}
static u16 _jc_hid_output_rpt_craft(jc_wired_hdr_t *rpt, const u8 *payload, u16 size, bool crc)
static u16 _jc_hid_output_rpt_craft(jc_wired_hdr_t *rpt, u8 *payload, u16 size, bool crc)
{
u16 pkt_size = _jc_packet_add_uart_hdr(rpt, JC_WIRED_HID, NULL, 0, crc);
pkt_size += size;
@ -518,18 +519,22 @@ static u16 _jc_hid_output_rpt_craft(jc_wired_hdr_t *rpt, const u8 *payload, u16
return pkt_size;
}
static void _jc_send_hid_output_rpt(joycon_ctxt_t *jc, jc_hid_out_rpt_t *hid_pkt, u16 size, bool crc)
static void _jc_send_hid_output_rpt(u8 uart, u8 *payload, u16 size, bool crc)
{
u8 rpt[0x50];
memset(rpt, 0, sizeof(rpt));
hid_pkt->pkt_id = (jc->pkt_id++ & 0xF);
u32 rpt_size = _jc_hid_output_rpt_craft((jc_wired_hdr_t *)rpt, (u8 *)hid_pkt, size, crc);
u32 rpt_size = _jc_hid_output_rpt_craft((jc_wired_hdr_t *)rpt, payload, size, crc);
_joycon_send_raw(jc->uart, rpt, rpt_size);
_joycon_send_raw(uart, rpt, rpt_size);
}
static void _jc_send_hid_cmd(joycon_ctxt_t *jc, u8 subcmd, const u8 *data, u16 size)
static u8 _jc_hid_pkt_id_incr()
{
return (hid_pkt_inc++ & 0xF);
}
static void _jc_send_hid_cmd(u8 uart, u8 subcmd, u8 *data, u16 size)
{
static const u8 rumble_neutral[8] = { 0x00, 0x01, 0x40, 0x40, 0x00, 0x01, 0x40, 0x40 };
static const u8 rumble_init[8] = { 0xc2, 0xc8, 0x03, 0x72, 0xc2, 0xc8, 0x03, 0x72 };
@ -546,43 +551,47 @@ static void _jc_send_hid_cmd(joycon_ctxt_t *jc, u8 subcmd, const u8 *data, u16 s
// Enable rumble.
hid_pkt->cmd = JC_HID_OUTPUT_RPT;
hid_pkt->pkt_id = _jc_hid_pkt_id_incr();
hid_pkt->subcmd = JC_HID_SUBCMD_RUMBLE_CTL;
hid_pkt->subcmd_data[0] = 1;
if (send_r_rumble)
_jc_send_hid_output_rpt(&jc_r, hid_pkt, 0x10, false);
_jc_send_hid_output_rpt(UART_B, (u8 *)hid_pkt, 0x10, false);
if (send_l_rumble)
_jc_send_hid_output_rpt(&jc_l, hid_pkt, 0x10, false);
_jc_send_hid_output_rpt(UART_C, (u8 *)hid_pkt, 0x10, false);
// Send rumble.
hid_pkt->cmd = JC_HID_RUMBLE_RPT;
hid_pkt->pkt_id = _jc_hid_pkt_id_incr();
memcpy(hid_pkt->rumble, rumble_init, sizeof(rumble_init));
if (send_r_rumble)
_jc_send_hid_output_rpt(&jc_r, hid_pkt, 10, false);
_jc_send_hid_output_rpt(UART_B, (u8 *)hid_pkt, 10, false);
if (send_l_rumble)
_jc_send_hid_output_rpt(&jc_l, hid_pkt, 10, false);
_jc_send_hid_output_rpt(UART_C, (u8 *)hid_pkt, 10, false);
msleep(15);
// Disable rumble.
hid_pkt->cmd = JC_HID_OUTPUT_RPT;
hid_pkt->pkt_id = _jc_hid_pkt_id_incr();
hid_pkt->subcmd = JC_HID_SUBCMD_RUMBLE_CTL;
hid_pkt->subcmd_data[0] = 0;
memcpy(hid_pkt->rumble, rumble_neutral, sizeof(rumble_neutral));
if (send_r_rumble)
_jc_send_hid_output_rpt(&jc_r, hid_pkt, 0x10, false);
_jc_send_hid_output_rpt(UART_B, (u8 *)hid_pkt, 0x10, false);
if (send_l_rumble)
_jc_send_hid_output_rpt(&jc_l, hid_pkt, 0x10, false);
_jc_send_hid_output_rpt(UART_C, (u8 *)hid_pkt, 0x10, false);
}
else
{
bool crc_needed = jc->type & JC_ID_HORI;
bool crc_needed = (jc_l.uart == uart) ? (jc_l.type & JC_ID_HORI) : (jc_r.type & JC_ID_HORI);
hid_pkt->cmd = JC_HID_OUTPUT_RPT;
hid_pkt->pkt_id = _jc_hid_pkt_id_incr();
hid_pkt->subcmd = subcmd;
if (data)
memcpy(hid_pkt->subcmd_data, data, size);
_jc_send_hid_output_rpt(jc, hid_pkt, sizeof(jc_hid_out_rpt_t) + size, crc_needed);
_jc_send_hid_output_rpt(uart, (u8 *)hid_pkt, sizeof(jc_hid_out_rpt_t) + size, crc_needed);
}
}
@ -814,7 +823,7 @@ static bool _jc_send_init_rumble(joycon_ctxt_t *jc)
// Send init rumble or request nx pad status report.
if ((jc_r.connected && !jc_r.rumble_sent) || (jc_l.connected && !jc_l.rumble_sent))
{
_jc_send_hid_cmd(jc, JC_HID_SUBCMD_SND_RUMBLE, NULL, 0);
_jc_send_hid_cmd(jc->uart, JC_HID_SUBCMD_SND_RUMBLE, NULL, 0);
if (jc_l.connected)
jc_l.rumble_sent = true;
@ -855,7 +864,7 @@ static void _jc_req_nx_pad_status(joycon_ctxt_t *jc)
jc->last_status_req_time = get_tmr_ms() + (!jc->sio_mode ? 15 : 7);
}
static bool _jc_validate_pairing_info(const u8 *buf, bool *is_hos)
static bool _jc_validate_pairing_info(u8 *buf, bool *is_hos)
{
u8 crc = 0;
for (u32 i = 0; i < 0x22; i++)
@ -924,13 +933,13 @@ retry:
{
if (!jc_l_found)
{
_jc_send_hid_cmd(&jc_l, JC_HID_SUBCMD_SPI_READ, (u8 *)&subcmd_data_l, 5);
_jc_send_hid_cmd(jc_l.uart, JC_HID_SUBCMD_SPI_READ, (u8 *)&subcmd_data_l, 5);
jc_l.last_status_req_time = get_tmr_ms() + 15;
}
if (!jc_r_found)
{
_jc_send_hid_cmd(&jc_r, JC_HID_SUBCMD_SPI_READ, (u8 *)&subcmd_data_r, 5);
_jc_send_hid_cmd(jc_r.uart, JC_HID_SUBCMD_SPI_READ, (u8 *)&subcmd_data_r, 5);
jc_r.last_status_req_time = get_tmr_ms() + 15;
}
@ -1121,7 +1130,7 @@ static void _jc_init_conn(joycon_ctxt_t *jc)
// Initialize the controller.
u32 retries = 10;
while (!jc->connected && retries)
while (!jc->connected)
{
_joycon_send_raw(jc->uart, sio_init, sizeof(sio_init));
msleep(5);
@ -1230,12 +1239,12 @@ void jc_deinit()
u8 data = HCI_STATE_SLEEP;
if (jc_r.connected && !(jc_r.type & JC_ID_HORI))
{
_jc_send_hid_cmd(&jc_r, JC_HID_SUBCMD_HCI_STATE, &data, 1);
_jc_send_hid_cmd(UART_B, JC_HID_SUBCMD_HCI_STATE, &data, 1);
_jc_rcv_pkt(&jc_r);
}
if (jc_l.connected && !(jc_l.type & JC_ID_HORI))
{
_jc_send_hid_cmd(&jc_l, JC_HID_SUBCMD_HCI_STATE, &data, 1);
_jc_send_hid_cmd(UART_C, JC_HID_SUBCMD_HCI_STATE, &data, 1);
_jc_rcv_pkt(&jc_l);
}
}

View file

@ -4698,20 +4698,13 @@ FRESULT f_lseek (
DWORD *f_expand_cltbl (
FIL* fp, /* Pointer to the file object */
UINT tblsz, /* Size of table (2 DWORDs + 2 DWORDs per fragment) */
UINT tblsz, /* Size of table */
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->cltbl) { /* Allocate memory for cluster link table */
fp->cltbl = (DWORD *)ff_memalloc(tblsz);
if (!fp->cltbl) return (void *)0;
fp->cltbl[0] = tblsz;
}
if (f_lseek(fp, CREATE_LINKMAP)) { /* Create cluster link table */

View file

@ -38,7 +38,7 @@ typedef struct
bool emc_2X_clk_src_is_pllmb;
bool fsp_for_src_freq;
bool train_ram_patterns;
u32 init_done;
bool init_done;
} mtc_config_t;
enum train_mode_t

View file

@ -75,7 +75,7 @@ void bm92t36_get_sink_info(bool *inserted, usb_pd_objects_t *usb_pd)
{
memset(buf, 0, sizeof(buf));
_bm92t36_read_reg(buf, 2, STATUS1_REG);
*inserted = (buf[0] & STATUS1_INSERT) ? true : false;
*inserted = buf[0] & STATUS1_INSERT ? true : false;
}
if (usb_pd)

View file

@ -29,8 +29,7 @@ int bq24193_get_property(enum BQ24193_reg_prop prop, int *value)
{
u8 data;
switch (prop)
{
switch (prop) {
case BQ24193_InputVoltageLimit: // Input voltage limit (mV).
data = bq24193_get_reg(BQ24193_InputSource);
data = (data & BQ24193_INCONFIG_VINDPM_MASK) >> 3;

View file

@ -327,7 +327,7 @@ void max77620_config_default()
return;
// Set default voltages and enable regulators.
for (u32 i = REGULATOR_SD1; i <= REGULATOR_LDO8; i++)
for (u32 i = 1; i <= REGULATOR_LDO8; i++)
{
max77620_regulator_config_fps(i);
max7762x_regulator_set_voltage(i, _pmic_regulators[i].uv_default);

View file

@ -1,6 +1,6 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2025 CTCaer
* Copyright (c) 2018-2024 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
@ -19,6 +19,7 @@
#include "se.h"
#include <memory_map.h>
#include <mem/heap.h>
#include <soc/bpmp.h>
#include <soc/hw_init.h>
#include <soc/pmc.h>
@ -181,7 +182,7 @@ static int _se_execute_one_block(u32 op, void *dst, u32 dst_size, const void *sr
if (!src || !dst)
return 0;
u32 block[SE_AES_BLOCK_SIZE / sizeof(u32)] = {0};
u8 *block = (u8 *)zalloc(SE_AES_BLOCK_SIZE);
SE(SE_CRYPTO_BLOCK_COUNT_REG) = 1 - 1;
@ -189,10 +190,11 @@ 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);
memcpy(dst, block, dst_size);
free(block);
return res;
}
static void _se_aes_ctr_set(const void *ctr)
static void _se_aes_ctr_set(void *ctr)
{
u32 data[SE_AES_IV_SIZE / 4];
memcpy(data, ctr, SE_AES_IV_SIZE);
@ -224,7 +226,7 @@ u32 se_key_acc_ctrl_get(u32 ks)
return SE(SE_CRYPTO_KEYTABLE_ACCESS_REG + 4 * ks);
}
void se_aes_key_set(u32 ks, const void *key, u32 size)
void se_aes_key_set(u32 ks, void *key, u32 size)
{
u32 data[SE_AES_MAX_KEY_SIZE / 4];
memcpy(data, key, size);
@ -236,7 +238,7 @@ void se_aes_key_set(u32 ks, const void *key, u32 size)
}
}
void se_aes_iv_set(u32 ks, const void *iv)
void se_aes_iv_set(u32 ks, void *iv)
{
u32 data[SE_AES_IV_SIZE / 4];
memcpy(data, iv, SE_AES_IV_SIZE);
@ -387,8 +389,7 @@ 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 res = 0;
u32 tmp[SE_AES_BLOCK_SIZE / sizeof(u32)];
u8 *tweak = (u8 *)tmp;
u8 *tweak = (u8 *)malloc(SE_AES_BLOCK_SIZE);
u8 *pdst = (u8 *)dst;
u8 *psrc = (u8 *)src;
@ -417,7 +418,8 @@ int se_aes_xts_crypt_sec(u32 tweak_ks, u32 crypt_ks, u32 enc, u64 sec, void *dst
res = 1;
out:
out:;
free(tweak);
return res;
}
@ -512,15 +514,15 @@ int se_calc_sha256(void *hash, u32 *msg_left, const void *src, u32 src_size, u64
return 0;
// Src size of 0 is not supported, so return null string sha256.
if (!src_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,
0x27, 0xAE, 0x41, 0xE4, 0x64, 0x9B, 0x93, 0x4C, 0xA4, 0x95, 0x99, 0x1B, 0x78, 0x52, 0xB8, 0x55
};
memcpy(hash, null_hash, SE_SHA_256_SIZE);
return 1;
}
// if (!src_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,
// 0x27, 0xAE, 0x41, 0xE4, 0x64, 0x9B, 0x93, 0x4C, 0xA4, 0x95, 0x99, 0x1B, 0x78, 0x52, 0xB8, 0x55
// };
// memcpy(hash, null_hash, SE_SHA_256_SIZE);
// return 1;
// }
// 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);
@ -655,11 +657,8 @@ 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 res = 0;
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;
u8 *key = (u8 *)zalloc(SE_KEY_128_SIZE);
u8 *last_block = (u8 *)zalloc(SE_AES_BLOCK_SIZE);
se_aes_iv_clear(ks);
se_aes_iv_updated_clear(ks);
@ -708,6 +707,8 @@ 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++)
dst32[i] = SE(SE_HASH_RESULT_REG + (i * 4));
out:
out:;
free(key);
free(last_block);
return res;
}

View file

@ -25,8 +25,8 @@ void se_rsa_acc_ctrl(u32 rs, u32 flags);
void se_key_acc_ctrl(u32 ks, u32 flags);
u32 se_key_acc_ctrl_get(u32 ks);
void se_get_aes_keys(u8 *buf, u8 *keys, u32 keysize);
void se_aes_key_set(u32 ks, const void *key, u32 size);
void se_aes_iv_set(u32 ks, const void *iv);
void se_aes_key_set(u32 ks, void *key, u32 size);
void se_aes_iv_set(u32 ks, void *iv);
void se_aes_key_get(u32 ks, void *key, u32 size);
void se_aes_key_clear(u32 ks);
void se_aes_iv_clear(u32 ks);

View file

@ -237,7 +237,6 @@ void bpmp_clk_rate_relaxed(bool enable)
// APB clock affects RTC, PWM, MEMFETCH, APE, USB, SOR PWM,
// I2C host, DC/DSI/DISP. UART gives extra stress.
// 92: 100% success ratio. 93-94: 595-602MHz has 99% success ratio. 95: 608MHz less.
// APB clock max is supposed to be 204 MHz though.
static const u8 pll_divn[] = {
0, // BPMP_CLK_NORMAL: 408MHz 0% - 136MHz APB.
85, // BPMP_CLK_HIGH_BOOST: 544MHz 33% - 136MHz APB.
@ -301,13 +300,6 @@ void bpmp_clk_rate_set(bpmp_freq_t fid)
}
}
// State is reset to RUN on any clock or source set via SW.
void bpmp_state_set(bpmp_state_t state)
{
u32 cfg = CLOCK(CLK_RST_CONTROLLER_SCLK_BURST_POLICY) & ~0xF0000000u;
CLOCK(CLK_RST_CONTROLLER_SCLK_BURST_POLICY) = cfg | (state << 28u);
}
// The following functions halt BPMP to reduce power while sleeping.
// They are not as accurate as RTC at big values but they guarantee time+ delay.
void bpmp_usleep(u32 us)

View file

@ -54,16 +54,6 @@ typedef enum
BPMP_CLK_MAX
} bpmp_freq_t;
typedef enum
{
BPMP_STATE_STANDBY = 0, // 32KHz.
BPMP_STATE_IDLE = 1,
BPMP_STATE_RUN = 2,
BPMP_STATE_IRQ = BIT(2),
BPMP_STATE_FIQ = BIT(3),
} bpmp_state_t;
#define BPMP_CLK_LOWEST_BOOST BPMP_CLK_HIGH2_BOOST
#define BPMP_CLK_LOWER_BOOST BPMP_CLK_SUPER_BOOST
#define BPMP_CLK_DEFAULT_BOOST BPMP_CLK_HYPER_BOOST
@ -75,7 +65,6 @@ void bpmp_mmu_disable();
void bpmp_clk_rate_relaxed(bool enable);
void bpmp_clk_rate_get();
void bpmp_clk_rate_set(bpmp_freq_t fid);
void bpmp_state_set(bpmp_state_t state);
void bpmp_usleep(u32 us);
void bpmp_msleep(u32 ms);
void bpmp_halt();

View file

@ -701,7 +701,7 @@ static void _clock_sdmmc_clear_enable(u32 id)
static void _clock_sdmmc_config_legacy_tm()
{
const clk_rst_t *clk = &_clock_sdmmc_legacy_tm;
clk_rst_t *clk = &_clock_sdmmc_legacy_tm;
if (!(CLOCK(clk->enable) & BIT(clk->index)))
clock_enable(clk);
}

View file

@ -150,7 +150,6 @@
#define CLK_RST_CONTROLLER_PLLC_MISC_2 0x5D0
#define CLK_RST_CONTROLLER_PLLC4_OUT 0x5E4
#define CLK_RST_CONTROLLER_PLLMB_BASE 0x5E8
#define CLK_RST_CONTROLLER_PLLMB_MISC1 0x5EC
#define CLK_RST_CONTROLLER_CLK_SOURCE_XUSB_FS 0x608
#define CLK_RST_CONTROLLER_CLK_SOURCE_XUSB_CORE_DEV 0x60C
#define CLK_RST_CONTROLLER_CLK_SOURCE_XUSB_SS 0x610

View file

@ -24,9 +24,7 @@
#include <sec/se_t210.h>
#include <soc/fuse.h>
#include <soc/hw_init.h>
#include <soc/pmc.h>
#include <soc/t210.h>
#include <soc/timer.h>
#include <utils/types.h>
static const u32 evp_thunk_template[] = {
@ -191,7 +189,7 @@ void fuse_read_array(u32 *words)
words[i] = fuse_read(i);
}
static u32 _parity32_even(const u32 *words, u32 count)
static u32 _parity32_even(u32 *words, u32 count)
{
u32 acc = words[0];
for (u32 i = 1; i < count; i++)
@ -305,7 +303,7 @@ int fuse_read_ipatch(void (*ipatch)(u32 offset, u32 value))
u32 words[80];
u32 word_count;
u32 word_addr;
u32 word0;
u32 word0 = 0;
u32 total_read = 0;
word_count = FUSE(FUSE_FIRST_BOOTROM_PATCH_SIZE);
@ -365,7 +363,7 @@ int fuse_read_evp_thunk(u32 *iram_evp_thunks, u32 *iram_evp_thunks_len)
u32 words[80];
u32 word_count;
u32 word_addr;
u32 word0;
u32 word0 = 0;
u32 total_read = 0;
int evp_thunk_written = 0;
void *evp_thunk_dst_addr = 0;

View file

@ -96,7 +96,7 @@ static void _i2c_load_cfg_wait(vu32 *base)
}
}
static int _i2c_send_single(u32 i2c_idx, u32 dev_addr, const u8 *buf, u32 size)
static int _i2c_send_single(u32 i2c_idx, u32 dev_addr, u8 *buf, u32 size)
{
if (size > 8)
return 0;
@ -384,7 +384,7 @@ int i2c_recv_buf_big(u8 *buf, u32 size, u32 i2c_idx, u32 dev_addr, u32 reg)
return _i2c_recv_pkt(i2c_idx, buf, size, dev_addr, reg);
}
int i2c_send_buf_small(u32 i2c_idx, u32 dev_addr, u32 reg, const u8 *buf, u32 size)
int i2c_send_buf_small(u32 i2c_idx, u32 dev_addr, u32 reg, u8 *buf, u32 size)
{
u8 tmp[8];

View file

@ -31,7 +31,7 @@ void i2c_init(u32 i2c_idx);
int i2c_recv_buf(u8 *buf, u32 size, u32 i2c_idx, u32 dev_addr);
int i2c_send_buf_big(u32 i2c_idx, u32 dev_addr, u8 *buf, u32 size);
int i2c_recv_buf_big(u8 *buf, u32 size, u32 i2c_idx, u32 dev_addr, u32 reg);
int i2c_send_buf_small(u32 i2c_idx, u32 dev_addr, u32 reg, const u8 *buf, u32 size);
int i2c_send_buf_small(u32 i2c_idx, u32 dev_addr, u32 reg, u8 *buf, u32 size);
int i2c_recv_buf_small(u8 *buf, u32 size, u32 i2c_idx, u32 dev_addr, u32 reg);
int i2c_send_byte(u32 i2c_idx, u32 dev_addr, u32 reg, u8 val);
u8 i2c_recv_byte(u32 i2c_idx, u32 dev_addr, u32 reg);

View file

@ -124,8 +124,8 @@ static irq_status_t _irq_handle_source(u32 irq)
}
}
// Do not re-enable if not handled or error.
if (status != IRQ_HANDLED)
// Do not re-enable if not handled.
if (status == IRQ_NONE)
return status;
if (irqs[idx].flags & IRQ_FLAG_ONE_OFF)

View file

@ -85,7 +85,6 @@
#define AXBAR_BASE 0x702D0800
#define I2S_BASE 0x702D1000
#define ADMA_BASE 0x702E2000
#define AMC_BASE 0x702EF000
#define SE2_BASE 0x70412000
#define SE_PKA1_BASE 0x70420000
#define TZRAM_BASE 0x7C010000
@ -152,7 +151,6 @@
#define CL_DVFS(off) MMIO_REG32(CL_DVFS_BASE, off)
#define I2S(off) MMIO_REG32(I2S_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 SE_PKA1(off) MMIO_REG32(SE_PKA1_BASE, off)
#define USB(off) MMIO_REG32(USB_BASE, off)
@ -212,7 +210,7 @@
#define AHB_GIZMO_USB 0x20
#define AHB_GIZMO_SDMMC4 0x48
#define AHB_GIZMO_USB2 0x7C
#define AHB_GIZMO_USB3 0x80 // Doesn't exist on T21x??
#define AHB_GIZMO_USB3 0x80
#define AHB_GIZMO_IMMEDIATE BIT(18)
#define AHB_ARBITRATION_XBAR_CTRL 0xE0
#define AHB_AHB_MEM_PREFETCH_CFG3 0xE4
@ -221,9 +219,9 @@
#define AHB_AHB_MEM_PREFETCH_CFG2 0xF4
#define MST_ID(x) (((x) & 0x1F) << 26)
#define MEM_PREFETCH_AHBDMA_MST_ID MST_ID(5)
#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. Doesn't exist on T210B01.
#define MEM_PREFETCH_USB3_MST_ID MST_ID(17) // XUSB. Doesn't exist on T210B01.
#define MEM_PREFETCH_USB_MST_ID MST_ID(6) // USB-OTG.
#define MEM_PREFETCH_USB2_MST_ID MST_ID(18) // USB-HSIC.
#define MEM_PREFETCH_USB3_MST_ID MST_ID(17) // XUSB.
#define MEM_PREFETCH_ADDR_BNDRY(x) (((x) & 0xF) << 21)
#define MEM_PREFETCH_ENABLE BIT(31)
#define AHB_ARBITRATION_AHB_MEM_WRQUE_MST_ID 0xFC

View file

@ -25,8 +25,6 @@
#define EXCP_TYPE_ADDR 0x4003FFF8
#define EXCP_TYPE_WDT 0x544457 // "WDT".
#define USE_RTC_TIMER
u32 get_tmr_s()
{
(void)RTC(APBDEV_RTC_MILLI_SECONDS);

View file

@ -174,14 +174,14 @@ void uart_empty_fifo(u32 idx, u32 which)
(void)uart->UART_SPR;
usleep(96);
uart->UART_IIR_FCR = UART_IIR_FCR_EN_FIFO | which;
uart->UART_IIR_FCR = UART_IIR_FCR_EN_FIFO | UART_IIR_FCR_TX_CLR | UART_IIR_FCR_RX_CLR;
(void)uart->UART_SPR;
usleep(18);
u32 tries = 0;
if (UART_IIR_FCR_TX_CLR & which)
{
while (tries < 10 && !(uart->UART_LSR & UART_LSR_TMTY))
while (tries < 10 && uart->UART_LSR & UART_LSR_TMTY)
{
tries++;
usleep(100);
@ -191,7 +191,7 @@ void uart_empty_fifo(u32 idx, u32 which)
if (UART_IIR_FCR_RX_CLR & which)
{
while (tries < 10 && (uart->UART_LSR & UART_LSR_RDR))
while (tries < 10 && !uart->UART_LSR & UART_LSR_RDR)
{
tries++;
usleep(100);

View file

@ -70,8 +70,6 @@
#define UART_MCR_CTS_EN BIT(5)
#define UART_MCR_RTS_EN BIT(6)
#define UART_FIFO_SIZE 36
typedef struct _uart_t
{
/* 0x00 */ vu32 UART_THR_DLAB;

View file

@ -274,7 +274,7 @@ void *sd_file_read(const char *path, u32 *fsize)
return buf;
}
int sd_save_to_file(const void *buf, u32 size, const char *filename)
int sd_save_to_file(void *buf, u32 size, const char *filename)
{
FIL fp;
u32 res = 0;

View file

@ -61,6 +61,6 @@ void sd_unmount();
void sd_end();
bool sd_is_gpt();
void *sd_file_read(const char *path, u32 *fsize);
int sd_save_to_file(const void *buf, u32 size, const char *filename);
int sd_save_to_file(void *buf, u32 size, const char *filename);
#endif

View file

@ -1,6 +1,6 @@
/*
* Copyright (c) 2005-2007 Pierre Ossman, All Rights Reserved.
* Copyright (c) 2018-2025 CTCaer
* Copyright (c) 2018-2023 CTCaer
*
* 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
@ -17,16 +17,11 @@
#define SD_SEND_RELATIVE_ADDR 3 /* bcr R6 */
#define SD_SEND_IF_COND 8 /* bcr [11:0] See below R7 */
#define SD_SWITCH_VOLTAGE 11 /* ac R1 */
/* Class 2 */
#define SD_ADDR_EXT 22 /* ac [5:0] R1 */
/* class 10 */
#define SD_SWITCH 6 /* adtc [31:0] See below R1 */
/* class 5 */
#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 */
/* class 11 */
#define SD_READ_EXTR_SINGLE 48 /* adtc [31:0] R1 */
#define SD_WRITE_EXTR_SINGLE 49 /* adtc [31:0] R1 */
/* Application commands */
#define SD_APP_SET_BUS_WIDTH 6 /* ac [1:0] bus width R1 */

View file

@ -1,6 +1,6 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2025 CTCaer
* Copyright (c) 2018-2023 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
@ -18,7 +18,6 @@
#include <string.h>
#include <mem/heap.h>
#include <mem/mc.h>
#include <soc/timer.h>
#include <storage/emmc.h>
#include <storage/sdmmc.h>
@ -28,26 +27,14 @@
#include <memory_map.h>
#include <gfx_utils.h>
//#define SDMMC_DEBUG_PRINT_SD_REGS
//#define DPRINTF(...) gfx_printf(__VA_ARGS__)
#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;
static inline u32 unstuff_bits(const u32 *resp, u32 start, u32 size)
static inline u32 unstuff_bits(u32 *resp, u32 start, u32 size)
{
start %= 128;
const u32 mask = (size < 32 ? 1 << size : 0) - 1;
const u32 off = 3 - ((start) / 32);
const u32 shft = (start) & 31;
@ -65,7 +52,7 @@ static inline u32 unstuff_bits(const u32 *resp, u32 start, u32 size)
static int _sdmmc_storage_check_card_status(u32 res)
{
//Error mask:
//!WARN: R1_SWITCH_ERROR is reserved on SD. The card isn't supposed to use it.
//TODO: R1_SWITCH_ERROR can be skipped for certain card types.
if (res &
(R1_OUT_OF_RANGE | R1_ADDRESS_ERROR | R1_BLOCK_LEN_ERROR |
R1_ERASE_SEQ_ERROR | R1_ERASE_PARAM | R1_WP_VIOLATION |
@ -86,7 +73,7 @@ static int _sdmmc_storage_execute_cmd_type1_ex(sdmmc_storage_t *storage, u32 *re
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, NULL, NULL))
return 0;
sdmmc_get_cached_rsp(storage->sdmmc, resp, SDMMC_RSP_TYPE_1);
sdmmc_get_rsp(storage->sdmmc, resp, 4, SDMMC_RSP_TYPE_1);
if (mask)
*resp &= ~mask;
@ -118,7 +105,7 @@ static int _sdmmc_storage_get_cid(sdmmc_storage_t *storage)
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, NULL, NULL))
return 0;
sdmmc_get_cached_rsp(storage->sdmmc, (u32 *)storage->raw_cid, SDMMC_RSP_TYPE_2);
sdmmc_get_rsp(storage->sdmmc, (u32 *)storage->raw_cid, 16, SDMMC_RSP_TYPE_2);
return 1;
}
@ -135,7 +122,7 @@ static int _sdmmc_storage_get_csd(sdmmc_storage_t *storage)
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, NULL, NULL))
return 0;
sdmmc_get_cached_rsp(storage->sdmmc, (u32 *)storage->raw_csd, SDMMC_RSP_TYPE_2);
sdmmc_get_rsp(storage->sdmmc, (u32 *)storage->raw_csd, 16, SDMMC_RSP_TYPE_2);
return 1;
}
@ -164,7 +151,7 @@ int sdmmc_storage_execute_vendor_cmd(sdmmc_storage_t *storage, u32 arg)
return 0;
u32 resp;
sdmmc_get_cached_rsp(storage->sdmmc, &resp, SDMMC_RSP_TYPE_1);
sdmmc_get_rsp(storage->sdmmc, &resp, 4, SDMMC_RSP_TYPE_1);
resp = -1;
u32 timeout = get_tmr_ms() + 1500;
@ -241,10 +228,6 @@ static int _sdmmc_storage_readwrite_ex(sdmmc_storage_t *storage, u32 *blkcnt_out
return 0;
}
sdmmc_get_cached_rsp(storage->sdmmc, &tmp, SDMMC_RSP_TYPE_1);
if (!_sdmmc_storage_check_card_status(tmp))
return 0;
return 1;
}
@ -262,12 +245,40 @@ int sdmmc_storage_end(sdmmc_storage_t *storage)
return 1;
}
static int _sdmmc_storage_handle_io_error(sdmmc_storage_t *storage, bool first_reinit)
static int _sdmmc_storage_readwrite(sdmmc_storage_t *storage, u32 sector, u32 num_sectors, void *buf, u32 is_write)
{
int res = 0;
u8 *bbuf = (u8 *)buf;
u32 sct_off = sector;
u32 sct_total = num_sectors;
bool first_reinit = true;
// Exit if not initialized.
if (!storage->initialized)
return 0;
while (sct_total)
{
u32 blkcnt = 0;
// Retry 5 times if failed.
u32 retries = 5;
do
{
reinit_try:
if (_sdmmc_storage_readwrite_ex(storage, &blkcnt, sct_off, MIN(sct_total, 0xFFFF), bbuf, is_write))
goto out;
else
retries--;
sd_error_count_increment(SD_ERROR_RW_RETRY);
msleep(50);
} while (retries);
// Disk IO failure! Reinit SD/EMMC to a lower speed.
if (storage->sdmmc->id == SDMMC_1 || storage->sdmmc->id == SDMMC_4)
{
int res = 0;
if (storage->sdmmc->id == SDMMC_1)
{
sd_error_count_increment(SD_ERROR_RW_FAIL);
@ -294,63 +305,22 @@ static int _sdmmc_storage_handle_io_error(sdmmc_storage_t *storage, bool first_r
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)
{
u8 *bbuf = (u8 *)buf;
u32 sct_off = sector;
u32 sct_total = num_sectors;
bool first_reinit = true;
// Exit if not initialized.
if (!storage->initialized)
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)
{
u32 blkcnt = 0;
// Retry 5 times if failed.
u32 retries = 5;
do
{
reinit_try:
if (_sdmmc_storage_readwrite_ex(storage, &blkcnt, sct_off, MIN(sct_total, 0xFFFF), bbuf, is_write))
goto out;
else
retries--;
sd_error_count_increment(SD_ERROR_RW_RETRY);
msleep(50);
} while (retries);
// Disk IO failure! Reinit SD/EMMC to a lower speed.
if (_sdmmc_storage_handle_io_error(storage, first_reinit))
{
// Reset values for a retry.
blkcnt = 0;
retries = 3;
first_reinit = false;
// If successful reinit, restart xfer.
if (res)
{
bbuf = (u8 *)buf;
sct_off = sector;
sct_total = num_sectors;
goto reinit_try;
}
}
// Failed.
return 0;
@ -423,7 +393,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))
return 0;
return sdmmc_get_cached_rsp(storage->sdmmc, pout, SDMMC_RSP_TYPE_3);
return sdmmc_get_rsp(storage->sdmmc, pout, 4, SDMMC_RSP_TYPE_3);
}
static int _mmc_storage_get_op_cond(sdmmc_storage_t *storage, u32 power)
@ -561,40 +531,12 @@ int mmc_storage_get_ext_csd(sdmmc_storage_t *storage, void *buf)
return 0;
u32 tmp = 0;
sdmmc_get_cached_rsp(storage->sdmmc, &tmp, SDMMC_RSP_TYPE_1);
sdmmc_get_rsp(storage->sdmmc, &tmp, 4, SDMMC_RSP_TYPE_1);
_mmc_storage_parse_ext_csd(storage, buf);
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)
{
return _sdmmc_storage_execute_cmd_type1(storage, MMC_SWITCH, arg, 1, R1_SKIP_STATE_CHECK);
@ -841,7 +783,7 @@ static int _sd_storage_execute_app_cmd_type1(sdmmc_storage_t *storage, u32 *resp
}
#ifdef SDMMC_DEBUG_PRINT_SD_REGS
void _sd_storage_debug_print_cid(const u32 *raw_cid)
void _sd_storage_debug_print_cid(u32 *raw_cid)
{
gfx_printf("Card Identification\n");
@ -857,7 +799,7 @@ void _sd_storage_debug_print_cid(const u32 *raw_cid)
gfx_printf("--RSVD-- %X\n", unstuff_bits(raw_cid, 20, 4));
}
void _sd_storage_debug_print_csd(const u32 *raw_csd)
void _sd_storage_debug_print_csd(u32 *raw_csd)
{
gfx_printf("\n");
@ -871,7 +813,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("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("C_SIZE: %06X\n", unstuff_bits(raw_csd, 48, 28)); // CSD 3 (SDUC).
gfx_printf("C_SIZE: %06X\n", unstuff_bits(raw_csd, 48, 22));
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));
@ -888,13 +830,13 @@ 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("FILE_FORMAT: %X\n", unstuff_bits(raw_csd, 10, 2));
gfx_printf("--RSVD-- %02X %X %X %02X %X\n",
unstuff_bits(raw_csd, 120, 6),
gfx_printf("--RSVD-- %02X %02X %X %X %02X %X\n",
unstuff_bits(raw_csd, 120, 6), unstuff_bits(raw_csd, 70, 6),
unstuff_bits(raw_csd, 47, 1), unstuff_bits(raw_csd, 29, 2),
unstuff_bits(raw_csd, 16, 5), unstuff_bits(raw_csd, 8, 2));
}
void _sd_storage_debug_print_scr(const u32 *raw_scr)
void _sd_storage_debug_print_scr(u32 *raw_scr)
{
u32 resp[4];
memcpy(&resp[2], raw_scr, 8);
@ -915,7 +857,7 @@ void _sd_storage_debug_print_scr(const u32 *raw_scr)
gfx_printf("--RSVD-- %X\n", unstuff_bits(resp, 36, 2));
}
void _sd_storage_debug_print_ssr(const u8 *raw_ssr)
void _sd_storage_debug_print_ssr(u8 *raw_ssr)
{
u32 raw_ssr0[4]; // 511:384.
u32 raw_ssr1[4]; // 383:256.
@ -928,39 +870,39 @@ void _sd_storage_debug_print_ssr(const u8 *raw_ssr)
gfx_printf("\nSD Status:\n");
gfx_printf("DAT_BUS_WIDTH: %X\n", unstuff_bits(raw_ssr0, 510, 2));
gfx_printf("SECURED_MODE: %X\n", unstuff_bits(raw_ssr0, 509, 1));
gfx_printf("SECURITY_FUNCTIONS: %02X\n", unstuff_bits(raw_ssr0, 502, 6));
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, 32));
gfx_printf("SPEED_CLASS: %02X\n", unstuff_bits(raw_ssr0, 440, 8));
gfx_printf("PERFORMANCE_MOVE: %02X\n", unstuff_bits(raw_ssr0, 432, 8));
gfx_printf("AU_SIZE: %X\n", unstuff_bits(raw_ssr0, 428, 4));
gfx_printf("ERAZE_SIZE: %04X\n", unstuff_bits(raw_ssr0, 408, 16));
gfx_printf("ERASE_TIMEOUT: %02X\n", unstuff_bits(raw_ssr0, 402, 6));
gfx_printf("ERASE_OFFSET: %X\n", unstuff_bits(raw_ssr0, 400, 2));
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, 4));
gfx_printf("VIDEO_SPEED_CLASS: %02X\n", unstuff_bits(raw_ssr0, 384, 8));
gfx_printf("DAT_BUS_WIDTH: %X\n", unstuff_bits(raw_ssr0, 510 - 384, 2));
gfx_printf("SECURED_MODE: %X\n", unstuff_bits(raw_ssr0, 509 - 384, 1));
gfx_printf("SECURITY_FUNCTIONS: %02X\n", unstuff_bits(raw_ssr0, 502 - 384, 6));
gfx_printf("SD_CARD_TYPE: %04X\n", unstuff_bits(raw_ssr0, 480 - 384, 16));
gfx_printf("SZ_OF_PROTECTED_AREA: %08X\n", unstuff_bits(raw_ssr0, 448 - 384, 32));
gfx_printf("SPEED_CLASS: %02X\n", unstuff_bits(raw_ssr0, 440 - 384, 8));
gfx_printf("PERFORMANCE_MOVE: %02X\n", unstuff_bits(raw_ssr0, 432 - 384, 8));
gfx_printf("AU_SIZE: %X\n", unstuff_bits(raw_ssr0, 428 - 384, 4));
gfx_printf("ERAZE_SIZE: %04X\n", unstuff_bits(raw_ssr0, 408 - 384, 16));
gfx_printf("ERASE_TIMEOUT: %02X\n", unstuff_bits(raw_ssr0, 402 - 384, 6));
gfx_printf("ERASE_OFFSET: %X\n", unstuff_bits(raw_ssr0, 400 - 384, 2));
gfx_printf("UHS_SPEED_GRADE: %X\n", unstuff_bits(raw_ssr0, 396 - 384, 4));
gfx_printf("UHS_AU_SIZE: %X\n", unstuff_bits(raw_ssr0, 392 - 384, 4));
gfx_printf("VIDEO_SPEED_CLASS: %02X\n", unstuff_bits(raw_ssr0, 384 - 384, 8));
gfx_printf("VSC_AU_SIZE: %03X\n", unstuff_bits(raw_ssr1, 368, 10));
gfx_printf("SUS_ADDR: %06X\n", unstuff_bits(raw_ssr1, 346, 22));
gfx_printf("APP_PERF_CLASS: %X\n", unstuff_bits(raw_ssr1, 336, 4));
gfx_printf("PERFORMANCE_ENHANCE: %02X\n", unstuff_bits(raw_ssr1, 328, 8));
gfx_printf("DISCARD_SUPPORT: %X\n", unstuff_bits(raw_ssr1, 313, 1));
gfx_printf("FULE_SUPPORT: %X\n", unstuff_bits(raw_ssr1, 312, 1));
gfx_printf("VSC_AU_SIZE: %03X\n", unstuff_bits(raw_ssr1, 368 - 256, 10));
gfx_printf("SUS_ADDR: %06X\n", unstuff_bits(raw_ssr1, 346 - 256, 22));
gfx_printf("APP_PERF_CLASS: %X\n", unstuff_bits(raw_ssr1, 336 - 256, 4));
gfx_printf("PERFORMANCE_ENHANCE: %02X\n", unstuff_bits(raw_ssr1, 328 - 256, 8));
gfx_printf("DISCARD_SUPPORT: %X\n", unstuff_bits(raw_ssr1, 313 - 256, 1));
gfx_printf("FULE_SUPPORT: %X\n", unstuff_bits(raw_ssr1, 312 - 256, 1));
gfx_printf("--RSVD-- %02X %X %02X %02X %04X\n",
unstuff_bits(raw_ssr0, 496, 6), unstuff_bits(raw_ssr0, 424, 4),
unstuff_bits(raw_ssr1, 378, 6), unstuff_bits(raw_ssr1, 340, 6),
unstuff_bits(raw_ssr1, 314, 14));
unstuff_bits(raw_ssr0, 496 - 384, 6), unstuff_bits(raw_ssr0, 424 - 384, 4),
unstuff_bits(raw_ssr1, 378 - 256, 6), unstuff_bits(raw_ssr1, 340 - 256, 6),
unstuff_bits(raw_ssr1, 314 - 256, 14));
gfx_printf("VENDOR_1: %06X %08X\n",
unstuff_bits(raw_ssr1, 288, 24), unstuff_bits(raw_ssr1, 256, 32));
unstuff_bits(raw_ssr1, 288 - 256, 24), unstuff_bits(raw_ssr1, 256 - 256, 32));
gfx_printf("VENDOR_2: %08X %08X %08X %08X\n",
unstuff_bits(raw_ssr2, 224, 32), unstuff_bits(raw_ssr2, 192, 32),
unstuff_bits(raw_ssr2, 160, 32), unstuff_bits(raw_ssr2, 128, 32));
unstuff_bits(raw_ssr2, 224 - 128, 32), unstuff_bits(raw_ssr2, 192 - 128, 32),
unstuff_bits(raw_ssr2, 160 - 128, 32), unstuff_bits(raw_ssr2, 128 - 128, 32));
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, 32 - 0, 32), unstuff_bits(raw_ssr3, 0, 32));
@ -974,19 +916,13 @@ 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);
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, NULL, NULL))
{
// The SD Card is version 1.X (SDSC) if there is no response.
if (storage->sdmmc->error_sts == SDHCI_ERR_INT_CMD_TIMEOUT)
{
*is_sdsc = 1;
*is_sdsc = 1; // The SD Card is version 1.X
return 1;
}
return 0;
}
// For Card version >= 2.0, parse results.
u32 resp = 0;
sdmmc_get_cached_rsp(storage->sdmmc, &resp, SDMMC_RSP_TYPE_5);
sdmmc_get_rsp(storage->sdmmc, &resp, 4, SDMMC_RSP_TYPE_5);
// Check if VHD was accepted and pattern was properly returned.
if ((resp & 0xFFF) == vhd_pattern)
@ -1012,7 +948,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))
return 0;
return sdmmc_get_cached_rsp(storage->sdmmc, cond, SDMMC_RSP_TYPE_3);
return sdmmc_get_rsp(storage->sdmmc, cond, 4, SDMMC_RSP_TYPE_3);
}
static int _sd_storage_get_op_cond(sdmmc_storage_t *storage, bool is_sdsc, int bus_uhs_support)
@ -1035,7 +971,7 @@ static int _sd_storage_get_op_cond(sdmmc_storage_t *storage, bool is_sdsc, int b
storage->has_sector_access = 1;
// Check if card supports 1.8V signaling.
if (cond & SD_ROCR_S18A && bus_uhs_support && !storage->is_low_voltage)
if (cond & SD_ROCR_S18A && bus_uhs_support)
{
// Switch to 1.8V signaling.
if (_sdmmc_storage_execute_cmd_type1(storage, SD_SWITCH_VOLTAGE, 0, 0, R1_STATE_READY))
@ -1079,7 +1015,7 @@ static int _sd_storage_get_rca(sdmmc_storage_t *storage)
break;
u32 resp = 0;
if (!sdmmc_get_cached_rsp(storage->sdmmc, &resp, SDMMC_RSP_TYPE_4))
if (!sdmmc_get_rsp(storage->sdmmc, &resp, 4, SDMMC_RSP_TYPE_4))
break;
if (resp >> 16)
@ -1110,17 +1046,11 @@ static void _sd_storage_parse_scr(sdmmc_storage_t *storage)
storage->scr.sda_vsn = unstuff_bits(resp, 56, 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)
storage->scr.sda_spec3 = unstuff_bits(resp, 47, 1);
if (storage->scr.sda_spec3)
{
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)
@ -1140,9 +1070,9 @@ int sd_storage_get_scr(sdmmc_storage_t *storage, u8 *buf)
return 0;
u32 tmp = 0;
sdmmc_get_cached_rsp(storage->sdmmc, &tmp, SDMMC_RSP_TYPE_1);
sdmmc_get_rsp(storage->sdmmc, &tmp, 4, SDMMC_RSP_TYPE_1);
//Prepare buffer for unstuff_bits
for (u32 i = 0; i < 8; i+=4)
for (int i = 0; i < 8; i+=4)
{
storage->raw_scr[i + 3] = buf[i];
storage->raw_scr[i + 2] = buf[i + 1];
@ -1171,7 +1101,7 @@ static int _sd_storage_switch_get(sdmmc_storage_t *storage, void *buf)
return 0;
u32 tmp = 0;
sdmmc_get_cached_rsp(storage->sdmmc, &tmp, SDMMC_RSP_TYPE_1);
sdmmc_get_rsp(storage->sdmmc, &tmp, 4, SDMMC_RSP_TYPE_1);
return _sdmmc_storage_check_card_status(tmp);
}
@ -1195,7 +1125,7 @@ static int _sd_storage_switch(sdmmc_storage_t *storage, void *buf, int mode, int
return 0;
u32 tmp = 0;
sdmmc_get_cached_rsp(storage->sdmmc, &tmp, SDMMC_RSP_TYPE_1);
sdmmc_get_rsp(storage->sdmmc, &tmp, 4, SDMMC_RSP_TYPE_1);
return _sdmmc_storage_check_card_status(tmp);
}
@ -1311,7 +1241,7 @@ static int _sd_storage_enable_DDR200(sdmmc_storage_t *storage, u8 *buf)
u16 total_pwr_consumption = ((u16)buf[0] << 8) | buf[1];
DPRINTF("[SD] max power: %d mW\n", total_pwr_consumption * 3600 / 1000);
storage->max_power = total_pwr_consumption;
storage->card_power_limit = total_pwr_consumption;
if (total_pwr_consumption <= 800)
{
@ -1350,7 +1280,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];
DPRINTF("[SD] max power: %d mW\n", total_pwr_consumption * 3600 / 1000);
storage->max_power = total_pwr_consumption;
storage->card_power_limit = total_pwr_consumption;
if (total_pwr_consumption <= 800)
{
@ -1562,10 +1492,10 @@ static void _sd_storage_parse_ssr(sdmmc_storage_t *storage)
_sd_storage_debug_print_ssr(storage->raw_ssr);
#endif
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, 32);
storage->ssr.bus_width = (unstuff_bits(raw_ssr1, 510 - 384, 2) & SD_BUS_WIDTH_4) ? 4 : 1;
storage->ssr.protected_size = unstuff_bits(raw_ssr1, 448 - 384, 32);
u32 speed_class = unstuff_bits(raw_ssr1, 440, 8);
u32 speed_class = unstuff_bits(raw_ssr1, 440 - 384, 8);
switch(speed_class)
{
case 0:
@ -1583,94 +1513,12 @@ static void _sd_storage_parse_ssr(sdmmc_storage_t *storage)
storage->ssr.speed_class = speed_class;
break;
}
storage->ssr.uhs_grade = unstuff_bits(raw_ssr1, 396, 4);
storage->ssr.video_class = unstuff_bits(raw_ssr1, 384, 8);
storage->ssr.app_class = unstuff_bits(raw_ssr2, 336, 4);
storage->ssr.uhs_grade = unstuff_bits(raw_ssr1, 396 - 384, 4);
storage->ssr.video_class = unstuff_bits(raw_ssr1, 384 - 384, 8);
storage->ssr.app_class = unstuff_bits(raw_ssr2, 336 - 256, 4);
storage->ssr.au_size = unstuff_bits(raw_ssr1, 428, 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(&reg_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(&reg_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);
storage->ssr.au_size = unstuff_bits(raw_ssr1, 428 - 384, 4);
storage->ssr.uhs_au_size = unstuff_bits(raw_ssr1, 392 - 384, 4);
}
int sd_storage_get_ssr(sdmmc_storage_t *storage, u8 *buf)
@ -1696,10 +1544,10 @@ int sd_storage_get_ssr(sdmmc_storage_t *storage, u8 *buf)
return 0;
u32 tmp = 0;
sdmmc_get_cached_rsp(storage->sdmmc, &tmp, SDMMC_RSP_TYPE_1);
sdmmc_get_rsp(storage->sdmmc, &tmp, 4, SDMMC_RSP_TYPE_1);
// Convert buffer to LE.
for (u32 i = 0; i < SDMMC_CMD_BLOCKSIZE; i += 4)
for (int i = 0; i < SDMMC_CMD_BLOCKSIZE; i += 4)
{
storage->raw_ssr[i + 3] = buf[i];
storage->raw_ssr[i + 2] = buf[i + 1];
@ -1796,7 +1644,7 @@ void sdmmc_storage_init_wait_sd()
int sdmmc_storage_init_sd(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 bus_width, u32 type)
{
u32 tmp = 0;
bool is_sdsc = 0;
int is_sdsc = 0;
u8 *buf = (u8 *)SDMMC_UPPER_BUFFER;
bool bus_uhs_support = _sdmmc_storage_get_bus_uhs_support(bus_width, type);
@ -1941,7 +1789,7 @@ int _gc_storage_custom_cmd(sdmmc_storage_t *storage, void *buf)
return 0;
}
if (!sdmmc_get_cached_rsp(storage->sdmmc, &resp, SDMMC_RSP_TYPE_1))
if (!sdmmc_get_rsp(storage->sdmmc, &resp, 4, SDMMC_RSP_TYPE_1))
return 0;
if (!_sdmmc_storage_check_card_status(resp))
return 0;

View file

@ -1,6 +1,6 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2025 CTCaer
* Copyright (c) 2018-2022 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,
@ -174,30 +174,20 @@ typedef struct _sd_ssr
u8 app_class;
u8 au_size;
u8 uhs_au_size;
u8 perf_enhance;
u32 protected_size;
} 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. */
typedef struct _sdmmc_storage_t
{
sdmmc_t *sdmmc;
int initialized;
int is_low_voltage;
int has_sector_access;
u32 rca;
int has_sector_access;
u32 sec_cnt;
int is_low_voltage;
u32 partition;
u32 max_power;
int initialized;
u32 card_power_limit;
u8 raw_cid[0x10];
u8 raw_csd[0x10];
u8 raw_scr[8];
@ -207,7 +197,6 @@ typedef struct _sdmmc_storage_t
mmc_ext_csd_t ext_csd;
sd_scr_t scr;
sd_ssr_t ssr;
sd_ext_reg_t ser;
} sdmmc_storage_t;
typedef struct _sd_func_modes_t
@ -232,13 +221,9 @@ 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 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_scr(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);
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

View file

@ -1,6 +1,6 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2025 CTCaer
* Copyright (c) 2018-2024 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
@ -212,7 +212,7 @@ static void _sdmmc_autocal_execute(sdmmc_t *sdmmc, u32 power)
// Use 0x1F mask for all.
u8 autocal_pu_status = sdmmc->regs->autocalsts & 0x1F;
if (!autocal_pu_status)
EPRINTFARGS("SDMMC%d: Comp Pad open!", sdmmc->id + 1); // Or resistance is extreme.
EPRINTFARGS("SDMMC%d: Comp Pad open!", sdmmc->id + 1);
else if (autocal_pu_status == 0x1F)
EPRINTFARGS("SDMMC%d: Comp Pad short to gnd!", sdmmc->id + 1);
#endif
@ -394,8 +394,8 @@ int sdmmc_setup_clock(sdmmc_t *sdmmc, u32 type)
static void _sdmmc_card_clock_enable(sdmmc_t *sdmmc)
{
// Recalibrate periodically if needed.
if (sdmmc->periodic_calibration && !sdmmc->powersave_enabled)
// Recalibrate conditionally.
if (sdmmc->manual_cal && !sdmmc->powersave_enabled)
_sdmmc_autocal_execute(sdmmc, sdmmc_get_io_power(sdmmc));
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)
{
// Recalibrate periodically if needed.
if (sdmmc->periodic_calibration && !powersave_enable && sdmmc->card_clock_enabled)
// Recalibrate periodically for SDMMC1.
if (sdmmc->manual_cal && !powersave_enable && sdmmc->card_clock_enabled)
_sdmmc_autocal_execute(sdmmc, sdmmc_get_io_power(sdmmc));
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;
}
static int _sdmmc_cache_rsp(sdmmc_t *sdmmc, u32 *rsp, u32 type)
static int _sdmmc_cache_rsp(sdmmc_t *sdmmc, u32 *rsp, u32 size, u32 type)
{
switch (type)
{
@ -439,14 +439,33 @@ static int _sdmmc_cache_rsp(sdmmc_t *sdmmc, u32 *rsp, u32 type)
case SDMMC_RSP_TYPE_3:
case SDMMC_RSP_TYPE_4:
case SDMMC_RSP_TYPE_5:
rsp[0] = sdmmc->regs->rspreg[0];
if (size < 4)
return 0;
rsp[0] = sdmmc->regs->rspreg0;
break;
case SDMMC_RSP_TYPE_2:
if (size < 0x10)
return 0;
// CRC is stripped, so shifting is needed.
for (u32 i = 0; i < 4; i++)
u32 tempreg;
for (int i = 0; i < 4; i++)
{
u32 tempreg = sdmmc->regs->rspreg[3 - i];
switch(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;
if (i != 0)
@ -461,7 +480,7 @@ static int _sdmmc_cache_rsp(sdmmc_t *sdmmc, u32 *rsp, u32 type)
return 1;
}
int sdmmc_get_cached_rsp(sdmmc_t *sdmmc, u32 *rsp, u32 type)
int sdmmc_get_rsp(sdmmc_t *sdmmc, u32 *rsp, u32 size, u32 type)
{
if (!rsp || sdmmc->expected_rsp_type != type)
return 0;
@ -472,12 +491,18 @@ int sdmmc_get_cached_rsp(sdmmc_t *sdmmc, u32 *rsp, u32 type)
case SDMMC_RSP_TYPE_3:
case SDMMC_RSP_TYPE_4:
case SDMMC_RSP_TYPE_5:
if (size < 4)
return 0;
rsp[0] = sdmmc->rsp[0];
break;
case SDMMC_RSP_TYPE_2:
for (u32 i = 0; i < 4; i++)
rsp[i] = sdmmc->rsp[i];
if (size < 16)
return 0;
rsp[0] = sdmmc->rsp[0];
rsp[1] = sdmmc->rsp[1];
rsp[2] = sdmmc->rsp[2];
rsp[3] = sdmmc->rsp[3];
break;
default:
@ -550,7 +575,7 @@ static int _sdmmc_setup_read_small_block(sdmmc_t *sdmmc)
return 1;
}
static int _sdmmc_send_cmd(sdmmc_t *sdmmc, const sdmmc_cmd_t *cmd, bool is_data_present)
static int _sdmmc_send_cmd(sdmmc_t *sdmmc, sdmmc_cmd_t *cmd, bool is_data_present)
{
u16 cmdflags = 0;
@ -890,7 +915,6 @@ static void _sdmmc_enable_interrupts(sdmmc_t *sdmmc)
sdmmc->regs->errintstsen |= SDHCI_ERR_INT_ALL_EXCEPT_ADMA_BUSPWR;
sdmmc->regs->norintsts = sdmmc->regs->norintsts;
sdmmc->regs->errintsts = sdmmc->regs->errintsts;
sdmmc->error_sts = 0;
}
static void _sdmmc_mask_interrupts(sdmmc_t *sdmmc)
@ -913,9 +937,8 @@ static u32 _sdmmc_check_mask_interrupt(sdmmc_t *sdmmc, u16 *pout, u16 mask)
if (norintsts & SDHCI_INT_ERROR)
{
#ifdef ERROR_EXTRA_PRINTING
EPRINTFARGS("SDMMC%d: intsts %08X, errintsts %08X", sdmmc->id + 1, norintsts, errintsts);
EPRINTFARGS("SDMMC%d: norintsts %08X, errintsts %08X", sdmmc->id + 1, norintsts, errintsts);
#endif
sdmmc->error_sts = errintsts;
sdmmc->regs->errintsts = errintsts;
return SDMMC_MASKINT_ERROR;
}
@ -970,7 +993,7 @@ static int _sdmmc_stop_transmission_inner(sdmmc_t *sdmmc, u32 *rsp)
if (!result)
return 0;
_sdmmc_cache_rsp(sdmmc, rsp, SDMMC_RSP_TYPE_1);
_sdmmc_cache_rsp(sdmmc, rsp, 4, SDMMC_RSP_TYPE_1);
return _sdmmc_wait_card_busy(sdmmc);
}
@ -980,8 +1003,8 @@ int sdmmc_stop_transmission(sdmmc_t *sdmmc, u32 *rsp)
if (!sdmmc->card_clock_enabled)
return 0;
// Recalibrate periodically if needed.
if (sdmmc->periodic_calibration && sdmmc->powersave_enabled)
// Recalibrate periodically for SDMMC1.
if (sdmmc->manual_cal && sdmmc->powersave_enabled)
_sdmmc_autocal_execute(sdmmc, sdmmc_get_io_power(sdmmc));
bool should_disable_sd_clock = false;
@ -1002,7 +1025,7 @@ int sdmmc_stop_transmission(sdmmc_t *sdmmc, u32 *rsp)
return result;
}
static int _sdmmc_config_sdma(sdmmc_t *sdmmc, u32 *blkcnt_out, const sdmmc_req_t *req)
static int _sdmmc_config_sdma(sdmmc_t *sdmmc, u32 *blkcnt_out, sdmmc_req_t *req)
{
if (!req->blksize || !req->num_sectors)
return 0;
@ -1097,7 +1120,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)
{
bool has_req_or_check_busy = req || cmd->check_busy;
int has_req_or_check_busy = req || cmd->check_busy;
if (!_sdmmc_wait_cmd_data_inhibit(sdmmc, has_req_or_check_busy))
return 0;
@ -1135,13 +1158,13 @@ static int _sdmmc_execute_cmd_inner(sdmmc_t *sdmmc, sdmmc_cmd_t *cmd, sdmmc_req_
EPRINTFARGS("SDMMC%d: Transfer error!", sdmmc->id + 1);
#endif
DPRINTF("rsp(%d): %08X, %08X, %08X, %08X\n", result,
sdmmc->regs->rspreg[0], sdmmc->regs->rspreg[1], sdmmc->regs->rspreg[2], sdmmc->regs->rspreg[3]);
sdmmc->regs->rspreg0, sdmmc->regs->rspreg1, sdmmc->regs->rspreg2, sdmmc->regs->rspreg3);
if (result)
{
if (cmd->rsp_type)
{
sdmmc->expected_rsp_type = cmd->rsp_type;
result = _sdmmc_cache_rsp(sdmmc, sdmmc->rsp, cmd->rsp_type);
result = _sdmmc_cache_rsp(sdmmc, sdmmc->rsp, 0x10, cmd->rsp_type);
#ifdef ERROR_EXTRA_PRINTING
if (!result)
EPRINTFARGS("SDMMC%d: Unknown response type!", sdmmc->id + 1);
@ -1170,10 +1193,10 @@ static int _sdmmc_execute_cmd_inner(sdmmc_t *sdmmc, sdmmc_cmd_t *cmd, sdmmc_req_
*blkcnt_out = blkcnt;
if (req->is_auto_stop_trn)
sdmmc->stop_trn_rsp = sdmmc->regs->rspreg[3];
sdmmc->rsp3 = sdmmc->regs->rspreg3;
}
if (has_req_or_check_busy)
if (cmd->check_busy || req)
{
result = _sdmmc_wait_card_busy(sdmmc);
#ifdef ERROR_EXTRA_PRINTING
@ -1225,7 +1248,7 @@ static void _sdmmc_config_sdmmc1_pads(bool discharge)
u32 level = GPIO_LOW;
u32 output = GPIO_OUTPUT_DISABLE;
// Set values for discharging.
// Set values for dicharging.
if (discharge)
{
function = GPIO_MODE_GPIO;
@ -1281,7 +1304,7 @@ static int _sdmmc_config_sdmmc1(bool t210b01)
// Enable SD card power. Powers LDO2 also.
PINMUX_AUX(PINMUX_AUX_DMIC3_CLK) = PINMUX_PULL_DOWN | 2;
gpio_direction_output(GPIO_PORT_E, GPIO_PIN_4, GPIO_HIGH);
usleep(10000); // Minimum 3 to 10 ms.
usleep(10000);
// Inform IO pads that voltage is gonna be 3.3V.
PMC(APBDEV_PMC_PWR_DET_VAL) |= PMC_PWR_DET_33V_SDMMC1;
@ -1362,7 +1385,7 @@ int sdmmc_init(sdmmc_t *sdmmc, u32 id, u32 power, u32 bus_width, u32 type)
if (sdmmc->t210b01)
vref_sel = 0;
else
sdmmc->periodic_calibration = 1;
sdmmc->manual_cal = 1;
break;
case SDMMC_2:
@ -1396,8 +1419,6 @@ int sdmmc_init(sdmmc_t *sdmmc, u32 id, u32 power, u32 bus_width, u32 type)
if (!_sdmmc_autocal_config_offset(sdmmc, power))
return 0;
_sdmmc_commit_changes(sdmmc);
// Calibrate pads.
_sdmmc_autocal_execute(sdmmc, power);
@ -1485,8 +1506,8 @@ int sdmmc_execute_cmd(sdmmc_t *sdmmc, sdmmc_cmd_t *cmd, sdmmc_req_t *req, u32 *b
if (!sdmmc->card_clock_enabled)
return 0;
// Recalibrate periodically if needed.
if (sdmmc->periodic_calibration && sdmmc->powersave_enabled)
// Recalibrate periodically for SDMMC1.
if (sdmmc->manual_cal && sdmmc->powersave_enabled)
_sdmmc_autocal_execute(sdmmc, sdmmc_get_io_power(sdmmc));
int should_disable_sd_clock = 0;

View file

@ -1,6 +1,6 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2025 CTCaer
* Copyright (c) 2018-2023 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
@ -101,7 +101,6 @@
#define SDHCI_CMD_TYPE_SUSPEND (1U << 6)
#define SDHCI_CMD_TYPE_RESUME (2U << 6)
#define SDHCI_CMD_TYPE_ABORT (3U << 6)
#define SDHCI_CMD_SPI_CS_LOW BIT(7)
#define SDHCI_CMD_IDX(cmd) ((cmd) << 8)
@ -171,10 +170,10 @@
#define SDHCI_INT_ERROR BIT(15)
/*! SDMMC error interrupt status and control. 0x32/0x36. */
#define SDHCI_ERR_INT_CMD_TIMEOUT BIT(0)
#define SDHCI_ERR_INT_CMD_CRC BIT(1)
#define SDHCI_ERR_INT_CMD_END_BIT BIT(2)
#define SDHCI_ERR_INT_CMD_INDEX BIT(3)
#define SDHCI_ERR_INT_TIMEOUT BIT(0)
#define SDHCI_ERR_INT_CRC BIT(1)
#define SDHCI_ERR_INT_END_BIT BIT(2)
#define SDHCI_ERR_INT_INDEX BIT(3)
#define SDHCI_ERR_INT_DATA_TIMEOUT BIT(4)
#define SDHCI_ERR_INT_DATA_CRC BIT(5)
#define SDHCI_ERR_INT_DATA_END_BIT BIT(6)
@ -191,8 +190,8 @@
#define SDHCI_ERR_INT_ALL_EXCEPT_ADMA_BUSPWR \
(SDHCI_ERR_INT_AUTO_CMD12 | SDHCI_ERR_INT_DATA_END_BIT | \
SDHCI_ERR_INT_DATA_CRC | SDHCI_ERR_INT_DATA_TIMEOUT | \
SDHCI_ERR_INT_CMD_INDEX | SDHCI_ERR_INT_CMD_END_BIT | \
SDHCI_ERR_INT_CMD_CRC | SDHCI_ERR_INT_CMD_TIMEOUT)
SDHCI_ERR_INT_INDEX | SDHCI_ERR_INT_END_BIT | \
SDHCI_ERR_INT_CRC | SDHCI_ERR_INT_TIMEOUT)
/*! Host Capability 1. 0x40. */
#define SDHCI_CAP_TM_CLK_FREQ_MASK 0x3F
@ -286,15 +285,14 @@ typedef struct _sdmmc_t
u32 card_clock;
u32 clock_stopped;
int powersave_enabled;
int periodic_calibration;
int manual_cal;
int card_clock_enabled;
int venclkctl_set;
u32 venclkctl_tap;
u32 expected_rsp_type;
u32 dma_addr_next;
u32 rsp[4];
u32 stop_trn_rsp;
u32 error_sts;
u32 rsp3;
int t210b01;
} sdmmc_t;
@ -325,7 +323,7 @@ void sdmmc_save_tap_value(sdmmc_t *sdmmc);
void sdmmc_setup_drv_type(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);
int sdmmc_get_cached_rsp(sdmmc_t *sdmmc, u32 *rsp, u32 type);
int sdmmc_get_rsp(sdmmc_t *sdmmc, u32 *rsp, u32 size, u32 type);
int sdmmc_tuning_execute(sdmmc_t *sdmmc, u32 type, u32 cmd);
int sdmmc_stop_transmission(sdmmc_t *sdmmc, u32 *rsp);
bool sdmmc_get_sd_inserted();

View file

@ -1,6 +1,6 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2025 CTCaer
* Copyright (c) 2018-2023 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
@ -39,7 +39,10 @@ typedef struct _t210_sdmmc_t
/* 0x08 */ vu32 argument;
/* 0x0C */ vu16 trnmod;
/* 0x0E */ vu16 cmdreg;
/* 0x10 */ vu32 rspreg[4];
/* 0x10 */ vu32 rspreg0;
/* 0x14 */ vu32 rspreg1;
/* 0x18 */ vu32 rspreg2;
/* 0x1C */ vu32 rspreg3;
/* 0x20 */ vu32 bdata; // Buffer data port.
/* 0x24 */ vu32 prnsts;
/* 0x28 */ vu8 hostctl;

View file

@ -99,7 +99,7 @@ typedef struct _usb_cfg_descr_t
u8 bConfigurationValue; // Value of this configuration (1 based).
u8 iConfiguration; // Index of String Descriptor describing the configuration.
u8 bmAttributes; // Configuration characteristics.
u8 bMaxPower; // Maximum power consumed by this configuration. In 2mA (usb2) or 8mA (usb3).
u8 bMaxPower; // Maximum power consumed by this configuration.
} __attribute__((packed)) usb_cfg_descr_t;
/* Interface descriptor structure */

View file

@ -80,7 +80,7 @@ enum {
static jc_cal_t jc_cal_ctx;
static usb_ops_t usb_ops;
static bool _jc_calibration(const jc_gamepad_rpt_t *jc_pad)
static bool _jc_calibration(jc_gamepad_rpt_t *jc_pad)
{
// Calibrate left stick.
if (jc_cal_ctx.cl_step != JC_CAL_MAX_STEPS)

View file

@ -1936,9 +1936,7 @@ int usb_device_gadget_ums(usb_ctxt_t *usbs)
_handle_ep0_ctrl(&ums);
_parse_scsi_cmd(&ums, &ums.bulk_ctxt);
if (ums.state > UMS_STATE_NORMAL)
if (_parse_scsi_cmd(&ums, &ums.bulk_ctxt) || (ums.state > UMS_STATE_NORMAL))
continue;
_handle_ep0_ctrl(&ums);

View file

@ -1011,7 +1011,7 @@ static void _xusb_device_power_down()
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_W_CLR) = BIT(CLK_W_XUSB);
}
static int _xusb_queue_trb(u32 ep_idx, const void *trb, bool ring_doorbell)
static int _xusb_queue_trb(u32 ep_idx, void *trb, bool ring_doorbell)
{
int res = USB_RES_OK;
data_trb_t *next_trb;
@ -1226,7 +1226,7 @@ static int _xusb_wait_ep_stopped(u32 endpoint)
return USB_RES_OK;
}
static int _xusb_handle_transfer_event(const transfer_event_trb_t *trb)
static int _xusb_handle_transfer_event(transfer_event_trb_t *trb)
{
// Advance dequeue list.
data_trb_t *next_trb;
@ -1461,7 +1461,7 @@ static int _xusb_handle_get_ep_status(u32 ep_idx)
return _xusb_issue_data_trb(xusb_ep_status_descriptor, 2, USB_DIR_IN);
}
static int _xusb_handle_get_class_request(const usb_ctrl_setup_t *ctrl_setup)
static int _xusb_handle_get_class_request(usb_ctrl_setup_t *ctrl_setup)
{
u8 _bRequest = ctrl_setup->bRequest;
u16 _wIndex = ctrl_setup->wIndex;
@ -1492,7 +1492,7 @@ stall:
return USB_RES_OK;
}
static int _xusb_handle_get_descriptor(const usb_ctrl_setup_t *ctrl_setup)
static int _xusb_handle_get_descriptor(usb_ctrl_setup_t *ctrl_setup)
{
u32 size;
void *descriptor;
@ -1621,7 +1621,7 @@ static int _xusb_handle_get_descriptor(const usb_ctrl_setup_t *ctrl_setup)
return _xusb_issue_data_trb(descriptor, size, USB_DIR_IN);
}
static void _xusb_handle_set_request_dev_address(const usb_ctrl_setup_t *ctrl_setup)
static void _xusb_handle_set_request_dev_address(usb_ctrl_setup_t *ctrl_setup)
{
u32 addr = ctrl_setup->wValue & 0xFF;
@ -1633,7 +1633,7 @@ static void _xusb_handle_set_request_dev_address(const usb_ctrl_setup_t *ctrl_se
usbd_xotg->device_state = XUSB_ADDRESSED_STS_WAIT;
}
static void _xusb_handle_set_request_configuration(const usb_ctrl_setup_t *ctrl_setup)
static void _xusb_handle_set_request_configuration(usb_ctrl_setup_t *ctrl_setup)
{
usbd_xotg->config_num = ctrl_setup->wValue;

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2018-2025 CTCaer
* Copyright (c) 2018-2024 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
@ -17,23 +17,21 @@
#include <string.h>
#include <stdlib.h>
#include "dirlist.h"
#include <libs/fatfs/ff.h>
#include <mem/heap.h>
#include <utils/types.h>
dirlist_t *dirlist(const char *directory, const char *pattern, bool includeHiddenFiles, bool parse_dirs)
#define MAX_ENTRIES 64
char *dirlist(const char *directory, const char *pattern, bool includeHiddenFiles, bool parse_dirs)
{
int res = 0;
u32 k = 0;
u32 i = 0, j = 0, k = 0;
DIR dir;
FILINFO fno;
dirlist_t *dir_entries = (dirlist_t *)malloc(sizeof(dirlist_t));
// Setup pointer tree.
for (u32 i = 0; i < DIR_MAX_ENTRIES; i++)
dir_entries->name[i] = &dir_entries->data[i * 256];
char *dir_entries = (char *)zalloc(MAX_ENTRIES * 256);
char *temp = (char *)zalloc(256);
if (!pattern && !f_opendir(&dir, directory))
{
@ -49,8 +47,9 @@ dirlist_t *dirlist(const char *directory, const char *pattern, bool includeHidde
{
if ((fno.fname[0] != '.') && (includeHiddenFiles || !(fno.fattrib & AM_HID)))
{
strcpy(&dir_entries->data[k * 256], fno.fname);
if (++k >= DIR_MAX_ENTRIES)
strcpy(dir_entries + (k * 256), fno.fname);
k++;
if (k > (MAX_ENTRIES - 1))
break;
}
}
@ -63,8 +62,9 @@ dirlist_t *dirlist(const char *directory, const char *pattern, bool includeHidde
{
if (!(fno.fattrib & AM_DIR) && (fno.fname[0] != '.') && (includeHiddenFiles || !(fno.fattrib & AM_HID)))
{
strcpy(&dir_entries->data[k * 256], fno.fname);
if (++k >= DIR_MAX_ENTRIES)
strcpy(dir_entries + (k * 256), fno.fname);
k++;
if (k > (MAX_ENTRIES - 1))
break;
}
res = f_findnext(&dir, &fno);
@ -74,27 +74,27 @@ dirlist_t *dirlist(const char *directory, const char *pattern, bool includeHidde
if (!k)
{
free(temp);
free(dir_entries);
return NULL;
}
// Terminate name list.
dir_entries->name[k] = NULL;
// Reorder ini files by ASCII ordering.
for (i = 0; i < k - 1 ; i++)
{
for (j = i + 1; j < k; j++)
{
if (strcmp(&dir_entries[i * 256], &dir_entries[j * 256]) > 0)
{
strcpy(temp, &dir_entries[i * 256]);
strcpy(&dir_entries[i * 256], &dir_entries[j * 256]);
strcpy(&dir_entries[j * 256], temp);
}
}
}
// Reorder ini files Alphabetically.
for (u32 i = 0; i < k - 1 ; i++)
{
for (u32 j = i + 1; j < k; j++)
{
if (strcasecmp(dir_entries->name[i], dir_entries->name[j]) > 0)
{
char *tmp = dir_entries->name[i];
dir_entries->name[i] = dir_entries->name[j];
dir_entries->name[j] = tmp;
}
}
}
free(temp);
return dir_entries;
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2018-2024 CTCaer
* Copyright (c) 2018 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,
@ -16,12 +16,4 @@
#include <utils/types.h>
#define DIR_MAX_ENTRIES 64
typedef struct _dirlist_t
{
char *name[DIR_MAX_ENTRIES];
char data[DIR_MAX_ENTRIES * 256];
} dirlist_t;
dirlist_t *dirlist(const char *directory, const char *pattern, bool includeHiddenFiles, bool parse_dirs);
char *dirlist(const char *directory, const char *pattern, bool includeHiddenFiles, bool parse_dirs);

View file

@ -53,7 +53,7 @@ ini_sec_t *_ini_create_section(link_t *dst, ini_sec_t *csec, char *name, u8 type
return csec;
}
int ini_parse(link_t *dst, const char *ini_path, bool is_dir)
int ini_parse(link_t *dst, char *ini_path, bool is_dir)
{
FIL fp;
u32 lblen;
@ -62,7 +62,7 @@ int ini_parse(link_t *dst, const char *ini_path, bool is_dir)
ini_sec_t *csec = NULL;
char *lbuf = NULL;
dirlist_t *filelist = NULL;
char *filelist = NULL;
char *filename = (char *)malloc(256);
strcpy(filename, ini_path);
@ -85,9 +85,9 @@ int ini_parse(link_t *dst, const char *ini_path, bool is_dir)
// Copy ini filename in path string.
if (is_dir)
{
if (filelist->name[k])
if (filelist[k * 256])
{
strcpy(filename + pathlen, filelist->name[k]);
strcpy(filename + pathlen, &filelist[k * 256]);
k++;
}
else

View file

@ -43,7 +43,7 @@ typedef struct _ini_sec_t
u32 color;
} ini_sec_t;
int ini_parse(link_t *dst, const char *ini_path, bool is_dir);
int ini_parse(link_t *dst, char *ini_path, bool is_dir);
char *ini_check_special_section(ini_sec_t *cfg);
void ini_free(link_t *src);

View file

@ -172,14 +172,14 @@ parse_padding_dec:
_s_putc(c);
break;
case 'd':
_s_putn(va_arg(ap, u32), 10, fill, fcnt);
break;
case 's':
_s_puts(va_arg(ap, char *), fill, fcnt);
break;
case 'd':
_s_putn(va_arg(ap, u32), 10, fill, fcnt);
break;
case 'p':
case 'P':
case 'x':
@ -261,14 +261,14 @@ parse_padding_dec:
_s_putc(c);
break;
case 'd':
_s_putn(va_arg(ap, u32), 10, fill, fcnt);
break;
case 's':
_s_puts(va_arg(ap, char *), fill, fcnt);
break;
case 'd':
_s_putn(va_arg(ap, u32), 10, fill, fcnt);
break;
case 'p':
case 'P':
case 'x':

View file

@ -1,19 +1,19 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2025 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* 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/>.
*/
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2024 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* 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 <string.h>
@ -29,6 +29,8 @@
#include <storage/sd.h>
#include <utils/util.h>
#define USE_RTC_TIMER
u8 bit_count(u32 val)
{
u8 cnt = 0;
@ -239,21 +241,6 @@ u32 crc32_calc(u32 crc, const u8 *buf, u32 len)
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)
{
// Set panic code.

View file

@ -1,6 +1,6 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2025 CTCaer
* Copyright (c) 2018-2024 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
@ -89,10 +89,6 @@ int atoi(const char *nptr);
void reg_write_array(u32 *base, const reg_cfg_t *cfg, u32 num_cfg);
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 power_set_state(power_state_t state);
void power_set_state_ex(void *param);

View file

@ -313,14 +313,17 @@ void print_battery_charger_info()
gfx_printf("%k\n\nBattery Charger Info:\n%k", TXT_CLR_CYAN_L, TXT_CLR_DEFAULT);
bq24193_get_property(BQ24193_InputVoltageLimit, &value);
gfx_printf("Input voltage limit: %4d mV\n", value);
bq24193_get_property(BQ24193_InputCurrentLimit, &value);
gfx_printf("Input current limit: %4d mA\n", value);
bq24193_get_property(BQ24193_SystemMinimumVoltage, &value);
gfx_printf("System voltage limit: %4d mV\n", value);
gfx_printf("Min voltage limit: %4d mV\n", value);
bq24193_get_property(BQ24193_FastChargeCurrentLimit, &value);
gfx_printf("Charge current limit: %4d mA\n", value);
gfx_printf("Fast charge current limit: %4d mA\n", value);
bq24193_get_property(BQ24193_ChargeVoltageLimit, &value);
gfx_printf("Charge voltage limit: %4d mV\n", value);

View file

@ -155,8 +155,6 @@ void menu_autorcm()
tui_do_menu(&menu);
emmc_end();
free(ments);
}
#pragma GCC pop_options

View file

@ -1,7 +1,7 @@
/*
* Atmosphère Package 3 parser.
* Atmosphère Fusée Secondary Storage (Package3) parser.
*
* Copyright (c) 2019-2025 CTCaer
* Copyright (c) 2019-2024 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
@ -20,7 +20,7 @@
#include <bdk.h>
#include "pkg3.h"
#include "fss.h"
#include "hos.h"
#include "../config.h"
#include <libs/fatfs/ff.h>
@ -31,16 +31,14 @@
extern hekate_config h_cfg;
extern bool is_ipl_updated(void *buf, const char *path, bool force);
extern bool is_ipl_updated(void *buf, char *path, bool force);
#define PKG3_KIP_SKIP_MAX 16
// FSS0 Magic and Meta header offset.
#define FSS0_MAGIC 0x30535346
#define FSS0_META_OFFSET 0x4
#define FSS0_VERSION_0_17_0 0x110000
// 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.
// FSS0 Content Types.
#define CNT_TYPE_FSP 0
#define CNT_TYPE_EXO 1 // Exosphere (Secure Monitor).
#define CNT_TYPE_WBT 2 // Warmboot (SC7Exit fw).
@ -55,11 +53,11 @@ extern bool is_ipl_updated(void *buf, const char *path, bool force);
#define CNT_TYPE_EXF 11 // Exosphere Mariko fatal payload.
#define CNT_TYPE_TKG 12 // Tsec Keygen.
// PKG3 Content Flags.
// FSS0 Content Flags.
#define CNT_FLAG0_EXPERIMENTAL BIT(0)
// PKG3 Meta Header.
typedef struct _pkg3_meta_t
// FSS0 Meta Header.
typedef struct _fss_meta_t
{
u32 magic;
u32 size;
@ -69,10 +67,10 @@ typedef struct _pkg3_meta_t
u32 hos_ver;
u32 version;
u32 git_rev;
} pkg3_meta_t;
} fss_meta_t;
// PKG3 Content Header.
typedef struct _pkg3_content_t
// FSS0 Content Header.
typedef struct _fss_content_t
{
u32 offset;
u32 size;
@ -82,9 +80,9 @@ typedef struct _pkg3_content_t
u8 flags2;
u32 rsvd1;
char name[0x10];
} pkg3_content_t;
} fss_content_t;
static void _pkg3_update_r2p()
static void _fss_update_r2p()
{
u8 *r2p_payload = sd_file_read("atmosphere/reboot_payload.bin", NULL);
@ -93,44 +91,10 @@ static void _pkg3_update_r2p()
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)
int parse_fss(launch_ctxt_t *ctxt, const char *path)
{
FIL fp;
char **pkg3_kip1_skip = NULL;
u32 pkg3_kip1_skip_num = 0;
bool stock = false;
bool experimental = false;
@ -144,12 +108,9 @@ int parse_pkg3(launch_ctxt_t *ctxt, const char *path)
if (kv->val[0] == '1')
stock = true;
if (!strcmp("pkg3ex", kv->key))
if (!strcmp("fss0experimental", 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
@ -160,93 +121,79 @@ int parse_pkg3(launch_ctxt_t *ctxt, const char *path)
return 1;
#endif
// Try to open PKG3.
// Try to open FSS0.
if (f_open(&fp, path, FA_READ) != FR_OK)
return 0;
void *pkg3 = malloc(f_size(&fp));
void *fss = malloc(f_size(&fp));
// Read first 1024 bytes of the PKG3 file.
f_read(&fp, pkg3, 1024, NULL);
// Read first 1024 bytes of the FSS0 file.
f_read(&fp, fss, 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);
// 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 PKG3 and parse it.
if (pkg3_meta->magic == PKG3_MAGIC)
// Check if valid FSS0 and parse it.
if (fss_meta->magic == FSS0_MAGIC)
{
gfx_printf("Atmosphere %d.%d.%d-%08x via PKG3\n"
gfx_printf("Atmosphere %d.%d.%d-%08x via FSS0/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);
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->patch_krn_proc_id = true;
ctxt->pkg3_hosver = pkg3_meta->hos_ver;
ctxt->atmosphere = true;
ctxt->fss0_hosver = fss_meta->hos_ver;
// Parse PKG3 contents.
pkg3_content_t *curr_pkg3_cnt = (pkg3_content_t *)(pkg3 + pkg3_meta->cnt_off);
// Parse FSS0 contents.
fss_content_t *curr_fss_cnt = (fss_content_t *)(fss + fss_meta->cnt_off);
void *content;
for (u32 i = 0; i < pkg3_meta->cnt_count; i++)
for (u32 i = 0; i < fss_meta->cnt_count; i++)
{
content = (void *)(pkg3 + curr_pkg3_cnt[i].offset);
content = (void *)(fss + curr_fss_cnt[i].offset);
// Check if offset is inside limits.
if ((curr_pkg3_cnt[i].offset + curr_pkg3_cnt[i].size) > pkg3_meta->size)
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_pkg3_cnt[i].flags0 & CNT_FLAG0_EXPERIMENTAL) && !experimental)
if ((curr_fss_cnt[i].flags0 & CNT_FLAG0_EXPERIMENTAL) && !experimental)
continue;
// Prepare content.
switch (curr_pkg3_cnt[i].type)
switch (curr_fss_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);
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_pkg3_cnt[i].size;
ctxt->kernel_size = curr_fss_cnt[i].size;
ctxt->kernel = content;
break;
case CNT_TYPE_EXO:
ctxt->secmon_size = curr_pkg3_cnt[i].size;
ctxt->secmon_size = curr_fss_cnt[i].size;
ctxt->secmon = content;
break;
case CNT_TYPE_EXF:
ctxt->exofatal_size = curr_pkg3_cnt[i].size;
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_pkg3_cnt[i].size;
ctxt->warmboot_size = curr_fss_cnt[i].size;
ctxt->warmboot = content;
break;
@ -255,28 +202,23 @@ int parse_pkg3(launch_ctxt_t *ctxt, const char *path)
}
// Load content to launch context.
f_lseek(&fp, curr_pkg3_cnt[i].offset);
f_read(&fp, content, curr_pkg3_cnt[i].size, NULL);
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->pkg3 = pkg3;
ctxt->fss0 = fss;
// Update r2p if needed.
_pkg3_update_r2p();
free(pkg3_kip1_skip);
_fss_update_r2p();
return 1;
}
// Failed. Close and free all.
f_close(&fp);
free(pkg3_kip1_skip);
free(pkg3);
free(fss);
return 0;
}

View file

@ -14,11 +14,11 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _PKG3_H_
#define _PKG3_H_
#ifndef _FSS_H_
#define _FSS_H_
#include "hos.h"
int parse_pkg3(launch_ctxt_t *ctxt, const char *path);
int parse_fss(launch_ctxt_t *ctxt, const char *path);
#endif

View file

@ -2,7 +2,7 @@
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018 st4rk
* Copyright (c) 2018 Ced2911
* Copyright (c) 2018-2025 CTCaer
* Copyright (c) 2018-2024 CTCaer
* Copyright (c) 2018 balika011
*
* This program is free software; you can redistribute it and/or modify it
@ -123,8 +123,6 @@ static const u8 master_kekseed_t210_tsec_v4[HOS_KB_VERSION_MAX - HOS_KB_VERSION_
{ 0x99, 0x22, 0x09, 0x57, 0xA7, 0xF9, 0x5E, 0x94, 0xFE, 0x78, 0x7F, 0x41, 0xD6, 0xE7, 0x56, 0xE6 }, // 16.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.
{ 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.
@ -142,8 +140,6 @@ static const u8 master_kekseed_t210b01[HOS_KB_VERSION_MAX - HOS_KB_VERSION_600 +
{ 0xA5, 0xEC, 0x16, 0x39, 0x1A, 0x30, 0x16, 0x08, 0x2E, 0xCF, 0x09, 0x6F, 0x5E, 0x7C, 0xEE, 0xA9 }, // 16.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.
{ 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] =
@ -196,7 +192,7 @@ static void _se_lock(bool lock_se)
gfx_hexdump(SE_BASE, (void *)SE_BASE, 0x400);*/
}
static bool _hos_eks_rw_try(u8 *buf, bool write)
bool hos_eks_rw_try(u8 *buf, bool write)
{
for (u32 i = 0; i < 3; i++)
{
@ -226,7 +222,7 @@ static void _hos_eks_get()
{
// Read EKS blob.
u8 *mbr = zalloc(SD_BLOCKSIZE);
if (!_hos_eks_rw_try(mbr, false))
if (!hos_eks_rw_try(mbr, false))
goto out;
// Decrypt EKS blob.
@ -264,7 +260,7 @@ static void _hos_eks_save()
{
// Read EKS blob.
u8 *mbr = zalloc(SD_BLOCKSIZE);
if (!_hos_eks_rw_try(mbr, false))
if (!hos_eks_rw_try(mbr, false))
{
if (new_eks)
{
@ -296,7 +292,7 @@ static void _hos_eks_save()
// Write EKS blob to SD.
memcpy(mbr + 0x80, eks, sizeof(hos_eks_mbr_t));
_hos_eks_rw_try(mbr, true);
hos_eks_rw_try(mbr, true);
free(eks);
free(keys);
@ -305,7 +301,7 @@ out:
}
}
static void _hos_eks_clear(u32 kb)
void hos_eks_clear(u32 kb)
{
// Check if Erista based unit.
if (h_cfg.t210b01)
@ -318,7 +314,7 @@ static void _hos_eks_clear(u32 kb)
{
// Read EKS blob.
u8 *mbr = zalloc(SD_BLOCKSIZE);
if (!_hos_eks_rw_try(mbr, false))
if (!hos_eks_rw_try(mbr, false))
goto out;
// Disable current Master key version.
@ -331,7 +327,7 @@ static void _hos_eks_clear(u32 kb)
// Write EKS blob to SD.
memcpy(mbr + 0x80, eks, sizeof(hos_eks_mbr_t));
_hos_eks_rw_try(mbr, true);
hos_eks_rw_try(mbr, true);
free(eks);
out:
@ -340,21 +336,8 @@ out:
}
}
static int _hos_keygen(void *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt, bool stock, bool is_exo)
int hos_keygen_t210b01(u32 kb)
{
static bool sbk_is_set = true;
u32 retries = 0;
bool use_tsec = false;
tsec_keys_t tsec_keys;
kb_t *kb_data = (kb_t *)keyblob;
if (kb > HOS_KB_VERSION_MAX)
return 0;
// Do Mariko keygen.
if (h_cfg.t210b01)
{
// Use SBK as Device key 4x unsealer and KEK for mkey in T210B01 units.
se_aes_unwrap_key(10, 14, console_keyseed_4xx);
@ -366,15 +349,30 @@ static int _hos_keygen(void *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt, bool stock
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;
bool use_tsec = false;
tsec_keys_t tsec_keys;
kb_t *kb_data = (kb_t *)keyblob;
if (kb > HOS_KB_VERSION_MAX)
return 0;
if (h_cfg.t210b01)
return hos_keygen_t210b01(kb);
// Do Erista keygen.
// Check if SBK is wiped and try to restore it from fuses.
if (!sbk_is_set)
// SBK is wiped. Try to restore it from fuses.
if (sbk_wiped)
{
if (fuse_set_sbk())
sbk_is_set = true;
sbk_wiped = false;
else
return 1; // Continue with current SE keys.
}
@ -383,7 +381,7 @@ static int _hos_keygen(void *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt, bool stock
_hos_eks_get();
// Use tsec keygen for old firmware or if EKS keys does not exist for newer.
if (kb <= HOS_KB_VERSION_620 || !h_cfg.eks || (h_cfg.eks->enabled != HOS_EKS_TSEC_VER))
if (kb <= HOS_KB_VERSION_620 || !h_cfg.eks || (h_cfg.eks && h_cfg.eks->enabled != HOS_EKS_TSEC_VER))
use_tsec = true;
if (kb <= HOS_KB_VERSION_600)
@ -412,7 +410,7 @@ static int _hos_keygen(void *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt, bool stock
tsec_ctxt->fw = sd_file_read("bootloader/sys/thk.bin", NULL);
if (!tsec_ctxt->fw)
{
_hos_crit_error("Failed to load thk.bin");
_hos_crit_error("\nFailed to load thk.bin");
return 0;
}
@ -436,7 +434,7 @@ static int _hos_keygen(void *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt, bool stock
// We rely on racing conditions, make sure we cover even the unluckiest cases.
if (retries > 15)
{
_hos_crit_error("Failed to get TSEC keys.");
_hos_crit_error("\nFailed to get TSEC keys. Please try again.");
return 0;
}
}
@ -570,7 +568,7 @@ static int _hos_keygen(void *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt, bool stock
se_aes_unwrap_key(15, 15, console_keyseed);
se_aes_unwrap_key(14, 12, master_keyseed_4xx);
se_aes_unwrap_key(12, 12, master_keyseed_retail);
sbk_is_set = false;
sbk_wiped = true;
break;
case HOS_KB_VERSION_500:
case HOS_KB_VERSION_600:
@ -578,7 +576,7 @@ static int _hos_keygen(void *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt, bool stock
se_aes_unwrap_key(15, 15, console_keyseed);
se_aes_unwrap_key(14, 12, master_keyseed_4xx);
se_aes_unwrap_key(12, 12, master_keyseed_retail);
sbk_is_set = false;
sbk_wiped = true;
break;
}
}
@ -700,7 +698,7 @@ out:
static void _free_launch_components(launch_ctxt_t *ctxt)
{
// Free the malloc'ed guaranteed addresses.
free(ctxt->pkg3);
free(ctxt->fss0);
free(ctxt->keyblob);
free(ctxt->pkg1);
free(ctxt->pkg2);
@ -750,7 +748,7 @@ static bool _get_fs_exfat_compatible(link_t *info, u32 *hos_revision)
return true;
}
void hos_launch(ini_sec_t *cfg)
int hos_launch(ini_sec_t *cfg)
{
u8 kb;
u32 secmon_base;
@ -758,6 +756,7 @@ void hos_launch(ini_sec_t *cfg)
bool is_exo = false;
launch_ctxt_t ctxt = {0};
tsec_ctxt_t tsec_ctxt = {0};
volatile secmon_mailbox_t *secmon_mailbox;
minerva_change_freq(FREQ_1600);
sdram_src_pllc(true);
@ -775,7 +774,10 @@ void hos_launch(ini_sec_t *cfg)
int res = emummc_storage_init_mmc();
if (res)
{
_hos_crit_error(res == 2 ? "Failed to init eMMC." : "Failed to init emuMMC.");
if (res == 2)
_hos_crit_error("Failed to init eMMC.");
else
_hos_crit_error("Failed to init emuMMC.");
goto error;
}
@ -783,12 +785,12 @@ void hos_launch(ini_sec_t *cfg)
// Check if SD Card is GPT.
if (sd_is_gpt())
{
_hos_crit_error("SD has GPT only! Run Fix Hybrid MBR!");
_hos_crit_error("SD has GPT only!");
goto error;
}
// Try to parse config if present.
if (!parse_boot_config(&ctxt))
if (ctxt.cfg && !parse_boot_config(&ctxt))
{
_hos_crit_error("Wrong ini cfg or missing/corrupt files!");
goto error;
@ -800,7 +802,6 @@ void hos_launch(ini_sec_t *cfg)
// Check if stock is enabled and device can boot in OFW.
if (ctxt.stock && (h_cfg.t210b01 || !tools_autorcm_enabled()))
{
sdram_src_pllc(false);
emmc_end();
WPRINTF("\nRebooting to OFW in 5s...");
@ -824,7 +825,7 @@ void hos_launch(ini_sec_t *cfg)
goto error;
}
ctxt.patch_krn_proc_id = true; // Set kernel process id patching in case of no pkg3.
ctxt.atmosphere = true; // Set atmosphere patching in case of no fss0.
config_kip1patch(&ctxt, "emummc");
}
else if (!emu_cfg.enabled && ctxt.emummc_forced)
@ -876,7 +877,7 @@ void hos_launch(ini_sec_t *cfg)
tsec_ctxt.pkg11_off = ctxt.pkg1_id->pkg11_off;
// 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;
gfx_puts("Generated keys\n");
@ -978,7 +979,7 @@ void hos_launch(ini_sec_t *cfg)
_hos_crit_error("Pkg2 decryption failed!\npkg1/pkg2 mismatch or old hekate!");
// Clear EKS slot, in case something went wrong with tsec keygen.
_hos_eks_clear(kb);
hos_eks_clear(kb);
goto error;
}
@ -997,7 +998,7 @@ void hos_launch(ini_sec_t *cfg)
ctxt.kernel = pkg2_hdr->data;
ctxt.kernel_size = pkg2_hdr->sec_size[PKG2_SEC_KERNEL];
if (!ctxt.stock && (ctxt.svcperm || ctxt.debugmode || ctxt.patch_krn_proc_id))
if (!ctxt.stock && (ctxt.svcperm || ctxt.debugmode || ctxt.atmosphere))
{
// Hash only Kernel when it embeds INI1.
u8 kernel_hash[0x20];
@ -1024,10 +1025,10 @@ void hos_launch(ini_sec_t *cfg)
for (u32 i = 0; kernel_patchset[i].id != 0xFFFFFFFF; i++)
{
if ((ctxt.svcperm && kernel_patchset[i].id == SVC_VERIFY_DS)
|| (ctxt.debugmode && kernel_patchset[i].id == DEBUG_MODE_EN && !(ctxt.patch_krn_proc_id && ctxt.secmon))
|| (ctxt.patch_krn_proc_id && kernel_patchset[i].id == ATM_GEN_PATCH))
|| (ctxt.debugmode && kernel_patchset[i].id == DEBUG_MODE_EN && !(ctxt.atmosphere && ctxt.secmon))
|| (ctxt.atmosphere && kernel_patchset[i].id == ATM_GEN_PATCH))
*(vu32 *)(ctxt.kernel + kernel_patchset[i].off) = kernel_patchset[i].val;
else if (ctxt.patch_krn_proc_id && kernel_patchset[i].id == ATM_ARR_PATCH)
else if (ctxt.atmosphere && kernel_patchset[i].id == ATM_ARR_PATCH)
{
temp = (u32 *)kernel_patchset[i].ptr;
for (u32 j = 0; j < kernel_patchset[i].val; j++)
@ -1147,7 +1148,6 @@ void hos_launch(ini_sec_t *cfg)
//pmc_scratch_lock(PMC_SEC_LOCK_LP0_PARAMS);
// Set secmon mailbox address and clear it.
volatile secmon_mailbox_t *secmon_mailbox;
if (kb >= HOS_KB_VERSION_700 || is_exo)
{
memset((void *)SECMON7_MAILBOX_ADDR, 0, 0x200);
@ -1199,4 +1199,6 @@ error:
emmc_end();
EPRINTF("\nFailed to launch HOS!");
return 0;
}

View file

@ -1,6 +1,6 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2025 CTCaer
* Copyright (c) 2018-2024 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
@ -45,9 +45,7 @@ enum {
HOS_KB_VERSION_1600 = 15,
HOS_KB_VERSION_1700 = 16,
HOS_KB_VERSION_1800 = 17,
HOS_KB_VERSION_1900 = 18,
HOS_KB_VERSION_2000 = 19,
HOS_KB_VERSION_MAX = HOS_KB_VERSION_2000
HOS_KB_VERSION_MAX = HOS_KB_VERSION_1800
};
#define HOS_TSEC_VERSION 4 //! TODO: Update on TSEC Root Key changes.
@ -105,16 +103,16 @@ typedef struct _launch_ctxt_t
u32 kernel_size;
link_t kip1_list;
char *kip1_patches;
char* kip1_patches;
bool svcperm;
bool debugmode;
bool stock;
bool emummc_forced;
void *pkg3;
u32 pkg3_hosver;
bool patch_krn_proc_id;
void *fss0;
u32 fss0_hosver;
bool atmosphere;
int ucid;
@ -129,6 +127,8 @@ typedef struct _merge_kip_t
link_t link;
} merge_kip_t;
void hos_launch(ini_sec_t *cfg);
void hos_eks_clear(u32 kb);
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

View file

@ -1,6 +1,6 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2025 CTCaer
* Copyright (c) 2018-2024 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
@ -21,7 +21,7 @@
#include "hos.h"
#include "hos_config.h"
#include "pkg3.h"
#include "fss.h"
#include <libs/fatfs/ff.h>
//#define DPRINTF(...) gfx_printf(__VA_ARGS__)
@ -58,14 +58,14 @@ static int _config_kip1(launch_ctxt_t *ctxt, const char *value)
{
u32 size;
if (value[strlen(value) - 1] == '*')
if (!memcmp(value + strlen(value) - 1, "*", 1))
{
char *dir = (char *)malloc(256);
strcpy(dir, value);
u32 dirlen = 0;
dir[strlen(dir) - 2] = 0;
dirlist_t *filelist = dirlist(dir, "*.kip*", false, false);
char *filelist = dirlist(dir, "*.kip*", false, false);
strcat(dir, "/");
dirlen = strlen(dir);
@ -75,10 +75,10 @@ static int _config_kip1(launch_ctxt_t *ctxt, const char *value)
{
while (true)
{
if (!filelist->name[i])
if (!filelist[i * 256])
break;
strcpy(dir + dirlen, filelist->name[i]);
strcpy(dir + dirlen, &filelist[i * 256]);
merge_kip_t *mkip1 = (merge_kip_t *)malloc(sizeof(merge_kip_t));
mkip1->kip1 = sd_file_read(dir, &size);
@ -119,6 +119,9 @@ static int _config_kip1(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);
if (!len)
return 0;
@ -185,12 +188,12 @@ static int _config_emummc_forced(launch_ctxt_t *ctxt, const char *value)
return 1;
}
static int _config_kernel_proc_id(launch_ctxt_t *ctxt, const char *value)
static int _config_atmosphere(launch_ctxt_t *ctxt, const char *value)
{
if (*value == '1')
{
DPRINTF("Enabled kernel process id send/recv patching\n");
ctxt->patch_krn_proc_id = true;
DPRINTF("Enabled atmosphere patching\n");
ctxt->atmosphere = true;
}
return 1;
}
@ -255,9 +258,9 @@ static int _config_exo_cal0_writes_enable(launch_ctxt_t *ctxt, const char *value
return 1;
}
static int _config_pkg3(launch_ctxt_t *ctxt, const char *value)
static int _config_fss(launch_ctxt_t *ctxt, const char *value)
{
return parse_pkg3(ctxt, value);
return parse_fss(ctxt, value);
}
static int _config_exo_fatal_payload(launch_ctxt_t *ctxt, const char *value)
@ -284,7 +287,6 @@ typedef struct _cfg_handler_t
} cfg_handler_t;
static const cfg_handler_t _config_handlers[] = {
{ "stock", _config_stock },
{ "warmboot", _config_warmboot },
{ "secmon", _config_secmon },
{ "kernel", _config_kernel },
@ -292,12 +294,9 @@ static const cfg_handler_t _config_handlers[] = {
{ "kip1patch", config_kip1patch },
{ "fullsvcperm", _config_svcperm },
{ "debugmode", _config_debugmode },
{ "kernelprocid", _config_kernel_proc_id },
// To override elements from PKG3, it should be set before others.
{ "pkg3", _config_pkg3 },
{ "fss0", _config_pkg3 },
{ "stock", _config_stock },
{ "atmosphere", _config_atmosphere },
{ "fss0", _config_fss },
{ "exofatal", _config_exo_fatal_payload},
{ "emummcforce", _config_emummc_forced },
{ "nouserexceptions", _config_dis_exo_user_exceptions },
@ -311,15 +310,10 @@ static const cfg_handler_t _config_handlers[] = {
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)
{
for (u32 i = 0; _config_handlers[i].key; i++)
{
// If key matches, call its handler.
if (!strcmp(_config_handlers[i].key, kv->key))
{
if (!_config_handlers[i].handler(ctxt, kv->val))
@ -329,8 +323,6 @@ int parse_boot_config(launch_ctxt_t *ctxt)
return 0;
}
break;
}
}
}

View file

@ -1,7 +1,7 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018 st4rk
* Copyright (c) 2018-2025 CTCaer
* Copyright (c) 2018-2024 CTCaer
* Copyright (c) 2018 balika011
*
* This program is free software; you can redistribute it and/or modify it
@ -33,7 +33,7 @@ extern hekate_config h_cfg;
#define SM_100_ADR 0x4002B020 // Original: 0x40014020.
PATCHSET_DEF(_secmon_1_patchset,
// Patch the relocator to be able to run from SM_100_ADR.
{ 0x1E0, _ADRP(0, TZRAM_BASE + 0x3000 - _PAGEOFF(SM_100_ADR)) },
{ 0x1E0, _ADRP(0, 0x7C013000 - _PAGEOFF(SM_100_ADR)) },
// Patch package2 signature/hash checks.
{ 0x9F0 + 0xADC, _NOP() }
);
@ -143,7 +143,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_4xx[3] = { PK11_SECTION_LD, PK11_SECTION_SM, PK11_SECTION_WB };
// Timestamp KB FU TSEC PK11 SECMON Warmboot
// ID (Timestamp), KB, Fuses, TSEC, PK11, SECMON, Warmboot.
static const pkg1_id_t _pkg1_ids[] = {
{ "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.
@ -170,9 +170,7 @@ static const pkg1_id_t _pkg1_ids[] = {
{ "20220801", 14, 17, 0x0E00, 0x6FE0, 0x40030000, 0x4003E000, NULL }, // 15.0.0 - 15.0.1.
{ "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.
{ "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 - 19.0.1.
{ "20250206", 19, 21, 0x0E00, 0x6FE0, 0x40030000, 0x4003E000, NULL }, // 20.0.0+
{ "20240207", 17, 19, 0x0E00, 0x6FE0, 0x40030000, 0x4003E000, NULL }, // 18.0.0+
};
const pkg1_id_t *pkg1_get_latest()

View file

@ -1,6 +1,6 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2025 CTCaer
* Copyright (c) 2018-2024 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
@ -37,7 +37,6 @@ extern const u8 package2_keyseed[];
u32 pkg2_newkern_ini1_info;
u32 pkg2_newkern_ini1_start;
u32 pkg2_newkern_ini1_end;
u32 pkg2_newkern_ini1_rela;
enum kip_offset_section
{
@ -171,7 +170,7 @@ static void parse_external_kip_patches()
ext_patches_parsed = true;
}
const pkg2_kernel_id_t *pkg2_identify(const u8 *hash)
const pkg2_kernel_id_t *pkg2_identify(u8 *hash)
{
for (u32 i = 0; i < ARRAY_SIZE(_pkg2_kernel_ids); i++)
{
@ -189,12 +188,11 @@ static u32 _pkg2_calc_kip1_size(pkg2_kip1_t *kip1)
return size;
}
static void _pkg2_get_newkern_info(u8 *kern_data)
void pkg2_get_newkern_info(u8 *kern_data)
{
u32 crt_start = 0;
pkg2_newkern_ini1_info = 0;
pkg2_newkern_ini1_start = 0;
pkg2_newkern_ini1_rela = 0;
u32 first_op = *(u32 *)kern_data;
if ((first_op & 0xFE000000) == 0x14000000)
@ -231,7 +229,6 @@ static void _pkg2_get_newkern_info(u8 *kern_data)
// On v2 kernel with dynamic crt, values are relative to value address.
if (crt_start)
{
pkg2_newkern_ini1_rela = pkg2_newkern_ini1_info;
pkg2_newkern_ini1_start += pkg2_newkern_ini1_info;
pkg2_newkern_ini1_end += pkg2_newkern_ini1_info + 0x8;
}
@ -243,7 +240,7 @@ bool pkg2_parse_kips(link_t *info, pkg2_hdr_t *pkg2, bool *new_pkg2)
// Check for new pkg2 type.
if (!pkg2->sec_size[PKG2_SEC_INI1])
{
_pkg2_get_newkern_info(pkg2->data);
pkg2_get_newkern_info(pkg2->data);
if (!pkg2_newkern_ini1_start)
return false;
@ -686,10 +683,6 @@ const char *pkg2_patch_kips(link_t *info, char *patch_names)
return patches[i];
}
// Check if emuMMC was applied.
if (emummc_patch_selected)
return "emummc";
return NULL;
}
@ -852,15 +845,10 @@ DPRINTF("%s @ %08X (%08X)\n", is_meso ? "Mesosphere": "kernel",(u32)ctxt->kernel
// Set new INI1 offset to kernel.
u32 meso_meta_offset = *(u32 *)(pdst + 8);
if (is_meso && (meso_magic & 0x0F000000)) // MSS1.
if (is_meso && (meso_magic & 0xF000000)) // MSS1.
*(u32 *)(pdst + meso_meta_offset) = kernel_size - meso_meta_offset;
else if (ini1_size)
{
if (is_meso) // MSS0.
*(u32 *)(pdst + 8) = kernel_size;
else
*(u32 *)(pdst + pkg2_newkern_ini1_info) = kernel_size - pkg2_newkern_ini1_rela;
}
*(u32 *)(pdst + (is_meso ? 8 : pkg2_newkern_ini1_info)) = kernel_size;
kernel_size += ini1_size;
}
@ -877,13 +865,13 @@ DPRINTF("INI1 encrypted\n");
if (!is_exo) // Not needed on Exosphere 1.0.0 and up.
{
// Calculate SHA256 over encrypted sections. Only 3 have valid hashes.
// Calculate SHA256 over encrypted Kernel and INI1.
u8 *pk2_hash_data = (u8 *)dst + 0x100 + sizeof(pkg2_hdr_t);
for (u32 i = PKG2_SEC_KERNEL; i <= PKG2_SEC_UNUSED; i++)
{
se_calc_sha256_oneshot(&hdr->sec_sha256[SE_SHA_256_SIZE * i], (void *)pk2_hash_data, hdr->sec_size[i]);
pk2_hash_data += hdr->sec_size[i];
}
se_calc_sha256_oneshot(&hdr->sec_sha256[SE_SHA_256_SIZE * PKG2_SEC_KERNEL],
(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 * PKG2_SEC_INI1],
(void *)pk2_hash_data, hdr->sec_size[PKG2_SEC_INI1]);
}
// Encrypt header.

View file

@ -1,6 +1,6 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2025 CTCaer
* Copyright (c) 2018-2024 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
@ -24,13 +24,12 @@
#define PKG2_SEC_BASE 0x80000000
#define PKG2_SEC_KERNEL 0
#define PKG2_SEC_INI1 1
#define PKG2_SEC_UNUSED 2
#define INI1_MAGIC 0x31494E49
//! TODO: Update on kernel change if needed.
// Offset of OP + 12 is the INI1 offset. On v2 with dynamic crt0 it's + 16.
#define PKG2_NEWKERN_GET_INI1_HEURISTIC 0xD2800015 // MOV X21, #0.
#define PKG2_NEWKERN_GET_INI1_HEURISTIC 0xD2800015
#define PKG2_NEWKERN_START 0x800
#define ATM_MESOSPHERE 0x3053534D
@ -68,18 +67,18 @@ enum
typedef struct _pkg2_hdr_t
{
/* 0x000 */ u8 ctr[0x10];
/* 0x010 */ u8 sec_ctr[0x40];
/* 0x050 */ u32 magic;
/* 0x054 */ u32 base;
/* 0x058 */ u32 pad0;
/* 0x05C */ u8 pkg2_ver;
/* 0x05D */ u8 bl_ver;
/* 0x05E */ u16 pad1;
/* 0x060 */ u32 sec_size[4];
/* 0x070 */ u32 sec_off[4];
/* 0x080 */ u8 sec_sha256[0x80];
/* 0x100 */ u8 data[];
u8 ctr[0x10];
u8 sec_ctr[0x40];
u32 magic;
u32 base;
u32 pad0;
u8 pkg2_ver;
u8 bl_ver;
u16 pad1;
u32 sec_size[4];
u32 sec_off[4];
u8 sec_sha256[0x80];
u8 data[];
} pkg2_hdr_t;
typedef struct _pkg2_ini1_t
@ -103,7 +102,7 @@ typedef struct _pkg2_kip1_sec_t
typedef struct _pkg2_kip1_t
{
/* 0x000 */ u32 magic;
/* 0x004 */ u8 name[12];
/* 0x004*/ u8 name[12];
/* 0x010 */ u64 tid;
/* 0x018 */ u32 proc_cat;
/* 0x01C */ u8 main_thrd_prio;
@ -151,6 +150,7 @@ typedef struct _kip1_id_t
const kip1_patchset_t *patchset;
} 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);
int pkg2_has_kip(link_t *info, u64 tid);
void pkg2_replace_kip(link_t *info, u64 tid, pkg2_kip1_t *kip1);
@ -159,7 +159,7 @@ void pkg2_merge_kip(link_t *info, pkg2_kip1_t *kip1);
void pkg2_get_ids(kip1_id_t **ids, u32 *entries);
const char *pkg2_patch_kips(link_t *info, char *patch_names);
const pkg2_kernel_id_t *pkg2_identify(const u8 *hash);
const pkg2_kernel_id_t *pkg2_identify(u8 *hash);
pkg2_hdr_t *pkg2_decrypt(void *data, u8 kb, bool is_exo);
void pkg2_build_encrypt(void *dst, void *hos_ctxt, link_t *kips_info, bool is_exo);

View file

@ -95,7 +95,7 @@ static ini_kip_sec_t *_ini_create_kip_section(link_t *dst, ini_kip_sec_t *ksec,
return ksec;
}
int ini_patch_parse(link_t *dst, const char *ini_path)
int ini_patch_parse(link_t *dst, char *ini_path)
{
FIL fp;
u32 lblen;
@ -154,15 +154,15 @@ int ini_patch_parse(link_t *dst, const char *ini_path)
pt->length = strtol(&lbuf[pos], NULL, 16);
pos += str_start + 1;
u8 *data = malloc(pt->length * 2);
u8 *buf = malloc(pt->length * 2);
// Set patch source data.
str_start = _find_patch_section_name(&lbuf[pos], lblen - pos, ',');
pt->src_data = _htoa(NULL, &lbuf[pos], pt->length, data);
pt->src_data = _htoa(NULL, &lbuf[pos], pt->length, buf);
pos += str_start + 1;
// Set patch destination data.
pt->dst_data = _htoa(NULL, &lbuf[pos], pt->length, data + pt->length);
pt->dst_data = _htoa(NULL, &lbuf[pos], pt->length, buf + pt->length);
}
list_append(&ksec->pts, &pt->link);

View file

@ -37,6 +37,6 @@ typedef struct _ini_kip_sec_t
link_t link;
} ini_kip_sec_t;
int ini_patch_parse(link_t *dst, const char *ini_path);
int ini_patch_parse(link_t *dst, char *ini_path);
#endif

View file

@ -794,54 +794,6 @@ static const kip1_patchset_t _fs_patches_1800_exfat[] = {
{ NULL, NULL }
};
static const kip1_patch_t _fs_nogc_1900[] = {
{ KPS(KIP_TEXT) | 0x16F070, 8, KIP1_PATCH_SRC_NO_CHECK, "\xE0\x03\x1F\x2A\xC0\x03\x5F\xD6" },
{ KPS(KIP_TEXT) | 0x195B74, 4, KIP1_PATCH_SRC_NO_CHECK, "\x14\x80\x80\x52" },
{ KPS(KIP_TEXT) | 0x195D74, 4, KIP1_PATCH_SRC_NO_CHECK, "\x16\x80\x80\x52" },
{ 0, 0, NULL, NULL }
};
static const kip1_patchset_t _fs_patches_1900[] = {
{ "nogc", _fs_nogc_1900 },
{ NULL, NULL }
};
static const kip1_patch_t _fs_nogc_1900_exfat[] = {
{ KPS(KIP_TEXT) | 0x17A8A0, 8, KIP1_PATCH_SRC_NO_CHECK, "\xE0\x03\x1F\x2A\xC0\x03\x5F\xD6" },
{ KPS(KIP_TEXT) | 0x1A13A4, 4, KIP1_PATCH_SRC_NO_CHECK, "\x14\x80\x80\x52" },
{ KPS(KIP_TEXT) | 0x1A15A4, 4, KIP1_PATCH_SRC_NO_CHECK, "\x16\x80\x80\x52" },
{ 0, 0, NULL, NULL }
};
static const kip1_patchset_t _fs_patches_1900_exfat[] = {
{ "nogc", _fs_nogc_1900_exfat },
{ 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.
static const kip1_id_t _kip_ids[] =
{
@ -905,10 +857,4 @@ static const kip1_id_t _kip_ids[] =
{ "FS", "\x1E\x2C\x64\xB1\xCC\xE2\x78\x24", _fs_patches_1800_exfat }, // FS 18.0.0 exFAT
{ "FS", "\xA3\x39\xF0\x1C\x95\xBF\xA7\x68", _fs_patches_1800 }, // FS 18.1.0
{ "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", "\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
};

View file

@ -199,7 +199,7 @@ void config_exosphere(launch_ctxt_t *ctxt, u32 warmboot_base)
case 12:
exo_fw_no = EXO_FW_VER(9, 1);
break;
case 13 ... 23: //!TODO: Update on API changes. 23: 20.0.0.
case 13 ... 21: //!TODO: Update on API changes. 21: 18.0.0.
exo_fw_no = EXO_FW_VER(exo_fw_no - 3, ctxt->exo_ctx.hos_revision);
break;
}
@ -207,10 +207,10 @@ void config_exosphere(launch_ctxt_t *ctxt, u32 warmboot_base)
// Parse exosphere.ini.
if (!ctxt->stock)
{
LIST_INIT(ini_exo_sections);
if (ini_parse(&ini_exo_sections, "exosphere.ini", false))
LIST_INIT(ini_sections);
if (ini_parse(&ini_sections, "exosphere.ini", false))
{
LIST_FOREACH_ENTRY(ini_sec_t, ini_sec, &ini_exo_sections, link)
LIST_FOREACH_ENTRY(ini_sec_t, ini_sec, &ini_sections, link)
{
// Only parse exosphere section.
if (!(ini_sec->type == INI_CHOICE) || strcmp(ini_sec->name, "exosphere"))
@ -241,15 +241,14 @@ void config_exosphere(launch_ctxt_t *ctxt, u32 warmboot_base)
}
break;
}
}
// Parse usb mtim settings. Avoid parsing if it's overridden.
if (!ctxt->exo_ctx.usb3_force)
{
LIST_INIT(ini_sys_sections);
if (ini_parse(&ini_sys_sections, "atmosphere/config/system_settings.ini", false))
LIST_INIT(ini_sections);
if (ini_parse(&ini_sections, "atmosphere/config/system_settings.ini", false))
{
LIST_FOREACH_ENTRY(ini_sec_t, ini_sec, &ini_sys_sections, link)
LIST_FOREACH_ENTRY(ini_sec_t, ini_sec, &ini_sections, link)
{
// Only parse usb section.
if (!(ini_sec->type == INI_CHOICE) || strcmp(ini_sec->name, "usb"))
@ -268,9 +267,10 @@ void config_exosphere(launch_ctxt_t *ctxt, u32 warmboot_base)
}
}
}
}
// Private debug mode always on for CFW mode.
if (!ctxt->stock)
// To avoid problems, make private debug mode always on if not semi-stock.
if (!ctxt->stock || (emu_cfg.enabled && !h_cfg.emummc_force_disable))
exo_flags |= EXO_FLAG_DBG_PRIV;
// Enable user debug.

View file

@ -1,7 +1,7 @@
/*
* L4T Loader for Tegra X1
*
* Copyright (c) 2020-2025 CTCaer
* Copyright (c) 2020-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,
@ -36,11 +36,10 @@
* 4: Arachne Register Cell v3. DRAM OPT and DDR200 changes.
* 5: Arachne Register Cell v4. DRAM FREQ and DDR200 changes.
* 6: Arachne Register Cell v5. Signal quality and performance changes. TZ param changes.
* 7: Arachne Register Cell v6. Decouple of rd/wr latencies.
*/
#define L4T_LOADER_API_REV 7
#define L4T_FIRMWARE_REV 0x37524556 // REV7.
#define L4T_LOADER_API_REV 6
#define L4T_FIRMWARE_REV 0x36524556 // REV6.
#ifdef DEBUG_UART_PORT
#include <soc/uart.h>
@ -272,8 +271,6 @@ typedef struct _l4t_ctxt_t
int ram_oc_opt;
u32 serial_port;
u32 sld_type;
u32 sc7entry_size;
emc_table_t *mtc_table;
@ -290,22 +287,18 @@ typedef struct _l4t_ctxt_t
#define DRAM_VDDQ_OC_MAX_VOLTAGE 650
#define DRAM_T210B01_TBL_MAX_FREQ 1600000
#define NA 0 // Default to 0 for incorrect dram ids.
//!TODO: Update on dram config changes.
//! TODO: Update on dram config changes.
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 */
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
-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
};
#undef NA
static const l4t_fw_t l4t_fw[] = {
{ TZDRAM_BASE, "bl31.bin" },
{ BL33_LOAD_BASE, "bl33.bin" },
{ SC7ENTRY_BASE, "sc7entry.bin" },
{ SC7EXIT_BASE, "sc7exit.bin" },
{ SC7EXIT_B01_BASE, "sc7exit_b01.bin" }, //!TODO: Update on fuse burns.
{ SC7EXIT_B01_BASE, "sc7exit_b01.bin" },
{ BPMPFW_BASE, "bpmpfw.bin" },
{ BPMPFW_B01_BASE, "bpmpfw_b01.bin" },
{ BPMPFW_B01_MTC_TABLE_BASE, "mtc_tbl_b01.bin" },
@ -386,7 +379,7 @@ static void _l4t_sdram_lp0_save_params(bool t210b01)
s(MC_VIDEO_PROTECT_REG_CTRL, 1:0, secure_scratch14, 31:30);
}
// TZDRAM.
// TZD.
s(MC_SEC_CARVEOUT_BOM, 31:20, secure_scratch53, 23:12);
s(MC_SEC_CARVEOUT_SIZE_MB, 11:0, secure_scratch54, 11:0);
if (!t210b01) {
@ -528,6 +521,11 @@ 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_ACCESS3) = SEC_CARVEOUT_CA3_R_NVDEC | SEC_CARVEOUT_CA3_W_NVDEC;
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 |
SEC_CARVEOUT_CFG_UNTRANSLATED_ONLY |
SEC_CARVEOUT_CFG_RD_SEC |
@ -559,6 +557,11 @@ static void _l4t_mc_config_carveout(bool t210b01)
MC(MC_SECURITY_CARVEOUT1_CLIENT_ACCESS2) = 0;
MC(MC_SECURITY_CARVEOUT1_CLIENT_ACCESS3) = 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 |
SEC_CARVEOUT_CFG_RD_SEC |
SEC_CARVEOUT_CFG_WR_NS |
@ -595,6 +598,11 @@ 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_ACCESS3) = 0;
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 |
SEC_CARVEOUT_CFG_UNTRANSLATED_ONLY |
SEC_CARVEOUT_CFG_RD_NS |
@ -623,6 +631,11 @@ 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_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_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 |
SEC_CARVEOUT_CFG_UNTRANSLATED_ONLY |
SEC_CARVEOUT_CFG_RD_NS |
@ -838,7 +851,7 @@ static int _l4t_sc7_exit_config(bool t210b01)
return 1;
}
static void _l4t_bl33_cfg_set_key(char *env, const char *key, const char *val)
static void _l4t_bl33_cfg_set_key(char *env, char *key, char *val)
{
strcat(env, key);
strcat(env, "=");
@ -852,9 +865,6 @@ static void _l4t_set_config(l4t_ctxt_t *ctxt, const ini_sec_t *ini_sec, int entr
bl33_env[0] = '\0';
char val[4] = {0};
// Set default SLD type.
ctxt->sld_type = BL_MAGIC_L4TLDR_SLD;
// Parse ini section and prepare BL33 env.
LIST_FOREACH_ENTRY(ini_kv_t, kv, &ini_sec->kvs, link)
{
@ -888,8 +898,6 @@ static void _l4t_set_config(l4t_ctxt_t *ctxt, const ini_sec_t *ini_sec, int entr
ctxt->ram_oc_opt = atoi(kv->val);
else if (!strcmp("uart_port", kv->key))
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.
_l4t_bl33_cfg_set_key(bl33_env, kv->key, kv->val);
@ -1156,7 +1164,7 @@ void launch_l4t(const ini_sec_t *ini_sec, int entry_idx, int is_list, bool t210b
_l4t_mc_config_carveout(t210b01);
// Deinit any unneeded HW.
hw_deinit(false, ctxt->sld_type);
hw_deinit(false, BL_MAGIC_L4TLDR_SLD);
// Do late hardware config.
_l4t_late_hw_config(t210b01);

View file

@ -256,7 +256,7 @@
#define FF_FS_NORTC 1
#define FF_NORTC_MON 1
#define FF_NORTC_MDAY 1
#define FF_NORTC_YEAR 2025
#define FF_NORTC_YEAR 2024
/* 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
/ the timestamp function. Every object modified by FatFs will have a fixed timestamp

View file

@ -120,7 +120,7 @@ static void _reloc_patcher(u32 payload_dst, u32 payload_src, u32 payload_size)
}
}
bool is_ipl_updated(void *buf, const char *path, bool force)
bool is_ipl_updated(void *buf, char *path, bool force)
{
ipl_ver_meta_t *update_ft = (ipl_ver_meta_t *)(buf + PATCHED_RELOC_SZ + sizeof(boot_cfg_t));
@ -257,9 +257,9 @@ static void _launch_payloads()
{
u8 max_entries = 61;
ment_t *ments = NULL;
char *filelist = NULL;
char *file_sec = NULL;
char *dir = NULL;
dirlist_t *filelist = NULL;
gfx_clear_grey(0x1B);
gfx_con_setpos(0, 0);
@ -286,11 +286,11 @@ static void _launch_payloads()
while (true)
{
if (i > max_entries || !filelist->name[i])
if (i > max_entries || !filelist[i * 256])
break;
ments[i + 2].type = INI_CHOICE;
ments[i + 2].caption = filelist->name[i];
ments[i + 2].data = filelist->name[i];
ments[i + 2].caption = &filelist[i * 256];
ments[i + 2].data = &filelist[i * 256];
i++;
}
@ -444,10 +444,8 @@ parse_failed:
launch_l4t(cfg_sec, entry_idx, 1, h_cfg.t210b01);
}
}
else
else if (!hos_launch(cfg_sec))
{
hos_launch(cfg_sec);
wrong_emupath:
if (emummc_path)
{
@ -589,10 +587,8 @@ parse_failed:
launch_l4t(cfg_sec, entry_idx, 0, h_cfg.t210b01);
}
}
else
else if (!hos_launch(cfg_sec))
{
hos_launch(cfg_sec);
wrong_emupath:
if (emummc_path)
{
@ -1354,7 +1350,7 @@ static void _about()
{
static const char credits[] =
"\nhekate (c) 2018, naehrwert, st4rk\n\n"
" (c) 2018-2025, CTCaer\n\n"
" (c) 2018-2024, CTCaer\n\n"
" ___________________________________________\n\n"
"Thanks to: %kderrek, nedwill, plutoo,\n"
" shuffle2, smea, thexyz, yellows8%k\n"
@ -1450,7 +1446,7 @@ ment_t ment_top[] = {
MDEF_END()
};
menu_t menu_top = { ment_top, "hekate v6.3.1", 0, 0 };
menu_t menu_top = { ment_top, "hekate v6.2.1", 0, 0 };
extern void pivot_stack(u32 stack_top);

View file

@ -46,7 +46,7 @@ clean:
@rm -rf $(OBJS)
$(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)
@$(CC) $(LDFLAGS) -T link.ld $^ -o $@

View file

@ -85,7 +85,7 @@ typedef struct
bool emc_2X_clk_src_is_pllmb;
bool fsp_for_src_freq;
bool train_ram_patterns;
u32 init_done;
bool init_done;
} mtc_config_t;
enum train_mode_t

View file

@ -93,12 +93,12 @@ CUSTOMDEFINES += -DGFX_INC=$(GFX_INC) -DFFCFG_INC=$(FFCFG_INC)
#CUSTOMDEFINES += -DDEBUG_UART_LV_LOG
#TODO: Considering reinstating some of these when pointer warnings have been fixed.
WARNINGS := -Wall -Wsign-compare -Wtype-limits -Wno-array-bounds -Wno-stringop-overread -Wno-stringop-overflow
WARNINGS := -Wall -Wsign-compare -Wno-array-bounds -Wno-stringop-overread -Wno-stringop-overflow
#-fno-delete-null-pointer-checks
#-Wstack-usage=byte-size -fstack-usage
ARCH := -march=armv4t -mtune=arm7tdmi -mthumb-interwork $(WARNINGS)
CFLAGS = $(ARCH) -O2 -g -gdwarf-4 -nostdlib -ffunction-sections -fdata-sections -fomit-frame-pointer -std=gnu11 $(CUSTOMDEFINES)
ARCH := -march=armv4t -mtune=arm7tdmi -mthumb-interwork
CFLAGS = $(ARCH) -O2 -g -gdwarf-4 -nostdlib -ffunction-sections -fdata-sections -fomit-frame-pointer -std=gnu11 $(WARNINGS) $(CUSTOMDEFINES)
LDFLAGS = $(ARCH) -nostartfiles -lgcc -Wl,--nmagic,--gc-sections -Xlinker --defsym=NYX_LOAD_ADDR=$(NYX_LOAD_ADDR)
################################################################################
@ -118,11 +118,11 @@ clean:
@rm -rf $(OUTPUTDIR)
$(TARGET).bin: $(BUILDDIR)/$(TARGET)/$(TARGET).elf
@$(OBJCOPY) -S -O binary $< $(OUTPUTDIR)/$@
$(OBJCOPY) -S -O binary $< $(OUTPUTDIR)/$@
$(BUILDDIR)/$(TARGET)/$(TARGET).elf: $(OBJS)
@$(CC) $(LDFLAGS) -T $(SOURCEDIR)/link.ld $^ -o $@
@printf "$(TARGET) was built with the following flags:\nCFLAGS: $(CFLAGS)\nLDFLAGS: $(LDFLAGS)\n"
@echo "Nyx was built with the following flags:\nCFLAGS: "$(CFLAGS)"\nLDFLAGS: "$(LDFLAGS)
$(BUILDDIR)/$(TARGET)/%.o: %.c
@echo Building $@

View file

@ -53,19 +53,19 @@ static void _get_valid_partition(u32 *sector_start, u32 *sector_size, u32 *part_
*sector_start = mbr->partitions[i].start_sct;
u8 type = mbr->partitions[i].type;
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)
{
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))
{
*sector_size = curr_part_size;
*sector_start = (*sector_start) + 0x8000;
*sector_start = *sector_start + 0x8000;
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))
{
*sector_size = curr_part_size;
@ -91,7 +91,7 @@ static void _get_valid_partition(u32 *sector_start, u32 *sector_size, u32 *part_
if (backup && *part_idx && *sector_size)
{
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;
if (*sector_size > new_size)
@ -102,10 +102,10 @@ static void _get_valid_partition(u32 *sector_start, u32 *sector_size, u32 *part_
free(gpt);
}
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(char *text, bool button_ok)
{
lv_obj_t *dark_bg = lv_obj_create(lv_scr_act(), NULL);
lv_obj_set_style(dark_bg, &mbox_darken);
@ -137,7 +137,7 @@ static void _update_filename(char *outFilename, u32 sdPathLen, u32 currPartIdx)
itoa(currPartIdx, &outFilename[sdPathLen], 10);
}
static int _dump_emmc_verify(emmc_tool_gui_t *gui, sdmmc_storage_t *storage, u32 lba_curr, const char *outFilename, const emmc_part_t *part)
static int _dump_emmc_verify(emmc_tool_gui_t *gui, sdmmc_storage_t *storage, u32 lba_curr, char *outFilename, emmc_part_t *part)
{
FIL fp;
FIL hashFp;
@ -621,21 +621,11 @@ static int _dump_emmc_part(emmc_tool_gui_t *gui, char *sd_path, int active_part,
res_read = !sdmmc_storage_read(&sd_storage, lba_curr + sd_sector_off, num, buf);
while (res_read)
{
if (!gui->raw_emummc)
{
s_printf(gui->txt_buf,
"\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);
manual_system_maintenance(true);
@ -1128,7 +1118,7 @@ multipart_not_allowed:
manual_system_maintenance(true);
}
return -1;
return 0;
}
else if (!use_multipart && (((u32)((u64)f_size(&fp) >> (u64)9)) != totalSectors)) // Check total restore size vs emmc size.
{
@ -1485,13 +1475,10 @@ void restore_emmc_selected(emmcPartType_t restoreType, emmc_tool_gui_t *gui)
if (!res)
s_printf(txt_buf, "#FFDD00 Failed!#\n");
else if (res > 0)
else
s_printf(txt_buf, "Done!\n");
if (res >= 0)
lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, txt_buf);
else
res = 0;
manual_system_maintenance(true);
}
}
@ -1521,13 +1508,10 @@ void restore_emmc_selected(emmcPartType_t restoreType, emmc_tool_gui_t *gui)
if (!res)
s_printf(txt_buf, "#FFDD00 Failed!#\n");
else if (res > 0)
else
s_printf(txt_buf, "Done!\n");
if (res >= 0)
lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, txt_buf);
else
res = 0;
manual_system_maintenance(true);
}
emmc_gpt_free(&gpt);
@ -1560,13 +1544,10 @@ void restore_emmc_selected(emmcPartType_t restoreType, emmc_tool_gui_t *gui)
if (!res)
s_printf(txt_buf, "#FFDD00 Failed!#\n");
else if (res > 0)
else
s_printf(txt_buf, "Done!\n");
if (res >= 0)
lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, txt_buf);
else
res = 0;
manual_system_maintenance(true);
}
}

View file

@ -143,7 +143,7 @@ void update_emummc_base_folder(char *outFilename, u32 sdPathLen, u32 currPartIdx
itoa(currPartIdx, &outFilename[sdPathLen], 10);
}
static int _dump_emummc_file_part(emmc_tool_gui_t *gui, char *sd_path, sdmmc_storage_t *storage, const emmc_part_t *part)
static int _dump_emummc_file_part(emmc_tool_gui_t *gui, char *sd_path, sdmmc_storage_t *storage, emmc_part_t *part)
{
static const u32 FAT32_FILESIZE_LIMIT = 0xFFFFFFFF;
static const u32 SECTORS_TO_MIB_COEFF = 11;
@ -779,7 +779,7 @@ static int _emummc_raw_derive_bis_keys(emmc_tool_gui_t *gui, u32 resized_count)
// Generate BIS keys.
hos_bis_keygen();
u8 *cal0_buff = malloc(SZ_64K);
u8 *cal0_buf = malloc(SZ_64K);
// Read and decrypt CAL0 for validation of working BIS keys.
emmc_set_partition(EMMC_GPP);
@ -787,11 +787,11 @@ static int _emummc_raw_derive_bis_keys(emmc_tool_gui_t *gui, u32 resized_count)
emmc_gpt_parse(&gpt);
emmc_part_t *cal0_part = emmc_part_find(&gpt, "PRODINFO"); // check if null
nx_emmc_bis_init(cal0_part, false, 0);
nx_emmc_bis_read(0, 0x40, cal0_buff);
nx_emmc_bis_read(0, 0x40, cal0_buf);
nx_emmc_bis_end();
emmc_gpt_free(&gpt);
nx_emmc_cal0_t *cal0 = (nx_emmc_cal0_t *)cal0_buff;
nx_emmc_cal0_t *cal0 = (nx_emmc_cal0_t *)cal0_buf;
// Check keys validity.
if (memcmp(&cal0->magic, "CAL0", 4))
@ -803,7 +803,7 @@ static int _emummc_raw_derive_bis_keys(emmc_tool_gui_t *gui, u32 resized_count)
error = true;
}
free(cal0_buff);
free(cal0_buf);
if (error)
{

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2018-2025 CTCaer
* Copyright (c) 2018-2024 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
@ -38,7 +38,7 @@ extern volatile nyx_storage_t *nyx_str;
extern lv_res_t launch_payload(lv_obj_t *list);
static bool disp_init_done = false;
static bool do_auto_reload = false;
static bool do_reload = false;
lv_style_t hint_small_style;
lv_style_t hint_small_style_white;
@ -200,8 +200,8 @@ static void _save_fb_to_bmp()
if (get_tmr_ms() < timer)
return;
if (do_auto_reload)
goto exit;
if (do_reload)
return;
// Invalidate data.
bpmp_mmu_maintenance(BPMP_MMU_MAINT_INVALID_WAY, false);
@ -304,7 +304,6 @@ static void _save_fb_to_bmp()
manual_system_maintenance(true);
lv_mbox_start_auto_close(mbox, 4000);
exit:
// Set timer to 2s.
timer = get_tmr_ms() + 2000;
}
@ -695,7 +694,7 @@ lv_img_dsc_t *bmp_to_lvimg_obj(const char *path)
img_desc->header.always_zero = 0;
img_desc->header.w = bmpData.size_x;
img_desc->header.h = bmpData.size_y;
img_desc->header.cf = (bitmap[28] == 32) ? LV_IMG_CF_TRUE_COLOR_ALPHA : LV_IMG_CF_TRUE_COLOR; // Only LV_IMG_CF_TRUE_COLOR_ALPHA is actually allowed.
img_desc->header.cf = (bitmap[28] == 32) ? LV_IMG_CF_TRUE_COLOR_ALPHA : LV_IMG_CF_TRUE_COLOR;
img_desc->data_size = bmpData.size - bmpData.offset;
img_desc->data = (u8 *)offset_copy;
@ -816,7 +815,7 @@ bool nyx_emmc_check_battery_enough()
return true;
}
static void _nyx_sd_card_issues_warning(void *param)
static void _nyx_sd_card_issues(void *param)
{
lv_obj_t *dark_bg = lv_obj_create(lv_scr_act(), NULL);
lv_obj_set_style(dark_bg, &mbox_darken);
@ -827,7 +826,7 @@ static void _nyx_sd_card_issues_warning(void *param)
lv_mbox_set_recolor_text(mbox, true);
lv_mbox_set_text(mbox,
"#FF8000 SD Card Issues Warning#\n\n"
"#FF8000 SD Card Issues Check#\n\n"
"#FFDD00 The SD Card is initialized in 1-bit mode!#\n"
"#FFDD00 This might mean detached or broken connector!#\n\n"
"You might want to check\n#C7EA46 Console Info# -> #C7EA46 microSD#");
@ -867,7 +866,7 @@ void nyx_window_toggle_buttons(lv_obj_t *win, bool disable)
}
}
lv_res_t nyx_win_close_action_custom(lv_obj_t * btn)
lv_res_t lv_win_close_action_custom(lv_obj_t * btn)
{
close_btn = NULL;
@ -887,7 +886,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_obj_set_size(win, LV_HOR_RES, LV_VER_RES);
close_btn = lv_win_add_btn(win, NULL, SYMBOL_CLOSE" Close", nyx_win_close_action_custom);
close_btn = lv_win_add_btn(win, NULL, SYMBOL_CLOSE" Close", lv_win_close_action_custom);
return win;
}
@ -929,27 +928,8 @@ static void _launch_hos(u8 autoboot, u8 autoboot_list)
(*main_ptr)();
}
void reload_nyx(lv_obj_t *obj, bool force)
void reload_nyx()
{
if (!force)
{
sd_mount();
// Check that Nyx still exists.
if (f_stat("bootloader/sys/nyx.bin", NULL))
{
sd_unmount();
// Remove lvgl object in case of being invoked from a window.
if (obj)
lv_obj_del(obj);
do_auto_reload = false;
return;
}
}
b_cfg->boot_cfg = BOOT_CFG_AUTOBOOT_EN;
b_cfg->autoboot = 0;
b_cfg->autoboot_list = 0;
@ -967,7 +947,7 @@ void reload_nyx(lv_obj_t *obj, bool force)
static lv_res_t reload_action(lv_obj_t *btns, const char *txt)
{
if (!lv_btnm_get_pressed(btns))
reload_nyx(NULL, false);
reload_nyx();
return mbox_action(btns, txt);
}
@ -989,7 +969,7 @@ static lv_res_t _removed_sd_action(lv_obj_t *btns, const char *txt)
break;
case 2:
sd_end();
do_auto_reload = false;
do_reload = false;
break;
}
@ -998,14 +978,12 @@ static lv_res_t _removed_sd_action(lv_obj_t *btns, const char *txt)
static void _check_sd_card_removed(void *params)
{
static lv_obj_t *dark_bg = NULL;
// The following checks if SDMMC_1 is initialized.
// If yes and card was removed, shows a message box,
// that will reload Nyx, when the card is inserted again.
if (!do_auto_reload && sd_get_card_removed())
if (!do_reload && sd_get_card_removed())
{
dark_bg = lv_obj_create(lv_scr_act(), NULL);
lv_obj_t *dark_bg = lv_obj_create(lv_scr_act(), NULL);
lv_obj_set_style(dark_bg, &mbox_darken);
lv_obj_set_size(dark_bg, LV_HOR_RES, LV_VER_RES);
@ -1021,16 +999,16 @@ static void _check_sd_card_removed(void *params)
lv_obj_align(mbox, NULL, LV_ALIGN_CENTER, 0, 0);
lv_obj_set_top(mbox, true);
do_auto_reload = true;
do_reload = true;
}
// If in reload state and card was inserted, reload nyx.
if (do_auto_reload && !sd_get_card_removed())
reload_nyx(dark_bg, false);
if (do_reload && !sd_get_card_removed())
reload_nyx();
}
lv_task_t *task_emmc_errors;
static void _nyx_emmc_issues_warning(void *params)
static void _nyx_emmc_issues(void *params)
{
if (emmc_get_mode() < EMMC_MMC_HS400)
{
@ -1046,8 +1024,8 @@ static void _nyx_emmc_issues_warning(void *params)
lv_mbox_set_recolor_text(mbox, true);
lv_mbox_set_text(mbox,
"#FF8000 eMMC Issues Warning#\n\n"
"#FFDD00 Your eMMC is initialized in a slower mode!#\n"
"#FF8000 eMMC Issues Check#\n\n"
"#FFDD00 Your eMMC is initialized in slower mode!#\n"
"#FFDD00 This might mean hardware issues!#\n\n"
"You might want to check\n#C7EA46 Console Info# -> #C7EA46 eMMC#");
@ -1254,9 +1232,9 @@ static void _create_tab_about(lv_theme_t * th, lv_obj_t * parent)
lv_label_set_recolor(lbl_credits, true);
lv_label_set_static_text(lbl_credits,
"#C7EA46 hekate# (c) 2018, #C7EA46 naehrwert#, #C7EA46 st4rk#\n"
" (c) 2018-2025, #C7EA46 CTCaer#\n"
" (c) 2018-2024, #C7EA46 CTCaer#\n"
"\n"
"#C7EA46 Nyx# (c) 2019-2025, #C7EA46 CTCaer#\n"
"#C7EA46 Nyx# (c) 2019-2024, #C7EA46 CTCaer#\n"
"\n"
"Thanks to: #00CCFF derrek, nedwill, plutoo, #\n"
" #00CCFF shuffle2, smea, thexyz, yellows8 #\n"
@ -1416,7 +1394,7 @@ static lv_res_t _create_mbox_payloads(lv_obj_t *btn)
goto out_end;
}
dirlist_t *filelist = dirlist("bootloader/payloads", NULL, false, false);
char *filelist = dirlist("bootloader/payloads", NULL, false, false);
sd_unmount();
u32 i = 0;
@ -1424,9 +1402,9 @@ static lv_res_t _create_mbox_payloads(lv_obj_t *btn)
{
while (true)
{
if (!filelist->name[i])
if (!filelist[i * 256])
break;
lv_list_add(list, NULL, filelist->name[i], launch_payload);
lv_list_add(list, NULL, &filelist[i * 256], launch_payload);
i++;
}
free(filelist);
@ -1462,15 +1440,15 @@ static lv_res_t _launch_more_cfg_action(lv_obj_t *btn)
static lv_res_t _win_launch_close_action(lv_obj_t * btn)
{
// Cleanup icons.
for (u32 i = 0; i < (n_cfg.entries_5_col ? 10 : 8); i++)
for (u32 i = 0; i < 8; i++)
{
lv_obj_t *btns = launch_ctxt.btn[i];
lv_btn_ext_t *ext = lv_obj_get_ext_attr(btns);
lv_obj_t *btn = launch_ctxt.btn[i];
lv_btn_ext_t *ext = lv_obj_get_ext_attr(btn);
if (ext->idx)
{
// This gets latest object, which is the button overlay. So iterate 2 times.
lv_obj_t * img = lv_obj_get_child(btns, NULL);
img = lv_obj_get_child(btns, img);
lv_obj_t * img = lv_obj_get_child(btn, NULL);
img = lv_obj_get_child(btn, img);
lv_img_dsc_t *src = (lv_img_dsc_t *)lv_img_get_src(img);
@ -1854,7 +1832,7 @@ ini_parsing:
}
// Add button mask/radius and align icon.
lv_obj_t *btns = lv_btn_create(launch_ctxt.btn[curr_btn_idx], NULL);
lv_obj_t *btn = lv_btn_create(launch_ctxt.btn[curr_btn_idx], NULL);
u32 btn_width = 200;
u32 btn_height = 200;
if (img_noborder)
@ -1870,25 +1848,25 @@ ini_parsing:
lv_btn_set_style(launch_ctxt.btn[curr_btn_idx], LV_BTN_STYLE_REL, &btn_home_noborder_rel);
lv_btn_set_style(launch_ctxt.btn[curr_btn_idx], LV_BTN_STYLE_PR, &btn_home_noborder_rel);
}
lv_obj_set_size(btns, btn_width, btn_height);
lv_btn_set_style(btns, LV_BTN_STYLE_REL, img_noborder ? &btn_home_noborder_rel : &btn_home_transp_rel);
lv_btn_set_style(btns, LV_BTN_STYLE_PR, &btn_home_transp_pr);
lv_obj_set_size(btn, btn_width, btn_height);
lv_btn_set_style(btn, LV_BTN_STYLE_REL, img_noborder ? &btn_home_noborder_rel : &btn_home_transp_rel);
lv_btn_set_style(btn, LV_BTN_STYLE_PR, &btn_home_transp_pr);
if (img)
lv_obj_align(img, NULL, LV_ALIGN_CENTER, 0, 0);
if (img_noborder)
lv_obj_align(btns, NULL, LV_ALIGN_CENTER, 0, 0);
lv_obj_align(btn, NULL, LV_ALIGN_CENTER, 0, 0);
// Set autoboot index.
ext = lv_obj_get_ext_attr(btns);
ext = lv_obj_get_ext_attr(btn);
ext->idx = entry_idx;
ext = lv_obj_get_ext_attr(launch_ctxt.btn[curr_btn_idx]); // Redundancy.
ext->idx = entry_idx;
// Set action.
if (!more_cfg)
lv_btn_set_action(btns, LV_BTN_ACTION_CLICK, _launch_action);
lv_btn_set_action(btn, LV_BTN_ACTION_CLICK, _launch_action);
else
lv_btn_set_action(btns, LV_BTN_ACTION_CLICK, _launch_more_cfg_action);
lv_btn_set_action(btn, LV_BTN_ACTION_CLICK, _launch_more_cfg_action);
// Set button's label text.
lv_label_set_text(launch_ctxt.label[curr_btn_idx], ini_sec->name);
@ -2101,7 +2079,6 @@ static void _create_status_bar(lv_theme_t * th)
{
static lv_obj_t *status_bar_bg;
status_bar_bg = lv_cont_create(lv_layer_top(), NULL);
status_bar.bar_bg = status_bar_bg;
static lv_style_t status_bar_style;
lv_style_copy(&status_bar_style, &lv_style_plain_color);
@ -2154,9 +2131,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_align(btn_mid, NULL, LV_ALIGN_CENTER, 0, 0);
status_bar.mid = btn_mid;
lv_obj_set_opa_scale(btn_mid, LV_OPA_0);
lv_obj_set_opa_scale_enable(btn_mid, true);
lv_obj_set_click(btn_mid, false);
lv_obj_set_opa_scale(status_bar.mid, LV_OPA_0);
lv_obj_set_opa_scale_enable(status_bar.mid, true);
lv_obj_set_click(status_bar.mid, false);
lv_btn_set_action(btn_mid, LV_BTN_ACTION_CLICK, _save_options_action);
}
@ -2377,7 +2354,7 @@ static void _nyx_main_menu(lv_theme_t * th)
lv_task_create(_check_sd_card_removed, 2000, LV_TASK_PRIO_LOWEST, NULL);
task_emmc_errors = lv_task_create(_nyx_emmc_issues_warning, 2000, LV_TASK_PRIO_LOWEST, NULL);
task_emmc_errors = lv_task_create(_nyx_emmc_issues, 2000, LV_TASK_PRIO_LOWEST, NULL);
lv_task_ready(task_emmc_errors);
// Create top level global line separators.
@ -2477,19 +2454,16 @@ void nyx_load_and_run()
// Check if sd card issues.
if (sd_get_mode() == SD_1BIT_HS25)
{
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_t *task_run_sd_errors = lv_task_create(_nyx_sd_card_issues, LV_TASK_ONESHOT, LV_TASK_PRIO_LOWEST, NULL);
lv_task_once(task_run_sd_errors);
}
// Gui loop.
if (h_cfg.t210b01)
{
// Minerva not supported on T210B01 yet. Slight power saving via spinlock.
// Minerva not supported on T210B01 yet. No power saving.
while (true)
{
lv_task_handler();
usleep(400);
}
}
else
{

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2018-2025 CTCaer
* Copyright (c) 2018-2019 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,
@ -36,7 +36,6 @@ typedef struct _emmc_tool_gui_t
typedef struct _gui_status_bar_ctx
{
lv_obj_t *bar_bg;
lv_obj_t *mid;
lv_obj_t *time_temp;
lv_obj_t *temp_symbol;
@ -73,7 +72,6 @@ void reload_nyx();
lv_img_dsc_t *bmp_to_lvimg_obj(const char *path);
lv_res_t mbox_action(lv_obj_t * btns, const char * txt);
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);
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);

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2019-2024 CTCaer
* Copyright (c) 2019-2022 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,
@ -42,7 +42,8 @@ static lv_res_t (*emummc_tools)(lv_obj_t *btn);
static lv_res_t _action_emummc_window_close(lv_obj_t *btn)
{
nyx_win_close_action_custom(btn);
lv_win_close_action(btn);
close_btn = NULL;
// Delete and relaunch main emuMMC window.
lv_obj_del(emummc_manage_window);
@ -748,7 +749,7 @@ static lv_res_t _create_emummc_migrate_action(lv_obj_t * btns, const char * txt)
typedef struct _emummc_images_t
{
dirlist_t *dirlist;
char *dirlist;
u32 part_sector[3];
u32 part_type[3];
u32 part_end[3];
@ -1008,9 +1009,9 @@ static lv_res_t _create_change_emummc_window(lv_obj_t *btn_caller)
FIL fp;
// Check for sd raw partitions, based on the folders in /emuMMC.
while (emummc_img->dirlist->name[emummc_idx])
while (emummc_img->dirlist[emummc_idx * 256])
{
s_printf(path, "emuMMC/%s/raw_based", emummc_img->dirlist->name[emummc_idx]);
s_printf(path, "emuMMC/%s/raw_based", &emummc_img->dirlist[emummc_idx * 256]);
if (!f_stat(path, NULL))
{
@ -1023,21 +1024,21 @@ static lv_res_t _create_change_emummc_window(lv_obj_t *btn_caller)
if ((curr_list_sector == 2) || (emummc_img->part_sector[0] && curr_list_sector >= emummc_img->part_sector[0] &&
curr_list_sector < emummc_img->part_end[0] && emummc_img->part_type[0] != 0x83))
{
s_printf(&emummc_img->part_path[0], "emuMMC/%s", emummc_img->dirlist->name[emummc_idx]);
s_printf(&emummc_img->part_path[0], "emuMMC/%s", &emummc_img->dirlist[emummc_idx * 256]);
emummc_img->part_sector[0] = curr_list_sector;
emummc_img->part_end[0] = 0;
}
else if (emummc_img->part_sector[1] && curr_list_sector >= emummc_img->part_sector[1] &&
curr_list_sector < emummc_img->part_end[1] && emummc_img->part_type[1] != 0x83)
{
s_printf(&emummc_img->part_path[1 * 128], "emuMMC/%s", emummc_img->dirlist->name[emummc_idx]);
s_printf(&emummc_img->part_path[1 * 128], "emuMMC/%s", &emummc_img->dirlist[emummc_idx * 256]);
emummc_img->part_sector[1] = curr_list_sector;
emummc_img->part_end[1] = 0;
}
else if (emummc_img->part_sector[2] && curr_list_sector >= emummc_img->part_sector[2] &&
curr_list_sector < emummc_img->part_end[2] && emummc_img->part_type[2] != 0x83)
{
s_printf(&emummc_img->part_path[2 * 128], "emuMMC/%s", emummc_img->dirlist->name[emummc_idx]);
s_printf(&emummc_img->part_path[2 * 128], "emuMMC/%s", &emummc_img->dirlist[emummc_idx * 256]);
emummc_img->part_sector[2] = curr_list_sector;
emummc_img->part_end[2] = 0;
}
@ -1049,19 +1050,19 @@ static lv_res_t _create_change_emummc_window(lv_obj_t *btn_caller)
u32 file_based_idx = 0;
// Sanitize the directory list with sd file based ones.
while (emummc_img->dirlist->name[emummc_idx])
while (emummc_img->dirlist[emummc_idx * 256])
{
s_printf(path, "emuMMC/%s/file_based", emummc_img->dirlist->name[emummc_idx]);
s_printf(path, "emuMMC/%s/file_based", &emummc_img->dirlist[emummc_idx * 256]);
if (!f_stat(path, NULL))
{
char *tmp = emummc_img->dirlist->name[emummc_idx];
memcpy(emummc_img->dirlist->name[file_based_idx], tmp, strlen(tmp) + 1);
char *tmp = &emummc_img->dirlist[emummc_idx * 256];
memcpy(&emummc_img->dirlist[file_based_idx * 256], tmp, strlen(tmp) + 1);
file_based_idx++;
}
emummc_idx++;
}
emummc_img->dirlist->name[file_based_idx] = NULL;
emummc_img->dirlist[file_based_idx * 256] = 0;
out0:;
static lv_style_t h_style;
@ -1178,9 +1179,9 @@ out0:;
emummc_idx = 0;
// Add file based to the list.
while (emummc_img->dirlist->name[emummc_idx])
while (emummc_img->dirlist[emummc_idx * 256])
{
s_printf(path, "emuMMC/%s", emummc_img->dirlist->name[emummc_idx]);
s_printf(path, "emuMMC/%s", &emummc_img->dirlist[emummc_idx * 256]);
lv_list_add(list_sd_based, NULL, path, _save_file_emummc_cfg_action);

View file

@ -1,6 +1,6 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2025 CTCaer
* Copyright (c) 2018-2024 CTCaer
* Copyright (c) 2018 balika011
*
* This program is free software; you can redistribute it and/or modify it
@ -24,8 +24,6 @@
#include "../hos/pkg1.h"
#include <libs/fatfs/ff.h>
#include <stdlib.h>
#define SECTORS_TO_MIB_COEFF 11
extern hekate_config h_cfg;
@ -353,21 +351,9 @@ out:
return LV_RES_OK;
}
static lv_obj_t *hw_info_ver = NULL;
static lv_res_t _action_win_hw_info_status_close(lv_obj_t *btn)
static lv_res_t _create_window_fuses_info_status(lv_obj_t *btn)
{
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_obj_t *win = nyx_create_standard_window(SYMBOL_CHIP" HW & Fuses Info");
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);
@ -379,14 +365,6 @@ static lv_res_t _create_window_hw_info_status(lv_obj_t *btn)
lv_label_set_recolor(lb_desc, true);
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,
"#FF8000 SoC:#\n"
"#FF8000 SKU:#\n"
@ -609,13 +587,7 @@ static lv_res_t _create_window_hw_info_status(lv_obj_t *btn)
strcpy(fuses_hos_version, "16.0.0 - 16.1.0");
break;
case 19:
strcpy(fuses_hos_version, "17.0.0 - 18.1.0");
break;
case 20:
strcpy(fuses_hos_version, "19.0.0 - 19.0.1");
break;
case 21:
strcpy(fuses_hos_version, "20.0.0+");
strcpy(fuses_hos_version, "17.0.0+");
break;
case 255:
strcpy(fuses_hos_version, "#FFD000 Overburnt#");
@ -688,7 +660,7 @@ static lv_res_t _create_window_hw_info_status(lv_obj_t *btn)
u32 ranks = EMC(EMC_ADR_CFG) + 1;
u32 channels = (EMC(EMC_FBIO_CFG7) >> 1) & 3;
channels = (channels & 1) + ((channels & 2) >> 1);
s_printf(txt_buf, "#00DDFF %s SDRAM ##FF8000 (Module 0 | 1):#\n#FF8000 Vendor:# ", h_cfg.t210b01 ? "LPDDR4X" : "LPDDR4");
s_printf(txt_buf, "#00DDFF %s SDRAM ##FF8000 (Ch 0 | Ch 1):#\n#FF8000 Vendor:# ", h_cfg.t210b01 ? "LPDDR4X" : "LPDDR4");
switch (ram_vendor.chip0.rank0_ch0)
{
case 1:
@ -760,76 +732,49 @@ static lv_res_t _create_window_hw_info_status(lv_obj_t *btn)
s_printf(txt_buf + strlen(txt_buf), "#FF8000 Unknown# (%d)", ram_vendor.chip1.rank0_ch0);
break;
}
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 ? "#" : "");
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);
switch ((ram_density.chip0.rank0_ch0 & 0x3C) >> 2)
{
case 2:
strcat(txt_buf, "512MB");
strcat(txt_buf, " x 512MB");
break;
case 3:
strcat(txt_buf, "768MB");
strcat(txt_buf, " x 768MB");
break;
case 4:
strcat(txt_buf, "1GB");
strcat(txt_buf, " x 1GB");
break;
case 5:
strcat(txt_buf, "1.5GB");
strcat(txt_buf, " x 1.5GB");
break;
case 6:
strcat(txt_buf, "2GB");
strcat(txt_buf, " x 2GB");
break;
default:
s_printf(txt_buf + strlen(txt_buf), "Unk (%d)", (ram_density.chip0.rank0_ch0 & 0x3C) >> 2);
s_printf(txt_buf + strlen(txt_buf), " x Unk (%d)", (ram_density.chip0.rank0_ch0 & 0x3C) >> 2);
break;
}
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 ? "#" : "");
s_printf(txt_buf + strlen(txt_buf), " #FF8000 |# %d", ranks * channels);
switch ((ram_density.chip1.rank0_ch0 & 0x3C) >> 2)
{
case 2:
strcat(txt_buf, "512MB");
strcat(txt_buf, " x 512MB");
break;
case 3:
strcat(txt_buf, "768MB");
strcat(txt_buf, " x 768MB");
break;
case 4:
strcat(txt_buf, "1GB");
strcat(txt_buf, " x 1GB");
break;
case 5:
strcat(txt_buf, "1.5GB");
strcat(txt_buf, " x 1.5GB");
break;
case 6:
strcat(txt_buf, "2GB");
strcat(txt_buf, " x 2GB");
break;
default:
s_printf(txt_buf + strlen(txt_buf), "Unk (%d)", (ram_density.chip1.rank0_ch0 & 0x3C) >> 2);
s_printf(txt_buf + strlen(txt_buf), " x Unk (%d)", (ram_density.chip1.rank0_ch0 & 0x3C) >> 2);
break;
}
strcat(txt_buf, "\n\n");
@ -992,13 +937,13 @@ static lv_res_t _create_window_hw_info_status(lv_obj_t *btn)
if (touch_panel)
panel_ic_paired = touch_panel->idx == 0; // NISSHA NFT-K12D.
break;
// case 0x98000004: // New 6.2" panel?
// case 0x50000001:
// case 0x50000002:
// strcat(txt_buf, "FST2 UNK");
// if (touch_panel)
// panel_ic_paired = touch_panel->idx == 0;
// break;
case 0x98000004: // New 6.2" panel?
case 0x50000001:
case 0x50000002:
strcat(txt_buf, "FST2 UNK");
if (touch_panel)
panel_ic_paired = touch_panel->idx == 0;
break;
case 0x001A0300:
case 0x32000102:
strcat(txt_buf, "4CD60D/2");
@ -1026,7 +971,7 @@ static lv_res_t _create_window_hw_info_status(lv_obj_t *btn)
panel_ic_paired = touch_panel->idx == 4; // Samsung BH2109.
break;
default:
strcat(txt_buf, "#FF8000 Contact me#");
strcat(txt_buf, "#FF8000 Unknown#");
break;
}
@ -1051,6 +996,9 @@ static lv_res_t _create_window_hw_info_status(lv_obj_t *btn)
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);
if (!btn)
_create_mbox_cal0(NULL);
return LV_RES_OK;
}
@ -1348,11 +1296,12 @@ static lv_res_t _create_mbox_benchmark(bool sd_bench)
static const char * mbox_btn_map[] = { "\251", "\222OK", "\251", "" };
lv_obj_t * mbox = lv_mbox_create(dark_bg, NULL);
lv_mbox_set_recolor_text(mbox, true);
lv_obj_set_width(mbox, LV_HOR_RES * 3 / 7);
lv_obj_set_width(mbox, LV_HOR_RES / 7 * 4);
char *txt_buf = (char *)malloc(SZ_16K);
s_printf(txt_buf, "#FF8000 %s Benchmark#\n[Raw Reads] Abort: VOL- & VOL+", sd_bench ? "SD Card" : "eMMC");
s_printf(txt_buf, "#FF8000 %s Benchmark#\n[Raw Reads] Abort: VOL- & VOL+",
sd_bench ? "SD Card" : "eMMC");
lv_mbox_set_text(mbox, txt_buf);
txt_buf[0] = 0;
@ -1401,60 +1350,30 @@ static lv_res_t _create_mbox_benchmark(bool sd_bench)
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;
u32 iters = 3;
u32 offset_chunk_start = ALIGN_DOWN(storage->sec_cnt / 3, sct_blk_seq); // Align to block.
u32 offset_chunk_start = ALIGN_DOWN(storage->sec_cnt / 3, 0x8000); // Align to 16MB.
if (storage->sec_cnt < 0xC00000)
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++)
{
u32 pct = 0;
u32 prevPct = 200;
u32 timer = 0;
u32 lba_curr = 0;
u32 sector_off = offset_chunk_start * iter_curr;
u32 sector_num = sct_blk_seq;
u32 data_remaining = sct_rem_seq;
u32 sector = offset_chunk_start * iter_curr;
u32 sector_num = 0x8000; // 16MB chunks.
u32 data_remaining = 0x200000; // 1GB.
s_printf(txt_buf + strlen(txt_buf), "#C7EA46 %d/3# - Sector Offset #C7EA46 %08X#:\n", iter_curr + 1, sector_off);
s_printf(txt_buf + strlen(txt_buf), "#C7EA46 %d/3# - Sector Offset #C7EA46 %08X#:\n", iter_curr + 1, sector);
u32 render_min_ms = 66;
u32 render_timer = get_tmr_ms() + render_min_ms;
while (data_remaining)
{
u32 time_taken = get_tmr_us();
error = !sdmmc_storage_read(storage, sector_off + lba_curr, sector_num, (u8 *)MIXD_BUF_ALIGNED);
error = !sdmmc_storage_read(storage, sector + lba_curr, sector_num, (u8 *)MIXD_BUF_ALIGNED);
time_taken = get_tmr_us() - time_taken;
timer += time_taken;
@ -1462,7 +1381,7 @@ static lv_res_t _create_mbox_benchmark(bool sd_bench)
data_remaining -= sector_num;
lba_curr += sector_num;
pct = (lba_curr * 100) / sct_rem_seq;
pct = (lba_curr * 100) / 0x200000;
if (pct != prevPct && render_timer < get_tmr_ms())
{
lv_bar_set_value(bar, pct);
@ -1480,10 +1399,10 @@ static lv_res_t _create_mbox_benchmark(bool sd_bench)
}
lv_bar_set_value(bar, 100);
// Calculate rate for transfer.
u32 rate_1k = (u64)size_bytes_seq * 1000 * 1000 * 1000 / mb_div / timer;
s_printf(txt_buf + strlen(txt_buf), " SEQ 16MB - Rate: #C7EA46 %3d.%02d %s#",
rate_1k / 1000, (rate_1k % 1000) / 10, mbs_text);
u32 rate_1k = ((u64)1024 * 1000 * 1000 * 1000) / timer;
s_printf(txt_buf + strlen(txt_buf),
" Sequential 16MiB - Rate: #C7EA46 %3d.%02d MiB/s#\n",
rate_1k / 1000, (rate_1k % 1000) / 10);
lv_label_set_text(lbl_status, txt_buf);
lv_obj_align(lbl_status, NULL, LV_ALIGN_CENTER, 0, 0);
lv_obj_align(mbox, NULL, LV_ALIGN_CENTER, 0, 0);
@ -1493,25 +1412,22 @@ static lv_res_t _create_mbox_benchmark(bool sd_bench)
prevPct = 200;
timer = 0;
lba_curr = 0;
sector_num = sct_blk_4kb;
data_remaining = sct_rem_4kb;
sector_num = 8; // 4KB chunks.
data_remaining = 0x100000; // 512MB.
u32 loop_idx = 0;
render_timer = get_tmr_ms() + render_min_ms;
while (data_remaining)
{
u32 time_taken = get_tmr_us();
error = !sdmmc_storage_read(storage, sector_off + lba_curr, sector_num, (u8 *)MIXD_BUF_ALIGNED);
error = !sdmmc_storage_read(storage, sector + lba_curr, sector_num, (u8 *)MIXD_BUF_ALIGNED);
time_taken = get_tmr_us() - time_taken;
timer += time_taken;
times_taken_4k[loop_idx++] = time_taken;
manual_system_maintenance(false);
data_remaining -= sector_num;
lba_curr += sector_num;
pct = (lba_curr * 100) / sct_rem_4kb;
pct = (lba_curr * 100) / 0x100000;
if (pct != prevPct && render_timer < get_tmr_ms())
{
lv_bar_set_value(bar, pct);
@ -1529,64 +1445,49 @@ static lv_res_t _create_mbox_benchmark(bool sd_bench)
}
lv_bar_set_value(bar, 100);
qsort(times_taken_4k, loop_idx, sizeof(u32), qsort_compare_int); // Use int for faster compare. Value can't exceed 2s.
u32 pct95 = 0;
for (u32 i = 0; i < loop_idx * 95 / 100; i++)
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);
rate_1k = ((u64)512 * 1000 * 1000 * 1000) / timer;
u32 iops_1k = ((u64)512 * 1024 * 1000 * 1000 * 1000) / (4096 / 1024) / timer / 1000;
s_printf(txt_buf + strlen(txt_buf),
" Sequential 4KiB - Rate: #C7EA46 %3d.%02d MiB/s#, IOPS: #C7EA46 %4d#\n",
rate_1k / 1000, (rate_1k % 1000) / 10, iops_1k);
lv_label_set_text(lbl_status, txt_buf);
lv_obj_align(lbl_status, NULL, LV_ALIGN_CENTER, 0, 0);
lv_obj_align(mbox, NULL, LV_ALIGN_CENTER, 0, 0);
manual_system_maintenance(true);
u32 lba_idx = 0;
u32 *random_offsets = malloc(0x20000 * sizeof(u32));
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.
while (!se_gen_prng128(random_numbers))
;
// Clamp offsets to 256MB range.
random_offsets[i + 0] = random_numbers[0] % sct_rem_4kb;
random_offsets[i + 1] = random_numbers[1] % sct_rem_4kb;
random_offsets[i + 2] = random_numbers[2] % sct_rem_4kb;
random_offsets[i + 3] = random_numbers[3] % sct_rem_4kb;
// Clamp offsets to 512MB range.
random_offsets[i + 0] = random_numbers[0] % 0x100000;
random_offsets[i + 1] = random_numbers[1] % 0x100000;
random_offsets[i + 2] = random_numbers[2] % 0x100000;
random_offsets[i + 3] = random_numbers[3] % 0x100000;
}
pct = 0;
prevPct = 200;
timer = 0;
data_remaining = sct_rem_4kb;
data_remaining = 0x100000; // 512MB.
loop_idx = 0;
render_timer = get_tmr_ms() + render_min_ms;
while (data_remaining)
{
u32 time_taken = get_tmr_us();
error = !sdmmc_storage_read(storage, sector_off + random_offsets[lba_idx], sector_num, (u8 *)MIXD_BUF_ALIGNED);
error = !sdmmc_storage_read(storage, sector + random_offsets[lba_idx], sector_num, (u8 *)MIXD_BUF_ALIGNED);
time_taken = get_tmr_us() - time_taken;
timer += time_taken;
times_taken_4k[loop_idx++] = time_taken;
manual_system_maintenance(false);
data_remaining -= sector_num;
lba_idx++;
pct = (lba_idx * 100) / rnd_off_cnt;
pct = (lba_idx * 100) / 0x20000;
if (pct != prevPct && render_timer < get_tmr_ms())
{
lv_bar_set_value(bar, pct);
@ -1600,39 +1501,29 @@ static lv_res_t _create_mbox_benchmark(bool sd_bench)
}
if (error)
{
free(random_offsets);
goto error;
}
}
lv_bar_set_value(bar, 100);
qsort(times_taken_4k, loop_idx, sizeof(u32), qsort_compare_int); // Use int for faster compare. Value can't exceed 2s.
pct95 = 0;
for (u32 i = 0; i < loop_idx * 95 / 100; i++)
pct95 += times_taken_4k[i];
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);
// Calculate rate and IOPS for 512MB transfer.
rate_1k = ((u64)512 * 1000 * 1000 * 1000) / timer;
iops_1k = ((u64)512 * 1024 * 1000 * 1000 * 1000) / (4096 / 1024) / timer / 1000;
s_printf(txt_buf + strlen(txt_buf),
" Random 4KiB - Rate: #C7EA46 %3d.%02d MiB/s#, IOPS: #C7EA46 %4d#\n",
rate_1k / 1000, (rate_1k % 1000) / 10, iops_1k);
if (iter_curr == iters - 1)
txt_buf[strlen(txt_buf) - 1] = 0; // Cut off last new line.
txt_buf[strlen(txt_buf) - 1] = 0; // Cut off last line change.
lv_label_set_text(lbl_status, txt_buf);
lv_obj_align(lbl_status, NULL, LV_ALIGN_CENTER, 0, 0);
lv_obj_align(mbox, NULL, LV_ALIGN_CENTER, 0, 0);
manual_system_maintenance(true);
free(random_offsets);
}
error:
free(random_offsets);
free(times_taken_4k);
if (error)
{
if (error == -1)
@ -1659,8 +1550,6 @@ error:
emmc_end();
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);
lv_mbox_add_btns(mbox, mbox_btn_map, mbox_action); // Important. After set_text.
@ -1867,7 +1756,7 @@ static lv_res_t _create_window_emmc_info_status(lv_obj_t *btn)
emmc_gpt_parse(&gpt);
u32 idx = 0;
int lines_left = 20;
u32 lines_left = 20;
s_printf(txt_buf + strlen(txt_buf), "#FFBA00 Idx Name Size Offset Sectors#\n");
LIST_FOREACH_ENTRY(emmc_part_t, part, &gpt, link)
{
@ -1919,8 +1808,8 @@ out_error:
lv_mbox_set_recolor_text(mbox, true);
s_printf(txt_buf,
"#FF8000 eMMC Issues Warning#\n\n"
"#FFDD00 Your eMMC is initialized in a slower mode,#\n"
"#FF8000 eMMC Issues Check#\n\n"
"#FFDD00 Your eMMC is initialized in slower mode,#\n"
"#FFDD00 or init/read/write errors occurred!#\n"
"#FFDD00 This might mean hardware issues!#\n\n"
"#00DDFF Bus Speed:# %d MB/s\n\n"
@ -1952,7 +1841,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_obj_t *desc = lv_cont_create(win, NULL);
lv_obj_set_size(desc, LV_HOR_RES / 2 / 6 * 2, LV_VER_RES - (LV_DPI * 11 / 8) * 5 / 2);
lv_obj_set_size(desc, LV_HOR_RES / 2 / 5 * 2, LV_VER_RES - (LV_DPI * 11 / 8) * 5 / 2);
lv_obj_t * lb_desc = lv_label_create(desc, NULL);
lv_label_set_long_mode(lb_desc, LV_LABEL_LONG_BREAK);
@ -1973,7 +1862,7 @@ static lv_res_t _create_window_sdcard_info_status(lv_obj_t *btn)
}
lv_label_set_text(lb_desc,
"#00DDFF Card ID:#\n"
"#00DDFF Card IDentification:#\n"
"Vendor ID:\n"
"Model:\n"
"OEM ID:\n"
@ -1982,11 +1871,11 @@ static lv_res_t _create_window_sdcard_info_status(lv_obj_t *btn)
"S/N:\n"
"Month/Year:\n\n"
"Max Power:\n"
"Initial bus:"
"Bootloader bus:"
);
lv_obj_t *val = lv_cont_create(win, NULL);
lv_obj_set_size(val, LV_HOR_RES / 12 * 3, LV_VER_RES - (LV_DPI * 11 / 8) * 5 / 2);
lv_obj_set_size(val, LV_HOR_RES / 9 * 2, LV_VER_RES - (LV_DPI * 11 / 8) * 5 / 2);
lv_obj_t * lb_val = lv_label_create(val, lb_desc);
@ -2093,7 +1982,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.
u32 max_power_nominal = sd_storage.max_power > 400 ? 400 : sd_storage.max_power;
u32 card_power_limit_nominal = sd_storage.card_power_limit > 400 ? 400 : sd_storage.card_power_limit;
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,
@ -2102,7 +1991,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.hwrev, sd_storage.cid.fwrev, sd_storage.cid.serial,
sd_storage.cid.month, sd_storage.cid.year,
max_power_nominal * 3600 / 1000, sd_storage.max_power);
card_power_limit_nominal * 3600 / 1000, sd_storage.card_power_limit);
switch (nyx_str->info.sd_init)
{
@ -2128,7 +2017,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_t *desc2 = lv_cont_create(win, NULL);
lv_obj_set_size(desc2, LV_HOR_RES / 2 / 11 * 5, LV_VER_RES - (LV_DPI * 11 / 8) * 5 / 2);
lv_obj_set_size(desc2, LV_HOR_RES / 2 / 4 * 2, LV_VER_RES - (LV_DPI * 11 / 8) * 5 / 2);
lv_obj_t * lb_desc2 = lv_label_create(desc2, lb_desc);
@ -2145,10 +2034,10 @@ static lv_res_t _create_window_sdcard_info_status(lv_obj_t *btn)
"Write Protect:"
);
lv_obj_set_width(lb_desc2, lv_obj_get_width(desc2));
lv_obj_align(desc2, val, LV_ALIGN_OUT_RIGHT_MID, LV_DPI / 5 * 3, 0);
lv_obj_align(desc2, val, LV_ALIGN_OUT_RIGHT_MID, LV_DPI / 2, 0);
lv_obj_t *val2 = lv_cont_create(win, NULL);
lv_obj_set_size(val2, LV_HOR_RES / 4, LV_VER_RES - (LV_DPI * 11 / 8) * 5 / 2);
lv_obj_set_size(val2, LV_HOR_RES / 13 * 3, LV_VER_RES - (LV_DPI * 11 / 8) * 5 / 2);
lv_obj_t * lb_val2 = lv_label_create(val2, lb_desc);
@ -2192,64 +2081,15 @@ static lv_res_t _create_window_sdcard_info_status(lv_obj_t *btn)
else
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,
"#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\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,
"#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",
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.ssr.speed_class, uhs_au_size, uhs_au_mb ? "MiB)" : "KiB)",
sd_storage.ssr.uhs_grade, sd_storage.ssr.video_class, cpe ? cpe : "", sd_storage.ssr.app_class, cpe ? "#" : "",
bus_speed,
wp_info);
sd_storage.ssr.uhs_grade, sd_storage.ssr.video_class, sd_storage.ssr.app_class,
bus_speed, wp_info);
lv_label_set_text(lb_val2, txt_buf);
@ -2266,29 +2106,47 @@ 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_t * lb_desc3 = lv_label_create(desc3, lb_desc);
lv_label_set_text(lb_desc3, "#D4FF00 Acquiring info...#");
lv_label_set_text(lb_desc3, "#D4FF00 Acquiring FAT volume info...#");
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);
manual_system_maintenance(true);
lv_obj_set_size(desc3, LV_HOR_RES / 2 / 6 * 2, LV_VER_RES - (LV_DPI * 11 / 8) * 4);
f_getfree("", &sd_fs.free_clst, NULL);
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_t *val3 = lv_cont_create(win, NULL);
lv_obj_set_size(val3, LV_HOR_RES / 12 * 3, LV_VER_RES - (LV_DPI * 11 / 8) * 4);
lv_obj_set_size(val3, LV_HOR_RES / 13 * 3, LV_VER_RES - (LV_DPI * 11 / 8) * 4);
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_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_t * lb_desc4 = lv_label_create(desc4, lb_desc);
lv_label_set_text(lb_desc4, " ");
lv_label_set_text(lb_desc4, "#D4FF00 Acquiring FAT volume info...#");
lv_obj_set_width(lb_desc4, lv_obj_get_width(desc4));
lv_label_set_text(lb_desc4,
@ -2297,12 +2155,12 @@ static lv_res_t _create_window_sdcard_info_status(lv_obj_t *btn)
"Read/Write fails:\n"
"Read/Write errors:"
);
lv_obj_set_size(desc4, LV_HOR_RES / 2 / 11 * 5, LV_VER_RES - (LV_DPI * 11 / 8) * 4);
lv_obj_set_size(desc4, LV_HOR_RES / 2 / 5 * 2, LV_VER_RES - (LV_DPI * 11 / 8) * 4);
lv_obj_set_width(lb_desc4, lv_obj_get_width(desc4));
lv_obj_align(desc4, val3, LV_ALIGN_OUT_RIGHT_MID, LV_DPI / 5 * 3, 0);
lv_obj_align(desc4, val3, LV_ALIGN_OUT_RIGHT_MID, LV_DPI / 2, 0);
lv_obj_t *val4 = lv_cont_create(win, NULL);
lv_obj_set_size(val4, LV_HOR_RES / 4, LV_VER_RES - (LV_DPI * 11 / 8) * 4);
lv_obj_set_size(val4, LV_HOR_RES / 13 * 3, LV_VER_RES - (LV_DPI * 11 / 8) * 4);
lv_obj_t * lb_val4 = lv_label_create(val4, lb_desc);
@ -2315,31 +2173,7 @@ static lv_res_t _create_window_sdcard_info_status(lv_obj_t *btn)
lv_label_set_text(lb_val4, txt_buf);
lv_obj_set_width(lb_val4, lv_obj_get_width(val4));
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));
lv_obj_align(val4, desc4, LV_ALIGN_OUT_RIGHT_MID, LV_DPI / 2, 0);
free(txt_buf);
sd_unmount();
@ -2470,9 +2304,10 @@ static lv_res_t _create_window_battery_status(lv_obj_t *btn)
lv_label_set_static_text(lb_desc2,
"#00DDFF Battery Charger IC Info:#\n"
"Input voltage limit:\n"
"Input current limit:\n"
"System voltage limit:\n"
"Charge current limit:\n"
"Min voltage limit:\n"
"Fast charge current limit:\n"
"Charge voltage limit:\n"
"Charge status:\n"
"Temperature status:\n\n"
@ -2490,9 +2325,12 @@ static lv_res_t _create_window_battery_status(lv_obj_t *btn)
lv_obj_t * lb_val2 = lv_label_create(val2, lb_desc);
// Charger IC info.
bq24193_get_property(BQ24193_InputVoltageLimit, &value);
s_printf(txt_buf, "\n%d mV\n", value);
int iinlim = 0;
bq24193_get_property(BQ24193_InputCurrentLimit, &iinlim);
s_printf(txt_buf, "\n%d mA\n", iinlim);
s_printf(txt_buf + strlen(txt_buf), "%d mA\n", iinlim);
bq24193_get_property(BQ24193_SystemMinimumVoltage, &value);
s_printf(txt_buf + strlen(txt_buf), "%d mV\n", value);
@ -2562,8 +2400,8 @@ static lv_res_t _create_window_battery_status(lv_obj_t *btn)
if (!usb_pd.pdo_no)
strcat(txt_buf, "\nNon PD");
// Limit to 6 profiles so it can fit.
usb_pd.pdo_no = MIN(usb_pd.pdo_no, 6);
// Limit to 5 profiles so it can fit.
usb_pd.pdo_no = MIN(usb_pd.pdo_no, 5);
for (u32 i = 0; i < usb_pd.pdo_no; i++)
{
@ -2714,7 +2552,7 @@ void create_tab_info(lv_theme_t *th, lv_obj_t *parent)
lv_btn_set_fit(btn3, true, true);
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_btn_set_action(btn3, LV_BTN_ACTION_CLICK, _create_window_hw_info_status);
lv_btn_set_action(btn3, LV_BTN_ACTION_CLICK, _create_window_fuses_info_status);
// Create KFuses button.
lv_obj_t *btn4 = lv_btn_create(h1, btn);

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2018-2025 CTCaer
* Copyright (c) 2018-2024 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
@ -24,9 +24,9 @@
#include <libs/lvgl/lv_themes/lv_theme_hekate.h>
#include <libs/lvgl/lvgl.h>
#define CLOCK_MIN_YEAR 2025
#define CLOCK_MIN_YEAR 2024
#define CLOCK_MAX_YEAR (CLOCK_MIN_YEAR + 10)
#define CLOCK_YEARLIST "2025\n2026\n2027\n2028\n2029\n2030\n2031\n2032\n2033\n2034\n2035"
#define CLOCK_YEARLIST "2024\n2025\n2026\n2027\n2028\n2029\n2030\n2031\n2032\n2033\n2034"
extern hekate_config h_cfg;
extern nyx_config n_cfg;
@ -432,7 +432,7 @@ static lv_res_t _save_theme_color_action(lv_obj_t *btn)
// Save nyx config.
create_nyx_config_entry(true);
reload_nyx(NULL, false);
reload_nyx();
return LV_RES_OK;
}
@ -954,7 +954,7 @@ save_data:
cal0->gyro_offset[0], cal0->gyro_offset[1], cal0->gyro_offset[2],
cal0->gyro_scale[0], cal0->gyro_scale[1], cal0->gyro_scale[2],
cal0->bd_mac[0], cal0->bd_mac[1], cal0->bd_mac[2], cal0->bd_mac[3], cal0->bd_mac[4], cal0->bd_mac[5]);
if (!error)
error = f_open(&fp, "switchroot/switch.cal", FA_WRITE | FA_CREATE_ALWAYS) ? 4 : 0;
if (!error)
{
@ -1168,11 +1168,13 @@ 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_click(status_bar.mid, false);
lv_res_t res = nyx_win_close_action_custom(btn);
lv_win_close_action(btn);
close_btn = NULL;
_check_nyx_changes();
return res;
return LV_RES_INV;
}
lv_res_t create_win_nyx_options(lv_obj_t *parrent_btn)

View file

@ -85,7 +85,7 @@ l4t_flasher_ctxt_t l4t_flash_ctxt;
lv_obj_t *btn_flash_l4t;
lv_obj_t *btn_flash_android;
int _copy_file(const char *src, const char *dst, const char *path)
int _copy_file(const char *src, const char *dst, char *path)
{
FIL fp_src;
FIL fp_dst;
@ -265,7 +265,7 @@ out:
return res;
}
static void _create_gpt_partition(gpt_t *gpt, u8 *gpt_idx, u32 *curr_part_lba, u32 size_lba, const char *name, int name_size)
static void _create_gpt_partition(gpt_t *gpt, u8 *gpt_idx, u32 *curr_part_lba, u32 size_lba, char *name, int name_size)
{
static const u8 linux_part_guid[] = { 0xAF, 0x3D, 0xC6, 0x0F, 0x83, 0x84, 0x72, 0x47, 0x8E, 0x79, 0x3D, 0x69, 0xD8, 0x47, 0x7D, 0xE4 };
u8 random_number[16];
@ -813,7 +813,7 @@ static u32 _get_available_l4t_partition()
return size_sct;
}
static int _get_available_android_partition()
static bool _get_available_android_partition()
{
gpt_t *gpt = zalloc(sizeof(gpt_t));
@ -827,17 +827,11 @@ static int _get_available_android_partition()
// Find kernel partition.
for (u32 i = 0; i < gpt->header.num_part_ents; i++)
{
if (gpt->entries[i].lba_start)
{
int found = !memcmp(gpt->entries[i].name, (char[]) { 'b', 0, 'o', 0, 'o', 0, 't', 0 }, 8) ? 2 : 0;
found |= !memcmp(gpt->entries[i].name, (char[]) { 'L', 0, 'N', 0, 'X', 0 }, 6) ? 1 : 0;
if (found)
if (gpt->entries[i].lba_start && (!memcmp(gpt->entries[i].name, (char[]) { 'L', 0, 'N', 0, 'X', 0 }, 6) || !memcmp(gpt->entries[i].name, (char[]) { 'b', 0, 'o', 0, 'o', 0, 't', 0 }, 8)))
{
free(gpt);
return found;
}
return true;
}
if (i > 126)
@ -888,7 +882,7 @@ static lv_res_t _action_check_flash_linux(lv_obj_t *btn)
// Find an applicable partition for L4T.
u32 size_sct = _get_available_l4t_partition();
if (!l4t_flash_ctxt.offset_sct || size_sct < 0x800000)
if (!l4t_flash_ctxt.offset_sct || !size_sct || size_sct < 0x800000)
{
lv_label_set_text(lbl_status, "#FFDD00 Error:# No partition found!");
goto error;
@ -2057,9 +2051,9 @@ static void _create_mbox_check_files_total_size()
bar_l4t_ind.body.main_color = LV_COLOR_HEX(0x00DDFF);
bar_l4t_ind.body.grad_color = bar_l4t_ind.body.main_color;
// Set GPT bar style.
// Set Android bar style.
lv_style_copy(&bar_and_ind, lv_theme_get_current()->bar.indic);
bar_and_ind.body.main_color = LV_COLOR_HEX(0xC000FF);
bar_and_ind.body.main_color = LV_COLOR_HEX(0xFF8000);
bar_and_ind.body.grad_color = bar_and_ind.body.main_color;
// Set separator styles.
@ -2071,7 +2065,7 @@ static void _create_mbox_check_files_total_size()
sep_l4t_bg.body.main_color = LV_COLOR_HEX(0x00DDFF);
sep_l4t_bg.body.grad_color = sep_l4t_bg.body.main_color;
lv_style_copy(&sep_and_bg, &sep_emu_bg);
sep_and_bg.body.main_color = LV_COLOR_HEX(0xC000FF);
sep_and_bg.body.main_color = LV_COLOR_HEX(0xFF8000);
sep_and_bg.body.grad_color = sep_and_bg.body.main_color;
char *txt_buf = malloc(SZ_8K);
@ -2691,7 +2685,7 @@ lv_res_t create_window_partition_manager(lv_obj_t *btn)
// Create Android size slider.
lv_obj_t *slider_and = lv_slider_create(h1, NULL);
lv_obj_set_size(slider_and, LV_DPI * 7, LV_DPI / 3);
lv_slider_set_range(slider_and, 0, (part_info.total_sct - extra_sct) / SECTORS_PER_GB - (ANDROID_SYSTEM_SIZE_MB / 1024)); // Subtract android reserved size.
lv_slider_set_range(slider_and, 0, (part_info.total_sct - extra_sct) / SECTORS_PER_GB - 4); // Subtract android reserved size.
lv_slider_set_value(slider_and, 0);
lv_slider_set_style(slider_and, LV_SLIDER_STYLE_BG, &bar_and_bg);
lv_slider_set_style(slider_and, LV_SLIDER_STYLE_INDIC, &bar_and_ind);
@ -2754,35 +2748,27 @@ lv_res_t create_window_partition_manager(lv_obj_t *btn)
// Disable Flash Linux button if partition not found.
u32 size_sct = _get_available_l4t_partition();
if (!l4t_flash_ctxt.offset_sct || size_sct < 0x800000)
if (!l4t_flash_ctxt.offset_sct || !size_sct || size_sct < 0x800000)
{
lv_obj_set_click(btn_flash_l4t, false);
lv_btn_set_state(btn_flash_l4t, LV_BTN_STATE_INA);
}
int part_type_and = _get_available_android_partition();
// Create Flash Android button.
btn_flash_android = lv_btn_create(h1, NULL);
label_btn = lv_label_create(btn_flash_android, NULL);
lv_btn_set_fit(btn_flash_android, true, true);
switch (part_type_and)
{
case 0: // Disable Flash Android button if partition not found.
lv_label_set_static_text(label_btn, SYMBOL_DOWNLOAD" Flash Android");
lv_obj_set_click(btn_flash_android, false);
lv_btn_set_state(btn_flash_android, LV_BTN_STATE_INA);
break;
case 1: // Android 10/11.
lv_label_set_static_text(label_btn, SYMBOL_DOWNLOAD" Flash Android 10/11");
break;
case 2: // Android 13+
lv_label_set_static_text(label_btn, SYMBOL_DOWNLOAD" Flash Android 13+");
break;
}
lv_obj_align(btn_flash_android, btn_flash_l4t, LV_ALIGN_OUT_RIGHT_MID, LV_DPI / 3, 0);
lv_btn_set_action(btn_flash_android, LV_BTN_ACTION_CLICK, _action_flash_android);
// Disable Flash Android button if partition not found.
if (!_get_available_android_partition())
{
lv_obj_set_click(btn_flash_android, false);
lv_btn_set_state(btn_flash_android, LV_BTN_STATE_INA);
}
// Create next step button.
btn1 = lv_btn_create(h1, NULL);
label_btn = lv_label_create(btn1, NULL);

View file

@ -2,7 +2,7 @@
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018 st4rk
* Copyright (c) 2018 Ced2911
* Copyright (c) 2018-2025 CTCaer
* Copyright (c) 2018-2024 CTCaer
* Copyright (c) 2018 balika011
*
* This program is free software; you can redistribute it and/or modify it
@ -76,7 +76,7 @@ static const u8 master_kekseed_620[SE_KEY_128_SIZE] =
//!TODO: Update on mkey changes.
static const u8 master_kekseed_t210_max[SE_KEY_128_SIZE] =
{ 0xA1, 0x7D, 0x34, 0xDB, 0x2D, 0x9D, 0xDA, 0xE5, 0xF8, 0x15, 0x63, 0x4C, 0x8F, 0xE7, 0x6C, 0xD8 }; // 20.0.0.
{ 0x00, 0x04, 0x5D, 0xF0, 0x4D, 0xCD, 0x14, 0xA3, 0x1C, 0xBF, 0xDE, 0x48, 0x55, 0xBA, 0x35, 0xC1 }; // 18.0.0.
//!TODO: Update on mkey changes.
static const u8 master_kekseed_t210b01[HOS_KB_VERSION_MAX - HOS_KB_VERSION_600 + 1][SE_KEY_128_SIZE] = {
@ -93,8 +93,6 @@ static const u8 master_kekseed_t210b01[HOS_KB_VERSION_MAX - HOS_KB_VERSION_600 +
{ 0xA5, 0xEC, 0x16, 0x39, 0x1A, 0x30, 0x16, 0x08, 0x2E, 0xCF, 0x09, 0x6F, 0x5E, 0x7C, 0xEE, 0xA9 }, // 16.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.
{ 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] =
@ -126,8 +124,6 @@ static const u8 mkey_vectors[HOS_KB_VERSION_MAX + 1][SE_KEY_128_SIZE] = {
{ 0xAF, 0x11, 0x4C, 0x67, 0x17, 0x7A, 0x52, 0x43, 0xF7, 0x70, 0x2F, 0xC7, 0xEF, 0x81, 0x72, 0x16 }, // Mkey 14 encrypted with mkey 15.
{ 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.
{ 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.
@ -147,8 +143,6 @@ static const u8 new_console_keyseed[HOS_KB_VERSION_MAX - HOS_KB_VERSION_400 + 1]
{ 0xEA, 0x90, 0x6E, 0xA8, 0xAE, 0x92, 0x99, 0x64, 0x36, 0xC1, 0xF3, 0x1C, 0xC6, 0x32, 0x83, 0x8C }, // 16.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.
{ 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.
@ -168,8 +162,6 @@ static const u8 new_console_kekseed[HOS_KB_VERSION_MAX - HOS_KB_VERSION_400 + 1]
{ 0xF0, 0xF3, 0xFF, 0x52, 0x75, 0x2F, 0xBA, 0x4D, 0x09, 0x72, 0x30, 0x89, 0xA9, 0xDF, 0xFE, 0x1F }, // 16.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.
{ 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] =
@ -273,7 +265,7 @@ static void _hos_eks_save()
}
// Get keys.
u8 *keys = (u8 *)zalloc(SZ_8K);
u8 *keys = (u8 *)calloc(2, SZ_4K);
se_get_aes_keys(keys + SZ_4K, keys, SE_KEY_128_SIZE);
// Set magic and personalized info.
@ -337,19 +329,8 @@ out:
}
}
int hos_keygen(void *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt)
int hos_keygen_t210b01(u32 kb)
{
u32 retries = 0;
bool use_tsec = false;
tsec_keys_t tsec_keys;
kb_t *kb_data = (kb_t *)keyblob;
if (kb > HOS_KB_VERSION_MAX)
return 0;
// Do Mariko keygen.
if (h_cfg.t210b01)
{
// Use SBK as Device key 4x unsealer and KEK for mkey in T210B01 units.
se_aes_unwrap_key(10, 14, console_keyseed_4xx);
@ -361,7 +342,20 @@ int hos_keygen(void *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt)
se_aes_unwrap_key(8, 7, package2_keyseed);
return 1;
}
}
int hos_keygen(void *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt)
{
u32 retries = 0;
bool use_tsec = false;
tsec_keys_t tsec_keys;
kb_t *kb_data = (kb_t *)keyblob;
if (kb > HOS_KB_VERSION_MAX)
return 0;
if (h_cfg.t210b01)
return hos_keygen_t210b01(kb);
// Do Erista keygen.
@ -369,7 +363,7 @@ int hos_keygen(void *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt)
_hos_eks_get();
// Use tsec keygen for old firmware or if EKS keys does not exist for newer.
if (kb <= HOS_KB_VERSION_620 || !h_cfg.eks || (h_cfg.eks->enabled != HOS_EKS_TSEC_VER))
if (kb <= HOS_KB_VERSION_620 || !h_cfg.eks || (h_cfg.eks && h_cfg.eks->enabled != HOS_EKS_TSEC_VER))
use_tsec = true;
if (kb <= HOS_KB_VERSION_600)

View file

@ -1,6 +1,6 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2024 CTCaer
* Copyright (c) 2018-2023 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,
@ -45,9 +45,7 @@ enum {
HOS_KB_VERSION_1600 = 15,
HOS_KB_VERSION_1700 = 16,
HOS_KB_VERSION_1800 = 17,
HOS_KB_VERSION_1900 = 18,
HOS_KB_VERSION_2000 = 19,
HOS_KB_VERSION_MAX = HOS_KB_VERSION_2000
HOS_KB_VERSION_MAX = HOS_KB_VERSION_1800
};
#define HOS_TSEC_VERSION 4 //! TODO: Update on TSEC Root Key changes.

View file

@ -1,7 +1,7 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018 st4rk
* Copyright (c) 2018-2025 CTCaer
* Copyright (c) 2018-2023 CTCaer
* Copyright (c) 2018 balika011
*
* 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_4xx[3] = { PK11_SECTION_LD, PK11_SECTION_SM, PK11_SECTION_WB };
// Timestamp KB TSEC PK11 SECMON Warmboot
// ID (Timestamp), KB, TSEC, PK11, SECMON, Warmboot.
static const pkg1_id_t _pkg1_ids[] = {
{ "20161121", 0, 0x1900, 0x3FE0, 0x40014020, 0x8000D000 }, // 1.0.0.
{ "20170210", 0, 0x1900, 0x3FE0, 0x4002D000, 0x8000D000 }, // 2.0.0 - 2.3.0.
@ -66,9 +66,7 @@ static const pkg1_id_t _pkg1_ids[] = {
{ "20220801", 14, 0x0E00, 0x6FE0, 0x40030000, 0x4003E000 }, // 15.0.0 - 15.0.1.
{ "20230111", 15, 0x0E00, 0x6FE0, 0x40030000, 0x4003E000 }, // 16.0.0 - 16.1.0.
{ "20230906", 16, 0x0E00, 0x6FE0, 0x40030000, 0x4003E000 }, // 17.0.0 - 17.0.1.
{ "20240207", 17, 0x0E00, 0x6FE0, 0x40030000, 0x4003E000 }, // 18.0.0 - 18.1.0.
{ "20240808", 18, 0x0E00, 0x6FE0, 0x40030000, 0x4003E000 }, // 19.0.0 - 19.0.1.
{ "20250206", 19, 0x0E00, 0x6FE0, 0x40030000, 0x4003E000 }, // 20.0.0+
{ "20240207", 17, 0x0E00, 0x6FE0, 0x40030000, 0x4003E000 }, // 18.0.0+
};
const pkg1_id_t *pkg1_identify(u8 *pkg1, char *build_date)
@ -125,7 +123,7 @@ const u8 *pkg1_unpack(void *wm_dst, void *sm_dst, void *ldr_dst, const pkg1_id_t
// Get correct header mapping.
if (id->kb == HOS_KB_VERSION_100 && !memcmp(id->id, "20161121", 8))
sec_map = sec_map_100;
else if (id->kb <= HOS_KB_VERSION_301)
else if (id->kb >= HOS_KB_VERSION_100 && id->kb <= HOS_KB_VERSION_301)
sec_map = sec_map_2xx;
else
sec_map = sec_map_4xx;

View file

@ -1,6 +1,6 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2024 CTCaer
* Copyright (c) 2018-2023 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,
@ -113,10 +113,6 @@ static const u8 mkey_vector_7xx[HOS_KB_VERSION_MAX - HOS_KB_VERSION_810 + 1][SE_
{ 0x25, 0x12, 0x8B, 0xCB, 0xB5, 0x46, 0xA1, 0xF8, 0xE0, 0x52, 0x15, 0xB7, 0x0B, 0x57, 0x00, 0xBD },
// Master key 16 encrypted with 17. (17.0.0 with 18.0.0)
{ 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)
{ 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)

View file

@ -1,6 +1,6 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2025 CTCaer
* Copyright (c) 2018-2023 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,
@ -24,13 +24,12 @@
#define PKG2_SEC_BASE 0x80000000
#define PKG2_SEC_KERNEL 0
#define PKG2_SEC_INI1 1
#define PKG2_SEC_UNUSED 2
#define INI1_MAGIC 0x31494E49
//! TODO: Update on kernel change if needed.
// Offset of OP + 12 is the INI1 offset. On v2 with dynamic crt0 it's + 16.
#define PKG2_NEWKERN_GET_INI1_HEURISTIC 0xD2800015 // MOV X21, #0.
#define PKG2_NEWKERN_GET_INI1_HEURISTIC 0xD2800015
#define PKG2_NEWKERN_START 0x800
extern u32 pkg2_newkern_ini1_start;

View file

@ -402,7 +402,7 @@ error_occured:
msleep(1000);
btn_wait();
reload_nyx(NULL, true);
reload_nyx();
}
}

View file

@ -61,7 +61,7 @@ _reloc_ipl:
_real_start:
/* We place our stack in SDRAM. */
LDR SP, =0x4003F000
LDR SP, =0x83100000
LDR R0, =__bss_start
EOR R1, R1, R1
LDR R2, =__bss_end

View file

@ -9,13 +9,10 @@ autonogc=1
updater2p=1
bootprotect=0
# Only include above what you want to change from defaults.
# config.c in bootloader and Nyx have all the defaults.
{-------- Stock -------}
[Stock]
pkg3=atmosphere/package3
fss0=atmosphere/package3
stock=1
emummc_force_disable=1
@ -29,7 +26,7 @@ emummc_force_disable=1
{-- Custom Firmwares --}
[Atmo Vanilla]
pkg3=atmosphere/package3
fss0=atmosphere/package3
kip1=atmosphere/kips/*
# Note:
@ -39,11 +36,11 @@ kip1=atmosphere/kips/*
[Atmo EMU]
pkg3=atmosphere/package3
fss0=atmosphere/package3
emummcforce=1
[Atmo SYS]
pkg3=atmosphere/package3
fss0=atmosphere/package3
emummc_force_disable=1
# Note:
@ -58,7 +55,7 @@ emummc_force_disable=1
[Atmo EMU2]
pkg3=atmosphere/package3
fss0=atmosphere/package3
emupath=emuMMC/SD02
emummcforce=1
@ -71,26 +68,26 @@ emummcforce=1
[Atmo with extra kips]
pkg3=atmosphere/package3
fss0=atmosphere/package3
kip1=cfw/mods/mods_extra/*
kip1=cfw/mods/mods_extra/single/extra.kip
# Note:
# The above can be used with any pkg3 entry. Like the ones above.
# You can even override atmosphere (pkg3) kips with this.
# The above can be used with any fss0 entry. Like the ones above.
# You can even override atmosphere (fss0) kips with this.
# The wildcard '*' like above can be used to load all kips from a selected directory.
{-- Custom Firmwares Old methods --}
[CFW PKG3 extra kips & patches]
pkg3=atmosphere/package3
[CFW FSS0 extra kips & patches]
fss0=atmosphere/package3
kip1patch=name_of_patch
kip1=cfw/mods/mods_extra/*
kip1=cfw/mods/mods_extra/single/extra.kip
# Note:
# Both options for kip1 can be used. Wildcard and single.
# You can override kips loaded from PKG3/FSS0 if you define them after the pkg3 key.
# You can override kips loaded from FSS0/PKG3 if you define them after the fss0 key.
# If kip1 patch resides in patches.ini and that file OR the patch for
# current HOS version does not exist, it will error out.
@ -109,7 +106,7 @@ atmosphere=1
# Note:
# All kips defined method. This can be changed to what is below also.
# atmosphere=1 key is IMPORTANT when no PKG3/FSS0 is defined.
# atmosphere=1 key is IMPORTANT when no FFS0 is defined.