Compare commits
10 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7af531de77 | ||
|
|
a77783b922 | ||
|
|
33457ad8f8 | ||
|
|
828b616468 | ||
|
|
2f120d1cbb | ||
|
|
a5f2bb9d57 | ||
|
|
60905c3829 | ||
|
|
19e9292128 | ||
|
|
6d556bf213 | ||
|
|
f91546a1e5 |
@@ -1,10 +1,12 @@
|
||||
# hekate - Bootlogo
|
||||
|
||||
The bootlogo can be any size with a maximum of 720 x 1280. It is automatically centered when it's smaller than 720 x 1280.
|
||||
The bootlogo can be any size with a maximum of 720 x 1280.
|
||||
|
||||
When saving a landscape bootlogo, it should be rotated 90o counterclockwise.
|
||||
When it's smaller than 720 x 1280, it is automatically centered and the background takes the color of the first pixel.
|
||||
|
||||
Lastly, the supported format is 32-bit BMP. Classic 24-bit BMPs are not supported for performance reasons.
|
||||
When saving a landscape bootlogo, it should be rotated 90 degrees counterclockwise.
|
||||
|
||||
Lastly, the supported format is 32-bit (ARGB) BMP. Classic 24-bit (RGB) BMPs are not supported for performance reasons.
|
||||
|
||||
|
||||
## How to configure
|
||||
|
||||
10
ipl/config.c
10
ipl/config.c
@@ -42,6 +42,8 @@ void set_default_configuration()
|
||||
h_cfg.bootwait = 3;
|
||||
h_cfg.customlogo = 0;
|
||||
h_cfg.verification = 2;
|
||||
h_cfg.se_keygen_done = 0;
|
||||
h_cfg.sbar_time_keeping = 0;
|
||||
}
|
||||
|
||||
int create_config_entry()
|
||||
@@ -272,7 +274,7 @@ void config_bootdelay()
|
||||
else
|
||||
delay_text[i * 32] = '*';
|
||||
delay_text[i * 32 + 1] = i + '0';
|
||||
memcpy(delay_text + i * 32 + 2, " seconds\0", 9);
|
||||
memcpy(delay_text + i * 32 + 2, " seconds", 9);
|
||||
|
||||
ments[i + 2].type = MENT_CHOICE;
|
||||
ments[i + 2].caption = delay_text + i * 32;
|
||||
@@ -389,9 +391,9 @@ void config_verification()
|
||||
|
||||
ments[1].type = MENT_CHGLINE;
|
||||
|
||||
memcpy(vr_text, " Disable\0", 9);
|
||||
memcpy(vr_text + 64, " Sparse (Fast - Not reliable)\0", 31);
|
||||
memcpy(vr_text + 128, " Full (Slow - 100% reliable)\0", 31);
|
||||
memcpy(vr_text, " Disable", 9);
|
||||
memcpy(vr_text + 64, " Sparse (Fast - Not reliable)", 31);
|
||||
memcpy(vr_text + 128, " Full (Slow - 100% reliable)", 31);
|
||||
|
||||
for (u32 i = 0; i < 3; i++)
|
||||
{
|
||||
|
||||
@@ -25,6 +25,9 @@ typedef struct _hekate_config
|
||||
u32 bootwait;
|
||||
u32 customlogo;
|
||||
u32 verification;
|
||||
// Global temporary config.
|
||||
int se_keygen_done;
|
||||
u32 sbar_time_keeping;
|
||||
}hekate_config;
|
||||
|
||||
void set_default_configuration();
|
||||
|
||||
86
ipl/ff.c
86
ipl/ff.c
@@ -3290,11 +3290,11 @@ static FRESULT find_volume ( /* FR_OK(0): successful, !=0: an error occurred */
|
||||
} while (LD2PT(vol) == 0 && fmt >= 2 && ++i < 4);
|
||||
}
|
||||
if (fmt == 4) {
|
||||
EFSPRINTF("Disk I/O error - Could not load boot record!");
|
||||
EFSPRINTF("Could not load boot record!");
|
||||
return FR_DISK_ERR; /* An error occured in the disk I/O layer */
|
||||
}
|
||||
if (fmt >= 2) {
|
||||
EFSPRINTF("No FAT/FAT32/exFAT filesystem found!");
|
||||
EFSPRINTF("No FAT/FAT32/exFAT found!");
|
||||
return FR_NO_FILESYSTEM; /* No FAT volume is found */
|
||||
}
|
||||
|
||||
@@ -3305,26 +3305,20 @@ static FRESULT find_volume ( /* FR_OK(0): successful, !=0: an error occurred */
|
||||
QWORD maxlba;
|
||||
|
||||
for (i = BPB_ZeroedEx; i < BPB_ZeroedEx + 53 && fs->win[i] == 0; i++) ; /* Check zero filler */
|
||||
if (i < BPB_ZeroedEx + 53) {
|
||||
EFSPRINTF("exFAT - Zero filler check failed!");
|
||||
if (i < BPB_ZeroedEx + 53)
|
||||
return FR_NO_FILESYSTEM;
|
||||
}
|
||||
|
||||
if (ld_word(fs->win + BPB_FSVerEx) != 0x100) {
|
||||
EFSPRINTF("exFAT - Version check failed!");
|
||||
if (ld_word(fs->win + BPB_FSVerEx) != 0x100)
|
||||
return FR_NO_FILESYSTEM; /* Check exFAT version (must be version 1.0) */
|
||||
}
|
||||
|
||||
if (1 << fs->win[BPB_BytsPerSecEx] != SS(fs)) { /* (BPB_BytsPerSecEx must be equal to the physical sector size) */
|
||||
EFSPRINTF("exFAT - Bytes per sector does not match physical sector size!");
|
||||
EFSPRINTF("exFAT - Sector size does not match physical sector size!");
|
||||
return FR_NO_FILESYSTEM;
|
||||
}
|
||||
|
||||
maxlba = ld_qword(fs->win + BPB_TotSecEx) + bsect; /* Last LBA + 1 of the volume */
|
||||
if (maxlba >= 0x100000000) {
|
||||
EFSPRINTF("exFAT - Cannot handle volume LBA with 32-bit LBA!");
|
||||
if (maxlba >= 0x100000000)
|
||||
return FR_NO_FILESYSTEM; /* (It cannot be handled in 32-bit LBA) */
|
||||
}
|
||||
|
||||
fs->fsize = ld_dword(fs->win + BPB_FatSzEx); /* Number of sectors per FAT */
|
||||
|
||||
@@ -3336,30 +3330,26 @@ static FRESULT find_volume ( /* FR_OK(0): successful, !=0: an error occurred */
|
||||
|
||||
fs->csize = 1 << fs->win[BPB_SecPerClusEx]; /* Cluster size */
|
||||
if (fs->csize == 0) {
|
||||
EFSPRINTF("exFAT - Cluster size is not between 1KB - 32KB!");
|
||||
EFSPRINTF("exFAT - Sectors per clusters!");
|
||||
return FR_NO_FILESYSTEM; /* (Must be 1..32768) */
|
||||
}
|
||||
|
||||
nclst = ld_dword(fs->win + BPB_NumClusEx); /* Number of clusters */
|
||||
if (nclst > MAX_EXFAT) {
|
||||
EFSPRINTF("exFAT - Total clusters exceed allowed!");
|
||||
if (nclst > MAX_EXFAT)
|
||||
return FR_NO_FILESYSTEM; /* (Too many clusters) */
|
||||
}
|
||||
fs->n_fatent = nclst + 2;
|
||||
|
||||
/* Boundaries and Limits */
|
||||
fs->volbase = bsect;
|
||||
fs->database = bsect + ld_dword(fs->win + BPB_DataOfsEx);
|
||||
fs->fatbase = bsect + ld_dword(fs->win + BPB_FatOfsEx);
|
||||
if (maxlba < (QWORD)fs->database + nclst * fs->csize) {
|
||||
EFSPRINTF("exFAT - Volume size is lower than required!");
|
||||
if (maxlba < (QWORD)fs->database + nclst * fs->csize)
|
||||
return FR_NO_FILESYSTEM; /* (Volume size must not be smaller than the size required) */
|
||||
}
|
||||
fs->dirbase = ld_dword(fs->win + BPB_RootClusEx);
|
||||
|
||||
/* Check if bitmap location is in assumption (at the first cluster) */
|
||||
if (move_window(fs, clst2sect(fs, fs->dirbase)) != FR_OK) {
|
||||
EFSPRINTF("exFAT - Bitmap location not at first cluster!");
|
||||
EFSPRINTF("exFAT - Bitmap location not at 1st cluster!");
|
||||
return FR_DISK_ERR;
|
||||
}
|
||||
for (i = 0; i < SS(fs); i += SZDIRE) {
|
||||
@@ -3377,7 +3367,7 @@ static FRESULT find_volume ( /* FR_OK(0): successful, !=0: an error occurred */
|
||||
#endif /* FF_FS_EXFAT */
|
||||
{
|
||||
if (ld_word(fs->win + BPB_BytsPerSec) != SS(fs)) {
|
||||
EFSPRINTF("FAT - Bytes per sector does not match physical sector size!");
|
||||
EFSPRINTF("FAT - Sector size does not match physical sector size!");
|
||||
return FR_NO_FILESYSTEM; /* (BPB_BytsPerSec must be equal to the physical sector size) */
|
||||
}
|
||||
|
||||
@@ -3386,52 +3376,38 @@ static FRESULT find_volume ( /* FR_OK(0): successful, !=0: an error occurred */
|
||||
fs->fsize = fasize;
|
||||
|
||||
fs->n_fats = fs->win[BPB_NumFATs]; /* Number of FATs */
|
||||
if (fs->n_fats != 1 && fs->n_fats != 2) {
|
||||
EFSPRINTF("FAT - No or more than 2 file allocation tables found!");
|
||||
if (fs->n_fats != 1 && fs->n_fats != 2)
|
||||
return FR_NO_FILESYSTEM; /* (Must be 1 or 2) */
|
||||
}
|
||||
fasize *= fs->n_fats; /* Number of sectors for FAT area */
|
||||
|
||||
fs->csize = fs->win[BPB_SecPerClus]; /* Cluster size */
|
||||
if (fs->csize == 0 || (fs->csize & (fs->csize - 1))) {
|
||||
EFSPRINTF("FAT - Cluster size is not a power of 2!");
|
||||
if (fs->csize == 0 || (fs->csize & (fs->csize - 1)))
|
||||
return FR_NO_FILESYSTEM; /* (Must be power of 2) */
|
||||
}
|
||||
|
||||
fs->n_rootdir = ld_word(fs->win + BPB_RootEntCnt); /* Number of root directory entries */
|
||||
if (fs->n_rootdir % (SS(fs) / SZDIRE)) {
|
||||
EFSPRINTF("FAT - Root directory entries are not sector aligned!");
|
||||
if (fs->n_rootdir % (SS(fs) / SZDIRE))
|
||||
return FR_NO_FILESYSTEM; /* (Must be sector aligned) */
|
||||
}
|
||||
|
||||
tsect = ld_word(fs->win + BPB_TotSec16); /* Number of sectors on the volume */
|
||||
if (tsect == 0) tsect = ld_dword(fs->win + BPB_TotSec32);
|
||||
|
||||
nrsv = ld_word(fs->win + BPB_RsvdSecCnt); /* Number of reserved sectors */
|
||||
if (nrsv == 0) {
|
||||
EFSPRINTF("FAT - Zero reserved sectors!");
|
||||
if (nrsv == 0)
|
||||
return FR_NO_FILESYSTEM; /* (Must not be 0) */
|
||||
}
|
||||
|
||||
/* Determine the FAT sub type */
|
||||
sysect = nrsv + fasize + fs->n_rootdir / (SS(fs) / SZDIRE); /* RSV + FAT + DIR */
|
||||
if (tsect < sysect) {
|
||||
EFSPRINTF("FAT - Invalid volume size!");
|
||||
if (tsect < sysect)
|
||||
return FR_NO_FILESYSTEM; /* (Invalid volume size) */
|
||||
}
|
||||
nclst = (tsect - sysect) / fs->csize; /* Number of clusters */
|
||||
if (nclst == 0) {
|
||||
EFSPRINTF("FAT - Invalid volume size!");
|
||||
if (nclst == 0)
|
||||
return FR_NO_FILESYSTEM; /* (Invalid volume size) */
|
||||
}
|
||||
fmt = 0;
|
||||
if (nclst <= MAX_FAT32) fmt = FS_FAT32;
|
||||
if (nclst <= MAX_FAT16) fmt = FS_FAT16;
|
||||
if (nclst <= MAX_FAT12) fmt = FS_FAT12;
|
||||
if (fmt == 0) {
|
||||
EFSPRINTF("FAT - Not compatible FAT12/16/32 filesystem!");
|
||||
if (fmt == 0)
|
||||
return FR_NO_FILESYSTEM;
|
||||
}
|
||||
|
||||
/* Boundaries and Limits */
|
||||
fs->n_fatent = nclst + 2; /* Number of FAT entries */
|
||||
@@ -3439,29 +3415,21 @@ static FRESULT find_volume ( /* FR_OK(0): successful, !=0: an error occurred */
|
||||
fs->fatbase = bsect + nrsv; /* FAT start sector */
|
||||
fs->database = bsect + sysect; /* Data start sector */
|
||||
if (fmt == FS_FAT32) {
|
||||
if (ld_word(fs->win + BPB_FSVer32) != 0) {
|
||||
EFSPRINTF("FAT32 - Not a 0.0 revision!");
|
||||
if (ld_word(fs->win + BPB_FSVer32) != 0)
|
||||
return FR_NO_FILESYSTEM; /* (Must be FAT32 revision 0.0) */
|
||||
}
|
||||
if (fs->n_rootdir != 0) {
|
||||
EFSPRINTF("FAT32 - Root entry sector is not 0!");
|
||||
if (fs->n_rootdir != 0)
|
||||
return FR_NO_FILESYSTEM; /* (BPB_RootEntCnt must be 0) */
|
||||
}
|
||||
fs->dirbase = ld_dword(fs->win + BPB_RootClus32); /* Root directory start cluster */
|
||||
szbfat = fs->n_fatent * 4; /* (Needed FAT size) */
|
||||
} else {
|
||||
if (fs->n_rootdir == 0) {
|
||||
EFSPRINTF("FAT - Root entry sector is 0!");
|
||||
if (fs->n_rootdir == 0)
|
||||
return FR_NO_FILESYSTEM; /* (BPB_RootEntCnt must not be 0) */
|
||||
}
|
||||
fs->dirbase = fs->fatbase + fasize; /* Root directory start sector */
|
||||
szbfat = (fmt == FS_FAT16) ? /* (Needed FAT size) */
|
||||
fs->n_fatent * 2 : fs->n_fatent * 3 / 2 + (fs->n_fatent & 1);
|
||||
}
|
||||
if (fs->fsize < (szbfat + (SS(fs) - 1)) / SS(fs)) {
|
||||
EFSPRINTF("FAT - FAT size is not the required size!");
|
||||
if (fs->fsize < (szbfat + (SS(fs) - 1)) / SS(fs))
|
||||
return FR_NO_FILESYSTEM; /* (BPB_FATSz must not be less than the size needed) */
|
||||
}
|
||||
|
||||
#if !FF_FS_READONLY
|
||||
/* Get FSInfo if available */
|
||||
@@ -3894,7 +3862,7 @@ FRESULT f_read (
|
||||
}
|
||||
#endif
|
||||
if (disk_read(fs->pdrv, fp->buf, sect, 1) != RES_OK) {
|
||||
EFSPRINTF("Read - Low level disk I/O!\n(fill sector cache)");
|
||||
EFSPRINTF("Read - Fill sector cache");
|
||||
ABORT(fs, FR_DISK_ERR); /* Fill sector cache */
|
||||
}
|
||||
}
|
||||
@@ -3991,10 +3959,8 @@ FRESULT f_write (
|
||||
if (fs->winsect == fp->sect && sync_window(fs) != FR_OK) ABORT(fs, FR_DISK_ERR); /* Write-back sector cache */
|
||||
#else
|
||||
if (fp->flag & FA_DIRTY) { /* Write-back sector cache */
|
||||
if (disk_write(fs->pdrv, fp->buf, fp->sect, 1) != RES_OK) {
|
||||
EFSPRINTF("Write-back sector cache!");
|
||||
if (disk_write(fs->pdrv, fp->buf, fp->sect, 1) != RES_OK)
|
||||
ABORT(fs, FR_DISK_ERR);
|
||||
}
|
||||
fp->flag &= (BYTE)~FA_DIRTY;
|
||||
}
|
||||
#endif
|
||||
@@ -4037,10 +4003,8 @@ FRESULT f_write (
|
||||
#else
|
||||
if (fp->sect != sect && /* Fill sector cache with file data */
|
||||
fp->fptr < fp->obj.objsize &&
|
||||
disk_read(fs->pdrv, fp->buf, sect, 1) != RES_OK) {
|
||||
EFSPRINTF("Read - Low level disk I/O!\n(Could not fill sector cache with file data)");
|
||||
disk_read(fs->pdrv, fp->buf, sect, 1) != RES_OK)
|
||||
ABORT(fs, FR_DISK_ERR);
|
||||
}
|
||||
#endif
|
||||
fp->sect = sect;
|
||||
}
|
||||
|
||||
@@ -136,6 +136,11 @@ void gfx_clear_color(gfx_ctxt_t *ctxt, u32 color)
|
||||
ctxt->fb[i] = color;
|
||||
}
|
||||
|
||||
void gfx_clear_partial_grey(gfx_ctxt_t *ctxt, u8 color, u32 pos_x, u32 height)
|
||||
{
|
||||
memset(ctxt->fb + pos_x * ctxt->stride , color, height * 4 * ctxt->stride);
|
||||
}
|
||||
|
||||
void gfx_con_init(gfx_con_t *con, gfx_ctxt_t *ctxt)
|
||||
{
|
||||
con->gfx_ctxt = ctxt;
|
||||
@@ -360,7 +365,7 @@ void gfx_printf(gfx_con_t *con, const char *fmt, ...)
|
||||
break;
|
||||
case 'K':
|
||||
con->bgcol = va_arg(ap, u32);
|
||||
con->fillbg = fcnt;
|
||||
con->fillbg = 1;
|
||||
break;
|
||||
case '%':
|
||||
gfx_putc(con, '%');
|
||||
|
||||
@@ -44,6 +44,7 @@ typedef struct _gfx_con_t
|
||||
|
||||
void gfx_init_ctxt(gfx_ctxt_t *ctxt, u32 *fb, u32 width, u32 height, u32 stride);
|
||||
void gfx_clear_grey(gfx_ctxt_t *ctxt, u8 color);
|
||||
void gfx_clear_partial_grey(gfx_ctxt_t *ctxt, u8 color, u32 pos_x, u32 height);
|
||||
void gfx_clear_color(gfx_ctxt_t *ctxt, u32 color);
|
||||
void gfx_con_init(gfx_con_t *con, gfx_ctxt_t *ctxt);
|
||||
void gfx_con_setcol(gfx_con_t *con, u32 fgcol, int fillbg, u32 bgcol);
|
||||
|
||||
47
ipl/hos.c
47
ipl/hos.c
@@ -35,6 +35,7 @@
|
||||
#include "pkg2.h"
|
||||
#include "ff.h"
|
||||
#include "di.h"
|
||||
#include "config.h"
|
||||
|
||||
#include "gfx.h"
|
||||
extern gfx_ctxt_t gfx_ctxt;
|
||||
@@ -43,6 +44,8 @@ extern void sd_unmount();
|
||||
//#define DPRINTF(...) gfx_printf(&gfx_con, __VA_ARGS__)
|
||||
#define DPRINTF(...)
|
||||
|
||||
extern hekate_config h_cfg;
|
||||
|
||||
typedef struct _launch_ctxt_t
|
||||
{
|
||||
void *keyblob;
|
||||
@@ -209,7 +212,7 @@ int keygen(u8 *keyblob, u32 kb, void *tsec_fw)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void _copy_bootconfig(launch_ctxt_t *ctxt)
|
||||
static void _copy_bootconfig()
|
||||
{
|
||||
sdmmc_storage_t storage;
|
||||
sdmmc_t sdmmc;
|
||||
@@ -247,7 +250,7 @@ static int _read_emmc_pkg1(launch_ctxt_t *ctxt)
|
||||
gfx_printf(&gfx_con, "Identified package1 ('%s'),\nKeyblob version %d\n\n", (char *)(ctxt->pkg1 + 0x10), ctxt->pkg1_id->kb);
|
||||
|
||||
//Read the correct keyblob.
|
||||
ctxt->keyblob = (u8 *)malloc(NX_EMMC_BLOCKSIZE);
|
||||
ctxt->keyblob = (u8 *)calloc(NX_EMMC_BLOCKSIZE, 1);
|
||||
sdmmc_storage_read(&storage, 0x180000 / NX_EMMC_BLOCKSIZE + ctxt->pkg1_id->kb, 1, ctxt->keyblob);
|
||||
|
||||
res = 1;
|
||||
@@ -406,6 +409,16 @@ static int _config(launch_ctxt_t *ctxt, ini_sec_t *cfg)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void _free_launch_components(launch_ctxt_t *ctxt)
|
||||
{
|
||||
free(ctxt->keyblob);
|
||||
free(ctxt->pkg1);
|
||||
free(ctxt->pkg2);
|
||||
free(ctxt->warmboot);
|
||||
free(ctxt->secmon);
|
||||
free(ctxt->kernel);
|
||||
}
|
||||
|
||||
int hos_launch(ini_sec_t *cfg)
|
||||
{
|
||||
int bootStateDramPkg2 = 0;
|
||||
@@ -434,8 +447,12 @@ int hos_launch(ini_sec_t *cfg)
|
||||
gfx_printf(&gfx_con, "Loaded package1 and keyblob\n");
|
||||
|
||||
// Generate keys.
|
||||
keygen(ctxt.keyblob, ctxt.pkg1_id->kb, (u8 *)ctxt.pkg1 + ctxt.pkg1_id->tsec_off);
|
||||
DPRINTF("Generated keys\n");
|
||||
if (!h_cfg.se_keygen_done)
|
||||
{
|
||||
keygen(ctxt.keyblob, ctxt.pkg1_id->kb, (u8 *)ctxt.pkg1 + ctxt.pkg1_id->tsec_off);
|
||||
h_cfg.se_keygen_done = 1;
|
||||
DPRINTF("Generated keys\n");
|
||||
}
|
||||
|
||||
// Decrypt and unpack package1 if we require parts of it.
|
||||
if (!ctxt.warmboot || !ctxt.secmon)
|
||||
@@ -544,6 +561,10 @@ int hos_launch(ini_sec_t *cfg)
|
||||
}
|
||||
case KB_FIRMWARE_VERSION_300:
|
||||
case KB_FIRMWARE_VERSION_301:
|
||||
if (ctxt.pkg1_id->kb == KB_FIRMWARE_VERSION_300)
|
||||
PMC(APBDEV_PMC_SECURE_SCRATCH32) = 0xE3; // Warmboot 3.0.0 security check.
|
||||
else if (ctxt.pkg1_id->kb == KB_FIRMWARE_VERSION_301)
|
||||
PMC(APBDEV_PMC_SECURE_SCRATCH32) = 0x104; // Warmboot 3.0.1/.2 security check.
|
||||
se_key_acc_ctrl(12, 0xFF);
|
||||
se_key_acc_ctrl(13, 0xFF);
|
||||
bootStateDramPkg2 = 2;
|
||||
@@ -552,11 +573,11 @@ int hos_launch(ini_sec_t *cfg)
|
||||
if (!exoFwNumber)
|
||||
exoFwNumber = 3;
|
||||
break;
|
||||
default:
|
||||
case KB_FIRMWARE_VERSION_400:
|
||||
if (!exoFwNumber)
|
||||
exoFwNumber = 4;
|
||||
case KB_FIRMWARE_VERSION_500:
|
||||
default:
|
||||
se_key_acc_ctrl(12, 0xFF);
|
||||
se_key_acc_ctrl(15, 0xFF);
|
||||
bootStateDramPkg2 = 2;
|
||||
@@ -566,6 +587,10 @@ int hos_launch(ini_sec_t *cfg)
|
||||
break;
|
||||
}
|
||||
|
||||
// Free allocated memory.
|
||||
ini_free_section(cfg);
|
||||
_free_launch_components(&ctxt);
|
||||
|
||||
// Copy BCT if debug mode is enabled.
|
||||
memset((void *)0x4003D000, 0, 0x3000);
|
||||
if(ctxt.debugmode)
|
||||
@@ -584,17 +609,17 @@ int hos_launch(ini_sec_t *cfg)
|
||||
// Lock SE before starting 'SecureMonitor'.
|
||||
_se_lock();
|
||||
|
||||
//< 4.0.0 Signals. 0: Nothing ready, 1: BCT ready, 2: DRAM and pkg2 ready, 3: Continue boot
|
||||
//>=4.0.0 Signals. 0: Nothing ready, 1: BCT ready, 2: DRAM ready, 4: pkg2 ready and continue boot
|
||||
// < 4.0.0 Signals - 0: Nothing ready, 1: BCT ready, 2: DRAM and pkg2 ready, 3: Continue boot.
|
||||
// >= 4.0.0 Signals - 0: Nothing ready, 1: BCT ready, 2: DRAM ready, 4: pkg2 ready and continue boot.
|
||||
vu32 *mb_in = (vu32 *)0x40002EF8;
|
||||
//Non-zero: Secmon ready
|
||||
vu32 *mb_out = (vu32 *)0x40002EFC;
|
||||
|
||||
//Start from DRAM ready signal
|
||||
// Start from DRAM ready signal.
|
||||
*mb_in = bootStateDramPkg2;
|
||||
*mb_out = 0;
|
||||
|
||||
//Wait for secmon to get ready.
|
||||
// Wait for secmon to get ready.
|
||||
cluster_boot_cpu0(ctxt.pkg1_id->secmon_base);
|
||||
while (!*mb_out)
|
||||
usleep(1);
|
||||
@@ -613,10 +638,10 @@ int hos_launch(ini_sec_t *cfg)
|
||||
if (end_di)
|
||||
display_end();
|
||||
|
||||
//Signal to pkg2 ready and continue boot.
|
||||
// Signal pkg2 ready and continue boot.
|
||||
*mb_in = bootStatePkg2Continue;
|
||||
|
||||
//Halt ourselves in waitevent state and resume if there's JTAG activity.
|
||||
// Halt ourselves in waitevent state and resume if there's JTAG activity.
|
||||
while (1)
|
||||
FLOW_CTLR(FLOW_CTLR_HALT_COP_EVENTS) = 0x50000000;
|
||||
|
||||
|
||||
294
ipl/main.c
294
ipl/main.c
@@ -50,6 +50,7 @@
|
||||
#include "se_t210.h"
|
||||
#include "hos.h"
|
||||
#include "pkg1.h"
|
||||
#include "pkg2.h"
|
||||
#include "mmc.h"
|
||||
#include "lz.h"
|
||||
#include "max17050.h"
|
||||
@@ -354,7 +355,7 @@ void config_hw()
|
||||
|
||||
void print_fuseinfo()
|
||||
{
|
||||
gfx_clear_grey(&gfx_ctxt, 0x1B);
|
||||
gfx_clear_partial_grey(&gfx_ctxt, 0x1B, 0, 1256);
|
||||
gfx_con_setpos(&gfx_con, 0, 0);
|
||||
|
||||
u32 burntFuses = 0;
|
||||
@@ -392,11 +393,9 @@ void print_fuseinfo()
|
||||
char fuseFilename[23];
|
||||
f_mkdir("Backup");
|
||||
f_mkdir("Backup/Dumps");
|
||||
memcpy(fuseFilename, "Backup/Dumps/fuses.bin\0", 23);
|
||||
memcpy(fuseFilename, "Backup/Dumps/fuses.bin", 23);
|
||||
|
||||
if (sd_save_to_file((u8 *)0x7000F900, 0x2FC, fuseFilename))
|
||||
EPRINTF("\nError creating fuse.bin file.");
|
||||
else
|
||||
if (!sd_save_to_file((u8 *)0x7000F900, 0x2FC, fuseFilename))
|
||||
gfx_puts(&gfx_con, "\nDone!\n");
|
||||
sd_unmount();
|
||||
}
|
||||
@@ -407,7 +406,7 @@ void print_fuseinfo()
|
||||
|
||||
void print_kfuseinfo()
|
||||
{
|
||||
gfx_clear_grey(&gfx_ctxt, 0x1B);
|
||||
gfx_clear_partial_grey(&gfx_ctxt, 0x1B, 0, 1256);
|
||||
gfx_con_setpos(&gfx_con, 0, 0);
|
||||
|
||||
gfx_printf(&gfx_con, "%kKFuse contents:\n\n%k", 0xFF00DDFF, 0xFFCCCCCC);
|
||||
@@ -427,11 +426,9 @@ void print_kfuseinfo()
|
||||
char kfuseFilename[24];
|
||||
f_mkdir("Backup");
|
||||
f_mkdir("Backup/Dumps");
|
||||
memcpy(kfuseFilename, "Backup/Dumps/kfuses.bin\0", 24);
|
||||
memcpy(kfuseFilename, "Backup/Dumps/kfuses.bin", 24);
|
||||
|
||||
if (sd_save_to_file((u8 *)buf, KFUSE_NUM_WORDS * 4, kfuseFilename))
|
||||
EPRINTF("\nError creating kfuse.bin file.");
|
||||
else
|
||||
if (!sd_save_to_file((u8 *)buf, KFUSE_NUM_WORDS * 4, kfuseFilename))
|
||||
gfx_puts(&gfx_con, "\nDone!\n");
|
||||
sd_unmount();
|
||||
}
|
||||
@@ -442,7 +439,7 @@ void print_kfuseinfo()
|
||||
|
||||
void print_mmc_info()
|
||||
{
|
||||
gfx_clear_grey(&gfx_ctxt, 0x1B);
|
||||
gfx_clear_partial_grey(&gfx_ctxt, 0x1B, 0, 1256);
|
||||
gfx_con_setpos(&gfx_con, 0, 0);
|
||||
|
||||
static const u32 SECTORS_TO_MIB_COEFF = 11;
|
||||
@@ -599,7 +596,7 @@ void print_sdcard_info()
|
||||
{
|
||||
static const u32 SECTORS_TO_MIB_COEFF = 11;
|
||||
|
||||
gfx_clear_grey(&gfx_ctxt, 0x1B);
|
||||
gfx_clear_partial_grey(&gfx_ctxt, 0x1B, 0, 1256);
|
||||
gfx_con_setpos(&gfx_con, 0, 0);
|
||||
|
||||
if (sd_mount())
|
||||
@@ -651,7 +648,7 @@ void print_sdcard_info()
|
||||
|
||||
void print_tsec_key()
|
||||
{
|
||||
gfx_clear_grey(&gfx_ctxt, 0x1B);
|
||||
gfx_clear_partial_grey(&gfx_ctxt, 0x1B, 0, 1256);
|
||||
gfx_con_setpos(&gfx_con, 0, 0);
|
||||
|
||||
sdmmc_storage_t storage;
|
||||
@@ -845,7 +842,7 @@ int dump_emmc_part(char *sd_path, sdmmc_storage_t *storage, emmc_part_t *part)
|
||||
|
||||
FIL partialIdxFp;
|
||||
char partialIdxFilename[12];
|
||||
memcpy(partialIdxFilename, "partial.idx\0", 12);
|
||||
memcpy(partialIdxFilename, "partial.idx", 12);
|
||||
|
||||
gfx_con.fntsz = 8;
|
||||
gfx_printf(&gfx_con, "\nSD Card free space: %d MiB, Total backup size %d MiB\n\n",
|
||||
@@ -1015,11 +1012,11 @@ int dump_emmc_part(char *sd_path, sdmmc_storage_t *storage, emmc_part_t *part)
|
||||
// More parts to backup that do not currently fit the sd card free space or fatal error.
|
||||
if (currPartIdx >= maxSplitParts)
|
||||
{
|
||||
gfx_puts(&gfx_con, "\n\n1. Press any key and Power off Switch from the main menu.\n\
|
||||
2. Move the files from SD card to free space.\n\
|
||||
gfx_puts(&gfx_con, "\n\n1. Press any key to unmount SD Card.\n\
|
||||
2. Remove SD Card and move files to free space.\n\
|
||||
Don\'t move the partial.idx file!\n\
|
||||
3. Unplug and re-plug USB while pressing Vol+.\n\
|
||||
4. Run hekate again and press Backup eMMC RAW GPP (or eMMC USER) to continue.\n");
|
||||
3. Re-insert SD Card.\n\
|
||||
4. Select the SAME option again to continue.\n");
|
||||
gfx_con.fntsz = 16;
|
||||
|
||||
free(buf);
|
||||
@@ -1137,7 +1134,8 @@ static void dump_emmc_selected(emmcPartType_t dumpType)
|
||||
{
|
||||
int res = 0;
|
||||
u32 timer = 0;
|
||||
gfx_clear_grey(&gfx_ctxt, 0x1B);
|
||||
gfx_clear_partial_grey(&gfx_ctxt, 0x1B, 0, 1256);
|
||||
tui_sbar(&gfx_con, 1);
|
||||
gfx_con_setpos(&gfx_con, 0, 0);
|
||||
|
||||
if (!sd_mount())
|
||||
@@ -1283,7 +1281,7 @@ int restore_emmc_part(char *sd_path, sdmmc_storage_t *storage, emmc_part_t *part
|
||||
else if (((u32)((u64)f_size(&fp)>>(u64)9)) != totalSectors)
|
||||
{
|
||||
gfx_con.fntsz = 16;
|
||||
EPRINTF("Size of sd card backup does not match,\neMMC's selected part size.\n");
|
||||
EPRINTF("Size of the SD Card backup does not match,\neMMC's selected part size.\n");
|
||||
f_close(&fp);
|
||||
|
||||
return 0;
|
||||
@@ -1381,7 +1379,8 @@ static void restore_emmc_selected(emmcPartType_t restoreType)
|
||||
{
|
||||
int res = 0;
|
||||
u32 timer = 0;
|
||||
gfx_clear_grey(&gfx_ctxt, 0x1B);
|
||||
gfx_clear_partial_grey(&gfx_ctxt, 0x1B, 0, 1256);
|
||||
tui_sbar(&gfx_con, 1);
|
||||
gfx_con_setpos(&gfx_con, 0, 0);
|
||||
|
||||
gfx_printf(&gfx_con, "%kThis is a dangerous operation\nand may render your device inoperative!\n\n", 0xFFFFDD00);
|
||||
@@ -1504,16 +1503,15 @@ void restore_emmc_boot() { restore_emmc_selected(PART_BOOT); }
|
||||
void restore_emmc_rawnand() { restore_emmc_selected(PART_RAW); }
|
||||
void restore_emmc_gpp_parts() { restore_emmc_selected(PART_GP_ALL); }
|
||||
|
||||
//TODO: dump_package2
|
||||
|
||||
void dump_package1()
|
||||
void dump_packages12()
|
||||
{
|
||||
u8 *pkg1 = (u8 *)calloc(1, 0x40000);
|
||||
u8 *warmboot = (u8 *)calloc(1, 0x40000);
|
||||
u8 *secmon = (u8 *)calloc(1, 0x40000);
|
||||
u8 *loader = (u8 *)calloc(1, 0x40000);
|
||||
u8 *pkg2 = NULL;
|
||||
|
||||
gfx_clear_grey(&gfx_ctxt, 0x1B);
|
||||
gfx_clear_partial_grey(&gfx_ctxt, 0x1B, 0, 1256);
|
||||
gfx_con_setpos(&gfx_con, 0, 0);
|
||||
|
||||
if (!sd_mount())
|
||||
@@ -1539,61 +1537,102 @@ void dump_package1()
|
||||
goto out;
|
||||
}
|
||||
|
||||
// Read keyblob.
|
||||
u8 * keyblob = (u8 *)malloc(NX_EMMC_BLOCKSIZE);
|
||||
sdmmc_storage_read(&storage, 0x180000 / NX_EMMC_BLOCKSIZE + pkg1_id->kb, 1, keyblob);
|
||||
if (!h_cfg.se_keygen_done)
|
||||
{
|
||||
// Read keyblob.
|
||||
u8 *keyblob = (u8 *)calloc(NX_EMMC_BLOCKSIZE, 1);
|
||||
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);
|
||||
// Decrypt.
|
||||
keygen(keyblob, pkg1_id->kb, (u8 *)pkg1 + pkg1_id->tsec_off);
|
||||
|
||||
h_cfg.se_keygen_done = 1;
|
||||
free(keyblob);
|
||||
}
|
||||
pkg1_decrypt(pkg1_id, pkg1);
|
||||
|
||||
pkg1_unpack(warmboot, secmon, loader, pkg1_id, pkg1);
|
||||
|
||||
// Display info.
|
||||
gfx_printf(&gfx_con, "%kNX Bootloader size: %k0x%05X\n", 0xFFC7EA46, 0xFFCCCCCC, hdr->ldr_size);
|
||||
gfx_printf(&gfx_con, "%kNX Bootloader ofst: %k0x%05X\n\n", 0xFFC7EA46, 0xFFCCCCCC, hdr->ldr_off);
|
||||
gfx_printf(&gfx_con, "%kNX Bootloader size: %k0x%05X\n\n", 0xFFC7EA46, 0xFFCCCCCC, hdr->ldr_size);
|
||||
|
||||
gfx_printf(&gfx_con, "%kSecure monitor addr: %k0x%05X\n", 0xFFC7EA46, 0xFFCCCCCC, pkg1_id->secmon_base);
|
||||
gfx_printf(&gfx_con, "%kSecure monitor size: %k0x%05X\n\n", 0xFFC7EA46, 0xFFCCCCCC, hdr->sm_size);
|
||||
gfx_printf(&gfx_con, "%kSecure monitor ofst: %k0x%05X\n\n", 0xFFC7EA46, 0xFFCCCCCC, hdr->sm_off);
|
||||
|
||||
gfx_printf(&gfx_con, "%kWarmboot addr: %k0x%05X\n", 0xFFC7EA46, 0xFFCCCCCC, pkg1_id->warmboot_base);
|
||||
gfx_printf(&gfx_con, "%kWarmboot size: %k0x%05X\n\n", 0xFFC7EA46, 0xFFCCCCCC, hdr->wb_size);
|
||||
gfx_printf(&gfx_con, "%kWarmboot ofst: %k0x%05X\n\n", 0xFFC7EA46, 0xFFCCCCCC, hdr->wb_off);
|
||||
|
||||
// Dump package1.
|
||||
// Create folders if they do not exist.
|
||||
f_mkdir("Backup");
|
||||
f_mkdir("Backup/pkg1");
|
||||
if (sd_save_to_file(pkg1, 0x40000, "Backup/pkg1/pkg1_decr.bin")) {
|
||||
EPRINTF("\nFailed to create pkg1_decr.bin");
|
||||
f_mkdir("Backup/pkg2");
|
||||
|
||||
// Dump package1.1.
|
||||
if (sd_save_to_file(pkg1, 0x40000, "Backup/pkg1/pkg1_decr.bin"))
|
||||
goto out;
|
||||
}
|
||||
gfx_puts(&gfx_con, "\nFull package1 dumped to pkg1_decr.bin\n");
|
||||
|
||||
// Dump nxbootloader.
|
||||
if (sd_save_to_file(loader, hdr->ldr_size, "Backup/pkg1/nxloader.bin")) {
|
||||
EPRINTF("\nFailed to create nxloader.bin");
|
||||
if (sd_save_to_file(loader, hdr->ldr_size, "Backup/pkg1/nxloader.bin"))
|
||||
goto out;
|
||||
}
|
||||
gfx_puts(&gfx_con, "NX Bootloader dumped to nxloader.bin\n");
|
||||
|
||||
// Dump secmon.
|
||||
if (sd_save_to_file(secmon, hdr->sm_size, "Backup/pkg1/secmon.bin")) {
|
||||
EPRINTF("\nFailed to create secmon.bin");
|
||||
if (sd_save_to_file(secmon, hdr->sm_size, "Backup/pkg1/secmon.bin"))
|
||||
goto out;
|
||||
}
|
||||
gfx_puts(&gfx_con, "Secure Monitor dumped to secmon.bin\n");
|
||||
|
||||
// Dump warmboot.
|
||||
if (sd_save_to_file(warmboot, hdr->wb_size, "Backup/pkg1/warmboot.bin")) {
|
||||
EPRINTF("\nFailed to create warmboot.bin");
|
||||
if (sd_save_to_file(warmboot, hdr->wb_size, "Backup/pkg1/warmboot.bin"))
|
||||
goto out;
|
||||
}
|
||||
gfx_puts(&gfx_con, "Warmboot dumped to warmboot.bin\n");
|
||||
gfx_puts(&gfx_con, "Warmboot dumped to warmboot.bin\n\n\n");
|
||||
|
||||
// Dump package2.1
|
||||
sdmmc_storage_set_mmc_partition(&storage, 0);
|
||||
//Parse eMMC GPT.
|
||||
LIST_INIT(gpt);
|
||||
nx_emmc_gpt_parse(&gpt, &storage);
|
||||
//Find package2 partition.
|
||||
emmc_part_t *pkg2_part = nx_emmc_part_find(&gpt, "BCPKG2-1-Normal-Main");
|
||||
if (!pkg2_part)
|
||||
goto out;
|
||||
|
||||
sdmmc_storage_end(&storage);
|
||||
sd_unmount();
|
||||
//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);
|
||||
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,
|
||||
pkg2_size_aligned / NX_EMMC_BLOCKSIZE, pkg2);
|
||||
// Decrypt package2 and parse KIP1 blobs in INI1 section.
|
||||
pkg2_hdr_t *pkg2_hdr = pkg2_decrypt(pkg2);
|
||||
|
||||
// Display info.
|
||||
u32 kernel_crc32 = crc32c(pkg2_hdr->data, pkg2_hdr->sec_size[PKG2_SEC_KERNEL]);
|
||||
gfx_printf(&gfx_con, "\n%kKernel CRC32C: %k0x%08X\n\n",0xFFC7EA46, 0xFFCCCCCC, kernel_crc32);
|
||||
gfx_printf(&gfx_con, "%kKernel size: %k0x%05X\n\n", 0xFFC7EA46, 0xFFCCCCCC, pkg2_hdr->sec_size[PKG2_SEC_KERNEL]);
|
||||
gfx_printf(&gfx_con, "%kINI1 size: %k0x%05X\n\n", 0xFFC7EA46, 0xFFCCCCCC, pkg2_hdr->sec_size[PKG2_SEC_INI1]);
|
||||
// Dump pkg2.1.
|
||||
if (sd_save_to_file(pkg2, pkg2_hdr->sec_size[PKG2_SEC_KERNEL] + pkg2_hdr->sec_size[PKG2_SEC_INI1],
|
||||
"Backup/pkg2/pkg2_decr.bin"))
|
||||
goto out;
|
||||
gfx_puts(&gfx_con, "\nFull package2 dumped to pkg2_decr.bin\n");
|
||||
|
||||
// Dump kernel.
|
||||
if (sd_save_to_file(pkg2_hdr->data, pkg2_hdr->sec_size[PKG2_SEC_KERNEL], "Backup/pkg2/kernel.bin"))
|
||||
goto out;
|
||||
gfx_puts(&gfx_con, "Kernel dumped to kernel.bin\n");
|
||||
|
||||
// Dump INI1.
|
||||
if (sd_save_to_file(pkg2_hdr->data + pkg2_hdr->sec_size[PKG2_SEC_KERNEL],
|
||||
pkg2_hdr->sec_size[PKG2_SEC_INI1], "Backup/pkg2/ini1.bin"))
|
||||
goto out;
|
||||
gfx_puts(&gfx_con, "INI1 kip1 package dumped to ini1.bin\n");
|
||||
|
||||
gfx_puts(&gfx_con, "\nDone. Press any key...\n");
|
||||
|
||||
out:;
|
||||
@@ -1601,6 +1640,10 @@ out:;
|
||||
free(secmon);
|
||||
free(warmboot);
|
||||
free(loader);
|
||||
free(pkg2);
|
||||
nx_emmc_gpt_free(&gpt);
|
||||
sdmmc_storage_end(&storage);
|
||||
sd_unmount();
|
||||
|
||||
btn_wait();
|
||||
}
|
||||
@@ -1812,6 +1855,9 @@ void auto_launch_firmware()
|
||||
// Center logo if res < 720x1280.
|
||||
bmpData.pos_x = (720 - bmpData.size_x) >> 1;
|
||||
bmpData.pos_y = (1280 - bmpData.size_y) >> 1;
|
||||
// Get background color from 1st pixel.
|
||||
if (bmpData.size_x < 720 || bmpData.size_y < 1280)
|
||||
gfx_clear_color(&gfx_ctxt, *(u32 *)BOOTLOGO);
|
||||
|
||||
bootlogoFound = 1;
|
||||
}
|
||||
@@ -1861,6 +1907,7 @@ void auto_launch_firmware()
|
||||
}
|
||||
|
||||
out:;
|
||||
gfx_clear_grey(&gfx_ctxt, 0x1B);
|
||||
if (!ini_freed)
|
||||
ini_free(&ini_sections);
|
||||
ini_free_section(cfg_sec);
|
||||
@@ -1876,7 +1923,7 @@ void toggle_autorcm(){
|
||||
sdmmc_storage_t storage;
|
||||
sdmmc_t sdmmc;
|
||||
|
||||
gfx_clear_grey(&gfx_ctxt, 0x1B);
|
||||
gfx_clear_partial_grey(&gfx_ctxt, 0x1B, 0, 1256);
|
||||
gfx_con_setpos(&gfx_con, 0, 0);
|
||||
|
||||
if (!sdmmc_storage_init_mmc(&storage, &sdmmc, SDMMC_4, SDMMC_BUS_WIDTH_8, 4))
|
||||
@@ -1906,70 +1953,83 @@ out:;
|
||||
btn_wait();
|
||||
}
|
||||
|
||||
int fix_attributes(char *path, u32 *total)
|
||||
int fix_attributes(char *path, u32 *total, u32 is_root, u32 check_first_run)
|
||||
{
|
||||
FRESULT res;
|
||||
DIR dir;
|
||||
u32 i = 0;
|
||||
u32 k = 0;
|
||||
u32 dirLength = 0;
|
||||
static FILINFO fno;
|
||||
|
||||
// Remove archive bit for selected "root" path.
|
||||
f_chmod(path, 0, AM_ARC);
|
||||
if (check_first_run)
|
||||
{
|
||||
// Read file attributes.
|
||||
res = f_stat(path, &fno);
|
||||
if (res != FR_OK)
|
||||
return res;
|
||||
|
||||
// Check if archive bit is set.
|
||||
if (fno.fattrib & AM_ARC)
|
||||
{
|
||||
*(u32 *)total = *(u32 *)total + 1;
|
||||
f_chmod(path, 0, AM_ARC);
|
||||
}
|
||||
}
|
||||
|
||||
// Open directory.
|
||||
res = f_opendir(&dir, path);
|
||||
if (res == FR_OK)
|
||||
if (res != FR_OK)
|
||||
return res;
|
||||
|
||||
dirLength = strlen(path);
|
||||
for (;;)
|
||||
{
|
||||
for (;;)
|
||||
// Clear file or folder path.
|
||||
path[dirLength] = 0;
|
||||
|
||||
// Read a directory item.
|
||||
res = f_readdir(&dir, &fno);
|
||||
|
||||
// Break on error or end of dir.
|
||||
if (res != FR_OK || fno.fname[0] == 0)
|
||||
break;
|
||||
|
||||
// Skip official Nintendo dir.
|
||||
if (is_root && !strcmp(fno.fname, "Nintendo"))
|
||||
continue;
|
||||
|
||||
// Set new directory or file.
|
||||
memcpy(&path[dirLength], "/", 1);
|
||||
memcpy(&path[dirLength+1], fno.fname, strlen(fno.fname) + 1);
|
||||
|
||||
// Check if archive bit is set.
|
||||
if (fno.fattrib & AM_ARC)
|
||||
{
|
||||
// Read a directory item.
|
||||
res = f_readdir(&dir, &fno);
|
||||
// Break on error or end of dir.
|
||||
if (res != FR_OK || fno.fname[0] == 0)
|
||||
break;
|
||||
|
||||
// Set new directory.
|
||||
i = strlen(path);
|
||||
memcpy(&path[i], "/", 1);
|
||||
for (k = 0; k < 256; k++)
|
||||
{
|
||||
if (fno.fname[k] == 0)
|
||||
break;
|
||||
}
|
||||
memcpy(&path[i+1], fno.fname, k + 1);
|
||||
path[i + k + 2] = 0;
|
||||
|
||||
// Check if archive bit is set.
|
||||
if (fno.fattrib & AM_ARC)
|
||||
{
|
||||
*(u32 *)total = *(u32 *)total + 1;
|
||||
f_chmod(path, 0, AM_ARC);
|
||||
}
|
||||
|
||||
// Is it a directory?
|
||||
if (fno.fattrib & AM_DIR)
|
||||
{
|
||||
// Enter the directory.
|
||||
res = fix_attributes(path, total);
|
||||
if (res != FR_OK)
|
||||
break;
|
||||
}
|
||||
// Clear file or folder path.
|
||||
path[i] = 0;
|
||||
*(u32 *)total = *(u32 *)total + 1;
|
||||
f_chmod(path, 0, AM_ARC);
|
||||
}
|
||||
|
||||
// Is it a directory?
|
||||
if (fno.fattrib & AM_DIR)
|
||||
{
|
||||
// Enter the directory.
|
||||
res = fix_attributes(path, total, 0, 0);
|
||||
if (res != FR_OK)
|
||||
break;
|
||||
}
|
||||
f_closedir(&dir);
|
||||
}
|
||||
|
||||
f_closedir(&dir);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
void fix_sd_attr(u32 type)
|
||||
{
|
||||
gfx_clear_grey(&gfx_ctxt, 0x1B);
|
||||
gfx_clear_partial_grey(&gfx_ctxt, 0x1B, 0, 1256);
|
||||
gfx_con_setpos(&gfx_con, 0, 0);
|
||||
|
||||
char buff[256];
|
||||
char path[256];
|
||||
char label[14];
|
||||
|
||||
u32 total = 0;
|
||||
if (sd_mount())
|
||||
@@ -1977,25 +2037,26 @@ void fix_sd_attr(u32 type)
|
||||
switch (type)
|
||||
{
|
||||
case 0:
|
||||
gfx_printf(&gfx_con, "Traversing all switch folder files!\nThis may take some time, please wait...\n");
|
||||
memcpy(buff, "/switch\0", 8);
|
||||
memcpy(path, "/", 2);
|
||||
memcpy(label, "SD Card", 8);
|
||||
break;
|
||||
case 1:
|
||||
default:
|
||||
gfx_printf(&gfx_con, "Traversing all sd card files!\nThis may take some time, please wait...\n");
|
||||
memcpy(buff, "/\0", 2);
|
||||
memcpy(path, "/switch", 8);
|
||||
memcpy(label, "switch folder", 14);
|
||||
break;
|
||||
}
|
||||
|
||||
fix_attributes(buff, &total);
|
||||
gfx_printf(&gfx_con, "\n%kTotal archive bits cleared: %d!%k\n\nDone! Press any key...", 0xFF96FF00, total, 0xFFCCCCCC);
|
||||
gfx_printf(&gfx_con, "Traversing all %s files!\nThis may take some time, please wait...\n\n", label);
|
||||
fix_attributes(path, &total, !type, type);
|
||||
gfx_printf(&gfx_con, "%kTotal archive bits cleared: %d!%k\n\nDone! Press any key...", 0xFF96FF00, total, 0xFFCCCCCC);
|
||||
sd_unmount();
|
||||
}
|
||||
btn_wait();
|
||||
}
|
||||
|
||||
void fix_sd_switch_attr() { fix_sd_attr(0); }
|
||||
void fix_sd_all_attr() { fix_sd_attr(1); }
|
||||
void fix_sd_all_attr() { fix_sd_attr(0); }
|
||||
void fix_sd_switch_attr() { fix_sd_attr(1); }
|
||||
|
||||
void print_fuel_gauge_info()
|
||||
{
|
||||
@@ -2123,7 +2184,7 @@ void print_battery_charger_info()
|
||||
|
||||
void print_battery_info()
|
||||
{
|
||||
gfx_clear_grey(&gfx_ctxt, 0x1B);
|
||||
gfx_clear_partial_grey(&gfx_ctxt, 0x1B, 0, 1256);
|
||||
gfx_con_setpos(&gfx_con, 0, 0);
|
||||
|
||||
print_fuel_gauge_info();
|
||||
@@ -2153,7 +2214,7 @@ void print_battery_info()
|
||||
char fuelFilename[28];
|
||||
f_mkdir("Backup");
|
||||
f_mkdir("Backup/Dumps");
|
||||
memcpy(fuelFilename, "Backup/Dumps/fuel_gauge.bin\0", 28);
|
||||
memcpy(fuelFilename, "Backup/Dumps/fuel_gauge.bin", 28);
|
||||
|
||||
if (sd_save_to_file((u8 *)buf, 0x200, fuelFilename))
|
||||
EPRINTF("\nError creating fuel.bin file.");
|
||||
@@ -2169,7 +2230,7 @@ void print_battery_info()
|
||||
|
||||
/* void fix_fuel_gauge_configuration()
|
||||
{
|
||||
gfx_clear_grey(&gfx_ctxt, 0x1B);
|
||||
gfx_clear_partial_grey(&gfx_ctxt, 0x1B, 0, 1256);
|
||||
gfx_con_setpos(&gfx_con, 0, 0);
|
||||
|
||||
int battVoltage, avgCurrent;
|
||||
@@ -2222,7 +2283,7 @@ void print_battery_info()
|
||||
{
|
||||
int avgCurrent;
|
||||
|
||||
gfx_clear_grey(&gfx_ctxt, 0x1B);
|
||||
gfx_clear_partial_grey(&gfx_ctxt, 0x1B, 0, 1256);
|
||||
gfx_con_setpos(&gfx_con, 0, 0);
|
||||
|
||||
gfx_printf(&gfx_con, "%k\nThis will wipe your battery stats completely!\n"
|
||||
@@ -2233,7 +2294,7 @@ void print_battery_info()
|
||||
u32 btn = btn_wait();
|
||||
if (btn & BTN_POWER)
|
||||
{
|
||||
gfx_clear_grey(&gfx_ctxt, 0x1B);
|
||||
gfx_clear_partial_grey(&gfx_ctxt, 0x1B, 0, 1256);
|
||||
gfx_con_setpos(&gfx_con, 0, 0);
|
||||
gfx_printf(&gfx_con, "%kKeep the USB cable connected!%k\n\n", 0xFFFFDD00, 0xFFCCCCCC);
|
||||
gfx_con_getpos(&gfx_con, &gfx_con.savedx, &gfx_con.savedy);
|
||||
@@ -2268,7 +2329,7 @@ void print_battery_info()
|
||||
|
||||
void fix_battery_desync()
|
||||
{
|
||||
gfx_clear_grey(&gfx_ctxt, 0x1B);
|
||||
gfx_clear_partial_grey(&gfx_ctxt, 0x1B, 0, 1256);
|
||||
gfx_con_setpos(&gfx_con, 0, 0);
|
||||
|
||||
max77620_low_battery_monitor_config();
|
||||
@@ -2339,7 +2400,7 @@ ment_t ment_options[] = {
|
||||
|
||||
menu_t menu_options = {
|
||||
ment_options,
|
||||
"Launch options", 0, 0
|
||||
"Launch Options", 0, 0
|
||||
};
|
||||
|
||||
ment_t ment_cinfo[] = {
|
||||
@@ -2360,7 +2421,7 @@ ment_t ment_cinfo[] = {
|
||||
};
|
||||
menu_t menu_cinfo = {
|
||||
ment_cinfo,
|
||||
"Console info", 0, 0
|
||||
"Console Info", 0, 0
|
||||
};
|
||||
|
||||
ment_t ment_autorcm[] = {
|
||||
@@ -2399,7 +2460,7 @@ ment_t ment_restore[] = {
|
||||
|
||||
menu_t menu_restore = {
|
||||
ment_restore,
|
||||
"Restore options", 0, 0
|
||||
"Restore Options", 0, 0
|
||||
};
|
||||
|
||||
ment_t ment_backup[] = {
|
||||
@@ -2417,7 +2478,7 @@ ment_t ment_backup[] = {
|
||||
|
||||
menu_t menu_backup = {
|
||||
ment_backup,
|
||||
"Backup options", 0, 0
|
||||
"Backup Options", 0, 0
|
||||
};
|
||||
|
||||
ment_t ment_tools[] = {
|
||||
@@ -2429,10 +2490,10 @@ ment_t ment_tools[] = {
|
||||
MDEF_HANDLER("Verification options", config_verification),
|
||||
MDEF_CHGLINE(),
|
||||
MDEF_CAPTION("-------- Misc --------", 0xFF0AB9E6),
|
||||
MDEF_HANDLER("Dump package1", dump_package1),
|
||||
MDEF_HANDLER("Dump package1/2", dump_packages12),
|
||||
MDEF_HANDLER("Fix battery de-sync", fix_battery_desync),
|
||||
MDEF_HANDLER("Remove archive bit (switch folder)", fix_sd_switch_attr),
|
||||
//MDEF_HANDLER("Remove archive bit (all sd files)", fix_sd_all_attr),
|
||||
MDEF_HANDLER("Unset archive bit (switch folder)", fix_sd_switch_attr),
|
||||
MDEF_HANDLER("Unset archive bit (all sd files)", fix_sd_all_attr),
|
||||
//MDEF_HANDLER("Fix fuel gauge configuration", fix_fuel_gauge_configuration),
|
||||
//MDEF_HANDLER("Reset all battery cfg", reset_pmic_fuel_gauge_charger_config),
|
||||
MDEF_CHGLINE(),
|
||||
@@ -2484,7 +2545,6 @@ void ipl_main()
|
||||
//display_color_screen(0xAABBCCDD);
|
||||
u32 *fb = display_init_framebuffer();
|
||||
gfx_init_ctxt(&gfx_ctxt, fb, 720, 1280, 768);
|
||||
gfx_clear_grey(&gfx_ctxt, 0x1B);
|
||||
|
||||
#ifdef MENU_LOGO_ENABLE
|
||||
Kc_MENU_LOGO = (u8 *)malloc(0x6000);
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
#define APBDEV_PMC_REG_SHORT 0x2CC
|
||||
#define APBDEV_PMC_WEAK_BIAS 0x2C8
|
||||
#define APBDEV_PMC_SECURE_SCRATCH21 0x334
|
||||
#define APBDEV_PMC_SECURE_SCRATCH32 0x360
|
||||
#define APBDEV_PMC_CNTRL2 0x440
|
||||
#define APBDEV_PMC_IO_DPD4_REQ 0x464
|
||||
#define APBDEV_PMC_DDR_CNTRL 0x4E4
|
||||
|
||||
4
ipl/se.c
4
ipl/se.c
@@ -259,7 +259,8 @@ int se_aes_xts_crypt(u32 ks1, u32 ks2, u32 enc, u64 sec, void *dst, void *src, u
|
||||
}
|
||||
|
||||
// se_calc_sha256() was derived from Atmosphère's se_calculate_sha256.
|
||||
int se_calc_sha256(void *dst, const void *src, u32 src_size) {
|
||||
int se_calc_sha256(void *dst, const void *src, u32 src_size)
|
||||
{
|
||||
int res;
|
||||
// Setup config for SHA256, size = BITS(src_size).
|
||||
SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_ENC_MODE(MODE_SHA256) | SE_CONFIG_ENC_ALG(ALG_SHA) | SE_CONFIG_DST(DST_HASHREG);
|
||||
@@ -283,3 +284,4 @@ int se_calc_sha256(void *dst, const void *src, u32 src_size) {
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
71
ipl/tui.c
71
ipl/tui.c
@@ -18,15 +18,55 @@
|
||||
#include "tui.h"
|
||||
#include "btn.h"
|
||||
#include "max17050.h"
|
||||
#include "config.h"
|
||||
#include "util.h"
|
||||
|
||||
#ifdef MENU_LOGO_ENABLE
|
||||
extern u8 *Kc_MENU_LOGO;
|
||||
#define X_MENU_LOGO 119
|
||||
#define Y_MENU_LOGO 57
|
||||
#define X_POS_MENU_LOGO 577
|
||||
#define Y_POS_MENU_LOGO 1199
|
||||
#define Y_POS_MENU_LOGO 1179
|
||||
#endif //MENU_LOGO_ENABLE
|
||||
|
||||
extern hekate_config h_cfg;
|
||||
|
||||
void tui_sbar(gfx_con_t *con, int force_update)
|
||||
{
|
||||
u32 timePassed = get_tmr_s() - h_cfg.sbar_time_keeping;
|
||||
if (!force_update)
|
||||
if (timePassed < 5)
|
||||
return;
|
||||
|
||||
u8 prevFontSize = con->fntsz;
|
||||
con->fntsz = 16;
|
||||
h_cfg.sbar_time_keeping = get_tmr_s();
|
||||
|
||||
u32 battPercent = 0;
|
||||
int battVoltCurr = 0;
|
||||
|
||||
gfx_con_getpos(con, &con->savedx, &con->savedy);
|
||||
gfx_con_setpos(con, 0, 1260);
|
||||
|
||||
max17050_get_property(MAX17050_RepSOC, (int *)&battPercent);
|
||||
max17050_get_property(MAX17050_VCELL, &battVoltCurr);
|
||||
|
||||
gfx_clear_partial_grey(con->gfx_ctxt, 0x30, 1256, 24);
|
||||
gfx_printf(con, "%K%k Battery: %d.%d%% (%d mV) - Charge:", 0xFF303030, 0xFF888888,
|
||||
(battPercent >> 8) & 0xFF, (battPercent & 0xFF) / 26, battVoltCurr);
|
||||
|
||||
max17050_get_property(MAX17050_AvgCurrent, &battVoltCurr);
|
||||
|
||||
if (battVoltCurr >= 0)
|
||||
gfx_printf(con, " %k+%d mA %k%K\n",
|
||||
0xFF008000, battVoltCurr / 1000, 0xFFCCCCCC, 0xFF1B1B1B);
|
||||
else
|
||||
gfx_printf(con, " %k-%d mA %k%K\n",
|
||||
0xFF800000, (~battVoltCurr) / 1000, 0xFFCCCCCC, 0xFF1B1B1B);
|
||||
con->fntsz = prevFontSize;
|
||||
gfx_con_setpos(con, con->savedx, con->savedy);
|
||||
}
|
||||
|
||||
void tui_pbar(gfx_con_t *con, int x, int y, u32 val, u32 fgcol, u32 bgcol)
|
||||
{
|
||||
u32 cx, cy;
|
||||
@@ -48,15 +88,18 @@ void tui_pbar(gfx_con_t *con, int x, int y, u32 val, u32 fgcol, u32 bgcol)
|
||||
}
|
||||
|
||||
gfx_con_setpos(con, cx, cy);
|
||||
|
||||
// Update status bar.
|
||||
tui_sbar(con, 0);
|
||||
}
|
||||
|
||||
void *tui_do_menu(gfx_con_t *con, menu_t *menu)
|
||||
{
|
||||
int idx = 0, prev_idx = 0, cnt = 0x7FFFFFFF;
|
||||
u32 battPercent = 0;
|
||||
int battVoltCurr = 0;
|
||||
|
||||
gfx_clear_grey(con->gfx_ctxt, 0x1B);
|
||||
gfx_clear_partial_grey(con->gfx_ctxt, 0x1B, 0, 1256);
|
||||
tui_sbar(con, 1);
|
||||
|
||||
#ifdef MENU_LOGO_ENABLE
|
||||
gfx_set_rect_rgb(con->gfx_ctxt, Kc_MENU_LOGO,
|
||||
X_MENU_LOGO, Y_MENU_LOGO, X_POS_MENU_LOGO, Y_POS_MENU_LOGO);
|
||||
@@ -113,21 +156,8 @@ void *tui_do_menu(gfx_con_t *con, menu_t *menu)
|
||||
|
||||
// Print help and battery status.
|
||||
gfx_con_getpos(con, &con->savedx, &con->savedy);
|
||||
gfx_con_setpos(con, 0, 74 * 16);
|
||||
gfx_printf(con, "%k VOL: Move up/down\n PWR: Select option\n\n", 0xFF555555);
|
||||
|
||||
max17050_get_property(MAX17050_RepSOC, (int *)&battPercent);
|
||||
gfx_printf(con, " %d.%d%%", (battPercent >> 8) & 0xFF, (battPercent & 0xFF) / 26);
|
||||
max17050_get_property(MAX17050_VCELL, &battVoltCurr);
|
||||
gfx_printf(con, " (%d mV) ", battVoltCurr);
|
||||
max17050_get_property(MAX17050_AvgCurrent, &battVoltCurr);
|
||||
if (battVoltCurr >= 0)
|
||||
gfx_printf(con, "\n %kCharging:%k %d mA %k\n",
|
||||
0xFF008000, 0xFF555555, battVoltCurr / 1000, 0xFFCCCCCC);
|
||||
else
|
||||
gfx_printf(con, "\n %kDischarging:%k -%d mA %k\n",
|
||||
0xFF800000, 0xFF555555, (~battVoltCurr) / 1000, 0xFFCCCCCC);
|
||||
gfx_con_setpos(con, con->savedx, con->savedy);
|
||||
gfx_con_setpos(con, 0, 1191);
|
||||
gfx_printf(con, "%k VOL: Move up/down\n PWR: Select option%k", 0xFF555555, 0xFFCCCCCC);
|
||||
|
||||
// Wait for user command.
|
||||
u32 btn = btn_wait();
|
||||
@@ -161,12 +191,13 @@ void *tui_do_menu(gfx_con_t *con, menu_t *menu)
|
||||
break;
|
||||
}
|
||||
con->fntsz = 16;
|
||||
gfx_clear_grey(con->gfx_ctxt, 0x1B);
|
||||
gfx_clear_partial_grey(con->gfx_ctxt, 0x1B, 0, 1256);
|
||||
#ifdef MENU_LOGO_ENABLE
|
||||
gfx_set_rect_rgb(con->gfx_ctxt, Kc_MENU_LOGO,
|
||||
X_MENU_LOGO, Y_MENU_LOGO, X_POS_MENU_LOGO, Y_POS_MENU_LOGO);
|
||||
#endif //MENU_LOGO_ENABLE
|
||||
}
|
||||
tui_sbar(con, 0);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
|
||||
@@ -58,6 +58,7 @@ typedef struct _menu_t
|
||||
#define MDEF_CAPTION(caption, color) { MENT_CAPTION, caption, color }
|
||||
#define MDEF_CHGLINE() {MENT_CHGLINE}
|
||||
|
||||
void tui_sbar(gfx_con_t *con, int force_update);
|
||||
void tui_pbar(gfx_con_t *con, int x, int y, u32 val, u32 fgcol, u32 bgcol);
|
||||
void *tui_do_menu(gfx_con_t *con, menu_t *menu);
|
||||
|
||||
|
||||
@@ -26,13 +26,13 @@ u32 get_tmr_s()
|
||||
u32 get_tmr_ms()
|
||||
{
|
||||
// The registers must be read with the following order:
|
||||
// -> RTC_MILLI_SECONDS (0x10) -> RTC_SHADOW_SECONDS (0x8)
|
||||
// -> RTC_MILLI_SECONDS (0x10) -> RTC_SHADOW_SECONDS (0xC)
|
||||
return (RTC(0x10) | (RTC(0xC)<< 10));
|
||||
}
|
||||
|
||||
u32 get_tmr_us()
|
||||
{
|
||||
return TMR(0x10); //TMRUS
|
||||
return TMR(0x10); //TIMERUS_CNTR_1US
|
||||
}
|
||||
|
||||
void msleep(u32 milliseconds)
|
||||
|
||||
Reference in New Issue
Block a user