Pre-IPL RAM Stage pseudo C code

Pre-IPL RAM Stage

Dumped from Motherboard: TA-081

header file:

/*
*  file: pre-IPL_ram_def.h
*  pre-IPL_ram pseudo C code
*  dumped from Motherboard: TA-081
*/

#define ENDIAN_SWAP(_x) ((((_x)<<24) & 0xFF000000) | (((_x)<<8) & 0x00FF0000) | (((_x)>>8) & 0x0000FF00) | (((_x)>>24) & 0x000000FF))
#define KEY_IO 11
#define SYSREG_IO0_ENABLE(DEVICE) *0xBC100078 |= 1<<DEVICE
#define SYSREG_IO1_ENABLE(DEVICE) *0xBC10007C |= 1<<DEVICE
#define REG32(ADDR) (*(vu32*)(ADDR))
#define GPIO_PORT_JIGKICK	(4)
#define GPIO_MASK_JIGKICK	(1<<GPIO_PORT_JIGKICK)
#define SYNC()	asm("sync")

typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned int u32;
typedef int (*LoadIplBlockFunc) (int iplBlockNum, void *buf);
typedef struct
{
	u8 opcode:4;
	u32 addr:28;
	u32 val;
}regConf;

/********************************
Memroy Stick Related define
********************************/
// HW registers
#define IO_MEM_STICK_SYS *((volatile int*)(0xBD20003C))
#define IO_MEM_STICK_DATA *((volatile int*)(0xBD200034))
#define IO_MEM_STICK_CMD *((volatile int*)(0xBD200030))
#define IO_MEM_STICK_STATUS *((volatile int*)(0xBD200038))
#define MSRST 0x8000
#define SET_RW_REG_ADRS 0x8000
// SYS bit
#define MSRST 0x8000
// STATUS bit 
#define MS_FIFO_RW     0x4000
#define MS_RDY         0x1000
#define MS_TIME_OUT    0x0100
#define MS_CRC_ERROR   0x0200
// MS command code
#define READ_PAGE_DATA  0x2000
#define READ_REG        0x4000
#define GET_INT         0x7000
#define SET_RW_REG_ADRS 0x8000
#define EX_SET_CMD      0x9000
#define WRITE_REG       0xB000
#define WRITE_PAGE_DATA 0xD000
#define SET_CMD         0xE000
// MS status bit
#define INT_REG_CED   0x80
#define INT_REG_ERR   0x40
#define INT_REG_BREQ  0x20
#define INT_REG_CMDNK 0x01

/********************************
IPL Decryption
********************************/
#define GET_PHYSICAL_ADDRESS(_addr) ((u32) _addr & 0x1FFFFFFF)
#define KIRK_HW_REGISTER_ADDRESS    ((PspKirkRegs *)0xBDE00000)

enum PspKirkStatus
{
	STATUS_FLAG0 = 0X00,
	STATUS_FLAG1 = 0X01,
	STATUS_FLAG2 = 0X02,
	STATUS_FLAG3 = 0X04,
	STATUS_FLAG4 = 0X08,
	STATUS_FLAG5 = 0X10,
	STATUS_FLAG6 = 0X20,
	STATUS_FLAG7 = 0X40,
	STATUS_FLAG8 = 0X80
};

enum PspKirkCmd
{
	ASYMM_CIPHER1 = 1,
	ASYMM_CIPHER2,
	ASYMM_CIPHER3,
	BLOCK_CIPHER4,
	BLOCK_CIPHER5,
	BLOCK_CIPHER6,
	BLOCK_CIPHER7,
	BLOCK_CIPHER8,
	BLOCK_CIPHER9,
	ASYMM_CIPHER_CHECK,
	SHA1_CHECK,
	MUL1_CHECK,
	MUL2_CHECK,
	PRN_GEN1,
	PRN_GEN2,
	SIG_GEN,
	SIG_CHECK,
	CERT_CHECK
};

enum PspKirkError
{
	NO_ERROR = 0,
	BUS_CLK_DISABLED,
	INVALID_MODE,
	HEADER_HASH_FAIL,
	DATA_HASH_FAIL,
	INVALID_CODE = 0xE,
	INVALID_SIZE_A,
	INVALID_SIZE_B
};

enum PspKirkPhase
{
	PHASE1 = 1,
	PHASE2 = 2
};

typedef volatile struct
{
	const u32 signature;
	const u32 version;
	const u32 error;
	u32 proc_phase;
	u32 command;
	const u32 result;
	u32 unk_18;
	const u32 status;
	u32 status_async;
	u32 status_async_end;
	u32 status_end;
	void *src_addr;
	void *dst_addr;
	
} PspKirkRegs;

typedef struct
{
	void *loadaddr;
	int blocksize;
	void (* entry)(void);
	u32 checksum;
	u8 data[0xF50];
} iplBlock;

/********************************
NAND Related define
********************************/
#define NAND_BUSY	(0)
#define NAND_READY	(1)

#define NAND_SPARE_PAGE_SIZE	(16)
#define NAND_LOGICAL_PAGE_SIZE	(512)
#define NAND_PHYSICAL_PAGE_SIZE	(NAND_LOGICAL_PAGE_SIZE+NAND_SPARE_PAGE_SIZE)

#define NAND_PAGES_PER_BLOCK	(32)

#define NAND_RESET_CMD		(0xFF)

#define NAND_CMD_REG		(0xBD101008)
#define NAND_STATUS_REG		(0xBD101004)
#define NAND_RESET_REG		(0xBD101014)
#define NAND_DMA_ADDR_REG	(0xBD101020)
#define NAND_DMA_CTRL_REG	(0xBD101024)
#define NAND_DMA_STAT_REG	(0xBD101028)
#define NAND_PAGE_DATA_BUF_REG	(0xBFF00000)
#define NAND_SPARE_BUF0_REG	(0xBFF00900)
#define NAND_SPARE_BUF1_REG	(0xBFF00904)
#define NAND_SPARE_BUF2_REG	(0xBFF00908)

#define NAND_SET_CMD(cmd)	(_sw(cmd, NAND_CMD_REG))
#define NAND_SET_RESET(v)	(_sw(v, NAND_RESET_REG))
#define NAND_SET_DMA_ADDR(v)	(_sw(v, NAND_DMA_ADDR_REG))
#define NAND_SET_DMA_CTRL(v)	(_sw(v, NAND_DMA_CTRL_REG))

#define NAND_GET_STATUS()	(_lw(NAND_STATUS_REG))
#define NAND_GET_DMA_CTRL()	(_lw(NAND_DMA_CTRL_REG))
#define NAND_GET_DMA_STAT()	(_lw(NAND_DMA_STAT_REG))
#define NAND_GET_PAGE_DATA()	(_lw(NAND_PAGE_DATA_BUF_REG))
#define NAND_GET_SPARE_BUF0()	(_lw(NAND_SPARE_BUF0_REG))
#define NAND_GET_SPARE_BUF1()	(_lw(NAND_SPARE_BUF1_REG))
#define NAND_GET_SPARE_BUF2()	(_lw(NAND_SPARE_BUF2_REG))

/********************************
22 functions defined in pre_ipl_ram
********************************/
void _RamEntry(void);// 0x80010000
void ReadIplNandBlockTable(void); // 0x80010130
int LoadIplBlockFromNand(int iplBlockNum, void *buf); // 0x80010194
void MsCheck(void); // 0x80010240
int LoadIplBlockFromMs(int iplBlockNum, void *buf); // 0x80010248
void ClearICache(void); //0x800102A0
void ClearDCache(void); //0x800102D8
void ResetNand(void); //0x80010308
int ReadNandPage(int pageNum, void *buf, void *spare); //0x80010334
void _MsCheck(void); //0x800103B4
int ReadMsSector(int sectNum, void * buf); //0x80010418
int SendDataAndSync(u32 arg1, u32 arg2); //0x800104C0
int ReadMsData(void * addr, int count); //0x800104CC
int WaitMsReady(void); //0x80010508
int CheckMsStatus(void); //0x80010530
int ReadMsReg(void *buffer, int reg); //0x800105A4
u8 GetMsStatus(void); //0x800105B8
void WaitMsStatus(void); //0x80010608
u32 DecryptIplBlock(void *dst, void *src); //0x80010620
u32 _Memcpy(void *dst, void *src, int size); //0x80010688
void SysRegConfig(regConf *conf); //0x800106B0
void Delay(int cnt); //0x80010768

c file:

/*
*  file: pre-IPL_ram.c
*  pre-IPL_ram pseudo C code
*  dumped from Motherboard: TA-081
*/

/*
REG_CONF_TBL0 do the following Ops:
*(u32*)0xBC100058 = *(u32*)0xBC100058 | 0x800000;	GPIO Enable
*(u32*)0xBC100050 = *(u32*)0xBC100050 | 0x608E;		CLK Enable: AW/KIRK/EMCSM(nand)/UART4
*(u32*)0xBC10004C = *(u32*)0xBC10004C & 0xFFFFFBF7;
*(u32*)0xBC100078 = *(u32*)0xBC100078 | 0x2;		IO Enable: USB
*(u32*)0xBE240000 = *(u32*)0xBE240000 & 0xFFFFFFEF;	GPIO 
*(u32*)0xBE240040 = *(u32*)0xBE240040 | 0x10;		
delay(1);
*(u32*)0xBD500010 = 1;					Graphics engine
while(*(u32)0xBD500010&0x1);
*(u32*)0xBD500040 = 1;

REG_CONF_TBL1 do the following Ops:
*(u32*)0xBC100054 = *(u32*)0xBC100054 | 0x100;		Mem stick init
*(u32*)0xBC100050 = *(u32*)0xBC100050 | 0x400;
*(u32*)0xBC100078 = *(u32*)0xBC100078 | 0x10;
*(u32*)0xBC10004C = *(u32*)0xBC10004C & 0xFFFFFEFF;

*/

#include "preIPL_ram_def.h"

/***********************************************************************/
iplBlock *block = (void*) 0xBDF00000; //temp addr to store a single ipl block
LoadIplBlockFunc LoadIplBlock;//0x80010808
int iplBlockNumber = 0; //0x8001080C
u32 gSpare[3]; //0x80010810
u8 gIplBlkIndex[512]; //0x8001081C
u32 REG_CONF_TBL0[]={//0x80010A80
	0x1C100058, 0x00800000,
	0x1C100050, 0x0000608E,
	0x2C10004C, 0xFFFFFBF7,
	0x1C100078, 0x00000002,
	0x2E240000, 0xFFFFFFEF,
	0x1E240040, 0x00000010,
	0x50000000, 0x00000001,
	0x0D500010, 0x00000001,
	0x3D500010, 0x00000001,
	0x0D500040, 0x00000001,
	0xF0000000,
};
u32 REG_CONF_TBL1[]={//0x80010AD4
	0x1C100054, 0x00000100,
	0x1C100050, 0x00000400,
	0x1C100078, 0x00000010,
	0x2C10004C, 0xFFFFFEFF,
	0xF0000000,
}

/***********************************************************************/
// 0x80010000
void _RamEntry(void)
{
	u32 checksum = 0;
	SysRegConfig((regConf *)REG_CONF_TBL0);
	if (*0xBC100068 >> 16)
		SYSREG_IO0_ENABLE(KEY_IO);
	else
		SYSREG_IO1_ENABLE(4);
	Delay(10);
	SYNC();

	// if service mode
	if (REG32(0xBE240004) & GPIO_MASK_JIGKICK){
		LoadIplBlock = (void *)LoadIplBlockFromMs;
		MsCheck(); // will stuck here on empty MS
	}else{
		LoadIplBlock = (void *)LoadIplBlockFromNand;
		ReadIplNandBlockTable(); // will stuck here on empty nand
	}

	// load/decrypt all encrypted ipl blocks
	while(1){
		// copy an encrypted ipl block to 0xBFD00000-0xBFD01000 (4KB temp ram)
		if (LoadIplBlock(iplBlockNumber, block) < 0) while(1);
		// decrypt the ipl block in place (uh oh...)
		if (DecryptIplBlock(block, block)) while(1);
		// note first block has zero as its checksum (another uh oh...)
		if (block->checksum != checksum) while(1);
		// load the 'data' section of the ipl block to the specified address (0x040Fxxxx range)
		if (block->loadaddr) checksum = _Memcpy(block->loadaddr, block->data, block->blocksize);
		// reached the end of the ipl, jump to the entry address (0x040F0000)
		if (block->entry){
			// clear caches
			ClearDCache();
			ClearICache();
			// jump to ipl - do not return
			block->entry();
		}
		iplBlockNumber++;
	}
}

/***********************************************************************/
// 0x80010130
void ReadIplNandBlockTable(void)
{
	u32 iplBlkIndexPage = 128;
	ResetNand();
	// if empty nand, this while loop is where it'll get stuck
	while(1){
		if (ReadNandPage(iplBlkIndexPage, gIplBlkIndex, gSpare) >= 0)
			if (gSpare[1] == 0x6DC64A38) return;
		iplBlkIndexPage += NAND_PAGES_PER_BLOCK; // try next block
	}
}

/***********************************************************************/
// 0x80010194
#define IPLBLOCKNUM_TO_NANDPAGENUM(b)	(((*(u16 *)(gIplBlkIndex + (b>>2)<<1) << 2) | (b&3)) << 3)
#define NUMPAGES_PER_IPLBLOCK		(8)
int LoadIplBlockFromNand(int iplBlockNum, void *buf)
{
	int i;
	int pageNum = IPLBLOCKNUM_TO_NANDPAGENUM(iplBlockNum);
	*0x80010804 = iplBlockNum; //unuseful
	for (i=0; i<NUMPAGES_PER_IPLBLOCK; i++){
		if (ReadNandPage(pageNum+i, buf+i*NAND_LOGICAL_PAGE_SIZE, &gSpare) < 0) return -1;
		if (gSpare[1] != 0x6DC64A38) return -1;
	}
	return 0;
}

/***********************************************************************/
// 0x80010240
void MsCheck(void)
{
	_MsCheck();
}

/***********************************************************************/
// 0x80010248
int LoadIplBlockFromMs(int iplBlockNum, void *buf)
{
	u32 a0, i;
	for (i=0; i<8; i++){
		a0 = (iplBlockNum*8)+i;
		a0 += 0x10;
		while(ReadMsSector(a0, buf+i*512) < 0);
	}
	return 0;
}

/***********************************************************************/
// 0x800102A0 
void ClearICache(void)
{
	__asm__ volatile
	(
	 ".word 0x40088000 \n" // mfc0    $t0, Config
	 ".word 0x24091000 \n" // li      $t1, 0x1000
	 ".word 0x7D081240 \n" // ext     $t0, 9, 3
	 ".word 0x01094804 \n" // sllv    $t1, $t0
	 ".word 0x4080E000 \n" // mtc0    $0, TagLo
	 ".word 0x4080E800 \n" // mtc0    $0, TagHi
	 ".word 0x00004021 \n" // move    $t0, $0
	 ".word 0xBD010000 \n" // cache   1, 0($t0) #loop
	 ".word 0xBD030000 \n" // cache   3, 0($t0) 
	 ".word 0x25080040 \n" // addiu   $t0, 0x40
	 ".word 0x1509FFFC \n" // bne     $t0, $t1, loop
	 ".word 0x00000000 \n" // nop
	 ".word 0x03E00008 \n" // jr      $ra
	 ".word 0x00000000 \n" // nop
	 );
}

/***********************************************************************/
// 0x800102D8
void ClearDCache(void)
{
	__asm__ volatile
	(
	 ".word 0x40088000 \n" // mfc0    $t0, Config
	 ".word 0x24090800 \n" // li      $t1, 0x800
	 ".word 0x7D081180 \n" // ext     $t0, 6, 3
	 ".word 0x01094804 \n" // sllv    $t1, $t0
	 ".word 0x00004021 \n" // move    $t0, $0
	 ".word 0xBD140000 \n" // cache   0x14, 0($t0) #loop
	 ".word 0xBD140000 \n" // cache   0x14, 0($t0)
	 ".word 0x25080040 \n" // addiu   $t0, 0x40
	 ".word 0x1509FFFC \n" // bne     $t0, $t1, loop
	 ".word 0x00000000 \n" // nop
	 ".word 0x03E00008 \n" // jr      $ra
	 ".word 0x0000000F \n" // sync
	 );
}

/***********************************************************************/
 //0x80010308
void ResetNand(void)
{
	NAND_SET_CMD(NAND_RESET_CMD);
	while((NAND_GET_STATUS() & 1) == NAND_BUSY);
	NAND_SET_RESET(1);
}

/***********************************************************************/
//0x80010334
int ReadNandPage(int pageNum, void *buf, void *spare)
{
	while((NAND_GET_STATUS() & 1) == NAND_BUSY);
	
	NAND_SET_DMA_ADDR(pageNum*1024); // shouldnt this be 512?
	
	NAND_SET_DMA_CTRL(0x00000301);
	while(NAND_GET_DMA_CTRL() & 1);
	
	if (NAND_GET_DMA_STAT()) return -1;
	
	spare[0] = NAND_GET_SPARE_BUF0();
	spare[1] = NAND_GET_SPARE_BUF1();
	spare[2] = NAND_GET_SPARE_BUF2();
	
	MEMCPY(buf, NAND_GET_PAGE_DATA(), NAND_PAGE_LOGICAL_SIZE);
	
	return 0;
}

/***********************************************************************/
//0x800103B4
void _MsCheck(void)
{
	u8 ret;
	SysRegConfig((regConf *)REG_CONF_TBL1);
	//reset the controller
	IO_MEM_STICK_SYS = MSRST;
	while(IO_MEM_STICK_SYS & MSRST);
	CheckMsStatus();
	WaitMsReady();
	do{
		ret = GetMsStatus();
	} while ((ret<0) || (ret & INT_REG_CED == 0));	
}

/***********************************************************************/
//0x80010418
int ReadMsSector(int sectNum, void *buf)
{
	int ret;
	IO_MEM_STICK_CMD = EX_SET_CMD | 0x7;
	ret = SendDataAndSync(0x00010020 | ((sectNum>>24)<<24), ENDIAN_SWAP(sectNum)>>8);
	if (ret<0) return -1;
	WaitMsStatus();
	do{
		ret = GetMsStatus(); 
		if(ret<0) return -1;
	} while(!(ret & INT_REG_BREQ));
	if (ret & INT_REG_ERR) return -1;

	//send command to read data and get the data.
	IO_MEM_STICK_CMD = READ_PAGE_DATA | 512;
	ret = ReadMsData(buf, 512); 
	if(ret<0) return -1;
	ret = WaitMsReady();  
	if(ret<0) return -1;
	
	WaitMsStatus();
	do{
		ret = GetMsStatus();
	} while ((ret<0) || (ret & INT_REG_CED == 0));
	
	return 0;
}

/***********************************************************************/
//0x800104C0
int SendDataAndSync(u32 arg1, u32 arg2)
{
	int ret;
	IO_MEM_STICK_DATA = arg1;
	IO_MEM_STICK_DATA = arg2;
	ret = WaitMsReady();
	return ret;	
}

/***********************************************************************/
//0x800104CC
int ReadMsData(void *addr, int count)
{
	int i;
	int status;
	for(i = 0; i<count; i+= 4){
		do{
			status = IO_MEM_STICK_STATUS;
			if (status & MS_TIME_OUT) return -1;
		}while(!(status & MS_FIFO_RW));
		*((volatile int*)(addr + i)) = IO_MEM_STICK_DATA;
	}
	return 0;
}

/***********************************************************************/
//0x80010508
int WaitMsReady(void)
{
	int status;
	do{
		status = IO_MEM_STICK_STATUS;
	}while(!(status & MS_RDY));

	if (status & (MS_CRC_ERROR|MS_TIME_OUT)){
		return -1;
	}
	return 0;
}

/***********************************************************************/
//0x80010530
int CheckMsStatus(void)
{
	int ret;
	u8 status[8]; //80010A1C
	IO_MEM_STICK_CMD = SET_RW_REG_ADRS | 0x4;
	IO_MEM_STICK_DATA = 0x06100800;
	IO_MEM_STICK_DATA = 0x00000000;
	if (WaitMsReady() < 0) return -1;
	ret = ReadMsReg(status, 8);
	if (0 != (status[2] & 0x15)) return -1;
	return 0;
}

/***********************************************************************/
//0x800105A4
int ReadMsReg(void *buffer, int reg)
{
	int ret;
	IO_MEM_STICK_CMD = READ_REG | reg;
	ret = ReadMsData(buffer, reg);
	return ret;
}

/***********************************************************************/
//0x800105B8
u8 GetMsStatus()
{
	u32 ret, dummy;
	IO_MEM_STICK_CMD = GET_INT |0x1;
	do
	{
		if (IO_MEM_STICK_STATUS & MS_TIME_OUT) 
			return -1;
	} while(!(IO_MEM_STICK_STATUS & MS_FIFO_RW));
	
	ret = IO_MEM_STICK_DATA;
	dummy = IO_MEM_STICK_DATA; //$zero = *0xBD200034;
	do
	{
		if (IO_MEM_STICK_STATUS & MS_TIME_OUT)
			return -1;
	} while(!(IO_MEM_STICK_STATUS & MS_RDY));
	return(ret & 0xFF);
}

/***********************************************************************/
//0x80010608
void WaitMsStatus(void)
{
	while(!(IO_MEM_STICK_STATUS & 0x2000));
}

/***********************************************************************/
//0x80010620
u32 DecryptIplBlock(void *dst, void *src)
{
	PspKirkRegs *const crypt = KIRK_HW_REGISTER_ADDRESS;
	crypt->command = ASYMM_CIPHER1;
	crypt->src_addr = (void *) GET_PHYSICAL_ADDRESS(src);
	crypt->dst_addr = (void *) GET_PHYSICAL_ADDRESS(dst);
	crypt->proc_phase = PHASE1; // tell hardware to start work
	while(!(crypt->status & (STATUS_FLAG1 | STATUS_FLAG5))); // while not complete and not error?
	if (crypt->status & STATUS_FLAG5){// error
		crypt->proc_phase = PHASE2;
		while(!(crypt->status & STATUS_FLAG2));
		crypt->status_end = crypt->status;
		SYNC();
		return -1;
	}
	crypt->status_end = crypt->status;
	return(crypt->result);
}

/***********************************************************************/
//0x80010688
u32 _Memcpy(void *dst, void *src, int size)
{
	u32 checksum = 0;
	
	// decrementing 'i' because more optimised in asm
	for (i=size; i>0; i-=4)
	{
		*dst = *src;
		checksum += *src;
		src += 4;
		dst += 4;
	}
	
	return(checksum);
}

/***********************************************************************/
//0x800106B0
void SysRegConfig(regConf *conf)
{
	u8 opcode;
	u32 addr, val;
	regConf *p = conf;
	while(1){
		addr = p->addr  | 0xb0000000;
		val = p->val;
		switch(p->opcode){
			case 0:
				*addr = val;
				break;
			case 1:
				*addr = *addr | val;
				break;
			case 2:
				*addr = *addr & val;
				break;
			case 3:
				while(*addr & val);
				break;
			case 4:
				while((~(*addr)) & val);
				break;
			case 5:
				delay(val);
				break;
			default:
				return;
		}
		p++;
	}
}

/***********************************************************************/
//80010768
void Delay(int cnt)
{
    int loop = (cnt*2+cnt)<<5;
    while(loop) loop--;
    return;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值