diff options
author | Cyril Bur <cyril.bur@au1.ibm.com> | 2016-11-02 17:46:21 +1100 |
---|---|---|
committer | Stewart Smith <stewart@linux.vnet.ibm.com> | 2016-11-02 17:54:03 +1100 |
commit | c7e432869d8fdd0f91672bed3976bf096c90b56b (patch) | |
tree | f4866872bd99e3540b8c0da4f6967e56b61d3fd9 /libflash | |
parent | 6979263e3430763b79490fbbb4f024370f2a32d2 (diff) | |
download | skiboot-c7e432869d8fdd0f91672bed3976bf096c90b56b.zip skiboot-c7e432869d8fdd0f91672bed3976bf096c90b56b.tar.gz skiboot-c7e432869d8fdd0f91672bed3976bf096c90b56b.tar.bz2 |
core/flash: Don't do anything clever for OPAL_FLASH_{READ, WRITE, ERASE}
These OPAL calls are exposing the host flash chip to linux as a flash
device. The host is expected to understand that it is raw flash and use
it appropriately, it isn't skiboots place to strip ecc bytes or perform
erase before writes.
Over the course of other developments blocklevel has gotten quite clever
but in this case the cleverness is inappropriate.
Fixes: https://github.com/open-power/skiboot/issues/44
Signed-off-by: Cyril Bur <cyril.bur@au1.ibm.com>
Signed-off-by: Stewart Smith <stewart@linux.vnet.ibm.com>
Diffstat (limited to 'libflash')
-rw-r--r-- | libflash/blocklevel.c | 62 | ||||
-rw-r--r-- | libflash/blocklevel.h | 3 |
2 files changed, 46 insertions, 19 deletions
diff --git a/libflash/blocklevel.c b/libflash/blocklevel.c index b827045..c18de1f 100644 --- a/libflash/blocklevel.c +++ b/libflash/blocklevel.c @@ -78,11 +78,9 @@ static int release(struct blocklevel_device *bl) return rc; } -int blocklevel_read(struct blocklevel_device *bl, uint64_t pos, void *buf, uint64_t len) +int blocklevel_raw_read(struct blocklevel_device *bl, uint64_t pos, void *buf, uint64_t len) { int rc; - struct ecc64 *buffer; - uint64_t ecc_len = ecc_buffer_size(len); if (!bl || !bl->read || !buf) { errno = EINVAL; @@ -93,12 +91,27 @@ int blocklevel_read(struct blocklevel_device *bl, uint64_t pos, void *buf, uint6 if (rc) return rc; - if (!ecc_protected(bl, pos, len)) { - rc = bl->read(bl, pos, buf, len); - release(bl); - return rc; + rc = bl->read(bl, pos, buf, len); + + release(bl); + + return rc; +} + +int blocklevel_read(struct blocklevel_device *bl, uint64_t pos, void *buf, uint64_t len) +{ + int rc; + struct ecc64 *buffer; + uint64_t ecc_len = ecc_buffer_size(len); + + if (!bl || !buf) { + errno = EINVAL; + return FLASH_ERR_PARM_ERROR; } + if (!ecc_protected(bl, pos, len)) + return blocklevel_raw_read(bl, pos, buf, len); + buffer = malloc(ecc_len); if (!buffer) { errno = ENOMEM; @@ -106,7 +119,7 @@ int blocklevel_read(struct blocklevel_device *bl, uint64_t pos, void *buf, uint6 goto out; } - rc = bl->read(bl, pos, buffer, ecc_len); + rc = blocklevel_raw_read(bl, pos, buffer, ecc_len); if (rc) goto out; @@ -116,16 +129,14 @@ int blocklevel_read(struct blocklevel_device *bl, uint64_t pos, void *buf, uint6 } out: - release(bl); free(buffer); return rc; } -int blocklevel_write(struct blocklevel_device *bl, uint64_t pos, const void *buf, uint64_t len) +int blocklevel_raw_write(struct blocklevel_device *bl, uint64_t pos, + const void *buf, uint64_t len) { int rc; - struct ecc64 *buffer; - uint64_t ecc_len = ecc_buffer_size(len); if (!bl || !bl->write || !buf) { errno = EINVAL; @@ -136,12 +147,28 @@ int blocklevel_write(struct blocklevel_device *bl, uint64_t pos, const void *buf if (rc) return rc; - if (!ecc_protected(bl, pos, len)) { - rc = bl->write(bl, pos, buf, len); - release(bl); - return rc; + rc = bl->write(bl, pos, buf, len); + + release(bl); + + return rc; +} + +int blocklevel_write(struct blocklevel_device *bl, uint64_t pos, const void *buf, + uint64_t len) +{ + int rc; + struct ecc64 *buffer; + uint64_t ecc_len = ecc_buffer_size(len); + + if (!bl || !buf) { + errno = EINVAL; + return FLASH_ERR_PARM_ERROR; } + if (!ecc_protected(bl, pos, len)) + return blocklevel_raw_write(bl, pos, buf, len); + buffer = malloc(ecc_len); if (!buffer) { errno = ENOMEM; @@ -155,10 +182,9 @@ int blocklevel_write(struct blocklevel_device *bl, uint64_t pos, const void *buf goto out; } - rc = bl->write(bl, pos, buffer, ecc_len); + rc = blocklevel_raw_write(bl, pos, buffer, ecc_len); out: - release(bl); free(buffer); return rc; } diff --git a/libflash/blocklevel.h b/libflash/blocklevel.h index ddec1dd..09f0096 100644 --- a/libflash/blocklevel.h +++ b/libflash/blocklevel.h @@ -57,8 +57,9 @@ struct blocklevel_device { struct blocklevel_range ecc_prot; }; - +int blocklevel_raw_read(struct blocklevel_device *bl, uint64_t pos, void *buf, uint64_t len); int blocklevel_read(struct blocklevel_device *bl, uint64_t pos, void *buf, uint64_t len); +int blocklevel_raw_write(struct blocklevel_device *bl, uint64_t pos, const void *buf, uint64_t len); int blocklevel_write(struct blocklevel_device *bl, uint64_t pos, const void *buf, uint64_t len); int blocklevel_erase(struct blocklevel_device *bl, uint64_t pos, uint64_t len); int blocklevel_get_info(struct blocklevel_device *bl, const char **name, uint64_t *total_size, |