/*********************************************************************** * * Function: flash_image_save * * Purpose: Moves image in memory to FLASH application load region * * Processing: * See function. * * Parameters: None * * Outputs: None * * Returns: Always returns TRUE. * * Notes: None * **********************************************************************/ BOOL_32 flash_image_save(void) { UNS_32 fblock, ffblock; INT_32 sector, numsecs, nblks; FLASH_SAVE_T flashsavdat; /* Set first block pat boot loader */ ffblock = fblock = sysinfo.sysrtcfg.bl_num_blks; /* Save programmed FLASH data */ flashsavdat.block_first = fblock; flashsavdat.num_bytes = sysinfo.lfile.num_bytes; flashsavdat.loadaddr = sysinfo.lfile.loadaddr; flashsavdat.startaddr = (UNS_32) sysinfo.lfile.startaddr; flashsavdat.valid = TRUE; /* Get starting sector and number of sectors to program */ numsecs = sysinfo.lfile.num_bytes / sysinfo.nandgeom->data_bytes_per_page; if ((numsecs * sysinfo.nandgeom->data_bytes_per_page) < sysinfo.lfile.num_bytes) { numsecs++; } flashsavdat.secs_used = numsecs; nblks = numsecs / sysinfo.nandgeom->pages_per_block; if ((nblks * sysinfo.nandgeom->pages_per_block) < numsecs) { nblks++; } flashsavdat.blocks_used = nblks; /* Erase necessary blocks first */ while (nblks > 0) { if (flash_is_bad_block(ffblock) == FALSE) { flash_erase_block(ffblock); nblks--; } ffblock++; } /* Burn image into FLASH */ sector = conv_to_sector(fblock, 0); if (mem_to_nand(sector, (UNS_8 *) sysinfo.lfile.loadaddr, (numsecs * sysinfo.nandgeom->data_bytes_per_page)) == FALSE) { term_dat_out_crlf(nsaeerr_msg); } else { /* Update saved NAND configuration */ syscfg.fsave = flashsavdat; cfg_save(&syscfg); } return TRUE; }
/*********************************************************************** * * Function: nand_to_mem * * Purpose: Moves data from FLASH to memory * * Processing: * See function. * * Parameters: * starting_sector : Starting sector for read operation * buff : Buffer to place read data * bytes : Number of bytyes to read * * Outputs: None * * Returns: Nothing * * Notes: None * **********************************************************************/ BOOL_32 nand_to_mem(UNS_32 starting_sector, void *buff, UNS_32 bytes) { BOOL_32 blkchk; UNS_32 block, page, sector, toread; UNS_8 str[16], *p8 = (UNS_8 *) buff; if (sysinfo.nandgeom == NULL) { term_dat_out_crlf(noflash_msg); return FALSE; } /* Get block and page for passed sector */ block = starting_sector / sysinfo.nandgeom->pages_per_block; page = starting_sector - (block * sysinfo.nandgeom->pages_per_block); /* Read data */ blkchk = TRUE; while (bytes > 0) { /* Is a block check needed? */ if ((page == 0) && (blkchk == TRUE)) { if (flash_is_bad_block(block) != FALSE) { /* Goto next block */ term_dat_out(bskip_msg); str_makedec(str, block); term_dat_out_crlf(str); block++; page = 0; blkchk = TRUE; } else { blkchk = FALSE; } } else { /* Convert to sector */ sector = conv_to_sector(block, page); toread = bytes; if (toread > sysinfo.nandgeom->data_bytes_per_page) { toread = sysinfo.nandgeom->data_bytes_per_page; } /* Read sector data */ if (flash_read_sector(sector, secdat, NULL) <= 0) { term_dat_out(readerr_msg); str_makedec(str, sector); term_dat_out_crlf(str); } memcpy(p8, secdat, toread); p8 += toread; bytes -= toread; /* Next page and block */ page++; if (page >= sysinfo.nandgeom->pages_per_block) { page = 0; block++; blkchk = TRUE; } } } return TRUE; }
/*********************************************************************** * * Function: mem_to_nand * * Purpose: Moves data from memory to FLASH * * Processing: * See function. * * Parameters: * starting_sector : Starting sector for write * buff : Pointer to buffer to write * bytes : Number of bytes to write * * Outputs: None * * Returns: Nothing * * Notes: None * **********************************************************************/ BOOL_32 mem_to_nand(UNS_32 starting_sector, void *buff, UNS_32 bytes) { BOOL_32 blkchk; UNS_32 block, page, sector, wbytes; UNS_8 str[16], *p8 = (UNS_8 *) buff; if (sysinfo.nandgeom == NULL) { term_dat_out_crlf(noflash_msg); return FALSE; } /* Get block and page for passed sector */ block = starting_sector / sysinfo.nandgeom->pages_per_block; page = starting_sector - (block * sysinfo.nandgeom->pages_per_block); /* Align bytes to a sector boundary */ wbytes = bytes & ~(sysinfo.nandgeom->data_bytes_per_page - 1); if (wbytes < bytes) { bytes = wbytes + sysinfo.nandgeom->data_bytes_per_page; } /* Write data */ blkchk = TRUE; while (bytes > 0) { /* Is a block check needed? */ if ((page == 0) && (blkchk == TRUE)) { if (flash_is_bad_block(block) != FALSE) { /* Goto next block */ term_dat_out(bskip_msg); str_makedec(str, block); term_dat_out_crlf(str); block++; page = 0; } else { /* Block is good */ blkchk = FALSE; } } else { /* Convert to sector */ sector = conv_to_sector(block, page); /* Write sector data */ if (flash_write_sector(sector, p8, NULL) == FALSE) { term_dat_out(writeerr_msg); str_makedec(str, sector); term_dat_out_crlf(str); bytes = 0; return FALSE; } else { p8 += sysinfo.nandgeom->data_bytes_per_page; bytes -= sysinfo.nandgeom->data_bytes_per_page; } /* Next page and block */ page++; if (page >= sysinfo.nandgeom->pages_per_block) { page = 0; block++; blkchk = TRUE; } } } return TRUE; }
/*********************************************************************** * * Function: stream_flash_read * * Purpose: Read data from FLASH * * Processing: * See function. * * Parameters: * fdata : Pointer to file data to fill * bytes : BYtes to read * * Outputs: None * * Returns: Number of bytes read * * Notes: None * **********************************************************************/ static INT_32 stream_flash_read(UNS_8 *data, int bytes) { UNS_32 sector; INT_32 btoread, bread = 0; /* Limit read size */ if (bytes > bytestoread) { bytes = bytestoread; } while (bytes > 0) { /* Is a bad block check needed? */ if (checkblk == TRUE) { /* Start of block, read bad block marker */ if (flash_is_bad_block(curblock) == FALSE) { /* Block is good */ checkblk = FALSE; } else { /* Block is bad, go to next block */ curblock++; } } /* Read more data if needed */ if (checkblk == FALSE) { /* Is a data read needed? */ if (lefttoread == 0) { /* Out of pages in the block? */ if (curpage >= sysinfo.nandgeom->pages_per_block) { /* Reset block and page marker */ curblock++; curpage = 0; checkblk = TRUE; } else { /* Time to read in a new sector */ sector = conv_to_sector(curblock, curpage); if (flash_read_sector(sector, secdat, NULL) <= 0) term_dat_out((UNS_8 *) "Read error: data may be corrupt\r\n"); lefttoread = sysinfo.nandgeom->data_bytes_per_page; cindex = 0; curpage++; } } /* Move data into user buffer */ btoread = lefttoread; if (btoread > bytes) { btoread = bytes; } while (btoread > 0) { bread++; *data = secdat [cindex]; cindex++; btoread--; lefttoread--; bytes--; } } } return bread; }
/*********************************************************************** * * Function: cfg_load * * Purpose: Load an S1L configuariton * * Processing: * See function. * * Parameters: * pCfg : Pointer to config structure to populate * * Outputs: None * * Returns: FALSE if the structure wasn't loaded, otherwise TRUE * * Notes: None * **********************************************************************/ BOOL_32 cfg_load(S1L_CFG_T *pCfg) { UNS_32 sector, blk = adjusted_num_blocks - 1; UNS_32 cfg_check_data = 0; UNS_32 pg_sz = sysConfig.nandgeom->data_bytes_per_page; if (cfg_size_check() == FALSE) return FALSE; while (blk < adjusted_num_blocks) { /* If bad block skip-it */ if (flash_is_bad_block(blk) != TRUE) { INT_32 offset = 0, page = 0; INT_32 sz_bcfg = sizeof(s1l_board_cfg); INT_32 sz_cfg = sizeof(*pCfg); UNS_8 *ptr_cfg = (UNS_8 *)pCfg; UNS_8 *ptr_bcfg = (UNS_8 *)&s1l_board_cfg; /* Read first page of sector */ sector = conv_to_sector(blk, page); if(flash_read_sector(sector, secdat, NULL) < 0) return FALSE; /* Check for the signature */ memcpy(&cfg_check_data, secdat, sizeof(cfg_check_data)); offset += sizeof(cfg_check_data); if (cfg_check_data != CHECK_KEY) return FALSE; page ++; /* Copy structure by structure */ while (sz_bcfg > 0 || sz_cfg > 0) { /* Copy S1l Configuration structure */ if (sz_cfg > 0) { UNS_32 tmp = sz_cfg > (pg_sz - offset) ? pg_sz - offset : sz_cfg; memcpy(ptr_cfg, (UNS_8 *)secdat + offset, tmp); sz_cfg -= tmp; offset += tmp; ptr_cfg += tmp; } /* Copy Board configuration structure */ if (sz_bcfg > 0 && offset < pg_sz) { UNS_32 tmp = sz_bcfg > (pg_sz - offset) ? pg_sz - offset : sz_bcfg; memcpy(ptr_bcfg, (UNS_8 *)secdat + offset, tmp); sz_bcfg -= tmp; offset += tmp; ptr_bcfg += tmp; } if (sz_bcfg > 0 || sz_cfg > 0) { sector = conv_to_sector(blk, page); if(flash_read_sector(sector, secdat, NULL) < 0) return FALSE; page ++; offset = 0; } } #ifdef ENABLE_CKLSWITCHING clock_adjust(); #endif return TRUE; } else { adjusted_num_blocks ++; // sysinfo.sysrtcfg.bl_num_blks = adjusted_num_blocks; } blk ++; } return FALSE; }