diff options
-rw-r--r-- | ubi-utils/.gitignore | 19 | ||||
-rw-r--r-- | ubi-utils/LICENSE.libiniparser (renamed from ubi-utils/new-utils/LICENSE.libiniparser) | 0 | ||||
-rw-r--r-- | ubi-utils/Makefile | 64 | ||||
-rw-r--r-- | ubi-utils/include/libiniparser.h (renamed from ubi-utils/new-utils/include/libiniparser.h) | 0 | ||||
-rw-r--r-- | ubi-utils/include/libmtd.h (renamed from ubi-utils/new-utils/include/libmtd.h) | 0 | ||||
-rw-r--r-- | ubi-utils/include/libscan.h (renamed from ubi-utils/new-utils/include/libscan.h) | 0 | ||||
-rw-r--r-- | ubi-utils/include/libubi.h (renamed from ubi-utils/new-utils/include/libubi.h) | 0 | ||||
-rw-r--r-- | ubi-utils/include/libubigen.h (renamed from ubi-utils/new-utils/include/libubigen.h) | 0 | ||||
-rw-r--r-- | ubi-utils/new-utils/.gitignore | 10 | ||||
-rw-r--r-- | ubi-utils/new-utils/Makefile | 57 | ||||
-rw-r--r-- | ubi-utils/new-utils/README | 55 | ||||
-rw-r--r-- | ubi-utils/new-utils/src/crc32.c | 95 | ||||
-rw-r--r-- | ubi-utils/new-utils/src/crc32.h | 19 | ||||
-rw-r--r-- | ubi-utils/new-utils/src/libubi.c | 1206 | ||||
-rw-r--r-- | ubi-utils/new-utils/src/libubigen.c | 330 | ||||
-rw-r--r-- | ubi-utils/old-utils/.gitignore | 9 | ||||
-rw-r--r-- | ubi-utils/old-utils/Makefile | 59 | ||||
-rw-r--r-- | ubi-utils/old-utils/README (renamed from ubi-utils/README) | 0 | ||||
-rw-r--r-- | ubi-utils/old-utils/UBI.TXT (renamed from ubi-utils/UBI.TXT) | 0 | ||||
-rw-r--r-- | ubi-utils/old-utils/doc/unubi.roff (renamed from ubi-utils/doc/unubi.roff) | 0 | ||||
-rw-r--r-- | ubi-utils/old-utils/inc/libubi.h (renamed from ubi-utils/inc/libubi.h) | 0 | ||||
-rw-r--r-- | ubi-utils/old-utils/lib/Makefile.am (renamed from ubi-utils/lib/Makefile.am) | 0 | ||||
-rw-r--r-- | ubi-utils/old-utils/perl/f128_nand_sample.cfg (renamed from ubi-utils/perl/f128_nand_sample.cfg) | 0 | ||||
-rw-r--r-- | ubi-utils/old-utils/perl/f64_nor_sample.cfg (renamed from ubi-utils/perl/f64_nor_sample.cfg) | 0 | ||||
-rwxr-xr-x | ubi-utils/old-utils/perl/mkpfi (renamed from ubi-utils/perl/mkpfi) | 0 | ||||
-rwxr-xr-x | ubi-utils/old-utils/perl/ubicrc32.pl (renamed from ubi-utils/perl/ubicrc32.pl) | 0 | ||||
-rw-r--r-- | ubi-utils/old-utils/scripts/Makefile (renamed from ubi-utils/scripts/Makefile) | 0 | ||||
-rw-r--r-- | ubi-utils/old-utils/scripts/README (renamed from ubi-utils/scripts/README) | 0 | ||||
-rw-r--r-- | ubi-utils/old-utils/scripts/TODO (renamed from ubi-utils/scripts/TODO) | 0 | ||||
-rw-r--r-- | ubi-utils/old-utils/scripts/bin2nand2bin_test.sh (renamed from ubi-utils/scripts/bin2nand2bin_test.sh) | 0 | ||||
-rw-r--r-- | ubi-utils/old-utils/scripts/inject_biterror.pl (renamed from ubi-utils/scripts/inject_biterror.pl) | 0 | ||||
-rwxr-xr-x | ubi-utils/old-utils/scripts/jffs2_test.sh (renamed from ubi-utils/scripts/jffs2_test.sh) | 0 | ||||
-rwxr-xr-x | ubi-utils/old-utils/scripts/mkdevs.pl (renamed from ubi-utils/scripts/mkdevs.pl) | 0 | ||||
-rw-r--r-- | ubi-utils/old-utils/scripts/pdd.txt (renamed from ubi-utils/scripts/pdd.txt) | 0 | ||||
-rwxr-xr-x | ubi-utils/old-utils/scripts/run_all.sh (renamed from ubi-utils/scripts/run_all.sh) | 0 | ||||
-rw-r--r-- | ubi-utils/old-utils/scripts/test.cfg (renamed from ubi-utils/scripts/test.cfg) | 0 | ||||
-rwxr-xr-x | ubi-utils/old-utils/scripts/ubi_jffs2_test.sh (renamed from ubi-utils/scripts/ubi_jffs2_test.sh) | 0 | ||||
-rwxr-xr-x | ubi-utils/old-utils/scripts/ubi_test.sh (renamed from ubi-utils/scripts/ubi_test.sh) | 0 | ||||
-rwxr-xr-x | ubi-utils/old-utils/scripts/ubi_tools_test.sh (renamed from ubi-utils/scripts/ubi_tools_test.sh) | 0 | ||||
-rw-r--r-- | ubi-utils/old-utils/scripts/unubi_test.sh (renamed from ubi-utils/scripts/unubi_test.sh) | 0 | ||||
-rw-r--r-- | ubi-utils/old-utils/src/bin2nand.c (renamed from ubi-utils/src/bin2nand.c) | 0 | ||||
-rw-r--r-- | ubi-utils/old-utils/src/bootenv.c (renamed from ubi-utils/src/bootenv.c) | 0 | ||||
-rw-r--r-- | ubi-utils/old-utils/src/bootenv.h (renamed from ubi-utils/src/bootenv.h) | 0 | ||||
-rw-r--r-- | ubi-utils/old-utils/src/config.h (renamed from ubi-utils/src/config.h) | 0 | ||||
-rw-r--r-- | ubi-utils/old-utils/src/crc32.c | 83 | ||||
-rw-r--r-- | ubi-utils/old-utils/src/crc32.h | 36 | ||||
-rw-r--r-- | ubi-utils/old-utils/src/eb_chain.c (renamed from ubi-utils/src/eb_chain.c) | 0 | ||||
-rw-r--r-- | ubi-utils/old-utils/src/error.c (renamed from ubi-utils/src/error.c) | 0 | ||||
-rw-r--r-- | ubi-utils/old-utils/src/error.h (renamed from ubi-utils/src/error.h) | 0 | ||||
-rw-r--r-- | ubi-utils/old-utils/src/example_ubi.h (renamed from ubi-utils/src/example_ubi.h) | 0 | ||||
-rw-r--r-- | ubi-utils/old-utils/src/hashmap.c (renamed from ubi-utils/src/hashmap.c) | 0 | ||||
-rw-r--r-- | ubi-utils/old-utils/src/hashmap.h (renamed from ubi-utils/src/hashmap.h) | 0 | ||||
-rw-r--r-- | ubi-utils/old-utils/src/libpfiflash.c (renamed from ubi-utils/src/libpfiflash.c) | 0 | ||||
-rw-r--r-- | ubi-utils/old-utils/src/libubi.c | 915 | ||||
-rw-r--r-- | ubi-utils/old-utils/src/libubi_int.h (renamed from ubi-utils/new-utils/src/libubi_int.h) | 88 | ||||
-rw-r--r-- | ubi-utils/old-utils/src/libubigen.c | 487 | ||||
-rw-r--r-- | ubi-utils/old-utils/src/libubimirror.c (renamed from ubi-utils/src/libubimirror.c) | 0 | ||||
-rw-r--r-- | ubi-utils/old-utils/src/list.c (renamed from ubi-utils/src/list.c) | 0 | ||||
-rw-r--r-- | ubi-utils/old-utils/src/list.h (renamed from ubi-utils/src/list.h) | 0 | ||||
-rw-r--r-- | ubi-utils/old-utils/src/mkbootenv.c (renamed from ubi-utils/src/mkbootenv.c) | 0 | ||||
-rw-r--r-- | ubi-utils/old-utils/src/nand2bin.c (renamed from ubi-utils/src/nand2bin.c) | 0 | ||||
-rw-r--r-- | ubi-utils/old-utils/src/nandcorr.c (renamed from ubi-utils/src/nandcorr.c) | 0 | ||||
-rw-r--r-- | ubi-utils/old-utils/src/nandecc.c (renamed from ubi-utils/src/nandecc.c) | 0 | ||||
-rw-r--r-- | ubi-utils/old-utils/src/nandecc.h (renamed from ubi-utils/src/nandecc.h) | 0 | ||||
-rw-r--r-- | ubi-utils/old-utils/src/pddcustomize.c (renamed from ubi-utils/src/pddcustomize.c) | 0 | ||||
-rw-r--r-- | ubi-utils/old-utils/src/peb.c (renamed from ubi-utils/src/peb.c) | 0 | ||||
-rw-r--r-- | ubi-utils/old-utils/src/peb.h (renamed from ubi-utils/src/peb.h) | 0 | ||||
-rw-r--r-- | ubi-utils/old-utils/src/pfi.c (renamed from ubi-utils/src/pfi.c) | 0 | ||||
-rw-r--r-- | ubi-utils/old-utils/src/pfi.h (renamed from ubi-utils/src/pfi.h) | 0 | ||||
-rw-r--r-- | ubi-utils/old-utils/src/pfi2bin.c (renamed from ubi-utils/src/pfi2bin.c) | 0 | ||||
-rw-r--r-- | ubi-utils/old-utils/src/pfiflash.c (renamed from ubi-utils/src/pfiflash.c) | 0 | ||||
-rw-r--r-- | ubi-utils/old-utils/src/pfiflash.h (renamed from ubi-utils/src/pfiflash.h) | 0 | ||||
-rw-r--r-- | ubi-utils/old-utils/src/pfiflash_error.h (renamed from ubi-utils/src/pfiflash_error.h) | 0 | ||||
-rw-r--r-- | ubi-utils/old-utils/src/reader.c (renamed from ubi-utils/src/reader.c) | 0 | ||||
-rw-r--r-- | ubi-utils/old-utils/src/reader.h (renamed from ubi-utils/src/reader.h) | 0 | ||||
-rw-r--r-- | ubi-utils/old-utils/src/ubigen.c (renamed from ubi-utils/src/ubigen.c) | 0 | ||||
-rw-r--r-- | ubi-utils/old-utils/src/ubigen.h (renamed from ubi-utils/src/ubigen.h) | 0 | ||||
-rw-r--r-- | ubi-utils/old-utils/src/ubimirror.c (renamed from ubi-utils/src/ubimirror.c) | 0 | ||||
-rw-r--r-- | ubi-utils/old-utils/src/ubimirror.h (renamed from ubi-utils/src/ubimirror.h) | 0 | ||||
-rw-r--r-- | ubi-utils/old-utils/src/unubi.c (renamed from ubi-utils/src/unubi.c) | 0 | ||||
-rw-r--r-- | ubi-utils/old-utils/src/unubi_analyze.c (renamed from ubi-utils/src/unubi_analyze.c) | 0 | ||||
-rw-r--r-- | ubi-utils/old-utils/src/unubi_analyze.h (renamed from ubi-utils/src/unubi_analyze.h) | 0 | ||||
-rw-r--r-- | ubi-utils/old-utils/testcases.txt (renamed from ubi-utils/testcases.txt) | 0 | ||||
-rw-r--r-- | ubi-utils/src/common.c (renamed from ubi-utils/new-utils/src/common.c) | 0 | ||||
-rw-r--r-- | ubi-utils/src/common.h (renamed from ubi-utils/new-utils/src/common.h) | 0 | ||||
-rw-r--r-- | ubi-utils/src/crc32.c | 156 | ||||
-rw-r--r-- | ubi-utils/src/crc32.h | 47 | ||||
-rw-r--r-- | ubi-utils/src/dictionary.c (renamed from ubi-utils/new-utils/src/dictionary.c) | 0 | ||||
-rw-r--r-- | ubi-utils/src/dictionary.h (renamed from ubi-utils/new-utils/src/dictionary.h) | 0 | ||||
-rw-r--r-- | ubi-utils/src/libiniparser.c (renamed from ubi-utils/new-utils/src/libiniparser.c) | 0 | ||||
-rw-r--r-- | ubi-utils/src/libmtd.c (renamed from ubi-utils/new-utils/src/libmtd.c) | 0 | ||||
-rw-r--r-- | ubi-utils/src/libscan.c (renamed from ubi-utils/new-utils/src/libscan.c) | 0 | ||||
-rw-r--r-- | ubi-utils/src/libubi.c | 1377 | ||||
-rw-r--r-- | ubi-utils/src/libubi_int.h | 88 | ||||
-rw-r--r-- | ubi-utils/src/libubigen.c | 665 | ||||
-rw-r--r-- | ubi-utils/src/ubiattach.c (renamed from ubi-utils/new-utils/src/ubiattach.c) | 0 | ||||
-rw-r--r-- | ubi-utils/src/ubicrc32.c (renamed from ubi-utils/new-utils/src/ubicrc32.c) | 0 | ||||
-rw-r--r-- | ubi-utils/src/ubidetach.c (renamed from ubi-utils/new-utils/src/ubidetach.c) | 0 | ||||
-rw-r--r-- | ubi-utils/src/ubiformat.c (renamed from ubi-utils/new-utils/src/ubiformat.c) | 0 | ||||
-rw-r--r-- | ubi-utils/src/ubimkvol.c (renamed from ubi-utils/new-utils/src/ubimkvol.c) | 0 | ||||
-rw-r--r-- | ubi-utils/src/ubinfo.c (renamed from ubi-utils/new-utils/src/ubinfo.c) | 0 | ||||
-rw-r--r-- | ubi-utils/src/ubinize.c (renamed from ubi-utils/new-utils/src/ubinize.c) | 0 | ||||
-rw-r--r-- | ubi-utils/src/ubirename.c (renamed from ubi-utils/new-utils/src/ubirename.c) | 0 | ||||
-rw-r--r-- | ubi-utils/src/ubirmvol.c (renamed from ubi-utils/new-utils/src/ubirmvol.c) | 0 | ||||
-rw-r--r-- | ubi-utils/src/ubiupdatevol.c (renamed from ubi-utils/new-utils/src/ubiupdatevol.c) | 0 |
105 files changed, 2905 insertions, 2960 deletions
diff --git a/ubi-utils/.gitignore b/ubi-utils/.gitignore index 83e8b71..4155cd1 100644 --- a/ubi-utils/.gitignore +++ b/ubi-utils/.gitignore @@ -1,9 +1,10 @@ -/bin2nand -/mkbootenv -/nand2bin -/pddcustomize -/pfi2bin -/pfiflash -/ubigen -/ubimirror -/unubi +/ubiattach +/ubicrc32 +/ubidetach +/ubiformat +/ubimkvol +/ubinfo +/ubinize +/ubirename +/ubirmvol +/ubiupdatevol diff --git a/ubi-utils/new-utils/LICENSE.libiniparser b/ubi-utils/LICENSE.libiniparser index dbfa45d..dbfa45d 100644 --- a/ubi-utils/new-utils/LICENSE.libiniparser +++ b/ubi-utils/LICENSE.libiniparser diff --git a/ubi-utils/Makefile b/ubi-utils/Makefile index 3be813a..020fe09 100644 --- a/ubi-utils/Makefile +++ b/ubi-utils/Makefile @@ -4,58 +4,56 @@ KERNELHDR := ../include -CFLAGS ?= -O2 -g -Werror -CPPFLAGS += -I./inc -I./src -I$(KERNELHDR) \ - -std=gnu99 -DPACKAGE_VERSION=\"1.0\" +SUBDIRS = old-utils -PERLPROGS = mkpfi ubicrc32.pl +#CFLAGS += -Werror +CPPFLAGS += -Iinclude -Isrc -I$(KERNELHDR) -SUBDIRS = new-utils +LIBS = libubi libmtd libubigen libiniparser libscan +TARGETS = ubiupdatevol ubimkvol ubirmvol ubicrc32 ubinfo ubiattach \ + ubidetach ubinize ubiformat ubirename -TARGETS = pfiflash pddcustomize ubimirror bin2nand nand2bin ubigen \ - mkbootenv unubi pfi2bin - -vpath %.c ./src +vpath %.c src include ../common.mk -$(BUILDDIR)/pddcustomize: $(addprefix $(BUILDDIR)/,\ - pddcustomize.o error.o libubimirror.o bootenv.o hashmap.o \ - libubi.o crc32.o) +# And the below is the rule to get final executable from its .o and common.o +$(TARGETS): $(addprefix $(BUILDDIR)/,\ + libubi.a common.o) +# $(CC) $(CFLAGS) $(filter %.o, $^) -L. -lubi -o $@ + +$(BUILDDIR)/ubicrc32: $(addprefix $(BUILDDIR)/,\ + ubicrc32.o crc32.o) +# $(CC) $(CFLAGS) -o $@ $^ -$(BUILDDIR)/pfiflash: $(addprefix $(BUILDDIR)/,\ - pfiflash.o libpfiflash.o list.o reader.o error.o libubimirror.o \ - bootenv.o hashmap.o pfi.o libubi.o crc32.o) +$(BUILDDIR)/ubinize: $(addprefix $(BUILDDIR)/,\ + ubinize.o common.o crc32.o libiniparser.a libubigen.a) +# $(CC) $(CFLAGS) $(filter %.o, $^) -L. -liniparser -lubigen -o $@ -$(BUILDDIR)/ubimirror: $(addprefix $(BUILDDIR)/,\ - ubimirror.o error.o libubimirror.o bootenv.o hashmap.o \ - libubi.o crc32.o) +$(BUILDDIR)/ubiformat: $(addprefix $(BUILDDIR)/,\ + ubiformat.o common.o crc32.o libmtd.a libscan.a libubi.a libubigen.a) +# $(CC) $(CFLAGS) $(filter %.o, $^) -L. -lmtd -lscan -lubi -lubigen -o $@ -$(BUILDDIR)/nand2bin: $(addprefix $(BUILDDIR)/,\ - nand2bin.o nandecc.o nandcorr.o) +$(BUILDDIR)/libubi.a: $(BUILDDIR)/libubi.o -$(BUILDDIR)/bin2nand: $(addprefix $(BUILDDIR)/,\ - bin2nand.o error.o nandecc.o) +$(BUILDDIR)/libmtd.a: $(BUILDDIR)/libmtd.o -$(BUILDDIR)/ubigen: $(addprefix $(BUILDDIR)/,\ - ubigen.o libubigen.o crc32.o) +$(BUILDDIR)/libubigen.a: $(BUILDDIR)/libubigen.o -$(BUILDDIR)/mkbootenv: $(addprefix $(BUILDDIR)/,\ - mkbootenv.o bootenv.o hashmap.o error.o crc32.o) +$(BUILDDIR)/libiniparser.a: $(addprefix $(BUILDDIR)/,\ + libiniparser.o dictionary.o) -$(BUILDDIR)/unubi: $(addprefix $(BUILDDIR)/,\ - unubi.o crc32.o unubi_analyze.o eb_chain.o) +$(BUILDDIR)/libscan.a: $(addprefix $(BUILDDIR)/,\ + libscan.o crc32.o) -$(BUILDDIR)/pfi2bin: $(addprefix $(BUILDDIR)/,\ - pfi2bin.o peb.o error.o list.o crc32.o libubigen.o bootenv.o \ - hashmap.o reader.o pfi.o) +clean:: + rm -f $(addsuffix .a, $(LIBS)) install:: mkdir -p ${DESTDIR}/${SBINDIR} install -m 0755 ${TARGETS} ${DESTDIR}/${SBINDIR}/ - (cd perl && install ${PERLPROGS} ${DESTDIR}/${SBINDIR}/) uninstall: - for file in ${TARGETS} ${PERLPROGS}; do \ + for file in ${TARGETS}; do \ $(RM) ${DESTDIR}/${SBINDIR}/$$file; \ done diff --git a/ubi-utils/new-utils/include/libiniparser.h b/ubi-utils/include/libiniparser.h index be3c667..be3c667 100644 --- a/ubi-utils/new-utils/include/libiniparser.h +++ b/ubi-utils/include/libiniparser.h diff --git a/ubi-utils/new-utils/include/libmtd.h b/ubi-utils/include/libmtd.h index d3c6a63..d3c6a63 100644 --- a/ubi-utils/new-utils/include/libmtd.h +++ b/ubi-utils/include/libmtd.h diff --git a/ubi-utils/new-utils/include/libscan.h b/ubi-utils/include/libscan.h index 5afc93e..5afc93e 100644 --- a/ubi-utils/new-utils/include/libscan.h +++ b/ubi-utils/include/libscan.h diff --git a/ubi-utils/new-utils/include/libubi.h b/ubi-utils/include/libubi.h index 1299e81..1299e81 100644 --- a/ubi-utils/new-utils/include/libubi.h +++ b/ubi-utils/include/libubi.h diff --git a/ubi-utils/new-utils/include/libubigen.h b/ubi-utils/include/libubigen.h index c2b95b0..c2b95b0 100644 --- a/ubi-utils/new-utils/include/libubigen.h +++ b/ubi-utils/include/libubigen.h diff --git a/ubi-utils/new-utils/.gitignore b/ubi-utils/new-utils/.gitignore deleted file mode 100644 index 4155cd1..0000000 --- a/ubi-utils/new-utils/.gitignore +++ /dev/null @@ -1,10 +0,0 @@ -/ubiattach -/ubicrc32 -/ubidetach -/ubiformat -/ubimkvol -/ubinfo -/ubinize -/ubirename -/ubirmvol -/ubiupdatevol diff --git a/ubi-utils/new-utils/Makefile b/ubi-utils/new-utils/Makefile deleted file mode 100644 index 83751e6..0000000 --- a/ubi-utils/new-utils/Makefile +++ /dev/null @@ -1,57 +0,0 @@ -# -# Makefile for ubi-utils -# - -KERNELHDR := ../../include - -#CFLAGS += -Werror -CPPFLAGS += -Iinclude -Isrc -I$(KERNELHDR) - -LIBS = libubi libmtd libubigen libiniparser libscan -TARGETS = ubiupdatevol ubimkvol ubirmvol ubicrc32 ubinfo ubiattach \ - ubidetach ubinize ubiformat ubirename - -vpath %.c src - -include ../../common.mk - -# And the below is the rule to get final executable from its .o and common.o -$(TARGETS): $(addprefix $(BUILDDIR)/,\ - libubi.a common.o) -# $(CC) $(CFLAGS) $(filter %.o, $^) -L. -lubi -o $@ - -$(BUILDDIR)/ubicrc32: $(addprefix $(BUILDDIR)/,\ - ubicrc32.o crc32.o) -# $(CC) $(CFLAGS) -o $@ $^ - -$(BUILDDIR)/ubinize: $(addprefix $(BUILDDIR)/,\ - ubinize.o common.o crc32.o libiniparser.a libubigen.a) -# $(CC) $(CFLAGS) $(filter %.o, $^) -L. -liniparser -lubigen -o $@ - -$(BUILDDIR)/ubiformat: $(addprefix $(BUILDDIR)/,\ - ubiformat.o common.o crc32.o libmtd.a libscan.a libubi.a libubigen.a) -# $(CC) $(CFLAGS) $(filter %.o, $^) -L. -lmtd -lscan -lubi -lubigen -o $@ - -$(BUILDDIR)/libubi.a: $(BUILDDIR)/libubi.o - -$(BUILDDIR)/libmtd.a: $(BUILDDIR)/libmtd.o - -$(BUILDDIR)/libubigen.a: $(BUILDDIR)/libubigen.o - -$(BUILDDIR)/libiniparser.a: $(addprefix $(BUILDDIR)/,\ - libiniparser.o dictionary.o) - -$(BUILDDIR)/libscan.a: $(addprefix $(BUILDDIR)/,\ - libscan.o crc32.o) - -clean:: - rm -f $(addsuffix .a, $(LIBS)) - -install:: - mkdir -p ${DESTDIR}/${SBINDIR} - install -m 0755 ${TARGETS} ${DESTDIR}/${SBINDIR}/ - -uninstall: - for file in ${TARGETS}; do \ - $(RM) ${DESTDIR}/${SBINDIR}/$$file; \ - done diff --git a/ubi-utils/new-utils/README b/ubi-utils/new-utils/README deleted file mode 100644 index 41c5957..0000000 --- a/ubi-utils/new-utils/README +++ /dev/null @@ -1,55 +0,0 @@ -This directory contains a new UBI toolchain which is intended to replace -the old one. All utilities support "-h" option which prints sufficient -usage information. See the MTD web-site for more information. - -Motivation for new tool-chain. - -I was doing very active UBI development and had to add new features like -dynamic UBI devices and auto-resize feature. Because of the mess in the -the old tools I basically could not figure out how to upgrade them. In -my humble oppinion, they are unmaintainable. The original authors did not -show enthusiasm when I mailed them and asked to clean-up the tool-chain -[1]. Thus, I re-implemented them, but I did borrow things from the old -tool-chain and preserved copyrights and author names. - -I really did try to clean-up the old tool chain, but gave up (see git -history for confirmation). So, - -1. I found the source codes very difficult to navigate and read, especially - those related to pdd, pfi, and bootenv. Try to do this yourself - they - are a puzzle. -2. I foud the concept of PFI needlesly complecated - PFI file is nothing - else but the initial configuration .ini file + the contents of the - UBI volumes packed into one file, but with some changes of the .ini file's - format. The PFI file format is not very nice and it is difficult to parse, - especially because the PFI headers do not tell you data star and end for - each data chunk, and you have to do additional parsing. - - So basically, you have .ini file + images, then you transfer this to pfi, - which does not add any other information. For .ini you have libraries - which may parse them, for pfi - not. Then you have to parse this pfi - which adds unneeded and complex code. This all needs lists, hashmaps, - and so on - for no reason. -3. I found the command line options of the utilities to be inconsistent. - This is OK when you script your single task and do not touch it anymore. - But when you have to use the utilities while developing and testing, - It is difficult to remember their inconsistent options. -4. I found it wrong to add development options to user utilities like - "broken update". End users should not see them. -5. I did not find any consistent style and convention inside which - irritated me. -6. I found it weird to introduce needless "logging infrastructure" instead - of just re-directing stdout and stderr to another file. -7. I found the tool to be rather IBM-setup oriented. For example, the VID - header position was hard-coded. Some utilities were just weird, like - mkbootenv, which changed some ethernet addresses mentioned in a - configuration file. -8. Finally, it was very difficult to realize what is pfi and pdd, what for, - why I need this transiant pfi file when I just want to create an UBI - image. There was zero documentation. - -And so on. - -Feb 19, 2008, Artem Bityutskiy. - -[1]. http://lists.infradead.org/pipermail/linux-mtd/2007-December/020134.html diff --git a/ubi-utils/new-utils/src/crc32.c b/ubi-utils/new-utils/src/crc32.c deleted file mode 100644 index 6b1e50c..0000000 --- a/ubi-utils/new-utils/src/crc32.c +++ /dev/null @@ -1,95 +0,0 @@ -/* - * COPYRIGHT (C) 1986 Gary S. Brown. You may use this program, or - * code or tables extracted from it, as desired without restriction. - * - * First, the polynomial itself and its table of feedback terms. The - * polynomial is - * X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0 - * - * Note that we take it "backwards" and put the highest-order term in - * the lowest-order bit. The X^32 term is "implied"; the LSB is the - * X^31 term, etc. The X^0 term (usually shown as "+1") results in - * the MSB being 1 - * - * Note that the usual hardware shift register implementation, which - * is what we're using (we're merely optimizing it by doing eight-bit - * chunks at a time) shifts bits into the lowest-order term. In our - * implementation, that means shifting towards the right. Why do we - * do it this way? Because the calculated CRC must be transmitted in - * order from highest-order term to lowest-order term. UARTs transmit - * characters in order from LSB to MSB. By storing the CRC this way - * we hand it to the UART in the order low-byte to high-byte; the UART - * sends each low-bit to hight-bit; and the result is transmission bit - * by bit from highest- to lowest-order term without requiring any bit - * shuffling on our part. Reception works similarly - * - * The feedback terms table consists of 256, 32-bit entries. Notes - * - * The table can be generated at runtime if desired; code to do so - * is shown later. It might not be obvious, but the feedback - * terms simply represent the results of eight shift/xor opera - * tions for all combinations of data and CRC register values - * - * The values must be right-shifted by eight bits by the "updcrc - * logic; the shift must be unsigned (bring in zeroes). On some - * hardware you could probably optimize the shift in assembler by - * using byte-swap instructions - * polynomial $edb88320 - */ - -#include <stdint.h> - -const uint32_t crc32_table[256] = { - 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L, - 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L, - 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L, - 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL, - 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L, - 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L, - 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L, - 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL, - 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L, - 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL, - 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L, - 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L, - 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L, - 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL, - 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL, - 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L, - 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL, - 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L, - 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L, - 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L, - 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL, - 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L, - 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L, - 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL, - 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L, - 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L, - 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L, - 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L, - 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L, - 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL, - 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL, - 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L, - 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L, - 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL, - 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL, - 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L, - 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL, - 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L, - 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL, - 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L, - 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL, - 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L, - 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L, - 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL, - 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L, - 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L, - 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L, - 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L, - 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L, - 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L, - 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL, - 0x2d02ef8dL -}; diff --git a/ubi-utils/new-utils/src/crc32.h b/ubi-utils/new-utils/src/crc32.h deleted file mode 100644 index ee3145b..0000000 --- a/ubi-utils/new-utils/src/crc32.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef CRC32_H -#define CRC32_H - -#include <stdint.h> - -extern const uint32_t crc32_table[256]; - -/* Return a 32-bit CRC of the contents of the buffer. */ - - static inline uint32_t -crc32(uint32_t val, const void *ss, int len) -{ - const unsigned char *s = ss; - while (--len >= 0) - val = crc32_table[(val ^ *s++) & 0xff] ^ (val >> 8); - return val; -} - -#endif diff --git a/ubi-utils/new-utils/src/libubi.c b/ubi-utils/new-utils/src/libubi.c deleted file mode 100644 index 1aa66d8..0000000 --- a/ubi-utils/new-utils/src/libubi.c +++ /dev/null @@ -1,1206 +0,0 @@ -/* - * Copyright (c) International Business Machines Corp., 2006 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * Author: Artem Bityutskiy - * - * UBI (Unsorted Block Images) library. - */ - -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <fcntl.h> -#include <sys/stat.h> -#include <sys/types.h> -#include <dirent.h> -#include <unistd.h> -#include <sys/ioctl.h> -#include <limits.h> -#include "libubi.h" -#include "libubi_int.h" -#include "common.h" - -#define PROGRAM_NAME "libubi" - -/** - * mkpath - compose full path from 2 given components. - * @path: the first component - * @name: the second component - * - * This function returns the resulting path in case of success and %NULL in - * case of failure. - */ -static char *mkpath(const char *path, const char *name) -{ - char *n; - int len1 = strlen(path); - int len2 = strlen(name); - - n = malloc(len1 + len2 + 2); - if (!n) { - sys_errmsg("cannot allocate %d bytes", len1 + len2 + 2); - return NULL; - } - - memcpy(n, path, len1); - if (n[len1 - 1] != '/') - n[len1++] = '/'; - - memcpy(n + len1, name, len2 + 1); - return n; -} - -/** - * read_positive_ll - read a positive 'long long' value from a file. - * @file: the file to read from - * @value: the result is stored here - * - * This function reads file @file and interprets its contents as a positive - * 'long long' integer. If this is not true, it fails with %EINVAL error code. - * Returns %0 in case of success and %-1 in case of failure. - */ -static int read_positive_ll(const char *file, long long *value) -{ - int fd, rd; - char buf[50]; - - fd = open(file, O_RDONLY); - if (fd == -1) - return -1; - - rd = read(fd, buf, 50); - if (rd == -1) { - sys_errmsg("cannot read \"%s\"", file); - goto out_error; - } - if (rd == 50) { - errmsg("contents of \"%s\" is too long", file); - errno = EINVAL; - goto out_error; - } - - if (sscanf(buf, "%lld\n", value) != 1) { - /* This must be a UBI bug */ - errmsg("cannot read integer from \"%s\"\n", file); - errno = EINVAL; - goto out_error; - } - - if (*value < 0) { - errmsg("negative value %lld in \"%s\"", *value, file); - errno = EINVAL; - goto out_error; - } - - if (close(fd)) - return sys_errmsg("close failed on \"%s\"", file); - - return 0; - -out_error: - close(fd); - return -1; -} - -/** - * read_positive_int - read a positive 'int' value from a file. - * @file: the file to read from - * @value: the result is stored here - * - * This function is the same as 'read_positive_ll()', but it reads an 'int' - * value, not 'long long'. - */ -static int read_positive_int(const char *file, int *value) -{ - long long res; - - if (read_positive_ll(file, &res)) - return -1; - - /* Make sure the value is not too big */ - if (res > INT_MAX) { - errmsg("value %lld read from file \"%s\" is out of range", - res, file); - errno = EINVAL; - return -1; - } - - *value = res; - return 0; -} - -/** - * read_data - read data from a file. - * @file: the file to read from - * @buf: the buffer to read to - * @buf_len: buffer length - * - * This function returns number of read bytes in case of success and %-1 in - * case of failure. Note, if the file contains more then @buf_len bytes of - * date, this function fails with %EINVAL error code. - */ -static int read_data(const char *file, void *buf, int buf_len) -{ - int fd, rd, tmp, tmp1; - - fd = open(file, O_RDONLY); - if (fd == -1) - return -1; - - rd = read(fd, buf, buf_len); - if (rd == -1) { - sys_errmsg("cannot read \"%s\"", file); - goto out_error; - } - - /* Make sure all data is read */ - tmp1 = read(fd, &tmp, 1); - if (tmp1 == 1) { - sys_errmsg("cannot read \"%s\"", file); - goto out_error; - } - if (tmp1) { - errmsg("file \"%s\" contains too much data (> %d bytes)", - file, buf_len); - errno = EINVAL; - goto out_error; - } - - if (close(fd)) { - sys_errmsg("close failed on \"%s\"", file); - return -1; - } - - return rd; - -out_error: - close(fd); - return -1; -} - -/** - * read_major - read major and minor numbers from a file. - * @file: name of the file to read from - * @major: major number is returned here - * @minor: minor number is returned here - * - * This function returns % in case of succes, and %-1 in case of failure. - */ -static int read_major(const char *file, int *major, int *minor) -{ - int ret; - char buf[50]; - - ret = read_data(file, buf, 50); - if (ret < 0) - return ret; - - ret = sscanf(buf, "%d:%d\n", major, minor); - if (ret != 2) { - errno = EINVAL; - return errmsg("\"%s\" does not have major:minor format", file); - } - - if (*major < 0 || *minor < 0) { - errno = EINVAL; - return errmsg("bad major:minor %d:%d in \"%s\"", - *major, *minor, file); - } - - return 0; -} - -/** - * dev_read_int - read a positive 'int' value from an UBI device sysfs file. - * @patt: file pattern to read from - * @dev_num: UBI device number - * @value: the result is stored here - * - * This function returns %0 in case of success and %-1 in case of failure. - */ -static int dev_read_int(const char *patt, int dev_num, int *value) -{ - char file[strlen(patt) + 50]; - - sprintf(file, patt, dev_num); - return read_positive_int(file, value); -} - -/** - * vol_read_int - read a positive 'int' value from an UBI volume sysfs file. - * @patt: file pattern to read from - * @dev_num: UBI device number - * @vol_id: volume ID - * @value: the result is stored here - * - * This function returns %0 in case of success and %-1 in case of failure. - */ -static int vol_read_int(const char *patt, int dev_num, int vol_id, int *value) -{ - char file[strlen(patt) + 100]; - - sprintf(file, patt, dev_num, vol_id); - return read_positive_int(file, value); -} - -/** - * dev_read_ll - read a positive 'long long' value from an UBI device sysfs file. - * @patt: file pattern to read from - * @dev_num: UBI device number - * @value: the result is stored here - * - * This function returns %0 in case of success and %-1 in case of failure. - */ -static int dev_read_ll(const char *patt, int dev_num, long long *value) -{ - char file[strlen(patt) + 50]; - - sprintf(file, patt, dev_num); - return read_positive_ll(file, value); -} - -/** - * vol_read_ll - read a positive 'long long' value from an UBI volume sysfs file. - * @patt: file pattern to read from - * @dev_num: UBI device number - * @vol_id: volume ID - * @value: the result is stored here - * - * This function returns %0 in case of success and %-1 in case of failure. - */ -static int vol_read_ll(const char *patt, int dev_num, int vol_id, - long long *value) -{ - char file[strlen(patt) + 100]; - - sprintf(file, patt, dev_num, vol_id); - return read_positive_ll(file, value); -} - -/** - * vol_read_data - read data from an UBI volume's sysfs file. - * @patt: file pattern to read from - * @dev_num: UBI device number - * @vol_id: volume ID - * @buf: buffer to read to - * @buf_len: buffer length - * - * This function returns number of read bytes in case of success and %-1 in - * case of failure. - */ -static int vol_read_data(const char *patt, int dev_num, int vol_id, void *buf, - int buf_len) -{ - char file[strlen(patt) + 100]; - - sprintf(file, patt, dev_num, vol_id); - return read_data(file, buf, buf_len); -} - -/** - * dev_get_major - get major and minor numbers of an UBI device. - * @lib: libubi descriptor - * @dev_num: UBI device number - * @major: major number is returned here - * @minor: minor number is returned here - * - * This function returns zero in case of succes and %-1 in case of failure. - */ -static int dev_get_major(struct libubi *lib, int dev_num, int *major, int *minor) -{ - char file[strlen(lib->dev_dev) + 50]; - - sprintf(file, lib->dev_dev, dev_num); - return read_major(file, major, minor); -} - -/** - * vol_get_major - get major and minor numbers of an UBI volume. - * @lib: libubi descriptor - * @dev_num: UBI device number - * @vol_id: volume ID - * @major: major number is returned here - * @minor: minor number is returned here - * - * This function returns zero in case of succes and %-1 in case of failure. - */ -static int vol_get_major(struct libubi *lib, int dev_num, int vol_id, - int *major, int *minor) -{ - char file[strlen(lib->vol_dev) + 100]; - - sprintf(file, lib->vol_dev, dev_num, vol_id); - return read_major(file, major, minor); -} - -/** - * vol_node2nums - find UBI device number and volume ID by volume device node - * file. - * @lib: UBI library descriptor - * @node: UBI character device node name - * @dev_num: UBI device number is returned here - * @vol_id: volume ID is returned hers - * - * This function returns zero in case of succes and %-1 in case of failure. - */ -static int vol_node2nums(struct libubi *lib, const char *node, int *dev_num, - int *vol_id) -{ - struct stat st; - struct ubi_info info; - int i, fd, major, minor; - char file[strlen(lib->ubi_vol) + 100]; - - if (stat(node, &st)) - return sys_errmsg("cannot get information about \"%s\"", - node); - - if (!S_ISCHR(st.st_mode)) { - errno = EINVAL; - return errmsg("\"%s\" is not a character device", node); - } - - major = major(st.st_rdev); - minor = minor(st.st_rdev); - - if (minor == 0) { - errno = EINVAL; - return errmsg("\"%s\" is not a volume character device", node); - } - - if (ubi_get_info((libubi_t *)lib, &info)) - return -1; - - for (i = info.lowest_dev_num; i <= info.highest_dev_num; i++) { - int major1, minor1, ret; - - ret = dev_get_major(lib, i, &major1, &minor1); - if (ret) { - if (errno == ENOENT) - continue; - return -1; - } - - if (major1 == major) - break; - } - - if (i > info.highest_dev_num) { - errno = ENODEV; - return -1; - } - - /* Make sure this UBI volume exists */ - sprintf(file, lib->ubi_vol, i, minor - 1); - fd = open(file, O_RDONLY); - if (fd == -1) { - errno = ENODEV; - return -1; - } - - *dev_num = i; - *vol_id = minor - 1; - errno = 0; - return 0; -} - -/** - * dev_node2num - find UBI device number by its character device node. - * @lib: UBI library descriptor - * @node: UBI character device node name - * - * This function returns positive UBI device number in case of success and %-1 - * in case of failure. - */ -static int dev_node2num(struct libubi *lib, const char *node, int *dev_num) -{ - struct stat st; - struct ubi_info info; - int i, major, minor; - - if (stat(node, &st)) - return sys_errmsg("cannot get information about \"%s\"", - node); - - if (!S_ISCHR(st.st_mode)) { - errno = EINVAL; - return errmsg("\"%s\" is not a character device", node); - } - - major = major(st.st_rdev); - minor = minor(st.st_rdev); - - if (minor != 0) { - errno = EINVAL; - return errmsg("\"%s\" is not an UBI character device", node); - } - - if (ubi_get_info((libubi_t *)lib, &info)) - return -1; - - for (i = info.lowest_dev_num; i <= info.highest_dev_num; i++) { - int major1, minor1, ret; - - ret = dev_get_major(lib, i, &major1, &minor1); - if (ret) { - if (errno == ENOENT) - continue; - return -1; - } - - if (major1 == major) { - if (minor1 != 0) { - errmsg("UBI character device minor number is " - "%d, but must be 0", minor1); - errno = EINVAL; - return -1; - } - errno = 0; - *dev_num = i; - return 0; - } - } - - errno = ENODEV; - return -1; -} - -int mtd_num2ubi_dev(libubi_t desc, int mtd_num, int *dev_num) -{ - struct ubi_info info; - int i, ret, mtd_num1; - struct libubi *lib = desc; - - if (ubi_get_info(desc, &info)) - return -1; - - for (i = info.lowest_dev_num; i <= info.highest_dev_num; i++) { - ret = dev_read_int(lib->dev_mtd_num, i, &mtd_num1); - if (ret) { - if (errno == ENOENT) - continue; - return -1; - } - - if (mtd_num1 == mtd_num) { - errno = 0; - *dev_num = i; - return 0; - } - } - - errno = 0; - return -1; -} - -libubi_t libubi_open(int required) -{ - int fd, version; - struct libubi *lib; - - lib = calloc(1, sizeof(struct libubi)); - if (!lib) - return NULL; - - /* TODO: this must be discovered instead */ - lib->sysfs = strdup("/sys"); - if (!lib->sysfs) - goto out_error; - - lib->sysfs_ctrl = mkpath(lib->sysfs, SYSFS_CTRL); - if (!lib->sysfs_ctrl) - goto out_error; - - lib->ctrl_dev = mkpath(lib->sysfs_ctrl, CTRL_DEV); - if (!lib->ctrl_dev) - goto out_error; - - lib->sysfs_ubi = mkpath(lib->sysfs, SYSFS_UBI); - if (!lib->sysfs_ubi) - goto out_error; - - /* Make sure UBI is present */ - fd = open(lib->sysfs_ubi, O_RDONLY); - if (fd == -1) { - if (required) - errmsg("cannot open \"%s\", UBI does not seem to " - "exist in system", lib->sysfs_ubi); - goto out_error; - } - - if (close(fd)) { - sys_errmsg("close failed on \"%s\"", lib->sysfs_ubi); - goto out_error; - } - - lib->ubi_dev = mkpath(lib->sysfs_ubi, UBI_DEV_NAME_PATT); - if (!lib->ubi_dev) - goto out_error; - - lib->ubi_version = mkpath(lib->sysfs_ubi, UBI_VER); - if (!lib->ubi_version) - goto out_error; - - lib->dev_dev = mkpath(lib->ubi_dev, DEV_DEV); - if (!lib->dev_dev) - goto out_error; - - lib->dev_avail_ebs = mkpath(lib->ubi_dev, DEV_AVAIL_EBS); - if (!lib->dev_avail_ebs) - goto out_error; - - lib->dev_total_ebs = mkpath(lib->ubi_dev, DEV_TOTAL_EBS); - if (!lib->dev_total_ebs) - goto out_error; - - lib->dev_bad_count = mkpath(lib->ubi_dev, DEV_BAD_COUNT); - if (!lib->dev_bad_count) - goto out_error; - - lib->dev_eb_size = mkpath(lib->ubi_dev, DEV_EB_SIZE); - if (!lib->dev_eb_size) - goto out_error; - - lib->dev_max_ec = mkpath(lib->ubi_dev, DEV_MAX_EC); - if (!lib->dev_max_ec) - goto out_error; - - lib->dev_bad_rsvd = mkpath(lib->ubi_dev, DEV_MAX_RSVD); - if (!lib->dev_bad_rsvd) - goto out_error; - - lib->dev_max_vols = mkpath(lib->ubi_dev, DEV_MAX_VOLS); - if (!lib->dev_max_vols) - goto out_error; - - lib->dev_min_io_size = mkpath(lib->ubi_dev, DEV_MIN_IO_SIZE); - if (!lib->dev_min_io_size) - goto out_error; - - lib->dev_mtd_num = mkpath(lib->ubi_dev, DEV_MTD_NUM); - if (!lib->dev_mtd_num) - goto out_error; - - lib->ubi_vol = mkpath(lib->sysfs_ubi, UBI_VOL_NAME_PATT); - if (!lib->ubi_vol) - goto out_error; - - lib->vol_type = mkpath(lib->ubi_vol, VOL_TYPE); - if (!lib->vol_type) - goto out_error; - - lib->vol_dev = mkpath(lib->ubi_vol, VOL_DEV); - if (!lib->vol_dev) - goto out_error; - - lib->vol_alignment = mkpath(lib->ubi_vol, VOL_ALIGNMENT); - if (!lib->vol_alignment) - goto out_error; - - lib->vol_data_bytes = mkpath(lib->ubi_vol, VOL_DATA_BYTES); - if (!lib->vol_data_bytes) - goto out_error; - - lib->vol_rsvd_ebs = mkpath(lib->ubi_vol, VOL_RSVD_EBS); - if (!lib->vol_rsvd_ebs) - goto out_error; - - lib->vol_eb_size = mkpath(lib->ubi_vol, VOL_EB_SIZE); - if (!lib->vol_eb_size) - goto out_error; - - lib->vol_corrupted = mkpath(lib->ubi_vol, VOL_CORRUPTED); - if (!lib->vol_corrupted) - goto out_error; - - lib->vol_name = mkpath(lib->ubi_vol, VOL_NAME); - if (!lib->vol_name) - goto out_error; - - if (read_positive_int(lib->ubi_version, &version)) - goto out_error; - if (version != LIBUBI_UBI_VERSION) { - errmsg("this library was made for UBI version %d, but UBI " - "version %d is detected\n", LIBUBI_UBI_VERSION, version); - goto out_error; - } - - return lib; - -out_error: - libubi_close((libubi_t)lib); - return NULL; -} - -void libubi_close(libubi_t desc) -{ - struct libubi *lib = (struct libubi *)desc; - - free(lib->vol_name); - free(lib->vol_corrupted); - free(lib->vol_eb_size); - free(lib->vol_rsvd_ebs); - free(lib->vol_data_bytes); - free(lib->vol_alignment); - free(lib->vol_dev); - free(lib->vol_type); - free(lib->ubi_vol); - free(lib->dev_mtd_num); - free(lib->dev_min_io_size); - free(lib->dev_max_vols); - free(lib->dev_bad_rsvd); - free(lib->dev_max_ec); - free(lib->dev_eb_size); - free(lib->dev_bad_count); - free(lib->dev_total_ebs); - free(lib->dev_avail_ebs); - free(lib->dev_dev); - free(lib->ubi_version); - free(lib->ubi_dev); - free(lib->sysfs_ubi); - free(lib->ctrl_dev); - free(lib->sysfs_ctrl); - free(lib->sysfs); - free(lib); -} - -int ubi_attach_mtd(libubi_t desc, const char *node, - struct ubi_attach_request *req) -{ - int fd, ret; - struct ubi_attach_req r; - - memset(&r, sizeof(struct ubi_attach_req), '\0'); - - desc = desc; - r.ubi_num = req->dev_num; - r.mtd_num = req->mtd_num; - r.vid_hdr_offset = req->vid_hdr_offset; - - fd = open(node, O_RDONLY); - if (fd == -1) - return sys_errmsg("cannot open \"%s\"", node); - - ret = ioctl(fd, UBI_IOCATT, &r); - close(fd); - if (ret == -1) - return -1; - - req->dev_num = r.ubi_num; - -#ifdef UDEV_SETTLE_HACK - if (system("udevsettle") == -1) - return -1; -#endif - - return ret; -} - -int ubi_detach_mtd(libubi_t desc, const char *node, int mtd_num) -{ - int ret, ubi_dev; - - ret = mtd_num2ubi_dev(desc, mtd_num, &ubi_dev); - if (ret == -1) { - errno = ENODEV; - return ret; - } - - return ubi_remove_dev(desc, node, ubi_dev); -} - -int ubi_remove_dev(libubi_t desc, const char *node, int ubi_dev) -{ - int fd, ret; - - desc = desc; - - fd = open(node, O_RDONLY); - if (fd == -1) - return sys_errmsg("cannot open \"%s\"", node); - ret = ioctl(fd, UBI_IOCDET, &ubi_dev); - if (ret == -1) - goto out_close; - -#ifdef UDEV_SETTLE_HACK - if (system("udevsettle") == -1) - return -1; -#endif - -out_close: - close(fd); - return ret; -} - -int ubi_node_type(libubi_t desc, const char *node) -{ - struct stat st; - struct ubi_info info; - int i, fd, major, minor; - struct libubi *lib = (struct libubi *)desc; - char file[strlen(lib->ubi_vol) + 100]; - - if (stat(node, &st)) - return sys_errmsg("cannot get information about \"%s\"", - node); - - if (!S_ISCHR(st.st_mode)) { - errmsg("\"%s\" is not a character device", node); - errno = EINVAL; - return -1; - } - - major = major(st.st_rdev); - minor = minor(st.st_rdev); - - if (ubi_get_info((libubi_t *)lib, &info)) - return -1; - - for (i = info.lowest_dev_num; i <= info.highest_dev_num; i++) { - int major1, minor1, ret; - - ret = dev_get_major(lib, i, &major1, &minor1); - if (ret) { - if (errno == ENOENT) - continue; - if (!errno) - goto out_not_ubi; - return -1; - } - - if (major1 == major) - break; - } - - if (i > info.highest_dev_num) - goto out_not_ubi; - - if (minor == 0) - return 1; - - /* This is supposdely an UBI volume device node */ - sprintf(file, lib->ubi_vol, i, minor - 1); - fd = open(file, O_RDONLY); - if (fd == -1) { - sys_errmsg("cannot open \"%s\"", node); - return -1; - } - - return 2; - -out_not_ubi: - errmsg("\"%s\" has major:minor %d:%d, but this does not correspond to " - "any UBI device or volume", node, major, minor); - errno = 0; - return -1; -} - -int ubi_get_info(libubi_t desc, struct ubi_info *info) -{ - DIR *sysfs_ubi; - struct dirent *dirent; - struct libubi *lib = (struct libubi *)desc; - - memset(info, '\0', sizeof(struct ubi_info)); - - if (read_major(lib->ctrl_dev, &info->ctrl_major, &info->ctrl_minor)) { - /* - * Older UBI versions did not have control device, so we do not - * panic here for compatibility reasons. May be few years later - * we could return -1 here, but for now just set major:minor to - * -1. - */ - info->ctrl_major = info->ctrl_minor = -1; - } - - /* - * We have to scan the UBI sysfs directory to identify how many UBI - * devices are present. - */ - sysfs_ubi = opendir(lib->sysfs_ubi); - if (!sysfs_ubi) - return -1; - - info->lowest_dev_num = INT_MAX; - while (1) { - int dev_num, ret; - char tmp_buf[256]; - - errno = 0; - dirent = readdir(sysfs_ubi); - if (!dirent) - break; - - if (strlen(dirent->d_name) > 256) { - errmsg("invalid entry in %s: \"%s\"", - lib->sysfs_ubi, dirent->d_name); - goto out_close; - } - - ret = sscanf(dirent->d_name, UBI_DEV_NAME_PATT"%s", - &dev_num, tmp_buf); - if (ret == 1) { - info->dev_count += 1; - if (dev_num > info->highest_dev_num) - info->highest_dev_num = dev_num; - if (dev_num < info->lowest_dev_num) - info->lowest_dev_num = dev_num; - } - } - - if (!dirent && errno) { - sys_errmsg("readdir failed on \"%s\"", lib->sysfs_ubi); - goto out_close; - } - - if (closedir(sysfs_ubi)) - return sys_errmsg("closedir failed on \"%s\"", lib->sysfs_ubi); - - if (info->lowest_dev_num == INT_MAX) - info->lowest_dev_num = 0; - - if (read_positive_int(lib->ubi_version, &info->version)) - return -1; - - return 0; - -out_close: - closedir(sysfs_ubi); - return -1; -} - -int ubi_mkvol(libubi_t desc, const char *node, struct ubi_mkvol_request *req) -{ - int fd, ret; - struct ubi_mkvol_req r; - size_t n; - - memset(&r, sizeof(struct ubi_mkvol_req), '\0'); - - desc = desc; - r.vol_id = req->vol_id; - r.alignment = req->alignment; - r.bytes = req->bytes; - r.vol_type = req->vol_type; - - n = strlen(req->name); - if (n > UBI_MAX_VOLUME_NAME) - return -1; - - strncpy(r.name, req->name, UBI_MAX_VOLUME_NAME + 1); - r.name_len = n; - - fd = open(node, O_RDONLY); - if (fd == -1) - return sys_errmsg("cannot open \"%s\"", node); - - ret = ioctl(fd, UBI_IOCMKVOL, &r); - if (ret == -1) - goto out_close; - - req->vol_id = r.vol_id; - -#ifdef UDEV_SETTLE_HACK - if (system("udevsettle") == -1) - return -1; -#endif - -out_close: - close(fd); - return ret; -} - -int ubi_rmvol(libubi_t desc, const char *node, int vol_id) -{ - int fd, ret; - - desc = desc; - fd = open(node, O_RDONLY); - if (fd == -1) - return sys_errmsg("cannot open \"%s\"", node); - - ret = ioctl(fd, UBI_IOCRMVOL, &vol_id); - if (ret == -1) - goto out_close; - -#ifdef UDEV_SETTLE_HACK - if (system("udevsettle") == -1) - return -1; -#endif - -out_close: - close(fd); - return ret; -} - -int ubi_rnvols(libubi_t desc, const char *node, struct ubi_rnvol_req *rnvol) -{ - int fd, ret; - - fd = open(node, O_RDONLY); - if (fd == -1) - return -1; - ret = ioctl(fd, UBI_IOCRNVOL, rnvol); - if (ret == -1) - goto out_close; - -#ifdef UDEV_SETTLE_HACK - if (system("udevsettle") == -1) - return -1; -#endif - -out_close: - close(fd); - return ret; -} - -int ubi_rsvol(libubi_t desc, const char *node, int vol_id, long long bytes) -{ - int fd, ret; - struct ubi_rsvol_req req; - - desc = desc; - fd = open(node, O_RDONLY); - if (fd == -1) - return sys_errmsg("cannot open \"%s\"", node); - - req.bytes = bytes; - req.vol_id = vol_id; - - ret = ioctl(fd, UBI_IOCRSVOL, &req); - close(fd); - return ret; -} - -int ubi_update_start(libubi_t desc, int fd, long long bytes) -{ - desc = desc; - if (ioctl(fd, UBI_IOCVOLUP, &bytes)) - return -1; - return 0; -} - -int ubi_leb_change_start(libubi_t desc, int fd, int lnum, int bytes, int dtype) -{ - struct ubi_leb_change_req req; - - desc = desc; - memset(&req, 0, sizeof(struct ubi_leb_change_req)); - req.lnum = lnum; - req.bytes = bytes; - req.dtype = dtype; - - if (ioctl(fd, UBI_IOCEBCH, &req)) - return -1; - return 0; -} - -int ubi_get_dev_info1(libubi_t desc, int dev_num, struct ubi_dev_info *info) -{ - DIR *sysfs_ubi; - struct dirent *dirent; - struct libubi *lib = (struct libubi *)desc; - - memset(info, '\0', sizeof(struct ubi_dev_info)); - info->dev_num = dev_num; - - sysfs_ubi = opendir(lib->sysfs_ubi); - if (!sysfs_ubi) - return -1; - - info->lowest_vol_id = INT_MAX; - - while (1) { - int vol_id, ret, devno; - char tmp_buf[256]; - - errno = 0; - dirent = readdir(sysfs_ubi); - if (!dirent) - break; - - if (strlen(dirent->d_name) > 256) { - errmsg("invalid entry in %s: \"%s\"", - lib->sysfs_ubi, dirent->d_name); - goto out_close; - } - - ret = sscanf(dirent->d_name, UBI_VOL_NAME_PATT"%s", &devno, &vol_id, tmp_buf); - if (ret == 2 && devno == dev_num) { - info->vol_count += 1; - if (vol_id > info->highest_vol_id) - info->highest_vol_id = vol_id; - if (vol_id < info->lowest_vol_id) - info->lowest_vol_id = vol_id; - } - } - - if (!dirent && errno) { - sys_errmsg("readdir failed on \"%s\"", lib->sysfs_ubi); - goto out_close; - } - - if (closedir(sysfs_ubi)) - return sys_errmsg("closedir failed on \"%s\"", lib->sysfs_ubi); - - if (info->lowest_vol_id == INT_MAX) - info->lowest_vol_id = 0; - - if (dev_get_major(lib, dev_num, &info->major, &info->minor)) - return -1; - - if (dev_read_int(lib->dev_avail_ebs, dev_num, &info->avail_lebs)) - return -1; - if (dev_read_int(lib->dev_total_ebs, dev_num, &info->total_lebs)) - return -1; - if (dev_read_int(lib->dev_bad_count, dev_num, &info->bad_count)) - return -1; - if (dev_read_int(lib->dev_eb_size, dev_num, &info->leb_size)) - return -1; - if (dev_read_int(lib->dev_bad_rsvd, dev_num, &info->bad_rsvd)) - return -1; - if (dev_read_ll(lib->dev_max_ec, dev_num, &info->max_ec)) - return -1; - if (dev_read_int(lib->dev_max_vols, dev_num, &info->max_vol_count)) - return -1; - if (dev_read_int(lib->dev_min_io_size, dev_num, &info->min_io_size)) - return -1; - - info->avail_bytes = info->avail_lebs * info->leb_size; - info->total_bytes = info->total_lebs * info->leb_size; - - return 0; - -out_close: - closedir(sysfs_ubi); - return -1; -} - -int ubi_get_dev_info(libubi_t desc, const char *node, struct ubi_dev_info *info) -{ - int dev_num; - struct libubi *lib = (struct libubi *)desc; - - if (dev_node2num(lib, node, &dev_num)) - return -1; - - return ubi_get_dev_info1(desc, dev_num, info); -} - -int ubi_get_vol_info1(libubi_t desc, int dev_num, int vol_id, - struct ubi_vol_info *info) -{ - int ret; - struct libubi *lib = (struct libubi *)desc; - char buf[50]; - - memset(info, '\0', sizeof(struct ubi_vol_info)); - info->dev_num = dev_num; - info->vol_id = vol_id; - - if (dev_get_major(lib, dev_num, &info->dev_major, &info->dev_minor)) - return -1; - if (vol_get_major(lib, dev_num, vol_id, &info->major, &info->minor)) - return -1; - - ret = vol_read_data(lib->vol_type, dev_num, vol_id, buf, 50); - if (ret < 0) - return -1; - - if (strncmp(buf, "static\n", ret) == 0) - info->type = UBI_STATIC_VOLUME; - else if (strncmp(buf, "dynamic\n", ret) == 0) - info->type = UBI_DYNAMIC_VOLUME; - else { - errmsg("bad value at \"%s\"", buf); - errno = EINVAL; - return -1; - } - - ret = vol_read_int(lib->vol_alignment, dev_num, vol_id, - &info->alignment); - if (ret) - return -1; - ret = vol_read_ll(lib->vol_data_bytes, dev_num, vol_id, - &info->data_bytes); - if (ret) - return -1; - ret = vol_read_int(lib->vol_rsvd_ebs, dev_num, vol_id, &info->rsvd_lebs); - if (ret) - return -1; - ret = vol_read_int(lib->vol_eb_size, dev_num, vol_id, &info->leb_size); - if (ret) - return -1; - ret = vol_read_int(lib->vol_corrupted, dev_num, vol_id, - &info->corrupted); - if (ret) - return -1; - info->rsvd_bytes = info->leb_size * info->rsvd_lebs; - - ret = vol_read_data(lib->vol_name, dev_num, vol_id, &info->name, - UBI_VOL_NAME_MAX + 2); - if (ret < 0) - return -1; - - info->name[ret - 1] = '\0'; - return 0; -} - -int ubi_get_vol_info(libubi_t desc, const char *node, struct ubi_vol_info *info) -{ - int vol_id, dev_num; - struct libubi *lib = (struct libubi *)desc; - - if (vol_node2nums(lib, node, &dev_num, &vol_id)) - return -1; - - return ubi_get_vol_info1(desc, dev_num, vol_id, info); -} - -int ubi_get_vol_info1_nm(libubi_t desc, int dev_num, const char *name, - struct ubi_vol_info *info) -{ - int i, err; - unsigned int nlen = strlen(name); - struct ubi_dev_info dev_info; - - if (nlen == 0) { - errmsg("bad \"name\" input parameter"); - errno = EINVAL; - return -1; - } - - err = ubi_get_dev_info1(desc, dev_num, &dev_info); - if (err) - return err; - - for (i = dev_info.lowest_vol_id; - i <= dev_info.highest_vol_id; i++) { - err = ubi_get_vol_info1(desc, dev_num, i, info); - if (err == -1) { - if (errno == ENOENT) - continue; - return -1; - } - - if (nlen == strlen(info->name) && !strcmp(name, info->name)) - return 0; - } - - errno = ENOENT; - return -1; -} diff --git a/ubi-utils/new-utils/src/libubigen.c b/ubi-utils/new-utils/src/libubigen.c deleted file mode 100644 index 91bb274..0000000 --- a/ubi-utils/new-utils/src/libubigen.c +++ /dev/null @@ -1,330 +0,0 @@ -/* - * Copyright (c) International Business Machines Corp., 2006 - * Copyright (C) 2008 Nokia Corporation - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -/* - * Generating UBI images. - * - * Authors: Oliver Lohmann - * Artem Bityutskiy - */ - -#include <stdlib.h> -#include <stdint.h> -#include <unistd.h> -#include <string.h> - -#include <mtd/ubi-media.h> -#include <mtd_swab.h> -#include <libubigen.h> -#include "crc32.h" -#include "common.h" - -#define PROGRAM_NAME "libubigen" - -/** - * ubigen_info_init - initialize libubigen. - * @ui: libubigen information - * @peb_size: flash physical eraseblock size - * @min_io_size: flash minimum input/output unit size - * @subpage_size: flash sub-page, if present (has to be equivalent to - * @min_io_size if does not exist) - * @vid_hdr_offs: offset of the VID header - * @ubi_ver: UBI version - */ -void ubigen_info_init(struct ubigen_info *ui, int peb_size, int min_io_size, - int subpage_size, int vid_hdr_offs, int ubi_ver) -{ - if (!vid_hdr_offs) { - vid_hdr_offs = UBI_EC_HDR_SIZE + subpage_size - 1; - vid_hdr_offs /= subpage_size; - vid_hdr_offs *= subpage_size; - } - - ui->peb_size = peb_size; - ui->min_io_size = min_io_size; - ui->vid_hdr_offs = vid_hdr_offs; - ui->data_offs = vid_hdr_offs + UBI_VID_HDR_SIZE + min_io_size - 1; - ui->data_offs /= min_io_size; - ui->data_offs *= min_io_size; - ui->leb_size = peb_size - ui->data_offs; - ui->ubi_ver = ubi_ver; - - ui->max_volumes = ui->leb_size / UBI_VTBL_RECORD_SIZE; - if (ui->max_volumes > UBI_MAX_VOLUMES) - ui->max_volumes = UBI_MAX_VOLUMES; - ui->vtbl_size = ui->max_volumes * UBI_VTBL_RECORD_SIZE; -} - -/** - * ubigen_create_empty_vtbl - creates empty volume table. - * - * This function creates an empty volume table and returns a pointer to it in - * case of success and %NULL in case of failure. The returned object has to be - * freed with 'free()' call. - */ -struct ubi_vtbl_record *ubigen_create_empty_vtbl(const struct ubigen_info *ui) -{ - struct ubi_vtbl_record *vtbl; - int i; - - vtbl = calloc(1, ui->vtbl_size); - if (!vtbl) { - sys_errmsg("cannot allocate %d bytes of memory", ui->vtbl_size); - return NULL; - } - - for (i = 0; i < ui->max_volumes; i++) { - uint32_t crc = crc32(UBI_CRC32_INIT, &vtbl[i], - UBI_VTBL_RECORD_SIZE_CRC); - vtbl[i].crc = cpu_to_be32(crc); - } - - return vtbl; -} - -/** - * ubigen_add_volume - add a volume to the volume table. - * @ui: libubigen information - * @vi: volume information - * @vtbl: volume table to add to - * - * This function adds volume described by input parameters to the volume table - * @vtbl. - */ -int ubigen_add_volume(const struct ubigen_info *ui, - const struct ubigen_vol_info *vi, - struct ubi_vtbl_record *vtbl) -{ - struct ubi_vtbl_record *vtbl_rec = &vtbl[vi->id]; - uint32_t tmp; - - if (vi->id >= ui->max_volumes) - return errmsg("too high volume id %d, max. volumes is %d", - vi->id, ui->max_volumes); - - if (vi->alignment >= ui->leb_size) - return errmsg("too large alignment %d, max is %d (LEB size)", - vi->alignment, ui->leb_size); - - memset(vtbl_rec, '\0', sizeof(struct ubi_vtbl_record)); - tmp = (vi->bytes + ui->leb_size - 1) / ui->leb_size; - vtbl_rec->reserved_pebs = cpu_to_be32(tmp); - vtbl_rec->alignment = cpu_to_be32(vi->alignment); - vtbl_rec->vol_type = vi->type; - tmp = ui->leb_size % vi->alignment; - vtbl_rec->data_pad = cpu_to_be32(tmp); - vtbl_rec->flags = vi->flags; - - memcpy(vtbl_rec->name, vi->name, vi->name_len); - vtbl_rec->name[vi->name_len] = '\0'; - vtbl_rec->name_len = cpu_to_be16(vi->name_len); - - tmp = crc32(UBI_CRC32_INIT, vtbl_rec, UBI_VTBL_RECORD_SIZE_CRC); - vtbl_rec->crc = cpu_to_be32(tmp); - return 0; -} - -/** - * ubigen_init_ec_hdr - initialize EC header. - * @ui: libubigen information - * @hdr: the EC header to initialize - * @ec: erase counter value - */ -void ubigen_init_ec_hdr(const struct ubigen_info *ui, - struct ubi_ec_hdr *hdr, long long ec) -{ - uint32_t crc; - - memset(hdr, '\0', sizeof(struct ubi_ec_hdr)); - - hdr->magic = cpu_to_be32(UBI_EC_HDR_MAGIC); - hdr->version = ui->ubi_ver; - hdr->ec = cpu_to_be64(ec); - hdr->vid_hdr_offset = cpu_to_be32(ui->vid_hdr_offs); - - hdr->data_offset = cpu_to_be32(ui->data_offs); - - crc = crc32(UBI_CRC32_INIT, hdr, UBI_EC_HDR_SIZE_CRC); - hdr->hdr_crc = cpu_to_be32(crc); -} - -/** - * init_vid_hdr - initialize VID header. - * @ui: libubigen information - * @vi: volume information - * @hdr: the VID header to initialize - * @lnum: logical eraseblock number - * @data: the contents of the LEB (static volumes only) - * @data_size: amount of data in this LEB (static volumes only) - * - * Note, @used_ebs, @data and @data_size are ignored in case of dynamic - * volumes. - */ -static void init_vid_hdr(const struct ubigen_info *ui, - const struct ubigen_vol_info *vi, - struct ubi_vid_hdr *hdr, int lnum, - const void *data, int data_size) -{ - uint32_t crc; - - memset(hdr, '\0', sizeof(struct ubi_vid_hdr)); - - hdr->magic = cpu_to_be32(UBI_VID_HDR_MAGIC); - hdr->version = ui->ubi_ver; - hdr->vol_type = vi->type; - hdr->vol_id = cpu_to_be32(vi->id); - hdr->lnum = cpu_to_be32(lnum); - hdr->data_pad = cpu_to_be32(vi->data_pad); - hdr->compat = vi->compat; - - if (vi->type == UBI_VID_STATIC) { - hdr->data_size = cpu_to_be32(data_size); - hdr->used_ebs = cpu_to_be32(vi->used_ebs); - crc = crc32(UBI_CRC32_INIT, data, data_size); - hdr->data_crc = cpu_to_be32(crc); - } - - crc = crc32(UBI_CRC32_INIT, hdr, UBI_VID_HDR_SIZE_CRC); - hdr->hdr_crc = cpu_to_be32(crc); -} - -/** - * ubigen_write_volume - write UBI volume. - * @ui: libubigen information - * @vi: volume information - * @ec: erase coutner value to put to EC headers - * @bytes: volume size in bytes - * @in: input file descriptor (has to be properly seeked) - * @out: output file descriptor - * - * This function reads the contents of the volume from the input file @in and - * writes the UBI volume to the output file @out. Returns zero on success and - * %-1 on failure. - */ -int ubigen_write_volume(const struct ubigen_info *ui, - const struct ubigen_vol_info *vi, long long ec, - long long bytes, int in, int out) -{ - int len = vi->usable_leb_size, rd, lnum = 0; - char inbuf[ui->leb_size], outbuf[ui->peb_size]; - - if (vi->id >= ui->max_volumes) - return errmsg("too high volume id %d, max. volumes is %d", - vi->id, ui->max_volumes); - - if (vi->alignment >= ui->leb_size) - return errmsg("too large alignment %d, max is %d (LEB size)", - vi->alignment, ui->leb_size); - - memset(outbuf, 0xFF, ui->data_offs); - ubigen_init_ec_hdr(ui, (struct ubi_ec_hdr *)outbuf, ec); - - while (bytes) { - int l; - struct ubi_vid_hdr *vid_hdr; - - if (bytes < len) - len = bytes; - bytes -= len; - - l = len; - do { - rd = read(in, inbuf + len - l, l); - if (rd != l) - return sys_errmsg("cannot read %d bytes from the input file", l); - - l -= rd; - } while (l); - - vid_hdr = (struct ubi_vid_hdr *)(&outbuf[ui->vid_hdr_offs]); - init_vid_hdr(ui, vi, vid_hdr, lnum, inbuf, len); - - memcpy(outbuf + ui->data_offs, inbuf, len); - memset(outbuf + ui->data_offs + len, 0xFF, - ui->peb_size - ui->data_offs - len); - - if (write(out, outbuf, ui->peb_size) != ui->peb_size) - return sys_errmsg("cannot write %d bytes to the output file", ui->peb_size); - - lnum += 1; - } - - return 0; -} - -/** - * ubigen_write_layout_vol - write UBI layout volume - * @ui: libubigen information - * @peb1: physical eraseblock number to write the first volume table copy - * @peb2: physical eraseblock number to write the second volume table copy - * @ec1: erase counter value for @peb1 - * @ec2: erase counter value for @peb1 - * @vtbl: volume table - * @fd: output file descriptor seeked to the proper position - * - * This function creates the UBI layout volume which contains 2 copies of the - * volume table. Returns zero in case of success and %-1 in case of failure. - */ -int ubigen_write_layout_vol(const struct ubigen_info *ui, int peb1, int peb2, - long long ec1, long long ec2, - struct ubi_vtbl_record *vtbl, int fd) -{ - int ret; - struct ubigen_vol_info vi; - char outbuf[ui->peb_size]; - struct ubi_vid_hdr *vid_hdr; - off_t seek; - - vi.bytes = ui->leb_size * UBI_LAYOUT_VOLUME_EBS; - vi.id = UBI_LAYOUT_VOLUME_ID; - vi.alignment = UBI_LAYOUT_VOLUME_ALIGN; - vi.data_pad = ui->leb_size % UBI_LAYOUT_VOLUME_ALIGN; - vi.usable_leb_size = ui->leb_size - vi.data_pad; - vi.data_pad = ui->leb_size - vi.usable_leb_size; - vi.type = UBI_LAYOUT_VOLUME_TYPE; - vi.name = UBI_LAYOUT_VOLUME_NAME; - vi.name_len = strlen(UBI_LAYOUT_VOLUME_NAME); - vi.compat = UBI_LAYOUT_VOLUME_COMPAT; - - memset(outbuf, 0xFF, ui->data_offs); - vid_hdr = (struct ubi_vid_hdr *)(&outbuf[ui->vid_hdr_offs]); - memcpy(outbuf + ui->data_offs, vtbl, ui->vtbl_size); - memset(outbuf + ui->data_offs + ui->vtbl_size, 0xFF, - ui->peb_size - ui->data_offs - ui->vtbl_size); - - seek = peb1 * ui->peb_size; - if (lseek(fd, seek, SEEK_SET) != seek) - return sys_errmsg("cannot seek output file"); - ubigen_init_ec_hdr(ui, (struct ubi_ec_hdr *)outbuf, ec1); - init_vid_hdr(ui, &vi, vid_hdr, 0, NULL, 0); - ret = write(fd, outbuf, ui->peb_size); - if (ret != ui->peb_size) - return sys_errmsg("cannot write %d bytes", ui->peb_size); - - seek = peb2 * ui->peb_size; - if (lseek(fd, seek, SEEK_SET) != seek) - return sys_errmsg("cannot seek output file"); - ubigen_init_ec_hdr(ui, (struct ubi_ec_hdr *)outbuf, ec2); - init_vid_hdr(ui, &vi, vid_hdr, 1, NULL, 0); - ret = write(fd, outbuf, ui->peb_size); - if (ret != ui->peb_size) - return sys_errmsg("cannot write %d bytes", ui->peb_size); - - return 0; -} diff --git a/ubi-utils/old-utils/.gitignore b/ubi-utils/old-utils/.gitignore new file mode 100644 index 0000000..83e8b71 --- /dev/null +++ b/ubi-utils/old-utils/.gitignore @@ -0,0 +1,9 @@ +/bin2nand +/mkbootenv +/nand2bin +/pddcustomize +/pfi2bin +/pfiflash +/ubigen +/ubimirror +/unubi diff --git a/ubi-utils/old-utils/Makefile b/ubi-utils/old-utils/Makefile new file mode 100644 index 0000000..5d20592 --- /dev/null +++ b/ubi-utils/old-utils/Makefile @@ -0,0 +1,59 @@ +# +# Makefile for ubi-utils +# + +KERNELHDR := ../../include + +CFLAGS ?= -O2 -g -Werror +CPPFLAGS += -I./inc -I./src -I$(KERNELHDR) \ + -std=gnu99 -DPACKAGE_VERSION=\"1.0\" + +PERLPROGS = mkpfi ubicrc32.pl + +TARGETS = pfiflash pddcustomize ubimirror bin2nand nand2bin ubigen \ + mkbootenv unubi pfi2bin + +vpath %.c ./src + +include ../../common.mk + +$(BUILDDIR)/pddcustomize: $(addprefix $(BUILDDIR)/,\ + pddcustomize.o error.o libubimirror.o bootenv.o hashmap.o \ + libubi.o crc32.o) + +$(BUILDDIR)/pfiflash: $(addprefix $(BUILDDIR)/,\ + pfiflash.o libpfiflash.o list.o reader.o error.o libubimirror.o \ + bootenv.o hashmap.o pfi.o libubi.o crc32.o) + +$(BUILDDIR)/ubimirror: $(addprefix $(BUILDDIR)/,\ + ubimirror.o error.o libubimirror.o bootenv.o hashmap.o \ + libubi.o crc32.o) + +$(BUILDDIR)/nand2bin: $(addprefix $(BUILDDIR)/,\ + nand2bin.o nandecc.o nandcorr.o) + +$(BUILDDIR)/bin2nand: $(addprefix $(BUILDDIR)/,\ + bin2nand.o error.o nandecc.o) + +$(BUILDDIR)/ubigen: $(addprefix $(BUILDDIR)/,\ + ubigen.o libubigen.o crc32.o) + +$(BUILDDIR)/mkbootenv: $(addprefix $(BUILDDIR)/,\ + mkbootenv.o bootenv.o hashmap.o error.o crc32.o) + +$(BUILDDIR)/unubi: $(addprefix $(BUILDDIR)/,\ + unubi.o crc32.o unubi_analyze.o eb_chain.o) + +$(BUILDDIR)/pfi2bin: $(addprefix $(BUILDDIR)/,\ + pfi2bin.o peb.o error.o list.o crc32.o libubigen.o bootenv.o \ + hashmap.o reader.o pfi.o) + +install:: + mkdir -p ${DESTDIR}/${SBINDIR} + install -m 0755 ${TARGETS} ${DESTDIR}/${SBINDIR}/ + (cd perl && install ${PERLPROGS} ${DESTDIR}/${SBINDIR}/) + +uninstall: + for file in ${TARGETS} ${PERLPROGS}; do \ + $(RM) ${DESTDIR}/${SBINDIR}/$$file; \ + done diff --git a/ubi-utils/README b/ubi-utils/old-utils/README index d976a76..d976a76 100644 --- a/ubi-utils/README +++ b/ubi-utils/old-utils/README diff --git a/ubi-utils/UBI.TXT b/ubi-utils/old-utils/UBI.TXT index 9a1c3c7..9a1c3c7 100644 --- a/ubi-utils/UBI.TXT +++ b/ubi-utils/old-utils/UBI.TXT diff --git a/ubi-utils/doc/unubi.roff b/ubi-utils/old-utils/doc/unubi.roff index 6cebc46..6cebc46 100644 --- a/ubi-utils/doc/unubi.roff +++ b/ubi-utils/old-utils/doc/unubi.roff diff --git a/ubi-utils/inc/libubi.h b/ubi-utils/old-utils/inc/libubi.h index 82824bd..82824bd 100644 --- a/ubi-utils/inc/libubi.h +++ b/ubi-utils/old-utils/inc/libubi.h diff --git a/ubi-utils/lib/Makefile.am b/ubi-utils/old-utils/lib/Makefile.am index 1b0dc01..1b0dc01 100644 --- a/ubi-utils/lib/Makefile.am +++ b/ubi-utils/old-utils/lib/Makefile.am diff --git a/ubi-utils/perl/f128_nand_sample.cfg b/ubi-utils/old-utils/perl/f128_nand_sample.cfg index e468d9d..e468d9d 100644 --- a/ubi-utils/perl/f128_nand_sample.cfg +++ b/ubi-utils/old-utils/perl/f128_nand_sample.cfg diff --git a/ubi-utils/perl/f64_nor_sample.cfg b/ubi-utils/old-utils/perl/f64_nor_sample.cfg index fd44e27..fd44e27 100644 --- a/ubi-utils/perl/f64_nor_sample.cfg +++ b/ubi-utils/old-utils/perl/f64_nor_sample.cfg diff --git a/ubi-utils/perl/mkpfi b/ubi-utils/old-utils/perl/mkpfi index 2cce587..2cce587 100755 --- a/ubi-utils/perl/mkpfi +++ b/ubi-utils/old-utils/perl/mkpfi diff --git a/ubi-utils/perl/ubicrc32.pl b/ubi-utils/old-utils/perl/ubicrc32.pl index add5f9d..add5f9d 100755 --- a/ubi-utils/perl/ubicrc32.pl +++ b/ubi-utils/old-utils/perl/ubicrc32.pl diff --git a/ubi-utils/scripts/Makefile b/ubi-utils/old-utils/scripts/Makefile index ebd9bc6..ebd9bc6 100644 --- a/ubi-utils/scripts/Makefile +++ b/ubi-utils/old-utils/scripts/Makefile diff --git a/ubi-utils/scripts/README b/ubi-utils/old-utils/scripts/README index 899b4a1..899b4a1 100644 --- a/ubi-utils/scripts/README +++ b/ubi-utils/old-utils/scripts/README diff --git a/ubi-utils/scripts/TODO b/ubi-utils/old-utils/scripts/TODO index f093e77..f093e77 100644 --- a/ubi-utils/scripts/TODO +++ b/ubi-utils/old-utils/scripts/TODO diff --git a/ubi-utils/scripts/bin2nand2bin_test.sh b/ubi-utils/old-utils/scripts/bin2nand2bin_test.sh index a17c91b..a17c91b 100644 --- a/ubi-utils/scripts/bin2nand2bin_test.sh +++ b/ubi-utils/old-utils/scripts/bin2nand2bin_test.sh diff --git a/ubi-utils/scripts/inject_biterror.pl b/ubi-utils/old-utils/scripts/inject_biterror.pl index b4a862a..b4a862a 100644 --- a/ubi-utils/scripts/inject_biterror.pl +++ b/ubi-utils/old-utils/scripts/inject_biterror.pl diff --git a/ubi-utils/scripts/jffs2_test.sh b/ubi-utils/old-utils/scripts/jffs2_test.sh index 0cc9f0c..0cc9f0c 100755 --- a/ubi-utils/scripts/jffs2_test.sh +++ b/ubi-utils/old-utils/scripts/jffs2_test.sh diff --git a/ubi-utils/scripts/mkdevs.pl b/ubi-utils/old-utils/scripts/mkdevs.pl index f0fd464..f0fd464 100755 --- a/ubi-utils/scripts/mkdevs.pl +++ b/ubi-utils/old-utils/scripts/mkdevs.pl diff --git a/ubi-utils/scripts/pdd.txt b/ubi-utils/old-utils/scripts/pdd.txt index a3ad915..a3ad915 100644 --- a/ubi-utils/scripts/pdd.txt +++ b/ubi-utils/old-utils/scripts/pdd.txt diff --git a/ubi-utils/scripts/run_all.sh b/ubi-utils/old-utils/scripts/run_all.sh index 040bcbd..040bcbd 100755 --- a/ubi-utils/scripts/run_all.sh +++ b/ubi-utils/old-utils/scripts/run_all.sh diff --git a/ubi-utils/scripts/test.cfg b/ubi-utils/old-utils/scripts/test.cfg index 0b5ec48..0b5ec48 100644 --- a/ubi-utils/scripts/test.cfg +++ b/ubi-utils/old-utils/scripts/test.cfg diff --git a/ubi-utils/scripts/ubi_jffs2_test.sh b/ubi-utils/old-utils/scripts/ubi_jffs2_test.sh index 883903d..883903d 100755 --- a/ubi-utils/scripts/ubi_jffs2_test.sh +++ b/ubi-utils/old-utils/scripts/ubi_jffs2_test.sh diff --git a/ubi-utils/scripts/ubi_test.sh b/ubi-utils/old-utils/scripts/ubi_test.sh index 73e4b19..73e4b19 100755 --- a/ubi-utils/scripts/ubi_test.sh +++ b/ubi-utils/old-utils/scripts/ubi_test.sh diff --git a/ubi-utils/scripts/ubi_tools_test.sh b/ubi-utils/old-utils/scripts/ubi_tools_test.sh index 7f121f1..7f121f1 100755 --- a/ubi-utils/scripts/ubi_tools_test.sh +++ b/ubi-utils/old-utils/scripts/ubi_tools_test.sh diff --git a/ubi-utils/scripts/unubi_test.sh b/ubi-utils/old-utils/scripts/unubi_test.sh index 40dc2e2..40dc2e2 100644 --- a/ubi-utils/scripts/unubi_test.sh +++ b/ubi-utils/old-utils/scripts/unubi_test.sh diff --git a/ubi-utils/src/bin2nand.c b/ubi-utils/old-utils/src/bin2nand.c index c7c7ccc..c7c7ccc 100644 --- a/ubi-utils/src/bin2nand.c +++ b/ubi-utils/old-utils/src/bin2nand.c diff --git a/ubi-utils/src/bootenv.c b/ubi-utils/old-utils/src/bootenv.c index 78198fe..78198fe 100644 --- a/ubi-utils/src/bootenv.c +++ b/ubi-utils/old-utils/src/bootenv.c diff --git a/ubi-utils/src/bootenv.h b/ubi-utils/old-utils/src/bootenv.h index 8fecdbf..8fecdbf 100644 --- a/ubi-utils/src/bootenv.h +++ b/ubi-utils/old-utils/src/bootenv.h diff --git a/ubi-utils/src/config.h b/ubi-utils/old-utils/src/config.h index 55e60f3..55e60f3 100644 --- a/ubi-utils/src/config.h +++ b/ubi-utils/old-utils/src/config.h diff --git a/ubi-utils/old-utils/src/crc32.c b/ubi-utils/old-utils/src/crc32.c new file mode 100644 index 0000000..666e217 --- /dev/null +++ b/ubi-utils/old-utils/src/crc32.c @@ -0,0 +1,83 @@ +/* + * Copyright (c) International Business Machines Corp., 2006 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See + * the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Author: Thomas Gleixner + */ + +/* + * CRC32 functions + * + * Can be compiled as seperate object, but is included into the ipl source + * so gcc can inline the functions. We optimize for size so the omission of + * the function frame is helpful. + * + */ + +#include <stdint.h> +#include <crc32.h> + +/* CRC polynomial */ +#define CRC_POLY 0xEDB88320 + +/** + * init_crc32_table - Initialize crc table + * + * @table: pointer to the CRC table which must be initialized + * + * Create CRC32 table for given polynomial. The table is created with + * the lowest order term in the highest order bit. So the x^32 term + * has to implied in the crc calculation function. + */ +void init_crc32_table(uint32_t *table) +{ + uint32_t crc; + int i, j; + + for (i = 0; i < 256; i++) { + crc = i; + for (j = 8; j > 0; j--) { + if (crc & 1) + crc = (crc >> 1) ^ CRC_POLY; + else + crc >>= 1; + } + table[i] = crc; + } +} + +/** + * clc_crc32 - Calculate CRC32 over a buffer + * + * @table: pointer to the CRC table + * @crc: initial crc value + * @buf: pointer to the buffer + * @len: number of bytes to calc + * + * Returns the updated crc value. + * + * The algorithm resembles a hardware shift register, but calculates 8 + * bit at once. + */ +uint32_t clc_crc32(uint32_t *table, uint32_t crc, void *buf, + int len) +{ + const unsigned char *p = buf; + + while(--len >= 0) + crc = table[(crc ^ *p++) & 0xff] ^ (crc >> 8); + return crc; +} diff --git a/ubi-utils/old-utils/src/crc32.h b/ubi-utils/old-utils/src/crc32.h new file mode 100644 index 0000000..31362b0 --- /dev/null +++ b/ubi-utils/old-utils/src/crc32.h @@ -0,0 +1,36 @@ +#ifndef __CRC32_H__ +#define __CRC32_H__ +/* + * Copyright (c) International Business Machines Corp., 2006 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See + * the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* + * Author: Thomas Gleixner + * + * CRC32 functions + * + * Can be compiled as seperate object, but is included into the ipl source + * so gcc can inline the functions. We optimize for size so the omission of + * the function frame is helpful. + * + */ +#include <stdint.h> + +void init_crc32_table(uint32_t *table); +uint32_t clc_crc32(uint32_t *table, uint32_t crc, void *buf, int len); + +#endif /* __CRC32_H__ */ diff --git a/ubi-utils/src/eb_chain.c b/ubi-utils/old-utils/src/eb_chain.c index da5c2e3..da5c2e3 100644 --- a/ubi-utils/src/eb_chain.c +++ b/ubi-utils/old-utils/src/eb_chain.c diff --git a/ubi-utils/src/error.c b/ubi-utils/old-utils/src/error.c index 4aaedad..4aaedad 100644 --- a/ubi-utils/src/error.c +++ b/ubi-utils/old-utils/src/error.c diff --git a/ubi-utils/src/error.h b/ubi-utils/old-utils/src/error.h index 05d8078..05d8078 100644 --- a/ubi-utils/src/error.h +++ b/ubi-utils/old-utils/src/error.h diff --git a/ubi-utils/src/example_ubi.h b/ubi-utils/old-utils/src/example_ubi.h index 23c7b54..23c7b54 100644 --- a/ubi-utils/src/example_ubi.h +++ b/ubi-utils/old-utils/src/example_ubi.h diff --git a/ubi-utils/src/hashmap.c b/ubi-utils/old-utils/src/hashmap.c index 3511d56..3511d56 100644 --- a/ubi-utils/src/hashmap.c +++ b/ubi-utils/old-utils/src/hashmap.c diff --git a/ubi-utils/src/hashmap.h b/ubi-utils/old-utils/src/hashmap.h index 1b13e95..1b13e95 100644 --- a/ubi-utils/src/hashmap.h +++ b/ubi-utils/old-utils/src/hashmap.h diff --git a/ubi-utils/src/libpfiflash.c b/ubi-utils/old-utils/src/libpfiflash.c index b0d454a..b0d454a 100644 --- a/ubi-utils/src/libpfiflash.c +++ b/ubi-utils/old-utils/src/libpfiflash.c diff --git a/ubi-utils/old-utils/src/libubi.c b/ubi-utils/old-utils/src/libubi.c new file mode 100644 index 0000000..a536b47 --- /dev/null +++ b/ubi-utils/old-utils/src/libubi.c @@ -0,0 +1,915 @@ +/* + * Copyright (c) International Business Machines Corp., 2006 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See + * the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Author: Artem B. Bityutskiy + * + * UBI (Unsorted Block Images) library. + */ + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <fcntl.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <dirent.h> +#include <errno.h> +#include <unistd.h> +#include <sys/ioctl.h> +#include <limits.h> +#include "libubi.h" +#include "libubi_int.h" + +libubi_t libubi_open(void) +{ + int fd, version; + struct libubi *lib; + + lib = calloc(1, sizeof(struct libubi)); + if (!lib) + return NULL; + + /* TODO: this must be discovered instead */ + lib->sysfs = strdup("/sys"); + if (!lib->sysfs) + goto error; + + lib->sysfs_ubi = mkpath(lib->sysfs, SYSFS_UBI); + if (!lib->sysfs_ubi) + goto error; + + /* Make sure UBI is present */ + fd = open(lib->sysfs_ubi, O_RDONLY); + if (fd == -1) + goto error; + close(fd); + + lib->ubi_dev = mkpath(lib->sysfs_ubi, UBI_DEV_NAME_PATT); + if (!lib->ubi_dev) + goto error; + + lib->ubi_version = mkpath(lib->sysfs_ubi, UBI_VER); + if (!lib->ubi_version) + goto error; + + lib->dev_dev = mkpath(lib->ubi_dev, DEV_DEV); + if (!lib->dev_dev) + goto error; + + lib->dev_avail_ebs = mkpath(lib->ubi_dev, DEV_AVAIL_EBS); + if (!lib->dev_avail_ebs) + goto error; + + lib->dev_total_ebs = mkpath(lib->ubi_dev, DEV_TOTAL_EBS); + if (!lib->dev_total_ebs) + goto error; + + lib->dev_bad_count = mkpath(lib->ubi_dev, DEV_BAD_COUNT); + if (!lib->dev_bad_count) + goto error; + + lib->dev_eb_size = mkpath(lib->ubi_dev, DEV_EB_SIZE); + if (!lib->dev_eb_size) + goto error; + + lib->dev_max_ec = mkpath(lib->ubi_dev, DEV_MAX_EC); + if (!lib->dev_max_ec) + goto error; + + lib->dev_bad_rsvd = mkpath(lib->ubi_dev, DEV_MAX_RSVD); + if (!lib->dev_bad_rsvd) + goto error; + + lib->dev_max_vols = mkpath(lib->ubi_dev, DEV_MAX_VOLS); + if (!lib->dev_max_vols) + goto error; + + lib->dev_min_io_size = mkpath(lib->ubi_dev, DEV_MIN_IO_SIZE); + if (!lib->dev_min_io_size) + goto error; + + lib->ubi_vol = mkpath(lib->sysfs_ubi, UBI_VOL_NAME_PATT); + if (!lib->ubi_vol) + goto error; + + lib->vol_type = mkpath(lib->ubi_vol, VOL_TYPE); + if (!lib->vol_type) + goto error; + + lib->vol_dev = mkpath(lib->ubi_vol, VOL_DEV); + if (!lib->vol_dev) + goto error; + + lib->vol_alignment = mkpath(lib->ubi_vol, VOL_ALIGNMENT); + if (!lib->vol_alignment) + goto error; + + lib->vol_data_bytes = mkpath(lib->ubi_vol, VOL_DATA_BYTES); + if (!lib->vol_data_bytes) + goto error; + + lib->vol_rsvd_ebs = mkpath(lib->ubi_vol, VOL_RSVD_EBS); + if (!lib->vol_rsvd_ebs) + goto error; + + lib->vol_eb_size = mkpath(lib->ubi_vol, VOL_EB_SIZE); + if (!lib->vol_eb_size) + goto error; + + lib->vol_corrupted = mkpath(lib->ubi_vol, VOL_CORRUPTED); + if (!lib->vol_corrupted) + goto error; + + lib->vol_name = mkpath(lib->ubi_vol, VOL_NAME); + if (!lib->vol_name) + goto error; + + if (read_int(lib->ubi_version, &version)) + goto error; + if (version != LIBUBI_UBI_VERSION) { + fprintf(stderr, "LIBUBI: this library was made for UBI version " + "%d, but UBI version %d is detected\n", + LIBUBI_UBI_VERSION, version); + goto error; + } + + return lib; + +error: + free(lib->vol_corrupted); + free(lib->vol_eb_size); + free(lib->vol_rsvd_ebs); + free(lib->vol_data_bytes); + free(lib->vol_alignment); + free(lib->vol_dev); + free(lib->vol_type); + free(lib->ubi_vol); + free(lib->dev_min_io_size); + free(lib->dev_max_vols); + free(lib->dev_bad_rsvd); + free(lib->dev_max_ec); + free(lib->dev_eb_size); + free(lib->dev_bad_count); + free(lib->dev_total_ebs); + free(lib->dev_avail_ebs); + free(lib->dev_dev); + free(lib->ubi_version); + free(lib->ubi_dev); + free(lib->sysfs_ubi); + free(lib->sysfs); + free(lib); + return NULL; +} + +void libubi_close(libubi_t desc) +{ + struct libubi *lib = (struct libubi *)desc; + + free(lib->vol_name); + free(lib->vol_corrupted); + free(lib->vol_eb_size); + free(lib->vol_rsvd_ebs); + free(lib->vol_data_bytes); + free(lib->vol_alignment); + free(lib->vol_dev); + free(lib->vol_type); + free(lib->ubi_vol); + free(lib->dev_min_io_size); + free(lib->dev_max_vols); + free(lib->dev_bad_rsvd); + free(lib->dev_max_ec); + free(lib->dev_eb_size); + free(lib->dev_bad_count); + free(lib->dev_total_ebs); + free(lib->dev_avail_ebs); + free(lib->dev_dev); + free(lib->ubi_version); + free(lib->ubi_dev); + free(lib->sysfs_ubi); + free(lib->sysfs); + free(lib); +} + +int ubi_get_info(libubi_t desc, struct ubi_info *info) +{ + DIR *sysfs_ubi; + struct dirent *dirent; + struct libubi *lib = (struct libubi *)desc; + + memset(info, '\0', sizeof(struct ubi_info)); + + /* + * We have to scan the UBI sysfs directory to identify how many UBI + * devices are present. + */ + sysfs_ubi = opendir(lib->sysfs_ubi); + if (!sysfs_ubi) + return -1; + + info->lowest_dev_num = INT_MAX; + while ((dirent = readdir(sysfs_ubi))) { + char *name = &dirent->d_name[0]; + int dev_num, ret; + + ret = sscanf(name, UBI_DEV_NAME_PATT, &dev_num); + if (ret == 1) { + info->dev_count += 1; + if (dev_num > info->highest_dev_num) + info->highest_dev_num = dev_num; + if (dev_num < info->lowest_dev_num) + info->lowest_dev_num = dev_num; + } + } + + if (info->lowest_dev_num == INT_MAX) + info->lowest_dev_num = 0; + + if (read_int(lib->ubi_version, &info->version)) + goto close; + + return closedir(sysfs_ubi); + +close: + closedir(sysfs_ubi); + return -1; +} + +int ubi_mkvol(libubi_t desc, const char *node, struct ubi_mkvol_request *req) +{ + int fd, ret; + struct ubi_mkvol_req r; + size_t n; + + desc = desc; + r.vol_id = req->vol_id; + r.alignment = req->alignment; + r.bytes = req->bytes; + r.vol_type = req->vol_type; + + n = strlen(req->name); + if (n > UBI_MAX_VOLUME_NAME) + return -1; + + strncpy(r.name, req->name, UBI_MAX_VOLUME_NAME + 1); + r.name_len = n; + + fd = open(node, O_RDONLY); + if (fd == -1) + return -1; + + ret = ioctl(fd, UBI_IOCMKVOL, &r); + if (!ret) + req->vol_id = r.vol_id; + + close(fd); + return ret; +} + +int ubi_rmvol(libubi_t desc, const char *node, int vol_id) +{ + int fd, ret; + + desc = desc; + fd = open(node, O_RDONLY); + if (fd == -1) + return -1; + + ret = ioctl(fd, UBI_IOCRMVOL, &vol_id); + close(fd); + return ret; +} + +int ubi_rsvol(libubi_t desc, const char *node, int vol_id, long long bytes) +{ + int fd, ret; + struct ubi_rsvol_req req; + + desc = desc; + fd = open(node, O_RDONLY); + if (fd == -1) + return -1; + + req.bytes = bytes; + req.vol_id = vol_id; + + ret = ioctl(fd, UBI_IOCRSVOL, &req); + close(fd); + return ret; +} + +int ubi_update_start(libubi_t desc, int fd, long long bytes) +{ + desc = desc; + if (ioctl(fd, UBI_IOCVOLUP, &bytes)) + return -1; + return 0; +} + +int ubi_get_dev_info(libubi_t desc, const char *node, struct ubi_dev_info *info) +{ + int dev_num; + struct libubi *lib = (struct libubi *)desc; + + dev_num = find_dev_num(lib, node); + if (dev_num == -1) + return -1; + + return ubi_get_dev_info1(desc, dev_num, info); +} + +int ubi_get_dev_info1(libubi_t desc, int dev_num, struct ubi_dev_info *info) +{ + DIR *sysfs_ubi; + struct dirent *dirent; + struct libubi *lib = (struct libubi *)desc; + + memset(info, '\0', sizeof(struct ubi_dev_info)); + info->dev_num = dev_num; + + sysfs_ubi = opendir(lib->sysfs_ubi); + if (!sysfs_ubi) + return -1; + + info->lowest_vol_num = INT_MAX; + while ((dirent = readdir(sysfs_ubi))) { + char *name = &dirent->d_name[0]; + int vol_id, ret, devno; + + ret = sscanf(name, UBI_VOL_NAME_PATT, &devno, &vol_id); + if (ret == 2 && devno == dev_num) { + info->vol_count += 1; + if (vol_id > info->highest_vol_num) + info->highest_vol_num = vol_id; + if (vol_id < info->lowest_vol_num) + info->lowest_vol_num = vol_id; + } + } + + closedir(sysfs_ubi); + + if (info->lowest_vol_num == INT_MAX) + info->lowest_vol_num = 0; + + if (dev_read_int(lib->dev_avail_ebs, dev_num, &info->avail_ebs)) + return -1; + if (dev_read_int(lib->dev_total_ebs, dev_num, &info->total_ebs)) + return -1; + if (dev_read_int(lib->dev_bad_count, dev_num, &info->bad_count)) + return -1; + if (dev_read_int(lib->dev_eb_size, dev_num, &info->eb_size)) + return -1; + if (dev_read_int(lib->dev_bad_rsvd, dev_num, &info->bad_rsvd)) + return -1; + if (dev_read_ll(lib->dev_max_ec, dev_num, &info->max_ec)) + return -1; + if (dev_read_int(lib->dev_max_vols, dev_num, &info->max_vol_count)) + return -1; + if (dev_read_int(lib->dev_min_io_size, dev_num, &info->min_io_size)) + return -1; + + info->avail_bytes = info->avail_ebs * info->eb_size; + info->total_bytes = info->total_ebs * info->eb_size; + + return 0; +} + +int ubi_get_vol_info(libubi_t desc, const char *node, struct ubi_vol_info *info) +{ + int vol_id, dev_num; + struct libubi *lib = (struct libubi *)desc; + + dev_num = find_dev_num_vol(lib, node); + if (dev_num == -1) + return -1; + + vol_id = find_vol_num(lib, dev_num, node); + if (vol_id == -1) + return -1; + + return ubi_get_vol_info1(desc, dev_num, vol_id, info); +} + +int ubi_get_vol_info1(libubi_t desc, int dev_num, int vol_id, + struct ubi_vol_info *info) +{ + int ret; + struct libubi *lib = (struct libubi *)desc; + char buf[50]; + + memset(info, '\0', sizeof(struct ubi_vol_info)); + info->dev_num = dev_num; + info->vol_id = vol_id; + + ret = vol_read_data(lib->vol_type, dev_num, vol_id, &buf[0], 50); + if (ret < 0) + return -1; + + if (strncmp(&buf[0], "static\n", ret) == 0) + info->type = UBI_STATIC_VOLUME; + else if (strncmp(&buf[0], "dynamic\n", ret) == 0) + info->type = UBI_DYNAMIC_VOLUME; + else { + fprintf(stderr, "LIBUBI: bad value at sysfs file\n"); + errno = EINVAL; + return -1; + } + + ret = vol_read_int(lib->vol_alignment, dev_num, vol_id, + &info->alignment); + if (ret) + return -1; + ret = vol_read_ll(lib->vol_data_bytes, dev_num, vol_id, + &info->data_bytes); + if (ret) + return -1; + ret = vol_read_int(lib->vol_rsvd_ebs, dev_num, vol_id, &info->rsvd_ebs); + if (ret) + return -1; + ret = vol_read_int(lib->vol_eb_size, dev_num, vol_id, &info->eb_size); + if (ret) + return -1; + ret = vol_read_int(lib->vol_corrupted, dev_num, vol_id, + &info->corrupted); + if (ret) + return -1; + info->rsvd_bytes = info->eb_size * info->rsvd_ebs; + + ret = vol_read_data(lib->vol_name, dev_num, vol_id, &info->name, + UBI_VOL_NAME_MAX + 2); + if (ret < 0) + return -1; + + info->name[ret - 1] = '\0'; + return 0; +} + +/** + * read_int - read an 'int' value from a file. + * + * @file the file to read from + * @value the result is stored here + * + * This function returns %0 in case of success and %-1 in case of failure. + */ +static int read_int(const char *file, int *value) +{ + int fd, rd; + char buf[50]; + + fd = open(file, O_RDONLY); + if (fd == -1) + return -1; + + rd = read(fd, &buf[0], 50); + if (rd == -1) + goto error; + + if (sscanf(&buf[0], "%d\n", value) != 1) { + /* This must be a UBI bug */ + fprintf(stderr, "LIBUBI: bad value at sysfs file\n"); + errno = EINVAL; + goto error; + } + + close(fd); + return 0; + +error: + close(fd); + return -1; +} + +/** + * dev_read_int - read an 'int' value from an UBI device's sysfs file. + * + * @patt the file pattern to read from + * @dev_num UBI device number + * @value the result is stored here + * + * This function returns %0 in case of success and %-1 in case of failure. + */ +static int dev_read_int(const char *patt, int dev_num, int *value) +{ + int fd, rd; + char buf[50]; + char file[strlen(patt) + 50]; + + sprintf(&file[0], patt, dev_num); + fd = open(&file[0], O_RDONLY); + if (fd == -1) + return -1; + + rd = read(fd, &buf[0], 50); + if (rd == -1) + goto error; + + if (sscanf(&buf[0], "%d\n", value) != 1) { + /* This must be a UBI bug */ + fprintf(stderr, "LIBUBI: bad value at sysfs file\n"); + errno = EINVAL; + goto error; + } + + close(fd); + return 0; + +error: + close(fd); + return -1; +} + +/** + * dev_read_ll - read a 'long long' value from an UBI device's sysfs file. + * + * @patt the file pattern to read from + * @dev_num UBI device number + * @value the result is stored here + * + * This function returns %0 in case of success and %-1 in case of failure. + */ +static int dev_read_ll(const char *patt, int dev_num, long long *value) +{ + int fd, rd; + char buf[50]; + char file[strlen(patt) + 50]; + + sprintf(&file[0], patt, dev_num); + fd = open(&file[0], O_RDONLY); + if (fd == -1) + return -1; + + rd = read(fd, &buf[0], 50); + if (rd == -1) + goto error; + + if (sscanf(&buf[0], "%lld\n", value) != 1) { + /* This must be a UBI bug */ + fprintf(stderr, "LIBUBI: bad value at sysfs file\n"); + errno = EINVAL; + goto error; + } + + close(fd); + return 0; + +error: + close(fd); + return -1; +} + +/** + * dev_read_data - read data from an UBI device's sysfs file. + * + * @patt the file pattern to read from + * @dev_num UBI device number + * @buf buffer to read data to + * @buf_len buffer length + * + * This function returns number of read bytes in case of success and %-1 in + * case of failure. + */ +static int dev_read_data(const char *patt, int dev_num, void *buf, int buf_len) +{ + int fd, rd; + char file[strlen(patt) + 50]; + + sprintf(&file[0], patt, dev_num); + fd = open(&file[0], O_RDONLY); + if (fd == -1) + return -1; + + rd = read(fd, buf, buf_len); + if (rd == -1) { + close(fd); + return -1; + } + + close(fd); + return rd; +} + +/** + * vol_read_int - read an 'int' value from an UBI volume's sysfs file. + * + * @patt the file pattern to read from + * @dev_num UBI device number + * @vol_id volume identifier + * @value the result is stored here + * + * This function returns %0 in case of success and %-1 in case of failure. + */ +static int vol_read_int(const char *patt, int dev_num, int vol_id, int *value) +{ + int fd, rd; + char buf[50]; + char file[strlen(patt) + 100]; + + sprintf(&file[0], patt, dev_num, vol_id); + fd = open(&file[0], O_RDONLY); + if (fd == -1) + return -1; + + rd = read(fd, &buf[0], 50); + if (rd == -1) + goto error; + + if (sscanf(&buf[0], "%d\n", value) != 1) { + /* This must be a UBI bug */ + fprintf(stderr, "LIBUBI: bad value at sysfs file\n"); + errno = EINVAL; + goto error; + } + + close(fd); + return 0; + +error: + close(fd); + return -1; +} + +/** + * vol_read_ll - read a 'long long' value from an UBI volume's sysfs file. + * + * @patt the file pattern to read from + * @dev_num UBI device number + * @vol_id volume identifier + * @value the result is stored here + * + * This function returns %0 in case of success and %-1 in case of failure. + */ +static int vol_read_ll(const char *patt, int dev_num, int vol_id, + long long *value) +{ + int fd, rd; + char buf[50]; + char file[strlen(patt) + 100]; + + sprintf(&file[0], patt, dev_num, vol_id); + fd = open(&file[0], O_RDONLY); + if (fd == -1) + return -1; + + rd = read(fd, &buf[0], 50); + if (rd == -1) + goto error; + + if (sscanf(&buf[0], "%lld\n", value) != 1) { + /* This must be a UBI bug */ + fprintf(stderr, "LIBUBI: bad value at sysfs file\n"); + errno = EINVAL; + goto error; + } + + close(fd); + return 0; + +error: + close(fd); + return -1; +} + +/** + * vol_read_data - read data from an UBI volume's sysfs file. + * + * @patt the file pattern to read from + * @dev_num UBI device number + * @vol_id volume identifier + * @buf buffer to read to + * @buf_len buffer length + * + * This function returns number of read bytes in case of success and %-1 in + * case of failure. + */ +static int vol_read_data(const char *patt, int dev_num, int vol_id, void *buf, + int buf_len) +{ + int fd, rd; + char file[strlen(patt) + 100]; + + sprintf(&file[0], patt, dev_num, vol_id); + fd = open(&file[0], O_RDONLY); + if (fd == -1) + return -1; + + rd = read(fd, buf, buf_len); + if (rd == -1) { + close(fd); + return -1; + } + + close(fd); + return rd; +} + +/** + * mkpath - compose full path from 2 given components. + * + * @path first component + * @name second component + * + * This function returns the resulting path in case of success and %NULL in + * case of failure. + */ +static char *mkpath(const char *path, const char *name) +{ + char *n; + int len1 = strlen(path); + int len2 = strlen(name); + + n = malloc(len1 + len2 + 2); + if (!n) + return NULL; + + memcpy(n, path, len1); + if (n[len1 - 1] != '/') + n[len1++] = '/'; + + memcpy(n + len1, name, len2 + 1); + return n; +} + +/** + * find_dev_num - find UBI device number by its character device node. + * + * @lib UBI library descriptor + * @node UBI character device node name + * + * This function returns positive UBI device number in case of success and %-1 + * in case of failure. + */ +static int find_dev_num(struct libubi *lib, const char *node) +{ + struct stat st; + struct ubi_info info; + int i, major, minor; + + if (stat(node, &st)) + return -1; + + if (!S_ISCHR(st.st_mode)) { + errno = EINVAL; + return -1; + } + + major = major(st.st_rdev); + minor = minor(st.st_rdev); + + if (minor != 0) { + errno = -EINVAL; + return -1; + } + + if (ubi_get_info((libubi_t *)lib, &info)) + return -1; + + for (i = info.lowest_dev_num; i <= info.highest_dev_num; i++) { + int major1, minor1, ret; + char buf[50]; + + ret = dev_read_data(lib->dev_dev, i, &buf[0], 50); + if (ret < 0) + return -1; + + ret = sscanf(&buf[0], "%d:%d\n", &major1, &minor1); + if (ret != 2) { + fprintf(stderr, "LIBUBI: bad value at sysfs file\n"); + errno = EINVAL; + return -1; + } + + if (minor1 == minor && major1 == major) + return i; + } + + errno = ENOENT; + return -1; +} + +/** + * find_dev_num_vol - find UBI device number by volume character device node. + * + * @lib UBI library descriptor + * @node UBI character device node name + * + * This function returns positive UBI device number in case of success and %-1 + * in case of failure. + */ +static int find_dev_num_vol(struct libubi *lib, const char *node) +{ + struct stat st; + struct ubi_info info; + int i, major; + + if (stat(node, &st)) + return -1; + + if (!S_ISCHR(st.st_mode)) { + errno = EINVAL; + return -1; + } + + major = major(st.st_rdev); + + if (minor(st.st_rdev) == 0) { + errno = -EINVAL; + return -1; + } + + if (ubi_get_info((libubi_t *)lib, &info)) + return -1; + + for (i = info.lowest_dev_num; i <= info.highest_dev_num; i++) { + int major1, minor1, ret; + char buf[50]; + + ret = dev_read_data(lib->dev_dev, i, &buf[0], 50); + if (ret < 0) + return -1; + + ret = sscanf(&buf[0], "%d:%d\n", &major1, &minor1); + if (ret != 2) { + fprintf(stderr, "LIBUBI: bad value at sysfs file\n"); + errno = EINVAL; + return -1; + } + + if (major1 == major) + return i; + } + + errno = ENOENT; + return -1; +} + +/** + * find_vol_num - find UBI volume number by its character device node. + * + * @lib UBI library descriptor + * @dev_num UBI device number + * @node UBI volume character device node name + * + * This function returns positive UBI volume number in case of success and %-1 + * in case of failure. + */ +static int find_vol_num(struct libubi *lib, int dev_num, const char *node) +{ + struct stat st; + struct ubi_dev_info info; + int i, major, minor; + + if (stat(node, &st)) + return -1; + + if (!S_ISCHR(st.st_mode)) { + errno = EINVAL; + return -1; + } + + major = major(st.st_rdev); + minor = minor(st.st_rdev); + + if (minor == 0) { + errno = -EINVAL; + return -1; + } + + if (ubi_get_dev_info1((libubi_t *)lib, dev_num, &info)) + return -1; + + for (i = info.lowest_vol_num; i <= info.highest_vol_num; i++) { + int major1, minor1, ret; + char buf[50]; + + ret = vol_read_data(lib->vol_dev, dev_num, i, &buf[0], 50); + if (ret < 0) + return -1; + + ret = sscanf(&buf[0], "%d:%d\n", &major1, &minor1); + if (ret != 2) { + fprintf(stderr, "LIBUBI: bad value at sysfs file\n"); + errno = EINVAL; + return -1; + } + + if (minor1 == minor && major1 == major) + return i; + } + + errno = ENOENT; + return -1; +} diff --git a/ubi-utils/new-utils/src/libubi_int.h b/ubi-utils/old-utils/src/libubi_int.h index 2e664b8..e68b791 100644 --- a/ubi-utils/new-utils/src/libubi_int.h +++ b/ubi-utils/old-utils/src/libubi_int.h @@ -15,7 +15,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * - * Author: Artem Bityutskiy + * Author: Artem B. Bityutskiy * * UBI (Unsorted Block Images) library. */ @@ -23,31 +23,20 @@ #ifndef __LIBUBI_INT_H__ #define __LIBUBI_INT_H__ -#include <string.h> -#include <errno.h> - #ifdef __cplusplus extern "C" { #endif /* + * UBI heavily makes use of the sysfs file system to interact with users-pace. * The below are pre-define UBI file and directory names. - * - * Note, older kernels put 'ubiX_Y' directories straight to '/sys/class/ubi/'. - * New kernels puts 'ubiX_Y' directories to '/sys/class/ubi/ubiX/', which is - * saner. And for compatibility reasons it also puts symlinks to 'ubiX_Y' - * directories to '/sys/class/ubi/'. For now libubi assumes old layout. */ #define SYSFS_UBI "class/ubi" -#define SYSFS_CTRL "class/misc/ubi_ctrl/" - -#define CTRL_DEV "dev" - -#define UBI_VER "version" #define UBI_DEV_NAME_PATT "ubi%d" - +#define UBI_VER "version" #define DEV_DEV "dev" +#define UBI_VOL_NAME_PATT "ubi%d_%d" #define DEV_AVAIL_EBS "avail_eraseblocks" #define DEV_TOTAL_EBS "total_eraseblocks" #define DEV_BAD_COUNT "bad_peb_count" @@ -56,9 +45,6 @@ extern "C" { #define DEV_MAX_RSVD "reserved_for_bad" #define DEV_MAX_VOLS "max_vol_count" #define DEV_MIN_IO_SIZE "min_io_size" -#define DEV_MTD_NUM "mtd_num" - -#define UBI_VOL_NAME_PATT "ubi%d_%d" #define VOL_TYPE "type" #define VOL_DEV "dev" #define VOL_ALIGNMENT "alignment" @@ -70,37 +56,34 @@ extern "C" { /** * libubi - UBI library description data structure. - * @sysfs: sysfs file system path - * @sysfs_ctrl: UBI control device directory in sysfs - * @ctrl_dev: UBI control device major/minor numbers sysfs file - * @sysfs_ubi: UBI directory in sysfs - * @ubi_dev: UBI device sysfs directory pattern - * @ubi_version: UBI version file sysfs path - * @dev_dev: UBI device major/minor numbers file pattern - * @dev_avail_ebs: count of available eraseblocks sysfs path pattern - * @dev_total_ebs: total eraseblocks count sysfs path pattern - * @dev_bad_count: count of bad eraseblocks sysfs path pattern - * @dev_eb_size: size of UBI device's eraseblocks sysfs path pattern - * @dev_max_ec: maximum erase counter sysfs path pattern - * @dev_bad_rsvd: count of physical eraseblock reserved for bad eraseblocks - * handling - * @dev_max_vols: maximum volumes number count sysfs path pattern - * @dev_min_io_size: minimum I/O unit size sysfs path pattern - * @ubi_vol: UBI volume sysfs directory pattern - * @vol_type: volume type sysfs path pattern - * @vol_dev: volume major/minor numbers file pattern - * @vol_alignment: volume alignment sysfs path pattern - * @vol_data_bytes: volume data size sysfs path pattern - * @vol_rsvd_ebs: volume reserved size sysfs path pattern - * @vol_eb_size: volume eraseblock size sysfs path pattern - * @vol_corrupted: volume corruption flag sysfs path pattern - * @vol_name: volume name sysfs path pattern + * + * @sysfs sysfs file system path + * @sysfs_ubi UBI directory in sysfs + * @ubi_dev UBI device sysfs directory pattern + * @ubi_version UBI version file sysfs path + * @dev_dev UBI device's major/minor numbers file pattern + * @dev_avail_ebs count of available eraseblocks sysfs path pattern + * @dev_total_ebs total eraseblocks count sysfs path pattern + * @dev_bad_count count of bad eraseblocks sysfs path pattern + * @dev_eb_size size of UBI device's eraseblocks sysfs path pattern + * @dev_max_ec maximum erase counter sysfs path pattern + * @dev_bad_rsvd count of physical eraseblock reserved for bad eraseblocks + * handling + * @dev_max_vols maximum volumes number count sysfs path pattern + * @dev_min_io_size minimum I/O unit size sysfs path pattern + * @ubi_vol UBI volume sysfs directory pattern + * @vol_type volume type sysfs path pattern + * @vol_dev volume's major/minor numbers file pattern + * @vol_alignment volume alignment sysfs path pattern + * @vol_data_bytes volume data size sysfs path pattern + * @vol_rsvd_ebs volume reserved size sysfs path pattern + * @vol_eb_size volume eraseblock size sysfs path pattern + * @vol_corrupted volume corruption flag sysfs path pattern + * @vol_name volume name sysfs path pattern */ struct libubi { char *sysfs; - char *sysfs_ctrl; - char *ctrl_dev; char *sysfs_ubi; char *ubi_dev; char *ubi_version; @@ -113,7 +96,6 @@ struct libubi char *dev_bad_rsvd; char *dev_max_vols; char *dev_min_io_size; - char *dev_mtd_num; char *ubi_vol; char *vol_type; char *vol_dev; @@ -126,6 +108,20 @@ struct libubi char *vol_max_count; }; +static int read_int(const char *file, int *value); +static int dev_read_int(const char *patt, int dev_num, int *value); +static int dev_read_ll(const char *patt, int dev_num, long long *value); +static int dev_read_data(const char *patt, int dev_num, void *buf, int buf_len); +static int vol_read_int(const char *patt, int dev_num, int vol_id, int *value); +static int vol_read_ll(const char *patt, int dev_num, int vol_id, + long long *value); +static int vol_read_data(const char *patt, int dev_num, int vol_id, void *buf, + int buf_len); +static char *mkpath(const char *path, const char *name); +static int find_dev_num(struct libubi *lib, const char *node); +static int find_dev_num_vol(struct libubi *lib, const char *node); +static int find_vol_num(struct libubi *lib, int dev_num, const char *node); + #ifdef __cplusplus } #endif diff --git a/ubi-utils/old-utils/src/libubigen.c b/ubi-utils/old-utils/src/libubigen.c new file mode 100644 index 0000000..1793009 --- /dev/null +++ b/ubi-utils/old-utils/src/libubigen.c @@ -0,0 +1,487 @@ +/* + * Copyright (c) International Business Machines Corp., 2006 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See + * the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Author: Oliver Lohmann + * + * Add UBI headers to binary data. + */ + +#include <stdlib.h> +#include <stdint.h> +#include <stdio.h> +#include <errno.h> +#include <string.h> +#include <mtd/ubi-media.h> +#include <mtd_swab.h> + +#include "config.h" +#include "ubigen.h" +#include "crc32.h" + +#define UBI_NAME_SIZE 256 +#define DEFAULT_VID_OFFSET ((DEFAULT_PAGESIZE) - (UBI_VID_HDR_SIZE)) +#define MIN(a,b) ((a) < (b) ? (a) : (b)) + +static uint32_t crc32_table[256]; + +struct ubi_info { + struct ubi_vid_hdr* v; /* Volume ID header */ + struct ubi_ec_hdr* ec; /* Erase count header */ + + FILE* fp_in; /* Input Stream */ + FILE* fp_out; /* Output stream */ + + size_t eb_size; /* Physical EB size in bytes */ + size_t leb_size; /* Size of a logical EB in a physical EB */ + size_t leb_total; /* Total input size in logical EB */ + size_t alignment; /* Block alignment */ + size_t data_pad; /* Size of padding in each physical EB */ + + size_t bytes_total; /* Total input size in bytes */ + size_t bytes_read; /* Nymber of read bytes (total) */ + + uint32_t blks_written; /* Number of written logical EB */ + + uint8_t* buf; /* Allocated buffer */ + uint8_t* ptr_ec_hdr; /* Pointer to EC hdr in buf */ + uint8_t* ptr_vid_hdr; /* Pointer to VID hdr in buf */ + uint8_t* ptr_data; /* Pointer to data region in buf */ +}; + + +static uint32_t +byte_to_blk(uint64_t byte, uint32_t eb_size) +{ + return (byte % eb_size) == 0 + ? (byte / eb_size) + : (byte / eb_size) + 1; +} + +static int +validate_ubi_info(ubi_info_t u) +{ + if ((u->v->vol_type != UBI_VID_DYNAMIC) && + (u->v->vol_type != UBI_VID_STATIC)) { + return EUBIGEN_INVALID_TYPE; + } + + if (be32_to_cpu(u->ec->vid_hdr_offset) < UBI_VID_HDR_SIZE) { + return EUBIGEN_INVALID_HDR_OFFSET; + } + + return 0; +} + +static int +skip_blks(ubi_info_t u, uint32_t blks) +{ + uint32_t i; + size_t read = 0, to_read = 0; + + /* Step to a maximum of leb_total - 1 to keep the + restrictions. */ + for (i = 0; i < MIN(blks, u->leb_total-1); i++) { + /* Read in data */ + to_read = MIN(u->leb_size, + (u->bytes_total - u->bytes_read)); + read = fread(u->ptr_data, 1, to_read, u->fp_in); + if (read != to_read) { + return -EIO; + } + u->bytes_read += read; + u->blks_written++; + } + + return 0; +} + +static void +clear_buf(ubi_info_t u) +{ + memset(u->buf, 0xff, u->eb_size); +} + +static void +write_ec_hdr(ubi_info_t u) +{ + memcpy(u->ptr_ec_hdr, u->ec, UBI_EC_HDR_SIZE); +} + +static int +fill_data_buffer_from_file(ubi_info_t u, size_t* read) +{ + size_t to_read = 0; + + if (u-> fp_in == NULL) + return -EIO; + + to_read = MIN(u->leb_size, (u->bytes_total - u->bytes_read)); + *read = fread(u->ptr_data, 1, to_read, u->fp_in); + if (*read != to_read) { + return -EIO; + } + return 0; +} + +static void +add_static_info(ubi_info_t u, size_t data_size, ubigen_action_t action) +{ + uint32_t crc = clc_crc32(crc32_table, UBI_CRC32_INIT, + u->ptr_data, data_size); + + u->v->data_size = cpu_to_be32(data_size); + u->v->data_crc = cpu_to_be32(crc); + + if (action & BROKEN_DATA_CRC) { + u->v->data_crc = + cpu_to_be32(be32_to_cpu(u->v->data_crc) + 1); + } + if (action & BROKEN_DATA_SIZE) { + u->v->data_size = + cpu_to_be32(be32_to_cpu(u->v->data_size) + 1); + } +} + +static void +write_vid_hdr(ubi_info_t u, ubigen_action_t action) +{ + uint32_t crc = clc_crc32(crc32_table, UBI_CRC32_INIT, + u->v, UBI_VID_HDR_SIZE_CRC); + /* Write VID header */ + u->v->hdr_crc = cpu_to_be32(crc); + if (action & BROKEN_HDR_CRC) { + u->v->hdr_crc = cpu_to_be32(be32_to_cpu(u->v->hdr_crc) + 1); + } + memcpy(u->ptr_vid_hdr, u->v, UBI_VID_HDR_SIZE); +} + +static int +write_to_output_stream(ubi_info_t u) +{ + size_t written; + + written = fwrite(u->buf, 1, u->eb_size, u->fp_out); + if (written != u->eb_size) { + return -EIO; + } + return 0; +} + +int +ubigen_write_leb(ubi_info_t u, ubigen_action_t action) +{ + int rc = 0; + size_t read = 0; + + clear_buf(u); + write_ec_hdr(u); + + rc = fill_data_buffer_from_file(u, &read); + if (rc != 0) + return rc; + + if (u->v->vol_type == UBI_VID_STATIC) { + add_static_info(u, read, action); + } + + u->v->lnum = cpu_to_be32(u->blks_written); + + if (action & MARK_AS_UPDATE) { + u->v->copy_flag = (u->v->copy_flag)++; + } + + write_vid_hdr(u, action); + rc = write_to_output_stream(u); + if (rc != 0) + return rc; + + /* Update current handle */ + u->bytes_read += read; + u->blks_written++; + return 0; +} + +int +ubigen_write_complete(ubi_info_t u) +{ + size_t i; + int rc = 0; + + for (i = 0; i < u->leb_total; i++) { + rc = ubigen_write_leb(u, NO_ERROR); + if (rc != 0) + return rc; + } + + return 0; +} + +int +ubigen_write_broken_update(ubi_info_t u, uint32_t blk) +{ + int rc = 0; + + rc = skip_blks(u, blk); + if (rc != 0) + return rc; + + rc = ubigen_write_leb(u, MARK_AS_UPDATE | BROKEN_DATA_CRC); + if (rc != 0) + return rc; + + + return 0; +} + +void +dump_info(ubi_info_t u ubi_unused) +{ +#ifdef DEBUG + int err = 0; + if (!u) { + fprintf(stderr, "<empty>"); + return; + } + if (!u->ec) { + fprintf(stderr, "<ec-empty>"); + err = 1; + } + if (!u->v) { + fprintf(stderr, "<v-empty>"); + err = 1; + } + if (err) return; + + fprintf(stderr, "ubi volume\n"); + fprintf(stderr, "version : %8d\n", u->v->version); + fprintf(stderr, "vol_id : %8d\n", be32_to_cpu(u->v->vol_id)); + fprintf(stderr, "vol_type : %8s\n", + u->v->vol_type == UBI_VID_STATIC ? + "static" : "dynamic"); + fprintf(stderr, "used_ebs : %8d\n", + be32_to_cpu(u->v->used_ebs)); + fprintf(stderr, "eb_size : 0x%08x\n", u->eb_size); + fprintf(stderr, "leb_size : 0x%08x\n", u->leb_size); + fprintf(stderr, "data_pad : 0x%08x\n", + be32_to_cpu(u->v->data_pad)); + fprintf(stderr, "leb_total : %8d\n", u->leb_total); + fprintf(stderr, "header offs : 0x%08x\n", + be32_to_cpu(u->ec->vid_hdr_offset)); + fprintf(stderr, "bytes_total : %8d\n", u->bytes_total); + fprintf(stderr, " + in MiB : %8.2f M\n", + ((float)(u->bytes_total)) / 1024 / 1024); + fprintf(stderr, "-------------------------------\n\n"); +#else + return; +#endif +} + +int +ubigen_destroy(ubi_info_t *u) +{ + if (u == NULL) + return -EINVAL; + + ubi_info_t tmp = *u; + + if (tmp) { + if (tmp->v) + free(tmp->v); + if (tmp->ec) + free(tmp->ec); + if (tmp->buf) + free(tmp->buf); + free(tmp); + } + *u = NULL; + return 0; +} + +void +ubigen_init(void) +{ + init_crc32_table(crc32_table); +} + +int +ubigen_create(ubi_info_t* u, uint32_t vol_id, uint8_t vol_type, + uint32_t eb_size, uint64_t ec, uint32_t alignment, + uint8_t version, uint32_t vid_hdr_offset, uint8_t compat_flag, + size_t data_size, FILE* fp_in, FILE* fp_out) +{ + int rc = 0; + ubi_info_t res = NULL; + uint32_t crc; + uint32_t data_offset; + + if (alignment == 0) { + rc = EUBIGEN_INVALID_ALIGNMENT; + goto ubigen_create_err; + } + if ((fp_in == NULL) || (fp_out == NULL)) { + rc = -EINVAL; + goto ubigen_create_err; + } + + res = (ubi_info_t) calloc(1, sizeof(struct ubi_info)); + if (res == NULL) { + rc = -ENOMEM; + goto ubigen_create_err; + } + + res->v = (struct ubi_vid_hdr*) calloc(1, sizeof(struct ubi_vid_hdr)); + if (res->v == NULL) { + rc = -ENOMEM; + goto ubigen_create_err; + } + + res->ec = (struct ubi_ec_hdr*) calloc(1, sizeof(struct ubi_ec_hdr)); + if (res->ec == NULL) { + rc = -ENOMEM; + goto ubigen_create_err; + } + + /* data which is needed in the general process */ + vid_hdr_offset = vid_hdr_offset ? vid_hdr_offset : DEFAULT_VID_OFFSET; + data_offset = vid_hdr_offset + UBI_VID_HDR_SIZE; + res->bytes_total = data_size; + res->eb_size = eb_size ? eb_size : DEFAULT_BLOCKSIZE; + res->data_pad = (res->eb_size - data_offset) % alignment; + res->leb_size = res->eb_size - data_offset - res->data_pad; + res->leb_total = byte_to_blk(data_size, res->leb_size); + res->alignment = alignment; + + if ((res->eb_size < (vid_hdr_offset + UBI_VID_HDR_SIZE))) { + rc = EUBIGEN_TOO_SMALL_EB; + goto ubigen_create_err; + } + res->fp_in = fp_in; + res->fp_out = fp_out; + + /* vid hdr data which doesn't change */ + res->v->magic = cpu_to_be32(UBI_VID_HDR_MAGIC); + res->v->version = version ? version : UBI_VERSION; + res->v->vol_type = vol_type; + res->v->vol_id = cpu_to_be32(vol_id); + res->v->compat = compat_flag; + res->v->data_pad = cpu_to_be32(res->data_pad); + + /* static only: used_ebs */ + if (res->v->vol_type == UBI_VID_STATIC) { + res->v->used_ebs = cpu_to_be32(byte_to_blk + (res->bytes_total, + res->leb_size)); + } + + /* ec hdr (fixed, doesn't change) */ + res->ec->magic = cpu_to_be32(UBI_EC_HDR_MAGIC); + res->ec->version = version ? version : UBI_VERSION; + res->ec->ec = cpu_to_be64(ec); + res->ec->vid_hdr_offset = cpu_to_be32(vid_hdr_offset); + + res->ec->data_offset = cpu_to_be32(data_offset); + + crc = clc_crc32(crc32_table, UBI_CRC32_INIT, res->ec, + UBI_EC_HDR_SIZE_CRC); + res->ec->hdr_crc = cpu_to_be32(crc); + + /* prepare a read buffer */ + res->buf = (uint8_t*) malloc (res->eb_size * sizeof(uint8_t)); + if (res->buf == NULL) { + rc = -ENOMEM; + goto ubigen_create_err; + } + + /* point to distinct regions within the buffer */ + res->ptr_ec_hdr = res->buf; + res->ptr_vid_hdr = res->buf + be32_to_cpu(res->ec->vid_hdr_offset); + res->ptr_data = res->buf + be32_to_cpu(res->ec->vid_hdr_offset) + + UBI_VID_HDR_SIZE; + + rc = validate_ubi_info(res); + if (rc != 0) { + fprintf(stderr, "Volume validation failed: %d\n", rc); + goto ubigen_create_err; + } + + dump_info(res); + *u = res; + return rc; + + ubigen_create_err: + if (res) { + if (res->v) + free(res->v); + if (res->ec) + free(res->ec); + if (res->buf) + free(res->buf); + free(res); + } + *u = NULL; + return rc; +} + +int +ubigen_get_leb_size(ubi_info_t u, size_t* size) +{ + if (u == NULL) + return -EINVAL; + + *size = u->leb_size; + return 0; +} + + +int +ubigen_get_leb_total(ubi_info_t u, size_t* total) +{ + if (u == NULL) + return -EINVAL; + + *total = u->leb_total; + return 0; +} + +int +ubigen_set_lvol_rec(ubi_info_t u, size_t reserved_bytes, + const char* vol_name, struct ubi_vtbl_record *lvol_rec) +{ + uint32_t crc; + + if ((u == NULL) || (vol_name == NULL)) + return -EINVAL; + + memset(lvol_rec, 0x0, UBI_VTBL_RECORD_SIZE); + + lvol_rec->reserved_pebs = + cpu_to_be32(byte_to_blk(reserved_bytes, u->leb_size)); + lvol_rec->alignment = cpu_to_be32(u->alignment); + lvol_rec->data_pad = u->v->data_pad; + lvol_rec->vol_type = u->v->vol_type; + + lvol_rec->name_len = + cpu_to_be16((uint16_t)strlen((const char*)vol_name)); + + memcpy(lvol_rec->name, vol_name, UBI_VOL_NAME_MAX + 1); + + crc = clc_crc32(crc32_table, UBI_CRC32_INIT, + lvol_rec, UBI_VTBL_RECORD_SIZE_CRC); + lvol_rec->crc = cpu_to_be32(crc); + + return 0; +} diff --git a/ubi-utils/src/libubimirror.c b/ubi-utils/old-utils/src/libubimirror.c index d06770e..d06770e 100644 --- a/ubi-utils/src/libubimirror.c +++ b/ubi-utils/old-utils/src/libubimirror.c diff --git a/ubi-utils/src/list.c b/ubi-utils/old-utils/src/list.c index 6eb716b..6eb716b 100644 --- a/ubi-utils/src/list.c +++ b/ubi-utils/old-utils/src/list.c diff --git a/ubi-utils/src/list.h b/ubi-utils/old-utils/src/list.h index e8452a2..e8452a2 100644 --- a/ubi-utils/src/list.h +++ b/ubi-utils/old-utils/src/list.h diff --git a/ubi-utils/src/mkbootenv.c b/ubi-utils/old-utils/src/mkbootenv.c index 50fc8ac..50fc8ac 100644 --- a/ubi-utils/src/mkbootenv.c +++ b/ubi-utils/old-utils/src/mkbootenv.c diff --git a/ubi-utils/src/nand2bin.c b/ubi-utils/old-utils/src/nand2bin.c index 93ba29f..93ba29f 100644 --- a/ubi-utils/src/nand2bin.c +++ b/ubi-utils/old-utils/src/nand2bin.c diff --git a/ubi-utils/src/nandcorr.c b/ubi-utils/old-utils/src/nandcorr.c index caa07e2..caa07e2 100644 --- a/ubi-utils/src/nandcorr.c +++ b/ubi-utils/old-utils/src/nandcorr.c diff --git a/ubi-utils/src/nandecc.c b/ubi-utils/old-utils/src/nandecc.c index 71660ef..71660ef 100644 --- a/ubi-utils/src/nandecc.c +++ b/ubi-utils/old-utils/src/nandecc.c diff --git a/ubi-utils/src/nandecc.h b/ubi-utils/old-utils/src/nandecc.h index bcf1982..bcf1982 100644 --- a/ubi-utils/src/nandecc.h +++ b/ubi-utils/old-utils/src/nandecc.h diff --git a/ubi-utils/src/pddcustomize.c b/ubi-utils/old-utils/src/pddcustomize.c index 1eb9b9a..1eb9b9a 100644 --- a/ubi-utils/src/pddcustomize.c +++ b/ubi-utils/old-utils/src/pddcustomize.c diff --git a/ubi-utils/src/peb.c b/ubi-utils/old-utils/src/peb.c index 08b770f..08b770f 100644 --- a/ubi-utils/src/peb.c +++ b/ubi-utils/old-utils/src/peb.c diff --git a/ubi-utils/src/peb.h b/ubi-utils/old-utils/src/peb.h index 246bce8..246bce8 100644 --- a/ubi-utils/src/peb.h +++ b/ubi-utils/old-utils/src/peb.h diff --git a/ubi-utils/src/pfi.c b/ubi-utils/old-utils/src/pfi.c index fa835e2..fa835e2 100644 --- a/ubi-utils/src/pfi.c +++ b/ubi-utils/old-utils/src/pfi.c diff --git a/ubi-utils/src/pfi.h b/ubi-utils/old-utils/src/pfi.h index 8c5cc07..8c5cc07 100644 --- a/ubi-utils/src/pfi.h +++ b/ubi-utils/old-utils/src/pfi.h diff --git a/ubi-utils/src/pfi2bin.c b/ubi-utils/old-utils/src/pfi2bin.c index 34ecc92..34ecc92 100644 --- a/ubi-utils/src/pfi2bin.c +++ b/ubi-utils/old-utils/src/pfi2bin.c diff --git a/ubi-utils/src/pfiflash.c b/ubi-utils/old-utils/src/pfiflash.c index 754fe33..754fe33 100644 --- a/ubi-utils/src/pfiflash.c +++ b/ubi-utils/old-utils/src/pfiflash.c diff --git a/ubi-utils/src/pfiflash.h b/ubi-utils/old-utils/src/pfiflash.h index 039705d..039705d 100644 --- a/ubi-utils/src/pfiflash.h +++ b/ubi-utils/old-utils/src/pfiflash.h diff --git a/ubi-utils/src/pfiflash_error.h b/ubi-utils/old-utils/src/pfiflash_error.h index 0f27f4a..0f27f4a 100644 --- a/ubi-utils/src/pfiflash_error.h +++ b/ubi-utils/old-utils/src/pfiflash_error.h diff --git a/ubi-utils/src/reader.c b/ubi-utils/old-utils/src/reader.c index 0ea8c6d..0ea8c6d 100644 --- a/ubi-utils/src/reader.c +++ b/ubi-utils/old-utils/src/reader.c diff --git a/ubi-utils/src/reader.h b/ubi-utils/old-utils/src/reader.h index 715e464..715e464 100644 --- a/ubi-utils/src/reader.h +++ b/ubi-utils/old-utils/src/reader.h diff --git a/ubi-utils/src/ubigen.c b/ubi-utils/old-utils/src/ubigen.c index bb55fa9..bb55fa9 100644 --- a/ubi-utils/src/ubigen.c +++ b/ubi-utils/old-utils/src/ubigen.c diff --git a/ubi-utils/src/ubigen.h b/ubi-utils/old-utils/src/ubigen.h index 8d29120..8d29120 100644 --- a/ubi-utils/src/ubigen.h +++ b/ubi-utils/old-utils/src/ubigen.h diff --git a/ubi-utils/src/ubimirror.c b/ubi-utils/old-utils/src/ubimirror.c index da05a8b..da05a8b 100644 --- a/ubi-utils/src/ubimirror.c +++ b/ubi-utils/old-utils/src/ubimirror.c diff --git a/ubi-utils/src/ubimirror.h b/ubi-utils/old-utils/src/ubimirror.h index d7ae2ad..d7ae2ad 100644 --- a/ubi-utils/src/ubimirror.h +++ b/ubi-utils/old-utils/src/ubimirror.h diff --git a/ubi-utils/src/unubi.c b/ubi-utils/old-utils/src/unubi.c index 0f72b18..0f72b18 100644 --- a/ubi-utils/src/unubi.c +++ b/ubi-utils/old-utils/src/unubi.c diff --git a/ubi-utils/src/unubi_analyze.c b/ubi-utils/old-utils/src/unubi_analyze.c index ceaa85f..ceaa85f 100644 --- a/ubi-utils/src/unubi_analyze.c +++ b/ubi-utils/old-utils/src/unubi_analyze.c diff --git a/ubi-utils/src/unubi_analyze.h b/ubi-utils/old-utils/src/unubi_analyze.h index c478f53..c478f53 100644 --- a/ubi-utils/src/unubi_analyze.h +++ b/ubi-utils/old-utils/src/unubi_analyze.h diff --git a/ubi-utils/testcases.txt b/ubi-utils/old-utils/testcases.txt index dcc1c35..dcc1c35 100644 --- a/ubi-utils/testcases.txt +++ b/ubi-utils/old-utils/testcases.txt diff --git a/ubi-utils/new-utils/src/common.c b/ubi-utils/src/common.c index bcb775c..bcb775c 100644 --- a/ubi-utils/new-utils/src/common.c +++ b/ubi-utils/src/common.c diff --git a/ubi-utils/new-utils/src/common.h b/ubi-utils/src/common.h index 56fa020..56fa020 100644 --- a/ubi-utils/new-utils/src/common.h +++ b/ubi-utils/src/common.h diff --git a/ubi-utils/src/crc32.c b/ubi-utils/src/crc32.c index 666e217..6b1e50c 100644 --- a/ubi-utils/src/crc32.c +++ b/ubi-utils/src/crc32.c @@ -1,83 +1,95 @@ /* - * Copyright (c) International Business Machines Corp., 2006 + * COPYRIGHT (C) 1986 Gary S. Brown. You may use this program, or + * code or tables extracted from it, as desired without restriction. * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. + * First, the polynomial itself and its table of feedback terms. The + * polynomial is + * X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU General Public License for more details. + * Note that we take it "backwards" and put the highest-order term in + * the lowest-order bit. The X^32 term is "implied"; the LSB is the + * X^31 term, etc. The X^0 term (usually shown as "+1") results in + * the MSB being 1 * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Note that the usual hardware shift register implementation, which + * is what we're using (we're merely optimizing it by doing eight-bit + * chunks at a time) shifts bits into the lowest-order term. In our + * implementation, that means shifting towards the right. Why do we + * do it this way? Because the calculated CRC must be transmitted in + * order from highest-order term to lowest-order term. UARTs transmit + * characters in order from LSB to MSB. By storing the CRC this way + * we hand it to the UART in the order low-byte to high-byte; the UART + * sends each low-bit to hight-bit; and the result is transmission bit + * by bit from highest- to lowest-order term without requiring any bit + * shuffling on our part. Reception works similarly * - * Author: Thomas Gleixner - */ - -/* - * CRC32 functions + * The feedback terms table consists of 256, 32-bit entries. Notes * - * Can be compiled as seperate object, but is included into the ipl source - * so gcc can inline the functions. We optimize for size so the omission of - * the function frame is helpful. + * The table can be generated at runtime if desired; code to do so + * is shown later. It might not be obvious, but the feedback + * terms simply represent the results of eight shift/xor opera + * tions for all combinations of data and CRC register values * + * The values must be right-shifted by eight bits by the "updcrc + * logic; the shift must be unsigned (bring in zeroes). On some + * hardware you could probably optimize the shift in assembler by + * using byte-swap instructions + * polynomial $edb88320 */ #include <stdint.h> -#include <crc32.h> - -/* CRC polynomial */ -#define CRC_POLY 0xEDB88320 - -/** - * init_crc32_table - Initialize crc table - * - * @table: pointer to the CRC table which must be initialized - * - * Create CRC32 table for given polynomial. The table is created with - * the lowest order term in the highest order bit. So the x^32 term - * has to implied in the crc calculation function. - */ -void init_crc32_table(uint32_t *table) -{ - uint32_t crc; - int i, j; - - for (i = 0; i < 256; i++) { - crc = i; - for (j = 8; j > 0; j--) { - if (crc & 1) - crc = (crc >> 1) ^ CRC_POLY; - else - crc >>= 1; - } - table[i] = crc; - } -} - -/** - * clc_crc32 - Calculate CRC32 over a buffer - * - * @table: pointer to the CRC table - * @crc: initial crc value - * @buf: pointer to the buffer - * @len: number of bytes to calc - * - * Returns the updated crc value. - * - * The algorithm resembles a hardware shift register, but calculates 8 - * bit at once. - */ -uint32_t clc_crc32(uint32_t *table, uint32_t crc, void *buf, - int len) -{ - const unsigned char *p = buf; - while(--len >= 0) - crc = table[(crc ^ *p++) & 0xff] ^ (crc >> 8); - return crc; -} +const uint32_t crc32_table[256] = { + 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L, + 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L, + 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L, + 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL, + 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L, + 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L, + 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L, + 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL, + 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L, + 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL, + 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L, + 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L, + 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L, + 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL, + 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL, + 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L, + 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL, + 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L, + 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L, + 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L, + 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL, + 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L, + 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L, + 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL, + 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L, + 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L, + 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L, + 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L, + 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L, + 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL, + 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL, + 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L, + 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L, + 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL, + 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL, + 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L, + 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL, + 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L, + 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL, + 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L, + 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL, + 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L, + 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L, + 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL, + 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L, + 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L, + 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L, + 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L, + 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L, + 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L, + 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL, + 0x2d02ef8dL +}; diff --git a/ubi-utils/src/crc32.h b/ubi-utils/src/crc32.h index 31362b0..ee3145b 100644 --- a/ubi-utils/src/crc32.h +++ b/ubi-utils/src/crc32.h @@ -1,36 +1,19 @@ -#ifndef __CRC32_H__ -#define __CRC32_H__ -/* - * Copyright (c) International Business Machines Corp., 2006 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ +#ifndef CRC32_H +#define CRC32_H -/* - * Author: Thomas Gleixner - * - * CRC32 functions - * - * Can be compiled as seperate object, but is included into the ipl source - * so gcc can inline the functions. We optimize for size so the omission of - * the function frame is helpful. - * - */ #include <stdint.h> -void init_crc32_table(uint32_t *table); -uint32_t clc_crc32(uint32_t *table, uint32_t crc, void *buf, int len); +extern const uint32_t crc32_table[256]; -#endif /* __CRC32_H__ */ +/* Return a 32-bit CRC of the contents of the buffer. */ + + static inline uint32_t +crc32(uint32_t val, const void *ss, int len) +{ + const unsigned char *s = ss; + while (--len >= 0) + val = crc32_table[(val ^ *s++) & 0xff] ^ (val >> 8); + return val; +} + +#endif diff --git a/ubi-utils/new-utils/src/dictionary.c b/ubi-utils/src/dictionary.c index b7c9ebf..b7c9ebf 100644 --- a/ubi-utils/new-utils/src/dictionary.c +++ b/ubi-utils/src/dictionary.c diff --git a/ubi-utils/new-utils/src/dictionary.h b/ubi-utils/src/dictionary.h index c7d1790..c7d1790 100644 --- a/ubi-utils/new-utils/src/dictionary.h +++ b/ubi-utils/src/dictionary.h diff --git a/ubi-utils/new-utils/src/libiniparser.c b/ubi-utils/src/libiniparser.c index 3bea51e..3bea51e 100644 --- a/ubi-utils/new-utils/src/libiniparser.c +++ b/ubi-utils/src/libiniparser.c diff --git a/ubi-utils/new-utils/src/libmtd.c b/ubi-utils/src/libmtd.c index b60ddbd..b60ddbd 100644 --- a/ubi-utils/new-utils/src/libmtd.c +++ b/ubi-utils/src/libmtd.c diff --git a/ubi-utils/new-utils/src/libscan.c b/ubi-utils/src/libscan.c index dc1f083..dc1f083 100644 --- a/ubi-utils/new-utils/src/libscan.c +++ b/ubi-utils/src/libscan.c diff --git a/ubi-utils/src/libubi.c b/ubi-utils/src/libubi.c index a536b47..1aa66d8 100644 --- a/ubi-utils/src/libubi.c +++ b/ubi-utils/src/libubi.c @@ -15,7 +15,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * - * Author: Artem B. Bityutskiy + * Author: Artem Bityutskiy * * UBI (Unsorted Block Images) library. */ @@ -27,14 +27,487 @@ #include <sys/stat.h> #include <sys/types.h> #include <dirent.h> -#include <errno.h> #include <unistd.h> #include <sys/ioctl.h> #include <limits.h> #include "libubi.h" #include "libubi_int.h" +#include "common.h" -libubi_t libubi_open(void) +#define PROGRAM_NAME "libubi" + +/** + * mkpath - compose full path from 2 given components. + * @path: the first component + * @name: the second component + * + * This function returns the resulting path in case of success and %NULL in + * case of failure. + */ +static char *mkpath(const char *path, const char *name) +{ + char *n; + int len1 = strlen(path); + int len2 = strlen(name); + + n = malloc(len1 + len2 + 2); + if (!n) { + sys_errmsg("cannot allocate %d bytes", len1 + len2 + 2); + return NULL; + } + + memcpy(n, path, len1); + if (n[len1 - 1] != '/') + n[len1++] = '/'; + + memcpy(n + len1, name, len2 + 1); + return n; +} + +/** + * read_positive_ll - read a positive 'long long' value from a file. + * @file: the file to read from + * @value: the result is stored here + * + * This function reads file @file and interprets its contents as a positive + * 'long long' integer. If this is not true, it fails with %EINVAL error code. + * Returns %0 in case of success and %-1 in case of failure. + */ +static int read_positive_ll(const char *file, long long *value) +{ + int fd, rd; + char buf[50]; + + fd = open(file, O_RDONLY); + if (fd == -1) + return -1; + + rd = read(fd, buf, 50); + if (rd == -1) { + sys_errmsg("cannot read \"%s\"", file); + goto out_error; + } + if (rd == 50) { + errmsg("contents of \"%s\" is too long", file); + errno = EINVAL; + goto out_error; + } + + if (sscanf(buf, "%lld\n", value) != 1) { + /* This must be a UBI bug */ + errmsg("cannot read integer from \"%s\"\n", file); + errno = EINVAL; + goto out_error; + } + + if (*value < 0) { + errmsg("negative value %lld in \"%s\"", *value, file); + errno = EINVAL; + goto out_error; + } + + if (close(fd)) + return sys_errmsg("close failed on \"%s\"", file); + + return 0; + +out_error: + close(fd); + return -1; +} + +/** + * read_positive_int - read a positive 'int' value from a file. + * @file: the file to read from + * @value: the result is stored here + * + * This function is the same as 'read_positive_ll()', but it reads an 'int' + * value, not 'long long'. + */ +static int read_positive_int(const char *file, int *value) +{ + long long res; + + if (read_positive_ll(file, &res)) + return -1; + + /* Make sure the value is not too big */ + if (res > INT_MAX) { + errmsg("value %lld read from file \"%s\" is out of range", + res, file); + errno = EINVAL; + return -1; + } + + *value = res; + return 0; +} + +/** + * read_data - read data from a file. + * @file: the file to read from + * @buf: the buffer to read to + * @buf_len: buffer length + * + * This function returns number of read bytes in case of success and %-1 in + * case of failure. Note, if the file contains more then @buf_len bytes of + * date, this function fails with %EINVAL error code. + */ +static int read_data(const char *file, void *buf, int buf_len) +{ + int fd, rd, tmp, tmp1; + + fd = open(file, O_RDONLY); + if (fd == -1) + return -1; + + rd = read(fd, buf, buf_len); + if (rd == -1) { + sys_errmsg("cannot read \"%s\"", file); + goto out_error; + } + + /* Make sure all data is read */ + tmp1 = read(fd, &tmp, 1); + if (tmp1 == 1) { + sys_errmsg("cannot read \"%s\"", file); + goto out_error; + } + if (tmp1) { + errmsg("file \"%s\" contains too much data (> %d bytes)", + file, buf_len); + errno = EINVAL; + goto out_error; + } + + if (close(fd)) { + sys_errmsg("close failed on \"%s\"", file); + return -1; + } + + return rd; + +out_error: + close(fd); + return -1; +} + +/** + * read_major - read major and minor numbers from a file. + * @file: name of the file to read from + * @major: major number is returned here + * @minor: minor number is returned here + * + * This function returns % in case of succes, and %-1 in case of failure. + */ +static int read_major(const char *file, int *major, int *minor) +{ + int ret; + char buf[50]; + + ret = read_data(file, buf, 50); + if (ret < 0) + return ret; + + ret = sscanf(buf, "%d:%d\n", major, minor); + if (ret != 2) { + errno = EINVAL; + return errmsg("\"%s\" does not have major:minor format", file); + } + + if (*major < 0 || *minor < 0) { + errno = EINVAL; + return errmsg("bad major:minor %d:%d in \"%s\"", + *major, *minor, file); + } + + return 0; +} + +/** + * dev_read_int - read a positive 'int' value from an UBI device sysfs file. + * @patt: file pattern to read from + * @dev_num: UBI device number + * @value: the result is stored here + * + * This function returns %0 in case of success and %-1 in case of failure. + */ +static int dev_read_int(const char *patt, int dev_num, int *value) +{ + char file[strlen(patt) + 50]; + + sprintf(file, patt, dev_num); + return read_positive_int(file, value); +} + +/** + * vol_read_int - read a positive 'int' value from an UBI volume sysfs file. + * @patt: file pattern to read from + * @dev_num: UBI device number + * @vol_id: volume ID + * @value: the result is stored here + * + * This function returns %0 in case of success and %-1 in case of failure. + */ +static int vol_read_int(const char *patt, int dev_num, int vol_id, int *value) +{ + char file[strlen(patt) + 100]; + + sprintf(file, patt, dev_num, vol_id); + return read_positive_int(file, value); +} + +/** + * dev_read_ll - read a positive 'long long' value from an UBI device sysfs file. + * @patt: file pattern to read from + * @dev_num: UBI device number + * @value: the result is stored here + * + * This function returns %0 in case of success and %-1 in case of failure. + */ +static int dev_read_ll(const char *patt, int dev_num, long long *value) +{ + char file[strlen(patt) + 50]; + + sprintf(file, patt, dev_num); + return read_positive_ll(file, value); +} + +/** + * vol_read_ll - read a positive 'long long' value from an UBI volume sysfs file. + * @patt: file pattern to read from + * @dev_num: UBI device number + * @vol_id: volume ID + * @value: the result is stored here + * + * This function returns %0 in case of success and %-1 in case of failure. + */ +static int vol_read_ll(const char *patt, int dev_num, int vol_id, + long long *value) +{ + char file[strlen(patt) + 100]; + + sprintf(file, patt, dev_num, vol_id); + return read_positive_ll(file, value); +} + +/** + * vol_read_data - read data from an UBI volume's sysfs file. + * @patt: file pattern to read from + * @dev_num: UBI device number + * @vol_id: volume ID + * @buf: buffer to read to + * @buf_len: buffer length + * + * This function returns number of read bytes in case of success and %-1 in + * case of failure. + */ +static int vol_read_data(const char *patt, int dev_num, int vol_id, void *buf, + int buf_len) +{ + char file[strlen(patt) + 100]; + + sprintf(file, patt, dev_num, vol_id); + return read_data(file, buf, buf_len); +} + +/** + * dev_get_major - get major and minor numbers of an UBI device. + * @lib: libubi descriptor + * @dev_num: UBI device number + * @major: major number is returned here + * @minor: minor number is returned here + * + * This function returns zero in case of succes and %-1 in case of failure. + */ +static int dev_get_major(struct libubi *lib, int dev_num, int *major, int *minor) +{ + char file[strlen(lib->dev_dev) + 50]; + + sprintf(file, lib->dev_dev, dev_num); + return read_major(file, major, minor); +} + +/** + * vol_get_major - get major and minor numbers of an UBI volume. + * @lib: libubi descriptor + * @dev_num: UBI device number + * @vol_id: volume ID + * @major: major number is returned here + * @minor: minor number is returned here + * + * This function returns zero in case of succes and %-1 in case of failure. + */ +static int vol_get_major(struct libubi *lib, int dev_num, int vol_id, + int *major, int *minor) +{ + char file[strlen(lib->vol_dev) + 100]; + + sprintf(file, lib->vol_dev, dev_num, vol_id); + return read_major(file, major, minor); +} + +/** + * vol_node2nums - find UBI device number and volume ID by volume device node + * file. + * @lib: UBI library descriptor + * @node: UBI character device node name + * @dev_num: UBI device number is returned here + * @vol_id: volume ID is returned hers + * + * This function returns zero in case of succes and %-1 in case of failure. + */ +static int vol_node2nums(struct libubi *lib, const char *node, int *dev_num, + int *vol_id) +{ + struct stat st; + struct ubi_info info; + int i, fd, major, minor; + char file[strlen(lib->ubi_vol) + 100]; + + if (stat(node, &st)) + return sys_errmsg("cannot get information about \"%s\"", + node); + + if (!S_ISCHR(st.st_mode)) { + errno = EINVAL; + return errmsg("\"%s\" is not a character device", node); + } + + major = major(st.st_rdev); + minor = minor(st.st_rdev); + + if (minor == 0) { + errno = EINVAL; + return errmsg("\"%s\" is not a volume character device", node); + } + + if (ubi_get_info((libubi_t *)lib, &info)) + return -1; + + for (i = info.lowest_dev_num; i <= info.highest_dev_num; i++) { + int major1, minor1, ret; + + ret = dev_get_major(lib, i, &major1, &minor1); + if (ret) { + if (errno == ENOENT) + continue; + return -1; + } + + if (major1 == major) + break; + } + + if (i > info.highest_dev_num) { + errno = ENODEV; + return -1; + } + + /* Make sure this UBI volume exists */ + sprintf(file, lib->ubi_vol, i, minor - 1); + fd = open(file, O_RDONLY); + if (fd == -1) { + errno = ENODEV; + return -1; + } + + *dev_num = i; + *vol_id = minor - 1; + errno = 0; + return 0; +} + +/** + * dev_node2num - find UBI device number by its character device node. + * @lib: UBI library descriptor + * @node: UBI character device node name + * + * This function returns positive UBI device number in case of success and %-1 + * in case of failure. + */ +static int dev_node2num(struct libubi *lib, const char *node, int *dev_num) +{ + struct stat st; + struct ubi_info info; + int i, major, minor; + + if (stat(node, &st)) + return sys_errmsg("cannot get information about \"%s\"", + node); + + if (!S_ISCHR(st.st_mode)) { + errno = EINVAL; + return errmsg("\"%s\" is not a character device", node); + } + + major = major(st.st_rdev); + minor = minor(st.st_rdev); + + if (minor != 0) { + errno = EINVAL; + return errmsg("\"%s\" is not an UBI character device", node); + } + + if (ubi_get_info((libubi_t *)lib, &info)) + return -1; + + for (i = info.lowest_dev_num; i <= info.highest_dev_num; i++) { + int major1, minor1, ret; + + ret = dev_get_major(lib, i, &major1, &minor1); + if (ret) { + if (errno == ENOENT) + continue; + return -1; + } + + if (major1 == major) { + if (minor1 != 0) { + errmsg("UBI character device minor number is " + "%d, but must be 0", minor1); + errno = EINVAL; + return -1; + } + errno = 0; + *dev_num = i; + return 0; + } + } + + errno = ENODEV; + return -1; +} + +int mtd_num2ubi_dev(libubi_t desc, int mtd_num, int *dev_num) +{ + struct ubi_info info; + int i, ret, mtd_num1; + struct libubi *lib = desc; + + if (ubi_get_info(desc, &info)) + return -1; + + for (i = info.lowest_dev_num; i <= info.highest_dev_num; i++) { + ret = dev_read_int(lib->dev_mtd_num, i, &mtd_num1); + if (ret) { + if (errno == ENOENT) + continue; + return -1; + } + + if (mtd_num1 == mtd_num) { + errno = 0; + *dev_num = i; + return 0; + } + } + + errno = 0; + return -1; +} + +libubi_t libubi_open(int required) { int fd, version; struct libubi *lib; @@ -46,132 +519,130 @@ libubi_t libubi_open(void) /* TODO: this must be discovered instead */ lib->sysfs = strdup("/sys"); if (!lib->sysfs) - goto error; + goto out_error; + + lib->sysfs_ctrl = mkpath(lib->sysfs, SYSFS_CTRL); + if (!lib->sysfs_ctrl) + goto out_error; + + lib->ctrl_dev = mkpath(lib->sysfs_ctrl, CTRL_DEV); + if (!lib->ctrl_dev) + goto out_error; lib->sysfs_ubi = mkpath(lib->sysfs, SYSFS_UBI); if (!lib->sysfs_ubi) - goto error; + goto out_error; /* Make sure UBI is present */ fd = open(lib->sysfs_ubi, O_RDONLY); - if (fd == -1) - goto error; - close(fd); + if (fd == -1) { + if (required) + errmsg("cannot open \"%s\", UBI does not seem to " + "exist in system", lib->sysfs_ubi); + goto out_error; + } + + if (close(fd)) { + sys_errmsg("close failed on \"%s\"", lib->sysfs_ubi); + goto out_error; + } lib->ubi_dev = mkpath(lib->sysfs_ubi, UBI_DEV_NAME_PATT); if (!lib->ubi_dev) - goto error; + goto out_error; lib->ubi_version = mkpath(lib->sysfs_ubi, UBI_VER); if (!lib->ubi_version) - goto error; + goto out_error; lib->dev_dev = mkpath(lib->ubi_dev, DEV_DEV); if (!lib->dev_dev) - goto error; + goto out_error; lib->dev_avail_ebs = mkpath(lib->ubi_dev, DEV_AVAIL_EBS); if (!lib->dev_avail_ebs) - goto error; + goto out_error; lib->dev_total_ebs = mkpath(lib->ubi_dev, DEV_TOTAL_EBS); if (!lib->dev_total_ebs) - goto error; + goto out_error; lib->dev_bad_count = mkpath(lib->ubi_dev, DEV_BAD_COUNT); if (!lib->dev_bad_count) - goto error; + goto out_error; lib->dev_eb_size = mkpath(lib->ubi_dev, DEV_EB_SIZE); if (!lib->dev_eb_size) - goto error; + goto out_error; lib->dev_max_ec = mkpath(lib->ubi_dev, DEV_MAX_EC); if (!lib->dev_max_ec) - goto error; + goto out_error; lib->dev_bad_rsvd = mkpath(lib->ubi_dev, DEV_MAX_RSVD); if (!lib->dev_bad_rsvd) - goto error; + goto out_error; lib->dev_max_vols = mkpath(lib->ubi_dev, DEV_MAX_VOLS); if (!lib->dev_max_vols) - goto error; + goto out_error; lib->dev_min_io_size = mkpath(lib->ubi_dev, DEV_MIN_IO_SIZE); if (!lib->dev_min_io_size) - goto error; + goto out_error; + + lib->dev_mtd_num = mkpath(lib->ubi_dev, DEV_MTD_NUM); + if (!lib->dev_mtd_num) + goto out_error; lib->ubi_vol = mkpath(lib->sysfs_ubi, UBI_VOL_NAME_PATT); if (!lib->ubi_vol) - goto error; + goto out_error; lib->vol_type = mkpath(lib->ubi_vol, VOL_TYPE); if (!lib->vol_type) - goto error; + goto out_error; lib->vol_dev = mkpath(lib->ubi_vol, VOL_DEV); if (!lib->vol_dev) - goto error; + goto out_error; lib->vol_alignment = mkpath(lib->ubi_vol, VOL_ALIGNMENT); if (!lib->vol_alignment) - goto error; + goto out_error; lib->vol_data_bytes = mkpath(lib->ubi_vol, VOL_DATA_BYTES); if (!lib->vol_data_bytes) - goto error; + goto out_error; lib->vol_rsvd_ebs = mkpath(lib->ubi_vol, VOL_RSVD_EBS); if (!lib->vol_rsvd_ebs) - goto error; + goto out_error; lib->vol_eb_size = mkpath(lib->ubi_vol, VOL_EB_SIZE); if (!lib->vol_eb_size) - goto error; + goto out_error; lib->vol_corrupted = mkpath(lib->ubi_vol, VOL_CORRUPTED); if (!lib->vol_corrupted) - goto error; + goto out_error; lib->vol_name = mkpath(lib->ubi_vol, VOL_NAME); if (!lib->vol_name) - goto error; + goto out_error; - if (read_int(lib->ubi_version, &version)) - goto error; + if (read_positive_int(lib->ubi_version, &version)) + goto out_error; if (version != LIBUBI_UBI_VERSION) { - fprintf(stderr, "LIBUBI: this library was made for UBI version " - "%d, but UBI version %d is detected\n", - LIBUBI_UBI_VERSION, version); - goto error; + errmsg("this library was made for UBI version %d, but UBI " + "version %d is detected\n", LIBUBI_UBI_VERSION, version); + goto out_error; } return lib; -error: - free(lib->vol_corrupted); - free(lib->vol_eb_size); - free(lib->vol_rsvd_ebs); - free(lib->vol_data_bytes); - free(lib->vol_alignment); - free(lib->vol_dev); - free(lib->vol_type); - free(lib->ubi_vol); - free(lib->dev_min_io_size); - free(lib->dev_max_vols); - free(lib->dev_bad_rsvd); - free(lib->dev_max_ec); - free(lib->dev_eb_size); - free(lib->dev_bad_count); - free(lib->dev_total_ebs); - free(lib->dev_avail_ebs); - free(lib->dev_dev); - free(lib->ubi_version); - free(lib->ubi_dev); - free(lib->sysfs_ubi); - free(lib->sysfs); - free(lib); +out_error: + libubi_close((libubi_t)lib); return NULL; } @@ -188,6 +659,7 @@ void libubi_close(libubi_t desc) free(lib->vol_dev); free(lib->vol_type); free(lib->ubi_vol); + free(lib->dev_mtd_num); free(lib->dev_min_io_size); free(lib->dev_max_vols); free(lib->dev_bad_rsvd); @@ -200,10 +672,143 @@ void libubi_close(libubi_t desc) free(lib->ubi_version); free(lib->ubi_dev); free(lib->sysfs_ubi); + free(lib->ctrl_dev); + free(lib->sysfs_ctrl); free(lib->sysfs); free(lib); } +int ubi_attach_mtd(libubi_t desc, const char *node, + struct ubi_attach_request *req) +{ + int fd, ret; + struct ubi_attach_req r; + + memset(&r, sizeof(struct ubi_attach_req), '\0'); + + desc = desc; + r.ubi_num = req->dev_num; + r.mtd_num = req->mtd_num; + r.vid_hdr_offset = req->vid_hdr_offset; + + fd = open(node, O_RDONLY); + if (fd == -1) + return sys_errmsg("cannot open \"%s\"", node); + + ret = ioctl(fd, UBI_IOCATT, &r); + close(fd); + if (ret == -1) + return -1; + + req->dev_num = r.ubi_num; + +#ifdef UDEV_SETTLE_HACK + if (system("udevsettle") == -1) + return -1; +#endif + + return ret; +} + +int ubi_detach_mtd(libubi_t desc, const char *node, int mtd_num) +{ + int ret, ubi_dev; + + ret = mtd_num2ubi_dev(desc, mtd_num, &ubi_dev); + if (ret == -1) { + errno = ENODEV; + return ret; + } + + return ubi_remove_dev(desc, node, ubi_dev); +} + +int ubi_remove_dev(libubi_t desc, const char *node, int ubi_dev) +{ + int fd, ret; + + desc = desc; + + fd = open(node, O_RDONLY); + if (fd == -1) + return sys_errmsg("cannot open \"%s\"", node); + ret = ioctl(fd, UBI_IOCDET, &ubi_dev); + if (ret == -1) + goto out_close; + +#ifdef UDEV_SETTLE_HACK + if (system("udevsettle") == -1) + return -1; +#endif + +out_close: + close(fd); + return ret; +} + +int ubi_node_type(libubi_t desc, const char *node) +{ + struct stat st; + struct ubi_info info; + int i, fd, major, minor; + struct libubi *lib = (struct libubi *)desc; + char file[strlen(lib->ubi_vol) + 100]; + + if (stat(node, &st)) + return sys_errmsg("cannot get information about \"%s\"", + node); + + if (!S_ISCHR(st.st_mode)) { + errmsg("\"%s\" is not a character device", node); + errno = EINVAL; + return -1; + } + + major = major(st.st_rdev); + minor = minor(st.st_rdev); + + if (ubi_get_info((libubi_t *)lib, &info)) + return -1; + + for (i = info.lowest_dev_num; i <= info.highest_dev_num; i++) { + int major1, minor1, ret; + + ret = dev_get_major(lib, i, &major1, &minor1); + if (ret) { + if (errno == ENOENT) + continue; + if (!errno) + goto out_not_ubi; + return -1; + } + + if (major1 == major) + break; + } + + if (i > info.highest_dev_num) + goto out_not_ubi; + + if (minor == 0) + return 1; + + /* This is supposdely an UBI volume device node */ + sprintf(file, lib->ubi_vol, i, minor - 1); + fd = open(file, O_RDONLY); + if (fd == -1) { + sys_errmsg("cannot open \"%s\"", node); + return -1; + } + + return 2; + +out_not_ubi: + errmsg("\"%s\" has major:minor %d:%d, but this does not correspond to " + "any UBI device or volume", node, major, minor); + errno = 0; + return -1; +} + int ubi_get_info(libubi_t desc, struct ubi_info *info) { DIR *sysfs_ubi; @@ -212,6 +817,16 @@ int ubi_get_info(libubi_t desc, struct ubi_info *info) memset(info, '\0', sizeof(struct ubi_info)); + if (read_major(lib->ctrl_dev, &info->ctrl_major, &info->ctrl_minor)) { + /* + * Older UBI versions did not have control device, so we do not + * panic here for compatibility reasons. May be few years later + * we could return -1 here, but for now just set major:minor to + * -1. + */ + info->ctrl_major = info->ctrl_minor = -1; + } + /* * We have to scan the UBI sysfs directory to identify how many UBI * devices are present. @@ -221,11 +836,23 @@ int ubi_get_info(libubi_t desc, struct ubi_info *info) return -1; info->lowest_dev_num = INT_MAX; - while ((dirent = readdir(sysfs_ubi))) { - char *name = &dirent->d_name[0]; + while (1) { int dev_num, ret; + char tmp_buf[256]; + + errno = 0; + dirent = readdir(sysfs_ubi); + if (!dirent) + break; + + if (strlen(dirent->d_name) > 256) { + errmsg("invalid entry in %s: \"%s\"", + lib->sysfs_ubi, dirent->d_name); + goto out_close; + } - ret = sscanf(name, UBI_DEV_NAME_PATT, &dev_num); + ret = sscanf(dirent->d_name, UBI_DEV_NAME_PATT"%s", + &dev_num, tmp_buf); if (ret == 1) { info->dev_count += 1; if (dev_num > info->highest_dev_num) @@ -235,15 +862,23 @@ int ubi_get_info(libubi_t desc, struct ubi_info *info) } } + if (!dirent && errno) { + sys_errmsg("readdir failed on \"%s\"", lib->sysfs_ubi); + goto out_close; + } + + if (closedir(sysfs_ubi)) + return sys_errmsg("closedir failed on \"%s\"", lib->sysfs_ubi); + if (info->lowest_dev_num == INT_MAX) info->lowest_dev_num = 0; - if (read_int(lib->ubi_version, &info->version)) - goto close; + if (read_positive_int(lib->ubi_version, &info->version)) + return -1; - return closedir(sysfs_ubi); + return 0; -close: +out_close: closedir(sysfs_ubi); return -1; } @@ -254,6 +889,8 @@ int ubi_mkvol(libubi_t desc, const char *node, struct ubi_mkvol_request *req) struct ubi_mkvol_req r; size_t n; + memset(&r, sizeof(struct ubi_mkvol_req), '\0'); + desc = desc; r.vol_id = req->vol_id; r.alignment = req->alignment; @@ -269,12 +906,20 @@ int ubi_mkvol(libubi_t desc, const char *node, struct ubi_mkvol_request *req) fd = open(node, O_RDONLY); if (fd == -1) - return -1; + return sys_errmsg("cannot open \"%s\"", node); ret = ioctl(fd, UBI_IOCMKVOL, &r); - if (!ret) - req->vol_id = r.vol_id; + if (ret == -1) + goto out_close; + + req->vol_id = r.vol_id; +#ifdef UDEV_SETTLE_HACK + if (system("udevsettle") == -1) + return -1; +#endif + +out_close: close(fd); return ret; } @@ -286,9 +931,39 @@ int ubi_rmvol(libubi_t desc, const char *node, int vol_id) desc = desc; fd = open(node, O_RDONLY); if (fd == -1) - return -1; + return sys_errmsg("cannot open \"%s\"", node); ret = ioctl(fd, UBI_IOCRMVOL, &vol_id); + if (ret == -1) + goto out_close; + +#ifdef UDEV_SETTLE_HACK + if (system("udevsettle") == -1) + return -1; +#endif + +out_close: + close(fd); + return ret; +} + +int ubi_rnvols(libubi_t desc, const char *node, struct ubi_rnvol_req *rnvol) +{ + int fd, ret; + + fd = open(node, O_RDONLY); + if (fd == -1) + return -1; + ret = ioctl(fd, UBI_IOCRNVOL, rnvol); + if (ret == -1) + goto out_close; + +#ifdef UDEV_SETTLE_HACK + if (system("udevsettle") == -1) + return -1; +#endif + +out_close: close(fd); return ret; } @@ -301,7 +976,7 @@ int ubi_rsvol(libubi_t desc, const char *node, int vol_id, long long bytes) desc = desc; fd = open(node, O_RDONLY); if (fd == -1) - return -1; + return sys_errmsg("cannot open \"%s\"", node); req.bytes = bytes; req.vol_id = vol_id; @@ -319,16 +994,19 @@ int ubi_update_start(libubi_t desc, int fd, long long bytes) return 0; } -int ubi_get_dev_info(libubi_t desc, const char *node, struct ubi_dev_info *info) +int ubi_leb_change_start(libubi_t desc, int fd, int lnum, int bytes, int dtype) { - int dev_num; - struct libubi *lib = (struct libubi *)desc; + struct ubi_leb_change_req req; - dev_num = find_dev_num(lib, node); - if (dev_num == -1) - return -1; + desc = desc; + memset(&req, 0, sizeof(struct ubi_leb_change_req)); + req.lnum = lnum; + req.bytes = bytes; + req.dtype = dtype; - return ubi_get_dev_info1(desc, dev_num, info); + if (ioctl(fd, UBI_IOCEBCH, &req)) + return -1; + return 0; } int ubi_get_dev_info1(libubi_t desc, int dev_num, struct ubi_dev_info *info) @@ -344,33 +1022,54 @@ int ubi_get_dev_info1(libubi_t desc, int dev_num, struct ubi_dev_info *info) if (!sysfs_ubi) return -1; - info->lowest_vol_num = INT_MAX; - while ((dirent = readdir(sysfs_ubi))) { - char *name = &dirent->d_name[0]; + info->lowest_vol_id = INT_MAX; + + while (1) { int vol_id, ret, devno; + char tmp_buf[256]; + + errno = 0; + dirent = readdir(sysfs_ubi); + if (!dirent) + break; + + if (strlen(dirent->d_name) > 256) { + errmsg("invalid entry in %s: \"%s\"", + lib->sysfs_ubi, dirent->d_name); + goto out_close; + } - ret = sscanf(name, UBI_VOL_NAME_PATT, &devno, &vol_id); + ret = sscanf(dirent->d_name, UBI_VOL_NAME_PATT"%s", &devno, &vol_id, tmp_buf); if (ret == 2 && devno == dev_num) { info->vol_count += 1; - if (vol_id > info->highest_vol_num) - info->highest_vol_num = vol_id; - if (vol_id < info->lowest_vol_num) - info->lowest_vol_num = vol_id; + if (vol_id > info->highest_vol_id) + info->highest_vol_id = vol_id; + if (vol_id < info->lowest_vol_id) + info->lowest_vol_id = vol_id; } } - closedir(sysfs_ubi); + if (!dirent && errno) { + sys_errmsg("readdir failed on \"%s\"", lib->sysfs_ubi); + goto out_close; + } - if (info->lowest_vol_num == INT_MAX) - info->lowest_vol_num = 0; + if (closedir(sysfs_ubi)) + return sys_errmsg("closedir failed on \"%s\"", lib->sysfs_ubi); - if (dev_read_int(lib->dev_avail_ebs, dev_num, &info->avail_ebs)) + if (info->lowest_vol_id == INT_MAX) + info->lowest_vol_id = 0; + + if (dev_get_major(lib, dev_num, &info->major, &info->minor)) + return -1; + + if (dev_read_int(lib->dev_avail_ebs, dev_num, &info->avail_lebs)) return -1; - if (dev_read_int(lib->dev_total_ebs, dev_num, &info->total_ebs)) + if (dev_read_int(lib->dev_total_ebs, dev_num, &info->total_lebs)) return -1; if (dev_read_int(lib->dev_bad_count, dev_num, &info->bad_count)) return -1; - if (dev_read_int(lib->dev_eb_size, dev_num, &info->eb_size)) + if (dev_read_int(lib->dev_eb_size, dev_num, &info->leb_size)) return -1; if (dev_read_int(lib->dev_bad_rsvd, dev_num, &info->bad_rsvd)) return -1; @@ -381,26 +1080,25 @@ int ubi_get_dev_info1(libubi_t desc, int dev_num, struct ubi_dev_info *info) if (dev_read_int(lib->dev_min_io_size, dev_num, &info->min_io_size)) return -1; - info->avail_bytes = info->avail_ebs * info->eb_size; - info->total_bytes = info->total_ebs * info->eb_size; + info->avail_bytes = info->avail_lebs * info->leb_size; + info->total_bytes = info->total_lebs * info->leb_size; return 0; + +out_close: + closedir(sysfs_ubi); + return -1; } -int ubi_get_vol_info(libubi_t desc, const char *node, struct ubi_vol_info *info) +int ubi_get_dev_info(libubi_t desc, const char *node, struct ubi_dev_info *info) { - int vol_id, dev_num; + int dev_num; struct libubi *lib = (struct libubi *)desc; - dev_num = find_dev_num_vol(lib, node); - if (dev_num == -1) - return -1; - - vol_id = find_vol_num(lib, dev_num, node); - if (vol_id == -1) + if (dev_node2num(lib, node, &dev_num)) return -1; - return ubi_get_vol_info1(desc, dev_num, vol_id, info); + return ubi_get_dev_info1(desc, dev_num, info); } int ubi_get_vol_info1(libubi_t desc, int dev_num, int vol_id, @@ -414,16 +1112,21 @@ int ubi_get_vol_info1(libubi_t desc, int dev_num, int vol_id, info->dev_num = dev_num; info->vol_id = vol_id; - ret = vol_read_data(lib->vol_type, dev_num, vol_id, &buf[0], 50); + if (dev_get_major(lib, dev_num, &info->dev_major, &info->dev_minor)) + return -1; + if (vol_get_major(lib, dev_num, vol_id, &info->major, &info->minor)) + return -1; + + ret = vol_read_data(lib->vol_type, dev_num, vol_id, buf, 50); if (ret < 0) return -1; - if (strncmp(&buf[0], "static\n", ret) == 0) + if (strncmp(buf, "static\n", ret) == 0) info->type = UBI_STATIC_VOLUME; - else if (strncmp(&buf[0], "dynamic\n", ret) == 0) + else if (strncmp(buf, "dynamic\n", ret) == 0) info->type = UBI_DYNAMIC_VOLUME; else { - fprintf(stderr, "LIBUBI: bad value at sysfs file\n"); + errmsg("bad value at \"%s\"", buf); errno = EINVAL; return -1; } @@ -436,17 +1139,17 @@ int ubi_get_vol_info1(libubi_t desc, int dev_num, int vol_id, &info->data_bytes); if (ret) return -1; - ret = vol_read_int(lib->vol_rsvd_ebs, dev_num, vol_id, &info->rsvd_ebs); + ret = vol_read_int(lib->vol_rsvd_ebs, dev_num, vol_id, &info->rsvd_lebs); if (ret) return -1; - ret = vol_read_int(lib->vol_eb_size, dev_num, vol_id, &info->eb_size); + ret = vol_read_int(lib->vol_eb_size, dev_num, vol_id, &info->leb_size); if (ret) return -1; ret = vol_read_int(lib->vol_corrupted, dev_num, vol_id, &info->corrupted); if (ret) return -1; - info->rsvd_bytes = info->eb_size * info->rsvd_ebs; + info->rsvd_bytes = info->leb_size * info->rsvd_lebs; ret = vol_read_data(lib->vol_name, dev_num, vol_id, &info->name, UBI_VOL_NAME_MAX + 2); @@ -457,457 +1160,45 @@ int ubi_get_vol_info1(libubi_t desc, int dev_num, int vol_id, return 0; } -/** - * read_int - read an 'int' value from a file. - * - * @file the file to read from - * @value the result is stored here - * - * This function returns %0 in case of success and %-1 in case of failure. - */ -static int read_int(const char *file, int *value) -{ - int fd, rd; - char buf[50]; - - fd = open(file, O_RDONLY); - if (fd == -1) - return -1; - - rd = read(fd, &buf[0], 50); - if (rd == -1) - goto error; - - if (sscanf(&buf[0], "%d\n", value) != 1) { - /* This must be a UBI bug */ - fprintf(stderr, "LIBUBI: bad value at sysfs file\n"); - errno = EINVAL; - goto error; - } - - close(fd); - return 0; - -error: - close(fd); - return -1; -} - -/** - * dev_read_int - read an 'int' value from an UBI device's sysfs file. - * - * @patt the file pattern to read from - * @dev_num UBI device number - * @value the result is stored here - * - * This function returns %0 in case of success and %-1 in case of failure. - */ -static int dev_read_int(const char *patt, int dev_num, int *value) -{ - int fd, rd; - char buf[50]; - char file[strlen(patt) + 50]; - - sprintf(&file[0], patt, dev_num); - fd = open(&file[0], O_RDONLY); - if (fd == -1) - return -1; - - rd = read(fd, &buf[0], 50); - if (rd == -1) - goto error; - - if (sscanf(&buf[0], "%d\n", value) != 1) { - /* This must be a UBI bug */ - fprintf(stderr, "LIBUBI: bad value at sysfs file\n"); - errno = EINVAL; - goto error; - } - - close(fd); - return 0; - -error: - close(fd); - return -1; -} - -/** - * dev_read_ll - read a 'long long' value from an UBI device's sysfs file. - * - * @patt the file pattern to read from - * @dev_num UBI device number - * @value the result is stored here - * - * This function returns %0 in case of success and %-1 in case of failure. - */ -static int dev_read_ll(const char *patt, int dev_num, long long *value) -{ - int fd, rd; - char buf[50]; - char file[strlen(patt) + 50]; - - sprintf(&file[0], patt, dev_num); - fd = open(&file[0], O_RDONLY); - if (fd == -1) - return -1; - - rd = read(fd, &buf[0], 50); - if (rd == -1) - goto error; - - if (sscanf(&buf[0], "%lld\n", value) != 1) { - /* This must be a UBI bug */ - fprintf(stderr, "LIBUBI: bad value at sysfs file\n"); - errno = EINVAL; - goto error; - } - - close(fd); - return 0; - -error: - close(fd); - return -1; -} - -/** - * dev_read_data - read data from an UBI device's sysfs file. - * - * @patt the file pattern to read from - * @dev_num UBI device number - * @buf buffer to read data to - * @buf_len buffer length - * - * This function returns number of read bytes in case of success and %-1 in - * case of failure. - */ -static int dev_read_data(const char *patt, int dev_num, void *buf, int buf_len) -{ - int fd, rd; - char file[strlen(patt) + 50]; - - sprintf(&file[0], patt, dev_num); - fd = open(&file[0], O_RDONLY); - if (fd == -1) - return -1; - - rd = read(fd, buf, buf_len); - if (rd == -1) { - close(fd); - return -1; - } - - close(fd); - return rd; -} - -/** - * vol_read_int - read an 'int' value from an UBI volume's sysfs file. - * - * @patt the file pattern to read from - * @dev_num UBI device number - * @vol_id volume identifier - * @value the result is stored here - * - * This function returns %0 in case of success and %-1 in case of failure. - */ -static int vol_read_int(const char *patt, int dev_num, int vol_id, int *value) -{ - int fd, rd; - char buf[50]; - char file[strlen(patt) + 100]; - - sprintf(&file[0], patt, dev_num, vol_id); - fd = open(&file[0], O_RDONLY); - if (fd == -1) - return -1; - - rd = read(fd, &buf[0], 50); - if (rd == -1) - goto error; - - if (sscanf(&buf[0], "%d\n", value) != 1) { - /* This must be a UBI bug */ - fprintf(stderr, "LIBUBI: bad value at sysfs file\n"); - errno = EINVAL; - goto error; - } - - close(fd); - return 0; - -error: - close(fd); - return -1; -} - -/** - * vol_read_ll - read a 'long long' value from an UBI volume's sysfs file. - * - * @patt the file pattern to read from - * @dev_num UBI device number - * @vol_id volume identifier - * @value the result is stored here - * - * This function returns %0 in case of success and %-1 in case of failure. - */ -static int vol_read_ll(const char *patt, int dev_num, int vol_id, - long long *value) -{ - int fd, rd; - char buf[50]; - char file[strlen(patt) + 100]; - - sprintf(&file[0], patt, dev_num, vol_id); - fd = open(&file[0], O_RDONLY); - if (fd == -1) - return -1; - - rd = read(fd, &buf[0], 50); - if (rd == -1) - goto error; - - if (sscanf(&buf[0], "%lld\n", value) != 1) { - /* This must be a UBI bug */ - fprintf(stderr, "LIBUBI: bad value at sysfs file\n"); - errno = EINVAL; - goto error; - } - - close(fd); - return 0; - -error: - close(fd); - return -1; -} - -/** - * vol_read_data - read data from an UBI volume's sysfs file. - * - * @patt the file pattern to read from - * @dev_num UBI device number - * @vol_id volume identifier - * @buf buffer to read to - * @buf_len buffer length - * - * This function returns number of read bytes in case of success and %-1 in - * case of failure. - */ -static int vol_read_data(const char *patt, int dev_num, int vol_id, void *buf, - int buf_len) -{ - int fd, rd; - char file[strlen(patt) + 100]; - - sprintf(&file[0], patt, dev_num, vol_id); - fd = open(&file[0], O_RDONLY); - if (fd == -1) - return -1; - - rd = read(fd, buf, buf_len); - if (rd == -1) { - close(fd); - return -1; - } - - close(fd); - return rd; -} - -/** - * mkpath - compose full path from 2 given components. - * - * @path first component - * @name second component - * - * This function returns the resulting path in case of success and %NULL in - * case of failure. - */ -static char *mkpath(const char *path, const char *name) -{ - char *n; - int len1 = strlen(path); - int len2 = strlen(name); - - n = malloc(len1 + len2 + 2); - if (!n) - return NULL; - - memcpy(n, path, len1); - if (n[len1 - 1] != '/') - n[len1++] = '/'; - - memcpy(n + len1, name, len2 + 1); - return n; -} - -/** - * find_dev_num - find UBI device number by its character device node. - * - * @lib UBI library descriptor - * @node UBI character device node name - * - * This function returns positive UBI device number in case of success and %-1 - * in case of failure. - */ -static int find_dev_num(struct libubi *lib, const char *node) -{ - struct stat st; - struct ubi_info info; - int i, major, minor; - - if (stat(node, &st)) - return -1; - - if (!S_ISCHR(st.st_mode)) { - errno = EINVAL; - return -1; - } - - major = major(st.st_rdev); - minor = minor(st.st_rdev); - - if (minor != 0) { - errno = -EINVAL; - return -1; - } - - if (ubi_get_info((libubi_t *)lib, &info)) - return -1; - - for (i = info.lowest_dev_num; i <= info.highest_dev_num; i++) { - int major1, minor1, ret; - char buf[50]; - - ret = dev_read_data(lib->dev_dev, i, &buf[0], 50); - if (ret < 0) - return -1; - - ret = sscanf(&buf[0], "%d:%d\n", &major1, &minor1); - if (ret != 2) { - fprintf(stderr, "LIBUBI: bad value at sysfs file\n"); - errno = EINVAL; - return -1; - } - - if (minor1 == minor && major1 == major) - return i; - } - - errno = ENOENT; - return -1; -} - -/** - * find_dev_num_vol - find UBI device number by volume character device node. - * - * @lib UBI library descriptor - * @node UBI character device node name - * - * This function returns positive UBI device number in case of success and %-1 - * in case of failure. - */ -static int find_dev_num_vol(struct libubi *lib, const char *node) +int ubi_get_vol_info(libubi_t desc, const char *node, struct ubi_vol_info *info) { - struct stat st; - struct ubi_info info; - int i, major; - - if (stat(node, &st)) - return -1; - - if (!S_ISCHR(st.st_mode)) { - errno = EINVAL; - return -1; - } - - major = major(st.st_rdev); - - if (minor(st.st_rdev) == 0) { - errno = -EINVAL; - return -1; - } + int vol_id, dev_num; + struct libubi *lib = (struct libubi *)desc; - if (ubi_get_info((libubi_t *)lib, &info)) + if (vol_node2nums(lib, node, &dev_num, &vol_id)) return -1; - for (i = info.lowest_dev_num; i <= info.highest_dev_num; i++) { - int major1, minor1, ret; - char buf[50]; - - ret = dev_read_data(lib->dev_dev, i, &buf[0], 50); - if (ret < 0) - return -1; - - ret = sscanf(&buf[0], "%d:%d\n", &major1, &minor1); - if (ret != 2) { - fprintf(stderr, "LIBUBI: bad value at sysfs file\n"); - errno = EINVAL; - return -1; - } - - if (major1 == major) - return i; - } - - errno = ENOENT; - return -1; + return ubi_get_vol_info1(desc, dev_num, vol_id, info); } -/** - * find_vol_num - find UBI volume number by its character device node. - * - * @lib UBI library descriptor - * @dev_num UBI device number - * @node UBI volume character device node name - * - * This function returns positive UBI volume number in case of success and %-1 - * in case of failure. - */ -static int find_vol_num(struct libubi *lib, int dev_num, const char *node) +int ubi_get_vol_info1_nm(libubi_t desc, int dev_num, const char *name, + struct ubi_vol_info *info) { - struct stat st; - struct ubi_dev_info info; - int i, major, minor; - - if (stat(node, &st)) - return -1; + int i, err; + unsigned int nlen = strlen(name); + struct ubi_dev_info dev_info; - if (!S_ISCHR(st.st_mode)) { + if (nlen == 0) { + errmsg("bad \"name\" input parameter"); errno = EINVAL; return -1; } - major = major(st.st_rdev); - minor = minor(st.st_rdev); - - if (minor == 0) { - errno = -EINVAL; - return -1; - } - - if (ubi_get_dev_info1((libubi_t *)lib, dev_num, &info)) - return -1; - - for (i = info.lowest_vol_num; i <= info.highest_vol_num; i++) { - int major1, minor1, ret; - char buf[50]; - - ret = vol_read_data(lib->vol_dev, dev_num, i, &buf[0], 50); - if (ret < 0) - return -1; + err = ubi_get_dev_info1(desc, dev_num, &dev_info); + if (err) + return err; - ret = sscanf(&buf[0], "%d:%d\n", &major1, &minor1); - if (ret != 2) { - fprintf(stderr, "LIBUBI: bad value at sysfs file\n"); - errno = EINVAL; + for (i = dev_info.lowest_vol_id; + i <= dev_info.highest_vol_id; i++) { + err = ubi_get_vol_info1(desc, dev_num, i, info); + if (err == -1) { + if (errno == ENOENT) + continue; return -1; } - if (minor1 == minor && major1 == major) - return i; + if (nlen == strlen(info->name) && !strcmp(name, info->name)) + return 0; } errno = ENOENT; diff --git a/ubi-utils/src/libubi_int.h b/ubi-utils/src/libubi_int.h index e68b791..2e664b8 100644 --- a/ubi-utils/src/libubi_int.h +++ b/ubi-utils/src/libubi_int.h @@ -15,7 +15,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * - * Author: Artem B. Bityutskiy + * Author: Artem Bityutskiy * * UBI (Unsorted Block Images) library. */ @@ -23,20 +23,31 @@ #ifndef __LIBUBI_INT_H__ #define __LIBUBI_INT_H__ +#include <string.h> +#include <errno.h> + #ifdef __cplusplus extern "C" { #endif /* - * UBI heavily makes use of the sysfs file system to interact with users-pace. * The below are pre-define UBI file and directory names. + * + * Note, older kernels put 'ubiX_Y' directories straight to '/sys/class/ubi/'. + * New kernels puts 'ubiX_Y' directories to '/sys/class/ubi/ubiX/', which is + * saner. And for compatibility reasons it also puts symlinks to 'ubiX_Y' + * directories to '/sys/class/ubi/'. For now libubi assumes old layout. */ #define SYSFS_UBI "class/ubi" -#define UBI_DEV_NAME_PATT "ubi%d" +#define SYSFS_CTRL "class/misc/ubi_ctrl/" + +#define CTRL_DEV "dev" + #define UBI_VER "version" +#define UBI_DEV_NAME_PATT "ubi%d" + #define DEV_DEV "dev" -#define UBI_VOL_NAME_PATT "ubi%d_%d" #define DEV_AVAIL_EBS "avail_eraseblocks" #define DEV_TOTAL_EBS "total_eraseblocks" #define DEV_BAD_COUNT "bad_peb_count" @@ -45,6 +56,9 @@ extern "C" { #define DEV_MAX_RSVD "reserved_for_bad" #define DEV_MAX_VOLS "max_vol_count" #define DEV_MIN_IO_SIZE "min_io_size" +#define DEV_MTD_NUM "mtd_num" + +#define UBI_VOL_NAME_PATT "ubi%d_%d" #define VOL_TYPE "type" #define VOL_DEV "dev" #define VOL_ALIGNMENT "alignment" @@ -56,34 +70,37 @@ extern "C" { /** * libubi - UBI library description data structure. - * - * @sysfs sysfs file system path - * @sysfs_ubi UBI directory in sysfs - * @ubi_dev UBI device sysfs directory pattern - * @ubi_version UBI version file sysfs path - * @dev_dev UBI device's major/minor numbers file pattern - * @dev_avail_ebs count of available eraseblocks sysfs path pattern - * @dev_total_ebs total eraseblocks count sysfs path pattern - * @dev_bad_count count of bad eraseblocks sysfs path pattern - * @dev_eb_size size of UBI device's eraseblocks sysfs path pattern - * @dev_max_ec maximum erase counter sysfs path pattern - * @dev_bad_rsvd count of physical eraseblock reserved for bad eraseblocks - * handling - * @dev_max_vols maximum volumes number count sysfs path pattern - * @dev_min_io_size minimum I/O unit size sysfs path pattern - * @ubi_vol UBI volume sysfs directory pattern - * @vol_type volume type sysfs path pattern - * @vol_dev volume's major/minor numbers file pattern - * @vol_alignment volume alignment sysfs path pattern - * @vol_data_bytes volume data size sysfs path pattern - * @vol_rsvd_ebs volume reserved size sysfs path pattern - * @vol_eb_size volume eraseblock size sysfs path pattern - * @vol_corrupted volume corruption flag sysfs path pattern - * @vol_name volume name sysfs path pattern + * @sysfs: sysfs file system path + * @sysfs_ctrl: UBI control device directory in sysfs + * @ctrl_dev: UBI control device major/minor numbers sysfs file + * @sysfs_ubi: UBI directory in sysfs + * @ubi_dev: UBI device sysfs directory pattern + * @ubi_version: UBI version file sysfs path + * @dev_dev: UBI device major/minor numbers file pattern + * @dev_avail_ebs: count of available eraseblocks sysfs path pattern + * @dev_total_ebs: total eraseblocks count sysfs path pattern + * @dev_bad_count: count of bad eraseblocks sysfs path pattern + * @dev_eb_size: size of UBI device's eraseblocks sysfs path pattern + * @dev_max_ec: maximum erase counter sysfs path pattern + * @dev_bad_rsvd: count of physical eraseblock reserved for bad eraseblocks + * handling + * @dev_max_vols: maximum volumes number count sysfs path pattern + * @dev_min_io_size: minimum I/O unit size sysfs path pattern + * @ubi_vol: UBI volume sysfs directory pattern + * @vol_type: volume type sysfs path pattern + * @vol_dev: volume major/minor numbers file pattern + * @vol_alignment: volume alignment sysfs path pattern + * @vol_data_bytes: volume data size sysfs path pattern + * @vol_rsvd_ebs: volume reserved size sysfs path pattern + * @vol_eb_size: volume eraseblock size sysfs path pattern + * @vol_corrupted: volume corruption flag sysfs path pattern + * @vol_name: volume name sysfs path pattern */ struct libubi { char *sysfs; + char *sysfs_ctrl; + char *ctrl_dev; char *sysfs_ubi; char *ubi_dev; char *ubi_version; @@ -96,6 +113,7 @@ struct libubi char *dev_bad_rsvd; char *dev_max_vols; char *dev_min_io_size; + char *dev_mtd_num; char *ubi_vol; char *vol_type; char *vol_dev; @@ -108,20 +126,6 @@ struct libubi char *vol_max_count; }; -static int read_int(const char *file, int *value); -static int dev_read_int(const char *patt, int dev_num, int *value); -static int dev_read_ll(const char *patt, int dev_num, long long *value); -static int dev_read_data(const char *patt, int dev_num, void *buf, int buf_len); -static int vol_read_int(const char *patt, int dev_num, int vol_id, int *value); -static int vol_read_ll(const char *patt, int dev_num, int vol_id, - long long *value); -static int vol_read_data(const char *patt, int dev_num, int vol_id, void *buf, - int buf_len); -static char *mkpath(const char *path, const char *name); -static int find_dev_num(struct libubi *lib, const char *node); -static int find_dev_num_vol(struct libubi *lib, const char *node); -static int find_vol_num(struct libubi *lib, int dev_num, const char *node); - #ifdef __cplusplus } #endif diff --git a/ubi-utils/src/libubigen.c b/ubi-utils/src/libubigen.c index 1793009..91bb274 100644 --- a/ubi-utils/src/libubigen.c +++ b/ubi-utils/src/libubigen.c @@ -1,5 +1,6 @@ /* * Copyright (c) International Business Machines Corp., 2006 + * Copyright (C) 2008 Nokia Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,474 +15,316 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* + * Generating UBI images. * - * Author: Oliver Lohmann - * - * Add UBI headers to binary data. + * Authors: Oliver Lohmann + * Artem Bityutskiy */ #include <stdlib.h> #include <stdint.h> -#include <stdio.h> -#include <errno.h> +#include <unistd.h> #include <string.h> + #include <mtd/ubi-media.h> #include <mtd_swab.h> - -#include "config.h" -#include "ubigen.h" +#include <libubigen.h> #include "crc32.h" - -#define UBI_NAME_SIZE 256 -#define DEFAULT_VID_OFFSET ((DEFAULT_PAGESIZE) - (UBI_VID_HDR_SIZE)) -#define MIN(a,b) ((a) < (b) ? (a) : (b)) - -static uint32_t crc32_table[256]; - -struct ubi_info { - struct ubi_vid_hdr* v; /* Volume ID header */ - struct ubi_ec_hdr* ec; /* Erase count header */ - - FILE* fp_in; /* Input Stream */ - FILE* fp_out; /* Output stream */ - - size_t eb_size; /* Physical EB size in bytes */ - size_t leb_size; /* Size of a logical EB in a physical EB */ - size_t leb_total; /* Total input size in logical EB */ - size_t alignment; /* Block alignment */ - size_t data_pad; /* Size of padding in each physical EB */ - - size_t bytes_total; /* Total input size in bytes */ - size_t bytes_read; /* Nymber of read bytes (total) */ - - uint32_t blks_written; /* Number of written logical EB */ - - uint8_t* buf; /* Allocated buffer */ - uint8_t* ptr_ec_hdr; /* Pointer to EC hdr in buf */ - uint8_t* ptr_vid_hdr; /* Pointer to VID hdr in buf */ - uint8_t* ptr_data; /* Pointer to data region in buf */ -}; - - -static uint32_t -byte_to_blk(uint64_t byte, uint32_t eb_size) -{ - return (byte % eb_size) == 0 - ? (byte / eb_size) - : (byte / eb_size) + 1; -} - -static int -validate_ubi_info(ubi_info_t u) -{ - if ((u->v->vol_type != UBI_VID_DYNAMIC) && - (u->v->vol_type != UBI_VID_STATIC)) { - return EUBIGEN_INVALID_TYPE; - } - - if (be32_to_cpu(u->ec->vid_hdr_offset) < UBI_VID_HDR_SIZE) { - return EUBIGEN_INVALID_HDR_OFFSET; - } - - return 0; -} - -static int -skip_blks(ubi_info_t u, uint32_t blks) -{ - uint32_t i; - size_t read = 0, to_read = 0; - - /* Step to a maximum of leb_total - 1 to keep the - restrictions. */ - for (i = 0; i < MIN(blks, u->leb_total-1); i++) { - /* Read in data */ - to_read = MIN(u->leb_size, - (u->bytes_total - u->bytes_read)); - read = fread(u->ptr_data, 1, to_read, u->fp_in); - if (read != to_read) { - return -EIO; - } - u->bytes_read += read; - u->blks_written++; - } - - return 0; -} - -static void -clear_buf(ubi_info_t u) -{ - memset(u->buf, 0xff, u->eb_size); -} - -static void -write_ec_hdr(ubi_info_t u) -{ - memcpy(u->ptr_ec_hdr, u->ec, UBI_EC_HDR_SIZE); -} - -static int -fill_data_buffer_from_file(ubi_info_t u, size_t* read) -{ - size_t to_read = 0; - - if (u-> fp_in == NULL) - return -EIO; - - to_read = MIN(u->leb_size, (u->bytes_total - u->bytes_read)); - *read = fread(u->ptr_data, 1, to_read, u->fp_in); - if (*read != to_read) { - return -EIO; - } - return 0; -} - -static void -add_static_info(ubi_info_t u, size_t data_size, ubigen_action_t action) -{ - uint32_t crc = clc_crc32(crc32_table, UBI_CRC32_INIT, - u->ptr_data, data_size); - - u->v->data_size = cpu_to_be32(data_size); - u->v->data_crc = cpu_to_be32(crc); - - if (action & BROKEN_DATA_CRC) { - u->v->data_crc = - cpu_to_be32(be32_to_cpu(u->v->data_crc) + 1); - } - if (action & BROKEN_DATA_SIZE) { - u->v->data_size = - cpu_to_be32(be32_to_cpu(u->v->data_size) + 1); - } -} - -static void -write_vid_hdr(ubi_info_t u, ubigen_action_t action) +#include "common.h" + +#define PROGRAM_NAME "libubigen" + +/** + * ubigen_info_init - initialize libubigen. + * @ui: libubigen information + * @peb_size: flash physical eraseblock size + * @min_io_size: flash minimum input/output unit size + * @subpage_size: flash sub-page, if present (has to be equivalent to + * @min_io_size if does not exist) + * @vid_hdr_offs: offset of the VID header + * @ubi_ver: UBI version + */ +void ubigen_info_init(struct ubigen_info *ui, int peb_size, int min_io_size, + int subpage_size, int vid_hdr_offs, int ubi_ver) { - uint32_t crc = clc_crc32(crc32_table, UBI_CRC32_INIT, - u->v, UBI_VID_HDR_SIZE_CRC); - /* Write VID header */ - u->v->hdr_crc = cpu_to_be32(crc); - if (action & BROKEN_HDR_CRC) { - u->v->hdr_crc = cpu_to_be32(be32_to_cpu(u->v->hdr_crc) + 1); + if (!vid_hdr_offs) { + vid_hdr_offs = UBI_EC_HDR_SIZE + subpage_size - 1; + vid_hdr_offs /= subpage_size; + vid_hdr_offs *= subpage_size; } - memcpy(u->ptr_vid_hdr, u->v, UBI_VID_HDR_SIZE); -} -static int -write_to_output_stream(ubi_info_t u) -{ - size_t written; - - written = fwrite(u->buf, 1, u->eb_size, u->fp_out); - if (written != u->eb_size) { - return -EIO; - } - return 0; + ui->peb_size = peb_size; + ui->min_io_size = min_io_size; + ui->vid_hdr_offs = vid_hdr_offs; + ui->data_offs = vid_hdr_offs + UBI_VID_HDR_SIZE + min_io_size - 1; + ui->data_offs /= min_io_size; + ui->data_offs *= min_io_size; + ui->leb_size = peb_size - ui->data_offs; + ui->ubi_ver = ubi_ver; + + ui->max_volumes = ui->leb_size / UBI_VTBL_RECORD_SIZE; + if (ui->max_volumes > UBI_MAX_VOLUMES) + ui->max_volumes = UBI_MAX_VOLUMES; + ui->vtbl_size = ui->max_volumes * UBI_VTBL_RECORD_SIZE; } -int -ubigen_write_leb(ubi_info_t u, ubigen_action_t action) +/** + * ubigen_create_empty_vtbl - creates empty volume table. + * + * This function creates an empty volume table and returns a pointer to it in + * case of success and %NULL in case of failure. The returned object has to be + * freed with 'free()' call. + */ +struct ubi_vtbl_record *ubigen_create_empty_vtbl(const struct ubigen_info *ui) { - int rc = 0; - size_t read = 0; - - clear_buf(u); - write_ec_hdr(u); + struct ubi_vtbl_record *vtbl; + int i; - rc = fill_data_buffer_from_file(u, &read); - if (rc != 0) - return rc; - - if (u->v->vol_type == UBI_VID_STATIC) { - add_static_info(u, read, action); + vtbl = calloc(1, ui->vtbl_size); + if (!vtbl) { + sys_errmsg("cannot allocate %d bytes of memory", ui->vtbl_size); + return NULL; } - u->v->lnum = cpu_to_be32(u->blks_written); - - if (action & MARK_AS_UPDATE) { - u->v->copy_flag = (u->v->copy_flag)++; + for (i = 0; i < ui->max_volumes; i++) { + uint32_t crc = crc32(UBI_CRC32_INIT, &vtbl[i], + UBI_VTBL_RECORD_SIZE_CRC); + vtbl[i].crc = cpu_to_be32(crc); } - write_vid_hdr(u, action); - rc = write_to_output_stream(u); - if (rc != 0) - return rc; - - /* Update current handle */ - u->bytes_read += read; - u->blks_written++; - return 0; + return vtbl; } -int -ubigen_write_complete(ubi_info_t u) +/** + * ubigen_add_volume - add a volume to the volume table. + * @ui: libubigen information + * @vi: volume information + * @vtbl: volume table to add to + * + * This function adds volume described by input parameters to the volume table + * @vtbl. + */ +int ubigen_add_volume(const struct ubigen_info *ui, + const struct ubigen_vol_info *vi, + struct ubi_vtbl_record *vtbl) { - size_t i; - int rc = 0; - - for (i = 0; i < u->leb_total; i++) { - rc = ubigen_write_leb(u, NO_ERROR); - if (rc != 0) - return rc; - } - + struct ubi_vtbl_record *vtbl_rec = &vtbl[vi->id]; + uint32_t tmp; + + if (vi->id >= ui->max_volumes) + return errmsg("too high volume id %d, max. volumes is %d", + vi->id, ui->max_volumes); + + if (vi->alignment >= ui->leb_size) + return errmsg("too large alignment %d, max is %d (LEB size)", + vi->alignment, ui->leb_size); + + memset(vtbl_rec, '\0', sizeof(struct ubi_vtbl_record)); + tmp = (vi->bytes + ui->leb_size - 1) / ui->leb_size; + vtbl_rec->reserved_pebs = cpu_to_be32(tmp); + vtbl_rec->alignment = cpu_to_be32(vi->alignment); + vtbl_rec->vol_type = vi->type; + tmp = ui->leb_size % vi->alignment; + vtbl_rec->data_pad = cpu_to_be32(tmp); + vtbl_rec->flags = vi->flags; + + memcpy(vtbl_rec->name, vi->name, vi->name_len); + vtbl_rec->name[vi->name_len] = '\0'; + vtbl_rec->name_len = cpu_to_be16(vi->name_len); + + tmp = crc32(UBI_CRC32_INIT, vtbl_rec, UBI_VTBL_RECORD_SIZE_CRC); + vtbl_rec->crc = cpu_to_be32(tmp); return 0; } -int -ubigen_write_broken_update(ubi_info_t u, uint32_t blk) +/** + * ubigen_init_ec_hdr - initialize EC header. + * @ui: libubigen information + * @hdr: the EC header to initialize + * @ec: erase counter value + */ +void ubigen_init_ec_hdr(const struct ubigen_info *ui, + struct ubi_ec_hdr *hdr, long long ec) { - int rc = 0; + uint32_t crc; - rc = skip_blks(u, blk); - if (rc != 0) - return rc; + memset(hdr, '\0', sizeof(struct ubi_ec_hdr)); - rc = ubigen_write_leb(u, MARK_AS_UPDATE | BROKEN_DATA_CRC); - if (rc != 0) - return rc; + hdr->magic = cpu_to_be32(UBI_EC_HDR_MAGIC); + hdr->version = ui->ubi_ver; + hdr->ec = cpu_to_be64(ec); + hdr->vid_hdr_offset = cpu_to_be32(ui->vid_hdr_offs); + hdr->data_offset = cpu_to_be32(ui->data_offs); - return 0; + crc = crc32(UBI_CRC32_INIT, hdr, UBI_EC_HDR_SIZE_CRC); + hdr->hdr_crc = cpu_to_be32(crc); } -void -dump_info(ubi_info_t u ubi_unused) +/** + * init_vid_hdr - initialize VID header. + * @ui: libubigen information + * @vi: volume information + * @hdr: the VID header to initialize + * @lnum: logical eraseblock number + * @data: the contents of the LEB (static volumes only) + * @data_size: amount of data in this LEB (static volumes only) + * + * Note, @used_ebs, @data and @data_size are ignored in case of dynamic + * volumes. + */ +static void init_vid_hdr(const struct ubigen_info *ui, + const struct ubigen_vol_info *vi, + struct ubi_vid_hdr *hdr, int lnum, + const void *data, int data_size) { -#ifdef DEBUG - int err = 0; - if (!u) { - fprintf(stderr, "<empty>"); - return; - } - if (!u->ec) { - fprintf(stderr, "<ec-empty>"); - err = 1; - } - if (!u->v) { - fprintf(stderr, "<v-empty>"); - err = 1; - } - if (err) return; - - fprintf(stderr, "ubi volume\n"); - fprintf(stderr, "version : %8d\n", u->v->version); - fprintf(stderr, "vol_id : %8d\n", be32_to_cpu(u->v->vol_id)); - fprintf(stderr, "vol_type : %8s\n", - u->v->vol_type == UBI_VID_STATIC ? - "static" : "dynamic"); - fprintf(stderr, "used_ebs : %8d\n", - be32_to_cpu(u->v->used_ebs)); - fprintf(stderr, "eb_size : 0x%08x\n", u->eb_size); - fprintf(stderr, "leb_size : 0x%08x\n", u->leb_size); - fprintf(stderr, "data_pad : 0x%08x\n", - be32_to_cpu(u->v->data_pad)); - fprintf(stderr, "leb_total : %8d\n", u->leb_total); - fprintf(stderr, "header offs : 0x%08x\n", - be32_to_cpu(u->ec->vid_hdr_offset)); - fprintf(stderr, "bytes_total : %8d\n", u->bytes_total); - fprintf(stderr, " + in MiB : %8.2f M\n", - ((float)(u->bytes_total)) / 1024 / 1024); - fprintf(stderr, "-------------------------------\n\n"); -#else - return; -#endif -} + uint32_t crc; -int -ubigen_destroy(ubi_info_t *u) -{ - if (u == NULL) - return -EINVAL; - - ubi_info_t tmp = *u; - - if (tmp) { - if (tmp->v) - free(tmp->v); - if (tmp->ec) - free(tmp->ec); - if (tmp->buf) - free(tmp->buf); - free(tmp); + memset(hdr, '\0', sizeof(struct ubi_vid_hdr)); + + hdr->magic = cpu_to_be32(UBI_VID_HDR_MAGIC); + hdr->version = ui->ubi_ver; + hdr->vol_type = vi->type; + hdr->vol_id = cpu_to_be32(vi->id); + hdr->lnum = cpu_to_be32(lnum); + hdr->data_pad = cpu_to_be32(vi->data_pad); + hdr->compat = vi->compat; + + if (vi->type == UBI_VID_STATIC) { + hdr->data_size = cpu_to_be32(data_size); + hdr->used_ebs = cpu_to_be32(vi->used_ebs); + crc = crc32(UBI_CRC32_INIT, data, data_size); + hdr->data_crc = cpu_to_be32(crc); } - *u = NULL; - return 0; -} -void -ubigen_init(void) -{ - init_crc32_table(crc32_table); + crc = crc32(UBI_CRC32_INIT, hdr, UBI_VID_HDR_SIZE_CRC); + hdr->hdr_crc = cpu_to_be32(crc); } -int -ubigen_create(ubi_info_t* u, uint32_t vol_id, uint8_t vol_type, - uint32_t eb_size, uint64_t ec, uint32_t alignment, - uint8_t version, uint32_t vid_hdr_offset, uint8_t compat_flag, - size_t data_size, FILE* fp_in, FILE* fp_out) +/** + * ubigen_write_volume - write UBI volume. + * @ui: libubigen information + * @vi: volume information + * @ec: erase coutner value to put to EC headers + * @bytes: volume size in bytes + * @in: input file descriptor (has to be properly seeked) + * @out: output file descriptor + * + * This function reads the contents of the volume from the input file @in and + * writes the UBI volume to the output file @out. Returns zero on success and + * %-1 on failure. + */ +int ubigen_write_volume(const struct ubigen_info *ui, + const struct ubigen_vol_info *vi, long long ec, + long long bytes, int in, int out) { - int rc = 0; - ubi_info_t res = NULL; - uint32_t crc; - uint32_t data_offset; + int len = vi->usable_leb_size, rd, lnum = 0; + char inbuf[ui->leb_size], outbuf[ui->peb_size]; - if (alignment == 0) { - rc = EUBIGEN_INVALID_ALIGNMENT; - goto ubigen_create_err; - } - if ((fp_in == NULL) || (fp_out == NULL)) { - rc = -EINVAL; - goto ubigen_create_err; - } + if (vi->id >= ui->max_volumes) + return errmsg("too high volume id %d, max. volumes is %d", + vi->id, ui->max_volumes); - res = (ubi_info_t) calloc(1, sizeof(struct ubi_info)); - if (res == NULL) { - rc = -ENOMEM; - goto ubigen_create_err; - } + if (vi->alignment >= ui->leb_size) + return errmsg("too large alignment %d, max is %d (LEB size)", + vi->alignment, ui->leb_size); - res->v = (struct ubi_vid_hdr*) calloc(1, sizeof(struct ubi_vid_hdr)); - if (res->v == NULL) { - rc = -ENOMEM; - goto ubigen_create_err; - } + memset(outbuf, 0xFF, ui->data_offs); + ubigen_init_ec_hdr(ui, (struct ubi_ec_hdr *)outbuf, ec); - res->ec = (struct ubi_ec_hdr*) calloc(1, sizeof(struct ubi_ec_hdr)); - if (res->ec == NULL) { - rc = -ENOMEM; - goto ubigen_create_err; - } + while (bytes) { + int l; + struct ubi_vid_hdr *vid_hdr; - /* data which is needed in the general process */ - vid_hdr_offset = vid_hdr_offset ? vid_hdr_offset : DEFAULT_VID_OFFSET; - data_offset = vid_hdr_offset + UBI_VID_HDR_SIZE; - res->bytes_total = data_size; - res->eb_size = eb_size ? eb_size : DEFAULT_BLOCKSIZE; - res->data_pad = (res->eb_size - data_offset) % alignment; - res->leb_size = res->eb_size - data_offset - res->data_pad; - res->leb_total = byte_to_blk(data_size, res->leb_size); - res->alignment = alignment; - - if ((res->eb_size < (vid_hdr_offset + UBI_VID_HDR_SIZE))) { - rc = EUBIGEN_TOO_SMALL_EB; - goto ubigen_create_err; - } - res->fp_in = fp_in; - res->fp_out = fp_out; - - /* vid hdr data which doesn't change */ - res->v->magic = cpu_to_be32(UBI_VID_HDR_MAGIC); - res->v->version = version ? version : UBI_VERSION; - res->v->vol_type = vol_type; - res->v->vol_id = cpu_to_be32(vol_id); - res->v->compat = compat_flag; - res->v->data_pad = cpu_to_be32(res->data_pad); - - /* static only: used_ebs */ - if (res->v->vol_type == UBI_VID_STATIC) { - res->v->used_ebs = cpu_to_be32(byte_to_blk - (res->bytes_total, - res->leb_size)); - } + if (bytes < len) + len = bytes; + bytes -= len; - /* ec hdr (fixed, doesn't change) */ - res->ec->magic = cpu_to_be32(UBI_EC_HDR_MAGIC); - res->ec->version = version ? version : UBI_VERSION; - res->ec->ec = cpu_to_be64(ec); - res->ec->vid_hdr_offset = cpu_to_be32(vid_hdr_offset); + l = len; + do { + rd = read(in, inbuf + len - l, l); + if (rd != l) + return sys_errmsg("cannot read %d bytes from the input file", l); - res->ec->data_offset = cpu_to_be32(data_offset); + l -= rd; + } while (l); - crc = clc_crc32(crc32_table, UBI_CRC32_INIT, res->ec, - UBI_EC_HDR_SIZE_CRC); - res->ec->hdr_crc = cpu_to_be32(crc); + vid_hdr = (struct ubi_vid_hdr *)(&outbuf[ui->vid_hdr_offs]); + init_vid_hdr(ui, vi, vid_hdr, lnum, inbuf, len); - /* prepare a read buffer */ - res->buf = (uint8_t*) malloc (res->eb_size * sizeof(uint8_t)); - if (res->buf == NULL) { - rc = -ENOMEM; - goto ubigen_create_err; - } - - /* point to distinct regions within the buffer */ - res->ptr_ec_hdr = res->buf; - res->ptr_vid_hdr = res->buf + be32_to_cpu(res->ec->vid_hdr_offset); - res->ptr_data = res->buf + be32_to_cpu(res->ec->vid_hdr_offset) - + UBI_VID_HDR_SIZE; + memcpy(outbuf + ui->data_offs, inbuf, len); + memset(outbuf + ui->data_offs + len, 0xFF, + ui->peb_size - ui->data_offs - len); - rc = validate_ubi_info(res); - if (rc != 0) { - fprintf(stderr, "Volume validation failed: %d\n", rc); - goto ubigen_create_err; - } + if (write(out, outbuf, ui->peb_size) != ui->peb_size) + return sys_errmsg("cannot write %d bytes to the output file", ui->peb_size); - dump_info(res); - *u = res; - return rc; - - ubigen_create_err: - if (res) { - if (res->v) - free(res->v); - if (res->ec) - free(res->ec); - if (res->buf) - free(res->buf); - free(res); + lnum += 1; } - *u = NULL; - return rc; -} -int -ubigen_get_leb_size(ubi_info_t u, size_t* size) -{ - if (u == NULL) - return -EINVAL; - - *size = u->leb_size; return 0; } - -int -ubigen_get_leb_total(ubi_info_t u, size_t* total) -{ - if (u == NULL) - return -EINVAL; - - *total = u->leb_total; - return 0; -} - -int -ubigen_set_lvol_rec(ubi_info_t u, size_t reserved_bytes, - const char* vol_name, struct ubi_vtbl_record *lvol_rec) +/** + * ubigen_write_layout_vol - write UBI layout volume + * @ui: libubigen information + * @peb1: physical eraseblock number to write the first volume table copy + * @peb2: physical eraseblock number to write the second volume table copy + * @ec1: erase counter value for @peb1 + * @ec2: erase counter value for @peb1 + * @vtbl: volume table + * @fd: output file descriptor seeked to the proper position + * + * This function creates the UBI layout volume which contains 2 copies of the + * volume table. Returns zero in case of success and %-1 in case of failure. + */ +int ubigen_write_layout_vol(const struct ubigen_info *ui, int peb1, int peb2, + long long ec1, long long ec2, + struct ubi_vtbl_record *vtbl, int fd) { - uint32_t crc; - - if ((u == NULL) || (vol_name == NULL)) - return -EINVAL; - - memset(lvol_rec, 0x0, UBI_VTBL_RECORD_SIZE); - - lvol_rec->reserved_pebs = - cpu_to_be32(byte_to_blk(reserved_bytes, u->leb_size)); - lvol_rec->alignment = cpu_to_be32(u->alignment); - lvol_rec->data_pad = u->v->data_pad; - lvol_rec->vol_type = u->v->vol_type; - - lvol_rec->name_len = - cpu_to_be16((uint16_t)strlen((const char*)vol_name)); - - memcpy(lvol_rec->name, vol_name, UBI_VOL_NAME_MAX + 1); - - crc = clc_crc32(crc32_table, UBI_CRC32_INIT, - lvol_rec, UBI_VTBL_RECORD_SIZE_CRC); - lvol_rec->crc = cpu_to_be32(crc); + int ret; + struct ubigen_vol_info vi; + char outbuf[ui->peb_size]; + struct ubi_vid_hdr *vid_hdr; + off_t seek; + + vi.bytes = ui->leb_size * UBI_LAYOUT_VOLUME_EBS; + vi.id = UBI_LAYOUT_VOLUME_ID; + vi.alignment = UBI_LAYOUT_VOLUME_ALIGN; + vi.data_pad = ui->leb_size % UBI_LAYOUT_VOLUME_ALIGN; + vi.usable_leb_size = ui->leb_size - vi.data_pad; + vi.data_pad = ui->leb_size - vi.usable_leb_size; + vi.type = UBI_LAYOUT_VOLUME_TYPE; + vi.name = UBI_LAYOUT_VOLUME_NAME; + vi.name_len = strlen(UBI_LAYOUT_VOLUME_NAME); + vi.compat = UBI_LAYOUT_VOLUME_COMPAT; + + memset(outbuf, 0xFF, ui->data_offs); + vid_hdr = (struct ubi_vid_hdr *)(&outbuf[ui->vid_hdr_offs]); + memcpy(outbuf + ui->data_offs, vtbl, ui->vtbl_size); + memset(outbuf + ui->data_offs + ui->vtbl_size, 0xFF, + ui->peb_size - ui->data_offs - ui->vtbl_size); + + seek = peb1 * ui->peb_size; + if (lseek(fd, seek, SEEK_SET) != seek) + return sys_errmsg("cannot seek output file"); + ubigen_init_ec_hdr(ui, (struct ubi_ec_hdr *)outbuf, ec1); + init_vid_hdr(ui, &vi, vid_hdr, 0, NULL, 0); + ret = write(fd, outbuf, ui->peb_size); + if (ret != ui->peb_size) + return sys_errmsg("cannot write %d bytes", ui->peb_size); + + seek = peb2 * ui->peb_size; + if (lseek(fd, seek, SEEK_SET) != seek) + return sys_errmsg("cannot seek output file"); + ubigen_init_ec_hdr(ui, (struct ubi_ec_hdr *)outbuf, ec2); + init_vid_hdr(ui, &vi, vid_hdr, 1, NULL, 0); + ret = write(fd, outbuf, ui->peb_size); + if (ret != ui->peb_size) + return sys_errmsg("cannot write %d bytes", ui->peb_size); return 0; } diff --git a/ubi-utils/new-utils/src/ubiattach.c b/ubi-utils/src/ubiattach.c index 1f72620..1f72620 100644 --- a/ubi-utils/new-utils/src/ubiattach.c +++ b/ubi-utils/src/ubiattach.c diff --git a/ubi-utils/new-utils/src/ubicrc32.c b/ubi-utils/src/ubicrc32.c index d39af10..d39af10 100644 --- a/ubi-utils/new-utils/src/ubicrc32.c +++ b/ubi-utils/src/ubicrc32.c diff --git a/ubi-utils/new-utils/src/ubidetach.c b/ubi-utils/src/ubidetach.c index 50670d0..50670d0 100644 --- a/ubi-utils/new-utils/src/ubidetach.c +++ b/ubi-utils/src/ubidetach.c diff --git a/ubi-utils/new-utils/src/ubiformat.c b/ubi-utils/src/ubiformat.c index 0074c7a..0074c7a 100644 --- a/ubi-utils/new-utils/src/ubiformat.c +++ b/ubi-utils/src/ubiformat.c diff --git a/ubi-utils/new-utils/src/ubimkvol.c b/ubi-utils/src/ubimkvol.c index 820c9d8..820c9d8 100644 --- a/ubi-utils/new-utils/src/ubimkvol.c +++ b/ubi-utils/src/ubimkvol.c diff --git a/ubi-utils/new-utils/src/ubinfo.c b/ubi-utils/src/ubinfo.c index 536ec01..536ec01 100644 --- a/ubi-utils/new-utils/src/ubinfo.c +++ b/ubi-utils/src/ubinfo.c diff --git a/ubi-utils/new-utils/src/ubinize.c b/ubi-utils/src/ubinize.c index 0762aa8..0762aa8 100644 --- a/ubi-utils/new-utils/src/ubinize.c +++ b/ubi-utils/src/ubinize.c diff --git a/ubi-utils/new-utils/src/ubirename.c b/ubi-utils/src/ubirename.c index 8f33718..8f33718 100644 --- a/ubi-utils/new-utils/src/ubirename.c +++ b/ubi-utils/src/ubirename.c diff --git a/ubi-utils/new-utils/src/ubirmvol.c b/ubi-utils/src/ubirmvol.c index a4cf1df..a4cf1df 100644 --- a/ubi-utils/new-utils/src/ubirmvol.c +++ b/ubi-utils/src/ubirmvol.c diff --git a/ubi-utils/new-utils/src/ubiupdatevol.c b/ubi-utils/src/ubiupdatevol.c index c83731c..c83731c 100644 --- a/ubi-utils/new-utils/src/ubiupdatevol.c +++ b/ubi-utils/src/ubiupdatevol.c |