int blocklevel_read(struct blocklevel_device *bl, uint32_t pos, void *buf, uint32_t len) { int rc; struct ecc64 *buffer; uint32_t ecc_len = ecc_buffer_size(len); if (!bl || !bl->read || !buf) { errno = EINVAL; return FLASH_ERR_PARM_ERROR; } if (!ecc_protected(bl, pos, len)) { return bl->read(bl, pos, buf, len); } buffer = malloc(ecc_len); if (!buffer) { errno = ENOMEM; return FLASH_ERR_MALLOC_FAILED; } rc = bl->read(bl, pos, buffer, ecc_len); if (rc) goto out; if (memcpy_from_ecc(buf, buffer, len)) { errno = EBADF; rc = FLASH_ERR_ECC_INVALID; } out: free(buffer); return rc; }
/* * This provides a wrapper around flash_read on ECCed data * len is length of data without ECC attached */ int flash_read_corrected(struct blocklevel_device *bl, uint32_t pos, void *buf, uint32_t len, bool ecc) { struct ecc64 *bufecc; uint32_t copylen; int rc; uint8_t ret; if (!ecc) return flash_read(bl, pos, buf, len); /* Copy the buffer in chunks */ bufecc = malloc(ecc_buffer_size(COPY_BUFFER_LENGTH)); if (!bufecc) return FLASH_ERR_MALLOC_FAILED; while (len > 0) { /* What's left to copy? */ copylen = MIN(len, COPY_BUFFER_LENGTH); /* Read ECCed data from flash */ rc = flash_read(bl, pos, bufecc, ecc_buffer_size(copylen)); if (rc) goto err; /* Extract data from ECCed data */ ret = memcpy_from_ecc(buf, bufecc, copylen); if (ret) { rc = FLASH_ERR_ECC_INVALID; goto err; } /* Update for next copy */ len -= copylen; buf = (uint8_t *)buf + copylen; pos += ecc_buffer_size(copylen); } rc = 0; err: free(bufecc); return rc; }