first and last commit
This commit is contained in:
commit
1bf4efd552
2612 files changed
+636500
No files matched your search
@@ -0,0 +1,255 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2009 Apple Inc. All rights reserved.
|
||||
*
|
||||
* This document is the property of Apple Inc.
|
||||
* It is considered confidential and proprietary.
|
||||
*
|
||||
* This document may not be reproduced or transmitted in any form,
|
||||
* in whole or in part, without the express written permission of
|
||||
* Apple Inc.
|
||||
*/
|
||||
|
||||
#include "ANDTypes.h"
|
||||
#include "WMROAM.h"
|
||||
#include "VFLBuffer.h"
|
||||
#include "FPart.h"
|
||||
#include "FPartTypes.h"
|
||||
#include "WMRConfig.h"
|
||||
#include "WMRExam.h"
|
||||
#include "ANDStats.h"
|
||||
|
||||
static VFLFunctions *stVflFunctions;
|
||||
static FTLFunctions *stFtlFunctions;
|
||||
|
||||
typedef BOOL32 (*GetStructFunc)(UInt32 dwStructType, void * pvoidStructBuffer, UInt32 * pdwStructSize);
|
||||
|
||||
typedef struct {
|
||||
UInt32 dwStructLayer;
|
||||
UInt32 dwStructType;
|
||||
UInt32 dwStructVersion;
|
||||
} ExportStructParameters;
|
||||
|
||||
|
||||
static ExportStructParameters astrStructsToExport[] =
|
||||
{
|
||||
// header (must be first)
|
||||
{ 0, AND_STRUCT_WMR_EXPORT_ALL, AND_EXPORT_STRUCTURE_VERSION},
|
||||
|
||||
// WMR Version (FTL & VFL types)
|
||||
{AND_STRUCT_LAYER_WMR, AND_STRUCT_WMR_VERSION, 0},
|
||||
|
||||
// VFL_type
|
||||
{AND_STRUCT_LAYER_VFL, AND_STRUCT_VFL_GET_TYPE, 0},
|
||||
|
||||
// FTL_type ( FTL/yaFTL)
|
||||
{AND_STRUCT_LAYER_FTL, AND_STRUCT_FTL_GET_TYPE, 0},
|
||||
|
||||
// All VFL Meta
|
||||
{AND_STRUCT_LAYER_VFL, AND_STRUCT_VFL_VFLMETA | 0, 0},
|
||||
{AND_STRUCT_LAYER_VFL, AND_STRUCT_VFL_VFLMETA | 1, 0},
|
||||
{AND_STRUCT_LAYER_VFL, AND_STRUCT_VFL_VFLMETA | 2, 0},
|
||||
{AND_STRUCT_LAYER_VFL, AND_STRUCT_VFL_VFLMETA | 3, 0},
|
||||
{AND_STRUCT_LAYER_VFL, AND_STRUCT_VFL_VFLMETA | 4, 0},
|
||||
{AND_STRUCT_LAYER_VFL, AND_STRUCT_VFL_VFLMETA | 5, 0},
|
||||
{AND_STRUCT_LAYER_VFL, AND_STRUCT_VFL_VFLMETA | 6, 0},
|
||||
{AND_STRUCT_LAYER_VFL, AND_STRUCT_VFL_VFLMETA | 7, 0},
|
||||
{AND_STRUCT_LAYER_VFL, AND_STRUCT_VFL_VFLMETA | 8, 0},
|
||||
{AND_STRUCT_LAYER_VFL, AND_STRUCT_VFL_VFLMETA | 9, 0},
|
||||
{AND_STRUCT_LAYER_VFL, AND_STRUCT_VFL_VFLMETA | 10, 0},
|
||||
{AND_STRUCT_LAYER_VFL, AND_STRUCT_VFL_VFLMETA | 11, 0},
|
||||
{AND_STRUCT_LAYER_VFL, AND_STRUCT_VFL_VFLMETA | 12, 0},
|
||||
{AND_STRUCT_LAYER_VFL, AND_STRUCT_VFL_VFLMETA | 13, 0},
|
||||
{AND_STRUCT_LAYER_VFL, AND_STRUCT_VFL_VFLMETA | 14, 0},
|
||||
{AND_STRUCT_LAYER_VFL, AND_STRUCT_VFL_VFLMETA | 15, 0},
|
||||
|
||||
//FTL geometry
|
||||
{AND_STRUCT_LAYER_FTL,AND_STRUCT_FTL_GET_FTL_DEVICEINFO, 0},
|
||||
|
||||
// FTL
|
||||
{AND_STRUCT_LAYER_FTL, AND_STRUCT_FTL_FTLCXT, 0},
|
||||
|
||||
// FTL counters
|
||||
{AND_STRUCT_LAYER_FTL, AND_STRUCT_FTL_GET_FTL_EC_BINS, 1},
|
||||
{AND_STRUCT_LAYER_FTL, AND_STRUCT_FTL_GET_FTL_RC_BINS, 1},
|
||||
|
||||
// FTL - Stat
|
||||
{AND_STRUCT_LAYER_FTL, AND_STRUCT_FTL_STATISTICS, 0},
|
||||
|
||||
// VFL - Stat
|
||||
{AND_STRUCT_LAYER_VFL, AND_STRUCT_VFL_STATISTICS, 0},
|
||||
|
||||
// FIL - Device Info
|
||||
{AND_STRUCT_LAYER_FIL, AND_STRUCT_FIL_DEVICE_INFO, 0},
|
||||
|
||||
// FIL - Stat
|
||||
{AND_STRUCT_LAYER_FIL, AND_STRUCT_FIL_STATISTICS, 0},
|
||||
|
||||
// footer (must be last)
|
||||
{0, AND_STRUCT_WMR_EXPORT_ALL_END, AND_EXPORT_STRUCTURE_VERSION},
|
||||
|
||||
};
|
||||
|
||||
#define AND_DUMP_DEBUG (0)
|
||||
|
||||
#if AND_DUMP_DEBUG
|
||||
#define DUMP_VAR(variable) WMR_PRINT(ALWAYS, "%s : %u\n", #variable, (UInt32)(variable))
|
||||
|
||||
|
||||
static void
|
||||
hexdump(UInt8 *bytes, int count)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
for (i = 0; i < count; i += 16) {
|
||||
kprintf("%04x:", i);
|
||||
for (j = 0; (j < 16) && ((i + j) < count); j++)
|
||||
kprintf(" %02.2x", *bytes++);
|
||||
kprintf("\n");
|
||||
}
|
||||
}
|
||||
#else
|
||||
#define DUMP_VAR(variable)
|
||||
#endif //AND_DUMP_DEBUG
|
||||
|
||||
|
||||
|
||||
static GetStructFunc _translateStructLayer (UInt32 dwStructLayer)
|
||||
{
|
||||
switch (dwStructLayer)
|
||||
{
|
||||
case AND_STRUCT_LAYER_FTL:
|
||||
return stFtlFunctions->GetStruct;
|
||||
case AND_STRUCT_LAYER_VFL:
|
||||
return stVflFunctions->GetStruct;
|
||||
case AND_STRUCT_LAYER_FIL:
|
||||
return FIL_GetStruct;
|
||||
case AND_STRUCT_LAYER_WMR:
|
||||
return WMRGetStruct;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static BOOL32 _appendStructToBuffer(void *pvoidExportBuffer,
|
||||
UInt32 *pdwBufferSize,
|
||||
UInt32 dwStructLayer,
|
||||
UInt32 dwStructType,
|
||||
UInt32 dwStructVersion)
|
||||
{
|
||||
UInt32 dwDataSize;
|
||||
BOOL32 boolResult;
|
||||
GetStructFunc fGetStruct = _translateStructLayer(dwStructLayer);
|
||||
UInt8 *cursor = (UInt8*) pvoidExportBuffer;
|
||||
|
||||
|
||||
DUMP_VAR(pvoidExportBuffer);
|
||||
if (pdwBufferSize)
|
||||
{
|
||||
DUMP_VAR(*pdwBufferSize);
|
||||
}
|
||||
DUMP_VAR(dwStructLayer);
|
||||
DUMP_VAR(dwStructType);
|
||||
DUMP_VAR(dwStructVersion);
|
||||
|
||||
if (fGetStruct)
|
||||
{
|
||||
if (pvoidExportBuffer)
|
||||
{
|
||||
// leave room for the struct header
|
||||
cursor += sizeof(ANDExportStruct);
|
||||
}
|
||||
dwDataSize = pdwBufferSize ? (*pdwBufferSize - sizeof(ANDExportStruct)) : 0;
|
||||
boolResult = fGetStruct(dwStructType, cursor, &dwDataSize);
|
||||
DUMP_VAR(dwDataSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
// for header and footer
|
||||
boolResult = TRUE32;
|
||||
dwDataSize = 0;
|
||||
}
|
||||
|
||||
if (boolResult)
|
||||
{
|
||||
#if AND_DUMP_DEBUG
|
||||
if (pvoidExportBuffer)
|
||||
{
|
||||
hexdump(pvoidExportBuffer, dwDataSize);
|
||||
}
|
||||
#endif
|
||||
if (pdwBufferSize)
|
||||
{
|
||||
*pdwBufferSize = dwDataSize + sizeof(ANDExportStruct);
|
||||
}
|
||||
|
||||
if (pvoidExportBuffer)
|
||||
{
|
||||
ANDExportStruct strExport;
|
||||
|
||||
strExport.dwStructID = dwStructType;
|
||||
strExport.dwStructureVersion = dwStructVersion;
|
||||
strExport.dwDataSize = dwDataSize;
|
||||
strExport.dwIndex = 0; // What is this?
|
||||
|
||||
WMR_MEMCPY(pvoidExportBuffer, &strExport, sizeof(ANDExportStruct));
|
||||
}
|
||||
}
|
||||
else if (pdwBufferSize)
|
||||
{
|
||||
*pdwBufferSize = 0;
|
||||
}
|
||||
|
||||
DUMP_VAR(boolResult);
|
||||
return boolResult;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#define SUB_MIN_ZERO(minuend, subtrahend) (((minuend) > (subtrahend)) ? ((minuend) - (subtrahend)) : 0)
|
||||
|
||||
BOOL32 ANDExportAllStructs(void * pvoidDataBuffer, UInt32 * pdwDataSize)
|
||||
{
|
||||
UInt32 idx;
|
||||
ExportStructParameters *nextStruct;
|
||||
const UInt32 dwNumStructures = sizeof(astrStructsToExport) / sizeof(astrStructsToExport[0]);
|
||||
const UInt32 dwBufferSize = pdwDataSize ? *pdwDataSize : 0;
|
||||
UInt8 *cursor = (UInt8*) pvoidDataBuffer;
|
||||
UInt32 dwBufferRead = 0;
|
||||
UInt32 dwTmpStructSize;
|
||||
|
||||
if (!pdwDataSize)
|
||||
{
|
||||
return FALSE32;
|
||||
}
|
||||
|
||||
// Update globals
|
||||
stVflFunctions = WMR_GetVFL();
|
||||
stFtlFunctions = WMR_GetFTL();
|
||||
|
||||
nextStruct = &astrStructsToExport[0];
|
||||
for (idx = 0; idx < dwNumStructures; ++idx)
|
||||
{
|
||||
dwTmpStructSize = SUB_MIN_ZERO(dwBufferSize, dwBufferRead);
|
||||
_appendStructToBuffer(cursor,
|
||||
&dwTmpStructSize,
|
||||
nextStruct->dwStructLayer,
|
||||
nextStruct->dwStructType,
|
||||
nextStruct->dwStructVersion);
|
||||
nextStruct++;
|
||||
if (cursor)
|
||||
{
|
||||
cursor += dwTmpStructSize;
|
||||
}
|
||||
dwBufferRead += dwTmpStructSize;
|
||||
}
|
||||
|
||||
if (pdwDataSize)
|
||||
{
|
||||
*pdwDataSize = dwBufferRead;
|
||||
}
|
||||
|
||||
// pdwDataSize tells the whole story, always pass
|
||||
return TRUE32;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2009 Apple Inc. All rights reserved.
|
||||
*
|
||||
* This document is the property of Apple Inc.
|
||||
* It is considered confidential and proprietary.
|
||||
*
|
||||
* This document may not be reproduced or transmitted in any form,
|
||||
* in whole or in part, without the express written permission of
|
||||
* Apple Inc.
|
||||
*/
|
||||
|
||||
#include "WMRTypes.h"
|
||||
|
||||
#ifndef _ANDSTATS_H_
|
||||
#define _ANDSTATS_H_
|
||||
|
||||
BOOL32 ANDExportAllStructs(void * pvoidDataBuffer, UInt32 * pdwDataSize);
|
||||
|
||||
#endif //_ANDSTATS_H_
|
||||
|
||||
|
||||
@@ -0,0 +1,1000 @@
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* 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)
|
||||
|
||||
@@ -0,0 +1,136 @@
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* COMPONENT : Rainbow */
|
||||
/* MODULE : Example */
|
||||
/* NAME : Example */
|
||||
/* FILE : WMRExam.h */
|
||||
/* 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 */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
#if (!defined(AND_FPART_ONLY) || !AND_FPART_ONLY)
|
||||
#include "FTL.h"
|
||||
#include "VFL.h"
|
||||
#include "FIL.h"
|
||||
#else
|
||||
#include "FPart.h"
|
||||
#include "FIL.h"
|
||||
#endif
|
||||
|
||||
#ifndef _WMR_EXAM_H_
|
||||
#define _WMR_EXAM_H_
|
||||
|
||||
/*****************************************************************************/
|
||||
/* whimory version signature */
|
||||
// Platform Types
|
||||
#define WMR_PLATFORM_SHIFT (24)
|
||||
#define WMR_PLATFORM_DARWIN ('C')
|
||||
|
||||
// Layout Types
|
||||
#define WMR_LAYOUT_SHIFT (16)
|
||||
#define WMR_LAYOUT_SIMPLE ('0')
|
||||
#define WMR_LAYOUT_VS ('1')
|
||||
|
||||
// VFL types
|
||||
#define WMR_VFL_SHIFT (8)
|
||||
#define WMR_M68_VFL ('0')
|
||||
#define WMR_VSVFL ('1')
|
||||
|
||||
// default signature goes here
|
||||
#define WMR_VFL_SIGNATURE ((WMR_PLATFORM_DARWIN << WMR_PLATFORM_SHIFT) | (WMR_LAYOUT_SIMPLE << WMR_LAYOUT_SHIFT) | (WMR_M68_VFL << 8)) /* 'C0' for P2 */
|
||||
#define WMR_VSVFL_SIGNATURE ((WMR_PLATFORM_DARWIN << WMR_PLATFORM_SHIFT) | (WMR_LAYOUT_SIMPLE << WMR_LAYOUT_SHIFT) | (WMR_VSVFL << 8)) /* 'C0' for P2 */
|
||||
#define WMR_VSVFL_VS_SIGNATURE ((WMR_PLATFORM_DARWIN << WMR_PLATFORM_SHIFT) | (WMR_LAYOUT_VS << WMR_LAYOUT_SHIFT) | (WMR_VSVFL << 8)) /* 'C1' for N72+ */
|
||||
|
||||
#define WMR_SIGNATURE_EPOCH_MASK (0x000000FF)
|
||||
#define WMR_SIGNATURE_VFL_MASK (0x0000FF00)
|
||||
#define WMR_SIGNATURE_LAYOUT_MASK (0x00FF0000)
|
||||
#define WMR_SIGNATURE_PLATFORM_MASK (0xFF000000)
|
||||
// signature bit masks for 2nd ID
|
||||
#define WMR_SIGNATURE_FORMAT_VERSION_MASK (0x0000FFFF)
|
||||
#define WMR_SIGNATURE_METADATA_MASK (0x00010000)
|
||||
|
||||
#define WMR_SIGNATURE_VFL(_x) (UInt8)(((_x) & WMR_SIGNATURE_VFL_MASK) >> WMR_VFL_SHIFT)
|
||||
#define WMR_SIGNATURE_LAYOUT(_x) (UInt8)(((_x) & WMR_SIGNATURE_LAYOUT_MASK) >> WMR_LAYOUT_SHIFT)
|
||||
#define WMR_SIGNATURE_PLATFORM(_x) (UInt8)(((_x) & WMR_SIGNATURE_PLATFORM_MASK) >> WMR_PLATFORM_SHIFT)
|
||||
#define WMR_SIGNATURE_FORMATTING_VERSION(_x) (UInt8)((_x) & WMR_SIGNATURE_FORMAT_VERSION_MASK)
|
||||
#define WMR_SIGNATURE_METADATA(_x) (UInt8)(((_x) & WMR_SIGNATURE_METADATA_MASK) >> WMR_METADATA_SHIFT)
|
||||
|
||||
#define WMR_FORMATTING_VERSION_2 ((UInt32)0x00000002) /* May 20th 2007 */
|
||||
#define WMR_FORMATTING_VERSION_3 ((UInt32)0x00000003) /* August 22nd 2007 */
|
||||
#define WMR_FORMATTING_VERSION_4 ((UInt32)0x00000004) /* July 23rd 2008 */
|
||||
#define WMR_FORMATTING_VERSION_5 ((UInt32)0x00000005) /* Dec 1st 2009 */
|
||||
#define WMR_FORMATTING_VERSION ((UInt32)0x00000006) /* July 30th 2010 */
|
||||
|
||||
// Metadata Whitening
|
||||
#define WMR_METADATA_SHIFT (16)
|
||||
#define WMR_METADATA_WHITENING_NONE ((UInt32)0x0)
|
||||
#define WMR_METADATA_WHITENING ((UInt32)0x1)
|
||||
#define WMR_METADATA_SIGNATURE (WMR_METADATA_WHITENING << WMR_METADATA_SHIFT)
|
||||
|
||||
#define WMR_FORMAT_SUPPORTED(_x) ((_x) <= WMR_FORMATTING_VERSION)
|
||||
|
||||
/* used during epoch updates */
|
||||
#define WMR_TEMP_SIGNATURE (('X' << 24) | ('X' << 16) | ('X' << 8) | ('X' << 0))
|
||||
/* Return value of WMR_XXX() */
|
||||
/*****************************************************************************/
|
||||
#define WMR_SUCCESS ANDErrorCodeOk
|
||||
#define WMR_CRITICAL_ERROR ANDErrorCodeHwErr
|
||||
#define WMR_UNRECOVERABLE_ERROR ANDErrorCodeUserDataErr
|
||||
|
||||
#define WMR_MAX_STR_BUILD_SIZE (256)
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UInt32 dwMainSignature; // main driver version number
|
||||
UInt32 dw2ndId; // to be used for undetifying sub versions
|
||||
UInt8 strBuildInfo[WMR_MAX_STR_BUILD_SIZE]; // kernel / build version that formatted the device
|
||||
} ANDDriverSignature;
|
||||
|
||||
/*****************************************************************************/
|
||||
/* exported function prototype of WMR example */
|
||||
/*****************************************************************************/
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
Int32 WMR_PreInit(UInt32 dwFormatType, UInt32 dwBootAreaSize);
|
||||
|
||||
#if (!defined(AND_FPART_ONLY) || !AND_FPART_ONLY)
|
||||
Int32 WMR_Init(UInt32 *pTotalScts, UInt32 * pdwSectorSize, UInt32 * tmpIndexCache, UInt32 dwFormatType, UInt32 dwBootAreaSize);
|
||||
void WMR_Close(void);
|
||||
BOOL32 WMR_CtrlIO(UInt32 dwCtlrIOType, void * pvoidDataBuffer, UInt32 * pdwDataSize);
|
||||
BOOL32 WMRGetStruct(UInt32 dwStructType, void * pvoidStructBuffer, UInt32 * pdwStructSize);
|
||||
|
||||
FTLFunctions * WMR_GetFTL(void);
|
||||
VFLFunctions * WMR_GetVFL(void);
|
||||
#endif // (!defined(AND_FPART_ONLY) || !AND_FPART_ONLY)
|
||||
|
||||
FPartFunctions * WMR_GetFPart(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* _FTL_H_ */
|
||||
Reference in new issue
Block a user