[Skiboot] [PATCH 2/3] external/opal-prd: Allow partial ops with PNOR API

Joel Stanley joel at jms.id.au
Wed Mar 4 17:42:18 AEDT 2015


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 at jms.id.au>
---
 external/opal-prd/hostboot-interface.h |  4 ++--
 external/opal-prd/pnor.c               | 32 ++++++++++++++++++++++++--------
 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);
-- 
2.1.4



More information about the Skiboot mailing list