Compare commits
40 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4e7e5081a7 | ||
|
|
fff750e609 | ||
|
|
38ce46a158 | ||
|
|
7a27a7b3b5 | ||
|
|
c6ec175045 | ||
|
|
3b9ab66cf1 | ||
|
|
b6e458e97b | ||
|
|
c5152f6a9d | ||
|
|
e5689cfe57 | ||
|
|
f3f1d4d4f0 | ||
|
|
796b15a861 | ||
|
|
add351289a | ||
|
|
a4a056128a | ||
|
|
6e314933d9 | ||
|
|
a31bedda97 | ||
|
|
a25c82a8ce | ||
|
|
8ccc47dfa5 | ||
|
|
9de5a4ba66 | ||
|
|
84e437ae5b | ||
|
|
9e34c5995d | ||
|
|
497bbdf3cd | ||
|
|
8683a0ff58 | ||
|
|
874c801772 | ||
|
|
eea5463a5c | ||
|
|
af790aeaf8 | ||
|
|
a8a45b215a | ||
|
|
38f456a2ee | ||
|
|
a980eac647 | ||
|
|
ea83566fc9 | ||
|
|
0857d7ff0e | ||
|
|
48e98ab8c9 | ||
|
|
8cd438146d | ||
|
|
a80cc0ae2c | ||
|
|
2428736bfa | ||
|
|
a7bf8bf118 | ||
|
|
8038e1faa9 | ||
|
|
15a7e49dde | ||
|
|
8b30bd4b57 | ||
|
|
63d03303a2 | ||
|
|
0e40fef049 |
@@ -92,7 +92,7 @@ You can find a template [Here](./res/hekate_ipl_template.ini)
|
||||
| emupath={SD folder} | Forces emuMMC to use the selected one. (=emuMMC/RAW1, =emuMMC/SD00, etc). emuMMC must be created by hekate because it uses the raw_based/file_based files. |
|
||||
| emummcforce=1 | Forces the use of emuMMC. If emummc.ini is disabled or not found, then it causes an error. |
|
||||
| emummc_force_disable=1 | Disables emuMMC, if it's enabled. |
|
||||
| stock=1 | Disables unneeded kernel patching when running stock or semi-stock. `If emuMMC is enabled, emummc_force_disabled=1` is required. emuMMC is not supported on stock. If additional KIPs are needed other than OFW's, you can define them with `kip1` key. No kip should be used that relies on Atmosphère patching, because it will hang. If `NOGC` is needed, use `kip1patch=nogc`. |
|
||||
| stock=1 | Disables unneeded kernel patching and CFW kips when running stock or semi-stock. `If emuMMC is enabled, emummc_force_disabled=1` is required. emuMMC is not supported on stock. If additional KIPs are needed other than OFW's, you can define them with `kip1` key. No kip should be used that relies on Atmosphère patching, because it will hang. If `NOGC` is needed, use `kip1patch=nogc`. |
|
||||
| id=idname | Identifies boot entry for forced boot via id. Max 7 chars. |
|
||||
| payload={SD path} | Payload launching. Tools, Linux, CFW bootloaders, etc. |
|
||||
| logopath={SD path} | If no logopath, `bootloader/bootlogo.bmp` will be used if exists. If logopath exists, it will load the specified bitmap. |
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
# IPL Version.
|
||||
BLVERSION_MAJOR := 5
|
||||
BLVERSION_MINOR := 5
|
||||
BLVERSION_HOTFX := 3
|
||||
BLVERSION_HOTFX := 4
|
||||
BLVERSION_RSVD := 0
|
||||
|
||||
# Nyx Version.
|
||||
NYXVERSION_MAJOR := 0
|
||||
NYXVERSION_MINOR := 9
|
||||
NYXVERSION_HOTFX := 9
|
||||
NYXVERSION_MAJOR := 1
|
||||
NYXVERSION_MINOR := 0
|
||||
NYXVERSION_HOTFX := 1
|
||||
NYXVERSION_RSVD := 0
|
||||
|
||||
@@ -694,9 +694,15 @@ retry:
|
||||
|
||||
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_D, GPIO_PIN_1, GPIO_MODE_SPIO);
|
||||
|
||||
// Send sleep command.
|
||||
u8 data = HCI_STATE_SLEEP;
|
||||
|
||||
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_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)
|
||||
|
||||
@@ -27,7 +27,8 @@ typedef enum {
|
||||
DRIVE_SD = 0,
|
||||
DRIVE_RAM = 1,
|
||||
DRIVE_EMMC = 2,
|
||||
DRIVE_BIS = 3
|
||||
DRIVE_BIS = 3,
|
||||
DRIVE_EMU = 4
|
||||
} DDRIVE;
|
||||
|
||||
|
||||
@@ -59,6 +60,7 @@ DRESULT disk_set_info (BYTE pdrv, BYTE cmd, void *buff);
|
||||
#define GET_SECTOR_SIZE 2 /* Get sector size (needed at FF_MAX_SS != FF_MIN_SS) */
|
||||
#define GET_BLOCK_SIZE 3 /* Get erase block size (needed at FF_USE_MKFS == 1) */
|
||||
#define CTRL_TRIM 4 /* Inform device that the data on the block of sectors is no longer used (needed at FF_USE_TRIM == 1) */
|
||||
#define SET_SECTOR_OFFSET 5 /* Set media logical offset */
|
||||
|
||||
/* Generic command (Not used by FatFs) */
|
||||
#define CTRL_POWER 5 /* Get/Set power status */
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2018-2019 CTCaer
|
||||
* Copyright (c) 2018-2021 CTCaer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
@@ -38,6 +38,7 @@
|
||||
|
||||
#include "ff.h" /* Declarations of FatFs API */
|
||||
#include "diskio.h" /* Declarations of device I/O functions */
|
||||
#include <storage/mbr_gpt.h>
|
||||
#include <gfx_utils.h>
|
||||
|
||||
#define EFSPRINTF(text, ...) print_error(); gfx_printf("%k"text"%k\n", 0xFFFFFF00, 0xFFFFFFFF);
|
||||
@@ -3284,6 +3285,7 @@ static FRESULT find_volume ( /* FR_OK(0): successful, !=0: an error occurred */
|
||||
/* Following code attempts to mount the volume. (analyze BPB and initialize the filesystem object) */
|
||||
|
||||
fs->fs_type = 0; /* Clear the filesystem object */
|
||||
fs->part_type = 0; /* Clear the Partition object */
|
||||
fs->pdrv = LD2PD(vol); /* Bind the logical drive and a physical drive */
|
||||
stat = disk_initialize(fs->pdrv); /* Initialize the physical drive */
|
||||
if (stat & STA_NOINIT) { /* Check if the initialization succeeded */
|
||||
@@ -3318,6 +3320,18 @@ static FRESULT find_volume ( /* FR_OK(0): successful, !=0: an error occurred */
|
||||
EFSPRINTF("BRNL");
|
||||
return FR_DISK_ERR; /* An error occured in the disk I/O layer */
|
||||
}
|
||||
#if FF_SIMPLE_GPT
|
||||
if (fmt >= 2) {
|
||||
/* If GPT Check the first partition */
|
||||
gpt_t gpt;
|
||||
if (disk_read(fs->pdrv, (BYTE *)&gpt, 1, sizeof(gpt_t) / SS(fs))) return FR_DISK_ERR;
|
||||
if (!mem_cmp(&gpt.header.signature, "EFI PART", 8)) {
|
||||
fs->part_type = 1;
|
||||
bsect = gpt.entries[0].lba_start;
|
||||
fmt = bsect ? check_fs(fs, bsect) : 3; /* Check the partition */
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (fmt >= 2) {
|
||||
EFSPRINTF("NOFAT");
|
||||
return FR_NO_FILESYSTEM; /* No FAT volume is found */
|
||||
@@ -6169,7 +6183,9 @@ FRESULT f_mkfs (
|
||||
#endif
|
||||
/* Create FAT VBR */
|
||||
mem_set(buf, 0, ss);
|
||||
mem_cpy(buf + BS_JmpBoot, "\xEB\xFE\x90" "MSDOS5.0", 11);/* Boot jump code (x86), OEM name */
|
||||
/* Boot jump code (x86), OEM name */
|
||||
if (!(opt & FM_PRF2)) mem_cpy(buf + BS_JmpBoot, "\xEB\xFE\x90" "NYX1.0.0", 11);
|
||||
else mem_cpy(buf + BS_JmpBoot, "\xEB\xE9\x90\x00\x00\x00\x00\x00\x00\x00\x00", 11);
|
||||
st_word(buf + BPB_BytsPerSec, ss); /* Sector size [byte] */
|
||||
buf[BPB_SecPerClus] = (BYTE)pau; /* Cluster size [sector] */
|
||||
st_word(buf + BPB_RsvdSecCnt, (WORD)sz_rsv); /* Size of reserved area */
|
||||
@@ -6182,23 +6198,27 @@ FRESULT f_mkfs (
|
||||
}
|
||||
buf[BPB_Media] = 0xF8; /* Media descriptor byte */
|
||||
st_word(buf + BPB_SecPerTrk, 63); /* Number of sectors per track (for int13) */
|
||||
st_word(buf + BPB_NumHeads, 255); /* Number of heads (for int13) */
|
||||
st_word(buf + BPB_NumHeads, (opt & FM_PRF2) ? 16 : 255); /* Number of heads (for int13) */
|
||||
st_dword(buf + BPB_HiddSec, b_vol); /* Volume offset in the physical drive [sector] */
|
||||
if (fmt == FS_FAT32) {
|
||||
st_dword(buf + BS_VolID32, GET_FATTIME()); /* VSN */
|
||||
st_dword(buf + BS_VolID32, (opt & FM_PRF2) ? 0 : GET_FATTIME()); /* VSN */
|
||||
st_dword(buf + BPB_FATSz32, sz_fat); /* FAT size [sector] */
|
||||
st_dword(buf + BPB_RootClus32, 2); /* Root directory cluster # (2) */
|
||||
st_word(buf + BPB_FSInfo32, 1); /* Offset of FSINFO sector (VBR + 1) */
|
||||
st_word(buf + BPB_BkBootSec32, 6); /* Offset of backup VBR (VBR + 6) */
|
||||
buf[BS_DrvNum32] = 0x80; /* Drive number (for int13) */
|
||||
buf[BS_BootSig32] = 0x29; /* Extended boot signature */
|
||||
mem_cpy(buf + BS_VolLab32, "SWITCH SD " "FAT32 ", 19); /* Volume label, FAT signature */
|
||||
/* Volume label, FAT signature */
|
||||
if (!(opt & FM_PRF2)) mem_cpy(buf + BS_VolLab32, FF_MKFS_LABEL "FAT32 ", 19);
|
||||
else mem_cpy(buf + BS_VolLab32, "NO NAME " "FAT32 ", 19);
|
||||
} else {
|
||||
st_dword(buf + BS_VolID, GET_FATTIME()); /* VSN */
|
||||
st_word(buf + BPB_FATSz16, (WORD)sz_fat); /* FAT size [sector] */
|
||||
buf[BS_DrvNum] = 0x80; /* Drive number (for int13) */
|
||||
buf[BS_BootSig] = 0x29; /* Extended boot signature */
|
||||
mem_cpy(buf + BS_VolLab, "SWITCH SD " "FAT ", 19); /* Volume label, FAT signature */
|
||||
/* Volume label, FAT signature */
|
||||
if (!(opt & FM_PRF2)) mem_cpy(buf + BS_VolLab, FF_MKFS_LABEL "FAT ", 19);
|
||||
else mem_cpy(buf + BS_VolLab, "NO NAME " "FAT ", 19);
|
||||
}
|
||||
st_word(buf + BS_55AA, 0xAA55); /* Signature (offset is fixed here regardless of sector size) */
|
||||
if (disk_write(pdrv, buf, b_vol, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); /* Write it to the VBR sector */
|
||||
@@ -6216,6 +6236,16 @@ FRESULT f_mkfs (
|
||||
disk_write(pdrv, buf, b_vol + 1, 1); /* Write original FSINFO (VBR + 1) */
|
||||
}
|
||||
|
||||
/* Create PRF2SAFE info */
|
||||
if (fmt == FS_FAT32 && opt & FM_PRF2) {
|
||||
mem_set(buf, 0, ss);
|
||||
buf[16] = 0x64; /* Record type */
|
||||
st_dword(buf + 32, 0x03); /* Unknown. SYSTEM: 0x3F00. USER: 0x03. Volatile. */
|
||||
st_dword(buf + 36, 25); /* Entries. SYSTEM: 22. USER: 25.Static? */
|
||||
st_dword(buf + 508, 0x517BBFE0); /* Custom CRC32. SYSTEM: 0x6B673904. USER: 0x517BBFE0. */
|
||||
disk_write(pdrv, buf, b_vol + 3, 1); /* Write PRF2SAFE info (VBR + 3) */
|
||||
}
|
||||
|
||||
/* Initialize FAT area */
|
||||
mem_set(buf, 0, (UINT)szb_buf);
|
||||
sect = b_fat; /* FAT start sector */
|
||||
|
||||
@@ -95,8 +95,8 @@ typedef DWORD FSIZE_t;
|
||||
/* Filesystem object structure (FATFS) */
|
||||
|
||||
typedef struct {
|
||||
BYTE win[FF_MAX_SS]; /* Disk access window for Directory, FAT (and file data at tiny cfg) */
|
||||
BYTE fs_type; /* Filesystem type (0:not mounted) */
|
||||
BYTE part_type; /* Partition type (0:MBR, 1:GPT) */
|
||||
BYTE pdrv; /* Associated physical drive */
|
||||
BYTE n_fats; /* Number of FATs (1 or 2) */
|
||||
BYTE wflag; /* win[] flag (b0:dirty) */
|
||||
@@ -138,6 +138,7 @@ typedef struct {
|
||||
DWORD bitbase; /* Allocation bitmap base sector */
|
||||
#endif
|
||||
DWORD winsect; /* Current sector appearing in the win[] */
|
||||
BYTE win[FF_MAX_SS] __attribute__((aligned(8))); /* Disk access window for Directory, FAT (and file data at tiny cfg). DMA aligned. */
|
||||
} FATFS;
|
||||
|
||||
|
||||
@@ -168,9 +169,6 @@ typedef struct {
|
||||
/* File object structure (FIL) */
|
||||
|
||||
typedef struct {
|
||||
#if !FF_FS_TINY
|
||||
BYTE buf[FF_MAX_SS]; /* File private data read/write window */
|
||||
#endif
|
||||
FFOBJID obj; /* Object identifier (must be the 1st member to detect invalid object pointer) */
|
||||
BYTE flag; /* File status flags */
|
||||
BYTE err; /* Abort flag (error code) */
|
||||
@@ -184,6 +182,9 @@ typedef struct {
|
||||
#if FF_USE_FASTSEEK
|
||||
DWORD* cltbl; /* Pointer to the cluster link map table (nulled on open, set by application) */
|
||||
#endif
|
||||
#if !FF_FS_TINY
|
||||
BYTE buf[FF_MAX_SS] __attribute__((aligned(8))); /* File private data read/write window. DMA aligned. */
|
||||
#endif
|
||||
} FIL;
|
||||
|
||||
|
||||
@@ -365,6 +366,7 @@ int ff_del_syncobj (FF_SYNC_t sobj); /* Delete a sync object */
|
||||
#define FM_EXFAT 0x04
|
||||
#define FM_ANY 0x07
|
||||
#define FM_SFD 0x08
|
||||
#define FM_PRF2 0x10
|
||||
|
||||
/* Filesystem type (FATFS.fs_type) */
|
||||
#define FS_FAT12 1
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019 CTCaer
|
||||
* Copyright (c) 2019-2021 CTCaer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
@@ -50,6 +50,13 @@
|
||||
// Virtual disk / Chainloader buffers.
|
||||
#define RAM_DISK_ADDR 0xA4000000
|
||||
#define RAM_DISK_SZ 0x41000000 // 1040MB.
|
||||
#define RAM_DISK2_SZ 0x21000000 // 528MB.
|
||||
|
||||
// NX BIS driver sector cache.
|
||||
#define NX_BIS_CACHE_ADDR 0xC5000000
|
||||
#define NX_BIS_CACHE_SZ 0x10020000 // 256MB.
|
||||
#define NX_BIS_LOOKUP_ADDR 0xD6000000
|
||||
#define NX_BIS_LOOKUP_SZ 0xF000000 // 240MB.
|
||||
|
||||
// L4T Kernel Panic Storage (PSTORE).
|
||||
#define PSTORE_ADDR 0xB0000000
|
||||
@@ -93,10 +100,6 @@
|
||||
/* --- Hole: 129MB 0xF6A00000 - 0xFEB3FFFF --- */
|
||||
#define DRAM_START2 0xFEB40000
|
||||
|
||||
// NX BIS driver sector cache.
|
||||
#define NX_BIS_CACHE_ADDR 0xFEE00000
|
||||
#define NX_BIS_CACHE_SZ 0x100000
|
||||
|
||||
// USB buffers.
|
||||
#define USBD_ADDR 0xFEF00000
|
||||
#define USB_DESCRIPTOR_ADDR 0xFEF40000
|
||||
|
||||
275
bdk/sec/se.c
275
bdk/sec/se.c
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2018-2020 CTCaer
|
||||
* Copyright (c) 2018-2021 CTCaer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
@@ -57,17 +57,17 @@ static void _se_ll_init(se_ll_t *ll, u32 addr, u32 size)
|
||||
|
||||
static void _se_ll_set(se_ll_t *dst, se_ll_t *src)
|
||||
{
|
||||
SE(SE_IN_LL_ADDR_REG_OFFSET) = (u32)src;
|
||||
SE(SE_OUT_LL_ADDR_REG_OFFSET) = (u32)dst;
|
||||
SE(SE_IN_LL_ADDR_REG) = (u32)src;
|
||||
SE(SE_OUT_LL_ADDR_REG) = (u32)dst;
|
||||
}
|
||||
|
||||
static int _se_wait()
|
||||
{
|
||||
while (!(SE(SE_INT_STATUS_REG_OFFSET) & SE_INT_OP_DONE(INT_SET)))
|
||||
while (!(SE(SE_INT_STATUS_REG) & SE_INT_OP_DONE))
|
||||
;
|
||||
if (SE(SE_INT_STATUS_REG_OFFSET) & SE_INT_ERROR(INT_SET) ||
|
||||
SE(SE_STATUS_0) & SE_STATUS_0_STATE_WAIT_IN ||
|
||||
SE(SE_ERR_STATUS_0) != SE_ERR_STATUS_0_SE_NS_ACCESS_CLEAR)
|
||||
if (SE(SE_INT_STATUS_REG) & SE_INT_ERR_STAT ||
|
||||
(SE(SE_STATUS_REG) & SE_STATUS_STATE_MASK) != SE_STATUS_STATE_IDLE ||
|
||||
SE(SE_ERR_STATUS_REG) != 0)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
@@ -92,12 +92,12 @@ static int _se_execute(u32 op, void *dst, u32 dst_size, const void *src, u32 src
|
||||
|
||||
_se_ll_set(ll_dst, ll_src);
|
||||
|
||||
SE(SE_ERR_STATUS_0) = SE(SE_ERR_STATUS_0);
|
||||
SE(SE_INT_STATUS_REG_OFFSET) = SE(SE_INT_STATUS_REG_OFFSET);
|
||||
SE(SE_ERR_STATUS_REG) = SE(SE_ERR_STATUS_REG);
|
||||
SE(SE_INT_STATUS_REG) = SE(SE_INT_STATUS_REG);
|
||||
|
||||
bpmp_mmu_maintenance(BPMP_MMU_MAINT_CLN_INV_WAY, false);
|
||||
|
||||
SE(SE_OPERATION_REG_OFFSET) = SE_OPERATION(op);
|
||||
SE(SE_OPERATION_REG) = op;
|
||||
|
||||
if (is_oneshot)
|
||||
{
|
||||
@@ -146,13 +146,13 @@ static int _se_execute_one_block(u32 op, void *dst, u32 dst_size, const void *sr
|
||||
if (!src || !dst)
|
||||
return 0;
|
||||
|
||||
u8 *block = (u8 *)malloc(0x10);
|
||||
memset(block, 0, 0x10);
|
||||
u8 *block = (u8 *)malloc(SE_AES_BLOCK_SIZE);
|
||||
memset(block, 0, SE_AES_BLOCK_SIZE);
|
||||
|
||||
SE(SE_BLOCK_COUNT_REG_OFFSET) = 0;
|
||||
SE(SE_CRYPTO_BLOCK_COUNT_REG) = 1 - 1;
|
||||
|
||||
memcpy(block, src, src_size);
|
||||
int res = _se_execute_oneshot(op, block, 0x10, block, 0x10);
|
||||
int res = _se_execute_oneshot(op, block, SE_AES_BLOCK_SIZE, block, SE_AES_BLOCK_SIZE);
|
||||
memcpy(dst, block, dst_size);
|
||||
|
||||
free(block);
|
||||
@@ -161,68 +161,68 @@ static int _se_execute_one_block(u32 op, void *dst, u32 dst_size, const void *sr
|
||||
|
||||
static void _se_aes_ctr_set(void *ctr)
|
||||
{
|
||||
u32 data[TEGRA_SE_AES_BLOCK_SIZE / 4];
|
||||
memcpy(data, ctr, TEGRA_SE_AES_BLOCK_SIZE);
|
||||
u32 data[SE_AES_IV_SIZE / 4];
|
||||
memcpy(data, ctr, SE_AES_IV_SIZE);
|
||||
|
||||
for (u32 i = 0; i < (TEGRA_SE_AES_BLOCK_SIZE / 4); i++)
|
||||
SE(SE_CRYPTO_CTR_REG_OFFSET + (4 * i)) = data[i];
|
||||
for (u32 i = 0; i < SE_CRYPTO_LINEAR_CTR_REG_COUNT; i++)
|
||||
SE(SE_CRYPTO_LINEAR_CTR_REG + (4 * i)) = data[i];
|
||||
}
|
||||
|
||||
void se_rsa_acc_ctrl(u32 rs, u32 flags)
|
||||
{
|
||||
if (flags & SE_RSA_KEY_TBL_DIS_KEY_ALL_FLAG)
|
||||
SE(SE_RSA_KEYTABLE_ACCESS_REG_OFFSET + 4 * rs) =
|
||||
((flags >> SE_RSA_KEY_TBL_DIS_KEYUSE_FLAG_SHIFT) & SE_RSA_KEY_TBL_DIS_KEYUSE_FLAG) |
|
||||
((flags & SE_RSA_KEY_TBL_DIS_KEY_READ_UPDATE_FLAG) ^ SE_RSA_KEY_TBL_DIS_KEY_ALL_COMMON_FLAG);
|
||||
if (flags & SE_RSA_KEY_TBL_DIS_KEY_LOCK_FLAG)
|
||||
SE(SE_RSA_KEYTABLE_ACCESS_LOCK_OFFSET) &= ~BIT(rs);
|
||||
if (flags & SE_RSA_KEY_TBL_DIS_KEY_ACCESS_FLAG)
|
||||
SE(SE_RSA_KEYTABLE_ACCESS_REG + 4 * rs) =
|
||||
(((flags >> 4) & SE_RSA_KEY_TBL_DIS_KEYUSE_FLAG) |(flags & SE_RSA_KEY_TBL_DIS_KEY_READ_UPDATE_FLAG)) ^
|
||||
SE_RSA_KEY_TBL_DIS_KEY_READ_UPDATE_USE_FLAG;
|
||||
if (flags & SE_RSA_KEY_LOCK_FLAG)
|
||||
SE(SE_RSA_SECURITY_PERKEY_REG) &= ~BIT(rs);
|
||||
}
|
||||
|
||||
void se_key_acc_ctrl(u32 ks, u32 flags)
|
||||
{
|
||||
if (flags & SE_KEY_TBL_DIS_KEY_ACCESS_FLAG)
|
||||
SE(SE_KEY_TABLE_ACCESS_REG_OFFSET + 4 * ks) = ~flags;
|
||||
if (flags & SE_KEY_TBL_DIS_KEY_LOCK_FLAG)
|
||||
SE(SE_KEY_TABLE_ACCESS_LOCK_OFFSET) &= ~BIT(ks);
|
||||
SE(SE_CRYPTO_KEYTABLE_ACCESS_REG + 4 * ks) = ~flags;
|
||||
if (flags & SE_KEY_LOCK_FLAG)
|
||||
SE(SE_CRYPTO_SECURITY_PERKEY_REG) &= ~BIT(ks);
|
||||
}
|
||||
|
||||
u32 se_key_acc_ctrl_get(u32 ks)
|
||||
{
|
||||
return SE(SE_KEY_TABLE_ACCESS_REG_OFFSET + 4 * ks);
|
||||
return SE(SE_CRYPTO_KEYTABLE_ACCESS_REG + 4 * ks);
|
||||
}
|
||||
|
||||
void se_aes_key_set(u32 ks, void *key, u32 size)
|
||||
{
|
||||
u32 data[TEGRA_SE_AES_MAX_KEY_SIZE / 4];
|
||||
u32 data[SE_AES_MAX_KEY_SIZE / 4];
|
||||
memcpy(data, key, size);
|
||||
|
||||
for (u32 i = 0; i < (size / 4); i++)
|
||||
{
|
||||
SE(SE_KEYTABLE_REG_OFFSET) = SE_KEYTABLE_SLOT(ks) | i;
|
||||
SE(SE_KEYTABLE_DATA0_REG_OFFSET) = data[i];
|
||||
SE(SE_CRYPTO_KEYTABLE_ADDR_REG) = SE_KEYTABLE_SLOT(ks) | SE_KEYTABLE_PKT(i); // QUAD is automatically set by PKT.
|
||||
SE(SE_CRYPTO_KEYTABLE_DATA_REG) = data[i];
|
||||
}
|
||||
}
|
||||
|
||||
void se_aes_iv_set(u32 ks, void *iv)
|
||||
{
|
||||
u32 data[TEGRA_SE_AES_BLOCK_SIZE / 4];
|
||||
memcpy(data, iv, TEGRA_SE_AES_BLOCK_SIZE);
|
||||
u32 data[SE_AES_IV_SIZE / 4];
|
||||
memcpy(data, iv, SE_AES_IV_SIZE);
|
||||
|
||||
for (u32 i = 0; i < (TEGRA_SE_AES_BLOCK_SIZE / 4); i++)
|
||||
for (u32 i = 0; i < (SE_AES_IV_SIZE / 4); i++)
|
||||
{
|
||||
SE(SE_KEYTABLE_REG_OFFSET) = SE_KEYTABLE_SLOT(ks) | SE_KEYTABLE_QUAD(QUAD_ORG_IV) | i;
|
||||
SE(SE_KEYTABLE_DATA0_REG_OFFSET) = data[i];
|
||||
SE(SE_CRYPTO_KEYTABLE_ADDR_REG) = SE_KEYTABLE_SLOT(ks) | SE_KEYTABLE_QUAD(ORIGINAL_IV) | SE_KEYTABLE_PKT(i);
|
||||
SE(SE_CRYPTO_KEYTABLE_DATA_REG) = data[i];
|
||||
}
|
||||
}
|
||||
|
||||
void se_aes_key_get(u32 ks, void *key, u32 size)
|
||||
{
|
||||
u32 data[TEGRA_SE_AES_MAX_KEY_SIZE / 4];
|
||||
u32 data[SE_AES_MAX_KEY_SIZE / 4];
|
||||
|
||||
for (u32 i = 0; i < (size / 4); i++)
|
||||
{
|
||||
SE(SE_KEYTABLE_REG_OFFSET) = SE_KEYTABLE_SLOT(ks) | i;
|
||||
data[i] = SE(SE_KEYTABLE_DATA0_REG_OFFSET);
|
||||
SE(SE_CRYPTO_KEYTABLE_ADDR_REG) = SE_KEYTABLE_SLOT(ks) | SE_KEYTABLE_PKT(i); // QUAD is automatically set by PKT.
|
||||
data[i] = SE(SE_CRYPTO_KEYTABLE_DATA_REG);
|
||||
}
|
||||
|
||||
memcpy(key, data, size);
|
||||
@@ -230,78 +230,78 @@ void se_aes_key_get(u32 ks, void *key, u32 size)
|
||||
|
||||
void se_aes_key_clear(u32 ks)
|
||||
{
|
||||
for (u32 i = 0; i < (TEGRA_SE_AES_MAX_KEY_SIZE / 4); i++)
|
||||
for (u32 i = 0; i < (SE_AES_MAX_KEY_SIZE / 4); i++)
|
||||
{
|
||||
SE(SE_KEYTABLE_REG_OFFSET) = SE_KEYTABLE_SLOT(ks) | i;
|
||||
SE(SE_KEYTABLE_DATA0_REG_OFFSET) = 0;
|
||||
SE(SE_CRYPTO_KEYTABLE_ADDR_REG) = SE_KEYTABLE_SLOT(ks) | SE_KEYTABLE_PKT(i); // QUAD is automatically set by PKT.
|
||||
SE(SE_CRYPTO_KEYTABLE_DATA_REG) = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void se_aes_iv_clear(u32 ks)
|
||||
{
|
||||
for (u32 i = 0; i < (TEGRA_SE_AES_BLOCK_SIZE / 4); i++)
|
||||
for (u32 i = 0; i < (SE_AES_IV_SIZE / 4); i++)
|
||||
{
|
||||
SE(SE_KEYTABLE_REG_OFFSET) = SE_KEYTABLE_SLOT(ks) | SE_KEYTABLE_QUAD(QUAD_ORG_IV) | i;
|
||||
SE(SE_KEYTABLE_DATA0_REG_OFFSET) = 0;
|
||||
SE(SE_CRYPTO_KEYTABLE_ADDR_REG) = SE_KEYTABLE_SLOT(ks) | SE_KEYTABLE_QUAD(ORIGINAL_IV) | SE_KEYTABLE_PKT(i);
|
||||
SE(SE_CRYPTO_KEYTABLE_DATA_REG) = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int se_aes_unwrap_key(u32 ks_dst, u32 ks_src, const void *input)
|
||||
{
|
||||
SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_DEC_ALG(ALG_AES_DEC) | SE_CONFIG_DST(DST_KEYTAB);
|
||||
SE(SE_CRYPTO_REG_OFFSET) = SE_CRYPTO_KEY_INDEX(ks_src) | SE_CRYPTO_CORE_SEL(CORE_DECRYPT);
|
||||
SE(SE_BLOCK_COUNT_REG_OFFSET) = 0;
|
||||
SE(SE_CRYPTO_KEYTABLE_DST_REG_OFFSET) = SE_CRYPTO_KEYTABLE_DST_KEY_INDEX(ks_dst);
|
||||
SE(SE_CONFIG_REG) = SE_CONFIG_DEC_ALG(ALG_AES_DEC) | SE_CONFIG_DST(DST_KEYTABLE);
|
||||
SE(SE_CRYPTO_CONFIG_REG) = SE_CRYPTO_KEY_INDEX(ks_src) | SE_CRYPTO_CORE_SEL(CORE_DECRYPT);
|
||||
SE(SE_CRYPTO_BLOCK_COUNT_REG) = 1 - 1;
|
||||
SE(SE_CRYPTO_KEYTABLE_DST_REG) = SE_KEYTABLE_DST_KEY_INDEX(ks_dst) | SE_KEYTABLE_DST_WORD_QUAD(KEYS_0_3);
|
||||
|
||||
return _se_execute_oneshot(OP_START, NULL, 0, input, 0x10);
|
||||
return _se_execute_oneshot(SE_OP_START, NULL, 0, input, SE_KEY_128_SIZE);
|
||||
}
|
||||
|
||||
int se_aes_crypt_ecb(u32 ks, u32 enc, void *dst, u32 dst_size, const void *src, u32 src_size)
|
||||
{
|
||||
if (enc)
|
||||
{
|
||||
SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_ENC_ALG(ALG_AES_ENC) | SE_CONFIG_DST(DST_MEMORY);
|
||||
SE(SE_CRYPTO_REG_OFFSET) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_CORE_SEL(CORE_ENCRYPT);
|
||||
SE(SE_CONFIG_REG) = SE_CONFIG_ENC_ALG(ALG_AES_ENC) | SE_CONFIG_DST(DST_MEMORY);
|
||||
SE(SE_CRYPTO_CONFIG_REG) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_CORE_SEL(CORE_ENCRYPT);
|
||||
}
|
||||
else
|
||||
{
|
||||
SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_DEC_ALG(ALG_AES_DEC) | SE_CONFIG_DST(DST_MEMORY);
|
||||
SE(SE_CRYPTO_REG_OFFSET) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_CORE_SEL(CORE_DECRYPT);
|
||||
SE(SE_CONFIG_REG) = SE_CONFIG_DEC_ALG(ALG_AES_DEC) | SE_CONFIG_DST(DST_MEMORY);
|
||||
SE(SE_CRYPTO_CONFIG_REG) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_CORE_SEL(CORE_DECRYPT);
|
||||
}
|
||||
SE(SE_BLOCK_COUNT_REG_OFFSET) = (src_size >> 4) - 1;
|
||||
return _se_execute_oneshot(OP_START, dst, dst_size, src, src_size);
|
||||
SE(SE_CRYPTO_BLOCK_COUNT_REG) = (src_size >> 4) - 1;
|
||||
return _se_execute_oneshot(SE_OP_START, dst, dst_size, src, src_size);
|
||||
}
|
||||
|
||||
int se_aes_crypt_cbc(u32 ks, u32 enc, void *dst, u32 dst_size, const void *src, u32 src_size)
|
||||
{
|
||||
if (enc)
|
||||
{
|
||||
SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_ENC_ALG(ALG_AES_ENC) | SE_CONFIG_DST(DST_MEMORY);
|
||||
SE(SE_CRYPTO_REG_OFFSET) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_VCTRAM_SEL(VCTRAM_AESOUT) |
|
||||
SE(SE_CONFIG_REG) = SE_CONFIG_ENC_ALG(ALG_AES_ENC) | SE_CONFIG_DST(DST_MEMORY);
|
||||
SE(SE_CRYPTO_CONFIG_REG) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_VCTRAM_SEL(VCTRAM_AESOUT) |
|
||||
SE_CRYPTO_CORE_SEL(CORE_ENCRYPT) | SE_CRYPTO_XOR_POS(XOR_TOP);
|
||||
}
|
||||
else
|
||||
{
|
||||
SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_DEC_ALG(ALG_AES_DEC) | SE_CONFIG_DST(DST_MEMORY);
|
||||
SE(SE_CRYPTO_REG_OFFSET) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_VCTRAM_SEL(VCTRAM_PREVAHB) |
|
||||
SE(SE_CONFIG_REG) = SE_CONFIG_DEC_ALG(ALG_AES_DEC) | SE_CONFIG_DST(DST_MEMORY);
|
||||
SE(SE_CRYPTO_CONFIG_REG) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_VCTRAM_SEL(VCTRAM_PREVMEM) |
|
||||
SE_CRYPTO_CORE_SEL(CORE_DECRYPT) | SE_CRYPTO_XOR_POS(XOR_BOTTOM);
|
||||
}
|
||||
SE(SE_BLOCK_COUNT_REG_OFFSET) = (src_size >> 4) - 1;
|
||||
return _se_execute_oneshot(OP_START, dst, dst_size, src, src_size);
|
||||
SE(SE_CRYPTO_BLOCK_COUNT_REG) = (src_size >> 4) - 1;
|
||||
return _se_execute_oneshot(SE_OP_START, dst, dst_size, src, src_size);
|
||||
}
|
||||
|
||||
int se_aes_crypt_block_ecb(u32 ks, u32 enc, void *dst, const void *src)
|
||||
{
|
||||
return se_aes_crypt_ecb(ks, enc, dst, 0x10, src, 0x10);
|
||||
return se_aes_crypt_ecb(ks, enc, dst, SE_AES_BLOCK_SIZE, src, SE_AES_BLOCK_SIZE);
|
||||
}
|
||||
|
||||
int se_aes_crypt_ctr(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_size, void *ctr)
|
||||
{
|
||||
SE(SE_SPARE_0_REG_OFFSET) = 1;
|
||||
SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_ENC_ALG(ALG_AES_ENC) | SE_CONFIG_DST(DST_MEMORY);
|
||||
SE(SE_CRYPTO_REG_OFFSET) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_CORE_SEL(CORE_ENCRYPT) |
|
||||
SE_CRYPTO_XOR_POS(XOR_BOTTOM) | SE_CRYPTO_INPUT_SEL(INPUT_LNR_CTR) | SE_CRYPTO_CTR_VAL(1);
|
||||
SE(SE_SPARE_REG) = SE_ECO(SE_ERRATA_FIX_ENABLE);
|
||||
SE(SE_CONFIG_REG) = SE_CONFIG_ENC_ALG(ALG_AES_ENC) | SE_CONFIG_DST(DST_MEMORY);
|
||||
SE(SE_CRYPTO_CONFIG_REG) = SE_CRYPTO_KEY_INDEX(ks) | SE_CRYPTO_CORE_SEL(CORE_ENCRYPT) |
|
||||
SE_CRYPTO_XOR_POS(XOR_BOTTOM) | SE_CRYPTO_INPUT_SEL(INPUT_LNR_CTR) | SE_CRYPTO_CTR_CNTN(1);
|
||||
_se_aes_ctr_set(ctr);
|
||||
|
||||
u32 src_size_aligned = src_size & 0xFFFFFFF0;
|
||||
@@ -309,13 +309,13 @@ int se_aes_crypt_ctr(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_s
|
||||
|
||||
if (src_size_aligned)
|
||||
{
|
||||
SE(SE_BLOCK_COUNT_REG_OFFSET) = (src_size >> 4) - 1;
|
||||
if (!_se_execute_oneshot(OP_START, dst, dst_size, src, src_size_aligned))
|
||||
SE(SE_CRYPTO_BLOCK_COUNT_REG) = (src_size >> 4) - 1;
|
||||
if (!_se_execute_oneshot(SE_OP_START, dst, dst_size, src, src_size_aligned))
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (src_size - src_size_aligned && src_size_aligned < dst_size)
|
||||
return _se_execute_one_block(OP_START, dst + src_size_aligned,
|
||||
return _se_execute_one_block(SE_OP_START, dst + src_size_aligned,
|
||||
MIN(src_size_delta, dst_size - src_size_aligned),
|
||||
src + src_size_aligned, src_size_delta);
|
||||
|
||||
@@ -325,11 +325,11 @@ int se_aes_crypt_ctr(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_s
|
||||
int se_aes_xts_crypt_sec(u32 ks1, u32 ks2, u32 enc, u64 sec, void *dst, void *src, u32 secsize)
|
||||
{
|
||||
int res = 0;
|
||||
u8 *tweak = (u8 *)malloc(0x10);
|
||||
u8 *tweak = (u8 *)malloc(SE_AES_BLOCK_SIZE);
|
||||
u8 *pdst = (u8 *)dst;
|
||||
u8 *psrc = (u8 *)src;
|
||||
|
||||
//Generate tweak.
|
||||
// Generate tweak.
|
||||
for (int i = 0xF; i >= 0; i--)
|
||||
{
|
||||
tweak[i] = sec & 0xFF;
|
||||
@@ -338,18 +338,18 @@ int se_aes_xts_crypt_sec(u32 ks1, u32 ks2, u32 enc, u64 sec, void *dst, void *sr
|
||||
if (!se_aes_crypt_block_ecb(ks1, 1, tweak, tweak))
|
||||
goto out;
|
||||
|
||||
//We are assuming a 0x10-aligned sector size in this implementation.
|
||||
for (u32 i = 0; i < secsize / 0x10; i++)
|
||||
// We are assuming a 0x10-aligned sector size in this implementation.
|
||||
for (u32 i = 0; i < secsize / SE_AES_BLOCK_SIZE; i++)
|
||||
{
|
||||
for (u32 j = 0; j < 0x10; j++)
|
||||
for (u32 j = 0; j < SE_AES_BLOCK_SIZE; j++)
|
||||
pdst[j] = psrc[j] ^ tweak[j];
|
||||
if (!se_aes_crypt_block_ecb(ks2, enc, pdst, pdst))
|
||||
goto out;
|
||||
for (u32 j = 0; j < 0x10; j++)
|
||||
for (u32 j = 0; j < SE_AES_BLOCK_SIZE; j++)
|
||||
pdst[j] = pdst[j] ^ tweak[j];
|
||||
_gf256_mul_x(tweak);
|
||||
psrc += 0x10;
|
||||
pdst += 0x10;
|
||||
psrc += SE_AES_BLOCK_SIZE;
|
||||
pdst += SE_AES_BLOCK_SIZE;
|
||||
}
|
||||
|
||||
res = 1;
|
||||
@@ -374,62 +374,62 @@ int se_aes_xts_crypt(u32 ks1, u32 ks2, u32 enc, u64 sec, void *dst, void *src, u
|
||||
int se_calc_sha256(void *hash, u32 *msg_left, const void *src, u32 src_size, u64 total_size, u32 sha_cfg, bool is_oneshot)
|
||||
{
|
||||
int res;
|
||||
u32 hash32[TEGRA_SE_SHA_256_SIZE / 4];
|
||||
u32 hash32[SE_SHA_256_SIZE / 4];
|
||||
|
||||
//! TODO: src_size must be 512 bit aligned if continuing and not last block for SHA256.
|
||||
if (src_size > 0xFFFFFF || !hash) // Max 16MB - 1 chunks and aligned x4 hash buffer.
|
||||
return 0;
|
||||
|
||||
// Setup config for SHA256.
|
||||
SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_ENC_MODE(MODE_SHA256) | SE_CONFIG_ENC_ALG(ALG_SHA) | SE_CONFIG_DST(DST_HASHREG);
|
||||
SE(SE_SHA_CONFIG_REG_OFFSET) = sha_cfg;
|
||||
SE(SE_BLOCK_COUNT_REG_OFFSET) = 0;
|
||||
SE(SE_CONFIG_REG) = SE_CONFIG_ENC_MODE(MODE_SHA256) | SE_CONFIG_ENC_ALG(ALG_SHA) | SE_CONFIG_DST(DST_HASHREG);
|
||||
SE(SE_SHA_CONFIG_REG) = sha_cfg;
|
||||
SE(SE_CRYPTO_BLOCK_COUNT_REG) = 1 - 1;
|
||||
|
||||
// Set total size to current buffer size if empty.
|
||||
if (!total_size)
|
||||
total_size = src_size;
|
||||
|
||||
// Set total size: BITS(src_size), up to 2 EB.
|
||||
SE(SE_SHA_MSG_LENGTH_0_REG_OFFSET) = (u32)(total_size << 3);
|
||||
SE(SE_SHA_MSG_LENGTH_1_REG_OFFSET) = (u32)(total_size >> 29);
|
||||
SE(SE_SHA_MSG_LENGTH_2_REG_OFFSET) = 0;
|
||||
SE(SE_SHA_MSG_LENGTH_3_REG_OFFSET) = 0;
|
||||
SE(SE_SHA_MSG_LENGTH_0_REG) = (u32)(total_size << 3);
|
||||
SE(SE_SHA_MSG_LENGTH_1_REG) = (u32)(total_size >> 29);
|
||||
SE(SE_SHA_MSG_LENGTH_2_REG) = 0;
|
||||
SE(SE_SHA_MSG_LENGTH_3_REG) = 0;
|
||||
|
||||
// Set size left to hash.
|
||||
SE(SE_SHA_MSG_LEFT_0_REG_OFFSET) = (u32)(total_size << 3);
|
||||
SE(SE_SHA_MSG_LEFT_1_REG_OFFSET) = (u32)(total_size >> 29);
|
||||
SE(SE_SHA_MSG_LEFT_2_REG_OFFSET) = 0;
|
||||
SE(SE_SHA_MSG_LEFT_3_REG_OFFSET) = 0;
|
||||
SE(SE_SHA_MSG_LEFT_0_REG) = (u32)(total_size << 3);
|
||||
SE(SE_SHA_MSG_LEFT_1_REG) = (u32)(total_size >> 29);
|
||||
SE(SE_SHA_MSG_LEFT_2_REG) = 0;
|
||||
SE(SE_SHA_MSG_LEFT_3_REG) = 0;
|
||||
|
||||
// If we hash in chunks, copy over the intermediate.
|
||||
if (sha_cfg == SHA_CONTINUE && msg_left)
|
||||
{
|
||||
// Restore message left to process.
|
||||
SE(SE_SHA_MSG_LEFT_0_REG_OFFSET) = msg_left[0];
|
||||
SE(SE_SHA_MSG_LEFT_1_REG_OFFSET) = msg_left[1];
|
||||
SE(SE_SHA_MSG_LEFT_0_REG) = msg_left[0];
|
||||
SE(SE_SHA_MSG_LEFT_1_REG) = msg_left[1];
|
||||
|
||||
// Restore hash reg.
|
||||
memcpy(hash32, hash, TEGRA_SE_SHA_256_SIZE);
|
||||
for (u32 i = 0; i < (TEGRA_SE_SHA_256_SIZE / 4); i++)
|
||||
SE(SE_HASH_RESULT_REG_OFFSET + (i << 2)) = byte_swap_32(hash32[i]);
|
||||
memcpy(hash32, hash, SE_SHA_256_SIZE);
|
||||
for (u32 i = 0; i < (SE_SHA_256_SIZE / 4); i++)
|
||||
SE(SE_HASH_RESULT_REG + (i * 4)) = byte_swap_32(hash32[i]);
|
||||
}
|
||||
|
||||
// Trigger the operation.
|
||||
res = _se_execute(OP_START, NULL, 0, src, src_size, is_oneshot);
|
||||
res = _se_execute(SE_OP_START, NULL, 0, src, src_size, is_oneshot);
|
||||
|
||||
if (is_oneshot)
|
||||
{
|
||||
// Backup message left.
|
||||
if (msg_left)
|
||||
{
|
||||
msg_left[0] = SE(SE_SHA_MSG_LEFT_0_REG_OFFSET);
|
||||
msg_left[1] = SE(SE_SHA_MSG_LEFT_1_REG_OFFSET);
|
||||
msg_left[0] = SE(SE_SHA_MSG_LEFT_0_REG);
|
||||
msg_left[1] = SE(SE_SHA_MSG_LEFT_1_REG);
|
||||
}
|
||||
|
||||
// Copy output hash.
|
||||
for (u32 i = 0; i < (TEGRA_SE_SHA_256_SIZE / 4); i++)
|
||||
hash32[i] = byte_swap_32(SE(SE_HASH_RESULT_REG_OFFSET + (i << 2)));
|
||||
memcpy(hash, hash32, TEGRA_SE_SHA_256_SIZE);
|
||||
for (u32 i = 0; i < (SE_SHA_256_SIZE / 4); i++)
|
||||
hash32[i] = byte_swap_32(SE(SE_HASH_RESULT_REG + (i * 4)));
|
||||
memcpy(hash, hash32, SE_SHA_256_SIZE);
|
||||
}
|
||||
|
||||
return res;
|
||||
@@ -442,20 +442,20 @@ int se_calc_sha256_oneshot(void *hash, const void *src, u32 src_size)
|
||||
|
||||
int se_calc_sha256_finalize(void *hash, u32 *msg_left)
|
||||
{
|
||||
u32 hash32[TEGRA_SE_SHA_256_SIZE / 4];
|
||||
u32 hash32[SE_SHA_256_SIZE / 4];
|
||||
int res = _se_execute_finalize();
|
||||
|
||||
// Backup message left.
|
||||
if (msg_left)
|
||||
{
|
||||
msg_left[0] = SE(SE_SHA_MSG_LEFT_0_REG_OFFSET);
|
||||
msg_left[1] = SE(SE_SHA_MSG_LEFT_1_REG_OFFSET);
|
||||
msg_left[0] = SE(SE_SHA_MSG_LEFT_0_REG);
|
||||
msg_left[1] = SE(SE_SHA_MSG_LEFT_1_REG);
|
||||
}
|
||||
|
||||
// Copy output hash.
|
||||
for (u32 i = 0; i < (TEGRA_SE_SHA_256_SIZE / 4); i++)
|
||||
hash32[i] = byte_swap_32(SE(SE_HASH_RESULT_REG_OFFSET + (i << 2)));
|
||||
memcpy(hash, hash32, TEGRA_SE_SHA_256_SIZE);
|
||||
for (u32 i = 0; i < (SE_SHA_256_SIZE / 4); i++)
|
||||
hash32[i] = byte_swap_32(SE(SE_HASH_RESULT_REG + (i * 4)));
|
||||
memcpy(hash, hash32, SE_SHA_256_SIZE);
|
||||
|
||||
return res;
|
||||
}
|
||||
@@ -463,18 +463,17 @@ int se_calc_sha256_finalize(void *hash, u32 *msg_left)
|
||||
int se_gen_prng128(void *dst)
|
||||
{
|
||||
// Setup config for X931 PRNG.
|
||||
SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_ENC_MODE(MODE_KEY128) | SE_CONFIG_ENC_ALG(ALG_RNG) | SE_CONFIG_DST(DST_MEMORY);
|
||||
SE(SE_CRYPTO_REG_OFFSET) = SE_CRYPTO_HASH(HASH_DISABLE) | SE_CRYPTO_XOR_POS(XOR_BYPASS) | SE_CRYPTO_INPUT_SEL(INPUT_RANDOM);
|
||||
SE(SE_CONFIG_REG) = SE_CONFIG_ENC_MODE(MODE_KEY128) | SE_CONFIG_ENC_ALG(ALG_RNG) | SE_CONFIG_DST(DST_MEMORY);
|
||||
SE(SE_CRYPTO_CONFIG_REG) = SE_CRYPTO_HASH(HASH_DISABLE) | SE_CRYPTO_XOR_POS(XOR_BYPASS) | SE_CRYPTO_INPUT_SEL(INPUT_RANDOM);
|
||||
SE(SE_RNG_CONFIG_REG) = SE_RNG_CONFIG_SRC(SRC_ENTROPY) | SE_RNG_CONFIG_MODE(MODE_NORMAL);
|
||||
//SE(SE_RNG_SRC_CONFIG_REG) =
|
||||
// SE_RNG_SRC_CONFIG_ENTR_SRC(RO_ENTR_ENABLE) | SE_RNG_SRC_CONFIG_ENTR_SRC_LOCK(RO_ENTR_LOCK_ENABLE);
|
||||
SE(SE_RNG_RESEED_INTERVAL_REG) = 1;
|
||||
|
||||
SE(SE_RNG_CONFIG_REG_OFFSET) = SE_RNG_CONFIG_SRC(RNG_SRC_ENTROPY) | SE_RNG_CONFIG_MODE(RNG_MODE_NORMAL);
|
||||
//SE(SE_RNG_SRC_CONFIG_REG_OFFSET) =
|
||||
// SE_RNG_SRC_CONFIG_ENT_SRC(RNG_SRC_RO_ENT_ENABLE) | SE_RNG_SRC_CONFIG_ENT_SRC_LOCK(RNG_SRC_RO_ENT_LOCK_ENABLE);
|
||||
SE(SE_RNG_RESEED_INTERVAL_REG_OFFSET) = 1;
|
||||
|
||||
SE(SE_BLOCK_COUNT_REG_OFFSET) = (16 >> 4) - 1;
|
||||
SE(SE_CRYPTO_BLOCK_COUNT_REG) = (16 >> 4) - 1;
|
||||
|
||||
// Trigger the operation.
|
||||
return _se_execute_oneshot(OP_START, dst, 16, NULL, 0);
|
||||
return _se_execute_oneshot(SE_OP_START, dst, 16, NULL, 0);
|
||||
}
|
||||
|
||||
void se_get_aes_keys(u8 *buf, u8 *keys, u32 keysize)
|
||||
@@ -482,43 +481,43 @@ void se_get_aes_keys(u8 *buf, u8 *keys, u32 keysize)
|
||||
u8 *aligned_buf = (u8 *)ALIGN((u32)buf, 0x40);
|
||||
|
||||
// Set Secure Random Key.
|
||||
SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_ENC_MODE(MODE_KEY128) | SE_CONFIG_ENC_ALG(ALG_RNG) | SE_CONFIG_DST(DST_SRK);
|
||||
SE(SE_CRYPTO_REG_OFFSET) = SE_CRYPTO_KEY_INDEX(0) | SE_CRYPTO_CORE_SEL(CORE_ENCRYPT) | SE_CRYPTO_INPUT_SEL(INPUT_RANDOM);
|
||||
SE(SE_RNG_CONFIG_REG_OFFSET) = SE_RNG_CONFIG_SRC(RNG_SRC_ENTROPY) | SE_RNG_CONFIG_MODE(RNG_MODE_FORCE_RESEED);
|
||||
SE(SE_CONFIG_REG) = SE_CONFIG_ENC_MODE(MODE_KEY128) | SE_CONFIG_ENC_ALG(ALG_RNG) | SE_CONFIG_DST(DST_SRK);
|
||||
SE(SE_CRYPTO_CONFIG_REG) = SE_CRYPTO_KEY_INDEX(0) | SE_CRYPTO_CORE_SEL(CORE_ENCRYPT) | SE_CRYPTO_INPUT_SEL(INPUT_RANDOM);
|
||||
SE(SE_RNG_CONFIG_REG) = SE_RNG_CONFIG_SRC(SRC_ENTROPY) | SE_RNG_CONFIG_MODE(MODE_FORCE_RESEED);
|
||||
SE(SE_CRYPTO_LAST_BLOCK) = 0;
|
||||
_se_execute_oneshot(OP_START, NULL, 0, NULL, 0);
|
||||
_se_execute_oneshot(SE_OP_START, NULL, 0, NULL, 0);
|
||||
|
||||
// Save AES keys.
|
||||
SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_ENC_MODE(MODE_KEY128) | SE_CONFIG_ENC_ALG(ALG_AES_ENC) | SE_CONFIG_DST(DST_MEMORY);
|
||||
SE(SE_CONFIG_REG) = SE_CONFIG_ENC_MODE(MODE_KEY128) | SE_CONFIG_ENC_ALG(ALG_AES_ENC) | SE_CONFIG_DST(DST_MEMORY);
|
||||
|
||||
for (u32 i = 0; i < TEGRA_SE_KEYSLOT_COUNT; i++)
|
||||
for (u32 i = 0; i < SE_AES_KEYSLOT_COUNT; i++)
|
||||
{
|
||||
SE(SE_CONTEXT_SAVE_CONFIG_REG_OFFSET) = SE_CONTEXT_SAVE_SRC(AES_KEYTABLE) |
|
||||
(i << SE_KEY_INDEX_SHIFT) | SE_CONTEXT_SAVE_WORD_QUAD(KEYS_0_3);
|
||||
SE(SE_CONTEXT_SAVE_CONFIG_REG) = SE_CONTEXT_SRC(AES_KEYTABLE) | SE_KEYTABLE_DST_KEY_INDEX(i) |
|
||||
SE_CONTEXT_AES_KEY_INDEX(0) | SE_CONTEXT_AES_WORD_QUAD(KEYS_0_3);
|
||||
|
||||
SE(SE_CRYPTO_LAST_BLOCK) = 0;
|
||||
_se_execute_oneshot(OP_CTX_SAVE, aligned_buf, 0x10, NULL, 0);
|
||||
memcpy(keys + i * keysize, aligned_buf, 0x10);
|
||||
_se_execute_oneshot(SE_OP_CTX_SAVE, aligned_buf, SE_AES_BLOCK_SIZE, NULL, 0);
|
||||
memcpy(keys + i * keysize, aligned_buf, SE_AES_BLOCK_SIZE);
|
||||
|
||||
if (keysize > 0x10)
|
||||
if (keysize > SE_KEY_128_SIZE)
|
||||
{
|
||||
SE(SE_CONTEXT_SAVE_CONFIG_REG_OFFSET) = SE_CONTEXT_SAVE_SRC(AES_KEYTABLE) |
|
||||
(i << SE_KEY_INDEX_SHIFT) | SE_CONTEXT_SAVE_WORD_QUAD(KEYS_4_7);
|
||||
SE(SE_CONTEXT_SAVE_CONFIG_REG) = SE_CONTEXT_SRC(AES_KEYTABLE) | SE_KEYTABLE_DST_KEY_INDEX(i) |
|
||||
SE_CONTEXT_AES_KEY_INDEX(0) | SE_CONTEXT_AES_WORD_QUAD(KEYS_4_7);
|
||||
|
||||
SE(SE_CRYPTO_LAST_BLOCK) = 0;
|
||||
_se_execute_oneshot(OP_CTX_SAVE, aligned_buf, 0x10, NULL, 0);
|
||||
memcpy(keys + i * keysize + 0x10, aligned_buf, 0x10);
|
||||
_se_execute_oneshot(SE_OP_CTX_SAVE, aligned_buf, SE_AES_BLOCK_SIZE, NULL, 0);
|
||||
memcpy(keys + i * keysize + SE_AES_BLOCK_SIZE, aligned_buf, SE_AES_BLOCK_SIZE);
|
||||
}
|
||||
}
|
||||
|
||||
// Save SRK to PMC secure scratches.
|
||||
SE(SE_CONTEXT_SAVE_CONFIG_REG_OFFSET) = SE_CONTEXT_SAVE_SRC(SRK);
|
||||
SE(SE_CRYPTO_LAST_BLOCK) = 0;
|
||||
_se_execute_oneshot(OP_CTX_SAVE, NULL, 0, NULL, 0);
|
||||
SE(SE_CONTEXT_SAVE_CONFIG_REG) = SE_CONTEXT_SRC(SRK);
|
||||
SE(SE_CRYPTO_LAST_BLOCK) = 0;
|
||||
_se_execute_oneshot(SE_OP_CTX_SAVE, NULL, 0, NULL, 0);
|
||||
|
||||
// End context save.
|
||||
SE(SE_CONFIG_REG_OFFSET) = 0;
|
||||
_se_execute_oneshot(OP_CTX_SAVE, NULL, 0, NULL, 0);
|
||||
SE(SE_CONFIG_REG) = 0;
|
||||
_se_execute_oneshot(SE_OP_CTX_SAVE, NULL, 0, NULL, 0);
|
||||
|
||||
// Get SRK.
|
||||
u32 srk[4];
|
||||
@@ -529,7 +528,7 @@ void se_get_aes_keys(u8 *buf, u8 *keys, u32 keysize)
|
||||
|
||||
// Decrypt context.
|
||||
se_aes_key_clear(3);
|
||||
se_aes_key_set(3, srk, 0x10);
|
||||
se_aes_crypt_cbc(3, 0, keys, TEGRA_SE_KEYSLOT_COUNT * keysize, keys, TEGRA_SE_KEYSLOT_COUNT * keysize);
|
||||
se_aes_key_set(3, srk, SE_KEY_128_SIZE);
|
||||
se_aes_crypt_cbc(3, 0, keys, SE_AES_KEYSLOT_COUNT * keysize, keys, SE_AES_KEYSLOT_COUNT * keysize);
|
||||
se_aes_key_clear(3);
|
||||
}
|
||||
|
||||
47
bdk/sec/se.h
47
bdk/sec/se.h
@@ -1,18 +1,19 @@
|
||||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2019-2021 CTCaer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _SE_H_
|
||||
#define _SE_H_
|
||||
@@ -28,14 +29,14 @@ void se_aes_iv_set(u32 ks, void *iv);
|
||||
void se_aes_key_get(u32 ks, void *key, u32 size);
|
||||
void se_aes_key_clear(u32 ks);
|
||||
void se_aes_iv_clear(u32 ks);
|
||||
int se_aes_unwrap_key(u32 ks_dst, u32 ks_src, const void *input);
|
||||
int se_aes_crypt_cbc(u32 ks, u32 enc, void *dst, u32 dst_size, const void *src, u32 src_size);
|
||||
int se_aes_crypt_ecb(u32 ks, u32 enc, void *dst, u32 dst_size, const void *src, u32 src_size);
|
||||
int se_aes_crypt_block_ecb(u32 ks, u32 enc, void *dst, const void *src);
|
||||
int se_aes_crypt_ctr(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_size, void *ctr);
|
||||
int se_calc_sha256(void *hash, u32 *msg_left, const void *src, u32 src_size, u64 total_size, u32 sha_cfg, bool is_oneshot);
|
||||
int se_calc_sha256_oneshot(void *hash, const void *src, u32 src_size);
|
||||
int se_calc_sha256_finalize(void *hash, u32 *msg_left);
|
||||
int se_gen_prng128(void *dst);
|
||||
int se_aes_unwrap_key(u32 ks_dst, u32 ks_src, const void *input);
|
||||
int se_aes_crypt_cbc(u32 ks, u32 enc, void *dst, u32 dst_size, const void *src, u32 src_size);
|
||||
int se_aes_crypt_ecb(u32 ks, u32 enc, void *dst, u32 dst_size, const void *src, u32 src_size);
|
||||
int se_aes_crypt_block_ecb(u32 ks, u32 enc, void *dst, const void *src);
|
||||
int se_aes_crypt_ctr(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_size, void *ctr);
|
||||
int se_calc_sha256(void *hash, u32 *msg_left, const void *src, u32 src_size, u64 total_size, u32 sha_cfg, bool is_oneshot);
|
||||
int se_calc_sha256_oneshot(void *hash, const void *src, u32 src_size);
|
||||
int se_calc_sha256_finalize(void *hash, u32 *msg_left);
|
||||
int se_gen_prng128(void *dst);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,400 +1,323 @@
|
||||
/*
|
||||
* Driver for Tegra Security Engine
|
||||
*
|
||||
* Copyright (c) 2011-2013, NVIDIA Corporation. All Rights Reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2018-2021 CTCaer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _CRYPTO_TEGRA_SE_H
|
||||
#define _CRYPTO_TEGRA_SE_H
|
||||
#ifndef _SE_T210_H
|
||||
#define _SE_T210_H
|
||||
|
||||
#include <utils/types.h>
|
||||
|
||||
#define TEGRA_SE_CRA_PRIORITY 300
|
||||
#define TEGRA_SE_COMPOSITE_PRIORITY 400
|
||||
#define TEGRA_SE_CRYPTO_QUEUE_LENGTH 50
|
||||
#define SE_MAX_SRC_SG_COUNT 50
|
||||
#define SE_MAX_DST_SG_COUNT 50
|
||||
#define SE_CRYPTO_QUEUE_LENGTH 50
|
||||
#define SE_MAX_SRC_SG_COUNT 50
|
||||
#define SE_MAX_DST_SG_COUNT 50
|
||||
|
||||
#define TEGRA_SE_KEYSLOT_COUNT 16
|
||||
#define SE_MAX_LAST_BLOCK_SIZE 0xFFFFF
|
||||
#define SE_AES_KEYSLOT_COUNT 16
|
||||
#define SE_RSA_KEYSLOT_COUNT 2
|
||||
#define SE_MAX_LAST_BLOCK_SIZE 0xFFFFF
|
||||
|
||||
#define SE_AES_BLOCK_SIZE 16
|
||||
#define SE_AES_IV_SIZE 16
|
||||
#define SE_AES_MIN_KEY_SIZE 16
|
||||
#define SE_AES_MAX_KEY_SIZE 32
|
||||
#define SE_KEY_128_SIZE 16
|
||||
#define SE_KEY_192_SIZE 24
|
||||
#define SE_KEY_256_SIZE 32
|
||||
#define SE_SHA_192_SIZE 24
|
||||
#define SE_SHA_256_SIZE 32
|
||||
#define SE_SHA_384_SIZE 48
|
||||
#define SE_SHA_512_SIZE 64
|
||||
#define SE_RNG_IV_SIZE 16
|
||||
#define SE_RNG_DT_SIZE 16
|
||||
#define SE_RNG_KEY_SIZE 16
|
||||
#define SE_RNG_SEED_SIZE (SE_RNG_IV_SIZE + SE_RNG_KEY_SIZE + SE_RNG_DT_SIZE)
|
||||
|
||||
#define SE_AES_CMAC_DIGEST_SIZE 16
|
||||
#define SE_RSA512_DIGEST_SIZE 64
|
||||
#define SE_RSA1024_DIGEST_SIZE 128
|
||||
#define SE_RSA1536_DIGEST_SIZE 192
|
||||
#define SE_RSA2048_DIGEST_SIZE 256
|
||||
|
||||
/* SE register definitions */
|
||||
#define SE_SECURITY_0 0x000
|
||||
#define SE_KEY_SCHED_READ_SHIFT 3
|
||||
#define SE_SE_SECURITY_REG 0x000
|
||||
#define SE_HARD_SETTING BIT(0)
|
||||
#define SE_ENG_DIS BIT(1)
|
||||
#define SE_PERKEY_SETTING BIT(2)
|
||||
#define SE_SOFT_SETTING BIT(16)
|
||||
|
||||
#define SE_TZRAM_SECURITY_0 0x004
|
||||
#define SE_TZRAM_SECURITY_REG 0x004
|
||||
#define SE_TZRAM_HARD_SETTING BIT(0)
|
||||
#define SE_TZRAM_ENG_DIS BIT(1)
|
||||
|
||||
#define SE_CONFIG_REG_OFFSET 0x014
|
||||
#define SE_CONFIG_ENC_ALG_SHIFT 12
|
||||
#define SE_CONFIG_DEC_ALG_SHIFT 8
|
||||
#define ALG_AES_ENC 1
|
||||
#define ALG_RNG 2
|
||||
#define ALG_SHA 3
|
||||
#define ALG_RSA 4
|
||||
#define ALG_NOP 0
|
||||
#define ALG_AES_DEC 1
|
||||
#define SE_CONFIG_ENC_ALG(x) ((x) << SE_CONFIG_ENC_ALG_SHIFT)
|
||||
#define SE_CONFIG_DEC_ALG(x) ((x) << SE_CONFIG_DEC_ALG_SHIFT)
|
||||
#define SE_CONFIG_DST_SHIFT 2
|
||||
#define DST_MEMORY 0
|
||||
#define DST_HASHREG 1
|
||||
#define DST_KEYTAB 2
|
||||
#define DST_SRK 3
|
||||
#define DST_RSAREG 4
|
||||
#define SE_CONFIG_DST(x) ((x) << SE_CONFIG_DST_SHIFT)
|
||||
#define SE_CONFIG_ENC_MODE_SHIFT 24
|
||||
#define SE_CONFIG_DEC_MODE_SHIFT 16
|
||||
#define MODE_KEY128 0
|
||||
#define MODE_KEY192 1
|
||||
#define MODE_KEY256 2
|
||||
#define MODE_SHA1 0
|
||||
#define MODE_SHA224 4
|
||||
#define MODE_SHA256 5
|
||||
#define MODE_SHA384 6
|
||||
#define MODE_SHA512 7
|
||||
#define SE_CONFIG_ENC_MODE(x) ((x) << SE_CONFIG_ENC_MODE_SHIFT)
|
||||
#define SE_CONFIG_DEC_MODE(x) ((x) << SE_CONFIG_DEC_MODE_SHIFT)
|
||||
#define SE_OPERATION_REG 0x008
|
||||
#define SE_OP_ABORT 0
|
||||
#define SE_OP_START 1
|
||||
#define SE_OP_RESTART_OUT 2
|
||||
#define SE_OP_CTX_SAVE 3
|
||||
#define SE_OP_RESTART_IN 4
|
||||
|
||||
#define SE_RNG_CONFIG_REG_OFFSET 0x340
|
||||
#define RNG_MODE_SHIFT 0
|
||||
#define RNG_MODE_NORMAL 0
|
||||
#define RNG_MODE_FORCE_INSTANTION 1
|
||||
#define RNG_MODE_FORCE_RESEED 2
|
||||
#define SE_RNG_CONFIG_MODE(x) ((x) << RNG_MODE_SHIFT)
|
||||
#define RNG_SRC_SHIFT 2
|
||||
#define RNG_SRC_NONE 0
|
||||
#define RNG_SRC_ENTROPY 1
|
||||
#define RNG_SRC_LFSR 2
|
||||
#define SE_RNG_CONFIG_SRC(x) ((x) << RNG_SRC_SHIFT)
|
||||
#define SE_INT_ENABLE_REG 0x00C
|
||||
#define SE_INT_STATUS_REG 0x010
|
||||
#define SE_INT_IN_LL_BUF_RD BIT(0)
|
||||
#define SE_INT_IN_DONE BIT(1)
|
||||
#define SE_INT_OUT_LL_BUF_WR BIT(2)
|
||||
#define SE_INT_OUT_DONE BIT(3)
|
||||
#define SE_INT_OP_DONE BIT(4)
|
||||
#define SE_INT_RESEED_NEEDED BIT(5)
|
||||
#define SE_INT_ERR_STAT BIT(16)
|
||||
|
||||
#define SE_RNG_SRC_CONFIG_REG_OFFSET 0x344
|
||||
#define RNG_SRC_RO_ENT_SHIFT 1
|
||||
#define RNG_SRC_RO_ENT_ENABLE 1
|
||||
#define RNG_SRC_RO_ENT_DISABLE 0
|
||||
#define SE_RNG_SRC_CONFIG_ENT_SRC(x) ((x) << RNG_SRC_RO_ENT_SHIFT)
|
||||
#define RNG_SRC_RO_ENT_LOCK_SHIFT 0
|
||||
#define RNG_SRC_RO_ENT_LOCK_ENABLE 1
|
||||
#define RNG_SRC_RO_ENT_LOCK_DISABLE 0
|
||||
#define SE_RNG_SRC_CONFIG_ENT_SRC_LOCK(x) ((x) << RNG_SRC_RO_ENT_LOCK_SHIFT)
|
||||
#define SE_CONFIG_REG 0x014
|
||||
#define DST_MEMORY 0
|
||||
#define DST_HASHREG 1
|
||||
#define DST_KEYTABLE 2
|
||||
#define DST_SRK 3
|
||||
#define DST_RSAREG 4
|
||||
#define SE_CONFIG_DST(x) ((x) << 2)
|
||||
#define ALG_NOP 0
|
||||
#define ALG_AES_DEC 1
|
||||
#define SE_CONFIG_DEC_ALG(x) ((x) << 8)
|
||||
#define ALG_NOP 0
|
||||
#define ALG_AES_ENC 1
|
||||
#define ALG_RNG 2
|
||||
#define ALG_SHA 3
|
||||
#define ALG_RSA 4
|
||||
#define SE_CONFIG_ENC_ALG(x) ((x) << 12)
|
||||
#define MODE_KEY128 0
|
||||
#define MODE_KEY192 1
|
||||
#define MODE_KEY256 2
|
||||
#define MODE_SHA1 0
|
||||
#define MODE_SHA224 4
|
||||
#define MODE_SHA256 5
|
||||
#define MODE_SHA384 6
|
||||
#define MODE_SHA512 7
|
||||
#define SE_CONFIG_DEC_MODE(x) ((x) << 16)
|
||||
#define SE_CONFIG_ENC_MODE(x) ((x) << 24)
|
||||
|
||||
#define SE_RNG_RESEED_INTERVAL_REG_OFFSET 0x348
|
||||
#define SE_IN_LL_ADDR_REG 0x018
|
||||
#define SE_IN_CUR_BYTE_ADDR_REG 0x01C
|
||||
#define SE_IN_CUR_LL_ID_REG 0x020
|
||||
#define SE_OUT_LL_ADDR_REG 0x024
|
||||
#define SE_OUT_CUR_BYTE_ADDR_REG 0x028
|
||||
#define SE_OUT_CUR_LL_ID_REG 0x02C
|
||||
|
||||
#define SE_KEYTABLE_REG_OFFSET 0x31c
|
||||
#define SE_KEYTABLE_SLOT_SHIFT 4
|
||||
#define SE_KEYTABLE_SLOT(x) ((x) << SE_KEYTABLE_SLOT_SHIFT)
|
||||
#define SE_KEYTABLE_QUAD_SHIFT 2
|
||||
#define QUAD_KEYS_128 0
|
||||
#define QUAD_KEYS_192 1
|
||||
#define QUAD_KEYS_256 1
|
||||
#define QUAD_ORG_IV 2
|
||||
#define QUAD_UPDTD_IV 3
|
||||
#define SE_KEYTABLE_QUAD(x) ((x) << SE_KEYTABLE_QUAD_SHIFT)
|
||||
#define SE_KEYTABLE_OP_TYPE_SHIFT 9
|
||||
#define OP_READ 0
|
||||
#define OP_WRITE 1
|
||||
#define SE_KEYTABLE_OP_TYPE(x) ((x) << SE_KEYTABLE_OP_TYPE_SHIFT)
|
||||
#define SE_KEYTABLE_TABLE_SEL_SHIFT 8
|
||||
#define TABLE_KEYIV 0
|
||||
#define TABLE_SCHEDULE 1
|
||||
#define SE_KEYTABLE_TABLE_SEL(x) ((x) << SE_KEYTABLE_TABLE_SEL_SHIFT)
|
||||
#define SE_KEYTABLE_PKT_SHIFT 0
|
||||
#define SE_KEYTABLE_PKT(x) ((x) << SE_KEYTABLE_PKT_SHIFT)
|
||||
#define SE_HASH_RESULT_REG 0x030
|
||||
#define SE_HASH_RESULT_REG_COUNT 16
|
||||
|
||||
#define SE_OP_DONE_SHIFT 4
|
||||
#define OP_DONE 1
|
||||
#define SE_OP_DONE(x, y) ((x) && ((y) << SE_OP_DONE_SHIFT))
|
||||
#define SE_CONTEXT_SAVE_CONFIG_REG 0x070
|
||||
#define KEYS_0_3 0
|
||||
#define KEYS_4_7 1
|
||||
#define ORIGINAL_IV 2
|
||||
#define UPDATED_IV 3
|
||||
#define SE_CONTEXT_AES_WORD_QUAD(x) ((x) << 0)
|
||||
#define SE_CONTEXT_AES_KEY_INDEX(x) ((x) << 8)
|
||||
#define KEYS_0_3 0
|
||||
#define KEYS_4_7 1
|
||||
#define KEYS_8_11 2
|
||||
#define KEYS_12_15 3
|
||||
#define SE_CONTEXT_RSA_WORD_QUAD(x) ((x) << 12)
|
||||
#define SLOT0_EXPONENT 0
|
||||
#define SLOT0_MODULUS 1
|
||||
#define SLOT1_EXPONENT 2
|
||||
#define SLOT1_MODULUS 3
|
||||
#define SE_CONTEXT_RSA_KEY_INDEX(x) ((x) << 16)
|
||||
#define STICKY_0_3 0
|
||||
#define STICKY_4_7 1
|
||||
#define SE_CONTEXT_STICKY_WORD_QUAD(x) ((x) << 24)
|
||||
#define STICKY_BITS 0
|
||||
#define RSA_KEYTABLE 1
|
||||
#define AES_KEYTABLE 2
|
||||
#define MEM 4
|
||||
#define SRK 6
|
||||
#define SE_CONTEXT_SRC(x) ((x) << 29)
|
||||
|
||||
#define SE_CRYPTO_LAST_BLOCK 0x080
|
||||
#define SE_CTX_SAVE_AUTO_T210B01_REG 0x074
|
||||
#define SE_CTX_SAVE_AUTO_ENABLE BIT(0)
|
||||
#define SE_CTX_SAVE_AUTO_LOCK BIT(8)
|
||||
#define SE_CTX_SAVE_AUTO_CURR_CNT_MASK (0x3FF << 16)
|
||||
|
||||
#define SE_CRYPTO_REG_OFFSET 0x304
|
||||
#define SE_CRYPTO_HASH_SHIFT 0
|
||||
#define HASH_DISABLE 0
|
||||
#define HASH_ENABLE 1
|
||||
#define SE_CRYPTO_HASH(x) ((x) << SE_CRYPTO_HASH_SHIFT)
|
||||
#define SE_CRYPTO_XOR_POS_SHIFT 1
|
||||
#define XOR_BYPASS 0
|
||||
#define XOR_TOP 2
|
||||
#define XOR_BOTTOM 3
|
||||
#define SE_CRYPTO_XOR_POS(x) ((x) << SE_CRYPTO_XOR_POS_SHIFT)
|
||||
#define SE_CRYPTO_INPUT_SEL_SHIFT 3
|
||||
#define INPUT_AHB 0
|
||||
#define INPUT_RANDOM 1
|
||||
#define INPUT_AESOUT 2
|
||||
#define INPUT_LNR_CTR 3
|
||||
#define SE_CRYPTO_INPUT_SEL(x) ((x) << SE_CRYPTO_INPUT_SEL_SHIFT)
|
||||
#define SE_CRYPTO_VCTRAM_SEL_SHIFT 5
|
||||
#define VCTRAM_AHB 0
|
||||
#define VCTRAM_AESOUT 2
|
||||
#define VCTRAM_PREVAHB 3
|
||||
#define SE_CRYPTO_VCTRAM_SEL(x) ((x) << SE_CRYPTO_VCTRAM_SEL_SHIFT)
|
||||
#define SE_CRYPTO_IV_SEL_SHIFT 7
|
||||
#define IV_ORIGINAL 0
|
||||
#define IV_UPDATED 1
|
||||
#define SE_CRYPTO_IV_SEL(x) ((x) << SE_CRYPTO_IV_SEL_SHIFT)
|
||||
#define SE_CRYPTO_CORE_SEL_SHIFT 8
|
||||
#define CORE_DECRYPT 0
|
||||
#define CORE_ENCRYPT 1
|
||||
#define SE_CRYPTO_CORE_SEL(x) ((x) << SE_CRYPTO_CORE_SEL_SHIFT)
|
||||
#define SE_CRYPTO_CTR_VAL_SHIFT 11
|
||||
#define SE_CRYPTO_CTR_VAL(x) ((x) << SE_CRYPTO_CTR_VAL_SHIFT)
|
||||
#define SE_CRYPTO_KEY_INDEX_SHIFT 24
|
||||
#define SE_CRYPTO_KEY_INDEX(x) ((x) << SE_CRYPTO_KEY_INDEX_SHIFT)
|
||||
#define SE_CRYPTO_CTR_CNTN_SHIFT 11
|
||||
#define SE_CRYPTO_CTR_CNTN(x) ((x) << SE_CRYPTO_CTR_CNTN_SHIFT)
|
||||
#define SE_CRYPTO_LAST_BLOCK 0x080
|
||||
|
||||
#define SE_CRYPTO_CTR_REG_COUNT 4
|
||||
#define SE_CRYPTO_CTR_REG_OFFSET 0x308
|
||||
|
||||
#define SE_OPERATION_REG_OFFSET 0x008
|
||||
#define SE_OPERATION_SHIFT 0
|
||||
#define OP_ABORT 0
|
||||
#define OP_START 1
|
||||
#define OP_RESTART 2
|
||||
#define OP_CTX_SAVE 3
|
||||
#define OP_RESTART_IN 4
|
||||
#define SE_OPERATION(x) ((x) << SE_OPERATION_SHIFT)
|
||||
|
||||
#define SE_CONTEXT_SAVE_CONFIG_REG_OFFSET 0x070
|
||||
#define SE_CONTEXT_SAVE_WORD_QUAD_SHIFT 0
|
||||
#define KEYS_0_3 0
|
||||
#define KEYS_4_7 1
|
||||
#define ORIG_IV 2
|
||||
#define UPD_IV 3
|
||||
#define SE_CONTEXT_SAVE_WORD_QUAD(x) ((x) << SE_CONTEXT_SAVE_WORD_QUAD_SHIFT)
|
||||
|
||||
#define SE_CONTEXT_SAVE_KEY_INDEX_SHIFT 8
|
||||
#define SE_CONTEXT_SAVE_KEY_INDEX(x) ((x) << SE_CONTEXT_SAVE_KEY_INDEX_SHIFT)
|
||||
|
||||
#define SE_CONTEXT_SAVE_STICKY_WORD_QUAD_SHIFT 24
|
||||
#define STICKY_0_3 0
|
||||
#define STICKY_4_7 1
|
||||
#define SE_CONTEXT_SAVE_STICKY_WORD_QUAD(x) \
|
||||
((x) << SE_CONTEXT_SAVE_STICKY_WORD_QUAD_SHIFT)
|
||||
|
||||
#define SE_CONTEXT_SAVE_SRC_SHIFT 29
|
||||
#define STICKY_BITS 0
|
||||
#define KEYTABLE 2
|
||||
#define MEM 4
|
||||
#define SRK 6
|
||||
|
||||
#define RSA_KEYTABLE 1
|
||||
#define AES_KEYTABLE 2
|
||||
#define SE_CONTEXT_SAVE_SRC(x) ((x) << SE_CONTEXT_SAVE_SRC_SHIFT)
|
||||
|
||||
#define SE_CONTEXT_SAVE_RSA_KEY_INDEX_SHIFT 16
|
||||
#define SE_CONTEXT_SAVE_RSA_KEY_INDEX(x) \
|
||||
((x) << SE_CONTEXT_SAVE_RSA_KEY_INDEX_SHIFT)
|
||||
|
||||
#define SE_CONTEXT_RSA_WORD_QUAD_SHIFT 12
|
||||
#define SE_CONTEXT_RSA_WORD_QUAD(x) \
|
||||
((x) << SE_CONTEXT_RSA_WORD_QUAD_SHIFT)
|
||||
|
||||
#define SE_CTX_SAVE_AUTO 0x074
|
||||
#define CTX_SAVE_AUTO_ENABLE BIT(0)
|
||||
#define CTX_SAVE_AUTO_LOCK BIT(8)
|
||||
#define CTX_SAVE_AUTO_CURR_CNT_MASK (0x3FF << 16)
|
||||
|
||||
#define SE_INT_ENABLE_REG_OFFSET 0x00c
|
||||
#define SE_INT_STATUS_REG_OFFSET 0x010
|
||||
#define INT_DISABLE 0
|
||||
#define INT_ENABLE 1
|
||||
#define INT_UNSET 0
|
||||
#define INT_SET 1
|
||||
#define SE_INT_OP_DONE_SHIFT 4
|
||||
#define SE_INT_OP_DONE(x) ((x) << SE_INT_OP_DONE_SHIFT)
|
||||
#define SE_INT_ERROR_SHIFT 16
|
||||
#define SE_INT_ERROR(x) ((x) << SE_INT_ERROR_SHIFT)
|
||||
|
||||
#define SE_STATUS_0 0x800
|
||||
#define SE_STATUS_0_STATE_WAIT_IN 3
|
||||
|
||||
#define SE_ERR_STATUS_0 0x804
|
||||
#define SE_ERR_STATUS_0_SE_NS_ACCESS_CLEAR 0
|
||||
|
||||
#define SE_CRYPTO_KEYTABLE_DST_REG_OFFSET 0X330
|
||||
#define SE_CRYPTO_KEYTABLE_DST_WORD_QUAD_SHIFT 0
|
||||
#define SE_CRYPTO_KEYTABLE_DST_WORD_QUAD(x) \
|
||||
((x) << SE_CRYPTO_KEYTABLE_DST_WORD_QUAD_SHIFT)
|
||||
|
||||
#define SE_KEY_INDEX_SHIFT 8
|
||||
#define SE_CRYPTO_KEYTABLE_DST_KEY_INDEX(x) ((x) << SE_KEY_INDEX_SHIFT)
|
||||
|
||||
#define SE_IN_LL_ADDR_REG_OFFSET 0x018
|
||||
#define SE_OUT_LL_ADDR_REG_OFFSET 0x024
|
||||
|
||||
#define SE_KEYTABLE_DATA0_REG_OFFSET 0x320
|
||||
#define SE_KEYTABLE_REG_MAX_DATA 16
|
||||
|
||||
#define SE_BLOCK_COUNT_REG_OFFSET 0x318
|
||||
|
||||
#define SE_SPARE_0_REG_OFFSET 0x80c
|
||||
|
||||
#define SE_SHA_CONFIG_REG_OFFSET 0x200
|
||||
#define SE_SHA_CONFIG_REG 0x200
|
||||
#define SHA_CONTINUE 0
|
||||
#define SHA_INIT_HASH 1
|
||||
|
||||
#define SE_SHA_MSG_LENGTH_0_REG_OFFSET 0x204
|
||||
#define SE_SHA_MSG_LENGTH_1_REG_OFFSET 0x208
|
||||
#define SE_SHA_MSG_LENGTH_2_REG_OFFSET 0x20C
|
||||
#define SE_SHA_MSG_LENGTH_3_REG_OFFSET 0x210
|
||||
#define SE_SHA_MSG_LEFT_0_REG_OFFSET 0x214
|
||||
#define SE_SHA_MSG_LEFT_1_REG_OFFSET 0x218
|
||||
#define SE_SHA_MSG_LEFT_2_REG_OFFSET 0x21C
|
||||
#define SE_SHA_MSG_LEFT_3_REG_OFFSET 0x220
|
||||
#define SE_SHA_MSG_LENGTH_0_REG 0x204
|
||||
#define SE_SHA_MSG_LENGTH_1_REG 0x208
|
||||
#define SE_SHA_MSG_LENGTH_2_REG 0x20C
|
||||
#define SE_SHA_MSG_LENGTH_3_REG 0x210
|
||||
#define SE_SHA_MSG_LEFT_0_REG 0x214
|
||||
#define SE_SHA_MSG_LEFT_1_REG 0x218
|
||||
#define SE_SHA_MSG_LEFT_2_REG 0x21C
|
||||
#define SE_SHA_MSG_LEFT_3_REG 0x220
|
||||
|
||||
#define SE_HASH_RESULT_REG_COUNT 16
|
||||
#define SE_HASH_RESULT_REG_OFFSET 0x030
|
||||
#define TEGRA_SE_KEY_256_SIZE 32
|
||||
#define TEGRA_SE_KEY_192_SIZE 24
|
||||
#define TEGRA_SE_KEY_128_SIZE 16
|
||||
#define TEGRA_SE_AES_BLOCK_SIZE 16
|
||||
#define TEGRA_SE_AES_MIN_KEY_SIZE 16
|
||||
#define TEGRA_SE_AES_MAX_KEY_SIZE 32
|
||||
#define TEGRA_SE_AES_IV_SIZE 16
|
||||
#define TEGRA_SE_SHA_512_SIZE 64
|
||||
#define TEGRA_SE_SHA_384_SIZE 48
|
||||
#define TEGRA_SE_SHA_256_SIZE 32
|
||||
#define TEGRA_SE_SHA_192_SIZE 24
|
||||
#define TEGRA_SE_RNG_IV_SIZE 16
|
||||
#define TEGRA_SE_RNG_DT_SIZE 16
|
||||
#define TEGRA_SE_RNG_KEY_SIZE 16
|
||||
#define TEGRA_SE_RNG_SEED_SIZE (TEGRA_SE_RNG_IV_SIZE + \
|
||||
TEGRA_SE_RNG_KEY_SIZE + \
|
||||
TEGRA_SE_RNG_DT_SIZE)
|
||||
#define SE_CRYPTO_SECURITY_PERKEY_REG 0x280
|
||||
#define SE_KEY_LOCK_FLAG 0x80
|
||||
#define SE_CRYPTO_KEYTABLE_ACCESS_REG 0x284
|
||||
#define SE_CRYPTO_KEYTABLE_ACCESS_REG_COUNT 16
|
||||
#define SE_KEY_TBL_DIS_KEYREAD_FLAG BIT(0)
|
||||
#define SE_KEY_TBL_DIS_KEYUPDATE_FLAG BIT(1)
|
||||
#define SE_KEY_TBL_DIS_OIVREAD_FLAG BIT(2)
|
||||
#define SE_KEY_TBL_DIS_OIVUPDATE_FLAG BIT(3)
|
||||
#define SE_KEY_TBL_DIS_UIVREAD_FLAG BIT(4)
|
||||
#define SE_KEY_TBL_DIS_UIVUPDATE_FLAG BIT(5)
|
||||
#define SE_KEY_TBL_DIS_KEYUSE_FLAG BIT(6)
|
||||
#define SE_KEY_TBL_DIS_KEY_ACCESS_FLAG 0x7F
|
||||
|
||||
#define TEGRA_SE_AES_CMAC_DIGEST_SIZE 16
|
||||
#define TEGRA_SE_RSA512_DIGEST_SIZE 64
|
||||
#define TEGRA_SE_RSA1024_DIGEST_SIZE 128
|
||||
#define TEGRA_SE_RSA1536_DIGEST_SIZE 192
|
||||
#define TEGRA_SE_RSA2048_DIGEST_SIZE 256
|
||||
#define SE_CRYPTO_CONFIG_REG 0x304
|
||||
#define HASH_DISABLE 0
|
||||
#define HASH_ENABLE 1
|
||||
#define SE_CRYPTO_HASH(x) ((x) << 0)
|
||||
#define XOR_BYPASS 0
|
||||
#define XOR_TOP 2
|
||||
#define XOR_BOTTOM 3
|
||||
#define SE_CRYPTO_XOR_POS(x) ((x) << 1)
|
||||
#define INPUT_MEMORY 0
|
||||
#define INPUT_RANDOM 1
|
||||
#define INPUT_AESOUT 2
|
||||
#define INPUT_LNR_CTR 3
|
||||
#define SE_CRYPTO_INPUT_SEL(x) ((x) << 3)
|
||||
#define VCTRAM_MEM 0
|
||||
#define VCTRAM_AESOUT 2
|
||||
#define VCTRAM_PREVMEM 3
|
||||
#define SE_CRYPTO_VCTRAM_SEL(x) ((x) << 5)
|
||||
#define IV_ORIGINAL 0
|
||||
#define IV_UPDATED 1
|
||||
#define SE_CRYPTO_IV_SEL(x) ((x) << 7)
|
||||
#define CORE_DECRYPT 0
|
||||
#define CORE_ENCRYPT 1
|
||||
#define SE_CRYPTO_CORE_SEL(x) ((x) << 8)
|
||||
#define SE_CRYPTO_KEYSCH_BYPASS BIT(10)
|
||||
#define SE_CRYPTO_CTR_CNTN(x) ((x) << 11)
|
||||
#define SE_CRYPTO_KEY_INDEX(x) ((x) << 24)
|
||||
#define MEMIF_AHB 0
|
||||
#define MEMIF_MCCIF 1
|
||||
#define SE_CRYPTO_MEMIF(x) ((x) << 31)
|
||||
|
||||
#define SE_KEY_TABLE_ACCESS_LOCK_OFFSET 0x280
|
||||
#define SE_KEY_TBL_DIS_KEY_LOCK_FLAG 0x80
|
||||
#define SE_CRYPTO_LINEAR_CTR_REG 0x308
|
||||
#define SE_CRYPTO_LINEAR_CTR_REG_COUNT 4
|
||||
|
||||
#define SE_KEY_TABLE_ACCESS_REG_OFFSET 0x284
|
||||
#define SE_KEY_TBL_DIS_KEYREAD_FLAG BIT(0)
|
||||
#define SE_KEY_TBL_DIS_KEYUPDATE_FLAG BIT(1)
|
||||
#define SE_KEY_TBL_DIS_OIVREAD_FLAG BIT(2)
|
||||
#define SE_KEY_TBL_DIS_OIVUPDATE_FLAG BIT(3)
|
||||
#define SE_KEY_TBL_DIS_UIVREAD_FLAG BIT(4)
|
||||
#define SE_KEY_TBL_DIS_UIVUPDATE_FLAG BIT(5)
|
||||
#define SE_KEY_TBL_DIS_KEYUSE_FLAG BIT(6)
|
||||
#define SE_KEY_TBL_DIS_KEY_ACCESS_FLAG 0x7F
|
||||
#define SE_CRYPTO_BLOCK_COUNT_REG 0x318
|
||||
|
||||
#define SE_KEY_READ_DISABLE_SHIFT 0
|
||||
#define SE_KEY_UPDATE_DISABLE_SHIFT 1
|
||||
#define SE_CRYPTO_KEYTABLE_ADDR_REG 0x31C
|
||||
#define SE_KEYTABLE_PKT(x) ((x) << 0)
|
||||
#define KEYS_0_3 0
|
||||
#define KEYS_4_7 1
|
||||
#define ORIGINAL_IV 2
|
||||
#define UPDATED_IV 3
|
||||
#define SE_KEYTABLE_QUAD(x) ((x) << 2)
|
||||
#define SE_KEYTABLE_SLOT(x) ((x) << 4)
|
||||
|
||||
#define SE_CONTEXT_BUFER_SIZE 1072
|
||||
#define SE_CONTEXT_DRBG_BUFER_SIZE 2112
|
||||
#define SE_CRYPTO_KEYTABLE_DATA_REG 0x320
|
||||
|
||||
#define SE_CONTEXT_SAVE_RANDOM_DATA_OFFSET 0
|
||||
#define SE_CONTEXT_SAVE_RANDOM_DATA_SIZE 16
|
||||
#define SE_CONTEXT_SAVE_STICKY_BITS_OFFSET \
|
||||
(SE_CONTEXT_SAVE_RANDOM_DATA_OFFSET + SE_CONTEXT_SAVE_RANDOM_DATA_SIZE)
|
||||
#define SE_CONTEXT_SAVE_STICKY_BITS_SIZE 16
|
||||
#define SE_CRYPTO_KEYTABLE_DST_REG 0x330
|
||||
#define KEYS_0_3 0
|
||||
#define KEYS_4_7 1
|
||||
#define ORIGINAL_IV 2
|
||||
#define UPDATED_IV 3
|
||||
#define SE_KEYTABLE_DST_WORD_QUAD(x) ((x) << 0)
|
||||
#define SE_KEYTABLE_DST_KEY_INDEX(x) ((x) << 8)
|
||||
|
||||
#define SE_CONTEXT_SAVE_KEYS_OFFSET (SE_CONTEXT_SAVE_STICKY_BITS_OFFSET + \
|
||||
SE_CONTEXT_SAVE_STICKY_BITS_SIZE)
|
||||
#define SE11_CONTEXT_SAVE_KEYS_OFFSET (SE_CONTEXT_SAVE_STICKY_BITS_OFFSET + \
|
||||
SE_CONTEXT_SAVE_STICKY_BITS_SIZE + \
|
||||
SE_CONTEXT_SAVE_STICKY_BITS_SIZE)
|
||||
#define SE_RNG_CONFIG_REG 0x340
|
||||
#define MODE_NORMAL 0
|
||||
#define MODE_FORCE_INSTANTION 1
|
||||
#define MODE_FORCE_RESEED 2
|
||||
#define SE_RNG_CONFIG_MODE(x) ((x) << 0)
|
||||
#define SRC_NONE 0
|
||||
#define SRC_ENTROPY 1
|
||||
#define SRC_LFSR 2
|
||||
#define SE_RNG_CONFIG_SRC(x) ((x) << 2)
|
||||
|
||||
#define SE_CONTEXT_SAVE_KEY_LENGTH 512
|
||||
#define SE_CONTEXT_ORIGINAL_IV_OFFSET (SE_CONTEXT_SAVE_KEYS_OFFSET + \
|
||||
SE_CONTEXT_SAVE_KEY_LENGTH)
|
||||
#define SE11_CONTEXT_ORIGINAL_IV_OFFSET (SE11_CONTEXT_SAVE_KEYS_OFFSET + \
|
||||
SE_CONTEXT_SAVE_KEY_LENGTH)
|
||||
#define SE_RNG_SRC_CONFIG_REG 0x344
|
||||
#define RO_ENTR_LOCK_DISABLE 0
|
||||
#define RO_ENTR_LOCK_ENABLE 1
|
||||
#define SE_RNG_SRC_CONFIG_ENTR_SRC_LOCK(x) ((x) << 0)
|
||||
#define RO_ENTR_DISABLE 0
|
||||
#define RO_ENTR_ENABLE 1
|
||||
#define SE_RNG_SRC_CONFIG_ENTR_SRC(x) ((x) << 1)
|
||||
#define RO_HW_DIS_CYA_DISABLE 0
|
||||
#define RO_HW_DIS_CYA_ENABLE 1
|
||||
#define SE_RNG_SRC_CONFIG_HW_DIS_CYA(x) ((x) << 2)
|
||||
#define SE_RNG_SRC_CONFIG_ENTR_SUBSMPL(x) ((x) << 4)
|
||||
#define SE_RNG_SRC_CONFIG_ENTR_DATA_FLUSH BIT(8)
|
||||
|
||||
#define SE_CONTEXT_ORIGINAL_IV_LENGTH 256
|
||||
#define SE_RNG_RESEED_INTERVAL_REG 0x348
|
||||
|
||||
#define SE_CONTEXT_UPDATED_IV_OFFSET (SE_CONTEXT_ORIGINAL_IV_OFFSET + \
|
||||
SE_CONTEXT_ORIGINAL_IV_LENGTH)
|
||||
#define SE11_CONTEXT_UPDATED_IV_OFFSET (SE11_CONTEXT_ORIGINAL_IV_OFFSET + \
|
||||
SE_CONTEXT_ORIGINAL_IV_LENGTH)
|
||||
#define SE_RSA_CONFIG 0x400
|
||||
#define RSA_KEY_SLOT_ONE 0
|
||||
#define RSA_KEY_SLOT_TW0 1
|
||||
#define RSA_KEY_SLOT(x) ((x) << 24)
|
||||
|
||||
#define SE_CONTEXT_UPDATED_IV_LENGTH 256
|
||||
#define SE_RSA_KEY_SIZE_REG 0x404
|
||||
#define RSA_KEY_WIDTH_512 0
|
||||
#define RSA_KEY_WIDTH_1024 1
|
||||
#define RSA_KEY_WIDTH_1536 2
|
||||
#define RSA_KEY_WIDTH_2048 3
|
||||
|
||||
#define SE_CONTEXT_SAVE_KNOWN_PATTERN_OFFSET (SE_CONTEXT_UPDATED_IV_OFFSET + \
|
||||
SE_CONTEXT_UPDATED_IV_LENGTH)
|
||||
#define SE11_CONTEXT_SAVE_KNOWN_PATTERN_OFFSET \
|
||||
(SE11_CONTEXT_UPDATED_IV_OFFSET + \
|
||||
SE_CONTEXT_UPDATED_IV_LENGTH)
|
||||
#define SE_RSA_EXP_SIZE_REG 0x408
|
||||
|
||||
#define SE_CONTEXT_SAVE_RSA_KEYS_OFFSET SE11_CONTEXT_SAVE_KNOWN_PATTERN_OFFSET
|
||||
#define SE_RSA_SECURITY_PERKEY_REG 0x40C
|
||||
#define SE_RSA_KEY_LOCK_FLAG 0x80
|
||||
#define SE_RSA_KEYTABLE_ACCESS_REG 0x410
|
||||
#define SE_RSA_KEY_TBL_DIS_KEYREAD_FLAG BIT(0)
|
||||
#define SE_RSA_KEY_TBL_DIS_KEYUPDATE_FLAG BIT(1)
|
||||
#define SE_RSA_KEY_TBL_DIS_KEYUSE_FLAG BIT(2)
|
||||
#define SE_RSA_KEY_TBL_DIS_KEY_ACCESS_FLAG 0x7F
|
||||
#define SE_RSA_KEY_TBL_DIS_KEY_READ_UPDATE_FLAG (SE_RSA_KEY_TBL_DIS_KEYREAD_FLAG | SE_RSA_KEY_TBL_DIS_KEYUPDATE_FLAG)
|
||||
#define SE_RSA_KEY_TBL_DIS_KEY_READ_UPDATE_USE_FLAG (SE_RSA_KEY_TBL_DIS_KEYREAD_FLAG | SE_RSA_KEY_TBL_DIS_KEYUPDATE_FLAG | SE_RSA_KEY_TBL_DIS_KEYUSE_FLAG)
|
||||
|
||||
#define SE_CONTEXT_SAVE_RSA_KEY_LENGTH 1024
|
||||
#define SE_RSA_KEYTABLE_ADDR_REG 0x420
|
||||
#define SE_RSA_KEYTABLE_PKT(x) ((x) << 0)
|
||||
#define RSA_KEY_TYPE_EXP 0
|
||||
#define RSA_KEY_TYPE_MOD 1
|
||||
#define SE_RSA_KEYTABLE_TYPE(x) ((x) << 6)
|
||||
#define RSA_KEY_NUM(x) ((x) << 7)
|
||||
#define RSA_KEY_INPUT_MODE_REG 0
|
||||
#define RSA_KEY_INPUT_MODE_DMA 1
|
||||
#define SE_RSA_KEYTABLE_INPUT_MODE(x) ((x) << 8)
|
||||
#define RSA_KEY_READ 0
|
||||
#define RSA_KEY_WRITE 1
|
||||
#define SE_RSA_KEY_OP(x) ((x) << 10)
|
||||
|
||||
#define SE_CONTEXT_SAVE_RSA_KNOWN_PATTERN_OFFSET \
|
||||
(SE_CONTEXT_SAVE_RSA_KEYS_OFFSET + SE_CONTEXT_SAVE_RSA_KEY_LENGTH)
|
||||
#define SE_RSA_KEYTABLE_DATA_REG 0x424
|
||||
|
||||
#define SE_CONTEXT_KNOWN_PATTERN_SIZE 16
|
||||
#define SE_RSA_OUTPUT_REG 0x428
|
||||
#define SE_RSA_OUTPUT_REG_COUNT 64
|
||||
|
||||
#define TEGRA_SE_RSA_KEYSLOT_COUNT 2
|
||||
#define SE_STATUS_REG 0x800
|
||||
#define SE_STATUS_STATE_IDLE 0
|
||||
#define SE_STATUS_STATE_BUSY 1
|
||||
#define SE_STATUS_STATE_WAIT_OUT 2
|
||||
#define SE_STATUS_STATE_WAIT_IN 3
|
||||
#define SE_STATUS_STATE_MASK 3
|
||||
|
||||
#define SE_RSA_KEYTABLE_ACCESS_LOCK_OFFSET 0x40C
|
||||
#define SE_RSA_KEY_TBL_DIS_KEY_LOCK_FLAG 0x80
|
||||
#define SE_ERR_STATUS_REG 0x804
|
||||
#define SE_ERR_STATUS_SE_NS_ACCESS BIT(0)
|
||||
#define SE_ERR_STATUS_BUSY_REG_WR BIT(1)
|
||||
#define SE_ERR_STATUS_DST BIT(2)
|
||||
#define SE_ERR_STATUS_SRK_USAGE_LIMIT BIT(3)
|
||||
#define SE_ERR_STATUS_TZRAM_NS_ACCESS BIT(24)
|
||||
#define SE_ERR_STATUS_TZRAM_ADDRESS BIT(25)
|
||||
|
||||
#define SE_RSA_KEYTABLE_ACCESS_REG_OFFSET 0x410
|
||||
#define SE_RSA_KEY_TBL_DIS_KEYREAD_FLAG BIT(0)
|
||||
#define SE_RSA_KEY_TBL_DIS_KEYUPDATE_FLAG BIT(1)
|
||||
#define SE_RSA_KEY_TBL_DIS_KEY_READ_UPDATE_FLAG (SE_RSA_KEY_TBL_DIS_KEYREAD_FLAG | SE_RSA_KEY_TBL_DIS_KEYUPDATE_FLAG)
|
||||
#define SE_RSA_KEY_TBL_DIS_KEYUSE_FLAG BIT(2)
|
||||
#define SE_RSA_KEY_TBL_DIS_KEYUSE_FLAG_SHIFT BIT(2)
|
||||
#define SE_RSA_KEY_TBL_DIS_KEY_ALL_COMMON_FLAG 7
|
||||
#define SE_RSA_KEY_TBL_DIS_KEY_ALL_FLAG 0x7F
|
||||
#define SE_MISC_REG 0x808
|
||||
#define SE_ENTROPY_NEXT_192BIT BIT(0)
|
||||
#define SE_ENTROPY_VN_BYPASS BIT(1)
|
||||
#define SE_CLK_OVR_ON BIT(2)
|
||||
|
||||
#define SE_RSA_KEYTABLE_ADDR 0x420
|
||||
#define SE_RSA_KEYTABLE_DATA 0x424
|
||||
#define SE_RSA_OUTPUT 0x428
|
||||
#define SE_SPARE_REG 0x80C
|
||||
#define SE_ERRATA_FIX_DISABLE 0
|
||||
#define SE_ERRATA_FIX_ENABLE 1
|
||||
#define SE_ECO(x) ((x) << 0)
|
||||
|
||||
#define RSA_KEY_READ 0
|
||||
#define RSA_KEY_WRITE 1
|
||||
#define SE_RSA_KEY_OP_SHIFT 10
|
||||
#define SE_RSA_KEY_OP(x) ((x) << SE_RSA_KEY_OP_SHIFT)
|
||||
|
||||
#define RSA_KEY_INPUT_MODE_REG 0
|
||||
#define RSA_KEY_INPUT_MODE_DMA 1
|
||||
#define RSA_KEY_INPUT_MODE_SHIFT 8
|
||||
#define RSA_KEY_INPUT_MODE(x) ((x) << RSA_KEY_INPUT_MODE_SHIFT)
|
||||
|
||||
#define RSA_KEY_SLOT_ONE 0
|
||||
#define RSA_KEY_SLOT_TW0 1
|
||||
#define RSA_KEY_NUM_SHIFT 7
|
||||
#define RSA_KEY_NUM(x) ((x) << RSA_KEY_NUM_SHIFT)
|
||||
|
||||
#define RSA_KEY_TYPE_EXP 0
|
||||
#define RSA_KEY_TYPE_MOD 1
|
||||
#define RSA_KEY_TYPE_SHIFT 6
|
||||
#define RSA_KEY_TYPE(x) ((x) << RSA_KEY_TYPE_SHIFT)
|
||||
|
||||
#define SE_RSA_KEY_SIZE_REG_OFFSET 0x404
|
||||
#define SE_RSA_EXP_SIZE_REG_OFFSET 0x408
|
||||
|
||||
#define RSA_KEY_SLOT_SHIFT 24
|
||||
#define RSA_KEY_SLOT(x) ((x) << RSA_KEY_SLOT_SHIFT)
|
||||
#define SE_RSA_CONFIG 0x400
|
||||
|
||||
#define RSA_KEY_PKT_WORD_ADDR_SHIFT 0
|
||||
#define RSA_KEY_PKT_WORD_ADDR(x) ((x) << RSA_KEY_PKT_WORD_ADDR_SHIFT)
|
||||
|
||||
#define RSA_KEY_WORD_ADDR_SHIFT 0
|
||||
#define RSA_KEY_WORD_ADDR(x) ((x) << RSA_KEY_WORD_ADDR_SHIFT)
|
||||
|
||||
#define SE_RSA_KEYTABLE_PKT_SHIFT 0
|
||||
#define SE_RSA_KEYTABLE_PKT(x) ((x) << SE_RSA_KEYTABLE_PKT_SHIFT)
|
||||
|
||||
#endif /* _CRYPTO_TEGRA_SE_H */
|
||||
#endif
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2018-2019 CTCaer
|
||||
* Copyright (c) 2018-2021 CTCaer
|
||||
* Copyright (c) 2018 balika011
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
@@ -62,7 +62,7 @@ static int _tsec_dma_pa_to_internal_100(int not_imem, int i_offset, int pa_offse
|
||||
return _tsec_dma_wait_idle();
|
||||
}
|
||||
|
||||
int tsec_query(u8 *tsec_keys, u8 kb, tsec_ctxt_t *tsec_ctxt)
|
||||
int tsec_query(void *tsec_keys, u8 kb, tsec_ctxt_t *tsec_ctxt)
|
||||
{
|
||||
int res = 0;
|
||||
u8 *fwbuf = NULL;
|
||||
@@ -190,7 +190,7 @@ int tsec_query(u8 *tsec_keys, u8 kb, tsec_ctxt_t *tsec_ctxt)
|
||||
if (kb == KB_TSEC_FW_EMU_COMPAT)
|
||||
{
|
||||
u32 start = get_tmr_us();
|
||||
u32 k = se[SE_KEYTABLE_DATA0_REG_OFFSET / 4];
|
||||
u32 k = se[SE_CRYPTO_KEYTABLE_DATA_REG / 4];
|
||||
u32 key[16] = {0};
|
||||
u32 kidx = 0;
|
||||
|
||||
@@ -198,9 +198,9 @@ int tsec_query(u8 *tsec_keys, u8 kb, tsec_ctxt_t *tsec_ctxt)
|
||||
{
|
||||
smmu_flush_all();
|
||||
|
||||
if (k != se[SE_KEYTABLE_DATA0_REG_OFFSET / 4])
|
||||
if (k != se[SE_CRYPTO_KEYTABLE_DATA_REG / 4])
|
||||
{
|
||||
k = se[SE_KEYTABLE_DATA0_REG_OFFSET / 4];
|
||||
k = se[SE_CRYPTO_KEYTABLE_DATA_REG / 4];
|
||||
key[kidx++] = k;
|
||||
}
|
||||
|
||||
@@ -269,7 +269,7 @@ int tsec_query(u8 *tsec_keys, u8 kb, tsec_ctxt_t *tsec_ctxt)
|
||||
SOR1(SOR_NV_PDISP_SOR_TMDS_HDCP_CN_MSB) = 0;
|
||||
SOR1(SOR_NV_PDISP_SOR_TMDS_HDCP_CN_LSB) = 0;
|
||||
|
||||
memcpy(tsec_keys, &buf, 0x10);
|
||||
memcpy(tsec_keys, &buf, SE_KEY_128_SIZE);
|
||||
}
|
||||
|
||||
out_free:;
|
||||
|
||||
@@ -29,6 +29,6 @@ typedef struct _tsec_ctxt_t
|
||||
u32 secmon_base;
|
||||
} tsec_ctxt_t;
|
||||
|
||||
int tsec_query(u8 *tsec_keys, u8 kb, tsec_ctxt_t *tsec_ctxt);
|
||||
int tsec_query(void *tsec_keys, u8 kb, tsec_ctxt_t *tsec_ctxt);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2018-2020 CTCaer
|
||||
* Copyright (c) 2018-2021 CTCaer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
@@ -264,7 +264,7 @@ static void _config_se_brom()
|
||||
FUSE(FUSE_PRIVATE_KEY3)
|
||||
};
|
||||
// Set SBK to slot 14.
|
||||
se_aes_key_set(14, sbk, 0x10);
|
||||
se_aes_key_set(14, sbk, SE_KEY_128_SIZE);
|
||||
|
||||
// Lock SBK from being read.
|
||||
se_key_acc_ctrl(14, SE_KEY_TBL_DIS_KEYREAD_FLAG);
|
||||
@@ -276,7 +276,7 @@ static void _config_se_brom()
|
||||
// This memset needs to happen here, else TZRAM will behave weirdly later on.
|
||||
memset((void *)TZRAM_BASE, 0, 0x10000);
|
||||
PMC(APBDEV_PMC_CRYPTO_OP) = PMC_CRYPTO_OP_SE_ENABLE;
|
||||
SE(SE_INT_STATUS_REG_OFFSET) = 0x1F;
|
||||
SE(SE_INT_STATUS_REG) = 0x1F; // Clear all SE interrupts.
|
||||
|
||||
// Clear the boot reason to avoid problems later
|
||||
PMC(APBDEV_PMC_SCRATCH200) = 0x0;
|
||||
|
||||
@@ -84,6 +84,11 @@
|
||||
#define MMC_APP_CMD 55 /* ac [31:16] RCA R1 */
|
||||
#define MMC_GEN_CMD 56 /* adtc [0] RD/WR R1 */
|
||||
|
||||
#define MMC_VENDOR_60_CMD 60 /* Vendor Defined */
|
||||
#define MMC_VENDOR_61_CMD 61 /* Vendor Defined */
|
||||
#define MMC_VENDOR_62_CMD 62 /* Vendor Defined */
|
||||
#define MMC_VENDOR_63_CMD 63 /* Vendor Defined */
|
||||
|
||||
/* class 11 */
|
||||
#define MMC_QUE_TASK_PARAMS 44 /* ac [20:16] task id R1 */
|
||||
#define MMC_QUE_TASK_ADDR 45 /* ac [31:0] data addr R1 */
|
||||
@@ -182,7 +187,10 @@ c : clear by read
|
||||
/*
|
||||
* OCR bits are mostly in host.h
|
||||
*/
|
||||
#define MMC_CARD_BUSY 0x80000000 /* Card Power up status bit */
|
||||
#define MMC_CARD_VDD_18 (1 << 7) /* Card VDD voltage 1.8 */
|
||||
#define MMC_CARD_VDD_27_34 (0x7F << 15) /* Card VDD voltage 2.7 ~ 3.4 */
|
||||
#define MMC_CARD_CCS (1 << 30) /* Card Capacity status bit */
|
||||
#define MMC_CARD_BUSY (1 << 31) /* Card Power up status bit */
|
||||
|
||||
/*
|
||||
* Card Command Classes (CCC)
|
||||
@@ -244,6 +252,7 @@ c : clear by read
|
||||
#define EXT_CSD_GP_SIZE_MULT 143 /* R/W */
|
||||
#define EXT_CSD_PARTITION_SETTING_COMPLETED 155 /* R/W */
|
||||
#define EXT_CSD_PARTITION_ATTRIBUTE 156 /* R/W */
|
||||
#define EXT_CSD_MAX_ENH_SIZE_MULT 157 /* RO, 3 bytes */
|
||||
#define EXT_CSD_PARTITION_SUPPORT 160 /* RO */
|
||||
#define EXT_CSD_HPI_MGMT 161 /* R/W */
|
||||
#define EXT_CSD_RST_N_FUNCTION 162 /* R/W */
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2018-2019 CTCaer
|
||||
* Copyright (c) 2018-2021 CTCaer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
@@ -45,12 +45,14 @@ extern FATFS sd_fs;
|
||||
void sd_error_count_increment(u8 type);
|
||||
u16 *sd_get_error_count();
|
||||
bool sd_get_card_removed();
|
||||
bool sd_get_card_initialized();
|
||||
u32 sd_get_mode();
|
||||
int sd_init_retry(bool power_cycle);
|
||||
bool sd_initialize(bool power_cycle);
|
||||
bool sd_mount();
|
||||
void sd_unmount();
|
||||
void sd_end();
|
||||
bool sd_is_gpt();
|
||||
void *sd_file_read(const char *path, u32 *fsize);
|
||||
int sd_save_to_file(void *buf, u32 size, const char *filename);
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Ramdisk driver for Tegra X1
|
||||
*
|
||||
* Copyright (c) 2019 CTCaer
|
||||
* Copyright (c) 2019-2021 CTCaer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
@@ -19,23 +19,40 @@
|
||||
#include <string.h>
|
||||
|
||||
#include "ramdisk.h"
|
||||
#include <libs/fatfs/diskio.h>
|
||||
#include <mem/heap.h>
|
||||
#include <utils/types.h>
|
||||
|
||||
#include <memory_map.h>
|
||||
|
||||
int ram_disk_init(FATFS *ram_fs)
|
||||
static u32 disk_size = 0;
|
||||
|
||||
int ram_disk_init(FATFS *ram_fs, u32 ramdisk_size)
|
||||
{
|
||||
int res;
|
||||
u8 *buf = malloc(0x400000);
|
||||
int res = 0;
|
||||
disk_size = ramdisk_size;
|
||||
|
||||
f_mount(NULL, "ram:", 1); // Unmount ramdisk.
|
||||
// If ramdisk is not raw, format it.
|
||||
if (ram_fs)
|
||||
{
|
||||
u8 *buf = malloc(0x400000);
|
||||
|
||||
res = f_mkfs("ram:", FM_EXFAT, RAMDISK_CLUSTER_SZ, buf, 0x400000); // Format as exFAT w/ 32KB cluster.
|
||||
if (!res)
|
||||
res = f_mount(ram_fs, "ram:", 1); // Mount ramdisk.
|
||||
// Set ramdisk size.
|
||||
ramdisk_size >>= 9;
|
||||
disk_set_info(DRIVE_RAM, SET_SECTOR_COUNT, &ramdisk_size);
|
||||
|
||||
free(buf);
|
||||
// Unmount ramdisk.
|
||||
f_mount(NULL, "ram:", 1);
|
||||
|
||||
// Format as exFAT w/ 32KB cluster with no MBR.
|
||||
res = f_mkfs("ram:", FM_EXFAT | FM_SFD, RAMDISK_CLUSTER_SZ, buf, 0x400000);
|
||||
|
||||
// Mount ramdisk.
|
||||
if (!res)
|
||||
res = f_mount(ram_fs, "ram:", 1);
|
||||
|
||||
free(buf);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
@@ -45,7 +62,7 @@ int ram_disk_read(u32 sector, u32 sector_count, void *buf)
|
||||
u32 sector_off = RAM_DISK_ADDR + (sector << 9);
|
||||
u32 bytes_count = sector_count << 9;
|
||||
|
||||
if ((sector_off - RAM_DISK_ADDR) > RAM_DISK_SZ)
|
||||
if ((sector_off - RAM_DISK_ADDR) > disk_size)
|
||||
return 1;
|
||||
|
||||
memcpy(buf, (void *)sector_off, bytes_count);
|
||||
@@ -58,7 +75,7 @@ int ram_disk_write(u32 sector, u32 sector_count, const void *buf)
|
||||
u32 sector_off = RAM_DISK_ADDR + (sector << 9);
|
||||
u32 bytes_count = sector_count << 9;
|
||||
|
||||
if ((sector_off - RAM_DISK_ADDR) > RAM_DISK_SZ)
|
||||
if ((sector_off - RAM_DISK_ADDR) > disk_size)
|
||||
return 1;
|
||||
|
||||
memcpy((void *)sector_off, buf, bytes_count);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Ramdisk driver for Tegra X1
|
||||
*
|
||||
* Copyright (c) 2019 CTCaer
|
||||
* Copyright (c) 2019-2021 CTCaer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
@@ -23,7 +23,7 @@
|
||||
|
||||
#define RAMDISK_CLUSTER_SZ 32768
|
||||
|
||||
int ram_disk_init(FATFS *ram_fs);
|
||||
int ram_disk_init(FATFS *ram_fs, u32 ramdisk_size);
|
||||
int ram_disk_read(u32 sector, u32 sector_count, void *buf);
|
||||
int ram_disk_write(u32 sector, u32 sector_count, const void *buf);
|
||||
|
||||
|
||||
121
bdk/storage/sd.h
121
bdk/storage/sd.h
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2005-2007 Pierre Ossman, All Rights Reserved.
|
||||
* Copyright (c) 2018 CTCaer
|
||||
* Copyright (c) 2018-2021 CTCaer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -14,60 +14,79 @@
|
||||
/* SD commands type argument response */
|
||||
/* class 0 */
|
||||
/* This is basically the same command as for MMC with some quirks. */
|
||||
#define SD_SEND_RELATIVE_ADDR 3 /* bcr R6 */
|
||||
#define SD_SEND_IF_COND 8 /* bcr [11:0] See below R7 */
|
||||
#define SD_SWITCH_VOLTAGE 11 /* ac R1 */
|
||||
|
||||
#define SD_SEND_RELATIVE_ADDR 3 /* bcr R6 */
|
||||
#define SD_SEND_IF_COND 8 /* bcr [11:0] See below R7 */
|
||||
#define SD_SWITCH_VOLTAGE 11 /* ac R1 */
|
||||
/* class 10 */
|
||||
#define SD_SWITCH 6 /* adtc [31:0] See below R1 */
|
||||
|
||||
#define SD_SWITCH 6 /* adtc [31:0] See below R1 */
|
||||
/* class 5 */
|
||||
#define SD_ERASE_WR_BLK_START 32 /* ac [31:0] data addr R1 */
|
||||
#define SD_ERASE_WR_BLK_END 33 /* ac [31:0] data addr R1 */
|
||||
#define SD_ERASE_WR_BLK_START 32 /* ac [31:0] data addr R1 */
|
||||
#define SD_ERASE_WR_BLK_END 33 /* ac [31:0] data addr R1 */
|
||||
|
||||
/* Application commands */
|
||||
#define SD_APP_SET_BUS_WIDTH 6 /* ac [1:0] bus width R1 */
|
||||
#define SD_APP_SD_STATUS 13 /* adtc R1 */
|
||||
#define SD_APP_SEND_NUM_WR_BLKS 22 /* adtc R1 */
|
||||
#define SD_APP_OP_COND 41 /* bcr [31:0] OCR R3 */
|
||||
#define SD_APP_SET_CLR_CARD_DETECT 42
|
||||
#define SD_APP_SEND_SCR 51 /* adtc R1 */
|
||||
#define SD_APP_SET_BUS_WIDTH 6 /* ac [1:0] bus width R1 */
|
||||
#define SD_APP_SD_STATUS 13 /* adtc R1 */
|
||||
#define SD_APP_SEND_NUM_WR_BLKS 22 /* adtc R1 */
|
||||
#define SD_APP_OP_COND 41 /* bcr [31:0] OCR R3 */
|
||||
#define SD_APP_SET_CLR_CARD_DETECT 42 /* adtc R1 */
|
||||
#define SD_APP_SEND_SCR 51 /* adtc R1 */
|
||||
|
||||
/* Application secure commands */
|
||||
#define SD_APP_SECURE_READ_MULTI_BLOCK 18 /* adtc R1 */
|
||||
#define SD_APP_SECURE_WRITE_MULTI_BLOCK 25 /* adtc R1 */
|
||||
#define SD_APP_SECURE_WRITE_MKB 26 /* adtc R1 */
|
||||
#define SD_APP_SECURE_ERASE 38 /* adtc R1b */
|
||||
#define SD_APP_GET_MKB 43 /* adtc [31:0] See below R1 */
|
||||
#define SD_APP_GET_MID 44 /* adtc R1 */
|
||||
#define SD_APP_SET_CER_RN1 45 /* adtc R1 */
|
||||
#define SD_APP_GET_CER_RN2 46 /* adtc R1 */
|
||||
#define SD_APP_SET_CER_RES2 47 /* adtc R1 */
|
||||
#define SD_APP_GET_CER_RES1 48 /* adtc R1 */
|
||||
#define SD_APP_CHANGE_SECURE_AREA 49 /* adtc R1b */
|
||||
|
||||
/* OCR bit definitions */
|
||||
#define SD_OCR_CCS (1 << 30) /* Card Capacity Status */
|
||||
#define SD_OCR_XPC (1 << 28) /* SDXC power control */
|
||||
#define SD_OCR_S18R (1 << 24) /* 1.8V switching request */
|
||||
#define SD_ROCR_S18A SD_OCR_S18R /* 1.8V switching accepted by card */
|
||||
#define SD_OCR_VDD_18 (1 << 7) /* VDD voltage 1.8 */
|
||||
#define SD_VHD_27_36 (1 << 8) /* VDD voltage 2.7 ~ 3.6 */
|
||||
#define SD_OCR_VDD_27_34 (0x7F << 15) /* VDD voltage 2.7 ~ 3.4 */
|
||||
#define SD_OCR_VDD_32_33 (1 << 20) /* VDD voltage 3.2 ~ 3.3 */
|
||||
#define SD_OCR_VDD_18 (1 << 7) /* VDD voltage 1.8 */
|
||||
|
||||
#define SD_VHD_27_36 (1 << 8) /* VDD voltage 2.7 ~ 3.6 */
|
||||
#define SD_OCR_S18R (1 << 24) /* 1.8V switching request */
|
||||
#define SD_ROCR_S18A SD_OCR_S18R /* 1.8V switching accepted by card */
|
||||
#define SD_OCR_XPC (1 << 28) /* SDXC power control */
|
||||
#define SD_OCR_CCS (1 << 30) /* Card Capacity Status */
|
||||
#define SD_OCR_BUSY (1 << 31) /* Card Power up Status */
|
||||
|
||||
/*
|
||||
* SD_SWITCH argument format:
|
||||
*
|
||||
* [31] Check (0) or switch (1)
|
||||
* [30:24] Reserved (0)
|
||||
* [23:20] Function group 6
|
||||
* [19:16] Function group 5
|
||||
* [15:12] Function group 4
|
||||
* [11:8] Function group 3
|
||||
* [7:4] Function group 2
|
||||
* [3:0] Function group 1
|
||||
*/
|
||||
* SD_SWITCH argument format:
|
||||
*
|
||||
* [31] Check (0) or switch (1)
|
||||
* [30:24] Reserved (0)
|
||||
* [23:20] Function group 6
|
||||
* [19:16] Function group 5
|
||||
* [15:12] Function group 4
|
||||
* [11:8] Function group 3
|
||||
* [7:4] Function group 2
|
||||
* [3:0] Function group 1
|
||||
*/
|
||||
|
||||
/*
|
||||
* SD_SEND_IF_COND argument format:
|
||||
*
|
||||
* [31:12] Reserved (0)
|
||||
* [11:8] Host Voltage Supply Flags
|
||||
* [7:0] Check Pattern (0xAA)
|
||||
*/
|
||||
* SD_SEND_IF_COND argument format:
|
||||
*
|
||||
* [31:12] Reserved (0)
|
||||
* [11:8] Host Voltage Supply Flags
|
||||
* [7:0] Check Pattern (0xAA)
|
||||
*/
|
||||
|
||||
/*
|
||||
* SCR field definitions
|
||||
*/
|
||||
* SD_APP_GET_MKB argument format:
|
||||
*
|
||||
* [31:24] Number of blocks to read (512 block size)
|
||||
* [23:16] MKB ID
|
||||
* [15:0] Block offset
|
||||
*/
|
||||
|
||||
/*
|
||||
* SCR field definitions
|
||||
*/
|
||||
#define SCR_SPEC_VER_0 0 /* Implements system specification 1.0 - 1.01 */
|
||||
#define SCR_SPEC_VER_1 1 /* Implements system specification 1.10 */
|
||||
#define SCR_SPEC_VER_2 2 /* Implements system specification 2.00-3.0X */
|
||||
@@ -75,14 +94,14 @@
|
||||
#define SD_SCR_BUS_WIDTH_4 (1<<2)
|
||||
|
||||
/*
|
||||
* SD bus widths
|
||||
*/
|
||||
* SD bus widths
|
||||
*/
|
||||
#define SD_BUS_WIDTH_1 0
|
||||
#define SD_BUS_WIDTH_4 2
|
||||
|
||||
/*
|
||||
* SD bus speeds
|
||||
*/
|
||||
* SD bus speeds
|
||||
*/
|
||||
#define UHS_SDR12_BUS_SPEED 0
|
||||
#define HIGH_SPEED_BUS_SPEED 1
|
||||
#define UHS_SDR25_BUS_SPEED 1
|
||||
@@ -112,19 +131,19 @@
|
||||
#define SD_MAX_CURRENT_800 (1 << SD_SET_CURRENT_LIMIT_800)
|
||||
|
||||
/*
|
||||
* SD_SWITCH mode
|
||||
*/
|
||||
* SD_SWITCH mode
|
||||
*/
|
||||
#define SD_SWITCH_CHECK 0
|
||||
#define SD_SWITCH_SET 1
|
||||
|
||||
/*
|
||||
* SD_SWITCH function groups
|
||||
*/
|
||||
* SD_SWITCH function groups
|
||||
*/
|
||||
#define SD_SWITCH_GRP_ACCESS 0
|
||||
|
||||
/*
|
||||
* SD_SWITCH access modes
|
||||
*/
|
||||
* SD_SWITCH access modes
|
||||
*/
|
||||
#define SD_SWITCH_ACCESS_DEF 0
|
||||
#define SD_SWITCH_ACCESS_HS 1
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2018-2020 CTCaer
|
||||
* Copyright (c) 2018-2021 CTCaer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
@@ -42,8 +42,8 @@ static inline u32 unstuff_bits(u32 *resp, u32 start, u32 size)
|
||||
}
|
||||
|
||||
/*
|
||||
* Common functions for SD and MMC.
|
||||
*/
|
||||
* Common functions for SD and MMC.
|
||||
*/
|
||||
|
||||
static int _sdmmc_storage_check_card_status(u32 res)
|
||||
{
|
||||
@@ -88,20 +88,20 @@ static int _sdmmc_storage_execute_cmd_type1(sdmmc_storage_t *storage, u32 cmd, u
|
||||
|
||||
static int _sdmmc_storage_go_idle_state(sdmmc_storage_t *storage)
|
||||
{
|
||||
sdmmc_cmd_t cmd;
|
||||
sdmmc_init_cmd(&cmd, MMC_GO_IDLE_STATE, 0, SDMMC_RSP_TYPE_0, 0);
|
||||
sdmmc_cmd_t cmdbuf;
|
||||
sdmmc_init_cmd(&cmdbuf, MMC_GO_IDLE_STATE, 0, SDMMC_RSP_TYPE_0, 0);
|
||||
|
||||
return sdmmc_execute_cmd(storage->sdmmc, &cmd, NULL, NULL);
|
||||
return sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, NULL, NULL);
|
||||
}
|
||||
|
||||
static int _sdmmc_storage_get_cid(sdmmc_storage_t *storage, void *buf)
|
||||
static int _sdmmc_storage_get_cid(sdmmc_storage_t *storage)
|
||||
{
|
||||
sdmmc_cmd_t cmd;
|
||||
sdmmc_init_cmd(&cmd, MMC_ALL_SEND_CID, 0, SDMMC_RSP_TYPE_2, 0);
|
||||
if (!sdmmc_execute_cmd(storage->sdmmc, &cmd, NULL, NULL))
|
||||
sdmmc_cmd_t cmdbuf;
|
||||
sdmmc_init_cmd(&cmdbuf, MMC_ALL_SEND_CID, 0, SDMMC_RSP_TYPE_2, 0);
|
||||
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, NULL, NULL))
|
||||
return 0;
|
||||
|
||||
sdmmc_get_rsp(storage->sdmmc, buf, 16, SDMMC_RSP_TYPE_2);
|
||||
sdmmc_get_rsp(storage->sdmmc, (u32 *)storage->raw_cid, 16, SDMMC_RSP_TYPE_2);
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -111,14 +111,14 @@ static int _sdmmc_storage_select_card(sdmmc_storage_t *storage)
|
||||
return _sdmmc_storage_execute_cmd_type1(storage, MMC_SELECT_CARD, storage->rca << 16, 1, R1_SKIP_STATE_CHECK);
|
||||
}
|
||||
|
||||
static int _sdmmc_storage_get_csd(sdmmc_storage_t *storage, void *buf)
|
||||
static int _sdmmc_storage_get_csd(sdmmc_storage_t *storage)
|
||||
{
|
||||
sdmmc_cmd_t cmdbuf;
|
||||
sdmmc_init_cmd(&cmdbuf, MMC_SEND_CSD, storage->rca << 16, SDMMC_RSP_TYPE_2, 0);
|
||||
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, NULL, NULL))
|
||||
return 0;
|
||||
|
||||
sdmmc_get_rsp(storage->sdmmc, buf, 16, SDMMC_RSP_TYPE_2);
|
||||
sdmmc_get_rsp(storage->sdmmc, (u32 *)storage->raw_csd, 16, SDMMC_RSP_TYPE_2);
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -145,6 +145,10 @@ static int _sdmmc_storage_readwrite_ex(sdmmc_storage_t *storage, u32 *blkcnt_out
|
||||
sdmmc_cmd_t cmdbuf;
|
||||
sdmmc_req_t reqbuf;
|
||||
|
||||
// If SDSC convert block address to byte address.
|
||||
if (!storage->has_sector_access)
|
||||
sector <<= 9;
|
||||
|
||||
sdmmc_init_cmd(&cmdbuf, is_write ? MMC_WRITE_MULTIPLE_BLOCK : MMC_READ_MULTIPLE_BLOCK, sector, SDMMC_RSP_TYPE_1, 0);
|
||||
|
||||
reqbuf.buf = buf;
|
||||
@@ -152,7 +156,7 @@ static int _sdmmc_storage_readwrite_ex(sdmmc_storage_t *storage, u32 *blkcnt_out
|
||||
reqbuf.blksize = 512;
|
||||
reqbuf.is_write = is_write;
|
||||
reqbuf.is_multi_block = 1;
|
||||
reqbuf.is_auto_cmd12 = 1;
|
||||
reqbuf.is_auto_stop_trn = 1;
|
||||
|
||||
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, &reqbuf, blkcnt_out))
|
||||
{
|
||||
@@ -288,25 +292,25 @@ int sdmmc_storage_write(sdmmc_storage_t *storage, u32 sector, u32 num_sectors, v
|
||||
|
||||
static int _mmc_storage_get_op_cond_inner(sdmmc_storage_t *storage, u32 *pout, u32 power)
|
||||
{
|
||||
sdmmc_cmd_t cmd;
|
||||
sdmmc_cmd_t cmdbuf;
|
||||
|
||||
u32 arg = 0;
|
||||
switch (power)
|
||||
{
|
||||
case SDMMC_POWER_1_8:
|
||||
arg = SD_OCR_CCS | SD_OCR_VDD_18;
|
||||
arg = MMC_CARD_CCS | MMC_CARD_VDD_18;
|
||||
break;
|
||||
|
||||
case SDMMC_POWER_3_3:
|
||||
arg = SD_OCR_CCS | SD_OCR_VDD_27_34;
|
||||
arg = MMC_CARD_CCS | MMC_CARD_VDD_27_34;
|
||||
break;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
sdmmc_init_cmd(&cmd, MMC_SEND_OP_COND, arg, SDMMC_RSP_TYPE_3, 0);
|
||||
if (!sdmmc_execute_cmd(storage->sdmmc, &cmd, NULL, NULL))
|
||||
sdmmc_init_cmd(&cmdbuf, MMC_SEND_OP_COND, arg, SDMMC_RSP_TYPE_3, 0);
|
||||
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, NULL, NULL))
|
||||
return 0;
|
||||
|
||||
return sdmmc_get_rsp(storage->sdmmc, pout, 4, SDMMC_RSP_TYPE_3);
|
||||
@@ -316,15 +320,17 @@ static int _mmc_storage_get_op_cond(sdmmc_storage_t *storage, u32 power)
|
||||
{
|
||||
u32 timeout = get_tmr_ms() + 1500;
|
||||
|
||||
while (1)
|
||||
while (true)
|
||||
{
|
||||
u32 cond = 0;
|
||||
if (!_mmc_storage_get_op_cond_inner(storage, &cond, power))
|
||||
break;
|
||||
|
||||
// Check if power up is done.
|
||||
if (cond & MMC_CARD_BUSY)
|
||||
{
|
||||
if (cond & SD_OCR_CCS)
|
||||
// Check if card is high capacity.
|
||||
if (cond & MMC_CARD_CCS)
|
||||
storage->has_sector_access = 1;
|
||||
|
||||
return 1;
|
||||
@@ -362,7 +368,6 @@ static void _mmc_storage_parse_cid(sdmmc_storage_t *storage)
|
||||
case 3: /* MMC v3.1 - v3.3 */
|
||||
case 4: /* MMC v4 */
|
||||
storage->cid.manfid = unstuff_bits(raw_cid, 120, 8);
|
||||
storage->cid.card_bga = unstuff_bits(raw_cid, 112, 2);
|
||||
storage->cid.oemid = unstuff_bits(raw_cid, 104, 8);
|
||||
storage->cid.prv = unstuff_bits(raw_cid, 48, 8);
|
||||
storage->cid.serial = unstuff_bits(raw_cid, 16, 32);
|
||||
@@ -390,13 +395,14 @@ static void _mmc_storage_parse_cid(sdmmc_storage_t *storage)
|
||||
|
||||
static void _mmc_storage_parse_csd(sdmmc_storage_t *storage)
|
||||
{
|
||||
u32 *raw_csd = (u32 *)&(storage->raw_csd);
|
||||
u32 *raw_csd = (u32 *)storage->raw_csd;
|
||||
|
||||
storage->csd.mmca_vsn = unstuff_bits(raw_csd, 122, 4);
|
||||
storage->csd.structure = unstuff_bits(raw_csd, 126, 2);
|
||||
storage->csd.cmdclass = unstuff_bits(raw_csd, 84, 12);
|
||||
storage->csd.read_blkbits = unstuff_bits(raw_csd, 80, 4);
|
||||
storage->csd.capacity = (1 + unstuff_bits(raw_csd, 62, 12)) << (unstuff_bits(raw_csd, 47, 3) + 2);
|
||||
storage->sec_cnt = storage->csd.capacity;
|
||||
}
|
||||
|
||||
static void _mmc_storage_parse_ext_csd(sdmmc_storage_t *storage, u8 *buf)
|
||||
@@ -407,16 +413,26 @@ static void _mmc_storage_parse_ext_csd(sdmmc_storage_t *storage, u8 *buf)
|
||||
storage->ext_csd.dev_version = *(u16 *)&buf[EXT_CSD_DEVICE_VERSION];
|
||||
storage->ext_csd.boot_mult = buf[EXT_CSD_BOOT_MULT];
|
||||
storage->ext_csd.rpmb_mult = buf[EXT_CSD_RPMB_MULT];
|
||||
storage->ext_csd.sectors = *(u32 *)&buf[EXT_CSD_SEC_CNT];
|
||||
storage->ext_csd.bkops = buf[EXT_CSD_BKOPS_SUPPORT];
|
||||
storage->ext_csd.bkops_en = buf[EXT_CSD_BKOPS_EN];
|
||||
storage->ext_csd.bkops_status = buf[EXT_CSD_BKOPS_STATUS];
|
||||
//storage->ext_csd.bkops = buf[EXT_CSD_BKOPS_SUPPORT];
|
||||
//storage->ext_csd.bkops_en = buf[EXT_CSD_BKOPS_EN];
|
||||
//storage->ext_csd.bkops_status = buf[EXT_CSD_BKOPS_STATUS];
|
||||
|
||||
storage->ext_csd.pre_eol_info = buf[EXT_CSD_PRE_EOL_INFO];
|
||||
storage->ext_csd.dev_life_est_a = buf[EXT_CSD_DEVICE_LIFE_TIME_EST_TYP_A];
|
||||
storage->ext_csd.dev_life_est_b = buf[EXT_CSD_DEVICE_LIFE_TIME_EST_TYP_B];
|
||||
|
||||
storage->sec_cnt = *(u32 *)&buf[EXT_CSD_SEC_CNT];
|
||||
storage->ext_csd.cache_size =
|
||||
buf[EXT_CSD_CACHE_SIZE] |
|
||||
(buf[EXT_CSD_CACHE_SIZE + 1] << 8) |
|
||||
(buf[EXT_CSD_CACHE_SIZE + 2] << 16) |
|
||||
(buf[EXT_CSD_CACHE_SIZE + 3] << 24);
|
||||
storage->ext_csd.max_enh_mult =
|
||||
(buf[EXT_CSD_MAX_ENH_SIZE_MULT] |
|
||||
(buf[EXT_CSD_MAX_ENH_SIZE_MULT + 1] << 8) |
|
||||
(buf[EXT_CSD_MAX_ENH_SIZE_MULT + 2] << 16)) *
|
||||
buf[EXT_CSD_HC_WP_GRP_SIZE] * buf[EXT_CSD_HC_ERASE_GRP_SIZE];
|
||||
|
||||
storage->sec_cnt = *(u32 *)&buf[EXT_CSD_SEC_CNT];
|
||||
}
|
||||
|
||||
static int _mmc_storage_get_ext_csd(sdmmc_storage_t *storage, void *buf)
|
||||
@@ -430,7 +446,7 @@ static int _mmc_storage_get_ext_csd(sdmmc_storage_t *storage, void *buf)
|
||||
reqbuf.num_sectors = 1;
|
||||
reqbuf.is_write = 0;
|
||||
reqbuf.is_multi_block = 0;
|
||||
reqbuf.is_auto_cmd12 = 0;
|
||||
reqbuf.is_auto_stop_trn = 0;
|
||||
|
||||
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, &reqbuf, NULL))
|
||||
return 0;
|
||||
@@ -559,19 +575,21 @@ out:
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
static int _mmc_storage_enable_bkops(sdmmc_storage_t *storage)
|
||||
{
|
||||
if (!_mmc_storage_switch(storage, SDMMC_SWITCH(MMC_SWITCH_MODE_SET_BITS, EXT_CSD_BKOPS_EN, EXT_CSD_BKOPS_LEVEL_2)))
|
||||
if (!_mmc_storage_switch(storage, SDMMC_SWITCH(MMC_SWITCH_MODE_SET_BITS, EXT_CSD_BKOPS_EN, EXT_CSD_AUTO_BKOPS_MASK)))
|
||||
return 0;
|
||||
|
||||
return _sdmmc_storage_check_status(storage);
|
||||
}
|
||||
*/
|
||||
|
||||
int sdmmc_storage_init_mmc(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 bus_width, u32 type)
|
||||
{
|
||||
memset(storage, 0, sizeof(sdmmc_storage_t));
|
||||
storage->sdmmc = sdmmc;
|
||||
storage->rca = 2; //TODO: this could be a config item.
|
||||
storage->rca = 2; // Set default device address. This could be a config item.
|
||||
|
||||
if (!sdmmc_init(sdmmc, SDMMC_4, SDMMC_POWER_1_8, SDMMC_BUS_WIDTH_1, SDHCI_TIMING_MMC_ID, SDMMC_POWER_SAVE_DISABLE))
|
||||
return 0;
|
||||
@@ -587,7 +605,7 @@ DPRINTF("[MMC] went to idle state\n");
|
||||
return 0;
|
||||
DPRINTF("[MMC] got op cond\n");
|
||||
|
||||
if (!_sdmmc_storage_get_cid(storage, storage->raw_cid))
|
||||
if (!_sdmmc_storage_get_cid(storage))
|
||||
return 0;
|
||||
DPRINTF("[MMC] got cid\n");
|
||||
|
||||
@@ -595,7 +613,7 @@ DPRINTF("[MMC] got cid\n");
|
||||
return 0;
|
||||
DPRINTF("[MMC] set relative addr\n");
|
||||
|
||||
if (!_sdmmc_storage_get_csd(storage, storage->raw_csd))
|
||||
if (!_sdmmc_storage_get_csd(storage))
|
||||
return 0;
|
||||
DPRINTF("[MMC] got csd\n");
|
||||
_mmc_storage_parse_csd(storage);
|
||||
@@ -612,13 +630,9 @@ DPRINTF("[MMC] card selected\n");
|
||||
return 0;
|
||||
DPRINTF("[MMC] set blocklen to 512\n");
|
||||
|
||||
u32 *csd = (u32 *)storage->raw_csd;
|
||||
//Check system specification version, only version 4.0 and later support below features.
|
||||
if (unstuff_bits(csd, 122, 4) < CSD_SPEC_VER_4)
|
||||
{
|
||||
storage->sec_cnt = (1 + unstuff_bits(csd, 62, 12)) << (unstuff_bits(csd, 47, 3) + 2);
|
||||
// Check system specification version, only version 4.0 and later support below features.
|
||||
if (storage->csd.mmca_vsn < CSD_SPEC_VER_4)
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!_mmc_storage_switch_buswidth(storage, bus_width))
|
||||
return 0;
|
||||
@@ -628,21 +642,20 @@ DPRINTF("[MMC] switched buswidth\n");
|
||||
return 0;
|
||||
DPRINTF("[MMC] got ext_csd\n");
|
||||
|
||||
_mmc_storage_parse_cid(storage); //This needs to be after csd and ext_csd
|
||||
_mmc_storage_parse_cid(storage); // This needs to be after csd and ext_csd.
|
||||
//gfx_hexdump(0, ext_csd, 512);
|
||||
|
||||
/* When auto BKOPS is enabled the mmc device should be powered all the time until we disable this and check status.
|
||||
Disable it for now until BKOPS disable added to power down sequence at sdmmc_storage_end().
|
||||
Additionally this works only when we put the device in idle mode which we don't after enabling it. */
|
||||
if (0 && storage->ext_csd.bkops & 0x1 && !(storage->ext_csd.bkops_en & EXT_CSD_BKOPS_LEVEL_2))
|
||||
/*
|
||||
if (storage->ext_csd.bkops & 0x1 && !(storage->ext_csd.bkops_en & EXT_CSD_AUTO_BKOPS_MASK))
|
||||
{
|
||||
_mmc_storage_enable_bkops(storage);
|
||||
DPRINTF("[MMC] BKOPS enabled\n");
|
||||
}
|
||||
*/
|
||||
|
||||
if (!_mmc_storage_enable_highspeed(storage, storage->ext_csd.card_type, type))
|
||||
return 0;
|
||||
DPRINTF("[MMC] succesfully switched to HS mode\n");
|
||||
DPRINTF("[MMC] successfully switched to HS mode\n");
|
||||
|
||||
sdmmc_card_clock_powersave(storage->sdmmc, SDMMC_POWER_SAVE_ENABLE);
|
||||
|
||||
@@ -665,16 +678,16 @@ int sdmmc_storage_set_mmc_partition(sdmmc_storage_t *storage, u32 partition)
|
||||
}
|
||||
|
||||
/*
|
||||
* SD specific functions.
|
||||
*/
|
||||
* SD specific functions.
|
||||
*/
|
||||
|
||||
static int _sd_storage_execute_app_cmd(sdmmc_storage_t *storage, u32 expected_state, u32 mask, sdmmc_cmd_t *cmd, sdmmc_req_t *req, u32 *blkcnt_out)
|
||||
static int _sd_storage_execute_app_cmd(sdmmc_storage_t *storage, u32 expected_state, u32 mask, sdmmc_cmd_t *cmdbuf, sdmmc_req_t *req, u32 *blkcnt_out)
|
||||
{
|
||||
u32 tmp;
|
||||
if (!_sdmmc_storage_execute_cmd_type1_ex(storage, &tmp, MMC_APP_CMD, storage->rca << 16, 0, expected_state, mask))
|
||||
return 0;
|
||||
|
||||
return sdmmc_execute_cmd(storage->sdmmc, cmd, req, blkcnt_out);
|
||||
return sdmmc_execute_cmd(storage->sdmmc, cmdbuf, req, blkcnt_out);
|
||||
}
|
||||
|
||||
static int _sd_storage_execute_app_cmd_type1(sdmmc_storage_t *storage, u32 *resp, u32 cmd, u32 arg, u32 check_busy, u32 expected_state)
|
||||
@@ -685,67 +698,70 @@ static int _sd_storage_execute_app_cmd_type1(sdmmc_storage_t *storage, u32 *resp
|
||||
return _sdmmc_storage_execute_cmd_type1_ex(storage, resp, cmd, arg, check_busy, expected_state, 0);
|
||||
}
|
||||
|
||||
static int _sd_storage_send_if_cond(sdmmc_storage_t *storage)
|
||||
static int _sd_storage_send_if_cond(sdmmc_storage_t *storage, bool *is_sdsc)
|
||||
{
|
||||
sdmmc_cmd_t cmdbuf;
|
||||
u16 vhd_pattern = SD_VHD_27_36 | 0xAA;
|
||||
sdmmc_init_cmd(&cmdbuf, SD_SEND_IF_COND, vhd_pattern, SDMMC_RSP_TYPE_5, 0);
|
||||
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, NULL, NULL))
|
||||
return 1; // The SD Card is version 1.X
|
||||
{
|
||||
*is_sdsc = 1; // The SD Card is version 1.X
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Card version is >= 2.0, parse results.
|
||||
// For Card version >= 2.0, parse results.
|
||||
u32 resp = 0;
|
||||
if (!sdmmc_get_rsp(storage->sdmmc, &resp, 4, SDMMC_RSP_TYPE_5))
|
||||
return 2; // Failed.
|
||||
sdmmc_get_rsp(storage->sdmmc, &resp, 4, SDMMC_RSP_TYPE_5);
|
||||
|
||||
// Check if VHD was accepted and pattern was properly returned.
|
||||
if ((resp & 0xFFF) == vhd_pattern)
|
||||
return 0;
|
||||
return 1;
|
||||
|
||||
// Failed.
|
||||
return 2;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _sd_storage_get_op_cond_once(sdmmc_storage_t *storage, u32 *cond, int is_version_1, int bus_uhs_support)
|
||||
static int _sd_storage_get_op_cond_once(sdmmc_storage_t *storage, u32 *cond, bool is_sdsc, int bus_uhs_support)
|
||||
{
|
||||
sdmmc_cmd_t cmdbuf;
|
||||
// Support for Current > 150mA
|
||||
u32 arg = !is_version_1 ? SD_OCR_XPC : 0;
|
||||
u32 arg = !is_sdsc ? SD_OCR_XPC : 0;
|
||||
// Support for handling block-addressed SDHC cards
|
||||
arg |= !is_version_1 ? SD_OCR_CCS : 0;
|
||||
arg |= !is_sdsc ? SD_OCR_CCS : 0;
|
||||
// Support for 1.8V
|
||||
arg |= (bus_uhs_support && !is_version_1) ? SD_OCR_S18R : 0;
|
||||
arg |= (bus_uhs_support && !is_sdsc) ? SD_OCR_S18R : 0;
|
||||
// This is needed for most cards. Do not set bit7 even if 1.8V is supported.
|
||||
arg |= SD_OCR_VDD_32_33;
|
||||
sdmmc_init_cmd(&cmdbuf, SD_APP_OP_COND, arg, SDMMC_RSP_TYPE_3, 0);
|
||||
if (!_sd_storage_execute_app_cmd(storage, R1_SKIP_STATE_CHECK, is_version_1 ? R1_ILLEGAL_COMMAND : 0, &cmdbuf, NULL, NULL))
|
||||
if (!_sd_storage_execute_app_cmd(storage, R1_SKIP_STATE_CHECK, is_sdsc ? R1_ILLEGAL_COMMAND : 0, &cmdbuf, NULL, NULL))
|
||||
return 0;
|
||||
|
||||
return sdmmc_get_rsp(storage->sdmmc, cond, 4, SDMMC_RSP_TYPE_3);
|
||||
}
|
||||
|
||||
static int _sd_storage_get_op_cond(sdmmc_storage_t *storage, int is_version_1, int bus_uhs_support)
|
||||
static int _sd_storage_get_op_cond(sdmmc_storage_t *storage, bool is_sdsc, int bus_uhs_support)
|
||||
{
|
||||
u32 timeout = get_tmr_ms() + 1500;
|
||||
|
||||
while (1)
|
||||
while (true)
|
||||
{
|
||||
u32 cond = 0;
|
||||
if (!_sd_storage_get_op_cond_once(storage, &cond, is_version_1, bus_uhs_support))
|
||||
if (!_sd_storage_get_op_cond_once(storage, &cond, is_sdsc, bus_uhs_support))
|
||||
break;
|
||||
if (cond & MMC_CARD_BUSY)
|
||||
|
||||
// Check if power up is done.
|
||||
if (cond & SD_OCR_BUSY)
|
||||
{
|
||||
DPRINTF("[SD] op cond: %08X, lv: %d\n", cond, bus_uhs_support);
|
||||
|
||||
// Check if card is high capacity.
|
||||
if (cond & SD_OCR_CCS)
|
||||
storage->has_sector_access = 1;
|
||||
|
||||
// Check if card supports 1.8V signaling.
|
||||
if (cond & SD_ROCR_S18A && bus_uhs_support)
|
||||
{
|
||||
//The low voltage regulator configuration is valid for SDMMC1 only.
|
||||
if (storage->sdmmc->id == SDMMC_1 &&
|
||||
_sdmmc_storage_execute_cmd_type1(storage, SD_SWITCH_VOLTAGE, 0, 0, R1_STATE_READY))
|
||||
// Switch to 1.8V signaling.
|
||||
if (_sdmmc_storage_execute_cmd_type1(storage, SD_SWITCH_VOLTAGE, 0, 0, R1_STATE_READY))
|
||||
{
|
||||
if (!sdmmc_enable_low_voltage(storage->sdmmc))
|
||||
return 0;
|
||||
@@ -776,7 +792,7 @@ static int _sd_storage_get_rca(sdmmc_storage_t *storage)
|
||||
|
||||
u32 timeout = get_tmr_ms() + 1500;
|
||||
|
||||
while (1)
|
||||
while (true)
|
||||
{
|
||||
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, NULL, NULL))
|
||||
break;
|
||||
@@ -809,8 +825,9 @@ static void _sd_storage_parse_scr(sdmmc_storage_t *storage)
|
||||
|
||||
storage->scr.sda_vsn = unstuff_bits(resp, 56, 4);
|
||||
storage->scr.bus_widths = unstuff_bits(resp, 48, 4);
|
||||
|
||||
/* If v2.0 is supported, check if Physical Layer Spec v3.0 is supported */
|
||||
if (storage->scr.sda_vsn == SCR_SPEC_VER_2)
|
||||
/* Check if Physical Layer Spec v3.0 is supported */
|
||||
storage->scr.sda_spec3 = unstuff_bits(resp, 47, 1);
|
||||
if (storage->scr.sda_spec3)
|
||||
storage->scr.cmds = unstuff_bits(resp, 32, 2);
|
||||
@@ -827,7 +844,7 @@ int _sd_storage_get_scr(sdmmc_storage_t *storage, u8 *buf)
|
||||
reqbuf.num_sectors = 1;
|
||||
reqbuf.is_write = 0;
|
||||
reqbuf.is_multi_block = 0;
|
||||
reqbuf.is_auto_cmd12 = 0;
|
||||
reqbuf.is_auto_stop_trn = 0;
|
||||
|
||||
if (!_sd_storage_execute_app_cmd(storage, R1_STATE_TRAN, 0, &cmdbuf, &reqbuf, NULL))
|
||||
return 0;
|
||||
@@ -859,7 +876,7 @@ int _sd_storage_switch_get(sdmmc_storage_t *storage, void *buf)
|
||||
reqbuf.num_sectors = 1;
|
||||
reqbuf.is_write = 0;
|
||||
reqbuf.is_multi_block = 0;
|
||||
reqbuf.is_auto_cmd12 = 0;
|
||||
reqbuf.is_auto_stop_trn = 0;
|
||||
|
||||
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, &reqbuf, NULL))
|
||||
return 0;
|
||||
@@ -883,7 +900,7 @@ int _sd_storage_switch(sdmmc_storage_t *storage, void *buf, int mode, int group,
|
||||
reqbuf.num_sectors = 1;
|
||||
reqbuf.is_write = 0;
|
||||
reqbuf.is_multi_block = 0;
|
||||
reqbuf.is_auto_cmd12 = 0;
|
||||
reqbuf.is_auto_stop_trn = 0;
|
||||
|
||||
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, &reqbuf, NULL))
|
||||
return 0;
|
||||
@@ -1064,7 +1081,7 @@ int _sd_storage_enable_hs_high_volt(sdmmc_storage_t *storage, u8 *buf)
|
||||
return sdmmc_setup_clock(storage->sdmmc, SDHCI_TIMING_SD_HS25);
|
||||
}
|
||||
|
||||
u32 sd_storage_ssr_get_au(sdmmc_storage_t *storage)
|
||||
u32 sd_storage_get_ssr_au(sdmmc_storage_t *storage)
|
||||
{
|
||||
u32 au_size = storage->ssr.uhs_au_size;
|
||||
|
||||
@@ -1104,39 +1121,24 @@ u32 sd_storage_ssr_get_au(sdmmc_storage_t *storage)
|
||||
|
||||
static void _sd_storage_parse_ssr(sdmmc_storage_t *storage)
|
||||
{
|
||||
// unstuff_bits supports only 4 u32 so break into 2 x 16byte groups
|
||||
// unstuff_bits supports only 4 u32 so break into 2 x u32x4 groups.
|
||||
u32 raw_ssr1[4];
|
||||
u32 raw_ssr2[4];
|
||||
|
||||
raw_ssr1[3] = *(u32 *)&storage->raw_ssr[12];
|
||||
raw_ssr1[2] = *(u32 *)&storage->raw_ssr[8];
|
||||
raw_ssr1[1] = *(u32 *)&storage->raw_ssr[4];
|
||||
raw_ssr1[0] = *(u32 *)&storage->raw_ssr[0];
|
||||
|
||||
raw_ssr2[3] = *(u32 *)&storage->raw_ssr[28];
|
||||
raw_ssr2[2] = *(u32 *)&storage->raw_ssr[24];
|
||||
raw_ssr2[1] = *(u32 *)&storage->raw_ssr[20];
|
||||
raw_ssr2[0] = *(u32 *)&storage->raw_ssr[16];
|
||||
memcpy(raw_ssr1, &storage->raw_ssr[0], 16);
|
||||
memcpy(raw_ssr2, &storage->raw_ssr[16], 16);
|
||||
|
||||
storage->ssr.bus_width = (unstuff_bits(raw_ssr1, 510 - 384, 2) & SD_BUS_WIDTH_4) ? 4 : 1;
|
||||
storage->ssr.protected_size = unstuff_bits(raw_ssr1, 448 - 384, 32);
|
||||
|
||||
switch(unstuff_bits(raw_ssr1, 440 - 384, 8))
|
||||
u32 speed_class = unstuff_bits(raw_ssr1, 440 - 384, 8);
|
||||
switch(speed_class)
|
||||
{
|
||||
case 0:
|
||||
storage->ssr.speed_class = 0;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
storage->ssr.speed_class = 2;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
storage->ssr.speed_class = 4;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
storage->ssr.speed_class = 6;
|
||||
storage->ssr.speed_class = speed_class << 1;
|
||||
break;
|
||||
|
||||
case 4:
|
||||
@@ -1144,19 +1146,18 @@ static void _sd_storage_parse_ssr(sdmmc_storage_t *storage)
|
||||
break;
|
||||
|
||||
default:
|
||||
storage->ssr.speed_class = unstuff_bits(raw_ssr1, 440 - 384, 8);
|
||||
storage->ssr.speed_class = speed_class;
|
||||
break;
|
||||
}
|
||||
storage->ssr.uhs_grade = unstuff_bits(raw_ssr1, 396 - 384, 4);
|
||||
storage->ssr.uhs_grade = unstuff_bits(raw_ssr1, 396 - 384, 4);
|
||||
storage->ssr.video_class = unstuff_bits(raw_ssr1, 384 - 384, 8);
|
||||
storage->ssr.app_class = unstuff_bits(raw_ssr2, 336 - 256, 4);
|
||||
|
||||
storage->ssr.app_class = unstuff_bits(raw_ssr2, 336 - 256, 4);
|
||||
|
||||
storage->ssr.au_size = unstuff_bits(raw_ssr1, 428 - 384, 4);
|
||||
storage->ssr.au_size = unstuff_bits(raw_ssr1, 428 - 384, 4);
|
||||
storage->ssr.uhs_au_size = unstuff_bits(raw_ssr1, 392 - 384, 4);
|
||||
}
|
||||
|
||||
static int _sd_storage_get_ssr(sdmmc_storage_t *storage, u8 *buf)
|
||||
int sd_storage_get_ssr(sdmmc_storage_t *storage, u8 *buf)
|
||||
{
|
||||
sdmmc_cmd_t cmdbuf;
|
||||
sdmmc_init_cmd(&cmdbuf, SD_APP_SD_STATUS, 0, SDMMC_RSP_TYPE_1, 0);
|
||||
@@ -1167,11 +1168,11 @@ static int _sd_storage_get_ssr(sdmmc_storage_t *storage, u8 *buf)
|
||||
reqbuf.num_sectors = 1;
|
||||
reqbuf.is_write = 0;
|
||||
reqbuf.is_multi_block = 0;
|
||||
reqbuf.is_auto_cmd12 = 0;
|
||||
reqbuf.is_auto_stop_trn = 0;
|
||||
|
||||
if (!(storage->csd.cmdclass & CCC_APP_SPEC))
|
||||
{
|
||||
DPRINTF("[SD] ssr: Card lacks mandatory SD Status function\n");
|
||||
DPRINTF("[SD] ssr: Not supported\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1180,14 +1181,16 @@ DPRINTF("[SD] ssr: Card lacks mandatory SD Status function\n");
|
||||
|
||||
u32 tmp = 0;
|
||||
sdmmc_get_rsp(storage->sdmmc, &tmp, 4, SDMMC_RSP_TYPE_1);
|
||||
//Prepare buffer for unstuff_bits
|
||||
for (int i = 0; i < 64; i+=4)
|
||||
|
||||
// Convert buffer to LE.
|
||||
for (int i = 0; i < 64; i += 4)
|
||||
{
|
||||
storage->raw_ssr[i + 3] = buf[i];
|
||||
storage->raw_ssr[i + 2] = buf[i + 1];
|
||||
storage->raw_ssr[i + 1] = buf[i + 2];
|
||||
storage->raw_ssr[i] = buf[i + 3];
|
||||
}
|
||||
|
||||
_sd_storage_parse_ssr(storage);
|
||||
//gfx_hexdump(0, storage->raw_ssr, 64);
|
||||
|
||||
@@ -1198,18 +1201,18 @@ static void _sd_storage_parse_cid(sdmmc_storage_t *storage)
|
||||
{
|
||||
u32 *raw_cid = (u32 *)&(storage->raw_cid);
|
||||
|
||||
storage->cid.manfid = unstuff_bits(raw_cid, 120, 8);
|
||||
storage->cid.oemid = unstuff_bits(raw_cid, 104, 16);
|
||||
storage->cid.prod_name[0] = unstuff_bits(raw_cid, 96, 8);
|
||||
storage->cid.prod_name[1] = unstuff_bits(raw_cid, 88, 8);
|
||||
storage->cid.prod_name[2] = unstuff_bits(raw_cid, 80, 8);
|
||||
storage->cid.prod_name[3] = unstuff_bits(raw_cid, 72, 8);
|
||||
storage->cid.prod_name[4] = unstuff_bits(raw_cid, 64, 8);
|
||||
storage->cid.hwrev = unstuff_bits(raw_cid, 60, 4);
|
||||
storage->cid.fwrev = unstuff_bits(raw_cid, 56, 4);
|
||||
storage->cid.serial = unstuff_bits(raw_cid, 24, 32);
|
||||
storage->cid.month = unstuff_bits(raw_cid, 8, 4);
|
||||
storage->cid.year = unstuff_bits(raw_cid, 12, 8) + 2000;
|
||||
storage->cid.manfid = unstuff_bits(raw_cid, 120, 8);
|
||||
storage->cid.oemid = unstuff_bits(raw_cid, 104, 16);
|
||||
storage->cid.prod_name[0] = unstuff_bits(raw_cid, 96, 8);
|
||||
storage->cid.prod_name[1] = unstuff_bits(raw_cid, 88, 8);
|
||||
storage->cid.prod_name[2] = unstuff_bits(raw_cid, 80, 8);
|
||||
storage->cid.prod_name[3] = unstuff_bits(raw_cid, 72, 8);
|
||||
storage->cid.prod_name[4] = unstuff_bits(raw_cid, 64, 8);
|
||||
storage->cid.hwrev = unstuff_bits(raw_cid, 60, 4);
|
||||
storage->cid.fwrev = unstuff_bits(raw_cid, 56, 4);
|
||||
storage->cid.serial = unstuff_bits(raw_cid, 24, 32);
|
||||
storage->cid.year = unstuff_bits(raw_cid, 12, 8) + 2000;
|
||||
storage->cid.month = unstuff_bits(raw_cid, 8, 4);
|
||||
}
|
||||
|
||||
static void _sd_storage_parse_csd(sdmmc_storage_t *storage)
|
||||
@@ -1224,6 +1227,7 @@ static void _sd_storage_parse_csd(sdmmc_storage_t *storage)
|
||||
{
|
||||
case 0:
|
||||
storage->csd.capacity = (1 + unstuff_bits(raw_csd, 62, 12)) << (unstuff_bits(raw_csd, 47, 3) + 2);
|
||||
storage->csd.capacity <<= unstuff_bits(raw_csd, 80, 4) - 9; // Convert native block size to LBA 512B.
|
||||
break;
|
||||
|
||||
case 1:
|
||||
@@ -1231,7 +1235,13 @@ static void _sd_storage_parse_csd(sdmmc_storage_t *storage)
|
||||
storage->csd.capacity = storage->csd.c_size << 10;
|
||||
storage->csd.read_blkbits = 9;
|
||||
break;
|
||||
|
||||
default:
|
||||
DPRINTF("[SD] unknown CSD structure %d\n", storage->csd.structure);
|
||||
break;
|
||||
}
|
||||
|
||||
storage->sec_cnt = storage->csd.capacity;
|
||||
}
|
||||
|
||||
static bool _sdmmc_storage_get_bus_uhs_support(u32 bus_width, u32 type)
|
||||
@@ -1261,8 +1271,10 @@ void sdmmc_storage_init_wait_sd()
|
||||
|
||||
int sdmmc_storage_init_sd(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 bus_width, u32 type)
|
||||
{
|
||||
int is_version_1 = 0;
|
||||
u8 *buf = (u8 *)SDMMC_UPPER_BUFFER;
|
||||
u32 tmp = 0;
|
||||
int is_sdsc = 0;
|
||||
u8 *buf = (u8 *)SDMMC_UPPER_BUFFER;
|
||||
bool bus_uhs_support = _sdmmc_storage_get_bus_uhs_support(bus_width, type);
|
||||
|
||||
DPRINTF("[SD] init: bus: %d, type: %d\n", bus_width, type);
|
||||
|
||||
@@ -1282,18 +1294,15 @@ DPRINTF("[SD] after init\n");
|
||||
return 0;
|
||||
DPRINTF("[SD] went to idle state\n");
|
||||
|
||||
is_version_1 = _sd_storage_send_if_cond(storage);
|
||||
if (is_version_1 == 2) // Failed.
|
||||
if (!_sd_storage_send_if_cond(storage, &is_sdsc))
|
||||
return 0;
|
||||
DPRINTF("[SD] after send if cond\n");
|
||||
|
||||
bool bus_uhs_support = _sdmmc_storage_get_bus_uhs_support(bus_width, type);
|
||||
|
||||
if (!_sd_storage_get_op_cond(storage, is_version_1, bus_uhs_support))
|
||||
if (!_sd_storage_get_op_cond(storage, is_sdsc, bus_uhs_support))
|
||||
return 0;
|
||||
DPRINTF("[SD] got op cond\n");
|
||||
|
||||
if (!_sdmmc_storage_get_cid(storage, storage->raw_cid))
|
||||
if (!_sdmmc_storage_get_cid(storage))
|
||||
return 0;
|
||||
DPRINTF("[SD] got cid\n");
|
||||
_sd_storage_parse_cid(storage);
|
||||
@@ -1302,30 +1311,16 @@ DPRINTF("[SD] got cid\n");
|
||||
return 0;
|
||||
DPRINTF("[SD] got rca (= %04X)\n", storage->rca);
|
||||
|
||||
if (!_sdmmc_storage_get_csd(storage, storage->raw_csd))
|
||||
if (!_sdmmc_storage_get_csd(storage))
|
||||
return 0;
|
||||
DPRINTF("[SD] got csd\n");
|
||||
|
||||
//Parse CSD.
|
||||
_sd_storage_parse_csd(storage);
|
||||
switch (storage->csd.structure)
|
||||
{
|
||||
case 0:
|
||||
storage->sec_cnt = storage->csd.capacity;
|
||||
break;
|
||||
case 1:
|
||||
storage->sec_cnt = storage->csd.c_size << 10;
|
||||
break;
|
||||
default:
|
||||
DPRINTF("[SD] unknown CSD structure %d\n", storage->csd.structure);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!storage->is_low_voltage)
|
||||
{
|
||||
if (!sdmmc_setup_clock(storage->sdmmc, SDHCI_TIMING_SD_DS12))
|
||||
return 0;
|
||||
DPRINTF("[SD] after setup clock\n");
|
||||
DPRINTF("[SD] after setup default clock\n");
|
||||
}
|
||||
|
||||
if (!_sdmmc_storage_select_card(storage))
|
||||
@@ -1336,19 +1331,17 @@ DPRINTF("[SD] card selected\n");
|
||||
return 0;
|
||||
DPRINTF("[SD] set blocklen to 512\n");
|
||||
|
||||
u32 tmp = 0;
|
||||
// Disconnect Card Detect resistor from DAT3.
|
||||
if (!_sd_storage_execute_app_cmd_type1(storage, &tmp, SD_APP_SET_CLR_CARD_DETECT, 0, 0, R1_STATE_TRAN))
|
||||
return 0;
|
||||
DPRINTF("[SD] cleared card detect\n");
|
||||
|
||||
if (!_sd_storage_get_scr(storage, buf))
|
||||
return 0;
|
||||
|
||||
//gfx_hexdump(0, storage->raw_scr, 8);
|
||||
DPRINTF("[SD] got scr\n");
|
||||
|
||||
// Check if card supports a wider bus and if it's not SD Version 1.X
|
||||
if (bus_width == SDMMC_BUS_WIDTH_4 && (storage->scr.bus_widths & 4) && (storage->scr.sda_vsn & 0xF))
|
||||
// If card supports a wider bus and if it's not SD Version 1.0 switch bus width.
|
||||
if (bus_width == SDMMC_BUS_WIDTH_4 && (storage->scr.bus_widths & BIT(SD_BUS_WIDTH_4)) && storage->scr.sda_vsn)
|
||||
{
|
||||
if (!_sd_storage_execute_app_cmd_type1(storage, &tmp, SD_APP_SET_BUS_WIDTH, SD_BUS_WIDTH_4, 0, R1_STATE_TRAN))
|
||||
return 0;
|
||||
@@ -1370,7 +1363,7 @@ DPRINTF("[SD] enabled UHS\n");
|
||||
|
||||
sdmmc_card_clock_powersave(sdmmc, SDMMC_POWER_SAVE_ENABLE);
|
||||
}
|
||||
else if (type != SDHCI_TIMING_SD_DS12 && (storage->scr.sda_vsn & 0xF)) // Not default speed and not SD Version 1.x
|
||||
else if (type != SDHCI_TIMING_SD_DS12 && storage->scr.sda_vsn) // Not default speed and not SD Version 1.0.
|
||||
{
|
||||
if (!_sd_storage_enable_hs_high_volt(storage, buf))
|
||||
return 0;
|
||||
@@ -1389,7 +1382,7 @@ DPRINTF("[SD] enabled HS\n");
|
||||
}
|
||||
|
||||
// Parse additional card info from sd status.
|
||||
if (_sd_storage_get_ssr(storage, buf))
|
||||
if (sd_storage_get_ssr(storage, buf))
|
||||
{
|
||||
DPRINTF("[SD] got sd status\n");
|
||||
}
|
||||
@@ -1400,14 +1393,14 @@ DPRINTF("[SD] got sd status\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* Gamecard specific functions.
|
||||
*/
|
||||
* Gamecard specific functions.
|
||||
*/
|
||||
|
||||
int _gc_storage_custom_cmd(sdmmc_storage_t *storage, void *buf)
|
||||
{
|
||||
u32 resp;
|
||||
sdmmc_cmd_t cmdbuf;
|
||||
sdmmc_init_cmd(&cmdbuf, 60, 0, SDMMC_RSP_TYPE_1, 1);
|
||||
sdmmc_init_cmd(&cmdbuf, MMC_VENDOR_60_CMD, 0, SDMMC_RSP_TYPE_1, 1);
|
||||
|
||||
sdmmc_req_t reqbuf;
|
||||
reqbuf.buf = buf;
|
||||
@@ -1415,7 +1408,7 @@ int _gc_storage_custom_cmd(sdmmc_storage_t *storage, void *buf)
|
||||
reqbuf.num_sectors = 1;
|
||||
reqbuf.is_write = 1;
|
||||
reqbuf.is_multi_block = 0;
|
||||
reqbuf.is_auto_cmd12 = 0;
|
||||
reqbuf.is_auto_stop_trn = 0;
|
||||
|
||||
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, &reqbuf, NULL))
|
||||
{
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2018-2020 CTCaer
|
||||
* Copyright (c) 2018-2021 CTCaer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
@@ -30,18 +30,18 @@ typedef enum _sdmmc_type
|
||||
|
||||
EMMC_GPP = 0,
|
||||
EMMC_BOOT0 = 1,
|
||||
EMMC_BOOT1 = 2
|
||||
EMMC_BOOT1 = 2,
|
||||
EMMC_RPMB = 3
|
||||
} sdmmc_type;
|
||||
|
||||
typedef struct _mmc_cid
|
||||
{
|
||||
u32 manfid;
|
||||
u8 prod_name[8];
|
||||
u8 card_bga;
|
||||
u8 prv;
|
||||
u32 serial;
|
||||
u16 oemid;
|
||||
u16 year;
|
||||
u8 prv;
|
||||
u8 hwrev;
|
||||
u8 fwrev;
|
||||
u8 month;
|
||||
@@ -65,19 +65,20 @@ typedef struct _mmc_csd
|
||||
|
||||
typedef struct _mmc_ext_csd
|
||||
{
|
||||
u32 sectors;
|
||||
int bkops; /* background support bit */
|
||||
int bkops_en; /* manual bkops enable bit */
|
||||
//u8 bkops; /* background support bit */
|
||||
//u8 bkops_en; /* manual bkops enable bit */
|
||||
//u8 bkops_status; /* 246 */
|
||||
u8 rev;
|
||||
u8 ext_struct; /* 194 */
|
||||
u8 card_type; /* 196 */
|
||||
u8 bkops_status; /* 246 */
|
||||
u8 pre_eol_info;
|
||||
u8 dev_life_est_a;
|
||||
u8 dev_life_est_b;
|
||||
u8 boot_mult;
|
||||
u8 rpmb_mult;
|
||||
u16 dev_version;
|
||||
u32 cache_size;
|
||||
u32 max_enh_mult;
|
||||
} mmc_ext_csd_t;
|
||||
|
||||
typedef struct _sd_scr
|
||||
@@ -90,13 +91,13 @@ typedef struct _sd_scr
|
||||
|
||||
typedef struct _sd_ssr
|
||||
{
|
||||
u8 bus_width;
|
||||
u8 speed_class;
|
||||
u8 uhs_grade;
|
||||
u8 video_class;
|
||||
u8 app_class;
|
||||
u8 au_size;
|
||||
u8 uhs_au_size;
|
||||
u8 bus_width;
|
||||
u8 speed_class;
|
||||
u8 uhs_grade;
|
||||
u8 video_class;
|
||||
u8 app_class;
|
||||
u8 au_size;
|
||||
u8 uhs_au_size;
|
||||
u32 protected_size;
|
||||
} sd_ssr_t;
|
||||
|
||||
@@ -130,6 +131,7 @@ void sdmmc_storage_init_wait_sd();
|
||||
int sdmmc_storage_init_sd(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 bus_width, u32 type);
|
||||
int sdmmc_storage_init_gc(sdmmc_storage_t *storage, sdmmc_t *sdmmc);
|
||||
|
||||
u32 sd_storage_ssr_get_au(sdmmc_storage_t *storage);
|
||||
int sd_storage_get_ssr(sdmmc_storage_t *storage, u8 *buf);
|
||||
u32 sd_storage_get_ssr_au(sdmmc_storage_t *storage);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2018-2020 CTCaer
|
||||
* Copyright (c) 2018-2021 CTCaer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
@@ -934,12 +934,20 @@ static int _sdmmc_config_dma(sdmmc_t *sdmmc, u32 *blkcnt_out, sdmmc_req_t *req)
|
||||
*blkcnt_out = blkcnt;
|
||||
|
||||
u32 trnmode = SDHCI_TRNS_DMA;
|
||||
|
||||
// Set mulitblock request.
|
||||
if (req->is_multi_block)
|
||||
trnmode = SDHCI_TRNS_MULTI | SDHCI_TRNS_BLK_CNT_EN | SDHCI_TRNS_DMA;
|
||||
|
||||
// Set request direction.
|
||||
if (!req->is_write)
|
||||
trnmode |= SDHCI_TRNS_READ;
|
||||
if (req->is_auto_cmd12)
|
||||
trnmode = (trnmode & ~(SDHCI_TRNS_AUTO_CMD12 | SDHCI_TRNS_AUTO_CMD23)) | SDHCI_TRNS_AUTO_CMD12;
|
||||
|
||||
// Automatic send of stop transmission or set block count cmd.
|
||||
if (req->is_auto_stop_trn)
|
||||
trnmode |= SDHCI_TRNS_AUTO_CMD12;
|
||||
//else if (req->is_auto_set_blkcnt)
|
||||
// trnmode |= SDHCI_TRNS_AUTO_CMD23;
|
||||
|
||||
sdmmc->regs->trnmod = trnmode;
|
||||
|
||||
@@ -1070,7 +1078,7 @@ DPRINTF("rsp(%d): %08X, %08X, %08X, %08X\n", result,
|
||||
if (blkcnt_out)
|
||||
*blkcnt_out = blkcnt;
|
||||
|
||||
if (req->is_auto_cmd12)
|
||||
if (req->is_auto_stop_trn)
|
||||
sdmmc->rsp3 = sdmmc->regs->rspreg3;
|
||||
}
|
||||
|
||||
|
||||
@@ -242,7 +242,7 @@ typedef struct _sdmmc_req_t
|
||||
u32 num_sectors;
|
||||
int is_write;
|
||||
int is_multi_block;
|
||||
int is_auto_cmd12;
|
||||
int is_auto_stop_trn;
|
||||
} sdmmc_req_t;
|
||||
|
||||
int sdmmc_get_io_power(sdmmc_t *sdmmc);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2018-2020 CTCaer
|
||||
* Copyright (c) 2018-2021 CTCaer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
@@ -75,10 +75,9 @@ typedef int bool;
|
||||
#define EXTRA_CFG_PAYLOAD BIT(1)
|
||||
#define EXTRA_CFG_MODULE BIT(2)
|
||||
|
||||
#define EXTRA_CFG_NYX_BIS BIT(4)
|
||||
#define EXTRA_CFG_NYX_UMS BIT(5)
|
||||
#define EXTRA_CFG_NYX_RELOAD BIT(6)
|
||||
#define EXTRA_CFG_NYX_DUMP BIT(7)
|
||||
#define EXTRA_CFG_NYX_SEPT BIT(7)
|
||||
|
||||
typedef enum _nyx_ums_type
|
||||
{
|
||||
@@ -91,6 +90,13 @@ typedef enum _nyx_ums_type
|
||||
NYX_UMS_EMUMMC_GPP
|
||||
} nyx_ums_type;
|
||||
|
||||
typedef enum _nyx_sept_type
|
||||
{
|
||||
NYX_SEPT_DUMP = 0,
|
||||
NYX_SEPT_CAL0,
|
||||
NYX_SEPT_EMUF
|
||||
} nyx_sept_type;
|
||||
|
||||
typedef struct __attribute__((__packed__)) _boot_cfg_t
|
||||
{
|
||||
u8 boot_cfg;
|
||||
@@ -104,7 +110,8 @@ typedef struct __attribute__((__packed__)) _boot_cfg_t
|
||||
char id[8]; // 7 char ASCII null teminated.
|
||||
char emummc_path[0x78]; // emuMMC/XXX, ASCII null teminated.
|
||||
};
|
||||
u8 ums; // nyx_ums_type.
|
||||
u8 ums; // nyx_ums_type.
|
||||
u8 sept; // nyx_sept_type.
|
||||
u8 xt_str[0x80];
|
||||
};
|
||||
} boot_cfg_t;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2018-2020 CTCaer
|
||||
* Copyright (c) 2018-2021 CTCaer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
@@ -35,9 +35,10 @@ typedef enum
|
||||
|
||||
typedef enum
|
||||
{
|
||||
NYX_CFG_BIS = BIT(5),
|
||||
NYX_CFG_UMS = BIT(6),
|
||||
NYX_CFG_DUMP = BIT(7),
|
||||
NYX_CFG_SEPT = BIT(7),
|
||||
|
||||
NYX_CFG_EXTRA = 0xFF << 24
|
||||
} nyx_cfg_t;
|
||||
|
||||
typedef enum
|
||||
@@ -53,6 +54,8 @@ typedef enum
|
||||
#define byte_swap_32(num) ((((num) >> 24) & 0xff) | (((num) << 8) & 0xff0000) | \
|
||||
(((num) >> 8 )& 0xff00) | (((num) << 24) & 0xff000000))
|
||||
|
||||
#define byte_swap_16(num) ((((num) >> 8) & 0xff) | (((num) << 8) & 0xff00))
|
||||
|
||||
typedef struct _cfg_op_t
|
||||
{
|
||||
u32 off;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2018 Rajko Stojadinovic
|
||||
* Copyright (c) 2018-2019 CTCaer
|
||||
* Copyright (c) 2018-2021 CTCaer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
@@ -27,6 +27,7 @@
|
||||
#include <libs/fatfs/ff.h>
|
||||
#include <mem/heap.h>
|
||||
#include <sec/se.h>
|
||||
#include <sec/se_t210.h>
|
||||
#include "../storage/nx_emmc.h"
|
||||
#include <storage/nx_sd.h>
|
||||
#include <storage/sdmmc.h>
|
||||
@@ -96,7 +97,7 @@ static int _dump_emmc_verify(sdmmc_storage_t *storage, u32 lba_curr, char *outFi
|
||||
|
||||
se_calc_sha256_oneshot(hashEm, bufEm, num << 9);
|
||||
se_calc_sha256_oneshot(hashSd, bufSd, num << 9);
|
||||
res = memcmp(hashEm, hashSd, 0x10);
|
||||
res = memcmp(hashEm, hashSd, SE_SHA_256_SIZE / 2);
|
||||
|
||||
if (res)
|
||||
{
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2018-2020 CTCaer
|
||||
* Copyright (c) 2018-2021 CTCaer
|
||||
* Copyright (c) 2018 balika011
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
@@ -27,6 +27,7 @@
|
||||
#include <mem/smmu.h>
|
||||
#include <power/bq24193.h>
|
||||
#include <power/max17050.h>
|
||||
#include <sec/se_t210.h>
|
||||
#include <sec/tsec.h>
|
||||
#include <soc/fuse.h>
|
||||
#include <soc/i2c.h>
|
||||
@@ -130,10 +131,7 @@ void print_mmc_info()
|
||||
|
||||
static const u32 SECTORS_TO_MIB_COEFF = 11;
|
||||
|
||||
sdmmc_storage_t storage;
|
||||
sdmmc_t sdmmc;
|
||||
|
||||
if (!sdmmc_storage_init_mmc(&storage, &sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400))
|
||||
if (!sdmmc_storage_init_mmc(&emmc_storage, &emmc_sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400))
|
||||
{
|
||||
EPRINTF("Failed to init eMMC.");
|
||||
goto out;
|
||||
@@ -144,35 +142,34 @@ void print_mmc_info()
|
||||
u32 speed = 0;
|
||||
|
||||
gfx_printf("%kCID:%k\n", 0xFF00DDFF, 0xFFCCCCCC);
|
||||
switch (storage.csd.mmca_vsn)
|
||||
switch (emmc_storage.csd.mmca_vsn)
|
||||
{
|
||||
case 2: /* MMC v2.0 - v2.2 */
|
||||
case 3: /* MMC v3.1 - v3.3 */
|
||||
case 4: /* MMC v4 */
|
||||
gfx_printf(
|
||||
" Vendor ID: %X\n"
|
||||
" Card/BGA: %X\n"
|
||||
" OEM ID: %02X\n"
|
||||
" Model: %c%c%c%c%c%c\n"
|
||||
" Prd Rev: %X\n"
|
||||
" S/N: %04X\n"
|
||||
" Month/Year: %02d/%04d\n\n",
|
||||
storage.cid.manfid, storage.cid.card_bga, storage.cid.oemid,
|
||||
storage.cid.prod_name[0], storage.cid.prod_name[1], storage.cid.prod_name[2],
|
||||
storage.cid.prod_name[3], storage.cid.prod_name[4], storage.cid.prod_name[5],
|
||||
storage.cid.prv, storage.cid.serial, storage.cid.month, storage.cid.year);
|
||||
emmc_storage.cid.manfid, emmc_storage.cid.oemid,
|
||||
emmc_storage.cid.prod_name[0], emmc_storage.cid.prod_name[1], emmc_storage.cid.prod_name[2],
|
||||
emmc_storage.cid.prod_name[3], emmc_storage.cid.prod_name[4], emmc_storage.cid.prod_name[5],
|
||||
emmc_storage.cid.prv, emmc_storage.cid.serial, emmc_storage.cid.month, emmc_storage.cid.year);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (storage.csd.structure == 0)
|
||||
if (emmc_storage.csd.structure == 0)
|
||||
EPRINTF("Unknown CSD structure.");
|
||||
else
|
||||
{
|
||||
gfx_printf("%kExtended CSD V1.%d:%k\n",
|
||||
0xFF00DDFF, storage.ext_csd.ext_struct, 0xFFCCCCCC);
|
||||
card_type = storage.ext_csd.card_type;
|
||||
0xFF00DDFF, emmc_storage.ext_csd.ext_struct, 0xFFCCCCCC);
|
||||
card_type = emmc_storage.ext_csd.card_type;
|
||||
char card_type_support[96];
|
||||
card_type_support[0] = 0;
|
||||
if (card_type & EXT_CSD_CARD_TYPE_HS_26)
|
||||
@@ -210,16 +207,16 @@ void print_mmc_info()
|
||||
" Max Rate: %d MB/s (%d MHz)\n"
|
||||
" Current Rate: %d MB/s\n"
|
||||
" Type Support: ",
|
||||
storage.csd.mmca_vsn, storage.ext_csd.rev, storage.ext_csd.dev_version, storage.csd.cmdclass,
|
||||
storage.csd.capacity == (4096 * 512) ? "High" : "Low", speed & 0xFFFF, (speed >> 16) & 0xFFFF,
|
||||
storage.csd.busspeed);
|
||||
emmc_storage.csd.mmca_vsn, emmc_storage.ext_csd.rev, emmc_storage.ext_csd.dev_version, emmc_storage.csd.cmdclass,
|
||||
emmc_storage.csd.capacity == (4096 * 512) ? "High" : "Low", speed & 0xFFFF, (speed >> 16) & 0xFFFF,
|
||||
emmc_storage.csd.busspeed);
|
||||
gfx_con.fntsz = 8;
|
||||
gfx_printf("%s", card_type_support);
|
||||
gfx_con.fntsz = 16;
|
||||
gfx_printf("\n\n", card_type_support);
|
||||
|
||||
u32 boot_size = storage.ext_csd.boot_mult << 17;
|
||||
u32 rpmb_size = storage.ext_csd.rpmb_mult << 17;
|
||||
u32 boot_size = emmc_storage.ext_csd.boot_mult << 17;
|
||||
u32 rpmb_size = emmc_storage.ext_csd.rpmb_mult << 17;
|
||||
gfx_printf("%keMMC Partitions:%k\n", 0xFF00DDFF, 0xFFCCCCCC);
|
||||
gfx_printf(" 1: %kBOOT0 %k\n Size: %5d KiB (LBA Sectors: 0x%07X)\n", 0xFF96FF00, 0xFFCCCCCC,
|
||||
boot_size / 1024, boot_size / 512);
|
||||
@@ -231,13 +228,13 @@ void print_mmc_info()
|
||||
rpmb_size / 1024, rpmb_size / 512);
|
||||
gfx_put_small_sep();
|
||||
gfx_printf(" 0: %kGPP (USER) %k\n Size: %5d MiB (LBA Sectors: 0x%07X)\n\n", 0xFF96FF00, 0xFFCCCCCC,
|
||||
storage.sec_cnt >> SECTORS_TO_MIB_COEFF, storage.sec_cnt);
|
||||
emmc_storage.sec_cnt >> SECTORS_TO_MIB_COEFF, emmc_storage.sec_cnt);
|
||||
gfx_put_small_sep();
|
||||
gfx_printf("%kGPP (eMMC USER) partition table:%k\n", 0xFF00DDFF, 0xFFCCCCCC);
|
||||
|
||||
sdmmc_storage_set_mmc_partition(&storage, EMMC_GPP);
|
||||
sdmmc_storage_set_mmc_partition(&emmc_storage, EMMC_GPP);
|
||||
LIST_INIT(gpt);
|
||||
nx_emmc_gpt_parse(&gpt, &storage);
|
||||
nx_emmc_gpt_parse(&gpt, &emmc_storage);
|
||||
int gpp_idx = 0;
|
||||
LIST_FOREACH_ENTRY(emmc_part_t, part, &gpt, link)
|
||||
{
|
||||
@@ -251,7 +248,7 @@ void print_mmc_info()
|
||||
}
|
||||
|
||||
out:
|
||||
sdmmc_storage_end(&storage);
|
||||
sdmmc_storage_end(&emmc_storage);
|
||||
|
||||
btn_wait();
|
||||
}
|
||||
@@ -263,7 +260,7 @@ void print_sdcard_info()
|
||||
gfx_clear_partial_grey(0x1B, 0, 1256);
|
||||
gfx_con_setpos(0, 0);
|
||||
|
||||
if (sd_initialize(true))
|
||||
if (sd_initialize(false))
|
||||
{
|
||||
gfx_printf("%kCard IDentification:%k\n", 0xFF00DDFF, 0xFFCCCCCC);
|
||||
gfx_printf(
|
||||
@@ -337,16 +334,14 @@ void print_tsec_key()
|
||||
u32 retries = 0;
|
||||
|
||||
tsec_ctxt_t tsec_ctxt;
|
||||
sdmmc_storage_t storage;
|
||||
sdmmc_t sdmmc;
|
||||
|
||||
sdmmc_storage_init_mmc(&storage, &sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400);
|
||||
sdmmc_storage_init_mmc(&emmc_storage, &emmc_sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400);
|
||||
|
||||
// Read package1.
|
||||
u8 *pkg1 = (u8 *)malloc(0x40000);
|
||||
sdmmc_storage_set_mmc_partition(&storage, EMMC_BOOT0);
|
||||
sdmmc_storage_read(&storage, 0x100000 / NX_EMMC_BLOCKSIZE, 0x40000 / NX_EMMC_BLOCKSIZE, pkg1);
|
||||
sdmmc_storage_end(&storage);
|
||||
sdmmc_storage_set_mmc_partition(&emmc_storage, EMMC_BOOT0);
|
||||
sdmmc_storage_read(&emmc_storage, 0x100000 / NX_EMMC_BLOCKSIZE, 0x40000 / NX_EMMC_BLOCKSIZE, pkg1);
|
||||
sdmmc_storage_end(&emmc_storage);
|
||||
const pkg1_id_t *pkg1_id = pkg1_identify(pkg1);
|
||||
if (!pkg1_id)
|
||||
{
|
||||
@@ -354,7 +349,7 @@ void print_tsec_key()
|
||||
goto out_wait;
|
||||
}
|
||||
|
||||
u8 keys[0x10 * 2];
|
||||
u8 keys[SE_KEY_128_SIZE * 2];
|
||||
memset(keys, 0x00, 0x20);
|
||||
|
||||
tsec_ctxt.fw = (u8 *)pkg1 + pkg1_id->tsec_off;
|
||||
@@ -401,14 +396,14 @@ void print_tsec_key()
|
||||
|
||||
if (res >= 0)
|
||||
{
|
||||
for (u32 j = 0; j < 0x10; j++)
|
||||
for (u32 j = 0; j < SE_KEY_128_SIZE; j++)
|
||||
gfx_printf("%02X", keys[j]);
|
||||
|
||||
if (pkg1_id->kb == KB_FIRMWARE_VERSION_620)
|
||||
{
|
||||
gfx_printf("\n%kTSEC root: %k", 0xFF00DDFF, 0xFFCCCCCC);
|
||||
for (u32 j = 0; j < 0x10; j++)
|
||||
gfx_printf("%02X", keys[0x10 + j]);
|
||||
for (u32 j = 0; j < SE_KEY_128_SIZE; j++)
|
||||
gfx_printf("%02X", keys[SE_KEY_128_SIZE + j]);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -423,7 +418,7 @@ void print_tsec_key()
|
||||
{
|
||||
char path[64];
|
||||
emmcsn_path_impl(path, "/dumps", "tsec_keys.bin", NULL);
|
||||
if (!sd_save_to_file(keys, 0x10 * 2, path))
|
||||
if (!sd_save_to_file(keys, SE_KEY_128_SIZE * 2, path))
|
||||
gfx_puts("\nDone!\n");
|
||||
sd_end();
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2018-2019 CTCaer
|
||||
* Copyright (c) 2018-2021 CTCaer
|
||||
* Copyright (c) 2018 Reisyukaku
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
@@ -31,6 +31,7 @@
|
||||
#include <mem/heap.h>
|
||||
#include <power/max7762x.h>
|
||||
#include <sec/se.h>
|
||||
#include <sec/se_t210.h>
|
||||
#include "../storage/nx_emmc.h"
|
||||
#include <storage/nx_sd.h>
|
||||
#include <storage/sdmmc.h>
|
||||
@@ -65,23 +66,21 @@ void dump_packages12()
|
||||
gfx_clear_partial_grey(0x1B, 0, 1256);
|
||||
gfx_con_setpos(0, 0);
|
||||
|
||||
sdmmc_storage_t storage;
|
||||
sdmmc_t sdmmc;
|
||||
if (!sdmmc_storage_init_mmc(&storage, &sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400))
|
||||
if (!sdmmc_storage_init_mmc(&emmc_storage, &emmc_sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400))
|
||||
{
|
||||
EPRINTF("Failed to init eMMC.");
|
||||
goto out_free;
|
||||
}
|
||||
sdmmc_storage_set_mmc_partition(&storage, EMMC_BOOT0);
|
||||
sdmmc_storage_set_mmc_partition(&emmc_storage, EMMC_BOOT0);
|
||||
|
||||
// Read package1.
|
||||
sdmmc_storage_read(&storage, 0x100000 / NX_EMMC_BLOCKSIZE, 0x40000 / NX_EMMC_BLOCKSIZE, pkg1);
|
||||
sdmmc_storage_read(&emmc_storage, 0x100000 / NX_EMMC_BLOCKSIZE, 0x40000 / NX_EMMC_BLOCKSIZE, pkg1);
|
||||
const pkg1_id_t *pkg1_id = pkg1_identify(pkg1);
|
||||
if (!pkg1_id)
|
||||
{
|
||||
EPRINTF("Unknown pkg1 version for reading\nTSEC firmware.");
|
||||
// Dump package1.
|
||||
emmcsn_path_impl(path, "/pkg1", "pkg1_enc.bin", &storage);
|
||||
emmcsn_path_impl(path, "/pkg1", "pkg1_enc.bin", &emmc_storage);
|
||||
if (sd_save_to_file(pkg1, 0x40000, path))
|
||||
goto out_free;
|
||||
gfx_puts("\nEnc pkg1 dumped to pkg1_enc.bin\n");
|
||||
@@ -115,7 +114,7 @@ void dump_packages12()
|
||||
|
||||
// Read keyblob.
|
||||
u8 *keyblob = (u8 *)calloc(NX_EMMC_BLOCKSIZE, 1);
|
||||
sdmmc_storage_read(&storage, 0x180000 / NX_EMMC_BLOCKSIZE + kb, 1, keyblob);
|
||||
sdmmc_storage_read(&emmc_storage, 0x180000 / NX_EMMC_BLOCKSIZE + kb, 1, keyblob);
|
||||
|
||||
// Decrypt.
|
||||
hos_keygen(keyblob, kb, &tsec_ctxt, NULL);
|
||||
@@ -155,35 +154,35 @@ void dump_packages12()
|
||||
gfx_printf("%kWarmboot size: %k0x%05X\n\n", 0xFFC7EA46, 0xFFCCCCCC, hdr_pk11->wb_size);
|
||||
|
||||
// Dump package1.1.
|
||||
emmcsn_path_impl(path, "/pkg1", "pkg1_decr.bin", &storage);
|
||||
emmcsn_path_impl(path, "/pkg1", "pkg1_decr.bin", &emmc_storage);
|
||||
if (sd_save_to_file(pkg1, 0x40000, path))
|
||||
goto out_free;
|
||||
gfx_puts("\npkg1 dumped to pkg1_decr.bin\n");
|
||||
|
||||
// Dump nxbootloader.
|
||||
emmcsn_path_impl(path, "/pkg1", "nxloader.bin", &storage);
|
||||
emmcsn_path_impl(path, "/pkg1", "nxloader.bin", &emmc_storage);
|
||||
if (sd_save_to_file(loader, hdr_pk11->ldr_size, path))
|
||||
goto out_free;
|
||||
gfx_puts("NX Bootloader dumped to nxloader.bin\n");
|
||||
|
||||
// Dump secmon.
|
||||
emmcsn_path_impl(path, "/pkg1", "secmon.bin", &storage);
|
||||
emmcsn_path_impl(path, "/pkg1", "secmon.bin", &emmc_storage);
|
||||
if (sd_save_to_file(secmon, hdr_pk11->sm_size, path))
|
||||
goto out_free;
|
||||
gfx_puts("Secure Monitor dumped to secmon.bin\n");
|
||||
|
||||
// Dump warmboot.
|
||||
emmcsn_path_impl(path, "/pkg1", "warmboot.bin", &storage);
|
||||
emmcsn_path_impl(path, "/pkg1", "warmboot.bin", &emmc_storage);
|
||||
if (sd_save_to_file(warmboot, hdr_pk11->wb_size, path))
|
||||
goto out_free;
|
||||
gfx_puts("Warmboot dumped to warmboot.bin\n\n\n");
|
||||
}
|
||||
|
||||
// Dump package2.1.
|
||||
sdmmc_storage_set_mmc_partition(&storage, EMMC_GPP);
|
||||
sdmmc_storage_set_mmc_partition(&emmc_storage, EMMC_GPP);
|
||||
// Parse eMMC GPT.
|
||||
LIST_INIT(gpt);
|
||||
nx_emmc_gpt_parse(&gpt, &storage);
|
||||
nx_emmc_gpt_parse(&gpt, &emmc_storage);
|
||||
// Find package2 partition.
|
||||
emmc_part_t *pkg2_part = nx_emmc_part_find(&gpt, "BCPKG2-1-Normal-Main");
|
||||
if (!pkg2_part)
|
||||
@@ -191,14 +190,14 @@ void dump_packages12()
|
||||
|
||||
// Read in package2 header and get package2 real size.
|
||||
u8 *tmp = (u8 *)malloc(NX_EMMC_BLOCKSIZE);
|
||||
nx_emmc_part_read(&storage, pkg2_part, 0x4000 / NX_EMMC_BLOCKSIZE, 1, tmp);
|
||||
nx_emmc_part_read(&emmc_storage, pkg2_part, 0x4000 / NX_EMMC_BLOCKSIZE, 1, tmp);
|
||||
u32 *hdr_pkg2_raw = (u32 *)(tmp + 0x100);
|
||||
u32 pkg2_size = hdr_pkg2_raw[0] ^ hdr_pkg2_raw[2] ^ hdr_pkg2_raw[3];
|
||||
free(tmp);
|
||||
// Read in package2.
|
||||
u32 pkg2_size_aligned = ALIGN(pkg2_size, NX_EMMC_BLOCKSIZE);
|
||||
pkg2 = malloc(pkg2_size_aligned);
|
||||
nx_emmc_part_read(&storage, pkg2_part, 0x4000 / NX_EMMC_BLOCKSIZE,
|
||||
nx_emmc_part_read(&emmc_storage, pkg2_part, 0x4000 / NX_EMMC_BLOCKSIZE,
|
||||
pkg2_size_aligned / NX_EMMC_BLOCKSIZE, pkg2);
|
||||
// Decrypt package2 and parse KIP1 blobs in INI1 section.
|
||||
pkg2_hdr_t *pkg2_hdr = pkg2_decrypt(pkg2, kb);
|
||||
@@ -213,19 +212,19 @@ void dump_packages12()
|
||||
gfx_printf("%kINI1 size: %k0x%05X\n\n", 0xFFC7EA46, 0xFFCCCCCC, pkg2_hdr->sec_size[PKG2_SEC_INI1]);
|
||||
|
||||
// Dump pkg2.1.
|
||||
emmcsn_path_impl(path, "/pkg2", "pkg2_decr.bin", &storage);
|
||||
emmcsn_path_impl(path, "/pkg2", "pkg2_decr.bin", &emmc_storage);
|
||||
if (sd_save_to_file(pkg2, pkg2_hdr->sec_size[PKG2_SEC_KERNEL] + pkg2_hdr->sec_size[PKG2_SEC_INI1], path))
|
||||
goto out;
|
||||
gfx_puts("\npkg2 dumped to pkg2_decr.bin\n");
|
||||
|
||||
// Dump kernel.
|
||||
emmcsn_path_impl(path, "/pkg2", "kernel.bin", &storage);
|
||||
emmcsn_path_impl(path, "/pkg2", "kernel.bin", &emmc_storage);
|
||||
if (sd_save_to_file(pkg2_hdr->data, pkg2_hdr->sec_size[PKG2_SEC_KERNEL], path))
|
||||
goto out;
|
||||
gfx_puts("Kernel dumped to kernel.bin\n");
|
||||
|
||||
// Dump INI1.
|
||||
emmcsn_path_impl(path, "/pkg2", "ini1.bin", &storage);
|
||||
emmcsn_path_impl(path, "/pkg2", "ini1.bin", &emmc_storage);
|
||||
u32 ini1_off = pkg2_hdr->sec_size[PKG2_SEC_KERNEL];
|
||||
u32 ini1_size = pkg2_hdr->sec_size[PKG2_SEC_INI1];
|
||||
if (!ini1_size)
|
||||
@@ -256,7 +255,7 @@ out_free:
|
||||
free(warmboot);
|
||||
free(loader);
|
||||
free(pkg2);
|
||||
sdmmc_storage_end(&storage);
|
||||
sdmmc_storage_end(&emmc_storage);
|
||||
sd_end();
|
||||
|
||||
if (kb >= KB_FIRMWARE_VERSION_620)
|
||||
@@ -267,20 +266,17 @@ out_free:
|
||||
|
||||
void _toggle_autorcm(bool enable)
|
||||
{
|
||||
sdmmc_storage_t storage;
|
||||
sdmmc_t sdmmc;
|
||||
|
||||
gfx_clear_partial_grey(0x1B, 0, 1256);
|
||||
gfx_con_setpos(0, 0);
|
||||
|
||||
if (!sdmmc_storage_init_mmc(&storage, &sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400))
|
||||
if (!sdmmc_storage_init_mmc(&emmc_storage, &emmc_sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400))
|
||||
{
|
||||
EPRINTF("Failed to init eMMC.");
|
||||
goto out;
|
||||
}
|
||||
|
||||
u8 *tempbuf = (u8 *)malloc(0x200);
|
||||
sdmmc_storage_set_mmc_partition(&storage, EMMC_BOOT0);
|
||||
sdmmc_storage_set_mmc_partition(&emmc_storage, EMMC_BOOT0);
|
||||
|
||||
int i, sect = 0;
|
||||
u8 corr_mod0, mod1;
|
||||
@@ -292,7 +288,7 @@ void _toggle_autorcm(bool enable)
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
sect = (0x200 + (0x4000 * i)) / NX_EMMC_BLOCKSIZE;
|
||||
sdmmc_storage_read(&storage, sect, 1, tempbuf);
|
||||
sdmmc_storage_read(&emmc_storage, sect, 1, tempbuf);
|
||||
|
||||
// Check if 2nd byte of modulus is correct.
|
||||
if (tempbuf[0x11] != mod1)
|
||||
@@ -302,11 +298,11 @@ void _toggle_autorcm(bool enable)
|
||||
tempbuf[0x10] = 0;
|
||||
else
|
||||
tempbuf[0x10] = corr_mod0;
|
||||
sdmmc_storage_write(&storage, sect, 1, tempbuf);
|
||||
sdmmc_storage_write(&emmc_storage, sect, 1, tempbuf);
|
||||
}
|
||||
|
||||
free(tempbuf);
|
||||
sdmmc_storage_end(&storage);
|
||||
sdmmc_storage_end(&emmc_storage);
|
||||
|
||||
if (enable)
|
||||
gfx_printf("%kAutoRCM mode enabled!%k", 0xFFFFBA00, 0xFFCCCCCC);
|
||||
@@ -337,11 +333,9 @@ void menu_autorcm()
|
||||
}
|
||||
|
||||
// Do a simple check on the main BCT.
|
||||
sdmmc_storage_t storage;
|
||||
sdmmc_t sdmmc;
|
||||
bool disabled = true;
|
||||
|
||||
if (!sdmmc_storage_init_mmc(&storage, &sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400))
|
||||
if (!sdmmc_storage_init_mmc(&emmc_storage, &emmc_sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400))
|
||||
{
|
||||
EPRINTF("Failed to init eMMC.");
|
||||
btn_wait();
|
||||
@@ -354,8 +348,8 @@ void menu_autorcm()
|
||||
nx_emmc_get_autorcm_masks(&mod0, &mod1);
|
||||
|
||||
u8 *tempbuf = (u8 *)malloc(0x200);
|
||||
sdmmc_storage_set_mmc_partition(&storage, EMMC_BOOT0);
|
||||
sdmmc_storage_read(&storage, 0x200 / NX_EMMC_BLOCKSIZE, 1, tempbuf);
|
||||
sdmmc_storage_set_mmc_partition(&emmc_storage, EMMC_BOOT0);
|
||||
sdmmc_storage_read(&emmc_storage, 0x200 / NX_EMMC_BLOCKSIZE, 1, tempbuf);
|
||||
|
||||
// Check if 2nd byte of modulus is correct.
|
||||
if (tempbuf[0x11] == mod1)
|
||||
@@ -363,7 +357,7 @@ void menu_autorcm()
|
||||
disabled = false;
|
||||
|
||||
free(tempbuf);
|
||||
sdmmc_storage_end(&storage);
|
||||
sdmmc_storage_end(&emmc_storage);
|
||||
|
||||
// Create AutoRCM menu.
|
||||
ment_t *ments = (ment_t *)malloc(sizeof(ment_t) * 6);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2018-2020 CTCaer
|
||||
* Copyright (c) 2018-2021 CTCaer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
@@ -397,11 +397,13 @@ void gfx_printf(const char *fmt, ...)
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
void gfx_hexdump(u32 base, const u8 *buf, u32 len)
|
||||
void gfx_hexdump(u32 base, const void *buf, u32 len)
|
||||
{
|
||||
if (!gfx_con_init_done || gfx_con.mute)
|
||||
return;
|
||||
|
||||
u8 *buff = (u8 *)buf;
|
||||
|
||||
u8 prevFontSize = gfx_con.fntsz;
|
||||
gfx_con.fntsz = 8;
|
||||
for(u32 i = 0; i < len; i++)
|
||||
@@ -413,7 +415,7 @@ void gfx_hexdump(u32 base, const u8 *buf, u32 len)
|
||||
gfx_puts("| ");
|
||||
for(u32 j = 0; j < 0x10; j++)
|
||||
{
|
||||
u8 c = buf[i - 0x10 + j];
|
||||
u8 c = buff[i - 0x10 + j];
|
||||
if(c >= 32 && c <= 126)
|
||||
gfx_putc(c);
|
||||
else
|
||||
@@ -423,7 +425,7 @@ void gfx_hexdump(u32 base, const u8 *buf, u32 len)
|
||||
}
|
||||
gfx_printf("%08x: ", base + i);
|
||||
}
|
||||
gfx_printf("%02x ", buf[i]);
|
||||
gfx_printf("%02x ", buff[i]);
|
||||
if (i == len - 1)
|
||||
{
|
||||
int ln = len % 0x10 != 0;
|
||||
@@ -437,7 +439,7 @@ void gfx_hexdump(u32 base, const u8 *buf, u32 len)
|
||||
gfx_puts("| ");
|
||||
for(u32 j = 0; j < (ln ? k : k + 1); j++)
|
||||
{
|
||||
u8 c = buf[i - k + j];
|
||||
u8 c = buff[i - k + j];
|
||||
if(c >= 32 && c <= 126)
|
||||
gfx_putc(c);
|
||||
else
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2018-2020 CTCaer
|
||||
* Copyright (c) 2018-2021 CTCaer
|
||||
* Copyright (c) 2018 M4xw
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
@@ -63,7 +63,7 @@ void gfx_con_setpos(u32 x, u32 y);
|
||||
void gfx_putc(char c);
|
||||
void gfx_puts(char *s);
|
||||
void gfx_printf(const char *fmt, ...);
|
||||
void gfx_hexdump(u32 base, const u8 *buf, u32 len);
|
||||
void gfx_hexdump(u32 base, const void *buf, u32 len);
|
||||
|
||||
void gfx_set_pixel(u32 x, u32 y, u32 color);
|
||||
void gfx_line(int x0, int y0, int x1, int y1, u32 color);
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2018 st4rk
|
||||
* Copyright (c) 2018 Ced2911
|
||||
* Copyright (c) 2018-2020 CTCaer
|
||||
* Copyright (c) 2018-2021 CTCaer
|
||||
* Copyright (c) 2018 balika011
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
@@ -75,7 +75,29 @@ typedef struct _secmon_mailbox_t
|
||||
u32 out;
|
||||
} secmon_mailbox_t;
|
||||
|
||||
static const u8 keyblob_keyseeds[][0x10] = {
|
||||
typedef struct _tsec_keys_t
|
||||
{
|
||||
u8 tsec[SE_KEY_128_SIZE];
|
||||
u8 tsec_root[SE_KEY_128_SIZE];
|
||||
u8 tmp[SE_KEY_128_SIZE];
|
||||
} tsec_keys_t;
|
||||
|
||||
typedef struct _kb_keys_t
|
||||
{
|
||||
u8 master_keyseed[SE_KEY_128_SIZE];
|
||||
u8 random_data[0x70];
|
||||
u8 package1_key[SE_KEY_128_SIZE];
|
||||
} kb_keys_t;
|
||||
|
||||
typedef struct _kb_t
|
||||
{
|
||||
u8 cmac[SE_KEY_128_SIZE];
|
||||
u8 ctr[SE_AES_IV_SIZE];
|
||||
kb_keys_t keys;
|
||||
u8 padding[0x150];
|
||||
} kb_t;
|
||||
|
||||
static const u8 keyblob_keyseeds[][SE_KEY_128_SIZE] = {
|
||||
{ 0xDF, 0x20, 0x6F, 0x59, 0x44, 0x54, 0xEF, 0xDC, 0x70, 0x74, 0x48, 0x3B, 0x0D, 0xED, 0x9F, 0xD3 }, // 1.0.0.
|
||||
{ 0x0C, 0x25, 0x61, 0x5D, 0x68, 0x4C, 0xEB, 0x42, 0x1C, 0x23, 0x79, 0xEA, 0x82, 0x25, 0x12, 0xAC }, // 3.0.0.
|
||||
{ 0x33, 0x76, 0x85, 0xEE, 0x88, 0x4A, 0xAE, 0x0A, 0xC2, 0x8A, 0xFD, 0x7D, 0x63, 0xC0, 0x43, 0x3B }, // 3.0.1.
|
||||
@@ -84,19 +106,19 @@ static const u8 keyblob_keyseeds[][0x10] = {
|
||||
{ 0xD8, 0xCC, 0xE1, 0x26, 0x6A, 0x35, 0x3F, 0xCC, 0x20, 0xF3, 0x2D, 0x3B, 0x51, 0x7D, 0xE9, 0xC0 } // 6.0.0.
|
||||
};
|
||||
|
||||
static const u8 cmac_keyseed[0x10] =
|
||||
static const u8 cmac_keyseed[SE_KEY_128_SIZE] =
|
||||
{ 0x59, 0xC7, 0xFB, 0x6F, 0xBE, 0x9B, 0xBE, 0x87, 0x65, 0x6B, 0x15, 0xC0, 0x53, 0x73, 0x36, 0xA5 };
|
||||
|
||||
static const u8 master_keyseed_retail[0x10] =
|
||||
static const u8 master_keyseed_retail[SE_KEY_128_SIZE] =
|
||||
{ 0xD8, 0xA2, 0x41, 0x0A, 0xC6, 0xC5, 0x90, 0x01, 0xC6, 0x1D, 0x6A, 0x26, 0x7C, 0x51, 0x3F, 0x3C };
|
||||
|
||||
static const u8 master_keyseed_4xx_5xx_610[0x10] =
|
||||
static const u8 master_keyseed_4xx_5xx_610[SE_KEY_128_SIZE] =
|
||||
{ 0x2D, 0xC1, 0xF4, 0x8D, 0xF3, 0x5B, 0x69, 0x33, 0x42, 0x10, 0xAC, 0x65, 0xDA, 0x90, 0x46, 0x66 };
|
||||
|
||||
static const u8 master_keyseed_620[0x10] =
|
||||
static const u8 master_keyseed_620[SE_KEY_128_SIZE] =
|
||||
{ 0x37, 0x4B, 0x77, 0x29, 0x59, 0xB4, 0x04, 0x30, 0x81, 0xF6, 0xE5, 0x8C, 0x6D, 0x36, 0x17, 0x9A };
|
||||
|
||||
static const u8 master_kekseed_t210b01[][0x10] = {
|
||||
static const u8 master_kekseed_t210b01[][SE_KEY_128_SIZE] = {
|
||||
{ 0x77, 0x60, 0x5A, 0xD2, 0xEE, 0x6E, 0xF8, 0x3C, 0x3F, 0x72, 0xE2, 0x59, 0x9D, 0xAC, 0x5E, 0x56 }, // 6.0.0.
|
||||
{ 0x1E, 0x80, 0xB8, 0x17, 0x3E, 0xC0, 0x60, 0xAA, 0x11, 0xBE, 0x1A, 0x4A, 0xA6, 0x6F, 0xE4, 0xAE }, // 6.2.0.
|
||||
{ 0x94, 0x08, 0x67, 0xBD, 0x0A, 0x00, 0x38, 0x84, 0x11, 0xD3, 0x1A, 0xDB, 0xDD, 0x8D, 0xF1, 0x8A }, // 7.0.0.
|
||||
@@ -105,13 +127,13 @@ static const u8 master_kekseed_t210b01[][0x10] = {
|
||||
{ 0x0E, 0x44, 0x0C, 0xED, 0xB4, 0x36, 0xC0, 0x3F, 0xAA, 0x1D, 0xAE, 0xBF, 0x62, 0xB1, 0x09, 0x82 }, // 9.1.0.
|
||||
};
|
||||
|
||||
static const u8 console_keyseed[0x10] =
|
||||
static const u8 console_keyseed[SE_KEY_128_SIZE] =
|
||||
{ 0x4F, 0x02, 0x5F, 0x0E, 0xB6, 0x6D, 0x11, 0x0E, 0xDC, 0x32, 0x7D, 0x41, 0x86, 0xC2, 0xF4, 0x78 };
|
||||
|
||||
static const u8 console_keyseed_4xx_5xx[0x10] =
|
||||
static const u8 console_keyseed_4xx_5xx[SE_KEY_128_SIZE] =
|
||||
{ 0x0C, 0x91, 0x09, 0xDB, 0x93, 0x93, 0x07, 0x81, 0x07, 0x3C, 0xC4, 0x16, 0x22, 0x7C, 0x6C, 0x28 };
|
||||
|
||||
const u8 package2_keyseed[0x10] =
|
||||
const u8 package2_keyseed[SE_KEY_128_SIZE] =
|
||||
{ 0xFB, 0x8B, 0x6A, 0x9C, 0x79, 0x00, 0xC8, 0x49, 0xEF, 0xD2, 0x4D, 0x85, 0x4D, 0x30, 0xA0, 0xC7 };
|
||||
|
||||
static void _hos_crit_error(const char *text)
|
||||
@@ -124,30 +146,33 @@ static void _se_lock(bool lock_se)
|
||||
{
|
||||
if (lock_se)
|
||||
{
|
||||
// Disable aes key read.
|
||||
for (u32 i = 0; i < 16; i++)
|
||||
se_key_acc_ctrl(i, SE_KEY_TBL_DIS_KEYREAD_FLAG | SE_KEY_TBL_DIS_OIVREAD_FLAG | SE_KEY_TBL_DIS_UIVREAD_FLAG);
|
||||
|
||||
// Disable RSA key read.
|
||||
for (u32 i = 0; i < 2; i++)
|
||||
se_rsa_acc_ctrl(i, SE_RSA_KEY_TBL_DIS_KEYREAD_FLAG);
|
||||
SE(SE_TZRAM_SECURITY_0) = 0; // Make SE TZRAM secure only.
|
||||
SE(SE_KEY_TABLE_ACCESS_LOCK_OFFSET) = 0; // Make all key access regs secure only.
|
||||
SE(SE_RSA_KEYTABLE_ACCESS_LOCK_OFFSET) = 0; // Make all RSA access regs secure only.
|
||||
SE(SE_SECURITY_0) &= 0xFFFFFFFB; // Make access lock regs secure only.
|
||||
|
||||
SE(SE_TZRAM_SECURITY_REG) = 0; // Make SE TZRAM secure only.
|
||||
SE(SE_CRYPTO_SECURITY_PERKEY_REG) = 0; // Make all AES keys access secure only.
|
||||
SE(SE_RSA_SECURITY_PERKEY_REG) = 0; // Make all RSA keys access secure only.
|
||||
SE(SE_SE_SECURITY_REG) &= ~SE_PERKEY_SETTING; // Make access lock regs secure only.
|
||||
}
|
||||
|
||||
memset((void *)IPATCH_BASE, 0, 14 * sizeof(u32));
|
||||
SB(SB_CSR) = SB_CSR_PIROM_DISABLE;
|
||||
|
||||
// This is useful for documenting the bits in the SE config registers, so we can keep it around.
|
||||
/*gfx_printf("SE(SE_SECURITY_0) = %08X\n", SE(SE_SECURITY_0));
|
||||
/*gfx_printf("SE(SE_SE_SECURITY_REG) = %08X\n", SE(SE_SE_SECURITY_REG));
|
||||
gfx_printf("SE(0x4) = %08X\n", SE(0x4));
|
||||
gfx_printf("SE(SE_KEY_TABLE_ACCESS_LOCK_OFFSET) = %08X\n", SE(SE_KEY_TABLE_ACCESS_LOCK_OFFSET));
|
||||
gfx_printf("SE(SE_RSA_KEYTABLE_ACCESS_LOCK_OFFSET) = %08X\n", SE(SE_RSA_KEYTABLE_ACCESS_LOCK_OFFSET));
|
||||
gfx_printf("SE(SE_CRYPTO_SECURITY_PERKEY_REG) = %08X\n", SE(SE_CRYPTO_SECURITY_PERKEY_REG));
|
||||
gfx_printf("SE(SE_RSA_SECURITY_PERKEY_REG) = %08X\n", SE(SE_RSA_SECURITY_PERKEY_REG));
|
||||
for(u32 i = 0; i < 16; i++)
|
||||
gfx_printf("%02X ", SE(SE_KEY_TABLE_ACCESS_REG_OFFSET + i * 4) & 0xFF);
|
||||
gfx_printf("%02X ", SE(SE_CRYPTO_KEYTABLE_ACCESS_REG + i * 4) & 0xFF);
|
||||
gfx_putc('\n');
|
||||
for(u32 i = 0; i < 2; i++)
|
||||
gfx_printf("%02X ", SE(SE_RSA_KEYTABLE_ACCESS_REG_OFFSET + i * 4) & 0xFF);
|
||||
gfx_printf("%02X ", SE(SE_RSA_KEYTABLE_ACCESS_REG + i * 4) & 0xFF);
|
||||
gfx_putc('\n');
|
||||
gfx_hexdump(SE_BASE, (void *)SE_BASE, 0x400);*/
|
||||
}
|
||||
@@ -240,6 +265,8 @@ void hos_eks_save(u32 kb)
|
||||
|
||||
// If matching blob doesn't exist, create it.
|
||||
bool update_eks = key_idx ? (h_cfg.eks->enabled[key_idx] < kb) : !h_cfg.eks->enabled[0];
|
||||
// If old EKS version was found, update it.
|
||||
update_eks |= h_cfg.eks->lot0 != FUSE(FUSE_OPT_LOT_CODE_0);
|
||||
if (update_eks)
|
||||
{
|
||||
// Read EKS blob.
|
||||
@@ -256,8 +283,8 @@ void hos_eks_save(u32 kb)
|
||||
}
|
||||
|
||||
// Get keys.
|
||||
u8 *keys = (u8 *)calloc(0x1000, 1);
|
||||
se_get_aes_keys(keys + 0x800, keys, 0x10);
|
||||
u8 *keys = (u8 *)calloc(0x2000, 1);
|
||||
se_get_aes_keys(keys + 0x1000, keys, SE_KEY_128_SIZE);
|
||||
|
||||
// Set magic and personalized info.
|
||||
h_cfg.eks->magic = HOS_EKS_MAGIC;
|
||||
@@ -265,18 +292,18 @@ void hos_eks_save(u32 kb)
|
||||
h_cfg.eks->lot0 = FUSE(FUSE_OPT_LOT_CODE_0);
|
||||
|
||||
// Copy new keys.
|
||||
memcpy(h_cfg.eks->dkg, keys + 10 * 0x10, 0x10);
|
||||
memcpy(h_cfg.eks->dkk, keys + 15 * 0x10, 0x10);
|
||||
memcpy(h_cfg.eks->dkg, keys + 10 * SE_KEY_128_SIZE, SE_KEY_128_SIZE);
|
||||
memcpy(h_cfg.eks->dkk, keys + 15 * SE_KEY_128_SIZE, SE_KEY_128_SIZE);
|
||||
|
||||
if (!h_cfg.aes_slots_new)
|
||||
{
|
||||
memcpy(h_cfg.eks->keys[key_idx].mkk, keys + 12 * 0x10, 0x10);
|
||||
memcpy(h_cfg.eks->keys[key_idx].fdk, keys + 13 * 0x10, 0x10);
|
||||
memcpy(h_cfg.eks->keys[key_idx].mkk, keys + 12 * SE_KEY_128_SIZE, SE_KEY_128_SIZE);
|
||||
memcpy(h_cfg.eks->keys[key_idx].fdk, keys + 13 * SE_KEY_128_SIZE, SE_KEY_128_SIZE);
|
||||
}
|
||||
else // New sept slots.
|
||||
{
|
||||
memcpy(h_cfg.eks->keys[key_idx].mkk, keys + 13 * 0x10, 0x10);
|
||||
memcpy(h_cfg.eks->keys[key_idx].fdk, keys + 12 * 0x10, 0x10);
|
||||
memcpy(h_cfg.eks->keys[key_idx].mkk, keys + 13 * SE_KEY_128_SIZE, SE_KEY_128_SIZE);
|
||||
memcpy(h_cfg.eks->keys[key_idx].fdk, keys + 12 * SE_KEY_128_SIZE, SE_KEY_128_SIZE);
|
||||
}
|
||||
|
||||
// Encrypt EKS blob.
|
||||
@@ -288,7 +315,6 @@ void hos_eks_save(u32 kb)
|
||||
memcpy(mbr + 0x80, eks, sizeof(hos_eks_mbr_t));
|
||||
hos_eks_rw_try(mbr, true);
|
||||
|
||||
|
||||
free(eks);
|
||||
free(keys);
|
||||
out:
|
||||
@@ -354,10 +380,11 @@ int hos_keygen_t210b01(u32 kb)
|
||||
return 1;
|
||||
}
|
||||
|
||||
int hos_keygen(u8 *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt, launch_ctxt_t *hos_ctxt)
|
||||
int hos_keygen(void *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt, launch_ctxt_t *hos_ctxt)
|
||||
{
|
||||
u8 tmp[0x30];
|
||||
u32 retries = 0;
|
||||
tsec_keys_t tsec_keys;
|
||||
kb_t *kb_data = (kb_t *)keyblob;
|
||||
|
||||
if (kb > KB_FIRMWARE_VERSION_MAX)
|
||||
return 0;
|
||||
@@ -385,9 +412,9 @@ int hos_keygen(u8 *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt, launch_ctxt_t *hos_c
|
||||
// Get TSEC key.
|
||||
if (kb <= KB_FIRMWARE_VERSION_620)
|
||||
{
|
||||
while (tsec_query(tmp, kb, tsec_ctxt) < 0)
|
||||
while (tsec_query(&tsec_keys, kb, tsec_ctxt) < 0)
|
||||
{
|
||||
memset(tmp, 0x00, 0x20);
|
||||
memset(&tsec_keys, 0x00, 0x20);
|
||||
retries++;
|
||||
|
||||
// We rely on racing conditions, make sure we cover even the unluckiest cases.
|
||||
@@ -409,25 +436,25 @@ int hos_keygen(u8 *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt, launch_ctxt_t *hos_c
|
||||
if (h_cfg.eks && h_cfg.eks->enabled[key_idx] >= kb)
|
||||
{
|
||||
// Set Device keygen key to slot 10.
|
||||
se_aes_key_set(10, h_cfg.eks->dkg, 0x10);
|
||||
se_aes_key_set(10, h_cfg.eks->dkg, SE_KEY_128_SIZE);
|
||||
// Set Device key to slot 15.
|
||||
se_aes_key_set(15, h_cfg.eks->dkk, 0x10);
|
||||
se_aes_key_set(15, h_cfg.eks->dkk, SE_KEY_128_SIZE);
|
||||
|
||||
if (!h_cfg.aes_slots_new)
|
||||
{
|
||||
// Set Master key to slot 12.
|
||||
se_aes_key_set(12, h_cfg.eks->keys[key_idx].mkk, 0x10);
|
||||
se_aes_key_set(12, h_cfg.eks->keys[key_idx].mkk, SE_KEY_128_SIZE);
|
||||
// Set FW Device key key to slot 13.
|
||||
se_aes_key_set(13, h_cfg.eks->keys[key_idx].fdk, 0x10);
|
||||
se_aes_key_set(13, h_cfg.eks->keys[key_idx].fdk, SE_KEY_128_SIZE);
|
||||
// Lock FDK.
|
||||
se_key_acc_ctrl(13, SE_KEY_TBL_DIS_KEYREAD_FLAG | SE_KEY_TBL_DIS_OIVREAD_FLAG | SE_KEY_TBL_DIS_UIVREAD_FLAG);
|
||||
}
|
||||
else // New exosphere.
|
||||
{
|
||||
// Set Master key to slot 13.
|
||||
se_aes_key_set(13, h_cfg.eks->keys[key_idx].mkk, 0x10);
|
||||
se_aes_key_set(13, h_cfg.eks->keys[key_idx].mkk, SE_KEY_128_SIZE);
|
||||
// Set FW Device key key to slot 12.
|
||||
se_aes_key_set(12, h_cfg.eks->keys[key_idx].fdk, 0x10);
|
||||
se_aes_key_set(12, h_cfg.eks->keys[key_idx].fdk, SE_KEY_128_SIZE);
|
||||
// Lock FDK.
|
||||
se_key_acc_ctrl(12, SE_KEY_TBL_DIS_KEYREAD_FLAG | SE_KEY_TBL_DIS_OIVREAD_FLAG | SE_KEY_TBL_DIS_UIVREAD_FLAG);
|
||||
}
|
||||
@@ -439,14 +466,14 @@ int hos_keygen(u8 *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt, launch_ctxt_t *hos_c
|
||||
else if (kb == KB_FIRMWARE_VERSION_620)
|
||||
{
|
||||
// Set TSEC key.
|
||||
se_aes_key_set(12, tmp, 0x10);
|
||||
se_aes_key_set(12, tsec_keys.tsec, SE_KEY_128_SIZE);
|
||||
// Set TSEC root key.
|
||||
se_aes_key_set(13, tmp + 0x10, 0x10);
|
||||
se_aes_key_set(13, tsec_keys.tsec_root, SE_KEY_128_SIZE);
|
||||
|
||||
if (!(emu_cfg.enabled && !h_cfg.emummc_force_disable) && hos_ctxt->stock)
|
||||
{
|
||||
// Package2 key.
|
||||
se_aes_key_set(8, tmp + 0x10, 0x10);
|
||||
se_aes_key_set(8, tsec_keys.tsec_root, SE_KEY_128_SIZE);
|
||||
se_aes_unwrap_key(8, 8, master_keyseed_620);
|
||||
se_aes_unwrap_key(8, 8, master_keyseed_retail);
|
||||
se_aes_unwrap_key(8, 8, package2_keyseed);
|
||||
@@ -454,8 +481,8 @@ int hos_keygen(u8 *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt, launch_ctxt_t *hos_c
|
||||
else
|
||||
{
|
||||
// Decrypt keyblob and set keyslots
|
||||
se_aes_crypt_block_ecb(12, 0, tmp + 0x20, keyblob_keyseeds[0]);
|
||||
se_aes_unwrap_key(15, 14, tmp + 0x20);
|
||||
se_aes_crypt_block_ecb(12, 0, tsec_keys.tmp, keyblob_keyseeds[0]);
|
||||
se_aes_unwrap_key(15, 14, tsec_keys.tmp);
|
||||
se_aes_unwrap_key(10, 15, console_keyseed_4xx_5xx);
|
||||
se_aes_unwrap_key(15, 15, console_keyseed);
|
||||
|
||||
@@ -484,33 +511,36 @@ int hos_keygen(u8 *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt, launch_ctxt_t *hos_c
|
||||
se_key_acc_ctrl(14, SE_KEY_TBL_DIS_KEYREAD_FLAG | SE_KEY_TBL_DIS_OIVREAD_FLAG | SE_KEY_TBL_DIS_UIVREAD_FLAG);
|
||||
|
||||
// Set TSEC key.
|
||||
se_aes_key_set(13, tmp, 0x10);
|
||||
se_aes_key_set(13, tsec_keys.tsec, SE_KEY_128_SIZE);
|
||||
|
||||
// Derive keyblob keys from TSEC+SBK.
|
||||
se_aes_crypt_block_ecb(13, 0, tmp, keyblob_keyseeds[0]);
|
||||
se_aes_unwrap_key(15, 14, tmp);
|
||||
se_aes_crypt_block_ecb(13, 0, tmp, keyblob_keyseeds[kb]);
|
||||
se_aes_unwrap_key(13, 14, tmp);
|
||||
se_aes_crypt_block_ecb(13, 0, tsec_keys.tsec, keyblob_keyseeds[0]);
|
||||
se_aes_unwrap_key(15, 14, tsec_keys.tsec);
|
||||
se_aes_crypt_block_ecb(13, 0, tsec_keys.tsec, keyblob_keyseeds[kb]);
|
||||
se_aes_unwrap_key(13, 14, tsec_keys.tsec);
|
||||
|
||||
// Clear SBK.
|
||||
se_aes_key_clear(14);
|
||||
|
||||
//TODO: verify keyblob CMAC.
|
||||
//se_aes_unwrap_key(11, 13, cmac_keyseed);
|
||||
//se_aes_cmac(tmp, 0x10, 11, keyblob + 0x10, 0xA0);
|
||||
//if (!memcmp(keyblob, tmp, 0x10))
|
||||
// return 0;
|
||||
/*
|
||||
// Verify keyblob CMAC.
|
||||
u8 cmac[SE_KEY_128_SIZE];
|
||||
se_aes_unwrap_key(11, 13, cmac_keyseed);
|
||||
se_aes_cmac(cmac, SE_KEY_128_SIZE, 11, (void *)kb_data->ctr, sizeof(kb_data->ctr) + sizeof(kb_data->keys));
|
||||
if (!memcmp(kb_data->cmac, cmac, SE_KEY_128_SIZE))
|
||||
return 0;
|
||||
*/
|
||||
|
||||
se_aes_crypt_block_ecb(13, 0, tmp, cmac_keyseed);
|
||||
se_aes_crypt_block_ecb(13, 0, tsec_keys.tsec, cmac_keyseed);
|
||||
se_aes_unwrap_key(11, 13, cmac_keyseed);
|
||||
|
||||
// Decrypt keyblob and set keyslots.
|
||||
se_aes_crypt_ctr(13, keyblob + 0x20, 0x90, keyblob + 0x20, 0x90, keyblob + 0x10);
|
||||
se_aes_key_set(11, keyblob + 0x20 + 0x80, 0x10); // Package1 key.
|
||||
se_aes_key_set(12, keyblob + 0x20, 0x10);
|
||||
se_aes_key_set(13, keyblob + 0x20, 0x10);
|
||||
se_aes_crypt_ctr(13, &kb_data->keys, sizeof(kb_data->keys), &kb_data->keys, sizeof(kb_data->keys), kb_data->ctr);
|
||||
se_aes_key_set(11, kb_data->keys.package1_key, SE_KEY_128_SIZE);
|
||||
se_aes_key_set(12, kb_data->keys.master_keyseed, SE_KEY_128_SIZE);
|
||||
se_aes_key_set(13, kb_data->keys.master_keyseed, SE_KEY_128_SIZE);
|
||||
|
||||
se_aes_crypt_block_ecb(12, 0, tmp, master_keyseed_retail);
|
||||
se_aes_crypt_block_ecb(12, 0, tsec_keys.tsec, master_keyseed_retail);
|
||||
|
||||
if (!h_cfg.aes_slots_new)
|
||||
{
|
||||
@@ -566,8 +596,8 @@ static int _read_emmc_pkg1(launch_ctxt_t *ctxt)
|
||||
|
||||
try_load:
|
||||
// Read package1.
|
||||
emummc_storage_set_mmc_partition(&emmc_storage, EMMC_BOOT0);
|
||||
emummc_storage_read(&emmc_storage, bootloader_offset / NX_EMMC_BLOCKSIZE, BOOTLOADER_SIZE / NX_EMMC_BLOCKSIZE, ctxt->pkg1);
|
||||
emummc_storage_set_mmc_partition(EMMC_BOOT0);
|
||||
emummc_storage_read(bootloader_offset / NX_EMMC_BLOCKSIZE, BOOTLOADER_SIZE / NX_EMMC_BLOCKSIZE, ctxt->pkg1);
|
||||
|
||||
ctxt->pkg1_id = pkg1_identify(ctxt->pkg1 + pk1_offset);
|
||||
if (!ctxt->pkg1_id)
|
||||
@@ -590,7 +620,7 @@ try_load:
|
||||
|
||||
// Read the correct keyblob.
|
||||
ctxt->keyblob = (u8 *)calloc(NX_EMMC_BLOCKSIZE, 1);
|
||||
emummc_storage_read(&emmc_storage, HOS_KEYBLOBS_OFFSET / NX_EMMC_BLOCKSIZE + ctxt->pkg1_id->kb, 1, ctxt->keyblob);
|
||||
emummc_storage_read(HOS_KEYBLOBS_OFFSET / NX_EMMC_BLOCKSIZE + ctxt->pkg1_id->kb, 1, ctxt->keyblob);
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -599,7 +629,7 @@ static u8 *_read_emmc_pkg2(launch_ctxt_t *ctxt)
|
||||
{
|
||||
u8 *bctBuf = NULL;
|
||||
|
||||
emummc_storage_set_mmc_partition(&emmc_storage, EMMC_GPP);
|
||||
emummc_storage_set_mmc_partition(EMMC_GPP);
|
||||
|
||||
// Parse eMMC GPT.
|
||||
LIST_INIT(gpt);
|
||||
@@ -710,17 +740,21 @@ int hos_launch(ini_sec_t *cfg)
|
||||
gfx_puts("Initializing...\n\n");
|
||||
|
||||
// Initialize eMMC/emuMMC.
|
||||
int res = emummc_storage_init_mmc(&emmc_storage, &emmc_sdmmc);
|
||||
int res = emummc_storage_init_mmc();
|
||||
if (res)
|
||||
{
|
||||
if (res == 2)
|
||||
_hos_crit_error("Failed to init eMMC");
|
||||
_hos_crit_error("Failed to init eMMC.");
|
||||
else
|
||||
_hos_crit_error("Failed to init emuMMC");
|
||||
_hos_crit_error("Failed to init emuMMC.");
|
||||
|
||||
goto error;
|
||||
}
|
||||
|
||||
// Check if SD Card is GPT.
|
||||
if (sd_is_gpt())
|
||||
_hos_crit_error("SD has GPT only!");
|
||||
|
||||
// Read package1 and the correct keyblob.
|
||||
if (!_read_emmc_pkg1(&ctxt))
|
||||
goto error;
|
||||
@@ -843,7 +877,17 @@ int hos_launch(ini_sec_t *cfg)
|
||||
}
|
||||
|
||||
// Configure and manage Warmboot binary.
|
||||
pkg1_warmboot_config(&ctxt, warmboot_base);
|
||||
if (!pkg1_warmboot_config(&ctxt, warmboot_base))
|
||||
{
|
||||
// Can only happen on T210B01.
|
||||
_hos_crit_error("Failed to match warmboot with fuses!\nIf you continue, sleep wont work!");
|
||||
|
||||
gfx_puts("\nPress POWER to continue.\nPress VOL to go to the menu.\n");
|
||||
display_backlight_brightness(h_cfg.backlight, 1000);
|
||||
|
||||
if (!(btn_wait() & BTN_POWER))
|
||||
goto error;
|
||||
}
|
||||
|
||||
// Replace 'warmboot.bin' if requested.
|
||||
if (ctxt.warmboot)
|
||||
@@ -1012,16 +1056,16 @@ int hos_launch(ini_sec_t *cfg)
|
||||
case KB_FIRMWARE_VERSION_100_200:
|
||||
case KB_FIRMWARE_VERSION_300:
|
||||
case KB_FIRMWARE_VERSION_301:
|
||||
se_key_acc_ctrl(12, SE_KEY_TBL_DIS_KEY_ACCESS_FLAG | SE_KEY_TBL_DIS_KEY_LOCK_FLAG);
|
||||
se_key_acc_ctrl(13, SE_KEY_TBL_DIS_KEY_ACCESS_FLAG | SE_KEY_TBL_DIS_KEY_LOCK_FLAG);
|
||||
se_key_acc_ctrl(12, SE_KEY_TBL_DIS_KEY_ACCESS_FLAG | SE_KEY_LOCK_FLAG);
|
||||
se_key_acc_ctrl(13, SE_KEY_TBL_DIS_KEY_ACCESS_FLAG | SE_KEY_LOCK_FLAG);
|
||||
bootStateDramPkg2 = 2;
|
||||
bootStatePkg2Continue = 3;
|
||||
break;
|
||||
case KB_FIRMWARE_VERSION_400:
|
||||
case KB_FIRMWARE_VERSION_500:
|
||||
case KB_FIRMWARE_VERSION_600:
|
||||
se_key_acc_ctrl(12, SE_KEY_TBL_DIS_KEY_ACCESS_FLAG | SE_KEY_TBL_DIS_KEY_LOCK_FLAG);
|
||||
se_key_acc_ctrl(15, SE_KEY_TBL_DIS_KEY_ACCESS_FLAG | SE_KEY_TBL_DIS_KEY_LOCK_FLAG);
|
||||
se_key_acc_ctrl(12, SE_KEY_TBL_DIS_KEY_ACCESS_FLAG | SE_KEY_LOCK_FLAG);
|
||||
se_key_acc_ctrl(15, SE_KEY_TBL_DIS_KEY_ACCESS_FLAG | SE_KEY_LOCK_FLAG);
|
||||
default:
|
||||
bootStateDramPkg2 = 2;
|
||||
bootStatePkg2Continue = 4;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2018-2020 CTCaer
|
||||
* Copyright (c) 2018-2021 CTCaer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
@@ -20,6 +20,7 @@
|
||||
|
||||
#include "pkg1.h"
|
||||
#include "pkg2.h"
|
||||
#include <sec/se_t210.h>
|
||||
#include <utils/types.h>
|
||||
#include <utils/ini.h>
|
||||
#include <sec/tsec.h>
|
||||
@@ -56,14 +57,14 @@ typedef struct _exo_ctxt_t
|
||||
|
||||
typedef struct _hos_eks_keys_t
|
||||
{
|
||||
u8 mkk[0x10];
|
||||
u8 fdk[0x10];
|
||||
u8 mkk[SE_KEY_128_SIZE];
|
||||
u8 fdk[SE_KEY_128_SIZE];
|
||||
} hos_eks_keys_t;
|
||||
|
||||
typedef struct _hos_eks_bis_keys_t
|
||||
{
|
||||
u8 crypt[0x10];
|
||||
u8 tweak[0x10];
|
||||
u8 crypt[SE_KEY_128_SIZE];
|
||||
u8 tweak[SE_KEY_128_SIZE];
|
||||
} hos_eks_bis_keys_t;
|
||||
|
||||
typedef struct _hos_eks_mbr_t
|
||||
@@ -73,8 +74,8 @@ typedef struct _hos_eks_mbr_t
|
||||
u8 enabled_bis;
|
||||
u8 rsvd[2];
|
||||
u32 lot0;
|
||||
u8 dkg[0x10];
|
||||
u8 dkk[0x10];
|
||||
u8 dkg[SE_KEY_128_SIZE];
|
||||
u8 dkk[SE_KEY_128_SIZE];
|
||||
hos_eks_keys_t keys[5];
|
||||
hos_eks_bis_keys_t bis_keys[3];
|
||||
} hos_eks_mbr_t;
|
||||
@@ -129,6 +130,6 @@ void hos_eks_get();
|
||||
void hos_eks_save(u32 kb);
|
||||
void hos_eks_clear(u32 kb);
|
||||
int hos_launch(ini_sec_t *cfg);
|
||||
int hos_keygen(u8 *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt, launch_ctxt_t *hos_ctxt);
|
||||
int hos_keygen(void *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt, launch_ctxt_t *hos_ctxt);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2018 st4rk
|
||||
* Copyright (c) 2018-2020 CTCaer
|
||||
* Copyright (c) 2018-2021 CTCaer
|
||||
* Copyright (c) 2018 balika011
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
@@ -331,10 +331,11 @@ static void _warmboot_filename(char *out, u32 fuses)
|
||||
strcat(out, ".bin");
|
||||
}
|
||||
|
||||
void pkg1_warmboot_config(void *hos_ctxt, u32 warmboot_base)
|
||||
int pkg1_warmboot_config(void *hos_ctxt, u32 warmboot_base)
|
||||
{
|
||||
launch_ctxt_t *ctxt = (launch_ctxt_t *)hos_ctxt;
|
||||
u32 kb = ctxt->pkg1_id->kb;
|
||||
int res = 1;
|
||||
|
||||
// Set warmboot address in PMC if required.
|
||||
if (kb <= KB_FIRMWARE_VERSION_301)
|
||||
@@ -347,7 +348,7 @@ void pkg1_warmboot_config(void *hos_ctxt, u32 warmboot_base)
|
||||
u32 fuses_fw = ctxt->pkg1_id->fuses;
|
||||
u8 burnt_fuses = fuse_count_burnt(fuse_read_odm(7));
|
||||
|
||||
// Save current warmboot in storage cache and check if another one is needed.
|
||||
// Save current warmboot in storage cache (MWS) and check if another one is needed.
|
||||
if (!ctxt->warmboot)
|
||||
{
|
||||
char path[128];
|
||||
@@ -357,7 +358,7 @@ void pkg1_warmboot_config(void *hos_ctxt, u32 warmboot_base)
|
||||
if (f_stat(path, NULL))
|
||||
sd_save_to_file((void *)warmboot_base, ctxt->warmboot_size, path);
|
||||
|
||||
// Load warmboot fw from storage if not matched.
|
||||
// Load warmboot fw from storage (MWS) if not matched.
|
||||
if (burnt_fuses > fuses_fw)
|
||||
{
|
||||
u32 tmp_fuses = burnt_fuses;
|
||||
@@ -374,6 +375,10 @@ void pkg1_warmboot_config(void *hos_ctxt, u32 warmboot_base)
|
||||
break;
|
||||
tmp_fuses++;
|
||||
}
|
||||
|
||||
// Check if proper warmboot firmware was found.
|
||||
if (!ctxt->warmboot)
|
||||
res = 0;
|
||||
}
|
||||
else // Replace burnt fuses with higher count.
|
||||
burnt_fuses = fuses_fw;
|
||||
@@ -406,4 +411,6 @@ void pkg1_warmboot_config(void *hos_ctxt, u32 warmboot_base)
|
||||
else if (kb == KB_FIRMWARE_VERSION_301)
|
||||
PMC(APBDEV_PMC_SECURE_SCRATCH32) = 0x104; // Warmboot 3.0.1/.2 PA address id.
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -81,6 +81,6 @@ int pkg1_decrypt(const pkg1_id_t *id, u8 *pkg1);
|
||||
const u8 *pkg1_unpack(void *wm_dst, u32 *wb_sz, void *sm_dst, void *ldr_dst, const pkg1_id_t *id, u8 *pkg1);
|
||||
void pkg1_secmon_patch(void *hos_ctxt, u32 secmon_base, bool t210b01);
|
||||
void pkg1_warmboot_patch(void *hos_ctxt);
|
||||
void pkg1_warmboot_config(void *hos_ctxt, u32 warmboot_base);
|
||||
int pkg1_warmboot_config(void *hos_ctxt, u32 warmboot_base);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2018-2020 CTCaer
|
||||
* Copyright (c) 2018-2021 CTCaer
|
||||
* Copyright (c) 2018 Atmosphère-NX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
@@ -27,6 +27,7 @@
|
||||
#include <libs/fatfs/ff.h>
|
||||
#include <mem/heap.h>
|
||||
#include <sec/se.h>
|
||||
#include <sec/se_t210.h>
|
||||
#include "../storage/emummc.h"
|
||||
#include <storage/nx_sd.h>
|
||||
#include <utils/aarch64_util.h>
|
||||
@@ -1335,7 +1336,7 @@ const char* pkg2_patch_kips(link_t *info, char* patchNames)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const u8 mkey_vector_8xx[][0x10] =
|
||||
static const u8 mkey_vector_8xx[][SE_KEY_128_SIZE] =
|
||||
{
|
||||
// Master key 8 encrypted with 9. (8.1.0 with 9.0.0)
|
||||
{ 0x4D, 0xD9, 0x98, 0x42, 0x45, 0x0D, 0xB1, 0x3C, 0x52, 0x0C, 0x9A, 0x44, 0xBB, 0xAD, 0xAF, 0x80 },
|
||||
@@ -1346,10 +1347,10 @@ static const u8 mkey_vector_8xx[][0x10] =
|
||||
static bool _pkg2_key_unwrap_validate(pkg2_hdr_t *tmp_test, pkg2_hdr_t *hdr, u8 src_slot, u8 *mkey, const u8 *key_seed)
|
||||
{
|
||||
// Decrypt older encrypted mkey.
|
||||
se_aes_crypt_ecb(src_slot, 0, mkey, 0x10, key_seed, 0x10);
|
||||
se_aes_crypt_ecb(src_slot, 0, mkey, SE_KEY_128_SIZE, key_seed, SE_KEY_128_SIZE);
|
||||
// Set and unwrap pkg2 key.
|
||||
se_aes_key_clear(9);
|
||||
se_aes_key_set(9, mkey, 0x10);
|
||||
se_aes_key_set(9, mkey, SE_KEY_128_SIZE);
|
||||
se_aes_unwrap_key(9, 9, package2_keyseed);
|
||||
|
||||
// Decrypt header.
|
||||
@@ -1383,9 +1384,9 @@ pkg2_hdr_t *pkg2_decrypt(void *data, u8 kb)
|
||||
// Decrypt older pkg2 via new mkeys.
|
||||
if ((kb >= KB_FIRMWARE_VERSION_810) && (kb < KB_FIRMWARE_VERSION_MAX))
|
||||
{
|
||||
u8 tmp_mkey[0x10];
|
||||
u8 tmp_mkey[SE_KEY_128_SIZE];
|
||||
u8 decr_slot = !h_cfg.t210b01 ? (!h_cfg.aes_slots_new ? 12 : 13) : 7; // Sept mkey or T210B01 mkey.
|
||||
u8 mkey_seeds_cnt = sizeof(mkey_vector_8xx) / 0x10;
|
||||
u8 mkey_seeds_cnt = sizeof(mkey_vector_8xx) / SE_KEY_128_SIZE;
|
||||
u8 mkey_seeds_idx = mkey_seeds_cnt; // Real index + 1.
|
||||
u8 mkey_seeds_min_idx = mkey_seeds_cnt - (KB_FIRMWARE_VERSION_MAX - kb);
|
||||
|
||||
@@ -1405,7 +1406,7 @@ pkg2_hdr_t *pkg2_decrypt(void *data, u8 kb)
|
||||
// Set current mkey in order to decrypt a lower mkey.
|
||||
mkey_seeds_idx--;
|
||||
se_aes_key_clear(9);
|
||||
se_aes_key_set(9, tmp_mkey, 0x10);
|
||||
se_aes_key_set(9, tmp_mkey, SE_KEY_128_SIZE);
|
||||
|
||||
decr_slot = 9; // Temp key.
|
||||
|
||||
@@ -1439,7 +1440,7 @@ DPRINTF("sec %d has size %08X\n", i, hdr->sec_size[i]);
|
||||
if (!hdr->sec_size[i])
|
||||
continue;
|
||||
|
||||
se_aes_crypt_ctr(pkg2_keyslot, pdata, hdr->sec_size[i], pdata, hdr->sec_size[i], &hdr->sec_ctr[i * 0x10]);
|
||||
se_aes_crypt_ctr(pkg2_keyslot, pdata, hdr->sec_size[i], pdata, hdr->sec_size[i], &hdr->sec_ctr[i * SE_AES_IV_SIZE]);
|
||||
//gfx_hexdump((u32)pdata, pdata, 0x100);
|
||||
|
||||
pdata += hdr->sec_size[i];
|
||||
@@ -1469,7 +1470,7 @@ DPRINTF("adding kip1 '%s' @ %08X (%08X)\n", ki->kip1->name, (u32)ki->kip1, ki->s
|
||||
{
|
||||
hdr->sec_size[PKG2_SEC_INI1] = ini1_size;
|
||||
hdr->sec_off[PKG2_SEC_INI1] = 0x14080000;
|
||||
se_aes_crypt_ctr(8, ini1, ini1_size, ini1, ini1_size, &hdr->sec_ctr[PKG2_SEC_INI1 * 0x10]);
|
||||
se_aes_crypt_ctr(8, ini1, ini1_size, ini1, ini1_size, &hdr->sec_ctr[PKG2_SEC_INI1 * SE_AES_IV_SIZE]);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1526,7 +1527,7 @@ DPRINTF("%s @ %08X (%08X)\n", is_meso ? "Mesosphere": "kernel",(u32)ctxt->kernel
|
||||
hdr->sec_off[PKG2_SEC_KERNEL] = 0x60000;
|
||||
}
|
||||
hdr->sec_size[PKG2_SEC_KERNEL] = kernel_size;
|
||||
se_aes_crypt_ctr(pkg2_keyslot, pdst, kernel_size, pdst, kernel_size, &hdr->sec_ctr[PKG2_SEC_KERNEL * 0x10]);
|
||||
se_aes_crypt_ctr(pkg2_keyslot, pdst, kernel_size, pdst, kernel_size, &hdr->sec_ctr[PKG2_SEC_KERNEL * SE_AES_IV_SIZE]);
|
||||
pdst += kernel_size;
|
||||
DPRINTF("kernel encrypted\n");
|
||||
|
||||
@@ -1549,7 +1550,7 @@ DPRINTF("INI1 encrypted\n");
|
||||
*(u32 *)hdr->ctr = 0x100 + sizeof(pkg2_hdr_t) + kernel_size + ini1_size;
|
||||
hdr->ctr[4] = key_ver;
|
||||
se_aes_crypt_ctr(pkg2_keyslot, hdr, sizeof(pkg2_hdr_t), hdr, sizeof(pkg2_hdr_t), hdr);
|
||||
memset(hdr->ctr, 0 , 0x10);
|
||||
memset(hdr->ctr, 0 , SE_AES_IV_SIZE);
|
||||
*(u32 *)hdr->ctr = 0x100 + sizeof(pkg2_hdr_t) + kernel_size + ini1_size;
|
||||
hdr->ctr[4] = key_ver;
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019 CTCaer
|
||||
* Copyright (c) 2019-2021 CTCaer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
@@ -33,6 +33,7 @@
|
||||
#include <storage/sdmmc.h>
|
||||
#include <utils/btn.h>
|
||||
#include <utils/types.h>
|
||||
#include <utils/util.h>
|
||||
|
||||
#include <gfx_utils.h>
|
||||
|
||||
@@ -55,6 +56,7 @@ u8 warmboot_reboot[] = {
|
||||
};
|
||||
|
||||
#define SEPT_PRI_ADDR 0x4003F000
|
||||
#define SEPT_PRI_ENTRY 0x40010340
|
||||
|
||||
#define SEPT_PK1T_ADDR 0xC0400000
|
||||
#define SEPT_TCSZ_ADDR (SEPT_PK1T_ADDR - 0x4)
|
||||
@@ -93,23 +95,21 @@ void check_sept(ini_sec_t *cfg_sec)
|
||||
|
||||
u8 *pkg1 = (u8 *)calloc(1, 0x40000);
|
||||
|
||||
sdmmc_storage_t storage;
|
||||
sdmmc_t sdmmc;
|
||||
int res = emummc_storage_init_mmc(&storage, &sdmmc);
|
||||
int res = emummc_storage_init_mmc();
|
||||
if (res)
|
||||
{
|
||||
if (res == 2)
|
||||
EPRINTF("Failed to init eMMC");
|
||||
EPRINTF("Failed to init eMMC.");
|
||||
else
|
||||
EPRINTF("Failed to init emuMMC");
|
||||
EPRINTF("Failed to init emuMMC.");
|
||||
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
emummc_storage_set_mmc_partition(&storage, EMMC_BOOT0);
|
||||
emummc_storage_set_mmc_partition(EMMC_BOOT0);
|
||||
|
||||
// Read package1.
|
||||
emummc_storage_read(&storage, 0x100000 / NX_EMMC_BLOCKSIZE, 0x40000 / NX_EMMC_BLOCKSIZE, pkg1);
|
||||
emummc_storage_read(0x100000 / NX_EMMC_BLOCKSIZE, 0x40000 / NX_EMMC_BLOCKSIZE, pkg1);
|
||||
const pkg1_id_t *pkg1_id = pkg1_identify(pkg1);
|
||||
if (!pkg1_id)
|
||||
{
|
||||
@@ -129,13 +129,28 @@ void check_sept(ini_sec_t *cfg_sec)
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
sdmmc_storage_end(&storage);
|
||||
u8 *bct_bldr = (u8 *)calloc(1, 512);
|
||||
sdmmc_storage_read(&emmc_storage, 0x2200 / NX_EMMC_BLOCKSIZE, 1, bct_bldr);
|
||||
u32 bootloader_entrypoint = *(u32 *)&bct_bldr[0x144];
|
||||
free(bct_bldr);
|
||||
if (bootloader_entrypoint > SEPT_PRI_ENTRY)
|
||||
{
|
||||
gfx_con.mute = false;
|
||||
EPRINTF("Failed to run sept\n""Main BCT is improper!\nRun sept with proper BCT at least once\nto cache keys.");
|
||||
gfx_printf("\nPress any key...\n");
|
||||
display_backlight_brightness(h_cfg.backlight, 1000);
|
||||
msleep(500);
|
||||
btn_wait();
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
sdmmc_storage_end(&emmc_storage);
|
||||
reboot_to_sept((u8 *)pkg1 + pkg1_id->tsec_off, pkg1_id->kb, cfg_sec);
|
||||
}
|
||||
|
||||
out_free:
|
||||
free(pkg1);
|
||||
sdmmc_storage_end(&storage);
|
||||
sdmmc_storage_end(&emmc_storage);
|
||||
}
|
||||
|
||||
int reboot_to_sept(const u8 *tsec_fw, u32 kb, ini_sec_t *cfg_sec)
|
||||
|
||||
@@ -20,6 +20,6 @@
|
||||
#include <utils/types.h>
|
||||
|
||||
void check_sept(ini_sec_t *cfg_sec);
|
||||
int reboot_to_sept(const u8 *tsec_fw, u32 kb, ini_sec_t *cfg_sec);
|
||||
int reboot_to_sept(const u8 *tsec_fw, u32 kb, ini_sec_t *cfg_sec);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -41,16 +41,25 @@
|
||||
#define FF_USE_MKFS 0
|
||||
/* This option switches f_mkfs() function. (0:Disable or 1:Enable) */
|
||||
|
||||
#if FF_USE_MKFS
|
||||
#define FF_MKFS_LABEL "SWITCH SD "
|
||||
#endif
|
||||
/* This sets FAT/FAT32 label. Exactly 11 characters, all caps. */
|
||||
|
||||
|
||||
#define FF_USE_FASTSEEK 0
|
||||
/* This option switches fast seek function. (0:Disable or 1:Enable) */
|
||||
|
||||
#define FF_FASTFS 0
|
||||
|
||||
#if FF_FASTFS
|
||||
#undef FF_USE_FASTSEEK
|
||||
#define FF_USE_FASTSEEK 1
|
||||
#endif
|
||||
/* This option switches fast access to chained clusters. (0:Disable or 1:Enable) */
|
||||
|
||||
|
||||
#define FF_SIMPLE_GPT 1
|
||||
/* This option switches support for the first GPT partition. (0:Disable or 1:Enable) */
|
||||
|
||||
|
||||
#define FF_USE_EXPAND 0
|
||||
@@ -185,6 +194,7 @@
|
||||
/ not defined, a user defined volume string table needs to be defined as:
|
||||
/
|
||||
/ const char* VolumeStr[FF_VOLUMES] = {"ram","flash","sd","usb",...
|
||||
/ Order is important. Any change to order, must also be reflected to diskio drive enum.
|
||||
*/
|
||||
|
||||
|
||||
@@ -246,7 +256,7 @@
|
||||
#define FF_FS_NORTC 1
|
||||
#define FF_NORTC_MON 1
|
||||
#define FF_NORTC_MDAY 1
|
||||
#define FF_NORTC_YEAR 2020
|
||||
#define FF_NORTC_YEAR 2021
|
||||
/* The option FF_FS_NORTC switches timestamp function. If the system does not have
|
||||
/ any RTC function or valid timestamp is not needed, set FF_FS_NORTC = 1 to disable
|
||||
/ the timestamp function. Every object modified by FatFs will have a fixed timestamp
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
*
|
||||
* Copyright (c) 2018-2020 CTCaer
|
||||
* Copyright (c) 2018-2021 CTCaer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
@@ -73,8 +73,6 @@ volatile nyx_storage_t *nyx_str = (nyx_storage_t *)NYX_STORAGE_ADDR;
|
||||
|
||||
void emmcsn_path_impl(char *path, char *sub_dir, char *filename, sdmmc_storage_t *storage)
|
||||
{
|
||||
sdmmc_storage_t storage2;
|
||||
sdmmc_t sdmmc;
|
||||
char emmcSN[9];
|
||||
bool init_done = false;
|
||||
|
||||
@@ -83,12 +81,12 @@ void emmcsn_path_impl(char *path, char *sub_dir, char *filename, sdmmc_storage_t
|
||||
|
||||
if (!storage)
|
||||
{
|
||||
if (!sdmmc_storage_init_mmc(&storage2, &sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400))
|
||||
if (!sdmmc_storage_init_mmc(&emmc_storage, &emmc_sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400))
|
||||
memcpy(emmcSN, "00000000", 9);
|
||||
else
|
||||
{
|
||||
init_done = true;
|
||||
itoa(storage2.cid.serial, emmcSN, 16);
|
||||
itoa(emmc_storage.cid.serial, emmcSN, 16);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -107,7 +105,7 @@ void emmcsn_path_impl(char *path, char *sub_dir, char *filename, sdmmc_storage_t
|
||||
memcpy(path + strlen(path), filename, filename_len + 1);
|
||||
|
||||
if (init_done)
|
||||
sdmmc_storage_end(&storage2);
|
||||
sdmmc_storage_end(&emmc_storage);
|
||||
}
|
||||
|
||||
void check_power_off_from_hos()
|
||||
@@ -644,12 +642,8 @@ void launch_firmware()
|
||||
|
||||
if (!cfg_sec)
|
||||
{
|
||||
gfx_puts("\nUsing default launch configuration...\n");
|
||||
gfx_puts("\nPress POWER to Continue.\nPress VOL to go to the menu.");
|
||||
|
||||
u32 btn = btn_wait();
|
||||
if (!(btn & BTN_POWER))
|
||||
goto out;
|
||||
gfx_printf("\nPress any key...\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (payload_path)
|
||||
@@ -720,15 +714,11 @@ void nyx_load_run()
|
||||
nyx_str->cfg = 0;
|
||||
if (b_cfg.extra_cfg)
|
||||
{
|
||||
if (b_cfg.extra_cfg & EXTRA_CFG_NYX_DUMP)
|
||||
if (b_cfg.extra_cfg & EXTRA_CFG_NYX_SEPT)
|
||||
{
|
||||
b_cfg.extra_cfg &= ~(EXTRA_CFG_NYX_DUMP);
|
||||
nyx_str->cfg |= NYX_CFG_DUMP;
|
||||
}
|
||||
if (b_cfg.extra_cfg & EXTRA_CFG_NYX_BIS)
|
||||
{
|
||||
b_cfg.extra_cfg &= ~(EXTRA_CFG_NYX_BIS);
|
||||
nyx_str->cfg |= NYX_CFG_BIS;
|
||||
b_cfg.extra_cfg &= ~(EXTRA_CFG_NYX_SEPT);
|
||||
nyx_str->cfg |= NYX_CFG_SEPT;
|
||||
nyx_str->cfg |= b_cfg.sept << 24;
|
||||
}
|
||||
if (b_cfg.extra_cfg & EXTRA_CFG_NYX_UMS)
|
||||
{
|
||||
@@ -808,7 +798,7 @@ static void _bootloader_corruption_protect()
|
||||
|
||||
static void _auto_launch_firmware()
|
||||
{
|
||||
if(b_cfg.extra_cfg & (EXTRA_CFG_NYX_DUMP | EXTRA_CFG_NYX_BIS))
|
||||
if(b_cfg.extra_cfg & EXTRA_CFG_NYX_SEPT)
|
||||
{
|
||||
if (!h_cfg.sept_run)
|
||||
EMC(EMC_SCRATCH0) |= EMC_HEKA_UPD;
|
||||
@@ -1120,18 +1110,15 @@ out:
|
||||
|
||||
static void _patched_rcm_protection()
|
||||
{
|
||||
sdmmc_storage_t storage;
|
||||
sdmmc_t sdmmc;
|
||||
|
||||
if (!h_cfg.rcm_patched || hw_get_chip_id() == GP_HIDREV_MAJOR_T210B01)
|
||||
return;
|
||||
|
||||
// Check if AutoRCM is enabled and protect from a permanent brick.
|
||||
if (!sdmmc_storage_init_mmc(&storage, &sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400))
|
||||
if (!sdmmc_storage_init_mmc(&emmc_storage, &emmc_sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400))
|
||||
return;
|
||||
|
||||
u8 *buf = (u8 *)malloc(0x200);
|
||||
sdmmc_storage_set_mmc_partition(&storage, EMMC_BOOT0);
|
||||
sdmmc_storage_set_mmc_partition(&emmc_storage, EMMC_BOOT0);
|
||||
|
||||
u32 sector;
|
||||
u8 corr_mod0, mod1;
|
||||
@@ -1143,7 +1130,7 @@ static void _patched_rcm_protection()
|
||||
for (u32 i = 0; i < 4; i++)
|
||||
{
|
||||
sector = 1 + (32 * i); // 0x4000 bct + 0x200 offset.
|
||||
sdmmc_storage_read(&storage, sector, 1, buf);
|
||||
sdmmc_storage_read(&emmc_storage, sector, 1, buf);
|
||||
|
||||
// Check if 2nd byte of modulus is correct.
|
||||
if (buf[0x11] != mod1)
|
||||
@@ -1154,12 +1141,12 @@ static void _patched_rcm_protection()
|
||||
{
|
||||
buf[0x10] = corr_mod0;
|
||||
|
||||
sdmmc_storage_write(&storage, sector, 1, buf);
|
||||
sdmmc_storage_write(&emmc_storage, sector, 1, buf);
|
||||
}
|
||||
}
|
||||
|
||||
free(buf);
|
||||
sdmmc_storage_end(&storage);
|
||||
sdmmc_storage_end(&emmc_storage);
|
||||
}
|
||||
|
||||
#define EXCP_EN_ADDR 0x4003FFFC
|
||||
@@ -1513,15 +1500,15 @@ ment_t ment_top[] = {
|
||||
MDEF_MENU("Console info", &menu_cinfo),
|
||||
MDEF_CAPTION("---------------", 0xFF444444),
|
||||
MDEF_HANDLER("Reload", ipl_reload),
|
||||
MDEF_HANDLER_EX("Reboot (Normal)", &STATE_REBOOT_BYPASS_FUSES, power_set_state_ex),
|
||||
MDEF_HANDLER_EX("Reboot (RCM)", &STATE_REBOOT_RCM, power_set_state_ex),
|
||||
MDEF_HANDLER_EX("Power off", &STATE_POWER_OFF, power_set_state_ex),
|
||||
MDEF_HANDLER_EX("Reboot (OFW)", &STATE_REBOOT_BYPASS_FUSES, power_set_state_ex),
|
||||
MDEF_HANDLER_EX("Reboot (RCM)", &STATE_REBOOT_RCM, power_set_state_ex),
|
||||
MDEF_HANDLER_EX("Power off", &STATE_POWER_OFF, power_set_state_ex),
|
||||
MDEF_CAPTION("---------------", 0xFF444444),
|
||||
MDEF_HANDLER("About", _about),
|
||||
MDEF_END()
|
||||
};
|
||||
|
||||
menu_t menu_top = { ment_top, "hekate - CTCaer mod v5.5.3", 0, 0 };
|
||||
menu_t menu_top = { ment_top, "hekate - CTCaer mod v5.5.4", 0, 0 };
|
||||
|
||||
extern void pivot_stack(u32 stack_top);
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019 CTCaer
|
||||
* Copyright (c) 2019-2021 CTCaer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
@@ -131,13 +131,13 @@ static int emummc_raw_get_part_off(int part_idx)
|
||||
return 2;
|
||||
}
|
||||
|
||||
int emummc_storage_init_mmc(sdmmc_storage_t *storage, sdmmc_t *sdmmc)
|
||||
int emummc_storage_init_mmc()
|
||||
{
|
||||
FILINFO fno;
|
||||
emu_cfg.active_part = 0;
|
||||
|
||||
// Always init eMMC even when in emuMMC. eMMC is needed from the emuMMC driver anyway.
|
||||
if (!sdmmc_storage_init_mmc(storage, sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400))
|
||||
if (!sdmmc_storage_init_mmc(&emmc_storage, &emmc_sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400))
|
||||
return 2;
|
||||
|
||||
if (!emu_cfg.enabled || h_cfg.emummc_force_disable)
|
||||
@@ -173,21 +173,21 @@ out:
|
||||
return 1;
|
||||
}
|
||||
|
||||
int emummc_storage_end(sdmmc_storage_t *storage)
|
||||
int emummc_storage_end()
|
||||
{
|
||||
if (!emu_cfg.enabled || h_cfg.emummc_force_disable)
|
||||
sdmmc_storage_end(storage);
|
||||
sdmmc_storage_end(&emmc_storage);
|
||||
else
|
||||
sd_end();
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int emummc_storage_read(sdmmc_storage_t *storage, u32 sector, u32 num_sectors, void *buf)
|
||||
int emummc_storage_read(u32 sector, u32 num_sectors, void *buf)
|
||||
{
|
||||
FIL fp;
|
||||
if (!emu_cfg.enabled || h_cfg.emummc_force_disable)
|
||||
return sdmmc_storage_read(storage, sector, num_sectors, buf);
|
||||
return sdmmc_storage_read(&emmc_storage, sector, num_sectors, buf);
|
||||
else if (emu_cfg.sector)
|
||||
{
|
||||
sector += emu_cfg.sector;
|
||||
@@ -228,11 +228,11 @@ int emummc_storage_read(sdmmc_storage_t *storage, u32 sector, u32 num_sectors, v
|
||||
return 1;
|
||||
}
|
||||
|
||||
int emummc_storage_write(sdmmc_storage_t *storage, u32 sector, u32 num_sectors, void *buf)
|
||||
int emummc_storage_write(u32 sector, u32 num_sectors, void *buf)
|
||||
{
|
||||
FIL fp;
|
||||
if (!emu_cfg.enabled || h_cfg.emummc_force_disable)
|
||||
return sdmmc_storage_write(storage, sector, num_sectors, buf);
|
||||
return sdmmc_storage_write(&emmc_storage, sector, num_sectors, buf);
|
||||
else if (emu_cfg.sector)
|
||||
{
|
||||
sector += emu_cfg.sector;
|
||||
@@ -253,15 +253,13 @@ int emummc_storage_write(sdmmc_storage_t *storage, u32 sector, u32 num_sectors,
|
||||
itoa(file_part, emu_cfg.emummc_file_based_path + strlen(emu_cfg.emummc_file_based_path) - 1, 10);
|
||||
}
|
||||
}
|
||||
|
||||
if (f_open(&fp, emu_cfg.emummc_file_based_path, FA_WRITE))
|
||||
{
|
||||
gfx_printf("e5\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
f_lseek(&fp, (u64)sector << 9);
|
||||
if (f_write(&fp, buf, (u64)num_sectors << 9, NULL))
|
||||
{
|
||||
gfx_printf("e6\n");
|
||||
f_close(&fp);
|
||||
return 0;
|
||||
}
|
||||
@@ -271,13 +269,12 @@ int emummc_storage_write(sdmmc_storage_t *storage, u32 sector, u32 num_sectors,
|
||||
}
|
||||
}
|
||||
|
||||
int emummc_storage_set_mmc_partition(sdmmc_storage_t *storage, u32 partition)
|
||||
int emummc_storage_set_mmc_partition(u32 partition)
|
||||
{
|
||||
emu_cfg.active_part = partition;
|
||||
sdmmc_storage_set_mmc_partition(&emmc_storage, partition);
|
||||
|
||||
if (!emu_cfg.enabled || h_cfg.emummc_force_disable)
|
||||
sdmmc_storage_set_mmc_partition(storage, partition);
|
||||
else if (emu_cfg.sector)
|
||||
if (!emu_cfg.enabled || h_cfg.emummc_force_disable || emu_cfg.sector)
|
||||
return 1;
|
||||
else
|
||||
{
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019 CTCaer
|
||||
* Copyright (c) 2019-2021 CTCaer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
@@ -51,10 +51,10 @@ extern emummc_cfg_t emu_cfg;
|
||||
|
||||
void emummc_load_cfg();
|
||||
bool emummc_set_path(char *path);
|
||||
int emummc_storage_init_mmc(sdmmc_storage_t *storage, sdmmc_t *sdmmc);
|
||||
int emummc_storage_end(sdmmc_storage_t *storage);
|
||||
int emummc_storage_read(sdmmc_storage_t *storage, u32 sector, u32 num_sectors, void *buf);
|
||||
int emummc_storage_write(sdmmc_storage_t *storage, u32 sector, u32 num_sectors, void *buf);
|
||||
int emummc_storage_set_mmc_partition(sdmmc_storage_t *storage, u32 partition);
|
||||
int emummc_storage_init_mmc();
|
||||
int emummc_storage_end();
|
||||
int emummc_storage_read(u32 sector, u32 num_sectors, void *buf);
|
||||
int emummc_storage_write(u32 sector, u32 num_sectors, void *buf);
|
||||
int emummc_storage_set_mmc_partition(u32 partition);
|
||||
|
||||
#endif
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2019-2020 CTCaer
|
||||
* Copyright (c) 2019-2021 CTCaer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
@@ -32,7 +32,7 @@ void nx_emmc_gpt_parse(link_t *gpt, sdmmc_storage_t *storage)
|
||||
{
|
||||
gpt_t *gpt_buf = (gpt_t *)calloc(NX_GPT_NUM_BLOCKS, NX_EMMC_BLOCKSIZE);
|
||||
|
||||
emummc_storage_read(storage, NX_GPT_FIRST_LBA, NX_GPT_NUM_BLOCKS, gpt_buf);
|
||||
emummc_storage_read(NX_GPT_FIRST_LBA, NX_GPT_NUM_BLOCKS, gpt_buf);
|
||||
|
||||
for (u32 i = 0; i < gpt_buf->header.num_part_ents; i++)
|
||||
{
|
||||
@@ -78,7 +78,7 @@ int nx_emmc_part_read(sdmmc_storage_t *storage, emmc_part_t *part, u32 sector_of
|
||||
if (part->lba_start + sector_off > part->lba_end)
|
||||
return 0;
|
||||
|
||||
return emummc_storage_read(storage, part->lba_start + sector_off, num_sectors, buf);
|
||||
return emummc_storage_read(part->lba_start + sector_off, num_sectors, buf);
|
||||
}
|
||||
|
||||
int nx_emmc_part_write(sdmmc_storage_t *storage, emmc_part_t *part, u32 sector_off, u32 num_sectors, void *buf)
|
||||
@@ -87,7 +87,7 @@ int nx_emmc_part_write(sdmmc_storage_t *storage, emmc_part_t *part, u32 sector_o
|
||||
if (part->lba_start + sector_off > part->lba_end)
|
||||
return 0;
|
||||
|
||||
return sdmmc_storage_write(storage, part->lba_start + sector_off, num_sectors, buf);
|
||||
return emummc_storage_write(part->lba_start + sector_off, num_sectors, buf);
|
||||
}
|
||||
|
||||
void nx_emmc_get_autorcm_masks(u8 *mod0, u8 *mod1)
|
||||
|
||||
@@ -180,6 +180,11 @@ static void _sd_deinit()
|
||||
void sd_unmount() { _sd_deinit(); }
|
||||
void sd_end() { _sd_deinit(); }
|
||||
|
||||
bool sd_is_gpt()
|
||||
{
|
||||
return sd_fs.part_type;
|
||||
}
|
||||
|
||||
void *sd_file_read(const char *path, u32 *fsize)
|
||||
{
|
||||
FIL fp;
|
||||
|
||||
@@ -73,7 +73,8 @@ void loader_main()
|
||||
CLOCK(CLK_RST_CONTROLLER_SCLK_BURST_POLICY) = 0x20003333; // Set SCLK to PLLP_OUT (408MHz).
|
||||
|
||||
// Get Loader and Payload size.
|
||||
u32 payload_size = sizeof(payload_00) + sizeof(payload_01);
|
||||
u32 payload_size = sizeof(payload_00) + sizeof(payload_01); // Actual payload size.
|
||||
payload_size += (u32)payload_01 - (u32)payload_00 - sizeof(payload_00); // Add array alignment.
|
||||
u32 *payload_addr = (u32 *)payload_00;
|
||||
|
||||
// Relocate payload to a safer place.
|
||||
@@ -88,16 +89,20 @@ void loader_main()
|
||||
bytes--;
|
||||
}
|
||||
|
||||
// Uncompress payload parts.
|
||||
// Set source address of the first part.
|
||||
u8 *src_addr = (void *)(IPL_RELOC_TOP - ALIGN(payload_size, 4));
|
||||
u32 pos = LZ_Uncompress((const u8 *)src_addr, (u8*)IPL_LOAD_ADDR, sizeof(payload_00));
|
||||
src_addr += (u32)payload_01 - (u32)payload_00;
|
||||
LZ_Uncompress((const u8 *)src_addr, (u8*)IPL_LOAD_ADDR + pos, sizeof(payload_01));
|
||||
// Uncompress first part.
|
||||
u32 dst_pos = LZ_Uncompress((const u8 *)src_addr, (u8*)IPL_LOAD_ADDR, sizeof(payload_00));
|
||||
|
||||
// Copy over boot configuration storage in case it was set.
|
||||
// Set source address of the second part. Includes array alignment.
|
||||
src_addr += (u32)payload_01 - (u32)payload_00;
|
||||
// Uncompress second part.
|
||||
LZ_Uncompress((const u8 *)src_addr, (u8*)IPL_LOAD_ADDR + dst_pos, sizeof(payload_01));
|
||||
|
||||
// Copy over boot configuration storage.
|
||||
memcpy((u8 *)(IPL_LOAD_ADDR + IPL_PATCHED_RELOC_SZ), &b_cfg, sizeof(boot_cfg_t));
|
||||
|
||||
// Chainload.
|
||||
// Chainload into uncompressed payload.
|
||||
void (*ipl_ptr)() = (void *)IPL_LOAD_ADDR;
|
||||
(*ipl_ptr)();
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2018 Rajko Stojadinovic
|
||||
* Copyright (c) 2018-2020 CTCaer
|
||||
* Copyright (c) 2018-2021 CTCaer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
@@ -41,7 +41,6 @@
|
||||
#define NUM_SECTORS_PER_ITER 8192 // 4MB Cache.
|
||||
#define OUT_FILENAME_SZ 128
|
||||
#define HASH_FILENAME_SZ (OUT_FILENAME_SZ + 11) // 11 == strlen(".sha256sums")
|
||||
#define SHA256_SZ 0x20
|
||||
|
||||
extern nyx_config n_cfg;
|
||||
|
||||
@@ -156,8 +155,8 @@ static int _dump_emmc_verify(emmc_tool_gui_t *gui, sdmmc_storage_t *storage, u32
|
||||
const char hexa[] = "0123456789abcdef";
|
||||
DWORD *clmt = NULL;
|
||||
|
||||
u8 hashEm[SHA256_SZ];
|
||||
u8 hashSd[SHA256_SZ];
|
||||
u8 hashEm[SE_SHA_256_SIZE];
|
||||
u8 hashSd[SE_SHA_256_SIZE];
|
||||
|
||||
if (f_open(&fp, outFilename, FA_READ) == FR_OK)
|
||||
{
|
||||
@@ -254,7 +253,7 @@ static int _dump_emmc_verify(emmc_tool_gui_t *gui, sdmmc_storage_t *storage, u32
|
||||
manual_system_maintenance(false);
|
||||
se_calc_sha256_finalize(hashEm, NULL);
|
||||
se_calc_sha256_oneshot(hashSd, bufSd, num << 9);
|
||||
res = memcmp(hashEm, hashSd, 0x10);
|
||||
res = memcmp(hashEm, hashSd, SE_SHA_256_SIZE / 2);
|
||||
|
||||
if (res)
|
||||
{
|
||||
@@ -276,14 +275,14 @@ static int _dump_emmc_verify(emmc_tool_gui_t *gui, sdmmc_storage_t *storage, u32
|
||||
if (n_cfg.verification == 3)
|
||||
{
|
||||
// Transform computed hash to readable hexadecimal
|
||||
char hashStr[SHA256_SZ * 2 + 1];
|
||||
char hashStr[SE_SHA_256_SIZE * 2 + 1];
|
||||
char *hashStrPtr = hashStr;
|
||||
for (int i = 0; i < SHA256_SZ; i++)
|
||||
for (int i = 0; i < SE_SHA_256_SIZE; i++)
|
||||
{
|
||||
*(hashStrPtr++) = hexa[hashSd[i] >> 4];
|
||||
*(hashStrPtr++) = hexa[hashSd[i] & 0x0F];
|
||||
}
|
||||
hashStr[SHA256_SZ * 2] = '\0';
|
||||
hashStr[SE_SHA_256_SIZE * 2] = '\0';
|
||||
|
||||
f_puts(hashStr, &hashFp);
|
||||
f_puts("\n", &hashFp);
|
||||
@@ -771,9 +770,7 @@ void dump_emmc_selected(emmcPartType_t dumpType, emmc_tool_gui_t *gui)
|
||||
// Get SD Card free space for Partial Backup.
|
||||
f_getfree("", &sd_fs.free_clst, NULL);
|
||||
|
||||
sdmmc_storage_t storage;
|
||||
sdmmc_t sdmmc;
|
||||
if (!sdmmc_storage_init_mmc(&storage, &sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400))
|
||||
if (!sdmmc_storage_init_mmc(&emmc_storage, &emmc_sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400))
|
||||
{
|
||||
lv_label_set_text(gui->label_info, "#FFDD00 Failed to init eMMC!#");
|
||||
goto out;
|
||||
@@ -782,16 +779,16 @@ void dump_emmc_selected(emmcPartType_t dumpType, emmc_tool_gui_t *gui)
|
||||
int i = 0;
|
||||
char sdPath[OUT_FILENAME_SZ];
|
||||
// Create Restore folders, if they do not exist.
|
||||
emmcsn_path_impl(sdPath, "/restore", "", &storage);
|
||||
emmcsn_path_impl(sdPath, "/restore/partitions", "", &storage);
|
||||
emmcsn_path_impl(sdPath, "", "", &storage);
|
||||
emmcsn_path_impl(sdPath, "/restore", "", &emmc_storage);
|
||||
emmcsn_path_impl(sdPath, "/restore/partitions", "", &emmc_storage);
|
||||
emmcsn_path_impl(sdPath, "", "", &emmc_storage);
|
||||
gui->base_path = (char *)malloc(strlen(sdPath) + 1);
|
||||
strcpy(gui->base_path, sdPath);
|
||||
|
||||
timer = get_tmr_s();
|
||||
if (dumpType & PART_BOOT)
|
||||
{
|
||||
const u32 BOOT_PART_SIZE = storage.ext_csd.boot_mult << 17;
|
||||
const u32 BOOT_PART_SIZE = emmc_storage.ext_csd.boot_mult << 17;
|
||||
|
||||
emmc_part_t bootPart;
|
||||
memset(&bootPart, 0, sizeof(bootPart));
|
||||
@@ -810,10 +807,10 @@ void dump_emmc_selected(emmcPartType_t dumpType, emmc_tool_gui_t *gui)
|
||||
lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, txt_buf);
|
||||
manual_system_maintenance(true);
|
||||
|
||||
sdmmc_storage_set_mmc_partition(&storage, i + 1);
|
||||
sdmmc_storage_set_mmc_partition(&emmc_storage, i + 1);
|
||||
|
||||
emmcsn_path_impl(sdPath, "", bootPart.name, &storage);
|
||||
res = _dump_emmc_part(gui, sdPath, i, &storage, &bootPart);
|
||||
emmcsn_path_impl(sdPath, "", bootPart.name, &emmc_storage);
|
||||
res = _dump_emmc_part(gui, sdPath, i, &emmc_storage, &bootPart);
|
||||
|
||||
if (!res)
|
||||
s_printf(txt_buf, "#FFDD00 Failed!#\n");
|
||||
@@ -827,16 +824,16 @@ void dump_emmc_selected(emmcPartType_t dumpType, emmc_tool_gui_t *gui)
|
||||
|
||||
if ((dumpType & PART_SYSTEM) || (dumpType & PART_USER) || (dumpType & PART_RAW))
|
||||
{
|
||||
sdmmc_storage_set_mmc_partition(&storage, EMMC_GPP);
|
||||
sdmmc_storage_set_mmc_partition(&emmc_storage, EMMC_GPP);
|
||||
|
||||
if ((dumpType & PART_SYSTEM) || (dumpType & PART_USER))
|
||||
{
|
||||
emmcsn_path_impl(sdPath, "/partitions", "", &storage);
|
||||
emmcsn_path_impl(sdPath, "/partitions", "", &emmc_storage);
|
||||
gui->base_path = (char *)malloc(strlen(sdPath) + 1);
|
||||
strcpy(gui->base_path, sdPath);
|
||||
|
||||
LIST_INIT(gpt);
|
||||
nx_emmc_gpt_parse(&gpt, &storage);
|
||||
nx_emmc_gpt_parse(&gpt, &emmc_storage);
|
||||
LIST_FOREACH_ENTRY(emmc_part_t, part, &gpt, link)
|
||||
{
|
||||
if ((dumpType & PART_USER) == 0 && !strcmp(part->name, "USER"))
|
||||
@@ -852,8 +849,8 @@ void dump_emmc_selected(emmcPartType_t dumpType, emmc_tool_gui_t *gui)
|
||||
manual_system_maintenance(true);
|
||||
i++;
|
||||
|
||||
emmcsn_path_impl(sdPath, "/partitions", part->name, &storage);
|
||||
res = _dump_emmc_part(gui, sdPath, 0, &storage, part);
|
||||
emmcsn_path_impl(sdPath, "/partitions", part->name, &emmc_storage);
|
||||
res = _dump_emmc_part(gui, sdPath, 0, &emmc_storage, part);
|
||||
// If a part failed, don't continue.
|
||||
if (!res)
|
||||
{
|
||||
@@ -873,7 +870,7 @@ void dump_emmc_selected(emmcPartType_t dumpType, emmc_tool_gui_t *gui)
|
||||
if (dumpType & PART_RAW)
|
||||
{
|
||||
// Get GP partition size dynamically.
|
||||
const u32 RAW_AREA_NUM_SECTORS = storage.sec_cnt;
|
||||
const u32 RAW_AREA_NUM_SECTORS = emmc_storage.sec_cnt;
|
||||
|
||||
emmc_part_t rawPart;
|
||||
memset(&rawPart, 0, sizeof(rawPart));
|
||||
@@ -890,8 +887,8 @@ void dump_emmc_selected(emmcPartType_t dumpType, emmc_tool_gui_t *gui)
|
||||
|
||||
i++;
|
||||
|
||||
emmcsn_path_impl(sdPath, "", rawPart.name, &storage);
|
||||
res = _dump_emmc_part(gui, sdPath, 2, &storage, &rawPart);
|
||||
emmcsn_path_impl(sdPath, "", rawPart.name, &emmc_storage);
|
||||
res = _dump_emmc_part(gui, sdPath, 2, &emmc_storage, &rawPart);
|
||||
|
||||
if (!res)
|
||||
s_printf(txt_buf, "#FFDD00 Failed!#\n");
|
||||
@@ -905,7 +902,7 @@ void dump_emmc_selected(emmcPartType_t dumpType, emmc_tool_gui_t *gui)
|
||||
}
|
||||
|
||||
timer = get_tmr_s() - timer;
|
||||
sdmmc_storage_end(&storage);
|
||||
sdmmc_storage_end(&emmc_storage);
|
||||
|
||||
if (res && n_cfg.verification && !gui->raw_emummc)
|
||||
s_printf(txt_buf, "Time taken: %dm %ds.\n#96FF00 Finished and verified!#", timer / 60, timer % 60);
|
||||
@@ -1134,7 +1131,7 @@ static int _restore_emmc_part(emmc_tool_gui_t *gui, char *sd_path, int active_pa
|
||||
_get_valid_partition(§or_start, §or_size, &part_idx, false);
|
||||
if (!part_idx || !sector_size)
|
||||
{
|
||||
s_printf(gui->txt_buf, "#FFDD00 Failed to find a partition...#\n");
|
||||
s_printf(gui->txt_buf, "\n#FFDD00 Failed to find a partition...#\n");
|
||||
lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf);
|
||||
manual_system_maintenance(true);
|
||||
|
||||
@@ -1161,7 +1158,7 @@ static int _restore_emmc_part(emmc_tool_gui_t *gui, char *sd_path, int active_pa
|
||||
// Verify part.
|
||||
if (_dump_emmc_verify(gui, storage, lbaStartPart, outFilename, part))
|
||||
{
|
||||
s_printf(gui->txt_buf, "#FFDD00 Please try again...#\n");
|
||||
s_printf(gui->txt_buf, "\n#FFDD00 Please try again...#\n");
|
||||
lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf);
|
||||
manual_system_maintenance(true);
|
||||
|
||||
@@ -1185,7 +1182,7 @@ static int _restore_emmc_part(emmc_tool_gui_t *gui, char *sd_path, int active_pa
|
||||
res = f_open(&fp, outFilename, FA_READ);
|
||||
if (res)
|
||||
{
|
||||
s_printf(gui->txt_buf, "#FF0000 Error (%d) while opening file#\n#FFDD00 %s!#\n", res, outFilename);
|
||||
s_printf(gui->txt_buf, "\n#FF0000 Error (%d) while opening file#\n#FFDD00 %s!#\n", res, outFilename);
|
||||
lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf);
|
||||
manual_system_maintenance(true);
|
||||
|
||||
@@ -1225,8 +1222,8 @@ static int _restore_emmc_part(emmc_tool_gui_t *gui, char *sd_path, int active_pa
|
||||
while (res)
|
||||
{
|
||||
s_printf(gui->txt_buf,
|
||||
"#FFDD00 Error reading %d blocks @ LBA %08X,#\n"
|
||||
"#FFDD00 from eMMC (try %d). #",
|
||||
"\n#FFDD00 Error reading %d blocks @ LBA %08X,#\n"
|
||||
"#FFDD00 from eMMC (try %d).\n#",
|
||||
num, lba_curr, ++retryCount);
|
||||
lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf);
|
||||
manual_system_maintenance(true);
|
||||
@@ -1371,9 +1368,7 @@ void restore_emmc_selected(emmcPartType_t restoreType, emmc_tool_gui_t *gui)
|
||||
goto out;
|
||||
}
|
||||
|
||||
sdmmc_storage_t storage;
|
||||
sdmmc_t sdmmc;
|
||||
if (!sdmmc_storage_init_mmc(&storage, &sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400))
|
||||
if (!sdmmc_storage_init_mmc(&emmc_storage, &emmc_sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400))
|
||||
{
|
||||
lv_label_set_text(gui->label_info, "#FFDD00 Failed to init eMMC!#");
|
||||
goto out;
|
||||
@@ -1382,14 +1377,14 @@ void restore_emmc_selected(emmcPartType_t restoreType, emmc_tool_gui_t *gui)
|
||||
int i = 0;
|
||||
char sdPath[OUT_FILENAME_SZ];
|
||||
|
||||
emmcsn_path_impl(sdPath, "/restore", "", &storage);
|
||||
emmcsn_path_impl(sdPath, "/restore", "", &emmc_storage);
|
||||
gui->base_path = (char *)malloc(strlen(sdPath) + 1);
|
||||
strcpy(gui->base_path, sdPath);
|
||||
|
||||
timer = get_tmr_s();
|
||||
if (restoreType & PART_BOOT)
|
||||
{
|
||||
const u32 BOOT_PART_SIZE = storage.ext_csd.boot_mult << 17;
|
||||
const u32 BOOT_PART_SIZE = emmc_storage.ext_csd.boot_mult << 17;
|
||||
|
||||
emmc_part_t bootPart;
|
||||
memset(&bootPart, 0, sizeof(bootPart));
|
||||
@@ -1408,10 +1403,10 @@ void restore_emmc_selected(emmcPartType_t restoreType, emmc_tool_gui_t *gui)
|
||||
lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, txt_buf);
|
||||
manual_system_maintenance(true);
|
||||
|
||||
sdmmc_storage_set_mmc_partition(&storage, i + 1);
|
||||
sdmmc_storage_set_mmc_partition(&emmc_storage, i + 1);
|
||||
|
||||
emmcsn_path_impl(sdPath, "/restore", bootPart.name, &storage);
|
||||
res = _restore_emmc_part(gui, sdPath, i, &storage, &bootPart, false);
|
||||
emmcsn_path_impl(sdPath, "/restore", bootPart.name, &emmc_storage);
|
||||
res = _restore_emmc_part(gui, sdPath, i, &emmc_storage, &bootPart, false);
|
||||
|
||||
if (!res)
|
||||
s_printf(txt_buf, "#FFDD00 Failed!#\n");
|
||||
@@ -1425,14 +1420,14 @@ void restore_emmc_selected(emmcPartType_t restoreType, emmc_tool_gui_t *gui)
|
||||
|
||||
if (restoreType & PART_GP_ALL)
|
||||
{
|
||||
emmcsn_path_impl(sdPath, "/restore/partitions", "", &storage);
|
||||
emmcsn_path_impl(sdPath, "/restore/partitions", "", &emmc_storage);
|
||||
gui->base_path = (char *)malloc(strlen(sdPath) + 1);
|
||||
strcpy(gui->base_path, sdPath);
|
||||
|
||||
sdmmc_storage_set_mmc_partition(&storage, EMMC_GPP);
|
||||
sdmmc_storage_set_mmc_partition(&emmc_storage, EMMC_GPP);
|
||||
|
||||
LIST_INIT(gpt);
|
||||
nx_emmc_gpt_parse(&gpt, &storage);
|
||||
nx_emmc_gpt_parse(&gpt, &emmc_storage);
|
||||
LIST_FOREACH_ENTRY(emmc_part_t, part, &gpt, link)
|
||||
{
|
||||
s_printf(txt_buf, "#00DDFF %02d: %s#\n#00DDFF Range: 0x%08X - 0x%08X#\n\n\n\n\n",
|
||||
@@ -1443,8 +1438,8 @@ void restore_emmc_selected(emmcPartType_t restoreType, emmc_tool_gui_t *gui)
|
||||
manual_system_maintenance(true);
|
||||
i++;
|
||||
|
||||
emmcsn_path_impl(sdPath, "/restore/partitions", part->name, &storage);
|
||||
res = _restore_emmc_part(gui, sdPath, 0, &storage, part, false);
|
||||
emmcsn_path_impl(sdPath, "/restore/partitions", part->name, &emmc_storage);
|
||||
res = _restore_emmc_part(gui, sdPath, 0, &emmc_storage, part, false);
|
||||
|
||||
if (!res)
|
||||
s_printf(txt_buf, "#FFDD00 Failed!#\n");
|
||||
@@ -1460,7 +1455,7 @@ void restore_emmc_selected(emmcPartType_t restoreType, emmc_tool_gui_t *gui)
|
||||
if (restoreType & PART_RAW)
|
||||
{
|
||||
// Get GP partition size dynamically.
|
||||
const u32 RAW_AREA_NUM_SECTORS = storage.sec_cnt;
|
||||
const u32 RAW_AREA_NUM_SECTORS = emmc_storage.sec_cnt;
|
||||
|
||||
emmc_part_t rawPart;
|
||||
memset(&rawPart, 0, sizeof(rawPart));
|
||||
@@ -1476,8 +1471,8 @@ void restore_emmc_selected(emmcPartType_t restoreType, emmc_tool_gui_t *gui)
|
||||
manual_system_maintenance(true);
|
||||
i++;
|
||||
|
||||
emmcsn_path_impl(sdPath, "/restore", rawPart.name, &storage);
|
||||
res = _restore_emmc_part(gui, sdPath, 2, &storage, &rawPart, true);
|
||||
emmcsn_path_impl(sdPath, "/restore", rawPart.name, &emmc_storage);
|
||||
res = _restore_emmc_part(gui, sdPath, 2, &emmc_storage, &rawPart, true);
|
||||
|
||||
if (!res)
|
||||
s_printf(txt_buf, "#FFDD00 Failed!#\n");
|
||||
@@ -1490,7 +1485,7 @@ void restore_emmc_selected(emmcPartType_t restoreType, emmc_tool_gui_t *gui)
|
||||
}
|
||||
|
||||
timer = get_tmr_s() - timer;
|
||||
sdmmc_storage_end(&storage);
|
||||
sdmmc_storage_end(&emmc_storage);
|
||||
|
||||
if (res && n_cfg.verification && !gui->raw_emummc)
|
||||
s_printf(txt_buf, "Time taken: %dm %ds.\n#96FF00 Finished and verified!#", timer / 60, timer % 60);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2018 Rajko Stojadinovic
|
||||
* Copyright (c) 2018-2020 CTCaer
|
||||
* Copyright (c) 2018-2021 CTCaer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
@@ -23,13 +23,16 @@
|
||||
|
||||
#include "gui.h"
|
||||
#include "fe_emummc_tools.h"
|
||||
#include "../hos/sept.h"
|
||||
#include "../config.h"
|
||||
#include <utils/ini.h>
|
||||
#include <libs/fatfs/diskio.h>
|
||||
#include <libs/fatfs/ff.h>
|
||||
#include <mem/heap.h>
|
||||
#include <sec/se.h>
|
||||
#include <storage/mbr_gpt.h>
|
||||
#include "../storage/nx_emmc.h"
|
||||
#include "../storage/nx_emmc_bis.h"
|
||||
#include <storage/nx_sd.h>
|
||||
#include <storage/sdmmc.h>
|
||||
#include <utils/btn.h>
|
||||
@@ -40,6 +43,7 @@
|
||||
#define OUT_FILENAME_SZ 128
|
||||
|
||||
extern hekate_config h_cfg;
|
||||
extern volatile boot_cfg_t *b_cfg;
|
||||
|
||||
void load_emummc_cfg(emummc_cfg_t *emu_info)
|
||||
{
|
||||
@@ -228,7 +232,7 @@ static int _dump_emummc_file_part(emmc_tool_gui_t *gui, char *sd_path, sdmmc_sto
|
||||
res = f_open(&fp, outFilename, FA_CREATE_ALWAYS | FA_WRITE);
|
||||
if (res)
|
||||
{
|
||||
s_printf(gui->txt_buf, "#FF0000 Error (%d) while creating#\n#FFDD00 %s#\n", res, outFilename);
|
||||
s_printf(gui->txt_buf, "\n#FF0000 Error (%d) while creating#\n#FFDD00 %s#\n", res, outFilename);
|
||||
lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf);
|
||||
manual_system_maintenance(true);
|
||||
|
||||
@@ -244,7 +248,7 @@ static int _dump_emummc_file_part(emmc_tool_gui_t *gui, char *sd_path, sdmmc_sto
|
||||
// Check for cancellation combo.
|
||||
if (btn_read_vol() == (BTN_VOL_UP | BTN_VOL_DOWN))
|
||||
{
|
||||
s_printf(gui->txt_buf, "#FFDD00 The emuMMC was cancelled!#\n");
|
||||
s_printf(gui->txt_buf, "\n#FFDD00 The emuMMC was cancelled!#\n");
|
||||
lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf);
|
||||
manual_system_maintenance(true);
|
||||
|
||||
@@ -262,7 +266,7 @@ static int _dump_emummc_file_part(emmc_tool_gui_t *gui, char *sd_path, sdmmc_sto
|
||||
while (!sdmmc_storage_read(storage, lba_curr, num, buf))
|
||||
{
|
||||
s_printf(gui->txt_buf,
|
||||
"#FFDD00 Error reading %d blocks @ LBA %08X,#\n"
|
||||
"\n#FFDD00 Error reading %d blocks @ LBA %08X,#\n"
|
||||
"#FFDD00 from eMMC (try %d). #",
|
||||
num, lba_curr, ++retryCount);
|
||||
lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf);
|
||||
@@ -283,7 +287,7 @@ static int _dump_emummc_file_part(emmc_tool_gui_t *gui, char *sd_path, sdmmc_sto
|
||||
}
|
||||
else
|
||||
{
|
||||
s_printf(gui->txt_buf, "#FFDD00 Retrying...#\n");
|
||||
s_printf(gui->txt_buf, "#FFDD00 Retrying...#");
|
||||
lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf);
|
||||
manual_system_maintenance(true);
|
||||
}
|
||||
@@ -349,6 +353,7 @@ void dump_emummc_file(emmc_tool_gui_t *gui)
|
||||
u32 timer = 0;
|
||||
|
||||
char *txt_buf = (char *)malloc(0x4000);
|
||||
gui->base_path = (char *)malloc(OUT_FILENAME_SZ);
|
||||
gui->txt_buf = txt_buf;
|
||||
|
||||
s_printf(txt_buf, "");
|
||||
@@ -368,9 +373,7 @@ void dump_emummc_file(emmc_tool_gui_t *gui)
|
||||
// Get SD Card free space for Partial Backup.
|
||||
f_getfree("", &sd_fs.free_clst, NULL);
|
||||
|
||||
sdmmc_storage_t storage;
|
||||
sdmmc_t sdmmc;
|
||||
if (!sdmmc_storage_init_mmc(&storage, &sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400))
|
||||
if (!sdmmc_storage_init_mmc(&emmc_storage, &emmc_sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400))
|
||||
{
|
||||
lv_label_set_text(gui->label_info, "#FFDD00 Failed to init eMMC!#");
|
||||
goto out;
|
||||
@@ -382,7 +385,6 @@ void dump_emummc_file(emmc_tool_gui_t *gui)
|
||||
f_mkdir("emuMMC");
|
||||
strcpy(sdPath, "emuMMC/SD");
|
||||
base_len = strlen(sdPath);
|
||||
gui->base_path = (char *)malloc(OUT_FILENAME_SZ);
|
||||
|
||||
for (int j = 0; j < 100; j++)
|
||||
{
|
||||
@@ -398,7 +400,7 @@ void dump_emummc_file(emmc_tool_gui_t *gui)
|
||||
strcpy(gui->base_path, sdPath);
|
||||
|
||||
timer = get_tmr_s();
|
||||
const u32 BOOT_PART_SIZE = storage.ext_csd.boot_mult << 17;
|
||||
const u32 BOOT_PART_SIZE = emmc_storage.ext_csd.boot_mult << 17;
|
||||
|
||||
emmc_part_t bootPart;
|
||||
memset(&bootPart, 0, sizeof(bootPart));
|
||||
@@ -417,10 +419,10 @@ void dump_emummc_file(emmc_tool_gui_t *gui)
|
||||
lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, txt_buf);
|
||||
manual_system_maintenance(true);
|
||||
|
||||
sdmmc_storage_set_mmc_partition(&storage, i + 1);
|
||||
sdmmc_storage_set_mmc_partition(&emmc_storage, i + 1);
|
||||
|
||||
strcat(sdPath, bootPart.name);
|
||||
res = _dump_emummc_file_part(gui, sdPath, &storage, &bootPart);
|
||||
res = _dump_emummc_file_part(gui, sdPath, &emmc_storage, &bootPart);
|
||||
|
||||
if (!res)
|
||||
{
|
||||
@@ -437,10 +439,10 @@ void dump_emummc_file(emmc_tool_gui_t *gui)
|
||||
}
|
||||
|
||||
// Get GP partition size dynamically.
|
||||
sdmmc_storage_set_mmc_partition(&storage, EMMC_GPP);
|
||||
sdmmc_storage_set_mmc_partition(&emmc_storage, EMMC_GPP);
|
||||
|
||||
// Get GP partition size dynamically.
|
||||
const u32 RAW_AREA_NUM_SECTORS = storage.sec_cnt;
|
||||
const u32 RAW_AREA_NUM_SECTORS = emmc_storage.sec_cnt;
|
||||
|
||||
emmc_part_t rawPart;
|
||||
memset(&rawPart, 0, sizeof(rawPart));
|
||||
@@ -455,7 +457,7 @@ void dump_emummc_file(emmc_tool_gui_t *gui)
|
||||
lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, txt_buf);
|
||||
manual_system_maintenance(true);
|
||||
|
||||
res = _dump_emummc_file_part(gui, sdPath, &storage, &rawPart);
|
||||
res = _dump_emummc_file_part(gui, sdPath, &emmc_storage, &rawPart);
|
||||
|
||||
if (!res)
|
||||
s_printf(txt_buf, "#FFDD00 Failed!#\n");
|
||||
@@ -468,7 +470,7 @@ void dump_emummc_file(emmc_tool_gui_t *gui)
|
||||
|
||||
out_failed:
|
||||
timer = get_tmr_s() - timer;
|
||||
sdmmc_storage_end(&storage);
|
||||
sdmmc_storage_end(&emmc_storage);
|
||||
|
||||
if (res)
|
||||
{
|
||||
@@ -494,9 +496,15 @@ out:
|
||||
sd_unmount();
|
||||
}
|
||||
|
||||
static int _dump_emummc_raw_part(emmc_tool_gui_t *gui, int active_part, int part_idx, u32 sd_part_off, sdmmc_storage_t *storage, emmc_part_t *part)
|
||||
static int _dump_emummc_raw_part(emmc_tool_gui_t *gui, int active_part, int part_idx, u32 sd_part_off, sdmmc_storage_t *storage, emmc_part_t *part, u32 resized_count)
|
||||
{
|
||||
u32 totalSectors = part->lba_end - part->lba_start + 1;
|
||||
u32 num = 0;
|
||||
u32 pct = 0;
|
||||
u32 prevPct = 200;
|
||||
int retryCount = 0;
|
||||
u32 sd_sector_off = sd_part_off + (0x2000 * active_part);
|
||||
u32 lba_curr = part->lba_start;
|
||||
u8 *buf = (u8 *)MIXD_BUF_ALIGNED;
|
||||
|
||||
s_printf(gui->txt_buf, "\n\n\n");
|
||||
lv_label_ins_text(gui->label_info, LV_LABEL_POS_LAST, gui->txt_buf);
|
||||
@@ -511,24 +519,38 @@ static int _dump_emummc_raw_part(emmc_tool_gui_t *gui, int active_part, int part
|
||||
lv_label_ins_text(gui->label_info, LV_LABEL_POS_LAST, gui->txt_buf);
|
||||
manual_system_maintenance(true);
|
||||
|
||||
u8 *buf = (u8 *)MIXD_BUF_ALIGNED;
|
||||
u32 sd_sector_off = sd_part_off + (0x2000 * active_part);
|
||||
u32 lba_curr = part->lba_start;
|
||||
u32 prevPct = 200;
|
||||
int retryCount = 0;
|
||||
|
||||
u32 num = 0;
|
||||
u32 pct = 0;
|
||||
|
||||
lv_obj_set_opa_scale(gui->bar, LV_OPA_COVER);
|
||||
lv_obj_set_opa_scale(gui->label_pct, LV_OPA_COVER);
|
||||
|
||||
u32 user_offset = 0;
|
||||
|
||||
if (resized_count)
|
||||
{
|
||||
// Get USER partition info.
|
||||
LIST_INIT(gpt);
|
||||
nx_emmc_gpt_parse(&gpt, storage);
|
||||
emmc_part_t *user_part = nx_emmc_part_find(&gpt, "USER");
|
||||
if (!user_part)
|
||||
{
|
||||
s_printf(gui->txt_buf, "\n#FFDD00 USER partition not found!#\n");
|
||||
lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf);
|
||||
manual_system_maintenance(true);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
user_offset = user_part->lba_start;
|
||||
part->lba_end = user_offset - 1;
|
||||
nx_emmc_gpt_free(&gpt);
|
||||
}
|
||||
|
||||
u32 totalSectors = part->lba_end - part->lba_start + 1;
|
||||
while (totalSectors > 0)
|
||||
{
|
||||
// Check for cancellation combo.
|
||||
if (btn_read_vol() == (BTN_VOL_UP | BTN_VOL_DOWN))
|
||||
{
|
||||
s_printf(gui->txt_buf, "#FFDD00 The emuMMC was cancelled!#\n");
|
||||
s_printf(gui->txt_buf, "\n#FFDD00 The emuMMC was cancelled!#\n");
|
||||
lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf);
|
||||
manual_system_maintenance(true);
|
||||
|
||||
@@ -618,25 +640,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%");
|
||||
manual_system_maintenance(true);
|
||||
|
||||
// Hide the partition.
|
||||
// Set partition type to emuMMC (0xE0).
|
||||
if (active_part == 2)
|
||||
{
|
||||
mbr_t *mbr = (mbr_t *)malloc(sizeof(mbr_t));
|
||||
sdmmc_storage_read(&sd_storage, 0, 1, mbr);
|
||||
mbr->partitions[part_idx].type = 0xE0;
|
||||
sdmmc_storage_write(&sd_storage, 0, 1, mbr);
|
||||
free(mbr);
|
||||
mbr_t mbr;
|
||||
sdmmc_storage_read(&sd_storage, 0, 1, &mbr);
|
||||
mbr.partitions[part_idx].type = 0xE0;
|
||||
sdmmc_storage_write(&sd_storage, 0, 1, &mbr);
|
||||
}
|
||||
|
||||
if (resized_count)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
void dump_emummc_raw(emmc_tool_gui_t *gui, int part_idx, u32 sector_start)
|
||||
u32 kb = 0;
|
||||
u8 *tsec_fw = NULL;
|
||||
bool sept_error = false;
|
||||
|
||||
static lv_res_t _emummc_raw_check_sept_action(lv_obj_t *btns, const char * txt)
|
||||
{
|
||||
int btn_idx = lv_btnm_get_pressed(btns);
|
||||
|
||||
mbox_action(btns, txt);
|
||||
|
||||
if (btn_idx == 1 && !sept_error)
|
||||
{
|
||||
// Set boot cfg.
|
||||
b_cfg->autoboot = 0;
|
||||
b_cfg->autoboot_list = 0;
|
||||
b_cfg->extra_cfg = EXTRA_CFG_NYX_SEPT;
|
||||
b_cfg->sept = NYX_SEPT_EMUF;
|
||||
|
||||
sd_mount();
|
||||
reboot_to_sept(tsec_fw, kb);
|
||||
}
|
||||
|
||||
return LV_RES_INV;
|
||||
}
|
||||
|
||||
static int _emummc_raw_check_sept(emmc_tool_gui_t *gui, u32 resized_count)
|
||||
{
|
||||
if (!resized_count)
|
||||
return 1;
|
||||
|
||||
bool sept_needed = false;
|
||||
sept_error = false;
|
||||
tsec_fw = NULL;
|
||||
|
||||
char *txt_buf = (char *)malloc(0x4000);
|
||||
txt_buf[0] = 0;
|
||||
|
||||
// Read package1.
|
||||
static const u32 BOOTLOADER_SIZE = 0x40000;
|
||||
static const u32 BOOTLOADER_MAIN_OFFSET = 0x100000;
|
||||
static const u32 BOOTLOADER_BACKUP_OFFSET = 0x140000;
|
||||
static const u32 HOS_KEYBLOBS_OFFSET = 0x180000;
|
||||
|
||||
u32 bootloader_offset = BOOTLOADER_MAIN_OFFSET;
|
||||
u32 pk1_offset = h_cfg.t210b01 ? sizeof(bl_hdr_t210b01_t) : 0; // Skip T210B01 OEM header.
|
||||
u8 *pkg1 = (u8 *)malloc(BOOTLOADER_SIZE);
|
||||
|
||||
sdmmc_storage_set_mmc_partition(&emmc_storage, EMMC_BOOT0);
|
||||
|
||||
try_load:
|
||||
sdmmc_storage_read(&emmc_storage, bootloader_offset / NX_EMMC_BLOCKSIZE, BOOTLOADER_SIZE / NX_EMMC_BLOCKSIZE, pkg1);
|
||||
|
||||
char *build_date = malloc(32);
|
||||
const pkg1_id_t *pkg1_id = pkg1_identify(pkg1 + pk1_offset, build_date);
|
||||
|
||||
s_printf(txt_buf + strlen(txt_buf), "#00DDFF Found pkg1 ('%s')#\n", build_date);
|
||||
free(build_date);
|
||||
|
||||
if (!pkg1_id)
|
||||
{
|
||||
strcat(txt_buf, "#FFDD00 Unknown pkg1 version!#\n");
|
||||
// Try backup bootloader.
|
||||
if (bootloader_offset != BOOTLOADER_BACKUP_OFFSET)
|
||||
{
|
||||
strcat(txt_buf, "Trying backup bootloader...\n");
|
||||
bootloader_offset = BOOTLOADER_BACKUP_OFFSET;
|
||||
goto try_load;
|
||||
}
|
||||
|
||||
sept_error = true;
|
||||
goto out;
|
||||
}
|
||||
|
||||
kb = pkg1_id->kb;
|
||||
|
||||
// Skip if Mariko.
|
||||
if (h_cfg.t210b01)
|
||||
goto bis_derivation;
|
||||
|
||||
tsec_ctxt_t tsec_ctxt;
|
||||
tsec_ctxt.fw = (u8 *)pkg1 + pkg1_id->tsec_off;
|
||||
tsec_ctxt.pkg1 = pkg1;
|
||||
tsec_ctxt.pkg11_off = pkg1_id->pkg11_off;
|
||||
tsec_ctxt.secmon_base = pkg1_id->secmon_base;
|
||||
|
||||
// Get keys.
|
||||
hos_eks_get();
|
||||
if (kb >= KB_FIRMWARE_VERSION_700 && !h_cfg.sept_run)
|
||||
{
|
||||
u32 key_idx = 0;
|
||||
if (kb >= KB_FIRMWARE_VERSION_810)
|
||||
key_idx = 1;
|
||||
|
||||
if (h_cfg.eks && h_cfg.eks->enabled[key_idx] >= kb)
|
||||
h_cfg.sept_run = true;
|
||||
else
|
||||
{
|
||||
// Check that BCT is proper so sept can run.
|
||||
u8 *bct_bldr = (u8 *)calloc(1, 512);
|
||||
sdmmc_storage_read(&emmc_storage, 0x2200 / NX_EMMC_BLOCKSIZE, 1, bct_bldr);
|
||||
u32 bootloader_entrypoint = *(u32 *)&bct_bldr[0x144];
|
||||
free(bct_bldr);
|
||||
if (bootloader_entrypoint > SEPT_PRI_ENTRY)
|
||||
{
|
||||
strcpy(txt_buf, "#FFDD00 Failed to run sept because main BCT is improper!#\n"
|
||||
"#FFDD00 Run sept with proper BCT at least once to cache keys.#\n");
|
||||
sept_error = true;
|
||||
goto out;
|
||||
}
|
||||
|
||||
// Set TSEC fw.
|
||||
tsec_fw = (u8 *)tsec_ctxt.fw;
|
||||
|
||||
sept_needed = true;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
bis_derivation:;
|
||||
// Read the correct keyblob.
|
||||
u8 *keyblob = (u8 *)calloc(NX_EMMC_BLOCKSIZE, 1);
|
||||
sdmmc_storage_read(&emmc_storage, HOS_KEYBLOBS_OFFSET / NX_EMMC_BLOCKSIZE + kb, 1, keyblob);
|
||||
|
||||
// Generate BIS keys
|
||||
hos_bis_keygen(keyblob, kb, &tsec_ctxt);
|
||||
|
||||
free(keyblob);
|
||||
|
||||
u8 *cal0_buf = malloc(0x10000);
|
||||
|
||||
// Read and decrypt CAL0 for validation of working BIS keys.
|
||||
sdmmc_storage_set_mmc_partition(&emmc_storage, EMMC_GPP);
|
||||
LIST_INIT(gpt);
|
||||
nx_emmc_gpt_parse(&gpt, &emmc_storage);
|
||||
emmc_part_t *cal0_part = nx_emmc_part_find(&gpt, "PRODINFO"); // check if null
|
||||
nx_emmc_bis_init(cal0_part, false, 0);
|
||||
nx_emmc_bis_read(0, 0x40, cal0_buf);
|
||||
nx_emmc_bis_end();
|
||||
nx_emmc_gpt_free(&gpt);
|
||||
|
||||
nx_emmc_cal0_t *cal0 = (nx_emmc_cal0_t *)cal0_buf;
|
||||
|
||||
// If successful, save BIS keys.
|
||||
if (memcmp(&cal0->magic, "CAL0", 4))
|
||||
{
|
||||
hos_bis_keys_clear();
|
||||
hos_eks_bis_clear();
|
||||
|
||||
strcpy(txt_buf, "#FFDD00 BIS keys validation failed!#\n");
|
||||
sept_error = true;
|
||||
}
|
||||
else
|
||||
hos_eks_bis_save();
|
||||
free(cal0_buf);
|
||||
|
||||
out:
|
||||
// Check if sept is not needed.
|
||||
if (!sept_needed)
|
||||
free(pkg1);
|
||||
|
||||
if (sept_needed || sept_error)
|
||||
{
|
||||
lv_obj_t *dark_bg = lv_obj_create(lv_scr_act(), NULL);
|
||||
lv_obj_set_style(dark_bg, &mbox_darken);
|
||||
lv_obj_set_size(dark_bg, LV_HOR_RES, LV_VER_RES);
|
||||
|
||||
static const char * mbox_btn_map[] = { "\211", "\222Launch", "\222Close", "\211", "" };
|
||||
static const char * mbox_btn_map2[] = { "\211", "\222Close", "\211", "" };
|
||||
lv_obj_t * mbox = lv_mbox_create(dark_bg, NULL);
|
||||
lv_mbox_set_recolor_text(mbox, true);
|
||||
lv_obj_set_width(mbox, LV_HOR_RES / 9 * 5);
|
||||
|
||||
lv_mbox_set_text(mbox, "#C7EA46 BIS Keys Generation#");
|
||||
|
||||
lv_obj_t * lb_desc = lv_label_create(mbox, NULL);
|
||||
lv_label_set_long_mode(lb_desc, LV_LABEL_LONG_BREAK);
|
||||
lv_label_set_recolor(lb_desc, true);
|
||||
lv_label_set_style(lb_desc, &monospace_text);
|
||||
lv_obj_set_width(lb_desc, LV_HOR_RES / 9 * 4);
|
||||
|
||||
if (sept_error)
|
||||
{
|
||||
lv_label_set_text(lb_desc, txt_buf);
|
||||
lv_mbox_add_btns(mbox, mbox_btn_map2, _emummc_raw_check_sept_action);
|
||||
free(pkg1);
|
||||
}
|
||||
else
|
||||
{
|
||||
lv_label_set_text(lb_desc, "Sept needs to launch in order to generate keys\nneeded for emuMMC resizing.\n"
|
||||
"After that enter this menu again.");
|
||||
lv_mbox_add_btns(mbox, mbox_btn_map, _emummc_raw_check_sept_action);
|
||||
}
|
||||
|
||||
lv_obj_align(mbox, NULL, LV_ALIGN_CENTER, 0, 0);
|
||||
lv_obj_set_top(mbox, true);
|
||||
|
||||
free(txt_buf);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
sdmmc_storage_set_mmc_partition(&emmc_storage, EMMC_GPP);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void dump_emummc_raw(emmc_tool_gui_t *gui, int part_idx, u32 sector_start, u32 resized_count)
|
||||
{
|
||||
int res = 0;
|
||||
u32 timer = 0;
|
||||
|
||||
char *txt_buf = (char *)malloc(0x4000);
|
||||
gui->base_path = (char *)malloc(OUT_FILENAME_SZ);
|
||||
gui->txt_buf = txt_buf;
|
||||
|
||||
s_printf(txt_buf, "");
|
||||
@@ -650,26 +975,31 @@ void dump_emummc_raw(emmc_tool_gui_t *gui, int part_idx, u32 sector_start)
|
||||
goto out;
|
||||
}
|
||||
|
||||
sdmmc_storage_t storage;
|
||||
sdmmc_t sdmmc;
|
||||
if (!sdmmc_storage_init_mmc(&storage, &sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400))
|
||||
if (!sdmmc_storage_init_mmc(&emmc_storage, &emmc_sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400))
|
||||
{
|
||||
lv_label_set_text(gui->label_info, "#FFDD00 Failed to init eMMC!#");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!_emummc_raw_check_sept(gui, resized_count))
|
||||
{
|
||||
s_printf(gui->txt_buf, "#FFDD00 For formatting USER partition,#\n#FFDD00 BIS keys are needed!#\n");
|
||||
lv_label_ins_text(gui->label_log, LV_LABEL_POS_LAST, gui->txt_buf);
|
||||
sdmmc_storage_end(&emmc_storage);
|
||||
goto out;
|
||||
}
|
||||
|
||||
int i = 0;
|
||||
char sdPath[OUT_FILENAME_SZ];
|
||||
// Create Restore folders, if they do not exist.
|
||||
f_mkdir("emuMMC");
|
||||
s_printf(sdPath, "emuMMC/RAW%d", part_idx);
|
||||
gui->base_path = (char *)malloc(OUT_FILENAME_SZ);
|
||||
f_mkdir(sdPath);
|
||||
strcat(sdPath, "/");
|
||||
strcpy(gui->base_path, sdPath);
|
||||
|
||||
timer = get_tmr_s();
|
||||
const u32 BOOT_PART_SIZE = storage.ext_csd.boot_mult << 17;
|
||||
const u32 BOOT_PART_SIZE = emmc_storage.ext_csd.boot_mult << 17;
|
||||
|
||||
emmc_part_t bootPart;
|
||||
memset(&bootPart, 0, sizeof(bootPart));
|
||||
@@ -693,10 +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);
|
||||
manual_system_maintenance(true);
|
||||
|
||||
sdmmc_storage_set_mmc_partition(&storage, i + 1);
|
||||
sdmmc_storage_set_mmc_partition(&emmc_storage, i + 1);
|
||||
|
||||
strcat(sdPath, bootPart.name);
|
||||
res = _dump_emummc_raw_part(gui, i, part_idx, sector_start, &storage, &bootPart);
|
||||
res = _dump_emummc_raw_part(gui, i, part_idx, sector_start, &emmc_storage, &bootPart, 0);
|
||||
|
||||
if (!res)
|
||||
{
|
||||
@@ -712,10 +1042,10 @@ void dump_emummc_raw(emmc_tool_gui_t *gui, int part_idx, u32 sector_start)
|
||||
strcpy(sdPath, gui->base_path);
|
||||
}
|
||||
|
||||
sdmmc_storage_set_mmc_partition(&storage, EMMC_GPP);
|
||||
sdmmc_storage_set_mmc_partition(&emmc_storage, EMMC_GPP);
|
||||
|
||||
// Get GP partition size dynamically.
|
||||
const u32 RAW_AREA_NUM_SECTORS = storage.sec_cnt;
|
||||
const u32 RAW_AREA_NUM_SECTORS = emmc_storage.sec_cnt;
|
||||
|
||||
emmc_part_t rawPart;
|
||||
memset(&rawPart, 0, sizeof(rawPart));
|
||||
@@ -730,7 +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);
|
||||
manual_system_maintenance(true);
|
||||
|
||||
res = _dump_emummc_raw_part(gui, 2, part_idx, sector_start, &storage, &rawPart);
|
||||
res = _dump_emummc_raw_part(gui, 2, part_idx, sector_start, &emmc_storage, &rawPart, resized_count);
|
||||
|
||||
if (!res)
|
||||
s_printf(txt_buf, "#FFDD00 Failed!#\n");
|
||||
@@ -743,7 +1073,7 @@ void dump_emummc_raw(emmc_tool_gui_t *gui, int part_idx, u32 sector_start)
|
||||
|
||||
out_failed:
|
||||
timer = get_tmr_s() - timer;
|
||||
sdmmc_storage_end(&storage);
|
||||
sdmmc_storage_end(&emmc_storage);
|
||||
|
||||
if (res)
|
||||
{
|
||||
|
||||
@@ -32,7 +32,7 @@ typedef struct _emummc_cfg_t
|
||||
void load_emummc_cfg(emummc_cfg_t *emu_info);
|
||||
void save_emummc_cfg(u32 part_idx, u32 sector_start, const char *path);
|
||||
void dump_emummc_file(emmc_tool_gui_t *gui);
|
||||
void dump_emummc_raw(emmc_tool_gui_t *gui, int part_idx, u32 sector_start);
|
||||
void dump_emummc_raw(emmc_tool_gui_t *gui, int part_idx, u32 sector_start, u32 resized_count);
|
||||
void update_emummc_base_folder(char *outFilename, u32 sdPathLen, u32 currPartIdx);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2020 CTCaer
|
||||
* Copyright (c) 2018-2021 CTCaer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
@@ -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_static_text(lbl_credits,
|
||||
"#C7EA46 hekate# (c) 2018, #C7EA46 naehrwert#, #C7EA46 st4rk#\n"
|
||||
" (c) 2018-2020, #C7EA46 CTCaer#\n"
|
||||
" (c) 2018-2021, #C7EA46 CTCaer#\n"
|
||||
"\n"
|
||||
"#C7EA46 Nyx GUI# (c) 2019-2020, #C7EA46 CTCaer#\n"
|
||||
"#C7EA46 Nyx GUI# (c) 2019-2021, #C7EA46 CTCaer#\n"
|
||||
"\n"
|
||||
"Thanks to: #00CCFF derrek, nedwill, plutoo, #\n"
|
||||
" #00CCFF shuffle2, smea, thexyz, yellows8 #\n"
|
||||
@@ -1755,14 +1755,14 @@ ini_parsing:
|
||||
{
|
||||
lv_label_set_static_text(label_error,
|
||||
"#FFDD00 No main boot entries found...#\n"
|
||||
"You can use the following entry to boot stock,\n"
|
||||
"Check that #96FF00 bootloader/hekate_ipl.ini# has boot entries\n"
|
||||
"or use #C7EA46 More configs# button for more boot entries.");
|
||||
}
|
||||
else
|
||||
{
|
||||
lv_label_set_static_text(label_error,
|
||||
"#FFDD00 No .ini or boot entries found...#\n"
|
||||
"Check that a .ini file exists in #96FF00 /bootloader/ini/#,\n"
|
||||
"Check that a .ini file exists in #96FF00 bootloader/ini/#\n"
|
||||
"and that it contains at least one entry.");
|
||||
}
|
||||
|
||||
@@ -2206,17 +2206,25 @@ static void _nyx_main_menu(lv_theme_t * th)
|
||||
lv_tabview_set_tab_load_action(tv, _show_hide_save_button);
|
||||
|
||||
// If we rebooted to run sept for dumping, lunch dump immediately.
|
||||
if (nyx_str->cfg & NYX_CFG_DUMP)
|
||||
if (nyx_str->cfg & NYX_CFG_SEPT)
|
||||
{
|
||||
nyx_str->cfg &= ~(NYX_CFG_DUMP);
|
||||
lv_task_t *task_run_dump = lv_task_create(sept_run_dump, LV_TASK_ONESHOT, LV_TASK_PRIO_MID, NULL);
|
||||
lv_task_once(task_run_dump);
|
||||
}
|
||||
else if (nyx_str->cfg & NYX_CFG_BIS)
|
||||
{
|
||||
nyx_str->cfg &= ~(NYX_CFG_BIS);
|
||||
lv_task_t *task_run_cal0 = lv_task_create(sept_run_cal0, LV_TASK_ONESHOT, LV_TASK_PRIO_LOWEST, NULL);
|
||||
lv_task_once(task_run_cal0);
|
||||
u32 type = nyx_str->cfg >> 24;
|
||||
nyx_str->cfg &= ~(NYX_CFG_SEPT | NYX_CFG_EXTRA);
|
||||
|
||||
if (type == NYX_SEPT_DUMP)
|
||||
{
|
||||
lv_task_t *task_run_dump = lv_task_create(sept_run_dump, LV_TASK_ONESHOT, LV_TASK_PRIO_MID, NULL);
|
||||
lv_task_once(task_run_dump);
|
||||
}
|
||||
else if (type == NYX_SEPT_CAL0)
|
||||
{
|
||||
lv_task_t *task_run_cal0 = lv_task_create(sept_run_cal0, LV_TASK_ONESHOT, LV_TASK_PRIO_LOWEST, NULL);
|
||||
lv_task_once(task_run_cal0);
|
||||
}
|
||||
else if (type == NYX_SEPT_EMUF)
|
||||
{
|
||||
// TODO: Maybe automatically relaunch emuMMC creation in the future.
|
||||
}
|
||||
}
|
||||
else if (nyx_str->cfg & NYX_CFG_UMS)
|
||||
{
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019-2020 CTCaer
|
||||
* Copyright (c) 2019-2021 CTCaer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
@@ -24,6 +24,7 @@
|
||||
#include <libs/fatfs/ff.h>
|
||||
#include <mem/heap.h>
|
||||
#include <storage/mbr_gpt.h>
|
||||
#include "../storage/nx_emmc_bis.h"
|
||||
#include <storage/nx_sd.h>
|
||||
#include <storage/sdmmc.h>
|
||||
#include <utils/dirlist.h>
|
||||
@@ -37,6 +38,8 @@ typedef struct _mbr_ctxt_t
|
||||
{
|
||||
u32 available;
|
||||
u32 sector[3];
|
||||
u32 resized_cnt[3];
|
||||
|
||||
int part_idx;
|
||||
u32 sector_start;
|
||||
} mbr_ctxt_t;
|
||||
@@ -49,12 +52,12 @@ static lv_res_t (*emummc_tools)(lv_obj_t *btn);
|
||||
static lv_res_t _action_emummc_window_close(lv_obj_t *btn)
|
||||
{
|
||||
lv_win_close_action(btn);
|
||||
lv_obj_del(emummc_manage_window);
|
||||
|
||||
(*emummc_tools)(NULL);
|
||||
|
||||
close_btn = NULL;
|
||||
|
||||
// Delete and relaunch main emuMMC window.
|
||||
lv_obj_del(emummc_manage_window);
|
||||
(*emummc_tools)(NULL);
|
||||
|
||||
return LV_RES_INV;
|
||||
}
|
||||
|
||||
@@ -141,7 +144,7 @@ static void _create_window_emummc()
|
||||
if (!mbr_ctx.part_idx)
|
||||
dump_emummc_file(&emmc_tool_gui_ctxt);
|
||||
else
|
||||
dump_emummc_raw(&emmc_tool_gui_ctxt, mbr_ctx.part_idx, mbr_ctx.sector_start);
|
||||
dump_emummc_raw(&emmc_tool_gui_ctxt, mbr_ctx.part_idx, mbr_ctx.sector_start, mbr_ctx.resized_cnt[mbr_ctx.part_idx - 1]);
|
||||
|
||||
nyx_window_toggle_buttons(win, false);
|
||||
}
|
||||
@@ -223,13 +226,11 @@ static void _create_mbox_emummc_raw()
|
||||
sdmmc_storage_read(&sd_storage, 0, 1, mbr);
|
||||
sd_unmount();
|
||||
|
||||
sdmmc_storage_t storage;
|
||||
sdmmc_t sdmmc;
|
||||
sdmmc_storage_init_mmc(&storage, &sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400);
|
||||
sdmmc_storage_init_mmc(&emmc_storage, &emmc_sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400);
|
||||
|
||||
u32 emmc_size_safe = storage.sec_cnt + 0xC000; // eMMC GPP size + BOOT0/1.
|
||||
u32 emmc_size_safe = emmc_storage.sec_cnt + 0xC000; // eMMC GPP size + BOOT0/1.
|
||||
|
||||
sdmmc_storage_end(&storage);
|
||||
sdmmc_storage_end(&emmc_storage);
|
||||
|
||||
for (int i = 1; i < 4; i++)
|
||||
{
|
||||
@@ -240,10 +241,22 @@ static void _create_mbox_emummc_raw()
|
||||
// Skip Linux, GPT (Android) and SFD partitions.
|
||||
bool valid_part = (part_type != 0x83) && (part_type != 0xEE) && (part_type != 0xFF);
|
||||
|
||||
if ((part_size >= emmc_size_safe) && part_start > 0x8000 && valid_part)
|
||||
// Check if at least 4GB and start above 16MB.
|
||||
if ((part_size >= 0x80F000) && part_start > 0x8000 && valid_part)
|
||||
{
|
||||
mbr_ctx.available |= (1 << (i - 1));
|
||||
mbr_ctx.available |= BIT(i - 1);
|
||||
mbr_ctx.sector[i - 1] = part_start;
|
||||
|
||||
// Only allow up to 16GB resized emuMMC.
|
||||
if (part_size <= 0x2010000)
|
||||
mbr_ctx.resized_cnt[i - 1] = part_size - 0xC000; // Save sectors count without protective size and BOOT0/1.
|
||||
else if (part_size >= emmc_size_safe)
|
||||
mbr_ctx.resized_cnt[i - 1] = 0;
|
||||
else
|
||||
{
|
||||
mbr_ctx.available &= ~BIT(i - 1);
|
||||
mbr_ctx.sector[i - 1] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -261,19 +274,21 @@ static void _create_mbox_emummc_raw()
|
||||
"#C0C0C0 Part 0: Type: %02x, Start: %08x, Size: %08x#\n"
|
||||
"#%s Part 1: Type: %02x, Start: %08x, Size: %08x#\n"
|
||||
"#%s Part 2: Type: %02x, Start: %08x, Size: %08x#\n"
|
||||
"#%s Part 3: Type: %02x, Start: %08x, Size: %08x#\n",
|
||||
"#%s Part 3: Type: %02x, Start: %08x, Size: %08x#",
|
||||
mbr->partitions[0].type, mbr->partitions[0].start_sct, mbr->partitions[0].size_sct,
|
||||
(mbr_ctx.available & 1) ? "C7EA46" : "C0C0C0",
|
||||
mbr->partitions[1].type, mbr->partitions[1].start_sct, mbr->partitions[1].size_sct,
|
||||
(mbr_ctx.available & 2) ? "C7EA46" : "C0C0C0",
|
||||
mbr->partitions[2].type, mbr->partitions[2].start_sct, mbr->partitions[2].size_sct,
|
||||
(mbr_ctx.available & 4) ? "C7EA46" : "C0C0C0",
|
||||
mbr->partitions[3].type, mbr->partitions[3].start_sct, mbr->partitions[3].size_sct);
|
||||
(mbr_ctx.available & BIT(0)) ? (mbr_ctx.resized_cnt[0] ? "FFDD00" : "C7EA46") : "C0C0C0",
|
||||
mbr->partitions[1].type, mbr->partitions[1].start_sct, mbr->partitions[1].size_sct,
|
||||
(mbr_ctx.available & BIT(1)) ? (mbr_ctx.resized_cnt[1] ? "FFDD00" : "C7EA46") : "C0C0C0",
|
||||
mbr->partitions[2].type, mbr->partitions[2].start_sct, mbr->partitions[2].size_sct,
|
||||
(mbr_ctx.available & BIT(2)) ? (mbr_ctx.resized_cnt[2] ? "FFDD00" : "C7EA46") : "C0C0C0",
|
||||
mbr->partitions[3].type, mbr->partitions[3].start_sct, mbr->partitions[3].size_sct);
|
||||
|
||||
if (mbr_ctx.resized_cnt[0] || mbr_ctx.resized_cnt[1] || mbr_ctx.resized_cnt[2])
|
||||
strcat(txt_buf, "\n\n#FFDD00 Note:# Yellow entries have USER partition resized.");
|
||||
|
||||
if (!mbr_ctx.available)
|
||||
strcat(txt_buf,
|
||||
"\n#FF8000 Do you want to partition the SD card?#\n"
|
||||
"#FF8000 (You will be asked on how to proceed)#");
|
||||
strcat(txt_buf, "\n#FF8000 Do you want to partition the SD card?#\n"
|
||||
"#FF8000 (You will be asked on how to proceed)#");
|
||||
|
||||
lv_mbox_set_text(mbox, txt_buf);
|
||||
free(txt_buf);
|
||||
@@ -365,6 +380,38 @@ static void _change_raw_emummc_part_type()
|
||||
free(mbr);
|
||||
}
|
||||
|
||||
static lv_res_t _save_emummc_cfg_mig_mbox_action(lv_obj_t *btns, const char *txt)
|
||||
{
|
||||
// Delete main emuMMC and popup windows and relaunch main emuMMC window.
|
||||
lv_obj_del(emummc_manage_window);
|
||||
mbox_action(btns, txt);
|
||||
|
||||
(*emummc_tools)(NULL);
|
||||
|
||||
return LV_RES_INV;
|
||||
}
|
||||
|
||||
static void _create_emummc_migrated_mbox()
|
||||
{
|
||||
lv_obj_t *dark_bg = lv_obj_create(lv_scr_act(), NULL);
|
||||
lv_obj_set_style(dark_bg, &mbox_darken);
|
||||
lv_obj_set_size(dark_bg, LV_HOR_RES, LV_VER_RES);
|
||||
|
||||
static const char *mbox_btn_map[] = { "\211", "OK", "\211", "" };
|
||||
lv_obj_t * mbox = lv_mbox_create(dark_bg, NULL);
|
||||
lv_mbox_set_recolor_text(mbox, true);
|
||||
lv_obj_set_width(mbox, LV_HOR_RES / 9 * 4);
|
||||
|
||||
lv_mbox_set_text(mbox,
|
||||
"#FF8000 emuMMC Configuration#\n\n"
|
||||
"#96FF00 The emuMMC configuration#\n#96FF00 was saved to sd card!#");
|
||||
|
||||
lv_mbox_add_btns(mbox, mbox_btn_map, _save_emummc_cfg_mig_mbox_action);
|
||||
|
||||
lv_obj_align(mbox, NULL, LV_ALIGN_CENTER, 0, 0);
|
||||
lv_obj_set_top(mbox, true);
|
||||
}
|
||||
|
||||
static void _migrate_sd_raw_based()
|
||||
{
|
||||
mbr_ctx.sector_start = 2;
|
||||
@@ -380,6 +427,7 @@ static void _migrate_sd_raw_based()
|
||||
f_close(&fp);
|
||||
|
||||
save_emummc_cfg(1, mbr_ctx.sector_start, "emuMMC/ER00");
|
||||
_create_emummc_migrated_mbox();
|
||||
sd_unmount();
|
||||
}
|
||||
|
||||
@@ -405,7 +453,7 @@ static void _migrate_sd_raw_emummc_based()
|
||||
_change_raw_emummc_part_type();
|
||||
|
||||
save_emummc_cfg(mbr_ctx.part_idx, mbr_ctx.sector_start, tmp);
|
||||
|
||||
_create_emummc_migrated_mbox();
|
||||
free(tmp);
|
||||
|
||||
sd_unmount();
|
||||
@@ -444,6 +492,7 @@ static void _migrate_sd_file_based()
|
||||
free(path2);
|
||||
|
||||
save_emummc_cfg(0, 0, "emuMMC/EF00");
|
||||
_create_emummc_migrated_mbox();
|
||||
sd_unmount();
|
||||
}
|
||||
|
||||
@@ -516,6 +565,7 @@ static void _migrate_sd_backup_file_based()
|
||||
free(backup_file_path);
|
||||
|
||||
save_emummc_cfg(0, 0, "emuMMC/BK00");
|
||||
_create_emummc_migrated_mbox();
|
||||
sd_unmount();
|
||||
}
|
||||
|
||||
@@ -645,41 +695,41 @@ static lv_res_t _create_emummc_migrate_action(lv_obj_t * btns, const char * txt)
|
||||
if (backup)
|
||||
{
|
||||
s_printf(txt_buf,
|
||||
"#C7EA46 Found suitable backup for emuMMC!#\n"
|
||||
"#FF8000 Do you want to migrate it?#\n\n");
|
||||
"#C7EA46 Found suitable backup for emuMMC!#\n\n"
|
||||
"#FF8000 Do you want to migrate it?#\n");
|
||||
lv_mbox_add_btns(mbox, mbox_btn_map, _create_emummc_mig4_action);
|
||||
}
|
||||
else if (emummc)
|
||||
{
|
||||
s_printf(txt_buf,
|
||||
"#C7EA46 Found SD Partition based emuMMC!#\n"
|
||||
"#FF8000 Do you want to repair the config for it?#\n\n");
|
||||
"#C7EA46 Found SD Partition based emuMMC!#\n\n"
|
||||
"#FF8000 Do you want to repair the config for it?#\n");
|
||||
lv_mbox_add_btns(mbox, mbox_btn_map, _create_emummc_mig3_action);
|
||||
}
|
||||
else if (em_raw && em_file)
|
||||
{
|
||||
s_printf(txt_buf,
|
||||
"#C7EA46 Found both foreign SD File and Partition emunand!#\n"
|
||||
"#FF8000 Choose what to migrate:#\n\n");
|
||||
"#C7EA46 Found both foreign SD File and Partition emunand!#\n\n"
|
||||
"#FF8000 Choose what to migrate:#\n");
|
||||
lv_mbox_add_btns(mbox, mbox_btn_map1, _create_emummc_mig1_action);
|
||||
}
|
||||
else if (em_raw)
|
||||
{
|
||||
s_printf(txt_buf,
|
||||
"#C7EA46 Found foreign SD Partition emunand!#\n"
|
||||
"#FF8000 Do you want to migrate it?#\n\n");
|
||||
"#C7EA46 Found foreign SD Partition emunand!#\n\n"
|
||||
"#FF8000 Do you want to migrate it?#\n");
|
||||
lv_mbox_add_btns(mbox, mbox_btn_map, _create_emummc_mig2_action);
|
||||
}
|
||||
else if (em_file)
|
||||
{
|
||||
s_printf(txt_buf,
|
||||
"#C7EA46 Found foreign SD File emunand!#\n"
|
||||
"#FF8000 Do you want to migrate it?#\n\n");
|
||||
"#C7EA46 Found foreign SD File emunand!#\n\n"
|
||||
"#FF8000 Do you want to migrate it?#\n");
|
||||
lv_mbox_add_btns(mbox, mbox_btn_map, _create_emummc_mig0_action);
|
||||
}
|
||||
else
|
||||
{
|
||||
s_printf(txt_buf, "No emuMMC or foreign emunand found!\n\n");
|
||||
s_printf(txt_buf, "No emuMMC or foreign emunand found!\n");
|
||||
lv_mbox_add_btns(mbox, mbox_btn_map3, mbox_action);
|
||||
}
|
||||
|
||||
@@ -727,9 +777,7 @@ static lv_res_t _create_mbox_emummc_migrate(lv_obj_t *btn)
|
||||
sd_mount();
|
||||
sdmmc_storage_read(&sd_storage, 0, 1, mbr);
|
||||
|
||||
sdmmc_storage_t storage;
|
||||
sdmmc_t sdmmc;
|
||||
sdmmc_storage_init_mmc(&storage, &sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400);
|
||||
sdmmc_storage_init_mmc(&emmc_storage, &emmc_sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400);
|
||||
|
||||
em_raw = false;
|
||||
em_file = false;
|
||||
@@ -778,22 +826,22 @@ static lv_res_t _create_mbox_emummc_migrate(lv_obj_t *btn)
|
||||
if(!f_stat(path_buf, NULL))
|
||||
em_file = true;
|
||||
|
||||
emmcsn_path_impl(path_buf, "", "BOOT0", &storage);
|
||||
emmcsn_path_impl(path_buf, "", "BOOT0", &emmc_storage);
|
||||
if(!f_stat(path_buf, NULL))
|
||||
backup = true;
|
||||
|
||||
emmcsn_path_impl(path_buf, "", "rawnand.bin", &storage);
|
||||
emmcsn_path_impl(path_buf, "", "rawnand.bin", &emmc_storage);
|
||||
if(!f_stat(path_buf, NULL))
|
||||
rawnand_backup = true;
|
||||
|
||||
emmcsn_path_impl(path_buf, "", "rawnand.bin.00", &storage);
|
||||
emmcsn_path_impl(path_buf, "", "rawnand.bin.00", &emmc_storage);
|
||||
if(!f_stat(path_buf, NULL))
|
||||
rawnand_backup = true;
|
||||
|
||||
backup = backup && rawnand_backup;
|
||||
|
||||
sd_unmount();
|
||||
sdmmc_storage_end(&storage);
|
||||
sdmmc_storage_end(&emmc_storage);
|
||||
|
||||
// Check available types and enable the corresponding buttons.
|
||||
if (backup)
|
||||
@@ -825,6 +873,7 @@ static emummc_images_t *emummc_img;
|
||||
|
||||
static lv_res_t _save_emummc_cfg_mbox_action(lv_obj_t *btns, const char *txt)
|
||||
{
|
||||
// Free components, delete main emuMMC and popup windows and relaunch main emuMMC window.
|
||||
free(emummc_img->dirlist);
|
||||
lv_obj_del(emummc_img->win);
|
||||
lv_obj_del(emummc_manage_window);
|
||||
@@ -1121,8 +1170,9 @@ out1:
|
||||
lv_res_t create_win_emummc_tools(lv_obj_t *btn)
|
||||
{
|
||||
lv_obj_t *win = nyx_create_standard_window(SYMBOL_EDIT" emuMMC Manage");
|
||||
emummc_manage_window = win;
|
||||
|
||||
// Set resources to be managed by other windows.
|
||||
emummc_manage_window = win;
|
||||
emummc_tools = (void *)create_win_emummc_tools;
|
||||
|
||||
sd_mount();
|
||||
@@ -1246,7 +1296,6 @@ lv_res_t create_win_emummc_tools(lv_obj_t *btn)
|
||||
lv_obj_set_style(label_txt4, &hint_small_style);
|
||||
lv_obj_align(label_txt4, btn3, LV_ALIGN_OUT_BOTTOM_LEFT, 0, LV_DPI / 3);
|
||||
|
||||
//! TODO: Move it to a window with multiple choices.
|
||||
// Create Migrate emuMMC button.
|
||||
lv_obj_t *btn4 = lv_btn_create(h2, btn2);
|
||||
label_btn = lv_label_create(btn4, NULL);
|
||||
@@ -1260,8 +1309,6 @@ lv_res_t create_win_emummc_tools(lv_obj_t *btn)
|
||||
lv_label_set_static_text(label_txt4,
|
||||
"Migrate a backup to a #C7EA46 SD File# or repair existing #C7EA46 SD Raw Partition#.\n"
|
||||
"Additionally it allows you to migrate from other emunand\nsolutions.");
|
||||
//"Move between #C7EA46 SD File# and #C7EA46 SD Raw Partition# emuMMC.\n"
|
||||
//"Additionally it allows you to migrate from other emunand\nsolutions.");
|
||||
lv_obj_set_style(label_txt4, &hint_small_style);
|
||||
lv_obj_align(label_txt4, btn4, LV_ALIGN_OUT_BOTTOM_LEFT, 0, LV_DPI / 3);
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2018-2020 CTCaer
|
||||
* Copyright (c) 2018-2021 CTCaer
|
||||
* Copyright (c) 2018 balika011
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
@@ -269,7 +269,7 @@ static lv_res_t _tsec_keys_dump_window_action(lv_obj_t * btn)
|
||||
{
|
||||
char path[64];
|
||||
emmcsn_path_impl(path, "/dumps", "tsec_keys.bin", NULL);
|
||||
error = sd_save_to_file(tsec_keys, 0x10 * 2, path);
|
||||
error = sd_save_to_file(tsec_keys, SE_KEY_128_SIZE * 2, path);
|
||||
|
||||
sd_unmount();
|
||||
}
|
||||
@@ -312,7 +312,13 @@ static lv_res_t _create_mbox_cal0(lv_obj_t *btn)
|
||||
u32 bootloader_offset = BOOTLOADER_MAIN_OFFSET;
|
||||
u32 pk1_offset = h_cfg.t210b01 ? sizeof(bl_hdr_t210b01_t) : 0; // Skip T210B01 OEM header.
|
||||
u8 *pkg1 = (u8 *)malloc(BOOTLOADER_SIZE);
|
||||
sdmmc_storage_init_mmc(&emmc_storage, &emmc_sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400);
|
||||
|
||||
if (!sdmmc_storage_init_mmc(&emmc_storage, &emmc_sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400))
|
||||
{
|
||||
lv_label_set_text(lb_desc, "#FFDD00 Failed to init eMMC!#");
|
||||
|
||||
goto out;
|
||||
}
|
||||
sdmmc_storage_set_mmc_partition(&emmc_storage, EMMC_BOOT0);
|
||||
|
||||
try_load:
|
||||
@@ -326,7 +332,7 @@ try_load:
|
||||
|
||||
if (!pkg1_id)
|
||||
{
|
||||
strcat(txt_buf, "#FFDD00 Unknown pkg1 version for reading#\n#FFDD00 TSEC firmware!#\n");
|
||||
strcat(txt_buf, "#FFDD00 Unknown pkg1 version!#\n");
|
||||
// Try backup bootloader.
|
||||
if (bootloader_offset != BOOTLOADER_BACKUP_OFFSET)
|
||||
{
|
||||
@@ -363,9 +369,23 @@ try_load:
|
||||
h_cfg.sept_run = true;
|
||||
else
|
||||
{
|
||||
// Check that BCT is proper so sept can run.
|
||||
u8 *bct_bldr = (u8 *)calloc(1, 512);
|
||||
sdmmc_storage_read(&emmc_storage, 0x2200 / NX_EMMC_BLOCKSIZE, 1, bct_bldr);
|
||||
u32 bootloader_entrypoint = *(u32 *)&bct_bldr[0x144];
|
||||
free(bct_bldr);
|
||||
if (bootloader_entrypoint > SEPT_PRI_ENTRY)
|
||||
{
|
||||
lv_label_set_text(lb_desc, "#FFDD00 Main BCT is improper! Failed to run sept.#\n"
|
||||
"#FFDD00 Run sept with proper BCT at least once#\n#FFDD00 to cache keys.#\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
// Set boot cfg.
|
||||
b_cfg->autoboot = 0;
|
||||
b_cfg->autoboot_list = 0;
|
||||
b_cfg->extra_cfg = EXTRA_CFG_NYX_BIS;
|
||||
b_cfg->extra_cfg = EXTRA_CFG_NYX_SEPT;
|
||||
b_cfg->sept = NYX_SEPT_CAL0;
|
||||
|
||||
if (!reboot_to_sept((u8 *)tsec_ctxt.fw, kb))
|
||||
{
|
||||
@@ -393,10 +413,12 @@ t210b01:;
|
||||
LIST_INIT(gpt);
|
||||
nx_emmc_gpt_parse(&gpt, &emmc_storage);
|
||||
emmc_part_t *cal0_part = nx_emmc_part_find(&gpt, "PRODINFO"); // check if null
|
||||
nx_emmc_bis_init(cal0_part);
|
||||
nx_emmc_bis_init(cal0_part, false, 0);
|
||||
nx_emmc_bis_read(0, 0x40, cal0_buf);
|
||||
nx_emmc_bis_end();
|
||||
nx_emmc_gpt_free(&gpt);
|
||||
|
||||
// Clear BIS keys slots.
|
||||
// Clear BIS keys slots and reinstate SBK.
|
||||
hos_bis_keys_clear();
|
||||
|
||||
nx_emmc_cal0_t *cal0 = (nx_emmc_cal0_t *)cal0_buf;
|
||||
@@ -1090,7 +1112,7 @@ try_load:
|
||||
|
||||
if (!pkg1_id)
|
||||
{
|
||||
strcat(txt_buf, "#FFDD00 Unknown pkg1 version for reading#\n#FFDD00 TSEC firmware!#\n");
|
||||
strcat(txt_buf, "#FFDD00 Unknown pkg1 version!#\n");
|
||||
// Try backup bootloader.
|
||||
if (bootloader_offset != BOOTLOADER_BACKUP_OFFSET)
|
||||
{
|
||||
@@ -1192,8 +1214,6 @@ out:
|
||||
|
||||
static lv_res_t _create_mbox_benchmark(bool sd_bench)
|
||||
{
|
||||
sdmmc_t emmc_sdmmc;
|
||||
sdmmc_storage_t emmc_storage;
|
||||
sdmmc_storage_t *storage;
|
||||
|
||||
lv_obj_t *dark_bg = lv_obj_create(lv_scr_act(), NULL);
|
||||
@@ -1203,16 +1223,28 @@ static lv_res_t _create_mbox_benchmark(bool sd_bench)
|
||||
static const char * mbox_btn_map[] = { "\211", "\222OK", "\211", "" };
|
||||
lv_obj_t * mbox = lv_mbox_create(dark_bg, NULL);
|
||||
lv_mbox_set_recolor_text(mbox, true);
|
||||
lv_obj_set_width(mbox, LV_HOR_RES / 7 * 5);
|
||||
lv_obj_set_width(mbox, LV_HOR_RES / 7 * 4);
|
||||
|
||||
char *txt_buf = (char *)malloc(0x1000);
|
||||
char *txt_buf = (char *)malloc(0x4000);
|
||||
|
||||
s_printf(txt_buf, "#FF8000 %s Benchmark#\n[3 x %s raw reads] Abort: VOL- & VOL+\n",
|
||||
sd_bench ? "SD Card" : "eMMC", sd_bench ? "2GB" : "8GB");
|
||||
s_printf(txt_buf, "#FF8000 %s Benchmark#\n[Raw Reads] Abort: VOL- & VOL+",
|
||||
sd_bench ? "SD Card" : "eMMC");
|
||||
|
||||
lv_mbox_set_text(mbox, txt_buf);
|
||||
txt_buf[0] = 0;
|
||||
|
||||
lv_obj_t * bar = lv_bar_create(mbox, NULL);
|
||||
lv_obj_t *h1 = lv_cont_create(mbox, NULL);
|
||||
lv_cont_set_fit(h1, false, true);
|
||||
lv_cont_set_style(h1, &lv_style_transp_tight);
|
||||
lv_obj_set_width(h1, lv_obj_get_width(mbox) - LV_DPI / 10);
|
||||
|
||||
lv_obj_t *lbl_status = lv_label_create(h1, NULL);
|
||||
lv_label_set_style(lbl_status, &monospace_text);
|
||||
lv_label_set_recolor(lbl_status, true);
|
||||
lv_label_set_text(lbl_status, " ");
|
||||
lv_obj_align(lbl_status, h1, LV_ALIGN_IN_TOP_MID, 0, 0);
|
||||
|
||||
lv_obj_t *bar = lv_bar_create(mbox, NULL);
|
||||
lv_obj_set_size(bar, LV_DPI * 2, LV_DPI / 5);
|
||||
lv_bar_set_range(bar, 0, 100);
|
||||
lv_bar_set_value(bar, 0);
|
||||
@@ -1241,9 +1273,7 @@ static lv_res_t _create_mbox_benchmark(bool sd_bench)
|
||||
else
|
||||
{
|
||||
u32 iters = 3;
|
||||
u32 sector_num = 0x8000;
|
||||
u32 data_scts = sd_bench ? 0x400000 : 0x1000000; // SD 2GB or eMMC 8GB.
|
||||
u32 offset_chunk_start = ALIGN_DOWN(storage->sec_cnt / 3, sector_num);
|
||||
u32 offset_chunk_start = ALIGN_DOWN(storage->sec_cnt / 3, 0x8000); // Align to 16MB.
|
||||
if (storage->sec_cnt < 0xC00000)
|
||||
iters -= 2; // 4GB card.
|
||||
|
||||
@@ -1251,24 +1281,26 @@ static lv_res_t _create_mbox_benchmark(bool sd_bench)
|
||||
{
|
||||
u32 pct = 0;
|
||||
u32 prevPct = 200;
|
||||
u32 timer = 0;
|
||||
u32 lba_curr = 0;
|
||||
u32 sector = offset_chunk_start * iter_curr;
|
||||
u32 data_remaining = data_scts;
|
||||
u32 sector_num = 0x8000; // 16MB chunks.
|
||||
u32 data_remaining = 0x200000; // 1GB.
|
||||
|
||||
u32 timer = get_tmr_ms();
|
||||
|
||||
strcat(txt_buf, "\n");
|
||||
lv_mbox_set_text(mbox, txt_buf);
|
||||
s_printf(txt_buf + strlen(txt_buf), "#C7EA46 %d/3# - Sector Offset #C7EA46 %08X#:\n", iter_curr + 1, sector);
|
||||
|
||||
while (data_remaining)
|
||||
{
|
||||
// Read 16MB chunks.
|
||||
u32 time_taken = get_tmr_us();
|
||||
sdmmc_storage_read(storage, sector + lba_curr, sector_num, (u8 *)MIXD_BUF_ALIGNED);
|
||||
time_taken = get_tmr_us() - time_taken;
|
||||
timer += time_taken;
|
||||
|
||||
manual_system_maintenance(false);
|
||||
data_remaining -= sector_num;
|
||||
lba_curr += sector_num;
|
||||
|
||||
pct = (lba_curr * 100) / data_scts;
|
||||
pct = (lba_curr * 100) / 0x200000;
|
||||
if (pct != prevPct)
|
||||
{
|
||||
lv_bar_set_value(bar, pct);
|
||||
@@ -1280,17 +1312,115 @@ static lv_res_t _create_mbox_benchmark(bool sd_bench)
|
||||
break;
|
||||
}
|
||||
}
|
||||
timer = get_tmr_ms() - timer;
|
||||
timer -= sd_bench ? 175 : 185; // Compensate 175ms/185ms for maintenance/drawing/calc ops.
|
||||
|
||||
lv_bar_set_value(bar, 100);
|
||||
u32 rate_1k = (sd_bench ? (2048 * 1000 * 1000) : (u64)((u64)8192 * 1000 * 1000)) / timer;
|
||||
|
||||
u32 rate_1k = ((u64)1024 * 1000 * 1000 * 1000) / timer;
|
||||
s_printf(txt_buf + strlen(txt_buf),
|
||||
"#C7EA46 %d#: Offset: #C7EA46 %08X#, Time: #C7EA46 %d.%02ds#, Rate: #C7EA46 %d.%02d MB/s#",
|
||||
iter_curr, sector, timer / 1000, (timer % 1000) / 10, rate_1k / 1000, (rate_1k % 1000) / 10);
|
||||
lv_mbox_set_text(mbox, txt_buf);
|
||||
" Sequential 16MiB - Rate: #C7EA46 %3d.%02d MiB/s#\n",
|
||||
rate_1k / 1000, (rate_1k % 1000) / 10);
|
||||
lv_label_set_text(lbl_status, txt_buf);
|
||||
lv_obj_align(lbl_status, NULL, LV_ALIGN_CENTER, 0, 0);
|
||||
lv_obj_align(mbox, NULL, LV_ALIGN_CENTER, 0, 0);
|
||||
manual_system_maintenance(true);
|
||||
|
||||
pct = 0;
|
||||
prevPct = 200;
|
||||
timer = 0;
|
||||
lba_curr = 0;
|
||||
sector_num = 8; // 4KB chunks.
|
||||
data_remaining = 0x100000; // 512MB.
|
||||
|
||||
while (data_remaining)
|
||||
{
|
||||
u32 time_taken = get_tmr_us();
|
||||
sdmmc_storage_read(storage, sector + lba_curr, sector_num, (u8 *)MIXD_BUF_ALIGNED);
|
||||
time_taken = get_tmr_us() - time_taken;
|
||||
timer += time_taken;
|
||||
|
||||
manual_system_maintenance(false);
|
||||
data_remaining -= sector_num;
|
||||
lba_curr += sector_num;
|
||||
|
||||
pct = (lba_curr * 100) / 0x100000;
|
||||
if (pct != prevPct)
|
||||
{
|
||||
lv_bar_set_value(bar, pct);
|
||||
manual_system_maintenance(true);
|
||||
|
||||
prevPct = pct;
|
||||
|
||||
if (btn_read_vol() == (BTN_VOL_UP | BTN_VOL_DOWN))
|
||||
break;
|
||||
}
|
||||
}
|
||||
lv_bar_set_value(bar, 100);
|
||||
|
||||
rate_1k = ((u64)512 * 1000 * 1000 * 1000) / timer;
|
||||
u32 iops_1k = ((u64)512 * 1024 * 1000 * 1000 * 1000) / (4096 / 1024) / timer / 1000;
|
||||
s_printf(txt_buf + strlen(txt_buf),
|
||||
" Sequential 4KiB - Rate: #C7EA46 %3d.%02d MiB/s#, IOPS: #C7EA46 %4d#\n",
|
||||
rate_1k / 1000, (rate_1k % 1000) / 10, iops_1k);
|
||||
lv_label_set_text(lbl_status, txt_buf);
|
||||
lv_obj_align(lbl_status, NULL, LV_ALIGN_CENTER, 0, 0);
|
||||
lv_obj_align(mbox, NULL, LV_ALIGN_CENTER, 0, 0);
|
||||
manual_system_maintenance(true);
|
||||
|
||||
u32 lba_idx = 0;
|
||||
u32 *random_offsets = malloc(0x20000 * sizeof(u32));
|
||||
u32 random_numbers[4];
|
||||
for (u32 i = 0; i < 0x20000; i += 4)
|
||||
{
|
||||
// Generate new random numbers.
|
||||
while (!se_gen_prng128(random_numbers))
|
||||
;
|
||||
// Clamp offsets to 512MBrange.
|
||||
random_offsets[i + 0] = random_numbers[0] % 0x100000;
|
||||
random_offsets[i + 1] = random_numbers[1] % 0x100000;
|
||||
random_offsets[i + 2] = random_numbers[2] % 0x100000;
|
||||
random_offsets[i + 3] = random_numbers[3] % 0x100000;
|
||||
}
|
||||
|
||||
pct = 0;
|
||||
prevPct = 200;
|
||||
timer = 0;
|
||||
data_remaining = 0x100000; // 512MB.
|
||||
|
||||
while (data_remaining)
|
||||
{
|
||||
u32 time_taken = get_tmr_us();
|
||||
sdmmc_storage_read(storage, sector + random_offsets[lba_idx], sector_num, (u8 *)MIXD_BUF_ALIGNED);
|
||||
time_taken = get_tmr_us() - time_taken;
|
||||
timer += time_taken;
|
||||
|
||||
manual_system_maintenance(false);
|
||||
data_remaining -= sector_num;
|
||||
lba_idx++;
|
||||
|
||||
pct = (lba_idx * 100) / 0x20000;
|
||||
if (pct != prevPct)
|
||||
{
|
||||
lv_bar_set_value(bar, pct);
|
||||
manual_system_maintenance(true);
|
||||
|
||||
prevPct = pct;
|
||||
|
||||
if (btn_read_vol() == (BTN_VOL_UP | BTN_VOL_DOWN))
|
||||
break;
|
||||
}
|
||||
}
|
||||
lv_bar_set_value(bar, 100);
|
||||
|
||||
// Calculate rate and IOPS for 512MB transfer.
|
||||
rate_1k = ((u64)512 * 1000 * 1000 * 1000) / timer;
|
||||
iops_1k = ((u64)512 * 1024 * 1000 * 1000 * 1000) / (4096 / 1024) / timer / 1000;
|
||||
s_printf(txt_buf + strlen(txt_buf),
|
||||
" Random 4KiB - Rate: #C7EA46 %3d.%02d MiB/s#, IOPS: #C7EA46 %4d#\n",
|
||||
rate_1k / 1000, (rate_1k % 1000) / 10, iops_1k);
|
||||
lv_label_set_text(lbl_status, txt_buf);
|
||||
lv_obj_align(lbl_status, NULL, LV_ALIGN_CENTER, 0, 0);
|
||||
lv_obj_align(mbox, NULL, LV_ALIGN_CENTER, 0, 0);
|
||||
manual_system_maintenance(true);
|
||||
free(random_offsets);
|
||||
}
|
||||
|
||||
lv_obj_del(bar);
|
||||
@@ -1300,8 +1430,10 @@ static lv_res_t _create_mbox_benchmark(bool sd_bench)
|
||||
else
|
||||
sdmmc_storage_end(&emmc_storage);
|
||||
}
|
||||
free(txt_buf);
|
||||
|
||||
lv_mbox_add_btns(mbox, mbox_btn_map, mbox_action); // Important. After set_text.
|
||||
lv_obj_align(mbox, NULL, LV_ALIGN_CENTER, 0, 0);
|
||||
|
||||
return LV_RES_OK;
|
||||
}
|
||||
@@ -1332,14 +1464,11 @@ static lv_res_t _create_window_emmc_info_status(lv_obj_t *btn)
|
||||
lv_label_set_long_mode(lb_desc, LV_LABEL_LONG_BREAK);
|
||||
lv_label_set_recolor(lb_desc, true);
|
||||
|
||||
sdmmc_storage_t storage;
|
||||
sdmmc_t sdmmc;
|
||||
|
||||
char *txt_buf = (char *)malloc(0x4000);
|
||||
txt_buf[0] = '\n';
|
||||
txt_buf[1] = 0;
|
||||
|
||||
if (!sdmmc_storage_init_mmc(&storage, &sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400))
|
||||
if (!sdmmc_storage_init_mmc(&emmc_storage, &emmc_sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400))
|
||||
{
|
||||
lv_label_set_text(lb_desc, "#FFDD00 Failed to init eMMC!#");
|
||||
lv_obj_set_width(lb_desc, lv_obj_get_width(desc));
|
||||
@@ -1350,14 +1479,15 @@ static lv_res_t _create_window_emmc_info_status(lv_obj_t *btn)
|
||||
char *rsvd_blocks;
|
||||
char life_a_txt[8];
|
||||
char life_b_txt[8];
|
||||
u32 life_a = storage.ext_csd.dev_life_est_a;
|
||||
u32 life_b = storage.ext_csd.dev_life_est_b;
|
||||
u16 card_type = storage.ext_csd.card_type;
|
||||
u32 cache = emmc_storage.ext_csd.cache_size;
|
||||
u32 life_a = emmc_storage.ext_csd.dev_life_est_a;
|
||||
u32 life_b = emmc_storage.ext_csd.dev_life_est_b;
|
||||
u16 card_type = emmc_storage.ext_csd.card_type;
|
||||
char card_type_support[96];
|
||||
card_type_support[0] = 0;
|
||||
|
||||
// Identify manufacturer. Only official eMMCs.
|
||||
switch (storage.cid.manfid)
|
||||
switch (emmc_storage.cid.manfid)
|
||||
{
|
||||
case 0x11:
|
||||
strcat(txt_buf, "Toshiba ");
|
||||
@@ -1365,16 +1495,20 @@ static lv_res_t _create_window_emmc_info_status(lv_obj_t *btn)
|
||||
case 0x15:
|
||||
strcat(txt_buf, "Samsung ");
|
||||
break;
|
||||
case 0x45: // Unofficial.
|
||||
strcat(txt_buf, "SanDisk ");
|
||||
break;
|
||||
case 0x90:
|
||||
strcat(txt_buf, "SK Hynix ");
|
||||
break;
|
||||
}
|
||||
|
||||
s_printf(txt_buf + strlen(txt_buf), "(%02X)\n%X\n%02X\n%c%c%c%c%c%c\n%X\n%04X\n%02d/%04d\n\n",
|
||||
storage.cid.manfid, storage.cid.card_bga, storage.cid.oemid,
|
||||
storage.cid.prod_name[0], storage.cid.prod_name[1], storage.cid.prod_name[2],
|
||||
storage.cid.prod_name[3], storage.cid.prod_name[4], storage.cid.prod_name[5],
|
||||
storage.cid.prv, storage.cid.serial, storage.cid.month, storage.cid.year);
|
||||
s_printf(txt_buf + strlen(txt_buf), "(%02X)\n%c%c%c%c%c%c\n%d.%d\n%04X\n%02d/%04d\n\n",
|
||||
emmc_storage.cid.manfid,
|
||||
emmc_storage.cid.prod_name[0], emmc_storage.cid.prod_name[1], emmc_storage.cid.prod_name[2],
|
||||
emmc_storage.cid.prod_name[3], emmc_storage.cid.prod_name[4], emmc_storage.cid.prod_name[5],
|
||||
emmc_storage.cid.prv & 0xF, emmc_storage.cid.prv >> 4,
|
||||
emmc_storage.cid.serial, emmc_storage.cid.month, emmc_storage.cid.year);
|
||||
|
||||
if (card_type & EXT_CSD_CARD_TYPE_HS_26)
|
||||
{
|
||||
@@ -1406,7 +1540,7 @@ static lv_res_t _create_window_emmc_info_status(lv_obj_t *btn)
|
||||
strcpy(life_b_txt, "-");
|
||||
|
||||
// Normalize cells life.
|
||||
if (life_a)
|
||||
if (life_a) // SK Hynix is 0 (undefined).
|
||||
{
|
||||
life_a--;
|
||||
life_a = (10 - life_a) * 10;
|
||||
@@ -1420,7 +1554,7 @@ static lv_res_t _create_window_emmc_info_status(lv_obj_t *btn)
|
||||
s_printf(life_b_txt, "%d%%", life_b);
|
||||
}
|
||||
|
||||
switch (storage.ext_csd.pre_eol_info)
|
||||
switch (emmc_storage.ext_csd.pre_eol_info)
|
||||
{
|
||||
case 1:
|
||||
rsvd_blocks = "Normal (< 80%)";
|
||||
@@ -1429,7 +1563,7 @@ static lv_res_t _create_window_emmc_info_status(lv_obj_t *btn)
|
||||
rsvd_blocks = "Warning (> 80%)";
|
||||
break;
|
||||
case 3:
|
||||
rsvd_blocks = "Urgent (> 90%)";
|
||||
rsvd_blocks = "Critical (> 90%)";
|
||||
break;
|
||||
default:
|
||||
rsvd_blocks = "#FF8000 Unknown#";
|
||||
@@ -1437,25 +1571,28 @@ static lv_res_t _create_window_emmc_info_status(lv_obj_t *btn)
|
||||
}
|
||||
|
||||
s_printf(txt_buf + strlen(txt_buf),
|
||||
"#00DDFF V1.%d (rev 1.%d)#\n%02X\n%d MB/s (%d MHz)\n%d MB/s\n%s\nA: %s, B: %s\n%s",
|
||||
storage.ext_csd.ext_struct, storage.ext_csd.rev,
|
||||
storage.csd.cmdclass, speed & 0xFFFF, (speed >> 16) & 0xFFFF,
|
||||
storage.csd.busspeed, card_type_support, life_a_txt, life_b_txt, rsvd_blocks);
|
||||
"#00DDFF V1.%d (rev 1.%d)#\n%02X\n%d MB/s (%d MHz)\n%d MB/s\n%s\n%d %s\n%d MiB\nA: %s, B: %s\n%s",
|
||||
emmc_storage.ext_csd.ext_struct, emmc_storage.ext_csd.rev,
|
||||
emmc_storage.csd.cmdclass, speed & 0xFFFF, (speed >> 16) & 0xFFFF,
|
||||
emmc_storage.csd.busspeed, card_type_support,
|
||||
!(cache % 1024) ? (cache / 1024) : cache, !(cache % 1024) ? "MiB" : "KiB",
|
||||
emmc_storage.ext_csd.max_enh_mult * 512 / 1024,
|
||||
life_a_txt, life_b_txt, rsvd_blocks);
|
||||
|
||||
lv_label_set_static_text(lb_desc,
|
||||
"#00DDFF CID:#\n"
|
||||
"Vendor ID:\n"
|
||||
"Card/BGA:\n"
|
||||
"OEM ID:\n"
|
||||
"Model:\n"
|
||||
"Prd Rev:\n"
|
||||
"Prod Rev:\n"
|
||||
"S/N:\n"
|
||||
"Month/Year:\n\n"
|
||||
"#00DDFF Ext CSD#\n"
|
||||
"#00DDFF Ext CSD:#\n"
|
||||
"Cmd Classes:\n"
|
||||
"Max Rate:\n"
|
||||
"Current Rate:\n"
|
||||
"Type Support:\n\n"
|
||||
"Write Cache:\n"
|
||||
"Enhanced Area:\n"
|
||||
"Estimated Life:\n"
|
||||
"Reserved Used:"
|
||||
);
|
||||
@@ -1477,32 +1614,32 @@ static lv_res_t _create_window_emmc_info_status(lv_obj_t *btn)
|
||||
lv_obj_t * lb_desc2 = lv_label_create(desc2, lb_desc);
|
||||
lv_label_set_style(lb_desc2, &monospace_text);
|
||||
|
||||
u32 boot_size = storage.ext_csd.boot_mult << 17;
|
||||
u32 rpmb_size = storage.ext_csd.rpmb_mult << 17;
|
||||
s_printf(txt_buf, "#00DDFF eMMC Physical Partitions:#\n");
|
||||
s_printf(txt_buf + strlen(txt_buf), "1: #96FF00 BOOT0# Size: %5d KiB (Sect: 0x%08X)\n", boot_size / 1024, boot_size / 512);
|
||||
s_printf(txt_buf + strlen(txt_buf), "2: #96FF00 BOOT1# Size: %5d KiB (Sect: 0x%08X)\n", boot_size / 1024, boot_size / 512);
|
||||
s_printf(txt_buf + strlen(txt_buf), "3: #96FF00 RPMB# Size: %5d KiB (Sect: 0x%08X)\n", rpmb_size / 1024, rpmb_size / 512);
|
||||
s_printf(txt_buf + strlen(txt_buf), "0: #96FF00 GPP# Size: %5d MiB (Sect: 0x%08X)\n\n", storage.sec_cnt >> SECTORS_TO_MIB_COEFF, storage.sec_cnt);
|
||||
s_printf(txt_buf + strlen(txt_buf), "#00DDFF GPP (eMMC USER) Partition Table:#\n");
|
||||
u32 boot_size = emmc_storage.ext_csd.boot_mult << 17;
|
||||
u32 rpmb_size = emmc_storage.ext_csd.rpmb_mult << 17;
|
||||
strcpy(txt_buf, "#00DDFF eMMC Physical Partitions:#\n");
|
||||
s_printf(txt_buf + strlen(txt_buf), "1: #96FF00 BOOT0# Size: %6d KiB (Sect: 0x%08X)\n", boot_size / 1024, boot_size / 512);
|
||||
s_printf(txt_buf + strlen(txt_buf), "2: #96FF00 BOOT1# Size: %6d KiB (Sect: 0x%08X)\n", boot_size / 1024, boot_size / 512);
|
||||
s_printf(txt_buf + strlen(txt_buf), "3: #96FF00 RPMB# Size: %6d KiB (Sect: 0x%08X)\n", rpmb_size / 1024, rpmb_size / 512);
|
||||
s_printf(txt_buf + strlen(txt_buf), "0: #96FF00 GPP# Size: %6d MiB (Sect: 0x%08X)\n", emmc_storage.sec_cnt >> SECTORS_TO_MIB_COEFF, emmc_storage.sec_cnt);
|
||||
strcat(txt_buf, "\n#00DDFF GPP (eMMC USER) Partition Table:#\n");
|
||||
|
||||
sdmmc_storage_set_mmc_partition(&storage, EMMC_GPP);
|
||||
sdmmc_storage_set_mmc_partition(&emmc_storage, EMMC_GPP);
|
||||
LIST_INIT(gpt);
|
||||
nx_emmc_gpt_parse(&gpt, &storage);
|
||||
nx_emmc_gpt_parse(&gpt, &emmc_storage);
|
||||
|
||||
u32 idx = 0;
|
||||
LIST_FOREACH_ENTRY(emmc_part_t, part, &gpt, link)
|
||||
{
|
||||
if (idx > 10)
|
||||
{
|
||||
strcat(txt_buf, "#FFDD00 Table truncated!#");
|
||||
strcat(txt_buf, "#FFDD00 Table does not fit on screen!#");
|
||||
break;
|
||||
}
|
||||
|
||||
if (part->index < 2)
|
||||
{
|
||||
s_printf(txt_buf + strlen(txt_buf), "%02d: #96FF00 %s# ", part->index, part->name);
|
||||
s_printf(txt_buf + strlen(txt_buf), " Size: %d MiB (Sect: 0x%X), Start: %06X\n",
|
||||
s_printf(txt_buf + strlen(txt_buf), "%02d: #96FF00 %s#%s Size: %d MiB (Sect: 0x%X), Start: %06X\n",
|
||||
part->index, part->name, !part->name[8] ? " " : "",
|
||||
(part->lba_end - part->lba_start + 1) >> SECTORS_TO_MIB_COEFF,
|
||||
part->lba_end - part->lba_start + 1, part->lba_start);
|
||||
}
|
||||
@@ -1515,6 +1652,9 @@ static lv_res_t _create_window_emmc_info_status(lv_obj_t *btn)
|
||||
|
||||
idx++;
|
||||
}
|
||||
if (!idx)
|
||||
strcat(txt_buf, "#FFDD00 Partition table is empty!#");
|
||||
|
||||
nx_emmc_gpt_free(&gpt);
|
||||
|
||||
lv_label_set_text(lb_desc2, txt_buf);
|
||||
@@ -1522,7 +1662,7 @@ static lv_res_t _create_window_emmc_info_status(lv_obj_t *btn)
|
||||
lv_obj_align(desc2, val, LV_ALIGN_OUT_RIGHT_MID, LV_DPI / 6, 0);
|
||||
}
|
||||
|
||||
sdmmc_storage_end(&storage);
|
||||
sdmmc_storage_end(&emmc_storage);
|
||||
free(txt_buf);
|
||||
|
||||
return LV_RES_OK;
|
||||
@@ -1555,8 +1695,8 @@ static lv_res_t _create_window_sdcard_info_status(lv_obj_t *btn)
|
||||
lv_label_set_text(lb_desc,
|
||||
"#00DDFF Card IDentification:#\n"
|
||||
"Vendor ID:\n"
|
||||
"OEM ID:\n"
|
||||
"Model:\n"
|
||||
"OEM ID:\n"
|
||||
"HW rev:\n"
|
||||
"FW rev:\n"
|
||||
"S/N:\n"
|
||||
@@ -1614,10 +1754,11 @@ static lv_res_t _create_window_sdcard_info_status(lv_obj_t *btn)
|
||||
break;
|
||||
}
|
||||
|
||||
s_printf(txt_buf + strlen(txt_buf), "(%02X)\n%c%c\n%c%c%c%c%c\n%X\n%X\n%08x\n%02d/%04d\n\n",
|
||||
sd_storage.cid.manfid, (sd_storage.cid.oemid >> 8) & 0xFF, sd_storage.cid.oemid & 0xFF,
|
||||
s_printf(txt_buf + strlen(txt_buf), "(%02X)\n%c%c%c%c%c\n%c%c\n%X\n%X\n%08x\n%02d/%04d\n\n",
|
||||
sd_storage.cid.manfid,
|
||||
sd_storage.cid.prod_name[0], sd_storage.cid.prod_name[1], sd_storage.cid.prod_name[2],
|
||||
sd_storage.cid.prod_name[3], sd_storage.cid.prod_name[4],
|
||||
(sd_storage.cid.oemid >> 8) & 0xFF, sd_storage.cid.oemid & 0xFF,
|
||||
sd_storage.cid.hwrev, sd_storage.cid.fwrev, sd_storage.cid.serial,
|
||||
sd_storage.cid.month, sd_storage.cid.year);
|
||||
|
||||
@@ -1686,7 +1827,7 @@ static lv_res_t _create_window_sdcard_info_status(lv_obj_t *btn)
|
||||
}
|
||||
|
||||
bool uhs_au_mb = false;
|
||||
u32 uhs_au_size = sd_storage_ssr_get_au(&sd_storage);
|
||||
u32 uhs_au_size = sd_storage_get_ssr_au(&sd_storage);
|
||||
if (uhs_au_size >= 1024)
|
||||
{
|
||||
uhs_au_mb = true;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2019 CTCaer
|
||||
* Copyright (c) 2018-2021 CTCaer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
@@ -842,10 +842,10 @@ disabled:;
|
||||
|
||||
// Check if pairing info was found.
|
||||
if (joycon_found == 2)
|
||||
strcat(txt_buf, "#C7EA46 Found 2 out of 2 Joy-Con pairing data!#\n");
|
||||
strcat(txt_buf, "#C7EA46 Success!#\n#C7EA46 Found 2 out of 2 Joy-Con pairing data!#\n");
|
||||
else
|
||||
{
|
||||
s_printf(txt_buf + strlen(txt_buf), "#FF8000 Warning:# Found #FFDD00 %d out of 2# pairing data!\n", joycon_found);
|
||||
s_printf(txt_buf + strlen(txt_buf), "#FF8000 Failed!#\n#FF8000 Warning:# Found #FFDD00 %d out of 2# pairing data!\n", joycon_found);
|
||||
success = false;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2018-2020 CTCaer
|
||||
* Copyright (c) 2018-2021 CTCaer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
@@ -71,18 +71,16 @@ static lv_obj_t *_create_container(lv_obj_t *parent)
|
||||
bool get_autorcm_status(bool change)
|
||||
{
|
||||
u8 corr_mod0, mod1;
|
||||
sdmmc_storage_t storage;
|
||||
sdmmc_t sdmmc;
|
||||
bool enabled = false;
|
||||
|
||||
if (h_cfg.t210b01)
|
||||
return false;
|
||||
|
||||
sdmmc_storage_init_mmc(&storage, &sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400);
|
||||
sdmmc_storage_init_mmc(&emmc_storage, &emmc_sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400);
|
||||
|
||||
u8 *tempbuf = (u8 *)malloc(0x200);
|
||||
sdmmc_storage_set_mmc_partition(&storage, EMMC_BOOT0);
|
||||
sdmmc_storage_read(&storage, 0x200 / NX_EMMC_BLOCKSIZE, 1, tempbuf);
|
||||
sdmmc_storage_set_mmc_partition(&emmc_storage, EMMC_BOOT0);
|
||||
sdmmc_storage_read(&emmc_storage, 0x200 / NX_EMMC_BLOCKSIZE, 1, tempbuf);
|
||||
|
||||
// Get the correct RSA modulus byte masks.
|
||||
nx_emmc_get_autorcm_masks(&corr_mod0, &mod1);
|
||||
@@ -103,20 +101,20 @@ bool get_autorcm_status(bool change)
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
sect = (0x200 + (0x4000 * i)) / NX_EMMC_BLOCKSIZE;
|
||||
sdmmc_storage_read(&storage, sect, 1, tempbuf);
|
||||
sdmmc_storage_read(&emmc_storage, sect, 1, tempbuf);
|
||||
|
||||
if (!enabled)
|
||||
tempbuf[0x10] = 0;
|
||||
else
|
||||
tempbuf[0x10] = corr_mod0;
|
||||
sdmmc_storage_write(&storage, sect, 1, tempbuf);
|
||||
sdmmc_storage_write(&emmc_storage, sect, 1, tempbuf);
|
||||
}
|
||||
enabled = !(enabled);
|
||||
}
|
||||
|
||||
out:
|
||||
free(tempbuf);
|
||||
sdmmc_storage_end(&storage);
|
||||
sdmmc_storage_end(&emmc_storage);
|
||||
|
||||
return enabled;
|
||||
}
|
||||
@@ -607,7 +605,7 @@ void nyx_run_ums(void *param)
|
||||
u32 *cfg = (u32 *)param;
|
||||
|
||||
u8 type = (*cfg) >> 24;
|
||||
*cfg = *cfg & 0xFFFFFF;
|
||||
*cfg = *cfg & (~NYX_CFG_EXTRA);
|
||||
|
||||
// Disable read only flag.
|
||||
usb_msc_emmc_read_only = false;
|
||||
@@ -1095,19 +1093,14 @@ static lv_res_t _create_window_dump_pk12_tool(lv_obj_t *btn)
|
||||
|
||||
char *txt_buf = (char *)malloc(0x4000);
|
||||
|
||||
tsec_ctxt_t tsec_ctxt;
|
||||
|
||||
sdmmc_storage_t storage;
|
||||
sdmmc_t sdmmc;
|
||||
|
||||
if (!sdmmc_storage_init_mmc(&storage, &sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400))
|
||||
if (!sdmmc_storage_init_mmc(&emmc_storage, &emmc_sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400))
|
||||
{
|
||||
lv_label_set_text(lb_desc, "#FFDD00 Failed to init eMMC!#");
|
||||
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
sdmmc_storage_set_mmc_partition(&storage, EMMC_BOOT0);
|
||||
sdmmc_storage_set_mmc_partition(&emmc_storage, EMMC_BOOT0);
|
||||
|
||||
// Read package1.
|
||||
static const u32 BOOTLOADER_SIZE = 0x40000;
|
||||
@@ -1116,7 +1109,7 @@ static lv_res_t _create_window_dump_pk12_tool(lv_obj_t *btn)
|
||||
|
||||
char *build_date = malloc(32);
|
||||
u32 pk1_offset = h_cfg.t210b01 ? sizeof(bl_hdr_t210b01_t) : 0; // Skip T210B01 OEM header.
|
||||
sdmmc_storage_read(&storage, BOOTLOADER_MAIN_OFFSET / NX_EMMC_BLOCKSIZE, BOOTLOADER_SIZE / NX_EMMC_BLOCKSIZE, pkg1);
|
||||
sdmmc_storage_read(&emmc_storage, BOOTLOADER_MAIN_OFFSET / NX_EMMC_BLOCKSIZE, BOOTLOADER_SIZE / NX_EMMC_BLOCKSIZE, pkg1);
|
||||
|
||||
const pkg1_id_t *pkg1_id = pkg1_identify(pkg1 + pk1_offset, build_date);
|
||||
|
||||
@@ -1128,11 +1121,11 @@ static lv_res_t _create_window_dump_pk12_tool(lv_obj_t *btn)
|
||||
// Dump package1 in its encrypted state if unknown.
|
||||
if (!pkg1_id)
|
||||
{
|
||||
strcat(txt_buf, "#FFDD00 Unknown pkg1 version for reading#\n#FFDD00 TSEC firmware!#");
|
||||
strcat(txt_buf, "#FFDD00 Unknown pkg1 version!#");
|
||||
lv_label_set_text(lb_desc, txt_buf);
|
||||
manual_system_maintenance(true);
|
||||
|
||||
emmcsn_path_impl(path, "/pkg1", "pkg1_enc.bin", &storage);
|
||||
emmcsn_path_impl(path, "/pkg1", "pkg1_enc.bin", &emmc_storage);
|
||||
if (sd_save_to_file(pkg1, BOOTLOADER_SIZE, path))
|
||||
goto out_free;
|
||||
|
||||
@@ -1147,6 +1140,7 @@ static lv_res_t _create_window_dump_pk12_tool(lv_obj_t *btn)
|
||||
|
||||
if (!h_cfg.se_keygen_done)
|
||||
{
|
||||
tsec_ctxt_t tsec_ctxt;
|
||||
tsec_ctxt.fw = (void *)(pkg1 + pkg1_id->tsec_off);
|
||||
tsec_ctxt.pkg1 = (void *)pkg1;
|
||||
tsec_ctxt.pkg11_off = pkg1_id->pkg11_off;
|
||||
@@ -1164,9 +1158,23 @@ static lv_res_t _create_window_dump_pk12_tool(lv_obj_t *btn)
|
||||
h_cfg.sept_run = true;
|
||||
else
|
||||
{
|
||||
// Check that BCT is proper so sept can run.
|
||||
u8 *bct_bldr = (u8 *)calloc(1, 512);
|
||||
sdmmc_storage_read(&emmc_storage, 0x2200 / NX_EMMC_BLOCKSIZE, 1, bct_bldr);
|
||||
u32 bootloader_entrypoint = *(u32 *)&bct_bldr[0x144];
|
||||
free(bct_bldr);
|
||||
if (bootloader_entrypoint > SEPT_PRI_ENTRY)
|
||||
{
|
||||
lv_label_set_text(lb_desc, "#FFDD00 Failed to run sept because main BCT is improper!#\n"
|
||||
"#FFDD00 Run sept with proper BCT at least once to cache keys.#\n");
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
// Set boot cfg.
|
||||
b_cfg->autoboot = 0;
|
||||
b_cfg->autoboot_list = 0;
|
||||
b_cfg->extra_cfg = EXTRA_CFG_NYX_DUMP;
|
||||
b_cfg->extra_cfg = EXTRA_CFG_NYX_SEPT;
|
||||
b_cfg->sept = NYX_SEPT_DUMP;
|
||||
|
||||
if (!reboot_to_sept((u8 *)tsec_ctxt.fw, kb))
|
||||
{
|
||||
@@ -1178,7 +1186,7 @@ static lv_res_t _create_window_dump_pk12_tool(lv_obj_t *btn)
|
||||
|
||||
// Read keyblob.
|
||||
u8 *keyblob = (u8 *)calloc(NX_EMMC_BLOCKSIZE, 1);
|
||||
sdmmc_storage_read(&storage, HOS_KEYBLOBS_OFFSET / NX_EMMC_BLOCKSIZE + kb, 1, keyblob);
|
||||
sdmmc_storage_read(&emmc_storage, HOS_KEYBLOBS_OFFSET / NX_EMMC_BLOCKSIZE + kb, 1, keyblob);
|
||||
|
||||
// Decrypt.
|
||||
hos_keygen(keyblob, kb, &tsec_ctxt);
|
||||
@@ -1230,7 +1238,7 @@ static lv_res_t _create_window_dump_pk12_tool(lv_obj_t *btn)
|
||||
manual_system_maintenance(true);
|
||||
|
||||
// Dump package1.1.
|
||||
emmcsn_path_impl(path, "/pkg1", "pkg1_decr.bin", &storage);
|
||||
emmcsn_path_impl(path, "/pkg1", "pkg1_decr.bin", &emmc_storage);
|
||||
if (sd_save_to_file(pkg1, 0x40000, path))
|
||||
goto out_free;
|
||||
strcat(txt_buf, "pkg1 dumped to pkg1_decr.bin\n");
|
||||
@@ -1238,7 +1246,7 @@ static lv_res_t _create_window_dump_pk12_tool(lv_obj_t *btn)
|
||||
manual_system_maintenance(true);
|
||||
|
||||
// Dump nxbootloader.
|
||||
emmcsn_path_impl(path, "/pkg1", "nxloader.bin", &storage);
|
||||
emmcsn_path_impl(path, "/pkg1", "nxloader.bin", &emmc_storage);
|
||||
if (sd_save_to_file(loader, hdr_pk11->ldr_size, path))
|
||||
goto out_free;
|
||||
strcat(txt_buf, "NX Bootloader dumped to nxloader.bin\n");
|
||||
@@ -1246,7 +1254,7 @@ static lv_res_t _create_window_dump_pk12_tool(lv_obj_t *btn)
|
||||
manual_system_maintenance(true);
|
||||
|
||||
// Dump secmon.
|
||||
emmcsn_path_impl(path, "/pkg1", "secmon.bin", &storage);
|
||||
emmcsn_path_impl(path, "/pkg1", "secmon.bin", &emmc_storage);
|
||||
if (sd_save_to_file(secmon, hdr_pk11->sm_size, path))
|
||||
goto out_free;
|
||||
strcat(txt_buf, "Secure Monitor dumped to secmon.bin\n");
|
||||
@@ -1254,7 +1262,7 @@ static lv_res_t _create_window_dump_pk12_tool(lv_obj_t *btn)
|
||||
manual_system_maintenance(true);
|
||||
|
||||
// Dump warmboot.
|
||||
emmcsn_path_impl(path, "/pkg1", "warmboot.bin", &storage);
|
||||
emmcsn_path_impl(path, "/pkg1", "warmboot.bin", &emmc_storage);
|
||||
if (sd_save_to_file(warmboot, hdr_pk11->wb_size, path))
|
||||
goto out_free;
|
||||
// If T210B01, save a copy of decrypted warmboot binary also.
|
||||
@@ -1263,7 +1271,7 @@ static lv_res_t _create_window_dump_pk12_tool(lv_obj_t *btn)
|
||||
|
||||
se_aes_iv_clear(13);
|
||||
se_aes_crypt_cbc(13, 0, warmboot + 0x330, hdr_pk11->wb_size - 0x330, warmboot + 0x330, hdr_pk11->wb_size - 0x330);
|
||||
emmcsn_path_impl(path, "/pkg1", "warmboot_dec.bin", &storage);
|
||||
emmcsn_path_impl(path, "/pkg1", "warmboot_dec.bin", &emmc_storage);
|
||||
if (sd_save_to_file(warmboot, hdr_pk11->wb_size, path))
|
||||
goto out_free;
|
||||
}
|
||||
@@ -1273,10 +1281,10 @@ static lv_res_t _create_window_dump_pk12_tool(lv_obj_t *btn)
|
||||
}
|
||||
|
||||
// Dump package2.1.
|
||||
sdmmc_storage_set_mmc_partition(&storage, EMMC_GPP);
|
||||
sdmmc_storage_set_mmc_partition(&emmc_storage, EMMC_GPP);
|
||||
// Parse eMMC GPT.
|
||||
LIST_INIT(gpt);
|
||||
nx_emmc_gpt_parse(&gpt, &storage);
|
||||
nx_emmc_gpt_parse(&gpt, &emmc_storage);
|
||||
// Find package2 partition.
|
||||
emmc_part_t *pkg2_part = nx_emmc_part_find(&gpt, "BCPKG2-1-Normal-Main");
|
||||
if (!pkg2_part)
|
||||
@@ -1284,17 +1292,17 @@ static lv_res_t _create_window_dump_pk12_tool(lv_obj_t *btn)
|
||||
|
||||
// Read in package2 header and get package2 real size.
|
||||
u8 *tmp = (u8 *)malloc(NX_EMMC_BLOCKSIZE);
|
||||
nx_emmc_part_read(&storage, pkg2_part, 0x4000 / NX_EMMC_BLOCKSIZE, 1, tmp);
|
||||
nx_emmc_part_read(&emmc_storage, pkg2_part, 0x4000 / NX_EMMC_BLOCKSIZE, 1, tmp);
|
||||
u32 *hdr_pkg2_raw = (u32 *)(tmp + 0x100);
|
||||
u32 pkg2_size = hdr_pkg2_raw[0] ^ hdr_pkg2_raw[2] ^ hdr_pkg2_raw[3];
|
||||
free(tmp);
|
||||
// Read in package2.
|
||||
u32 pkg2_size_aligned = ALIGN(pkg2_size, NX_EMMC_BLOCKSIZE);
|
||||
pkg2 = malloc(pkg2_size_aligned);
|
||||
nx_emmc_part_read(&storage, pkg2_part, 0x4000 / NX_EMMC_BLOCKSIZE,
|
||||
nx_emmc_part_read(&emmc_storage, pkg2_part, 0x4000 / NX_EMMC_BLOCKSIZE,
|
||||
pkg2_size_aligned / NX_EMMC_BLOCKSIZE, pkg2);
|
||||
#if 0
|
||||
emmcsn_path_impl(path, "/pkg2", "pkg2_encr.bin", &storage);
|
||||
emmcsn_path_impl(path, "/pkg2", "pkg2_encr.bin", &emmc_storage);
|
||||
if (sd_save_to_file(pkg2, pkg2_size_aligned, path))
|
||||
goto out;
|
||||
gfx_puts("\npkg2 dumped to pkg2_encr.bin\n");
|
||||
@@ -1326,7 +1334,7 @@ static lv_res_t _create_window_dump_pk12_tool(lv_obj_t *btn)
|
||||
manual_system_maintenance(true);
|
||||
|
||||
// Dump pkg2.1.
|
||||
emmcsn_path_impl(path, "/pkg2", "pkg2_decr.bin", &storage);
|
||||
emmcsn_path_impl(path, "/pkg2", "pkg2_decr.bin", &emmc_storage);
|
||||
if (sd_save_to_file(pkg2, pkg2_hdr->sec_size[PKG2_SEC_KERNEL] + pkg2_hdr->sec_size[PKG2_SEC_INI1], path))
|
||||
goto out;
|
||||
strcat(txt_buf, "pkg2 dumped to pkg2_decr.bin\n");
|
||||
@@ -1334,7 +1342,7 @@ static lv_res_t _create_window_dump_pk12_tool(lv_obj_t *btn)
|
||||
manual_system_maintenance(true);
|
||||
|
||||
// Dump kernel.
|
||||
emmcsn_path_impl(path, "/pkg2", "kernel.bin", &storage);
|
||||
emmcsn_path_impl(path, "/pkg2", "kernel.bin", &emmc_storage);
|
||||
if (sd_save_to_file(pkg2_hdr->data, pkg2_hdr->sec_size[PKG2_SEC_KERNEL], path))
|
||||
goto out;
|
||||
strcat(txt_buf, "Kernel dumped to kernel.bin\n");
|
||||
@@ -1358,7 +1366,7 @@ static lv_res_t _create_window_dump_pk12_tool(lv_obj_t *btn)
|
||||
}
|
||||
|
||||
pkg2_ini1_t *ini1 = (pkg2_ini1_t *)(pkg2_hdr->data + ini1_off);
|
||||
emmcsn_path_impl(path, "/pkg2", "ini1.bin", &storage);
|
||||
emmcsn_path_impl(path, "/pkg2", "ini1.bin", &emmc_storage);
|
||||
if (sd_save_to_file(ini1, ini1_size, path))
|
||||
goto out;
|
||||
|
||||
@@ -1385,7 +1393,7 @@ static lv_res_t _create_window_dump_pk12_tool(lv_obj_t *btn)
|
||||
kip1 = (pkg2_kip1_t *)kip_buffer;
|
||||
}
|
||||
|
||||
emmcsn_path_impl(path, "/pkg2/ini1", filename, &storage);
|
||||
emmcsn_path_impl(path, "/pkg2/ini1", filename, &emmc_storage);
|
||||
if (sd_save_to_file(kip1, kip1_size, path))
|
||||
{
|
||||
free(kip_buffer);
|
||||
@@ -1409,7 +1417,7 @@ out_free:
|
||||
free(loader);
|
||||
free(pkg2);
|
||||
free(txt_buf);
|
||||
sdmmc_storage_end(&storage);
|
||||
sdmmc_storage_end(&emmc_storage);
|
||||
sd_unmount();
|
||||
|
||||
if (kb >= KB_FIRMWARE_VERSION_620)
|
||||
@@ -1495,14 +1503,14 @@ static void _create_tab_tools_emmc_pkg12(lv_theme_t *th, lv_obj_t *parent)
|
||||
lv_label_set_static_text(label_sep, "");
|
||||
|
||||
lv_obj_t *label_txt3 = lv_label_create(h2, NULL);
|
||||
lv_label_set_static_text(label_txt3, "Misc");
|
||||
lv_label_set_static_text(label_txt3, "SD Partitions & USB");
|
||||
lv_obj_set_style(label_txt3, th->label.prim);
|
||||
lv_obj_align(label_txt3, label_sep, LV_ALIGN_OUT_BOTTOM_LEFT, LV_DPI / 4, -LV_DPI * 3 / 10);
|
||||
|
||||
line_sep = lv_line_create(h2, line_sep);
|
||||
lv_obj_align(line_sep, label_txt3, LV_ALIGN_OUT_BOTTOM_LEFT, -(LV_DPI / 4), LV_DPI / 8);
|
||||
|
||||
// Create Dump Package1/2 button.
|
||||
// Create Partition SD Card button.
|
||||
lv_obj_t *btn3 = lv_btn_create(h2, NULL);
|
||||
if (hekate_bg)
|
||||
{
|
||||
@@ -1511,15 +1519,15 @@ static void _create_tab_tools_emmc_pkg12(lv_theme_t *th, lv_obj_t *parent)
|
||||
}
|
||||
label_btn = lv_label_create(btn3, NULL);
|
||||
lv_btn_set_fit(btn3, true, true);
|
||||
lv_label_set_static_text(label_btn, SYMBOL_MODULES" Dump Package1/2");
|
||||
lv_label_set_static_text(label_btn, SYMBOL_SD" Partition SD Card");
|
||||
lv_obj_align(btn3, line_sep, LV_ALIGN_OUT_BOTTOM_LEFT, LV_DPI / 4, LV_DPI / 4);
|
||||
lv_btn_set_action(btn3, LV_BTN_ACTION_CLICK, _create_window_dump_pk12_tool);
|
||||
lv_btn_set_action(btn3, LV_BTN_ACTION_CLICK, create_window_partition_manager);
|
||||
|
||||
lv_obj_t *label_txt4 = lv_label_create(h2, NULL);
|
||||
lv_label_set_recolor(label_txt4, true);
|
||||
lv_label_set_static_text(label_txt4,
|
||||
"Allows you to dump and decrypt pkg1 and pkg2 and further\n"
|
||||
"split it up into their individual parts. It also dumps the kip1.\n");
|
||||
"Allows you to partition the SD Card for using it with #C7EA46 emuMMC#,\n"
|
||||
"#C7EA46 Android# and #C7EA46 Linux#. You can also flash Linux and Android.\n");
|
||||
lv_obj_set_style(label_txt4, &hint_small_style);
|
||||
lv_obj_align(label_txt4, btn3, LV_ALIGN_OUT_BOTTOM_LEFT, 0, LV_DPI / 3);
|
||||
|
||||
@@ -1671,18 +1679,18 @@ static void _create_tab_tools_arc_autorcm(lv_theme_t *th, lv_obj_t *parent)
|
||||
lv_label_set_static_text(label_sep, "");
|
||||
lv_obj_align(label_sep, label_txt4, LV_ALIGN_OUT_BOTTOM_LEFT, 0, LV_DPI * 11 / 7);
|
||||
|
||||
// Create Partition SD Card button.
|
||||
// Create Dump Package1/2 button.
|
||||
lv_obj_t *btn4 = lv_btn_create(h2, btn);
|
||||
label_btn = lv_label_create(btn4, NULL);
|
||||
lv_label_set_static_text(label_btn, SYMBOL_SD" Partition SD Card");
|
||||
lv_label_set_static_text(label_btn, SYMBOL_MODULES" Dump Package1/2");
|
||||
lv_obj_align(btn4, label_txt4, LV_ALIGN_OUT_BOTTOM_LEFT, 0, LV_DPI / 2);
|
||||
lv_btn_set_action(btn4, LV_BTN_ACTION_CLICK, create_window_partition_manager);
|
||||
lv_btn_set_action(btn4, LV_BTN_ACTION_CLICK, _create_window_dump_pk12_tool);
|
||||
|
||||
label_txt2 = lv_label_create(h2, NULL);
|
||||
lv_label_set_recolor(label_txt2, true);
|
||||
lv_label_set_static_text(label_txt2,
|
||||
"Allows you to partition the SD Card for using it with #C7EA46 emuMMC#,\n"
|
||||
"#C7EA46 Android# and #C7EA46 Linux#. You can also flash Linux and Android.");
|
||||
"Allows you to dump and decrypt pkg1 and pkg2 and further\n"
|
||||
"split it up into their individual parts. It also dumps the kip1.");
|
||||
lv_obj_set_style(label_txt2, &hint_small_style);
|
||||
lv_obj_align(label_txt2, btn4, LV_ALIGN_OUT_BOTTOM_LEFT, 0, LV_DPI / 3);
|
||||
}
|
||||
@@ -1707,8 +1715,8 @@ void create_tab_tools(lv_theme_t *th, lv_obj_t *parent)
|
||||
lv_tabview_set_sliding(tv, false);
|
||||
lv_tabview_set_btns_pos(tv, LV_TABVIEW_BTNS_POS_BOTTOM);
|
||||
|
||||
lv_obj_t *tab1= lv_tabview_add_tab(tv, "eMMC "SYMBOL_DOT" Pkg1/2 "SYMBOL_DOT" USB Tools");
|
||||
lv_obj_t *tab2 = lv_tabview_add_tab(tv, "Arch bit "SYMBOL_DOT" RCM "SYMBOL_DOT" Touch "SYMBOL_DOT" Partitions");
|
||||
lv_obj_t *tab1= lv_tabview_add_tab(tv, "eMMC "SYMBOL_DOT" SD Partitions "SYMBOL_DOT" USB");
|
||||
lv_obj_t *tab2 = lv_tabview_add_tab(tv, "Arch bit "SYMBOL_DOT" RCM "SYMBOL_DOT" Touch "SYMBOL_DOT" Pkg1/2");
|
||||
|
||||
lv_obj_t *line_sep = lv_line_create(tv, NULL);
|
||||
static const lv_point_t line_pp[] = { {0, 0}, { 0, LV_DPI / 4} };
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019-2020 CTCaer
|
||||
* Copyright (c) 2019-2021 CTCaer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
@@ -48,6 +48,8 @@ typedef struct _partition_ctxt_t
|
||||
u32 l4t_size;
|
||||
u32 and_size;
|
||||
|
||||
bool emu_double;
|
||||
|
||||
mbr_t *mbr_old;
|
||||
|
||||
lv_obj_t *bar_hos;
|
||||
@@ -244,26 +246,20 @@ static void _prepare_and_flash_mbr_gpt()
|
||||
if (part_info.l4t_size && !part_info.and_size)
|
||||
{
|
||||
mbr.partitions[mbr_idx].type = 0x83; // Linux system partition.
|
||||
mbr.partitions[mbr_idx].start_sct = 0x8000 + (part_info.hos_size << 11);
|
||||
mbr.partitions[mbr_idx].start_sct = 0x8000 + ((u32)part_info.hos_size << 11);
|
||||
mbr.partitions[mbr_idx].size_sct = part_info.l4t_size << 11;
|
||||
sdmmc_storage_write(&sd_storage, mbr.partitions[mbr_idx].start_sct, 0x800, (void *)SDMMC_UPPER_BUFFER); // Clear the first 1MB.
|
||||
mbr_idx++;
|
||||
}
|
||||
|
||||
// emuMMC goes second or third. Next to L4T if no Android.
|
||||
bool double_emummc = part_info.emu_size > 29856;
|
||||
if (part_info.emu_size)
|
||||
{
|
||||
mbr.partitions[mbr_idx].type = 0xE0; // emuMMC partition.
|
||||
mbr.partitions[mbr_idx].start_sct = 0x8000 + (part_info.hos_size << 11) + (part_info.l4t_size << 11) + (part_info.and_size << 11);
|
||||
mbr.partitions[mbr_idx].start_sct = 0x8000 + ((u32)part_info.hos_size << 11) + (part_info.l4t_size << 11) + (part_info.and_size << 11);
|
||||
|
||||
if (!double_emummc)
|
||||
{
|
||||
if (!part_info.and_size)
|
||||
mbr.partitions[mbr_idx].size_sct = part_info.emu_size << 11;
|
||||
else
|
||||
mbr.partitions[mbr_idx].size_sct = (part_info.emu_size << 11) - 0x800; // Reserve 1MB.
|
||||
}
|
||||
if (!part_info.emu_double)
|
||||
mbr.partitions[mbr_idx].size_sct = (part_info.emu_size << 11) - 0x800; // Reserve 1MB.
|
||||
else
|
||||
{
|
||||
mbr.partitions[mbr_idx].type = 0xE0; // emuMMC partition.
|
||||
@@ -272,10 +268,7 @@ static void _prepare_and_flash_mbr_gpt()
|
||||
|
||||
// 2nd emuMMC.
|
||||
mbr.partitions[mbr_idx].start_sct = mbr.partitions[mbr_idx - 1].start_sct + (part_info.emu_size << 10);
|
||||
if (!part_info.and_size)
|
||||
mbr.partitions[mbr_idx].size_sct = part_info.emu_size << 10;
|
||||
else
|
||||
mbr.partitions[mbr_idx].size_sct = (part_info.emu_size << 10) - 0x800; // Reserve 1MB.
|
||||
mbr.partitions[mbr_idx].size_sct = (part_info.emu_size << 10) - 0x800; // Reserve 1MB.
|
||||
}
|
||||
mbr_idx++;
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
u8 gpt_idx = 1;
|
||||
u32 curr_part_lba = 0x8000 + (part_info.hos_size << 11);
|
||||
u32 curr_part_lba = 0x8000 + ((u32)part_info.hos_size << 11);
|
||||
u8 android_part_guid[] = { 0xAF, 0x3D, 0xC6, 0x0F, 0x83, 0x84, 0x72, 0x47, 0x8E, 0x79, 0x3D, 0x69, 0xD8, 0x47, 0x7D, 0xE4 };
|
||||
if (part_info.l4t_size)
|
||||
{
|
||||
@@ -440,14 +433,14 @@ static void _prepare_and_flash_mbr_gpt()
|
||||
se_gen_prng128(random_number);
|
||||
memcpy(gpt.entries[gpt_idx].part_guid, random_number, 16);
|
||||
gpt.entries[gpt_idx].lba_start = curr_part_lba;
|
||||
if (!double_emummc)
|
||||
if (!part_info.emu_double)
|
||||
gpt.entries[gpt_idx].lba_end = curr_part_lba + (part_info.emu_size << 11) - 0x800 - 1; // Reserve 1MB.
|
||||
else
|
||||
gpt.entries[gpt_idx].lba_end = curr_part_lba + (part_info.emu_size << 10); // Reserve 1MB.
|
||||
gpt.entries[gpt_idx].lba_end = curr_part_lba + (part_info.emu_size << 10) - 1;
|
||||
memcpy(gpt.entries[gpt_idx].name, (char[]) { 'e', 0, 'm', 0, 'u', 0, 'm', 0, 'm', 0, 'c', 0 }, 12);
|
||||
gpt_idx++;
|
||||
|
||||
if (double_emummc)
|
||||
if (part_info.emu_double)
|
||||
{
|
||||
curr_part_lba += (part_info.emu_size << 10);
|
||||
memcpy(gpt.entries[gpt_idx].type_guid, emu_part_guid, 16);
|
||||
@@ -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_size(dark_bg, LV_HOR_RES, LV_VER_RES);
|
||||
|
||||
static const char *mbox_btn_map[] = { "\211", "\222OK", "\211", "" };
|
||||
static const char *mbox_btn_map[] = { "\211", "\222OK", "\211", "" };
|
||||
static const char *mbox_btn_map1[] = { "\222SD UMS", "\222Flash Linux", "\222Flash Android", "\221OK", "" };
|
||||
static const char *mbox_btn_map2[] = { "\222SD UMS", "\222Flash Linux", "\221OK", "" };
|
||||
static const char *mbox_btn_map3[] = { "\222SD UMS", "\222Flash Android", "\221OK", "" };
|
||||
@@ -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_obj_align(mbox, NULL, LV_ALIGN_CENTER, 0, 0);
|
||||
manual_system_maintenance(true);
|
||||
if (ram_disk_init(&ram_fs))
|
||||
if (ram_disk_init(&ram_fs, RAM_DISK_SZ))
|
||||
{
|
||||
lv_label_set_text(lbl_status, "#FFDD00 Error:# Failed to initialize Ramdisk!");
|
||||
goto error;
|
||||
@@ -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");
|
||||
|
||||
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
|
||||
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);
|
||||
|
||||
@@ -1677,12 +1677,33 @@ static void _update_partition_bar()
|
||||
|
||||
static lv_res_t _action_slider_emu(lv_obj_t *slider)
|
||||
{
|
||||
u32 size;
|
||||
char lbl_text[64];
|
||||
|
||||
bool prev_emu_double = part_info.emu_double;
|
||||
int slide_val = lv_slider_get_value(slider);
|
||||
u32 size = slide_val ? ((slide_val < 2) ? 29856 : 59712) : 0;
|
||||
s32 hos_size = (part_info.total_sct >> 11) - 16 - size - part_info.l4t_size - part_info.and_size;
|
||||
const u32 rsvd_mb = 4 + 4 + 16 + 8; // BOOT0 + BOOT1 + 16MB offset + 8MB alignment.
|
||||
|
||||
part_info.emu_double = false;
|
||||
|
||||
size = (slide_val > 10 ? (slide_val - 10) : slide_val) + 3; // Min 4GB.
|
||||
size *= 1024; // Convert to GB.
|
||||
size += rsvd_mb; // Add reserved size.
|
||||
|
||||
if (!slide_val)
|
||||
size = 0; // Reset if 0.
|
||||
else if (slide_val >= 11)
|
||||
{
|
||||
size *= 2;
|
||||
part_info.emu_double = true;
|
||||
}
|
||||
|
||||
// Handle special case.
|
||||
if (slide_val == 10)
|
||||
size = 29856;
|
||||
else if (slide_val == 20)
|
||||
size = 59712;
|
||||
|
||||
s32 hos_size = (part_info.total_sct >> 11) - 16 - size - part_info.l4t_size - part_info.and_size;
|
||||
if (hos_size > 2048)
|
||||
{
|
||||
part_info.emu_size = size;
|
||||
@@ -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_bar_set_value(part_info.slider_bar_hos, hos_size >> 10);
|
||||
|
||||
if (slide_val < 2)
|
||||
s_printf(lbl_text, "#FF3C28 %d GiB#", size >> 10);
|
||||
if (!part_info.emu_double)
|
||||
{
|
||||
if (slide_val != 10)
|
||||
s_printf(lbl_text, "#FF3C28 %d GiB#", size >> 10);
|
||||
else
|
||||
s_printf(lbl_text, "#FF3C28 %d FULL#", size >> 10);
|
||||
}
|
||||
else
|
||||
s_printf(lbl_text, "#FF3C28 2x%d GiB#", size >> 11);
|
||||
s_printf(lbl_text, "#FFDD00 2x##FF3C28 %d#", size >> 11);
|
||||
lv_label_set_text(part_info.lbl_emu, lbl_text);
|
||||
}
|
||||
else
|
||||
{
|
||||
int new_slider_val;
|
||||
switch (part_info.emu_size)
|
||||
u32 emu_size = part_info.emu_size;
|
||||
|
||||
if (emu_size == 29856)
|
||||
emu_size = 10;
|
||||
else if (emu_size == 59712)
|
||||
emu_size = 20;
|
||||
else if (emu_size)
|
||||
{
|
||||
case 29856:
|
||||
new_slider_val = 1;
|
||||
break;
|
||||
case 59712:
|
||||
new_slider_val = 2;
|
||||
break;
|
||||
case 0:
|
||||
default:
|
||||
new_slider_val = 0;
|
||||
break;
|
||||
if (prev_emu_double)
|
||||
emu_size /= 2;
|
||||
emu_size -= rsvd_mb;
|
||||
emu_size /= 1024;
|
||||
emu_size -= 3;
|
||||
|
||||
if (prev_emu_double)
|
||||
emu_size += 11;
|
||||
}
|
||||
|
||||
int new_slider_val = emu_size;
|
||||
part_info.emu_double = prev_emu_double ? true : false;
|
||||
|
||||
lv_slider_set_value(slider, new_slider_val);
|
||||
}
|
||||
|
||||
@@ -1883,7 +1916,8 @@ static void create_mbox_check_files_total_size()
|
||||
else
|
||||
{
|
||||
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.");
|
||||
}
|
||||
|
||||
@@ -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_label_set_recolor(lbl_status, true);
|
||||
|
||||
if (!sd_mount())
|
||||
// Try to init sd card. No need for valid MBR.
|
||||
if (!sd_mount() && !sd_get_card_initialized())
|
||||
{
|
||||
lv_label_set_text(lbl_status, "#FFDD00 Failed to init SD!#");
|
||||
goto out;
|
||||
@@ -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_set_size(slider_emu, LV_DPI * 7, LV_DPI / 3);
|
||||
lv_slider_set_range(slider_emu, 0, 2);
|
||||
lv_slider_set_range(slider_emu, 0, 20);
|
||||
lv_slider_set_value(slider_emu, 0);
|
||||
lv_slider_set_style(slider_emu, LV_SLIDER_STYLE_BG, &bar_emu_bg);
|
||||
lv_slider_set_style(slider_emu, LV_SLIDER_STYLE_INDIC, &bar_emu_ind);
|
||||
@@ -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_static_text(lbl_notes,
|
||||
"Note 1: Only up to #C7EA46 1GB# can be backed up. If more, you will be asked to back them manually at the next step.\n"
|
||||
"Note 2: The #C7EA46 Flash Linux# and #C7EA46 Flash Android# work independently and will flash files if suitable partitions and installer files are found.\n"
|
||||
"Note 3: The installation files reside in #C7EA46 switchroot/install# folder. Linux uses #C7EA46 l4t.XX# and Android uses #C7EA46 twrp.img# and #C7EA46 tegra210-icosa.dtb#.\n"
|
||||
"Note 4: #FFDD00 The installation files will be deleted after a successful flashing.#");
|
||||
"Note 2: Resized emuMMC formats the USER partition. A save data manager can be used to move them over.\n"
|
||||
"Note 3: The #C7EA46 Flash Linux# and #C7EA46 Flash Android# will flash files if suitable partitions and installer files are found.\n"
|
||||
"Note 4: The installation folder is #C7EA46 switchroot/install#. Linux uses #C7EA46 l4t.XX# and Android uses #C7EA46 twrp.img# and #C7EA46 tegra210-icosa.dtb#.");
|
||||
lv_label_set_style(lbl_notes, &hint_small_style);
|
||||
lv_obj_align(lbl_notes, lbl_and, LV_ALIGN_OUT_BOTTOM_LEFT, 0, LV_DPI / 5);
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2018-2020 CTCaer
|
||||
* Copyright (c) 2018-2021 CTCaer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
@@ -379,11 +379,13 @@ void gfx_printf(const char *fmt, ...)
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
void gfx_hexdump(u32 base, const u8 *buf, u32 len)
|
||||
void gfx_hexdump(u32 base, const void *buf, u32 len)
|
||||
{
|
||||
if (gfx_con.mute)
|
||||
return;
|
||||
|
||||
u8 *buff = (u8 *)buf;
|
||||
|
||||
u8 prevFontSize = gfx_con.fntsz;
|
||||
gfx_con.fntsz = 8;
|
||||
for(u32 i = 0; i < len; i++)
|
||||
@@ -395,7 +397,7 @@ void gfx_hexdump(u32 base, const u8 *buf, u32 len)
|
||||
gfx_puts("| ");
|
||||
for(u32 j = 0; j < 0x10; j++)
|
||||
{
|
||||
u8 c = buf[i - 0x10 + j];
|
||||
u8 c = buff[i - 0x10 + j];
|
||||
if(c >= 32 && c <= 126)
|
||||
gfx_putc(c);
|
||||
else
|
||||
@@ -405,7 +407,7 @@ void gfx_hexdump(u32 base, const u8 *buf, u32 len)
|
||||
}
|
||||
gfx_printf("%08x: ", base + i);
|
||||
}
|
||||
gfx_printf("%02x ", buf[i]);
|
||||
gfx_printf("%02x ", buff[i]);
|
||||
if (i == len - 1)
|
||||
{
|
||||
int ln = len % 0x10 != 0;
|
||||
@@ -419,7 +421,7 @@ void gfx_hexdump(u32 base, const u8 *buf, u32 len)
|
||||
gfx_puts("| ");
|
||||
for(u32 j = 0; j < (ln ? k : k + 1); j++)
|
||||
{
|
||||
u8 c = buf[i - k + j];
|
||||
u8 c = buff[i - k + j];
|
||||
if(c >= 32 && c <= 126)
|
||||
gfx_putc(c);
|
||||
else
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2018-2020 CTCaer
|
||||
* Copyright (c) 2018-2021 CTCaer
|
||||
* Copyright (c) 2018 M4xw
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
@@ -62,7 +62,7 @@ void gfx_con_setpos(u32 x, u32 y);
|
||||
void gfx_putc(char c);
|
||||
void gfx_puts(char *s);
|
||||
void gfx_printf(const char *fmt, ...);
|
||||
void gfx_hexdump(u32 base, const u8 *buf, u32 len);
|
||||
void gfx_hexdump(u32 base, const void *buf, u32 len);
|
||||
|
||||
void gfx_set_pixel(u32 x, u32 y, u32 color);
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2018 st4rk
|
||||
* Copyright (c) 2018 Ced2911
|
||||
* Copyright (c) 2018-2020 CTCaer
|
||||
* Copyright (c) 2018-2021 CTCaer
|
||||
* Copyright (c) 2018 balika011
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
@@ -45,7 +45,29 @@ extern hekate_config h_cfg;
|
||||
|
||||
static u8 *bis_keys = NULL;
|
||||
|
||||
static const u8 keyblob_keyseeds[][0x10] = {
|
||||
typedef struct _tsec_keys_t
|
||||
{
|
||||
u8 tsec[SE_KEY_128_SIZE];
|
||||
u8 tsec_root[SE_KEY_128_SIZE];
|
||||
u8 tmp[SE_KEY_128_SIZE];
|
||||
} tsec_keys_t;
|
||||
|
||||
typedef struct _kb_keys_t
|
||||
{
|
||||
u8 master_keyseed[SE_KEY_128_SIZE];
|
||||
u8 random_data[0x70];
|
||||
u8 package1_key[SE_KEY_128_SIZE];
|
||||
} kb_keys_t;
|
||||
|
||||
typedef struct _kb_t
|
||||
{
|
||||
u8 cmac[SE_KEY_128_SIZE];
|
||||
u8 ctr[SE_AES_IV_SIZE];
|
||||
kb_keys_t keys;
|
||||
u8 padding[0x150];
|
||||
} kb_t;
|
||||
|
||||
static const u8 keyblob_keyseeds[][SE_KEY_128_SIZE] = {
|
||||
{ 0xDF, 0x20, 0x6F, 0x59, 0x44, 0x54, 0xEF, 0xDC, 0x70, 0x74, 0x48, 0x3B, 0x0D, 0xED, 0x9F, 0xD3 }, // 1.0.0.
|
||||
{ 0x0C, 0x25, 0x61, 0x5D, 0x68, 0x4C, 0xEB, 0x42, 0x1C, 0x23, 0x79, 0xEA, 0x82, 0x25, 0x12, 0xAC }, // 3.0.0.
|
||||
{ 0x33, 0x76, 0x85, 0xEE, 0x88, 0x4A, 0xAE, 0x0A, 0xC2, 0x8A, 0xFD, 0x7D, 0x63, 0xC0, 0x43, 0x3B }, // 3.0.1.
|
||||
@@ -54,19 +76,19 @@ static const u8 keyblob_keyseeds[][0x10] = {
|
||||
{ 0xD8, 0xCC, 0xE1, 0x26, 0x6A, 0x35, 0x3F, 0xCC, 0x20, 0xF3, 0x2D, 0x3B, 0x51, 0x7D, 0xE9, 0xC0 } // 6.0.0.
|
||||
};
|
||||
|
||||
static const u8 cmac_keyseed[0x10] =
|
||||
static const u8 cmac_keyseed[SE_KEY_128_SIZE] =
|
||||
{ 0x59, 0xC7, 0xFB, 0x6F, 0xBE, 0x9B, 0xBE, 0x87, 0x65, 0x6B, 0x15, 0xC0, 0x53, 0x73, 0x36, 0xA5 };
|
||||
|
||||
static const u8 master_keyseed_retail[0x10] =
|
||||
static const u8 master_keyseed_retail[SE_KEY_128_SIZE] =
|
||||
{ 0xD8, 0xA2, 0x41, 0x0A, 0xC6, 0xC5, 0x90, 0x01, 0xC6, 0x1D, 0x6A, 0x26, 0x7C, 0x51, 0x3F, 0x3C };
|
||||
|
||||
static const u8 master_keyseed_4xx_5xx_610[0x10] =
|
||||
static const u8 master_keyseed_4xx_5xx_610[SE_KEY_128_SIZE] =
|
||||
{ 0x2D, 0xC1, 0xF4, 0x8D, 0xF3, 0x5B, 0x69, 0x33, 0x42, 0x10, 0xAC, 0x65, 0xDA, 0x90, 0x46, 0x66 };
|
||||
|
||||
static const u8 master_keyseed_620[0x10] =
|
||||
static const u8 master_keyseed_620[SE_KEY_128_SIZE] =
|
||||
{ 0x37, 0x4B, 0x77, 0x29, 0x59, 0xB4, 0x04, 0x30, 0x81, 0xF6, 0xE5, 0x8C, 0x6D, 0x36, 0x17, 0x9A };
|
||||
|
||||
static const u8 master_kekseed_t210b01[][0x10] = {
|
||||
static const u8 master_kekseed_t210b01[][SE_KEY_128_SIZE] = {
|
||||
{ 0x77, 0x60, 0x5A, 0xD2, 0xEE, 0x6E, 0xF8, 0x3C, 0x3F, 0x72, 0xE2, 0x59, 0x9D, 0xAC, 0x5E, 0x56 }, // 6.0.0.
|
||||
{ 0x1E, 0x80, 0xB8, 0x17, 0x3E, 0xC0, 0x60, 0xAA, 0x11, 0xBE, 0x1A, 0x4A, 0xA6, 0x6F, 0xE4, 0xAE }, // 6.2.0.
|
||||
{ 0x94, 0x08, 0x67, 0xBD, 0x0A, 0x00, 0x38, 0x84, 0x11, 0xD3, 0x1A, 0xDB, 0xDD, 0x8D, 0xF1, 0x8A }, // 7.0.0.
|
||||
@@ -75,16 +97,16 @@ static const u8 master_kekseed_t210b01[][0x10] = {
|
||||
{ 0x0E, 0x44, 0x0C, 0xED, 0xB4, 0x36, 0xC0, 0x3F, 0xAA, 0x1D, 0xAE, 0xBF, 0x62, 0xB1, 0x09, 0x82 }, // 9.1.0.
|
||||
};
|
||||
|
||||
static const u8 console_keyseed[0x10] =
|
||||
static const u8 console_keyseed[SE_KEY_128_SIZE] =
|
||||
{ 0x4F, 0x02, 0x5F, 0x0E, 0xB6, 0x6D, 0x11, 0x0E, 0xDC, 0x32, 0x7D, 0x41, 0x86, 0xC2, 0xF4, 0x78 };
|
||||
|
||||
static const u8 console_keyseed_4xx_5xx[0x10] =
|
||||
static const u8 console_keyseed_4xx_5xx[SE_KEY_128_SIZE] =
|
||||
{ 0x0C, 0x91, 0x09, 0xDB, 0x93, 0x93, 0x07, 0x81, 0x07, 0x3C, 0xC4, 0x16, 0x22, 0x7C, 0x6C, 0x28 };
|
||||
|
||||
const u8 package2_keyseed[0x10] =
|
||||
const u8 package2_keyseed[SE_KEY_128_SIZE] =
|
||||
{ 0xFB, 0x8B, 0x6A, 0x9C, 0x79, 0x00, 0xC8, 0x49, 0xEF, 0xD2, 0x4D, 0x85, 0x4D, 0x30, 0xA0, 0xC7 };
|
||||
|
||||
static const u8 mkey_vectors[KB_FIRMWARE_VERSION_MAX + 1][0x10] = {
|
||||
static const u8 mkey_vectors[KB_FIRMWARE_VERSION_MAX + 1][SE_KEY_128_SIZE] = {
|
||||
{ 0x0C, 0xF0, 0x59, 0xAC, 0x85, 0xF6, 0x26, 0x65, 0xE1, 0xE9, 0x19, 0x55, 0xE6, 0xF2, 0x67, 0x3D }, // Zeroes encrypted with mkey 00.
|
||||
{ 0x29, 0x4C, 0x04, 0xC8, 0xEB, 0x10, 0xED, 0x9D, 0x51, 0x64, 0x97, 0xFB, 0xF3, 0x4D, 0x50, 0xDD }, // Mkey 00 encrypted with mkey 01.
|
||||
{ 0xDE, 0xCF, 0xEB, 0xEB, 0x10, 0xAE, 0x74, 0xD8, 0xAD, 0x7C, 0xF4, 0x9E, 0x62, 0xE0, 0xE8, 0x72 }, // Mkey 01 encrypted with mkey 02.
|
||||
@@ -98,7 +120,7 @@ static const u8 mkey_vectors[KB_FIRMWARE_VERSION_MAX + 1][0x10] = {
|
||||
{ 0xB8, 0x96, 0x9E, 0x4A, 0x00, 0x0D, 0xD6, 0x28, 0xB3, 0xD1, 0xDB, 0x68, 0x5F, 0xFB, 0xE1, 0x2A }, // Mkey 09 encrypted with mkey 10.
|
||||
};
|
||||
|
||||
static const u8 new_console_keyseed[KB_FIRMWARE_VERSION_MAX - KB_FIRMWARE_VERSION_400 + 1][0x10] = {
|
||||
static const u8 new_console_keyseed[KB_FIRMWARE_VERSION_MAX - KB_FIRMWARE_VERSION_400 + 1][SE_KEY_128_SIZE] = {
|
||||
{ 0x8B, 0x4E, 0x1C, 0x22, 0x42, 0x07, 0xC8, 0x73, 0x56, 0x94, 0x08, 0x8B, 0xCC, 0x47, 0x0F, 0x5D }, // 4.x New Device Key Source.
|
||||
{ 0x6C, 0xEF, 0xC6, 0x27, 0x8B, 0xEC, 0x8A, 0x91, 0x99, 0xAB, 0x24, 0xAC, 0x4F, 0x1C, 0x8F, 0x1C }, // 5.x New Device Key Source.
|
||||
{ 0x70, 0x08, 0x1B, 0x97, 0x44, 0x64, 0xF8, 0x91, 0x54, 0x9D, 0xC6, 0x84, 0x8F, 0x1A, 0xB2, 0xE4 }, // 6.x New Device Key Source.
|
||||
@@ -109,7 +131,7 @@ static const u8 new_console_keyseed[KB_FIRMWARE_VERSION_MAX - KB_FIRMWARE_VERSIO
|
||||
{ 0x14, 0xB8, 0x74, 0x12, 0xCB, 0xBD, 0x0B, 0x8F, 0x20, 0xFB, 0x30, 0xDA, 0x27, 0xE4, 0x58, 0x94 }, // 9.1.0 New Device Key Source.
|
||||
};
|
||||
|
||||
static const u8 new_console_kekseed[KB_FIRMWARE_VERSION_MAX - KB_FIRMWARE_VERSION_400 + 1][0x10] = {
|
||||
static const u8 new_console_kekseed[KB_FIRMWARE_VERSION_MAX - KB_FIRMWARE_VERSION_400 + 1][SE_KEY_128_SIZE] = {
|
||||
{ 0x88, 0x62, 0x34, 0x6E, 0xFA, 0xF7, 0xD8, 0x3F, 0xE1, 0x30, 0x39, 0x50, 0xF0, 0xB7, 0x5D, 0x5D }, // 4.x New Device Keygen Source.
|
||||
{ 0x06, 0x1E, 0x7B, 0xE9, 0x6D, 0x47, 0x8C, 0x77, 0xC5, 0xC8, 0xE7, 0x94, 0x9A, 0xA8, 0x5F, 0x2E }, // 5.x New Device Keygen Source.
|
||||
{ 0x99, 0xFA, 0x98, 0xBD, 0x15, 0x1C, 0x72, 0xFD, 0x7D, 0x9A, 0xD5, 0x41, 0x00, 0xFD, 0xB2, 0xEF }, // 6.x New Device Keygen Source.
|
||||
@@ -120,19 +142,19 @@ static const u8 new_console_kekseed[KB_FIRMWARE_VERSION_MAX - KB_FIRMWARE_VERSIO
|
||||
{ 0xCE, 0xFE, 0x41, 0x0F, 0x46, 0x9A, 0x30, 0xD6, 0xF2, 0xE9, 0x0C, 0x6B, 0xB7, 0x15, 0x91, 0x36 }, // 9.1.0 New Device Keygen Source.
|
||||
};
|
||||
|
||||
static const u8 gen_keyseed[0x10] =
|
||||
static const u8 gen_keyseed[SE_KEY_128_SIZE] =
|
||||
{ 0x89, 0x61, 0x5E, 0xE0, 0x5C, 0x31, 0xB6, 0x80, 0x5F, 0xE5, 0x8F, 0x3D, 0xA2, 0x4F, 0x7A, 0xA8 };
|
||||
|
||||
static const u8 gen_kekseed[0x10] =
|
||||
static const u8 gen_kekseed[SE_KEY_128_SIZE] =
|
||||
{ 0x4D, 0x87, 0x09, 0x86, 0xC4, 0x5D, 0x20, 0x72, 0x2F, 0xBA, 0x10, 0x53, 0xDA, 0x92, 0xE8, 0xA9 };
|
||||
|
||||
static const u8 gen_keyseed_retail[0x10] =
|
||||
static const u8 gen_keyseed_retail[SE_KEY_128_SIZE] =
|
||||
{ 0xE2, 0xD6, 0xB8, 0x7A, 0x11, 0x9C, 0xB8, 0x80, 0xE8, 0x22, 0x88, 0x8A, 0x46, 0xFB, 0xA1, 0x95 };
|
||||
|
||||
static const u8 bis_kekseed[0x10] =
|
||||
static const u8 bis_kekseed[SE_KEY_128_SIZE] =
|
||||
{ 0x34, 0xC1, 0xA0, 0xC4, 0x82, 0x58, 0xF8, 0xB4, 0xFA, 0x9E, 0x5E, 0x6A, 0xDA, 0xFC, 0x7E, 0x4F };
|
||||
|
||||
static const u8 bis_keyseed[][0x10] = {
|
||||
static const u8 bis_keyseed[][SE_KEY_128_SIZE] = {
|
||||
{ 0xF8, 0x3F, 0x38, 0x6E, 0x2C, 0xD2, 0xCA, 0x32, 0xA8, 0x9A, 0xB9, 0xAA, 0x29, 0xBF, 0xC7, 0x48 }, // BIS 0 Crypt seed.
|
||||
{ 0x7D, 0x92, 0xB0, 0x3A, 0xA8, 0xBF, 0xDE, 0xE1, 0xA7, 0x4C, 0x3B, 0x6E, 0x35, 0xCB, 0x71, 0x06 }, // BIS 0 Tweak seed.
|
||||
{ 0x41, 0x00, 0x30, 0x49, 0xDD, 0xCC, 0xC0, 0x65, 0x64, 0x7A, 0x7E, 0xB4, 0x1E, 0xED, 0x9C, 0x5F }, // BIS 1 Crypt seed.
|
||||
@@ -212,6 +234,8 @@ void hos_eks_save(u32 kb)
|
||||
|
||||
// If matching blob doesn't exist, create it.
|
||||
bool update_eks = key_idx ? (h_cfg.eks->enabled[key_idx] < kb) : !h_cfg.eks->enabled[0];
|
||||
// If old EKS version was found, update it.
|
||||
update_eks |= h_cfg.eks->lot0 != FUSE(FUSE_OPT_LOT_CODE_0);
|
||||
if (update_eks)
|
||||
{
|
||||
// Read EKS blob.
|
||||
@@ -228,8 +252,8 @@ void hos_eks_save(u32 kb)
|
||||
}
|
||||
|
||||
// Get keys.
|
||||
u8 *keys = (u8 *)calloc(0x1000, 1);
|
||||
se_get_aes_keys(keys + 0x800, keys, 0x10);
|
||||
u8 *keys = (u8 *)calloc(0x2000, 1);
|
||||
se_get_aes_keys(keys + 0x1000, keys, SE_KEY_128_SIZE);
|
||||
|
||||
// Set magic and personalized info.
|
||||
h_cfg.eks->magic = HOS_EKS_MAGIC;
|
||||
@@ -237,18 +261,18 @@ void hos_eks_save(u32 kb)
|
||||
h_cfg.eks->lot0 = FUSE(FUSE_OPT_LOT_CODE_0);
|
||||
|
||||
// Copy new keys.
|
||||
memcpy(h_cfg.eks->dkg, keys + 10 * 0x10, 0x10);
|
||||
memcpy(h_cfg.eks->dkk, keys + 15 * 0x10, 0x10);
|
||||
memcpy(h_cfg.eks->dkg, keys + 10 * SE_KEY_128_SIZE, SE_KEY_128_SIZE);
|
||||
memcpy(h_cfg.eks->dkk, keys + 15 * SE_KEY_128_SIZE, SE_KEY_128_SIZE);
|
||||
|
||||
if (!h_cfg.aes_slots_new)
|
||||
{
|
||||
memcpy(h_cfg.eks->keys[key_idx].mkk, keys + 12 * 0x10, 0x10);
|
||||
memcpy(h_cfg.eks->keys[key_idx].fdk, keys + 13 * 0x10, 0x10);
|
||||
memcpy(h_cfg.eks->keys[key_idx].mkk, keys + 12 * SE_KEY_128_SIZE, SE_KEY_128_SIZE);
|
||||
memcpy(h_cfg.eks->keys[key_idx].fdk, keys + 13 * SE_KEY_128_SIZE, SE_KEY_128_SIZE);
|
||||
}
|
||||
else // New sept slots.
|
||||
{
|
||||
memcpy(h_cfg.eks->keys[key_idx].mkk, keys + 13 * 0x10, 0x10);
|
||||
memcpy(h_cfg.eks->keys[key_idx].fdk, keys + 12 * 0x10, 0x10);
|
||||
memcpy(h_cfg.eks->keys[key_idx].mkk, keys + 13 * SE_KEY_128_SIZE, SE_KEY_128_SIZE);
|
||||
memcpy(h_cfg.eks->keys[key_idx].fdk, keys + 12 * SE_KEY_128_SIZE, SE_KEY_128_SIZE);
|
||||
}
|
||||
|
||||
// Encrypt EKS blob.
|
||||
@@ -260,7 +284,6 @@ void hos_eks_save(u32 kb)
|
||||
memcpy(mbr + 0x80, eks, sizeof(hos_eks_mbr_t));
|
||||
hos_eks_rw_try(mbr, true);
|
||||
|
||||
|
||||
free(eks);
|
||||
free(keys);
|
||||
out:
|
||||
@@ -346,14 +369,14 @@ void hos_eks_bis_save()
|
||||
h_cfg.eks->lot0 = FUSE(FUSE_OPT_LOT_CODE_0);
|
||||
|
||||
// Copy new keys.
|
||||
memcpy(h_cfg.eks->bis_keys[0].crypt, bis_keys + (0 * 0x10), 0x10);
|
||||
memcpy(h_cfg.eks->bis_keys[0].tweak, bis_keys + (1 * 0x10), 0x10);
|
||||
memcpy(h_cfg.eks->bis_keys[0].crypt, bis_keys + (0 * SE_KEY_128_SIZE), SE_KEY_128_SIZE);
|
||||
memcpy(h_cfg.eks->bis_keys[0].tweak, bis_keys + (1 * SE_KEY_128_SIZE), SE_KEY_128_SIZE);
|
||||
|
||||
memcpy(h_cfg.eks->bis_keys[1].crypt, bis_keys + (2 * 0x10), 0x10);
|
||||
memcpy(h_cfg.eks->bis_keys[1].tweak, bis_keys + (3 * 0x10), 0x10);
|
||||
memcpy(h_cfg.eks->bis_keys[1].crypt, bis_keys + (2 * SE_KEY_128_SIZE), SE_KEY_128_SIZE);
|
||||
memcpy(h_cfg.eks->bis_keys[1].tweak, bis_keys + (3 * SE_KEY_128_SIZE), SE_KEY_128_SIZE);
|
||||
|
||||
memcpy(h_cfg.eks->bis_keys[2].crypt, bis_keys + (4 * 0x10), 0x10);
|
||||
memcpy(h_cfg.eks->bis_keys[2].tweak, bis_keys + (5 * 0x10), 0x10);
|
||||
memcpy(h_cfg.eks->bis_keys[2].crypt, bis_keys + (4 * SE_KEY_128_SIZE), SE_KEY_128_SIZE);
|
||||
memcpy(h_cfg.eks->bis_keys[2].tweak, bis_keys + (5 * SE_KEY_128_SIZE), SE_KEY_128_SIZE);
|
||||
|
||||
// Encrypt EKS blob.
|
||||
u8 *eks = calloc(512 , 1);
|
||||
@@ -418,10 +441,11 @@ int hos_keygen_t210b01(u32 kb)
|
||||
return 1;
|
||||
}
|
||||
|
||||
int hos_keygen(u8 *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt)
|
||||
int hos_keygen(void *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt)
|
||||
{
|
||||
u8 tmp[0x30];
|
||||
u32 retries = 0;
|
||||
tsec_keys_t tsec_keys;
|
||||
kb_t *kb_data = (kb_t *)keyblob;
|
||||
|
||||
if (kb > KB_FIRMWARE_VERSION_MAX)
|
||||
return 0;
|
||||
@@ -449,9 +473,9 @@ int hos_keygen(u8 *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt)
|
||||
// Get TSEC key.
|
||||
if (kb <= KB_FIRMWARE_VERSION_620)
|
||||
{
|
||||
while (tsec_query(tmp, kb, tsec_ctxt) < 0)
|
||||
while (tsec_query(&tsec_keys, kb, tsec_ctxt) < 0)
|
||||
{
|
||||
memset(tmp, 0x00, 0x20);
|
||||
memset(&tsec_keys, 0x00, 0x20);
|
||||
retries++;
|
||||
|
||||
// We rely on racing conditions, make sure we cover even the unluckiest cases.
|
||||
@@ -473,13 +497,13 @@ int hos_keygen(u8 *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt)
|
||||
if (h_cfg.eks && h_cfg.eks->enabled[key_idx] >= kb)
|
||||
{
|
||||
// Set Device keygen key to slot 10.
|
||||
se_aes_key_set(10, h_cfg.eks->dkg, 0x10);
|
||||
se_aes_key_set(10, h_cfg.eks->dkg, SE_KEY_128_SIZE);
|
||||
// Set Master key to slot 12.
|
||||
se_aes_key_set(12, h_cfg.eks->keys[key_idx].mkk, 0x10);
|
||||
se_aes_key_set(12, h_cfg.eks->keys[key_idx].mkk, SE_KEY_128_SIZE);
|
||||
// Set FW Device key key to slot 13.
|
||||
se_aes_key_set(13, h_cfg.eks->keys[key_idx].fdk, 0x10);
|
||||
se_aes_key_set(13, h_cfg.eks->keys[key_idx].fdk, SE_KEY_128_SIZE);
|
||||
// Set Device key to slot 15.
|
||||
se_aes_key_set(15, h_cfg.eks->dkk, 0x10);
|
||||
se_aes_key_set(15, h_cfg.eks->dkk, SE_KEY_128_SIZE);
|
||||
}
|
||||
else
|
||||
h_cfg.aes_slots_new = se_key_acc_ctrl_get(12) == 0x6A;
|
||||
@@ -490,13 +514,13 @@ int hos_keygen(u8 *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt)
|
||||
else if (kb == KB_FIRMWARE_VERSION_620)
|
||||
{
|
||||
// Set TSEC key.
|
||||
se_aes_key_set(12, tmp, 0x10);
|
||||
se_aes_key_set(12, tsec_keys.tsec, SE_KEY_128_SIZE);
|
||||
// Set TSEC root key.
|
||||
se_aes_key_set(13, tmp + 0x10, 0x10);
|
||||
se_aes_key_set(13, tsec_keys.tsec_root, SE_KEY_128_SIZE);
|
||||
|
||||
// Decrypt keyblob and set keyslots
|
||||
se_aes_crypt_block_ecb(12, 0, tmp + 0x20, keyblob_keyseeds[0]);
|
||||
se_aes_unwrap_key(15, 14, tmp + 0x20);
|
||||
se_aes_crypt_block_ecb(12, 0, tsec_keys.tmp, keyblob_keyseeds[0]);
|
||||
se_aes_unwrap_key(15, 14, tsec_keys.tmp);
|
||||
se_aes_unwrap_key(10, 15, console_keyseed_4xx_5xx);
|
||||
se_aes_unwrap_key(15, 15, console_keyseed);
|
||||
|
||||
@@ -508,33 +532,37 @@ int hos_keygen(u8 *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt)
|
||||
else
|
||||
{
|
||||
// Set TSEC key.
|
||||
se_aes_key_set(13, tmp, 0x10);
|
||||
se_aes_key_set(13, tsec_keys.tsec, SE_KEY_128_SIZE);
|
||||
|
||||
// Derive keyblob keys from TSEC+SBK.
|
||||
se_aes_crypt_block_ecb(13, 0, tmp, keyblob_keyseeds[0]);
|
||||
se_aes_unwrap_key(15, 14, tmp);
|
||||
se_aes_crypt_block_ecb(13, 0, tmp, keyblob_keyseeds[kb]);
|
||||
se_aes_unwrap_key(13, 14, tmp);
|
||||
se_aes_crypt_block_ecb(13, 0, tsec_keys.tsec, keyblob_keyseeds[0]);
|
||||
se_aes_unwrap_key(15, 14, tsec_keys.tsec);
|
||||
se_aes_crypt_block_ecb(13, 0, tsec_keys.tsec, keyblob_keyseeds[kb]);
|
||||
se_aes_unwrap_key(13, 14, tsec_keys.tsec);
|
||||
|
||||
// Clear SBK.
|
||||
se_aes_key_clear(14);
|
||||
if (!h_cfg.sbk_set)
|
||||
se_aes_key_clear(14);
|
||||
|
||||
//TODO: verify keyblob CMAC.
|
||||
//se_aes_unwrap_key(11, 13, cmac_keyseed);
|
||||
//se_aes_cmac(tmp, 0x10, 11, keyblob + 0x10, 0xA0);
|
||||
//if (!memcmp(keyblob, tmp, 0x10))
|
||||
// return 0;
|
||||
/*
|
||||
// Verify keyblob CMAC.
|
||||
u8 cmac[SE_KEY_128_SIZE];
|
||||
se_aes_unwrap_key(11, 13, cmac_keyseed);
|
||||
se_aes_cmac(cmac, SE_KEY_128_SIZE, 11, (void *)kb_data->ctr, sizeof(kb_data->ctr) + sizeof(kb_data->keys));
|
||||
if (!memcmp(kb_data->cmac, cmac, SE_KEY_128_SIZE))
|
||||
return 0;
|
||||
*/
|
||||
|
||||
se_aes_crypt_block_ecb(13, 0, tmp, cmac_keyseed);
|
||||
se_aes_crypt_block_ecb(13, 0, tsec_keys.tsec, cmac_keyseed);
|
||||
se_aes_unwrap_key(11, 13, cmac_keyseed);
|
||||
|
||||
// Decrypt keyblob and set keyslots.
|
||||
se_aes_crypt_ctr(13, keyblob + 0x20, 0x90, keyblob + 0x20, 0x90, keyblob + 0x10);
|
||||
se_aes_key_set(11, keyblob + 0x20 + 0x80, 0x10); // Package1 key.
|
||||
se_aes_key_set(12, keyblob + 0x20, 0x10);
|
||||
se_aes_key_set(13, keyblob + 0x20, 0x10);
|
||||
se_aes_crypt_ctr(13, &kb_data->keys, sizeof(kb_data->keys), &kb_data->keys, sizeof(kb_data->keys), kb_data->ctr);
|
||||
se_aes_key_set(11, kb_data->keys.package1_key, SE_KEY_128_SIZE);
|
||||
se_aes_key_set(12, kb_data->keys.master_keyseed, SE_KEY_128_SIZE);
|
||||
se_aes_key_set(13, kb_data->keys.master_keyseed, SE_KEY_128_SIZE);
|
||||
|
||||
se_aes_crypt_block_ecb(12, 0, tmp, master_keyseed_retail);
|
||||
se_aes_crypt_block_ecb(12, 0, tsec_keys.tsec, master_keyseed_retail);
|
||||
|
||||
switch (kb)
|
||||
{
|
||||
@@ -547,14 +575,16 @@ int hos_keygen(u8 *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt)
|
||||
case KB_FIRMWARE_VERSION_400:
|
||||
se_aes_unwrap_key(13, 15, console_keyseed_4xx_5xx);
|
||||
se_aes_unwrap_key(15, 15, console_keyseed);
|
||||
se_aes_unwrap_key(14, 12, master_keyseed_4xx_5xx_610);
|
||||
if (!h_cfg.sbk_set) // Do not clear SBK if patched. In this context the below key is useless.
|
||||
se_aes_unwrap_key(14, 12, master_keyseed_4xx_5xx_610);
|
||||
se_aes_unwrap_key(12, 12, master_keyseed_retail);
|
||||
break;
|
||||
case KB_FIRMWARE_VERSION_500:
|
||||
case KB_FIRMWARE_VERSION_600:
|
||||
se_aes_unwrap_key(10, 15, console_keyseed_4xx_5xx);
|
||||
se_aes_unwrap_key(15, 15, console_keyseed);
|
||||
se_aes_unwrap_key(14, 12, master_keyseed_4xx_5xx_610);
|
||||
if (!h_cfg.sbk_set) // Do not clear SBK if patched. In this context the below key is useless.
|
||||
se_aes_unwrap_key(14, 12, master_keyseed_4xx_5xx_610);
|
||||
se_aes_unwrap_key(12, 12, master_keyseed_retail);
|
||||
break;
|
||||
}
|
||||
@@ -568,18 +598,18 @@ int hos_keygen(u8 *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt)
|
||||
|
||||
static void _hos_validate_sept_mkey(u32 kb)
|
||||
{
|
||||
u8 tmp_mkey[0x10];
|
||||
u32 mkey_idx = sizeof(mkey_vectors) / 0x10;
|
||||
u8 tmp_mkey[SE_KEY_128_SIZE];
|
||||
u32 mkey_idx = sizeof(mkey_vectors) / SE_KEY_128_SIZE;
|
||||
u8 mkey_slot = !h_cfg.aes_slots_new ? 12 : 13;
|
||||
do
|
||||
{
|
||||
mkey_idx--;
|
||||
se_aes_crypt_ecb(mkey_slot, 0, tmp_mkey, 0x10, mkey_vectors[mkey_idx], 0x10);
|
||||
se_aes_crypt_ecb(mkey_slot, 0, tmp_mkey, SE_KEY_128_SIZE, mkey_vectors[mkey_idx], SE_KEY_128_SIZE);
|
||||
for (u32 idx = 0; idx < mkey_idx; idx++)
|
||||
{
|
||||
se_aes_key_clear(2);
|
||||
se_aes_key_set(2, tmp_mkey, 0x10);
|
||||
se_aes_crypt_ecb(2, 0, tmp_mkey, 0x10, mkey_vectors[mkey_idx - 1 - idx], 0x10);
|
||||
se_aes_key_set(2, tmp_mkey, SE_KEY_128_SIZE);
|
||||
se_aes_crypt_ecb(2, 0, tmp_mkey, SE_KEY_128_SIZE, mkey_vectors[mkey_idx - 1 - idx], SE_KEY_128_SIZE);
|
||||
}
|
||||
|
||||
if (!memcmp(tmp_mkey, "\x00\x00\x00\x00\x00\x00\x00\x00", 8))
|
||||
@@ -597,23 +627,23 @@ static void _hos_validate_sept_mkey(u32 kb)
|
||||
static void _hos_bis_print_key(u32 idx, u8 *key)
|
||||
{
|
||||
gfx_printf("BIS %d Crypt: ", idx);
|
||||
for (int i = 0; i < 0x10; i++)
|
||||
gfx_printf("%02X", key[((idx * 2 + 0) * 0x10) + i]);
|
||||
for (int i = 0; i < SE_KEY_128_SIZE; i++)
|
||||
gfx_printf("%02X", key[((idx * 2 + 0) * SE_KEY_128_SIZE) + i]);
|
||||
gfx_puts("\n");
|
||||
|
||||
gfx_printf("BIS %d Tweak: ", idx);
|
||||
for (int i = 0; i < 0x10; i++)
|
||||
gfx_printf("%02X", key[((idx * 2 + 1) * 0x10) + i]);
|
||||
for (int i = 0; i < SE_KEY_128_SIZE; i++)
|
||||
gfx_printf("%02X", key[((idx * 2 + 1) * SE_KEY_128_SIZE) + i]);
|
||||
gfx_puts("\n");
|
||||
}
|
||||
|
||||
int hos_bis_keygen(u8 *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt)
|
||||
int hos_bis_keygen(void *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt)
|
||||
{
|
||||
u32 keygen_rev = 0;
|
||||
u32 console_key_slot = kb >= KB_FIRMWARE_VERSION_400 ? 15 : 13;
|
||||
|
||||
if (!bis_keys)
|
||||
bis_keys = malloc(0x10 * 6);
|
||||
bis_keys = malloc(SE_KEY_128_SIZE * 6);
|
||||
|
||||
if (!h_cfg.eks || !h_cfg.eks->enabled_bis)
|
||||
{
|
||||
@@ -627,8 +657,8 @@ int hos_bis_keygen(u8 *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt)
|
||||
|
||||
if (keygen_rev)
|
||||
{
|
||||
u8 tmp_mkey[0x10];
|
||||
u32 mkey_idx = sizeof(mkey_vectors) / 0x10;
|
||||
u8 tmp_mkey[SE_KEY_128_SIZE];
|
||||
u32 mkey_idx = sizeof(mkey_vectors) / SE_KEY_128_SIZE;
|
||||
u8 mkey_slot = kb >= KB_FIRMWARE_VERSION_700 ? (!h_cfg.aes_slots_new ? 12 : 13) : (kb == KB_FIRMWARE_VERSION_620 ? 9 : 12);
|
||||
|
||||
// Keygen revision uses bootloader version, which starts from 1.
|
||||
@@ -642,19 +672,19 @@ int hos_bis_keygen(u8 *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt)
|
||||
do
|
||||
{
|
||||
mkey_idx--;
|
||||
se_aes_crypt_ecb(mkey_slot, 0, tmp_mkey, 0x10, mkey_vectors[mkey_idx], 0x10);
|
||||
se_aes_crypt_ecb(mkey_slot, 0, tmp_mkey, SE_KEY_128_SIZE, mkey_vectors[mkey_idx], SE_KEY_128_SIZE);
|
||||
for (u32 idx = 0; idx < mkey_idx; idx++)
|
||||
{
|
||||
se_aes_key_clear(2);
|
||||
se_aes_key_set(2, tmp_mkey, 0x10);
|
||||
se_aes_crypt_ecb(2, 0, tmp_mkey, 0x10, mkey_vectors[mkey_idx - 1 - idx], 0x10);
|
||||
se_aes_key_set(2, tmp_mkey, SE_KEY_128_SIZE);
|
||||
se_aes_crypt_ecb(2, 0, tmp_mkey, SE_KEY_128_SIZE, mkey_vectors[mkey_idx - 1 - idx], SE_KEY_128_SIZE);
|
||||
}
|
||||
} while (memcmp(tmp_mkey, "\x00\x00\x00\x00\x00\x00\x00\x00", 8) != 0 && (mkey_idx - 1));
|
||||
|
||||
// Derive new device key.
|
||||
se_aes_key_clear(1);
|
||||
se_aes_unwrap_key(1, 10, new_console_keyseed[keygen_rev]); // Uses Device key 4x.
|
||||
se_aes_crypt_ecb(10, 0, tmp_mkey, 0x10, new_console_keyseed[keygen_rev], 0x10); // Uses Device key 4x.
|
||||
se_aes_crypt_ecb(10, 0, tmp_mkey, SE_KEY_128_SIZE, new_console_keyseed[keygen_rev], SE_KEY_128_SIZE); // Uses Device key 4x.
|
||||
se_aes_unwrap_key(1, 2, new_console_kekseed[keygen_rev]); // Uses Master Key 0.
|
||||
se_aes_unwrap_key(1, 1, tmp_mkey);
|
||||
|
||||
@@ -666,11 +696,11 @@ int hos_bis_keygen(u8 *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt)
|
||||
se_aes_unwrap_key(2, console_key_slot, gen_keyseed_retail);
|
||||
|
||||
// Clear bis keys storage.
|
||||
memset(bis_keys, 0, 0x10 * 6);
|
||||
memset(bis_keys, 0, SE_KEY_128_SIZE * 6);
|
||||
|
||||
// Generate BIS 0 Keys.
|
||||
se_aes_crypt_block_ecb(2, 0, bis_keys + (0 * 0x10), bis_keyseed[0]);
|
||||
se_aes_crypt_block_ecb(2, 0, bis_keys + (1 * 0x10), bis_keyseed[1]);
|
||||
se_aes_crypt_block_ecb(2, 0, bis_keys + (0 * SE_KEY_128_SIZE), bis_keyseed[0]);
|
||||
se_aes_crypt_block_ecb(2, 0, bis_keys + (1 * SE_KEY_128_SIZE), bis_keyseed[1]);
|
||||
|
||||
// Generate generic kek.
|
||||
se_aes_key_clear(2);
|
||||
@@ -679,26 +709,26 @@ int hos_bis_keygen(u8 *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt)
|
||||
se_aes_unwrap_key(2, 2, gen_keyseed);
|
||||
|
||||
// Generate BIS 1 Keys.
|
||||
se_aes_crypt_block_ecb(2, 0, bis_keys + (2 * 0x10), bis_keyseed[2]);
|
||||
se_aes_crypt_block_ecb(2, 0, bis_keys + (3 * 0x10), bis_keyseed[3]);
|
||||
se_aes_crypt_block_ecb(2, 0, bis_keys + (2 * SE_KEY_128_SIZE), bis_keyseed[2]);
|
||||
se_aes_crypt_block_ecb(2, 0, bis_keys + (3 * SE_KEY_128_SIZE), bis_keyseed[3]);
|
||||
|
||||
// Generate BIS 2/3 Keys.
|
||||
se_aes_crypt_block_ecb(2, 0, bis_keys + (4 * 0x10), bis_keyseed[4]);
|
||||
se_aes_crypt_block_ecb(2, 0, bis_keys + (5 * 0x10), bis_keyseed[5]);
|
||||
se_aes_crypt_block_ecb(2, 0, bis_keys + (4 * SE_KEY_128_SIZE), bis_keyseed[4]);
|
||||
se_aes_crypt_block_ecb(2, 0, bis_keys + (5 * SE_KEY_128_SIZE), bis_keyseed[5]);
|
||||
|
||||
if (!h_cfg.t210b01 && kb >= KB_FIRMWARE_VERSION_700)
|
||||
_hos_validate_sept_mkey(kb);
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(bis_keys + (0 * 0x10), h_cfg.eks->bis_keys[0].crypt, 0x10);
|
||||
memcpy(bis_keys + (1 * 0x10), h_cfg.eks->bis_keys[0].tweak, 0x10);
|
||||
memcpy(bis_keys + (0 * SE_KEY_128_SIZE), h_cfg.eks->bis_keys[0].crypt, SE_KEY_128_SIZE);
|
||||
memcpy(bis_keys + (1 * SE_KEY_128_SIZE), h_cfg.eks->bis_keys[0].tweak, SE_KEY_128_SIZE);
|
||||
|
||||
memcpy(bis_keys + (2 * 0x10), h_cfg.eks->bis_keys[1].crypt, 0x10);
|
||||
memcpy(bis_keys + (3 * 0x10), h_cfg.eks->bis_keys[1].tweak, 0x10);
|
||||
memcpy(bis_keys + (2 * SE_KEY_128_SIZE), h_cfg.eks->bis_keys[1].crypt, SE_KEY_128_SIZE);
|
||||
memcpy(bis_keys + (3 * SE_KEY_128_SIZE), h_cfg.eks->bis_keys[1].tweak, SE_KEY_128_SIZE);
|
||||
|
||||
memcpy(bis_keys + (4 * 0x10), h_cfg.eks->bis_keys[2].crypt, 0x10);
|
||||
memcpy(bis_keys + (5 * 0x10), h_cfg.eks->bis_keys[2].tweak, 0x10);
|
||||
memcpy(bis_keys + (4 * SE_KEY_128_SIZE), h_cfg.eks->bis_keys[2].crypt, SE_KEY_128_SIZE);
|
||||
memcpy(bis_keys + (5 * SE_KEY_128_SIZE), h_cfg.eks->bis_keys[2].tweak, SE_KEY_128_SIZE);
|
||||
}
|
||||
|
||||
_hos_bis_print_key(0, bis_keys);
|
||||
@@ -710,14 +740,14 @@ int hos_bis_keygen(u8 *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt)
|
||||
se_aes_key_clear(i);
|
||||
|
||||
// Set BIS keys.
|
||||
se_aes_key_set(0, bis_keys + (0 * 0x10), 0x10);
|
||||
se_aes_key_set(1, bis_keys + (1 * 0x10), 0x10);
|
||||
se_aes_key_set(0, bis_keys + (0 * SE_KEY_128_SIZE), SE_KEY_128_SIZE);
|
||||
se_aes_key_set(1, bis_keys + (1 * SE_KEY_128_SIZE), SE_KEY_128_SIZE);
|
||||
|
||||
se_aes_key_set(2, bis_keys + (2 * 0x10), 0x10);
|
||||
se_aes_key_set(3, bis_keys + (3 * 0x10), 0x10);
|
||||
se_aes_key_set(2, bis_keys + (2 * SE_KEY_128_SIZE), SE_KEY_128_SIZE);
|
||||
se_aes_key_set(3, bis_keys + (3 * SE_KEY_128_SIZE), SE_KEY_128_SIZE);
|
||||
|
||||
se_aes_key_set(4, bis_keys + (4 * 0x10), 0x10);
|
||||
se_aes_key_set(5, bis_keys + (5 * 0x10), 0x10);
|
||||
se_aes_key_set(4, bis_keys + (4 * SE_KEY_128_SIZE), SE_KEY_128_SIZE);
|
||||
se_aes_key_set(5, bis_keys + (5 * SE_KEY_128_SIZE), SE_KEY_128_SIZE);
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -742,7 +772,7 @@ void hos_bis_keys_clear()
|
||||
FUSE(FUSE_PRIVATE_KEY3)
|
||||
};
|
||||
// Set SBK to slot 14.
|
||||
se_aes_key_set(14, sbk, 0x10);
|
||||
se_aes_key_set(14, sbk, SE_KEY_128_SIZE);
|
||||
|
||||
// Lock SBK from being read.
|
||||
se_key_acc_ctrl(14, SE_KEY_TBL_DIS_KEYREAD_FLAG);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2018-2020 CTCaer
|
||||
* Copyright (c) 2018-2021 CTCaer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
@@ -20,6 +20,7 @@
|
||||
|
||||
#include "pkg1.h"
|
||||
#include "pkg2.h"
|
||||
#include <sec/se_t210.h>
|
||||
#include <utils/types.h>
|
||||
#include <utils/ini.h>
|
||||
#include <sec/tsec.h>
|
||||
@@ -44,14 +45,14 @@
|
||||
|
||||
typedef struct _hos_eks_keys_t
|
||||
{
|
||||
u8 mkk[0x10];
|
||||
u8 fdk[0x10];
|
||||
u8 mkk[SE_KEY_128_SIZE];
|
||||
u8 fdk[SE_KEY_128_SIZE];
|
||||
} hos_eks_keys_t;
|
||||
|
||||
typedef struct _hos_eks_bis_keys_t
|
||||
{
|
||||
u8 crypt[0x10];
|
||||
u8 tweak[0x10];
|
||||
u8 crypt[SE_KEY_128_SIZE];
|
||||
u8 tweak[SE_KEY_128_SIZE];
|
||||
} hos_eks_bis_keys_t;
|
||||
|
||||
typedef struct _hos_eks_mbr_t
|
||||
@@ -61,8 +62,8 @@ typedef struct _hos_eks_mbr_t
|
||||
u8 enabled_bis;
|
||||
u8 rsvd[2];
|
||||
u32 lot0;
|
||||
u8 dkg[0x10];
|
||||
u8 dkk[0x10];
|
||||
u8 dkg[SE_KEY_128_SIZE];
|
||||
u8 dkk[SE_KEY_128_SIZE];
|
||||
hos_eks_keys_t keys[5];
|
||||
hos_eks_bis_keys_t bis_keys[3];
|
||||
} hos_eks_mbr_t;
|
||||
@@ -98,8 +99,8 @@ void hos_eks_save(u32 kb);
|
||||
void hos_eks_clear(u32 kb);
|
||||
void hos_eks_bis_save();
|
||||
void hos_eks_bis_clear();
|
||||
int hos_keygen(u8 *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt);
|
||||
int hos_bis_keygen(u8 *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt);
|
||||
int hos_keygen(void *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt);
|
||||
int hos_bis_keygen(void *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt);
|
||||
void hos_bis_keys_clear();
|
||||
|
||||
#endif
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include <libs/fatfs/ff.h>
|
||||
#include <mem/heap.h>
|
||||
#include <sec/se.h>
|
||||
#include <sec/se_t210.h>
|
||||
#include <libs/compr/blz.h>
|
||||
|
||||
#include <gfx_utils.h>
|
||||
@@ -111,7 +112,7 @@ DPRINTF(" kip1 %d:%s @ %08X (%08X)\n", i, kip1->name, (u32)kip1, ki->size);
|
||||
return true;
|
||||
}
|
||||
|
||||
static const u8 mkey_vector_8xx[][0x10] =
|
||||
static const u8 mkey_vector_8xx[][SE_KEY_128_SIZE] =
|
||||
{
|
||||
// Master key 8 encrypted with 9. (8.1.0 with 9.0.0)
|
||||
{ 0x4D, 0xD9, 0x98, 0x42, 0x45, 0x0D, 0xB1, 0x3C, 0x52, 0x0C, 0x9A, 0x44, 0xBB, 0xAD, 0xAF, 0x80 },
|
||||
@@ -122,10 +123,10 @@ static const u8 mkey_vector_8xx[][0x10] =
|
||||
static bool _pkg2_key_unwrap_validate(pkg2_hdr_t *tmp_test, pkg2_hdr_t *hdr, u8 src_slot, u8 *mkey, const u8 *key_seed)
|
||||
{
|
||||
// Decrypt older encrypted mkey.
|
||||
se_aes_crypt_ecb(src_slot, 0, mkey, 0x10, key_seed, 0x10);
|
||||
se_aes_crypt_ecb(src_slot, 0, mkey, SE_KEY_128_SIZE, key_seed, SE_KEY_128_SIZE);
|
||||
// Set and unwrap pkg2 key.
|
||||
se_aes_key_clear(9);
|
||||
se_aes_key_set(9, mkey, 0x10);
|
||||
se_aes_key_set(9, mkey, SE_KEY_128_SIZE);
|
||||
se_aes_unwrap_key(9, 9, package2_keyseed);
|
||||
|
||||
// Decrypt header.
|
||||
@@ -158,9 +159,9 @@ pkg2_hdr_t *pkg2_decrypt(void *data, u8 kb)
|
||||
// Decrypt older pkg2 via new mkeys.
|
||||
if ((kb >= KB_FIRMWARE_VERSION_810) && (kb < KB_FIRMWARE_VERSION_MAX))
|
||||
{
|
||||
u8 tmp_mkey[0x10];
|
||||
u8 tmp_mkey[SE_KEY_128_SIZE];
|
||||
u8 decr_slot = !h_cfg.t210b01 ? (!h_cfg.aes_slots_new ? 12 : 13) : 7; // Sept mkey or T210B01 mkey.
|
||||
u8 mkey_seeds_cnt = sizeof(mkey_vector_8xx) / 0x10;
|
||||
u8 mkey_seeds_cnt = sizeof(mkey_vector_8xx) / SE_KEY_128_SIZE;
|
||||
u8 mkey_seeds_idx = mkey_seeds_cnt; // Real index + 1.
|
||||
u8 mkey_seeds_min_idx = mkey_seeds_cnt - (KB_FIRMWARE_VERSION_MAX - kb);
|
||||
|
||||
@@ -180,7 +181,7 @@ pkg2_hdr_t *pkg2_decrypt(void *data, u8 kb)
|
||||
// Set current mkey in order to decrypt a lower mkey.
|
||||
mkey_seeds_idx--;
|
||||
se_aes_key_clear(9);
|
||||
se_aes_key_set(9, tmp_mkey, 0x10);
|
||||
se_aes_key_set(9, tmp_mkey, SE_KEY_128_SIZE);
|
||||
|
||||
decr_slot = 9; // Temp key.
|
||||
|
||||
@@ -214,7 +215,7 @@ DPRINTF("sec %d has size %08X\n", i, hdr->sec_size[i]);
|
||||
if (!hdr->sec_size[i])
|
||||
continue;
|
||||
|
||||
se_aes_crypt_ctr(keyslot, pdata, hdr->sec_size[i], pdata, hdr->sec_size[i], &hdr->sec_ctr[i * 0x10]);
|
||||
se_aes_crypt_ctr(keyslot, pdata, hdr->sec_size[i], pdata, hdr->sec_size[i], &hdr->sec_ctr[i * SE_AES_IV_SIZE]);
|
||||
//gfx_hexdump((u32)pdata, pdata, 0x100);
|
||||
|
||||
pdata += hdr->sec_size[i];
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019 CTCaer
|
||||
* Copyright (c) 2019-2021 CTCaer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
@@ -68,72 +68,6 @@ extern volatile nyx_storage_t *nyx_str;
|
||||
extern bool is_ipl_updated(void *buf);
|
||||
extern void reloc_patcher(u32 payload_dst, u32 payload_src, u32 payload_size);
|
||||
|
||||
void check_sept()
|
||||
{
|
||||
if (h_cfg.t210b01)
|
||||
{
|
||||
h_cfg.sept_run = true;
|
||||
return;
|
||||
}
|
||||
|
||||
hos_eks_get();
|
||||
|
||||
// Check if non-hekate payload is used for sept and restore it.
|
||||
if (h_cfg.sept_run)
|
||||
{
|
||||
if (!f_stat("sept/payload.bak", NULL))
|
||||
{
|
||||
f_unlink("sept/payload.bin");
|
||||
f_rename("sept/payload.bak", "sept/payload.bin");
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
u8 *pkg1 = (u8 *)calloc(1, 0x40000);
|
||||
|
||||
sdmmc_storage_t storage;
|
||||
sdmmc_t sdmmc;
|
||||
if (!sdmmc_storage_init_mmc(&storage, &sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400))
|
||||
{
|
||||
EPRINTF("Failed to init eMMC.");
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
sdmmc_storage_set_mmc_partition(&storage, EMMC_BOOT0);
|
||||
|
||||
// Read package1.
|
||||
char *build_date = malloc(32);
|
||||
sdmmc_storage_read(&storage, 0x100000 / NX_EMMC_BLOCKSIZE, 0x40000 / NX_EMMC_BLOCKSIZE, pkg1);
|
||||
const pkg1_id_t *pkg1_id = pkg1_identify(pkg1, build_date);
|
||||
free(build_date);
|
||||
if (!pkg1_id)
|
||||
{
|
||||
EPRINTF("Unknown pkg1 version.");
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
if (pkg1_id->kb >= KB_FIRMWARE_VERSION_700 && !h_cfg.sept_run)
|
||||
{
|
||||
u32 key_idx = 0;
|
||||
if (pkg1_id->kb >= KB_FIRMWARE_VERSION_810)
|
||||
key_idx = 1;
|
||||
|
||||
if (h_cfg.eks && h_cfg.eks->enabled[key_idx] >= pkg1_id->kb)
|
||||
{
|
||||
h_cfg.sept_run = true;
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
sdmmc_storage_end(&storage);
|
||||
reboot_to_sept((u8 *)pkg1 + pkg1_id->tsec_off, pkg1_id->kb);
|
||||
}
|
||||
|
||||
out_free:
|
||||
free(pkg1);
|
||||
sdmmc_storage_end(&storage);
|
||||
}
|
||||
|
||||
int reboot_to_sept(const u8 *tsec_fw, u32 kb)
|
||||
{
|
||||
FIL fp;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019 CTCaer
|
||||
* Copyright (c) 2019-2021 CTCaer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
@@ -19,7 +19,8 @@
|
||||
|
||||
#include <utils/types.h>
|
||||
|
||||
void check_sept();
|
||||
#define SEPT_PRI_ENTRY 0x40010340
|
||||
|
||||
int reboot_to_sept(const u8 *tsec_fw, u32 kb);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -16,6 +16,10 @@
|
||||
#include <storage/ramdisk.h>
|
||||
#include <storage/sdmmc.h>
|
||||
|
||||
static u32 sd_rsvd_sectors = 0;
|
||||
static u32 ramdisk_sectors = 0;
|
||||
static u32 emummc_sectors = 0;
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* Get Drive Status */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
@@ -55,7 +59,8 @@ DRESULT disk_read (
|
||||
case DRIVE_EMMC:
|
||||
return sdmmc_storage_read(&emmc_storage, sector, count, (void *)buff) ? RES_OK : RES_ERROR;
|
||||
case DRIVE_BIS:
|
||||
return nx_emmc_bis_read(sector, count, (void *)buff);
|
||||
case DRIVE_EMU:
|
||||
return nx_emmc_bis_read(sector, count, (void *)buff) ? RES_OK : RES_ERROR;
|
||||
}
|
||||
|
||||
return RES_ERROR;
|
||||
@@ -80,6 +85,8 @@ DRESULT disk_write (
|
||||
case DRIVE_EMMC:
|
||||
case DRIVE_BIS:
|
||||
return RES_WRPRT;
|
||||
case DRIVE_EMU:
|
||||
return nx_emmc_bis_write(sector, count, (void *)buff) ? RES_OK : RES_ERROR;
|
||||
}
|
||||
|
||||
return RES_ERROR;
|
||||
@@ -88,7 +95,6 @@ DRESULT disk_write (
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* Miscellaneous Functions */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
static u32 part_rsvd_size = 0;
|
||||
DRESULT disk_ioctl (
|
||||
BYTE pdrv, /* Physical drive nmuber (0..) */
|
||||
BYTE cmd, /* Control code */
|
||||
@@ -102,7 +108,7 @@ DRESULT disk_ioctl (
|
||||
switch (cmd)
|
||||
{
|
||||
case GET_SECTOR_COUNT:
|
||||
*buf = sd_storage.sec_cnt - part_rsvd_size;
|
||||
*buf = sd_storage.sec_cnt - sd_rsvd_sectors;
|
||||
break;
|
||||
case GET_BLOCK_SIZE:
|
||||
*buf = 32768; // Align to 16MB.
|
||||
@@ -114,13 +120,25 @@ DRESULT disk_ioctl (
|
||||
switch (cmd)
|
||||
{
|
||||
case GET_SECTOR_COUNT:
|
||||
*buf = RAM_DISK_SZ >> 9; // 1GB.
|
||||
*buf = ramdisk_sectors;
|
||||
break;
|
||||
case GET_BLOCK_SIZE:
|
||||
*buf = 2048; // Align to 1MB.
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (pdrv == DRIVE_EMU)
|
||||
{
|
||||
switch (cmd)
|
||||
{
|
||||
case GET_SECTOR_COUNT:
|
||||
*buf = emummc_sectors;
|
||||
break;
|
||||
case GET_BLOCK_SIZE:
|
||||
*buf = 32768; // Align to 16MB.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return RES_OK;
|
||||
}
|
||||
@@ -133,12 +151,18 @@ DRESULT disk_set_info (
|
||||
{
|
||||
DWORD *buf = (DWORD *)buff;
|
||||
|
||||
if (pdrv == DRIVE_SD)
|
||||
if (cmd == SET_SECTOR_COUNT)
|
||||
{
|
||||
switch (cmd)
|
||||
switch (pdrv)
|
||||
{
|
||||
case SET_SECTOR_COUNT:
|
||||
part_rsvd_size = *buf;
|
||||
case DRIVE_SD:
|
||||
sd_rsvd_sectors = *buf;
|
||||
break;
|
||||
case DRIVE_RAM:
|
||||
ramdisk_sectors = *buf;
|
||||
break;
|
||||
case DRIVE_EMU:
|
||||
emummc_sectors = *buf;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,16 +41,25 @@
|
||||
#define FF_USE_MKFS 1
|
||||
/* This option switches f_mkfs() function. (0:Disable or 1:Enable) */
|
||||
|
||||
#if FF_USE_MKFS
|
||||
#define FF_MKFS_LABEL "SWITCH SD "
|
||||
#endif
|
||||
/* This sets FAT/FAT32 label. Exactly 11 characters, all caps. */
|
||||
|
||||
|
||||
#define FF_USE_FASTSEEK 0
|
||||
/* This option switches fast seek function. (0:Disable or 1:Enable) */
|
||||
|
||||
#define FF_FASTFS 1
|
||||
|
||||
#if FF_FASTFS
|
||||
#undef FF_USE_FASTSEEK
|
||||
#define FF_USE_FASTSEEK 1
|
||||
#endif
|
||||
/* This option switches fast access to chained clusters. (0:Disable or 1:Enable) */
|
||||
|
||||
|
||||
#define FF_SIMPLE_GPT 1
|
||||
/* This option switches support for the first GPT partition. (0:Disable or 1:Enable) */
|
||||
|
||||
|
||||
#define FF_USE_EXPAND 0
|
||||
@@ -170,13 +179,13 @@
|
||||
/ Drive/Volume Configurations
|
||||
/---------------------------------------------------------------------------*/
|
||||
|
||||
#define FF_VOLUMES 4
|
||||
#define FF_VOLUMES 5
|
||||
/* Number of volumes (logical drives) to be used. (1-10) */
|
||||
|
||||
|
||||
#define FF_STR_VOLUME_ID 1
|
||||
// Order is important. Any change to order, must also be reflected to diskio drive enum.
|
||||
#define FF_VOLUME_STRS "sd","ram","emmc","bis"
|
||||
#define FF_VOLUME_STRS "sd","ram","emmc","bis","emu"
|
||||
/* FF_STR_VOLUME_ID switches support for volume ID in arbitrary strings.
|
||||
/ When FF_STR_VOLUME_ID is set to 1 or 2, arbitrary strings can be used as drive
|
||||
/ number in the path name. FF_VOLUME_STRS defines the volume ID strings for each
|
||||
@@ -186,6 +195,7 @@
|
||||
/ not defined, a user defined volume string table needs to be defined as:
|
||||
/
|
||||
/ const char* VolumeStr[FF_VOLUMES] = {"ram","flash","sd","usb",...
|
||||
/ Order is important. Any change to order, must also be reflected to diskio drive enum.
|
||||
*/
|
||||
|
||||
|
||||
@@ -247,7 +257,7 @@
|
||||
#define FF_FS_NORTC 0
|
||||
#define FF_NORTC_MON 1
|
||||
#define FF_NORTC_MDAY 1
|
||||
#define FF_NORTC_YEAR 2020
|
||||
#define FF_NORTC_YEAR 2021
|
||||
/* The option FF_FS_NORTC switches timestamp function. If the system does not have
|
||||
/ any RTC function or valid timestamp is not needed, set FF_FS_NORTC = 1 to disable
|
||||
/ the timestamp function. Every object modified by FatFs will have a fixed timestamp
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
*
|
||||
* Copyright (c) 2018-2019 CTCaer
|
||||
* Copyright (c) 2018-2021 CTCaer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
@@ -42,6 +42,7 @@
|
||||
#include <soc/pmc.h>
|
||||
#include <soc/t210.h>
|
||||
#include <soc/uart.h>
|
||||
#include "storage/nx_emmc.h"
|
||||
#include <storage/nx_sd.h>
|
||||
#include <storage/sdmmc.h>
|
||||
#include <utils/btn.h>
|
||||
@@ -80,15 +81,12 @@ char *emmcsn_path_impl(char *path, char *sub_dir, char *filename, sdmmc_storage_
|
||||
// Get actual eMMC S/N.
|
||||
if (!storage)
|
||||
{
|
||||
sdmmc_t sdmmc;
|
||||
sdmmc_storage_t storage2;
|
||||
|
||||
if (!sdmmc_storage_init_mmc(&storage2, &sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400))
|
||||
if (!sdmmc_storage_init_mmc(&emmc_storage, &emmc_sdmmc, SDMMC_BUS_WIDTH_8, SDHCI_TIMING_MMC_HS400))
|
||||
strcpy(emmc_sn, "00000000");
|
||||
else
|
||||
{
|
||||
itoa(storage2.cid.serial, emmc_sn, 16);
|
||||
sdmmc_storage_end(&storage2);
|
||||
itoa(emmc_storage.cid.serial, emmc_sn, 16);
|
||||
sdmmc_storage_end(&emmc_storage);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* eMMC BIS driver for Nintendo Switch
|
||||
*
|
||||
* Copyright (c) 2019 shchmue
|
||||
* Copyright (c) 2019-2020 CTCaer
|
||||
* Copyright (c) 2019-2020 shchmue
|
||||
* Copyright (c) 2019-2021 CTCaer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
@@ -21,48 +21,64 @@
|
||||
|
||||
#include <memory_map.h>
|
||||
|
||||
#include <mem/heap.h>
|
||||
#include <sec/se.h>
|
||||
#include <sec/se_t210.h>
|
||||
#include "../storage/nx_emmc.h"
|
||||
#include <storage/nx_sd.h>
|
||||
#include <storage/sdmmc.h>
|
||||
#include <utils/types.h>
|
||||
|
||||
#define MAX_SEC_CACHE_ENTRIES 1500
|
||||
#define BIS_CLUSTER_SECTORS 32
|
||||
#define BIS_CLUSTER_SIZE 16384
|
||||
#define BIS_CACHE_MAX_ENTRIES 16384
|
||||
#define BIS_CACHE_LOOKUP_TBL_EMPTY_ENTRY -1
|
||||
|
||||
typedef struct _sector_cache_t
|
||||
typedef struct _cluster_cache_t
|
||||
{
|
||||
u32 sector;
|
||||
u32 visit_cnt;
|
||||
u8 tweak[0x10];
|
||||
u8 data[0x200];
|
||||
u8 align[8];
|
||||
} sector_cache_t;
|
||||
u32 cluster_idx; // Index of the cluster in the partition.
|
||||
bool dirty; // Has been modified without write-back flag.
|
||||
u8 data[BIS_CLUSTER_SIZE]; // The cached cluster itself. Aligned to 8 bytes for DMA engine.
|
||||
} cluster_cache_t;
|
||||
|
||||
static u8 ks_crypt = 0;
|
||||
static u8 ks_tweak = 0;
|
||||
static u32 sector_cache_cnt = 0;
|
||||
typedef struct _bis_cache_t
|
||||
{
|
||||
bool full;
|
||||
bool enabled;
|
||||
u32 dirty_cnt;
|
||||
u32 top_idx;
|
||||
u8 dma_buff[BIS_CLUSTER_SIZE]; // Aligned to 8 bytes for DMA engine.
|
||||
cluster_cache_t clusters[];
|
||||
} bis_cache_t;
|
||||
|
||||
static u8 ks_crypt = 0;
|
||||
static u8 ks_tweak = 0;
|
||||
static u32 emu_offset = 0;
|
||||
static emmc_part_t *system_part = NULL;
|
||||
static sector_cache_t *sector_cache = (sector_cache_t *)NX_BIS_CACHE_ADDR;
|
||||
static u32 *cache_lookup_tbl = (u32 *)NX_BIS_LOOKUP_ADDR;
|
||||
static bis_cache_t *bis_cache = (bis_cache_t *)NX_BIS_CACHE_ADDR;
|
||||
|
||||
static void _gf256_mul_x_le(u8 *block)
|
||||
static void _gf256_mul_x_le(void *block)
|
||||
{
|
||||
u8 *pdata = (u8 *)block;
|
||||
u32 *pdata = (u32 *)block;
|
||||
u32 carry = 0;
|
||||
|
||||
for (u32 i = 0; i < 0x10; i++)
|
||||
for (u32 i = 0; i < 4; i++)
|
||||
{
|
||||
u8 b = pdata[i];
|
||||
u32 b = pdata[i];
|
||||
pdata[i] = (b << 1) | carry;
|
||||
carry = b >> 7;
|
||||
carry = b >> 31;
|
||||
}
|
||||
|
||||
if (carry)
|
||||
pdata[0x0] ^= 0x87;
|
||||
}
|
||||
|
||||
static int _nx_aes_xts_crypt_sec(u32 ks1, u32 ks2, u32 enc, u8 *tweak, bool regen_tweak, u32 tweak_exp, u64 sec, void *dst, void *src, u32 sec_size)
|
||||
static int _nx_aes_xts_crypt_sec(u32 tweak_ks, u32 crypt_ks, u32 enc, u8 *tweak, bool regen_tweak, u32 tweak_exp, u64 sec, void *dst, void *src, u32 sec_size)
|
||||
{
|
||||
u8 *pdst = (u8 *)dst;
|
||||
u8 *psrc = (u8 *)src;
|
||||
u32 *pdst = (u32 *)dst;
|
||||
u32 *psrc = (u32 *)src;
|
||||
u32 *ptweak = (u32 *)tweak;
|
||||
|
||||
if (regen_tweak)
|
||||
{
|
||||
@@ -71,155 +87,298 @@ static int _nx_aes_xts_crypt_sec(u32 ks1, u32 ks2, u32 enc, u8 *tweak, bool rege
|
||||
tweak[i] = sec & 0xFF;
|
||||
sec >>= 8;
|
||||
}
|
||||
if (!se_aes_crypt_block_ecb(ks1, 1, tweak, tweak))
|
||||
if (!se_aes_crypt_block_ecb(tweak_ks, 1, tweak, tweak))
|
||||
return 0;
|
||||
}
|
||||
|
||||
// tweak_exp allows us to use a saved tweak to reduce _gf256_mul_x_le calls.
|
||||
for (u32 i = 0; i < (tweak_exp << 5); i++)
|
||||
_gf256_mul_x_le(tweak);
|
||||
|
||||
u8 tmp_tweak[0x10];
|
||||
memcpy(tmp_tweak, tweak, 0x10);
|
||||
u8 orig_tweak[SE_KEY_128_SIZE] __attribute__((aligned(4)));
|
||||
memcpy(orig_tweak, tweak, SE_KEY_128_SIZE);
|
||||
|
||||
// We are assuming a 0x10-aligned sector size in this implementation.
|
||||
// We are assuming a 16 sector aligned size in this implementation.
|
||||
for (u32 i = 0; i < (sec_size >> 4); i++)
|
||||
{
|
||||
for (u32 j = 0; j < 0x10; j++)
|
||||
pdst[j] = psrc[j] ^ tweak[j];
|
||||
for (u32 j = 0; j < 4; j++)
|
||||
pdst[j] = psrc[j] ^ ptweak[j];
|
||||
|
||||
_gf256_mul_x_le(tweak);
|
||||
psrc += 0x10;
|
||||
pdst += 0x10;
|
||||
psrc += 4;
|
||||
pdst += 4;
|
||||
}
|
||||
|
||||
se_aes_crypt_ecb(ks2, enc, dst, sec_size, src, sec_size);
|
||||
if (!se_aes_crypt_ecb(crypt_ks, enc, dst, sec_size, dst, sec_size))
|
||||
return 0;
|
||||
|
||||
memcpy(tweak, tmp_tweak, 0x10);
|
||||
|
||||
pdst = (u8 *)dst;
|
||||
pdst = (u32 *)dst;
|
||||
ptweak = (u32 *)orig_tweak;
|
||||
for (u32 i = 0; i < (sec_size >> 4); i++)
|
||||
{
|
||||
for (u32 j = 0; j < 0x10; j++)
|
||||
pdst[j] = pdst[j] ^ tweak[j];
|
||||
for (u32 j = 0; j < 4; j++)
|
||||
pdst[j] = pdst[j] ^ ptweak[j];
|
||||
|
||||
_gf256_mul_x_le(tweak);
|
||||
pdst += 0x10;
|
||||
_gf256_mul_x_le(orig_tweak);
|
||||
pdst += 4;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int nx_emmc_bis_write_block(u32 sector, u32 count, void *buff, bool flush)
|
||||
{
|
||||
if (!system_part)
|
||||
return 3; // Not ready.
|
||||
|
||||
int res;
|
||||
u8 tweak[SE_KEY_128_SIZE] __attribute__((aligned(4)));
|
||||
u32 cluster = sector / BIS_CLUSTER_SECTORS;
|
||||
u32 aligned_sector = cluster * BIS_CLUSTER_SECTORS;
|
||||
u32 sector_in_cluster = sector % BIS_CLUSTER_SECTORS;
|
||||
u32 lookup_idx = cache_lookup_tbl[cluster];
|
||||
bool is_cached = lookup_idx != BIS_CACHE_LOOKUP_TBL_EMPTY_ENTRY;
|
||||
|
||||
// Write to cached cluster.
|
||||
if (is_cached)
|
||||
{
|
||||
if (buff)
|
||||
memcpy(bis_cache->clusters[lookup_idx].data + sector_in_cluster * NX_EMMC_BLOCKSIZE, buff, count * NX_EMMC_BLOCKSIZE);
|
||||
else
|
||||
buff = bis_cache->clusters[lookup_idx].data;
|
||||
if (!bis_cache->clusters[lookup_idx].dirty)
|
||||
bis_cache->dirty_cnt++;
|
||||
bis_cache->clusters[lookup_idx].dirty = true;
|
||||
|
||||
if (!flush)
|
||||
return 0; // Success.
|
||||
|
||||
// Reset args to trigger a full cluster flush to emmc.
|
||||
sector_in_cluster = 0;
|
||||
sector = aligned_sector;
|
||||
count = BIS_CLUSTER_SECTORS;
|
||||
}
|
||||
|
||||
// Encrypt cluster.
|
||||
if (!_nx_aes_xts_crypt_sec(ks_tweak, ks_crypt, 1, tweak, true, sector_in_cluster, cluster, bis_cache->dma_buff, buff, count * NX_EMMC_BLOCKSIZE))
|
||||
return 1; // Encryption error.
|
||||
|
||||
// If not reading from cache, do a regular read and decrypt.
|
||||
if (!emu_offset)
|
||||
res = nx_emmc_part_write(&emmc_storage, system_part, sector, count, bis_cache->dma_buff);
|
||||
else
|
||||
res = sdmmc_storage_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)
|
||||
{
|
||||
if (!system_part)
|
||||
return 3; // Not ready.
|
||||
|
||||
static u32 prev_cluster = -1;
|
||||
static u32 prev_sector = 0;
|
||||
static u8 tweak[0x10];
|
||||
|
||||
u32 cache_idx = 0;
|
||||
u32 tweak_exp = 0;
|
||||
bool regen_tweak = true;
|
||||
bool cache_sector = false;
|
||||
|
||||
if (count == 1)
|
||||
{
|
||||
for ( ; cache_idx < sector_cache_cnt; cache_idx++)
|
||||
{
|
||||
if (sector_cache[cache_idx].sector == sector)
|
||||
{
|
||||
sector_cache[cache_idx].visit_cnt++;
|
||||
memcpy(buff, sector_cache[cache_idx].data, 0x200);
|
||||
memcpy(tweak, sector_cache[cache_idx].tweak, 0x10);
|
||||
prev_sector = sector;
|
||||
prev_cluster = sector >> 5;
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
// add to cache
|
||||
if (cache_idx == sector_cache_cnt && cache_idx < MAX_SEC_CACHE_ENTRIES)
|
||||
{
|
||||
sector_cache[cache_idx].sector = sector;
|
||||
sector_cache[cache_idx].visit_cnt++;
|
||||
cache_sector = true;
|
||||
sector_cache_cnt++;
|
||||
}
|
||||
}
|
||||
|
||||
if (nx_emmc_part_read(&emmc_storage, system_part, sector, count, buff))
|
||||
{
|
||||
if (prev_cluster != sector >> 5) // Sector in different cluster than last read.
|
||||
{
|
||||
prev_cluster = sector >> 5;
|
||||
tweak_exp = sector % 0x20;
|
||||
}
|
||||
else if (sector > prev_sector) // Sector in same cluster and past last sector.
|
||||
{
|
||||
tweak_exp = sector - prev_sector - 1;
|
||||
regen_tweak = false;
|
||||
}
|
||||
else // Sector in same cluster and before or same as last sector.
|
||||
tweak_exp = sector % 0x20;
|
||||
|
||||
// Maximum one cluster (1 XTS crypto block 16KB).
|
||||
_nx_aes_xts_crypt_sec(ks_tweak, ks_crypt, 0, tweak, regen_tweak, tweak_exp, prev_cluster, buff, buff, count << 9);
|
||||
if (cache_sector)
|
||||
{
|
||||
memcpy(sector_cache[cache_idx].data, buff, 0x200);
|
||||
memcpy(sector_cache[cache_idx].tweak, tweak, 0x10);
|
||||
}
|
||||
prev_sector = sector + count - 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Error occurred.
|
||||
return 1;
|
||||
if (bis_cache->enabled)
|
||||
return nx_emmc_bis_read_block_cached(sector, count, buff);
|
||||
else
|
||||
return nx_emmc_bis_read_block_normal(sector, count, buff);
|
||||
}
|
||||
|
||||
int nx_emmc_bis_read(u32 sector, u32 count, void *buff)
|
||||
{
|
||||
int res = 1;
|
||||
u8 *buf = (u8 *)buff;
|
||||
u32 curr_sct = sector;
|
||||
|
||||
while (count)
|
||||
{
|
||||
u32 sct_cnt = MIN(count, 0x20);
|
||||
res = nx_emmc_bis_read_block(curr_sct, sct_cnt, buf);
|
||||
if (res)
|
||||
return 1;
|
||||
u32 sct_cnt = MIN(count, BIS_CLUSTER_SECTORS);
|
||||
if (nx_emmc_bis_read_block(curr_sct, sct_cnt, buf))
|
||||
return 0;
|
||||
|
||||
count -= sct_cnt;
|
||||
count -= sct_cnt;
|
||||
curr_sct += sct_cnt;
|
||||
buf += 512 * sct_cnt;
|
||||
buf += sct_cnt * NX_EMMC_BLOCKSIZE;
|
||||
}
|
||||
|
||||
return res;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void nx_emmc_bis_init(emmc_part_t *part)
|
||||
int nx_emmc_bis_write(u32 sector, u32 count, void *buff)
|
||||
{
|
||||
u8 *buf = (u8 *)buff;
|
||||
u32 curr_sct = sector;
|
||||
|
||||
while (count)
|
||||
{
|
||||
u32 sct_cnt = MIN(count, BIS_CLUSTER_SECTORS);
|
||||
if (nx_emmc_bis_write_block(curr_sct, sct_cnt, buf, false))
|
||||
return 0;
|
||||
|
||||
count -= sct_cnt;
|
||||
curr_sct += sct_cnt;
|
||||
buf += sct_cnt * NX_EMMC_BLOCKSIZE;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void nx_emmc_bis_init(emmc_part_t *part, bool enable_cache, u32 emummc_offset)
|
||||
{
|
||||
system_part = part;
|
||||
sector_cache_cnt = 0;
|
||||
emu_offset = emummc_offset;
|
||||
|
||||
switch (part->index)
|
||||
_nx_emmc_bis_cluster_cache_init(enable_cache);
|
||||
|
||||
if (!strcmp(part->name, "PRODINFO") || !strcmp(part->name, "PRODINFOF"))
|
||||
{
|
||||
case 0: // PRODINFO.
|
||||
case 1: // PRODINFOF.
|
||||
ks_crypt = 0;
|
||||
ks_tweak = 1;
|
||||
break;
|
||||
case 8: // SAFE.
|
||||
}
|
||||
else if (!strcmp(part->name, "SAFE"))
|
||||
{
|
||||
ks_crypt = 2;
|
||||
ks_tweak = 3;
|
||||
break;
|
||||
case 9: // SYSTEM.
|
||||
case 10: // USER.
|
||||
}
|
||||
else if (!strcmp(part->name, "SYSTEM") || !strcmp(part->name, "USER"))
|
||||
{
|
||||
ks_crypt = 4;
|
||||
ks_tweak = 5;
|
||||
break;
|
||||
}
|
||||
else
|
||||
system_part = NULL;
|
||||
}
|
||||
|
||||
void nx_emmc_bis_end()
|
||||
{
|
||||
_nx_emmc_bis_flush_cache();
|
||||
system_part = NULL;
|
||||
}
|
||||
|
||||
@@ -223,7 +223,9 @@ typedef struct _nx_emmc_cal0_t
|
||||
u8 console_6axis_sensor_mount_type;
|
||||
} __attribute__((packed)) nx_emmc_cal0_t;
|
||||
|
||||
int nx_emmc_bis_read(u32 sector, u32 count, void *buff);
|
||||
void nx_emmc_bis_init(emmc_part_t *part);
|
||||
int nx_emmc_bis_read(u32 sector, u32 count, void *buff);
|
||||
int nx_emmc_bis_write(u32 sector, u32 count, void *buff);
|
||||
void nx_emmc_bis_init(emmc_part_t *part, bool enable_cache, u32 emummc_offset);
|
||||
void nx_emmc_bis_end();
|
||||
|
||||
#endif
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2018 naehrwert
|
||||
* Copyright (c) 2018-2019 CTCaer
|
||||
* Copyright (c) 2018-2021 CTCaer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
@@ -60,6 +60,11 @@ bool sd_get_card_removed()
|
||||
return false;
|
||||
}
|
||||
|
||||
bool sd_get_card_initialized()
|
||||
{
|
||||
return sd_init_done;
|
||||
}
|
||||
|
||||
u32 sd_get_mode()
|
||||
{
|
||||
return sd_mode;
|
||||
|
||||
@@ -6,37 +6,53 @@ backlight=100
|
||||
autohosoff=0
|
||||
autonogc=1
|
||||
updater2p=1
|
||||
bootprotect=0
|
||||
|
||||
|
||||
{-------- Stock -------}
|
||||
[Stock 6.2.0 and lower]
|
||||
stock=1
|
||||
emummc_force_disable=1
|
||||
|
||||
[Stock All FW]
|
||||
[Stock]
|
||||
fss0=atmosphere/fusee-secondary.bin
|
||||
stock=1
|
||||
emummc_force_disable=1
|
||||
# Both above disable kernel patching
|
||||
# Stock All FW, includes exosphere and warmboot, ONLY when >= 7.0.0.
|
||||
|
||||
[Stock emuMMC All FW]
|
||||
fss0=atmosphere/fusee-secondary.bin
|
||||
stock=1
|
||||
{ }
|
||||
# This disables kernel patching and CFW kips.
|
||||
# Includes exosphere and warmboot, ONLY when >= 7.0.0 and Erista.
|
||||
# Includes exosphere on Mariko.
|
||||
# Exosphere/warmboot are not identifiable as it is now.
|
||||
# This is the closest to OFW, especially when AutoRCM is needed.
|
||||
|
||||
|
||||
|
||||
{-- Custom Firmwares --}
|
||||
[Atmo FSS0 Vanilla]
|
||||
[Atmo Vanilla]
|
||||
fss0=atmosphere/fusee-secondary.bin
|
||||
logopath=bootloader/res/bootlogo_atmo.bmp
|
||||
icon=bootloader/res/icon_atmo.bmp
|
||||
|
||||
# Note:
|
||||
# The above adheres to emummc.ini. It will launch emuMMC if enabled, otherwise sysMMC
|
||||
# You can have 2 entries of everything where one can boot with emuMMC and one without,
|
||||
# via the emummc_force_disable=1 key.
|
||||
# logopath= key is for bootlogo. icon= key is for Nyx icon.
|
||||
# All entries can have these stylistic keys.
|
||||
# via the emummc_force_disable=1 and emummcforce=1 keys. Examples follow below.
|
||||
|
||||
[Atmo EMU]
|
||||
fss0=atmosphere/fusee-secondary.bin
|
||||
emummcforce=1
|
||||
|
||||
[Atmo SYS]
|
||||
fss0=atmosphere/fusee-secondary.bin
|
||||
emummc_force_disable=1
|
||||
|
||||
|
||||
[Atmo with extra kips]
|
||||
fss0=atmosphere/fusee-secondary.bin
|
||||
kip1=cfw/mods/mods_extra/*
|
||||
kip1=cfw/mods/mods_extra/single/extra.kip
|
||||
|
||||
# Note:
|
||||
# The above can be used with any fss0 entry. Like the ones above.
|
||||
# You can even override atmosphere (fss0) kips with this.
|
||||
|
||||
|
||||
|
||||
{-- Custom Firmwares Old methods --}
|
||||
[CFW FSS0 extra kips & patches]
|
||||
fss0=atmosphere/fusee-secondary.bin
|
||||
kip1patch=name_of_patch
|
||||
@@ -45,12 +61,12 @@ kip1=cfw/mods/mods_extra/single/extra.kip
|
||||
|
||||
# Note:
|
||||
# Both options for kip1 can be used. Wildcard and single.
|
||||
# You can override kips loaded from FSS0 if you define them after that entry.
|
||||
# You can override kips loaded from FSS0 if you define them after the fss0 key.
|
||||
# If kip1 patch resides in patches.ini and that file OR the patch for
|
||||
# current HOS version does not exist, it will error out.
|
||||
|
||||
|
||||
[Atmo Vanilla]
|
||||
[CFW KIPs method]
|
||||
secmon=cfw/mods/exosphere.bin
|
||||
warmboot=cfw/mods/lp0fw.bin
|
||||
kip1=cfw/mods/loader.kip
|
||||
@@ -66,7 +82,7 @@ atmosphere=1
|
||||
# atmosphere=1 key is IMPORTANT when no FFS0 is defined.
|
||||
|
||||
|
||||
[CFW Extra kips]
|
||||
[CFW KIPs method with wildcard]
|
||||
secmon=cfw/mods/exosphere.bin
|
||||
warmboot=cfw/mods/lp0fw.bin
|
||||
kip1=cfw/mods/*
|
||||
@@ -83,7 +99,12 @@ atmosphere=1
|
||||
payload=bootloader/payloads/memloader.bin
|
||||
|
||||
|
||||
# hekate - CTCaer mod v5.0.0 .ini template
|
||||
# hekate - CTCaer mod v5.5.3 .ini template
|
||||
|
||||
# All entries in this template can have these stylistic keys.
|
||||
# Like logopath= key which is for bootlogo and icon= key for Nyx icon.
|
||||
# Other than these there many other keys to choose from, like the exosphere configuration keys.
|
||||
# All of them are descibed in the main README.
|
||||
|
||||
# NOT TO BE USED AS IS!
|
||||
# Pick [config] and then only the needed [sections]. # or { } lines can be ommited.
|
||||
|
||||
Reference in New Issue
Block a user