aboutsummaryrefslogtreecommitdiff
path: root/external
diff options
context:
space:
mode:
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);