BOOL WriteRawImageToBootMedia(DWORD dwImageStart, DWORD dwImageLength, DWORD dwLaunchAddr) { DWORD dwBlock = 0; DWORD dwNumBlocks = 0; LPBYTE pbBuffer; SectorInfo si; //unsigned int sectorchk; unsigned int sectorcnt = 0; unsigned int areachange = 0; OALMSG(OAL_FUNC, (TEXT("+WriteRawImageToBootMedia\r\n"))); if ( !g_bBootMediaExist ) { OALMSG(OAL_ERROR, (TEXT("ERROR: WriteRawImageToBootMedia: device doesn't exist.\r\n"))); return(FALSE); } if(dwLaunchAddr==0x10) { dwBlock = LOGO_BLOCK; //dwImageLength = UPLDR_RAM_IMAGE_SIZE; g_ImageType=IMAGE_TYPE_RAWBIN; }else{ if (g_ImageType == IMAGE_TYPE_LOADER) { dwBlock = EBOOT_BLOCK; if ( !VALID_TOC(g_pTOC) ) { OALMSG(OAL_WARN, (TEXT("WARN: WriteRawImageToBootMedia: INVALID_TOC\r\n"))); if ( !TOC_Init(g_dwTocEntry, g_ImageType, dwImageStart, dwImageLength, dwLaunchAddr) ) { OALMSG(OAL_ERROR, (TEXT("ERROR: INVALID_TOC\r\n"))); return(FALSE); } } } else if (g_ImageType == IMAGE_TYPE_STEPLDR) { dwBlock = STEPLDR_BLOCK; dwImageStart += dwLaunchAddr; //dwImageLength = 0x2050; //step loader can support 8k bytes. //dwImageLength = STEPLDR_RAM_IMAGE_SIZE; //step loader can support 4k bytes only. NO SuperIPL case is 16K....... 3 Block } else if (g_ImageType == IMAGE_TYPE_DIONB0) { dwBlock = DIONB0_BLOCK; dwImageStart += dwLaunchAddr; dwImageLength -= (dwImageLength / (g_FlashInfo.wDataBytesPerSector + 8))*8; } else if (g_ImageType == IMAGE_TYPE_UPLDR) { dwBlock = UPLDR_BLOCK; dwImageStart += dwLaunchAddr; dwImageLength = UPLDR_RAM_IMAGE_SIZE; //step loader can support 4k bytes only. NO SuperIPL case is 16K....... 3 Block } else if (g_ImageType == IMAGE_TYPE_FLASHBIN) { dwBlock = FLASHBIN_BLOCK; // dwImageStart += dwLaunchAddr; // dwImageLength = dwImageLength; //step loader can support 4k bytes only. NO SuperIPL case is 16K....... 3 Block } } if(dwLaunchAddr==0x10) pbBuffer=(LPBYTE)dwImageStart; else pbBuffer = OEMMapMemAddr(dwImageStart, dwImageStart); // Compute number of blocks. dwNumBlocks = (dwImageLength / (g_FlashInfo.wDataBytesPerSector*g_FlashInfo.wSectorsPerBlock)) + (dwImageLength%(g_FlashInfo.wDataBytesPerSector*g_FlashInfo.wSectorsPerBlock) ? 1: 0); OALMSG(TRUE, (TEXT("dwImageLength = 0x%x \r\n"), dwImageLength)); OALMSG(TRUE, (TEXT("dwNumBlocks = 0x%x \r\n"), dwNumBlocks)); while (dwNumBlocks--) { // If the block is marked bad, skip to next block. Note that the assumption in our error checking // is that any truely bad block will be marked either by the factory during production or will be marked // during the erase and write verification phases. If anything other than a bad block fails ECC correction // in this routine, it's fatal. OALMSG(TRUE, (TEXT("dwBlock(0x%x) X "), dwBlock)); OALMSG(TRUE, (TEXT("g_FlashInfo.wSectorsPerBlock(0x%x)"), g_FlashInfo.wSectorsPerBlock)); OALMSG(TRUE, (TEXT(" = 0x%x \r\n"), dwBlock*g_FlashInfo.wSectorsPerBlock)); if (!FMD_EraseBlock(dwBlock)) { OALMSG(TRUE, (TEXT("WriteData: failed to erase block (0x%x).\r\n"), dwBlock)); ++dwBlock; ++dwNumBlocks; // Compensate for fact that we didn't write any blocks. continue; } // FMD_GetBlockStatus(dwBlock); if ((FMD_GetBlockStatus(dwBlock) & (BLOCK_STATUS_BAD | BLOCK_STATUS_RESERVED))&&dwBlock!=0) { OALMSG(TRUE, (TEXT("FMD_GetBlockStatus Error \r\n"))); ++dwBlock; ++dwNumBlocks; // Compensate for fact that we didn't write any blocks. continue; } //FMD_ReadSector(dwBlock*g_FlashInfo.wSectorsPerBlock, NULL, &si, 1); if (!FMD_ReadSector(dwBlock*g_FlashInfo.wSectorsPerBlock, NULL, &si, 1)) { OALMSG(TRUE, (TEXT("FMD_ReadSector : Failed to get block(0x%x)'s sector info.\r\n"), dwBlock)); ++dwBlock; ++dwNumBlocks; // Compensate for fact that we didn't write any blocks. continue; } // Stepldr & Eboot image in nand flash // block mark as BLOCK_STATUS_RESERVED & BLOCK_STATUS_READONLY & BLOCK_STATUS_BAD if ((si.bBadBlock == 0x0) && (si.bOEMReserved !=0xfc )&&dwBlock!=0) { OALMSG(TRUE, (TEXT("si.bBadBlock failed, si.bOEMReserved %x,si.bBadBlock %x.\r\n"),si.bOEMReserved, si.bBadBlock)); ++dwBlock; ++dwNumBlocks; // Compensate for fact that we didn't write any blocks. continue; } if (!ReadBlock(dwBlock, NULL, g_pSectorInfoBuf)) { OALMSG(TRUE, (TEXT("WriteData: failed to read block (0x%x).\r\n"), dwBlock)); return(FALSE); } if (g_ImageType == IMAGE_TYPE_DIONB0) { for ( int iSector = 0; iSector < g_FlashInfo.wSectorsPerBlock; iSector ++ ) { if (!WritePage(dwBlock*g_FlashInfo.wSectorsPerBlock + iSector, pbBuffer, (PSectorInfo)(pbBuffer+g_FlashInfo.wDataBytesPerSector) )) { OALMSG(TRUE, (TEXT("WriteData: failed to write block (0x%x).\r\n"), dwBlock)); return(FALSE); } pbBuffer += (g_FlashInfo.wDataBytesPerSector + 8); } ++dwBlock; } else if (g_ImageType == IMAGE_TYPE_FLASHBIN) { for ( int iSector = 0; iSector < g_FlashInfo.wSectorsPerBlock; iSector ++ ) { //RETAILMSG(1, (TEXT("WriteData: (0x%x)(0x%x,0x%x,0x%x).\r\n"), dwBlock*g_FlashInfo.wSectorsPerBlock + iSector, g_pSectorInfoBuf->dwReserved1, g_pSectorInfoBuf->bOEMReserved, g_pSectorInfoBuf->wReserved2)); if (!WritePage(dwBlock*g_FlashInfo.wSectorsPerBlock + iSector, pbBuffer, (PSectorInfo)(pbBuffer+g_FlashInfo.wDataBytesPerSector) )) { OALMSG(TRUE, (TEXT("WriteData: failed to write block (0x%x).\r\n"), dwBlock)); #ifdef IROMBOOT FMD_EraseBlock(dwBlock); // this block is actually considered to bad block. // because it may be erased initial bad block information. si.bOEMReserved = 0xff; si.bBadBlock = BADBLOCKMARK; si.dwReserved1 = 0xffffffff; si.wReserved2 = 0xffff; FMD_WriteSector(BLOCK_TO_SECTOR(dwBlock), NULL, &si, 1); pbBuffer -= (g_FlashInfo.wDataBytesPerSector + 8)*iSector; iSector = 0; break; #else return(FALSE); #endif // !IROMBOOT } pbBuffer += (g_FlashInfo.wDataBytesPerSector + 8); } ++dwBlock; } else { OALMSG(TRUE, (TEXT(" Write Reserved Area \n"))); if (!WriteBlock(dwBlock, pbBuffer, g_pSectorInfoBuf)) { OALMSG(TRUE, (TEXT("WriteData: failed to write block (0x%x).\r\n"), dwBlock)); return(FALSE); } ++dwBlock; OALMSG(TRUE, (TEXT("pbBuffer + %x .\r\n"), SECTOR_SIZE/*SECTORS_PER_PAGE*/*PAGES_PER_BLOCK)); #ifdef IROMBOOT pbBuffer += (SECTOR_SIZE/*SECTORS_PER_PAGE*/*PAGES_PER_BLOCK); #else pbBuffer += 0x4000; #endif // !IROMBOOT } } if (g_ImageType == IMAGE_TYPE_LOADER) { g_pTOC->id[0].dwLoadAddress = dwImageStart; g_pTOC->id[0].dwJumpAddress = 0; g_pTOC->id[0].dwTtlSectors = FILE_TO_SECTOR_SIZE(dwImageLength); g_pTOC->id[0].sgList[0].dwSector = BLOCK_TO_SECTOR(EBOOT_BLOCK); g_pTOC->id[0].sgList[0].dwLength = g_pTOC->id[0].dwTtlSectors; } OALMSG(OAL_FUNC, (TEXT("_WriteRawImageToBootMedia\r\n"))); return TRUE; }
BOOL WriteFlashNK(UINT32 address, UINT32 size) { BOOL rc = FALSE; HANDLE hFMD; FlashInfo flashInfo; SectorInfo sectorInfo; BOOL ok = FALSE; BLOCK_ID block; //ROMHDR *pTOC; UINT32 *pInfo, count, sector; UINT32 blockSize, sectorSize, sectorsPerBlock; UINT8 *pData; OALMSG(OAL_INFO, (L"OEMWriteFlash: Writing NK image to flash\r\n")); // We need to know sector/block size if ((hFMD = FMD_Init(NULL, NULL, NULL)) == NULL) { OALMSG(OAL_ERROR, (L"ERROR: OEMWriteFlash: " L"FMD_Init call failed\r\n" )); goto cleanUp; } // Get flash info if (!FMD_GetInfo(&flashInfo)) { OALMSG(OAL_ERROR, (L"ERROR: EBOOT!OEMWriteFlash: " L"FMD_GetInfo call failed!\r\n" )); FMD_Deinit(hFMD); goto cleanUp; } // We don't need access to FMD library FMD_Deinit(hFMD); OALMSG(OAL_INFO, (L"OEMWriteFlash: " L"Flash has %d blocks, %d bytes/block, %d sectors/block\r\n", flashInfo.dwNumBlocks, flashInfo.dwBytesPerBlock, flashInfo.wSectorsPerBlock )); // Make block & sector size ready blockSize = flashInfo.dwBytesPerBlock; sectorSize = flashInfo.wDataBytesPerSector; sectorsPerBlock = flashInfo.wSectorsPerBlock; // Get data location pData = OEMMapMemAddr(address, address); // Verify that we get CE image. pInfo = (UINT32*)(pData + ROM_SIGNATURE_OFFSET); if (*pInfo++ != ROM_SIGNATURE) { OALMSG(OAL_ERROR, (L"ERROR: OEMWriteFlash: " L"Image Signature not found\r\n" )); goto cleanUp; } pInfo++; // Skip reserved blocks block = 0; while (block < flashInfo.dwNumBlocks) { if ((FMD_GetBlockStatus(block) & BLOCK_STATUS_BAD) != 0) { OALMSG(OAL_WARN, (L"WARN: EBOOT!OEMWriteFlash: " L"Skip bad block %d\r\n", block )); block++; continue; } if ((FMD_GetBlockStatus(block) & BLOCK_STATUS_RESERVED) == 0) break; block++; } OALMSG(OAL_INFO, (L"OEMWriteFlash: " L"NK image starts at block %d\r\n", block )); // Write image count = 0; while (count < size && block < flashInfo.dwNumBlocks) { // If block is bad, we have to offset it if ((FMD_GetBlockStatus(block) & BLOCK_STATUS_BAD) != 0) { block++; OALMSG(OAL_WARN, (L"WARN: EBOOT!OEMWriteFlash: " L"Skip bad block %d\r\n", block )); continue; } // Erase block if (!EraseBlock(block)) { FMD_SetBlockStatus(block, BLOCK_STATUS_BAD); block++; OALMSG(OAL_WARN, (L"WARN: EBOOT!OEMWriteFlash: " L"Block %d erase failed, mark block as bad\r\n", block )); continue; } // Now write sectors sector = 0; while (sector < sectorsPerBlock && count < size) { // Prepare sector info memset(§orInfo, 0xFF, sizeof(sectorInfo)); sectorInfo.dwReserved1 = 0; sectorInfo.wReserved2 = 0; // Write sector if (!(ok = WriteSector( block * sectorsPerBlock + sector, pData + count, §orInfo ))) break; // Move to next sector count += sectorSize; sector++; } // When sector write failed, mark block as bad and move back if (!ok) { OALMSG(OAL_WARN, (L"WARN: EBOOT!OEMWriteFlash: " L"Block %d sector %d write failed, mark block as bad\r\n", block, sector )); // First move back count -= sector * flashInfo.wDataBytesPerSector; // Mark block as bad FMD_SetBlockStatus(block, BLOCK_STATUS_BAD); } // We are done with block block++; } // Erase rest of media while (block < flashInfo.dwNumBlocks) { // If block is bad, we have to offset it if ((FMD_GetBlockStatus(block) & BLOCK_STATUS_BAD) != 0) { block++; OALMSG(OAL_WARN, (L"WARN: EBOOT!OEMWriteFlash: " L"Skip bad block %d\r\n", block )); continue; } // When erase failed, mark block as bad and skip it if (!EraseBlock(block)) { FMD_SetBlockStatus(block, BLOCK_STATUS_BAD); block++; OALMSG(OAL_WARN, (L"WARN: EBOOT!OEMWriteFlash: " L"Block %d erase failed, mark block as bad\r\n", block )); continue; } // Move to next block block++; } // Close FMD driver FMD_Deinit(hFMD); hFMD = NULL; OALMSG(OAL_INFO, (L"OEMWriteFlash: NK written\r\n")); // Done rc = TRUE; cleanUp: if (hFMD != NULL) FMD_Deinit(hFMD); return rc; }
//------------------------------------------------------------------------------ // // Function: DFT_IOControl // // This function sends a command to a device. // BOOL DFT_IOControl( DWORD context, DWORD dwCode, BYTE *pInBuffer, DWORD inSize, BYTE *pOutBuffer, DWORD outSize, DWORD *pOutSize) { NANDTEST_CONTEXT *pContext = (NANDTEST_CONTEXT *)context; HANDLE hFMD; PCI_REG_INFO regInfo; FlashInfo flashInfo; DWORD sector,block; BOOL rc=FALSE; UCHAR p_goodata[SECTOR_SIZE*2]; UNREFERENCED_PARAMETER(pOutSize); DEBUGMSG(ZONE_FUNCTION, (L"+DFT_IOControl(0x%08x, 0x%08x, 0x%08x, %d, 0x%08x, %d, 0x%08x)\r\n", context, dwCode, pInBuffer, inSize, pOutBuffer, outSize, pOutSize)); regInfo.MemBase.Reg[0] = OMAP_GPMC_REGS_PA; regInfo.MemLen.Reg[0] = 0x00001000; regInfo.MemBase.Reg[1] = BSP_NAND_REGS_PA; regInfo.MemLen.Reg[1] = 0x00001000; hFMD = FMD_Init(NULL, ®Info, NULL); if (hFMD == NULL) { DEBUGMSG(ZONE_ERROR, (L"ERROR: FMD_Init call failed!\r\n")); goto cleanUp; } switch (dwCode) { case NAND_SET_SECTOR: // Checking parameter if (pInBuffer == NULL || inSize < sizeof(DWORD)) { DEBUGMSG(ZONE_ERROR, (L"+DFT_IOControl(%d): ERROR - invalid parameters\r\n", dwCode)); goto cleanUp; } // Get flash info if (!FMD_GetInfo(&flashInfo)) { DEBUGMSG(ZONE_ERROR, (L"ERROR: FMD_GetInfo call failed!\r\n")); goto cleanUp; } pContext->test_sector = *(DWORD*)pInBuffer; block = pContext->test_sector / flashInfo.wSectorsPerBlock; sector = pContext->test_sector % flashInfo.wSectorsPerBlock; DEBUGMSG(ZONE_ERROR, (L"Test section info: block=%d sector=%d !\r\n", block, sector)); if(block >= flashInfo.dwNumBlocks) { DEBUGMSG(ZONE_ERROR, (L"ERROR: invalid sector!\r\n")); goto cleanUp; } if(FMD_GetBlockStatus(block) & (BLOCK_STATUS_BAD |BLOCK_STATUS_RESERVED |BLOCK_STATUS_READONLY)) { DEBUGMSG(ZONE_ERROR, (L"ERROR: invalid sector status:%x!\r\n", FMD_GetBlockStatus(block) )); goto cleanUp; } rc = TRUE; break; case NAND_ECC_CORRECTION: /* Expecting 2 * 2K data, first 2K is good data, second 2K is bad data needs correction */ // Checking parameter if (pInBuffer == NULL || inSize != SECTOR_SIZE *2) { DEBUGMSG(ZONE_ERROR, (L"+DFT_IOControl(%d): ERROR - invalid in parameters\r\n", dwCode)); goto cleanUp; } memcpy(p_goodata, pInBuffer, SECTOR_SIZE * 2); if (pOutBuffer == NULL || outSize != SECTOR_SIZE) { DEBUGMSG(ZONE_ERROR, (L"+DFT_IOControl(%d): ERROR - invalid out parameters\r\n", dwCode)); goto cleanUp; } /* Call ECC test routine */ rc = nand_ecc_test(context, p_goodata, pOutBuffer); break; default: break; } cleanUp: if (hFMD != NULL) FMD_Deinit(hFMD); return rc; }
BOOL BLReserveBootBlocks( BOOT_CFG *pBootCfg ) { #ifndef BSP_NO_NAND_IN_SDBOOT BOOL rc = FALSE; HANDLE hFMD; PCI_REG_INFO regInfo; FlashInfo flashInfo; UINT32 size; BLOCK_ID firstblock, lastblock; UINT32 status; UNREFERENCED_PARAMETER(pBootCfg); // Automatically mark the bootloader blocks as read-only/reserved regInfo.MemBase.Reg[0] = g_ulFlashBase; hFMD = FMD_Init(NULL, ®Info, NULL); if (hFMD == NULL) { OALMSG(OAL_ERROR, (L"ERROR: FMD_Init call failed!\r\n")); goto cleanUp; } // Get flash info if (!FMD_GetInfo(&flashInfo)) { OALMSG(OAL_ERROR, (L"ERROR: FMD_GetInfo call failed!\r\n")); goto cleanUp; } // Loop thru the bootloader blocks to ensure they are marked reserved firstblock = 0; size = IMAGE_BOOTLOADER_NAND_SIZE; lastblock = ((size -1) / flashInfo.dwBytesPerBlock) + 1; OALLog(L"Checking bootloader blocks are marked as reserved (Num = %d)\r\n", lastblock-firstblock); while (firstblock < lastblock) { // If block is bad, we have to offset it status = FMD_GetBlockStatus(firstblock); // Skip bad blocks if ((status & BLOCK_STATUS_BAD) != 0) { OALLog(L" Skip bad block %d\r\n", firstblock); // blocks marked bad would not have been written either, so don't include this // in the count of blocks that are reserved. firstblock++; lastblock++; continue; } // Skip already reserved blocks if ((status & BLOCK_STATUS_RESERVED) != 0) { firstblock++; continue; } // Mark block as read-only & reserved if (!FMD_SetBlockStatus(firstblock, BLOCK_STATUS_READONLY|BLOCK_STATUS_RESERVED)) { OALLog(L" Oops, can't mark block %d - as reserved\r\n", firstblock); } firstblock++; OALLog(L"."); } // Done rc = TRUE; OALLog(L"\r\n"); cleanUp: if (hFMD != NULL) FMD_Deinit(hFMD); return rc; #else UNREFERENCED_PARAMETER(pBootCfg); // Nothing to do... return TRUE; #endif }
static UINT32 ReadFlashNK() { UINT32 rc = BL_ERROR; HANDLE hFMD = NULL; FlashInfo flashInfo; ROMHDR *pTOC; UINT32 offset, size, toc; UINT32 blockSize, sectorSize, sectorsPerBlock; SectorInfo sectorInfo; SECTOR_ADDR sector; BLOCK_ID block; UINT8 *pImage; // Check if there is a valid image OALMSG(OAL_INFO, (L"\r\nLoad NK image from flash memory\r\n")); // Open FMD to access NAND hFMD = FMD_Init(NULL, NULL, NULL); if (hFMD == NULL) { OALMSG(OAL_ERROR, (L"ERROR: BLFlashDownload: " L"FMD_Init call failed\r\n" )); goto cleanUp; } // Get flash info if (!FMD_GetInfo(&flashInfo)) { OALMSG(OAL_ERROR, (L"ERROR: BLFlashDownload: " L"FMD_GetInfo call failed\r\n" )); goto cleanUp; } // Make block & sector size ready blockSize = flashInfo.dwBytesPerBlock; sectorSize = flashInfo.wDataBytesPerSector; sectorsPerBlock = flashInfo.wSectorsPerBlock; // Skip reserved blocks block = 0; while (block < flashInfo.dwNumBlocks) { if ((FMD_GetBlockStatus(block) & BLOCK_STATUS_BAD) != 0) { OALMSG(OAL_WARN, (L"WARN: EBOOT!FMD_GetBlockStatus: " L"Skip bad block %d\r\n", block )); block++; continue; } if ((FMD_GetBlockStatus(block) & BLOCK_STATUS_RESERVED) == 0) break; block++; } // Set address where to place image pImage = (UINT8*)IMAGE_WINCE_CODE_PA; size = IMAGE_WINCE_CODE_SIZE; // Read image to memory offset = 0; toc = 0; pTOC = NULL; while (offset < size && block < flashInfo.dwNumBlocks) { // Skip bad blocks if ((FMD_GetBlockStatus(block) & BLOCK_STATUS_BAD) != 0) { block++; sector += flashInfo.wSectorsPerBlock; continue; } // Read sectors in block sector = 0; while (sector < sectorsPerBlock && offset < size) { // When block read fail, there isn't what we can do more RETAILMSG(1, (TEXT("0x%x 0x%x \r\n"), block * sectorsPerBlock + sector, pImage + offset)); if (!FMD_ReadSector( block * sectorsPerBlock + sector, pImage + offset, §orInfo, 1 )) { OALMSG(OAL_ERROR, (L"\r\nERROR: BLFlashDownload: " L"Failed read sector %d from flash\r\n", sector )); goto cleanUp; } // Move to next sector sector++; offset += sectorSize; } // Move to next block block++; } g_pTOC->id[g_dwTocEntry].dwJumpAddress = IMAGE_WINCE_CODE_PA; rc = BL_JUMP; cleanUp: return rc; }
BOOL BLReadBootCfg( BOOT_CFG *pBootCfg ) { BOOL rc = FALSE; #ifndef BSP_NO_NAND_IN_SDBOOT HANDLE hFMD; PCI_REG_INFO regInfo; FlashInfo flashInfo; SectorInfo sectorInfo; SECTOR_ADDR sector; BLOCK_ID block; UINT32 count, offset; UINT8 buffer[2048]; // EBOOT configuration is placed in last sector of EBOOT image regInfo.MemBase.Reg[0] = g_ulFlashBase; hFMD = FMD_Init(NULL, ®Info, NULL); if (hFMD == NULL) { OALMSG(OAL_ERROR, (L"ERROR: FMD_Init call failed!\r\n")); goto cleanUp; } // Get flash info if (!FMD_GetInfo(&flashInfo)) { OALMSG(OAL_ERROR, (L"ERROR: FMD_GetInfo call failed!\r\n")); goto cleanUp; } // We can support only flash with sector size < 2048 bytes if (flashInfo.wDataBytesPerSector > sizeof(buffer)) { OALMSG(OAL_ERROR, (L"ERROR: " L"Flash sector size %d bytes bigger than supported %d bytes\r\n", flashInfo.wDataBytesPerSector, sizeof(buffer) )); goto cleanUp; } // Configuration is located in last sector of EBOOT image offset = IMAGE_XLDR_BOOTSEC_NAND_SIZE + IMAGE_EBOOT_BOOTSEC_NAND_SIZE; // Start from beginning block = 0; sector = 0; // Skip X-Loader & EBOOT code & bad blocks // Note that we also check the last eboot block in order to ensure it is good count = 0; while ((count < offset) && (block < flashInfo.dwNumBlocks)) { if ((FMD_GetBlockStatus(block) & BLOCK_STATUS_BAD) == 0) { count += flashInfo.dwBytesPerBlock; } block++; } // We've incremented past the last eboot block in order to check it too // Back up now, the previous block is the last one containing eboot and is good block--; // Compute sector within the block where config lies sector = block * flashInfo.wSectorsPerBlock; sector += flashInfo.wSectorsPerBlock - 1; // Read sector to buffer if (!FMD_ReadSector(sector, buffer, §orInfo, 1)) { OALMSG(OAL_ERROR, (L"ERROR: EBOOT!BLReadBootCfg: " L"Flash sector %d read failed\r\n", sector )); goto cleanUp; } // Copy data to BOOT_CFG structure memcpy(pBootCfg, buffer, sizeof(BOOT_CFG)); // Done rc = TRUE; cleanUp: if (hFMD != NULL) FMD_Deinit(hFMD); #else UNREFERENCED_PARAMETER(pBootCfg); #endif return rc; }
BOOL BLWriteBootCfg( BOOT_CFG *pBootCfg ) { BOOL rc = FALSE; #ifndef BSP_NO_NAND_IN_SDBOOT HANDLE hFMD; PCI_REG_INFO regInfo; FlashInfo flashInfo; SectorInfo sectorInfo; SECTOR_ADDR sector; BLOCK_ID block; UINT32 count, offset, length; UINT8 buffer[2048]; UINT8 *pEBOOT; // EBOOT configuration is placed in last sector of image regInfo.MemBase.Reg[0] = g_ulFlashBase; hFMD = FMD_Init(NULL, ®Info, NULL); if (hFMD == NULL) { OALMSG(OAL_ERROR, (L"ERROR: FMD_Init call failed!\r\n")); goto cleanUp; } // Get flash info if (!FMD_GetInfo(&flashInfo)) { OALMSG(OAL_ERROR, (L"ERROR: FMD_GetInfo call failed!\r\n")); goto cleanUp; } // We can support only flash with sector size which fit to our buffer if (flashInfo.wDataBytesPerSector > sizeof(buffer)) { OALMSG(OAL_ERROR, (L"ERROR: " L"Flash sector size %d bytes bigger that supported %d bytes\r\n", flashInfo.wDataBytesPerSector, sizeof(buffer) )); goto cleanUp; } // Configuration is located in last sector of last EBOOT block offset = IMAGE_XLDR_BOOTSEC_NAND_SIZE + IMAGE_EBOOT_BOOTSEC_NAND_SIZE; // Skip X-Loader & EBOOT code & bad blocks // Note that we also check the last eboot block in order to ensure it is good block = 0; count = 0; while ((count < offset) && (block < flashInfo.dwNumBlocks)) { if ((FMD_GetBlockStatus(block) & BLOCK_STATUS_BAD) == 0) { count += flashInfo.dwBytesPerBlock; } block++; } // We've incremented past the last eboot block in order to check it too // Back up now, the previous block is the last one containing eboot and is good block--; // Need to copy off the block contents to RAM (minus the config sector) pEBOOT = (UINT8*)IMAGE_WINCE_CODE_CA; length = flashInfo.dwBytesPerBlock - flashInfo.wDataBytesPerSector; memset((VOID*)pEBOOT, 0xFF, flashInfo.dwBytesPerBlock); sector = block * flashInfo.wSectorsPerBlock; offset = 0; while (offset < length) { // When block read fail, there isn't what we can do more if (!FMD_ReadSector(sector, pEBOOT + offset, §orInfo, 1)) { OALMSG(OAL_ERROR, (L"\r\nERROR: EBOOT!BLWriteBootCfg: " L"Failed read sector %d from flash\r\n", sector )); goto cleanUp; } // Move to next sector sector++; offset += flashInfo.wDataBytesPerSector; } // Copy the config info into last sector of saved block in RAM memcpy(pEBOOT + offset, pBootCfg, sizeof(BOOT_CFG)); // Erase block if (!FMD_EraseBlock(block)) { OALMSG(OAL_ERROR, (L"ERROR: EBOOT!BLWriteBootCfg: " L"Flash block %d erase failed\r\n", block )); goto cleanUp; } // Write contents of the save block + config sector back to flash pEBOOT = (UINT8*)IMAGE_WINCE_CODE_CA; length = flashInfo.dwBytesPerBlock; sector = block * flashInfo.wSectorsPerBlock; offset = 0; while (offset < length) { // Prepare sector info memset(§orInfo, 0xFF, sizeof(sectorInfo)); sectorInfo.bOEMReserved &= ~(OEM_BLOCK_READONLY|OEM_BLOCK_RESERVED); sectorInfo.dwReserved1 = 0; sectorInfo.wReserved2 = 0; // Write sector if (!FMD_WriteSector(sector, pEBOOT + offset, §orInfo, 1)) { OALMSG(OAL_ERROR, (L"ERROR: EBOOT!BLWriteBootCfg: " L"Flash sector %d write failed\r\n", sector )); goto cleanUp; } // Move to next sector sector++; offset += flashInfo.wDataBytesPerSector; } // Done rc = TRUE; cleanUp: if (hFMD != NULL) FMD_Deinit(hFMD); #else UNREFERENCED_PARAMETER(pBootCfg); #endif return rc; }
VOID ReserveBlock(OAL_BLMENU_ITEM *pMenu) { WCHAR key; HANDLE hFMD = NULL; PCI_REG_INFO regInfo; FlashInfo flashInfo; BLOCK_ID firstblock, lastblock=0; WCHAR szInputLine[16]; UINT32 status; UNREFERENCED_PARAMETER(pMenu); OALLog(L"\r\n First Block Number: "); if (OALBLMenuReadLine(szInputLine, dimof(szInputLine)) == 0) { goto cleanUp; } // Get block number firstblock = OALStringToUINT32(szInputLine); OALLog(L"\r\n Last Block Number: "); if (OALBLMenuReadLine(szInputLine, dimof(szInputLine)) != 0) { // Get block number lastblock = OALStringToUINT32(szInputLine); } if (lastblock < firstblock) { lastblock=firstblock; } // Open FMD regInfo.MemBase.Reg[0] = g_ulFlashBase; hFMD = FMD_Init(NULL, ®Info, NULL); if (hFMD == NULL) { OALLog(L" Oops, can't open FMD driver\r\n"); goto cleanUp; } if (!FMD_GetInfo(&flashInfo)) { OALLog(L" Oops, can't get flash geometry info\r\n"); goto cleanUp; } if (lastblock >= flashInfo.dwNumBlocks) { OALLog(L" Oops, too big block number\r\n"); goto cleanUp; } OALLog(L" Do you want mark as reserved block %d-%d [-/y]? ", firstblock, lastblock); // Get key key = OALBLMenuReadKey(TRUE); OALLog(L"%c\r\n", key); // Depending on result if (key != L'y' && key != L'Y') { goto cleanUp; } while (firstblock<=lastblock) { // If block is bad, we have to offset it status = FMD_GetBlockStatus(firstblock); // Skip bad blocks if ((status & BLOCK_STATUS_BAD) != 0) { OALLog(L" Skip bad block %d\r\n", firstblock); // NOTE - this will cause a smaller number of blocks to actually be reserved... firstblock++; continue; } // Skip already reserved blocks if ((status & BLOCK_STATUS_RESERVED) != 0) { OALLog(L" Skip reserved block %d\r\n", firstblock); firstblock++; continue; } // Mark block as read-only & reserved if (!FMD_SetBlockStatus(firstblock, BLOCK_STATUS_READONLY|BLOCK_STATUS_RESERVED)) { OALLog(L" Oops, can't mark block %d - as reserved\r\n", firstblock); } firstblock++; OALLog(L"."); } OALLog(L" Done\r\n"); cleanUp: if (hFMD != NULL) FMD_Deinit(hFMD); return; }
VOID EraseFlash(OAL_BLMENU_ITEM *pMenu) { WCHAR key; HANDLE hFMD = NULL; PCI_REG_INFO regInfo; FlashInfo flashInfo; BLOCK_ID block; UINT32 status; UNREFERENCED_PARAMETER(pMenu); OALLog(L" Do you want to erase unreserved blocks [-/y]? "); // Get key key = OALBLMenuReadKey(TRUE); OALLog(L"%c\r\n", key); // Depending on result if (key != L'y' && key != L'Y') goto cleanUp; // Open FMD regInfo.MemBase.Reg[0] = g_ulFlashBase; hFMD = FMD_Init(NULL, ®Info, NULL); if (hFMD == NULL) { OALLog(L" Oops, can't open FMD driver\r\n"); goto cleanUp; } if (!FMD_GetInfo(&flashInfo)) { OALLog(L" Oops, can't get flash geometry info\r\n"); goto cleanUp; } // First offset given block = 0; while (block < flashInfo.dwNumBlocks) { // If block is bad, we have to offset it status = FMD_GetBlockStatus(block); // Skip bad blocks if ((status & BLOCK_STATUS_BAD) != 0) { OALLog(L" Skip bad block %d\r\n", block); block++; continue; } // Skip reserved blocks if ((status & BLOCK_STATUS_RESERVED) != 0) { OALLog(L" Skip reserved block %d\r\n", block); block++; continue; } // Erase block if (!FMD_EraseBlock(block)) { OALLog(L" Oops, can't erase block %d - mark as bad\r\n", block); FMD_SetBlockStatus(block, BLOCK_STATUS_BAD); } block++; } OALLog(L" Done\r\n"); // Block until a keypress OALBLMenuReadKey(TRUE); cleanUp: if (hFMD != NULL) FMD_Deinit(hFMD); return; }
VOID ShowFlashGeometry(OAL_BLMENU_ITEM *pMenu) { HANDLE hFMD; PCI_REG_INFO regInfo; FlashInfo flashInfo; LPCWSTR pszType; BLOCK_ID block; UINT32 status; UINT32 listmode=0; UNREFERENCED_PARAMETER(pMenu); regInfo.MemBase.Reg[0] = g_ulFlashBase; hFMD = FMD_Init(NULL, ®Info, NULL); if (hFMD == NULL) { OALLog(L" Oops, can't open FMD driver\r\n"); goto cleanUp; } if (!FMD_GetInfo(&flashInfo)) { OALLog(L" Oops, can't get flash geometry info\r\n"); goto cleanUp; } switch (flashInfo.flashType) { case NAND: pszType = L"NAND"; break; case NOR: pszType = L"NOR"; break; default: pszType = L"Unknown"; } OALLog(L"\r\n"); OALLog(L" Flash Type: %s\r\n", pszType); OALLog(L" Blocks: %d\r\n", flashInfo.dwNumBlocks); OALLog(L" Bytes/block: %d\r\n", flashInfo.dwBytesPerBlock); OALLog(L" Sectors/block: %d\r\n", flashInfo.wSectorsPerBlock); OALLog(L" Bytes/sector: %d\r\n", flashInfo.wDataBytesPerSector); switch (g_bootCfg.ECCtype) { case 0: pszType = L"Hamming 1bit ECC"; break; case 1: pszType = L"BCH 4bit ECC"; break; case 2: pszType = L"BCH 8bit ECC"; break; default: pszType = L"Unknown"; } OALLog(L" ECC mode: %s\r\n", pszType); // now list bad/reserved sectors // First offset given block = 0; while (block < flashInfo.dwNumBlocks) { // If block is bad, we have to offset it status = FMD_GetBlockStatus(block); // bad block if ((status & BLOCK_STATUS_BAD) != 0) { if (listmode!=1) { OALLog(L"\r\n[bad] "); listmode=1; } OALLog(L" %d", block); block++; continue; } // reserved block if ((status & BLOCK_STATUS_RESERVED) != 0) { if (listmode!=2) { OALLog(L"\r\n[reserved]"); listmode=2; } OALLog(L" %d", block); block++; continue; } block++; } OALLog(L" Done\r\n"); cleanUp: if (hFMD != NULL) { FMD_Deinit(hFMD); } return; }