Created
January 26, 2023 23:04
-
-
Save Kreyren/d83d127d7de1f7a2b5916f4ea9f9a28e to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/sh | |
# shellcheck shell=sh # Written to comply with IEEE Std 1003.1-2017 | |
#@ Inspired by Milan P. Stanič from https://arvanta.net/alpine/alpine-on-olimex/ | |
#@ Inspired by Milan P. Stanič's script for OlinuXino-A64 boards to do non-UEFI setup -- https://tpaste.us/wxZK | |
#@ Refactored and rewritten by Jacob Hrbek under Expat License | |
###! Script to generate a stable alpine image for OLIMEX Teres-1 | |
###! | |
###! To achieve this we are creating an .img file intended to be flashed on the desired storage device through e.g. `# dd if=./output.img of=/dev/sdX conv=sync status=progress` with the following partitions: | |
###! | |
###! ## With UEFI | |
###! (Allegedly) generally recommended for ARM64 boards, but the exact reasoning is not known, unification?[mps] | |
###! | |
###! In this step we are making the following partitionining: | |
###! Table: msdos | |
###! Sector 0 to 8191 (16 MB) -- Unformatted used for the bootloader(?) | |
###! Sector 8192 to 1056767 (2048 MB) -- EXT4 partition used for the u-boot bootloader, needs to be flagged as 'esp' (EFI System Partition) for the grub to install bootaa64.efi on it | |
###! Sector 1056768 to 17833983 -- EXT4 partition for rootfs of alpine linux | |
###! | |
###! Configuration by mps | |
###! | |
###! ## Without UEFI (recommended) | |
###! For those who doesn't like UEFI on their system | |
###! | |
###! In this step we are making the following partitioning: | |
###! Disklabel type: dos | |
###! Units: sectors of 1 * 512 = 512 bytes | |
###! Sector 0 to 40959 (20MiB) -- Unformatted used for the bootloader(?) | |
###! Sector 40960 to 327679 (286720 sectors - 140 MiB) -- fat16 partition used for the u-boot bootloader | |
###! Sector 327680 to 17104859 (16777216 sectors - 8 GiB) -- EXT4 partition for rootfs of alpine linux | |
###! | |
###! Configuration taken from an official olimex image | |
###! | |
###! # Creating the .img file with MBR records | |
###! This can be done through: | |
###! $ dd if=/dev/zero of=file.img seek=$((512 * 1000)) bs=512 count=1 conv=sync status=progress # Make an img file with the size of 1000 MB with 512 sectors | |
###! And then formated using e.g. fdisk to be treated as block device | |
###! | |
###! 1 GB = 2097152 sectors at block size 512 | |
###! | |
###! # Additional informations | |
###! The boot partition should have at least 300 MB to avoid issues with upgrading[https://github.com/OLIMEX/DIY-LAPTOP/issues/52] | |
###! The Boot partition should be FAT32, because FAT16 has issues[mps] | |
###! | |
###! # Experiments on docker | |
###! alpine:3.17.1 | |
###! | |
###! Run docker `docker run -v "$PWD/tmpdir":/tmpdir --device=/dev/sdc:/dev/sdc:rwm -it alpine:3.17.1` | |
###! | |
###! ```shell | |
###! # Make directories | |
###! mkdir -p "/tmpdir/etc/apk/keys" /boot/efi | |
###! ``` | |
###! | |
###! ``shell | |
###! # Get alpine keys | |
###! wget -qP "/tmpdir/etc/apk/keys" "https://alpinelinux.org/keys/alpine-devel@lists.alpinelinux.org-60ac2099.rsa.pub" | |
###! ``` | |
###! | |
###! ```shell | |
###! # Set up repositories | |
###! printf "http://dl-cdn.alpinelinux.org/alpine/edge/%s\n" main community testing > "/tmpdir/etc/apk/repositories" | |
###! ``` | |
###! | |
###! ```shell | |
###! # Install required packages | |
###! apk --allow-untrusted --root /tmpdir --arch aarch64 --initdb add alpine-base alpine-baselayout alpine-conf kmod openrc dbus util-linux blkid chrony u-boot-sunxi sysfsutils ssl_client ca-certificates-bundle alpine-keys ethtool e2fsprogs libudev-zero libudev-zero-helper iwd linux-firmware-none efibootmgr ttf-dejavu agetty terminus-font openresolv tar wget | |
###! ``` | |
###! | |
###! ```shell | |
###! # Download kernel and install it | |
###! wget https://dev.alpinelinux.org/~mps/sunxi/linux-sunxi-5.17.4-r0.apk | |
###! apk --allow-untrusted --root "/tmpdir" --arch aarch64 --no-script add ./linux-sunxi-5.17.4-r0.apk | |
###! ``` | |
###! | |
###! ```shell | |
###! # Install bootloader? | |
###! apk --allow-untrusted --root /tmpdir --arch aarch64 --no-script add grub-efi grub-mkfont | |
###! ``` | |
###! | |
###! ```shell | |
###! # Get the u-boot things on the thing? | |
###! dd if=/tmpdir/usr/share/u-boot/teres_i/u-boot-sunxi-with-spl.bin of=/dev/sdc bs=8k seek=1 | |
###! ``` | |
###! | |
###! ```shell | |
###! No fucking idea what this does | |
###! for rc in boot/bootmisc boot/hostname boot/modules boot/sysctl boot/urandom boot/networking sysinit/devfs sysinit/hwdrivers sysinit/mdev sysinit/modules shutdown/mount-ro shutdown/killprocs default/dbus default/chronyd default/iwd; do | |
###! ln -s /etc/init.d/"${rc##*/}" /tmpdir/etc/runlevels/"$rc" | |
###! done | |
###! ``` | |
###! | |
###! Stuck at last step from https://arvanta.net/alpine/alpine-on-olimex/ doing the grub installation: | |
###! | |
###! # chroot $TMPDIR grub-install --target=arm64-efi --efi-directory=/boot/efi␏ | |
###! Installing for arm64-efi platform. | |
###! grub-install: error: disk `hostdisk//dev/dm-0' not found | |
# Alternavive declaration | |
# NOTE(Krey): Abstracting for a new version | |
# make a blank .img file | |
## dd if=/dev/zero of=./alpine-teres-i.img bs=512 count=$((4 * 2097152)) status=progress | |
# format partitions on it | |
## sudo losetup /dev/loop0 ./alpine-teres-i.img | |
## sudo mkfs.vfat -F 32 -n BOOT /dev/loop0p1 | |
## sudo mkfs.ext4 -L rootfs /dev/loop0p2 | |
# Get the keys and repos | |
## wget -qP "$TMPDIR/etc/apk/keys" "https://alpinelinux.org/keys/alpine-devel@lists.alpinelinux.org-60ac2099.rsa.pub" | |
## wget -qP "$TMPDIR/etc/apk/keys" "https://arvanta.net/mps/aports-local/mps@arvanta.net-5a88c744.rsa.pub" | |
## printf "http://dl-cdn.alpinelinux.org/alpine/latest-stable/%s\n" main community > "$TMPDIR"/etc/apk/repositories | |
## printf "%s\n" "https://www.arvanta.net/mps/aports-local" >> "$TMPDIR"/etc/apk/repositories | |
# Install packages | |
## NOTE(Krey): This is supposed to be using a static apk | |
## apkVersion="2.12.11-r0" | |
## wget -qP "$cacheDir/$scriptName/" "https://dl-cdn.alpinelinux.org/alpine/edge/main/x86_64/apk-tools-static-2.12.11-r0.apk" | |
## According to https://linux-sunxi.org/Linux_mainlining_effort#Merged_into_5.14the linux-lts should work (MBUS supported since 5.17) | |
## apk --allow-untrusted --root "$TMPDIR" --arch aarch64 --initdb add alpine-base alpine-baselayout alpine-conf kmod openrc dbus util-linux blkid chrony u-boot-sunxi sysfsutils ssl_client ca-certificates-bundle alpine-keys ethtool e2fsprogs libudev-zero libudev-zero-helper iwd agetty openresolv tar wget linux-sunxi linux-firmware-rtlwifi iw wpa_supplicant | |
# Install the u-boot thing? | |
## dd if="$TMPDIR"/usr/share/u-boot/teres-i/u-boot-sunxi-with-spl.bin of=$DISK bs=8k seek=1 | |
# Setup services | |
## for rc in boot/bootmisc boot/hostname boot/modules boot/sysctl boot/urandom boot/networking boot/syslog boot/klogd sysinit/devfs sysinit/hwdrivers sysinit/mdev sysinit/modules shutdown/mount-ro shutdown/killprocs default/dbus default/chronyd default/iwd; do ln -s /etc/init.d/"${rc##*/}" "$TMPDIR"/etc/runlevels/"$rc"; done | |
# WITHOUT UEFI | |
# mkdir -p "$TMPDIR"/boot/extlinux | |
# partuuid=`fdisk -l $DISK | grep 'Disk identifier:'| cut -d ' ' -f 3 | cut -d 'x' -f 2` | |
# ROOTPART="$partuuid-02" | |
# BOOTPART="$partuuid-01" | |
# console='console=${console}' | |
# | |
# echo "Creating extlinux.conf" | |
# cat > "$TMPDIR"/boot/extlinux/extlinux.conf</dev/null || die() { ${PRINTF:-"printf"} "FATAL: %s\\n" "$2"; exit 1 ;} | |
${COMMAND:-command} ${FIXME:-"fixme"} 1>/dev/null || fixme() { ${PRINTF:-"printf"} "FIXME: %s\\n" "$1" ;} | |
${COMMAND:-command} ${DEBUG:-"debug"} 1>/dev/null || { | |
[ -z "$SCRIPT_DEBUG" ] || ${PRINTF:-"printf"} "DEBUG: %s\\n" "$2" | |
} | |
# Dependencies | |
${COMMAND:-command} ${CURL:-"curl"} 1>/dev/null || { | |
case "$LANG" in | |
en-*|*) die 1 "This script requires curl to verify availability of alpine mirror and download relevant files" | |
esac | |
} | |
# sfdisk | |
# sed | |
# grep | |
# read | |
# Process arguments | |
while [ "#$" -gt 0 ]; do case "$1" in | |
"--apk-key") # set apk-key | |
apkKey="$2" | |
shift 1 | |
;; | |
"--alpine-mirror") # Set the expected alpine mirror | |
alpineMirror="$2" | |
shift 1 | |
;; | |
"--target-dev"|"--target-device"|"--target") # Declare target device | |
[ -b "$2" ] || { | |
case "$LANG" in | |
en-*|*) die 1 "The target device '$2' is not a block device, exitting for safety.." | |
esac | |
} | |
targetDev="$2" | |
shift 1 | |
;; | |
# FIXME(Krey): See below we are using a kernel from 3rd party source that needs to be handled | |
# "--kernel") # Set kernel | |
# kernel="$2" | |
# ;; | |
"-h") # Print short help message | |
${FIXME:-"fixme"} "Short help message here" | |
;; | |
"--help") # Print long help message | |
${FIXME:-"fixme"} "Long help message here" | |
;; | |
*) die 2 "This input is not implemented/recognized: $1" | |
esac; shift 1; done | |
# Set default apk-key if it's not set already | |
apkKey="${apkKey:-"alpine-devel@lists.alpinelinux.org-60ac2099.rsa.pub"}" | |
# Mirror for alpine linux | |
## Declare default alpine mirror if none is set | |
[ -n "$alpineMirror" ] || alpineMirror="http://dl-cdn.alpinelinux.org/alpine" | |
## Check that the alpine mirror is working | |
${CURL:-"curl"} "$alpineMirror" || { | |
case "$?" in | |
0) | |
case "$LANG" in | |
en-*|*) ${DEBUG:-"debug"} 1 "The alpine mirror '$alpineMirror' is working" ;; | |
esac | |
;; | |
97) | |
case "$LANG" in | |
en-*|*) ${DIE:-"die"} 1 "Curl returned exit state '97' while checking alpine mirror '$alpineMirror', assuming that the mirror is not reachable" | |
esac | |
;; | |
esac | |
} | |
# Kernel | |
## Set the expected kernel if it's not already set | |
kernel="${kernel:-"linux-sunxi-5.17.4-r0"}" | |
kernelUrl="${kernelPackage:-"https://dev.alpinelinux.org/~mps/sunxi/$kernel.apk"}" | |
## Cache the kernel | |
[ -f "$cacheDir/$scriptName/$kernel.apk" ] || ${CURL:-"curl"} "$alpineMirror" "$kernelUrl" --output "$cacheDir/$scriptName/$kernel.apk" | |
# Create the .img file | |
[ -f "$output" ] || ${DD:-"dd"} \ | |
if="/dev/zero" \ | |
of="$output" \ | |
seek="$((512 * 2099199))" \ | |
bs="512" | |
# Make the partitions | |
# NOTE-QA(Krey): This could be sanitized through e.g. `$ [ "$(${FDISK:-"fdisk"} --list "$output" | grep "Disklabel type: dos" | sed -E "s/^(Disklabel\stype:\s)(.*))" = dos ] || printf "%s\n" "o" | ${SFDISK:-sfdisk} "$output"`, but shell is kinda too limited to do that in a maintainable way due to potential changes in fdisk's output | |
${PRINTF:-"printf"} "%s\n" \ | |
"o" \ | |
"n" \ | |
"p" \ | |
"1" \ | |
"2048" \ | |
"616447" \ | |
"n" \ | |
"2" \ | |
"616448" \ | |
"2713599" \ | |
"w" \ | |
| ${SFDISK:-"sfdisk"} "$output" | |
### --- ### | |
echo "eeep2" | |
exit 255 | |
# NOTE(Krey): Abandoned as shell is too limited on programming capability to make this reliable | |
# bootloaderEFI="0" # Without UEFI as we don't have an objective reason to use it | |
# if [ "$bootloaderEFI" = "1" ]; then | |
# | |
# elif [ "$bootloaderEFI" = "0" ]; then | |
# case "$partitioningMethod" in | |
# "sfdisk") | |
# # Set the msdos table | |
# targetDevTable="$(${SFDISK:-"sfdisk"} --list "$targetDev" | ${GREP:-"grep"} "Disklabel" | ${SED:-"sed"} --regexp-extended "s/^(Disklabel\stype\:\s)(.*)$/\2/g")" | |
# case "$targetDevTable" in | |
# "dos") # Expected table | |
# case "$LANG" in | |
# en-*|*) ${DEBUG:-debug} 1 "Target device '$targetDevice' is already using 'dos' table" | |
# esac | |
# ;; | |
# "gpt") # Unexpected table | |
# # Print the current partition list for user review | |
# ${SFDISK:-"sfdisk"} --list "$targetDev" | |
# | |
# # Inform user about important decision | |
# case "$LANG" in | |
# en-*|*) ${PRINTF:-"printf"} "%s\\n" \ | |
# "The target device '$targetDev' is using wrong table '$targetDevTable', do you wish to overwrite it?" \ | |
# "To proceed type: IRREVERSEBLY DESTROY DATA ON $targetDev" | |
# esac | |
# | |
# # Process the answer | |
# ${READ:-read} -r makeTableAnswer | |
# case "$makeTableAnswer" in | |
# # TRANSLATE(Krey): This needs to be updated with translations | |
# "IRREVERSEBLY DESTROY DATA ON $targetDev") | |
# # Make 'dos' partition table on target device | |
# ${PRINTF:-"printf"} "%s" "o" | ${SFDISK:-"sfdisk"} "$targetDev" || ${DIE:-"die"} 1 "sfdisk failed to make 'dos' partition table on target device '$targetDev'" | |
# | |
# # Check the new partition table | |
# newTargetDevTable="$(${SFDISK:-"sfdisk"} --list "$targetDev" | ${GREP:-"grep"} "Disklabel" | ${SED:-"sed"} --regex-extended "s/^(Disklabel\stype\:\s)(.*)$/\2/g")" | |
# [ "$newTargetDevTable" = "dos" ] || { | |
# case "$LANG" in | |
# en-*|*) ${DIE:-"die"} 1 "The partiion table on target device '$targetDev' has unexpected table '$newTargetDevTable', exitting for safety.." | |
# esac | |
# } | |
# | |
# ;; | |
# *) | |
# case "$LANG" in | |
# en-*|*) ${DIE:-"die"} 0 "Script terminated.." | |
# esac | |
# | |
# esac | |
# ;; | |
# *) ${DIE:-die} 255 "The table on target device '$targetDevice' in unexpected, exitting for safety: $targetDevTable" | |
# esac | |
# | |
# # Ensure that there is a an unformatted space for the bootloader | |
# check sector 0 to 40959 (20MiB) is an unformatted space || | |
# | |
# ;; | |
# *) | |
# case "$LANG" in | |
# en-*|*) ${DIE:-"die"} 1 "Partitioning method '$partitioningMethod' is not implemented" | |
# esac | |
# esac | |
# else | |
# die 255 "Unexpected happen while choosing whether we will do EFI in the bootloader" | |
# fi | |
### --- ### | |
echo "eeep" | |
exit 87 | |
echo "Paritioning disk" | |
# fat32 512, ext4 8GB | |
parted -s "$DISK" mktable msdos > /dev/null | |
parted -s "$DISK" unit s -- mkpart primary ext4 8192 1056767 > /dev/null | |
parted -s "$DISK" unit s -- mkpart primary ext4 1056768 17833983 > /dev/null | |
parted -s "$DISK" -- set 1 esp on > /dev/null | |
echo "Creating dirs and mounting" | |
mkfs.fat -F 32 -n ESP "$BOOTDEV" | |
#mkfs.ext4 -qL root "$ROOTDEV" | |
#mount -t ext4 "$ROOTDEV" "$TMPDIR" | |
mkfs.f2fs -f -l root "$ROOTDEV" | |
mount -t f2fs "$ROOTDEV" "$TMPDIR" | |
mkdir -p "$TMPDIR"/boot | |
mkdir -p "$TMPDIR"/boot/efi "$TMPDIR"/etc/apk/keys | |
mount -t vfat "$BOOTDEV" "$TMPDIR"/boot/efi | |
echo "Setup apk keys and repositories" | |
wget -qP "$TMPDIR"/etc/apk/keys https://alpinelinux.org/keys/"$APK_KEY" | |
printf "$MIRROR/edge/%s\n" main community testing > "$TMPDIR"/etc/apk/repositories | |
echo "installing base packages" | |
apk --allow-untrusted --root "$TMPDIR" --arch aarch64 --initdb add \ | |
alpine-base alpine-baselayout alpine-conf kmod openrc \ | |
dbus util-linux blkid chrony u-boot-sunxi \ | |
sysfsutils ssl_client ca-certificates-bundle alpine-keys \ | |
ethtool e2fsprogs libudev-zero libudev-zero-helper \ | |
iwd linux-firmware-none efibootmgr ttf-dejavu \ | |
agetty terminus-font openresolv tar wget | |
apk --allow-untrusted --root "$TMPDIR" --arch aarch64 --no-script add $kernel | |
apk --allow-untrusted --root "$TMPDIR" --arch aarch64 --no-script add grub-efi grub-mkfont | |
#dd if="$TMPDIR"/usr/share/u-boot/teres_i/u-boot-sunxi-with-spl.bin of=$DISK bs=8k seek=1 | |
dd if=u-boot-sunxi-with-spl.bin of=$DISK bs=8k seek=1 | |
echo "Setting up services and inittab" | |
for rc in boot/bootmisc boot/hostname boot/modules boot/sysctl boot/urandom boot/networking \ | |
sysinit/devfs sysinit/hwdrivers sysinit/mdev sysinit/modules \ | |
shutdown/mount-ro shutdown/killprocs \ | |
default/dbus default/chronyd default/iwd; do | |
ln -s /etc/init.d/"${rc##*/}" "$TMPDIR"/etc/runlevels/"$rc" | |
done | |
echo "preparing scripts for setup" | |
cat > "$TMPDIR"/root/grub-setup.sh< /boot/grub/grub.cfg | |
exit | |
EOF | |
echo 'GRUB_DISABLE_LINUX_PARTUUID=false' >> "$TMPDIR"/etc/default/grub | |
echo 'GRUB_CMDLINE_LINUX="rootwait console=tty1"' >> "$TMPDIR"/etc/default/grub | |
echo 'GRUB_TIMEOUT=10' >> "$TMPDIR"/etc/default/grub | |
echo 'GRUB_FONT="/boot/grub/fonts/dejavu.pf2"' >> "$TMPDIR"/etc/default/grub | |
chmod 0744 "$TMPDIR"/root/grub-setup.sh | |
echo "Settting grub boot loader" | |
mount -t proc none $TMPDIR/proc | |
mount -o bind /sys $TMPDIR/sys | |
mount -o bind /dev $TMPDIR/dev | |
echo "Run this two commands and after that exit" | |
echo "grub-install --target=arm64-efi --efi-directory=/boot/efi --removable" | |
echo "grub-mkconfig > /boot/grub/grub.cfg" | |
chroot $TMPDIR /root/grub-setup.sh | |
#chroot $TMPDIR /bin/ash -l | |
umount $TMPDIR/dev | |
umount $TMPDIR/sys | |
umount $TMPDIR/proc | |
sed -i 's/^tty1.*/tty1::respawn:\/sbin\/agetty -L 115200 tty1 linux --login-pause --autologin root --noclear/' $TMPDIR/etc/inittab | |
echo "Finished, cleaning up" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment