diff options
-rw-r--r-- | external/common/rules.mk | 2 | ||||
-rw-r--r-- | external/opal-prd/Makefile | 27 | ||||
-rw-r--r-- | external/opal-prd/opal-prd.c | 12 | ||||
-rw-r--r-- | external/opal-prd/pnor.c | 215 | ||||
-rw-r--r-- | external/opal-prd/pnor.h | 2 |
5 files changed, 60 insertions, 198 deletions
diff --git a/external/common/rules.mk b/external/common/rules.mk index 356c207..81adddd 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 ff3fc73..98c7b48 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 a82000a..f80e74c 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 7c98603..0e7e5c0 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 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 { |