[PATCH v6 5/6] scripts: Add helper script to generate eMMC block device images

Jan Kiszka posted 6 patches 1 week, 3 days ago
Maintainers: "Philippe Mathieu-Daudé" <philmd@linaro.org>, Bin Meng <bmeng.cn@gmail.com>
[PATCH v6 5/6] scripts: Add helper script to generate eMMC block device images
Posted by Jan Kiszka 1 week, 3 days ago
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
[PATCH v6.1 5/6] scripts: Add helper script to generate eMMC block device images
Posted by Jan Kiszka 1 week, 3 days ago
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
Re: [PATCH v6.1 5/6] scripts: Add helper script to generate eMMC block device images
Posted by Philippe Mathieu-Daudé 1 week, 2 days ago
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?
Re: [PATCH v6.1 5/6] scripts: Add helper script to generate eMMC block device images
Posted by Jan Kiszka 1 week, 2 days ago
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

Re: [PATCH v6.1 5/6] scripts: Add helper script to generate eMMC block device images
Posted by Philippe Mathieu-Daudé 1 week, 3 days ago
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"


Re: [PATCH v6.1 5/6] scripts: Add helper script to generate eMMC block device images
Posted by Jan Kiszka 1 week, 2 days ago
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

Re: [PATCH v6.1 5/6] scripts: Add helper script to generate eMMC block device images
Posted by Philippe Mathieu-Daudé 1 week, 2 days ago
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.

Re: [PATCH v6.1 5/6] scripts: Add helper script to generate eMMC block device images
Posted by Jan Kiszka 1 week, 2 days ago
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