Compare commits

..

74 Commits

Author SHA1 Message Date
CTCaer
5a6608dff4 Bump hekate to v5.3.4 and Nyx to v0.9.5 2020-10-27 21:28:06 +02:00
CTCaer
8f222fd0bd main: Fix update.bin creation on first boot 2020-10-27 21:27:51 +02:00
CTCaer
1f5b371608 Refactor some names
Additionally:
- Do not retry to init sd if all modes failed in Nyx.
- Do not try to read/write if sdmmc controller and card are not initialized.
2020-10-23 06:32:24 +03:00
CTCaer
ce156ab4e7 hos: Automate some eks and bis checks 2020-10-20 11:53:28 +03:00
CTCaer
94235dd005 bm92t30: Add proper info
The driver will now show more charger supported profiles and will also show selected profile.
2020-10-20 10:42:57 +03:00
CTCaer
cb471162d2 i2c: Fix packet mode 2020-10-20 10:37:33 +03:00
CTCaer
9d1c0ce308 Create update.bin if missing
This will allow l4t/Android to always use latest hekate in case of old r2p.
2020-10-20 10:34:33 +03:00
CTCaer
27b1f0e843 Various small fixes 2020-10-20 10:32:32 +03:00
CTCaer
dae7be8ec4 nyx: Allow disabling of Joycon
Setting `jcdisable=1` in nyx.ini disables the usage of Joycon completely.

This also disables the BT pairing data dumping tool.
2020-10-20 10:21:48 +03:00
CTCaer
2f5b52223c config: Add bootloader protection
`bootprotect=1` enables protection of the `bootloader` folder inside HOS.

This disallows any reading/writing of the folder and its contents inside HOS, preventing any corruption of it.

This of course has the side-effect of homebrew that depend on it (e.g. hekate Toolbox) to not work fully.
2020-10-20 10:16:12 +03:00
CTCaer
bf222290b8 hos: Add support for mesosphere
The change adds support for mesosphere loading from fss0 or sd (kernel=).
2020-10-17 23:18:48 +03:00
CTCaer
d825be5eb2 hos: Tiny refactoring 2020-10-17 23:16:16 +03:00
CTCaer
9da0e0358b Merge pull request #500 from AuroraWright/master
hos: Prevent booting emummc with failed emummc patching
2020-10-17 23:02:34 +03:00
Aurora Wright
216d97aada Push changes as requested 2020-10-17 21:11:21 +02:00
Aurora Wright
e3421fd44e hos: Prevent sysmmc boot on emummc patch failure if emummc is forced 2020-10-14 19:37:36 +02:00
CTCaer
85d43147ee Bump hekate to v5.3.3 and Nyx to v0.9.4 2020-09-15 20:24:56 +03:00
CTCaer
e3e5dab0fc nyx: Add USB Charger info 2020-09-15 20:14:56 +03:00
CTCaer
8b837dd81b bm92t30 Add USB-PD driver stub
TODO:
This driver is a stub and relies on incorrect I2C requests.
The I2C driver needs to be updated with proper multi-xfer support.

For now it replies its whole register range, according to request size.
That's because the IC does not support the classic single transfer request-response style.
2020-09-15 20:13:29 +03:00
CTCaer
8f7bdd45b1 hos: Report exFAT compatible if missing FS kip hashes 2020-09-15 19:07:16 +03:00
CTCaer
0142ac1697 Add TUI reload in case of missing bootloader files 2020-09-15 18:57:49 +03:00
CTCaer
e8fb6624c0 Merge pull request #481 from NicholeMattera/master
Added new FS patches for 10.2.0.
2020-09-15 18:39:04 +03:00
Nichole Mattera
bdb21ce3fd Added new FS patches for 10.2.0. 2020-09-15 07:26:27 -04:00
CTCaer
2ca4fb6d8f Correct readme about UMS on boot 2020-09-07 00:10:23 +03:00
CTCaer
e7900b11b4 nyx: Allow L4T last part to be unaligned 2020-09-02 13:11:03 +03:00
CTCaer
d71f6d0b99 sdmmc: Restart xfer on Read/Write error 2020-08-28 09:39:06 +03:00
CTCaer
926bd5d2fb Add SD error report on first boot 2020-08-28 09:37:48 +03:00
CTCaer
461d14c39a di: Correct panel id for AUO A062TAN02 2020-08-28 05:26:18 +03:00
CTCaer
6714cae498 i2c: Add packet mode support (32 bytes) 2020-08-27 10:04:52 +03:00
CTCaer
b20a0e74c2 i2c: Refactor 2020-08-27 10:04:26 +03:00
CTCaer
9686eaf3f1 info: Add better SD error debugging on hekate main
Now the SD Card info function on hekate main will not rely on proper FAT partition, allowing for SDMMC init and FAT mounting to be separate for debugging issues with each one.

Additionally, add SDMMC error counters info.
2020-08-15 13:23:11 +03:00
CTCaer
7b03a24196 sdmmc: Add extra error printing 2020-08-15 13:16:37 +03:00
CTCaer
98555b24f8 l4t: Clear boot mode if user canceled autoboot 2020-08-15 13:12:41 +03:00
CTCaer
3d05b58856 nyx: Add eMMC NAND cells life estimation 2020-08-15 12:33:11 +03:00
CTCaer
15b46ddb27 hos: Hold more devices in Reset for secmon launch 2020-08-15 12:31:44 +03:00
CTCaer
78c4e6510d hos: Add backup bootloader support 2020-08-15 12:30:18 +03:00
CTCaer
cd76d5ac09 nyx: Fix hang on using B button after Launch window 2020-08-15 12:22:01 +03:00
CTCaer
9c2a064817 nyx: Allow SD removal without reloading Nyx 2020-08-15 12:21:25 +03:00
CTCaer
db2da89f69 nyx: Remove delay on JC calibration
This does not help with drifting as the logged values are always changing drastically.
2020-08-15 12:19:43 +03:00
CTCaer
0652d6b3f1 util: sprintf: Fix pointer printing 2020-08-15 12:16:25 +03:00
CTCaer
1111125aab usb: Invalidate cache on ep1_out_reading_finish 2020-08-15 12:15:02 +03:00
CTCaer
4fc420616d nyx: Control UART debug completely via makefile
Also enables LvGL log.
2020-08-13 10:21:00 +03:00
CTCaer
fb7c83a66c exo: Fix exo fatal dump's header 2020-08-02 03:51:36 +03:00
CTCaer
f021665089 Bump hekate to v5.3.2 2020-07-19 23:26:05 +03:00
CTCaer
6c887c15be l4t: Disable kernel panic dumping for now 2020-07-19 23:25:49 +03:00
CTCaer
2b7722da7d hos: Fix hold usbd in reset 2020-07-19 23:10:21 +03:00
CTCaer
4f65697522 Bump hekate to v5.3.1 and Nyx to v0.9.3 2020-07-19 20:56:22 +03:00
CTCaer
5140992a7b nyx: Add proper info about SD write protect 2020-07-19 20:56:08 +03:00
CTCaer
af0cd34f92 l4t: Add panic dump (PSTORE) 2020-07-19 20:32:22 +03:00
CTCaer
b8ca88ee0a exo: Change fatal names and add stack overflow 2020-07-18 12:53:05 +03:00
CTCaer
fac1884a43 i2c: Reduce timeout to proper levels (100ms) 2020-07-18 02:33:46 +03:00
CTCaer
46fa330bdd Add proper make prints for modules 2020-07-18 01:36:16 +03:00
CTCaer
adfa7c0780 fuse: Use fuse count function for burnt fuses 2020-07-18 01:15:28 +03:00
CTCaer
11df6030f9 Various fixes 2020-07-18 00:54:35 +03:00
CTCaer
45ca2938f5 pmc: Move rail power function to its own object 2020-07-18 00:42:53 +03:00
CTCaer
88fa4fa861 se: Add set/clear IV and aes key get 2020-07-18 00:36:51 +03:00
CTCaer
100d6cc4a5 lz: Return uncompressed size 2020-07-18 00:35:04 +03:00
CTCaer
32e58d2bb3 hw init: Cosmetic refactoring 2020-07-17 18:08:27 +03:00
CTCaer
638a3909c5 Refactor various variables and names 2020-07-17 18:00:32 +03:00
CTCaer
82da1aaf2a sdmmc: Correct name of bus speed 14 2020-07-17 17:38:01 +03:00
CTCaer
3c2d86ef7b sdmmc: Add protected area info (Content Protection) 2020-07-17 17:01:40 +03:00
CTCaer
f559017aeb di: Update display panels and info 2020-07-17 16:57:45 +03:00
CTCaer
e158d9bc00 clk: Refactor CLK devices bits 2020-07-17 16:50:17 +03:00
CTCaer
3ddd1c26ad pkg1: Fix PK11 component split in pkg1/2 dump tool 2020-07-14 23:29:48 +03:00
CTCaer
ab5b59e10d Refactor fatal/hard error names 2020-07-14 22:41:48 +03:00
CTCaer
1f67251331 nyx: Use strcat whenever possible 2020-07-14 22:26:40 +03:00
CTCaer
4eecdfa553 nyx: Add decrypted CAL0 dumping 2020-07-14 21:16:52 +03:00
CTCaer
80dd0f1580 joycon: Skip first 4 packets for calibration 2020-07-14 21:13:37 +03:00
CTCaer
4e0c70a402 nyx: Do not timeout joycon with screenshot
Additionally, screenshots are allowed only every 2s instead per second.
2020-07-14 21:12:09 +03:00
CTCaer
ffd5a198f9 Beautify make size prints 2020-07-14 20:56:56 +03:00
CTCaer
ddc89c9f49 hos: Reduce size of pkg1 id array 2020-06-22 12:04:49 +03:00
CTCaer
9673d5524a hos: Fix pkg2 re-encryption for exo2 & 8.1.0/9.0.X 2020-06-20 21:31:58 +03:00
CTCaer
3214fc2f93 nyx: Fix validation check for emuMMC restore
When checking a partition for enough size for emuMMC restore, always check against the extra 16MB.
2020-06-18 01:23:06 +03:00
CTCaer
3b0925b912 touch: Check if init failed and stop parsing if yes 2020-06-17 00:41:37 +03:00
CTCaer
c5f032fcb2 Fix building on msys2 2020-06-16 12:41:42 +03:00
82 changed files with 2235 additions and 974 deletions

View File

@@ -19,7 +19,7 @@ SOURCEDIR = bootloader
BDKDIR := bdk
BDKINC := -I./$(BDKDIR)
VPATH = $(dir ./$(SOURCEDIR)/) $(dir $(wildcard ./$(SOURCEDIR)/*/)) $(dir $(wildcard ./$(SOURCEDIR)/*/*/))
VPATH += $(dir $(wildcard ./$(BDKDIR)/*/)) $(dir $(wildcard ./$(BDKDIR)/*/*/))
VPATH += $(dir $(wildcard ./$(BDKDIR)/)) $(dir $(wildcard ./$(BDKDIR)/*/)) $(dir $(wildcard ./$(BDKDIR)/*/*/))
# Main and graphics.
OBJS = $(addprefix $(BUILDDIR)/$(TARGET)/, \
@@ -32,7 +32,7 @@ OBJS = $(addprefix $(BUILDDIR)/$(TARGET)/, \
# Hardware.
OBJS += $(addprefix $(BUILDDIR)/$(TARGET)/, \
bpmp.o ccplex.o clock.o di.o gpio.o i2c.o irq.o mc.o sdram.o \
pinmux.o se.o smmu.o tsec.o uart.o \
pinmux.o pmc.o se.o smmu.o tsec.o uart.o \
fuse.o kfuse.o minerva.o \
sdmmc.o sdmmc_driver.o emummc.o nx_emmc.o nx_sd.o \
bq24193.o max17050.o max7762x.o max77620-rtc.o \
@@ -84,11 +84,14 @@ NYXDIR := $(wildcard nyx)
.PHONY: all clean $(MODULEDIRS) $(NYXDIR)
all: $(TARGET).bin
@echo -n "Payload size is "
@printf ICTC49 >> $(OUTPUTDIR)/$(TARGET).bin
@echo "--------------------------------------"
@echo -n "Payload size: "
$(eval BIN_SIZE = $(shell wc -c < $(OUTPUTDIR)/$(TARGET).bin))
@echo $(BIN_SIZE)
@echo "Max size is 126296 Bytes."
@echo $(BIN_SIZE)" Bytes"
@echo "Payload Max: 126296 Bytes"
@if [ ${BIN_SIZE} -gt 126296 ]; then echo "\e[1;33mPayload size exceeds limit!\e[0m"; fi
@echo "--------------------------------------"
clean:
@rm -rf $(OBJS)
@@ -96,14 +99,13 @@ clean:
@rm -rf $(OUTPUTDIR)
$(MODULEDIRS):
@$(MAKE) -C $@ $(MAKECMDGOALS) -$(MAKEFLAGS)
@$(MAKE) --no-print-directory -C $@ $(MAKECMDGOALS) -$(MAKEFLAGS)
$(NYXDIR):
@$(MAKE) -C $@ $(MAKECMDGOALS) -$(MAKEFLAGS)
@$(MAKE) --no-print-directory -C $@ $(MAKECMDGOALS) -$(MAKEFLAGS)
$(TARGET).bin: $(BUILDDIR)/$(TARGET)/$(TARGET).elf $(MODULEDIRS) $(NYXDIR)
$(OBJCOPY) -S -O binary $< $(OUTPUTDIR)/$@
@printf ICTC49 >> $(OUTPUTDIR)/$@
$(BUILDDIR)/$(TARGET)/$(TARGET).elf: $(OBJS)
@$(CC) $(LDFLAGS) -T $(SOURCEDIR)/link.ld $^ -o $@

View File

@@ -55,6 +55,7 @@ You can find a template [Here](./res/hekate_ipl_template.ini)
| bootwait=3 | 0: Disable (It also disables bootlogo. Having **VOL-** pressed since injection goes to menu.), #: Time to wait for **VOL-** to enter menu. |
| autohosoff=1 | 0: Disable, 1: If woke up from HOS via an RTC alarm, shows logo, then powers off completely, 2: No logo, immediately powers off.|
| autonogc=1 | 0: Disable, 1: Automatically applies nogc patch if unburnt fuses found and a >= 4.0.0 HOS is booted. |
| bootprotect=0 | 0: Disable, 1: Protect bootloader folder from being corrupted by disallowing reading or editing in HOS. |
| updater2p=0 | 0: Disable, 1: Force updates (if needed) the reboot2payload binary to be hekate. |
| backlight=100 | Screen backlight level. 0-255. |
@@ -67,7 +68,8 @@ You can find a template [Here](./res/hekate_ipl_template.ini)
| timeoff=100 | Sets time offset in HEX. Must be in HOS epoch format |
| homescreen=0 | Sets home screen. 0: Home menu, 1: All configs (merges Launch and More configs), 2: Launch, 3: More Configs. |
| verification=1 | 0: Disable Backup/Restore verification, 1: Sparse (block based, fast and mostly reliable), 2: Full (sha256 based, slow and 100% reliable). |
| umsemmcrw=1 | 1: eMMC/emuMMC UMS will be mounted as writable by default. |
| umsemmcrw=0 | 1: eMMC/emuMMC UMS will be mounted as writable by default. |
| jcdisable=0 | 1: Disables Joycon driver completely. |
### Boot entry key/value combinations:
@@ -120,12 +122,12 @@ hekate has a boot storage in the binary that helps it configure it outside of BP
| Offset / Name | Description |
| ----------------------- | ----------------------------------------------------------------- |
| '0x94' boot_cfg | bit0: `Force AutoBoot`, bit1: `Show launch log`, bit2: `Boot from ID`, bit3: `Boot to emuMMC`, bit6: `Boot to UMS`, bit7: `sept run`. |
| '0x94' boot_cfg | bit0: `Force AutoBoot`, bit1: `Show launch log`, bit2: `Boot from ID`, bit3: `Boot to emuMMC`, bit7: `sept run`. |
| '0x95' autoboot | If `Force AutoBoot`: 0: Force go to menu, else boot that entry. |
| '0x96' autoboot_list | If `Force AutoBoot` and `autoboot` then it boots from ini folder. |
| '0x97' extra_cfg | bit7: Force Nyx to run `Dump pkg1/2`. |
| '0x97' extra_cfg | When menu is forced: bit5: `Run UMS`, bit7: `Run Dump pkg1/2`. |
| '0x98' xt_str[128] | Depends on the set cfg bits. |
| '0x98' ums[1] | When `Boot to UMS` is set, it will launch the selected UMS. 0: SD, 1: eMMC BOOT0, 2: eMMC BOOT1, 3: eMMC GPP, 4: emuMMC BOOT0, 5: emuMMC BOOT1, 6: emuMMC GPP, |
| '0x98' ums[1] | When `Run UMS` is set, it will launch the selected UMS. 0: SD, 1: eMMC BOOT0, 2: eMMC BOOT1, 3: eMMC GPP, 4: emuMMC BOOT0, 5: emuMMC BOOT1, 6: emuMMC GPP, |
| '0x98' id[8] | When `Boot from ID` is set, it will search all inis automatically and find the boot entry with that id and boot it. Must be NULL terminated. |
| '0xA0' emummc_path[120] | When `Boot to emuMMC` is set, it will override the current emuMMC (boot entry or emummc.ini). Must be NULL terminated. |

View File

@@ -1,11 +1,11 @@
# IPL Version.
BLVERSION_MAJOR := 5
BLVERSION_MINOR := 3
BLVERSION_HOTFX := 0
BLVERSION_HOTFX := 4
BLVERSION_RSVD := 0
# Nyx Version.
NYXVERSION_MAJOR := 0
NYXVERSION_MINOR := 9
NYXVERSION_HOTFX := 2
NYXVERSION_HOTFX := 5
NYXVERSION_RSVD := 0

View File

@@ -56,7 +56,7 @@ static void _display_dsi_send_cmd(u8 cmd, u32 param, u32 wait)
void display_init()
{
// Check if display is already initialized.
if (CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_SET) & 0x18000000)
if (CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_SET) & (BIT(CLK_L_DISP1) | BIT(CLK_L_HOST1X)))
display_end();
// Power on.
@@ -64,28 +64,28 @@ void display_init()
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_GPIO7, MAX77620_CNFG_GPIO_OUTPUT_VAL_HIGH | MAX77620_CNFG_GPIO_DRV_PUSHPULL);
// Enable Display Interface specific clocks.
CLOCK(CLK_RST_CONTROLLER_RST_DEV_H_CLR) = 0x1010000; // Clear reset DSI, MIPI_CAL.
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_SET) = 0x1010000; // Set enable clock DSI, MIPI_CAL.
CLOCK(CLK_RST_CONTROLLER_RST_DEV_H_CLR) = BIT(CLK_H_MIPI_CAL) | BIT(CLK_H_DSI);
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_SET) = BIT(CLK_H_MIPI_CAL) | BIT(CLK_H_DSI);
CLOCK(CLK_RST_CONTROLLER_RST_DEV_L_CLR) = 0x18000000; // Clear reset DISP1, HOST1X.
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_SET) = 0x18000000; // Set enable clock DISP1, HOST1X.
CLOCK(CLK_RST_CONTROLLER_RST_DEV_L_CLR) = BIT(CLK_L_HOST1X) | BIT(CLK_L_DISP1);
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_SET) = BIT(CLK_L_HOST1X) | BIT(CLK_L_DISP1);
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_X_SET) = 0x20000; // Set enable clock UART_FST_MIPI_CAL.
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_X_SET) = BIT(CLK_X_UART_FST_MIPI_CAL);
CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_UART_FST_MIPI_CAL) = 10; // Set PLLP_OUT3 and div 6 (17MHz).
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_W_SET) = 0x80000; // Set enable clock DSIA_LP.
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_W_SET) = BIT(CLK_W_DSIA_LP);
CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_DSIA_LP) = 10; // Set PLLP_OUT and div 6 (68MHz).
// Disable deep power down.
PMC(APBDEV_PMC_IO_DPD_REQ) = 0x40000000;
PMC(APBDEV_PMC_IO_DPD_REQ) = 0x40000000;
PMC(APBDEV_PMC_IO_DPD2_REQ) = 0x40000000;
// Config LCD and Backlight pins.
PINMUX_AUX(PINMUX_AUX_NFC_EN) &= ~PINMUX_TRISTATE; // PULL_DOWN
PINMUX_AUX(PINMUX_AUX_NFC_INT) &= ~PINMUX_TRISTATE; // PULL_DOWN
PINMUX_AUX(PINMUX_AUX_NFC_EN) &= ~PINMUX_TRISTATE; // PULL_DOWN
PINMUX_AUX(PINMUX_AUX_NFC_INT) &= ~PINMUX_TRISTATE; // PULL_DOWN
PINMUX_AUX(PINMUX_AUX_LCD_BL_PWM) &= ~PINMUX_TRISTATE; // PULL_DOWN | 1
PINMUX_AUX(PINMUX_AUX_LCD_BL_EN) &= ~PINMUX_TRISTATE; // PULL_DOWN
PINMUX_AUX(PINMUX_AUX_LCD_RST) &= ~PINMUX_TRISTATE; // PULL_DOWN
PINMUX_AUX(PINMUX_AUX_LCD_BL_EN) &= ~PINMUX_TRISTATE; // PULL_DOWN
PINMUX_AUX(PINMUX_AUX_LCD_RST) &= ~PINMUX_TRISTATE; // PULL_DOWN
// Set Backlight +-5V pins mode and direction
gpio_config(GPIO_PORT_I, GPIO_PIN_0 | GPIO_PIN_1, GPIO_MODE_GPIO);
@@ -170,8 +170,8 @@ void display_init()
DSI(_DSIREG(DSI_TRIGGER)) = DSI_TRIGGER_HOST;
usleep(5000);
break;
case PANEL_INL_P062CCA_AZ2:
case PANEL_AUO_A062TAN02:
case PANEL_INL_2J055IA_27A:
case PANEL_AUO_A055TAN01:
default: // Allow spare part displays to work.
_display_dsi_send_cmd(MIPI_DSI_DCS_SHORT_WRITE, MIPI_DCS_EXIT_SLEEP_MODE, 120000);
break;
@@ -180,14 +180,15 @@ void display_init()
_display_dsi_send_cmd(MIPI_DSI_DCS_SHORT_WRITE, MIPI_DCS_SET_DISPLAY_ON, 20000);
// Configure PLLD for DISP1.
plld_div = (1 << 20) | (24 << 11) | 1; // DIVM: 1, DIVN: 24, DIVP: 1. PLLD_OUT: 768 MHz, PLLD_OUT0 (DSI): 460.8 MHz.
plld_div = (1 << 20) | (24 << 11) | 1; // DIVM: 1, DIVN: 24, DIVP: 1. PLLD_OUT: 768 MHz, PLLD_OUT0 (DSI): 230.4 MHz.
CLOCK(CLK_RST_CONTROLLER_PLLD_BASE) = PLLCX_BASE_ENABLE | PLLCX_BASE_LOCK | plld_div;
CLOCK(CLK_RST_CONTROLLER_PLLD_MISC1) = 0x20;
CLOCK(CLK_RST_CONTROLLER_PLLD_MISC) = 0x2DFC00; // Use new PLLD_SDM_DIN.
// Finalize DSI configuration.
exec_cfg((u32 *)DSI_BASE, _display_dsi_packet_config, 21);
DISPLAY_A(_DIREG(DC_DISP_DISP_CLOCK_CONTROL)) = 4; // PCD1 | div3.
// Set pixel clock dividers: 230.4 / 3 / 1 = 76.8 MHz. 60 Hz.
DISPLAY_A(_DIREG(DC_DISP_DISP_CLOCK_CONTROL)) = PIXEL_CLK_DIVIDER_PCD1 | SHIFT_CLK_DIVIDER(4); // 4: div3.
exec_cfg((u32 *)DSI_BASE, _display_dsi_mode_config, 10);
usleep(10000);
@@ -269,15 +270,15 @@ void display_end()
case PANEL_AUO_A062TAN01:
exec_cfg((u32 *)DSI_BASE, _display_deinit_config_auo, 37);
break;
case PANEL_INL_P062CCA_AZ2:
case PANEL_AUO_A062TAN02:
case PANEL_INL_2J055IA_27A:
case PANEL_AUO_A055TAN01:
DSI(_DSIREG(DSI_WR_DATA)) = 0x439; // MIPI_DSI_DCS_LONG_WRITE: 4 bytes.
DSI(_DSIREG(DSI_WR_DATA)) = 0x9483FFB9; // Enable extension cmd. (Pass: FF 83 94).
DSI(_DSIREG(DSI_TRIGGER)) = DSI_TRIGGER_HOST;
usleep(5000);
// Set Power.
DSI(_DSIREG(DSI_WR_DATA)) = 0xB39; // MIPI_DSI_DCS_LONG_WRITE: 11 bytes.
if (_display_id == PANEL_INL_P062CCA_AZ2)
if (_display_id == PANEL_INL_2J055IA_27A)
DSI(_DSIREG(DSI_WR_DATA)) = 0x751548B1; // Set Power control. (Not deep standby, BT5 / XDK, VRH gamma volt adj 53 / x40).
else
DSI(_DSIREG(DSI_WR_DATA)) = 0x711148B1; // Set Power control. (Not deep standby, BT1 / XDK, VRH gamma volt adj 49 / x40).
@@ -305,10 +306,10 @@ void display_end()
usleep(10000);
// Disable Display Interface specific clocks.
CLOCK(CLK_RST_CONTROLLER_RST_DEV_H_SET) = 0x1010000; // Set reset clock DSI, MIPI_CAL.
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_CLR) = 0x1010000; // Clear enable clock DSI, MIPI_CAL.
CLOCK(CLK_RST_CONTROLLER_RST_DEV_L_SET) = 0x18000000; // Set reset DISP1, HOST1X.
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_CLR) = 0x18000000; // Clear enable DISP1, HOST1X.
CLOCK(CLK_RST_CONTROLLER_RST_DEV_H_SET) = BIT(CLK_H_MIPI_CAL) | BIT(CLK_H_DSI);
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_CLR) = BIT(CLK_H_MIPI_CAL) | BIT(CLK_H_DSI);
CLOCK(CLK_RST_CONTROLLER_RST_DEV_L_SET) = BIT(CLK_L_HOST1X) | BIT(CLK_L_DISP1);
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_CLR) = BIT(CLK_L_HOST1X) | BIT(CLK_L_DISP1);
// Power down pads.
DSI(_DSIREG(DSI_PAD_CONTROL_0)) = DSI_PAD_CONTROL_VS1_PULLDN_CLK | DSI_PAD_CONTROL_VS1_PULLDN(0xF) | DSI_PAD_CONTROL_VS1_PDIO_CLK | DSI_PAD_CONTROL_VS1_PDIO(0xF);

View File

@@ -496,12 +496,18 @@
#define MIPI_DCS_SET_DISPLAY_ON 0x29
/* Switch Panels:
*
* 6.2 panels":
* [10] 81 [26]: JDI LPM062M326A
* [10] 96 [09]: JDI LAM062M109A
* [20] 93 [0F]: InnoLux P062CCA-AZ1 (Rev A1)
* [20] XX [10]: InnoLux P062CCA-AZ2 [UNCONFIRMED ID]
* [20] 95 [0F]: InnoLux P062CCA-AZ2
* [30] 94 [0F]: AUO A062TAN01 (59.06A33.001)
* [30] XX [10]: AUO A062TAN02 (59.06A33.002) [UNCONFIRMED ID]
* [30] 95 [0F]: AUO A062TAN02 (59.06A33.002)
*
* 5.5" panels:
* [20] 94 [10]: InnoLux 2J055IA-27A (Rev B1)
* [30] XX [10]: AUO A055TAN01 (59.05A30.001) [UNCONFIRMED ID]
*/
enum
@@ -511,8 +517,8 @@ enum
PANEL_JDI_LPM062M326A = 0x2610,
PANEL_INL_P062CCA_AZ1 = 0x0F20,
PANEL_AUO_A062TAN01 = 0x0F30,
PANEL_INL_P062CCA_AZ2 = 0x1020,
PANEL_AUO_A062TAN02 = 0x1030
PANEL_INL_2J055IA_27A = 0x1020,
PANEL_AUO_A055TAN01 = 0x1030
};
void display_init();

View File

@@ -96,7 +96,7 @@ static const cfg_op_t _display_dc_setup_win_config[94] = {
{DC_DISP_DISP_INTERFACE_CONTROL, DISP_DATA_FORMAT_DF1P1C},
{DC_COM_PIN_OUTPUT_POLARITY(1), 0x1000000},
{DC_COM_PIN_OUTPUT_POLARITY(3), 0},
{0x4E4, 0},
{DC_DISP_BLEND_BACKGROUND_COLOR, 0},
{DC_COM_CRC_CONTROL, 0},
{DC_CMD_STATE_CONTROL, GENERAL_UPDATE | WIN_A_UPDATE | WIN_B_UPDATE | WIN_C_UPDATE},
{DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ | WIN_A_ACT_REQ | WIN_B_ACT_REQ | WIN_C_ACT_REQ},
@@ -253,7 +253,7 @@ static const cfg_op_t _display_dsi_packet_config[21] = {
{DSI_PKT_LEN_2_3, 0x87001A2},
{DSI_PKT_LEN_4_5, 0x190},
{DSI_PKT_LEN_6_7, 0x190},
{DSI_HOST_CONTROL, 0},
{DSI_HOST_CONTROL, 0}
};
//DSI mode config.
@@ -372,16 +372,16 @@ static const cfg_op_t _display_video_disp_controller_enable_config[113] = {
{DC_DISP_DISP_INTERFACE_CONTROL, DISP_DATA_FORMAT_DF1P1C},
{DC_COM_PIN_OUTPUT_POLARITY(1), 0x1000000},
{DC_COM_PIN_OUTPUT_POLARITY(3), 0},
{0x4E4, 0},
{DC_DISP_BLEND_BACKGROUND_COLOR, 0},
{DC_COM_CRC_CONTROL, 0},
{DC_CMD_STATE_CONTROL, GENERAL_UPDATE | WIN_A_UPDATE | WIN_B_UPDATE | WIN_C_UPDATE},
{DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ | WIN_A_ACT_REQ | WIN_B_ACT_REQ | WIN_C_ACT_REQ},
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT},
{0x716, 0x10000FF},
{DC_WINBUF_BLEND_LAYER_CONTROL, 0x10000FF},
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_B_SELECT},
{0x716, 0x10000FF},
{DC_WINBUF_BLEND_LAYER_CONTROL, 0x10000FF},
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_C_SELECT},
{0x716, 0x10000FF},
{DC_WINBUF_BLEND_LAYER_CONTROL, 0x10000FF},
{DC_CMD_DISPLAY_COMMAND_OPTION0, 0},
{DC_CMD_DISPLAY_WINDOW_HEADER, WINDOW_A_SELECT},
{DC_WIN_WIN_OPTIONS, 0},
@@ -394,14 +394,37 @@ static const cfg_op_t _display_video_disp_controller_enable_config[113] = {
{DC_CMD_STATE_CONTROL, GENERAL_UPDATE | WIN_A_UPDATE | WIN_B_UPDATE | WIN_C_UPDATE},
{DC_CMD_STATE_CONTROL, GENERAL_ACT_REQ | WIN_A_ACT_REQ | WIN_B_ACT_REQ | WIN_C_ACT_REQ},
{DC_CMD_STATE_ACCESS, 0},
/* Set Display timings */
/* Set Display timings
*
* DC_DISP_REF_TO_SYNC:
* V_REF_TO_SYNC - 1
* H_REF_TO_SYNC - 0
*
* DC_DISP_SYNC_WIDTH:
* V_SYNC_WIDTH - 1
* H_SYNC_WIDTH - 72
*
* DC_DISP_BACK_PORCH:
* V_BACK_PORCH - 9
* H_BACK_PORCH - 72
*
* DC_DISP_ACTIVE:
* V_DISP_ACTIVE - 1280
* H_DISP_ACTIVE - 720
*
* DC_DISP_FRONT_PORCH:
* V_FRONT_PORCH - 10
* H_FRONT_PORCH - 136
*/
{DC_DISP_DISP_TIMING_OPTIONS, 0},
{DC_DISP_REF_TO_SYNC, (1 << 16)}, // h_ref_to_sync = 0, v_ref_to_sync = 1.
{DC_DISP_REF_TO_SYNC, 0x10000},
{DC_DISP_SYNC_WIDTH, 0x10048},
{DC_DISP_BACK_PORCH, 0x90048},
{DC_DISP_ACTIVE, 0x50002D0},
{DC_DISP_FRONT_PORCH, 0xA0088}, // Sources say that this should be above the DC_DISP_ACTIVE cmd.
{DC_DISP_FRONT_PORCH, 0xA0088}, // Sources say that this should happen before DC_DISP_ACTIVE cmd.
/* End of Display timings */
{DC_DISP_SHIFT_CLOCK_OPTIONS, SC1_H_QUALIFIER_NONE | SC0_H_QUALIFIER_NONE},
{DC_COM_PIN_OUTPUT_ENABLE(1), 0},
{DC_DISP_DATA_ENABLE_OPTIONS, DE_SELECT_ACTIVE | DE_CONTROL_NORMAL},

View File

@@ -102,7 +102,8 @@ u8 als_init(als_table_t *als_val)
i2c_init(I2C_2);
max77620_regulator_set_volt_and_flags(REGULATOR_LDO6, 2900000, MAX77620_POWER_MODE_NORMAL);
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_LDO6_CFG2, 0xD8 | MAX77620_LDO_CFG2_ADE_MASK);
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_LDO6_CFG2,
(MAX77620_POWER_MODE_NORMAL << MAX77620_LDO_POWER_MODE_SHIFT | (3 << 3) | MAX77620_LDO_CFG2_ADE_ENABLE));
u8 id = i2c_recv_byte(I2C_2, BH1730_I2C_ADDR, BH1730_ADDR(0x12));
i2c_send_byte(I2C_2, BH1730_I2C_ADDR, BH1730_SPEC(BH1730_SPECCMD_RESET), 0);

View File

@@ -206,7 +206,7 @@ static u16 jc_packet_add_uart_hdr(jc_wired_hdr_t *out, u8 wired_cmd, u8 *data, u
out->uart_hdr.magic[1] = 0x01;
out->uart_hdr.magic[2] = 0x3;
out->uart_hdr.total_size_lsb = 7;
out->uart_hdr.total_size_lsb = sizeof(jc_wired_hdr_t) - sizeof(jc_uart_hdr_t);
out->uart_hdr.total_size_msb = 0;
out->cmd = wired_cmd;
@@ -523,6 +523,9 @@ jc_gamepad_rpt_t *jc_get_bt_pairing_info(bool *is_l_hos, bool *is_r_hos)
u8 retries;
jc_bt_conn_t *bt_conn;
if (!jc_init_done)
return NULL;
bt_conn = &jc_gamepad.bt_conn_l;
memset(bt_conn->host_mac, 0, 6);
memset(bt_conn->ltk, 0, 16);
@@ -812,7 +815,7 @@ void jc_init_hw()
jc_l.uart = UART_C;
jc_r.uart = UART_B;
#if (LV_LOG_PRINTF != 1)
#ifndef DEBUG_UART_PORT
jc_power_supply(UART_C, true);
jc_power_supply(UART_B, true);

View File

@@ -361,7 +361,7 @@ int touch_power_on()
// Enables LDO6 for touchscreen VDD/AVDD supply
max77620_regulator_set_volt_and_flags(REGULATOR_LDO6, 2900000, MAX77620_POWER_MODE_NORMAL);
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_LDO6_CFG2,
MAX77620_LDO_CFG2_ADE_ENABLE | (3 << 3) | (MAX77620_POWER_MODE_NORMAL << MAX77620_LDO_POWER_MODE_SHIFT));
(MAX77620_POWER_MODE_NORMAL << MAX77620_LDO_POWER_MODE_SHIFT | (3 << 3) | MAX77620_LDO_CFG2_ADE_ENABLE));
// Configure touchscreen GPIO.
PINMUX_AUX(PINMUX_AUX_DAP4_SCLK) = PINMUX_PULL_DOWN | 1;

View File

@@ -125,7 +125,7 @@ static int _LZ_ReadVarSize( unsigned int * x, const unsigned char * buf )
* insize - Number of input bytes.
*************************************************************************/
void LZ_Uncompress( const unsigned char *in, unsigned char *out,
unsigned int LZ_Uncompress( const unsigned char *in, unsigned char *out,
unsigned int insize )
{
unsigned char marker, symbol;
@@ -134,7 +134,7 @@ void LZ_Uncompress( const unsigned char *in, unsigned char *out,
/* Do we have anything to uncompress? */
if( insize < 1 )
{
return;
return 0;
}
/* Get marker symbol from input stream */
@@ -176,4 +176,6 @@ void LZ_Uncompress( const unsigned char *in, unsigned char *out,
}
}
while( inpos < insize );
return outpos;
}

View File

@@ -41,7 +41,7 @@ extern "C" {
* Function prototypes
*************************************************************************/
void LZ_Uncompress( const unsigned char *in, unsigned char *out,
unsigned int LZ_Uncompress( const unsigned char *in, unsigned char *out,
unsigned int insize );

View File

@@ -155,7 +155,11 @@
/*Log settings*/
#define USE_LV_LOG 0 /*Enable/disable the log module*/
#ifdef DEBUG_UART_PORT
# define USE_LV_LOG 1 /*Enable/disable the log module*/
#else
# define USE_LV_LOG 0 /*Enable/disable the log module*/
#endif
#if USE_LV_LOG
/* How important log should be added:
* LV_LOG_LEVEL_TRACE A lot of logs to give detailed information

View File

@@ -67,7 +67,7 @@ void lv_log_add(lv_log_level_t level, const char * file, int line, const char *
static const char * lvl_prefix[] = {"Trace", "Info", "Warn", "Error"};
char *log = (char *)malloc(0x1000);
s_printf(log, "%s: %s \t(%s #%d)\r\n", lvl_prefix[level], dsc, file, line);
uart_send(UART_B, (u8 *)log, strlen(log) + 1);
uart_send(DEBUG_UART_PORT, (u8 *)log, strlen(log) + 1);
//gfx_printf("%s: %s \t(%s #%d)\n", lvl_prefix[level], dsc, file, line);
#else
if(print_cb) print_cb(level, file, line, dsc);

View File

@@ -144,13 +144,12 @@ void mc_disable_ahb_redirect()
void mc_enable()
{
CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_EMC) = (CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_EMC) & 0x1FFFFFFF) | 0x40000000;
// Enable EMC clock.
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_SET) = (CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_SET) & 0xFDFFFFFF) | 0x2000000;
// Enable MC clock.
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_SET) = (CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_SET) & 0xFFFFFFFE) | 1;
// Enable EMC DLL clock.
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_X_SET) = (CLOCK(CLK_RST_CONTROLLER_CLK_ENB_X_SET) & 0xFFFFBFFF) | 0x4000;
CLOCK(CLK_RST_CONTROLLER_RST_DEV_H_CLR) = 0x2000001; //Clear EMC and MC reset.
// Enable memory clocks.
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_SET) = (CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_SET) & ~BIT(CLK_H_EMC)) | BIT(CLK_H_EMC);
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_SET) = (CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_SET) & ~BIT(CLK_H_MEM)) | BIT(CLK_H_MEM);
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_X_SET) = (CLOCK(CLK_RST_CONTROLLER_CLK_ENB_X_SET) & ~BIT(CLK_X_EMC_DLL)) | BIT(CLK_X_EMC_DLL);
// Clear clock resets for memory.
CLOCK(CLK_RST_CONTROLLER_RST_DEV_H_CLR) = BIT(CLK_H_EMC) | BIT(CLK_H_MEM);
usleep(5);
//#ifdef CONFIG_ENABLE_AHB_REDIRECT

View File

@@ -143,9 +143,10 @@ break_nosleep:
if (params->clear_clock2_mc1)
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_W_CLR) = 0x40000000; // Clear Reset to MC1.
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_SET) = 0x2000001; // Enable EMC and MEM clocks.
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_X_SET) = 0x4000; // Enable EMC_DLL clock.
CLOCK(CLK_RST_CONTROLLER_RST_DEV_H_CLR) = 0x2000001; // Clear EMC and MEM resets.
// Enable and clear reset for memory clocks.
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_H_SET) = BIT(CLK_H_EMC) | BIT(CLK_H_MEM);
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_X_SET) = BIT(CLK_X_EMC_DLL);
CLOCK(CLK_RST_CONTROLLER_RST_DEV_H_CLR) = BIT(CLK_H_EMC) | BIT(CLK_H_MEM);
// Set pad macros.
EMC(EMC_PMACRO_VTTGEN_CTRL_0) = params->emc_pmacro_vttgen_ctrl0;

View File

@@ -41,8 +41,12 @@
/* --- Gap: 1040MB 0xA4000000 - 0xE4FFFFFF --- */
// Virtual disk / Chainloader buffers.
#define RAM_DISK_ADDR 0xA4000000
#define RAM_DISK_SZ 0x41000000 // 1040MB.
#define RAM_DISK_ADDR 0xA4000000
#define RAM_DISK_SZ 0x41000000 // 1040MB.
// L4T Kernel Panic Storage (PSTORE).
#define PSTORE_ADDR 0xB0000000
#define PSTORE_SZ 0x200000 // 2MB.
//#define DRAM_LIB_ADDR 0xE0000000
/* --- Chnldr: 252MB 0xC03C0000 - 0xCFFFFFFF --- */ //! Only used when chainloading.

99
bdk/power/bm92t36.c Normal file
View File

@@ -0,0 +1,99 @@
/*
* USB-PD driver for Nintendo Switch's TI BM92T36
*
* Copyright (c) 2020 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* 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>
#include "bm92t36.h"
#include <soc/i2c.h>
#include <utils/util.h>
#define ALERT_STATUS_REG 0x2
#define STATUS1_REG 0x3
#define STATUS2_REG 0x4
#define COMMAND_REG 0x5
#define CONFIG1_REG 0x6
#define DEV_CAPS_REG 0x7
#define READ_PDOS_SRC_REG 0x8
#define CONFIG2_REG 0x17
#define DP_STATUS_REG 0x18
#define DP_ALERT_EN_REG 0x19
#define VENDOR_CONFIG_REG 0x1A
#define AUTO_NGT_FIXED_REG 0x20
#define AUTO_NGT_BATT_REG 0x23
#define SYS_CONFIG1_REG 0x26
#define SYS_CONFIG2_REG 0x27
#define CURRENT_PDO_REG 0x28
#define CURRENT_RDO_REG 0x2B
#define ALERT_ENABLE_REG 0x2E
#define SYS_CONFIG3_REG 0x2F
#define SET_RDO_REG 0x30
#define PDOS_SNK_REG 0x33
#define PDOS_SRC_PROV_REG 0x3C
#define FW_TYPE_REG 0x4B
#define FW_REVISION_REG 0x4C
#define MAN_ID_REG 0x4D
#define DEV_ID_REG 0x4E
#define REV_ID_REG 0x4F
#define INCOMING_VDM_REG 0x50
#define OUTGOING_VDM_REG 0x60
#define STATUS1_INSERT BIT(7) // Cable inserted.
typedef struct _pd_object_t {
unsigned int amp:10;
unsigned int volt:10;
unsigned int info:10;
unsigned int type:2;
} __attribute__((packed)) pd_object_t;
static int _bm92t36_read_reg(u8 *buf, u32 size, u32 reg)
{
return i2c_recv_buf_big(buf, size, I2C_1, BM92T36_I2C_ADDR, reg);
}
void bm92t36_get_sink_info(bool *inserted, usb_pd_objects_t *usb_pd)
{
u8 buf[32];
pd_object_t pdos[7];
if (inserted)
{
_bm92t36_read_reg(buf, 2, STATUS1_REG);
*inserted = buf[0] & STATUS1_INSERT ? true : false;
}
if (usb_pd)
{
_bm92t36_read_reg(buf, 29, READ_PDOS_SRC_REG);
memcpy(pdos, &buf[1], 28);
memset(usb_pd, 0, sizeof(usb_pd_objects_t));
usb_pd->pdo_no = buf[0] / sizeof(pd_object_t);
for (u32 i = 0; i < usb_pd->pdo_no; i++)
{
usb_pd->pdos[i].amperage = pdos[i].amp * 10;
usb_pd->pdos[i].voltage = (pdos[i].volt * 50) / 1000;
}
_bm92t36_read_reg(buf, 5, CURRENT_PDO_REG);
memcpy(pdos, &buf[1], 4);
usb_pd->selected_pdo.amperage = pdos[0].amp * 10;
usb_pd->selected_pdo.voltage = (pdos[0].volt * 50) / 1000;
}
}

41
bdk/power/bm92t36.h Normal file
View File

@@ -0,0 +1,41 @@
/*
* USB-PD driver for Nintendo Switch's TI BM92T36
*
* Copyright (c) 2020 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __BM92T36_H_
#define __BM92T36_H_
#include <utils/types.h>
#define BM92T36_I2C_ADDR 0x18
typedef struct _usb_pd_object_t
{
u32 amperage;
u32 voltage;
} usb_pd_object_t;
typedef struct _usb_pd_objects_t
{
u32 pdo_no;
usb_pd_object_t pdos[7];
usb_pd_object_t selected_pdo;
} usb_pd_objects_t;
void bm92t36_get_sink_info(bool *inserted, usb_pd_objects_t *usb_pd);
#endif

View File

@@ -108,11 +108,11 @@
#define MAX77620_LDO_VOLT_MASK 0x3F
#define MAX77620_REG_DVSSD0 0x1B
#define MAX77620_REG_DVSSD1 0x1C
#define MAX77620_REG_SD0_CFG 0x1D
#define MAX77620_REG_SD1_CFG 0x1E
#define MAX77620_REG_SD2_CFG 0x1F
#define MAX77620_REG_SD3_CFG 0x20
#define MAX77620_REG_SD4_CFG 0x21
#define MAX77620_REG_SD0_CFG 0x1D // SD CNFG1.
#define MAX77620_REG_SD1_CFG 0x1E // SD CNFG1.
#define MAX77620_REG_SD2_CFG 0x1F // SD CNFG1.
#define MAX77620_REG_SD3_CFG 0x20 // SD CNFG1.
#define MAX77620_REG_SD4_CFG 0x21 // SD CNFG1.
#define MAX77620_REG_SD_CFG2 0x22
#define MAX77620_REG_LDO0_CFG 0x23
#define MAX77620_REG_LDO0_CFG2 0x24

View File

@@ -198,6 +198,27 @@ void se_aes_key_set(u32 ks, void *key, u32 size)
}
}
void se_aes_iv_set(u32 ks, void *iv)
{
u32 *data = (u32 *)iv;
for (u32 i = 0; i < TEGRA_SE_AES_MIN_KEY_SIZE / 4; i++)
{
SE(SE_KEYTABLE_REG_OFFSET) = SE_KEYTABLE_SLOT(ks) | SE_KEYTABLE_QUAD(QUAD_ORG_IV) | i;
SE(SE_KEYTABLE_DATA0_REG_OFFSET) = data[i];
}
}
void se_aes_key_get(u32 ks, void *key, u32 size)
{
u32 *data = (u32 *)key;
for (u32 i = 0; i < size / 4; i++)
{
SE(SE_KEYTABLE_REG_OFFSET) = SE_KEYTABLE_SLOT(ks) | i;
data[i] = SE(SE_KEYTABLE_DATA0_REG_OFFSET);
}
}
void se_aes_key_clear(u32 ks)
{
for (u32 i = 0; i < TEGRA_SE_AES_MAX_KEY_SIZE / 4; i++)
@@ -207,6 +228,16 @@ void se_aes_key_clear(u32 ks)
}
}
void se_aes_iv_clear(u32 ks)
{
for (u32 i = 0; i < TEGRA_SE_AES_MIN_KEY_SIZE / 4; i++)
{
SE(SE_KEYTABLE_REG_OFFSET) = SE_KEYTABLE_SLOT(ks) | SE_KEYTABLE_QUAD(QUAD_ORG_IV) | i;
SE(SE_KEYTABLE_DATA0_REG_OFFSET) = 0;
}
}
int se_aes_unwrap_key(u32 ks_dst, u32 ks_src, const void *input)
{
SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_DEC_ALG(ALG_AES_DEC) | SE_CONFIG_DST(DST_KEYTAB);
@@ -336,6 +367,7 @@ int se_calc_sha256(void *hash, u32 *msg_left, const void *src, u32 src_size, u64
int res;
u32 *hash32 = (u32 *)hash;
//! TODO: src_size must be 512 bit aligned if continuing and not last block for SHA256.
if (src_size > 0xFFFFFF || (u32)hash % 4 || !hash) // Max 16MB - 1 chunks and aligned x4 hash buffer.
return 0;

View File

@@ -24,8 +24,12 @@ 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, 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);
int se_aes_unwrap_key(u32 ks_dst, u32 ks_src, const void *input);
int se_aes_crypt_cbc(u32 ks, u32 enc, void *dst, u32 dst_size, const void *src, u32 src_size);
int se_aes_crypt_ecb(u32 ks, u32 enc, void *dst, u32 dst_size, const void *src, u32 src_size);
int se_aes_crypt_block_ecb(u32 ks, u32 enc, void *dst, const void *src);
int se_aes_crypt_ctr(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_size, void *ctr);

View File

@@ -17,11 +17,11 @@
#include <soc/ccplex.h>
#include <soc/i2c.h>
#include <soc/clock.h>
#include <utils/util.h>
#include <soc/pmc.h>
#include <soc/t210.h>
#include <power/max77620.h>
#include <power/max7762x.h>
#include <utils/util.h>
void _ccplex_enable_power()
{
@@ -40,39 +40,6 @@ void _ccplex_enable_power()
i2c_send_byte(I2C_5, MAX77621_CPU_I2C_ADDR, MAX77621_VOUT_DVS_REG, MAX77621_VOUT_ENABLE | MAX77621_VOUT_0_95V);
}
int _ccplex_pmc_enable_partition(u32 part, int enable)
{
u32 part_mask = 1 << part;
u32 desired_state = enable << part;
// Check if the partition has the state we want.
if ((PMC(APBDEV_PMC_PWRGATE_STATUS) & part_mask) == desired_state)
return 1;
u32 i = 5001;
while (PMC(APBDEV_PMC_PWRGATE_TOGGLE) & 0x100)
{
usleep(1);
i--;
if (i < 1)
return 0;
}
// Toggle power gating.
PMC(APBDEV_PMC_PWRGATE_TOGGLE) = part | 0x100;
i = 5001;
while (i > 0)
{
if ((PMC(APBDEV_PMC_PWRGATE_STATUS) & part_mask) == desired_state)
break;
usleep(1);
i--;
}
return 1;
}
void ccplex_boot_cpu0(u32 entry)
{
// Set ACTIVE_CLUSER to FAST.
@@ -94,12 +61,12 @@ void ccplex_boot_cpu0(u32 entry)
// Configure MSELECT source and enable clock.
CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_MSELECT) = (CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_MSELECT) & 0x1FFFFF00) | 6;
CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_V) = (CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_V) & 0xFFFFFFF7) | 8;
CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_V) = (CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_V) & ~BIT(CLK_V_MSELECT)) | BIT(CLK_V_MSELECT);
// Configure initial CPU clock frequency and enable clock.
CLOCK(CLK_RST_CONTROLLER_CCLK_BURST_POLICY) = 0x20008888;
CLOCK(CLK_RST_CONTROLLER_SUPER_CCLK_DIVIDER) = 0x80000000;
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_V_SET) = 1;
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_V_SET) = BIT(CLK_V_CPUG);
clock_enable_coresight();
@@ -107,11 +74,11 @@ void ccplex_boot_cpu0(u32 entry)
CLOCK(CLK_RST_CONTROLLER_CPU_SOFTRST_CTRL2) &= 0xFFFFF000;
// Enable CPU rail.
_ccplex_pmc_enable_partition(0, 1);
// Enable cluster 0 non-CPU.
_ccplex_pmc_enable_partition(15, 1);
// Enable CE0.
_ccplex_pmc_enable_partition(14, 1);
pmc_enable_partition(0, 1);
// Enable cluster 0 non-CPU rail.
pmc_enable_partition(15, 1);
// Enable CE0 rail.
pmc_enable_partition(14, 1);
// Request and wait for RAM repair.
FLOW_CTLR(FLOW_CTLR_RAM_REPAIR) = 1;
@@ -131,7 +98,7 @@ void ccplex_boot_cpu0(u32 entry)
// MC(MC_TZ_SECURITY_CTRL) = 1;
// Clear MSELECT reset.
CLOCK(CLK_RST_CONTROLLER_RST_DEVICES_V) &= 0xFFFFFFF7;
CLOCK(CLK_RST_CONTROLLER_RST_DEVICES_V) &= ~BIT(CLK_V_MSELECT);
// Clear NONCPU reset.
CLOCK(CLK_RST_CONTROLLER_RST_CPUG_CMPLX_CLR) = 0x20000000;
// Clear CPU0 reset.

View File

@@ -34,63 +34,63 @@
/* clock_t: reset, enable, source, index, clk_src, clk_div */
static const clock_t _clock_uart[] = {
/* UART A */ { CLK_RST_CONTROLLER_RST_DEVICES_L, CLK_RST_CONTROLLER_CLK_OUT_ENB_L, CLK_RST_CONTROLLER_CLK_SOURCE_UARTA, 6, 0, 2 },
/* UART B */ { CLK_RST_CONTROLLER_RST_DEVICES_L, CLK_RST_CONTROLLER_CLK_OUT_ENB_L, CLK_RST_CONTROLLER_CLK_SOURCE_UARTB, 7, 0, 2 },
/* UART C */ { CLK_RST_CONTROLLER_RST_DEVICES_H, CLK_RST_CONTROLLER_CLK_OUT_ENB_H, CLK_RST_CONTROLLER_CLK_SOURCE_UARTC, 23, 0, 2 },
/* UART D */ { CLK_RST_CONTROLLER_RST_DEVICES_U, CLK_RST_CONTROLLER_CLK_OUT_ENB_U, CLK_RST_CONTROLLER_CLK_SOURCE_UARTD, 1, 0, 2 },
/* UART E */ { CLK_RST_CONTROLLER_RST_DEVICES_Y, CLK_RST_CONTROLLER_CLK_OUT_ENB_Y, CLK_RST_CONTROLLER_CLK_SOURCE_UARTAPE, 20, 0, 2 }
{ CLK_RST_CONTROLLER_RST_DEVICES_L, CLK_RST_CONTROLLER_CLK_OUT_ENB_L, CLK_RST_CONTROLLER_CLK_SOURCE_UARTA, CLK_L_UARTA, 0, 2 },
{ CLK_RST_CONTROLLER_RST_DEVICES_L, CLK_RST_CONTROLLER_CLK_OUT_ENB_L, CLK_RST_CONTROLLER_CLK_SOURCE_UARTB, CLK_L_UARTB, 0, 2 },
{ CLK_RST_CONTROLLER_RST_DEVICES_H, CLK_RST_CONTROLLER_CLK_OUT_ENB_H, CLK_RST_CONTROLLER_CLK_SOURCE_UARTC, CLK_H_UARTC, 0, 2 },
{ CLK_RST_CONTROLLER_RST_DEVICES_U, CLK_RST_CONTROLLER_CLK_OUT_ENB_U, CLK_RST_CONTROLLER_CLK_SOURCE_UARTD, CLK_U_UARTD, 0, 2 },
{ CLK_RST_CONTROLLER_RST_DEVICES_Y, CLK_RST_CONTROLLER_CLK_OUT_ENB_Y, CLK_RST_CONTROLLER_CLK_SOURCE_UARTAPE, CLK_Y_UARTAPE, 0, 2 }
};
//I2C default parameters - TLOW: 4, THIGH: 2, DEBOUNCE: 0, FM_DIV: 26.
static const clock_t _clock_i2c[] = {
/* I2C1 */ { CLK_RST_CONTROLLER_RST_DEVICES_L, CLK_RST_CONTROLLER_CLK_OUT_ENB_L, CLK_RST_CONTROLLER_CLK_SOURCE_I2C1, 12, 0, 19 }, //20.4MHz -> 100KHz
/* I2C2 */ { CLK_RST_CONTROLLER_RST_DEVICES_H, CLK_RST_CONTROLLER_CLK_OUT_ENB_H, CLK_RST_CONTROLLER_CLK_SOURCE_I2C2, 22, 0, 4 }, //81.6MHz -> 400KHz
/* I2C3 */ { CLK_RST_CONTROLLER_RST_DEVICES_U, CLK_RST_CONTROLLER_CLK_OUT_ENB_U, CLK_RST_CONTROLLER_CLK_SOURCE_I2C3, 3, 0, 4 }, //81.6MHz -> 400KHz
/* I2C4 */ { CLK_RST_CONTROLLER_RST_DEVICES_V, CLK_RST_CONTROLLER_CLK_OUT_ENB_V, CLK_RST_CONTROLLER_CLK_SOURCE_I2C4, 7, 0, 19 }, //20.4MHz -> 100KHz
/* I2C5 */ { CLK_RST_CONTROLLER_RST_DEVICES_H, CLK_RST_CONTROLLER_CLK_OUT_ENB_H, CLK_RST_CONTROLLER_CLK_SOURCE_I2C5, 15, 0, 4 }, //81.6MHz -> 400KHz
/* I2C6 */ { CLK_RST_CONTROLLER_RST_DEVICES_X, CLK_RST_CONTROLLER_CLK_OUT_ENB_X, CLK_RST_CONTROLLER_CLK_SOURCE_I2C6, 6, 0, 19 } //20.4MHz -> 100KHz
{ CLK_RST_CONTROLLER_RST_DEVICES_L, CLK_RST_CONTROLLER_CLK_OUT_ENB_L, CLK_RST_CONTROLLER_CLK_SOURCE_I2C1, CLK_L_I2C1, 0, 19 }, //20.4MHz -> 100KHz
{ CLK_RST_CONTROLLER_RST_DEVICES_H, CLK_RST_CONTROLLER_CLK_OUT_ENB_H, CLK_RST_CONTROLLER_CLK_SOURCE_I2C2, CLK_H_I2C2, 0, 4 }, //81.6MHz -> 400KHz
{ CLK_RST_CONTROLLER_RST_DEVICES_U, CLK_RST_CONTROLLER_CLK_OUT_ENB_U, CLK_RST_CONTROLLER_CLK_SOURCE_I2C3, CLK_U_I2C3, 0, 4 }, //81.6MHz -> 400KHz
{ CLK_RST_CONTROLLER_RST_DEVICES_V, CLK_RST_CONTROLLER_CLK_OUT_ENB_V, CLK_RST_CONTROLLER_CLK_SOURCE_I2C4, CLK_V_I2C4, 0, 19 }, //20.4MHz -> 100KHz
{ CLK_RST_CONTROLLER_RST_DEVICES_H, CLK_RST_CONTROLLER_CLK_OUT_ENB_H, CLK_RST_CONTROLLER_CLK_SOURCE_I2C5, CLK_H_I2C5, 0, 4 }, //81.6MHz -> 400KHz
{ CLK_RST_CONTROLLER_RST_DEVICES_X, CLK_RST_CONTROLLER_CLK_OUT_ENB_X, CLK_RST_CONTROLLER_CLK_SOURCE_I2C6, CLK_X_I2C6, 0, 19 } //20.4MHz -> 100KHz
};
static clock_t _clock_se = {
CLK_RST_CONTROLLER_RST_DEVICES_V, CLK_RST_CONTROLLER_CLK_OUT_ENB_V, CLK_RST_CONTROLLER_CLK_SOURCE_SE, 31, 0, 0
CLK_RST_CONTROLLER_RST_DEVICES_V, CLK_RST_CONTROLLER_CLK_OUT_ENB_V, CLK_RST_CONTROLLER_CLK_SOURCE_SE, CLK_V_SE, 0, 0
};
static clock_t _clock_tzram = {
CLK_RST_CONTROLLER_RST_DEVICES_V, CLK_RST_CONTROLLER_CLK_OUT_ENB_V, CLK_NO_SOURCE, 30, 0, 0
CLK_RST_CONTROLLER_RST_DEVICES_V, CLK_RST_CONTROLLER_CLK_OUT_ENB_V, CLK_NO_SOURCE, CLK_V_TZRAM, 0, 0
};
static clock_t _clock_host1x = {
CLK_RST_CONTROLLER_RST_DEVICES_L, CLK_RST_CONTROLLER_CLK_OUT_ENB_L, CLK_RST_CONTROLLER_CLK_SOURCE_HOST1X, 28, 4, 3
CLK_RST_CONTROLLER_RST_DEVICES_L, CLK_RST_CONTROLLER_CLK_OUT_ENB_L, CLK_RST_CONTROLLER_CLK_SOURCE_HOST1X, CLK_L_HOST1X, 4, 3
};
static clock_t _clock_tsec = {
CLK_RST_CONTROLLER_RST_DEVICES_U, CLK_RST_CONTROLLER_CLK_OUT_ENB_U, CLK_RST_CONTROLLER_CLK_SOURCE_TSEC, 19, 0, 2
CLK_RST_CONTROLLER_RST_DEVICES_U, CLK_RST_CONTROLLER_CLK_OUT_ENB_U, CLK_RST_CONTROLLER_CLK_SOURCE_TSEC, CLK_U_TSEC, 0, 2
};
static clock_t _clock_sor_safe = {
CLK_RST_CONTROLLER_RST_DEVICES_Y, CLK_RST_CONTROLLER_CLK_OUT_ENB_Y, CLK_NO_SOURCE, 30, 0, 0
CLK_RST_CONTROLLER_RST_DEVICES_Y, CLK_RST_CONTROLLER_CLK_OUT_ENB_Y, CLK_NO_SOURCE, CLK_Y_SOR_SAFE, 0, 0
};
static clock_t _clock_sor0 = {
CLK_RST_CONTROLLER_RST_DEVICES_X, CLK_RST_CONTROLLER_CLK_OUT_ENB_X, CLK_NO_SOURCE, 22, 0, 0
CLK_RST_CONTROLLER_RST_DEVICES_X, CLK_RST_CONTROLLER_CLK_OUT_ENB_X, CLK_NO_SOURCE, CLK_X_SOR0, 0, 0
};
static clock_t _clock_sor1 = {
CLK_RST_CONTROLLER_RST_DEVICES_X, CLK_RST_CONTROLLER_CLK_OUT_ENB_X, CLK_RST_CONTROLLER_CLK_SOURCE_SOR1, 23, 0, 2
CLK_RST_CONTROLLER_RST_DEVICES_X, CLK_RST_CONTROLLER_CLK_OUT_ENB_X, CLK_RST_CONTROLLER_CLK_SOURCE_SOR1, CLK_X_SOR1, 0, 2
};
static clock_t _clock_kfuse = {
CLK_RST_CONTROLLER_RST_DEVICES_H, CLK_RST_CONTROLLER_CLK_OUT_ENB_H, CLK_NO_SOURCE, 8, 0, 0
CLK_RST_CONTROLLER_RST_DEVICES_H, CLK_RST_CONTROLLER_CLK_OUT_ENB_H, CLK_NO_SOURCE, CLK_H_KFUSE, 0, 0
};
static clock_t _clock_cl_dvfs = {
CLK_RST_CONTROLLER_RST_DEVICES_W, CLK_RST_CONTROLLER_CLK_OUT_ENB_W, CLK_NO_SOURCE, 27, 0, 0
CLK_RST_CONTROLLER_RST_DEVICES_W, CLK_RST_CONTROLLER_CLK_OUT_ENB_W, CLK_NO_SOURCE, CLK_W_DVFS, 0, 0
};
static clock_t _clock_coresight = {
CLK_RST_CONTROLLER_RST_DEVICES_U, CLK_RST_CONTROLLER_CLK_OUT_ENB_U, CLK_RST_CONTROLLER_CLK_SOURCE_CSITE, 9, 0, 4
CLK_RST_CONTROLLER_RST_DEVICES_U, CLK_RST_CONTROLLER_CLK_OUT_ENB_U, CLK_RST_CONTROLLER_CLK_SOURCE_CSITE, CLK_U_CSITE, 0, 4
};
static clock_t _clock_pwm = {
CLK_RST_CONTROLLER_RST_DEVICES_L, CLK_RST_CONTROLLER_CLK_OUT_ENB_L, CLK_RST_CONTROLLER_CLK_SOURCE_PWM, 17, 6, 4 // Fref: 6.2MHz.
CLK_RST_CONTROLLER_RST_DEVICES_L, CLK_RST_CONTROLLER_CLK_OUT_ENB_L, CLK_RST_CONTROLLER_CLK_SOURCE_PWM, CLK_L_PWM, 6, 4 // Fref: 6.2MHz.
};
static clock_t _clock_sdmmc_legacy_tm = {
CLK_RST_CONTROLLER_RST_DEVICES_Y, CLK_RST_CONTROLLER_CLK_OUT_ENB_Y, CLK_RST_CONTROLLER_CLK_SOURCE_SDMMC_LEGACY_TM, 1, 4, 66
CLK_RST_CONTROLLER_RST_DEVICES_Y, CLK_RST_CONTROLLER_CLK_OUT_ENB_Y, CLK_RST_CONTROLLER_CLK_SOURCE_SDMMC_LEGACY_TM, CLK_Y_SDMMC_LEGACY_TM, 4, 66
};
void clock_enable(const clock_t *clk)
@@ -223,12 +223,12 @@ void clock_disable_sor1()
void clock_enable_kfuse()
{
//clock_enable(&_clock_kfuse);
CLOCK(CLK_RST_CONTROLLER_RST_DEVICES_H) = (CLOCK(CLK_RST_CONTROLLER_RST_DEVICES_H) & 0xFFFFFEFF) | 0x100;
CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_H) &= 0xFFFFFEFF;
CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_H) = (CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_H) & 0xFFFFFEFF) | 0x100;
u32 kfuse_clk_unmask = ~BIT(CLK_H_KFUSE);
CLOCK(CLK_RST_CONTROLLER_RST_DEVICES_H) = (CLOCK(CLK_RST_CONTROLLER_RST_DEVICES_H) & kfuse_clk_unmask) | BIT(CLK_H_KFUSE);
CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_H) &= kfuse_clk_unmask;
CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_H) = (CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_H) & kfuse_clk_unmask) | BIT(CLK_H_KFUSE);
usleep(10);
CLOCK(CLK_RST_CONTROLLER_RST_DEVICES_H) &= 0xFFFFFEFF;
CLOCK(CLK_RST_CONTROLLER_RST_DEVICES_H) &= kfuse_clk_unmask;
usleep(20);
}
@@ -362,48 +362,18 @@ static void _clock_disable_pllc4(u32 mask)
pllc4_enabled = 0;
}
#define L_SWR_SDMMC1_RST (1 << 14)
#define L_SWR_SDMMC2_RST (1 << 9)
#define L_SWR_SDMMC4_RST (1 << 15)
#define U_SWR_SDMMC3_RST (1 << 5)
#define L_CLK_ENB_SDMMC1 (1 << 14)
#define L_CLK_ENB_SDMMC2 (1 << 9)
#define L_CLK_ENB_SDMMC4 (1 << 15)
#define U_CLK_ENB_SDMMC3 (1 << 5)
#define L_SET_SDMMC1_RST (1 << 14)
#define L_SET_SDMMC2_RST (1 << 9)
#define L_SET_SDMMC4_RST (1 << 15)
#define U_SET_SDMMC3_RST (1 << 5)
#define L_CLR_SDMMC1_RST (1 << 14)
#define L_CLR_SDMMC2_RST (1 << 9)
#define L_CLR_SDMMC4_RST (1 << 15)
#define U_CLR_SDMMC3_RST (1 << 5)
#define L_SET_CLK_ENB_SDMMC1 (1 << 14)
#define L_SET_CLK_ENB_SDMMC2 (1 << 9)
#define L_SET_CLK_ENB_SDMMC4 (1 << 15)
#define U_SET_CLK_ENB_SDMMC3 (1 << 5)
#define L_CLR_CLK_ENB_SDMMC1 (1 << 14)
#define L_CLR_CLK_ENB_SDMMC2 (1 << 9)
#define L_CLR_CLK_ENB_SDMMC4 (1 << 15)
#define U_CLR_CLK_ENB_SDMMC3 (1 << 5)
static int _clock_sdmmc_is_reset(u32 id)
{
switch (id)
{
case SDMMC_1:
return CLOCK(CLK_RST_CONTROLLER_RST_DEVICES_L) & L_SWR_SDMMC1_RST;
return CLOCK(CLK_RST_CONTROLLER_RST_DEVICES_L) & BIT(CLK_L_SDMMC1);
case SDMMC_2:
return CLOCK(CLK_RST_CONTROLLER_RST_DEVICES_L) & L_SWR_SDMMC2_RST;
return CLOCK(CLK_RST_CONTROLLER_RST_DEVICES_L) & BIT(CLK_L_SDMMC2);
case SDMMC_3:
return CLOCK(CLK_RST_CONTROLLER_RST_DEVICES_U) & U_SWR_SDMMC3_RST;
return CLOCK(CLK_RST_CONTROLLER_RST_DEVICES_U) & BIT(CLK_U_SDMMC3);
case SDMMC_4:
return CLOCK(CLK_RST_CONTROLLER_RST_DEVICES_L) & L_SWR_SDMMC4_RST;
return CLOCK(CLK_RST_CONTROLLER_RST_DEVICES_L) & BIT(CLK_L_SDMMC4);
}
return 0;
}
@@ -413,16 +383,16 @@ static void _clock_sdmmc_set_reset(u32 id)
switch (id)
{
case SDMMC_1:
CLOCK(CLK_RST_CONTROLLER_RST_DEV_L_SET) = L_SET_SDMMC1_RST;
CLOCK(CLK_RST_CONTROLLER_RST_DEV_L_SET) = BIT(CLK_L_SDMMC1);
break;
case SDMMC_2:
CLOCK(CLK_RST_CONTROLLER_RST_DEV_L_SET) = L_SET_SDMMC2_RST;
CLOCK(CLK_RST_CONTROLLER_RST_DEV_L_SET) = BIT(CLK_L_SDMMC2);
break;
case SDMMC_3:
CLOCK(CLK_RST_CONTROLLER_RST_DEV_U_SET) = U_SET_SDMMC3_RST;
CLOCK(CLK_RST_CONTROLLER_RST_DEV_U_SET) = BIT(CLK_U_SDMMC3);
break;
case SDMMC_4:
CLOCK(CLK_RST_CONTROLLER_RST_DEV_L_SET) = L_SET_SDMMC4_RST;
CLOCK(CLK_RST_CONTROLLER_RST_DEV_L_SET) = BIT(CLK_L_SDMMC4);
break;
}
}
@@ -432,16 +402,16 @@ static void _clock_sdmmc_clear_reset(u32 id)
switch (id)
{
case SDMMC_1:
CLOCK(CLK_RST_CONTROLLER_RST_DEV_L_CLR) = L_CLR_SDMMC1_RST;
CLOCK(CLK_RST_CONTROLLER_RST_DEV_L_CLR) = BIT(CLK_L_SDMMC1);
break;
case SDMMC_2:
CLOCK(CLK_RST_CONTROLLER_RST_DEV_L_CLR) = L_CLR_SDMMC2_RST;
CLOCK(CLK_RST_CONTROLLER_RST_DEV_L_CLR) = BIT(CLK_L_SDMMC2);
break;
case SDMMC_3:
CLOCK(CLK_RST_CONTROLLER_RST_DEV_U_CLR) = U_CLR_SDMMC3_RST;
CLOCK(CLK_RST_CONTROLLER_RST_DEV_U_CLR) = BIT(CLK_U_SDMMC3);
break;
case SDMMC_4:
CLOCK(CLK_RST_CONTROLLER_RST_DEV_L_CLR) = L_CLR_SDMMC4_RST;
CLOCK(CLK_RST_CONTROLLER_RST_DEV_L_CLR) = BIT(CLK_L_SDMMC4);
break;
}
}
@@ -451,13 +421,13 @@ static int _clock_sdmmc_is_enabled(u32 id)
switch (id)
{
case SDMMC_1:
return CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_L) & L_CLK_ENB_SDMMC1;
return CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_L) & BIT(CLK_L_SDMMC1);
case SDMMC_2:
return CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_L) & L_CLK_ENB_SDMMC2;
return CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_L) & BIT(CLK_L_SDMMC2);
case SDMMC_3:
return CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_U) & U_CLK_ENB_SDMMC3;
return CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_U) & BIT(CLK_U_SDMMC3);
case SDMMC_4:
return CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_L) & L_CLK_ENB_SDMMC4;
return CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_L) & BIT(CLK_L_SDMMC4);
}
return 0;
}
@@ -467,16 +437,16 @@ static void _clock_sdmmc_set_enable(u32 id)
switch (id)
{
case SDMMC_1:
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_SET) = L_SET_CLK_ENB_SDMMC1;
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_SET) = BIT(CLK_L_SDMMC1);
break;
case SDMMC_2:
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_SET) = L_SET_CLK_ENB_SDMMC2;
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_SET) = BIT(CLK_L_SDMMC2);
break;
case SDMMC_3:
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_U_SET) = U_SET_CLK_ENB_SDMMC3;
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_U_SET) = BIT(CLK_U_SDMMC3);
break;
case SDMMC_4:
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_SET) = L_SET_CLK_ENB_SDMMC4;
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_SET) = BIT(CLK_L_SDMMC4);
break;
}
}
@@ -486,16 +456,16 @@ static void _clock_sdmmc_clear_enable(u32 id)
switch (id)
{
case SDMMC_1:
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_CLR) = L_CLR_CLK_ENB_SDMMC1;
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_CLR) = BIT(CLK_L_SDMMC1);
break;
case SDMMC_2:
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_CLR) = L_CLR_CLK_ENB_SDMMC2;
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_CLR) = BIT(CLK_L_SDMMC2);
break;
case SDMMC_3:
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_U_CLR) = U_CLR_CLK_ENB_SDMMC3;
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_U_CLR) = BIT(CLK_U_SDMMC3);
break;
case SDMMC_4:
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_CLR) = L_CLR_CLK_ENB_SDMMC4;
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_CLR) = BIT(CLK_L_SDMMC4);
break;
}
}
@@ -680,7 +650,7 @@ void clock_sdmmc_get_card_clock_div(u32 *pclock, u16 *pdivisor, u32 type)
*pclock = 40800;
*pdivisor = 1;
break;
case SDHCI_TIMING_MMC_DDR52: // Actual IO Freq: 49.92 MHz.
case SDHCI_TIMING_MMC_HS102: // Actual IO Freq: 99.84 MHz.
*pclock = 200000;
*pdivisor = 2;
break;

View File

@@ -171,6 +171,269 @@
#define PLLC4_OUT3_CLKEN (1 << 1)
#define PLLC4_OUT3_RSTN_CLR (1 << 0)
/*
* CLOCK Peripherals:
* L 0 - 31
* H 32 - 63
* U 64 - 95
* V 96 - 127
* W 128 - 159
* X 160 - 191
* Y 192 - 223
*/
enum CLK_L_DEV
{
CLK_L_CPU = 0, // Only reset. Deprecated.
CLK_L_BPMP = 1, // Only reset.
CLK_L_SYS = 2, // Only reset.
CLK_L_ISPB = 3,
CLK_L_RTC = 4,
CLK_L_TMR = 5,
CLK_L_UARTA = 6,
CLK_L_UARTB = 7,
CLK_L_GPIO = 8,
CLK_L_SDMMC2 = 9,
CLK_L_SPDIF = 10,
CLK_L_I2S2 = 11, // I2S1
CLK_L_I2C1 = 12,
CLK_L_NDFLASH = 13, // HIDDEN.
CLK_L_SDMMC1 = 14,
CLK_L_SDMMC4 = 15,
CLK_L_TWC = 16, // HIDDEN.
CLK_L_PWM = 17,
CLK_L_I2S3 = 18,
CLK_L_EPP = 19, // HIDDEN.
CLK_L_VI = 20,
CLK_L_2D = 21, // HIDDEN.
CLK_L_USBD = 22,
CLK_L_ISP = 23,
CLK_L_3D = 24, // HIDDEN.
//CLK_L_ = 25,
CLK_L_DISP2 = 26,
CLK_L_DISP1 = 27,
CLK_L_HOST1X = 28,
CLK_L_VCP = 29, // HIDDEN.
CLK_L_I2S1 = 30, // I2S0
CLK_L_BPMP_CACHE_CTRL = 31, // CONTROLLER
};
enum CLK_H_DEV
{
CLK_H_MEM = 0, // MC.
CLK_H_AHBDMA = 1,
CLK_H_APBDMA = 2,
//CLK_H_ = 3,
CLK_H_KBC = 4, // HIDDEN.
CLK_H_STAT_MON = 5,
CLK_H_PMC = 6,
CLK_H_FUSE = 7,
CLK_H_KFUSE = 8,
CLK_H_SPI1 = 9,
CLK_H_SNOR = 10, // HIDDEN.
CLK_H_JTAG2TBC = 11,
CLK_H_SPI2 = 12,
CLK_H_XIO = 13, // HIDDEN.
CLK_H_SPI3 = 14,
CLK_H_I2C5 = 15,
CLK_H_DSI = 16,
//CLK_H_ = 17,
CLK_H_HSI = 18, // HIDDEN.
CLK_H_HDMI = 19, // HIDDEN.
CLK_H_CSI = 20,
//CLK_H_ = 21,
CLK_H_I2C2 = 22,
CLK_H_UARTC = 23,
CLK_H_MIPI_CAL = 24,
CLK_H_EMC = 25,
CLK_H_USB2 = 26,
CLK_H_USB3 = 27, // HIDDEN.
CLK_H_MPE = 28, // HIDDEN.
CLK_H_VDE = 29, // HIDDEN.
CLK_H_BSEA = 30, // HIDDEN.
CLK_H_BSEV = 31,
};
enum CLK_U_DEV
{
//CLK_U_ = 0,
CLK_U_UARTD = 1,
CLK_U_UARTE = 2, // HIDDEN.
CLK_U_I2C3 = 3,
CLK_U_SPI4 = 4,
CLK_U_SDMMC3 = 5,
CLK_U_PCIE = 6,
CLK_U_UNUSED = 7, // RESERVED
CLK_U_AFI = 8,
CLK_U_CSITE = 9,
CLK_U_PCIEXCLK = 10, // Only reset.
CLK_U_BPMPUCQ = 11, // HIDDEN.
CLK_U_LA = 12,
CLK_U_TRACECLKIN = 13, // HIDDEN.
CLK_U_SOC_THERM = 14,
CLK_U_DTV = 15,
CLK_U_NAND_SPEED = 16, // HIDDEN.
CLK_U_I2C_SLOW = 17,
CLK_U_DSIB = 18,
CLK_U_TSEC = 19,
CLK_U_IRAMA = 20,
CLK_U_IRAMB = 21,
CLK_U_IRAMC = 22,
CLK_U_IRAMD = 23, // EMUCIF ON RESET
CLK_U_BPMP_CACHE_RAM = 24,
CLK_U_XUSB_HOST = 25,
CLK_U_CLK_M_DOUBLER = 26,
CLK_U_MSENC = 27, // HIDDEN.
CLK_U_SUS_OUT = 28,
CLK_U_DEV2_OUT = 29,
CLK_U_DEV1_OUT = 30,
CLK_U_XUSB_DEV = 31,
};
enum CLK_V_DEV
{
CLK_V_CPUG = 0,
CLK_V_CPULP = 1, // Reserved.
CLK_V_3D2 = 2, // HIDDEN.
CLK_V_MSELECT = 3,
CLK_V_TSENSOR = 4,
CLK_V_I2S4 = 5,
CLK_V_I2S5 = 6,
CLK_V_I2C4 = 7,
CLK_V_SPI5 = 8, // HIDDEN.
CLK_V_SPI6 = 9, // HIDDEN.
CLK_V_AHUB = 10, // AUDIO.
CLK_V_APB2APE = 11, // APBIF.
CLK_V_DAM0 = 12, // HIDDEN.
CLK_V_DAM1 = 13, // HIDDEN.
CLK_V_DAM2 = 14, // HIDDEN.
CLK_V_HDA2CODEC_2X = 15,
CLK_V_ATOMICS = 16,
//CLK_V_ = 17,
//CLK_V_ = 18,
//CLK_V_ = 19,
//CLK_V_ = 20,
//CLK_V_ = 21,
CLK_V_SPDIF_DOUBLER = 22,
CLK_V_ACTMON = 23,
CLK_V_EXTPERIPH1 = 24,
CLK_V_EXTPERIPH2 = 25,
CLK_V_EXTPERIPH3 = 26,
CLK_V_SATA_OOB = 27,
CLK_V_SATA = 28,
CLK_V_HDA = 29,
CLK_V_TZRAM = 30, // HIDDEN.
CLK_V_SE = 31, // HIDDEN.
};
enum CLK_W_DEV
{
CLK_W_HDA2HDMICODEC = 0,
CLK_W_RESERVED0 = 1, //satacoldrstn
CLK_W_PCIERX0 = 2,
CLK_W_PCIERX1 = 3,
CLK_W_PCIERX2 = 4,
CLK_W_PCIERX3 = 5,
CLK_W_PCIERX4 = 6,
CLK_W_PCIERX5 = 7,
CLK_W_CEC = 8,
CLK_W_PCIE2_IOBIST = 9,
CLK_W_EMC_IOBIST = 10,
CLK_W_HDMI_IOBIST = 11, // HIDDEN.
CLK_W_SATA_IOBIST = 12,
CLK_W_MIPI_IOBIST = 13,
CLK_W_XUSB_PADCTL = 14, // Only reset.
CLK_W_XUSB = 15,
CLK_W_CILAB = 16,
CLK_W_CILCD = 17,
CLK_W_CILEF = 18,
CLK_W_DSIA_LP = 19,
CLK_W_DSIB_LP = 20,
CLK_W_ENTROPY = 21,
CLK_W_DDS = 22, // HIDDEN.
//CLK_W_ = 23,
CLK_W_DP2 = 24, // HIDDEN.
CLK_W_AMX0 = 25, // HIDDEN.
CLK_W_ADX0 = 26, // HIDDEN.
CLK_W_DVFS = 27,
CLK_W_XUSB_SS = 28,
CLK_W_EMC_LATENCY = 29,
CLK_W_MC1 = 30,
//CLK_W_ = 31,
};
enum CLK_X_DEV
{
CLK_X_SPARE = 0,
CLK_X_DMIC1 = 1,
CLK_X_DMIC2 = 2,
CLK_X_ETR = 3,
CLK_X_CAM_MCLK = 4,
CLK_X_CAM_MCLK2 = 5,
CLK_X_I2C6 = 6,
CLK_X_MC_CAPA = 7, // MC DAISY CHAIN1
CLK_X_MC_CBPA = 8, // MC DAISY CHAIN2
CLK_X_MC_CPU = 9,
CLK_X_MC_BBC = 10,
CLK_X_VIM2_CLK = 11,
//CLK_X_ = 12,
CLK_X_MIPIBIF = 13, //RESERVED
CLK_X_EMC_DLL = 14,
//CLK_X_ = 15,
CLK_X_HDMI_AUDIO = 16, // HIDDEN.
CLK_X_UART_FST_MIPI_CAL = 17,
CLK_X_VIC = 18,
//CLK_X_ = 19,
CLK_X_ADX1 = 20, // HIDDEN.
CLK_X_DPAUX = 21,
CLK_X_SOR0 = 22,
CLK_X_SOR1 = 23,
CLK_X_GPU = 24,
CLK_X_DBGAPB = 25,
CLK_X_HPLL_ADSP = 26,
CLK_X_PLLP_ADSP = 27,
CLK_X_PLLA_ADSP = 28,
CLK_X_PLLG_REF = 29,
//CLK_X_ = 30,
//CLK_X_ = 31,
};
enum CLK_Y_DEV
{
CLK_Y_SPARE1 = 0,
CLK_Y_SDMMC_LEGACY_TM = 1,
CLK_Y_NVDEC = 2,
CLK_Y_NVJPG = 3,
CLK_Y_AXIAP = 4,
CLK_Y_DMIC3 = 5,
CLK_Y_APE = 6,
CLK_Y_ADSP = 7,
CLK_Y_MC_CDPA = 8, // MC DAISY CHAIN4
CLK_Y_MC_CCPA = 9, // MC DAISY CHAIN3
CLK_Y_MAUD = 10,
//CLK_Y_ = 11,
CLK_Y_SATA_USB_UPHY = 12, // Only reset.
CLK_Y_PEX_USB_UPHY = 13, // Only reset.
CLK_Y_TSECB = 14,
CLK_Y_DPAUX1 = 15,
CLK_Y_VI_I2C = 16,
CLK_Y_HSIC_TRK = 17,
CLK_Y_USB2_TRK = 18,
CLK_Y_QSPI = 19,
CLK_Y_UARTAPE = 20,
CLK_Y_ADSPINTF = 21, // Only reset.
CLK_Y_ADSPPERIPH = 22, // Only reset.
CLK_Y_ADSPDBG = 23, // Only reset.
CLK_Y_ADSPWDT = 24, // Only reset.
CLK_Y_ADSPSCU = 25, // Only reset.
CLK_Y_ADSPNEON = 26,
CLK_Y_NVENC = 27,
CLK_Y_IQC2 = 28,
CLK_Y_IQC1 = 29,
CLK_Y_SOR_SAFE = 30,
CLK_Y_PLLP_OUT_CPU = 31,
};
/*! Generic clock descriptor. */
typedef struct _clock_t
{

View File

@@ -68,6 +68,18 @@ u32 fuse_read_odm_keygen_rev()
return 0;
}
u8 fuse_count_burnt(u32 val)
{
u8 burnt_fuses = 0;
for (u32 i = 0; i < 32; i++)
{
if ((val >> i) & 1)
burnt_fuses++;
}
return burnt_fuses;
}
void fuse_wait_idle()
{
u32 ctrl;

View File

@@ -76,11 +76,12 @@
#define FUSE_RESERVED_ODMX(x) (0x1C8 + 4 * (x))
void fuse_disable_program();
u32 fuse_read_odm(u32 idx);
u32 fuse_read_odm_keygen_rev();
u32 fuse_read_odm(u32 idx);
u32 fuse_read_odm_keygen_rev();
u8 fuse_count_burnt(u32 val);
void fuse_wait_idle();
int fuse_read_ipatch(void (*ipatch)(u32 offset, u32 value));
int fuse_read_evp_thunk(u32 *iram_evp_thunks, u32 *iram_evp_thunks_len);
int fuse_read_ipatch(void (*ipatch)(u32 offset, u32 value));
int fuse_read_evp_thunk(u32 *iram_evp_thunks, u32 *iram_evp_thunks_len);
void fuse_read_array(u32 *words);
bool fuse_check_patched_rcm();

View File

@@ -56,7 +56,7 @@ extern volatile nyx_storage_t *nyx_str;
* PCLK - 68MHz init (-> 136MHz -> OC/4).
*/
void _config_oscillators()
static void _config_oscillators()
{
CLOCK(CLK_RST_CONTROLLER_SPARE_REG0) = (CLOCK(CLK_RST_CONTROLLER_SPARE_REG0) & 0xFFFFFFF3) | 4; // Set CLK_M_DIVISOR to 2.
SYSCTR0(SYSCTR0_CNTFID0) = 19200000; // Set counter frequency.
@@ -73,14 +73,17 @@ void _config_oscillators()
PMC(APBDEV_PMC_TSC_MULT) = (PMC(APBDEV_PMC_TSC_MULT) & 0xFFFF0000) | 0x249F; //0x249F = 19200000 * (16 / 32.768 kHz)
CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_SYS) = 0; // Set SCLK div to 1.
CLOCK(CLK_RST_CONTROLLER_SCLK_BURST_POLICY) = 0x20004444; // Set clk source to Run and PLLP_OUT2 (204MHz).
CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_SYS) = 0; // Set BPMP/SCLK div to 1.
CLOCK(CLK_RST_CONTROLLER_SCLK_BURST_POLICY) = 0x20004444; // Set BPMP/SCLK source to Run and PLLP_OUT2 (204MHz).
CLOCK(CLK_RST_CONTROLLER_SUPER_SCLK_DIVIDER) = 0x80000000; // Enable SUPER_SDIV to 1.
CLOCK(CLK_RST_CONTROLLER_CLK_SYSTEM_RATE) = 2; // Set HCLK div to 1 and PCLK div to 3.
}
void _config_gpios()
static void _config_gpios()
{
// Clamp inputs when tristated.
APB_MISC(APB_MISC_PP_PINMUX_GLOBAL) = 0;
PINMUX_AUX(PINMUX_AUX_UART2_TX) = 0;
PINMUX_AUX(PINMUX_AUX_UART3_TX) = 0;
@@ -120,27 +123,28 @@ void _config_gpios()
// gpio_config(GPIO_PORT_Y, GPIO_PIN_1, GPIO_MODE_GPIO);
}
void _config_pmc_scratch()
static void _config_pmc_scratch()
{
PMC(APBDEV_PMC_SCRATCH20) &= 0xFFF3FFFF; // Unset Debug console from Customer Option.
PMC(APBDEV_PMC_SCRATCH20) &= 0xFFF3FFFF; // Unset Debug console from Customer Option.
PMC(APBDEV_PMC_SCRATCH190) &= 0xFFFFFFFE; // Unset DATA_DQ_E_IVREF EMC_PMACRO_DATA_PAD_TX_CTRL
PMC(APBDEV_PMC_SECURE_SCRATCH21) |= PMC_FUSE_PRIVATEKEYDISABLE_TZ_STICKY_BIT;
}
void _mbist_workaround()
static void _mbist_workaround()
{
CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_V) |= (1 << 10); // Enable AHUB clock.
CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_Y) |= (1 << 6); // Enable APE clock.
// Make sure Audio clocks are enabled before accessing I2S.
CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_V) |= BIT(CLK_V_AHUB);
CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_Y) |= BIT(CLK_Y_APE);
// Set mux output to SOR1 clock switch.
CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_SOR1) = (CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_SOR1) | 0x8000) & 0xFFFFBFFF;
// Enabled PLLD and set csi to PLLD for test pattern generation.
CLOCK(CLK_RST_CONTROLLER_PLLD_BASE) |= 0x40800000;
// Clear per-clock resets.
CLOCK(CLK_RST_CONTROLLER_RST_DEV_Y_CLR) = 0x40; // Clear reset APE.
CLOCK(CLK_RST_CONTROLLER_RST_DEV_X_CLR) = 0x40000; // Clear reset VIC.
CLOCK(CLK_RST_CONTROLLER_RST_DEV_L_CLR) = 0x18000000; // Clear reset DISP1, HOST1X.
// Clear per-clock resets for APE/VIC/HOST1X/DISP1.
CLOCK(CLK_RST_CONTROLLER_RST_DEV_Y_CLR) = BIT(CLK_Y_APE);
CLOCK(CLK_RST_CONTROLLER_RST_DEV_X_CLR) = BIT(CLK_X_VIC);
CLOCK(CLK_RST_CONTROLLER_RST_DEV_L_CLR) = BIT(CLK_L_HOST1X) | BIT(CLK_L_DISP1);
usleep(2);
// I2S channels to master and disable SLCG.
@@ -159,20 +163,59 @@ void _mbist_workaround()
VIC(0x8C) = 0xFFFFFFFF;
usleep(2);
// Set per-clock reset.
CLOCK(CLK_RST_CONTROLLER_RST_DEV_Y_SET) = 0x40; // Set reset APE.
CLOCK(CLK_RST_CONTROLLER_RST_DEV_L_SET) = 0x18000000; // Set reset DISP1, HOST1x.
CLOCK(CLK_RST_CONTROLLER_RST_DEV_X_SET) = 0x40000; // Set reset VIC.
// Set per-clock reset for APE/VIC/HOST1X/DISP1.
CLOCK(CLK_RST_CONTROLLER_RST_DEV_Y_SET) = BIT(CLK_Y_APE);
CLOCK(CLK_RST_CONTROLLER_RST_DEV_L_SET) = BIT(CLK_L_HOST1X) | BIT(CLK_L_DISP1);
CLOCK(CLK_RST_CONTROLLER_RST_DEV_X_SET) = BIT(CLK_X_VIC);
// Enable specific clocks and disable all others.
CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_H) = 0xC0; // Enable clock PMC, FUSE.
CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_L) = 0x80000130; // Enable clock RTC, TMR, GPIO, BPMP_CACHE.
//CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_L) = 0x80400130; // Keep USBD ON.
CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_U) = 0x1F00200; // Enable clock CSITE, IRAMA, IRAMB, IRAMC, IRAMD, BPMP_CACHE_RAM.
CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_V) = 0x80400808; // Enable clock MSELECT, APB2APE, SPDIF_DOUBLER, SE.
CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_W) = 0x402000FC; // Enable clock PCIERX0, PCIERX1, PCIERX2, PCIERX3, PCIERX4, PCIERX5, ENTROPY, MC1.
CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_X) = 0x23000780; // Enable clock MC_CAPA, MC_CAPB, MC_CPU, MC_BBC, DBGAPB, HPLL_ADSP, PLLG_REF.
CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_Y) = 0x300; // Enable clock MC_CDPA, MC_CCPA.
// CLK L Devices.
CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_H) =
BIT(CLK_H_PMC) |
BIT(CLK_H_FUSE);
// CLK H Devices.
CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_L) =
BIT(CLK_L_RTC) |
BIT(CLK_L_TMR) |
BIT(CLK_L_GPIO) |
BIT(CLK_L_BPMP_CACHE_CTRL);
// CLK U Devices.
CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_U) =
BIT(CLK_U_CSITE) |
BIT(CLK_U_IRAMA) |
BIT(CLK_U_IRAMB) |
BIT(CLK_U_IRAMC) |
BIT(CLK_U_IRAMD) |
BIT(CLK_U_BPMP_CACHE_RAM);
// CLK V Devices.
CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_V) =
BIT(CLK_V_MSELECT) |
BIT(CLK_V_APB2APE) |
BIT(CLK_V_SPDIF_DOUBLER) |
BIT(CLK_V_SE);
// CLK W Devices.
CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_W) =
BIT(CLK_W_PCIERX0) |
BIT(CLK_W_PCIERX1) |
BIT(CLK_W_PCIERX2) |
BIT(CLK_W_PCIERX3) |
BIT(CLK_W_PCIERX4) |
BIT(CLK_W_PCIERX5) |
BIT(CLK_W_ENTROPY) |
BIT(CLK_W_MC1);
// CLK X Devices.
CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_X) =
BIT(CLK_X_MC_CAPA) |
BIT(CLK_X_MC_CBPA) |
BIT(CLK_X_MC_CPU) |
BIT(CLK_X_MC_BBC) |
BIT(CLK_X_GPU) |
BIT(CLK_X_DBGAPB) |
BIT(CLK_X_PLLG_REF);
// CLK Y Devices.
CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_Y) =
BIT(CLK_Y_MC_CDPA) |
BIT(CLK_Y_MC_CCPA);
// Disable clock gate overrides.
CLOCK(CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRA) = 0;
@@ -182,20 +225,21 @@ void _mbist_workaround()
CLOCK(CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRE) = 0;
// Set child clock sources.
CLOCK(CLK_RST_CONTROLLER_PLLD_BASE) &= 0x1F7FFFFF; // Disable PLLD and set reference clock and csi clock.
CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_SOR1) &= 0xFFFF3FFF; // Set SOR1 to automatic muxing of safe clock (24MHz) or SOR1 clk switch.
CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_VI) = (CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_VI) & 0x1FFFFFFF) | 0x80000000; // Set clock source to PLLP_OUT.
CLOCK(CLK_RST_CONTROLLER_PLLD_BASE) &= 0x1F7FFFFF; // Disable PLLD and set reference clock and csi clock.
CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_SOR1) &= 0xFFFF3FFF; // Set SOR1 to automatic muxing of safe clock (24MHz) or SOR1 clk switch.
CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_VI) = (CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_VI) & 0x1FFFFFFF) | 0x80000000; // Set clock source to PLLP_OUT.
CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_HOST1X) = (CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_HOST1X) & 0x1FFFFFFF) | 0x80000000; // Set clock source to PLLP_OUT.
CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_NVENC) = (CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_NVENC) & 0x1FFFFFFF) | 0x80000000; // Set clock source to PLLP_OUT.
CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_NVENC) = (CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_NVENC) & 0x1FFFFFFF) | 0x80000000; // Set clock source to PLLP_OUT.
}
void _config_se_brom()
static void _config_se_brom()
{
// Enable fuse clock.
clock_enable_fuse(true);
// Skip SBK/SSK if sept was run.
if (!(b_cfg.boot_cfg & BOOT_CFG_SEPT_RUN))
bool sbk_skip = b_cfg.boot_cfg & BOOT_CFG_SEPT_RUN || FUSE(FUSE_PRIVATE_KEY0) == 0xFFFFFFFF;
if (!sbk_skip)
{
// Bootrom part we skipped.
u32 sbk[4] = {
@@ -225,7 +269,7 @@ void _config_se_brom()
APB_MISC(APB_MISC_PP_STRAPPING_OPT_A) = (APB_MISC(APB_MISC_PP_STRAPPING_OPT_A) & 0xF0) | (7 << 10);
}
void _config_regulators()
static void _config_regulators()
{
// Disable low battery shutdown monitor.
max77620_low_battery_monitor_config(false);
@@ -277,7 +321,7 @@ void _config_regulators()
MAX77621_CKKADV_TRIP_150mV_PER_US | MAX77621_INDUCTOR_NOMINAL);
}
void config_hw()
void hw_init()
{
// Bootrom stuff we skipped by going through rcm.
_config_se_brom();
@@ -285,19 +329,25 @@ void config_hw()
SYSREG(AHB_AHB_SPARE_REG) &= 0xFFFFFF9F; // Unset APB2JTAG_OVERRIDE_EN and OBS_OVERRIDE_EN.
PMC(APBDEV_PMC_SCRATCH49) = PMC(APBDEV_PMC_SCRATCH49) & 0xFFFFFFFC;
// Perform Memory Built-In Self Test WAR if T210.
_mbist_workaround();
// Enable Security Engine clock.
clock_enable_se();
// Enable fuse clock.
// Enable Fuse clock.
clock_enable_fuse(true);
// Disable fuse programming.
// Disable Fuse programming.
fuse_disable_program();
// Enable clocks to Memory controllers and disable AHB redirect.
mc_enable();
// Initialize counters, CLKM, BPMP and other clocks based on 38.4MHz oscillator.
_config_oscillators();
APB_MISC(APB_MISC_PP_PINMUX_GLOBAL) = 0;
// Initialize pin configuration.
_config_gpios();
#ifdef DEBUG_UART_PORT
@@ -305,34 +355,39 @@ void config_hw()
uart_init(DEBUG_UART_PORT, 115200);
#endif
// Enable Dynamic Voltage and Frequency Scaling device clock.
clock_enable_cl_dvfs();
// Enable clocks to I2C1 and I2CPWR.
clock_enable_i2c(I2C_1);
clock_enable_i2c(I2C_5);
// Enable clock to TZRAM.
clock_enable_tzram();
// Initialize I2C5, mandatory for PMIC comms.
i2c_init(I2C_1);
i2c_init(I2C_5);
// Enable charger in case it's disabled.
bq24193_enable_charger();
// Initialize various regulators based on Erista/Mariko platform.
_config_regulators();
_config_pmc_scratch(); // Missing from 4.x+
CLOCK(CLK_RST_CONTROLLER_SCLK_BURST_POLICY) = 0x20003333; // Set SCLK to PLLP_OUT (408MHz).
// Set BPMP/SCLK to PLLP_OUT (408MHz).
CLOCK(CLK_RST_CONTROLLER_SCLK_BURST_POLICY) = 0x20003333;
// Initialize External memory controller and configure DRAM parameters.
sdram_init();
bpmp_mmu_enable();
// Clear flags from PMC_SCRATCH0
PMC(APBDEV_PMC_SCRATCH0) &= ~PMC_SCRATCH0_MODE_PAYLOAD;
}
void reconfig_hw_workaround(bool extra_reconfig, u32 magic)
void hw_reinit_workaround(bool extra_reconfig, u32 magic)
{
// Disable BPMP max clock.
bpmp_clk_rate_set(BPMP_CLK_NORMAL);
@@ -353,8 +408,8 @@ void reconfig_hw_workaround(bool extra_reconfig, u32 magic)
nyx_str->mtc_cfg.init_done = 0;
// Re-enable clocks to Audio Processing Engine as a workaround to hanging.
CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_V) |= (1 << 10); // Enable AHUB clock.
CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_Y) |= (1 << 6); // Enable APE clock.
CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_V) |= BIT(CLK_V_AHUB);
CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_Y) |= BIT(CLK_Y_APE);
if (extra_reconfig)
{
@@ -376,7 +431,7 @@ void reconfig_hw_workaround(bool extra_reconfig, u32 magic)
// Enable clock to USBD and init SDMMC1 to avoid hangs with bad hw inits.
if (magic == 0xBAADF00D)
{
CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_L) |= (1 << 22);
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_SET) = BIT(CLK_L_USBD);
sdmmc_init(&sd_sdmmc, SDMMC_1, SDMMC_POWER_3_3, SDMMC_BUS_WIDTH_1, SDHCI_TIMING_SD_ID, 0);
clock_disable_cl_dvfs();

View File

@@ -20,7 +20,7 @@
#include <utils/types.h>
void config_hw();
void reconfig_hw_workaround(bool extra_reconfig, u32 magic);
void hw_init();
void hw_reinit_workaround(bool extra_reconfig, u32 magic);
#endif

View File

@@ -20,31 +20,98 @@
#include <soc/i2c.h>
#include <utils/util.h>
#define I2C_PACKET_PROT_I2C (1 << 4)
#define I2C_HEADER_CONT_XFER (1 << 15)
#define I2C_HEADER_REP_START (1 << 16)
#define I2C_HEADER_IE_ENABLE (1 << 17)
#define I2C_HEADER_READ (1 << 19)
#define I2C_CNFG (0x00 / 4)
#define CMD1_WRITE (0 << 6)
#define CMD1_READ (1 << 6)
#define NORMAL_MODE_GO (1 << 9)
#define PACKET_MODE_GO (1 << 10)
#define NEW_MASTER_FSM (1 << 11)
#define DEBOUNCE_CNT_4T (2 << 12)
#define I2C_CMD_ADDR0 (0x04 / 4)
#define ADDR0_WRITE 0
#define ADDR0_READ 1
#define I2C_CMD_DATA1 (0x0C / 4)
#define I2C_CMD_DATA2 (0x10 / 4)
#define I2C_STATUS (0x1C / 4)
#define I2C_STATUS_NOACK (0xF << 0)
#define I2C_STATUS_BUSY (1 << 8)
#define I2C_TX_FIFO (0x50 / 4)
#define I2C_RX_FIFO (0x54 / 4)
#define I2C_FIFO_CONTROL (0x5C / 4)
#define RX_FIFO_FLUSH (1 << 0)
#define TX_FIFO_FLUSH (1 << 1)
#define I2C_FIFO_STATUS (0x60 / 4)
#define RX_FIFO_FULL_CNT (0xF << 0)
#define TX_FIFO_EMPTY_CNT (0xF << 4)
#define I2C_INT_EN (0x64 / 4)
#define I2C_INT_STATUS (0x68 / 4)
#define I2C_INT_SOURCE (0x70 / 4)
#define RX_FIFO_DATA_REQ (1 << 0)
#define TX_FIFO_DATA_REQ (1 << 1)
#define ARB_LOST (1 << 2)
#define NO_ACK (1 << 3)
#define RX_FIFO_UNDER (1 << 4)
#define TX_FIFO_OVER (1 << 5)
#define ALL_PACKETS_COMPLETE (1 << 6)
#define PACKET_COMPLETE (1 << 7)
#define BUS_CLEAR_DONE (1 << 11)
#define I2C_CLK_DIVISOR (0x6C / 4)
#define I2C_BUS_CLEAR_CONFIG (0x84 / 4)
#define BC_ENABLE (1 << 0)
#define BC_TERMINATE (1 << 1)
#define I2C_BUS_CLEAR_STATUS (0x88 / 4)
#define I2C_CONFIG_LOAD (0x8C / 4)
#define MSTR_CONFIG_LOAD (1 << 0)
#define TIMEOUT_CONFIG_LOAD (1 << 2)
static const u32 i2c_addrs[] = {
0x7000C000, 0x7000C400, 0x7000C500,
0x7000C700, 0x7000D000, 0x7000D100
0x7000C000, // I2C_1.
0x7000C400, // I2C_2.
0x7000C500, // I2C_3.
0x7000C700, // I2C_4.
0x7000D000, // I2C_5.
0x7000D100 // I2C_6.
};
static void _i2c_wait(vu32 *base)
static void _i2c_load_cfg_wait(vu32 *base)
{
base[I2C_CONFIG_LOAD] = 0x25;
base[I2C_CONFIG_LOAD] = (1 << 5) | TIMEOUT_CONFIG_LOAD | MSTR_CONFIG_LOAD;
for (u32 i = 0; i < 20; i++)
{
usleep(1);
if (!(base[I2C_CONFIG_LOAD] & 1))
if (!(base[I2C_CONFIG_LOAD] & MSTR_CONFIG_LOAD))
break;
}
}
static int _i2c_send_pkt(u32 idx, u32 x, u8 *buf, u32 size)
static int _i2c_send_single(u32 i2c_idx, u32 dev_addr, u8 *buf, u32 size)
{
if (size > 8)
return 0;
u32 tmp = 0;
vu32 *base = (vu32 *)i2c_addrs[idx];
base[I2C_CMD_ADDR0] = x << 1; //Set x (send mode).
vu32 *base = (vu32 *)i2c_addrs[i2c_idx];
// Set device address and send mode.
base[I2C_CMD_ADDR0] = dev_addr << 1 | ADDR0_WRITE;
if (size > 4)
{
@@ -60,44 +127,55 @@ static int _i2c_send_pkt(u32 idx, u32 x, u8 *buf, u32 size)
base[I2C_CMD_DATA1] = tmp; //Set value.
}
base[I2C_CNFG] = ((size - 1) << 1) | 0x2800; //Set size and send mode.
_i2c_wait(base); //Kick transaction.
// Set size and send mode.
base[I2C_CNFG] = ((size - 1) << 1) | DEBOUNCE_CNT_4T | NEW_MASTER_FSM | CMD1_WRITE;
base[I2C_CNFG] = (base[I2C_CNFG] & 0xFFFFFDFF) | 0x200;
// Load configuration.
_i2c_load_cfg_wait(base);
u32 timeout = get_tmr_ms() + 1500;
while (base[I2C_STATUS] & 0x100)
// Initiate transaction on normal mode.
base[I2C_CNFG] = (base[I2C_CNFG] & 0xFFFFF9FF) | NORMAL_MODE_GO;
u32 timeout = get_tmr_ms() + 100; // Actual for max 8 bytes at 100KHz is 0.74ms.
while (base[I2C_STATUS] & I2C_STATUS_BUSY)
{
if (get_tmr_ms() > timeout)
return 0;
}
if (base[I2C_STATUS] << 28)
if (base[I2C_STATUS] & I2C_STATUS_NOACK)
return 0;
return 1;
}
static int _i2c_recv_pkt(u32 idx, u8 *buf, u32 size, u32 x)
static int _i2c_recv_single(u32 i2c_idx, u8 *buf, u32 size, u32 dev_addr)
{
if (size > 8)
return 0;
vu32 *base = (vu32 *)i2c_addrs[idx];
base[I2C_CMD_ADDR0] = (x << 1) | 1; // Set x (recv mode).
base[I2C_CNFG] = ((size - 1) << 1) | 0x2840; // Set size and recv mode.
_i2c_wait(base); // Kick transaction.
vu32 *base = (vu32 *)i2c_addrs[i2c_idx];
base[I2C_CNFG] = (base[I2C_CNFG] & 0xFFFFFDFF) | 0x200;
// Set device address and recv mode.
base[I2C_CMD_ADDR0] = (dev_addr << 1) | ADDR0_READ;
u32 timeout = get_tmr_ms() + 1500;
while (base[I2C_STATUS] & 0x100)
// Set size and recv mode.
base[I2C_CNFG] = ((size - 1) << 1) | DEBOUNCE_CNT_4T | NEW_MASTER_FSM | CMD1_READ;
// Load configuration.
_i2c_load_cfg_wait(base);
// Initiate transaction on normal mode.
base[I2C_CNFG] = (base[I2C_CNFG] & 0xFFFFF9FF) | NORMAL_MODE_GO;
u32 timeout = get_tmr_ms() + 100; // Actual for max 8 bytes at 100KHz is 0.74ms.
while (base[I2C_STATUS] & I2C_STATUS_BUSY)
{
if (get_tmr_ms() > timeout)
return 0;
}
if (base[I2C_STATUS] << 28)
if (base[I2C_STATUS] & I2C_STATUS_NOACK)
return 0;
u32 tmp = base[I2C_CMD_DATA1]; // Get LS value.
@@ -113,60 +191,234 @@ static int _i2c_recv_pkt(u32 idx, u8 *buf, u32 size, u32 x)
return 1;
}
void i2c_init(u32 idx)
static int _i2c_send_pkt(u32 i2c_idx, u8 *buf, u32 size, u32 dev_addr)
{
vu32 *base = (vu32 *)i2c_addrs[idx];
if (size > 32)
return 0;
base[I2C_CLK_DIVISOR_REGISTER] = 0x50001;
base[I2C_BUS_CLEAR_CONFIG] = 0x90003;
_i2c_wait(base);
int res = 0;
vu32 *base = (vu32 *)i2c_addrs[i2c_idx];
// Enable interrupts.
base[I2C_INT_EN] = ALL_PACKETS_COMPLETE | PACKET_COMPLETE | NO_ACK |
ARB_LOST | TX_FIFO_OVER | RX_FIFO_UNDER | TX_FIFO_DATA_REQ;
base[I2C_INT_STATUS] = base[I2C_INT_STATUS];
// Set device address and recv mode.
base[I2C_CMD_ADDR0] = (dev_addr << 1) | ADDR0_READ;
// Set recv mode.
base[I2C_CNFG] = DEBOUNCE_CNT_4T | NEW_MASTER_FSM | CMD1_WRITE;
// Set and flush FIFO.
base[I2C_FIFO_CONTROL] = RX_FIFO_FLUSH | TX_FIFO_FLUSH;
// Load configuration.
_i2c_load_cfg_wait(base);
// Initiate transaction on packet mode.
base[I2C_CNFG] = (base[I2C_CNFG] & 0xFFFFF9FF) | PACKET_MODE_GO;
u32 hdr[3];
hdr[0] = I2C_PACKET_PROT_I2C;
hdr[1] = size - 1;
hdr[2] = I2C_HEADER_IE_ENABLE | I2C_HEADER_CONT_XFER | (dev_addr << 1);
// Send header with request.
base[I2C_TX_FIFO] = hdr[0];
base[I2C_TX_FIFO] = hdr[1];
base[I2C_TX_FIFO] = hdr[2];
u32 timeout = get_tmr_ms() + 400;
while (size)
{
if (base[I2C_FIFO_STATUS] & TX_FIFO_EMPTY_CNT)
{
u32 tmp = 0;
u32 snd_size = MIN(size, 4);
memcpy(&tmp, buf, snd_size);
base[I2C_TX_FIFO] = tmp;
buf += snd_size;
size -= snd_size;
}
if (get_tmr_ms() > timeout)
{
res = 1;
break;
}
}
if (base[I2C_STATUS] & I2C_STATUS_NOACK || base[I2C_INT_STATUS] & NO_ACK)
res = 1;
// Disable packet mode.
usleep(20);
base[I2C_CNFG] &= 0xFFFFF9FF;
// Disable interrupts.
base[I2C_INT_EN] = 0;
return res;
}
static int _i2c_recv_pkt(u32 i2c_idx, u8 *buf, u32 size, u32 dev_addr, u32 reg)
{
if (size > 32)
return 0;
int res = 0;
vu32 *base = (vu32 *)i2c_addrs[i2c_idx];
// Enable interrupts.
base[I2C_INT_EN] = ALL_PACKETS_COMPLETE | PACKET_COMPLETE | NO_ACK |
ARB_LOST | TX_FIFO_OVER | RX_FIFO_UNDER | RX_FIFO_DATA_REQ;
base[I2C_INT_STATUS] = base[I2C_INT_STATUS];
// Set device address and recv mode.
base[I2C_CMD_ADDR0] = (dev_addr << 1) | ADDR0_READ;
// Set recv mode.
base[I2C_CNFG] = DEBOUNCE_CNT_4T | NEW_MASTER_FSM | CMD1_READ;
// Set and flush FIFO.
base[I2C_FIFO_CONTROL] = RX_FIFO_FLUSH | TX_FIFO_FLUSH;
// Load configuration.
_i2c_load_cfg_wait(base);
// Initiate transaction on packet mode.
base[I2C_CNFG] = (base[I2C_CNFG] & 0xFFFFF9FF) | PACKET_MODE_GO;
// Send reg request.
u32 hdr[3];
hdr[0] = I2C_PACKET_PROT_I2C;
hdr[1] = 1 - 1;
hdr[2] = I2C_HEADER_REP_START | (dev_addr << 1);
// Send header with reg request.
base[I2C_TX_FIFO] = hdr[0];
base[I2C_TX_FIFO] = hdr[1];
base[I2C_TX_FIFO] = hdr[2];
base[I2C_TX_FIFO] = reg;
u32 timeout = get_tmr_ms() + 400;
while (!(base[I2C_FIFO_STATUS] & TX_FIFO_EMPTY_CNT))
if (get_tmr_ms() > timeout)
break;
// Send read request.
hdr[1] = size - 1;
hdr[2] = I2C_HEADER_READ | (dev_addr << 1);
// Send header with read request.
base[I2C_TX_FIFO] = hdr[0];
base[I2C_TX_FIFO] = hdr[1];
base[I2C_TX_FIFO] = hdr[2];
timeout = get_tmr_ms() + 400;
while (size)
{
if (base[I2C_FIFO_STATUS] & RX_FIFO_FULL_CNT)
{
u32 rcv_size = MIN(size, 4);
u32 tmp = base[I2C_RX_FIFO];
memcpy(buf, &tmp, rcv_size);
buf += rcv_size;
size -= rcv_size;
}
if (get_tmr_ms() > timeout)
{
res = 1;
break;
}
}
if (base[I2C_STATUS] & I2C_STATUS_NOACK || base[I2C_INT_STATUS] & NO_ACK)
res = 1;
// Disable packet mode.
usleep(20);
base[I2C_CNFG] &= 0xFFFFF9FF;
// Disable interrupts.
base[I2C_INT_EN] = 0;
return res;
}
void i2c_init(u32 i2c_idx)
{
vu32 *base = (vu32 *)i2c_addrs[i2c_idx];
base[I2C_CLK_DIVISOR] = (5 << 16) | 1; // SF mode Div: 6, HS mode div: 2.
base[I2C_BUS_CLEAR_CONFIG] = (9 << 16) | BC_TERMINATE | BC_ENABLE;
// Load configuration.
_i2c_load_cfg_wait(base);
for (u32 i = 0; i < 10; i++)
{
usleep(20000);
if (base[INTERRUPT_STATUS_REGISTER] & 0x800)
if (base[I2C_INT_STATUS] & BUS_CLEAR_DONE)
break;
}
(vu32)base[I2C_BUS_CLEAR_STATUS];
base[INTERRUPT_STATUS_REGISTER] = base[INTERRUPT_STATUS_REGISTER];
base[I2C_INT_STATUS] = base[I2C_INT_STATUS];
}
int i2c_send_buf_small(u32 idx, u32 x, u32 y, u8 *buf, u32 size)
int i2c_recv_buf(u8 *buf, u32 size, u32 i2c_idx, u32 dev_addr)
{
return _i2c_recv_single(i2c_idx, buf, size, dev_addr);
}
int i2c_send_buf_big(u32 i2c_idx, u32 dev_addr, u8 *buf, u32 size)
{
if (size > 32)
return 0;
return _i2c_send_pkt(i2c_idx, buf, size, dev_addr);
}
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, u8 *buf, u32 size)
{
u8 tmp[4];
if (size > 7)
return 0;
tmp[0] = y;
tmp[0] = reg;
memcpy(tmp + 1, buf, size);
return _i2c_send_pkt(idx, x, tmp, size + 1);
return _i2c_send_single(i2c_idx, dev_addr, tmp, size + 1);
}
int i2c_recv_buf(u8 *buf, u32 size, u32 idx, u32 x)
int i2c_recv_buf_small(u8 *buf, u32 size, u32 i2c_idx, u32 dev_addr, u32 reg)
{
return _i2c_recv_pkt(idx, buf, size, x);
}
int i2c_recv_buf_small(u8 *buf, u32 size, u32 idx, u32 x, u32 y)
{
int res = _i2c_send_pkt(idx, x, (u8 *)&y, 1);
int res = _i2c_send_single(i2c_idx, dev_addr, (u8 *)&reg, 1);
if (res)
res = _i2c_recv_pkt(idx, buf, size, x);
res = _i2c_recv_single(i2c_idx, buf, size, dev_addr);
return res;
}
int i2c_send_byte(u32 idx, u32 x, u32 y, u8 b)
int i2c_send_byte(u32 i2c_idx, u32 dev_addr, u32 reg, u8 val)
{
return i2c_send_buf_small(idx, x, y, &b, 1);
return i2c_send_buf_small(i2c_idx, dev_addr, reg, &val, 1);
}
u8 i2c_recv_byte(u32 idx, u32 x, u32 y)
u8 i2c_recv_byte(u32 i2c_idx, u32 dev_addr, u32 reg)
{
u8 tmp = 0;
i2c_recv_buf_small(&tmp, 1, idx, x, y);
i2c_recv_buf_small(&tmp, 1, i2c_idx, dev_addr, reg);
return tmp;
}

View File

@@ -27,22 +27,13 @@
#define I2C_5 4
#define I2C_6 5
#define I2C_CNFG 0x00
#define I2C_CMD_ADDR0 0x01
#define I2C_CMD_DATA1 0x03
#define I2C_CMD_DATA2 0x04
#define I2C_STATUS 0x07
#define INTERRUPT_STATUS_REGISTER 0x1A
#define I2C_CLK_DIVISOR_REGISTER 0x1B
#define I2C_BUS_CLEAR_CONFIG 0x21
#define I2C_BUS_CLEAR_STATUS 0x22
#define I2C_CONFIG_LOAD 0x23
void i2c_init(u32 idx);
int i2c_send_buf_small(u32 idx, u32 x, u32 y, u8 *buf, u32 size);
int i2c_recv_buf(u8 *buf, u32 size, u32 idx, u32 x);
int i2c_recv_buf_small(u8 *buf, u32 size, u32 idx, u32 x, u32 y);
int i2c_send_byte(u32 idx, u32 x, u32 y, u8 b);
u8 i2c_recv_byte(u32 idx, u32 x, u32 y);
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, 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);
#endif

52
bdk/soc/pmc.c Normal file
View File

@@ -0,0 +1,52 @@
/*
* Copyright (c) 2020 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* 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 <soc/pmc.h>
#include <soc/t210.h>
#include <utils/util.h>
int pmc_enable_partition(u32 part, int enable)
{
u32 part_mask = 1 << part;
u32 desired_state = enable << part;
// Check if the partition has the state we want.
if ((PMC(APBDEV_PMC_PWRGATE_STATUS) & part_mask) == desired_state)
return 1;
u32 i = 5001;
while (PMC(APBDEV_PMC_PWRGATE_TOGGLE) & 0x100)
{
usleep(1);
i--;
if (i < 1)
return 0;
}
// Toggle power gating.
PMC(APBDEV_PMC_PWRGATE_TOGGLE) = part | 0x100;
i = 5001;
while (i > 0)
{
if ((PMC(APBDEV_PMC_PWRGATE_STATUS) & part_mask) == desired_state)
break;
usleep(1);
i--;
}
return 1;
}

View File

@@ -1,6 +1,7 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018 st4rk
* Copyright (c) 2018-2020 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
@@ -18,6 +19,8 @@
#ifndef _PMC_H_
#define _PMC_H_
#include <utils/types.h>
/*! PMC registers. */
#define APBDEV_PMC_CNTRL 0x0
#define PMC_CNTRL_MAIN_RST (1 << 4)
@@ -34,6 +37,7 @@
#define PMC_SCRATCH0_MODE_PAYLOAD (1 << 29)
#define PMC_SCRATCH0_MODE_RCM (1 << 1)
#define PMC_SCRATCH0_MODE_WARMBOOT (1 << 0)
#define PMC_SCRATCH0_MODE_CUSTOM_ALL (PMC_SCRATCH0_MODE_RECOVERY | PMC_SCRATCH0_MODE_FASTBOOT | PMC_SCRATCH0_MODE_PAYLOAD)
#define APBDEV_PMC_SCRATCH1 0x54
#define APBDEV_PMC_SCRATCH20 0xA0
#define APBDEV_PMC_PWR_DET_VAL 0xE4
@@ -46,6 +50,8 @@
#define PMC_CRYPTO_OP_SE_ENABLE 0
#define PMC_CRYPTO_OP_SE_DISABLE 1
#define APBDEV_PMC_SCRATCH33 0x120
#define APBDEV_PMC_SCRATCH37 0x130
#define PMC_SCRATCH37_KERNEL_PANIC_FLAG (1 << 24)
#define APBDEV_PMC_SCRATCH40 0x13C
#define APBDEV_PMC_OSC_EDPD_OVER 0x1A4
#define PMC_OSC_EDPD_OVER_OSC_CTRL_OVER 0x400000
@@ -84,4 +90,6 @@
#define APBDEV_PMC_SCRATCH190 0x818
#define APBDEV_PMC_SCRATCH200 0x840
int pmc_enable_partition(u32 part, int enable);
#endif

View File

@@ -169,14 +169,23 @@ int sdmmc_storage_end(sdmmc_storage_t *storage)
sdmmc_end(storage->sdmmc);
storage->initialized = 0;
return 1;
}
static int _sdmmc_storage_readwrite(sdmmc_storage_t *storage, u32 sector, u32 num_sectors, void *buf, u32 is_write)
{
u8 *bbuf = (u8 *)buf;
bool first_reinit = false;
while (num_sectors)
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.
@@ -184,7 +193,7 @@ static int _sdmmc_storage_readwrite(sdmmc_storage_t *storage, u32 sector, u32 nu
do
{
reinit_try:
if (_sdmmc_storage_readwrite_ex(storage, &blkcnt, sector, MIN(num_sectors, 0xFFFF), bbuf, is_write))
if (_sdmmc_storage_readwrite_ex(storage, &blkcnt, sct_off, MIN(sct_total, 0xFFFF), bbuf, is_write))
goto out;
else
retries--;
@@ -201,7 +210,7 @@ reinit_try:
sd_error_count_increment(SD_ERROR_RW_FAIL);
if (!first_reinit)
if (first_reinit)
res = sd_initialize(true);
else
{
@@ -210,19 +219,29 @@ reinit_try:
sd_error_count_increment(SD_ERROR_INIT_FAIL);
}
// Reset values for a retry.
blkcnt = 0;
retries = 3;
first_reinit = true;
first_reinit = false;
// If succesful reinit, restart xfer.
if (res)
{
bbuf = (u8 *)buf;
sct_off = sector;
sct_total = num_sectors;
goto reinit_try;
}
}
// Failed.
return 0;
out:
DPRINTF("readwrite: %08X\n", blkcnt);
sector += blkcnt;
num_sectors -= blkcnt;
sct_off += blkcnt;
sct_total -= blkcnt;
bbuf += 512 * blkcnt;
}
@@ -387,6 +406,10 @@ static void _mmc_storage_parse_ext_csd(sdmmc_storage_t *storage, u8 *buf)
storage->ext_csd.bkops_en = buf[EXT_CSD_BKOPS_EN];
storage->ext_csd.bkops_status = buf[EXT_CSD_BKOPS_STATUS];
storage->ext_csd.pre_eol_info = buf[EXT_CSD_PRE_EOL_INFO];
storage->ext_csd.dev_life_est_a = buf[EXT_CSD_DEVICE_LIFE_TIME_EST_TYP_A];
storage->ext_csd.dev_life_est_b = buf[EXT_CSD_DEVICE_LIFE_TIME_EST_TYP_B];
storage->sec_cnt = *(u32 *)&buf[EXT_CSD_SEC_CNT];
}
@@ -616,6 +639,8 @@ DPRINTF("[MMC] succesfully switched to HS mode\n");
sdmmc_card_clock_ctrl(storage->sdmmc, SDMMC_AUTO_CAL_ENABLE);
storage->initialized = 1;
return 1;
}
@@ -628,6 +653,7 @@ int sdmmc_storage_set_mmc_partition(sdmmc_storage_t *storage, u32 partition)
return 0;
storage->partition = partition;
return 1;
}
@@ -1030,6 +1056,8 @@ static void _sd_storage_parse_ssr(sdmmc_storage_t *storage)
raw_ssr2[0] = *(u32 *)&storage->raw_ssr[16];
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);
switch(unstuff_bits(raw_ssr1, 440 - 384, 8))
{
case 0:
@@ -1289,6 +1317,8 @@ DPRINTF("[SD] enabled HS\n");
DPRINTF("[SD] got sd status\n");
}
storage->initialized = 1;
return 1;
}
@@ -1328,17 +1358,19 @@ int sdmmc_storage_init_gc(sdmmc_storage_t *storage, sdmmc_t *sdmmc)
memset(storage, 0, sizeof(sdmmc_storage_t));
storage->sdmmc = sdmmc;
if (!sdmmc_init(sdmmc, SDMMC_2, SDMMC_POWER_1_8, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_DDR52, SDMMC_AUTO_CAL_DISABLE))
if (!sdmmc_init(sdmmc, SDMMC_2, SDMMC_POWER_1_8, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS102, SDMMC_AUTO_CAL_DISABLE))
return 0;
DPRINTF("[gc] after init\n");
usleep(1000 + (10000 + sdmmc->divisor - 1) / sdmmc->divisor);
if (!sdmmc_tuning_execute(storage->sdmmc, SDHCI_TIMING_MMC_DDR52, MMC_SEND_TUNING_BLOCK_HS200))
if (!sdmmc_tuning_execute(storage->sdmmc, SDHCI_TIMING_MMC_HS102, MMC_SEND_TUNING_BLOCK_HS200))
return 0;
DPRINTF("[gc] after tuning\n");
sdmmc_card_clock_ctrl(sdmmc, SDMMC_AUTO_CAL_ENABLE);
storage->initialized = 1;
return 1;
}

View File

@@ -65,16 +65,19 @@ typedef struct _mmc_csd
typedef struct _mmc_ext_csd
{
u8 rev;
u32 sectors;
int bkops; /* background support bit */
int bkops_en; /* manual bkops enable bit */
u8 rev;
u8 ext_struct; /* 194 */
u8 card_type; /* 196 */
u8 bkops_status; /* 246 */
u16 dev_version;
u8 pre_eol_info;
u8 dev_life_est_a;
u8 dev_life_est_b;
u8 boot_mult;
u8 rpmb_mult;
u16 dev_version;
} mmc_ext_csd_t;
typedef struct _sd_scr
@@ -92,6 +95,7 @@ typedef struct _sd_ssr
u8 uhs_grade;
u8 video_class;
u8 app_class;
u32 protected_size;
} sd_ssr_t;
/*! SDMMC storage context. */
@@ -112,6 +116,7 @@ typedef struct _sdmmc_storage_t
mmc_ext_csd_t ext_csd;
sd_scr_t scr;
sd_ssr_t ssr;
int initialized;
} sdmmc_storage_t;
int sdmmc_storage_end(sdmmc_storage_t *storage);

View File

@@ -241,8 +241,9 @@ static int _sdmmc_dll_cal_execute(sdmmc_t *sdmmc)
}
#ifdef SDMMC_EMMC_OC
// Add -4 TX_DLY_CODE_OFFSET if HS533.
if (sdmmc->id == SDMMC_4 && overclock)
sdmmc->regs->vendllcalcfg = sdmmc->regs->vendllcalcfg &= 0xFFFFC07F | (0x7C << 7); // Add -4 TX_DLY_CODE_OFFSET if HS533.
sdmmc->regs->vendllcalcfg = sdmmc->regs->vendllcalcfg &= 0xFFFFC07F | (0x7C << 7);
#endif
sdmmc->regs->vendllcalcfg |= TEGRA_MMC_DLLCAL_CFG_EN_CALIBRATE;
@@ -316,7 +317,7 @@ int sdmmc_setup_clock(sdmmc_t *sdmmc, u32 type)
case SDHCI_TIMING_UHS_SDR104:
case SDHCI_TIMING_UHS_SDR82:
case SDHCI_TIMING_UHS_DDR50:
case SDHCI_TIMING_MMC_DDR52:
case SDHCI_TIMING_MMC_HS102:
sdmmc->regs->hostctl2 = (sdmmc->regs->hostctl2 & SDHCI_CTRL_UHS_MASK) | UHS_SDR104_BUS_SPEED;
sdmmc->regs->hostctl2 |= SDHCI_CTRL_VDD_180;
break;
@@ -399,9 +400,8 @@ void sdmmc_card_clock_ctrl(sdmmc_t *sdmmc, int auto_cal_enable)
sdmmc->auto_cal_enabled = auto_cal_enable;
if (auto_cal_enable)
{
if (!(sdmmc->regs->clkcon & SDHCI_CLOCK_CARD_EN))
return;
sdmmc->regs->clkcon &= ~SDHCI_CLOCK_CARD_EN;
if (sdmmc->regs->clkcon & SDHCI_CLOCK_CARD_EN)
sdmmc->regs->clkcon &= ~SDHCI_CLOCK_CARD_EN;
return;
}
@@ -653,7 +653,7 @@ int sdmmc_tuning_execute(sdmmc_t *sdmmc, u32 type, u32 cmd)
break;
case SDHCI_TIMING_UHS_SDR50:
case SDHCI_TIMING_UHS_DDR50:
case SDHCI_TIMING_MMC_DDR52:
case SDHCI_TIMING_MMC_HS102:
max = 256;
flag = (4 << 13); // 256 iterations.
break;
@@ -725,7 +725,6 @@ static int _sdmmc_autocal_config_offset(sdmmc_t *sdmmc, u32 power)
off_pu = 5;
break;
case SDMMC_1:
case SDMMC_3:
if (power == SDMMC_POWER_1_8)
{
off_pd = 123;
@@ -764,7 +763,7 @@ static int _sdmmc_check_mask_interrupt(sdmmc_t *sdmmc, u16 *pout, u16 mask)
u16 norintsts = sdmmc->regs->norintsts;
u16 errintsts = sdmmc->regs->errintsts;
DPRINTF("norintsts %08X; errintsts %08X\n", norintsts, errintsts);
DPRINTF("norintsts %08X, errintsts %08X\n", norintsts, errintsts);
if (pout)
*pout = norintsts;
@@ -772,6 +771,9 @@ DPRINTF("norintsts %08X; errintsts %08X\n", norintsts, errintsts);
// Check for error interrupt.
if (norintsts & SDHCI_INT_ERROR)
{
#ifdef ERROR_EXTRA_PRINTING
EPRINTFARGS("SDMMC: norintsts %08X, errintsts %08X\n", norintsts, errintsts);
#endif
sdmmc->regs->errintsts = errintsts;
return SDMMC_MASKINT_ERROR;
}
@@ -963,8 +965,6 @@ static int _sdmmc_execute_cmd_inner(sdmmc_t *sdmmc, sdmmc_cmd_t *cmd, sdmmc_req_
is_data_present = true;
}
else
is_data_present = false;
_sdmmc_enable_interrupts(sdmmc);
@@ -983,7 +983,7 @@ static int _sdmmc_execute_cmd_inner(sdmmc_t *sdmmc, sdmmc_cmd_t *cmd, sdmmc_req_
EPRINTF("SDMMC: Transfer timeout!");
#endif
}
DPRINTF("rsp(%d): %08X, %08X, %08X, %08X\n", result,
DPRINTF("rsp(%d): %08X, %08X, %08X, %08X\n", result,
sdmmc->regs->rspreg0, sdmmc->regs->rspreg1, sdmmc->regs->rspreg2, sdmmc->regs->rspreg3);
if (result)
{
@@ -994,7 +994,7 @@ static int _sdmmc_execute_cmd_inner(sdmmc_t *sdmmc, sdmmc_cmd_t *cmd, sdmmc_req_
if (!result)
{
#ifdef ERROR_EXTRA_PRINTING
EPRINTFARGS("SDMMC: Unknown response %08X!", sdmmc->rsp[0]);
EPRINTF("SDMMC: Unknown response type!");
#endif
}
}
@@ -1004,7 +1004,7 @@ static int _sdmmc_execute_cmd_inner(sdmmc_t *sdmmc, sdmmc_cmd_t *cmd, sdmmc_req_
if (!result)
{
#ifdef ERROR_EXTRA_PRINTING
EPRINTF("SDMMC: DMA Update failed!");
EPRINTFARGS("SDMMC: DMA Update failed (%08X)!", result);
#endif
}
}
@@ -1116,10 +1116,7 @@ static void _sdmmc_config_emmc(u32 id)
case SDMMC_4:
// Unset park for pads.
APB_MISC(APB_MISC_GP_EMMC4_PAD_CFGPADCTRL) &= 0xF8003FFF;
// Set default pad cfg.
APB_MISC(APB_MISC_GP_EMMC4_PAD_CFGPADCTRL) = (APB_MISC(APB_MISC_GP_EMMC4_PAD_CFGPADCTRL) & 0xFFFFC003) | 0x1040;
// Enabled schmitt trigger.
// Enable schmitt trigger.
APB_MISC(APB_MISC_GP_EMMC4_PAD_CFGPADCTRL) |= 1; // Enable Schmitt trigger.
break;
}
@@ -1129,7 +1126,7 @@ int sdmmc_init(sdmmc_t *sdmmc, u32 id, u32 power, u32 bus_width, u32 type, int a
{
const u32 trim_values[] = { 2, 8, 3, 8 };
if (id > SDMMC_4)
if (id > SDMMC_4 || id == SDMMC_3)
return 0;
memset(sdmmc, 0, sizeof(sdmmc_t));
@@ -1294,7 +1291,7 @@ int sdmmc_enable_low_voltage(sdmmc_t *sdmmc)
sdmmc->regs->clkcon |= SDHCI_CLOCK_CARD_EN;
_sdmmc_get_clkcon(sdmmc);
usleep(1000);
if ((sdmmc->regs->prnsts & 0xF00000) == 0xF00000)
if ((sdmmc->regs->prnsts & SDHCI_DATA_LVL_MASK) == SDHCI_DATA_LVL_MASK)
return 1;
}

View File

@@ -195,7 +195,7 @@
#define SDHCI_TIMING_UHS_SDR104 11
#define SDHCI_TIMING_UHS_SDR82 12 // SDR104 with a 163.2MHz -> 81.6MHz clock.
#define SDHCI_TIMING_UHS_DDR50 13
#define SDHCI_TIMING_MMC_DDR52 14
#define SDHCI_TIMING_MMC_HS102 14
#define SDHCI_CAN_64BIT 0x10000000

View File

@@ -38,7 +38,7 @@ void set_fan_duty(u32 duty)
gpio_config(GPIO_PORT_S, GPIO_PIN_7, GPIO_MODE_GPIO);
gpio_output_enable(GPIO_PORT_S, GPIO_PIN_7, GPIO_OUTPUT_DISABLE);
PWM(PWM_CONTROLLER_PWM_CSR_1) = PWM_CSR_EN | (1 << 24); // Max PWM to disable fan.
PWM(PWM_CONTROLLER_PWM_CSR_1) = PWM_CSR_EN | (0x100 << 16); // Max PWM to disable fan.
PINMUX_AUX(PINMUX_AUX_LCD_GPIO2) = 1; // Set source to PWM1.
gpio_config(GPIO_PORT_V, GPIO_PIN_4, GPIO_MODE_SPIO); // Fan power mode.
@@ -55,7 +55,7 @@ void set_fan_duty(u32 duty)
// If disabled send a 0 duty.
if (inv_duty == 236)
{
PWM(PWM_CONTROLLER_PWM_CSR_1) = PWM_CSR_EN | (1 << 24); // Bit 24 is absolute 0%.
PWM(PWM_CONTROLLER_PWM_CSR_1) = PWM_CSR_EN | (0x100 << 16); // Bit 24 is absolute 0%.
regulator_disable_5v(REGULATOR_5V_FAN);
// Disable fan.

View File

@@ -75,7 +75,7 @@ typedef struct _usb_dev_descr_t
u8 bNumConfigs; // Number of possible configuration.
} __attribute__((packed)) usb_dev_descr_t;
/* Device Qualigier descriptor structure */
/* Device Qualifier descriptor structure */
typedef struct _usb_dev_qual_descr_t
{
u8 bLength; // Size of this descriptor in bytes.
@@ -369,7 +369,7 @@ usb_dev_bot_t usb_device_binary_object_descriptor =
.wU2DevExitLat = 0
};
u8 usb_vendor_string_descriptor_ums[32] =
u8 usb_vendor_string_descriptor_ums[32] =
{
26, 0x03,
'N', 0, 'y', 0, 'x', 0, ' ', 0, 'U', 0, 'S', 0, 'B', 0, ' ', 0,

View File

@@ -1523,7 +1523,7 @@ static int received_cbw(usbd_gadget_ums_t *ums, bulk_ctxt_t *bulk_ctxt)
DPRINTF("USB: EP timeout\n");
// In case we disconnected, exit UMS.
// Raise timeout if removable and didn't got a unit ready command inside 4s.
if (bulk_ctxt->bulk_out_status == 28 ||
if (bulk_ctxt->bulk_out_status == 28 ||
(bulk_ctxt->bulk_out_status == 3 && ums->lun.removable && !ums->lun.prevent_medium_removal))
{
if (bulk_ctxt->bulk_out_status == 3)

View File

@@ -1,5 +1,5 @@
/*
* USB driver for Tegra X1
* Enhanced USB (EHCI) device driver for Tegra X1
*
* Copyright (c) 2019 CTCaer
*

View File

@@ -1,5 +1,5 @@
/*
* USB Device driver for Tegra X1
* Enhanced USB (EHCI) Device driver for Tegra X1
*
* Copyright (c) 2019 CTCaer
*
@@ -312,7 +312,7 @@ static void _usb_charger_detect()
gpio_config(GPIO_PORT_V, GPIO_PIN_3, GPIO_MODE_GPIO);
// Configure charger pin.
PINMUX_AUX(PINMUX_AUX_USB_VBUS_EN0) &=
PINMUX_AUX(PINMUX_AUX_USB_VBUS_EN1) &=
~(PINMUX_INPUT_ENABLE | PINMUX_PARKED | PINMUX_TRISTATE | PINMUX_PULL_MASK);
gpio_config(GPIO_PORT_CC, GPIO_PIN_5, GPIO_MODE_GPIO);
gpio_output_enable(GPIO_PORT_CC, GPIO_PIN_5, GPIO_OUTPUT_ENABLE);
@@ -335,10 +335,10 @@ int usb_device_init()
return 0;
// Configure PLLU.
CLOCK(CLK_RST_CONTROLLER_PLLU_MISC) = CLOCK(CLK_RST_CONTROLLER_PLLU_MISC) | 0x20000000; // Disable reference clock.
u32 pllu_cfg = (((((CLOCK(CLK_RST_CONTROLLER_PLLU_BASE) >> 8 << 8) | 2) & 0xFFFF00FF) | ((0x19 << 8) & 0xFFFF)) & 0xFFE0FFFF) | (1<< 16) | 0x1000000;
CLOCK(CLK_RST_CONTROLLER_PLLU_MISC) |= (1 << 29); // Disable reference clock.
u32 pllu_cfg = (((((CLOCK(CLK_RST_CONTROLLER_PLLU_BASE) >> 8 << 8) | 2) & 0xFFFF00FF) | ((0x19 << 8) & 0xFFFF)) & 0xFFE0FFFF) | (1 << 16) | (1 << 24);
CLOCK(CLK_RST_CONTROLLER_PLLU_BASE) = pllu_cfg;
CLOCK(CLK_RST_CONTROLLER_PLLU_BASE) = pllu_cfg | 0x40000000; // Enable.
CLOCK(CLK_RST_CONTROLLER_PLLU_BASE) = pllu_cfg | (1 << 30); // Enable.
// Wait for PLL to stabilize.
u32 timeout = (u32)TMR(TIMERUS_CNTR_1US) + 1300;
@@ -348,18 +348,18 @@ int usb_device_init()
usleep(10);
// Enable PLLU USB/HSIC/ICUSB/48M.
CLOCK(CLK_RST_CONTROLLER_PLLU_BASE) = CLOCK(CLK_RST_CONTROLLER_PLLU_BASE) | 0x2600000 | 0x800000;
CLOCK(CLK_RST_CONTROLLER_PLLU_BASE) |= 0x2E00000;
// Enable USBD clock.
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_SET) = (1 << 22);
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_SET) = BIT(CLK_L_USBD);
usleep(2);
CLOCK(CLK_RST_CONTROLLER_RST_DEV_L_SET) = (1 << 22);
CLOCK(CLK_RST_CONTROLLER_RST_DEV_L_SET) = BIT(CLK_L_USBD);
usleep(2);
CLOCK(CLK_RST_CONTROLLER_RST_DEV_L_CLR) = (1 << 22);
CLOCK(CLK_RST_CONTROLLER_RST_DEV_L_CLR) = BIT(CLK_L_USBD);
usleep(2);
// Clear XUSB_PADCTL reset
CLOCK(CLK_RST_CONTROLLER_RST_DEV_W_CLR) = (1 << 14);
CLOCK(CLK_RST_CONTROLLER_RST_DEV_W_CLR) = BIT(CLK_W_XUSB_PADCTL);
// Enable USB PHY and reset for programming.
u32 usb_susp_ctrl = USB(USB1_IF_USB_SUSP_CTRL);
@@ -419,7 +419,7 @@ int usb_device_init()
// Enable crystal clock.
CLOCK(CLK_RST_CONTROLLER_UTMIP_PLL_CFG2) |= 0x40000000;
// Enable USB2 tracking.
CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_Y) |= 0x40000;
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_Y_SET) = BIT(CLK_Y_USB2_TRK);
CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_USB2_HSIC_TRK) = (CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_USB2_HSIC_TRK) & 0xFFFFFF00) | 6; // Set trank divisor to 4.
USB(USB1_UTMIP_BIAS_CFG1) = (USB(USB1_UTMIP_BIAS_CFG1) & 0xFFC03F07) | 0x78000 | 0x50; // Set delays.
@@ -442,7 +442,7 @@ int usb_device_init()
USB(USB1_UTMIP_BIAS_CFG1) = (USB(USB1_UTMIP_BIAS_CFG1) & 0xFF7FFFFF) | 1;
// Disable USB2_TRK clock and configure UTMIP misc.
CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_Y) &= 0xFFFBFFFF;
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_Y_CLR) = BIT(CLK_Y_USB2_TRK);
CLOCK(CLK_RST_CONTROLLER_UTMIP_PLL_CFG2) = (CLOCK(CLK_RST_CONTROLLER_UTMIP_PLL_CFG2) & 0xFEFFFFEA) | 0x2000000 | 0x28 | 2;
usleep(1);
@@ -535,10 +535,10 @@ static void _usb_device_power_down()
CLOCK(CLK_RST_CONTROLLER_UTMIPLL_HW_PWRDN_CFG0) |= 2;
// Set XUSB_PADCTL reset
CLOCK(CLK_RST_CONTROLLER_RST_DEV_W_SET) = (1 << 14);
CLOCK(CLK_RST_CONTROLLER_RST_DEV_W_SET) = BIT(CLK_W_XUSB_PADCTL);
// Disable USBD clock.
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_CLR) = (1 << 22);
CLOCK(CLK_RST_CONTROLLER_CLK_ENB_L_CLR) = BIT(CLK_L_USBD);
// Completely disable PLLU.
CLOCK(CLK_RST_CONTROLLER_PLLU_BASE) &= ~0x2E00000; // Disable PLLU USB/HSIC/ICUSB/48M.
@@ -930,10 +930,10 @@ out:
_usbd_mark_ep_complete(endpoint);
else if (_usbd_get_ep_status(endpoint) != USB_EP_STATUS_IDLE)
res = 26;
}
if (direction == USB_XFER_DIR_OUT)
bpmp_mmu_maintenance(BPMP_MMU_MAINT_CLN_INV_WAY, false);
if (direction == USB_XFER_DIR_OUT)
bpmp_mmu_maintenance(BPMP_MMU_MAINT_CLN_INV_WAY, false);
}
return res;
}
@@ -1175,17 +1175,17 @@ static int _usbd_handle_ep0_control_transfer()
switch (_bmRequestType)
{
case (USB_SETUP_HOST_TO_DEVICE | USB_SETUP_RECIPIENT_DEVICE | USB_SETUP_TYPE_STANDARD):
case (USB_SETUP_HOST_TO_DEVICE | USB_SETUP_TYPE_STANDARD | USB_SETUP_RECIPIENT_DEVICE):
ret = _usbd_handle_set_request(&ep_stall);
break;
case (USB_SETUP_HOST_TO_DEVICE | USB_SETUP_RECIPIENT_INTERFACE | USB_SETUP_TYPE_STANDARD):
case (USB_SETUP_HOST_TO_DEVICE | USB_SETUP_TYPE_STANDARD | USB_SETUP_RECIPIENT_INTERFACE):
ret = _usbd_ep_ack(USB_EP_CTRL_IN);
if (!ret)
usbd_otg->interface = _wValue;
break;
case (USB_SETUP_HOST_TO_DEVICE | USB_SETUP_RECIPIENT_ENDPOINT | USB_SETUP_TYPE_STANDARD):
case (USB_SETUP_HOST_TO_DEVICE | USB_SETUP_TYPE_STANDARD | USB_SETUP_RECIPIENT_ENDPOINT):
switch (_bRequest)
{
case USB_REQUEST_CLEAR_FEATURE:
@@ -1227,10 +1227,12 @@ static int _usbd_handle_ep0_control_transfer()
break;
}
break;
case (USB_SETUP_HOST_TO_DEVICE | USB_SETUP_RECIPIENT_INTERFACE | USB_SETUP_TYPE_CLASS):
case (USB_SETUP_HOST_TO_DEVICE | USB_SETUP_TYPE_CLASS | USB_SETUP_RECIPIENT_INTERFACE):
_usbd_handle_get_class_request(&transmit_data, descriptor, &size, &ep_stall);
break;
case (USB_SETUP_DEVICE_TO_HOST | USB_SETUP_RECIPIENT_DEVICE | USB_SETUP_TYPE_STANDARD):
case (USB_SETUP_DEVICE_TO_HOST | USB_SETUP_TYPE_STANDARD | USB_SETUP_RECIPIENT_DEVICE):
switch (_bRequest)
{
case USB_REQUEST_GET_STATUS:
@@ -1253,7 +1255,7 @@ static int _usbd_handle_ep0_control_transfer()
}
break;
case (USB_SETUP_DEVICE_TO_HOST | USB_SETUP_RECIPIENT_INTERFACE | USB_SETUP_TYPE_STANDARD):
case (USB_SETUP_DEVICE_TO_HOST | USB_SETUP_TYPE_STANDARD | USB_SETUP_RECIPIENT_INTERFACE):
if (_bRequest == USB_REQUEST_GET_INTERFACE)
{
descriptor = (void *)&usbd_otg->interface;
@@ -1287,7 +1289,7 @@ static int _usbd_handle_ep0_control_transfer()
transmit_data = 1;
break;
case (USB_SETUP_DEVICE_TO_HOST | USB_SETUP_RECIPIENT_ENDPOINT | USB_SETUP_TYPE_STANDARD):
case (USB_SETUP_DEVICE_TO_HOST | USB_SETUP_TYPE_STANDARD | USB_SETUP_RECIPIENT_ENDPOINT):
if (_bRequest == USB_REQUEST_GET_STATUS)
{
int ep_req;
@@ -1324,14 +1326,15 @@ static int _usbd_handle_ep0_control_transfer()
_usbd_stall_reset_ep1(3, USB_EP_CFG_STALL);
break;
case (USB_SETUP_DEVICE_TO_HOST | USB_SETUP_RECIPIENT_INTERFACE | USB_SETUP_TYPE_CLASS):
case (USB_SETUP_DEVICE_TO_HOST | USB_SETUP_TYPE_CLASS | USB_SETUP_RECIPIENT_INTERFACE):
memset(descriptor, 0, _wLength);
_usbd_handle_get_class_request(&transmit_data, descriptor, &size, &ep_stall);
size = _wLength;
break;
case (USB_SETUP_DEVICE_TO_HOST | USB_SETUP_RECIPIENT_INTERFACE | USB_SETUP_TYPE_VENDOR):
case (USB_SETUP_DEVICE_TO_HOST | USB_SETUP_RECIPIENT_DEVICE | USB_SETUP_TYPE_VENDOR):
case (USB_SETUP_DEVICE_TO_HOST | USB_SETUP_TYPE_VENDOR | USB_SETUP_RECIPIENT_INTERFACE):
case (USB_SETUP_DEVICE_TO_HOST | USB_SETUP_TYPE_VENDOR | USB_SETUP_RECIPIENT_DEVICE):
if (_bRequest == USB_REQUEST_GET_MS_DESCRIPTOR)
{
switch (_wIndex)
@@ -1565,6 +1568,8 @@ int usb_device_ep1_out_reading_finish(u32 *pending_bytes)
*pending_bytes = _usbd_get_ep1_out_bytes_read();
bpmp_mmu_maintenance(BPMP_MMU_MAINT_CLN_INV_WAY, false);
if (ep_status == USB_EP_STATUS_IDLE)
return 0;
else if (ep_status == USB_EP_STATUS_DISABLED)

View File

@@ -1,5 +1,5 @@
/*
* USB Device driver for Tegra X1
* Enhanced USB (EHCI) Device driver for Tegra X1
*
* Copyright (c) 2019 CTCaer
*

View File

@@ -65,11 +65,6 @@ static void _s_putn(u32 v, int base, char fill, int fcnt)
_s_puts(p);
}
static void _s_putp(u32 *v, int base, char fill, int fcnt)
{
_s_putn(*v, base, fill, fcnt);
}
void s_printf(char *out_buf, const char *fmt, ...)
{
va_list ap;
@@ -114,8 +109,6 @@ void s_printf(char *out_buf, const char *fmt, ...)
break;
case 'p':
case 'P':
_s_putp(va_arg(ap, u32*), 16, fill, fcnt);
break;
case 'x':
case 'X':
_s_putn(va_arg(ap, u32), 16, fill, fcnt);

View File

@@ -21,6 +21,7 @@
#define ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1))
#define ALIGN_DOWN(x, a) (((x) - ((a) - 1)) & ~((a) - 1))
#define BIT(n) (1U << (n))
#define MAX(a, b) ((a) > (b) ? (a) : (b))
#define MIN(a, b) ((a) < (b) ? (a) : (b))

View File

@@ -135,7 +135,7 @@ void panic(u32 val)
void reboot_normal()
{
sd_end();
reconfig_hw_workaround(false, 0);
hw_reinit_workaround(false, 0);
panic(0x21); // Bypass fuse programming in package1.
}
@@ -143,7 +143,7 @@ void reboot_normal()
void reboot_rcm()
{
sd_end();
reconfig_hw_workaround(false, 0);
hw_reinit_workaround(false, 0);
PMC(APBDEV_PMC_SCRATCH0) = PMC_SCRATCH0_MODE_RCM;
PMC(APBDEV_PMC_CNTRL) |= PMC_CNTRL_MAIN_RST;
@@ -155,7 +155,7 @@ void reboot_rcm()
void power_off()
{
sd_end();
reconfig_hw_workaround(false, 0);
hw_reinit_workaround(false, 0);
// Stop the alarm, in case we injected and powered off too fast.
max77620_rtc_stop_alarm();

View File

@@ -32,8 +32,10 @@ typedef enum
{
ERR_LIBSYS_LP0 = (1 << 0),
ERR_SYSOLD_NYX = (1 << 1),
ERR_SYSOLD_MTC = (1 << 2),
ERR_EXCEPT_ENB = (1 << 31),
ERR_LIBSYS_MTC = (1 << 2),
ERR_SD_BOOT_EN = (1 << 3),
ERR_L4T_KERNEL = (1 << 24),
ERR_EXCEPTION = (1 << 31),
} hekate_errors_t;
#define byte_swap_32(num) (((num >> 24) & 0xff) | ((num << 8) & 0xff0000) | \

View File

@@ -42,8 +42,7 @@ void set_default_configuration()
h_cfg.autohosoff = 0;
h_cfg.autonogc = 1;
h_cfg.updater2p = 0;
h_cfg.brand = NULL;
h_cfg.tagline = NULL;
h_cfg.bootprotect = 0;
h_cfg.errors = 0;
h_cfg.eks = NULL;
h_cfg.sept_run = EMC(EMC_SCRATCH0) & EMC_SEPT_RUN;
@@ -107,16 +106,9 @@ int create_config_entry()
f_puts("\nupdater2p=", &fp);
itoa(h_cfg.updater2p, lbuf, 10);
f_puts(lbuf, &fp);
if (h_cfg.brand)
{
f_puts("\nbrand=", &fp);
f_puts(h_cfg.brand, &fp);
}
if (h_cfg.tagline)
{
f_puts("\ntagline=", &fp);
f_puts(h_cfg.tagline, &fp);
}
f_puts("\nbootprotect=", &fp);
itoa(h_cfg.bootprotect, lbuf, 10);
f_puts(lbuf, &fp);
f_puts("\n", &fp);
if (mainIniFound)

View File

@@ -30,8 +30,7 @@ typedef struct _hekate_config
u32 autohosoff;
u32 autonogc;
u32 updater2p;
char *brand;
char *tagline;
u32 bootprotect;
// Global temporary config.
bool se_keygen_done;
bool sept_run;

View File

@@ -270,7 +270,7 @@ void print_sdcard_info()
gfx_clear_partial_grey(0x1B, 0, 1256);
gfx_con_setpos(0, 0);
if (sd_mount())
if (sd_initialize(true))
{
gfx_printf("%kCard IDentification:%k\n", 0xFF00DDFF, 0xFFCCCCCC);
gfx_printf(
@@ -287,6 +287,7 @@ void print_sdcard_info()
sd_storage.cid.hwrev, sd_storage.cid.fwrev, sd_storage.cid.serial,
sd_storage.cid.month, sd_storage.cid.year);
u16 *sd_errors = sd_get_error_count();
gfx_printf("%kCard-Specific Data V%d.0:%k\n", 0xFF00DDFF, sd_storage.csd.structure + 1, 0xFFCCCCCC);
gfx_printf(
" Cmd Classes: %02X\n"
@@ -297,18 +298,39 @@ void print_sdcard_info()
" UHS Grade: U%d\n"
" Video Class: V%d\n"
" App perf class: A%d\n"
" Write Protect: %d\n\n",
" Write Protect: %d\n"
" SDMMC Errors: %d %d %d\n\n",
sd_storage.csd.cmdclass, sd_storage.sec_cnt >> 11,
sd_storage.ssr.bus_width, sd_storage.csd.busspeed, sd_storage.csd.busspeed * 2,
sd_storage.ssr.speed_class, sd_storage.ssr.uhs_grade, sd_storage.ssr.video_class,
sd_storage.ssr.app_class, sd_storage.csd.write_protect);
sd_storage.ssr.app_class, sd_storage.csd.write_protect,
sd_errors[0], sd_errors[1], sd_errors[2]); // SD_ERROR_INIT_FAIL, SD_ERROR_RW_FAIL, SD_ERROR_RW_RETRY.
gfx_puts("Acquiring FAT volume info...\n\n");
f_getfree("", &sd_fs.free_clst, NULL);
gfx_printf("%kFound %s volume:%k\n Free: %d MiB\n Cluster: %d KiB\n",
0xFF00DDFF, sd_fs.fs_type == FS_EXFAT ? "exFAT" : "FAT32", 0xFFCCCCCC,
sd_fs.free_clst * sd_fs.csize >> SECTORS_TO_MIB_COEFF, (sd_fs.csize > 1) ? (sd_fs.csize >> 1) : 512);
sd_end();
int res = f_mount(&sd_fs, "", 1);
if (!res)
{
gfx_puts("Acquiring FAT volume info...\n\n");
f_getfree("", &sd_fs.free_clst, NULL);
gfx_printf("%kFound %s volume:%k\n Free: %d MiB\n Cluster: %d KiB\n",
0xFF00DDFF, sd_fs.fs_type == FS_EXFAT ? "exFAT" : "FAT32", 0xFFCCCCCC,
sd_fs.free_clst * sd_fs.csize >> SECTORS_TO_MIB_COEFF, (sd_fs.csize > 1) ? (sd_fs.csize >> 1) : 512);
f_mount(NULL, "", 1);
}
else
{
EPRINTFARGS("Failed to mount SD card (FatFS Error %d).\n"
"Make sure that a FAT partition exists..", res);
}
sdmmc_storage_end(&sd_storage);
}
else
{
EPRINTF("Failed to init SD card.");
if (!sdmmc_get_sd_inserted())
EPRINTF("Make sure that it is inserted.");
else
EPRINTF("SD Card Reader is not properly seated!");
}
btn_wait();

View File

@@ -88,7 +88,6 @@ void dump_packages12()
goto out_free;
}
const pk11_hdr_t *hdr = (pk11_hdr_t *)(pkg1 + pkg1_id->pkg11_off + 0x20);
kb = pkg1_id->kb;
@@ -130,16 +129,30 @@ void dump_packages12()
if (kb <= KB_FIRMWARE_VERSION_620)
{
pkg1_unpack(warmboot, secmon, loader, pkg1_id, pkg1);
const u8 *sec_map = pkg1_unpack(warmboot, secmon, loader, pkg1_id, pkg1);
pk11_hdr_t *hdr_pk11 = (pk11_hdr_t *)(pkg1 + pkg1_id->pkg11_off + 0x20);
// Use correct sizes.
u32 sec_size[3] = { hdr_pk11->wb_size, hdr_pk11->ldr_size, hdr_pk11->sm_size };
for (u32 i = 0; i < 3; i++)
{
if (sec_map[i] == PK11_SECTION_WB)
hdr_pk11->wb_size = sec_size[i];
else if (sec_map[i] == PK11_SECTION_LD)
hdr_pk11->ldr_size = sec_size[i];
else if (sec_map[i] == PK11_SECTION_SM)
hdr_pk11->sm_size = sec_size[i];
}
// Display info.
gfx_printf("%kNX Bootloader size: %k0x%05X\n\n", 0xFFC7EA46, 0xFFCCCCCC, hdr->ldr_size);
gfx_printf("%kNX Bootloader size: %k0x%05X\n\n", 0xFFC7EA46, 0xFFCCCCCC, hdr_pk11->ldr_size);
gfx_printf("%kSecure monitor addr: %k0x%05X\n", 0xFFC7EA46, 0xFFCCCCCC, pkg1_id->secmon_base);
gfx_printf("%kSecure monitor size: %k0x%05X\n\n", 0xFFC7EA46, 0xFFCCCCCC, hdr->sm_size);
gfx_printf("%kSecure monitor size: %k0x%05X\n\n", 0xFFC7EA46, 0xFFCCCCCC, hdr_pk11->sm_size);
gfx_printf("%kWarmboot addr: %k0x%05X\n", 0xFFC7EA46, 0xFFCCCCCC, pkg1_id->warmboot_base);
gfx_printf("%kWarmboot size: %k0x%05X\n\n", 0xFFC7EA46, 0xFFCCCCCC, hdr->wb_size);
gfx_printf("%kWarmboot size: %k0x%05X\n\n", 0xFFC7EA46, 0xFFCCCCCC, hdr_pk11->wb_size);
// Dump package1.1.
emmcsn_path_impl(path, "/pkg1", "pkg1_decr.bin", &storage);
@@ -149,19 +162,19 @@ void dump_packages12()
// Dump nxbootloader.
emmcsn_path_impl(path, "/pkg1", "nxloader.bin", &storage);
if (sd_save_to_file(loader, hdr->ldr_size, path))
if (sd_save_to_file(loader, hdr_pk11->ldr_size, path))
goto out_free;
gfx_puts("NX Bootloader dumped to nxloader.bin\n");
// Dump secmon.
emmcsn_path_impl(path, "/pkg1", "secmon.bin", &storage);
if (sd_save_to_file(secmon, hdr->sm_size, path))
if (sd_save_to_file(secmon, hdr_pk11->sm_size, path))
goto out_free;
gfx_puts("Secure Monitor dumped to secmon.bin\n");
// Dump warmboot.
emmcsn_path_impl(path, "/pkg1", "warmboot.bin", &storage);
if (sd_save_to_file(warmboot, hdr->wb_size, path))
if (sd_save_to_file(warmboot, hdr_pk11->wb_size, path))
goto out_free;
gfx_puts("Warmboot dumped to warmboot.bin\n\n\n");
}

View File

@@ -111,6 +111,7 @@ int parse_fss(launch_ctxt_t *ctxt, const char *path, fss0_sept_t *sept_ctxt)
bool stock = false;
int sept_used = 0;
// Skip if stock and Exosphere and warmboot are not needed.
if (!sept_ctxt)
{
LIST_FOREACH_ENTRY(ini_kv_t, kv, &ctxt->cfg->kvs, link)
@@ -120,7 +121,8 @@ int parse_fss(launch_ctxt_t *ctxt, const char *path, fss0_sept_t *sept_ctxt)
stock = true;
}
if (stock && ctxt->pkg1_id->kb <= KB_FIRMWARE_VERSION_620 && (!emu_cfg.enabled || h_cfg.emummc_force_disable))
bool emummc_disabled = !emu_cfg.enabled || h_cfg.emummc_force_disable;
if (stock && ctxt->pkg1_id->kb <= KB_FIRMWARE_VERSION_620 && emummc_disabled)
return 1;
}
@@ -163,7 +165,7 @@ int parse_fss(launch_ctxt_t *ctxt, const char *path, fss0_sept_t *sept_ctxt)
continue;
// If content is experimental and experimental flag is not enabled, skip it.
if ((curr_fss_cnt[i].flags0 & CNT_FLAG0_EXPERIMENTAL) && !ctxt->fss0_enable_experimental)
if ((curr_fss_cnt[i].flags0 & CNT_FLAG0_EXPERIMENTAL) && !ctxt->fss0_experimental)
continue;
// Parse content.
@@ -188,6 +190,10 @@ int parse_fss(launch_ctxt_t *ctxt, const char *path, fss0_sept_t *sept_ctxt)
ctxt->warmboot_size = curr_fss_cnt[i].size;
ctxt->warmboot = content;
break;
case CNT_TYPE_KRN:
ctxt->kernel_size = curr_fss_cnt[i].size;
ctxt->kernel = content;
break;
default:
continue;
}

View File

@@ -59,6 +59,9 @@ extern hekate_config h_cfg;
#define PKG2_LOAD_ADDR 0xA9800000
#define SECMON_BCT_CFG_ADDR 0x4003D000
#define SECMON6_BCT_CFG_ADDR 0x4003F800
// Secmon mailbox.
#define SECMON_MAILBOX_ADDR 0x40002E00
#define SECMON7_MAILBOX_ADDR 0x40000000
@@ -87,21 +90,21 @@ static const u8 cmac_keyseed[0x10] =
static const u8 master_keyseed_retail[0x10] =
{ 0xD8, 0xA2, 0x41, 0x0A, 0xC6, 0xC5, 0x90, 0x01, 0xC6, 0x1D, 0x6A, 0x26, 0x7C, 0x51, 0x3F, 0x3C };
static const u8 console_keyseed[0x10] =
{ 0x4F, 0x02, 0x5F, 0x0E, 0xB6, 0x6D, 0x11, 0x0E, 0xDC, 0x32, 0x7D, 0x41, 0x86, 0xC2, 0xF4, 0x78 };
const u8 package2_keyseed[0x10] =
{ 0xFB, 0x8B, 0x6A, 0x9C, 0x79, 0x00, 0xC8, 0x49, 0xEF, 0xD2, 0x4D, 0x85, 0x4D, 0x30, 0xA0, 0xC7 };
static const u8 master_keyseed_4xx_5xx_610[0x10] =
{ 0x2D, 0xC1, 0xF4, 0x8D, 0xF3, 0x5B, 0x69, 0x33, 0x42, 0x10, 0xAC, 0x65, 0xDA, 0x90, 0x46, 0x66 };
static const u8 master_keyseed_620[0x10] =
{ 0x37, 0x4B, 0x77, 0x29, 0x59, 0xB4, 0x04, 0x30, 0x81, 0xF6, 0xE5, 0x8C, 0x6D, 0x36, 0x17, 0x9A };
static const u8 console_keyseed[0x10] =
{ 0x4F, 0x02, 0x5F, 0x0E, 0xB6, 0x6D, 0x11, 0x0E, 0xDC, 0x32, 0x7D, 0x41, 0x86, 0xC2, 0xF4, 0x78 };
static const u8 console_keyseed_4xx_5xx[0x10] =
{ 0x0C, 0x91, 0x09, 0xDB, 0x93, 0x93, 0x07, 0x81, 0x07, 0x3C, 0xC4, 0x16, 0x22, 0x7C, 0x6C, 0x28 };
const u8 package2_keyseed[0x10] =
{ 0xFB, 0x8B, 0x6A, 0x9C, 0x79, 0x00, 0xC8, 0x49, 0xEF, 0xD2, 0x4D, 0x85, 0x4D, 0x30, 0xA0, 0xC7 };
static void _hos_crit_error(const char *text)
{
gfx_con.mute = false;
@@ -214,7 +217,7 @@ void hos_eks_get()
goto out;
// Decrypt EKS blob.
hos_eks_mbr_t *eks = (hos_eks_mbr_t *)(mbr + 0x60);
hos_eks_mbr_t *eks = (hos_eks_mbr_t *)(mbr + 0x80);
se_aes_crypt_ecb(14, 0, eks, sizeof(hos_eks_mbr_t), eks, sizeof(hos_eks_mbr_t));
// Check if valid and for this unit.
@@ -266,6 +269,10 @@ void hos_eks_save(u32 kb)
u8 *keys = (u8 *)calloc(0x1000, 1);
se_get_aes_keys(keys + 0x800, keys, 0x10);
// Set SBK back.
if (FUSE(FUSE_PRIVATE_KEY0) == 0xFFFFFFFF)
se_aes_key_set(14, keys + 14 * 0x10, 0x10);
// Set magic and personalized info.
h_cfg.eks->magic = HOS_EKS_MAGIC;
h_cfg.eks->enabled[key_idx] = kb;
@@ -292,7 +299,7 @@ void hos_eks_save(u32 kb)
se_aes_crypt_ecb(14, 1, eks, sizeof(hos_eks_mbr_t), eks, sizeof(hos_eks_mbr_t));
// Write EKS blob to SD.
memcpy(mbr + 0x60, eks, sizeof(hos_eks_mbr_t));
memcpy(mbr + 0x80, eks, sizeof(hos_eks_mbr_t));
hos_eks_rw_try(mbr, true);
@@ -329,7 +336,7 @@ void hos_eks_clear(u32 kb)
se_aes_crypt_ecb(14, 1, eks, sizeof(hos_eks_mbr_t), eks, sizeof(hos_eks_mbr_t));
// Write EKS blob to SD.
memcpy(mbr + 0x60, eks, sizeof(hos_eks_mbr_t));
memcpy(mbr + 0x80, eks, sizeof(hos_eks_mbr_t));
hos_eks_rw_try(mbr, true);
EMC(EMC_SCRATCH0) &= ~EMC_SEPT_RUN;
@@ -540,23 +547,41 @@ int hos_keygen(u8 *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt, launch_ctxt_t *hos_c
static int _read_emmc_pkg1(launch_ctxt_t *ctxt)
{
static const u32 BOOTLOADER_SIZE = 0x40000;
static const u32 BOOTLOADER_MAIN_OFFSET = 0x100000;
static const u32 BOOTLOADER_BACKUP_OFFSET = 0x140000;
static const u32 HOS_KEYBLOBS_OFFSET = 0x180000;
u32 bootloader_offset = BOOTLOADER_MAIN_OFFSET;
ctxt->pkg1 = (void *)malloc(BOOTLOADER_SIZE);
try_load:
// Read package1.
ctxt->pkg1 = (void *)malloc(0x40000);
emummc_storage_set_mmc_partition(&emmc_storage, EMMC_BOOT0);
emummc_storage_read(&emmc_storage, 0x100000 / NX_EMMC_BLOCKSIZE, 0x40000 / NX_EMMC_BLOCKSIZE, ctxt->pkg1);
emummc_storage_read(&emmc_storage, bootloader_offset / NX_EMMC_BLOCKSIZE, BOOTLOADER_SIZE / NX_EMMC_BLOCKSIZE, ctxt->pkg1);
ctxt->pkg1_id = pkg1_identify(ctxt->pkg1);
if (!ctxt->pkg1_id)
{
_hos_crit_error("Unknown pkg1 version.");
EHPRINTFARGS("HOS version not supported!%s",
EPRINTFARGS("HOS version not supported!%s",
(emu_cfg.enabled && !h_cfg.emummc_force_disable) ? "\nOr emuMMC corrupt!" : "");
// Try backup bootloader.
if (bootloader_offset != BOOTLOADER_BACKUP_OFFSET)
{
EPRINTF("Trying backup bootloader...");
bootloader_offset = BOOTLOADER_BACKUP_OFFSET;
goto try_load;
}
return 0;
}
gfx_printf("Identified pkg1 and Keyblob %d\n\n", ctxt->pkg1_id->kb);
gfx_printf("Identified pkg1 and mkey %d\n\n", ctxt->pkg1_id->kb);
// Read the correct keyblob.
ctxt->keyblob = (u8 *)calloc(NX_EMMC_BLOCKSIZE, 1);
emummc_storage_read(&emmc_storage, 0x180000 / NX_EMMC_BLOCKSIZE + ctxt->pkg1_id->kb, 1, ctxt->keyblob);
emummc_storage_read(&emmc_storage, HOS_KEYBLOBS_OFFSET / NX_EMMC_BLOCKSIZE + ctxt->pkg1_id->kb, 1, ctxt->keyblob);
return 1;
}
@@ -630,20 +655,26 @@ static bool _get_fs_exfat_compatible(link_t *info, bool *fs_is_510)
pkg2_get_ids(&kip_ids, &fs_ids_cnt);
for (fs_idx = 0; fs_idx < fs_ids_cnt; fs_idx++)
{
if (!memcmp(sha_buf, kip_ids[fs_idx].hash, 8))
{
// Check if it's 5.1.0.
if ((fs_idx & ~1) == 16)
*fs_is_510 = true;
// Check if FAT32-only.
if (fs_ids_cnt <= fs_idx && !(fs_idx & 1))
return false;
// FS is FAT32 + exFAT.
break;
// Check if it's 5.1.0.
if ((fs_idx & ~1) == 16)
*fs_is_510 = true;
// Return false if FAT32 only.
if (fs_ids_cnt <= fs_idx && !(fs_idx & 1))
return false;
}
}
break;
}
// Hash didn't match or FAT32 + exFAT.
return true;
}
@@ -695,8 +726,10 @@ int hos_launch(ini_sec_t *cfg)
goto error;
}
bool emummc_enabled = emu_cfg.enabled && !h_cfg.emummc_force_disable;
// Enable emummc patching.
if (emu_cfg.enabled && !h_cfg.emummc_force_disable)
if (emummc_enabled)
{
if (ctxt.stock)
{
@@ -721,7 +754,7 @@ int hos_launch(ini_sec_t *cfg)
if ((h_cfg.autonogc &&
((!(fuses & ~0xF) && (kb >= KB_FIRMWARE_VERSION_400)) || // LAFW v2.
(!(fuses & ~0x3FF) && (kb >= KB_FIRMWARE_VERSION_900)))) // LAFW v3.
|| ((emu_cfg.enabled && !h_cfg.emummc_force_disable) &&
|| ((emummc_enabled) &&
((fuses & 0x400) && (kb <= KB_FIRMWARE_VERSION_810))))
config_kip1patch(&ctxt, "nogc");
}
@@ -763,7 +796,7 @@ int hos_launch(ini_sec_t *cfg)
if (kb <= KB_FIRMWARE_VERSION_600)
pkg1_decrypt(ctxt.pkg1_id, ctxt.pkg1);
if (kb <= KB_FIRMWARE_VERSION_620 && !(emu_cfg.enabled && !h_cfg.emummc_force_disable))
if (kb <= KB_FIRMWARE_VERSION_620 && !emummc_enabled)
{
pkg1_unpack((void *)ctxt.pkg1_id->warmboot_base, (void *)ctxt.pkg1_id->secmon_base, NULL, ctxt.pkg1_id, ctxt.pkg1);
gfx_puts("Decrypted & unpacked pkg1\n");
@@ -780,6 +813,7 @@ int hos_launch(ini_sec_t *cfg)
memcpy((void *)warmboot_base, ctxt.warmboot, ctxt.warmboot_size);
else
{
// Patch warmboot on T210 to allow downgrading.
if (kb >= KB_FIRMWARE_VERSION_700)
{
_hos_crit_error("No warmboot provided!");
@@ -792,10 +826,10 @@ int hos_launch(ini_sec_t *cfg)
*(vu32 *)(ctxt.pkg1_id->warmboot_base + warmboot_patchset[i].off) = warmboot_patchset[i].val;
}
// Set warmboot address in PMC if required.
if (ctxt.pkg1_id->set_warmboot)
if (kb <= KB_FIRMWARE_VERSION_301)
PMC(APBDEV_PMC_SCRATCH1) = warmboot_base;
// Replace 'SecureMonitor' if requested.
// Replace 'SecureMonitor' if requested or patch Pkg2 checks if needed.
if (ctxt.secmon)
memcpy((void *)secmon_base, ctxt.secmon, ctxt.secmon_size);
else if (ctxt.pkg1_id->secmon_patchset)
@@ -824,13 +858,11 @@ int hos_launch(ini_sec_t *cfg)
if (!pkg2_hdr)
{
_hos_crit_error("Pkg2 decryption failed!");
if (kb >= KB_FIRMWARE_VERSION_700)
{
EPRINTF("Is Sept updated?");
EPRINTFARGS("Is hekate%s updated?", kb >= KB_FIRMWARE_VERSION_700 ? " or Sept" : "");
// Clear EKS slot, in case something went wrong with sept keygen.
// Clear EKS slot, in case something went wrong with sept keygen.
if (kb >= KB_FIRMWARE_VERSION_700)
hos_eks_clear(kb);
}
goto error;
}
else if (kb >= KB_FIRMWARE_VERSION_700)
@@ -853,8 +885,8 @@ int hos_launch(ini_sec_t *cfg)
if (!ctxt.stock && (ctxt.svcperm || ctxt.debugmode || ctxt.atmosphere))
{
u8 kernel_hash[0x20];
// Hash only Kernel when it embeds INI1.
u8 kernel_hash[0x20];
if (!ctxt.new_pkg2)
se_calc_sha256_oneshot(kernel_hash, ctxt.kernel, ctxt.kernel_size);
else
@@ -919,11 +951,14 @@ int hos_launch(ini_sec_t *cfg)
{
EHPRINTFARGS("Failed to apply '%s'!", unappliedPatch);
gfx_puts("\nPress POWER to continue.\nPress VOL to go to the menu.\n");
display_backlight_brightness(h_cfg.backlight, 1000);
bool emmc_patch_failed = !strcmp(unappliedPatch, "emummc");
if (!emmc_patch_failed)
{
gfx_puts("\nPress POWER to continue.\nPress VOL to go to the menu.\n");
display_backlight_brightness(h_cfg.backlight, 1000);
}
u32 btn = btn_wait();
if (!(btn & BTN_POWER))
if (emmc_patch_failed || !(btn_wait() & BTN_POWER))
{
_free_launch_components(&ctxt);
goto error; // MUST stop here, because if user requests 'nogc' but it's not applied, their GC controller gets updated!
@@ -931,16 +966,12 @@ int hos_launch(ini_sec_t *cfg)
}
// Rebuild and encrypt package2.
pkg2_build_encrypt((void *)PKG2_LOAD_ADDR, ctxt.kernel, ctxt.kernel_size, &kip1_info, ctxt.new_pkg2, kb);
pkg2_build_encrypt((void *)PKG2_LOAD_ADDR, &ctxt, &kip1_info);
gfx_puts("Rebuilt & loaded pkg2\n");
gfx_printf("\n%kBooting...%k\n", 0xFF96FF00, 0xFFCCCCCC);
// Clear pkg1/pkg2 keys.
se_aes_key_clear(8);
se_aes_key_clear(11);
// Set initial mailbox values.
int bootStateDramPkg2 = 0;
int bootStatePkg2Continue = 0;
@@ -951,6 +982,10 @@ int hos_launch(ini_sec_t *cfg)
else if (kb == KB_FIRMWARE_VERSION_301)
PMC(APBDEV_PMC_SECURE_SCRATCH32) = 0x104; // Warmboot 3.0.1/.2 PA address id.
// Clear pkg1/pkg2 keys.
se_aes_key_clear(8);
se_aes_key_clear(11);
// Finalize per firmware key access. Skip access control if new exosphere.
switch (kb | (exo_new << 7))
{
@@ -976,15 +1011,15 @@ int hos_launch(ini_sec_t *cfg)
// Clear BCT area for retail units and copy it over if dev unit.
if (kb <= KB_FIRMWARE_VERSION_500 && !exo_new)
{
memset((void *)0x4003D000, 0, 0x3000);
memset((void *)SECMON_BCT_CFG_ADDR, 0, 0x3000);
if ((fuse_read_odm(4) & 3) == 3)
memcpy((void *)0x4003D000, bootConfigBuf, 0x1000);
memcpy((void *)SECMON_BCT_CFG_ADDR, bootConfigBuf, 0x1000);
}
else
{
memset((void *)0x4003F800, 0, 0x800);
memset((void *)SECMON6_BCT_CFG_ADDR, 0, 0x800);
if ((fuse_read_odm(4) & 3) == 3)
memcpy((void *)0x4003F800, bootConfigBuf, 0x800);
memcpy((void *)SECMON6_BCT_CFG_ADDR, bootConfigBuf, 0x800);
}
free(bootConfigBuf);
@@ -997,7 +1032,7 @@ int hos_launch(ini_sec_t *cfg)
sdmmc_storage_end(&emmc_storage);
// Finalize MC carveout.
if (kb <= KB_FIRMWARE_VERSION_301)
if (kb <= KB_FIRMWARE_VERSION_301 && !exo_new)
mc_config_carveout();
// Lock SE before starting 'SecureMonitor' if < 6.2.0, otherwise lock bootrom and ipatches.
@@ -1033,8 +1068,9 @@ int hos_launch(ini_sec_t *cfg)
// Clear EMC_SCRATCH0.
EMC(EMC_SCRATCH0) = 0;
// Hold USBD in reset for SoC state validation on sleep.
CLOCK(CLK_RST_CONTROLLER_RST_DEVICES_L) |= 0x400000;
// Hold USBD, USB2, AHBDMA and APBDMA in reset for SoC state validation on sleep.
CLOCK(CLK_RST_CONTROLLER_RST_DEV_L_SET) = BIT(CLK_L_USBD);
CLOCK(CLK_RST_CONTROLLER_RST_DEV_H_SET) = BIT(CLK_H_AHBDMA) | BIT(CLK_H_APBDMA) | BIT(CLK_H_USB2);
// Flush cache and disable MMU.
bpmp_mmu_disable();
@@ -1043,13 +1079,15 @@ int hos_launch(ini_sec_t *cfg)
// emuMMC: Some cards (Sandisk U1), do not like a fast power cycle. Wait min 100ms.
sdmmc_storage_init_wait_sd();
// Wait for secmon to get ready.
// Launch secmon.
if (smmu_is_used())
smmu_exit();
else
ccplex_boot_cpu0(secmon_base);
// Wait for secmon to get ready.
while (!secmon_mailbox->out)
; // A usleep(1) only works when in IRAM or with a trained DRAM.
;
// Signal pkg2 ready and continue boot.
secmon_mailbox->in = bootStatePkg2Continue;

View File

@@ -66,17 +66,17 @@ typedef struct _hos_eks_bis_keys_t
typedef struct _hos_eks_mbr_t
{
u32 magic;
u8 enabled[6];
u8 enabled[5];
u8 enabled_bis;
u8 rsvd;
u8 rsvd[2];
u32 sbk_low;
u8 dkg[0x10];
u8 dkk[0x10];
hos_eks_keys_t keys[6];
hos_eks_keys_t keys[5];
hos_eks_bis_keys_t bis_keys[3];
} hos_eks_mbr_t;
static_assert(sizeof(hos_eks_mbr_t) == 336, "HOS EKS size is wrong!");
static_assert(sizeof(hos_eks_mbr_t) == 304, "HOS EKS size is wrong!");
typedef struct _launch_ctxt_t
{
@@ -97,6 +97,7 @@ typedef struct _launch_ctxt_t
void *kernel;
u32 kernel_size;
link_t kip1_list;
char* kip1_patches;
@@ -105,7 +106,7 @@ typedef struct _launch_ctxt_t
bool debugmode;
bool stock;
bool atmosphere;
bool fss0_enable_experimental;
bool fss0_experimental;
bool emummc_forced;
exo_ctxt_t exo_ctx;

View File

@@ -253,7 +253,7 @@ static int _config_fss(launch_ctxt_t *ctxt, const char *value)
{
if (!strcmp("fss0experimental", kv->key))
{
ctxt->fss0_enable_experimental = *kv->val == '1';
ctxt->fss0_experimental = *kv->val == '1';
break;
}
}

View File

@@ -19,45 +19,45 @@
#include <string.h>
#include "hos.h"
#include "pkg1.h"
#include <gfx_utils.h>
#include <mem/heap.h>
#include <sec/se.h>
#include <utils/aarch64_util.h>
#define _NOPv7() 0xE320F000
#define SM_100_ADR 0x4002B020
// Secmon package2 signature/hash checks patches for Erista.
#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, 0x7C013000 - _PAGEOFF(SM_100_ADR)) },
//Patch package2 decryption and signature/hash checks.
{ 0x9F0 + 0xADC, _NOP() } // Header signature.
// Patch package2 signature/hash checks.
{ 0x9F0 + 0xADC, _NOP() }
);
PATCHSET_DEF(_secmon_2_patchset,
// Patch package2 decryption and signature/hash checks.
{ 0xAC8 + 0xAAC, _NOP() } // Header signature.
// Patch package2 signature/hash checks.
{ 0xAC8 + 0xAAC, _NOP() }
);
PATCHSET_DEF(_secmon_3_patchset,
// Patch package2 decryption and signature/hash checks.
{ 0xAC8 + 0xA30, _NOP() } // Header signature.
// Patch package2 signature/hash checks.
{ 0xAC8 + 0xA30, _NOP() }
);
PATCHSET_DEF(_secmon_4_patchset,
// Patch package2 decryption and signature/hash checks.
{ 0x2300 + 0x5EFC, _NOP() } // Header signature.
// Patch package2 signature/hash checks.
{ 0x2300 + 0x5EFC, _NOP() }
);
PATCHSET_DEF(_secmon_5_patchset,
// Patch package2 decryption and signature/hash checks.
{ 0xDA8 + 0xC9C, _NOP() } // Header signature.
// Patch package2 signature/hash checks.
{ 0xDA8 + 0xC9C, _NOP() }
);
PATCHSET_DEF(_secmon_6_patchset,
// Patch package2 decryption and signature/hash checks.
{ 0xDC8 + 0xE90, _NOP() } // Header signature.
// Patch package2 signature/hash checks.
{ 0xDC8 + 0xE90, _NOP() }
// Fix sleep mode for debug.
// { 0x1A68 + 0x3854, 0x94000E45 }, //gpio_config_for_uart.
// { 0x1A68 + 0x3858, 0x97FFFC0F }, //clkrst_reboot_uarta.
@@ -69,8 +69,8 @@ PATCHSET_DEF(_secmon_6_patchset,
);
PATCHSET_DEF(_secmon_620_patchset,
// Patch package2 decryption and signature/hash checks.
{ 0xDC8 + 0xC74, _NOP() } // Header signature.
// Patch package2 signature/hash checks.
{ 0xDC8 + 0xC74, _NOP() }
// Fix sleep mode for debug.
// { 0x2AC8 + 0x3854, 0x94000F42 }, //gpio_config_for_uart.
// { 0x2AC8 + 0x3858, 0x97FFFC0F }, //clkrst_reboot_uarta.
@@ -81,6 +81,8 @@ PATCHSET_DEF(_secmon_620_patchset,
// { 0x2AC8 + 0x3A6C, _NOP() } // warmboot UARTA cfg.
);
// Erista fuse check warmboot patches.
#define _NOPv7() 0xE320F000
PATCHSET_DEF(_warmboot_1_patchset,
{ 0x4DC, _NOPv7() } // Fuse check.
);
@@ -99,38 +101,35 @@ PATCHSET_DEF(_warmboot_4_patchset,
{ 0x558, _NOPv7() } // Segment id check.
);
/*
* package1.1 header: <wb, ldr, sm>
* package1.1 layout:
* 1.0: {sm, ldr, wb} { 2, 1, 0 }
* 2.0: {wb, ldr, sm} { 0, 1, 2 }
* 3.0: {wb, ldr, sm} { 0, 1, 2 }
* 3.1: {wb, ldr, sm} { 0, 1, 2 }
* 4.0: {ldr, sm, wb} { 1, 2, 0 }
* 5.0: {ldr, sm, wb} { 1, 2, 0 }
* 6.0: {ldr, sm, wb} { 1, 2, 0 }
* 6.2: {ldr, sm, wb} { 1, 2, 0 }
* 7.0: {ldr, sm, wb} { 1, 2, 0 }
* 1.0: {sm, ldr, wb} { 2, 1, 0 }
* 2.0+: {wb, ldr, sm} { 0, 1, 2 }
* 4.0+: {ldr, sm, wb} { 1, 2, 0 }
*/
static const u8 sec_map_100[3] = { PK11_SECTION_SM, PK11_SECTION_LD, PK11_SECTION_WB };
static const u8 sec_map_2xx[3] = { PK11_SECTION_WB, PK11_SECTION_LD, PK11_SECTION_SM };
static const u8 sec_map_4xx[3] = { PK11_SECTION_LD, PK11_SECTION_SM, PK11_SECTION_WB };
static const pkg1_id_t _pkg1_ids[] = {
{ "20161121183008", 0, 0x1900, 0x3FE0, { 2, 1, 0 }, SM_100_ADR, 0x8000D000, true, _secmon_1_patchset, _warmboot_1_patchset }, //1.0.0 (Patched relocator)
{ "20170210155124", 0, 0x1900, 0x3FE0, { 0, 1, 2 }, 0x4002D000, 0x8000D000, true, _secmon_2_patchset, _warmboot_2_patchset }, //2.0.0 - 2.3.0
{ "20170519101410", 1, 0x1A00, 0x3FE0, { 0, 1, 2 }, 0x4002D000, 0x8000D000, true, _secmon_3_patchset, _warmboot_3_patchset }, //3.0.0
{ "20170710161758", 2, 0x1A00, 0x3FE0, { 0, 1, 2 }, 0x4002D000, 0x8000D000, true, _secmon_3_patchset, _warmboot_3_patchset }, //3.0.1 - 3.0.2
{ "20170921172629", 3, 0x1800, 0x3FE0, { 1, 2, 0 }, 0x4002B000, 0x4003B000, false, _secmon_4_patchset, _warmboot_4_patchset }, //4.0.0 - 4.1.0
{ "20180220163747", 4, 0x1900, 0x3FE0, { 1, 2, 0 }, 0x4002B000, 0x4003B000, false, _secmon_5_patchset, _warmboot_4_patchset }, //5.0.0 - 5.1.0
{ "20180802162753", 5, 0x1900, 0x3FE0, { 1, 2, 0 }, 0x4002B000, 0x4003D800, false, _secmon_6_patchset, _warmboot_4_patchset }, //6.0.0 - 6.1.0
{ "20181107105733", 6, 0x0E00, 0x6FE0, { 1, 2, 0 }, 0x4002B000, 0x4003D800, false, _secmon_620_patchset, _warmboot_4_patchset }, //6.2.0
{ "20181218175730", 7, 0x0F00, 0x6FE0, { 1, 2, 0 }, 0x40030000, 0x4003E000, false, NULL, NULL }, //7.0.0
{ "20190208150037", 7, 0x0F00, 0x6FE0, { 1, 2, 0 }, 0x40030000, 0x4003E000, false, NULL, NULL }, //7.0.1
{ "20190314172056", 7, 0x0E00, 0x6FE0, { 1, 2, 0 }, 0x40030000, 0x4003E000, false, NULL, NULL }, //8.0.0 - 8.0.1
{ "20190531152432", 8, 0x0E00, 0x6FE0, { 1, 2, 0 }, 0x40030000, 0x4003E000, false, NULL, NULL }, //8.1.0
{ "20190809135709", 9, 0x0E00, 0x6FE0, { 1, 2, 0 }, 0x40030000, 0x4003E000, false, NULL, NULL }, //9.0.0 - 9.0.1
{ "20191021113848", 10, 0x0E00, 0x6FE0, { 1, 2, 0 }, 0x40030000, 0x4003E000, false, NULL, NULL }, //9.1.0
{ "20200303104606", 10, 0x0E00, 0x6FE0, { 1, 2, 0 }, 0x40030000, 0x4003E000, false, NULL, NULL }, //10.0.0
{ NULL } //End.
{ "20161121183008", 0, 0x1900, 0x3FE0, SM_100_ADR, 0x8000D000, _secmon_1_patchset, _warmboot_1_patchset }, // 1.0.0 (Patched relocator).
{ "20170210155124", 0, 0x1900, 0x3FE0, 0x4002D000, 0x8000D000, _secmon_2_patchset, _warmboot_2_patchset }, // 2.0.0 - 2.3.0.
{ "20170519101410", 1, 0x1A00, 0x3FE0, 0x4002D000, 0x8000D000, _secmon_3_patchset, _warmboot_3_patchset }, // 3.0.0.
{ "20170710161758", 2, 0x1A00, 0x3FE0, 0x4002D000, 0x8000D000, _secmon_3_patchset, _warmboot_3_patchset }, // 3.0.1 - 3.0.2.
{ "20170921172629", 3, 0x1800, 0x3FE0, 0x4002B000, 0x4003B000, _secmon_4_patchset, _warmboot_4_patchset }, // 4.0.0 - 4.1.0.
{ "20180220163747", 4, 0x1900, 0x3FE0, 0x4002B000, 0x4003B000, _secmon_5_patchset, _warmboot_4_patchset }, // 5.0.0 - 5.1.0.
{ "20180802162753", 5, 0x1900, 0x3FE0, 0x4002B000, 0x4003D800, _secmon_6_patchset, _warmboot_4_patchset }, // 6.0.0 - 6.1.0.
{ "20181107105733", 6, 0x0E00, 0x6FE0, 0x4002B000, 0x4003D800, _secmon_620_patchset, _warmboot_4_patchset }, // 6.2.0.
{ "20181218175730", 7, 0x0F00, 0x6FE0, 0x40030000, 0x4003E000, NULL, NULL }, // 7.0.0.
{ "20190208150037", 7, 0x0F00, 0x6FE0, 0x40030000, 0x4003E000, NULL, NULL }, // 7.0.1.
{ "20190314172056", 7, 0x0E00, 0x6FE0, 0x40030000, 0x4003E000, NULL, NULL }, // 8.0.0 - 8.0.1.
{ "20190531152432", 8, 0x0E00, 0x6FE0, 0x40030000, 0x4003E000, NULL, NULL }, // 8.1.0.
{ "20190809135709", 9, 0x0E00, 0x6FE0, 0x40030000, 0x4003E000, NULL, NULL }, // 9.0.0 - 9.0.1.
{ "20191021113848", 10, 0x0E00, 0x6FE0, 0x40030000, 0x4003E000, NULL, NULL }, // 9.1.0.
{ "20200303104606", 10, 0x0E00, 0x6FE0, 0x40030000, 0x4003E000, NULL, NULL }, // 10.0.0.
{ NULL } // End.
};
const pkg1_id_t *pkg1_get_latest()
@@ -159,22 +158,34 @@ void pkg1_decrypt(const pkg1_id_t *id, u8 *pkg1)
se_aes_crypt_ctr(11, pkg11 + 0x20, pkg11_size, pkg11 + 0x20, pkg11_size, pkg11 + 0x10);
}
void pkg1_unpack(void *warmboot_dst, void *secmon_dst, void *ldr_dst, const pkg1_id_t *id, u8 *pkg1)
const u8 *pkg1_unpack(void *wm_dst, void *sm_dst, void *ldr_dst, const pkg1_id_t *id, u8 *pkg1)
{
pk11_hdr_t *hdr = (pk11_hdr_t *)(pkg1 + id->pkg11_off + 0x20);
const u8 *sec_map;
const pk11_hdr_t *hdr = (pk11_hdr_t *)(pkg1 + id->pkg11_off + 0x20);
u32 sec_size[3] = { hdr->wb_size, hdr->ldr_size, hdr->sm_size };
//u32 sec_off[3] = { hdr->wb_off, hdr->ldr_off, hdr->sm_off };
// Get correct header mapping.
if (id->kb == KB_FIRMWARE_VERSION_100_200 && !strcmp(id->id, "20161121183008"))
sec_map = sec_map_100;
else if (id->kb >= KB_FIRMWARE_VERSION_100_200 && id->kb <= KB_FIRMWARE_VERSION_301)
sec_map = sec_map_2xx;
else
sec_map = sec_map_4xx;
// Copy secmon, warmboot and nx bootloader payloads.
u8 *pdata = (u8 *)hdr + sizeof(pk11_hdr_t);
for (u32 i = 0; i < 3; i++)
{
if (id->sec_map[i] == 0 && warmboot_dst)
memcpy(warmboot_dst, pdata, sec_size[id->sec_map[i]]);
else if (id->sec_map[i] == 1 && ldr_dst)
memcpy(ldr_dst, pdata, sec_size[id->sec_map[i]]);
else if (id->sec_map[i] == 2 && secmon_dst)
memcpy(secmon_dst, pdata, sec_size[id->sec_map[i]]);
pdata += sec_size[id->sec_map[i]];
if (sec_map[i] == PK11_SECTION_WB && wm_dst)
memcpy(wm_dst, pdata, sec_size[sec_map[i]]);
else if (sec_map[i] == PK11_SECTION_LD && ldr_dst)
memcpy(ldr_dst, pdata, sec_size[sec_map[i]]);
else if (sec_map[i] == PK11_SECTION_SM && sm_dst)
memcpy(sm_dst, pdata, sec_size[sec_map[i]]);
pdata += sec_size[sec_map[i]];
}
return sec_map;
}

View File

@@ -19,6 +19,10 @@
#include <utils/types.h>
#define PK11_SECTION_WB 0
#define PK11_SECTION_LD 1
#define PK11_SECTION_SM 2
typedef struct _patch_t
{
u32 off;
@@ -37,10 +41,8 @@ typedef struct _pkg1_id_t
u32 kb;
u32 tsec_off;
u32 pkg11_off;
u32 sec_map[3];
u32 secmon_base;
u32 warmboot_base;
bool set_warmboot;
patch_t *secmon_patchset;
patch_t *warmboot_patchset;
} pkg1_id_t;
@@ -60,6 +62,6 @@ typedef struct _pk11_hdr_t
const pkg1_id_t *pkg1_get_latest();
const pkg1_id_t *pkg1_identify(u8 *pkg1);
void pkg1_decrypt(const pkg1_id_t *id, u8 *pkg1);
void pkg1_unpack(void *warmboot_dst, void *secmon_dst, void *ldr_dst, const pkg1_id_t *id, u8 *pkg1);
const u8 *pkg1_unpack(void *wm_dst, void *sm_dst, void *ldr_dst, const pkg1_id_t *id, u8 *pkg1);
#endif

View File

@@ -604,6 +604,20 @@ static kip1_patchset_t _fs_patches_1000[] =
{ NULL, NULL }
};
static kip1_patch_t _fs_nogc_1020[] =
{
{ KPS(KIP_TEXT) | 0x13C2F0, 8, "\xF4\x4F\xBE\xA9\xFD\x7B\x01\xA9", "\xE0\x03\x1F\x2A\xC0\x03\x5F\xD6" },
{ KPS(KIP_TEXT) | 0x14E268, 4, "\x14\x40\x80\x52", "\x14\x80\x80\x52" },
{ 0, 0, NULL, NULL }
};
static kip1_patchset_t _fs_patches_1020[] =
{
{ "nogc", _fs_nogc_1020 },
{ "emummc", _fs_emummc },
{ NULL, NULL }
};
// SHA256 hashes.
static kip1_id_t _kip_ids[] =
{
@@ -641,6 +655,8 @@ static kip1_id_t _kip_ids[] =
{ "FS", "\xF1\x96\xD1\x44\xD0\x44\x45\xB6", _fs_patches_910 }, // FS 9.1.0 exfat
{ "FS", "\x3E\xEB\xD9\xB7\xBC\xD1\xB5\xE0", _fs_patches_1000 }, // FS 10.0.0
{ "FS", "\x81\x7E\xA2\xB0\xB7\x02\xC1\xF3", _fs_patches_1000 }, // FS 10.0.0 exfat
{ "FS", "\xA9\x52\xB6\x57\xAD\xF9\xC2\xBA", _fs_patches_1020 }, // FS 10.2.0
{ "FS", "\x16\x0D\x3E\x10\x4E\xAD\x61\x76", _fs_patches_1020 }, // FS 10.2.0 exfat
};
static kip1_id_t *_kip_id_sets = _kip_ids;
@@ -1273,11 +1289,12 @@ static bool _pkg2_key_unwrap_validate(pkg2_hdr_t *tmp_test, pkg2_hdr_t *hdr, u8
return (tmp_test->magic == PKG2_MAGIC);
}
u8 pkg2_keyslot;
pkg2_hdr_t *pkg2_decrypt(void *data, u8 kb)
{
pkg2_hdr_t mkey_test;
u8 *pdata = (u8 *)data;
u8 keyslot = 8;
pkg2_keyslot = 8;
// Skip signature.
pdata += 0x100;
@@ -1310,7 +1327,7 @@ pkg2_hdr_t *pkg2_decrypt(void *data, u8 kb)
if (res)
{
keyslot = 9;
pkg2_keyslot = 9;
goto key_found;
}
else
@@ -1340,7 +1357,7 @@ pkg2_hdr_t *pkg2_decrypt(void *data, u8 kb)
key_found:
// Decrypt header.
se_aes_crypt_ctr(keyslot, hdr, sizeof(pkg2_hdr_t), hdr, sizeof(pkg2_hdr_t), hdr);
se_aes_crypt_ctr(pkg2_keyslot, hdr, sizeof(pkg2_hdr_t), hdr, sizeof(pkg2_hdr_t), hdr);
//gfx_hexdump((u32)hdr, hdr, 0x100);
if (hdr->magic != PKG2_MAGIC)
@@ -1352,15 +1369,12 @@ DPRINTF("sec %d has size %08X\n", i, hdr->sec_size[i]);
if (!hdr->sec_size[i])
continue;
se_aes_crypt_ctr(keyslot, pdata, hdr->sec_size[i], pdata, hdr->sec_size[i], &hdr->sec_ctr[i * 0x10]);
se_aes_crypt_ctr(pkg2_keyslot, pdata, hdr->sec_size[i], pdata, hdr->sec_size[i], &hdr->sec_ctr[i * 0x10]);
//gfx_hexdump((u32)pdata, pdata, 0x100);
pdata += hdr->sec_size[i];
}
if (keyslot != 8)
se_aes_key_clear(9);
return hdr;
}
@@ -1396,9 +1410,16 @@ DPRINTF("adding kip1 '%s' @ %08X (%08X)\n", ki->kip1->name, (u32)ki->kip1, ki->s
return ini1_size;
}
void pkg2_build_encrypt(void *dst, void *kernel, u32 kernel_size, link_t *kips_info, bool new_pkg2, u8 kb)
void pkg2_build_encrypt(void *dst, void *hos_ctxt, link_t *kips_info)
{
u8 *pdst = (u8 *)dst;
launch_ctxt_t * ctxt = (launch_ctxt_t *)hos_ctxt;
u32 kernel_size = ctxt->kernel_size;
bool is_meso = *(u32 *)(ctxt->kernel + 4) == ATM_MESOSPHERE;
// Force new Package2 if Mesosphere.
if (is_meso)
ctxt->new_pkg2 = true;
// Signature.
memset(pdst, 0, 0x100);
@@ -1413,34 +1434,36 @@ void pkg2_build_encrypt(void *dst, void *kernel, u32 kernel_size, link_t *kips_i
hdr->bl_ver = 0;
hdr->pkg2_ver = 0xFF;
if (!new_pkg2)
if (!ctxt->new_pkg2)
hdr->base = 0x10000000;
else
hdr->base = 0x60000;
DPRINTF("kernel @ %08X (%08X)\n", (u32)kernel, kernel_size);
DPRINTF("%s @ %08X (%08X)\n", is_meso ? "Mesosphere": "kernel",(u32)ctxt->kernel, kernel_size);
pdst += sizeof(pkg2_hdr_t);
// Kernel.
memcpy(pdst, kernel, kernel_size);
if (!new_pkg2)
memcpy(pdst, ctxt->kernel, kernel_size);
if (!ctxt->new_pkg2)
hdr->sec_off[PKG2_SEC_KERNEL] = 0x10000000;
else
{
// Set new INI1 offset to kernel.
*(u32 *)(pdst + pkg2_newkern_ini1_val) = kernel_size;
kernel_size += _pkg2_ini1_build(pdst + kernel_size, hdr, kips_info, new_pkg2);
*(u32 *)(pdst + (is_meso ? 8 : pkg2_newkern_ini1_val)) = kernel_size;
// Build INI1 for new Package2.
kernel_size += _pkg2_ini1_build(pdst + kernel_size, hdr, kips_info, ctxt->new_pkg2);
hdr->sec_off[PKG2_SEC_KERNEL] = 0x60000;
}
hdr->sec_size[PKG2_SEC_KERNEL] = kernel_size;
se_aes_crypt_ctr(8, pdst, kernel_size, pdst, kernel_size, &hdr->sec_ctr[PKG2_SEC_KERNEL * 0x10]);
se_aes_crypt_ctr(pkg2_keyslot, pdst, kernel_size, pdst, kernel_size, &hdr->sec_ctr[PKG2_SEC_KERNEL * 0x10]);
pdst += kernel_size;
DPRINTF("kernel encrypted\n");
// INI1.
/// Build INI1 for old Package2.
u32 ini1_size = 0;
if (!new_pkg2)
ini1_size = _pkg2_ini1_build(pdst, hdr, kips_info, new_pkg2);
if (!ctxt->new_pkg2)
ini1_size = _pkg2_ini1_build(pdst, hdr, kips_info, false);
DPRINTF("INI1 encrypted\n");
// Calculate SHA256 over encrypted Kernel and INI1.
@@ -1452,11 +1475,14 @@ DPRINTF("INI1 encrypted\n");
(void *)pk2_hash_data, hdr->sec_size[PKG2_SEC_INI1]);
//Encrypt header.
u8 key_ver = kb ? kb + 1 : 0;
u8 key_ver = ctxt->pkg1_id->kb ? ctxt->pkg1_id->kb + 1 : 0;
*(u32 *)hdr->ctr = 0x100 + sizeof(pkg2_hdr_t) + kernel_size + ini1_size;
hdr->ctr[4] = key_ver;
se_aes_crypt_ctr(8, hdr, sizeof(pkg2_hdr_t), hdr, sizeof(pkg2_hdr_t), hdr);
se_aes_crypt_ctr(pkg2_keyslot, hdr, sizeof(pkg2_hdr_t), hdr, sizeof(pkg2_hdr_t), hdr);
memset(hdr->ctr, 0 , 0x10);
*(u32 *)hdr->ctr = 0x100 + sizeof(pkg2_hdr_t) + kernel_size + ini1_size;
hdr->ctr[4] = key_ver;
if (pkg2_keyslot != 8)
se_aes_key_clear(9);
}

View File

@@ -30,6 +30,8 @@
#define PKG2_NEWKERN_GET_INI1_HEURISTIC 0xD2800015 // Offset of OP + 12 is the INI1 offset.
#define PKG2_NEWKERN_START 0x800
#define ATM_MESOSPHERE 0x3053534D
extern u32 pkg2_newkern_ini1_val;
extern u32 pkg2_newkern_ini1_start;
extern u32 pkg2_newkern_ini1_end;
@@ -155,6 +157,6 @@ const char* pkg2_patch_kips(link_t *info, char* patchNames);
const pkg2_kernel_id_t *pkg2_identify(u8 *hash);
pkg2_hdr_t *pkg2_decrypt(void *data, u8 kb);
void pkg2_build_encrypt(void *dst, void *kernel, u32 kernel_size, link_t *kips_info, bool new_pkg2, u8 kb);
void pkg2_build_encrypt(void *dst, void *hos_ctxt, link_t *kips_info);
#endif

View File

@@ -331,23 +331,27 @@ static const char *get_error_desc(u32 error_desc)
switch (error_desc)
{
case 0x100:
return "Instruction Abort";
return "IABRT"; // Instruction Abort.
case 0x101:
return "Data Abort";
return "DABRT"; // Data Abort.
case 0x102:
return "PC Misalignment";
return "IUA"; // Instruction Unaligned Access.
case 0x103:
return "SP Misalignment";
return "DUA"; // Data Unaligned Access.
case 0x104:
return "Trap";
return "UDF"; // Undefined Instruction.
case 0x106:
return "SError";
return "SYS"; // System Error.
case 0x301:
return "Bad SVC";
return "SVC"; // Bad arguments or unimplemented SVC.
case 0xF00:
return "KRNL"; // Kernel panic.
case 0xFFD:
return "SO"; // Stack Overflow.
case 0xFFE:
return "std::abort()";
return "std::abort";
default:
return "Unknown";
return "UNK";
}
}
@@ -363,8 +367,8 @@ void secmon_exo_check_panic()
gfx_con_setpos(0, 0);
WPRINTF("Panic occurred while running Atmosphere.\n\n");
WPRINTFARGS("Title ID: %08X%08X", (u32)((u64)rpt->title_id >> 32), (u32)rpt->title_id);
WPRINTFARGS("Error Desc: %s (0x%x)\n", get_error_desc(rpt->error_desc), rpt->error_desc);
WPRINTFARGS("Title ID: %08X%08X", (u32)((u64)rpt->title_id >> 32), (u32)rpt->title_id);
WPRINTFARGS("Error: %s (0x%x)\n", get_error_desc(rpt->error_desc), rpt->error_desc);
// Save context to the SD card.
char filepath[0x40];
@@ -374,23 +378,23 @@ void secmon_exo_check_panic()
itoa((u32)(rpt->report_identifier), filepath + strlen(filepath), 16);
strcat(filepath, ".bin");
sd_save_to_file((void *)rpt, sizeof(atm_fatal_error_ctx), filepath);
gfx_con.fntsz = 8;
WPRINTFARGS("Report saved to %s\n", filepath);
if (!sd_save_to_file((void *)rpt, sizeof(atm_fatal_error_ctx), filepath))
{
gfx_con.fntsz = 8;
WPRINTFARGS("Report saved to %s\n", filepath);
gfx_con.fntsz = 16;
}
// Change magic to invalid, to prevent double-display of error/bootlooping.
rpt->magic = 0x0;
rpt->magic = 0;
gfx_con.fntsz = 16;
gfx_printf("\n\nPress POWER to continue.\n");
display_backlight_brightness(100, 1000);
msleep(1000);
u32 btn = btn_wait();
while (!(btn & BTN_POWER))
btn = btn_wait();
while (!(btn_wait() & BTN_POWER))
;
display_backlight_brightness(0, 1000);
gfx_con_setpos(0, 0);

View File

@@ -243,7 +243,7 @@ int reboot_to_sept(const u8 *tsec_fw, u32 kb, ini_sec_t *cfg_sec)
PMC(APBDEV_PMC_SCRATCH33) = SEPT_PRI_ADDR;
PMC(APBDEV_PMC_SCRATCH40) = 0x6000F208;
reconfig_hw_workaround(false, 0);
hw_reinit_workaround(false, 0);
(*sept)();

View File

@@ -44,6 +44,7 @@
#include <soc/fuse.h>
#include <soc/hw_init.h>
#include <soc/i2c.h>
#include <soc/pmc.h>
#include <soc/t210.h>
#include <soc/uart.h>
#include "storage/emummc.h"
@@ -255,12 +256,12 @@ int launch_payload(char *path, bool update)
else
reloc_patcher(PATCHED_RELOC_ENTRY, EXT_PAYLOAD_ADDR, ALIGN(size, 0x10));
reconfig_hw_workaround(false, byte_swap_32(*(u32 *)(buf + size - sizeof(u32))));
hw_reinit_workaround(false, byte_swap_32(*(u32 *)(buf + size - sizeof(u32))));
}
else
{
reloc_patcher(PATCHED_RELOC_ENTRY, EXT_PAYLOAD_ADDR, 0x7000);
reconfig_hw_workaround(true, 0);
hw_reinit_workaround(true, 0);
}
// Some cards (Sandisk U1), do not like a fast power cycle. Wait min 100ms.
@@ -292,8 +293,15 @@ void auto_launch_update()
EMC(EMC_SCRATCH0) &= ~EMC_HEKA_UPD;
else if (sd_mount())
{
// Check if update.bin exists and is newer and launch it. Otherwise create it.
if (!f_stat("bootloader/update.bin", NULL))
launch_payload("bootloader/update.bin", true);
else
{
u8 *buf = calloc(0x200, 1);
is_ipl_updated(buf, "bootloader/update.bin", true);
free(buf);
}
}
}
@@ -692,7 +700,7 @@ void nyx_load_run()
WPRINTF("\nUpdate your bootloader folder!\n\n");
WPRINTF("Press any key...");
msleep(2000);
msleep(1000);
btn_wait();
}
@@ -766,6 +774,18 @@ static ini_sec_t *get_ini_sec_from_id(ini_sec_t *ini_sec, char **bootlogoCustomE
return cfg_sec;
}
static void _bootloader_corruption_protect()
{
FILINFO fno;
if (!f_stat("bootloader", &fno))
{
if (!h_cfg.bootprotect && (fno.fattrib & AM_ARC))
f_chmod("bootloader", 0, AM_ARC);
else if (h_cfg.bootprotect && !(fno.fattrib & AM_ARC))
f_chmod("bootloader", AM_ARC, AM_ARC);
}
}
static void _auto_launch_firmware()
{
if(b_cfg.extra_cfg & (EXTRA_CFG_NYX_DUMP | EXTRA_CFG_NYX_BIS))
@@ -774,8 +794,6 @@ static void _auto_launch_firmware()
EMC(EMC_SCRATCH0) |= EMC_HEKA_UPD;
check_sept(NULL);
}
else if (b_cfg.extra_cfg & EXTRA_CFG_NYX_UMS)
EMC(EMC_SCRATCH0) |= EMC_HEKA_UPD;
if (!h_cfg.sept_run)
auto_launch_update();
@@ -844,16 +862,8 @@ static void _auto_launch_firmware()
h_cfg.autonogc = atoi(kv->val);
else if (!strcmp("updater2p", kv->key))
h_cfg.updater2p = atoi(kv->val);
else if (!strcmp("brand", kv->key))
{
h_cfg.brand = malloc(strlen(kv->val) + 1);
strcpy(h_cfg.brand, kv->val);
}
else if (!strcmp("tagline", kv->key))
{
h_cfg.tagline = malloc(strlen(kv->val) + 1);
strcpy(h_cfg.tagline, kv->val);
}
else if (!strcmp("bootprotect", kv->key))
h_cfg.bootprotect = atoi(kv->val);
}
boot_entry_id++;
@@ -869,6 +879,9 @@ static void _auto_launch_firmware()
b_cfg.autoboot_list = h_cfg.autoboot_list;
}
// Apply bootloader protection against corruption.
_bootloader_corruption_protect();
continue;
}
@@ -1079,9 +1092,10 @@ out:
b_cfg.boot_cfg &= BOOT_CFG_SEPT_RUN;
h_cfg.emummc_force_disable = false;
nyx_load_run();
// L4T: Clear custom boot mode flags from PMC_SCRATCH0.
PMC(APBDEV_PMC_SCRATCH0) &= ~PMC_SCRATCH0_MODE_CUSTOM_ALL;
sd_end();
nyx_load_run();
}
static void _patched_rcm_protection()
@@ -1127,10 +1141,10 @@ static void _patched_rcm_protection()
}
#define EXCP_EN_ADDR 0x4003FFFC
#define EXCP_MAGIC 0x30505645 // EVP0
#define EXCP_MAGIC 0x30505645 // EVP0
#define EXCP_TYPE_ADDR 0x4003FFF8
#define EXCP_TYPE_RESET 0x545352 // RST
#define EXCP_TYPE_UNDEF 0x464455 // UDF
#define EXCP_TYPE_RESET 0x545352 // RST
#define EXCP_TYPE_UNDEF 0x464455 // UDF
#define EXCP_TYPE_PABRT 0x54424150 // PABT
#define EXCP_TYPE_DABRT 0x54424144 // DABT
#define EXCP_LR_ADDR 0x4003FFF4
@@ -1142,7 +1156,15 @@ static void _show_errors()
u32 *excp_lr = (u32 *)EXCP_LR_ADDR;
if (*excp_enabled == EXCP_MAGIC)
h_cfg.errors |= ERR_EXCEPT_ENB;
h_cfg.errors |= ERR_EXCEPTION;
//! FIXME: Find a better way to identify if that scratch has proper data.
if (0 && PMC(APBDEV_PMC_SCRATCH37) & PMC_SCRATCH37_KERNEL_PANIC_FLAG)
{
// Set error and clear flag.
h_cfg.errors |= ERR_L4T_KERNEL;
PMC(APBDEV_PMC_SCRATCH37) &= ~PMC_SCRATCH37_KERNEL_PANIC_FLAG;
}
if (h_cfg.errors)
{
@@ -1150,32 +1172,33 @@ static void _show_errors()
gfx_con_setpos(0, 0);
display_backlight_brightness(150, 1000);
if (h_cfg.errors & ERR_SD_BOOT_EN)
WPRINTF("Failed to mount SD!\n");
if (h_cfg.errors & ERR_LIBSYS_LP0)
WPRINTF("Missing LP0 (sleep mode) lib!\n");
if (h_cfg.errors & ERR_SYSOLD_MTC)
if (h_cfg.errors & ERR_LIBSYS_MTC)
WPRINTF("Missing or old Minerva lib!\n");
if (h_cfg.errors & ~ERR_EXCEPT_ENB)
{
if (h_cfg.errors & (ERR_LIBSYS_LP0 | ERR_LIBSYS_MTC))
WPRINTF("\nUpdate bootloader folder!\n\n");
}
if (h_cfg.errors & ERR_EXCEPT_ENB)
if (h_cfg.errors & ERR_EXCEPTION)
{
WPRINTFARGS("An exception occurred (LR %08X):\n", *excp_lr);
switch (*excp_type)
{
case EXCP_TYPE_RESET:
WPRINTF("Reset");
WPRINTF("RESET");
break;
case EXCP_TYPE_UNDEF:
WPRINTF("Undefined instruction");
WPRINTF("UNDEF");
break;
case EXCP_TYPE_PABRT:
WPRINTF("Prefetch abort");
WPRINTF("PABRT");
break;
case EXCP_TYPE_DABRT:
WPRINTF("Data abort");
WPRINTF("DABRT");
break;
}
WPRINTF("\n");
@@ -1184,9 +1207,16 @@ static void _show_errors()
*excp_enabled = 0;
}
if (0 && h_cfg.errors & ERR_L4T_KERNEL)
{
WPRINTF("Panic occurred while running L4T.\n");
if (!sd_save_to_file((void *)PSTORE_ADDR, PSTORE_SZ, "L4T_panic.bin"))
WPRINTF("PSTORE saved to L4T_panic.bin\n");
}
WPRINTF("Press any key...");
msleep(2000);
msleep(1000);
btn_wait();
}
}
@@ -1301,6 +1331,15 @@ out:
max77620_low_battery_monitor_config(true);
}
void ipl_reload()
{
hw_reinit_workaround(false, 0);
// Reload hekate.
void (*ipl_ptr)() = (void *)IPL_LOAD_ADDR;
(*ipl_ptr)();
}
static void _about()
{
static const char credits[] =
@@ -1444,6 +1483,7 @@ ment_t ment_top[] = {
MDEF_MENU("Tools", &menu_tools),
MDEF_MENU("Console info", &menu_cinfo),
MDEF_CAPTION("---------------", 0xFF444444),
MDEF_HANDLER("Reload", ipl_reload),
MDEF_HANDLER("Reboot (Normal)", reboot_normal),
MDEF_HANDLER("Reboot (RCM)", reboot_rcm),
MDEF_HANDLER("Power off", power_off),
@@ -1452,14 +1492,14 @@ ment_t ment_top[] = {
MDEF_END()
};
menu_t menu_top = { ment_top, "hekate - CTCaer mod v5.3.0", 0, 0 };
menu_t menu_top = { ment_top, "hekate - CTCaer mod v5.3.4", 0, 0 };
extern void pivot_stack(u32 stack_top);
void ipl_main()
{
// Do initial HW configuration. This is compatible with consecutive reruns without a reset.
config_hw();
hw_init();
// Pivot the stack so we have enough space.
pivot_stack(IPL_STACK_TOP);
@@ -1478,7 +1518,8 @@ void ipl_main()
// Set bootloader's default configuration.
set_default_configuration();
sd_mount();
// Mount SD Card.
h_cfg.errors |= !sd_mount() ? ERR_SD_BOOT_EN : 0;
// Save sdram lp0 config.
if (!ianos_loader("bootloader/sys/libsys_lp0.bso", DRAM_LIB, (void *)sdram_get_params_patched()))
@@ -1486,7 +1527,7 @@ void ipl_main()
// Train DRAM and switch to max frequency.
if (minerva_init())
h_cfg.errors |= ERR_SYSOLD_MTC;
h_cfg.errors |= ERR_LIBSYS_MTC;
display_init();
@@ -1516,6 +1557,9 @@ void ipl_main()
// Load saved configuration and auto boot if enabled.
_auto_launch_firmware();
// Failed to launch Nyx, unmount SD Card.
sd_end();
minerva_change_freq(FREQ_800);
while (true)

View File

@@ -136,7 +136,7 @@ int emummc_storage_init_mmc(sdmmc_storage_t *storage, sdmmc_t *sdmmc)
FILINFO fno;
emu_cfg.active_part = 0;
// Always init eMMC even when in emuMMC. eMMC is needed from theh emuMMC driver anyway.
// Always init eMMC even when in emuMMC. eMMC is needed from the emuMMC driver anyway.
if (!sdmmc_storage_init_mmc(storage, sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400))
return 2;

View File

@@ -27,7 +27,8 @@ $(BUILD)/%.o: ./%.c
$(TARGET).bso: $(OBJS)
@$(CC) $(LDFLAGS) -e _modInit $^ -o $(OUTPUT)/$(TARGET).bso
$(STRIP) -g $(OUTPUT)/$(TARGET).bso
@$(STRIP) -g $(OUTPUT)/$(TARGET).bso
@echo "-------------\nBuilt module: "$(TARGET)".bso\n-------------"
clean:
@rm -rf $(OUTPUT)/$(TARGET).bso

View File

@@ -27,7 +27,8 @@ $(BUILD)/%.o: ./%.c
$(TARGET).bso: $(OBJS)
@$(CC) $(LDFLAGS) -e _minerva_init $^ -o $(OUTPUT)/$(TARGET).bso
$(STRIP) -g $(OUTPUT)/$(TARGET).bso
@$(STRIP) -g $(OUTPUT)/$(TARGET).bso
@echo "-------------\nBuilt module: "$(TARGET)".bso\n-------------"
clean:
@rm -rf $(OUTPUT)/$(TARGET).bso

View File

@@ -34,7 +34,8 @@ $(BUILD)/%.o: ./%.c
$(TARGET).bso: $(OBJS)
@$(CC) $(LDFLAGS) -e _modInit $^ -o $(OUTPUT)/$(TARGET).bso
$(STRIP) -g $(OUTPUT)/$(TARGET).bso
@$(STRIP) -g $(OUTPUT)/$(TARGET).bso
@echo "-------------\nBuilt module: "$(TARGET)".bso\n-------------"
clean:
@rm -rf $(OUTPUT)/$(TARGET).bso

View File

@@ -20,7 +20,7 @@ BDKDIR := bdk
BDKINC := -I../$(BDKDIR)
VPATH = $(dir $(wildcard ./$(SOURCEDIR)/)) $(dir $(wildcard ./$(SOURCEDIR)/*/)) $(dir $(wildcard ./$(SOURCEDIR)/*/*/))
VPATH += $(dir $(wildcard ./$(SOURCEDIR)/*/*/*/)) $(dir $(wildcard ./$(SOURCEDIR)/*/*/*/*/))
VPATH += $(dir $(wildcard ../$(BDKDIR)/*/)) $(dir $(wildcard ../$(BDKDIR)/*/*/)) $(dir $(wildcard ../$(BDKDIR)/*/*/*/))
VPATH += $(dir $(wildcard ../$(BDKDIR)/)) $(dir $(wildcard ../$(BDKDIR)/*/)) $(dir $(wildcard ../$(BDKDIR)/*/*/)) $(dir $(wildcard ../$(BDKDIR)/*/*/*/))
# Main and graphics.
OBJS = $(addprefix $(BUILDDIR)/$(TARGET)/, \
@@ -33,11 +33,11 @@ OBJS = $(addprefix $(BUILDDIR)/$(TARGET)/, \
# Hardware.
OBJS += $(addprefix $(BUILDDIR)/$(TARGET)/, \
bpmp.o ccplex.o clock.o di.o gpio.o i2c.o irq.o pinmux.o se.o smmu.o tsec.o uart.o \
bpmp.o ccplex.o clock.o di.o gpio.o i2c.o irq.o pinmux.o pmc.o se.o smmu.o tsec.o uart.o \
fuse.o kfuse.o \
mc.o sdram.o minerva.o ramdisk.o \
sdmmc.o sdmmc_driver.o nx_emmc.o nx_emmc_bis.o nx_sd.o \
bq24193.o max17050.o max7762x.o max77620-rtc.o regulator_5v.o \
bm92t36.o bq24193.o max17050.o max7762x.o max77620-rtc.o regulator_5v.o \
touch.o joycon.o tmp451.o fan.o \
usbd.o usb_gadget_ums.o usb_gadget_hid.o \
hw_init.o \
@@ -80,14 +80,14 @@ CUSTOMDEFINES := -DNYX_LOAD_ADDR=$(NYX_LOAD_ADDR) -DNYX_MAGIC=$(NYX_MAGIC)
CUSTOMDEFINES += -DNYX_VER_MJ=$(NYXVERSION_MAJOR) -DNYX_VER_MN=$(NYXVERSION_MINOR) -DNYX_VER_HF=$(NYXVERSION_HOTFX) -DNYX_RESERVED=$(NYXVERSION_RSVD)
CUSTOMDEFINES += -DNYX -DGFX_INC=$(GFX_INC) -DFFCFG_INC=$(FFCFG_INC)
# 0: UART_A, 1: UART_B.
# 0: UART_A, 1: UART_B, 2: UART_C.
# Also enables LV LOG.
#CUSTOMDEFINES += -DDEBUG_UART_PORT=1
#CUSTOMDEFINES += -DDEBUG
ARCH := -march=armv4t -mtune=arm7tdmi -mthumb-interwork
CFLAGS = $(ARCH) -O2 -nostdlib -ffunction-sections -fdata-sections -fomit-frame-pointer -std=gnu11 -Wall $(CUSTOMDEFINES)
CFLAGS += -g
CFLAGS = $(ARCH) -O2 -g -nostdlib -ffunction-sections -fdata-sections -fomit-frame-pointer -std=gnu11 -Wall $(CUSTOMDEFINES)
LDFLAGS = $(ARCH) -nostartfiles -lgcc -Wl,--nmagic,--gc-sections -Xlinker --defsym=NYX_LOAD_ADDR=$(NYX_LOAD_ADDR)
################################################################################
@@ -95,8 +95,11 @@ LDFLAGS = $(ARCH) -nostartfiles -lgcc -Wl,--nmagic,--gc-sections -Xlinker --defs
.PHONY: all clean
all: $(TARGET).bin
@echo -n "Nyx size is "
@wc -c < $(OUTPUTDIR)/$(TARGET).bin
@echo "--------------------------------------"
@echo -n "Nyx size: "
$(eval BIN_SIZE = $(shell wc -c < $(OUTPUTDIR)/$(TARGET).bin))
@echo $(BIN_SIZE)" Bytes"
@echo "--------------------------------------"
clean:
@rm -rf $(OBJS)

View File

@@ -42,13 +42,13 @@ void set_default_configuration()
h_cfg.autohosoff = 0;
h_cfg.autonogc = 1;
h_cfg.updater2p = 0;
h_cfg.brand = NULL;
h_cfg.tagline = NULL;
h_cfg.bootprotect = 0;
h_cfg.errors = 0;
h_cfg.eks = NULL;
h_cfg.sept_run = EMC(EMC_SCRATCH0) & EMC_SEPT_RUN;
h_cfg.aes_slots_new = false;
h_cfg.rcm_patched = fuse_check_patched_rcm();
h_cfg.sbk_set = FUSE(FUSE_PRIVATE_KEY0) == 0xFFFFFFFF;
h_cfg.emummc_force_disable = false;
sd_power_cycle_time_start = 0;
@@ -61,6 +61,7 @@ void set_nyx_default_configuration()
n_cfg.home_screen = 0;
n_cfg.verification = 1;
n_cfg.ums_emmc_rw = 0;
n_cfg.jc_disable = 0;
}
int create_config_entry()
@@ -118,16 +119,9 @@ int create_config_entry()
f_puts("\nupdater2p=", &fp);
itoa(h_cfg.updater2p, lbuf, 10);
f_puts(lbuf, &fp);
if (h_cfg.brand)
{
f_puts("\nbrand=", &fp);
f_puts(h_cfg.brand, &fp);
}
if (h_cfg.tagline)
{
f_puts("\ntagline=", &fp);
f_puts(h_cfg.tagline, &fp);
}
f_puts("\nbootprotect=", &fp);
itoa(h_cfg.bootprotect, lbuf, 10);
f_puts(lbuf, &fp);
f_puts("\n", &fp);
if (mainIniFound)
@@ -206,6 +200,9 @@ int create_nyx_config_entry()
f_puts("\numsemmcrw=", &fp);
itoa(n_cfg.ums_emmc_rw, lbuf, 10);
f_puts(lbuf, &fp);
f_puts("\njcdisable=", &fp);
itoa(n_cfg.jc_disable, lbuf, 10);
f_puts(lbuf, &fp);
f_puts("\n", &fp);
f_close(&fp);

View File

@@ -30,14 +30,14 @@ typedef struct _hekate_config
u32 autohosoff;
u32 autonogc;
u32 updater2p;
char *brand;
char *tagline;
u32 bootprotect;
// Global temporary config.
bool se_keygen_done;
bool sept_run;
bool aes_slots_new;
bool emummc_force_disable;
bool rcm_patched;
bool sbk_set;
u32 errors;
hos_eks_mbr_t *eks;
} hekate_config;
@@ -49,6 +49,7 @@ typedef struct _nyx_config
u32 home_screen;
u32 verification;
u32 ums_emmc_rw;
u32 jc_disable;
} nyx_config;
void set_default_configuration();

View File

@@ -61,7 +61,8 @@ static void _get_valid_partition(u32 *sector_start, u32 *sector_size, u32 *part_
curr_part_size = mbr->partitions[i].size_sct;
*sector_start = mbr->partitions[i].start_sct;
u8 type = mbr->partitions[i].type;
if ((curr_part_size >= *sector_size) && *sector_start && type != 0x83 && (!backup || type == 0xE0))
u32 sector_size_safe = !backup ? (*sector_size) + 0x8000 : (*sector_size);
if ((curr_part_size >= sector_size_safe) && *sector_start && type != 0x83 && (!backup || type == 0xE0))
{
if (backup)
{

View File

@@ -200,6 +200,11 @@ static void _save_log_to_bmp(char *fname)
static void _save_fb_to_bmp()
{
// Disallow screenshots if less than 2s passed.
static u32 timer = 0;
if (get_tmr_ms() < timer)
return;
if (do_reload)
return;
@@ -298,6 +303,9 @@ static void _save_fb_to_bmp()
lv_mbox_set_text(mbox, SYMBOL_CAMERA" #96FF00 Screenshot saved!#");
manual_system_maintenance(true);
lv_mbox_start_auto_close(mbox, 4000);
// Set timer to 2s.
timer = get_tmr_ms() + 2000;
}
static void _disp_fb_flush(int32_t x1, int32_t y1, int32_t x2, int32_t y2, const lv_color_t *color_p)
@@ -316,25 +324,22 @@ static void _disp_fb_flush(int32_t x1, int32_t y1, int32_t x2, int32_t y2, const
}
static touch_event touchpad;
static bool touch_enabled;
static bool console_enabled = false;
static bool _fts_touch_read(lv_indev_data_t *data)
{
touch_poll(&touchpad);
if (touch_enabled)
touch_poll(&touchpad);
else
return false;
// Take a screenshot if 3 fingers.
if (touchpad.fingers > 2)
{
// Disallow screenshots if less than 2s passed.
static u32 timer = 0;
if (get_tmr_ms() > timer)
{
_save_fb_to_bmp();
timer = get_tmr_ms() + 2000;
}
_save_fb_to_bmp();
data->state = LV_INDEV_STATE_REL;
return false;
}
@@ -394,7 +399,9 @@ static bool _jc_virt_mouse_read(lv_indev_data_t *data)
if (jc_pad->cap)
{
_save_fb_to_bmp();
msleep(1000);
data->state = LV_INDEV_STATE_REL;
return false;
}
// Calibrate left stick.
@@ -844,7 +851,7 @@ static void _launch_hos(u8 autoboot, u8 autoboot_list)
sd_end();
reconfig_hw_workaround(false, 0);
hw_reinit_workaround(false, 0);
// Mitigate L4T Joy-Con driver issue.
if ((autoboot & 0x80) && h_cfg.bootwait < 2)
@@ -864,7 +871,7 @@ void reload_nyx()
sd_end();
reconfig_hw_workaround(false, 0);
hw_reinit_workaround(false, 0);
// Some cards (Sandisk U1), do not like a fast power cycle. Wait min 100ms.
sdmmc_storage_init_wait_sd();
@@ -892,6 +899,10 @@ static lv_res_t _removed_sd_action(lv_obj_t *btns, const char *txt)
case 1:
power_off();
break;
case 2:
sd_end();
do_reload = false;
break;
}
return mbox_action(btns, txt);
@@ -908,10 +919,10 @@ static void _check_sd_card_removed(void *params)
lv_obj_set_style(dark_bg, &mbox_darken);
lv_obj_set_size(dark_bg, LV_HOR_RES, LV_VER_RES);
static const char * mbox_btn_map[] = { "\221Reboot (RCM)", "\221Power Off", "" };
static const char * mbox_btn_map[] = { "\221Reboot (RCM)", "\221Power Off", "\221Do not reload", "" };
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 * 4 / 9);
lv_obj_set_width(mbox, LV_HOR_RES * 6 / 9);
lv_mbox_set_text(mbox, "\n#FF8000 SD card was removed!#\n\n#96FF00 Nyx will reload after inserting it.#\n");
lv_mbox_add_btns(mbox, mbox_btn_map, _removed_sd_action);
@@ -1227,18 +1238,18 @@ static void _update_status_bar(void *params)
u8 batt_level = (batt_percent >> 8) & 0xFF;
if (batt_level > 80)
s_printf(label + strlen(label), SYMBOL_BATTERY_FULL);
strcat(label, SYMBOL_BATTERY_FULL);
else if (batt_level > 60)
s_printf(label + strlen(label), SYMBOL_BATTERY_3);
strcat(label, SYMBOL_BATTERY_3);
else if (batt_level > 40)
s_printf(label + strlen(label), SYMBOL_BATTERY_2);
strcat(label, SYMBOL_BATTERY_2);
else if (batt_level > 15)
s_printf(label + strlen(label), SYMBOL_BATTERY_1);
strcat(label, SYMBOL_BATTERY_1);
else
s_printf(label + strlen(label), "#FF3C28 "SYMBOL_BATTERY_EMPTY"#");
strcat(label, "#FF3C28 "SYMBOL_BATTERY_EMPTY"#");
if (charge_status)
s_printf(label + strlen(label), " #FFDD00 "SYMBOL_CHARGE"#");
strcat(label, " #FFDD00 "SYMBOL_CHARGE"#");
lv_label_set_text(status_bar.battery, label);
lv_obj_realign(status_bar.battery);
@@ -1361,6 +1372,8 @@ static lv_res_t _win_launch_close_action(lv_obj_t * btn)
launch_bg_done = true;
}
close_btn = NULL;
return LV_RES_INV;
}
@@ -2221,8 +2234,11 @@ void nyx_load_and_run()
lv_disp_drv_register(&disp_drv);
// Initialize Joy-Con.
lv_task_t *task_jc_init_hw = lv_task_create(jc_init_hw, LV_TASK_ONESHOT, LV_TASK_PRIO_LOWEST, NULL);
lv_task_once(task_jc_init_hw);
if (!n_cfg.jc_disable)
{
lv_task_t *task_jc_init_hw = lv_task_create(jc_init_hw, LV_TASK_ONESHOT, LV_TASK_PRIO_LOWEST, NULL);
lv_task_once(task_jc_init_hw);
}
lv_indev_drv_t indev_drv_jc;
lv_indev_drv_init(&indev_drv_jc);
indev_drv_jc.type = LV_INDEV_TYPE_POINTER;
@@ -2232,7 +2248,7 @@ void nyx_load_and_run()
close_btn = NULL;
// Initialize touch.
touch_power_on();
touch_enabled = touch_power_on();
lv_indev_drv_t indev_drv_touch;
lv_indev_drv_init(&indev_drv_touch);
indev_drv_touch.type = LV_INDEV_TYPE_POINTER;

View File

@@ -271,7 +271,7 @@ static void _create_mbox_emummc_raw()
mbr->partitions[3].type, mbr->partitions[3].start_sct, mbr->partitions[3].size_sct);
if (!mbr_ctx.available)
s_printf(txt_buf + strlen(txt_buf),
strcat(txt_buf,
"\n#FF8000 Do you want to partition your SD card?#\n"
"#FF8000 (You will be asked on how to proceed)#");

View File

@@ -28,6 +28,7 @@
#include <mem/heap.h>
#include <mem/sdram.h>
#include <mem/smmu.h>
#include <power/bm92t36.h>
#include <power/bq24193.h>
#include <power/max17050.h>
#include <sec/se.h>
@@ -81,6 +82,32 @@ static lv_res_t _create_window_dump_done(int error, char *dump_filenames)
return LV_RES_OK;
}
static lv_res_t _cal0_dump_window_action(lv_obj_t *btns, const char * txt)
{
int btn_idx = lv_btnm_get_pressed(btns);
mbox_action(btns, txt);
if (btn_idx == 1)
{
int error = !sd_mount();
if (!error)
{
char path[64];
emmcsn_path_impl(path, "/dumps", "cal0.bin", NULL);
error = sd_save_to_file((u8 *)cal0_buf, 0x8000, path);
sd_unmount();
}
_create_window_dump_done(error, "cal0.bin");
}
return LV_RES_INV;
}
static lv_res_t _battery_dump_window_action(lv_obj_t * btn)
{
int error = !sd_mount();
@@ -230,7 +257,7 @@ static lv_res_t _create_mbox_cal0(lv_obj_t *btn)
lv_obj_set_style(dark_bg, &mbox_darken);
lv_obj_set_size(dark_bg, LV_HOR_RES, LV_VER_RES);
static const char * mbox_btn_map[] = { "\211", "\222OK", "\211", "" };
static const char * mbox_btn_map[] = { "\211", "\222Dump", "\222Close", "\211", "" };
lv_obj_t * mbox = lv_mbox_create(dark_bg, NULL);
lv_mbox_set_recolor_text(mbox, true);
lv_obj_set_width(mbox, LV_HOR_RES / 9 * 5);
@@ -238,6 +265,7 @@ static lv_res_t _create_mbox_cal0(lv_obj_t *btn)
lv_mbox_set_text(mbox, "#C7EA46 CAL0 Info#");
char *txt_buf = (char *)malloc(0x4000);
txt_buf[0] = 0;
lv_obj_t * lb_desc = lv_label_create(mbox, NULL);
lv_label_set_long_mode(lb_desc, LV_LABEL_LONG_BREAK);
@@ -245,28 +273,46 @@ static lv_res_t _create_mbox_cal0(lv_obj_t *btn)
lv_label_set_style(lb_desc, &monospace_text);
lv_obj_set_width(lb_desc, LV_HOR_RES / 9 * 3);
sd_mount();
// Read package1.
char *build_date = malloc(32);
u8 *pkg1 = (u8 *)malloc(0x40000);
static const u32 BOOTLOADER_SIZE = 0x40000;
static const u32 BOOTLOADER_MAIN_OFFSET = 0x100000;
static const u32 BOOTLOADER_BACKUP_OFFSET = 0x140000;
static const u32 HOS_KEYBLOBS_OFFSET = 0x180000;
u8 kb = 0;
u32 bootloader_offset = BOOTLOADER_MAIN_OFFSET;
u8 *pkg1 = (u8 *)malloc(BOOTLOADER_SIZE);
sdmmc_storage_init_mmc(&emmc_storage, &emmc_sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400);
sdmmc_storage_set_mmc_partition(&emmc_storage, EMMC_BOOT0);
sdmmc_storage_read(&emmc_storage, 0x100000 / NX_EMMC_BLOCKSIZE, 0x40000 / NX_EMMC_BLOCKSIZE, pkg1);
try_load:
sdmmc_storage_read(&emmc_storage, bootloader_offset / NX_EMMC_BLOCKSIZE, BOOTLOADER_SIZE / NX_EMMC_BLOCKSIZE, pkg1);
char *build_date = malloc(32);
const pkg1_id_t *pkg1_id = pkg1_identify(pkg1, build_date);
s_printf(txt_buf, "#00DDFF Found pkg1 ('%s')#\n", build_date);
s_printf(txt_buf + strlen(txt_buf), "#00DDFF Found pkg1 ('%s')#\n", build_date);
free(build_date);
sd_mount();
if (!pkg1_id)
{
s_printf(txt_buf + strlen(txt_buf), "#FFDD00 Unknown pkg1 version for reading#\n#FFDD00 TSEC firmware!#");
strcat(txt_buf, "#FFDD00 Unknown pkg1 version for reading#\n#FFDD00 TSEC firmware!#\n");
// Try backup bootloader.
if (bootloader_offset != BOOTLOADER_BACKUP_OFFSET)
{
strcat(txt_buf, "Trying backup bootloader...\n");
bootloader_offset = BOOTLOADER_BACKUP_OFFSET;
goto try_load;
}
lv_label_set_text(lb_desc, txt_buf);
goto out;
}
kb = pkg1_id->kb;
tsec_ctxt_t tsec_ctxt;
tsec_ctxt.fw = (u8 *)pkg1 + pkg1_id->tsec_off;
tsec_ctxt.pkg1 = pkg1;
@@ -275,13 +321,13 @@ static lv_res_t _create_mbox_cal0(lv_obj_t *btn)
// Get keys.
hos_eks_get();
if (pkg1_id->kb >= KB_FIRMWARE_VERSION_700 && !h_cfg.sept_run)
if (kb >= KB_FIRMWARE_VERSION_700 && !h_cfg.sept_run)
{
u32 key_idx = 0;
if (pkg1_id->kb >= KB_FIRMWARE_VERSION_810)
if (kb >= KB_FIRMWARE_VERSION_810)
key_idx = 1;
if (h_cfg.eks && h_cfg.eks->enabled[key_idx] >= pkg1_id->kb)
if (h_cfg.eks && h_cfg.eks->enabled[key_idx] >= kb)
h_cfg.sept_run = true;
else
{
@@ -289,7 +335,7 @@ static lv_res_t _create_mbox_cal0(lv_obj_t *btn)
b_cfg->autoboot_list = 0;
b_cfg->extra_cfg = EXTRA_CFG_NYX_BIS;
if (!reboot_to_sept((u8 *)tsec_ctxt.fw, pkg1_id->kb))
if (!reboot_to_sept((u8 *)tsec_ctxt.fw, kb))
{
lv_label_set_text(lb_desc, "#FFDD00 Failed to run sept#\n");
goto out;
@@ -299,10 +345,10 @@ static lv_res_t _create_mbox_cal0(lv_obj_t *btn)
// Read the correct keyblob.
u8 *keyblob = (u8 *)calloc(NX_EMMC_BLOCKSIZE, 1);
sdmmc_storage_read(&emmc_storage, 0x180000 / NX_EMMC_BLOCKSIZE + pkg1_id->kb, 1, keyblob);
sdmmc_storage_read(&emmc_storage, HOS_KEYBLOBS_OFFSET / NX_EMMC_BLOCKSIZE + kb, 1, keyblob);
// Generate BIS keys
hos_bis_keygen(keyblob, pkg1_id->kb, &tsec_ctxt);
hos_bis_keygen(keyblob, kb, &tsec_ctxt);
free(keyblob);
@@ -352,42 +398,67 @@ static lv_res_t _create_mbox_cal0(lv_obj_t *btn)
cal0->bd_mac[0], cal0->bd_mac[1], cal0->bd_mac[2], cal0->bd_mac[3], cal0->bd_mac[4], cal0->bd_mac[5],
cal0->battery_lot);
u8 display_rev = (nyx_str->info.disp_id >> 8) & 0xFF;
u32 display_id = (cal0->lcd_vendor & 0xFF) << 8 | (cal0->lcd_vendor & 0xFF0000) >> 16;
switch (display_id)
{
case PANEL_JDI_LAM062M109A:
s_printf(txt_buf + strlen(txt_buf), "JDI LAM062M109A");
strcat(txt_buf, "JDI LAM062M109A");
break;
case PANEL_JDI_LPM062M326A:
s_printf(txt_buf + strlen(txt_buf), "JDI LPM062M326A");
strcat(txt_buf, "JDI LPM062M326A");
break;
case PANEL_INL_P062CCA_AZ1:
s_printf(txt_buf + strlen(txt_buf), "InnoLux P062CCA-AZ1");
strcat(txt_buf, "InnoLux P062CCA-AZ");
switch (display_rev)
{
case 0x93:
strcat(txt_buf, "1");
break;
case 0x95:
strcat(txt_buf, "2");
break;
default:
strcat(txt_buf, "X");
break;
}
break;
case PANEL_AUO_A062TAN01:
s_printf(txt_buf + strlen(txt_buf), "AUO A062TAN01");
strcat(txt_buf, "AUO A062TAN0");
switch (display_rev)
{
case 0x94:
strcat(txt_buf, "1");
break;
case 0x95:
strcat(txt_buf, "2");
break;
default:
strcat(txt_buf, "X");
break;
}
break;
case PANEL_INL_P062CCA_AZ2:
s_printf(txt_buf + strlen(txt_buf), "InnoLux P062CCA-AZ2");
case PANEL_INL_2J055IA_27A:
strcat(txt_buf, "InnoLux 2J055IA-27A");
break;
case PANEL_AUO_A062TAN02:
s_printf(txt_buf + strlen(txt_buf), "AUO A062TAN02");
case PANEL_AUO_A055TAN01:
strcat(txt_buf, "AUO A055TAN01");
break;
default:
switch (cal0->lcd_vendor & 0xFF)
{
case 0:
case PANEL_JDI_XXX062M:
s_printf(txt_buf + strlen(txt_buf), "JDI ");
strcat(txt_buf, "JDI ");
break;
case (PANEL_INL_P062CCA_AZ1 & 0xFF):
s_printf(txt_buf + strlen(txt_buf), "InnoLux ");
strcat(txt_buf, "InnoLux ");
break;
case (PANEL_AUO_A062TAN01 & 0xFF):
s_printf(txt_buf + strlen(txt_buf), "AUO ");
strcat(txt_buf, "AUO ");
break;
}
s_printf(txt_buf + strlen(txt_buf), "Unknown");
strcat(txt_buf, "Unknown");
break;
}
@@ -402,7 +473,7 @@ out:
sd_unmount();
sdmmc_storage_end(&emmc_storage);
lv_mbox_add_btns(mbox, mbox_btn_map, mbox_action);
lv_mbox_add_btns(mbox, mbox_btn_map, _cal0_dump_window_action);
lv_obj_align(mbox, NULL, LV_ALIGN_CENTER, 0, 0);
lv_obj_set_top(mbox, true);
@@ -463,8 +534,6 @@ static lv_res_t _create_window_fuses_info_status(lv_obj_t *btn)
char *txt_buf = (char *)malloc(0x4000);
// Decode fuses.
u8 burntFuses7 = 0;
u8 burntFuses6 = 0;
u32 odm4 = fuse_read_odm(4);
u8 dram_id = (odm4 >> 3) & 0x1F;
char dram_man[16] = {0};
@@ -485,17 +554,11 @@ static lv_res_t _create_window_fuses_info_status(lv_obj_t *btn)
break;
}
for (u32 i = 0; i < 32; i++)
{
if ((fuse_read_odm(7) >> i) & 1)
burntFuses7++;
}
for (u32 i = 0; i < 32; i++)
{
if ((fuse_read_odm(6) >> i) & 1)
burntFuses6++;
}
// Count burnt fuses.
u8 burnt_fuses_7 = fuse_count_burnt(fuse_read_odm(7));
u8 burnt_fuses_6 = fuse_count_burnt(fuse_read_odm(6));
// Calculate LOT.
u32 lot_code0 = (FUSE(FUSE_OPT_LOT_CODE_0) & 0xFFFFFFF) << 2;
u32 lot_bin = 0;
for (int i = 0; i < 5; ++i)
@@ -514,7 +577,7 @@ static lv_res_t _create_window_fuses_info_status(lv_obj_t *btn)
"%d\n%d\n%d (0x%X)\n%d\n%d\n%d\n%d\n"
"ID: %02X, Major: A0%d, Minor: %d",
FUSE(FUSE_SKU_INFO), odm4 & 0x30000 ? "Mariko" : "Erista", (fuse_read_odm(4) & 3) ? "Dev" : "Retail",
dram_id, dram_man, burntFuses7, burntFuses6,
dram_id, dram_man, burnt_fuses_7, burnt_fuses_6,
byte_swap_32(FUSE(FUSE_PRIVATE_KEY0)), byte_swap_32(FUSE(FUSE_PRIVATE_KEY1)),
byte_swap_32(FUSE(FUSE_PRIVATE_KEY2)), byte_swap_32(FUSE(FUSE_PRIVATE_KEY3)),
byte_swap_32(FUSE(FUSE_PRIVATE_KEY4)),
@@ -550,32 +613,32 @@ static lv_res_t _create_window_fuses_info_status(lv_obj_t *btn)
switch (ram_vendor.dev0_ch0)
{
case 1:
s_printf(txt_buf + strlen(txt_buf), "Samsung");
strcat(txt_buf, "Samsung");
break;
case 6:
s_printf(txt_buf + strlen(txt_buf), "Hynix");
strcat(txt_buf, "Hynix");
break;
case 255:
s_printf(txt_buf + strlen(txt_buf), "Micron");
strcat(txt_buf, "Micron");
break;
default:
s_printf(txt_buf + strlen(txt_buf), "Unknown");
strcat(txt_buf, "Unknown");
break;
}
s_printf(txt_buf + strlen(txt_buf), " (%d) #FF8000 |# ", ram_vendor.dev0_ch0);
switch (ram_vendor.dev1_ch0)
{
case 1:
s_printf(txt_buf + strlen(txt_buf), "Samsung");
strcat(txt_buf, "Samsung");
break;
case 6:
s_printf(txt_buf + strlen(txt_buf), "Hynix");
strcat(txt_buf, "Hynix");
break;
case 255:
s_printf(txt_buf + strlen(txt_buf), "Micron");
strcat(txt_buf, "Micron");
break;
default:
s_printf(txt_buf + strlen(txt_buf), "Unknown");
strcat(txt_buf, "Unknown");
break;
}
s_printf(txt_buf + strlen(txt_buf), " (%d)\n#FF8000 Rev ID:# %04X #FF8000 |# %04X\n#FF8000 Density:# ",
@@ -583,75 +646,100 @@ static lv_res_t _create_window_fuses_info_status(lv_obj_t *btn)
switch ((ram_density.dev0_ch0 & 0x3C) >> 2)
{
case 2:
s_printf(txt_buf + strlen(txt_buf), "4x512MB");
strcat(txt_buf, " x 512MB");
break;
case 3:
s_printf(txt_buf + strlen(txt_buf), "4x768MB");
strcat(txt_buf, " x 768MB");
break;
case 4:
s_printf(txt_buf + strlen(txt_buf), "4x1GB");
strcat(txt_buf, " x 1GB");
break;
default:
s_printf(txt_buf + strlen(txt_buf), "4xUnk");
strcat(txt_buf, " x Unk");
break;
}
s_printf(txt_buf + strlen(txt_buf), " (%d) #FF8000 |# ", (ram_density.dev0_ch0 & 0x3C) >> 2);
switch ((ram_density.dev1_ch0 & 0x3C) >> 2)
{
case 2:
s_printf(txt_buf + strlen(txt_buf), "4x512MB");
strcat(txt_buf, " x 512MB");
break;
case 3:
s_printf(txt_buf + strlen(txt_buf), "4x768MB");
strcat(txt_buf, " x 768MB");
break;
case 4:
s_printf(txt_buf + strlen(txt_buf), "4x1GB");
strcat(txt_buf, " x 1GB");
break;
default:
s_printf(txt_buf + strlen(txt_buf), "2xUnk");
strcat(txt_buf, " x Unk");
break;
}
s_printf(txt_buf + strlen(txt_buf), " (%d)\n\n", (ram_density.dev1_ch0 & 0x3C) >> 2);
// Display info.
u8 display_rev = (nyx_str->info.disp_id >> 8) & 0xFF;
u32 display_id = ((nyx_str->info.disp_id >> 8) & 0xFF00) | (nyx_str->info.disp_id & 0xFF);
s_printf(txt_buf + strlen(txt_buf), "#00DDFF Display Panel:#\n#FF8000 Model:# ");
strcat(txt_buf, "#00DDFF Display Panel:#\n#FF8000 Model:# ");
switch (display_id)
{
case PANEL_JDI_LAM062M109A:
s_printf(txt_buf + strlen(txt_buf), "JDI LAM062M109A");
strcat(txt_buf, "JDI LAM062M109A");
break;
case PANEL_JDI_LPM062M326A:
s_printf(txt_buf + strlen(txt_buf), "JDI LPM062M326A");
strcat(txt_buf, "JDI LPM062M326A");
break;
case PANEL_INL_P062CCA_AZ1:
s_printf(txt_buf + strlen(txt_buf), "InnoLux P062CCA-AZ1");
strcat(txt_buf, "InnoLux P062CCA-AZ");
switch (display_rev)
{
case 0x93:
strcat(txt_buf, "1");
break;
case 0x95:
strcat(txt_buf, "2");
break;
default:
strcat(txt_buf, "X #FFDD00 Contact me!#");
break;
}
break;
case PANEL_AUO_A062TAN01:
s_printf(txt_buf + strlen(txt_buf), "AUO A062TAN01");
strcat(txt_buf, "AUO A062TAN0");
switch (display_rev)
{
case 0x94:
strcat(txt_buf, "1");
break;
case 0x95:
strcat(txt_buf, "2");
break;
default:
strcat(txt_buf, "X #FFDD00 Contact me!#");
break;
}
break;
case PANEL_INL_P062CCA_AZ2:
s_printf(txt_buf + strlen(txt_buf), "InnoLux P062CCA-AZ2");
case PANEL_INL_2J055IA_27A:
strcat(txt_buf, "InnoLux 2J055IA-27A");
break;
case PANEL_AUO_A062TAN02:
s_printf(txt_buf + strlen(txt_buf), "AUO A062TAN02");
case PANEL_AUO_A055TAN01:
strcat(txt_buf, "AUO A055TAN01");
break;
default:
switch (display_id & 0xFF)
{
case PANEL_JDI_XXX062M:
s_printf(txt_buf + strlen(txt_buf), "JDI ");
strcat(txt_buf, "JDI ");
break;
case (PANEL_INL_P062CCA_AZ1 & 0xFF):
s_printf(txt_buf + strlen(txt_buf), "InnoLux ");
strcat(txt_buf, "InnoLux ");
break;
case (PANEL_AUO_A062TAN01 & 0xFF):
s_printf(txt_buf + strlen(txt_buf), "AUO ");
strcat(txt_buf, "AUO ");
break;
}
s_printf(txt_buf + strlen(txt_buf), "Unknown");
strcat(txt_buf, "Unknown #FFDD00 Contact me!#");
break;
}
@@ -662,30 +750,30 @@ static lv_res_t _create_window_fuses_info_status(lv_obj_t *btn)
if (!touch_get_fw_info(&touch_fw))
{
s_printf(txt_buf + strlen(txt_buf), "\n\n#00DDFF Touch Panel:#\n#FF8000 Model:# ");
strcat(txt_buf, "\n\n#00DDFF Touch Panel:#\n#FF8000 Model:# ");
switch (touch_fw.fw_id)
{
case 0x100100:
s_printf(txt_buf + strlen(txt_buf), "NTD 4CD 1601");
strcat(txt_buf, "NTD 4CD 1601");
break;
case 0x00120100:
case 0x32000001:
s_printf(txt_buf + strlen(txt_buf), "NTD 4CD 1801");
strcat(txt_buf, "NTD 4CD 1801");
break;
case 0x001A0300:
case 0x32000102:
s_printf(txt_buf + strlen(txt_buf), "NTD 4CD 2602");
strcat(txt_buf, "NTD 4CD 2602");
break;
case 0x00290100:
case 0x32000302:
s_printf(txt_buf + strlen(txt_buf), "NTD 4CD 3801");
strcat(txt_buf, "NTD 4CD 3801");
break;
case 0x31051820:
case 0x32000402:
s_printf(txt_buf + strlen(txt_buf), "NTD 4CD XXXX");
strcat(txt_buf, "NTD 4CD XXXX");
break;
default:
s_printf(txt_buf + strlen(txt_buf), "Unknown");
strcat(txt_buf, "Unknown");
}
s_printf(txt_buf + strlen(txt_buf), "\n#FF8000 ID:# %X\n#FF8000 FTB ver:# %04X\n#FF8000 FW rev:# %04X",
@@ -694,9 +782,9 @@ static lv_res_t _create_window_fuses_info_status(lv_obj_t *btn)
// Check if patched unit.
if (!fuse_check_patched_rcm())
s_printf(txt_buf + strlen(txt_buf), "\n\n#96FF00 Your unit is exploitable#\n#96FF00 to the RCM bug!#");
strcat(txt_buf, "\n\n#96FF00 Your unit is exploitable#\n#96FF00 to the RCM bug!#");
else
s_printf(txt_buf + strlen(txt_buf), "\n\n#FF8000 Your unit is patched#\n#FF8000 to the RCM bug!#");
strcat(txt_buf, "\n\n#FF8000 Your unit is patched#\n#FF8000 to the RCM bug!#");
lv_label_set_text(lb_desc2, txt_buf);
@@ -730,7 +818,7 @@ static void _ipatch_process(u32 offset, u32 value)
s_printf(ipatches_txt + strlen(ipatches_txt), "SVC ##0x%02X", lo);
break;
}
s_printf(ipatches_txt + strlen(ipatches_txt), "\n");
strcat(ipatches_txt, "\n");
}
static lv_res_t _create_window_bootrom_info_status(lv_obj_t *btn)
@@ -783,23 +871,40 @@ static lv_res_t _create_window_tsec_keys_status(lv_obj_t *btn)
lv_label_set_recolor(lb_desc, true);
lv_label_set_style(lb_desc, &monospace_text);
// Read package1.
char *build_date = malloc(32);
u8 *pkg1 = (u8 *)malloc(0x40000);
sdmmc_storage_init_mmc(&emmc_storage, &emmc_sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400);
sdmmc_storage_set_mmc_partition(&emmc_storage, EMMC_BOOT0);
sdmmc_storage_read(&emmc_storage, 0x100000 / NX_EMMC_BLOCKSIZE, 0x40000 / NX_EMMC_BLOCKSIZE, pkg1);
sdmmc_storage_end(&emmc_storage);
const pkg1_id_t *pkg1_id = pkg1_identify(pkg1, build_date);
char *txt_buf = (char *)malloc(0x1000);
char *txt_buf2 = (char *)malloc(0x1000);
s_printf(txt_buf, "#00DDFF Found pkg1 ('%s')#\n", build_date);
txt_buf[0] = 0;
// Read package1.
static const u32 BOOTLOADER_SIZE = 0x40000;
static const u32 BOOTLOADER_MAIN_OFFSET = 0x100000;
static const u32 BOOTLOADER_BACKUP_OFFSET = 0x140000;
u8 *pkg1 = (u8 *)malloc(0x40000);
u32 bootloader_offset = BOOTLOADER_MAIN_OFFSET;
try_load:
sdmmc_storage_init_mmc(&emmc_storage, &emmc_sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400);
sdmmc_storage_set_mmc_partition(&emmc_storage, EMMC_BOOT0);
sdmmc_storage_read(&emmc_storage, bootloader_offset / NX_EMMC_BLOCKSIZE, BOOTLOADER_SIZE / NX_EMMC_BLOCKSIZE, pkg1);
sdmmc_storage_end(&emmc_storage);
char *build_date = malloc(32);
const pkg1_id_t *pkg1_id = pkg1_identify(pkg1, build_date);
s_printf(txt_buf + strlen(txt_buf), "#00DDFF Found pkg1 ('%s')#\n", build_date);
free(build_date);
if (!pkg1_id)
{
s_printf(txt_buf + strlen(txt_buf), "#FFDD00 Unknown pkg1 version for reading#\n#FFDD00 TSEC firmware!#");
strcat(txt_buf, "#FFDD00 Unknown pkg1 version for reading#\n#FFDD00 TSEC firmware!#\n");
// Try backup bootloader.
if (bootloader_offset != BOOTLOADER_BACKUP_OFFSET)
{
strcat(txt_buf, "Trying backup bootloader...\n");
bootloader_offset = BOOTLOADER_BACKUP_OFFSET;
goto try_load;
}
lv_label_set_text(lb_desc, txt_buf);
lv_obj_set_width(lb_desc, lv_obj_get_width(desc));
@@ -859,7 +964,7 @@ static lv_res_t _create_window_tsec_keys_status(lv_obj_t *btn)
}
}
s_printf(txt_buf + strlen(txt_buf), "#C7EA46 TSEC Key:#\n");
strcat(txt_buf, "#C7EA46 TSEC Key:#\n");
if (res >= 0)
{
s_printf(txt_buf2, "\n%08X%08X%08X%08X\n",
@@ -867,7 +972,7 @@ static lv_res_t _create_window_tsec_keys_status(lv_obj_t *btn)
if (pkg1_id->kb == KB_FIRMWARE_VERSION_620)
{
s_printf(txt_buf + strlen(txt_buf), "#C7EA46 TSEC root:#\n");
strcat(txt_buf, "#C7EA46 TSEC root:#\n");
s_printf(txt_buf2 + strlen(txt_buf2), "%08X%08X%08X%08X\n",
byte_swap_32(tsec_keys[4]), byte_swap_32(tsec_keys[5]), byte_swap_32(tsec_keys[6]), byte_swap_32(tsec_keys[7]));
}
@@ -909,7 +1014,7 @@ static lv_res_t _create_mbox_benchmark(bool sd_bench)
char *txt_buf = (char *)malloc(0x1000);
s_printf(txt_buf, "#FF8000 %s Benchmark#\n[3 x %s raw reads. Cancel: VOL- & VOL+]\n",
s_printf(txt_buf, "#FF8000 %s Benchmark#\n[3 x %s raw reads] Abort: VOL- & VOL+\n",
sd_bench ? "SD Card" : "eMMC", sd_bench ? "2GB" : "8GB");
lv_mbox_set_text(mbox, txt_buf);
@@ -959,7 +1064,7 @@ static lv_res_t _create_mbox_benchmark(bool sd_bench)
u32 timer = get_tmr_ms();
s_printf(txt_buf + strlen(txt_buf), "\n");
strcat(txt_buf, "\n");
lv_mbox_set_text(mbox, txt_buf);
while (data_remaining)
@@ -1046,8 +1151,15 @@ static lv_res_t _create_window_emmc_info_status(lv_obj_t *btn)
}
else
{
u16 card_type;
u32 speed = 0;
char *rsvd_blocks;
char life_a_txt[8];
char life_b_txt[8];
u32 life_a = storage.ext_csd.dev_life_est_a;
u32 life_b = storage.ext_csd.dev_life_est_b;
u16 card_type = storage.ext_csd.card_type;
char card_type_support[96];
card_type_support[0] = 0;
s_printf(txt_buf, "\n%X\n%X\n%02X\n%c%c%c%c%c%c\n%X\n%04X\n%02d/%04d\n\n",
storage.cid.manfid, storage.cid.card_bga, storage.cid.oemid,
@@ -1055,9 +1167,6 @@ static lv_res_t _create_window_emmc_info_status(lv_obj_t *btn)
storage.cid.prod_name[3], storage.cid.prod_name[4], storage.cid.prod_name[5],
storage.cid.prv, storage.cid.serial, storage.cid.month, storage.cid.year);
card_type = storage.ext_csd.card_type;
char card_type_support[96];
card_type_support[0] = 0;
if (card_type & EXT_CSD_CARD_TYPE_HS_26)
{
strcat(card_type_support, "HS26");
@@ -1084,11 +1193,45 @@ static lv_res_t _create_window_emmc_info_status(lv_obj_t *btn)
speed = (200 << 16) | 400;
}
strcpy(life_a_txt, "-");
strcpy(life_b_txt, "-");
// Normalize cells life.
if (life_a)
{
life_a--;
life_a = (10 - life_a) * 10;
s_printf(life_a_txt, "%d%%", life_a);
}
if (life_b) // Toshiba is 0 (undefined).
{
life_b--;
life_b = (10 - life_b) * 10;
s_printf(life_b_txt, "%d%%", life_b);
}
switch (storage.ext_csd.pre_eol_info)
{
case 1:
rsvd_blocks = "Normal (< 80%)";
break;
case 2:
rsvd_blocks = "Warning (> 80%)";
break;
case 3:
rsvd_blocks = "Urgent (> 90%)";
break;
default:
rsvd_blocks = "Unknown";
break;
}
s_printf(txt_buf + strlen(txt_buf),
"#00DDFF V1.%d#\n%02X\n1.%d\n%02X\n%d MB/s (%d MHz)\n%d MB/s\n%s",
storage.ext_csd.ext_struct, storage.csd.mmca_vsn, storage.ext_csd.rev,
"#00DDFF V1.%d (rev 1.%d)#\n%02X\n%d MB/s (%d MHz)\n%d MB/s\n%s\nA: %s, B: %s\n%s",
storage.ext_csd.ext_struct, storage.ext_csd.rev,
storage.csd.cmdclass, speed & 0xFFFF, (speed >> 16) & 0xFFFF,
storage.csd.busspeed, card_type_support);
storage.csd.busspeed, card_type_support, life_a_txt, life_b_txt, rsvd_blocks);
lv_label_set_static_text(lb_desc,
"#00DDFF CID:#\n"
@@ -1100,12 +1243,12 @@ static lv_res_t _create_window_emmc_info_status(lv_obj_t *btn)
"S/N:\n"
"Month/Year:\n\n"
"#00DDFF Ext CSD#\n"
"Spec Version:\n"
"Extended Rev:\n"
"Cmd Classes:\n"
"Max Rate:\n"
"Current Rate:\n"
"Type Support:"
"Type Support:\n\n"
"Estimated Life:\n"
"Reserved Used:"
);
lv_obj_set_width(lb_desc, lv_obj_get_width(desc));
@@ -1143,7 +1286,7 @@ static lv_res_t _create_window_emmc_info_status(lv_obj_t *btn)
{
if (idx > 10)
{
s_printf(txt_buf + strlen(txt_buf), "#FFDD00 Table truncated!#");
strcat(txt_buf, "#FFDD00 Table truncated!#");
break;
}
@@ -1256,13 +1399,29 @@ static lv_res_t _create_window_sdcard_info_status(lv_obj_t *btn)
lv_obj_t * lb_val2 = lv_label_create(val2, lb_desc);
char *wp_info;
switch (sd_storage.csd.write_protect)
{
case 1:
wp_info = "Temporary";
break;
case 2:
case 3:
wp_info = "Permanent";
break;
default:
wp_info = "None";
break;
}
s_printf(txt_buf,
"#00DDFF v%d.0#\n%02X\n%d MiB\n%X\n%d\n%d MB/s (%d MHz)\n%d\nU%d\nV%d\nA%d\n%d",
sd_storage.csd.structure + 1, sd_storage.csd.cmdclass, sd_storage.sec_cnt >> 11, sd_storage.sec_cnt,
"#00DDFF v%d.0#\n%02X\n%d MiB\n%X (CP %X)\n%d\n%d MB/s (%d MHz)\n%d\nU%d\nV%d\nA%d\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, sd_storage.ssr.uhs_grade, sd_storage.ssr.video_class,
sd_storage.ssr.app_class, sd_storage.csd.write_protect);
sd_storage.ssr.app_class, wp_info);
lv_label_set_text(lb_val2, txt_buf);
@@ -1303,9 +1462,10 @@ static lv_res_t _create_window_sdcard_info_status(lv_obj_t *btn)
lv_obj_t * lb_val3 = lv_label_create(val3, lb_desc);
s_printf(txt_buf, "\n%s\n%d KiB\n%d MiB",
s_printf(txt_buf, "\n%s\n%d %s\n%d MiB",
sd_fs.fs_type == FS_EXFAT ? ("exFAT "SYMBOL_SHRK) : ("FAT32"),
(sd_fs.csize > 1) ? (sd_fs.csize >> 1) : 512,
(sd_fs.csize > 1) ? "KiB" : "B",
sd_fs.free_clst * sd_fs.csize >> SECTORS_TO_MIB_COEFF);
lv_label_set_text(lb_val3, txt_buf);
@@ -1454,7 +1614,11 @@ static lv_res_t _create_window_battery_status(lv_obj_t *btn)
"Fast charge current limit:\n"
"Charge voltage limit:\n"
"Charge status:\n"
"Temperature status:"
"Temperature status:\n\n"
"#00DDFF USB-PD IC Info:#\n"
"Connection status:\n"
"Input Wattage Limit:\n"
"USB-PD Profiles:"
);
lv_obj_set_width(lb_desc2, lv_obj_get_width(desc2));
lv_obj_align(desc2, val, LV_ALIGN_OUT_RIGHT_MID, LV_DPI / 2, 0);
@@ -1467,8 +1631,9 @@ static lv_res_t _create_window_battery_status(lv_obj_t *btn)
bq24193_get_property(BQ24193_InputVoltageLimit, &value);
s_printf(txt_buf, "\n%d mV\n", value);
bq24193_get_property(BQ24193_InputCurrentLimit, &value);
s_printf(txt_buf + strlen(txt_buf), "%d mA\n", value);
int iinlim = 0;
bq24193_get_property(BQ24193_InputCurrentLimit, &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);
@@ -1483,16 +1648,16 @@ static lv_res_t _create_window_battery_status(lv_obj_t *btn)
switch (value)
{
case 0:
s_printf(txt_buf + strlen(txt_buf), "Not charging\n");
strcat(txt_buf, "Not charging\n");
break;
case 1:
s_printf(txt_buf + strlen(txt_buf), "Pre-charging\n");
strcat(txt_buf, "Pre-charging\n");
break;
case 2:
s_printf(txt_buf + strlen(txt_buf), "Fast charging\n");
strcat(txt_buf, "Fast charging\n");
break;
case 3:
s_printf(txt_buf + strlen(txt_buf), "Charge terminated\n");
strcat(txt_buf, "Charge terminated\n");
break;
default:
s_printf(txt_buf + strlen(txt_buf), "Unknown (%d)\n", value);
@@ -1503,25 +1668,54 @@ static lv_res_t _create_window_battery_status(lv_obj_t *btn)
switch (value)
{
case 0:
s_printf(txt_buf + strlen(txt_buf), "Normal");
strcat(txt_buf, "Normal");
break;
case 2:
s_printf(txt_buf + strlen(txt_buf), "Warm");
strcat(txt_buf, "Warm");
break;
case 3:
s_printf(txt_buf + strlen(txt_buf), "Cool");
strcat(txt_buf, "Cool");
break;
case 5:
s_printf(txt_buf + strlen(txt_buf), "Cold");
strcat(txt_buf, "Cold");
break;
case 6:
s_printf(txt_buf + strlen(txt_buf), "Hot");
strcat(txt_buf, "Hot");
break;
default:
s_printf(txt_buf + strlen(txt_buf), "Unknown (%d)", value);
break;
}
bool inserted;
u32 wattage = 0;
usb_pd_objects_t usb_pd;
bm92t36_get_sink_info(&inserted, &usb_pd);
strcat(txt_buf, "\n\n\n");
strcat(txt_buf, inserted ? "Connected" : "Disconnected");
// Select 5V is no PD contract.
wattage = iinlim * (usb_pd.pdo_no ? usb_pd.selected_pdo.voltage : 5);
s_printf(txt_buf + strlen(txt_buf), "\n%d.%d W", wattage / 1000, (wattage % 1000) / 100);
if (!usb_pd.pdo_no)
strcat(txt_buf, "\nNon PD");
// 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++)
{
bool selected =
usb_pd.pdos[i].amperage == usb_pd.selected_pdo.amperage &&
usb_pd.pdos[i].voltage == usb_pd.selected_pdo.voltage;
s_printf(txt_buf + strlen(txt_buf), "\n%s%d mA, %2d V%s",
selected ? "#D4FF00 " : "",
usb_pd.pdos[i].amperage, usb_pd.pdos[i].voltage,
selected ? "#" : "");
}
lv_label_set_text(lb_val2, txt_buf);
lv_obj_set_width(lb_val2, lv_obj_get_width(val2));

View File

@@ -740,10 +740,20 @@ void first_time_clock_edit(void *param)
static lv_res_t _joycon_info_dump_action(lv_obj_t * btn)
{
FIL fp;
int error;
bool is_l_hos = false;
bool is_r_hos = false;
jc_gamepad_rpt_t *jc_pad = jc_get_bt_pairing_info(&is_l_hos, &is_r_hos);
char *data = (char *)malloc(0x4000);
char *txt_buf = (char *)malloc(0x1000);
if (!jc_pad)
{
error = 255;
goto disabled;
}
// Count valid joycon.
u32 joycon_found = jc_pad->bt_conn_l.type ? 1 : 0;
if (jc_pad->bt_conn_r.type)
@@ -753,10 +763,7 @@ static lv_res_t _joycon_info_dump_action(lv_obj_t * btn)
jc_pad->bt_conn_l.type = is_l_hos ? jc_pad->bt_conn_l.type : 0;
jc_pad->bt_conn_r.type = is_r_hos ? jc_pad->bt_conn_r.type : 0;
int error = !sd_mount();
char *data = (char *)malloc(0x4000);
char *txt_buf = (char *)malloc(0x1000);
error = !sd_mount();
if (!error)
{
@@ -798,6 +805,7 @@ static lv_res_t _joycon_info_dump_action(lv_obj_t * btn)
sd_unmount();
}
disabled:;
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);
@@ -817,7 +825,7 @@ static lv_res_t _joycon_info_dump_action(lv_obj_t * btn)
// Check if pairing info was found.
if (joycon_found == 2)
s_printf(txt_buf + strlen(txt_buf), "#C7EA46 Found 2 out of 2 Joy-Con pairing data!#\n");
strcat(txt_buf, "#C7EA46 Found 2 out of 2 Joy-Con pairing data!#\n");
else
{
s_printf(txt_buf + strlen(txt_buf), "#FF8000 Warning:# Found #FFDD00 %d out of 2# pairing data!\n", joycon_found);
@@ -826,25 +834,25 @@ static lv_res_t _joycon_info_dump_action(lv_obj_t * btn)
// Check if pairing was done in HOS.
if (is_l_hos && is_r_hos)
s_printf(txt_buf + strlen(txt_buf), "#C7EA46 Both pairing data are HOS based!#");
strcat(txt_buf, "#C7EA46 Both pairing data are HOS based!#");
else if (!is_l_hos && is_r_hos)
{
s_printf(txt_buf + strlen(txt_buf), "#FF8000 Warning:# #FFDD00 Left# pairing data is not HOS based!");
strcat(txt_buf, "#FF8000 Warning:# #FFDD00 Left# pairing data is not HOS based!");
success = false;
}
else if (is_l_hos && !is_r_hos)
{
s_printf(txt_buf + strlen(txt_buf), "#FF8000 Warning:# #FFDD00 Right# pairing data is not HOS based!");
strcat(txt_buf, "#FF8000 Warning:# #FFDD00 Right# pairing data is not HOS based!");
success = false;
}
else
{
s_printf(txt_buf + strlen(txt_buf), "#FF8000 Warning:# #FFDD00 No# pairing data is HOS based!");
strcat(txt_buf, "#FF8000 Warning:# #FFDD00 No# pairing data is HOS based!");
success = false;
}
if (!success)
s_printf(txt_buf + strlen(txt_buf),
strcat(txt_buf,
"\n\n#FFDD00 Make sure that both Joy-Con are connected,#\n"
"#FFDD00 and that you paired them in HOS!#");
}

View File

@@ -173,16 +173,17 @@ static lv_res_t _create_mbox_hid(usb_ctxt_t *usbs)
lv_obj_t *mbox = lv_mbox_create(dark_bg, NULL);
lv_mbox_set_recolor_text(mbox, true);
char *text_buf = malloc(0x1000);
char *txt_buf = malloc(0x1000);
s_printf(text_buf, "#FF8000 HID Emulation#\n\n#C7EA46 Device:# ");
s_printf(txt_buf, "#FF8000 HID Emulation#\n\n#C7EA46 Device:# ");
if (usbs->type == USB_HID_GAMEPAD)
s_printf(text_buf + strlen(text_buf), "Gamepad");
strcat(txt_buf, "Gamepad");
else
s_printf(text_buf + strlen(text_buf), "Touchpad");
strcat(txt_buf, "Touchpad");
lv_mbox_set_text(mbox, text_buf);
lv_mbox_set_text(mbox, txt_buf);
free(txt_buf);
lv_obj_t *lbl_status = lv_label_create(mbox, NULL);
lv_label_set_recolor(lbl_status, true);
@@ -217,25 +218,25 @@ static lv_res_t _create_mbox_ums(usb_ctxt_t *usbs)
lv_obj_t *mbox = lv_mbox_create(dark_bg, NULL);
lv_mbox_set_recolor_text(mbox, true);
char *text_buf = malloc(0x1000);
char *txt_buf = malloc(0x1000);
s_printf(text_buf, "#FF8000 USB Mass Storage#\n\n#C7EA46 Device:# ");
s_printf(txt_buf, "#FF8000 USB Mass Storage#\n\n#C7EA46 Device:# ");
if (usbs->type == MMC_SD)
{
switch (usbs->partition)
{
case 0:
s_printf(text_buf + strlen(text_buf), "SD Card");
strcat(txt_buf, "SD Card");
break;
case EMMC_GPP + 1:
s_printf(text_buf + strlen(text_buf), "emuMMC GPP");
strcat(txt_buf, "emuMMC GPP");
break;
case EMMC_BOOT0 + 1:
s_printf(text_buf + strlen(text_buf), "emuMMC BOOT0");
strcat(txt_buf, "emuMMC BOOT0");
break;
case EMMC_BOOT1 + 1:
s_printf(text_buf + strlen(text_buf), "emuMMC BOOT1");
strcat(txt_buf, "emuMMC BOOT1");
break;
}
}
@@ -244,18 +245,19 @@ static lv_res_t _create_mbox_ums(usb_ctxt_t *usbs)
switch (usbs->partition)
{
case EMMC_GPP + 1:
s_printf(text_buf + strlen(text_buf), "eMMC GPP");
strcat(txt_buf, "eMMC GPP");
break;
case EMMC_BOOT0 + 1:
s_printf(text_buf + strlen(text_buf), "eMMC BOOT0");
strcat(txt_buf, "eMMC BOOT0");
break;
case EMMC_BOOT1 + 1:
s_printf(text_buf + strlen(text_buf), "eMMC BOOT1");
strcat(txt_buf, "eMMC BOOT1");
break;
}
}
lv_mbox_set_text(mbox, text_buf);
lv_mbox_set_text(mbox, txt_buf);
free(txt_buf);
lv_obj_t *lbl_status = lv_label_create(mbox, NULL);
lv_label_set_recolor(lbl_status, true);
@@ -947,7 +949,7 @@ static lv_res_t _create_mbox_fix_touchscreen(lv_obj_t *btn)
lv_obj_t * mbox = lv_mbox_create(dark_bg, NULL);
lv_mbox_set_recolor_text(mbox, true);
char *txt_buf = malloc(0x1000);
char *txt_buf = malloc(0x4000);
strcpy(txt_buf, "#FF8000 Don't touch the screen!#\n\nThe tuning process will start in ");
u32 text_idx = strlen(txt_buf);
lv_mbox_set_text(mbox, txt_buf);
@@ -994,45 +996,45 @@ static lv_res_t _create_mbox_fix_touchscreen(lv_obj_t *btn)
switch (err[0])
{
case ITO_FORCE_OPEN:
s_printf(txt_buf + strlen(txt_buf), "Force Open");
strcat(txt_buf, "Force Open");
break;
case ITO_SENSE_OPEN:
s_printf(txt_buf + strlen(txt_buf), "Sense Open");
strcat(txt_buf, "Sense Open");
break;
case ITO_FORCE_SHRT_GND:
s_printf(txt_buf + strlen(txt_buf), "Force Short to GND");
strcat(txt_buf, "Force Short to GND");
break;
case ITO_SENSE_SHRT_GND:
s_printf(txt_buf + strlen(txt_buf), "Sense Short to GND");
strcat(txt_buf, "Sense Short to GND");
break;
case ITO_FORCE_SHRT_VCM:
s_printf(txt_buf + strlen(txt_buf), "Force Short to VDD");
strcat(txt_buf, "Force Short to VDD");
break;
case ITO_SENSE_SHRT_VCM:
s_printf(txt_buf + strlen(txt_buf), "Sense Short to VDD");
strcat(txt_buf, "Sense Short to VDD");
break;
case ITO_FORCE_SHRT_FORCE:
s_printf(txt_buf + strlen(txt_buf), "Force Short to Force");
strcat(txt_buf, "Force Short to Force");
break;
case ITO_SENSE_SHRT_SENSE:
s_printf(txt_buf + strlen(txt_buf), "Sense Short to Sense");
strcat(txt_buf, "Sense Short to Sense");
break;
case ITO_F2E_SENSE:
s_printf(txt_buf + strlen(txt_buf), "Force Short to Sense");
strcat(txt_buf, "Force Short to Sense");
break;
case ITO_FPC_FORCE_OPEN:
s_printf(txt_buf + strlen(txt_buf), "FPC Force Open");
strcat(txt_buf, "FPC Force Open");
break;
case ITO_FPC_SENSE_OPEN:
s_printf(txt_buf + strlen(txt_buf), "FPC Sense Open");
strcat(txt_buf, "FPC Sense Open");
break;
default:
s_printf(txt_buf + strlen(txt_buf), "Unknown");
strcat(txt_buf, "Unknown");
break;
}
s_printf(txt_buf + strlen(txt_buf), " (%d), Chn: %d#\n\n", err[0], err[1]);
s_printf(txt_buf + strlen(txt_buf), "#FFFF00 The touchscreen calibration failed!");
strcat(txt_buf, "#FFFF00 The touchscreen calibration failed!");
lv_mbox_set_text(mbox, txt_buf);
goto out2;
}
@@ -1079,15 +1081,14 @@ static lv_res_t _create_window_dump_pk12_tool(lv_obj_t *btn)
char path[128];
u8 kb = 0;
u8 *pkg1 = (u8 *)calloc(1, 0x40000);
u8 *warmboot = (u8 *)calloc(1, 0x40000);
u8 *secmon = (u8 *)calloc(1, 0x40000);
u8 *loader = (u8 *)calloc(1, 0x40000);
u8 *pkg2 = NULL;
u8 kb = 0;
char *txt_buf = (char *)malloc(0x4000);
char *txt_buf2 = (char *)malloc(0x4000);
tsec_ctxt_t tsec_ctxt;
@@ -1104,8 +1105,13 @@ static lv_res_t _create_window_dump_pk12_tool(lv_obj_t *btn)
sdmmc_storage_set_mmc_partition(&storage, EMMC_BOOT0);
// Read package1.
static const u32 BOOTLOADER_SIZE = 0x40000;
static const u32 BOOTLOADER_MAIN_OFFSET = 0x100000;
static const u32 HOS_KEYBLOBS_OFFSET = 0x180000;
char *build_date = malloc(32);
sdmmc_storage_read(&storage, 0x100000 / NX_EMMC_BLOCKSIZE, 0x40000 / NX_EMMC_BLOCKSIZE, pkg1);
sdmmc_storage_read(&storage, BOOTLOADER_MAIN_OFFSET / NX_EMMC_BLOCKSIZE, BOOTLOADER_SIZE / NX_EMMC_BLOCKSIZE, pkg1);
const pkg1_id_t *pkg1_id = pkg1_identify(pkg1, build_date);
s_printf(txt_buf, "#00DDFF Found pkg1 ('%s')#\n\n", build_date);
@@ -1116,24 +1122,21 @@ static lv_res_t _create_window_dump_pk12_tool(lv_obj_t *btn)
// Dump package1 in its encrypted state if unknown.
if (!pkg1_id)
{
s_printf(txt_buf + strlen(txt_buf),
"#FFDD00 Unknown pkg1 version for reading#\n#FFDD00 TSEC firmware!#");
strcat(txt_buf, "#FFDD00 Unknown pkg1 version for reading#\n#FFDD00 TSEC firmware!#");
lv_label_set_text(lb_desc, txt_buf);
manual_system_maintenance(true);
emmcsn_path_impl(path, "/pkg1", "pkg1_enc.bin", &storage);
if (sd_save_to_file(pkg1, 0x40000, path))
if (sd_save_to_file(pkg1, BOOTLOADER_SIZE, path))
goto out_free;
s_printf(txt_buf + strlen(txt_buf), "\nEncrypted pkg1 dumped to pkg1_enc.bin");
strcat(txt_buf, "\nEncrypted pkg1 dumped to pkg1_enc.bin");
lv_label_set_text(lb_desc, txt_buf);
manual_system_maintenance(true);
goto out_free;
}
const pk11_hdr_t *hdr = (pk11_hdr_t *)(pkg1 + pkg1_id->pkg11_off + 0x20);
kb = pkg1_id->kb;
if (!h_cfg.se_keygen_done)
@@ -1169,7 +1172,7 @@ static lv_res_t _create_window_dump_pk12_tool(lv_obj_t *btn)
// Read keyblob.
u8 *keyblob = (u8 *)calloc(NX_EMMC_BLOCKSIZE, 1);
sdmmc_storage_read(&storage, 0x180000 / NX_EMMC_BLOCKSIZE + kb, 1, keyblob);
sdmmc_storage_read(&storage, HOS_KEYBLOBS_OFFSET / NX_EMMC_BLOCKSIZE + kb, 1, keyblob);
// Decrypt.
hos_keygen(keyblob, kb, &tsec_ctxt);
@@ -1183,7 +1186,21 @@ static lv_res_t _create_window_dump_pk12_tool(lv_obj_t *btn)
if (kb <= KB_FIRMWARE_VERSION_620)
{
pkg1_unpack(warmboot, secmon, loader, pkg1_id, pkg1);
const u8 *sec_map = pkg1_unpack(warmboot, secmon, loader, pkg1_id, pkg1);
pk11_hdr_t *hdr_pk11 = (pk11_hdr_t *)(pkg1 + pkg1_id->pkg11_off + 0x20);
// Use correct sizes.
u32 sec_size[3] = { hdr_pk11->wb_size, hdr_pk11->ldr_size, hdr_pk11->sm_size };
for (u32 i = 0; i < 3; i++)
{
if (sec_map[i] == PK11_SECTION_WB)
hdr_pk11->wb_size = sec_size[i];
else if (sec_map[i] == PK11_SECTION_LD)
hdr_pk11->ldr_size = sec_size[i];
else if (sec_map[i] == PK11_SECTION_SM)
hdr_pk11->sm_size = sec_size[i];
}
// Display info.
s_printf(txt_buf + strlen(txt_buf),
@@ -1192,7 +1209,7 @@ static lv_res_t _create_window_dump_pk12_tool(lv_obj_t *btn)
"#C7EA46 Secure monitor size: #0x%05X\n"
"#C7EA46 Warmboot addr: #0x%05X\n"
"#C7EA46 Warmboot size: #0x%05X\n\n",
hdr->ldr_size, pkg1_id->secmon_base, hdr->sm_size, pkg1_id->warmboot_base, hdr->wb_size);
hdr_pk11->ldr_size, pkg1_id->secmon_base, hdr_pk11->sm_size, pkg1_id->warmboot_base, hdr_pk11->wb_size);
lv_label_set_text(lb_desc, txt_buf);
manual_system_maintenance(true);
@@ -1201,31 +1218,31 @@ static lv_res_t _create_window_dump_pk12_tool(lv_obj_t *btn)
emmcsn_path_impl(path, "/pkg1", "pkg1_decr.bin", &storage);
if (sd_save_to_file(pkg1, 0x40000, path))
goto out_free;
s_printf(txt_buf + strlen(txt_buf), "pkg1 dumped to pkg1_decr.bin\n");
strcat(txt_buf, "pkg1 dumped to pkg1_decr.bin\n");
lv_label_set_text(lb_desc, txt_buf);
manual_system_maintenance(true);
// Dump nxbootloader.
emmcsn_path_impl(path, "/pkg1", "nxloader.bin", &storage);
if (sd_save_to_file(loader, hdr->ldr_size, path))
if (sd_save_to_file(loader, hdr_pk11->ldr_size, path))
goto out_free;
s_printf(txt_buf + strlen(txt_buf), "NX Bootloader dumped to nxloader.bin\n");
strcat(txt_buf, "NX Bootloader dumped to nxloader.bin\n");
lv_label_set_text(lb_desc, txt_buf);
manual_system_maintenance(true);
// Dump secmon.
emmcsn_path_impl(path, "/pkg1", "secmon.bin", &storage);
if (sd_save_to_file(secmon, hdr->sm_size, path))
if (sd_save_to_file(secmon, hdr_pk11->sm_size, path))
goto out_free;
s_printf(txt_buf + strlen(txt_buf), "Secure Monitor dumped to secmon.bin\n");
strcat(txt_buf, "Secure Monitor dumped to secmon.bin\n");
lv_label_set_text(lb_desc, txt_buf);
manual_system_maintenance(true);
// Dump warmboot.
emmcsn_path_impl(path, "/pkg1", "warmboot.bin", &storage);
if (sd_save_to_file(warmboot, hdr->wb_size, path))
if (sd_save_to_file(warmboot, hdr_pk11->wb_size, path))
goto out_free;
s_printf(txt_buf + strlen(txt_buf), "Warmboot dumped to warmboot.bin\n\n");
strcat(txt_buf, "Warmboot dumped to warmboot.bin\n\n");
lv_label_set_text(lb_desc, txt_buf);
manual_system_maintenance(true);
}
@@ -1262,7 +1279,7 @@ static lv_res_t _create_window_dump_pk12_tool(lv_obj_t *btn)
pkg2_hdr_t *pkg2_hdr = pkg2_decrypt(pkg2, kb);
if (!pkg2_hdr)
{
s_printf(txt_buf + strlen(txt_buf), "#FFDD00 Pkg2 decryption failed!#");
strcat(txt_buf, "#FFDD00 Pkg2 decryption failed!#");
lv_label_set_text(lb_desc, txt_buf);
manual_system_maintenance(true);
@@ -1287,7 +1304,7 @@ static lv_res_t _create_window_dump_pk12_tool(lv_obj_t *btn)
emmcsn_path_impl(path, "/pkg2", "pkg2_decr.bin", &storage);
if (sd_save_to_file(pkg2, pkg2_hdr->sec_size[PKG2_SEC_KERNEL] + pkg2_hdr->sec_size[PKG2_SEC_INI1], path))
goto out;
s_printf(txt_buf + strlen(txt_buf), "pkg2 dumped to pkg2_decr.bin\n");
strcat(txt_buf, "pkg2 dumped to pkg2_decr.bin\n");
lv_label_set_text(lb_desc, txt_buf);
manual_system_maintenance(true);
@@ -1295,7 +1312,7 @@ static lv_res_t _create_window_dump_pk12_tool(lv_obj_t *btn)
emmcsn_path_impl(path, "/pkg2", "kernel.bin", &storage);
if (sd_save_to_file(pkg2_hdr->data, pkg2_hdr->sec_size[PKG2_SEC_KERNEL], path))
goto out;
s_printf(txt_buf + strlen(txt_buf), "Kernel dumped to kernel.bin\n");
strcat(txt_buf, "Kernel dumped to kernel.bin\n");
lv_label_set_text(lb_desc, txt_buf);
manual_system_maintenance(true);
@@ -1311,7 +1328,7 @@ static lv_res_t _create_window_dump_pk12_tool(lv_obj_t *btn)
if (!ini1_off)
{
s_printf(txt_buf + strlen(txt_buf), "#FFDD00 Failed to dump INI1 and kips!#\n");
strcat(txt_buf, "#FFDD00 Failed to dump INI1 and kips!#\n");
goto out;
}
@@ -1320,7 +1337,7 @@ static lv_res_t _create_window_dump_pk12_tool(lv_obj_t *btn)
if (sd_save_to_file(ini1, ini1_size, path))
goto out;
s_printf(txt_buf + strlen(txt_buf), "INI1 dumped to ini1.bin\n\n");
strcat(txt_buf, "INI1 dumped to ini1.bin\n\n");
lv_label_set_text(lb_desc, txt_buf);
manual_system_maintenance(true);
@@ -1367,7 +1384,6 @@ out_free:
free(loader);
free(pkg2);
free(txt_buf);
free(txt_buf2);
sdmmc_storage_end(&storage);
sd_unmount();
@@ -1616,7 +1632,7 @@ static void _create_tab_tools_arc_autorcm(lv_theme_t *th, lv_obj_t *parent)
"#FF3C28 bootloader.#");
if (h_cfg.rcm_patched)
s_printf(txt_buf + strlen(txt_buf), " #FF8000 This is disabled because this unit is patched!#");
strcat(txt_buf, " #FF8000 This is disabled because this unit is patched!#");
lv_obj_t *label_txt4 = lv_label_create(h2, NULL);
lv_label_set_recolor(label_txt4, true);

View File

@@ -676,7 +676,7 @@ static lv_res_t _action_flash_linux_data(lv_obj_t * btns, const char * txt)
if (pct != prevPct)
{
lv_bar_set_value(bar, pct);
s_printf(txt_buf, " "SYMBOL_DOT" %d%%", pct);
s_printf(txt_buf, " #DDDDDD "SYMBOL_DOT"# %d%%", pct);
lv_label_set_text(label_pct, txt_buf);
manual_system_maintenance(true);
prevPct = pct;
@@ -810,8 +810,26 @@ static lv_res_t _action_check_flash_linux(lv_obj_t *btn)
{
if ((u64)fno.fsize % 0x400000)
{
lv_label_set_text(lbl_status, "#FFDD00 Error:# The image is not aligned to 4 MiB!");
goto error;
// Check if last part.
idx++;
if (idx < 10)
{
path[23] = '0';
itoa(idx, &path[23 + 1], 10);
}
else
itoa(idx, &path[23], 10);
// If not the last part, unaligned size is not permitted.
if (!f_stat(path, NULL)) // NULL: Don't override current part fs info.
{
lv_label_set_text(lbl_status, "#FFDD00 Error:# The image is not aligned to 4 MiB!");
goto error;
}
// Last part. Align size to LBA (512 bytes).
fno.fsize = ALIGN((u64)fno.fsize, 512);
idx--;
}
l4t_flash_ctxt.image_size_sct += (u64)fno.fsize >> 9;
}
@@ -867,7 +885,7 @@ static lv_res_t _action_reboot_twrp(lv_obj_t * btns, const char * txt)
sd_end();
reconfig_hw_workaround(false, 0);
hw_reinit_workaround(false, 0);
(*main_ptr)();
}
@@ -894,7 +912,7 @@ static lv_res_t _action_flash_android_data(lv_obj_t * btns, const char * txt)
lv_obj_set_size(dark_bg, LV_HOR_RES, LV_VER_RES);
static const char *mbox_btn_map[] = { "\211", "\222OK", "\211", "" };
static const char *mbox_btn_map2[] = { "\222Continue", "\222Cancel", "" };
static const char *mbox_btn_map2[] = { "\222Continue", "\222No", "" };
lv_obj_t *mbox = lv_mbox_create(dark_bg, NULL);
lv_mbox_set_recolor_text(mbox, true);
lv_obj_set_width(mbox, LV_HOR_RES / 9 * 6);
@@ -1008,21 +1026,21 @@ static lv_res_t _action_flash_android_data(lv_obj_t * btns, const char * txt)
}
if ((file_size >> 9) > size_sct)
s_printf(txt_buf + strlen(txt_buf), "#FF8000 Warning:# TWRP image too big!\n");
strcat(txt_buf, "#FF8000 Warning:# TWRP image too big!\n");
else
{
sdmmc_storage_write(&sd_storage, offset_sct, file_size >> 9, buf);
s_printf(txt_buf + strlen(txt_buf), "#C7EA46 Success:# TWRP image flashed!\n");
strcat(txt_buf, "#C7EA46 Success:# TWRP image flashed!\n");
f_unlink(path);
}
free(buf);
}
else
s_printf(txt_buf + strlen(txt_buf), "#FF8000 Warning:# TWRP partition not found!\n");
strcat(txt_buf, "#FF8000 Warning:# TWRP partition not found!\n");
}
else
s_printf(txt_buf + strlen(txt_buf), "#FF8000 Warning:# TWRP image not found!\n");
strcat(txt_buf, "#FF8000 Warning:# TWRP image not found!\n");
lv_label_set_text(lbl_status, txt_buf);
manual_system_maintenance(true);
@@ -1060,21 +1078,21 @@ static lv_res_t _action_flash_android_data(lv_obj_t * btns, const char * txt)
}
if ((file_size >> 9) > size_sct)
s_printf(txt_buf + strlen(txt_buf), "#FF8000 Warning:# DTB image too big!");
strcat(txt_buf, "#FF8000 Warning:# DTB image too big!");
else
{
sdmmc_storage_write(&sd_storage, offset_sct, file_size >> 9, buf);
s_printf(txt_buf + strlen(txt_buf), "#C7EA46 Success:# DTB image flashed!");
strcat(txt_buf, "#C7EA46 Success:# DTB image flashed!");
f_unlink(path);
}
free(buf);
}
else
s_printf(txt_buf + strlen(txt_buf), "#FF8000 Warning:# DTB partition not found!");
strcat(txt_buf, "#FF8000 Warning:# DTB partition not found!");
}
else
s_printf(txt_buf + strlen(txt_buf), "#FF8000 Warning:# DTB image not found!");
strcat(txt_buf, "#FF8000 Warning:# DTB image not found!");
lv_label_set_text(lbl_status, txt_buf);
@@ -1098,7 +1116,7 @@ static lv_res_t _action_flash_android_data(lv_obj_t * btns, const char * txt)
error:
if (boot_twrp)
{
s_printf(txt_buf + strlen(txt_buf),"\n\nDo you want to reboot into TWRP\nto finish Android installation?");
strcat(txt_buf,"\n\nDo you want to reboot into TWRP\nto finish Android installation?");
lv_label_set_text(lbl_status, txt_buf);
lv_mbox_add_btns(mbox, mbox_btn_map2, _action_reboot_twrp);
}
@@ -1525,9 +1543,9 @@ static lv_res_t _create_mbox_partitioning_next(lv_obj_t *btn)
s_printf(txt_buf, "#FFDD00 Warning: This will partition your SD Card!#\n\n");
if (part_info.backup_possible)
s_printf(txt_buf + strlen(txt_buf), "#C7EA46 Your files will be backed up and restored!#");
strcat(txt_buf, "#C7EA46 Your files will be backed up and restored!#");
else
s_printf(txt_buf + strlen(txt_buf), "#FFDD00 Your files will be wiped!#\n#FFDD00 Use USB UMS to copy them over!#");
strcat(txt_buf, "#FFDD00 Your files will be wiped!#\n#FFDD00 Use USB UMS to copy them over!#");
lv_label_set_text(lbl_status, txt_buf);

View File

@@ -45,23 +45,6 @@ extern hekate_config h_cfg;
static u8 *bis_keys = NULL;
//#define DPRINTF(...) gfx_printf(__VA_ARGS__)
#define DPRINTF(...)
#define PKG2_LOAD_ADDR 0xA9800000
// Secmon mailbox.
#define SECMON_MB_ADDR 0x40002EF8
#define SECMON7_MB_ADDR 0x400000F8
typedef struct _secmon_mailbox_t
{
// < 4.0.0 Signals - 0: Not ready, 1: BCT ready, 2: DRAM and pkg2 ready, 3: Continue boot.
// >= 4.0.0 Signals - 0: Not ready, 1: BCT ready, 2: DRAM ready, 4: pkg2 ready and continue boot.
u32 in;
// Non-zero: Secmon ready.
u32 out;
} secmon_mailbox_t;
static const u8 keyblob_keyseeds[][0x10] = {
{ 0xDF, 0x20, 0x6F, 0x59, 0x44, 0x54, 0xEF, 0xDC, 0x70, 0x74, 0x48, 0x3B, 0x0D, 0xED, 0x9F, 0xD3 }, // 1.0.0.
{ 0x0C, 0x25, 0x61, 0x5D, 0x68, 0x4C, 0xEB, 0x42, 0x1C, 0x23, 0x79, 0xEA, 0x82, 0x25, 0x12, 0xAC }, // 3.0.0.
@@ -77,21 +60,21 @@ static const u8 cmac_keyseed[0x10] =
static const u8 master_keyseed_retail[0x10] =
{ 0xD8, 0xA2, 0x41, 0x0A, 0xC6, 0xC5, 0x90, 0x01, 0xC6, 0x1D, 0x6A, 0x26, 0x7C, 0x51, 0x3F, 0x3C };
static const u8 console_keyseed[0x10] =
{ 0x4F, 0x02, 0x5F, 0x0E, 0xB6, 0x6D, 0x11, 0x0E, 0xDC, 0x32, 0x7D, 0x41, 0x86, 0xC2, 0xF4, 0x78 };
const u8 package2_keyseed[0x10] =
{ 0xFB, 0x8B, 0x6A, 0x9C, 0x79, 0x00, 0xC8, 0x49, 0xEF, 0xD2, 0x4D, 0x85, 0x4D, 0x30, 0xA0, 0xC7 };
static const u8 master_keyseed_4xx_5xx_610[0x10] =
{ 0x2D, 0xC1, 0xF4, 0x8D, 0xF3, 0x5B, 0x69, 0x33, 0x42, 0x10, 0xAC, 0x65, 0xDA, 0x90, 0x46, 0x66 };
static const u8 master_keyseed_620[0x10] =
{ 0x37, 0x4B, 0x77, 0x29, 0x59, 0xB4, 0x04, 0x30, 0x81, 0xF6, 0xE5, 0x8C, 0x6D, 0x36, 0x17, 0x9A };
static const u8 console_keyseed[0x10] =
{ 0x4F, 0x02, 0x5F, 0x0E, 0xB6, 0x6D, 0x11, 0x0E, 0xDC, 0x32, 0x7D, 0x41, 0x86, 0xC2, 0xF4, 0x78 };
static const u8 console_keyseed_4xx_5xx[0x10] =
{ 0x0C, 0x91, 0x09, 0xDB, 0x93, 0x93, 0x07, 0x81, 0x07, 0x3C, 0xC4, 0x16, 0x22, 0x7C, 0x6C, 0x28 };
const u8 package2_keyseed[0x10] =
{ 0xFB, 0x8B, 0x6A, 0x9C, 0x79, 0x00, 0xC8, 0x49, 0xEF, 0xD2, 0x4D, 0x85, 0x4D, 0x30, 0xA0, 0xC7 };
static const u8 mkey_vectors[KB_FIRMWARE_VERSION_MAX + 1][0x10] = {
{ 0x0C, 0xF0, 0x59, 0xAC, 0x85, 0xF6, 0x26, 0x65, 0xE1, 0xE9, 0x19, 0x55, 0xE6, 0xF2, 0x67, 0x3D }, // Zeroes encrypted with mkey 00.
{ 0x29, 0x4C, 0x04, 0xC8, 0xEB, 0x10, 0xED, 0x9D, 0x51, 0x64, 0x97, 0xFB, 0xF3, 0x4D, 0x50, 0xDD }, // Mkey 00 encrypted with mkey 01.
@@ -106,7 +89,7 @@ static const u8 mkey_vectors[KB_FIRMWARE_VERSION_MAX + 1][0x10] = {
{ 0xB8, 0x96, 0x9E, 0x4A, 0x00, 0x0D, 0xD6, 0x28, 0xB3, 0xD1, 0xDB, 0x68, 0x5F, 0xFB, 0xE1, 0x2A }, // Mkey 09 encrypted with mkey 10.
};
static const u8 new_console_keyseed_4xx[KB_FIRMWARE_VERSION_MAX - KB_FIRMWARE_VERSION_400 + 1][0x10] = {
static const u8 new_console_keyseed[KB_FIRMWARE_VERSION_MAX - KB_FIRMWARE_VERSION_400 + 1][0x10] = {
{ 0x8B, 0x4E, 0x1C, 0x22, 0x42, 0x07, 0xC8, 0x73, 0x56, 0x94, 0x08, 0x8B, 0xCC, 0x47, 0x0F, 0x5D }, // 4.x New Device Key Source.
{ 0x6C, 0xEF, 0xC6, 0x27, 0x8B, 0xEC, 0x8A, 0x91, 0x99, 0xAB, 0x24, 0xAC, 0x4F, 0x1C, 0x8F, 0x1C }, // 5.x New Device Key Source.
{ 0x70, 0x08, 0x1B, 0x97, 0x44, 0x64, 0xF8, 0x91, 0x54, 0x9D, 0xC6, 0x84, 0x8F, 0x1A, 0xB2, 0xE4 }, // 6.x New Device Key Source.
@@ -117,7 +100,7 @@ static const u8 new_console_keyseed_4xx[KB_FIRMWARE_VERSION_MAX - KB_FIRMWARE_VE
{ 0x14, 0xB8, 0x74, 0x12, 0xCB, 0xBD, 0x0B, 0x8F, 0x20, 0xFB, 0x30, 0xDA, 0x27, 0xE4, 0x58, 0x94 }, // 9.1.0 New Device Key Source.
};
static const u8 new_console_keyseed[KB_FIRMWARE_VERSION_MAX - KB_FIRMWARE_VERSION_400 + 1][0x10] = {
static const u8 new_console_kekseed[KB_FIRMWARE_VERSION_MAX - KB_FIRMWARE_VERSION_400 + 1][0x10] = {
{ 0x88, 0x62, 0x34, 0x6E, 0xFA, 0xF7, 0xD8, 0x3F, 0xE1, 0x30, 0x39, 0x50, 0xF0, 0xB7, 0x5D, 0x5D }, // 4.x New Device Keygen Source.
{ 0x06, 0x1E, 0x7B, 0xE9, 0x6D, 0x47, 0x8C, 0x77, 0xC5, 0xC8, 0xE7, 0x94, 0x9A, 0xA8, 0x5F, 0x2E }, // 5.x New Device Keygen Source.
{ 0x99, 0xFA, 0x98, 0xBD, 0x15, 0x1C, 0x72, 0xFD, 0x7D, 0x9A, 0xD5, 0x41, 0x00, 0xFD, 0xB2, 0xEF }, // 6.x New Device Keygen Source.
@@ -125,7 +108,7 @@ static const u8 new_console_keyseed[KB_FIRMWARE_VERSION_MAX - KB_FIRMWARE_VERSIO
{ 0x86, 0x61, 0xB0, 0x16, 0xFA, 0x7A, 0x9A, 0xEA, 0xF6, 0xF5, 0xBE, 0x1A, 0x13, 0x5B, 0x6D, 0x9E }, // 7.0.0 New Device Keygen Source.
{ 0xA6, 0x81, 0x71, 0xE7, 0xB5, 0x23, 0x74, 0xB0, 0x39, 0x8C, 0xB7, 0xFF, 0xA0, 0x62, 0x9F, 0x8D }, // 8.1.0 New Device Keygen Source.
{ 0x03, 0xE7, 0xEB, 0x43, 0x1B, 0xCF, 0x5F, 0xB5, 0xED, 0xDC, 0x97, 0xAE, 0x21, 0x8D, 0x19, 0xED }, // 9.0.0 New Device Keygen Source.
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // TODO: 9.1.0 New Device Keygen Source to be added on next change-of-keys. */
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // TODO: 9.1.0 New Device Keygen Source to be added on next change-of-keys.
};
static const u8 gen_keyseed[0x10] =
@@ -179,7 +162,7 @@ void hos_eks_get()
goto out;
// Decrypt EKS blob.
hos_eks_mbr_t *eks = (hos_eks_mbr_t *)(mbr + 0x60);
hos_eks_mbr_t *eks = (hos_eks_mbr_t *)(mbr + 0x80);
se_aes_crypt_ecb(14, 0, eks, sizeof(hos_eks_mbr_t), eks, sizeof(hos_eks_mbr_t));
// Check if valid and for this unit.
@@ -231,6 +214,10 @@ void hos_eks_save(u32 kb)
u8 *keys = (u8 *)calloc(0x1000, 1);
se_get_aes_keys(keys + 0x800, keys, 0x10);
// Set SBK back.
if (h_cfg.sbk_set)
se_aes_key_set(14, keys + 14 * 0x10, 0x10);
// Set magic and personalized info.
h_cfg.eks->magic = HOS_EKS_MAGIC;
h_cfg.eks->enabled[key_idx] = kb;
@@ -257,7 +244,7 @@ void hos_eks_save(u32 kb)
se_aes_crypt_ecb(14, 1, eks, sizeof(hos_eks_mbr_t), eks, sizeof(hos_eks_mbr_t));
// Write EKS blob to SD.
memcpy(mbr + 0x60, eks, sizeof(hos_eks_mbr_t));
memcpy(mbr + 0x80, eks, sizeof(hos_eks_mbr_t));
hos_eks_rw_try(mbr, true);
@@ -294,7 +281,7 @@ void hos_eks_clear(u32 kb)
se_aes_crypt_ecb(14, 1, eks, sizeof(hos_eks_mbr_t), eks, sizeof(hos_eks_mbr_t));
// Write EKS blob to SD.
memcpy(mbr + 0x60, eks, sizeof(hos_eks_mbr_t));
memcpy(mbr + 0x80, eks, sizeof(hos_eks_mbr_t));
hos_eks_rw_try(mbr, true);
EMC(EMC_SCRATCH0) &= ~EMC_SEPT_RUN;
@@ -353,7 +340,7 @@ void hos_eks_bis_save()
se_aes_crypt_ecb(14, 1, eks, sizeof(hos_eks_mbr_t), eks, sizeof(hos_eks_mbr_t));
// Write EKS blob to SD.
memcpy(mbr + 0x60, eks, sizeof(hos_eks_mbr_t));
memcpy(mbr + 0x80, eks, sizeof(hos_eks_mbr_t));
hos_eks_rw_try(mbr, true);
@@ -382,7 +369,7 @@ void hos_eks_bis_clear()
se_aes_crypt_ecb(14, 1, eks, sizeof(hos_eks_mbr_t), eks, sizeof(hos_eks_mbr_t));
// Write EKS blob to SD.
memcpy(mbr + 0x60, eks, sizeof(hos_eks_mbr_t));
memcpy(mbr + 0x80, eks, sizeof(hos_eks_mbr_t));
hos_eks_rw_try(mbr, true);
free(eks);
@@ -576,18 +563,20 @@ int hos_bis_keygen(u8 *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt)
{
hos_keygen(keyblob, kb, tsec_ctxt);
if (kb >= KB_FIRMWARE_VERSION_400)
keygen_rev = fuse_read_odm_keygen_rev();
// New keygen was introduced in 4.0.0.
// We check unconditionally in order to support downgrades.
keygen_rev = fuse_read_odm_keygen_rev();
if (keygen_rev)
{
u8 tmp_mkey[0x10];
u32 mkey_idx = sizeof(mkey_vectors) / 0x10;
u8 mkey_slot = kb >= KB_FIRMWARE_VERSION_700 ? (!h_cfg.aes_slots_new ? 12 : 13) : (kb == KB_FIRMWARE_VERSION_620 ? 9 : 12);
// Keygen revision uses bootloader version, which starts from 1.
keygen_rev -= (KB_FIRMWARE_VERSION_400 + 1);
// Derive mkey 0.
u8 tmp_mkey[0x10];
u32 mkey_idx = sizeof(mkey_vectors) / 0x10;
u8 mkey_slot = kb >= KB_FIRMWARE_VERSION_700 ? (!h_cfg.aes_slots_new ? 12 : 13) : (kb == KB_FIRMWARE_VERSION_620 ? 9 : 12);
do
{
mkey_idx--;
@@ -602,9 +591,9 @@ int hos_bis_keygen(u8 *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt)
// Derive new device key.
se_aes_key_clear(1);
se_aes_unwrap_key(1, 10, new_console_keyseed_4xx[keygen_rev]); // Uses Device key 4x.
se_aes_crypt_ecb(10, 0, tmp_mkey, 0x10, new_console_keyseed_4xx[keygen_rev], 0x10); // Uses Device key 4x.
se_aes_unwrap_key(1, 2, new_console_keyseed[keygen_rev]); // Uses Master Key 0.
se_aes_unwrap_key(1, 10, new_console_keyseed[keygen_rev]); // Uses Device key 4x.
se_aes_crypt_ecb(10, 0, tmp_mkey, 0x10, new_console_keyseed[keygen_rev], 0x10); // Uses Device key 4x.
se_aes_unwrap_key(1, 2, new_console_kekseed[keygen_rev]); // Uses Master Key 0.
se_aes_unwrap_key(1, 1, tmp_mkey);
console_key_slot = 1;
@@ -674,15 +663,18 @@ void hos_bis_keys_clear()
se_aes_key_clear(i);
// Set SBK back.
u32 sbk[4] = {
if (!h_cfg.sbk_set)
{
u32 sbk[4] = {
FUSE(FUSE_PRIVATE_KEY0),
FUSE(FUSE_PRIVATE_KEY1),
FUSE(FUSE_PRIVATE_KEY2),
FUSE(FUSE_PRIVATE_KEY3)
};
// Set SBK to slot 14.
se_aes_key_set(14, sbk, 0x10);
// Set SBK to slot 14.
se_aes_key_set(14, sbk, 0x10);
// Lock SBK from being read.
se_key_acc_ctrl(14, SE_KEY_TBL_DIS_KEYREAD_FLAG);
// Lock SBK from being read.
se_key_acc_ctrl(14, SE_KEY_TBL_DIS_KEYREAD_FLAG);
}
}

View File

@@ -57,17 +57,17 @@ typedef struct _hos_eks_bis_keys_t
typedef struct _hos_eks_mbr_t
{
u32 magic;
u8 enabled[6];
u8 enabled[5];
u8 enabled_bis;
u8 rsvd;
u8 rsvd[2];
u32 sbk_low;
u8 dkg[0x10];
u8 dkk[0x10];
hos_eks_keys_t keys[6];
hos_eks_keys_t keys[5];
hos_eks_bis_keys_t bis_keys[3];
} hos_eks_mbr_t;
static_assert(sizeof(hos_eks_mbr_t) == 336, "HOS EKS size is wrong!");
static_assert(sizeof(hos_eks_mbr_t) == 304, "HOS EKS size is wrong!");
typedef struct _launch_ctxt_t
{

View File

@@ -19,6 +19,7 @@
#include <string.h>
#include "hos.h"
#include "pkg1.h"
#include <gfx_utils.h>
#include <mem/heap.h>
@@ -28,33 +29,31 @@
/*
* package1.1 header: <wb, ldr, sm>
* package1.1 layout:
* 1.0: {sm, ldr, wb} { 2, 1, 0 }
* 2.0: {wb, ldr, sm} { 0, 1, 2 }
* 3.0: {wb, ldr, sm} { 0, 1, 2 }
* 3.1: {wb, ldr, sm} { 0, 1, 2 }
* 4.0: {ldr, sm, wb} { 1, 2, 0 }
* 5.0: {ldr, sm, wb} { 1, 2, 0 }
* 6.0: {ldr, sm, wb} { 1, 2, 0 }
* 6.2: {ldr, sm, wb} { 1, 2, 0 }
* 7.0: {ldr, sm, wb} { 1, 2, 0 }
* 1.0: {sm, ldr, wb} { 2, 1, 0 }
* 2.0+: {wb, ldr, sm} { 0, 1, 2 }
* 4.0+: {ldr, sm, wb} { 1, 2, 0 }
*/
static const u8 sec_map_100[3] = { PK11_SECTION_SM, PK11_SECTION_LD, PK11_SECTION_WB };
static const u8 sec_map_2xx[3] = { PK11_SECTION_WB, PK11_SECTION_LD, PK11_SECTION_SM };
static const u8 sec_map_4xx[3] = { PK11_SECTION_LD, PK11_SECTION_SM, PK11_SECTION_WB };
static const pkg1_id_t _pkg1_ids[] = {
{ "20161121183008", 0, 0x1900, 0x3FE0, { 2, 1, 0 }, 0x40014020, 0x8000D000 }, //1.0.0
{ "20170210155124", 0, 0x1900, 0x3FE0, { 0, 1, 2 }, 0x4002D000, 0x8000D000 }, //2.0.0 - 2.3.0
{ "20170519101410", 1, 0x1A00, 0x3FE0, { 0, 1, 2 }, 0x4002D000, 0x8000D000 }, //3.0.0
{ "20170710161758", 2, 0x1A00, 0x3FE0, { 0, 1, 2 }, 0x4002D000, 0x8000D000 }, //3.0.1 - 3.0.2
{ "20170921172629", 3, 0x1800, 0x3FE0, { 1, 2, 0 }, 0x4002B000, 0x4003B000 }, //4.0.0 - 4.1.0
{ "20180220163747", 4, 0x1900, 0x3FE0, { 1, 2, 0 }, 0x4002B000, 0x4003B000 }, //5.0.0 - 5.1.0
{ "20180802162753", 5, 0x1900, 0x3FE0, { 1, 2, 0 }, 0x4002B000, 0x4003D800 }, //6.0.0 - 6.1.0
{ "20181107105733", 6, 0x0E00, 0x6FE0, { 1, 2, 0 }, 0x4002B000, 0x4003D800 }, //6.2.0
{ "20181218175730", 7, 0x0F00, 0x6FE0, { 1, 2, 0 }, 0x40030000, 0x4003E000 }, //7.0.0
{ "20190208150037", 7, 0x0F00, 0x6FE0, { 1, 2, 0 }, 0x40030000, 0x4003E000 }, //7.0.1
{ "20190314172056", 7, 0x0E00, 0x6FE0, { 1, 2, 0 }, 0x40030000, 0x4003E000 }, //8.0.0 - 8.0.1
{ "20190531152432", 8, 0x0E00, 0x6FE0, { 1, 2, 0 }, 0x40030000, 0x4003E000 }, //8.1.0
{ "20190809135709", 9, 0x0E00, 0x6FE0, { 1, 2, 0 }, 0x40030000, 0x4003E000 }, //9.0.0 - 9.0.1
{ "20191021113848", 10, 0x0E00, 0x6FE0, { 1, 2, 0 }, 0x40030000, 0x4003E000 }, //9.1.0
{ "20200303104606", 10, 0x0E00, 0x6FE0, { 1, 2, 0 }, 0x40030000, 0x4003E000 }, //10.0.0
{ "20161121183008", 0, 0x1900, 0x3FE0, 0x40014020, 0x8000D000 }, // 1.0.0.
{ "20170210155124", 0, 0x1900, 0x3FE0, 0x4002D000, 0x8000D000 }, // 2.0.0 - 2.3.0.
{ "20170519101410", 1, 0x1A00, 0x3FE0, 0x4002D000, 0x8000D000 }, // 3.0.0.
{ "20170710161758", 2, 0x1A00, 0x3FE0, 0x4002D000, 0x8000D000 }, // 3.0.1 - 3.0.2.
{ "20170921172629", 3, 0x1800, 0x3FE0, 0x4002B000, 0x4003B000 }, // 4.0.0 - 4.1.0.
{ "20180220163747", 4, 0x1900, 0x3FE0, 0x4002B000, 0x4003B000 }, // 5.0.0 - 5.1.0.
{ "20180802162753", 5, 0x1900, 0x3FE0, 0x4002B000, 0x4003D800 }, // 6.0.0 - 6.1.0.
{ "20181107105733", 6, 0x0E00, 0x6FE0, 0x4002B000, 0x4003D800 }, // 6.2.0.
{ "20181218175730", 7, 0x0F00, 0x6FE0, 0x40030000, 0x4003E000 }, // 7.0.0.
{ "20190208150037", 7, 0x0F00, 0x6FE0, 0x40030000, 0x4003E000 }, // 7.0.1.
{ "20190314172056", 7, 0x0E00, 0x6FE0, 0x40030000, 0x4003E000 }, // 8.0.0 - 8.0.1.
{ "20190531152432", 8, 0x0E00, 0x6FE0, 0x40030000, 0x4003E000 }, // 8.1.0.
{ "20190809135709", 9, 0x0E00, 0x6FE0, 0x40030000, 0x4003E000 }, // 9.0.0 - 9.0.1.
{ "20191021113848", 10, 0x0E00, 0x6FE0, 0x40030000, 0x4003E000 }, // 9.1.0.
{ "20200303104606", 10, 0x0E00, 0x6FE0, 0x40030000, 0x4003E000 }, // 10.0.0.
{ NULL } //End.
};
@@ -80,22 +79,34 @@ void pkg1_decrypt(const pkg1_id_t *id, u8 *pkg1)
se_aes_crypt_ctr(11, pkg11 + 0x20, pkg11_size, pkg11 + 0x20, pkg11_size, pkg11 + 0x10);
}
void pkg1_unpack(void *warmboot_dst, void *secmon_dst, void *ldr_dst, const pkg1_id_t *id, u8 *pkg1)
const u8 *pkg1_unpack(void *wm_dst, void *sm_dst, void *ldr_dst, const pkg1_id_t *id, u8 *pkg1)
{
pk11_hdr_t *hdr = (pk11_hdr_t *)(pkg1 + id->pkg11_off + 0x20);
const u8 *sec_map;
const pk11_hdr_t *hdr = (pk11_hdr_t *)(pkg1 + id->pkg11_off + 0x20);
u32 sec_size[3] = { hdr->wb_size, hdr->ldr_size, hdr->sm_size };
//u32 sec_off[3] = { hdr->wb_off, hdr->ldr_off, hdr->sm_off };
// Get correct header mapping.
if (id->kb == KB_FIRMWARE_VERSION_100_200 && !strcmp(id->id, "20161121183008"))
sec_map = sec_map_100;
else if (id->kb >= KB_FIRMWARE_VERSION_100_200 && id->kb <= KB_FIRMWARE_VERSION_301)
sec_map = sec_map_2xx;
else
sec_map = sec_map_4xx;
// Copy secmon, warmboot and nx bootloader payloads.
u8 *pdata = (u8 *)hdr + sizeof(pk11_hdr_t);
for (u32 i = 0; i < 3; i++)
{
if (id->sec_map[i] == 0 && warmboot_dst)
memcpy(warmboot_dst, pdata, sec_size[id->sec_map[i]]);
else if (id->sec_map[i] == 1 && ldr_dst)
memcpy(ldr_dst, pdata, sec_size[id->sec_map[i]]);
else if (id->sec_map[i] == 2 && secmon_dst)
memcpy(secmon_dst, pdata, sec_size[id->sec_map[i]]);
pdata += sec_size[id->sec_map[i]];
if (sec_map[i] == PK11_SECTION_WB && wm_dst)
memcpy(wm_dst, pdata, sec_size[sec_map[i]]);
else if (sec_map[i] == PK11_SECTION_LD && ldr_dst)
memcpy(ldr_dst, pdata, sec_size[sec_map[i]]);
else if (sec_map[i] == PK11_SECTION_SM && sm_dst)
memcpy(sm_dst, pdata, sec_size[sec_map[i]]);
pdata += sec_size[sec_map[i]];
}
return sec_map;
}

View File

@@ -19,13 +19,16 @@
#include <utils/types.h>
#define PK11_SECTION_WB 0
#define PK11_SECTION_LD 1
#define PK11_SECTION_SM 2
typedef struct _pkg1_id_t
{
const char *id;
u32 kb;
u32 tsec_off;
u32 pkg11_off;
u32 sec_map[3];
u32 secmon_base;
u32 warmboot_base;
} pkg1_id_t;
@@ -44,6 +47,6 @@ typedef struct _pk11_hdr_t
const pkg1_id_t *pkg1_identify(u8 *pkg1, char *build_date);
void pkg1_decrypt(const pkg1_id_t *id, u8 *pkg1);
void pkg1_unpack(void *warmboot_dst, void *secmon_dst, void *ldr_dst, const pkg1_id_t *id, u8 *pkg1);
const u8 *pkg1_unpack(void *wm_dst, void *sm_dst, void *ldr_dst, const pkg1_id_t *id, u8 *pkg1);
#endif

View File

@@ -226,7 +226,7 @@ int reboot_to_sept(const u8 *tsec_fw, u32 kb)
PMC(APBDEV_PMC_SCRATCH33) = SEPT_PRI_ADDR;
PMC(APBDEV_PMC_SCRATCH40) = 0x6000F208;
reconfig_hw_workaround(false, 0);
hw_reinit_workaround(false, 0);
(*sept)();

View File

@@ -185,12 +185,12 @@ lv_res_t launch_payload(lv_obj_t *list)
if (size < 0x30000)
{
reloc_patcher(PATCHED_RELOC_ENTRY, EXT_PAYLOAD_ADDR, ALIGN(size, 0x10));
reconfig_hw_workaround(false, byte_swap_32(*(u32 *)(buf + size - sizeof(u32))));
hw_reinit_workaround(false, byte_swap_32(*(u32 *)(buf + size - sizeof(u32))));
}
else
{
reloc_patcher(PATCHED_RELOC_ENTRY, EXT_PAYLOAD_ADDR, 0x7000);
reconfig_hw_workaround(true, 0);
hw_reinit_workaround(true, 0);
}
void (*ext_payload_ptr)() = (void *)EXT_PAYLOAD_ADDR;
@@ -241,10 +241,8 @@ void load_saved_configuration()
h_cfg.autonogc = atoi(kv->val);
else if (!strcmp("updater2p", kv->key))
h_cfg.updater2p = atoi(kv->val);
else if (!strcmp("brand", kv->key))
h_cfg.brand = kv->val;
else if (!strcmp("tagline", kv->key))
h_cfg.tagline = kv->val;
else if (!strcmp("bootprotect", kv->key))
h_cfg.bootprotect = atoi(kv->val);
}
break;
@@ -272,6 +270,8 @@ void load_saved_configuration()
n_cfg.verification = atoi(kv->val);
else if (!strcmp("umsemmcrw", kv->key))
n_cfg.ums_emmc_rw = atoi(kv->val) == 1;
else if (!strcmp("jcdisable", kv->key))
n_cfg.jc_disable = atoi(kv->val) == 1;
}
break;
@@ -281,10 +281,10 @@ void load_saved_configuration()
}
#define EXCP_EN_ADDR 0x4003FFFC
#define EXCP_MAGIC 0x30505645 // EVP0
#define EXCP_MAGIC 0x30505645 // EVP0
#define EXCP_TYPE_ADDR 0x4003FFF8
#define EXCP_TYPE_RESET 0x545352 // RST
#define EXCP_TYPE_UNDEF 0x464455 // UDF
#define EXCP_TYPE_RESET 0x545352 // RST
#define EXCP_TYPE_UNDEF 0x464455 // UDF
#define EXCP_TYPE_PABRT 0x54424150 // PABT
#define EXCP_TYPE_DABRT 0x54424144 // DABT
#define EXCP_LR_ADDR 0x4003FFF4
@@ -307,16 +307,16 @@ static void _show_errors()
switch (*excp_type)
{
case EXCP_TYPE_RESET:
WPRINTF("Reset");
WPRINTF("RESET");
break;
case EXCP_TYPE_UNDEF:
WPRINTF("Undefined instruction");
WPRINTF("UNDEF");
break;
case EXCP_TYPE_PABRT:
WPRINTF("Prefetch abort");
WPRINTF("PABRT");
break;
case EXCP_TYPE_DABRT:
WPRINTF("Data abort");
WPRINTF("DABRT");
break;
}
WPRINTF("\n");
@@ -359,9 +359,11 @@ void nyx_init_load_res()
load_saved_configuration();
FIL fp;
f_open(&fp, "bootloader/sys/res.pak", FA_READ);
f_read(&fp, (void *)NYX_RES_ADDR, f_size(&fp), NULL);
f_close(&fp);
if (!f_open(&fp, "bootloader/sys/res.pak", FA_READ))
{
f_read(&fp, (void *)NYX_RES_ADDR, f_size(&fp), NULL);
f_close(&fp);
}
// If no custom switch icon exists, load normal.
if (f_stat("bootloader/res/icon_switch_custom.bmp", NULL))
@@ -400,15 +402,21 @@ void ipl_main()
// Important: Preserve version header!
__asm__ ("" : : "" (ipl_ver));
#if (LV_LOG_PRINTF == 1)
gpio_config(GPIO_PORT_G, GPIO_PIN_0, GPIO_MODE_SPIO);
gpio_config(GPIO_PORT_D, GPIO_PIN_1, GPIO_MODE_GPIO);
pinmux_config_uart(UART_B);
clock_enable_uart(UART_B);
uart_init(UART_B, 115200);
#ifdef DEBUG_UART_PORT
#if DEBUG_UART_PORT == UART_B
gpio_config(GPIO_PORT_G, GPIO_PIN_0, GPIO_MODE_SPIO);
gpio_config(GPIO_PORT_D, GPIO_PIN_1, GPIO_MODE_GPIO);
#endif
#if DEBUG_UART_PORT == UART_C
gpio_config(GPIO_PORT_G, GPIO_PIN_0, GPIO_MODE_GPIO);
gpio_config(GPIO_PORT_D, GPIO_PIN_1, GPIO_MODE_SPIO);
#endif
pinmux_config_uart(DEBUG_UART_PORT);
clock_enable_uart(DEBUG_UART_PORT);
uart_init(DEBUG_UART_PORT, 115200);
uart_send(UART_B, (u8 *)"hekate-NYX: Hello!\r\n", 20);
uart_wait_idle(UART_B, UART_TX_IDLE);
uart_send(DEBUG_UART_PORT, (u8 *)"hekate-NYX: Hello!\r\n", 20);
uart_wait_idle(DEBUG_UART_PORT, UART_TX_IDLE);
#endif
// Initialize the rest of hw and load nyx's resources.

View File

@@ -174,7 +174,7 @@ bool sd_mount()
static void _sd_deinit(bool deinit)
{
if (sd_mode == SD_INIT_FAIL)
if (deinit && sd_mode == SD_INIT_FAIL)
sd_mode = SD_UHS_SDR104;
if (sd_init_done && sd_mounted)