#include "libsys_boot.h" #include "cfiflash.h" #define MAGIC_EB 0x4A464931 // "JFI1" in big-endian; #define MAGIC_EL 0x3149464A // "JFI1" in little-endian; typedef struct _ssrec_t { uint32_t addr; uint32_t size; uint32_t type; uint8_t *data; } srec_t; typedef struct _sflash_alloc_tbl_t { uint32_t images[16]; } flash_alloc_tbl_t; typedef struct _sflash_img_hdr_t { uint32_t magic; uint32_t target_base; uint32_t img_base; uint32_t img_size; uint32_t hdr_next; uint8_t img_name[128]; uint8_t res[108]; } flash_img_hdr_t; enum srec_type { srec_err, srec_sob, srec_data, srec_rec, srec_eob }; uint8_t h2i(uint8_t *c) { int i; uint8_t 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_t *pBuf, int buflen) { uint8_t 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_t*) &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_t *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 ( "li $26, 0x1000000A\n" "mtc0 $26, $12\n" ); __asm ( "jr %[pEntry]\n" // jump entry : : [pEntry] "r" (pEntry) ); __asm ( "rfe\n" ); __asm ( ".set reorder\n" ); } void Exec_RE_at(void *pEntry) { __asm ( ".set noreorder\n" ); __asm ( "mfc0 $26, $12\n" // change exception vector "li $27, 0xFFBFFFFF\n" "and $26, $27\n" "li $27, 0x02000000\n" // Reverse Endianess "or $26, $27\n" "mtc0 $26, $12\n" ); __asm ( "jr %[pEntry]\n" // jump entry : : [pEntry] "r" (pEntry) ); __asm ( "rfe\n" ); __asm ( ".set reorder\n" ); } #define MAX_IMG_SIZE (1024*1024) // bytes #define FLASH_USE_BLOCK 1 int main(int argc, char *argv[]) { uint8_t buf[256]; srec_t srec; int srec_state, i; uint32_t haddr, result; flash_t flash; flash_img_hdr_t img_hdr = {0}; flash_img_hdr_t *pImg_hdr; uint32_t img_size, block_sel; volatile uint32_t *pGPIO_DATA = (uint32_t*)SYS_GPIO_0_DATA; volatile uint8_t *pMem; volatile uint32_t *pFlashIO = (uint32_t*)FLASH_BASE_IO; // Flash in uncached area volatile uint32_t *pFlashMem = (uint32_t*)FLASH_BASE_MEM; // Flash in cached area volatile uint32_t *ram32 = (uint32_t*)SDRAM_BASE; uint32_t flash_offset; *pGPIO_DATA = GPIO_0_DFLT_DATA; haddr = 0; block_sel = 0x7F & (uint32_t)((*pGPIO_DATA & GPIO_0_DIP) >> GPIO_0_ALIGN_DIP); sputs("\nMIPS bootloader\n"); // ---------------------------------------------------------- if (IS_ERROR(flash_find(&flash, SYS_FLASH_IO))) { sputs("Cannot find flash device. Exit now!\n\n"); return 1; } // Get flash offset by value of DIP-switch flash_offset = flash_get_offset_by_blocknum(&flash, block_sel); ram32 = (uint32_t*)(SDRAM_BASE); pFlashIO = (uint32_t*)(SYS_FLASH_IO + flash_offset); if (!(((*pGPIO_DATA & GPIO_0_BTN) >> GPIO_0_ALIGN_BTN) & 8)) { sputs("Loading image from flash at ");print_word(flash_offset);sputs("\n"); pImg_hdr = (flash_img_hdr_t*)pFlashIO; if ((pImg_hdr->magic != MAGIC_EL) && (pImg_hdr->magic != MAGIC_EB)) { sputs("\n\n"); sputs("Invalid image found at ");print_word(flash_offset); sputs(". Abort.\n"); return 1; } ram32 = (uint32_t*)pImg_hdr->target_base; img_size = pImg_hdr->img_size; // It's safe to use cached Flash, // because D-Cache was invalidated during execution of start code pFlashMem = (uint32_t*)pImg_hdr->img_base; for (i=0; i < img_size/4; i++) ram32[i] = pFlashMem[i]; sputs("Booting from ");print_word(pImg_hdr->target_base);sputs("\n\n"); Exec_at((void*)ram32); } else { sputs("\n\n"); sputs("Reading HEX-Record from UART.."); // Erase SDRAM for (i=0; i < MAX_IMG_SIZE/4; i++) ram32[i] = 0; while(1) { sputs("."); while(1) { result = srec_getline(buf); srec_state = decode_srec(&srec, buf, result); switch (srec_state) { case srec_data: if ((srec.addr + srec.size) > haddr) haddr = srec.addr + srec.size; pMem = (uint8_t*)srec.addr; for (i=0; i < srec.size; i++) *pMem++ = srec.data[i]; break; case srec_eob: sputs("done\n\n"); img_hdr.magic = MAGIC_EB; img_hdr.target_base = srec.addr; img_hdr.img_size = haddr - srec.addr; img_hdr.img_base = flash_offset + sizeof(flash_img_hdr_t); img_hdr.hdr_next = flash_get_offset_blockaligned(&flash, img_hdr.img_base + img_hdr.img_size); sputs("Size of application : ");print_word(img_hdr.img_size); sputs("\n"); sputs("Programming flash at : ");print_word(flash_offset); sputs("\n"); sputs("Next free flash offset : ");print_word(img_hdr.hdr_next); sputs("\n"); sputs("Flash erase..."); result = flash_erase(&flash, flash_offset, img_hdr.img_size + sizeof(flash_img_hdr_t)); if (IS_ERROR(result)) { sputs("failed (");print_word(result);sputs(")\n"); break; } sputs("done\n"); sputs("Flash write..."); result = flash_program(&flash, flash_offset, (uint8_t*)&img_hdr, sizeof(flash_img_hdr_t)); if (IS_ERROR(result)) { sputs("failed (");print_word(result);sputs(")\n"); break; } result = flash_program(&flash, img_hdr.img_base, (uint8_t*)img_hdr.target_base, img_hdr.img_size); if (IS_ERROR(result)) { sputs("failed (");print_word(result);sputs(")\n"); break; } sputs("done\n"); sputs("Flash verify..."); result = flash_verify(&flash, img_hdr.img_base, (uint8_t*)img_hdr.target_base, img_hdr.img_size); if (IS_ERROR(result)) { sputs("failed (");print_word(result);sputs(")\n"); break; } sputs("passed\n"); // Jump to reset vector Jump_to((void*)0xBFC00000); break; default: result = -1; break; } if (IS_ERROR(result)) { break; } }; } } return 0; }