Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8cb76be5fb | ||
|
|
075a9e0a9e | ||
|
|
bda777b1da | ||
|
|
eed1c6945d | ||
|
|
09267b884d | ||
|
|
cbd964306d | ||
|
|
4bfdee8b20 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,4 +1,3 @@
|
||||
.vs
|
||||
.vscode
|
||||
build_ipl/*
|
||||
/ipl.bin
|
||||
|
||||
203
ipl/ff.c
203
ipl/ff.c
@@ -3,7 +3,6 @@
|
||||
/-----------------------------------------------------------------------------/
|
||||
/
|
||||
/ Copyright (C) 2017, ChaN, all right reserved.
|
||||
/ Copyright (c) 2018 naehrwert
|
||||
/
|
||||
/ FatFs module is an open source software. Redistribution and use of FatFs in
|
||||
/ source and binary forms, with or without modification, are permitted provided
|
||||
@@ -23,11 +22,6 @@
|
||||
#include "ff.h" /* Declarations of FatFs API */
|
||||
#include "diskio.h" /* Declarations of device I/O functions */
|
||||
|
||||
#include "gfx.h"
|
||||
extern gfx_ctxt_t gfx_ctxt;
|
||||
extern gfx_con_t gfx_con;
|
||||
#define EFSPRINTF(text, ...) gfx_printf(&gfx_con, "\n\n%k[FatFS] "text"%k\n", 0xFF00FFFF, 0xFFFFFFFF)
|
||||
//#define EFSPRINTF(...)
|
||||
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@@ -3259,7 +3253,6 @@ FRESULT find_volume ( /* FR_OK(0): successful, !=0: any error occurred */
|
||||
stat = disk_status(fs->pdrv);
|
||||
if (!(stat & STA_NOINIT)) { /* and the physical drive is kept initialized */
|
||||
if (!FF_FS_READONLY && mode && (stat & STA_PROTECT)) { /* Check write protection if needed */
|
||||
EFSPRINTF("Error: Write protected!");
|
||||
return FR_WRITE_PROTECTED;
|
||||
}
|
||||
return FR_OK; /* The filesystem object is valid */
|
||||
@@ -3273,11 +3266,9 @@ FRESULT find_volume ( /* FR_OK(0): successful, !=0: any error occurred */
|
||||
fs->pdrv = LD2PD(vol); /* Bind the logical drive and a physical drive */
|
||||
stat = disk_initialize(fs->pdrv); /* Initialize the physical drive */
|
||||
if (stat & STA_NOINIT) { /* Check if the initialization succeeded */
|
||||
EFSPRINTF("Error: Medium not ready or hard error!");
|
||||
return FR_NOT_READY; /* Failed to initialize due to no medium or hard error */
|
||||
}
|
||||
if (!FF_FS_READONLY && mode && (stat & STA_PROTECT)) { /* Check disk write protection if needed */
|
||||
EFSPRINTF("Error: Write protected!");
|
||||
return FR_WRITE_PROTECTED;
|
||||
}
|
||||
#if FF_MAX_SS != FF_MIN_SS /* Get sector size (multiple sector size cfg only) */
|
||||
@@ -3300,14 +3291,8 @@ FRESULT find_volume ( /* FR_OK(0): successful, !=0: any error occurred */
|
||||
fmt = bsect ? check_fs(fs, bsect) : 3; /* Check the partition */
|
||||
} while (LD2PT(vol) == 0 && fmt >= 2 && ++i < 4);
|
||||
}
|
||||
if (fmt == 4) {
|
||||
EFSPRINTF("Error: Disk I/O error - Could not load boot record!");
|
||||
return FR_DISK_ERR; /* An error occured in the disk I/O layer */
|
||||
}
|
||||
if (fmt >= 2) {
|
||||
EFSPRINTF("Error: No FAT/FAT32/exFAT filesystem found!");
|
||||
return FR_NO_FILESYSTEM; /* No FAT volume is found */
|
||||
}
|
||||
if (fmt == 4) return FR_DISK_ERR; /* An error occured in the disk I/O layer */
|
||||
if (fmt >= 2) return FR_NO_FILESYSTEM; /* No FAT volume is found */
|
||||
|
||||
/* An FAT volume is found (bsect). Following code initializes the filesystem object */
|
||||
|
||||
@@ -3318,58 +3303,36 @@ FRESULT find_volume ( /* FR_OK(0): successful, !=0: any error occurred */
|
||||
for (i = BPB_ZeroedEx; i < BPB_ZeroedEx + 53 && fs->win[i] == 0; i++) ; /* Check zero filler */
|
||||
if (i < BPB_ZeroedEx + 53) return FR_NO_FILESYSTEM;
|
||||
|
||||
if (ld_word(fs->win + BPB_FSVerEx) != 0x100) {
|
||||
EFSPRINTF("Error: exFAT - Version check failed!");
|
||||
return FR_NO_FILESYSTEM; /* Check exFAT version (must be version 1.0) */
|
||||
}
|
||||
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("Error: exFAT - Bytes per sector 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("Error: exFAT - Cannot handle volume LBA with 32-bit LBA!");
|
||||
return FR_NO_FILESYSTEM; /* (It cannot be handled in 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 */
|
||||
|
||||
fs->n_fats = fs->win[BPB_NumFATsEx]; /* Number of FATs */
|
||||
if (fs->n_fats != 1) {
|
||||
EFSPRINTF("Error: exFAT - Multiple or no file allocation tables found!");
|
||||
return FR_NO_FILESYSTEM; /* (Supports only 1 FAT) */
|
||||
}
|
||||
if (fs->n_fats != 1) return FR_NO_FILESYSTEM; /* (Supports only 1 FAT) */
|
||||
|
||||
fs->csize = 1 << fs->win[BPB_SecPerClusEx]; /* Cluster size */
|
||||
if (fs->csize == 0) {
|
||||
EFSPRINTF("Error: exFAT - Cluster size is not between 1KB - 32KB!");
|
||||
return FR_NO_FILESYSTEM; /* (Must be 1..32768) */
|
||||
}
|
||||
if (fs->csize == 0) return FR_NO_FILESYSTEM; /* (Must be 1..32768) */
|
||||
|
||||
nclst = ld_dword(fs->win + BPB_NumClusEx); /* Number of clusters */
|
||||
if (nclst > MAX_EXFAT) {
|
||||
EFSPRINTF("Error: exFAT - Total clusters exceed allowed!");
|
||||
return FR_NO_FILESYSTEM; /* (Too many clusters) */
|
||||
}
|
||||
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("Error: exFAT - Volume size is lower than required!");
|
||||
return FR_NO_FILESYSTEM; /* (Volume size must not be smaller than the size required) */
|
||||
}
|
||||
if (maxlba < (QWORD)fs->database + nclst * fs->csize) return FR_NO_FILESYSTEM; /* (Volume size must not be smaller than the size requiered) */
|
||||
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("Error: exFAT - Bitmap location not at first cluster!");
|
||||
return FR_DISK_ERR;
|
||||
}
|
||||
if (move_window(fs, clst2sect(fs, fs->dirbase)) != FR_OK) return FR_DISK_ERR;
|
||||
for (i = 0; i < SS(fs); i += SZDIRE) {
|
||||
if (fs->win[i] == 0x81 && ld_dword(fs->win + i + 20) == 2) break; /* 81 entry with cluster #2? */
|
||||
}
|
||||
@@ -3381,62 +3344,38 @@ FRESULT find_volume ( /* FR_OK(0): successful, !=0: any error occurred */
|
||||
} else
|
||||
#endif /* FF_FS_EXFAT */
|
||||
{
|
||||
if (ld_word(fs->win + BPB_BytsPerSec) != SS(fs)) {
|
||||
EFSPRINTF("Error: FAT - Bytes per sector does not match physical sector size!");
|
||||
return FR_NO_FILESYSTEM; /* (BPB_BytsPerSec must be equal to the physical sector size) */
|
||||
}
|
||||
if (ld_word(fs->win + BPB_BytsPerSec) != SS(fs)) return FR_NO_FILESYSTEM; /* (BPB_BytsPerSec must be equal to the physical sector size) */
|
||||
|
||||
fasize = ld_word(fs->win + BPB_FATSz16); /* Number of sectors per FAT */
|
||||
if (fasize == 0) fasize = ld_dword(fs->win + BPB_FATSz32);
|
||||
fs->fsize = fasize;
|
||||
|
||||
fs->n_fats = fs->win[BPB_NumFATs]; /* Number of FATs */
|
||||
if (fs->n_fats != 1 && fs->n_fats != 2) {
|
||||
EFSPRINTF("Error: FAT - No or more than 2 file allocation tables found!");
|
||||
return FR_NO_FILESYSTEM; /* (Must be 1 or 2) */
|
||||
}
|
||||
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("Error: FAT - Cluster size is not a power of 2!");
|
||||
return FR_NO_FILESYSTEM; /* (Must be 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("Error: FAT - Root directory entries are not sector aligned!");
|
||||
return FR_NO_FILESYSTEM; /* (Must be 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("Error: FAT - Zero reserved sectors!");
|
||||
return FR_NO_FILESYSTEM; /* (Must not be 0) */
|
||||
}
|
||||
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("Error: FAT - Invalid volume size!");
|
||||
return FR_NO_FILESYSTEM; /* (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("Error: FAT - Invalid volume size!");
|
||||
return FR_NO_FILESYSTEM; /* (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("Error: FAT - Not compatible FAT12/16/32 filesystem!");
|
||||
return FR_NO_FILESYSTEM;
|
||||
}
|
||||
if (fmt == 0) return FR_NO_FILESYSTEM;
|
||||
|
||||
/* Boundaries and Limits */
|
||||
fs->n_fatent = nclst + 2; /* Number of FAT entries */
|
||||
@@ -3444,29 +3383,17 @@ FRESULT find_volume ( /* FR_OK(0): successful, !=0: any 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("Error: FAT32 - Not a 0.0 revision!");
|
||||
return FR_NO_FILESYSTEM; /* (Must be FAT32 revision 0.0) */
|
||||
}
|
||||
if (fs->n_rootdir != 0) {
|
||||
EFSPRINTF("Error: FAT32 - Root entry sector is not 0!");
|
||||
return FR_NO_FILESYSTEM; /* (BPB_RootEntCnt must be 0) */
|
||||
}
|
||||
if (ld_word(fs->win + BPB_FSVer32) != 0) return FR_NO_FILESYSTEM; /* (Must be FAT32 revision 0.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("Error: FAT - Root entry sector is 0!");
|
||||
return FR_NO_FILESYSTEM; /* (BPB_RootEntCnt must not be 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("Error: FAT - FAT size is not the required size!");
|
||||
return FR_NO_FILESYSTEM; /* (BPB_FATSz must not be less than the size needed) */
|
||||
}
|
||||
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 */
|
||||
@@ -3499,7 +3426,7 @@ FRESULT find_volume ( /* FR_OK(0): successful, !=0: any error occurred */
|
||||
#if FF_USE_LFN == 1
|
||||
fs->lfnbuf = LfnBuf; /* Static LFN working buffer */
|
||||
#if FF_FS_EXFAT
|
||||
fs->dirbuf = DirBuf; /* Static directory block scratch-pad buffer */
|
||||
fs->dirbuf = DirBuf; /* Static directory block scratchpad buuffer */
|
||||
#endif
|
||||
#endif
|
||||
#if FF_FS_RPATH != 0
|
||||
@@ -3577,10 +3504,7 @@ FRESULT f_mount (
|
||||
|
||||
/* Get logical drive number */
|
||||
vol = get_ldnumber(&rp);
|
||||
if (vol < 0) {
|
||||
EFSPRINTF("Error: Invalid drive!");
|
||||
return FR_INVALID_DRIVE;
|
||||
}
|
||||
if (vol < 0) return FR_INVALID_DRIVE;
|
||||
cfs = FatFs[vol]; /* Pointer to fs object */
|
||||
|
||||
if (cfs) {
|
||||
@@ -3821,14 +3745,8 @@ FRESULT f_read (
|
||||
|
||||
*br = 0; /* Clear read byte counter */
|
||||
res = validate(&fp->obj, &fs); /* Check validity of the file object */
|
||||
if (res != FR_OK || (res = (FRESULT)fp->err) != FR_OK) {
|
||||
EFSPRINTF("Error: File object Validation!");
|
||||
LEAVE_FF(fs, res); /* Check validity */
|
||||
}
|
||||
if (!(fp->flag & FA_READ)) {
|
||||
EFSPRINTF("Error: Access denied!");
|
||||
LEAVE_FF(fs, FR_DENIED); /* Check access mode */
|
||||
}
|
||||
if (res != FR_OK || (res = (FRESULT)fp->err) != FR_OK) LEAVE_FF(fs, res); /* Check validity */
|
||||
if (!(fp->flag & FA_READ)) LEAVE_FF(fs, FR_DENIED); /* Check access mode */
|
||||
remain = fp->obj.objsize - fp->fptr;
|
||||
if (btr > remain) btr = (UINT)remain; /* Truncate btr by remaining bytes */
|
||||
|
||||
@@ -3849,31 +3767,19 @@ FRESULT f_read (
|
||||
clst = get_fat(&fp->obj, fp->clust); /* Follow cluster chain on the FAT */
|
||||
}
|
||||
}
|
||||
if (clst < 2) {
|
||||
EFSPRINTF("Error: Cluster status check or Internal error!");
|
||||
ABORT(fs, FR_INT_ERR);
|
||||
}
|
||||
if (clst == 0xFFFFFFFF) {
|
||||
EFSPRINTF("Error: Disk error (cluster hard error)!");
|
||||
ABORT(fs, FR_DISK_ERR);
|
||||
}
|
||||
if (clst < 2) ABORT(fs, FR_INT_ERR);
|
||||
if (clst == 0xFFFFFFFF) ABORT(fs, FR_DISK_ERR);
|
||||
fp->clust = clst; /* Update current cluster */
|
||||
}
|
||||
sect = clst2sect(fs, fp->clust); /* Get current sector */
|
||||
if (sect == 0) {
|
||||
EFSPRINTF("Error: Get current sector error!");
|
||||
ABORT(fs, FR_INT_ERR);
|
||||
}
|
||||
if (sect == 0) ABORT(fs, FR_INT_ERR);
|
||||
sect += csect;
|
||||
cc = btr / SS(fs); /* When remaining bytes >= sector size, */
|
||||
if (cc > 0) { /* Read maximum contiguous sectors directly */
|
||||
if (csect + cc > fs->csize) { /* Clip at cluster boundary */
|
||||
cc = fs->csize - csect;
|
||||
}
|
||||
if (disk_read(fs->pdrv, rbuff, sect, cc) != RES_OK) {
|
||||
EFSPRINTF("Error: Read - Low level disk I/O!");
|
||||
ABORT(fs, FR_DISK_ERR);
|
||||
}
|
||||
if (disk_read(fs->pdrv, rbuff, sect, cc) != RES_OK) ABORT(fs, FR_DISK_ERR);
|
||||
#if !FF_FS_READONLY && FF_FS_MINIMIZE <= 2 /* Replace one of the read sectors with cached data if it contains a dirty sector */
|
||||
#if FF_FS_TINY
|
||||
if (fs->wflag && fs->winsect - sect < cc) {
|
||||
@@ -3892,17 +3798,11 @@ FRESULT f_read (
|
||||
if (fp->sect != sect) { /* Load data sector if not in cache */
|
||||
#if !FF_FS_READONLY
|
||||
if (fp->flag & FA_DIRTY) { /* Write-back dirty sector cache */
|
||||
if (disk_write(fs->pdrv, fp->buf, fp->sect, 1) != RES_OK) {
|
||||
EFSPRINTF("Error: Write-back dirty sector cache!");
|
||||
ABORT(fs, FR_DISK_ERR);
|
||||
}
|
||||
if (disk_write(fs->pdrv, fp->buf, fp->sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR);
|
||||
fp->flag &= (BYTE)~FA_DIRTY;
|
||||
}
|
||||
#endif
|
||||
if (disk_read(fs->pdrv, fp->buf, sect, 1) != RES_OK) {
|
||||
EFSPRINTF("Error: Read - Low level disk I/O!\n(fill sector cache)");
|
||||
ABORT(fs, FR_DISK_ERR); /* Fill sector cache */
|
||||
}
|
||||
if (disk_read(fs->pdrv, fp->buf, sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR); /* Fill sector cache */
|
||||
}
|
||||
#endif
|
||||
fp->sect = sect;
|
||||
@@ -3944,14 +3844,8 @@ FRESULT f_write (
|
||||
|
||||
*bw = 0; /* Clear write byte counter */
|
||||
res = validate(&fp->obj, &fs); /* Check validity of the file object */
|
||||
if (res != FR_OK || (res = (FRESULT)fp->err) != FR_OK) {
|
||||
EFSPRINTF("Error: File object Validation!");
|
||||
LEAVE_FF(fs, res); /* Check validity */
|
||||
}
|
||||
if (!(fp->flag & FA_WRITE)) {
|
||||
EFSPRINTF("Error: Access denied!");
|
||||
LEAVE_FF(fs, FR_DENIED); /* Check access mode */
|
||||
}
|
||||
if (res != FR_OK || (res = (FRESULT)fp->err) != FR_OK) LEAVE_FF(fs, res); /* Check validity */
|
||||
if (!(fp->flag & FA_WRITE)) LEAVE_FF(fs, FR_DENIED); /* Check access mode */
|
||||
|
||||
/* Check fptr wrap-around (file size cannot reach 4 GiB at FAT volume) */
|
||||
if ((!FF_FS_EXFAT || fs->fs_type != FS_EXFAT) && (DWORD)(fp->fptr + btw) < (DWORD)fp->fptr) {
|
||||
@@ -3978,18 +3872,9 @@ FRESULT f_write (
|
||||
clst = create_chain(&fp->obj, fp->clust); /* Follow or stretch cluster chain on the FAT */
|
||||
}
|
||||
}
|
||||
if (clst == 0) {
|
||||
EFSPRINTF("Error: Could not allocate a new cluster\n(disk full or low level disk I/O error)!");
|
||||
break; /* Could not allocate a new cluster (disk full) */
|
||||
}
|
||||
if (clst == 1) {
|
||||
EFSPRINTF("Error: Cluster status check or Internal error!");
|
||||
ABORT(fs, FR_INT_ERR);
|
||||
}
|
||||
if (clst == 0xFFFFFFFF) {
|
||||
EFSPRINTF("Error: Disk error (cluster hard error)!");
|
||||
ABORT(fs, FR_DISK_ERR);
|
||||
}
|
||||
if (clst == 0) break; /* Could not allocate a new cluster (disk full) */
|
||||
if (clst == 1) ABORT(fs, FR_INT_ERR);
|
||||
if (clst == 0xFFFFFFFF) ABORT(fs, FR_DISK_ERR);
|
||||
fp->clust = clst; /* Update current cluster */
|
||||
if (fp->obj.sclust == 0) fp->obj.sclust = clst; /* Set start cluster if the first write */
|
||||
}
|
||||
@@ -3997,28 +3882,19 @@ 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("Error: Write-back sector cache!");
|
||||
ABORT(fs, FR_DISK_ERR);
|
||||
}
|
||||
if (disk_write(fs->pdrv, fp->buf, fp->sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR);
|
||||
fp->flag &= (BYTE)~FA_DIRTY;
|
||||
}
|
||||
#endif
|
||||
sect = clst2sect(fs, fp->clust); /* Get current sector */
|
||||
if (sect == 0) {
|
||||
EFSPRINTF("Error: Get current sector error!");
|
||||
ABORT(fs, FR_INT_ERR);
|
||||
}
|
||||
if (sect == 0) ABORT(fs, FR_INT_ERR);
|
||||
sect += csect;
|
||||
cc = btw / SS(fs); /* When remaining bytes >= sector size, */
|
||||
if (cc > 0) { /* Write maximum contiguous sectors directly */
|
||||
if (csect + cc > fs->csize) { /* Clip at cluster boundary */
|
||||
cc = fs->csize - csect;
|
||||
}
|
||||
if (disk_write(fs->pdrv, wbuff, sect, cc) != RES_OK) {
|
||||
EFSPRINTF("Error: Write - Low level disk I/O!");
|
||||
ABORT(fs, FR_DISK_ERR);
|
||||
}
|
||||
if (disk_write(fs->pdrv, wbuff, sect, cc) != RES_OK) ABORT(fs, FR_DISK_ERR);
|
||||
#if FF_FS_MINIMIZE <= 2
|
||||
#if FF_FS_TINY
|
||||
if (fs->winsect - sect < cc) { /* Refill sector cache if it gets invalidated by the direct write */
|
||||
@@ -4044,7 +3920,6 @@ FRESULT f_write (
|
||||
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("Error: Read - Low level disk I/O!\n(Could not fill sector cache with file data)");
|
||||
ABORT(fs, FR_DISK_ERR);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -472,6 +472,8 @@ DPRINTF("decrypted and unpacked pkg1\n");
|
||||
*mb_in = 3;
|
||||
sleep(100);
|
||||
|
||||
|
||||
|
||||
/*PMC(0x4) = 0x7FFFF3;
|
||||
PMC(0x2C4) = 0xFFFFFFFF;
|
||||
PMC(0x2D8) = 0xFFAFFFFF;
|
||||
|
||||
413
ipl/main.c
413
ipl/main.c
@@ -48,14 +48,6 @@
|
||||
#include "pkg1.h"
|
||||
#include "mmc.h"
|
||||
|
||||
//TODO: ugly.
|
||||
gfx_ctxt_t gfx_ctxt;
|
||||
gfx_con_t gfx_con;
|
||||
|
||||
//TODO: Create more macros (info, header, debug, etc) with different colors and utilize them for consistency.
|
||||
#define EPRINTF(text) gfx_printf(&gfx_con, "%k"text"%k\n", 0xFF0000FF, 0xFFFFFFFF)
|
||||
#define EPRINTFARGS(text, args...) gfx_printf(&gfx_con, "%k"text"%k\n", 0xFF0000FF, args, 0xFFFFFFFF)
|
||||
|
||||
//TODO: ugly.
|
||||
sdmmc_t sd_sdmmc;
|
||||
sdmmc_storage_t sd_storage;
|
||||
@@ -67,38 +59,16 @@ int sd_mount()
|
||||
if (sd_mounted)
|
||||
return 1;
|
||||
|
||||
if (!sdmmc_storage_init_sd(&sd_storage, &sd_sdmmc, SDMMC_1, SDMMC_BUS_WIDTH_4, 11))
|
||||
if (sdmmc_storage_init_sd(&sd_storage, &sd_sdmmc, SDMMC_1, SDMMC_BUS_WIDTH_4, 11) &&
|
||||
f_mount(&sd_fs, "", 1) == FR_OK)
|
||||
{
|
||||
EPRINTF("Failed to init SD card (make sure that it is inserted).");
|
||||
}
|
||||
else
|
||||
{
|
||||
int res = 0;
|
||||
res = f_mount(&sd_fs, "", 1);
|
||||
if (res == FR_OK)
|
||||
{
|
||||
sd_mounted = 1;
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
EPRINTFARGS("Failed to mount SD card (FatFS Error %d).\n(make sure that a FAT32/exFAT partition exists)", res);
|
||||
}
|
||||
sd_mounted = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void sd_unmount()
|
||||
{
|
||||
if (sd_mounted)
|
||||
{
|
||||
gfx_puts(&gfx_con, "Unmounting SD card...\n");
|
||||
f_mount(NULL, "", 1);
|
||||
sdmmc_storage_end(&sd_storage);
|
||||
}
|
||||
}
|
||||
|
||||
void *sd_file_read(char *path)
|
||||
{
|
||||
FIL fp;
|
||||
@@ -127,20 +97,6 @@ void *sd_file_read(char *path)
|
||||
return buf;
|
||||
}
|
||||
|
||||
int sd_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 panic(u32 val)
|
||||
{
|
||||
//Set panic code.
|
||||
@@ -273,7 +229,7 @@ void config_se_brom()
|
||||
|
||||
void config_hw()
|
||||
{
|
||||
//Bootrom stuff we skipped by going through rcm.
|
||||
//Bootrom stuff we skipped by going thru rcm.
|
||||
config_se_brom();
|
||||
//FUSE(FUSE_PRIVATEKEYDISABLE) = 0x11;
|
||||
SYSREG(0x110) &= 0xFFFFFF9F;
|
||||
@@ -334,6 +290,10 @@ void config_hw()
|
||||
sdram_lp0_save_params(sdram_get_params());
|
||||
}
|
||||
|
||||
//TODO: ugly.
|
||||
gfx_ctxt_t gfx_ctxt;
|
||||
gfx_con_t gfx_con;
|
||||
|
||||
void print_fuseinfo()
|
||||
{
|
||||
gfx_clear(&gfx_ctxt, 0xFF000000);
|
||||
@@ -349,17 +309,25 @@ void print_fuseinfo()
|
||||
u32 btn = btn_wait();
|
||||
if (btn & BTN_POWER)
|
||||
{
|
||||
if (sd_mount())
|
||||
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 (sd_save_to_file((u8 *)0x7000F900, 0x2FC, fuseFilename))
|
||||
EPRINTF("\nError creating fuse.bin file.");
|
||||
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_puts(&gfx_con, "\nDone!\n");
|
||||
gfx_printf(&gfx_con, "%k\nError creating fuse.bin file.%k\n", 0xFF0000FF, 0xFFFFFFFF);
|
||||
}
|
||||
sleep(2000000);
|
||||
btn_wait();
|
||||
@@ -374,7 +342,7 @@ void print_kfuseinfo()
|
||||
gfx_printf(&gfx_con, "%kKFuse contents:\n\n%k", 0xFFFF9955, 0xFFFFFFFF);
|
||||
u32 buf[KFUSE_NUM_WORDS];
|
||||
if (!kfuse_read(buf))
|
||||
EPRINTF("CRC fail.");
|
||||
gfx_printf(&gfx_con, "%kCRC fail.\n", 0xFF0000FF);
|
||||
else
|
||||
gfx_hexdump(&gfx_con, 0, (u8 *)buf, KFUSE_NUM_WORDS * 4);
|
||||
|
||||
@@ -385,17 +353,25 @@ void print_kfuseinfo()
|
||||
u32 btn = btn_wait();
|
||||
if (btn & BTN_POWER)
|
||||
{
|
||||
if (sd_mount())
|
||||
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 (sd_save_to_file((u8 *)buf, KFUSE_NUM_WORDS * 4, kfuseFilename))
|
||||
EPRINTF("\nError creating kfuse.bin file.");
|
||||
else
|
||||
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();
|
||||
@@ -407,14 +383,14 @@ void print_mmc_info()
|
||||
gfx_clear(&gfx_ctxt, 0xFF000000);
|
||||
gfx_con_setpos(&gfx_con, 0, 0);
|
||||
|
||||
static const u32 SECTORS_TO_MIB_COEFF = 11;
|
||||
|
||||
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))
|
||||
{
|
||||
EPRINTF("Failed to init eMMC.");
|
||||
gfx_printf(&gfx_con, "%kFailed to init eMMC.%k\n", 0xFF0000FF, 0xFFFFFFFF);
|
||||
goto out;
|
||||
}
|
||||
else
|
||||
@@ -457,12 +433,12 @@ void print_mmc_info()
|
||||
storage.cid.prv, storage.cid.serial, storage.cid.month, storage.cid.year);
|
||||
break;
|
||||
default:
|
||||
EPRINTFARGS("eMMC has unknown MMCA version %d", storage.csd.mmca_vsn);
|
||||
gfx_printf(&gfx_con, "%keMMC has unknown MMCA version %d%k\n", 0xFF0000FF, storage.csd.mmca_vsn, 0xFFFFFFFF);
|
||||
break;
|
||||
}
|
||||
|
||||
if (storage.csd.structure == 0)
|
||||
EPRINTF("Unknown CSD structure.");
|
||||
gfx_printf(&gfx_con, "%kUnknown CSD structure%k\n", 0xFF0000FF, 0xFFFFFFFF);
|
||||
else
|
||||
{
|
||||
gfx_printf(&gfx_con, "%kExtended Card-Specific Data V1.%d:%k\n",
|
||||
@@ -523,9 +499,9 @@ void print_mmc_info()
|
||||
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);
|
||||
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);
|
||||
@@ -533,7 +509,7 @@ void print_mmc_info()
|
||||
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,
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -550,9 +526,14 @@ void print_sdcard_info()
|
||||
gfx_clear(&gfx_ctxt, 0xFF000000);
|
||||
gfx_con_setpos(&gfx_con, 0, 0);
|
||||
|
||||
static const u32 SECTORS_TO_MIB_COEFF = 11;
|
||||
static const u32 SECTORS_TO_MIB_COEFF = 0x800;
|
||||
|
||||
if (sd_mount())
|
||||
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;
|
||||
|
||||
@@ -572,25 +553,37 @@ void print_sdcard_info()
|
||||
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);
|
||||
capacity = sd_storage.csd.capacity >> (20 - sd_storage.csd.read_blkbits);
|
||||
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,
|
||||
" Cmd Classes: %02X\n\
|
||||
Capacity: %d MiB\n\
|
||||
Bus Width: %d\n\
|
||||
" Bus Width: %d\n\
|
||||
Speed Class: %d\n\
|
||||
UHS Grade: U%d\n\
|
||||
Video Class: V%d\n\
|
||||
App perf class: A%d\n\
|
||||
Write Protect: %d\n\n",
|
||||
sd_storage.csd.cmdclass, capacity,
|
||||
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, sd_storage.csd.write_protect);
|
||||
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 Cluster: %d B\n",
|
||||
0xFFFFDD00, sd_fs.fs_type == FS_EXFAT ? "exFAT" : "FAT32", 0xFFFFFFFF,
|
||||
sd_fs.free_clst * sd_fs.csize >> SECTORS_TO_MIB_COEFF, sd_fs.csize * 512);
|
||||
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);
|
||||
@@ -615,8 +608,8 @@ void print_tsec_key()
|
||||
const pkg1_id_t *pkg1_id = pkg1_identify(pkg1);
|
||||
if (!pkg1_id)
|
||||
{
|
||||
EPRINTFARGS("Could not identify package1 version to read TSEC firmware (= '%s').",
|
||||
(char *)pkg1 + 0x10);
|
||||
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 +625,7 @@ void print_tsec_key()
|
||||
gfx_printf(&gfx_con, "%02X", key[i]);
|
||||
}
|
||||
else
|
||||
EPRINTFARGS("ERROR %X", res);
|
||||
gfx_printf(&gfx_con, "%kERROR %X", 0xFF0000FF, res);
|
||||
gfx_putc(&gfx_con, '\n');
|
||||
}
|
||||
|
||||
@@ -645,13 +638,11 @@ out:;
|
||||
|
||||
void reboot_normal()
|
||||
{
|
||||
sd_unmount();
|
||||
panic(0x21); //Bypass fuse programming in package1.
|
||||
}
|
||||
|
||||
void reboot_rcm()
|
||||
{
|
||||
sd_unmount();
|
||||
PMC(APBDEV_PMC_SCRATCH0) = 2; //Reboot into rcm.
|
||||
PMC(0) |= 0x10;
|
||||
while (1)
|
||||
@@ -660,7 +651,6 @@ void reboot_rcm()
|
||||
|
||||
void power_off()
|
||||
{
|
||||
sd_unmount();
|
||||
//TODO: we should probably make sure all regulators are powered off properly.
|
||||
i2c_send_byte(I2C_5, 0x3C, MAX77620_REG_ONOFFCNFG1, MAX77620_ONOFFCNFG1_PWR_OFF);
|
||||
}
|
||||
@@ -668,9 +658,9 @@ void power_off()
|
||||
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 SECTORS_TO_MIB_COEFF = 11;
|
||||
static const u32 MULTIPART_SPLIT_SIZE = (1u << 31);
|
||||
static const u32 SECTORS_TO_MIB_COEFF = 0x800;
|
||||
|
||||
u32 multipartSplitSize = (1u << 31);
|
||||
u32 totalSectors = part->lba_end - part->lba_start + 1;
|
||||
u32 currPartIdx = 0;
|
||||
u32 numSplitParts = 0;
|
||||
@@ -678,6 +668,7 @@ int dump_emmc_part(char *sd_path, sdmmc_storage_t *storage, emmc_part_t *part)
|
||||
int isSmallSdCard = 0;
|
||||
int partialDumpInProgress = 0;
|
||||
int res = 0;
|
||||
int ignoreWriteErrors = 0;
|
||||
char* outFilename = sd_path;
|
||||
u32 sdPathLen = strlen(sd_path);
|
||||
|
||||
@@ -687,59 +678,49 @@ int dump_emmc_part(char *sd_path, sdmmc_storage_t *storage, emmc_part_t *part)
|
||||
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);
|
||||
|
||||
// 1GB parts for sd cards 8GB and less
|
||||
if ((sd_storage.csd.capacity >> (20 - sd_storage.csd.read_blkbits)) <= 8192)
|
||||
multipartSplitSize = (1u << 30);
|
||||
// Maximum parts fitting the free space available
|
||||
maxSplitParts = (sd_fs.free_clst * sd_fs.csize) / (multipartSplitSize / 512);
|
||||
sd_fs.free_clst * sd_fs.csize / SECTORS_TO_MIB_COEFF,
|
||||
totalSectors / SECTORS_TO_MIB_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))
|
||||
{
|
||||
isSmallSdCard = 1;
|
||||
|
||||
gfx_printf(&gfx_con, "%k\nSD card free space is smaller than dump total size.%k\n", 0xFF00BAFF, 0xFFFFFFFF);
|
||||
gfx_printf(&gfx_con, "%kSD card free space is smaller than dump total size.%k\n", 0xFF00BAFF, 0xFFFFFFFF);
|
||||
|
||||
maxSplitParts = (sd_fs.free_clst * sd_fs.csize) / (MULTIPART_SPLIT_SIZE / 512);
|
||||
|
||||
if (!maxSplitParts)
|
||||
{
|
||||
EPRINTF("Not enough free space for partial dumping.");
|
||||
gfx_printf(&gfx_con, "%kNot enough free space for partial dumping.%k\n", 0xFF0000FF, 0xFFFFFFFF);
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
// Check if we continuing a previous raw eMMC dump in progress.
|
||||
if (f_open(&partialIdxFp, partialIdxFilename, FA_READ) == FR_OK)
|
||||
// Check if we continueing a previous raw eMMC dump in progress.
|
||||
if (isSmallSdCard)
|
||||
{
|
||||
gfx_printf(&gfx_con, "%kFound partial dump in progress. Continuing...%k\n\n", 0xFF14FDAE, 0xFFFFFFFF);
|
||||
|
||||
partialDumpInProgress = 1;
|
||||
// Force partial dumping, even if the card is larger.
|
||||
isSmallSdCard = 1;
|
||||
|
||||
f_read(&partialIdxFp, &currPartIdx, 4, NULL);
|
||||
f_close(&partialIdxFp);
|
||||
|
||||
if (!maxSplitParts)
|
||||
if (f_open(&partialIdxFp, partialIdxFilename, FA_READ) == FR_OK)
|
||||
{
|
||||
EPRINTF("Not enough free space for partial dumping.");
|
||||
gfx_printf(&gfx_con, "%kFound partial dump in progress. Continuing...%k\n", 0xFF14FDAE, 0xFFFFFFFF);
|
||||
|
||||
return 0;
|
||||
partialDumpInProgress = 1;
|
||||
|
||||
f_read(&partialIdxFp, &currPartIdx, 4, NULL);
|
||||
f_close(&partialIdxFp);
|
||||
|
||||
// Increase maxSplitParts to accommodate previously dumped parts
|
||||
maxSplitParts += currPartIdx;
|
||||
}
|
||||
|
||||
// Increase maxSplitParts to accommodate previously dumped parts
|
||||
maxSplitParts += currPartIdx;
|
||||
else
|
||||
gfx_printf(&gfx_con, "%kContinuing with partial dumping...%k\n", 0xFF00BAFF, 0xFFFFFFFF);
|
||||
}
|
||||
else if (isSmallSdCard)
|
||||
gfx_printf(&gfx_con, "%kPartial dumping enabled (with %d MiB parts)...%k\n\n", 0xFF00BAFF, multipartSplitSize >> 20, 0xFFFFFFFF);
|
||||
|
||||
// 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) && totalSectors > (FAT32_FILESIZE_LIMIT/NX_EMMC_BLOCKSIZE)) | isSmallSdCard)
|
||||
{
|
||||
u32 multipartSplitSectors = multipartSplitSize / NX_EMMC_BLOCKSIZE;
|
||||
numSplitParts = (totalSectors + multipartSplitSectors - 1) / multipartSplitSectors;
|
||||
static const u32 MULTIPART_SPLIT_SECTORS = MULTIPART_SPLIT_SIZE/NX_EMMC_BLOCKSIZE;
|
||||
numSplitParts = (totalSectors+MULTIPART_SPLIT_SECTORS-1)/MULTIPART_SPLIT_SECTORS;
|
||||
|
||||
outFilename = alloca(sdPathLen+4);
|
||||
memcpy(outFilename, sd_path, sdPathLen);
|
||||
@@ -750,19 +731,19 @@ int dump_emmc_part(char *sd_path, sdmmc_storage_t *storage, emmc_part_t *part)
|
||||
outFilename[sdPathLen] = '0';
|
||||
if (numSplitParts >= 10)
|
||||
{
|
||||
outFilename[sdPathLen + 1] = '0';
|
||||
outFilename[sdPathLen + 2] = 0;
|
||||
outFilename[sdPathLen+1] = '0';
|
||||
outFilename[sdPathLen+2] = 0;
|
||||
}
|
||||
else
|
||||
outFilename[sdPathLen + 1] = 0;
|
||||
outFilename[sdPathLen+1] = 0;
|
||||
}
|
||||
// Continue from where we left, if partial dump in progress.
|
||||
// Continue from where we left, if partial dump in proggress.
|
||||
else
|
||||
{
|
||||
if (numSplitParts >= 10 && currPartIdx < 10)
|
||||
{
|
||||
outFilename[sdPathLen] = '0';
|
||||
itoa(currPartIdx, &outFilename[sdPathLen + 1], 10);
|
||||
itoa(currPartIdx, &outFilename[sdPathLen+1], 10);
|
||||
}
|
||||
else
|
||||
itoa(currPartIdx, &outFilename[sdPathLen], 10);
|
||||
@@ -771,11 +752,7 @@ int dump_emmc_part(char *sd_path, sdmmc_storage_t *storage, emmc_part_t *part)
|
||||
|
||||
FIL fp;
|
||||
if (f_open(&fp, outFilename, FA_CREATE_ALWAYS | FA_WRITE) != FR_OK)
|
||||
{
|
||||
EPRINTFARGS("Error creating file %s.", outFilename);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const u32 NUM_SECTORS_PER_ITER = 512;
|
||||
u8 *buf = (u8 *)malloc(NX_EMMC_BLOCKSIZE * NUM_SECTORS_PER_ITER);
|
||||
@@ -785,16 +762,16 @@ int dump_emmc_part(char *sd_path, sdmmc_storage_t *storage, emmc_part_t *part)
|
||||
u32 prevPct = 200;
|
||||
int retryCount = 0;
|
||||
|
||||
// Continue from where we left, if partial dump in progress.
|
||||
// Continue from where we left, if partial dump in proggress.
|
||||
if (partialDumpInProgress)
|
||||
{
|
||||
lba_curr += currPartIdx * (multipartSplitSize / NX_EMMC_BLOCKSIZE);
|
||||
totalSectors -= currPartIdx * (multipartSplitSize / NX_EMMC_BLOCKSIZE);
|
||||
lba_curr += currPartIdx * (MULTIPART_SPLIT_SIZE / NX_EMMC_BLOCKSIZE);
|
||||
totalSectors -= currPartIdx * (MULTIPART_SPLIT_SIZE / NX_EMMC_BLOCKSIZE);
|
||||
}
|
||||
|
||||
while(totalSectors > 0)
|
||||
{
|
||||
if (numSplitParts != 0 && bytesWritten >= multipartSplitSize)
|
||||
if (numSplitParts != 0 && bytesWritten >= MULTIPART_SPLIT_SIZE)
|
||||
{
|
||||
f_close(&fp);
|
||||
memset(&fp, 0, sizeof(fp));
|
||||
@@ -803,13 +780,13 @@ int dump_emmc_part(char *sd_path, sdmmc_storage_t *storage, emmc_part_t *part)
|
||||
if (numSplitParts >= 10 && currPartIdx < 10)
|
||||
{
|
||||
outFilename[sdPathLen] = '0';
|
||||
itoa(currPartIdx, &outFilename[sdPathLen + 1], 10);
|
||||
itoa(currPartIdx, &outFilename[sdPathLen+1], 10);
|
||||
}
|
||||
else
|
||||
itoa(currPartIdx, &outFilename[sdPathLen], 10);
|
||||
|
||||
// Always create partial.idx before next part, in case a fatal error occurs.
|
||||
if (isSmallSdCard)
|
||||
// More parts to dump that do not currently fit the sd card free space
|
||||
if ((isSmallSdCard && currPartIdx >= maxSplitParts) || (res && !ignoreWriteErrors))
|
||||
{
|
||||
// Create partial dump index file
|
||||
if (f_open(&partialIdxFp, partialIdxFilename, FA_CREATE_ALWAYS | FA_WRITE) == FR_OK)
|
||||
@@ -819,31 +796,32 @@ int dump_emmc_part(char *sd_path, sdmmc_storage_t *storage, emmc_part_t *part)
|
||||
}
|
||||
else
|
||||
{
|
||||
EPRINTF("\nError creating partial.idx file.");
|
||||
gfx_printf(&gfx_con, "%k\nError creating partial.idx file.%k\n", 0xFF0000FF, 0xFFFFFFFF);
|
||||
|
||||
free(buf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// More parts to dump that do not currently fit the sd card free space or fatal error
|
||||
if (currPartIdx >= maxSplitParts)
|
||||
// Sd card fatal error.
|
||||
if (res && !ignoreWriteErrors)
|
||||
{
|
||||
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\
|
||||
Don\'t move the partial.idx file!\n\
|
||||
3. Unplug and re-plug USB while pressing Vol+.\n\
|
||||
4. Run hekate - ipl again and press Dump RAW eMMC or eMMC USER to continue\n");
|
||||
gfx_printf(&gfx_con, "%k\nPress any key and try again.%k\n",
|
||||
0xFF0000FF, 0xFFFFFFFF);
|
||||
|
||||
free(buf);
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
gfx_puts(&gfx_con, "\n1. Press any key and Power off Switch from the main menu.\n\
|
||||
2. Move the files from SD card 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 - ipl again and press Dump RAW eMMC or eMMC USER to continue");
|
||||
|
||||
free(buf);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Create next part
|
||||
if (f_open(&fp, outFilename, FA_CREATE_ALWAYS | FA_WRITE) != FR_OK)
|
||||
{
|
||||
EPRINTFARGS("Error creating file %s.", outFilename);
|
||||
|
||||
free(buf);
|
||||
return 0;
|
||||
}
|
||||
@@ -854,43 +832,44 @@ int dump_emmc_part(char *sd_path, sdmmc_storage_t *storage, emmc_part_t *part)
|
||||
u32 num = MIN(totalSectors, NUM_SECTORS_PER_ITER);
|
||||
while(!sdmmc_storage_read(storage, lba_curr, num, buf))
|
||||
{
|
||||
EPRINTFARGS("Error reading %d blocks @ LBA %08X from eMMC (try %d)",
|
||||
num, lba_curr, ++retryCount);
|
||||
gfx_printf(&gfx_con, "%kError reading %d blocks @ LBA %08X from eMMC (try %d)%k\n",
|
||||
0xFF0000FF, num, lba_curr, ++retryCount, 0xFFFFFFFF);
|
||||
|
||||
sleep(500000);
|
||||
if (retryCount >= 10)
|
||||
{
|
||||
EPRINTFARGS("\nFailed to read %d blocks @ LBA %08X from eMMC. Aborting..",
|
||||
num, lba_curr);
|
||||
|
||||
free(buf);
|
||||
f_close(&fp);
|
||||
return 0;
|
||||
}
|
||||
goto out;
|
||||
}
|
||||
res = f_write(&fp, buf, NX_EMMC_BLOCKSIZE * num, NULL);
|
||||
if (res)
|
||||
if (res && !ignoreWriteErrors)
|
||||
{
|
||||
EPRINTFARGS("\nFatal error (%d) when writing to SD Card", res);
|
||||
EPRINTF("\nPress any key and try again.");
|
||||
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",
|
||||
0xFF0000FF, res, 0xFFFFFFFF);
|
||||
u32 btn = btn_wait();
|
||||
|
||||
free(buf);
|
||||
f_close(&fp);
|
||||
return 0;
|
||||
if (btn & BTN_POWER)
|
||||
{
|
||||
ignoreWriteErrors = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
bytesWritten = MULTIPART_SPLIT_SIZE - num * NX_EMMC_BLOCKSIZE;
|
||||
currPartIdx--;
|
||||
}
|
||||
}
|
||||
u32 pct = (u64)((u64)(lba_curr - part->lba_start) * 100u) / (u64)(part->lba_end - part->lba_start);
|
||||
if (pct != prevPct)
|
||||
{
|
||||
tui_pbar(&gfx_con, 0, gfx_con.y, pct);
|
||||
prevPct = pct;
|
||||
}
|
||||
}
|
||||
|
||||
lba_curr += num;
|
||||
totalSectors -= num;
|
||||
bytesWritten += num * NX_EMMC_BLOCKSIZE;
|
||||
|
||||
// Force a flush after a lot of data if not splitting
|
||||
if (numSplitParts == 0 && bytesWritten >= multipartSplitSize)
|
||||
//force a flush after a lot of data if not splitting
|
||||
if (numSplitParts == 0 && bytesWritten >= MULTIPART_SPLIT_SIZE)
|
||||
{
|
||||
f_sync(&fp);
|
||||
bytesWritten = 0;
|
||||
@@ -901,8 +880,8 @@ int dump_emmc_part(char *sd_path, sdmmc_storage_t *storage, emmc_part_t *part)
|
||||
out:;
|
||||
free(buf);
|
||||
f_close(&fp);
|
||||
// Remove partial dump index file if no fatal errors occurred.
|
||||
if(isSmallSdCard)
|
||||
// Partial dump done. Remove partial dump index file.
|
||||
if(partialDumpInProgress)
|
||||
{
|
||||
f_unlink(partialIdxFilename);
|
||||
gfx_printf(&gfx_con, "\n\nYou can now join the files and get the complete raw eMMC dump.");
|
||||
@@ -922,37 +901,41 @@ typedef enum
|
||||
|
||||
static void dump_emmc_selected(dumpType_t dumpType)
|
||||
{
|
||||
int res = 0;
|
||||
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);
|
||||
goto out;
|
||||
|
||||
gfx_puts(&gfx_con, "Checking for available free space...\n\n");
|
||||
// Get SD Card free space for partial dumping
|
||||
f_getfree("", &sd_fs.free_clst, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
gfx_puts(&gfx_con, "Checking for available free space...\n");
|
||||
// Get SD Card free space for partial dumping
|
||||
f_getfree("", &sd_fs.free_clst, NULL);
|
||||
}
|
||||
|
||||
sdmmc_storage_t storage;
|
||||
sdmmc_t sdmmc;
|
||||
if(!sdmmc_storage_init_mmc(&storage, &sdmmc, SDMMC_4, SDMMC_BUS_WIDTH_8, 4))
|
||||
{
|
||||
EPRINTF("Failed to init eMMC.");
|
||||
gfx_printf(&gfx_con, "%kFailed to init eMMC.%k\n", 0xFF0000FF, 0xFFFFFFFF);
|
||||
goto out;
|
||||
}
|
||||
|
||||
int i = 0;
|
||||
timer = get_tmr();
|
||||
if (dumpType & DUMP_BOOT)
|
||||
{
|
||||
{
|
||||
static const u32 BOOT_PART_SIZE = 0x400000;
|
||||
|
||||
emmc_part_t bootPart;
|
||||
memset(&bootPart, 0, sizeof(bootPart));
|
||||
bootPart.lba_start = 0;
|
||||
bootPart.lba_end = (BOOT_PART_SIZE/NX_EMMC_BLOCKSIZE)-1;
|
||||
for (i = 0; i < 2; i++)
|
||||
for (i=0; i<2; i++)
|
||||
{
|
||||
memcpy(bootPart.name, "BOOT", 4);
|
||||
bootPart.name[4] = (u8)('0' + i);
|
||||
@@ -962,8 +945,9 @@ static void dump_emmc_selected(dumpType_t dumpType)
|
||||
bootPart.name, bootPart.lba_start, bootPart.lba_end, 0xFFFFFFFF);
|
||||
|
||||
sdmmc_storage_set_mmc_partition(&storage, i+1);
|
||||
res = dump_emmc_part(bootPart.name, &storage, &bootPart);
|
||||
}
|
||||
dump_emmc_part(bootPart.name, &storage, &bootPart);
|
||||
gfx_putc(&gfx_con, '\n');
|
||||
}
|
||||
}
|
||||
|
||||
if ((dumpType & DUMP_SYSTEM) || (dumpType & DUMP_USER) || (dumpType & DUMP_RAW))
|
||||
@@ -984,10 +968,11 @@ static void dump_emmc_selected(dumpType_t dumpType)
|
||||
gfx_printf(&gfx_con, "%k%02d: %s (%08X-%08X)%k\n", 0xFFFFDD00, i++,
|
||||
part->name, part->lba_start, part->lba_end, 0xFFFFFFFF);
|
||||
|
||||
res = dump_emmc_part(part->name, &storage, part);
|
||||
dump_emmc_part(part->name, &storage, part);
|
||||
gfx_putc(&gfx_con, '\n');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (dumpType & DUMP_RAW)
|
||||
{
|
||||
static const u32 RAW_AREA_NUM_SECTORS = 0x3A3E000;
|
||||
@@ -1001,16 +986,15 @@ static void dump_emmc_selected(dumpType_t dumpType)
|
||||
gfx_printf(&gfx_con, "%k%02d: %s (%08X-%08X)%k\n", 0xFFFFDD00, i++,
|
||||
rawPart.name, rawPart.lba_start, rawPart.lba_end, 0xFFFFFFFF);
|
||||
|
||||
res = dump_emmc_part(rawPart.name, &storage, &rawPart);
|
||||
}
|
||||
dump_emmc_part(rawPart.name, &storage, &rawPart);
|
||||
gfx_putc(&gfx_con, '\n');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
gfx_putc(&gfx_con, '\n');
|
||||
gfx_printf(&gfx_con, "%kTime taken: %d seconds.%k\n", 0xFF00FF96, (get_tmr() - timer) / 1000000, 0xFFFFFFFF);
|
||||
sdmmc_storage_end(&storage);
|
||||
if (res)
|
||||
gfx_puts(&gfx_con, "\nDone. Press any key.\n");
|
||||
gfx_puts(&gfx_con, "\nDone. Press any key.\n");
|
||||
|
||||
out:;
|
||||
sleep(1000000);
|
||||
@@ -1022,7 +1006,21 @@ 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); }
|
||||
|
||||
void dump_package1()
|
||||
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);
|
||||
@@ -1032,13 +1030,16 @@ void dump_package1()
|
||||
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))
|
||||
{
|
||||
EPRINTF("Failed to init eMMC.");
|
||||
gfx_printf(&gfx_con, "%kFailed to init eMMC.%k\n", 0xFF0000FF, 0xFFFFFFFF);
|
||||
goto out;
|
||||
}
|
||||
sdmmc_storage_set_mmc_partition(&storage, 1);
|
||||
@@ -1049,7 +1050,7 @@ void dump_package1()
|
||||
const pk11_hdr_t *hdr = (pk11_hdr_t *)(pkg1 + pkg1_id->pkg11_off + 0x20);
|
||||
if (!pkg1_id)
|
||||
{
|
||||
EPRINTFARGS("Could not identify package1 version to read TSEC firmware (= '%s').", (char *)pkg1 + 0x10);
|
||||
gfx_printf(&gfx_con, "%kCould not identify package 1 version to read TSEC firmware (= '%s').%k\n", 0xFF0000FF, (char *)pkg1 + 0x10, 0xFFFFFFFF);
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -1065,26 +1066,26 @@ void dump_package1()
|
||||
pkg1_unpack(warmboot, secmon, pkg1_id, pkg1);
|
||||
|
||||
// display info
|
||||
gfx_printf(&gfx_con, "%kSecure monitor addr: %08X\n", 0xFF00FFA8, pkg1_id->secmon_base);
|
||||
gfx_printf(&gfx_con, "%kSecure monitor size: %08X\n", 0xFF00FFA8, hdr->sm_size);
|
||||
gfx_printf(&gfx_con, "%kSecure monitor off: %08X\n", 0xFF00FFA8, hdr->sm_off);
|
||||
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 (sd_save_to_file(pkg1, 0x40000, "pkg_decr.bin")) {
|
||||
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");
|
||||
gfx_puts(&gfx_con, "%kPackage1 dumped to pkg_decr.bin\n");
|
||||
|
||||
// dump sm
|
||||
if (sd_save_to_file(secmon, 0x40000, "sm.bin")) {
|
||||
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 (sd_save_to_file(warmboot, 0x40000, "warmboot.bin")) {
|
||||
if (save_to_file(warmboot, 0x40000, "warmboot.bin") == -1) {
|
||||
gfx_puts(&gfx_con, "Failed to create warmboot.bin\n");
|
||||
goto out;
|
||||
}
|
||||
@@ -1139,18 +1140,20 @@ void launch_firmware()
|
||||
return;
|
||||
}
|
||||
else
|
||||
EPRINTF("No launch configurations found.");
|
||||
gfx_printf(&gfx_con, "%kNo launch configurations found.%k\n", 0xFF0000FF, 0xFFFFFFFF);
|
||||
free(ments);
|
||||
}
|
||||
else
|
||||
EPRINTF("Failed to load 'hekate_ipl.ini'.");
|
||||
gfx_printf(&gfx_con, "%kFailed to load 'hekate_ipl.ini'.%k\n", 0xFF0000FF, 0xFFFFFFFF);
|
||||
}
|
||||
else
|
||||
gfx_printf(&gfx_con, "%kFailed to mount SD card (make sure that it is inserted).%k\n", 0xFF0000FF, 0xFFFFFFFF);
|
||||
|
||||
if (!cfg_sec)
|
||||
gfx_printf(&gfx_con, "Using default launch configuration.\n");
|
||||
|
||||
if (!hos_launch(cfg_sec))
|
||||
EPRINTF("Failed to launch firmware.");
|
||||
gfx_printf(&gfx_con, "%kFailed to launch firmware.%k\n", 0xFF0000FF, 0xFFFFFFFF);
|
||||
|
||||
//TODO: free ini.
|
||||
|
||||
@@ -1190,7 +1193,7 @@ void about()
|
||||
gfx_clear(&gfx_ctxt, 0xFF000000);
|
||||
gfx_con_setpos(&gfx_con, 0, 0);
|
||||
|
||||
gfx_printf(&gfx_con, octopus, 0xFFFFCC00, 0xFFFFFFFF,
|
||||
gfx_printf(&gfx_con, octopus, 0xFFFFCC00, 0xFFFFFFFF,
|
||||
0xFFFFCC00, 0xFFCCFF00, 0xFFFFCC00, 0xFFFFFFFF);
|
||||
|
||||
sleep(1000000);
|
||||
@@ -1217,7 +1220,7 @@ 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_HANDLER("Dump Package1", dump_package1),
|
||||
MDEF_END()
|
||||
};
|
||||
menu_t menu_tools = {
|
||||
@@ -1237,7 +1240,7 @@ ment_t ment_top[] = {
|
||||
};
|
||||
menu_t menu_top = {
|
||||
ment_top,
|
||||
"hekate - ipl", 0, 0
|
||||
"hekate - ipl (CTCaer mod v1.3)", 0, 0
|
||||
};
|
||||
|
||||
extern void pivot_stack(u32 stack_top);
|
||||
|
||||
11
ipl/pkg1.c
11
ipl/pkg1.c
@@ -30,21 +30,21 @@ PATCHSET_DEF(_secmon_1_patchset,
|
||||
//Patch package2 decryption and signature/hash checks.
|
||||
{ 0x9F0 + 0xADC, _NOP() }, //Header signature.
|
||||
{ 0x9F0 + 0xB8C, _NOP() }, //Version.
|
||||
{ 0x9F0 + 0xBB0, _NOP() } //Sections SHA2.
|
||||
{ 0x9F0 + 0xBB0, _NOP() } //Sections SHA2.
|
||||
);
|
||||
|
||||
PATCHSET_DEF(_secmon_2_patchset,
|
||||
//Patch package2 decryption and signature/hash checks.
|
||||
{ 0xAC8 + 0xAAC, _NOP() }, //Header signature.
|
||||
{ 0xAC8 + 0xB3C, _NOP() }, //Version.
|
||||
{ 0xAC8 + 0xB58, _NOP() } //Sections SHA2.
|
||||
{ 0xAC8 + 0xB58, _NOP() } //Sections SHA2.
|
||||
);
|
||||
|
||||
PATCHSET_DEF(_secmon_3_patchset,
|
||||
//Patch package2 decryption and signature/hash checks.
|
||||
{ 0xAC8 + 0xA30, _NOP() }, //Header signature.
|
||||
{ 0xAC8 + 0xAC0, _NOP() }, //Version.
|
||||
{ 0xAC8 + 0xADC, _NOP() } //Sections SHA2.
|
||||
{ 0xAC8 + 0xADC, _NOP() } //Sections SHA2.
|
||||
);
|
||||
|
||||
PATCHSET_DEF(_secmon_5_patchset,
|
||||
@@ -52,11 +52,10 @@ PATCHSET_DEF(_secmon_5_patchset,
|
||||
{ 0x1218 + 0x6E68, _NOP() }, //Header signature.
|
||||
{ 0x1218 + 0x6E74, _NOP() }, //Version.
|
||||
{ 0x1218 + 0x6FE4, _NOP() }, //Sections SHA2.
|
||||
{ 0x1218 + 0x2DC, _NOP() } //Unknown.
|
||||
{ 0x1218 + 0x2DC, _NOP() } //Unknown.
|
||||
);
|
||||
|
||||
PATCHSET_DEF(_secmon_6_patchset,
|
||||
//Patch package2 decryption and signature/hash checks.
|
||||
{ 0x12b0 + 0x4d0, _NOP() },
|
||||
{ 0x12b0 + 0x4dc, _NOP() },
|
||||
{ 0x12b0 + 0x794, _NOP() },
|
||||
@@ -79,7 +78,7 @@ 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
|
||||
{ "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
|
||||
{ NULL, 0, 0, 0, 0 } //End.
|
||||
|
||||
@@ -42,6 +42,7 @@ typedef struct _pkg1_id_t
|
||||
patch_t *secmon_patchset;
|
||||
} pkg1_id_t;
|
||||
|
||||
|
||||
typedef struct _pk11_hdr_t
|
||||
{
|
||||
u32 magic;
|
||||
|
||||
47
ipl/sdmmc.c
47
ipl/sdmmc.c
@@ -187,7 +187,7 @@ int sdmmc_storage_write(sdmmc_storage_t *storage, u32 sector, u32 num_sectors, v
|
||||
}
|
||||
|
||||
/*
|
||||
* MMC specific functions.
|
||||
* MMC specific functions.
|
||||
*/
|
||||
|
||||
static int _mmc_storage_get_op_cond_inner(sdmmc_storage_t *storage, u32 *pout, u32 power)
|
||||
@@ -605,7 +605,7 @@ static int _sd_storage_get_op_cond(sdmmc_storage_t *storage, int is_version_1, i
|
||||
if (cond & SD_ROCR_S18A && supports_low_voltage)
|
||||
{
|
||||
//The low voltage regulator configuration is valid for SDMMC1 only.
|
||||
if (storage->sdmmc->id == SDMMC_1 &&
|
||||
if (storage->sdmmc->id == SDMMC_1 &&
|
||||
_sdmmc_storage_execute_cmd_type1(storage, SD_SWITCH_VOLTAGE, 0, 0, R1_STATE_READY))
|
||||
{
|
||||
if (!sdmmc_enable_low_voltage(storage->sdmmc))
|
||||
@@ -824,22 +824,9 @@ int _sd_storage_enable_highspeed_high_volt(sdmmc_storage_t *storage, u8 *buf)
|
||||
|
||||
static void _sd_storage_parse_ssr(sdmmc_storage_t *storage)
|
||||
{
|
||||
// unstuff_bits supports only 4 u32 so break into 2 x 16byte groups
|
||||
u32 raw_ssr1[4];
|
||||
u32 raw_ssr2[4];
|
||||
|
||||
raw_ssr1[3] = *(u32 *)&storage->raw_ssr[12];
|
||||
raw_ssr1[2] = *(u32 *)&storage->raw_ssr[8];
|
||||
raw_ssr1[1] = *(u32 *)&storage->raw_ssr[4];
|
||||
raw_ssr1[0] = *(u32 *)&storage->raw_ssr[0];
|
||||
|
||||
raw_ssr2[3] = *(u32 *)&storage->raw_ssr[28];
|
||||
raw_ssr2[2] = *(u32 *)&storage->raw_ssr[24];
|
||||
raw_ssr2[1] = *(u32 *)&storage->raw_ssr[20];
|
||||
raw_ssr2[0] = *(u32 *)&storage->raw_ssr[16];
|
||||
|
||||
storage->ssr.bus_width = unstuff_bits(raw_ssr1, 510 - 384, 2) & SD_BUS_WIDTH_4 ? 4 : 1;
|
||||
switch(unstuff_bits(raw_ssr1, 440 - 384, 8))
|
||||
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;
|
||||
@@ -857,13 +844,12 @@ static void _sd_storage_parse_ssr(sdmmc_storage_t *storage)
|
||||
storage->ssr.speed_class = 10;
|
||||
break;
|
||||
default:
|
||||
storage->ssr.speed_class = unstuff_bits(raw_ssr1, 440 - 384, 8);
|
||||
storage->ssr.speed_class = unstuff_bits(raw_ssr, 440 - 384, 8);
|
||||
break;
|
||||
}
|
||||
storage->ssr.uhs_grade = unstuff_bits(raw_ssr1, 396 - 384, 4);
|
||||
storage->ssr.video_class = unstuff_bits(raw_ssr1, 384 - 384, 8);
|
||||
|
||||
storage->ssr.app_class = unstuff_bits(raw_ssr2, 336 - 256, 4);
|
||||
storage->ssr.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)
|
||||
@@ -908,17 +894,17 @@ 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.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.hwrev = unstuff_bits(raw_cid, 60, 4);
|
||||
storage->cid.fwrev = unstuff_bits(raw_cid, 56, 4);
|
||||
storage->cid.serial = unstuff_bits(raw_cid, 24, 32);
|
||||
storage->cid.month = unstuff_bits(raw_cid, 8, 4);
|
||||
storage->cid.year = unstuff_bits(raw_cid, 12, 8) + 2000;
|
||||
storage->cid.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)
|
||||
@@ -926,9 +912,8 @@ 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);
|
||||
storage->csd.write_protect = unstuff_bits(raw_csd, 12, 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:
|
||||
|
||||
21
ipl/sdmmc.h
21
ipl/sdmmc.h
@@ -36,17 +36,16 @@ typedef struct _mmc_cid
|
||||
|
||||
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;
|
||||
u8 write_protect;
|
||||
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
|
||||
|
||||
1
ipl/se.h
1
ipl/se.h
@@ -26,5 +26,4 @@ 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);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -68,14 +68,10 @@ void *tui_do_menu(gfx_con_t *con, menu_t *menu)
|
||||
|
||||
u32 btn = btn_wait();
|
||||
|
||||
if (btn & BTN_VOL_DOWN && idx < (cnt - 1))
|
||||
if (btn & BTN_VOL_DOWN && idx < cnt - 1)
|
||||
idx++;
|
||||
else if (btn & BTN_VOL_DOWN && idx == (cnt - 1))
|
||||
idx = 0;
|
||||
if (btn & BTN_VOL_UP && idx > 0)
|
||||
idx--;
|
||||
else if (btn & BTN_VOL_UP && idx == 0)
|
||||
idx = cnt - 1;
|
||||
if (btn & BTN_POWER)
|
||||
{
|
||||
ment_t *ent = &menu->ents[idx];
|
||||
|
||||
Reference in New Issue
Block a user