Committed on the Free edition of March Hare Software CVSNT Server. Upgrade to CVS Suite for more features and support: http://march-hare.com/cvsnt/ git-svn-id: http://moon:8086/svn/vhdl/trunk@319 cc03376c-175c-47c8-b038-4cd826a8556b
361 lines
6.0 KiB
C
361 lines
6.0 KiB
C
#include "libsys_boot.h"
|
|
#include "cfiflash.h"
|
|
|
|
typedef struct _ssrec_t
|
|
{
|
|
UINT32 addr;
|
|
UINT32 size;
|
|
UINT32 type;
|
|
UINT8 *data;
|
|
|
|
} srec_t;
|
|
|
|
typedef struct _sflash_img_hdr_t
|
|
{
|
|
UINT8 magic[4];
|
|
UINT32 target_addr;
|
|
UINT32 img_offset;
|
|
UINT32 img_size;
|
|
UINT32 hdr_next;
|
|
UINT8 img_name[128];
|
|
UINT8 res[108];
|
|
|
|
} flash_img_hdr_t;
|
|
|
|
enum srec_type
|
|
{
|
|
srec_err, srec_sob, srec_data, srec_rec, srec_eob
|
|
};
|
|
|
|
UINT8 h2i(UINT8 *c)
|
|
{
|
|
int i;
|
|
UINT8 t, b = 0;
|
|
|
|
for (i=0; i < 2; i++)
|
|
{
|
|
t = c[i];
|
|
if (t >= 'A')
|
|
t = t - 'A' + 10;
|
|
else
|
|
t -= '0';
|
|
|
|
b = (b << 4) | t;
|
|
}
|
|
return b;
|
|
}
|
|
|
|
int decode_srec(srec_t *pRec, UINT8 *pBuf, int buflen)
|
|
{
|
|
UINT8 chksum, byte;
|
|
int alen, i;
|
|
|
|
if (!buflen)
|
|
return srec_err;
|
|
|
|
pRec->type = srec_rec;
|
|
alen = 0;
|
|
if ((pBuf[1] > '0') && (pBuf[1] < '4'))
|
|
{
|
|
alen = pBuf[1] - '0' + 1;
|
|
pRec->type = srec_data;
|
|
}
|
|
else if ((pBuf[1] >= '7') && (pBuf[1] <= '9'))
|
|
{
|
|
alen = 11 - (pBuf[1] - '0');
|
|
pRec->type = srec_eob;
|
|
}
|
|
else if (pBuf[1] == '0')
|
|
{
|
|
alen = 2;
|
|
pRec->type = srec_sob;
|
|
}
|
|
|
|
byte = h2i(&pBuf[2]);
|
|
pRec->size = byte;
|
|
chksum = byte;
|
|
|
|
pRec->addr = 0;
|
|
for (i=0; i < alen; i++)
|
|
{
|
|
byte = h2i(&pBuf[4+2*i]);
|
|
pRec->addr = pRec->addr << 8 | byte;
|
|
chksum += byte;
|
|
}
|
|
pRec->size -= (alen+1);
|
|
|
|
pRec->data = (UINT8*) &pBuf[4 + 2*alen];
|
|
for (i=0; i < (int)pRec->size; i++)
|
|
{
|
|
byte = h2i(&pRec->data[2*i]);
|
|
pRec->data[i] = byte;
|
|
chksum += byte;
|
|
}
|
|
chksum = ~chksum;
|
|
byte = h2i(&pRec->data[2*i]);
|
|
if (chksum != byte)
|
|
return 0;
|
|
|
|
return pRec->type;
|
|
}
|
|
|
|
int srec_getline(UINT8 *pLine)
|
|
{
|
|
char c;
|
|
int i = 0;
|
|
|
|
do
|
|
{
|
|
c = readchar();
|
|
|
|
} while ((c != 's') && (c != 'S'));
|
|
|
|
while(((c != 0x0D) && (c != 0x0A)))
|
|
{
|
|
pLine[i++] = c;
|
|
c = readchar();
|
|
};
|
|
|
|
return i;
|
|
}
|
|
|
|
void Jump_to(void *pEntry)
|
|
{
|
|
__asm
|
|
(
|
|
".set noreorder\n"
|
|
);
|
|
__asm
|
|
(
|
|
"jr %[pEntry]\n" // jump entry
|
|
:
|
|
: [pEntry] "r" (pEntry)
|
|
);
|
|
__asm
|
|
(
|
|
"nop\n"
|
|
);
|
|
__asm
|
|
(
|
|
".set reorder\n"
|
|
);
|
|
}
|
|
|
|
void Exec_at(void *pEntry)
|
|
{
|
|
__asm
|
|
(
|
|
".set noreorder\n"
|
|
);
|
|
|
|
__asm
|
|
(
|
|
"mfc0 $26, $12\n" // change exception vector
|
|
"li $27, 0xFFBFFFFF\n"
|
|
"and $26, $27\n"
|
|
"mtc0 $26, $12\n"
|
|
);
|
|
|
|
__asm
|
|
(
|
|
"jr %[pEntry]\n" // jump entry
|
|
:
|
|
: [pEntry] "r" (pEntry)
|
|
);
|
|
|
|
__asm
|
|
(
|
|
"rfe\n"
|
|
);
|
|
|
|
__asm
|
|
(
|
|
".set reorder\n"
|
|
);
|
|
}
|
|
|
|
void PrintCPUinfo(void)
|
|
{
|
|
int result, rev_id;
|
|
|
|
char *cpu_type_str[7] = {"invalid", "R2000", "R3000", "R6000", "R4000", "reserved", "R6000A"};
|
|
|
|
// Print Status register
|
|
result = CP0_SR_read();
|
|
|
|
sputs("Status : ");
|
|
print_word(result);
|
|
sputs("\n");
|
|
|
|
// Print Revision
|
|
result = CP0_PRID_read();
|
|
rev_id = (result >> 8) & 0xFF;
|
|
sputs("CPU type: ");
|
|
if ((rev_id > 0) && (rev_id < 0x07))
|
|
{
|
|
sputs(cpu_type_str[rev_id]);
|
|
sputs(" Rev.");
|
|
rev_id = result & 0xFF;
|
|
print_byte((char)rev_id);
|
|
}
|
|
else
|
|
sputs("Unknown");
|
|
|
|
sputs("\n");
|
|
|
|
}
|
|
|
|
#define MAX_IMG_SIZE (1024*1024) // bytes
|
|
#define SDRAM_BASE 0x40000000
|
|
#define FLASH_OFFSET 0x00000000
|
|
|
|
int main(int argc, char *argv[])
|
|
{
|
|
UINT8 buf[256];
|
|
srec_t srec;
|
|
int result, srec_state, i;
|
|
UINT32 haddr;
|
|
flash_t flash;
|
|
flash_img_hdr_t img_hdr = {0};
|
|
flash_img_hdr_t *pImg_hdr;
|
|
UINT32 img_size;
|
|
|
|
volatile UINT32 *pReg = (UINT32*)sys_led_port;
|
|
volatile UINT32 *pBtn = (UINT32*)sys_gpio0;
|
|
volatile UINT8 *pMem;
|
|
volatile UINT32 *pROM32;
|
|
volatile UINT32 *pMem32;
|
|
volatile UINT32 *pFlash = (UINT32*)sys_flash_io;
|
|
volatile UINT32 *pUSB = (UINT32*)sys_usb_data;
|
|
|
|
volatile UINT8 *ram8 = (UINT8*)SDRAM_BASE;
|
|
volatile UINT16 *ram16 = (UINT16*)SDRAM_BASE;
|
|
volatile UINT32 *ram32 = (UINT32*)SDRAM_BASE;
|
|
|
|
*pReg = 0;
|
|
haddr = 0;
|
|
|
|
// ----------------------------------------------------------
|
|
ram32 = (UINT32*)(SDRAM_BASE);
|
|
pFlash = (UINT32*)(sys_flash_io + FLASH_OFFSET);
|
|
|
|
if (!*pBtn)
|
|
{
|
|
sputs("\n\n");
|
|
sputs("Booting from flash...");
|
|
|
|
pImg_hdr = (flash_img_hdr_t*)pFlash;
|
|
ram32 = (UINT32*)pImg_hdr->target_addr;
|
|
pFlash = (UINT32*)(sys_flash_io + pImg_hdr->img_offset);
|
|
img_size = pImg_hdr->img_size;
|
|
|
|
for (i=0; i < img_size/4; i++)
|
|
ram32[i] = pFlash[i];
|
|
|
|
sputs("done\n\n");
|
|
|
|
Exec_at((void*)ram32);
|
|
}
|
|
else
|
|
{
|
|
|
|
if (flash_find(&flash, sys_flash_io) < 0)
|
|
{
|
|
sputs("Cannot find flash device. Exit now!\n\n");
|
|
return 1;
|
|
}
|
|
|
|
// Erase SDRAM
|
|
for (i=0; i < MAX_IMG_SIZE/4; i++)
|
|
ram32[i] = 0;
|
|
|
|
sputs("\n\n");
|
|
sputs("Booting from UART..");
|
|
|
|
while(1)
|
|
{
|
|
sputs(".");
|
|
while(1)
|
|
{
|
|
result = srec_getline(buf);
|
|
srec_state = decode_srec(&srec, buf, result);
|
|
*pReg = 0;
|
|
switch (srec_state)
|
|
{
|
|
case srec_data:
|
|
if ((srec.addr + srec.size) > haddr)
|
|
haddr = srec.addr + srec.size;
|
|
|
|
pMem = (UINT8*)srec.addr;
|
|
for (i=0; i < srec.size; i++)
|
|
*pMem++ = srec.data[i];
|
|
|
|
break;
|
|
|
|
case srec_eob:
|
|
sputs("done\n\n");
|
|
|
|
img_hdr.magic[0] = 'J';
|
|
img_hdr.magic[1] = 'F';
|
|
img_hdr.magic[2] = 'I';
|
|
img_hdr.magic[3] = '1';
|
|
img_hdr.target_addr = srec.addr;
|
|
img_hdr.img_size = haddr - srec.addr;
|
|
img_hdr.img_offset = FLASH_OFFSET + sizeof(flash_img_hdr_t);
|
|
img_hdr.hdr_next = FLASH_OFFSET;
|
|
|
|
sputs("Flash erase...");
|
|
result = flash_erase(&flash, FLASH_OFFSET, img_hdr.img_size + sizeof(flash_img_hdr_t));
|
|
if (result < 0)
|
|
{
|
|
sputs("failed!\n");
|
|
break;
|
|
}
|
|
sputs("done\n");
|
|
|
|
sputs("Flash write...");
|
|
result = flash_program(&flash, FLASH_OFFSET, (UINT8*)&img_hdr, sizeof(flash_img_hdr_t));
|
|
if (result < 0)
|
|
{
|
|
sputs("failed!\n");
|
|
break;
|
|
}
|
|
result = flash_program(&flash, img_hdr.img_offset, (UINT8*)ram32, img_hdr.img_size);
|
|
if (result < 0)
|
|
{
|
|
sputs("failed!\n");
|
|
break;
|
|
}
|
|
sputs("done\n");
|
|
|
|
sputs("Flash verify...");
|
|
result = flash_verify(&flash, img_hdr.img_offset, (UINT8*)ram32, img_hdr.img_size);
|
|
if (result < 0)
|
|
{
|
|
sputs("failed!\n");
|
|
break;
|
|
}
|
|
sputs("passed\n");
|
|
Jump_to((void*)0xBFC00000);
|
|
// sputs("\nPush reset button to boot!\n");
|
|
// *pReg = 1;
|
|
|
|
break;
|
|
|
|
default:
|
|
result = -1;
|
|
break;
|
|
}
|
|
if (result < 0)
|
|
{
|
|
*pReg = 0x40000000;
|
|
break;
|
|
}
|
|
|
|
};
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|