blob: f826a1978c48c33f3944068e12be3e34c6d2f1f3 [file] [log] [blame]
#include <memory.h>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <fstream>
#include <stdarg.h>
using namespace std;
#ifdef HAS_MRVL_FLASH_LDPC_LIB
#include "../../Src/mrvlFlashBCH.h"
#else
#include "bch.h"
#endif
#include "ndPageInfo.h"
#include "buildEccImage.h"
#ifdef HAS_MRVL_FLASH_LDPC_LIB
int binary2hex(int *a, int len);
int binary2hex_rev(int *a, int len);
void bits2symbols_rev(int *bits, int *symbols, int bit_len, int width);
#else
#include "utilities.h"
#define EXP2_CODE_FILE "exp2Int15.txt"
#endif
#define DWORD_SIZE sizeof(int)
#define BCH_PARAM_T 16
#define NDBF_BUS_WIDTH (64/sizeof(char))
bldEccImg::bldEccImg(const char *image) {
char eccImage[256];
this->inputFs.open(image, ios::in|ios::binary);
strcpy(eccImage, image);
strcat(eccImage, ".out");
this->outputFs.open(eccImage, ios::out|ios::trunc|ios::binary);
}
bldEccImg::~bldEccImg() {
this->inputFs.close();
this->outputFs.close();
#ifndef HAS_MRVL_FLASH_LDPC_LIB
delete bchNormChnk;
if (bchLastChnk)
delete bchLastChnk;
#endif
}
void bldEccImg::buildNandEccImage(ndPageInfo *pageAlloc) {
int m = 15; /* GF field degree, Fixed */
int kNorm, kLast;
int i = 0;
ECCTOOL_PRINT("INFO: start building ECC image\n");
kNorm = (pageAlloc->getChunkSz()+ pageAlloc->getChunkSpr())*8; /* encoding data length (bits) for normal chunks */
kLast = (pageAlloc->getLastChunkSz()+ pageAlloc->getLastChunkSpr())*8; /* encoding data length (bits) for last chunks */
this->initBch(m, kNorm, kLast);
while (!this->inputFs.eof()) {
ECCTOOL_PRINT("INFO: populating page %d\n", i);
this->dumpPageData(pageAlloc);
i++;
}
ECCTOOL_PRINT("INFO: end building ECC image\n");
}
void bldEccImg::initBch(int m, int kNorm, int kLast) {
#ifdef HAS_MRVL_FLASH_LDPC_LIB
mrvlCreateFlashBCH();
#else
int p[16] = {1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1}; /* p(x) - Polynomial, Fixed */
char *file = EXP2_CODE_FILE;
GF *gf = new GF2m(m, p, m, file);
this->bchNormChnk = new BCH(gf, 0, BCH_PARAM_T, 1, kNorm);
if (kLast)
this->bchLastChnk = new BCH(gf, 0, BCH_PARAM_T, 1, kLast);
else
this->bchLastChnk = NULL;
delete gf;
#endif
}
void bldEccImg::readInBitStream(int dataSz, int padBytes) {
char dataBuff;
int i, j, k;
ECCTOOL_PRINT("Data In:\n");
for (i = j = k = 0; i < (dataSz+padBytes); i++) {
if (i < dataSz) {
this->inputFs.read(&dataBuff, sizeof(dataBuff));
if (this->inputFs.eof())
dataBuff = 0xff; /* padding data area with '1' */
} else {
dataBuff = 0xff; /* padding spare area with '1' */
}
ECCTOOL_PRINT("%02x ", (unsigned char)dataBuff);
if (j++ == 15) {
ECCTOOL_PRINT("\n");
j = 0;
}
// LittleEndia + LSB
bitStmIn[k++] = (dataBuff & 0x01) ? 1 : 0;
bitStmIn[k++] = (dataBuff & 0x02) ? 1 : 0;
bitStmIn[k++] = (dataBuff & 0x04) ? 1 : 0;
bitStmIn[k++] = (dataBuff & 0x08) ? 1 : 0;
bitStmIn[k++] = (dataBuff & 0x10) ? 1 : 0;
bitStmIn[k++] = (dataBuff & 0x20) ? 1 : 0;
bitStmIn[k++] = (dataBuff & 0x40) ? 1 : 0;
bitStmIn[k++] = (dataBuff & 0x80) ? 1 : 0;
}
ECCTOOL_PRINT("\n");
}
void bldEccImg::writeOutBitStream(int dataSz, int padBytes) {
unsigned int *bitStmOutSym = new unsigned int[dataSz/DWORD_SIZE];
char dataBuff;
int i, j;
bits2symbols_rev(bitStmOut, (int *)bitStmOutSym, dataSz, DWORD_SIZE);
ECCTOOL_PRINT("Data Out:\n");
for (i = 0, j = 0; i < dataSz/DWORD_SIZE; i = i + 2) {
dataBuff = ((bitStmOutSym[i] & 0x0F) << 4) | (bitStmOutSym[i + 1]);
dataBuff = (dataBuff & 0xAA) >> 1 | (dataBuff & 0x55) << 1;
dataBuff = (dataBuff & 0xCC) >> 2 | (dataBuff & 0x33) << 2;
dataBuff = (dataBuff & 0xF0) >> 4 | (dataBuff & 0x0F) << 4;
this->outputFs.write(&dataBuff, sizeof(dataBuff));
ECCTOOL_PRINT("%02x ", (unsigned char)dataBuff);
if (j++ == 15) {
ECCTOOL_PRINT("\n");
j = 0;
}
}
delete [] bitStmOutSym;
dataBuff = 0xFF;
for (i = 0; i < padBytes; i++) {
this->outputFs.write(&dataBuff, sizeof(dataBuff));
ECCTOOL_PRINT("%02x ", (unsigned char)dataBuff);
if (j++ == 15) {
ECCTOOL_PRINT("\n");
j = 0;
}
}
ECCTOOL_PRINT("\n");
}
void bldEccImg::dumpPageData(ndPageInfo *pageAlloc) {
int chnkSz, sprSz, chnkCnt;
int bitStmSzIn, bitStmSzOut;
int padSz;
int i;
int last = (pageAlloc->getLastChunkSz()+ pageAlloc->getLastChunkSpr())*8;
chnkSz = pageAlloc->getChunkSz();
sprSz = pageAlloc->getChunkSpr();
chnkCnt = pageAlloc->getChunkCnt();
bitStmSzIn = (chnkSz + sprSz)*8;
ECCTOOL_PRINT("DEBUG: Code Len = %d \n", bitStmSzIn);
#ifdef HAS_MRVL_FLASH_LDPC_LIB
mrvlInitializeFlashBCH(1, &bitStmSzIn, BCH_PARAM_T);
bitStmSzOut = mrvlGetParityLength();
bitStmSzOut += bitStmSzIn;
ECCTOOL_PRINT("DEBUG: Parity Len = %d \n", bitStmSzOut);
#else
bitStmSzOut = this->bchNormChnk->getN();
#endif
this->bitStmIn = new int[bitStmSzIn];
this->bitStmOut = new int[bitStmSzOut];
padSz = NDBF_BUS_WIDTH - ((bitStmSzOut / (DWORD_SIZE * 2)) % NDBF_BUS_WIDTH);
padSz = (padSz == NDBF_BUS_WIDTH) ? 0 : padSz;
ECCTOOL_PRINT("DEBUG: padding size = %d \n", padSz);
for (i = 0; i < chnkCnt; i++) {
ECCTOOL_PRINT("INFO: calculate ECC bytes - chunk %d/%d \n", i+1, chnkCnt);
this->readInBitStream(chnkSz, sprSz);
#ifdef HAS_MRVL_FLASH_LDPC_LIB
if (mrvlEncodeBCH(this->bitStmIn, this->bitStmOut) == 1)
ECCTOOL_PRINT("ERROR: failed to encode the input bitstream \n");
#else
this->bchNormChnk->encode(this->bitStmIn, this->bitStmOut);
#endif
#ifdef HAS_MRVL_FLASH_LDPC_LIB
if ((i == (chnkCnt - 1)) && (!last))
#else
if ((i == (chnkCnt - 1)) && (this->bchLastChnk == NULL))
#endif
this->writeOutBitStream(bitStmSzOut, padSz);
else
this->writeOutBitStream(bitStmSzOut, 0);
}
delete [] this->bitStmIn;
delete [] this->bitStmOut;
if (last) {
ECCTOOL_PRINT("INFO: calculate ECC bytes - last chunk \n");
bitStmSzIn = last;
ECCTOOL_PRINT("DEBUG: Code Len = %d \n", bitStmSzIn);
#ifdef HAS_MRVL_FLASH_LDPC_LIB
mrvlInitializeFlashBCH(1, &bitStmSzIn, BCH_PARAM_T);
bitStmSzOut = mrvlGetParityLength();
bitStmSzOut += bitStmSzIn;
ECCTOOL_PRINT("DEBUG: Parity Len = %d \n", bitStmSzOut);
#else
bitStmSzOut = this->bchLastChnk->getN();
#endif
this->bitStmIn = new int[bitStmSzIn];
this->bitStmOut = new int[bitStmSzOut];
padSz = NDBF_BUS_WIDTH - ((bitStmSzOut / (DWORD_SIZE * 2)) % NDBF_BUS_WIDTH);
padSz = (padSz == NDBF_BUS_WIDTH) ? 0 : padSz;
ECCTOOL_PRINT("DEBUG: padding size = %d \n", padSz);
this->readInBitStream(chnkSz, sprSz);
#ifdef HAS_MRVL_FLASH_LDPC_LIB
if (mrvlEncodeBCH(this->bitStmIn, this->bitStmOut) == 1)
ECCTOOL_PRINT("ERROR: failed to encode the input bitstream \n");
#else
this->bchLastChnk->encode(this->bitStmIn, this->bitStmOut);
#endif
this->writeOutBitStream(bitStmSzOut, padSz);
delete [] this->bitStmIn;
delete [] this->bitStmOut;
}
}
#ifdef HAS_MRVL_FLASH_LDPC_LIB
int binary2hex(int *a, int len) {
int h = 0, i;
for (i = 0; i < len; i++)
h += a[i] * (1 << i);
return h;
}
int binary2hex_rev(int *a, int len) {
int i, s;
int *tmp = new int[len];
for(i = 0; i < len; i++)
tmp[i] = a[len-1-i];
s = binary2hex(tmp,len);
delete [] tmp;
return s;
}
void bits2symbols_rev(int *bits, int *symbols, int bit_len, int width) {
int i;
for(i = 0; i < bit_len/width; i++)
symbols[i] = binary2hex_rev(bits + i*width, width);
}
#endif