Compare commits

...

40 Commits

Author SHA1 Message Date
CTCaer
4e7e5081a7 Bump Nyx to v1.0.1 2021-02-08 04:01:39 +02:00
CTCaer
fff750e609 bis: Fix BIS write for emuMMC
A last minute cleanup changed the function for writing the changed BIS sectors in emuMMC to a read.

Restore it to a sd card write.
2021-02-08 04:00:11 +02:00
CTCaer
38ce46a158 nyx: Add more info while formatting emuMMC USER 2021-02-08 03:52:23 +02:00
CTCaer
7a27a7b3b5 joycon: Disable regulators before sending the sleep cmd 2021-02-08 03:49:04 +02:00
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
66 changed files with 2578 additions and 1739 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. | | 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. | | emummcforce=1 | Forces the use of emuMMC. If emummc.ini is disabled or not found, then it causes an error. |
| emummc_force_disable=1 | Disables emuMMC, if it's enabled. | | emummc_force_disable=1 | Disables emuMMC, if it's enabled. |
| stock=1 | 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. | | id=idname | Identifies boot entry for forced boot via id. Max 7 chars. |
| payload={SD path} | Payload launching. Tools, Linux, CFW bootloaders, etc. | | 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. | | 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. # IPL Version.
BLVERSION_MAJOR := 5 BLVERSION_MAJOR := 5
BLVERSION_MINOR := 5 BLVERSION_MINOR := 5
BLVERSION_HOTFX := 3 BLVERSION_HOTFX := 4
BLVERSION_RSVD := 0 BLVERSION_RSVD := 0
# Nyx Version. # Nyx Version.
NYXVERSION_MAJOR := 0 NYXVERSION_MAJOR := 1
NYXVERSION_MINOR := 9 NYXVERSION_MINOR := 0
NYXVERSION_HOTFX := 9 NYXVERSION_HOTFX := 1
NYXVERSION_RSVD := 0 NYXVERSION_RSVD := 0

View File

@@ -694,9 +694,15 @@ retry:
void jc_deinit() void jc_deinit()
{ {
// Disable power.
jc_power_supply(UART_B, false);
jc_power_supply(UART_C, false);
// Turn off Joy-Con detect.
gpio_config(GPIO_PORT_G, GPIO_PIN_0, GPIO_MODE_SPIO); gpio_config(GPIO_PORT_G, GPIO_PIN_0, GPIO_MODE_SPIO);
gpio_config(GPIO_PORT_D, GPIO_PIN_1, GPIO_MODE_SPIO); gpio_config(GPIO_PORT_D, GPIO_PIN_1, GPIO_MODE_SPIO);
// Send sleep command.
u8 data = HCI_STATE_SLEEP; u8 data = HCI_STATE_SLEEP;
if (jc_r.connected && !(jc_r.type & JC_ID_HORI)) if (jc_r.connected && !(jc_r.type & JC_ID_HORI))
@@ -709,9 +715,6 @@ void jc_deinit()
jc_send_hid_cmd(UART_C, JC_HID_SUBCMD_HCI_STATE, &data, 1); jc_send_hid_cmd(UART_C, JC_HID_SUBCMD_HCI_STATE, &data, 1);
jc_rcv_pkt(&jc_l); jc_rcv_pkt(&jc_l);
} }
jc_power_supply(UART_B, false);
jc_power_supply(UART_C, false);
} }
static void jc_init_conn(joycon_ctxt_t *jc) static void jc_init_conn(joycon_ctxt_t *jc)

View File

@@ -27,7 +27,8 @@ typedef enum {
DRIVE_SD = 0, DRIVE_SD = 0,
DRIVE_RAM = 1, DRIVE_RAM = 1,
DRIVE_EMMC = 2, DRIVE_EMMC = 2,
DRIVE_BIS = 3 DRIVE_BIS = 3,
DRIVE_EMU = 4
} DDRIVE; } 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_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 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 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) */ /* Generic command (Not used by FatFs) */
#define CTRL_POWER 5 /* Get/Set power status */ #define CTRL_POWER 5 /* Get/Set power status */

View File

@@ -1,6 +1,6 @@
/* /*
* Copyright (c) 2018 naehrwert * 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 * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@@ -38,6 +38,7 @@
#include "ff.h" /* Declarations of FatFs API */ #include "ff.h" /* Declarations of FatFs API */
#include "diskio.h" /* Declarations of device I/O functions */ #include "diskio.h" /* Declarations of device I/O functions */
#include <storage/mbr_gpt.h>
#include <gfx_utils.h> #include <gfx_utils.h>
#define EFSPRINTF(text, ...) print_error(); gfx_printf("%k"text"%k\n", 0xFFFFFF00, 0xFFFFFFFF); #define EFSPRINTF(text, ...) print_error(); gfx_printf("%k"text"%k\n", 0xFFFFFF00, 0xFFFFFFFF);
@@ -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) */ /* Following code attempts to mount the volume. (analyze BPB and initialize the filesystem object) */
fs->fs_type = 0; /* Clear 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 */ fs->pdrv = LD2PD(vol); /* Bind the logical drive and a physical drive */
stat = disk_initialize(fs->pdrv); /* Initialize the physical drive */ stat = disk_initialize(fs->pdrv); /* Initialize the physical drive */
if (stat & STA_NOINIT) { /* Check if the initialization succeeded */ 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"); EFSPRINTF("BRNL");
return FR_DISK_ERR; /* An error occured in the disk I/O layer */ 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) { if (fmt >= 2) {
EFSPRINTF("NOFAT"); EFSPRINTF("NOFAT");
return FR_NO_FILESYSTEM; /* No FAT volume is found */ return FR_NO_FILESYSTEM; /* No FAT volume is found */
@@ -6169,7 +6183,9 @@ FRESULT f_mkfs (
#endif #endif
/* Create FAT VBR */ /* Create FAT VBR */
mem_set(buf, 0, ss); 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] */ st_word(buf + BPB_BytsPerSec, ss); /* Sector size [byte] */
buf[BPB_SecPerClus] = (BYTE)pau; /* Cluster size [sector] */ buf[BPB_SecPerClus] = (BYTE)pau; /* Cluster size [sector] */
st_word(buf + BPB_RsvdSecCnt, (WORD)sz_rsv); /* Size of reserved area */ 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 */ buf[BPB_Media] = 0xF8; /* Media descriptor byte */
st_word(buf + BPB_SecPerTrk, 63); /* Number of sectors per track (for int13) */ 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] */ st_dword(buf + BPB_HiddSec, b_vol); /* Volume offset in the physical drive [sector] */
if (fmt == FS_FAT32) { 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_FATSz32, sz_fat); /* FAT size [sector] */
st_dword(buf + BPB_RootClus32, 2); /* Root directory cluster # (2) */ 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_FSInfo32, 1); /* Offset of FSINFO sector (VBR + 1) */
st_word(buf + BPB_BkBootSec32, 6); /* Offset of backup VBR (VBR + 6) */ st_word(buf + BPB_BkBootSec32, 6); /* Offset of backup VBR (VBR + 6) */
buf[BS_DrvNum32] = 0x80; /* Drive number (for int13) */ buf[BS_DrvNum32] = 0x80; /* Drive number (for int13) */
buf[BS_BootSig32] = 0x29; /* Extended boot signature */ 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 { } else {
st_dword(buf + BS_VolID, GET_FATTIME()); /* VSN */ st_dword(buf + BS_VolID, GET_FATTIME()); /* VSN */
st_word(buf + BPB_FATSz16, (WORD)sz_fat); /* FAT size [sector] */ st_word(buf + BPB_FATSz16, (WORD)sz_fat); /* FAT size [sector] */
buf[BS_DrvNum] = 0x80; /* Drive number (for int13) */ buf[BS_DrvNum] = 0x80; /* Drive number (for int13) */
buf[BS_BootSig] = 0x29; /* Extended boot signature */ 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) */ 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 */ 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) */ 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 */ /* Initialize FAT area */
mem_set(buf, 0, (UINT)szb_buf); mem_set(buf, 0, (UINT)szb_buf);
sect = b_fat; /* FAT start sector */ sect = b_fat; /* FAT start sector */

View File

@@ -95,8 +95,8 @@ typedef DWORD FSIZE_t;
/* Filesystem object structure (FATFS) */ /* Filesystem object structure (FATFS) */
typedef struct { 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 fs_type; /* Filesystem type (0:not mounted) */
BYTE part_type; /* Partition type (0:MBR, 1:GPT) */
BYTE pdrv; /* Associated physical drive */ BYTE pdrv; /* Associated physical drive */
BYTE n_fats; /* Number of FATs (1 or 2) */ BYTE n_fats; /* Number of FATs (1 or 2) */
BYTE wflag; /* win[] flag (b0:dirty) */ BYTE wflag; /* win[] flag (b0:dirty) */
@@ -138,6 +138,7 @@ typedef struct {
DWORD bitbase; /* Allocation bitmap base sector */ DWORD bitbase; /* Allocation bitmap base sector */
#endif #endif
DWORD winsect; /* Current sector appearing in the win[] */ 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; } FATFS;
@@ -168,9 +169,6 @@ typedef struct {
/* File object structure (FIL) */ /* File object structure (FIL) */
typedef struct { 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) */ FFOBJID obj; /* Object identifier (must be the 1st member to detect invalid object pointer) */
BYTE flag; /* File status flags */ BYTE flag; /* File status flags */
BYTE err; /* Abort flag (error code) */ BYTE err; /* Abort flag (error code) */
@@ -184,6 +182,9 @@ typedef struct {
#if FF_USE_FASTSEEK #if FF_USE_FASTSEEK
DWORD* cltbl; /* Pointer to the cluster link map table (nulled on open, set by application) */ DWORD* cltbl; /* Pointer to the cluster link map table (nulled on open, set by application) */
#endif #endif
#if !FF_FS_TINY
BYTE buf[FF_MAX_SS] __attribute__((aligned(8))); /* File private data read/write window. DMA aligned. */
#endif
} FIL; } FIL;
@@ -365,6 +366,7 @@ int ff_del_syncobj (FF_SYNC_t sobj); /* Delete a sync object */
#define FM_EXFAT 0x04 #define FM_EXFAT 0x04
#define FM_ANY 0x07 #define FM_ANY 0x07
#define FM_SFD 0x08 #define FM_SFD 0x08
#define FM_PRF2 0x10
/* Filesystem type (FATFS.fs_type) */ /* Filesystem type (FATFS.fs_type) */
#define FS_FAT12 1 #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 * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@@ -50,6 +50,13 @@
// Virtual disk / Chainloader buffers. // Virtual disk / Chainloader buffers.
#define RAM_DISK_ADDR 0xA4000000 #define RAM_DISK_ADDR 0xA4000000
#define RAM_DISK_SZ 0x41000000 // 1040MB. #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). // L4T Kernel Panic Storage (PSTORE).
#define PSTORE_ADDR 0xB0000000 #define PSTORE_ADDR 0xB0000000
@@ -93,10 +100,6 @@
/* --- Hole: 129MB 0xF6A00000 - 0xFEB3FFFF --- */ /* --- Hole: 129MB 0xF6A00000 - 0xFEB3FFFF --- */
#define DRAM_START2 0xFEB40000 #define DRAM_START2 0xFEB40000
// NX BIS driver sector cache.
#define NX_BIS_CACHE_ADDR 0xFEE00000
#define NX_BIS_CACHE_SZ 0x100000
// USB buffers. // USB buffers.
#define USBD_ADDR 0xFEF00000 #define USBD_ADDR 0xFEF00000
#define USB_DESCRIPTOR_ADDR 0xFEF40000 #define USB_DESCRIPTOR_ADDR 0xFEF40000

View File

@@ -1,6 +1,6 @@
/* /*
* Copyright (c) 2018 naehrwert * 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 * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@@ -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) static void _se_ll_set(se_ll_t *dst, se_ll_t *src)
{ {
SE(SE_IN_LL_ADDR_REG_OFFSET) = (u32)src; SE(SE_IN_LL_ADDR_REG) = (u32)src;
SE(SE_OUT_LL_ADDR_REG_OFFSET) = (u32)dst; SE(SE_OUT_LL_ADDR_REG) = (u32)dst;
} }
static int _se_wait() 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) || if (SE(SE_INT_STATUS_REG) & SE_INT_ERR_STAT ||
SE(SE_STATUS_0) & SE_STATUS_0_STATE_WAIT_IN || (SE(SE_STATUS_REG) & SE_STATUS_STATE_MASK) != SE_STATUS_STATE_IDLE ||
SE(SE_ERR_STATUS_0) != SE_ERR_STATUS_0_SE_NS_ACCESS_CLEAR) SE(SE_ERR_STATUS_REG) != 0)
return 0; return 0;
return 1; 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_ll_set(ll_dst, ll_src);
SE(SE_ERR_STATUS_0) = SE(SE_ERR_STATUS_0); SE(SE_ERR_STATUS_REG) = SE(SE_ERR_STATUS_REG);
SE(SE_INT_STATUS_REG_OFFSET) = SE(SE_INT_STATUS_REG_OFFSET); SE(SE_INT_STATUS_REG) = SE(SE_INT_STATUS_REG);
bpmp_mmu_maintenance(BPMP_MMU_MAINT_CLN_INV_WAY, false); 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) 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) if (!src || !dst)
return 0; return 0;
u8 *block = (u8 *)malloc(0x10); u8 *block = (u8 *)malloc(SE_AES_BLOCK_SIZE);
memset(block, 0, 0x10); 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); 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); memcpy(dst, block, dst_size);
free(block); 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) static void _se_aes_ctr_set(void *ctr)
{ {
u32 data[TEGRA_SE_AES_BLOCK_SIZE / 4]; u32 data[SE_AES_IV_SIZE / 4];
memcpy(data, ctr, TEGRA_SE_AES_BLOCK_SIZE); memcpy(data, ctr, SE_AES_IV_SIZE);
for (u32 i = 0; i < (TEGRA_SE_AES_BLOCK_SIZE / 4); i++) for (u32 i = 0; i < SE_CRYPTO_LINEAR_CTR_REG_COUNT; i++)
SE(SE_CRYPTO_CTR_REG_OFFSET + (4 * i)) = data[i]; SE(SE_CRYPTO_LINEAR_CTR_REG + (4 * i)) = data[i];
} }
void se_rsa_acc_ctrl(u32 rs, u32 flags) void se_rsa_acc_ctrl(u32 rs, u32 flags)
{ {
if (flags & SE_RSA_KEY_TBL_DIS_KEY_ALL_FLAG) if (flags & SE_RSA_KEY_TBL_DIS_KEY_ACCESS_FLAG)
SE(SE_RSA_KEYTABLE_ACCESS_REG_OFFSET + 4 * rs) = SE(SE_RSA_KEYTABLE_ACCESS_REG + 4 * rs) =
((flags >> SE_RSA_KEY_TBL_DIS_KEYUSE_FLAG_SHIFT) & SE_RSA_KEY_TBL_DIS_KEYUSE_FLAG) | (((flags >> 4) & SE_RSA_KEY_TBL_DIS_KEYUSE_FLAG) |(flags & SE_RSA_KEY_TBL_DIS_KEY_READ_UPDATE_FLAG)) ^
((flags & SE_RSA_KEY_TBL_DIS_KEY_READ_UPDATE_FLAG) ^ SE_RSA_KEY_TBL_DIS_KEY_ALL_COMMON_FLAG); SE_RSA_KEY_TBL_DIS_KEY_READ_UPDATE_USE_FLAG;
if (flags & SE_RSA_KEY_TBL_DIS_KEY_LOCK_FLAG) if (flags & SE_RSA_KEY_LOCK_FLAG)
SE(SE_RSA_KEYTABLE_ACCESS_LOCK_OFFSET) &= ~BIT(rs); SE(SE_RSA_SECURITY_PERKEY_REG) &= ~BIT(rs);
} }
void se_key_acc_ctrl(u32 ks, u32 flags) void se_key_acc_ctrl(u32 ks, u32 flags)
{ {
if (flags & SE_KEY_TBL_DIS_KEY_ACCESS_FLAG) if (flags & SE_KEY_TBL_DIS_KEY_ACCESS_FLAG)
SE(SE_KEY_TABLE_ACCESS_REG_OFFSET + 4 * ks) = ~flags; SE(SE_CRYPTO_KEYTABLE_ACCESS_REG + 4 * ks) = ~flags;
if (flags & SE_KEY_TBL_DIS_KEY_LOCK_FLAG) if (flags & SE_KEY_LOCK_FLAG)
SE(SE_KEY_TABLE_ACCESS_LOCK_OFFSET) &= ~BIT(ks); SE(SE_CRYPTO_SECURITY_PERKEY_REG) &= ~BIT(ks);
} }
u32 se_key_acc_ctrl_get(u32 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) 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); memcpy(data, key, size);
for (u32 i = 0; i < (size / 4); i++) for (u32 i = 0; i < (size / 4); i++)
{ {
SE(SE_KEYTABLE_REG_OFFSET) = SE_KEYTABLE_SLOT(ks) | i; SE(SE_CRYPTO_KEYTABLE_ADDR_REG) = SE_KEYTABLE_SLOT(ks) | SE_KEYTABLE_PKT(i); // QUAD is automatically set by PKT.
SE(SE_KEYTABLE_DATA0_REG_OFFSET) = data[i]; SE(SE_CRYPTO_KEYTABLE_DATA_REG) = data[i];
} }
} }
void se_aes_iv_set(u32 ks, void *iv) void se_aes_iv_set(u32 ks, void *iv)
{ {
u32 data[TEGRA_SE_AES_BLOCK_SIZE / 4]; u32 data[SE_AES_IV_SIZE / 4];
memcpy(data, iv, TEGRA_SE_AES_BLOCK_SIZE); 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_CRYPTO_KEYTABLE_ADDR_REG) = SE_KEYTABLE_SLOT(ks) | SE_KEYTABLE_QUAD(ORIGINAL_IV) | SE_KEYTABLE_PKT(i);
SE(SE_KEYTABLE_DATA0_REG_OFFSET) = data[i]; SE(SE_CRYPTO_KEYTABLE_DATA_REG) = data[i];
} }
} }
void se_aes_key_get(u32 ks, void *key, u32 size) 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++) for (u32 i = 0; i < (size / 4); i++)
{ {
SE(SE_KEYTABLE_REG_OFFSET) = SE_KEYTABLE_SLOT(ks) | i; SE(SE_CRYPTO_KEYTABLE_ADDR_REG) = SE_KEYTABLE_SLOT(ks) | SE_KEYTABLE_PKT(i); // QUAD is automatically set by PKT.
data[i] = SE(SE_KEYTABLE_DATA0_REG_OFFSET); data[i] = SE(SE_CRYPTO_KEYTABLE_DATA_REG);
} }
memcpy(key, data, size); 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) 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_CRYPTO_KEYTABLE_ADDR_REG) = SE_KEYTABLE_SLOT(ks) | SE_KEYTABLE_PKT(i); // QUAD is automatically set by PKT.
SE(SE_KEYTABLE_DATA0_REG_OFFSET) = 0; SE(SE_CRYPTO_KEYTABLE_DATA_REG) = 0;
} }
} }
void se_aes_iv_clear(u32 ks) 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_CRYPTO_KEYTABLE_ADDR_REG) = SE_KEYTABLE_SLOT(ks) | SE_KEYTABLE_QUAD(ORIGINAL_IV) | SE_KEYTABLE_PKT(i);
SE(SE_KEYTABLE_DATA0_REG_OFFSET) = 0; SE(SE_CRYPTO_KEYTABLE_DATA_REG) = 0;
} }
} }
int se_aes_unwrap_key(u32 ks_dst, u32 ks_src, const void *input) 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_CONFIG_REG) = SE_CONFIG_DEC_ALG(ALG_AES_DEC) | SE_CONFIG_DST(DST_KEYTABLE);
SE(SE_CRYPTO_REG_OFFSET) = SE_CRYPTO_KEY_INDEX(ks_src) | SE_CRYPTO_CORE_SEL(CORE_DECRYPT); SE(SE_CRYPTO_CONFIG_REG) = SE_CRYPTO_KEY_INDEX(ks_src) | SE_CRYPTO_CORE_SEL(CORE_DECRYPT);
SE(SE_BLOCK_COUNT_REG_OFFSET) = 0; SE(SE_CRYPTO_BLOCK_COUNT_REG) = 1 - 1;
SE(SE_CRYPTO_KEYTABLE_DST_REG_OFFSET) = SE_CRYPTO_KEYTABLE_DST_KEY_INDEX(ks_dst); 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) int se_aes_crypt_ecb(u32 ks, u32 enc, void *dst, u32 dst_size, const void *src, u32 src_size)
{ {
if (enc) if (enc)
{ {
SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_ENC_ALG(ALG_AES_ENC) | SE_CONFIG_DST(DST_MEMORY); SE(SE_CONFIG_REG) = 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_CRYPTO_CONFIG_REG) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_CORE_SEL(CORE_ENCRYPT);
} }
else else
{ {
SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_DEC_ALG(ALG_AES_DEC) | SE_CONFIG_DST(DST_MEMORY); SE(SE_CONFIG_REG) = 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_CRYPTO_CONFIG_REG) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_CORE_SEL(CORE_DECRYPT);
} }
SE(SE_BLOCK_COUNT_REG_OFFSET) = (src_size >> 4) - 1; SE(SE_CRYPTO_BLOCK_COUNT_REG) = (src_size >> 4) - 1;
return _se_execute_oneshot(OP_START, dst, dst_size, src, src_size); 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) int se_aes_crypt_cbc(u32 ks, u32 enc, void *dst, u32 dst_size, const void *src, u32 src_size)
{ {
if (enc) if (enc)
{ {
SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_ENC_ALG(ALG_AES_ENC) | SE_CONFIG_DST(DST_MEMORY); SE(SE_CONFIG_REG) = 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_CRYPTO_CONFIG_REG) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_VCTRAM_SEL(VCTRAM_AESOUT) |
SE_CRYPTO_CORE_SEL(CORE_ENCRYPT) | SE_CRYPTO_XOR_POS(XOR_TOP); SE_CRYPTO_CORE_SEL(CORE_ENCRYPT) | SE_CRYPTO_XOR_POS(XOR_TOP);
} }
else else
{ {
SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_DEC_ALG(ALG_AES_DEC) | SE_CONFIG_DST(DST_MEMORY); SE(SE_CONFIG_REG) = 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_CRYPTO_CONFIG_REG) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_VCTRAM_SEL(VCTRAM_PREVMEM) |
SE_CRYPTO_CORE_SEL(CORE_DECRYPT) | SE_CRYPTO_XOR_POS(XOR_BOTTOM); SE_CRYPTO_CORE_SEL(CORE_DECRYPT) | SE_CRYPTO_XOR_POS(XOR_BOTTOM);
} }
SE(SE_BLOCK_COUNT_REG_OFFSET) = (src_size >> 4) - 1; SE(SE_CRYPTO_BLOCK_COUNT_REG) = (src_size >> 4) - 1;
return _se_execute_oneshot(OP_START, dst, dst_size, src, src_size); 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) 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) 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_SPARE_REG) = SE_ECO(SE_ERRATA_FIX_ENABLE);
SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_ENC_ALG(ALG_AES_ENC) | SE_CONFIG_DST(DST_MEMORY); SE(SE_CONFIG_REG) = 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_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_VAL(1); SE_CRYPTO_XOR_POS(XOR_BOTTOM) | SE_CRYPTO_INPUT_SEL(INPUT_LNR_CTR) | SE_CRYPTO_CTR_CNTN(1);
_se_aes_ctr_set(ctr); _se_aes_ctr_set(ctr);
u32 src_size_aligned = src_size & 0xFFFFFFF0; 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) if (src_size_aligned)
{ {
SE(SE_BLOCK_COUNT_REG_OFFSET) = (src_size >> 4) - 1; SE(SE_CRYPTO_BLOCK_COUNT_REG) = (src_size >> 4) - 1;
if (!_se_execute_oneshot(OP_START, dst, dst_size, src, src_size_aligned)) if (!_se_execute_oneshot(SE_OP_START, dst, dst_size, src, src_size_aligned))
return 0; return 0;
} }
if (src_size - src_size_aligned && src_size_aligned < dst_size) 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), MIN(src_size_delta, dst_size - src_size_aligned),
src + src_size_aligned, src_size_delta); 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 se_aes_xts_crypt_sec(u32 ks1, u32 ks2, u32 enc, u64 sec, void *dst, void *src, u32 secsize)
{ {
int res = 0; int res = 0;
u8 *tweak = (u8 *)malloc(0x10); u8 *tweak = (u8 *)malloc(SE_AES_BLOCK_SIZE);
u8 *pdst = (u8 *)dst; u8 *pdst = (u8 *)dst;
u8 *psrc = (u8 *)src; u8 *psrc = (u8 *)src;
//Generate tweak. // Generate tweak.
for (int i = 0xF; i >= 0; i--) for (int i = 0xF; i >= 0; i--)
{ {
tweak[i] = sec & 0xFF; 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)) if (!se_aes_crypt_block_ecb(ks1, 1, tweak, tweak))
goto out; goto out;
//We are assuming a 0x10-aligned sector size in this implementation. // We are assuming a 0x10-aligned sector size in this implementation.
for (u32 i = 0; i < secsize / 0x10; i++) 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]; pdst[j] = psrc[j] ^ tweak[j];
if (!se_aes_crypt_block_ecb(ks2, enc, pdst, pdst)) if (!se_aes_crypt_block_ecb(ks2, enc, pdst, pdst))
goto out; 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]; pdst[j] = pdst[j] ^ tweak[j];
_gf256_mul_x(tweak); _gf256_mul_x(tweak);
psrc += 0x10; psrc += SE_AES_BLOCK_SIZE;
pdst += 0x10; pdst += SE_AES_BLOCK_SIZE;
} }
res = 1; 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 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; 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. //! 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. if (src_size > 0xFFFFFF || !hash) // Max 16MB - 1 chunks and aligned x4 hash buffer.
return 0; return 0;
// Setup config for SHA256. // 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_CONFIG_REG) = 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_SHA_CONFIG_REG) = sha_cfg;
SE(SE_BLOCK_COUNT_REG_OFFSET) = 0; SE(SE_CRYPTO_BLOCK_COUNT_REG) = 1 - 1;
// Set total size to current buffer size if empty. // Set total size to current buffer size if empty.
if (!total_size) if (!total_size)
total_size = src_size; total_size = src_size;
// Set total size: BITS(src_size), up to 2 EB. // 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_0_REG) = (u32)(total_size << 3);
SE(SE_SHA_MSG_LENGTH_1_REG_OFFSET) = (u32)(total_size >> 29); SE(SE_SHA_MSG_LENGTH_1_REG) = (u32)(total_size >> 29);
SE(SE_SHA_MSG_LENGTH_2_REG_OFFSET) = 0; SE(SE_SHA_MSG_LENGTH_2_REG) = 0;
SE(SE_SHA_MSG_LENGTH_3_REG_OFFSET) = 0; SE(SE_SHA_MSG_LENGTH_3_REG) = 0;
// Set size left to hash. // Set size left to hash.
SE(SE_SHA_MSG_LEFT_0_REG_OFFSET) = (u32)(total_size << 3); SE(SE_SHA_MSG_LEFT_0_REG) = (u32)(total_size << 3);
SE(SE_SHA_MSG_LEFT_1_REG_OFFSET) = (u32)(total_size >> 29); SE(SE_SHA_MSG_LEFT_1_REG) = (u32)(total_size >> 29);
SE(SE_SHA_MSG_LEFT_2_REG_OFFSET) = 0; SE(SE_SHA_MSG_LEFT_2_REG) = 0;
SE(SE_SHA_MSG_LEFT_3_REG_OFFSET) = 0; SE(SE_SHA_MSG_LEFT_3_REG) = 0;
// If we hash in chunks, copy over the intermediate. // If we hash in chunks, copy over the intermediate.
if (sha_cfg == SHA_CONTINUE && msg_left) if (sha_cfg == SHA_CONTINUE && msg_left)
{ {
// Restore message left to process. // Restore message left to process.
SE(SE_SHA_MSG_LEFT_0_REG_OFFSET) = msg_left[0]; SE(SE_SHA_MSG_LEFT_0_REG) = msg_left[0];
SE(SE_SHA_MSG_LEFT_1_REG_OFFSET) = msg_left[1]; SE(SE_SHA_MSG_LEFT_1_REG) = msg_left[1];
// Restore hash reg. // Restore hash reg.
memcpy(hash32, hash, TEGRA_SE_SHA_256_SIZE); memcpy(hash32, hash, SE_SHA_256_SIZE);
for (u32 i = 0; i < (TEGRA_SE_SHA_256_SIZE / 4); i++) for (u32 i = 0; i < (SE_SHA_256_SIZE / 4); i++)
SE(SE_HASH_RESULT_REG_OFFSET + (i << 2)) = byte_swap_32(hash32[i]); SE(SE_HASH_RESULT_REG + (i * 4)) = byte_swap_32(hash32[i]);
} }
// Trigger the operation. // 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) if (is_oneshot)
{ {
// Backup message left. // Backup message left.
if (msg_left) if (msg_left)
{ {
msg_left[0] = SE(SE_SHA_MSG_LEFT_0_REG_OFFSET); msg_left[0] = SE(SE_SHA_MSG_LEFT_0_REG);
msg_left[1] = SE(SE_SHA_MSG_LEFT_1_REG_OFFSET); msg_left[1] = SE(SE_SHA_MSG_LEFT_1_REG);
} }
// Copy output hash. // Copy output hash.
for (u32 i = 0; i < (TEGRA_SE_SHA_256_SIZE / 4); i++) for (u32 i = 0; i < (SE_SHA_256_SIZE / 4); i++)
hash32[i] = byte_swap_32(SE(SE_HASH_RESULT_REG_OFFSET + (i << 2))); hash32[i] = byte_swap_32(SE(SE_HASH_RESULT_REG + (i * 4)));
memcpy(hash, hash32, TEGRA_SE_SHA_256_SIZE); memcpy(hash, hash32, SE_SHA_256_SIZE);
} }
return res; 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) 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(); int res = _se_execute_finalize();
// Backup message left. // Backup message left.
if (msg_left) if (msg_left)
{ {
msg_left[0] = SE(SE_SHA_MSG_LEFT_0_REG_OFFSET); msg_left[0] = SE(SE_SHA_MSG_LEFT_0_REG);
msg_left[1] = SE(SE_SHA_MSG_LEFT_1_REG_OFFSET); msg_left[1] = SE(SE_SHA_MSG_LEFT_1_REG);
} }
// Copy output hash. // Copy output hash.
for (u32 i = 0; i < (TEGRA_SE_SHA_256_SIZE / 4); i++) for (u32 i = 0; i < (SE_SHA_256_SIZE / 4); i++)
hash32[i] = byte_swap_32(SE(SE_HASH_RESULT_REG_OFFSET + (i << 2))); hash32[i] = byte_swap_32(SE(SE_HASH_RESULT_REG + (i * 4)));
memcpy(hash, hash32, TEGRA_SE_SHA_256_SIZE); memcpy(hash, hash32, SE_SHA_256_SIZE);
return res; return res;
} }
@@ -463,18 +463,17 @@ int se_calc_sha256_finalize(void *hash, u32 *msg_left)
int se_gen_prng128(void *dst) int se_gen_prng128(void *dst)
{ {
// Setup config for X931 PRNG. // 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_CONFIG_REG) = 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_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_CRYPTO_BLOCK_COUNT_REG) = (16 >> 4) - 1;
//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;
// Trigger the operation. // 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) 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); u8 *aligned_buf = (u8 *)ALIGN((u32)buf, 0x40);
// Set Secure Random Key. // 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_CONFIG_REG) = 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_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_OFFSET) = SE_RNG_CONFIG_SRC(RNG_SRC_ENTROPY) | SE_RNG_CONFIG_MODE(RNG_MODE_FORCE_RESEED); 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(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. // 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) | SE(SE_CONTEXT_SAVE_CONFIG_REG) = SE_CONTEXT_SRC(AES_KEYTABLE) | SE_KEYTABLE_DST_KEY_INDEX(i) |
(i << SE_KEY_INDEX_SHIFT) | SE_CONTEXT_SAVE_WORD_QUAD(KEYS_0_3); SE_CONTEXT_AES_KEY_INDEX(0) | SE_CONTEXT_AES_WORD_QUAD(KEYS_0_3);
SE(SE_CRYPTO_LAST_BLOCK) = 0; SE(SE_CRYPTO_LAST_BLOCK) = 0;
_se_execute_oneshot(OP_CTX_SAVE, aligned_buf, 0x10, NULL, 0); _se_execute_oneshot(SE_OP_CTX_SAVE, aligned_buf, SE_AES_BLOCK_SIZE, NULL, 0);
memcpy(keys + i * keysize, aligned_buf, 0x10); 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) | SE(SE_CONTEXT_SAVE_CONFIG_REG) = SE_CONTEXT_SRC(AES_KEYTABLE) | SE_KEYTABLE_DST_KEY_INDEX(i) |
(i << SE_KEY_INDEX_SHIFT) | SE_CONTEXT_SAVE_WORD_QUAD(KEYS_4_7); SE_CONTEXT_AES_KEY_INDEX(0) | SE_CONTEXT_AES_WORD_QUAD(KEYS_4_7);
SE(SE_CRYPTO_LAST_BLOCK) = 0; SE(SE_CRYPTO_LAST_BLOCK) = 0;
_se_execute_oneshot(OP_CTX_SAVE, aligned_buf, 0x10, NULL, 0); _se_execute_oneshot(SE_OP_CTX_SAVE, aligned_buf, SE_AES_BLOCK_SIZE, NULL, 0);
memcpy(keys + i * keysize + 0x10, aligned_buf, 0x10); memcpy(keys + i * keysize + SE_AES_BLOCK_SIZE, aligned_buf, SE_AES_BLOCK_SIZE);
} }
} }
// Save SRK to PMC secure scratches. // Save SRK to PMC secure scratches.
SE(SE_CONTEXT_SAVE_CONFIG_REG_OFFSET) = SE_CONTEXT_SAVE_SRC(SRK); SE(SE_CONTEXT_SAVE_CONFIG_REG) = SE_CONTEXT_SRC(SRK);
SE(SE_CRYPTO_LAST_BLOCK) = 0; SE(SE_CRYPTO_LAST_BLOCK) = 0;
_se_execute_oneshot(OP_CTX_SAVE, NULL, 0, NULL, 0); _se_execute_oneshot(SE_OP_CTX_SAVE, NULL, 0, NULL, 0);
// End context save. // End context save.
SE(SE_CONFIG_REG_OFFSET) = 0; SE(SE_CONFIG_REG) = 0;
_se_execute_oneshot(OP_CTX_SAVE, NULL, 0, NULL, 0); _se_execute_oneshot(SE_OP_CTX_SAVE, NULL, 0, NULL, 0);
// Get SRK. // Get SRK.
u32 srk[4]; u32 srk[4];
@@ -529,7 +528,7 @@ void se_get_aes_keys(u8 *buf, u8 *keys, u32 keysize)
// Decrypt context. // Decrypt context.
se_aes_key_clear(3); se_aes_key_clear(3);
se_aes_key_set(3, srk, 0x10); se_aes_key_set(3, srk, SE_KEY_128_SIZE);
se_aes_crypt_cbc(3, 0, keys, TEGRA_SE_KEYSLOT_COUNT * keysize, keys, TEGRA_SE_KEYSLOT_COUNT * keysize); se_aes_crypt_cbc(3, 0, keys, SE_AES_KEYSLOT_COUNT * keysize, keys, SE_AES_KEYSLOT_COUNT * keysize);
se_aes_key_clear(3); se_aes_key_clear(3);
} }

View File

@@ -1,18 +1,19 @@
/* /*
* Copyright (c) 2018 naehrwert * 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, * This program is free software; you can redistribute it and/or modify it
* version 2, as published by the Free Software Foundation. * 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 * This program is distributed in the hope it will be useful, but WITHOUT
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* more details. * 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/>. * 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_ #ifndef _SE_H_
#define _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_get(u32 ks, void *key, u32 size);
void se_aes_key_clear(u32 ks); void se_aes_key_clear(u32 ks);
void se_aes_iv_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_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_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_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_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_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(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_oneshot(void *hash, const void *src, u32 src_size);
int se_calc_sha256_finalize(void *hash, u32 *msg_left); int se_calc_sha256_finalize(void *hash, u32 *msg_left);
int se_gen_prng128(void *dst); int se_gen_prng128(void *dst);
#endif #endif

View File

@@ -1,400 +1,323 @@
/* /*
* Driver for Tegra Security Engine * Copyright (c) 2018 naehrwert
* * Copyright (c) 2018-2021 CTCaer
* Copyright (c) 2011-2013, NVIDIA Corporation. All Rights Reserved. *
* * This program is free software; you can redistribute it and/or modify it
* This program is free software; you can redistribute it and/or modify * under the terms and conditions of the GNU General Public License,
* it under the terms of the GNU General Public License as published by * version 2, as published by the Free Software Foundation.
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. * This program is distributed in the hope it will be useful, but WITHOUT
* * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* This program is distributed in the hope that it will be useful, but WITHOUT * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * more details.
* 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/>.
* 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.
*/
#ifndef _CRYPTO_TEGRA_SE_H #ifndef _SE_T210_H
#define _CRYPTO_TEGRA_SE_H #define _SE_T210_H
#include <utils/types.h> #include <utils/types.h>
#define TEGRA_SE_CRA_PRIORITY 300 #define SE_CRYPTO_QUEUE_LENGTH 50
#define TEGRA_SE_COMPOSITE_PRIORITY 400 #define SE_MAX_SRC_SG_COUNT 50
#define TEGRA_SE_CRYPTO_QUEUE_LENGTH 50 #define SE_MAX_DST_SG_COUNT 50
#define SE_MAX_SRC_SG_COUNT 50
#define SE_MAX_DST_SG_COUNT 50
#define TEGRA_SE_KEYSLOT_COUNT 16 #define SE_AES_KEYSLOT_COUNT 16
#define SE_MAX_LAST_BLOCK_SIZE 0xFFFFF #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 */ /* SE register definitions */
#define SE_SECURITY_0 0x000 #define SE_SE_SECURITY_REG 0x000
#define SE_KEY_SCHED_READ_SHIFT 3 #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_OPERATION_REG 0x008
#define SE_CONFIG_ENC_ALG_SHIFT 12 #define SE_OP_ABORT 0
#define SE_CONFIG_DEC_ALG_SHIFT 8 #define SE_OP_START 1
#define ALG_AES_ENC 1 #define SE_OP_RESTART_OUT 2
#define ALG_RNG 2 #define SE_OP_CTX_SAVE 3
#define ALG_SHA 3 #define SE_OP_RESTART_IN 4
#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_RNG_CONFIG_REG_OFFSET 0x340 #define SE_INT_ENABLE_REG 0x00C
#define RNG_MODE_SHIFT 0 #define SE_INT_STATUS_REG 0x010
#define RNG_MODE_NORMAL 0 #define SE_INT_IN_LL_BUF_RD BIT(0)
#define RNG_MODE_FORCE_INSTANTION 1 #define SE_INT_IN_DONE BIT(1)
#define RNG_MODE_FORCE_RESEED 2 #define SE_INT_OUT_LL_BUF_WR BIT(2)
#define SE_RNG_CONFIG_MODE(x) ((x) << RNG_MODE_SHIFT) #define SE_INT_OUT_DONE BIT(3)
#define RNG_SRC_SHIFT 2 #define SE_INT_OP_DONE BIT(4)
#define RNG_SRC_NONE 0 #define SE_INT_RESEED_NEEDED BIT(5)
#define RNG_SRC_ENTROPY 1 #define SE_INT_ERR_STAT BIT(16)
#define RNG_SRC_LFSR 2
#define SE_RNG_CONFIG_SRC(x) ((x) << RNG_SRC_SHIFT)
#define SE_RNG_SRC_CONFIG_REG_OFFSET 0x344 #define SE_CONFIG_REG 0x014
#define RNG_SRC_RO_ENT_SHIFT 1 #define DST_MEMORY 0
#define RNG_SRC_RO_ENT_ENABLE 1 #define DST_HASHREG 1
#define RNG_SRC_RO_ENT_DISABLE 0 #define DST_KEYTABLE 2
#define SE_RNG_SRC_CONFIG_ENT_SRC(x) ((x) << RNG_SRC_RO_ENT_SHIFT) #define DST_SRK 3
#define RNG_SRC_RO_ENT_LOCK_SHIFT 0 #define DST_RSAREG 4
#define RNG_SRC_RO_ENT_LOCK_ENABLE 1 #define SE_CONFIG_DST(x) ((x) << 2)
#define RNG_SRC_RO_ENT_LOCK_DISABLE 0 #define ALG_NOP 0
#define SE_RNG_SRC_CONFIG_ENT_SRC_LOCK(x) ((x) << RNG_SRC_RO_ENT_LOCK_SHIFT) #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_HASH_RESULT_REG 0x030
#define SE_KEYTABLE_SLOT_SHIFT 4 #define SE_HASH_RESULT_REG_COUNT 16
#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_OP_DONE_SHIFT 4 #define SE_CONTEXT_SAVE_CONFIG_REG 0x070
#define OP_DONE 1 #define KEYS_0_3 0
#define SE_OP_DONE(x, y) ((x) && ((y) << SE_OP_DONE_SHIFT)) #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_LAST_BLOCK 0x080
#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_CTR_REG_COUNT 4 #define SE_SHA_CONFIG_REG 0x200
#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 SHA_CONTINUE 0 #define SHA_CONTINUE 0
#define SHA_INIT_HASH 1 #define SHA_INIT_HASH 1
#define SE_SHA_MSG_LENGTH_0_REG_OFFSET 0x204 #define SE_SHA_MSG_LENGTH_0_REG 0x204
#define SE_SHA_MSG_LENGTH_1_REG_OFFSET 0x208 #define SE_SHA_MSG_LENGTH_1_REG 0x208
#define SE_SHA_MSG_LENGTH_2_REG_OFFSET 0x20C #define SE_SHA_MSG_LENGTH_2_REG 0x20C
#define SE_SHA_MSG_LENGTH_3_REG_OFFSET 0x210 #define SE_SHA_MSG_LENGTH_3_REG 0x210
#define SE_SHA_MSG_LEFT_0_REG_OFFSET 0x214 #define SE_SHA_MSG_LEFT_0_REG 0x214
#define SE_SHA_MSG_LEFT_1_REG_OFFSET 0x218 #define SE_SHA_MSG_LEFT_1_REG 0x218
#define SE_SHA_MSG_LEFT_2_REG_OFFSET 0x21C #define SE_SHA_MSG_LEFT_2_REG 0x21C
#define SE_SHA_MSG_LEFT_3_REG_OFFSET 0x220 #define SE_SHA_MSG_LEFT_3_REG 0x220
#define SE_HASH_RESULT_REG_COUNT 16 #define SE_CRYPTO_SECURITY_PERKEY_REG 0x280
#define SE_HASH_RESULT_REG_OFFSET 0x030 #define SE_KEY_LOCK_FLAG 0x80
#define TEGRA_SE_KEY_256_SIZE 32 #define SE_CRYPTO_KEYTABLE_ACCESS_REG 0x284
#define TEGRA_SE_KEY_192_SIZE 24 #define SE_CRYPTO_KEYTABLE_ACCESS_REG_COUNT 16
#define TEGRA_SE_KEY_128_SIZE 16 #define SE_KEY_TBL_DIS_KEYREAD_FLAG BIT(0)
#define TEGRA_SE_AES_BLOCK_SIZE 16 #define SE_KEY_TBL_DIS_KEYUPDATE_FLAG BIT(1)
#define TEGRA_SE_AES_MIN_KEY_SIZE 16 #define SE_KEY_TBL_DIS_OIVREAD_FLAG BIT(2)
#define TEGRA_SE_AES_MAX_KEY_SIZE 32 #define SE_KEY_TBL_DIS_OIVUPDATE_FLAG BIT(3)
#define TEGRA_SE_AES_IV_SIZE 16 #define SE_KEY_TBL_DIS_UIVREAD_FLAG BIT(4)
#define TEGRA_SE_SHA_512_SIZE 64 #define SE_KEY_TBL_DIS_UIVUPDATE_FLAG BIT(5)
#define TEGRA_SE_SHA_384_SIZE 48 #define SE_KEY_TBL_DIS_KEYUSE_FLAG BIT(6)
#define TEGRA_SE_SHA_256_SIZE 32 #define SE_KEY_TBL_DIS_KEY_ACCESS_FLAG 0x7F
#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 TEGRA_SE_AES_CMAC_DIGEST_SIZE 16 #define SE_CRYPTO_CONFIG_REG 0x304
#define TEGRA_SE_RSA512_DIGEST_SIZE 64 #define HASH_DISABLE 0
#define TEGRA_SE_RSA1024_DIGEST_SIZE 128 #define HASH_ENABLE 1
#define TEGRA_SE_RSA1536_DIGEST_SIZE 192 #define SE_CRYPTO_HASH(x) ((x) << 0)
#define TEGRA_SE_RSA2048_DIGEST_SIZE 256 #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_CRYPTO_LINEAR_CTR_REG 0x308
#define SE_KEY_TBL_DIS_KEY_LOCK_FLAG 0x80 #define SE_CRYPTO_LINEAR_CTR_REG_COUNT 4
#define SE_KEY_TABLE_ACCESS_REG_OFFSET 0x284 #define SE_CRYPTO_BLOCK_COUNT_REG 0x318
#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_KEY_READ_DISABLE_SHIFT 0 #define SE_CRYPTO_KEYTABLE_ADDR_REG 0x31C
#define SE_KEY_UPDATE_DISABLE_SHIFT 1 #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_CRYPTO_KEYTABLE_DATA_REG 0x320
#define SE_CONTEXT_DRBG_BUFER_SIZE 2112
#define SE_CONTEXT_SAVE_RANDOM_DATA_OFFSET 0 #define SE_CRYPTO_KEYTABLE_DST_REG 0x330
#define SE_CONTEXT_SAVE_RANDOM_DATA_SIZE 16 #define KEYS_0_3 0
#define SE_CONTEXT_SAVE_STICKY_BITS_OFFSET \ #define KEYS_4_7 1
(SE_CONTEXT_SAVE_RANDOM_DATA_OFFSET + SE_CONTEXT_SAVE_RANDOM_DATA_SIZE) #define ORIGINAL_IV 2
#define SE_CONTEXT_SAVE_STICKY_BITS_SIZE 16 #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 + \ #define SE_RNG_CONFIG_REG 0x340
SE_CONTEXT_SAVE_STICKY_BITS_SIZE) #define MODE_NORMAL 0
#define SE11_CONTEXT_SAVE_KEYS_OFFSET (SE_CONTEXT_SAVE_STICKY_BITS_OFFSET + \ #define MODE_FORCE_INSTANTION 1
SE_CONTEXT_SAVE_STICKY_BITS_SIZE + \ #define MODE_FORCE_RESEED 2
SE_CONTEXT_SAVE_STICKY_BITS_SIZE) #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_RNG_SRC_CONFIG_REG 0x344
#define SE_CONTEXT_ORIGINAL_IV_OFFSET (SE_CONTEXT_SAVE_KEYS_OFFSET + \ #define RO_ENTR_LOCK_DISABLE 0
SE_CONTEXT_SAVE_KEY_LENGTH) #define RO_ENTR_LOCK_ENABLE 1
#define SE11_CONTEXT_ORIGINAL_IV_OFFSET (SE11_CONTEXT_SAVE_KEYS_OFFSET + \ #define SE_RNG_SRC_CONFIG_ENTR_SRC_LOCK(x) ((x) << 0)
SE_CONTEXT_SAVE_KEY_LENGTH) #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 + \ #define SE_RSA_CONFIG 0x400
SE_CONTEXT_ORIGINAL_IV_LENGTH) #define RSA_KEY_SLOT_ONE 0
#define SE11_CONTEXT_UPDATED_IV_OFFSET (SE11_CONTEXT_ORIGINAL_IV_OFFSET + \ #define RSA_KEY_SLOT_TW0 1
SE_CONTEXT_ORIGINAL_IV_LENGTH) #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 + \ #define SE_RSA_EXP_SIZE_REG 0x408
SE_CONTEXT_UPDATED_IV_LENGTH)
#define SE11_CONTEXT_SAVE_KNOWN_PATTERN_OFFSET \
(SE11_CONTEXT_UPDATED_IV_OFFSET + \
SE_CONTEXT_UPDATED_IV_LENGTH)
#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 \ #define SE_RSA_KEYTABLE_DATA_REG 0x424
(SE_CONTEXT_SAVE_RSA_KEYS_OFFSET + SE_CONTEXT_SAVE_RSA_KEY_LENGTH)
#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_ERR_STATUS_REG 0x804
#define SE_RSA_KEY_TBL_DIS_KEY_LOCK_FLAG 0x80 #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_MISC_REG 0x808
#define SE_RSA_KEY_TBL_DIS_KEYREAD_FLAG BIT(0) #define SE_ENTROPY_NEXT_192BIT BIT(0)
#define SE_RSA_KEY_TBL_DIS_KEYUPDATE_FLAG BIT(1) #define SE_ENTROPY_VN_BYPASS 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_CLK_OVR_ON BIT(2)
#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_RSA_KEYTABLE_ADDR 0x420 #define SE_SPARE_REG 0x80C
#define SE_RSA_KEYTABLE_DATA 0x424 #define SE_ERRATA_FIX_DISABLE 0
#define SE_RSA_OUTPUT 0x428 #define SE_ERRATA_FIX_ENABLE 1
#define SE_ECO(x) ((x) << 0)
#define RSA_KEY_READ 0 #endif
#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 */

View File

@@ -1,6 +1,6 @@
/* /*
* Copyright (c) 2018 naehrwert * Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2019 CTCaer * Copyright (c) 2018-2021 CTCaer
* Copyright (c) 2018 balika011 * Copyright (c) 2018 balika011
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
@@ -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(); 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; int res = 0;
u8 *fwbuf = NULL; 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) if (kb == KB_TSEC_FW_EMU_COMPAT)
{ {
u32 start = get_tmr_us(); 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 key[16] = {0};
u32 kidx = 0; u32 kidx = 0;
@@ -198,9 +198,9 @@ int tsec_query(u8 *tsec_keys, u8 kb, tsec_ctxt_t *tsec_ctxt)
{ {
smmu_flush_all(); 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; 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_MSB) = 0;
SOR1(SOR_NV_PDISP_SOR_TMDS_HDCP_CN_LSB) = 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:; out_free:;

View File

@@ -29,6 +29,6 @@ typedef struct _tsec_ctxt_t
u32 secmon_base; u32 secmon_base;
} tsec_ctxt_t; } 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 #endif

View File

@@ -1,6 +1,6 @@
/* /*
* Copyright (c) 2018 naehrwert * 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 * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@@ -264,7 +264,7 @@ static void _config_se_brom()
FUSE(FUSE_PRIVATE_KEY3) FUSE(FUSE_PRIVATE_KEY3)
}; };
// Set SBK to slot 14. // 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. // Lock SBK from being read.
se_key_acc_ctrl(14, SE_KEY_TBL_DIS_KEYREAD_FLAG); se_key_acc_ctrl(14, SE_KEY_TBL_DIS_KEYREAD_FLAG);
@@ -276,7 +276,7 @@ static void _config_se_brom()
// This memset needs to happen here, else TZRAM will behave weirdly later on. // This memset needs to happen here, else TZRAM will behave weirdly later on.
memset((void *)TZRAM_BASE, 0, 0x10000); memset((void *)TZRAM_BASE, 0, 0x10000);
PMC(APBDEV_PMC_CRYPTO_OP) = PMC_CRYPTO_OP_SE_ENABLE; 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 // Clear the boot reason to avoid problems later
PMC(APBDEV_PMC_SCRATCH200) = 0x0; PMC(APBDEV_PMC_SCRATCH200) = 0x0;

View File

@@ -84,6 +84,11 @@
#define MMC_APP_CMD 55 /* ac [31:16] RCA R1 */ #define MMC_APP_CMD 55 /* ac [31:16] RCA R1 */
#define MMC_GEN_CMD 56 /* adtc [0] RD/WR 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 */ /* class 11 */
#define MMC_QUE_TASK_PARAMS 44 /* ac [20:16] task id R1 */ #define MMC_QUE_TASK_PARAMS 44 /* ac [20:16] task id R1 */
#define MMC_QUE_TASK_ADDR 45 /* ac [31:0] data addr 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 * 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) * Card Command Classes (CCC)
@@ -244,6 +252,7 @@ c : clear by read
#define EXT_CSD_GP_SIZE_MULT 143 /* R/W */ #define EXT_CSD_GP_SIZE_MULT 143 /* R/W */
#define EXT_CSD_PARTITION_SETTING_COMPLETED 155 /* R/W */ #define EXT_CSD_PARTITION_SETTING_COMPLETED 155 /* R/W */
#define EXT_CSD_PARTITION_ATTRIBUTE 156 /* 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_PARTITION_SUPPORT 160 /* RO */
#define EXT_CSD_HPI_MGMT 161 /* R/W */ #define EXT_CSD_HPI_MGMT 161 /* R/W */
#define EXT_CSD_RST_N_FUNCTION 162 /* R/W */ #define EXT_CSD_RST_N_FUNCTION 162 /* R/W */

View File

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

View File

@@ -1,7 +1,7 @@
/* /*
* Ramdisk driver for Tegra X1 * 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 * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@@ -19,23 +19,40 @@
#include <string.h> #include <string.h>
#include "ramdisk.h" #include "ramdisk.h"
#include <libs/fatfs/diskio.h>
#include <mem/heap.h> #include <mem/heap.h>
#include <utils/types.h> #include <utils/types.h>
#include <memory_map.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; int res = 0;
u8 *buf = malloc(0x400000); 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. // Set ramdisk size.
if (!res) ramdisk_size >>= 9;
res = f_mount(ram_fs, "ram:", 1); // Mount ramdisk. 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; 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 sector_off = RAM_DISK_ADDR + (sector << 9);
u32 bytes_count = sector_count << 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; return 1;
memcpy(buf, (void *)sector_off, bytes_count); 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 sector_off = RAM_DISK_ADDR + (sector << 9);
u32 bytes_count = sector_count << 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; return 1;
memcpy((void *)sector_off, buf, bytes_count); memcpy((void *)sector_off, buf, bytes_count);

View File

@@ -1,7 +1,7 @@
/* /*
* Ramdisk driver for Tegra X1 * 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 * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@@ -23,7 +23,7 @@
#define RAMDISK_CLUSTER_SZ 32768 #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_read(u32 sector, u32 sector_count, void *buf);
int ram_disk_write(u32 sector, u32 sector_count, const 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) 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 * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@@ -14,60 +14,79 @@
/* SD commands type argument response */ /* SD commands type argument response */
/* class 0 */ /* class 0 */
/* This is basically the same command as for MMC with some quirks. */ /* This is basically the same command as for MMC with some quirks. */
#define SD_SEND_RELATIVE_ADDR 3 /* bcr R6 */ #define SD_SEND_RELATIVE_ADDR 3 /* bcr R6 */
#define SD_SEND_IF_COND 8 /* bcr [11:0] See below R7 */ #define SD_SEND_IF_COND 8 /* bcr [11:0] See below R7 */
#define SD_SWITCH_VOLTAGE 11 /* ac R1 */ #define SD_SWITCH_VOLTAGE 11 /* ac R1 */
/* class 10 */ /* class 10 */
#define SD_SWITCH 6 /* adtc [31:0] See below R1 */ #define SD_SWITCH 6 /* adtc [31:0] See below R1 */
/* class 5 */ /* class 5 */
#define SD_ERASE_WR_BLK_START 32 /* ac [31:0] data addr R1 */ #define SD_ERASE_WR_BLK_START 32 /* ac [31:0] data addr R1 */
#define SD_ERASE_WR_BLK_END 33 /* ac [31:0] data addr R1 */ #define SD_ERASE_WR_BLK_END 33 /* ac [31:0] data addr R1 */
/* Application commands */ /* Application commands */
#define SD_APP_SET_BUS_WIDTH 6 /* ac [1:0] bus width R1 */ #define SD_APP_SET_BUS_WIDTH 6 /* ac [1:0] bus width R1 */
#define SD_APP_SD_STATUS 13 /* adtc R1 */ #define SD_APP_SD_STATUS 13 /* adtc R1 */
#define SD_APP_SEND_NUM_WR_BLKS 22 /* 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_OP_COND 41 /* bcr [31:0] OCR R3 */
#define SD_APP_SET_CLR_CARD_DETECT 42 #define SD_APP_SET_CLR_CARD_DETECT 42 /* adtc R1 */
#define SD_APP_SEND_SCR 51 /* 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 */ /* OCR bit definitions */
#define SD_OCR_CCS (1 << 30) /* Card Capacity Status */ #define SD_OCR_VDD_18 (1 << 7) /* VDD voltage 1.8 */
#define SD_OCR_XPC (1 << 28) /* SDXC power control */ #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_VDD_27_34 (0x7F << 15) /* VDD voltage 2.7 ~ 3.4 */ #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_32_33 (1 << 20) /* VDD voltage 3.2 ~ 3.3 */
#define SD_OCR_VDD_18 (1 << 7) /* VDD voltage 1.8 */ #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_VHD_27_36 (1 << 8) /* VDD voltage 2.7 ~ 3.6 */ #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: * SD_SWITCH argument format:
* *
* [31] Check (0) or switch (1) * [31] Check (0) or switch (1)
* [30:24] Reserved (0) * [30:24] Reserved (0)
* [23:20] Function group 6 * [23:20] Function group 6
* [19:16] Function group 5 * [19:16] Function group 5
* [15:12] Function group 4 * [15:12] Function group 4
* [11:8] Function group 3 * [11:8] Function group 3
* [7:4] Function group 2 * [7:4] Function group 2
* [3:0] Function group 1 * [3:0] Function group 1
*/ */
/* /*
* SD_SEND_IF_COND argument format: * SD_SEND_IF_COND argument format:
* *
* [31:12] Reserved (0) * [31:12] Reserved (0)
* [11:8] Host Voltage Supply Flags * [11:8] Host Voltage Supply Flags
* [7:0] Check Pattern (0xAA) * [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_0 0 /* Implements system specification 1.0 - 1.01 */
#define SCR_SPEC_VER_1 1 /* Implements system specification 1.10 */ #define SCR_SPEC_VER_1 1 /* Implements system specification 1.10 */
#define SCR_SPEC_VER_2 2 /* Implements system specification 2.00-3.0X */ #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) #define SD_SCR_BUS_WIDTH_4 (1<<2)
/* /*
* SD bus widths * SD bus widths
*/ */
#define SD_BUS_WIDTH_1 0 #define SD_BUS_WIDTH_1 0
#define SD_BUS_WIDTH_4 2 #define SD_BUS_WIDTH_4 2
/* /*
* SD bus speeds * SD bus speeds
*/ */
#define UHS_SDR12_BUS_SPEED 0 #define UHS_SDR12_BUS_SPEED 0
#define HIGH_SPEED_BUS_SPEED 1 #define HIGH_SPEED_BUS_SPEED 1
#define UHS_SDR25_BUS_SPEED 1 #define UHS_SDR25_BUS_SPEED 1
@@ -112,19 +131,19 @@
#define SD_MAX_CURRENT_800 (1 << SD_SET_CURRENT_LIMIT_800) #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_CHECK 0
#define SD_SWITCH_SET 1 #define SD_SWITCH_SET 1
/* /*
* SD_SWITCH function groups * SD_SWITCH function groups
*/ */
#define SD_SWITCH_GRP_ACCESS 0 #define SD_SWITCH_GRP_ACCESS 0
/* /*
* SD_SWITCH access modes * SD_SWITCH access modes
*/ */
#define SD_SWITCH_ACCESS_DEF 0 #define SD_SWITCH_ACCESS_DEF 0
#define SD_SWITCH_ACCESS_HS 1 #define SD_SWITCH_ACCESS_HS 1

View File

@@ -1,6 +1,6 @@
/* /*
* Copyright (c) 2018 naehrwert * 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 * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@@ -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) 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) static int _sdmmc_storage_go_idle_state(sdmmc_storage_t *storage)
{ {
sdmmc_cmd_t cmd; sdmmc_cmd_t cmdbuf;
sdmmc_init_cmd(&cmd, MMC_GO_IDLE_STATE, 0, SDMMC_RSP_TYPE_0, 0); 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_cmd_t cmdbuf;
sdmmc_init_cmd(&cmd, MMC_ALL_SEND_CID, 0, SDMMC_RSP_TYPE_2, 0); sdmmc_init_cmd(&cmdbuf, MMC_ALL_SEND_CID, 0, SDMMC_RSP_TYPE_2, 0);
if (!sdmmc_execute_cmd(storage->sdmmc, &cmd, NULL, NULL)) if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, NULL, NULL))
return 0; 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; 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); 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_cmd_t cmdbuf;
sdmmc_init_cmd(&cmdbuf, MMC_SEND_CSD, storage->rca << 16, SDMMC_RSP_TYPE_2, 0); sdmmc_init_cmd(&cmdbuf, MMC_SEND_CSD, storage->rca << 16, SDMMC_RSP_TYPE_2, 0);
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, NULL, NULL)) if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, NULL, NULL))
return 0; return 0;
sdmmc_get_rsp(storage->sdmmc, buf, 16, SDMMC_RSP_TYPE_2); sdmmc_get_rsp(storage->sdmmc, (u32 *)storage->raw_csd, 16, SDMMC_RSP_TYPE_2);
return 1; return 1;
} }
@@ -145,6 +145,10 @@ static int _sdmmc_storage_readwrite_ex(sdmmc_storage_t *storage, u32 *blkcnt_out
sdmmc_cmd_t cmdbuf; sdmmc_cmd_t cmdbuf;
sdmmc_req_t reqbuf; 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); sdmmc_init_cmd(&cmdbuf, is_write ? MMC_WRITE_MULTIPLE_BLOCK : MMC_READ_MULTIPLE_BLOCK, sector, SDMMC_RSP_TYPE_1, 0);
reqbuf.buf = buf; reqbuf.buf = buf;
@@ -152,7 +156,7 @@ static int _sdmmc_storage_readwrite_ex(sdmmc_storage_t *storage, u32 *blkcnt_out
reqbuf.blksize = 512; reqbuf.blksize = 512;
reqbuf.is_write = is_write; reqbuf.is_write = is_write;
reqbuf.is_multi_block = 1; 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)) 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) 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; u32 arg = 0;
switch (power) switch (power)
{ {
case SDMMC_POWER_1_8: case SDMMC_POWER_1_8:
arg = SD_OCR_CCS | SD_OCR_VDD_18; arg = MMC_CARD_CCS | MMC_CARD_VDD_18;
break; break;
case SDMMC_POWER_3_3: case SDMMC_POWER_3_3:
arg = SD_OCR_CCS | SD_OCR_VDD_27_34; arg = MMC_CARD_CCS | MMC_CARD_VDD_27_34;
break; break;
default: default:
return 0; return 0;
} }
sdmmc_init_cmd(&cmd, MMC_SEND_OP_COND, arg, SDMMC_RSP_TYPE_3, 0); sdmmc_init_cmd(&cmdbuf, MMC_SEND_OP_COND, arg, SDMMC_RSP_TYPE_3, 0);
if (!sdmmc_execute_cmd(storage->sdmmc, &cmd, NULL, NULL)) if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, NULL, NULL))
return 0; return 0;
return sdmmc_get_rsp(storage->sdmmc, pout, 4, SDMMC_RSP_TYPE_3); return sdmmc_get_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; u32 timeout = get_tmr_ms() + 1500;
while (1) while (true)
{ {
u32 cond = 0; u32 cond = 0;
if (!_mmc_storage_get_op_cond_inner(storage, &cond, power)) if (!_mmc_storage_get_op_cond_inner(storage, &cond, power))
break; break;
// Check if power up is done.
if (cond & MMC_CARD_BUSY) 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; storage->has_sector_access = 1;
return 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 3: /* MMC v3.1 - v3.3 */
case 4: /* MMC v4 */ case 4: /* MMC v4 */
storage->cid.manfid = unstuff_bits(raw_cid, 120, 8); 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.oemid = unstuff_bits(raw_cid, 104, 8);
storage->cid.prv = unstuff_bits(raw_cid, 48, 8); storage->cid.prv = unstuff_bits(raw_cid, 48, 8);
storage->cid.serial = unstuff_bits(raw_cid, 16, 32); 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) static void _mmc_storage_parse_csd(sdmmc_storage_t *storage)
{ {
u32 *raw_csd = (u32 *)&(storage->raw_csd); u32 *raw_csd = (u32 *)storage->raw_csd;
storage->csd.mmca_vsn = unstuff_bits(raw_csd, 122, 4); storage->csd.mmca_vsn = unstuff_bits(raw_csd, 122, 4);
storage->csd.structure = unstuff_bits(raw_csd, 126, 2); storage->csd.structure = unstuff_bits(raw_csd, 126, 2);
storage->csd.cmdclass = unstuff_bits(raw_csd, 84, 12); storage->csd.cmdclass = unstuff_bits(raw_csd, 84, 12);
storage->csd.read_blkbits = unstuff_bits(raw_csd, 80, 4); storage->csd.read_blkbits = unstuff_bits(raw_csd, 80, 4);
storage->csd.capacity = (1 + unstuff_bits(raw_csd, 62, 12)) << (unstuff_bits(raw_csd, 47, 3) + 2); storage->csd.capacity = (1 + unstuff_bits(raw_csd, 62, 12)) << (unstuff_bits(raw_csd, 47, 3) + 2);
storage->sec_cnt = storage->csd.capacity;
} }
static void _mmc_storage_parse_ext_csd(sdmmc_storage_t *storage, u8 *buf) static void _mmc_storage_parse_ext_csd(sdmmc_storage_t *storage, u8 *buf)
@@ -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.dev_version = *(u16 *)&buf[EXT_CSD_DEVICE_VERSION];
storage->ext_csd.boot_mult = buf[EXT_CSD_BOOT_MULT]; storage->ext_csd.boot_mult = buf[EXT_CSD_BOOT_MULT];
storage->ext_csd.rpmb_mult = buf[EXT_CSD_RPMB_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 = buf[EXT_CSD_BKOPS_SUPPORT]; //storage->ext_csd.bkops_en = buf[EXT_CSD_BKOPS_EN];
storage->ext_csd.bkops_en = buf[EXT_CSD_BKOPS_EN]; //storage->ext_csd.bkops_status = buf[EXT_CSD_BKOPS_STATUS];
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.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_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->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) 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.num_sectors = 1;
reqbuf.is_write = 0; reqbuf.is_write = 0;
reqbuf.is_multi_block = 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)) if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, &reqbuf, NULL))
return 0; return 0;
@@ -559,19 +575,21 @@ out:
return 1; return 1;
} }
/*
static int _mmc_storage_enable_bkops(sdmmc_storage_t *storage) 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 0;
return _sdmmc_storage_check_status(storage); return _sdmmc_storage_check_status(storage);
} }
*/
int sdmmc_storage_init_mmc(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 bus_width, u32 type) int sdmmc_storage_init_mmc(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 bus_width, u32 type)
{ {
memset(storage, 0, sizeof(sdmmc_storage_t)); memset(storage, 0, sizeof(sdmmc_storage_t));
storage->sdmmc = sdmmc; 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)) if (!sdmmc_init(sdmmc, SDMMC_4, SDMMC_POWER_1_8, SDMMC_BUS_WIDTH_1, SDHCI_TIMING_MMC_ID, SDMMC_POWER_SAVE_DISABLE))
return 0; return 0;
@@ -587,7 +605,7 @@ DPRINTF("[MMC] went to idle state\n");
return 0; return 0;
DPRINTF("[MMC] got op cond\n"); DPRINTF("[MMC] got op cond\n");
if (!_sdmmc_storage_get_cid(storage, storage->raw_cid)) if (!_sdmmc_storage_get_cid(storage))
return 0; return 0;
DPRINTF("[MMC] got cid\n"); DPRINTF("[MMC] got cid\n");
@@ -595,7 +613,7 @@ DPRINTF("[MMC] got cid\n");
return 0; return 0;
DPRINTF("[MMC] set relative addr\n"); DPRINTF("[MMC] set relative addr\n");
if (!_sdmmc_storage_get_csd(storage, storage->raw_csd)) if (!_sdmmc_storage_get_csd(storage))
return 0; return 0;
DPRINTF("[MMC] got csd\n"); DPRINTF("[MMC] got csd\n");
_mmc_storage_parse_csd(storage); _mmc_storage_parse_csd(storage);
@@ -612,13 +630,9 @@ DPRINTF("[MMC] card selected\n");
return 0; return 0;
DPRINTF("[MMC] set blocklen to 512\n"); 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.
//Check system specification version, only version 4.0 and later support below features. if (storage->csd.mmca_vsn < CSD_SPEC_VER_4)
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);
return 1; return 1;
}
if (!_mmc_storage_switch_buswidth(storage, bus_width)) if (!_mmc_storage_switch_buswidth(storage, bus_width))
return 0; return 0;
@@ -628,21 +642,20 @@ DPRINTF("[MMC] switched buswidth\n");
return 0; return 0;
DPRINTF("[MMC] got ext_csd\n"); 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); //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(). if (storage->ext_csd.bkops & 0x1 && !(storage->ext_csd.bkops_en & EXT_CSD_AUTO_BKOPS_MASK))
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))
{ {
_mmc_storage_enable_bkops(storage); _mmc_storage_enable_bkops(storage);
DPRINTF("[MMC] BKOPS enabled\n"); DPRINTF("[MMC] BKOPS enabled\n");
} }
*/
if (!_mmc_storage_enable_highspeed(storage, storage->ext_csd.card_type, type)) if (!_mmc_storage_enable_highspeed(storage, storage->ext_csd.card_type, type))
return 0; 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); 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; u32 tmp;
if (!_sdmmc_storage_execute_cmd_type1_ex(storage, &tmp, MMC_APP_CMD, storage->rca << 16, 0, expected_state, mask)) if (!_sdmmc_storage_execute_cmd_type1_ex(storage, &tmp, MMC_APP_CMD, storage->rca << 16, 0, expected_state, mask))
return 0; 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) 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); 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; sdmmc_cmd_t cmdbuf;
u16 vhd_pattern = SD_VHD_27_36 | 0xAA; u16 vhd_pattern = SD_VHD_27_36 | 0xAA;
sdmmc_init_cmd(&cmdbuf, SD_SEND_IF_COND, vhd_pattern, SDMMC_RSP_TYPE_5, 0); sdmmc_init_cmd(&cmdbuf, SD_SEND_IF_COND, vhd_pattern, SDMMC_RSP_TYPE_5, 0);
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, NULL, NULL)) if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, NULL, NULL))
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; u32 resp = 0;
if (!sdmmc_get_rsp(storage->sdmmc, &resp, 4, SDMMC_RSP_TYPE_5)) sdmmc_get_rsp(storage->sdmmc, &resp, 4, SDMMC_RSP_TYPE_5);
return 2; // Failed.
// Check if VHD was accepted and pattern was properly returned. // Check if VHD was accepted and pattern was properly returned.
if ((resp & 0xFFF) == vhd_pattern) if ((resp & 0xFFF) == vhd_pattern)
return 0; return 1;
// Failed. return 0;
return 2;
} }
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; sdmmc_cmd_t cmdbuf;
// Support for Current > 150mA // 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 // 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 // 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. // This is needed for most cards. Do not set bit7 even if 1.8V is supported.
arg |= SD_OCR_VDD_32_33; arg |= SD_OCR_VDD_32_33;
sdmmc_init_cmd(&cmdbuf, SD_APP_OP_COND, arg, SDMMC_RSP_TYPE_3, 0); 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 0;
return sdmmc_get_rsp(storage->sdmmc, cond, 4, SDMMC_RSP_TYPE_3); return sdmmc_get_rsp(storage->sdmmc, cond, 4, SDMMC_RSP_TYPE_3);
} }
static int _sd_storage_get_op_cond(sdmmc_storage_t *storage, 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; u32 timeout = get_tmr_ms() + 1500;
while (1) while (true)
{ {
u32 cond = 0; 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; 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); DPRINTF("[SD] op cond: %08X, lv: %d\n", cond, bus_uhs_support);
// Check if card is high capacity.
if (cond & SD_OCR_CCS) if (cond & SD_OCR_CCS)
storage->has_sector_access = 1; storage->has_sector_access = 1;
// Check if card supports 1.8V signaling. // Check if card supports 1.8V signaling.
if (cond & SD_ROCR_S18A && bus_uhs_support) if (cond & SD_ROCR_S18A && bus_uhs_support)
{ {
//The low voltage regulator configuration is valid for SDMMC1 only. // Switch to 1.8V signaling.
if (storage->sdmmc->id == SDMMC_1 && if (_sdmmc_storage_execute_cmd_type1(storage, SD_SWITCH_VOLTAGE, 0, 0, R1_STATE_READY))
_sdmmc_storage_execute_cmd_type1(storage, SD_SWITCH_VOLTAGE, 0, 0, R1_STATE_READY))
{ {
if (!sdmmc_enable_low_voltage(storage->sdmmc)) if (!sdmmc_enable_low_voltage(storage->sdmmc))
return 0; return 0;
@@ -776,7 +792,7 @@ static int _sd_storage_get_rca(sdmmc_storage_t *storage)
u32 timeout = get_tmr_ms() + 1500; u32 timeout = get_tmr_ms() + 1500;
while (1) while (true)
{ {
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, NULL, NULL)) if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, NULL, NULL))
break; 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.sda_vsn = unstuff_bits(resp, 56, 4);
storage->scr.bus_widths = unstuff_bits(resp, 48, 4); storage->scr.bus_widths = unstuff_bits(resp, 48, 4);
/* If v2.0 is supported, check if Physical Layer Spec v3.0 is supported */
if (storage->scr.sda_vsn == SCR_SPEC_VER_2) 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); storage->scr.sda_spec3 = unstuff_bits(resp, 47, 1);
if (storage->scr.sda_spec3) if (storage->scr.sda_spec3)
storage->scr.cmds = unstuff_bits(resp, 32, 2); 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.num_sectors = 1;
reqbuf.is_write = 0; reqbuf.is_write = 0;
reqbuf.is_multi_block = 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)) if (!_sd_storage_execute_app_cmd(storage, R1_STATE_TRAN, 0, &cmdbuf, &reqbuf, NULL))
return 0; return 0;
@@ -859,7 +876,7 @@ int _sd_storage_switch_get(sdmmc_storage_t *storage, void *buf)
reqbuf.num_sectors = 1; reqbuf.num_sectors = 1;
reqbuf.is_write = 0; reqbuf.is_write = 0;
reqbuf.is_multi_block = 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)) if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, &reqbuf, NULL))
return 0; 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.num_sectors = 1;
reqbuf.is_write = 0; reqbuf.is_write = 0;
reqbuf.is_multi_block = 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)) if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, &reqbuf, NULL))
return 0; 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); 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; 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) 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_ssr1[4];
u32 raw_ssr2[4]; u32 raw_ssr2[4];
raw_ssr1[3] = *(u32 *)&storage->raw_ssr[12]; memcpy(raw_ssr1, &storage->raw_ssr[0], 16);
raw_ssr1[2] = *(u32 *)&storage->raw_ssr[8]; memcpy(raw_ssr2, &storage->raw_ssr[16], 16);
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];
storage->ssr.bus_width = (unstuff_bits(raw_ssr1, 510 - 384, 2) & SD_BUS_WIDTH_4) ? 4 : 1; storage->ssr.bus_width = (unstuff_bits(raw_ssr1, 510 - 384, 2) & SD_BUS_WIDTH_4) ? 4 : 1;
storage->ssr.protected_size = unstuff_bits(raw_ssr1, 448 - 384, 32); storage->ssr.protected_size = unstuff_bits(raw_ssr1, 448 - 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: case 0:
storage->ssr.speed_class = 0;
break;
case 1: case 1:
storage->ssr.speed_class = 2;
break;
case 2: case 2:
storage->ssr.speed_class = 4;
break;
case 3: case 3:
storage->ssr.speed_class = 6; storage->ssr.speed_class = speed_class << 1;
break; break;
case 4: case 4:
@@ -1144,19 +1146,18 @@ static void _sd_storage_parse_ssr(sdmmc_storage_t *storage)
break; break;
default: default:
storage->ssr.speed_class = unstuff_bits(raw_ssr1, 440 - 384, 8); storage->ssr.speed_class = speed_class;
break; break;
} }
storage->ssr.uhs_grade = unstuff_bits(raw_ssr1, 396 - 384, 4); storage->ssr.uhs_grade = unstuff_bits(raw_ssr1, 396 - 384, 4);
storage->ssr.video_class = unstuff_bits(raw_ssr1, 384 - 384, 8); 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); 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_cmd_t cmdbuf;
sdmmc_init_cmd(&cmdbuf, SD_APP_SD_STATUS, 0, SDMMC_RSP_TYPE_1, 0); 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.num_sectors = 1;
reqbuf.is_write = 0; reqbuf.is_write = 0;
reqbuf.is_multi_block = 0; reqbuf.is_multi_block = 0;
reqbuf.is_auto_cmd12 = 0; reqbuf.is_auto_stop_trn = 0;
if (!(storage->csd.cmdclass & CCC_APP_SPEC)) 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; return 0;
} }
@@ -1180,14 +1181,16 @@ DPRINTF("[SD] ssr: Card lacks mandatory SD Status function\n");
u32 tmp = 0; u32 tmp = 0;
sdmmc_get_rsp(storage->sdmmc, &tmp, 4, SDMMC_RSP_TYPE_1); 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 + 3] = buf[i];
storage->raw_ssr[i + 2] = buf[i + 1]; storage->raw_ssr[i + 2] = buf[i + 1];
storage->raw_ssr[i + 1] = buf[i + 2]; storage->raw_ssr[i + 1] = buf[i + 2];
storage->raw_ssr[i] = buf[i + 3]; storage->raw_ssr[i] = buf[i + 3];
} }
_sd_storage_parse_ssr(storage); _sd_storage_parse_ssr(storage);
//gfx_hexdump(0, storage->raw_ssr, 64); //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); u32 *raw_cid = (u32 *)&(storage->raw_cid);
storage->cid.manfid = unstuff_bits(raw_cid, 120, 8); storage->cid.manfid = unstuff_bits(raw_cid, 120, 8);
storage->cid.oemid = unstuff_bits(raw_cid, 104, 16); storage->cid.oemid = unstuff_bits(raw_cid, 104, 16);
storage->cid.prod_name[0] = unstuff_bits(raw_cid, 96, 8); 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[1] = unstuff_bits(raw_cid, 88, 8);
storage->cid.prod_name[2] = unstuff_bits(raw_cid, 80, 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[3] = unstuff_bits(raw_cid, 72, 8);
storage->cid.prod_name[4] = unstuff_bits(raw_cid, 64, 8); storage->cid.prod_name[4] = unstuff_bits(raw_cid, 64, 8);
storage->cid.hwrev = unstuff_bits(raw_cid, 60, 4); storage->cid.hwrev = unstuff_bits(raw_cid, 60, 4);
storage->cid.fwrev = unstuff_bits(raw_cid, 56, 4); storage->cid.fwrev = unstuff_bits(raw_cid, 56, 4);
storage->cid.serial = unstuff_bits(raw_cid, 24, 32); 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.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) 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: case 0:
storage->csd.capacity = (1 + unstuff_bits(raw_csd, 62, 12)) << (unstuff_bits(raw_csd, 47, 3) + 2); storage->csd.capacity = (1 + unstuff_bits(raw_csd, 62, 12)) << (unstuff_bits(raw_csd, 47, 3) + 2);
storage->csd.capacity <<= unstuff_bits(raw_csd, 80, 4) - 9; // Convert native block size to LBA 512B.
break; break;
case 1: 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.capacity = storage->csd.c_size << 10;
storage->csd.read_blkbits = 9; storage->csd.read_blkbits = 9;
break; 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) 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 sdmmc_storage_init_sd(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 bus_width, u32 type)
{ {
int is_version_1 = 0; u32 tmp = 0;
u8 *buf = (u8 *)SDMMC_UPPER_BUFFER; 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); DPRINTF("[SD] init: bus: %d, type: %d\n", bus_width, type);
@@ -1282,18 +1294,15 @@ DPRINTF("[SD] after init\n");
return 0; return 0;
DPRINTF("[SD] went to idle state\n"); DPRINTF("[SD] went to idle state\n");
is_version_1 = _sd_storage_send_if_cond(storage); if (!_sd_storage_send_if_cond(storage, &is_sdsc))
if (is_version_1 == 2) // Failed.
return 0; return 0;
DPRINTF("[SD] after send if cond\n"); 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_sdsc, bus_uhs_support))
if (!_sd_storage_get_op_cond(storage, is_version_1, bus_uhs_support))
return 0; return 0;
DPRINTF("[SD] got op cond\n"); DPRINTF("[SD] got op cond\n");
if (!_sdmmc_storage_get_cid(storage, storage->raw_cid)) if (!_sdmmc_storage_get_cid(storage))
return 0; return 0;
DPRINTF("[SD] got cid\n"); DPRINTF("[SD] got cid\n");
_sd_storage_parse_cid(storage); _sd_storage_parse_cid(storage);
@@ -1302,30 +1311,16 @@ DPRINTF("[SD] got cid\n");
return 0; return 0;
DPRINTF("[SD] got rca (= %04X)\n", storage->rca); 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; return 0;
DPRINTF("[SD] got csd\n"); DPRINTF("[SD] got csd\n");
//Parse CSD.
_sd_storage_parse_csd(storage); _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 (!storage->is_low_voltage)
{ {
if (!sdmmc_setup_clock(storage->sdmmc, SDHCI_TIMING_SD_DS12)) if (!sdmmc_setup_clock(storage->sdmmc, SDHCI_TIMING_SD_DS12))
return 0; return 0;
DPRINTF("[SD] after setup clock\n"); DPRINTF("[SD] after setup default clock\n");
} }
if (!_sdmmc_storage_select_card(storage)) if (!_sdmmc_storage_select_card(storage))
@@ -1336,19 +1331,17 @@ DPRINTF("[SD] card selected\n");
return 0; return 0;
DPRINTF("[SD] set blocklen to 512\n"); 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)) if (!_sd_storage_execute_app_cmd_type1(storage, &tmp, SD_APP_SET_CLR_CARD_DETECT, 0, 0, R1_STATE_TRAN))
return 0; return 0;
DPRINTF("[SD] cleared card detect\n"); DPRINTF("[SD] cleared card detect\n");
if (!_sd_storage_get_scr(storage, buf)) if (!_sd_storage_get_scr(storage, buf))
return 0; return 0;
//gfx_hexdump(0, storage->raw_scr, 8);
DPRINTF("[SD] got scr\n"); DPRINTF("[SD] got scr\n");
// Check if card supports a wider bus and if it's not SD Version 1.X // 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 & 4) && (storage->scr.sda_vsn & 0xF)) 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)) if (!_sd_storage_execute_app_cmd_type1(storage, &tmp, SD_APP_SET_BUS_WIDTH, SD_BUS_WIDTH_4, 0, R1_STATE_TRAN))
return 0; return 0;
@@ -1370,7 +1363,7 @@ DPRINTF("[SD] enabled UHS\n");
sdmmc_card_clock_powersave(sdmmc, SDMMC_POWER_SAVE_ENABLE); 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)) if (!_sd_storage_enable_hs_high_volt(storage, buf))
return 0; return 0;
@@ -1389,7 +1382,7 @@ DPRINTF("[SD] enabled HS\n");
} }
// Parse additional card info from sd status. // 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"); 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) int _gc_storage_custom_cmd(sdmmc_storage_t *storage, void *buf)
{ {
u32 resp; u32 resp;
sdmmc_cmd_t cmdbuf; 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; sdmmc_req_t reqbuf;
reqbuf.buf = buf; reqbuf.buf = buf;
@@ -1415,7 +1408,7 @@ int _gc_storage_custom_cmd(sdmmc_storage_t *storage, void *buf)
reqbuf.num_sectors = 1; reqbuf.num_sectors = 1;
reqbuf.is_write = 1; reqbuf.is_write = 1;
reqbuf.is_multi_block = 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)) if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, &reqbuf, NULL))
{ {

View File

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

View File

@@ -1,6 +1,6 @@
/* /*
* Copyright (c) 2018 naehrwert * 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 * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@@ -934,12 +934,20 @@ static int _sdmmc_config_dma(sdmmc_t *sdmmc, u32 *blkcnt_out, sdmmc_req_t *req)
*blkcnt_out = blkcnt; *blkcnt_out = blkcnt;
u32 trnmode = SDHCI_TRNS_DMA; u32 trnmode = SDHCI_TRNS_DMA;
// Set mulitblock request.
if (req->is_multi_block) if (req->is_multi_block)
trnmode = SDHCI_TRNS_MULTI | SDHCI_TRNS_BLK_CNT_EN | SDHCI_TRNS_DMA; trnmode = SDHCI_TRNS_MULTI | SDHCI_TRNS_BLK_CNT_EN | SDHCI_TRNS_DMA;
// Set request direction.
if (!req->is_write) if (!req->is_write)
trnmode |= SDHCI_TRNS_READ; 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; sdmmc->regs->trnmod = trnmode;
@@ -1070,7 +1078,7 @@ DPRINTF("rsp(%d): %08X, %08X, %08X, %08X\n", result,
if (blkcnt_out) if (blkcnt_out)
*blkcnt_out = blkcnt; *blkcnt_out = blkcnt;
if (req->is_auto_cmd12) if (req->is_auto_stop_trn)
sdmmc->rsp3 = sdmmc->regs->rspreg3; sdmmc->rsp3 = sdmmc->regs->rspreg3;
} }

View File

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

View File

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

View File

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

View File

@@ -1,7 +1,7 @@
/* /*
* Copyright (c) 2018 naehrwert * Copyright (c) 2018 naehrwert
* Copyright (c) 2018 Rajko Stojadinovic * 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 * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@@ -27,6 +27,7 @@
#include <libs/fatfs/ff.h> #include <libs/fatfs/ff.h>
#include <mem/heap.h> #include <mem/heap.h>
#include <sec/se.h> #include <sec/se.h>
#include <sec/se_t210.h>
#include "../storage/nx_emmc.h" #include "../storage/nx_emmc.h"
#include <storage/nx_sd.h> #include <storage/nx_sd.h>
#include <storage/sdmmc.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(hashEm, bufEm, num << 9);
se_calc_sha256_oneshot(hashSd, bufSd, 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) if (res)
{ {

View File

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

View File

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

View File

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

View File

@@ -1,6 +1,6 @@
/* /*
* Copyright (c) 2018 naehrwert * Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2020 CTCaer * Copyright (c) 2018-2021 CTCaer
* Copyright (c) 2018 M4xw * Copyright (c) 2018 M4xw
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
@@ -63,7 +63,7 @@ void gfx_con_setpos(u32 x, u32 y);
void gfx_putc(char c); void gfx_putc(char c);
void gfx_puts(char *s); void gfx_puts(char *s);
void gfx_printf(const char *fmt, ...); 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_set_pixel(u32 x, u32 y, u32 color);
void gfx_line(int x0, int y0, int x1, int y1, 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 naehrwert
* Copyright (c) 2018 st4rk * Copyright (c) 2018 st4rk
* Copyright (c) 2018 Ced2911 * Copyright (c) 2018 Ced2911
* Copyright (c) 2018-2020 CTCaer * Copyright (c) 2018-2021 CTCaer
* Copyright (c) 2018 balika011 * Copyright (c) 2018 balika011
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
@@ -75,7 +75,29 @@ typedef struct _secmon_mailbox_t
u32 out; u32 out;
} secmon_mailbox_t; } 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. { 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. { 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. { 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. { 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 }; { 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 }; { 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 }; { 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 }; { 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. { 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. { 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. { 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. { 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 }; { 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 }; { 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 }; { 0xFB, 0x8B, 0x6A, 0x9C, 0x79, 0x00, 0xC8, 0x49, 0xEF, 0xD2, 0x4D, 0x85, 0x4D, 0x30, 0xA0, 0xC7 };
static void _hos_crit_error(const char *text) static void _hos_crit_error(const char *text)
@@ -124,30 +146,33 @@ static void _se_lock(bool lock_se)
{ {
if (lock_se) if (lock_se)
{ {
// Disable aes key read.
for (u32 i = 0; i < 16; i++) 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); 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++) for (u32 i = 0; i < 2; i++)
se_rsa_acc_ctrl(i, SE_RSA_KEY_TBL_DIS_KEYREAD_FLAG); 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_TZRAM_SECURITY_REG) = 0; // Make SE TZRAM secure only.
SE(SE_RSA_KEYTABLE_ACCESS_LOCK_OFFSET) = 0; // Make all RSA access regs secure only. SE(SE_CRYPTO_SECURITY_PERKEY_REG) = 0; // Make all AES keys access secure only.
SE(SE_SECURITY_0) &= 0xFFFFFFFB; // Make access lock regs 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)); memset((void *)IPATCH_BASE, 0, 14 * sizeof(u32));
SB(SB_CSR) = SB_CSR_PIROM_DISABLE; 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. // 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(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_CRYPTO_SECURITY_PERKEY_REG) = %08X\n", SE(SE_CRYPTO_SECURITY_PERKEY_REG));
gfx_printf("SE(SE_RSA_KEYTABLE_ACCESS_LOCK_OFFSET) = %08X\n", SE(SE_RSA_KEYTABLE_ACCESS_LOCK_OFFSET)); gfx_printf("SE(SE_RSA_SECURITY_PERKEY_REG) = %08X\n", SE(SE_RSA_SECURITY_PERKEY_REG));
for(u32 i = 0; i < 16; i++) 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'); gfx_putc('\n');
for(u32 i = 0; i < 2; i++) 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_putc('\n');
gfx_hexdump(SE_BASE, (void *)SE_BASE, 0x400);*/ 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. // 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]; 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) if (update_eks)
{ {
// Read EKS blob. // Read EKS blob.
@@ -256,8 +283,8 @@ void hos_eks_save(u32 kb)
} }
// Get keys. // Get keys.
u8 *keys = (u8 *)calloc(0x1000, 1); u8 *keys = (u8 *)calloc(0x2000, 1);
se_get_aes_keys(keys + 0x800, keys, 0x10); se_get_aes_keys(keys + 0x1000, keys, SE_KEY_128_SIZE);
// Set magic and personalized info. // Set magic and personalized info.
h_cfg.eks->magic = HOS_EKS_MAGIC; 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); h_cfg.eks->lot0 = FUSE(FUSE_OPT_LOT_CODE_0);
// Copy new keys. // Copy new keys.
memcpy(h_cfg.eks->dkg, keys + 10 * 0x10, 0x10); memcpy(h_cfg.eks->dkg, keys + 10 * SE_KEY_128_SIZE, SE_KEY_128_SIZE);
memcpy(h_cfg.eks->dkk, keys + 15 * 0x10, 0x10); memcpy(h_cfg.eks->dkk, keys + 15 * SE_KEY_128_SIZE, SE_KEY_128_SIZE);
if (!h_cfg.aes_slots_new) 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].mkk, keys + 12 * SE_KEY_128_SIZE, SE_KEY_128_SIZE);
memcpy(h_cfg.eks->keys[key_idx].fdk, keys + 13 * 0x10, 0x10); memcpy(h_cfg.eks->keys[key_idx].fdk, keys + 13 * SE_KEY_128_SIZE, SE_KEY_128_SIZE);
} }
else // New sept slots. else // New sept slots.
{ {
memcpy(h_cfg.eks->keys[key_idx].mkk, keys + 13 * 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 * 0x10, 0x10); memcpy(h_cfg.eks->keys[key_idx].fdk, keys + 12 * SE_KEY_128_SIZE, SE_KEY_128_SIZE);
} }
// Encrypt EKS blob. // Encrypt EKS blob.
@@ -288,7 +315,6 @@ void hos_eks_save(u32 kb)
memcpy(mbr + 0x80, eks, sizeof(hos_eks_mbr_t)); memcpy(mbr + 0x80, eks, sizeof(hos_eks_mbr_t));
hos_eks_rw_try(mbr, true); hos_eks_rw_try(mbr, true);
free(eks); free(eks);
free(keys); free(keys);
out: out:
@@ -354,10 +380,11 @@ int hos_keygen_t210b01(u32 kb)
return 1; 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; u32 retries = 0;
tsec_keys_t tsec_keys;
kb_t *kb_data = (kb_t *)keyblob;
if (kb > KB_FIRMWARE_VERSION_MAX) if (kb > KB_FIRMWARE_VERSION_MAX)
return 0; 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. // Get TSEC key.
if (kb <= KB_FIRMWARE_VERSION_620) 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++; retries++;
// We rely on racing conditions, make sure we cover even the unluckiest cases. // We rely on racing conditions, make sure we cover even the unluckiest cases.
@@ -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) if (h_cfg.eks && h_cfg.eks->enabled[key_idx] >= kb)
{ {
// Set Device keygen key to slot 10. // 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. // 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) if (!h_cfg.aes_slots_new)
{ {
// Set Master key to slot 12. // 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. // 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. // 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); 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. else // New exosphere.
{ {
// Set Master key to slot 13. // 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. // 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. // 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); 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) else if (kb == KB_FIRMWARE_VERSION_620)
{ {
// Set TSEC key. // 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. // 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) if (!(emu_cfg.enabled && !h_cfg.emummc_force_disable) && hos_ctxt->stock)
{ {
// Package2 key. // 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_620);
se_aes_unwrap_key(8, 8, master_keyseed_retail); se_aes_unwrap_key(8, 8, master_keyseed_retail);
se_aes_unwrap_key(8, 8, package2_keyseed); 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 else
{ {
// Decrypt keyblob and set keyslots // Decrypt keyblob and set keyslots
se_aes_crypt_block_ecb(12, 0, tmp + 0x20, keyblob_keyseeds[0]); se_aes_crypt_block_ecb(12, 0, tsec_keys.tmp, keyblob_keyseeds[0]);
se_aes_unwrap_key(15, 14, tmp + 0x20); se_aes_unwrap_key(15, 14, tsec_keys.tmp);
se_aes_unwrap_key(10, 15, console_keyseed_4xx_5xx); se_aes_unwrap_key(10, 15, console_keyseed_4xx_5xx);
se_aes_unwrap_key(15, 15, console_keyseed); 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); 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. // 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. // Derive keyblob keys from TSEC+SBK.
se_aes_crypt_block_ecb(13, 0, tmp, keyblob_keyseeds[0]); se_aes_crypt_block_ecb(13, 0, tsec_keys.tsec, keyblob_keyseeds[0]);
se_aes_unwrap_key(15, 14, tmp); se_aes_unwrap_key(15, 14, tsec_keys.tsec);
se_aes_crypt_block_ecb(13, 0, tmp, keyblob_keyseeds[kb]); se_aes_crypt_block_ecb(13, 0, tsec_keys.tsec, keyblob_keyseeds[kb]);
se_aes_unwrap_key(13, 14, tmp); se_aes_unwrap_key(13, 14, tsec_keys.tsec);
// Clear SBK. // Clear SBK.
se_aes_key_clear(14); se_aes_key_clear(14);
//TODO: verify keyblob CMAC. /*
//se_aes_unwrap_key(11, 13, cmac_keyseed); // Verify keyblob CMAC.
//se_aes_cmac(tmp, 0x10, 11, keyblob + 0x10, 0xA0); u8 cmac[SE_KEY_128_SIZE];
//if (!memcmp(keyblob, tmp, 0x10)) se_aes_unwrap_key(11, 13, cmac_keyseed);
// return 0; 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); se_aes_unwrap_key(11, 13, cmac_keyseed);
// Decrypt keyblob and set keyslots. // Decrypt keyblob and set keyslots.
se_aes_crypt_ctr(13, keyblob + 0x20, 0x90, keyblob + 0x20, 0x90, keyblob + 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, keyblob + 0x20 + 0x80, 0x10); // Package1 key. se_aes_key_set(11, kb_data->keys.package1_key, SE_KEY_128_SIZE);
se_aes_key_set(12, keyblob + 0x20, 0x10); se_aes_key_set(12, kb_data->keys.master_keyseed, SE_KEY_128_SIZE);
se_aes_key_set(13, keyblob + 0x20, 0x10); 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) if (!h_cfg.aes_slots_new)
{ {
@@ -566,8 +596,8 @@ static int _read_emmc_pkg1(launch_ctxt_t *ctxt)
try_load: try_load:
// Read package1. // Read package1.
emummc_storage_set_mmc_partition(&emmc_storage, EMMC_BOOT0); emummc_storage_set_mmc_partition(EMMC_BOOT0);
emummc_storage_read(&emmc_storage, bootloader_offset / NX_EMMC_BLOCKSIZE, BOOTLOADER_SIZE / NX_EMMC_BLOCKSIZE, ctxt->pkg1); emummc_storage_read(bootloader_offset / NX_EMMC_BLOCKSIZE, BOOTLOADER_SIZE / NX_EMMC_BLOCKSIZE, ctxt->pkg1);
ctxt->pkg1_id = pkg1_identify(ctxt->pkg1 + pk1_offset); ctxt->pkg1_id = pkg1_identify(ctxt->pkg1 + pk1_offset);
if (!ctxt->pkg1_id) if (!ctxt->pkg1_id)
@@ -590,7 +620,7 @@ try_load:
// Read the correct keyblob. // Read the correct keyblob.
ctxt->keyblob = (u8 *)calloc(NX_EMMC_BLOCKSIZE, 1); 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; return 1;
} }
@@ -599,7 +629,7 @@ static u8 *_read_emmc_pkg2(launch_ctxt_t *ctxt)
{ {
u8 *bctBuf = NULL; u8 *bctBuf = NULL;
emummc_storage_set_mmc_partition(&emmc_storage, EMMC_GPP); emummc_storage_set_mmc_partition(EMMC_GPP);
// Parse eMMC GPT. // Parse eMMC GPT.
LIST_INIT(gpt); LIST_INIT(gpt);
@@ -710,17 +740,21 @@ int hos_launch(ini_sec_t *cfg)
gfx_puts("Initializing...\n\n"); gfx_puts("Initializing...\n\n");
// Initialize eMMC/emuMMC. // Initialize eMMC/emuMMC.
int res = emummc_storage_init_mmc(&emmc_storage, &emmc_sdmmc); int res = emummc_storage_init_mmc();
if (res) if (res)
{ {
if (res == 2) if (res == 2)
_hos_crit_error("Failed to init eMMC"); _hos_crit_error("Failed to init eMMC.");
else else
_hos_crit_error("Failed to init emuMMC"); _hos_crit_error("Failed to init emuMMC.");
goto error; 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. // Read package1 and the correct keyblob.
if (!_read_emmc_pkg1(&ctxt)) if (!_read_emmc_pkg1(&ctxt))
goto error; goto error;
@@ -843,7 +877,17 @@ int hos_launch(ini_sec_t *cfg)
} }
// Configure and manage Warmboot binary. // 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. // Replace 'warmboot.bin' if requested.
if (ctxt.warmboot) if (ctxt.warmboot)
@@ -1012,16 +1056,16 @@ int hos_launch(ini_sec_t *cfg)
case KB_FIRMWARE_VERSION_100_200: case KB_FIRMWARE_VERSION_100_200:
case KB_FIRMWARE_VERSION_300: case KB_FIRMWARE_VERSION_300:
case KB_FIRMWARE_VERSION_301: 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(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_TBL_DIS_KEY_LOCK_FLAG); se_key_acc_ctrl(13, SE_KEY_TBL_DIS_KEY_ACCESS_FLAG | SE_KEY_LOCK_FLAG);
bootStateDramPkg2 = 2; bootStateDramPkg2 = 2;
bootStatePkg2Continue = 3; bootStatePkg2Continue = 3;
break; break;
case KB_FIRMWARE_VERSION_400: case KB_FIRMWARE_VERSION_400:
case KB_FIRMWARE_VERSION_500: case KB_FIRMWARE_VERSION_500:
case KB_FIRMWARE_VERSION_600: 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(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_TBL_DIS_KEY_LOCK_FLAG); se_key_acc_ctrl(15, SE_KEY_TBL_DIS_KEY_ACCESS_FLAG | SE_KEY_LOCK_FLAG);
default: default:
bootStateDramPkg2 = 2; bootStateDramPkg2 = 2;
bootStatePkg2Continue = 4; bootStatePkg2Continue = 4;

View File

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

View File

@@ -1,7 +1,7 @@
/* /*
* Copyright (c) 2018 naehrwert * Copyright (c) 2018 naehrwert
* Copyright (c) 2018 st4rk * Copyright (c) 2018 st4rk
* Copyright (c) 2018-2020 CTCaer * Copyright (c) 2018-2021 CTCaer
* Copyright (c) 2018 balika011 * Copyright (c) 2018 balika011
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
@@ -331,10 +331,11 @@ static void _warmboot_filename(char *out, u32 fuses)
strcat(out, ".bin"); 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; launch_ctxt_t *ctxt = (launch_ctxt_t *)hos_ctxt;
u32 kb = ctxt->pkg1_id->kb; u32 kb = ctxt->pkg1_id->kb;
int res = 1;
// Set warmboot address in PMC if required. // Set warmboot address in PMC if required.
if (kb <= KB_FIRMWARE_VERSION_301) if (kb <= KB_FIRMWARE_VERSION_301)
@@ -347,7 +348,7 @@ void pkg1_warmboot_config(void *hos_ctxt, u32 warmboot_base)
u32 fuses_fw = ctxt->pkg1_id->fuses; u32 fuses_fw = ctxt->pkg1_id->fuses;
u8 burnt_fuses = fuse_count_burnt(fuse_read_odm(7)); 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) if (!ctxt->warmboot)
{ {
char path[128]; char path[128];
@@ -357,7 +358,7 @@ void pkg1_warmboot_config(void *hos_ctxt, u32 warmboot_base)
if (f_stat(path, NULL)) if (f_stat(path, NULL))
sd_save_to_file((void *)warmboot_base, ctxt->warmboot_size, path); 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) if (burnt_fuses > fuses_fw)
{ {
u32 tmp_fuses = burnt_fuses; u32 tmp_fuses = burnt_fuses;
@@ -374,6 +375,10 @@ void pkg1_warmboot_config(void *hos_ctxt, u32 warmboot_base)
break; break;
tmp_fuses++; tmp_fuses++;
} }
// Check if proper warmboot firmware was found.
if (!ctxt->warmboot)
res = 0;
} }
else // Replace burnt fuses with higher count. else // Replace burnt fuses with higher count.
burnt_fuses = fuses_fw; burnt_fuses = fuses_fw;
@@ -406,4 +411,6 @@ void pkg1_warmboot_config(void *hos_ctxt, u32 warmboot_base)
else if (kb == KB_FIRMWARE_VERSION_301) else if (kb == KB_FIRMWARE_VERSION_301)
PMC(APBDEV_PMC_SECURE_SCRATCH32) = 0x104; // Warmboot 3.0.1/.2 PA address id. 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); 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_secmon_patch(void *hos_ctxt, u32 secmon_base, bool t210b01);
void pkg1_warmboot_patch(void *hos_ctxt); 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 #endif

View File

@@ -1,6 +1,6 @@
/* /*
* Copyright (c) 2018 naehrwert * Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2020 CTCaer * Copyright (c) 2018-2021 CTCaer
* Copyright (c) 2018 Atmosphère-NX * Copyright (c) 2018 Atmosphère-NX
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
@@ -27,6 +27,7 @@
#include <libs/fatfs/ff.h> #include <libs/fatfs/ff.h>
#include <mem/heap.h> #include <mem/heap.h>
#include <sec/se.h> #include <sec/se.h>
#include <sec/se_t210.h>
#include "../storage/emummc.h" #include "../storage/emummc.h"
#include <storage/nx_sd.h> #include <storage/nx_sd.h>
#include <utils/aarch64_util.h> #include <utils/aarch64_util.h>
@@ -1335,7 +1336,7 @@ const char* pkg2_patch_kips(link_t *info, char* patchNames)
return NULL; 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) // 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 }, { 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) 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. // 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. // Set and unwrap pkg2 key.
se_aes_key_clear(9); 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); se_aes_unwrap_key(9, 9, package2_keyseed);
// Decrypt header. // Decrypt header.
@@ -1383,9 +1384,9 @@ pkg2_hdr_t *pkg2_decrypt(void *data, u8 kb)
// Decrypt older pkg2 via new mkeys. // Decrypt older pkg2 via new mkeys.
if ((kb >= KB_FIRMWARE_VERSION_810) && (kb < KB_FIRMWARE_VERSION_MAX)) 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 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_idx = mkey_seeds_cnt; // Real index + 1.
u8 mkey_seeds_min_idx = mkey_seeds_cnt - (KB_FIRMWARE_VERSION_MAX - kb); 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. // Set current mkey in order to decrypt a lower mkey.
mkey_seeds_idx--; mkey_seeds_idx--;
se_aes_key_clear(9); 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. 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]) if (!hdr->sec_size[i])
continue; 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); //gfx_hexdump((u32)pdata, pdata, 0x100);
pdata += hdr->sec_size[i]; 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_size[PKG2_SEC_INI1] = ini1_size;
hdr->sec_off[PKG2_SEC_INI1] = 0x14080000; 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 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_off[PKG2_SEC_KERNEL] = 0x60000;
} }
hdr->sec_size[PKG2_SEC_KERNEL] = kernel_size; 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; pdst += kernel_size;
DPRINTF("kernel encrypted\n"); DPRINTF("kernel encrypted\n");
@@ -1549,7 +1550,7 @@ DPRINTF("INI1 encrypted\n");
*(u32 *)hdr->ctr = 0x100 + sizeof(pkg2_hdr_t) + kernel_size + ini1_size; *(u32 *)hdr->ctr = 0x100 + sizeof(pkg2_hdr_t) + kernel_size + ini1_size;
hdr->ctr[4] = key_ver; hdr->ctr[4] = key_ver;
se_aes_crypt_ctr(pkg2_keyslot, hdr, sizeof(pkg2_hdr_t), hdr, sizeof(pkg2_hdr_t), hdr); se_aes_crypt_ctr(pkg2_keyslot, hdr, sizeof(pkg2_hdr_t), hdr, sizeof(pkg2_hdr_t), hdr);
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; *(u32 *)hdr->ctr = 0x100 + sizeof(pkg2_hdr_t) + kernel_size + ini1_size;
hdr->ctr[4] = key_ver; 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 * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@@ -33,6 +33,7 @@
#include <storage/sdmmc.h> #include <storage/sdmmc.h>
#include <utils/btn.h> #include <utils/btn.h>
#include <utils/types.h> #include <utils/types.h>
#include <utils/util.h>
#include <gfx_utils.h> #include <gfx_utils.h>
@@ -55,6 +56,7 @@ u8 warmboot_reboot[] = {
}; };
#define SEPT_PRI_ADDR 0x4003F000 #define SEPT_PRI_ADDR 0x4003F000
#define SEPT_PRI_ENTRY 0x40010340
#define SEPT_PK1T_ADDR 0xC0400000 #define SEPT_PK1T_ADDR 0xC0400000
#define SEPT_TCSZ_ADDR (SEPT_PK1T_ADDR - 0x4) #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); u8 *pkg1 = (u8 *)calloc(1, 0x40000);
sdmmc_storage_t storage; int res = emummc_storage_init_mmc();
sdmmc_t sdmmc;
int res = emummc_storage_init_mmc(&storage, &sdmmc);
if (res) if (res)
{ {
if (res == 2) if (res == 2)
EPRINTF("Failed to init eMMC"); EPRINTF("Failed to init eMMC.");
else else
EPRINTF("Failed to init emuMMC"); EPRINTF("Failed to init emuMMC.");
goto out_free; goto out_free;
} }
emummc_storage_set_mmc_partition(&storage, EMMC_BOOT0); emummc_storage_set_mmc_partition(EMMC_BOOT0);
// Read package1. // 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); const pkg1_id_t *pkg1_id = pkg1_identify(pkg1);
if (!pkg1_id) if (!pkg1_id)
{ {
@@ -129,13 +129,28 @@ void check_sept(ini_sec_t *cfg_sec)
goto out_free; 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); reboot_to_sept((u8 *)pkg1 + pkg1_id->tsec_off, pkg1_id->kb, cfg_sec);
} }
out_free: out_free:
free(pkg1); 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) 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> #include <utils/types.h>
void check_sept(ini_sec_t *cfg_sec); 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 #endif

View File

@@ -41,16 +41,25 @@
#define FF_USE_MKFS 0 #define FF_USE_MKFS 0
/* This option switches f_mkfs() function. (0:Disable or 1:Enable) */ /* 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 #define FF_USE_FASTSEEK 0
/* This option switches fast seek function. (0:Disable or 1:Enable) */ /* This option switches fast seek function. (0:Disable or 1:Enable) */
#define FF_FASTFS 0 #define FF_FASTFS 0
#if FF_FASTFS #if FF_FASTFS
#undef FF_USE_FASTSEEK #undef FF_USE_FASTSEEK
#define FF_USE_FASTSEEK 1 #define FF_USE_FASTSEEK 1
#endif #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 #define FF_USE_EXPAND 0
@@ -185,6 +194,7 @@
/ not defined, a user defined volume string table needs to be defined as: / not defined, a user defined volume string table needs to be defined as:
/ /
/ const char* VolumeStr[FF_VOLUMES] = {"ram","flash","sd","usb",... / 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_FS_NORTC 1
#define FF_NORTC_MON 1 #define FF_NORTC_MON 1
#define FF_NORTC_MDAY 1 #define FF_NORTC_MDAY 1
#define FF_NORTC_YEAR 2020 #define FF_NORTC_YEAR 2021
/* The option FF_FS_NORTC switches timestamp function. If the system does not have /* The option FF_FS_NORTC switches timestamp function. If the system does not have
/ any RTC function or valid timestamp is not needed, set FF_FS_NORTC = 1 to disable / any RTC function or valid timestamp is not needed, set FF_FS_NORTC = 1 to disable
/ the timestamp function. Every object modified by FatFs will have a fixed timestamp / the timestamp function. Every object modified by FatFs will have a fixed timestamp

View File

@@ -1,7 +1,7 @@
/* /*
* Copyright (c) 2018 naehrwert * 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 * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@@ -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) 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]; char emmcSN[9];
bool init_done = false; 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 (!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); memcpy(emmcSN, "00000000", 9);
else else
{ {
init_done = true; init_done = true;
itoa(storage2.cid.serial, emmcSN, 16); itoa(emmc_storage.cid.serial, emmcSN, 16);
} }
} }
else 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); memcpy(path + strlen(path), filename, filename_len + 1);
if (init_done) if (init_done)
sdmmc_storage_end(&storage2); sdmmc_storage_end(&emmc_storage);
} }
void check_power_off_from_hos() void check_power_off_from_hos()
@@ -644,12 +642,8 @@ void launch_firmware()
if (!cfg_sec) if (!cfg_sec)
{ {
gfx_puts("\nUsing default launch configuration...\n"); gfx_printf("\nPress any key...\n");
gfx_puts("\nPress POWER to Continue.\nPress VOL to go to the menu."); goto out;
u32 btn = btn_wait();
if (!(btn & BTN_POWER))
goto out;
} }
if (payload_path) if (payload_path)
@@ -720,15 +714,11 @@ void nyx_load_run()
nyx_str->cfg = 0; nyx_str->cfg = 0;
if (b_cfg.extra_cfg) 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); b_cfg.extra_cfg &= ~(EXTRA_CFG_NYX_SEPT);
nyx_str->cfg |= NYX_CFG_DUMP; nyx_str->cfg |= NYX_CFG_SEPT;
} nyx_str->cfg |= b_cfg.sept << 24;
if (b_cfg.extra_cfg & EXTRA_CFG_NYX_BIS)
{
b_cfg.extra_cfg &= ~(EXTRA_CFG_NYX_BIS);
nyx_str->cfg |= NYX_CFG_BIS;
} }
if (b_cfg.extra_cfg & EXTRA_CFG_NYX_UMS) if (b_cfg.extra_cfg & EXTRA_CFG_NYX_UMS)
{ {
@@ -808,7 +798,7 @@ static void _bootloader_corruption_protect()
static void _auto_launch_firmware() 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) if (!h_cfg.sept_run)
EMC(EMC_SCRATCH0) |= EMC_HEKA_UPD; EMC(EMC_SCRATCH0) |= EMC_HEKA_UPD;
@@ -1120,18 +1110,15 @@ out:
static void _patched_rcm_protection() 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) if (!h_cfg.rcm_patched || hw_get_chip_id() == GP_HIDREV_MAJOR_T210B01)
return; return;
// Check if AutoRCM is enabled and protect from a permanent brick. // 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; return;
u8 *buf = (u8 *)malloc(0x200); u8 *buf = (u8 *)malloc(0x200);
sdmmc_storage_set_mmc_partition(&storage, EMMC_BOOT0); sdmmc_storage_set_mmc_partition(&emmc_storage, EMMC_BOOT0);
u32 sector; u32 sector;
u8 corr_mod0, mod1; u8 corr_mod0, mod1;
@@ -1143,7 +1130,7 @@ static void _patched_rcm_protection()
for (u32 i = 0; i < 4; i++) for (u32 i = 0; i < 4; i++)
{ {
sector = 1 + (32 * i); // 0x4000 bct + 0x200 offset. 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. // Check if 2nd byte of modulus is correct.
if (buf[0x11] != mod1) if (buf[0x11] != mod1)
@@ -1154,12 +1141,12 @@ static void _patched_rcm_protection()
{ {
buf[0x10] = corr_mod0; buf[0x10] = corr_mod0;
sdmmc_storage_write(&storage, sector, 1, buf); sdmmc_storage_write(&emmc_storage, sector, 1, buf);
} }
} }
free(buf); free(buf);
sdmmc_storage_end(&storage); sdmmc_storage_end(&emmc_storage);
} }
#define EXCP_EN_ADDR 0x4003FFFC #define EXCP_EN_ADDR 0x4003FFFC
@@ -1513,15 +1500,15 @@ ment_t ment_top[] = {
MDEF_MENU("Console info", &menu_cinfo), MDEF_MENU("Console info", &menu_cinfo),
MDEF_CAPTION("---------------", 0xFF444444), MDEF_CAPTION("---------------", 0xFF444444),
MDEF_HANDLER("Reload", ipl_reload), MDEF_HANDLER("Reload", ipl_reload),
MDEF_HANDLER_EX("Reboot (Normal)", &STATE_REBOOT_BYPASS_FUSES, 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("Reboot (RCM)", &STATE_REBOOT_RCM, power_set_state_ex),
MDEF_HANDLER_EX("Power off", &STATE_POWER_OFF, power_set_state_ex), MDEF_HANDLER_EX("Power off", &STATE_POWER_OFF, power_set_state_ex),
MDEF_CAPTION("---------------", 0xFF444444), MDEF_CAPTION("---------------", 0xFF444444),
MDEF_HANDLER("About", _about), MDEF_HANDLER("About", _about),
MDEF_END() MDEF_END()
}; };
menu_t menu_top = { ment_top, "hekate - CTCaer mod v5.5.3", 0, 0 }; menu_t menu_top = { ment_top, "hekate - CTCaer mod v5.5.4", 0, 0 };
extern void pivot_stack(u32 stack_top); 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 * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@@ -131,13 +131,13 @@ static int emummc_raw_get_part_off(int part_idx)
return 2; return 2;
} }
int emummc_storage_init_mmc(sdmmc_storage_t *storage, sdmmc_t *sdmmc) int emummc_storage_init_mmc()
{ {
FILINFO fno; FILINFO fno;
emu_cfg.active_part = 0; emu_cfg.active_part = 0;
// Always init eMMC even when in emuMMC. eMMC is needed from the emuMMC driver anyway. // Always init eMMC even when in emuMMC. eMMC is needed from the emuMMC driver anyway.
if (!sdmmc_storage_init_mmc(storage, sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400)) if (!sdmmc_storage_init_mmc(&emmc_storage, &emmc_sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400))
return 2; return 2;
if (!emu_cfg.enabled || h_cfg.emummc_force_disable) if (!emu_cfg.enabled || h_cfg.emummc_force_disable)
@@ -173,21 +173,21 @@ out:
return 1; return 1;
} }
int emummc_storage_end(sdmmc_storage_t *storage) int emummc_storage_end()
{ {
if (!emu_cfg.enabled || h_cfg.emummc_force_disable) if (!emu_cfg.enabled || h_cfg.emummc_force_disable)
sdmmc_storage_end(storage); sdmmc_storage_end(&emmc_storage);
else else
sd_end(); sd_end();
return 1; 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; FIL fp;
if (!emu_cfg.enabled || h_cfg.emummc_force_disable) 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) else if (emu_cfg.sector)
{ {
sector += 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; 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; FIL fp;
if (!emu_cfg.enabled || h_cfg.emummc_force_disable) 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) else if (emu_cfg.sector)
{ {
sector += 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); 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)) if (f_open(&fp, emu_cfg.emummc_file_based_path, FA_WRITE))
{
gfx_printf("e5\n");
return 0; return 0;
}
f_lseek(&fp, (u64)sector << 9); f_lseek(&fp, (u64)sector << 9);
if (f_write(&fp, buf, (u64)num_sectors << 9, NULL)) if (f_write(&fp, buf, (u64)num_sectors << 9, NULL))
{ {
gfx_printf("e6\n");
f_close(&fp); f_close(&fp);
return 0; 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; emu_cfg.active_part = partition;
sdmmc_storage_set_mmc_partition(&emmc_storage, partition);
if (!emu_cfg.enabled || h_cfg.emummc_force_disable) if (!emu_cfg.enabled || h_cfg.emummc_force_disable || emu_cfg.sector)
sdmmc_storage_set_mmc_partition(storage, partition);
else if (emu_cfg.sector)
return 1; return 1;
else 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 * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@@ -51,10 +51,10 @@ extern emummc_cfg_t emu_cfg;
void emummc_load_cfg(); void emummc_load_cfg();
bool emummc_set_path(char *path); bool emummc_set_path(char *path);
int emummc_storage_init_mmc(sdmmc_storage_t *storage, sdmmc_t *sdmmc); int emummc_storage_init_mmc();
int emummc_storage_end(sdmmc_storage_t *storage); int emummc_storage_end();
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);
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);
int emummc_storage_set_mmc_partition(sdmmc_storage_t *storage, u32 partition); int emummc_storage_set_mmc_partition(u32 partition);
#endif #endif

View File

@@ -1,6 +1,6 @@
/* /*
* Copyright (c) 2018 naehrwert * 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 * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@@ -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); 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++) 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) if (part->lba_start + sector_off > part->lba_end)
return 0; 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) 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) if (part->lba_start + sector_off > part->lba_end)
return 0; 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) 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_unmount() { _sd_deinit(); }
void sd_end() { _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) void *sd_file_read(const char *path, u32 *fsize)
{ {
FIL fp; 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). CLOCK(CLK_RST_CONTROLLER_SCLK_BURST_POLICY) = 0x20003333; // Set SCLK to PLLP_OUT (408MHz).
// Get Loader and Payload size. // 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; u32 *payload_addr = (u32 *)payload_00;
// Relocate payload to a safer place. // Relocate payload to a safer place.
@@ -88,16 +89,20 @@ void loader_main()
bytes--; bytes--;
} }
// Uncompress payload parts. // Set source address of the first part.
u8 *src_addr = (void *)(IPL_RELOC_TOP - ALIGN(payload_size, 4)); 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)); // Uncompress first part.
src_addr += (u32)payload_01 - (u32)payload_00; u32 dst_pos = LZ_Uncompress((const u8 *)src_addr, (u8*)IPL_LOAD_ADDR, sizeof(payload_00));
LZ_Uncompress((const u8 *)src_addr, (u8*)IPL_LOAD_ADDR + pos, sizeof(payload_01));
// 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)); 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; void (*ipl_ptr)() = (void *)IPL_LOAD_ADDR;
(*ipl_ptr)(); (*ipl_ptr)();

View File

@@ -1,7 +1,7 @@
/* /*
* Copyright (c) 2018 naehrwert * Copyright (c) 2018 naehrwert
* Copyright (c) 2018 Rajko Stojadinovic * 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 * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@@ -41,7 +41,6 @@
#define NUM_SECTORS_PER_ITER 8192 // 4MB Cache. #define NUM_SECTORS_PER_ITER 8192 // 4MB Cache.
#define OUT_FILENAME_SZ 128 #define OUT_FILENAME_SZ 128
#define HASH_FILENAME_SZ (OUT_FILENAME_SZ + 11) // 11 == strlen(".sha256sums") #define HASH_FILENAME_SZ (OUT_FILENAME_SZ + 11) // 11 == strlen(".sha256sums")
#define SHA256_SZ 0x20
extern nyx_config n_cfg; 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"; const char hexa[] = "0123456789abcdef";
DWORD *clmt = NULL; DWORD *clmt = NULL;
u8 hashEm[SHA256_SZ]; u8 hashEm[SE_SHA_256_SIZE];
u8 hashSd[SHA256_SZ]; u8 hashSd[SE_SHA_256_SIZE];
if (f_open(&fp, outFilename, FA_READ) == FR_OK) 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); manual_system_maintenance(false);
se_calc_sha256_finalize(hashEm, NULL); se_calc_sha256_finalize(hashEm, NULL);
se_calc_sha256_oneshot(hashSd, bufSd, 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) 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) if (n_cfg.verification == 3)
{ {
// Transform computed hash to readable hexadecimal // Transform computed hash to readable hexadecimal
char hashStr[SHA256_SZ * 2 + 1]; char hashStr[SE_SHA_256_SIZE * 2 + 1];
char *hashStrPtr = hashStr; 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] >> 4];
*(hashStrPtr++) = hexa[hashSd[i] & 0x0F]; *(hashStrPtr++) = hexa[hashSd[i] & 0x0F];
} }
hashStr[SHA256_SZ * 2] = '\0'; hashStr[SE_SHA_256_SIZE * 2] = '\0';
f_puts(hashStr, &hashFp); f_puts(hashStr, &hashFp);
f_puts("\n", &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. // Get SD Card free space for Partial Backup.
f_getfree("", &sd_fs.free_clst, NULL); f_getfree("", &sd_fs.free_clst, NULL);
sdmmc_storage_t storage; if (!sdmmc_storage_init_mmc(&emmc_storage, &emmc_sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400))
sdmmc_t sdmmc;
if (!sdmmc_storage_init_mmc(&storage, &sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400))
{ {
lv_label_set_text(gui->label_info, "#FFDD00 Failed to init eMMC!#"); lv_label_set_text(gui->label_info, "#FFDD00 Failed to init eMMC!#");
goto out; goto out;
@@ -782,16 +779,16 @@ void dump_emmc_selected(emmcPartType_t dumpType, emmc_tool_gui_t *gui)
int i = 0; int i = 0;
char sdPath[OUT_FILENAME_SZ]; char sdPath[OUT_FILENAME_SZ];
// Create Restore folders, if they do not exist. // Create Restore folders, if they do not exist.
emmcsn_path_impl(sdPath, "/restore", "", &storage); emmcsn_path_impl(sdPath, "/restore", "", &emmc_storage);
emmcsn_path_impl(sdPath, "/restore/partitions", "", &storage); emmcsn_path_impl(sdPath, "/restore/partitions", "", &emmc_storage);
emmcsn_path_impl(sdPath, "", "", &storage); emmcsn_path_impl(sdPath, "", "", &emmc_storage);
gui->base_path = (char *)malloc(strlen(sdPath) + 1); gui->base_path = (char *)malloc(strlen(sdPath) + 1);
strcpy(gui->base_path, sdPath); strcpy(gui->base_path, sdPath);
timer = get_tmr_s(); timer = get_tmr_s();
if (dumpType & PART_BOOT) 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; emmc_part_t bootPart;
memset(&bootPart, 0, sizeof(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); lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, txt_buf);
manual_system_maintenance(true); 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); emmcsn_path_impl(sdPath, "", bootPart.name, &emmc_storage);
res = _dump_emmc_part(gui, sdPath, i, &storage, &bootPart); res = _dump_emmc_part(gui, sdPath, i, &emmc_storage, &bootPart);
if (!res) if (!res)
s_printf(txt_buf, "#FFDD00 Failed!#\n"); 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)) 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)) 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); gui->base_path = (char *)malloc(strlen(sdPath) + 1);
strcpy(gui->base_path, sdPath); strcpy(gui->base_path, sdPath);
LIST_INIT(gpt); 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) LIST_FOREACH_ENTRY(emmc_part_t, part, &gpt, link)
{ {
if ((dumpType & PART_USER) == 0 && !strcmp(part->name, "USER")) 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); manual_system_maintenance(true);
i++; i++;
emmcsn_path_impl(sdPath, "/partitions", part->name, &storage); emmcsn_path_impl(sdPath, "/partitions", part->name, &emmc_storage);
res = _dump_emmc_part(gui, sdPath, 0, &storage, part); res = _dump_emmc_part(gui, sdPath, 0, &emmc_storage, part);
// If a part failed, don't continue. // If a part failed, don't continue.
if (!res) if (!res)
{ {
@@ -873,7 +870,7 @@ void dump_emmc_selected(emmcPartType_t dumpType, emmc_tool_gui_t *gui)
if (dumpType & PART_RAW) if (dumpType & PART_RAW)
{ {
// Get GP partition size dynamically. // 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; emmc_part_t rawPart;
memset(&rawPart, 0, sizeof(rawPart)); memset(&rawPart, 0, sizeof(rawPart));
@@ -890,8 +887,8 @@ void dump_emmc_selected(emmcPartType_t dumpType, emmc_tool_gui_t *gui)
i++; i++;
emmcsn_path_impl(sdPath, "", rawPart.name, &storage); emmcsn_path_impl(sdPath, "", rawPart.name, &emmc_storage);
res = _dump_emmc_part(gui, sdPath, 2, &storage, &rawPart); res = _dump_emmc_part(gui, sdPath, 2, &emmc_storage, &rawPart);
if (!res) if (!res)
s_printf(txt_buf, "#FFDD00 Failed!#\n"); 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; timer = get_tmr_s() - timer;
sdmmc_storage_end(&storage); sdmmc_storage_end(&emmc_storage);
if (res && n_cfg.verification && !gui->raw_emummc) 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); s_printf(txt_buf, "Time taken: %dm %ds.\n#96FF00 Finished and verified!#", timer / 60, timer % 60);
@@ -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); _get_valid_partition(&sector_start, &sector_size, &part_idx, false);
if (!part_idx || !sector_size) 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); lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf);
manual_system_maintenance(true); 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. // Verify part.
if (_dump_emmc_verify(gui, storage, lbaStartPart, outFilename, 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); lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf);
manual_system_maintenance(true); 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); res = f_open(&fp, outFilename, FA_READ);
if (res) 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); lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf);
manual_system_maintenance(true); 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) while (res)
{ {
s_printf(gui->txt_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). #", "#FFDD00 from eMMC (try %d).\n#",
num, lba_curr, ++retryCount); num, lba_curr, ++retryCount);
lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf); lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf);
manual_system_maintenance(true); manual_system_maintenance(true);
@@ -1371,9 +1368,7 @@ void restore_emmc_selected(emmcPartType_t restoreType, emmc_tool_gui_t *gui)
goto out; goto out;
} }
sdmmc_storage_t storage; if (!sdmmc_storage_init_mmc(&emmc_storage, &emmc_sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400))
sdmmc_t sdmmc;
if (!sdmmc_storage_init_mmc(&storage, &sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400))
{ {
lv_label_set_text(gui->label_info, "#FFDD00 Failed to init eMMC!#"); lv_label_set_text(gui->label_info, "#FFDD00 Failed to init eMMC!#");
goto out; goto out;
@@ -1382,14 +1377,14 @@ void restore_emmc_selected(emmcPartType_t restoreType, emmc_tool_gui_t *gui)
int i = 0; int i = 0;
char sdPath[OUT_FILENAME_SZ]; 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); gui->base_path = (char *)malloc(strlen(sdPath) + 1);
strcpy(gui->base_path, sdPath); strcpy(gui->base_path, sdPath);
timer = get_tmr_s(); timer = get_tmr_s();
if (restoreType & PART_BOOT) 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; emmc_part_t bootPart;
memset(&bootPart, 0, sizeof(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); lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, txt_buf);
manual_system_maintenance(true); 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); emmcsn_path_impl(sdPath, "/restore", bootPart.name, &emmc_storage);
res = _restore_emmc_part(gui, sdPath, i, &storage, &bootPart, false); res = _restore_emmc_part(gui, sdPath, i, &emmc_storage, &bootPart, false);
if (!res) if (!res)
s_printf(txt_buf, "#FFDD00 Failed!#\n"); 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) 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); gui->base_path = (char *)malloc(strlen(sdPath) + 1);
strcpy(gui->base_path, sdPath); 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); 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) 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", 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); manual_system_maintenance(true);
i++; i++;
emmcsn_path_impl(sdPath, "/restore/partitions", part->name, &storage); emmcsn_path_impl(sdPath, "/restore/partitions", part->name, &emmc_storage);
res = _restore_emmc_part(gui, sdPath, 0, &storage, part, false); res = _restore_emmc_part(gui, sdPath, 0, &emmc_storage, part, false);
if (!res) if (!res)
s_printf(txt_buf, "#FFDD00 Failed!#\n"); 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) if (restoreType & PART_RAW)
{ {
// Get GP partition size dynamically. // 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; emmc_part_t rawPart;
memset(&rawPart, 0, sizeof(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); manual_system_maintenance(true);
i++; i++;
emmcsn_path_impl(sdPath, "/restore", rawPart.name, &storage); emmcsn_path_impl(sdPath, "/restore", rawPart.name, &emmc_storage);
res = _restore_emmc_part(gui, sdPath, 2, &storage, &rawPart, true); res = _restore_emmc_part(gui, sdPath, 2, &emmc_storage, &rawPart, true);
if (!res) if (!res)
s_printf(txt_buf, "#FFDD00 Failed!#\n"); 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; timer = get_tmr_s() - timer;
sdmmc_storage_end(&storage); sdmmc_storage_end(&emmc_storage);
if (res && n_cfg.verification && !gui->raw_emummc) 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); 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 naehrwert
* Copyright (c) 2018 Rajko Stojadinovic * 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 * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@@ -23,13 +23,16 @@
#include "gui.h" #include "gui.h"
#include "fe_emummc_tools.h" #include "fe_emummc_tools.h"
#include "../hos/sept.h"
#include "../config.h" #include "../config.h"
#include <utils/ini.h> #include <utils/ini.h>
#include <libs/fatfs/diskio.h>
#include <libs/fatfs/ff.h> #include <libs/fatfs/ff.h>
#include <mem/heap.h> #include <mem/heap.h>
#include <sec/se.h> #include <sec/se.h>
#include <storage/mbr_gpt.h> #include <storage/mbr_gpt.h>
#include "../storage/nx_emmc.h" #include "../storage/nx_emmc.h"
#include "../storage/nx_emmc_bis.h"
#include <storage/nx_sd.h> #include <storage/nx_sd.h>
#include <storage/sdmmc.h> #include <storage/sdmmc.h>
#include <utils/btn.h> #include <utils/btn.h>
@@ -40,6 +43,7 @@
#define OUT_FILENAME_SZ 128 #define OUT_FILENAME_SZ 128
extern hekate_config h_cfg; extern hekate_config h_cfg;
extern volatile boot_cfg_t *b_cfg;
void load_emummc_cfg(emummc_cfg_t *emu_info) 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); res = f_open(&fp, outFilename, FA_CREATE_ALWAYS | FA_WRITE);
if (res) 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); lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf);
manual_system_maintenance(true); 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. // Check for cancellation combo.
if (btn_read_vol() == (BTN_VOL_UP | BTN_VOL_DOWN)) 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); lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf);
manual_system_maintenance(true); 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)) while (!sdmmc_storage_read(storage, lba_curr, num, buf))
{ {
s_printf(gui->txt_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). #", "#FFDD00 from eMMC (try %d). #",
num, lba_curr, ++retryCount); num, lba_curr, ++retryCount);
lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf); lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf);
@@ -283,7 +287,7 @@ static int _dump_emummc_file_part(emmc_tool_gui_t *gui, char *sd_path, sdmmc_sto
} }
else 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); lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf);
manual_system_maintenance(true); manual_system_maintenance(true);
} }
@@ -349,6 +353,7 @@ void dump_emummc_file(emmc_tool_gui_t *gui)
u32 timer = 0; u32 timer = 0;
char *txt_buf = (char *)malloc(0x4000); char *txt_buf = (char *)malloc(0x4000);
gui->base_path = (char *)malloc(OUT_FILENAME_SZ);
gui->txt_buf = txt_buf; gui->txt_buf = txt_buf;
s_printf(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. // Get SD Card free space for Partial Backup.
f_getfree("", &sd_fs.free_clst, NULL); f_getfree("", &sd_fs.free_clst, NULL);
sdmmc_storage_t storage; if (!sdmmc_storage_init_mmc(&emmc_storage, &emmc_sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400))
sdmmc_t sdmmc;
if (!sdmmc_storage_init_mmc(&storage, &sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400))
{ {
lv_label_set_text(gui->label_info, "#FFDD00 Failed to init eMMC!#"); lv_label_set_text(gui->label_info, "#FFDD00 Failed to init eMMC!#");
goto out; goto out;
@@ -382,7 +385,6 @@ void dump_emummc_file(emmc_tool_gui_t *gui)
f_mkdir("emuMMC"); f_mkdir("emuMMC");
strcpy(sdPath, "emuMMC/SD"); strcpy(sdPath, "emuMMC/SD");
base_len = strlen(sdPath); base_len = strlen(sdPath);
gui->base_path = (char *)malloc(OUT_FILENAME_SZ);
for (int j = 0; j < 100; j++) 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); strcpy(gui->base_path, sdPath);
timer = get_tmr_s(); 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; emmc_part_t bootPart;
memset(&bootPart, 0, sizeof(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); lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, txt_buf);
manual_system_maintenance(true); 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); 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) if (!res)
{ {
@@ -437,10 +439,10 @@ void dump_emummc_file(emmc_tool_gui_t *gui)
} }
// Get GP partition size dynamically. // 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. // 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; emmc_part_t rawPart;
memset(&rawPart, 0, sizeof(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); lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, txt_buf);
manual_system_maintenance(true); 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) if (!res)
s_printf(txt_buf, "#FFDD00 Failed!#\n"); s_printf(txt_buf, "#FFDD00 Failed!#\n");
@@ -468,7 +470,7 @@ void dump_emummc_file(emmc_tool_gui_t *gui)
out_failed: out_failed:
timer = get_tmr_s() - timer; timer = get_tmr_s() - timer;
sdmmc_storage_end(&storage); sdmmc_storage_end(&emmc_storage);
if (res) if (res)
{ {
@@ -494,9 +496,15 @@ out:
sd_unmount(); 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"); s_printf(gui->txt_buf, "\n\n\n");
lv_label_ins_text(gui->label_info, LV_LABEL_POS_LAST, gui->txt_buf); 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); lv_label_ins_text(gui->label_info, LV_LABEL_POS_LAST, gui->txt_buf);
manual_system_maintenance(true); 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->bar, LV_OPA_COVER);
lv_obj_set_opa_scale(gui->label_pct, 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) while (totalSectors > 0)
{ {
// Check for cancellation combo. // Check for cancellation combo.
if (btn_read_vol() == (BTN_VOL_UP | BTN_VOL_DOWN)) 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); lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf);
manual_system_maintenance(true); manual_system_maintenance(true);
@@ -618,25 +640,328 @@ 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%"); lv_label_set_text(gui->label_pct, " "SYMBOL_DOT" 100%");
manual_system_maintenance(true); manual_system_maintenance(true);
// Hide the partition. // Set partition type to emuMMC (0xE0).
if (active_part == 2) if (active_part == 2)
{ {
mbr_t *mbr = (mbr_t *)malloc(sizeof(mbr_t)); mbr_t mbr;
sdmmc_storage_read(&sd_storage, 0, 1, mbr); sdmmc_storage_read(&sd_storage, 0, 1, &mbr);
mbr->partitions[part_idx].type = 0xE0; mbr.partitions[part_idx].type = 0xE0;
sdmmc_storage_write(&sd_storage, 0, 1, mbr); sdmmc_storage_write(&sd_storage, 0, 1, &mbr);
free(mbr); }
if (resized_count)
{
lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, "Done!\n");
// Calculate USER size and set it for FatFS.
u32 user_sectors = resized_count - user_offset - 33;
disk_set_info(DRIVE_EMU, SET_SECTOR_COUNT, &user_sectors);
// Initialize BIS for emuMMC. BIS keys should be already in place.
emmc_part_t user_part = {0};
user_part.lba_start = user_offset;
user_part.lba_end = user_offset + user_sectors - 1;
strcpy(user_part.name, "USER");
nx_emmc_bis_init(&user_part, true, sd_sector_off);
s_printf(gui->txt_buf, "Formatting USER... \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 Failed (%d)!#\nPlease try again...\n", mkfs_error);
lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf);
return 0;
}
lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, "Done!\n");
// Flush BIS cache, deinit, clear BIS keys slots and reinstate SBK.
nx_emmc_bis_end();
hos_bis_keys_clear();
s_printf(gui->txt_buf, "Writing new GPT... ");
lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf);
manual_system_maintenance(true);
// Read MBR, GPT and backup GPT.
mbr_t mbr;
gpt_t gpt_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, "\n#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; 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; int res = 0;
u32 timer = 0; u32 timer = 0;
char *txt_buf = (char *)malloc(0x4000); char *txt_buf = (char *)malloc(0x4000);
gui->base_path = (char *)malloc(OUT_FILENAME_SZ);
gui->txt_buf = txt_buf; gui->txt_buf = txt_buf;
s_printf(txt_buf, ""); s_printf(txt_buf, "");
@@ -650,26 +975,31 @@ void dump_emummc_raw(emmc_tool_gui_t *gui, int part_idx, u32 sector_start)
goto out; goto out;
} }
sdmmc_storage_t storage; if (!sdmmc_storage_init_mmc(&emmc_storage, &emmc_sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400))
sdmmc_t sdmmc;
if (!sdmmc_storage_init_mmc(&storage, &sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400))
{ {
lv_label_set_text(gui->label_info, "#FFDD00 Failed to init eMMC!#"); lv_label_set_text(gui->label_info, "#FFDD00 Failed to init eMMC!#");
goto out; 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; int i = 0;
char sdPath[OUT_FILENAME_SZ]; char sdPath[OUT_FILENAME_SZ];
// Create Restore folders, if they do not exist. // Create Restore folders, if they do not exist.
f_mkdir("emuMMC"); f_mkdir("emuMMC");
s_printf(sdPath, "emuMMC/RAW%d", part_idx); s_printf(sdPath, "emuMMC/RAW%d", part_idx);
gui->base_path = (char *)malloc(OUT_FILENAME_SZ);
f_mkdir(sdPath); f_mkdir(sdPath);
strcat(sdPath, "/"); strcat(sdPath, "/");
strcpy(gui->base_path, sdPath); strcpy(gui->base_path, sdPath);
timer = get_tmr_s(); 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; emmc_part_t bootPart;
memset(&bootPart, 0, sizeof(bootPart)); memset(&bootPart, 0, sizeof(bootPart));
@@ -693,10 +1023,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); lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, txt_buf);
manual_system_maintenance(true); 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); 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) if (!res)
{ {
@@ -712,10 +1042,10 @@ void dump_emummc_raw(emmc_tool_gui_t *gui, int part_idx, u32 sector_start)
strcpy(sdPath, gui->base_path); 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. // 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; emmc_part_t rawPart;
memset(&rawPart, 0, sizeof(rawPart)); memset(&rawPart, 0, sizeof(rawPart));
@@ -730,7 +1060,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); lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, txt_buf);
manual_system_maintenance(true); 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) if (!res)
s_printf(txt_buf, "#FFDD00 Failed!#\n"); s_printf(txt_buf, "#FFDD00 Failed!#\n");
@@ -743,7 +1073,7 @@ void dump_emummc_raw(emmc_tool_gui_t *gui, int part_idx, u32 sector_start)
out_failed: out_failed:
timer = get_tmr_s() - timer; timer = get_tmr_s() - timer;
sdmmc_storage_end(&storage); sdmmc_storage_end(&emmc_storage);
if (res) if (res)
{ {

View File

@@ -32,7 +32,7 @@ typedef struct _emummc_cfg_t
void load_emummc_cfg(emummc_cfg_t *emu_info); void load_emummc_cfg(emummc_cfg_t *emu_info);
void save_emummc_cfg(u32 part_idx, u32 sector_start, const char *path); void save_emummc_cfg(u32 part_idx, u32 sector_start, const char *path);
void dump_emummc_file(emmc_tool_gui_t *gui); 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); void update_emummc_base_folder(char *outFilename, u32 sdPathLen, u32 currPartIdx);
#endif #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 * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@@ -1139,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_recolor(lbl_credits, true);
lv_label_set_static_text(lbl_credits, lv_label_set_static_text(lbl_credits,
"#C7EA46 hekate# (c) 2018, #C7EA46 naehrwert#, #C7EA46 st4rk#\n" "#C7EA46 hekate# (c) 2018, #C7EA46 naehrwert#, #C7EA46 st4rk#\n"
" (c) 2018-2020, #C7EA46 CTCaer#\n" " (c) 2018-2021, #C7EA46 CTCaer#\n"
"\n" "\n"
"#C7EA46 Nyx GUI# (c) 2019-2020, #C7EA46 CTCaer#\n" "#C7EA46 Nyx GUI# (c) 2019-2021, #C7EA46 CTCaer#\n"
"\n" "\n"
"Thanks to: #00CCFF derrek, nedwill, plutoo, #\n" "Thanks to: #00CCFF derrek, nedwill, plutoo, #\n"
" #00CCFF shuffle2, smea, thexyz, yellows8 #\n" " #00CCFF shuffle2, smea, thexyz, yellows8 #\n"
@@ -1755,14 +1755,14 @@ ini_parsing:
{ {
lv_label_set_static_text(label_error, lv_label_set_static_text(label_error,
"#FFDD00 No main boot entries found...#\n" "#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."); "or use #C7EA46 More configs# button for more boot entries.");
} }
else else
{ {
lv_label_set_static_text(label_error, lv_label_set_static_text(label_error,
"#FFDD00 No .ini or boot entries found...#\n" "#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."); "and that it contains at least one entry.");
} }
@@ -2206,17 +2206,25 @@ static void _nyx_main_menu(lv_theme_t * th)
lv_tabview_set_tab_load_action(tv, _show_hide_save_button); lv_tabview_set_tab_load_action(tv, _show_hide_save_button);
// If we rebooted to run sept for dumping, lunch dump immediately. // 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); u32 type = nyx_str->cfg >> 24;
lv_task_t *task_run_dump = lv_task_create(sept_run_dump, LV_TASK_ONESHOT, LV_TASK_PRIO_MID, NULL); nyx_str->cfg &= ~(NYX_CFG_SEPT | NYX_CFG_EXTRA);
lv_task_once(task_run_dump);
} if (type == NYX_SEPT_DUMP)
else if (nyx_str->cfg & NYX_CFG_BIS) {
{ lv_task_t *task_run_dump = lv_task_create(sept_run_dump, LV_TASK_ONESHOT, LV_TASK_PRIO_MID, NULL);
nyx_str->cfg &= ~(NYX_CFG_BIS); lv_task_once(task_run_dump);
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_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) else if (nyx_str->cfg & NYX_CFG_UMS)
{ {

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 * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@@ -24,6 +24,7 @@
#include <libs/fatfs/ff.h> #include <libs/fatfs/ff.h>
#include <mem/heap.h> #include <mem/heap.h>
#include <storage/mbr_gpt.h> #include <storage/mbr_gpt.h>
#include "../storage/nx_emmc_bis.h"
#include <storage/nx_sd.h> #include <storage/nx_sd.h>
#include <storage/sdmmc.h> #include <storage/sdmmc.h>
#include <utils/dirlist.h> #include <utils/dirlist.h>
@@ -37,6 +38,8 @@ typedef struct _mbr_ctxt_t
{ {
u32 available; u32 available;
u32 sector[3]; u32 sector[3];
u32 resized_cnt[3];
int part_idx; int part_idx;
u32 sector_start; u32 sector_start;
} mbr_ctxt_t; } 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) static lv_res_t _action_emummc_window_close(lv_obj_t *btn)
{ {
lv_win_close_action(btn); lv_win_close_action(btn);
lv_obj_del(emummc_manage_window);
(*emummc_tools)(NULL);
close_btn = NULL; close_btn = NULL;
// Delete and relaunch main emuMMC window.
lv_obj_del(emummc_manage_window);
(*emummc_tools)(NULL);
return LV_RES_INV; return LV_RES_INV;
} }
@@ -141,7 +144,7 @@ static void _create_window_emummc()
if (!mbr_ctx.part_idx) if (!mbr_ctx.part_idx)
dump_emummc_file(&emmc_tool_gui_ctxt); dump_emummc_file(&emmc_tool_gui_ctxt);
else 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); nyx_window_toggle_buttons(win, false);
} }
@@ -223,13 +226,11 @@ static void _create_mbox_emummc_raw()
sdmmc_storage_read(&sd_storage, 0, 1, mbr); sdmmc_storage_read(&sd_storage, 0, 1, mbr);
sd_unmount(); sd_unmount();
sdmmc_storage_t storage; sdmmc_storage_init_mmc(&emmc_storage, &emmc_sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400);
sdmmc_t sdmmc;
sdmmc_storage_init_mmc(&storage, &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++) for (int i = 1; i < 4; i++)
{ {
@@ -240,10 +241,22 @@ static void _create_mbox_emummc_raw()
// Skip Linux, GPT (Android) and SFD partitions. // Skip Linux, GPT (Android) and SFD partitions.
bool valid_part = (part_type != 0x83) && (part_type != 0xEE) && (part_type != 0xFF); 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; 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" "#C0C0C0 Part 0: Type: %02x, Start: %08x, Size: %08x#\n"
"#%s Part 1: 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 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->partitions[0].type, mbr->partitions[0].start_sct, mbr->partitions[0].size_sct,
(mbr_ctx.available & 1) ? "C7EA46" : "C0C0C0", (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->partitions[1].type, mbr->partitions[1].start_sct, mbr->partitions[1].size_sct,
(mbr_ctx.available & 2) ? "C7EA46" : "C0C0C0", (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->partitions[2].type, mbr->partitions[2].start_sct, mbr->partitions[2].size_sct,
(mbr_ctx.available & 4) ? "C7EA46" : "C0C0C0", (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); 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) if (!mbr_ctx.available)
strcat(txt_buf, strcat(txt_buf, "\n#FF8000 Do you want to partition the SD card?#\n"
"\n#FF8000 Do you want to partition the SD card?#\n" "#FF8000 (You will be asked on how to proceed)#");
"#FF8000 (You will be asked on how to proceed)#");
lv_mbox_set_text(mbox, txt_buf); lv_mbox_set_text(mbox, txt_buf);
free(txt_buf); free(txt_buf);
@@ -365,6 +380,38 @@ static void _change_raw_emummc_part_type()
free(mbr); free(mbr);
} }
static lv_res_t _save_emummc_cfg_mig_mbox_action(lv_obj_t *btns, const char *txt)
{
// Delete main emuMMC and popup windows and relaunch main emuMMC window.
lv_obj_del(emummc_manage_window);
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() static void _migrate_sd_raw_based()
{ {
mbr_ctx.sector_start = 2; mbr_ctx.sector_start = 2;
@@ -380,6 +427,7 @@ static void _migrate_sd_raw_based()
f_close(&fp); f_close(&fp);
save_emummc_cfg(1, mbr_ctx.sector_start, "emuMMC/ER00"); save_emummc_cfg(1, mbr_ctx.sector_start, "emuMMC/ER00");
_create_emummc_migrated_mbox();
sd_unmount(); sd_unmount();
} }
@@ -405,7 +453,7 @@ static void _migrate_sd_raw_emummc_based()
_change_raw_emummc_part_type(); _change_raw_emummc_part_type();
save_emummc_cfg(mbr_ctx.part_idx, mbr_ctx.sector_start, tmp); save_emummc_cfg(mbr_ctx.part_idx, mbr_ctx.sector_start, tmp);
_create_emummc_migrated_mbox();
free(tmp); free(tmp);
sd_unmount(); sd_unmount();
@@ -444,6 +492,7 @@ static void _migrate_sd_file_based()
free(path2); free(path2);
save_emummc_cfg(0, 0, "emuMMC/EF00"); save_emummc_cfg(0, 0, "emuMMC/EF00");
_create_emummc_migrated_mbox();
sd_unmount(); sd_unmount();
} }
@@ -516,6 +565,7 @@ static void _migrate_sd_backup_file_based()
free(backup_file_path); free(backup_file_path);
save_emummc_cfg(0, 0, "emuMMC/BK00"); save_emummc_cfg(0, 0, "emuMMC/BK00");
_create_emummc_migrated_mbox();
sd_unmount(); sd_unmount();
} }
@@ -645,41 +695,41 @@ static lv_res_t _create_emummc_migrate_action(lv_obj_t * btns, const char * txt)
if (backup) if (backup)
{ {
s_printf(txt_buf, s_printf(txt_buf,
"#C7EA46 Found suitable backup for emuMMC!#\n" "#C7EA46 Found suitable backup for emuMMC!#\n\n"
"#FF8000 Do you want to migrate it?#\n\n"); "#FF8000 Do you want to migrate it?#\n");
lv_mbox_add_btns(mbox, mbox_btn_map, _create_emummc_mig4_action); lv_mbox_add_btns(mbox, mbox_btn_map, _create_emummc_mig4_action);
} }
else if (emummc) else if (emummc)
{ {
s_printf(txt_buf, s_printf(txt_buf,
"#C7EA46 Found SD Partition based emuMMC!#\n" "#C7EA46 Found SD Partition based emuMMC!#\n\n"
"#FF8000 Do you want to repair the config for it?#\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); lv_mbox_add_btns(mbox, mbox_btn_map, _create_emummc_mig3_action);
} }
else if (em_raw && em_file) else if (em_raw && em_file)
{ {
s_printf(txt_buf, s_printf(txt_buf,
"#C7EA46 Found both foreign SD File and Partition emunand!#\n" "#C7EA46 Found both foreign SD File and Partition emunand!#\n\n"
"#FF8000 Choose what to migrate:#\n\n"); "#FF8000 Choose what to migrate:#\n");
lv_mbox_add_btns(mbox, mbox_btn_map1, _create_emummc_mig1_action); lv_mbox_add_btns(mbox, mbox_btn_map1, _create_emummc_mig1_action);
} }
else if (em_raw) else if (em_raw)
{ {
s_printf(txt_buf, s_printf(txt_buf,
"#C7EA46 Found foreign SD Partition emunand!#\n" "#C7EA46 Found foreign SD Partition emunand!#\n\n"
"#FF8000 Do you want to migrate it?#\n\n"); "#FF8000 Do you want to migrate it?#\n");
lv_mbox_add_btns(mbox, mbox_btn_map, _create_emummc_mig2_action); lv_mbox_add_btns(mbox, mbox_btn_map, _create_emummc_mig2_action);
} }
else if (em_file) else if (em_file)
{ {
s_printf(txt_buf, s_printf(txt_buf,
"#C7EA46 Found foreign SD File emunand!#\n" "#C7EA46 Found foreign SD File emunand!#\n\n"
"#FF8000 Do you want to migrate it?#\n\n"); "#FF8000 Do you want to migrate it?#\n");
lv_mbox_add_btns(mbox, mbox_btn_map, _create_emummc_mig0_action); lv_mbox_add_btns(mbox, mbox_btn_map, _create_emummc_mig0_action);
} }
else 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); 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(); sd_mount();
sdmmc_storage_read(&sd_storage, 0, 1, mbr); sdmmc_storage_read(&sd_storage, 0, 1, mbr);
sdmmc_storage_t storage; sdmmc_storage_init_mmc(&emmc_storage, &emmc_sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400);
sdmmc_t sdmmc;
sdmmc_storage_init_mmc(&storage, &sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400);
em_raw = false; em_raw = false;
em_file = 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)) if(!f_stat(path_buf, NULL))
em_file = true; em_file = true;
emmcsn_path_impl(path_buf, "", "BOOT0", &storage); emmcsn_path_impl(path_buf, "", "BOOT0", &emmc_storage);
if(!f_stat(path_buf, NULL)) if(!f_stat(path_buf, NULL))
backup = true; 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)) if(!f_stat(path_buf, NULL))
rawnand_backup = true; 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)) if(!f_stat(path_buf, NULL))
rawnand_backup = true; rawnand_backup = true;
backup = backup && rawnand_backup; backup = backup && rawnand_backup;
sd_unmount(); sd_unmount();
sdmmc_storage_end(&storage); sdmmc_storage_end(&emmc_storage);
// Check available types and enable the corresponding buttons. // Check available types and enable the corresponding buttons.
if (backup) 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) 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); free(emummc_img->dirlist);
lv_obj_del(emummc_img->win); lv_obj_del(emummc_img->win);
lv_obj_del(emummc_manage_window); lv_obj_del(emummc_manage_window);
@@ -1121,8 +1170,9 @@ out1:
lv_res_t create_win_emummc_tools(lv_obj_t *btn) lv_res_t create_win_emummc_tools(lv_obj_t *btn)
{ {
lv_obj_t *win = nyx_create_standard_window(SYMBOL_EDIT" emuMMC Manage"); 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; emummc_tools = (void *)create_win_emummc_tools;
sd_mount(); 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_set_style(label_txt4, &hint_small_style);
lv_obj_align(label_txt4, btn3, LV_ALIGN_OUT_BOTTOM_LEFT, 0, LV_DPI / 3); lv_obj_align(label_txt4, btn3, LV_ALIGN_OUT_BOTTOM_LEFT, 0, LV_DPI / 3);
//! TODO: Move it to a window with multiple choices.
// Create Migrate emuMMC button. // Create Migrate emuMMC button.
lv_obj_t *btn4 = lv_btn_create(h2, btn2); lv_obj_t *btn4 = lv_btn_create(h2, btn2);
label_btn = lv_label_create(btn4, NULL); 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, lv_label_set_static_text(label_txt4,
"Migrate a backup to a #C7EA46 SD File# or repair existing #C7EA46 SD Raw Partition#.\n" "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."); "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_set_style(label_txt4, &hint_small_style);
lv_obj_align(label_txt4, btn4, LV_ALIGN_OUT_BOTTOM_LEFT, 0, LV_DPI / 3); lv_obj_align(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 naehrwert
* Copyright (c) 2018-2020 CTCaer * Copyright (c) 2018-2021 CTCaer
* Copyright (c) 2018 balika011 * Copyright (c) 2018 balika011
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
@@ -269,7 +269,7 @@ static lv_res_t _tsec_keys_dump_window_action(lv_obj_t * btn)
{ {
char path[64]; char path[64];
emmcsn_path_impl(path, "/dumps", "tsec_keys.bin", NULL); 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(); sd_unmount();
} }
@@ -312,7 +312,13 @@ static lv_res_t _create_mbox_cal0(lv_obj_t *btn)
u32 bootloader_offset = BOOTLOADER_MAIN_OFFSET; u32 bootloader_offset = BOOTLOADER_MAIN_OFFSET;
u32 pk1_offset = h_cfg.t210b01 ? sizeof(bl_hdr_t210b01_t) : 0; // Skip T210B01 OEM header. u32 pk1_offset = h_cfg.t210b01 ? sizeof(bl_hdr_t210b01_t) : 0; // Skip T210B01 OEM header.
u8 *pkg1 = (u8 *)malloc(BOOTLOADER_SIZE); 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); sdmmc_storage_set_mmc_partition(&emmc_storage, EMMC_BOOT0);
try_load: try_load:
@@ -326,7 +332,7 @@ try_load:
if (!pkg1_id) 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. // Try backup bootloader.
if (bootloader_offset != BOOTLOADER_BACKUP_OFFSET) if (bootloader_offset != BOOTLOADER_BACKUP_OFFSET)
{ {
@@ -363,9 +369,23 @@ try_load:
h_cfg.sept_run = true; h_cfg.sept_run = true;
else 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 = 0;
b_cfg->autoboot_list = 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)) if (!reboot_to_sept((u8 *)tsec_ctxt.fw, kb))
{ {
@@ -393,10 +413,12 @@ t210b01:;
LIST_INIT(gpt); LIST_INIT(gpt);
nx_emmc_gpt_parse(&gpt, &emmc_storage); nx_emmc_gpt_parse(&gpt, &emmc_storage);
emmc_part_t *cal0_part = nx_emmc_part_find(&gpt, "PRODINFO"); // check if null 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_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(); hos_bis_keys_clear();
nx_emmc_cal0_t *cal0 = (nx_emmc_cal0_t *)cal0_buf; nx_emmc_cal0_t *cal0 = (nx_emmc_cal0_t *)cal0_buf;
@@ -1090,7 +1112,7 @@ try_load:
if (!pkg1_id) 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. // Try backup bootloader.
if (bootloader_offset != BOOTLOADER_BACKUP_OFFSET) if (bootloader_offset != BOOTLOADER_BACKUP_OFFSET)
{ {
@@ -1192,8 +1214,6 @@ out:
static lv_res_t _create_mbox_benchmark(bool sd_bench) static lv_res_t _create_mbox_benchmark(bool sd_bench)
{ {
sdmmc_t emmc_sdmmc;
sdmmc_storage_t emmc_storage;
sdmmc_storage_t *storage; sdmmc_storage_t *storage;
lv_obj_t *dark_bg = lv_obj_create(lv_scr_act(), NULL); 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", "" }; static const char * mbox_btn_map[] = { "\211", "\222OK", "\211", "" };
lv_obj_t * mbox = lv_mbox_create(dark_bg, NULL); lv_obj_t * mbox = lv_mbox_create(dark_bg, NULL);
lv_mbox_set_recolor_text(mbox, true); lv_mbox_set_recolor_text(mbox, true);
lv_obj_set_width(mbox, LV_HOR_RES / 7 * 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", s_printf(txt_buf, "#FF8000 %s Benchmark#\n[Raw Reads] Abort: VOL- & VOL+",
sd_bench ? "SD Card" : "eMMC", sd_bench ? "2GB" : "8GB"); sd_bench ? "SD Card" : "eMMC");
lv_mbox_set_text(mbox, txt_buf); 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_obj_set_size(bar, LV_DPI * 2, LV_DPI / 5);
lv_bar_set_range(bar, 0, 100); lv_bar_set_range(bar, 0, 100);
lv_bar_set_value(bar, 0); lv_bar_set_value(bar, 0);
@@ -1241,9 +1273,7 @@ static lv_res_t _create_mbox_benchmark(bool sd_bench)
else else
{ {
u32 iters = 3; u32 iters = 3;
u32 sector_num = 0x8000; u32 offset_chunk_start = ALIGN_DOWN(storage->sec_cnt / 3, 0x8000); // Align to 16MB.
u32 data_scts = sd_bench ? 0x400000 : 0x1000000; // SD 2GB or eMMC 8GB.
u32 offset_chunk_start = ALIGN_DOWN(storage->sec_cnt / 3, sector_num);
if (storage->sec_cnt < 0xC00000) if (storage->sec_cnt < 0xC00000)
iters -= 2; // 4GB card. iters -= 2; // 4GB card.
@@ -1251,24 +1281,26 @@ static lv_res_t _create_mbox_benchmark(bool sd_bench)
{ {
u32 pct = 0; u32 pct = 0;
u32 prevPct = 200; u32 prevPct = 200;
u32 timer = 0;
u32 lba_curr = 0; u32 lba_curr = 0;
u32 sector = offset_chunk_start * iter_curr; 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(); s_printf(txt_buf + strlen(txt_buf), "#C7EA46 %d/3# - Sector Offset #C7EA46 %08X#:\n", iter_curr + 1, sector);
strcat(txt_buf, "\n");
lv_mbox_set_text(mbox, txt_buf);
while (data_remaining) 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); 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); manual_system_maintenance(false);
data_remaining -= sector_num; data_remaining -= sector_num;
lba_curr += sector_num; lba_curr += sector_num;
pct = (lba_curr * 100) / data_scts; pct = (lba_curr * 100) / 0x200000;
if (pct != prevPct) if (pct != prevPct)
{ {
lv_bar_set_value(bar, pct); lv_bar_set_value(bar, pct);
@@ -1280,17 +1312,115 @@ static lv_res_t _create_mbox_benchmark(bool sd_bench)
break; 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); 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), s_printf(txt_buf + strlen(txt_buf),
"#C7EA46 %d#: Offset: #C7EA46 %08X#, Time: #C7EA46 %d.%02ds#, Rate: #C7EA46 %d.%02d MB/s#", " Sequential 16MiB - Rate: #C7EA46 %3d.%02d MiB/s#\n",
iter_curr, sector, timer / 1000, (timer % 1000) / 10, rate_1k / 1000, (rate_1k % 1000) / 10); rate_1k / 1000, (rate_1k % 1000) / 10);
lv_mbox_set_text(mbox, txt_buf); 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); lv_obj_align(mbox, NULL, LV_ALIGN_CENTER, 0, 0);
manual_system_maintenance(true); 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); lv_obj_del(bar);
@@ -1300,8 +1430,10 @@ static lv_res_t _create_mbox_benchmark(bool sd_bench)
else else
sdmmc_storage_end(&emmc_storage); sdmmc_storage_end(&emmc_storage);
} }
free(txt_buf);
lv_mbox_add_btns(mbox, mbox_btn_map, mbox_action); // Important. After set_text. lv_mbox_add_btns(mbox, mbox_btn_map, mbox_action); // Important. After set_text.
lv_obj_align(mbox, NULL, LV_ALIGN_CENTER, 0, 0);
return LV_RES_OK; 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_long_mode(lb_desc, LV_LABEL_LONG_BREAK);
lv_label_set_recolor(lb_desc, true); lv_label_set_recolor(lb_desc, true);
sdmmc_storage_t storage;
sdmmc_t sdmmc;
char *txt_buf = (char *)malloc(0x4000); char *txt_buf = (char *)malloc(0x4000);
txt_buf[0] = '\n'; txt_buf[0] = '\n';
txt_buf[1] = 0; 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_label_set_text(lb_desc, "#FFDD00 Failed to init eMMC!#");
lv_obj_set_width(lb_desc, lv_obj_get_width(desc)); 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 *rsvd_blocks;
char life_a_txt[8]; char life_a_txt[8];
char life_b_txt[8]; char life_b_txt[8];
u32 life_a = storage.ext_csd.dev_life_est_a; u32 cache = emmc_storage.ext_csd.cache_size;
u32 life_b = storage.ext_csd.dev_life_est_b; u32 life_a = emmc_storage.ext_csd.dev_life_est_a;
u16 card_type = storage.ext_csd.card_type; 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]; char card_type_support[96];
card_type_support[0] = 0; card_type_support[0] = 0;
// Identify manufacturer. Only official eMMCs. // Identify manufacturer. Only official eMMCs.
switch (storage.cid.manfid) switch (emmc_storage.cid.manfid)
{ {
case 0x11: case 0x11:
strcat(txt_buf, "Toshiba "); strcat(txt_buf, "Toshiba ");
@@ -1365,16 +1495,20 @@ static lv_res_t _create_window_emmc_info_status(lv_obj_t *btn)
case 0x15: case 0x15:
strcat(txt_buf, "Samsung "); strcat(txt_buf, "Samsung ");
break; break;
case 0x45: // Unofficial.
strcat(txt_buf, "SanDisk ");
break;
case 0x90: case 0x90:
strcat(txt_buf, "SK Hynix "); strcat(txt_buf, "SK Hynix ");
break; 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", 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",
storage.cid.manfid, storage.cid.card_bga, storage.cid.oemid, emmc_storage.cid.manfid,
storage.cid.prod_name[0], storage.cid.prod_name[1], storage.cid.prod_name[2], emmc_storage.cid.prod_name[0], emmc_storage.cid.prod_name[1], emmc_storage.cid.prod_name[2],
storage.cid.prod_name[3], storage.cid.prod_name[4], storage.cid.prod_name[5], emmc_storage.cid.prod_name[3], emmc_storage.cid.prod_name[4], emmc_storage.cid.prod_name[5],
storage.cid.prv, storage.cid.serial, storage.cid.month, storage.cid.year); 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) 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, "-"); strcpy(life_b_txt, "-");
// Normalize cells life. // Normalize cells life.
if (life_a) if (life_a) // SK Hynix is 0 (undefined).
{ {
life_a--; life_a--;
life_a = (10 - life_a) * 10; 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); 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: case 1:
rsvd_blocks = "Normal (< 80%)"; 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%)"; rsvd_blocks = "Warning (> 80%)";
break; break;
case 3: case 3:
rsvd_blocks = "Urgent (> 90%)"; rsvd_blocks = "Critical (> 90%)";
break; break;
default: default:
rsvd_blocks = "#FF8000 Unknown#"; 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), 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", "#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",
storage.ext_csd.ext_struct, storage.ext_csd.rev, emmc_storage.ext_csd.ext_struct, emmc_storage.ext_csd.rev,
storage.csd.cmdclass, speed & 0xFFFF, (speed >> 16) & 0xFFFF, emmc_storage.csd.cmdclass, speed & 0xFFFF, (speed >> 16) & 0xFFFF,
storage.csd.busspeed, card_type_support, life_a_txt, life_b_txt, rsvd_blocks); 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, lv_label_set_static_text(lb_desc,
"#00DDFF CID:#\n" "#00DDFF CID:#\n"
"Vendor ID:\n" "Vendor ID:\n"
"Card/BGA:\n"
"OEM ID:\n"
"Model:\n" "Model:\n"
"Prd Rev:\n" "Prod Rev:\n"
"S/N:\n" "S/N:\n"
"Month/Year:\n\n" "Month/Year:\n\n"
"#00DDFF Ext CSD#\n" "#00DDFF Ext CSD:#\n"
"Cmd Classes:\n" "Cmd Classes:\n"
"Max Rate:\n" "Max Rate:\n"
"Current Rate:\n" "Current Rate:\n"
"Type Support:\n\n" "Type Support:\n\n"
"Write Cache:\n"
"Enhanced Area:\n"
"Estimated Life:\n" "Estimated Life:\n"
"Reserved Used:" "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_obj_t * lb_desc2 = lv_label_create(desc2, lb_desc);
lv_label_set_style(lb_desc2, &monospace_text); lv_label_set_style(lb_desc2, &monospace_text);
u32 boot_size = storage.ext_csd.boot_mult << 17; u32 boot_size = emmc_storage.ext_csd.boot_mult << 17;
u32 rpmb_size = storage.ext_csd.rpmb_mult << 17; u32 rpmb_size = emmc_storage.ext_csd.rpmb_mult << 17;
s_printf(txt_buf, "#00DDFF eMMC Physical Partitions:#\n"); strcpy(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), "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: %5d 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: %5d KiB (Sect: 0x%08X)\n", rpmb_size / 1024, rpmb_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: %5d MiB (Sect: 0x%08X)\n\n", storage.sec_cnt >> SECTORS_TO_MIB_COEFF, storage.sec_cnt); 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);
s_printf(txt_buf + strlen(txt_buf), "#00DDFF GPP (eMMC USER) Partition Table:#\n"); 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); LIST_INIT(gpt);
nx_emmc_gpt_parse(&gpt, &storage); nx_emmc_gpt_parse(&gpt, &emmc_storage);
u32 idx = 0; u32 idx = 0;
LIST_FOREACH_ENTRY(emmc_part_t, part, &gpt, link) LIST_FOREACH_ENTRY(emmc_part_t, part, &gpt, link)
{ {
if (idx > 10) if (idx > 10)
{ {
strcat(txt_buf, "#FFDD00 Table truncated!#"); strcat(txt_buf, "#FFDD00 Table does not fit on screen!#");
break; break;
} }
if (part->index < 2) 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), "%02d: #96FF00 %s#%s Size: %d MiB (Sect: 0x%X), Start: %06X\n",
s_printf(txt_buf + strlen(txt_buf), " 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) >> SECTORS_TO_MIB_COEFF,
part->lba_end - part->lba_start + 1, part->lba_start); 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++; idx++;
} }
if (!idx)
strcat(txt_buf, "#FFDD00 Partition table is empty!#");
nx_emmc_gpt_free(&gpt); nx_emmc_gpt_free(&gpt);
lv_label_set_text(lb_desc2, txt_buf); 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); 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); free(txt_buf);
return LV_RES_OK; 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, lv_label_set_text(lb_desc,
"#00DDFF Card IDentification:#\n" "#00DDFF Card IDentification:#\n"
"Vendor ID:\n" "Vendor ID:\n"
"OEM ID:\n"
"Model:\n" "Model:\n"
"OEM ID:\n"
"HW rev:\n" "HW rev:\n"
"FW rev:\n" "FW rev:\n"
"S/N:\n" "S/N:\n"
@@ -1614,10 +1754,11 @@ static lv_res_t _create_window_sdcard_info_status(lv_obj_t *btn)
break; 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", 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.oemid >> 8) & 0xFF, sd_storage.cid.oemid & 0xFF, 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[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.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.hwrev, sd_storage.cid.fwrev, sd_storage.cid.serial,
sd_storage.cid.month, sd_storage.cid.year); sd_storage.cid.month, sd_storage.cid.year);
@@ -1686,7 +1827,7 @@ static lv_res_t _create_window_sdcard_info_status(lv_obj_t *btn)
} }
bool uhs_au_mb = false; 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) if (uhs_au_size >= 1024)
{ {
uhs_au_mb = true; uhs_au_mb = true;

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 * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@@ -842,10 +842,10 @@ disabled:;
// Check if pairing info was found. // Check if pairing info was found.
if (joycon_found == 2) 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 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; success = false;
} }

View File

@@ -1,6 +1,6 @@
/* /*
* Copyright (c) 2018 naehrwert * 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 * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@@ -71,18 +71,16 @@ static lv_obj_t *_create_container(lv_obj_t *parent)
bool get_autorcm_status(bool change) bool get_autorcm_status(bool change)
{ {
u8 corr_mod0, mod1; u8 corr_mod0, mod1;
sdmmc_storage_t storage;
sdmmc_t sdmmc;
bool enabled = false; bool enabled = false;
if (h_cfg.t210b01) if (h_cfg.t210b01)
return false; 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); u8 *tempbuf = (u8 *)malloc(0x200);
sdmmc_storage_set_mmc_partition(&storage, EMMC_BOOT0); sdmmc_storage_set_mmc_partition(&emmc_storage, EMMC_BOOT0);
sdmmc_storage_read(&storage, 0x200 / NX_EMMC_BLOCKSIZE, 1, tempbuf); sdmmc_storage_read(&emmc_storage, 0x200 / NX_EMMC_BLOCKSIZE, 1, tempbuf);
// Get the correct RSA modulus byte masks. // Get the correct RSA modulus byte masks.
nx_emmc_get_autorcm_masks(&corr_mod0, &mod1); nx_emmc_get_autorcm_masks(&corr_mod0, &mod1);
@@ -103,20 +101,20 @@ bool get_autorcm_status(bool change)
for (i = 0; i < 4; i++) for (i = 0; i < 4; i++)
{ {
sect = (0x200 + (0x4000 * i)) / NX_EMMC_BLOCKSIZE; sect = (0x200 + (0x4000 * i)) / NX_EMMC_BLOCKSIZE;
sdmmc_storage_read(&storage, sect, 1, tempbuf); sdmmc_storage_read(&emmc_storage, sect, 1, tempbuf);
if (!enabled) if (!enabled)
tempbuf[0x10] = 0; tempbuf[0x10] = 0;
else else
tempbuf[0x10] = corr_mod0; tempbuf[0x10] = corr_mod0;
sdmmc_storage_write(&storage, sect, 1, tempbuf); sdmmc_storage_write(&emmc_storage, sect, 1, tempbuf);
} }
enabled = !(enabled); enabled = !(enabled);
} }
out: out:
free(tempbuf); free(tempbuf);
sdmmc_storage_end(&storage); sdmmc_storage_end(&emmc_storage);
return enabled; return enabled;
} }
@@ -607,7 +605,7 @@ void nyx_run_ums(void *param)
u32 *cfg = (u32 *)param; u32 *cfg = (u32 *)param;
u8 type = (*cfg) >> 24; u8 type = (*cfg) >> 24;
*cfg = *cfg & 0xFFFFFF; *cfg = *cfg & (~NYX_CFG_EXTRA);
// Disable read only flag. // Disable read only flag.
usb_msc_emmc_read_only = false; usb_msc_emmc_read_only = false;
@@ -1095,19 +1093,14 @@ static lv_res_t _create_window_dump_pk12_tool(lv_obj_t *btn)
char *txt_buf = (char *)malloc(0x4000); char *txt_buf = (char *)malloc(0x4000);
tsec_ctxt_t tsec_ctxt; if (!sdmmc_storage_init_mmc(&emmc_storage, &emmc_sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400))
sdmmc_storage_t storage;
sdmmc_t sdmmc;
if (!sdmmc_storage_init_mmc(&storage, &sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400))
{ {
lv_label_set_text(lb_desc, "#FFDD00 Failed to init eMMC!#"); lv_label_set_text(lb_desc, "#FFDD00 Failed to init eMMC!#");
goto out_free; goto out_free;
} }
sdmmc_storage_set_mmc_partition(&storage, EMMC_BOOT0); sdmmc_storage_set_mmc_partition(&emmc_storage, EMMC_BOOT0);
// Read package1. // Read package1.
static const u32 BOOTLOADER_SIZE = 0x40000; 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); char *build_date = malloc(32);
u32 pk1_offset = h_cfg.t210b01 ? sizeof(bl_hdr_t210b01_t) : 0; // Skip T210B01 OEM header. 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); 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. // Dump package1 in its encrypted state if unknown.
if (!pkg1_id) 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); lv_label_set_text(lb_desc, txt_buf);
manual_system_maintenance(true); 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)) if (sd_save_to_file(pkg1, BOOTLOADER_SIZE, path))
goto out_free; 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) if (!h_cfg.se_keygen_done)
{ {
tsec_ctxt_t tsec_ctxt;
tsec_ctxt.fw = (void *)(pkg1 + pkg1_id->tsec_off); tsec_ctxt.fw = (void *)(pkg1 + pkg1_id->tsec_off);
tsec_ctxt.pkg1 = (void *)pkg1; tsec_ctxt.pkg1 = (void *)pkg1;
tsec_ctxt.pkg11_off = pkg1_id->pkg11_off; 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; h_cfg.sept_run = true;
else 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 = 0;
b_cfg->autoboot_list = 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)) 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. // Read keyblob.
u8 *keyblob = (u8 *)calloc(NX_EMMC_BLOCKSIZE, 1); 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. // Decrypt.
hos_keygen(keyblob, kb, &tsec_ctxt); 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); manual_system_maintenance(true);
// Dump package1.1. // 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)) if (sd_save_to_file(pkg1, 0x40000, path))
goto out_free; goto out_free;
strcat(txt_buf, "pkg1 dumped to pkg1_decr.bin\n"); 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); manual_system_maintenance(true);
// Dump nxbootloader. // 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)) if (sd_save_to_file(loader, hdr_pk11->ldr_size, path))
goto out_free; goto out_free;
strcat(txt_buf, "NX Bootloader dumped to nxloader.bin\n"); 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); manual_system_maintenance(true);
// Dump secmon. // 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)) if (sd_save_to_file(secmon, hdr_pk11->sm_size, path))
goto out_free; goto out_free;
strcat(txt_buf, "Secure Monitor dumped to secmon.bin\n"); 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); manual_system_maintenance(true);
// Dump warmboot. // 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)) if (sd_save_to_file(warmboot, hdr_pk11->wb_size, path))
goto out_free; goto out_free;
// If T210B01, save a copy of decrypted warmboot binary also. // 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_iv_clear(13);
se_aes_crypt_cbc(13, 0, warmboot + 0x330, hdr_pk11->wb_size - 0x330, warmboot + 0x330, hdr_pk11->wb_size - 0x330); 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)) if (sd_save_to_file(warmboot, hdr_pk11->wb_size, path))
goto out_free; goto out_free;
} }
@@ -1273,10 +1281,10 @@ static lv_res_t _create_window_dump_pk12_tool(lv_obj_t *btn)
} }
// Dump package2.1. // Dump package2.1.
sdmmc_storage_set_mmc_partition(&storage, EMMC_GPP); sdmmc_storage_set_mmc_partition(&emmc_storage, EMMC_GPP);
// Parse eMMC GPT. // Parse eMMC GPT.
LIST_INIT(gpt); LIST_INIT(gpt);
nx_emmc_gpt_parse(&gpt, &storage); nx_emmc_gpt_parse(&gpt, &emmc_storage);
// Find package2 partition. // Find package2 partition.
emmc_part_t *pkg2_part = nx_emmc_part_find(&gpt, "BCPKG2-1-Normal-Main"); emmc_part_t *pkg2_part = nx_emmc_part_find(&gpt, "BCPKG2-1-Normal-Main");
if (!pkg2_part) 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. // Read in package2 header and get package2 real size.
u8 *tmp = (u8 *)malloc(NX_EMMC_BLOCKSIZE); 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 *hdr_pkg2_raw = (u32 *)(tmp + 0x100);
u32 pkg2_size = hdr_pkg2_raw[0] ^ hdr_pkg2_raw[2] ^ hdr_pkg2_raw[3]; u32 pkg2_size = hdr_pkg2_raw[0] ^ hdr_pkg2_raw[2] ^ hdr_pkg2_raw[3];
free(tmp); free(tmp);
// Read in package2. // Read in package2.
u32 pkg2_size_aligned = ALIGN(pkg2_size, NX_EMMC_BLOCKSIZE); u32 pkg2_size_aligned = ALIGN(pkg2_size, NX_EMMC_BLOCKSIZE);
pkg2 = malloc(pkg2_size_aligned); 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); pkg2_size_aligned / NX_EMMC_BLOCKSIZE, pkg2);
#if 0 #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)) if (sd_save_to_file(pkg2, pkg2_size_aligned, path))
goto out; goto out;
gfx_puts("\npkg2 dumped to pkg2_encr.bin\n"); 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); manual_system_maintenance(true);
// Dump pkg2.1. // 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)) if (sd_save_to_file(pkg2, pkg2_hdr->sec_size[PKG2_SEC_KERNEL] + pkg2_hdr->sec_size[PKG2_SEC_INI1], path))
goto out; goto out;
strcat(txt_buf, "pkg2 dumped to pkg2_decr.bin\n"); 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); manual_system_maintenance(true);
// Dump kernel. // 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)) if (sd_save_to_file(pkg2_hdr->data, pkg2_hdr->sec_size[PKG2_SEC_KERNEL], path))
goto out; goto out;
strcat(txt_buf, "Kernel dumped to kernel.bin\n"); 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); 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)) if (sd_save_to_file(ini1, ini1_size, path))
goto out; 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; 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)) if (sd_save_to_file(kip1, kip1_size, path))
{ {
free(kip_buffer); free(kip_buffer);
@@ -1409,7 +1417,7 @@ out_free:
free(loader); free(loader);
free(pkg2); free(pkg2);
free(txt_buf); free(txt_buf);
sdmmc_storage_end(&storage); sdmmc_storage_end(&emmc_storage);
sd_unmount(); sd_unmount();
if (kb >= KB_FIRMWARE_VERSION_620) if (kb >= KB_FIRMWARE_VERSION_620)
@@ -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_label_set_static_text(label_sep, "");
lv_obj_t *label_txt3 = lv_label_create(h2, NULL); 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_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); 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); 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); 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); lv_obj_t *btn3 = lv_btn_create(h2, NULL);
if (hekate_bg) 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); label_btn = lv_label_create(btn3, NULL);
lv_btn_set_fit(btn3, true, true); 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_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_obj_t *label_txt4 = lv_label_create(h2, NULL);
lv_label_set_recolor(label_txt4, true); lv_label_set_recolor(label_txt4, true);
lv_label_set_static_text(label_txt4, lv_label_set_static_text(label_txt4,
"Allows you to dump and decrypt pkg1 and pkg2 and further\n" "Allows you to partition the SD Card for using it with #C7EA46 emuMMC#,\n"
"split it up into their individual parts. It also dumps the kip1.\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_set_style(label_txt4, &hint_small_style);
lv_obj_align(label_txt4, btn3, LV_ALIGN_OUT_BOTTOM_LEFT, 0, LV_DPI / 3); lv_obj_align(label_txt4, btn3, LV_ALIGN_OUT_BOTTOM_LEFT, 0, LV_DPI / 3);
@@ -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_label_set_static_text(label_sep, "");
lv_obj_align(label_sep, label_txt4, LV_ALIGN_OUT_BOTTOM_LEFT, 0, LV_DPI * 11 / 7); 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); lv_obj_t *btn4 = lv_btn_create(h2, btn);
label_btn = lv_label_create(btn4, NULL); 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_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); label_txt2 = lv_label_create(h2, NULL);
lv_label_set_recolor(label_txt2, true); lv_label_set_recolor(label_txt2, true);
lv_label_set_static_text(label_txt2, lv_label_set_static_text(label_txt2,
"Allows you to partition the SD Card for using it with #C7EA46 emuMMC#,\n" "Allows you to dump and decrypt pkg1 and pkg2 and further\n"
"#C7EA46 Android# and #C7EA46 Linux#. You can also flash Linux and Android."); "split it up into their individual parts. It also dumps the kip1.");
lv_obj_set_style(label_txt2, &hint_small_style); lv_obj_set_style(label_txt2, &hint_small_style);
lv_obj_align(label_txt2, btn4, LV_ALIGN_OUT_BOTTOM_LEFT, 0, LV_DPI / 3); 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_sliding(tv, false);
lv_tabview_set_btns_pos(tv, LV_TABVIEW_BTNS_POS_BOTTOM); 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 *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" Partitions"); 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); lv_obj_t *line_sep = lv_line_create(tv, NULL);
static const lv_point_t line_pp[] = { {0, 0}, { 0, LV_DPI / 4} }; 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 * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@@ -48,6 +48,8 @@ typedef struct _partition_ctxt_t
u32 l4t_size; u32 l4t_size;
u32 and_size; u32 and_size;
bool emu_double;
mbr_t *mbr_old; mbr_t *mbr_old;
lv_obj_t *bar_hos; lv_obj_t *bar_hos;
@@ -244,26 +246,20 @@ static void _prepare_and_flash_mbr_gpt()
if (part_info.l4t_size && !part_info.and_size) if (part_info.l4t_size && !part_info.and_size)
{ {
mbr.partitions[mbr_idx].type = 0x83; // Linux system partition. 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; 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. sdmmc_storage_write(&sd_storage, mbr.partitions[mbr_idx].start_sct, 0x800, (void *)SDMMC_UPPER_BUFFER); // Clear the first 1MB.
mbr_idx++; mbr_idx++;
} }
// emuMMC goes second or third. Next to L4T if no Android. // emuMMC goes second or third. Next to L4T if no Android.
bool double_emummc = part_info.emu_size > 29856;
if (part_info.emu_size) if (part_info.emu_size)
{ {
mbr.partitions[mbr_idx].type = 0xE0; // emuMMC partition. 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.emu_double)
{ mbr.partitions[mbr_idx].size_sct = (part_info.emu_size << 11) - 0x800; // Reserve 1MB.
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.
}
else else
{ {
mbr.partitions[mbr_idx].type = 0xE0; // emuMMC partition. mbr.partitions[mbr_idx].type = 0xE0; // emuMMC partition.
@@ -272,10 +268,7 @@ static void _prepare_and_flash_mbr_gpt()
// 2nd emuMMC. // 2nd emuMMC.
mbr.partitions[mbr_idx].start_sct = mbr.partitions[mbr_idx - 1].start_sct + (part_info.emu_size << 10); 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) - 0x800; // Reserve 1MB.
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_idx++; mbr_idx++;
} }
@@ -315,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); 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; 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 }; 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) if (part_info.l4t_size)
{ {
@@ -440,14 +433,14 @@ static void _prepare_and_flash_mbr_gpt()
se_gen_prng128(random_number); se_gen_prng128(random_number);
memcpy(gpt.entries[gpt_idx].part_guid, random_number, 16); memcpy(gpt.entries[gpt_idx].part_guid, random_number, 16);
gpt.entries[gpt_idx].lba_start = curr_part_lba; 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. gpt.entries[gpt_idx].lba_end = curr_part_lba + (part_info.emu_size << 11) - 0x800 - 1; // Reserve 1MB.
else 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); memcpy(gpt.entries[gpt_idx].name, (char[]) { 'e', 0, 'm', 0, 'u', 0, 'm', 0, 'm', 0, 'c', 0 }, 12);
gpt_idx++; gpt_idx++;
if (double_emummc) if (part_info.emu_double)
{ {
curr_part_lba += (part_info.emu_size << 10); curr_part_lba += (part_info.emu_size << 10);
memcpy(gpt.entries[gpt_idx].type_guid, emu_part_guid, 16); memcpy(gpt.entries[gpt_idx].type_guid, emu_part_guid, 16);
@@ -1292,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_style(dark_bg, &mbox_darken);
lv_obj_set_size(dark_bg, LV_HOR_RES, LV_VER_RES); 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_map1[] = { "\222SD UMS", "\222Flash Linux", "\222Flash Android", "\221OK", "" };
static const char *mbox_btn_map2[] = { "\222SD UMS", "\222Flash Linux", "\221OK", "" }; static const char *mbox_btn_map2[] = { "\222SD UMS", "\222Flash Linux", "\221OK", "" };
static const char *mbox_btn_map3[] = { "\222SD UMS", "\222Flash Android", "\221OK", "" }; static const char *mbox_btn_map3[] = { "\222SD UMS", "\222Flash Android", "\221OK", "" };
@@ -1373,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_label_set_text(lbl_paths[0], "Please wait...");
lv_obj_align(mbox, NULL, LV_ALIGN_CENTER, 0, 0); lv_obj_align(mbox, NULL, LV_ALIGN_CENTER, 0, 0);
manual_system_maintenance(true); manual_system_maintenance(true);
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!"); lv_label_set_text(lbl_status, "#FFDD00 Error:# Failed to initialize Ramdisk!");
goto error; goto error;
@@ -1628,9 +1621,16 @@ static lv_res_t _create_mbox_partitioning_next(lv_obj_t *btn)
s_printf(txt_buf, "#FFDD00 Warning: This will partition the SD Card!#\n\n"); s_printf(txt_buf, "#FFDD00 Warning: This will partition the SD Card!#\n\n");
if (part_info.backup_possible) if (part_info.backup_possible)
strcat(txt_buf, "#C7EA46 Your files will be backed up and restored!#\n#FFDD00Any other partition will be wiped!#"); {
strcat(txt_buf, "#C7EA46 Your files will be backed up and restored!#\n"
"#FFDD00 Any other partition will be wiped!#");
}
else else
strcat(txt_buf, "#FFDD00 Your files will be wiped!#\n#FFDD00 Use USB UMS to copy them over!#"); {
strcat(txt_buf, "#FFDD00 Your files will be wiped!#\n"
"#FFDD00 Any other partition will be also wiped!#\n"
"#FFDD00 Use USB UMS to copy them over!#");
}
lv_label_set_text(lbl_status, txt_buf); lv_label_set_text(lbl_status, txt_buf);
@@ -1677,12 +1677,33 @@ static void _update_partition_bar()
static lv_res_t _action_slider_emu(lv_obj_t *slider) static lv_res_t _action_slider_emu(lv_obj_t *slider)
{ {
u32 size;
char lbl_text[64]; char lbl_text[64];
bool prev_emu_double = part_info.emu_double;
int slide_val = lv_slider_get_value(slider); int slide_val = lv_slider_get_value(slider);
u32 size = slide_val ? ((slide_val < 2) ? 29856 : 59712) : 0; const u32 rsvd_mb = 4 + 4 + 16 + 8; // BOOT0 + BOOT1 + 16MB offset + 8MB alignment.
s32 hos_size = (part_info.total_sct >> 11) - 16 - size - part_info.l4t_size - part_info.and_size;
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) if (hos_size > 2048)
{ {
part_info.emu_size = size; part_info.emu_size = size;
@@ -1692,28 +1713,40 @@ static lv_res_t _action_slider_emu(lv_obj_t *slider)
lv_label_set_text(part_info.lbl_hos, lbl_text); lv_label_set_text(part_info.lbl_hos, lbl_text);
lv_bar_set_value(part_info.slider_bar_hos, hos_size >> 10); lv_bar_set_value(part_info.slider_bar_hos, hos_size >> 10);
if (slide_val < 2) if (!part_info.emu_double)
s_printf(lbl_text, "#FF3C28 %d GiB#", size >> 10); {
if (slide_val != 10)
s_printf(lbl_text, "#FF3C28 %d GiB#", size >> 10);
else
s_printf(lbl_text, "#FF3C28 %d FULL#", size >> 10);
}
else 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); lv_label_set_text(part_info.lbl_emu, lbl_text);
} }
else else
{ {
int new_slider_val; u32 emu_size = part_info.emu_size;
switch (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: if (prev_emu_double)
new_slider_val = 1; emu_size /= 2;
break; emu_size -= rsvd_mb;
case 59712: emu_size /= 1024;
new_slider_val = 2; emu_size -= 3;
break;
case 0: if (prev_emu_double)
default: emu_size += 11;
new_slider_val = 0;
break;
} }
int new_slider_val = emu_size;
part_info.emu_double = prev_emu_double ? true : false;
lv_slider_set_value(slider, new_slider_val); lv_slider_set_value(slider, new_slider_val);
} }
@@ -1883,7 +1916,8 @@ static void create_mbox_check_files_total_size()
else else
{ {
lv_mbox_set_text(mbox, lv_mbox_set_text(mbox,
"#FFDD00 The SD Card cannot be backed up!#\n\n" "#FFDD00 The SD Card cannot be backed up!#\n"
"#FFDD00 Any other partition will be also wiped!#\n\n"
"You will be asked to back up your files later via UMS."); "You will be asked to back up your files later via UMS.");
} }
@@ -1996,7 +2030,8 @@ static lv_res_t _action_fix_mbr(lv_obj_t *btn)
lv_obj_t *lbl_status = lv_label_create(mbox, NULL); lv_obj_t *lbl_status = lv_label_create(mbox, NULL);
lv_label_set_recolor(lbl_status, true); 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!#"); lv_label_set_text(lbl_status, "#FFDD00 Failed to init SD!#");
goto out; goto out;
@@ -2317,7 +2352,7 @@ lv_res_t create_window_partition_manager(lv_obj_t *btn)
lv_obj_t *slider_emu = lv_slider_create(h1, NULL); lv_obj_t *slider_emu = lv_slider_create(h1, NULL);
lv_obj_set_size(slider_emu, LV_DPI * 7, LV_DPI / 3); 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_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_BG, &bar_emu_bg);
lv_slider_set_style(slider_emu, LV_SLIDER_STYLE_INDIC, &bar_emu_ind); lv_slider_set_style(slider_emu, LV_SLIDER_STYLE_INDIC, &bar_emu_ind);
@@ -2374,9 +2409,9 @@ lv_res_t create_window_partition_manager(lv_obj_t *btn)
lv_label_set_recolor(lbl_notes, true); lv_label_set_recolor(lbl_notes, true);
lv_label_set_static_text(lbl_notes, 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 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 2: Resized emuMMC formats the USER partition. A save data manager can be used to move them over.\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 3: The #C7EA46 Flash Linux# and #C7EA46 Flash Android# will flash files if suitable partitions and installer files are found.\n"
"Note 4: #FFDD00 The installation files will be deleted after a successful flashing.#"); "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_label_set_style(lbl_notes, &hint_small_style);
lv_obj_align(lbl_notes, lbl_and, LV_ALIGN_OUT_BOTTOM_LEFT, 0, LV_DPI / 5); lv_obj_align(lbl_notes, lbl_and, LV_ALIGN_OUT_BOTTOM_LEFT, 0, LV_DPI / 5);

View File

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

View File

@@ -1,6 +1,6 @@
/* /*
* Copyright (c) 2018 naehrwert * Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2020 CTCaer * Copyright (c) 2018-2021 CTCaer
* Copyright (c) 2018 M4xw * Copyright (c) 2018 M4xw
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
@@ -62,7 +62,7 @@ void gfx_con_setpos(u32 x, u32 y);
void gfx_putc(char c); void gfx_putc(char c);
void gfx_puts(char *s); void gfx_puts(char *s);
void gfx_printf(const char *fmt, ...); 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_set_pixel(u32 x, u32 y, u32 color);

View File

@@ -2,7 +2,7 @@
* Copyright (c) 2018 naehrwert * Copyright (c) 2018 naehrwert
* Copyright (c) 2018 st4rk * Copyright (c) 2018 st4rk
* Copyright (c) 2018 Ced2911 * Copyright (c) 2018 Ced2911
* Copyright (c) 2018-2020 CTCaer * Copyright (c) 2018-2021 CTCaer
* Copyright (c) 2018 balika011 * Copyright (c) 2018 balika011
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
@@ -45,7 +45,29 @@ extern hekate_config h_cfg;
static u8 *bis_keys = NULL; 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. { 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. { 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. { 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. { 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 }; { 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 }; { 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 }; { 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 }; { 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. { 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. { 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. { 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. { 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 }; { 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 }; { 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 }; { 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. { 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. { 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. { 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. { 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. { 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. { 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. { 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. { 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. { 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. { 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. { 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. { 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 }; { 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 }; { 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 }; { 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 }; { 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. { 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. { 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. { 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. // 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]; 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) if (update_eks)
{ {
// Read EKS blob. // Read EKS blob.
@@ -228,8 +252,8 @@ void hos_eks_save(u32 kb)
} }
// Get keys. // Get keys.
u8 *keys = (u8 *)calloc(0x1000, 1); u8 *keys = (u8 *)calloc(0x2000, 1);
se_get_aes_keys(keys + 0x800, keys, 0x10); se_get_aes_keys(keys + 0x1000, keys, SE_KEY_128_SIZE);
// Set magic and personalized info. // Set magic and personalized info.
h_cfg.eks->magic = HOS_EKS_MAGIC; 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); h_cfg.eks->lot0 = FUSE(FUSE_OPT_LOT_CODE_0);
// Copy new keys. // Copy new keys.
memcpy(h_cfg.eks->dkg, keys + 10 * 0x10, 0x10); memcpy(h_cfg.eks->dkg, keys + 10 * SE_KEY_128_SIZE, SE_KEY_128_SIZE);
memcpy(h_cfg.eks->dkk, keys + 15 * 0x10, 0x10); memcpy(h_cfg.eks->dkk, keys + 15 * SE_KEY_128_SIZE, SE_KEY_128_SIZE);
if (!h_cfg.aes_slots_new) 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].mkk, keys + 12 * SE_KEY_128_SIZE, SE_KEY_128_SIZE);
memcpy(h_cfg.eks->keys[key_idx].fdk, keys + 13 * 0x10, 0x10); memcpy(h_cfg.eks->keys[key_idx].fdk, keys + 13 * SE_KEY_128_SIZE, SE_KEY_128_SIZE);
} }
else // New sept slots. else // New sept slots.
{ {
memcpy(h_cfg.eks->keys[key_idx].mkk, keys + 13 * 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 * 0x10, 0x10); memcpy(h_cfg.eks->keys[key_idx].fdk, keys + 12 * SE_KEY_128_SIZE, SE_KEY_128_SIZE);
} }
// Encrypt EKS blob. // Encrypt EKS blob.
@@ -260,7 +284,6 @@ void hos_eks_save(u32 kb)
memcpy(mbr + 0x80, eks, sizeof(hos_eks_mbr_t)); memcpy(mbr + 0x80, eks, sizeof(hos_eks_mbr_t));
hos_eks_rw_try(mbr, true); hos_eks_rw_try(mbr, true);
free(eks); free(eks);
free(keys); free(keys);
out: out:
@@ -346,14 +369,14 @@ void hos_eks_bis_save()
h_cfg.eks->lot0 = FUSE(FUSE_OPT_LOT_CODE_0); h_cfg.eks->lot0 = FUSE(FUSE_OPT_LOT_CODE_0);
// Copy new keys. // Copy new keys.
memcpy(h_cfg.eks->bis_keys[0].crypt, bis_keys + (0 * 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 * 0x10), 0x10); 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].crypt, bis_keys + (2 * SE_KEY_128_SIZE), SE_KEY_128_SIZE);
memcpy(h_cfg.eks->bis_keys[1].tweak, bis_keys + (3 * 0x10), 0x10); 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].crypt, bis_keys + (4 * SE_KEY_128_SIZE), SE_KEY_128_SIZE);
memcpy(h_cfg.eks->bis_keys[2].tweak, bis_keys + (5 * 0x10), 0x10); memcpy(h_cfg.eks->bis_keys[2].tweak, bis_keys + (5 * SE_KEY_128_SIZE), SE_KEY_128_SIZE);
// Encrypt EKS blob. // Encrypt EKS blob.
u8 *eks = calloc(512 , 1); u8 *eks = calloc(512 , 1);
@@ -418,10 +441,11 @@ int hos_keygen_t210b01(u32 kb)
return 1; 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; u32 retries = 0;
tsec_keys_t tsec_keys;
kb_t *kb_data = (kb_t *)keyblob;
if (kb > KB_FIRMWARE_VERSION_MAX) if (kb > KB_FIRMWARE_VERSION_MAX)
return 0; return 0;
@@ -449,9 +473,9 @@ int hos_keygen(u8 *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt)
// Get TSEC key. // Get TSEC key.
if (kb <= KB_FIRMWARE_VERSION_620) 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++; retries++;
// We rely on racing conditions, make sure we cover even the unluckiest cases. // We rely on racing conditions, make sure we cover even the unluckiest cases.
@@ -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) if (h_cfg.eks && h_cfg.eks->enabled[key_idx] >= kb)
{ {
// Set Device keygen key to slot 10. // 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. // 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. // 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. // 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 else
h_cfg.aes_slots_new = se_key_acc_ctrl_get(12) == 0x6A; 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) else if (kb == KB_FIRMWARE_VERSION_620)
{ {
// Set TSEC key. // 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. // 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 // Decrypt keyblob and set keyslots
se_aes_crypt_block_ecb(12, 0, tmp + 0x20, keyblob_keyseeds[0]); se_aes_crypt_block_ecb(12, 0, tsec_keys.tmp, keyblob_keyseeds[0]);
se_aes_unwrap_key(15, 14, tmp + 0x20); se_aes_unwrap_key(15, 14, tsec_keys.tmp);
se_aes_unwrap_key(10, 15, console_keyseed_4xx_5xx); se_aes_unwrap_key(10, 15, console_keyseed_4xx_5xx);
se_aes_unwrap_key(15, 15, console_keyseed); 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 else
{ {
// Set TSEC key. // 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. // Derive keyblob keys from TSEC+SBK.
se_aes_crypt_block_ecb(13, 0, tmp, keyblob_keyseeds[0]); se_aes_crypt_block_ecb(13, 0, tsec_keys.tsec, keyblob_keyseeds[0]);
se_aes_unwrap_key(15, 14, tmp); se_aes_unwrap_key(15, 14, tsec_keys.tsec);
se_aes_crypt_block_ecb(13, 0, tmp, keyblob_keyseeds[kb]); se_aes_crypt_block_ecb(13, 0, tsec_keys.tsec, keyblob_keyseeds[kb]);
se_aes_unwrap_key(13, 14, tmp); se_aes_unwrap_key(13, 14, tsec_keys.tsec);
// Clear SBK. // 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); // Verify keyblob CMAC.
//se_aes_cmac(tmp, 0x10, 11, keyblob + 0x10, 0xA0); u8 cmac[SE_KEY_128_SIZE];
//if (!memcmp(keyblob, tmp, 0x10)) se_aes_unwrap_key(11, 13, cmac_keyseed);
// return 0; 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); se_aes_unwrap_key(11, 13, cmac_keyseed);
// Decrypt keyblob and set keyslots. // Decrypt keyblob and set keyslots.
se_aes_crypt_ctr(13, keyblob + 0x20, 0x90, keyblob + 0x20, 0x90, keyblob + 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, keyblob + 0x20 + 0x80, 0x10); // Package1 key. se_aes_key_set(11, kb_data->keys.package1_key, SE_KEY_128_SIZE);
se_aes_key_set(12, keyblob + 0x20, 0x10); se_aes_key_set(12, kb_data->keys.master_keyseed, SE_KEY_128_SIZE);
se_aes_key_set(13, keyblob + 0x20, 0x10); 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) switch (kb)
{ {
@@ -547,14 +575,16 @@ int hos_keygen(u8 *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt)
case KB_FIRMWARE_VERSION_400: case KB_FIRMWARE_VERSION_400:
se_aes_unwrap_key(13, 15, console_keyseed_4xx_5xx); se_aes_unwrap_key(13, 15, console_keyseed_4xx_5xx);
se_aes_unwrap_key(15, 15, console_keyseed); se_aes_unwrap_key(15, 15, console_keyseed);
se_aes_unwrap_key(14, 12, master_keyseed_4xx_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); se_aes_unwrap_key(12, 12, master_keyseed_retail);
break; break;
case KB_FIRMWARE_VERSION_500: case KB_FIRMWARE_VERSION_500:
case KB_FIRMWARE_VERSION_600: case KB_FIRMWARE_VERSION_600:
se_aes_unwrap_key(10, 15, console_keyseed_4xx_5xx); se_aes_unwrap_key(10, 15, console_keyseed_4xx_5xx);
se_aes_unwrap_key(15, 15, console_keyseed); se_aes_unwrap_key(15, 15, console_keyseed);
se_aes_unwrap_key(14, 12, master_keyseed_4xx_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); se_aes_unwrap_key(12, 12, master_keyseed_retail);
break; 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) static void _hos_validate_sept_mkey(u32 kb)
{ {
u8 tmp_mkey[0x10]; u8 tmp_mkey[SE_KEY_128_SIZE];
u32 mkey_idx = sizeof(mkey_vectors) / 0x10; u32 mkey_idx = sizeof(mkey_vectors) / SE_KEY_128_SIZE;
u8 mkey_slot = !h_cfg.aes_slots_new ? 12 : 13; u8 mkey_slot = !h_cfg.aes_slots_new ? 12 : 13;
do do
{ {
mkey_idx--; 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++) for (u32 idx = 0; idx < mkey_idx; idx++)
{ {
se_aes_key_clear(2); se_aes_key_clear(2);
se_aes_key_set(2, tmp_mkey, 0x10); se_aes_key_set(2, tmp_mkey, SE_KEY_128_SIZE);
se_aes_crypt_ecb(2, 0, tmp_mkey, 0x10, mkey_vectors[mkey_idx - 1 - idx], 0x10); 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)) 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) static void _hos_bis_print_key(u32 idx, u8 *key)
{ {
gfx_printf("BIS %d Crypt: ", idx); gfx_printf("BIS %d Crypt: ", idx);
for (int i = 0; i < 0x10; i++) for (int i = 0; i < SE_KEY_128_SIZE; i++)
gfx_printf("%02X", key[((idx * 2 + 0) * 0x10) + i]); gfx_printf("%02X", key[((idx * 2 + 0) * SE_KEY_128_SIZE) + i]);
gfx_puts("\n"); gfx_puts("\n");
gfx_printf("BIS %d Tweak: ", idx); gfx_printf("BIS %d Tweak: ", idx);
for (int i = 0; i < 0x10; i++) for (int i = 0; i < SE_KEY_128_SIZE; i++)
gfx_printf("%02X", key[((idx * 2 + 1) * 0x10) + i]); gfx_printf("%02X", key[((idx * 2 + 1) * SE_KEY_128_SIZE) + i]);
gfx_puts("\n"); 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 keygen_rev = 0;
u32 console_key_slot = kb >= KB_FIRMWARE_VERSION_400 ? 15 : 13; u32 console_key_slot = kb >= KB_FIRMWARE_VERSION_400 ? 15 : 13;
if (!bis_keys) 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) 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) if (keygen_rev)
{ {
u8 tmp_mkey[0x10]; u8 tmp_mkey[SE_KEY_128_SIZE];
u32 mkey_idx = sizeof(mkey_vectors) / 0x10; 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); u8 mkey_slot = kb >= KB_FIRMWARE_VERSION_700 ? (!h_cfg.aes_slots_new ? 12 : 13) : (kb == KB_FIRMWARE_VERSION_620 ? 9 : 12);
// Keygen revision uses bootloader version, which starts from 1. // Keygen 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 do
{ {
mkey_idx--; 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++) for (u32 idx = 0; idx < mkey_idx; idx++)
{ {
se_aes_key_clear(2); se_aes_key_clear(2);
se_aes_key_set(2, tmp_mkey, 0x10); se_aes_key_set(2, tmp_mkey, SE_KEY_128_SIZE);
se_aes_crypt_ecb(2, 0, tmp_mkey, 0x10, mkey_vectors[mkey_idx - 1 - idx], 0x10); 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)); } while (memcmp(tmp_mkey, "\x00\x00\x00\x00\x00\x00\x00\x00", 8) != 0 && (mkey_idx - 1));
// Derive new device key. // Derive new device key.
se_aes_key_clear(1); se_aes_key_clear(1);
se_aes_unwrap_key(1, 10, new_console_keyseed[keygen_rev]); // Uses Device key 4x. 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, 2, new_console_kekseed[keygen_rev]); // Uses Master Key 0.
se_aes_unwrap_key(1, 1, tmp_mkey); 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); se_aes_unwrap_key(2, console_key_slot, gen_keyseed_retail);
// Clear bis keys storage. // Clear bis keys storage.
memset(bis_keys, 0, 0x10 * 6); memset(bis_keys, 0, SE_KEY_128_SIZE * 6);
// Generate BIS 0 Keys. // 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 + (0 * SE_KEY_128_SIZE), 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 + (1 * SE_KEY_128_SIZE), bis_keyseed[1]);
// Generate generic kek. // Generate generic kek.
se_aes_key_clear(2); 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); se_aes_unwrap_key(2, 2, gen_keyseed);
// Generate BIS 1 Keys. // 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 + (2 * SE_KEY_128_SIZE), 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 + (3 * SE_KEY_128_SIZE), bis_keyseed[3]);
// Generate BIS 2/3 Keys. // 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 + (4 * SE_KEY_128_SIZE), 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 + (5 * SE_KEY_128_SIZE), bis_keyseed[5]);
if (!h_cfg.t210b01 && kb >= KB_FIRMWARE_VERSION_700) if (!h_cfg.t210b01 && kb >= KB_FIRMWARE_VERSION_700)
_hos_validate_sept_mkey(kb); _hos_validate_sept_mkey(kb);
} }
else else
{ {
memcpy(bis_keys + (0 * 0x10), h_cfg.eks->bis_keys[0].crypt, 0x10); memcpy(bis_keys + (0 * SE_KEY_128_SIZE), h_cfg.eks->bis_keys[0].crypt, SE_KEY_128_SIZE);
memcpy(bis_keys + (1 * 0x10), h_cfg.eks->bis_keys[0].tweak, 0x10); 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 + (2 * SE_KEY_128_SIZE), h_cfg.eks->bis_keys[1].crypt, SE_KEY_128_SIZE);
memcpy(bis_keys + (3 * 0x10), h_cfg.eks->bis_keys[1].tweak, 0x10); 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 + (4 * SE_KEY_128_SIZE), h_cfg.eks->bis_keys[2].crypt, SE_KEY_128_SIZE);
memcpy(bis_keys + (5 * 0x10), h_cfg.eks->bis_keys[2].tweak, 0x10); 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); _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); se_aes_key_clear(i);
// Set BIS keys. // Set BIS keys.
se_aes_key_set(0, bis_keys + (0 * 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 * 0x10), 0x10); 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(2, bis_keys + (2 * SE_KEY_128_SIZE), SE_KEY_128_SIZE);
se_aes_key_set(3, bis_keys + (3 * 0x10), 0x10); 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(4, bis_keys + (4 * SE_KEY_128_SIZE), SE_KEY_128_SIZE);
se_aes_key_set(5, bis_keys + (5 * 0x10), 0x10); se_aes_key_set(5, bis_keys + (5 * SE_KEY_128_SIZE), SE_KEY_128_SIZE);
return 1; return 1;
} }
@@ -742,7 +772,7 @@ void hos_bis_keys_clear()
FUSE(FUSE_PRIVATE_KEY3) FUSE(FUSE_PRIVATE_KEY3)
}; };
// Set SBK to slot 14. // 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. // Lock SBK from being read.
se_key_acc_ctrl(14, SE_KEY_TBL_DIS_KEYREAD_FLAG); se_key_acc_ctrl(14, SE_KEY_TBL_DIS_KEYREAD_FLAG);

View File

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

View File

@@ -24,6 +24,7 @@
#include <libs/fatfs/ff.h> #include <libs/fatfs/ff.h>
#include <mem/heap.h> #include <mem/heap.h>
#include <sec/se.h> #include <sec/se.h>
#include <sec/se_t210.h>
#include <libs/compr/blz.h> #include <libs/compr/blz.h>
#include <gfx_utils.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; 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) // 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 }, { 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) 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. // 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. // Set and unwrap pkg2 key.
se_aes_key_clear(9); 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); se_aes_unwrap_key(9, 9, package2_keyseed);
// Decrypt header. // Decrypt header.
@@ -158,9 +159,9 @@ pkg2_hdr_t *pkg2_decrypt(void *data, u8 kb)
// Decrypt older pkg2 via new mkeys. // Decrypt older pkg2 via new mkeys.
if ((kb >= KB_FIRMWARE_VERSION_810) && (kb < KB_FIRMWARE_VERSION_MAX)) 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 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_idx = mkey_seeds_cnt; // Real index + 1.
u8 mkey_seeds_min_idx = mkey_seeds_cnt - (KB_FIRMWARE_VERSION_MAX - kb); 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. // Set current mkey in order to decrypt a lower mkey.
mkey_seeds_idx--; mkey_seeds_idx--;
se_aes_key_clear(9); 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. 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]) if (!hdr->sec_size[i])
continue; 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); //gfx_hexdump((u32)pdata, pdata, 0x100);
pdata += hdr->sec_size[i]; 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 * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@@ -68,72 +68,6 @@ extern volatile nyx_storage_t *nyx_str;
extern bool is_ipl_updated(void *buf); extern bool is_ipl_updated(void *buf);
extern void reloc_patcher(u32 payload_dst, u32 payload_src, u32 payload_size); 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) int reboot_to_sept(const u8 *tsec_fw, u32 kb)
{ {
FIL fp; 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 * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@@ -19,7 +19,8 @@
#include <utils/types.h> #include <utils/types.h>
void check_sept(); #define SEPT_PRI_ENTRY 0x40010340
int reboot_to_sept(const u8 *tsec_fw, u32 kb); int reboot_to_sept(const u8 *tsec_fw, u32 kb);
#endif #endif

View File

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

View File

@@ -41,16 +41,25 @@
#define FF_USE_MKFS 1 #define FF_USE_MKFS 1
/* This option switches f_mkfs() function. (0:Disable or 1:Enable) */ /* 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 #define FF_USE_FASTSEEK 0
/* This option switches fast seek function. (0:Disable or 1:Enable) */ /* This option switches fast seek function. (0:Disable or 1:Enable) */
#define FF_FASTFS 1 #define FF_FASTFS 1
#if FF_FASTFS #if FF_FASTFS
#undef FF_USE_FASTSEEK #undef FF_USE_FASTSEEK
#define FF_USE_FASTSEEK 1 #define FF_USE_FASTSEEK 1
#endif #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 #define FF_USE_EXPAND 0
@@ -170,13 +179,13 @@
/ Drive/Volume Configurations / Drive/Volume Configurations
/---------------------------------------------------------------------------*/ /---------------------------------------------------------------------------*/
#define FF_VOLUMES 4 #define FF_VOLUMES 5
/* Number of volumes (logical drives) to be used. (1-10) */ /* Number of volumes (logical drives) to be used. (1-10) */
#define FF_STR_VOLUME_ID 1 #define FF_STR_VOLUME_ID 1
// Order is important. Any change to order, must also be reflected to diskio drive enum. // 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. /* FF_STR_VOLUME_ID switches support for volume ID in arbitrary strings.
/ When FF_STR_VOLUME_ID is set to 1 or 2, arbitrary strings can be used as drive / When FF_STR_VOLUME_ID is set to 1 or 2, arbitrary strings can be used as drive
/ number in the path name. FF_VOLUME_STRS defines the volume ID strings for each / number in the path name. FF_VOLUME_STRS defines the volume ID strings for each
@@ -186,6 +195,7 @@
/ not defined, a user defined volume string table needs to be defined as: / not defined, a user defined volume string table needs to be defined as:
/ /
/ const char* VolumeStr[FF_VOLUMES] = {"ram","flash","sd","usb",... / 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_FS_NORTC 0
#define FF_NORTC_MON 1 #define FF_NORTC_MON 1
#define FF_NORTC_MDAY 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 /* The option FF_FS_NORTC switches timestamp function. If the system does not have
/ any RTC function or valid timestamp is not needed, set FF_FS_NORTC = 1 to disable / any RTC function or valid timestamp is not needed, set FF_FS_NORTC = 1 to disable
/ the timestamp function. Every object modified by FatFs will have a fixed timestamp / the timestamp function. Every object modified by FatFs will have a fixed timestamp

View File

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

View File

@@ -1,8 +1,8 @@
/* /*
* eMMC BIS driver for Nintendo Switch * eMMC BIS driver for Nintendo Switch
* *
* Copyright (c) 2019 shchmue * Copyright (c) 2019-2020 shchmue
* Copyright (c) 2019-2020 CTCaer * Copyright (c) 2019-2021 CTCaer
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@@ -21,48 +21,64 @@
#include <memory_map.h> #include <memory_map.h>
#include <mem/heap.h>
#include <sec/se.h> #include <sec/se.h>
#include <sec/se_t210.h>
#include "../storage/nx_emmc.h" #include "../storage/nx_emmc.h"
#include <storage/nx_sd.h>
#include <storage/sdmmc.h> #include <storage/sdmmc.h>
#include <utils/types.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 cluster_idx; // Index of the cluster in the partition.
u32 visit_cnt; bool dirty; // Has been modified without write-back flag.
u8 tweak[0x10]; u8 data[BIS_CLUSTER_SIZE]; // The cached cluster itself. Aligned to 8 bytes for DMA engine.
u8 data[0x200]; } cluster_cache_t;
u8 align[8];
} sector_cache_t;
static u8 ks_crypt = 0; typedef struct _bis_cache_t
static u8 ks_tweak = 0; {
static u32 sector_cache_cnt = 0; 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 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; 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; pdata[i] = (b << 1) | carry;
carry = b >> 7; carry = b >> 31;
} }
if (carry) if (carry)
pdata[0x0] ^= 0x87; 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; u32 *pdst = (u32 *)dst;
u8 *psrc = (u8 *)src; u32 *psrc = (u32 *)src;
u32 *ptweak = (u32 *)tweak;
if (regen_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; tweak[i] = sec & 0xFF;
sec >>= 8; 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; 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++) for (u32 i = 0; i < (tweak_exp << 5); i++)
_gf256_mul_x_le(tweak); _gf256_mul_x_le(tweak);
u8 tmp_tweak[0x10]; u8 orig_tweak[SE_KEY_128_SIZE] __attribute__((aligned(4)));
memcpy(tmp_tweak, tweak, 0x10); 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 i = 0; i < (sec_size >> 4); i++)
{ {
for (u32 j = 0; j < 0x10; j++) for (u32 j = 0; j < 4; j++)
pdst[j] = psrc[j] ^ tweak[j]; pdst[j] = psrc[j] ^ ptweak[j];
_gf256_mul_x_le(tweak); _gf256_mul_x_le(tweak);
psrc += 0x10; psrc += 4;
pdst += 0x10; 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 = (u32 *)dst;
ptweak = (u32 *)orig_tweak;
pdst = (u8 *)dst;
for (u32 i = 0; i < (sec_size >> 4); i++) for (u32 i = 0; i < (sec_size >> 4); i++)
{ {
for (u32 j = 0; j < 0x10; j++) for (u32 j = 0; j < 4; j++)
pdst[j] = pdst[j] ^ tweak[j]; pdst[j] = pdst[j] ^ ptweak[j];
_gf256_mul_x_le(tweak); _gf256_mul_x_le(orig_tweak);
pdst += 0x10; pdst += 4;
} }
return 1; 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_write(&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) static int nx_emmc_bis_read_block(u32 sector, u32 count, void *buff)
{ {
if (!system_part) if (!system_part)
return 3; // Not ready. return 3; // Not ready.
static u32 prev_cluster = -1; if (bis_cache->enabled)
static u32 prev_sector = 0; return nx_emmc_bis_read_block_cached(sector, count, buff);
static u8 tweak[0x10]; else
return nx_emmc_bis_read_block_normal(sector, count, buff);
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;
} }
int nx_emmc_bis_read(u32 sector, u32 count, void *buff) int nx_emmc_bis_read(u32 sector, u32 count, void *buff)
{ {
int res = 1;
u8 *buf = (u8 *)buff; u8 *buf = (u8 *)buff;
u32 curr_sct = sector; u32 curr_sct = sector;
while (count) while (count)
{ {
u32 sct_cnt = MIN(count, 0x20); u32 sct_cnt = MIN(count, BIS_CLUSTER_SECTORS);
res = nx_emmc_bis_read_block(curr_sct, sct_cnt, buf); if (nx_emmc_bis_read_block(curr_sct, sct_cnt, buf))
if (res) return 0;
return 1;
count -= sct_cnt; count -= sct_cnt;
curr_sct += 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; 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_crypt = 0;
ks_tweak = 1; ks_tweak = 1;
break; }
case 8: // SAFE. else if (!strcmp(part->name, "SAFE"))
{
ks_crypt = 2; ks_crypt = 2;
ks_tweak = 3; ks_tweak = 3;
break; }
case 9: // SYSTEM. else if (!strcmp(part->name, "SYSTEM") || !strcmp(part->name, "USER"))
case 10: // USER. {
ks_crypt = 4; ks_crypt = 4;
ks_tweak = 5; 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; u8 console_6axis_sensor_mount_type;
} __attribute__((packed)) nx_emmc_cal0_t; } __attribute__((packed)) nx_emmc_cal0_t;
int nx_emmc_bis_read(u32 sector, u32 count, void *buff); int nx_emmc_bis_read(u32 sector, u32 count, void *buff);
void nx_emmc_bis_init(emmc_part_t *part); 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 #endif

View File

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

View File

@@ -6,37 +6,53 @@ backlight=100
autohosoff=0 autohosoff=0
autonogc=1 autonogc=1
updater2p=1 updater2p=1
bootprotect=0
{-------- Stock -------} {-------- Stock -------}
[Stock 6.2.0 and lower] [Stock]
stock=1
emummc_force_disable=1
[Stock All FW]
fss0=atmosphere/fusee-secondary.bin fss0=atmosphere/fusee-secondary.bin
stock=1 stock=1
emummc_force_disable=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] # This disables kernel patching and CFW kips.
fss0=atmosphere/fusee-secondary.bin # Includes exosphere and warmboot, ONLY when >= 7.0.0 and Erista.
stock=1 # 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 --} {-- Custom Firmwares --}
[Atmo FSS0 Vanilla] [Atmo Vanilla]
fss0=atmosphere/fusee-secondary.bin fss0=atmosphere/fusee-secondary.bin
logopath=bootloader/res/bootlogo_atmo.bmp
icon=bootloader/res/icon_atmo.bmp
# Note: # 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, # You can have 2 entries of everything where one can boot with emuMMC and one without,
# via the emummc_force_disable=1 key. # via the emummc_force_disable=1 and emummcforce=1 keys. Examples follow below.
# logopath= key is for bootlogo. icon= key is for Nyx icon.
# All entries can have these stylistic keys. [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] [CFW FSS0 extra kips & patches]
fss0=atmosphere/fusee-secondary.bin fss0=atmosphere/fusee-secondary.bin
kip1patch=name_of_patch kip1patch=name_of_patch
@@ -45,12 +61,12 @@ kip1=cfw/mods/mods_extra/single/extra.kip
# Note: # Note:
# Both options for kip1 can be used. Wildcard and single. # Both options for kip1 can be used. Wildcard and single.
# You can override kips loaded from FSS0 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 # If kip1 patch resides in patches.ini and that file OR the patch for
# current HOS version does not exist, it will error out. # current HOS version does not exist, it will error out.
[Atmo Vanilla] [CFW KIPs method]
secmon=cfw/mods/exosphere.bin secmon=cfw/mods/exosphere.bin
warmboot=cfw/mods/lp0fw.bin warmboot=cfw/mods/lp0fw.bin
kip1=cfw/mods/loader.kip kip1=cfw/mods/loader.kip
@@ -66,7 +82,7 @@ atmosphere=1
# atmosphere=1 key is IMPORTANT when no FFS0 is defined. # atmosphere=1 key is IMPORTANT when no FFS0 is defined.
[CFW Extra kips] [CFW KIPs method with wildcard]
secmon=cfw/mods/exosphere.bin secmon=cfw/mods/exosphere.bin
warmboot=cfw/mods/lp0fw.bin warmboot=cfw/mods/lp0fw.bin
kip1=cfw/mods/* kip1=cfw/mods/*
@@ -83,7 +99,12 @@ atmosphere=1
payload=bootloader/payloads/memloader.bin 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! # NOT TO BE USED AS IS!
# Pick [config] and then only the needed [sections]. # or { } lines can be ommited. # Pick [config] and then only the needed [sections]. # or { } lines can be ommited.