[Skiboot] [PATCH 3/3] external/opal-prd: Use libflash/blocklevel for MTD/file accesses

Cyril Bur cyril.bur at au1.ibm.com
Tue Dec 22 13:45:19 AEDT 2015


pnor.c existed before blocklevel, it is time that this code got updated to
use the available libraries.

Signed-off-by: Cyril Bur <cyril.bur at au1.ibm.com>
---
Putting this patch out there, I haven't tested it. Please let me know what I can do.

 external/opal-prd/Makefile |   2 +-
 external/opal-prd/pnor.c   | 215 +++++++--------------------------------------
 external/opal-prd/pnor.h   |   2 +
 3 files changed, 36 insertions(+), 183 deletions(-)

diff --git a/external/opal-prd/Makefile b/external/opal-prd/Makefile
index ff3fc73..78b24cd 100644
--- a/external/opal-prd/Makefile
+++ b/external/opal-prd/Makefile
@@ -19,7 +19,7 @@ ifndef V
 endif
 
 OBJS = opal-prd.o thunk.o pnor.o i2c.o module.o version.o \
-       blocklevel.o libffs.o libflash.o ecc.o
+       blocklevel.o libffs.o libflash.o ecc.o file.o
 
 all: opal-prd
 
diff --git a/external/opal-prd/pnor.c b/external/opal-prd/pnor.c
index 7c98603..4d9e9b0 100644
--- a/external/opal-prd/pnor.c
+++ b/external/opal-prd/pnor.c
@@ -15,6 +15,8 @@
  */
 
 #include <libflash/libffs.h>
+#include <libflash/file.h>
+
 #include <errno.h>
 
 #include <sys/stat.h>
@@ -32,57 +34,34 @@
 
 int pnor_init(struct pnor *pnor)
 {
-	int rc, fd;
-	struct blocklevel_device *bl;
-	mtd_info_t mtd_info;
+	int rc;
 
 	if (!pnor)
 		return -1;
 
-	/* Open device and ffs */
-	fd = open(pnor->path, O_RDWR);
-	if (fd < 0) {
-		perror(pnor->path);
+	rc = file_init_path(pnor->path, NULL, false, &(pnor->bl));
+	if (rc) {
+		pr_log(LOG_ERR, "PNOR: (libflash) file_init_path() failed");
 		return -1;
 	}
 
-	/* Hack so we can test on non-mtd file descriptors */
-#if defined(__powerpc__)
-	rc = ioctl(fd, MEMGETINFO, &mtd_info);
-	if (rc < 0) {
-		pr_log(LOG_ERR, "PNOR: ioctl failed to get pnor info: %m");
-		goto out;
-	}
-	pnor->size = mtd_info.size;
-	pnor->erasesize = mtd_info.erasesize;
-#else
-	pnor->size = lseek(fd, 0, SEEK_END);
-	if (pnor->size < 0) {
-		perror(pnor->path);
+	rc = blocklevel_get_info(pnor->bl, NULL, &(pnor->size), &(pnor->erasesize));
+	if (rc) {
+		pr_log(LOG_ERR, "PNOR: blocklevel_get_info() failed. Can't use PNOR");
 		goto out;
 	}
-	/* Fake it */
-	pnor->erasesize = 1024;
-#endif
-
-	pr_debug("PNOR: Found PNOR: %d bytes (%d blocks)", pnor->size,
-	       pnor->erasesize);
 
-	rc = file_init(fd, &bl);
+	rc = ffs_init(0, pnor->size, pnor->bl, &pnor->ffsh, 0);
 	if (rc) {
-		pr_log(LOG_ERR, "PNOR: (libflash) file_init() failed");
+		pr_log(LOG_ERR, "PNOR: Failed to open pnor partition table");
 		goto out;
 	}
 
-	rc = ffs_init(0, pnor->size, 0, bl, &pnor->ffsh, 0);
-	if (rc)
-		pr_log(LOG_ERR, "PNOR: Failed to open pnor partition table");
-
-	file_exit(bl);
+	return 0;
 out:
-	close(fd);
-
-	return rc;
+	file_exit_close(pnor->bl);
+	pnor->bl = NULL;
+	return -1;
 }
 
 void pnor_close(struct pnor *pnor)
@@ -93,6 +72,9 @@ void pnor_close(struct pnor *pnor)
 	if (pnor->ffsh)
 		ffs_close(pnor->ffsh);
 
+	if (pnor->bl)
+		file_exit_close(pnor->bl);
+
 	if (pnor->path)
 		free(pnor->path);
 }
@@ -115,159 +97,36 @@ void dump_parts(struct ffs_handle *ffs) {
 	}
 }
 
-static int mtd_write(struct pnor *pnor, int fd, void *data, uint64_t offset,
+static int mtd_write(struct pnor *pnor, void *data, uint64_t offset,
 		     size_t len)
 {
-	int write_start, write_len, start_waste, rc;
-	bool end_waste = false;
-	uint8_t *buf;
-	struct erase_info_user erase;
+	int rc;
 
 	if (len > pnor->size || offset > pnor->size ||
 	    len + offset > pnor->size)
 		return -ERANGE;
 
-	start_waste = offset % pnor->erasesize;
-	write_start = offset - start_waste;
-
-	/* Align size to multiple of block size */
-	write_len = (len + start_waste) & ~(pnor->erasesize - 1);
-	if ((len + start_waste) > write_len) {
-		end_waste = true;
-		write_len += pnor->erasesize;
-	}
-
-	buf = malloc(write_len);
-
-	if (start_waste) {
-		rc = lseek(fd, write_start, SEEK_SET);
-		if (rc < 0) {
-			pr_log(LOG_ERR, "PNOR: lseek write_start(0x%x) "
-					"failed; %m", write_start);
-			goto out;
-		}
-
-		rc = read(fd, buf, pnor->erasesize);
-		if (rc < 0) {
-			pr_log(LOG_ERR, "PNOR: read(0x%x bytes) failed: %m",
-					pnor->erasesize);
-			goto out;
-		}
-	}
-
-	if (end_waste)  {
-		rc = lseek(fd, write_start + write_len - pnor->erasesize,
-			   SEEK_SET);
-		if (rc < 0) {
-			perror("lseek last write block");
-			pr_log(LOG_ERR, "PNOR: lseek last write block(0x%x) "
-					"failed; %m",
-						write_start + write_len -
-						pnor->erasesize);
-			goto out;
-		}
-
-		rc = read(fd, buf + write_len - pnor->erasesize, pnor->erasesize);
-		if (rc < 0) {
-			pr_log(LOG_ERR, "PNOR: read(0x%x bytes) failed: %m",
-					pnor->erasesize);
-			goto out;
-		}
-	}
-
-	/* Put data in the correct spot */
-	memcpy(buf + start_waste, data, len);
-
-	/* Not sure if this is required */
-	rc = lseek(fd, 0, SEEK_SET);
-	if (rc < 0) {
-		pr_log(LOG_NOTICE, "PNOR: lseek(0) failed: %m");
-		goto out;
-	}
-
-	/* Erase */
-	erase.start = write_start;
-	erase.length = write_len;
-
-	rc = ioctl(fd, MEMERASE, &erase);
-	if (rc < 0) {
-		pr_log(LOG_ERR, "PNOR: erase(start 0x%x, len 0x%x) ioctl "
-				"failed: %m", write_start, write_len);
-		goto out;
-	}
-
-	/* Write */
-	rc = lseek(fd, write_start, SEEK_SET);
-	if (rc < 0) {
-		pr_log(LOG_ERR, "PNOR: lseek write_start(0x%x) failed: %m",
-				write_start);
-		goto out;
-	}
-
-	rc = write(fd, buf, write_len);
-	if (rc < 0) {
-		pr_log(LOG_ERR, "PNOR: write(0x%x bytes) failed: %m",
-				write_len);
-		goto out;
-	}
-
-	/* We have succeded, report the requested write size */
-	rc = len;
+	rc = blocklevel_smart_write(pnor->bl, offset, data, len);
+	if (rc)
+		return -errno;
 
-out:
-	free(buf);
-	return rc;
+	return len;
 }
 
-static int mtd_read(struct pnor *pnor, int fd, void *data, uint64_t offset,
+static int mtd_read(struct pnor *pnor, void *data, uint64_t offset,
 		    size_t len)
 {
-	int read_start, read_len, start_waste, rc;
-	int mask = pnor->erasesize - 1;
-	void *buf;
+	int rc;
 
 	if (len > pnor->size || offset > pnor->size ||
 	    len + offset > pnor->size)
 		return -ERANGE;
 
-	/* Align start to erase block size */
-	start_waste = offset % pnor->erasesize;
-	read_start = offset - start_waste;
-
-	/* Align size to multiple of block size */
-	read_len = (len + start_waste) & ~mask;
-	if ((len + start_waste) > read_len)
-		read_len += pnor->erasesize;
-
-	/* Ensure read is not out of bounds */
-	if (read_start + read_len > pnor->size) {
-		pr_log(LOG_ERR, "PNOR: read out of bounds");
-		return -ERANGE;
-	}
-
-	buf = malloc(read_len);
-
-	rc = lseek(fd, read_start, SEEK_SET);
-	if (rc < 0) {
-		pr_log(LOG_ERR, "PNOR: lseek read_start(0x%x) failed: %m",
-				read_start);
-		goto out;
-	}
-
-	rc = read(fd, buf, read_len);
-	if (rc < 0) {
-		pr_log(LOG_ERR, "PNOR: write(offset 0x%x, len 0x%x) "
-				"failed: %m", read_start, read_len);
-		goto out;
-	}
+	rc = blocklevel_read(pnor->bl, offset, data, len);
+	if (rc)
+		return -errno;
 
-	/* Copy data into destination, carefully avoiding the extra data we
-	 * added to align to block size */
-	memcpy(data, buf + start_waste, len);
-	rc = len;
-out:
-	free(buf);
-	return rc;
+	return len;
 }
 
 /* Similar to read(2), this performs partial operations where the number of
@@ -277,7 +136,7 @@ out:
 int pnor_operation(struct pnor *pnor, const char *name, uint64_t offset,
 		   void *data, size_t requested_size, enum pnor_op op)
 {
-	int rc, fd;
+	int rc;
 	uint32_t pstart, psize, idx;
 	int size;
 
@@ -323,18 +182,12 @@ int pnor_operation(struct pnor *pnor, const char *name, uint64_t offset,
 		return -ERANGE;
 	}
 
-	fd = open(pnor->path, O_RDWR);
-	if (fd < 0) {
-		perror(pnor->path);
-		return fd;
-	}
-
 	switch (op) {
 	case PNOR_OP_READ:
-		rc = mtd_read(pnor, fd, data, pstart + offset, size);
+		rc = mtd_read(pnor, data, pstart + offset, size);
 		break;
 	case PNOR_OP_WRITE:
-		rc = mtd_write(pnor, fd, data, pstart + offset, size);
+		rc = mtd_write(pnor, data, pstart + offset, size);
 		break;
 	default:
 		rc  = -EIO;
@@ -350,7 +203,5 @@ int pnor_operation(struct pnor *pnor, const char *name, uint64_t offset,
 				rc, size);
 
 out:
-	close(fd);
-
 	return rc;
 }
diff --git a/external/opal-prd/pnor.h b/external/opal-prd/pnor.h
index 06219dc..729a969 100644
--- a/external/opal-prd/pnor.h
+++ b/external/opal-prd/pnor.h
@@ -2,12 +2,14 @@
 #define PNOR_H
 
 #include <libflash/libffs.h>
+#include <libflash/blocklevel.h>
 
 struct pnor {
 	char			*path;
 	struct ffs_handle	*ffsh;
 	uint32_t		size;
 	uint32_t		erasesize;
+	struct blocklevel_device *bl;
 };
 
 enum pnor_op {
-- 
2.6.4



More information about the Skiboot mailing list