aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoel Stanley <joel@jms.id.au>2015-03-04 17:11:30 +1030
committerJeremy Kerr <jk@ozlabs.org>2015-03-04 22:57:43 +1100
commit5ae13c25766b0025ffab99b9f8622182af2d4b36 (patch)
tree9600cea74c9c55dcd01234bec65561b9de4688d4
parentdddd88034e069ba2c1fe540f1a701d94cd01710e (diff)
downloadskiboot-5ae13c25766b0025ffab99b9f8622182af2d4b36.zip
skiboot-5ae13c25766b0025ffab99b9f8622182af2d4b36.tar.gz
skiboot-5ae13c25766b0025ffab99b9f8622182af2d4b36.tar.bz2
external/opal-prd: Allow partial ops with PNOR API
The PNOR operations will now return the number of bytes successfully written, which may be less than the number of bytes requested, similar to read(2) and write(2). The hostboot interface is updated with this information. The signature does not change. Signed-off-by: Joel Stanley <joel@jms.id.au> Signed-off-by: Jeremy Kerr <jk@ozlabs.org>
-rw-r--r--external/opal-prd/hostboot-interface.h4
-rw-r--r--external/opal-prd/pnor.c32
2 files changed, 26 insertions, 10 deletions
diff --git a/external/opal-prd/hostboot-interface.h b/external/opal-prd/hostboot-interface.h
index 1088178..a518f50 100644
--- a/external/opal-prd/hostboot-interface.h
+++ b/external/opal-prd/hostboot-interface.h
@@ -170,7 +170,7 @@ struct host_interfaces {
* @param[in] i_offset: offset within the partition
* @param[out] o_data: pointer to the data read
* @param[in] i_sizeBytes: size of data to read
- * @retval rc - non-zero on error
+ * @retval rc - number of bytes read, or non-zero on error
* @platform OpenPOWER
*/
int (*pnor_read) ( uint32_t i_proc, const char* i_partitionName,
@@ -183,7 +183,7 @@ struct host_interfaces {
* @param[in] i_offset: offset withing the partition
* @param[in] i_data: pointer to the data to write
* @param[in] i_sizeBytes: size of data to write
- * @retval rc - non-zero on error
+ * @retval rc - number of bytes written, or non-zero on error
* @platform OpenPOWER
*/
int (*pnor_write) ( uint32_t i_proc, const char* i_partitionName,
diff --git a/external/opal-prd/pnor.c b/external/opal-prd/pnor.c
index e5609fe..e40d292 100644
--- a/external/opal-prd/pnor.c
+++ b/external/opal-prd/pnor.c
@@ -240,11 +240,16 @@ out:
return rc;
}
+/* Similar to read(2), this performs partial operations where the number of
+ * bytes read/written may be less than size.
+ *
+ * Returns number of bytes written, or a negative value on failure. */
int pnor_operation(struct pnor *pnor, const char *name, uint64_t offset,
- void *data, size_t size, enum pnor_op op)
+ void *data, size_t requested_size, enum pnor_op op)
{
int rc, fd;
uint32_t pstart, psize, idx;
+ int size;
if (!pnor->ffsh) {
warnx("PNOR: ffs not initialised");
@@ -263,9 +268,23 @@ int pnor_operation(struct pnor *pnor, const char *name, uint64_t offset,
return -ENOENT;
}
- if (size > psize || offset > psize || size + offset > psize) {
- warnx("PNOR: offset (%ld) or size (%ld) out of bounds (%d)",
- offset, size, psize);
+ if (offset > psize) {
+ warnx("PNOR: offset (%ld) out of bounds (%d)", offset, psize);
+ return -ERANGE;
+ }
+
+ /* Large requests are trimmed */
+ if (requested_size > psize)
+ size = psize;
+ else
+ size = requested_size;
+
+ if (size + offset > psize)
+ size = psize - offset;
+
+ if (size < 0) {
+ warnx("PNOR: size (%zd) and offset (%ld) out of bounds (%d)",
+ requested_size, offset, psize);
return -ERANGE;
}
@@ -297,11 +316,8 @@ int pnor_operation(struct pnor *pnor, const char *name, uint64_t offset,
if (rc < 0)
warn("PNOR: MTD operation failed");
else if (rc != size)
- warnx("PNOR: mtd operation returned %d, expected %zd",
+ warnx("PNOR: mtd operation returned %d, expected %d",
rc, size);
- else
- rc = 0;
-
out:
close(fd);