aboutsummaryrefslogtreecommitdiff
path: root/libflash
diff options
context:
space:
mode:
authorCyril Bur <cyril.bur@au1.ibm.com>2016-11-02 17:46:21 +1100
committerStewart Smith <stewart@linux.vnet.ibm.com>2016-11-02 17:54:03 +1100
commitc7e432869d8fdd0f91672bed3976bf096c90b56b (patch)
treef4866872bd99e3540b8c0da4f6967e56b61d3fd9 /libflash
parent6979263e3430763b79490fbbb4f024370f2a32d2 (diff)
downloadskiboot-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.c62
-rw-r--r--libflash/blocklevel.h3
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,