/**
 * \brief  Read the data and/or spare of a page of a NAND Flash 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 nand_flash_ecc 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
 * NAND_COMMON_ERROR_CORRUPTEDDATA or ...
 */
uint32_t nand_flash_ecc_read_page(const struct nand_flash_ecc *ecc,
		uint16_t block, uint16_t page, uint8_t *data, uint8_t *spare)
{
	uint32_t error;

	uint8_t hamming_code[NAND_COMMON_MAX_SPARE_ECC_BYTES];
	uint8_t spare_buffer[NAND_COMMON_MAX_PAGE_SPARE_SIZE];

	uint16_t page_data_size
		= nand_flash_model_get_page_data_size(MODEL(ecc));

	/* if no buffer provided, use a temp one */
	if (!spare) {
		spare = spare_buffer;
	}

	memset(spare, 0xFF, NAND_COMMON_MAX_PAGE_SPARE_SIZE);

	/* Start by reading the spare and the data */
	nand_flash_raw_read_page(RAW(ecc), block, page, data, spare);

	/* Retrieve ECC information from page and verify the data */
	nand_flash_spare_scheme_read_ecc(nand_flash_model_get_scheme(MODEL(ecc)),
			spare, hamming_code);
	error = hamming_verify_256x(data, page_data_size, hamming_code);
	if (error && (error != HAMMING_ERROR_SINGLE_BIT)) {
		return NAND_COMMON_ERROR_CORRUPTEDDATA;
	}

	return 0;
}
/**
 * \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 nand  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
 * NAND_ERROR_CORRUPTEDDATA or ...
 */
static uint8_t ecc_read_page_with_swecc(const struct _nand_flash *nand,
		uint16_t block, uint16_t page, void *data, void *spare)
{
	uint8_t error;
	uint8_t hamming[NAND_MAX_SPARE_ECC_BYTES];
	uint16_t page_data_size = nand_model_get_page_data_size(&nand->model);
	uint8_t page_spare_size = nand_model_get_page_spare_size(&nand->model);

	/* Start by reading the spare data */
	error = nand_raw_read_page(nand, block, page, NULL, spare_buf);
	if (error) {
		trace_error("nand_ecc_read_page: Failed to read page\r\n");
		return error;
	}

	/* Then reading the data */
	error = nand_raw_read_page(nand, block, page, data, NULL);
	if (error) {
		trace_error("nand_ecc_read_page: Failed to read page\r\n");
		return error;
	}

	/* Retrieve ECC information from page and verify the data */
	nand_spare_scheme_read_ecc(nand_model_get_scheme(&nand->model),
					spare_buf, hamming);
	error = hamming_verify_256x(data, page_data_size, hamming);
	if (error && (error != HAMMING_ERROR_SINGLEBIT)) {
		trace_error("nand_ecc_read_page: at B%d.P%d Unrecoverable data\r\n",
					block, page);
		return NAND_ERROR_CORRUPTEDDATA;
	}
	if (spare) {
		memcpy(spare, spare_buf, page_spare_size);
	}
	return 0;
}