[OpenWrt-Devel] [PATCH v2] package/base-files: caldata: work around dd's limitation
Etienne Champetier
champetier.etienne at gmail.com
Sun May 17 16:24:25 EDT 2020
Hi Thibaut,
Le dim. 17 mai 2020 à 15:46, Thibaut VARÈNE <hacks at slashdirt.org> a écrit :
>
> tl;dr: dd will silently truncate the output if reading from special
> files (e.g. sysfs attributes) with a too large bs parameter.
>
> This problem was exposed on some RouterBOARD ipq40xx devices which use a
> caldata payload which is larger than PAGE_SIZE, contrary to all other
> currently supported RouterBOARD devices: the caldata would fail to
> properly load with the current scripts.
>
> Background: dd doesn't seem to correctly handle read() results that
> return less than requested data. sysfs attributes have a kernel exchange
> buffer which is at most PAGE_SIZE big, so only 1 page can be read() at a
> time. In this case, if bs is larger than PAGE_SIZE, dd will silently
> truncate blocks to PAGE_SIZE. With the current scripts using bs=<size>
> count=1, the data is truncated to PAGE_SIZE as soon as the requested
> <size> exceeds this value.
>
> This commit works around this problem by using `cat` in the caldata
> routines that can read from a file (routines that read from mtd devices
> are untouched). cat correctly handles partial read requests. The output
> is then piped to dd with the same parameters as before, to ensure that
> the resulting file remains exactly the same.
>
> This is a simple workaround, the downside is that it uses a pipe and one
> more executable, and therefore has a larger memory footprint and is
> slower. This is deemed acceptable considering these routines are only
> used at boot time.
>
> Tested-by: Robert Marko <robimarko at gmail.com>
> Signed-off-by: Thibaut VARÈNE <hacks at slashdirt.org>
> ---
> v2: leave a comment in scripts
> ---
> package/base-files/Makefile | 2 +-
> package/base-files/files/lib/functions/caldata.sh | 8 +++++---
> 2 files changed, 6 insertions(+), 4 deletions(-)
>
> diff --git a/package/base-files/Makefile b/package/base-files/Makefile
> index d8e7c31878..5fb275533d 100644
> --- a/package/base-files/Makefile
> +++ b/package/base-files/Makefile
> @@ -12,7 +12,7 @@ include $(INCLUDE_DIR)/version.mk
> include $(INCLUDE_DIR)/feeds.mk
>
> PKG_NAME:=base-files
> -PKG_RELEASE:=220
> +PKG_RELEASE:=221
> PKG_FLAGS:=nonshared
>
> PKG_FILE_DEPENDS:=$(PLATFORM_DIR)/ $(GENERIC_PLATFORM_DIR)/base-files/
> diff --git a/package/base-files/files/lib/functions/caldata.sh b/package/base-files/files/lib/functions/caldata.sh
> index 6862da7164..e22c7d27e6 100644
> --- a/package/base-files/files/lib/functions/caldata.sh
> +++ b/package/base-files/files/lib/functions/caldata.sh
> @@ -64,7 +64,8 @@ caldata_from_file() {
>
> [ -n "$target" ] || target=/lib/firmware/$FIRMWARE
>
> - dd if=$source of=$target iflag=skip_bytes bs=$count skip=$offset count=1 2>/dev/null || \
> + # dd doesn't handle partial reads from special files: use cat
> + cat $source | dd of=$target iflag=skip_bytes bs=$count skip=$offset count=1 2>/dev/null || \
Not way more elegant, but you could use something like
tail -c+$start $source | head -c$count > $target
with $start == $offset+1 I think
# head -c10 /dev/zero | wc
0 0 10
# head -c10 /dev/zero | tail -c+3 | wc
0 0 8
> caldata_die "failed to extract calibration data from $source"
> }
>
> @@ -73,13 +74,14 @@ caldata_sysfsload_from_file() {
> local offset=$(($2))
> local count=$(($3))
>
> + # dd doesn't handle partial reads from special files: use cat
> # test extract to /dev/null first
> - dd if=$source of=/dev/null iflag=skip_bytes bs=$count skip=$offset count=1 2>/dev/null || \
> + cat $source | dd of=/dev/null iflag=skip_bytes bs=$count skip=$offset count=1 2>/dev/null || \
> caldata_die "failed to extract calibration data from $source"
>
> # can't fail now
> echo 1 > /sys/$DEVPATH/loading
> - dd if=$source of=/sys/$DEVPATH/data iflag=skip_bytes bs=$count skip=$offset count=1 2>/dev/null
> + cat $source | dd of=/sys/$DEVPATH/data iflag=skip_bytes bs=$count skip=$offset count=1 2>/dev/null
> echo 0 > /sys/$DEVPATH/loading
> }
>
> --
> 2.11.0
>
>
> _______________________________________________
> openwrt-devel mailing list
> openwrt-devel at lists.openwrt.org
> https://lists.openwrt.org/mailman/listinfo/openwrt-devel
_______________________________________________
openwrt-devel mailing list
openwrt-devel at lists.openwrt.org
https://lists.openwrt.org/mailman/listinfo/openwrt-devel
More information about the openwrt-devel
mailing list