Merge changes from master, added support for netloader companion (payload must be "nlc.bin" and will be deleted after being read, moved exception vectors

This commit is contained in:
Aurora 2016-05-03 16:57:00 +02:00
commit 169b12fc20
38 changed files with 242 additions and 7517 deletions

View File

@ -18,7 +18,7 @@ dir_build := build
ASFLAGS := -mcpu=arm946e-s
CFLAGS := -Wall -Wextra -MMD -MP -mthumb -mthumb-interwork $(ASFLAGS) -fno-builtin -std=c11 -Wno-main -O2 -flto -ffast-math
LDFLAGS := -nostartfiles
LDFLAGS := -nostdlib
objects = $(patsubst $(dir_source)/%.s, $(dir_build)/%.o, \
$(patsubst $(dir_source)/%.c, $(dir_build)/%.o, \
@ -37,6 +37,8 @@ $(name).bin: $(dir_build)/$(name).elf
$(dir_build)/$(name).elf: $(objects)
$(LINK.o) -T linker.ld $(OUTPUT_OPTION) $^
$(dir_build)/memory.o: CFLAGS += -O3
$(dir_build)/%.o: $(dir_source)/%.c
@mkdir -p "$(@D)"
$(COMPILE.c) $(OUTPUT_OPTION) $<

View File

@ -1,7 +1,7 @@
ENTRY(_start)
SECTIONS
{
. = 0x24F00000;
. = 0x24FFFB00;
.text.start : { *(.text.start) }
.text : { *(.text) }
.data : { *(.data) }

View File

@ -1,254 +0,0 @@
----------------------------------------------------------------------------
Revision history of FatFs module
----------------------------------------------------------------------------
R0.00 (February 26, 2006)
Prototype.
R0.01 (April 29, 2006)
First stable version.
R0.02 (June 01, 2006)
Added FAT12 support.
Removed unbuffered mode.
Fixed a problem on small (<32M) partition.
R0.02a (June 10, 2006)
Added a configuration option (_FS_MINIMUM).
R0.03 (September 22, 2006)
Added f_rename().
Changed option _FS_MINIMUM to _FS_MINIMIZE.
R0.03a (December 11, 2006)
Improved cluster scan algorithm to write files fast.
Fixed f_mkdir() creates incorrect directory on FAT32.
R0.04 (February 04, 2007)
Added f_mkfs().
Supported multiple drive system.
Changed some interfaces for multiple drive system.
Changed f_mountdrv() to f_mount().
R0.04a (April 01, 2007)
Supported multiple partitions on a physical drive.
Added a capability of extending file size to f_lseek().
Added minimization level 3.
Fixed an endian sensitive code in f_mkfs().
R0.04b (May 05, 2007)
Added a configuration option _USE_NTFLAG.
Added FSINFO support.
Fixed DBCS name can result FR_INVALID_NAME.
Fixed short seek (<= csize) collapses the file object.
R0.05 (August 25, 2007)
Changed arguments of f_read(), f_write() and f_mkfs().
Fixed f_mkfs() on FAT32 creates incorrect FSINFO.
Fixed f_mkdir() on FAT32 creates incorrect directory.
R0.05a (February 03, 2008)
Added f_truncate() and f_utime().
Fixed off by one error at FAT sub-type determination.
Fixed btr in f_read() can be mistruncated.
Fixed cached sector is not flushed when create and close without write.
R0.06 (April 01, 2008)
Added fputc(), fputs(), fprintf() and fgets().
Improved performance of f_lseek() on moving to the same or following cluster.
R0.07 (April 01, 2009)
Merged Tiny-FatFs as a configuration option. (_FS_TINY)
Added long file name feature. (_USE_LFN)
Added multiple code page feature. (_CODE_PAGE)
Added re-entrancy for multitask operation. (_FS_REENTRANT)
Added auto cluster size selection to f_mkfs().
Added rewind option to f_readdir().
Changed result code of critical errors.
Renamed string functions to avoid name collision.
R0.07a (April 14, 2009)
Septemberarated out OS dependent code on reentrant cfg.
Added multiple sector size feature.
R0.07c (June 21, 2009)
Fixed f_unlink() can return FR_OK on error.
Fixed wrong cache control in f_lseek().
Added relative path feature.
Added f_chdir() and f_chdrive().
Added proper case conversion to extended character.
R0.07e (November 03, 2009)
Septemberarated out configuration options from ff.h to ffconf.h.
Fixed f_unlink() fails to remove a sub-directory on _FS_RPATH.
Fixed name matching error on the 13 character boundary.
Added a configuration option, _LFN_UNICODE.
Changed f_readdir() to return the SFN with always upper case on non-LFN cfg.
R0.08 (May 15, 2010)
Added a memory configuration option. (_USE_LFN = 3)
Added file lock feature. (_FS_SHARE)
Added fast seek feature. (_USE_FASTSEEK)
Changed some types on the API, XCHAR->TCHAR.
Changed .fname in the FILINFO structure on Unicode cfg.
String functions support UTF-8 encoding files on Unicode cfg.
R0.08a (August 16, 2010)
Added f_getcwd(). (_FS_RPATH = 2)
Added sector erase feature. (_USE_ERASE)
Moved file lock semaphore table from fs object to the bss.
Fixed f_mkfs() creates wrong FAT32 volume.
R0.08b (January 15, 2011)
Fast seek feature is also applied to f_read() and f_write().
f_lseek() reports required table size on creating CLMP.
Extended format syntax of f_printf().
Ignores duplicated directory separators in given path name.
R0.09 (September 06, 2011)
f_mkfs() supports multiple partition to complete the multiple partition feature.
Added f_fdisk().
R0.09a (August 27, 2012)
Changed f_open() and f_opendir() reject null object pointer to avoid crash.
Changed option name _FS_SHARE to _FS_LOCK.
Fixed assertion failure due to OS/2 EA on FAT12/16 volume.
R0.09b (January 24, 2013)
Added f_setlabel() and f_getlabel().
R0.10 (October 02, 2013)
Added selection of character encoding on the file. (_STRF_ENCODE)
Added f_closedir().
Added forced full FAT scan for f_getfree(). (_FS_NOFSINFO)
Added forced mount feature with changes of f_mount().
Improved behavior of volume auto detection.
Improved write throughput of f_puts() and f_printf().
Changed argument of f_chdrive(), f_mkfs(), disk_read() and disk_write().
Fixed f_write() can be truncated when the file size is close to 4GB.
Fixed f_open(), f_mkdir() and f_setlabel() can return incorrect value on error.
R0.10a (January 15, 2014)
Added arbitrary strings as drive number in the path name. (_STR_VOLUME_ID)
Added a configuration option of minimum sector size. (_MIN_SS)
2nd argument of f_rename() can have a drive number and it will be ignored.
Fixed f_mount() with forced mount fails when drive number is >= 1. (appeared at R0.10)
Fixed f_close() invalidates the file object without volume lock.
Fixed f_closedir() returns but the volume lock is left acquired. (appeared at R0.10)
Fixed creation of an entry with LFN fails on too many SFN collisions. (appeared at R0.07)
R0.10b (May 19, 2014)
Fixed a hard error in the disk I/O layer can collapse the directory entry.
Fixed LFN entry is not deleted on delete/rename an object with lossy converted SFN. (appeared at R0.07)
R0.10c (November 09, 2014)
Added a configuration option for the platforms without RTC. (_FS_NORTC)
Changed option name _USE_ERASE to _USE_TRIM.
Fixed volume label created by Mac OS X cannot be retrieved with f_getlabel(). (appeared at R0.09b)
Fixed a potential problem of FAT access that can appear on disk error.
Fixed null pointer dereference on attempting to delete the root direcotry. (appeared at R0.08)
R0.11 (February 09, 2015)
Added f_findfirst(), f_findnext() and f_findclose(). (_USE_FIND)
Fixed f_unlink() does not remove cluster chain of the file. (appeared at R0.10c)
Fixed _FS_NORTC option does not work properly. (appeared at R0.10c)
R0.11a (September 05, 2015)
Fixed wrong media change can lead a deadlock at thread-safe configuration.
Added code page 771, 860, 861, 863, 864, 865 and 869. (_CODE_PAGE)
Removed some code pages actually not exist on the standard systems. (_CODE_PAGE)
Fixed errors in the case conversion teble of code page 437 and 850 (ff.c).
Fixed errors in the case conversion teble of Unicode (cc*.c).
R0.12 (April 12, 2016)
Added support of exFAT file system. (_FS_EXFAT)
Added f_expand(). (_USE_EXPAND)
Changed some members in FINFO structure and behavior of f_readdir().
Added an option _USE_CHMOD and removed an option _WORD_ACCESS.
Fixed errors in the case conversion teble of Unicode (cc*.c).

View File

@ -1,21 +0,0 @@
FatFs Module Source Files R0.12
FILES
00readme.txt This file.
history.txt Revision history.
ffconf.h Configuration file for FatFs module.
ff.h Common include file for FatFs and application module.
ff.c FatFs module.
diskio.h Common include file for FatFs and disk I/O module.
diskio.c An example of glue function to attach existing disk I/O module to FatFs.
integer.h Integer type definitions for FatFs.
option Optional external functions.
Low level disk I/O module is not included in this archive because the FatFs
module is only a generic file system layer and not depend on any specific
storage device. You have to provide a low level disk I/O module that written
to control the target storage device.

View File

@ -1,101 +0,0 @@
/*-----------------------------------------------------------------------*/
/* Low level disk I/O module skeleton for FatFs (C)ChaN, 2014 */
/*-----------------------------------------------------------------------*/
/* If a working storage control module is available, it should be */
/* attached to the FatFs via a glue function rather than modifying it. */
/* This is an example of glue functions to attach various exsisting */
/* storage control modules to the FatFs module with a defined API. */
/*-----------------------------------------------------------------------*/
#include "diskio.h" /* FatFs lower layer API */
#include "sdmmc/sdmmc.h"
/*-----------------------------------------------------------------------*/
/* Get Drive Status */
/*-----------------------------------------------------------------------*/
DSTATUS disk_status (
__attribute__((unused))
BYTE pdrv /* Physical drive nmuber to identify the drive */
)
{
return RES_OK;
}
/*-----------------------------------------------------------------------*/
/* Inidialize a Drive */
/*-----------------------------------------------------------------------*/
DSTATUS disk_initialize (
__attribute__((unused))
BYTE pdrv /* Physical drive nmuber to identify the drive */
)
{
sdmmc_sdcard_init();
return RES_OK;
}
/*-----------------------------------------------------------------------*/
/* Read Sector(s) */
/*-----------------------------------------------------------------------*/
DRESULT disk_read (
__attribute__((unused))
BYTE pdrv, /* Physical drive nmuber to identify the drive */
BYTE *buff, /* Data buffer to store read data */
DWORD sector, /* Sector address in LBA */
UINT count /* Number of sectors to read */
)
{
if(sdmmc_sdcard_readsectors(sector, count, buff))
return RES_PARERR;
return RES_OK;
}
/*-----------------------------------------------------------------------*/
/* Write Sector(s) */
/*-----------------------------------------------------------------------*/
#if _USE_WRITE
DRESULT disk_write (
__attribute__((unused))
BYTE pdrv, /* Physical drive nmuber to identify the drive */
__attribute__((unused))
const BYTE *buff, /* Data to be written */
__attribute__((unused))
DWORD sector, /* Sector address in LBA */
__attribute__((unused))
UINT count /* Number of sectors to write */
)
{
return RES_OK;
}
#endif
/*-----------------------------------------------------------------------*/
/* Miscellaneous Functions */
/*-----------------------------------------------------------------------*/
#if _USE_IOCTL
DRESULT disk_ioctl (
__attribute__((unused))
BYTE pdrv, /* Physical drive nmuber (0..) */
__attribute__((unused))
BYTE cmd, /* Control code */
__attribute__((unused))
void *buff /* Buffer to send/receive control data */
)
{
return RES_PARERR;
}
#endif

View File

@ -1,80 +0,0 @@
/*-----------------------------------------------------------------------/
/ Low level disk interface modlue include file (C)ChaN, 2014 /
/-----------------------------------------------------------------------*/
#ifndef _DISKIO_DEFINED
#define _DISKIO_DEFINED
#ifdef __cplusplus
extern "C" {
#endif
#define _USE_WRITE 1 /* 1: Enable disk_write function */
#define _USE_IOCTL 1 /* 1: Enable disk_ioctl fucntion */
#include "integer.h"
/* Status of Disk Functions */
typedef BYTE DSTATUS;
/* Results of Disk Functions */
typedef enum {
RES_OK = 0, /* 0: Successful */
RES_ERROR, /* 1: R/W Error */
RES_WRPRT, /* 2: Write Protected */
RES_NOTRDY, /* 3: Not Ready */
RES_PARERR /* 4: Invalid Parameter */
} DRESULT;
/*---------------------------------------*/
/* Prototypes for disk control functions */
DSTATUS disk_initialize (BYTE pdrv);
DSTATUS disk_status (BYTE pdrv);
DRESULT disk_read (BYTE pdrv, BYTE* buff, DWORD sector, UINT count);
DRESULT disk_write (BYTE pdrv, const BYTE* buff, DWORD sector, UINT count);
DRESULT disk_ioctl (BYTE pdrv, BYTE cmd, void* buff);
/* Disk Status Bits (DSTATUS) */
#define STA_NOINIT 0x01 /* Drive not initialized */
#define STA_NODISK 0x02 /* No medium in the drive */
#define STA_PROTECT 0x04 /* Write protected */
/* Command code for disk_ioctrl fucntion */
/* Generic command (Used by FatFs) */
#define CTRL_SYNC 0 /* Complete pending write process (needed at _FS_READONLY == 0) */
#define GET_SECTOR_COUNT 1 /* Get media size (needed at _USE_MKFS == 1) */
#define GET_SECTOR_SIZE 2 /* Get sector size (needed at _MAX_SS != _MIN_SS) */
#define GET_BLOCK_SIZE 3 /* Get erase block size (needed at _USE_MKFS == 1) */
#define CTRL_TRIM 4 /* Inform device that the data on the block of sectors is no longer used (needed at _USE_TRIM == 1) */
/* Generic command (Not used by FatFs) */
#define CTRL_POWER 5 /* Get/Set power status */
#define CTRL_LOCK 6 /* Lock/Unlock media removal */
#define CTRL_EJECT 7 /* Eject media */
#define CTRL_FORMAT 8 /* Create physical format on the media */
/* MMC/SDC specific ioctl command */
#define MMC_GET_TYPE 10 /* Get card type */
#define MMC_GET_CSD 11 /* Get CSD */
#define MMC_GET_CID 12 /* Get CID */
#define MMC_GET_OCR 13 /* Get OCR */
#define MMC_GET_SDSTAT 14 /* Get SD status */
/* ATA/CF specific ioctl command */
#define ATA_GET_REV 20 /* Get F/W revision */
#define ATA_GET_MODEL 21 /* Get model name */
#define ATA_GET_SN 22 /* Get serial number */
#ifdef __cplusplus
}
#endif
#endif

File diff suppressed because it is too large Load Diff

View File

@ -1,366 +0,0 @@
/*---------------------------------------------------------------------------/
/ FatFs - FAT file system module include R0.12 (C)ChaN, 2016
/----------------------------------------------------------------------------/
/ FatFs module is a free software that opened under license policy of
/ following conditions.
/
/ Copyright (C) 2016, ChaN, all right reserved.
/
/ 1. Redistributions of source code must retain the above copyright notice,
/ this condition and the following disclaimer.
/
/ This software is provided by the copyright holder and contributors "AS IS"
/ and any warranties related to this software are DISCLAIMED.
/ The copyright owner or contributors be NOT LIABLE for any damages caused
/ by use of this software.
/---------------------------------------------------------------------------*/
#ifndef _FATFS
#define _FATFS 88100 /* Revision ID */
#ifdef __cplusplus
extern "C" {
#endif
#include "integer.h" /* Basic integer types */
#include "ffconf.h" /* FatFs configuration options */
#if _FATFS != _FFCONF
#error Wrong configuration file (ffconf.h).
#endif
/* Definitions of volume management */
#if _MULTI_PARTITION /* Multiple partition configuration */
typedef struct {
BYTE pd; /* Physical drive number */
BYTE pt; /* Partition: 0:Auto detect, 1-4:Forced partition) */
} PARTITION;
extern PARTITION VolToPart[]; /* Volume - Partition resolution table */
#define LD2PD(vol) (VolToPart[vol].pd) /* Get physical drive number */
#define LD2PT(vol) (VolToPart[vol].pt) /* Get partition index */
#else /* Single partition configuration */
#define LD2PD(vol) (BYTE)(vol) /* Each logical drive is bound to the same physical drive number */
#define LD2PT(vol) 0 /* Find first valid partition or in SFD */
#endif
/* Type of path name strings on FatFs API */
#if _LFN_UNICODE /* Unicode string */
#if _USE_LFN == 0
#error _LFN_UNICODE must be 0 at non-LFN cfg.
#endif
#ifndef _INC_TCHAR
typedef WCHAR TCHAR;
#define _T(x) L ## x
#define _TEXT(x) L ## x
#endif
#else /* ANSI/OEM string */
#ifndef _INC_TCHAR
typedef char TCHAR;
#define _T(x) x
#define _TEXT(x) x
#endif
#endif
/* File system object structure (FATFS) */
typedef struct {
BYTE fs_type; /* File system type (0:N/A) */
BYTE drv; /* Physical drive number */
BYTE n_fats; /* Number of FATs (1 or 2) */
BYTE wflag; /* win[] flag (b0:dirty) */
BYTE fsi_flag; /* FSINFO flags (b7:disabled, b0:dirty) */
WORD id; /* File system mount ID */
WORD n_rootdir; /* Number of root directory entries (FAT12/16) */
WORD csize; /* Cluster size [sectors] */
#if _MAX_SS != _MIN_SS
WORD ssize; /* Sector size (512, 1024, 2048 or 4096) */
#endif
#if _FS_EXFAT
BYTE* dirbuf; /* Directory entry block scratchpad buffer */
#endif
#if _FS_REENTRANT
_SYNC_t sobj; /* Identifier of sync object */
#endif
#if !_FS_READONLY
DWORD last_clst; /* Last allocated cluster */
DWORD free_clst; /* Number of free clusters */
#endif
#if _FS_RPATH != 0
DWORD cdir; /* Current directory start cluster (0:root) */
#if _FS_EXFAT
DWORD cdc_scl; /* Containing directory start cluster (invalid when cdir is 0) */
DWORD cdc_size; /* b31-b8:Size of containing directory, b7-b0: Chain status */
DWORD cdc_ofs; /* Offset in the containing directory (invalid when cdir is 0) */
#endif
#endif
DWORD n_fatent; /* Number of FAT entries (number of clusters + 2) */
DWORD fsize; /* Size of an FAT [sectors] */
DWORD volbase; /* Volume base sector */
DWORD fatbase; /* FAT base sector */
DWORD dirbase; /* Root directory base sector/cluster */
DWORD database; /* Data base sector */
DWORD winsect; /* Current sector appearing in the win[] */
BYTE win[_MAX_SS]; /* Disk access window for Directory, FAT (and file data at tiny cfg) */
} FATFS;
/* Type of file size variables and object identifier */
#if _FS_EXFAT
#if _USE_LFN == 0
#error LFN must be enabled when enable exFAT
#endif
typedef QWORD FSIZE_t;
#else
typedef DWORD FSIZE_t;
#endif
/* Object ID and allocation information (_FDID) */
typedef struct {
FATFS* fs; /* Pointer to the owner file system object */
WORD id; /* Owner file system mount ID */
BYTE attr; /* Object attribute */
BYTE stat; /* Object chain status (b1-0: =0:not contiguous, =2:contiguous (no data on FAT), =3:got flagmented, b2:sub-directory stretched) */
DWORD sclust; /* Object start cluster (0:no cluster or root directory) */
FSIZE_t objsize; /* Object size (valid when sclust != 0) */
#if _FS_EXFAT
DWORD n_cont; /* Size of coutiguous part, clusters - 1 (valid when stat == 3) */
DWORD c_scl; /* Containing directory start cluster (valid when sclust != 0) */
DWORD c_size; /* b31-b8:Size of containing directory, b7-b0: Chain status (valid when c_scl != 0) */
DWORD c_ofs; /* Offset in the containing directory (valid when sclust != 0) */
#endif
#if _FS_LOCK != 0
UINT lockid; /* File lock ID origin from 1 (index of file semaphore table Files[]) */
#endif
} _FDID;
/* File object structure (FIL) */
typedef struct {
_FDID obj; /* Object identifier */
BYTE flag; /* File status flags */
BYTE err; /* Abort flag (error code) */
FSIZE_t fptr; /* File read/write pointer (Zeroed on file open) */
DWORD clust; /* Current cluster of fpter (not valid when fprt is 0) */
DWORD sect; /* Sector number appearing in buf[] (0:invalid) */
#if !_FS_READONLY
DWORD dir_sect; /* Sector number containing the directory entry */
BYTE* dir_ptr; /* Pointer to the directory entry in the win[] */
#endif
#if _USE_FASTSEEK
DWORD* cltbl; /* Pointer to the cluster link map table (Nulled on file open) */
#endif
#if !_FS_TINY
BYTE buf[_MAX_SS]; /* File private data read/write window */
#endif
} FIL;
/* Directory object structure (DIR) */
typedef struct {
_FDID obj; /* Object identifier */
DWORD dptr; /* Current read/write offset */
DWORD clust; /* Current cluster */
DWORD sect; /* Current sector */
BYTE* dir; /* Pointer to the directory item in the win[] */
BYTE* fn; /* Pointer to the SFN (in/out) {body[8],ext[3],status[1]} */
#if _USE_LFN != 0
DWORD blk_ofs; /* Offset of current entry block being processed (0xFFFFFFFF:Invalid) */
WCHAR* lfn; /* Pointer to the LFN working buffer */
#endif
#if _USE_FIND
const TCHAR* pat; /* Pointer to the name matching pattern */
#endif
} DIR;
/* File information structure (FILINFO) */
typedef struct {
FSIZE_t fsize; /* File size */
WORD fdate; /* Modified date */
WORD ftime; /* Modified time */
BYTE fattrib; /* File attribute */
#if _USE_LFN != 0
TCHAR altname[13]; /* Altenative file name */
TCHAR fname[_MAX_LFN + 1]; /* Primary file name */
#else
TCHAR fname[13]; /* File name */
#endif
} FILINFO;
/* File function return code (FRESULT) */
typedef enum {
FR_OK = 0, /* (0) Succeeded */
FR_DISK_ERR, /* (1) A hard error occurred in the low level disk I/O layer */
FR_INT_ERR, /* (2) Assertion failed */
FR_NOT_READY, /* (3) The physical drive cannot work */
FR_NO_FILE, /* (4) Could not find the file */
FR_NO_PATH, /* (5) Could not find the path */
FR_INVALID_NAME, /* (6) The path name format is invalid */
FR_DENIED, /* (7) Access denied due to prohibited access or directory full */
FR_EXIST, /* (8) Access denied due to prohibited access */
FR_INVALID_OBJECT, /* (9) The file/directory object is invalid */
FR_WRITE_PROTECTED, /* (10) The physical drive is write protected */
FR_INVALID_DRIVE, /* (11) The logical drive number is invalid */
FR_NOT_ENABLED, /* (12) The volume has no work area */
FR_NO_FILESYSTEM, /* (13) There is no valid FAT volume */
FR_MKFS_ABORTED, /* (14) The f_mkfs() aborted due to any parameter error */
FR_TIMEOUT, /* (15) Could not get a grant to access the volume within defined period */
FR_LOCKED, /* (16) The operation is rejected according to the file sharing policy */
FR_NOT_ENOUGH_CORE, /* (17) LFN working buffer could not be allocated */
FR_TOO_MANY_OPEN_FILES, /* (18) Number of open files > _FS_LOCK */
FR_INVALID_PARAMETER /* (19) Given parameter is invalid */
} FRESULT;
/*--------------------------------------------------------------*/
/* FatFs module application interface */
FRESULT f_open (FIL* fp, const TCHAR* path, BYTE mode); /* Open or create a file */
FRESULT f_close (FIL* fp); /* Close an open file object */
FRESULT f_read (FIL* fp, void* buff, UINT btr, UINT* br); /* Read data from a file */
FRESULT f_write (FIL* fp, const void* buff, UINT btw, UINT* bw); /* Write data to a file */
FRESULT f_lseek (FIL* fp, FSIZE_t ofs); /* Move file pointer of a file object */
FRESULT f_truncate (FIL* fp); /* Truncate file */
FRESULT f_sync (FIL* fp); /* Flush cached data of a writing file */
FRESULT f_opendir (DIR* dp, const TCHAR* path); /* Open a directory */
FRESULT f_closedir (DIR* dp); /* Close an open directory */
FRESULT f_readdir (DIR* dp, FILINFO* fno); /* Read a directory item */
FRESULT f_findfirst (DIR* dp, FILINFO* fno, const TCHAR* path, const TCHAR* pattern); /* Find first file */
FRESULT f_findnext (DIR* dp, FILINFO* fno); /* Find next file */
FRESULT f_mkdir (const TCHAR* path); /* Create a sub directory */
FRESULT f_unlink (const TCHAR* path); /* Delete an existing file or directory */
FRESULT f_rename (const TCHAR* path_old, const TCHAR* path_new); /* Rename/Move a file or directory */
FRESULT f_stat (const TCHAR* path, FILINFO* fno); /* Get file status */
FRESULT f_chmod (const TCHAR* path, BYTE attr, BYTE mask); /* Change attribute of the file/dir */
FRESULT f_utime (const TCHAR* path, const FILINFO* fno); /* Change timestamp of the file/dir */
FRESULT f_chdir (const TCHAR* path); /* Change current directory */
FRESULT f_chdrive (const TCHAR* path); /* Change current drive */
FRESULT f_getcwd (TCHAR* buff, UINT len); /* Get current directory */
FRESULT f_getfree (const TCHAR* path, DWORD* nclst, FATFS** fatfs); /* Get number of free clusters on the drive */
FRESULT f_getlabel (const TCHAR* path, TCHAR* label, DWORD* vsn); /* Get volume label */
FRESULT f_setlabel (const TCHAR* label); /* Set volume label */
FRESULT f_forward (FIL* fp, UINT(*func)(const BYTE*,UINT), UINT btf, UINT* bf); /* Forward data to the stream */
FRESULT f_expand (FIL* fp, FSIZE_t szf, BYTE opt); /* Allocate a contiguous block to the file */
FRESULT f_mount (FATFS* fs, const TCHAR* path, BYTE opt); /* Mount/Unmount a logical drive */
FRESULT f_mkfs (const TCHAR* path, BYTE sfd, UINT au); /* Create a file system on the volume */
FRESULT f_fdisk (BYTE pdrv, const DWORD szt[], void* work); /* Divide a physical drive into some partitions */
int f_putc (TCHAR c, FIL* fp); /* Put a character to the file */
int f_puts (const TCHAR* str, FIL* cp); /* Put a string to the file */
int f_printf (FIL* fp, const TCHAR* str, ...); /* Put a formatted string to the file */
TCHAR* f_gets (TCHAR* buff, int len, FIL* fp); /* Get a string from the file */
#define f_eof(fp) ((int)((fp)->fptr == (fp)->obj.objsize))
#define f_error(fp) ((fp)->err)
#define f_tell(fp) ((fp)->fptr)
#define f_size(fp) ((fp)->obj.objsize)
#define f_rewind(fp) f_lseek((fp), 0)
#define f_rewinddir(dp) f_readdir((dp), 0)
#ifndef EOF
#define EOF (-1)
#endif
/*--------------------------------------------------------------*/
/* Additional user defined functions */
/* RTC function */
#if !_FS_READONLY && !_FS_NORTC
DWORD get_fattime (void);
#endif
/* Unicode support functions */
#if _USE_LFN != 0 /* Unicode - OEM code conversion */
WCHAR ff_convert (WCHAR chr, UINT dir); /* OEM-Unicode bidirectional conversion */
WCHAR ff_wtoupper (WCHAR chr); /* Unicode upper-case conversion */
#if _USE_LFN == 3 /* Memory functions */
void* ff_memalloc (UINT msize); /* Allocate memory block */
void ff_memfree (void* mblock); /* Free memory block */
#endif
#endif
/* Sync functions */
#if _FS_REENTRANT
int ff_cre_syncobj (BYTE vol, _SYNC_t* sobj); /* Create a sync object */
int ff_req_grant (_SYNC_t sobj); /* Lock sync object */
void ff_rel_grant (_SYNC_t sobj); /* Unlock sync object */
int ff_del_syncobj (_SYNC_t sobj); /* Delete a sync object */
#endif
/*--------------------------------------------------------------*/
/* Flags and offset address */
/* File access control and file status flags (FIL.flag) */
#define FA_READ 0x01
#define FA_WRITE 0x02
#define FA_OPEN_EXISTING 0x00
#define FA_CREATE_NEW 0x04
#define FA_CREATE_ALWAYS 0x08
#define FA_OPEN_ALWAYS 0x10
#define _FA_MODIFIED 0x20
#define _FA_DIRTY 0x40
/* FAT sub type (FATFS.fs_type) */
#define FS_FAT12 1
#define FS_FAT16 2
#define FS_FAT32 3
#define FS_EXFAT 4
/* File attribute bits for directory entry */
#define AM_RDO 0x01 /* Read only */
#define AM_HID 0x02 /* Hidden */
#define AM_SYS 0x04 /* System */
#define AM_VOL 0x08 /* Volume label */
#define AM_LFN 0x0F /* LFN entry */
#define AM_DIR 0x10 /* Directory */
#define AM_ARC 0x20 /* Archive */
#define AM_MASK 0x3F /* Mask of defined bits */
/* Fast seek controls */
#define CREATE_LINKMAP ((FSIZE_t)0 - 1)
#ifdef __cplusplus
}
#endif
#endif /* _FATFS */

View File

@ -1,266 +0,0 @@
/*---------------------------------------------------------------------------/
/ FatFs - FAT file system module configuration file R0.12 (C)ChaN, 2016
/---------------------------------------------------------------------------*/
#define _FFCONF 88100 /* Revision ID */
/*---------------------------------------------------------------------------/
/ Function Configurations
/---------------------------------------------------------------------------*/
#define _FS_READONLY 1
/* This option switches read-only configuration. (0:Read/Write or 1:Read-only)
/ Read-only configuration removes writing API functions, f_write(), f_sync(),
/ f_unlink(), f_mkdir(), f_chmod(), f_rename(), f_truncate(), f_getfree()
/ and optional writing functions as well. */
#define _FS_MINIMIZE 3
/* This option defines minimization level to remove some basic API functions.
/
/ 0: All basic functions are enabled.
/ 1: f_stat(), f_getfree(), f_unlink(), f_mkdir(), f_truncate() and f_rename()
/ are removed.
/ 2: f_opendir(), f_readdir() and f_closedir() are removed in addition to 1.
/ 3: f_lseek() function is removed in addition to 2. */
#define _USE_STRFUNC 0
/* This option switches string functions, f_gets(), f_putc(), f_puts() and
/ f_printf().
/
/ 0: Disable string functions.
/ 1: Enable without LF-CRLF conversion.
/ 2: Enable with LF-CRLF conversion. */
#define _USE_FIND 0
/* This option switches filtered directory read functions, f_findfirst() and
/ f_findnext(). (0:Disable, 1:Enable 2:Enable with matching altname[] too) */
#define _USE_MKFS 0
/* This option switches f_mkfs() function. (0:Disable or 1:Enable) */
#define _USE_FASTSEEK 0
/* This option switches fast seek function. (0:Disable or 1:Enable) */
#define _USE_EXPAND 0
/* This option switches f_expand function. (0:Disable or 1:Enable) */
#define _USE_CHMOD 0
/* This option switches attribute manipulation functions, f_chmod() and f_utime().
/ (0:Disable or 1:Enable) Also _FS_READONLY needs to be 0 to enable this option. */
#define _USE_LABEL 0
/* This option switches volume label functions, f_getlabel() and f_setlabel().
/ (0:Disable or 1:Enable) */
#define _USE_FORWARD 0
/* This option switches f_forward() function. (0:Disable or 1:Enable)
/ To enable it, also _FS_TINY need to be 1. */
/*---------------------------------------------------------------------------/
/ Locale and Namespace Configurations
/---------------------------------------------------------------------------*/
#define _CODE_PAGE 1
/* This option specifies the OEM code page to be used on the target system.
/ Incorrect setting of the code page can cause a file open failure.
/
/ 1 - ASCII (No extended character. Non-LFN cfg. only)
/ 437 - U.S.
/ 720 - Arabic
/ 737 - Greek
/ 771 - KBL
/ 775 - Baltic
/ 850 - Latin 1
/ 852 - Latin 2
/ 855 - Cyrillic
/ 857 - Turkish
/ 860 - Portuguese
/ 861 - Icelandic
/ 862 - Hebrew
/ 863 - Canadian French
/ 864 - Arabic
/ 865 - Nordic
/ 866 - Russian
/ 869 - Greek 2
/ 932 - Japanese (DBCS)
/ 936 - Simplified Chinese (DBCS)
/ 949 - Korean (DBCS)
/ 950 - Traditional Chinese (DBCS)
*/
#define _USE_LFN 0
#define _MAX_LFN 255
/* The _USE_LFN switches the support of long file name (LFN).
/
/ 0: Disable support of LFN. _MAX_LFN has no effect.
/ 1: Enable LFN with static working buffer on the BSS. Always NOT thread-safe.
/ 2: Enable LFN with dynamic working buffer on the STACK.
/ 3: Enable LFN with dynamic working buffer on the HEAP.
/
/ To enable the LFN, Unicode handling functions (option/unicode.c) must be added
/ to the project. The working buffer occupies (_MAX_LFN + 1) * 2 bytes and
/ additional 608 bytes at exFAT enabled. _MAX_LFN can be in range from 12 to 255.
/ It should be set 255 to support full featured LFN operations.
/ When use stack for the working buffer, take care on stack overflow. When use heap
/ memory for the working buffer, memory management functions, ff_memalloc() and
/ ff_memfree(), must be added to the project. */
#define _LFN_UNICODE 0
/* This option switches character encoding on the API. (0:ANSI/OEM or 1:Unicode)
/ To use Unicode string for the path name, enable LFN and set _LFN_UNICODE = 1.
/ This option also affects behavior of string I/O functions. */
#define _STRF_ENCODE 3
/* When _LFN_UNICODE == 1, this option selects the character encoding on the file to
/ be read/written via string I/O functions, f_gets(), f_putc(), f_puts and f_printf().
/
/ 0: ANSI/OEM
/ 1: UTF-16LE
/ 2: UTF-16BE
/ 3: UTF-8
/
/ This option has no effect when _LFN_UNICODE == 0. */
#define _FS_RPATH 0
/* This option configures support of relative path.
/
/ 0: Disable relative path and remove related functions.
/ 1: Enable relative path. f_chdir() and f_chdrive() are available.
/ 2: f_getcwd() function is available in addition to 1.
*/
/*---------------------------------------------------------------------------/
/ Drive/Volume Configurations
/---------------------------------------------------------------------------*/
#define _VOLUMES 1
/* Number of volumes (logical drives) to be used. */
#define _STR_VOLUME_ID 0
#define _VOLUME_STRS "RAM","NAND","CF","SD1","SD2","USB1","USB2","USB3"
/* _STR_VOLUME_ID switches string support of volume ID.
/ When _STR_VOLUME_ID is set to 1, also pre-defined strings can be used as drive
/ number in the path name. _VOLUME_STRS defines the drive ID strings for each
/ logical drives. Number of items must be equal to _VOLUMES. Valid characters for
/ the drive ID strings are: A-Z and 0-9. */
#define _MULTI_PARTITION 0
/* This option switches support of multi-partition on a physical drive.
/ By default (0), each logical drive number is bound to the same physical drive
/ number and only an FAT volume found on the physical drive will be mounted.
/ When multi-partition is enabled (1), each logical drive number can be bound to
/ arbitrary physical drive and partition listed in the VolToPart[]. Also f_fdisk()
/ funciton will be available. */
#define _MIN_SS 512
#define _MAX_SS 512
/* These options configure the range of sector size to be supported. (512, 1024,
/ 2048 or 4096) Always set both 512 for most systems, all type of memory cards and
/ harddisk. But a larger value may be required for on-board flash memory and some
/ type of optical media. When _MAX_SS is larger than _MIN_SS, FatFs is configured
/ to variable sector size and GET_SECTOR_SIZE command must be implemented to the
/ disk_ioctl() function. */
#define _USE_TRIM 0
/* This option switches support of ATA-TRIM. (0:Disable or 1:Enable)
/ To enable Trim function, also CTRL_TRIM command should be implemented to the
/ disk_ioctl() function. */
#define _FS_NOFSINFO 0
/* If you need to know correct free space on the FAT32 volume, set bit 0 of this
/ option, and f_getfree() function at first time after volume mount will force
/ a full FAT scan. Bit 1 controls the use of last allocated cluster number.
/
/ bit0=0: Use free cluster count in the FSINFO if available.
/ bit0=1: Do not trust free cluster count in the FSINFO.
/ bit1=0: Use last allocated cluster number in the FSINFO if available.
/ bit1=1: Do not trust last allocated cluster number in the FSINFO.
*/
/*---------------------------------------------------------------------------/
/ System Configurations
/---------------------------------------------------------------------------*/
#define _FS_TINY 0
/* This option switches tiny buffer configuration. (0:Normal or 1:Tiny)
/ At the tiny configuration, size of the file object (FIL) is reduced _MAX_SS bytes.
/ Instead of private sector buffer eliminated from the file object, common sector
/ buffer in the file system object (FATFS) is used for the file data transfer. */
#define _FS_EXFAT 0
/* This option switches support of exFAT file system in addition to the traditional
/ FAT file system. (0:Disable or 1:Enable) To enable exFAT, also LFN must be enabled.
/ Note that enabling exFAT discards C89 compatibility. */
#define _FS_NORTC 1
#define _NORTC_MON 3
#define _NORTC_MDAY 1
#define _NORTC_YEAR 2016
/* The option _FS_NORTC switches timestamp functiton. If the system does not have
/ any RTC function or valid timestamp is not needed, set _FS_NORTC = 1 to disable
/ the timestamp function. All objects modified by FatFs will have a fixed timestamp
/ defined by _NORTC_MON, _NORTC_MDAY and _NORTC_YEAR in local time.
/ To enable timestamp function (_FS_NORTC = 0), get_fattime() function need to be
/ added to the project to get current time form real-time clock. _NORTC_MON,
/ _NORTC_MDAY and _NORTC_YEAR have no effect.
/ These options have no effect at read-only configuration (_FS_READONLY = 1). */
#define _FS_LOCK 0
/* The option _FS_LOCK switches file lock function to control duplicated file open
/ and illegal operation to open objects. This option must be 0 when _FS_READONLY
/ is 1.
/
/ 0: Disable file lock function. To avoid volume corruption, application program
/ should avoid illegal open, remove and rename to the open objects.
/ >0: Enable file lock function. The value defines how many files/sub-directories
/ can be opened simultaneously under file lock control. Note that the file
/ lock control is independent of re-entrancy. */
#define _FS_REENTRANT 0
#define _FS_TIMEOUT 1000
#define _SYNC_t HANDLE
/* The option _FS_REENTRANT switches the re-entrancy (thread safe) of the FatFs
/ module itself. Note that regardless of this option, file access to different
/ volume is always re-entrant and volume control functions, f_mount(), f_mkfs()
/ and f_fdisk() function, are always not re-entrant. Only file/directory access
/ to the same volume is under control of this function.
/
/ 0: Disable re-entrancy. _FS_TIMEOUT and _SYNC_t have no effect.
/ 1: Enable re-entrancy. Also user provided synchronization handlers,
/ ff_req_grant(), ff_rel_grant(), ff_del_syncobj() and ff_cre_syncobj()
/ function, must be added to the project. Samples are available in
/ option/syscall.c.
/
/ The _FS_TIMEOUT defines timeout period in unit of time tick.
/ The _SYNC_t defines O/S dependent sync object type. e.g. HANDLE, ID, OS_EVENT*,
/ SemaphoreHandle_t and etc.. A header file for O/S definitions needs to be
/ included somewhere in the scope of ff.c. */
/*--- End of configuration options ---*/

View File

@ -1,38 +0,0 @@
/*-------------------------------------------*/
/* Integer type definitions for FatFs module */
/*-------------------------------------------*/
#ifndef _FF_INTEGER
#define _FF_INTEGER
#ifdef _WIN32 /* FatFs development platform */
#include <windows.h>
#include <tchar.h>
typedef unsigned __int64 QWORD;
#else /* Embedded platform */
/* These types MUST be 16-bit or 32-bit */
typedef int INT;
typedef unsigned int UINT;
/* This type MUST be 8-bit */
typedef unsigned char BYTE;
/* These types MUST be 16-bit */
typedef short SHORT;
typedef unsigned short WORD;
typedef unsigned short WCHAR;
/* These types MUST be 32-bit */
typedef long LONG;
typedef unsigned long DWORD;
/* This type MUST be 64-bit (Remove this for C89 compatibility) */
typedef unsigned long long QWORD;
#endif
#endif

View File

@ -1,9 +0,0 @@
// Copyright 2014 Normmatt
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include "common.h"
void ioDelay(u32 us);

View File

@ -1,17 +0,0 @@
// Copyright 2014 Normmatt
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
.arm
.global ioDelay
.type ioDelay STT_FUNC
@ioDelay ( u32 us )
ioDelay:
ldr r1, =0x18000000 @ VRAM
1:
@ Loop doing uncached reads from VRAM to make loop timing more reliable
ldr r2, [r1]
subs r0, #1
bgt 1b
bx lr

View File

@ -1,290 +0,0 @@
// Copyright 2014 Normmatt
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include "sdmmc.h"
#include "delay.h"
static struct mmcdevice handleSD;
static inline u16 sdmmc_read16(u16 reg) {
return *(vu16*)(SDMMC_BASE + reg);
}
static inline void sdmmc_write16(u16 reg, u16 val) {
*(vu16*)(SDMMC_BASE + reg) = val;
}
static inline u32 sdmmc_read32(u16 reg) {
return *(vu32*)(SDMMC_BASE + reg);
}
static inline void sdmmc_write32(u16 reg, u32 val) {
*(vu32*)(SDMMC_BASE + reg) = val;
}
static inline void sdmmc_mask16(u16 reg, const u16 clear, const u16 set) {
u16 val = sdmmc_read16(reg);
val &= ~clear;
val |= set;
sdmmc_write16(reg, val);
}
static inline void setckl(u32 data)
{
sdmmc_mask16(REG_SDCLKCTL, 0x100, 0);
sdmmc_mask16(REG_SDCLKCTL, 0x2FF, data & 0x2FF);
sdmmc_mask16(REG_SDCLKCTL, 0x0, 0x100);
}
static u32 __attribute__((noinline)) geterror(struct mmcdevice *ctx)
{
return (ctx->error << 29) >> 31;
}
static void __attribute__((noinline)) inittarget(struct mmcdevice *ctx)
{
sdmmc_mask16(REG_SDPORTSEL,0x3,(u16)ctx->devicenumber);
setckl(ctx->clk);
if (ctx->SDOPT == 0) {
sdmmc_mask16(REG_SDOPT, 0, 0x8000);
} else {
sdmmc_mask16(REG_SDOPT, 0x8000, 0);
}
}
static void __attribute__((noinline)) sdmmc_send_command(struct mmcdevice *ctx, u32 cmd, u32 args)
{
bool getSDRESP = (cmd << 15) >> 31;
u16 flags = (cmd << 15) >> 31;
const bool readdata = cmd & 0x20000;
const bool writedata = cmd & 0x40000;
if (readdata || writedata)
flags |= TMIO_STAT0_DATAEND;
ctx->error = 0;
while (sdmmc_read16(REG_SDSTATUS1) & TMIO_STAT1_CMD_BUSY); //mmc working?
sdmmc_write16(REG_SDIRMASK0,0);
sdmmc_write16(REG_SDIRMASK1,0);
sdmmc_write16(REG_SDSTATUS0,0);
sdmmc_write16(REG_SDSTATUS1,0);
sdmmc_mask16(REG_SDDATACTL32,0x1800,0);
sdmmc_write16(REG_SDCMDARG0,args &0xFFFF);
sdmmc_write16(REG_SDCMDARG1,args >> 16);
sdmmc_write16(REG_SDCMD,cmd &0xFFFF);
u32 size = ctx->size;
vu8 *dataPtr = ctx->data;
bool useBuf = ( NULL != dataPtr );
u16 status0 = 0;
while(true) {
u16 status1 = sdmmc_read16(REG_SDSTATUS1);
if (status1 & TMIO_STAT1_RXRDY) {
if (readdata && useBuf) {
sdmmc_mask16(REG_SDSTATUS1, TMIO_STAT1_RXRDY, 0);
//sdmmc_write16(REG_SDSTATUS1,~TMIO_STAT1_RXRDY);
if (size > 0x1FF) {
for(int i = 0; i<0x200; i+=2) {
u16 data = sdmmc_read16(REG_SDFIFO);
*dataPtr++ = data & 0xFF;
*dataPtr++ = data >> 8;
}
size -= 0x200;
}
}
}
if (status1 & TMIO_STAT1_TXRQ) {
if (writedata && useBuf) {
sdmmc_mask16(REG_SDSTATUS1, TMIO_STAT1_TXRQ, 0);
//sdmmc_write16(REG_SDSTATUS1,~TMIO_STAT1_TXRQ);
if (size > 0x1FF) {
for (int i = 0; i<0x200; i+=2) {
u16 data = *dataPtr++;
data |= *dataPtr++ << 8;
sdmmc_write16(REG_SDFIFO, data);
}
size -= 0x200;
}
}
}
if (status1 & TMIO_MASK_GW) {
ctx->error |= 4;
break;
}
if (!(status1 & TMIO_STAT1_CMD_BUSY)) {
status0 = sdmmc_read16(REG_SDSTATUS0);
if (sdmmc_read16(REG_SDSTATUS0) & TMIO_STAT0_CMDRESPEND)
ctx->error |= 0x1;
if (status0 & TMIO_STAT0_DATAEND)
ctx->error |= 0x2;
if ((status0 & flags) == flags)
break;
}
}
ctx->stat0 = sdmmc_read16(REG_SDSTATUS0);
ctx->stat1 = sdmmc_read16(REG_SDSTATUS1);
sdmmc_write16(REG_SDSTATUS0,0);
sdmmc_write16(REG_SDSTATUS1,0);
if (getSDRESP != 0) {
ctx->ret[0] = (u32)sdmmc_read16(REG_SDRESP0) | (u32)(sdmmc_read16(REG_SDRESP1) << 16);
ctx->ret[1] = (u32)sdmmc_read16(REG_SDRESP2) | (u32)(sdmmc_read16(REG_SDRESP3) << 16);
ctx->ret[2] = (u32)sdmmc_read16(REG_SDRESP4) | (u32)(sdmmc_read16(REG_SDRESP5) << 16);
ctx->ret[3] = (u32)sdmmc_read16(REG_SDRESP6) | (u32)(sdmmc_read16(REG_SDRESP7) << 16);
}
}
u32 __attribute__((noinline)) sdmmc_sdcard_readsectors(u32 sector_no, u32 numsectors, vu8 *out)
{
if (handleSD.isSDHC == 0)
sector_no <<= 9;
inittarget(&handleSD);
sdmmc_write16(REG_SDSTOP,0x100);
sdmmc_write16(REG_SDBLKCOUNT,numsectors);
handleSD.data = out;
handleSD.size = numsectors << 9;
sdmmc_send_command(&handleSD,0x33C12,sector_no);
return geterror(&handleSD);
}
static u32 calcSDSize(u8* csd, int type)
{
u32 result = 0;
if (type == -1) type = csd[14] >> 6;
switch (type) {
case 0:
{
u32 block_len = csd[9] & 0xf;
block_len = 1u << block_len;
u32 mult = (u32)(csd[4] >> 7) | (u32)((csd[5] & 3) << 1);
mult = 1u << (mult + 2);
result = csd[8] & 3;
result = (result << 8) | csd[7];
result = (result << 2) | (csd[6] >> 6);
result = (result + 1) * mult * block_len / 512;
}
break;
case 1:
result = csd[7] & 0x3f;
result = (result << 8) | csd[6];
result = (result << 8) | csd[5];
result = (result + 1) * 1024;
break;
default:
break; //Do nothing otherwise
}
return result;
}
static void InitSD()
{
//SD
handleSD.isSDHC = 0;
handleSD.SDOPT = 0;
handleSD.res = 0;
handleSD.initarg = 0;
handleSD.clk = 0x80;
handleSD.devicenumber = 0;
*(vu16*)0x10006100 &= 0xF7FFu; //SDDATACTL32
*(vu16*)0x10006100 &= 0xEFFFu; //SDDATACTL32
*(vu16*)0x10006100 |= 0x402u; //SDDATACTL32
*(vu16*)0x100060D8 = (*(vu16*)0x100060D8 & 0xFFDD) | 2;
*(vu16*)0x10006100 &= 0xFFFDu; //SDDATACTL32
*(vu16*)0x100060D8 &= 0xFFDDu; //SDDATACTL
*(vu16*)0x10006104 = 0; //SDBLKLEN32
*(vu16*)0x10006108 = 1; //SDBLKCOUNT32
*(vu16*)0x100060E0 &= 0xFFFEu; //SDRESET
*(vu16*)0x100060E0 |= 1u; //SDRESET
*(vu16*)0x10006020 |= TMIO_MASK_ALL; //SDIR_MASK0
*(vu16*)0x10006022 |= TMIO_MASK_ALL>>16; //SDIR_MASK1
*(vu16*)0x100060FC |= 0xDBu; //SDCTL_RESERVED7
*(vu16*)0x100060FE |= 0xDBu; //SDCTL_RESERVED8
*(vu16*)0x10006002 &= 0xFFFCu; //SDPORTSEL
*(vu16*)0x10006024 = 0x40; //Nintendo sets this to 0x20
*(vu16*)0x10006028 = 0x40EB; //Nintendo sets this to 0x40EE
*(vu16*)0x10006002 &= 0xFFFCu; ////SDPORTSEL
*(vu16*)0x10006026 = 512; //SDBLKLEN
*(vu16*)0x10006008 = 0; //SDSTOP
inittarget(&handleSD);
}
static int SD_Init()
{
inittarget(&handleSD);
ioDelay(1u << 18); //Card needs a little bit of time to be detected, it seems
//If not inserted
if (!(*((vu16*)0x1000601c) & TMIO_STAT0_SIGSTATE)) return -1;
sdmmc_send_command(&handleSD,0,0);
sdmmc_send_command(&handleSD,0x10408,0x1AA);
//u32 temp = (handleSD.ret[0] == 0x1AA) << 0x1E;
u32 temp = (handleSD.error & 0x1) << 0x1E;
//int count = 0;
u32 temp2 = 0;
do {
do {
sdmmc_send_command(&handleSD,0x10437,handleSD.initarg << 0x10);
sdmmc_send_command(&handleSD,0x10769,0x00FF8000 | temp);
temp2 = 1;
} while ( !(handleSD.error & 1) );
} while((handleSD.ret[0] & 0x80000000) == 0);
if(!((handleSD.ret[0] >> 30) & 1) || !temp)
temp2 = 0;
handleSD.isSDHC = temp2;
sdmmc_send_command(&handleSD,0x10602,0);
if (handleSD.error & 0x4) return -1;
sdmmc_send_command(&handleSD,0x10403,0);
if (handleSD.error & 0x4) return -1;
handleSD.initarg = handleSD.ret[0] >> 0x10;
sdmmc_send_command(&handleSD,0x10609,handleSD.initarg << 0x10);
if (handleSD.error & 0x4) return -1;
handleSD.total_size = calcSDSize((u8*)&handleSD.ret[0],-1);
handleSD.clk = 1;
setckl(1);
sdmmc_send_command(&handleSD,0x10507,handleSD.initarg << 0x10);
if (handleSD.error & 0x4) return -1;
sdmmc_send_command(&handleSD,0x10437,handleSD.initarg << 0x10);
if (handleSD.error & 0x4) return -1;
handleSD.SDOPT = 1;
sdmmc_send_command(&handleSD,0x10446,0x2);
if (handleSD.error & 0x4) return -1;
sdmmc_send_command(&handleSD,0x1040D,handleSD.initarg << 0x10);
if (handleSD.error & 0x4) return -1;
sdmmc_send_command(&handleSD,0x10410,0x200);
if (handleSD.error & 0x4) return -1;
handleSD.clk |= 0x200;
return 0;
}
void sdmmc_sdcard_init()
{
InitSD();
SD_Init();
}

View File

@ -1,122 +0,0 @@
// Copyright 2014 Normmatt
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include "common.h"
#define SDMMC_BASE 0x10006000u
#define REG_SDCMD 0x00
#define REG_SDPORTSEL 0x02
#define REG_SDCMDARG 0x04
#define REG_SDCMDARG0 0x04
#define REG_SDCMDARG1 0x06
#define REG_SDSTOP 0x08
#define REG_SDBLKCOUNT 0x0a
#define REG_SDRESP0 0x0c
#define REG_SDRESP1 0x0e
#define REG_SDRESP2 0x10
#define REG_SDRESP3 0x12
#define REG_SDRESP4 0x14
#define REG_SDRESP5 0x16
#define REG_SDRESP6 0x18
#define REG_SDRESP7 0x1a
#define REG_SDSTATUS0 0x1c
#define REG_SDSTATUS1 0x1e
#define REG_SDIRMASK0 0x20
#define REG_SDIRMASK1 0x22
#define REG_SDCLKCTL 0x24
#define REG_SDBLKLEN 0x26
#define REG_SDOPT 0x28
#define REG_SDFIFO 0x30
#define REG_SDDATACTL 0xd8
#define REG_SDRESET 0xe0
#define REG_SDPROTECTED 0xf6 //bit 0 determines if sd is protected or not?
#define REG_SDDATACTL32 0x100
#define REG_SDBLKLEN32 0x104
#define REG_SDBLKCOUNT32 0x108
#define REG_SDFIFO32 0x10C
#define REG_CLK_AND_WAIT_CTL 0x138
#define REG_RESET_SDIO 0x1e0
#define TMIO_STAT0_CMDRESPEND 0x0001
#define TMIO_STAT0_DATAEND 0x0004
#define TMIO_STAT0_CARD_REMOVE 0x0008
#define TMIO_STAT0_CARD_INSERT 0x0010
#define TMIO_STAT0_SIGSTATE 0x0020
#define TMIO_STAT0_WRPROTECT 0x0080
#define TMIO_STAT0_CARD_REMOVE_A 0x0100
#define TMIO_STAT0_CARD_INSERT_A 0x0200
#define TMIO_STAT0_SIGSTATE_A 0x0400
#define TMIO_STAT1_CMD_IDX_ERR 0x0001
#define TMIO_STAT1_CRCFAIL 0x0002
#define TMIO_STAT1_STOPBIT_ERR 0x0004
#define TMIO_STAT1_DATATIMEOUT 0x0008
#define TMIO_STAT1_RXOVERFLOW 0x0010
#define TMIO_STAT1_TXUNDERRUN 0x0020
#define TMIO_STAT1_CMDTIMEOUT 0x0040
#define TMIO_STAT1_RXRDY 0x0100
#define TMIO_STAT1_TXRQ 0x0200
#define TMIO_STAT1_ILL_FUNC 0x2000
#define TMIO_STAT1_CMD_BUSY 0x4000
#define TMIO_STAT1_ILL_ACCESS 0x8000
//Comes from TWLSDK mongoose.tef DWARF info
#define SDMC_NORMAL 0x00000000
#define SDMC_ERR_COMMAND 0x00000001
#define SDMC_ERR_CRC 0x00000002
#define SDMC_ERR_END 0x00000004
#define SDMC_ERR_TIMEOUT 0x00000008
#define SDMC_ERR_FIFO_OVF 0x00000010
#define SDMC_ERR_FIFO_UDF 0x00000020
#define SDMC_ERR_WP 0x00000040
#define SDMC_ERR_ABORT 0x00000080
#define SDMC_ERR_FPGA_TIMEOUT 0x00000100
#define SDMC_ERR_PARAM 0x00000200
#define SDMC_ERR_R1_STATUS 0x00000800
#define SDMC_ERR_NUM_WR_SECTORS 0x00001000
#define SDMC_ERR_RESET 0x00002000
#define SDMC_ERR_ILA 0x00004000
#define SDMC_ERR_INFO_DETECT 0x00008000
#define SDMC_STAT_ERR_UNKNOWN 0x00080000
#define SDMC_STAT_ERR_CC 0x00100000
#define SDMC_STAT_ERR_ECC_FAILED 0x00200000
#define SDMC_STAT_ERR_CRC 0x00800000
#define SDMC_STAT_ERR_OTHER 0xf9c70008
#define TMIO_MASK_ALL 0x837f031d
#define TMIO_MASK_GW (TMIO_STAT1_ILL_ACCESS | TMIO_STAT1_CMDTIMEOUT | TMIO_STAT1_TXUNDERRUN | TMIO_STAT1_RXOVERFLOW | \
TMIO_STAT1_DATATIMEOUT | TMIO_STAT1_STOPBIT_ERR | TMIO_STAT1_CRCFAIL | TMIO_STAT1_CMD_IDX_ERR)
#define TMIO_MASK_READOP (TMIO_STAT1_RXRDY | TMIO_STAT1_DATAEND)
#define TMIO_MASK_WRITEOP (TMIO_STAT1_TXRQ | TMIO_STAT1_DATAEND)
typedef struct mmcdevice {
vu8* data;
u32 size;
u32 error;
u16 stat0;
u16 stat1;
u32 ret[4];
u32 initarg;
u32 isSDHC;
u32 clk;
u32 SDOPT;
u32 devicenumber;
u32 total_size; //size in sectors of the device
u32 res;
} mmcdevice;
void sdmmc_sdcard_init();
u32 sdmmc_sdcard_readsectors(u32 sector_no, u32 numsectors, vu8 *out);

View File

@ -1,19 +1,10 @@
#include "fatfs/ff.h"
#define PAYLOAD_ADDRESS 0x23F00000
#include "memory.h"
void main(void)
{
FATFS fs;
void *payloadAddress = (void *)0x23F00000;
f_mount(&fs, "0:", 1);
memcpy(payloadAddress, (void*)0x24F00000, *(u32 *)0x24FFFB04);
FIL payload;
unsigned int read;
f_open(&payload, (char *)0x24F00004, FA_READ);
f_read(&payload, (void *)PAYLOAD_ADDRESS, f_size(&payload), &read);
f_close(&payload);
((void (*)())PAYLOAD_ADDRESS)();
((void (*)())payloadAddress)();
}

10
loader/source/memory.c Normal file
View File

@ -0,0 +1,10 @@
#include "memory.h"
void memcpy(void *dest, const void *src, u32 size)
{
u8 *destc = (u8 *)dest;
const u8 *srcc = (const u8 *)src;
for(u32 i = 0; i < size; i++)
destc[i] = srcc[i];
}

5
loader/source/memory.h Normal file
View File

@ -0,0 +1,5 @@
#pragma once
#include "types.h"
void memcpy(void *dest, const void *src, u32 size);

View File

@ -4,7 +4,7 @@
_start:
b start
.word 0, 0, 0, 0, 0, 0, 0
.word 0
start:
@ Flush caches

View File

@ -1,8 +1,6 @@
#pragma once
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
//Common data types
typedef uint8_t u8;

View File

@ -54,10 +54,13 @@ payload_maxsize equ 0x20000 ; Maximum size for the payload (200 KB will do).
movne r4, #0
bne read_payload ; Go read the real payload.
add r0, sp, #0x3A8 - 0x70
ldr r0, [r0, #0x27]
; Copy the last digits of the wanted firm to the 5th byte of the payload
add r2, sp, #0x3A8 - 0x70
ldr r0, [r2, #0x27]
ldr r1, =payload_addr + 4
str r0, [r1] ; Copy the last digits of the wanted firm to the 5th byte of the payload.
str r0, [r1]
ldr r0, [r2, #0x2B]
str r0, [r1, #4]
; Set kernel state
mov r0, #0

View File

@ -1,7 +1,7 @@
ENTRY(_start)
SECTIONS
{
. = 0x24F02000;
. = 0x24FFFC00;
.text.start : { *(.text.start) }
.text : { *(.text) }
.data : { *(.data) }

View File

@ -3,7 +3,7 @@
void main(void)
{
const u32 brightness[4] = {0x5F, 0x4C, 0x39, 0x26};
u32 brightnessLevel = *(vu32 *)0x24F02008;
u32 brightnessLevel = *(vu32 *)0x24FFFC08;
vu32 *const arm11 = (u32 *)0x1FFFFFF8;
*(vu32 *)0x10141200 = 0x1007F;

View File

@ -7,6 +7,7 @@
#include "types.h"
#define HID_PAD (*(vu32 *)0x10146000 ^ 0xFFF)
#define BUTTON_R1 (1 << 8)
#define BUTTON_L1 (1 << 9)
#define BUTTON_A 1
@ -19,6 +20,7 @@
#define BUTTON_LEFT (1 << 5)
#define BUTTON_UP (1 << 6)
#define BUTTON_DOWN (1 << 7)
#define SAFE_MODE (BUTTON_R1 | BUTTON_L1 | BUTTON_A | BUTTON_UP)
#define OVERRIDE_BUTTONS (BUTTON_B ^ 0xFFF)
#define SINGLE_PAYLOAD_BUTTONS (BUTTON_LEFT | BUTTON_RIGHT | BUTTON_UP | BUTTON_DOWN | BUTTON_START | BUTTON_X | BUTTON_Y)

View File

@ -10,9 +10,6 @@
#include "memory.h"
#include "font.h"
#define SCREEN_TOP_WIDTH 400
#define SCREEN_TOP_HEIGHT 240
static const struct fb {
u8 *top_left;
u8 *top_right;

View File

@ -8,8 +8,12 @@
#include "types.h"
#define SPACING_Y 10
#define SPACING_X 8
#define SCREEN_TOP_WIDTH 400
#define SCREEN_TOP_HEIGHT 240
#define SPACING_Y 10
#define SPACING_X 8
#define COLOR_TITLE 0xFF9900
#define COLOR_WHITE 0xFFFFFF
#define COLOR_RED 0x0000FF

View File

@ -15,31 +15,27 @@ void getEmunandSect(u32 *off, u32 *head, u32 *emuNAND)
(nandSize > 0x200000 ? 0x400000 : 0x200000);
//Check for RedNAND
if(sdmmc_sdcard_readsectors(nandOffset + 1, 1, temp) == 0)
if(!sdmmc_sdcard_readsectors(nandOffset + 1, 1, temp) &&
*(u32 *)(temp + 0x100) == NCSD_MAGIC)
{
if(*(u32 *)(temp + 0x100) == NCSD_MAGIC)
{
*off = nandOffset + 1;
*head = nandOffset + 1;
}
*off = nandOffset + 1;
*head = nandOffset + 1;
}
//Check for Gateway emuNAND
else if(sdmmc_sdcard_readsectors(nandOffset + nandSize, 1, temp) == 0)
{
if(*(u32 *)(temp + 0x100) == NCSD_MAGIC)
{
*off = nandOffset;
*head = nandOffset + nandSize;
}
//Check for Gateway emuNAND
else if(!sdmmc_sdcard_readsectors(nandOffset + nandSize, 1, temp) &&
*(u32 *)(temp + 0x100) == NCSD_MAGIC)
{
*off = nandOffset;
*head = nandOffset + nandSize;
}
/* Fallback to the first emuNAND if there's no second one,
or to SysNAND if there isn't any */
else
{
(*emuNAND)--;
if(*emuNAND) getEmunandSect(off, head, emuNAND);
}
}
/* Fallback to the first emuNAND if there's no second one,
or to SysNAND if there isn't any */
else
{
(*emuNAND)--;
if(*emuNAND) getEmunandSect(off, head, emuNAND);
}
}

View File

@ -15,7 +15,7 @@
/ and optional writing functions as well. */
#define _FS_MINIMIZE 1
#define _FS_MINIMIZE 0
/* This option defines minimization level to remove some basic API functions.
/
/ 0: All basic functions are enabled.

View File

@ -10,9 +10,9 @@
#include "memory.h"
#include "emunand.h"
#include "crypto.h"
#include "exceptions.h"
#include "draw.h"
#include "screeninit.h"
#include "exceptions.h"
#include "buttons.h"
#include "../build/patches.h"
@ -29,26 +29,22 @@ void main(void)
u32 bootType,
firmType,
nandType,
a9lhInstalled,
a9lhMode,
updatedSys,
needConfig,
newConfig,
emuHeader;
//Detect the console being used
console = (PDN_MPCORE_CFG == 1) ? 0 : 1;
console = PDN_MPCORE_CFG == 7;
//Mount filesystems. CTRNAND will be mounted only if/when needed
mountFs();
//Attempt to read the configuration file
const char configPath[] = "/luma/config.bin";
if(!fileRead(&config, configPath, 4)) needConfig = 1;
else
{
config = 0;
needConfig = 2;
}
//Attempt to read the configuration file
needConfig = !fileRead(&config, configPath, 4) ? 1 : 2;
//Determine if this is a firmlaunch boot
if(*(vu8 *)0x23F00005)
@ -58,104 +54,114 @@ void main(void)
bootType = 1;
//'0' = NATIVE_FIRM, '1' = TWL_FIRM, '2' = AGB_FIRM
firmType = *(vu8 *)0x23F00005 - '0';
firmType = *(vu8 *)0x23F00009 == '3' ? 3 : *(vu8 *)0x23F00005 - '0';
nandType = BOOTCONFIG(0, 3);
firmSource = BOOTCONFIG(2, 1);
a9lhInstalled = BOOTCONFIG(3, 1);
updatedSys = (a9lhInstalled && CONFIG(1)) ? 1 : 0;
a9lhMode = BOOTCONFIG(3, 1);
updatedSys = (a9lhMode && CONFIG(1)) ? 1 : 0;
}
else
{
//Only when "Enable developer features" is set
if(CONFIG(5))
{
detectAndProcessExceptionDumps();
installArm9Handlers();
}
//Get pressed buttons
u32 pressed = HID_PAD;
//If no configuration file exists or SELECT is held, load configuration menu
if(needConfig == 2 || (pressed & BUTTON_SELECT))
configureCFW(configPath);
u32 devMode = CONFIG(5);
if(devMode) detectAndProcessExceptionDumps();
bootType = 0;
firmType = 0;
//Determine if booting with A9LH
u32 a9lhBoot = !PDN_SPI_CNT ? 1 : 0;
//Retrieve the last booted FIRM
u32 previousFirm = CFG_BOOTENV;
//Get pressed buttons
u32 pressed = HID_PAD;
u32 a9lhBoot = !PDN_SPI_CNT;
//Determine if A9LH is installed and the user has an updated sysNAND
if(a9lhBoot || CONFIG(2))
{
if(pressed == SAFE_MODE)
error("Using Safe Mode would brick you, or remove A9LH!");
a9lhInstalled = 1;
//Check setting for > 9.2 sysNAND
a9lhMode = 1;
updatedSys = CONFIG(1);
}
else
{
a9lhInstalled = 0;
a9lhMode = 0;
updatedSys = 0;
}
newConfig = a9lhInstalled << 3;
newConfig = a9lhMode << 3;
/* If booting with A9LH, it's a MCU reboot and a previous configuration exists,
try to force boot options */
if(a9lhBoot && previousFirm && needConfig == 1)
if(a9lhBoot)
{
//Always force a sysNAND boot when quitting AGB_FIRM
if(previousFirm == 7)
{
nandType = 0;
firmSource = updatedSys ? 0 : BOOTCONFIG(2, 1);
needConfig = 0;
//Retrieve the last booted FIRM
u32 previousFirm = CFG_BOOTENV;
//Flag to prevent multiple boot options-forcing
newConfig |= 1 << 4;
}
/* Else, force the last used boot options unless a payload button or A/L/R are pressed
or the no-forcing flag is set */
else if(!(pressed & OVERRIDE_BUTTONS) && !BOOTCONFIG(4, 1))
//If it's a MCU reboot, try to force boot options
if(previousFirm)
{
nandType = BOOTCONFIG(0, 3);
firmSource = BOOTCONFIG(2, 1);
needConfig = 0;
//Always force a sysNAND boot when quitting AGB_FIRM
if(previousFirm == 7)
{
nandType = 0;
firmSource = updatedSys ? 0 : BOOTCONFIG(2, 1);
needConfig--;
//Flag to prevent multiple boot options-forcing
newConfig |= 1 << 4;
}
/* Else, force the last used boot options unless a payload button or A/L/R are pressed
or the no-forcing flag is set */
else if(!(pressed & OVERRIDE_BUTTONS) && !BOOTCONFIG(4, 1))
{
nandType = BOOTCONFIG(0, 3);
firmSource = BOOTCONFIG(2, 1);
needConfig--;
}
}
//If the SAFE MODE combo is held, force a sysNAND boot
else if(pressed == SAFE_MODE)
{
a9lhMode++;
nandType = 0;
firmSource = 0;
needConfig--;
}
}
//Boot options aren't being forced
if(needConfig)
{
/* If L and R/Select or one of the single payload buttons are pressed and, if not using A9LH,
the Safe Mode combo is not pressed, chainload an external payload */
if(((pressed & SINGLE_PAYLOAD_BUTTONS) || ((pressed & BUTTON_L1) && (pressed & L_PAYLOAD_BUTTONS)))
&& pressed != SAFE_MODE)
loadPayload(pressed);
//If no configuration file exists or SELECT is held, load configuration menu
if(needConfig == 2 || (pressed & BUTTON_SELECT))
configureCFW(configPath);
/* If L and R/A/Select or one of the single payload buttons are pressed,
chainload an external payload */
if(devMode || (pressed & SINGLE_PAYLOAD_BUTTONS) || ((pressed & BUTTON_L1) && (pressed & L_PAYLOAD_BUTTONS)))
loadPayload(pressed, devMode);
//If screens are inited or the corresponding option is set, load splash screen
if(PDN_GPU_CNT != 1 || CONFIG(8)) loadSplash();
u32 autoBootSys = CONFIG(0);
//If R is pressed, boot the non-updated NAND with the FIRM of the opposite one
if(pressed & BUTTON_R1)
{
nandType = updatedSys;
firmSource = !nandType;
}
//Determine if we need to boot an emuNAND or sysNAND
nandType = (pressed & BUTTON_L1) ? autoBootSys : ((pressed & BUTTON_R1) ? updatedSys : !autoBootSys);
/* Else, boot the NAND the user set to autoboot or the opposite one, depending on L,
with their own FIRM */
else
{
nandType = CONFIG(0) != !(pressed & BUTTON_L1);
firmSource = nandType;
}
/* If we're booting emuNAND the second emuNAND is set as default and B isn't pressed,
or vice-versa, boot the second emuNAND */
if(nandType && ((!(pressed & BUTTON_B)) == CONFIG(3))) nandType++;
//Determine the NAND we should take the FIRM from
firmSource = (pressed & BUTTON_R1) ? !nandType : (nandType != 0);
if(nandType && (CONFIG(3) == !(pressed & BUTTON_B))) nandType++;
}
}
@ -187,8 +193,18 @@ void main(void)
loadFirm(firmType, !firmType && updatedSys == !firmSource);
if(!firmType) patchNativeFirm(nandType, emuHeader, a9lhInstalled);
else patchTwlAgbFirm(firmType);
switch(firmType)
{
case 0:
patchNativeFirm(nandType, emuHeader, a9lhMode);
break;
case 3:
patchSafeFirm();
break;
default:
patchLegacyFirm(firmType);
break;
}
launchFirm(bootType);
}
@ -205,16 +221,17 @@ static inline void loadFirm(u32 firmType, u32 externalFirm)
doesn't match the console, load FIRM from CTRNAND */
if(!externalFirmLoaded)
{
const char *firmFolders[3][2] = {{ "00000002", "20000002" },
const char *firmFolders[4][2] = {{ "00000002", "20000002" },
{ "00000102", "20000102" },
{ "00000202", "20000202" }};
{ "00000202", "20000202" },
{ "00000003", "20000003" }};
firmRead(firm, firmFolders[firmType][console]);
decryptExeFs((u8 *)firm);
}
}
static inline void patchNativeFirm(u32 nandType, u32 emuHeader, u32 a9lhInstalled)
static inline void patchNativeFirm(u32 nandType, u32 emuHeader, u32 a9lhMode)
{
u8 *arm9Section = (u8 *)firm + section[2].offset;
@ -236,7 +253,7 @@ static inline void patchNativeFirm(u32 nandType, u32 emuHeader, u32 a9lhInstalle
nativeFirmType = (memcmp(section[2].hash, firm90Hash, 0x10) == 0) ? 0 : 1;
}
if(nativeFirmType || nandType)
if(nativeFirmType || nandType || a9lhMode == 2)
{
//Find the Process9 NCCH location
u8 *proc9Offset = getProc9(arm9Section, section[2].size);
@ -245,16 +262,11 @@ static inline void patchNativeFirm(u32 nandType, u32 emuHeader, u32 a9lhInstalle
if(nandType) patchEmuNAND(arm9Section, proc9Offset, emuHeader);
//Apply FIRM reboot patches, not on 9.0 FIRM as it breaks firmlaunchhax
if(nativeFirmType) patchReboots(arm9Section, proc9Offset);
if(nativeFirmType || a9lhMode == 2) patchReboots(arm9Section, proc9Offset);
}
//Apply FIRM0/1 writes patches on sysNAND to protect A9LH
if(a9lhInstalled && !nandType)
{
u16 *writeOffset = getFirmWrite(arm9Section, section[2].size);
*writeOffset = writeBlock[0];
*(writeOffset + 1) = writeBlock[1];
}
if(a9lhMode && !nandType) patchFirmWrites(arm9Section, 1);
//Apply signature checks patches
u32 sigOffset,
@ -348,7 +360,7 @@ static inline void injectLoader(void)
}
}
static inline void patchTwlAgbFirm(u32 firmType)
static inline void patchLegacyFirm(u32 firmType)
{
//On N3DS, decrypt ARM9Bin and patch ARM9 entrypoint to skip arm9loader
if(console)
@ -396,6 +408,37 @@ static inline void patchTwlAgbFirm(u32 firmType)
}
}
static inline void patchSafeFirm(void)
{
u8 *arm9Section = (u8 *)firm + section[2].offset;
if(console)
{
//Decrypt ARM9Bin and patch ARM9 entrypoint to skip arm9loader
arm9Loader(arm9Section, 0);
firm->arm9Entry = (u8 *)0x801B01C;
}
//Apply FIRM0/1 writes patches to protect A9LH
patchFirmWrites(arm9Section, console);
}
static void patchFirmWrites(u8 *arm9Section, u32 mode)
{
if(mode)
{
u16 *writeOffset = getFirmWrite(arm9Section, section[2].size);
*writeOffset = writeBlock[0];
*(writeOffset + 1) = writeBlock[1];
}
else
{
u16 *writeOffset = getFirmWriteSafe(arm9Section, section[2].size);
*writeOffset = writeBlockSafe[0];
*(writeOffset + 1) = writeBlockSafe[1];
}
}
static inline void launchFirm(u32 bootType)
{
//Copy FIRM sections to respective memory locations

View File

@ -37,9 +37,11 @@ typedef struct patchData {
} patchData;
static inline void loadFirm(u32 firmType, u32 externalFirm);
static inline void patchNativeFirm(u32 emuNAND, u32 emuHeader, u32 a9lhSetup);
static inline void patchNativeFirm(u32 nandType, u32 emuHeader, u32 a9lhMode);
static inline void patchEmuNAND(u8 *arm9Section, u8 *proc9Offset, u32 emuHeader);
static inline void patchReboots(u8 *arm9Section, u8 *proc9Offset);
static inline void injectLoader(void);
static inline void patchTwlAgbFirm(u32 firmType);
static inline void patchLegacyFirm(u32 firmType);
static inline void patchSafeFirm(void);
static void patchFirmWrites(u8 *arm9Section, u32 mode);
static inline void launchFirm(u32 bootType);

View File

@ -5,13 +5,11 @@
#include "fs.h"
#include "memory.h"
#include "screeninit.h"
#include "exceptions.h"
#include "fatfs/ff.h"
#include "buttons.h"
#include "../build/loader.h"
#define PAYLOAD_ADDRESS 0x24F00000
#define PATTERN(a) a "_*.bin"
static FATFS sdFs,
nandFs;
@ -58,7 +56,7 @@ u32 fileWrite(const void *buffer, const char *path, u32 size)
return result;
}
void loadPayload(u32 pressed)
void loadPayload(u32 pressed, u32 devMode)
{
const char *pattern;
@ -71,11 +69,12 @@ void loadPayload(u32 pressed)
else if(pressed & BUTTON_R1) pattern = PATTERN("r");
else if(pressed & BUTTON_A) pattern = PATTERN("a");
else if(pressed & BUTTON_START) pattern = PATTERN("start");
else pattern = PATTERN("select");
else if(pressed & BUTTON_SELECT) pattern = PATTERN("select");
else pattern = "nlc.bin";
DIR dir;
FILINFO info;
char path[] = "/luma/payloads";
char path[28] = "/luma/payloads";
FRESULT result = f_findfirst(&dir, &info, path, pattern);
@ -83,14 +82,31 @@ void loadPayload(u32 pressed)
if(result == FR_OK && info.fname[0])
{
//Only when "Enable developer features" is set
if(devMode) installArm9Handlers();
initScreens();
memcpy((void *)PAYLOAD_ADDRESS, loader, loader_size);
path[sizeof(path) - 1] = '/';
memcpy((void *)(PAYLOAD_ADDRESS + 4), path, sizeof(path));
memcpy((void *)(PAYLOAD_ADDRESS + 4 + sizeof(path)), info.altname, 13);
u32 *const loaderAddress = (u32 *)0x24FFFB00;
((void (*)())PAYLOAD_ADDRESS)();
memcpy(loaderAddress, loader, loader_size);
path[14] = '/';
memcpy(&path[15], info.altname, 13);
FIL payload;
unsigned int read;
f_open(&payload, path, FA_READ);
u32 size = f_size(&payload);
f_read(&payload, (void *)0x24F00000, size, &read);
f_close(&payload);
if(pattern[0] == 'n') f_unlink(path);
loaderAddress[1] = size;
((void (*)())loaderAddress)();
}
}

View File

@ -6,9 +6,11 @@
#include "types.h"
#define PATTERN(a) a "_*.bin"
u32 mountFs(void);
u32 fileRead(void *dest, const char *path, u32 size);
u32 fileWrite(const void *buffer, const char *path, u32 size);
void findDumpFile(const char *path, char *fileName);
void loadPayload(u32 pressed);
void loadPayload(u32 pressed, u32 devMode);
void firmRead(void *dest, const char *firmFolder);

View File

@ -13,7 +13,8 @@ const u32 mpuPatch[3] = {0x00360003, 0x00200603, 0x001C0603};
const u16 nandRedir[2] = {0x4C00, 0x47A0},
sigPatch[2] = {0x2000, 0x4770},
writeBlock[2] = {0x2000, 0x46C0};
writeBlock[2] = {0x2000, 0x46C0},
writeBlockSafe[2] = {0x2400, 0xE01D};
const u8 unitInfoPatch = 0xE3;
@ -65,6 +66,14 @@ u16 *getFirmWrite(u8 *pos, u32 size)
return (u16 *)memsearch(off - 0x100, pattern, 0x100, 4);
}
u16 *getFirmWriteSafe(u8 *pos, u32 size)
{
//Look for FIRM writing code
const u8 pattern[] = {0x04, 0x1E, 0x1D, 0xDB};
return (u16 *)memsearch(pos, pattern, size, 4);
}
u8 *getUnitInfoValueSet(u8 *pos, u32 size)
{
//Look for UNITINFO value being set

View File

@ -12,8 +12,9 @@
const u32 mpuPatch[3];
const u16 nandRedir[2],
sigPatch[2],
writeBlock[2];
const u8 unitInfoPatch;
writeBlock[2],
writeBlockSafe[2];
const u8 unitInfoPatch;
/**************************************************
* Functions
@ -23,5 +24,6 @@ void getSigChecks(u8 *pos, u32 size, u32 *off, u32 *off2);
void *getReboot(u8 *pos, u32 size);
u32 getfOpen(u8 *proc9Offset, void *rebootOffset);
u16 *getFirmWrite(u8 *pos, u32 size);
u16 *getFirmWriteSafe(u8 *pos, u32 size);
u8 *getUnitInfoValueSet(u8 *pos, u32 size);
void *getLoader(u8 *pos, u32 size, u32 *loaderSize);

View File

@ -12,8 +12,6 @@
#include "i2c.h"
#include "../build/screeninit.h"
#define SCREENINIT_ADDRESS 0x24F02000
vu32 *arm11Entry = (u32 *)0x1FFFFFF8;
void deinitScreens(void)
@ -49,12 +47,14 @@ void initScreens(void)
{
if(PDN_GPU_CNT == 1)
{
memcpy((void *)SCREENINIT_ADDRESS, screeninit, screeninit_size);
u32 *const screenInitAddress = (u32 *)0x24FFFC00;
memcpy(screenInitAddress, screeninit, screeninit_size);
//Write brightness level for the stub to pick up
*(vu32 *)(SCREENINIT_ADDRESS + 8) = MULTICONFIG(0);
screenInitAddress[2] = MULTICONFIG(0);
*arm11Entry = SCREENINIT_ADDRESS;
*arm11Entry = (u32)screenInitAddress;
while(*arm11Entry);
//Turn on backlight

View File

@ -9,7 +9,7 @@
#include "types.h"
#define PDN_GPU_CNT (*(vu8 *)0x10141200)
#define PDN_GPU_CNT (*(vu8 *)0x10141200)
void deinitScreens(void);
void initScreens(void);

View File

@ -4,7 +4,7 @@
_start:
b start
.word 0
.word 0, 0
start:
@ Change the stack pointer

View File

@ -3,9 +3,9 @@
*/
#include "utils.h"
#include "i2c.h"
#include "screeninit.h"
#include "draw.h"
#include "i2c.h"
#include "buttons.h"
u32 waitInput(void)
@ -35,12 +35,6 @@ u32 waitInput(void)
return key;
}
void mcuShutDown(void)
{
i2cWriteRegister(I2C_DEV_MCU, 0x20, 1);
while(1);
}
void mcuReboot(void)
{
i2cWriteRegister(I2C_DEV_MCU, 0x20, 1 << 2);
@ -57,5 +51,6 @@ void error(const char *message)
waitInput();
mcuShutDown();
i2cWriteRegister(I2C_DEV_MCU, 0x20, 1);
while(1);
}

View File

@ -7,6 +7,5 @@
#include "types.h"
u32 waitInput(void);
void mcuShutDown(void);
void mcuReboot(void);
void error(const char *message);