# mtd-utils, ubifs half -- mkfs.ubifs builds a UBIFS image from a directory # tree and ubinize wraps one (or several) into the UBI container a real flash # is programmed with. Together they are the modern NAND authoring path, the # successor to the JFFS2 one 96-mtd-utils-jffs2 covers. # # THIS SUITE IS WRITE-ONLY, AND THAT IS A PROPERTY OF UPSTREAM, NOT OF THIS # PORT. mtd-utils 2.1.6 ships no UBIFS reader -- there is no ubifsdump or # fsck.ubifs to close the loop the way jffs2reader does for JFFS2, and the only # way to read a UBIFS volume back is to mount it on a kernel with a UBI stack. # So the assertions here are structural rather than round-trip: the superblock # magic and recorded compressor mkfs.ubifs wrote, the erase-counter magic and # PEB alignment ubinize wrote, and the fact that changing the compressor changes # the bytes. The compressor round-trip proof lives in the jffs2 suite, where # mkfs.jffs2 -t decompresses and compares in-process. # # NOTHING HERE TOUCHES /dev/ubi_ctrl. There is no MTD hardware behind a browser # tab; the last case asserts that the device-access tools fail CLEANLY rather # than pretending, which is the ticket's own premise stated as a test. . "$BST_LIB" require mkfs.ubifs mtd-utils-ubifs/mkfs-present require ubinize mtd-utils-ubifs/ubinize-present T=${TMPDIR:-/tmp}/bst-ubifs.$$ SRC=$T/src rm -rf "$T"; mkdir -p "$SRC/sub" MIN_IO=2048 # NAND page LEB=126976 # 124 KiB LEB inside a 128 KiB PEB PEB=128KiB msg() { _i=$1; _n=$2; shift 2; _o=$("$@" 2>&1) case "$_o" in *"$_n"*) bst_ok "$_i" ;; *) bst_notok "$_i" "want '$_n' got: $(_bst_1line "$_o")" ;; esac; } fails() { _i=$1; shift if "$@" >/dev/null 2>&1; then bst_notok "$_i" "unexpectedly succeeded" else bst_ok "$_i"; fi; } size() { wc -c < "$1" 2>/dev/null | tr -d ' '; } printf 'ubifs-payload-marker\n' > "$SRC/hello.txt" printf 'nested payload\n' > "$SRC/sub/nested.txt" ln -s hello.txt "$SRC/link.txt" # ~67 KiB of one repeated line -- see the note in the jffs2 suite on why this is # ten string doublings and not a shell loop. L='the quick brown fox jumps over the lazy dog 0123456789 ABCDEFGHIJ ' L="$L$L"; L="$L$L"; L="$L$L"; L="$L$L"; L="$L$L" L="$L$L"; L="$L$L"; L="$L$L"; L="$L$L"; L="$L$L" printf '%s' "$L" > "$SRC/fill.txt" msg mtd-utils-ubifs/mkfs-version "mkfs.ubifs (mtd-utils) 2.1.6" mkfs.ubifs -V # ------------------------------------------------------- authoring a UBIFS image # mkfs.ubifs's default compressor is lzo, so the plain invocation is already the # new recipe's first on-target exercise. check mtd-utils-ubifs/mkfs \ mkfs.ubifs -r "$SRC" -m $MIN_IO -e $LEB -c 200 -U -o "$T/lzo.ubifs" LZOSZ=$(size "$T/lzo.ubifs") if [ -n "$LZOSZ" ] && [ "$LZOSZ" -gt "$LEB" ]; then bst_ok mtd-utils-ubifs/image-nonempty else bst_notok mtd-utils-ubifs/image-nonempty "image is ${LZOSZ:-absent} bytes"; fi # Every UBIFS node opens with a common header carrying UBIFS_NODE_MAGIC # 0x06101831 little-endian -> bytes 31 18 10 06, and the node at offset 0 is the # superblock. A tool that wrote a plausible-looking file without formatting it # would miss this. check_eq mtd-utils-ubifs/sb-magic "31181006" \ "$(od -An -tx1 -N4 "$T/lzo.ubifs" 2>/dev/null | tr -d ' \n')" # ------------------------------------------------ the compressors, by selection check mtd-utils-ubifs/compr-zlib mkfs.ubifs -r "$SRC" -m $MIN_IO -e $LEB -c 200 -U -x zlib -o "$T/zlib.ubifs" check mtd-utils-ubifs/compr-none mkfs.ubifs -r "$SRC" -m $MIN_IO -e $LEB -c 200 -U -x none -o "$T/none.ubifs" check mtd-utils-ubifs/compr-favor-lzo mkfs.ubifs -r "$SRC" -m $MIN_IO -e $LEB -c 200 -U -x favor_lzo -o "$T/favor.ubifs" # THE SELECTION IS ASSERTED ON DISK, NOT THROUGH THE FILE SIZE. A size relation # is the obvious test and it is WRONG here: mkfs.ubifs lays out a fixed minimum # volume, so -x none, -x lzo and -x zlib over this payload all produce exactly # 1650688 bytes (13 LEBs) and a size comparison reports a working compressor as # broken. The superblock records the choice instead -- default_compr is a __le16 # at offset 84, immediately after the 24-byte common header and the fixed fields # ahead of it -- with UBIFS_COMPR_NONE=0, _LZO=1, _ZLIB=2. That is the value the # kernel itself would read at mount, so it is the selection that actually # reached the on-disk format. check_eq mtd-utils-ubifs/compr-recorded-none "0000" \ "$(od -An -tx1 -j84 -N2 "$T/none.ubifs" 2>/dev/null | tr -d ' \n')" check_eq mtd-utils-ubifs/compr-recorded-lzo "0100" \ "$(od -An -tx1 -j84 -N2 "$T/lzo.ubifs" 2>/dev/null | tr -d ' \n')" check_eq mtd-utils-ubifs/compr-recorded-zlib "0200" \ "$(od -An -tx1 -j84 -N2 "$T/zlib.ubifs" 2>/dev/null | tr -d ' \n')" # The three images must still differ from each other somewhere, or "selection" # meant nothing -- equal size does not license equal content. if [ "$(md5sum < "$T/none.ubifs" | cut -c1-32)" != "$(md5sum < "$T/lzo.ubifs" | cut -c1-32)" ]; then bst_ok mtd-utils-ubifs/compr-changes-content else bst_notok mtd-utils-ubifs/compr-changes-content "-x none and -x lzo produced identical bytes" fi # ------------------------------------------------------- wrapping it for a flash # ubinize turns the bare filesystem image into the UBI container a programmer # writes to NAND: EC and VID headers per PEB, and the volume table. -Q pins the # image sequence number, which is a RANDOM value by default -- without it two # runs over identical input produce different bytes, which would make any # determinism claim here false. cat > "$T/ubi.cfg" </dev/null | tr -d ' \n')" # The container is written PEB by PEB, so its length is an exact multiple of the # 128 KiB physical erase block and it must be bigger than the payload it carries. UBISZ=$(size "$T/ubi.img") if [ -n "$UBISZ" ] && [ $((UBISZ % 131072)) -eq 0 ] && [ "$UBISZ" -gt "$LZOSZ" ]; then bst_ok mtd-utils-ubifs/ubi-peb-aligned else bst_notok mtd-utils-ubifs/ubi-peb-aligned "ubi.img ${UBISZ:-absent} is not a >payload multiple of 131072" fi # ------------------------------------------------------------------- ubicrc32 # UBI's own CRC32 over a file. Asserting a hardcoded digest would pin this suite # to a payload; asserting determinism and discrimination proves the same # arithmetic without that coupling. if command -v ubicrc32 >/dev/null 2>&1; then C1=$(ubicrc32 "$SRC/hello.txt" 2>/dev/null) C2=$(ubicrc32 "$SRC/hello.txt" 2>/dev/null) C3=$(ubicrc32 "$SRC/sub/nested.txt" 2>/dev/null) if [ -n "$C1" ] && [ "$C1" = "$C2" ]; then bst_ok mtd-utils-ubifs/ubicrc32-deterministic else bst_notok mtd-utils-ubifs/ubicrc32-deterministic "'$C1' vs '$C2'"; fi if [ -n "$C1" ] && [ "$C1" != "$C3" ]; then bst_ok mtd-utils-ubifs/ubicrc32-discriminates else bst_notok mtd-utils-ubifs/ubicrc32-discriminates "different files both gave '$C1'"; fi else bst_skip mtd-utils-ubifs/ubicrc32-deterministic "ubicrc32 not installed on this image" bst_skip mtd-utils-ubifs/ubicrc32-discriminates "ubicrc32 not installed on this image" fi # ------------------------------------------------------------------- controls fails mtd-utils-ubifs/reject-bad-compr \ mkfs.ubifs -r "$SRC" -m $MIN_IO -e $LEB -c 200 -U -x nosuchcompressor -o "$T/bad.ubifs" # 5 LEBs cannot hold UBIFS' own log, LPT, orphan and root areas, let alone data. fails mtd-utils-ubifs/reject-tiny-volume \ mkfs.ubifs -r "$SRC" -m $MIN_IO -e $LEB -c 5 -U -o "$T/tiny.ubifs" fails mtd-utils-ubifs/reject-missing-cfg ubinize -o "$T/x.img" -m $MIN_IO -p $PEB "$T/no-such.cfg" # THE TICKET'S PREMISE, STATED AS A TEST. ubiattach needs /dev/ubi_ctrl, which # needs a UBI stack over an MTD device, and this kernel has neither. The case # asserts only that the tool FAILS -- it is documentation that the device half # of mtd-utils is inert here by design, not a defect report, and it would go red # only if a future kernel grew MTD support and nobody revisited the image's # package selection. if command -v ubiattach >/dev/null 2>&1; then fails mtd-utils-ubifs/no-mtd-hardware ubiattach -m 0 else bst_skip mtd-utils-ubifs/no-mtd-hardware "ubiattach not installed on this image" fi rm -rf "$T"