aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore4
-rw-r--r--CHANGELOG.md997
-rw-r--r--Makefile.am39
-rw-r--r--README.txt142
-rw-r--r--configure.ac377
-rw-r--r--include/common.h3
-rw-r--r--include/libmissing.h2
-rw-r--r--include/libmtd.h28
-rw-r--r--include/libubi.h5
-rw-r--r--include/mtd/mtd-abi.h2
-rw-r--r--include/mtd/ubi-user.h10
-rw-r--r--jffsX-utils/Makemodule.am40
-rw-r--r--jffsX-utils/compr.c8
-rw-r--r--jffsX-utils/compr.h6
-rw-r--r--jffsX-utils/compr_lzo.c15
-rw-r--r--jffsX-utils/jffs2dump.c6
-rw-r--r--jffsX-utils/jffs2reader.c12
-rw-r--r--jffsX-utils/mkfs.jffs2.14
-rw-r--r--jffsX-utils/mkfs.jffs2.c15
-rw-r--r--lib/Makemodule.am30
-rw-r--r--lib/common.c46
-rw-r--r--lib/libmtd.c99
-rw-r--r--lib/libmtd_int.h1
-rw-r--r--lib/libmtd_legacy.c38
-rw-r--r--lib/libubi.c2
-rw-r--r--m4/ac_define_dir.m435
-rw-r--r--m4/ax_pthread.m4256
-rw-r--r--misc-utils/Makemodule.am48
-rw-r--r--misc-utils/fectest.c4
-rw-r--r--misc-utils/flash_erase.c130
-rw-r--r--misc-utils/flash_otp_dump.c2
-rw-r--r--misc-utils/flash_otp_erase.c64
-rw-r--r--misc-utils/flash_unlock.c9
-rw-r--r--misc-utils/flashcp.c367
-rw-r--r--misc-utils/lsmtd.82
-rw-r--r--misc-utils/lsmtd.c6
-rw-r--r--misc-utils/lsmtd_scan.c2
-rw-r--r--misc-utils/mtd_debug.c7
-rw-r--r--misc-utils/mtdpart.c9
-rw-r--r--nand-utils/Makemodule.am18
-rw-r--r--nand-utils/nanddump.c2
-rw-r--r--nand-utils/nandflipbits.c326
-rw-r--r--nand-utils/nandtest.c49
-rw-r--r--nand-utils/nandwrite.c13
-rw-r--r--nor-utils/Makemodule.am7
-rw-r--r--nor-utils/rfddump.c4
-rw-r--r--tests/checkfs/Makemodule.am18
-rw-r--r--tests/fs-tests/Makemodule.am42
-rwxr-xr-xtests/fs-tests/fs_help_all.sh.in6
-rwxr-xr-xtests/fs-tests/fs_run_all.sh.in6
-rw-r--r--tests/fs-tests/lib/tests.c1
-rwxr-xr-xtests/fs-tests/stress/fs_stress00.sh.in6
-rwxr-xr-xtests/fs-tests/stress/fs_stress01.sh.in6
-rw-r--r--tests/jittertest/Makemodule.am19
-rw-r--r--tests/mtd-tests/Makemodule.am13
-rw-r--r--tests/mtd-tests/flash_readtest.c12
-rw-r--r--tests/mtd-tests/flash_speed.c177
-rw-r--r--tests/mtd-tests/flash_stress.c12
-rw-r--r--tests/mtd-tests/flash_torture.c10
-rw-r--r--tests/ubi-tests/Makemodule.am27
-rwxr-xr-xtests/ubi-tests/runubitests.sh.in6
-rwxr-xr-xtests/ubi-tests/ubi-stress-test.sh.in6
-rw-r--r--tests/unittests/Makemodule.am10
-rw-r--r--ubi-utils/Makemodule.am21
-rw-r--r--ubi-utils/mtdinfo.c16
-rw-r--r--ubi-utils/ubiattach.c25
-rw-r--r--ubi-utils/ubinfo.c10
-rw-r--r--ubi-utils/ubinize.c2
-rw-r--r--ubi-utils/ubiscan.c318
-rw-r--r--ubifs-utils/Makemodule.am26
-rw-r--r--ubifs-utils/mkfs.ubifs/compr.c39
-rw-r--r--ubifs-utils/mkfs.ubifs/fscrypt.h4
-rw-r--r--ubifs-utils/mkfs.ubifs/mkfs.ubifs.c71
-rw-r--r--ubifs-utils/mkfs.ubifs/sign.c3
-rwxr-xr-xubifs-utils/mount.ubifs101
75 files changed, 3427 insertions, 877 deletions
diff --git a/.gitignore b/.gitignore
index 488b35c..8c51ee5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -20,9 +20,11 @@
#
doc_loadbios
docfdisk
+fectest
flash_erase
flash_lock
flash_otp_dump
+flash_otp_erase
flash_otp_info
flash_otp_lock
flash_otp_write
@@ -84,6 +86,7 @@ flash_stress
flash_speed
flash_readtest
nandbiterrs
+nandflipbits
nandpagetest
nandsubpagetest
ubiattach
@@ -97,6 +100,7 @@ ubinize
ubirename
ubirmvol
ubirsvol
+ubiscan
ubiupdatevol
volrefcnt
mtdlib_test
diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
index 0000000..b69ea3b
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,997 @@
+# Changelog
+
+All notable changes to this project will be documented in this file.
+
+The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
+
+## [2.2.0] - 2024-03-29
+### Added
+ - flashcp: Add write last option
+ - flash_erase: Add an option for JFFS2 cleanmarker size
+ - ubiattach: Add disable fastmap option
+ - ubiattach: Add option to reserve peb pool for fastmap
+ - support building without zlib
+ - CHANGELOG & README files
+
+### Fixed
+ - jffs2dump: check return value of lseek
+ - mkfs.ubifs: fix xattr scanning for builds with selinux support
+
+### Changed
+ - overhaul dependency handling in the build system
+
+## [2.1.6] - 2023-08-30
+### Added
+ - flash_speed: Measure read while write latency
+ - Support `mtd:<num>` syntax for several tools
+
+### Fixed
+ - flashcp: check for lseek errors
+ - flashcp: fix buffer overflow
+ - flashcp: verify data in `--partition`
+ - flashcp: abort on `--partition` and `--erase-all`
+ - flashcp: correct casting for percent display
+ - mtdpart: document partition of size 0
+ - mkfs.ubifs: Non-terminated string related failure with option selinux
+ - nandtest: handle nand devices larger than 4G
+ - Fix printf format specifiers for 64 bit integer types
+
+### Changed
+ - flashcp: merge duplicate write code paths
+ - flashcp: merge duplicate MEMERASE code paths
+ - flashcp: simplify logging
+
+## [2.1.5] - 2022-10-07
+### Fixed
+ - mkfs.jffs2: spelling of `--compression-mode` parameter in help text
+ - ubinfo: `--vol_id` return code for absent volume id
+ - nandflipbits: fix corrupted oob
+ - libmtd: do not ignore non-zero eraseblock size when `MTD_NO_ERASE` is set
+ - jffs2reader: warning about unaligned pointer
+ - tests: Remove unused linux/fs.h header from includes
+ - fix test bashism
+ - nanddump: fix writing big images on 32bit machines
+ - nor-utils: fix memory leak
+
+### Changed
+ - flash_otp_dump: make offset optional
+ - nandwrite: warn about writing 0xff blocks
+
+## [2.1.4] - 2022-10-07
+### Added
+ - ubiscan debugging and statistics utility
+
+### Fixed
+ - Some mtd-tests erroneously using sub-pages instead of the full page size
+ - Buffer overrun in fectest
+ - Build failures due to missing jffs2 kernel header
+
+## [2.1.3] - 2021-07-25
+### Added
+ - flashcp: Add new function that copy only different blocks
+ - flash_erase: Add flash erase chip
+ - Add flash_otp_erase
+ - Add an ubifs mount helper
+ - Add nandflipbits tool
+
+### Fixed
+ - mkfs.ubifs: Fix runtime assertions when running without crypto
+ - Use AC_SYS_LARGEFILE
+ - Fix test binary installation
+ - libmtd: avoid divide by zero
+ - ubihealthd: fix UBIFS build dependency
+ - mkfs.ubifs: remove `OPENSSL_no_config()`
+ - misc-utils: Add fectest to build system
+ - mkfs.ubifs: Fix build with SELinux
+ - Fix typos found by Debian's lintian tool
+ - Fix jffs2 build if zlib or lzo headers are not in default paths
+
+## [2.1.2] - 2020-07-13
+### Added
+ - flashcp: Add option `-A`, `--erase-all`
+ - mtd-utils: add optional offset parameter to `flash_otp_dump`
+ - ubi-utils: Implement a ubihealthd
+ - mkfs.ubifs: Add authentication support
+
+### Fixed
+ - mtd-utils: Fix return value of ubiformat
+ - ubiupdatevol: Prevent null pointer dereference
+ - libubigen: remove unnecessary include
+ - libubi: remove private kernel header from includes
+ - mkfs.ubifs: fscrypt: bail from encrypt_block if gen_essiv_salt fails
+ - mkfs.ubifs: abort add_directory if readdir fails
+ - mkfs.ubifs: close file descriptor in add_file error path
+ - mkfs.ubifs: don't leak copied command line arguments
+ - mkfs.ubifs: free derived fscrypt context in add_directory error paths
+ - mkfs.ubifs: don't leak hastable iterators
+ - mkfs.ubifs: don't leak temporary buffers
+ - mkfs.ubifs: propperly cleanup in ALL interpret_table_entry error paths
+ - mkfs.jffs2: don't leak temporary buffer if readlink fails
+ - libmtd: don't leak temporary buffers
+ - ftl_check: don't leak temporary buffers
+ - ftl_format: don't leak temporary buffers
+ - ubiformat: don't leak file descriptors
+ - nanddump: don't leak copied command line arguments
+ - mtd_debug: cleanup error handling in flash_to_file
+ - jittertest: fix error check for open system call
+ - fs-tests: don't leak temporary buffers
+ - mtd-utils: Fix printf format specifiers with the wrong type
+ - mtd-utils: Fix potential negative arguments passed to close(2)
+ - mtd-utils: Fix various TOCTOU issues
+ - mtd-utils: Fix some simple cases of uninitialized value reads
+ - mtd-utils: Fix wrong argument to sizeof in nanddump
+ - mtd-utils: Fix "are we really at EOF" test logic in libubi read_data
+ - mtd-utils: Fix potentially unterminated strings
+ - mtd-utils: Add checks to code that copies strings into fixed sized buffers
+ - mkfs.ubifs: fix broken build if fscrtyp is disabled
+
+### Changed
+ - ubifs-media: Update to Linux-5.3-rc3
+
+## [2.1.1] - 2019-07-21
+### Added
+ - mkfs.ubifs: Add ZSTD compression
+
+### Fixed
+ - ubiformat: Dont ignore sequence number CLI option
+ - mkfs.ubifs: fix build without openssl
+ - mkfs.ubifs: fix regression when trying to store device special files
+ - mkfs.ubifs: fix description of favor_lzo
+ - unittests/test_lib: Include proper header for `_IOC_SIZE`
+ - unittests/libmtd_test: Include fcntl header
+ - unittests: Define the use of `_GNU_SOURCE`
+ - ubinize: Exit with non-zero exit code on error.
+ - mtd-tests: nandbiterrs: Fix issue that just insert error at bit 7
+ - ubi-tests: ubi_mkvol_request: Fully initialize `struct ubi_mkvol_request req`
+ - ubi-tests: io_read: Filter invalid offset before `lseek` in `io_read` test
+ - ubi-tests: mkvol test: Checks return value `ENOSPC` for `ubi_mkvol`
+ - ubi-tests: fm_param: Replace `fm_auto` with `fm_autoconvert`
+
+## [2.1.0] - 2019-03-19
+### Added
+ - mkfs.ubifs: Implement support for file system encryption
+ - mkfs.ubifs: Implement selinux labelling support
+ - ubinize: add support for skipping CRC check of a static volume when opening
+ - ubimkvol: add support for skipping CRC check of a static volume when opening
+ - Add lsmtd program
+
+### Fixed
+ - update various kernel headers
+ - Instead of doing preprocessor magic, just output off_t as long long
+ - fix verification percent display in flashcp
+ - mkfs.ubifs: fix double free
+ - mkfs.ubifs: Fix xattr nlink value
+ - ubinize: avoid to create two `UBI_LAYOUT_VOLUME_ID` volume
+ - common.h: fix prompt function
+ - libmtd: don't print an error message for devices without ecc support
+ - io_paral: Fix error handling of update_volume()
+ - ubimkvol: Initialize req to zero to make sure no flags are set by default
+ - libubi: add volume flags to `ubi_mkvol_request`
+ - mkfs.ubifs: add_xattr is not depending on host XATTR support
+ - Revert "Return correct error number in ubi_get_vol_info1" which
+ introduced a regression.
+ - make sure pkg-config is installed in configure script
+ - ubiformat: process command line arguments before handling file arguments
+
+### Changed
+ - ubiformat: remove no-volume-table option
+
+## [2.0.2] - 2018-04-16
+### Added
+ - libmtd: Add support to access OOB available size
+ - mkfs.ubifs: Allow root entry in device table
+
+### Fixed
+ - Fix unit-test header and file paths for out of tree builds
+ - Fix unit test mockup for oobavail sysfs file
+ - misc-utils: flash_erase: Fix Jffs2 type flash erase problem
+ - libmtd_legacy: Fix some function description mismatches
+ - mtd-utils: ubifs: fix typo in without_lzo definition
+ - mtd: tests: check erase block count in page test
+ - mtd: unittests: Stop testing stat() calls
+ - mtd: unittests: Decode arg size from ioctl request
+ - mtd: unittests: Use proper unsigned long type for ioctl requests
+ - mtd: tests: Fix check on ebcnt in nandpagetest
+ - ubi-utils: ubicrc32: process command line arguments first
+ - nandbiterrs: Fix erroneous counter increment in for loop body
+ - jittertest: Use the appropriate versions of abs()
+ - Mark or fix switch cases that fall through
+ - mkfs.ubifs: ignore EOPNOTSUPP when listing extended attributes
+ - misc-utils: initialize "ip" in docfdisk to NULL
+ - mkfs.ubifs: Apply squash-uids to the root node
+
+### Changed
+ - ubi-utils: ubiformat.c: convert to integer arithmetic
+ - mtd-utils: common.c: convert to integer arithmetic
+ - Run unit test programs through "make check"
+ - Enable more compiler warning flags, fix warnings
+ - Add no-return attribute to usage() style functions
+ - Remove self-assignments of unused paramters
+ - tests: checkfs: Remove unused source file from makefiles
+ - ubi-tests: io_update: fix missleading indentation
+ - Add ctags files to .gitignore
+ - libscan: fix a comment typo in libscan.h
+ - libmtd: fix a comment typo in dev_node2num
+
+## [2.0.1] - 2017-08-24
+### Added
+ - nandbiterrs: Add Erased Pages Bit Flip Test
+ - mkfs.ubifs: Add support for symlinks in device table
+ - nanddump: Add `--skip-bad-blocks-to-start` option
+ - nandwrite: Add `--skip-bad-blocks-to-start` option
+
+### Fixed
+ - common: Always terminate with failure status if command line options
+ are unknown or missing
+ - common: Fix format specifier definitions for `off_t` and `loff_t`
+ - common: More consistent exit codes
+ - libmtd: Fix error status if MTD is not present on the system
+ - libubi: Add klibc specific fixes for `ioctl`
+ - libubi: Fix error status in `ubi_get_vol_info1` for non-existing volumes
+ - misc-utils: Support jffs2 flash-erase for large OOB (>32b)
+ - mkfs.jffs2: Add missing header inclusions required for build with musl
+ - mkfs.ubifs: Fix alignment trap triggered by NEON instructions
+ - mkfs.ubifs: Fix uuid.h path
+ - mkfs.ubifs: Replace broken ubifs_assert with libc assert
+ - nandbiterrs: Actually get the new ECC bit flip count before comparing stats
+ - nandpagetest: Improved argument sanity checking
+ - nandwrite: Fix bad block skipping
+ - nandwrite: Improved argument sanity checking
+ - ubinfo: Improved argument sanity checking
+ - ubi-tests: Replace variable-length array with `malloc`
+ - ubi-tests: Support up to 64k NAND page size
+
+### Changed
+ - build-system: Enable compiler warnings
+ - build-system: Restructure autoconf dependency checking
+ - common: Add const modifier to read only strings and string constants
+ - common: Eliminate warnings about missing prototypes
+ - common: Get rid of rpmatch usage
+ - common: Remove README.udev from ubi-tests extra dist
+ - common: Remove unused variables and functions
+ - common: Silence warnings about unused arguments
+ - flashcp: Drop custom defines for `EXIT_FAILURE` and `EXIT_SUCCESS`
+ - libiniparser: remove unused function needing float
+ - libmissing: Use autoconf header detection directly
+ - libubi: Remove `UDEV_SETTLE_HACK`
+ - misc-utils: Move libfec to common public header & library directory
+ - nandwrite: replace erase loop with mtd_erase_multi
+ - serve_image: Use PRIdoff_t as format specifier.
+ - ubi-tests: Speedup io_paral by using rand_r()
+ - ubirename: Fix spelling
+
+## [2.0.0] - 2016-12-22
+### Added
+ - libmissing with stubs for functions not present in libraries like musl
+ - unittests for libmtd and libubi
+ - port most kernel space mtd test modules to userspace
+ - mkfs.ubifs: extended attribute support
+ - ubinize: Move lengthy help text to a man page
+ - nandwrite: Add skip-all-ff-pages option
+ - flash_{un,}lock: support for MEMISLOCKED
+ - nandtest: support hex/dec/oct for `--offset` and `--length`
+
+### Fixed
+ - common: Fix 'unchecked return code' warnings
+ - common: Fix PRI{x,d}off definitions for x86_64 platform
+ - common: include sys/sysmacros.h for major/minor/makedev
+ - common: fix wrong format specifiers on mips32
+ - libmtd: Fix uninitialized buffers
+ - libmtd: Eliminate warnings about implicit non-const casting
+ - libmtd: Fix return status in mtd_torture test function
+ - libmtd: mtd_read: Take the buffer offset into account when reading
+ - mkfs.ubifs: use gid from table instead 2x uid
+ - mkfs.ubifs: fix compiler warning for WITHOUT_LZO
+ - mkfs.ubifs: fix build when WITHOUT_LZO is set
+ - mkfs.ubifs: correct the size of nnode in memset
+ - mkfs.jffs2: initialize lzo decompression buffer size
+ - mkfs.jffs2: Fix scanf() formatstring for modern C version
+ - nanddump: check write function result for errors
+ - nanddump: write requested length only
+ - flash_{un,}lock: don't allow "last byte + 1"
+ - flash_{un,}lock: improve strtol() error handling
+ - ubinize: Always return error code (at least -1) in case of an error
+ - recv_image: fix build warnings w/newer glibc & _BSD_SOURCE
+ - serve_image: use proper POSIX_C_SOURCE value
+ - flashcp: Use %llu to print filestat.st_size
+ - mtd_debug: check amount of data read.
+ - fs-tests: integrity: don't include header <bits/stdio_lim.h>
+ - tests: Fix endian issue with CRC generation algorithm
+ - make_a_release.sh: fix MTD spelling
+ - Fix packaging of unit test files
+ - Correct casting for final status report in flashcp
+
+### Changed
+ - autotools based build system
+ - complete restructuring of the source tree
+ - cleanup of some utilities
+ - removal of some very old, unused or duplicated files from the source tree
+ - libmtd: removal of very old, completely unused and broken functions
+ - nandwrite: Factor out buffer checking code
+
+## [1.5.2] - 2015-07-24
+### Added
+ - mtdpart utility to add/delete partition
+ - jffs2dump: XATTR and XREF support for content dump & endianess conversion
+
+### Fixed
+ - ubifs-media.h: include "byteorder.h"
+ - ubiformat: fix the subpage size hint on the error path
+ - include/common.h: fix build against current uClibc
+ - include/common.h: fix build against recent 0.9.33 uClibc
+ - libmtd: fix comment typo
+ - mkfs.ubifs: Fix build with gcc 5.1
+ - libmtd: don't ignore "region index" parameter in `mtd_regioninfo()`
+ - .gitignore: add new mtdpart utility
+ - ubi-tests: fix a some overflows
+ - formating issues (trailing whitespaces, space-before-tab, blank line at EOF)
+ - fs-tests: pass `TEST_DIR` to integck in run_all.sh
+ - nandtest: fix `--reads` argument
+ - libmtd: fix `mtd_dev_present` return value on legacy systems
+ - libfec: use standard C type instead of `u_long`
+ - serve_image: do not include error.h
+ - recv_image: do not include error.h
+ - include/common.h: fix build against musl
+ - integck: Use `$(CC)` and `$(AR)` instead of `gcc` and `ar` consistently
+
+### Changed
+ - mkfs.ubifs: start using common code, move some macros to common header
+ - Move mkfs.ubifs/ubifs-media.h to include/mtd
+ - make_a_release.sh: suggest announcement e-mail
+ - nandtest: Remove redundant check
+ - nandtest: Move the "read and compare" code to a function
+ - nandtest: Introduce multiple reads & check iterations
+
+## [1.5.1] - 2014-04-07
+### Added
+ - tests: ubi: add stress-test.sh
+ - ubi-utils: Add ubiblock tool
+ - flash_erase, flash_otp_write: check the nand type
+ - ubiupdatevol: add a `--skip` option
+ - nandwrite: add `--input-{skip,size}` options
+ - mkfs.ubifs: allow reformatting of devices
+ - new prompt() helper for talking to the user
+
+### Fixed
+ - Makefile: add LDFLAGS_mkfs.ubifs, fix libuuid issue
+ - runtests.sh: print more consistent messages
+ - integck: fix identation
+ - nandwrite: apply corrent version of `--input-*` patch series
+ - ubi-tests: argument number mismatch for `ubi_leb_change_start`
+ - ubi-tests: fix pthreads linking
+ - ubiformat: correct "non-ubifs" warning message
+ - mkfs.ubifs: correct and improve LEB size error prints
+ - ubi-utils: Fix file descriptor leaks in libubi
+ - integck.c: Fix buffer overflow in save_file
+ - integck.c: Only verify the operation after datastructures have been updated
+ - mkfs.ubifs: Improve error handling of is_contained()
+ - nandwrite: clean up length types
+ - nand{dump, test, write}: clean up `--help` handling
+ - fix build errors w/newer kernel headers & glibc
+ - ubinize: fix usage text
+ - consistency between `u_int32_t` / `off_t` / `off64_t`
+ - tests: io_update correct lseek parameters order
+ - ubiformat: fix failure on big partitions (>4Gio)
+ - Check mtdoffset is not larger than mtd.size in case of a bad block.
+ - flash_otp_write: fix writing to NAND in presence of partial reads
+ - flash_otp_write: fix a buffer overflow on NAND with write size > 2048
+ - ubiformat: really skip some messages when quiet
+ - ubiformat: fix error path
+
+### Changed
+ - nandwrite: minor cleanups
+ - tests: ubi: clean-up the runtests.sh script
+ - libubi: Remove `ubi_attach_mtd`
+ - load_nandsim.sh: switch to sh, remove bashisms, cleanup code
+ - load_nandsim.sh: introduce a usage function
+ - load_nandsim.sh: intruduce fatal function
+ - load_nandsim.sh: use dochere for help output
+ - mkfs.ubifs: rewrite path checking
+ - ubi-tests: switch to using common.h from the top level
+ - ubi-tests: rename common.[ch] to helpers.[ch]
+ - integck.c: immediately dump the buffer containing the errors
+ - use xstrdup in a few more places
+ - move `_GNU_SOURCE` to the main makefile
+ - ftl_check/ftl_format/nftldump: use existing mtd_swab.h header
+ - flash_erase: use `pwrite()` rather than `lseek()` and `write()`
+ - UBI: sync ubi-user.h with kernel v3.6-rc1
+ - introduce `PRIxoff_t` and `PRIdoff_t` printf helpers
+ - ubiattach: use `max_beb_per1024` in `UBI_IOCATT` ioctl
+ - ubiattach: fail if kernel ignores max_beb_per1024
+ - libubi: factorize `ubi_attach` and `ubi_attach_mtd` code
+ - Makefile: Build and install `flash_otp_lock`, `flash_otp_write`
+ - ubiformat: clean up synopsis of command-line parameters
+
+## [1.5.0] - 2012-05-07
+### Added
+ - limbtd: implement `mtd_dev_present` for older kernels
+ - libubi: make `ubi_dev_present()` a library function
+ - libmtd: add `mtd_dev_present()` library function
+
+### Fixed
+ - mkfs.ubifs: do not ignore `--max-leb-cnt` when formatting an UBI volume
+ - ubinfo: fix `--all` for non-consecutive device numbers
+ - mtdinfo: fix `--all` for non-consecutive device numbers
+ - libmtd: fix segmentation fault on lib->mtd
+ - mtdinfo: correct grammar on error message
+ - libmtd: fix `mtd_write()` issues for large data-only writes
+ - libmtd: check if the device is present before accessing it
+ - libmtd_legacy: don't open device in R/W
+ - Makefile: fix "make clean" for old GNU find
+ - libmtd: Variable name same as function name causing compile to fail (Android)
+
+### Changed
+ - make_a_release.sh: remind about pushing the master branch
+ - docfsdisk: minor cosmetic cleanup
+ - mkfs.jffs2: improve documentation of `--pagesize` parameter
+
+## [1.4.9] - 2011-12-17
+### Added
+ - Add a script to make releases
+ - nandtest: add seed argument
+
+### Fixed
+ - nandtest: seed random generator with time
+ - libmtd: allow write operations when MEMWRITE is not supported
+ - nandtest: set oldstats.failed
+ - Makefile: fix install target with out-of-tree builds
+
+### Changed
+ - Makefile: separate man page install and compression steps
+
+## [1.4.8] - 2011-11-19
+### Fixed
+ - Makefile: Version number accedientally left at 1.4.6 in last release
+
+## [1.4.7] - 2011-11-18
+### Added
+ - libmtd: support MEMWRITE ioctl
+
+### Fixed
+ - jffs2reader: get rid of linker error
+ - jffs2reader: eliminate compiler errors
+ - ubiformat: handle write errors correctly
+ - mtd-utils: add jffs2reader to .gitignore
+
+### Changed
+ - jffs2reader: use major() and minor() helpers
+ - jffs2reader: print ctime only by user's request
+ - jffs2reader: use const char * for path variables
+ - jffs2reader: introduce ADD_BYTES macro
+ - jffs2reader: update the header inclusion block
+ - nandtest: print number of bits corrected during test
+ - mkfs.ubifs/ubinize: increase PEB size limit to 2MiB
+ - mtdinfo: provide info when used without arguments
+ - nandwrite: use common.h "errmsg" functions
+ - nandwrite: re-implement `--autoplace` option
+ - move OOB auto-layout into libmtd's mtd_write
+ - nandwrite: merge `mtd_write_oob` and `mtd_write` calls
+ - libmtd: modify `mtd_write` to cover OOB writes
+ - update mtd-abi.h
+ - nandwrite: consolidate buffer usage
+ - nanddump: kill usages of MEMSETOOBSEL ioctl
+ - nandwrite: refactor "old_oobinfo" code
+ - nandwrite: cleanup "oobinfochanged" leftovers
+ - nandwrite: remove C99 comment style
+ - use `__func__` instead of `__FUNCTION__`
+ - mtd_debug: replace #defines with enum
+ - mtd_debug: fixup style
+
+### Removed
+ - tests: checkfs: remove unused code
+ - nandwrite: kill `--raw` option
+ - nandwrite: kill -j, -y, and -f options
+ - nandwrite: remove `autoplace` features
+
+## [1.4.6] - 2011-08-20
+### Fixed
+ - mkfs.ubifs: fix a gcc warning
+ - integck: fix build error (MS_DIRSYNC, MS_RELATIME)
+ - mtd-tests: checkfs: fix size_t related warning
+ - mtd-tests: io_paral: build error, "variable length strings"
+ - flash_erase: fix incorrect help message
+ - Makefile: fix "version.h" build for cross-compiling
+ - Makefile: fix "make clean" for cross-compile
+ - mtdinfo: don't open NULL pointer when getting region_info with `-a'
+ - mtdinfo: refactor code to remove "args.all" dependency
+ - mtdinfo: fixup "example usage" help section
+ - nandwrite: invalid erase after page write failure
+
+### Changed
+ - nanddump: change default to `--bb=skipbad`
+ - nanddump: change `-o` to mean `--oob`, not `--omitoob`
+ - nanddump: default to NOT dumping OOB data
+ - mkfs.ubifs: use common.h
+ - switch more utils to unified versioning
+ - add common version printing function
+ - mtdinfo: restructure help message
+ - mtdinfo: consolidate help as display_help()
+ - rewrite build system to avoid recursion
+ - autogenerate version.h from build system
+
+### Removed
+ - mtdinfo: remove -m leftovers
+ - mkfs.ubifs: remove root inode squash feature
+ - nanddump: kill `--omitbad`, `--noskipbad`
+ - kill flash_info
+ - mtdinfo: kill `-m` option
+ - build: remove old SYMLINKS variable
+
+## [1.4.5] - 2011-07-25
+### Added
+ - Makefile: introduce new target tests in Makefile
+ - Makefile: introduce cscope target
+ - nanddump: add `--oob` option
+ - nanddump: add `--bb=METHOD` option
+ - mkfs.ubifs: add `-F` option for `free-space fixup`
+ - libmtd: add helper funcs for getting regioninfo and locked info
+ - mtdinfo: add regioninfo/eraseblock map display
+ - flash_info: allow people to get info on multiple devices
+
+### Fixed
+ - serve_image: adjust classifier and type for printf
+ - libmtd: use PRIu64 classifier for uint64_t printf arguments
+ - mkfs.jffs2: fix casting of __off64_t
+ - tests: ubi-tests: clean libubi.a and *.o
+ - tests: fs-tests: ssize_t return type in read() wrapper
+ - mkfs.jffs2: fix casting of printf argument
+ - tests: jittertest: fix set of compiler warnings
+ - tests: ubi-tests: seed_random_generator() was used w/o prototype
+ - tests: fs-tests: check return value of functions
+ - tests: checkfs: fix linker warnings
+ - tests: checkfs: fix compiler warnings
+ - tests: make jittertest buildable
+ - mkfs.ubifs: check output first
+ - flash_{lock, unlock}: fix off-by-one error for "entire device" length
+ - fs-tests: use independent random generators for ops and data
+ - ubi-utils: ubimkvol: fix parameters parsing regression
+
+### Changed
+ - tests: checkfs: integerate with common Makefile
+ - fs-tests: integck: major cleanup/rewrite
+ - mtdinfo: deprecate the -m option
+ - libmtd: improve mtd_islocked interface
+ - switch ubi and ubifs tools to use common strtoX funcs
+ - mtdinfo: separate out ubi information printing
+ - fs_tests: make the test-suite finish faster
+ - nanddump: document, warn about future default `--omitoob`
+ - feature-removal-schedule: describe nanddump changes
+ - nanddump: warn about new default BB handling
+ - nanddump: update help message for BB method changes
+ - nanddump: sort options in help message alphabetically by shortname
+ - jffs2: make lzo optional at build time
+ - flash_info: deprecate
+ - ubi-utils: send help/version info to stdout
+ - libmtd: use O_CLOEXEC
+ - include/mtd: sync with kernel
+ - flash_info: convert to common.h
+ - ignore (FLAT) gdb files
+ - flash_{lock,unlock}: convert to common code
+ - flash_{lock,unlock}: merge into one util
+ - flash_{lock,unlock}: merge functionality
+ - flash_lock/flash_unlock/flash_info: clean up style
+
+### Removed
+ - punt redundant libcrc32
+ - mtdinfo: remove now unused ubigen info
+
+## [1.4.4] - 2011-04-01
+### Added
+ - libmtd: fix OOB read and write interface
+
+### Fixed
+ - fs-tests: test_1: fix compilation warnings
+ - fs-tests: perf: fix compilation warning
+ - fs-tests: integck: improve re-mounting test coverage
+
+### Changed
+ - mkfs.ubifs: deprecate `squash-rino-perm` options
+ - nanddump: fail if `-s` parameter is unaligned
+
+## [1.4.3] - 2011-03-18
+### Added
+ - nandwrite: add only write oob option
+
+### Fixed
+ - common.h: simple_strtoll type
+
+### Changed
+ - flash_erase: start position should be in bytes
+
+## [1.4.2] - 2010-12-31
+### Added
+ - nandwrite: Large page+oob support
+ - nanddump/nandwrite: 64-bit support utilizing libmtd
+ - introduce xzalloc() helper
+ - add xasprintf() helper
+ - new memory wrappers
+ - new strtoX helpers
+ - new bareverbose() helper
+ - libmtd: add lock/unlock helpers
+ - nandwrite: add `--skipbad` to write bad blocks
+
+### Fixed
+ - nanddump: fix initialization of bad blocks oob data buffer
+ - nanddump: always check the first erase block
+ - flash_erase: Fix output of offsets
+ - nanddump/nandwrite: Style fixups
+ - nanddump/nandwrite: style, signed-ness, printing fixups
+ - nandwrite: type consistency
+ - nandwrite: prevent 32-bit overflow
+ - nandwrite: avoid NULL buffer pointers
+ - libmtd: fix OOB size initialization in legacy code
+ - Makefile: Use $(CURDIR) in place of $(PWD)
+ - mkfs.ubifs: Fix heap corruption on LEB overrun
+ - mkfs.ubifs: Fix --squash-rino-perm / --nosquash-rino-perm
+ - Fix make install errors
+ - libmtd: fix "fount" typo
+ - sys_errmsg: fix indentation
+ - recv_image: fix `__USE_GNU` hack
+ - ubi-utils: tweak const strings decls
+ - compr_rtime: fix unused warning
+ - libfec: fix up pointer warnings in fec magic computation
+ - mkfs.jffs2: fix devtable count as mkfs.ubifs does
+ - mkfs.jffs2: fix repeated dev nodes
+ - mkfs.ubifs: Fix typo in short options of mkfs.ubifs
+
+### Changed
+ - mkfs.ubifs: do not override root inode permissions
+ - Makefile: remove old ubi-utils
+ - Add --squash-rino-perm removal plan
+ - nanddump: warn when the start address is not page aligned
+ - nanddump: Dynamic buffer, increase pagesize/oobsize
+ - nandwrite: Use libmtd to get correct mtd parameters
+ - nandwrite: switch "oobsize" for "writesize"
+ - nandwrite: Clarify usage of aligned "erasesize"
+ - nandwrite: add check for negative blockalign
+ - nandwrite: use common.h "errmsg_die"
+ - nanddump: choose correct "printf" format-specifier
+ - nanddump: check for negative inputs
+ - nanddump: change "unsigned" to "signed"
+ - nanddump/nandwrite: use "simple_" str functions
+ - common.h: Add MAX() macro, fix MIN()
+ - nanddump: Refactor pretty print code into an sprintf()
+ - jffs2reader: convert to common.h helpers
+ - libmtd: make malloc failures fatal
+ - sumtool/libfec: convert "()" to "(void)" in func defs
+ - sumtool: convert to common.h helpers
+ - mkfs.jffs2: convert to common.h and xalloc.h helpers
+ - libmtd: unify some error messages
+ - xalloc: simplify/unify error messages
+ - enable garbage collection of unused function/data sections
+ - mkfs.jffs2: use new xasprintf() helper
+ - unify flash_erase and flash_eraseall
+ - common.h: clean up PROGRAM_NAME usage
+ - standardize PROGRAM_NAME
+ - mkfs.ubifs: use common ARRAY_SIZE
+ - punt duplicate normsg_cont define
+ - convert to common.h/min
+ - libmtd: unify erase block argument checking
+ - compr: drop unused model argument
+ - compr_zlib: mark local functions as static
+ - rbtree: avoid redefining offsetof
+
+### Removed
+ - ftl_check: drop unused verbose flag
+ - nandwrite: Remove redundant 'autoplace' check
+
+## [1.4.1] - 2010-10-19
+### Changed
+ - Hide zlib's crc32 in compr_zlib.c and mkfs.ubifs/compr.c
+
+## [1.4.0] - 2010-09-13
+### Added
+ - libmtd: add OOB read and write interfaces
+ - libmtd: support MEMERASE64
+ - lib: Add forgotten Makefile
+ - libmtd: add mtd_write_img
+ - ubi-tests: add normsg
+ - ubinfo: document the new -N option
+ - nanddump: add canonical (hex+ascii) flag
+ - nanddump: add "forcebinary" flag
+ - nanddump: add `--nobad` to read bad blocks
+ - libubi: add support to attach/detach by MTD device path
+ - ubiattach/ubidetach: add support to attach/detach by path
+ - nanddump: Support 4096+218 and 4096+224 page sizes
+ - ubinfo: add -N option to get info by name of ubi volume
+ - support 4096+64 page sizes
+
+### Fixed
+ - mkfs.jffs2: fix `--enable-compressor`
+ - lib: fix libcrc32 generation
+ - rename crc32 to mtd_crc32
+ - mkfs.ubifs: fix compilation warning
+ - mkfs.jffs2: fixed warnings
+ - nandtest: Fixed indentation
+ - fix spelling error
+ - fix compiler warnings
+ - nandwrite: fix the bug of writing a yaffs2 image to NAND
+ - nandwrite: check if the start address is page-aligned
+ - nandtest: fix `--keep` argument
+ - fix parallel build between ubi-utils and mkfs.ubifs
+ - clean up compile warnings
+ - ubi-utils: reformat help text to fit in 80 columns
+ - nanddump: Fix hexdump nybble ordering
+ - mtd_debug: fix creation mode parameter
+ - mkfs.jffs2: fix integer underflow in jffs2_rtime_compress()
+
+### Changed
+ - libs: remove ubiutils-specific stuff from common.h
+ - libs: make crc32 and fec to be libraries
+ - libscan: rename hdr to ech
+ - ubi-test: seed the random genrator in tests
+ - ubi-tests: use rand instead of random in io_paral
+ - ubi-utils: harmonize mtd device node variables
+ - ubi-utils: harmonize libmtd interface a bit
+ - ubi-tests: remove some junk from the integ test
+ - libubigen: make init_vid_hdr externally visible
+ - libubigen: move header comments
+ - libubigen: do not create huge arrays on stack
+ - ubi-tests: teach errmsg and failed return error code
+ - ubi-tests: rename err_msg to errmsg
+ - libubi: provide mtd number in UBI device information
+ - libubi: remove few fields from volume info
+ - nanddump: increase max OOB size
+ - nanddump: rename `--nobad` to `--noskipbad`
+ - build: add option to not force largefile support
+ - ubi-utils: drop -Werror in old utils
+ - flash_eraseall: tweaks to make binary size smaller
+ - mtd: change flash_eraseall to use libmtd-wrapped ioctls
+ - mtd-utils: update to latest mtd-abi.h from kernel.org
+ - move libmtd source files to lib/ subdirectory
+ - ubi-utils: provide default value for /dev/ubi_ctrl
+
+### Removed
+ - nanddump: drop unused --ignoreerrors option
+
+## [1.3.1] - 2010-01-15
+### Fixed
+ - ubiformat: always initialize seq number
+ - ubiformat: be consistent with sequence numbers
+
+## [1.3.0] - 2009-12-09
+### Added
+ - Makefile: Add Optional ZLIB and LZO CPPFLAGS and LDFLAGS
+ - Add mkfs.ubifs
+ - Add support for 4k pages
+ - ubirmvol: remove volume by name
+ - nandwrite: Support reading from standard input
+ - nanddump: Add Support for Quiet Option
+ - ubinize: allow an absent 'image' in the ubinize configuration
+ - handle non-power-of-2 erase size
+ - add ubirename utility
+ - ubiformat: mark faulty blocks as bad
+ - ubi-utils: add sysfs interface support and new tool
+ - libubi: add `ubi_set_property`, `ubi_leb_unmap` interfaces
+ - libubi: add `ubi_is_mapped()` function
+ - ubinize: add sequence number support
+ - ubiformat: add image sequence support
+ - ubi-utils: add ubirsvol tool to resize UBI volumes
+ - flash_unlock: enhancing for unlocking of specified number of blocks
+
+### Fixed
+ - ubi-tests: fix makefile
+ - ubi-tests: fix run script
+ - ubinize: validate number of sections
+ - ubinize: add more ini-file validation
+ - ubinize: fix static volumes generation
+ - fs-tests: fix symlink bug in integrity test
+ - fs-tests: fix max file name length in integrity test
+ - fs-tests: allow for symlink name too long in integrity test
+ - ubi-utils: fixed and enhanced `--flash-image` option
+ - ubimkvol: check for free LEBs
+ - ubiupdatevol: remove non-existing option from help message
+ - fs-tests: also preserve mount options when mounting again
+ - nandwrite/nanddump: Pass Real Names as Arguments to perror
+ - ubinize: correct subpage_size print and initialise vol_info to zero
+ - flash_eraseall reports incorrect percentage
+ - ubi-utils: fix CFLAGS handling wrt cross compilation
+ - Makefile: Separate '-m' and the mode with a space when invoking 'install'
+ - ubi-utils: various fixes
+ - ubiformat.c: fix printf(%d, size_t) warning
+ - ubi-utils: fix up build system
+ - nandwrite: correct data reading
+ - mkfs.jffs2: fix dir creation in /
+ - ubi-utils: fix warning in fprintf() code
+ - common.mk: tweak rules to workaround make-3.80 bugs
+ - fs-tests: fix remounting in integck
+ - ubi-utils: minor printing fix
+ - ubi-utils: fix compilation warnings
+ - ubi-tests: fix build and some warnings
+ - ubiupdatevol: fix -t parameter
+ - mkfs.jffs2: fix lzo usage on 64bit systems
+ - make sure compiler supports warning flags
+ - libmtd: fix mtd_is_bad return code
+ - libubigen: don't define large array on stack
+ - ubiformat: fix segfault and messages
+ - Prevent git-clean from removing cscope files
+ - ubinfo: handle -d correctly
+ - ubiformat: fix build error
+ - ubi-tests: make tests compile again
+ - libubigen: add missing include
+ - libubi: fix multiple memory corruptions
+ - ubi-utils: fix memory corruptions
+ - libmtd: recognize pre-MTD-sysfs kernels better
+ - nandwrite: fix loop condition
+ - nandwrite: return error if failure when reading from standard input
+ - nandwrite: fix error handling
+ - libubi: fix wrong size calculation with sizes > 4GiB
+ - ubiformat: allow zero erase counter
+ - ubi-utils: fix compilation errors when using CPPFLAGS
+ - nandwrite: fix incorrect use of errno
+ - ubiformat: fix typo in the help output
+ - ubiformat: fix `--erase-counter` handling
+ - flash_lock: fix length being passed
+ - ubiformat: check that min IO size is power of 2
+ - ubiformat: fix error message
+
+### Changed
+ - enable parallel build process
+ - ubi-utils: use 'stat(2)' instead of 'lstat(2)'
+ - ubi-utils: allow ubiformat to read from stdin
+ - ubi-utils: minor rename
+ - nandwrite/nanddump: cleanup qualifiers, exit mnemonics, booleans, usage
+ - fec.c: replace bzero, bcopy, bcmp wiuth memset, memcpy, memcmp
+ - libubi: be more verbose about errors
+ - libubi: remove some too verbose messages
+ - Unify all common build system parts
+ - ubiformat: nicify error messages
+ - libmtd: Add `_FILE_OFFSET_BITS=64`, fix `lseek` overflow
+ - update ubi-user.h, ubi-header.h, ubi-media.h
+ - Add generated binaries to gitignore
+ - ubi-utils: re-arrange directory layout
+ - ubi-utils: tweak vpath handling
+ - libmtd: move comments to headers
+ - libubi: amend included header files
+ - libubi: remove unnecessary header files
+ - libmtd: amend interface
+ - ubi-utils: rename `ubi_node_type`, `mtd_get_info`, `mtd_info`
+ - libubi: improve `libubi_open` interface, error handling
+ - libubi: do not use udevsettle
+ - libmtd: rename `allows_bb`, `rdonly`, `num` fields
+ - libmtd: make type_str to be an array
+ - ubi-tests: improve io_paral test
+ - ubiformat: torture eraseblocks on write errors
+ - ubiformat: minor printing clean-up
+ - ubiformat: nicify error output
+ - ubiformat: make badblocks output less confusing
+ - common: remove depricated KB,MB,GB support
+ - ubi-utils: update ubi-media.h
+ - ubiformat: clean up help output a little
+ - jffs2dump: rewrite `--help` output to be more suitable for `help2man`
+ - nandwrite: unified reading from standard input and from file
+
+### Removed
+ - ubi-utils: remove debugging leftovers
+ - ubi-utils: remove depricated -d option
+
+## [1.2.0] - 2008-06-27
+### Added
+ - nandwrite: add 'markbad' option
+ - Add nand integrity testing utility
+ - Add utilities for multicast send/receive of MTD images
+ - ubi-utils: add -m option to ubimkvol
+ - ubi-utils: add -S option to ubimkvol
+ - ubi-utils: Add rmvol test
+ - Add test program orph.c
+ - mkfs.jffs2.c: detect hardlinks
+ - ubi-utils: add ubinfo, ubiupdate, ubiattach, ubidetach
+ - ubi-utils: bin2nand, nand2bin support for different ecc layouts
+ - ubi-utils: ubinize, ubiformat
+ - Add libmtd, libscan
+ - libubi: support atomic LEB change ioctl
+ - mtd_debug: support new flags
+ - Add load_nandsim.sh script
+ - fs-tests: add simple performance test
+ - mkfs.jffs2: Add Support for Symlinks to Device Table
+
+### Fixed
+ - Fix repeated warning about ECC correction, in nandtest
+ - fs-tests: fix bug in simple test_2
+ - ubi-utils: Fixup oob data generation
+ - ubi-utils: various fixes in unubi
+ - ubi-utils: nand2bin had ECC calculation problems
+ - libubi: fix use of negative `errno` values
+ - libubi: fail gracefully if ubi is not supported on the current system
+ - ubi-utils: fix readdir error checking
+ - ubi-utils: fix bytes output formating
+ - libubi: fix sysfs direntries scanning
+ - ubi-utils: pddcustomize fixup update volume
+ - ubi-utils: fix warnings for gcc 4.2.3
+ - ubi-utils: ubimkvol: fix wrong variable printout
+ - Use LSB locations for manpages
+ - compr_lzo.c: allocate enough memory for lzo compressor.
+ - mkfs.jffs2.c: fix issue with crashing when using lzo compression
+ - fs-tests: preserve mount options when mounting again
+ - mkfs.jffs2: Remove Incorrect Find Optimization
+
+### Changed
+ - nandtest: Mark blocks bad on failed write; don't abort
+ - Makefile: Make optflags easier for distros to override
+ - Makefile: build ubi-utils from top dir, add to install target
+ - Improve option handling in nandtest, add markbad and offset/length options
+ - ubi-utils: rename `__unused` to `ubi_unused`
+ - ubi-utils: remove useless build information
+ - ubi-utils: Nand2bin add more information when bad blocks occur
+ - ubi-utils: migrate to new libubi
+ - ubi-utils: Update and bugfix unubi
+ - ubi-utils: Test-case for unubi
+ - ubi-utils: unubi: add physical erase block number for analysis
+ - ubi-utils: overhaul README, tests
+ - ubi-utils: move UBI tests to tests/ubi-tests/
+ - ubi-utils: move jffs2_test.sh to ubi-tests
+ - mkfs.jffs2: use separate ino field in struct filesystem_entry for jffs2 ino#
+ - mkfs.jffs2: Set mkfs.jffs2 page size runtime instead of fixed
+ - ubi-tools: major cleanups in ubimkvol, ubirmvol
+ - libubi: consistently rename `eb` to `leb`
+ - ubi-utils: cleanup ubicrc32
+ - ubi-utils: more sanity checks
+ - Move perl scripts to scritps directory
+ - tests: move checkfs test, jittertest to tests directory
+ - ubi-utils: update headers
+ - ubi-utils: CLI handling for ubigen consistent with other tools
+ - ubi-utils: scripts/mkdevs.pl: create control device node as well
+ - ubi-utils: major overhaul/rewrite for pfi2ubi
+ - ubi-tools: use uint32_t in userspace
+ - ubi-utils: use macros not hardcoded constants
+ - ubi-utils: use mtd_swab.h
+ - ubi-tools: improve printing macros
+ - ubi-tools: consistent option handling for ubimkvol, ubirmvol, ubiupdatevol
+ - ubi-utils: don't use argp.h
+ - Teach libubi_open not to prirnt error message
+ - ubi-utils: use common.h in libubi
+ - fs-tests: allow for ENOSPC in test fwrite00
+ - Makefile: respect CFLAGS/CPPFLAGS from build environment
+
+### Removed
+ - Remove mkfs.jffs utility
+ - ubi-utils: remove unused directory, testcases.txt
+
+## [1.1.0] - 2007-08-03
+### Added
+ - Add GPL license text, .gitignore file
+ - mkfs.jffs2: Add XATTR support
+ - nanddump: Add `-n` argument (no-ecc)
+ - Support for 1KB page & 32 bytes spare NAND
+ - Add feature removal schedule file
+ - Add fs-tests from Adrian Hunter
+ - Add UBI utilities
+ - Add lzo helper functions
+
+### Fixed
+ - nanddump.c: add missing `--file` long options
+ - fix handling of ioctl return value in nand-utils
+ - Correct integrity test calculations of free space
+
+### Changed
+ - nandwrite: Allow `-s` argument to accept hex and octal values
+ - Add usage message for flash_erase.c
+ - Consolidate the swab macros into one location
+ - Switch to using standard types
+ - Update mtd-abi.h from upstream kernel.
+ - Update user headers from latest kernel tree
+ - Update mtd-abi.h and use new NAND ECC functionality
+ - Makefile: Support out-of-tree builds
+ - mkfs.jffs2: Add xseqno into `jffs2_raw_xref`
+ - Report compressed file sizes (including node headers) in mkfs.jffs2 stats
+ - Consistently use getopt based option parsing
+ - Amend tests not to insist that file system type is JFFS2
+ - Remove CVS $Id:$ tags
+
+### Removed
+ - mkfs.ffs2
+ - Remaining Automake files
+
+## [1.0.0] - 2006-04-30
+### Added
+ - Import source from CVS
+ - Add user space headers
+
+### Fixed
+ - memory leak in `write_regular_file`
+ - Fix cbuf free properly
+ - Fix mtd_debug after removal of some MTD types and flags
+ - Fix `make install` target
+
+### Changed
+ - Build using in-tree user space headers
diff --git a/Makefile.am b/Makefile.am
index 4fdcd70..887ce93 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,17 +1,22 @@
ACLOCAL_AMFLAGS = -I m4
-AM_CPPFLAGS = $(WARN_CFLAGS) -D_GNU_SOURCE -std=gnu99 -I$(top_srcdir)/include
+AM_CPPFLAGS = $(WARN_CFLAGS) -D_GNU_SOURCE -std=gnu99 -I$(top_srcdir)/include \
+ -include $(top_builddir)/include/config.h
-if WITHOUT_XATTR
-AM_CPPFLAGS += -DWITHOUT_XATTR
+if WITH_ZLIB
+AM_CPPFLAGS += -DWITH_ZLIB
endif
-if WITHOUT_LZO
-AM_CPPFLAGS += -DWITHOUT_LZO
+if WITH_XATTR
+AM_CPPFLAGS += -DWITH_XATTR
endif
-if WITHOUT_ZSTD
-AM_CPPFLAGS += -DWITHOUT_ZSTD
+if WITH_LZO
+AM_CPPFLAGS += -DWITH_LZO
+endif
+
+if WITH_ZSTD
+AM_CPPFLAGS += -DWITH_ZSTD
endif
if WITH_SELINUX
@@ -22,31 +27,21 @@ if WITH_CRYPTO
AM_CPPFLAGS += -DWITH_CRYPTO
endif
-if WITH_GETRANDOM
-AM_CPPFLAGS += -DWITH_GETRANDOM
-endif
-
sbin_PROGRAMS =
sbin_SCRIPTS =
check_PROGRAMS =
noinst_LIBRARIES =
noinst_PROGRAMS =
noinst_SCRIPTS =
-pkglibexec_PROGRAMS =
-pkglibexec_SCRIPTS =
dist_man1_MANS =
dist_man8_MANS =
-TESTS =
-EXTRA_DIST =
-
-GLOBAL_HEADER = \
- include
+testdir = @TESTBINDIR@
+test_PROGRAMS =
+test_SCRIPTS =
-GLOBAL_EXTRA = \
- COPYING
-
-EXTRA_DIST += $(GLOBAL_HEADER) $(GLOBAL_EXTRA)
+TESTS =
+EXTRA_DIST = COPYING CHANGELOG.md README.txt
include lib/Makemodule.am
include ubi-utils/Makemodule.am
diff --git a/README.txt b/README.txt
new file mode 100644
index 0000000..4311698
--- /dev/null
+++ b/README.txt
@@ -0,0 +1,142 @@
+
+ mtd-utils
+ =========
+
+ This package provides userspace utilities for working with Linux MTD and UBI
+ infrastructure, as well as related filesystems (JFFS2, UBIFS).
+
+ MTD stands for "Memory Technology Devices" and means flash, RAM and similar
+ chips, used for solid state storage on embedded devices. Think of e.g. a raw
+ nand-flash chip attached directly to an SoC via parallel or SPI bus, but
+ without _any_ special management like an eMMC has. The MTD subsystem exposes
+ those devices to userspace as character devices. It provides a unified
+ interface, but does not attempt to hide the page vs erase-block device
+ geometry or issues involved in dealing with the underlying storage, like wear
+ or bad blocks.
+
+ For this purpose, UBI provides a layer on top of MTD that hides away some
+ of those complexities. UBI also implements LVM-like logical volume partitioning
+ and some other useful capabilities.
+
+ UBI does not emulate block device like storage. UBI volumes are exposed as
+ character devices with page vs erase-block access geometry, much like MTD
+ partitions. But they behave more like a flash chip with "idealized" properties
+ and transparent wear-leveling.
+
+ JFFS2 is a flash friendly filesystem. It predates UBI and is designed to run
+ on top of raw MTD, implementing its own wear leveling.
+
+ The more recent UBIFS (formerly JFFS3) can be used on top of UBI volumes and
+ offers a number of improvements over JFFS2, offers newer compression schemes
+ and advanced features like file-level encryption and authentication.
+
+
+ Installing
+ ----------
+
+ mtd-utils are packaged by a number of Linux distributions[0] and can be
+ installed via the package management system. A Yocto recipe is available
+ as well[1] as part of the openembedded-core layer.
+
+ Should the tools be too big for on-device use, the BusyBox project provides
+ compatible clone versions.
+
+ Before making this choice however, please note that some "heavy weight" tools
+ like mkfs.ubifs are typically not needed on the device itself. The kernel
+ module can format a volume on first mount. Other, heavy weight tools like lsmtd
+ can be disabled via a configure flag.
+
+ [0] https://repology.org/project/mtd-utils/versions
+ [1] https://layers.openembedded.org/layerindex/recipe/262/
+
+
+ How to get the source
+ ---------------------
+
+ The official git repository and release tarballs are hosted on infradead.org:
+
+ Relase tarballs: ftp://ftp.infradead.org/pub/mtd-utils
+ git repository: git://git.infradead.org/mtd-utils.git
+
+ This is also where the website and documentation are hosted:
+
+ http://www.linux-mtd.infradead.org/
+
+ A http mirror is also provided on infraroot.at:
+
+ Relase tarballs: https://infraroot.at/pub/mtd
+ git repository: https://git.infraroot.at/mtd-utils.git
+
+
+ There are a number of mirrored repositories on GitHub, but this is not where
+ official development takes place. If you want to contribute upstream, please
+ do not open any issues or pull requests there. Upstream development is done
+ via mailing list (see below).
+
+
+ How to build
+ ------------
+
+ mtd-utils uses an autotools based build system. If you are building the git
+ tree, you first need to run `./autogen.sh`. This sets up the build system
+ and requires autoconf, automake and possibly other autotools to be installed.
+
+ After unpacking a tarball (or running autogen.sh) simply run:
+
+ $ ./configure
+ $ make
+
+ to build the package. This does not require autotools to be installed, but
+ does need pkg-config, make, etc...
+
+ There are a number of configure switches to tune the build.
+ Run `./configure --help` to get an overview.
+
+
+ For compiling mtd-utils, you need development packages for the following
+ dependency libraries:
+
+ zlib (optional dependency for mkfs.ubifs, mkfs.jffs2)
+ lzo2 (optional dependency for mkfs.ubifs, mkfs.jffs2)
+ zstd (optional dependency for mkfs.ubifs)
+ libuuid* (required by mkfs.ubifs)
+ libselinux (optional dependency for mkfs.ubifs)
+ openssl (optional dependency for mkfs.ubifs)
+
+ * this library is part of util-linux, aka util-linux-ng and some distributions
+ package it under that name.
+
+ For xattr & acl support in mkfs.ubifs and mkfs.jffs2, the build system looks
+ for the "sys/xattr.h" and "sys/acl.h" header files. Depending on your
+ distributions, those may be packaged as part of libattr and libacl
+ respectively.
+
+
+ Please note that the mkfs tools are optional and can be disabled via a
+ configure flag. This should also remove any library dependencies.
+
+
+ How to contribute
+ -----------------
+
+ Development of mtd-utils takes place on the linux-mtd mailing list:
+
+ mailto: linux-mtd@lists.infradead.org
+ archive: https://lists.infradead.org/pipermail/linux-mtd/
+
+ You can subscribe here: http://lists.infradead.org/mailman/listinfo/linux-mtd/
+ or simply send "subscribe" to linux-mtd-request@lists.infradead.org
+
+
+ Contributions are submitted in the form of plain text patches,
+ using `git send-email` or similar.
+
+ Please prefix your subject with "mtd-utils: " to make them easier to spot.
+
+ It may take a few days for a patch to be picked up. This is in part done
+ intentionally to allow other people to comment on it. If it's been more
+ than a week and you feel your patch might have been overlooked, please send
+ a friendly ping, or re-submit the patch series with "[RESEND]" in the subject.
+
+
+ There is also a #mtd IRC channel on irc.oftc.net
diff --git a/configure.ac b/configure.ac
index bcea080..cf3a959 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,29 +1,25 @@
AC_PREREQ([2.60])
-m4_define([RELEASE], 2.1.2)
+m4_define([RELEASE], 2.2.0)
AC_INIT([mtd-utils], [RELEASE], [linux-mtd@lists.infradead.org], mtd-utils)
AC_ARG_ENABLE([unit-tests],
[AS_HELP_STRING([--enable-unit-tests], [Compile unit test programs])],
- [case "${enableval}" in
- yes) AM_CONDITIONAL([UNIT_TESTS], [true]) ;;
- no) AM_CONDITIONAL([UNIT_TESTS], [false]) ;;
- *) AC_MSG_ERROR([bad value ${enableval} for --enable-unit-tests]) ;;
- esac],
- [AM_CONDITIONAL([UNIT_TESTS], [false])])
+ [], [enable_unit_tests="no"])
-AM_COND_IF([UNIT_TESTS], [: ${CFLAGS=""}], [])
+AS_IF([test "x$enable_unit_tests" = "xyes"], [: ${CFLAGS=""}], [])
AC_CONFIG_MACRO_DIR([m4])
AM_INIT_AUTOMAKE([foreign subdir-objects dist-bzip2])
AM_SILENT_RULES([yes])
-AC_PROG_LIBTOOL
-AC_DISABLE_STATIC
AC_PROG_CC
AC_PROG_INSTALL
-
+# autoconf <= 2.63 doesn't have AC_PROG_AR
+AC_CHECK_TOOL(AR, ar, :)
+AC_PROG_RANLIB
+AC_SYS_LARGEFILE
m4_ifndef([PKG_PROG_PKG_CONFIG],
[m4_fatal([Could not locate the pkg-config autoconf
@@ -61,160 +57,92 @@ AC_SUBST([WARN_CFLAGS])
###### handle configure switches, select dependencies ######
-need_clock_gettime="no"
-need_pthread="no"
-need_uuid="no"
-need_zlib="no"
-need_lzo="no"
-need_zstd="no"
-need_xattr="no"
-need_cmocka="no"
-need_selinux="no"
-need_openssl="no"
-need_getrandom="no"
+AC_ARG_WITH([tests],
+ [AS_HELP_STRING([--without-tests], [Compile test programs])],
+ [], [with_tests="yes"])
-AM_COND_IF([UNIT_TESTS], [
- need_cmocka="yes"
-])
+AC_DEFINE_DIR(TESTBINDIR, libexecdir/mtd-utils,
+ [Path where test and debug programs will be installed])
+AC_ARG_ENABLE([ubihealthd],
+ [AS_HELP_STRING([--enable-ubihealthd], [Build the ubihealthd program])],
+ [], [enable_ubihealthd="yes"])
-AC_ARG_ENABLE([tests],
- [AS_HELP_STRING([--disable-tests], [Compile test programs])],
- [case "${enableval}" in
- yes) AM_CONDITIONAL([BUILD_TESTS], [true]) ;;
- no) AM_CONDITIONAL([BUILD_TESTS], [false]) ;;
- *) AC_MSG_ERROR([bad value ${enableval} for --disable-tests]) ;;
- esac],
- [AM_CONDITIONAL([BUILD_TESTS], [true])])
-
-AM_COND_IF([BUILD_TESTS], [
- need_clock_gettime="yes"
- need_pthread="yes"
-])
-
-
-AC_ARG_ENABLE([install-tests],
- [AS_HELP_STRING([--enable-install-tests], [Install test programs])],
- [case "${enableval}" in
- yes) AM_CONDITIONAL([INSTALL_TESTS], [true]) ;;
- no) AM_CONDITIONAL([INSTALL_TESTS], [false]) ;;
- *) AC_MSG_ERROR([bad value ${enableval} for --enable-install-tests]) ;;
- esac],
- [AM_CONDITIONAL([INSTALL_TESTS], [false])])
-
-
-AM_COND_IF([INSTALL_TESTS],
- [AC_SUBST(testbindir, ["\$libexecpath"])],
- [AC_SUBST(testbindir, ["\".\""])])
-
-
-AC_ARG_ENABLE([lsmtd],
- [AS_HELP_STRING([--disable-lsmtd], [Do not build the lsmtd program])],
- [case "${enableval}" in
- yes) AM_CONDITIONAL([BUILD_LSMTD], [true]) ;;
- no) AM_CONDITIONAL([BUILD_LSMTD], [false]) ;;
- *) AC_MSG_ERROR([bad value ${enableval} for --disable-lsmtd]) ;;
- esac],
- [AM_CONDITIONAL([BUILD_LSMTD], [true])])
+AC_ARG_WITH([lsmtd],
+ [AS_HELP_STRING([--without-lsmtd], [Do not build the lsmtd program])],
+ [], [with_lsmtd="yes"])
AC_ARG_WITH([jffs],
[AS_HELP_STRING([--without-jffs], [Disable jffsX utilities])],
- [case "${withval}" in
- yes) AM_CONDITIONAL([BUILD_JFFSX], [true]) ;;
- no) AM_CONDITIONAL([BUILD_JFFSX], [false]) ;;
- *) AC_MSG_ERROR([bad value ${withval} for --without-jffs]) ;;
- esac],
- [AM_CONDITIONAL([BUILD_JFFSX], [true])])
+ [], [with_jffs="yes"])
AC_ARG_WITH([ubifs],
[AS_HELP_STRING([--without-ubifs], [Disable ubifs utilities])],
- [case "${withval}" in
- yes) AM_CONDITIONAL([BUILD_UBIFS], [true]) ;;
- no) AM_CONDITIONAL([BUILD_UBIFS], [false]) ;;
- *) AC_MSG_ERROR([bad value ${withval} for --without-ubifs]) ;;
- esac],
- [AM_CONDITIONAL([BUILD_UBIFS], [true])])
-
-AM_COND_IF([BUILD_UBIFS], [
- need_uuid="yes"
- need_xattr="yes"
- need_zlib="yes"
- need_lzo="yes"
- need_zstd="yes"
- need_openssl="yes"
- need_getrandom="yes"
-])
+ [], [with_ubifs="yes"])
-AM_COND_IF([BUILD_JFFSX], [
- need_xattr="yes"
- need_zlib="yes"
- need_lzo="yes"
-])
+AC_ARG_WITH([zlib],
+ [AS_HELP_STRING([--with-zlib], [Support zlib deflate compression])],
+ [], [with_zlib="check"])
AC_ARG_WITH([xattr],
- [AS_HELP_STRING([--without-xattr],
- [Disable support forextended file attributes])],
- [case "${withval}" in
- yes) ;;
- no) need_xattr="no" ;;
- *) AC_MSG_ERROR([bad value ${withval} for --without-xattr]) ;;
- esac])
+ [AS_HELP_STRING([--with-xattr], [Support extended file attributes])],
+ [], [with_xattr="check"])
AC_ARG_WITH([lzo],
- [AS_HELP_STRING([--without-lzo], [Disable support for LZO compression])],
- [case "${withval}" in
- yes) ;;
- no) need_lzo="no" ;;
- *) AC_MSG_ERROR([bad value ${withval} for --without-lzo]) ;;
- esac])
+ [AS_HELP_STRING([--with-lzo], [Support LZO compression])],
+ [], [with_lzo="check"])
AC_ARG_WITH([zstd],
- [AS_HELP_STRING([--without-zstd], [Disable support for ZSTD compression])],
- [case "${withval}" in
- yes) ;;
- no) need_zstd="no" ;;
- *) AC_MSG_ERROR([bad value ${withval} for --without-zstd]) ;;
- esac])
+ [AS_HELP_STRING([--with-zstd], [Support for ZSTD compression])],
+ [], [with_zstd="check"])
AC_ARG_WITH([selinux],
[AS_HELP_STRING([--with-selinux],
- [Enable support for selinux extended attributes])],
- [case "${withval}" in
- yes) need_selinux="yes";;
- no) ;;
- *) AC_MSG_ERROR([bad value ${withval} for --with-selinux]) ;;
- esac])
+ [Support for selinux extended attributes])],
+ [], [with_selinux="check"])
AC_ARG_WITH([crypto],
- [AS_HELP_STRING([--without-crypto],
- [Disable support for UBIFS crypto features])],
- [case "${withval}" in
- yes) ;;
- no) need_openssl="no";;
- *) AC_MSG_ERROR([bad value ${withval} for --without-crypto]) ;;
- esac])
+ [AS_HELP_STRING([--with-crypto], [Support for UBIFS crypto features])],
+ [], [with_crypto="check"])
##### search for dependencies #####
+need_clock_gettime="no"
+need_pthread="no"
+need_uuid="no"
+need_cmocka="no"
+need_getrandom="no"
+
clock_gettime_missing="no"
pthread_missing="no"
uuid_missing="no"
-zlib_missing="no"
-lzo_missing="no"
-zstd_missing="no"
-xattr_missing="no"
cmocka_missing="no"
-selinux_missing="no"
-openssl_missing="no"
getrandom_missing="no"
-if test "x$need_zlib" = "xyes"; then
- PKG_CHECK_MODULES(ZLIB, [zlib], [], [zlib_missing="yes"])
-fi
+AS_IF([test "x$enable_unit_tests" = "xyes"], [
+ need_cmocka="yes"
+])
-if test "x$need_selinux" = "xyes"; then
- PKG_CHECK_MODULES(LIBSELINUX, [libselinux], [], [selinux_missing="yes"])
-fi
+AS_IF([test "x$with_tests" = "xyes"], [
+ need_clock_gettime="yes"
+ need_pthread="yes"
+])
+
+AS_IF([test "x$enable_ubihealthd" = "xyes"], [
+ need_getrandom="yes"
+])
+
+AS_IF([test "x$with_ubifs" = "xyes"], [
+ need_uuid="yes"
+ need_getrandom="yes"
+])
+
+AS_IF([test "x$with_zlib" != "xno"], [
+ PKG_CHECK_MODULES(ZLIB, [zlib], [with_zlib="yes"],
+ [AS_IF([test "x$with_zlib" != "xcheck"],
+ [AC_MSG_ERROR([cannot find zlib])],
+ [with_zlib="no"])])
+], [])
if test "x$need_uuid" = "xyes"; then
PKG_CHECK_MODULES(UUID, [uuid], [], [uuid_missing="yes"])
@@ -229,34 +157,63 @@ if test "x$need_pthread" = "xyes"; then
AX_PTHREAD([], [pthread_missing="yes"])
fi
-if test "x$need_lzo" = "xyes"; then
- AC_ARG_VAR([LZO_CFLAGS], [C compiler flags for lzo])
- AC_ARG_VAR([LZO_LIBS], [linker flags for lzo])
- AC_CHECK_LIB([lzo2], [lzo1x_1_15_compress], [LZO_LIBS="-llzo2"],
- [AC_CHECK_LIB([lzo],[lzo1x_1_15_compress],[LZO_LIBS="-llzo"],
- [lzo_missing="yes"]
- )]
- )
-fi
-
-if test "x$need_zstd" = "xyes"; then
- PKG_CHECK_MODULES([ZSTD], [libzstd],, zstd_missing="yes")
-fi
+AC_ARG_VAR([LZO_CFLAGS], [C compiler flags for lzo])
+AC_ARG_VAR([LZO_LIBS], [linker flags for lzo])
-if test "x$need_xattr" = "xyes"; then
- AC_CHECK_HEADERS([sys/xattr.h], [], [xattr_missing="yes"])
- AC_CHECK_HEADERS([sys/acl.h], [], [xattr_missing="yes"])
-fi
-
-if test "x$need_selinux" = "xyes"; then
- AC_CHECK_HEADERS([selinux/selinux.h], [], [selinux_missing="yes"])
- AC_CHECK_HEADERS([selinux/label.h], [], [selinux_missing="yes"])
-fi
-
-if test "x$need_openssl" = "xyes"; then
- AC_CHECK_HEADER(openssl/rand.h)
- PKG_CHECK_MODULES(OPENSSL, [openssl], [], [openssl_missing="yes"])
-fi
+AS_IF([test -z "$LZO_LIBS" -a "x$with_lzo" != "xno"], [
+ AC_CHECK_LIB([lzo2], [lzo1x_1_15_compress], [LZO_LIBS="-llzo2"],
+ [AC_CHECK_LIB([lzo],[lzo1x_1_15_compress],
+ [LZO_LIBS="-llzo"],
+ []
+ )]
+ )
+], [])
+
+AS_IF([test -z "$LZO_LIBS"], [AS_IF([test "x$with_lzo" = "xyes"],
+ [AC_MSG_ERROR([cannot find liblzo])],
+ [with_lzo="no"])],
+ [with_lzo="yes"])
+
+AS_IF([test "x$with_zstd" != "xno"], [
+ PKG_CHECK_MODULES(ZSTD, [libzstd], [with_zstd="yes"],
+ [AS_IF([test "x$with_zstd" != "xcheck"],
+ [AC_MSG_ERROR([cannot find zstd])],
+ [with_zstd="no"])])
+], [])
+
+AS_IF([test "x$with_xattr" != "xno"], [
+ have_xattr="yes"
+
+ AC_CHECK_HEADERS([sys/xattr.h], [], [have_xattr="no"])
+ AC_CHECK_HEADERS([sys/acl.h], [], [have_xattr="no"])
+
+ AS_IF([test "x$with_xattr" != "xcheck" -a "x$have_xattr" = "xno"],
+ [AC_MSG_ERROR([cannot find xattr/acl headers])],
+ [with_xattr="$have_xattr"])
+], [])
+
+AS_IF([test "x$with_selinux" != "xno"], [
+ have_selinux="yes"
+
+ PKG_CHECK_MODULES(LIBSELINUX, [libselinux], [], [have_selinux="no"])
+ AC_CHECK_HEADERS([selinux/selinux.h], [], [have_selinux="no"])
+ AC_CHECK_HEADERS([selinux/label.h], [], [have_selinux="no"])
+
+ AS_IF([test "x$with_selinux" != "xcheck" -a "x$have_selinux" = "xno"],
+ [AC_MSG_ERROR([cannot find SELinux libraries])],
+ [with_selinux="$have_selinux"])
+], [])
+
+AS_IF([test "x$with_crypto" != "xno"], [
+ have_openssl="yes"
+
+ AC_CHECK_HEADERS([openssl/rand.h], [], [have_openssl="no"])
+ PKG_CHECK_MODULES(OPENSSL, [openssl], [], [have_openssl="no"])
+
+ AS_IF([test "x$with_crypto" != "xcheck" -a "x$have_openssl" = "xno"],
+ [AC_MSG_ERROR([cannot find OpenSSL libraries])],
+ [with_crypto="$have_openssl"])
+], [])
if test "x$need_getrandom" = "xyes"; then
AC_CHECK_HEADERS([sys/random.h], [], [getrandom_missing="yes"])
@@ -290,49 +247,9 @@ if test "x$uuid_missing" = "xyes"; then
dep_missing="yes"
fi
-if test "x$zlib_missing" = "xyes"; then
- AC_MSG_WARN([cannot find ZLIB library required for mkfs programs])
- AC_MSG_NOTICE([mtd-utils can optionally be built without mkfs.ubifs])
- AC_MSG_NOTICE([mtd-utils can optionally be built without mkfs.jffs2])
- dep_missing="yes"
-fi
-
-if test "x$lzo_missing" = "xyes"; then
- AC_MSG_WARN([cannot find LZO library required for mkfs programs])
- AC_MSG_NOTICE([mtd-utils can optionally be built without mkfs.ubifs])
- AC_MSG_NOTICE([mtd-utils can optionally be built without mkfs.jffs2])
- AC_MSG_NOTICE([mtd-utils can optionally be built without LZO support])
- dep_missing="yes"
-fi
-
-if test "x$zstd_missing" = "xyes"; then
- AC_MSG_WARN([cannot find ZSTD library required for mkfs program])
- AC_MSG_NOTICE([mtd-utils can optionally be built without mkfs.ubifs])
- AC_MSG_NOTICE([mtd-utils can optionally be built without ZSTD support])
- dep_missing="yes"
-fi
-
-if test "x$xattr_missing" = "xyes"; then
- AC_MSG_WARN([cannot find headers for extended attributes])
- AC_MSG_WARN([disabling XATTR support])
- need_xattr="no"
-fi
-
-if test "x$selinux_missing" = "xyes"; then
- AC_MSG_WARN([cannot find headers for selinux library])
- AC_MSG_WARN([disabling SELINUX support])
- need_selinux="no"
-fi
-
-if test "x$openssl_missing" = "xyes"; then
- AC_MSG_WARN([cannot find headers for OpenSSL library])
- AC_MSG_WARN([disabling OpenSSL support])
- need_openssl="no"
-fi
-
if test "x$getrandom_missing" = "xyes"; then
AC_MSG_WARN([cannot find headers for getrandom() function])
- AC_MSG_WARN([disabling UBIFS ubihealthd support])
+ AC_MSG_NOTICE([mkfs.ubifs, ubihealthd can optionally be disabled])
need_getrandom="no"
fi
@@ -348,12 +265,19 @@ fi
##### generate output #####
-AM_CONDITIONAL([WITHOUT_LZO], [test "x$need_lzo" != "xyes"])
-AM_CONDITIONAL([WITHOUT_ZSTD], [test "x$need_zstd" != "xyes"])
-AM_CONDITIONAL([WITHOUT_XATTR], [test "x$need_xattr" != "xyes"])
-AM_CONDITIONAL([WITH_SELINUX], [test "x$need_selinux" == "xyes"])
-AM_CONDITIONAL([WITH_CRYPTO], [test "x$need_openssl" == "xyes"])
-AM_CONDITIONAL([WITH_GETRANDOM], [test "x$need_getrandom" == "xyes"])
+AM_CONDITIONAL([WITH_LZO], [test "x$with_lzo" = "xyes"])
+AM_CONDITIONAL([WITH_ZLIB], [test "x$with_zlib" = "xyes"])
+AM_CONDITIONAL([WITH_ZSTD], [test "x$with_zstd" = "xyes"])
+AM_CONDITIONAL([WITH_XATTR], [test "x$with_xattr" = "xyes"])
+AM_CONDITIONAL([WITH_SELINUX], [test "x$with_selinux" = "xyes"])
+AM_CONDITIONAL([WITH_CRYPTO], [test "x$with_crypto" = "xyes"])
+AM_CONDITIONAL([WITH_UBIHEALTHD], [test "x$enable_ubihealthd" = "xyes"])
+
+AM_CONDITIONAL([BUILD_UBIFS], [test "x$with_ubifs" = "xyes"])
+AM_CONDITIONAL([BUILD_JFFSX], [test "x$with_jffs" = "xyes"])
+AM_CONDITIONAL([BUILD_LSMTD], [test "x$with_lsmtd" = "xyes"])
+AM_CONDITIONAL([BUILD_TESTS], [test "x$with_tests" = "xyes"])
+AM_CONDITIONAL([UNIT_TESTS], [test "x$enable_unit_tests" = "xyes"])
AC_CHECK_SIZEOF([off_t])
AC_CHECK_SIZEOF([loff_t])
@@ -368,3 +292,40 @@ AC_CONFIG_FILES([tests/fs-tests/fs_help_all.sh
tests/ubi-tests/ubi-stress-test.sh])
AC_OUTPUT([Makefile])
+
+AC_MSG_RESULT([
+ ${PACKAGE} ${VERSION}
+
+ prefix: ${prefix}
+ exec prefix: ${exec_prefix}
+
+ runstatedir: ${runstatedir}
+ bindir: ${bindir}
+ sbindir: ${sbindir}
+ libdir: ${libdir}
+ includedir: ${includedir}
+
+ compiler: ${CC}
+ cflags: ${CFLAGS}
+ ldflags: ${LDFLAGS}
+
+ lzo support: ${with_lzo}
+ zlib support: ${with_zlib}
+ zstd support: ${with_zstd}
+ xattr/acl support: ${with_xattr}
+ SELinux support: ${with_selinux}
+ fscrypt support: ${with_crypto}
+
+ Test programs: ${with_tests}
+ Unit tests: ${enable_unit_tests}
+ ubihealthd: ${enable_ubihealthd}
+ lsmtd: ${with_lsmtd}
+ jffs2 utils: ${with_jffs}
+ ubifs utils: ${with_ubifs}
+
+ warnings:
+
+${WARN_CFLAGS}
+
+ Type 'make' or 'make <utilname>' to compile.
+])
diff --git a/include/common.h b/include/common.h
index 7270769..303d30d 100644
--- a/include/common.h
+++ b/include/common.h
@@ -31,8 +31,6 @@
#include <unistd.h>
#include <sys/sysmacros.h>
-#include "config.h"
-
#ifndef PROGRAM_NAME
# error "You must define PROGRAM_NAME before including this header"
#endif
@@ -238,6 +236,7 @@ do { \
long long util_get_bytes(const char *str);
void util_print_bytes(long long bytes, int bracket);
int util_srand(void);
+char *mtd_find_dev_node(const char *id);
/*
* The following helpers are here to avoid compiler complaints about unchecked
diff --git a/include/libmissing.h b/include/libmissing.h
index 0196033..0fb0cf4 100644
--- a/include/libmissing.h
+++ b/include/libmissing.h
@@ -1,8 +1,6 @@
#ifndef LIBMISSING_H
#define LIBMISSING_H
-#include "config.h"
-
#ifdef HAVE_EXECINFO_H
#include <execinfo.h>
#endif
diff --git a/include/libmtd.h b/include/libmtd.h
index cc24af8..f909a16 100644
--- a/include/libmtd.h
+++ b/include/libmtd.h
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2008, 2009 Nokia Corporation
+ * Copyright 2021 NXP
*
* 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
@@ -129,7 +130,7 @@ int mtd_get_info(libmtd_t desc, struct mtd_info *info);
/**
* mtd_get_dev_info - get information about an MTD device.
* @desc: MTD library descriptor
- * @node: name of the MTD device node
+ * @node: path of the MTD device node
* @mtd: the MTD device information is returned here
*
* This function gets information about MTD device defined by the @node device
@@ -151,6 +152,17 @@ int mtd_get_dev_info(libmtd_t desc, const char *node, struct mtd_dev_info *mtd);
int mtd_get_dev_info1(libmtd_t desc, int mtd_num, struct mtd_dev_info *mtd);
/**
+ * mtd_get_dev_info2 - get information about an MTD device.
+ * @desc: MTD library descriptor
+ * @name: name of the MTD device
+ * @mtd: the MTD device information is returned here
+ *
+ * This function is identical to 'mtd_get_dev_info()' except that it accepts
+ * MTD device's name, not MTD character device.
+ */
+int mtd_get_dev_info2(libmtd_t desc, const char *name, struct mtd_dev_info *mtd);
+
+/**
* mtd_lock - lock eraseblocks.
* @desc: MTD library descriptor
* @mtd: MTD device description object
@@ -175,6 +187,20 @@ int mtd_lock(const struct mtd_dev_info *mtd, int fd, int eb);
int mtd_unlock(const struct mtd_dev_info *mtd, int fd, int eb);
/**
+ * mtd_unlock_multi - unlock eraseblocks.
+ * @desc: MTD library descriptor
+ * @mtd: MTD device description object
+ * @fd: MTD device node file descriptor
+ * @eb: index of first eraseblock to unlock
+ * @blocks: the number of eraseblocks to unlock
+ *
+ * This function unlocks @blocks starting at eraseblock @eb.
+ * Returns %0 in case of success and %-1 in case of failure.
+ */
+int mtd_unlock_multi(const struct mtd_dev_info *mtd, int fd, int eb,
+ int blocks);
+
+/**
* mtd_erase - erase multiple eraseblocks.
* @desc: MTD library descriptor
* @mtd: MTD device description object
diff --git a/include/libubi.h b/include/libubi.h
index 46c732a..e1e234e 100644
--- a/include/libubi.h
+++ b/include/libubi.h
@@ -25,6 +25,7 @@
#include <ctype.h>
#include <stdint.h>
+#include <stdbool.h>
#include <mtd/ubi-user.h>
#ifdef __cplusplus
@@ -53,6 +54,8 @@ typedef void * libubi_t;
* @vid_hdr_offset: VID header offset (%0 means default offset and this is what
* most of the users want)
* @max_beb_per1024: Maximum expected bad eraseblocks per 1024 eraseblocks
+ * @disable_fm: whether disable fastmap
+ * @need_resv_pool: whether reserve free pebs for filling pool/wl_pool
*/
struct ubi_attach_request
{
@@ -61,6 +64,8 @@ struct ubi_attach_request
const char *mtd_dev_node;
int vid_hdr_offset;
int max_beb_per1024;
+ bool disable_fm;
+ bool need_resv_pool;
};
/**
diff --git a/include/mtd/mtd-abi.h b/include/mtd/mtd-abi.h
index bcd7496..a54c386 100644
--- a/include/mtd/mtd-abi.h
+++ b/include/mtd/mtd-abi.h
@@ -201,6 +201,8 @@ struct otp_info {
* modes (see "struct mtd_write_req")
*/
#define MEMWRITE _IOWR('M', 24, struct mtd_write_req)
+/* Erase a given range of user data (must be in mode %MTD_FILE_MODE_OTP_USER) */
+#define OTPERASE _IOW('M', 25, struct otp_info)
/*
* Obsolete legacy interface. Keep it in order not to break userspace
diff --git a/include/mtd/ubi-user.h b/include/mtd/ubi-user.h
index 707c4f2..bb5c0f9 100644
--- a/include/mtd/ubi-user.h
+++ b/include/mtd/ubi-user.h
@@ -235,6 +235,8 @@ enum {
* @mtd_num: MTD device number to attach
* @vid_hdr_offset: VID header offset (use defaults if %0)
* @max_beb_per1024: maximum expected number of bad PEB per 1024 PEBs
+ * @disable_fm: whether disable fastmap
+ * @need_resv_pool: whether reserve free pebs for filling pool/wl_pool
* @padding: reserved for future, not used, has to be zeroed
*
* This data structure is used to specify MTD device UBI has to attach and the
@@ -270,13 +272,19 @@ enum {
* eraseblocks for new bad eraseblocks, but attempts to use available
* eraseblocks (if any). The accepted range is 0-768. If 0 is given, the
* default kernel value of %CONFIG_MTD_UBI_BEB_LIMIT will be used.
+ *
+ * If @disable_fm is not zero, ubi doesn't create new fastmap even the module
+ * param 'fm_autoconvert' is set, and existed old fastmap will be destroyed
+ * after doing full scanning.
*/
struct ubi_attach_req {
int32_t ubi_num;
int32_t mtd_num;
int32_t vid_hdr_offset;
int16_t max_beb_per1024;
- int8_t padding[10];
+ int8_t disable_fm;
+ int8_t need_resv_pool;
+ int8_t padding[8];
};
/*
diff --git a/jffsX-utils/Makemodule.am b/jffsX-utils/Makemodule.am
index fb181de..266c12e 100644
--- a/jffsX-utils/Makemodule.am
+++ b/jffsX-utils/Makemodule.am
@@ -1,37 +1,39 @@
mkfs_jffs2_SOURCES = \
jffsX-utils/mkfs.jffs2.c \
jffsX-utils/rbtree.h \
- jffsX-utils/compr_zlib.c \
jffsX-utils/compr.h \
jffsX-utils/rbtree.c \
- jffsX-utils/compr_lzo.c \
jffsX-utils/compr.c \
- jffsX-utils/compr_rtime.c
+ jffsX-utils/compr_rtime.c \
+ jffsX-utils/compr.h \
+ jffsX-utils/rbtree.h \
+ jffsX-utils/summary.h \
+ include/linux/jffs2.h \
+ include/mtd/jffs2-user.h
mkfs_jffs2_LDADD = libmtd.a $(ZLIB_LIBS) $(LZO_LIBS)
mkfs_jffs2_CPPFLAGS = $(AM_CPPFLAGS) $(ZLIB_CFLAGS) $(LZO_CFLAGS)
-jffs2reader_SOURCES = jffsX-utils/jffs2reader.c
+jffs2reader_SOURCES = jffsX-utils/jffs2reader.c include/mtd/jffs2-user.h
jffs2reader_LDADD = libmtd.a $(ZLIB_LIBS) $(LZO_LIBS)
+jffs2reader_CPPFLAGS = $(AM_CPPFLAGS) $(ZLIB_CFLAGS) $(LZO_CFLAGS)
-jffs2dump_SOURCES = jffsX-utils/jffs2dump.c
+jffs2dump_SOURCES = jffsX-utils/jffs2dump.c include/mtd/jffs2-user.h
+jffs2dump_SOURCES += jffsX-utils/summary.h
jffs2dump_LDADD = libmtd.a $(ZLIB_LIBS) $(LZO_LIBS)
+jffs2dump_CPPFLAGS = $(AM_CPPFLAGS) $(ZLIB_CFLAGS) $(LZO_CFLAGS)
-sumtool_SOURCES = jffsX-utils/sumtool.c
+sumtool_SOURCES = jffsX-utils/sumtool.c jffsX-utils/summary.h
sumtool_LDADD = libmtd.a
-JFFSX_BINS = \
- mkfs.jffs2 jffs2dump jffs2reader sumtool
-
-JFFSX_MAN = \
- jffsX-utils/mkfs.jffs2.1
-
-JFFSX_EXTRA = \
- jffsX-utils/device_table.txt jffsX-utils/mkfs.jffs2.1
+if WITH_LZO
+mkfs_jffs2_SOURCES += jffsX-utils/compr_lzo.c
+endif
-JFFSX_HEADER = \
- jffsX-utils/compr.h jffsX-utils/rbtree.h jffsX-utils/summary.h
+if WITH_ZLIB
+mkfs_jffs2_SOURCES += jffsX-utils/compr_zlib.c
+endif
-EXTRA_DIST += $(JFFSX_HEADER) $(JFFSX_EXTRA)
+EXTRA_DIST += jffsX-utils/device_table.txt jffsX-utils/mkfs.jffs2.1
-dist_man1_MANS += $(JFFSX_MAN)
-sbin_PROGRAMS += $(JFFSX_BINS)
+dist_man1_MANS += jffsX-utils/mkfs.jffs2.1
+sbin_PROGRAMS += mkfs.jffs2 jffs2dump jffs2reader sumtool
diff --git a/jffsX-utils/compr.c b/jffsX-utils/compr.c
index cb4432e..01176eb 100644
--- a/jffsX-utils/compr.c
+++ b/jffsX-utils/compr.c
@@ -511,13 +511,13 @@ reinsert:
int jffs2_compressors_init(void)
{
-#ifdef CONFIG_JFFS2_ZLIB
+#ifdef WITH_ZLIB
jffs2_zlib_init();
#endif
#ifdef CONFIG_JFFS2_RTIME
jffs2_rtime_init();
#endif
-#ifdef CONFIG_JFFS2_LZO
+#ifdef WITH_LZO
jffs2_lzo_init();
#endif
return 0;
@@ -528,10 +528,10 @@ int jffs2_compressors_exit(void)
#ifdef CONFIG_JFFS2_RTIME
jffs2_rtime_exit();
#endif
-#ifdef CONFIG_JFFS2_ZLIB
+#ifdef WITH_ZLIB
jffs2_zlib_exit();
#endif
-#ifdef CONFIG_JFFS2_LZO
+#ifdef WITH_LZO
jffs2_lzo_exit();
#endif
return 0;
diff --git a/jffsX-utils/compr.h b/jffsX-utils/compr.h
index a21e935..f1f5975 100644
--- a/jffsX-utils/compr.h
+++ b/jffsX-utils/compr.h
@@ -16,9 +16,7 @@
#include <stdint.h>
#include "linux/jffs2.h"
-#define CONFIG_JFFS2_ZLIB
#define CONFIG_JFFS2_RTIME
-#define CONFIG_JFFS2_LZO
#define JFFS2_RUBINMIPS_PRIORITY 10
#define JFFS2_DYNRUBIN_PRIORITY 20
@@ -103,7 +101,7 @@ char *jffs2_stats(void);
/* Compressor modules */
/* These functions will be called by jffs2_compressors_init/exit */
-#ifdef CONFIG_JFFS2_ZLIB
+#ifdef WITH_ZLIB
int jffs2_zlib_init(void);
void jffs2_zlib_exit(void);
#endif
@@ -111,7 +109,7 @@ void jffs2_zlib_exit(void);
int jffs2_rtime_init(void);
void jffs2_rtime_exit(void);
#endif
-#ifdef CONFIG_JFFS2_LZO
+#ifdef WITH_LZO
int jffs2_lzo_init(void);
void jffs2_lzo_exit(void);
#endif
diff --git a/jffsX-utils/compr_lzo.c b/jffsX-utils/compr_lzo.c
index 56aa1b4..ddd8d55 100644
--- a/jffsX-utils/compr_lzo.c
+++ b/jffsX-utils/compr_lzo.c
@@ -24,8 +24,6 @@
#include <stdint.h>
#include <stdio.h>
#include <string.h>
-
-#ifndef WITHOUT_LZO
#include <asm/types.h>
#include <linux/jffs2.h>
#include <lzo/lzo1x.h>
@@ -121,16 +119,3 @@ void jffs2_lzo_exit(void)
free(lzo_compress_buf);
free(lzo_mem);
}
-
-#else
-
-int jffs2_lzo_init(void)
-{
- return 0;
-}
-
-void jffs2_lzo_exit(void)
-{
-}
-
-#endif
diff --git a/jffsX-utils/jffs2dump.c b/jffsX-utils/jffs2dump.c
index d30b59f..30455ea 100644
--- a/jffsX-utils/jffs2dump.c
+++ b/jffsX-utils/jffs2dump.c
@@ -757,6 +757,12 @@ int main(int argc, char **argv)
// get image length
imglen = lseek(fd, 0, SEEK_END);
+ if (imglen < 0) {
+ perror(img);
+ close(fd);
+ exit(EXIT_FAILURE);
+ }
+
lseek (fd, 0, SEEK_SET);
data = malloc (imglen);
diff --git a/jffsX-utils/jffs2reader.c b/jffsX-utils/jffs2reader.c
index 083500e..87a2167 100644
--- a/jffsX-utils/jffs2reader.c
+++ b/jffsX-utils/jffs2reader.c
@@ -75,7 +75,11 @@ BUGS:
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
+#ifdef WITH_ZLIB
#include <zlib.h>
+#else
+typedef unsigned long uLongf;
+#endif
#include "mtd/jffs2-user.h"
#include "common.h"
@@ -132,12 +136,13 @@ static void putblock(char *b, size_t bsize, size_t * rsize,
bzero(b + *rsize, je32_to_cpu(n->isize) - *rsize);
switch (n->compr) {
+#ifdef WITH_ZLIB
case JFFS2_COMPR_ZLIB:
uncompress((Bytef *) b + je32_to_cpu(n->offset), &dlen,
(Bytef *) ((char *) n) + sizeof(struct jffs2_raw_inode),
(uLongf) je32_to_cpu(n->csize));
break;
-
+#endif
case JFFS2_COMPR_NONE:
memcpy(b + je32_to_cpu(n->offset),
((char *) n) + sizeof(struct jffs2_raw_inode), dlen);
@@ -336,8 +341,9 @@ static void printdir(char *o, size_t size, struct dir *d, const char *path,
d = d->next;
continue;
}
-
- filetime = ctime((const time_t *) &(ri->ctime));
+ time_t _ctime;
+ memcpy(&_ctime, &(ri->ctime), sizeof(time_t));
+ filetime = ctime(&_ctime);
age = time(NULL) - je32_to_cpu(ri->ctime);
mode.v32 = ri->mode.m;
printf("%s %-4d %-8d %-8d ", mode_string(je32_to_cpu(mode)),
diff --git a/jffsX-utils/mkfs.jffs2.1 b/jffsX-utils/mkfs.jffs2.1
index 7c57ddc..75f96f5 100644
--- a/jffsX-utils/mkfs.jffs2.1
+++ b/jffsX-utils/mkfs.jffs2.1
@@ -119,13 +119,13 @@ the kernel can be changed with a #define to accept images of the
non-native endianness. Full bi-endian support in the kernel is not
planned.
-It is unlikely that JFFS2 images are useful except in conjuction
+It is unlikely that JFFS2 images are useful except in conjunction
with the MTD (Memory Technology Device) drivers in the Linux
kernel, since the JFFS2 file system driver in the kernel requires
MTD devices.
.SH OPTIONS
Options that take SIZE arguments can be specified as either
-decimal (e.g., 65536), octal (0200000), or hexidecimal (0x1000).
+decimal (e.g., 65536), octal (0200000), or hexadecimal (0x1000).
.TP
.B -p, --pad[=SIZE]
Pad output to SIZE bytes with 0xFF. If SIZE is not specified,
diff --git a/jffsX-utils/mkfs.jffs2.c b/jffsX-utils/mkfs.jffs2.c
index 9cc5eaf..b9dd96b 100644
--- a/jffsX-utils/mkfs.jffs2.c
+++ b/jffsX-utils/mkfs.jffs2.c
@@ -65,7 +65,7 @@
#include <ctype.h>
#include <time.h>
#include <getopt.h>
-#ifndef WITHOUT_XATTR
+#ifdef WITH_XATTR
#include <sys/xattr.h>
#include <sys/acl.h>
#endif
@@ -978,7 +978,7 @@ static void write_special_file(struct filesystem_entry *e)
padword();
}
-#ifndef WITHOUT_XATTR
+#ifdef WITH_XATTR
typedef struct xattr_entry {
struct xattr_entry *next;
uint32_t xid;
@@ -1209,7 +1209,7 @@ static void write_xattr_entry(struct filesystem_entry *e)
}
}
-#else /* WITHOUT_XATTR */
+#else /* WITH_XATTR */
#define write_xattr_entry(x)
#endif
@@ -1380,7 +1380,7 @@ static struct option long_options[] = {
{"test-compression", 0, NULL, 't'},
{"compressor-priority", 1, NULL, 'y'},
{"incremental", 1, NULL, 'i'},
-#ifndef WITHOUT_XATTR
+#ifdef WITH_XATTR
{"with-xattr", 0, NULL, 1000 },
{"with-selinux", 0, NULL, 1001 },
{"with-posix-acl", 0, NULL, 1002 },
@@ -1401,7 +1401,8 @@ static const char helptext[] =
" page size (default: 4KiB)\n"
" -e, --eraseblock=SIZE Use erase block size SIZE (default: 64KiB)\n"
" -c, --cleanmarker=SIZE Size of cleanmarker (default 12)\n"
-" -m, --compr-mode=MODE Select compression mode (default: priority)\n"
+" -m, --compression-mode=MODE\n"
+" Select compression mode (default: priority)\n"
" -x, --disable-compressor=COMPRESSOR_NAME\n"
" Disable a compressor\n"
" -X, --enable-compressor=COMPRESSOR_NAME\n"
@@ -1419,7 +1420,7 @@ static const char helptext[] =
" -q, --squash Squash permissions and owners making all files be owned by root\n"
" -U, --squash-uids Squash owners making all files be owned by root\n"
" -P, --squash-perms Squash permissions on all files\n"
-#ifndef WITHOUT_XATTR
+#ifdef WITH_XATTR
" --with-xattr stuff all xattr entries into image\n"
" --with-selinux stuff only SELinux Labels into jffs2 image\n"
" --with-posix-acl stuff only POSIX ACL entries into jffs2 image\n"
@@ -1744,7 +1745,7 @@ int main(int argc, char **argv)
sys_errmsg_die("cannot open (incremental) file");
}
break;
-#ifndef WITHOUT_XATTR
+#ifdef WITH_XATTR
case 1000: /* --with-xattr */
enable_xattr |= (1 << JFFS2_XPREFIX_USER)
| (1 << JFFS2_XPREFIX_SECURITY)
diff --git a/lib/Makemodule.am b/lib/Makemodule.am
index 5bee5b6..570896b 100644
--- a/lib/Makemodule.am
+++ b/lib/Makemodule.am
@@ -1,27 +1,45 @@
libmtd_a_SOURCES = \
lib/libmtd.c \
+ include/libmtd.h \
lib/libfec.c \
+ include/libfec.h \
lib/common.c \
+ include/common.h \
lib/libcrc32.c \
+ include/crc32.h \
lib/libmtd_legacy.c \
- lib/libmtd_int.h
+ lib/libmtd_int.h \
+ include/xalloc.h \
+ include/mtd/mtd-user.h \
+ include/mtd/mtd-abi.h
libmissing_a_SOURCES = \
- lib/execinfo.c
+ lib/execinfo.c \
+ include/libmissing.h
libubi_a_SOURCES = \
lib/libubi.c \
- lib/libubi_int.h
+ lib/libubi_int.h \
+ include/libubi.h \
+ include/mtd/ubi-user.h
libubigen_a_SOURCES = \
- lib/libubigen.c
+ lib/libubigen.c \
+ include/libubigen.h \
+ include/mtd_swab.h \
+ include/mtd/ubi-media.h
libscan_a_SOURCES = \
- lib/libscan.c
+ lib/libscan.c \
+ include/libscan.h \
+ include/mtd_swab.h \
+ include/mtd/ubi-media.h
libiniparser_a_SOURCES = \
lib/libiniparser.c \
- lib/dictionary.c
+ include/libiniparser.h \
+ lib/dictionary.c \
+ include/dictionary.h
EXTRA_DIST += lib/LICENSE.libiniparser
diff --git a/lib/common.c b/lib/common.c
index 8041878..e278593 100644
--- a/lib/common.c
+++ b/lib/common.c
@@ -33,6 +33,9 @@
#include <stdlib.h>
#include <unistd.h>
#include "common.h"
+#include "libmtd.h"
+
+#define MTD_DEV_PATT "/dev/mtd%d"
/**
* get_multiplier - convert size specifier to an integer multiplier.
@@ -162,3 +165,46 @@ int util_srand(void)
srand(seed);
return 0;
}
+
+/**
+ * mtd_find_dev_node - Find the device node for an MTD
+ * @id: Identifier for the MTD. this can be the device node itself, or
+ * "mtd:<name>" to look up MTD by name
+ *
+ * This is a helper function to convert MTD device identifiers into their
+ * device node.
+ *
+ * Returns a pointer to a string containing the device node that must be
+ * free'd, or NULL on failure.
+ */
+char *mtd_find_dev_node(const char *id)
+{
+ struct mtd_dev_info info;
+ struct libmtd_t *lib_mtd;
+ char *node;
+ int ret;
+
+ if (strncmp(id, "mtd:", 4)) {
+ /* Assume @id is the device node */
+ return strdup(id);
+ }
+
+ /* Search for MTD matching name */
+ id += 4;
+
+ lib_mtd = libmtd_open();
+ if (!lib_mtd)
+ return NULL;
+
+ ret = mtd_get_dev_info2(lib_mtd, id, &info);
+ libmtd_close(lib_mtd);
+ if (ret < 0)
+ return NULL;
+
+ node = malloc(strlen(MTD_DEV_PATT) + 20);
+ if (!node)
+ return NULL;
+
+ sprintf(node, MTD_DEV_PATT, info.mtd_num);
+ return node;
+}
diff --git a/lib/libmtd.c b/lib/libmtd.c
index 9d8d0e8..f588e09 100644
--- a/lib/libmtd.c
+++ b/lib/libmtd.c
@@ -1,6 +1,7 @@
/*
* Copyright (c) International Business Machines Corp., 2006
* Copyright (C) 2009 Nokia Corporation
+ * Copyright 2021 NXP
*
* 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
@@ -426,7 +427,7 @@ static int type_str2int(const char *str)
/**
* dev_node2num - find MTD device number by its character device node.
* @lib: MTD library descriptor
- * @node: name of the MTD device node
+ * @node: path of the MTD device node
* @mtd_num: MTD device number is returned here
*
* This function returns %0 in case of success and %-1 in case of failure.
@@ -476,6 +477,58 @@ static int dev_node2num(struct libmtd *lib, const char *node, int *mtd_num)
}
/**
+ * dev_name2num - find MTD device number by its MTD name
+ * @lib: MTD library descriptor
+ * @name: name of the MTD device
+ * @mtd_num: MTD device number is returned here
+ *
+ * This function returns %0 in case of success and %-1 in case of failure.
+ */
+static int dev_name2num(struct libmtd *lib, const char *name, int *mtd_num)
+{
+ struct mtd_info info;
+ char name2[MTD_NAME_MAX + 1];
+ int i, mtd_num_tmp = -1;
+
+ if (mtd_get_info((libmtd_t *)lib, &info))
+ return -1;
+
+ for (i = info.lowest_mtd_num; i <= info.highest_mtd_num; i++) {
+ int ret;
+
+ ret = dev_read_data(lib->mtd_name, i, name2,
+ MTD_NAME_MAX + 1);
+ if (ret < 0) {
+ if (errno == ENOENT)
+ continue;
+ if (!errno)
+ break;
+ return -1;
+ }
+ name2[ret - 1] = '\0';
+
+ if (!strcmp(name, name2)) {
+ // Device name collision
+ if (mtd_num_tmp >= 0) {
+ errmsg("Multiple MTD's found matching name %s", name);
+ errno = ENODEV;
+ return -1;
+ }
+
+ mtd_num_tmp = i;
+ }
+ }
+
+ if (mtd_num_tmp < 0) {
+ errno = ENODEV;
+ return -1;
+ }
+
+ *mtd_num = mtd_num_tmp;
+ return 0;
+}
+
+/**
* sysfs_is_supported - check whether the MTD sub-system supports MTD.
* @lib: MTD library descriptor
*
@@ -791,7 +844,10 @@ int mtd_get_dev_info1(libmtd_t desc, int mtd_num, struct mtd_dev_info *mtd)
return -1;
mtd->writable = !!(ret & MTD_WRITEABLE);
- mtd->eb_cnt = mtd->size / mtd->eb_size;
+ if ((ret & MTD_NO_ERASE) && (mtd->eb_size == 0))
+ mtd->eb_cnt = 1;
+ else
+ mtd->eb_cnt = mtd->size / mtd->eb_size;
mtd->type = type_str2int(mtd->type_str);
mtd->bb_allowed = !!(mtd->type == MTD_NANDFLASH ||
mtd->type == MTD_MLCNANDFLASH);
@@ -813,6 +869,20 @@ int mtd_get_dev_info(libmtd_t desc, const char *node, struct mtd_dev_info *mtd)
return mtd_get_dev_info1(desc, mtd_num, mtd);
}
+int mtd_get_dev_info2(libmtd_t desc, const char *name, struct mtd_dev_info *mtd)
+{
+ int mtd_num;
+ struct libmtd *lib = (struct libmtd *)desc;
+
+ if (!lib->sysfs_supported)
+ return legacy_get_dev_info2(name, mtd);
+
+ if (dev_name2num(lib, name, &mtd_num))
+ return -1;
+
+ return mtd_get_dev_info1(desc, mtd_num, mtd);
+}
+
static inline int mtd_ioctl_error(const struct mtd_dev_info *mtd, int eb,
const char *sreq)
{
@@ -831,8 +901,8 @@ static int mtd_valid_erase_block(const struct mtd_dev_info *mtd, int eb)
return 0;
}
-static int mtd_xlock(const struct mtd_dev_info *mtd, int fd, int eb, int req,
- const char *sreq)
+static int mtd_xlock(const struct mtd_dev_info *mtd, int fd, int eb,
+ int blocks, int req, const char *sreq)
{
int ret;
struct erase_info_user ei;
@@ -841,8 +911,14 @@ static int mtd_xlock(const struct mtd_dev_info *mtd, int fd, int eb, int req,
if (ret)
return ret;
+ if (blocks > 1) {
+ ret = mtd_valid_erase_block(mtd, eb + blocks - 1);
+ if (ret)
+ return ret;
+ }
+
ei.start = eb * mtd->eb_size;
- ei.length = mtd->eb_size;
+ ei.length = mtd->eb_size * blocks;
ret = ioctl(fd, req, &ei);
if (ret < 0)
@@ -850,16 +926,23 @@ static int mtd_xlock(const struct mtd_dev_info *mtd, int fd, int eb, int req,
return 0;
}
-#define mtd_xlock(mtd, fd, eb, req) mtd_xlock(mtd, fd, eb, req, #req)
+#define mtd_xlock(mtd, fd, eb, blocks, req) \
+ mtd_xlock(mtd, fd, eb, blocks, req, #req)
int mtd_lock(const struct mtd_dev_info *mtd, int fd, int eb)
{
- return mtd_xlock(mtd, fd, eb, MEMLOCK);
+ return mtd_xlock(mtd, fd, eb, 1, MEMLOCK);
}
int mtd_unlock(const struct mtd_dev_info *mtd, int fd, int eb)
{
- return mtd_xlock(mtd, fd, eb, MEMUNLOCK);
+ return mtd_xlock(mtd, fd, eb, 1, MEMUNLOCK);
+}
+
+int mtd_unlock_multi(const struct mtd_dev_info *mtd, int fd, int eb,
+ int blocks)
+{
+ return mtd_xlock(mtd, fd, eb, blocks, MEMUNLOCK);
}
int mtd_erase_multi(libmtd_t desc, const struct mtd_dev_info *mtd,
diff --git a/lib/libmtd_int.h b/lib/libmtd_int.h
index c0514d2..79200f7 100644
--- a/lib/libmtd_int.h
+++ b/lib/libmtd_int.h
@@ -106,6 +106,7 @@ int legacy_dev_present(int mtd_num);
int legacy_mtd_get_info(struct mtd_info *info);
int legacy_get_dev_info(const char *node, struct mtd_dev_info *mtd);
int legacy_get_dev_info1(int dev_num, struct mtd_dev_info *mtd);
+int legacy_get_dev_info2(const char *name, struct mtd_dev_info *mtd);
int legacy_get_mtd_oobavail(const char *node);
int legacy_get_mtd_oobavail1(int mtd_num);
diff --git a/lib/libmtd_legacy.c b/lib/libmtd_legacy.c
index 4eb4a70..e0ecf49 100644
--- a/lib/libmtd_legacy.c
+++ b/lib/libmtd_legacy.c
@@ -428,3 +428,41 @@ int legacy_get_dev_info1(int mtd_num, struct mtd_dev_info *mtd)
sprintf(node, MTD_DEV_PATT, mtd_num);
return legacy_get_dev_info(node, mtd);
}
+
+/**
+ * legacy_get_dev_info2 - legacy version of `mtd_get_dev_info2()`
+ * @name: name of the MTD device
+ * @mtd: the MTD device information is returned here
+ *
+ * This function is similar to 'mtd_get_dev_info2()' and has the same
+ * conventions.
+ */
+int legacy_get_dev_info2(const char *name, struct mtd_dev_info *mtd)
+{
+ struct proc_parse_info pi;
+ int ret, mtd_num = -1;
+
+ ret = proc_parse_start(&pi);
+ if (ret)
+ return -1;
+
+ while (proc_parse_next(&pi)) {
+ if (!strcmp(name, pi.name)) {
+ // Device name collision
+ if (mtd_num >= 0) {
+ errmsg("Multiple MTD's found matching name %s", name);
+ errno = ENODEV;
+ return -1;
+ }
+
+ mtd_num = pi.mtd_num;
+ }
+ }
+
+ if (mtd_num < 0) {
+ errno = ENODEV;
+ return -1;
+ }
+
+ return legacy_get_dev_info1(mtd_num, mtd);
+}
diff --git a/lib/libubi.c b/lib/libubi.c
index baaca2f..6b57e50 100644
--- a/lib/libubi.c
+++ b/lib/libubi.c
@@ -767,6 +767,8 @@ int ubi_attach(libubi_t desc, const char *node, struct ubi_attach_request *req)
r.ubi_num = req->dev_num;
r.mtd_num = req->mtd_num;
r.vid_hdr_offset = req->vid_hdr_offset;
+ r.disable_fm = req->disable_fm ? 1 : 0;
+ r.need_resv_pool = req->need_resv_pool ? 1 : 0;
if (req->max_beb_per1024) {
/*
diff --git a/m4/ac_define_dir.m4 b/m4/ac_define_dir.m4
new file mode 100644
index 0000000..3b48c8b
--- /dev/null
+++ b/m4/ac_define_dir.m4
@@ -0,0 +1,35 @@
+dnl @synopsis AC_DEFINE_DIR(VARNAME, DIR [, DESCRIPTION])
+dnl
+dnl This macro sets VARNAME to the expansion of the DIR variable,
+dnl taking care of fixing up ${prefix} and such.
+dnl
+dnl VARNAME is then offered as both an output variable and a C
+dnl preprocessor symbol.
+dnl
+dnl Example:
+dnl
+dnl AC_DEFINE_DIR([DATADIR], [datadir], [Where data are placed to.])
+dnl
+dnl @category Misc
+dnl @author Stepan Kasal <kasal@ucw.cz>
+dnl @author Andreas Schwab <schwab@suse.de>
+dnl @author Guido U. Draheim <guidod@gmx.de>
+dnl @author Alexandre Oliva
+dnl @version 2006-10-13
+dnl @license AllPermissive
+
+AC_DEFUN([AC_DEFINE_DIR], [
+ prefix_NONE=
+ exec_prefix_NONE=
+ test "x$prefix" = xNONE && prefix_NONE=yes && prefix=$ac_default_prefix
+ test "x$exec_prefix" = xNONE && exec_prefix_NONE=yes && exec_prefix=$prefix
+dnl In Autoconf 2.60, ${datadir} refers to ${datarootdir}, which in turn
+dnl refers to ${prefix}. Thus we have to use `eval' twice.
+ eval ac_define_dir="\"[$]$2\""
+ eval ac_define_dir="\"$ac_define_dir\""
+ AC_SUBST($1, "$ac_define_dir")
+ AC_DEFINE_UNQUOTED($1, "$ac_define_dir", [$3])
+ test "$prefix_NONE" && prefix=NONE
+ test "$exec_prefix_NONE" && exec_prefix=NONE
+])
+
diff --git a/m4/ax_pthread.m4 b/m4/ax_pthread.m4
index 82ce2b9..9f35d13 100644
--- a/m4/ax_pthread.m4
+++ b/m4/ax_pthread.m4
@@ -1,5 +1,5 @@
# ===========================================================================
-# http://www.gnu.org/software/autoconf-archive/ax_pthread.html
+# https://www.gnu.org/software/autoconf-archive/ax_pthread.html
# ===========================================================================
#
# SYNOPSIS
@@ -14,20 +14,24 @@
# flags that are needed. (The user can also force certain compiler
# flags/libs to be tested by setting these environment variables.)
#
-# Also sets PTHREAD_CC to any special C compiler that is needed for
-# multi-threaded programs (defaults to the value of CC otherwise). (This
-# is necessary on AIX to use the special cc_r compiler alias.)
+# Also sets PTHREAD_CC and PTHREAD_CXX to any special C compiler that is
+# needed for multi-threaded programs (defaults to the value of CC
+# respectively CXX otherwise). (This is necessary on e.g. AIX to use the
+# special cc_r/CC_r compiler alias.)
#
# NOTE: You are assumed to not only compile your program with these flags,
# but also to link with them as well. For example, you might link with
# $PTHREAD_CC $CFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS $LIBS
+# $PTHREAD_CXX $CXXFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS $LIBS
#
# If you are only building threaded programs, you may wish to use these
# variables in your default LIBS, CFLAGS, and CC:
#
# LIBS="$PTHREAD_LIBS $LIBS"
# CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+# CXXFLAGS="$CXXFLAGS $PTHREAD_CFLAGS"
# CC="$PTHREAD_CC"
+# CXX="$PTHREAD_CXX"
#
# In addition, if the PTHREAD_CREATE_JOINABLE thread-attribute constant
# has a nonstandard name, this macro defines PTHREAD_CREATE_JOINABLE to
@@ -55,6 +59,7 @@
#
# Copyright (c) 2008 Steven G. Johnson <stevenj@alum.mit.edu>
# Copyright (c) 2011 Daniel Richard G. <skunk@iSKUNK.ORG>
+# Copyright (c) 2019 Marc Stevens <marc.stevens@cwi.nl>
#
# 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
@@ -67,7 +72,7 @@
# Public License for more details.
#
# You should have received a copy of the GNU General Public License along
-# with this program. If not, see <http://www.gnu.org/licenses/>.
+# with this program. If not, see <https://www.gnu.org/licenses/>.
#
# As a special exception, the respective Autoconf Macro's copyright owner
# gives unlimited permission to copy, distribute and modify the configure
@@ -82,7 +87,7 @@
# modified version of the Autoconf Macro, you may extend this special
# exception to the GPL to apply to your modified version as well.
-#serial 23
+#serial 31
AU_ALIAS([ACX_PTHREAD], [AX_PTHREAD])
AC_DEFUN([AX_PTHREAD], [
@@ -104,6 +109,7 @@ if test "x$PTHREAD_CFLAGS$PTHREAD_LIBS" != "x"; then
ax_pthread_save_CFLAGS="$CFLAGS"
ax_pthread_save_LIBS="$LIBS"
AS_IF([test "x$PTHREAD_CC" != "x"], [CC="$PTHREAD_CC"])
+ AS_IF([test "x$PTHREAD_CXX" != "x"], [CXX="$PTHREAD_CXX"])
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
LIBS="$PTHREAD_LIBS $LIBS"
AC_MSG_CHECKING([for pthread_join using $CC $PTHREAD_CFLAGS $PTHREAD_LIBS])
@@ -123,10 +129,12 @@ fi
# (e.g. DEC) have both -lpthread and -lpthreads, where one of the
# libraries is broken (non-POSIX).
-# Create a list of thread flags to try. Items starting with a "-" are
-# C compiler flags, and other items are library names, except for "none"
-# which indicates that we try without any flags at all, and "pthread-config"
-# which is a program returning the flags for the Pth emulation library.
+# Create a list of thread flags to try. Items with a "," contain both
+# C compiler flags (before ",") and linker flags (after ","). Other items
+# starting with a "-" are C compiler flags, and remaining items are
+# library names, except for "none" which indicates that we try without
+# any flags at all, and "pthread-config" which is a program returning
+# the flags for the Pth emulation library.
ax_pthread_flags="pthreads none -Kthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config"
@@ -194,14 +202,47 @@ case $host_os in
# that too in a future libc.) So we'll check first for the
# standard Solaris way of linking pthreads (-mt -lpthread).
- ax_pthread_flags="-mt,pthread pthread $ax_pthread_flags"
+ ax_pthread_flags="-mt,-lpthread pthread $ax_pthread_flags"
;;
esac
+# Are we compiling with Clang?
+
+AC_CACHE_CHECK([whether $CC is Clang],
+ [ax_cv_PTHREAD_CLANG],
+ [ax_cv_PTHREAD_CLANG=no
+ # Note that Autoconf sets GCC=yes for Clang as well as GCC
+ if test "x$GCC" = "xyes"; then
+ AC_EGREP_CPP([AX_PTHREAD_CC_IS_CLANG],
+ [/* Note: Clang 2.7 lacks __clang_[a-z]+__ */
+# if defined(__clang__) && defined(__llvm__)
+ AX_PTHREAD_CC_IS_CLANG
+# endif
+ ],
+ [ax_cv_PTHREAD_CLANG=yes])
+ fi
+ ])
+ax_pthread_clang="$ax_cv_PTHREAD_CLANG"
+
+
# GCC generally uses -pthread, or -pthreads on some platforms (e.g. SPARC)
+# Note that for GCC and Clang -pthread generally implies -lpthread,
+# except when -nostdlib is passed.
+# This is problematic using libtool to build C++ shared libraries with pthread:
+# [1] https://gcc.gnu.org/bugzilla/show_bug.cgi?id=25460
+# [2] https://bugzilla.redhat.com/show_bug.cgi?id=661333
+# [3] https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=468555
+# To solve this, first try -pthread together with -lpthread for GCC
+
AS_IF([test "x$GCC" = "xyes"],
- [ax_pthread_flags="-pthread -pthreads $ax_pthread_flags"])
+ [ax_pthread_flags="-pthread,-lpthread -pthread -pthreads $ax_pthread_flags"])
+
+# Clang takes -pthread (never supported any other flag), but we'll try with -lpthread first
+
+AS_IF([test "x$ax_pthread_clang" = "xyes"],
+ [ax_pthread_flags="-pthread,-lpthread -pthread"])
+
# The presence of a feature test macro requesting re-entrant function
# definitions is, on some systems, a strong hint that pthreads support is
@@ -224,25 +265,86 @@ AS_IF([test "x$ax_pthread_check_macro" = "x--"],
[ax_pthread_check_cond=0],
[ax_pthread_check_cond="!defined($ax_pthread_check_macro)"])
-# Are we compiling with Clang?
-AC_CACHE_CHECK([whether $CC is Clang],
- [ax_cv_PTHREAD_CLANG],
- [ax_cv_PTHREAD_CLANG=no
- # Note that Autoconf sets GCC=yes for Clang as well as GCC
- if test "x$GCC" = "xyes"; then
- AC_EGREP_CPP([AX_PTHREAD_CC_IS_CLANG],
- [/* Note: Clang 2.7 lacks __clang_[a-z]+__ */
-# if defined(__clang__) && defined(__llvm__)
- AX_PTHREAD_CC_IS_CLANG
-# endif
- ],
- [ax_cv_PTHREAD_CLANG=yes])
- fi
- ])
-ax_pthread_clang="$ax_cv_PTHREAD_CLANG"
+if test "x$ax_pthread_ok" = "xno"; then
+for ax_pthread_try_flag in $ax_pthread_flags; do
+
+ case $ax_pthread_try_flag in
+ none)
+ AC_MSG_CHECKING([whether pthreads work without any flags])
+ ;;
+
+ *,*)
+ PTHREAD_CFLAGS=`echo $ax_pthread_try_flag | sed "s/^\(.*\),\(.*\)$/\1/"`
+ PTHREAD_LIBS=`echo $ax_pthread_try_flag | sed "s/^\(.*\),\(.*\)$/\2/"`
+ AC_MSG_CHECKING([whether pthreads work with "$PTHREAD_CFLAGS" and "$PTHREAD_LIBS"])
+ ;;
+
+ -*)
+ AC_MSG_CHECKING([whether pthreads work with $ax_pthread_try_flag])
+ PTHREAD_CFLAGS="$ax_pthread_try_flag"
+ ;;
+
+ pthread-config)
+ AC_CHECK_PROG([ax_pthread_config], [pthread-config], [yes], [no])
+ AS_IF([test "x$ax_pthread_config" = "xno"], [continue])
+ PTHREAD_CFLAGS="`pthread-config --cflags`"
+ PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`"
+ ;;
+
+ *)
+ AC_MSG_CHECKING([for the pthreads library -l$ax_pthread_try_flag])
+ PTHREAD_LIBS="-l$ax_pthread_try_flag"
+ ;;
+ esac
+
+ ax_pthread_save_CFLAGS="$CFLAGS"
+ ax_pthread_save_LIBS="$LIBS"
+ CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+ LIBS="$PTHREAD_LIBS $LIBS"
+
+ # Check for various functions. We must include pthread.h,
+ # since some functions may be macros. (On the Sequent, we
+ # need a special flag -Kthread to make this header compile.)
+ # We check for pthread_join because it is in -lpthread on IRIX
+ # while pthread_create is in libc. We check for pthread_attr_init
+ # due to DEC craziness with -lpthreads. We check for
+ # pthread_cleanup_push because it is one of the few pthread
+ # functions on Solaris that doesn't have a non-functional libc stub.
+ # We try pthread_create on general principles.
+
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <pthread.h>
+# if $ax_pthread_check_cond
+# error "$ax_pthread_check_macro must be defined"
+# endif
+ static void *some_global = NULL;
+ static void routine(void *a)
+ {
+ /* To avoid any unused-parameter or
+ unused-but-set-parameter warning. */
+ some_global = a;
+ }
+ static void *start_routine(void *a) { return a; }],
+ [pthread_t th; pthread_attr_t attr;
+ pthread_create(&th, 0, start_routine, 0);
+ pthread_join(th, 0);
+ pthread_attr_init(&attr);
+ pthread_cleanup_push(routine, 0);
+ pthread_cleanup_pop(0) /* ; */])],
+ [ax_pthread_ok=yes],
+ [])
+
+ CFLAGS="$ax_pthread_save_CFLAGS"
+ LIBS="$ax_pthread_save_LIBS"
+
+ AC_MSG_RESULT([$ax_pthread_ok])
+ AS_IF([test "x$ax_pthread_ok" = "xyes"], [break])
+
+ PTHREAD_LIBS=""
+ PTHREAD_CFLAGS=""
+done
+fi
-ax_pthread_clang_warning=no
# Clang needs special handling, because older versions handle the -pthread
# option in a rather... idiosyncratic way
@@ -261,11 +363,6 @@ if test "x$ax_pthread_clang" = "xyes"; then
# -pthread does define _REENTRANT, and while the Darwin headers
# ignore this macro, third-party headers might not.)
- PTHREAD_CFLAGS="-pthread"
- PTHREAD_LIBS=
-
- ax_pthread_ok=yes
-
# However, older versions of Clang make a point of warning the user
# that, in an invocation where only linking and no compilation is
# taking place, the -pthread option has no effect ("argument unused
@@ -294,7 +391,7 @@ if test "x$ax_pthread_clang" = "xyes"; then
# step
ax_pthread_save_ac_link="$ac_link"
ax_pthread_sed='s/conftest\.\$ac_ext/conftest.$ac_objext/g'
- ax_pthread_link_step=`$as_echo "$ac_link" | sed "$ax_pthread_sed"`
+ ax_pthread_link_step=`AS_ECHO(["$ac_link"]) | sed "$ax_pthread_sed"`
ax_pthread_2step_ac_link="($ac_compile) && (echo ==== >&5) && ($ax_pthread_link_step)"
ax_pthread_save_CFLAGS="$CFLAGS"
for ax_pthread_try in '' -Qunused-arguments -Wno-unused-command-line-argument unknown; do
@@ -320,78 +417,7 @@ if test "x$ax_pthread_clang" = "xyes"; then
fi # $ax_pthread_clang = yes
-if test "x$ax_pthread_ok" = "xno"; then
-for ax_pthread_try_flag in $ax_pthread_flags; do
-
- case $ax_pthread_try_flag in
- none)
- AC_MSG_CHECKING([whether pthreads work without any flags])
- ;;
-
- -mt,pthread)
- AC_MSG_CHECKING([whether pthreads work with -mt -lpthread])
- PTHREAD_CFLAGS="-mt"
- PTHREAD_LIBS="-lpthread"
- ;;
-
- -*)
- AC_MSG_CHECKING([whether pthreads work with $ax_pthread_try_flag])
- PTHREAD_CFLAGS="$ax_pthread_try_flag"
- ;;
-
- pthread-config)
- AC_CHECK_PROG([ax_pthread_config], [pthread-config], [yes], [no])
- AS_IF([test "x$ax_pthread_config" = "xno"], [continue])
- PTHREAD_CFLAGS="`pthread-config --cflags`"
- PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`"
- ;;
-
- *)
- AC_MSG_CHECKING([for the pthreads library -l$ax_pthread_try_flag])
- PTHREAD_LIBS="-l$ax_pthread_try_flag"
- ;;
- esac
-
- ax_pthread_save_CFLAGS="$CFLAGS"
- ax_pthread_save_LIBS="$LIBS"
- CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
- LIBS="$PTHREAD_LIBS $LIBS"
-
- # Check for various functions. We must include pthread.h,
- # since some functions may be macros. (On the Sequent, we
- # need a special flag -Kthread to make this header compile.)
- # We check for pthread_join because it is in -lpthread on IRIX
- # while pthread_create is in libc. We check for pthread_attr_init
- # due to DEC craziness with -lpthreads. We check for
- # pthread_cleanup_push because it is one of the few pthread
- # functions on Solaris that doesn't have a non-functional libc stub.
- # We try pthread_create on general principles.
-
- AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <pthread.h>
-# if $ax_pthread_check_cond
-# error "$ax_pthread_check_macro must be defined"
-# endif
- static void routine(void *a) { a = 0; }
- static void *start_routine(void *a) { return a; }],
- [pthread_t th; pthread_attr_t attr;
- pthread_create(&th, 0, start_routine, 0);
- pthread_join(th, 0);
- pthread_attr_init(&attr);
- pthread_cleanup_push(routine, 0);
- pthread_cleanup_pop(0) /* ; */])],
- [ax_pthread_ok=yes],
- [])
-
- CFLAGS="$ax_pthread_save_CFLAGS"
- LIBS="$ax_pthread_save_LIBS"
- AC_MSG_RESULT([$ax_pthread_ok])
- AS_IF([test "x$ax_pthread_ok" = "xyes"], [break])
-
- PTHREAD_LIBS=""
- PTHREAD_CFLAGS=""
-done
-fi
# Various other checks:
if test "x$ax_pthread_ok" = "xyes"; then
@@ -438,7 +464,8 @@ if test "x$ax_pthread_ok" = "xyes"; then
AC_CACHE_CHECK([for PTHREAD_PRIO_INHERIT],
[ax_cv_PTHREAD_PRIO_INHERIT],
[AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <pthread.h>]],
- [[int i = PTHREAD_PRIO_INHERIT;]])],
+ [[int i = PTHREAD_PRIO_INHERIT;
+ return i;]])],
[ax_cv_PTHREAD_PRIO_INHERIT=yes],
[ax_cv_PTHREAD_PRIO_INHERIT=no])
])
@@ -460,18 +487,28 @@ if test "x$ax_pthread_ok" = "xyes"; then
[#handle absolute path differently from PATH based program lookup
AS_CASE(["x$CC"],
[x/*],
- [AS_IF([AS_EXECUTABLE_P([${CC}_r])],[PTHREAD_CC="${CC}_r"])],
- [AC_CHECK_PROGS([PTHREAD_CC],[${CC}_r],[$CC])])])
+ [
+ AS_IF([AS_EXECUTABLE_P([${CC}_r])],[PTHREAD_CC="${CC}_r"])
+ AS_IF([test "x${CXX}" != "x"], [AS_IF([AS_EXECUTABLE_P([${CXX}_r])],[PTHREAD_CXX="${CXX}_r"])])
+ ],
+ [
+ AC_CHECK_PROGS([PTHREAD_CC],[${CC}_r],[$CC])
+ AS_IF([test "x${CXX}" != "x"], [AC_CHECK_PROGS([PTHREAD_CXX],[${CXX}_r],[$CXX])])
+ ]
+ )
+ ])
;;
esac
fi
fi
test -n "$PTHREAD_CC" || PTHREAD_CC="$CC"
+test -n "$PTHREAD_CXX" || PTHREAD_CXX="$CXX"
AC_SUBST([PTHREAD_LIBS])
AC_SUBST([PTHREAD_CFLAGS])
AC_SUBST([PTHREAD_CC])
+AC_SUBST([PTHREAD_CXX])
# Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND:
if test "x$ax_pthread_ok" = "xyes"; then
@@ -483,4 +520,3 @@ else
fi
AC_LANG_POP
])dnl AX_PTHREAD
-
diff --git a/misc-utils/Makemodule.am b/misc-utils/Makemodule.am
index 2289252..1ce1a68 100644
--- a/misc-utils/Makemodule.am
+++ b/misc-utils/Makemodule.am
@@ -1,24 +1,34 @@
-ftl_format_SOURCES = misc-utils/ftl_format.c
+ftl_format_SOURCES = misc-utils/ftl_format.c include/mtd_swab.h
+ftl_format_SOURCES += include/mtd/ftl-user.h
doc_loadbios_SOURCES = misc-utils/doc_loadbios.c
-ftl_check_SOURCES = misc-utils/ftl_check.c
+ftl_check_SOURCES = misc-utils/ftl_check.c include/mtd_swab.h
+ftl_check_SOURCES += include/mtd/ftl-user.h
mtd_debug_SOURCES = misc-utils/mtd_debug.c
+mtd_debug_LDADD = libmtd.a
mtdpart_SOURCES = misc-utils/mtdpart.c
+mtdpart_LDADD = libmtd.a
-docfdisk_SOURCES = misc-utils/docfdisk.c
+docfdisk_SOURCES = misc-utils/docfdisk.c include/mtd_swab.h
+docfdisk_SOURCES += include/mtd/inftl-user.h include/mtd/ftl-user.h
-serve_image_SOURCES = misc-utils/serve_image.c
+serve_image_SOURCES = misc-utils/serve_image.c misc-utils/mcast_image.h
serve_image_LDADD = libmtd.a
-recv_image_SOURCES = misc-utils/recv_image.c
+recv_image_SOURCES = misc-utils/recv_image.c misc-utils/mcast_image.h
recv_image_LDADD = libmtd.a
+fectest_SOURCES = misc-utils/fectest.c misc-utils/mcast_image.h
+fectest_LDADD = libmtd.a
+
flash_lock_SOURCES = misc-utils/flash_lock.c
+flash_lock_LDADD = libmtd.a
flash_unlock_SOURCES = misc-utils/flash_unlock.c
+flash_unlock_LDADD = libmtd.a
flash_otp_info_SOURCES = misc-utils/flash_otp_info.c
@@ -26,42 +36,34 @@ flash_otp_dump_SOURCES = misc-utils/flash_otp_dump.c
flash_otp_lock_SOURCES = misc-utils/flash_otp_lock.c
+flash_otp_erase_SOURCES = misc-utils/flash_otp_erase.c
+
flash_otp_write_SOURCES = misc-utils/flash_otp_write.c
flashcp_SOURCES = misc-utils/flashcp.c
+flashcp_LDADD = libmtd.a
flash_erase_SOURCES = misc-utils/flash_erase.c
flash_erase_LDADD = libmtd.a
-MISC_BINS = \
+sbin_PROGRAMS += \
ftl_format doc_loadbios ftl_check mtd_debug docfdisk \
- serve_image recv_image flash_erase flash_lock \
+ serve_image recv_image fectest flash_erase flash_lock \
flash_unlock flash_otp_info flash_otp_dump flash_otp_lock \
- flash_otp_write flashcp mtdpart
+ flash_otp_erase flash_otp_write flashcp mtdpart
MISC_SH = \
misc-utils/flash_eraseall
-MISC_EXTRA = \
- misc-utils/MAKEDEV
-
-MISC_HEADER = \
- misc-utils/mcast_image.h \
- misc-utils/lsmtd.h
-
-MISC_MAN =
-
if BUILD_LSMTD
-lsmtd_SOURCES = misc-utils/lsmtd.c misc-utils/lsmtd_scan.c
+lsmtd_SOURCES = misc-utils/lsmtd.c misc-utils/lsmtd_scan.c misc-utils/lsmtd.h
lsmtd_LDADD = libmtd.a libubi.a
lsmtd_CPPFLAGS = $(AM_CPPFLAGS) -I$(top_srcdir)/misc-utils
-MISC_BINS += lsmtd
-MISC_MAN += misc-utils/lsmtd.8
+sbin_PROGRAMS += lsmtd
+dist_man8_MANS += misc-utils/lsmtd.8
endif
-EXTRA_DIST += $(MISC_HEADER) $(MISC_EXTRA) $(MISC_SH)
+EXTRA_DIST += misc-utils/MAKEDEV $(MISC_SH)
-dist_man8_MANS += $(MISC_MAN)
-sbin_PROGRAMS += $(MISC_BINS)
sbin_SCRIPTS += $(MISC_SH)
diff --git a/misc-utils/fectest.c b/misc-utils/fectest.c
index fcba513..f560f2b 100644
--- a/misc-utils/fectest.c
+++ b/misc-utils/fectest.c
@@ -21,7 +21,7 @@ int main(void)
unsigned char buf[NR_PKTS * PKT_SIZE];
unsigned char pktbuf[(NR_PKTS + DROPS) * PKT_SIZE];
struct fec_parms *fec;
- unsigned char *srcs[NR_PKTS];
+ unsigned char *srcs[NR_PKTS + DROPS];
unsigned char *pkt[NR_PKTS + DROPS];
int pktnr[NR_PKTS + DROPS];
struct timeval then, now;
@@ -87,6 +87,6 @@ int main(void)
exit(1);
}
- printf("Decoded in %ld.%06lds\n", now.tv_sec, now.tv_usec);
+ printf("Decoded in %ld.%06lds\n", (long)now.tv_sec, (long)now.tv_usec);
return 0;
}
diff --git a/misc-utils/flash_erase.c b/misc-utils/flash_erase.c
index a7fc6a6..c6f6f66 100644
--- a/misc-utils/flash_erase.c
+++ b/misc-utils/flash_erase.c
@@ -2,6 +2,7 @@
Copyright (C) 2000 Arcom Control System Ltd
Copyright (C) 2010 Mike Frysinger <vapier@gentoo.org>
+ Copyright 2021 NXP
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
@@ -50,11 +51,10 @@ static int unlock; /* unlock sectors before erasing */
static struct jffs2_unknown_node cleanmarker;
int target_endian = __BYTE_ORDER;
-static void show_progress(struct mtd_dev_info *mtd, off_t start, int eb,
- int eb_start, int eb_cnt)
+static void show_progress(off_t start, int eb, int eb_start, int eb_cnt, int step)
{
bareverbose(!quiet, "\rErasing %d Kibyte @ %llx -- %2i %% complete ",
- mtd->eb_size / 1024, (unsigned long long)start, ((eb - eb_start) * 100) / eb_cnt);
+ step / 1024, (unsigned long long)start, ((eb - eb_start) * 100) / eb_cnt);
fflush(stdout);
}
@@ -64,13 +64,16 @@ static void display_help (void)
"Erase blocks of the specified MTD device.\n"
"Specify a count of 0 to erase to end of device.\n"
"\n"
- " -j, --jffs2 format the device for jffs2\n"
- " -N, --noskipbad don't skip bad blocks\n"
- " -u, --unlock unlock sectors before erasing\n"
- " -q, --quiet do not display progress messages\n"
- " --silent same as --quiet\n"
- " --help display this help and exit\n"
- " --version output version information and exit\n",
+ " -j, --jffs2 format the device for jffs2\n"
+ " -c, --cleanmarker=SIZE size of jffs2 cleanmarker (default 12)\n"
+ " -N, --noskipbad don't skip bad blocks\n"
+ " -u, --unlock unlock sectors before erasing\n"
+ " -q, --quiet do not display progress messages\n"
+ " --silent same as --quiet\n"
+ " --help display this help and exit\n"
+ " --version output version information and exit\n",
+ "\n"
+ " MTD_DEVICE MTD device node or 'mtd:<name>'\n"
PROGRAM_NAME);
}
@@ -88,14 +91,35 @@ static void display_version (void)
PROGRAM_NAME);
}
+static void clear_marker(libmtd_t mtd_desc, struct mtd_dev_info *mtd, int fd,
+ unsigned int eb, int cmlen, bool isNAND)
+{
+ off_t offset = (off_t)eb * mtd->eb_size;
+
+ /* write cleanmarker */
+ if (isNAND) {
+ if (mtd_write(mtd_desc, mtd, fd, eb, 0, NULL, 0, &cleanmarker, cmlen,
+ MTD_OPS_AUTO_OOB) != 0) {
+ sys_errmsg("%s: MTD writeoob failure", mtd_device);
+ return;
+ }
+ } else {
+ if (pwrite(fd, &cleanmarker, sizeof(cleanmarker), (loff_t)offset) != sizeof(cleanmarker)) {
+ sys_errmsg("%s: MTD write failure", mtd_device);
+ return;
+ }
+ }
+ verbose(!quiet, "%llx : Cleanmarker Updated.", (unsigned long long)offset);
+}
+
int main(int argc, char *argv[])
{
libmtd_t mtd_desc;
struct mtd_dev_info mtd;
- int fd, cmlen = 8;
+ int fd, cmlen = 8, cmsize = sizeof(cleanmarker);
unsigned long long start;
unsigned int eb, eb_start, eb_cnt;
- bool isNAND;
+ bool isNAND, erase_chip = false;
int error = 0;
off_t offset = 0;
@@ -104,11 +128,12 @@ int main(int argc, char *argv[])
*/
for (;;) {
int option_index = 0;
- static const char *short_options = "jNquVh";
+ static const char *short_options = "jc:NquVh";
static const struct option long_options[] = {
{"help", no_argument, 0, 'h'},
{"version", no_argument, 0, 'V'},
{"jffs2", no_argument, 0, 'j'},
+ {"cleanmarker", required_argument, 0, 'c'},
{"noskipbad", no_argument, 0, 'N'},
{"quiet", no_argument, 0, 'q'},
{"silent", no_argument, 0, 'q'},
@@ -132,6 +157,9 @@ int main(int argc, char *argv[])
case 'j':
jffs2 = 1;
break;
+ case 'c':
+ cmsize = atoi(optarg);
+ break;
case 'N':
noskipbad = 1;
break;
@@ -148,7 +176,9 @@ int main(int argc, char *argv[])
}
switch (argc - optind) {
case 3:
- mtd_device = argv[optind];
+ mtd_device = mtd_find_dev_node(argv[optind]);
+ if (!mtd_device)
+ return errmsg("Can't find MTD device %s", argv[optind]);
start = simple_strtoull(argv[optind + 1], &error);
eb_cnt = simple_strtoul(argv[optind + 2], &error);
break;
@@ -182,6 +212,10 @@ int main(int argc, char *argv[])
if (jffs2 && mtd.type == MTD_MLCNANDFLASH)
return errmsg("JFFS2 cannot support MLC NAND.");
+ if (jffs2 && cmsize < sizeof(cleanmarker))
+ return errmsg("cleanmarker size must be >= 12");
+ if (jffs2 && cmsize >= mtd.eb_size)
+ return errmsg("cleanmarker size must be < eraseblock size");
eb_start = start / mtd.eb_size;
@@ -191,7 +225,7 @@ int main(int argc, char *argv[])
cleanmarker.magic = cpu_to_je16 (JFFS2_MAGIC_BITMASK);
cleanmarker.nodetype = cpu_to_je16 (JFFS2_NODETYPE_CLEANMARKER);
if (!isNAND) {
- cleanmarker.totlen = cpu_to_je32(sizeof(cleanmarker));
+ cleanmarker.totlen = cpu_to_je32(cmsize);
} else {
cleanmarker.totlen = cpu_to_je32(8);
cmlen = min(mtd.oobavail, 8);
@@ -205,6 +239,47 @@ int main(int argc, char *argv[])
if (eb_cnt == 0)
eb_cnt = (mtd.size / mtd.eb_size) - eb_start;
+ if (eb_start == 0 && mtd.size == eb_cnt * mtd.eb_size)
+ erase_chip = true;
+
+ /* If MTD device may have bad eraseblocks,
+ * erase one by one each sector
+ */
+ if (noskipbad && mtd.bb_allowed)
+ erase_chip = false;
+
+ if (erase_chip) {
+ show_progress(0, eb_start, eb_start, eb_cnt, mtd.size);
+
+ if (unlock) {
+ if (mtd_unlock_multi(&mtd, fd, eb_start, eb_cnt) != 0) {
+ sys_errmsg("%s: MTD unlock entire chip failure." \
+ "Trying one by one each sector.",
+ mtd_device);
+ goto erase_each_sector;
+ }
+ }
+
+ if (mtd_erase_multi(mtd_desc, &mtd, fd, eb_start, eb_cnt) != 0) {
+ sys_errmsg("%s: MTD Erase entire chip failure" \
+ "Trying one by one each sector.",
+ mtd_device);
+ goto erase_each_sector;
+ }
+
+ show_progress(0, eb_start + eb_cnt, eb_start,
+ eb_cnt, mtd.size);
+
+ if (!jffs2)
+ goto out;
+
+ /* write cleanmarker */
+ for (eb = eb_start; eb < eb_start + eb_cnt; eb++)
+ clear_marker(mtd_desc, &mtd, fd, eb, cmlen, isNAND);
+ goto out;
+ }
+
+erase_each_sector:
for (eb = eb_start; eb < eb_start + eb_cnt; eb++) {
offset = (off_t)eb * mtd.eb_size;
@@ -223,7 +298,7 @@ int main(int argc, char *argv[])
}
}
- show_progress(&mtd, offset, eb, eb_start, eb_cnt);
+ show_progress(offset, eb, eb_start, eb_cnt, mtd.eb_size);
if (unlock) {
if (mtd_unlock(&mtd, fd, eb) != 0) {
@@ -237,26 +312,11 @@ int main(int argc, char *argv[])
continue;
}
- /* format for JFFS2 ? */
- if (!jffs2)
- continue;
-
- /* write cleanmarker */
- if (isNAND) {
- if (mtd_write(mtd_desc, &mtd, fd, eb, 0, NULL, 0, &cleanmarker, cmlen,
- MTD_OPS_AUTO_OOB) != 0) {
- sys_errmsg("%s: MTD writeoob failure", mtd_device);
- continue;
- }
- } else {
- if (pwrite(fd, &cleanmarker, sizeof(cleanmarker), (loff_t)offset) != sizeof(cleanmarker)) {
- sys_errmsg("%s: MTD write failure", mtd_device);
- continue;
- }
- }
- verbose(!quiet, " Cleanmarker Updated.");
+ if (jffs2)
+ clear_marker(mtd_desc, &mtd, fd, eb, cmlen, isNAND);
}
- show_progress(&mtd, offset, eb, eb_start, eb_cnt);
+ show_progress(offset, eb, eb_start, eb_cnt, mtd.eb_size);
+out:
bareverbose(!quiet, "\n");
return 0;
diff --git a/misc-utils/flash_otp_dump.c b/misc-utils/flash_otp_dump.c
index f1e1782..324d856 100644
--- a/misc-utils/flash_otp_dump.c
+++ b/misc-utils/flash_otp_dump.c
@@ -20,7 +20,7 @@ int main(int argc,char *argv[])
int offset = 0;
unsigned char buf[16];
- if (argc <= 3 || (strcmp(argv[1], "-f") && strcmp(argv[1], "-u"))) {
+ if (argc < 3 || (strcmp(argv[1], "-f") && strcmp(argv[1], "-u"))) {
fprintf(stderr,"Usage: %s [ -f | -u ] <device> [<offset>]\n", PROGRAM_NAME);
return EINVAL;
}
diff --git a/misc-utils/flash_otp_erase.c b/misc-utils/flash_otp_erase.c
new file mode 100644
index 0000000..771e230
--- /dev/null
+++ b/misc-utils/flash_otp_erase.c
@@ -0,0 +1,64 @@
+/*
+ * flash_otp_erase.c -- erase area of One-Time-Program data
+ */
+
+#define PROGRAM_NAME "flash_otp_erase"
+
+#include <stdio.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <sys/ioctl.h>
+
+#include <mtd/mtd-user.h>
+#include "common.h"
+
+int main(int argc,char *argv[])
+{
+ int fd, val, ret, offset, size;
+ struct otp_info info;
+ char *p;
+
+ if (argc != 5 || strcmp(argv[1], "-u")) {
+ fprintf(stderr, "Usage: %s -u <device> <offset> <size>\n", PROGRAM_NAME);
+ fprintf(stderr, "offset and size must match on OTP region boundaries\n");
+ return EINVAL;
+ }
+
+ fd = open(argv[2], O_WRONLY);
+ if (fd < 0) {
+ perror(argv[2]);
+ return errno;
+ }
+
+ val = MTD_OTP_USER;
+ ret = ioctl(fd, OTPSELECT, &val);
+ if (ret < 0) {
+ perror("OTPSELECT");
+ return errno;
+ }
+
+ offset = strtoul(argv[3], &p, 0);
+ if (argv[3][0] == 0 || *p != 0) {
+ fprintf(stderr, "%s: bad offset value\n", PROGRAM_NAME);
+ return ERANGE;
+ }
+
+ size = strtoul(argv[4], &p, 0);
+ if (argv[4][0] == 0 || *p != 0) {
+ fprintf(stderr, "%s: bad size value\n", PROGRAM_NAME);
+ return ERANGE;
+ }
+
+ info.start = offset;
+ info.length = size;
+ ret = ioctl(fd, OTPERASE, &info);
+ if (ret < 0) {
+ perror("OTPERASE");
+ return errno;
+ }
+
+ return 0;
+}
diff --git a/misc-utils/flash_unlock.c b/misc-utils/flash_unlock.c
index fbbfa51..fa5decb 100644
--- a/misc-utils/flash_unlock.c
+++ b/misc-utils/flash_unlock.c
@@ -51,6 +51,8 @@ static NORETURN void usage(int status)
" -l --lock Lock a region of flash\n"
" -u --unlock Unlock a region of flash\n"
"\n"
+ " <mtd device> MTD device node or 'mtd:<name>'\n"
+ "\n"
"If offset is not specified, it defaults to 0.\n"
"If block count is not specified, it defaults to all blocks.\n"
"A block count of -1 means all blocks.\n",
@@ -125,7 +127,12 @@ static void process_args(int argc, char *argv[])
}
/* First non-option argument */
- dev = argv[arg_idx++];
+ dev = mtd_find_dev_node(argv[arg_idx]);
+ if (!dev) {
+ errmsg("MTD device not found %s", argv[arg_idx]);
+ usage(EXIT_FAILURE);
+ }
+ arg_idx++;
/* Second non-option argument */
if (arg_idx < argc)
diff --git a/misc-utils/flashcp.c b/misc-utils/flashcp.c
index d7b0a59..9c48637 100644
--- a/misc-utils/flashcp.c
+++ b/misc-utils/flashcp.c
@@ -48,7 +48,7 @@
/* for debugging purposes only */
#ifdef DEBUG
#undef DEBUG
-#define DEBUG(fmt,args...) { log_printf (LOG_ERROR,"%d: ",__LINE__); log_printf (LOG_ERROR,fmt,## args); }
+#define DEBUG(fmt,args...) { fprintf (stderr,"%d: ",__LINE__); fprintf (stderr,fmt,## args); }
#else
#undef DEBUG
#define DEBUG(fmt,args...)
@@ -57,36 +57,47 @@
#define KB(x) ((x) / 1024)
#define PERCENTAGE(x,total) (((x) * 100) / (total))
-/* size of read/write buffer */
-#define BUFSIZE (10 * 1024)
-
/* cmd-line flags */
#define FLAG_NONE 0x00
-#define FLAG_VERBOSE 0x01
#define FLAG_HELP 0x02
#define FLAG_FILENAME 0x04
#define FLAG_DEVICE 0x08
#define FLAG_ERASE_ALL 0x10
+#define FLAG_PARTITION 0x20
+#define FLAG_WR_LAST 0x40
/* error levels */
#define LOG_NORMAL 1
#define LOG_ERROR 2
-static void log_printf (int level,const char *fmt, ...)
+static NORETURN void log_failure (const char *fmt, ...)
{
- FILE *fp = level == LOG_NORMAL ? stdout : stderr;
va_list ap;
va_start (ap,fmt);
- vfprintf (fp,fmt,ap);
+ vfprintf (stderr,fmt,ap);
va_end (ap);
- fflush (fp);
+ fflush (stderr);
+
+ exit (EXIT_FAILURE);
}
-static NORETURN void showusage(bool error)
+static int verbose = 0;
+static void log_verbose (const char *fmt, ...)
{
- int level = error ? LOG_ERROR : LOG_NORMAL;
+ va_list ap;
+
+ if (!verbose)
+ return;
+
+ va_start (ap,fmt);
+ vfprintf (stdout,fmt,ap);
+ va_end (ap);
+ fflush (stdout);
+}
- log_printf (level,
+static NORETURN void showusage(bool error)
+{
+ fprintf (error ? stderr : stdout,
"\n"
"Flash Copy - Written by Abraham van der Merwe <abraham@2d3d.co.za>\n"
"\n"
@@ -94,12 +105,14 @@ static NORETURN void showusage(bool error)
" %1$s -h | --help\n"
" %1$s -V | --version\n"
"\n"
- " -h | --help Show this help message\n"
- " -v | --verbose Show progress reports\n"
- " -A | --erase-all Erases the whole device regardless of the image size\n"
- " -V | --version Show version information and exit\n"
- " <filename> File which you want to copy to flash\n"
- " <device> Flash device to write to (e.g. /dev/mtd0, /dev/mtd1, etc.)\n"
+ " -h | --help Show this help message\n"
+ " -v | --verbose Show progress reports\n"
+ " -p | --partition Only copy different block from file to device\n"
+ " -A | --erase-all Erases the whole device regardless of the image size\n"
+ " -l | --wr-last=bytes Write the first [bytes] last\n"
+ " -V | --version Show version information and exit\n"
+ " <filename> File which you want to copy to flash\n"
+ " <device> Flash device node or 'mtd:<name>' to write to (e.g. /dev/mtd0, /dev/mtd1, mtd:data, etc.)\n"
"\n",
PROGRAM_NAME);
@@ -108,49 +121,85 @@ static NORETURN void showusage(bool error)
static int safe_open (const char *pathname,int flags)
{
+ const char *access = "unknown";
int fd;
fd = open (pathname,flags);
if (fd < 0)
{
- log_printf (LOG_ERROR,"While trying to open %s",pathname);
if (flags & O_RDWR)
- log_printf (LOG_ERROR," for read/write access");
+ access = "read/write";
else if (flags & O_RDONLY)
- log_printf (LOG_ERROR," for read access");
+ access = "read";
else if (flags & O_WRONLY)
- log_printf (LOG_ERROR," for write access");
- log_printf (LOG_ERROR,": %m\n");
- exit (EXIT_FAILURE);
+ access = "write";
+
+ log_failure ("While trying to open %s for %s access: %m\n",pathname,access);
}
return (fd);
}
-static void safe_read (int fd,const char *filename,void *buf,size_t count,bool verbose)
+static void safe_read (int fd,const char *filename,void *buf,size_t count)
{
ssize_t result;
result = read (fd,buf,count);
if (count != result)
{
- if (verbose) log_printf (LOG_NORMAL,"\n");
+ log_verbose ("\n");
+ if (result < 0)
+ {
+ log_failure("While reading data from %s: %m\n",filename);
+ }
+ log_failure("Short read count returned while reading from %s\n",filename);
+ }
+}
+
+static void safe_write (int fd,const void *buf,size_t count,size_t written,unsigned long long to_write,const char *device)
+{
+ ssize_t result;
+
+ /* write to device */
+ result = write (fd,buf,count);
+ if (count != result)
+ {
+ log_verbose ("\n");
if (result < 0)
{
- log_printf (LOG_ERROR,"While reading data from %s: %m\n",filename);
- exit (EXIT_FAILURE);
+ log_failure("While writing data to 0x%.8lx-0x%.8lx on %s: %m\n",
+ written,written + count,device);
}
- log_printf (LOG_ERROR,"Short read count returned while reading from %s\n",filename);
- exit (EXIT_FAILURE);
+ log_failure("Short write count returned while writing to x%.8zx-0x%.8zx on %s: %zu/%llu bytes written to flash\n",
+ written,written + count,device,written + result,to_write);
}
}
+static off_t safe_lseek (int fd,off_t offset,int whence,const char *filename)
+{
+ off_t off;
+
+ off = lseek (fd,offset,whence);
+ if (off < 0)
+ {
+ log_failure("While seeking on %s: %m\n",filename);
+ }
+
+ return off;
+}
+
static void safe_rewind (int fd,const char *filename)
{
- if (lseek (fd,0L,SEEK_SET) < 0)
+ safe_lseek(fd,0L,SEEK_SET,filename);
+}
+
+static void safe_memerase (int fd,const char *device,struct erase_info_user *erase)
+{
+ if (ioctl (fd,MEMERASE,erase) < 0)
{
- log_printf (LOG_ERROR,"While seeking to start of %s: %m\n",filename);
- exit (EXIT_FAILURE);
+ log_verbose ("\n");
+ log_failure("While erasing blocks 0x%.8x-0x%.8x on %s: %m\n",
+ (unsigned int) erase->start,(unsigned int) (erase->start + erase->length),device);
}
}
@@ -168,12 +217,13 @@ int main (int argc,char *argv[])
{
const char *filename = NULL,*device = NULL;
int i,flags = FLAG_NONE;
- ssize_t result;
size_t size,written;
struct mtd_info_user mtd;
struct erase_info_user erase;
struct stat filestat;
- unsigned char src[BUFSIZE],dest[BUFSIZE];
+ unsigned char *src,*dest,*wrlast_buf;
+ unsigned long long wrlast_len = 0;
+ int error = 0;
/*********************
* parse cmd-line
@@ -181,11 +231,13 @@ int main (int argc,char *argv[])
for (;;) {
int option_index = 0;
- static const char *short_options = "hvAV";
+ static const char *short_options = "hvpAl:V";
static const struct option long_options[] = {
{"help", no_argument, 0, 'h'},
{"verbose", no_argument, 0, 'v'},
+ {"partition", no_argument, 0, 'p'},
{"erase-all", no_argument, 0, 'A'},
+ {"wr-last", required_argument, 0, 'l'},
{"version", no_argument, 0, 'V'},
{0, 0, 0, 0},
};
@@ -202,13 +254,21 @@ int main (int argc,char *argv[])
DEBUG("Got FLAG_HELP\n");
break;
case 'v':
- flags |= FLAG_VERBOSE;
+ verbose = 1;
DEBUG("Got FLAG_VERBOSE\n");
break;
+ case 'p':
+ flags |= FLAG_PARTITION;
+ DEBUG("Got FLAG_PARTITION");
+ break;
case 'A':
flags |= FLAG_ERASE_ALL;
DEBUG("Got FLAG_ERASE_ALL\n");
break;
+ case 'l':
+ flags |= FLAG_WR_LAST;
+ wrlast_len = simple_strtoll(optarg, &error);
+ break;
case 'V':
common_print_version();
exit(EXIT_SUCCESS);
@@ -224,13 +284,23 @@ int main (int argc,char *argv[])
DEBUG("Got filename: %s\n",filename);
flags |= FLAG_DEVICE;
- device = argv[optind+1];
+ device = mtd_find_dev_node(argv[optind+1]);
+ if (!device)
+ log_failure("Failed to find device %s\n", argv[optind+1]);
+
DEBUG("Got device: %s\n",device);
}
if (flags & FLAG_HELP || device == NULL)
showusage(flags != FLAG_HELP);
+ if (flags & FLAG_PARTITION && flags & FLAG_ERASE_ALL)
+ log_failure("Option --partition does not support --erase-all\n");
+
+ if (flags & FLAG_PARTITION && flags & FLAG_WR_LAST) {
+ log_failure("Option --partition does not support --wr-last\n");
+ }
+
atexit (cleanup);
/* get some info about the flash device */
@@ -238,23 +308,30 @@ int main (int argc,char *argv[])
if (ioctl (dev_fd,MEMGETINFO,&mtd) < 0)
{
DEBUG("ioctl(): %m\n");
- log_printf (LOG_ERROR,"This doesn't seem to be a valid MTD flash device!\n");
- exit (EXIT_FAILURE);
+ log_failure("This doesn't seem to be a valid MTD flash device!\n");
}
/* get some info about the file we want to copy */
fil_fd = safe_open (filename,O_RDONLY);
if (fstat (fil_fd,&filestat) < 0)
- {
- log_printf (LOG_ERROR,"While trying to get the file status of %s: %m\n",filename);
- exit (EXIT_FAILURE);
- }
+ log_failure("While trying to get the file status of %s: %m\n",filename);
/* does it fit into the device/partition? */
if (filestat.st_size > mtd.size)
+ log_failure("%s won't fit into %s!\n",filename,device);
+
+ src = malloc(mtd.erasesize);
+ if (!src)
+ log_failure("Malloc failed");
+
+ dest = malloc(mtd.erasesize);
+ if (!dest)
+ log_failure("Malloc failed");
+
+ /* diff block flashcp */
+ if (flags & FLAG_PARTITION)
{
- log_printf (LOG_ERROR,"%s won't fit into %s!\n",filename,device);
- exit (EXIT_FAILURE);
+ goto DIFF_BLOCKS;
}
/*****************************************************
@@ -275,37 +352,24 @@ int main (int argc,char *argv[])
erase.length *= mtd.erasesize;
}
- if (flags & FLAG_VERBOSE)
+ if (verbose)
{
/* if the user wants verbose output, erase 1 block at a time and show him/her what's going on */
int blocks = erase.length / mtd.erasesize;
erase.length = mtd.erasesize;
- log_printf (LOG_NORMAL,"Erasing blocks: 0/%d (0%%)",blocks);
+ log_verbose ("Erasing blocks: 0/%d (0%%)",blocks);
for (i = 1; i <= blocks; i++)
{
- log_printf (LOG_NORMAL,"\rErasing blocks: %d/%d (%d%%)",i,blocks,PERCENTAGE (i,blocks));
- if (ioctl (dev_fd,MEMERASE,&erase) < 0)
- {
- log_printf (LOG_NORMAL,"\n");
- log_printf (LOG_ERROR,
- "While erasing blocks 0x%.8x-0x%.8x on %s: %m\n",
- (unsigned int) erase.start,(unsigned int) (erase.start + erase.length),device);
- exit (EXIT_FAILURE);
- }
+ log_verbose ("\rErasing blocks: %d/%d (%d%%)",i,blocks,PERCENTAGE (i,blocks));
+ safe_memerase(dev_fd,device,&erase);
erase.start += mtd.erasesize;
}
- log_printf (LOG_NORMAL,"\rErasing blocks: %d/%d (100%%)\n",blocks,blocks);
+ log_verbose ("\rErasing blocks: %d/%d (100%%)\n",blocks,blocks);
}
else
{
/* if not, erase the whole chunk in one shot */
- if (ioctl (dev_fd,MEMERASE,&erase) < 0)
- {
- log_printf (LOG_ERROR,
- "While erasing blocks from 0x%.8x-0x%.8x on %s: %m\n",
- (unsigned int) erase.start,(unsigned int) (erase.start + erase.length),device);
- exit (EXIT_FAILURE);
- }
+ safe_memerase(dev_fd,device,&erase);
}
DEBUG("Erased %u / %luk bytes\n",erase.length,filestat.st_size);
@@ -313,50 +377,68 @@ int main (int argc,char *argv[])
* write the entire file to flash *
**********************************/
- if (flags & FLAG_VERBOSE) log_printf (LOG_NORMAL,"Writing data: 0k/%lluk (0%%)",KB ((unsigned long long)filestat.st_size));
size = filestat.st_size;
- i = BUFSIZE;
+ i = mtd.erasesize;
written = 0;
+
+ if ((flags & FLAG_WR_LAST) && (filestat.st_size > wrlast_len)) {
+ if (wrlast_len > mtd.erasesize)
+ log_failure("The wrlast (%lluk) is larger than erasesize (%lluk)\n", KB (wrlast_len), KB ((unsigned long long)mtd.erasesize));
+
+ if (size < mtd.erasesize) i = size;
+
+ log_verbose ("Reading %lluk of data to write last.\n", KB ((unsigned long long)wrlast_len));
+ wrlast_buf = malloc(wrlast_len);
+ if (!wrlast_buf)
+ log_failure("Malloc failed");
+ safe_read (fil_fd, filename, wrlast_buf, wrlast_len);
+ safe_lseek(dev_fd, wrlast_len, SEEK_SET, device);
+ written += wrlast_len;
+ size -= wrlast_len;
+ i -= wrlast_len;
+
+ log_verbose ("Writing remaining erase block data: %dk/%lluk (%llu%%)\n",
+ KB (written + i),
+ KB ((unsigned long long)filestat.st_size),
+ PERCENTAGE ((unsigned long long)written + i, (unsigned long long)filestat.st_size));
+ safe_read (fil_fd, filename, src, i);
+ safe_write(dev_fd, src, i, written, (unsigned long long)filestat.st_size, device);
+
+ written += i;
+ size -= i;
+ i = mtd.erasesize;
+ } else {
+ log_verbose ("Writing data: 0k/%lluk (0%%)",KB ((unsigned long long)filestat.st_size));
+ }
+
while (size)
{
- if (size < BUFSIZE) i = size;
- if (flags & FLAG_VERBOSE)
- log_printf (LOG_NORMAL,"\rWriting data: %dk/%lluk (%llu%%)",
- KB (written + i),
- KB ((unsigned long long)filestat.st_size),
- PERCENTAGE (written + i,(unsigned long long)filestat.st_size));
+ if (size < mtd.erasesize) i = size;
+ log_verbose ("\rWriting data: %dk/%lluk (%llu%%)",
+ KB (written + i),
+ KB ((unsigned long long)filestat.st_size),
+ PERCENTAGE ((unsigned long long)written + i,(unsigned long long)filestat.st_size));
/* read from filename */
- safe_read (fil_fd,filename,src,i,flags & FLAG_VERBOSE);
+ safe_read (fil_fd,filename,src,i);
/* write to device */
- result = write (dev_fd,src,i);
- if (i != result)
- {
- if (flags & FLAG_VERBOSE) log_printf (LOG_NORMAL,"\n");
- if (result < 0)
- {
- log_printf (LOG_ERROR,
- "While writing data to 0x%.8lx-0x%.8lx on %s: %m\n",
- written,written + i,device);
- exit (EXIT_FAILURE);
- }
- log_printf (LOG_ERROR,
- "Short write count returned while writing to x%.8zx-0x%.8zx on %s: %zu/%llu bytes written to flash\n",
- written,written + i,device,written + result,(unsigned long long)filestat.st_size);
- exit (EXIT_FAILURE);
- }
+ safe_write(dev_fd,src,i,written,(unsigned long long)filestat.st_size,device);
written += i;
size -= i;
}
- if (flags & FLAG_VERBOSE)
- log_printf (LOG_NORMAL,
- "\rWriting data: %lluk/%lluk (100%%)\n",
- KB ((unsigned long long)filestat.st_size),
- KB ((unsigned long long)filestat.st_size));
+ log_verbose ("\rWriting data: %lluk/%lluk (100%%)\n",
+ KB ((unsigned long long)filestat.st_size),
+ KB ((unsigned long long)filestat.st_size));
DEBUG("Wrote %d / %lluk bytes\n",written,(unsigned long long)filestat.st_size);
+ if ((flags & FLAG_WR_LAST) && (filestat.st_size > wrlast_len)) {
+ log_verbose ("Writing %lluk of the write last data.\n", KB ((unsigned long long)wrlast_len));
+ safe_rewind (dev_fd, device);
+ safe_write(dev_fd, wrlast_buf, wrlast_len, 0, wrlast_len, device);
+ }
+
/**********************************
* verify that flash == file data *
**********************************/
@@ -364,43 +446,96 @@ int main (int argc,char *argv[])
safe_rewind (fil_fd,filename);
safe_rewind (dev_fd,device);
size = filestat.st_size;
- i = BUFSIZE;
+ i = mtd.erasesize;
written = 0;
- if (flags & FLAG_VERBOSE) log_printf (LOG_NORMAL,"Verifying data: 0k/%lluk (0%%)",KB ((unsigned long long)filestat.st_size));
+ log_verbose ("Verifying data: 0k/%lluk (0%%)",KB ((unsigned long long)filestat.st_size));
while (size)
{
- if (size < BUFSIZE) i = size;
- if (flags & FLAG_VERBOSE)
- log_printf (LOG_NORMAL,
- "\rVerifying data: %luk/%lluk (%llu%%)",
- KB (written + i),
- KB ((unsigned long long)filestat.st_size),
- PERCENTAGE (written + i,(unsigned long long)filestat.st_size));
+ if (size < mtd.erasesize) i = size;
+ log_verbose ("\rVerifying data: %luk/%lluk (%llu%%)",
+ KB (written + i),
+ KB ((unsigned long long)filestat.st_size),
+ PERCENTAGE ((unsigned long long)written + i,(unsigned long long)filestat.st_size));
/* read from filename */
- safe_read (fil_fd,filename,src,i,flags & FLAG_VERBOSE);
+ safe_read (fil_fd,filename,src,i);
/* read from device */
- safe_read (dev_fd,device,dest,i,flags & FLAG_VERBOSE);
+ safe_read (dev_fd,device,dest,i);
/* compare buffers */
if (memcmp (src,dest,i))
- {
- log_printf (LOG_ERROR,
- "File does not seem to match flash data. First mismatch at 0x%.8zx-0x%.8zx\n",
+ log_failure("File does not seem to match flash data. First mismatch at 0x%.8zx-0x%.8zx\n",
written,written + i);
- exit (EXIT_FAILURE);
- }
written += i;
size -= i;
}
- if (flags & FLAG_VERBOSE)
- log_printf (LOG_NORMAL,
- "\rVerifying data: %lluk/%lluk (100%%)\n",
- KB ((unsigned long long)filestat.st_size),
- KB ((unsigned long long)filestat.st_size));
+ log_verbose ("\rVerifying data: %lluk/%lluk (100%%)\n",
+ KB ((unsigned long long)filestat.st_size),
+ KB ((unsigned long long)filestat.st_size));
DEBUG("Verified %d / %lluk bytes\n",written,(unsigned long long)filestat.st_size);
exit (EXIT_SUCCESS);
+
+ /*********************************************
+ * Copy different blocks from file to device *
+ ********************************************/
+DIFF_BLOCKS:
+ safe_rewind (fil_fd,filename);
+ safe_rewind (dev_fd,device);
+ size = filestat.st_size;
+ i = mtd.erasesize;
+ erase.start = 0;
+ erase.length = (filestat.st_size + mtd.erasesize - 1) / mtd.erasesize;
+ erase.length *= mtd.erasesize;
+ written = 0;
+ unsigned long current_dev_block = 0;
+ int diffBlock = 0;
+ int blocks = erase.length / mtd.erasesize;
+ erase.length = mtd.erasesize;
+
+ log_verbose ("\rProcessing blocks: 0/%d (%d%%)", blocks, PERCENTAGE (0,blocks));
+ for (int s = 1; s <= blocks; s++)
+ {
+ if (size < mtd.erasesize) i = size;
+ log_verbose ("\rProcessing blocks: %d/%d (%d%%)", s, blocks, PERCENTAGE (s,blocks));
+
+ /* read from filename */
+ safe_read (fil_fd,filename,src,i);
+
+ /* read from device */
+ current_dev_block = safe_lseek(dev_fd, 0, SEEK_CUR, device);
+ safe_read (dev_fd,device,dest,i);
+
+ /* compare buffers, if not the same, erase and write the block */
+ if (memcmp (src,dest,i))
+ {
+ diffBlock++;
+ /* erase block */
+ safe_lseek(dev_fd, current_dev_block, SEEK_SET, device);
+ safe_memerase(dev_fd,device,&erase);
+
+ /* write to device */
+ safe_lseek(dev_fd, current_dev_block, SEEK_SET, device);
+ safe_write(dev_fd,src,i,written,(unsigned long long)filestat.st_size,device);
+
+ /* read from device */
+ safe_lseek(dev_fd, current_dev_block, SEEK_SET, device);
+ safe_read (dev_fd,device,dest,i);
+
+ /* compare buffers for write success */
+ if (memcmp (src,dest,i))
+ log_failure("File does not seem to match flash data. First mismatch at 0x%.8zx-0x%.8zx\n",
+ written,written + i);
+ }
+
+ erase.start += i;
+ written += i;
+ size -= i;
+ }
+
+ log_verbose ("\ndiff blocks: %d\n", diffBlock);
+
+ exit (EXIT_SUCCESS);
}
diff --git a/misc-utils/lsmtd.8 b/misc-utils/lsmtd.8
index 3061c40..198c8a7 100644
--- a/misc-utils/lsmtd.8
+++ b/misc-utils/lsmtd.8
@@ -14,7 +14,7 @@ command reads the
.B sysfs
filesystem to gather information. Alternatively, the
.B procfs
-filesystem and ioctl interfaces are used, should the sysfs filesytem not
+filesystem and ioctl interfaces are used, should the sysfs filesystem not
be available.
.PP
The command prints all MTD and UBI devices in a pretty-printed list format by
diff --git a/misc-utils/lsmtd.c b/misc-utils/lsmtd.c
index 24a30ac..b62b69f 100644
--- a/misc-utils/lsmtd.c
+++ b/misc-utils/lsmtd.c
@@ -72,11 +72,11 @@ static struct column cols[] = {
{ "SUB-SIZE", "subpage size", COL_SUBSIZE, COL_DT_SIZE, 0 },
{ "OOB-SIZE", "out of band data size", COL_OOBSIZE, COL_DT_SIZE, 0 },
{ "RO", "read-only device", COL_RO, COL_DT_BOOL, 0 },
- { "CORRUPTED", "wheather an UBI volume is corrupted",
+ { "CORRUPTED", "whether an UBI volume is corrupted",
COL_CORRUPTED, COL_DT_BOOL, 0 },
{ "REGIONS", "number of additional erase regions",
COL_REGION, COL_DT_NUMBER, 0 },
- { "BB", "wheather the MTD device may have bad eraseblocks",
+ { "BB", "whether the MTD device may have bad eraseblocks",
COL_BB, COL_DT_BOOL, 0 },
{ "MAX-EC", "current highest erase counter value on UBI devices",
COL_MAXEC, COL_DT_NUMBER, 0 },
@@ -107,7 +107,7 @@ static NORETURN void usage(int status)
" -r, --raw Use raw output format\n"
" -P, --pairs Use key=\"value\" output format\n"
" -J, --json Use JSON output format\n"
-" -o, --output <list> Comma seperated list of columns to print\n"
+" -o, --output <list> Comma separated list of columns to print\n"
" -O, --output-all Print all columns\n"
" -x, --sort <column> Sort output by <column>\n"
" -m, --no-ubi Do not display information about UBI devices/volumes\n"
diff --git a/misc-utils/lsmtd_scan.c b/misc-utils/lsmtd_scan.c
index cec7b5c..9331c5b 100644
--- a/misc-utils/lsmtd_scan.c
+++ b/misc-utils/lsmtd_scan.c
@@ -162,7 +162,7 @@ int scan_ubi(libubi_t lib_ubi)
}
if (j == num_mtd_devices) {
- fprintf(stderr, "Cannot find mtd device %d refered to "
+ fprintf(stderr, "Cannot find mtd device %d referred to "
"by ubi device %d\n", dev_info.mtd_num,
dev_info.dev_num);
return -1;
diff --git a/misc-utils/mtd_debug.c b/misc-utils/mtd_debug.c
index c0b7109..abee5e3 100644
--- a/misc-utils/mtd_debug.c
+++ b/misc-utils/mtd_debug.c
@@ -348,6 +348,7 @@ int main(int argc, char *argv[])
{
int err = 0, fd;
int open_flag;
+ char *dev;
enum {
OPT_INFO,
@@ -369,8 +370,12 @@ int main(int argc, char *argv[])
showusage();
/* open device */
+ dev = mtd_find_dev_node(argv[2]);
+ if (!dev)
+ errmsg_die("Failed to find MTD device %s", argv[2]);
+
open_flag = (option == OPT_INFO || option == OPT_READ) ? O_RDONLY : O_RDWR;
- if ((fd = open(argv[2], O_SYNC | open_flag)) < 0)
+ if ((fd = open(dev, O_SYNC | open_flag)) < 0)
errmsg_die("open()");
switch (option) {
diff --git a/misc-utils/mtdpart.c b/misc-utils/mtdpart.c
index ba35d87..a341148 100644
--- a/misc-utils/mtdpart.c
+++ b/misc-utils/mtdpart.c
@@ -36,8 +36,10 @@ static void display_help(int status)
" -h, --help Display this help and exit\n"
" -V, --version Output version information and exit\n"
"\n"
+" <MTD_DEVICE> MTD device node or 'mtd:<name>'\n"
+"\n"
"START location and SIZE of the partition are in bytes. They should align on\n"
-"eraseblock size.\n",
+"eraseblock size. If SIZE is 0 the partition will go to end of MTD device.\n",
PROGRAM_NAME
);
exit(status);
@@ -106,7 +108,10 @@ static void process_options(int argc, char * const argv[])
display_help(EXIT_FAILURE);
const char *s_command = argv[optind++];
- mtddev = argv[optind++];
+ mtddev = mtd_find_dev_node(argv[optind]);
+ if (!mtddev)
+ errmsg_die("MTD device not found %s", argv[optind]);
+ optind++;
if (strcmp(s_command, "del") == 0 && (argc - optind) == 1) {
const char *s_part_no = argv[optind++];
diff --git a/nand-utils/Makemodule.am b/nand-utils/Makemodule.am
index d75b0cb..cee6777 100644
--- a/nand-utils/Makemodule.am
+++ b/nand-utils/Makemodule.am
@@ -7,26 +7,24 @@ nandwrite_LDADD = libmtd.a
nandtest_SOURCES = nand-utils/nandtest.c
nandtest_LDADD = libmtd.a
-nftldump_SOURCES = nand-utils/nftldump.c
+nftldump_SOURCES = nand-utils/nftldump.c include/mtd_swab.h
+nftldump_SOURCES += include/mtd/nftl-user.h include/mtd/ftl-user.h
nftldump_LDADD = libmtd.a
-nftl_format_SOURCES = nand-utils/nftl_format.c
+nftl_format_SOURCES = nand-utils/nftl_format.c include/mtd_swab.h
+nftl_format_SOURCES += include/mtd/nftl-user.h include/mtd/ftl-user.h
nftl_format_LDADD = libmtd.a
-NAND_BINS = \
- nanddump nandwrite nandtest nftldump nftl_format
+nandflipbits_SOURCES = nand-utils/nandflipbits.c
+nandflipbits_LDADD = libmtd.a
NAND_SH = \
nand-utils/load_nandsim.sh
EXTRA_DIST += $(NAND_SH)
-sbin_PROGRAMS += $(NAND_BINS)
+sbin_PROGRAMS += nanddump nandwrite nandtest nftldump nftl_format nandflipbits
if BUILD_TESTS
-if INSTALL_TESTS
-pkglibexec_SCRIPTS += $(NAND_SH)
-else
-noinst_SCRIPTS += $(NAND_SH)
-endif
+test_SCRIPTS += $(NAND_SH)
endif
diff --git a/nand-utils/nanddump.c b/nand-utils/nanddump.c
index d7fc320..47539f5 100644
--- a/nand-utils/nanddump.c
+++ b/nand-utils/nanddump.c
@@ -499,7 +499,7 @@ int main(int argc, char * const argv[])
}
} else {
/* Write requested length if oob is omitted */
- size_t size_left = end_addr - ofs;
+ long long size_left = end_addr - ofs;
if (omitoob && (size_left < bs))
err = ofd_write(ofd, readbuf, size_left);
else
diff --git a/nand-utils/nandflipbits.c b/nand-utils/nandflipbits.c
new file mode 100644
index 0000000..7066408
--- /dev/null
+++ b/nand-utils/nandflipbits.c
@@ -0,0 +1,326 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2014 Bootlin
+ *
+ * Authors: Boris Brezillon <boris.brezillon@collabora.com>
+ * Miquel Raynal <miquel.raynal@bootlin.com>
+ *
+ * Overview:
+ * This utility manually flips specified bits in a NAND flash.
+ */
+
+#define PROGRAM_NAME "nandflipbits"
+
+#include <mtd/mtd-user.h>
+#include <sys/ioctl.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <libmtd.h>
+#include <getopt.h>
+#include <stdio.h>
+#include <fcntl.h>
+
+#include "common.h"
+
+struct bit_flip {
+ uint32_t block;
+ uint64_t offset;
+ int bit;
+ bool done;
+};
+
+static void usage(int status)
+{
+ fprintf(status == EXIT_SUCCESS ? stdout : stderr,
+"Usage: "PROGRAM_NAME" [OPTIONS] <device> <bit>@<address> [<bit>@<address>...]\n"
+"\n"
+" Test ECC engines, see if they match the specified correction strength:\n"
+" * Reads in raw mode the data from an MTD device\n"
+" * Flips the indicated bit(s)\n"
+" * Write it back in raw mode.\n"
+"\n"
+" -h, --help Display this help and exit\n"
+" -o, --oob Provided addresses take OOB area into account\n"
+" -q, --quiet Don't display progress messages\n"
+"\n"
+ );
+ exit(status);
+}
+
+static const char *mtd_device;
+static bool quiet = false;
+static bool oob_mode = false;
+static struct bit_flip *bits_to_flip;
+static int nbits_to_flip = 0;
+
+static void process_options(int argc, char * const argv[])
+{
+ int error = 0;
+ int i;
+
+ for (;;) {
+ int option_index = 0;
+ static const char short_options[] = "hoq";
+ static const struct option long_options[] = {
+ {"help", no_argument, 0, 'h'},
+ {"oob", no_argument, 0, 'o'},
+ {"quiet", no_argument, 0, 'q'},
+ {0, 0, 0, 0},
+ };
+
+ int c = getopt_long(argc, argv, short_options,
+ long_options, &option_index);
+ if (c == EOF)
+ break;
+
+ switch (c) {
+ case 'q':
+ quiet = true;
+ break;
+ case 'o':
+ oob_mode = true;
+ break;
+ case 'h':
+ usage(EXIT_SUCCESS);
+ break;
+ case '?':
+ default:
+ error++;
+ break;
+ }
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ /*
+ * There must be at least the MTD device node path argument remaining
+ * and a list of minimum one 'bits-to-flip'.
+ */
+
+ if (argc < 2 || error)
+ usage(EXIT_FAILURE);
+
+ /* MTD device */
+ mtd_device = argv[0];
+ argc--;
+ argv++;
+
+ /* Parse the bits to flip */
+ nbits_to_flip = argc;
+ bits_to_flip = malloc(sizeof(*bits_to_flip) * nbits_to_flip);
+ if (!bits_to_flip)
+ exit(EXIT_FAILURE);
+
+ for (i = 0; i < nbits_to_flip; i++) {
+ struct bit_flip *bit_to_flip = &bits_to_flip[i];
+ char *desc = argv[i];
+
+ bit_to_flip->bit = strtol(desc, &desc, 0);
+ if (errno || bit_to_flip->bit > 7)
+ goto free_bits;
+
+ if (!desc || *desc++ != '@')
+ goto free_bits;
+
+ bit_to_flip->offset = strtol(desc, &desc, 0);
+ if (errno)
+ goto free_bits;
+ }
+
+ return;
+
+free_bits:
+ free(bits_to_flip);
+
+ fprintf(stderr, "Invalid bit description\n");
+
+ exit(EXIT_FAILURE);
+}
+
+int main(int argc, char **argv)
+{
+ struct mtd_dev_info mtd;
+ libmtd_t mtd_desc;
+ uint64_t mtdlen;
+ uint32_t pagelen, pages_per_blk, blklen;
+ uint8_t *buffer;
+ int fd, ret, i;
+
+ process_options(argc, argv);
+
+ /* Open the libmtd */
+ mtd_desc = libmtd_open();
+ if (!mtd_desc) {
+ fprintf(stderr, "Cannot initialize libmtd\n");
+ ret = EXIT_FAILURE;
+ goto free_bits;
+ }
+
+ /* Fill in MTD device capability structure */
+ ret = mtd_get_dev_info(mtd_desc, mtd_device, &mtd);
+ if (ret < 0) {
+ fprintf(stderr, "Cannot retrieve MTD device information\n");
+ ret = EXIT_FAILURE;
+ goto close_lib;
+ }
+
+ /* Verify we are using a NAND device */
+ if (mtd.type != MTD_NANDFLASH && mtd.type != MTD_MLCNANDFLASH) {
+ fprintf(stderr, "%s is not a NAND flash\n", mtd_device);
+ ret = EXIT_FAILURE;
+ goto close_lib;
+ }
+
+ /* Open the MTD device */
+ fd = open(mtd_device, O_RDWR);
+ if (fd < 0) {
+ fprintf(stderr, "Cannot open %s\n", mtd_device);
+ ret = EXIT_FAILURE;
+ goto close_lib;
+ }
+
+ /* Select raw mode */
+ ret = ioctl(fd, MTDFILEMODE, MTD_FILE_MODE_RAW);
+ if (ret) {
+ fprintf(stderr, "Unavailable raw mode ioctl\n");
+ ret = EXIT_FAILURE;
+ goto close_fd;
+ }
+
+ pagelen = mtd.min_io_size + (oob_mode ? mtd.oob_size : 0);
+ pages_per_blk = mtd.eb_size / mtd.min_io_size;
+ blklen = pages_per_blk * pagelen;
+ mtdlen = (uint64_t)blklen * (uint64_t)mtd.eb_cnt;
+ buffer = malloc((mtd.min_io_size + mtd.oob_size) * pages_per_blk);
+ if (!buffer) {
+ ret = EXIT_FAILURE;
+ goto close_fd;
+ }
+
+ for (i = 0; i < nbits_to_flip; i++) {
+ int page;
+
+ if (bits_to_flip[i].offset >= mtdlen) {
+ fprintf(stderr, "Invalid byte offset %" PRId64
+ " (max %" PRId64 ")\n",
+ bits_to_flip[i].offset, mtdlen);
+ ret = EXIT_FAILURE;
+ goto free_buf;
+ }
+
+ bits_to_flip[i].block = bits_to_flip[i].offset / blklen;
+ bits_to_flip[i].offset %= blklen;
+ page = bits_to_flip[i].offset / pagelen;
+ bits_to_flip[i].offset = (page *
+ (mtd.min_io_size + mtd.oob_size)) +
+ (bits_to_flip[i].offset % pagelen);
+ }
+
+ while (1) {
+ struct bit_flip *bit_to_flip = NULL;
+ int blkoffs;
+ int bufoffs;
+
+ /* Look for the next bitflip to insert */
+ for (i = 0; i < nbits_to_flip; i++) {
+ if (bits_to_flip[i].done == false) {
+ bit_to_flip = &bits_to_flip[i];
+ break;
+ }
+ }
+
+ if (!bit_to_flip) {
+ ret = EXIT_SUCCESS;
+ break;
+ }
+
+ /* Read the content of all the pages of a block */
+ blkoffs = 0;
+ bufoffs = 0;
+ for (i = 0; i < pages_per_blk; i++) {
+ ret = mtd_read(&mtd, fd, bit_to_flip->block, blkoffs,
+ buffer + bufoffs, mtd.min_io_size);
+ if (ret) {
+ fprintf(stderr, "MTD read failure\n");
+ ret = EXIT_FAILURE;
+ goto free_buf;
+ }
+
+ bufoffs += mtd.min_io_size;
+
+ ret = mtd_read_oob(mtd_desc, &mtd, fd,
+ bit_to_flip->block * mtd.eb_size +
+ blkoffs,
+ mtd.oob_size, buffer + bufoffs);
+ if (ret) {
+ fprintf(stderr, "MTD OOB read failure\n");
+ ret = EXIT_FAILURE;
+ goto free_buf;
+ }
+
+ bufoffs += mtd.oob_size;
+ blkoffs += mtd.min_io_size;
+ }
+
+ /* Flip all bits that are located in this particular block */
+ for (i = 0; i < nbits_to_flip; i++) {
+ unsigned char val, mask;
+
+ if (bits_to_flip[i].block != bit_to_flip->block)
+ continue;
+
+ mask = 1 << bits_to_flip[i].bit;
+ val = buffer[bits_to_flip[i].offset] & mask;
+ if (val)
+ buffer[bits_to_flip[i].offset] &= ~mask;
+ else
+ buffer[bits_to_flip[i].offset] |= mask;
+ }
+
+ /* Erase the block */
+ ret = mtd_erase(mtd_desc, &mtd, fd, bit_to_flip->block);
+ if (ret) {
+ fprintf(stderr, "MTD erase failure\n");
+ ret = EXIT_FAILURE;
+ goto free_buf;
+ }
+
+ /* Rewrite the pages, still in raw mode, with the bitflips */
+ blkoffs = 0;
+ bufoffs = 0;
+ for (i = 0; i < pages_per_blk; i++) {
+ ret = mtd_write(mtd_desc, &mtd, fd, bit_to_flip->block,
+ blkoffs, buffer + bufoffs, mtd.min_io_size,
+ buffer + bufoffs + mtd.min_io_size,
+ mtd.oob_size,
+ MTD_OPS_RAW);
+ if (ret) {
+ fprintf(stderr, "MTD write failure\n");
+ ret = EXIT_FAILURE;
+ goto free_buf;
+ }
+
+ blkoffs += mtd.min_io_size;
+ bufoffs += mtd.min_io_size + mtd.oob_size;
+ }
+
+ /* Mark the added bitflips as done */
+ for (i = 0; i < nbits_to_flip; i++) {
+ if (bits_to_flip[i].block == bit_to_flip->block)
+ bits_to_flip[i].done = true;
+ }
+ }
+
+free_buf:
+ free(buffer);
+close_fd:
+ close(fd);
+close_lib:
+ libmtd_close(mtd_desc);
+free_bits:
+ free(bits_to_flip);
+
+ exit(ret);
+}
diff --git a/nand-utils/nandtest.c b/nand-utils/nandtest.c
index 06dec25..cac0dde 100644
--- a/nand-utils/nandtest.c
+++ b/nand-utils/nandtest.c
@@ -8,6 +8,7 @@
#include <string.h>
#include <time.h>
#include <unistd.h>
+#include <limits.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/types.h>
@@ -144,6 +145,26 @@ static int erase_and_write(loff_t ofs, unsigned char *data, unsigned char *rbuf,
return 0;
}
+static uint64_t get_mem_size(const char* device)
+{
+ const char* p = strrchr(device, '/');
+ char path[PATH_MAX];
+ int fd;
+
+ snprintf(path, sizeof(path), "/sys/class/mtd/%s/size", p);
+ fd = open(path, O_RDONLY);
+ if (fd >= 0) {
+ char buffer[32];
+ ssize_t n = read(fd, buffer, sizeof(buffer));
+ close(fd);
+ if (n > 0) {
+ return strtoull(buffer, NULL, 0);
+ }
+ }
+
+ fprintf(stderr, "Can't read size from %s\n", path);
+ exit(1);
+}
/*
* Main program
@@ -156,8 +177,9 @@ int main(int argc, char **argv)
int nr_passes = 1;
int nr_reads = 4;
int keep_contents = 0;
- uint32_t offset = 0;
- uint32_t length = -1;
+ uint64_t offset = 0;
+ uint64_t length = -1;
+ uint64_t mem_size = 0;
int error = 0;
seed = time(NULL);
@@ -212,11 +234,11 @@ int main(int argc, char **argv)
break;
case 'o':
- offset = simple_strtoul(optarg, &error);
+ offset = simple_strtoull(optarg, &error);
break;
case 'l':
- length = simple_strtoul(optarg, &error);
+ length = simple_strtoull(optarg, &error);
break;
}
@@ -238,29 +260,34 @@ int main(int argc, char **argv)
exit(1);
}
+ mem_size = get_mem_size(argv[optind]);
+
if (length == -1)
- length = meminfo.size;
+ length = mem_size;
if (offset % meminfo.erasesize) {
- fprintf(stderr, "Offset %x not multiple of erase size %x\n",
+ fprintf(stderr, "Offset %" PRIx64
+ " not multiple of erase size %x\n",
offset, meminfo.erasesize);
exit(1);
}
if (length % meminfo.erasesize) {
- fprintf(stderr, "Length %x not multiple of erase size %x\n",
+ fprintf(stderr, "Length %" PRIx64
+ " not multiple of erase size %x\n",
length, meminfo.erasesize);
exit(1);
}
- if (length + offset > meminfo.size) {
- fprintf(stderr, "Length %x + offset %x exceeds device size %x\n",
- length, offset, meminfo.size);
+ if (length + offset > mem_size) {
+ fprintf(stderr, "Length %" PRIx64 " + offset %" PRIx64
+ " exceeds device size %" PRIx64 "\n",
+ length, offset, mem_size);
exit(1);
}
wbuf = malloc(meminfo.erasesize * 3);
if (!wbuf) {
fprintf(stderr, "Could not allocate %d bytes for buffer\n",
- meminfo.erasesize * 2);
+ meminfo.erasesize * 3);
exit(1);
}
rbuf = wbuf + meminfo.erasesize;
diff --git a/nand-utils/nandwrite.c b/nand-utils/nandwrite.c
index e8a210c..cd53a17 100644
--- a/nand-utils/nandwrite.c
+++ b/nand-utils/nandwrite.c
@@ -280,6 +280,7 @@ int main(int argc, char * const argv[])
libmtd_t mtd_desc;
int ebsize_aligned;
uint8_t write_mode;
+ size_t all_ffs_cnt = 0;
process_options(argc, argv);
@@ -417,6 +418,8 @@ int main(int argc, char * const argv[])
*/
while ((imglen > 0 || writebuf < filebuf + filebuf_len)
&& mtdoffset < mtd.size) {
+ bool allffs;
+
/*
* New eraseblock, check for bad block(s)
* Stay in the loop to be sure that, if mtdoffset changes because
@@ -555,7 +558,8 @@ int main(int argc, char * const argv[])
}
ret = 0;
- if (!skipallffs || !buffer_check_pattern(writebuf, mtd.min_io_size, 0xff)) {
+ allffs = buffer_check_pattern(writebuf, mtd.min_io_size, 0xff);
+ if (!allffs || !skipallffs) {
/* Write out data */
ret = mtd_write(mtd_desc, &mtd, fd, mtdoffset / mtd.eb_size,
mtdoffset % mtd.eb_size,
@@ -564,6 +568,8 @@ int main(int argc, char * const argv[])
writeoob ? oobbuf : NULL,
writeoob ? mtd.oob_size : 0,
write_mode);
+ if (!ret && allffs)
+ all_ffs_cnt++;
}
if (ret) {
@@ -615,6 +621,11 @@ closeall:
|| (writebuf < filebuf + filebuf_len))
sys_errmsg_die("Data was only partially written due to error");
+ if (all_ffs_cnt) {
+ fprintf(stderr, "Written %zu blocks containing only 0xff bytes\n", all_ffs_cnt);
+ fprintf(stderr, "Those block may be incorrectly treated as empty!\n");
+ }
+
/* Return happy */
return EXIT_SUCCESS;
}
diff --git a/nor-utils/Makemodule.am b/nor-utils/Makemodule.am
index a5a0d4d..441a72e 100644
--- a/nor-utils/Makemodule.am
+++ b/nor-utils/Makemodule.am
@@ -1,10 +1,7 @@
-rfddump_SOURCES = nor-utils/rfddump.c
+rfddump_SOURCES = nor-utils/rfddump.c include/mtd_swab.h
rfddump_LDADD = libmtd.a
rfdformat_SOURCES = nor-utils/rfdformat.c
rfdformat_LDADD = libmtd.a
-NOR_BINS = \
- rfddump rfdformat
-
-sbin_PROGRAMS += $(NOR_BINS)
+sbin_PROGRAMS += rfddump rfdformat
diff --git a/nor-utils/rfddump.c b/nor-utils/rfddump.c
index 01ab4c2..d6d7f68 100644
--- a/nor-utils/rfddump.c
+++ b/nor-utils/rfddump.c
@@ -256,12 +256,10 @@ int main(int argc, char *argv[])
if (!rfd.sector_map) {
perror(PROGRAM_NAME);
close(fd);
- free(rfd.sector_map);
+ free(rfd.header);
return 2;
}
- rfd.mtd_filename = rfd.mtd_filename;
-
for (i=0; i<rfd.sector_count; i++)
rfd.sector_map[i] = -1;
diff --git a/tests/checkfs/Makemodule.am b/tests/checkfs/Makemodule.am
index 6e1314f..631ab92 100644
--- a/tests/checkfs/Makemodule.am
+++ b/tests/checkfs/Makemodule.am
@@ -1,22 +1,10 @@
checkfs_SOURCES = tests/checkfs/checkfs.c tests/checkfs/comm.c
+checkfs_SOURCES += tests/checkfs/common.h
checkfs_CPPFLAGS = $(AM_CPPFLAGS)
makefiles_SOURCES = tests/checkfs/makefiles.c
makefiles_CPPFLAGS = $(AM_CPPFLAGS)
-CHECKFS_BINS = \
- makefiles checkfs
+EXTRA_DIST += tests/checkfs/README
-CHECKFS_HEADER = \
- tests/checkfs/common.h
-
-CHECKFS_EXTRA = \
- tests/checkfs/README
-
-EXTRA_DIST += $(CHECKFS_EXTRA) $(CHECKFS_HEADER)
-
-if INSTALL_TESTS
-pkglibexec_PROGRAMS += $(CHECKFS_BINS)
-else
-noinst_PROGRAMS += $(CHECKFS_BINS)
-endif
+test_PROGRAMS += makefiles checkfs
diff --git a/tests/fs-tests/Makemodule.am b/tests/fs-tests/Makemodule.am
index 2eae860..0c58c9c 100644
--- a/tests/fs-tests/Makemodule.am
+++ b/tests/fs-tests/Makemodule.am
@@ -3,84 +3,76 @@ integck_LDADD = libubi.a libmissing.a
integck_CPPFLAGS = $(AM_CPPFLAGS) -I$(top_srcdir)/ubi-utils/include
test_1_SOURCES = tests/fs-tests/simple/test_1.c tests/fs-tests/lib/tests.c
+test_1_SOURCES += tests/fs-tests/lib/tests.h
test_1_CPPFLAGS = $(AM_CPPFLAGS) -I$(top_srcdir)/tests/fs-tests/lib
test_2_SOURCES = tests/fs-tests/simple/test_2.c tests/fs-tests/lib/tests.c
+test_2_SOURCES += tests/fs-tests/lib/tests.h
test_2_CPPFLAGS = $(AM_CPPFLAGS) -I$(top_srcdir)/tests/fs-tests/lib
ftrunc_SOURCES = tests/fs-tests/simple/ftrunc.c tests/fs-tests/lib/tests.c
+ftrunc_SOURCES += tests/fs-tests/lib/tests.h
ftrunc_CPPFLAGS = $(AM_CPPFLAGS) -I$(top_srcdir)/tests/fs-tests/lib
perf_SOURCES = tests/fs-tests/simple/perf.c tests/fs-tests/lib/tests.c
+perf_SOURCES += tests/fs-tests/lib/tests.h
perf_CPPFLAGS = $(AM_CPPFLAGS) -I$(top_srcdir)/tests/fs-tests/lib
orph_SOURCES = tests/fs-tests/simple/orph.c tests/fs-tests/lib/tests.c
+orph_SOURCES += tests/fs-tests/lib/tests.h
orph_CPPFLAGS = $(AM_CPPFLAGS) -I$(top_srcdir)/tests/fs-tests/lib
stress_1_SOURCES = tests/fs-tests/stress/atoms/stress_1.c
-stress_1_SOURCES += tests/fs-tests/lib/tests.c
+stress_1_SOURCES += tests/fs-tests/lib/tests.c tests/fs-tests/lib/tests.h
stress_1_CPPFLAGS = $(AM_CPPFLAGS) -I$(top_srcdir)/tests/fs-tests/lib
stress_2_SOURCES = tests/fs-tests/stress/atoms/stress_2.c
-stress_2_SOURCES += tests/fs-tests/lib/tests.c
+stress_2_SOURCES += tests/fs-tests/lib/tests.c tests/fs-tests/lib/tests.h
stress_2_CPPFLAGS = $(AM_CPPFLAGS) -I$(top_srcdir)/tests/fs-tests/lib
stress_3_SOURCES = tests/fs-tests/stress/atoms/stress_3.c
-stress_3_SOURCES += tests/fs-tests/lib/tests.c
+stress_3_SOURCES += tests/fs-tests/lib/tests.c tests/fs-tests/lib/tests.h
stress_3_CPPFLAGS = $(AM_CPPFLAGS) -I$(top_srcdir)/tests/fs-tests/lib
pdfrun_SOURCES = tests/fs-tests/stress/atoms/pdfrun.c
-pdfrun_SOURCES += tests/fs-tests/lib/tests.c
+pdfrun_SOURCES += tests/fs-tests/lib/tests.c tests/fs-tests/lib/tests.h
pdfrun_CPPFLAGS = $(AM_CPPFLAGS) -I$(top_srcdir)/tests/fs-tests/lib
rndwrite00_SOURCES = tests/fs-tests/stress/atoms/rndwrite00.c
-rndwrite00_SOURCES += tests/fs-tests/lib/tests.c
+rndwrite00_SOURCES += tests/fs-tests/lib/tests.c tests/fs-tests/lib/tests.h
rndwrite00_CPPFLAGS = $(AM_CPPFLAGS) -I$(top_srcdir)/tests/fs-tests/lib
fwrite00_SOURCES = tests/fs-tests/stress/atoms/fwrite00.c
-fwrite00_SOURCES += tests/fs-tests/lib/tests.c
+fwrite00_SOURCES += tests/fs-tests/lib/tests.c tests/fs-tests/lib/tests.h
fwrite00_CPPFLAGS = $(AM_CPPFLAGS) -I$(top_srcdir)/tests/fs-tests/lib
rmdir00_SOURCES = tests/fs-tests/stress/atoms/rmdir00.c
-rmdir00_SOURCES += tests/fs-tests/lib/tests.c
+rmdir00_SOURCES += tests/fs-tests/lib/tests.c tests/fs-tests/lib/tests.h
rmdir00_CPPFLAGS = $(AM_CPPFLAGS) -I$(top_srcdir)/tests/fs-tests/lib
rndrm00_SOURCES = tests/fs-tests/stress/atoms/rndrm00.c
-rndrm00_SOURCES += tests/fs-tests/lib/tests.c
+rndrm00_SOURCES += tests/fs-tests/lib/tests.c tests/fs-tests/lib/tests.h
rndrm00_CPPFLAGS = $(AM_CPPFLAGS) -I$(top_srcdir)/tests/fs-tests/lib
rndrm99_SOURCES = tests/fs-tests/stress/atoms/rndrm99.c
-rndrm99_SOURCES += tests/fs-tests/lib/tests.c
+rndrm99_SOURCES += tests/fs-tests/lib/tests.c tests/fs-tests/lib/tests.h
rndrm99_CPPFLAGS = $(AM_CPPFLAGS) -I$(top_srcdir)/tests/fs-tests/lib
gcd_hupper_SOURCES = tests/fs-tests/stress/atoms/gcd_hupper.c
-gcd_hupper_SOURCES += tests/fs-tests/lib/tests.c
+gcd_hupper_SOURCES += tests/fs-tests/lib/tests.c tests/fs-tests/lib/tests.h
gcd_hupper_CPPFLAGS = $(AM_CPPFLAGS) -I$(top_srcdir)/tests/fs-tests/lib
fstest_monitor_SOURCES = tests/fs-tests/utils/fstest_monitor.c
free_space_SOURCES = tests/fs-tests/utils/free_space.c
-FSTEST_BINS = \
+test_PROGRAMS += \
integck test_1 test_2 ftrunc perf orph \
stress_1 stress_2 stress_3 pdfrun gcd_hupper \
rndwrite00 fwrite00 rmdir00 rndrm00 rndrm99 \
fstest_monitor free_space
-FSTEST_SH = \
+test_SCRIPTS += \
tests/fs-tests/fs_help_all.sh tests/fs-tests/fs_run_all.sh \
tests/fs-tests/stress/fs_stress00.sh \
tests/fs-tests/stress/fs_stress01.sh
-
-FSTEST_HEADER = \
- tests/fs-tests/lib/tests.h
-
-EXTRA_DIST += $(FSTEST_HEADER)
-
-if INSTALL_TESTS
-pkglibexec_SCRIPTS += $(FSTEST_SH)
-pkglibexec_PROGRAMS += $(FSTEST_BINS)
-else
-noinst_SCRIPTS += $(FSTEST_SH)
-noinst_PROGRAMS += $(FSTEST_BINS)
-endif
diff --git a/tests/fs-tests/fs_help_all.sh.in b/tests/fs-tests/fs_help_all.sh.in
index 39219b2..3898fbd 100755
--- a/tests/fs-tests/fs_help_all.sh.in
+++ b/tests/fs-tests/fs_help_all.sh.in
@@ -1,10 +1,6 @@
#!/bin/sh
-prefix=@prefix@
-exec_prefix=@exec_prefix@
-bindir=@bindir@
-libexecpath=@libexecdir@/mtd-utils
-TESTBINDIR=@testbindir@
+TESTBINDIR=@TESTBINDIR@
echo -------------------------------------------------------------------------------
$TESTBINDIR/test_1 -h
diff --git a/tests/fs-tests/fs_run_all.sh.in b/tests/fs-tests/fs_run_all.sh.in
index a3676f9..f15a63b 100755
--- a/tests/fs-tests/fs_run_all.sh.in
+++ b/tests/fs-tests/fs_run_all.sh.in
@@ -1,10 +1,6 @@
#!/bin/sh
-prefix=@prefix@
-exec_prefix=@exec_prefix@
-bindir=@bindir@
-libexecpath=@libexecdir@/mtd-utils
-TESTBINDIR=@testbindir@
+TESTBINDIR=@TESTBINDIR@
TEST_DIR=$TEST_FILE_SYSTEM_MOUNT_DIR
if test -z "$TEST_DIR";
diff --git a/tests/fs-tests/lib/tests.c b/tests/fs-tests/lib/tests.c
index d1a2e0c..3db0426 100644
--- a/tests/fs-tests/lib/tests.c
+++ b/tests/fs-tests/lib/tests.c
@@ -35,7 +35,6 @@
#include <sys/vfs.h>
#include <sys/mount.h>
#include <sys/statvfs.h>
-#include <linux/fs.h>
#include <linux/jffs2.h>
#include "tests.h"
diff --git a/tests/fs-tests/stress/fs_stress00.sh.in b/tests/fs-tests/stress/fs_stress00.sh.in
index 85ec7a2..f7d317c 100755
--- a/tests/fs-tests/stress/fs_stress00.sh.in
+++ b/tests/fs-tests/stress/fs_stress00.sh.in
@@ -1,10 +1,6 @@
#!/bin/sh
-prefix=@prefix@
-exec_prefix=@exec_prefix@
-bindir=@bindir@
-libexecpath=@libexecdir@/mtd-utils
-TESTBINDIR=@testbindir@
+TESTBINDIR=@TESTBINDIR@
TEST_DIR=$TEST_FILE_SYSTEM_MOUNT_DIR
if test -z "$TEST_DIR";
diff --git a/tests/fs-tests/stress/fs_stress01.sh.in b/tests/fs-tests/stress/fs_stress01.sh.in
index d0ea8f9..da6babf 100755
--- a/tests/fs-tests/stress/fs_stress01.sh.in
+++ b/tests/fs-tests/stress/fs_stress01.sh.in
@@ -1,10 +1,6 @@
#!/bin/sh
-prefix=@prefix@
-exec_prefix=@exec_prefix@
-bindir=@bindir@
-libexecpath=@libexecdir@/mtd-utils
-TESTBINDIR=@testbindir@
+TESTBINDIR=@TESTBINDIR@
TEST_DIR=$TEST_FILE_SYSTEM_MOUNT_DIR
if test -z "$TEST_DIR";
diff --git a/tests/jittertest/Makemodule.am b/tests/jittertest/Makemodule.am
index d4cc121..d280192 100644
--- a/tests/jittertest/Makemodule.am
+++ b/tests/jittertest/Makemodule.am
@@ -4,21 +4,8 @@ JitterTest_CPPFLAGS = $(AM_CPPFLAGS)
plotJittervsFill_SOURCES = tests/jittertest/plotJittervsFill.c
plotJittervsFill_CPPFLAGS = $(AM_CPPFLAGS)
-JITTEREST_BINS = \
- JitterTest plotJittervsFill
+test_PROGRAMS += JitterTest plotJittervsFill
-JITTERTEST_SH = \
- tests/jittertest/filljffs2.sh
+test_SCRIPTS += tests/jittertest/filljffs2.sh
-JITTERTEST_EXTRA = \
- tests/jittertest/README
-
-EXTRA_DIST += $(JITTERTEST_EXTRA) $(JITTERTEST_SH)
-
-if INSTALL_TESTS
-pkglibexec_SCRIPTS += $(JITTERTEST_SH)
-pkglibexec_PROGRAMS += $(JITTEREST_BINS)
-else
-noinst_SCRIPTS += $(JITTERTEST_SH)
-noinst_PROGRAMS += $(JITTEREST_BINS)
-endif
+EXTRA_DIST += tests/jittertest/README tests/jittertest/filljffs2.sh
diff --git a/tests/mtd-tests/Makemodule.am b/tests/mtd-tests/Makemodule.am
index 5925fd9..d02e9e4 100644
--- a/tests/mtd-tests/Makemodule.am
+++ b/tests/mtd-tests/Makemodule.am
@@ -7,9 +7,12 @@ flash_stress_LDADD = libmtd.a
flash_stress_CPPFLAGS = $(AM_CPPFLAGS)
flash_speed_SOURCES = tests/mtd-tests/flash_speed.c
-flash_speed_LDADD = libmtd.a
+flash_speed_LDADD = libmtd.a $(PTHREAD_LIBS)
flash_speed_CPPFLAGS = $(AM_CPPFLAGS)
+flash_speed_LDADD += $(PTHREAD_CFLAGS)
+flash_speed_CPPFLAGS += $(PTHREAD_CFLAGS)
+
nandbiterrs_SOURCES = tests/mtd-tests/nandbiterrs.c
nandbiterrs_LDADD = libmtd.a
nandbiterrs_CPPFLAGS = $(AM_CPPFLAGS)
@@ -26,12 +29,6 @@ nandsubpagetest_SOURCES = tests/mtd-tests/nandsubpagetest.c
nandsubpagetest_LDADD = libmtd.a
nandsubpagetest_CPPFLAGS = $(AM_CPPFLAGS)
-MTDTEST_BINS = \
+test_PROGRAMS += \
flash_torture flash_stress flash_speed nandbiterrs flash_readtest \
nandpagetest nandsubpagetest
-
-if INSTALL_TESTS
-pkglibexec_PROGRAMS += $(MTDTEST_BINS)
-else
-noinst_PROGRAMS += $(MTDTEST_BINS)
-endif
diff --git a/tests/mtd-tests/flash_readtest.c b/tests/mtd-tests/flash_readtest.c
index c5fabc9..519ff89 100644
--- a/tests/mtd-tests/flash_readtest.c
+++ b/tests/mtd-tests/flash_readtest.c
@@ -125,10 +125,14 @@ static void process_options(int argc, char **argv)
}
}
- if (optind < argc)
- mtddev = argv[optind++];
- else
+ if (optind < argc) {
+ mtddev = mtd_find_dev_node(argv[optind]);
+ if (!mtddev)
+ errmsg_die("Can't find MTD device %s", argv[optind]);
+ optind++;
+ } else {
errmsg_die("No device specified!\n");
+ }
if (optind < argc)
usage(EXIT_FAILURE);
@@ -227,7 +231,7 @@ int main(int argc, char **argv)
puts("not NAND flash, assume page size is 512 bytes.");
pgsize = 512;
} else {
- pgsize = mtd.subpage_size;
+ pgsize = mtd.min_io_size;
}
pgcnt = mtd.eb_size / pgsize;
diff --git a/tests/mtd-tests/flash_speed.c b/tests/mtd-tests/flash_speed.c
index 0058269..3489233 100644
--- a/tests/mtd-tests/flash_speed.c
+++ b/tests/mtd-tests/flash_speed.c
@@ -33,6 +33,7 @@
#include <stdlib.h>
#include <libmtd.h>
#include <getopt.h>
+#include <pthread.h>
#include <stdio.h>
#include <fcntl.h>
#include <time.h>
@@ -46,7 +47,7 @@ static const char *mtddev;
static libmtd_t mtd_desc;
static int fd;
-static int peb=-1, count=-1, skip=-1, flags=0;
+static int peb=-1, count=-1, skip=-1, flags=0, speb=-1;
static struct timespec start, finish;
static int pgsize, pgcnt;
static int goodebcnt;
@@ -57,6 +58,7 @@ static const struct option options[] = {
{ "peb", required_argument, NULL, 'b' },
{ "count", required_argument, NULL, 'c' },
{ "skip", required_argument, NULL, 's' },
+ { "sec-peb", required_argument, NULL, 'k' },
{ NULL, 0, NULL, 0 },
};
@@ -69,7 +71,8 @@ static NORETURN void usage(int status)
" -b, --peb <num> Start from this physical erase block\n"
" -c, --count <num> Number of erase blocks to use (default: all)\n"
" -s, --skip <num> Number of blocks to skip\n"
- " -d, --destructive Run destructive (erase and write speed) tests\n",
+ " -d, --destructive Run destructive (erase and write speed) tests\n"
+ " -k, --sec-peb <num> Start of secondary block to measure RWW latency (requires -d)\n",
status==EXIT_SUCCESS ? stdout : stderr);
exit(status);
}
@@ -93,7 +96,7 @@ static void process_options(int argc, char **argv)
int c;
while (1) {
- c = getopt_long(argc, argv, "hb:c:s:d", options, NULL);
+ c = getopt_long(argc, argv, "hb:c:s:dk:", options, NULL);
if (c == -1)
break;
@@ -126,15 +129,26 @@ static void process_options(int argc, char **argv)
goto failmulti;
flags |= DESTRUCTIVE;
break;
+ case 'k':
+ if (speb >= 0)
+ goto failmulti;
+ speb = read_num(c, optarg);
+ if (speb < 0)
+ goto failarg;
+ break;
default:
exit(EXIT_FAILURE);
}
}
- if (optind < argc)
- mtddev = argv[optind++];
- else
+ if (optind < argc) {
+ mtddev = mtd_find_dev_node(argv[optind]);
+ if (!mtddev)
+ errmsg_die("Can't find MTD device %s", argv[optind]);
+ optind++;
+ } else {
errmsg_die("No device specified!\n");
+ }
if (optind < argc)
usage(EXIT_FAILURE);
@@ -144,11 +158,15 @@ static void process_options(int argc, char **argv)
skip = 0;
if (count < 0)
count = 1;
+ if (speb >= 0 && !(flags & DESTRUCTIVE))
+ goto faildestr;
return;
failmulti:
errmsg_die("'-%c' specified more than once!\n", c);
failarg:
errmsg_die("Invalid argument for '-%c'!\n", c);
+faildestr:
+ errmsg_die("'-k' specified, -d is missing!\n");
}
static int write_eraseblock(int ebnum)
@@ -258,22 +276,29 @@ static int read_eraseblock_by_2pages(int ebnum)
return err;
}
-static void start_timing(void)
+static void start_timing(struct timespec *start)
{
- clock_gettime(CLOCK_MONOTONIC_RAW, &start);
+ clock_gettime(CLOCK_MONOTONIC_RAW, start);
}
-static void stop_timing(void)
+static void stop_timing(struct timespec *finish)
{
- clock_gettime(CLOCK_MONOTONIC_RAW, &finish);
+ clock_gettime(CLOCK_MONOTONIC_RAW, finish);
}
-static long calc_speed(void)
+static long calc_duration(struct timespec *start, struct timespec *finish)
{
long ms;
- ms = (finish.tv_sec - start.tv_sec) * 1000L;
- ms += (finish.tv_nsec - start.tv_nsec) / 1000000L;
+ ms = (finish->tv_sec - start->tv_sec) * 1000L;
+ ms += (finish->tv_nsec - start->tv_nsec) / 1000000L;
+
+ return ms;
+}
+
+static long calc_speed(struct timespec *start, struct timespec *finish)
+{
+ long ms = calc_duration(start, finish);
if (ms <= 0)
return 0;
@@ -313,8 +338,34 @@ static int erase_good_eraseblocks(unsigned int eb, int ebcnt, int ebskip)
return err;
}
+struct thread_arg {
+ int (*op)(int peb);
+ int peb;
+ struct timespec start;
+ struct timespec finish;
+};
+
+static void *op_thread(void *ptr)
+{
+ struct thread_arg *args = ptr;
+ unsigned long err = 0;
+ int i;
+
+ start_timing(&args->start);
+ for (i = 0; i < count; ++i) {
+ if (bbt[i])
+ continue;
+ err = args->op(args->peb + i * (skip + 1));
+ if (err)
+ break;
+ }
+ stop_timing(&args->finish);
+
+ return (void *)err;
+}
+
#define TIME_OP_PER_PEB( op )\
- start_timing();\
+ start_timing(&start);\
for (i = 0; i < count; ++i) {\
if (bbt[i])\
continue;\
@@ -322,8 +373,8 @@ static int erase_good_eraseblocks(unsigned int eb, int ebcnt, int ebskip)
if (err)\
goto out;\
}\
- stop_timing();\
- speed = calc_speed()
+ stop_timing(&finish);\
+ speed = calc_speed(&start, &finish)
int main(int argc, char **argv)
{
@@ -343,7 +394,7 @@ int main(int argc, char **argv)
puts("not NAND flash, assume page size is 512 bytes.");
pgsize = 512;
} else {
- pgsize = mtd.subpage_size;
+ pgsize = mtd.min_io_size;
}
pgcnt = mtd.eb_size / pgsize;
@@ -428,12 +479,12 @@ int main(int argc, char **argv)
/* Erase all eraseblocks */
if (flags & DESTRUCTIVE) {
puts("Testing erase speed");
- start_timing();
+ start_timing(&start);
err = erase_good_eraseblocks(peb, count, skip);
if (err)
goto out;
- stop_timing();
- speed = calc_speed();
+ stop_timing(&finish);
+ speed = calc_speed(&start, &finish);
printf("erase speed is %ld KiB/s\n", speed);
}
@@ -442,7 +493,7 @@ int main(int argc, char **argv)
for (k = 1; k < 7; ++k) {
blocks = 1 << k;
printf("Testing %dx multi-block erase speed\n", blocks);
- start_timing();
+ start_timing(&start);
for (i = 0; i < count; ) {
for (j = 0; j < blocks && (i + j) < count; ++j)
if (bbt[i + j])
@@ -456,13 +507,93 @@ int main(int argc, char **argv)
goto out;
i += j;
}
- stop_timing();
- speed = calc_speed();
+ stop_timing(&finish);
+ speed = calc_speed(&start, &finish);
printf("%dx multi-block erase speed is %ld KiB/s\n",
blocks, speed);
}
}
+ /* Write a page and immediately after try to read another page. Report
+ * the latency difference when performed on different banks (NOR only).
+ */
+ if (speb >= 0 && mtd.subpage_size == 1) {
+ long rww_duration_w, rww_latency_end;
+ long rww_duration_rnw, rww_duration_r_end;
+ bool rww_r_end_first;
+ struct thread_arg write_args_peb = {
+ .op = write_eraseblock,
+ .peb = peb,
+ };
+ struct thread_arg read_args_speb = {
+ .op = read_eraseblock,
+ .peb = speb,
+ };
+ struct sched_param param_write, param_read;
+ pthread_attr_t attr_write, attr_read;
+ pthread_t write_thread, read_thread;
+ void *retval;
+
+ puts("testing read while write latency");
+
+ /* Change scheduling priorities so that the write thread gets
+ *scheduled more aggressively than the read thread.
+ */
+ pthread_attr_init(&attr_write);
+ pthread_attr_setinheritsched(&attr_write, PTHREAD_EXPLICIT_SCHED);
+ pthread_attr_setschedpolicy(&attr_write, SCHED_FIFO);
+ param_write.sched_priority = 42;
+ pthread_attr_setschedparam(&attr_write, &param_write);
+
+ pthread_attr_init(&attr_read);
+ pthread_attr_setinheritsched(&attr_read, PTHREAD_EXPLICIT_SCHED);
+ pthread_attr_setschedpolicy(&attr_read, SCHED_FIFO);
+ param_read.sched_priority = 41;
+ pthread_attr_setschedparam(&attr_read, &param_read);
+
+ err = pthread_create(&write_thread, &attr_write,
+ (void *)op_thread, &write_args_peb);
+ if (err) {
+ errmsg("parallel write pthread create failed");
+ goto out;
+ }
+
+ err = pthread_create(&read_thread, &attr_read,
+ (void *)op_thread, &read_args_speb);
+ if (err) {
+ errmsg("parallel read pthread create failed");
+ goto out;
+ }
+
+ pthread_join(read_thread, &retval);
+ if ((long)retval) {
+ errmsg("parallel read pthread failed");
+ goto out;
+ }
+
+ pthread_join(write_thread, &retval);
+ if ((long)retval) {
+ errmsg("parallel write pthread failed");
+ goto out;
+ }
+
+ rww_duration_w = calc_duration(&write_args_peb.start,
+ &write_args_peb.finish);
+ rww_latency_end = calc_duration(&write_args_peb.finish,
+ &read_args_speb.finish);
+ rww_r_end_first = rww_latency_end < 0;
+ if (rww_r_end_first)
+ rww_duration_rnw = rww_duration_w;
+ else
+ rww_duration_rnw = calc_duration(&write_args_peb.start,
+ &read_args_speb.finish);
+
+ rww_duration_r_end = calc_duration(&write_args_peb.start,
+ &read_args_speb.finish);
+ printf("read while write took %ldms, read ended after %ldms\n",
+ rww_duration_rnw, rww_duration_r_end);
+ }
+
puts("finished");
status = EXIT_SUCCESS;
out:
diff --git a/tests/mtd-tests/flash_stress.c b/tests/mtd-tests/flash_stress.c
index 249d8cb..da39e14 100644
--- a/tests/mtd-tests/flash_stress.c
+++ b/tests/mtd-tests/flash_stress.c
@@ -126,10 +126,14 @@ static void process_options(int argc, char **argv)
}
}
- if (optind < argc)
- mtddev = argv[optind++];
- else
+ if (optind < argc) {
+ mtddev = mtd_find_dev_node(argv[optind]);
+ if (!mtddev)
+ errmsg_die("Can't find MTD device %s", argv[optind]);
+ optind++;
+ } else {
errmsg_die("No device specified!\n");
+ }
if (optind < argc)
usage(EXIT_FAILURE);
@@ -242,7 +246,7 @@ int main(int argc, char **argv)
puts("not NAND flash, assume page size is 512 bytes.");
pgsize = 512;
} else {
- pgsize = mtd.subpage_size;
+ pgsize = mtd.min_io_size;
}
pgcnt = mtd.eb_size / pgsize;
diff --git a/tests/mtd-tests/flash_torture.c b/tests/mtd-tests/flash_torture.c
index 5aad8e0..6363f9e 100644
--- a/tests/mtd-tests/flash_torture.c
+++ b/tests/mtd-tests/flash_torture.c
@@ -144,10 +144,14 @@ static void process_options(int argc, char **argv)
}
}
- if (optind < argc)
- mtddev = argv[optind++];
- else
+ if (optind < argc) {
+ mtddev = mtd_find_dev_node(argv[optind]);
+ if (!mtddev)
+ errmsg_die("Can't find MTD device %s", argv[optind]);
+ optind++;
+ } else {
errmsg_die("No device specified!\n");
+ }
if (optind < argc)
usage(EXIT_FAILURE);
diff --git a/tests/ubi-tests/Makemodule.am b/tests/ubi-tests/Makemodule.am
index d1fbab7..13d7b08 100644
--- a/tests/ubi-tests/Makemodule.am
+++ b/tests/ubi-tests/Makemodule.am
@@ -1,12 +1,15 @@
io_basic_SOURCES = tests/ubi-tests/io_basic.c tests/ubi-tests/helpers.c
+io_basic_SOURCES += tests/ubi-tests/helpers.h
io_basic_LDADD = libubi.a
io_basic_CPPFLAGS = $(AM_CPPFLAGS) -I$(top_srcdir)/ubi-utils/include
io_update_SOURCES = tests/ubi-tests/io_update.c tests/ubi-tests/helpers.c
+io_update_SOURCES += tests/ubi-tests/helpers.h
io_update_LDADD = libubi.a
io_update_CPPFLAGS = $(AM_CPPFLAGS) -I$(top_srcdir)/ubi-utils/include
io_paral_SOURCES = tests/ubi-tests/io_paral.c tests/ubi-tests/helpers.c
+io_paral_SOURCES += tests/ubi-tests/helpers.h
io_paral_LDADD = libubi.a $(PTHREAD_LIBS)
io_paral_CPPFLAGS = $(AM_CPPFLAGS) -I$(top_srcdir)/ubi-utils/include
@@ -14,26 +17,32 @@ io_paral_LDADD += $(PTHREAD_CFLAGS)
io_paral_CPPFLAGS += $(PTHREAD_CFLAGS)
io_read_SOURCES = tests/ubi-tests/io_read.c tests/ubi-tests/helpers.c
+io_read_SOURCES += tests/ubi-tests/helpers.h
io_read_LDADD = libubi.a
io_read_CPPFLAGS = $(AM_CPPFLAGS) -I$(top_srcdir)/ubi-utils/include
volrefcnt_SOURCES = tests/ubi-tests/volrefcnt.c tests/ubi-tests/helpers.c
+volrefcnt_SOURCES += tests/ubi-tests/helpers.h
volrefcnt_LDADD = libubi.a
volrefcnt_CPPFLAGS = $(AM_CPPFLAGS) -I$(top_srcdir)/ubi-utils/include
integ_SOURCES = tests/ubi-tests/integ.c tests/ubi-tests/helpers.c
+integ_SOURCES += tests/ubi-tests/helpers.h
integ_LDADD = libubi.a
integ_CPPFLAGS = $(AM_CPPFLAGS) -I$(top_srcdir)/ubi-utils/include
mkvol_basic_SOURCES = tests/ubi-tests/mkvol_basic.c tests/ubi-tests/helpers.c
+mkvol_basic_SOURCES += tests/ubi-tests/helpers.h
mkvol_basic_LDADD = libubi.a
mkvol_basic_CPPFLAGS = $(AM_CPPFLAGS) -I$(top_srcdir)/ubi-utils/include
mkvol_bad_SOURCES = tests/ubi-tests/mkvol_bad.c tests/ubi-tests/helpers.c
+mkvol_bad_SOURCES += tests/ubi-tests/helpers.h
mkvol_bad_LDADD = libubi.a
mkvol_bad_CPPFLAGS = $(AM_CPPFLAGS) -I$(top_srcdir)/ubi-utils/include
mkvol_paral_SOURCES = tests/ubi-tests/mkvol_paral.c tests/ubi-tests/helpers.c
+mkvol_paral_SOURCES += tests/ubi-tests/helpers.h
mkvol_paral_LDADD = libubi.a $(PTHREAD_LIBS)
mkvol_paral_CPPFLAGS = $(AM_CPPFLAGS) -I$(top_srcdir)/ubi-utils/include
@@ -41,25 +50,13 @@ mkvol_paral_LDADD += $(PTHREAD_CFLAGS)
mkvol_paral_CPPFLAGS += $(PTHREAD_CFLAGS)
rsvol_SOURCES = tests/ubi-tests/rsvol.c tests/ubi-tests/helpers.c
+rsvol_SOURCES += tests/ubi-tests/helpers.h
rsvol_LDADD = libubi.a
rsvol_CPPFLAGS = $(AM_CPPFLAGS) -I$(top_srcdir)/ubi-utils/include
-UBITEST_BINS = \
+test_PROGRAMS += \
io_basic io_update io_paral io_read volrefcnt integ \
mkvol_basic mkvol_bad mkvol_paral rsvol
-UBITEST_SH = \
+test_SCRIPTS += \
tests/ubi-tests/runubitests.sh tests/ubi-tests/ubi-stress-test.sh
-
-UBITEST_HEADER = \
- tests/ubi-tests/helpers.h
-
-EXTRA_DIST += $(UBITEST_HEADER)
-
-if INSTALL_TESTS
-pkglibexec_SCRIPTS += $(UBITEST_SH)
-pkglibexec_PROGRAMS += $(UBITEST_BINS)
-else
-noinst_SCRIPTS += $(UBITEST_SH)
-noinst_PROGRAMS += $(UBITEST_BINS)
-endif
diff --git a/tests/ubi-tests/runubitests.sh.in b/tests/ubi-tests/runubitests.sh.in
index a1b23c4..1675308 100755
--- a/tests/ubi-tests/runubitests.sh.in
+++ b/tests/ubi-tests/runubitests.sh.in
@@ -1,10 +1,6 @@
#!/bin/sh -euf
-prefix=@prefix@
-exec_prefix=@exec_prefix@
-bindir=@bindir@
-libexecpath=@libexecdir@/mtd-utils
-TESTBINDIR=@testbindir@
+TESTBINDIR=@TESTBINDIR@
tests="mkvol_basic mkvol_bad mkvol_paral rsvol io_basic io_read io_update io_paral volrefcnt"
diff --git a/tests/ubi-tests/ubi-stress-test.sh.in b/tests/ubi-tests/ubi-stress-test.sh.in
index 657ef4b..e178076 100755
--- a/tests/ubi-tests/ubi-stress-test.sh.in
+++ b/tests/ubi-tests/ubi-stress-test.sh.in
@@ -1,10 +1,6 @@
#!/bin/sh -euf
-prefix=@prefix@
-exec_prefix=@exec_prefix@
-bindir=@bindir@
-libexecpath=@libexecdir@/mtd-utils
-TESTBINDIR=@testbindir@
+TESTBINDIR=@TESTBINDIR@
fatal()
{
diff --git a/tests/unittests/Makemodule.am b/tests/unittests/Makemodule.am
index df1041d..277cac2 100644
--- a/tests/unittests/Makemodule.am
+++ b/tests/unittests/Makemodule.am
@@ -1,9 +1,11 @@
ubilib_test_SOURCES = tests/unittests/libubi_test.c lib/libubi.c
+ubilib_test_SOURCES += tests/unittests/test_lib.h
ubilib_test_LDADD = $(CMOCKA_LIBS)
ubilib_test_LDFLAGS = -Wl,--wrap=open -Wl,--wrap=close -Wl,--wrap=ioctl -Wl,--wrap=read -Wl,--wrap=lseek
ubilib_test_CPPFLAGS = -O0 --std=gnu99 $(CMOCKA_CFLAGS) -I$(top_srcdir)/include -DSYSFS_ROOT='"$(top_srcdir)/tests/unittests/sysfs_mock"'
mtdlib_test_SOURCES = tests/unittests/libmtd_test.c lib/libmtd.c lib/libmtd_legacy.c
+mtdlib_test_SOURCES += tests/unittests/test_lib.h
mtdlib_test_LDADD = $(CMOCKA_LIBS)
mtdlib_test_LDFLAGS = -Wl,--wrap=open -Wl,--wrap=close -Wl,--wrap=ioctl -Wl,--wrap=read -Wl,--wrap=lseek -Wl,--wrap=write
mtdlib_test_CPPFLAGS = -O0 -D_GNU_SOURCE --std=gnu99 $(CMOCKA_CFLAGS) -I$(top_srcdir)/lib/ -I$(top_srcdir)/include -DSYSFS_ROOT='"$(top_srcdir)/tests/unittests/sysfs_mock"'
@@ -12,13 +14,7 @@ TEST_BINS = \
ubilib_test \
mtdlib_test
-UNITTEST_HEADER = \
- tests/unittests/test_lib.h
-
-UNITTEST_EXTRA = \
- tests/unittests/sysfs_mock
-
-EXTRA_DIST += $(UNITTEST_HEADER) $(UNITTEST_EXTRA)
+EXTRA_DIST += tests/unittests/sysfs_mock
TESTS += $(TEST_BINS)
check_PROGRAMS += $(TEST_BINS)
diff --git a/ubi-utils/Makemodule.am b/ubi-utils/Makemodule.am
index 2835702..66c0238 100644
--- a/ubi-utils/Makemodule.am
+++ b/ubi-utils/Makemodule.am
@@ -22,9 +22,12 @@ ubidetach_LDADD = libmtd.a libubi.a
ubinize_SOURCES = ubi-utils/ubinize.c
ubinize_LDADD = libubi.a libubigen.a libmtd.a libiniparser.a
-ubiformat_SOURCES = ubi-utils/ubiformat.c
+ubiformat_SOURCES = ubi-utils/ubiformat.c include/mtd_swab.h
ubiformat_LDADD = libubi.a libubigen.a libmtd.a libscan.a
+ubiscan_SOURCES = ubi-utils/ubiscan.c include/mtd_swab.h
+ubiscan_LDADD = libubi.a libubigen.a libscan.a libmtd.a
+
ubirename_SOURCES = ubi-utils/ubirename.c
ubirename_LDADD = libmtd.a libubi.a
@@ -37,22 +40,16 @@ ubirsvol_LDADD = libmtd.a libubi.a
ubiblock_SOURCES = ubi-utils/ubiblock.c
ubiblock_LDADD = libmtd.a libubi.a
-if WITH_GETRANDOM
ubihealthd_SOURCES = ubi-utils/ubihealthd.c
ubihealthd_LDADD = libmtd.a libubi.a
-endif
-UBI_BINS = \
+sbin_PROGRAMS += \
ubiupdatevol ubimkvol ubirmvol ubicrc32 ubinfo ubiattach \
- ubidetach ubinize ubiformat ubirename mtdinfo ubirsvol ubiblock
+ ubidetach ubinize ubiformat ubirename mtdinfo ubirsvol ubiblock ubiscan
-if WITH_GETRANDOM
-UBI_BINS += ubihealthd
+if WITH_UBIHEALTHD
+sbin_PROGRAMS += ubihealthd
endif
-UBI_MAN = \
- ubi-utils/ubinize.8
-
-dist_man8_MANS += $(UBI_MAN)
+dist_man8_MANS += ubi-utils/ubinize.8
-sbin_PROGRAMS += $(UBI_BINS)
diff --git a/ubi-utils/mtdinfo.c b/ubi-utils/mtdinfo.c
index 0606ab0..7dff0de 100644
--- a/ubi-utils/mtdinfo.c
+++ b/ubi-utils/mtdinfo.c
@@ -30,6 +30,7 @@
#include <string.h>
#include <unistd.h>
#include <mtd/mtd-user.h>
+#include <mtd/ubi-media.h>
#include <libubigen.h>
#include <libmtd.h>
@@ -54,7 +55,7 @@ static void display_help(void)
printf(
"%1$s version %2$s - a tool to print MTD information.\n"
"\n"
- "Usage: %1$s <MTD node file path> [--map | -M] [--ubi-info | -u]\n"
+ "Usage: %1$s <mtd device> [--map | -M] [--ubi-info | -u]\n"
" %1$s --all [--ubi-info | -u]\n"
" %1$s [--help | --version]\n"
"\n"
@@ -68,6 +69,8 @@ static void display_help(void)
"-h, --help print help message\n"
"-V, --version print program version\n"
"\n"
+ "<mtd device> MTD device node or 'mtd:<name>'\n"
+ "\n"
"Examples:\n"
" %1$s /dev/mtd0 print information MTD device /dev/mtd0\n"
" %1$s /dev/mtd0 -u print information MTD device /dev/mtd0\n"
@@ -124,10 +127,13 @@ static int parse_opt(int argc, char * const argv[])
}
}
- if (optind == argc - 1)
- args.node = argv[optind];
- else if (optind < argc)
+ if (optind == argc - 1) {
+ args.node = mtd_find_dev_node(argv[optind]);
+ if (!args.node)
+ return errmsg("Failed to find MTD device %s", argv[optind]);
+ } else if (optind < argc) {
return errmsg("more then one MTD device specified (use -h for help)");
+ }
if (args.all && args.node)
args.node = NULL;
@@ -161,7 +167,7 @@ static void print_ubi_info(const struct mtd_info *mtd_info,
struct ubigen_info ui;
if (!mtd_info->sysfs_supported) {
- errmsg("cannot provide UBI info, becasue sub-page size is "
+ errmsg("cannot provide UBI info, because sub-page size is "
"not known");
return;
}
diff --git a/ubi-utils/ubiattach.c b/ubi-utils/ubiattach.c
index 09f85af..e758dab 100644
--- a/ubi-utils/ubiattach.c
+++ b/ubi-utils/ubiattach.c
@@ -42,6 +42,8 @@ struct args {
const char *node;
const char *dev;
int max_beb_per1024;
+ bool disable_fm;
+ bool need_resv_pool;
};
static struct args args = {
@@ -51,6 +53,8 @@ static struct args args = {
.node = NULL,
.dev = NULL,
.max_beb_per1024 = 0,
+ .disable_fm = false,
+ .need_resv_pool = false,
};
static const char doc[] = PROGRAM_NAME " version " VERSION
@@ -67,6 +71,11 @@ static const char optionsstr[] =
"-b, --max-beb-per1024 maximum expected bad block number per 1024 eraseblock.\n"
" The default value is correct for most NAND devices.\n"
" Allowed range is 0-768, 0 means the default kernel value.\n"
+"-f, --disable-fastmap don't create new fastmap and do full scanning (existed\n"
+" fastmap will be destroyed) for the given ubi device.\n"
+"-r, --reserve-pool Slow down the frequency of updating fastmap by reserving\n"
+" pebs for filling pool/wl_pool, which can prolong flash\n"
+" service life.\n"
"-h, --help print help message\n"
"-V, --version print program version";
@@ -74,7 +83,7 @@ static const char usage[] =
"Usage: " PROGRAM_NAME " [<UBI control device node file name>]\n"
"\t[-m <MTD device number>] [-d <UBI device number>] [-p <path to device>]\n"
"\t[--mtdn=<MTD device number>] [--devn=<UBI device number>]\n"
-"\t[--dev-path=<path to device>]\n"
+"\t[--dev-path=<path to device>] [-f] [--disable-fastmap] [-r] [--reserve-pool]\n"
"\t[--max-beb-per1024=<maximum bad block number per 1024 blocks>]\n"
"UBI control device defaults to " DEFAULT_CTRL_DEV " if not supplied.\n"
"Example 1: " PROGRAM_NAME " -p /dev/mtd0 - attach /dev/mtd0 to UBI\n"
@@ -93,6 +102,8 @@ static const struct option long_options[] = {
{ .name = "mtdn", .has_arg = 1, .flag = NULL, .val = 'm' },
{ .name = "vid-hdr-offset", .has_arg = 1, .flag = NULL, .val = 'O' },
{ .name = "max-beb-per1024", .has_arg = 1, .flag = NULL, .val = 'b' },
+ { .name = "disable-fastmap", .has_arg = 0, .flag = NULL, .val = 'f' },
+ { .name = "reserve-pool", .has_arg = 0, .flag = NULL, .val = 'r' },
{ .name = "help", .has_arg = 0, .flag = NULL, .val = 'h' },
{ .name = "version", .has_arg = 0, .flag = NULL, .val = 'V' },
{ NULL, 0, NULL, 0},
@@ -103,7 +114,7 @@ static int parse_opt(int argc, char * const argv[])
while (1) {
int key, error = 0;
- key = getopt_long(argc, argv, "p:m:d:O:b:hV", long_options, NULL);
+ key = getopt_long(argc, argv, "p:m:d:O:b:frhV", long_options, NULL);
if (key == -1)
break;
@@ -143,6 +154,14 @@ static int parse_opt(int argc, char * const argv[])
break;
+ case 'f':
+ args.disable_fm = true;
+ break;
+
+ case 'r':
+ args.need_resv_pool = true;
+ break;
+
case 'h':
printf("%s\n\n", doc);
printf("%s\n\n", usage);
@@ -213,6 +232,8 @@ int main(int argc, char * const argv[])
req.vid_hdr_offset = args.vidoffs;
req.mtd_dev_node = args.dev;
req.max_beb_per1024 = args.max_beb_per1024;
+ req.disable_fm = args.disable_fm;
+ req.need_resv_pool = args.need_resv_pool;
err = ubi_attach(libubi, args.node, &req);
if (err < 0) {
diff --git a/ubi-utils/ubinfo.c b/ubi-utils/ubinfo.c
index 29530be..6c5b19e 100644
--- a/ubi-utils/ubinfo.c
+++ b/ubi-utils/ubinfo.c
@@ -417,12 +417,9 @@ int main(int argc, char * const argv[])
goto out_libubi;
}
- if (args.devn != -1 && args.vol_id != -1) {
- print_vol_info(libubi, args.devn, args.vol_id);
- goto out;
- }
-
- if (args.devn == -1 && args.vol_id == -1)
+ if (args.devn != -1 && args.vol_id != -1)
+ err = print_vol_info(libubi, args.devn, args.vol_id);
+ else if (args.devn == -1 && args.vol_id == -1)
err = print_general_info(libubi, args.all);
else if (args.devn != -1 && args.vol_id == -1)
err = print_dev_info(libubi, args.devn, args.all);
@@ -430,7 +427,6 @@ int main(int argc, char * const argv[])
if (err)
goto out_libubi;
-out:
libubi_close(libubi);
return 0;
diff --git a/ubi-utils/ubinize.c b/ubi-utils/ubinize.c
index 967b65c..ac8c1e5 100644
--- a/ubi-utils/ubinize.c
+++ b/ubi-utils/ubinize.c
@@ -376,7 +376,7 @@ static int read_section(const struct ubigen_info *ui, const char *sname,
if (vi->alignment == -1)
vi->alignment = 1;
else if (vi->id < 0)
- return errmsg("negative volume alignement %d in section \"%s\"",
+ return errmsg("negative volume alignment %d in section \"%s\"",
vi->alignment, sname);
verbose(args.verbose, "volume alignment: %d", vi->alignment);
diff --git a/ubi-utils/ubiscan.c b/ubi-utils/ubiscan.c
new file mode 100644
index 0000000..66af12a
--- /dev/null
+++ b/ubi-utils/ubiscan.c
@@ -0,0 +1,318 @@
+/*
+ * Copyright (C) 2021 Diego Ismirlian
+ *
+ * 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.
+ */
+
+/*
+ * An utility to scan MTD devices.
+ *
+ * Author: Diego Ismirlian dismirlian (at) google's mail
+ */
+
+#define PROGRAM_NAME "ubiscan"
+
+#include <sys/stat.h>
+#include <unistd.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <fcntl.h>
+#include <limits.h>
+
+#include <mtd/ubi-media.h>
+#include <libubi.h>
+#include <libmtd.h>
+#include <libscan.h>
+#include "common.h"
+
+#define MAX_BINS 50
+
+/* The variables below are set by command line arguments */
+struct args {
+ int verbose;
+ const char *node;
+ int node_fd;
+ int bin_thresholds[MAX_BINS - 1];
+ int nbins;
+};
+
+static struct args args = {
+ .verbose = 0,
+ .nbins = 6,
+ .bin_thresholds = {
+ 10,
+ 100,
+ 1000,
+ 10000,
+ 100000,
+ },
+};
+
+static const char doc[] = PROGRAM_NAME " version " VERSION
+ " - a tool to scan MTD devices";
+
+static const char optionsstr[] =
+"-h, -?, --help print help message\n"
+"-H, --histrogram=<list> comma-separated list of bin thresholds\n"
+"-v, --verbose be verbose\n"
+"-V, --version print program version\n";
+
+static const char usage[] =
+"Usage: " PROGRAM_NAME " <MTD device node file name> "
+"\t\t\t[--help] [--version] [--verbose] [--histogram=<list>]";
+
+static const struct option long_options[] = {
+ { .name = "help", .has_arg = 0, .flag = NULL, .val = 'h' },
+ { .name = "histogram", .has_arg = 1, .flag = NULL, .val = 'H' },
+ { .name = "verbose", .has_arg = 0, .flag = NULL, .val = 'v' },
+ { .name = "version", .has_arg = 0, .flag = NULL, .val = 'V' },
+ { NULL, 0, NULL, 0},
+};
+
+static int parse_opt(int argc, char * const argv[])
+{
+ int last_bin = 0;
+ while (1) {
+ int key;
+
+ key = getopt_long(argc, argv, "h?VvH:", long_options, NULL);
+ if (key == -1)
+ break;
+
+ switch (key) {
+ case 'v':
+ args.verbose = 1;
+ break;
+ case 'H': {
+ args.nbins = 1;
+ char *token = strtok(optarg, ",");
+ while (token) {
+ if (args.nbins == MAX_BINS)
+ return errmsg("too many bins");
+ int th = atoi(token);
+ if (th <= last_bin)
+ return errmsg("bad bin threshold list");
+ args.bin_thresholds[args.nbins - 1] = th;
+ last_bin = th;
+ args.nbins++;
+ token = strtok(NULL, ",");
+ }
+ } break;
+ case 'V':
+ common_print_version();
+ exit(EXIT_SUCCESS);
+ case 'h':
+ printf("%s\n\n", doc);
+ printf("%s\n\n", usage);
+ printf("%s\n", optionsstr);
+ exit(EXIT_SUCCESS);
+ case '?':
+ printf("%s\n\n", doc);
+ printf("%s\n\n", usage);
+ printf("%s\n", optionsstr);
+ return -1;
+
+ case ':':
+ return errmsg("parameter is missing");
+
+ default:
+ fprintf(stderr, "Use -h for help\n");
+ return -1;
+ }
+ }
+
+ if (optind == argc)
+ return errmsg("MTD device name was not specified (use -h for help)");
+ else if (optind != argc - 1)
+ return errmsg("more then one MTD device specified (use -h for help)");
+
+ args.node = argv[optind];
+ return 0;
+}
+
+int main(int argc, char * const argv[])
+{
+ int err;
+ libmtd_t libmtd;
+ struct mtd_info mtd_info;
+ struct mtd_dev_info mtd;
+ struct ubi_scan_info *si;
+ int max, min;
+
+ struct {
+ int min;
+ int max;
+ int cnt;
+ uint64_t mean;
+ } bins[MAX_BINS];
+
+ err = parse_opt(argc, argv);
+ if (err)
+ return -1;
+
+ libmtd = libmtd_open();
+ if (!libmtd)
+ return errmsg("MTD subsystem is not present");
+
+ err = mtd_get_info(libmtd, &mtd_info);
+ if (err) {
+ sys_errmsg("cannot get MTD information");
+ goto out_close_mtd;
+ }
+
+ err = mtd_get_dev_info(libmtd, args.node, &mtd);
+ if (err) {
+ sys_errmsg("cannot get information about \"%s\"", args.node);
+ goto out_close_mtd;
+ }
+
+ args.node_fd = open(args.node, O_RDONLY);
+ if (args.node_fd == -1) {
+ sys_errmsg("cannot open \"%s\"", args.node);
+ goto out_close_mtd;
+ }
+
+ printf("Summary\n");
+ printf("=========================================================\n");
+ printf("mtd : %d\n", mtd.mtd_num);
+ printf("type : %s\n", mtd.type_str);
+ printf("size : ");
+ util_print_bytes(mtd.size, 1);
+ printf("\n");
+ printf("PEBs : %d\n", mtd.eb_cnt);
+ printf("min I/O: %d bytes\n", mtd.min_io_size);
+
+ printf("\n");
+ printf("PEB erase counters\n");
+ printf("=========================================================\n");
+ err = ubi_scan(&mtd, args.node_fd, &si, 0);
+ if (err) {
+ errmsg("failed to scan mtd%d (%s)", mtd.mtd_num, args.node);
+ goto out_close;
+ }
+
+ memset(bins, 0, sizeof(bins));
+
+ for (int j = 0; j < args.nbins; j++)
+ bins[j].min = INT_MAX;
+
+ min = INT_MAX;
+ max = 0;
+
+ for (int eb = 0; eb < mtd.eb_cnt; eb++) {
+ uint32_t ec = si->ec[eb];
+ switch (ec) {
+ case EB_EMPTY:
+ case EB_CORRUPTED:
+ case EB_ALIEN:
+ case EB_BAD:
+ case EC_MAX:
+ break;
+ default: {
+ int bin = 0;
+
+ if (ec > max)
+ max = ec;
+ if (ec < min)
+ min = ec;
+
+ for (int j = 0; j < args.nbins - 1 && ec >= args.bin_thresholds[j]; j++, bin++);
+
+ bins[bin].cnt++;
+ bins[bin].mean += ec;
+ if (ec < bins[bin].min)
+ bins[bin].min = ec;
+ if (ec > bins[bin].max)
+ bins[bin].max = ec;
+
+ } break;
+ }
+ }
+
+ printf("valid : %d\n", si->ok_cnt);
+ printf("empty : %d\n", si->empty_cnt);
+ printf("corrupted: %d\n", si->corrupted_cnt);
+ printf("alien : %d\n", si->alien_cnt);
+ printf("bad : %d\n", si->bad_cnt);
+
+ if (si->ok_cnt == 0)
+ min = 0;
+
+ printf("\n");
+ printf("Histogram\n");
+ printf("=========================================================\n");
+ printf("from to count min avg max\n");
+ printf("---------------------------------------------------------\n");
+ for (int j = 0; j < args.nbins; j++) {
+ if (bins[j].cnt)
+ bins[j].mean /= bins[j].cnt;
+ else
+ bins[j].min = 0;
+
+ int from = (j == 0) ? 0 : args.bin_thresholds[j - 1];
+ if (j == args.nbins - 1)
+ printf("%-8d .. inf: %8d %8d %8" PRIu64 " %8d\n",
+ from, bins[j].cnt, bins[j].min, bins[j].mean, bins[j].max);
+ else
+ printf("%-8d .. %8d: %8d %8d %8" PRIu64 " %8d\n",
+ from, args.bin_thresholds[j] - 1,
+ bins[j].cnt, bins[j].min, bins[j].mean, bins[j].max);
+ }
+ printf("---------------------------------------------------------\n");
+ printf("Total : %8d %8d %8llu %8d\n", si->ok_cnt, min, si->mean_ec, max);
+
+ if (args.verbose) {
+ printf("\n");
+ printf("Details\n");
+ printf("=========================================================\n");
+ for (int eb = 0; eb < mtd.eb_cnt; eb++) {
+ printf("PEB %8d: ", eb);
+ uint32_t ec = si->ec[eb];
+ switch (ec) {
+ case EB_EMPTY:
+ printf("EB_EMPTY\n");
+ break;
+ case EB_CORRUPTED:
+ printf("EB_CORRUPTED\n");
+ break;
+ case EB_ALIEN:
+ printf("EB_ALIEN\n");
+ break;
+ case EB_BAD:
+ printf("EB_BAD\n");
+ break;
+ case EC_MAX:
+ printf("EC_MAX\n");
+ break;
+ default:
+ printf("%u\n", ec);
+ break;
+ }
+ }
+ }
+
+ ubi_scan_free(si);
+ close(args.node_fd);
+ libmtd_close(libmtd);
+ return 0;
+
+out_close:
+ close(args.node_fd);
+out_close_mtd:
+ libmtd_close(libmtd);
+ return -1;
+}
+
diff --git a/ubifs-utils/Makemodule.am b/ubifs-utils/Makemodule.am
index 59109cc..6814d47 100644
--- a/ubifs-utils/Makemodule.am
+++ b/ubifs-utils/Makemodule.am
@@ -16,11 +16,14 @@ mkfs_ubifs_SOURCES = \
ubifs-utils/mkfs.ubifs/hashtable/hashtable_private.h \
ubifs-utils/mkfs.ubifs/hashtable/hashtable.c \
ubifs-utils/mkfs.ubifs/hashtable/hashtable_itr.c \
- ubifs-utils/mkfs.ubifs/devtable.c
+ ubifs-utils/mkfs.ubifs/devtable.c \
+ include/mtd/ubifs-media.h
if WITH_CRYPTO
mkfs_ubifs_SOURCES += ubifs-utils/mkfs.ubifs/crypto.c \
+ ubifs-utils/mkfs.ubifs/crypto.h \
ubifs-utils/mkfs.ubifs/fscrypt.c \
+ ubifs-utils/mkfs.ubifs/fscrypt.h \
ubifs-utils/mkfs.ubifs/sign.c
endif
@@ -28,23 +31,8 @@ mkfs_ubifs_LDADD = libmtd.a libubi.a $(ZLIB_LIBS) $(LZO_LIBS) $(ZSTD_LIBS) $(UUI
mkfs_ubifs_CPPFLAGS = $(AM_CPPFLAGS) $(ZLIB_CFLAGS) $(LZO_CFLAGS) $(ZSTD_CFLAGS) $(UUID_CFLAGS) $(LIBSELINUX_CFLAGS)\
-I$(top_srcdir)/ubi-utils/include -I$(top_srcdir)/ubifs-utils/mkfs.ubifs/
-UBIFS_BINS = \
- mkfs.ubifs
+EXTRA_DIST += ubifs-utils/mkfs.ubifs/README
-UBIFS_HEADER = \
- ubifs-utils/mkfs.ubifs/compr.h ubifs-utils/mkfs.ubifs/crc16.h \
- ubifs-utils/mkfs.ubifs/defs.h ubifs-utils/mkfs.ubifs/key.h \
- ubifs-utils/mkfs.ubifs/lpt.h ubifs-utils/mkfs.ubifs/mkfs.ubifs.h \
- ubifs-utils/mkfs.ubifs/ubifs.h \
- ubifs-utils/mkfs.ubifs/crypto.h \
- ubifs-utils/mkfs.ubifs/fscrypt.h \
- ubifs-utils/mkfs.ubifs/hashtable/hashtable.h \
- ubifs-utils/mkfs.ubifs/hashtable/hashtable_itr.h \
- ubifs-utils/mkfs.ubifs/hashtable/hashtable_private.h
-
-UBIFS_EXTRA = \
- ubifs-utils/mkfs.ubifs/README
-
-EXTRA_DIST += $(UBIFS_HEADER) $(UBIFS_EXTRA)
+dist_sbin_SCRIPTS = ubifs-utils/mount.ubifs
-sbin_PROGRAMS += $(UBIFS_BINS)
+sbin_PROGRAMS += mkfs.ubifs
diff --git a/ubifs-utils/mkfs.ubifs/compr.c b/ubifs-utils/mkfs.ubifs/compr.c
index 06c35ca..e4324f3 100644
--- a/ubifs-utils/mkfs.ubifs/compr.c
+++ b/ubifs-utils/mkfs.ubifs/compr.c
@@ -24,27 +24,30 @@
#include <stdio.h>
#include <stdint.h>
#include <string.h>
-#ifndef WITHOUT_LZO
+#ifdef WITH_LZO
#include <lzo/lzo1x.h>
#endif
#include <linux/types.h>
-#ifndef WITHOUT_ZSTD
+#ifdef WITH_ZSTD
#include <zstd.h>
#endif
+#ifdef WITH_ZLIB
#define crc32 __zlib_crc32
#include <zlib.h>
#undef crc32
+#endif
#include "compr.h"
#include "mkfs.ubifs.h"
static void *lzo_mem;
static unsigned long long errcnt = 0;
-#ifndef WITHOUT_LZO
+#ifdef WITH_LZO
static struct ubifs_info *c = &info_;
#endif
+#ifdef WITH_ZLIB
#define DEFLATE_DEF_LEVEL Z_DEFAULT_COMPRESSION
#define DEFLATE_DEF_WINBITS 11
#define DEFLATE_DEF_MEMLEVEL 8
@@ -91,8 +94,9 @@ static int zlib_deflate(void *in_buf, size_t in_len, void *out_buf,
return 0;
}
+#endif
-#ifndef WITHOUT_LZO
+#ifdef WITH_LZO
static int lzo_compress(void *in_buf, size_t in_len, void *out_buf,
size_t *out_len)
{
@@ -112,7 +116,7 @@ static int lzo_compress(void *in_buf, size_t in_len, void *out_buf,
}
#endif
-#ifndef WITHOUT_ZSTD
+#ifdef WITH_ZSTD
static ZSTD_CCtx *zctx;
static int zstd_compress(void *in_buf, size_t in_len, void *out_buf,
@@ -140,7 +144,7 @@ static int no_compress(void *in_buf, size_t in_len, void *out_buf,
static char *zlib_buf;
-#ifndef WITHOUT_LZO
+#if defined(WITH_LZO) && defined(WITH_ZLIB)
static int favor_lzo_compress(void *in_buf, size_t in_len, void *out_buf,
size_t *out_len, int *type)
{
@@ -198,22 +202,25 @@ int compress_data(void *in_buf, size_t in_len, void *out_buf, size_t *out_len,
return MKFS_UBIFS_COMPR_NONE;
}
-#ifdef WITHOUT_LZO
- {
- switch (type) {
-#else
+#if defined(WITH_LZO) && defined(WITH_ZLIB)
if (c->favor_lzo)
ret = favor_lzo_compress(in_buf, in_len, out_buf, out_len, &type);
else {
+#else
+ {
+#endif
switch (type) {
+#ifdef WITH_LZO
case MKFS_UBIFS_COMPR_LZO:
ret = lzo_compress(in_buf, in_len, out_buf, out_len);
break;
#endif
+#ifdef WITH_ZLIB
case MKFS_UBIFS_COMPR_ZLIB:
ret = zlib_deflate(in_buf, in_len, out_buf, out_len);
break;
-#ifndef WITHOUT_ZSTD
+#endif
+#ifdef WITH_ZSTD
case MKFS_UBIFS_COMPR_ZSTD:
ret = zstd_compress(in_buf, in_len, out_buf, out_len);
break;
@@ -236,7 +243,7 @@ int compress_data(void *in_buf, size_t in_len, void *out_buf, size_t *out_len,
int init_compression(void)
{
-#ifdef WITHOUT_LZO
+#ifndef WITH_LZO
lzo_mem = NULL;
#else
lzo_mem = malloc(LZO1X_999_MEM_COMPRESS);
@@ -244,11 +251,15 @@ int init_compression(void)
return -1;
#endif
+#ifndef WITH_ZLIB
+ zlib_buf = NULL;
+#else
zlib_buf = malloc(UBIFS_BLOCK_SIZE * WORST_COMPR_FACTOR);
if (!zlib_buf)
goto err;
+#endif
-#ifndef WITHOUT_ZSTD
+#ifdef WITH_ZSTD
zctx = ZSTD_createCCtx();
if (!zctx)
goto err;
@@ -265,7 +276,7 @@ void destroy_compression(void)
{
free(zlib_buf);
free(lzo_mem);
-#ifndef WITHOUT_ZSTD
+#ifdef WITH_ZSTD
ZSTD_freeCCtx(zctx);
#endif
if (errcnt)
diff --git a/ubifs-utils/mkfs.ubifs/fscrypt.h b/ubifs-utils/mkfs.ubifs/fscrypt.h
index 34b799c..ff3d326 100644
--- a/ubifs-utils/mkfs.ubifs/fscrypt.h
+++ b/ubifs-utils/mkfs.ubifs/fscrypt.h
@@ -131,7 +131,7 @@ static inline void free_fscrypt_context(struct fscrypt_context *fctx)
{
(void)fctx;
- assert(0);
+ assert(!fctx);
}
static inline int encrypt_path(void **outbuf, void *data, unsigned int data_len,
@@ -163,7 +163,7 @@ static inline struct fscrypt_context *inherit_fscrypt_context(struct fscrypt_con
{
(void)fctx;
- assert(0);
+ assert(!fctx);
return NULL;
}
#endif /* WITH_CRYPTO */
diff --git a/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c b/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c
index d4be610..42a47f8 100644
--- a/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c
+++ b/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c
@@ -26,7 +26,7 @@
#include <crc32.h>
#include "common.h"
#include <sys/types.h>
-#ifndef WITHOUT_XATTR
+#ifdef WITH_XATTR
#include <sys/xattr.h>
#endif
@@ -35,7 +35,7 @@
#include <selinux/label.h>
#endif
-#ifndef WITHOUT_ZSTD
+#ifdef WITH_ZSTD
#include <zstd.h>
#endif
@@ -56,7 +56,6 @@
#ifdef WITH_SELINUX
#define XATTR_NAME_SELINUX "security.selinux"
static struct selabel_handle *sehnd;
-static char *secontext;
#endif
/**
@@ -210,9 +209,9 @@ static const char *helptext =
"Usage: mkfs.ubifs [OPTIONS] target\n"
"Make a UBIFS file system image from an existing directory tree\n\n"
"Examples:\n"
-"Build file system from directory /opt/img, writting the result in the ubifs.img file\n"
+"Build file system from directory /opt/img, writing the result in the ubifs.img file\n"
"\tmkfs.ubifs -m 512 -e 128KiB -c 100 -r /opt/img ubifs.img\n"
-"The same, but writting directly to an UBI volume\n"
+"The same, but writing directly to an UBI volume\n"
"\tmkfs.ubifs -r /opt/img /dev/ubi0_0\n"
"Creating an empty UBIFS filesystem on an UBI volume\n"
"\tmkfs.ubifs /dev/ubi0_0\n\n"
@@ -540,10 +539,12 @@ static void select_default_compr(void)
return;
}
-#ifdef WITHOUT_LZO
+#ifdef WITH_LZO
+ c->default_compr = UBIFS_COMPR_LZO;
+#elif defined(WITH_ZLIB)
c->default_compr = UBIFS_COMPR_ZLIB;
#else
- c->default_compr = UBIFS_COMPR_LZO;
+ c->default_compr = UBIFS_COMPR_NONE;
#endif
}
@@ -682,26 +683,30 @@ static int get_options(int argc, char**argv)
case 'x':
if (strcmp(optarg, "none") == 0)
c->default_compr = UBIFS_COMPR_NONE;
+#ifdef WITH_ZLIB
else if (strcmp(optarg, "zlib") == 0)
c->default_compr = UBIFS_COMPR_ZLIB;
-#ifndef WITHOUT_ZSTD
+#endif
+#ifdef WITH_ZSTD
else if (strcmp(optarg, "zstd") == 0)
c->default_compr = UBIFS_COMPR_ZSTD;
#endif
-#ifndef WITHOUT_LZO
+#ifdef WITH_LZO
+ else if (strcmp(optarg, "lzo") == 0)
+ c->default_compr = UBIFS_COMPR_LZO;
+#endif
+#if defined(WITH_LZO) && defined(WITH_ZLIB)
else if (strcmp(optarg, "favor_lzo") == 0) {
c->default_compr = UBIFS_COMPR_LZO;
c->favor_lzo = 1;
- } else if (strcmp(optarg, "lzo") == 0) {
- c->default_compr = UBIFS_COMPR_LZO;
}
#endif
else
return err_msg("bad compressor name");
break;
case 'X':
-#ifdef WITHOUT_LZO
- return err_msg("built without LZO support");
+#if !defined(WITH_LZO) && !defined(WITH_ZLIB)
+ return err_msg("built without LZO or ZLIB support");
#else
c->favor_percent = strtol(optarg, &endp, 0);
if (*endp != '\0' || endp == optarg ||
@@ -733,6 +738,7 @@ static int get_options(int argc, char**argv)
if (!context)
return err_msg("xmalloc failed\n");
memcpy(context, optarg, context_len);
+ context[context_len] = '\0';
/* Make sure root directory exists */
if (stat(context, &context_st))
@@ -1288,7 +1294,7 @@ out:
return ret;
}
-#ifdef WITHOUT_XATTR
+#ifndef WITH_XATTR
static inline int create_inum_attr(ino_t inum, const char *name)
{
(void)inum;
@@ -1388,6 +1394,15 @@ static int inode_add_xattr(struct ubifs_ino_node *host_ino,
continue;
}
+#ifdef WITH_SELINUX
+ /*
+ Ignore selinux attributes if we have a label file, they are
+ instead provided by inode_add_selinux_xattr.
+ */
+ if (!strcmp(name, XATTR_NAME_SELINUX) && context && sehnd)
+ continue;
+#endif
+
ret = add_xattr(host_ino, st, inum, name, attrbuf, attrsize);
if (ret < 0)
goto out_free;
@@ -1411,14 +1426,11 @@ static int inode_add_selinux_xattr(struct ubifs_ino_node *host_ino,
int ret;
char *sepath = NULL;
char *name;
- struct qstr nm;
unsigned int con_size;
+ char *secontext;
- if (!context || !sehnd) {
- secontext = NULL;
- con_size = 0;
+ if (!context || !sehnd)
return 0;
- }
if (path_name[strlen(root)] == '/')
sepath = strdup(&path_name[strlen(root)]);
@@ -1442,14 +1454,7 @@ static int inode_add_selinux_xattr(struct ubifs_ino_node *host_ino,
con_size = strlen(secontext) + 1;
name = strdup(XATTR_NAME_SELINUX);
- nm.name = name;
- nm.len = strlen(name);
- host_ino->xattr_cnt++;
- host_ino->xattr_size += CALC_DENT_SIZE(nm.len);
- host_ino->xattr_size += CALC_XATTR_BYTES(con_size);
- host_ino->xattr_names += nm.len;
-
- ret = add_xattr(st, inum, secontext, con_size, &nm);
+ ret = add_xattr(host_ino, st, inum, name, secontext, con_size);
if (ret < 0)
dbg_msg(2, "add_xattr failed %d\n", ret);
return ret;
@@ -1602,11 +1607,11 @@ static int add_inode(struct stat *st, ino_t inum, void *data,
len = UBIFS_INO_NODE_SZ + data_len;
if (xattr_path) {
-#ifdef WITH_SELINUX
ret = inode_add_selinux_xattr(ino, xattr_path, st, inum);
-#else
+ if (ret < 0)
+ return ret;
+
ret = inode_add_xattr(ino, xattr_path, st, inum);
-#endif
if (ret < 0)
return ret;
}
@@ -1859,10 +1864,12 @@ static int add_file(const char *path_name, struct stat *st, ino_t inum,
out_len = NODE_BUFFER_SIZE - UBIFS_DATA_NODE_SZ;
if (c->default_compr == UBIFS_COMPR_NONE &&
!c->encrypted && (flags & FS_COMPR_FL))
-#ifdef WITHOUT_LZO
+#ifdef WITH_LZO
+ use_compr = UBIFS_COMPR_LZO;
+#elif defined(WITH_ZLIB)
use_compr = UBIFS_COMPR_ZLIB;
#else
- use_compr = UBIFS_COMPR_LZO;
+ use_compr = UBIFS_COMPR_NONE;
#endif
else
use_compr = c->default_compr;
diff --git a/ubifs-utils/mkfs.ubifs/sign.c b/ubifs-utils/mkfs.ubifs/sign.c
index b7ad7ef..7f284f8 100644
--- a/ubifs-utils/mkfs.ubifs/sign.c
+++ b/ubifs-utils/mkfs.ubifs/sign.c
@@ -388,7 +388,8 @@ int init_authentication(void)
if (!c->hash_algo_name)
return err_msg("Hash algorithm not given (--hash-algo)");
- OPENSSL_no_config();
+ OPENSSL_config(NULL);
+
OpenSSL_add_all_algorithms();
ERR_load_crypto_strings();
diff --git a/ubifs-utils/mount.ubifs b/ubifs-utils/mount.ubifs
new file mode 100755
index 0000000..b94ddc5
--- /dev/null
+++ b/ubifs-utils/mount.ubifs
@@ -0,0 +1,101 @@
+#!/bin/sh
+
+# This script should be installed as /sbin/mount.ubifs. The benefit is that an
+# fstab entry like:
+#
+# mtd=mtddev:home /home ubifs defaults 0 0
+#
+# results in the ubi contained in the mtd named "mtddev" to be attached (if not
+# already done) and then the volume named "home" being mounted to /home.
+
+# This is called by mount with the following options:
+# /sbin/mount.ubifs spec dir [-sfnv] [-N namespace] [-o options] [-t type.subtype]
+
+spec="$1"
+shift
+
+mtdname2num() {
+ local name
+
+ name="$1"
+
+ for d in $(find /sys/class/mtd/ -regex '.*/mtd[0-9]*'); do
+ case "$d" in
+ *ro)
+ continue
+ ;;
+ esac
+
+ if test "$name" = "$(cat "$d/name")"; then
+ local dev mtdnum
+
+ dev="$(basename "$d")"
+ mtdnum="${dev#mtd}"
+ echo "$mtdnum"
+ return
+ fi
+ done
+
+ return 1
+}
+
+mtdnum2ubi() {
+ local mtdnum
+
+ mtdnum="$1"
+
+ for d in $(find /sys/class/ubi/ -regex '.*/ubi[0-9]*'); do
+ case "$d" in
+ *_[0-9]*)
+ continue
+ ;;
+ esac
+
+ if test "$mtdnum" = "$(cat "$d/mtd_num")"; then
+ local ubi
+
+ ubi="$(basename "$d")"
+ echo "$ubi"
+ return;
+ fi
+ done
+
+ return 1
+}
+
+mtdnum2ubi_autoattach() {
+ local mtdnum ubi
+
+ mtdnum="$1"
+
+ ubi="$(mtdnum2ubi "$mtdnum")" && { echo "$ubi"; return; }
+
+ # ubiattach might fail with "mtdX is already attached to ubiY" if there
+ # is more than one mount to do in the same mtd partition. So ignore errors.
+ ubiattach -m "$mtdnum" >&2 || true
+
+ mtdnum2ubi "$mtdnum"
+}
+
+case "$spec" in
+ mtd=*:*)
+ spec="${spec#mtd=}"
+ mtd="${spec%:*}"
+ rspec="${spec#*:}"
+
+ mtdnum="$(mtdname2num "$mtd")" || {
+ echo "Failed to find mtdnum for mtd \"$mtd\""
+ exit 1
+ }
+
+ ubi="$(mtdnum2ubi_autoattach "$mtdnum")" || {
+ echo "Failed to find ubi for mtd \"$mtd\""
+ exit 1
+ }
+
+ spec="$ubi:$rspec"
+
+ ;;
+esac
+
+/bin/mount -i -t ubifs "$spec" "$@"