Initial commit: boot, wifi and ssh work

Signed-off-by: Maurizio Porrato <maurizio.porrato@gmail.com>
This commit is contained in:
Maurizio Porrato 2024-06-23 18:03:33 +01:00
commit 3216669497
No known key found for this signature in database
41 changed files with 585 additions and 0 deletions

6
.gitignore vendored Normal file
View File

@ -0,0 +1,6 @@
*.img
!config/
config/*
!config/etc/
config/etc/*
!config/etc/motd

72
Makefile Normal file
View File

@ -0,0 +1,72 @@
.PHONY: sdcard images clean
A=./artifacts
R=./resources
S=./scripts
#############################################################################
# Tunable parameters are in this section
ALPINE_VERSION?=latest
FACTORY_IMAGE?=factory.img
SD_SIZE?=250M
RESOURCES_SIZE?=8M
ROOTFS_SIZE?=100M
#############################################################################
SPL=$(A)/spl.img
UBOOT=$(A)/u-boot.img
ENV=$(A)/env.img
RESOURCES=$(A)/boot-resources.img
BOOT=$(A)/boot.img
BOOTCFG=$(A)/bootimg.cfg
KERNEL=$(A)/zImage
INITRD=$(A)/initramfs
FIRMWARE_TAR=$(A)/firmware.tar
MODULES_TAR=$(A)/modules.tar
ROOTFS_TAR=$(A)/rootfs.tar
ROOTFS=$(A)/rootfs.img
IMAGES=$(SPL) $(UBOOT) $(ENV) $(RESOURCES) $(BOOT) $(ROOTFS)
SD=$(A)/alpine-h700.img
sdcard: $(SD)
images: $(IMAGES)
$(SD): $(IMAGES)
$(RM) $@
truncate -s $(SD_SIZE) $@
$(S)/mkpart.sh $@ $^
$(SPL) $(UBOOT): $(FACTORY_IMAGE)
$(S)/extract-blobs.py $^ -o $(A)
$(ENV): env.txt
$(S)/mkenv.py $^ $@
$(BOOT): $(BOOTCFG) $(KERNEL) $(INITRD)
abootimg --create $@ -f $(BOOTCFG) -k $(KERNEL) -r $(INITRD)
$(KERNEL) $(BOOTCFG): $(FACTORY_IMAGE)
$(S)/extract-kernel.sh $^ $(A)
$(INITRD):
$(S)/mkinitrd.sh $(ALPINE_VERSION)
$(RESOURCES): $(shell find $(R) -type f -print0 | xargs -0)
$(RM) $@
truncate -s $(RESOURCES_SIZE) $@
$(S)/mkfsimage.sh $@ 0 vfat resources $(R)
$(ROOTFS_TAR):
$(S)/build-rootfs.sh $(ALPINE_VERSION) $(A)
$(FIRMWARE_TAR) $(MODULES_TAR): $(FACTORY_IMAGE)
$(S)/extract-modules.sh $< $(A)
$(ROOTFS): $(ROOTFS_TAR) $(FIRMWARE_TAR) $(MODULES_TAR)
$(RM) $@
truncate -s $(ROOTFS_SIZE) $@
$(S)/mkfsimage.sh $@ 0 ext4 rootfs $(ROOTFS_TAR) $(FIRMWARE_TAR):/lib/firmware/ $(MODULES_TAR):/lib/modules/ config
clean:
$(RM) $(A)/*

89
README.md Normal file
View File

@ -0,0 +1,89 @@
# Alpine Linux for the Allwinner H700 SoC
This repository contains a collection of scripts to create a custom Alpine
Linux based SD card image bootable on Allwinner H700 based devices.
In the standard configuration, a very basic system is installed, providing
a login prompt on `/dev/ttyS0`, automatic connection to a WiFi netowk on boot
and an SSH daemon running.
The scripts have been tested on a Fedora Linux 40 system and the generated
image has been tested on an Anbernic RG35XX Plus portable console.
## Requirements
The scripts require the following software:
- `make` (specifically, GNU Make) to orchestrate the build and track dependencies
- `python3` to run some of the provided scripts; only modules from the standard
library are used
- `sgdisk` to manipulate GPT partition tables
- `guestfish` to manipulate filesystem images without root privileges
- `podman` to provide an Alpine Linux environment
- `qemu-user-static-aarch64` to enable `podman` to run aarch64 container
images on a different architecture like x86_64
An image of a stock SD card is required in order to extract components that are
specific to the H700 SoC that do not have open source alternatives yet; those
components are:
- the SPL
- the U-Boot bootloader
- the kernel
- the kernel's modules
- various firmware blobs
## Preparation
### Configuration
Some extra configuration must be provided to connect to a WiFi network and
allow SSH connections.
Anything under the `config` directory will be injected in the rootfs image.
A good staring point would be something like this (replace `$ssid` and
`$password` with the correct network name and password for your WiFi network):
```shell
mkdir -p config/etc/wpa_supplicant
wpa_passphrase '$ssid' '$password' >config/etc/wpa_supplicant/wpa_supplicant.conf
mkdir -p config/root/.ssh
cat ~/.ssh/id_*.pub >config/root/.ssh/authorized_keys
```
### Stock SD card image
The scripts expect to find an image of the stock SD card in a file called
`factory.img` in the root of the repository. It can be either an image file or
a link to the actual image file or device, as long as the user running the
scripts has permission to read it. The name of the image can be overridden by
specifying a different path in the `FACTORY_IMAGE` variable when calling the
makefile.
## Usage
To build an image, just run:
```shell
make
```
Or, to use a path to the stock image other than the default:
```shell
make FACTORY_IMAGE=/tmp/RG35XX+-P-V1.1.3-EN16GB-240614.IMG
```
The resulting image will be saved to `./artifacts/alpine-h700.img` and can be
flashed to an SD card, for example, if the card is presented to the system as
`/dev/sde`:
```shell
dd if=artifacts/alpine-h700.img of=/dev/sde bs=1M oflag=dsync status=progress
```
There are other tunable settings: for an exaustive list, see the top of
`Makefile`. Keep in mind that tweaking those values between builds may require
forcing a clean build by issuing a `make clean`.

24
UNLICENSE Normal file
View File

@ -0,0 +1,24 @@
This is free and unencumbered software released into the public domain.
Anyone is free to copy, modify, publish, use, compile, sell, or
distribute this software, either in source code form or as a compiled
binary, for any purpose, commercial or non-commercial, and by any
means.
In jurisdictions that recognize copyright laws, the author or authors
of this software dedicate any and all copyright interest in the
software to the public domain. We make this dedication for the benefit
of the public at large and to the detriment of our heirs and
successors. We intend this dedication to be an overt act of
relinquishment in perpetuity of all present and future rights to this
software under copyright law.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
For more information, please refer to <https://unlicense.org/>

2
artifacts/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
*
!.gitignore

11
config/etc/motd Normal file
View File

@ -0,0 +1,11 @@
Welcome to Alpine!
This is an unofficial port to the Allwinner H700 SoC: please report
issues to https://github.com/mporrato/alpine-h700 .
The Alpine Wiki contains a large amount of how-to guides and general
information about administrating Alpine systems.
See <https://wiki.alpinelinux.org/>.
You may change this message by editing /etc/motd.

26
env.txt Normal file
View File

@ -0,0 +1,26 @@
earlyprintk=sunxi-uart,0x05000000
initcall_debug=0
console=ttyS0,115200
rootfstype=ext4
nand_root=/dev/nand0p4
mmc_root=/dev/mmcblk0p4
init=/sbin/init
loglevel=4
selinux=0
cma=64M
mac=
wifi_mac=
bt_mac=
specialstr=
keybox_list=hdcpkey,widevine
setargs_nand=setenv bootargs earlyprintk=${earlyprintk} initcall_debug=${initcall_debug} console=${console} loglevel=${loglevel} rootfstype=${rootfstype} root=${nand_root} init=${init} partitions=${partitions} cma=${cma} snum=${snum} mac_addr=${mac} wifi_mac=${wifi_mac} bt_mac=${bt_mac} selinux=${selinux} specialstr=${specialstr} gpt=1
setargs_mmc=setenv bootargs earlyprintk=${earlyprintk} initcall_debug=${initcall_debug} console=${console} loglevel=${loglevel} rootfstype=${rootfstype} root=${mmc_root} init=${init} partitions=${partitions} cma=${cma} snum=${snum} mac_addr=${mac} wifi_mac=${wifi_mac} bt_mac=${bt_mac} selinux=${selinux} specialstr=${specialstr} gpt=1
boot_normal=sunxi_flash read 45000000 boot;bootm 45000000
boot_recovery=sunxi_flash read 45000000 recovery;bootm 45000000
boot_fastboot=fastboot
recovery_key_value_max=0x13
recovery_key_value_min=0x10
fastboot_key_value_max=0x8
fastboot_key_value_min=0x2
bootdelay=0
bootcmd=run setargs_nand boot_normal

1
mkinitfs.conf Normal file
View File

@ -0,0 +1 @@
features="base"

BIN
resources/bat/bat0.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 88 KiB

BIN
resources/bat/bat1.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 117 KiB

BIN
resources/bat/bat10.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 117 KiB

BIN
resources/bat/bat2.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 117 KiB

BIN
resources/bat/bat3.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 117 KiB

BIN
resources/bat/bat4.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 117 KiB

BIN
resources/bat/bat5.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 117 KiB

BIN
resources/bat/bat6.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 117 KiB

BIN
resources/bat/bat7.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 117 KiB

BIN
resources/bat/bat8.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 117 KiB

BIN
resources/bat/bat9.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 117 KiB

BIN
resources/bat/bat_blank.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 B

BIN
resources/bat/bat_htmp.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 234 KiB

BIN
resources/bat/bat_ltmp.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 234 KiB

BIN
resources/bat/battery.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 117 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 87 KiB

BIN
resources/bat/bempty.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 117 KiB

BIN
resources/bat/bootlogo.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 337 KiB

BIN
resources/bat/low_pwr.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 192 KiB

BIN
resources/bootlogo.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 900 KiB

BIN
resources/fastbootlogo.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 186 KiB

BIN
resources/font24.sft Normal file

Binary file not shown.

BIN
resources/font32.sft Normal file

Binary file not shown.

1
resources/magic.bin Normal file
View File

@ -0,0 +1 @@
a1sp9maKde37ee6c-6dc4-4d74-86f0-db32116efb53e0e40ccf-7a66-406b-88c3-415b4a62a8f7777622ab-6bd0-464f-9da5-4cc203e855ea8ce5671f-e8b5-442e-9300-2ee6836c538aabf5f481-c961-4895-8245-631f74851d0c2bbb4229-55a8-4929-a165-3f406f0ee441ab5d09a9-c4dc-44bb-a175-cfb7c978a062329ea51e-1ddc-44ff-ac09-9ef7b64e0c52a712e47d-13f7-4490-9fea-bdcd587b8a4a5ed4d4e6-0ba3-45c5-a778-3232a42d4d960a9b7466-d7b3-4087-b8ff-c51763b852a50cd78bb6-a6d5-43a8-8661-fb91abd346433e8a86ee-711e-49c1-ad54-b59dd01fe513e22b0d8b-647f-4417-a115-9806c5d64eec

36
scripts/_build.sh Executable file
View File

@ -0,0 +1,36 @@
#!/bin/sh
# This script runs inside an aarch64 alpine linux container and creates a
# base rootfs tarball with wifi support and an ssh daemon active at boot.
set -e
target="$(mktemp -d)"
trap 'rm -rf "$target"' 0
apk update
apk -X "$(awk '/\/alpine\/[^\/]+\/main$/{print;exit}' /etc/apk/repositories)" \
--keys-dir /etc/apk/keys -U -p "$target/" --initdb \
add alpine-base alpine-release ca-certificates wpa_supplicant dropbear
cp /etc/apk/repositories "$target/etc/apk/"
echo "nameserver 8.8.8.8" >"$target/etc/resolv.conf"
sed -Ei 's/^(tty[0-9]+:)/#\1/;s/^#ttyS0:/ttyS0:/' "$target/etc/inittab"
echo h700 >"$target/etc/hostname"
echo 8821cs >"$target/etc/modules"
cat >"$target/etc/network/interfaces" <<__EOF__
auto lo
iface lo inet loopback
auto wlan0
iface wlan0 inet dhcp
__EOF__
for svc in devfs dmesg mdev ; do
chroot "$target" rc-update add "$svc" sysinit
done
for svc in hwclock modules sysctl hostname bootmisc syslog wpa_supplicant networking ; do
chroot "$target" rc-update add "$svc" boot
done
for svc in mount-ro killprocs savecache ; do
chroot "$target" rc-update add "$svc" shutdown
done
chroot "$target" rc-update add dropbear default
tar cf "${1:-/tmp/rootfs.tar}" -C "$target" .

7
scripts/build-rootfs.sh Executable file
View File

@ -0,0 +1,7 @@
#!/bin/bash
podman run --arch=aarch64 --security-opt=label=disable \
-v "${2:-./artifacts}:/artifacts" \
-v ./scripts/_build.sh:/usr/local/bin/_build.sh \
--rm "docker.io/library/alpine:${1:-latest}" \
sh /usr/local/bin/_build.sh /artifacts/rootfs.tar

82
scripts/extract-blobs.py Executable file
View File

@ -0,0 +1,82 @@
#!/usr/bin/env python3
"""
Extract SPL and U-Boot images from an Allwinner boot image
"""
import argparse
import mmap
from pathlib import Path
import struct
import sys
SPL_SIGNATURE = b"eGON.BT0"
# The SPL can be located at different locations depending on the SoC type
SPL_OFFSETS = [8 * 1024, 128 * 1024, 256 * 1024]
SPL_FILENAME = "spl.img"
UBOOT_SIGNATURE = b"sunxi-package"
UBOOT_OFFSET = 16400 * 1024
UBOOT_FILENAME = "u-boot.img"
class InvalidImageError(Exception):
pass
def extract_blobs(image: Path, output_dir: Path = Path(), verbose: bool = True):
with image.open("rb") as f:
# The first partition starts at 36MB: map all space before that into memory
mm = mmap.mmap(f.fileno(), 36 * 1024**2, prot=mmap.PROT_READ)
spl_offset = spl_size = None
for offset in SPL_OFFSETS:
sig_offset = offset + 4
if mm[sig_offset : sig_offset + len(SPL_SIGNATURE)] == SPL_SIGNATURE:
spl_offset = offset
(spl_size,) = struct.unpack("<I", mm[offset + 16 : offset + 16 + 4])
break
if spl_offset is None:
raise InvalidImageError("Can't find SPL")
if verbose:
print(
f"Found SPL at offset {spl_offset / 1024}KiB, size {spl_size / 1024}KiB"
)
if mm[UBOOT_OFFSET : UBOOT_OFFSET + len(UBOOT_SIGNATURE)] != UBOOT_SIGNATURE:
raise InvalidImageError("Can't find U-Boot")
(uboot_size,) = struct.unpack(
"<I", mm[UBOOT_OFFSET + 36 : UBOOT_OFFSET + 36 + 4]
)
if verbose:
print(
f"Found U-Boot at offset {UBOOT_OFFSET / 1024}KiB, size {uboot_size / 1024}KiB"
)
if not output_dir.exists():
output_dir.mkdir(mode=0o755, parents=True)
spl_image = output_dir / SPL_FILENAME
if verbose:
print(f"Writing SPL image to {spl_image}")
spl_image.write_bytes(mm[spl_offset : spl_offset + spl_size])
uboot_image = output_dir / UBOOT_FILENAME
if verbose:
print(f"Writing U-Boot image to {uboot_image}")
uboot_image.write_bytes(mm[UBOOT_OFFSET : UBOOT_OFFSET + uboot_size])
if __name__ == "__main__":
parser = argparse.ArgumentParser(
description="Extract Allwinner H700 binary blobs from SD card images"
)
parser.add_argument("image", type=Path, help="source image or device")
parser.add_argument(
"--output", "-o", type=Path, default=Path(), help="output directory"
)
parser.add_argument(
"--verbose", "-v", action="store_true", help="show what's being done"
)
args = parser.parse_args()
try:
extract_blobs(args.image, args.output, args.verbose)
sys.exit(0)
except Exception as e:
sys.stderr.write(f"{e}\n")
sys.exit(1)

21
scripts/extract-kernel.sh Executable file
View File

@ -0,0 +1,21 @@
#!/bin/bash
# Extract the kernel and boot image configuration from the given
# android boot image.
set -e
image="$1"
outdir="${2:-./artifacts}"
boot_part="$(sgdisk -p "$image" | awk '$7=="boot"{print $2 " " $3-$2+1;exit}')"
read -r -a boot <<<"$boot_part"
block_shift="$(factor -h "${boot[@]}" | grep -Eo "2\^[0-9]+" | sed 's/^2\^//' | sort -n | head -n1)"
block_size="$((2 ** block_shift))"
start_blocks="$((boot[0] / block_size))"
size_blocks="$((boot[1] / block_size))"
tmp="$(mktemp -d)"
trap 'rm -rf "$tmp"' 0
dd if="$image" of="$tmp/boot.img" bs="$((512 * block_size))" skip="$start_blocks" count="$size_blocks" conv=sparse status=none
abootimg -x "$tmp/boot.img" "$outdir/bootimg.cfg" "$outdir/zImage" /dev/null /dev/null

22
scripts/extract-modules.sh Executable file
View File

@ -0,0 +1,22 @@
#!/bin/bash
# Extracts kernel modules and firmware blobs from the given
# rootfs image.
set -e
if [[ $# -lt 2 ]] ; then
echo "Syntax: $0 IMAGE OUTDIR [PARTNO]"
exit 0
fi
image="$1"
outdir="$2"
partno="${3:-5}"
device="/dev/sda$partno"
guestfish --ro --format=raw -a "$image" <<__EOF__
run
mount "$device" /
tar-out /lib/modules "$outdir/modules.tar"
tar-out /lib/firmware "$outdir/firmware.tar"
__EOF__

87
scripts/mkenv.py Executable file
View File

@ -0,0 +1,87 @@
#!/usr/bin/env python3
"""
Create a U-Boot environment image from a text environment file
This is required because the Anbernic environment format is not compatible
with the binary format produced by the mkenvimage tool from the uboot-tools
package
"""
import argparse
import struct
import sys
import zlib
ENCODING = "utf-8"
DEFAULT_IMG_SIZE = 128 * 1024
DEFAULT_IMG_FLAGS = 0
class EnvError(Exception):
pass
def makebinenv(infile, outfile, size, flags):
"""
Create a U-Boot environment image from a text environment file
"""
buf = b""
for line in infile:
clean_line = line.strip()
if clean_line and not clean_line.startswith("#"):
buf += bytes(clean_line, ENCODING) + b"\0"
infile.close()
buf += b"\0"
if flags is not None:
buf = bytes([flags]) + buf
envsize = 4 + len(buf)
if envsize > size:
raise EnvError(f"Insufficient environment space: need at least {envsize} bytes")
buf += bytes(size - envsize)
crc = zlib.crc32(buf, 0)
buf = struct.pack("<I", crc) + buf
outfile.write(buf)
outfile.close()
if __name__ == "__main__":
parser = argparse.ArgumentParser(
prog="mkenv.py",
description=(
"Create an Anbernic U-Boot environment image from a text environment file"
),
)
parser.add_argument(
"textfile",
type=argparse.FileType("r", encoding=ENCODING),
help="input text environment file",
)
parser.add_argument(
"binfile",
type=argparse.FileType("wb"),
help="output binary environment image file",
)
parser.add_argument(
"-s",
"--size",
type=int,
default=DEFAULT_IMG_SIZE,
help=(f"size of the output binary image in bytes (default={DEFAULT_IMG_SIZE})"),
)
parser.add_argument(
"-f",
"--flags",
type=int,
default=0,
help=f"binary image flags (default={DEFAULT_IMG_FLAGS})",
)
args = parser.parse_args()
try:
makebinenv(args.textfile, args.binfile, args.size, args.flags)
sys.exit(0)
except Exception as e:
sys.stderr.write(f"{e}\n")
sys.exit(1)

54
scripts/mkfsimage.sh Executable file
View File

@ -0,0 +1,54 @@
#!/bin/bash
# Create a new filesystem and populate it with the specified files.
# Automatically extracts tarballs.
set -e
if [[ $# -lt 5 ]] ; then
echo "Syntax: $0 IMAGE PART# FSTYPE LABEL SOURCE [...]"
exit 0
fi
image="$1" ; shift
partition="$1" ; shift
fstype="$1" ; shift
label="$1" ; shift
device="/dev/sda"
[[ $partition -ne 0 ]] && device="$device$partition"
script=(
"run"
"mkfs $fstype $device label:$label"
"mount $device /"
)
while [ $# -gt 0 ] ; do
src="$1"
if [[ "$src" =~ .+:.+ ]] ; then
dest="${src##*:}"
src="${src%%:*}"
script+=("mkdir-p \"$dest\"")
else
dest="/"
fi
if [ -d "$src" ] ; then
for item in "$src"/* ; do
cmd="copy-in \"$item\" \"$dest\""
script+=("$cmd")
done
else
case "$src" in
*.tar) cmd="tar-in \"$src\" \"$dest\"" ;;
*.tar.gz) cmd="tar-in \"$src\" \"$dest\" compress:gzip" ;;
*) cmd="copy-in \"$src\" \"$dest\"" ;;
esac
script+=("$cmd")
fi
shift
done
script+=("fstrim /")
for cmd in "${script[@]}"; do
echo "$cmd"
done | guestfish --format=raw -a "$image"

7
scripts/mkinitrd.sh Executable file
View File

@ -0,0 +1,7 @@
#!/bin/bash
podman run --arch=arm64 --security-opt=label=disable \
-v "${2:-./artifacts}:/artifacts" \
-v ./mkinitfs.conf:/tmp/mkinitfs.conf:ro \
--rm "docker.io/library/alpine:${1:-latest}" \
sh -c "apk update && apk add mkinitfs apk-tools && mkinitfs -c /tmp/mkinitfs.conf -n -o /artifacts/initramfs"

37
scripts/mkpart.sh Executable file
View File

@ -0,0 +1,37 @@
#!/bin/bash
# Assemble SPL, U-Boot, U-Boot environment, boot-resources, boot and rootfs
# images into a final H700 bootable sdcard image.
set -e
if [[ $# -lt 7 ]] ; then
echo "Usage: $0 SDCARD SPL UBOOT ENV BOOT-RESOURCE BOOT ROOTFS"
exit 0
fi
mb() {
# Return the file size in MiB (rounded up)
local file_size
file_size="$(stat -c "%s" "$1")"
echo "$(( (file_size + 1024 ** 2 - 1) / 1024 ** 2 ))M"
}
sgdisk --move-main-table=73696 -I \
--new="0:0:+$(mb "$4")" --change-name=0:env --attributes=0:=:c000000000000001 --typecode=0:b000 \
--new="0:0:+$(mb "$5")" --change-name=0:boot-resource --attributes=0:=:c000000000000001 --typecode=0:0700 \
--new="0:0:+$(mb "$6")" --change-name=0:boot --attributes=0:=:c000000000000001 --typecode=0:a002 \
--new="0:0:+$(mb "$7")" --change-name=0:rootfs --attributes=0:=:c000000000000001 --typecode=0:8305 \
"$1"
part_table="$(sgdisk -p artifacts/alpine-h700.img | awk '/^ +[0-9]+ +[0-9]+ +[0-9]+/{print $2 / 2}' | xargs)"
read -r -a offsets <<<"$part_table"
images=("$2" "$3" "$4" "$5" "$6" "$7")
offsets=(8 16400 "${offsets[@]}")
for i in "${!images[@]}"; do
img="${images[$i]}"
off="${offsets[$i]}"
echo "Writing $img at offset ${off}KiB"
dd if="$img" of="$1" bs=1K seek="${off}" conv=sparse,notrunc status=none
done
echo "Your bootable SD image is $1"