External ARM9 payload chainloading for a9lh, cleaned up the sdmmc library (from the dark-samus a9lh fork)

This commit is contained in:
Aurora
2016-03-08 15:13:55 +01:00
parent 04978ebb01
commit 09380a19ff
30 changed files with 7137 additions and 717 deletions

View File

@@ -6,4 +6,4 @@
#include "common.h"
void ioDelay(u32 us);
void waitcycles(u32 us);

View File

@@ -1,616 +1,406 @@
/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*
* Copyright (c) 2014, Normmatt
*
* Alternatively, the contents of this file may be used under the terms
* of the GNU General Public License Version 2, as described below:
*
* This file is free software: you may copy, redistribute and/or modify
* it under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 2 of the License, or (at your
* option) any later version.
*
* This file 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.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see http://www.gnu.org/licenses/.
*/
// Copyright 2014 Normmatt
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include <inttypes.h>
#include <malloc.h>
#include <stdio.h>
#include <unistd.h>
#include <dirent.h>
#include <errno.h>
#include "common.h"
#include "sdmmc.h"
//#include "DrawCharacter.h"
#include "delay.h"
//Uncomment to enable 32bit fifo support?
//not currently working
#define DATA32_SUPPORT
struct mmcdevice handleNAND;
struct mmcdevice handleSD;
#define TRUE 1
#define FALSE 0
static inline u16 sdmmc_read16(u16 reg) {
return *(vu16*)(SDMMC_BASE + reg);
}
#define bool int
static inline void sdmmc_write16(u16 reg, u16 val) {
*(vu16*)(SDMMC_BASE + reg) = val;
}
#define NO_INLINE __attribute__ ((noinline))
static inline u32 sdmmc_read32(u16 reg) {
return *(vu32*)(SDMMC_BASE + reg);
}
#define RGB(r,g,b) (r<<24|b<<16|g<<8|r)
static inline void sdmmc_write32(u16 reg, u32 val) {
*(vu32*)(SDMMC_BASE + reg) = val;
}
#ifdef __cplusplus
extern "C" {
#endif
void waitcycles(uint32_t val);
#ifdef __cplusplus
};
#endif
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);
}
//#define DEBUG_SDMMC
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);
}
#ifdef DEBUG_SDMMC
extern uint8_t* topScreen;
extern void DrawHexWithName(unsigned char *screen, const char *str, unsigned int hex, int x, int y, int color, int bgcolor);
#define DEBUGPRINT(scr,str,hex,x,y,color,bg) DrawHexWithName(scr,str,hex,x,y,color,bg)
#else
#define DEBUGPRINT(...)
#endif
//extern "C" void sdmmc_send_command(struct mmcdevice *ctx, uint32_t cmd, uint32_t args);
//extern "C" void inittarget(struct mmcdevice *ctx);
//extern "C" int SD_Init();
//extern "C" int SD_Init2();
//extern "C" int Nand_Init2();
//extern "C" void InitSD();
struct mmcdevice handelNAND;
struct mmcdevice handelSD;
mmcdevice *getMMCDevice(int drive)
{
if(drive==0) return &handelNAND;
return &handelSD;
if(drive==0) return &handleNAND;
return &handleSD;
}
int geterror(struct mmcdevice *ctx)
static u32 __attribute__((noinline)) geterror(struct mmcdevice *ctx)
{
return (ctx->error << 29) >> 31;
return (ctx->error << 29) >> 31;
}
void inittarget(struct mmcdevice *ctx)
static void __attribute__((noinline)) inittarget(struct mmcdevice *ctx)
{
sdmmc_mask16(REG_SDPORTSEL,0x3,(uint16_t)ctx->devicenumber);
setckl(ctx->clk);
if(ctx->SDOPT == 0)
{
sdmmc_mask16(REG_SDOPT,0,0x8000);
}
else
{
sdmmc_mask16(REG_SDOPT,0x8000,0);
}
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 NO_INLINE sdmmc_send_command(struct mmcdevice *ctx, uint32_t cmd, uint32_t args)
static void __attribute__((noinline)) sdmmc_send_command(struct mmcdevice *ctx, u32 cmd, u32 args)
{
bool getSDRESP = (cmd << 15) >> 31;
uint16_t 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_DATACTL32, 0x1000, 0x800);
// if(writedata)sdmmc_mask16(REG_DATACTL32, 0x800, 0x1000);
// sdmmc_mask16(REG_DATACTL32,0x1800,2);
#else
sdmmc_mask16(REG_DATACTL32,0x1800,0);
#endif
sdmmc_write16(REG_SDCMDARG0,args &0xFFFF);
sdmmc_write16(REG_SDCMDARG1,args >> 16);
sdmmc_write16(REG_SDCMD,cmd &0xFFFF);
uint32_t size = ctx->size;
uint16_t *dataPtr = (uint16_t*)ctx->data;
uint32_t *dataPtr32 = (uint32_t*)ctx->data;
bool useBuf = ( NULL != dataPtr );
bool useBuf32 = (useBuf && (0 == (3 & ((uint32_t)dataPtr))));
uint16_t status0 = 0;
while(1)
{
volatile uint16_t status1 = sdmmc_read16(REG_SDSTATUS1);
#ifdef DATA32_SUPPORT
volatile uint16_t ctl32 = sdmmc_read16(REG_DATACTL32);
if((ctl32 & 0x100))
#else
if((status1 & TMIO_STAT1_RXRDY))
#endif
{
if(readdata)
{
if(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;
}
}
sdmmc_mask16(REG_DATACTL32, 0x800, 0);
}
}
#ifdef DATA32_SUPPORT
if(!(ctl32 & 0x200))
#else
if((status1 & TMIO_STAT1_TXRQ))
#endif
{
if(writedata)
{
if(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;
}
}
sdmmc_mask16(REG_DATACTL32, 0x1000, 0);
}
}
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);
}
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);
}
}
int NO_INLINE sdmmc_sdcard_writesectors(uint32_t sector_no, uint32_t numsectors, uint8_t *in)
u32 __attribute__((noinline)) sdmmc_sdcard_writesectors(u32 sector_no, u32 numsectors, vu8 *in)
{
if(handelSD.isSDHC == 0) sector_no <<= 9;
inittarget(&handelSD);
sdmmc_write16(REG_SDSTOP,0x100);
#ifdef DATA32_SUPPORT
sdmmc_write16(REG_SDBLKCOUNT32,numsectors);
sdmmc_write16(REG_SDBLKLEN32,0x200);
#endif
sdmmc_write16(REG_SDBLKCOUNT,numsectors);
handelSD.data = in;
handelSD.size = numsectors << 9;
sdmmc_send_command(&handelSD,0x52C19,sector_no);
return geterror(&handelSD);
if (handleSD.isSDHC == 0)
sector_no <<= 9;
inittarget(&handleSD);
sdmmc_write16(REG_SDSTOP,0x100);
sdmmc_write16(REG_SDBLKCOUNT,numsectors);
handleSD.data = in;
handleSD.size = numsectors << 9;
sdmmc_send_command(&handleSD,0x52C19,sector_no);
return geterror(&handleSD);
}
int NO_INLINE sdmmc_sdcard_readsectors(uint32_t sector_no, uint32_t numsectors, uint8_t *out)
u32 __attribute__((noinline)) sdmmc_sdcard_readsectors(u32 sector_no, u32 numsectors, vu8 *out)
{
if(handelSD.isSDHC == 0) sector_no <<= 9;
inittarget(&handelSD);
sdmmc_write16(REG_SDSTOP,0x100);
#ifdef DATA32_SUPPORT
sdmmc_write16(REG_SDBLKCOUNT32,numsectors);
sdmmc_write16(REG_SDBLKLEN32,0x200);
#endif
sdmmc_write16(REG_SDBLKCOUNT,numsectors);
handelSD.data = out;
handelSD.size = numsectors << 9;
sdmmc_send_command(&handelSD,0x33C12,sector_no);
return geterror(&handelSD);
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);
}
int NO_INLINE sdmmc_nand_readsectors(uint32_t sector_no, uint32_t numsectors, uint8_t *out)
u32 __attribute__((noinline)) sdmmc_nand_readsectors(u32 sector_no, u32 numsectors, vu8 *out)
{
if(handelNAND.isSDHC == 0) sector_no <<= 9;
inittarget(&handelNAND);
sdmmc_write16(REG_SDSTOP,0x100);
#ifdef DATA32_SUPPORT
sdmmc_write16(REG_SDBLKCOUNT32,numsectors);
sdmmc_write16(REG_SDBLKLEN32,0x200);
#endif
sdmmc_write16(REG_SDBLKCOUNT,numsectors);
handelNAND.data = out;
handelNAND.size = numsectors << 9;
sdmmc_send_command(&handelNAND,0x33C12,sector_no);
inittarget(&handelSD);
return geterror(&handelNAND);
if (handleNAND.isSDHC == 0)
sector_no <<= 9;
inittarget(&handleNAND);
sdmmc_write16(REG_SDSTOP,0x100);
sdmmc_write16(REG_SDBLKCOUNT,numsectors);
handleNAND.data = out;
handleNAND.size = numsectors << 9;
sdmmc_send_command(&handleNAND,0x33C12,sector_no);
inittarget(&handleSD);
return geterror(&handleNAND);
}
int NO_INLINE sdmmc_nand_writesectors(uint32_t sector_no, uint32_t numsectors, uint8_t *in) //experimental
u32 __attribute__((noinline)) sdmmc_nand_writesectors(u32 sector_no, u32 numsectors, vu8 *in) //experimental
{
if(handelNAND.isSDHC == 0) sector_no <<= 9;
inittarget(&handelNAND);
sdmmc_write16(REG_SDSTOP,0x100);
#ifdef DATA32_SUPPORT
sdmmc_write16(REG_SDBLKCOUNT32,numsectors);
sdmmc_write16(REG_SDBLKLEN32,0x200);
#endif
sdmmc_write16(REG_SDBLKCOUNT,numsectors);
handelNAND.data = in;
handelNAND.size = numsectors << 9;
sdmmc_send_command(&handelNAND,0x52C19,sector_no);
inittarget(&handelSD);
return geterror(&handelNAND);
if (handleNAND.isSDHC == 0)
sector_no <<= 9;
inittarget(&handleNAND);
sdmmc_write16(REG_SDSTOP,0x100);
sdmmc_write16(REG_SDBLKCOUNT,numsectors);
handleNAND.data = in;
handleNAND.size = numsectors << 9;
sdmmc_send_command(&handleNAND,0x52C19,sector_no);
inittarget(&handleSD);
return geterror(&handleNAND);
}
static uint32_t calcSDSize(uint8_t* csd, int type)
static u32 calcSDSize(u8* csd, int type)
{
uint32_t result=0;
if(type == -1) type = csd[14] >> 6;
switch(type)
{
case 0:
{
uint32_t block_len=csd[9]&0xf;
block_len=1<<block_len;
uint32_t 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;
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;
}
void InitSD()
static void InitSD()
{
//NAND
handelNAND.isSDHC = 0;
handelNAND.SDOPT = 0;
handelNAND.res = 0;
handelNAND.initarg = 1;
handelNAND.clk = 0x80;
handelNAND.devicenumber = 1;
//SD
handelSD.isSDHC = 0;
handelSD.SDOPT = 0;
handelSD.res = 0;
handelSD.initarg = 0;
handelSD.clk = 0x80;
handelSD.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);
*(volatile uint16_t*)0x10006100 &= 0xF7FFu; //SDDATACTL32
*(volatile uint16_t*)0x10006100 &= 0xEFFFu; //SDDATACTL32
#ifdef DATA32_SUPPORT
*(volatile uint16_t*)0x10006100 |= 0x402u; //SDDATACTL32
#else
*(volatile uint16_t*)0x10006100 |= 0x402u; //SDDATACTL32
#endif
*(volatile uint16_t*)0x100060D8 = (*(volatile uint16_t*)0x100060D8 & 0xFFDD) | 2;
#ifdef DATA32_SUPPORT
*(volatile uint16_t*)0x10006100 &= 0xFFFFu; //SDDATACTL32
*(volatile uint16_t*)0x100060D8 &= 0xFFDFu; //SDDATACTL
*(volatile uint16_t*)0x10006104 = 512; //SDBLKLEN32
#else
*(volatile uint16_t*)0x10006100 &= 0xFFFDu; //SDDATACTL32
*(volatile uint16_t*)0x100060D8 &= 0xFFDDu; //SDDATACTL
*(volatile uint16_t*)0x10006104 = 0; //SDBLKLEN32
#endif
*(volatile uint16_t*)0x10006108 = 1; //SDBLKCOUNT32
*(volatile uint16_t*)0x100060E0 &= 0xFFFEu; //SDRESET
*(volatile uint16_t*)0x100060E0 |= 1u; //SDRESET
*(volatile uint16_t*)0x10006020 |= TMIO_MASK_ALL; //SDIR_MASK0
*(volatile uint16_t*)0x10006022 |= TMIO_MASK_ALL>>16; //SDIR_MASK1
*(volatile uint16_t*)0x100060FC |= 0xDBu; //SDCTL_RESERVED7
*(volatile uint16_t*)0x100060FE |= 0xDBu; //SDCTL_RESERVED8
*(volatile uint16_t*)0x10006002 &= 0xFFFCu; //SDPORTSEL
#ifdef DATA32_SUPPORT
*(volatile uint16_t*)0x10006024 = 0x20;
*(volatile uint16_t*)0x10006028 = 0x40EE;
#else
*(volatile uint16_t*)0x10006024 = 0x40; //Nintendo sets this to 0x20
*(volatile uint16_t*)0x10006028 = 0x40EB; //Nintendo sets this to 0x40EE
#endif
*(volatile uint16_t*)0x10006002 &= 0xFFFCu; ////SDPORTSEL
*(volatile uint16_t*)0x10006026 = 512; //SDBLKLEN
*(volatile uint16_t*)0x10006008 = 0; //SDSTOP
inittarget(&handelSD);
//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;
*(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);
}
int Nand_Init()
static int Nand_Init()
{
inittarget(&handelNAND);
waitcycles(0xF000);
DEBUGPRINT(topScreen, "0x00000 ", handelNAND.error, 10, 20 + 13*8, RGB(40, 40, 40), RGB(208, 208, 208));
sdmmc_send_command(&handelNAND,0,0);
DEBUGPRINT(topScreen, "0x10701 ", handelNAND.error, 10, 20 + 13*8, RGB(40, 40, 40), RGB(208, 208, 208));
do
{
do
{
sdmmc_send_command(&handelNAND,0x10701,0x100000);
DEBUGPRINT(topScreen, "error ", handelNAND.error, 10, 20 + 17*8, RGB(40, 40, 40), RGB(208, 208, 208));
DEBUGPRINT(topScreen, "ret: ", handelNAND.ret[0], 10, 20 + 18*8, RGB(40, 40, 40), RGB(208, 208, 208));
DEBUGPRINT(topScreen, "test ", 3, 10, 20 + 19*8, RGB(40, 40, 40), RGB(208, 208, 208));
} while ( !(handelNAND.error & 1) );
}
while((handelNAND.ret[0] & 0x80000000) == 0);
DEBUGPRINT(topScreen, "0x10602 ", handelNAND.error, 10, 20 + 13*8, RGB(40, 40, 40), RGB(208, 208, 208));
sdmmc_send_command(&handelNAND,0x10602,0x0);
if((handelNAND.error & 0x4))return -1;
DEBUGPRINT(topScreen, "0x10403 ", handelNAND.error, 10, 20 + 13*8, RGB(40, 40, 40), RGB(208, 208, 208));
sdmmc_send_command(&handelNAND,0x10403,handelNAND.initarg << 0x10);
if((handelNAND.error & 0x4))return -1;
DEBUGPRINT(topScreen, "0x10609 ", handelNAND.error, 10, 20 + 13*8, RGB(40, 40, 40), RGB(208, 208, 208));
sdmmc_send_command(&handelNAND,0x10609,handelNAND.initarg << 0x10);
if((handelNAND.error & 0x4))return -1;
DEBUGPRINT(topScreen, "0x10407 ", handelNAND.error, 10, 20 + 13*8, RGB(40, 40, 40), RGB(208, 208, 208));
handelNAND.total_size = calcSDSize((uint8_t*)&handelNAND.ret[0],0);
handelNAND.clk = 1;
setckl(1);
sdmmc_send_command(&handelNAND,0x10407,handelNAND.initarg << 0x10);
if((handelNAND.error & 0x4))return -1;
DEBUGPRINT(topScreen, "0x10506 ", handelNAND.error, 10, 20 + 13*8, RGB(40, 40, 40), RGB(208, 208, 208));
handelNAND.SDOPT = 1;
sdmmc_send_command(&handelNAND,0x10506,0x3B70100);
if((handelNAND.error & 0x4))return -1;
DEBUGPRINT(topScreen, "0x10506 ", handelNAND.error, 10, 20 + 13*8, RGB(40, 40, 40), RGB(208, 208, 208));
sdmmc_send_command(&handelNAND,0x10506,0x3B90100);
if((handelNAND.error & 0x4))return -1;
DEBUGPRINT(topScreen, "0x1040D ", handelNAND.error, 10, 20 + 13*8, RGB(40, 40, 40), RGB(208, 208, 208));
sdmmc_send_command(&handelNAND,0x1040D,handelNAND.initarg << 0x10);
if((handelNAND.error & 0x4))return -1;
DEBUGPRINT(topScreen, "0x10410 ", handelNAND.error, 10, 20 + 13*8, RGB(40, 40, 40), RGB(208, 208, 208));
sdmmc_send_command(&handelNAND,0x10410,0x200);
if((handelNAND.error & 0x4))return -1;
handelNAND.clk |= 0x200;
inittarget(&handelSD);
return 0;
inittarget(&handleNAND);
waitcycles(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()
static int SD_Init()
{
inittarget(&handelSD);
//waitcycles(0x3E8);
waitcycles(0xF000);
DEBUGPRINT(topScreen, "0x00000 ", handelSD.error, 10, 20 + 14*8, RGB(40, 40, 40), RGB(208, 208, 208));
sdmmc_send_command(&handelSD,0,0);
DEBUGPRINT(topScreen, "0x10408 ", handelSD.error, 10, 20 + 14*8, RGB(40, 40, 40), RGB(208, 208, 208));
sdmmc_send_command(&handelSD,0x10408,0x1AA);
//uint32_t temp = (handelSD.ret[0] == 0x1AA) << 0x1E;
uint32_t temp = (handelSD.error & 0x1) << 0x1E;
DEBUGPRINT(topScreen, "0x10769 ", handelSD.error, 10, 20 + 14*8, RGB(40, 40, 40), RGB(208, 208, 208));
DEBUGPRINT(topScreen, "sd ret: ", handelSD.ret[0], 10, 20 + 15*8, RGB(40, 40, 40), RGB(208, 208, 208));
DEBUGPRINT(topScreen, "temp: ", temp, 10, 20 + 16*8, RGB(40, 40, 40), RGB(208, 208, 208));
//int count = 0;
uint32_t temp2 = 0;
do
{
do
{
sdmmc_send_command(&handelSD,0x10437,handelSD.initarg << 0x10);
sdmmc_send_command(&handelSD,0x10769,0x00FF8000 | temp);
temp2 = 1;
} while ( !(handelSD.error & 1) );
//DEBUGPRINT(topScreen, "sd error ", handelSD.error, 10, 20 + 17*8, RGB(40, 40, 40), RGB(208, 208, 208));
//DEBUGPRINT(topScreen, "sd ret: ", handelSD.ret[0], 10, 20 + 18*8, RGB(40, 40, 40), RGB(208, 208, 208));
//DEBUGPRINT(topScreen, "count: ", count++, 10, 20 + 19*8, RGB(40, 40, 40), RGB(208, 208, 208));
}
while((handelSD.ret[0] & 0x80000000) == 0);
//do
//{
// sdmmc_send_command(&handelSD,0x10437,handelSD.initarg << 0x10);
// sdmmc_send_command(&handelSD,0x10769,0x00FF8000 | temp);
//
// DEBUGPRINT(topScreen, "sd error ", handelSD.error, 10, 20 + 17*8, RGB(40, 40, 40), RGB(208, 208, 208));
// DEBUGPRINT(topScreen, "sd ret: ", handelSD.ret[0], 10, 20 + 18*8, RGB(40, 40, 40), RGB(208, 208, 208));
// DEBUGPRINT(topScreen, "count: ", count++, 10, 20 + 19*8, RGB(40, 40, 40), RGB(208, 208, 208));
//}
//while(!(handelSD.ret[0] & 0x80000000));
inittarget(&handleSD);
if(!((handelSD.ret[0] >> 30) & 1) || !temp)
temp2 = 0;
handelSD.isSDHC = temp2;
//handelSD.isSDHC = (handelSD.ret[0] & 0x40000000);
DEBUGPRINT(topScreen, "0x10602 ", handelSD.error, 10, 20 + 14*8, RGB(40, 40, 40), RGB(208, 208, 208));
sdmmc_send_command(&handelSD,0x10602,0);
if((handelSD.error & 0x4)) return -1;
DEBUGPRINT(topScreen, "0x10403 ", handelSD.error, 10, 20 + 14*8, RGB(40, 40, 40), RGB(208, 208, 208));
sdmmc_send_command(&handelSD,0x10403,0);
if((handelSD.error & 0x4)) return -1;
handelSD.initarg = handelSD.ret[0] >> 0x10;
DEBUGPRINT(topScreen, "0x10609 ", handelSD.error, 10, 20 + 14*8, RGB(40, 40, 40), RGB(208, 208, 208));
sdmmc_send_command(&handelSD,0x10609,handelSD.initarg << 0x10);
if((handelSD.error & 0x4)) return -1;
handelSD.total_size = calcSDSize((uint8_t*)&handelSD.ret[0],-1);
handelSD.clk = 1;
setckl(1);
DEBUGPRINT(topScreen, "0x10507 ", handelSD.error, 10, 20 + 14*8, RGB(40, 40, 40), RGB(208, 208, 208));
sdmmc_send_command(&handelSD,0x10507,handelSD.initarg << 0x10);
if((handelSD.error & 0x4)) return -1;
waitcycles(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;
DEBUGPRINT(topScreen, "0x10437 ", handelSD.error, 10, 20 + 14*8, RGB(40, 40, 40), RGB(208, 208, 208));
sdmmc_send_command(&handelSD,0x10437,handelSD.initarg << 0x10);
if((handelSD.error & 0x4)) return -1;
DEBUGPRINT(topScreen, "0x10446 ", handelSD.error, 10, 20 + 14*8, RGB(40, 40, 40), RGB(208, 208, 208));
handelSD.SDOPT = 1;
sdmmc_send_command(&handelSD,0x10446,0x2);
if((handelSD.error & 0x4)) return -1;
DEBUGPRINT(topScreen, "0x1040D ", handelSD.error, 10, 20 + 14*8, RGB(40, 40, 40), RGB(208, 208, 208));
sdmmc_send_command(&handelSD,0x1040D,handelSD.initarg << 0x10);
if((handelSD.error & 0x4)) return -1;
DEBUGPRINT(topScreen, "0x10410 ", handelSD.error, 10, 20 + 14*8, RGB(40, 40, 40), RGB(208, 208, 208));
sdmmc_send_command(&handelSD,0x10410,0x200);
if((handelSD.error & 0x4)) return -1;
handelSD.clk |= 0x200;
return 0;
//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()
int sdmmc_sdcard_init()
{
DEBUGPRINT(topScreen, "sdmmc_sdcard_init ", handelSD.error, 10, 20 + 2*8, RGB(40, 40, 40), RGB(208, 208, 208));
InitSD();
//SD_Init2();
//Nand_Init();
Nand_Init();
DEBUGPRINT(topScreen, "nand_res ", nand_res, 10, 20 + 3*8, RGB(40, 40, 40), RGB(208, 208, 208));
SD_Init();
DEBUGPRINT(topScreen, "sd_res ", sd_res, 10, 20 + 4*8, RGB(40, 40, 40), RGB(208, 208, 208));
InitSD();
int result = Nand_Init();
return result | SD_Init();
}

View File

@@ -1,52 +1,52 @@
#ifndef __SDMMC_H__
#define __SDMMC_H__
// Copyright 2014 Normmatt
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#define TRUE 1
#define FALSE 0
#pragma once
#include <stdint.h>
#include "common.h"
#define SDMMC_BASE 0x10006000
#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_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_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_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_SDIRMASK0 0x20
#define REG_SDIRMASK1 0x22
#define REG_SDCLKCTL 0x24
#define REG_DATACTL 0xd8
#define REG_SDRESET 0xe0
#define REG_SDPROTECTED 0xf6 //bit 0 determines if sd is protected or not?
#define REG_SDBLKLEN 0x26
#define REG_SDOPT 0x28
#define REG_SDFIFO 0x30
#define REG_DATACTL32 0x100
#define REG_SDBLKLEN32 0x104
#define REG_SDBLKCOUNT32 0x108
#define REG_SDFIFO32 0x10C
#define REG_SDDATACTL 0xd8
#define REG_SDRESET 0xe0
#define REG_SDPROTECTED 0xf6 //bit 0 determines if sd is protected or not?
#define REG_CLK_AND_WAIT_CTL 0x138
#define REG_RESET_SDIO 0x1e0
#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
@@ -97,88 +97,32 @@
#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)
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)
#ifdef __cplusplus
extern "C" {
#endif
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;
typedef struct mmcdevice {
uint8_t* data;
uint32_t size;
uint32_t error;
uint16_t stat0;
uint16_t stat1;
uint32_t ret[4];
uint32_t initarg;
uint32_t isSDHC;
uint32_t clk;
uint32_t SDOPT;
uint32_t devicenumber;
uint32_t total_size; //size in sectors of the device
uint32_t res;
} mmcdevice;
void sdmmc_sdcard_init();
int sdmmc_sdcard_readsector(uint32_t sector_no, uint8_t *out);
int sdmmc_sdcard_readsectors(uint32_t sector_no, uint32_t numsectors, uint8_t *out);
int sdmmc_sdcard_writesector(uint32_t sector_no, uint8_t *in);
int sdmmc_sdcard_writesectors(uint32_t sector_no, uint32_t numsectors, uint8_t *in);
int sdmmc_nand_readsectors(uint32_t sector_no, uint32_t numsectors, uint8_t *out);
int sdmmc_nand_writesectors(uint32_t sector_no, uint32_t numsectors, uint8_t *in);
mmcdevice *getMMCDevice(int drive);
void InitSD();
int Nand_Init();
int SD_Init();
int sdmmc_sdcard_init();
u32 sdmmc_sdcard_readsectors(u32 sector_no, u32 numsectors, vu8 *out);
u32 sdmmc_sdcard_writesectors(u32 sector_no, u32 numsectors, vu8 *in);
mmcdevice *getMMCDevice(int drive);
#ifdef __cplusplus
};
#endif
u32 sdmmc_nand_readsectors(u32 sector_no, u32 numsectors, vu8 *out);
u32 sdmmc_nand_writesectors(u32 sector_no, u32 numsectors, vu8 *in);
//---------------------------------------------------------------------------------
static inline uint16_t sdmmc_read16(uint16_t reg) {
//---------------------------------------------------------------------------------
return *(volatile uint16_t*)(SDMMC_BASE + reg);
}
//---------------------------------------------------------------------------------
static inline void sdmmc_write16(uint16_t reg, uint16_t val) {
//---------------------------------------------------------------------------------
*(volatile uint16_t*)(SDMMC_BASE + reg) = val;
}
//---------------------------------------------------------------------------------
static inline uint32_t sdmmc_read32(uint16_t reg) {
//---------------------------------------------------------------------------------
return *(volatile uint32_t*)(SDMMC_BASE + reg);
}
//---------------------------------------------------------------------------------
static inline void sdmmc_write32(uint16_t reg, uint32_t val) {
//---------------------------------------------------------------------------------
*(volatile uint32_t*)(SDMMC_BASE + reg) = val;
}
//---------------------------------------------------------------------------------
static inline void sdmmc_mask16(uint16_t reg, const uint16_t clear, const uint16_t set) {
//---------------------------------------------------------------------------------
uint16_t val = sdmmc_read16(reg);
val &= ~clear;
val |= set;
sdmmc_write16(reg, val);
}
static inline void setckl(uint32_t data)
{
sdmmc_mask16(REG_SDCLKCTL,0x100,0);
sdmmc_mask16(REG_SDCLKCTL,0x2FF,data&0x2FF);
sdmmc_mask16(REG_SDCLKCTL,0x0,0x100);
}
#endif

View File

@@ -11,6 +11,7 @@
#include "emunand.h"
#include "crypto.h"
#include "draw.h"
#include "loader.h"
firmHeader *firmLocation = (firmHeader *)0x24000000;
firmSectionHeader *section;
@@ -65,6 +66,9 @@ void setupCFW(void){
if(!overrideConfig){
//If L and R are pressed, chainload an external payload
if(a9lhBoot && (pressed & BUTTON_L1R1) == BUTTON_L1R1) loadPayload();
/* If L is pressed, and on an updated SysNAND setup the SAFE MODE combo
is not pressed, boot 9.0 FIRM */
if((pressed & BUTTON_L1) && !(updatedSys && pressed == SAFEMODE)) mode = 0;

View File

@@ -13,8 +13,9 @@
#define HID_PAD ((~*(u16*)0x10146000) & 0xFFF)
#define BUTTON_R1 (1 << 8)
#define BUTTON_L1 (1 << 9)
#define BUTTON_L1R1 (BUTTON_R1 | BUTTON_L1)
#define BUTTON_A 1
#define SAFEMODE (BUTTON_L1 | BUTTON_R1 | BUTTON_A | (1 << 6))
#define SAFEMODE (BUTTON_L1R1 | BUTTON_A | (1 << 6))
void setupCFW(void);
u32 loadFirm(void);

14
source/loader.c Normal file
View File

@@ -0,0 +1,14 @@
/*
* loader.c
*/
#include "loader.h"
#include "fs.h"
#define PAYLOAD_ADDRESS 0x24F00000
void loadPayload(void){
if(fileExists("rei/arm9payload.bin") &&
fileRead((u8 *)PAYLOAD_ADDRESS, "rei/loader.bin", 0))
((void (*)())PAYLOAD_ADDRESS)();
}

12
source/loader.h Normal file
View File

@@ -0,0 +1,12 @@
/*
* loader.h
*/
#ifndef LOADER_INC
#define LOADER_INC
#include "types.h"
void loadPayload(void);
#endif

View File

@@ -10,12 +10,14 @@
#include "firm.h"
#include "draw.h"
u32 main(){
void main(){
mountSD();
loadSplash();
setupCFW();
if(!loadFirm()) return 0;
if(!patchFirm()) return 0;
}
void startCFW(){
loadSplash();
if(!loadFirm()) return;
if(!patchFirm()) return;
launchFirm();
return 1;
}

View File

@@ -6,11 +6,11 @@ _start:
mov sp, #0x27000000
@ Give read/write access to all the memory regions
ldr r5, =0x33333333
mcr p15, 0, r5, c5, c0, 2 @ write data access
mcr p15, 0, r5, c5, c0, 3 @ write instruction access
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
@ Set MPU permissions
ldr r0, =0xFFFF001D @ ffff0000 32k
ldr r1, =0x01FF801D @ 01ff8000 32k
ldr r2, =0x08000027 @ 08000000 1M
@@ -19,9 +19,6 @@ _start:
ldr r5, =0x20000035 @ 20000000 128M
ldr r6, =0x1FF00027 @ 1FF00000 1M
ldr r7, =0x1800002D @ 18000000 8M
mov r10, #0x25
mov r11, #0x25
mov r12, #0x25
mcr p15, 0, r0, c6, c0, 0
mcr p15, 0, r1, c6, c1, 0
mcr p15, 0, r2, c6, c2, 0
@@ -30,29 +27,36 @@ _start:
mcr p15, 0, r5, c6, c5, 0
mcr p15, 0, r6, c6, c6, 0
mcr p15, 0, r7, c6, c7, 0
mcr p15, 0, r10, c3, c0, 0 @ Write bufferable 0, 2, 5
mcr p15, 0, r11, c2, c0, 0 @ Data cacheable 0, 2, 5
mcr p15, 0, r12, c2, c0, 1 @ Inst cacheable 0, 2, 5
@ Enable caches
mrc p15, 0, r4, c1, c0, 0 @ read control register
orr r4, r4, #(1<<12) @ - instruction cache enable
orr r4, r4, #(1<<2) @ - data cache enable
orr r4, r4, #(1<<0) @ - mpu enable
mcr p15, 0, r4, c1, c0, 0 @ write control register
mrc p15, 0, r0, c1, c0, 0 @ read control register
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 r5, #0
mcr p15, 0, r5, c7, c5, 0 @ flush I-cache
mcr p15, 0, r5, c7, c6, 0 @ flush D-cache
mcr p15, 0, r5, c7, c10, 4 @ drain write buffer
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]
@ Fix mounting of SDMC
ldr r0, =0x10000020
mov r1, #0x340
str r1, [r0]
bl main
@ Set cache settings
mov r0, #0x25
mov r1, #0x25
mov r2, #0x25
mcr p15, 0, r0, c3, c0, 0 @ Write bufferable 0, 2, 5
mcr p15, 0, r1, c2, c0, 0 @ Data cacheable 0, 2, 5
mcr p15, 0, r2, c2, c0, 1 @ Inst cacheable 0, 2, 5
bl startCFW
.die:
b .die