Initial commit

This commit is contained in:
shchmue 2019-03-04 18:05:42 -05:00
commit 641476a75e
95 changed files with 28756 additions and 0 deletions

61
source/hos/pkg1.c Normal file
View file

@ -0,0 +1,61 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018 st4rk
* Copyright (c) 2018-2019 CTCaer
* Copyright (c) 2018 balika011
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <string.h>
#include "pkg1.h"
#include "../sec/se.h"
#define SM_100_ADR 0x4002B020
/*
* package1.1 header: <wb, ldr, sm>
* package1.1 layout:
* 1.0: {sm, ldr, wb} { 2, 1, 0 }
* 2.0: {wb, ldr, sm} { 0, 1, 2 }
* 3.0: {wb, ldr, sm} { 0, 1, 2 }
* 3.1: {wb, ldr, sm} { 0, 1, 2 }
* 4.0: {ldr, sm, wb} { 1, 2, 0 }
* 5.0: {ldr, sm, wb} { 1, 2, 0 }
* 6.0: {ldr, sm, wb} { 1, 2, 0 }
* 6.2: {ldr, sm, wb} { 1, 2, 0 }
* 7.0: {ldr, sm, wb} { 1, 2, 0 }
*/
static const pkg1_id_t _pkg1_ids[] = {
{ "20161121183008", 0, 0x1900, 0x3FE0, { 2, 1, 0 }, SM_100_ADR, 0x8000D000, true, NULL, NULL }, //1.0.0 (Patched relocator)
{ "20170210155124", 0, 0x1900, 0x3FE0, { 0, 1, 2 }, 0x4002D000, 0x8000D000, true, NULL, NULL }, //2.0.0 - 2.3.0
{ "20170519101410", 1, 0x1A00, 0x3FE0, { 0, 1, 2 }, 0x4002D000, 0x8000D000, true, NULL, NULL }, //3.0.0
{ "20170710161758", 2, 0x1A00, 0x3FE0, { 0, 1, 2 }, 0x4002D000, 0x8000D000, true, NULL, NULL }, //3.0.1 - 3.0.2
{ "20170921172629", 3, 0x1800, 0x3FE0, { 1, 2, 0 }, 0x4002B000, 0x4003B000, false, NULL, NULL }, //4.0.0 - 4.1.0
{ "20180220163747", 4, 0x1900, 0x3FE0, { 1, 2, 0 }, 0x4002B000, 0x4003B000, false, NULL, NULL }, //5.0.0 - 5.1.0
{ "20180802162753", 5, 0x1900, 0x3FE0, { 1, 2, 0 }, 0x4002B000, 0x4003D800, false, NULL, NULL }, //6.0.0 - 6.1.0
{ "20181107105733", 6, 0x0E00, 0x6FE0, { 1, 2, 0 }, 0x4002B000, 0x4003D800, false, NULL, NULL }, //6.2.0
{ "20181218175730", 7, 0x0F00, 0x6FE0, { 1, 2, 0 }, 0x40030000, 0x4003E000, false, NULL, NULL }, //7.0.0
{ "20190208150037", 7, 0x0F00, 0x6FE0, { 1, 2, 0 }, 0x40030000, 0x4003E000, false, NULL, NULL }, //7.0.1
{ NULL } //End.
};
const pkg1_id_t *pkg1_identify(u8 *pkg1)
{
for (u32 i = 0; _pkg1_ids[i].id; i++)
if (!memcmp(pkg1 + 0x10, _pkg1_ids[i].id, 12))
return &_pkg1_ids[i];
return NULL;
}

38
source/hos/pkg1.h Normal file
View file

@ -0,0 +1,38 @@
/*
* 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/>.
*/
#ifndef _PKG1_H_
#define _PKG1_H_
#include "../utils/types.h"
typedef struct _pkg1_id_t
{
const char *id;
u32 kb;
u32 tsec_off;
u32 pkg11_off;
u32 sec_map[3];
u32 secmon_base;
u32 warmboot_base;
bool set_warmboot;
u32 *secmon_patchset;
u32 *warmboot_patchset;
} pkg1_id_t;
const pkg1_id_t *pkg1_identify(u8 *pkg1);
#endif

168
source/hos/pkg2.c Normal file
View file

@ -0,0 +1,168 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2019 CTCaer
* Copyright (c) 2018 Atmosphère-NX
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <string.h>
#include "pkg2.h"
#include "../utils/aarch64_util.h"
#include "../mem/heap.h"
#include "../sec/se.h"
#include "../libs/compr/blz.h"
#include "../gfx/gfx.h"
#pragma GCC push_options
#pragma GCC optimize ("Os")
extern gfx_con_t gfx_con;
/*#include "util.h"
#define DPRINTF(...) gfx_printf(&gfx_con, __VA_ARGS__)
#define DEBUG_PRINTING*/
#define DPRINTF(...)
static u32 _pkg2_calc_kip1_size(pkg2_kip1_t *kip1)
{
u32 size = sizeof(pkg2_kip1_t);
for (u32 j = 0; j < KIP1_NUM_SECTIONS; j++)
size += kip1->sections[j].size_comp;
return size;
}
void pkg2_parse_kips(link_t *info, pkg2_hdr_t *pkg2)
{
u8 *ptr = pkg2->data + pkg2->sec_size[PKG2_SEC_KERNEL];
pkg2_ini1_t *ini1 = (pkg2_ini1_t *)ptr;
ptr += sizeof(pkg2_ini1_t);
for (u32 i = 0; i < ini1->num_procs; i++)
{
pkg2_kip1_t *kip1 = (pkg2_kip1_t *)ptr;
pkg2_kip1_info_t *ki = (pkg2_kip1_info_t *)malloc(sizeof(pkg2_kip1_info_t));
ki->kip1 = kip1;
ki->size = _pkg2_calc_kip1_size(kip1);
list_append(info, &ki->link);
ptr += ki->size;
DPRINTF(" kip1 %d:%s @ %08X (%08X)\n", i, kip1->name, (u32)kip1, ki->size);
}
}
int pkg2_decompress_kip(pkg2_kip1_info_t* ki, u32 sectsToDecomp)
{
u32 compClearMask = ~sectsToDecomp;
if ((ki->kip1->flags & compClearMask) == ki->kip1->flags)
return 0; // Already decompressed, nothing to do.
pkg2_kip1_t hdr;
memcpy(&hdr, ki->kip1, sizeof(hdr));
unsigned int newKipSize = sizeof(hdr);
for (u32 sectIdx = 0; sectIdx < KIP1_NUM_SECTIONS; sectIdx++)
{
u32 sectCompBit = 1u << sectIdx;
// For compressed, cant get actual decompressed size without doing it, so use safe "output size".
if (sectIdx < 3 && (sectsToDecomp & sectCompBit) && (hdr.flags & sectCompBit))
newKipSize += hdr.sections[sectIdx].size_decomp;
else
newKipSize += hdr.sections[sectIdx].size_comp;
}
pkg2_kip1_t* newKip = malloc(newKipSize);
unsigned char* dstDataPtr = newKip->data;
const unsigned char* srcDataPtr = ki->kip1->data;
for (u32 sectIdx = 0; sectIdx < KIP1_NUM_SECTIONS; sectIdx++)
{
u32 sectCompBit = 1u << sectIdx;
// Easy copy path for uncompressed or ones we dont want to uncompress.
if (sectIdx >= 3 || !(sectsToDecomp & sectCompBit) || !(hdr.flags & sectCompBit))
{
unsigned int dataSize = hdr.sections[sectIdx].size_comp;
if (dataSize == 0)
continue;
memcpy(dstDataPtr, srcDataPtr, dataSize);
srcDataPtr += dataSize;
dstDataPtr += dataSize;
continue;
}
unsigned int compSize = hdr.sections[sectIdx].size_comp;
unsigned int outputSize = hdr.sections[sectIdx].size_decomp;
//gfx_printf(&gfx_con, "Decomping %s KIP1 sect %d of size %d...\n", (const char*)hdr.name, sectIdx, compSize);
if (blz_uncompress_srcdest(srcDataPtr, compSize, dstDataPtr, outputSize) == 0)
{
gfx_printf(&gfx_con, "%kERROR decomping sect %d of %s KIP!%k\n", 0xFFFF0000, sectIdx, (char*)hdr.name, 0xFFCCCCCC);
free(newKip);
return 1;
}
else
{
DPRINTF("Done! Decompressed size is %d!\n", outputSize);
}
hdr.sections[sectIdx].size_comp = outputSize;
srcDataPtr += compSize;
dstDataPtr += outputSize;
}
hdr.flags &= compClearMask;
memcpy(newKip, &hdr, sizeof(hdr));
newKipSize = dstDataPtr-(unsigned char*)(newKip);
free(ki->kip1);
ki->kip1 = newKip;
ki->size = newKipSize;
return 0;
}
pkg2_hdr_t *pkg2_decrypt(void *data)
{
u8 *pdata = (u8 *)data;
// Skip signature.
pdata += 0x100;
pkg2_hdr_t *hdr = (pkg2_hdr_t *)pdata;
// Skip header.
pdata += sizeof(pkg2_hdr_t);
// Decrypt header.
se_aes_crypt_ctr(8, hdr, sizeof(pkg2_hdr_t), hdr, sizeof(pkg2_hdr_t), hdr);
//gfx_hexdump(&gfx_con, (u32)hdr, hdr, 0x100);
if (hdr->magic != PKG2_MAGIC)
return NULL;
for (u32 i = 0; i < 4; i++)
{
DPRINTF("sec %d has size %08X\n", i, hdr->sec_size[i]);
if (!hdr->sec_size[i])
continue;
se_aes_crypt_ctr(8, pdata, hdr->sec_size[i], pdata, hdr->sec_size[i], &hdr->sec_ctr[i * 0x10]);
//gfx_hexdump(&gfx_con, (u32)pdata, pdata, 0x100);
pdata += hdr->sec_size[i];
}
return hdr;
}
#pragma GCC pop_options

102
source/hos/pkg2.h Normal file
View file

@ -0,0 +1,102 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (C) 2018 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 _PKG2_H_
#define _PKG2_H_
#include "../utils/types.h"
#include "../utils/list.h"
#define PKG2_MAGIC 0x31324B50
#define PKG2_SEC_BASE 0x80000000
#define PKG2_SEC_KERNEL 0
#define PKG2_SEC_INI1 1
#define INI1_MAGIC 0x31494E49
enum
{
// Always applied.
SVC_GENERIC = 0,
// Generic instruction patches.
SVC_VERIFY_DS = 0x10,
DEBUG_MODE_EN,
ATM_GEN_PATCH,
// >4 bytes patches. Value is a pointer of a u32 array.
ATM_ARR_PATCH,
};
typedef struct _pkg2_hdr_t
{
u8 ctr[0x10];
u8 sec_ctr[0x40];
u32 magic;
u32 base;
u32 pad0;
u16 version;
u16 pad1;
u32 sec_size[4];
u32 sec_off[4];
u8 sec_sha256[0x80];
u8 data[];
} pkg2_hdr_t;
typedef struct _pkg2_ini1_t
{
u32 magic;
u32 size;
u32 num_procs;
u32 pad;
} pkg2_ini1_t;
typedef struct _pkg2_kip1_sec_t
{
u32 offset;
u32 size_decomp;
u32 size_comp;
u32 attrib;
} pkg2_kip1_sec_t;
#define KIP1_NUM_SECTIONS 6
typedef struct _pkg2_kip1_t
{
u32 magic;
u8 name[12];
u64 tid;
u32 proc_cat;
u8 main_thrd_prio;
u8 def_cpu_core;
u8 res;
u8 flags;
pkg2_kip1_sec_t sections[KIP1_NUM_SECTIONS];
u32 caps[0x20];
u8 data[];
} pkg2_kip1_t;
typedef struct _pkg2_kip1_info_t
{
pkg2_kip1_t *kip1;
u32 size;
link_t link;
} pkg2_kip1_info_t;
void pkg2_parse_kips(link_t *info, pkg2_hdr_t *pkg2);
int pkg2_decompress_kip(pkg2_kip1_info_t* ki, u32 sectsToDecomp);
pkg2_hdr_t *pkg2_decrypt(void *data);
#endif

140
source/hos/sept.c Normal file
View file

@ -0,0 +1,140 @@
/*
* Copyright (c) 2019 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <string.h>
#include "sept.h"
#include "../gfx/di.h"
#include "../libs/fatfs/ff.h"
#include "../mem/heap.h"
#include "../soc/pmc.h"
#include "../soc/t210.h"
#include "../storage/nx_emmc.h"
#include "../storage/sdmmc.h"
#include "../utils/btn.h"
#include "../utils/types.h"
#include "../gfx/gfx.h"
extern gfx_con_t gfx_con;
#define EPRINTF(text) gfx_printf(&gfx_con, "%k"text"%k\n", 0xFFFF0000, 0xFFCCCCCC)
#define EPRINTFARGS(text, args...) gfx_printf(&gfx_con, "%k"text"%k\n", 0xFFFF0000, args, 0xFFCCCCCC)
#define PATCHED_RELOC_SZ 0x94
#define WB_RST_ADDR 0x40010ED0
#define WB_RST_SIZE 0x30
u8 warmboot_reboot[] = {
0x14, 0x00, 0x9F, 0xE5, // LDR R0, =0x7000E450
0x01, 0x10, 0xB0, 0xE3, // MOVS R1, #1
0x00, 0x10, 0x80, 0xE5, // STR R1, [R0]
0x0C, 0x00, 0x9F, 0xE5, // LDR R0, =0x7000E400
0x10, 0x10, 0xB0, 0xE3, // MOVS R1, #0x10
0x00, 0x10, 0x80, 0xE5, // STR R1, [R0]
0xFE, 0xFF, 0xFF, 0xEA, // LOOP
0x50, 0xE4, 0x00, 0x70, // #0x7000E450
0x00, 0xE4, 0x00, 0x70 // #0x7000E400
};
#define SEPT_PRI_ADDR 0x4003F000
#define SEPT_PK1T_ADDR 0xC0400000
#define SEPT_PK1T_STACK 0x40008000
#define SEPT_TCSZ_ADDR (SEPT_PK1T_ADDR - 0x4)
#define SEPT_STG1_ADDR (SEPT_PK1T_ADDR + 0x2E100)
#define SEPT_STG2_ADDR (SEPT_PK1T_ADDR + 0x60E0)
#define SEPT_PKG_SZ (0x2F100 + WB_RST_SIZE)
extern boot_cfg_t *b_cfg;
extern void sd_unmount();
extern void reloc_patcher(u32 payload_dst, u32 payload_src, u32 payload_size);
int reboot_to_sept(const u8 *tsec_fw)
{
FIL fp;
// Copy warmboot reboot code and TSEC fw.
memcpy((u8 *)(SEPT_PK1T_ADDR - WB_RST_SIZE), (u8 *)warmboot_reboot, sizeof(warmboot_reboot));
memcpy((void *)SEPT_PK1T_ADDR, tsec_fw, 0x3000);
*(vu32 *)SEPT_TCSZ_ADDR = 0x3000;
// Copy sept-primary.
if (f_open(&fp, "sd:/sept/sept-primary.bin", FA_READ))
goto error;
if (f_read(&fp, (u8 *)SEPT_STG1_ADDR, f_size(&fp), NULL))
{
f_close(&fp);
goto error;
}
f_close(&fp);
// Copy sept-secondary.
if (f_open(&fp, "sd:/sept/sept-secondary.enc", FA_READ))
goto error;
if (f_read(&fp, (u8 *)SEPT_STG2_ADDR, f_size(&fp), NULL))
{
f_close(&fp);
goto error;
}
f_close(&fp);
// Save auto boot config to payload, if any.
boot_cfg_t *tmp_cfg = malloc(sizeof(boot_cfg_t));
memcpy(tmp_cfg, b_cfg, sizeof(boot_cfg_t));
tmp_cfg->boot_cfg |= BOOT_CFG_SEPT_RUN;
if (f_open(&fp, "sd:/sept/payload.bin", FA_READ | FA_WRITE))
goto error;
f_lseek(&fp, PATCHED_RELOC_SZ);
f_write(&fp, tmp_cfg, sizeof(boot_cfg_t), NULL);
f_close(&fp);
sd_unmount();
gfx_printf(&gfx_con, "\n%kPress Power or Vol +/-\n%k to Reboot to Sept...", COLOR_BLUE, COLOR_VIOLET);
btn_wait();
u32 pk1t_sept = SEPT_PK1T_ADDR - (ALIGN(PATCHED_RELOC_SZ, 0x10) + WB_RST_SIZE);
void (*sept)() = (void *)pk1t_sept;
reloc_patcher(WB_RST_ADDR, pk1t_sept, SEPT_PKG_SZ);
// Patch SDRAM init to perform an SVC immediately after second write.
PMC(APBDEV_PMC_SCRATCH45) = 0x2E38DFFF;
PMC(APBDEV_PMC_SCRATCH46) = 0x6001DC28;
// Set SVC handler to jump to sept-primary in IRAM.
PMC(APBDEV_PMC_SCRATCH33) = SEPT_PRI_ADDR;
PMC(APBDEV_PMC_SCRATCH40) = 0x6000F208;
display_end();
(*sept)();
return 1;
error:
EPRINTF("Sept payloads not found in sd:/sept!\nPlace appropriate files and try again.");
display_backlight_brightness(100, 1000);
btn_wait();
return 0;
}

24
source/hos/sept.h Normal file
View file

@ -0,0 +1,24 @@
/*
* Copyright (c) 2019 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 _SEPT_H_
#define _SEPT_H_
#include "../utils/types.h"
int reboot_to_sept(const u8 *tsec_fw);
#endif