Compare commits

..

47 Commits

Author SHA1 Message Date
CTCaer
c6ec175045 Bump hekate to v5.5.4 and Nyx to v1.0.0 2021-02-06 17:32:07 +02:00
CTCaer
3b9ab66cf1 nyx: Add resized emuMMC creation 2021-02-06 17:19:37 +02:00
CTCaer
b6e458e97b sept: Correct bct buffer pointer and turn on backlight on error 2021-02-06 17:14:07 +02:00
CTCaer
c5152f6a9d nyx: Correct double emuMMC values in part manager 2021-02-06 17:12:09 +02:00
CTCaer
e5689cfe57 fatfs: Add raw emuMMC support for USER partition 2021-02-06 17:11:32 +02:00
CTCaer
f3f1d4d4f0 sdmmc: More functions use the global emmc storage 2021-02-06 17:10:13 +02:00
CTCaer
796b15a861 nyx: Correct text in Launch when missing boot entries 2021-02-06 04:47:23 +02:00
CTCaer
add351289a nyx: Show status for migration and update main window 2021-02-06 04:46:10 +02:00
CTCaer
a4a056128a sdmmc: Add support for SDSC cards 2021-02-06 04:18:30 +02:00
CTCaer
6e314933d9 Various small changes 2021-02-06 04:17:31 +02:00
CTCaer
a31bedda97 ramdisk: Sypport variable size 2021-02-06 04:15:19 +02:00
CTCaer
a25c82a8ce nyx: Allow fix hybrid mbr tool to always run 2021-02-06 04:10:50 +02:00
CTCaer
8ccc47dfa5 nyx: Add resized raw emuMMC support in partition manager 2021-02-06 04:10:02 +02:00
CTCaer
9de5a4ba66 nyx: Swap tab for Partition Manager and Dump Pkg1/2 2021-02-06 04:07:28 +02:00
CTCaer
84e437ae5b nyx: Explicitly state status in Joycon BT dumping 2021-02-06 04:06:09 +02:00
CTCaer
9e34c5995d bis: Pull latest lockpick driver and refactor it
- Refactor various variables and functions
- Flush whole cache when full
- Allow cache to be disabled
- Add support for raw emuMMC in nyx contenxt
- Use partition names for keys (to avoid issues with different ordering)
- Add deinit function that flushes the whole cache
- Change bis lookup address
- Halve cache size to 256MB in order to support 512MB ramdisk also.

Co-Authored-By: shchmue <7903403+shchmue@users.noreply.github.com>
2021-02-06 04:05:31 +02:00
CTCaer
497bbdf3cd fatfs: Add PrFile2Safe creation in format tool 2021-02-06 03:59:20 +02:00
CTCaer
8683a0ff58 gfx: Accept any type in gfx_hexdump 2021-02-06 03:57:39 +02:00
CTCaer
874c801772 Do not force deinit on hekate TUI sd info 2021-02-06 03:55:43 +02:00
CTCaer
eea5463a5c nyx: Refactor nyx extra cfg 2021-02-06 03:55:01 +02:00
CTCaer
af790aeaf8 nyx: Beef up eMMC/SD benchmark
- Added 4KB sequential and random tests that shows IOPS and rate
- The test is now faster as it does 1GB raw reads and 512GB for random reads
- Still does 3 iterations in order to cover both nands that most eMMCs and SDs have.
2021-02-06 03:51:26 +02:00
CTCaer
a8a45b215a nyx: Add emmc info about write cache and enhanced area 2021-02-06 03:44:27 +02:00
CTCaer
38f456a2ee sdmmc: Refactor again
- Refactor various variables and defines
- Removed Card/BGA and OEM ID info as they are static and useless
- Commented out bkops functions completely as not used
- Remove extra buf usage when there's already storage for storing that data
- Optimize various functions to save space
- Clean up useless or duplicate code
2021-02-06 03:41:35 +02:00
CTCaer
a980eac647 hos: disallow no configuration booting as it's useless nowadays 2021-02-06 03:27:18 +02:00
CTCaer
ea83566fc9 sept: Disallow sept if improper BCT to avoid black screen 2021-02-06 03:24:58 +02:00
CTCaer
0857d7ff0e hos: Do not clear SBK in Nyx for HOS 4.0.0 to 6.0.0 2021-02-06 03:21:14 +02:00
CTCaer
48e98ab8c9 eks: Update old version automatically 2021-02-06 03:20:43 +02:00
CTCaer
8cd438146d sdmmc: Use global emmc storage in various places 2021-02-06 03:19:42 +02:00
CTCaer
a80cc0ae2c hos: Add error message for mariko warmboot fw not found
Ability to continue without sleep working also.
2021-02-06 03:05:41 +02:00
CTCaer
2428736bfa hos: Use structs for eks keyblobs and tsec keys 2021-02-06 03:00:48 +02:00
CTCaer
a7bf8bf118 se: Refactor with proper names
Additionally fix some bugs in rsa access control
2021-02-06 02:55:58 +02:00
CTCaer
8038e1faa9 fatfs: Restore win buffer order and explicitly DMA align it 2021-02-05 23:32:07 +02:00
CTCaer
15a7e49dde fatfs: Add simple GPT support
This allows for a simple GPT parsing and checking first partition to see if it's FAT based.

This allows hekate booting GPT with tiny size cost.
2021-02-05 23:27:52 +02:00
CTCaer
8b30bd4b57 loader: Add array alignment compensation 2021-02-05 23:17:46 +02:00
CTCaer
63d03303a2 Rename Reboot normal to OFW in TUI
That otherwise needless change was actually made to change the compiled and compressed size of the payload.

A certain bad chainloader actually corrupts payloads when launched from it. The corruption seems to depend on hekate's actual compressed payload size.
2021-01-14 23:04:21 +02:00
CTCaer
0e40fef049 Modernize hekate_ipl.ini once again.
Additionally explain in **explicit words** that stock option disables CFW kips.
2021-01-14 19:24:56 +02:00
CTCaer
1a50425475 Bump hekate to v5.5.3 and Nyx to v0.9.9 2021-01-14 18:55:11 +02:00
CTCaer
8fc5267110 tmp451: Show correct temperature for T210B01
The thermal measurement substrate transistor was changed in Mariko SoCs.
This ensures that it's properly offset by -12.5 °C.
2021-01-14 17:58:23 +02:00
CTCaer
f6a3b2c9ac sdmmc: Ensure writes gone through after disabling io power 2021-01-14 17:53:22 +02:00
CTCaer
7aa1e77642 nyx: Do not over decrypt pkg1 on t210b01 2021-01-11 23:28:06 +02:00
CTCaer
2370ca0a44 util: Clear alarm wake flags also on power off even if rtc alram is off 2021-01-11 23:24:29 +02:00
CTCaer
abcf7f6f57 nyx: Allow reboot to OFW for patched units
- OFW: This bypasses fuses like always and does not cause a SYS Reset.
- Normal: Resets regulators and causes a SYS Reset.
2021-01-11 22:18:36 +02:00
CTCaer
d1f0ea3de7 Formalize language in various messages 2021-01-11 21:39:44 +02:00
CTCaer
dbc8f4a4c2 nyx: Fix an underflow on Android UDA partition 2021-01-11 21:32:35 +02:00
CTCaer
c6c396ce2a reg5V: Manage battery source based on charger status 2021-01-11 21:30:59 +02:00
CTCaer
74b91b0085 nyx: Cover edge case on backup/restore checks for partition manager
An edge was fixed where the checks for if it's possible to backup files for partition manager would overflow and end up with a value < 1GB and thus proceeding to the backup/restore process.
2021-01-10 02:09:03 +02:00
CTCaer
53c9ca8072 nyx: Fix nyx hanging when updating the partition buttons 2021-01-06 21:29:18 +02:00
75 changed files with 2691 additions and 1809 deletions

View File

@@ -92,7 +92,7 @@ You can find a template [Here](./res/hekate_ipl_template.ini)
| emupath={SD folder} | Forces emuMMC to use the selected one. (=emuMMC/RAW1, =emuMMC/SD00, etc). emuMMC must be created by hekate because it uses the raw_based/file_based files. |
| emummcforce=1 | Forces the use of emuMMC. If emummc.ini is disabled or not found, then it causes an error. |
| emummc_force_disable=1 | Disables emuMMC, if it's enabled. |
| stock=1 | Disables unneeded kernel patching when running stock or semi-stock. `If emuMMC is enabled, emummc_force_disabled=1` is required. emuMMC is not supported on stock. If additional KIPs are needed other than OFW's, you can define them with `kip1` key. No kip should be used that relies on Atmosphère patching, because it will hang. If `NOGC` is needed, use `kip1patch=nogc`. |
| stock=1 | Disables unneeded kernel patching and CFW kips when running stock or semi-stock. `If emuMMC is enabled, emummc_force_disabled=1` is required. emuMMC is not supported on stock. If additional KIPs are needed other than OFW's, you can define them with `kip1` key. No kip should be used that relies on Atmosphère patching, because it will hang. If `NOGC` is needed, use `kip1patch=nogc`. |
| id=idname | Identifies boot entry for forced boot via id. Max 7 chars. |
| payload={SD path} | Payload launching. Tools, Linux, CFW bootloaders, etc. |
| logopath={SD path} | If no logopath, `bootloader/bootlogo.bmp` will be used if exists. If logopath exists, it will load the specified bitmap. |

View File

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

View File

@@ -808,10 +808,10 @@ void jc_power_supply(u8 uart, bool enable)
{
if (enable)
{
if (regulator_get_5v_dev_enabled(1 << uart))
if (regulator_5v_get_dev_enabled(1 << uart))
return;
regulator_enable_5v(1 << uart);
regulator_5v_enable(1 << uart);
if (jc_init_done)
{
@@ -841,10 +841,10 @@ void jc_power_supply(u8 uart, bool enable)
}
else
{
if (!regulator_get_5v_dev_enabled(1 << uart))
if (!regulator_5v_get_dev_enabled(1 << uart))
return;
regulator_disable_5v(1 << uart);
regulator_5v_disable(1 << uart);
if (uart == UART_C)
gpio_write(GPIO_PORT_CC, GPIO_PIN_3, GPIO_LOW);

View File

@@ -27,7 +27,8 @@ typedef enum {
DRIVE_SD = 0,
DRIVE_RAM = 1,
DRIVE_EMMC = 2,
DRIVE_BIS = 3
DRIVE_BIS = 3,
DRIVE_EMU = 4
} DDRIVE;
@@ -59,6 +60,7 @@ DRESULT disk_set_info (BYTE pdrv, BYTE cmd, void *buff);
#define GET_SECTOR_SIZE 2 /* Get sector size (needed at FF_MAX_SS != FF_MIN_SS) */
#define GET_BLOCK_SIZE 3 /* Get erase block size (needed at FF_USE_MKFS == 1) */
#define CTRL_TRIM 4 /* Inform device that the data on the block of sectors is no longer used (needed at FF_USE_TRIM == 1) */
#define SET_SECTOR_OFFSET 5 /* Set media logical offset */
/* Generic command (Not used by FatFs) */
#define CTRL_POWER 5 /* Get/Set power status */

View File

@@ -1,6 +1,6 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2019 CTCaer
* Copyright (c) 2018-2021 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
@@ -38,6 +38,7 @@
#include "ff.h" /* Declarations of FatFs API */
#include "diskio.h" /* Declarations of device I/O functions */
#include <storage/mbr_gpt.h>
#include <gfx_utils.h>
#define EFSPRINTF(text, ...) print_error(); gfx_printf("%k"text"%k\n", 0xFFFFFF00, 0xFFFFFFFF);
@@ -3284,6 +3285,7 @@ static FRESULT find_volume ( /* FR_OK(0): successful, !=0: an error occurred */
/* Following code attempts to mount the volume. (analyze BPB and initialize the filesystem object) */
fs->fs_type = 0; /* Clear the filesystem object */
fs->part_type = 0; /* Clear the Partition object */
fs->pdrv = LD2PD(vol); /* Bind the logical drive and a physical drive */
stat = disk_initialize(fs->pdrv); /* Initialize the physical drive */
if (stat & STA_NOINIT) { /* Check if the initialization succeeded */
@@ -3318,6 +3320,18 @@ static FRESULT find_volume ( /* FR_OK(0): successful, !=0: an error occurred */
EFSPRINTF("BRNL");
return FR_DISK_ERR; /* An error occured in the disk I/O layer */
}
#if FF_SIMPLE_GPT
if (fmt >= 2) {
/* If GPT Check the first partition */
gpt_t gpt;
if (disk_read(fs->pdrv, (BYTE *)&gpt, 1, sizeof(gpt_t) / SS(fs))) return FR_DISK_ERR;
if (!mem_cmp(&gpt.header.signature, "EFI PART", 8)) {
fs->part_type = 1;
bsect = gpt.entries[0].lba_start;
fmt = bsect ? check_fs(fs, bsect) : 3; /* Check the partition */
}
}
#endif
if (fmt >= 2) {
EFSPRINTF("NOFAT");
return FR_NO_FILESYSTEM; /* No FAT volume is found */
@@ -6169,7 +6183,9 @@ FRESULT f_mkfs (
#endif
/* Create FAT VBR */
mem_set(buf, 0, ss);
mem_cpy(buf + BS_JmpBoot, "\xEB\xFE\x90" "MSDOS5.0", 11);/* Boot jump code (x86), OEM name */
/* Boot jump code (x86), OEM name */
if (!(opt & FM_PRF2)) mem_cpy(buf + BS_JmpBoot, "\xEB\xFE\x90" "NYX1.0.0", 11);
else mem_cpy(buf + BS_JmpBoot, "\xEB\xE9\x90\x00\x00\x00\x00\x00\x00\x00\x00", 11);
st_word(buf + BPB_BytsPerSec, ss); /* Sector size [byte] */
buf[BPB_SecPerClus] = (BYTE)pau; /* Cluster size [sector] */
st_word(buf + BPB_RsvdSecCnt, (WORD)sz_rsv); /* Size of reserved area */
@@ -6182,23 +6198,27 @@ FRESULT f_mkfs (
}
buf[BPB_Media] = 0xF8; /* Media descriptor byte */
st_word(buf + BPB_SecPerTrk, 63); /* Number of sectors per track (for int13) */
st_word(buf + BPB_NumHeads, 255); /* Number of heads (for int13) */
st_word(buf + BPB_NumHeads, (opt & FM_PRF2) ? 16 : 255); /* Number of heads (for int13) */
st_dword(buf + BPB_HiddSec, b_vol); /* Volume offset in the physical drive [sector] */
if (fmt == FS_FAT32) {
st_dword(buf + BS_VolID32, GET_FATTIME()); /* VSN */
st_dword(buf + BS_VolID32, (opt & FM_PRF2) ? 0 : GET_FATTIME()); /* VSN */
st_dword(buf + BPB_FATSz32, sz_fat); /* FAT size [sector] */
st_dword(buf + BPB_RootClus32, 2); /* Root directory cluster # (2) */
st_word(buf + BPB_FSInfo32, 1); /* Offset of FSINFO sector (VBR + 1) */
st_word(buf + BPB_BkBootSec32, 6); /* Offset of backup VBR (VBR + 6) */
buf[BS_DrvNum32] = 0x80; /* Drive number (for int13) */
buf[BS_BootSig32] = 0x29; /* Extended boot signature */
mem_cpy(buf + BS_VolLab32, "SWITCH SD " "FAT32 ", 19); /* Volume label, FAT signature */
/* Volume label, FAT signature */
if (!(opt & FM_PRF2)) mem_cpy(buf + BS_VolLab32, FF_MKFS_LABEL "FAT32 ", 19);
else mem_cpy(buf + BS_VolLab32, "NO NAME " "FAT32 ", 19);
} else {
st_dword(buf + BS_VolID, GET_FATTIME()); /* VSN */
st_word(buf + BPB_FATSz16, (WORD)sz_fat); /* FAT size [sector] */
buf[BS_DrvNum] = 0x80; /* Drive number (for int13) */
buf[BS_BootSig] = 0x29; /* Extended boot signature */
mem_cpy(buf + BS_VolLab, "SWITCH SD " "FAT ", 19); /* Volume label, FAT signature */
/* Volume label, FAT signature */
if (!(opt & FM_PRF2)) mem_cpy(buf + BS_VolLab, FF_MKFS_LABEL "FAT ", 19);
else mem_cpy(buf + BS_VolLab, "NO NAME " "FAT ", 19);
}
st_word(buf + BS_55AA, 0xAA55); /* Signature (offset is fixed here regardless of sector size) */
if (disk_write(pdrv, buf, b_vol, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); /* Write it to the VBR sector */
@@ -6216,6 +6236,16 @@ FRESULT f_mkfs (
disk_write(pdrv, buf, b_vol + 1, 1); /* Write original FSINFO (VBR + 1) */
}
/* Create PRF2SAFE info */
if (fmt == FS_FAT32 && opt & FM_PRF2) {
mem_set(buf, 0, ss);
buf[16] = 0x64; /* Record type */
st_dword(buf + 32, 0x03); /* Unknown. SYSTEM: 0x3F00. USER: 0x03. Volatile. */
st_dword(buf + 36, 25); /* Entries. SYSTEM: 22. USER: 25.Static? */
st_dword(buf + 508, 0x517BBFE0); /* Custom CRC32. SYSTEM: 0x6B673904. USER: 0x517BBFE0. */
disk_write(pdrv, buf, b_vol + 3, 1); /* Write PRF2SAFE info (VBR + 3) */
}
/* Initialize FAT area */
mem_set(buf, 0, (UINT)szb_buf);
sect = b_fat; /* FAT start sector */

View File

@@ -95,8 +95,8 @@ typedef DWORD FSIZE_t;
/* Filesystem object structure (FATFS) */
typedef struct {
BYTE win[FF_MAX_SS]; /* Disk access window for Directory, FAT (and file data at tiny cfg) */
BYTE fs_type; /* Filesystem type (0:not mounted) */
BYTE part_type; /* Partition type (0:MBR, 1:GPT) */
BYTE pdrv; /* Associated physical drive */
BYTE n_fats; /* Number of FATs (1 or 2) */
BYTE wflag; /* win[] flag (b0:dirty) */
@@ -138,6 +138,7 @@ typedef struct {
DWORD bitbase; /* Allocation bitmap base sector */
#endif
DWORD winsect; /* Current sector appearing in the win[] */
BYTE win[FF_MAX_SS] __attribute__((aligned(8))); /* Disk access window for Directory, FAT (and file data at tiny cfg). DMA aligned. */
} FATFS;
@@ -168,9 +169,6 @@ typedef struct {
/* File object structure (FIL) */
typedef struct {
#if !FF_FS_TINY
BYTE buf[FF_MAX_SS]; /* File private data read/write window */
#endif
FFOBJID obj; /* Object identifier (must be the 1st member to detect invalid object pointer) */
BYTE flag; /* File status flags */
BYTE err; /* Abort flag (error code) */
@@ -184,6 +182,9 @@ typedef struct {
#if FF_USE_FASTSEEK
DWORD* cltbl; /* Pointer to the cluster link map table (nulled on open, set by application) */
#endif
#if !FF_FS_TINY
BYTE buf[FF_MAX_SS] __attribute__((aligned(8))); /* File private data read/write window. DMA aligned. */
#endif
} FIL;
@@ -365,6 +366,7 @@ int ff_del_syncobj (FF_SYNC_t sobj); /* Delete a sync object */
#define FM_EXFAT 0x04
#define FM_ANY 0x07
#define FM_SFD 0x08
#define FM_PRF2 0x10
/* Filesystem type (FATFS.fs_type) */
#define FS_FAT12 1

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2019 CTCaer
* Copyright (c) 2019-2021 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
@@ -50,6 +50,13 @@
// Virtual disk / Chainloader buffers.
#define RAM_DISK_ADDR 0xA4000000
#define RAM_DISK_SZ 0x41000000 // 1040MB.
#define RAM_DISK2_SZ 0x21000000 // 528MB.
// NX BIS driver sector cache.
#define NX_BIS_CACHE_ADDR 0xC5000000
#define NX_BIS_CACHE_SZ 0x10020000 // 256MB.
#define NX_BIS_LOOKUP_ADDR 0xD6000000
#define NX_BIS_LOOKUP_SZ 0xF000000 // 240MB.
// L4T Kernel Panic Storage (PSTORE).
#define PSTORE_ADDR 0xB0000000
@@ -93,10 +100,6 @@
/* --- Hole: 129MB 0xF6A00000 - 0xFEB3FFFF --- */
#define DRAM_START2 0xFEB40000
// NX BIS driver sector cache.
#define NX_BIS_CACHE_ADDR 0xFEE00000
#define NX_BIS_CACHE_SZ 0x100000
// USB buffers.
#define USBD_ADDR 0xFEF00000
#define USB_DESCRIPTOR_ADDR 0xFEF40000

View File

@@ -21,8 +21,9 @@
#include <utils/types.h>
static u8 reg_5v_dev = 0;
static bool batt_src = false;
void regulator_enable_5v(u8 dev)
void regulator_5v_enable(u8 dev)
{
// The power supply selection from battery or USB is automatic.
if (!reg_5v_dev)
@@ -32,6 +33,7 @@ void regulator_enable_5v(u8 dev)
gpio_config(GPIO_PORT_A, GPIO_PIN_5, GPIO_MODE_GPIO);
gpio_output_enable(GPIO_PORT_A, GPIO_PIN_5, GPIO_OUTPUT_ENABLE);
gpio_write(GPIO_PORT_A, GPIO_PIN_5, GPIO_HIGH);
batt_src = true;
// Fan and Rail power from USB 5V VDD.
PINMUX_AUX(PINMUX_AUX_USB_VBUS_EN0) = PINMUX_LPDR | 1;
@@ -47,7 +49,7 @@ void regulator_enable_5v(u8 dev)
reg_5v_dev |= dev;
}
void regulator_disable_5v(u8 dev)
void regulator_5v_disable(u8 dev)
{
reg_5v_dev &= ~dev;
@@ -58,6 +60,7 @@ void regulator_disable_5v(u8 dev)
gpio_output_enable(GPIO_PORT_A, GPIO_PIN_5, GPIO_OUTPUT_DISABLE);
gpio_config(GPIO_PORT_A, GPIO_PIN_5, GPIO_MODE_SPIO);
PINMUX_AUX(PINMUX_AUX_SATA_LED_ACTIVE) = PINMUX_PARKED | PINMUX_INPUT_ENABLE;
batt_src = false;
// Rail power from USB 5V VDD.
gpio_write(GPIO_PORT_CC, GPIO_PIN_4, GPIO_LOW);
@@ -70,7 +73,15 @@ void regulator_disable_5v(u8 dev)
}
}
bool regulator_get_5v_dev_enabled(u8 dev)
bool regulator_5v_get_dev_enabled(u8 dev)
{
return (reg_5v_dev & dev);
}
void regulator_5v_batt_src_enable(bool enable)
{
if (enable && !batt_src)
gpio_write(GPIO_PORT_A, GPIO_PIN_5, GPIO_HIGH);
else if (!enable && batt_src)
gpio_write(GPIO_PORT_A, GPIO_PIN_5, GPIO_LOW);
}

View File

@@ -27,8 +27,9 @@ enum
REGULATOR_5V_ALL = 0xFF
};
void regulator_enable_5v(u8 dev);
void regulator_disable_5v(u8 dev);
bool regulator_get_5v_dev_enabled(u8 dev);
void regulator_5v_enable(u8 dev);
void regulator_5v_disable(u8 dev);
bool regulator_5v_get_dev_enabled(u8 dev);
void regulator_5v_batt_src_enable(bool enable);
#endif

View File

@@ -1,6 +1,6 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2020 CTCaer
* Copyright (c) 2018-2021 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
@@ -57,17 +57,17 @@ static void _se_ll_init(se_ll_t *ll, u32 addr, u32 size)
static void _se_ll_set(se_ll_t *dst, se_ll_t *src)
{
SE(SE_IN_LL_ADDR_REG_OFFSET) = (u32)src;
SE(SE_OUT_LL_ADDR_REG_OFFSET) = (u32)dst;
SE(SE_IN_LL_ADDR_REG) = (u32)src;
SE(SE_OUT_LL_ADDR_REG) = (u32)dst;
}
static int _se_wait()
{
while (!(SE(SE_INT_STATUS_REG_OFFSET) & SE_INT_OP_DONE(INT_SET)))
while (!(SE(SE_INT_STATUS_REG) & SE_INT_OP_DONE))
;
if (SE(SE_INT_STATUS_REG_OFFSET) & SE_INT_ERROR(INT_SET) ||
SE(SE_STATUS_0) & SE_STATUS_0_STATE_WAIT_IN ||
SE(SE_ERR_STATUS_0) != SE_ERR_STATUS_0_SE_NS_ACCESS_CLEAR)
if (SE(SE_INT_STATUS_REG) & SE_INT_ERR_STAT ||
(SE(SE_STATUS_REG) & SE_STATUS_STATE_MASK) != SE_STATUS_STATE_IDLE ||
SE(SE_ERR_STATUS_REG) != 0)
return 0;
return 1;
}
@@ -92,12 +92,12 @@ static int _se_execute(u32 op, void *dst, u32 dst_size, const void *src, u32 src
_se_ll_set(ll_dst, ll_src);
SE(SE_ERR_STATUS_0) = SE(SE_ERR_STATUS_0);
SE(SE_INT_STATUS_REG_OFFSET) = SE(SE_INT_STATUS_REG_OFFSET);
SE(SE_ERR_STATUS_REG) = SE(SE_ERR_STATUS_REG);
SE(SE_INT_STATUS_REG) = SE(SE_INT_STATUS_REG);
bpmp_mmu_maintenance(BPMP_MMU_MAINT_CLN_INV_WAY, false);
SE(SE_OPERATION_REG_OFFSET) = SE_OPERATION(op);
SE(SE_OPERATION_REG) = op;
if (is_oneshot)
{
@@ -146,13 +146,13 @@ static int _se_execute_one_block(u32 op, void *dst, u32 dst_size, const void *sr
if (!src || !dst)
return 0;
u8 *block = (u8 *)malloc(0x10);
memset(block, 0, 0x10);
u8 *block = (u8 *)malloc(SE_AES_BLOCK_SIZE);
memset(block, 0, SE_AES_BLOCK_SIZE);
SE(SE_BLOCK_COUNT_REG_OFFSET) = 0;
SE(SE_CRYPTO_BLOCK_COUNT_REG) = 1 - 1;
memcpy(block, src, src_size);
int res = _se_execute_oneshot(op, block, 0x10, block, 0x10);
int res = _se_execute_oneshot(op, block, SE_AES_BLOCK_SIZE, block, SE_AES_BLOCK_SIZE);
memcpy(dst, block, dst_size);
free(block);
@@ -161,68 +161,68 @@ static int _se_execute_one_block(u32 op, void *dst, u32 dst_size, const void *sr
static void _se_aes_ctr_set(void *ctr)
{
u32 data[TEGRA_SE_AES_BLOCK_SIZE / 4];
memcpy(data, ctr, TEGRA_SE_AES_BLOCK_SIZE);
u32 data[SE_AES_IV_SIZE / 4];
memcpy(data, ctr, SE_AES_IV_SIZE);
for (u32 i = 0; i < (TEGRA_SE_AES_BLOCK_SIZE / 4); i++)
SE(SE_CRYPTO_CTR_REG_OFFSET + (4 * i)) = data[i];
for (u32 i = 0; i < SE_CRYPTO_LINEAR_CTR_REG_COUNT; i++)
SE(SE_CRYPTO_LINEAR_CTR_REG + (4 * i)) = data[i];
}
void se_rsa_acc_ctrl(u32 rs, u32 flags)
{
if (flags & SE_RSA_KEY_TBL_DIS_KEY_ALL_FLAG)
SE(SE_RSA_KEYTABLE_ACCESS_REG_OFFSET + 4 * rs) =
((flags >> SE_RSA_KEY_TBL_DIS_KEYUSE_FLAG_SHIFT) & SE_RSA_KEY_TBL_DIS_KEYUSE_FLAG) |
((flags & SE_RSA_KEY_TBL_DIS_KEY_READ_UPDATE_FLAG) ^ SE_RSA_KEY_TBL_DIS_KEY_ALL_COMMON_FLAG);
if (flags & SE_RSA_KEY_TBL_DIS_KEY_LOCK_FLAG)
SE(SE_RSA_KEYTABLE_ACCESS_LOCK_OFFSET) &= ~BIT(rs);
if (flags & SE_RSA_KEY_TBL_DIS_KEY_ACCESS_FLAG)
SE(SE_RSA_KEYTABLE_ACCESS_REG + 4 * rs) =
(((flags >> 4) & SE_RSA_KEY_TBL_DIS_KEYUSE_FLAG) |(flags & SE_RSA_KEY_TBL_DIS_KEY_READ_UPDATE_FLAG)) ^
SE_RSA_KEY_TBL_DIS_KEY_READ_UPDATE_USE_FLAG;
if (flags & SE_RSA_KEY_LOCK_FLAG)
SE(SE_RSA_SECURITY_PERKEY_REG) &= ~BIT(rs);
}
void se_key_acc_ctrl(u32 ks, u32 flags)
{
if (flags & SE_KEY_TBL_DIS_KEY_ACCESS_FLAG)
SE(SE_KEY_TABLE_ACCESS_REG_OFFSET + 4 * ks) = ~flags;
if (flags & SE_KEY_TBL_DIS_KEY_LOCK_FLAG)
SE(SE_KEY_TABLE_ACCESS_LOCK_OFFSET) &= ~BIT(ks);
SE(SE_CRYPTO_KEYTABLE_ACCESS_REG + 4 * ks) = ~flags;
if (flags & SE_KEY_LOCK_FLAG)
SE(SE_CRYPTO_SECURITY_PERKEY_REG) &= ~BIT(ks);
}
u32 se_key_acc_ctrl_get(u32 ks)
{
return SE(SE_KEY_TABLE_ACCESS_REG_OFFSET + 4 * ks);
return SE(SE_CRYPTO_KEYTABLE_ACCESS_REG + 4 * ks);
}
void se_aes_key_set(u32 ks, void *key, u32 size)
{
u32 data[TEGRA_SE_AES_MAX_KEY_SIZE / 4];
u32 data[SE_AES_MAX_KEY_SIZE / 4];
memcpy(data, key, size);
for (u32 i = 0; i < (size / 4); i++)
{
SE(SE_KEYTABLE_REG_OFFSET) = SE_KEYTABLE_SLOT(ks) | i;
SE(SE_KEYTABLE_DATA0_REG_OFFSET) = data[i];
SE(SE_CRYPTO_KEYTABLE_ADDR_REG) = SE_KEYTABLE_SLOT(ks) | SE_KEYTABLE_PKT(i); // QUAD is automatically set by PKT.
SE(SE_CRYPTO_KEYTABLE_DATA_REG) = data[i];
}
}
void se_aes_iv_set(u32 ks, void *iv)
{
u32 data[TEGRA_SE_AES_BLOCK_SIZE / 4];
memcpy(data, iv, TEGRA_SE_AES_BLOCK_SIZE);
u32 data[SE_AES_IV_SIZE / 4];
memcpy(data, iv, SE_AES_IV_SIZE);
for (u32 i = 0; i < (TEGRA_SE_AES_BLOCK_SIZE / 4); i++)
for (u32 i = 0; i < (SE_AES_IV_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];
SE(SE_CRYPTO_KEYTABLE_ADDR_REG) = SE_KEYTABLE_SLOT(ks) | SE_KEYTABLE_QUAD(ORIGINAL_IV) | SE_KEYTABLE_PKT(i);
SE(SE_CRYPTO_KEYTABLE_DATA_REG) = data[i];
}
}
void se_aes_key_get(u32 ks, void *key, u32 size)
{
u32 data[TEGRA_SE_AES_MAX_KEY_SIZE / 4];
u32 data[SE_AES_MAX_KEY_SIZE / 4];
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);
SE(SE_CRYPTO_KEYTABLE_ADDR_REG) = SE_KEYTABLE_SLOT(ks) | SE_KEYTABLE_PKT(i); // QUAD is automatically set by PKT.
data[i] = SE(SE_CRYPTO_KEYTABLE_DATA_REG);
}
memcpy(key, data, size);
@@ -230,78 +230,78 @@ void se_aes_key_get(u32 ks, void *key, u32 size)
void se_aes_key_clear(u32 ks)
{
for (u32 i = 0; i < (TEGRA_SE_AES_MAX_KEY_SIZE / 4); i++)
for (u32 i = 0; i < (SE_AES_MAX_KEY_SIZE / 4); i++)
{
SE(SE_KEYTABLE_REG_OFFSET) = SE_KEYTABLE_SLOT(ks) | i;
SE(SE_KEYTABLE_DATA0_REG_OFFSET) = 0;
SE(SE_CRYPTO_KEYTABLE_ADDR_REG) = SE_KEYTABLE_SLOT(ks) | SE_KEYTABLE_PKT(i); // QUAD is automatically set by PKT.
SE(SE_CRYPTO_KEYTABLE_DATA_REG) = 0;
}
}
void se_aes_iv_clear(u32 ks)
{
for (u32 i = 0; i < (TEGRA_SE_AES_BLOCK_SIZE / 4); i++)
for (u32 i = 0; i < (SE_AES_IV_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;
SE(SE_CRYPTO_KEYTABLE_ADDR_REG) = SE_KEYTABLE_SLOT(ks) | SE_KEYTABLE_QUAD(ORIGINAL_IV) | SE_KEYTABLE_PKT(i);
SE(SE_CRYPTO_KEYTABLE_DATA_REG) = 0;
}
}
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);
SE(SE_CRYPTO_REG_OFFSET) = SE_CRYPTO_KEY_INDEX(ks_src) | SE_CRYPTO_CORE_SEL(CORE_DECRYPT);
SE(SE_BLOCK_COUNT_REG_OFFSET) = 0;
SE(SE_CRYPTO_KEYTABLE_DST_REG_OFFSET) = SE_CRYPTO_KEYTABLE_DST_KEY_INDEX(ks_dst);
SE(SE_CONFIG_REG) = SE_CONFIG_DEC_ALG(ALG_AES_DEC) | SE_CONFIG_DST(DST_KEYTABLE);
SE(SE_CRYPTO_CONFIG_REG) = SE_CRYPTO_KEY_INDEX(ks_src) | SE_CRYPTO_CORE_SEL(CORE_DECRYPT);
SE(SE_CRYPTO_BLOCK_COUNT_REG) = 1 - 1;
SE(SE_CRYPTO_KEYTABLE_DST_REG) = SE_KEYTABLE_DST_KEY_INDEX(ks_dst) | SE_KEYTABLE_DST_WORD_QUAD(KEYS_0_3);
return _se_execute_oneshot(OP_START, NULL, 0, input, 0x10);
return _se_execute_oneshot(SE_OP_START, NULL, 0, input, SE_KEY_128_SIZE);
}
int se_aes_crypt_ecb(u32 ks, u32 enc, void *dst, u32 dst_size, const void *src, u32 src_size)
{
if (enc)
{
SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_ENC_ALG(ALG_AES_ENC) | SE_CONFIG_DST(DST_MEMORY);
SE(SE_CRYPTO_REG_OFFSET) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_CORE_SEL(CORE_ENCRYPT);
SE(SE_CONFIG_REG) = SE_CONFIG_ENC_ALG(ALG_AES_ENC) | SE_CONFIG_DST(DST_MEMORY);
SE(SE_CRYPTO_CONFIG_REG) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_CORE_SEL(CORE_ENCRYPT);
}
else
{
SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_DEC_ALG(ALG_AES_DEC) | SE_CONFIG_DST(DST_MEMORY);
SE(SE_CRYPTO_REG_OFFSET) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_CORE_SEL(CORE_DECRYPT);
SE(SE_CONFIG_REG) = SE_CONFIG_DEC_ALG(ALG_AES_DEC) | SE_CONFIG_DST(DST_MEMORY);
SE(SE_CRYPTO_CONFIG_REG) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_CORE_SEL(CORE_DECRYPT);
}
SE(SE_BLOCK_COUNT_REG_OFFSET) = (src_size >> 4) - 1;
return _se_execute_oneshot(OP_START, dst, dst_size, src, src_size);
SE(SE_CRYPTO_BLOCK_COUNT_REG) = (src_size >> 4) - 1;
return _se_execute_oneshot(SE_OP_START, dst, dst_size, src, src_size);
}
int se_aes_crypt_cbc(u32 ks, u32 enc, void *dst, u32 dst_size, const void *src, u32 src_size)
{
if (enc)
{
SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_ENC_ALG(ALG_AES_ENC) | SE_CONFIG_DST(DST_MEMORY);
SE(SE_CRYPTO_REG_OFFSET) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_VCTRAM_SEL(VCTRAM_AESOUT) |
SE(SE_CONFIG_REG) = SE_CONFIG_ENC_ALG(ALG_AES_ENC) | SE_CONFIG_DST(DST_MEMORY);
SE(SE_CRYPTO_CONFIG_REG) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_VCTRAM_SEL(VCTRAM_AESOUT) |
SE_CRYPTO_CORE_SEL(CORE_ENCRYPT) | SE_CRYPTO_XOR_POS(XOR_TOP);
}
else
{
SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_DEC_ALG(ALG_AES_DEC) | SE_CONFIG_DST(DST_MEMORY);
SE(SE_CRYPTO_REG_OFFSET) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_VCTRAM_SEL(VCTRAM_PREVAHB) |
SE(SE_CONFIG_REG) = SE_CONFIG_DEC_ALG(ALG_AES_DEC) | SE_CONFIG_DST(DST_MEMORY);
SE(SE_CRYPTO_CONFIG_REG) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_VCTRAM_SEL(VCTRAM_PREVMEM) |
SE_CRYPTO_CORE_SEL(CORE_DECRYPT) | SE_CRYPTO_XOR_POS(XOR_BOTTOM);
}
SE(SE_BLOCK_COUNT_REG_OFFSET) = (src_size >> 4) - 1;
return _se_execute_oneshot(OP_START, dst, dst_size, src, src_size);
SE(SE_CRYPTO_BLOCK_COUNT_REG) = (src_size >> 4) - 1;
return _se_execute_oneshot(SE_OP_START, dst, dst_size, src, src_size);
}
int se_aes_crypt_block_ecb(u32 ks, u32 enc, void *dst, const void *src)
{
return se_aes_crypt_ecb(ks, enc, dst, 0x10, src, 0x10);
return se_aes_crypt_ecb(ks, enc, dst, SE_AES_BLOCK_SIZE, src, SE_AES_BLOCK_SIZE);
}
int se_aes_crypt_ctr(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_size, void *ctr)
{
SE(SE_SPARE_0_REG_OFFSET) = 1;
SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_ENC_ALG(ALG_AES_ENC) | SE_CONFIG_DST(DST_MEMORY);
SE(SE_CRYPTO_REG_OFFSET) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_CORE_SEL(CORE_ENCRYPT) |
SE_CRYPTO_XOR_POS(XOR_BOTTOM) | SE_CRYPTO_INPUT_SEL(INPUT_LNR_CTR) | SE_CRYPTO_CTR_VAL(1);
SE(SE_SPARE_REG) = SE_ECO(SE_ERRATA_FIX_ENABLE);
SE(SE_CONFIG_REG) = SE_CONFIG_ENC_ALG(ALG_AES_ENC) | SE_CONFIG_DST(DST_MEMORY);
SE(SE_CRYPTO_CONFIG_REG) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_CORE_SEL(CORE_ENCRYPT) |
SE_CRYPTO_XOR_POS(XOR_BOTTOM) | SE_CRYPTO_INPUT_SEL(INPUT_LNR_CTR) | SE_CRYPTO_CTR_CNTN(1);
_se_aes_ctr_set(ctr);
u32 src_size_aligned = src_size & 0xFFFFFFF0;
@@ -309,13 +309,13 @@ int se_aes_crypt_ctr(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_s
if (src_size_aligned)
{
SE(SE_BLOCK_COUNT_REG_OFFSET) = (src_size >> 4) - 1;
if (!_se_execute_oneshot(OP_START, dst, dst_size, src, src_size_aligned))
SE(SE_CRYPTO_BLOCK_COUNT_REG) = (src_size >> 4) - 1;
if (!_se_execute_oneshot(SE_OP_START, dst, dst_size, src, src_size_aligned))
return 0;
}
if (src_size - src_size_aligned && src_size_aligned < dst_size)
return _se_execute_one_block(OP_START, dst + src_size_aligned,
return _se_execute_one_block(SE_OP_START, dst + src_size_aligned,
MIN(src_size_delta, dst_size - src_size_aligned),
src + src_size_aligned, src_size_delta);
@@ -325,11 +325,11 @@ int se_aes_crypt_ctr(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_s
int se_aes_xts_crypt_sec(u32 ks1, u32 ks2, u32 enc, u64 sec, void *dst, void *src, u32 secsize)
{
int res = 0;
u8 *tweak = (u8 *)malloc(0x10);
u8 *tweak = (u8 *)malloc(SE_AES_BLOCK_SIZE);
u8 *pdst = (u8 *)dst;
u8 *psrc = (u8 *)src;
//Generate tweak.
// Generate tweak.
for (int i = 0xF; i >= 0; i--)
{
tweak[i] = sec & 0xFF;
@@ -338,18 +338,18 @@ int se_aes_xts_crypt_sec(u32 ks1, u32 ks2, u32 enc, u64 sec, void *dst, void *sr
if (!se_aes_crypt_block_ecb(ks1, 1, tweak, tweak))
goto out;
//We are assuming a 0x10-aligned sector size in this implementation.
for (u32 i = 0; i < secsize / 0x10; i++)
// We are assuming a 0x10-aligned sector size in this implementation.
for (u32 i = 0; i < secsize / SE_AES_BLOCK_SIZE; i++)
{
for (u32 j = 0; j < 0x10; j++)
for (u32 j = 0; j < SE_AES_BLOCK_SIZE; j++)
pdst[j] = psrc[j] ^ tweak[j];
if (!se_aes_crypt_block_ecb(ks2, enc, pdst, pdst))
goto out;
for (u32 j = 0; j < 0x10; j++)
for (u32 j = 0; j < SE_AES_BLOCK_SIZE; j++)
pdst[j] = pdst[j] ^ tweak[j];
_gf256_mul_x(tweak);
psrc += 0x10;
pdst += 0x10;
psrc += SE_AES_BLOCK_SIZE;
pdst += SE_AES_BLOCK_SIZE;
}
res = 1;
@@ -374,62 +374,62 @@ int se_aes_xts_crypt(u32 ks1, u32 ks2, u32 enc, u64 sec, void *dst, void *src, u
int se_calc_sha256(void *hash, u32 *msg_left, const void *src, u32 src_size, u64 total_size, u32 sha_cfg, bool is_oneshot)
{
int res;
u32 hash32[TEGRA_SE_SHA_256_SIZE / 4];
u32 hash32[SE_SHA_256_SIZE / 4];
//! TODO: src_size must be 512 bit aligned if continuing and not last block for SHA256.
if (src_size > 0xFFFFFF || !hash) // Max 16MB - 1 chunks and aligned x4 hash buffer.
return 0;
// Setup config for SHA256.
SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_ENC_MODE(MODE_SHA256) | SE_CONFIG_ENC_ALG(ALG_SHA) | SE_CONFIG_DST(DST_HASHREG);
SE(SE_SHA_CONFIG_REG_OFFSET) = sha_cfg;
SE(SE_BLOCK_COUNT_REG_OFFSET) = 0;
SE(SE_CONFIG_REG) = SE_CONFIG_ENC_MODE(MODE_SHA256) | SE_CONFIG_ENC_ALG(ALG_SHA) | SE_CONFIG_DST(DST_HASHREG);
SE(SE_SHA_CONFIG_REG) = sha_cfg;
SE(SE_CRYPTO_BLOCK_COUNT_REG) = 1 - 1;
// Set total size to current buffer size if empty.
if (!total_size)
total_size = src_size;
// Set total size: BITS(src_size), up to 2 EB.
SE(SE_SHA_MSG_LENGTH_0_REG_OFFSET) = (u32)(total_size << 3);
SE(SE_SHA_MSG_LENGTH_1_REG_OFFSET) = (u32)(total_size >> 29);
SE(SE_SHA_MSG_LENGTH_2_REG_OFFSET) = 0;
SE(SE_SHA_MSG_LENGTH_3_REG_OFFSET) = 0;
SE(SE_SHA_MSG_LENGTH_0_REG) = (u32)(total_size << 3);
SE(SE_SHA_MSG_LENGTH_1_REG) = (u32)(total_size >> 29);
SE(SE_SHA_MSG_LENGTH_2_REG) = 0;
SE(SE_SHA_MSG_LENGTH_3_REG) = 0;
// Set size left to hash.
SE(SE_SHA_MSG_LEFT_0_REG_OFFSET) = (u32)(total_size << 3);
SE(SE_SHA_MSG_LEFT_1_REG_OFFSET) = (u32)(total_size >> 29);
SE(SE_SHA_MSG_LEFT_2_REG_OFFSET) = 0;
SE(SE_SHA_MSG_LEFT_3_REG_OFFSET) = 0;
SE(SE_SHA_MSG_LEFT_0_REG) = (u32)(total_size << 3);
SE(SE_SHA_MSG_LEFT_1_REG) = (u32)(total_size >> 29);
SE(SE_SHA_MSG_LEFT_2_REG) = 0;
SE(SE_SHA_MSG_LEFT_3_REG) = 0;
// If we hash in chunks, copy over the intermediate.
if (sha_cfg == SHA_CONTINUE && msg_left)
{
// Restore message left to process.
SE(SE_SHA_MSG_LEFT_0_REG_OFFSET) = msg_left[0];
SE(SE_SHA_MSG_LEFT_1_REG_OFFSET) = msg_left[1];
SE(SE_SHA_MSG_LEFT_0_REG) = msg_left[0];
SE(SE_SHA_MSG_LEFT_1_REG) = msg_left[1];
// Restore hash reg.
memcpy(hash32, hash, TEGRA_SE_SHA_256_SIZE);
for (u32 i = 0; i < (TEGRA_SE_SHA_256_SIZE / 4); i++)
SE(SE_HASH_RESULT_REG_OFFSET + (i << 2)) = byte_swap_32(hash32[i]);
memcpy(hash32, hash, SE_SHA_256_SIZE);
for (u32 i = 0; i < (SE_SHA_256_SIZE / 4); i++)
SE(SE_HASH_RESULT_REG + (i * 4)) = byte_swap_32(hash32[i]);
}
// Trigger the operation.
res = _se_execute(OP_START, NULL, 0, src, src_size, is_oneshot);
res = _se_execute(SE_OP_START, NULL, 0, src, src_size, is_oneshot);
if (is_oneshot)
{
// Backup message left.
if (msg_left)
{
msg_left[0] = SE(SE_SHA_MSG_LEFT_0_REG_OFFSET);
msg_left[1] = SE(SE_SHA_MSG_LEFT_1_REG_OFFSET);
msg_left[0] = SE(SE_SHA_MSG_LEFT_0_REG);
msg_left[1] = SE(SE_SHA_MSG_LEFT_1_REG);
}
// Copy output hash.
for (u32 i = 0; i < (TEGRA_SE_SHA_256_SIZE / 4); i++)
hash32[i] = byte_swap_32(SE(SE_HASH_RESULT_REG_OFFSET + (i << 2)));
memcpy(hash, hash32, TEGRA_SE_SHA_256_SIZE);
for (u32 i = 0; i < (SE_SHA_256_SIZE / 4); i++)
hash32[i] = byte_swap_32(SE(SE_HASH_RESULT_REG + (i * 4)));
memcpy(hash, hash32, SE_SHA_256_SIZE);
}
return res;
@@ -442,20 +442,20 @@ int se_calc_sha256_oneshot(void *hash, const void *src, u32 src_size)
int se_calc_sha256_finalize(void *hash, u32 *msg_left)
{
u32 hash32[TEGRA_SE_SHA_256_SIZE / 4];
u32 hash32[SE_SHA_256_SIZE / 4];
int res = _se_execute_finalize();
// Backup message left.
if (msg_left)
{
msg_left[0] = SE(SE_SHA_MSG_LEFT_0_REG_OFFSET);
msg_left[1] = SE(SE_SHA_MSG_LEFT_1_REG_OFFSET);
msg_left[0] = SE(SE_SHA_MSG_LEFT_0_REG);
msg_left[1] = SE(SE_SHA_MSG_LEFT_1_REG);
}
// Copy output hash.
for (u32 i = 0; i < (TEGRA_SE_SHA_256_SIZE / 4); i++)
hash32[i] = byte_swap_32(SE(SE_HASH_RESULT_REG_OFFSET + (i << 2)));
memcpy(hash, hash32, TEGRA_SE_SHA_256_SIZE);
for (u32 i = 0; i < (SE_SHA_256_SIZE / 4); i++)
hash32[i] = byte_swap_32(SE(SE_HASH_RESULT_REG + (i * 4)));
memcpy(hash, hash32, SE_SHA_256_SIZE);
return res;
}
@@ -463,18 +463,17 @@ int se_calc_sha256_finalize(void *hash, u32 *msg_left)
int se_gen_prng128(void *dst)
{
// Setup config for X931 PRNG.
SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_ENC_MODE(MODE_KEY128) | SE_CONFIG_ENC_ALG(ALG_RNG) | SE_CONFIG_DST(DST_MEMORY);
SE(SE_CRYPTO_REG_OFFSET) = SE_CRYPTO_HASH(HASH_DISABLE) | SE_CRYPTO_XOR_POS(XOR_BYPASS) | SE_CRYPTO_INPUT_SEL(INPUT_RANDOM);
SE(SE_CONFIG_REG) = SE_CONFIG_ENC_MODE(MODE_KEY128) | SE_CONFIG_ENC_ALG(ALG_RNG) | SE_CONFIG_DST(DST_MEMORY);
SE(SE_CRYPTO_CONFIG_REG) = SE_CRYPTO_HASH(HASH_DISABLE) | SE_CRYPTO_XOR_POS(XOR_BYPASS) | SE_CRYPTO_INPUT_SEL(INPUT_RANDOM);
SE(SE_RNG_CONFIG_REG) = SE_RNG_CONFIG_SRC(SRC_ENTROPY) | SE_RNG_CONFIG_MODE(MODE_NORMAL);
//SE(SE_RNG_SRC_CONFIG_REG) =
// SE_RNG_SRC_CONFIG_ENTR_SRC(RO_ENTR_ENABLE) | SE_RNG_SRC_CONFIG_ENTR_SRC_LOCK(RO_ENTR_LOCK_ENABLE);
SE(SE_RNG_RESEED_INTERVAL_REG) = 1;
SE(SE_RNG_CONFIG_REG_OFFSET) = SE_RNG_CONFIG_SRC(RNG_SRC_ENTROPY) | SE_RNG_CONFIG_MODE(RNG_MODE_NORMAL);
//SE(SE_RNG_SRC_CONFIG_REG_OFFSET) =
// SE_RNG_SRC_CONFIG_ENT_SRC(RNG_SRC_RO_ENT_ENABLE) | SE_RNG_SRC_CONFIG_ENT_SRC_LOCK(RNG_SRC_RO_ENT_LOCK_ENABLE);
SE(SE_RNG_RESEED_INTERVAL_REG_OFFSET) = 1;
SE(SE_BLOCK_COUNT_REG_OFFSET) = (16 >> 4) - 1;
SE(SE_CRYPTO_BLOCK_COUNT_REG) = (16 >> 4) - 1;
// Trigger the operation.
return _se_execute_oneshot(OP_START, dst, 16, NULL, 0);
return _se_execute_oneshot(SE_OP_START, dst, 16, NULL, 0);
}
void se_get_aes_keys(u8 *buf, u8 *keys, u32 keysize)
@@ -482,43 +481,43 @@ void se_get_aes_keys(u8 *buf, u8 *keys, u32 keysize)
u8 *aligned_buf = (u8 *)ALIGN((u32)buf, 0x40);
// Set Secure Random Key.
SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_ENC_MODE(MODE_KEY128) | SE_CONFIG_ENC_ALG(ALG_RNG) | SE_CONFIG_DST(DST_SRK);
SE(SE_CRYPTO_REG_OFFSET) = SE_CRYPTO_KEY_INDEX(0) | SE_CRYPTO_CORE_SEL(CORE_ENCRYPT) | SE_CRYPTO_INPUT_SEL(INPUT_RANDOM);
SE(SE_RNG_CONFIG_REG_OFFSET) = SE_RNG_CONFIG_SRC(RNG_SRC_ENTROPY) | SE_RNG_CONFIG_MODE(RNG_MODE_FORCE_RESEED);
SE(SE_CONFIG_REG) = SE_CONFIG_ENC_MODE(MODE_KEY128) | SE_CONFIG_ENC_ALG(ALG_RNG) | SE_CONFIG_DST(DST_SRK);
SE(SE_CRYPTO_CONFIG_REG) = SE_CRYPTO_KEY_INDEX(0) | SE_CRYPTO_CORE_SEL(CORE_ENCRYPT) | SE_CRYPTO_INPUT_SEL(INPUT_RANDOM);
SE(SE_RNG_CONFIG_REG) = SE_RNG_CONFIG_SRC(SRC_ENTROPY) | SE_RNG_CONFIG_MODE(MODE_FORCE_RESEED);
SE(SE_CRYPTO_LAST_BLOCK) = 0;
_se_execute_oneshot(OP_START, NULL, 0, NULL, 0);
_se_execute_oneshot(SE_OP_START, NULL, 0, NULL, 0);
// Save AES keys.
SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_ENC_MODE(MODE_KEY128) | SE_CONFIG_ENC_ALG(ALG_AES_ENC) | SE_CONFIG_DST(DST_MEMORY);
SE(SE_CONFIG_REG) = SE_CONFIG_ENC_MODE(MODE_KEY128) | SE_CONFIG_ENC_ALG(ALG_AES_ENC) | SE_CONFIG_DST(DST_MEMORY);
for (u32 i = 0; i < TEGRA_SE_KEYSLOT_COUNT; i++)
for (u32 i = 0; i < SE_AES_KEYSLOT_COUNT; i++)
{
SE(SE_CONTEXT_SAVE_CONFIG_REG_OFFSET) = SE_CONTEXT_SAVE_SRC(AES_KEYTABLE) |
(i << SE_KEY_INDEX_SHIFT) | SE_CONTEXT_SAVE_WORD_QUAD(KEYS_0_3);
SE(SE_CONTEXT_SAVE_CONFIG_REG) = SE_CONTEXT_SRC(AES_KEYTABLE) | SE_KEYTABLE_DST_KEY_INDEX(i) |
SE_CONTEXT_AES_KEY_INDEX(0) | SE_CONTEXT_AES_WORD_QUAD(KEYS_0_3);
SE(SE_CRYPTO_LAST_BLOCK) = 0;
_se_execute_oneshot(OP_CTX_SAVE, aligned_buf, 0x10, NULL, 0);
memcpy(keys + i * keysize, aligned_buf, 0x10);
_se_execute_oneshot(SE_OP_CTX_SAVE, aligned_buf, SE_AES_BLOCK_SIZE, NULL, 0);
memcpy(keys + i * keysize, aligned_buf, SE_AES_BLOCK_SIZE);
if (keysize > 0x10)
if (keysize > SE_KEY_128_SIZE)
{
SE(SE_CONTEXT_SAVE_CONFIG_REG_OFFSET) = SE_CONTEXT_SAVE_SRC(AES_KEYTABLE) |
(i << SE_KEY_INDEX_SHIFT) | SE_CONTEXT_SAVE_WORD_QUAD(KEYS_4_7);
SE(SE_CONTEXT_SAVE_CONFIG_REG) = SE_CONTEXT_SRC(AES_KEYTABLE) | SE_KEYTABLE_DST_KEY_INDEX(i) |
SE_CONTEXT_AES_KEY_INDEX(0) | SE_CONTEXT_AES_WORD_QUAD(KEYS_4_7);
SE(SE_CRYPTO_LAST_BLOCK) = 0;
_se_execute_oneshot(OP_CTX_SAVE, aligned_buf, 0x10, NULL, 0);
memcpy(keys + i * keysize + 0x10, aligned_buf, 0x10);
_se_execute_oneshot(SE_OP_CTX_SAVE, aligned_buf, SE_AES_BLOCK_SIZE, NULL, 0);
memcpy(keys + i * keysize + SE_AES_BLOCK_SIZE, aligned_buf, SE_AES_BLOCK_SIZE);
}
}
// Save SRK to PMC secure scratches.
SE(SE_CONTEXT_SAVE_CONFIG_REG_OFFSET) = SE_CONTEXT_SAVE_SRC(SRK);
SE(SE_CRYPTO_LAST_BLOCK) = 0;
_se_execute_oneshot(OP_CTX_SAVE, NULL, 0, NULL, 0);
SE(SE_CONTEXT_SAVE_CONFIG_REG) = SE_CONTEXT_SRC(SRK);
SE(SE_CRYPTO_LAST_BLOCK) = 0;
_se_execute_oneshot(SE_OP_CTX_SAVE, NULL, 0, NULL, 0);
// End context save.
SE(SE_CONFIG_REG_OFFSET) = 0;
_se_execute_oneshot(OP_CTX_SAVE, NULL, 0, NULL, 0);
SE(SE_CONFIG_REG) = 0;
_se_execute_oneshot(SE_OP_CTX_SAVE, NULL, 0, NULL, 0);
// Get SRK.
u32 srk[4];
@@ -529,7 +528,7 @@ void se_get_aes_keys(u8 *buf, u8 *keys, u32 keysize)
// Decrypt context.
se_aes_key_clear(3);
se_aes_key_set(3, srk, 0x10);
se_aes_crypt_cbc(3, 0, keys, TEGRA_SE_KEYSLOT_COUNT * keysize, keys, TEGRA_SE_KEYSLOT_COUNT * keysize);
se_aes_key_set(3, srk, SE_KEY_128_SIZE);
se_aes_crypt_cbc(3, 0, keys, SE_AES_KEYSLOT_COUNT * keysize, keys, SE_AES_KEYSLOT_COUNT * keysize);
se_aes_key_clear(3);
}

View File

@@ -1,18 +1,19 @@
/*
* Copyright (c) 2018 naehrwert
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
* Copyright (c) 2018 naehrwert
* Copyright (c) 2019-2021 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _SE_H_
#define _SE_H_
@@ -28,14 +29,14 @@ 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);
int se_calc_sha256(void *hash, u32 *msg_left, const void *src, u32 src_size, u64 total_size, u32 sha_cfg, bool is_oneshot);
int se_calc_sha256_oneshot(void *hash, const void *src, u32 src_size);
int se_calc_sha256_finalize(void *hash, u32 *msg_left);
int se_gen_prng128(void *dst);
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);
int se_calc_sha256(void *hash, u32 *msg_left, const void *src, u32 src_size, u64 total_size, u32 sha_cfg, bool is_oneshot);
int se_calc_sha256_oneshot(void *hash, const void *src, u32 src_size);
int se_calc_sha256_finalize(void *hash, u32 *msg_left);
int se_gen_prng128(void *dst);
#endif

View File

@@ -1,400 +1,323 @@
/*
* Driver for Tegra Security Engine
*
* Copyright (c) 2011-2013, NVIDIA Corporation. All Rights Reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that 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, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2021 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _CRYPTO_TEGRA_SE_H
#define _CRYPTO_TEGRA_SE_H
#ifndef _SE_T210_H
#define _SE_T210_H
#include <utils/types.h>
#define TEGRA_SE_CRA_PRIORITY 300
#define TEGRA_SE_COMPOSITE_PRIORITY 400
#define TEGRA_SE_CRYPTO_QUEUE_LENGTH 50
#define SE_MAX_SRC_SG_COUNT 50
#define SE_MAX_DST_SG_COUNT 50
#define SE_CRYPTO_QUEUE_LENGTH 50
#define SE_MAX_SRC_SG_COUNT 50
#define SE_MAX_DST_SG_COUNT 50
#define TEGRA_SE_KEYSLOT_COUNT 16
#define SE_MAX_LAST_BLOCK_SIZE 0xFFFFF
#define SE_AES_KEYSLOT_COUNT 16
#define SE_RSA_KEYSLOT_COUNT 2
#define SE_MAX_LAST_BLOCK_SIZE 0xFFFFF
#define SE_AES_BLOCK_SIZE 16
#define SE_AES_IV_SIZE 16
#define SE_AES_MIN_KEY_SIZE 16
#define SE_AES_MAX_KEY_SIZE 32
#define SE_KEY_128_SIZE 16
#define SE_KEY_192_SIZE 24
#define SE_KEY_256_SIZE 32
#define SE_SHA_192_SIZE 24
#define SE_SHA_256_SIZE 32
#define SE_SHA_384_SIZE 48
#define SE_SHA_512_SIZE 64
#define SE_RNG_IV_SIZE 16
#define SE_RNG_DT_SIZE 16
#define SE_RNG_KEY_SIZE 16
#define SE_RNG_SEED_SIZE (SE_RNG_IV_SIZE + SE_RNG_KEY_SIZE + SE_RNG_DT_SIZE)
#define SE_AES_CMAC_DIGEST_SIZE 16
#define SE_RSA512_DIGEST_SIZE 64
#define SE_RSA1024_DIGEST_SIZE 128
#define SE_RSA1536_DIGEST_SIZE 192
#define SE_RSA2048_DIGEST_SIZE 256
/* SE register definitions */
#define SE_SECURITY_0 0x000
#define SE_KEY_SCHED_READ_SHIFT 3
#define SE_SE_SECURITY_REG 0x000
#define SE_HARD_SETTING BIT(0)
#define SE_ENG_DIS BIT(1)
#define SE_PERKEY_SETTING BIT(2)
#define SE_SOFT_SETTING BIT(16)
#define SE_TZRAM_SECURITY_0 0x004
#define SE_TZRAM_SECURITY_REG 0x004
#define SE_TZRAM_HARD_SETTING BIT(0)
#define SE_TZRAM_ENG_DIS BIT(1)
#define SE_CONFIG_REG_OFFSET 0x014
#define SE_CONFIG_ENC_ALG_SHIFT 12
#define SE_CONFIG_DEC_ALG_SHIFT 8
#define ALG_AES_ENC 1
#define ALG_RNG 2
#define ALG_SHA 3
#define ALG_RSA 4
#define ALG_NOP 0
#define ALG_AES_DEC 1
#define SE_CONFIG_ENC_ALG(x) ((x) << SE_CONFIG_ENC_ALG_SHIFT)
#define SE_CONFIG_DEC_ALG(x) ((x) << SE_CONFIG_DEC_ALG_SHIFT)
#define SE_CONFIG_DST_SHIFT 2
#define DST_MEMORY 0
#define DST_HASHREG 1
#define DST_KEYTAB 2
#define DST_SRK 3
#define DST_RSAREG 4
#define SE_CONFIG_DST(x) ((x) << SE_CONFIG_DST_SHIFT)
#define SE_CONFIG_ENC_MODE_SHIFT 24
#define SE_CONFIG_DEC_MODE_SHIFT 16
#define MODE_KEY128 0
#define MODE_KEY192 1
#define MODE_KEY256 2
#define MODE_SHA1 0
#define MODE_SHA224 4
#define MODE_SHA256 5
#define MODE_SHA384 6
#define MODE_SHA512 7
#define SE_CONFIG_ENC_MODE(x) ((x) << SE_CONFIG_ENC_MODE_SHIFT)
#define SE_CONFIG_DEC_MODE(x) ((x) << SE_CONFIG_DEC_MODE_SHIFT)
#define SE_OPERATION_REG 0x008
#define SE_OP_ABORT 0
#define SE_OP_START 1
#define SE_OP_RESTART_OUT 2
#define SE_OP_CTX_SAVE 3
#define SE_OP_RESTART_IN 4
#define SE_RNG_CONFIG_REG_OFFSET 0x340
#define RNG_MODE_SHIFT 0
#define RNG_MODE_NORMAL 0
#define RNG_MODE_FORCE_INSTANTION 1
#define RNG_MODE_FORCE_RESEED 2
#define SE_RNG_CONFIG_MODE(x) ((x) << RNG_MODE_SHIFT)
#define RNG_SRC_SHIFT 2
#define RNG_SRC_NONE 0
#define RNG_SRC_ENTROPY 1
#define RNG_SRC_LFSR 2
#define SE_RNG_CONFIG_SRC(x) ((x) << RNG_SRC_SHIFT)
#define SE_INT_ENABLE_REG 0x00C
#define SE_INT_STATUS_REG 0x010
#define SE_INT_IN_LL_BUF_RD BIT(0)
#define SE_INT_IN_DONE BIT(1)
#define SE_INT_OUT_LL_BUF_WR BIT(2)
#define SE_INT_OUT_DONE BIT(3)
#define SE_INT_OP_DONE BIT(4)
#define SE_INT_RESEED_NEEDED BIT(5)
#define SE_INT_ERR_STAT BIT(16)
#define SE_RNG_SRC_CONFIG_REG_OFFSET 0x344
#define RNG_SRC_RO_ENT_SHIFT 1
#define RNG_SRC_RO_ENT_ENABLE 1
#define RNG_SRC_RO_ENT_DISABLE 0
#define SE_RNG_SRC_CONFIG_ENT_SRC(x) ((x) << RNG_SRC_RO_ENT_SHIFT)
#define RNG_SRC_RO_ENT_LOCK_SHIFT 0
#define RNG_SRC_RO_ENT_LOCK_ENABLE 1
#define RNG_SRC_RO_ENT_LOCK_DISABLE 0
#define SE_RNG_SRC_CONFIG_ENT_SRC_LOCK(x) ((x) << RNG_SRC_RO_ENT_LOCK_SHIFT)
#define SE_CONFIG_REG 0x014
#define DST_MEMORY 0
#define DST_HASHREG 1
#define DST_KEYTABLE 2
#define DST_SRK 3
#define DST_RSAREG 4
#define SE_CONFIG_DST(x) ((x) << 2)
#define ALG_NOP 0
#define ALG_AES_DEC 1
#define SE_CONFIG_DEC_ALG(x) ((x) << 8)
#define ALG_NOP 0
#define ALG_AES_ENC 1
#define ALG_RNG 2
#define ALG_SHA 3
#define ALG_RSA 4
#define SE_CONFIG_ENC_ALG(x) ((x) << 12)
#define MODE_KEY128 0
#define MODE_KEY192 1
#define MODE_KEY256 2
#define MODE_SHA1 0
#define MODE_SHA224 4
#define MODE_SHA256 5
#define MODE_SHA384 6
#define MODE_SHA512 7
#define SE_CONFIG_DEC_MODE(x) ((x) << 16)
#define SE_CONFIG_ENC_MODE(x) ((x) << 24)
#define SE_RNG_RESEED_INTERVAL_REG_OFFSET 0x348
#define SE_IN_LL_ADDR_REG 0x018
#define SE_IN_CUR_BYTE_ADDR_REG 0x01C
#define SE_IN_CUR_LL_ID_REG 0x020
#define SE_OUT_LL_ADDR_REG 0x024
#define SE_OUT_CUR_BYTE_ADDR_REG 0x028
#define SE_OUT_CUR_LL_ID_REG 0x02C
#define SE_KEYTABLE_REG_OFFSET 0x31c
#define SE_KEYTABLE_SLOT_SHIFT 4
#define SE_KEYTABLE_SLOT(x) ((x) << SE_KEYTABLE_SLOT_SHIFT)
#define SE_KEYTABLE_QUAD_SHIFT 2
#define QUAD_KEYS_128 0
#define QUAD_KEYS_192 1
#define QUAD_KEYS_256 1
#define QUAD_ORG_IV 2
#define QUAD_UPDTD_IV 3
#define SE_KEYTABLE_QUAD(x) ((x) << SE_KEYTABLE_QUAD_SHIFT)
#define SE_KEYTABLE_OP_TYPE_SHIFT 9
#define OP_READ 0
#define OP_WRITE 1
#define SE_KEYTABLE_OP_TYPE(x) ((x) << SE_KEYTABLE_OP_TYPE_SHIFT)
#define SE_KEYTABLE_TABLE_SEL_SHIFT 8
#define TABLE_KEYIV 0
#define TABLE_SCHEDULE 1
#define SE_KEYTABLE_TABLE_SEL(x) ((x) << SE_KEYTABLE_TABLE_SEL_SHIFT)
#define SE_KEYTABLE_PKT_SHIFT 0
#define SE_KEYTABLE_PKT(x) ((x) << SE_KEYTABLE_PKT_SHIFT)
#define SE_HASH_RESULT_REG 0x030
#define SE_HASH_RESULT_REG_COUNT 16
#define SE_OP_DONE_SHIFT 4
#define OP_DONE 1
#define SE_OP_DONE(x, y) ((x) && ((y) << SE_OP_DONE_SHIFT))
#define SE_CONTEXT_SAVE_CONFIG_REG 0x070
#define KEYS_0_3 0
#define KEYS_4_7 1
#define ORIGINAL_IV 2
#define UPDATED_IV 3
#define SE_CONTEXT_AES_WORD_QUAD(x) ((x) << 0)
#define SE_CONTEXT_AES_KEY_INDEX(x) ((x) << 8)
#define KEYS_0_3 0
#define KEYS_4_7 1
#define KEYS_8_11 2
#define KEYS_12_15 3
#define SE_CONTEXT_RSA_WORD_QUAD(x) ((x) << 12)
#define SLOT0_EXPONENT 0
#define SLOT0_MODULUS 1
#define SLOT1_EXPONENT 2
#define SLOT1_MODULUS 3
#define SE_CONTEXT_RSA_KEY_INDEX(x) ((x) << 16)
#define STICKY_0_3 0
#define STICKY_4_7 1
#define SE_CONTEXT_STICKY_WORD_QUAD(x) ((x) << 24)
#define STICKY_BITS 0
#define RSA_KEYTABLE 1
#define AES_KEYTABLE 2
#define MEM 4
#define SRK 6
#define SE_CONTEXT_SRC(x) ((x) << 29)
#define SE_CRYPTO_LAST_BLOCK 0x080
#define SE_CTX_SAVE_AUTO_T210B01_REG 0x074
#define SE_CTX_SAVE_AUTO_ENABLE BIT(0)
#define SE_CTX_SAVE_AUTO_LOCK BIT(8)
#define SE_CTX_SAVE_AUTO_CURR_CNT_MASK (0x3FF << 16)
#define SE_CRYPTO_REG_OFFSET 0x304
#define SE_CRYPTO_HASH_SHIFT 0
#define HASH_DISABLE 0
#define HASH_ENABLE 1
#define SE_CRYPTO_HASH(x) ((x) << SE_CRYPTO_HASH_SHIFT)
#define SE_CRYPTO_XOR_POS_SHIFT 1
#define XOR_BYPASS 0
#define XOR_TOP 2
#define XOR_BOTTOM 3
#define SE_CRYPTO_XOR_POS(x) ((x) << SE_CRYPTO_XOR_POS_SHIFT)
#define SE_CRYPTO_INPUT_SEL_SHIFT 3
#define INPUT_AHB 0
#define INPUT_RANDOM 1
#define INPUT_AESOUT 2
#define INPUT_LNR_CTR 3
#define SE_CRYPTO_INPUT_SEL(x) ((x) << SE_CRYPTO_INPUT_SEL_SHIFT)
#define SE_CRYPTO_VCTRAM_SEL_SHIFT 5
#define VCTRAM_AHB 0
#define VCTRAM_AESOUT 2
#define VCTRAM_PREVAHB 3
#define SE_CRYPTO_VCTRAM_SEL(x) ((x) << SE_CRYPTO_VCTRAM_SEL_SHIFT)
#define SE_CRYPTO_IV_SEL_SHIFT 7
#define IV_ORIGINAL 0
#define IV_UPDATED 1
#define SE_CRYPTO_IV_SEL(x) ((x) << SE_CRYPTO_IV_SEL_SHIFT)
#define SE_CRYPTO_CORE_SEL_SHIFT 8
#define CORE_DECRYPT 0
#define CORE_ENCRYPT 1
#define SE_CRYPTO_CORE_SEL(x) ((x) << SE_CRYPTO_CORE_SEL_SHIFT)
#define SE_CRYPTO_CTR_VAL_SHIFT 11
#define SE_CRYPTO_CTR_VAL(x) ((x) << SE_CRYPTO_CTR_VAL_SHIFT)
#define SE_CRYPTO_KEY_INDEX_SHIFT 24
#define SE_CRYPTO_KEY_INDEX(x) ((x) << SE_CRYPTO_KEY_INDEX_SHIFT)
#define SE_CRYPTO_CTR_CNTN_SHIFT 11
#define SE_CRYPTO_CTR_CNTN(x) ((x) << SE_CRYPTO_CTR_CNTN_SHIFT)
#define SE_CRYPTO_LAST_BLOCK 0x080
#define SE_CRYPTO_CTR_REG_COUNT 4
#define SE_CRYPTO_CTR_REG_OFFSET 0x308
#define SE_OPERATION_REG_OFFSET 0x008
#define SE_OPERATION_SHIFT 0
#define OP_ABORT 0
#define OP_START 1
#define OP_RESTART 2
#define OP_CTX_SAVE 3
#define OP_RESTART_IN 4
#define SE_OPERATION(x) ((x) << SE_OPERATION_SHIFT)
#define SE_CONTEXT_SAVE_CONFIG_REG_OFFSET 0x070
#define SE_CONTEXT_SAVE_WORD_QUAD_SHIFT 0
#define KEYS_0_3 0
#define KEYS_4_7 1
#define ORIG_IV 2
#define UPD_IV 3
#define SE_CONTEXT_SAVE_WORD_QUAD(x) ((x) << SE_CONTEXT_SAVE_WORD_QUAD_SHIFT)
#define SE_CONTEXT_SAVE_KEY_INDEX_SHIFT 8
#define SE_CONTEXT_SAVE_KEY_INDEX(x) ((x) << SE_CONTEXT_SAVE_KEY_INDEX_SHIFT)
#define SE_CONTEXT_SAVE_STICKY_WORD_QUAD_SHIFT 24
#define STICKY_0_3 0
#define STICKY_4_7 1
#define SE_CONTEXT_SAVE_STICKY_WORD_QUAD(x) \
((x) << SE_CONTEXT_SAVE_STICKY_WORD_QUAD_SHIFT)
#define SE_CONTEXT_SAVE_SRC_SHIFT 29
#define STICKY_BITS 0
#define KEYTABLE 2
#define MEM 4
#define SRK 6
#define RSA_KEYTABLE 1
#define AES_KEYTABLE 2
#define SE_CONTEXT_SAVE_SRC(x) ((x) << SE_CONTEXT_SAVE_SRC_SHIFT)
#define SE_CONTEXT_SAVE_RSA_KEY_INDEX_SHIFT 16
#define SE_CONTEXT_SAVE_RSA_KEY_INDEX(x) \
((x) << SE_CONTEXT_SAVE_RSA_KEY_INDEX_SHIFT)
#define SE_CONTEXT_RSA_WORD_QUAD_SHIFT 12
#define SE_CONTEXT_RSA_WORD_QUAD(x) \
((x) << SE_CONTEXT_RSA_WORD_QUAD_SHIFT)
#define SE_CTX_SAVE_AUTO 0x074
#define CTX_SAVE_AUTO_ENABLE BIT(0)
#define CTX_SAVE_AUTO_LOCK BIT(8)
#define CTX_SAVE_AUTO_CURR_CNT_MASK (0x3FF << 16)
#define SE_INT_ENABLE_REG_OFFSET 0x00c
#define SE_INT_STATUS_REG_OFFSET 0x010
#define INT_DISABLE 0
#define INT_ENABLE 1
#define INT_UNSET 0
#define INT_SET 1
#define SE_INT_OP_DONE_SHIFT 4
#define SE_INT_OP_DONE(x) ((x) << SE_INT_OP_DONE_SHIFT)
#define SE_INT_ERROR_SHIFT 16
#define SE_INT_ERROR(x) ((x) << SE_INT_ERROR_SHIFT)
#define SE_STATUS_0 0x800
#define SE_STATUS_0_STATE_WAIT_IN 3
#define SE_ERR_STATUS_0 0x804
#define SE_ERR_STATUS_0_SE_NS_ACCESS_CLEAR 0
#define SE_CRYPTO_KEYTABLE_DST_REG_OFFSET 0X330
#define SE_CRYPTO_KEYTABLE_DST_WORD_QUAD_SHIFT 0
#define SE_CRYPTO_KEYTABLE_DST_WORD_QUAD(x) \
((x) << SE_CRYPTO_KEYTABLE_DST_WORD_QUAD_SHIFT)
#define SE_KEY_INDEX_SHIFT 8
#define SE_CRYPTO_KEYTABLE_DST_KEY_INDEX(x) ((x) << SE_KEY_INDEX_SHIFT)
#define SE_IN_LL_ADDR_REG_OFFSET 0x018
#define SE_OUT_LL_ADDR_REG_OFFSET 0x024
#define SE_KEYTABLE_DATA0_REG_OFFSET 0x320
#define SE_KEYTABLE_REG_MAX_DATA 16
#define SE_BLOCK_COUNT_REG_OFFSET 0x318
#define SE_SPARE_0_REG_OFFSET 0x80c
#define SE_SHA_CONFIG_REG_OFFSET 0x200
#define SE_SHA_CONFIG_REG 0x200
#define SHA_CONTINUE 0
#define SHA_INIT_HASH 1
#define SE_SHA_MSG_LENGTH_0_REG_OFFSET 0x204
#define SE_SHA_MSG_LENGTH_1_REG_OFFSET 0x208
#define SE_SHA_MSG_LENGTH_2_REG_OFFSET 0x20C
#define SE_SHA_MSG_LENGTH_3_REG_OFFSET 0x210
#define SE_SHA_MSG_LEFT_0_REG_OFFSET 0x214
#define SE_SHA_MSG_LEFT_1_REG_OFFSET 0x218
#define SE_SHA_MSG_LEFT_2_REG_OFFSET 0x21C
#define SE_SHA_MSG_LEFT_3_REG_OFFSET 0x220
#define SE_SHA_MSG_LENGTH_0_REG 0x204
#define SE_SHA_MSG_LENGTH_1_REG 0x208
#define SE_SHA_MSG_LENGTH_2_REG 0x20C
#define SE_SHA_MSG_LENGTH_3_REG 0x210
#define SE_SHA_MSG_LEFT_0_REG 0x214
#define SE_SHA_MSG_LEFT_1_REG 0x218
#define SE_SHA_MSG_LEFT_2_REG 0x21C
#define SE_SHA_MSG_LEFT_3_REG 0x220
#define SE_HASH_RESULT_REG_COUNT 16
#define SE_HASH_RESULT_REG_OFFSET 0x030
#define TEGRA_SE_KEY_256_SIZE 32
#define TEGRA_SE_KEY_192_SIZE 24
#define TEGRA_SE_KEY_128_SIZE 16
#define TEGRA_SE_AES_BLOCK_SIZE 16
#define TEGRA_SE_AES_MIN_KEY_SIZE 16
#define TEGRA_SE_AES_MAX_KEY_SIZE 32
#define TEGRA_SE_AES_IV_SIZE 16
#define TEGRA_SE_SHA_512_SIZE 64
#define TEGRA_SE_SHA_384_SIZE 48
#define TEGRA_SE_SHA_256_SIZE 32
#define TEGRA_SE_SHA_192_SIZE 24
#define TEGRA_SE_RNG_IV_SIZE 16
#define TEGRA_SE_RNG_DT_SIZE 16
#define TEGRA_SE_RNG_KEY_SIZE 16
#define TEGRA_SE_RNG_SEED_SIZE (TEGRA_SE_RNG_IV_SIZE + \
TEGRA_SE_RNG_KEY_SIZE + \
TEGRA_SE_RNG_DT_SIZE)
#define SE_CRYPTO_SECURITY_PERKEY_REG 0x280
#define SE_KEY_LOCK_FLAG 0x80
#define SE_CRYPTO_KEYTABLE_ACCESS_REG 0x284
#define SE_CRYPTO_KEYTABLE_ACCESS_REG_COUNT 16
#define SE_KEY_TBL_DIS_KEYREAD_FLAG BIT(0)
#define SE_KEY_TBL_DIS_KEYUPDATE_FLAG BIT(1)
#define SE_KEY_TBL_DIS_OIVREAD_FLAG BIT(2)
#define SE_KEY_TBL_DIS_OIVUPDATE_FLAG BIT(3)
#define SE_KEY_TBL_DIS_UIVREAD_FLAG BIT(4)
#define SE_KEY_TBL_DIS_UIVUPDATE_FLAG BIT(5)
#define SE_KEY_TBL_DIS_KEYUSE_FLAG BIT(6)
#define SE_KEY_TBL_DIS_KEY_ACCESS_FLAG 0x7F
#define TEGRA_SE_AES_CMAC_DIGEST_SIZE 16
#define TEGRA_SE_RSA512_DIGEST_SIZE 64
#define TEGRA_SE_RSA1024_DIGEST_SIZE 128
#define TEGRA_SE_RSA1536_DIGEST_SIZE 192
#define TEGRA_SE_RSA2048_DIGEST_SIZE 256
#define SE_CRYPTO_CONFIG_REG 0x304
#define HASH_DISABLE 0
#define HASH_ENABLE 1
#define SE_CRYPTO_HASH(x) ((x) << 0)
#define XOR_BYPASS 0
#define XOR_TOP 2
#define XOR_BOTTOM 3
#define SE_CRYPTO_XOR_POS(x) ((x) << 1)
#define INPUT_MEMORY 0
#define INPUT_RANDOM 1
#define INPUT_AESOUT 2
#define INPUT_LNR_CTR 3
#define SE_CRYPTO_INPUT_SEL(x) ((x) << 3)
#define VCTRAM_MEM 0
#define VCTRAM_AESOUT 2
#define VCTRAM_PREVMEM 3
#define SE_CRYPTO_VCTRAM_SEL(x) ((x) << 5)
#define IV_ORIGINAL 0
#define IV_UPDATED 1
#define SE_CRYPTO_IV_SEL(x) ((x) << 7)
#define CORE_DECRYPT 0
#define CORE_ENCRYPT 1
#define SE_CRYPTO_CORE_SEL(x) ((x) << 8)
#define SE_CRYPTO_KEYSCH_BYPASS BIT(10)
#define SE_CRYPTO_CTR_CNTN(x) ((x) << 11)
#define SE_CRYPTO_KEY_INDEX(x) ((x) << 24)
#define MEMIF_AHB 0
#define MEMIF_MCCIF 1
#define SE_CRYPTO_MEMIF(x) ((x) << 31)
#define SE_KEY_TABLE_ACCESS_LOCK_OFFSET 0x280
#define SE_KEY_TBL_DIS_KEY_LOCK_FLAG 0x80
#define SE_CRYPTO_LINEAR_CTR_REG 0x308
#define SE_CRYPTO_LINEAR_CTR_REG_COUNT 4
#define SE_KEY_TABLE_ACCESS_REG_OFFSET 0x284
#define SE_KEY_TBL_DIS_KEYREAD_FLAG BIT(0)
#define SE_KEY_TBL_DIS_KEYUPDATE_FLAG BIT(1)
#define SE_KEY_TBL_DIS_OIVREAD_FLAG BIT(2)
#define SE_KEY_TBL_DIS_OIVUPDATE_FLAG BIT(3)
#define SE_KEY_TBL_DIS_UIVREAD_FLAG BIT(4)
#define SE_KEY_TBL_DIS_UIVUPDATE_FLAG BIT(5)
#define SE_KEY_TBL_DIS_KEYUSE_FLAG BIT(6)
#define SE_KEY_TBL_DIS_KEY_ACCESS_FLAG 0x7F
#define SE_CRYPTO_BLOCK_COUNT_REG 0x318
#define SE_KEY_READ_DISABLE_SHIFT 0
#define SE_KEY_UPDATE_DISABLE_SHIFT 1
#define SE_CRYPTO_KEYTABLE_ADDR_REG 0x31C
#define SE_KEYTABLE_PKT(x) ((x) << 0)
#define KEYS_0_3 0
#define KEYS_4_7 1
#define ORIGINAL_IV 2
#define UPDATED_IV 3
#define SE_KEYTABLE_QUAD(x) ((x) << 2)
#define SE_KEYTABLE_SLOT(x) ((x) << 4)
#define SE_CONTEXT_BUFER_SIZE 1072
#define SE_CONTEXT_DRBG_BUFER_SIZE 2112
#define SE_CRYPTO_KEYTABLE_DATA_REG 0x320
#define SE_CONTEXT_SAVE_RANDOM_DATA_OFFSET 0
#define SE_CONTEXT_SAVE_RANDOM_DATA_SIZE 16
#define SE_CONTEXT_SAVE_STICKY_BITS_OFFSET \
(SE_CONTEXT_SAVE_RANDOM_DATA_OFFSET + SE_CONTEXT_SAVE_RANDOM_DATA_SIZE)
#define SE_CONTEXT_SAVE_STICKY_BITS_SIZE 16
#define SE_CRYPTO_KEYTABLE_DST_REG 0x330
#define KEYS_0_3 0
#define KEYS_4_7 1
#define ORIGINAL_IV 2
#define UPDATED_IV 3
#define SE_KEYTABLE_DST_WORD_QUAD(x) ((x) << 0)
#define SE_KEYTABLE_DST_KEY_INDEX(x) ((x) << 8)
#define SE_CONTEXT_SAVE_KEYS_OFFSET (SE_CONTEXT_SAVE_STICKY_BITS_OFFSET + \
SE_CONTEXT_SAVE_STICKY_BITS_SIZE)
#define SE11_CONTEXT_SAVE_KEYS_OFFSET (SE_CONTEXT_SAVE_STICKY_BITS_OFFSET + \
SE_CONTEXT_SAVE_STICKY_BITS_SIZE + \
SE_CONTEXT_SAVE_STICKY_BITS_SIZE)
#define SE_RNG_CONFIG_REG 0x340
#define MODE_NORMAL 0
#define MODE_FORCE_INSTANTION 1
#define MODE_FORCE_RESEED 2
#define SE_RNG_CONFIG_MODE(x) ((x) << 0)
#define SRC_NONE 0
#define SRC_ENTROPY 1
#define SRC_LFSR 2
#define SE_RNG_CONFIG_SRC(x) ((x) << 2)
#define SE_CONTEXT_SAVE_KEY_LENGTH 512
#define SE_CONTEXT_ORIGINAL_IV_OFFSET (SE_CONTEXT_SAVE_KEYS_OFFSET + \
SE_CONTEXT_SAVE_KEY_LENGTH)
#define SE11_CONTEXT_ORIGINAL_IV_OFFSET (SE11_CONTEXT_SAVE_KEYS_OFFSET + \
SE_CONTEXT_SAVE_KEY_LENGTH)
#define SE_RNG_SRC_CONFIG_REG 0x344
#define RO_ENTR_LOCK_DISABLE 0
#define RO_ENTR_LOCK_ENABLE 1
#define SE_RNG_SRC_CONFIG_ENTR_SRC_LOCK(x) ((x) << 0)
#define RO_ENTR_DISABLE 0
#define RO_ENTR_ENABLE 1
#define SE_RNG_SRC_CONFIG_ENTR_SRC(x) ((x) << 1)
#define RO_HW_DIS_CYA_DISABLE 0
#define RO_HW_DIS_CYA_ENABLE 1
#define SE_RNG_SRC_CONFIG_HW_DIS_CYA(x) ((x) << 2)
#define SE_RNG_SRC_CONFIG_ENTR_SUBSMPL(x) ((x) << 4)
#define SE_RNG_SRC_CONFIG_ENTR_DATA_FLUSH BIT(8)
#define SE_CONTEXT_ORIGINAL_IV_LENGTH 256
#define SE_RNG_RESEED_INTERVAL_REG 0x348
#define SE_CONTEXT_UPDATED_IV_OFFSET (SE_CONTEXT_ORIGINAL_IV_OFFSET + \
SE_CONTEXT_ORIGINAL_IV_LENGTH)
#define SE11_CONTEXT_UPDATED_IV_OFFSET (SE11_CONTEXT_ORIGINAL_IV_OFFSET + \
SE_CONTEXT_ORIGINAL_IV_LENGTH)
#define SE_RSA_CONFIG 0x400
#define RSA_KEY_SLOT_ONE 0
#define RSA_KEY_SLOT_TW0 1
#define RSA_KEY_SLOT(x) ((x) << 24)
#define SE_CONTEXT_UPDATED_IV_LENGTH 256
#define SE_RSA_KEY_SIZE_REG 0x404
#define RSA_KEY_WIDTH_512 0
#define RSA_KEY_WIDTH_1024 1
#define RSA_KEY_WIDTH_1536 2
#define RSA_KEY_WIDTH_2048 3
#define SE_CONTEXT_SAVE_KNOWN_PATTERN_OFFSET (SE_CONTEXT_UPDATED_IV_OFFSET + \
SE_CONTEXT_UPDATED_IV_LENGTH)
#define SE11_CONTEXT_SAVE_KNOWN_PATTERN_OFFSET \
(SE11_CONTEXT_UPDATED_IV_OFFSET + \
SE_CONTEXT_UPDATED_IV_LENGTH)
#define SE_RSA_EXP_SIZE_REG 0x408
#define SE_CONTEXT_SAVE_RSA_KEYS_OFFSET SE11_CONTEXT_SAVE_KNOWN_PATTERN_OFFSET
#define SE_RSA_SECURITY_PERKEY_REG 0x40C
#define SE_RSA_KEY_LOCK_FLAG 0x80
#define SE_RSA_KEYTABLE_ACCESS_REG 0x410
#define SE_RSA_KEY_TBL_DIS_KEYREAD_FLAG BIT(0)
#define SE_RSA_KEY_TBL_DIS_KEYUPDATE_FLAG BIT(1)
#define SE_RSA_KEY_TBL_DIS_KEYUSE_FLAG BIT(2)
#define SE_RSA_KEY_TBL_DIS_KEY_ACCESS_FLAG 0x7F
#define SE_RSA_KEY_TBL_DIS_KEY_READ_UPDATE_FLAG (SE_RSA_KEY_TBL_DIS_KEYREAD_FLAG | SE_RSA_KEY_TBL_DIS_KEYUPDATE_FLAG)
#define SE_RSA_KEY_TBL_DIS_KEY_READ_UPDATE_USE_FLAG (SE_RSA_KEY_TBL_DIS_KEYREAD_FLAG | SE_RSA_KEY_TBL_DIS_KEYUPDATE_FLAG | SE_RSA_KEY_TBL_DIS_KEYUSE_FLAG)
#define SE_CONTEXT_SAVE_RSA_KEY_LENGTH 1024
#define SE_RSA_KEYTABLE_ADDR_REG 0x420
#define SE_RSA_KEYTABLE_PKT(x) ((x) << 0)
#define RSA_KEY_TYPE_EXP 0
#define RSA_KEY_TYPE_MOD 1
#define SE_RSA_KEYTABLE_TYPE(x) ((x) << 6)
#define RSA_KEY_NUM(x) ((x) << 7)
#define RSA_KEY_INPUT_MODE_REG 0
#define RSA_KEY_INPUT_MODE_DMA 1
#define SE_RSA_KEYTABLE_INPUT_MODE(x) ((x) << 8)
#define RSA_KEY_READ 0
#define RSA_KEY_WRITE 1
#define SE_RSA_KEY_OP(x) ((x) << 10)
#define SE_CONTEXT_SAVE_RSA_KNOWN_PATTERN_OFFSET \
(SE_CONTEXT_SAVE_RSA_KEYS_OFFSET + SE_CONTEXT_SAVE_RSA_KEY_LENGTH)
#define SE_RSA_KEYTABLE_DATA_REG 0x424
#define SE_CONTEXT_KNOWN_PATTERN_SIZE 16
#define SE_RSA_OUTPUT_REG 0x428
#define SE_RSA_OUTPUT_REG_COUNT 64
#define TEGRA_SE_RSA_KEYSLOT_COUNT 2
#define SE_STATUS_REG 0x800
#define SE_STATUS_STATE_IDLE 0
#define SE_STATUS_STATE_BUSY 1
#define SE_STATUS_STATE_WAIT_OUT 2
#define SE_STATUS_STATE_WAIT_IN 3
#define SE_STATUS_STATE_MASK 3
#define SE_RSA_KEYTABLE_ACCESS_LOCK_OFFSET 0x40C
#define SE_RSA_KEY_TBL_DIS_KEY_LOCK_FLAG 0x80
#define SE_ERR_STATUS_REG 0x804
#define SE_ERR_STATUS_SE_NS_ACCESS BIT(0)
#define SE_ERR_STATUS_BUSY_REG_WR BIT(1)
#define SE_ERR_STATUS_DST BIT(2)
#define SE_ERR_STATUS_SRK_USAGE_LIMIT BIT(3)
#define SE_ERR_STATUS_TZRAM_NS_ACCESS BIT(24)
#define SE_ERR_STATUS_TZRAM_ADDRESS BIT(25)
#define SE_RSA_KEYTABLE_ACCESS_REG_OFFSET 0x410
#define SE_RSA_KEY_TBL_DIS_KEYREAD_FLAG BIT(0)
#define SE_RSA_KEY_TBL_DIS_KEYUPDATE_FLAG BIT(1)
#define SE_RSA_KEY_TBL_DIS_KEY_READ_UPDATE_FLAG (SE_RSA_KEY_TBL_DIS_KEYREAD_FLAG | SE_RSA_KEY_TBL_DIS_KEYUPDATE_FLAG)
#define SE_RSA_KEY_TBL_DIS_KEYUSE_FLAG BIT(2)
#define SE_RSA_KEY_TBL_DIS_KEYUSE_FLAG_SHIFT BIT(2)
#define SE_RSA_KEY_TBL_DIS_KEY_ALL_COMMON_FLAG 7
#define SE_RSA_KEY_TBL_DIS_KEY_ALL_FLAG 0x7F
#define SE_MISC_REG 0x808
#define SE_ENTROPY_NEXT_192BIT BIT(0)
#define SE_ENTROPY_VN_BYPASS BIT(1)
#define SE_CLK_OVR_ON BIT(2)
#define SE_RSA_KEYTABLE_ADDR 0x420
#define SE_RSA_KEYTABLE_DATA 0x424
#define SE_RSA_OUTPUT 0x428
#define SE_SPARE_REG 0x80C
#define SE_ERRATA_FIX_DISABLE 0
#define SE_ERRATA_FIX_ENABLE 1
#define SE_ECO(x) ((x) << 0)
#define RSA_KEY_READ 0
#define RSA_KEY_WRITE 1
#define SE_RSA_KEY_OP_SHIFT 10
#define SE_RSA_KEY_OP(x) ((x) << SE_RSA_KEY_OP_SHIFT)
#define RSA_KEY_INPUT_MODE_REG 0
#define RSA_KEY_INPUT_MODE_DMA 1
#define RSA_KEY_INPUT_MODE_SHIFT 8
#define RSA_KEY_INPUT_MODE(x) ((x) << RSA_KEY_INPUT_MODE_SHIFT)
#define RSA_KEY_SLOT_ONE 0
#define RSA_KEY_SLOT_TW0 1
#define RSA_KEY_NUM_SHIFT 7
#define RSA_KEY_NUM(x) ((x) << RSA_KEY_NUM_SHIFT)
#define RSA_KEY_TYPE_EXP 0
#define RSA_KEY_TYPE_MOD 1
#define RSA_KEY_TYPE_SHIFT 6
#define RSA_KEY_TYPE(x) ((x) << RSA_KEY_TYPE_SHIFT)
#define SE_RSA_KEY_SIZE_REG_OFFSET 0x404
#define SE_RSA_EXP_SIZE_REG_OFFSET 0x408
#define RSA_KEY_SLOT_SHIFT 24
#define RSA_KEY_SLOT(x) ((x) << RSA_KEY_SLOT_SHIFT)
#define SE_RSA_CONFIG 0x400
#define RSA_KEY_PKT_WORD_ADDR_SHIFT 0
#define RSA_KEY_PKT_WORD_ADDR(x) ((x) << RSA_KEY_PKT_WORD_ADDR_SHIFT)
#define RSA_KEY_WORD_ADDR_SHIFT 0
#define RSA_KEY_WORD_ADDR(x) ((x) << RSA_KEY_WORD_ADDR_SHIFT)
#define SE_RSA_KEYTABLE_PKT_SHIFT 0
#define SE_RSA_KEYTABLE_PKT(x) ((x) << SE_RSA_KEYTABLE_PKT_SHIFT)
#endif /* _CRYPTO_TEGRA_SE_H */
#endif

View File

@@ -1,6 +1,6 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2019 CTCaer
* Copyright (c) 2018-2021 CTCaer
* Copyright (c) 2018 balika011
*
* This program is free software; you can redistribute it and/or modify it
@@ -62,7 +62,7 @@ static int _tsec_dma_pa_to_internal_100(int not_imem, int i_offset, int pa_offse
return _tsec_dma_wait_idle();
}
int tsec_query(u8 *tsec_keys, u8 kb, tsec_ctxt_t *tsec_ctxt)
int tsec_query(void *tsec_keys, u8 kb, tsec_ctxt_t *tsec_ctxt)
{
int res = 0;
u8 *fwbuf = NULL;
@@ -190,7 +190,7 @@ int tsec_query(u8 *tsec_keys, u8 kb, tsec_ctxt_t *tsec_ctxt)
if (kb == KB_TSEC_FW_EMU_COMPAT)
{
u32 start = get_tmr_us();
u32 k = se[SE_KEYTABLE_DATA0_REG_OFFSET / 4];
u32 k = se[SE_CRYPTO_KEYTABLE_DATA_REG / 4];
u32 key[16] = {0};
u32 kidx = 0;
@@ -198,9 +198,9 @@ int tsec_query(u8 *tsec_keys, u8 kb, tsec_ctxt_t *tsec_ctxt)
{
smmu_flush_all();
if (k != se[SE_KEYTABLE_DATA0_REG_OFFSET / 4])
if (k != se[SE_CRYPTO_KEYTABLE_DATA_REG / 4])
{
k = se[SE_KEYTABLE_DATA0_REG_OFFSET / 4];
k = se[SE_CRYPTO_KEYTABLE_DATA_REG / 4];
key[kidx++] = k;
}
@@ -269,7 +269,7 @@ int tsec_query(u8 *tsec_keys, u8 kb, tsec_ctxt_t *tsec_ctxt)
SOR1(SOR_NV_PDISP_SOR_TMDS_HDCP_CN_MSB) = 0;
SOR1(SOR_NV_PDISP_SOR_TMDS_HDCP_CN_LSB) = 0;
memcpy(tsec_keys, &buf, 0x10);
memcpy(tsec_keys, &buf, SE_KEY_128_SIZE);
}
out_free:;

View File

@@ -29,6 +29,6 @@ typedef struct _tsec_ctxt_t
u32 secmon_base;
} tsec_ctxt_t;
int tsec_query(u8 *tsec_keys, u8 kb, tsec_ctxt_t *tsec_ctxt);
int tsec_query(void *tsec_keys, u8 kb, tsec_ctxt_t *tsec_ctxt);
#endif

View File

@@ -1,6 +1,6 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2020 CTCaer
* Copyright (c) 2018-2021 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
@@ -42,6 +42,7 @@
#include <storage/nx_sd.h>
#include <storage/sdmmc.h>
#include <thermal/fan.h>
#include <thermal/tmp451.h>
#include <utils/util.h>
extern boot_cfg_t b_cfg;
@@ -263,7 +264,7 @@ static void _config_se_brom()
FUSE(FUSE_PRIVATE_KEY3)
};
// Set SBK to slot 14.
se_aes_key_set(14, sbk, 0x10);
se_aes_key_set(14, sbk, SE_KEY_128_SIZE);
// Lock SBK from being read.
se_key_acc_ctrl(14, SE_KEY_TBL_DIS_KEYREAD_FLAG);
@@ -275,7 +276,7 @@ static void _config_se_brom()
// This memset needs to happen here, else TZRAM will behave weirdly later on.
memset((void *)TZRAM_BASE, 0, 0x10000);
PMC(APBDEV_PMC_CRYPTO_OP) = PMC_CRYPTO_OP_SE_ENABLE;
SE(SE_INT_STATUS_REG_OFFSET) = 0x1F;
SE(SE_INT_STATUS_REG) = 0x1F; // Clear all SE interrupts.
// Clear the boot reason to avoid problems later
PMC(APBDEV_PMC_SCRATCH200) = 0x0;
@@ -425,11 +426,12 @@ void hw_reinit_workaround(bool coreboot, u32 magic)
bpmp_clk_rate_set(BPMP_CLK_NORMAL);
#ifdef NYX
// Deinit touchscreen, 5V regulators and Joy-Con.
touch_power_off();
// Disable temperature sensor, touchscreen, 5V regulators and Joy-Con.
tmp451_end();
set_fan_duty(0);
touch_power_off();
jc_deinit();
regulator_disable_5v(REGULATOR_5V_ALL);
regulator_5v_disable(REGULATOR_5V_ALL);
clock_disable_uart(UART_B);
clock_disable_uart(UART_C);
#endif

View File

@@ -84,6 +84,11 @@
#define MMC_APP_CMD 55 /* ac [31:16] RCA R1 */
#define MMC_GEN_CMD 56 /* adtc [0] RD/WR R1 */
#define MMC_VENDOR_60_CMD 60 /* Vendor Defined */
#define MMC_VENDOR_61_CMD 61 /* Vendor Defined */
#define MMC_VENDOR_62_CMD 62 /* Vendor Defined */
#define MMC_VENDOR_63_CMD 63 /* Vendor Defined */
/* class 11 */
#define MMC_QUE_TASK_PARAMS 44 /* ac [20:16] task id R1 */
#define MMC_QUE_TASK_ADDR 45 /* ac [31:0] data addr R1 */
@@ -182,7 +187,10 @@ c : clear by read
/*
* OCR bits are mostly in host.h
*/
#define MMC_CARD_BUSY 0x80000000 /* Card Power up status bit */
#define MMC_CARD_VDD_18 (1 << 7) /* Card VDD voltage 1.8 */
#define MMC_CARD_VDD_27_34 (0x7F << 15) /* Card VDD voltage 2.7 ~ 3.4 */
#define MMC_CARD_CCS (1 << 30) /* Card Capacity status bit */
#define MMC_CARD_BUSY (1 << 31) /* Card Power up status bit */
/*
* Card Command Classes (CCC)
@@ -244,6 +252,7 @@ c : clear by read
#define EXT_CSD_GP_SIZE_MULT 143 /* R/W */
#define EXT_CSD_PARTITION_SETTING_COMPLETED 155 /* R/W */
#define EXT_CSD_PARTITION_ATTRIBUTE 156 /* R/W */
#define EXT_CSD_MAX_ENH_SIZE_MULT 157 /* RO, 3 bytes */
#define EXT_CSD_PARTITION_SUPPORT 160 /* RO */
#define EXT_CSD_HPI_MGMT 161 /* R/W */
#define EXT_CSD_RST_N_FUNCTION 162 /* R/W */

View File

@@ -1,6 +1,6 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2019 CTCaer
* Copyright (c) 2018-2021 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
@@ -45,12 +45,14 @@ extern FATFS sd_fs;
void sd_error_count_increment(u8 type);
u16 *sd_get_error_count();
bool sd_get_card_removed();
bool sd_get_card_initialized();
u32 sd_get_mode();
int sd_init_retry(bool power_cycle);
bool sd_initialize(bool power_cycle);
bool sd_mount();
void sd_unmount();
void sd_end();
bool sd_is_gpt();
void *sd_file_read(const char *path, u32 *fsize);
int sd_save_to_file(void *buf, u32 size, const char *filename);

View File

@@ -1,7 +1,7 @@
/*
* Ramdisk driver for Tegra X1
*
* Copyright (c) 2019 CTCaer
* Copyright (c) 2019-2021 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
@@ -19,23 +19,40 @@
#include <string.h>
#include "ramdisk.h"
#include <libs/fatfs/diskio.h>
#include <mem/heap.h>
#include <utils/types.h>
#include <memory_map.h>
int ram_disk_init(FATFS *ram_fs)
static u32 disk_size = 0;
int ram_disk_init(FATFS *ram_fs, u32 ramdisk_size)
{
int res;
u8 *buf = malloc(0x400000);
int res = 0;
disk_size = ramdisk_size;
f_mount(NULL, "ram:", 1); // Unmount ramdisk.
// If ramdisk is not raw, format it.
if (ram_fs)
{
u8 *buf = malloc(0x400000);
res = f_mkfs("ram:", FM_EXFAT, RAMDISK_CLUSTER_SZ, buf, 0x400000); // Format as exFAT w/ 32KB cluster.
if (!res)
res = f_mount(ram_fs, "ram:", 1); // Mount ramdisk.
// Set ramdisk size.
ramdisk_size >>= 9;
disk_set_info(DRIVE_RAM, SET_SECTOR_COUNT, &ramdisk_size);
free(buf);
// Unmount ramdisk.
f_mount(NULL, "ram:", 1);
// Format as exFAT w/ 32KB cluster with no MBR.
res = f_mkfs("ram:", FM_EXFAT | FM_SFD, RAMDISK_CLUSTER_SZ, buf, 0x400000);
// Mount ramdisk.
if (!res)
res = f_mount(ram_fs, "ram:", 1);
free(buf);
}
return res;
}
@@ -45,7 +62,7 @@ int ram_disk_read(u32 sector, u32 sector_count, void *buf)
u32 sector_off = RAM_DISK_ADDR + (sector << 9);
u32 bytes_count = sector_count << 9;
if ((sector_off - RAM_DISK_ADDR) > RAM_DISK_SZ)
if ((sector_off - RAM_DISK_ADDR) > disk_size)
return 1;
memcpy(buf, (void *)sector_off, bytes_count);
@@ -58,7 +75,7 @@ int ram_disk_write(u32 sector, u32 sector_count, const void *buf)
u32 sector_off = RAM_DISK_ADDR + (sector << 9);
u32 bytes_count = sector_count << 9;
if ((sector_off - RAM_DISK_ADDR) > RAM_DISK_SZ)
if ((sector_off - RAM_DISK_ADDR) > disk_size)
return 1;
memcpy((void *)sector_off, buf, bytes_count);

View File

@@ -1,7 +1,7 @@
/*
* Ramdisk driver for Tegra X1
*
* Copyright (c) 2019 CTCaer
* Copyright (c) 2019-2021 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
@@ -23,7 +23,7 @@
#define RAMDISK_CLUSTER_SZ 32768
int ram_disk_init(FATFS *ram_fs);
int ram_disk_init(FATFS *ram_fs, u32 ramdisk_size);
int ram_disk_read(u32 sector, u32 sector_count, void *buf);
int ram_disk_write(u32 sector, u32 sector_count, const void *buf);

View File

@@ -1,6 +1,6 @@
/*
* Copyright (c) 2005-2007 Pierre Ossman, All Rights Reserved.
* Copyright (c) 2018 CTCaer
* Copyright (c) 2018-2021 CTCaer
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -14,60 +14,79 @@
/* SD commands type argument response */
/* class 0 */
/* This is basically the same command as for MMC with some quirks. */
#define SD_SEND_RELATIVE_ADDR 3 /* bcr R6 */
#define SD_SEND_IF_COND 8 /* bcr [11:0] See below R7 */
#define SD_SWITCH_VOLTAGE 11 /* ac R1 */
#define SD_SEND_RELATIVE_ADDR 3 /* bcr R6 */
#define SD_SEND_IF_COND 8 /* bcr [11:0] See below R7 */
#define SD_SWITCH_VOLTAGE 11 /* ac R1 */
/* class 10 */
#define SD_SWITCH 6 /* adtc [31:0] See below R1 */
#define SD_SWITCH 6 /* adtc [31:0] See below R1 */
/* class 5 */
#define SD_ERASE_WR_BLK_START 32 /* ac [31:0] data addr R1 */
#define SD_ERASE_WR_BLK_END 33 /* ac [31:0] data addr R1 */
#define SD_ERASE_WR_BLK_START 32 /* ac [31:0] data addr R1 */
#define SD_ERASE_WR_BLK_END 33 /* ac [31:0] data addr R1 */
/* Application commands */
#define SD_APP_SET_BUS_WIDTH 6 /* ac [1:0] bus width R1 */
#define SD_APP_SD_STATUS 13 /* adtc R1 */
#define SD_APP_SEND_NUM_WR_BLKS 22 /* adtc R1 */
#define SD_APP_OP_COND 41 /* bcr [31:0] OCR R3 */
#define SD_APP_SET_CLR_CARD_DETECT 42
#define SD_APP_SEND_SCR 51 /* adtc R1 */
#define SD_APP_SET_BUS_WIDTH 6 /* ac [1:0] bus width R1 */
#define SD_APP_SD_STATUS 13 /* adtc R1 */
#define SD_APP_SEND_NUM_WR_BLKS 22 /* adtc R1 */
#define SD_APP_OP_COND 41 /* bcr [31:0] OCR R3 */
#define SD_APP_SET_CLR_CARD_DETECT 42 /* adtc R1 */
#define SD_APP_SEND_SCR 51 /* adtc R1 */
/* Application secure commands */
#define SD_APP_SECURE_READ_MULTI_BLOCK 18 /* adtc R1 */
#define SD_APP_SECURE_WRITE_MULTI_BLOCK 25 /* adtc R1 */
#define SD_APP_SECURE_WRITE_MKB 26 /* adtc R1 */
#define SD_APP_SECURE_ERASE 38 /* adtc R1b */
#define SD_APP_GET_MKB 43 /* adtc [31:0] See below R1 */
#define SD_APP_GET_MID 44 /* adtc R1 */
#define SD_APP_SET_CER_RN1 45 /* adtc R1 */
#define SD_APP_GET_CER_RN2 46 /* adtc R1 */
#define SD_APP_SET_CER_RES2 47 /* adtc R1 */
#define SD_APP_GET_CER_RES1 48 /* adtc R1 */
#define SD_APP_CHANGE_SECURE_AREA 49 /* adtc R1b */
/* OCR bit definitions */
#define SD_OCR_CCS (1 << 30) /* Card Capacity Status */
#define SD_OCR_XPC (1 << 28) /* SDXC power control */
#define SD_OCR_S18R (1 << 24) /* 1.8V switching request */
#define SD_ROCR_S18A SD_OCR_S18R /* 1.8V switching accepted by card */
#define SD_OCR_VDD_18 (1 << 7) /* VDD voltage 1.8 */
#define SD_VHD_27_36 (1 << 8) /* VDD voltage 2.7 ~ 3.6 */
#define SD_OCR_VDD_27_34 (0x7F << 15) /* VDD voltage 2.7 ~ 3.4 */
#define SD_OCR_VDD_32_33 (1 << 20) /* VDD voltage 3.2 ~ 3.3 */
#define SD_OCR_VDD_18 (1 << 7) /* VDD voltage 1.8 */
#define SD_VHD_27_36 (1 << 8) /* VDD voltage 2.7 ~ 3.6 */
#define SD_OCR_S18R (1 << 24) /* 1.8V switching request */
#define SD_ROCR_S18A SD_OCR_S18R /* 1.8V switching accepted by card */
#define SD_OCR_XPC (1 << 28) /* SDXC power control */
#define SD_OCR_CCS (1 << 30) /* Card Capacity Status */
#define SD_OCR_BUSY (1 << 31) /* Card Power up Status */
/*
* SD_SWITCH argument format:
*
* [31] Check (0) or switch (1)
* [30:24] Reserved (0)
* [23:20] Function group 6
* [19:16] Function group 5
* [15:12] Function group 4
* [11:8] Function group 3
* [7:4] Function group 2
* [3:0] Function group 1
*/
* SD_SWITCH argument format:
*
* [31] Check (0) or switch (1)
* [30:24] Reserved (0)
* [23:20] Function group 6
* [19:16] Function group 5
* [15:12] Function group 4
* [11:8] Function group 3
* [7:4] Function group 2
* [3:0] Function group 1
*/
/*
* SD_SEND_IF_COND argument format:
*
* [31:12] Reserved (0)
* [11:8] Host Voltage Supply Flags
* [7:0] Check Pattern (0xAA)
*/
* SD_SEND_IF_COND argument format:
*
* [31:12] Reserved (0)
* [11:8] Host Voltage Supply Flags
* [7:0] Check Pattern (0xAA)
*/
/*
* SCR field definitions
*/
* SD_APP_GET_MKB argument format:
*
* [31:24] Number of blocks to read (512 block size)
* [23:16] MKB ID
* [15:0] Block offset
*/
/*
* SCR field definitions
*/
#define SCR_SPEC_VER_0 0 /* Implements system specification 1.0 - 1.01 */
#define SCR_SPEC_VER_1 1 /* Implements system specification 1.10 */
#define SCR_SPEC_VER_2 2 /* Implements system specification 2.00-3.0X */
@@ -75,14 +94,14 @@
#define SD_SCR_BUS_WIDTH_4 (1<<2)
/*
* SD bus widths
*/
* SD bus widths
*/
#define SD_BUS_WIDTH_1 0
#define SD_BUS_WIDTH_4 2
/*
* SD bus speeds
*/
* SD bus speeds
*/
#define UHS_SDR12_BUS_SPEED 0
#define HIGH_SPEED_BUS_SPEED 1
#define UHS_SDR25_BUS_SPEED 1
@@ -112,19 +131,19 @@
#define SD_MAX_CURRENT_800 (1 << SD_SET_CURRENT_LIMIT_800)
/*
* SD_SWITCH mode
*/
* SD_SWITCH mode
*/
#define SD_SWITCH_CHECK 0
#define SD_SWITCH_SET 1
/*
* SD_SWITCH function groups
*/
* SD_SWITCH function groups
*/
#define SD_SWITCH_GRP_ACCESS 0
/*
* SD_SWITCH access modes
*/
* SD_SWITCH access modes
*/
#define SD_SWITCH_ACCESS_DEF 0
#define SD_SWITCH_ACCESS_HS 1

View File

@@ -1,6 +1,6 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2020 CTCaer
* Copyright (c) 2018-2021 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
@@ -42,8 +42,8 @@ static inline u32 unstuff_bits(u32 *resp, u32 start, u32 size)
}
/*
* Common functions for SD and MMC.
*/
* Common functions for SD and MMC.
*/
static int _sdmmc_storage_check_card_status(u32 res)
{
@@ -88,20 +88,20 @@ static int _sdmmc_storage_execute_cmd_type1(sdmmc_storage_t *storage, u32 cmd, u
static int _sdmmc_storage_go_idle_state(sdmmc_storage_t *storage)
{
sdmmc_cmd_t cmd;
sdmmc_init_cmd(&cmd, MMC_GO_IDLE_STATE, 0, SDMMC_RSP_TYPE_0, 0);
sdmmc_cmd_t cmdbuf;
sdmmc_init_cmd(&cmdbuf, MMC_GO_IDLE_STATE, 0, SDMMC_RSP_TYPE_0, 0);
return sdmmc_execute_cmd(storage->sdmmc, &cmd, NULL, NULL);
return sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, NULL, NULL);
}
static int _sdmmc_storage_get_cid(sdmmc_storage_t *storage, void *buf)
static int _sdmmc_storage_get_cid(sdmmc_storage_t *storage)
{
sdmmc_cmd_t cmd;
sdmmc_init_cmd(&cmd, MMC_ALL_SEND_CID, 0, SDMMC_RSP_TYPE_2, 0);
if (!sdmmc_execute_cmd(storage->sdmmc, &cmd, NULL, NULL))
sdmmc_cmd_t cmdbuf;
sdmmc_init_cmd(&cmdbuf, MMC_ALL_SEND_CID, 0, SDMMC_RSP_TYPE_2, 0);
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, NULL, NULL))
return 0;
sdmmc_get_rsp(storage->sdmmc, buf, 16, SDMMC_RSP_TYPE_2);
sdmmc_get_rsp(storage->sdmmc, (u32 *)storage->raw_cid, 16, SDMMC_RSP_TYPE_2);
return 1;
}
@@ -111,14 +111,14 @@ static int _sdmmc_storage_select_card(sdmmc_storage_t *storage)
return _sdmmc_storage_execute_cmd_type1(storage, MMC_SELECT_CARD, storage->rca << 16, 1, R1_SKIP_STATE_CHECK);
}
static int _sdmmc_storage_get_csd(sdmmc_storage_t *storage, void *buf)
static int _sdmmc_storage_get_csd(sdmmc_storage_t *storage)
{
sdmmc_cmd_t cmdbuf;
sdmmc_init_cmd(&cmdbuf, MMC_SEND_CSD, storage->rca << 16, SDMMC_RSP_TYPE_2, 0);
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, NULL, NULL))
return 0;
sdmmc_get_rsp(storage->sdmmc, buf, 16, SDMMC_RSP_TYPE_2);
sdmmc_get_rsp(storage->sdmmc, (u32 *)storage->raw_csd, 16, SDMMC_RSP_TYPE_2);
return 1;
}
@@ -145,6 +145,10 @@ static int _sdmmc_storage_readwrite_ex(sdmmc_storage_t *storage, u32 *blkcnt_out
sdmmc_cmd_t cmdbuf;
sdmmc_req_t reqbuf;
// If SDSC convert block address to byte address.
if (!storage->has_sector_access)
sector <<= 9;
sdmmc_init_cmd(&cmdbuf, is_write ? MMC_WRITE_MULTIPLE_BLOCK : MMC_READ_MULTIPLE_BLOCK, sector, SDMMC_RSP_TYPE_1, 0);
reqbuf.buf = buf;
@@ -152,7 +156,7 @@ static int _sdmmc_storage_readwrite_ex(sdmmc_storage_t *storage, u32 *blkcnt_out
reqbuf.blksize = 512;
reqbuf.is_write = is_write;
reqbuf.is_multi_block = 1;
reqbuf.is_auto_cmd12 = 1;
reqbuf.is_auto_stop_trn = 1;
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, &reqbuf, blkcnt_out))
{
@@ -288,25 +292,25 @@ int sdmmc_storage_write(sdmmc_storage_t *storage, u32 sector, u32 num_sectors, v
static int _mmc_storage_get_op_cond_inner(sdmmc_storage_t *storage, u32 *pout, u32 power)
{
sdmmc_cmd_t cmd;
sdmmc_cmd_t cmdbuf;
u32 arg = 0;
switch (power)
{
case SDMMC_POWER_1_8:
arg = SD_OCR_CCS | SD_OCR_VDD_18;
arg = MMC_CARD_CCS | MMC_CARD_VDD_18;
break;
case SDMMC_POWER_3_3:
arg = SD_OCR_CCS | SD_OCR_VDD_27_34;
arg = MMC_CARD_CCS | MMC_CARD_VDD_27_34;
break;
default:
return 0;
}
sdmmc_init_cmd(&cmd, MMC_SEND_OP_COND, arg, SDMMC_RSP_TYPE_3, 0);
if (!sdmmc_execute_cmd(storage->sdmmc, &cmd, NULL, NULL))
sdmmc_init_cmd(&cmdbuf, MMC_SEND_OP_COND, arg, SDMMC_RSP_TYPE_3, 0);
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, NULL, NULL))
return 0;
return sdmmc_get_rsp(storage->sdmmc, pout, 4, SDMMC_RSP_TYPE_3);
@@ -316,15 +320,17 @@ static int _mmc_storage_get_op_cond(sdmmc_storage_t *storage, u32 power)
{
u32 timeout = get_tmr_ms() + 1500;
while (1)
while (true)
{
u32 cond = 0;
if (!_mmc_storage_get_op_cond_inner(storage, &cond, power))
break;
// Check if power up is done.
if (cond & MMC_CARD_BUSY)
{
if (cond & SD_OCR_CCS)
// Check if card is high capacity.
if (cond & MMC_CARD_CCS)
storage->has_sector_access = 1;
return 1;
@@ -362,7 +368,6 @@ static void _mmc_storage_parse_cid(sdmmc_storage_t *storage)
case 3: /* MMC v3.1 - v3.3 */
case 4: /* MMC v4 */
storage->cid.manfid = unstuff_bits(raw_cid, 120, 8);
storage->cid.card_bga = unstuff_bits(raw_cid, 112, 2);
storage->cid.oemid = unstuff_bits(raw_cid, 104, 8);
storage->cid.prv = unstuff_bits(raw_cid, 48, 8);
storage->cid.serial = unstuff_bits(raw_cid, 16, 32);
@@ -390,13 +395,14 @@ static void _mmc_storage_parse_cid(sdmmc_storage_t *storage)
static void _mmc_storage_parse_csd(sdmmc_storage_t *storage)
{
u32 *raw_csd = (u32 *)&(storage->raw_csd);
u32 *raw_csd = (u32 *)storage->raw_csd;
storage->csd.mmca_vsn = unstuff_bits(raw_csd, 122, 4);
storage->csd.structure = unstuff_bits(raw_csd, 126, 2);
storage->csd.cmdclass = unstuff_bits(raw_csd, 84, 12);
storage->csd.read_blkbits = unstuff_bits(raw_csd, 80, 4);
storage->csd.capacity = (1 + unstuff_bits(raw_csd, 62, 12)) << (unstuff_bits(raw_csd, 47, 3) + 2);
storage->sec_cnt = storage->csd.capacity;
}
static void _mmc_storage_parse_ext_csd(sdmmc_storage_t *storage, u8 *buf)
@@ -407,16 +413,26 @@ static void _mmc_storage_parse_ext_csd(sdmmc_storage_t *storage, u8 *buf)
storage->ext_csd.dev_version = *(u16 *)&buf[EXT_CSD_DEVICE_VERSION];
storage->ext_csd.boot_mult = buf[EXT_CSD_BOOT_MULT];
storage->ext_csd.rpmb_mult = buf[EXT_CSD_RPMB_MULT];
storage->ext_csd.sectors = *(u32 *)&buf[EXT_CSD_SEC_CNT];
storage->ext_csd.bkops = buf[EXT_CSD_BKOPS_SUPPORT];
storage->ext_csd.bkops_en = buf[EXT_CSD_BKOPS_EN];
storage->ext_csd.bkops_status = buf[EXT_CSD_BKOPS_STATUS];
//storage->ext_csd.bkops = buf[EXT_CSD_BKOPS_SUPPORT];
//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];
storage->ext_csd.cache_size =
buf[EXT_CSD_CACHE_SIZE] |
(buf[EXT_CSD_CACHE_SIZE + 1] << 8) |
(buf[EXT_CSD_CACHE_SIZE + 2] << 16) |
(buf[EXT_CSD_CACHE_SIZE + 3] << 24);
storage->ext_csd.max_enh_mult =
(buf[EXT_CSD_MAX_ENH_SIZE_MULT] |
(buf[EXT_CSD_MAX_ENH_SIZE_MULT + 1] << 8) |
(buf[EXT_CSD_MAX_ENH_SIZE_MULT + 2] << 16)) *
buf[EXT_CSD_HC_WP_GRP_SIZE] * buf[EXT_CSD_HC_ERASE_GRP_SIZE];
storage->sec_cnt = *(u32 *)&buf[EXT_CSD_SEC_CNT];
}
static int _mmc_storage_get_ext_csd(sdmmc_storage_t *storage, void *buf)
@@ -430,7 +446,7 @@ static int _mmc_storage_get_ext_csd(sdmmc_storage_t *storage, void *buf)
reqbuf.num_sectors = 1;
reqbuf.is_write = 0;
reqbuf.is_multi_block = 0;
reqbuf.is_auto_cmd12 = 0;
reqbuf.is_auto_stop_trn = 0;
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, &reqbuf, NULL))
return 0;
@@ -559,19 +575,21 @@ out:
return 1;
}
/*
static int _mmc_storage_enable_bkops(sdmmc_storage_t *storage)
{
if (!_mmc_storage_switch(storage, SDMMC_SWITCH(MMC_SWITCH_MODE_SET_BITS, EXT_CSD_BKOPS_EN, EXT_CSD_BKOPS_LEVEL_2)))
if (!_mmc_storage_switch(storage, SDMMC_SWITCH(MMC_SWITCH_MODE_SET_BITS, EXT_CSD_BKOPS_EN, EXT_CSD_AUTO_BKOPS_MASK)))
return 0;
return _sdmmc_storage_check_status(storage);
}
*/
int sdmmc_storage_init_mmc(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 bus_width, u32 type)
{
memset(storage, 0, sizeof(sdmmc_storage_t));
storage->sdmmc = sdmmc;
storage->rca = 2; //TODO: this could be a config item.
storage->rca = 2; // Set default device address. This could be a config item.
if (!sdmmc_init(sdmmc, SDMMC_4, SDMMC_POWER_1_8, SDMMC_BUS_WIDTH_1, SDHCI_TIMING_MMC_ID, SDMMC_POWER_SAVE_DISABLE))
return 0;
@@ -587,7 +605,7 @@ DPRINTF("[MMC] went to idle state\n");
return 0;
DPRINTF("[MMC] got op cond\n");
if (!_sdmmc_storage_get_cid(storage, storage->raw_cid))
if (!_sdmmc_storage_get_cid(storage))
return 0;
DPRINTF("[MMC] got cid\n");
@@ -595,7 +613,7 @@ DPRINTF("[MMC] got cid\n");
return 0;
DPRINTF("[MMC] set relative addr\n");
if (!_sdmmc_storage_get_csd(storage, storage->raw_csd))
if (!_sdmmc_storage_get_csd(storage))
return 0;
DPRINTF("[MMC] got csd\n");
_mmc_storage_parse_csd(storage);
@@ -612,13 +630,9 @@ DPRINTF("[MMC] card selected\n");
return 0;
DPRINTF("[MMC] set blocklen to 512\n");
u32 *csd = (u32 *)storage->raw_csd;
//Check system specification version, only version 4.0 and later support below features.
if (unstuff_bits(csd, 122, 4) < CSD_SPEC_VER_4)
{
storage->sec_cnt = (1 + unstuff_bits(csd, 62, 12)) << (unstuff_bits(csd, 47, 3) + 2);
// Check system specification version, only version 4.0 and later support below features.
if (storage->csd.mmca_vsn < CSD_SPEC_VER_4)
return 1;
}
if (!_mmc_storage_switch_buswidth(storage, bus_width))
return 0;
@@ -628,21 +642,20 @@ DPRINTF("[MMC] switched buswidth\n");
return 0;
DPRINTF("[MMC] got ext_csd\n");
_mmc_storage_parse_cid(storage); //This needs to be after csd and ext_csd
_mmc_storage_parse_cid(storage); // This needs to be after csd and ext_csd.
//gfx_hexdump(0, ext_csd, 512);
/* When auto BKOPS is enabled the mmc device should be powered all the time until we disable this and check status.
Disable it for now until BKOPS disable added to power down sequence at sdmmc_storage_end().
Additionally this works only when we put the device in idle mode which we don't after enabling it. */
if (0 && storage->ext_csd.bkops & 0x1 && !(storage->ext_csd.bkops_en & EXT_CSD_BKOPS_LEVEL_2))
/*
if (storage->ext_csd.bkops & 0x1 && !(storage->ext_csd.bkops_en & EXT_CSD_AUTO_BKOPS_MASK))
{
_mmc_storage_enable_bkops(storage);
DPRINTF("[MMC] BKOPS enabled\n");
}
*/
if (!_mmc_storage_enable_highspeed(storage, storage->ext_csd.card_type, type))
return 0;
DPRINTF("[MMC] succesfully switched to HS mode\n");
DPRINTF("[MMC] successfully switched to HS mode\n");
sdmmc_card_clock_powersave(storage->sdmmc, SDMMC_POWER_SAVE_ENABLE);
@@ -665,16 +678,16 @@ int sdmmc_storage_set_mmc_partition(sdmmc_storage_t *storage, u32 partition)
}
/*
* SD specific functions.
*/
* SD specific functions.
*/
static int _sd_storage_execute_app_cmd(sdmmc_storage_t *storage, u32 expected_state, u32 mask, sdmmc_cmd_t *cmd, sdmmc_req_t *req, u32 *blkcnt_out)
static int _sd_storage_execute_app_cmd(sdmmc_storage_t *storage, u32 expected_state, u32 mask, sdmmc_cmd_t *cmdbuf, sdmmc_req_t *req, u32 *blkcnt_out)
{
u32 tmp;
if (!_sdmmc_storage_execute_cmd_type1_ex(storage, &tmp, MMC_APP_CMD, storage->rca << 16, 0, expected_state, mask))
return 0;
return sdmmc_execute_cmd(storage->sdmmc, cmd, req, blkcnt_out);
return sdmmc_execute_cmd(storage->sdmmc, cmdbuf, req, blkcnt_out);
}
static int _sd_storage_execute_app_cmd_type1(sdmmc_storage_t *storage, u32 *resp, u32 cmd, u32 arg, u32 check_busy, u32 expected_state)
@@ -685,67 +698,70 @@ static int _sd_storage_execute_app_cmd_type1(sdmmc_storage_t *storage, u32 *resp
return _sdmmc_storage_execute_cmd_type1_ex(storage, resp, cmd, arg, check_busy, expected_state, 0);
}
static int _sd_storage_send_if_cond(sdmmc_storage_t *storage)
static int _sd_storage_send_if_cond(sdmmc_storage_t *storage, bool *is_sdsc)
{
sdmmc_cmd_t cmdbuf;
u16 vhd_pattern = SD_VHD_27_36 | 0xAA;
sdmmc_init_cmd(&cmdbuf, SD_SEND_IF_COND, vhd_pattern, SDMMC_RSP_TYPE_5, 0);
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, NULL, NULL))
return 1; // The SD Card is version 1.X
{
*is_sdsc = 1; // The SD Card is version 1.X
return 1;
}
// Card version is >= 2.0, parse results.
// For Card version >= 2.0, parse results.
u32 resp = 0;
if (!sdmmc_get_rsp(storage->sdmmc, &resp, 4, SDMMC_RSP_TYPE_5))
return 2; // Failed.
sdmmc_get_rsp(storage->sdmmc, &resp, 4, SDMMC_RSP_TYPE_5);
// Check if VHD was accepted and pattern was properly returned.
if ((resp & 0xFFF) == vhd_pattern)
return 0;
return 1;
// Failed.
return 2;
return 0;
}
static int _sd_storage_get_op_cond_once(sdmmc_storage_t *storage, u32 *cond, int is_version_1, int bus_uhs_support)
static int _sd_storage_get_op_cond_once(sdmmc_storage_t *storage, u32 *cond, bool is_sdsc, int bus_uhs_support)
{
sdmmc_cmd_t cmdbuf;
// Support for Current > 150mA
u32 arg = !is_version_1 ? SD_OCR_XPC : 0;
u32 arg = !is_sdsc ? SD_OCR_XPC : 0;
// Support for handling block-addressed SDHC cards
arg |= !is_version_1 ? SD_OCR_CCS : 0;
arg |= !is_sdsc ? SD_OCR_CCS : 0;
// Support for 1.8V
arg |= (bus_uhs_support && !is_version_1) ? SD_OCR_S18R : 0;
arg |= (bus_uhs_support && !is_sdsc) ? SD_OCR_S18R : 0;
// This is needed for most cards. Do not set bit7 even if 1.8V is supported.
arg |= SD_OCR_VDD_32_33;
sdmmc_init_cmd(&cmdbuf, SD_APP_OP_COND, arg, SDMMC_RSP_TYPE_3, 0);
if (!_sd_storage_execute_app_cmd(storage, R1_SKIP_STATE_CHECK, is_version_1 ? R1_ILLEGAL_COMMAND : 0, &cmdbuf, NULL, NULL))
if (!_sd_storage_execute_app_cmd(storage, R1_SKIP_STATE_CHECK, is_sdsc ? R1_ILLEGAL_COMMAND : 0, &cmdbuf, NULL, NULL))
return 0;
return sdmmc_get_rsp(storage->sdmmc, cond, 4, SDMMC_RSP_TYPE_3);
}
static int _sd_storage_get_op_cond(sdmmc_storage_t *storage, int is_version_1, int bus_uhs_support)
static int _sd_storage_get_op_cond(sdmmc_storage_t *storage, bool is_sdsc, int bus_uhs_support)
{
u32 timeout = get_tmr_ms() + 1500;
while (1)
while (true)
{
u32 cond = 0;
if (!_sd_storage_get_op_cond_once(storage, &cond, is_version_1, bus_uhs_support))
if (!_sd_storage_get_op_cond_once(storage, &cond, is_sdsc, bus_uhs_support))
break;
if (cond & MMC_CARD_BUSY)
// Check if power up is done.
if (cond & SD_OCR_BUSY)
{
DPRINTF("[SD] op cond: %08X, lv: %d\n", cond, bus_uhs_support);
// Check if card is high capacity.
if (cond & SD_OCR_CCS)
storage->has_sector_access = 1;
// Check if card supports 1.8V signaling.
if (cond & SD_ROCR_S18A && bus_uhs_support)
{
//The low voltage regulator configuration is valid for SDMMC1 only.
if (storage->sdmmc->id == SDMMC_1 &&
_sdmmc_storage_execute_cmd_type1(storage, SD_SWITCH_VOLTAGE, 0, 0, R1_STATE_READY))
// Switch to 1.8V signaling.
if (_sdmmc_storage_execute_cmd_type1(storage, SD_SWITCH_VOLTAGE, 0, 0, R1_STATE_READY))
{
if (!sdmmc_enable_low_voltage(storage->sdmmc))
return 0;
@@ -776,7 +792,7 @@ static int _sd_storage_get_rca(sdmmc_storage_t *storage)
u32 timeout = get_tmr_ms() + 1500;
while (1)
while (true)
{
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, NULL, NULL))
break;
@@ -809,8 +825,9 @@ static void _sd_storage_parse_scr(sdmmc_storage_t *storage)
storage->scr.sda_vsn = unstuff_bits(resp, 56, 4);
storage->scr.bus_widths = unstuff_bits(resp, 48, 4);
/* If v2.0 is supported, check if Physical Layer Spec v3.0 is supported */
if (storage->scr.sda_vsn == SCR_SPEC_VER_2)
/* Check if Physical Layer Spec v3.0 is supported */
storage->scr.sda_spec3 = unstuff_bits(resp, 47, 1);
if (storage->scr.sda_spec3)
storage->scr.cmds = unstuff_bits(resp, 32, 2);
@@ -827,7 +844,7 @@ int _sd_storage_get_scr(sdmmc_storage_t *storage, u8 *buf)
reqbuf.num_sectors = 1;
reqbuf.is_write = 0;
reqbuf.is_multi_block = 0;
reqbuf.is_auto_cmd12 = 0;
reqbuf.is_auto_stop_trn = 0;
if (!_sd_storage_execute_app_cmd(storage, R1_STATE_TRAN, 0, &cmdbuf, &reqbuf, NULL))
return 0;
@@ -859,7 +876,7 @@ int _sd_storage_switch_get(sdmmc_storage_t *storage, void *buf)
reqbuf.num_sectors = 1;
reqbuf.is_write = 0;
reqbuf.is_multi_block = 0;
reqbuf.is_auto_cmd12 = 0;
reqbuf.is_auto_stop_trn = 0;
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, &reqbuf, NULL))
return 0;
@@ -883,7 +900,7 @@ int _sd_storage_switch(sdmmc_storage_t *storage, void *buf, int mode, int group,
reqbuf.num_sectors = 1;
reqbuf.is_write = 0;
reqbuf.is_multi_block = 0;
reqbuf.is_auto_cmd12 = 0;
reqbuf.is_auto_stop_trn = 0;
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, &reqbuf, NULL))
return 0;
@@ -1064,7 +1081,7 @@ int _sd_storage_enable_hs_high_volt(sdmmc_storage_t *storage, u8 *buf)
return sdmmc_setup_clock(storage->sdmmc, SDHCI_TIMING_SD_HS25);
}
u32 sd_storage_ssr_get_au(sdmmc_storage_t *storage)
u32 sd_storage_get_ssr_au(sdmmc_storage_t *storage)
{
u32 au_size = storage->ssr.uhs_au_size;
@@ -1104,39 +1121,24 @@ u32 sd_storage_ssr_get_au(sdmmc_storage_t *storage)
static void _sd_storage_parse_ssr(sdmmc_storage_t *storage)
{
// unstuff_bits supports only 4 u32 so break into 2 x 16byte groups
// unstuff_bits supports only 4 u32 so break into 2 x u32x4 groups.
u32 raw_ssr1[4];
u32 raw_ssr2[4];
raw_ssr1[3] = *(u32 *)&storage->raw_ssr[12];
raw_ssr1[2] = *(u32 *)&storage->raw_ssr[8];
raw_ssr1[1] = *(u32 *)&storage->raw_ssr[4];
raw_ssr1[0] = *(u32 *)&storage->raw_ssr[0];
raw_ssr2[3] = *(u32 *)&storage->raw_ssr[28];
raw_ssr2[2] = *(u32 *)&storage->raw_ssr[24];
raw_ssr2[1] = *(u32 *)&storage->raw_ssr[20];
raw_ssr2[0] = *(u32 *)&storage->raw_ssr[16];
memcpy(raw_ssr1, &storage->raw_ssr[0], 16);
memcpy(raw_ssr2, &storage->raw_ssr[16], 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))
u32 speed_class = unstuff_bits(raw_ssr1, 440 - 384, 8);
switch(speed_class)
{
case 0:
storage->ssr.speed_class = 0;
break;
case 1:
storage->ssr.speed_class = 2;
break;
case 2:
storage->ssr.speed_class = 4;
break;
case 3:
storage->ssr.speed_class = 6;
storage->ssr.speed_class = speed_class << 1;
break;
case 4:
@@ -1144,19 +1146,18 @@ static void _sd_storage_parse_ssr(sdmmc_storage_t *storage)
break;
default:
storage->ssr.speed_class = unstuff_bits(raw_ssr1, 440 - 384, 8);
storage->ssr.speed_class = speed_class;
break;
}
storage->ssr.uhs_grade = unstuff_bits(raw_ssr1, 396 - 384, 4);
storage->ssr.uhs_grade = unstuff_bits(raw_ssr1, 396 - 384, 4);
storage->ssr.video_class = unstuff_bits(raw_ssr1, 384 - 384, 8);
storage->ssr.app_class = unstuff_bits(raw_ssr2, 336 - 256, 4);
storage->ssr.app_class = unstuff_bits(raw_ssr2, 336 - 256, 4);
storage->ssr.au_size = unstuff_bits(raw_ssr1, 428 - 384, 4);
storage->ssr.au_size = unstuff_bits(raw_ssr1, 428 - 384, 4);
storage->ssr.uhs_au_size = unstuff_bits(raw_ssr1, 392 - 384, 4);
}
static int _sd_storage_get_ssr(sdmmc_storage_t *storage, u8 *buf)
int sd_storage_get_ssr(sdmmc_storage_t *storage, u8 *buf)
{
sdmmc_cmd_t cmdbuf;
sdmmc_init_cmd(&cmdbuf, SD_APP_SD_STATUS, 0, SDMMC_RSP_TYPE_1, 0);
@@ -1167,11 +1168,11 @@ static int _sd_storage_get_ssr(sdmmc_storage_t *storage, u8 *buf)
reqbuf.num_sectors = 1;
reqbuf.is_write = 0;
reqbuf.is_multi_block = 0;
reqbuf.is_auto_cmd12 = 0;
reqbuf.is_auto_stop_trn = 0;
if (!(storage->csd.cmdclass & CCC_APP_SPEC))
{
DPRINTF("[SD] ssr: Card lacks mandatory SD Status function\n");
DPRINTF("[SD] ssr: Not supported\n");
return 0;
}
@@ -1180,14 +1181,16 @@ DPRINTF("[SD] ssr: Card lacks mandatory SD Status function\n");
u32 tmp = 0;
sdmmc_get_rsp(storage->sdmmc, &tmp, 4, SDMMC_RSP_TYPE_1);
//Prepare buffer for unstuff_bits
for (int i = 0; i < 64; i+=4)
// Convert buffer to LE.
for (int i = 0; i < 64; i += 4)
{
storage->raw_ssr[i + 3] = buf[i];
storage->raw_ssr[i + 2] = buf[i + 1];
storage->raw_ssr[i + 1] = buf[i + 2];
storage->raw_ssr[i] = buf[i + 3];
}
_sd_storage_parse_ssr(storage);
//gfx_hexdump(0, storage->raw_ssr, 64);
@@ -1198,18 +1201,18 @@ static void _sd_storage_parse_cid(sdmmc_storage_t *storage)
{
u32 *raw_cid = (u32 *)&(storage->raw_cid);
storage->cid.manfid = unstuff_bits(raw_cid, 120, 8);
storage->cid.oemid = unstuff_bits(raw_cid, 104, 16);
storage->cid.prod_name[0] = unstuff_bits(raw_cid, 96, 8);
storage->cid.prod_name[1] = unstuff_bits(raw_cid, 88, 8);
storage->cid.prod_name[2] = unstuff_bits(raw_cid, 80, 8);
storage->cid.prod_name[3] = unstuff_bits(raw_cid, 72, 8);
storage->cid.prod_name[4] = unstuff_bits(raw_cid, 64, 8);
storage->cid.hwrev = unstuff_bits(raw_cid, 60, 4);
storage->cid.fwrev = unstuff_bits(raw_cid, 56, 4);
storage->cid.serial = unstuff_bits(raw_cid, 24, 32);
storage->cid.month = unstuff_bits(raw_cid, 8, 4);
storage->cid.year = unstuff_bits(raw_cid, 12, 8) + 2000;
storage->cid.manfid = unstuff_bits(raw_cid, 120, 8);
storage->cid.oemid = unstuff_bits(raw_cid, 104, 16);
storage->cid.prod_name[0] = unstuff_bits(raw_cid, 96, 8);
storage->cid.prod_name[1] = unstuff_bits(raw_cid, 88, 8);
storage->cid.prod_name[2] = unstuff_bits(raw_cid, 80, 8);
storage->cid.prod_name[3] = unstuff_bits(raw_cid, 72, 8);
storage->cid.prod_name[4] = unstuff_bits(raw_cid, 64, 8);
storage->cid.hwrev = unstuff_bits(raw_cid, 60, 4);
storage->cid.fwrev = unstuff_bits(raw_cid, 56, 4);
storage->cid.serial = unstuff_bits(raw_cid, 24, 32);
storage->cid.year = unstuff_bits(raw_cid, 12, 8) + 2000;
storage->cid.month = unstuff_bits(raw_cid, 8, 4);
}
static void _sd_storage_parse_csd(sdmmc_storage_t *storage)
@@ -1224,6 +1227,7 @@ static void _sd_storage_parse_csd(sdmmc_storage_t *storage)
{
case 0:
storage->csd.capacity = (1 + unstuff_bits(raw_csd, 62, 12)) << (unstuff_bits(raw_csd, 47, 3) + 2);
storage->csd.capacity <<= unstuff_bits(raw_csd, 80, 4) - 9; // Convert native block size to LBA 512B.
break;
case 1:
@@ -1231,7 +1235,13 @@ static void _sd_storage_parse_csd(sdmmc_storage_t *storage)
storage->csd.capacity = storage->csd.c_size << 10;
storage->csd.read_blkbits = 9;
break;
default:
DPRINTF("[SD] unknown CSD structure %d\n", storage->csd.structure);
break;
}
storage->sec_cnt = storage->csd.capacity;
}
static bool _sdmmc_storage_get_bus_uhs_support(u32 bus_width, u32 type)
@@ -1261,8 +1271,10 @@ void sdmmc_storage_init_wait_sd()
int sdmmc_storage_init_sd(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 bus_width, u32 type)
{
int is_version_1 = 0;
u8 *buf = (u8 *)SDMMC_UPPER_BUFFER;
u32 tmp = 0;
int is_sdsc = 0;
u8 *buf = (u8 *)SDMMC_UPPER_BUFFER;
bool bus_uhs_support = _sdmmc_storage_get_bus_uhs_support(bus_width, type);
DPRINTF("[SD] init: bus: %d, type: %d\n", bus_width, type);
@@ -1282,18 +1294,15 @@ DPRINTF("[SD] after init\n");
return 0;
DPRINTF("[SD] went to idle state\n");
is_version_1 = _sd_storage_send_if_cond(storage);
if (is_version_1 == 2) // Failed.
if (!_sd_storage_send_if_cond(storage, &is_sdsc))
return 0;
DPRINTF("[SD] after send if cond\n");
bool bus_uhs_support = _sdmmc_storage_get_bus_uhs_support(bus_width, type);
if (!_sd_storage_get_op_cond(storage, is_version_1, bus_uhs_support))
if (!_sd_storage_get_op_cond(storage, is_sdsc, bus_uhs_support))
return 0;
DPRINTF("[SD] got op cond\n");
if (!_sdmmc_storage_get_cid(storage, storage->raw_cid))
if (!_sdmmc_storage_get_cid(storage))
return 0;
DPRINTF("[SD] got cid\n");
_sd_storage_parse_cid(storage);
@@ -1302,30 +1311,16 @@ DPRINTF("[SD] got cid\n");
return 0;
DPRINTF("[SD] got rca (= %04X)\n", storage->rca);
if (!_sdmmc_storage_get_csd(storage, storage->raw_csd))
if (!_sdmmc_storage_get_csd(storage))
return 0;
DPRINTF("[SD] got csd\n");
//Parse CSD.
_sd_storage_parse_csd(storage);
switch (storage->csd.structure)
{
case 0:
storage->sec_cnt = storage->csd.capacity;
break;
case 1:
storage->sec_cnt = storage->csd.c_size << 10;
break;
default:
DPRINTF("[SD] unknown CSD structure %d\n", storage->csd.structure);
break;
}
if (!storage->is_low_voltage)
{
if (!sdmmc_setup_clock(storage->sdmmc, SDHCI_TIMING_SD_DS12))
return 0;
DPRINTF("[SD] after setup clock\n");
DPRINTF("[SD] after setup default clock\n");
}
if (!_sdmmc_storage_select_card(storage))
@@ -1336,19 +1331,17 @@ DPRINTF("[SD] card selected\n");
return 0;
DPRINTF("[SD] set blocklen to 512\n");
u32 tmp = 0;
// Disconnect Card Detect resistor from DAT3.
if (!_sd_storage_execute_app_cmd_type1(storage, &tmp, SD_APP_SET_CLR_CARD_DETECT, 0, 0, R1_STATE_TRAN))
return 0;
DPRINTF("[SD] cleared card detect\n");
if (!_sd_storage_get_scr(storage, buf))
return 0;
//gfx_hexdump(0, storage->raw_scr, 8);
DPRINTF("[SD] got scr\n");
// Check if card supports a wider bus and if it's not SD Version 1.X
if (bus_width == SDMMC_BUS_WIDTH_4 && (storage->scr.bus_widths & 4) && (storage->scr.sda_vsn & 0xF))
// If card supports a wider bus and if it's not SD Version 1.0 switch bus width.
if (bus_width == SDMMC_BUS_WIDTH_4 && (storage->scr.bus_widths & BIT(SD_BUS_WIDTH_4)) && storage->scr.sda_vsn)
{
if (!_sd_storage_execute_app_cmd_type1(storage, &tmp, SD_APP_SET_BUS_WIDTH, SD_BUS_WIDTH_4, 0, R1_STATE_TRAN))
return 0;
@@ -1370,7 +1363,7 @@ DPRINTF("[SD] enabled UHS\n");
sdmmc_card_clock_powersave(sdmmc, SDMMC_POWER_SAVE_ENABLE);
}
else if (type != SDHCI_TIMING_SD_DS12 && (storage->scr.sda_vsn & 0xF)) // Not default speed and not SD Version 1.x
else if (type != SDHCI_TIMING_SD_DS12 && storage->scr.sda_vsn) // Not default speed and not SD Version 1.0.
{
if (!_sd_storage_enable_hs_high_volt(storage, buf))
return 0;
@@ -1389,7 +1382,7 @@ DPRINTF("[SD] enabled HS\n");
}
// Parse additional card info from sd status.
if (_sd_storage_get_ssr(storage, buf))
if (sd_storage_get_ssr(storage, buf))
{
DPRINTF("[SD] got sd status\n");
}
@@ -1400,14 +1393,14 @@ DPRINTF("[SD] got sd status\n");
}
/*
* Gamecard specific functions.
*/
* Gamecard specific functions.
*/
int _gc_storage_custom_cmd(sdmmc_storage_t *storage, void *buf)
{
u32 resp;
sdmmc_cmd_t cmdbuf;
sdmmc_init_cmd(&cmdbuf, 60, 0, SDMMC_RSP_TYPE_1, 1);
sdmmc_init_cmd(&cmdbuf, MMC_VENDOR_60_CMD, 0, SDMMC_RSP_TYPE_1, 1);
sdmmc_req_t reqbuf;
reqbuf.buf = buf;
@@ -1415,7 +1408,7 @@ int _gc_storage_custom_cmd(sdmmc_storage_t *storage, void *buf)
reqbuf.num_sectors = 1;
reqbuf.is_write = 1;
reqbuf.is_multi_block = 0;
reqbuf.is_auto_cmd12 = 0;
reqbuf.is_auto_stop_trn = 0;
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, &reqbuf, NULL))
{

View File

@@ -1,6 +1,6 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2020 CTCaer
* Copyright (c) 2018-2021 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
@@ -30,18 +30,18 @@ typedef enum _sdmmc_type
EMMC_GPP = 0,
EMMC_BOOT0 = 1,
EMMC_BOOT1 = 2
EMMC_BOOT1 = 2,
EMMC_RPMB = 3
} sdmmc_type;
typedef struct _mmc_cid
{
u32 manfid;
u8 prod_name[8];
u8 card_bga;
u8 prv;
u32 serial;
u16 oemid;
u16 year;
u8 prv;
u8 hwrev;
u8 fwrev;
u8 month;
@@ -65,19 +65,20 @@ typedef struct _mmc_csd
typedef struct _mmc_ext_csd
{
u32 sectors;
int bkops; /* background support bit */
int bkops_en; /* manual bkops enable bit */
//u8 bkops; /* background support bit */
//u8 bkops_en; /* manual bkops enable bit */
//u8 bkops_status; /* 246 */
u8 rev;
u8 ext_struct; /* 194 */
u8 card_type; /* 196 */
u8 bkops_status; /* 246 */
u8 pre_eol_info;
u8 dev_life_est_a;
u8 dev_life_est_b;
u8 boot_mult;
u8 rpmb_mult;
u16 dev_version;
u32 cache_size;
u32 max_enh_mult;
} mmc_ext_csd_t;
typedef struct _sd_scr
@@ -90,13 +91,13 @@ typedef struct _sd_scr
typedef struct _sd_ssr
{
u8 bus_width;
u8 speed_class;
u8 uhs_grade;
u8 video_class;
u8 app_class;
u8 au_size;
u8 uhs_au_size;
u8 bus_width;
u8 speed_class;
u8 uhs_grade;
u8 video_class;
u8 app_class;
u8 au_size;
u8 uhs_au_size;
u32 protected_size;
} sd_ssr_t;
@@ -130,6 +131,7 @@ void sdmmc_storage_init_wait_sd();
int sdmmc_storage_init_sd(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 bus_width, u32 type);
int sdmmc_storage_init_gc(sdmmc_storage_t *storage, sdmmc_t *sdmmc);
u32 sd_storage_ssr_get_au(sdmmc_storage_t *storage);
int sd_storage_get_ssr(sdmmc_storage_t *storage, u8 *buf);
u32 sd_storage_get_ssr_au(sdmmc_storage_t *storage);
#endif

View File

@@ -1,6 +1,6 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2020 CTCaer
* Copyright (c) 2018-2021 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
@@ -934,12 +934,20 @@ static int _sdmmc_config_dma(sdmmc_t *sdmmc, u32 *blkcnt_out, sdmmc_req_t *req)
*blkcnt_out = blkcnt;
u32 trnmode = SDHCI_TRNS_DMA;
// Set mulitblock request.
if (req->is_multi_block)
trnmode = SDHCI_TRNS_MULTI | SDHCI_TRNS_BLK_CNT_EN | SDHCI_TRNS_DMA;
// Set request direction.
if (!req->is_write)
trnmode |= SDHCI_TRNS_READ;
if (req->is_auto_cmd12)
trnmode = (trnmode & ~(SDHCI_TRNS_AUTO_CMD12 | SDHCI_TRNS_AUTO_CMD23)) | SDHCI_TRNS_AUTO_CMD12;
// Automatic send of stop transmission or set block count cmd.
if (req->is_auto_stop_trn)
trnmode |= SDHCI_TRNS_AUTO_CMD12;
//else if (req->is_auto_set_blkcnt)
// trnmode |= SDHCI_TRNS_AUTO_CMD23;
sdmmc->regs->trnmod = trnmode;
@@ -1070,7 +1078,7 @@ DPRINTF("rsp(%d): %08X, %08X, %08X, %08X\n", result,
if (blkcnt_out)
*blkcnt_out = blkcnt;
if (req->is_auto_cmd12)
if (req->is_auto_stop_trn)
sdmmc->rsp3 = sdmmc->regs->rspreg3;
}
@@ -1371,12 +1379,12 @@ void sdmmc_end(sdmmc_t *sdmmc)
_sdmmc_sd_clock_disable(sdmmc);
// Disable SDMMC power.
_sdmmc_set_io_power(sdmmc, SDMMC_POWER_OFF);
_sdmmc_commit_changes(sdmmc);
// Disable SD card power.
if (sdmmc->id == SDMMC_1)
sdmmc1_disable_power();
_sdmmc_commit_changes(sdmmc);
clock_sdmmc_disable(sdmmc->id);
sdmmc->clock_stopped = 1;
}

View File

@@ -242,7 +242,7 @@ typedef struct _sdmmc_req_t
u32 num_sectors;
int is_write;
int is_multi_block;
int is_auto_cmd12;
int is_auto_stop_trn;
} sdmmc_req_t;
int sdmmc_get_io_power(sdmmc_t *sdmmc);

View File

@@ -56,7 +56,7 @@ void set_fan_duty(u32 duty)
if (inv_duty == 236)
{
PWM(PWM_CONTROLLER_PWM_CSR_1) = PWM_CSR_EN | (0x100 << 16); // Bit 24 is absolute 0%.
regulator_disable_5v(REGULATOR_5V_FAN);
regulator_5v_disable(REGULATOR_5V_FAN);
// Disable fan.
PINMUX_AUX(PINMUX_AUX_LCD_GPIO2) =
@@ -65,7 +65,7 @@ void set_fan_duty(u32 duty)
else // Set PWM duty.
{
// Fan power supply.
regulator_enable_5v(REGULATOR_5V_FAN);
regulator_5v_enable(REGULATOR_5V_FAN);
PWM(PWM_CONTROLLER_PWM_CSR_1) = PWM_CSR_EN | (inv_duty << 16);
// Enable fan.

View File

@@ -1,7 +1,7 @@
/*
* SOC/PCB Temperature driver for Nintendo Switch's TI TMP451
*
* Copyright (c) 2018 CTCaer
* Copyright (c) 2018-2020 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
@@ -16,7 +16,9 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <soc/hw_init.h>
#include <soc/i2c.h>
#include <soc/t210.h>
#include <thermal/tmp451.h>
u16 tmp451_get_soc_temp(bool intenger)
@@ -56,6 +58,20 @@ void tmp451_init()
// Disable ALARM and Range to 0 - 127 oC.
i2c_send_byte(I2C_1, TMP451_I2C_ADDR, TMP451_CONFIG_REG, 0x80);
// Set remote sensor offsets based on SoC.
if (hw_get_chip_id() == GP_HIDREV_MAJOR_T210)
{
// Set offset to 0 oC for Erista.
i2c_send_byte(I2C_1, TMP451_I2C_ADDR, TMP451_SOC_TMP_OFH_REG, 0);
i2c_send_byte(I2C_1, TMP451_I2C_ADDR, TMP451_SOC_TMP_OFL_REG, 0);
}
else
{
// Set offset to -12.5 oC for Mariko.
i2c_send_byte(I2C_1, TMP451_I2C_ADDR, TMP451_SOC_TMP_OFH_REG, 0xF3); // - 13 oC.
i2c_send_byte(I2C_1, TMP451_I2C_ADDR, TMP451_SOC_TMP_OFL_REG, 0x80); // + 0.5 oC.
}
// Set conversion rate to 32/s and make a read to update the reg.
i2c_send_byte(I2C_1, TMP451_I2C_ADDR, TMP451_CNV_RATE_REG, 9);
tmp451_get_soc_temp(false);
@@ -63,3 +79,9 @@ void tmp451_init()
// Set rate to every 4 seconds.
i2c_send_byte(I2C_1, TMP451_I2C_ADDR, TMP451_CNV_RATE_REG, 2);
}
void tmp451_end()
{
// Place into shutdown mode to conserve power.
i2c_send_byte(I2C_1, TMP451_I2C_ADDR, TMP451_CONFIG_REG, 0xC0);
}

View File

@@ -32,11 +32,15 @@
#define TMP451_SOC_TMP_DEC_REG 0x10
#define TMP451_PCB_TMP_DEC_REG 0x15
#define TMP451_SOC_TMP_OFH_REG 0x11
#define TMP451_SOC_TMP_OFL_REG 0x12
// If input is false, the return value is packed. MSByte is the integer in oC
// and the LSByte is the decimal point truncated to 2 decimal places.
// Otherwise it's an integer oC.
u16 tmp451_get_soc_temp(bool integer);
u16 tmp451_get_pcb_temp(bool integer);
void tmp451_init();
void tmp451_end();
#endif /* __TMP451_H_ */

View File

@@ -29,7 +29,7 @@ u8 btn_read()
res |= BTN_VOL_DOWN;
if (!gpio_read(GPIO_PORT_X, GPIO_PIN_6))
res |= BTN_VOL_UP;
if (i2c_recv_byte(4, MAX77620_I2C_ADDR, MAX77620_REG_ONOFFSTAT) & MAX77620_ONOFFSTAT_EN0)
if (i2c_recv_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_ONOFFSTAT) & MAX77620_ONOFFSTAT_EN0)
res |= BTN_POWER;
return res;
}

View File

@@ -1,6 +1,6 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2020 CTCaer
* Copyright (c) 2018-2021 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
@@ -75,10 +75,9 @@ typedef int bool;
#define EXTRA_CFG_PAYLOAD BIT(1)
#define EXTRA_CFG_MODULE BIT(2)
#define EXTRA_CFG_NYX_BIS BIT(4)
#define EXTRA_CFG_NYX_UMS BIT(5)
#define EXTRA_CFG_NYX_RELOAD BIT(6)
#define EXTRA_CFG_NYX_DUMP BIT(7)
#define EXTRA_CFG_NYX_SEPT BIT(7)
typedef enum _nyx_ums_type
{
@@ -91,6 +90,13 @@ typedef enum _nyx_ums_type
NYX_UMS_EMUMMC_GPP
} nyx_ums_type;
typedef enum _nyx_sept_type
{
NYX_SEPT_DUMP = 0,
NYX_SEPT_CAL0,
NYX_SEPT_EMUF
} nyx_sept_type;
typedef struct __attribute__((__packed__)) _boot_cfg_t
{
u8 boot_cfg;
@@ -104,7 +110,8 @@ typedef struct __attribute__((__packed__)) _boot_cfg_t
char id[8]; // 7 char ASCII null teminated.
char emummc_path[0x78]; // emuMMC/XXX, ASCII null teminated.
};
u8 ums; // nyx_ums_type.
u8 ums; // nyx_ums_type.
u8 sept; // nyx_sept_type.
u8 xt_str[0x80];
};
} boot_cfg_t;

View File

@@ -167,10 +167,10 @@ void power_set_state(power_state_t state)
default:
// Enable/Disable soft reset wake event.
reg = i2c_recv_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_ONOFFCNFG2);
if (state == POWER_OFF_RESET)
reg &= ~MAX77620_ONOFFCNFG2_SFT_RST_WK; // Do not wake up after power off.
else // POWER_OFF_REBOOT.
reg |= MAX77620_ONOFFCNFG2_SFT_RST_WK; // Wake up after power off.
if (state == POWER_OFF_RESET) // Do not wake up after power off.
reg &= ~(MAX77620_ONOFFCNFG2_SFT_RST_WK | MAX77620_ONOFFCNFG2_WK_ALARM1 | MAX77620_ONOFFCNFG2_WK_ALARM2);
else // POWER_OFF_REBOOT. Wake up after power off.
reg |= MAX77620_ONOFFCNFG2_SFT_RST_WK;
i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_ONOFFCNFG2, reg);
// Initiate power down sequence and generate a reset (regulators' state resets).

View File

@@ -1,6 +1,6 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2020 CTCaer
* Copyright (c) 2018-2021 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
@@ -35,9 +35,10 @@ typedef enum
typedef enum
{
NYX_CFG_BIS = BIT(5),
NYX_CFG_UMS = BIT(6),
NYX_CFG_DUMP = BIT(7),
NYX_CFG_SEPT = BIT(7),
NYX_CFG_EXTRA = 0xFF << 24
} nyx_cfg_t;
typedef enum
@@ -53,6 +54,8 @@ typedef enum
#define byte_swap_32(num) ((((num) >> 24) & 0xff) | (((num) << 8) & 0xff0000) | \
(((num) >> 8 )& 0xff00) | (((num) << 24) & 0xff000000))
#define byte_swap_16(num) ((((num) >> 8) & 0xff) | (((num) << 8) & 0xff00))
typedef struct _cfg_op_t
{
u32 off;

View File

@@ -1,7 +1,7 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018 Rajko Stojadinovic
* Copyright (c) 2018-2019 CTCaer
* Copyright (c) 2018-2021 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
@@ -27,6 +27,7 @@
#include <libs/fatfs/ff.h>
#include <mem/heap.h>
#include <sec/se.h>
#include <sec/se_t210.h>
#include "../storage/nx_emmc.h"
#include <storage/nx_sd.h>
#include <storage/sdmmc.h>
@@ -96,7 +97,7 @@ static int _dump_emmc_verify(sdmmc_storage_t *storage, u32 lba_curr, char *outFi
se_calc_sha256_oneshot(hashEm, bufEm, num << 9);
se_calc_sha256_oneshot(hashSd, bufSd, num << 9);
res = memcmp(hashEm, hashSd, 0x10);
res = memcmp(hashEm, hashSd, SE_SHA_256_SIZE / 2);
if (res)
{
@@ -735,7 +736,7 @@ static int _restore_emmc_part(char *sd_path, sdmmc_storage_t *storage, emmc_part
{
gfx_con.fntsz = 16;
EPRINTFARGS("\nFatal error (%d) when reading from SD Card", res);
EPRINTF("\nYour device may be in an inoperative state!\n\nPress any key and try again now...\n");
EPRINTF("\nThis device may be in an inoperative state!\n\nPress any key and try again now...\n");
f_close(&fp);
return 0;
@@ -751,7 +752,7 @@ static int _restore_emmc_part(char *sd_path, sdmmc_storage_t *storage, emmc_part
gfx_con.fntsz = 16;
EPRINTFARGS("\nFailed to write %d blocks @ LBA %08X\nfrom eMMC. Aborting..\n",
num, lba_curr);
EPRINTF("\nYour device may be in an inoperative state!\n\nPress any key and try again...\n");
EPRINTF("\nThis device may be in an inoperative state!\n\nPress any key and try again...\n");
f_close(&fp);
return 0;
@@ -797,7 +798,7 @@ static void _restore_emmc_selected(emmcPartType_t restoreType)
tui_sbar(true);
gfx_con_setpos(0, 0);
gfx_printf("%kThis may render your device inoperative!\n\n", 0xFFFFDD00);
gfx_printf("%kThis may render the device inoperative!\n\n", 0xFFFFDD00);
gfx_printf("Are you really sure?\n\n%k", 0xFFCCCCCC);
if ((restoreType & PART_BOOT) || (restoreType & PART_GP_ALL))
{

View File

@@ -1,6 +1,6 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2020 CTCaer
* Copyright (c) 2018-2021 CTCaer
* Copyright (c) 2018 balika011
*
* This program is free software; you can redistribute it and/or modify it
@@ -27,6 +27,7 @@
#include <mem/smmu.h>
#include <power/bq24193.h>
#include <power/max17050.h>
#include <sec/se_t210.h>
#include <sec/tsec.h>
#include <soc/fuse.h>
#include <soc/i2c.h>
@@ -130,10 +131,7 @@ void print_mmc_info()
static const u32 SECTORS_TO_MIB_COEFF = 11;
sdmmc_storage_t storage;
sdmmc_t sdmmc;
if (!sdmmc_storage_init_mmc(&storage, &sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400))
if (!sdmmc_storage_init_mmc(&emmc_storage, &emmc_sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400))
{
EPRINTF("Failed to init eMMC.");
goto out;
@@ -144,35 +142,34 @@ void print_mmc_info()
u32 speed = 0;
gfx_printf("%kCID:%k\n", 0xFF00DDFF, 0xFFCCCCCC);
switch (storage.csd.mmca_vsn)
switch (emmc_storage.csd.mmca_vsn)
{
case 2: /* MMC v2.0 - v2.2 */
case 3: /* MMC v3.1 - v3.3 */
case 4: /* MMC v4 */
gfx_printf(
" Vendor ID: %X\n"
" Card/BGA: %X\n"
" OEM ID: %02X\n"
" Model: %c%c%c%c%c%c\n"
" Prd Rev: %X\n"
" S/N: %04X\n"
" Month/Year: %02d/%04d\n\n",
storage.cid.manfid, storage.cid.card_bga, storage.cid.oemid,
storage.cid.prod_name[0], storage.cid.prod_name[1], storage.cid.prod_name[2],
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);
emmc_storage.cid.manfid, emmc_storage.cid.oemid,
emmc_storage.cid.prod_name[0], emmc_storage.cid.prod_name[1], emmc_storage.cid.prod_name[2],
emmc_storage.cid.prod_name[3], emmc_storage.cid.prod_name[4], emmc_storage.cid.prod_name[5],
emmc_storage.cid.prv, emmc_storage.cid.serial, emmc_storage.cid.month, emmc_storage.cid.year);
break;
default:
break;
}
if (storage.csd.structure == 0)
if (emmc_storage.csd.structure == 0)
EPRINTF("Unknown CSD structure.");
else
{
gfx_printf("%kExtended CSD V1.%d:%k\n",
0xFF00DDFF, storage.ext_csd.ext_struct, 0xFFCCCCCC);
card_type = storage.ext_csd.card_type;
0xFF00DDFF, emmc_storage.ext_csd.ext_struct, 0xFFCCCCCC);
card_type = emmc_storage.ext_csd.card_type;
char card_type_support[96];
card_type_support[0] = 0;
if (card_type & EXT_CSD_CARD_TYPE_HS_26)
@@ -210,16 +207,16 @@ void print_mmc_info()
" Max Rate: %d MB/s (%d MHz)\n"
" Current Rate: %d MB/s\n"
" Type Support: ",
storage.csd.mmca_vsn, storage.ext_csd.rev, storage.ext_csd.dev_version, storage.csd.cmdclass,
storage.csd.capacity == (4096 * 512) ? "High" : "Low", speed & 0xFFFF, (speed >> 16) & 0xFFFF,
storage.csd.busspeed);
emmc_storage.csd.mmca_vsn, emmc_storage.ext_csd.rev, emmc_storage.ext_csd.dev_version, emmc_storage.csd.cmdclass,
emmc_storage.csd.capacity == (4096 * 512) ? "High" : "Low", speed & 0xFFFF, (speed >> 16) & 0xFFFF,
emmc_storage.csd.busspeed);
gfx_con.fntsz = 8;
gfx_printf("%s", card_type_support);
gfx_con.fntsz = 16;
gfx_printf("\n\n", card_type_support);
u32 boot_size = storage.ext_csd.boot_mult << 17;
u32 rpmb_size = storage.ext_csd.rpmb_mult << 17;
u32 boot_size = emmc_storage.ext_csd.boot_mult << 17;
u32 rpmb_size = emmc_storage.ext_csd.rpmb_mult << 17;
gfx_printf("%keMMC Partitions:%k\n", 0xFF00DDFF, 0xFFCCCCCC);
gfx_printf(" 1: %kBOOT0 %k\n Size: %5d KiB (LBA Sectors: 0x%07X)\n", 0xFF96FF00, 0xFFCCCCCC,
boot_size / 1024, boot_size / 512);
@@ -231,13 +228,13 @@ void print_mmc_info()
rpmb_size / 1024, rpmb_size / 512);
gfx_put_small_sep();
gfx_printf(" 0: %kGPP (USER) %k\n Size: %5d MiB (LBA Sectors: 0x%07X)\n\n", 0xFF96FF00, 0xFFCCCCCC,
storage.sec_cnt >> SECTORS_TO_MIB_COEFF, storage.sec_cnt);
emmc_storage.sec_cnt >> SECTORS_TO_MIB_COEFF, emmc_storage.sec_cnt);
gfx_put_small_sep();
gfx_printf("%kGPP (eMMC USER) partition table:%k\n", 0xFF00DDFF, 0xFFCCCCCC);
sdmmc_storage_set_mmc_partition(&storage, EMMC_GPP);
sdmmc_storage_set_mmc_partition(&emmc_storage, EMMC_GPP);
LIST_INIT(gpt);
nx_emmc_gpt_parse(&gpt, &storage);
nx_emmc_gpt_parse(&gpt, &emmc_storage);
int gpp_idx = 0;
LIST_FOREACH_ENTRY(emmc_part_t, part, &gpt, link)
{
@@ -251,7 +248,7 @@ void print_mmc_info()
}
out:
sdmmc_storage_end(&storage);
sdmmc_storage_end(&emmc_storage);
btn_wait();
}
@@ -263,7 +260,7 @@ void print_sdcard_info()
gfx_clear_partial_grey(0x1B, 0, 1256);
gfx_con_setpos(0, 0);
if (sd_initialize(true))
if (sd_initialize(false))
{
gfx_printf("%kCard IDentification:%k\n", 0xFF00DDFF, 0xFFCCCCCC);
gfx_printf(
@@ -337,16 +334,14 @@ void print_tsec_key()
u32 retries = 0;
tsec_ctxt_t tsec_ctxt;
sdmmc_storage_t storage;
sdmmc_t sdmmc;
sdmmc_storage_init_mmc(&storage, &sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400);
sdmmc_storage_init_mmc(&emmc_storage, &emmc_sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400);
// Read package1.
u8 *pkg1 = (u8 *)malloc(0x40000);
sdmmc_storage_set_mmc_partition(&storage, EMMC_BOOT0);
sdmmc_storage_read(&storage, 0x100000 / NX_EMMC_BLOCKSIZE, 0x40000 / NX_EMMC_BLOCKSIZE, pkg1);
sdmmc_storage_end(&storage);
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);
if (!pkg1_id)
{
@@ -354,7 +349,7 @@ void print_tsec_key()
goto out_wait;
}
u8 keys[0x10 * 2];
u8 keys[SE_KEY_128_SIZE * 2];
memset(keys, 0x00, 0x20);
tsec_ctxt.fw = (u8 *)pkg1 + pkg1_id->tsec_off;
@@ -401,14 +396,14 @@ void print_tsec_key()
if (res >= 0)
{
for (u32 j = 0; j < 0x10; j++)
for (u32 j = 0; j < SE_KEY_128_SIZE; j++)
gfx_printf("%02X", keys[j]);
if (pkg1_id->kb == KB_FIRMWARE_VERSION_620)
{
gfx_printf("\n%kTSEC root: %k", 0xFF00DDFF, 0xFFCCCCCC);
for (u32 j = 0; j < 0x10; j++)
gfx_printf("%02X", keys[0x10 + j]);
for (u32 j = 0; j < SE_KEY_128_SIZE; j++)
gfx_printf("%02X", keys[SE_KEY_128_SIZE + j]);
}
}
else
@@ -423,7 +418,7 @@ void print_tsec_key()
{
char path[64];
emmcsn_path_impl(path, "/dumps", "tsec_keys.bin", NULL);
if (!sd_save_to_file(keys, 0x10 * 2, path))
if (!sd_save_to_file(keys, SE_KEY_128_SIZE * 2, path))
gfx_puts("\nDone!\n");
sd_end();
}

View File

@@ -1,6 +1,6 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2019 CTCaer
* Copyright (c) 2018-2021 CTCaer
* Copyright (c) 2018 Reisyukaku
*
* This program is free software; you can redistribute it and/or modify it
@@ -31,6 +31,7 @@
#include <mem/heap.h>
#include <power/max7762x.h>
#include <sec/se.h>
#include <sec/se_t210.h>
#include "../storage/nx_emmc.h"
#include <storage/nx_sd.h>
#include <storage/sdmmc.h>
@@ -65,23 +66,21 @@ void dump_packages12()
gfx_clear_partial_grey(0x1B, 0, 1256);
gfx_con_setpos(0, 0);
sdmmc_storage_t storage;
sdmmc_t sdmmc;
if (!sdmmc_storage_init_mmc(&storage, &sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400))
if (!sdmmc_storage_init_mmc(&emmc_storage, &emmc_sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400))
{
EPRINTF("Failed to init eMMC.");
goto out_free;
}
sdmmc_storage_set_mmc_partition(&storage, EMMC_BOOT0);
sdmmc_storage_set_mmc_partition(&emmc_storage, EMMC_BOOT0);
// Read package1.
sdmmc_storage_read(&storage, 0x100000 / NX_EMMC_BLOCKSIZE, 0x40000 / NX_EMMC_BLOCKSIZE, pkg1);
sdmmc_storage_read(&emmc_storage, 0x100000 / NX_EMMC_BLOCKSIZE, 0x40000 / NX_EMMC_BLOCKSIZE, pkg1);
const pkg1_id_t *pkg1_id = pkg1_identify(pkg1);
if (!pkg1_id)
{
EPRINTF("Unknown pkg1 version for reading\nTSEC firmware.");
// Dump package1.
emmcsn_path_impl(path, "/pkg1", "pkg1_enc.bin", &storage);
emmcsn_path_impl(path, "/pkg1", "pkg1_enc.bin", &emmc_storage);
if (sd_save_to_file(pkg1, 0x40000, path))
goto out_free;
gfx_puts("\nEnc pkg1 dumped to pkg1_enc.bin\n");
@@ -115,7 +114,7 @@ void dump_packages12()
// Read keyblob.
u8 *keyblob = (u8 *)calloc(NX_EMMC_BLOCKSIZE, 1);
sdmmc_storage_read(&storage, 0x180000 / NX_EMMC_BLOCKSIZE + kb, 1, keyblob);
sdmmc_storage_read(&emmc_storage, 0x180000 / NX_EMMC_BLOCKSIZE + kb, 1, keyblob);
// Decrypt.
hos_keygen(keyblob, kb, &tsec_ctxt, NULL);
@@ -155,35 +154,35 @@ void dump_packages12()
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);
emmcsn_path_impl(path, "/pkg1", "pkg1_decr.bin", &emmc_storage);
if (sd_save_to_file(pkg1, 0x40000, path))
goto out_free;
gfx_puts("\npkg1 dumped to pkg1_decr.bin\n");
// Dump nxbootloader.
emmcsn_path_impl(path, "/pkg1", "nxloader.bin", &storage);
emmcsn_path_impl(path, "/pkg1", "nxloader.bin", &emmc_storage);
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);
emmcsn_path_impl(path, "/pkg1", "secmon.bin", &emmc_storage);
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);
emmcsn_path_impl(path, "/pkg1", "warmboot.bin", &emmc_storage);
if (sd_save_to_file(warmboot, hdr_pk11->wb_size, path))
goto out_free;
gfx_puts("Warmboot dumped to warmboot.bin\n\n\n");
}
// Dump package2.1.
sdmmc_storage_set_mmc_partition(&storage, EMMC_GPP);
sdmmc_storage_set_mmc_partition(&emmc_storage, EMMC_GPP);
// Parse eMMC GPT.
LIST_INIT(gpt);
nx_emmc_gpt_parse(&gpt, &storage);
nx_emmc_gpt_parse(&gpt, &emmc_storage);
// Find package2 partition.
emmc_part_t *pkg2_part = nx_emmc_part_find(&gpt, "BCPKG2-1-Normal-Main");
if (!pkg2_part)
@@ -191,14 +190,14 @@ void dump_packages12()
// Read in package2 header and get package2 real size.
u8 *tmp = (u8 *)malloc(NX_EMMC_BLOCKSIZE);
nx_emmc_part_read(&storage, pkg2_part, 0x4000 / NX_EMMC_BLOCKSIZE, 1, tmp);
nx_emmc_part_read(&emmc_storage, pkg2_part, 0x4000 / NX_EMMC_BLOCKSIZE, 1, tmp);
u32 *hdr_pkg2_raw = (u32 *)(tmp + 0x100);
u32 pkg2_size = hdr_pkg2_raw[0] ^ hdr_pkg2_raw[2] ^ hdr_pkg2_raw[3];
free(tmp);
// Read in package2.
u32 pkg2_size_aligned = ALIGN(pkg2_size, NX_EMMC_BLOCKSIZE);
pkg2 = malloc(pkg2_size_aligned);
nx_emmc_part_read(&storage, pkg2_part, 0x4000 / NX_EMMC_BLOCKSIZE,
nx_emmc_part_read(&emmc_storage, pkg2_part, 0x4000 / NX_EMMC_BLOCKSIZE,
pkg2_size_aligned / NX_EMMC_BLOCKSIZE, pkg2);
// Decrypt package2 and parse KIP1 blobs in INI1 section.
pkg2_hdr_t *pkg2_hdr = pkg2_decrypt(pkg2, kb);
@@ -213,19 +212,19 @@ void dump_packages12()
gfx_printf("%kINI1 size: %k0x%05X\n\n", 0xFFC7EA46, 0xFFCCCCCC, pkg2_hdr->sec_size[PKG2_SEC_INI1]);
// Dump pkg2.1.
emmcsn_path_impl(path, "/pkg2", "pkg2_decr.bin", &storage);
emmcsn_path_impl(path, "/pkg2", "pkg2_decr.bin", &emmc_storage);
if (sd_save_to_file(pkg2, pkg2_hdr->sec_size[PKG2_SEC_KERNEL] + pkg2_hdr->sec_size[PKG2_SEC_INI1], path))
goto out;
gfx_puts("\npkg2 dumped to pkg2_decr.bin\n");
// Dump kernel.
emmcsn_path_impl(path, "/pkg2", "kernel.bin", &storage);
emmcsn_path_impl(path, "/pkg2", "kernel.bin", &emmc_storage);
if (sd_save_to_file(pkg2_hdr->data, pkg2_hdr->sec_size[PKG2_SEC_KERNEL], path))
goto out;
gfx_puts("Kernel dumped to kernel.bin\n");
// Dump INI1.
emmcsn_path_impl(path, "/pkg2", "ini1.bin", &storage);
emmcsn_path_impl(path, "/pkg2", "ini1.bin", &emmc_storage);
u32 ini1_off = pkg2_hdr->sec_size[PKG2_SEC_KERNEL];
u32 ini1_size = pkg2_hdr->sec_size[PKG2_SEC_INI1];
if (!ini1_size)
@@ -256,7 +255,7 @@ out_free:
free(warmboot);
free(loader);
free(pkg2);
sdmmc_storage_end(&storage);
sdmmc_storage_end(&emmc_storage);
sd_end();
if (kb >= KB_FIRMWARE_VERSION_620)
@@ -267,20 +266,17 @@ out_free:
void _toggle_autorcm(bool enable)
{
sdmmc_storage_t storage;
sdmmc_t sdmmc;
gfx_clear_partial_grey(0x1B, 0, 1256);
gfx_con_setpos(0, 0);
if (!sdmmc_storage_init_mmc(&storage, &sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400))
if (!sdmmc_storage_init_mmc(&emmc_storage, &emmc_sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400))
{
EPRINTF("Failed to init eMMC.");
goto out;
}
u8 *tempbuf = (u8 *)malloc(0x200);
sdmmc_storage_set_mmc_partition(&storage, EMMC_BOOT0);
sdmmc_storage_set_mmc_partition(&emmc_storage, EMMC_BOOT0);
int i, sect = 0;
u8 corr_mod0, mod1;
@@ -292,7 +288,7 @@ void _toggle_autorcm(bool enable)
for (i = 0; i < 4; i++)
{
sect = (0x200 + (0x4000 * i)) / NX_EMMC_BLOCKSIZE;
sdmmc_storage_read(&storage, sect, 1, tempbuf);
sdmmc_storage_read(&emmc_storage, sect, 1, tempbuf);
// Check if 2nd byte of modulus is correct.
if (tempbuf[0x11] != mod1)
@@ -302,11 +298,11 @@ void _toggle_autorcm(bool enable)
tempbuf[0x10] = 0;
else
tempbuf[0x10] = corr_mod0;
sdmmc_storage_write(&storage, sect, 1, tempbuf);
sdmmc_storage_write(&emmc_storage, sect, 1, tempbuf);
}
free(tempbuf);
sdmmc_storage_end(&storage);
sdmmc_storage_end(&emmc_storage);
if (enable)
gfx_printf("%kAutoRCM mode enabled!%k", 0xFFFFBA00, 0xFFCCCCCC);
@@ -329,7 +325,7 @@ void menu_autorcm()
if (h_cfg.rcm_patched)
{
gfx_printf("%kThis device is RCM patched and\nAutoRCM function is disabled.\n\n"
"In case %kAutoRCM%k is enabled\nthis will %kBRICK%k your device PERMANENTLY!!%k",
"In case %kAutoRCM%k is enabled\nthis will %kBRICK%k the device PERMANENTLY!!%k",
0xFFFFDD00, 0xFFFF0000, 0xFFFFDD00, 0xFFFF0000, 0xFFFFDD00, 0xFFCCCCCC);
btn_wait();
@@ -337,11 +333,9 @@ void menu_autorcm()
}
// Do a simple check on the main BCT.
sdmmc_storage_t storage;
sdmmc_t sdmmc;
bool disabled = true;
if (!sdmmc_storage_init_mmc(&storage, &sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400))
if (!sdmmc_storage_init_mmc(&emmc_storage, &emmc_sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400))
{
EPRINTF("Failed to init eMMC.");
btn_wait();
@@ -354,8 +348,8 @@ void menu_autorcm()
nx_emmc_get_autorcm_masks(&mod0, &mod1);
u8 *tempbuf = (u8 *)malloc(0x200);
sdmmc_storage_set_mmc_partition(&storage, EMMC_BOOT0);
sdmmc_storage_read(&storage, 0x200 / NX_EMMC_BLOCKSIZE, 1, tempbuf);
sdmmc_storage_set_mmc_partition(&emmc_storage, EMMC_BOOT0);
sdmmc_storage_read(&emmc_storage, 0x200 / NX_EMMC_BLOCKSIZE, 1, tempbuf);
// Check if 2nd byte of modulus is correct.
if (tempbuf[0x11] == mod1)
@@ -363,7 +357,7 @@ void menu_autorcm()
disabled = false;
free(tempbuf);
sdmmc_storage_end(&storage);
sdmmc_storage_end(&emmc_storage);
// Create AutoRCM menu.
ment_t *ments = (ment_t *)malloc(sizeof(ment_t) * 6);
@@ -393,7 +387,7 @@ void menu_autorcm()
ments[4].data = NULL;
memset(&ments[5], 0, sizeof(ment_t));
menu_t menu = {ments, "This corrupts your BOOT0!", 0, 0};
menu_t menu = {ments, "This corrupts BOOT0!", 0, 0};
tui_do_menu(&menu);
}

View File

@@ -1,6 +1,6 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2020 CTCaer
* Copyright (c) 2018-2021 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
@@ -397,11 +397,13 @@ void gfx_printf(const char *fmt, ...)
va_end(ap);
}
void gfx_hexdump(u32 base, const u8 *buf, u32 len)
void gfx_hexdump(u32 base, const void *buf, u32 len)
{
if (!gfx_con_init_done || gfx_con.mute)
return;
u8 *buff = (u8 *)buf;
u8 prevFontSize = gfx_con.fntsz;
gfx_con.fntsz = 8;
for(u32 i = 0; i < len; i++)
@@ -413,7 +415,7 @@ void gfx_hexdump(u32 base, const u8 *buf, u32 len)
gfx_puts("| ");
for(u32 j = 0; j < 0x10; j++)
{
u8 c = buf[i - 0x10 + j];
u8 c = buff[i - 0x10 + j];
if(c >= 32 && c <= 126)
gfx_putc(c);
else
@@ -423,7 +425,7 @@ void gfx_hexdump(u32 base, const u8 *buf, u32 len)
}
gfx_printf("%08x: ", base + i);
}
gfx_printf("%02x ", buf[i]);
gfx_printf("%02x ", buff[i]);
if (i == len - 1)
{
int ln = len % 0x10 != 0;
@@ -437,7 +439,7 @@ void gfx_hexdump(u32 base, const u8 *buf, u32 len)
gfx_puts("| ");
for(u32 j = 0; j < (ln ? k : k + 1); j++)
{
u8 c = buf[i - k + j];
u8 c = buff[i - k + j];
if(c >= 32 && c <= 126)
gfx_putc(c);
else

View File

@@ -1,6 +1,6 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2020 CTCaer
* Copyright (c) 2018-2021 CTCaer
* Copyright (c) 2018 M4xw
*
* This program is free software; you can redistribute it and/or modify it
@@ -63,7 +63,7 @@ void gfx_con_setpos(u32 x, u32 y);
void gfx_putc(char c);
void gfx_puts(char *s);
void gfx_printf(const char *fmt, ...);
void gfx_hexdump(u32 base, const u8 *buf, u32 len);
void gfx_hexdump(u32 base, const void *buf, u32 len);
void gfx_set_pixel(u32 x, u32 y, u32 color);
void gfx_line(int x0, int y0, int x1, int y1, u32 color);

View File

@@ -2,7 +2,7 @@
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018 st4rk
* Copyright (c) 2018 Ced2911
* Copyright (c) 2018-2020 CTCaer
* Copyright (c) 2018-2021 CTCaer
* Copyright (c) 2018 balika011
*
* This program is free software; you can redistribute it and/or modify it
@@ -75,7 +75,29 @@ typedef struct _secmon_mailbox_t
u32 out;
} secmon_mailbox_t;
static const u8 keyblob_keyseeds[][0x10] = {
typedef struct _tsec_keys_t
{
u8 tsec[SE_KEY_128_SIZE];
u8 tsec_root[SE_KEY_128_SIZE];
u8 tmp[SE_KEY_128_SIZE];
} tsec_keys_t;
typedef struct _kb_keys_t
{
u8 master_keyseed[SE_KEY_128_SIZE];
u8 random_data[0x70];
u8 package1_key[SE_KEY_128_SIZE];
} kb_keys_t;
typedef struct _kb_t
{
u8 cmac[SE_KEY_128_SIZE];
u8 ctr[SE_AES_IV_SIZE];
kb_keys_t keys;
u8 padding[0x150];
} kb_t;
static const u8 keyblob_keyseeds[][SE_KEY_128_SIZE] = {
{ 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.
{ 0x33, 0x76, 0x85, 0xEE, 0x88, 0x4A, 0xAE, 0x0A, 0xC2, 0x8A, 0xFD, 0x7D, 0x63, 0xC0, 0x43, 0x3B }, // 3.0.1.
@@ -84,19 +106,19 @@ static const u8 keyblob_keyseeds[][0x10] = {
{ 0xD8, 0xCC, 0xE1, 0x26, 0x6A, 0x35, 0x3F, 0xCC, 0x20, 0xF3, 0x2D, 0x3B, 0x51, 0x7D, 0xE9, 0xC0 } // 6.0.0.
};
static const u8 cmac_keyseed[0x10] =
static const u8 cmac_keyseed[SE_KEY_128_SIZE] =
{ 0x59, 0xC7, 0xFB, 0x6F, 0xBE, 0x9B, 0xBE, 0x87, 0x65, 0x6B, 0x15, 0xC0, 0x53, 0x73, 0x36, 0xA5 };
static const u8 master_keyseed_retail[0x10] =
static const u8 master_keyseed_retail[SE_KEY_128_SIZE] =
{ 0xD8, 0xA2, 0x41, 0x0A, 0xC6, 0xC5, 0x90, 0x01, 0xC6, 0x1D, 0x6A, 0x26, 0x7C, 0x51, 0x3F, 0x3C };
static const u8 master_keyseed_4xx_5xx_610[0x10] =
static const u8 master_keyseed_4xx_5xx_610[SE_KEY_128_SIZE] =
{ 0x2D, 0xC1, 0xF4, 0x8D, 0xF3, 0x5B, 0x69, 0x33, 0x42, 0x10, 0xAC, 0x65, 0xDA, 0x90, 0x46, 0x66 };
static const u8 master_keyseed_620[0x10] =
static const u8 master_keyseed_620[SE_KEY_128_SIZE] =
{ 0x37, 0x4B, 0x77, 0x29, 0x59, 0xB4, 0x04, 0x30, 0x81, 0xF6, 0xE5, 0x8C, 0x6D, 0x36, 0x17, 0x9A };
static const u8 master_kekseed_t210b01[][0x10] = {
static const u8 master_kekseed_t210b01[][SE_KEY_128_SIZE] = {
{ 0x77, 0x60, 0x5A, 0xD2, 0xEE, 0x6E, 0xF8, 0x3C, 0x3F, 0x72, 0xE2, 0x59, 0x9D, 0xAC, 0x5E, 0x56 }, // 6.0.0.
{ 0x1E, 0x80, 0xB8, 0x17, 0x3E, 0xC0, 0x60, 0xAA, 0x11, 0xBE, 0x1A, 0x4A, 0xA6, 0x6F, 0xE4, 0xAE }, // 6.2.0.
{ 0x94, 0x08, 0x67, 0xBD, 0x0A, 0x00, 0x38, 0x84, 0x11, 0xD3, 0x1A, 0xDB, 0xDD, 0x8D, 0xF1, 0x8A }, // 7.0.0.
@@ -105,13 +127,13 @@ static const u8 master_kekseed_t210b01[][0x10] = {
{ 0x0E, 0x44, 0x0C, 0xED, 0xB4, 0x36, 0xC0, 0x3F, 0xAA, 0x1D, 0xAE, 0xBF, 0x62, 0xB1, 0x09, 0x82 }, // 9.1.0.
};
static const u8 console_keyseed[0x10] =
static const u8 console_keyseed[SE_KEY_128_SIZE] =
{ 0x4F, 0x02, 0x5F, 0x0E, 0xB6, 0x6D, 0x11, 0x0E, 0xDC, 0x32, 0x7D, 0x41, 0x86, 0xC2, 0xF4, 0x78 };
static const u8 console_keyseed_4xx_5xx[0x10] =
static const u8 console_keyseed_4xx_5xx[SE_KEY_128_SIZE] =
{ 0x0C, 0x91, 0x09, 0xDB, 0x93, 0x93, 0x07, 0x81, 0x07, 0x3C, 0xC4, 0x16, 0x22, 0x7C, 0x6C, 0x28 };
const u8 package2_keyseed[0x10] =
const u8 package2_keyseed[SE_KEY_128_SIZE] =
{ 0xFB, 0x8B, 0x6A, 0x9C, 0x79, 0x00, 0xC8, 0x49, 0xEF, 0xD2, 0x4D, 0x85, 0x4D, 0x30, 0xA0, 0xC7 };
static void _hos_crit_error(const char *text)
@@ -124,30 +146,33 @@ static void _se_lock(bool lock_se)
{
if (lock_se)
{
// Disable aes key read.
for (u32 i = 0; i < 16; i++)
se_key_acc_ctrl(i, SE_KEY_TBL_DIS_KEYREAD_FLAG | SE_KEY_TBL_DIS_OIVREAD_FLAG | SE_KEY_TBL_DIS_UIVREAD_FLAG);
// Disable RSA key read.
for (u32 i = 0; i < 2; i++)
se_rsa_acc_ctrl(i, SE_RSA_KEY_TBL_DIS_KEYREAD_FLAG);
SE(SE_TZRAM_SECURITY_0) = 0; // Make SE TZRAM secure only.
SE(SE_KEY_TABLE_ACCESS_LOCK_OFFSET) = 0; // Make all key access regs secure only.
SE(SE_RSA_KEYTABLE_ACCESS_LOCK_OFFSET) = 0; // Make all RSA access regs secure only.
SE(SE_SECURITY_0) &= 0xFFFFFFFB; // Make access lock regs secure only.
SE(SE_TZRAM_SECURITY_REG) = 0; // Make SE TZRAM secure only.
SE(SE_CRYPTO_SECURITY_PERKEY_REG) = 0; // Make all AES keys access secure only.
SE(SE_RSA_SECURITY_PERKEY_REG) = 0; // Make all RSA keys access secure only.
SE(SE_SE_SECURITY_REG) &= ~SE_PERKEY_SETTING; // Make access lock regs secure only.
}
memset((void *)IPATCH_BASE, 0, 14 * sizeof(u32));
SB(SB_CSR) = SB_CSR_PIROM_DISABLE;
// This is useful for documenting the bits in the SE config registers, so we can keep it around.
/*gfx_printf("SE(SE_SECURITY_0) = %08X\n", SE(SE_SECURITY_0));
/*gfx_printf("SE(SE_SE_SECURITY_REG) = %08X\n", SE(SE_SE_SECURITY_REG));
gfx_printf("SE(0x4) = %08X\n", SE(0x4));
gfx_printf("SE(SE_KEY_TABLE_ACCESS_LOCK_OFFSET) = %08X\n", SE(SE_KEY_TABLE_ACCESS_LOCK_OFFSET));
gfx_printf("SE(SE_RSA_KEYTABLE_ACCESS_LOCK_OFFSET) = %08X\n", SE(SE_RSA_KEYTABLE_ACCESS_LOCK_OFFSET));
gfx_printf("SE(SE_CRYPTO_SECURITY_PERKEY_REG) = %08X\n", SE(SE_CRYPTO_SECURITY_PERKEY_REG));
gfx_printf("SE(SE_RSA_SECURITY_PERKEY_REG) = %08X\n", SE(SE_RSA_SECURITY_PERKEY_REG));
for(u32 i = 0; i < 16; i++)
gfx_printf("%02X ", SE(SE_KEY_TABLE_ACCESS_REG_OFFSET + i * 4) & 0xFF);
gfx_printf("%02X ", SE(SE_CRYPTO_KEYTABLE_ACCESS_REG + i * 4) & 0xFF);
gfx_putc('\n');
for(u32 i = 0; i < 2; i++)
gfx_printf("%02X ", SE(SE_RSA_KEYTABLE_ACCESS_REG_OFFSET + i * 4) & 0xFF);
gfx_printf("%02X ", SE(SE_RSA_KEYTABLE_ACCESS_REG + i * 4) & 0xFF);
gfx_putc('\n');
gfx_hexdump(SE_BASE, (void *)SE_BASE, 0x400);*/
}
@@ -240,6 +265,8 @@ void hos_eks_save(u32 kb)
// If matching blob doesn't exist, create it.
bool update_eks = key_idx ? (h_cfg.eks->enabled[key_idx] < kb) : !h_cfg.eks->enabled[0];
// If old EKS version was found, update it.
update_eks |= h_cfg.eks->lot0 != FUSE(FUSE_OPT_LOT_CODE_0);
if (update_eks)
{
// Read EKS blob.
@@ -256,8 +283,8 @@ void hos_eks_save(u32 kb)
}
// Get keys.
u8 *keys = (u8 *)calloc(0x1000, 1);
se_get_aes_keys(keys + 0x800, keys, 0x10);
u8 *keys = (u8 *)calloc(0x2000, 1);
se_get_aes_keys(keys + 0x1000, keys, SE_KEY_128_SIZE);
// Set magic and personalized info.
h_cfg.eks->magic = HOS_EKS_MAGIC;
@@ -265,18 +292,18 @@ void hos_eks_save(u32 kb)
h_cfg.eks->lot0 = FUSE(FUSE_OPT_LOT_CODE_0);
// Copy new keys.
memcpy(h_cfg.eks->dkg, keys + 10 * 0x10, 0x10);
memcpy(h_cfg.eks->dkk, keys + 15 * 0x10, 0x10);
memcpy(h_cfg.eks->dkg, keys + 10 * SE_KEY_128_SIZE, SE_KEY_128_SIZE);
memcpy(h_cfg.eks->dkk, keys + 15 * SE_KEY_128_SIZE, SE_KEY_128_SIZE);
if (!h_cfg.aes_slots_new)
{
memcpy(h_cfg.eks->keys[key_idx].mkk, keys + 12 * 0x10, 0x10);
memcpy(h_cfg.eks->keys[key_idx].fdk, keys + 13 * 0x10, 0x10);
memcpy(h_cfg.eks->keys[key_idx].mkk, keys + 12 * SE_KEY_128_SIZE, SE_KEY_128_SIZE);
memcpy(h_cfg.eks->keys[key_idx].fdk, keys + 13 * SE_KEY_128_SIZE, SE_KEY_128_SIZE);
}
else // New sept slots.
{
memcpy(h_cfg.eks->keys[key_idx].mkk, keys + 13 * 0x10, 0x10);
memcpy(h_cfg.eks->keys[key_idx].fdk, keys + 12 * 0x10, 0x10);
memcpy(h_cfg.eks->keys[key_idx].mkk, keys + 13 * SE_KEY_128_SIZE, SE_KEY_128_SIZE);
memcpy(h_cfg.eks->keys[key_idx].fdk, keys + 12 * SE_KEY_128_SIZE, SE_KEY_128_SIZE);
}
// Encrypt EKS blob.
@@ -288,7 +315,6 @@ void hos_eks_save(u32 kb)
memcpy(mbr + 0x80, eks, sizeof(hos_eks_mbr_t));
hos_eks_rw_try(mbr, true);
free(eks);
free(keys);
out:
@@ -354,10 +380,11 @@ int hos_keygen_t210b01(u32 kb)
return 1;
}
int hos_keygen(u8 *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt, launch_ctxt_t *hos_ctxt)
int hos_keygen(void *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt, launch_ctxt_t *hos_ctxt)
{
u8 tmp[0x30];
u32 retries = 0;
tsec_keys_t tsec_keys;
kb_t *kb_data = (kb_t *)keyblob;
if (kb > KB_FIRMWARE_VERSION_MAX)
return 0;
@@ -385,9 +412,9 @@ int hos_keygen(u8 *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt, launch_ctxt_t *hos_c
// Get TSEC key.
if (kb <= KB_FIRMWARE_VERSION_620)
{
while (tsec_query(tmp, kb, tsec_ctxt) < 0)
while (tsec_query(&tsec_keys, kb, tsec_ctxt) < 0)
{
memset(tmp, 0x00, 0x20);
memset(&tsec_keys, 0x00, 0x20);
retries++;
// We rely on racing conditions, make sure we cover even the unluckiest cases.
@@ -409,25 +436,25 @@ int hos_keygen(u8 *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt, launch_ctxt_t *hos_c
if (h_cfg.eks && h_cfg.eks->enabled[key_idx] >= kb)
{
// Set Device keygen key to slot 10.
se_aes_key_set(10, h_cfg.eks->dkg, 0x10);
se_aes_key_set(10, h_cfg.eks->dkg, SE_KEY_128_SIZE);
// Set Device key to slot 15.
se_aes_key_set(15, h_cfg.eks->dkk, 0x10);
se_aes_key_set(15, h_cfg.eks->dkk, SE_KEY_128_SIZE);
if (!h_cfg.aes_slots_new)
{
// Set Master key to slot 12.
se_aes_key_set(12, h_cfg.eks->keys[key_idx].mkk, 0x10);
se_aes_key_set(12, h_cfg.eks->keys[key_idx].mkk, SE_KEY_128_SIZE);
// Set FW Device key key to slot 13.
se_aes_key_set(13, h_cfg.eks->keys[key_idx].fdk, 0x10);
se_aes_key_set(13, h_cfg.eks->keys[key_idx].fdk, SE_KEY_128_SIZE);
// Lock FDK.
se_key_acc_ctrl(13, SE_KEY_TBL_DIS_KEYREAD_FLAG | SE_KEY_TBL_DIS_OIVREAD_FLAG | SE_KEY_TBL_DIS_UIVREAD_FLAG);
}
else // New exosphere.
{
// Set Master key to slot 13.
se_aes_key_set(13, h_cfg.eks->keys[key_idx].mkk, 0x10);
se_aes_key_set(13, h_cfg.eks->keys[key_idx].mkk, SE_KEY_128_SIZE);
// Set FW Device key key to slot 12.
se_aes_key_set(12, h_cfg.eks->keys[key_idx].fdk, 0x10);
se_aes_key_set(12, h_cfg.eks->keys[key_idx].fdk, SE_KEY_128_SIZE);
// Lock FDK.
se_key_acc_ctrl(12, SE_KEY_TBL_DIS_KEYREAD_FLAG | SE_KEY_TBL_DIS_OIVREAD_FLAG | SE_KEY_TBL_DIS_UIVREAD_FLAG);
}
@@ -439,14 +466,14 @@ int hos_keygen(u8 *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt, launch_ctxt_t *hos_c
else if (kb == KB_FIRMWARE_VERSION_620)
{
// Set TSEC key.
se_aes_key_set(12, tmp, 0x10);
se_aes_key_set(12, tsec_keys.tsec, SE_KEY_128_SIZE);
// Set TSEC root key.
se_aes_key_set(13, tmp + 0x10, 0x10);
se_aes_key_set(13, tsec_keys.tsec_root, SE_KEY_128_SIZE);
if (!(emu_cfg.enabled && !h_cfg.emummc_force_disable) && hos_ctxt->stock)
{
// Package2 key.
se_aes_key_set(8, tmp + 0x10, 0x10);
se_aes_key_set(8, tsec_keys.tsec_root, SE_KEY_128_SIZE);
se_aes_unwrap_key(8, 8, master_keyseed_620);
se_aes_unwrap_key(8, 8, master_keyseed_retail);
se_aes_unwrap_key(8, 8, package2_keyseed);
@@ -454,8 +481,8 @@ int hos_keygen(u8 *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt, launch_ctxt_t *hos_c
else
{
// Decrypt keyblob and set keyslots
se_aes_crypt_block_ecb(12, 0, tmp + 0x20, keyblob_keyseeds[0]);
se_aes_unwrap_key(15, 14, tmp + 0x20);
se_aes_crypt_block_ecb(12, 0, tsec_keys.tmp, keyblob_keyseeds[0]);
se_aes_unwrap_key(15, 14, tsec_keys.tmp);
se_aes_unwrap_key(10, 15, console_keyseed_4xx_5xx);
se_aes_unwrap_key(15, 15, console_keyseed);
@@ -484,33 +511,36 @@ int hos_keygen(u8 *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt, launch_ctxt_t *hos_c
se_key_acc_ctrl(14, SE_KEY_TBL_DIS_KEYREAD_FLAG | SE_KEY_TBL_DIS_OIVREAD_FLAG | SE_KEY_TBL_DIS_UIVREAD_FLAG);
// Set TSEC key.
se_aes_key_set(13, tmp, 0x10);
se_aes_key_set(13, tsec_keys.tsec, SE_KEY_128_SIZE);
// Derive keyblob keys from TSEC+SBK.
se_aes_crypt_block_ecb(13, 0, tmp, keyblob_keyseeds[0]);
se_aes_unwrap_key(15, 14, tmp);
se_aes_crypt_block_ecb(13, 0, tmp, keyblob_keyseeds[kb]);
se_aes_unwrap_key(13, 14, tmp);
se_aes_crypt_block_ecb(13, 0, tsec_keys.tsec, keyblob_keyseeds[0]);
se_aes_unwrap_key(15, 14, tsec_keys.tsec);
se_aes_crypt_block_ecb(13, 0, tsec_keys.tsec, keyblob_keyseeds[kb]);
se_aes_unwrap_key(13, 14, tsec_keys.tsec);
// Clear SBK.
se_aes_key_clear(14);
//TODO: verify keyblob CMAC.
//se_aes_unwrap_key(11, 13, cmac_keyseed);
//se_aes_cmac(tmp, 0x10, 11, keyblob + 0x10, 0xA0);
//if (!memcmp(keyblob, tmp, 0x10))
// return 0;
/*
// Verify keyblob CMAC.
u8 cmac[SE_KEY_128_SIZE];
se_aes_unwrap_key(11, 13, cmac_keyseed);
se_aes_cmac(cmac, SE_KEY_128_SIZE, 11, (void *)kb_data->ctr, sizeof(kb_data->ctr) + sizeof(kb_data->keys));
if (!memcmp(kb_data->cmac, cmac, SE_KEY_128_SIZE))
return 0;
*/
se_aes_crypt_block_ecb(13, 0, tmp, cmac_keyseed);
se_aes_crypt_block_ecb(13, 0, tsec_keys.tsec, cmac_keyseed);
se_aes_unwrap_key(11, 13, cmac_keyseed);
// Decrypt keyblob and set keyslots.
se_aes_crypt_ctr(13, keyblob + 0x20, 0x90, keyblob + 0x20, 0x90, keyblob + 0x10);
se_aes_key_set(11, keyblob + 0x20 + 0x80, 0x10); // Package1 key.
se_aes_key_set(12, keyblob + 0x20, 0x10);
se_aes_key_set(13, keyblob + 0x20, 0x10);
se_aes_crypt_ctr(13, &kb_data->keys, sizeof(kb_data->keys), &kb_data->keys, sizeof(kb_data->keys), kb_data->ctr);
se_aes_key_set(11, kb_data->keys.package1_key, SE_KEY_128_SIZE);
se_aes_key_set(12, kb_data->keys.master_keyseed, SE_KEY_128_SIZE);
se_aes_key_set(13, kb_data->keys.master_keyseed, SE_KEY_128_SIZE);
se_aes_crypt_block_ecb(12, 0, tmp, master_keyseed_retail);
se_aes_crypt_block_ecb(12, 0, tsec_keys.tsec, master_keyseed_retail);
if (!h_cfg.aes_slots_new)
{
@@ -566,8 +596,8 @@ static int _read_emmc_pkg1(launch_ctxt_t *ctxt)
try_load:
// Read package1.
emummc_storage_set_mmc_partition(&emmc_storage, EMMC_BOOT0);
emummc_storage_read(&emmc_storage, bootloader_offset / NX_EMMC_BLOCKSIZE, BOOTLOADER_SIZE / NX_EMMC_BLOCKSIZE, ctxt->pkg1);
emummc_storage_set_mmc_partition(EMMC_BOOT0);
emummc_storage_read(bootloader_offset / NX_EMMC_BLOCKSIZE, BOOTLOADER_SIZE / NX_EMMC_BLOCKSIZE, ctxt->pkg1);
ctxt->pkg1_id = pkg1_identify(ctxt->pkg1 + pk1_offset);
if (!ctxt->pkg1_id)
@@ -590,7 +620,7 @@ try_load:
// Read the correct keyblob.
ctxt->keyblob = (u8 *)calloc(NX_EMMC_BLOCKSIZE, 1);
emummc_storage_read(&emmc_storage, HOS_KEYBLOBS_OFFSET / NX_EMMC_BLOCKSIZE + ctxt->pkg1_id->kb, 1, ctxt->keyblob);
emummc_storage_read(HOS_KEYBLOBS_OFFSET / NX_EMMC_BLOCKSIZE + ctxt->pkg1_id->kb, 1, ctxt->keyblob);
return 1;
}
@@ -599,7 +629,7 @@ static u8 *_read_emmc_pkg2(launch_ctxt_t *ctxt)
{
u8 *bctBuf = NULL;
emummc_storage_set_mmc_partition(&emmc_storage, EMMC_GPP);
emummc_storage_set_mmc_partition(EMMC_GPP);
// Parse eMMC GPT.
LIST_INIT(gpt);
@@ -710,17 +740,21 @@ int hos_launch(ini_sec_t *cfg)
gfx_puts("Initializing...\n\n");
// Initialize eMMC/emuMMC.
int res = emummc_storage_init_mmc(&emmc_storage, &emmc_sdmmc);
int res = emummc_storage_init_mmc();
if (res)
{
if (res == 2)
_hos_crit_error("Failed to init eMMC");
_hos_crit_error("Failed to init eMMC.");
else
_hos_crit_error("Failed to init emuMMC");
_hos_crit_error("Failed to init emuMMC.");
goto error;
}
// Check if SD Card is GPT.
if (sd_is_gpt())
_hos_crit_error("SD has GPT only!");
// Read package1 and the correct keyblob.
if (!_read_emmc_pkg1(&ctxt))
goto error;
@@ -843,7 +877,17 @@ int hos_launch(ini_sec_t *cfg)
}
// Configure and manage Warmboot binary.
pkg1_warmboot_config(&ctxt, warmboot_base);
if (!pkg1_warmboot_config(&ctxt, warmboot_base))
{
// Can only happen on T210B01.
_hos_crit_error("Failed to match warmboot with fuses!\nIf you continue, sleep wont work!");
gfx_puts("\nPress POWER to continue.\nPress VOL to go to the menu.\n");
display_backlight_brightness(h_cfg.backlight, 1000);
if (!(btn_wait() & BTN_POWER))
goto error;
}
// Replace 'warmboot.bin' if requested.
if (ctxt.warmboot)
@@ -970,7 +1014,8 @@ int hos_launch(ini_sec_t *cfg)
}
// Patch kip1s in memory if needed.
gfx_printf("%kPatching kips%k\n", 0xFFFFBA00, 0xFFCCCCCC);
if (ctxt.kip1_patches)
gfx_printf("%kPatching kips%k\n", 0xFFFFBA00, 0xFFCCCCCC);
const char* unappliedPatch = pkg2_patch_kips(&kip1_info, ctxt.kip1_patches);
if (unappliedPatch != NULL)
{
@@ -1011,16 +1056,16 @@ int hos_launch(ini_sec_t *cfg)
case KB_FIRMWARE_VERSION_100_200:
case KB_FIRMWARE_VERSION_300:
case KB_FIRMWARE_VERSION_301:
se_key_acc_ctrl(12, SE_KEY_TBL_DIS_KEY_ACCESS_FLAG | SE_KEY_TBL_DIS_KEY_LOCK_FLAG);
se_key_acc_ctrl(13, SE_KEY_TBL_DIS_KEY_ACCESS_FLAG | SE_KEY_TBL_DIS_KEY_LOCK_FLAG);
se_key_acc_ctrl(12, SE_KEY_TBL_DIS_KEY_ACCESS_FLAG | SE_KEY_LOCK_FLAG);
se_key_acc_ctrl(13, SE_KEY_TBL_DIS_KEY_ACCESS_FLAG | SE_KEY_LOCK_FLAG);
bootStateDramPkg2 = 2;
bootStatePkg2Continue = 3;
break;
case KB_FIRMWARE_VERSION_400:
case KB_FIRMWARE_VERSION_500:
case KB_FIRMWARE_VERSION_600:
se_key_acc_ctrl(12, SE_KEY_TBL_DIS_KEY_ACCESS_FLAG | SE_KEY_TBL_DIS_KEY_LOCK_FLAG);
se_key_acc_ctrl(15, SE_KEY_TBL_DIS_KEY_ACCESS_FLAG | SE_KEY_TBL_DIS_KEY_LOCK_FLAG);
se_key_acc_ctrl(12, SE_KEY_TBL_DIS_KEY_ACCESS_FLAG | SE_KEY_LOCK_FLAG);
se_key_acc_ctrl(15, SE_KEY_TBL_DIS_KEY_ACCESS_FLAG | SE_KEY_LOCK_FLAG);
default:
bootStateDramPkg2 = 2;
bootStatePkg2Continue = 4;

View File

@@ -1,6 +1,6 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2020 CTCaer
* Copyright (c) 2018-2021 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
@@ -20,6 +20,7 @@
#include "pkg1.h"
#include "pkg2.h"
#include <sec/se_t210.h>
#include <utils/types.h>
#include <utils/ini.h>
#include <sec/tsec.h>
@@ -56,14 +57,14 @@ typedef struct _exo_ctxt_t
typedef struct _hos_eks_keys_t
{
u8 mkk[0x10];
u8 fdk[0x10];
u8 mkk[SE_KEY_128_SIZE];
u8 fdk[SE_KEY_128_SIZE];
} hos_eks_keys_t;
typedef struct _hos_eks_bis_keys_t
{
u8 crypt[0x10];
u8 tweak[0x10];
u8 crypt[SE_KEY_128_SIZE];
u8 tweak[SE_KEY_128_SIZE];
} hos_eks_bis_keys_t;
typedef struct _hos_eks_mbr_t
@@ -73,8 +74,8 @@ typedef struct _hos_eks_mbr_t
u8 enabled_bis;
u8 rsvd[2];
u32 lot0;
u8 dkg[0x10];
u8 dkk[0x10];
u8 dkg[SE_KEY_128_SIZE];
u8 dkk[SE_KEY_128_SIZE];
hos_eks_keys_t keys[5];
hos_eks_bis_keys_t bis_keys[3];
} hos_eks_mbr_t;
@@ -129,6 +130,6 @@ void hos_eks_get();
void hos_eks_save(u32 kb);
void hos_eks_clear(u32 kb);
int hos_launch(ini_sec_t *cfg);
int hos_keygen(u8 *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt, launch_ctxt_t *hos_ctxt);
int hos_keygen(void *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt, launch_ctxt_t *hos_ctxt);
#endif

View File

@@ -1,7 +1,7 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018 st4rk
* Copyright (c) 2018-2020 CTCaer
* Copyright (c) 2018-2021 CTCaer
* Copyright (c) 2018 balika011
*
* This program is free software; you can redistribute it and/or modify it
@@ -211,6 +211,7 @@ int pkg1_decrypt(const pkg1_id_t *id, u8 *pkg1)
hdr = (pk11_hdr_t *)(pkg1 + id->pkg11_off + 0x20);
// Use BEK for T210B01.
// Additionally, skip 0x20 bytes from decryption to maintain the header.
se_aes_iv_clear(13);
se_aes_crypt_cbc(13, 0, pkg1 + 0x20, oem_hdr->size - 0x20, pkg1 + 0x20, oem_hdr->size - 0x20);
}
@@ -330,10 +331,11 @@ static void _warmboot_filename(char *out, u32 fuses)
strcat(out, ".bin");
}
void pkg1_warmboot_config(void *hos_ctxt, u32 warmboot_base)
int pkg1_warmboot_config(void *hos_ctxt, u32 warmboot_base)
{
launch_ctxt_t *ctxt = (launch_ctxt_t *)hos_ctxt;
u32 kb = ctxt->pkg1_id->kb;
int res = 1;
// Set warmboot address in PMC if required.
if (kb <= KB_FIRMWARE_VERSION_301)
@@ -346,7 +348,7 @@ void pkg1_warmboot_config(void *hos_ctxt, u32 warmboot_base)
u32 fuses_fw = ctxt->pkg1_id->fuses;
u8 burnt_fuses = fuse_count_burnt(fuse_read_odm(7));
// Save current warmboot in storage cache and check if another one is needed.
// Save current warmboot in storage cache (MWS) and check if another one is needed.
if (!ctxt->warmboot)
{
char path[128];
@@ -356,7 +358,7 @@ void pkg1_warmboot_config(void *hos_ctxt, u32 warmboot_base)
if (f_stat(path, NULL))
sd_save_to_file((void *)warmboot_base, ctxt->warmboot_size, path);
// Load warmboot fw from storage if not matched.
// Load warmboot fw from storage (MWS) if not matched.
if (burnt_fuses > fuses_fw)
{
u32 tmp_fuses = burnt_fuses;
@@ -373,6 +375,10 @@ void pkg1_warmboot_config(void *hos_ctxt, u32 warmboot_base)
break;
tmp_fuses++;
}
// Check if proper warmboot firmware was found.
if (!ctxt->warmboot)
res = 0;
}
else // Replace burnt fuses with higher count.
burnt_fuses = fuses_fw;
@@ -405,4 +411,6 @@ void pkg1_warmboot_config(void *hos_ctxt, u32 warmboot_base)
else if (kb == KB_FIRMWARE_VERSION_301)
PMC(APBDEV_PMC_SECURE_SCRATCH32) = 0x104; // Warmboot 3.0.1/.2 PA address id.
}
return res;
}

View File

@@ -81,6 +81,6 @@ int pkg1_decrypt(const pkg1_id_t *id, u8 *pkg1);
const u8 *pkg1_unpack(void *wm_dst, u32 *wb_sz, void *sm_dst, void *ldr_dst, const pkg1_id_t *id, u8 *pkg1);
void pkg1_secmon_patch(void *hos_ctxt, u32 secmon_base, bool t210b01);
void pkg1_warmboot_patch(void *hos_ctxt);
void pkg1_warmboot_config(void *hos_ctxt, u32 warmboot_base);
int pkg1_warmboot_config(void *hos_ctxt, u32 warmboot_base);
#endif

View File

@@ -1,6 +1,6 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2020 CTCaer
* Copyright (c) 2018-2021 CTCaer
* Copyright (c) 2018 Atmosphère-NX
*
* This program is free software; you can redistribute it and/or modify it
@@ -27,6 +27,7 @@
#include <libs/fatfs/ff.h>
#include <mem/heap.h>
#include <sec/se.h>
#include <sec/se_t210.h>
#include "../storage/emummc.h"
#include <storage/nx_sd.h>
#include <utils/aarch64_util.h>
@@ -1335,7 +1336,7 @@ const char* pkg2_patch_kips(link_t *info, char* patchNames)
return NULL;
}
static const u8 mkey_vector_8xx[][0x10] =
static const u8 mkey_vector_8xx[][SE_KEY_128_SIZE] =
{
// Master key 8 encrypted with 9. (8.1.0 with 9.0.0)
{ 0x4D, 0xD9, 0x98, 0x42, 0x45, 0x0D, 0xB1, 0x3C, 0x52, 0x0C, 0x9A, 0x44, 0xBB, 0xAD, 0xAF, 0x80 },
@@ -1346,10 +1347,10 @@ static const u8 mkey_vector_8xx[][0x10] =
static bool _pkg2_key_unwrap_validate(pkg2_hdr_t *tmp_test, pkg2_hdr_t *hdr, u8 src_slot, u8 *mkey, const u8 *key_seed)
{
// Decrypt older encrypted mkey.
se_aes_crypt_ecb(src_slot, 0, mkey, 0x10, key_seed, 0x10);
se_aes_crypt_ecb(src_slot, 0, mkey, SE_KEY_128_SIZE, key_seed, SE_KEY_128_SIZE);
// Set and unwrap pkg2 key.
se_aes_key_clear(9);
se_aes_key_set(9, mkey, 0x10);
se_aes_key_set(9, mkey, SE_KEY_128_SIZE);
se_aes_unwrap_key(9, 9, package2_keyseed);
// Decrypt header.
@@ -1383,9 +1384,9 @@ pkg2_hdr_t *pkg2_decrypt(void *data, u8 kb)
// Decrypt older pkg2 via new mkeys.
if ((kb >= KB_FIRMWARE_VERSION_810) && (kb < KB_FIRMWARE_VERSION_MAX))
{
u8 tmp_mkey[0x10];
u8 tmp_mkey[SE_KEY_128_SIZE];
u8 decr_slot = !h_cfg.t210b01 ? (!h_cfg.aes_slots_new ? 12 : 13) : 7; // Sept mkey or T210B01 mkey.
u8 mkey_seeds_cnt = sizeof(mkey_vector_8xx) / 0x10;
u8 mkey_seeds_cnt = sizeof(mkey_vector_8xx) / SE_KEY_128_SIZE;
u8 mkey_seeds_idx = mkey_seeds_cnt; // Real index + 1.
u8 mkey_seeds_min_idx = mkey_seeds_cnt - (KB_FIRMWARE_VERSION_MAX - kb);
@@ -1405,7 +1406,7 @@ pkg2_hdr_t *pkg2_decrypt(void *data, u8 kb)
// Set current mkey in order to decrypt a lower mkey.
mkey_seeds_idx--;
se_aes_key_clear(9);
se_aes_key_set(9, tmp_mkey, 0x10);
se_aes_key_set(9, tmp_mkey, SE_KEY_128_SIZE);
decr_slot = 9; // Temp key.
@@ -1439,7 +1440,7 @@ DPRINTF("sec %d has size %08X\n", i, hdr->sec_size[i]);
if (!hdr->sec_size[i])
continue;
se_aes_crypt_ctr(pkg2_keyslot, pdata, 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 * SE_AES_IV_SIZE]);
//gfx_hexdump((u32)pdata, pdata, 0x100);
pdata += hdr->sec_size[i];
@@ -1469,7 +1470,7 @@ DPRINTF("adding kip1 '%s' @ %08X (%08X)\n", ki->kip1->name, (u32)ki->kip1, ki->s
{
hdr->sec_size[PKG2_SEC_INI1] = ini1_size;
hdr->sec_off[PKG2_SEC_INI1] = 0x14080000;
se_aes_crypt_ctr(8, ini1, ini1_size, ini1, ini1_size, &hdr->sec_ctr[PKG2_SEC_INI1 * 0x10]);
se_aes_crypt_ctr(8, ini1, ini1_size, ini1, ini1_size, &hdr->sec_ctr[PKG2_SEC_INI1 * SE_AES_IV_SIZE]);
}
else
{
@@ -1526,7 +1527,7 @@ DPRINTF("%s @ %08X (%08X)\n", is_meso ? "Mesosphere": "kernel",(u32)ctxt->kernel
hdr->sec_off[PKG2_SEC_KERNEL] = 0x60000;
}
hdr->sec_size[PKG2_SEC_KERNEL] = kernel_size;
se_aes_crypt_ctr(pkg2_keyslot, 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 * SE_AES_IV_SIZE]);
pdst += kernel_size;
DPRINTF("kernel encrypted\n");
@@ -1549,7 +1550,7 @@ DPRINTF("INI1 encrypted\n");
*(u32 *)hdr->ctr = 0x100 + sizeof(pkg2_hdr_t) + kernel_size + ini1_size;
hdr->ctr[4] = key_ver;
se_aes_crypt_ctr(pkg2_keyslot, hdr, sizeof(pkg2_hdr_t), hdr, sizeof(pkg2_hdr_t), hdr);
memset(hdr->ctr, 0 , 0x10);
memset(hdr->ctr, 0 , SE_AES_IV_SIZE);
*(u32 *)hdr->ctr = 0x100 + sizeof(pkg2_hdr_t) + kernel_size + ini1_size;
hdr->ctr[4] = key_ver;

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2019 CTCaer
* Copyright (c) 2019-2021 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
@@ -33,6 +33,7 @@
#include <storage/sdmmc.h>
#include <utils/btn.h>
#include <utils/types.h>
#include <utils/util.h>
#include <gfx_utils.h>
@@ -55,6 +56,7 @@ u8 warmboot_reboot[] = {
};
#define SEPT_PRI_ADDR 0x4003F000
#define SEPT_PRI_ENTRY 0x40010340
#define SEPT_PK1T_ADDR 0xC0400000
#define SEPT_TCSZ_ADDR (SEPT_PK1T_ADDR - 0x4)
@@ -93,23 +95,21 @@ void check_sept(ini_sec_t *cfg_sec)
u8 *pkg1 = (u8 *)calloc(1, 0x40000);
sdmmc_storage_t storage;
sdmmc_t sdmmc;
int res = emummc_storage_init_mmc(&storage, &sdmmc);
int res = emummc_storage_init_mmc();
if (res)
{
if (res == 2)
EPRINTF("Failed to init eMMC");
EPRINTF("Failed to init eMMC.");
else
EPRINTF("Failed to init emuMMC");
EPRINTF("Failed to init emuMMC.");
goto out_free;
}
emummc_storage_set_mmc_partition(&storage, EMMC_BOOT0);
emummc_storage_set_mmc_partition(EMMC_BOOT0);
// Read package1.
emummc_storage_read(&storage, 0x100000 / NX_EMMC_BLOCKSIZE, 0x40000 / NX_EMMC_BLOCKSIZE, pkg1);
emummc_storage_read(0x100000 / NX_EMMC_BLOCKSIZE, 0x40000 / NX_EMMC_BLOCKSIZE, pkg1);
const pkg1_id_t *pkg1_id = pkg1_identify(pkg1);
if (!pkg1_id)
{
@@ -129,13 +129,28 @@ void check_sept(ini_sec_t *cfg_sec)
goto out_free;
}
sdmmc_storage_end(&storage);
u8 *bct_bldr = (u8 *)calloc(1, 512);
sdmmc_storage_read(&emmc_storage, 0x2200 / NX_EMMC_BLOCKSIZE, 1, bct_bldr);
u32 bootloader_entrypoint = *(u32 *)&bct_bldr[0x144];
free(bct_bldr);
if (bootloader_entrypoint > SEPT_PRI_ENTRY)
{
gfx_con.mute = false;
EPRINTF("Failed to run sept\n""Main BCT is improper!\nRun sept with proper BCT at least once\nto cache keys.");
gfx_printf("\nPress any key...\n");
display_backlight_brightness(h_cfg.backlight, 1000);
msleep(500);
btn_wait();
goto out_free;
}
sdmmc_storage_end(&emmc_storage);
reboot_to_sept((u8 *)pkg1 + pkg1_id->tsec_off, pkg1_id->kb, cfg_sec);
}
out_free:
free(pkg1);
sdmmc_storage_end(&storage);
sdmmc_storage_end(&emmc_storage);
}
int reboot_to_sept(const u8 *tsec_fw, u32 kb, ini_sec_t *cfg_sec)

View File

@@ -20,6 +20,6 @@
#include <utils/types.h>
void check_sept(ini_sec_t *cfg_sec);
int reboot_to_sept(const u8 *tsec_fw, u32 kb, ini_sec_t *cfg_sec);
int reboot_to_sept(const u8 *tsec_fw, u32 kb, ini_sec_t *cfg_sec);
#endif

View File

@@ -41,16 +41,25 @@
#define FF_USE_MKFS 0
/* This option switches f_mkfs() function. (0:Disable or 1:Enable) */
#if FF_USE_MKFS
#define FF_MKFS_LABEL "SWITCH SD "
#endif
/* This sets FAT/FAT32 label. Exactly 11 characters, all caps. */
#define FF_USE_FASTSEEK 0
/* This option switches fast seek function. (0:Disable or 1:Enable) */
#define FF_FASTFS 0
#if FF_FASTFS
#undef FF_USE_FASTSEEK
#define FF_USE_FASTSEEK 1
#endif
/* This option switches fast access to chained clusters. (0:Disable or 1:Enable) */
#define FF_SIMPLE_GPT 1
/* This option switches support for the first GPT partition. (0:Disable or 1:Enable) */
#define FF_USE_EXPAND 0
@@ -185,6 +194,7 @@
/ not defined, a user defined volume string table needs to be defined as:
/
/ const char* VolumeStr[FF_VOLUMES] = {"ram","flash","sd","usb",...
/ Order is important. Any change to order, must also be reflected to diskio drive enum.
*/
@@ -246,7 +256,7 @@
#define FF_FS_NORTC 1
#define FF_NORTC_MON 1
#define FF_NORTC_MDAY 1
#define FF_NORTC_YEAR 2020
#define FF_NORTC_YEAR 2021
/* The option FF_FS_NORTC switches timestamp function. If the system does not have
/ any RTC function or valid timestamp is not needed, set FF_FS_NORTC = 1 to disable
/ the timestamp function. Every object modified by FatFs will have a fixed timestamp

View File

@@ -1,7 +1,7 @@
/*
* Copyright (c) 2018 naehrwert
*
* Copyright (c) 2018-2020 CTCaer
* Copyright (c) 2018-2021 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
@@ -73,8 +73,6 @@ volatile nyx_storage_t *nyx_str = (nyx_storage_t *)NYX_STORAGE_ADDR;
void emmcsn_path_impl(char *path, char *sub_dir, char *filename, sdmmc_storage_t *storage)
{
sdmmc_storage_t storage2;
sdmmc_t sdmmc;
char emmcSN[9];
bool init_done = false;
@@ -83,12 +81,12 @@ void emmcsn_path_impl(char *path, char *sub_dir, char *filename, sdmmc_storage_t
if (!storage)
{
if (!sdmmc_storage_init_mmc(&storage2, &sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400))
if (!sdmmc_storage_init_mmc(&emmc_storage, &emmc_sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400))
memcpy(emmcSN, "00000000", 9);
else
{
init_done = true;
itoa(storage2.cid.serial, emmcSN, 16);
itoa(emmc_storage.cid.serial, emmcSN, 16);
}
}
else
@@ -107,7 +105,7 @@ void emmcsn_path_impl(char *path, char *sub_dir, char *filename, sdmmc_storage_t
memcpy(path + strlen(path), filename, filename_len + 1);
if (init_done)
sdmmc_storage_end(&storage2);
sdmmc_storage_end(&emmc_storage);
}
void check_power_off_from_hos()
@@ -644,12 +642,8 @@ void launch_firmware()
if (!cfg_sec)
{
gfx_puts("\nUsing default launch configuration...\n");
gfx_puts("\nPress POWER to Continue.\nPress VOL to go to the menu.");
u32 btn = btn_wait();
if (!(btn & BTN_POWER))
goto out;
gfx_printf("\nPress any key...\n");
goto out;
}
if (payload_path)
@@ -706,7 +700,7 @@ void nyx_load_run()
gfx_con_setpos(0, 0);
WPRINTF("Old Nyx GUI found! There will be dragons!\n");
WPRINTF("\nUpdate your bootloader folder!\n\n");
WPRINTF("\nUpdate the bootloader folder!\n\n");
WPRINTF("Press any key...");
msleep(1000);
@@ -720,15 +714,11 @@ void nyx_load_run()
nyx_str->cfg = 0;
if (b_cfg.extra_cfg)
{
if (b_cfg.extra_cfg & EXTRA_CFG_NYX_DUMP)
if (b_cfg.extra_cfg & EXTRA_CFG_NYX_SEPT)
{
b_cfg.extra_cfg &= ~(EXTRA_CFG_NYX_DUMP);
nyx_str->cfg |= NYX_CFG_DUMP;
}
if (b_cfg.extra_cfg & EXTRA_CFG_NYX_BIS)
{
b_cfg.extra_cfg &= ~(EXTRA_CFG_NYX_BIS);
nyx_str->cfg |= NYX_CFG_BIS;
b_cfg.extra_cfg &= ~(EXTRA_CFG_NYX_SEPT);
nyx_str->cfg |= NYX_CFG_SEPT;
nyx_str->cfg |= b_cfg.sept << 24;
}
if (b_cfg.extra_cfg & EXTRA_CFG_NYX_UMS)
{
@@ -808,7 +798,7 @@ static void _bootloader_corruption_protect()
static void _auto_launch_firmware()
{
if(b_cfg.extra_cfg & (EXTRA_CFG_NYX_DUMP | EXTRA_CFG_NYX_BIS))
if(b_cfg.extra_cfg & EXTRA_CFG_NYX_SEPT)
{
if (!h_cfg.sept_run)
EMC(EMC_SCRATCH0) |= EMC_HEKA_UPD;
@@ -1120,18 +1110,15 @@ out:
static void _patched_rcm_protection()
{
sdmmc_storage_t storage;
sdmmc_t sdmmc;
if (!h_cfg.rcm_patched || hw_get_chip_id() == GP_HIDREV_MAJOR_T210B01)
return;
// Check if AutoRCM is enabled and protect from a permanent brick.
if (!sdmmc_storage_init_mmc(&storage, &sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400))
if (!sdmmc_storage_init_mmc(&emmc_storage, &emmc_sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400))
return;
u8 *buf = (u8 *)malloc(0x200);
sdmmc_storage_set_mmc_partition(&storage, EMMC_BOOT0);
sdmmc_storage_set_mmc_partition(&emmc_storage, EMMC_BOOT0);
u32 sector;
u8 corr_mod0, mod1;
@@ -1143,7 +1130,7 @@ static void _patched_rcm_protection()
for (u32 i = 0; i < 4; i++)
{
sector = 1 + (32 * i); // 0x4000 bct + 0x200 offset.
sdmmc_storage_read(&storage, sector, 1, buf);
sdmmc_storage_read(&emmc_storage, sector, 1, buf);
// Check if 2nd byte of modulus is correct.
if (buf[0x11] != mod1)
@@ -1154,12 +1141,12 @@ static void _patched_rcm_protection()
{
buf[0x10] = corr_mod0;
sdmmc_storage_write(&storage, sector, 1, buf);
sdmmc_storage_write(&emmc_storage, sector, 1, buf);
}
}
free(buf);
sdmmc_storage_end(&storage);
sdmmc_storage_end(&emmc_storage);
}
#define EXCP_EN_ADDR 0x4003FFFC
@@ -1513,15 +1500,15 @@ ment_t ment_top[] = {
MDEF_MENU("Console info", &menu_cinfo),
MDEF_CAPTION("---------------", 0xFF444444),
MDEF_HANDLER("Reload", ipl_reload),
MDEF_HANDLER_EX("Reboot (Normal)", &STATE_REBOOT_BYPASS_FUSES, power_set_state_ex),
MDEF_HANDLER_EX("Reboot (RCM)", &STATE_REBOOT_RCM, power_set_state_ex),
MDEF_HANDLER_EX("Power off", &STATE_POWER_OFF, power_set_state_ex),
MDEF_HANDLER_EX("Reboot (OFW)", &STATE_REBOOT_BYPASS_FUSES, power_set_state_ex),
MDEF_HANDLER_EX("Reboot (RCM)", &STATE_REBOOT_RCM, power_set_state_ex),
MDEF_HANDLER_EX("Power off", &STATE_POWER_OFF, power_set_state_ex),
MDEF_CAPTION("---------------", 0xFF444444),
MDEF_HANDLER("About", _about),
MDEF_END()
};
menu_t menu_top = { ment_top, "hekate - CTCaer mod v5.5.2", 0, 0 };
menu_t menu_top = { ment_top, "hekate - CTCaer mod v5.5.4", 0, 0 };
extern void pivot_stack(u32 stack_top);

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2019 CTCaer
* Copyright (c) 2019-2021 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
@@ -131,13 +131,13 @@ static int emummc_raw_get_part_off(int part_idx)
return 2;
}
int emummc_storage_init_mmc(sdmmc_storage_t *storage, sdmmc_t *sdmmc)
int emummc_storage_init_mmc()
{
FILINFO fno;
emu_cfg.active_part = 0;
// 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))
if (!sdmmc_storage_init_mmc(&emmc_storage, &emmc_sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400))
return 2;
if (!emu_cfg.enabled || h_cfg.emummc_force_disable)
@@ -173,21 +173,21 @@ out:
return 1;
}
int emummc_storage_end(sdmmc_storage_t *storage)
int emummc_storage_end()
{
if (!emu_cfg.enabled || h_cfg.emummc_force_disable)
sdmmc_storage_end(storage);
sdmmc_storage_end(&emmc_storage);
else
sd_end();
return 1;
}
int emummc_storage_read(sdmmc_storage_t *storage, u32 sector, u32 num_sectors, void *buf)
int emummc_storage_read(u32 sector, u32 num_sectors, void *buf)
{
FIL fp;
if (!emu_cfg.enabled || h_cfg.emummc_force_disable)
return sdmmc_storage_read(storage, sector, num_sectors, buf);
return sdmmc_storage_read(&emmc_storage, sector, num_sectors, buf);
else if (emu_cfg.sector)
{
sector += emu_cfg.sector;
@@ -228,11 +228,11 @@ int emummc_storage_read(sdmmc_storage_t *storage, u32 sector, u32 num_sectors, v
return 1;
}
int emummc_storage_write(sdmmc_storage_t *storage, u32 sector, u32 num_sectors, void *buf)
int emummc_storage_write(u32 sector, u32 num_sectors, void *buf)
{
FIL fp;
if (!emu_cfg.enabled || h_cfg.emummc_force_disable)
return sdmmc_storage_write(storage, sector, num_sectors, buf);
return sdmmc_storage_write(&emmc_storage, sector, num_sectors, buf);
else if (emu_cfg.sector)
{
sector += emu_cfg.sector;
@@ -253,15 +253,13 @@ int emummc_storage_write(sdmmc_storage_t *storage, u32 sector, u32 num_sectors,
itoa(file_part, emu_cfg.emummc_file_based_path + strlen(emu_cfg.emummc_file_based_path) - 1, 10);
}
}
if (f_open(&fp, emu_cfg.emummc_file_based_path, FA_WRITE))
{
gfx_printf("e5\n");
return 0;
}
f_lseek(&fp, (u64)sector << 9);
if (f_write(&fp, buf, (u64)num_sectors << 9, NULL))
{
gfx_printf("e6\n");
f_close(&fp);
return 0;
}
@@ -271,13 +269,12 @@ int emummc_storage_write(sdmmc_storage_t *storage, u32 sector, u32 num_sectors,
}
}
int emummc_storage_set_mmc_partition(sdmmc_storage_t *storage, u32 partition)
int emummc_storage_set_mmc_partition(u32 partition)
{
emu_cfg.active_part = partition;
sdmmc_storage_set_mmc_partition(&emmc_storage, partition);
if (!emu_cfg.enabled || h_cfg.emummc_force_disable)
sdmmc_storage_set_mmc_partition(storage, partition);
else if (emu_cfg.sector)
if (!emu_cfg.enabled || h_cfg.emummc_force_disable || emu_cfg.sector)
return 1;
else
{

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2019 CTCaer
* Copyright (c) 2019-2021 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
@@ -51,10 +51,10 @@ extern emummc_cfg_t emu_cfg;
void emummc_load_cfg();
bool emummc_set_path(char *path);
int emummc_storage_init_mmc(sdmmc_storage_t *storage, sdmmc_t *sdmmc);
int emummc_storage_end(sdmmc_storage_t *storage);
int emummc_storage_read(sdmmc_storage_t *storage, u32 sector, u32 num_sectors, void *buf);
int emummc_storage_write(sdmmc_storage_t *storage, u32 sector, u32 num_sectors, void *buf);
int emummc_storage_set_mmc_partition(sdmmc_storage_t *storage, u32 partition);
int emummc_storage_init_mmc();
int emummc_storage_end();
int emummc_storage_read(u32 sector, u32 num_sectors, void *buf);
int emummc_storage_write(u32 sector, u32 num_sectors, void *buf);
int emummc_storage_set_mmc_partition(u32 partition);
#endif

View File

@@ -1,6 +1,6 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2019-2020 CTCaer
* Copyright (c) 2019-2021 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
@@ -32,7 +32,7 @@ void nx_emmc_gpt_parse(link_t *gpt, sdmmc_storage_t *storage)
{
gpt_t *gpt_buf = (gpt_t *)calloc(NX_GPT_NUM_BLOCKS, NX_EMMC_BLOCKSIZE);
emummc_storage_read(storage, NX_GPT_FIRST_LBA, NX_GPT_NUM_BLOCKS, gpt_buf);
emummc_storage_read(NX_GPT_FIRST_LBA, NX_GPT_NUM_BLOCKS, gpt_buf);
for (u32 i = 0; i < gpt_buf->header.num_part_ents; i++)
{
@@ -78,7 +78,7 @@ int nx_emmc_part_read(sdmmc_storage_t *storage, emmc_part_t *part, u32 sector_of
if (part->lba_start + sector_off > part->lba_end)
return 0;
return emummc_storage_read(storage, part->lba_start + sector_off, num_sectors, buf);
return emummc_storage_read(part->lba_start + sector_off, num_sectors, buf);
}
int nx_emmc_part_write(sdmmc_storage_t *storage, emmc_part_t *part, u32 sector_off, u32 num_sectors, void *buf)
@@ -87,7 +87,7 @@ int nx_emmc_part_write(sdmmc_storage_t *storage, emmc_part_t *part, u32 sector_o
if (part->lba_start + sector_off > part->lba_end)
return 0;
return sdmmc_storage_write(storage, part->lba_start + sector_off, num_sectors, buf);
return emummc_storage_write(part->lba_start + sector_off, num_sectors, buf);
}
void nx_emmc_get_autorcm_masks(u8 *mod0, u8 *mod1)

View File

@@ -180,6 +180,11 @@ static void _sd_deinit()
void sd_unmount() { _sd_deinit(); }
void sd_end() { _sd_deinit(); }
bool sd_is_gpt()
{
return sd_fs.part_type;
}
void *sd_file_read(const char *path, u32 *fsize)
{
FIL fp;

View File

@@ -73,7 +73,8 @@ void loader_main()
CLOCK(CLK_RST_CONTROLLER_SCLK_BURST_POLICY) = 0x20003333; // Set SCLK to PLLP_OUT (408MHz).
// Get Loader and Payload size.
u32 payload_size = sizeof(payload_00) + sizeof(payload_01);
u32 payload_size = sizeof(payload_00) + sizeof(payload_01); // Actual payload size.
payload_size += (u32)payload_01 - (u32)payload_00 - sizeof(payload_00); // Add array alignment.
u32 *payload_addr = (u32 *)payload_00;
// Relocate payload to a safer place.
@@ -88,16 +89,20 @@ void loader_main()
bytes--;
}
// Uncompress payload parts.
// Set source address of the first part.
u8 *src_addr = (void *)(IPL_RELOC_TOP - ALIGN(payload_size, 4));
u32 pos = LZ_Uncompress((const u8 *)src_addr, (u8*)IPL_LOAD_ADDR, sizeof(payload_00));
src_addr += (u32)payload_01 - (u32)payload_00;
LZ_Uncompress((const u8 *)src_addr, (u8*)IPL_LOAD_ADDR + pos, sizeof(payload_01));
// Uncompress first part.
u32 dst_pos = LZ_Uncompress((const u8 *)src_addr, (u8*)IPL_LOAD_ADDR, sizeof(payload_00));
// Copy over boot configuration storage in case it was set.
// Set source address of the second part. Includes array alignment.
src_addr += (u32)payload_01 - (u32)payload_00;
// Uncompress second part.
LZ_Uncompress((const u8 *)src_addr, (u8*)IPL_LOAD_ADDR + dst_pos, sizeof(payload_01));
// Copy over boot configuration storage.
memcpy((u8 *)(IPL_LOAD_ADDR + IPL_PATCHED_RELOC_SZ), &b_cfg, sizeof(boot_cfg_t));
// Chainload.
// Chainload into uncompressed payload.
void (*ipl_ptr)() = (void *)IPL_LOAD_ADDR;
(*ipl_ptr)();

View File

@@ -1,7 +1,7 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018 Rajko Stojadinovic
* Copyright (c) 2018-2020 CTCaer
* Copyright (c) 2018-2021 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
@@ -41,7 +41,6 @@
#define NUM_SECTORS_PER_ITER 8192 // 4MB Cache.
#define OUT_FILENAME_SZ 128
#define HASH_FILENAME_SZ (OUT_FILENAME_SZ + 11) // 11 == strlen(".sha256sums")
#define SHA256_SZ 0x20
extern nyx_config n_cfg;
@@ -156,8 +155,8 @@ static int _dump_emmc_verify(emmc_tool_gui_t *gui, sdmmc_storage_t *storage, u32
const char hexa[] = "0123456789abcdef";
DWORD *clmt = NULL;
u8 hashEm[SHA256_SZ];
u8 hashSd[SHA256_SZ];
u8 hashEm[SE_SHA_256_SIZE];
u8 hashSd[SE_SHA_256_SIZE];
if (f_open(&fp, outFilename, FA_READ) == FR_OK)
{
@@ -254,7 +253,7 @@ static int _dump_emmc_verify(emmc_tool_gui_t *gui, sdmmc_storage_t *storage, u32
manual_system_maintenance(false);
se_calc_sha256_finalize(hashEm, NULL);
se_calc_sha256_oneshot(hashSd, bufSd, num << 9);
res = memcmp(hashEm, hashSd, 0x10);
res = memcmp(hashEm, hashSd, SE_SHA_256_SIZE / 2);
if (res)
{
@@ -276,14 +275,14 @@ static int _dump_emmc_verify(emmc_tool_gui_t *gui, sdmmc_storage_t *storage, u32
if (n_cfg.verification == 3)
{
// Transform computed hash to readable hexadecimal
char hashStr[SHA256_SZ * 2 + 1];
char hashStr[SE_SHA_256_SIZE * 2 + 1];
char *hashStrPtr = hashStr;
for (int i = 0; i < SHA256_SZ; i++)
for (int i = 0; i < SE_SHA_256_SIZE; i++)
{
*(hashStrPtr++) = hexa[hashSd[i] >> 4];
*(hashStrPtr++) = hexa[hashSd[i] & 0x0F];
}
hashStr[SHA256_SZ * 2] = '\0';
hashStr[SE_SHA_256_SIZE * 2] = '\0';
f_puts(hashStr, &hashFp);
f_puts("\n", &hashFp);
@@ -771,9 +770,7 @@ void dump_emmc_selected(emmcPartType_t dumpType, emmc_tool_gui_t *gui)
// Get SD Card free space for Partial Backup.
f_getfree("", &sd_fs.free_clst, NULL);
sdmmc_storage_t storage;
sdmmc_t sdmmc;
if (!sdmmc_storage_init_mmc(&storage, &sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400))
if (!sdmmc_storage_init_mmc(&emmc_storage, &emmc_sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400))
{
lv_label_set_text(gui->label_info, "#FFDD00 Failed to init eMMC!#");
goto out;
@@ -782,16 +779,16 @@ void dump_emmc_selected(emmcPartType_t dumpType, emmc_tool_gui_t *gui)
int i = 0;
char sdPath[OUT_FILENAME_SZ];
// Create Restore folders, if they do not exist.
emmcsn_path_impl(sdPath, "/restore", "", &storage);
emmcsn_path_impl(sdPath, "/restore/partitions", "", &storage);
emmcsn_path_impl(sdPath, "", "", &storage);
emmcsn_path_impl(sdPath, "/restore", "", &emmc_storage);
emmcsn_path_impl(sdPath, "/restore/partitions", "", &emmc_storage);
emmcsn_path_impl(sdPath, "", "", &emmc_storage);
gui->base_path = (char *)malloc(strlen(sdPath) + 1);
strcpy(gui->base_path, sdPath);
timer = get_tmr_s();
if (dumpType & PART_BOOT)
{
const u32 BOOT_PART_SIZE = storage.ext_csd.boot_mult << 17;
const u32 BOOT_PART_SIZE = emmc_storage.ext_csd.boot_mult << 17;
emmc_part_t bootPart;
memset(&bootPart, 0, sizeof(bootPart));
@@ -810,10 +807,10 @@ void dump_emmc_selected(emmcPartType_t dumpType, emmc_tool_gui_t *gui)
lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, txt_buf);
manual_system_maintenance(true);
sdmmc_storage_set_mmc_partition(&storage, i + 1);
sdmmc_storage_set_mmc_partition(&emmc_storage, i + 1);
emmcsn_path_impl(sdPath, "", bootPart.name, &storage);
res = _dump_emmc_part(gui, sdPath, i, &storage, &bootPart);
emmcsn_path_impl(sdPath, "", bootPart.name, &emmc_storage);
res = _dump_emmc_part(gui, sdPath, i, &emmc_storage, &bootPart);
if (!res)
s_printf(txt_buf, "#FFDD00 Failed!#\n");
@@ -827,16 +824,16 @@ void dump_emmc_selected(emmcPartType_t dumpType, emmc_tool_gui_t *gui)
if ((dumpType & PART_SYSTEM) || (dumpType & PART_USER) || (dumpType & PART_RAW))
{
sdmmc_storage_set_mmc_partition(&storage, EMMC_GPP);
sdmmc_storage_set_mmc_partition(&emmc_storage, EMMC_GPP);
if ((dumpType & PART_SYSTEM) || (dumpType & PART_USER))
{
emmcsn_path_impl(sdPath, "/partitions", "", &storage);
emmcsn_path_impl(sdPath, "/partitions", "", &emmc_storage);
gui->base_path = (char *)malloc(strlen(sdPath) + 1);
strcpy(gui->base_path, sdPath);
LIST_INIT(gpt);
nx_emmc_gpt_parse(&gpt, &storage);
nx_emmc_gpt_parse(&gpt, &emmc_storage);
LIST_FOREACH_ENTRY(emmc_part_t, part, &gpt, link)
{
if ((dumpType & PART_USER) == 0 && !strcmp(part->name, "USER"))
@@ -852,8 +849,8 @@ void dump_emmc_selected(emmcPartType_t dumpType, emmc_tool_gui_t *gui)
manual_system_maintenance(true);
i++;
emmcsn_path_impl(sdPath, "/partitions", part->name, &storage);
res = _dump_emmc_part(gui, sdPath, 0, &storage, part);
emmcsn_path_impl(sdPath, "/partitions", part->name, &emmc_storage);
res = _dump_emmc_part(gui, sdPath, 0, &emmc_storage, part);
// If a part failed, don't continue.
if (!res)
{
@@ -873,7 +870,7 @@ void dump_emmc_selected(emmcPartType_t dumpType, emmc_tool_gui_t *gui)
if (dumpType & PART_RAW)
{
// Get GP partition size dynamically.
const u32 RAW_AREA_NUM_SECTORS = storage.sec_cnt;
const u32 RAW_AREA_NUM_SECTORS = emmc_storage.sec_cnt;
emmc_part_t rawPart;
memset(&rawPart, 0, sizeof(rawPart));
@@ -890,8 +887,8 @@ void dump_emmc_selected(emmcPartType_t dumpType, emmc_tool_gui_t *gui)
i++;
emmcsn_path_impl(sdPath, "", rawPart.name, &storage);
res = _dump_emmc_part(gui, sdPath, 2, &storage, &rawPart);
emmcsn_path_impl(sdPath, "", rawPart.name, &emmc_storage);
res = _dump_emmc_part(gui, sdPath, 2, &emmc_storage, &rawPart);
if (!res)
s_printf(txt_buf, "#FFDD00 Failed!#\n");
@@ -905,7 +902,7 @@ void dump_emmc_selected(emmcPartType_t dumpType, emmc_tool_gui_t *gui)
}
timer = get_tmr_s() - timer;
sdmmc_storage_end(&storage);
sdmmc_storage_end(&emmc_storage);
if (res && n_cfg.verification && !gui->raw_emummc)
s_printf(txt_buf, "Time taken: %dm %ds.\n#96FF00 Finished and verified!#", timer / 60, timer % 60);
@@ -1023,7 +1020,7 @@ static int _restore_emmc_part(emmc_tool_gui_t *gui, char *sd_path, int active_pa
{
lv_obj_t *warn_mbox_bg = create_mbox_text(
"#FF8000 Size of SD Card split backup does not match,#\n#FF8000 eMMC's selected part size!#\n\n"
"#FFDD00 Your backup might be corrupted!#\n#FFDD00 Aborting is suggested!#\n\n"
"#FFDD00 The backup might be corrupted!#\n#FFDD00 Aborting is suggested!#\n\n"
"Press #FF8000 POWER# to Continue.\nPress #FF8000 VOL# to abort.", false);
manual_system_maintenance(true);
@@ -1085,7 +1082,7 @@ static int _restore_emmc_part(emmc_tool_gui_t *gui, char *sd_path, int active_pa
{
lv_obj_t *warn_mbox_bg = create_mbox_text(
"#FF8000 Size of the SD Card backup does not match,#\n#FF8000 eMMC's selected part size!#\n\n"
"#FFDD00 Your backup might be corrupted!#\n#FFDD00 Aborting is suggested!#\n\n"
"#FFDD00 The backup might be corrupted!#\n#FFDD00 Aborting is suggested!#\n\n"
"Press #FF8000 POWER# to Continue.\nPress #FF8000 VOL# to abort.", false);
manual_system_maintenance(true);
@@ -1134,7 +1131,7 @@ static int _restore_emmc_part(emmc_tool_gui_t *gui, char *sd_path, int active_pa
_get_valid_partition(&sector_start, &sector_size, &part_idx, false);
if (!part_idx || !sector_size)
{
s_printf(gui->txt_buf, "#FFDD00 Failed to find a partition...#\n");
s_printf(gui->txt_buf, "\n#FFDD00 Failed to find a partition...#\n");
lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf);
manual_system_maintenance(true);
@@ -1161,7 +1158,7 @@ static int _restore_emmc_part(emmc_tool_gui_t *gui, char *sd_path, int active_pa
// Verify part.
if (_dump_emmc_verify(gui, storage, lbaStartPart, outFilename, part))
{
s_printf(gui->txt_buf, "#FFDD00 Please try again...#\n");
s_printf(gui->txt_buf, "\n#FFDD00 Please try again...#\n");
lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf);
manual_system_maintenance(true);
@@ -1185,7 +1182,7 @@ static int _restore_emmc_part(emmc_tool_gui_t *gui, char *sd_path, int active_pa
res = f_open(&fp, outFilename, FA_READ);
if (res)
{
s_printf(gui->txt_buf, "#FF0000 Error (%d) while opening file#\n#FFDD00 %s!#\n", res, outFilename);
s_printf(gui->txt_buf, "\n#FF0000 Error (%d) while opening file#\n#FFDD00 %s!#\n", res, outFilename);
lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf);
manual_system_maintenance(true);
@@ -1206,7 +1203,7 @@ static int _restore_emmc_part(emmc_tool_gui_t *gui, char *sd_path, int active_pa
{
s_printf(gui->txt_buf,
"\n#FF0000 Fatal error (%d) when reading from SD!#\n"
"#FF0000 Your device may be in an inoperative state!#\n"
"#FF0000 This device may be in an inoperative state!#\n"
"#FFDD00 Please try again now!#\n", res);
lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf);
manual_system_maintenance(true);
@@ -1225,8 +1222,8 @@ static int _restore_emmc_part(emmc_tool_gui_t *gui, char *sd_path, int active_pa
while (res)
{
s_printf(gui->txt_buf,
"#FFDD00 Error reading %d blocks @ LBA %08X,#\n"
"#FFDD00 from eMMC (try %d). #",
"\n#FFDD00 Error reading %d blocks @ LBA %08X,#\n"
"#FFDD00 from eMMC (try %d).\n#",
num, lba_curr, ++retryCount);
lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf);
manual_system_maintenance(true);
@@ -1235,7 +1232,7 @@ static int _restore_emmc_part(emmc_tool_gui_t *gui, char *sd_path, int active_pa
if (retryCount >= 3)
{
s_printf(gui->txt_buf, "#FF0000 Aborting...#\n"
"#FF0000 Your device may be in an inoperative state!#\n"
"#FF0000 This device may be in an inoperative state!#\n"
"#FFDD00 Please try again now!#\n");
lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf);
manual_system_maintenance(true);
@@ -1328,7 +1325,7 @@ void restore_emmc_selected(emmcPartType_t restoreType, emmc_tool_gui_t *gui)
manual_system_maintenance(true);
s_printf(txt_buf,
"#FFDD00 This may render your device inoperative!#\n\n"
"#FFDD00 This may render the device inoperative!#\n\n"
"#FFDD00 Are you really sure?#");
if ((restoreType & PART_BOOT) || (restoreType & PART_GP_ALL))
{
@@ -1371,9 +1368,7 @@ void restore_emmc_selected(emmcPartType_t restoreType, emmc_tool_gui_t *gui)
goto out;
}
sdmmc_storage_t storage;
sdmmc_t sdmmc;
if (!sdmmc_storage_init_mmc(&storage, &sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400))
if (!sdmmc_storage_init_mmc(&emmc_storage, &emmc_sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400))
{
lv_label_set_text(gui->label_info, "#FFDD00 Failed to init eMMC!#");
goto out;
@@ -1382,14 +1377,14 @@ void restore_emmc_selected(emmcPartType_t restoreType, emmc_tool_gui_t *gui)
int i = 0;
char sdPath[OUT_FILENAME_SZ];
emmcsn_path_impl(sdPath, "/restore", "", &storage);
emmcsn_path_impl(sdPath, "/restore", "", &emmc_storage);
gui->base_path = (char *)malloc(strlen(sdPath) + 1);
strcpy(gui->base_path, sdPath);
timer = get_tmr_s();
if (restoreType & PART_BOOT)
{
const u32 BOOT_PART_SIZE = storage.ext_csd.boot_mult << 17;
const u32 BOOT_PART_SIZE = emmc_storage.ext_csd.boot_mult << 17;
emmc_part_t bootPart;
memset(&bootPart, 0, sizeof(bootPart));
@@ -1408,10 +1403,10 @@ void restore_emmc_selected(emmcPartType_t restoreType, emmc_tool_gui_t *gui)
lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, txt_buf);
manual_system_maintenance(true);
sdmmc_storage_set_mmc_partition(&storage, i + 1);
sdmmc_storage_set_mmc_partition(&emmc_storage, i + 1);
emmcsn_path_impl(sdPath, "/restore", bootPart.name, &storage);
res = _restore_emmc_part(gui, sdPath, i, &storage, &bootPart, false);
emmcsn_path_impl(sdPath, "/restore", bootPart.name, &emmc_storage);
res = _restore_emmc_part(gui, sdPath, i, &emmc_storage, &bootPart, false);
if (!res)
s_printf(txt_buf, "#FFDD00 Failed!#\n");
@@ -1425,14 +1420,14 @@ void restore_emmc_selected(emmcPartType_t restoreType, emmc_tool_gui_t *gui)
if (restoreType & PART_GP_ALL)
{
emmcsn_path_impl(sdPath, "/restore/partitions", "", &storage);
emmcsn_path_impl(sdPath, "/restore/partitions", "", &emmc_storage);
gui->base_path = (char *)malloc(strlen(sdPath) + 1);
strcpy(gui->base_path, sdPath);
sdmmc_storage_set_mmc_partition(&storage, EMMC_GPP);
sdmmc_storage_set_mmc_partition(&emmc_storage, EMMC_GPP);
LIST_INIT(gpt);
nx_emmc_gpt_parse(&gpt, &storage);
nx_emmc_gpt_parse(&gpt, &emmc_storage);
LIST_FOREACH_ENTRY(emmc_part_t, part, &gpt, link)
{
s_printf(txt_buf, "#00DDFF %02d: %s#\n#00DDFF Range: 0x%08X - 0x%08X#\n\n\n\n\n",
@@ -1443,8 +1438,8 @@ void restore_emmc_selected(emmcPartType_t restoreType, emmc_tool_gui_t *gui)
manual_system_maintenance(true);
i++;
emmcsn_path_impl(sdPath, "/restore/partitions", part->name, &storage);
res = _restore_emmc_part(gui, sdPath, 0, &storage, part, false);
emmcsn_path_impl(sdPath, "/restore/partitions", part->name, &emmc_storage);
res = _restore_emmc_part(gui, sdPath, 0, &emmc_storage, part, false);
if (!res)
s_printf(txt_buf, "#FFDD00 Failed!#\n");
@@ -1460,7 +1455,7 @@ void restore_emmc_selected(emmcPartType_t restoreType, emmc_tool_gui_t *gui)
if (restoreType & PART_RAW)
{
// Get GP partition size dynamically.
const u32 RAW_AREA_NUM_SECTORS = storage.sec_cnt;
const u32 RAW_AREA_NUM_SECTORS = emmc_storage.sec_cnt;
emmc_part_t rawPart;
memset(&rawPart, 0, sizeof(rawPart));
@@ -1476,8 +1471,8 @@ void restore_emmc_selected(emmcPartType_t restoreType, emmc_tool_gui_t *gui)
manual_system_maintenance(true);
i++;
emmcsn_path_impl(sdPath, "/restore", rawPart.name, &storage);
res = _restore_emmc_part(gui, sdPath, 2, &storage, &rawPart, true);
emmcsn_path_impl(sdPath, "/restore", rawPart.name, &emmc_storage);
res = _restore_emmc_part(gui, sdPath, 2, &emmc_storage, &rawPart, true);
if (!res)
s_printf(txt_buf, "#FFDD00 Failed!#\n");
@@ -1490,7 +1485,7 @@ void restore_emmc_selected(emmcPartType_t restoreType, emmc_tool_gui_t *gui)
}
timer = get_tmr_s() - timer;
sdmmc_storage_end(&storage);
sdmmc_storage_end(&emmc_storage);
if (res && n_cfg.verification && !gui->raw_emummc)
s_printf(txt_buf, "Time taken: %dm %ds.\n#96FF00 Finished and verified!#", timer / 60, timer % 60);

View File

@@ -1,7 +1,7 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018 Rajko Stojadinovic
* Copyright (c) 2018-2020 CTCaer
* Copyright (c) 2018-2021 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
@@ -23,13 +23,16 @@
#include "gui.h"
#include "fe_emummc_tools.h"
#include "../hos/sept.h"
#include "../config.h"
#include <utils/ini.h>
#include <libs/fatfs/diskio.h>
#include <libs/fatfs/ff.h>
#include <mem/heap.h>
#include <sec/se.h>
#include <storage/mbr_gpt.h>
#include "../storage/nx_emmc.h"
#include "../storage/nx_emmc_bis.h"
#include <storage/nx_sd.h>
#include <storage/sdmmc.h>
#include <utils/btn.h>
@@ -40,6 +43,7 @@
#define OUT_FILENAME_SZ 128
extern hekate_config h_cfg;
extern volatile boot_cfg_t *b_cfg;
void load_emummc_cfg(emummc_cfg_t *emu_info)
{
@@ -228,7 +232,7 @@ static int _dump_emummc_file_part(emmc_tool_gui_t *gui, char *sd_path, sdmmc_sto
res = f_open(&fp, outFilename, FA_CREATE_ALWAYS | FA_WRITE);
if (res)
{
s_printf(gui->txt_buf, "#FF0000 Error (%d) while creating#\n#FFDD00 %s#\n", res, outFilename);
s_printf(gui->txt_buf, "\n#FF0000 Error (%d) while creating#\n#FFDD00 %s#\n", res, outFilename);
lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf);
manual_system_maintenance(true);
@@ -244,7 +248,7 @@ static int _dump_emummc_file_part(emmc_tool_gui_t *gui, char *sd_path, sdmmc_sto
// Check for cancellation combo.
if (btn_read_vol() == (BTN_VOL_UP | BTN_VOL_DOWN))
{
s_printf(gui->txt_buf, "#FFDD00 The emuMMC was cancelled!#\n");
s_printf(gui->txt_buf, "\n#FFDD00 The emuMMC was cancelled!#\n");
lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf);
manual_system_maintenance(true);
@@ -262,7 +266,7 @@ static int _dump_emummc_file_part(emmc_tool_gui_t *gui, char *sd_path, sdmmc_sto
while (!sdmmc_storage_read(storage, lba_curr, num, buf))
{
s_printf(gui->txt_buf,
"#FFDD00 Error reading %d blocks @ LBA %08X,#\n"
"\n#FFDD00 Error reading %d blocks @ LBA %08X,#\n"
"#FFDD00 from eMMC (try %d). #",
num, lba_curr, ++retryCount);
lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf);
@@ -283,7 +287,7 @@ static int _dump_emummc_file_part(emmc_tool_gui_t *gui, char *sd_path, sdmmc_sto
}
else
{
s_printf(gui->txt_buf, "#FFDD00 Retrying...#\n");
s_printf(gui->txt_buf, "#FFDD00 Retrying...#");
lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf);
manual_system_maintenance(true);
}
@@ -349,6 +353,7 @@ void dump_emummc_file(emmc_tool_gui_t *gui)
u32 timer = 0;
char *txt_buf = (char *)malloc(0x4000);
gui->base_path = (char *)malloc(OUT_FILENAME_SZ);
gui->txt_buf = txt_buf;
s_printf(txt_buf, "");
@@ -368,9 +373,7 @@ void dump_emummc_file(emmc_tool_gui_t *gui)
// Get SD Card free space for Partial Backup.
f_getfree("", &sd_fs.free_clst, NULL);
sdmmc_storage_t storage;
sdmmc_t sdmmc;
if (!sdmmc_storage_init_mmc(&storage, &sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400))
if (!sdmmc_storage_init_mmc(&emmc_storage, &emmc_sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400))
{
lv_label_set_text(gui->label_info, "#FFDD00 Failed to init eMMC!#");
goto out;
@@ -382,7 +385,6 @@ void dump_emummc_file(emmc_tool_gui_t *gui)
f_mkdir("emuMMC");
strcpy(sdPath, "emuMMC/SD");
base_len = strlen(sdPath);
gui->base_path = (char *)malloc(OUT_FILENAME_SZ);
for (int j = 0; j < 100; j++)
{
@@ -398,7 +400,7 @@ void dump_emummc_file(emmc_tool_gui_t *gui)
strcpy(gui->base_path, sdPath);
timer = get_tmr_s();
const u32 BOOT_PART_SIZE = storage.ext_csd.boot_mult << 17;
const u32 BOOT_PART_SIZE = emmc_storage.ext_csd.boot_mult << 17;
emmc_part_t bootPart;
memset(&bootPart, 0, sizeof(bootPart));
@@ -417,10 +419,10 @@ void dump_emummc_file(emmc_tool_gui_t *gui)
lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, txt_buf);
manual_system_maintenance(true);
sdmmc_storage_set_mmc_partition(&storage, i + 1);
sdmmc_storage_set_mmc_partition(&emmc_storage, i + 1);
strcat(sdPath, bootPart.name);
res = _dump_emummc_file_part(gui, sdPath, &storage, &bootPart);
res = _dump_emummc_file_part(gui, sdPath, &emmc_storage, &bootPart);
if (!res)
{
@@ -437,10 +439,10 @@ void dump_emummc_file(emmc_tool_gui_t *gui)
}
// Get GP partition size dynamically.
sdmmc_storage_set_mmc_partition(&storage, EMMC_GPP);
sdmmc_storage_set_mmc_partition(&emmc_storage, EMMC_GPP);
// Get GP partition size dynamically.
const u32 RAW_AREA_NUM_SECTORS = storage.sec_cnt;
const u32 RAW_AREA_NUM_SECTORS = emmc_storage.sec_cnt;
emmc_part_t rawPart;
memset(&rawPart, 0, sizeof(rawPart));
@@ -455,7 +457,7 @@ void dump_emummc_file(emmc_tool_gui_t *gui)
lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, txt_buf);
manual_system_maintenance(true);
res = _dump_emummc_file_part(gui, sdPath, &storage, &rawPart);
res = _dump_emummc_file_part(gui, sdPath, &emmc_storage, &rawPart);
if (!res)
s_printf(txt_buf, "#FFDD00 Failed!#\n");
@@ -468,7 +470,7 @@ void dump_emummc_file(emmc_tool_gui_t *gui)
out_failed:
timer = get_tmr_s() - timer;
sdmmc_storage_end(&storage);
sdmmc_storage_end(&emmc_storage);
if (res)
{
@@ -494,9 +496,15 @@ out:
sd_unmount();
}
static int _dump_emummc_raw_part(emmc_tool_gui_t *gui, int active_part, int part_idx, u32 sd_part_off, sdmmc_storage_t *storage, emmc_part_t *part)
static int _dump_emummc_raw_part(emmc_tool_gui_t *gui, int active_part, int part_idx, u32 sd_part_off, sdmmc_storage_t *storage, emmc_part_t *part, u32 resized_count)
{
u32 totalSectors = part->lba_end - part->lba_start + 1;
u32 num = 0;
u32 pct = 0;
u32 prevPct = 200;
int retryCount = 0;
u32 sd_sector_off = sd_part_off + (0x2000 * active_part);
u32 lba_curr = part->lba_start;
u8 *buf = (u8 *)MIXD_BUF_ALIGNED;
s_printf(gui->txt_buf, "\n\n\n");
lv_label_ins_text(gui->label_info, LV_LABEL_POS_LAST, gui->txt_buf);
@@ -511,24 +519,38 @@ static int _dump_emummc_raw_part(emmc_tool_gui_t *gui, int active_part, int part
lv_label_ins_text(gui->label_info, LV_LABEL_POS_LAST, gui->txt_buf);
manual_system_maintenance(true);
u8 *buf = (u8 *)MIXD_BUF_ALIGNED;
u32 sd_sector_off = sd_part_off + (0x2000 * active_part);
u32 lba_curr = part->lba_start;
u32 prevPct = 200;
int retryCount = 0;
u32 num = 0;
u32 pct = 0;
lv_obj_set_opa_scale(gui->bar, LV_OPA_COVER);
lv_obj_set_opa_scale(gui->label_pct, LV_OPA_COVER);
u32 user_offset = 0;
if (resized_count)
{
// Get USER partition info.
LIST_INIT(gpt);
nx_emmc_gpt_parse(&gpt, storage);
emmc_part_t *user_part = nx_emmc_part_find(&gpt, "USER");
if (!user_part)
{
s_printf(gui->txt_buf, "\n#FFDD00 USER partition not found!#\n");
lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf);
manual_system_maintenance(true);
return 0;
}
user_offset = user_part->lba_start;
part->lba_end = user_offset - 1;
nx_emmc_gpt_free(&gpt);
}
u32 totalSectors = part->lba_end - part->lba_start + 1;
while (totalSectors > 0)
{
// Check for cancellation combo.
if (btn_read_vol() == (BTN_VOL_UP | BTN_VOL_DOWN))
{
s_printf(gui->txt_buf, "#FFDD00 The emuMMC was cancelled!#\n");
s_printf(gui->txt_buf, "\n#FFDD00 The emuMMC was cancelled!#\n");
lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf);
manual_system_maintenance(true);
@@ -618,25 +640,325 @@ static int _dump_emummc_raw_part(emmc_tool_gui_t *gui, int active_part, int part
lv_label_set_text(gui->label_pct, " "SYMBOL_DOT" 100%");
manual_system_maintenance(true);
// Hide the partition.
// Set partition type to emuMMC (0xE0).
if (active_part == 2)
{
mbr_t *mbr = (mbr_t *)malloc(sizeof(mbr_t));
sdmmc_storage_read(&sd_storage, 0, 1, mbr);
mbr->partitions[part_idx].type = 0xE0;
sdmmc_storage_write(&sd_storage, 0, 1, mbr);
free(mbr);
mbr_t mbr;
sdmmc_storage_read(&sd_storage, 0, 1, &mbr);
mbr.partitions[part_idx].type = 0xE0;
sdmmc_storage_write(&sd_storage, 0, 1, &mbr);
}
if (resized_count)
{
// Calculate USER size and set it for FatFS.
u32 user_sectors = resized_count - user_offset - 33;
disk_set_info(DRIVE_EMU, SET_SECTOR_COUNT, &user_sectors);
// Initialize BIS for emuMMC. BIS keys should be already in place.
emmc_part_t user_part = {0};
user_part.lba_start = user_offset;
user_part.lba_end = user_offset + user_sectors - 1;
strcpy(user_part.name, "USER");
nx_emmc_bis_init(&user_part, true, sd_sector_off);
s_printf(gui->txt_buf, "\nFormatting USER...\n");
lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf);
manual_system_maintenance(true);
// Format USER partition.
u8 *buf = malloc(0x400000);
int mkfs_error = f_mkfs("emu:", FM_FAT32 | FM_SFD | FM_PRF2, 16384, buf, 0x400000);
free(buf);
// Mount sd card back.
sd_mount();
if (mkfs_error)
{
s_printf(gui->txt_buf, "#FF0000 USER format failed (%d)...#\nPlease try again...\n", mkfs_error);
lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf);
return 0;
}
// Flush BIS cache, deinit, clear BIS keys slots and reinstate SBK.
nx_emmc_bis_end();
hos_bis_keys_clear();
s_printf(gui->txt_buf, "Writing new GPT...\n");
lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf);
manual_system_maintenance(true);
// Read MBR, GPT and backup GPT.
mbr_t mbr;
gpt_t gpt_main;
gpt_header_t gpt_hdr_backup;
sdmmc_storage_read(storage, 0, 1, &mbr);
sdmmc_storage_read(storage, 1, sizeof(gpt_t) >> 9, &gpt_main);
sdmmc_storage_read(storage, gpt_main.header.alt_lba, 1, &gpt_hdr_backup);
// Find USER partition.
u32 gpt_entry_idx = 0;
for (gpt_entry_idx = 0; gpt_entry_idx < gpt_main.header.num_part_ents; gpt_entry_idx++)
if (!memcmp(gpt_main.entries[gpt_entry_idx].name, (char[]) { 'U', 0, 'S', 0, 'E', 0, 'R', 0 }, 8))
break;
if (gpt_entry_idx >= gpt_main.header.num_part_ents)
{
s_printf(gui->txt_buf, "#FF0000 No USER partition...#\nPlease try again...\n");
lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf);
return 0;
}
// Set new emuMMC size and USER size.
mbr.partitions[0].size_sct = resized_count;
gpt_main.entries[gpt_entry_idx].lba_end = user_offset + user_sectors - 1;
// Update Main GPT.
gpt_main.header.alt_lba = resized_count - 1;
gpt_main.header.last_use_lba = resized_count - 34;
gpt_main.header.part_ents_crc32 = crc32_calc(0, (const u8 *)gpt_main.entries, sizeof(gpt_entry_t) * gpt_main.header.num_part_ents);
gpt_main.header.crc32 = 0; // Set to 0 for calculation.
gpt_main.header.crc32 = crc32_calc(0, (const u8 *)&gpt_main.header, gpt_main.header.size);
// Update Backup GPT.
gpt_hdr_backup.my_lba = resized_count - 1;
gpt_hdr_backup.part_ent_lba = resized_count - 33;
gpt_hdr_backup.part_ents_crc32 = gpt_main.header.part_ents_crc32;
gpt_hdr_backup.crc32 = 0; // Set to 0 for calculation.
gpt_hdr_backup.crc32 = crc32_calc(0, (const u8 *)&gpt_hdr_backup, gpt_hdr_backup.size);
// Write main GPT.
sdmmc_storage_write(&sd_storage, sd_sector_off + gpt_main.header.my_lba, sizeof(gpt_t) >> 9, &gpt_main);
// Write backup GPT partition table.
sdmmc_storage_write(&sd_storage, sd_sector_off + gpt_hdr_backup.part_ent_lba, ((sizeof(gpt_entry_t) * 128) >> 9), gpt_main.entries);
// Write backup GPT header.
sdmmc_storage_write(&sd_storage, sd_sector_off + gpt_hdr_backup.my_lba, 1, &gpt_hdr_backup);
// Write MBR.
sdmmc_storage_write(&sd_storage, sd_sector_off, 1, &mbr);
}
return 1;
}
void dump_emummc_raw(emmc_tool_gui_t *gui, int part_idx, u32 sector_start)
u32 kb = 0;
u8 *tsec_fw = NULL;
bool sept_error = false;
static lv_res_t _emummc_raw_check_sept_action(lv_obj_t *btns, const char * txt)
{
int btn_idx = lv_btnm_get_pressed(btns);
mbox_action(btns, txt);
if (btn_idx == 1 && !sept_error)
{
// Set boot cfg.
b_cfg->autoboot = 0;
b_cfg->autoboot_list = 0;
b_cfg->extra_cfg = EXTRA_CFG_NYX_SEPT;
b_cfg->sept = NYX_SEPT_EMUF;
sd_mount();
reboot_to_sept(tsec_fw, kb);
}
return LV_RES_INV;
}
static int _emummc_raw_check_sept(emmc_tool_gui_t *gui, u32 resized_count)
{
if (!resized_count)
return 1;
bool sept_needed = false;
sept_error = false;
tsec_fw = NULL;
char *txt_buf = (char *)malloc(0x4000);
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;
static const u32 HOS_KEYBLOBS_OFFSET = 0x180000;
u32 bootloader_offset = BOOTLOADER_MAIN_OFFSET;
u32 pk1_offset = h_cfg.t210b01 ? sizeof(bl_hdr_t210b01_t) : 0; // Skip T210B01 OEM header.
u8 *pkg1 = (u8 *)malloc(BOOTLOADER_SIZE);
sdmmc_storage_set_mmc_partition(&emmc_storage, EMMC_BOOT0);
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 + pk1_offset, build_date);
s_printf(txt_buf + strlen(txt_buf), "#00DDFF Found pkg1 ('%s')#\n", build_date);
free(build_date);
if (!pkg1_id)
{
strcat(txt_buf, "#FFDD00 Unknown pkg1 version!#\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;
}
sept_error = true;
goto out;
}
kb = pkg1_id->kb;
// Skip if Mariko.
if (h_cfg.t210b01)
goto bis_derivation;
tsec_ctxt_t tsec_ctxt;
tsec_ctxt.fw = (u8 *)pkg1 + pkg1_id->tsec_off;
tsec_ctxt.pkg1 = pkg1;
tsec_ctxt.pkg11_off = pkg1_id->pkg11_off;
tsec_ctxt.secmon_base = pkg1_id->secmon_base;
// Get keys.
hos_eks_get();
if (kb >= KB_FIRMWARE_VERSION_700 && !h_cfg.sept_run)
{
u32 key_idx = 0;
if (kb >= KB_FIRMWARE_VERSION_810)
key_idx = 1;
if (h_cfg.eks && h_cfg.eks->enabled[key_idx] >= kb)
h_cfg.sept_run = true;
else
{
// Check that BCT is proper so sept can run.
u8 *bct_bldr = (u8 *)calloc(1, 512);
sdmmc_storage_read(&emmc_storage, 0x2200 / NX_EMMC_BLOCKSIZE, 1, bct_bldr);
u32 bootloader_entrypoint = *(u32 *)&bct_bldr[0x144];
free(bct_bldr);
if (bootloader_entrypoint > SEPT_PRI_ENTRY)
{
strcpy(txt_buf, "#FFDD00 Failed to run sept because main BCT is improper!#\n"
"#FFDD00 Run sept with proper BCT at least once to cache keys.#\n");
sept_error = true;
goto out;
}
// Set TSEC fw.
tsec_fw = (u8 *)tsec_ctxt.fw;
sept_needed = true;
goto out;
}
}
bis_derivation:;
// Read the correct keyblob.
u8 *keyblob = (u8 *)calloc(NX_EMMC_BLOCKSIZE, 1);
sdmmc_storage_read(&emmc_storage, HOS_KEYBLOBS_OFFSET / NX_EMMC_BLOCKSIZE + kb, 1, keyblob);
// Generate BIS keys
hos_bis_keygen(keyblob, kb, &tsec_ctxt);
free(keyblob);
u8 *cal0_buf = malloc(0x10000);
// Read and decrypt CAL0 for validation of working BIS keys.
sdmmc_storage_set_mmc_partition(&emmc_storage, EMMC_GPP);
LIST_INIT(gpt);
nx_emmc_gpt_parse(&gpt, &emmc_storage);
emmc_part_t *cal0_part = nx_emmc_part_find(&gpt, "PRODINFO"); // check if null
nx_emmc_bis_init(cal0_part, false, 0);
nx_emmc_bis_read(0, 0x40, cal0_buf);
nx_emmc_bis_end();
nx_emmc_gpt_free(&gpt);
nx_emmc_cal0_t *cal0 = (nx_emmc_cal0_t *)cal0_buf;
// If successful, save BIS keys.
if (memcmp(&cal0->magic, "CAL0", 4))
{
hos_bis_keys_clear();
hos_eks_bis_clear();
strcpy(txt_buf, "#FFDD00 BIS keys validation failed!#\n");
sept_error = true;
}
else
hos_eks_bis_save();
free(cal0_buf);
out:
// Check if sept is not needed.
if (!sept_needed)
free(pkg1);
if (sept_needed || sept_error)
{
lv_obj_t *dark_bg = lv_obj_create(lv_scr_act(), NULL);
lv_obj_set_style(dark_bg, &mbox_darken);
lv_obj_set_size(dark_bg, LV_HOR_RES, LV_VER_RES);
static const char * mbox_btn_map[] = { "\211", "\222Launch", "\222Close", "\211", "" };
static const char * mbox_btn_map2[] = { "\211", "\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);
lv_mbox_set_text(mbox, "#C7EA46 BIS Keys Generation#");
lv_obj_t * lb_desc = lv_label_create(mbox, NULL);
lv_label_set_long_mode(lb_desc, LV_LABEL_LONG_BREAK);
lv_label_set_recolor(lb_desc, true);
lv_label_set_style(lb_desc, &monospace_text);
lv_obj_set_width(lb_desc, LV_HOR_RES / 9 * 4);
if (sept_error)
{
lv_label_set_text(lb_desc, txt_buf);
lv_mbox_add_btns(mbox, mbox_btn_map2, _emummc_raw_check_sept_action);
free(pkg1);
}
else
{
lv_label_set_text(lb_desc, "Sept needs to launch in order to generate keys\nneeded for emuMMC resizing.\n"
"After that enter this menu again.");
lv_mbox_add_btns(mbox, mbox_btn_map, _emummc_raw_check_sept_action);
}
lv_obj_align(mbox, NULL, LV_ALIGN_CENTER, 0, 0);
lv_obj_set_top(mbox, true);
free(txt_buf);
return 0;
}
sdmmc_storage_set_mmc_partition(&emmc_storage, EMMC_GPP);
return 1;
}
void dump_emummc_raw(emmc_tool_gui_t *gui, int part_idx, u32 sector_start, u32 resized_count)
{
int res = 0;
u32 timer = 0;
char *txt_buf = (char *)malloc(0x4000);
gui->base_path = (char *)malloc(OUT_FILENAME_SZ);
gui->txt_buf = txt_buf;
s_printf(txt_buf, "");
@@ -650,26 +972,31 @@ void dump_emummc_raw(emmc_tool_gui_t *gui, int part_idx, u32 sector_start)
goto out;
}
sdmmc_storage_t storage;
sdmmc_t sdmmc;
if (!sdmmc_storage_init_mmc(&storage, &sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400))
if (!sdmmc_storage_init_mmc(&emmc_storage, &emmc_sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400))
{
lv_label_set_text(gui->label_info, "#FFDD00 Failed to init eMMC!#");
goto out;
}
if (!_emummc_raw_check_sept(gui, resized_count))
{
s_printf(gui->txt_buf, "#FFDD00 For formatting USER partition,#\n#FFDD00 BIS keys are needed!#\n");
lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf);
sdmmc_storage_end(&emmc_storage);
goto out;
}
int i = 0;
char sdPath[OUT_FILENAME_SZ];
// Create Restore folders, if they do not exist.
f_mkdir("emuMMC");
s_printf(sdPath, "emuMMC/RAW%d", part_idx);
gui->base_path = (char *)malloc(OUT_FILENAME_SZ);
f_mkdir(sdPath);
strcat(sdPath, "/");
strcpy(gui->base_path, sdPath);
timer = get_tmr_s();
const u32 BOOT_PART_SIZE = storage.ext_csd.boot_mult << 17;
const u32 BOOT_PART_SIZE = emmc_storage.ext_csd.boot_mult << 17;
emmc_part_t bootPart;
memset(&bootPart, 0, sizeof(bootPart));
@@ -693,10 +1020,10 @@ void dump_emummc_raw(emmc_tool_gui_t *gui, int part_idx, u32 sector_start)
lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, txt_buf);
manual_system_maintenance(true);
sdmmc_storage_set_mmc_partition(&storage, i + 1);
sdmmc_storage_set_mmc_partition(&emmc_storage, i + 1);
strcat(sdPath, bootPart.name);
res = _dump_emummc_raw_part(gui, i, part_idx, sector_start, &storage, &bootPart);
res = _dump_emummc_raw_part(gui, i, part_idx, sector_start, &emmc_storage, &bootPart, 0);
if (!res)
{
@@ -712,10 +1039,10 @@ void dump_emummc_raw(emmc_tool_gui_t *gui, int part_idx, u32 sector_start)
strcpy(sdPath, gui->base_path);
}
sdmmc_storage_set_mmc_partition(&storage, EMMC_GPP);
sdmmc_storage_set_mmc_partition(&emmc_storage, EMMC_GPP);
// Get GP partition size dynamically.
const u32 RAW_AREA_NUM_SECTORS = storage.sec_cnt;
const u32 RAW_AREA_NUM_SECTORS = emmc_storage.sec_cnt;
emmc_part_t rawPart;
memset(&rawPart, 0, sizeof(rawPart));
@@ -730,7 +1057,7 @@ void dump_emummc_raw(emmc_tool_gui_t *gui, int part_idx, u32 sector_start)
lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, txt_buf);
manual_system_maintenance(true);
res = _dump_emummc_raw_part(gui, 2, part_idx, sector_start, &storage, &rawPart);
res = _dump_emummc_raw_part(gui, 2, part_idx, sector_start, &emmc_storage, &rawPart, resized_count);
if (!res)
s_printf(txt_buf, "#FFDD00 Failed!#\n");
@@ -743,7 +1070,7 @@ void dump_emummc_raw(emmc_tool_gui_t *gui, int part_idx, u32 sector_start)
out_failed:
timer = get_tmr_s() - timer;
sdmmc_storage_end(&storage);
sdmmc_storage_end(&emmc_storage);
if (res)
{

View File

@@ -32,7 +32,7 @@ typedef struct _emummc_cfg_t
void load_emummc_cfg(emummc_cfg_t *emu_info);
void save_emummc_cfg(u32 part_idx, u32 sector_start, const char *path);
void dump_emummc_file(emmc_tool_gui_t *gui);
void dump_emummc_raw(emmc_tool_gui_t *gui, int part_idx, u32 sector_start);
void dump_emummc_raw(emmc_tool_gui_t *gui, int part_idx, u32 sector_start, u32 resized_count);
void update_emummc_base_folder(char *outFilename, u32 sdPathLen, u32 currPartIdx);
#endif

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2018-2020 CTCaer
* Copyright (c) 2018-2021 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
@@ -36,6 +36,7 @@
#include <mem/minerva.h>
#include <power/bq24193.h>
#include <power/max17050.h>
#include <power/regulator_5v.h>
#include <rtc/max77620-rtc.h>
#include <soc/bpmp.h>
#include <soc/fuse.h>
@@ -765,7 +766,7 @@ static void nyx_sd_card_issues(void *param)
lv_mbox_set_text(mbox,
"#FF8000 SD Card Issues Check#\n\n"
"#FFDD00 Your SD Card is initialized in 1-bit mode!#\n"
"#FFDD00 The SD Card is initialized in 1-bit mode!#\n"
"#FFDD00 This might mean detached or broken connector!#\n\n"
"You might want to check\n#C7EA46 Console Info# -> #C7EA46 SD Card#");
@@ -954,15 +955,13 @@ static lv_res_t _reboot_action(lv_obj_t *btns, const char *txt)
switch (btnidx)
{
case 0:
if (h_cfg.rcm_patched)
power_set_state(POWER_OFF_REBOOT);
else
power_set_state(REBOOT_BYPASS_FUSES);
power_set_state(REBOOT_BYPASS_FUSES);
break;
case 1:
if (h_cfg.rcm_patched)
break;
power_set_state(REBOOT_RCM);
power_set_state(POWER_OFF_REBOOT);
else
power_set_state(REBOOT_RCM);
break;
}
@@ -1005,7 +1004,7 @@ static lv_res_t _create_mbox_reboot(lv_obj_t *btn)
lv_obj_set_size(dark_bg, LV_HOR_RES, LV_VER_RES);
static const char * mbox_btn_map[] = { "\221OFW", "\221RCM", "\221Cancel", "" };
static const char * mbox_btn_map_patched[] = { "\221Reboot", "\221Cancel", "" };
static const char * mbox_btn_map_patched[] = { "\221OFW", "\221Normal", "\221Cancel", "" };
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 / 2);
@@ -1140,9 +1139,9 @@ static void _create_tab_about(lv_theme_t * th, lv_obj_t * parent)
lv_label_set_recolor(lbl_credits, true);
lv_label_set_static_text(lbl_credits,
"#C7EA46 hekate# (c) 2018, #C7EA46 naehrwert#, #C7EA46 st4rk#\n"
" (c) 2018-2020, #C7EA46 CTCaer#\n"
" (c) 2018-2021, #C7EA46 CTCaer#\n"
"\n"
"#C7EA46 Nyx GUI# (c) 2019-2020, #C7EA46 CTCaer#\n"
"#C7EA46 Nyx GUI# (c) 2019-2021, #C7EA46 CTCaer#\n"
"\n"
"Thanks to: #00CCFF derrek, nedwill, plutoo, #\n"
" #00CCFF shuffle2, smea, thexyz, yellows8 #\n"
@@ -1263,8 +1262,14 @@ static void _update_status_bar(void *params)
else
strcat(label, "#FF3C28 "SYMBOL_BATTERY_EMPTY"#");
// Set charging symbol and regulator 5V source based on USB state.
if (charge_status)
{
strcat(label, " #FFDD00 "SYMBOL_CHARGE"#");
regulator_5v_batt_src_enable(false);
}
else
regulator_5v_batt_src_enable(true);
lv_label_set_text(status_bar.battery, label);
lv_obj_realign(status_bar.battery);
@@ -1750,14 +1755,14 @@ ini_parsing:
{
lv_label_set_static_text(label_error,
"#FFDD00 No main boot entries found...#\n"
"You can use the following entry to boot stock,\n"
"Check that #96FF00 bootloader/hekate_ipl.ini# has boot entries\n"
"or use #C7EA46 More configs# button for more boot entries.");
}
else
{
lv_label_set_static_text(label_error,
"#FFDD00 No .ini or boot entries found...#\n"
"Check that a .ini file exists in #96FF00 /bootloader/ini/#,\n"
"Check that a .ini file exists in #96FF00 bootloader/ini/#\n"
"and that it contains at least one entry.");
}
@@ -2000,7 +2005,7 @@ void nyx_check_ini_changes()
lv_mbox_set_text(mbox,
"#FF8000 Main configuration#\n\n"
"You changed your configuration!\n\n"
"You changed the configuration!\n\n"
"Do you want to save it?");
lv_mbox_add_btns(mbox, mbox_btn_map, _create_mbox_save_changes_action);
@@ -2201,17 +2206,25 @@ static void _nyx_main_menu(lv_theme_t * th)
lv_tabview_set_tab_load_action(tv, _show_hide_save_button);
// If we rebooted to run sept for dumping, lunch dump immediately.
if (nyx_str->cfg & NYX_CFG_DUMP)
if (nyx_str->cfg & NYX_CFG_SEPT)
{
nyx_str->cfg &= ~(NYX_CFG_DUMP);
lv_task_t *task_run_dump = lv_task_create(sept_run_dump, LV_TASK_ONESHOT, LV_TASK_PRIO_MID, NULL);
lv_task_once(task_run_dump);
}
else if (nyx_str->cfg & NYX_CFG_BIS)
{
nyx_str->cfg &= ~(NYX_CFG_BIS);
lv_task_t *task_run_cal0 = lv_task_create(sept_run_cal0, LV_TASK_ONESHOT, LV_TASK_PRIO_LOWEST, NULL);
lv_task_once(task_run_cal0);
u32 type = nyx_str->cfg >> 24;
nyx_str->cfg &= ~(NYX_CFG_SEPT | NYX_CFG_EXTRA);
if (type == NYX_SEPT_DUMP)
{
lv_task_t *task_run_dump = lv_task_create(sept_run_dump, LV_TASK_ONESHOT, LV_TASK_PRIO_MID, NULL);
lv_task_once(task_run_dump);
}
else if (type == NYX_SEPT_CAL0)
{
lv_task_t *task_run_cal0 = lv_task_create(sept_run_cal0, LV_TASK_ONESHOT, LV_TASK_PRIO_LOWEST, NULL);
lv_task_once(task_run_cal0);
}
else if (type == NYX_SEPT_EMUF)
{
// TODO: Maybe automatically relaunch emuMMC creation in the future.
}
}
else if (nyx_str->cfg & NYX_CFG_UMS)
{

View File

@@ -333,15 +333,15 @@ lv_res_t create_window_backup_restore_tool(lv_obj_t *btn)
if (!emmc_btn_ctxt.restore)
{
lv_label_set_static_text(label_txt2,
"Allows you to backup your BOOT physical partitions.\n"
"They contain your BCT, keys and various package1.\n"
"Allows you to backup the BOOT physical partitions.\n"
"They contain the BCT, keys and various package1.\n"
"#FF8000 These are paired with the RAW GPP backup.#");
}
else
{
lv_label_set_static_text(label_txt2,
"Allows you to restore your BOOT physical partitions.\n"
"They contain your BCT, keys and various package1.\n"
"Allows you to restore the BOOT physical partitions.\n"
"They contain the BCT, keys and various package1.\n"
"#FF8000 These are paired with the RAW GPP restore.#");
}
lv_obj_set_style(label_txt2, &hint_small_style);
@@ -363,14 +363,14 @@ lv_res_t create_window_backup_restore_tool(lv_obj_t *btn)
if (!emmc_btn_ctxt.restore)
{
lv_label_set_static_text(label_txt2,
"Allows you to backup your GPP physical partition.\n"
"Allows you to backup the GPP physical partition.\n"
"It contains, CAL0, various package2, SYSTEM, USER, etc.\n"
"#FF8000 This is paired with the BOOT0/1 backups.#");
}
else
{
lv_label_set_static_text(label_txt2,
"Allows you to restore your GPP physical partition.\n"
"Allows you to restore the GPP physical partition.\n"
"It contains, CAL0, various package2, SYSTEM, USER, etc.\n"
"#FF8000 This is paired with the BOOT0/1 restore.#");
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2019-2020 CTCaer
* Copyright (c) 2019-2021 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
@@ -24,6 +24,7 @@
#include <libs/fatfs/ff.h>
#include <mem/heap.h>
#include <storage/mbr_gpt.h>
#include "../storage/nx_emmc_bis.h"
#include <storage/nx_sd.h>
#include <storage/sdmmc.h>
#include <utils/dirlist.h>
@@ -37,6 +38,8 @@ typedef struct _mbr_ctxt_t
{
u32 available;
u32 sector[3];
u32 resized_cnt[3];
int part_idx;
u32 sector_start;
} mbr_ctxt_t;
@@ -49,12 +52,12 @@ static lv_res_t (*emummc_tools)(lv_obj_t *btn);
static lv_res_t _action_emummc_window_close(lv_obj_t *btn)
{
lv_win_close_action(btn);
lv_obj_del(emummc_manage_window);
(*emummc_tools)(NULL);
close_btn = NULL;
// Delete and relaunch main emuMMC window.
lv_obj_del(emummc_manage_window);
(*emummc_tools)(NULL);
return LV_RES_INV;
}
@@ -141,7 +144,7 @@ static void _create_window_emummc()
if (!mbr_ctx.part_idx)
dump_emummc_file(&emmc_tool_gui_ctxt);
else
dump_emummc_raw(&emmc_tool_gui_ctxt, mbr_ctx.part_idx, mbr_ctx.sector_start);
dump_emummc_raw(&emmc_tool_gui_ctxt, mbr_ctx.part_idx, mbr_ctx.sector_start, mbr_ctx.resized_cnt[mbr_ctx.part_idx - 1]);
nyx_window_toggle_buttons(win, false);
}
@@ -223,13 +226,11 @@ static void _create_mbox_emummc_raw()
sdmmc_storage_read(&sd_storage, 0, 1, mbr);
sd_unmount();
sdmmc_storage_t storage;
sdmmc_t sdmmc;
sdmmc_storage_init_mmc(&storage, &sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400);
sdmmc_storage_init_mmc(&emmc_storage, &emmc_sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400);
u32 emmc_size_safe = storage.sec_cnt + 0xC000; // eMMC GPP size + BOOT0/1.
u32 emmc_size_safe = emmc_storage.sec_cnt + 0xC000; // eMMC GPP size + BOOT0/1.
sdmmc_storage_end(&storage);
sdmmc_storage_end(&emmc_storage);
for (int i = 1; i < 4; i++)
{
@@ -240,10 +241,22 @@ static void _create_mbox_emummc_raw()
// Skip Linux, GPT (Android) and SFD partitions.
bool valid_part = (part_type != 0x83) && (part_type != 0xEE) && (part_type != 0xFF);
if ((part_size >= emmc_size_safe) && part_start > 0x8000 && valid_part)
// Check if at least 4GB and start above 16MB.
if ((part_size >= 0x80F000) && part_start > 0x8000 && valid_part)
{
mbr_ctx.available |= (1 << (i - 1));
mbr_ctx.available |= BIT(i - 1);
mbr_ctx.sector[i - 1] = part_start;
// Only allow up to 16GB resized emuMMC.
if (part_size <= 0x2010000)
mbr_ctx.resized_cnt[i - 1] = part_size - 0xC000; // Save sectors count without protective size and BOOT0/1.
else if (part_size >= emmc_size_safe)
mbr_ctx.resized_cnt[i - 1] = 0;
else
{
mbr_ctx.available &= ~BIT(i - 1);
mbr_ctx.sector[i - 1] = 0;
}
}
}
@@ -261,19 +274,21 @@ static void _create_mbox_emummc_raw()
"#C0C0C0 Part 0: Type: %02x, Start: %08x, Size: %08x#\n"
"#%s Part 1: Type: %02x, Start: %08x, Size: %08x#\n"
"#%s Part 2: Type: %02x, Start: %08x, Size: %08x#\n"
"#%s Part 3: Type: %02x, Start: %08x, Size: %08x#\n",
"#%s Part 3: Type: %02x, Start: %08x, Size: %08x#",
mbr->partitions[0].type, mbr->partitions[0].start_sct, mbr->partitions[0].size_sct,
(mbr_ctx.available & 1) ? "C7EA46" : "C0C0C0",
mbr->partitions[1].type, mbr->partitions[1].start_sct, mbr->partitions[1].size_sct,
(mbr_ctx.available & 2) ? "C7EA46" : "C0C0C0",
mbr->partitions[2].type, mbr->partitions[2].start_sct, mbr->partitions[2].size_sct,
(mbr_ctx.available & 4) ? "C7EA46" : "C0C0C0",
mbr->partitions[3].type, mbr->partitions[3].start_sct, mbr->partitions[3].size_sct);
(mbr_ctx.available & BIT(0)) ? (mbr_ctx.resized_cnt[0] ? "FFDD00" : "C7EA46") : "C0C0C0",
mbr->partitions[1].type, mbr->partitions[1].start_sct, mbr->partitions[1].size_sct,
(mbr_ctx.available & BIT(1)) ? (mbr_ctx.resized_cnt[1] ? "FFDD00" : "C7EA46") : "C0C0C0",
mbr->partitions[2].type, mbr->partitions[2].start_sct, mbr->partitions[2].size_sct,
(mbr_ctx.available & BIT(2)) ? (mbr_ctx.resized_cnt[2] ? "FFDD00" : "C7EA46") : "C0C0C0",
mbr->partitions[3].type, mbr->partitions[3].start_sct, mbr->partitions[3].size_sct);
if (mbr_ctx.resized_cnt[0] || mbr_ctx.resized_cnt[1] || mbr_ctx.resized_cnt[2])
strcat(txt_buf, "\n\n#FFDD00 Note:# Yellow entries have USER partition resized.");
if (!mbr_ctx.available)
strcat(txt_buf,
"\n#FF8000 Do you want to partition your SD card?#\n"
"#FF8000 (You will be asked on how to proceed)#");
strcat(txt_buf, "\n#FF8000 Do you want to partition the SD card?#\n"
"#FF8000 (You will be asked on how to proceed)#");
lv_mbox_set_text(mbox, txt_buf);
free(txt_buf);
@@ -345,7 +360,7 @@ static lv_res_t _create_mbox_emummc_create(lv_obj_t *btn)
lv_mbox_set_text(mbox,
"Welcome to #C7EA46 emuMMC# creation tool!\n\n"
"Please choose what type of emuMMC you want to create.\n"
"#FF8000 SD File# is saved as files in your FAT partition.\n"
"#FF8000 SD File# is saved as files in the FAT partition.\n"
"#FF8000 SD Partition# is saved as raw image in an available partition.");
lv_mbox_add_btns(mbox, mbox_btn_map, _create_emummc_action);
@@ -365,6 +380,38 @@ static void _change_raw_emummc_part_type()
free(mbr);
}
static lv_res_t _save_emummc_cfg_mig_mbox_action(lv_obj_t *btns, const char *txt)
{
// Delete main emuMMC and popup windows and relaunch main emuMMC window.
lv_obj_del(emummc_manage_window);
mbox_action(btns, txt);
(*emummc_tools)(NULL);
return LV_RES_INV;
}
static void _create_emummc_migrated_mbox()
{
lv_obj_t *dark_bg = lv_obj_create(lv_scr_act(), NULL);
lv_obj_set_style(dark_bg, &mbox_darken);
lv_obj_set_size(dark_bg, LV_HOR_RES, LV_VER_RES);
static const char *mbox_btn_map[] = { "\211", "OK", "\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 * 4);
lv_mbox_set_text(mbox,
"#FF8000 emuMMC Configuration#\n\n"
"#96FF00 The emuMMC configuration#\n#96FF00 was saved to sd card!#");
lv_mbox_add_btns(mbox, mbox_btn_map, _save_emummc_cfg_mig_mbox_action);
lv_obj_align(mbox, NULL, LV_ALIGN_CENTER, 0, 0);
lv_obj_set_top(mbox, true);
}
static void _migrate_sd_raw_based()
{
mbr_ctx.sector_start = 2;
@@ -380,6 +427,7 @@ static void _migrate_sd_raw_based()
f_close(&fp);
save_emummc_cfg(1, mbr_ctx.sector_start, "emuMMC/ER00");
_create_emummc_migrated_mbox();
sd_unmount();
}
@@ -405,7 +453,7 @@ static void _migrate_sd_raw_emummc_based()
_change_raw_emummc_part_type();
save_emummc_cfg(mbr_ctx.part_idx, mbr_ctx.sector_start, tmp);
_create_emummc_migrated_mbox();
free(tmp);
sd_unmount();
@@ -444,6 +492,7 @@ static void _migrate_sd_file_based()
free(path2);
save_emummc_cfg(0, 0, "emuMMC/EF00");
_create_emummc_migrated_mbox();
sd_unmount();
}
@@ -516,6 +565,7 @@ static void _migrate_sd_backup_file_based()
free(backup_file_path);
save_emummc_cfg(0, 0, "emuMMC/BK00");
_create_emummc_migrated_mbox();
sd_unmount();
}
@@ -645,41 +695,41 @@ static lv_res_t _create_emummc_migrate_action(lv_obj_t * btns, const char * txt)
if (backup)
{
s_printf(txt_buf,
"#C7EA46 Found suitable backup for emuMMC!#\n"
"#FF8000 Do you want to migrate it?#\n\n");
"#C7EA46 Found suitable backup for emuMMC!#\n\n"
"#FF8000 Do you want to migrate it?#\n");
lv_mbox_add_btns(mbox, mbox_btn_map, _create_emummc_mig4_action);
}
else if (emummc)
{
s_printf(txt_buf,
"#C7EA46 Found SD Partition based emuMMC!#\n"
"#FF8000 Do you want to repair the config for it?#\n\n");
"#C7EA46 Found SD Partition based emuMMC!#\n\n"
"#FF8000 Do you want to repair the config for it?#\n");
lv_mbox_add_btns(mbox, mbox_btn_map, _create_emummc_mig3_action);
}
else if (em_raw && em_file)
{
s_printf(txt_buf,
"#C7EA46 Found both foreign SD File and Partition emunand!#\n"
"#FF8000 Choose what to migrate:#\n\n");
"#C7EA46 Found both foreign SD File and Partition emunand!#\n\n"
"#FF8000 Choose what to migrate:#\n");
lv_mbox_add_btns(mbox, mbox_btn_map1, _create_emummc_mig1_action);
}
else if (em_raw)
{
s_printf(txt_buf,
"#C7EA46 Found foreign SD Partition emunand!#\n"
"#FF8000 Do you want to migrate it?#\n\n");
"#C7EA46 Found foreign SD Partition emunand!#\n\n"
"#FF8000 Do you want to migrate it?#\n");
lv_mbox_add_btns(mbox, mbox_btn_map, _create_emummc_mig2_action);
}
else if (em_file)
{
s_printf(txt_buf,
"#C7EA46 Found foreign SD File emunand!#\n"
"#FF8000 Do you want to migrate it?#\n\n");
"#C7EA46 Found foreign SD File emunand!#\n\n"
"#FF8000 Do you want to migrate it?#\n");
lv_mbox_add_btns(mbox, mbox_btn_map, _create_emummc_mig0_action);
}
else
{
s_printf(txt_buf, "No emuMMC or foreign emunand found!\n\n");
s_printf(txt_buf, "No emuMMC or foreign emunand found!\n");
lv_mbox_add_btns(mbox, mbox_btn_map3, mbox_action);
}
@@ -727,9 +777,7 @@ static lv_res_t _create_mbox_emummc_migrate(lv_obj_t *btn)
sd_mount();
sdmmc_storage_read(&sd_storage, 0, 1, mbr);
sdmmc_storage_t storage;
sdmmc_t sdmmc;
sdmmc_storage_init_mmc(&storage, &sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400);
sdmmc_storage_init_mmc(&emmc_storage, &emmc_sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400);
em_raw = false;
em_file = false;
@@ -778,22 +826,22 @@ static lv_res_t _create_mbox_emummc_migrate(lv_obj_t *btn)
if(!f_stat(path_buf, NULL))
em_file = true;
emmcsn_path_impl(path_buf, "", "BOOT0", &storage);
emmcsn_path_impl(path_buf, "", "BOOT0", &emmc_storage);
if(!f_stat(path_buf, NULL))
backup = true;
emmcsn_path_impl(path_buf, "", "rawnand.bin", &storage);
emmcsn_path_impl(path_buf, "", "rawnand.bin", &emmc_storage);
if(!f_stat(path_buf, NULL))
rawnand_backup = true;
emmcsn_path_impl(path_buf, "", "rawnand.bin.00", &storage);
emmcsn_path_impl(path_buf, "", "rawnand.bin.00", &emmc_storage);
if(!f_stat(path_buf, NULL))
rawnand_backup = true;
backup = backup && rawnand_backup;
sd_unmount();
sdmmc_storage_end(&storage);
sdmmc_storage_end(&emmc_storage);
// Check available types and enable the corresponding buttons.
if (backup)
@@ -825,6 +873,7 @@ static emummc_images_t *emummc_img;
static lv_res_t _save_emummc_cfg_mbox_action(lv_obj_t *btns, const char *txt)
{
// Free components, delete main emuMMC and popup windows and relaunch main emuMMC window.
free(emummc_img->dirlist);
lv_obj_del(emummc_img->win);
lv_obj_del(emummc_manage_window);
@@ -1121,8 +1170,9 @@ out1:
lv_res_t create_win_emummc_tools(lv_obj_t *btn)
{
lv_obj_t *win = nyx_create_standard_window(SYMBOL_EDIT" emuMMC Manage");
emummc_manage_window = win;
// Set resources to be managed by other windows.
emummc_manage_window = win;
emummc_tools = (void *)create_win_emummc_tools;
sd_mount();
@@ -1246,7 +1296,6 @@ lv_res_t create_win_emummc_tools(lv_obj_t *btn)
lv_obj_set_style(label_txt4, &hint_small_style);
lv_obj_align(label_txt4, btn3, LV_ALIGN_OUT_BOTTOM_LEFT, 0, LV_DPI / 3);
//! TODO: Move it to a window with multiple choices.
// Create Migrate emuMMC button.
lv_obj_t *btn4 = lv_btn_create(h2, btn2);
label_btn = lv_label_create(btn4, NULL);
@@ -1260,8 +1309,6 @@ lv_res_t create_win_emummc_tools(lv_obj_t *btn)
lv_label_set_static_text(label_txt4,
"Migrate a backup to a #C7EA46 SD File# or repair existing #C7EA46 SD Raw Partition#.\n"
"Additionally it allows you to migrate from other emunand\nsolutions.");
//"Move between #C7EA46 SD File# and #C7EA46 SD Raw Partition# emuMMC.\n"
//"Additionally it allows you to migrate from other emunand\nsolutions.");
lv_obj_set_style(label_txt4, &hint_small_style);
lv_obj_align(label_txt4, btn4, LV_ALIGN_OUT_BOTTOM_LEFT, 0, LV_DPI / 3);

View File

@@ -1,6 +1,6 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2020 CTCaer
* Copyright (c) 2018-2021 CTCaer
* Copyright (c) 2018 balika011
*
* This program is free software; you can redistribute it and/or modify it
@@ -269,7 +269,7 @@ static lv_res_t _tsec_keys_dump_window_action(lv_obj_t * btn)
{
char path[64];
emmcsn_path_impl(path, "/dumps", "tsec_keys.bin", NULL);
error = sd_save_to_file(tsec_keys, 0x10 * 2, path);
error = sd_save_to_file(tsec_keys, SE_KEY_128_SIZE * 2, path);
sd_unmount();
}
@@ -312,7 +312,13 @@ static lv_res_t _create_mbox_cal0(lv_obj_t *btn)
u32 bootloader_offset = BOOTLOADER_MAIN_OFFSET;
u32 pk1_offset = h_cfg.t210b01 ? sizeof(bl_hdr_t210b01_t) : 0; // Skip T210B01 OEM header.
u8 *pkg1 = (u8 *)malloc(BOOTLOADER_SIZE);
sdmmc_storage_init_mmc(&emmc_storage, &emmc_sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400);
if (!sdmmc_storage_init_mmc(&emmc_storage, &emmc_sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400))
{
lv_label_set_text(lb_desc, "#FFDD00 Failed to init eMMC!#");
goto out;
}
sdmmc_storage_set_mmc_partition(&emmc_storage, EMMC_BOOT0);
try_load:
@@ -326,7 +332,7 @@ try_load:
if (!pkg1_id)
{
strcat(txt_buf, "#FFDD00 Unknown pkg1 version for reading#\n#FFDD00 TSEC firmware!#\n");
strcat(txt_buf, "#FFDD00 Unknown pkg1 version!#\n");
// Try backup bootloader.
if (bootloader_offset != BOOTLOADER_BACKUP_OFFSET)
{
@@ -363,9 +369,23 @@ try_load:
h_cfg.sept_run = true;
else
{
// Check that BCT is proper so sept can run.
u8 *bct_bldr = (u8 *)calloc(1, 512);
sdmmc_storage_read(&emmc_storage, 0x2200 / NX_EMMC_BLOCKSIZE, 1, bct_bldr);
u32 bootloader_entrypoint = *(u32 *)&bct_bldr[0x144];
free(bct_bldr);
if (bootloader_entrypoint > SEPT_PRI_ENTRY)
{
lv_label_set_text(lb_desc, "#FFDD00 Main BCT is improper! Failed to run sept.#\n"
"#FFDD00 Run sept with proper BCT at least once#\n#FFDD00 to cache keys.#\n");
goto out;
}
// Set boot cfg.
b_cfg->autoboot = 0;
b_cfg->autoboot_list = 0;
b_cfg->extra_cfg = EXTRA_CFG_NYX_BIS;
b_cfg->extra_cfg = EXTRA_CFG_NYX_SEPT;
b_cfg->sept = NYX_SEPT_CAL0;
if (!reboot_to_sept((u8 *)tsec_ctxt.fw, kb))
{
@@ -393,10 +413,12 @@ t210b01:;
LIST_INIT(gpt);
nx_emmc_gpt_parse(&gpt, &emmc_storage);
emmc_part_t *cal0_part = nx_emmc_part_find(&gpt, "PRODINFO"); // check if null
nx_emmc_bis_init(cal0_part);
nx_emmc_bis_init(cal0_part, false, 0);
nx_emmc_bis_read(0, 0x40, cal0_buf);
nx_emmc_bis_end();
nx_emmc_gpt_free(&gpt);
// Clear BIS keys slots.
// Clear BIS keys slots and reinstate SBK.
hos_bis_keys_clear();
nx_emmc_cal0_t *cal0 = (nx_emmc_cal0_t *)cal0_buf;
@@ -975,9 +997,9 @@ static lv_res_t _create_window_fuses_info_status(lv_obj_t *btn)
// Check if patched unit.
if (!fuse_check_patched_rcm())
strcat(txt_buf, "\n\n#96FF00 Your unit is exploitable#\n#96FF00 to the RCM bug!#");
strcat(txt_buf, "\n\n#96FF00 This unit is exploitable#\n#96FF00 to the RCM bug!#");
else
strcat(txt_buf, "\n\n#FF8000 Your unit is patched#\n#FF8000 to the RCM bug!#");
strcat(txt_buf, "\n\n#FF8000 This unit is patched#\n#FF8000 to the RCM bug!#");
lv_label_set_text(lb_desc2, txt_buf);
@@ -1090,7 +1112,7 @@ try_load:
if (!pkg1_id)
{
strcat(txt_buf, "#FFDD00 Unknown pkg1 version for reading#\n#FFDD00 TSEC firmware!#\n");
strcat(txt_buf, "#FFDD00 Unknown pkg1 version!#\n");
// Try backup bootloader.
if (bootloader_offset != BOOTLOADER_BACKUP_OFFSET)
{
@@ -1192,8 +1214,6 @@ out:
static lv_res_t _create_mbox_benchmark(bool sd_bench)
{
sdmmc_t emmc_sdmmc;
sdmmc_storage_t emmc_storage;
sdmmc_storage_t *storage;
lv_obj_t *dark_bg = lv_obj_create(lv_scr_act(), NULL);
@@ -1203,16 +1223,28 @@ static lv_res_t _create_mbox_benchmark(bool sd_bench)
static const char * mbox_btn_map[] = { "\211", "\222OK", "\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 / 7 * 5);
lv_obj_set_width(mbox, LV_HOR_RES / 7 * 4);
char *txt_buf = (char *)malloc(0x1000);
char *txt_buf = (char *)malloc(0x4000);
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");
s_printf(txt_buf, "#FF8000 %s Benchmark#\n[Raw Reads] Abort: VOL- & VOL+",
sd_bench ? "SD Card" : "eMMC");
lv_mbox_set_text(mbox, txt_buf);
txt_buf[0] = 0;
lv_obj_t * bar = lv_bar_create(mbox, NULL);
lv_obj_t *h1 = lv_cont_create(mbox, NULL);
lv_cont_set_fit(h1, false, true);
lv_cont_set_style(h1, &lv_style_transp_tight);
lv_obj_set_width(h1, lv_obj_get_width(mbox) - LV_DPI / 10);
lv_obj_t *lbl_status = lv_label_create(h1, NULL);
lv_label_set_style(lbl_status, &monospace_text);
lv_label_set_recolor(lbl_status, true);
lv_label_set_text(lbl_status, " ");
lv_obj_align(lbl_status, h1, LV_ALIGN_IN_TOP_MID, 0, 0);
lv_obj_t *bar = lv_bar_create(mbox, NULL);
lv_obj_set_size(bar, LV_DPI * 2, LV_DPI / 5);
lv_bar_set_range(bar, 0, 100);
lv_bar_set_value(bar, 0);
@@ -1241,9 +1273,7 @@ static lv_res_t _create_mbox_benchmark(bool sd_bench)
else
{
u32 iters = 3;
u32 sector_num = 0x8000;
u32 data_scts = sd_bench ? 0x400000 : 0x1000000; // SD 2GB or eMMC 8GB.
u32 offset_chunk_start = ALIGN_DOWN(storage->sec_cnt / 3, sector_num);
u32 offset_chunk_start = ALIGN_DOWN(storage->sec_cnt / 3, 0x8000); // Align to 16MB.
if (storage->sec_cnt < 0xC00000)
iters -= 2; // 4GB card.
@@ -1251,24 +1281,26 @@ static lv_res_t _create_mbox_benchmark(bool sd_bench)
{
u32 pct = 0;
u32 prevPct = 200;
u32 timer = 0;
u32 lba_curr = 0;
u32 sector = offset_chunk_start * iter_curr;
u32 data_remaining = data_scts;
u32 sector_num = 0x8000; // 16MB chunks.
u32 data_remaining = 0x200000; // 1GB.
u32 timer = get_tmr_ms();
strcat(txt_buf, "\n");
lv_mbox_set_text(mbox, txt_buf);
s_printf(txt_buf + strlen(txt_buf), "#C7EA46 %d/3# - Sector Offset #C7EA46 %08X#:\n", iter_curr + 1, sector);
while (data_remaining)
{
// Read 16MB chunks.
u32 time_taken = get_tmr_us();
sdmmc_storage_read(storage, sector + lba_curr, sector_num, (u8 *)MIXD_BUF_ALIGNED);
time_taken = get_tmr_us() - time_taken;
timer += time_taken;
manual_system_maintenance(false);
data_remaining -= sector_num;
lba_curr += sector_num;
pct = (lba_curr * 100) / data_scts;
pct = (lba_curr * 100) / 0x200000;
if (pct != prevPct)
{
lv_bar_set_value(bar, pct);
@@ -1280,17 +1312,115 @@ static lv_res_t _create_mbox_benchmark(bool sd_bench)
break;
}
}
timer = get_tmr_ms() - timer;
timer -= sd_bench ? 175 : 185; // Compensate 175ms/185ms for maintenance/drawing/calc ops.
lv_bar_set_value(bar, 100);
u32 rate_1k = (sd_bench ? (2048 * 1000 * 1000) : (u64)((u64)8192 * 1000 * 1000)) / timer;
u32 rate_1k = ((u64)1024 * 1000 * 1000 * 1000) / timer;
s_printf(txt_buf + strlen(txt_buf),
"#C7EA46 %d#: Offset: #C7EA46 %08X#, Time: #C7EA46 %d.%02ds#, Rate: #C7EA46 %d.%02d MB/s#",
iter_curr, sector, timer / 1000, (timer % 1000) / 10, rate_1k / 1000, (rate_1k % 1000) / 10);
lv_mbox_set_text(mbox, txt_buf);
" Sequential 16MiB - Rate: #C7EA46 %3d.%02d MiB/s#\n",
rate_1k / 1000, (rate_1k % 1000) / 10);
lv_label_set_text(lbl_status, txt_buf);
lv_obj_align(lbl_status, NULL, LV_ALIGN_CENTER, 0, 0);
lv_obj_align(mbox, NULL, LV_ALIGN_CENTER, 0, 0);
manual_system_maintenance(true);
pct = 0;
prevPct = 200;
timer = 0;
lba_curr = 0;
sector_num = 8; // 4KB chunks.
data_remaining = 0x100000; // 512MB.
while (data_remaining)
{
u32 time_taken = get_tmr_us();
sdmmc_storage_read(storage, sector + lba_curr, sector_num, (u8 *)MIXD_BUF_ALIGNED);
time_taken = get_tmr_us() - time_taken;
timer += time_taken;
manual_system_maintenance(false);
data_remaining -= sector_num;
lba_curr += sector_num;
pct = (lba_curr * 100) / 0x100000;
if (pct != prevPct)
{
lv_bar_set_value(bar, pct);
manual_system_maintenance(true);
prevPct = pct;
if (btn_read_vol() == (BTN_VOL_UP | BTN_VOL_DOWN))
break;
}
}
lv_bar_set_value(bar, 100);
rate_1k = ((u64)512 * 1000 * 1000 * 1000) / timer;
u32 iops_1k = ((u64)512 * 1024 * 1000 * 1000 * 1000) / (4096 / 1024) / timer / 1000;
s_printf(txt_buf + strlen(txt_buf),
" Sequential 4KiB - Rate: #C7EA46 %3d.%02d MiB/s#, IOPS: #C7EA46 %4d#\n",
rate_1k / 1000, (rate_1k % 1000) / 10, iops_1k);
lv_label_set_text(lbl_status, txt_buf);
lv_obj_align(lbl_status, NULL, LV_ALIGN_CENTER, 0, 0);
lv_obj_align(mbox, NULL, LV_ALIGN_CENTER, 0, 0);
manual_system_maintenance(true);
u32 lba_idx = 0;
u32 *random_offsets = malloc(0x20000 * sizeof(u32));
u32 random_numbers[4];
for (u32 i = 0; i < 0x20000; i += 4)
{
// Generate new random numbers.
while (!se_gen_prng128(random_numbers))
;
// Clamp offsets to 512MBrange.
random_offsets[i + 0] = random_numbers[0] % 0x100000;
random_offsets[i + 1] = random_numbers[1] % 0x100000;
random_offsets[i + 2] = random_numbers[2] % 0x100000;
random_offsets[i + 3] = random_numbers[3] % 0x100000;
}
pct = 0;
prevPct = 200;
timer = 0;
data_remaining = 0x100000; // 512MB.
while (data_remaining)
{
u32 time_taken = get_tmr_us();
sdmmc_storage_read(storage, sector + random_offsets[lba_idx], sector_num, (u8 *)MIXD_BUF_ALIGNED);
time_taken = get_tmr_us() - time_taken;
timer += time_taken;
manual_system_maintenance(false);
data_remaining -= sector_num;
lba_idx++;
pct = (lba_idx * 100) / 0x20000;
if (pct != prevPct)
{
lv_bar_set_value(bar, pct);
manual_system_maintenance(true);
prevPct = pct;
if (btn_read_vol() == (BTN_VOL_UP | BTN_VOL_DOWN))
break;
}
}
lv_bar_set_value(bar, 100);
// Calculate rate and IOPS for 512MB transfer.
rate_1k = ((u64)512 * 1000 * 1000 * 1000) / timer;
iops_1k = ((u64)512 * 1024 * 1000 * 1000 * 1000) / (4096 / 1024) / timer / 1000;
s_printf(txt_buf + strlen(txt_buf),
" Random 4KiB - Rate: #C7EA46 %3d.%02d MiB/s#, IOPS: #C7EA46 %4d#\n",
rate_1k / 1000, (rate_1k % 1000) / 10, iops_1k);
lv_label_set_text(lbl_status, txt_buf);
lv_obj_align(lbl_status, NULL, LV_ALIGN_CENTER, 0, 0);
lv_obj_align(mbox, NULL, LV_ALIGN_CENTER, 0, 0);
manual_system_maintenance(true);
free(random_offsets);
}
lv_obj_del(bar);
@@ -1300,8 +1430,10 @@ static lv_res_t _create_mbox_benchmark(bool sd_bench)
else
sdmmc_storage_end(&emmc_storage);
}
free(txt_buf);
lv_mbox_add_btns(mbox, mbox_btn_map, mbox_action); // Important. After set_text.
lv_obj_align(mbox, NULL, LV_ALIGN_CENTER, 0, 0);
return LV_RES_OK;
}
@@ -1332,14 +1464,11 @@ static lv_res_t _create_window_emmc_info_status(lv_obj_t *btn)
lv_label_set_long_mode(lb_desc, LV_LABEL_LONG_BREAK);
lv_label_set_recolor(lb_desc, true);
sdmmc_storage_t storage;
sdmmc_t sdmmc;
char *txt_buf = (char *)malloc(0x4000);
txt_buf[0] = '\n';
txt_buf[1] = 0;
if (!sdmmc_storage_init_mmc(&storage, &sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400))
if (!sdmmc_storage_init_mmc(&emmc_storage, &emmc_sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400))
{
lv_label_set_text(lb_desc, "#FFDD00 Failed to init eMMC!#");
lv_obj_set_width(lb_desc, lv_obj_get_width(desc));
@@ -1350,14 +1479,15 @@ static lv_res_t _create_window_emmc_info_status(lv_obj_t *btn)
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;
u32 cache = emmc_storage.ext_csd.cache_size;
u32 life_a = emmc_storage.ext_csd.dev_life_est_a;
u32 life_b = emmc_storage.ext_csd.dev_life_est_b;
u16 card_type = emmc_storage.ext_csd.card_type;
char card_type_support[96];
card_type_support[0] = 0;
// Identify manufacturer. Only official eMMCs.
switch (storage.cid.manfid)
switch (emmc_storage.cid.manfid)
{
case 0x11:
strcat(txt_buf, "Toshiba ");
@@ -1365,16 +1495,20 @@ static lv_res_t _create_window_emmc_info_status(lv_obj_t *btn)
case 0x15:
strcat(txt_buf, "Samsung ");
break;
case 0x45: // Unofficial.
strcat(txt_buf, "SanDisk ");
break;
case 0x90:
strcat(txt_buf, "SK Hynix ");
break;
}
s_printf(txt_buf + strlen(txt_buf), "(%02X)\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,
storage.cid.prod_name[0], storage.cid.prod_name[1], storage.cid.prod_name[2],
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);
s_printf(txt_buf + strlen(txt_buf), "(%02X)\n%c%c%c%c%c%c\n%d.%d\n%04X\n%02d/%04d\n\n",
emmc_storage.cid.manfid,
emmc_storage.cid.prod_name[0], emmc_storage.cid.prod_name[1], emmc_storage.cid.prod_name[2],
emmc_storage.cid.prod_name[3], emmc_storage.cid.prod_name[4], emmc_storage.cid.prod_name[5],
emmc_storage.cid.prv & 0xF, emmc_storage.cid.prv >> 4,
emmc_storage.cid.serial, emmc_storage.cid.month, emmc_storage.cid.year);
if (card_type & EXT_CSD_CARD_TYPE_HS_26)
{
@@ -1406,7 +1540,7 @@ static lv_res_t _create_window_emmc_info_status(lv_obj_t *btn)
strcpy(life_b_txt, "-");
// Normalize cells life.
if (life_a)
if (life_a) // SK Hynix is 0 (undefined).
{
life_a--;
life_a = (10 - life_a) * 10;
@@ -1420,7 +1554,7 @@ static lv_res_t _create_window_emmc_info_status(lv_obj_t *btn)
s_printf(life_b_txt, "%d%%", life_b);
}
switch (storage.ext_csd.pre_eol_info)
switch (emmc_storage.ext_csd.pre_eol_info)
{
case 1:
rsvd_blocks = "Normal (< 80%)";
@@ -1429,7 +1563,7 @@ static lv_res_t _create_window_emmc_info_status(lv_obj_t *btn)
rsvd_blocks = "Warning (> 80%)";
break;
case 3:
rsvd_blocks = "Urgent (> 90%)";
rsvd_blocks = "Critical (> 90%)";
break;
default:
rsvd_blocks = "#FF8000 Unknown#";
@@ -1437,25 +1571,28 @@ static lv_res_t _create_window_emmc_info_status(lv_obj_t *btn)
}
s_printf(txt_buf + strlen(txt_buf),
"#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, life_a_txt, life_b_txt, rsvd_blocks);
"#00DDFF V1.%d (rev 1.%d)#\n%02X\n%d MB/s (%d MHz)\n%d MB/s\n%s\n%d %s\n%d MiB\nA: %s, B: %s\n%s",
emmc_storage.ext_csd.ext_struct, emmc_storage.ext_csd.rev,
emmc_storage.csd.cmdclass, speed & 0xFFFF, (speed >> 16) & 0xFFFF,
emmc_storage.csd.busspeed, card_type_support,
!(cache % 1024) ? (cache / 1024) : cache, !(cache % 1024) ? "MiB" : "KiB",
emmc_storage.ext_csd.max_enh_mult * 512 / 1024,
life_a_txt, life_b_txt, rsvd_blocks);
lv_label_set_static_text(lb_desc,
"#00DDFF CID:#\n"
"Vendor ID:\n"
"Card/BGA:\n"
"OEM ID:\n"
"Model:\n"
"Prd Rev:\n"
"Prod Rev:\n"
"S/N:\n"
"Month/Year:\n\n"
"#00DDFF Ext CSD#\n"
"#00DDFF Ext CSD:#\n"
"Cmd Classes:\n"
"Max Rate:\n"
"Current Rate:\n"
"Type Support:\n\n"
"Write Cache:\n"
"Enhanced Area:\n"
"Estimated Life:\n"
"Reserved Used:"
);
@@ -1477,32 +1614,32 @@ static lv_res_t _create_window_emmc_info_status(lv_obj_t *btn)
lv_obj_t * lb_desc2 = lv_label_create(desc2, lb_desc);
lv_label_set_style(lb_desc2, &monospace_text);
u32 boot_size = storage.ext_csd.boot_mult << 17;
u32 rpmb_size = storage.ext_csd.rpmb_mult << 17;
s_printf(txt_buf, "#00DDFF eMMC Physical Partitions:#\n");
s_printf(txt_buf + strlen(txt_buf), "1: #96FF00 BOOT0# Size: %5d KiB (Sect: 0x%08X)\n", boot_size / 1024, boot_size / 512);
s_printf(txt_buf + strlen(txt_buf), "2: #96FF00 BOOT1# Size: %5d KiB (Sect: 0x%08X)\n", boot_size / 1024, boot_size / 512);
s_printf(txt_buf + strlen(txt_buf), "3: #96FF00 RPMB# Size: %5d KiB (Sect: 0x%08X)\n", rpmb_size / 1024, rpmb_size / 512);
s_printf(txt_buf + strlen(txt_buf), "0: #96FF00 GPP# Size: %5d MiB (Sect: 0x%08X)\n\n", storage.sec_cnt >> SECTORS_TO_MIB_COEFF, storage.sec_cnt);
s_printf(txt_buf + strlen(txt_buf), "#00DDFF GPP (eMMC USER) Partition Table:#\n");
u32 boot_size = emmc_storage.ext_csd.boot_mult << 17;
u32 rpmb_size = emmc_storage.ext_csd.rpmb_mult << 17;
strcpy(txt_buf, "#00DDFF eMMC Physical Partitions:#\n");
s_printf(txt_buf + strlen(txt_buf), "1: #96FF00 BOOT0# Size: %6d KiB (Sect: 0x%08X)\n", boot_size / 1024, boot_size / 512);
s_printf(txt_buf + strlen(txt_buf), "2: #96FF00 BOOT1# Size: %6d KiB (Sect: 0x%08X)\n", boot_size / 1024, boot_size / 512);
s_printf(txt_buf + strlen(txt_buf), "3: #96FF00 RPMB# Size: %6d KiB (Sect: 0x%08X)\n", rpmb_size / 1024, rpmb_size / 512);
s_printf(txt_buf + strlen(txt_buf), "0: #96FF00 GPP# Size: %6d MiB (Sect: 0x%08X)\n", emmc_storage.sec_cnt >> SECTORS_TO_MIB_COEFF, emmc_storage.sec_cnt);
strcat(txt_buf, "\n#00DDFF GPP (eMMC USER) Partition Table:#\n");
sdmmc_storage_set_mmc_partition(&storage, EMMC_GPP);
sdmmc_storage_set_mmc_partition(&emmc_storage, EMMC_GPP);
LIST_INIT(gpt);
nx_emmc_gpt_parse(&gpt, &storage);
nx_emmc_gpt_parse(&gpt, &emmc_storage);
u32 idx = 0;
LIST_FOREACH_ENTRY(emmc_part_t, part, &gpt, link)
{
if (idx > 10)
{
strcat(txt_buf, "#FFDD00 Table truncated!#");
strcat(txt_buf, "#FFDD00 Table does not fit on screen!#");
break;
}
if (part->index < 2)
{
s_printf(txt_buf + strlen(txt_buf), "%02d: #96FF00 %s# ", part->index, part->name);
s_printf(txt_buf + strlen(txt_buf), " Size: %d MiB (Sect: 0x%X), Start: %06X\n",
s_printf(txt_buf + strlen(txt_buf), "%02d: #96FF00 %s#%s Size: %d MiB (Sect: 0x%X), Start: %06X\n",
part->index, part->name, !part->name[8] ? " " : "",
(part->lba_end - part->lba_start + 1) >> SECTORS_TO_MIB_COEFF,
part->lba_end - part->lba_start + 1, part->lba_start);
}
@@ -1515,6 +1652,9 @@ static lv_res_t _create_window_emmc_info_status(lv_obj_t *btn)
idx++;
}
if (!idx)
strcat(txt_buf, "#FFDD00 Partition table is empty!#");
nx_emmc_gpt_free(&gpt);
lv_label_set_text(lb_desc2, txt_buf);
@@ -1522,7 +1662,7 @@ static lv_res_t _create_window_emmc_info_status(lv_obj_t *btn)
lv_obj_align(desc2, val, LV_ALIGN_OUT_RIGHT_MID, LV_DPI / 6, 0);
}
sdmmc_storage_end(&storage);
sdmmc_storage_end(&emmc_storage);
free(txt_buf);
return LV_RES_OK;
@@ -1555,8 +1695,8 @@ static lv_res_t _create_window_sdcard_info_status(lv_obj_t *btn)
lv_label_set_text(lb_desc,
"#00DDFF Card IDentification:#\n"
"Vendor ID:\n"
"OEM ID:\n"
"Model:\n"
"OEM ID:\n"
"HW rev:\n"
"FW rev:\n"
"S/N:\n"
@@ -1614,10 +1754,11 @@ static lv_res_t _create_window_sdcard_info_status(lv_obj_t *btn)
break;
}
s_printf(txt_buf + strlen(txt_buf), "(%02X)\n%c%c\n%c%c%c%c%c\n%X\n%X\n%08x\n%02d/%04d\n\n",
sd_storage.cid.manfid, (sd_storage.cid.oemid >> 8) & 0xFF, sd_storage.cid.oemid & 0xFF,
s_printf(txt_buf + strlen(txt_buf), "(%02X)\n%c%c%c%c%c\n%c%c\n%X\n%X\n%08x\n%02d/%04d\n\n",
sd_storage.cid.manfid,
sd_storage.cid.prod_name[0], sd_storage.cid.prod_name[1], sd_storage.cid.prod_name[2],
sd_storage.cid.prod_name[3], sd_storage.cid.prod_name[4],
(sd_storage.cid.oemid >> 8) & 0xFF, sd_storage.cid.oemid & 0xFF,
sd_storage.cid.hwrev, sd_storage.cid.fwrev, sd_storage.cid.serial,
sd_storage.cid.month, sd_storage.cid.year);
@@ -1686,7 +1827,7 @@ static lv_res_t _create_window_sdcard_info_status(lv_obj_t *btn)
}
bool uhs_au_mb = false;
u32 uhs_au_size = sd_storage_ssr_get_au(&sd_storage);
u32 uhs_au_size = sd_storage_get_ssr_au(&sd_storage);
if (uhs_au_size >= 1024)
{
uhs_au_mb = true;
@@ -2122,8 +2263,8 @@ void create_tab_info(lv_theme_t *th, lv_obj_t *parent)
lv_obj_t *label_txt4 = lv_label_create(h1, NULL);
lv_label_set_recolor(label_txt4, true);
lv_label_set_static_text(label_txt4,
"View and dump your cached #C7EA46 Fuses# and #C7EA46 KFuses#.\n"
"Fuses contain info about your SoC and device and KFuses contain HDCP.\n"
"View and dump the cached #C7EA46 Fuses# and #C7EA46 KFuses#.\n"
"Fuses contain info about the SoC/SKU and KFuses HDCP keys.\n"
"You can also see info about #C7EA46 DRAM#, #C7EA46 Screen# and #C7EA46 Touch panel#.");
lv_obj_set_style(label_txt4, &hint_small_style);
lv_obj_align(label_txt4, btn3, LV_ALIGN_OUT_BOTTOM_LEFT, 0, LV_DPI / 3);
@@ -2172,7 +2313,7 @@ void create_tab_info(lv_theme_t *th, lv_obj_t *parent)
lv_obj_t *label_txt5 = lv_label_create(h2, NULL);
lv_label_set_recolor(label_txt5, true);
lv_label_set_static_text(label_txt5,
"View info about your eMMC or microSD and their partition list.\n"
"View info about the eMMC or microSD and their partition list.\n"
"Additionally you can benchmark read speeds.");
lv_obj_set_style(label_txt5, &hint_small_style);
lv_obj_align(label_txt5, btn5, LV_ALIGN_OUT_BOTTOM_LEFT, 0, LV_DPI / 3);

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2018-2019 CTCaer
* Copyright (c) 2018-2021 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
@@ -842,10 +842,10 @@ disabled:;
// Check if pairing info was found.
if (joycon_found == 2)
strcat(txt_buf, "#C7EA46 Found 2 out of 2 Joy-Con pairing data!#\n");
strcat(txt_buf, "#C7EA46 Success!#\n#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);
s_printf(txt_buf + strlen(txt_buf), "#FF8000 Failed!#\n#FF8000 Warning:# Found #FFDD00 %d out of 2# pairing data!\n", joycon_found);
success = false;
}
@@ -927,7 +927,7 @@ static void _check_nyx_changes()
lv_mbox_set_text(mbox,
"#FF8000 Nyx configuration#\n\n"
"You changed your configuration!\n\n"
"You changed the configuration!\n\n"
"Do you want to save it?");
lv_mbox_add_btns(mbox, mbox_btn_map, _action_nyx_options_save);

View File

@@ -1,6 +1,6 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2020 CTCaer
* Copyright (c) 2018-2021 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
@@ -71,18 +71,16 @@ static lv_obj_t *_create_container(lv_obj_t *parent)
bool get_autorcm_status(bool change)
{
u8 corr_mod0, mod1;
sdmmc_storage_t storage;
sdmmc_t sdmmc;
bool enabled = false;
if (h_cfg.t210b01)
return false;
sdmmc_storage_init_mmc(&storage, &sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400);
sdmmc_storage_init_mmc(&emmc_storage, &emmc_sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400);
u8 *tempbuf = (u8 *)malloc(0x200);
sdmmc_storage_set_mmc_partition(&storage, EMMC_BOOT0);
sdmmc_storage_read(&storage, 0x200 / NX_EMMC_BLOCKSIZE, 1, tempbuf);
sdmmc_storage_set_mmc_partition(&emmc_storage, EMMC_BOOT0);
sdmmc_storage_read(&emmc_storage, 0x200 / NX_EMMC_BLOCKSIZE, 1, tempbuf);
// Get the correct RSA modulus byte masks.
nx_emmc_get_autorcm_masks(&corr_mod0, &mod1);
@@ -103,20 +101,20 @@ bool get_autorcm_status(bool change)
for (i = 0; i < 4; i++)
{
sect = (0x200 + (0x4000 * i)) / NX_EMMC_BLOCKSIZE;
sdmmc_storage_read(&storage, sect, 1, tempbuf);
sdmmc_storage_read(&emmc_storage, sect, 1, tempbuf);
if (!enabled)
tempbuf[0x10] = 0;
else
tempbuf[0x10] = corr_mod0;
sdmmc_storage_write(&storage, sect, 1, tempbuf);
sdmmc_storage_write(&emmc_storage, sect, 1, tempbuf);
}
enabled = !(enabled);
}
out:
free(tempbuf);
sdmmc_storage_end(&storage);
sdmmc_storage_end(&emmc_storage);
return enabled;
}
@@ -607,7 +605,7 @@ void nyx_run_ums(void *param)
u32 *cfg = (u32 *)param;
u8 type = (*cfg) >> 24;
*cfg = *cfg & 0xFFFFFF;
*cfg = *cfg & (~NYX_CFG_EXTRA);
// Disable read only flag.
usb_msc_emmc_read_only = false;
@@ -691,7 +689,7 @@ static lv_res_t _create_window_usb_tools(lv_obj_t *parent)
lv_obj_t *label_txt2 = lv_label_create(h1, NULL);
lv_label_set_recolor(label_txt2, true);
lv_label_set_static_text(label_txt2,
"Allows you to mount your SD Card to a PC/Phone.\n"
"Allows you to mount the SD Card to a PC/Phone.\n"
"#C7EA46 All operating systems are supported. Access is# #FF8000 Read/Write.#");
lv_obj_set_style(label_txt2, &hint_small_style);
@@ -737,7 +735,7 @@ static lv_res_t _create_window_usb_tools(lv_obj_t *parent)
label_txt2 = lv_label_create(h1, NULL);
lv_label_set_recolor(label_txt2, true);
lv_label_set_static_text(label_txt2,
"Allows you to mount your eMMC/emuMMC.\n"
"Allows you to mount the eMMC/emuMMC.\n"
"#C7EA46 Default access is# #FF8000 read-only.#");
lv_obj_set_style(label_txt2, &hint_small_style);
lv_obj_align(label_txt2, btn_emu_gpp, LV_ALIGN_OUT_BOTTOM_LEFT, 0, LV_DPI / 3);
@@ -788,8 +786,8 @@ static lv_res_t _create_window_usb_tools(lv_obj_t *parent)
lv_obj_t *label_txt4 = lv_label_create(h2, NULL);
lv_label_set_recolor(label_txt4, true);
lv_label_set_static_text(label_txt4,
"Plug-in your Joy-Con and convert your device\n"
"into a gamepad for your PC/Phone.\n"
"Plug-in the Joy-Con and convert the device\n"
"into a gamepad for PC or Phone.\n"
"#C7EA46 Needs both Joy-Con in order to function.#");
lv_obj_set_style(label_txt4, &hint_small_style);
@@ -806,7 +804,7 @@ static lv_res_t _create_window_usb_tools(lv_obj_t *parent)
label_txt4 = lv_label_create(h2, NULL);
lv_label_set_recolor(label_txt4, true);
lv_label_set_static_text(label_txt4,
"Control your PC via your device touchscreen.\n"
"Control the PC via the device\'s touchscreen.\n"
"#C7EA46 Two fingers tap acts like a# #FF8000 Right click##C7EA46 .#\n");
lv_obj_set_style(label_txt4, &hint_small_style);
lv_obj_align(label_txt4, btn4, LV_ALIGN_OUT_BOTTOM_LEFT, 0, LV_DPI / 3);
@@ -1095,19 +1093,14 @@ static lv_res_t _create_window_dump_pk12_tool(lv_obj_t *btn)
char *txt_buf = (char *)malloc(0x4000);
tsec_ctxt_t tsec_ctxt;
sdmmc_storage_t storage;
sdmmc_t sdmmc;
if (!sdmmc_storage_init_mmc(&storage, &sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400))
if (!sdmmc_storage_init_mmc(&emmc_storage, &emmc_sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400))
{
lv_label_set_text(lb_desc, "#FFDD00 Failed to init eMMC!#");
goto out_free;
}
sdmmc_storage_set_mmc_partition(&storage, EMMC_BOOT0);
sdmmc_storage_set_mmc_partition(&emmc_storage, EMMC_BOOT0);
// Read package1.
static const u32 BOOTLOADER_SIZE = 0x40000;
@@ -1116,7 +1109,7 @@ static lv_res_t _create_window_dump_pk12_tool(lv_obj_t *btn)
char *build_date = malloc(32);
u32 pk1_offset = h_cfg.t210b01 ? sizeof(bl_hdr_t210b01_t) : 0; // Skip T210B01 OEM header.
sdmmc_storage_read(&storage, BOOTLOADER_MAIN_OFFSET / NX_EMMC_BLOCKSIZE, BOOTLOADER_SIZE / NX_EMMC_BLOCKSIZE, pkg1);
sdmmc_storage_read(&emmc_storage, BOOTLOADER_MAIN_OFFSET / NX_EMMC_BLOCKSIZE, BOOTLOADER_SIZE / NX_EMMC_BLOCKSIZE, pkg1);
const pkg1_id_t *pkg1_id = pkg1_identify(pkg1 + pk1_offset, build_date);
@@ -1128,11 +1121,11 @@ static lv_res_t _create_window_dump_pk12_tool(lv_obj_t *btn)
// Dump package1 in its encrypted state if unknown.
if (!pkg1_id)
{
strcat(txt_buf, "#FFDD00 Unknown pkg1 version for reading#\n#FFDD00 TSEC firmware!#");
strcat(txt_buf, "#FFDD00 Unknown pkg1 version!#");
lv_label_set_text(lb_desc, txt_buf);
manual_system_maintenance(true);
emmcsn_path_impl(path, "/pkg1", "pkg1_enc.bin", &storage);
emmcsn_path_impl(path, "/pkg1", "pkg1_enc.bin", &emmc_storage);
if (sd_save_to_file(pkg1, BOOTLOADER_SIZE, path))
goto out_free;
@@ -1147,6 +1140,7 @@ static lv_res_t _create_window_dump_pk12_tool(lv_obj_t *btn)
if (!h_cfg.se_keygen_done)
{
tsec_ctxt_t tsec_ctxt;
tsec_ctxt.fw = (void *)(pkg1 + pkg1_id->tsec_off);
tsec_ctxt.pkg1 = (void *)pkg1;
tsec_ctxt.pkg11_off = pkg1_id->pkg11_off;
@@ -1164,9 +1158,23 @@ static lv_res_t _create_window_dump_pk12_tool(lv_obj_t *btn)
h_cfg.sept_run = true;
else
{
// Check that BCT is proper so sept can run.
u8 *bct_bldr = (u8 *)calloc(1, 512);
sdmmc_storage_read(&emmc_storage, 0x2200 / NX_EMMC_BLOCKSIZE, 1, bct_bldr);
u32 bootloader_entrypoint = *(u32 *)&bct_bldr[0x144];
free(bct_bldr);
if (bootloader_entrypoint > SEPT_PRI_ENTRY)
{
lv_label_set_text(lb_desc, "#FFDD00 Failed to run sept because main BCT is improper!#\n"
"#FFDD00 Run sept with proper BCT at least once to cache keys.#\n");
goto out_free;
}
// Set boot cfg.
b_cfg->autoboot = 0;
b_cfg->autoboot_list = 0;
b_cfg->extra_cfg = EXTRA_CFG_NYX_DUMP;
b_cfg->extra_cfg = EXTRA_CFG_NYX_SEPT;
b_cfg->sept = NYX_SEPT_DUMP;
if (!reboot_to_sept((u8 *)tsec_ctxt.fw, kb))
{
@@ -1178,7 +1186,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, HOS_KEYBLOBS_OFFSET / NX_EMMC_BLOCKSIZE + kb, 1, keyblob);
sdmmc_storage_read(&emmc_storage, HOS_KEYBLOBS_OFFSET / NX_EMMC_BLOCKSIZE + kb, 1, keyblob);
// Decrypt.
hos_keygen(keyblob, kb, &tsec_ctxt);
@@ -1230,7 +1238,7 @@ static lv_res_t _create_window_dump_pk12_tool(lv_obj_t *btn)
manual_system_maintenance(true);
// Dump package1.1.
emmcsn_path_impl(path, "/pkg1", "pkg1_decr.bin", &storage);
emmcsn_path_impl(path, "/pkg1", "pkg1_decr.bin", &emmc_storage);
if (sd_save_to_file(pkg1, 0x40000, path))
goto out_free;
strcat(txt_buf, "pkg1 dumped to pkg1_decr.bin\n");
@@ -1238,7 +1246,7 @@ static lv_res_t _create_window_dump_pk12_tool(lv_obj_t *btn)
manual_system_maintenance(true);
// Dump nxbootloader.
emmcsn_path_impl(path, "/pkg1", "nxloader.bin", &storage);
emmcsn_path_impl(path, "/pkg1", "nxloader.bin", &emmc_storage);
if (sd_save_to_file(loader, hdr_pk11->ldr_size, path))
goto out_free;
strcat(txt_buf, "NX Bootloader dumped to nxloader.bin\n");
@@ -1246,7 +1254,7 @@ static lv_res_t _create_window_dump_pk12_tool(lv_obj_t *btn)
manual_system_maintenance(true);
// Dump secmon.
emmcsn_path_impl(path, "/pkg1", "secmon.bin", &storage);
emmcsn_path_impl(path, "/pkg1", "secmon.bin", &emmc_storage);
if (sd_save_to_file(secmon, hdr_pk11->sm_size, path))
goto out_free;
strcat(txt_buf, "Secure Monitor dumped to secmon.bin\n");
@@ -1254,7 +1262,7 @@ static lv_res_t _create_window_dump_pk12_tool(lv_obj_t *btn)
manual_system_maintenance(true);
// Dump warmboot.
emmcsn_path_impl(path, "/pkg1", "warmboot.bin", &storage);
emmcsn_path_impl(path, "/pkg1", "warmboot.bin", &emmc_storage);
if (sd_save_to_file(warmboot, hdr_pk11->wb_size, path))
goto out_free;
// If T210B01, save a copy of decrypted warmboot binary also.
@@ -1263,7 +1271,7 @@ static lv_res_t _create_window_dump_pk12_tool(lv_obj_t *btn)
se_aes_iv_clear(13);
se_aes_crypt_cbc(13, 0, warmboot + 0x330, hdr_pk11->wb_size - 0x330, warmboot + 0x330, hdr_pk11->wb_size - 0x330);
emmcsn_path_impl(path, "/pkg1", "warmboot_dec.bin", &storage);
emmcsn_path_impl(path, "/pkg1", "warmboot_dec.bin", &emmc_storage);
if (sd_save_to_file(warmboot, hdr_pk11->wb_size, path))
goto out_free;
}
@@ -1273,10 +1281,10 @@ static lv_res_t _create_window_dump_pk12_tool(lv_obj_t *btn)
}
// Dump package2.1.
sdmmc_storage_set_mmc_partition(&storage, EMMC_GPP);
sdmmc_storage_set_mmc_partition(&emmc_storage, EMMC_GPP);
// Parse eMMC GPT.
LIST_INIT(gpt);
nx_emmc_gpt_parse(&gpt, &storage);
nx_emmc_gpt_parse(&gpt, &emmc_storage);
// Find package2 partition.
emmc_part_t *pkg2_part = nx_emmc_part_find(&gpt, "BCPKG2-1-Normal-Main");
if (!pkg2_part)
@@ -1284,17 +1292,17 @@ static lv_res_t _create_window_dump_pk12_tool(lv_obj_t *btn)
// Read in package2 header and get package2 real size.
u8 *tmp = (u8 *)malloc(NX_EMMC_BLOCKSIZE);
nx_emmc_part_read(&storage, pkg2_part, 0x4000 / NX_EMMC_BLOCKSIZE, 1, tmp);
nx_emmc_part_read(&emmc_storage, pkg2_part, 0x4000 / NX_EMMC_BLOCKSIZE, 1, tmp);
u32 *hdr_pkg2_raw = (u32 *)(tmp + 0x100);
u32 pkg2_size = hdr_pkg2_raw[0] ^ hdr_pkg2_raw[2] ^ hdr_pkg2_raw[3];
free(tmp);
// Read in package2.
u32 pkg2_size_aligned = ALIGN(pkg2_size, NX_EMMC_BLOCKSIZE);
pkg2 = malloc(pkg2_size_aligned);
nx_emmc_part_read(&storage, pkg2_part, 0x4000 / NX_EMMC_BLOCKSIZE,
nx_emmc_part_read(&emmc_storage, pkg2_part, 0x4000 / NX_EMMC_BLOCKSIZE,
pkg2_size_aligned / NX_EMMC_BLOCKSIZE, pkg2);
#if 0
emmcsn_path_impl(path, "/pkg2", "pkg2_encr.bin", &storage);
emmcsn_path_impl(path, "/pkg2", "pkg2_encr.bin", &emmc_storage);
if (sd_save_to_file(pkg2, pkg2_size_aligned, path))
goto out;
gfx_puts("\npkg2 dumped to pkg2_encr.bin\n");
@@ -1326,7 +1334,7 @@ static lv_res_t _create_window_dump_pk12_tool(lv_obj_t *btn)
manual_system_maintenance(true);
// Dump pkg2.1.
emmcsn_path_impl(path, "/pkg2", "pkg2_decr.bin", &storage);
emmcsn_path_impl(path, "/pkg2", "pkg2_decr.bin", &emmc_storage);
if (sd_save_to_file(pkg2, pkg2_hdr->sec_size[PKG2_SEC_KERNEL] + pkg2_hdr->sec_size[PKG2_SEC_INI1], path))
goto out;
strcat(txt_buf, "pkg2 dumped to pkg2_decr.bin\n");
@@ -1334,7 +1342,7 @@ static lv_res_t _create_window_dump_pk12_tool(lv_obj_t *btn)
manual_system_maintenance(true);
// Dump kernel.
emmcsn_path_impl(path, "/pkg2", "kernel.bin", &storage);
emmcsn_path_impl(path, "/pkg2", "kernel.bin", &emmc_storage);
if (sd_save_to_file(pkg2_hdr->data, pkg2_hdr->sec_size[PKG2_SEC_KERNEL], path))
goto out;
strcat(txt_buf, "Kernel dumped to kernel.bin\n");
@@ -1358,7 +1366,7 @@ static lv_res_t _create_window_dump_pk12_tool(lv_obj_t *btn)
}
pkg2_ini1_t *ini1 = (pkg2_ini1_t *)(pkg2_hdr->data + ini1_off);
emmcsn_path_impl(path, "/pkg2", "ini1.bin", &storage);
emmcsn_path_impl(path, "/pkg2", "ini1.bin", &emmc_storage);
if (sd_save_to_file(ini1, ini1_size, path))
goto out;
@@ -1385,7 +1393,7 @@ static lv_res_t _create_window_dump_pk12_tool(lv_obj_t *btn)
kip1 = (pkg2_kip1_t *)kip_buffer;
}
emmcsn_path_impl(path, "/pkg2/ini1", filename, &storage);
emmcsn_path_impl(path, "/pkg2/ini1", filename, &emmc_storage);
if (sd_save_to_file(kip1, kip1_size, path))
{
free(kip_buffer);
@@ -1409,7 +1417,7 @@ out_free:
free(loader);
free(pkg2);
free(txt_buf);
sdmmc_storage_end(&storage);
sdmmc_storage_end(&emmc_storage);
sd_unmount();
if (kb >= KB_FIRMWARE_VERSION_620)
@@ -1463,8 +1471,8 @@ static void _create_tab_tools_emmc_pkg12(lv_theme_t *th, lv_obj_t *parent)
lv_obj_t *label_txt2 = lv_label_create(h1, NULL);
lv_label_set_recolor(label_txt2, true);
lv_label_set_static_text(label_txt2,
"Allows you to backup your eMMC partitions individually or as\n"
"a whole raw image to your SD card.\n"
"Allows you to backup the eMMC partitions individually or as\n"
"a whole raw image to the SD card.\n"
"#C7EA46 Supports SD cards from# #FF8000 4GB# #C7EA46 and up. #"
"#FF8000 FAT32# #C7EA46 and ##FF8000 exFAT##C7EA46 .#");
lv_obj_set_style(label_txt2, &hint_small_style);
@@ -1480,8 +1488,8 @@ static void _create_tab_tools_emmc_pkg12(lv_theme_t *th, lv_obj_t *parent)
label_txt2 = lv_label_create(h1, NULL);
lv_label_set_recolor(label_txt2, true);
lv_label_set_static_text(label_txt2,
"Allows you to restore your eMMC/emuMMC partitions individually\n"
"or as a whole raw image from your SD card.\n"
"Allows you to restore the eMMC/emuMMC partitions individually\n"
"or as a whole raw image from the SD card.\n"
"#C7EA46 Supports SD cards from# #FF8000 4GB# #C7EA46 and up. #"
"#FF8000 FAT32# #C7EA46 and ##FF8000 exFAT##C7EA46 .#");
lv_obj_set_style(label_txt2, &hint_small_style);
@@ -1495,14 +1503,14 @@ static void _create_tab_tools_emmc_pkg12(lv_theme_t *th, lv_obj_t *parent)
lv_label_set_static_text(label_sep, "");
lv_obj_t *label_txt3 = lv_label_create(h2, NULL);
lv_label_set_static_text(label_txt3, "Misc");
lv_label_set_static_text(label_txt3, "SD Partitions & USB");
lv_obj_set_style(label_txt3, th->label.prim);
lv_obj_align(label_txt3, label_sep, LV_ALIGN_OUT_BOTTOM_LEFT, LV_DPI / 4, -LV_DPI * 3 / 10);
line_sep = lv_line_create(h2, line_sep);
lv_obj_align(line_sep, label_txt3, LV_ALIGN_OUT_BOTTOM_LEFT, -(LV_DPI / 4), LV_DPI / 8);
// Create Dump Package1/2 button.
// Create Partition SD Card button.
lv_obj_t *btn3 = lv_btn_create(h2, NULL);
if (hekate_bg)
{
@@ -1511,15 +1519,15 @@ static void _create_tab_tools_emmc_pkg12(lv_theme_t *th, lv_obj_t *parent)
}
label_btn = lv_label_create(btn3, NULL);
lv_btn_set_fit(btn3, true, true);
lv_label_set_static_text(label_btn, SYMBOL_MODULES" Dump Package1/2");
lv_label_set_static_text(label_btn, SYMBOL_SD" Partition SD Card");
lv_obj_align(btn3, line_sep, LV_ALIGN_OUT_BOTTOM_LEFT, LV_DPI / 4, LV_DPI / 4);
lv_btn_set_action(btn3, LV_BTN_ACTION_CLICK, _create_window_dump_pk12_tool);
lv_btn_set_action(btn3, LV_BTN_ACTION_CLICK, create_window_partition_manager);
lv_obj_t *label_txt4 = lv_label_create(h2, NULL);
lv_label_set_recolor(label_txt4, true);
lv_label_set_static_text(label_txt4,
"Allows you to dump and decrypt pkg1 and pkg2 and further\n"
"split it up into their individual parts. It also dumps the kip1.\n");
"Allows you to partition the SD Card for using it with #C7EA46 emuMMC#,\n"
"#C7EA46 Android# and #C7EA46 Linux#. You can also flash Linux and Android.\n");
lv_obj_set_style(label_txt4, &hint_small_style);
lv_obj_align(label_txt4, btn3, LV_ALIGN_OUT_BOTTOM_LEFT, 0, LV_DPI / 3);
@@ -1539,7 +1547,7 @@ static void _create_tab_tools_emmc_pkg12(lv_theme_t *th, lv_obj_t *parent)
lv_label_set_static_text(label_txt4,
"#C7EA46 USB mass storage#, #C7EA46 gamepad# and other USB tools.\n"
"Mass storage can mount SD, eMMC and emuMMC. The\n"
"gamepad transforms your Switch into an input device.#");
"gamepad transforms the Switch into an input device.#");
lv_obj_set_style(label_txt4, &hint_small_style);
lv_obj_align(label_txt4, btn4, LV_ALIGN_OUT_BOTTOM_LEFT, 0, LV_DPI / 3);
}
@@ -1598,7 +1606,7 @@ static void _create_tab_tools_arc_autorcm(lv_theme_t *th, lv_obj_t *parent)
label_txt2 = lv_label_create(h1, NULL);
lv_label_set_recolor(label_txt2, true);
lv_label_set_static_text(label_txt2,
"Allows you to calibrate your touchscreen module.\n"
"Allows you to calibrate the touchscreen module.\n"
"#FF8000 This fixes any issues with touchscreen in Nyx and HOS.#");
lv_obj_set_style(label_txt2, &hint_small_style);
lv_obj_align(label_txt2, btn2, LV_ALIGN_OUT_BOTTOM_LEFT, 0, LV_DPI / 3);
@@ -1653,7 +1661,7 @@ static void _create_tab_tools_arc_autorcm(lv_theme_t *th, lv_obj_t *parent)
s_printf(txt_buf,
"Allows you to enter RCM without using #C7EA46 VOL+# & #C7EA46 HOME# (jig).\n"
"#FF8000 It can restore all versions of AutoRCM whenever requested.#\n"
"#FF3C28 This corrupts your BCT and you can't boot without a custom#\n"
"#FF3C28 This corrupts the BCT and you can't boot without a custom#\n"
"#FF3C28 bootloader.#");
if (h_cfg.rcm_patched)
@@ -1671,18 +1679,18 @@ static void _create_tab_tools_arc_autorcm(lv_theme_t *th, lv_obj_t *parent)
lv_label_set_static_text(label_sep, "");
lv_obj_align(label_sep, label_txt4, LV_ALIGN_OUT_BOTTOM_LEFT, 0, LV_DPI * 11 / 7);
// Create Partition SD Card button.
// Create Dump Package1/2 button.
lv_obj_t *btn4 = lv_btn_create(h2, btn);
label_btn = lv_label_create(btn4, NULL);
lv_label_set_static_text(label_btn, SYMBOL_SD" Partition SD Card");
lv_label_set_static_text(label_btn, SYMBOL_MODULES" Dump Package1/2");
lv_obj_align(btn4, label_txt4, LV_ALIGN_OUT_BOTTOM_LEFT, 0, LV_DPI / 2);
lv_btn_set_action(btn4, LV_BTN_ACTION_CLICK, create_window_partition_manager);
lv_btn_set_action(btn4, LV_BTN_ACTION_CLICK, _create_window_dump_pk12_tool);
label_txt2 = lv_label_create(h2, NULL);
lv_label_set_recolor(label_txt2, true);
lv_label_set_static_text(label_txt2,
"Allows you to partition your SD Card for using it with #C7EA46 emuMMC#,\n"
"#C7EA46 Android# and #C7EA46 Linux#. You can also flash Linux and Android.");
"Allows you to dump and decrypt pkg1 and pkg2 and further\n"
"split it up into their individual parts. It also dumps the kip1.");
lv_obj_set_style(label_txt2, &hint_small_style);
lv_obj_align(label_txt2, btn4, LV_ALIGN_OUT_BOTTOM_LEFT, 0, LV_DPI / 3);
}
@@ -1707,8 +1715,8 @@ void create_tab_tools(lv_theme_t *th, lv_obj_t *parent)
lv_tabview_set_sliding(tv, false);
lv_tabview_set_btns_pos(tv, LV_TABVIEW_BTNS_POS_BOTTOM);
lv_obj_t *tab1= lv_tabview_add_tab(tv, "eMMC "SYMBOL_DOT" Pkg1/2 "SYMBOL_DOT" USB Tools");
lv_obj_t *tab2 = lv_tabview_add_tab(tv, "Arch bit "SYMBOL_DOT" RCM "SYMBOL_DOT" Touch "SYMBOL_DOT" Partitions");
lv_obj_t *tab1= lv_tabview_add_tab(tv, "eMMC "SYMBOL_DOT" SD Partitions "SYMBOL_DOT" USB");
lv_obj_t *tab2 = lv_tabview_add_tab(tv, "Arch bit "SYMBOL_DOT" RCM "SYMBOL_DOT" Touch "SYMBOL_DOT" Pkg1/2");
lv_obj_t *line_sep = lv_line_create(tv, NULL);
static const lv_point_t line_pp[] = { {0, 0}, { 0, LV_DPI / 4} };

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2019-2020 CTCaer
* Copyright (c) 2019-2021 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
@@ -48,6 +48,8 @@ typedef struct _partition_ctxt_t
u32 l4t_size;
u32 and_size;
bool emu_double;
mbr_t *mbr_old;
lv_obj_t *bar_hos;
@@ -134,7 +136,12 @@ static int _backup_and_restore_files(char *path, u32 *total_files, u32 *total_si
// Check for overflow.
if ((file_size + *total_size) < *total_size)
{
// Set size to > 1GB, skip next folders and return.
*total_size = 0x80000000;
res = -1;
break;
}
*total_size += file_size;
*total_files += 1;
@@ -177,7 +184,11 @@ static int _backup_and_restore_files(char *path, u32 *total_files, u32 *total_si
// If total is > 1GB exit.
if (*total_size > (RAM_DISK_SZ - 0x1000000)) // 0x2400000.
{
// Skip next folders and return.
res = -1;
break;
}
}
else // It's a directory.
{
@@ -235,26 +246,20 @@ static void _prepare_and_flash_mbr_gpt()
if (part_info.l4t_size && !part_info.and_size)
{
mbr.partitions[mbr_idx].type = 0x83; // Linux system partition.
mbr.partitions[mbr_idx].start_sct = 0x8000 + (part_info.hos_size << 11);
mbr.partitions[mbr_idx].start_sct = 0x8000 + ((u32)part_info.hos_size << 11);
mbr.partitions[mbr_idx].size_sct = part_info.l4t_size << 11;
sdmmc_storage_write(&sd_storage, mbr.partitions[mbr_idx].start_sct, 0x800, (void *)SDMMC_UPPER_BUFFER); // Clear the first 1MB.
mbr_idx++;
}
// emuMMC goes second or third. Next to L4T if no Android.
bool double_emummc = part_info.emu_size > 29856;
if (part_info.emu_size)
{
mbr.partitions[mbr_idx].type = 0xE0; // emuMMC partition.
mbr.partitions[mbr_idx].start_sct = 0x8000 + (part_info.hos_size << 11) + (part_info.l4t_size << 11) + (part_info.and_size << 11);
mbr.partitions[mbr_idx].start_sct = 0x8000 + ((u32)part_info.hos_size << 11) + (part_info.l4t_size << 11) + (part_info.and_size << 11);
if (!double_emummc)
{
if (!part_info.and_size)
mbr.partitions[mbr_idx].size_sct = part_info.emu_size << 11;
else
mbr.partitions[mbr_idx].size_sct = (part_info.emu_size << 11) - 0x800; // Reserve 1MB.
}
if (!part_info.emu_double)
mbr.partitions[mbr_idx].size_sct = (part_info.emu_size << 11) - 0x800; // Reserve 1MB.
else
{
mbr.partitions[mbr_idx].type = 0xE0; // emuMMC partition.
@@ -263,10 +268,7 @@ static void _prepare_and_flash_mbr_gpt()
// 2nd emuMMC.
mbr.partitions[mbr_idx].start_sct = mbr.partitions[mbr_idx - 1].start_sct + (part_info.emu_size << 10);
if (!part_info.and_size)
mbr.partitions[mbr_idx].size_sct = part_info.emu_size << 10;
else
mbr.partitions[mbr_idx].size_sct = (part_info.emu_size << 10) - 0x800; // Reserve 1MB.
mbr.partitions[mbr_idx].size_sct = (part_info.emu_size << 10) - 0x800; // Reserve 1MB.
}
mbr_idx++;
}
@@ -306,7 +308,7 @@ static void _prepare_and_flash_mbr_gpt()
memcpy(gpt.entries[0].name, (char[]) { 'h', 0, 'o', 0, 's', 0, '_', 0, 'd', 0, 'a', 0, 't', 0, 'a', 0 }, 16);
u8 gpt_idx = 1;
u32 curr_part_lba = 0x8000 + (part_info.hos_size << 11);
u32 curr_part_lba = 0x8000 + ((u32)part_info.hos_size << 11);
u8 android_part_guid[] = { 0xAF, 0x3D, 0xC6, 0x0F, 0x83, 0x84, 0x72, 0x47, 0x8E, 0x79, 0x3D, 0x69, 0xD8, 0x47, 0x7D, 0xE4 };
if (part_info.l4t_size)
{
@@ -411,7 +413,7 @@ static void _prepare_and_flash_mbr_gpt()
gpt_idx++;
// Android Userdata partition.
u32 user_size = (part_info.and_size << 11) - 0x798000 - curr_part_lba; // Subtract the other partitions (3888MB).
u32 user_size = (part_info.and_size << 11) - 0x798000; // Subtract the other partitions (3888MB).
if (!part_info.emu_size)
user_size -= 0x800; // Reserve 1MB.
memcpy(gpt.entries[gpt_idx].type_guid, android_part_guid, 16);
@@ -431,14 +433,14 @@ static void _prepare_and_flash_mbr_gpt()
se_gen_prng128(random_number);
memcpy(gpt.entries[gpt_idx].part_guid, random_number, 16);
gpt.entries[gpt_idx].lba_start = curr_part_lba;
if (!double_emummc)
if (!part_info.emu_double)
gpt.entries[gpt_idx].lba_end = curr_part_lba + (part_info.emu_size << 11) - 0x800 - 1; // Reserve 1MB.
else
gpt.entries[gpt_idx].lba_end = curr_part_lba + (part_info.emu_size << 10); // Reserve 1MB.
gpt.entries[gpt_idx].lba_end = curr_part_lba + (part_info.emu_size << 10) - 1;
memcpy(gpt.entries[gpt_idx].name, (char[]) { 'e', 0, 'm', 0, 'u', 0, 'm', 0, 'm', 0, 'c', 0 }, 12);
gpt_idx++;
if (double_emummc)
if (part_info.emu_double)
{
curr_part_lba += (part_info.emu_size << 10);
memcpy(gpt.entries[gpt_idx].type_guid, emu_part_guid, 16);
@@ -1283,7 +1285,7 @@ static lv_res_t _create_mbox_start_partitioning(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", "\222OK", "\211", "" };
static const char *mbox_btn_map1[] = { "\222SD UMS", "\222Flash Linux", "\222Flash Android", "\221OK", "" };
static const char *mbox_btn_map2[] = { "\222SD UMS", "\222Flash Linux", "\221OK", "" };
static const char *mbox_btn_map3[] = { "\222SD UMS", "\222Flash Android", "\221OK", "" };
@@ -1364,7 +1366,7 @@ static lv_res_t _create_mbox_start_partitioning(lv_obj_t *btn)
lv_label_set_text(lbl_paths[0], "Please wait...");
lv_obj_align(mbox, NULL, LV_ALIGN_CENTER, 0, 0);
manual_system_maintenance(true);
if (ram_disk_init(&ram_fs))
if (ram_disk_init(&ram_fs, RAM_DISK_SZ))
{
lv_label_set_text(lbl_status, "#FFDD00 Error:# Failed to initialize Ramdisk!");
goto error;
@@ -1616,7 +1618,7 @@ static lv_res_t _create_mbox_partitioning_next(lv_obj_t *btn)
lv_obj_t *lbl_status = lv_label_create(mbox, NULL);
lv_label_set_recolor(lbl_status, true);
s_printf(txt_buf, "#FFDD00 Warning: This will partition your SD Card!#\n\n");
s_printf(txt_buf, "#FFDD00 Warning: This will partition the SD Card!#\n\n");
if (part_info.backup_possible)
strcat(txt_buf, "#C7EA46 Your files will be backed up and restored!#\n#FFDD00Any other partition will be wiped!#");
@@ -1668,12 +1670,33 @@ static void _update_partition_bar()
static lv_res_t _action_slider_emu(lv_obj_t *slider)
{
u32 size;
char lbl_text[64];
bool prev_emu_double = part_info.emu_double;
int slide_val = lv_slider_get_value(slider);
u32 size = slide_val ? ((slide_val < 2) ? 29856 : 59712) : 0;
s32 hos_size = (part_info.total_sct >> 11) - 16 - size - part_info.l4t_size - part_info.and_size;
const u32 rsvd_mb = 4 + 4 + 16 + 8; // BOOT0 + BOOT1 + 16MB offset + 8MB alignment.
part_info.emu_double = false;
size = (slide_val > 10 ? (slide_val - 10) : slide_val) + 3; // Min 4GB.
size *= 1024; // Convert to GB.
size += rsvd_mb; // Add reserved size.
if (!slide_val)
size = 0; // Reset if 0.
else if (slide_val >= 11)
{
size *= 2;
part_info.emu_double = true;
}
// Handle special case.
if (slide_val == 10)
size = 29856;
else if (slide_val == 20)
size = 59712;
s32 hos_size = (part_info.total_sct >> 11) - 16 - size - part_info.l4t_size - part_info.and_size;
if (hos_size > 2048)
{
part_info.emu_size = size;
@@ -1683,28 +1706,40 @@ static lv_res_t _action_slider_emu(lv_obj_t *slider)
lv_label_set_text(part_info.lbl_hos, lbl_text);
lv_bar_set_value(part_info.slider_bar_hos, hos_size >> 10);
if (slide_val < 2)
s_printf(lbl_text, "#FF3C28 %d GiB#", size >> 10);
if (!part_info.emu_double)
{
if (slide_val != 10)
s_printf(lbl_text, "#FF3C28 %d GiB#", size >> 10);
else
s_printf(lbl_text, "#FF3C28 %d FULL#", size >> 10);
}
else
s_printf(lbl_text, "#FF3C28 2x%d GiB#", size >> 11);
s_printf(lbl_text, "#FFDD00 2x##FF3C28 %d#", size >> 11);
lv_label_set_text(part_info.lbl_emu, lbl_text);
}
else
{
int new_slider_val;
switch (part_info.emu_size)
u32 emu_size = part_info.emu_size;
if (emu_size == 29856)
emu_size = 10;
else if (emu_size == 59712)
emu_size = 20;
else if (emu_size)
{
case 29856:
new_slider_val = 1;
break;
case 59712:
new_slider_val = 2;
break;
case 0:
default:
new_slider_val = 0;
break;
if (prev_emu_double)
emu_size /= 2;
emu_size -= rsvd_mb;
emu_size /= 1024;
emu_size -= 3;
if (prev_emu_double)
emu_size += 11;
}
int new_slider_val = emu_size;
part_info.emu_double = prev_emu_double ? true : false;
lv_slider_set_value(slider, new_slider_val);
}
@@ -1858,15 +1893,15 @@ static void create_mbox_check_files_total_size()
path[0] = 0;
// Check total size of files.
_backup_and_restore_files(path, &total_files, &total_size, NULL, NULL, NULL);
int res = _backup_and_restore_files(path, &total_files, &total_size, NULL, NULL, NULL);
// Not more than 1.0GB.
part_info.backup_possible = !(total_size > (RAM_DISK_SZ - 0x1000000)); // 0x2400000
part_info.backup_possible = !res && !(total_size > (RAM_DISK_SZ - 0x1000000)); // 0x2400000
if (part_info.backup_possible)
{
s_printf(txt_buf,
"#96FF00 Your SD Card files will be backed up automatically!#\n"
"#96FF00 The SD Card files will be backed up automatically!#\n"
"#FFDD00 Any other partition will be wiped!#\n"
"#00DDFF Total files:# %d, #00DDFF Total size:# %d MiB", total_files, total_size >> 20);
lv_mbox_set_text(mbox, txt_buf);
@@ -1874,7 +1909,7 @@ static void create_mbox_check_files_total_size()
else
{
lv_mbox_set_text(mbox,
"#FFDD00 Your SD Card cannot be backed up!#\n\n"
"#FFDD00 The SD Card cannot be backed up!#\n\n"
"You will be asked to back up your files later via UMS.");
}
@@ -1987,7 +2022,8 @@ static lv_res_t _action_fix_mbr(lv_obj_t *btn)
lv_obj_t *lbl_status = lv_label_create(mbox, NULL);
lv_label_set_recolor(lbl_status, true);
if (!sd_mount())
// Try to init sd card. No need for valid MBR.
if (!sd_mount() && !sd_get_card_initialized())
{
lv_label_set_text(lbl_status, "#FFDD00 Failed to init SD!#");
goto out;
@@ -2308,7 +2344,7 @@ lv_res_t create_window_partition_manager(lv_obj_t *btn)
lv_obj_t *slider_emu = lv_slider_create(h1, NULL);
lv_obj_set_size(slider_emu, LV_DPI * 7, LV_DPI / 3);
lv_slider_set_range(slider_emu, 0, 2);
lv_slider_set_range(slider_emu, 0, 20);
lv_slider_set_value(slider_emu, 0);
lv_slider_set_style(slider_emu, LV_SLIDER_STYLE_BG, &bar_emu_bg);
lv_slider_set_style(slider_emu, LV_SLIDER_STYLE_INDIC, &bar_emu_ind);
@@ -2365,9 +2401,9 @@ lv_res_t create_window_partition_manager(lv_obj_t *btn)
lv_label_set_recolor(lbl_notes, true);
lv_label_set_static_text(lbl_notes,
"Note 1: Only up to #C7EA46 1GB# can be backed up. If more, you will be asked to back them manually at the next step.\n"
"Note 2: The #C7EA46 Flash Linux# and #C7EA46 Flash Android# work independently and will flash files if suitable partitions and installer files are found.\n"
"Note 3: The installation files reside in #C7EA46 switchroot/install# folder. Linux uses #C7EA46 l4t.XX# and Android uses #C7EA46 twrp.img# and #C7EA46 tegra210-icosa.dtb#.\n"
"Note 4: #FFDD00 The installation files will be deleted after a successful flashing.#");
"Note 2: Resized emuMMC formats the USER partition. A save data manager can be used to move them over.\n"
"Note 3: The #C7EA46 Flash Linux# and #C7EA46 Flash Android# will flash files if suitable partitions and installer files are found.\n"
"Note 4: The installation folder is #C7EA46 switchroot/install#. Linux uses #C7EA46 l4t.XX# and Android uses #C7EA46 twrp.img# and #C7EA46 tegra210-icosa.dtb#.");
lv_label_set_style(lbl_notes, &hint_small_style);
lv_obj_align(lbl_notes, lbl_and, LV_ALIGN_OUT_BOTTOM_LEFT, 0, LV_DPI / 5);
@@ -2378,7 +2414,7 @@ lv_res_t create_window_partition_manager(lv_obj_t *btn)
lv_obj_align(btn1, h1, LV_ALIGN_IN_TOP_LEFT, 0, LV_DPI * 5);
lv_btn_set_action(btn1, LV_BTN_ACTION_CLICK, _action_part_manager_ums_sd);
lv_obj_t *btn_flash_l4t = lv_btn_create(h1, NULL);
btn_flash_l4t = lv_btn_create(h1, NULL);
lv_obj_t *label_btn2 = lv_label_create(btn_flash_l4t, NULL);
lv_btn_set_fit(btn_flash_l4t, true, true);
lv_label_set_static_text(label_btn2, SYMBOL_DOWNLOAD" Flash Linux");

View File

@@ -1,6 +1,6 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2020 CTCaer
* Copyright (c) 2018-2021 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
@@ -379,11 +379,13 @@ void gfx_printf(const char *fmt, ...)
va_end(ap);
}
void gfx_hexdump(u32 base, const u8 *buf, u32 len)
void gfx_hexdump(u32 base, const void *buf, u32 len)
{
if (gfx_con.mute)
return;
u8 *buff = (u8 *)buf;
u8 prevFontSize = gfx_con.fntsz;
gfx_con.fntsz = 8;
for(u32 i = 0; i < len; i++)
@@ -395,7 +397,7 @@ void gfx_hexdump(u32 base, const u8 *buf, u32 len)
gfx_puts("| ");
for(u32 j = 0; j < 0x10; j++)
{
u8 c = buf[i - 0x10 + j];
u8 c = buff[i - 0x10 + j];
if(c >= 32 && c <= 126)
gfx_putc(c);
else
@@ -405,7 +407,7 @@ void gfx_hexdump(u32 base, const u8 *buf, u32 len)
}
gfx_printf("%08x: ", base + i);
}
gfx_printf("%02x ", buf[i]);
gfx_printf("%02x ", buff[i]);
if (i == len - 1)
{
int ln = len % 0x10 != 0;
@@ -419,7 +421,7 @@ void gfx_hexdump(u32 base, const u8 *buf, u32 len)
gfx_puts("| ");
for(u32 j = 0; j < (ln ? k : k + 1); j++)
{
u8 c = buf[i - k + j];
u8 c = buff[i - k + j];
if(c >= 32 && c <= 126)
gfx_putc(c);
else

View File

@@ -1,6 +1,6 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2020 CTCaer
* Copyright (c) 2018-2021 CTCaer
* Copyright (c) 2018 M4xw
*
* This program is free software; you can redistribute it and/or modify it
@@ -62,7 +62,7 @@ void gfx_con_setpos(u32 x, u32 y);
void gfx_putc(char c);
void gfx_puts(char *s);
void gfx_printf(const char *fmt, ...);
void gfx_hexdump(u32 base, const u8 *buf, u32 len);
void gfx_hexdump(u32 base, const void *buf, u32 len);
void gfx_set_pixel(u32 x, u32 y, u32 color);

View File

@@ -2,7 +2,7 @@
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018 st4rk
* Copyright (c) 2018 Ced2911
* Copyright (c) 2018-2020 CTCaer
* Copyright (c) 2018-2021 CTCaer
* Copyright (c) 2018 balika011
*
* This program is free software; you can redistribute it and/or modify it
@@ -45,7 +45,29 @@ extern hekate_config h_cfg;
static u8 *bis_keys = NULL;
static const u8 keyblob_keyseeds[][0x10] = {
typedef struct _tsec_keys_t
{
u8 tsec[SE_KEY_128_SIZE];
u8 tsec_root[SE_KEY_128_SIZE];
u8 tmp[SE_KEY_128_SIZE];
} tsec_keys_t;
typedef struct _kb_keys_t
{
u8 master_keyseed[SE_KEY_128_SIZE];
u8 random_data[0x70];
u8 package1_key[SE_KEY_128_SIZE];
} kb_keys_t;
typedef struct _kb_t
{
u8 cmac[SE_KEY_128_SIZE];
u8 ctr[SE_AES_IV_SIZE];
kb_keys_t keys;
u8 padding[0x150];
} kb_t;
static const u8 keyblob_keyseeds[][SE_KEY_128_SIZE] = {
{ 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.
{ 0x33, 0x76, 0x85, 0xEE, 0x88, 0x4A, 0xAE, 0x0A, 0xC2, 0x8A, 0xFD, 0x7D, 0x63, 0xC0, 0x43, 0x3B }, // 3.0.1.
@@ -54,19 +76,19 @@ static const u8 keyblob_keyseeds[][0x10] = {
{ 0xD8, 0xCC, 0xE1, 0x26, 0x6A, 0x35, 0x3F, 0xCC, 0x20, 0xF3, 0x2D, 0x3B, 0x51, 0x7D, 0xE9, 0xC0 } // 6.0.0.
};
static const u8 cmac_keyseed[0x10] =
static const u8 cmac_keyseed[SE_KEY_128_SIZE] =
{ 0x59, 0xC7, 0xFB, 0x6F, 0xBE, 0x9B, 0xBE, 0x87, 0x65, 0x6B, 0x15, 0xC0, 0x53, 0x73, 0x36, 0xA5 };
static const u8 master_keyseed_retail[0x10] =
static const u8 master_keyseed_retail[SE_KEY_128_SIZE] =
{ 0xD8, 0xA2, 0x41, 0x0A, 0xC6, 0xC5, 0x90, 0x01, 0xC6, 0x1D, 0x6A, 0x26, 0x7C, 0x51, 0x3F, 0x3C };
static const u8 master_keyseed_4xx_5xx_610[0x10] =
static const u8 master_keyseed_4xx_5xx_610[SE_KEY_128_SIZE] =
{ 0x2D, 0xC1, 0xF4, 0x8D, 0xF3, 0x5B, 0x69, 0x33, 0x42, 0x10, 0xAC, 0x65, 0xDA, 0x90, 0x46, 0x66 };
static const u8 master_keyseed_620[0x10] =
static const u8 master_keyseed_620[SE_KEY_128_SIZE] =
{ 0x37, 0x4B, 0x77, 0x29, 0x59, 0xB4, 0x04, 0x30, 0x81, 0xF6, 0xE5, 0x8C, 0x6D, 0x36, 0x17, 0x9A };
static const u8 master_kekseed_t210b01[][0x10] = {
static const u8 master_kekseed_t210b01[][SE_KEY_128_SIZE] = {
{ 0x77, 0x60, 0x5A, 0xD2, 0xEE, 0x6E, 0xF8, 0x3C, 0x3F, 0x72, 0xE2, 0x59, 0x9D, 0xAC, 0x5E, 0x56 }, // 6.0.0.
{ 0x1E, 0x80, 0xB8, 0x17, 0x3E, 0xC0, 0x60, 0xAA, 0x11, 0xBE, 0x1A, 0x4A, 0xA6, 0x6F, 0xE4, 0xAE }, // 6.2.0.
{ 0x94, 0x08, 0x67, 0xBD, 0x0A, 0x00, 0x38, 0x84, 0x11, 0xD3, 0x1A, 0xDB, 0xDD, 0x8D, 0xF1, 0x8A }, // 7.0.0.
@@ -75,16 +97,16 @@ static const u8 master_kekseed_t210b01[][0x10] = {
{ 0x0E, 0x44, 0x0C, 0xED, 0xB4, 0x36, 0xC0, 0x3F, 0xAA, 0x1D, 0xAE, 0xBF, 0x62, 0xB1, 0x09, 0x82 }, // 9.1.0.
};
static const u8 console_keyseed[0x10] =
static const u8 console_keyseed[SE_KEY_128_SIZE] =
{ 0x4F, 0x02, 0x5F, 0x0E, 0xB6, 0x6D, 0x11, 0x0E, 0xDC, 0x32, 0x7D, 0x41, 0x86, 0xC2, 0xF4, 0x78 };
static const u8 console_keyseed_4xx_5xx[0x10] =
static const u8 console_keyseed_4xx_5xx[SE_KEY_128_SIZE] =
{ 0x0C, 0x91, 0x09, 0xDB, 0x93, 0x93, 0x07, 0x81, 0x07, 0x3C, 0xC4, 0x16, 0x22, 0x7C, 0x6C, 0x28 };
const u8 package2_keyseed[0x10] =
const u8 package2_keyseed[SE_KEY_128_SIZE] =
{ 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] = {
static const u8 mkey_vectors[KB_FIRMWARE_VERSION_MAX + 1][SE_KEY_128_SIZE] = {
{ 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.
{ 0xDE, 0xCF, 0xEB, 0xEB, 0x10, 0xAE, 0x74, 0xD8, 0xAD, 0x7C, 0xF4, 0x9E, 0x62, 0xE0, 0xE8, 0x72 }, // Mkey 01 encrypted with mkey 02.
@@ -98,7 +120,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[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][SE_KEY_128_SIZE] = {
{ 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.
@@ -109,7 +131,7 @@ static const u8 new_console_keyseed[KB_FIRMWARE_VERSION_MAX - KB_FIRMWARE_VERSIO
{ 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_kekseed[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][SE_KEY_128_SIZE] = {
{ 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.
@@ -120,19 +142,19 @@ static const u8 new_console_kekseed[KB_FIRMWARE_VERSION_MAX - KB_FIRMWARE_VERSIO
{ 0xCE, 0xFE, 0x41, 0x0F, 0x46, 0x9A, 0x30, 0xD6, 0xF2, 0xE9, 0x0C, 0x6B, 0xB7, 0x15, 0x91, 0x36 }, // 9.1.0 New Device Keygen Source.
};
static const u8 gen_keyseed[0x10] =
static const u8 gen_keyseed[SE_KEY_128_SIZE] =
{ 0x89, 0x61, 0x5E, 0xE0, 0x5C, 0x31, 0xB6, 0x80, 0x5F, 0xE5, 0x8F, 0x3D, 0xA2, 0x4F, 0x7A, 0xA8 };
static const u8 gen_kekseed[0x10] =
static const u8 gen_kekseed[SE_KEY_128_SIZE] =
{ 0x4D, 0x87, 0x09, 0x86, 0xC4, 0x5D, 0x20, 0x72, 0x2F, 0xBA, 0x10, 0x53, 0xDA, 0x92, 0xE8, 0xA9 };
static const u8 gen_keyseed_retail[0x10] =
static const u8 gen_keyseed_retail[SE_KEY_128_SIZE] =
{ 0xE2, 0xD6, 0xB8, 0x7A, 0x11, 0x9C, 0xB8, 0x80, 0xE8, 0x22, 0x88, 0x8A, 0x46, 0xFB, 0xA1, 0x95 };
static const u8 bis_kekseed[0x10] =
static const u8 bis_kekseed[SE_KEY_128_SIZE] =
{ 0x34, 0xC1, 0xA0, 0xC4, 0x82, 0x58, 0xF8, 0xB4, 0xFA, 0x9E, 0x5E, 0x6A, 0xDA, 0xFC, 0x7E, 0x4F };
static const u8 bis_keyseed[][0x10] = {
static const u8 bis_keyseed[][SE_KEY_128_SIZE] = {
{ 0xF8, 0x3F, 0x38, 0x6E, 0x2C, 0xD2, 0xCA, 0x32, 0xA8, 0x9A, 0xB9, 0xAA, 0x29, 0xBF, 0xC7, 0x48 }, // BIS 0 Crypt seed.
{ 0x7D, 0x92, 0xB0, 0x3A, 0xA8, 0xBF, 0xDE, 0xE1, 0xA7, 0x4C, 0x3B, 0x6E, 0x35, 0xCB, 0x71, 0x06 }, // BIS 0 Tweak seed.
{ 0x41, 0x00, 0x30, 0x49, 0xDD, 0xCC, 0xC0, 0x65, 0x64, 0x7A, 0x7E, 0xB4, 0x1E, 0xED, 0x9C, 0x5F }, // BIS 1 Crypt seed.
@@ -212,6 +234,8 @@ void hos_eks_save(u32 kb)
// If matching blob doesn't exist, create it.
bool update_eks = key_idx ? (h_cfg.eks->enabled[key_idx] < kb) : !h_cfg.eks->enabled[0];
// If old EKS version was found, update it.
update_eks |= h_cfg.eks->lot0 != FUSE(FUSE_OPT_LOT_CODE_0);
if (update_eks)
{
// Read EKS blob.
@@ -228,8 +252,8 @@ void hos_eks_save(u32 kb)
}
// Get keys.
u8 *keys = (u8 *)calloc(0x1000, 1);
se_get_aes_keys(keys + 0x800, keys, 0x10);
u8 *keys = (u8 *)calloc(0x2000, 1);
se_get_aes_keys(keys + 0x1000, keys, SE_KEY_128_SIZE);
// Set magic and personalized info.
h_cfg.eks->magic = HOS_EKS_MAGIC;
@@ -237,18 +261,18 @@ void hos_eks_save(u32 kb)
h_cfg.eks->lot0 = FUSE(FUSE_OPT_LOT_CODE_0);
// Copy new keys.
memcpy(h_cfg.eks->dkg, keys + 10 * 0x10, 0x10);
memcpy(h_cfg.eks->dkk, keys + 15 * 0x10, 0x10);
memcpy(h_cfg.eks->dkg, keys + 10 * SE_KEY_128_SIZE, SE_KEY_128_SIZE);
memcpy(h_cfg.eks->dkk, keys + 15 * SE_KEY_128_SIZE, SE_KEY_128_SIZE);
if (!h_cfg.aes_slots_new)
{
memcpy(h_cfg.eks->keys[key_idx].mkk, keys + 12 * 0x10, 0x10);
memcpy(h_cfg.eks->keys[key_idx].fdk, keys + 13 * 0x10, 0x10);
memcpy(h_cfg.eks->keys[key_idx].mkk, keys + 12 * SE_KEY_128_SIZE, SE_KEY_128_SIZE);
memcpy(h_cfg.eks->keys[key_idx].fdk, keys + 13 * SE_KEY_128_SIZE, SE_KEY_128_SIZE);
}
else // New sept slots.
{
memcpy(h_cfg.eks->keys[key_idx].mkk, keys + 13 * 0x10, 0x10);
memcpy(h_cfg.eks->keys[key_idx].fdk, keys + 12 * 0x10, 0x10);
memcpy(h_cfg.eks->keys[key_idx].mkk, keys + 13 * SE_KEY_128_SIZE, SE_KEY_128_SIZE);
memcpy(h_cfg.eks->keys[key_idx].fdk, keys + 12 * SE_KEY_128_SIZE, SE_KEY_128_SIZE);
}
// Encrypt EKS blob.
@@ -260,7 +284,6 @@ void hos_eks_save(u32 kb)
memcpy(mbr + 0x80, eks, sizeof(hos_eks_mbr_t));
hos_eks_rw_try(mbr, true);
free(eks);
free(keys);
out:
@@ -346,14 +369,14 @@ void hos_eks_bis_save()
h_cfg.eks->lot0 = FUSE(FUSE_OPT_LOT_CODE_0);
// Copy new keys.
memcpy(h_cfg.eks->bis_keys[0].crypt, bis_keys + (0 * 0x10), 0x10);
memcpy(h_cfg.eks->bis_keys[0].tweak, bis_keys + (1 * 0x10), 0x10);
memcpy(h_cfg.eks->bis_keys[0].crypt, bis_keys + (0 * SE_KEY_128_SIZE), SE_KEY_128_SIZE);
memcpy(h_cfg.eks->bis_keys[0].tweak, bis_keys + (1 * SE_KEY_128_SIZE), SE_KEY_128_SIZE);
memcpy(h_cfg.eks->bis_keys[1].crypt, bis_keys + (2 * 0x10), 0x10);
memcpy(h_cfg.eks->bis_keys[1].tweak, bis_keys + (3 * 0x10), 0x10);
memcpy(h_cfg.eks->bis_keys[1].crypt, bis_keys + (2 * SE_KEY_128_SIZE), SE_KEY_128_SIZE);
memcpy(h_cfg.eks->bis_keys[1].tweak, bis_keys + (3 * SE_KEY_128_SIZE), SE_KEY_128_SIZE);
memcpy(h_cfg.eks->bis_keys[2].crypt, bis_keys + (4 * 0x10), 0x10);
memcpy(h_cfg.eks->bis_keys[2].tweak, bis_keys + (5 * 0x10), 0x10);
memcpy(h_cfg.eks->bis_keys[2].crypt, bis_keys + (4 * SE_KEY_128_SIZE), SE_KEY_128_SIZE);
memcpy(h_cfg.eks->bis_keys[2].tweak, bis_keys + (5 * SE_KEY_128_SIZE), SE_KEY_128_SIZE);
// Encrypt EKS blob.
u8 *eks = calloc(512 , 1);
@@ -418,10 +441,11 @@ int hos_keygen_t210b01(u32 kb)
return 1;
}
int hos_keygen(u8 *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt)
int hos_keygen(void *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt)
{
u8 tmp[0x30];
u32 retries = 0;
tsec_keys_t tsec_keys;
kb_t *kb_data = (kb_t *)keyblob;
if (kb > KB_FIRMWARE_VERSION_MAX)
return 0;
@@ -449,9 +473,9 @@ int hos_keygen(u8 *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt)
// Get TSEC key.
if (kb <= KB_FIRMWARE_VERSION_620)
{
while (tsec_query(tmp, kb, tsec_ctxt) < 0)
while (tsec_query(&tsec_keys, kb, tsec_ctxt) < 0)
{
memset(tmp, 0x00, 0x20);
memset(&tsec_keys, 0x00, 0x20);
retries++;
// We rely on racing conditions, make sure we cover even the unluckiest cases.
@@ -473,13 +497,13 @@ int hos_keygen(u8 *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt)
if (h_cfg.eks && h_cfg.eks->enabled[key_idx] >= kb)
{
// Set Device keygen key to slot 10.
se_aes_key_set(10, h_cfg.eks->dkg, 0x10);
se_aes_key_set(10, h_cfg.eks->dkg, SE_KEY_128_SIZE);
// Set Master key to slot 12.
se_aes_key_set(12, h_cfg.eks->keys[key_idx].mkk, 0x10);
se_aes_key_set(12, h_cfg.eks->keys[key_idx].mkk, SE_KEY_128_SIZE);
// Set FW Device key key to slot 13.
se_aes_key_set(13, h_cfg.eks->keys[key_idx].fdk, 0x10);
se_aes_key_set(13, h_cfg.eks->keys[key_idx].fdk, SE_KEY_128_SIZE);
// Set Device key to slot 15.
se_aes_key_set(15, h_cfg.eks->dkk, 0x10);
se_aes_key_set(15, h_cfg.eks->dkk, SE_KEY_128_SIZE);
}
else
h_cfg.aes_slots_new = se_key_acc_ctrl_get(12) == 0x6A;
@@ -490,13 +514,13 @@ int hos_keygen(u8 *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt)
else if (kb == KB_FIRMWARE_VERSION_620)
{
// Set TSEC key.
se_aes_key_set(12, tmp, 0x10);
se_aes_key_set(12, tsec_keys.tsec, SE_KEY_128_SIZE);
// Set TSEC root key.
se_aes_key_set(13, tmp + 0x10, 0x10);
se_aes_key_set(13, tsec_keys.tsec_root, SE_KEY_128_SIZE);
// Decrypt keyblob and set keyslots
se_aes_crypt_block_ecb(12, 0, tmp + 0x20, keyblob_keyseeds[0]);
se_aes_unwrap_key(15, 14, tmp + 0x20);
se_aes_crypt_block_ecb(12, 0, tsec_keys.tmp, keyblob_keyseeds[0]);
se_aes_unwrap_key(15, 14, tsec_keys.tmp);
se_aes_unwrap_key(10, 15, console_keyseed_4xx_5xx);
se_aes_unwrap_key(15, 15, console_keyseed);
@@ -508,33 +532,37 @@ int hos_keygen(u8 *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt)
else
{
// Set TSEC key.
se_aes_key_set(13, tmp, 0x10);
se_aes_key_set(13, tsec_keys.tsec, SE_KEY_128_SIZE);
// Derive keyblob keys from TSEC+SBK.
se_aes_crypt_block_ecb(13, 0, tmp, keyblob_keyseeds[0]);
se_aes_unwrap_key(15, 14, tmp);
se_aes_crypt_block_ecb(13, 0, tmp, keyblob_keyseeds[kb]);
se_aes_unwrap_key(13, 14, tmp);
se_aes_crypt_block_ecb(13, 0, tsec_keys.tsec, keyblob_keyseeds[0]);
se_aes_unwrap_key(15, 14, tsec_keys.tsec);
se_aes_crypt_block_ecb(13, 0, tsec_keys.tsec, keyblob_keyseeds[kb]);
se_aes_unwrap_key(13, 14, tsec_keys.tsec);
// Clear SBK.
se_aes_key_clear(14);
if (!h_cfg.sbk_set)
se_aes_key_clear(14);
//TODO: verify keyblob CMAC.
//se_aes_unwrap_key(11, 13, cmac_keyseed);
//se_aes_cmac(tmp, 0x10, 11, keyblob + 0x10, 0xA0);
//if (!memcmp(keyblob, tmp, 0x10))
// return 0;
/*
// Verify keyblob CMAC.
u8 cmac[SE_KEY_128_SIZE];
se_aes_unwrap_key(11, 13, cmac_keyseed);
se_aes_cmac(cmac, SE_KEY_128_SIZE, 11, (void *)kb_data->ctr, sizeof(kb_data->ctr) + sizeof(kb_data->keys));
if (!memcmp(kb_data->cmac, cmac, SE_KEY_128_SIZE))
return 0;
*/
se_aes_crypt_block_ecb(13, 0, tmp, cmac_keyseed);
se_aes_crypt_block_ecb(13, 0, tsec_keys.tsec, cmac_keyseed);
se_aes_unwrap_key(11, 13, cmac_keyseed);
// Decrypt keyblob and set keyslots.
se_aes_crypt_ctr(13, keyblob + 0x20, 0x90, keyblob + 0x20, 0x90, keyblob + 0x10);
se_aes_key_set(11, keyblob + 0x20 + 0x80, 0x10); // Package1 key.
se_aes_key_set(12, keyblob + 0x20, 0x10);
se_aes_key_set(13, keyblob + 0x20, 0x10);
se_aes_crypt_ctr(13, &kb_data->keys, sizeof(kb_data->keys), &kb_data->keys, sizeof(kb_data->keys), kb_data->ctr);
se_aes_key_set(11, kb_data->keys.package1_key, SE_KEY_128_SIZE);
se_aes_key_set(12, kb_data->keys.master_keyseed, SE_KEY_128_SIZE);
se_aes_key_set(13, kb_data->keys.master_keyseed, SE_KEY_128_SIZE);
se_aes_crypt_block_ecb(12, 0, tmp, master_keyseed_retail);
se_aes_crypt_block_ecb(12, 0, tsec_keys.tsec, master_keyseed_retail);
switch (kb)
{
@@ -547,14 +575,16 @@ int hos_keygen(u8 *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt)
case KB_FIRMWARE_VERSION_400:
se_aes_unwrap_key(13, 15, console_keyseed_4xx_5xx);
se_aes_unwrap_key(15, 15, console_keyseed);
se_aes_unwrap_key(14, 12, master_keyseed_4xx_5xx_610);
if (!h_cfg.sbk_set) // Do not clear SBK if patched. In this context the below key is useless.
se_aes_unwrap_key(14, 12, master_keyseed_4xx_5xx_610);
se_aes_unwrap_key(12, 12, master_keyseed_retail);
break;
case KB_FIRMWARE_VERSION_500:
case KB_FIRMWARE_VERSION_600:
se_aes_unwrap_key(10, 15, console_keyseed_4xx_5xx);
se_aes_unwrap_key(15, 15, console_keyseed);
se_aes_unwrap_key(14, 12, master_keyseed_4xx_5xx_610);
if (!h_cfg.sbk_set) // Do not clear SBK if patched. In this context the below key is useless.
se_aes_unwrap_key(14, 12, master_keyseed_4xx_5xx_610);
se_aes_unwrap_key(12, 12, master_keyseed_retail);
break;
}
@@ -568,18 +598,18 @@ int hos_keygen(u8 *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt)
static void _hos_validate_sept_mkey(u32 kb)
{
u8 tmp_mkey[0x10];
u32 mkey_idx = sizeof(mkey_vectors) / 0x10;
u8 tmp_mkey[SE_KEY_128_SIZE];
u32 mkey_idx = sizeof(mkey_vectors) / SE_KEY_128_SIZE;
u8 mkey_slot = !h_cfg.aes_slots_new ? 12 : 13;
do
{
mkey_idx--;
se_aes_crypt_ecb(mkey_slot, 0, tmp_mkey, 0x10, mkey_vectors[mkey_idx], 0x10);
se_aes_crypt_ecb(mkey_slot, 0, tmp_mkey, SE_KEY_128_SIZE, mkey_vectors[mkey_idx], SE_KEY_128_SIZE);
for (u32 idx = 0; idx < mkey_idx; idx++)
{
se_aes_key_clear(2);
se_aes_key_set(2, tmp_mkey, 0x10);
se_aes_crypt_ecb(2, 0, tmp_mkey, 0x10, mkey_vectors[mkey_idx - 1 - idx], 0x10);
se_aes_key_set(2, tmp_mkey, SE_KEY_128_SIZE);
se_aes_crypt_ecb(2, 0, tmp_mkey, SE_KEY_128_SIZE, mkey_vectors[mkey_idx - 1 - idx], SE_KEY_128_SIZE);
}
if (!memcmp(tmp_mkey, "\x00\x00\x00\x00\x00\x00\x00\x00", 8))
@@ -597,23 +627,23 @@ static void _hos_validate_sept_mkey(u32 kb)
static void _hos_bis_print_key(u32 idx, u8 *key)
{
gfx_printf("BIS %d Crypt: ", idx);
for (int i = 0; i < 0x10; i++)
gfx_printf("%02X", key[((idx * 2 + 0) * 0x10) + i]);
for (int i = 0; i < SE_KEY_128_SIZE; i++)
gfx_printf("%02X", key[((idx * 2 + 0) * SE_KEY_128_SIZE) + i]);
gfx_puts("\n");
gfx_printf("BIS %d Tweak: ", idx);
for (int i = 0; i < 0x10; i++)
gfx_printf("%02X", key[((idx * 2 + 1) * 0x10) + i]);
for (int i = 0; i < SE_KEY_128_SIZE; i++)
gfx_printf("%02X", key[((idx * 2 + 1) * SE_KEY_128_SIZE) + i]);
gfx_puts("\n");
}
int hos_bis_keygen(u8 *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt)
int hos_bis_keygen(void *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt)
{
u32 keygen_rev = 0;
u32 console_key_slot = kb >= KB_FIRMWARE_VERSION_400 ? 15 : 13;
if (!bis_keys)
bis_keys = malloc(0x10 * 6);
bis_keys = malloc(SE_KEY_128_SIZE * 6);
if (!h_cfg.eks || !h_cfg.eks->enabled_bis)
{
@@ -627,8 +657,8 @@ int hos_bis_keygen(u8 *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt)
if (keygen_rev)
{
u8 tmp_mkey[0x10];
u32 mkey_idx = sizeof(mkey_vectors) / 0x10;
u8 tmp_mkey[SE_KEY_128_SIZE];
u32 mkey_idx = sizeof(mkey_vectors) / SE_KEY_128_SIZE;
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.
@@ -642,19 +672,19 @@ int hos_bis_keygen(u8 *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt)
do
{
mkey_idx--;
se_aes_crypt_ecb(mkey_slot, 0, tmp_mkey, 0x10, mkey_vectors[mkey_idx], 0x10);
se_aes_crypt_ecb(mkey_slot, 0, tmp_mkey, SE_KEY_128_SIZE, mkey_vectors[mkey_idx], SE_KEY_128_SIZE);
for (u32 idx = 0; idx < mkey_idx; idx++)
{
se_aes_key_clear(2);
se_aes_key_set(2, tmp_mkey, 0x10);
se_aes_crypt_ecb(2, 0, tmp_mkey, 0x10, mkey_vectors[mkey_idx - 1 - idx], 0x10);
se_aes_key_set(2, tmp_mkey, SE_KEY_128_SIZE);
se_aes_crypt_ecb(2, 0, tmp_mkey, SE_KEY_128_SIZE, mkey_vectors[mkey_idx - 1 - idx], SE_KEY_128_SIZE);
}
} while (memcmp(tmp_mkey, "\x00\x00\x00\x00\x00\x00\x00\x00", 8) != 0 && (mkey_idx - 1));
// Derive new device key.
se_aes_key_clear(1);
se_aes_unwrap_key(1, 10, new_console_keyseed[keygen_rev]); // Uses Device key 4x.
se_aes_crypt_ecb(10, 0, tmp_mkey, 0x10, new_console_keyseed[keygen_rev], 0x10); // Uses Device key 4x.
se_aes_crypt_ecb(10, 0, tmp_mkey, SE_KEY_128_SIZE, new_console_keyseed[keygen_rev], SE_KEY_128_SIZE); // Uses Device key 4x.
se_aes_unwrap_key(1, 2, new_console_kekseed[keygen_rev]); // Uses Master Key 0.
se_aes_unwrap_key(1, 1, tmp_mkey);
@@ -666,11 +696,11 @@ int hos_bis_keygen(u8 *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt)
se_aes_unwrap_key(2, console_key_slot, gen_keyseed_retail);
// Clear bis keys storage.
memset(bis_keys, 0, 0x10 * 6);
memset(bis_keys, 0, SE_KEY_128_SIZE * 6);
// Generate BIS 0 Keys.
se_aes_crypt_block_ecb(2, 0, bis_keys + (0 * 0x10), bis_keyseed[0]);
se_aes_crypt_block_ecb(2, 0, bis_keys + (1 * 0x10), bis_keyseed[1]);
se_aes_crypt_block_ecb(2, 0, bis_keys + (0 * SE_KEY_128_SIZE), bis_keyseed[0]);
se_aes_crypt_block_ecb(2, 0, bis_keys + (1 * SE_KEY_128_SIZE), bis_keyseed[1]);
// Generate generic kek.
se_aes_key_clear(2);
@@ -679,26 +709,26 @@ int hos_bis_keygen(u8 *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt)
se_aes_unwrap_key(2, 2, gen_keyseed);
// Generate BIS 1 Keys.
se_aes_crypt_block_ecb(2, 0, bis_keys + (2 * 0x10), bis_keyseed[2]);
se_aes_crypt_block_ecb(2, 0, bis_keys + (3 * 0x10), bis_keyseed[3]);
se_aes_crypt_block_ecb(2, 0, bis_keys + (2 * SE_KEY_128_SIZE), bis_keyseed[2]);
se_aes_crypt_block_ecb(2, 0, bis_keys + (3 * SE_KEY_128_SIZE), bis_keyseed[3]);
// Generate BIS 2/3 Keys.
se_aes_crypt_block_ecb(2, 0, bis_keys + (4 * 0x10), bis_keyseed[4]);
se_aes_crypt_block_ecb(2, 0, bis_keys + (5 * 0x10), bis_keyseed[5]);
se_aes_crypt_block_ecb(2, 0, bis_keys + (4 * SE_KEY_128_SIZE), bis_keyseed[4]);
se_aes_crypt_block_ecb(2, 0, bis_keys + (5 * SE_KEY_128_SIZE), bis_keyseed[5]);
if (!h_cfg.t210b01 && kb >= KB_FIRMWARE_VERSION_700)
_hos_validate_sept_mkey(kb);
}
else
{
memcpy(bis_keys + (0 * 0x10), h_cfg.eks->bis_keys[0].crypt, 0x10);
memcpy(bis_keys + (1 * 0x10), h_cfg.eks->bis_keys[0].tweak, 0x10);
memcpy(bis_keys + (0 * SE_KEY_128_SIZE), h_cfg.eks->bis_keys[0].crypt, SE_KEY_128_SIZE);
memcpy(bis_keys + (1 * SE_KEY_128_SIZE), h_cfg.eks->bis_keys[0].tweak, SE_KEY_128_SIZE);
memcpy(bis_keys + (2 * 0x10), h_cfg.eks->bis_keys[1].crypt, 0x10);
memcpy(bis_keys + (3 * 0x10), h_cfg.eks->bis_keys[1].tweak, 0x10);
memcpy(bis_keys + (2 * SE_KEY_128_SIZE), h_cfg.eks->bis_keys[1].crypt, SE_KEY_128_SIZE);
memcpy(bis_keys + (3 * SE_KEY_128_SIZE), h_cfg.eks->bis_keys[1].tweak, SE_KEY_128_SIZE);
memcpy(bis_keys + (4 * 0x10), h_cfg.eks->bis_keys[2].crypt, 0x10);
memcpy(bis_keys + (5 * 0x10), h_cfg.eks->bis_keys[2].tweak, 0x10);
memcpy(bis_keys + (4 * SE_KEY_128_SIZE), h_cfg.eks->bis_keys[2].crypt, SE_KEY_128_SIZE);
memcpy(bis_keys + (5 * SE_KEY_128_SIZE), h_cfg.eks->bis_keys[2].tweak, SE_KEY_128_SIZE);
}
_hos_bis_print_key(0, bis_keys);
@@ -710,14 +740,14 @@ int hos_bis_keygen(u8 *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt)
se_aes_key_clear(i);
// Set BIS keys.
se_aes_key_set(0, bis_keys + (0 * 0x10), 0x10);
se_aes_key_set(1, bis_keys + (1 * 0x10), 0x10);
se_aes_key_set(0, bis_keys + (0 * SE_KEY_128_SIZE), SE_KEY_128_SIZE);
se_aes_key_set(1, bis_keys + (1 * SE_KEY_128_SIZE), SE_KEY_128_SIZE);
se_aes_key_set(2, bis_keys + (2 * 0x10), 0x10);
se_aes_key_set(3, bis_keys + (3 * 0x10), 0x10);
se_aes_key_set(2, bis_keys + (2 * SE_KEY_128_SIZE), SE_KEY_128_SIZE);
se_aes_key_set(3, bis_keys + (3 * SE_KEY_128_SIZE), SE_KEY_128_SIZE);
se_aes_key_set(4, bis_keys + (4 * 0x10), 0x10);
se_aes_key_set(5, bis_keys + (5 * 0x10), 0x10);
se_aes_key_set(4, bis_keys + (4 * SE_KEY_128_SIZE), SE_KEY_128_SIZE);
se_aes_key_set(5, bis_keys + (5 * SE_KEY_128_SIZE), SE_KEY_128_SIZE);
return 1;
}
@@ -742,7 +772,7 @@ void hos_bis_keys_clear()
FUSE(FUSE_PRIVATE_KEY3)
};
// Set SBK to slot 14.
se_aes_key_set(14, sbk, 0x10);
se_aes_key_set(14, sbk, SE_KEY_128_SIZE);
// Lock SBK from being read.
se_key_acc_ctrl(14, SE_KEY_TBL_DIS_KEYREAD_FLAG);

View File

@@ -1,6 +1,6 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2020 CTCaer
* Copyright (c) 2018-2021 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
@@ -20,6 +20,7 @@
#include "pkg1.h"
#include "pkg2.h"
#include <sec/se_t210.h>
#include <utils/types.h>
#include <utils/ini.h>
#include <sec/tsec.h>
@@ -44,14 +45,14 @@
typedef struct _hos_eks_keys_t
{
u8 mkk[0x10];
u8 fdk[0x10];
u8 mkk[SE_KEY_128_SIZE];
u8 fdk[SE_KEY_128_SIZE];
} hos_eks_keys_t;
typedef struct _hos_eks_bis_keys_t
{
u8 crypt[0x10];
u8 tweak[0x10];
u8 crypt[SE_KEY_128_SIZE];
u8 tweak[SE_KEY_128_SIZE];
} hos_eks_bis_keys_t;
typedef struct _hos_eks_mbr_t
@@ -61,8 +62,8 @@ typedef struct _hos_eks_mbr_t
u8 enabled_bis;
u8 rsvd[2];
u32 lot0;
u8 dkg[0x10];
u8 dkk[0x10];
u8 dkg[SE_KEY_128_SIZE];
u8 dkk[SE_KEY_128_SIZE];
hos_eks_keys_t keys[5];
hos_eks_bis_keys_t bis_keys[3];
} hos_eks_mbr_t;
@@ -98,8 +99,8 @@ void hos_eks_save(u32 kb);
void hos_eks_clear(u32 kb);
void hos_eks_bis_save();
void hos_eks_bis_clear();
int hos_keygen(u8 *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt);
int hos_bis_keygen(u8 *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt);
int hos_keygen(void *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt);
int hos_bis_keygen(void *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt);
void hos_bis_keys_clear();
#endif

View File

@@ -94,8 +94,9 @@ int pkg1_decrypt(const pkg1_id_t *id, u8 *pkg1)
hdr = (pk11_hdr_t *)(pkg1 + id->pkg11_off + 0x20);
// Use BEK for T210B01.
// Additionally, skip 0x20 bytes from decryption to maintain the header.
se_aes_iv_clear(13);
se_aes_crypt_cbc(13, 0, pkg1 + 0x20, oem_hdr->size, pkg1 + 0x20, oem_hdr->size);
se_aes_crypt_cbc(13, 0, pkg1 + 0x20, oem_hdr->size - 0x20, pkg1 + 0x20, oem_hdr->size - 0x20);
}
// Return if header is valid.

View File

@@ -24,6 +24,7 @@
#include <libs/fatfs/ff.h>
#include <mem/heap.h>
#include <sec/se.h>
#include <sec/se_t210.h>
#include <libs/compr/blz.h>
#include <gfx_utils.h>
@@ -111,7 +112,7 @@ DPRINTF(" kip1 %d:%s @ %08X (%08X)\n", i, kip1->name, (u32)kip1, ki->size);
return true;
}
static const u8 mkey_vector_8xx[][0x10] =
static const u8 mkey_vector_8xx[][SE_KEY_128_SIZE] =
{
// Master key 8 encrypted with 9. (8.1.0 with 9.0.0)
{ 0x4D, 0xD9, 0x98, 0x42, 0x45, 0x0D, 0xB1, 0x3C, 0x52, 0x0C, 0x9A, 0x44, 0xBB, 0xAD, 0xAF, 0x80 },
@@ -122,10 +123,10 @@ static const u8 mkey_vector_8xx[][0x10] =
static bool _pkg2_key_unwrap_validate(pkg2_hdr_t *tmp_test, pkg2_hdr_t *hdr, u8 src_slot, u8 *mkey, const u8 *key_seed)
{
// Decrypt older encrypted mkey.
se_aes_crypt_ecb(src_slot, 0, mkey, 0x10, key_seed, 0x10);
se_aes_crypt_ecb(src_slot, 0, mkey, SE_KEY_128_SIZE, key_seed, SE_KEY_128_SIZE);
// Set and unwrap pkg2 key.
se_aes_key_clear(9);
se_aes_key_set(9, mkey, 0x10);
se_aes_key_set(9, mkey, SE_KEY_128_SIZE);
se_aes_unwrap_key(9, 9, package2_keyseed);
// Decrypt header.
@@ -158,9 +159,9 @@ pkg2_hdr_t *pkg2_decrypt(void *data, u8 kb)
// Decrypt older pkg2 via new mkeys.
if ((kb >= KB_FIRMWARE_VERSION_810) && (kb < KB_FIRMWARE_VERSION_MAX))
{
u8 tmp_mkey[0x10];
u8 tmp_mkey[SE_KEY_128_SIZE];
u8 decr_slot = !h_cfg.t210b01 ? (!h_cfg.aes_slots_new ? 12 : 13) : 7; // Sept mkey or T210B01 mkey.
u8 mkey_seeds_cnt = sizeof(mkey_vector_8xx) / 0x10;
u8 mkey_seeds_cnt = sizeof(mkey_vector_8xx) / SE_KEY_128_SIZE;
u8 mkey_seeds_idx = mkey_seeds_cnt; // Real index + 1.
u8 mkey_seeds_min_idx = mkey_seeds_cnt - (KB_FIRMWARE_VERSION_MAX - kb);
@@ -180,7 +181,7 @@ pkg2_hdr_t *pkg2_decrypt(void *data, u8 kb)
// Set current mkey in order to decrypt a lower mkey.
mkey_seeds_idx--;
se_aes_key_clear(9);
se_aes_key_set(9, tmp_mkey, 0x10);
se_aes_key_set(9, tmp_mkey, SE_KEY_128_SIZE);
decr_slot = 9; // Temp key.
@@ -214,7 +215,7 @@ 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(keyslot, pdata, hdr->sec_size[i], pdata, hdr->sec_size[i], &hdr->sec_ctr[i * SE_AES_IV_SIZE]);
//gfx_hexdump((u32)pdata, pdata, 0x100);
pdata += hdr->sec_size[i];

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2019 CTCaer
* Copyright (c) 2019-2021 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
@@ -68,72 +68,6 @@ extern volatile nyx_storage_t *nyx_str;
extern bool is_ipl_updated(void *buf);
extern void reloc_patcher(u32 payload_dst, u32 payload_src, u32 payload_size);
void check_sept()
{
if (h_cfg.t210b01)
{
h_cfg.sept_run = true;
return;
}
hos_eks_get();
// Check if non-hekate payload is used for sept and restore it.
if (h_cfg.sept_run)
{
if (!f_stat("sept/payload.bak", NULL))
{
f_unlink("sept/payload.bin");
f_rename("sept/payload.bak", "sept/payload.bin");
}
return;
}
u8 *pkg1 = (u8 *)calloc(1, 0x40000);
sdmmc_storage_t storage;
sdmmc_t sdmmc;
if (!sdmmc_storage_init_mmc(&storage, &sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400))
{
EPRINTF("Failed to init eMMC.");
goto out_free;
}
sdmmc_storage_set_mmc_partition(&storage, EMMC_BOOT0);
// Read package1.
char *build_date = malloc(32);
sdmmc_storage_read(&storage, 0x100000 / NX_EMMC_BLOCKSIZE, 0x40000 / NX_EMMC_BLOCKSIZE, pkg1);
const pkg1_id_t *pkg1_id = pkg1_identify(pkg1, build_date);
free(build_date);
if (!pkg1_id)
{
EPRINTF("Unknown pkg1 version.");
goto out_free;
}
if (pkg1_id->kb >= KB_FIRMWARE_VERSION_700 && !h_cfg.sept_run)
{
u32 key_idx = 0;
if (pkg1_id->kb >= KB_FIRMWARE_VERSION_810)
key_idx = 1;
if (h_cfg.eks && h_cfg.eks->enabled[key_idx] >= pkg1_id->kb)
{
h_cfg.sept_run = true;
goto out_free;
}
sdmmc_storage_end(&storage);
reboot_to_sept((u8 *)pkg1 + pkg1_id->tsec_off, pkg1_id->kb);
}
out_free:
free(pkg1);
sdmmc_storage_end(&storage);
}
int reboot_to_sept(const u8 *tsec_fw, u32 kb)
{
FIL fp;

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2019 CTCaer
* Copyright (c) 2019-2021 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
@@ -19,7 +19,8 @@
#include <utils/types.h>
void check_sept();
#define SEPT_PRI_ENTRY 0x40010340
int reboot_to_sept(const u8 *tsec_fw, u32 kb);
#endif

View File

@@ -16,6 +16,10 @@
#include <storage/ramdisk.h>
#include <storage/sdmmc.h>
static u32 sd_rsvd_sectors = 0;
static u32 ramdisk_sectors = 0;
static u32 emummc_sectors = 0;
/*-----------------------------------------------------------------------*/
/* Get Drive Status */
/*-----------------------------------------------------------------------*/
@@ -55,7 +59,8 @@ DRESULT disk_read (
case DRIVE_EMMC:
return sdmmc_storage_read(&emmc_storage, sector, count, (void *)buff) ? RES_OK : RES_ERROR;
case DRIVE_BIS:
return nx_emmc_bis_read(sector, count, (void *)buff);
case DRIVE_EMU:
return nx_emmc_bis_read(sector, count, (void *)buff) ? RES_OK : RES_ERROR;
}
return RES_ERROR;
@@ -80,6 +85,8 @@ DRESULT disk_write (
case DRIVE_EMMC:
case DRIVE_BIS:
return RES_WRPRT;
case DRIVE_EMU:
return nx_emmc_bis_write(sector, count, (void *)buff) ? RES_OK : RES_ERROR;
}
return RES_ERROR;
@@ -88,7 +95,6 @@ DRESULT disk_write (
/*-----------------------------------------------------------------------*/
/* Miscellaneous Functions */
/*-----------------------------------------------------------------------*/
static u32 part_rsvd_size = 0;
DRESULT disk_ioctl (
BYTE pdrv, /* Physical drive nmuber (0..) */
BYTE cmd, /* Control code */
@@ -102,7 +108,7 @@ DRESULT disk_ioctl (
switch (cmd)
{
case GET_SECTOR_COUNT:
*buf = sd_storage.sec_cnt - part_rsvd_size;
*buf = sd_storage.sec_cnt - sd_rsvd_sectors;
break;
case GET_BLOCK_SIZE:
*buf = 32768; // Align to 16MB.
@@ -114,13 +120,25 @@ DRESULT disk_ioctl (
switch (cmd)
{
case GET_SECTOR_COUNT:
*buf = RAM_DISK_SZ >> 9; // 1GB.
*buf = ramdisk_sectors;
break;
case GET_BLOCK_SIZE:
*buf = 2048; // Align to 1MB.
break;
}
}
else if (pdrv == DRIVE_EMU)
{
switch (cmd)
{
case GET_SECTOR_COUNT:
*buf = emummc_sectors;
break;
case GET_BLOCK_SIZE:
*buf = 32768; // Align to 16MB.
break;
}
}
return RES_OK;
}
@@ -133,12 +151,18 @@ DRESULT disk_set_info (
{
DWORD *buf = (DWORD *)buff;
if (pdrv == DRIVE_SD)
if (cmd == SET_SECTOR_COUNT)
{
switch (cmd)
switch (pdrv)
{
case SET_SECTOR_COUNT:
part_rsvd_size = *buf;
case DRIVE_SD:
sd_rsvd_sectors = *buf;
break;
case DRIVE_RAM:
ramdisk_sectors = *buf;
break;
case DRIVE_EMU:
emummc_sectors = *buf;
break;
}
}

View File

@@ -41,16 +41,25 @@
#define FF_USE_MKFS 1
/* This option switches f_mkfs() function. (0:Disable or 1:Enable) */
#if FF_USE_MKFS
#define FF_MKFS_LABEL "SWITCH SD "
#endif
/* This sets FAT/FAT32 label. Exactly 11 characters, all caps. */
#define FF_USE_FASTSEEK 0
/* This option switches fast seek function. (0:Disable or 1:Enable) */
#define FF_FASTFS 1
#if FF_FASTFS
#undef FF_USE_FASTSEEK
#define FF_USE_FASTSEEK 1
#endif
/* This option switches fast access to chained clusters. (0:Disable or 1:Enable) */
#define FF_SIMPLE_GPT 1
/* This option switches support for the first GPT partition. (0:Disable or 1:Enable) */
#define FF_USE_EXPAND 0
@@ -170,13 +179,13 @@
/ Drive/Volume Configurations
/---------------------------------------------------------------------------*/
#define FF_VOLUMES 4
#define FF_VOLUMES 5
/* Number of volumes (logical drives) to be used. (1-10) */
#define FF_STR_VOLUME_ID 1
// Order is important. Any change to order, must also be reflected to diskio drive enum.
#define FF_VOLUME_STRS "sd","ram","emmc","bis"
#define FF_VOLUME_STRS "sd","ram","emmc","bis","emu"
/* FF_STR_VOLUME_ID switches support for volume ID in arbitrary strings.
/ When FF_STR_VOLUME_ID is set to 1 or 2, arbitrary strings can be used as drive
/ number in the path name. FF_VOLUME_STRS defines the volume ID strings for each
@@ -186,6 +195,7 @@
/ not defined, a user defined volume string table needs to be defined as:
/
/ const char* VolumeStr[FF_VOLUMES] = {"ram","flash","sd","usb",...
/ Order is important. Any change to order, must also be reflected to diskio drive enum.
*/
@@ -247,7 +257,7 @@
#define FF_FS_NORTC 0
#define FF_NORTC_MON 1
#define FF_NORTC_MDAY 1
#define FF_NORTC_YEAR 2020
#define FF_NORTC_YEAR 2021
/* The option FF_FS_NORTC switches timestamp function. If the system does not have
/ any RTC function or valid timestamp is not needed, set FF_FS_NORTC = 1 to disable
/ the timestamp function. Every object modified by FatFs will have a fixed timestamp

View File

@@ -1,7 +1,7 @@
/*
* Copyright (c) 2018 naehrwert
*
* Copyright (c) 2018-2019 CTCaer
* Copyright (c) 2018-2021 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
@@ -42,6 +42,7 @@
#include <soc/pmc.h>
#include <soc/t210.h>
#include <soc/uart.h>
#include "storage/nx_emmc.h"
#include <storage/nx_sd.h>
#include <storage/sdmmc.h>
#include <utils/btn.h>
@@ -80,15 +81,12 @@ char *emmcsn_path_impl(char *path, char *sub_dir, char *filename, sdmmc_storage_
// Get actual eMMC S/N.
if (!storage)
{
sdmmc_t sdmmc;
sdmmc_storage_t storage2;
if (!sdmmc_storage_init_mmc(&storage2, &sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400))
if (!sdmmc_storage_init_mmc(&emmc_storage, &emmc_sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400))
strcpy(emmc_sn, "00000000");
else
{
itoa(storage2.cid.serial, emmc_sn, 16);
sdmmc_storage_end(&storage2);
itoa(emmc_storage.cid.serial, emmc_sn, 16);
sdmmc_storage_end(&emmc_storage);
}
}
else

View File

@@ -1,8 +1,8 @@
/*
* eMMC BIS driver for Nintendo Switch
*
* Copyright (c) 2019 shchmue
* Copyright (c) 2019-2020 CTCaer
* Copyright (c) 2019-2020 shchmue
* Copyright (c) 2019-2021 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
@@ -21,48 +21,64 @@
#include <memory_map.h>
#include <mem/heap.h>
#include <sec/se.h>
#include <sec/se_t210.h>
#include "../storage/nx_emmc.h"
#include <storage/nx_sd.h>
#include <storage/sdmmc.h>
#include <utils/types.h>
#define MAX_SEC_CACHE_ENTRIES 1500
#define BIS_CLUSTER_SECTORS 32
#define BIS_CLUSTER_SIZE 16384
#define BIS_CACHE_MAX_ENTRIES 16384
#define BIS_CACHE_LOOKUP_TBL_EMPTY_ENTRY -1
typedef struct _sector_cache_t
typedef struct _cluster_cache_t
{
u32 sector;
u32 visit_cnt;
u8 tweak[0x10];
u8 data[0x200];
u8 align[8];
} sector_cache_t;
u32 cluster_idx; // Index of the cluster in the partition.
bool dirty; // Has been modified without write-back flag.
u8 data[BIS_CLUSTER_SIZE]; // The cached cluster itself. Aligned to 8 bytes for DMA engine.
} cluster_cache_t;
static u8 ks_crypt = 0;
static u8 ks_tweak = 0;
static u32 sector_cache_cnt = 0;
typedef struct _bis_cache_t
{
bool full;
bool enabled;
u32 dirty_cnt;
u32 top_idx;
u8 dma_buff[BIS_CLUSTER_SIZE]; // Aligned to 8 bytes for DMA engine.
cluster_cache_t clusters[];
} bis_cache_t;
static u8 ks_crypt = 0;
static u8 ks_tweak = 0;
static u32 emu_offset = 0;
static emmc_part_t *system_part = NULL;
static sector_cache_t *sector_cache = (sector_cache_t *)NX_BIS_CACHE_ADDR;
static u32 *cache_lookup_tbl = (u32 *)NX_BIS_LOOKUP_ADDR;
static bis_cache_t *bis_cache = (bis_cache_t *)NX_BIS_CACHE_ADDR;
static void _gf256_mul_x_le(u8 *block)
static void _gf256_mul_x_le(void *block)
{
u8 *pdata = (u8 *)block;
u32 *pdata = (u32 *)block;
u32 carry = 0;
for (u32 i = 0; i < 0x10; i++)
for (u32 i = 0; i < 4; i++)
{
u8 b = pdata[i];
u32 b = pdata[i];
pdata[i] = (b << 1) | carry;
carry = b >> 7;
carry = b >> 31;
}
if (carry)
pdata[0x0] ^= 0x87;
}
static int _nx_aes_xts_crypt_sec(u32 ks1, u32 ks2, u32 enc, u8 *tweak, bool regen_tweak, u32 tweak_exp, u64 sec, void *dst, void *src, u32 sec_size)
static int _nx_aes_xts_crypt_sec(u32 tweak_ks, u32 crypt_ks, u32 enc, u8 *tweak, bool regen_tweak, u32 tweak_exp, u64 sec, void *dst, void *src, u32 sec_size)
{
u8 *pdst = (u8 *)dst;
u8 *psrc = (u8 *)src;
u32 *pdst = (u32 *)dst;
u32 *psrc = (u32 *)src;
u32 *ptweak = (u32 *)tweak;
if (regen_tweak)
{
@@ -71,155 +87,298 @@ static int _nx_aes_xts_crypt_sec(u32 ks1, u32 ks2, u32 enc, u8 *tweak, bool rege
tweak[i] = sec & 0xFF;
sec >>= 8;
}
if (!se_aes_crypt_block_ecb(ks1, 1, tweak, tweak))
if (!se_aes_crypt_block_ecb(tweak_ks, 1, tweak, tweak))
return 0;
}
// tweak_exp allows us to use a saved tweak to reduce _gf256_mul_x_le calls.
for (u32 i = 0; i < (tweak_exp << 5); i++)
_gf256_mul_x_le(tweak);
u8 tmp_tweak[0x10];
memcpy(tmp_tweak, tweak, 0x10);
u8 orig_tweak[SE_KEY_128_SIZE] __attribute__((aligned(4)));
memcpy(orig_tweak, tweak, SE_KEY_128_SIZE);
// We are assuming a 0x10-aligned sector size in this implementation.
// We are assuming a 16 sector aligned size in this implementation.
for (u32 i = 0; i < (sec_size >> 4); i++)
{
for (u32 j = 0; j < 0x10; j++)
pdst[j] = psrc[j] ^ tweak[j];
for (u32 j = 0; j < 4; j++)
pdst[j] = psrc[j] ^ ptweak[j];
_gf256_mul_x_le(tweak);
psrc += 0x10;
pdst += 0x10;
psrc += 4;
pdst += 4;
}
se_aes_crypt_ecb(ks2, enc, dst, sec_size, src, sec_size);
if (!se_aes_crypt_ecb(crypt_ks, enc, dst, sec_size, dst, sec_size))
return 0;
memcpy(tweak, tmp_tweak, 0x10);
pdst = (u8 *)dst;
pdst = (u32 *)dst;
ptweak = (u32 *)orig_tweak;
for (u32 i = 0; i < (sec_size >> 4); i++)
{
for (u32 j = 0; j < 0x10; j++)
pdst[j] = pdst[j] ^ tweak[j];
for (u32 j = 0; j < 4; j++)
pdst[j] = pdst[j] ^ ptweak[j];
_gf256_mul_x_le(tweak);
pdst += 0x10;
_gf256_mul_x_le(orig_tweak);
pdst += 4;
}
return 1;
}
static int nx_emmc_bis_write_block(u32 sector, u32 count, void *buff, bool flush)
{
if (!system_part)
return 3; // Not ready.
int res;
u8 tweak[SE_KEY_128_SIZE] __attribute__((aligned(4)));
u32 cluster = sector / BIS_CLUSTER_SECTORS;
u32 aligned_sector = cluster * BIS_CLUSTER_SECTORS;
u32 sector_in_cluster = sector % BIS_CLUSTER_SECTORS;
u32 lookup_idx = cache_lookup_tbl[cluster];
bool is_cached = lookup_idx != BIS_CACHE_LOOKUP_TBL_EMPTY_ENTRY;
// Write to cached cluster.
if (is_cached)
{
if (buff)
memcpy(bis_cache->clusters[lookup_idx].data + sector_in_cluster * NX_EMMC_BLOCKSIZE, buff, count * NX_EMMC_BLOCKSIZE);
else
buff = bis_cache->clusters[lookup_idx].data;
if (!bis_cache->clusters[lookup_idx].dirty)
bis_cache->dirty_cnt++;
bis_cache->clusters[lookup_idx].dirty = true;
if (!flush)
return 0; // Success.
// Reset args to trigger a full cluster flush to emmc.
sector_in_cluster = 0;
sector = aligned_sector;
count = BIS_CLUSTER_SECTORS;
}
// Encrypt cluster.
if (!_nx_aes_xts_crypt_sec(ks_tweak, ks_crypt, 1, tweak, true, sector_in_cluster, cluster, bis_cache->dma_buff, buff, count * NX_EMMC_BLOCKSIZE))
return 1; // Encryption error.
// If not reading from cache, do a regular read and decrypt.
if (!emu_offset)
res = nx_emmc_part_write(&emmc_storage, system_part, sector, count, bis_cache->dma_buff);
else
res = sdmmc_storage_read(&sd_storage, emu_offset + system_part->lba_start + sector, count, bis_cache->dma_buff);
if (!res)
return 1; // R/W error.
// Mark cache entry not dirty if write succeeds.
if (is_cached)
{
bis_cache->clusters[lookup_idx].dirty = false;
bis_cache->dirty_cnt--;
}
return 0; // Success.
}
static void _nx_emmc_bis_cluster_cache_init(bool enable_cache)
{
u32 cache_lookup_tbl_size = (system_part->lba_end - system_part->lba_start + 1) / BIS_CLUSTER_SECTORS * sizeof(*cache_lookup_tbl);
// Clear cache header.
memset(bis_cache, 0, sizeof(bis_cache_t));
// Clear cluster lookup table.
memset(cache_lookup_tbl, BIS_CACHE_LOOKUP_TBL_EMPTY_ENTRY, cache_lookup_tbl_size);
// Enable cache.
bis_cache->enabled = enable_cache;
}
static void _nx_emmc_bis_flush_cache()
{
if (!bis_cache->enabled || !bis_cache->dirty_cnt)
return;
for (u32 i = 0; i < bis_cache->top_idx && bis_cache->dirty_cnt; i++)
{
if (bis_cache->clusters[i].dirty) {
nx_emmc_bis_write_block(bis_cache->clusters[i].cluster_idx * BIS_CLUSTER_SECTORS, BIS_CLUSTER_SECTORS, NULL, true);
bis_cache->dirty_cnt--;
}
}
_nx_emmc_bis_cluster_cache_init(true);
}
static int nx_emmc_bis_read_block_normal(u32 sector, u32 count, void *buff)
{
static u32 prev_cluster = -1;
static u32 prev_sector = 0;
static u8 tweak[SE_KEY_128_SIZE] __attribute__((aligned(4)));
int res;
bool regen_tweak = true;
u32 tweak_exp = 0;
u32 cluster = sector / BIS_CLUSTER_SECTORS;
u32 sector_in_cluster = sector % BIS_CLUSTER_SECTORS;
// If not reading from cache, do a regular read and decrypt.
if (!emu_offset)
res = nx_emmc_part_read(&emmc_storage, system_part, sector, count, bis_cache->dma_buff);
else
res = sdmmc_storage_read(&sd_storage, emu_offset + system_part->lba_start + sector, count, bis_cache->dma_buff);
if (!res)
return 1; // R/W error.
if (prev_cluster != cluster) // Sector in different cluster than last read.
{
prev_cluster = cluster;
tweak_exp = sector_in_cluster;
}
else if (sector > prev_sector) // Sector in same cluster and past last sector.
{
// Calculates the new tweak using the saved one, reducing expensive _gf256_mul_x_le calls.
tweak_exp = sector - prev_sector - 1;
regen_tweak = false;
}
else // Sector in same cluster and before or same as last sector.
tweak_exp = sector_in_cluster;
// Maximum one cluster (1 XTS crypto block 16KB).
if (!_nx_aes_xts_crypt_sec(ks_tweak, ks_crypt, 0, tweak, regen_tweak, tweak_exp, prev_cluster, buff, bis_cache->dma_buff, count * NX_EMMC_BLOCKSIZE))
return 1; // R/W error.
prev_sector = sector + count - 1;
return 0; // Success.
}
static int nx_emmc_bis_read_block_cached(u32 sector, u32 count, void *buff)
{
int res;
u8 cache_tweak[SE_KEY_128_SIZE] __attribute__((aligned(4)));
u32 cluster = sector / BIS_CLUSTER_SECTORS;
u32 cluster_sector = cluster * BIS_CLUSTER_SECTORS;
u32 sector_in_cluster = sector % BIS_CLUSTER_SECTORS;
u32 lookup_idx = cache_lookup_tbl[cluster];
// Read from cached cluster.
if (lookup_idx != BIS_CACHE_LOOKUP_TBL_EMPTY_ENTRY)
{
memcpy(buff, bis_cache->clusters[lookup_idx].data + sector_in_cluster * NX_EMMC_BLOCKSIZE, count * NX_EMMC_BLOCKSIZE);
return 0; // Success.
}
// Flush cache if full.
if (bis_cache->top_idx >= BIS_CACHE_MAX_ENTRIES)
_nx_emmc_bis_flush_cache();
// Set new cached cluster parameters.
bis_cache->clusters[bis_cache->top_idx].cluster_idx = cluster;
bis_cache->clusters[bis_cache->top_idx].dirty = false;
cache_lookup_tbl[cluster] = bis_cache->top_idx;
// Read the whole cluster the sector resides in.
if (!emu_offset)
res = nx_emmc_part_read(&emmc_storage, system_part, cluster_sector, BIS_CLUSTER_SECTORS, bis_cache->dma_buff);
else
res = sdmmc_storage_read(&sd_storage, emu_offset + system_part->lba_start + cluster_sector, BIS_CLUSTER_SECTORS, bis_cache->dma_buff);
if (!res)
return 1; // R/W error.
// Decrypt cluster.
if (!_nx_aes_xts_crypt_sec(ks_tweak, ks_crypt, 0, cache_tweak, true, 0, cluster, bis_cache->dma_buff, bis_cache->dma_buff, BIS_CLUSTER_SIZE))
return 1; // Decryption error.
// Copy to cluster cache.
memcpy(bis_cache->clusters[bis_cache->top_idx].data, bis_cache->dma_buff, BIS_CLUSTER_SIZE);
memcpy(buff, bis_cache->dma_buff + sector_in_cluster * NX_EMMC_BLOCKSIZE, count * NX_EMMC_BLOCKSIZE);
// Increment cache count.
bis_cache->top_idx++;
return 0; // Success.
}
static int nx_emmc_bis_read_block(u32 sector, u32 count, void *buff)
{
if (!system_part)
return 3; // Not ready.
static u32 prev_cluster = -1;
static u32 prev_sector = 0;
static u8 tweak[0x10];
u32 cache_idx = 0;
u32 tweak_exp = 0;
bool regen_tweak = true;
bool cache_sector = false;
if (count == 1)
{
for ( ; cache_idx < sector_cache_cnt; cache_idx++)
{
if (sector_cache[cache_idx].sector == sector)
{
sector_cache[cache_idx].visit_cnt++;
memcpy(buff, sector_cache[cache_idx].data, 0x200);
memcpy(tweak, sector_cache[cache_idx].tweak, 0x10);
prev_sector = sector;
prev_cluster = sector >> 5;
return 0;
}
}
// add to cache
if (cache_idx == sector_cache_cnt && cache_idx < MAX_SEC_CACHE_ENTRIES)
{
sector_cache[cache_idx].sector = sector;
sector_cache[cache_idx].visit_cnt++;
cache_sector = true;
sector_cache_cnt++;
}
}
if (nx_emmc_part_read(&emmc_storage, system_part, sector, count, buff))
{
if (prev_cluster != sector >> 5) // Sector in different cluster than last read.
{
prev_cluster = sector >> 5;
tweak_exp = sector % 0x20;
}
else if (sector > prev_sector) // Sector in same cluster and past last sector.
{
tweak_exp = sector - prev_sector - 1;
regen_tweak = false;
}
else // Sector in same cluster and before or same as last sector.
tweak_exp = sector % 0x20;
// Maximum one cluster (1 XTS crypto block 16KB).
_nx_aes_xts_crypt_sec(ks_tweak, ks_crypt, 0, tweak, regen_tweak, tweak_exp, prev_cluster, buff, buff, count << 9);
if (cache_sector)
{
memcpy(sector_cache[cache_idx].data, buff, 0x200);
memcpy(sector_cache[cache_idx].tweak, tweak, 0x10);
}
prev_sector = sector + count - 1;
return 0;
}
// Error occurred.
return 1;
if (bis_cache->enabled)
return nx_emmc_bis_read_block_cached(sector, count, buff);
else
return nx_emmc_bis_read_block_normal(sector, count, buff);
}
int nx_emmc_bis_read(u32 sector, u32 count, void *buff)
{
int res = 1;
u8 *buf = (u8 *)buff;
u32 curr_sct = sector;
while (count)
{
u32 sct_cnt = MIN(count, 0x20);
res = nx_emmc_bis_read_block(curr_sct, sct_cnt, buf);
if (res)
return 1;
u32 sct_cnt = MIN(count, BIS_CLUSTER_SECTORS);
if (nx_emmc_bis_read_block(curr_sct, sct_cnt, buf))
return 0;
count -= sct_cnt;
count -= sct_cnt;
curr_sct += sct_cnt;
buf += 512 * sct_cnt;
buf += sct_cnt * NX_EMMC_BLOCKSIZE;
}
return res;
return 1;
}
void nx_emmc_bis_init(emmc_part_t *part)
int nx_emmc_bis_write(u32 sector, u32 count, void *buff)
{
u8 *buf = (u8 *)buff;
u32 curr_sct = sector;
while (count)
{
u32 sct_cnt = MIN(count, BIS_CLUSTER_SECTORS);
if (nx_emmc_bis_write_block(curr_sct, sct_cnt, buf, false))
return 0;
count -= sct_cnt;
curr_sct += sct_cnt;
buf += sct_cnt * NX_EMMC_BLOCKSIZE;
}
return 1;
}
void nx_emmc_bis_init(emmc_part_t *part, bool enable_cache, u32 emummc_offset)
{
system_part = part;
sector_cache_cnt = 0;
emu_offset = emummc_offset;
switch (part->index)
_nx_emmc_bis_cluster_cache_init(enable_cache);
if (!strcmp(part->name, "PRODINFO") || !strcmp(part->name, "PRODINFOF"))
{
case 0: // PRODINFO.
case 1: // PRODINFOF.
ks_crypt = 0;
ks_tweak = 1;
break;
case 8: // SAFE.
}
else if (!strcmp(part->name, "SAFE"))
{
ks_crypt = 2;
ks_tweak = 3;
break;
case 9: // SYSTEM.
case 10: // USER.
}
else if (!strcmp(part->name, "SYSTEM") || !strcmp(part->name, "USER"))
{
ks_crypt = 4;
ks_tweak = 5;
break;
}
else
system_part = NULL;
}
void nx_emmc_bis_end()
{
_nx_emmc_bis_flush_cache();
system_part = NULL;
}

View File

@@ -223,7 +223,9 @@ typedef struct _nx_emmc_cal0_t
u8 console_6axis_sensor_mount_type;
} __attribute__((packed)) nx_emmc_cal0_t;
int nx_emmc_bis_read(u32 sector, u32 count, void *buff);
void nx_emmc_bis_init(emmc_part_t *part);
int nx_emmc_bis_read(u32 sector, u32 count, void *buff);
int nx_emmc_bis_write(u32 sector, u32 count, void *buff);
void nx_emmc_bis_init(emmc_part_t *part, bool enable_cache, u32 emummc_offset);
void nx_emmc_bis_end();
#endif

View File

@@ -1,6 +1,6 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2019 CTCaer
* Copyright (c) 2018-2021 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
@@ -60,6 +60,11 @@ bool sd_get_card_removed()
return false;
}
bool sd_get_card_initialized()
{
return sd_init_done;
}
u32 sd_get_mode()
{
return sd_mode;

View File

@@ -6,37 +6,53 @@ backlight=100
autohosoff=0
autonogc=1
updater2p=1
bootprotect=0
{-------- Stock -------}
[Stock 6.2.0 and lower]
stock=1
emummc_force_disable=1
[Stock All FW]
[Stock]
fss0=atmosphere/fusee-secondary.bin
stock=1
emummc_force_disable=1
# Both above disable kernel patching
# Stock All FW, includes exosphere and warmboot, ONLY when >= 7.0.0.
[Stock emuMMC All FW]
fss0=atmosphere/fusee-secondary.bin
stock=1
{ }
# This disables kernel patching and CFW kips.
# Includes exosphere and warmboot, ONLY when >= 7.0.0 and Erista.
# Includes exosphere on Mariko.
# Exosphere/warmboot are not identifiable as it is now.
# This is the closest to OFW, especially when AutoRCM is needed.
{-- Custom Firmwares --}
[Atmo FSS0 Vanilla]
[Atmo Vanilla]
fss0=atmosphere/fusee-secondary.bin
logopath=bootloader/res/bootlogo_atmo.bmp
icon=bootloader/res/icon_atmo.bmp
# Note:
# The above adheres to emummc.ini. It will launch emuMMC if enabled, otherwise sysMMC
# You can have 2 entries of everything where one can boot with emuMMC and one without,
# via the emummc_force_disable=1 key.
# logopath= key is for bootlogo. icon= key is for Nyx icon.
# All entries can have these stylistic keys.
# via the emummc_force_disable=1 and emummcforce=1 keys. Examples follow below.
[Atmo EMU]
fss0=atmosphere/fusee-secondary.bin
emummcforce=1
[Atmo SYS]
fss0=atmosphere/fusee-secondary.bin
emummc_force_disable=1
[Atmo with extra kips]
fss0=atmosphere/fusee-secondary.bin
kip1=cfw/mods/mods_extra/*
kip1=cfw/mods/mods_extra/single/extra.kip
# Note:
# The above can be used with any fss0 entry. Like the ones above.
# You can even override atmosphere (fss0) kips with this.
{-- Custom Firmwares Old methods --}
[CFW FSS0 extra kips & patches]
fss0=atmosphere/fusee-secondary.bin
kip1patch=name_of_patch
@@ -45,12 +61,12 @@ kip1=cfw/mods/mods_extra/single/extra.kip
# Note:
# Both options for kip1 can be used. Wildcard and single.
# You can override kips loaded from FSS0 if you define them after that entry.
# You can override kips loaded from FSS0 if you define them after the fss0 key.
# If kip1 patch resides in patches.ini and that file OR the patch for
# current HOS version does not exist, it will error out.
[Atmo Vanilla]
[CFW KIPs method]
secmon=cfw/mods/exosphere.bin
warmboot=cfw/mods/lp0fw.bin
kip1=cfw/mods/loader.kip
@@ -66,7 +82,7 @@ atmosphere=1
# atmosphere=1 key is IMPORTANT when no FFS0 is defined.
[CFW Extra kips]
[CFW KIPs method with wildcard]
secmon=cfw/mods/exosphere.bin
warmboot=cfw/mods/lp0fw.bin
kip1=cfw/mods/*
@@ -83,7 +99,12 @@ atmosphere=1
payload=bootloader/payloads/memloader.bin
# hekate - CTCaer mod v5.0.0 .ini template
# hekate - CTCaer mod v5.5.3 .ini template
# All entries in this template can have these stylistic keys.
# Like logopath= key which is for bootlogo and icon= key for Nyx icon.
# Other than these there many other keys to choose from, like the exosphere configuration keys.
# All of them are descibed in the main README.
# NOT TO BE USED AS IS!
# Pick [config] and then only the needed [sections]. # or { } lines can be ommited.