From: Jan Kiszka <jan.kiszka@siemens.com>
As an eMMC block device image may consist of more than just the user
data partition, provide a helper script that can compose the image from
boot partitions, an RPMB partition and the user data image. The script
also does the required size validation and/or rounding.
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---
scripts/mkemmc.sh | 219 ++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 219 insertions(+)
create mode 100755 scripts/mkemmc.sh
diff --git a/scripts/mkemmc.sh b/scripts/mkemmc.sh
new file mode 100755
index 0000000000..558548ffc7
--- /dev/null
+++ b/scripts/mkemmc.sh
@@ -0,0 +1,219 @@
+#!/bin/sh -e
+# SPDX-License-Identifier: GPL-2.0-only
+#
+# Create eMMC block device image from boot, RPMB and user data images
+#
+# Copyright (c) Siemens, 2025
+#
+# Authors:
+# Jan Kiszka <jan.kiszka@siemens.com>
+#
+# This work is licensed under the terms of the GNU GPL version 2.
+# See the COPYING file in the top-level directory.
+#
+
+usage() {
+ echo "$0 [OPTIONS] USER_IMG[:SIZE] OUTPUT_IMG"
+ echo ""
+ echo "SIZE must be a power of 2 up to 2G and multiples of 512 byte from there on."
+ echo "If no SIZE is specified, the size of USER_ING will be used (rounded up)."
+ echo ""
+ echo "Supported options:"
+ echo " -b BOOT1_IMG[:SIZE] Add boot partitions. SIZE must be multiples of 128K. If"
+ echo " no SIZE is specified, the size of BOOT1_IMG will be"
+ echo " used (rounded up). BOOT1_IMG will be stored in boot"
+ echo " partition 1, and a boot partition 2 of the same size"
+ echo " will be created as empty (all zeros) unless -B is"
+ echo " specified as well."
+ echo " -B BOOT2_IMG Fill boot partition 2 with BOOT2_IMG. Must be combined"
+ echo " with -b which is also defining the partition size."
+ echo " -r RPMB_IMG[:SIZE] Add RPMB partition. SIZE must be multiples of 128K. If"
+ echo " no SIZE is specified, the size of RPMB_IMG will be"
+ echo " used (rounded up)."
+ echo " -h, --help This help"
+ echo ""
+ echo "All SIZE parameters support the units K, M, G. If SIZE is smaller than the"
+ echo "associated image, it will be truncated in the output image."
+ exit "$1"
+}
+
+process_size() {
+ name=$1
+ image_file=$2
+ alignment=$3
+ image_arg=$4
+ if [ "${image_arg#*:}" = "$image_arg" ]; then
+ if ! size=$(stat -L -c %s "$image_file" 2>/dev/null); then
+ echo "Missing $name image '$image_file'." >&2
+ exit 1
+ fi
+ if [ "$alignment" = 128 ]; then
+ size=$(( (size + 128 * 1024 - 1) & ~(128 * 1024 - 1) ))
+ elif [ $size -gt $((2 * 1024 * 1024 * 1024)) ]; then
+ size=$(( (size + 511) & ~511 ))
+ elif [ $(( size & (size - 1) )) -gt 0 ]; then
+ n=0
+ while [ "$size" -gt 0 ]; do
+ size=$((size >> 1))
+ n=$((n + 1))
+ done
+ size=$((1 << n))
+ fi
+ else
+ value="${image_arg#*:}"
+ if [ "${value%K}" != "$value" ]; then
+ size=${value%K}
+ multiplier=1024
+ elif [ "${value%M}" != "$value" ]; then
+ size=${value%M}
+ multiplier=$((1024 * 1024))
+ elif [ "${value%G}" != "$value" ]; then
+ size=${value%G}
+ multiplier=$((1024 * 1024 * 1024))
+ else
+ size=$value
+ multiplier=1
+ fi
+ # check if "$size" is a valid integer by doing a self-comparison
+ if [ "$size" -eq "$size" ] 2>/dev/null; then
+ size=$((size * multiplier))
+ else
+ echo "Invalid value '$value' specified for $image_file image size." >&2
+ exit 1
+ fi
+ if [ "$alignment" = 128 ]; then
+ if [ $(( size & (128 * 1024 - 1) )) -ne 0 ]; then
+ echo "The $name image size must be multiples of 128K." >&2
+ exit 1
+ fi
+ elif [ $size -gt $((2 * 1024 * 1024 * 1024)) ]; then
+ if [ $(( size & 511)) -ne 0 ]; then
+ echo "The $name image size must be multiples of 512 (if >2G)." >&2
+ exit 1
+ fi
+ elif [ $(( size & (size - 1) )) -gt 0 ]; then
+ echo "The $name image size must be power of 2 (up to 2G)." >&2
+ exit 1
+ fi
+ fi
+ echo $size
+}
+
+check_truncation() {
+ image_file=$1
+ output_size=$2
+ if [ "$image_file" = "/dev/zero" ]; then
+ return
+ fi
+ if ! actual_size=$(stat -L -c %s "$image_file" 2>/dev/null); then
+ echo "Missing image '$image_file'." >&2
+ exit 1
+ fi
+ if [ "$actual_size" -gt "$output_size" ]; then
+ echo "Warning: image '$image_file' will be truncated on output."
+ fi
+}
+
+userimg=
+outimg=
+bootimg1=
+bootimg2=/dev/zero
+bootsz=0
+rpmbimg=
+rpmbsz=0
+
+while [ $# -gt 0 ]; do
+ case "$1" in
+ -b)
+ shift
+ [ $# -ge 1 ] || usage 1
+ bootimg1=${1%%:*}
+ bootsz=$(process_size boot "$bootimg1" 128 "$1")
+ shift
+ ;;
+ -B)
+ shift
+ [ $# -ge 1 ] || usage 1
+ bootimg2=$1
+ shift
+ ;;
+ -r)
+ shift
+ [ $# -ge 1 ] || usage 1
+ rpmbimg=${1%%:*}
+ rpmbsz=$(process_size RPMB "$rpmbimg" 128 "$1")
+ shift
+ ;;
+ -h|--help)
+ usage 0
+ ;;
+ *)
+ if [ -z "$userimg" ]; then
+ userimg=${1%%:*}
+ usersz=$(process_size user "$userimg" U "$1")
+ elif [ -z "$outimg" ]; then
+ outimg=$1
+ else
+ usage 1
+ fi
+ shift
+ ;;
+ esac
+done
+
+[ -n "$outimg" ] || usage 1
+
+if [ "$bootsz" -gt $((32640 * 1024)) ]; then
+ echo "Boot image size is larger than 32640K." >&2
+ exit 1
+fi
+if [ "$rpmbsz" -gt $((16384 * 1024)) ]; then
+ echo "RPMB image size is larger than 16384K." >&2
+ exit 1
+fi
+
+echo "Creating eMMC image"
+
+truncate -s 0 "$outimg"
+pos=0
+
+if [ "$bootsz" -gt 0 ]; then
+ echo " Boot partition 1 and 2: $((bootsz / 1024))K each"
+ blocks=$(( bootsz / (128 * 1024) ))
+ check_truncation "$bootimg1" "$bootsz"
+ dd if="$bootimg1" of="$outimg" conv=sparse bs=128K count=$blocks \
+ status=none
+ check_truncation "$bootimg2" "$bootsz"
+ dd if="$bootimg2" of="$outimg" conv=sparse bs=128K count=$blocks \
+ seek=$blocks status=none
+ pos=$((2 * bootsz))
+fi
+
+if [ "$rpmbsz" -gt 0 ]; then
+ echo " RPMB partition: $((rpmbsz / 1024))K"
+ blocks=$(( rpmbsz / (128 * 1024) ))
+ check_truncation "$rpmbimg" "$rpmbsz"
+ dd if="$rpmbimg" of="$outimg" conv=sparse bs=128K count=$blocks \
+ seek=$(( pos / (128 * 1024) )) status=none
+ pos=$((pos + rpmbsz))
+fi
+
+if [ "$usersz" -lt 1024 ]; then
+ echo " User data: $usersz bytes"
+elif [ "$usersz" -lt $((1024 * 1024)) ]; then
+ echo " User data: $(( (usersz + 1023) / 1024 ))K ($usersz)"
+elif [ "$usersz" -lt $((1024 * 1024 * 1024)) ]; then
+ echo " User data: $(( (usersz + 1048575) / 1048576))M ($usersz)"
+else
+ echo " User data: $(( (usersz + 1073741823) / 1073741824))G ($usersz)"
+fi
+check_truncation "$userimg" "$usersz"
+dd if="$userimg" of="$outimg" conv=sparse bs=128K seek=$(( pos / (128 * 1024) )) \
+ count=$(( (usersz + 128 * 1024 - 1) / (128 * 1024) )) status=none
+pos=$((pos + usersz))
+truncate -s $pos "$outimg"
+
+echo ""
+echo "Instantiate by appending to the qemu command line:"
+echo " -drive file=$outimg,if=none,format=raw,id=emmc-img"
+echo " -device emmc,boot-partition-size=$bootsz,rpmb-partition-size=$rpmbsz,drive=emmc-img"
--
2.51.0
From: Jan Kiszka <jan.kiszka@siemens.com>
As an eMMC block device image may consist of more than just the user
data partition, provide a helper script that can compose the image from
boot partitions, an RPMB partition and the user data image. The script
also does the required size validation and/or rounding.
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---
Changes in v6.1:
- address BSD shell portability issue of stat -c
scripts/mkemmc.sh | 219 ++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 219 insertions(+)
create mode 100755 scripts/mkemmc.sh
diff --git a/scripts/mkemmc.sh b/scripts/mkemmc.sh
new file mode 100755
index 0000000000..45dc3f08fa
--- /dev/null
+++ b/scripts/mkemmc.sh
@@ -0,0 +1,219 @@
+#!/bin/sh -e
+# SPDX-License-Identifier: GPL-2.0-only
+#
+# Create eMMC block device image from boot, RPMB and user data images
+#
+# Copyright (c) Siemens, 2025
+#
+# Authors:
+# Jan Kiszka <jan.kiszka@siemens.com>
+#
+# This work is licensed under the terms of the GNU GPL version 2.
+# See the COPYING file in the top-level directory.
+#
+
+usage() {
+ echo "$0 [OPTIONS] USER_IMG[:SIZE] OUTPUT_IMG"
+ echo ""
+ echo "SIZE must be a power of 2 up to 2G and multiples of 512 byte from there on."
+ echo "If no SIZE is specified, the size of USER_ING will be used (rounded up)."
+ echo ""
+ echo "Supported options:"
+ echo " -b BOOT1_IMG[:SIZE] Add boot partitions. SIZE must be multiples of 128K. If"
+ echo " no SIZE is specified, the size of BOOT1_IMG will be"
+ echo " used (rounded up). BOOT1_IMG will be stored in boot"
+ echo " partition 1, and a boot partition 2 of the same size"
+ echo " will be created as empty (all zeros) unless -B is"
+ echo " specified as well."
+ echo " -B BOOT2_IMG Fill boot partition 2 with BOOT2_IMG. Must be combined"
+ echo " with -b which is also defining the partition size."
+ echo " -r RPMB_IMG[:SIZE] Add RPMB partition. SIZE must be multiples of 128K. If"
+ echo " no SIZE is specified, the size of RPMB_IMG will be"
+ echo " used (rounded up)."
+ echo " -h, --help This help"
+ echo ""
+ echo "All SIZE parameters support the units K, M, G. If SIZE is smaller than the"
+ echo "associated image, it will be truncated in the output image."
+ exit "$1"
+}
+
+process_size() {
+ name=$1
+ image_file=$2
+ alignment=$3
+ image_arg=$4
+ if [ "${image_arg#*:}" = "$image_arg" ]; then
+ if ! size=$(wc -c < "$image_file" 2>/dev/null); then
+ echo "Missing $name image '$image_file'." >&2
+ exit 1
+ fi
+ if [ "$alignment" = 128 ]; then
+ size=$(( (size + 128 * 1024 - 1) & ~(128 * 1024 - 1) ))
+ elif [ $size -gt $((2 * 1024 * 1024 * 1024)) ]; then
+ size=$(( (size + 511) & ~511 ))
+ elif [ $(( size & (size - 1) )) -gt 0 ]; then
+ n=0
+ while [ "$size" -gt 0 ]; do
+ size=$((size >> 1))
+ n=$((n + 1))
+ done
+ size=$((1 << n))
+ fi
+ else
+ value="${image_arg#*:}"
+ if [ "${value%K}" != "$value" ]; then
+ size=${value%K}
+ multiplier=1024
+ elif [ "${value%M}" != "$value" ]; then
+ size=${value%M}
+ multiplier=$((1024 * 1024))
+ elif [ "${value%G}" != "$value" ]; then
+ size=${value%G}
+ multiplier=$((1024 * 1024 * 1024))
+ else
+ size=$value
+ multiplier=1
+ fi
+ # check if "$size" is a valid integer by doing a self-comparison
+ if [ "$size" -eq "$size" ] 2>/dev/null; then
+ size=$((size * multiplier))
+ else
+ echo "Invalid value '$value' specified for $image_file image size." >&2
+ exit 1
+ fi
+ if [ "$alignment" = 128 ]; then
+ if [ $(( size & (128 * 1024 - 1) )) -ne 0 ]; then
+ echo "The $name image size must be multiples of 128K." >&2
+ exit 1
+ fi
+ elif [ $size -gt $((2 * 1024 * 1024 * 1024)) ]; then
+ if [ $(( size & 511)) -ne 0 ]; then
+ echo "The $name image size must be multiples of 512 (if >2G)." >&2
+ exit 1
+ fi
+ elif [ $(( size & (size - 1) )) -gt 0 ]; then
+ echo "The $name image size must be power of 2 (up to 2G)." >&2
+ exit 1
+ fi
+ fi
+ echo $size
+}
+
+check_truncation() {
+ image_file=$1
+ output_size=$2
+ if [ "$image_file" = "/dev/zero" ]; then
+ return
+ fi
+ if ! actual_size=$(wc -c < "$image_file" 2>/dev/null); then
+ echo "Missing image '$image_file'." >&2
+ exit 1
+ fi
+ if [ "$actual_size" -gt "$output_size" ]; then
+ echo "Warning: image '$image_file' will be truncated on output."
+ fi
+}
+
+userimg=
+outimg=
+bootimg1=
+bootimg2=/dev/zero
+bootsz=0
+rpmbimg=
+rpmbsz=0
+
+while [ $# -gt 0 ]; do
+ case "$1" in
+ -b)
+ shift
+ [ $# -ge 1 ] || usage 1
+ bootimg1=${1%%:*}
+ bootsz=$(process_size boot "$bootimg1" 128 "$1")
+ shift
+ ;;
+ -B)
+ shift
+ [ $# -ge 1 ] || usage 1
+ bootimg2=$1
+ shift
+ ;;
+ -r)
+ shift
+ [ $# -ge 1 ] || usage 1
+ rpmbimg=${1%%:*}
+ rpmbsz=$(process_size RPMB "$rpmbimg" 128 "$1")
+ shift
+ ;;
+ -h|--help)
+ usage 0
+ ;;
+ *)
+ if [ -z "$userimg" ]; then
+ userimg=${1%%:*}
+ usersz=$(process_size user "$userimg" U "$1")
+ elif [ -z "$outimg" ]; then
+ outimg=$1
+ else
+ usage 1
+ fi
+ shift
+ ;;
+ esac
+done
+
+[ -n "$outimg" ] || usage 1
+
+if [ "$bootsz" -gt $((32640 * 1024)) ]; then
+ echo "Boot image size is larger than 32640K." >&2
+ exit 1
+fi
+if [ "$rpmbsz" -gt $((16384 * 1024)) ]; then
+ echo "RPMB image size is larger than 16384K." >&2
+ exit 1
+fi
+
+echo "Creating eMMC image"
+
+truncate -s 0 "$outimg"
+pos=0
+
+if [ "$bootsz" -gt 0 ]; then
+ echo " Boot partition 1 and 2: $((bootsz / 1024))K each"
+ blocks=$(( bootsz / (128 * 1024) ))
+ check_truncation "$bootimg1" "$bootsz"
+ dd if="$bootimg1" of="$outimg" conv=sparse bs=128K count=$blocks \
+ status=none
+ check_truncation "$bootimg2" "$bootsz"
+ dd if="$bootimg2" of="$outimg" conv=sparse bs=128K count=$blocks \
+ seek=$blocks status=none
+ pos=$((2 * bootsz))
+fi
+
+if [ "$rpmbsz" -gt 0 ]; then
+ echo " RPMB partition: $((rpmbsz / 1024))K"
+ blocks=$(( rpmbsz / (128 * 1024) ))
+ check_truncation "$rpmbimg" "$rpmbsz"
+ dd if="$rpmbimg" of="$outimg" conv=sparse bs=128K count=$blocks \
+ seek=$(( pos / (128 * 1024) )) status=none
+ pos=$((pos + rpmbsz))
+fi
+
+if [ "$usersz" -lt 1024 ]; then
+ echo " User data: $usersz bytes"
+elif [ "$usersz" -lt $((1024 * 1024)) ]; then
+ echo " User data: $(( (usersz + 1023) / 1024 ))K ($usersz)"
+elif [ "$usersz" -lt $((1024 * 1024 * 1024)) ]; then
+ echo " User data: $(( (usersz + 1048575) / 1048576))M ($usersz)"
+else
+ echo " User data: $(( (usersz + 1073741823) / 1073741824))G ($usersz)"
+fi
+check_truncation "$userimg" "$usersz"
+dd if="$userimg" of="$outimg" conv=sparse bs=128K seek=$(( pos / (128 * 1024) )) \
+ count=$(( (usersz + 128 * 1024 - 1) / (128 * 1024) )) status=none
+pos=$((pos + usersz))
+truncate -s $pos "$outimg"
+
+echo ""
+echo "Instantiate by appending to the qemu command line:"
+echo " -drive file=$outimg,if=none,format=raw,id=emmc-img"
+echo " -device emmc,boot-partition-size=$bootsz,rpmb-partition-size=$rpmbsz,drive=emmc-img"
--
2.51.0
On 4/11/25 15:45, Jan Kiszka wrote: > From: Jan Kiszka <jan.kiszka@siemens.com> > > As an eMMC block device image may consist of more than just the user > data partition, provide a helper script that can compose the image from > boot partitions, an RPMB partition and the user data image. The script > also does the required size validation and/or rounding. > > Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com> > --- > > Changes in v6.1: > - address BSD shell portability issue of stat -c > > scripts/mkemmc.sh | 219 ++++++++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 219 insertions(+) > create mode 100755 scripts/mkemmc.sh > > diff --git a/scripts/mkemmc.sh b/scripts/mkemmc.sh > new file mode 100755 > index 0000000000..45dc3f08fa > --- /dev/null > +++ b/scripts/mkemmc.sh > @@ -0,0 +1,219 @@ > +#!/bin/sh -e > +# SPDX-License-Identifier: GPL-2.0-only > +# > +# Create eMMC block device image from boot, RPMB and user data images > +# > +# Copyright (c) Siemens, 2025 > +# > +# Authors: > +# Jan Kiszka <jan.kiszka@siemens.com> > +# > +# This work is licensed under the terms of the GNU GPL version 2. > +# See the COPYING file in the top-level directory. Failing CI with: ERROR: New file 'scripts/mkemmc.sh' must not have license boilerplate header text, only the SPDX-License-Identifier, unless this file was copied from existing code already having such text. Do you mind if I drop these 2 lines?
On 04.11.25 17:55, Philippe Mathieu-Daudé wrote: > On 4/11/25 15:45, Jan Kiszka wrote: >> From: Jan Kiszka <jan.kiszka@siemens.com> >> >> As an eMMC block device image may consist of more than just the user >> data partition, provide a helper script that can compose the image from >> boot partitions, an RPMB partition and the user data image. The script >> also does the required size validation and/or rounding. >> >> Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com> >> --- >> >> Changes in v6.1: >> - address BSD shell portability issue of stat -c >> >> scripts/mkemmc.sh | 219 ++++++++++++++++++++++++++++++++++++++++++++++ >> 1 file changed, 219 insertions(+) >> create mode 100755 scripts/mkemmc.sh >> >> diff --git a/scripts/mkemmc.sh b/scripts/mkemmc.sh >> new file mode 100755 >> index 0000000000..45dc3f08fa >> --- /dev/null >> +++ b/scripts/mkemmc.sh >> @@ -0,0 +1,219 @@ >> +#!/bin/sh -e >> +# SPDX-License-Identifier: GPL-2.0-only >> +# >> +# Create eMMC block device image from boot, RPMB and user data images >> +# >> +# Copyright (c) Siemens, 2025 >> +# >> +# Authors: >> +# Jan Kiszka <jan.kiszka@siemens.com> >> +# >> +# This work is licensed under the terms of the GNU GPL version 2. >> +# See the COPYING file in the top-level directory. > > Failing CI with: > > ERROR: New file 'scripts/mkemmc.sh' must not have license boilerplate > header text, only the SPDX-License-Identifier, unless this file was > copied from existing code already having such text. > > Do you mind if I drop these 2 lines? No problem, drop them - old header template. Jan -- Siemens AG, Foundational Technologies Linux Expert Center
On 4/11/25 15:45, Jan Kiszka wrote: > From: Jan Kiszka <jan.kiszka@siemens.com> > > As an eMMC block device image may consist of more than just the user > data partition, provide a helper script that can compose the image from > boot partitions, an RPMB partition and the user data image. The script > also does the required size validation and/or rounding. > > Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com> > --- > > Changes in v6.1: > - address BSD shell portability issue of stat -c > > scripts/mkemmc.sh | 219 ++++++++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 219 insertions(+) > create mode 100755 scripts/mkemmc.sh > +echo "Creating eMMC image" > + > +truncate -s 0 "$outimg" > +pos=0 > + > +if [ "$bootsz" -gt 0 ]; then > + echo " Boot partition 1 and 2: $((bootsz / 1024))K each" > + blocks=$(( bootsz / (128 * 1024) )) > + check_truncation "$bootimg1" "$bootsz" > + dd if="$bootimg1" of="$outimg" conv=sparse bs=128K count=$blocks \ > + status=none > + check_truncation "$bootimg2" "$bootsz" > + dd if="$bootimg2" of="$outimg" conv=sparse bs=128K count=$blocks \ > + seek=$blocks status=none > + pos=$((2 * bootsz)) > +fi > + > +if [ "$rpmbsz" -gt 0 ]; then > + echo " RPMB partition: $((rpmbsz / 1024))K" > + blocks=$(( rpmbsz / (128 * 1024) )) > + check_truncation "$rpmbimg" "$rpmbsz" > + dd if="$rpmbimg" of="$outimg" conv=sparse bs=128K count=$blocks \ > + seek=$(( pos / (128 * 1024) )) status=none > + pos=$((pos + rpmbsz)) > +fi Still: $ dash scripts/mkemmc.sh -b firmware.img -r /dev/zero:2MB os.img emmc.img Invalid value '2MB' specified for /dev/zero image size. scripts/mkemmc.sh: 170: [: Illegal number: Creating eMMC image Boot partition 1 and 2: 128K each scripts/mkemmc.sh: 192: [: Illegal number: User data: 4 bytes $ bash scripts/mkemmc.sh -b firmware.img -r /dev/zero:2MB os.img emmc.img Invalid value '2MB' specified for /dev/zero image size. scripts/mkemmc.sh: line 170: [: : integer expression expected Creating eMMC image Boot partition 1 and 2: 128K each scripts/mkemmc.sh: line 192: [: : integer expression expected User data: 4 bytes But now the file is generated :) We'll fix on top. Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> Tested-by: Philippe Mathieu-Daudé <philmd@linaro.org> > + > +if [ "$usersz" -lt 1024 ]; then > + echo " User data: $usersz bytes" > +elif [ "$usersz" -lt $((1024 * 1024)) ]; then > + echo " User data: $(( (usersz + 1023) / 1024 ))K ($usersz)" > +elif [ "$usersz" -lt $((1024 * 1024 * 1024)) ]; then > + echo " User data: $(( (usersz + 1048575) / 1048576))M ($usersz)" > +else > + echo " User data: $(( (usersz + 1073741823) / 1073741824))G ($usersz)" > +fi > +check_truncation "$userimg" "$usersz" > +dd if="$userimg" of="$outimg" conv=sparse bs=128K seek=$(( pos / (128 * 1024) )) \ > + count=$(( (usersz + 128 * 1024 - 1) / (128 * 1024) )) status=none > +pos=$((pos + usersz)) > +truncate -s $pos "$outimg" > + > +echo "" > +echo "Instantiate by appending to the qemu command line:" > +echo " -drive file=$outimg,if=none,format=raw,id=emmc-img" > +echo " -device emmc,boot-partition-size=$bootsz,rpmb-partition-size=$rpmbsz,drive=emmc-img"
On 04.11.25 17:27, Philippe Mathieu-Daudé wrote:
> On 4/11/25 15:45, Jan Kiszka wrote:
>> From: Jan Kiszka <jan.kiszka@siemens.com>
>>
>> As an eMMC block device image may consist of more than just the user
>> data partition, provide a helper script that can compose the image from
>> boot partitions, an RPMB partition and the user data image. The script
>> also does the required size validation and/or rounding.
>>
>> Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
>> ---
>>
>> Changes in v6.1:
>> - address BSD shell portability issue of stat -c
>>
>> scripts/mkemmc.sh | 219 ++++++++++++++++++++++++++++++++++++++++++++++
>> 1 file changed, 219 insertions(+)
>> create mode 100755 scripts/mkemmc.sh
>
>
>> +echo "Creating eMMC image"
>> +
>> +truncate -s 0 "$outimg"
>> +pos=0
>> +
>> +if [ "$bootsz" -gt 0 ]; then
>> + echo " Boot partition 1 and 2: $((bootsz / 1024))K each"
>> + blocks=$(( bootsz / (128 * 1024) ))
>> + check_truncation "$bootimg1" "$bootsz"
>> + dd if="$bootimg1" of="$outimg" conv=sparse bs=128K count=$blocks \
>> + status=none
>> + check_truncation "$bootimg2" "$bootsz"
>> + dd if="$bootimg2" of="$outimg" conv=sparse bs=128K count=$blocks \
>> + seek=$blocks status=none
>> + pos=$((2 * bootsz))
>> +fi
>> +
>> +if [ "$rpmbsz" -gt 0 ]; then
>> + echo " RPMB partition: $((rpmbsz / 1024))K"
>> + blocks=$(( rpmbsz / (128 * 1024) ))
>> + check_truncation "$rpmbimg" "$rpmbsz"
>> + dd if="$rpmbimg" of="$outimg" conv=sparse bs=128K count=$blocks \
>> + seek=$(( pos / (128 * 1024) )) status=none
>> + pos=$((pos + rpmbsz))
>> +fi
>
> Still:
>
> $ dash scripts/mkemmc.sh -b firmware.img -r /dev/zero:2MB os.img emmc.img
^^
User error ;-). This must be just "...:2M".
> Invalid value '2MB' specified for /dev/zero image size.
> scripts/mkemmc.sh: 170: [: Illegal number:
> Creating eMMC image
> Boot partition 1 and 2: 128K each
> scripts/mkemmc.sh: 192: [: Illegal number:
> User data: 4 bytes
>
> $ bash scripts/mkemmc.sh -b firmware.img -r /dev/zero:2MB os.img emmc.img
> Invalid value '2MB' specified for /dev/zero image size.
> scripts/mkemmc.sh: line 170: [: : integer expression expected
> Creating eMMC image
> Boot partition 1 and 2: 128K each
> scripts/mkemmc.sh: line 192: [: : integer expression expected
> User data: 4 bytes
>
> But now the file is generated :)
...which is actually a bug as well: We are not terminating the script
inside the process_size function when calling "exit" there. Deviates
from the behavior under Linux. Sigh.
Jan
>
> We'll fix on top.
>
> Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
> Tested-by: Philippe Mathieu-Daudé <philmd@linaro.org>
>
>> +
>> +if [ "$usersz" -lt 1024 ]; then
>> + echo " User data: $usersz bytes"
>> +elif [ "$usersz" -lt $((1024 * 1024)) ]; then
>> + echo " User data: $(( (usersz + 1023) / 1024 ))K
>> ($usersz)"
>> +elif [ "$usersz" -lt $((1024 * 1024 * 1024)) ]; then
>> + echo " User data: $(( (usersz + 1048575) /
>> 1048576))M ($usersz)"
>> +else
>> + echo " User data: $(( (usersz + 1073741823) /
>> 1073741824))G ($usersz)"
>> +fi
>> +check_truncation "$userimg" "$usersz"
>> +dd if="$userimg" of="$outimg" conv=sparse bs=128K seek=$(( pos / (128
>> * 1024) )) \
>> + count=$(( (usersz + 128 * 1024 - 1) / (128 * 1024) )) status=none
>> +pos=$((pos + usersz))
>> +truncate -s $pos "$outimg"
>> +
>> +echo ""
>> +echo "Instantiate by appending to the qemu command line:"
>> +echo " -drive file=$outimg,if=none,format=raw,id=emmc-img"
>> +echo " -device emmc,boot-partition-size=$bootsz,rpmb-partition-
>> size=$rpmbsz,drive=emmc-img"
>
--
Siemens AG, Foundational Technologies
Linux Expert Center
On 4/11/25 18:00, Jan Kiszka wrote: > On 04.11.25 17:27, Philippe Mathieu-Daudé wrote: >> On 4/11/25 15:45, Jan Kiszka wrote: >>> From: Jan Kiszka <jan.kiszka@siemens.com> >>> >>> As an eMMC block device image may consist of more than just the user >>> data partition, provide a helper script that can compose the image from >>> boot partitions, an RPMB partition and the user data image. The script >>> also does the required size validation and/or rounding. >>> >>> Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com> >>> --- >> Still: >> >> $ dash scripts/mkemmc.sh -b firmware.img -r /dev/zero:2MB os.img emmc.img > ^^ > User error ;-). This must be just "...:2M". Per the doc: +.. code-block:: console + + scripts/mkemmc.sh -b firmware.img -r /dev/zero:2MB os.img emmc.img (I'll update it) > >> Invalid value '2MB' specified for /dev/zero image size. >> scripts/mkemmc.sh: 170: [: Illegal number: >> Creating eMMC image >> Boot partition 1 and 2: 128K each >> scripts/mkemmc.sh: 192: [: Illegal number: >> User data: 4 bytes >> >> $ bash scripts/mkemmc.sh -b firmware.img -r /dev/zero:2MB os.img emmc.img >> Invalid value '2MB' specified for /dev/zero image size. >> scripts/mkemmc.sh: line 170: [: : integer expression expected >> Creating eMMC image >> Boot partition 1 and 2: 128K each >> scripts/mkemmc.sh: line 192: [: : integer expression expected >> User data: 4 bytes >> >> But now the file is generated :) > > ...which is actually a bug as well: We are not terminating the script > inside the process_size function when calling "exit" there. Deviates > from the behavior under Linux. Sigh. If you have a diff I can test & squash.
On 04.11.25 18:18, Philippe Mathieu-Daudé wrote: > On 4/11/25 18:00, Jan Kiszka wrote: >> On 04.11.25 17:27, Philippe Mathieu-Daudé wrote: >>> On 4/11/25 15:45, Jan Kiszka wrote: >>>> From: Jan Kiszka <jan.kiszka@siemens.com> >>>> >>>> As an eMMC block device image may consist of more than just the user >>>> data partition, provide a helper script that can compose the image from >>>> boot partitions, an RPMB partition and the user data image. The script >>>> also does the required size validation and/or rounding. >>>> >>>> Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com> >>>> --- > > >>> Still: >>> >>> $ dash scripts/mkemmc.sh -b firmware.img -r /dev/zero:2MB os.img >>> emmc.img >> ^^ >> User error ;-). This must be just "...:2M". > > Per the doc: > > +.. code-block:: console > + > + scripts/mkemmc.sh -b firmware.img -r /dev/zero:2MB os.img emmc.img > > (I'll update it) > Ouch, indeed. >> >>> Invalid value '2MB' specified for /dev/zero image size. >>> scripts/mkemmc.sh: 170: [: Illegal number: >>> Creating eMMC image >>> Boot partition 1 and 2: 128K each >>> scripts/mkemmc.sh: 192: [: Illegal number: >>> User data: 4 bytes >>> >>> $ bash scripts/mkemmc.sh -b firmware.img -r /dev/zero:2MB os.img >>> emmc.img >>> Invalid value '2MB' specified for /dev/zero image size. >>> scripts/mkemmc.sh: line 170: [: : integer expression expected >>> Creating eMMC image >>> Boot partition 1 and 2: 128K each >>> scripts/mkemmc.sh: line 192: [: : integer expression expected >>> User data: 4 bytes >>> >>> But now the file is generated :) >> >> ...which is actually a bug as well: We are not terminating the script >> inside the process_size function when calling "exit" there. Deviates >> from the behavior under Linux. Sigh. > If you have a diff I can test & squash. Someone rather needs to debug. A first remote experiment couldn't explain why we are not terminating. If you could run with -x, that trace may be a first hint. Jan -- Siemens AG, Foundational Technologies Linux Expert Center
© 2016 - 2025 Red Hat, Inc.