//------------------------------------------------------------------------------ /// Reads the data and/or spare of a page of a nandflash chip, and verify that /// the data is valid using the ECC information contained in the spare. If one /// buffer pointer is 0, the corresponding area is not saved. /// Returns 0 if the data has been read and is valid; otherwise returns either /// NandCommon_ERROR_CORRUPTEDDATA or ... /// \param ecc Pointer to an EccNandFlash instance. /// \param block Number of block to read from. /// \param page Number of page to read inside given block. /// \param data Data area buffer. /// \param spare Spare area buffer. //------------------------------------------------------------------------------ unsigned char EccNandFlash_ReadPage( const struct EccNandFlash *ecc, unsigned short block, unsigned short page, void *data, void *spare) { unsigned char tmpSpare[NandCommon_MAXPAGESPARESIZE]; unsigned char error; #ifndef HARDWARE_ECC unsigned char tmpData[NandCommon_MAXPAGEDATASIZE]; unsigned char hamming[NandCommon_MAXSPAREECCBYTES]; #else unsigned char hsiaoInSpare[NandCommon_MAXSPAREECCBYTES]; unsigned char hsiao[NandCommon_MAXSPAREECCBYTES]; #endif unsigned char tmpNoEcc; unsigned short pageDataSize = NandFlashModel_GetPageDataSize(MODEL(ecc)); unsigned char pageSpareSize = NandFlashModel_GetPageSpareSize(MODEL(ecc)); TRACE_DEBUG("EccNandFlash_ReadPage(B#%d:P#%d)\n\r", block, page); #ifndef HARDWARE_ECC // Start by reading the spare data error = RawNandFlash_ReadPage(RAW(ecc), block, page, 0, tmpSpare); if (error) { TRACE_ERROR("EccNandFlash_ReadPage: Failed to read page\n\r"); return error; } // Then reading the data error = RawNandFlash_ReadPage(RAW(ecc), block, page, tmpData, 0); if (error) { TRACE_ERROR("EccNandFlash_ReadPage: Failed to read page\n\r"); return error; } tmpNoEcc = EccNandlfash_GetNoECC(); if(!tmpNoEcc){ // Retrieve ECC information from page and verify the data NandSpareScheme_ReadEcc(NandFlashModel_GetScheme(MODEL(ecc)), tmpSpare, hamming); error = Hamming_Verify256x(tmpData, pageDataSize, hamming); } #else // Start by reading the spare area // Note: Can't read data and spare at the same time, otherwise, the ECC parity generation will be incorrect. error = RawNandFlash_ReadPage(RAW(ecc), block, page, 0, tmpSpare); if (error) { TRACE_ERROR("EccNandFlash_ReadPage: $page %d.%d\n\r", block, page); return error; } // Retrieve ECC information from page and verify the data NandSpareScheme_ReadEcc(NandFlashModel_GetScheme(MODEL(ecc)), tmpSpare, hsiaoInSpare); // Reading the main data area error = RawNandFlash_ReadPage(RAW(ecc), block, page, (unsigned char*)data, 0); if (error) { TRACE_ERROR("EccNandFlash_ReadPage: $page %d.%d\n\r", block, page); return error; } HSMC4_GetEccParity(pageDataSize, hsiao, NandFlashModel_GetDataBusWidth(MODEL(ecc))); error = HSMC4_VerifyHsiao((unsigned char*) data, pageDataSize, hsiaoInSpare, hsiao, NandFlashModel_GetDataBusWidth(MODEL(ecc))); #endif if (error && (error != Hamming_ERROR_SINGLEBIT) && (!tmpNoEcc)) { TRACE_ERROR("EccNandFlash_ReadPage: at B%d.P%d Unrecoverable data\n\r", block, page); return NandCommon_ERROR_CORRUPTEDDATA; } #ifndef HARDWARE_ECC // Copy data and/or spare into final buffers if (data) { memcpy(data, tmpData, pageDataSize); } if (spare) { memcpy(spare, tmpSpare, pageSpareSize); } #else if (spare) { memcpy(spare, tmpSpare, pageSpareSize); } #endif return 0; }
//------------------------------------------------------------------------------ /// Reads the data and/or spare of a page of a nandflash chip, and verify that /// the data is valid using the ECC information contained in the spare. If one /// buffer pointer is 0, the corresponding area is not saved. /// Returns 0 if the data has been read and is valid; otherwise returns either /// NandCommon_ERROR_CORRUPTEDDATA or ... /// \param ecc Pointer to an EccNandFlash instance. /// \param block Number of block to read from. /// \param page Number of page to read inside given block. /// \param data Data area buffer. /// \param spare Spare area buffer. //------------------------------------------------------------------------------ unsigned char EccNandFlash_ReadPage( struct EccNandFlash *ecc, unsigned short block, unsigned short page, void *data, void *spare) { unsigned char error; unsigned short pageDataSize = NandFlashModel_GetPageDataSize(MODEL(ecc)); unsigned char pageSpareSize = NandFlashModel_GetPageSpareSize(MODEL(ecc)); unsigned char *pDataBuffer; unsigned char *pSpareBuffer; TRACE_DEBUG("EccNandFlash_ReadPage(B#%d:P#%d)\n\r", block, page); pDataBuffer = (data) ? data : RawNandFlash_GetDataBuffer(RAW(ecc)); pSpareBuffer = (spare) ? spare : RawNandFlash_GetSpareBuffer(RAW(ecc)); #ifndef HARDWARE_ECC // Start by reading the spare and the data error = RawNandFlash_ReadPage(RAW(ecc), block, page, pDataBuffer, pSpareBuffer); if (error) { TRACE_ERROR("EccNandFlash_ReadPage: $page %d.%d\n\r", block, page); goto error; } // Retrieve ECC information from page and verify the data NandSpareScheme_ReadEcc(NandFlashModel_GetScheme(MODEL(ecc)), pSpareBuffer, ecc->hamming); error = Hamming_Verify256x(pDataBuffer, pageDataSize, ecc->hamming); #else error = RawNandFlash_ReadPage(RAW(ecc), block, page, (unsigned char*)data, tmpSpare); if (error) { TRACE_ERROR("EccNandFlash_ReadPage: $page %d.%d\n\r", block, page); goto error; } // Retrieve ECC information from page NandSpareScheme_ReadEcc(NandFlashModel_GetScheme(MODEL(ecc)), tmpSpare, ecc->hsiaoInSpare); HSMC4_GetEccParity(pageDataSize, hsiao, NandFlashModel_GetDataBusWidth(MODEL(ecc))); // Verify the data error = HSMC4_VerifyHsiao((unsigned char*) data, pageDataSize, ecc->hsiaoInSpare, ecc->hsiao, NandFlashModel_GetDataBusWidth(MODEL(ecc))); #endif if (error && (error != Hamming_ERROR_SINGLEBIT)) { error = NandCommon_ERROR_CORRUPTEDDATA; TRACE_ERROR("EccNandFlash_ReadPage: $page %d.%d\n\r", block, page); goto error; } #ifndef HARDWARE_ECC #else if (spare) { memcpy(spare, pSpareBuffer, pageSpareSize); } #endif error: if (data == (unsigned char *) 0) RawNandFlash_ReleaseDataBuffer(RAW(ecc)); if (spare == (unsigned char *) 0) RawNandFlash_ReleaseSpareBuffer(RAW(ecc)); return error; }
/** * \brief Reads the data and/or spare of a page of a nandflash chip, and verify that * the data is valid using the ECC information contained in the spare. If one * buffer pointer is 0, the corresponding area is not saved. * \param ecc Pointer to an EccNandFlash instance. * \param block Number of block to read from. * \param page Number of page to read inside given block. * \param data Data area buffer. * \param spare Spare area buffer. * \return 0 if the data has been read and is valid; otherwise returns either * NandCommon_ERROR_CORRUPTEDDATA or ... */ unsigned char EccNandFlash_ReadPage( const struct EccNandFlash *ecc, unsigned short block, unsigned short page, void *data, void *spare) { unsigned char tmpSpare[NandCommon_MAXPAGESPARESIZE]; unsigned char error; #ifndef HARDWARE_ECC // unsigned char tmpData[NandCommon_MAXPAGEDATASIZE]; unsigned char hamming[NandCommon_MAXSPAREECCBYTES]; #else unsigned char hsiaoInSpare[NandCommon_MAXSPAREECCBYTES]; unsigned char hsiao[NandCommon_MAXSPAREECCBYTES]; #endif unsigned short pageDataSize = NandFlashModel_GetPageDataSize(MODEL(ecc)); unsigned char pageSpareSize = NandFlashModel_GetPageSpareSize(MODEL(ecc)); TRACE_DEBUG("EccNandFlash_ReadPage(B#%d:P#%d)\n\r", block, page); #ifndef HARDWARE_ECC /* Start by reading the spare and the data */ error = RawNandFlash_ReadPage(RAW(ecc), block, page, gdwNandFlashTempBuffer, tmpSpare); if (error) { TRACE_ERROR("EccNandFlash_ReadPage: Failed to read page\n\r"); return error; } /* Retrieve ECC information from page and verify the data */ NandSpareScheme_ReadEcc(NandFlashModel_GetScheme(MODEL(ecc)), tmpSpare, hamming); error = Hamming_Verify256x(gdwNandFlashTempBuffer, pageDataSize, hamming); #else error = RawNandFlash_ReadPage(RAW(ecc), block, page, (unsigned char*)data, tmpSpare); if (error) { TRACE_ERROR("EccNandFlash_ReadPage: $page %d.%d\n\r", block, page); return error; } /* Retrieve ECC information from page */ NandSpareScheme_ReadEcc(NandFlashModel_GetScheme(MODEL(ecc)), tmpSpare, hsiaoInSpare); HSMC4_GetEccParity(pageDataSize, hsiao, NandFlashModel_GetDataBusWidth(MODEL(ecc))); /* Verify the data */ error = HSMC4_VerifyHsiao((unsigned char*) data, pageDataSize, hsiaoInSpare, hsiao, NandFlashModel_GetDataBusWidth(MODEL(ecc))); #endif if (error && (error != Hamming_ERROR_SINGLEBIT)) { TRACE_ERROR("EccNandFlash_ReadPage: at B%d.P%d Unrecoverable data\n\r", block, page); return NandCommon_ERROR_CORRUPTEDDATA; } #ifndef HARDWARE_ECC /* Copy data and/or spare into final buffers */ if (data) { memcpy(data, gdwNandFlashTempBuffer, pageDataSize); } if (spare) { memcpy(spare, tmpSpare, pageSpareSize); } #else if (spare) { memcpy(spare, tmpSpare, pageSpareSize); } #endif return 0; }