Example #1
0
BOOL ReadBlock(DWORD dwBlock, LPBYTE pbBlock, PSectorInfo pSectorInfoTable)
{
    for (int iSector = 0; iSector < g_FlashInfo.wSectorsPerBlock; iSector++) {
        if (!FMD_ReadSector(dwBlock * g_FlashInfo.wSectorsPerBlock + iSector, pbBlock, pSectorInfoTable, 1))
            return FALSE;
        if (pbBlock)
            pbBlock += g_FlashInfo.wDataBytesPerSector;
        if (pSectorInfoTable)
            pSectorInfoTable++;        
    }
    return TRUE;
}
Example #2
0
static BOOL ReadBootConfig(PBOOT_CFG pBootCfg)
{
	BOOLEAN bResult = FALSE;
	unsigned char tbuf[2048];
	SectorInfo si;
	BSP_ARGS *iplpBSPArgs = ((BSP_ARGS *) IMAGE_SHARE_ARGS_UA_START);

	OALMSG(OAL_FUNC, (TEXT("+ReadBootConfig.\r\n")));

	// Valid caller buffer?
	if (!pBootCfg)
	{
		OALMSG(OAL_ERROR, (TEXT("ERROR: Bad caller buffer.\r\n")));
		goto CleanUp;
	}

	// Read settings from flash...
	//
	if ( !FMD_ReadSector(TOC_SECTOR, tbuf, &si, 1) ) {
		OALMSG(OAL_ERROR, (TEXT("TOC_Read ERROR: Unable to read TOC\r\n")));
		goto CleanUp;
	}

	memcpy(g_pTOC, tbuf, sizeof(g_TOC));
	// is it a valid TOC?
	if ( !VALID_TOC(g_pTOC) ) {
		OALMSG(OAL_ERROR, (TEXT("TOC_Read ERROR: INVALID_TOC Signature: 0x%x\r\n"), g_pTOC->dwSignature));
		goto CleanUp;
	}

	// is it an OEM block?
	if ( (si.bBadBlock != BADBLOCKMARK) || !(si.bOEMReserved & (OEM_BLOCK_RESERVED | OEM_BLOCK_READONLY)) ) {
		OALMSG(OAL_ERROR, (TEXT("TOC_Read ERROR: SectorInfo verify failed: %x %x %x %x\r\n"),
		si.dwReserved1, si.bOEMReserved, si.bBadBlock, si.wReserved2));
		goto CleanUp;
	}

	// update our boot config
	pBootCfg = &g_pTOC->BootCfg;
		iplpBSPArgs->Device_ID[0]=pBootCfg->Device_ID[0];
		iplpBSPArgs->Device_ID[1]=pBootCfg->Device_ID[1];
		iplpBSPArgs->Device_ID[2]=pBootCfg->Device_ID[2];
		iplpBSPArgs->Device_ID[3]=pBootCfg->Device_ID[3];
//OALLog(L"\r\n<><>DeviceID %x %x %x %x : ",pBootCfg->Device_ID[0],pBootCfg->Device_ID[1],pBootCfg->Device_ID[2],pBootCfg->Device_ID[3]);
	bResult = TRUE;

CleanUp:

    OALMSG(OAL_FUNC, (TEXT("-ReadBootConfig.\r\n")));
    return(bResult);

}
Example #3
0
//
// Retrieve TOC from Nand.
//
BOOL TOC_Read(void)
{
    SectorInfo si;
	unsigned char tbuf[2048];

//	EdbgOutputDebugString("+TOC_Read\r\n");

    if ( !g_bBootMediaExist ) {
        EdbgOutputDebugString("TOC_Read ERROR: no boot media\r\n");
        return FALSE;
    }

//	EdbgOutputDebugString("FMD_ReadSector\r\n");
    if ( !FMD_ReadSector(TOC_SECTOR, tbuf, &si, 1) ) {
        EdbgOutputDebugString("TOC_Read ERROR: Unable to read TOC\r\n");
        return FALSE;
    }

	memcpy(g_pTOC, tbuf, sizeof(g_TOC));
//	EdbgOutputDebugString("VALID_TOC\r\n");
    // is it a valid TOC?
    if ( !VALID_TOC(g_pTOC) ) {
        EdbgOutputDebugString("TOC_Read ERROR: INVALID_TOC Signature: 0x%x\r\n", g_pTOC->dwSignature);
        return FALSE;
    }

    // is it an OEM block?
    if ( (si.bBadBlock != BADBLOCKMARK) || !(si.bOEMReserved & (OEM_BLOCK_RESERVED | OEM_BLOCK_READONLY)) ) {
        EdbgOutputDebugString("TOC_Read ERROR: SectorInfo verify failed: %x %x %x %x\r\n",
            si.dwReserved1, si.bOEMReserved, si.bBadBlock, si.wReserved2);
        return FALSE;
    }

    // update our boot config
    g_pBootCfg = &g_pTOC->BootCfg;
	pBSPArgs->Device_ID[0]=g_pBootCfg->Device_ID[0];
	pBSPArgs->Device_ID[1]=g_pBootCfg->Device_ID[1];
	pBSPArgs->Device_ID[2]=g_pBootCfg->Device_ID[2];
	pBSPArgs->Device_ID[3]=g_pBootCfg->Device_ID[3];

    // update our index
    g_dwTocEntry = g_pBootCfg->ImageIndex;

    // cache image type
    g_ImageType = g_pTOC->id[g_dwTocEntry].dwImageType;

//	EdbgOutputDebugString("-TOC_Read\r\n");

    return TRUE;

}
Example #4
0
// Stepldr & Eboot image in nand flash
// block mark as BLOCK_STATUS_RESERVED & BLOCK_STATUS_READONLY & BLOCK_STATUS_BAD
BOOL FlashIsRealBadBlock(DWORD block)
{
    SectorInfo si;

    FMD_ReadSector(BLOCK_TO_SECTOR(block), NULL, &si, 1);
   
	RETAILMSG(1,(TEXT("=FlashIsRealBadBlock:[%d] %x %x \r\n"),block,si.bBadBlock,si.bOEMReserved));

    // 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 )&&block!=0)
        return TRUE;

    return FALSE;
}
Example #5
0
//
// Retrieve TOC from Nand.
//
BOOL TOC_Read(void)
{
    SectorInfo si;

    //EdbgOutputDebugString("TOC_Read\r\n");

    if ( !g_bBootMediaExist ) {
        EdbgOutputDebugString("TOC_Read ERROR: no boot media\r\n");
        return FALSE;
    }

    if ( !FMD_ReadSector(TOC_SECTOR, (PUCHAR)g_pTOC, &si, 1) ) {
        EdbgOutputDebugString("TOC_Read ERROR: Unable to read TOC\r\n");
        return FALSE;
    }

    // is it a valid TOC?
    if ( !VALID_TOC(g_pTOC) ) {
        EdbgOutputDebugString("TOC_Read ERROR: INVALID_TOC Signature: 0x%x\r\n", g_pTOC->dwSignature);
        return FALSE;
    }

    // is it an OEM block?
    if ( (si.bBadBlock != BADBLOCKMARK) || (si.bOEMReserved & (OEM_BLOCK_RESERVED | OEM_BLOCK_READONLY)) ) {
        EdbgOutputDebugString("TOC_Read ERROR: SectorInfo verify failed: %x %x %x %x\r\n",
            si.dwReserved1, si.bOEMReserved, si.bBadBlock, si.wReserved2);
        return FALSE;
    }

    // update our boot config
    g_pBootCfg = &g_pTOC->BootCfg;

    // update our index
    g_dwTocEntry = g_pBootCfg->ImageIndex;

    // KITL enabled?
    g_bWaitForConnect = (g_pBootCfg->ConfigFlags & CONFIG_FLAGS_KITL) ? TRUE : FALSE;

    // cache image type
    g_ImageType = g_pTOC->id[g_dwTocEntry].dwImageType;

    //EdbgOutputDebugString("-TOC_Read\r\n");

    return TRUE;

}
Example #6
0
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;
}
Example #7
0
/*
    @func   BOOL | ReadKernelRegionFromBootMedia |
            BinFS support. Reads the kernel region from Boot Media into RAM.  The kernel region is fixed up
            to run from RAM and this is done just before jumping to the kernel entry point.
    @rdesc  TRUE = Success, FALSE = Failure.
    @comm
    @xref
*/
BOOL ReadOSImageFromBootMedia()
{
    HANDLE hPart;
    SectorInfo si;
	DWORD 	chainaddr, flashaddr;
	DWORD i;

    OALMSG(OAL_FUNC, (TEXT("+ReadOSImageFromBootMedia\r\n")));

    if (!g_bBootMediaExist)
    {
	    OALMSG(OAL_ERROR, (TEXT("ERROR: WriteRawImageToBootMedia: device doesn't exist.\r\n")));
        return(FALSE);
    }

    if ( !VALID_TOC(g_pTOC) ) 
    {
	    OALMSG(OAL_ERROR, (TEXT("ERROR: ReadOSImageFromBootMedia: INVALID_TOC\r\n")));
        return(FALSE);
    }

    if ( !VALID_IMAGE_DESCRIPTOR(&g_pTOC->id[g_dwTocEntry]) ) 
    {
        OALMSG(OAL_ERROR, (TEXT("ReadOSImageFromBootMedia: ERROR_INVALID_IMAGE_DESCRIPTOR: 0x%x\r\n"),
            g_pTOC->id[g_dwTocEntry].dwSignature));
        return FALSE;
    }

    if ( !OEMVerifyMemory(g_pTOC->id[g_dwTocEntry].dwLoadAddress, sizeof(DWORD)) ||
         !OEMVerifyMemory(g_pTOC->id[g_dwTocEntry].dwJumpAddress, sizeof(DWORD)) ||
         !g_pTOC->id[g_dwTocEntry].dwTtlSectors )
    {
        OALMSG(OAL_ERROR, (TEXT("ReadOSImageFromBootMedia: ERROR_INVALID_ADDRESS: (address=0x%x, sectors=0x%x, launch address=0x%x)...\r\n"),
            g_pTOC->id[g_dwTocEntry].dwLoadAddress, g_pTOC->id[g_dwTocEntry].dwTtlSectors, g_pTOC->id[g_dwTocEntry].dwJumpAddress));
        return FALSE;
    }

    // Open the BINFS partition (it must exist).
    //
    hPart = BP_OpenPartition( NEXT_FREE_LOC,
                              USE_REMAINING_SPACE,
                              PART_BINFS,
                              TRUE,
                              PART_OPEN_EXISTING);

    if (hPart == INVALID_HANDLE_VALUE )
    {
        OALMSG(OAL_ERROR, (TEXT("ERROR: ReadOSImageFromBootMedia: Failed to open existing partition.\r\n")));
        return(FALSE);
    }

    // Set the partition file pointer to the correct offset for the kernel region.
    //
    if ( !BP_SetDataPointer(hPart, g_pTOC->id[g_dwTocEntry].dwStoreOffset) )
    {
        OALMSG(OAL_ERROR, (TEXT("ERROR: ReadOSImageFromBootMedia: Failed to set data pointer in partition (offset=0x%x).\r\n"),
            g_pTOC->id[g_dwTocEntry].dwStoreOffset));
        return(FALSE);
    }

    // Read the kernel region from the Boot Media into RAM.
    //
    if ( !BP_ReadData( hPart,
                       (LPBYTE)(g_pTOC->id[g_dwTocEntry].dwLoadAddress),
                       SECTOR_TO_FILE_SIZE(g_pTOC->id[g_dwTocEntry].dwTtlSectors)) )
    {
        OALMSG(OAL_ERROR, (TEXT("ERROR: ReadOSImageFromBootMedia: Failed to read kernel region from partition.\r\n")));
        return(FALSE);
    }

	if (!g_pTOC->chainInfo.dwLoadAddress)
	{
		chainaddr = g_pTOC->chainInfo.dwLoadAddress;
		flashaddr = g_pTOC->chainInfo.dwFlashAddress;
		for ( i = 0; i < (g_pTOC->chainInfo.dwLength); i++ )
		{
		    OALMSG(TRUE, (TEXT("chainaddr=0x%x, flashaddr=0x%x\r\n"), chainaddr, flashaddr+i));

			if ( !FMD_ReadSector(flashaddr+i, (PUCHAR)(chainaddr), &si, 1) ) {
				OALMSG(OAL_ERROR, (TEXT("TOC_Write ERROR: Unable to read/verify TOC\r\n")));
				return FALSE;
			}
			chainaddr += 512;
		}
	}
    OALMSG(OAL_FUNC, (TEXT("_ReadOSImageFromBootMedia\r\n")));
    return(TRUE);
}
Example #8
0
//
// Store TOC to Nand
// BUGBUG: only uses 1 sector for now.
//
BOOL TOC_Write(void)
{
    SectorInfo si, si2;

    EdbgOutputDebugString("+TOC_Write\r\n");

    if ( !g_bBootMediaExist ) {
        EdbgOutputDebugString("TOC_Write WARN: no boot media\r\n");
        return FALSE;
    }

    // is it a valid TOC?
    if ( !VALID_TOC(g_pTOC) ) {
        EdbgOutputDebugString("TOC_Write ERROR: INVALID_TOC Signature: 0x%x\r\n", g_pTOC->dwSignature);
       // return FALSE;
    }

    // is it a valid image descriptor?
    if ( !VALID_IMAGE_DESCRIPTOR(&g_pTOC->id[g_dwTocEntry]) ) {
        EdbgOutputDebugString("TOC_Write ERROR: INVALID_IMAGE[%u] Signature: 0x%x\r\n",
            g_dwTocEntry, g_pTOC->id[g_dwTocEntry].dwSignature);
        //return FALSE;
    }

    // in order to write a sector we must erase the entire block first
	// !! BUGBUG: must cache the TOC first so we don't trash other image descriptors !!
    if ( !FMD_EraseBlock(TOC_BLOCK) ) {
        RETAILMSG(1, (TEXT("TOC_Write ERROR: EraseBlock[%d] \r\n"), TOC_BLOCK));
        return FALSE;
    }

    // setup our metadata so filesys won't stomp us
    si.dwReserved1 = 0;
    si.bOEMReserved = OEM_BLOCK_RESERVED | OEM_BLOCK_READONLY;
    si.bBadBlock = BADBLOCKMARK;
    si.wReserved2 = 0;

    // write the sector & metadata
    if ( !FMD_WriteSector(TOC_SECTOR, (PUCHAR)&g_TOC, &si, 1) ) {
        EdbgOutputDebugString("TOC_Write ERROR: Unable to save TOC\r\n");
        return FALSE;
    }

    // read it back & verify both data & metadata
    if ( !FMD_ReadSector(TOC_SECTOR, (PUCHAR)&toc, &si2, 1) ) {
        EdbgOutputDebugString("TOC_Write ERROR: Unable to read/verify TOC\r\n");
        return FALSE;
    }

    if ( 0 != memcmp(&g_TOC, &toc, SECTOR_SIZE) ) {
        EdbgOutputDebugString("TOC_Write ERROR: TOC verify failed\r\n");
        return FALSE;
    }

    if ( 0 != memcmp(&si, &si2, sizeof(si)) ) {
        EdbgOutputDebugString("TOC_Write ERROR: SectorInfo verify failed: %x %x %x %x\r\n",
            si.dwReserved1, si.bOEMReserved, si.bBadBlock, si.wReserved2);
        return FALSE;
    }

    EdbgOutputDebugString("-TOC_Write\r\n");
    return TRUE;
}
Example #9
0
BOOL nand_ecc_test( DWORD Context,  UCHAR *pInBuffer, UCHAR *p_outbuf)
{
    NANDTEST_CONTEXT *pContext = (NANDTEST_CONTEXT *)Context;
    BOOL rc = FALSE;
    DWORD block;
    FlashInfo flashInfo;
    UCHAR outBuf[SECTOR_SIZE];
    SectorInfo secInfo;
    UCHAR *p_gooddata, *p_baddata;
	
    /* NAND ECC test
         sector: pContext.test_sector
         data: p_gooddata, p_baddata
    */
    p_gooddata = pInBuffer;
    p_baddata = pInBuffer + SECTOR_SIZE;
	
    DEBUGMSG(ZONE_FUNCTION, (L"+nand_ecc_test: p_gooddata=%x, p_baddata=%x\r\n", p_gooddata, p_baddata));

    /* Step 0: Erase block */
    if (!FMD_GetInfo(&flashInfo))
    {
        DEBUGMSG(ZONE_ERROR,  (L"ERROR: FMD_GetInfo call failed!\r\n"));
        goto cleanUp;
    }
	
    block  = pContext->test_sector / flashInfo.wSectorsPerBlock;
	
    rc = FMD_EraseBlock(block);
    if(!rc)
    {
        DEBUGMSG(ZONE_ERROR,  (L"ERROR: nand_ecc_test ERASE block(%d) failed!\r\n", block));
        goto cleanUp;
    }
    /* Step 1: flash the NAND with Good data */
    rc = FMD_WriteSector(pContext->test_sector, p_gooddata, NULL, 1); 
    if( !rc )
    {
        DEBUGMSG(ZONE_ERROR,  (L"ERROR: nand_ecc_test WRITE good data in sector(%d) failed!\r\n", pContext->test_sector));
        goto cleanUp;
    }
	
    /* Step 2: read back to see if there are errors */
    rc = FMD_ReadSector(pContext->test_sector, outBuf, NULL, 1); 

    if( !rc )
    {
        DEBUGMSG(ZONE_ERROR,  (L"ERROR: nand_ecc_test READ good data in sector(%d) failed!\r\n", pContext->test_sector));
        goto cleanUp;
    }
    if(memcmp(outBuf, p_gooddata, SECTOR_SIZE))
    {
        DEBUGMSG(ZONE_ERROR,  (L"ERROR: nand_ecc_test READ data does not match good data in sector(%d) failed!\r\n", pContext->test_sector));
        goto cleanUp;
    }

    /* Step 3: flash the NAND with Bad data WITHOUT UPDATING ecc*/
    memset (&secInfo, 0, sizeof(secInfo));
    secInfo.bOEMReserved = SKIP_ECC_WRITE_MAGIC_NUMBER;
    rc = FMD_WriteSector(pContext->test_sector, p_baddata, &secInfo, 1); 
    if( !rc )
    {
        DEBUGMSG(ZONE_ERROR,  (L"ERROR: nand_ecc_test WRITE bad data in sector(%d) failed!\r\n", pContext->test_sector));
        goto cleanUp;
    }
	
    /* Step 4: read back to see if there are errors */
    rc = FMD_ReadSector(pContext->test_sector, outBuf, NULL, 1); 
    if( !rc )
    {
        DEBUGMSG(ZONE_ERROR,  (L"ERROR: nand_ecc_test READ good data in sector(%d) failed!\r\n", pContext->test_sector));
        goto cleanUp; 
    }
	
    if(memcmp(outBuf, p_gooddata, SECTOR_SIZE))
    {
        RETAILMSG(TRUE,  (L"ERROR: nand_ecc_test READ data after correction does not match good data in sector(%d) failed!\r\n",
			pContext->test_sector));
        goto cleanUp;
    }
    rc = TRUE;
	
cleanUp:
    memcpy(p_outbuf, outBuf, SECTOR_SIZE );
	
    return rc;
}
Example #10
0
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, 
                &sectorInfo, 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;
}
Example #11
0
static UINT32 ReadFlashIPL()
{
    UINT32 rc = BL_ERROR;
    HANDLE hFMD = NULL;
    FlashInfo flashInfo;
    UINT32 offset;
    SectorInfo sectorInfo;
    SECTOR_ADDR sector;
    BLOCK_ID block;
    UINT8 *pImage;
    UINT32 *pInfo;


    // Check if there is a valid image
    OALMSG(OAL_INFO, (L"\r\nLoad IPL 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;
    }

    // Start from NAND start
    block  = 0;
    sector = 8;
    offset = 0;

    // Set address where to place image
    pImage = (UINT8*)(IMAGE_IPL_ADDR_VA);

    // Read image to memory
    while (offset < IMAGE_IPL_SIZE && block < flashInfo.dwNumBlocks) {

        // Read sectors in block
        while ( offset < IMAGE_IPL_SIZE ) {
            // When block read fail, there isn't what we can do more
            if (!FMD_ReadSector(sector, pImage, &sectorInfo, 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++;
            pImage += flashInfo.wDataBytesPerSector;
            offset += flashInfo.wDataBytesPerSector;
//            OALMSG(OAL_INFO, (L"."));
        }

        // Move to next block
        block++;
    }

    OALMSG(OAL_INFO, (L"\r\n"));

    // Check if IPL is image and dump its content
    pInfo = (UINT32*)(IMAGE_IPL_ADDR_VA + ROM_SIGNATURE_OFFSET);
    if (*pInfo != ROM_SIGNATURE) {
        OALMSG(OAL_ERROR, (L"ERROR: BLFlashDownload: "
            L"IPL image doesn't have ROM signature at 0x%08x\r\n", pInfo
        ));
        goto cleanUp;
    }

    g_pTOC->id[g_dwTocEntry].dwJumpAddress = IMAGE_IPL_ADDR_VA;
    rc = BL_JUMP;

cleanUp:
    return rc;
}
Example #12
0
BOOL WriteRawImageToBootMedia(DWORD dwImageStart, DWORD dwImageLength, DWORD dwLaunchAddr)
{
    DWORD dwBlock,dwNumBlocks;
    LPBYTE pbBuffer;
    SectorInfo si;

    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 (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 = NBOOT_BLOCK;
        dwImageStart += dwLaunchAddr;
        dwImageLength = STEPPINGSTONE_SIZE; //step loader can support 8k bytes.
    }

    pbBuffer = OEMMapMemAddr(dwImageStart, dwImageStart);

    // Compute number of blocks.
    //dwNumBlocks = (dwImageLength / 0x4000) + 1;
    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));

        FMD_ReadSector(dwBlock*g_FlashInfo.wSectorsPerBlock, NULL, &si, 1);

        // Stepldr & Eboot image in nand flash
        // block mark as BLOCK_STATUS_RESERVED & BLOCK_STATUS_READONLY & BLOCK_STATUS_BAD
        if ((si.bBadBlock == BADBLOCKMARK) && (si.bOEMReserved != 0xFC ))
        {
            ++dwBlock;
            ++dwNumBlocks;        // Compensate for fact that we didn't write any blocks.
            continue;
        }

        if (!ReadBlock(dwBlock, NULL, g_pSectorInfoBuf))
        {
            OALMSG(OAL_ERROR, (TEXT("WriteData: failed to read block (0x%x).\r\n"), dwBlock));
            return(FALSE);
        }

        if (!FMD_EraseBlock(dwBlock))
        {
            OALMSG(OAL_ERROR, (TEXT("WriteData: failed to erase block (0x%x).\r\n"), dwBlock));
            return FALSE;
        }

        if (!WriteBlock(dwBlock, pbBuffer, g_pSectorInfoBuf))
        {
            OALMSG(OAL_ERROR, (TEXT("WriteData: failed to write block (0x%x).\r\n"), dwBlock));
            return(FALSE);
        }

        ++dwBlock;
        pbBuffer += g_FlashInfo.dwBytesPerBlock;    //c ksk 20060311
        OALMSG(TRUE, (TEXT("dwBytesPerBlock : %d\r\n"), g_FlashInfo.dwBytesPerBlock));
    }

    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
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, &regInfo, 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, &sectorInfo, 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, &regInfo, 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, &sectorInfo, 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(&sectorInfo, 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, &sectorInfo, 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;
}
Example #15
0
VOID DumpFlash(OAL_BLMENU_ITEM *pMenu)
{
    HANDLE hFMD = NULL;
    PCI_REG_INFO regInfo;
    FlashInfo flashInfo;
    SectorInfo sectorInfo;
    SECTOR_ADDR sector;
    WCHAR szInputLine[16];
    UINT8 buffer[2048], pOob[64];
    UINT32 i, j;

    UNREFERENCED_PARAMETER(pMenu);


    // Open FMD
    regInfo.MemBase.Reg[0] = g_ulFlashBase;
    hFMD = FMD_Init(NULL, &regInfo, 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 (flashInfo.wDataBytesPerSector > sizeof(buffer)) 
        {
        OALLog(L" Oops, sector size larger than my buffer\r\n");
        goto cleanUp;
        }

        for(;;)
        {

        OALLog(L"\r\n Sector Number: ");

        if (OALBLMenuReadLine(szInputLine, dimof(szInputLine)) == 0) 
            {
            break;
            }

        // Get sector number
        sector = OALStringToUINT32(szInputLine);

        // Check sector number
        if (sector > flashInfo.dwNumBlocks * flashInfo.wSectorsPerBlock) 
            {
            OALLog(L" Oops, too big sector number\r\n");
            continue;
            }

        if (!FMD_ReadSector(sector, buffer, &sectorInfo, 1)) 
            {
            OALLog(L" Oops, sector read failed\r\n");
            continue;
            }

        OALLog(
            L"\r\nSector %d (sector %d in block %d)\r\n", sector,
            sector%flashInfo.wSectorsPerBlock, sector/flashInfo.wSectorsPerBlock
        );
        OALLog(
            L"Reserved1: %08x OEMReserved: %02x Bad: %02x Reserved2: %04x\r\n",
            sectorInfo.dwReserved1, sectorInfo.bOEMReserved,
            sectorInfo.bBadBlock, sectorInfo.wReserved2
        );

        for (i = 0; i < flashInfo.wDataBytesPerSector; i += 16) 
            {
            OALLog(L"%04x ", i);
            for (j = i; j < i + 16 && j < flashInfo.wDataBytesPerSector; j++) 
                {
                OALLog(L" %02x", buffer[j]);
                }
            OALLog(L"  ");
            for (j = i; j < i + 16 && j < flashInfo.wDataBytesPerSector; j++) 
                {
                if (buffer[j] >= ' ' && buffer[j] < 127) 
                    {
                    OALLog(L"%c", buffer[j]);
                    } 
                else 
                    {
                    OALLog(L".");
                    }
                }
            OALLog(L"\r\n");
            }
	//dump OOB data
        if (!FMD_ReadSectorOOB(sector, pOob)) 
            {
            OALLog(L" Oops, sector read failed\r\n");
            continue;
            }
        for (i = 0; i < 64; i += 16) 
            {
            OALLog(L"%04x ", i);
            for (j = i; j < i + 16 && j < 64; j++) 
                {
                OALLog(L" %02x", pOob[j]);
                }
                
            OALLog(L"\r\n");
            }

        }

cleanUp:

    if (hFMD != NULL) 
        {
        FMD_Deinit(hFMD);
        }

    return;
}