#include <windows.h>
#include <pehdr.h>
#include <romldr.h>
#include "option.h"
#include "s2410addr.h"
// Constants.
//
#define LED_ON 0xA
#define LED_OFF 0x0
#define NAND_BLOCK_SIZE_BYTES 0x00004000
#define NAND_PAGE_SIZE_BYTES 0x00000200
#define NAND_PAGES_PER_BLOCK (NAND_BLOCK_SIZE_BYTES / NAND_PAGE_SIZE_BYTES)
// NOTE: we assume that this Steppingstone loader occupies *part* the first (good) NAND flash block. More
// specifically, the loader takes up 4096 bytes (or 8 NAND pages) of the first block. We'll start our image
// copy on the very next page.
#define NAND_COPY_PAGE_OFFSET 2*NAND_PAGES_PER_BLOCK
#define LOAD_ADDRESS_PHYSICAL 0x30038000
#define LOAD_SIZE_BYTES 0x00040000
#define LOAD_SIZE_PAGES (LOAD_SIZE_BYTES / NAND_PAGE_SIZE_BYTES)
#define SIGN_ON "/nWinCE nBoot v1.00 " __DATE__ " " __TIME__ "/r/n"
// Globals variables.
//
ROMHDR * volatile const pTOC = (ROMHDR *)-1;
// Function prototypes.
//
void MMU_EnableICache(void);
void Led_Display(int);
void Port_Init(void);
void ChangeClockDivider(int hdivn, int pdivn);
void ChangeMPllValue(int mdiv, int pdiv, int sdiv);
void NF_Init(void);
int NF_ReadPage(UINT32 block, UINT32 page, volatile BYTE *buffer);
//
typedef void (*PFN_IMAGE_LAUNCH)();
/*
@func BOOLEAN | SetupCopySection | Copies the IPL image's copy section data (initialized globals) to the correct fix-up location. Once completed, the IPLs initialized globals are valid.
@rdesc TRUE == Success and FALSE == Failure.
@comm
@xref
*/
static BOOLEAN SetupCopySection(ROMHDR *const pTOC)
{
// This code doesn't make use of global variables so there are no copy sections. To reduce code size, this is a stub function...
//
return(TRUE);
}
/*
@func void | main | C entrypoint function for the Steppingstone loader.
@rdesc None.
@comm
@xref
*/
void main(void)
{
register nBlock;
register nPage;
register nBadBlocks;
volatile BYTE *pCopyPtr;
// Set up copy section (initialized globals).
//
// NOTE: after this call, globals become valid.
//
SetupCopySection(pTOC);
// Enable the ICache.
//
MMU_EnableICache();
// Set up clock and PLL.
//
ChangeClockDivider(1, 1); // 1:2:4.
ChangeMPllValue(0x5C, 0x4, 0x0); // Fin=12MHz FCLK=202.8MHz.
// Set up all GPIO ports.
//
Port_Init();
Uart_Init();
Uart_SendString(SIGN_ON);
// Initialize the NAND flash interface.
//
NF_Init();
// Turn the LEDs off.
//
Led_Display(LED_OFF);
// Copy image from NAND flash to RAM.
//
pCopyPtr = (BYTE *)LOAD_ADDRESS_PHYSICAL; //指向跳转的地址
// NOTE: we assume that this Steppingstone loader occupies *part* the first (good) NAND flash block. More
// specifically, the loader takes up 4096 bytes (or 8 NAND pages) of the first block. We'll start our image
// copy on the very next page.
nBadBlocks = 0;
for (nPage = NAND_COPY_PAGE_OFFSET ; nPage < (LOAD_SIZE_PAGES + NAND_COPY_PAGE_OFFSET) ; nPage++)
{
nBlock = ((nPage / NAND_PAGES_PER_BLOCK) + nBadBlocks);
if (!NF_ReadPage(nBlock, (nPage % NAND_PAGES_PER_BLOCK), pCopyPtr))
{
if ((nPage % NAND_PAGES_PER_BLOCK) != 0)
{
Led_Display(0x9); // real ECC Error.
// Spin forever...
while(1)
{
}
}
// ECC error on a block boundary is (likely) a bad block - retry the page 0 read on the next block.
nBadBlocks++;
nPage--;
continue;
}
pCopyPtr += NAND_PAGE_SIZE_BYTES;
}
// Turn the LEDs on.
//
Led_Display(LED_ON);
// Jump to the image...
//
((PFN_IMAGE_LAUNCH)(LOAD_ADDRESS_PHYSICAL))(); //跳转到EBOOT的起始地址,可以参考BOOT.BIB
}
本文只分析红色部分,其他部分,请大家自己分析了哦。。
#define NAND_BLOCK_SIZE_BYTES 0x00004000
#define NAND_PAGE_SIZE_BYTES 0x00000200
#define NAND_PAGES_PER_BLOCK (NAND_BLOCK_SIZE_BYTES / NAND_PAGE_SIZE_BYTES)
// NOTE: we assume that this Steppingstone loader occupies *part* the first (good) NAND flash block. More
// specifically, the loader takes up 4096 bytes (or 8 NAND pages) of the first block. We'll start our image
// copy on the very next page.
#define NAND_COPY_PAGE_OFFSET 2*NAND_PAGES_PER_BLOCK
#define LOAD_ADDRESS_PHYSICAL 0x30038000
#define LOAD_SIZE_BYTES 0x00040000
#define LOAD_SIZE_PAGES (LOAD_SIZE_BYTES / NAND_PAGE_SIZE_BYTES)
NAND FLASH的BLOCK0作为BOOT引导。由于NAND FLASH的特性,1BLOCK = 32PAGE = 32X512BYTE=16K。所以NAND_PAGE_SIZE_BYTES被定义为0x200=512。NAND_PAGES_PER_BLOCK的意思是每块有多少页。按着上面的公式算出为32页。NAND_COPY_PAGE_OFFSET=2*NAND_PAGE_PER_BLOCK,为什么要偏移64页呢。。这是因为TOC_BLOCK是被定义在BLOCK2,而NBOOT被定义在BLOCK1,所以需要偏移64页。
LOAD_SIZE_BYTES被定义为256K。这是因为在BOOT.BIB文件中定义滴,见下面的定义:
MEMORY
; Name Start Size Type
; ------- -------- -------- ----
ARGS 80020800 00000800 RESERVED
BINFS 80021000 00005000 RESERVED
RAM 80026000 00006000 RAM
STACK 8002c000 00004000 RESERVED
EBOOT 80038000 00040000 RAMIMAGE
看到了吧LOAD_ADDRESS_PHYSICAL=0x30038000,而在Oemaddrtab_cfg.inc中有这样的定义:[红色部分]
;------------------------------------------------------------------------------
;
; File: Oemaddrtab_cfg.inc
;
; This file is used to define g_oalAddressTable. This table is passed to
; KernelStart to estabilish physical to virtual memory mapping. This table
; is used also in IOMEM OAL module to map between physical and virtual
; memory addresses via OALPAtoVA/OALVAtoPA functions.
;
;------------------------------------------------------------------------------
; Export Definition
EXPORT g_oalAddressTable[DATA]
;------------------------------------------------------------------------------
;
; TABLE FORMAT
; cached address, physical address, size
;------------------------------------------------------------------------------
g_oalAddressTable
DCD 0x80000000, 0x30000000, 64 ; 32 MB DRAM BANK 6
DCD 0x84000000, 0x10000000, 32 ; nGCS2: PCMCIA/PCCARD
DCD 0x86000000, 0x18000000, 32 ; 32 MB SROM(SRAM/ROM) BANK 3
DCD 0x88000000, 0x20000000, 32 ; 32 MB SROM(SRAM/ROM) BANK 4
DCD 0x8A000000, 0x28000000, 32 ; 32 MB SROM(SRAM/ROM) BANK 5
DCD 0x8C000000, 0x08000000, 32 ; 32 MB SROM(SRAM/ROM) BANK 1
因此LOAD_ADDRESS_PHYSICAL=0x30038000和0x80038000是指向同一个地址滴。
下面的代码是从NAND FLASH中的BLOCK3开始读取256K的EBOOT程序:
nBadBlocks = 0;
for (nPage = NAND_COPY_PAGE_OFFSET ; nPage < (LOAD_SIZE_PAGES + NAND_COPY_PAGE_OFFSET) ; nPage++)
{
nBlock = ((nPage / NAND_PAGES_PER_BLOCK) + nBadBlocks);
if (!NF_ReadPage(nBlock, (nPage % NAND_PAGES_PER_BLOCK), pCopyPtr))
{
if ((nPage % NAND_PAGES_PER_BLOCK) != 0)
{
Led_Display(0x9); // real ECC Error.
// Spin forever...
while(1)
{
}
}
// ECC error on a block boundary is (likely) a bad block - retry the page 0 read on the next block.
nBadBlocks++;
nPage--;
continue;
}
pCopyPtr += NAND_PAGE_SIZE_BYTES;
}
具体是怎样实现的,请自行分析了哦。嘿嘿。。好累。。去休息去了哦。