Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
40938fdb58 | ||
|
|
73e3cc7be6 | ||
|
|
90f893f573 | ||
|
|
3f44441df4 | ||
|
|
44c3ae5ef1 | ||
|
|
5a775ebb72 | ||
|
|
884ad1f6e6 |
9
Makefile
9
Makefile
@@ -49,14 +49,14 @@ LDFLAGS = $(ARCH) -nostartfiles -lgcc -Wl,--nmagic,--gc-sections
|
||||
|
||||
.PHONY: all clean
|
||||
|
||||
all: $(TARGET).bin
|
||||
all: $(BUILD)/$(TARGET)
|
||||
|
||||
clean:
|
||||
@rm -rf $(OBJS)
|
||||
@rm -rf $(BUILD)
|
||||
@rm -rf $(TARGET).bin
|
||||
@rm -rf $(BUILD)/$(TARGET).elf
|
||||
@rm -rf $(BUILD)/$(TARGET)
|
||||
|
||||
$(TARGET).bin: $(BUILD)/$(TARGET).elf
|
||||
$(BUILD)/$(TARGET): $(BUILD)/$(TARGET).elf
|
||||
$(OBJCOPY) -S -O binary $< $@
|
||||
|
||||
$(BUILD)/$(TARGET).elf: $(OBJS)
|
||||
@@ -66,5 +66,4 @@ $(BUILD)/%.o: $(SOURCEDIR)/%.c
|
||||
$(CC) $(CFLAGS) -c $< -o $@
|
||||
|
||||
$(BUILD)/%.o: $(SOURCEDIR)/%.S
|
||||
@mkdir -p "$(BUILD)"
|
||||
$(CC) $(CFLAGS) -c $< -o $@
|
||||
|
||||
@@ -65,7 +65,6 @@ static const u8 _gfx_font[] = {
|
||||
0x00, 0x00, 0x66, 0x3C, 0x18, 0x3C, 0x66, 0x00, 0x00, 0x00, 0x66, 0x66, 0x7C, 0x60, 0x3C, 0x00,
|
||||
0x00, 0x00, 0x7E, 0x30, 0x18, 0x0C, 0x7E, 0x00, 0x00, 0x00, 0x18, 0x08, 0x08, 0x04, 0x08, 0x08,
|
||||
0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x0C, 0x08, 0x08, 0x10, 0x08, 0x08,
|
||||
0x00, 0x00, 0x00, 0x4c, 0x32, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
void gfx_init_ctxt(gfx_ctxt_t *ctxt, u32 *fb, u32 width, u32 height, u32 stride)
|
||||
@@ -113,7 +112,7 @@ void gfx_con_setpos(gfx_con_t *con, u32 x, u32 y)
|
||||
|
||||
void gfx_putc(gfx_con_t *con, char c)
|
||||
{
|
||||
if (c >= 32 && c <= 126)
|
||||
if (c >= 32 && c < 128)
|
||||
{
|
||||
u8 *cbuf = (u8 *)&_gfx_font[8 * (c - 32)];
|
||||
u32 *fb = con->gfx_ctxt->fb + con->x + con->y * con->gfx_ctxt->stride;
|
||||
|
||||
249
ipl/hos.c
249
ipl/hos.c
@@ -32,20 +32,11 @@
|
||||
#include "pkg2.h"
|
||||
#include "ff.h"
|
||||
|
||||
#include "gfx.h"
|
||||
/*#include "gfx.h"
|
||||
extern gfx_ctxt_t gfx_ctxt;
|
||||
extern gfx_con_t gfx_con;
|
||||
#define DPRINTF(...) gfx_printf(&gfx_con, __VA_ARGS__)
|
||||
//#define DPRINTF(...)
|
||||
|
||||
enum KB_FIRMWARE_VERSION {
|
||||
KB_FIRMWARE_VERSION_100_200 = 0,
|
||||
KB_FIRMWARE_VERSION_300 = 1,
|
||||
KB_FIRMWARE_VERSION_301 = 2,
|
||||
KB_FIRMWARE_VERSION_400 = 3,
|
||||
KB_FIRMWARE_VERSION_500 = 4,
|
||||
KB_FIRMWARE_VERSION_MAX
|
||||
};
|
||||
#define DPRINTF(...) gfx_printf(&gfx_con, __VA_ARGS__)*/
|
||||
#define DPRINTF(...)
|
||||
|
||||
#define NUM_KEYBLOB_KEYS 5
|
||||
static const u8 keyblob_keyseeds[NUM_KEYBLOB_KEYS][0x10] = {
|
||||
@@ -59,19 +50,19 @@ static const u8 keyblob_keyseeds[NUM_KEYBLOB_KEYS][0x10] = {
|
||||
static const u8 cmac_keyseed[0x10] =
|
||||
{ 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 mkey_keyseed_retail[0x10] =
|
||||
{ 0xD8, 0xA2, 0x41, 0x0A, 0xC6, 0xC5, 0x90, 0x01, 0xC6, 0x1D, 0x6A, 0x26, 0x7C, 0x51, 0x3F, 0x3C };
|
||||
|
||||
static const u8 console_keyseed[0x10] =
|
||||
static const u8 ckey_keyseed[0x10] =
|
||||
{ 0x4F, 0x02, 0x5F, 0x0E, 0xB6, 0x6D, 0x11, 0x0E, 0xDC, 0x32, 0x7D, 0x41, 0x86, 0xC2, 0xF4, 0x78 };
|
||||
|
||||
static const u8 key8_keyseed[] =
|
||||
{ 0xFB, 0x8B, 0x6A, 0x9C, 0x79, 0x00, 0xC8, 0x49, 0xEF, 0xD2, 0x4D, 0x85, 0x4D, 0x30, 0xA0, 0xC7 };
|
||||
|
||||
static const u8 master_keyseed_4xx[0x10] =
|
||||
static const u8 new_masterkey_seed[0x10] =
|
||||
{ 0x2D, 0xC1, 0xF4, 0x8D, 0xF3, 0x5B, 0x69, 0x33, 0x42, 0x10, 0xAC, 0x65, 0xDA, 0x90, 0x46, 0x66 };
|
||||
|
||||
static const u8 console_keyseed_4xx[0x10] =
|
||||
static const u8 new_per_console_key[0x10] =
|
||||
{ 0x0C, 0x91, 0x09, 0xDB, 0x93, 0x93, 0x07, 0x81, 0x07, 0x3C, 0xC4, 0x16, 0x22, 0x7C, 0x6C, 0x28 };
|
||||
|
||||
|
||||
@@ -103,27 +94,18 @@ static void _se_lock()
|
||||
}
|
||||
|
||||
// <-- key derivation algorithm
|
||||
int keygen(u8 *keyblob, u32 kb, void *tsec_fw)
|
||||
static int keygen(u8 *keyblob, u32 kb, void *tsec_fw)
|
||||
{
|
||||
u8 tmp[0x10];
|
||||
u8 *tmp = (u8 *)malloc(0x10);
|
||||
|
||||
se_key_acc_ctrl(0x0D, 0x15);
|
||||
se_key_acc_ctrl(0x0E, 0x15);
|
||||
se_key_acc_ctrl(12, 0x15);
|
||||
se_key_acc_ctrl(13, 0x15);
|
||||
|
||||
//Get TSEC key.
|
||||
if (tsec_query(tmp, 1, tsec_fw) < 0)
|
||||
return 0;
|
||||
|
||||
se_aes_key_set(0x0D, tmp, 0x10);
|
||||
|
||||
//Derive keyblob keys from TSEC+SBK.
|
||||
se_aes_crypt_block_ecb(0x0D, 0x00, tmp, keyblob_keyseeds[0]);
|
||||
se_aes_unwrap_key(0x0F, 0x0E, tmp);
|
||||
se_aes_crypt_block_ecb(0xD, 0x00, tmp, keyblob_keyseeds[kb]);
|
||||
se_aes_unwrap_key(0x0D, 0x0E, tmp);
|
||||
|
||||
// Clear SBK
|
||||
se_aes_key_clear(0x0E);
|
||||
se_aes_key_set(13, tmp, 0x10);
|
||||
|
||||
//TODO: verify keyblob CMAC.
|
||||
//se_aes_unwrap_key(11, 13, cmac_keyseed);
|
||||
@@ -131,43 +113,131 @@ int keygen(u8 *keyblob, u32 kb, void *tsec_fw)
|
||||
//if (!memcmp(keyblob, tmp, 0x10))
|
||||
// return 0;
|
||||
|
||||
se_aes_crypt_block_ecb(0x0D, 0, tmp, cmac_keyseed);
|
||||
se_aes_unwrap_key(0x0B, 0x0D, cmac_keyseed);
|
||||
switch(kb) {
|
||||
// 1.0.0~2.0.0 FW
|
||||
case 0: {
|
||||
|
||||
//Decrypt keyblob and set keyslots.
|
||||
se_aes_crypt_ctr(0x0D, keyblob + 0x20, 0x90, keyblob + 0x20, 0x90, keyblob + 0x10);
|
||||
se_aes_key_set(0x0B, keyblob + 0x20 + 0x80, 0x10); // package1 key
|
||||
se_aes_key_set(0x0C, keyblob + 0x20, 0x10);
|
||||
se_aes_key_set(0x0D, keyblob + 0x20, 0x10);
|
||||
//Derive keyblob key from TSEC+SBK.
|
||||
memcpy(tmp, keyblob_keyseeds[kb], 0x10);
|
||||
se_aes_crypt_block_ecb(13, 0, tmp, tmp);
|
||||
se_aes_unwrap_key(13, 14, tmp);
|
||||
se_aes_key_clear(14);
|
||||
|
||||
se_aes_crypt_block_ecb(0x0C, 0, tmp, master_keyseed_retail);
|
||||
se_aes_crypt_ctr(13, keyblob + 0x20, 0x90, keyblob + 0x20, 0x90, keyblob + 0x10);
|
||||
se_aes_key_set(11, keyblob + 0x20 + 0x80, 0x10);
|
||||
se_aes_key_set(12, keyblob + 0x20, 0x10);
|
||||
|
||||
switch (kb) {
|
||||
case KB_FIRMWARE_VERSION_100_200:
|
||||
case KB_FIRMWARE_VERSION_300:
|
||||
se_aes_unwrap_key(0x0D, 0x0F, console_keyseed);
|
||||
se_aes_unwrap_key(0x0C, 0x0C, master_keyseed_retail);
|
||||
//TODO: for some reason SE likes to hang if we don't execute an operation here.
|
||||
memcpy(tmp, mkey_keyseed_retail, 0x10);
|
||||
se_aes_crypt_block_ecb(12, 0, tmp, tmp);
|
||||
|
||||
//Generate retail master key.
|
||||
memcpy(tmp, mkey_keyseed_retail, 0x10);
|
||||
se_aes_unwrap_key(12, 12, tmp);
|
||||
|
||||
//Generate console specific key.
|
||||
memcpy(tmp, ckey_keyseed, 0x10);
|
||||
se_aes_unwrap_key(13, 13, tmp);
|
||||
|
||||
memcpy(tmp, key8_keyseed, 0x10);
|
||||
se_key_acc_ctrl(8, 0x15);
|
||||
se_aes_unwrap_key(8, 12, tmp);
|
||||
|
||||
se_key_acc_ctrl(12, 0xFF);
|
||||
se_key_acc_ctrl(13, 0xFF);
|
||||
}
|
||||
break;
|
||||
// 3.0.0~3.0.1 FW
|
||||
case 1:
|
||||
case 2: {
|
||||
|
||||
// keyslot 10
|
||||
memcpy(tmp, keyblob_keyseeds[0], 0x10);
|
||||
se_aes_crypt_block_ecb(13, 0, tmp, tmp);
|
||||
se_aes_unwrap_key(10, 14, tmp);
|
||||
|
||||
// keyslot 13
|
||||
memcpy(tmp, keyblob_keyseeds[kb], 0x10);
|
||||
se_aes_crypt_block_ecb(13, 0, tmp, tmp);
|
||||
se_aes_unwrap_key(13, 14, tmp);
|
||||
|
||||
se_aes_key_clear(14);
|
||||
se_aes_key_clear(15);
|
||||
|
||||
se_aes_crypt_ctr(13, keyblob + 0x20, 0x90, keyblob + 0x20, 0x90, keyblob + 0x10);
|
||||
se_aes_key_set(11, keyblob + 0x20 + 0x80, 0x10);
|
||||
se_aes_key_set(12, keyblob + 0x20, 0x10);
|
||||
|
||||
//TODO: for some reason SE likes to hang if we don't execute an operation here.
|
||||
memcpy(tmp, mkey_keyseed_retail, 0x10);
|
||||
se_aes_crypt_block_ecb(12, 0, tmp, tmp);
|
||||
|
||||
//Generate retail master key.
|
||||
memcpy(tmp, mkey_keyseed_retail, 0x10);
|
||||
se_aes_unwrap_key(12, 12, tmp);
|
||||
|
||||
//Generate console specific key.
|
||||
memcpy(tmp, ckey_keyseed, 0x10);
|
||||
se_aes_unwrap_key(13, 10, tmp);
|
||||
se_aes_key_clear(10);
|
||||
|
||||
memcpy(tmp, key8_keyseed, 0x10);
|
||||
se_key_acc_ctrl(8, 0x15);
|
||||
se_aes_unwrap_key(8, 12, tmp);
|
||||
|
||||
se_key_acc_ctrl(12, 0xFF);
|
||||
se_key_acc_ctrl(13, 0xFF);
|
||||
}
|
||||
break;
|
||||
|
||||
case KB_FIRMWARE_VERSION_400:
|
||||
se_aes_unwrap_key(0x0D, 0x0F, console_keyseed_4xx);
|
||||
se_aes_unwrap_key(0x0F, 0x0F, console_keyseed);
|
||||
se_aes_unwrap_key(0x0E, 0x0C, master_keyseed_4xx);
|
||||
se_aes_unwrap_key(0x0C, 0x0C, master_keyseed_retail);
|
||||
break;
|
||||
// 4.0.0~5.0.1 FW
|
||||
case 3:
|
||||
case 4: {
|
||||
se_key_acc_ctrl(14, 0x15);
|
||||
se_key_acc_ctrl(15, 0x15);
|
||||
|
||||
case KB_FIRMWARE_VERSION_500:
|
||||
default:
|
||||
se_aes_unwrap_key(0x0A, 0x0F, console_keyseed_4xx);
|
||||
se_aes_unwrap_key(0x0F, 0x0F, console_keyseed);
|
||||
se_aes_unwrap_key(0x0E, 0x0C, master_keyseed_4xx);
|
||||
se_aes_unwrap_key(0x0C, 0x0C, master_keyseed_retail);
|
||||
// keyslot 15
|
||||
memcpy(tmp, keyblob_keyseeds[0], 0x10);
|
||||
se_aes_crypt_block_ecb(13, 0, tmp, tmp);
|
||||
se_aes_unwrap_key(15, 14, tmp);
|
||||
|
||||
// keyslot 13
|
||||
memcpy(tmp, keyblob_keyseeds[kb], 0x10);
|
||||
se_aes_crypt_block_ecb(13, 0, tmp, tmp);
|
||||
se_aes_unwrap_key(13, 14, tmp);
|
||||
|
||||
se_aes_key_clear(14);
|
||||
|
||||
se_aes_crypt_ctr(13, keyblob + 0x20, 0x90, keyblob + 0x20, 0x90, keyblob + 0x10);
|
||||
se_aes_key_set(11, keyblob + 0x20 + 0x80, 0x10);
|
||||
se_aes_key_set(12, keyblob + 0x20, 0x10);
|
||||
|
||||
//TODO: for some reason SE likes to hang if we don't execute an operation here.
|
||||
memcpy(tmp, mkey_keyseed_retail, 0x10);
|
||||
se_aes_crypt_block_ecb(12, 0, tmp, tmp);
|
||||
|
||||
// keyslot 14
|
||||
memcpy(tmp, new_masterkey_seed, 0x10);
|
||||
se_aes_unwrap_key(14, 12, tmp);
|
||||
|
||||
// keyslot 12
|
||||
memcpy(tmp, mkey_keyseed_retail, 0x10);
|
||||
se_aes_unwrap_key(12, 12, tmp);
|
||||
|
||||
// keyslot 13
|
||||
memcpy(tmp, new_per_console_key, 0x10);
|
||||
se_aes_unwrap_key(13, 15, tmp);
|
||||
|
||||
// keyslot 15
|
||||
memcpy(tmp, ckey_keyseed, 0x10);
|
||||
se_aes_unwrap_key(15, 13, tmp);
|
||||
|
||||
se_key_acc_ctrl(12, 0xFF);
|
||||
se_key_acc_ctrl(15, 0xFF);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// Package2 key
|
||||
se_key_acc_ctrl(0x08, 0x15);
|
||||
se_aes_unwrap_key(0x08, 0x0C, key8_keyseed);
|
||||
free(tmp);
|
||||
}
|
||||
|
||||
|
||||
@@ -387,39 +457,38 @@ DPRINTF("decrypted and unpacked pkg1\n");
|
||||
{
|
||||
//Else we patch it to allow for an unsigned package2.
|
||||
patch_t *secmon_patchset = ctxt.pkg1_id->secmon_patchset;
|
||||
|
||||
if (secmon_patchset != NULL) {
|
||||
for (u32 i = 0; secmon_patchset[i].off != 0xFFFFFFFF; i++)
|
||||
*(vu32 *)(ctxt.pkg1_id->secmon_base + secmon_patchset[i].off) = secmon_patchset[i].val;
|
||||
|
||||
DPRINTF("loaded warmboot.bin and secmon\n");
|
||||
|
||||
//Read package2.
|
||||
if (!_read_emmc_pkg2(&ctxt))
|
||||
return 0;
|
||||
DPRINTF("loaded warmboot.bin and secmon\n");
|
||||
|
||||
//Read package2.
|
||||
if (!_read_emmc_pkg2(&ctxt))
|
||||
return 0;
|
||||
|
||||
DPRINTF("read pkg2\n");
|
||||
//Decrypt package2 and parse KIP1 blobs in INI1 section.
|
||||
pkg2_hdr_t *pkg2_hdr = pkg2_decrypt(ctxt.pkg2);
|
||||
DPRINTF("read pkg2\n");
|
||||
//Decrypt package2 and parse KIP1 blobs in INI1 section.
|
||||
pkg2_hdr_t *pkg2_hdr = pkg2_decrypt(ctxt.pkg2);
|
||||
|
||||
LIST_INIT(kip1_info);
|
||||
pkg2_parse_kips(&kip1_info, pkg2_hdr);
|
||||
LIST_INIT(kip1_info);
|
||||
pkg2_parse_kips(&kip1_info, pkg2_hdr);
|
||||
|
||||
DPRINTF("parsed ini1\n");
|
||||
|
||||
//Use the kernel included in package2 in case we didn't load one already.
|
||||
if (!ctxt.kernel)
|
||||
{
|
||||
ctxt.kernel = pkg2_hdr->data;
|
||||
ctxt.kernel_size = pkg2_hdr->sec_size[PKG2_SEC_KERNEL];
|
||||
}
|
||||
DPRINTF("parsed ini1\n");
|
||||
|
||||
//Use the kernel included in package2 in case we didn't load one already.
|
||||
if (!ctxt.kernel)
|
||||
{
|
||||
ctxt.kernel = pkg2_hdr->data;
|
||||
ctxt.kernel_size = pkg2_hdr->sec_size[PKG2_SEC_KERNEL];
|
||||
}
|
||||
|
||||
//Merge extra KIP1s into loaded ones.
|
||||
LIST_FOREACH_ENTRY(merge_kip_t, mki, &ctxt.kip1_list, link)
|
||||
pkg2_merge_kip(&kip1_info, (pkg2_kip1_t *)mki->kip1);
|
||||
//Merge extra KIP1s into loaded ones.
|
||||
LIST_FOREACH_ENTRY(merge_kip_t, mki, &ctxt.kip1_list, link)
|
||||
pkg2_merge_kip(&kip1_info, (pkg2_kip1_t *)mki->kip1);
|
||||
|
||||
//Rebuild and encrypt package2.
|
||||
pkg2_build_encrypt((void *)0xA9800000, ctxt.kernel, ctxt.kernel_size, &kip1_info);
|
||||
//Rebuild and encrypt package2.
|
||||
pkg2_build_encrypt((void *)0xA9800000, ctxt.kernel, ctxt.kernel_size, &kip1_info);
|
||||
DPRINTF("rebuilt pkg2\n");
|
||||
} else {
|
||||
//Read package2.
|
||||
@@ -431,14 +500,6 @@ DPRINTF("decrypted and unpacked pkg1\n");
|
||||
}
|
||||
}
|
||||
|
||||
se_aes_key_clear(8);
|
||||
se_aes_key_clear(11);
|
||||
//se_aes_key_clear(13);
|
||||
//se_key_acc_ctrl(10, 0xFF);
|
||||
se_key_acc_ctrl(12, 0xFF);
|
||||
//se_key_acc_ctrl(13, 0xFF);
|
||||
//se_key_acc_ctrl(14, 0xFF);
|
||||
se_key_acc_ctrl(15, 0xFF);
|
||||
|
||||
//Clear 'BootConfig'.
|
||||
memset((void *)0x4003D000, 0, 0x3000);
|
||||
@@ -469,10 +530,6 @@ DPRINTF("decrypted and unpacked pkg1\n");
|
||||
//Signal package2 available.
|
||||
*mb_in = 2;
|
||||
sleep(100);
|
||||
*mb_in = 3;
|
||||
sleep(100);
|
||||
|
||||
|
||||
|
||||
/*PMC(0x4) = 0x7FFFF3;
|
||||
PMC(0x2C4) = 0xFFFFFFFF;
|
||||
@@ -487,7 +544,7 @@ DPRINTF("decrypted and unpacked pkg1\n");
|
||||
//display_end();
|
||||
|
||||
//Signal to continue boot.
|
||||
*mb_in = 4;
|
||||
*mb_in = 3;
|
||||
sleep(100);
|
||||
|
||||
//Halt ourselves in waitevent state.
|
||||
|
||||
@@ -21,6 +21,5 @@
|
||||
#include "ini.h"
|
||||
|
||||
int hos_launch(ini_sec_t *cfg);
|
||||
int keygen(u8 *keyblob, u32 kb, void *tsec_fw);
|
||||
|
||||
#endif
|
||||
|
||||
516
ipl/main.c
516
ipl/main.c
@@ -46,56 +46,6 @@
|
||||
#include "se_t210.h"
|
||||
#include "hos.h"
|
||||
#include "pkg1.h"
|
||||
#include "mmc.h"
|
||||
|
||||
//TODO: ugly.
|
||||
sdmmc_t sd_sdmmc;
|
||||
sdmmc_storage_t sd_storage;
|
||||
FATFS sd_fs;
|
||||
int sd_mounted;
|
||||
|
||||
int sd_mount()
|
||||
{
|
||||
if (sd_mounted)
|
||||
return 1;
|
||||
|
||||
if (sdmmc_storage_init_sd(&sd_storage, &sd_sdmmc, SDMMC_1, SDMMC_BUS_WIDTH_4, 11) &&
|
||||
f_mount(&sd_fs, "", 1) == FR_OK)
|
||||
{
|
||||
sd_mounted = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void *sd_file_read(char *path)
|
||||
{
|
||||
FIL fp;
|
||||
if (f_open(&fp, path, FA_READ) != FR_OK)
|
||||
return NULL;
|
||||
|
||||
u32 size = f_size(&fp);
|
||||
void *buf = malloc(size);
|
||||
|
||||
u8 *ptr = buf;
|
||||
while (size > 0)
|
||||
{
|
||||
u32 rsize = MIN(size, 512);
|
||||
if (f_read(&fp, ptr, rsize, NULL) != FR_OK)
|
||||
{
|
||||
free(buf);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ptr += rsize;
|
||||
size -= rsize;
|
||||
}
|
||||
|
||||
f_close(&fp);
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
void panic(u32 val)
|
||||
{
|
||||
@@ -302,36 +252,8 @@ void print_fuseinfo()
|
||||
gfx_printf(&gfx_con, "%k(Unlocked) fuse cache:\n\n%k", 0xFFFF9955, 0xFFFFFFFF);
|
||||
gfx_hexdump(&gfx_con, 0x7000F900, (u8 *)0x7000F900, 0x2FC);
|
||||
|
||||
gfx_puts(&gfx_con, "\nPress POWER to dump them to SD Card.\nPress VOL to go to the menu.\n");
|
||||
|
||||
sleep(1000000);
|
||||
|
||||
u32 btn = btn_wait();
|
||||
if (btn & BTN_POWER)
|
||||
{
|
||||
if (!sd_mount())
|
||||
{
|
||||
gfx_printf(&gfx_con, "%kFailed to mount SD card (make sure that it is inserted).%k\n",
|
||||
0xFF0000FF, 0xFFFFFFFF);
|
||||
}
|
||||
else
|
||||
{
|
||||
FIL fuseFp;
|
||||
char fuseFilename[9];
|
||||
memcpy(fuseFilename, "fuse.bin", 8);
|
||||
fuseFilename[8] = 0;
|
||||
if (f_open(&fuseFp, fuseFilename, FA_CREATE_ALWAYS | FA_WRITE) == FR_OK)
|
||||
{
|
||||
f_write(&fuseFp, (u8 *)0x7000F900, 0x2FC, NULL);
|
||||
f_close(&fuseFp);
|
||||
gfx_puts(&gfx_con, "\nDone!\n");
|
||||
}
|
||||
else
|
||||
gfx_printf(&gfx_con, "%k\nError creating fuse.bin file.%k\n", 0xFF0000FF, 0xFFFFFFFF);
|
||||
}
|
||||
sleep(2000000);
|
||||
btn_wait();
|
||||
}
|
||||
sleep(100000);
|
||||
btn_wait();
|
||||
}
|
||||
|
||||
void print_kfuseinfo()
|
||||
@@ -346,248 +268,7 @@ void print_kfuseinfo()
|
||||
else
|
||||
gfx_hexdump(&gfx_con, 0, (u8 *)buf, KFUSE_NUM_WORDS * 4);
|
||||
|
||||
gfx_puts(&gfx_con, "\nPress POWER to dump them to SD Card.\nPress VOL to go to the menu.\n");
|
||||
|
||||
sleep(1000000);
|
||||
|
||||
u32 btn = btn_wait();
|
||||
if (btn & BTN_POWER)
|
||||
{
|
||||
if (!sd_mount())
|
||||
{
|
||||
gfx_printf(&gfx_con, "%kFailed to mount SD card (make sure that it is inserted).%k\n",
|
||||
0xFF0000FF, 0xFFFFFFFF);
|
||||
}
|
||||
else
|
||||
{
|
||||
FIL kfuseFp;
|
||||
char kfuseFilename[10];
|
||||
memcpy(kfuseFilename, "kfuse.bin", 9);
|
||||
kfuseFilename[9] = 0;
|
||||
if (f_open(&kfuseFp, kfuseFilename, FA_CREATE_ALWAYS | FA_WRITE) == FR_OK)
|
||||
{
|
||||
f_write(&kfuseFp, (u8 *)buf, KFUSE_NUM_WORDS * 4, NULL);
|
||||
f_close(&kfuseFp);
|
||||
gfx_puts(&gfx_con, "\nDone!\n");
|
||||
}
|
||||
else
|
||||
gfx_printf(&gfx_con, "%k\nError creating kfuse.bin file.%k\n", 0xFF0000FF, 0xFFFFFFFF);
|
||||
}
|
||||
sleep(2000000);
|
||||
btn_wait();
|
||||
}
|
||||
}
|
||||
|
||||
void print_mmc_info()
|
||||
{
|
||||
gfx_clear(&gfx_ctxt, 0xFF000000);
|
||||
gfx_con_setpos(&gfx_con, 0, 0);
|
||||
|
||||
static const u32 SECTORS_TO_MIB_COEFF = 0x800;
|
||||
|
||||
sdmmc_storage_t storage;
|
||||
sdmmc_t sdmmc;
|
||||
|
||||
if(!sdmmc_storage_init_mmc(&storage, &sdmmc, SDMMC_4, SDMMC_BUS_WIDTH_8, 4))
|
||||
{
|
||||
gfx_printf(&gfx_con, "%kFailed to init eMMC.%k\n", 0xFF0000FF, 0xFFFFFFFF);
|
||||
goto out;
|
||||
}
|
||||
else
|
||||
{
|
||||
u16 card_type;
|
||||
u32 speed;
|
||||
|
||||
gfx_printf(&gfx_con, "%kCard IDentification:%k\n", 0xFFFFDD00, 0xFFFFFFFF);
|
||||
switch (storage.csd.mmca_vsn)
|
||||
{
|
||||
case 0: /* MMC v1.0 - v1.2 */
|
||||
case 1: /* MMC v1.4 */
|
||||
gfx_printf(&gfx_con,
|
||||
" Vendor ID: %03X\n\
|
||||
Model: %c%c%c%c%c%c%c\n\
|
||||
HW rev: %X\n\
|
||||
FW rev: %X\n\
|
||||
S/N: %03X\n\
|
||||
Month/Year: %02d/%04d\n\n",
|
||||
storage.cid.manfid,
|
||||
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.prod_name[6], storage.cid.hwrev, storage.cid.fwrev,
|
||||
storage.cid.serial, storage.cid.month, storage.cid.year);
|
||||
break;
|
||||
case 2: /* MMC v2.0 - v2.2 */
|
||||
case 3: /* MMC v3.1 - v3.3 */
|
||||
case 4: /* MMC v4 */
|
||||
gfx_printf(&gfx_con,
|
||||
" 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);
|
||||
break;
|
||||
default:
|
||||
gfx_printf(&gfx_con, "%keMMC has unknown MMCA version %d%k\n", 0xFF0000FF, storage.csd.mmca_vsn, 0xFFFFFFFF);
|
||||
break;
|
||||
}
|
||||
|
||||
if (storage.csd.structure == 0)
|
||||
gfx_printf(&gfx_con, "%kUnknown CSD structure%k\n", 0xFF0000FF, 0xFFFFFFFF);
|
||||
else
|
||||
{
|
||||
gfx_printf(&gfx_con, "%kExtended Card-Specific Data V1.%d:%k\n",
|
||||
0xFFFFDD00, storage.ext_csd.ext_struct, 0xFFFFFFFF);
|
||||
card_type = storage.ext_csd.card_type;
|
||||
u8 card_type_support[96];
|
||||
u8 pos_type = 0;
|
||||
if (card_type & EXT_CSD_CARD_TYPE_HS_26)
|
||||
{
|
||||
memcpy(card_type_support, "HS26", 4);
|
||||
speed = (26 << 16) | 26;
|
||||
pos_type += 4;
|
||||
}
|
||||
if (card_type & EXT_CSD_CARD_TYPE_HS_52)
|
||||
{
|
||||
memcpy(card_type_support + pos_type, ", HS52", 6);
|
||||
speed = (52 << 16) | 52;
|
||||
pos_type += 6;
|
||||
}
|
||||
if (card_type & EXT_CSD_CARD_TYPE_DDR_1_8V)
|
||||
{
|
||||
memcpy(card_type_support + pos_type, ", DDR52_1.8V", 12);
|
||||
speed = (52 << 16) | 104;
|
||||
pos_type += 12;
|
||||
}
|
||||
if (card_type & EXT_CSD_CARD_TYPE_HS200_1_8V)
|
||||
{
|
||||
memcpy(card_type_support + pos_type, ", HS200_1.8V", 12);
|
||||
speed = (200 << 16) | 200;
|
||||
pos_type += 12;
|
||||
}
|
||||
if (card_type & EXT_CSD_CARD_TYPE_HS400_1_8V)
|
||||
{
|
||||
memcpy(card_type_support + pos_type, ", HS400_1.8V", 12);
|
||||
speed = (200 << 16) | 400;
|
||||
pos_type += 12;
|
||||
}
|
||||
card_type_support[pos_type] = 0;
|
||||
|
||||
gfx_printf(&gfx_con,
|
||||
" Spec Version: %02X\n\
|
||||
Extended Rev: 1.%d\n\
|
||||
Dev Version: %d\n\
|
||||
Cmd Classes: %02X\n\
|
||||
Capacity: %s\n\
|
||||
Max Speed: %d MB/s (%d MHz)\n\
|
||||
Type Support: %s\n\n",
|
||||
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, card_type_support);
|
||||
|
||||
u32 boot_size = storage.ext_csd.boot_mult << 17;
|
||||
u32 rpmb_size = storage.ext_csd.rpmb_mult << 17;
|
||||
gfx_printf(&gfx_con, "%keMMC Partitions:%k\n", 0xFFFFDD00, 0xFFFFFFFF);
|
||||
gfx_printf(&gfx_con, " 1: %kBOOT0 %kSize: %5d KiB (LBA Sectors: 0x%07X)\n", 0xFF00FF96, 0xFFFFFFFF,
|
||||
boot_size / 1024, boot_size / 1024 / 512);
|
||||
gfx_printf(&gfx_con, " 2: %kBOOT1 %kSize: %5d KiB (LBA Sectors: 0x%07X)\n", 0xFF00FF96, 0xFFFFFFFF,
|
||||
boot_size / 1024, boot_size / 1024 / 512);
|
||||
gfx_printf(&gfx_con, " 3: %kRPMB %kSize: %5d KiB (LBA Sectors: 0x%07X)\n", 0xFF00FF96, 0xFFFFFFFF,
|
||||
rpmb_size / 1024, rpmb_size / 1024 / 512);
|
||||
gfx_printf(&gfx_con, " 0: %kGPP (USER) %kSize: %05d MiB (LBA Sectors: 0x%07X)\n\n", 0xFF00FF96, 0xFFFFFFFF,
|
||||
storage.sec_cnt / SECTORS_TO_MIB_COEFF, storage.sec_cnt);
|
||||
gfx_printf(&gfx_con, "%kGPP (eMMC USER) partition table:%k\n", 0xFFFFDD00, 0xFFFFFFFF);
|
||||
|
||||
sdmmc_storage_set_mmc_partition(&storage, 0);
|
||||
LIST_INIT(gpt);
|
||||
nx_emmc_gpt_parse(&gpt, &storage);
|
||||
int gpp_idx = 0;
|
||||
LIST_FOREACH_ENTRY(emmc_part_t, part, &gpt, link)
|
||||
{
|
||||
gfx_printf(&gfx_con, " %02d: %k%s%k\n Size: % 5d MiB (LBA Sectors 0x%07X, LBA Range: %08X-%08X)%k\n",
|
||||
gpp_idx++, 0xFF14FDAE, part->name, 0xFFFFFFFF, (part->lba_end - part->lba_start + 1) / SECTORS_TO_MIB_COEFF,
|
||||
part->lba_end - part->lba_start + 1, part->lba_start, part->lba_end, 0xFFFFFFFF);
|
||||
}
|
||||
}
|
||||
}
|
||||
out:
|
||||
sdmmc_storage_end(&storage);
|
||||
sleep(1000000);
|
||||
|
||||
btn_wait();
|
||||
}
|
||||
|
||||
void print_sdcard_info()
|
||||
{
|
||||
gfx_clear(&gfx_ctxt, 0xFF000000);
|
||||
gfx_con_setpos(&gfx_con, 0, 0);
|
||||
|
||||
static const u32 SECTORS_TO_MIB_COEFF = 0x800;
|
||||
|
||||
if (!sd_mount())
|
||||
{
|
||||
gfx_printf(&gfx_con, "%kFailed to mount SD card (make sure that it is inserted).%k\n",
|
||||
0xFF0000FF, 0xFFFFFFFF);
|
||||
}
|
||||
else
|
||||
{
|
||||
u32 capacity;
|
||||
|
||||
gfx_printf(&gfx_con, "%kCard IDentification:%k\n", 0xFFFFDD00, 0xFFFFFFFF);
|
||||
gfx_printf(&gfx_con,
|
||||
" Vendor ID: %02x\n\
|
||||
OEM ID: %c%c\n\
|
||||
Model: %c%c%c%c%c\n\
|
||||
HW rev: %X\n\
|
||||
FW rev: %X\n\
|
||||
S/N: %08x\n\
|
||||
Month/Year: %02d/%04d\n\n",
|
||||
sd_storage.cid.manfid, (sd_storage.cid.oemid >> 8) & 0xFF, sd_storage.cid.oemid & 0xFF,
|
||||
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.hwrev, sd_storage.cid.fwrev, sd_storage.cid.serial,
|
||||
sd_storage.cid.month, sd_storage.cid.year);
|
||||
|
||||
gfx_printf(&gfx_con, "%kCard-Specific Data V%d.0:%k\n", 0xFFFFDD00, sd_storage.csd.structure + 1, 0xFFFFFFFF);
|
||||
switch(sd_storage.csd.structure)
|
||||
{
|
||||
case 0:
|
||||
capacity = (sd_storage.csd.capacity << sd_storage.csd.read_blkbits) / 1024 / 1024;
|
||||
gfx_printf(&gfx_con,
|
||||
" Cmd Classes: %02X\n\
|
||||
Capacity: %d MiB\n",
|
||||
sd_storage.csd.cmdclass, capacity);
|
||||
break;
|
||||
case 1:
|
||||
capacity = (sd_storage.csd.c_size << sd_storage.csd.read_blkbits) / 1024;
|
||||
gfx_printf(&gfx_con,
|
||||
" Cmd Classes: %02X\n\
|
||||
Capacity: %d MiB\n",
|
||||
sd_storage.csd.cmdclass, capacity);
|
||||
break;
|
||||
}
|
||||
gfx_printf(&gfx_con,
|
||||
" Bus Width: %d\n\
|
||||
Speed Class: %d\n\
|
||||
UHS Grade: U%d\n\
|
||||
Video Class: V%d\n\
|
||||
App perf class: A%d\n\n",
|
||||
sd_storage.ssr.bus_width, sd_storage.ssr.speed_class, sd_storage.ssr.uhs_grade,
|
||||
sd_storage.ssr.video_class, sd_storage.ssr.app_class);
|
||||
|
||||
gfx_puts(&gfx_con, "Acquiring FAT volume info...\n\n");
|
||||
f_getfree("", &sd_fs.free_clst, NULL);
|
||||
gfx_printf(&gfx_con, "%kFound %s volume:%k\n Free: %d MiB\n", 0xFFFFDD00,
|
||||
sd_fs.fs_type == FS_EXFAT ? "exFAT" : "FAT32", 0xFFFFFFFF,
|
||||
sd_fs.free_clst * sd_fs.csize / SECTORS_TO_MIB_COEFF);
|
||||
}
|
||||
|
||||
sleep(1000000);
|
||||
|
||||
sleep(100000);
|
||||
btn_wait();
|
||||
}
|
||||
|
||||
@@ -608,8 +289,7 @@ void print_tsec_key()
|
||||
const pkg1_id_t *pkg1_id = pkg1_identify(pkg1);
|
||||
if (!pkg1_id)
|
||||
{
|
||||
gfx_printf(&gfx_con, "%kCould not identify package 1 version to read TSEC firmware (= '%s').%k\n",
|
||||
0xFF0000FF, (char *)pkg1 + 0x10, 0xFFFFFFFF);
|
||||
gfx_printf(&gfx_con, "%kCould not identify package 1 version to read TSEC firmware (= '%s').%k\n", 0xFF0000FF, (char *)pkg1 + 0x10, 0xFFFFFFFF);
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -632,7 +312,7 @@ void print_tsec_key()
|
||||
out:;
|
||||
free(pkg1);
|
||||
sdmmc_storage_end(&storage);
|
||||
sleep(1000000);
|
||||
sleep(100000);
|
||||
btn_wait();
|
||||
}
|
||||
|
||||
@@ -655,11 +335,60 @@ void power_off()
|
||||
i2c_send_byte(I2C_5, 0x3C, MAX77620_REG_ONOFFCNFG1, MAX77620_ONOFFCNFG1_PWR_OFF);
|
||||
}
|
||||
|
||||
//TODO: ugly.
|
||||
sdmmc_t sd_sdmmc;
|
||||
sdmmc_storage_t sd_storage;
|
||||
FATFS sd_fs;
|
||||
int sd_mounted;
|
||||
|
||||
int sd_mount()
|
||||
{
|
||||
if (sd_mounted)
|
||||
return 1;
|
||||
|
||||
if (sdmmc_storage_init_sd(&sd_storage, &sd_sdmmc, SDMMC_1, SDMMC_BUS_WIDTH_4, 11) &&
|
||||
f_mount(&sd_fs, "", 1) == FR_OK)
|
||||
{
|
||||
sd_mounted = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void *sd_file_read(char *path)
|
||||
{
|
||||
FIL fp;
|
||||
if (f_open(&fp, path, FA_READ) != FR_OK)
|
||||
return NULL;
|
||||
|
||||
u32 size = f_size(&fp);
|
||||
void *buf = malloc(size);
|
||||
|
||||
u8 *ptr = buf;
|
||||
while (size > 0)
|
||||
{
|
||||
u32 rsize = MIN(size, 512);
|
||||
if (f_read(&fp, ptr, rsize, NULL) != FR_OK)
|
||||
{
|
||||
free(buf);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ptr += rsize;
|
||||
size -= rsize;
|
||||
}
|
||||
|
||||
f_close(&fp);
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
int dump_emmc_part(char *sd_path, sdmmc_storage_t *storage, emmc_part_t *part)
|
||||
{
|
||||
static const u32 FAT32_FILESIZE_LIMIT = 0xFFFFFFFF;
|
||||
static const u32 MULTIPART_SPLIT_SIZE = (1u << 31);
|
||||
static const u32 SECTORS_TO_MIB_COEFF = 0x800;
|
||||
static const u32 SECTORS_TO_MB_COEFF = 0x800;
|
||||
|
||||
u32 totalSectors = part->lba_end - part->lba_start + 1;
|
||||
u32 currPartIdx = 0;
|
||||
@@ -677,9 +406,9 @@ int dump_emmc_part(char *sd_path, sdmmc_storage_t *storage, emmc_part_t *part)
|
||||
memcpy(partialIdxFilename, "partial.idx", 11);
|
||||
partialIdxFilename[11] = 0;
|
||||
|
||||
gfx_printf(&gfx_con, "SD Card free space: %d MiB, Total dump size %d MiB\n",
|
||||
sd_fs.free_clst * sd_fs.csize / SECTORS_TO_MIB_COEFF,
|
||||
totalSectors / SECTORS_TO_MIB_COEFF);
|
||||
gfx_printf(&gfx_con, "SD Card free space: %dMB, Total dump size %dMB\n",
|
||||
sd_fs.free_clst * sd_fs.csize / SECTORS_TO_MB_COEFF,
|
||||
totalSectors / SECTORS_TO_MB_COEFF);
|
||||
|
||||
// Check if the USER partition or the RAW eMMC fits the sd card free space
|
||||
if (totalSectors > (sd_fs.free_clst * sd_fs.csize))
|
||||
@@ -717,7 +446,7 @@ int dump_emmc_part(char *sd_path, sdmmc_storage_t *storage, emmc_part_t *part)
|
||||
}
|
||||
|
||||
// Check if filesystem is FAT32 or the free space is smaller and dump in parts
|
||||
if (((sd_fs.fs_type != FS_EXFAT) && totalSectors > (FAT32_FILESIZE_LIMIT/NX_EMMC_BLOCKSIZE)) | isSmallSdCard)
|
||||
if (((sd_fs.fs_type != FS_EXFAT) || isSmallSdCard) && totalSectors > (FAT32_FILESIZE_LIMIT/NX_EMMC_BLOCKSIZE))
|
||||
{
|
||||
static const u32 MULTIPART_SPLIT_SECTORS = MULTIPART_SPLIT_SIZE/NX_EMMC_BLOCKSIZE;
|
||||
numSplitParts = (totalSectors+MULTIPART_SPLIT_SECTORS-1)/MULTIPART_SPLIT_SECTORS;
|
||||
@@ -801,7 +530,6 @@ int dump_emmc_part(char *sd_path, sdmmc_storage_t *storage, emmc_part_t *part)
|
||||
free(buf);
|
||||
return 0;
|
||||
}
|
||||
// Sd card fatal error.
|
||||
if (res && !ignoreWriteErrors)
|
||||
{
|
||||
gfx_printf(&gfx_con, "%k\nPress any key and try again.%k\n",
|
||||
@@ -836,25 +564,25 @@ int dump_emmc_part(char *sd_path, sdmmc_storage_t *storage, emmc_part_t *part)
|
||||
0xFF0000FF, num, lba_curr, ++retryCount, 0xFFFFFFFF);
|
||||
|
||||
sleep(500000);
|
||||
if (retryCount >= 10)
|
||||
if (retryCount >= 10)
|
||||
goto out;
|
||||
}
|
||||
res = f_write(&fp, buf, NX_EMMC_BLOCKSIZE * num, NULL);
|
||||
if (res && !ignoreWriteErrors)
|
||||
{
|
||||
gfx_printf(&gfx_con, "%k\nFatal error %d when writing to SD Card%k\n\n\
|
||||
Press VOL to abort and try again.\nPress POWER to ignore errors (will produce a corrupt dump).\n",
|
||||
gfx_printf(&gfx_con, "%kFatal error %d when writing to SD Card%k\n\
|
||||
Press VOL to abort and try again\nPress POWER to ignore errors (will produce a corrupt dump)",
|
||||
0xFF0000FF, res, 0xFFFFFFFF);
|
||||
u32 btn = btn_wait();
|
||||
|
||||
if (btn & BTN_POWER)
|
||||
{
|
||||
ignoreWriteErrors = 1;
|
||||
bytesWritten = MULTIPART_SPLIT_SIZE - num * NX_EMMC_BLOCKSIZE;
|
||||
currPartIdx--;
|
||||
}
|
||||
else
|
||||
{
|
||||
bytesWritten = MULTIPART_SPLIT_SIZE - num * NX_EMMC_BLOCKSIZE;
|
||||
currPartIdx--;
|
||||
ignoreWriteErrors = 1;
|
||||
}
|
||||
}
|
||||
u32 pct = (u64)((u64)(lba_curr - part->lba_start) * 100u) / (u64)(part->lba_end - part->lba_start);
|
||||
@@ -884,9 +612,8 @@ out:;
|
||||
if(partialDumpInProgress)
|
||||
{
|
||||
f_unlink(partialIdxFilename);
|
||||
gfx_printf(&gfx_con, "\n\nYou can now join the files and get the complete raw eMMC dump.");
|
||||
gfx_printf(&gfx_con, "\n\nYou can now join the files and get the complete raw eMMC dump.\n");
|
||||
}
|
||||
gfx_putc(&gfx_con, '\n');
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -901,13 +628,12 @@ typedef enum
|
||||
|
||||
static void dump_emmc_selected(dumpType_t dumpType)
|
||||
{
|
||||
u32 timer = 0;
|
||||
gfx_clear(&gfx_ctxt, 0xFF000000);
|
||||
gfx_con_setpos(&gfx_con, 0, 0);
|
||||
|
||||
if (!sd_mount())
|
||||
{
|
||||
gfx_printf(&gfx_con, "%kFailed to init/mount SD card (make sure that it is inserted).%k\n", 0xFF0000FF, 0xFFFFFFFF);
|
||||
gfx_printf(&gfx_con, "%kFailed to mount SD card (make sure that it is inserted).%k\n", 0xFF0000FF, 0xFFFFFFFF);
|
||||
goto out;
|
||||
}
|
||||
else
|
||||
@@ -926,7 +652,6 @@ static void dump_emmc_selected(dumpType_t dumpType)
|
||||
}
|
||||
|
||||
int i = 0;
|
||||
timer = get_tmr();
|
||||
if (dumpType & DUMP_BOOT)
|
||||
{
|
||||
static const u32 BOOT_PART_SIZE = 0x400000;
|
||||
@@ -992,12 +717,11 @@ static void dump_emmc_selected(dumpType_t dumpType)
|
||||
}
|
||||
}
|
||||
|
||||
gfx_printf(&gfx_con, "%kTime taken: %d seconds.%k\n", 0xFF00FF96, (get_tmr() - timer) / 1000000, 0xFFFFFFFF);
|
||||
sdmmc_storage_end(&storage);
|
||||
gfx_puts(&gfx_con, "\nDone. Press any key.\n");
|
||||
gfx_puts(&gfx_con, "Done. Press any key.\n");
|
||||
|
||||
out:;
|
||||
sleep(1000000);
|
||||
sleep(100000);
|
||||
btn_wait();
|
||||
}
|
||||
|
||||
@@ -1006,103 +730,6 @@ void dump_emmc_user() { dump_emmc_selected(DUMP_USER); }
|
||||
void dump_emmc_boot() { dump_emmc_selected(DUMP_BOOT); }
|
||||
void dump_emmc_rawnand() { dump_emmc_selected(DUMP_RAW); }
|
||||
|
||||
u32 save_to_file(void * buf, u32 size, const char * filename)
|
||||
{
|
||||
FIL fp;
|
||||
if (f_open(&fp, filename, FA_CREATE_ALWAYS | FA_WRITE) != FR_OK) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
f_sync(&fp);
|
||||
f_write(&fp, buf, size, NULL);
|
||||
f_close(&fp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void dump_package1()
|
||||
{
|
||||
u8 * pkg1 = (u8 *)malloc(0x40000);
|
||||
u8 * warmboot = (u8 *)malloc(0x40000);
|
||||
u8 * secmon = (u8 *)malloc(0x40000);
|
||||
|
||||
gfx_clear(&gfx_ctxt, 0xFF000000);
|
||||
gfx_con_setpos(&gfx_con, 0, 0);
|
||||
|
||||
if (!sd_mount())
|
||||
{
|
||||
gfx_printf(&gfx_con, "%kFailed to mount SD card (make sure that it is inserted).%k\n", 0xFF0000FF, 0xFFFFFFFF);
|
||||
goto out;
|
||||
}
|
||||
|
||||
sdmmc_storage_t storage;
|
||||
sdmmc_t sdmmc;
|
||||
if(!sdmmc_storage_init_mmc(&storage, &sdmmc, SDMMC_4, SDMMC_BUS_WIDTH_8, 4))
|
||||
{
|
||||
gfx_printf(&gfx_con, "%kFailed to init eMMC.%k\n", 0xFF0000FF, 0xFFFFFFFF);
|
||||
goto out;
|
||||
}
|
||||
sdmmc_storage_set_mmc_partition(&storage, 1);
|
||||
|
||||
//Read package1.
|
||||
sdmmc_storage_read(&storage, 0x100000 / NX_EMMC_BLOCKSIZE, 0x40000 / NX_EMMC_BLOCKSIZE, pkg1);
|
||||
const pkg1_id_t *pkg1_id = pkg1_identify(pkg1);
|
||||
const pk11_hdr_t *hdr = (pk11_hdr_t *)(pkg1 + pkg1_id->pkg11_off + 0x20);
|
||||
if (!pkg1_id)
|
||||
{
|
||||
gfx_printf(&gfx_con, "%kCould not identify package 1 version to read TSEC firmware (= '%s').%k\n", 0xFF0000FF, (char *)pkg1 + 0x10, 0xFFFFFFFF);
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
||||
// Read keyblob
|
||||
u8 * keyblob = (u8 *)malloc(NX_EMMC_BLOCKSIZE);
|
||||
sdmmc_storage_read(&storage, 0x180000 / NX_EMMC_BLOCKSIZE + pkg1_id->kb, 1, keyblob);
|
||||
|
||||
// decrypt
|
||||
keygen(keyblob, pkg1_id->kb, (u8 *)pkg1 + pkg1_id->tsec_off);
|
||||
pkg1_decrypt(pkg1_id, pkg1);
|
||||
|
||||
pkg1_unpack(warmboot, secmon, pkg1_id, pkg1);
|
||||
|
||||
// display info
|
||||
gfx_printf(&gfx_con, "%kSecure monitor addr: %08X\n", 0xFF0000FF, pkg1_id->secmon_base);
|
||||
gfx_printf(&gfx_con, "%kSecure monitor size: %08X\n", 0xFF0000FF, hdr->sm_size);
|
||||
gfx_printf(&gfx_con, "%kSecure monitor off: %08X\n", 0xFF0000FF, hdr->sm_off);
|
||||
|
||||
// dump package1
|
||||
if (save_to_file(pkg1, 0x40000, "pkg_decr.bin") == -1) {
|
||||
gfx_printf(&gfx_con, "Failed to create pkg_decr.bin\n");
|
||||
goto out;
|
||||
}
|
||||
gfx_puts(&gfx_con, "%kPackage1 dumped to pkg_decr.bin\n");
|
||||
|
||||
// dump sm
|
||||
if (save_to_file(secmon, 0x40000, "sm.bin") == -1) {
|
||||
gfx_puts(&gfx_con, "Failed to create sm.bin\n");
|
||||
goto out;
|
||||
}
|
||||
gfx_puts(&gfx_con, "Secure Monitor dumped to sm.bin\n");
|
||||
|
||||
// dump warmboot
|
||||
if (save_to_file(warmboot, 0x40000, "warmboot.bin") == -1) {
|
||||
gfx_puts(&gfx_con, "Failed to create warmboot.bin\n");
|
||||
goto out;
|
||||
}
|
||||
gfx_puts(&gfx_con, "Warmboot dumped to warmboot.bin\n");
|
||||
|
||||
|
||||
sdmmc_storage_end(&storage);
|
||||
gfx_puts(&gfx_con, "Done. Press any key.\n");
|
||||
|
||||
out:;
|
||||
free(pkg1);
|
||||
free(secmon);
|
||||
free(warmboot);
|
||||
sleep(1000000);
|
||||
btn_wait();
|
||||
}
|
||||
|
||||
void launch_firmware()
|
||||
{
|
||||
ini_sec_t *cfg_sec = NULL;
|
||||
@@ -1205,8 +832,6 @@ ment_t ment_cinfo[] = {
|
||||
MDEF_HANDLER("Print fuse info", print_fuseinfo),
|
||||
MDEF_HANDLER("Print kfuse info", print_kfuseinfo),
|
||||
MDEF_HANDLER("Print TSEC keys", print_tsec_key),
|
||||
MDEF_HANDLER("Print eMMC info", print_mmc_info),
|
||||
MDEF_HANDLER("Print SD Card info", print_sdcard_info),
|
||||
MDEF_END()
|
||||
};
|
||||
menu_t menu_cinfo = {
|
||||
@@ -1220,7 +845,6 @@ ment_t ment_tools[] = {
|
||||
MDEF_HANDLER("Dump eMMC SYS", dump_emmc_system),
|
||||
MDEF_HANDLER("Dump eMMC USER", dump_emmc_user),
|
||||
MDEF_HANDLER("Dump eMMC BOOT", dump_emmc_boot),
|
||||
MDEF_HANDLER("Dump Package1", dump_package1),
|
||||
MDEF_END()
|
||||
};
|
||||
menu_t menu_tools = {
|
||||
@@ -1240,7 +864,7 @@ ment_t ment_top[] = {
|
||||
};
|
||||
menu_t menu_top = {
|
||||
ment_top,
|
||||
"hekate - ipl (CTCaer mod v1.3)", 0, 0
|
||||
"hekate - ipl", 0, 0
|
||||
};
|
||||
|
||||
extern void pivot_stack(u32 stack_top);
|
||||
|
||||
@@ -289,7 +289,6 @@ c : clear by read
|
||||
#define EXT_CSD_CACHE_SIZE 249 /* RO, 4 bytes */
|
||||
#define EXT_CSD_PWR_CL_DDR_200_360 253 /* RO */
|
||||
#define EXT_CSD_FIRMWARE_VERSION 254 /* RO, 8 bytes */
|
||||
#define EXT_CSD_DEVICE_VERSION 262 /* RO, 2 bytes */
|
||||
#define EXT_CSD_PRE_EOL_INFO 267 /* RO */
|
||||
#define EXT_CSD_DEVICE_LIFE_TIME_EST_TYP_A 268 /* RO */
|
||||
#define EXT_CSD_DEVICE_LIFE_TIME_EST_TYP_B 269 /* RO */
|
||||
|
||||
33
ipl/pkg1.c
33
ipl/pkg1.c
@@ -47,22 +47,6 @@ PATCHSET_DEF(_secmon_3_patchset,
|
||||
{ 0xAC8 + 0xADC, _NOP() } //Sections SHA2.
|
||||
);
|
||||
|
||||
PATCHSET_DEF(_secmon_5_patchset,
|
||||
//Patch package2 decryption and signature/hash checks.
|
||||
{ 0x1218 + 0x6E68, _NOP() }, //Header signature.
|
||||
{ 0x1218 + 0x6E74, _NOP() }, //Version.
|
||||
{ 0x1218 + 0x6FE4, _NOP() }, //Sections SHA2.
|
||||
{ 0x1218 + 0x2DC, _NOP() } //Unknown.
|
||||
);
|
||||
|
||||
PATCHSET_DEF(_secmon_6_patchset,
|
||||
{ 0x12b0 + 0x4d0, _NOP() },
|
||||
{ 0x12b0 + 0x4dc, _NOP() },
|
||||
{ 0x12b0 + 0x794, _NOP() },
|
||||
{ 0x12b0 + 0xb30, _NOP() }//,
|
||||
//{ 0x12b0 + 0xa18 , _NOP() } // BootConfig Retail Check
|
||||
);
|
||||
|
||||
/*
|
||||
* package1.1 header: <wb, ldr, sm>
|
||||
* package1.1 layout:
|
||||
@@ -78,12 +62,23 @@ static const pkg1_id_t _pkg1_ids[] = {
|
||||
{ "20161121183008", 0, 0x1900, 0x3FE0, { 2, 1, 0 }, 0x40014020, _secmon_1_patchset }, //1.0.0
|
||||
{ "20170210155124", 0, 0x1900, 0x3FE0, { 0, 1, 2 }, 0x4002D000, _secmon_2_patchset }, //2.0.0
|
||||
{ "20170519101410", 1, 0x1A00, 0x3FE0, { 0, 1, 2 }, 0x4002D000, NULL }, //3.0.0
|
||||
{ "20170710161758", 2, 0x1A00, 0x3FE0, { 0, 1, 2 }, 0x4002D000, NULL }, //3.0.1
|
||||
{ "20170921172629", 3, 0x1800, 0x3FE0, { 1, 2, 0 }, 0x4002B000, _secmon_5_patchset }, //4.0.0
|
||||
{ "20180220163747", 4, 0x1900, 0x3FE0, { 1, 2, 0 }, 0x4002B000, _secmon_6_patchset }, //5.0.0
|
||||
{ "20170710161758", 2, 0x1A00, 0x3FE0, { 0, 1, 2 }, 0x4002D000, NULL }, //3.0.1
|
||||
{ "20170921172629", 3, 0x1800, 0x3FE0, { 1, 2, 0 }, 0x4002B000, NULL }, //4.0.0
|
||||
{ "20180220163747", 4, 0x1900, 0x3FE0, { 1, 2, 0 }, 0x4002B000, NULL }, //5.0.0
|
||||
{ NULL, 0, 0, 0, 0 } //End.
|
||||
};
|
||||
|
||||
typedef struct _pk11_hdr_t
|
||||
{
|
||||
u32 magic;
|
||||
u32 wb_size;
|
||||
u32 wb_off;
|
||||
u32 pad;
|
||||
u32 ldr_size;
|
||||
u32 ldr_off;
|
||||
u32 sm_size;
|
||||
u32 sm_off;
|
||||
} pk11_hdr_t;
|
||||
|
||||
const pkg1_id_t *pkg1_identify(u8 *pkg1)
|
||||
{
|
||||
|
||||
13
ipl/pkg1.h
13
ipl/pkg1.h
@@ -42,19 +42,6 @@ typedef struct _pkg1_id_t
|
||||
patch_t *secmon_patchset;
|
||||
} pkg1_id_t;
|
||||
|
||||
|
||||
typedef struct _pk11_hdr_t
|
||||
{
|
||||
u32 magic;
|
||||
u32 wb_size;
|
||||
u32 wb_off;
|
||||
u32 pad;
|
||||
u32 ldr_size;
|
||||
u32 ldr_off;
|
||||
u32 sm_size;
|
||||
u32 sm_off;
|
||||
} pk11_hdr_t;
|
||||
|
||||
const pkg1_id_t *pkg1_identify(u8 *pkg1);
|
||||
void pkg1_decrypt(const pkg1_id_t *id, u8 *pkg1);
|
||||
void pkg1_unpack(void *warmboot_dst, void *secmon_dst, const pkg1_id_t *id, u8 *pkg1);
|
||||
|
||||
@@ -172,4 +172,3 @@ DPRINTF("INI1 encrypted\n");
|
||||
memset(hdr->ctr, 0 , 0x10);
|
||||
*(u32 *)hdr->ctr = 0x100 + sizeof(pkg2_hdr_t) + kernel_size + ini1_size;
|
||||
}
|
||||
|
||||
|
||||
22
ipl/sd.h
22
ipl/sd.h
@@ -35,11 +35,10 @@
|
||||
#define SD_APP_SEND_SCR 51 /* adtc R1 */
|
||||
|
||||
/* OCR bit definitions */
|
||||
#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_VDD_32_33 (1 << 20) /* VDD voltage 3.2 ~ 3.3 */
|
||||
#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 */
|
||||
|
||||
/*
|
||||
* SD_SWITCH argument format:
|
||||
@@ -65,11 +64,10 @@
|
||||
/*
|
||||
* 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 */
|
||||
#define SD_SCR_BUS_WIDTH_1 (1<<0)
|
||||
#define SD_SCR_BUS_WIDTH_4 (1<<2)
|
||||
|
||||
/*
|
||||
* SD bus widths
|
||||
@@ -77,16 +75,6 @@
|
||||
#define SD_BUS_WIDTH_1 0
|
||||
#define SD_BUS_WIDTH_4 2
|
||||
|
||||
/*
|
||||
* SD bus speeds
|
||||
*/
|
||||
#define UHS_SDR12_BUS_SPEED 0
|
||||
#define HIGH_SPEED_BUS_SPEED 1
|
||||
#define UHS_SDR25_BUS_SPEED 1
|
||||
#define UHS_SDR50_BUS_SPEED 2
|
||||
#define UHS_SDR104_BUS_SPEED 3
|
||||
#define UHS_DDR50_BUS_SPEED 4
|
||||
|
||||
/*
|
||||
* SD_SWITCH mode
|
||||
*/
|
||||
|
||||
316
ipl/sdmmc.c
316
ipl/sdmmc.c
@@ -223,7 +223,7 @@ static int _mmc_storage_get_op_cond(sdmmc_storage_t *storage, u32 power)
|
||||
u32 cond = 0;
|
||||
if (!_mmc_storage_get_op_cond_inner(storage, &cond, power))
|
||||
break;
|
||||
if (cond & MMC_CARD_BUSY)
|
||||
if (cond & 0x80000000)
|
||||
{
|
||||
if (cond & 0x40000000)
|
||||
storage->has_sector_access = 1;
|
||||
@@ -242,76 +242,6 @@ static int _mmc_storage_set_relative_addr(sdmmc_storage_t *storage)
|
||||
return _sdmmc_storage_execute_cmd_type1(storage, MMC_SET_RELATIVE_ADDR, storage->rca << 16, 0, 0x10);
|
||||
}
|
||||
|
||||
static void _mmc_storage_parse_cid(sdmmc_storage_t *storage)
|
||||
{
|
||||
u32 *raw_cid = (u32 *)&(storage->raw_cid);
|
||||
|
||||
switch (storage->csd.mmca_vsn)
|
||||
{
|
||||
case 0: /* MMC v1.0 - v1.2 */
|
||||
case 1: /* MMC v1.4 */
|
||||
storage->cid.prod_name[6] = unstuff_bits(raw_cid, 48, 8);
|
||||
storage->cid.manfid = unstuff_bits(raw_cid, 104, 24);
|
||||
storage->cid.hwrev = unstuff_bits(raw_cid, 44, 4);
|
||||
storage->cid.fwrev = unstuff_bits(raw_cid, 40, 4);
|
||||
storage->cid.serial = unstuff_bits(raw_cid, 16, 24);
|
||||
break;
|
||||
case 2: /* MMC v2.0 - v2.2 */
|
||||
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);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
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.prod_name[5] = unstuff_bits(raw_cid, 56, 8);
|
||||
|
||||
storage->cid.month = unstuff_bits(raw_cid, 12, 4);
|
||||
storage->cid.year = unstuff_bits(raw_cid, 8, 4) + 1997;
|
||||
if (storage->ext_csd.rev >= 5)
|
||||
{
|
||||
if (storage->cid.year < 2010)
|
||||
storage->cid.year += 16;
|
||||
}
|
||||
}
|
||||
|
||||
static void _mmc_storage_parse_csd(sdmmc_storage_t *storage)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
static int _mmc_storage_parse_ext_csd(sdmmc_storage_t *storage, u8 *buf)
|
||||
{
|
||||
storage->ext_csd.rev = buf[EXT_CSD_REV];
|
||||
storage->ext_csd.ext_struct = buf[EXT_CSD_STRUCTURE];
|
||||
storage->ext_csd.card_type = buf[EXT_CSD_CARD_TYPE];
|
||||
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->sec_cnt = *(u32 *)&buf[EXT_CSD_SEC_CNT];
|
||||
}
|
||||
|
||||
static int _mmc_storage_get_ext_csd(sdmmc_storage_t *storage, void *buf)
|
||||
{
|
||||
sdmmc_cmd_t cmdbuf;
|
||||
@@ -330,8 +260,6 @@ static int _mmc_storage_get_ext_csd(sdmmc_storage_t *storage, void *buf)
|
||||
|
||||
u32 tmp = 0;
|
||||
sdmmc_get_rsp(storage->sdmmc, &tmp, 4, SDMMC_RSP_TYPE_1);
|
||||
_mmc_storage_parse_ext_csd(storage, buf);
|
||||
|
||||
return _sdmmc_storage_check_result(tmp);
|
||||
}
|
||||
|
||||
@@ -460,7 +388,7 @@ int sdmmc_storage_init_mmc(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 id, u32
|
||||
return 0;
|
||||
DPRINTF("[mmc] got op cond\n");
|
||||
|
||||
if (!_sdmmc_storage_get_cid(storage, storage->raw_cid))
|
||||
if (!_sdmmc_storage_get_cid(storage, storage->cid))
|
||||
return 0;
|
||||
DPRINTF("[mmc] got cid\n");
|
||||
|
||||
@@ -468,10 +396,9 @@ int sdmmc_storage_init_mmc(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 id, u32
|
||||
return 0;
|
||||
DPRINTF("[mmc] set relative addr\n");
|
||||
|
||||
if (!_sdmmc_storage_get_csd(storage, storage->raw_csd))
|
||||
if (!_sdmmc_storage_get_csd(storage, storage->csd))
|
||||
return 0;
|
||||
DPRINTF("[mmc] got csd\n");
|
||||
_mmc_storage_parse_csd(storage);
|
||||
|
||||
if (!sdmmc_setup_clock(storage->sdmmc, 1))
|
||||
return 0;
|
||||
@@ -485,7 +412,7 @@ int sdmmc_storage_init_mmc(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 id, u32
|
||||
return 0;
|
||||
DPRINTF("[mmc] set blocklen to 512\n");
|
||||
|
||||
u32 *csd = (u32 *)storage->raw_csd;
|
||||
u32 *csd = (u32 *)storage->csd;
|
||||
//Check system specification version, only version 4.0 and later support below features.
|
||||
if (unstuff_bits(csd, 122, 4) < CSD_SPEC_VER_4)
|
||||
{
|
||||
@@ -503,28 +430,23 @@ int sdmmc_storage_init_mmc(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 id, u32
|
||||
free(ext_csd);
|
||||
return 0;
|
||||
}
|
||||
free(ext_csd);
|
||||
DPRINTF("[mmc] got ext_csd\n");
|
||||
_mmc_storage_parse_cid(storage); //This needs to be after csd and ext_csd
|
||||
//gfx_hexdump(&gfx_con, 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 (storage->ext_csd.bkops & 0x1 && !(storage->ext_csd.bkops_en & EXT_CSD_BKOPS_LEVEL_2) && 0)
|
||||
{
|
||||
_mmc_storage_enable_bkops(storage);
|
||||
DPRINTF("[mmc] BKOPS enabled\n");
|
||||
}
|
||||
else
|
||||
DPRINTF("[mmc] BKOPS disabled\n");
|
||||
storage->sec_cnt = *(u32 *)&ext_csd[EXT_CSD_SEC_CNT];
|
||||
|
||||
if (!_mmc_storage_enable_highspeed(storage, storage->ext_csd.card_type, type))
|
||||
if (storage->cid[0xE] == 0x11 && ext_csd[EXT_CSD_BKOPS_EN] & EXT_CSD_BKOPS_LEVEL_2)
|
||||
_mmc_storage_enable_bkops(storage);
|
||||
|
||||
if (!_mmc_storage_enable_highspeed(storage, ext_csd[EXT_CSD_CARD_TYPE], type))
|
||||
{
|
||||
free(ext_csd);
|
||||
return 0;
|
||||
DPRINTF("[mmc] switched to highspeed mode\n");
|
||||
}
|
||||
DPRINTF("[mmc] switched to possible highspeed mode\n");
|
||||
|
||||
sdmmc_sd_clock_ctrl(storage->sdmmc, 1);
|
||||
|
||||
free(ext_csd);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -562,26 +484,21 @@ static int _sd_storage_send_if_cond(sdmmc_storage_t *storage)
|
||||
sdmmc_cmd_t cmdbuf;
|
||||
sdmmc_init_cmd(&cmdbuf, SD_SEND_IF_COND, 0x1AA, SDMMC_RSP_TYPE_5, 0);
|
||||
if (!sdmmc_execute_cmd(storage->sdmmc, &cmdbuf, 0, 0))
|
||||
return 1; // The SD Card is version 1.X
|
||||
return 0;
|
||||
|
||||
//TODO: we may have received a timeout error in the above request, which indicates a version 1 card.
|
||||
|
||||
u32 resp = 0;
|
||||
if (!sdmmc_get_rsp(storage->sdmmc, &resp, 4, SDMMC_RSP_TYPE_5))
|
||||
return 2;
|
||||
return 0;
|
||||
|
||||
return (resp & 0xFF) == 0xAA ? 0 : 2;
|
||||
return (resp & 0xFF) == 0xAA ? 1 : 0;
|
||||
}
|
||||
|
||||
static int _sd_storage_get_op_cond_once(sdmmc_storage_t *storage, u32 *cond, int is_version_1, int supports_low_voltage)
|
||||
{
|
||||
sdmmc_cmd_t cmdbuf;
|
||||
// Support for Current > 150mA
|
||||
u32 arg = (~is_version_1 & 1) ? SD_OCR_XPC : 0;
|
||||
// Support for handling block-addressed SDHC cards
|
||||
arg |= (~is_version_1 & 1) ? SD_OCR_CCS : 0;
|
||||
// Support for 1.8V
|
||||
arg |= (supports_low_voltage & ~is_version_1 & 1) ? 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;
|
||||
u32 arg = (((~is_version_1 & 1) << 28) & 0xBFFFFFFF | ((~is_version_1 & 1) << 30)) & 0xFEFFFFFF | ((supports_low_voltage & ~is_version_1 & 1) << 24) | 0x100000;
|
||||
sdmmc_init_cmd(&cmdbuf, SD_APP_OP_COND, arg, SDMMC_RSP_TYPE_3, 0);
|
||||
if (!_sd_storage_execute_app_cmd(storage, 0x10, is_version_1 ? 0x400000 : 0, &cmdbuf, 0, 0))
|
||||
return 0;
|
||||
@@ -597,12 +514,13 @@ static int _sd_storage_get_op_cond(sdmmc_storage_t *storage, int is_version_1, i
|
||||
u32 cond = 0;
|
||||
if (!_sd_storage_get_op_cond_once(storage, &cond, is_version_1, supports_low_voltage))
|
||||
break;
|
||||
if (cond & MMC_CARD_BUSY)
|
||||
if (cond & 0x80000000)
|
||||
{
|
||||
if (cond & SD_OCR_CCS)
|
||||
if (cond & 0x40000000)
|
||||
storage->has_sector_access = 1;
|
||||
|
||||
if (cond & SD_ROCR_S18A && supports_low_voltage)
|
||||
// TODO: Some SD Card incorrectly report low voltage support
|
||||
// Disable it for now
|
||||
if (cond & 0x1000000 && supports_low_voltage)
|
||||
{
|
||||
//The low voltage regulator configuration is valid for SDMMC1 only.
|
||||
if (storage->sdmmc->id == SDMMC_1 &&
|
||||
@@ -656,24 +574,7 @@ static int _sd_storage_get_rca(sdmmc_storage_t *storage)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void _sd_storage_parse_scr(sdmmc_storage_t *storage)
|
||||
{
|
||||
// unstuff_bits can parse only 4 u32
|
||||
u32 resp[4];
|
||||
|
||||
resp[3] = *(u32 *)&storage->raw_scr[4];
|
||||
resp[2] = *(u32 *)&storage->raw_scr[0];
|
||||
|
||||
storage->scr.sda_vsn = unstuff_bits(resp, 56, 4);
|
||||
storage->scr.bus_widths = unstuff_bits(resp, 48, 4);
|
||||
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);
|
||||
}
|
||||
|
||||
int _sd_storage_get_scr(sdmmc_storage_t *storage, u8 *buf)
|
||||
int _sd_storage_get_scr(sdmmc_storage_t *storage, void *buf)
|
||||
{
|
||||
sdmmc_cmd_t cmdbuf;
|
||||
sdmmc_init_cmd(&cmdbuf, SD_APP_SEND_SCR, 0, SDMMC_RSP_TYPE_1, 0);
|
||||
@@ -691,17 +592,6 @@ int _sd_storage_get_scr(sdmmc_storage_t *storage, u8 *buf)
|
||||
|
||||
u32 tmp = 0;
|
||||
sdmmc_get_rsp(storage->sdmmc, &tmp, 4, SDMMC_RSP_TYPE_1);
|
||||
//Prepare buffer for unstuff_bits
|
||||
for (int i = 0; i < 8; i+=4)
|
||||
{
|
||||
storage->raw_scr[i + 3] = buf[i];
|
||||
storage->raw_scr[i + 2] = buf[i + 1];
|
||||
storage->raw_scr[i + 1] = buf[i + 2];
|
||||
storage->raw_scr[i] = buf[i + 3];
|
||||
}
|
||||
_sd_storage_parse_scr(storage);
|
||||
//gfx_hexdump(&gfx_con, 0, storage->raw_scr, 8);
|
||||
|
||||
return _sdmmc_storage_check_result(tmp);
|
||||
}
|
||||
|
||||
@@ -783,7 +673,7 @@ int _sd_storage_enable_highspeed_low_volt(sdmmc_storage_t *storage, u32 type, u8
|
||||
if (buf[13] & 8)
|
||||
{
|
||||
type = 11;
|
||||
hs_type = UHS_SDR104_BUS_SPEED;
|
||||
hs_type = 3;
|
||||
break;
|
||||
}
|
||||
//Fall through.
|
||||
@@ -791,7 +681,7 @@ int _sd_storage_enable_highspeed_low_volt(sdmmc_storage_t *storage, u32 type, u8
|
||||
if (!(buf[13] & 4))
|
||||
return 0;
|
||||
type = 10;
|
||||
hs_type = UHS_SDR50_BUS_SPEED;
|
||||
hs_type = 2;
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
@@ -822,115 +712,8 @@ int _sd_storage_enable_highspeed_high_volt(sdmmc_storage_t *storage, u8 *buf)
|
||||
return sdmmc_setup_clock(storage->sdmmc, 7);
|
||||
}
|
||||
|
||||
static void _sd_storage_parse_ssr(sdmmc_storage_t *storage)
|
||||
{
|
||||
u32 *raw_ssr = (u32 *)&(storage->raw_ssr);
|
||||
storage->ssr.bus_width = unstuff_bits(raw_ssr, 510 - 384, 2) & SD_BUS_WIDTH_4 ? 4 : 1;
|
||||
switch(unstuff_bits(raw_ssr, 440 - 384, 8))
|
||||
{
|
||||
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;
|
||||
break;
|
||||
case 4:
|
||||
storage->ssr.speed_class = 10;
|
||||
break;
|
||||
default:
|
||||
storage->ssr.speed_class = unstuff_bits(raw_ssr, 440 - 384, 8);
|
||||
break;
|
||||
}
|
||||
storage->ssr.uhs_grade = unstuff_bits(raw_ssr, 396 - 384, 4);
|
||||
storage->ssr.video_class = unstuff_bits(raw_ssr, 384 - 384, 8);
|
||||
storage->ssr.app_class = unstuff_bits(raw_ssr + 16, 472 + 4 - 384, 4);
|
||||
}
|
||||
|
||||
static 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);
|
||||
|
||||
sdmmc_req_t reqbuf;
|
||||
reqbuf.buf = buf;
|
||||
reqbuf.blksize = 64;
|
||||
reqbuf.num_sectors = 1;
|
||||
reqbuf.is_write = 0;
|
||||
reqbuf.is_multi_block = 0;
|
||||
reqbuf.is_auto_cmd12 = 0;
|
||||
|
||||
if (!(storage->csd.cmdclass & CCC_APP_SPEC)) {
|
||||
DPRINTF("[sd] ssr: Card lacks mandatory SD Status function\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!_sd_storage_execute_app_cmd(storage, R1_STATE_TRAN, 0, &cmdbuf, &reqbuf, 0))
|
||||
return 0;
|
||||
|
||||
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)
|
||||
{
|
||||
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(&gfx_con, 0, storage->raw_ssr, 64);
|
||||
|
||||
return _sdmmc_storage_check_result(tmp);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
static void _sd_storage_parse_csd(sdmmc_storage_t *storage)
|
||||
{
|
||||
u32 *raw_csd = (u32 *)&(storage->raw_csd);
|
||||
|
||||
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);
|
||||
switch(storage->csd.structure)
|
||||
{
|
||||
case 0:
|
||||
storage->csd.capacity = (1 + unstuff_bits(raw_csd, 62, 12)) << (unstuff_bits(raw_csd, 47, 3) + 2);
|
||||
break;
|
||||
case 1:
|
||||
storage->csd.c_size = (1 + unstuff_bits(raw_csd, 48, 22));
|
||||
storage->csd.capacity = storage->csd.c_size << 10;
|
||||
storage->csd.read_blkbits = 9;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int sdmmc_storage_init_sd(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 id, u32 bus_width, u32 type)
|
||||
{
|
||||
int is_version_1 = 0;
|
||||
|
||||
memset(storage, 0, sizeof(sdmmc_storage_t));
|
||||
storage->sdmmc = sdmmc;
|
||||
|
||||
@@ -944,40 +727,47 @@ int sdmmc_storage_init_sd(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 id, u32
|
||||
return 0;
|
||||
DPRINTF("[sd] went to idle state\n");
|
||||
|
||||
is_version_1 = _sd_storage_send_if_cond(storage);
|
||||
if (is_version_1 == 2)
|
||||
if (!_sd_storage_send_if_cond(storage))
|
||||
return 0;
|
||||
DPRINTF("[sd] after send if cond\n");
|
||||
|
||||
if (!_sd_storage_get_op_cond(storage, is_version_1, bus_width == SDMMC_BUS_WIDTH_4 && type == 11))
|
||||
//TODO: use correct version here -----v
|
||||
if (!_sd_storage_get_op_cond(storage, 0, bus_width == SDMMC_BUS_WIDTH_4 && (type | 1) == 11))
|
||||
return 0;
|
||||
DPRINTF("[sd] got op cond\n");
|
||||
|
||||
if (!_sdmmc_storage_get_cid(storage, storage->raw_cid))
|
||||
if (!_sdmmc_storage_get_cid(storage, storage->cid))
|
||||
return 0;
|
||||
DPRINTF("[sd] got cid\n");
|
||||
_sd_storage_parse_cid(storage);
|
||||
|
||||
if (!_sd_storage_get_rca(storage))
|
||||
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, storage->csd))
|
||||
return 0;
|
||||
DPRINTF("[sd] got csd\n");
|
||||
|
||||
//Parse CSD.
|
||||
_sd_storage_parse_csd(storage);
|
||||
switch (storage->csd.structure)
|
||||
u32 *csd = (u32 *)storage->csd;
|
||||
u32 csd_struct = unstuff_bits(csd, 126, 2);
|
||||
switch (csd_struct)
|
||||
{
|
||||
case 0:
|
||||
storage->sec_cnt = storage->csd.capacity;
|
||||
storage->sec_cnt = (1 + unstuff_bits(csd, 62, 12)) << (unstuff_bits(csd, 47, 3) + 2);
|
||||
break;
|
||||
case 1:
|
||||
storage->sec_cnt = storage->csd.c_size << 10;
|
||||
storage->sec_cnt = (1 + unstuff_bits(csd, 48, 22)) << 10;
|
||||
break;
|
||||
case 2:
|
||||
storage->sec_cnt = (1 + unstuff_bits(csd, 48, 22)) << 10;
|
||||
break;
|
||||
default:
|
||||
DPRINTF("[sd] Unknown CSD structure %d\n", storage->csd.structure);
|
||||
DPRINTF("[sd] Unknown CSD structure %d\n", csd_struct);
|
||||
//TODO: I've encountered this with one of my SD cards, but
|
||||
// according to the spec only version 0 and 1 are
|
||||
// supposed to be in use (mine was version 2).
|
||||
//return 0;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1004,11 +794,11 @@ int sdmmc_storage_init_sd(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 id, u32
|
||||
u8 *buf = (u8 *)malloc(512);
|
||||
if (!_sd_storage_get_scr(storage, buf))
|
||||
return 0;
|
||||
//gfx_hexdump(&gfx_con, 0, storage->raw_scr, 8);
|
||||
memcpy(storage->scr, buf, 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))
|
||||
// Check if card supports a wider bus and if it's not SD Version 1.0
|
||||
if (bus_width == SDMMC_BUS_WIDTH_4 && storage->scr[1] & 4 && (storage->scr[0] & 0xF))
|
||||
{
|
||||
if (!_sd_storage_execute_app_cmd_type1(storage, &tmp, SD_APP_SET_BUS_WIDTH, SD_BUS_WIDTH_4, 0, R1_STATE_TRAN))
|
||||
{
|
||||
@@ -1030,7 +820,7 @@ int sdmmc_storage_init_sd(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 id, u32
|
||||
}
|
||||
DPRINTF("[sd] enabled highspeed (low voltage)\n");
|
||||
}
|
||||
else if (type != 6 && (storage->scr.sda_vsn & 0xF) != 0)
|
||||
else if (type != 6 && (storage->scr[0] & 0xF) != 0)
|
||||
{
|
||||
if (!_sd_storage_enable_highspeed_high_volt(storage, buf))
|
||||
{
|
||||
@@ -1042,10 +832,6 @@ int sdmmc_storage_init_sd(sdmmc_storage_t *storage, sdmmc_t *sdmmc, u32 id, u32
|
||||
|
||||
sdmmc_sd_clock_ctrl(sdmmc, 1);
|
||||
|
||||
// Parse additional card info from sd status
|
||||
if (_sd_storage_get_ssr(storage, buf))
|
||||
DPRINTF("[sd] got sd status\n");
|
||||
|
||||
free(buf);
|
||||
return 1;
|
||||
}
|
||||
@@ -1062,7 +848,7 @@ int _gc_storage_custom_cmd(sdmmc_storage_t *storage, void *buf)
|
||||
|
||||
sdmmc_req_t reqbuf;
|
||||
reqbuf.buf = buf;
|
||||
reqbuf.blksize = 64;
|
||||
reqbuf.blksize = 0x40;
|
||||
reqbuf.num_sectors = 1;
|
||||
reqbuf.is_write = 1;
|
||||
reqbuf.is_multi_block = 0;
|
||||
|
||||
70
ipl/sdmmc.h
70
ipl/sdmmc.h
@@ -20,64 +20,6 @@
|
||||
#include "types.h"
|
||||
#include "sdmmc_driver.h"
|
||||
|
||||
typedef struct _mmc_cid
|
||||
{
|
||||
u32 manfid;
|
||||
u8 prod_name[8];
|
||||
u8 card_bga;
|
||||
u8 prv;
|
||||
u32 serial;
|
||||
u16 oemid;
|
||||
u16 year;
|
||||
u8 hwrev;
|
||||
u8 fwrev;
|
||||
u8 month;
|
||||
} mmc_cid_t;
|
||||
|
||||
typedef struct _mmc_csd
|
||||
{
|
||||
u8 structure;
|
||||
u8 mmca_vsn;
|
||||
u16 cmdclass;
|
||||
u32 c_size;
|
||||
u32 r2w_factor;
|
||||
u32 max_dtr;
|
||||
u32 erase_size; /* In sectors */
|
||||
u32 read_blkbits;
|
||||
u32 write_blkbits;
|
||||
u32 capacity;
|
||||
} mmc_csd_t;
|
||||
|
||||
typedef struct _mmc_ext_csd
|
||||
{
|
||||
u8 rev;
|
||||
u32 sectors;
|
||||
int bkops; /* background support bit */
|
||||
int bkops_en; /* manual bkops enable bit */
|
||||
u8 ext_struct; /* 194 */
|
||||
u8 card_type; /* 196 */
|
||||
u8 bkops_status; /* 246 */
|
||||
u16 dev_version;
|
||||
u8 boot_mult;
|
||||
u8 rpmb_mult;
|
||||
} mmc_ext_csd_t;
|
||||
|
||||
typedef struct _sd_scr
|
||||
{
|
||||
u8 sda_vsn;
|
||||
u8 sda_spec3;
|
||||
u8 bus_widths;
|
||||
u8 cmds;
|
||||
} sd_scr_t;
|
||||
|
||||
typedef struct _sd_ssr {
|
||||
u8 bus_width;
|
||||
u8 speed_class;
|
||||
u8 uhs_grade;
|
||||
u8 video_class;
|
||||
u8 app_class;
|
||||
} sd_ssr_t;
|
||||
|
||||
/*! SDMMC storage context. */
|
||||
typedef struct _sdmmc_storage_t
|
||||
{
|
||||
@@ -87,15 +29,9 @@ typedef struct _sdmmc_storage_t
|
||||
u32 sec_cnt;
|
||||
int is_low_voltage;
|
||||
u32 partition;
|
||||
u8 raw_cid[0x10];
|
||||
u8 raw_csd[0x10];
|
||||
u8 raw_scr[8];
|
||||
u8 raw_ssr[0x40];
|
||||
mmc_cid_t cid;
|
||||
mmc_csd_t csd;
|
||||
mmc_ext_csd_t ext_csd;
|
||||
sd_scr_t scr;
|
||||
sd_ssr_t ssr;
|
||||
u8 cid[0x10];
|
||||
u8 csd[0x10];
|
||||
u8 scr[8];
|
||||
} sdmmc_storage_t;
|
||||
|
||||
int sdmmc_storage_end(sdmmc_storage_t *storage);
|
||||
|
||||
@@ -304,30 +304,10 @@ static int _sdmmc_cache_rsp(sdmmc_t *sdmmc, u32 *rsp, u32 size, u32 type)
|
||||
case SDMMC_RSP_TYPE_2:
|
||||
if (size < 0x10)
|
||||
return 0;
|
||||
// CRC is stripped, so shifting is needed.
|
||||
u32 tempreg;
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
switch(i)
|
||||
{
|
||||
case 0:
|
||||
tempreg = sdmmc->regs->rspreg3;
|
||||
break;
|
||||
case 1:
|
||||
tempreg = sdmmc->regs->rspreg2;
|
||||
break;
|
||||
case 2:
|
||||
tempreg = sdmmc->regs->rspreg1;
|
||||
break;
|
||||
case 3:
|
||||
tempreg = sdmmc->regs->rspreg0;
|
||||
break;
|
||||
}
|
||||
rsp[i] = tempreg << 8;
|
||||
|
||||
if (i != 0)
|
||||
rsp[i - 1] |= (tempreg >> 24) & 0xFF;
|
||||
}
|
||||
rsp[0] = sdmmc->regs->rspreg0;
|
||||
rsp[1] = sdmmc->regs->rspreg1;
|
||||
rsp[2] = sdmmc->regs->rspreg2;
|
||||
rsp[3] = sdmmc->regs->rspreg3;
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
|
||||
10
ipl/se.c
10
ipl/se.c
@@ -67,7 +67,7 @@ static int _se_wait()
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _se_execute(u32 op, void *dst, u32 dst_size, const void *src, u32 src_size)
|
||||
static int _se_execute(u32 op, void *dst, u32 dst_size, void *src, u32 src_size)
|
||||
{
|
||||
se_ll_t *ll_dst = NULL, *ll_src = NULL;
|
||||
|
||||
@@ -99,7 +99,7 @@ static int _se_execute(u32 op, void *dst, u32 dst_size, const void *src, u32 src
|
||||
return res;
|
||||
}
|
||||
|
||||
static int _se_execute_one_block(u32 op, void *dst, u32 dst_size, const void *src, u32 src_size)
|
||||
static int _se_execute_one_block(u32 op, void *dst, u32 dst_size, void *src, u32 src_size)
|
||||
{
|
||||
u8 *block = (u8 *)malloc(0x10);
|
||||
memset(block, 0, 0x10);
|
||||
@@ -156,7 +156,7 @@ void se_aes_key_clear(u32 ks)
|
||||
}
|
||||
}
|
||||
|
||||
int se_aes_unwrap_key(u32 ks_dst, u32 ks_src, const void *input)
|
||||
int se_aes_unwrap_key(u32 ks_dst, u32 ks_src, 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);
|
||||
@@ -164,7 +164,7 @@ int se_aes_unwrap_key(u32 ks_dst, u32 ks_src, const void *input)
|
||||
return _se_execute(OP_START, NULL, 0, input, 0x10);
|
||||
}
|
||||
|
||||
int se_aes_crypt_block_ecb(u32 ks, u32 enc, void *dst, const void *src)
|
||||
int se_aes_crypt_block_ecb(u32 ks, u32 enc, void *dst, void *src)
|
||||
{
|
||||
if (enc)
|
||||
{
|
||||
@@ -180,7 +180,7 @@ int se_aes_crypt_block_ecb(u32 ks, u32 enc, void *dst, const void *src)
|
||||
return _se_execute(OP_START, dst, 0x10, src, 0x10);
|
||||
}
|
||||
|
||||
int se_aes_crypt_ctr(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_size, void *ctr)
|
||||
int se_aes_crypt_ctr(u32 ks, void *dst, u32 dst_size, 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);
|
||||
|
||||
7
ipl/se.h
7
ipl/se.h
@@ -23,7 +23,8 @@ void se_rsa_acc_ctrl(u32 rs, u32 flags);
|
||||
void se_key_acc_ctrl(u32 ks, u32 flags);
|
||||
void se_aes_key_set(u32 ks, void *key, u32 size);
|
||||
void se_aes_key_clear(u32 ks);
|
||||
int se_aes_unwrap_key(u32 ks_dst, u32 ks_src, const void *input);
|
||||
int se_aes_crypt_block_ecb(u32 ks, u32 enc, void *dst, const void *src);
|
||||
int se_aes_crypt_ctr(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_size, void *ctr);
|
||||
int se_aes_unwrap_key(u32 ks_dst, u32 ks_src, void *input);
|
||||
int se_aes_crypt_block_ecb(u32 ks, u32 enc, void *dst, void *src);
|
||||
int se_aes_crypt_ctr(u32 ks, void *dst, u32 dst_size, void *src, u32 src_size, void *ctr);
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user