aboutsummaryrefslogtreecommitdiff
path: root/external
diff options
context:
space:
mode:
authorJoel Stanley <joel@jms.id.au>2015-03-04 17:12:18 +1030
committerStewart Smith <stewart@linux.vnet.ibm.com>2015-03-05 15:00:52 +1100
commit118cc8c219eb30f0e729576521a1dbb03cf0b98f (patch)
treee146bdcedafcf0bb79a778810540178f6c362c0b /external
parent9be776ba8bc5579232481fad2f81602d57af934f (diff)
downloadskiboot-118cc8c219eb30f0e729576521a1dbb03cf0b98f.zip
skiboot-118cc8c219eb30f0e729576521a1dbb03cf0b98f.tar.gz
skiboot-118cc8c219eb30f0e729576521a1dbb03cf0b98f.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: Stewart Smith <stewart@linux.vnet.ibm.com>
Diffstat (limited to 'external')
-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);