//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//
// DO NOT REMOVE --- BEGIN 3RD PARTY MICROSOFT LICENSED SOURCE CODE ID --- DO NOT REMOVE
// HTTP://DEALPOINT/SOURCETAG/INFO.ASP?GUID={53074882-9DC5-433F-9348-8ADFF98A72D1}
// DO NOT REMOVE --- END 3RD PARTY MICROSOFT LICENSED SOURCE CODE ID --- DO NOT REMOVE
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Module Name: ECC.C
Abstract: Error Correcting Codes (ECC) module for FLASH Media Drivers
under Windows CE 3.0 (and later). Unfortunately, some types
of FLASH media (i.e. NAND flash) do not necessarily guarantee
data integrity due to the electrical characteristics of the
media. As a result, it is often necessary to use ECC to detect
erroneous data and (hopefully) correct it.
Notes: This code is based on the ECC algorithm publicly available on
Samsung's FLASH media website.
-----------------------------------------------------------------------------*/
#include <windows.h>
#define DATA_BLOCK_LEN 256
#define ECC_BUFF_LEN 6 // 3 bytes per 256 bytes of data
#define UNCORRECTABLE_ERROR 1
#define CORRECTABLE_ERROR 11
UCHAR CountNumberOfOnes(UCHAR num) ;
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function: ECC_ComputeECC()
Description: Computes the error correcting code for the specified data.
Notes: The following implementation uses a Hammming Code to compute
3 bytes of ECC information for every 256 bytes of data. It is
the caller's responsibility to insure the input buffers meet this
constraint...
Returns: Boolean indicating success.
-------------------------------------------------------------------------------*/
BOOL ECC_ComputeECC( LPBYTE pData, DWORD dwDataBuffLen, LPBYTE pECC, DWORD dwECCBuffLen )
{
static UINT i, j, k;
static UCHAR evenParity[16] = {0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0}; // Look-up table (LUT)
static UCHAR dataXOR = 0;
static UCHAR bit0, bit1, bit2, bit3, bit4, bit5, bit6, bit7;
// Column parity terms. NOTE: p subscript denotes "prime" (i.e. P1p = P1')
static UCHAR P1, P2, P4, P1p, P2p, P4p;
// Row parity terms. NOTE: p subscript denotes "prime" (i.e. P8p = P8')
UCHAR P8, P8p, P16, P16p, P32, P32p, P64, P64p, P128, P128p,
P256, P256p, P512, P512p, P1024, P1024p;
//----- 1. Check to make sure the input buffers are legitimate... -----
if((pData == NULL) || (pECC == NULL) || (dwDataBuffLen < DATA_BLOCK_LEN) || (dwECCBuffLen < ECC_BUFF_LEN) )
{
DEBUGMSG(1, (TEXT("FMD:ECC_ComputeECC() - Input buffers are not legitimate!\r\n")));
return FALSE;
}
//----- 2. Segregrate the data buffer into 256 byte blocks and compute ECC info for each block -----
for(j=0,k=0; j<dwDataBuffLen; j+= DATA_BLOCK_LEN)
{
//----- 3. Initialize the ROW parity terms -----
dataXOR = 0;
P8=0; P8p=0; P16=0; P16p=0; P32=0; P32p=0; P64=0; P64p=0;
P128=0; P128p=0; P256=0; P256p=0; P512=0; P512p=0; P1024=0; P1024p=0;
//----- 4. Compute the ROW parity terms P8, P8p, P16, ... P1024p -----
// NOTE: For speedup purposes, the otherwise 9 separate loops are unrolled into 3 large loops...
for(i=j; i<j+DATA_BLOCK_LEN; i+=32)
{
P8p ^= pData[i] ^ pData[i+2] ^ pData[i+4] ^ pData[i+6] ^ pData[i+8] ^ pData[i+10] ^ pData[i+12] ^ pData[i+14]
^ pData[i+16] ^ pData[i+18] ^ pData[i+20] ^ pData[i+22] ^ pData[i+24] ^ pData[i+26] ^ pData[i+28] ^ pData[i+30];
P8 ^= pData[i+1] ^ pData[i+3] ^ pData[i+5] ^ pData[i+7] ^ pData[i+9] ^ pData[i+11] ^ pData[i+13] ^ pData[i+15]
^ pData[i+17] ^ pData[i+19] ^ pData[i+21] ^ pData[i+23] ^ pData[i+25] ^ pData[i+27] ^ pData[i+29] ^ pData[i+31];
P16p ^= pData[i] ^ pData[i+1] ^ pData[i+4] ^ pData[i+5] ^ pData[i+8] ^ pData[i+9] ^ pData[i+12] ^ pData[i+13]
^ pData[i+16] ^ pData[i+17] ^ pData[i+20] ^ pData[i+21] ^ pData[i+24] ^ pData[i+25] ^ pData[i+28] ^ pData[i+29];
P16 ^= pData[i+2] ^ pData[i+3] ^ pData[i+6] ^ pData[i+7] ^ pData[i+10] ^ pData[i+11] ^ pData[i+14] ^ pData[i+15]
^ pData[i+18] ^ pData[i+19] ^ pData[i+22] ^ pData[i+23] ^ pData[i+26] ^ pData[i+27] ^ pData[i+30] ^ pData[i+31];
P32p ^= pData[i] ^ pData[i+1] ^ pData[i+2] ^ pData[i+3] ^ pData[i+8] ^ pData[i+9] ^ pData[i+10] ^ pData[i+11]
^ pData[i+16] ^ pData[i+17] ^ pData[i+18] ^ pData[i+19] ^ pData[i+24] ^ pData[i+25] ^ pData[i+26] ^ pData[i+27];
P32 ^= pData[i+4] ^ pData[i+5] ^ pData[i+6] ^ pData[i+7] ^ pData[i+12] ^ pData[i+13] ^ pData[i+14] ^ pData[i+15]
^ pData[i+20] ^ pData[i+21] ^ pData[i+22] ^ pData[i+23] ^ pData[i+28] ^ pData[i+29] ^ pData[i+30] ^ pData[i+31];
P64p ^= pData[i] ^ pData[i+1] ^ pData[i+2] ^ pData[i+3] ^ pData[i+4] ^ pData[i+5] ^ pData[i+6] ^ pData[i+7]
^ pData[i+16] ^ pData[i+17] ^ pData[i+18] ^ pData[i+19] ^ pData[i+20] ^ pData[i+21] ^ pData[i+22] ^ pData[i+23];
P64 ^= pData[i+8] ^ pData[i+9] ^ pData[i+10] ^ pData[i+11] ^ pData[i+12] ^ pData[i+13] ^ pData[i+14] ^ pData[i+15]
^ pData[i+24] ^ pData[i+25] ^ pData[i+26] ^ pData[i+27] ^ pData[i+28] ^ pData[i+29] ^ pData[i+30] ^ pData[i+31];
P128p ^= pData[i] ^ pData[i+1] ^ pData[i+2] ^ pData[i+3] ^ pData[i+4] ^ pData[i+5] ^ pData[i+6] ^ pData[i+7]
^ pData[i+8] ^ pData[i+9] ^ pData[i+10] ^ pData[i+11] ^ pData[i+12] ^ pData[i+13] ^ pData[i+14] ^ pData[i+15];
P128 ^= pData[i+16] ^ pData[i+17] ^ pData[i+18] ^ pData[i+19] ^ pData[i+20] ^ pData[i+21] ^ pData[i+22] ^ pData[i+23]
^ pData[i+24] ^ pData[i+25] ^ pData[i+26] ^ pData[i+27] ^ pData[i+28] ^ pData[i+29] ^ pData[i+30] ^ pData[i+31];
}
P8p = evenParity[((P8p & 0xF0) >> 4)] ^ evenParity[(P8p & 0x0F)];
P8 = evenParity[((P8 & 0xF0) >> 4)] ^ evenParity[(P8 & 0x0F)];
P16p = evenParity[((P16p & 0xF0) >> 4)] ^ evenParity[(P16p & 0x0F)];
P16 = evenParity[((P16 & 0xF0) >> 4)] ^ evenParity[(P16 & 0x0F)];
P32p = evenParity[((P32p & 0xF0) >> 4)] ^ evenParity[(P32p & 0x0F)];
P32 = evenParity[((P32 & 0xF0) >> 4)] ^ evenParity[(P32 & 0x0F)];
P64p = evenParity[((P64p & 0xF0) >> 4)] ^ evenParity[(P64p & 0x0F)];
P64 = evenParity[((P64 & 0xF0) >> 4)] ^ evenParity[(P64 & 0x0F)];
P128p = evenParity[((P128p & 0xF0) >> 4)] ^ evenParity[(P128p & 0x0F)];
P128 = evenParity[((P128 & 0xF0) >> 4)] ^ evenParity[(P128 & 0x0F)];
for(i=j; i<j+DATA_BLOCK_LEN; i+=128)
{
P256p ^= pData[i] ^ pData[i+1] ^ pData[i+2] ^ pData[i+3] ^ pData[i+4] ^ pData[i+5] ^ pData[i+6] ^ pData[i+7]
^ pData[i+8] ^ pData[i+9] ^ pData[i+10] ^ pData[i+11] ^ pData[i+12] ^ pData[i+13] ^ pData[i+14] ^ pData[i+15]
^ pData[i+16] ^ pData[i+17] ^ pData[i+18] ^ pData[i+19] ^ pData[i+20] ^ pData[i+21] ^ pData[i+22] ^ pData[i+23]
^ pData[i+24] ^ pData[i+25] ^ pData[i+26] ^ pData[i+27] ^ pData[i+28] ^ pData[i+29] ^ pData[i+30] ^ pData[i+31]
^ pData[i+64] ^ pData[i+65] ^ pData[i+66] ^ pData[i+67] ^ pData[i+68] ^ pData[i+69] ^ pData[i+70] ^ pData[i+71]
^ pData[i+72] ^ pData[i+73] ^ pData[i+74] ^ pData[i+75] ^ pData[i+76] ^ pData[i+77] ^ pData[i+78] ^ pData[i+79]
^ pData[i+80] ^ pData[i+81] ^ pData[i+82] ^ pData[i+83] ^ pData[i+84] ^ pData[i+85] ^ pData[i+86] ^ pData[i+87]
^ pData[i+88] ^ pData[i+89] ^ pData[i+90] ^ pData[i+91] ^ pData[i+92] ^ pData[i+93] ^ pData[i+94] ^ pData[i+95];
P256 ^= pData[i+32] ^ pData[i+33] ^ pData[i+34] ^ pData[i+35] ^ pData[i+36] ^