From: Ralph Ronnquist Date: Wed, 24 Jan 2024 21:02:37 +0000 (+1100) Subject: capture X-Git-Url: https://git.rrq.au/?a=commitdiff_plain;h=13753076a64ac46c4a54e9ce3654a31aab930ee4;p=rrq%2Ftiniest.git capture --- diff --git a/mkit.sh b/mkit.sh index 2fb62d0..48d4724 100755 --- a/mkit.sh +++ b/mkit.sh @@ -1,308 +1,47 @@ -#!/bin/bash +#!/bin/sh # -# A script to prepare the tiniest "linux system". It's a kernel and an -# initrd within a FAT with a syslinux boot loader. The initrd contains -# a fully expanded busybox and uses /bin/sh as its init. -# -# This script creates and packs that initrd, as well as the whole, -# boot image. - -set -e - -echo '### Step 1. Download original Packages files from sources' -mkdir -p save -[ -L save/save ] || ln -s . save/save -MAPFILE=save/mapfile.txt -DEPFILE=save/mapdepends.txt - -REPOS=( - deb.devuan.org/merged_daedalus_main - deb.devuan.org/merged_ceres_main -) -ARCH="amd64" -MBR=dos # gpt - -: > $MAPFILE -: > $DEPFILE +# This is the "main" script for preparing an ISO. -for REPO in ${REPOS[@]} ; do - W=( ${REPO//_/ } ) - SUITE=${W[1]} - SECTION=${W[2]} - - PKGFILE=save/${W[0]/\//_}_${SUITE}_${SECTION}_binary-${ARCH}_Packages - if [ ! -r $PKGFILE ] ; then - XZSRC="http://${W[0]}/dists/$SUITE/$SECTION/binary-$ARCH/Packages.xz" - echo "$XZSRC" - wget -qO - $XZSRC | xzcat - > ${PKGFILE} - fi - - echo '# Reduce Packages file into two maps for filename and depends' - echo "# ..creating $MAPFILE and $DEPFILE" - awk -v MAP=$MAPFILE -v DEP=$DEPFILE ' - BEGIN { print "###" >> MAP; print "###" >> DEP; } -$1=="Package:" {P=$2; next} -$1=="Pre-Depends:" {print P,$0 >> DEP;next } -$1=="Depends:" {print P,$0 >> DEP;next } -$1=="Filename:" {print P,$2 >> MAP;next } -' ${PKGFILE} -done +export APT_CONFIG=repo.conf -# Append any additional saved deb files -for DEB in save/*.deb ; do - P="${DEB%%_*}" - P="${P#save/}" - echo "$P save/$DEB" >> $MAPFILE - dpkg-deb -f "$DEB" Depends Pre-Depends | sed "s/^/$P/" >> $DEPFILE -done +# Update the repository package indexes as needed +apt-get update -# Function to find the filename for a given package in the given mapfile -maplookup() { - local FN=${3:-tail} - echo "maplookup $1 $2" >&2 - grep "^$1 " $2 >&2 - grep "^$1 " $2 | $FN -n 1 | sed 's/[^ ]* //' -} +# Prepare the initrd filesystem, containing a linux kernel with all +# modules, a busybox-static as OS platform, and an init script -# Function to clean up a "depends' line -depclean() { - sed 's/^[^:]*: //;s/([^)]*)//g;s/|[^,]*/ /g;s/,/ /g;s/\s\+/ /g' +# Download a package into deb/ +download() { + apt-get download $1 + mv repo/$(pwd)/$1_* deb/ || exit 1 } -# Map all dependencies for a list of package -# -mapdeps() { - local D - local B=( ) - local X=" $* " - for D in $* ; do - local A=( - $(grep "^$D Pre-Depends:" $DEPFILE | head -n 1 | depclean) - $(grep "^$D Depends:" $DEPFILE | head -n 1 | depclean) - ) - for P in ${A[@]} ; do - [ -z "${X%%* $P *}" ] && continue - B=( $B $P ) - X="$X$P " - done - done - if [ -z "$B" ] ; then - echo $X - else - mapdeps $X - fi +# Show meta attribute $1 for package $2, with newline between values +# +showdata() { + cat repo/var/lib/apt/lists/*_Packages | \ + sed "1,/^Package: $2/d;/^$1: /!d;s|$1: ||;s|([^)]*)||g;q" | \ + tr , '\012' } -# Function to download a deb file and return its name -debfile() { - local FN=${2-tail} - local F="$(maplookup $1 $MAPFILE $FN)" - local P="${F##*/}" - if [ ! -e "save/$P" ] ; then - for REPO in ${REPOS[@]} ; do - echo "download http://${REPO%%_*}/$F" >&2 - ( cd save && wget -q "http://${REPO%%_*}/$F" ) && break - ls -l save/$P >&2 - done || return 1 +# Unpack a deb $1 "manually" with $2 as root, ignoring dependencies +unpack() { + echo "unpack $1 [begin]" + local DEB=$(ls deb/${1}_* 2>/dev/null) + if [ -z "$DEB" ] ; then + download $1 + DEB=$(ls deb/${1}_* 2>/dev/null) + if [ -z "$DEB" ] ; then + echo "** Cannot download $1" >&2 + exit 1 + fi fi - echo "save/$P" -} - -# Function to extract from a deb without executing and pre/post scripts -# $1 = rootfs $2 = package -debextract() { - ar p $2 data.tar.xz | tar xJf - -C $1 -} - -# Deteremine which kernel to use; this is -echo "# Determine kernel" -KERNEL="$(maplookup linux-image-amd64 $DEPFILE head | \ - sed 's/.*\(linux-image[^ ]*\).*/\1/')" -echo "# ... $KERNEL" - -echo '### Step 2. Create and populate the initrd, and packit up.' -# The initrd contains only a few kernel modules for coping with a -# later pivoting onto a "full" filesystem. - -echo "# Create initrd filesystem" -rm -fr initrd - -# Helper function to copy a file or link, given full path -# $1 = full pathname, $2 = (relative) root path -copylinks() { - echo "copylinks $*" >&2 - [ -e "initrd/$1" ] && return 0 - mkdir -p "initrd${1%/*}" - if [ -L "$1" ] ; then - local L=$(readlink $2$1) - ln -s $L initrd$1 - [ "${L:0:1}" = "/" ] || L="${1%/*}/$L" - copylinks $L $2 - else - cp $2$1 initrd/$1 - fi -} - -# Helper function to copy dynamic binary and its libraries -# $1 = full pathname, $2 = (relative) root path -bincp() { - echo "bincp $*" >&2 - [ -e "initrd/$1" ] && return 0 - copylinks $1 $2 - objdump -x $2$1 | while read A B ; do - [ "$A" == "NEEDED" ] || continue - local L="$(find ${2:-/} -name $B)" - [ -z "$L" ] && echo "MISSING $B" && exit 1 - copylinks ${L#$2} $2 - done + ar p $DEB data.tar.xz | tar xJf - --keep-directory-symlink -C $2 + echo "unpack $1 [end]" } -echo '# Include static vtoydump for Ventoy support' -VTOYDUMP=../ventoy/vtoydump/vtoydump -if [ -e "$VTOYDUMP" ] ; then - mkdir -p initrd/bin - cp "$VTOYDUMP" initrd/bin -fi - -echo "# Extract static busybox, and fluff it up for more utilities" -mkdir -p initrd -debextract initrd $(debfile busybox-static head) -for L in $(initrd/bin/busybox --listfull) ; do - mkdir -p $(dirname initrd/$L) - [ -e "initrd/$L" ] && continue - case "$L" in - bin/busybox) : ;; - usr/*) ln -s ../../bin/busybox initrd/$L ;; - sbin/*) ln -s ../bin/busybox initrd/$L ;; - bin/*) ln -s busybox initrd/$L ;; - linuxrc) ln -s bin/busybox initrd/$L ;; - esac -done - -echo "# Extract the kernel package ($KERNEL)" -echo "# .. and syslinux stuff if needed" -if [ ! -d kernel ] ; then - mkdir kernel - debextract kernel $(debfile $KERNEL head) - debextract kernel $(debfile squashfs-tools head) - debextract kernel $(debfile syslinux) - debextract kernel $(debfile syslinux-common) - debextract kernel $(debfile syslinux-efi) - debextract kernel $(debfile syslinux-utils) - debextract kernel $(debfile isolinux) -fi - -echo "# Include some kernel modules in the initrd" -MODULES=( - # disk - scsi_common scsi_mod libata ata_piix ata_generic cdrom sr_mod - crc32-pclmul crct10dif_common crc-t10dif crc64 crc64-rocksoft - t10-pi sd_mod sg - nls_cp437 nls_ascii fat vfat - crc32c_generic jbd2 mbcache crc16 ext4 - usb-storage usbcore usb-common xhci-pci xhci-hcd - isofs exfat loop - efivarfs - # input - psmouse evdev - # network - e1000 - # overlay - overlay squashfs -) -MOODLES="" -B=$(pwd) -for m in ${MODULES[@]} ; do - km=$(find kernel/lib/modules -name $m.ko) - if [ -z "$km" ] ; then - echo "Missing module $m" - continue - fi - im=initrd/${km#kernel/} - MOODLES+=" $B/$im" - mkdir -p $(dirname $im) - cp -n $km $im -done -V=${KERNEL#linux-image-} -mkdir -p initrd/boot initrd/lib/modules/$V -cp kernel/boot/System.map-$V initrd/ -cp kernel/lib/modules/$V/modules.order initrd/lib/modules/$V/ -cp kernel/lib/modules/$V/modules.builtin initrd/lib/modules/$V/ -depmod -F initrd/System.map-$V -b initrd $V $MOODLES - -echo "# setup a scripted init. The kernel runs this via the #! interpreter" -rm -f initrd/sbin/init # just in case -cp init/init initrd/init -chmod a+x initrd/init - -echo "# Declare password-less root" -mkdir -p initrd/etc -echo 'root::0:0:root:/root:/bin/bash' > initrd/etc/passwd - -echo "# Now pack up that initrd as initrd.gz" -( cd initrd ; find . | fakeroot cpio -H newc -o | gzip ) >initrd.gz - -echo '### Step 3. create a 32 Mb fat filesystem with bios and UEFI boot' -rm -f bootimage.raw -dd if=/dev/zero of=bootimage.raw bs=32M count=1 - -# Prepare a gpt/dos partition table with a first partition marked as EFI -sfdisk bootimage.raw <