iBoot/drivers/flash_nand/raw/Whimory/Exam/WMRExam.c

1001 lines
36 KiB
C

/*****************************************************************************/
/* */
/* COMPONENT : Rainbow */
/* MODULE : Example */
/* NAME : Example */
/* FILE : WMRExam.c */
/* PURPOSE : the example for whimory initialization */
/* */
/*---------------------------------------------------------------------------*/
/* */
/* COPYRIGHT 2003-2005 SAMSUNG ELECTRONICS CO., LTD. */
/* ALL RIGHTS RESERVED */
/* */
/* Permission is hereby granted to licensees of Samsung Electronics */
/* Co., Ltd. products to use or abstract this computer program for the */
/* sole purpose of implementing a product based on Samsung */
/* Electronics Co., Ltd. products. No other rights to reproduce, use, */
/* or disseminate this computer program, whether in part or in whole, */
/* are granted. */
/* */
/* Samsung Electronics Co., Ltd. makes no representation or warranties */
/* with respect to the performance of this computer program, and */
/* specifically disclaims any responsibility for any damages, */
/* special or consequential, connected with the use of this program. */
/* */
/*---------------------------------------------------------------------------*/
/* */
/* REVISION HISTORY */
/* */
/* 12-SEP-2005 [Jaesung Jung] : first writing */
/* 15-MAR-2006 [Yangsup Lee ] : bad block detection bug fix */
/* */
/*****************************************************************************/
#if (!defined(AND_FPART_ONLY) || !AND_FPART_ONLY)
#include "ANDTypes.h"
#include "WMRConfig.h"
#include "WMROAM.h"
#include "VFLBuffer.h"
#include "FPart.h"
#include "VFL.h"
#include "FTL.h"
#include "FIL.h"
#include "WMRExam.h"
#include "FPartTypes.h"
#include "ANDStats.h"
#include "WMRTest.h"
#else
#include "ANDTypes.h"
#include "WMRConfig.h"
#include "WMROAM.h"
#include "VFLBuffer.h"
#include "FPart.h"
#include "FIL.h"
#include "WMRExam.h"
#include "FPartTypes.h"
#endif
/*****************************************************************************/
/* Debug Print #defines */
/*****************************************************************************/
#define EXAM_INF_MSG_ON
#define EXAM_ERR_PRINT(x) WMR_RTL_PRINT(x)
#define EXAM_RTL_PRINT(x) WMR_RTL_PRINT(x)
#if defined (EXAM_LOG_MSG_ON)
#define EXAM_LOG_PRINT(x) WMR_DBG_PRINT(x)
#else
#define EXAM_LOG_PRINT(x)
#endif
#if defined (EXAM_INF_MSG_ON)
#define EXAM_INF_PRINT(x) WMR_DBG_PRINT(x)
#else
#define EXAM_INF_PRINT(x)
#endif
#if (!defined(AND_FPART_ONLY) || !AND_FPART_ONLY)
static ANDDriverSignature g_flashANDSignature; // Keep what was read from flash
static ANDDriverSignature g_scratchANDSignature; // For writing new signatures
static VFLFunctions stVflFunctions;
static FTLFunctions stFtlFunctions;
#endif
static FPartFunctions stFPartFunctions;
static BOOL32 boolFPartInitialized = FALSE32;
/*****************************************************************************/
/* Code Implementation */
/*****************************************************************************/
static Int32 _initFPart(UInt32 dwFormatType, UInt32 dwBootAreaSize)
{
UInt32 dwFPartOptions = 0;
Int32 nRet;
if (FALSE32 == boolFPartInitialized)
{
WMR_MEMSET(&stFPartFunctions, 0, sizeof(FPartFunctions));
FPart_Register(&stFPartFunctions);
dwFPartOptions = 0;
dwFPartOptions |= (dwFormatType & WMR_INIT_USE_DEV_UNIQUE_INFO) ? FPART_INIT_OPTION_DEV_UNIQUE : 0;
dwFPartOptions |= (dwFormatType & WMR_INIT_USE_DIAG_CTRL_INFO) ? FPART_INIT_OPTION_DIAG_CTRL : 0;
nRet = stFPartFunctions.Init(FIL_GetFuncTbl(), dwFPartOptions);
if (nRet != TRUE32)
{
return WMR_CRITICAL_ERROR;
}
boolFPartInitialized = TRUE32;
}
return WMR_SUCCESS;
}
Int32
WMR_PreInit(UInt32 dwFormatType, UInt32 dwBootAreaSize)
{
Int32 nRet;
OAM_Init();
nRet = FIL_Init();
if (nRet != FIL_SUCCESS)
{
return WMR_CRITICAL_ERROR;
}
if (0 == FIL_GetFuncTbl()->GetDeviceInfo(AND_DEVINFO_NUM_OF_CS))
{
EXAM_RTL_PRINT((TEXT("[FTL:MSG] No NAND attached\n")));
return WMR_CRITICAL_ERROR;
}
nRet = BUF_Init((UInt16)FIL_GetFuncTbl()->GetDeviceInfo(AND_DEVINFO_BYTES_PER_PAGE),
BYTES_PER_METADATA_RAW,
WMR_NUM_BUFFERS);
if (nRet != BUF_SUCCESS)
{
return WMR_CRITICAL_ERROR;
}
nRet = _initFPart(dwFormatType, dwBootAreaSize);
if (nRet != WMR_SUCCESS)
{
return WMR_CRITICAL_ERROR;
}
return WMR_SUCCESS;
}
FPartFunctions * WMR_GetFPart(void)
{
return &stFPartFunctions;
}
#if (!defined(AND_FPART_ONLY) || !AND_FPART_ONLY)
static BOOL32 _isSignatureCompatible(ANDDriverSignature *pstSignature)
{
const UInt8 bPlatform = WMR_SIGNATURE_PLATFORM(pstSignature->dwMainSignature);
const UInt8 bLayout = WMR_SIGNATURE_LAYOUT(pstSignature->dwMainSignature);
const UInt8 bVFLType = WMR_SIGNATURE_VFL(pstSignature->dwMainSignature);
const UInt32 dw2ndId = WMR_SIGNATURE_FORMATTING_VERSION(pstSignature->dw2ndId);
if ( WMR_PLATFORM_DARWIN != bPlatform)
{
return FALSE32;
}
if ( (WMR_LAYOUT_SIMPLE != bLayout) && (WMR_LAYOUT_VS != bLayout) )
{
return FALSE32;
}
if ( (WMR_M68_VFL != bVFLType) && (WMR_VSVFL != bVFLType) )
{
return FALSE32;
}
// Only VS layout supports 2ndID field
if ((WMR_LAYOUT_VS == bLayout) && (dw2ndId > WMR_FORMATTING_VERSION))
{
return FALSE32;
}
return TRUE32;
}
static BOOL32 _selectVFL(BOOL32 boolSignatureFound,
BOOL32 boolAllowVSVFL,
BOOL32 boolSignInBlockZero,
ANDDriverSignature * pOldANDDriverSignature,
ANDDriverSignature * pNewANDDriverSignature)
{
// decide what VFL to use
if (((boolSignatureFound == TRUE32) &&
WMR_SIGNATURE_VFL(pOldANDDriverSignature->dwMainSignature) == WMR_VSVFL)
#ifndef AND_READONLY
|| ((boolSignatureFound == FALSE32) && (boolAllowVSVFL == TRUE32))
#endif
)
{
VSVFL_Register(&stVflFunctions);
pNewANDDriverSignature->dwMainSignature = WMR_VSVFL_VS_SIGNATURE;
EXAM_RTL_PRINT((TEXT("[FTL:MSG] VSVFL Register [OK]\n")));
if (boolSignInBlockZero == FALSE32)
{
stFPartFunctions.SetSignatureStyle(&stFPartFunctions, SIGNATURE_STYLE_RESERVEDBLOCK_HEADER);
}
else
{
EXAM_ERR_PRINT((TEXT("[WMR:ERR] Signature Style RESERVEDBLOCK HEADER has to be used with VSVFL formatting.\n")));
return FALSE32;
}
if ((WMR_SIGNATURE_METADATA(pOldANDDriverSignature->dw2ndId) == WMR_METADATA_WHITENING))
{
if (FIL_GetFuncTbl()->SetWhiteningMetadataState)
{
EXAM_RTL_PRINT((TEXT("[WMR:MSG] Metadata whitening is set in NAND signature\n")));
FIL_GetFuncTbl()->SetWhiteningMetadataState(TRUE32);
}
else
{
EXAM_RTL_PRINT((TEXT("[WMR:ERR] Metadata whitening not supported.\n")));
return FALSE32;
}
}
else if (FIL_GetFuncTbl()->SetWhiteningMetadataState)
{
FIL_GetFuncTbl()->SetWhiteningMetadataState(FALSE32);
}
}
else if (((boolSignatureFound == TRUE32) &&
WMR_SIGNATURE_VFL(pOldANDDriverSignature->dwMainSignature) == WMR_M68_VFL)
#ifndef AND_READONLY
|| ((boolSignatureFound == FALSE32) && (boolAllowVSVFL == FALSE32))
#endif
)
{
#if AND_SUPPORT_LEGACY_VFL
VFL_Register(&stVflFunctions);
pNewANDDriverSignature->dwMainSignature = WMR_VFL_SIGNATURE;
EXAM_RTL_PRINT((TEXT("[FTL:MSG] VFL Register [OK]\n")));
if (boolSignInBlockZero == TRUE32)
{
stFPartFunctions.SetSignatureStyle(&stFPartFunctions, SIGNATURE_STYLE_BLOCKZERO_NOHEADER);
}
else
{
EXAM_ERR_PRINT((TEXT("[WMR:ERR] Signature Style BLOCKZERO NOHEADER has to be used with VFL formatting.\n")));
return FALSE32;
}
#else
EXAM_ERR_PRINT((TEXT("[FTL:ERR] Legacy VFL is not supported - init fail\n")));
return FALSE32;
#endif
}
else
{
EXAM_ERR_PRINT((TEXT("[WMR:ERR] No Valid VFL type found main signature 0x%08X\n"),
pOldANDDriverSignature->dwMainSignature));
return FALSE32;
}
return TRUE32;
}
/*****************************************************************************/
/* */
/* NAME */
/* WMR_Init */
/* DESCRIPTION */
/* This function inits whimory & format & open. */
/* PARAMETERS */
/* pTotalScts [OUT] the count of sectors which user can use. */
/* RETURN VALUES */
/* WMR_SUCCESS */
/* FTL_Open is completed */
/* WMR_CRITICAL_ERROR */
/* FTL_Open is failed */
/* WMR_UNRECOVERABLE_ERROR */
/* Open failed but we can possibly read syscfg */
/* NOTES */
/* */
/*****************************************************************************/
Int32
WMR_Init(UInt32 *pTotalScts, UInt32 * pdwSectorSize, UInt32 * tmpIndexCache, UInt32 dwFormatType, UInt32 dwBootAreaSize)
{
Int32 nRet;
BOOL32 boolSignatureFound = FALSE32;
volatile BOOL32 boolProductionFormatVerified = TRUE32;
static UInt32 alreadyCalled = 0;
BOOL32 boolFTLRegistered = FALSE32;
BOOL32 boolSignInBlockZero = (dwFormatType & WMR_INIT_SIGNATURE_IN_BLOCKZERO ? TRUE32 : FALSE32);
BOOL32 nandFullRestore = (dwFormatType & WMR_INIT_NAND_RESTORE ? TRUE32 : FALSE32);
UInt32 ftlOpenOptions = 0;
#if (defined(AND_LOW_POWER_MOUNT) && AND_LOW_POWER_MOUNT)
UInt32 dwInitPowerMode = (dwFormatType & WMR_INIT_LOW_POWER_MODE) ? NAND_POWER_MODE_SINGLE_CE : NAND_POWER_MODE_FULL_SPEED;
#endif
BOOL32 boolAllowVSVFL = (dwFormatType & WMR_INIT_ALLOW_VSVFL ? TRUE32 : FALSE32);
BOOL32 boolMetadataWhitening = (dwFormatType & WMR_INIT_METADATA_WHITENING ? TRUE32 : FALSE32);
BOOL32 boolMetadataWhiteningCheck = (dwFormatType & WMR_INIT_METADATA_WHITENING_CHECK ? TRUE32 : FALSE32);
#ifndef AND_READONLY
BOOL32 boolStatus;
BOOL32 boolProductionFormatCompleted = FALSE32;
BOOL32 bFormatAllowed = (dwFormatType & WMR_INIT_ALLOW_FORMAT ? TRUE32 : FALSE32);
BOOL32 boolAllowYAFTL = (dwFormatType & WMR_INIT_ALLOW_YAFTL ? TRUE32 : FALSE32);
BOOL32 boolRunProductionReformat = (dwFormatType & WMR_INIT_RUN_PRODUCTION_FORMAT ? TRUE32 : FALSE32);
BOOL32 boolRunFTLFormat = (dwFormatType & WMR_INIT_RUN_FTL_FORMAT ? TRUE32 : FALSE32);
WMR_ASSERT(!(boolRunFTLFormat && boolRunProductionReformat));
#endif
// make sure we init the functions
WMR_MEMSET(&stVflFunctions, 0, sizeof(VFLFunctions));
WMR_MEMSET(&stFtlFunctions, 0, sizeof(FTLFunctions));
WMR_MEMSET(&g_flashANDSignature, 0, sizeof(ANDDriverSignature));
WMR_MEMSET(&g_scratchANDSignature, 0, sizeof(ANDDriverSignature));
OAM_Init();
#ifdef AND_READONLY
EXAM_RTL_PRINT((TEXT("[FTL:MSG] Apple NAND Driver (AND) RO\n")));
#else
EXAM_RTL_PRINT((TEXT("[FTL:MSG] Apple NAND Driver (AND) RW\n")));
#endif
if (alreadyCalled)
{
EXAM_ERR_PRINT((TEXT("[WMR:ERR] WMR_Init already called!\n")));
}
alreadyCalled++;
nRet = FIL_Init();
if (nRet != FIL_SUCCESS)
{
return WMR_CRITICAL_ERROR;
}
#if (defined(AND_LOW_POWER_MOUNT) && AND_LOW_POWER_MOUNT)
FIL_SetStruct(AND_STRUCT_FIL_POWER_MODE, &dwInitPowerMode, sizeof(UInt32));
#endif
EXAM_RTL_PRINT((TEXT("[FTL:MSG] FIL_Init [OK]\n")));
if (0 == FIL_GetFuncTbl()->GetDeviceInfo(AND_DEVINFO_NUM_OF_CS)) {
EXAM_RTL_PRINT((TEXT("[FTL:MSG] No NAND attached\n")));
return WMR_CRITICAL_ERROR;
}
#if defined(WMR_UNIT_TEST_ENABLED) && WMR_UNIT_TEST_ENABLED
if (!FIL_Test())
{
return WMR_CRITICAL_ERROR;
}
#endif /* FIL_TEST_ENABLED */
nRet = BUF_Init((UInt16)FIL_GetFuncTbl()->GetDeviceInfo(AND_DEVINFO_BYTES_PER_PAGE), BYTES_PER_METADATA_RAW, WMR_NUM_BUFFERS);
if (nRet != BUF_SUCCESS)
{
return WMR_CRITICAL_ERROR;
}
EXAM_RTL_PRINT((TEXT("[FTL:MSG] BUF_Init [OK]\n")));
nRet = _initFPart(dwFormatType, dwBootAreaSize);
if (nRet != WMR_SUCCESS)
{
return WMR_CRITICAL_ERROR;
}
EXAM_RTL_PRINT((TEXT("[FTL:MSG] FPart Init [OK]\n")));
/* signature searching */
// try old style signature first (quicker)
if (boolSignInBlockZero == TRUE32)
{
stFPartFunctions.SetSignatureStyle(&stFPartFunctions, SIGNATURE_STYLE_BLOCKZERO_NOHEADER);
}
else
{
stFPartFunctions.SetSignatureStyle(&stFPartFunctions, SIGNATURE_STYLE_RESERVEDBLOCK_HEADER);
}
if (stFPartFunctions.ReadSignature(&g_flashANDSignature, sizeof(ANDDriverSignature)))
{
if (boolSignInBlockZero == TRUE32)
{
EXAM_RTL_PRINT((TEXT("read old style signature 0x%08X (line:%d)\n"), g_flashANDSignature.dwMainSignature, __LINE__));
}
else
{
EXAM_RTL_PRINT((TEXT("read new style signature 0x%08X (line:%d)\n"), g_flashANDSignature.dwMainSignature, __LINE__));
}
if (_isSignatureCompatible(&g_flashANDSignature))
{
boolSignatureFound = TRUE32;
#ifndef AND_READONLY
if (boolRunProductionReformat == TRUE32)
{
stFPartFunctions.WriteSignature(NULL, 0);
}
#endif
if (boolMetadataWhiteningCheck)
{
BOOL32 boolSignatureHasMetadataWhitening = (WMR_SIGNATURE_METADATA(g_flashANDSignature.dw2ndId) == WMR_METADATA_WHITENING);
if ( (boolSignatureHasMetadataWhitening == TRUE32 && boolMetadataWhitening == FALSE32)
|| (boolSignatureHasMetadataWhitening == FALSE32 && boolMetadataWhitening == TRUE32))
{
#ifndef AND_READONLY
stFPartFunctions.WriteSignature(NULL, 0);
#endif
EXAM_RTL_PRINT((TEXT("[FTL:ERR] metadata whitening mismatch, please reformat\n")));
return WMR_UNRECOVERABLE_ERROR;
}
}
}
else
{
EXAM_RTL_PRINT((TEXT("[FTL:WRN] Incompatible Signature!\n")));
}
}
/*
* If we have been instructed to run a production reformat, force it by faking a signature
* mismatch
*/
#ifndef AND_READONLY
if (boolRunProductionReformat)
{
boolSignatureFound = FALSE32;
}
#endif // ! AND_READONLY
/*
* If any of the basic criteria are violated, we are going to have to reformat.
* If this isn't permitted, print a diagnoistic and bail out.
*/
if (!boolSignatureFound)
{
/*
* Verify that we can read the BBT from all banks.
*/
#ifndef AND_READONLY
if (!bFormatAllowed)
#endif
{
EXAM_RTL_PRINT((TEXT("[WMR:ERR] NAND format invalid (mismatch, corrupt, read error or blank NAND device)\n")));
EXAM_RTL_PRINT((TEXT("[WMR:ERR] boolSignatureFound %s boolProductionFormatVerified %s nSig 0x%x\n"),
boolSignatureFound ? "true" : "false",
boolProductionFormatVerified ? "true" : "false",
g_flashANDSignature.dwMainSignature));
goto fail_readonly;
}
#ifndef AND_READONLY
boolProductionFormatVerified = stFPartFunctions.VerifyProductionFormat();
#ifdef AND_USE_NOTIFY
/* one or more of the failed criteria will require a reformat operation */
FIL_GetFuncTbl()->Notify(AND_NOTIFY_REFORMAT);
#endif
#endif //!AND_READONLY
}
// decide what VFL to use
if (FALSE32 == _selectVFL(boolSignatureFound, boolAllowVSVFL,
boolSignInBlockZero, &g_flashANDSignature, &g_scratchANDSignature))
{
return WMR_UNRECOVERABLE_ERROR;
}
nRet = stVflFunctions.Init(&stFPartFunctions);
if (nRet != VFL_SUCCESS)
{
return WMR_UNRECOVERABLE_ERROR;
}
EXAM_RTL_PRINT((TEXT("[FTL:MSG] VFL Init [OK]\n")));
#ifndef AND_READONLY
/*
* If we couldn't find the BBT, or the signature is missing (or we are pretending it's missing),
* we need to think about (re)formatting.
*/
if (boolProductionFormatVerified != TRUE32 || boolSignatureFound != TRUE32)
{
Int32 nRetTemp;
if (boolMetadataWhitening)
{
if (FIL_GetFuncTbl()->SetWhiteningMetadataState)
{
EXAM_RTL_PRINT((TEXT("[WMR:INF] Formatting with metadata whitening\n")));
FIL_GetFuncTbl()->SetWhiteningMetadataState(TRUE32);
}
else
{
EXAM_RTL_PRINT((TEXT("[WMR:ERR] Metadata whitening unavailable!\n")));
return WMR_UNRECOVERABLE_ERROR;
}
}
if (boolProductionFormatVerified == FALSE32)
{
// this is a either virgin device or a device that went through
// power failure during initial format. We have to scan for
// the initial bad blocks and save them as a factory bad-block table.
EXAM_RTL_PRINT((TEXT("[WMR:INF] Calling VFL_ProductionFormat()\n")));
if (stFPartFunctions.WriteInitialBBT() != TRUE32)
{
EXAM_RTL_PRINT((TEXT("[WMR:ERR] Failed VFL_ProductionFormat\n")));
return WMR_UNRECOVERABLE_ERROR;
}
EXAM_RTL_PRINT((TEXT("[WMR:MSG] Production Format OK!\n")));
boolProductionFormatCompleted = TRUE32;
}
if (boolProductionFormatCompleted == FALSE32)
{
EXAM_RTL_PRINT((TEXT("[FTL:MSG] Calling VFL_FactoryReformat()\n")));
// erase signature before clearing the NAND
stFPartFunctions.WriteSignature(NULL, 0);
stFPartFunctions.FactoryReformat(FALSE32, FALSE32, dwBootAreaSize);
}
nRetTemp = stVflFunctions.Format(dwBootAreaSize, 0);
if (nRetTemp != VFL_SUCCESS)
{
return WMR_UNRECOVERABLE_ERROR;
}
EXAM_RTL_PRINT((TEXT("[FTL:MSG] VFL_Format [OK]\n")));
// check if we need a shrinked FTL partition
if ((*pTotalScts) && (*pdwSectorSize))
{
UInt32 dwPageSize, dwPagesPerSuBlks;
UInt16 wNewFTLSuBlkCnt;
UInt32 dwRequestedPages;
dwPagesPerSuBlks = (UInt16)stVflFunctions.GetDeviceInfo(AND_DEVINFO_PAGES_PER_SUBLK);
dwPageSize = (UInt16)stVflFunctions.GetDeviceInfo(AND_DEVINFO_BYTES_PER_PAGE);
dwRequestedPages = (*pTotalScts) * ((*pdwSectorSize) / dwPageSize);
wNewFTLSuBlkCnt = (UInt16)((UInt32)(110 * dwRequestedPages) /
(dwPagesPerSuBlks * 100)) + 23;
stVflFunctions.SetStruct(AND_STRUCT_VFL_NUM_OF_FTL_SUBLKS, &wNewFTLSuBlkCnt, sizeof(UInt16));
}
// choose the FTL we want to use and init it
if (boolAllowYAFTL == TRUE32)
{
#if (defined (AND_SUPPORT_YAFTL) && AND_SUPPORT_YAFTL)
YAFTL_Register(&stFtlFunctions);
EXAM_RTL_PRINT((TEXT("[FTL:MSG] YAFTL Register [OK]\n")));
#else
EXAM_RTL_PRINT((TEXT("[FTL:ERR] YAFTL is not supported - init fail\n")));
return WMR_UNRECOVERABLE_ERROR;
#endif
}
else
{
#if AND_SUPPORT_LEGACY_FTL
EXAM_RTL_PRINT((TEXT("[FTL:MSG] FTL Register [OK]\n")));
FTL_Register(&stFtlFunctions);
#else
EXAM_RTL_PRINT((TEXT("[FTL:ERR] Legacy FTL is not supported - init fail\n")));
return WMR_UNRECOVERABLE_ERROR;
#endif
}
boolFTLRegistered = TRUE32;
nRetTemp = stFtlFunctions.Init(&stVflFunctions);
if (nRetTemp != FTL_SUCCESS)
{
EXAM_RTL_PRINT((TEXT("[FTL:ERR] FTL failed Init\n")));
return WMR_UNRECOVERABLE_ERROR;
}
EXAM_RTL_PRINT((TEXT("[FTL:MSG] FTL Init [OK]\n")));
nRetTemp = stFtlFunctions.Format(0);
if (nRetTemp != FTL_SUCCESS)
{
EXAM_RTL_PRINT((TEXT("[FTL:ERR] FTL failed Formatting\n")));
return WMR_UNRECOVERABLE_ERROR;
}
EXAM_RTL_PRINT((TEXT("[FTL:MSG] FTL Format [OK]\n")));
/* full reformat, write normal signature */
// Main signature is set from _selectVFL
g_scratchANDSignature.dw2ndId = WMR_FORMATTING_VERSION;
// determine if metadata whitening is needed based on signature
if (boolMetadataWhitening)
{
g_scratchANDSignature.dw2ndId |= WMR_METADATA_SIGNATURE;
}
/* 5249095 - this should write FTL build info, not kernel version */
WMR_MEMSET(g_scratchANDSignature.strBuildInfo, 0, WMR_MAX_STR_BUILD_SIZE);
WMR_MEMCPY(g_scratchANDSignature.strBuildInfo, WMR_GETVERSION(),
WMR_MIN(WMR_STRLEN(WMR_GETVERSION()), (WMR_MAX_STR_BUILD_SIZE - 1)));
boolStatus = stFPartFunctions.WriteSignature(&g_scratchANDSignature, sizeof(ANDDriverSignature));
if (boolStatus)
{
WMR_MEMCPY(&g_flashANDSignature, &g_scratchANDSignature, sizeof(ANDDriverSignature));
}
else
{
EXAM_RTL_PRINT((TEXT("[FTL:MSG] Write Signature Failed 0x%08X\n"), g_flashANDSignature.dwMainSignature));
return WMR_CRITICAL_ERROR;
}
EXAM_RTL_PRINT((TEXT("[FTL:MSG] Write Signature OK 0x%08X\n"), g_flashANDSignature.dwMainSignature));
{
WMR_MEMSET(&g_scratchANDSignature, 0, sizeof(ANDDriverSignature));
boolStatus = stFPartFunctions.ReadSignature(&g_scratchANDSignature, sizeof(ANDDriverSignature));
if (!boolStatus || WMR_MEMCMP(&g_scratchANDSignature, &g_flashANDSignature, sizeof(ANDDriverSignature)))
{
EXAM_RTL_PRINT((TEXT("[FTL:MSG] Read back Signature Failed 0x%08X\n"), g_scratchANDSignature.dwMainSignature));
return WMR_CRITICAL_ERROR;
}
else
{
EXAM_RTL_PRINT((TEXT("[FTL:MSG] Read back Signature OK\n")));
}
}
}
#endif // ! AND_READONLY
nRet = stVflFunctions.Open(dwBootAreaSize, 0, 0);
if (nRet != VFL_SUCCESS)
{
EXAM_RTL_PRINT((TEXT("[WMR:ERR] VFL_Open failed\n")));
WMR_BEEP(1000000);
return WMR_UNRECOVERABLE_ERROR;
}
EXAM_RTL_PRINT((TEXT("[FTL:MSG] VFL_Open [OK]\n")));
if (boolFTLRegistered == FALSE32)
{
#ifndef AND_READONLY
// Check if we wanted to reformat FTL...
if (boolRunFTLFormat)
{
// change the FTL size inside the vfl and mark the FTL
// for format
if ((*pTotalScts) && (*pdwSectorSize))
{
UInt32 dwPageSize, dwPagesPerSuBlks;
UInt16 wNewFTLSuBlkCnt;
UInt32 dwRequestedPages;
dwPagesPerSuBlks = (UInt16)stVflFunctions.GetDeviceInfo(AND_DEVINFO_PAGES_PER_SUBLK);
dwPageSize = (UInt16)stVflFunctions.GetDeviceInfo(AND_DEVINFO_BYTES_PER_PAGE);
dwRequestedPages = (*pTotalScts) * ((*pdwSectorSize) / dwPageSize);
wNewFTLSuBlkCnt = (UInt16)((UInt32)(110 * dwRequestedPages) /
(dwPagesPerSuBlks * 100)) + 23;
stVflFunctions.SetStruct(AND_STRUCT_VFL_NUM_OF_FTL_SUBLKS, &wNewFTLSuBlkCnt, sizeof(UInt16));
}
else
{
UInt16 wNewFTLSuBlkCnt;
UInt32 dwSize = sizeof(wNewFTLSuBlkCnt);
stVflFunctions.GetStruct(AND_STRUCT_VFL_NUM_OF_SUBLKS, &wNewFTLSuBlkCnt, &dwSize);
stVflFunctions.SetStruct(AND_STRUCT_VFL_NUM_OF_FTL_SUBLKS, &wNewFTLSuBlkCnt, sizeof(UInt16));
}
}
#endif
// check what FTL to use here
if (stVflFunctions.GetDeviceInfo(AND_DEVINFO_FTL_TYPE) == FTL_TYPE_YAFTL)
{
#if (defined (AND_SUPPORT_YAFTL) && AND_SUPPORT_YAFTL)
YAFTL_Register(&stFtlFunctions);
EXAM_RTL_PRINT((TEXT("[FTL:MSG] YAFTL Register [OK]\n")));
#else
EXAM_RTL_PRINT((TEXT("[FTL:ERR] YAFTL is not supported - init fail\n")));
return WMR_UNRECOVERABLE_ERROR;
#endif
}
else
{
#if AND_SUPPORT_LEGACY_FTL
EXAM_RTL_PRINT((TEXT("[FTL:MSG] FTL Register [OK]\n")));
FTL_Register(&stFtlFunctions);
#else
EXAM_RTL_PRINT((TEXT("[FTL:ERR] Legacy FTL is not supported - init fail\n")));
return WMR_UNRECOVERABLE_ERROR;
#endif
}
nRet = stFtlFunctions.Init(&stVflFunctions);
if (nRet != FTL_SUCCESS)
{
EXAM_RTL_PRINT((TEXT("[WMR:ERR] FTL Init Fail\n")));
return WMR_UNRECOVERABLE_ERROR;
}
#ifndef AND_READONLY
if (stVflFunctions.GetDeviceInfo(AND_DEVINFO_FTL_NEED_FORMAT) ||
(boolRunFTLFormat == TRUE32))
{
nRet = stFtlFunctions.Format(0);
if (nRet != FTL_SUCCESS)
{
EXAM_RTL_PRINT((TEXT("[WMR:ERR] FTL ReFormat Fail\n")));
return WMR_UNRECOVERABLE_ERROR;
}
}
#endif
}
if ((dwFormatType & WMR_INIT_DISABLE_GC_IN_TRIM) == WMR_INIT_DISABLE_GC_IN_TRIM)
{
EXAM_RTL_PRINT((TEXT("FTL_Open will get trim GC disabled settings \n")));
ftlOpenOptions |= WMR_INIT_DISABLE_GC_IN_TRIM;
}
if ((dwFormatType & WMR_INIT_SET_INDEX_CACHE_SIZE) == WMR_INIT_SET_INDEX_CACHE_SIZE)
{
EXAM_RTL_PRINT((TEXT("FTL_Open will set index cache to 0x%x \n"),*tmpIndexCache));
ftlOpenOptions |= WMR_INIT_SET_INDEX_CACHE_SIZE;
ftlOpenOptions |= ((*tmpIndexCache) << 20);
}
if ( WMR_INIT_OPEN_READONLY == (dwFormatType & WMR_INIT_OPEN_READONLY) )
{
ftlOpenOptions |= WMR_INIT_OPEN_READONLY;
}
nRet = stFtlFunctions.Open(pTotalScts, pdwSectorSize, nandFullRestore, FALSE32, 0, ftlOpenOptions);
if (nRet != FTL_SUCCESS)
{
#ifdef WMR_ERASE_UNIT_WHEN_OPEN_FAIL
if (!bFormatAllowed)
{
EXAM_RTL_PRINT((TEXT("[WMR:ERR] FTL_Open failed\n"),
nSig, WMR_SIGNATURE));
goto fail_readonly;
}
EXAM_RTL_PRINT((TEXT("[WMR:ERR] FTL_Open failed - erasing block 0\n")));
pLowFuncTbl->Erase(0, 0);
#else
EXAM_RTL_PRINT((TEXT("[WMR:ERR] FTL_Open failed\n")));
WMR_BEEP(1000000);
#endif
return WMR_UNRECOVERABLE_ERROR;
}
EXAM_RTL_PRINT((TEXT("[FTL:MSG] FTL_Open [OK]\n")));
return WMR_SUCCESS;
fail_readonly:
EXAM_RTL_PRINT((TEXT("******************************************************************************\n")));
EXAM_RTL_PRINT((TEXT("******************************************************************************\n")));
EXAM_RTL_PRINT((TEXT("AND: NAND initialisation failed due to format mismatch or uninitialised NAND.\n")));
EXAM_RTL_PRINT((TEXT("AND: Please reboot with reformatting enabled.\n")));
EXAM_RTL_PRINT((TEXT("******************************************************************************\n")));
EXAM_RTL_PRINT((TEXT("******************************************************************************\n")));
return WMR_UNRECOVERABLE_ERROR;
}
BOOL32 WMRGetStruct(UInt32 dwStructType, void * pvoidStructBuffer, UInt32 * pdwStructSize)
{
BOOL32 boolRes = FALSE32;
switch(dwStructType)
{
case AND_STRUCT_WMR_VERSION:
{
UInt32 dwSignature = g_flashANDSignature.dwMainSignature;
boolRes = WMR_FILL_STRUCT(pvoidStructBuffer, pdwStructSize, &dwSignature, sizeof(dwSignature));
break;
}
default:
EXAM_ERR_PRINT((TEXT("[WMR:ERR] WMRGetStruct 0x%X is not identified is WMR data struct identifier!\n"), dwStructType));
boolRes = FALSE32;
}
return boolRes;
}
static BOOL32 _andGetStruct(UInt32 dwStructType, void * pvoidStructBuffer, UInt32 * pdwStructSize)
{
BOOL32 boolRes = FALSE32;
if (dwStructType == LOCKDOWN_EXTRACT_ALL)
{
// Mobile Lockdown - Get All Structures
#if AND_COLLECT_STATISTICS
boolRes = ANDExportAllStructs(pvoidStructBuffer, pdwStructSize);
#endif
}
else if (dwStructType == LOCKDOWN_GET_ALL_SIZE)
{
#if AND_COLLECT_STATISTICS
UInt32 *dwAllSize = (UInt32*) pvoidStructBuffer;
if (dwAllSize && pdwStructSize && (*pdwStructSize >= sizeof(UInt32)))
{
// Mobile Lockdown - Get Size
boolRes = ANDExportAllStructs(NULL, dwAllSize);
*pdwStructSize = sizeof(UInt32);
}
else
{
boolRes = FALSE32;
}
#endif
}
else
{
switch (dwStructType & AND_STRUCT_LAYER_MASK)
{
case AND_STRUCT_LAYER_FTL:
{
boolRes = stFtlFunctions.GetStruct(dwStructType, pvoidStructBuffer, pdwStructSize);
break;
}
case AND_STRUCT_LAYER_VFL:
{
boolRes = stVflFunctions.GetStruct(dwStructType, pvoidStructBuffer, pdwStructSize);
break;
}
case AND_STRUCT_LAYER_FIL:
{
boolRes = FIL_GetStruct(dwStructType, pvoidStructBuffer, pdwStructSize);
break;
}
case AND_STRUCT_LAYER_GETALL:
{
#if AND_COLLECT_STATISTICS
if (dwStructType == AND_STRUCT_WMR_EXPORT_ALL)
{
boolRes = ANDExportAllStructs(pvoidStructBuffer, pdwStructSize);
}
else if (dwStructType == AND_STRUCT_WMR_EXPORT_ALL_GET_SIZE)
{
UInt32 *dwStructSizeVal = (UInt32*) pvoidStructBuffer;
if (dwStructSizeVal && pdwStructSize && (*pdwStructSize >= sizeof(UInt32)))
{
boolRes = ANDExportAllStructs(NULL, dwStructSizeVal);
*pdwStructSize = sizeof(UInt32);
}
}
#endif
break;
}
default:
{
EXAM_ERR_PRINT((TEXT("[WMR:ERR] _andGetStruct 0x%X is not identified !\n"), dwStructType));
boolRes = FALSE32;
break;
}
}
}
return boolRes;
}
static BOOL32 _andPerformFunction(UInt32 dwFunctionSelector, void * pvoidStructBuffer, UInt32 * pdwStructSize)
{
switch (dwFunctionSelector)
{
#ifndef AND_READONLY
case _AND_FUNCTION_COMPLETE_EPOCH_UPDATE:
{
WMR_PRINT(ERROR, "Epoch update is deprecated\n");
return FALSE32;
}
case AND_FUNCTION_INDEX_CACHE_UPDATE:
{
BOOL32 boolRes = FALSE32;
if (stFtlFunctions.GetStruct && pdwStructSize)
{
boolRes = stFtlFunctions.GetStruct(dwFunctionSelector, NULL, pdwStructSize);
*pdwStructSize = 0;
}
return boolRes;
}
case AND_FUNCTION_CHANGE_FTL_TYPE:
{
BOOL32 boolRes = FALSE32;
if (stVflFunctions.SetStruct && pdwStructSize)
{
boolRes = stVflFunctions.SetStruct(AND_STRUCT_VFL_NEW_FTLTYPE, pvoidStructBuffer, *pdwStructSize);
}
return boolRes;
}
case AND_FUNCTION_CHANGE_NUM_OF_SUBLKS:
{
BOOL32 boolRes = FALSE32;
if (stVflFunctions.SetStruct && pdwStructSize)
{
boolRes = stVflFunctions.SetStruct(AND_STRUCT_VFL_NEW_NUM_OF_FTL_SUBLKS, pvoidStructBuffer, *pdwStructSize);
}
return boolRes;
}
case AND_FUNCTION_SET_BURNIN_CODE:
{
BOOL32 boolRes = FALSE32;
if (stVflFunctions.SetStruct && pdwStructSize)
{
boolRes = stVflFunctions.SetStruct(AND_STRUCT_VFL_BURNIN_CODE, pvoidStructBuffer, *pdwStructSize);
}
return boolRes;
}
case AND_FUNCTION_ERASE_SIGNATURE:
{
BOOL32 boolRes;
WMR_MEMSET(&g_flashANDSignature, 0, sizeof(ANDDriverSignature));
boolRes = stFPartFunctions.WriteSignature(&g_flashANDSignature, sizeof(ANDDriverSignature));
return boolRes;
}
case AND_FUNCTION_SET_POWER_MODE:
{
BOOL32 boolRes = FALSE32;
if (pdwStructSize)
{
boolRes = FIL_SetStruct(AND_STRUCT_FIL_POWER_MODE, pvoidStructBuffer, *pdwStructSize);
}
return boolRes;
}
case AND_FUNCTION_NEURALIZE:
{
BOOL32 boolRes;
boolRes = stFPartFunctions.Neuralize();
return boolRes;
}
case AND_FUNCTION_SET_TIMINGS:
{
BOOL32 boolRes = FALSE32;
if (pdwStructSize)
{
boolRes = FIL_SetStruct(AND_STRUCT_FIL_SET_TIMINGS, pvoidStructBuffer, *pdwStructSize);
}
return boolRes;
}
case AND_FUNCTION_SAVE_STATS:
{
BOOL32 boolRes = FALSE32;
if(stFtlFunctions.WriteStats)
{
boolRes = stFtlFunctions.WriteStats();
return boolRes;
}
}
#endif // ! AND_READONLY
default:
return FALSE32;
}
}
BOOL32 WMR_CtrlIO(UInt32 dwCtlrIOType, void * pvoidDataBuffer, UInt32 * pdwDataSize)
{
if ((dwCtlrIOType & AND_STRUCT_LAYER_MASK) == AND_STRUCT_LAYER_FUNCTIONAL)
{
return _andPerformFunction(dwCtlrIOType, pvoidDataBuffer, pdwDataSize);
}
else
{
return _andGetStruct(dwCtlrIOType, pvoidDataBuffer, pdwDataSize);
}
}
#if AND_SIMULATOR
void WMR_Close(void)
{
stFtlFunctions.Close();
WMR_MEMSET(&stFtlFunctions, 0, sizeof(FTLFunctions));
stVflFunctions.Close();
WMR_MEMSET(&stVflFunctions, 0, sizeof(VFLFunctions));
stFPartFunctions.Close();
WMR_MEMSET(&stFPartFunctions, 0, sizeof(FPartFunctions));
boolFPartInitialized = FALSE32;
// NirW - using Ram disk - killing FIL is a pain and irrelevant...
// FIL_Close();
// WMR_MEMSET(&stDeviceInfo, 0, sizeof(stDeviceInfo));
}
#endif
FTLFunctions * WMR_GetFTL(void)
{
return &stFtlFunctions;
}
VFLFunctions * WMR_GetVFL(void)
{
return &stVflFunctions;
}
#endif // (!defined(AND_FPART_ONLY) || !AND_FPART_ONLY)