Add NAND ECC correction to miniios and use for boot2 loads

This commit is contained in:
marcan 2009-03-07 17:31:45 +01:00 committed by bushing
parent 3310503c11
commit d1f9fa8a3a
4 changed files with 53 additions and 1 deletions

View File

@ -42,6 +42,10 @@ void boot2_init() {
for (i = 0x40; i < 0x140; i++, ptr += 2048) {
nand_read_page(i, ptr, ecc);
nand_wait();
if(nand_correct(i, ptr, ecc) < 0) {
gecko_printf("boot2 is corrupted, cannot load!\n");
return;
}
}
if (hdr->len != sizeof(struct wadheader))
@ -75,6 +79,7 @@ void boot2_init() {
memcpy(boot2, cntptr, datalen);
boot2_initialized = 1;
gecko_printf("boot2 loaded\n");
}
static u32 match[] = {

1
main.c
View File

@ -178,7 +178,6 @@ void *_main(void *base)
gecko_puts("NAND initialized.\n");
boot2_init();
gecko_puts("Boot2 loaded to memory.\n");
gecko_puts("Initializing IPC...\n");
ipc_initialize();

42
nand.c
View File

@ -200,6 +200,48 @@ void nand_initialize(void)
irq_enable(IRQ_NAND);
}
int nand_correct(u32 pageno, void *data, void *ecc)
{
u8 *dp = (u8*)data;
u32 *ecc_read = (u32*)((u8*)ecc)+0x30;
u32 *ecc_calc = (u32*)((u8*)ecc)+0x40;
int i;
int uncorrectable = 0;
int corrected = 0;
for(i=0;i<4;i++) {
u32 syndrome = *ecc_read ^ *ecc_calc; //calculate ECC syncrome
if(syndrome) {
if(!((syndrome-1)&syndrome)) {
// single-bit error in ECC
corrected++;
} else {
// byteswap and extract odd and even halves
u16 even = (syndrome >> 24) | ((syndrome >> 8) & 0xf00);
u16 odd = ((syndrome << 8) & 0xf00) | ((syndrome >> 8) & 0x0ff);
if((even ^ odd) != 0xfff) {
// oops, can't fix this one
uncorrectable++;
} else {
// fix the bad bit
dp[odd >> 3] ^= 1<<(odd&7);
corrected++;
}
}
}
dp += 0x200;
ecc_read++;
ecc_calc++;
}
if(uncorrectable || corrected)
gecko_printf("ECC stats for NAND page 0x%x: %d uncorrectable, %d corrected\n", uncorrectable, corrected);
if(uncorrectable)
return NAND_ECC_UNCORRECTABLE;
if(corrected)
return NAND_ECC_CORRECTED;
return NAND_ECC_OK;
}
void nand_ipc(volatile ipc_request *req)
{
if (ipc_code != 0 || ipc_tag != 0) {

6
nand.h
View File

@ -17,6 +17,12 @@ void nand_wait(void);
void nand_read_cluster(u32 clusterno, void *data);
#define NAND_ECC_OK 0
#define NAND_ECC_CORRECTED 1
#define NAND_ECC_UNCORRECTABLE -1
int nand_correct(u32 pageno, void *data, void *ecc);
void nand_initialize();
void nand_ipc(volatile ipc_request *req);