summaryrefslogtreecommitdiffstats
path: root/external
diff options
context:
space:
mode:
authorCyril Bur <cyril.bur@au1.ibm.com>2016-01-04 13:23:10 +1100
committerStewart Smith <stewart@linux.vnet.ibm.com>2016-01-15 15:04:57 +1100
commit748e38b6203f5e4bc3552e9ec9ae5fc85ca723d8 (patch)
tree52e1a59c055420e2519e61636a82fd12c5ae6349 /external
parent77b97a12d91cfd7ffe23276dea35c401e8989f73 (diff)
downloadtalos-skiboot-748e38b6203f5e4bc3552e9ec9ae5fc85ca723d8.tar.gz
talos-skiboot-748e38b6203f5e4bc3552e9ec9ae5fc85ca723d8.zip
external/opal-prd: Use libflash/blocklevel for MTD/file accesses
pnor.c existed before blocklevel, it is time that this code got updated to use the available libraries. Changes include using the blocklevel accessors for MTD reads and writes rather than read() and write() on a file descriptor. This patch also makes use of the arch_flash_init() auto detection of the /dev/mtd device which corresponds to the MTD device exposed by skiboot for access to platform flash. Signed-off-by: Cyril Bur <cyril.bur@au1.ibm.com> Signed-off-by: Stewart Smith <stewart@linux.vnet.ibm.com>
Diffstat (limited to 'external')
-rw-r--r--external/common/rules.mk2
-rw-r--r--external/opal-prd/Makefile27
-rw-r--r--external/opal-prd/opal-prd.c12
-rw-r--r--external/opal-prd/pnor.c215
-rw-r--r--external/opal-prd/pnor.h2
5 files changed, 60 insertions, 198 deletions
diff --git a/external/common/rules.mk b/external/common/rules.mk
index 356c2076..81adddde 100644
--- a/external/common/rules.mk
+++ b/external/common/rules.mk
@@ -42,7 +42,7 @@ arch_clean:
$(ARCH_SRC): | common
$(ARCH_OBJS): common-%.o: common/%.c
- $(Q_CC)$(CROSS_COMPILE)gcc $(CFLAGS) -c $< -o $@
+ $(Q_CC)$(CROSS_COMPILE)gcc $(CFLAGS) $(CPPFLAGS) -c $< -o $@
common-arch_flash.o: $(ARCH_OBJS)
$(Q_LD)$(CROSS_COMPILE)ld $(LDFLAGS) -r $(ARCH_OBJS) -o $@
diff --git a/external/opal-prd/Makefile b/external/opal-prd/Makefile
index ff3fc73d..98c7b482 100644
--- a/external/opal-prd/Makefile
+++ b/external/opal-prd/Makefile
@@ -10,6 +10,11 @@ sbindir = $(prefix)/sbin
datadir = $(prefix)/share
mandir = $(datadir)/man
+all: opal-prd
+
+GET_ARCH = ../../external/common/get_arch.sh
+include ../../external/common/rules.mk
+
# Use make V=1 for a verbose build.
ifndef V
Q_CC= @echo ' CC ' $@;
@@ -18,12 +23,14 @@ ifndef V
Q_MKDIR=@echo ' MKDIR ' $@;
endif
-OBJS = opal-prd.o thunk.o pnor.o i2c.o module.o version.o \
- blocklevel.o libffs.o libflash.o ecc.o
+LIBFLASH_OBJS = libflash-blocklevel.o libflash-libffs.o \
+ libflash-libflash.o libflash-ecc.o \
+ libflash-file.o
-all: opal-prd
+OBJS = opal-prd.o thunk.o pnor.o i2c.o module.o version.o \
+ $(LIBFLASH_OBJS) common-arch_flash.o
-LINKS = ccan
+LINKS = ccan common libflash $(ARCH_LINKS)
OPAL_PRD_VERSION ?= $(shell ../../make_version.sh opal-prd)
@@ -34,6 +41,12 @@ endif
ccan:
$(Q_LN)ln -sfr ../../ccan ./ccan
+libflash:
+ $(Q_LN)ln -sfr ../../libflash ./libflash
+
+common:
+ $(Q_LN)ln -sfr ../common ./common
+
asm/opal-prd.h:
$(Q_MKDIR)mkdir -p asm
$(Q_LN)ln -sfr $(KERNEL_DIR)/arch/powerpc/include/uapi/asm/opal-prd.h \
@@ -44,7 +57,7 @@ $(OBJS): $(LINKS)
%.o: %.c
$(Q_CC)$(COMPILE.c) $< -o $@
-%.o: ../../libflash/%.c
+$(LIBFLASH_OBJS): libflash-%.o : libflash/%.c
$(Q_CC)$(COMPILE.c) $< -o $@
%.o: %.S
@@ -66,9 +79,9 @@ version.c: ../../make_version.sh .version
@cmp -s $@ $@.tmp || cp $@.tmp $@
@rm -f $@.tmp
-test: test/test_pnor
+test: $(LINKS) test/test_pnor
-test/test_pnor: test/test_pnor.o pnor.o libflash.o libffs.o blocklevel.o file.o ecc.o
+test/test_pnor: test/test_pnor.o pnor.o $(LIBFLASH_OBJS) common-arch_flash.o
$(Q_LINK)$(LINK.o) -o $@ $^
install: all
diff --git a/external/opal-prd/opal-prd.c b/external/opal-prd/opal-prd.c
index a82000a2..f80e74c4 100644
--- a/external/opal-prd/opal-prd.c
+++ b/external/opal-prd/opal-prd.c
@@ -1603,14 +1603,10 @@ static int run_prd_daemon(struct opal_prd_ctx *ctx)
fixup_hinterface_table();
- if (ctx->pnor.path) {
- rc = pnor_init(&ctx->pnor);
- if (rc) {
- pr_log(LOG_ERR, "PNOR: Failed to open pnor: %m");
- goto out_close;
- }
- } else {
- pr_log(LOG_WARNING,"PNOR: No path provided, access will fail\n");
+ rc = pnor_init(&ctx->pnor);
+ if (rc) {
+ pr_log(LOG_ERR, "PNOR: Failed to open pnor: %m");
+ goto out_close;
}
ipmi_init(ctx);
diff --git a/external/opal-prd/pnor.c b/external/opal-prd/pnor.c
index 7c986034..0e7e5c04 100644
--- a/external/opal-prd/pnor.c
+++ b/external/opal-prd/pnor.c
@@ -15,6 +15,8 @@
*/
#include <libflash/libffs.h>
+#include <common/arch_flash.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 = arch_flash_init(&(pnor->bl), pnor->path, false);
+ if (rc) {
+ pr_log(LOG_ERR, "PNOR: Flash init 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;
+ arch_flash_close(pnor->bl, pnor->path);
+ 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)
+ arch_flash_close(pnor->bl, pnor->path);
+
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 06219dce..729a969e 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 {
OpenPOWER on IntegriCloud