aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore2
-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.am38
-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.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.am45
-rw-r--r--misc-utils/fectest.c2
-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/mtd_debug.c7
-rw-r--r--misc-utils/mtdpart.c9
-rw-r--r--nand-utils/Makemodule.am17
-rw-r--r--nand-utils/nanddump.c2
-rw-r--r--nand-utils/nandflipbits.c7
-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.c14
-rw-r--r--ubi-utils/ubiattach.c25
-rw-r--r--ubi-utils/ubinfo.c10
-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.c57
-rw-r--r--ubifs-utils/mkfs.ubifs/sign.c3
-rwxr-xr-xubifs-utils/mount.ubifs101
70 files changed, 3084 insertions, 859 deletions
diff --git a/.gitignore b/.gitignore
index 4c04c1a..8c51ee5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -24,6 +24,7 @@ fectest
flash_erase
flash_lock
flash_otp_dump
+flash_otp_erase
flash_otp_info
flash_otp_lock
flash_otp_write
@@ -99,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 9fd734b..266c12e 100644
--- a/jffsX-utils/Makemodule.am
+++ b/jffsX-utils/Makemodule.am
@@ -1,39 +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.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 9a86f6f..1ce1a68 100644
--- a/misc-utils/Makemodule.am
+++ b/misc-utils/Makemodule.am
@@ -1,27 +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
+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
@@ -29,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 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..eb1d33e 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;
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/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 b5a15ac..cee6777 100644
--- a/nand-utils/Makemodule.am
+++ b/nand-utils/Makemodule.am
@@ -7,29 +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
nandflipbits_SOURCES = nand-utils/nandflipbits.c
nandflipbits_LDADD = libmtd.a
-NAND_BINS = \
- nanddump nandwrite nandtest nftldump nftl_format nandflipbits
-
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
index aa6850f..7066408 100644
--- a/nand-utils/nandflipbits.c
+++ b/nand-utils/nandflipbits.c
@@ -203,7 +203,8 @@ int main(int argc, char **argv)
int page;
if (bits_to_flip[i].offset >= mtdlen) {
- fprintf(stderr, "Invalid byte offset %lld (max %lld)\n",
+ fprintf(stderr, "Invalid byte offset %" PRId64
+ " (max %" PRId64 ")\n",
bits_to_flip[i].offset, mtdlen);
ret = EXIT_FAILURE;
goto free_buf;
@@ -249,7 +250,9 @@ int main(int argc, char **argv)
bufoffs += mtd.min_io_size;
- ret = mtd_read_oob(mtd_desc, &mtd, fd, blkoffs,
+ 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");
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 8bd0fc8..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;
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/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 8211ada..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
/**
@@ -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;
@@ -1412,12 +1427,10 @@ static int inode_add_selinux_xattr(struct ubifs_ino_node *host_ino,
char *sepath = NULL;
char *name;
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)]);
@@ -1594,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;
}
@@ -1851,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" "$@"