added autobuild script and bootloader
This commit is contained in:
parent
9fcc1f0950
commit
3f9ba16962
23 changed files with 10544 additions and 0 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -15,3 +15,4 @@ html/
|
||||||
latex/
|
latex/
|
||||||
int.s
|
int.s
|
||||||
regs.h
|
regs.h
|
||||||
|
out/
|
||||||
|
|
12
boot/3ds/CMakeLists.txt
Normal file
12
boot/3ds/CMakeLists.txt
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
CMAKE_MINIMUM_REQUIRED(VERSION 2.8.0)
|
||||||
|
ENABLE_LANGUAGE(C CXX ASM-ATT)
|
||||||
|
FILE(GLOB SRCS *.c *.s)
|
||||||
|
FILE(GLOB_RECURSE FATFS_SRCS fatfs/*.c fatfs/*.s)
|
||||||
|
SET(CMAKE_ASM-ATT_COMPILE_OBJECT "<CMAKE_C_COMPILER> -g -x assembler-with-cpp -c -o -mcpu=arm946e-s -march=armv5te -o <OBJECT> <SOURCE>")
|
||||||
|
SET(CMAKE_C_FLAGS "-g -w -Werror -Wno-unused -Wno-unused-variable -mcpu=arm946e-s -march=armv5te -I.. -fno-stack-protector -nostdinc -ffreestanding -std=c11 -fno-builtin -w -Werror -nostdlib -fpie")
|
||||||
|
ADD_EXECUTABLE(arm9loaderhax.elf ${SRCS} ${FATFS_SRCS})
|
||||||
|
SET_TARGET_PROPERTIES(arm9loaderhax.elf PROPERTIES LINK_FLAGS "-T ../bootloader.ld")
|
||||||
|
TARGET_LINK_LIBRARIES(arm9loaderhax.elf gcc)
|
||||||
|
ADD_CUSTOM_COMMAND(TARGET arm9loaderhax.elf
|
||||||
|
POST_BUILD
|
||||||
|
COMMAND $ENV{HOME}/opt/bin/arm-none-eabi-objcopy -O binary arm9loaderhax.elf arm9loaderhax.bin)
|
BIN
boot/3ds/arm9loaderhax.bin
Executable file
BIN
boot/3ds/arm9loaderhax.bin
Executable file
Binary file not shown.
11
boot/3ds/bootloader.ld
Normal file
11
boot/3ds/bootloader.ld
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
ENTRY(_start)
|
||||||
|
SECTIONS
|
||||||
|
{
|
||||||
|
. = 0x23F00000;
|
||||||
|
.text.start : { *(.text.start)}
|
||||||
|
.text : {*(.text)}
|
||||||
|
.data : {*(.data)}
|
||||||
|
.bss : {*(.bss COMMON)}
|
||||||
|
.rodata : {*(.rodata)}
|
||||||
|
. = ALIGN(4);
|
||||||
|
}
|
21
boot/3ds/common.h
Normal file
21
boot/3ds/common.h
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
#define u8 unsigned char
|
||||||
|
#define u16 unsigned short
|
||||||
|
#define u32 unsigned int
|
||||||
|
#define u64 unsigned long long
|
||||||
|
#define bool int
|
||||||
|
#define true 1
|
||||||
|
#define false 0
|
||||||
|
#define NULL 0
|
||||||
|
#define vu8 volatile u8
|
||||||
|
#define vu16 volatile u16
|
||||||
|
#define vu32 volatile u32
|
||||||
|
#define vu64 volatile u64
|
||||||
|
|
||||||
|
#define max(a,b) \
|
||||||
|
({ __typeof__ (a) _a = (a); \
|
||||||
|
__typeof__ (b) _b = (b); \
|
||||||
|
_a > _b ? _a : _b; })
|
||||||
|
#define min(a,b) \
|
||||||
|
({ __typeof__ (a) _a = (a); \
|
||||||
|
__typeof__ (b) _b = (b); \
|
||||||
|
_a < _b ? _a : _b; })
|
10
boot/3ds/delay.h
Normal file
10
boot/3ds/delay.h
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
|
||||||
|
// 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);
|
17
boot/3ds/delay.s
Normal file
17
boot/3ds/delay.s
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
// 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
|
120
boot/3ds/fatfs/diskio.c
Normal file
120
boot/3ds/fatfs/diskio.c
Normal file
|
@ -0,0 +1,120 @@
|
||||||
|
/*-----------------------------------------------------------------------*/
|
||||||
|
/* Low level disk I/O module skeleton for FatFs (C)ChaN, 2013 */
|
||||||
|
/*-----------------------------------------------------------------------*/
|
||||||
|
/* 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 module to the FatFs module with a defined API. */
|
||||||
|
/*-----------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#include "diskio.h" /* FatFs lower layer API */
|
||||||
|
#include "../sdmmc.h"
|
||||||
|
|
||||||
|
/* Definitions of physical drive number for each media */
|
||||||
|
#define ATA 0
|
||||||
|
#define MMC 1
|
||||||
|
#define USB 2
|
||||||
|
|
||||||
|
static DSTATUS status;
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------*/
|
||||||
|
/* Inidialize a Drive */
|
||||||
|
/*-----------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
DSTATUS disk_initialize (
|
||||||
|
BYTE pdrv /* Physical drive nmuber (0..) */
|
||||||
|
)
|
||||||
|
{
|
||||||
|
int result = sdmmc_sdcard_init();
|
||||||
|
if (result)
|
||||||
|
{
|
||||||
|
status = STA_NOINIT;
|
||||||
|
}
|
||||||
|
status = RES_OK;
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------*/
|
||||||
|
/* Get Disk Status */
|
||||||
|
/*-----------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
DSTATUS disk_status (
|
||||||
|
BYTE pdrv /* Physical drive nmuber (0..) */
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------*/
|
||||||
|
/* Read Sector(s) */
|
||||||
|
/*-----------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
DRESULT disk_read (
|
||||||
|
BYTE pdrv, /* Physical drive nmuber (0..) */
|
||||||
|
BYTE *buff, /* Data buffer to store read data */
|
||||||
|
DWORD sector, /* Sector address (LBA) */
|
||||||
|
UINT count /* Number of sectors to read (1..128) */
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (!status)
|
||||||
|
{
|
||||||
|
switch(pdrv){
|
||||||
|
case 0:
|
||||||
|
if (sdmmc_sdcard_readsectors(sector,count,(u8*)buff))
|
||||||
|
return RES_PARERR;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return RES_OK;
|
||||||
|
}
|
||||||
|
return RES_NOTRDY;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------*/
|
||||||
|
/* Write Sector(s) */
|
||||||
|
/*-----------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#if _USE_WRITE
|
||||||
|
DRESULT disk_write (
|
||||||
|
BYTE pdrv, /* Physical drive nmuber (0..) */
|
||||||
|
const BYTE *buff, /* Data to be written */
|
||||||
|
DWORD sector, /* Sector address (LBA) */
|
||||||
|
UINT count /* Number of sectors to write (1..128) */
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (!status)
|
||||||
|
{
|
||||||
|
switch(pdrv){
|
||||||
|
case 0:
|
||||||
|
if (sdmmc_sdcard_writesectors(sector,count,(u8*)buff))
|
||||||
|
return RES_PARERR;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return RES_OK;
|
||||||
|
}
|
||||||
|
return RES_NOTRDY;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------*/
|
||||||
|
/* Miscellaneous Functions */
|
||||||
|
/*-----------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#if _USE_IOCTL
|
||||||
|
DRESULT disk_ioctl (
|
||||||
|
BYTE pdrv, /* Physical drive nmuber (0..) */
|
||||||
|
BYTE cmd, /* Control code */
|
||||||
|
void *buff /* Buffer to send/receive control data */
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (!status)
|
||||||
|
return RES_OK;
|
||||||
|
return RES_NOTRDY;
|
||||||
|
}
|
||||||
|
#endif
|
80
boot/3ds/fatfs/diskio.h
Normal file
80
boot/3ds/fatfs/diskio.h
Normal file
|
@ -0,0 +1,80 @@
|
||||||
|
/*-----------------------------------------------------------------------/
|
||||||
|
/ Low level disk interface modlue include file (C)ChaN, 2013 /
|
||||||
|
/-----------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#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 /* Flush disk cache (for write functions) */
|
||||||
|
#define GET_SECTOR_COUNT 1 /* Get media size (for only f_mkfs()) */
|
||||||
|
#define GET_SECTOR_SIZE 2 /* Get sector size (for multiple sector size (_MAX_SS >= 1024)) */
|
||||||
|
#define GET_BLOCK_SIZE 3 /* Get erase block size (for only f_mkfs()) */
|
||||||
|
#define CTRL_ERASE_SECTOR 4 /* Force erased a block of sectors (for only _USE_ERASE) */
|
||||||
|
|
||||||
|
/* 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
|
4734
boot/3ds/fatfs/ff.c
Normal file
4734
boot/3ds/fatfs/ff.c
Normal file
File diff suppressed because it is too large
Load diff
345
boot/3ds/fatfs/ff.h
Normal file
345
boot/3ds/fatfs/ff.h
Normal file
|
@ -0,0 +1,345 @@
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------/
|
||||||
|
/ FatFs - FAT file system module include file R0.10a (C)ChaN, 2014
|
||||||
|
/----------------------------------------------------------------------------/
|
||||||
|
/ FatFs module is a generic FAT file system module for small embedded systems.
|
||||||
|
/ This is a free software that opened for education, research and commercial
|
||||||
|
/ developments under license policy of following terms.
|
||||||
|
/
|
||||||
|
/ Copyright (C) 2014, ChaN, all right reserved.
|
||||||
|
/
|
||||||
|
/ * The FatFs module is a free software and there is NO WARRANTY.
|
||||||
|
/ * No restriction on use. You can use, modify and redistribute it for
|
||||||
|
/ personal, non-profit or commercial product UNDER YOUR RESPONSIBILITY.
|
||||||
|
/ * Redistributions of source code must retain the above copyright notice.
|
||||||
|
/
|
||||||
|
/----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#ifndef _FATFS
|
||||||
|
#define _FATFS 29000 /* 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
|
||||||
|
|
||||||
|
//----My Options----
|
||||||
|
|
||||||
|
|
||||||
|
//------------------
|
||||||
|
|
||||||
|
/* 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
|
||||||
|
#error _LFN_UNICODE must be 0 in 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; /* FAT sub-type (0:Not mounted) */
|
||||||
|
BYTE drv; /* Physical drive number */
|
||||||
|
BYTE csize; /* Sectors per cluster (1,2,4...128) */
|
||||||
|
BYTE n_fats; /* Number of FAT copies (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) */
|
||||||
|
#if _MAX_SS != _MIN_SS
|
||||||
|
WORD ssize; /* Bytes per sector (512, 1024, 2048 or 4096) */
|
||||||
|
#endif
|
||||||
|
#if _FS_REENTRANT
|
||||||
|
_SYNC_t sobj; /* Identifier of sync object */
|
||||||
|
#endif
|
||||||
|
#if !_FS_READONLY
|
||||||
|
DWORD last_clust; /* Last allocated cluster */
|
||||||
|
DWORD free_clust; /* Number of free clusters */
|
||||||
|
#endif
|
||||||
|
#if _FS_RPATH
|
||||||
|
DWORD cdir; /* Current directory start cluster (0:root) */
|
||||||
|
#endif
|
||||||
|
DWORD n_fatent; /* Number of FAT entries (= number of clusters + 2) */
|
||||||
|
DWORD fsize; /* Sectors per FAT */
|
||||||
|
DWORD volbase; /* Volume start sector */
|
||||||
|
DWORD fatbase; /* FAT start sector */
|
||||||
|
DWORD dirbase; /* Root directory start sector (FAT32:Cluster#) */
|
||||||
|
DWORD database; /* Data start 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;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* File object structure (FIL) */
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
FATFS* fs; /* Pointer to the related file system object (**do not change order**) */
|
||||||
|
WORD id; /* Owner file system mount ID (**do not change order**) */
|
||||||
|
BYTE flag; /* File status flags */
|
||||||
|
BYTE err; /* Abort flag (error code) */
|
||||||
|
DWORD fptr; /* File read/write pointer (Zeroed on file open) */
|
||||||
|
DWORD fsize; /* File size */
|
||||||
|
DWORD sclust; /* File data start cluster (0:no data cluster, always 0 when fsize is 0) */
|
||||||
|
DWORD clust; /* Current cluster of fpter */
|
||||||
|
DWORD dsect; /* Current data sector of fpter */
|
||||||
|
#if !_FS_READONLY
|
||||||
|
DWORD dir_sect; /* Sector containing the directory entry */
|
||||||
|
BYTE* dir_ptr; /* Pointer to the directory entry in the window */
|
||||||
|
#endif
|
||||||
|
#if _USE_FASTSEEK
|
||||||
|
DWORD* cltbl; /* Pointer to the cluster link map table (Nulled on file open) */
|
||||||
|
#endif
|
||||||
|
#if _FS_LOCK
|
||||||
|
UINT lockid; /* File lock ID (index of file semaphore table Files[]) */
|
||||||
|
#endif
|
||||||
|
#if !_FS_TINY
|
||||||
|
BYTE buf[_MAX_SS]; /* File data read/write buffer */
|
||||||
|
#endif
|
||||||
|
} FIL;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Directory object structure (DIR) */
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
FATFS* fs; /* Pointer to the owner file system object (**do not change order**) */
|
||||||
|
WORD id; /* Owner file system mount ID (**do not change order**) */
|
||||||
|
WORD index; /* Current read/write index number */
|
||||||
|
DWORD sclust; /* Table start cluster (0:Root dir) */
|
||||||
|
DWORD clust; /* Current cluster */
|
||||||
|
DWORD sect; /* Current sector */
|
||||||
|
BYTE* dir; /* Pointer to the current SFN entry in the win[] */
|
||||||
|
BYTE* fn; /* Pointer to the SFN (in/out) {file[8],ext[3],status[1]} */
|
||||||
|
#if _FS_LOCK
|
||||||
|
UINT lockid; /* File lock ID (index of file semaphore table Files[]) */
|
||||||
|
#endif
|
||||||
|
#if _USE_LFN
|
||||||
|
WCHAR* lfn; /* Pointer to the LFN working buffer */
|
||||||
|
WORD lfn_idx; /* Last matched LFN index number (0xFFFF:No LFN) */
|
||||||
|
#endif
|
||||||
|
} DIR;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* File status structure (FILINFO) */
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
DWORD fsize; /* File size */
|
||||||
|
WORD fdate; /* Last modified date */
|
||||||
|
WORD ftime; /* Last modified time */
|
||||||
|
BYTE fattrib; /* Attribute */
|
||||||
|
TCHAR fname[13]; /* Short file name (8.3 format) */
|
||||||
|
#if _USE_LFN
|
||||||
|
TCHAR* lfname; /* Pointer to the LFN buffer */
|
||||||
|
UINT lfsize; /* Size of LFN buffer in TCHAR */
|
||||||
|
#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_SHARE */
|
||||||
|
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_forward (FIL* fp, UINT(*func)(const BYTE*,UINT), UINT btf, UINT* bf); /* Forward data to the stream */
|
||||||
|
FRESULT f_lseek (FIL* fp, DWORD 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_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 value, BYTE mask); /* Change attribute of the file/dir */
|
||||||
|
FRESULT f_utime (const TCHAR* path, const FILINFO* fno); /* Change times-tamp 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* sn); /* Get volume label */
|
||||||
|
FRESULT f_setlabel (const TCHAR* label); /* Set volume label */
|
||||||
|
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) (((fp)->fptr == (fp)->fsize) ? 1 : 0)
|
||||||
|
#define f_error(fp) ((fp)->err)
|
||||||
|
#define f_tell(fp) ((fp)->fptr)
|
||||||
|
#define f_size(fp) ((fp)->fsize)
|
||||||
|
|
||||||
|
#ifndef EOF
|
||||||
|
#define EOF (-1)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*--------------------------------------------------------------*/
|
||||||
|
/* Additional user defined functions */
|
||||||
|
|
||||||
|
/* RTC function */
|
||||||
|
#if !_FS_READONLY
|
||||||
|
DWORD get_fattime (void);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Unicode support functions */
|
||||||
|
#if _USE_LFN /* 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_OPEN_EXISTING 0x00
|
||||||
|
|
||||||
|
#if !_FS_READONLY
|
||||||
|
#define FA_WRITE 0x02
|
||||||
|
#define FA_CREATE_NEW 0x04
|
||||||
|
#define FA_CREATE_ALWAYS 0x08
|
||||||
|
#define FA_OPEN_ALWAYS 0x10
|
||||||
|
#define FA__WRITTEN 0x20
|
||||||
|
#define FA__DIRTY 0x40
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* FAT sub type (FATFS.fs_type) */
|
||||||
|
|
||||||
|
#define FS_FAT12 1
|
||||||
|
#define FS_FAT16 2
|
||||||
|
#define FS_FAT32 3
|
||||||
|
|
||||||
|
|
||||||
|
/* 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 feature */
|
||||||
|
#define CREATE_LINKMAP 0xFFFFFFFF
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*--------------------------------*/
|
||||||
|
/* Multi-byte word access macros */
|
||||||
|
|
||||||
|
#if _WORD_ACCESS == 1 /* Enable word access to the FAT structure */
|
||||||
|
#define LD_WORD(ptr) (WORD)(*(WORD*)(BYTE*)(ptr))
|
||||||
|
#define LD_DWORD(ptr) (DWORD)(*(DWORD*)(BYTE*)(ptr))
|
||||||
|
#define ST_WORD(ptr,val) *(WORD*)(BYTE*)(ptr)=(WORD)(val)
|
||||||
|
#define ST_DWORD(ptr,val) *(DWORD*)(BYTE*)(ptr)=(DWORD)(val)
|
||||||
|
#else /* Use byte-by-byte access to the FAT structure */
|
||||||
|
#define LD_WORD(ptr) (WORD)(((WORD)*((BYTE*)(ptr)+1)<<8)|(WORD)*(BYTE*)(ptr))
|
||||||
|
#define LD_DWORD(ptr) (DWORD)(((DWORD)*((BYTE*)(ptr)+3)<<24)|((DWORD)*((BYTE*)(ptr)+2)<<16)|((WORD)*((BYTE*)(ptr)+1)<<8)|*(BYTE*)(ptr))
|
||||||
|
#define ST_WORD(ptr,val) *(BYTE*)(ptr)=(BYTE)(val); *((BYTE*)(ptr)+1)=(BYTE)((WORD)(val)>>8)
|
||||||
|
#define ST_DWORD(ptr,val) *(BYTE*)(ptr)=(BYTE)(val); *((BYTE*)(ptr)+1)=(BYTE)((WORD)(val)>>8); *((BYTE*)(ptr)+2)=(BYTE)((DWORD)(val)>>16); *((BYTE*)(ptr)+3)=(BYTE)((DWORD)(val)>>24)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* _FATFS */
|
222
boot/3ds/fatfs/ffconf.h
Normal file
222
boot/3ds/fatfs/ffconf.h
Normal file
|
@ -0,0 +1,222 @@
|
||||||
|
/*---------------------------------------------------------------------------/
|
||||||
|
/ FatFs - FAT file system module configuration file R0.10a (C)ChaN, 2014
|
||||||
|
/---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#ifndef _FFCONF
|
||||||
|
#define _FFCONF 29000 /* Revision ID */
|
||||||
|
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------/
|
||||||
|
/ Functions and Buffer Configurations
|
||||||
|
/---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#define _FS_TINY 1 /* 0:Normal or 1:Tiny */
|
||||||
|
/* When _FS_TINY is set to 1, it reduces memory consumption _MAX_SS bytes each
|
||||||
|
/ file object. For file data transfer, FatFs uses the common sector buffer in
|
||||||
|
/ the file system object (FATFS) instead of private sector buffer eliminated
|
||||||
|
/ from the file object (FIL). */
|
||||||
|
|
||||||
|
|
||||||
|
#define _FS_READONLY 1 /* 0:Read/Write or 1:Read only */
|
||||||
|
/* Setting _FS_READONLY to 1 defines read only configuration. This removes
|
||||||
|
/ writing functions, f_write(), f_sync(), f_unlink(), f_mkdir(), f_chmod(),
|
||||||
|
/ f_rename(), f_truncate() and useless f_getfree(). */
|
||||||
|
|
||||||
|
|
||||||
|
#define _FS_MINIMIZE 2 /* 0 to 3 */
|
||||||
|
/* The _FS_MINIMIZE option defines minimization level to remove API functions.
|
||||||
|
/
|
||||||
|
/ 0: All basic functions are enabled.
|
||||||
|
/ 1: f_stat(), f_getfree(), f_unlink(), f_mkdir(), f_chmod(), f_utime(),
|
||||||
|
/ f_truncate() and f_rename() function 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 /* 0:Disable or 1-2:Enable */
|
||||||
|
/* To enable string functions, set _USE_STRFUNC to 1 or 2. */
|
||||||
|
|
||||||
|
|
||||||
|
#define _USE_MKFS 0 /* 0:Disable or 1:Enable */
|
||||||
|
/* To enable f_mkfs() function, set _USE_MKFS to 1 and set _FS_READONLY to 0 */
|
||||||
|
|
||||||
|
|
||||||
|
#define _USE_FASTSEEK 0 /* 0:Disable or 1:Enable */
|
||||||
|
/* To enable fast seek feature, set _USE_FASTSEEK to 1. */
|
||||||
|
|
||||||
|
|
||||||
|
#define _USE_LABEL 0 /* 0:Disable or 1:Enable */
|
||||||
|
/* To enable volume label functions, set _USE_LAVEL to 1 */
|
||||||
|
|
||||||
|
|
||||||
|
#define _USE_FORWARD 0 /* 0:Disable or 1:Enable */
|
||||||
|
/* To enable f_forward() function, set _USE_FORWARD to 1 and set _FS_TINY to 1. */
|
||||||
|
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------/
|
||||||
|
/ Locale and Namespace Configurations
|
||||||
|
/---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#define _CODE_PAGE 932
|
||||||
|
/* The _CODE_PAGE specifies the OEM code page to be used on the target system.
|
||||||
|
/ Incorrect setting of the code page can cause a file open failure.
|
||||||
|
/
|
||||||
|
/ 932 - Japanese Shift-JIS (DBCS, OEM, Windows)
|
||||||
|
/ 936 - Simplified Chinese GBK (DBCS, OEM, Windows)
|
||||||
|
/ 949 - Korean (DBCS, OEM, Windows)
|
||||||
|
/ 950 - Traditional Chinese Big5 (DBCS, OEM, Windows)
|
||||||
|
/ 1250 - Central Europe (Windows)
|
||||||
|
/ 1251 - Cyrillic (Windows)
|
||||||
|
/ 1252 - Latin 1 (Windows)
|
||||||
|
/ 1253 - Greek (Windows)
|
||||||
|
/ 1254 - Turkish (Windows)
|
||||||
|
/ 1255 - Hebrew (Windows)
|
||||||
|
/ 1256 - Arabic (Windows)
|
||||||
|
/ 1257 - Baltic (Windows)
|
||||||
|
/ 1258 - Vietnam (OEM, Windows)
|
||||||
|
/ 437 - U.S. (OEM)
|
||||||
|
/ 720 - Arabic (OEM)
|
||||||
|
/ 737 - Greek (OEM)
|
||||||
|
/ 775 - Baltic (OEM)
|
||||||
|
/ 850 - Multilingual Latin 1 (OEM)
|
||||||
|
/ 858 - Multilingual Latin 1 + Euro (OEM)
|
||||||
|
/ 852 - Latin 2 (OEM)
|
||||||
|
/ 855 - Cyrillic (OEM)
|
||||||
|
/ 866 - Russian (OEM)
|
||||||
|
/ 857 - Turkish (OEM)
|
||||||
|
/ 862 - Hebrew (OEM)
|
||||||
|
/ 874 - Thai (OEM, Windows)
|
||||||
|
/ 1 - ASCII (Valid for only non-LFN cfg.) */
|
||||||
|
|
||||||
|
|
||||||
|
#define _USE_LFN 1 /* 0 to 3 */
|
||||||
|
#define _MAX_LFN 255 /* Maximum LFN length to handle (12 to 255) */
|
||||||
|
/* The _USE_LFN option switches the LFN feature.
|
||||||
|
/
|
||||||
|
/ 0: Disable LFN feature. _MAX_LFN and _LFN_UNICODE have 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.
|
||||||
|
/
|
||||||
|
/ When enable LFN feature, Unicode handling functions ff_convert() and ff_wtoupper()
|
||||||
|
/ function must be added to the project.
|
||||||
|
/ The LFN working buffer occupies (_MAX_LFN + 1) * 2 bytes. 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 /* 0:ANSI/OEM or 1:Unicode */
|
||||||
|
/* To switch the character encoding on the FatFs API (TCHAR) to Unicode, enable LFN
|
||||||
|
/ feature and set _LFN_UNICODE to 1. This option affects behavior of string I/O
|
||||||
|
/ functions. */
|
||||||
|
|
||||||
|
|
||||||
|
#define _STRF_ENCODE 0 /* 0:ANSI/OEM, 1:UTF-16LE, 2:UTF-16BE, 3:UTF-8 */
|
||||||
|
/* When Unicode API is enabled by _LFN_UNICODE option, 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(). This option has no effect when Unicode API is not enabled. */
|
||||||
|
|
||||||
|
|
||||||
|
#define _FS_RPATH 0 /* 0 to 2 */
|
||||||
|
/* The _FS_RPATH option configures relative path feature.
|
||||||
|
/
|
||||||
|
/ 0: Disable relative path feature and remove related functions.
|
||||||
|
/ 1: Enable relative path. f_chdrive() and f_chdir() function are available.
|
||||||
|
/ 2: f_getcwd() function is available in addition to 1.
|
||||||
|
/
|
||||||
|
/ Note that output of the f_readdir() fnction is affected by this option. */
|
||||||
|
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------/
|
||||||
|
/ Drive/Volume Configurations
|
||||||
|
/---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#define _VOLUMES 8
|
||||||
|
/* Number of volumes (logical drives) to be used. */
|
||||||
|
|
||||||
|
|
||||||
|
#define _STR_VOLUME_ID 0 /* 0:Use only 0-9 for drive ID, 1:Use strings for drive ID */
|
||||||
|
#define _VOLUME_STRS "RAM","NAND","CF","SD1","SD2","USB1","USB2","USB3"
|
||||||
|
/* When _STR_VOLUME_ID is set to 1, also pre-defined string 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: 0-9 and A-Z. */
|
||||||
|
|
||||||
|
|
||||||
|
#define _MULTI_PARTITION 0 /* 0:Single partition, 1:Enable multiple partition */
|
||||||
|
/* By default(0), each logical drive number is bound to the same physical drive number
|
||||||
|
/ and only a FAT volume found on the physical drive is mounted. When it is set to 1,
|
||||||
|
/ each logical drive number is bound to arbitrary drive/partition listed in VolToPart[].
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#define _MIN_SS 512
|
||||||
|
#define _MAX_SS 512
|
||||||
|
/* These options configure the sector size to be supported. (512, 1024, 2048 or 4096)
|
||||||
|
/ Always set both 512 for most systems, all memory card and hard disk. But a larger
|
||||||
|
/ value may be required for on-board flash memory and some type of optical media.
|
||||||
|
/ When _MIN_SS != _MAX_SS, FatFs is configured to multiple sector size and
|
||||||
|
/ GET_SECTOR_SIZE command must be implemented to the disk_ioctl() function. */
|
||||||
|
|
||||||
|
|
||||||
|
#define _USE_ERASE 0 /* 0:Disable or 1:Enable */
|
||||||
|
/* To enable sector erase feature, set _USE_ERASE to 1. Also CTRL_ERASE_SECTOR command
|
||||||
|
/ should be added to the disk_ioctl() function. */
|
||||||
|
|
||||||
|
|
||||||
|
#define _FS_NOFSINFO 0 /* 0 to 3 */
|
||||||
|
/* 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 last allocated cluster number as bit 0.
|
||||||
|
/
|
||||||
|
/ 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 _WORD_ACCESS 0 /* 0 or 1 */
|
||||||
|
/* The _WORD_ACCESS option is an only platform dependent option. It defines
|
||||||
|
/ which access method is used to the word data on the FAT volume.
|
||||||
|
/
|
||||||
|
/ 0: Byte-by-byte access. Always compatible with all platforms.
|
||||||
|
/ 1: Word access. Do not choose this unless under both the following conditions.
|
||||||
|
/
|
||||||
|
/ * Address misaligned memory access is always allowed for all instructions.
|
||||||
|
/ * Byte order on the memory is little-endian.
|
||||||
|
/
|
||||||
|
/ If it is the case, _WORD_ACCESS can also be set to 1 to improve performance
|
||||||
|
/ and reduce code size.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#define _FS_LOCK 0 /* 0:Disable or >=1:Enable */
|
||||||
|
/* To enable file lock control feature, set _FS_LOCK to 1 or greater.
|
||||||
|
/ The value defines how many files/sub-directories can be opened simultaneously.
|
||||||
|
/ This feature consumes _FS_LOCK * 12 bytes of bss area. */
|
||||||
|
|
||||||
|
|
||||||
|
#define _FS_REENTRANT 0 /* 0:Disable or 1:Enable */
|
||||||
|
#define _FS_TIMEOUT 1000 /* Timeout period in unit of time ticks */
|
||||||
|
#define _SYNC_t HANDLE /* O/S dependent sync object type. e.g. HANDLE, OS_EVENT*, ID and etc.. */
|
||||||
|
/*#include <windows.h>*/
|
||||||
|
|
||||||
|
/* A header file that defines sync object types on the O/S, such as windows.h,
|
||||||
|
/ ucos_ii.h and semphr.h, should be included here when enable this option.
|
||||||
|
/ The _FS_REENTRANT option switches the re-entrancy (thread safe) of the FatFs module.
|
||||||
|
/
|
||||||
|
/ 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* _FFCONFIG */
|
33
boot/3ds/fatfs/integer.h
Normal file
33
boot/3ds/fatfs/integer.h
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
/*-------------------------------------------*/
|
||||||
|
/* Integer type definitions for FatFs module */
|
||||||
|
/*-------------------------------------------*/
|
||||||
|
|
||||||
|
#ifndef _FF_INTEGER
|
||||||
|
#define _FF_INTEGER
|
||||||
|
|
||||||
|
#ifdef _WIN32 /* FatFs development platform */
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
#include <tchar.h>
|
||||||
|
|
||||||
|
#else /* Embedded platform */
|
||||||
|
|
||||||
|
/* 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 16 bit or 32 bit */
|
||||||
|
typedef int INT;
|
||||||
|
typedef unsigned int UINT;
|
||||||
|
|
||||||
|
/* These types MUST be 32 bit */
|
||||||
|
typedef long LONG;
|
||||||
|
typedef unsigned long DWORD;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
3798
boot/3ds/fatfs/options/cc932.c
Normal file
3798
boot/3ds/fatfs/options/cc932.c
Normal file
File diff suppressed because it is too large
Load diff
151
boot/3ds/fatfs/options/syscall.c
Normal file
151
boot/3ds/fatfs/options/syscall.c
Normal file
|
@ -0,0 +1,151 @@
|
||||||
|
/*------------------------------------------------------------------------*/
|
||||||
|
/* Sample code of OS dependent controls for FatFs */
|
||||||
|
/* (C)ChaN, 2014 */
|
||||||
|
/*------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "../ff.h"
|
||||||
|
|
||||||
|
|
||||||
|
#if _FS_REENTRANT
|
||||||
|
/*------------------------------------------------------------------------*/
|
||||||
|
/* Create a Synchronization Object
|
||||||
|
/*------------------------------------------------------------------------*/
|
||||||
|
/* This function is called in f_mount() function to create a new
|
||||||
|
/ synchronization object, such as semaphore and mutex. When a 0 is returned,
|
||||||
|
/ the f_mount() function fails with FR_INT_ERR.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int ff_cre_syncobj ( /* !=0:Function succeeded, ==0:Could not create due to any error */
|
||||||
|
BYTE vol, /* Corresponding logical drive being processed */
|
||||||
|
_SYNC_t *sobj /* Pointer to return the created sync object */
|
||||||
|
)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
|
||||||
|
*sobj = CreateMutex(NULL, FALSE, NULL); /* Win32 */
|
||||||
|
ret = (int)(*sobj != INVALID_HANDLE_VALUE);
|
||||||
|
|
||||||
|
// *sobj = SyncObjects[vol]; /* uITRON (give a static created sync object) */
|
||||||
|
// ret = 1; /* The initial value of the semaphore must be 1. */
|
||||||
|
|
||||||
|
// *sobj = OSMutexCreate(0, &err); /* uC/OS-II */
|
||||||
|
// ret = (int)(err == OS_NO_ERR);
|
||||||
|
|
||||||
|
// *sobj = xSemaphoreCreateMutex(); /* FreeRTOS */
|
||||||
|
// ret = (int)(*sobj != NULL);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------------*/
|
||||||
|
/* Delete a Synchronization Object */
|
||||||
|
/*------------------------------------------------------------------------*/
|
||||||
|
/* This function is called in f_mount() function to delete a synchronization
|
||||||
|
/ object that created with ff_cre_syncobj function. When a 0 is returned,
|
||||||
|
/ the f_mount() function fails with FR_INT_ERR.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int ff_del_syncobj ( /* !=0:Function succeeded, ==0:Could not delete due to any error */
|
||||||
|
_SYNC_t sobj /* Sync object tied to the logical drive to be deleted */
|
||||||
|
)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
|
||||||
|
ret = CloseHandle(sobj); /* Win32 */
|
||||||
|
|
||||||
|
// ret = 1; /* uITRON (nothing to do) */
|
||||||
|
|
||||||
|
// OSMutexDel(sobj, OS_DEL_ALWAYS, &err); /* uC/OS-II */
|
||||||
|
// ret = (int)(err == OS_NO_ERR);
|
||||||
|
|
||||||
|
// vSemaphoreDelete(sobj); /* FreeRTOS */
|
||||||
|
// ret = 1;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------------*/
|
||||||
|
/* Request Grant to Access the Volume */
|
||||||
|
/*------------------------------------------------------------------------*/
|
||||||
|
/* This function is called on entering file functions to lock the volume.
|
||||||
|
/ When a 0 is returned, the file function fails with FR_TIMEOUT.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int ff_req_grant ( /* 1:Got a grant to access the volume, 0:Could not get a grant */
|
||||||
|
_SYNC_t sobj /* Sync object to wait */
|
||||||
|
)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = (int)(WaitForSingleObject(sobj, _FS_TIMEOUT) == WAIT_OBJECT_0); /* Win32 */
|
||||||
|
|
||||||
|
// ret = (int)(wai_sem(sobj) == E_OK); /* uITRON */
|
||||||
|
|
||||||
|
// OSMutexPend(sobj, _FS_TIMEOUT, &err)); /* uC/OS-II */
|
||||||
|
// ret = (int)(err == OS_NO_ERR);
|
||||||
|
|
||||||
|
// ret = (int)(xSemaphoreTake(sobj, _FS_TIMEOUT) == pdTRUE); /* FreeRTOS */
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------------*/
|
||||||
|
/* Release Grant to Access the Volume */
|
||||||
|
/*------------------------------------------------------------------------*/
|
||||||
|
/* This function is called on leaving file functions to unlock the volume.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void ff_rel_grant (
|
||||||
|
_SYNC_t sobj /* Sync object to be signaled */
|
||||||
|
)
|
||||||
|
{
|
||||||
|
ReleaseMutex(sobj); /* Win32 */
|
||||||
|
|
||||||
|
// sig_sem(sobj); /* uITRON */
|
||||||
|
|
||||||
|
// OSMutexPost(sobj); /* uC/OS-II */
|
||||||
|
|
||||||
|
// xSemaphoreGive(sobj); /* FreeRTOS */
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#if _USE_LFN == 3 /* LFN with a working buffer on the heap */
|
||||||
|
/*------------------------------------------------------------------------*/
|
||||||
|
/* Allocate a memory block */
|
||||||
|
/*------------------------------------------------------------------------*/
|
||||||
|
/* If a NULL is returned, the file function fails with FR_NOT_ENOUGH_CORE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void* ff_memalloc ( /* Returns pointer to the allocated memory block */
|
||||||
|
UINT msize /* Number of bytes to allocate */
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return malloc(msize); /* Allocate a new memory block with POSIX API */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------------*/
|
||||||
|
/* Free a memory block */
|
||||||
|
/*------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void ff_memfree (
|
||||||
|
void* mblock /* Pointer to the memory block to free */
|
||||||
|
)
|
||||||
|
{
|
||||||
|
free(mblock); /* Discard the memory block with POSIX API */
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
91
boot/3ds/main.c
Normal file
91
boot/3ds/main.c
Normal file
|
@ -0,0 +1,91 @@
|
||||||
|
#include "common.h"
|
||||||
|
#include "sdmmc.h"
|
||||||
|
#include "fatfs/ff.h"
|
||||||
|
char *lfb=(char*)0x18346500;
|
||||||
|
#ifdef ARM9
|
||||||
|
#define DIAGPXL(i) (lfb[6*(i)]=lfb[6*(i)+1]=lfb[6*(i)+2]=0xFF)
|
||||||
|
#else
|
||||||
|
#define DIAGPXL(i) (0)
|
||||||
|
#endif
|
||||||
|
/**
|
||||||
|
* \struct FIRM_sect
|
||||||
|
* \brief Contains one section of the FIRM format
|
||||||
|
*/
|
||||||
|
struct FIRM_sect {
|
||||||
|
unsigned int offset; //! Offset in file (bytes)
|
||||||
|
unsigned int physical; //! Physical address, where the section is copied to
|
||||||
|
unsigned int size; //! Size of section
|
||||||
|
unsigned int arm11; //! currently unused
|
||||||
|
unsigned char SHA256[0x20]; //! Currently unused
|
||||||
|
}__attribute__((packed));
|
||||||
|
/**
|
||||||
|
* \struct FIRM_header
|
||||||
|
* \brief Contains the first sector of every FIRM file.
|
||||||
|
*/
|
||||||
|
struct FIRM_header {
|
||||||
|
char magic[4]; //! Magic "FIRM" string (not-null terminated)
|
||||||
|
int version; //! Version. Currently 1
|
||||||
|
void(*entrypoint)(void**); //! Address where the processor jumps to after loading
|
||||||
|
void (*arm11entry)(void**);
|
||||||
|
unsigned int reserved[0xC];
|
||||||
|
struct FIRM_sect sections[4]; //! The four internal sections
|
||||||
|
unsigned char RSA2048[0x100]; //! Currently unused
|
||||||
|
}__attribute__((packed));
|
||||||
|
/**
|
||||||
|
* \brief Module table for the kernel (Up to 1024 mods)
|
||||||
|
*/
|
||||||
|
void *arm9modtable[64];
|
||||||
|
void *arm11modtable[64];
|
||||||
|
struct FIRM_header hdr;
|
||||||
|
void doARM11() {
|
||||||
|
DIAGPXL(0);
|
||||||
|
hdr.arm11entry(arm11modtable);
|
||||||
|
for(;;);
|
||||||
|
}
|
||||||
|
void init() {
|
||||||
|
FATFS fs;
|
||||||
|
FIL firm;
|
||||||
|
f_mount(&fs, "0:", 0);
|
||||||
|
unsigned int off=0x20000000;
|
||||||
|
arm9modtable[0]=0x20000000;
|
||||||
|
arm9modtable[1]=0;
|
||||||
|
arm11modtable[0]=0x20000000;
|
||||||
|
arm11modtable[1]=0;
|
||||||
|
if(f_open(&firm, "mtgos.firm", FA_READ | FA_OPEN_EXISTING) == FR_OK) {
|
||||||
|
DIAGPXL(1);
|
||||||
|
unsigned int br;
|
||||||
|
f_read(&firm, (void*)&hdr, sizeof(struct FIRM_header), &br);
|
||||||
|
DIAGPXL(2);
|
||||||
|
if((hdr.magic[0]!='F')||(hdr.magic[1]!='I')||(hdr.magic[2]!='R')||(hdr.magic[3]!='M'))
|
||||||
|
while(1);
|
||||||
|
DIAGPXL(3);
|
||||||
|
for(int i=0;i<4;i++) { //Load sections
|
||||||
|
if(hdr.sections[i].size==0)
|
||||||
|
continue;
|
||||||
|
f_lseek(&firm, hdr.sections[i].offset);
|
||||||
|
*((char*)hdr.sections[i].physical)=0xFF;
|
||||||
|
char oldval=0xFF;
|
||||||
|
f_read(&firm, (void*)hdr.sections[i].physical, hdr.sections[i].size, &br);
|
||||||
|
if(oldval!=*((char*)hdr.sections[i].physical))
|
||||||
|
DIAGPXL(i+4);
|
||||||
|
DIAGPXL(i+8);
|
||||||
|
}
|
||||||
|
DIAGPXL(12);
|
||||||
|
FIL dsp_txt9;
|
||||||
|
f_open(&dsp_txt9, "dsp_txt.neun", FA_READ | FA_OPEN_EXISTING);
|
||||||
|
f_read(&dsp_txt9, (void*)off, f_size(&dsp_txt9), &br);
|
||||||
|
off+=f_size(&dsp_txt9);
|
||||||
|
off&=~0xfff;
|
||||||
|
off+=0x1000;
|
||||||
|
FIL dsp_txt11;
|
||||||
|
arm11modtable[0]=off;
|
||||||
|
arm11modtable[1]=0;
|
||||||
|
f_open(&dsp_txt11, "dsp_txt.elf", FA_READ | FA_OPEN_EXISTING);
|
||||||
|
f_read(&dsp_txt11, (void*)off, f_size(&dsp_txt11), &br);
|
||||||
|
off+=f_size(&dsp_txt11);
|
||||||
|
void(**a11fpointer)(void)=(void(**)(void**))0x1FFFFFF8;
|
||||||
|
*a11fpointer=&doARM11;
|
||||||
|
hdr.entrypoint(arm9modtable); //Jump to kernel
|
||||||
|
}
|
||||||
|
for(;;);
|
||||||
|
}
|
3
boot/3ds/readme
Normal file
3
boot/3ds/readme
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
Every file in this directory except for 'main.c', 'loader.ld' and 'Makefile'
|
||||||
|
are copied from https://github.com/delebile/arm9loaderhax and is distributed
|
||||||
|
under the GPLv3. Those files almost completely untouched.
|
500
boot/3ds/sdmmc.c
Normal file
500
boot/3ds/sdmmc.c
Normal file
|
@ -0,0 +1,500 @@
|
||||||
|
// Copyright 2014 Normmatt
|
||||||
|
// Licensed under GPLv2 or any later version
|
||||||
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
#include "sdmmc.h"
|
||||||
|
#include "delay.h"
|
||||||
|
|
||||||
|
//Uncomment to enable 32bit fifo support?
|
||||||
|
//not currently working
|
||||||
|
//#define DATA32_SUPPORT
|
||||||
|
|
||||||
|
static struct mmcdevice handleNAND;
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
mmcdevice *getMMCDevice(int drive)
|
||||||
|
{
|
||||||
|
if(drive==0) return &handleNAND;
|
||||||
|
return &handleSD;
|
||||||
|
}
|
||||||
|
|
||||||
|
int __attribute__((noinline)) geterror(struct mmcdevice *ctx)
|
||||||
|
{
|
||||||
|
//if(ctx->error == 0x4) return -1;
|
||||||
|
//else return 0;
|
||||||
|
return (ctx->error << 29) >> 31;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
#ifdef DATA32_SUPPORT
|
||||||
|
if (readdata)
|
||||||
|
sdmmc_mask16(REG_SDDATACTL32, 0x1000, 0x800);
|
||||||
|
if (writedata)
|
||||||
|
sdmmc_mask16(REG_SDDATACTL32, 0x800, 0x1000);
|
||||||
|
#else
|
||||||
|
sdmmc_mask16(REG_SDDATACTL32,0x1800,0);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
sdmmc_write16(REG_SDCMDARG0,args &0xFFFF);
|
||||||
|
sdmmc_write16(REG_SDCMDARG1,args >> 16);
|
||||||
|
sdmmc_write16(REG_SDCMD,cmd &0xFFFF);
|
||||||
|
|
||||||
|
u32 size = ctx->size;
|
||||||
|
u16 *dataPtr = (u16*)ctx->data;
|
||||||
|
#ifdef DATA32_SUPPORT
|
||||||
|
u32 *dataPtr32 = (u32*)ctx->data;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
bool useBuf = ( NULL != dataPtr );
|
||||||
|
#ifdef DATA32_SUPPORT
|
||||||
|
bool useBuf32 = (useBuf && (0 == (3 & ((u32)dataPtr))));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
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) {
|
||||||
|
#ifdef DATA32_SUPPORT
|
||||||
|
if (useBuf32) {
|
||||||
|
for(int i = 0; i<0x200; i+=4)
|
||||||
|
*dataPtr32++ = sdmmc_read32(REG_SDFIFO32);
|
||||||
|
} else {
|
||||||
|
#endif
|
||||||
|
for(int i = 0; i<0x200; i+=2)
|
||||||
|
*dataPtr++ = sdmmc_read16(REG_SDFIFO);
|
||||||
|
#ifdef DATA32_SUPPORT
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
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) {
|
||||||
|
#ifdef DATA32_SUPPORT
|
||||||
|
for (int i = 0; i<0x200; i+=4)
|
||||||
|
sdmmc_write32(REG_SDFIFO32,*dataPtr32++);
|
||||||
|
#else
|
||||||
|
for (int i = 0; i<0x200; i+=2)
|
||||||
|
sdmmc_write16(REG_SDFIFO,*dataPtr++);
|
||||||
|
#endif
|
||||||
|
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] = sdmmc_read16(REG_SDRESP0) | (sdmmc_read16(REG_SDRESP1) << 16);
|
||||||
|
ctx->ret[1] = sdmmc_read16(REG_SDRESP2) | (sdmmc_read16(REG_SDRESP3) << 16);
|
||||||
|
ctx->ret[2] = sdmmc_read16(REG_SDRESP4) | (sdmmc_read16(REG_SDRESP5) << 16);
|
||||||
|
ctx->ret[3] = sdmmc_read16(REG_SDRESP6) | (sdmmc_read16(REG_SDRESP7) << 16);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int __attribute__((noinline)) sdmmc_sdcard_writesectors(u32 sector_no, u32 numsectors, u8 *in)
|
||||||
|
{
|
||||||
|
if (handleSD.isSDHC == 0)
|
||||||
|
sector_no <<= 9;
|
||||||
|
inittarget(&handleSD);
|
||||||
|
sdmmc_write16(REG_SDSTOP,0x100);
|
||||||
|
|
||||||
|
#ifdef DATA32_SUPPORT
|
||||||
|
sdmmc_write16(REG_SDBLKCOUNT32,numsectors);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
sdmmc_write16(REG_SDBLKCOUNT,numsectors);
|
||||||
|
handleSD.data = in;
|
||||||
|
handleSD.size = numsectors << 9;
|
||||||
|
sdmmc_send_command(&handleSD,0x52C19,sector_no);
|
||||||
|
return geterror(&handleSD);
|
||||||
|
}
|
||||||
|
|
||||||
|
int __attribute__((noinline)) sdmmc_sdcard_readsectors(u32 sector_no, u32 numsectors, u8 *out)
|
||||||
|
{
|
||||||
|
if (handleSD.isSDHC == 0)
|
||||||
|
sector_no <<= 9;
|
||||||
|
inittarget(&handleSD);
|
||||||
|
sdmmc_write16(REG_SDSTOP,0x100);
|
||||||
|
|
||||||
|
#ifdef DATA32_SUPPORT
|
||||||
|
sdmmc_write16(REG_SDBLKCOUNT32,numsectors);
|
||||||
|
sdmmc_write16(REG_SDBLKLEN32,0x200);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
sdmmc_write16(REG_SDBLKCOUNT,numsectors);
|
||||||
|
handleSD.data = out;
|
||||||
|
handleSD.size = numsectors << 9;
|
||||||
|
sdmmc_send_command(&handleSD,0x33C12,sector_no);
|
||||||
|
return geterror(&handleSD);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int __attribute__((noinline)) sdmmc_nand_readsectors(u32 sector_no, u32 numsectors, u8 *out)
|
||||||
|
{
|
||||||
|
if (handleNAND.isSDHC == 0)
|
||||||
|
sector_no <<= 9;
|
||||||
|
inittarget(&handleNAND);
|
||||||
|
sdmmc_write16(REG_SDSTOP,0x100);
|
||||||
|
|
||||||
|
#ifdef DATA32_SUPPORT
|
||||||
|
sdmmc_write32(REG_SDBLKCOUNT32,numsectors);
|
||||||
|
#else
|
||||||
|
sdmmc_write16(REG_SDBLKCOUNT,numsectors);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
handleNAND.data = out;
|
||||||
|
handleNAND.size = numsectors << 9;
|
||||||
|
sdmmc_send_command(&handleNAND,0x33C12,sector_no);
|
||||||
|
inittarget(&handleSD);
|
||||||
|
return geterror(&handleNAND);
|
||||||
|
}
|
||||||
|
|
||||||
|
int __attribute__((noinline)) sdmmc_nand_writesectors(u32 sector_no, u32 numsectors, u8 *in) //experimental
|
||||||
|
{
|
||||||
|
if (handleNAND.isSDHC == 0)
|
||||||
|
sector_no <<= 9;
|
||||||
|
inittarget(&handleNAND);
|
||||||
|
sdmmc_write16(REG_SDSTOP,0x100);
|
||||||
|
|
||||||
|
#ifdef DATA32_SUPPORT
|
||||||
|
sdmmc_write32(REG_SDBLKCOUNT32,numsectors);
|
||||||
|
#else
|
||||||
|
sdmmc_write16(REG_SDBLKCOUNT,numsectors);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
handleNAND.data = in;
|
||||||
|
handleNAND.size = numsectors << 9;
|
||||||
|
sdmmc_send_command(&handleNAND,0x52C19,sector_no);
|
||||||
|
inittarget(&handleSD);
|
||||||
|
return geterror(&handleNAND);
|
||||||
|
}
|
||||||
|
|
||||||
|
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 = 1 << block_len;
|
||||||
|
u32 mult = (csd[4] >> 7) | ((csd[5] & 3) << 1);
|
||||||
|
mult = 1 << (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;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void InitSD()
|
||||||
|
{
|
||||||
|
//NAND
|
||||||
|
handleNAND.isSDHC = 0;
|
||||||
|
handleNAND.SDOPT = 0;
|
||||||
|
handleNAND.res = 0;
|
||||||
|
handleNAND.initarg = 1;
|
||||||
|
handleNAND.clk = 0x80;
|
||||||
|
handleNAND.devicenumber = 1;
|
||||||
|
|
||||||
|
//SD
|
||||||
|
handleSD.isSDHC = 0;
|
||||||
|
handleSD.SDOPT = 0;
|
||||||
|
handleSD.res = 0;
|
||||||
|
handleSD.initarg = 0;
|
||||||
|
handleSD.clk = 0x80;
|
||||||
|
handleSD.devicenumber = 0;
|
||||||
|
|
||||||
|
//sdmmc_mask16(0x100,0x800,0);
|
||||||
|
//sdmmc_mask16(0x100,0x1000,0);
|
||||||
|
//sdmmc_mask16(0x100,0x0,0x402);
|
||||||
|
//sdmmc_mask16(0xD8,0x22,0x2);
|
||||||
|
//sdmmc_mask16(0x100,0x2,0);
|
||||||
|
//sdmmc_mask16(0xD8,0x22,0);
|
||||||
|
//sdmmc_write16(0x104,0);
|
||||||
|
//sdmmc_write16(0x108,1);
|
||||||
|
//sdmmc_mask16(REG_SDRESET,1,0); //not in new Version -- nintendo's code does this
|
||||||
|
//sdmmc_mask16(REG_SDRESET,0,1); //not in new Version -- nintendo's code does this
|
||||||
|
//sdmmc_mask16(0x20,0,0x31D);
|
||||||
|
//sdmmc_mask16(0x22,0,0x837F);
|
||||||
|
//sdmmc_mask16(0xFC,0,0xDB);
|
||||||
|
//sdmmc_mask16(0xFE,0,0xDB);
|
||||||
|
////sdmmc_write16(REG_SDCLKCTL,0x20);
|
||||||
|
////sdmmc_write16(REG_SDOPT,0x40EE);
|
||||||
|
////sdmmc_mask16(0x02,0x3,0);
|
||||||
|
//sdmmc_write16(REG_SDCLKCTL,0x40);
|
||||||
|
//sdmmc_write16(REG_SDOPT,0x40EB);
|
||||||
|
//sdmmc_mask16(0x02,0x3,0);
|
||||||
|
//sdmmc_write16(REG_SDBLKLEN,0x200);
|
||||||
|
//sdmmc_write16(REG_SDSTOP,0);
|
||||||
|
|
||||||
|
*(vu16*)0x10006100 &= 0xF7FFu; //SDDATACTL32
|
||||||
|
*(vu16*)0x10006100 &= 0xEFFFu; //SDDATACTL32
|
||||||
|
#ifdef DATA32_SUPPORT
|
||||||
|
*(vu16*)0x10006100 |= 0x402u; //SDDATACTL32
|
||||||
|
#else
|
||||||
|
*(vu16*)0x10006100 |= 0x402u; //SDDATACTL32
|
||||||
|
#endif
|
||||||
|
*(vu16*)0x100060D8 = (*(vu16*)0x100060D8 & 0xFFDD) | 2;
|
||||||
|
#ifdef DATA32_SUPPORT
|
||||||
|
*(vu16*)0x10006100 &= 0xFFFFu; //SDDATACTL32
|
||||||
|
*(vu16*)0x100060D8 &= 0xFFDFu; //SDDATACTL
|
||||||
|
*(vu16*)0x10006104 = 512; //SDBLKLEN32
|
||||||
|
#else
|
||||||
|
*(vu16*)0x10006100 &= 0xFFFDu; //SDDATACTL32
|
||||||
|
*(vu16*)0x100060D8 &= 0xFFDDu; //SDDATACTL
|
||||||
|
*(vu16*)0x10006104 = 0; //SDBLKLEN32
|
||||||
|
#endif
|
||||||
|
*(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
|
||||||
|
#ifdef DATA32_SUPPORT
|
||||||
|
*(vu16*)0x10006024 = 0x20;
|
||||||
|
*(vu16*)0x10006028 = 0x40EE;
|
||||||
|
#else
|
||||||
|
*(vu16*)0x10006024 = 0x40; //Nintendo sets this to 0x20
|
||||||
|
*(vu16*)0x10006028 = 0x40EB; //Nintendo sets this to 0x40EE
|
||||||
|
#endif
|
||||||
|
*(vu16*)0x10006002 &= 0xFFFCu; ////SDPORTSEL
|
||||||
|
*(vu16*)0x10006026 = 512; //SDBLKLEN
|
||||||
|
*(vu16*)0x10006008 = 0; //SDSTOP
|
||||||
|
|
||||||
|
inittarget(&handleSD);
|
||||||
|
}
|
||||||
|
|
||||||
|
int Nand_Init()
|
||||||
|
{
|
||||||
|
inittarget(&handleNAND);
|
||||||
|
ioDelay(0xF000);
|
||||||
|
|
||||||
|
sdmmc_send_command(&handleNAND,0,0);
|
||||||
|
|
||||||
|
do {
|
||||||
|
do {
|
||||||
|
sdmmc_send_command(&handleNAND,0x10701,0x100000);
|
||||||
|
} while ( !(handleNAND.error & 1) );
|
||||||
|
} while((handleNAND.ret[0] & 0x80000000) == 0);
|
||||||
|
|
||||||
|
sdmmc_send_command(&handleNAND,0x10602,0x0);
|
||||||
|
if (handleNAND.error & 0x4) return -1;
|
||||||
|
|
||||||
|
sdmmc_send_command(&handleNAND,0x10403,handleNAND.initarg << 0x10);
|
||||||
|
if (handleNAND.error & 0x4) return -1;
|
||||||
|
|
||||||
|
sdmmc_send_command(&handleNAND,0x10609,handleNAND.initarg << 0x10);
|
||||||
|
if (handleNAND.error & 0x4) return -1;
|
||||||
|
|
||||||
|
handleNAND.total_size = calcSDSize((u8*)&handleNAND.ret[0],0);
|
||||||
|
handleNAND.clk = 1;
|
||||||
|
setckl(1);
|
||||||
|
|
||||||
|
sdmmc_send_command(&handleNAND,0x10407,handleNAND.initarg << 0x10);
|
||||||
|
if (handleNAND.error & 0x4) return -1;
|
||||||
|
|
||||||
|
handleNAND.SDOPT = 1;
|
||||||
|
|
||||||
|
sdmmc_send_command(&handleNAND,0x10506,0x3B70100);
|
||||||
|
if (handleNAND.error & 0x4) return -1;
|
||||||
|
|
||||||
|
sdmmc_send_command(&handleNAND,0x10506,0x3B90100);
|
||||||
|
if (handleNAND.error & 0x4) return -1;
|
||||||
|
|
||||||
|
sdmmc_send_command(&handleNAND,0x1040D,handleNAND.initarg << 0x10);
|
||||||
|
if (handleNAND.error & 0x4) return -1;
|
||||||
|
|
||||||
|
sdmmc_send_command(&handleNAND,0x10410,0x200);
|
||||||
|
if (handleNAND.error & 0x4) return -1;
|
||||||
|
|
||||||
|
handleNAND.clk |= 0x200;
|
||||||
|
|
||||||
|
inittarget(&handleSD);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int SD_Init()
|
||||||
|
{
|
||||||
|
inittarget(&handleSD);
|
||||||
|
|
||||||
|
//ioDelay(0x3E8);
|
||||||
|
//ioDelay(0xF000);
|
||||||
|
ioDelay(1u << 18);
|
||||||
|
|
||||||
|
//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);
|
||||||
|
//do
|
||||||
|
//{
|
||||||
|
// sdmmc_send_command(&handleSD,0x10437,handleSD.initarg << 0x10);
|
||||||
|
// sdmmc_send_command(&handleSD,0x10769,0x00FF8000 | temp);
|
||||||
|
//
|
||||||
|
//}
|
||||||
|
//while(!(handleSD.ret[0] & 0x80000000));
|
||||||
|
|
||||||
|
if(!((handleSD.ret[0] >> 30) & 1) || !temp)
|
||||||
|
temp2 = 0;
|
||||||
|
|
||||||
|
handleSD.isSDHC = temp2;
|
||||||
|
//handleSD.isSDHC = (handleSD.ret[0] & 0x40000000);
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sdmmc_sdcard_init()
|
||||||
|
{
|
||||||
|
InitSD();
|
||||||
|
Nand_Init();
|
||||||
|
return SD_Init();
|
||||||
|
}
|
141
boot/3ds/sdmmc.h
Normal file
141
boot/3ds/sdmmc.h
Normal file
|
@ -0,0 +1,141 @@
|
||||||
|
// 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 {
|
||||||
|
u8* 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;
|
||||||
|
|
||||||
|
/*int sdmmc_sdcard_init();
|
||||||
|
void sdmmc_sdcard_readsector(uint32_t sector_no, void *out);
|
||||||
|
void sdmmc_sdcard_readsectors(uint32_t sector_no, uint32_t numsectors, void *out);
|
||||||
|
void sdmmc_sdcard_writesector(uint32_t sector_no, void *in);
|
||||||
|
void sdmmc_sdcard_writesectors(uint32_t sector_no, uint32_t numsectors, void *in);
|
||||||
|
void sdmmc_blktransferinit();*/
|
||||||
|
|
||||||
|
int sdmmc_sdcard_init();
|
||||||
|
int sdmmc_sdcard_readsector(u32 sector_no, u8 *out);
|
||||||
|
int sdmmc_sdcard_readsectors(u32 sector_no, u32 numsectors, u8 *out);
|
||||||
|
int sdmmc_sdcard_writesector(u32 sector_no, u8 *in);
|
||||||
|
int sdmmc_sdcard_writesectors(u32 sector_no, u32 numsectors, u8 *in);
|
||||||
|
|
||||||
|
int sdmmc_nand_readsectors(u32 sector_no, u32 numsectors, u8 *out);
|
||||||
|
int sdmmc_nand_writesectors(u32 sector_no, u32 numsectors, u8 *in);
|
||||||
|
|
||||||
|
mmcdevice *getMMCDevice(int drive);
|
||||||
|
|
||||||
|
void InitSDMMC();
|
||||||
|
int Nand_Init();
|
||||||
|
int SD_Init();
|
63
boot/3ds/start.s
Normal file
63
boot/3ds/start.s
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
.section .text.start
|
||||||
|
.align 4
|
||||||
|
b _start
|
||||||
|
.word 0,0
|
||||||
|
.global _start
|
||||||
|
.extern main
|
||||||
|
_start:
|
||||||
|
mov sp, #0x28000000
|
||||||
|
//Disable caches/mpu
|
||||||
|
mrc p15, 0, r0, c1, c0, 0
|
||||||
|
bic r0, #0x1000 //Disable instruction cache
|
||||||
|
bic r0, #0x4 //Disable data cache
|
||||||
|
bic r0, #0x1 //Disable MPU
|
||||||
|
mcr p15, 0, r0, c1, c0, 0
|
||||||
|
ldr r0, =0x33333333
|
||||||
|
mcr p15, 0, r0, c5, c0, 2 //Write data access
|
||||||
|
mcr p15, 0, r0, c5, c0, 3 //Write instruction access
|
||||||
|
// Sets MPU permissions and cache settings
|
||||||
|
ldr r0, =0xFFFF001D // ffff0000 32k | bootrom (unprotected part)
|
||||||
|
ldr r1, =0x3000801B // fff00000 16k | dtcm
|
||||||
|
ldr r2, =0x01FF801D // 01ff8000 32k | itcm
|
||||||
|
ldr r3, =0x08000029 // 08000000 2M | arm9 mem (O3DS / N3DS)
|
||||||
|
ldr r4, =0x10000029 // 10000000 2M | io mem (ARM9 / first 2MB)
|
||||||
|
ldr r5, =0x20000037 // 20000000 256M | fcram (O3DS / N3DS)
|
||||||
|
ldr r6, =0x1FF00027 // 1FF00000 1M | dsp / axi wram
|
||||||
|
ldr r7, =0x1800002D // 18000000 8M | vram (+ 2MB)
|
||||||
|
mov r8, #0x29
|
||||||
|
mcr p15, 0, r0, c6, c0, 0
|
||||||
|
mcr p15, 0, r1, c6, c1, 0
|
||||||
|
mcr p15, 0, r2, c6, c2, 0
|
||||||
|
mcr p15, 0, r3, c6, c3, 0
|
||||||
|
mcr p15, 0, r4, c6, c4, 0
|
||||||
|
mcr p15, 0, r5, c6, c5, 0
|
||||||
|
mcr p15, 0, r6, c6, c6, 0
|
||||||
|
mcr p15, 0, r7, c6, c7, 0
|
||||||
|
mcr p15, 0, r8, c3, c0, 0 // Write bufferable 0, 3, 5
|
||||||
|
mcr p15, 0, r8, c2, c0, 0 // Data cacheable 0, 3, 5
|
||||||
|
mcr p15, 0, r8, c2, c0, 1 // Inst cacheable 0, 3, 5
|
||||||
|
// Enable dctm
|
||||||
|
ldr r0, =0x3000800A // set dtcm
|
||||||
|
mcr p15, 0, r0, c9, c1, 0 // set the dtcm Region Register
|
||||||
|
|
||||||
|
// Enable caches
|
||||||
|
mrc p15, 0, r0, c1, c0, 0 // read control register
|
||||||
|
orr r0, r0, #(1<<18) // - itcm enable
|
||||||
|
orr r0, r0, #(1<<16) // - dtcm enable
|
||||||
|
//orr r0, r0, #(1<<12) // - instruction cache enable
|
||||||
|
//orr r0, r0, #(1<<2) // - data cache enable
|
||||||
|
orr r0, r0, #(1<<0) // - mpu enable
|
||||||
|
mcr p15, 0, r0, c1, c0, 0 // write control register
|
||||||
|
|
||||||
|
// Flush caches
|
||||||
|
mov r0, #0
|
||||||
|
mcr p15, 0, r0, c7, c5, 0 // flush I-cache
|
||||||
|
mcr p15, 0, r0, c7, c6, 0 // flush D-cache
|
||||||
|
mcr p15, 0, r0, c7, c10, 4 // drain write buffer
|
||||||
|
|
||||||
|
// Fixes mounting of SDMC
|
||||||
|
ldr r0, =0x10000020
|
||||||
|
mov r1, #0x340
|
||||||
|
str r1, [r0]
|
||||||
|
|
||||||
|
b init
|
127
boot/3ds/stdarg.h
Normal file
127
boot/3ds/stdarg.h
Normal file
|
@ -0,0 +1,127 @@
|
||||||
|
/* Copyright (C) 1989-2016 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
This file is part of GCC.
|
||||||
|
|
||||||
|
GCC is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3, or (at your option)
|
||||||
|
any later version.
|
||||||
|
|
||||||
|
GCC is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
Under Section 7 of GPL version 3, you are granted additional
|
||||||
|
permissions described in the GCC Runtime Library Exception, version
|
||||||
|
3.1, as published by the Free Software Foundation.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License and
|
||||||
|
a copy of the GCC Runtime Library Exception along with this program;
|
||||||
|
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||||
|
<http://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ISO C Standard: 7.15 Variable arguments <stdarg.h>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _STDARG_H
|
||||||
|
#ifndef _ANSI_STDARG_H_
|
||||||
|
#ifndef __need___va_list
|
||||||
|
#define _STDARG_H
|
||||||
|
#define _ANSI_STDARG_H_
|
||||||
|
#endif /* not __need___va_list */
|
||||||
|
#undef __need___va_list
|
||||||
|
|
||||||
|
/* Define __gnuc_va_list. */
|
||||||
|
|
||||||
|
#ifndef __GNUC_VA_LIST
|
||||||
|
#define __GNUC_VA_LIST
|
||||||
|
typedef __builtin_va_list __gnuc_va_list;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Define the standard macros for the user,
|
||||||
|
if this invocation was from the user program. */
|
||||||
|
#ifdef _STDARG_H
|
||||||
|
|
||||||
|
#define va_start(v,l) __builtin_va_start(v,l)
|
||||||
|
#define va_end(v) __builtin_va_end(v)
|
||||||
|
#define va_arg(v,l) __builtin_va_arg(v,l)
|
||||||
|
#if !defined(__STRICT_ANSI__) || __STDC_VERSION__ + 0 >= 199900L \
|
||||||
|
|| __cplusplus + 0 >= 201103L
|
||||||
|
#define va_copy(d,s) __builtin_va_copy(d,s)
|
||||||
|
#endif
|
||||||
|
#define __va_copy(d,s) __builtin_va_copy(d,s)
|
||||||
|
|
||||||
|
/* Define va_list, if desired, from __gnuc_va_list. */
|
||||||
|
/* We deliberately do not define va_list when called from
|
||||||
|
stdio.h, because ANSI C says that stdio.h is not supposed to define
|
||||||
|
va_list. stdio.h needs to have access to that data type,
|
||||||
|
but must not use that name. It should use the name __gnuc_va_list,
|
||||||
|
which is safe because it is reserved for the implementation. */
|
||||||
|
|
||||||
|
#ifdef _BSD_VA_LIST
|
||||||
|
#undef _BSD_VA_LIST
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(__svr4__) || (defined(_SCO_DS) && !defined(__VA_LIST))
|
||||||
|
/* SVR4.2 uses _VA_LIST for an internal alias for va_list,
|
||||||
|
so we must avoid testing it and setting it here.
|
||||||
|
SVR4 uses _VA_LIST as a flag in stdarg.h, but we should
|
||||||
|
have no conflict with that. */
|
||||||
|
#ifndef _VA_LIST_
|
||||||
|
#define _VA_LIST_
|
||||||
|
#ifdef __i860__
|
||||||
|
#ifndef _VA_LIST
|
||||||
|
#define _VA_LIST va_list
|
||||||
|
#endif
|
||||||
|
#endif /* __i860__ */
|
||||||
|
typedef __gnuc_va_list va_list;
|
||||||
|
#ifdef _SCO_DS
|
||||||
|
#define __VA_LIST
|
||||||
|
#endif
|
||||||
|
#endif /* _VA_LIST_ */
|
||||||
|
#else /* not __svr4__ || _SCO_DS */
|
||||||
|
|
||||||
|
/* The macro _VA_LIST_ is the same thing used by this file in Ultrix.
|
||||||
|
But on BSD NET2 we must not test or define or undef it.
|
||||||
|
(Note that the comments in NET 2's ansi.h
|
||||||
|
are incorrect for _VA_LIST_--see stdio.h!) */
|
||||||
|
#if !defined (_VA_LIST_) || defined (__BSD_NET2__) || defined (____386BSD____) || defined (__bsdi__) || defined (__sequent__) || defined (__FreeBSD__) || defined(WINNT)
|
||||||
|
/* The macro _VA_LIST_DEFINED is used in Windows NT 3.5 */
|
||||||
|
#ifndef _VA_LIST_DEFINED
|
||||||
|
/* The macro _VA_LIST is used in SCO Unix 3.2. */
|
||||||
|
#ifndef _VA_LIST
|
||||||
|
/* The macro _VA_LIST_T_H is used in the Bull dpx2 */
|
||||||
|
#ifndef _VA_LIST_T_H
|
||||||
|
/* The macro __va_list__ is used by BeOS. */
|
||||||
|
#ifndef __va_list__
|
||||||
|
typedef __gnuc_va_list va_list;
|
||||||
|
#endif /* not __va_list__ */
|
||||||
|
#endif /* not _VA_LIST_T_H */
|
||||||
|
#endif /* not _VA_LIST */
|
||||||
|
#endif /* not _VA_LIST_DEFINED */
|
||||||
|
#if !(defined (__BSD_NET2__) || defined (____386BSD____) || defined (__bsdi__) || defined (__sequent__) || defined (__FreeBSD__))
|
||||||
|
#define _VA_LIST_
|
||||||
|
#endif
|
||||||
|
#ifndef _VA_LIST
|
||||||
|
#define _VA_LIST
|
||||||
|
#endif
|
||||||
|
#ifndef _VA_LIST_DEFINED
|
||||||
|
#define _VA_LIST_DEFINED
|
||||||
|
#endif
|
||||||
|
#ifndef _VA_LIST_T_H
|
||||||
|
#define _VA_LIST_T_H
|
||||||
|
#endif
|
||||||
|
#ifndef __va_list__
|
||||||
|
#define __va_list__
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* not _VA_LIST_, except on certain systems */
|
||||||
|
|
||||||
|
#endif /* not __svr4__ */
|
||||||
|
|
||||||
|
#endif /* _STDARG_H */
|
||||||
|
|
||||||
|
#endif /* not _ANSI_STDARG_H_ */
|
||||||
|
#endif /* not _STDARG_H */
|
2
boot/README
Normal file
2
boot/README
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
The official bootloaders, in case there are none.
|
||||||
|
|
62
do_all.sh
Executable file
62
do_all.sh
Executable file
|
@ -0,0 +1,62 @@
|
||||||
|
builddir() {
|
||||||
|
rm -rvvf build/ &&
|
||||||
|
mkdir -pv build/
|
||||||
|
}
|
||||||
|
rm -rvvf out/
|
||||||
|
mkdir -pv out/
|
||||||
|
#x86-PC config
|
||||||
|
{
|
||||||
|
echo 0 #x86-pc
|
||||||
|
yes ''
|
||||||
|
} | ./config.py &&
|
||||||
|
builddir &&
|
||||||
|
pushd build &&
|
||||||
|
cmake -DCMAKE_TOOLCHAIN_FILE=../toolchains/i686-elf.cmake .. &&
|
||||||
|
make -j$(nproc) &&
|
||||||
|
popd &&
|
||||||
|
buildtools/grub-iso.sh &&
|
||||||
|
mv bootable.iso out/x86-pc.iso
|
||||||
|
|
||||||
|
#x86-PC config
|
||||||
|
{
|
||||||
|
echo 1 #x86_64-pc
|
||||||
|
yes ''
|
||||||
|
} | ./config.py &&
|
||||||
|
builddir &&
|
||||||
|
pushd build &&
|
||||||
|
cmake -DCMAKE_TOOLCHAIN_FILE=../toolchains/x86_64-elf.cmake .. &&
|
||||||
|
make -j$(nproc) &&
|
||||||
|
popd &&
|
||||||
|
buildtools/grub-iso.sh &&
|
||||||
|
mv bootable.iso out/x86_64-pc.iso
|
||||||
|
|
||||||
|
#arm-3ds9 config
|
||||||
|
{
|
||||||
|
echo 2 #arm
|
||||||
|
echo 0 #3ds9
|
||||||
|
yes ''
|
||||||
|
} | ./config.py &&
|
||||||
|
builddir &&
|
||||||
|
pushd build &&
|
||||||
|
cmake -DCMAKE_TOOLCHAIN_FILE=../toolchains/arm-none-eabi.cmake .. &&
|
||||||
|
make -j$(nproc) &&
|
||||||
|
popd &&
|
||||||
|
mv build/kernel/kernel kernel9 &&
|
||||||
|
cp -v kernel9 out/arm9loaderhax.elf
|
||||||
|
|
||||||
|
#arm-3ds11 config
|
||||||
|
{
|
||||||
|
echo 2 #arm
|
||||||
|
echo 1 #3ds11
|
||||||
|
yes ''
|
||||||
|
} | ./config.py &&
|
||||||
|
builddir &&
|
||||||
|
pushd build &&
|
||||||
|
cmake -DCMAKE_TOOLCHAIN_FILE=../toolchains/arm-none-eabi.cmake .. &&
|
||||||
|
make -j$(nproc) &&
|
||||||
|
popd &&
|
||||||
|
mv kernel9 build/kernel &&
|
||||||
|
buildtools/sighax-firm.sh &&
|
||||||
|
mv sighax.firm out/ &&
|
||||||
|
cp -v build/kernel/kernel out/arm11loaderhax.elf
|
||||||
|
rm -rvvf build/
|
Loading…
Reference in a new issue