#!/bin/bash # (C) Copyright 2015 Stephen Warren # # SPDX-License-Identifier: GPL-2.0+ # This script tests U-Boot's FAT filesystem code's ability to read non- # contiguous files. # When porting the ff.c FAT parsing code into U-Boot, it was found that ff.c # always reads files cluster-by-cluster, which results in poor performance. # This was solved by adding a patch to ff.c to coalesce reads of adjacent # clusters. Since this patch needed to correctly handle non-contiguous files, # this test was written to validate that. # # To execute the test, simply run it from the U-Boot source root directory: # # cd u-boot # ./test/fs/fat-noncontig-test.sh # # The test will create a FAT filesystem image, record the CRC of a randomly # generated file in the image, build U-Boot sandbox, invoke U-Boot sandbox to # read the file and validate that the CRCs match. Expected output is shown # below. The important part of the log is the penultimate line that contains # either "PASS" or "FAILURE". # # mkfs.fat 3.0.26 (2014-03-07) # # # U-Boot 2015.10-rc4-00018-g4b22a3e5513f (Oct 03 2015 - 13:49:23 -0600) # # DRAM: 128 MiB # Using default environment # # In: serial # Out: lcd # Err: lcd # Net: No ethernet found. # => host bind 0 sandbox/fat-noncontig.img # => load host 0:0 1000 noncontig.img # 33584964 bytes read in 18 ms (1.7 GiB/s) # => crc32 1000 $filesize 0 # crc32 for 00001000 ... 02008743 ==> 6a080523 # => if itest.l *0 != 2305086a; then echo FAILURE; else echo PASS; fi # PASS # => reset # # All temporary files used by this script are created in ./sandbox to avoid # polluting the source tree. test/fs/fs-test.sh also uses this directory for # the same purpose. # # TODO: Integrate this (and many other corner-cases e.g. different types of # FAT) with fs-test.sh so that a single script tests everything filesystem- # related. odir=sandbox img=${odir}/fat-noncontig.img mnt=${odir}/mnt fill=/dev/urandom testfn=noncontig.img mnttestfn=${mnt}/${testfn} crcaddr=0 loadaddr=1000 for prereq in fallocate mkfs.fat dd crc32; do if [ ! -x "`which $prereq`" ]; then echo "Missing $prereq binary. Exiting!" exit 1 fi done make O=${odir} -s sandbox_defconfig && make O=${odir} -s -j8 mkdir -p ${mnt} if [ ! -f ${img} ]; then fallocate -l 40M ${img} if [ $? -ne 0 ]; then echo fallocate failed - using dd instead dd if=/dev/zero of=${img} bs=1024 count=$((40 * 1024)) if [ $? -ne 0 ]; then echo Could not create empty disk image exit $? fi fi mkfs.fat ${img} if [ $? -ne 0 ]; then echo Could not create FAT filesystem exit $? fi sudo mount -o loop,uid=$(id -u) ${img} ${mnt} if [ $? -ne 0 ]; then echo Could not mount test filesystem exit $? fi for ((sects=8; sects < 512; sects += 8)); do fn=${mnt}/keep-${sects}.img dd if=${fill} of=${fn} bs=512 count=${sects} >/dev/null 2>&1 fn=${mnt}/remove-${sects}.img dd if=${fill} of=${fn} bs=512 count=${sects} >/dev/null 2>&1 done rm -f ${mnt}/remove-*.img # 511 deliberately to trigger a file size that's not a multiple of the # sector size (ignoring sizes that are multiples of both). dd if=${fill} of=${mnttestfn} bs=511 >/dev/null 2>&1 sudo umount ${mnt} if [ $? -ne 0 ]; then echo Could not unmount test filesystem exit $? fi fi sudo mount -o ro,loop,uid=$(id -u) ${img} ${mnt} if [ $? -ne 0 ]; then echo Could not mount test filesystem exit $? fi crc=0x`crc32 ${mnttestfn}` sudo umount ${mnt} if [ $? -ne 0 ]; then echo Could not unmount test filesystem exit $? fi crc=`printf %02x%02x%02x%02x \ $((${crc} & 0xff)) \ $(((${crc} >> 8) & 0xff)) \ $(((${crc} >> 16) & 0xff)) \ $((${crc} >> 24))` ./sandbox/u-boot << EOF host bind 0 ${img} load host 0:0 ${loadaddr} ${testfn} crc32 ${loadaddr} \$filesize ${crcaddr} if itest.l *${crcaddr} != ${crc}; then echo FAILURE; else echo PASS; fi reset EOF if [ $? -ne 0 ]; then echo U-Boot exit status indicates an error exit $? fi