Refactoring with improved procedure. More comments.
authorRalph Ronnquist <rrq@rrq.au>
Sun, 15 Sep 2024 13:35:02 +0000 (23:35 +1000)
committerRalph Ronnquist <rrq@rrq.au>
Sun, 15 Sep 2024 13:35:02 +0000 (23:35 +1000)
build-installer-functions.sh [new file with mode: 0644]
build-installer.sh
installer-packages-arm64.list [new file with mode: 0644]

diff --git a/build-installer-functions.sh b/build-installer-functions.sh
new file mode 100644 (file)
index 0000000..a1640e9
--- /dev/null
@@ -0,0 +1,230 @@
+# This file implements special purpose bash functions to support the
+# build-installer.sh script.
+
+# Declare global tables:
+# DEBURL is a mapping: package => download source path
+# DEBDIR is a mapping: package => download target dir
+# PKGS is a subset of DEBURL with only packages to download
+typeset -A DEBURL DEBDIR PROVIDER PKGS
+
+# die() simply prints its arguments as a message to stderr and then
+# calls exit(1). This is only used at bailout points when something
+# seems badly wrong.
+die() { echo "$*" >&1 ; exit 1 ; }
+
+# deb_url_map() reduces a Packages file (argument $1) into a series of
+# mappings of the form "package=filename".
+deb_url_map() {
+    sed '/Package:/{s/[^ ]* //;h;d};/Filename:/!d;s/[^ ]* /=/;H;x;s/\n//' $1
+}
+
+# deb_provider_map() reduces a Packages files $@ into a series of
+# mappings package=provides. The provides part is one or more comma
+# separated packae names without spaces
+deb_provider_map() {
+    sed '/Package:/{s/[^ ]* //;h;d};/Provides:/!d;s/[^ ]* /=/;H;x;s/\n//;s/ *//g;s/([^)]*)//g' $@ | tee deb_provider_map.log
+}
+
+# check_depends() "resolves" an alternative dependency (presented as
+# the function arguments) to a preferred choice based on the global
+# table $PKGS. If an alternative is mentioned in $PKGS (i.e. it's an
+# already selected package) the check_depends returns silently.
+# Otherwise it prints the first alternative before returning. However,
+# if $ALLDEP is set, the chosen alternative printed also if found in
+# $PKGS.
+check_depends() {
+    local P
+    for P in $@ ; do
+       [ -z "${PKGS[$P]}" ] && continue
+       [ -z "$ALLDEP" ] || echo $P
+       return 0
+    done
+    echo "$1"
+}
+
+# show_depends() looks up and prints the Depends, Pre-Depends and
+# optionally the Recommends, lines for a given package from the
+# $SOURCES/*-Packages files, with post processing to remove version
+# constraints and reporting the entries on separate lines. Any
+# alternative entry becomes a single line alternatives space
+# separated.
+show_depends() {
+    local TAGS="Depends\|Pre-Depends" D DX DV X
+    [ "$REC" = T ] && TAGS+="\|Recommends"
+    sed '/^Package: '$1'$/,/^$/!d;/^\('$TAGS'\):/!d;s/^[^:]*: //;s/([^)]*)//g'\
+       $SOURCES/*-Packages | tr , '\012' | tr -d '|' | \
+       while read DX ; do
+           DV=( )
+           for D in $DX ; do
+               DV=( $DV $(check_depends ${PROVIDER["$D"]}) )
+           done
+           echo "${DV[*]}"
+       done
+}
+
+# missing_depends() enumerates all dependent and recommended
+# packages of a given package. Uses check_depends() to handle
+# alternative dependencies
+missing_depends() {
+    local D
+    REC=T ALLDEP= show_depends $1 | \
+       while read D ; do
+           check_depends ${PROVIDER["$D"]}
+       done
+}
+
+# expand_install_depends() expands a given package ($1) recursively
+# into all its depends and recommends and installs them all in PKGS.
+expand_install_depends() {
+    local F P
+    for P in $(missing_depends $1) ; do
+       F="${DEBURL[$P]}"
+       [ -z "$F" ] && continue
+       [ -z "${PKGS["$P"]}" ] || continue
+       PKGS["$P"]="$F"
+        expand_install_depends $P
+    done
+}
+
+# oneof() returns 0 (succeeds) if $1 is one of the other arguments
+# $2... and it returns 1 (fails) otherwise
+oneof() {
+    local P
+    for P in ${@:2} ; do [ "$1" = "$P" ] && return 0 ; done
+    return 1
+}
+
+# dropfirst() prints all of $2... except any $1
+dropfirst() {
+    for P in ${@:2} ; do [ "$1" = "$P" ] || echo $P ; done
+}
+
+# install_order() works out recursively all depends (and optionally
+# recommends) for a given package $1. In its recursion, it uses the
+# arguments $2... as recursion state, to tell inner recursion levels
+# which dependent packages are to be handled at outer recursion
+# levels. The result is a print out of packages in "best install
+# order" i.e. innermost dependencies first.
+install_order() {
+    local DEPS=( $(REC=$REC ALLDEP=$ALLDEP show_depends $1) )
+    local ARGS=( ${@:2} )
+    local D DX
+    for D in ${ARGS[@]} ; do
+       DEPS=( $(dropfirst $D ${DEPS[@]}) )
+    done
+    [ "$QUIET" = yes ] || echo "$1 [${ARGS[*]}] => ${DEPS[*]}" >&2
+    for D in ${DEPS[@]} ; do
+       oneof $D ${ARGS[@]} && continue
+       DX=( $(dropfirst $D ${DEPS[@]}) )
+       REC=$REC install_order $D ${DX[@]} ${ARGS[@]} $1
+    done
+    oneof $1 ${ARGS[@]} || echo $1
+}
+
+# download() downloads a given package ($1) and all its depends and
+# recommends into the $MEDIA pool. It uses install_order() to
+# determine dependents. Note that $ALLDEP may be set or unset (for
+# check_depends()) for considering all dependencies or only
+# considering those not already mentioned in $PKGS. All downloaded
+# packages will be installed into $PKGS.
+download() {
+    local P
+    for P in $(REC=T ALLDEP=$ALLDEP install_order $1) $1 ; do
+       [ "$QUIET" = yes ] || echo "DOWNLOAD $P" >&2
+       local URI="${DEBURL["$P"]}"
+       [ "$QUIET" = yes ] || echo "DOWNLOAD URI=$URI" >&2
+       [ -z "$URI" ] && die "** Cannot find package $P in the sources!!"
+       local F="${DEBDIR["$1"]}/${URI##*/}"
+       [ "$QUIET" = yes ] || echo "DOWNLOAD F=$F" >&2
+       [ -f "$F" ] && continue # alread y downloaded
+       PKGS["$P"]="$URI"
+       local URL="$SOURCE_SERVER/$URI"
+       mkdir -p "${F%/*}"
+       for I in {1..5} ; do
+           wget -O $F -nv "$URL" && break
+           echo "err $I: $URL" >&2
+           rm $F
+       done
+       if [ ! -f "$F" ] ; then
+           echo "** download error for package $P" >&2
+           return 1;
+       fi
+    done
+}
+
+# debs() downloads $1 and all it depends and recommends (as goverend
+# by $ALLDEP), then expand all dependencies (not recommends, unless
+# $REC is set) to the resulting $MEDIA package filename full
+# pathnames, enumerated in reverse dependency order.
+debs() {
+    local P
+    download $1
+    for P in $(REC=$REC ALLDEP=T install_order $1) ; do
+       echo $(realpath ${DEBDIR["$P"]}/${P}_*deb)
+    done
+}
+
+
+# herecoc() creates a heredoc file $1 from stdin, ensuring that the
+# path for the filename exists.
+heredoc() {
+    mkdir -p $(dirname $1)
+    cat > $1
+}
+
+# executable() creates an executable heredoc $1 from stdin, ensuring
+# that the directory path exists and that the file is exectable.
+executable() {
+    heredoc $1
+    chmod a+x $1
+}
+
+# target_dpkg() runs dpkg in $INITRD within fakechroot fakeroot and
+# with appropriate pathnames settings plus --force-architecture. It
+# also ensures $INITRD is set up to allow preinst and postrm scripting
+# to run (see inline comments)
+# etc/debconf.conf -- telling where databases are
+target_dpkg() {
+    local HERE=$(pwd)
+    cd $INITRD
+    if [ ! -f etc/debconf.conf ] ; then
+       cat /etc/debconf.conf | heredoc etc/debconf.conf
+       local F
+       for F in $(sed '/^Filename:/!d;s/[^ ]* /./' etc/debconf.conf) ; do
+           [ -f "$F" ] || echo -n | heredoc $F
+       done
+    fi
+    for Q in 1 10 ; do
+       echo "DPKG $*" >&2
+       if fakechroot fakeroot dpkg --abort-after=500 \
+                     --log=dpkg.log --root=. $@ ; then
+           cd $HERE
+           return 0
+       fi
+       [ $Q = 10 ] && die "severe badness :("
+       echo "DPKG: repeating ========================================" >&2
+    done
+}
+
+# Helper function to enumerate pool packages
+pool_packages() {
+    local T SRC=$SOURCES/non-free-firmware-Packages
+    {
+       # This step prepares the list of all packages of required,
+       # important and standard priority
+       for T in required important standard ; do
+           sed '/^Package:/{s/[^ ]* //;h;d};/^Priority: '$T'$/!d;x' \
+               $SOURCES/*-Packages
+       done
+
+       # This step prepares the list of all packages of
+       # non-free-firmware
+       if [ -r $SRC ] ; then
+           sed '/^Package:/!d;s/[^ ]* //' $SRC
+       fi
+
+       # This step includes additional packages from files
+       # pool-packages*.list
+       sed '/#/d;/^$/d' pool-packages*.list
+    } | sort -u
+}
index b2ac246b4484794a4dc25628d72e308d8f6972c0..62bc964d2696e610d8e651fb6a708186c9b2ec4d 100755 (executable)
@@ -6,7 +6,6 @@
 export http_proxy=http://10.10.10.100:3142
 
 : ${LINUX:=linux-image-6.1.0-25-arm64}
-
 : ${DISTNAME:=daedalus}
 : ${DISTVERS:=5.1.0}
 : ${TARGET_ARCH:=arm64}
@@ -17,110 +16,26 @@ export http_proxy=http://10.10.10.100:3142
 : ${MEDIA:=$BUILD/media}
 : ${INITRD:=$BUILD/initrd}
 : ${UDEBSDIR:=$INITRD/udebs}
-: ${UDEBSLIST:=$(pwd)/installer-packages.list}
-
-mkdir -p $SOURCES $MEDIA/{pool,dists} $INITRD
-
-# Declare global tables:
-# DEBURL is a mapping: package => download source path
-# DEBDIR is a mapping: package => download target dir
-# PKGS is a subset of DEBURL with only packages to download
-typeset -A DEBURL DEBDIR PKGS
-
-# Helper function to print a message to stderr and exit(1). This is
-# used as bailout when something seems badly wrong.
-die() { echo "$*" >&1 ; exit 1 ; }
-
-# Helper function to reduce a Pacakges file into a series of mappings
-# of the form "package=filename"
-deb_url_map() {
-    sed '/Package:/{s/[^ ]* //;h;d};/Filename:/!d;s/[^ ]* /=/;H;x;s/\n//' $1
-}
-
-# Helper function that resolves alternative dependency to preferred
-# choice, which is one already selected (in PKGS) or else the first of
-# options.
-check_depends() {
-    local P
-    for P in $@ ; do [ -n "${PKGS[$P]}" ] && return 0 ; done
-    echo "$1"
-}
-
-# Helper function that enumerates all dependent and recommended
-# packages of a given package. Uses check_depends to handle
-# alternative dependencies
-depends() {
-    local D
-    sed '/^Package: '$1'$/,/^$/!d;/^\(Depends\|Pre-Depends\|Recommends\):/!d;s/^[^:]*: //;s/([^)]*)//g' $SOURCES/*-Packages | tr , '\012' | \
-       while read D ; do check_depends ${D//\|/ } ; done
-}
-
-# Helper function that expands a given package recursively into all
-# its depends and recommends and installs them all in PKGS.
-expand_depends() {
-    local F P
-    for P in $(depends $1) ; do
-       F="${DEBURL[$P]}"
-       [ -z "$F" ] && continue
-       [ -z "${PKGS["$P"]}" ] || continue
-       PKGS["$P"]="$F"
-        expand_depends $P
-    done
-}
-
-# Helper function to download package $1 and all its dependencies
-#
-download() {
-    local URI="${DEBURL["$1"]}"
-    [ -z "$URI" ] && return 1 # Just ignore missing packages
-    local F="${DEBDIR["$1"]}/${URI##*/}"
-    [ -f "$F" ] && return 0 # alread y downloaded
-    PKGS["$1"]="$URI"
-    local URL="$SOURCE_SERVER/$URI"
-    mkdir -p "${F%/*}"
-    for I in {1..5} ; do
-       wget -O $F -nv "$URL" && break
-       echo "err $I: $URL" >&2
-       rm $F
-    done
-    if [ -f "$F" ] ; then
-       [ -n "$2" ] && cp "$F" "$2/${F##*/}"
-       for D in $(depends $1) ; do download $D $2 ; done
-       return 0
-    fi
-    echo "** download error for package $1" >&2
-    return 1;
-}
-
-# Helper function to enumerate pool packages
-pool_packages() {
-    local T SRC=$SOURCES/non-free-firmware-Packages
-    {
-       # This step prepares the list of all packages of required,
-       # important and standard priority
-       for T in required important standard ; do
-           sed '/^Package:/{s/[^ ]* //;h;d};/^Priority: '$T'$/!d;x' \
-               $SOURCES/*-Packages
-       done
+: ${UDEBSLIST:=$(pwd)/installer-packages-$TARGET_ARCH.list}
 
-       # This step prepares the list of all packages of
-       # non-free-firmware
-       if [ -r $SRC ] ; then
-           sed '/^Package:/!d;s/[^ ]* //' $SRC
-       fi
+: ${QUIET:=yes}
 
-       # This step includes additional packages from files
-       # pool-packages*.list
-       sed '/#/d;/^$/d' pool-packages*.list
-    } | sort -u
-}
+# Include the supporting functions.
+source build-installer-functions.sh
 
-############################################################
+# Ensure a pre-structured build area, including silly-links
+mkdir -p $SOURCES $MEDIA/{pool,dists}
+mkdir -p $INITRD/var/{log,lib/dpkg}
+mkdir -p $UDEBSDIR
+for D in bin sbin lib lib32 lib64 ; do
+    mkdir -p $INITRD/usr/$D
+    [ -e "$INITRD/$D" ] || ln -sTf usr/$D $INITRD/$D
+done
 
-#===== Step 1: Setup "The Sources".
-#
-# This which means to download Packages files for the $DISTNAME,
-# $SECTIONS and $TARGET_ARCH concerned into the $SOURCES directory.
+######################################################################
+# Step 1: Ensure that Packages files for the $DISTNAME, $SECTIONS and
+# $TARGET_ARCH are available in the $SOURCES directory, downloading
+# and decompressing as needed.
 
 for S in $SECTIONS ; do
     BASE=$SOURCE_SERVER/dists/$DISTNAME/$S/binary-$TARGET_ARCH/Packages
@@ -129,207 +44,94 @@ for S in $SECTIONS ; do
     for E in .xz .gz "" ; do
        if wget -nv -O $INTO$E $BASE$E ; then
            case "$E" in
-               .xz) unxz $INTO$E ;;
-               .gz) gunzip $INTO$E ;;
+               .xz) unxz $INTO$E || die Cannot decompress Packages.xz ;;
+               .gz) gunzip $INTO$E || die Cannot decompress Packages.gz ;;
            esac
            break;
-       else
-           rm -f $INTO$E
        fi
+       rm -f $INTO$E
     done
     [ -f $INTO ] || die "Cannot get $BASE"
 done
 
-#==== Step 2: Prepare DEBURL and DEBDIR from the Packages files as
-# mappings form package name to download filename and pool section
+######################################################################
+# Populate DEBURL and DEBDIR from the $SOURCES/*-Packages files as
+# mappings from package name to download filename and pool section
 # respectively
 
 for S in $SECTIONS ; do
     for M in $(deb_url_map "$SOURCES/${S/\//_}-Packages") ; do
-       echo "$M" >&2
+       [ "$QUIET" = yes ] || echo "$M" >&2
        P="${M%%=*}"
        F="${M#*=}"
        DEBURL["$P"]="$F"
        DEBDIR["$P"]="$MEDIA/pool/$S"
+       PROVIDER["$P"]="$P"
     done
 done
 
-#==== Step 3: load up packages to be unpacked for the initrd. This are
-# packages enumerated in $UDEBSLIST, expanded for depends and
-# recommends.
-
-mkdir -p $UDEBSDIR
-export KERNELVERSION="${LINUX#linux-image-}"
-for P in $(envsubst '${KERNELVERSION}' < $UDEBSLIST | sed '/#/d;/^$/d') ; do
-    download $P $UDEBSDIR
-done
-
-typeset -A INST
-
-# Helper function that resolves alternative dependency to preferred
-# choice, which is one already selected (in PKGS) or else the first of
-# options.
-check_installed_depends() {
-    local P
-    for P in $@ ; do [ -n "${INST[$P]}" ] && return 0 ; done
-    for P in $@ ; do [ -n "${PKGS[$P]}" ] && echo $P && return 0 ; done
-}
-
-# Helper function that enumerates all dependent and recommended
-# packages of a given package. Uses check_depends to handle
-# alternative dependencies
-install_after() {
-    local D
-    sed '/^Package: '$1'$/,/^$/!d;/^\(Depends\|Pre-Depends\|Recommends\):/!d;s/^[^:]*: //;s/([^)]*)//g' $SOURCES/*-Packages | tr , '\012' | \
-       while read D ; do check_installed_depends ${D//\|/ } ; done
-}
-
-# Does $1 occur in $2...
-mentioned() {
-    local X="${@:2}"
-    [ -n "$X" ] && [ -z "${X##*$1*}" ]
-}
-
-# Helper function to enumerate package dependencies in install order
-install_order() {
-    local ORDER=( ${@:1} ) BEFORE=( $(install_after $1) )
-    for D in ${BEFORE[@]} ; do
-       mentioned $D ${@:1} && continue
-       install_order $D ${BEFORE[@]} $1 ${@:1}
+for M in $(deb_provider_map $SOURCES/*-Packages) ; do
+    P="${M%%=*}"
+    F="${M#*=}"
+    for X in ${F//,/ } ; do
+       if [ -z "${PROVIDER["$X"]}" ] ; then
+           PROVIDER["$X"]="$P"
+       else
+           PROVIDER["$X"]="${PROVIDER["$X"]} $P"
+       fi
     done
-    echo $1
-}
-
-# Helper function to for using dpkg in $INITRD
-mydpkg() {
-    fakechroot fakeroot dpkg --force-architecture \
-        --admindir=$INITRD/var/lib/dpkg --log=$INITRD/var/log/dpkg.log \
-        --root=$INITRD $@
-}
-
-# Prepare for unpacking
-mkdir -p $INITRD/var/log $INITRD/var/lib/dpkg
-
-# Set up silly-links
-for D in bin sbin lib lib64 ; do
-    mkdir -p $INITRD/usr/$D
-    ln -sTf usr/$D $INITRD/$D
 done
 
-echo "######## Installing installer ######### ${#PKGS[@]}" >&2
-# Install busybox-static to have a good collection of static binaries.
-# busybox-udeb may be installed and replace some of them
-download busybox-static $UDEBSDIR
-
-mydpkg --unpack $UDEBSDIR/busybox-static_*.deb
-$INITRD/bin/busybox --list | while read B ; do
-    case "$B" in
-       linuxrc|busybox) : ;;
-       acpid|adjtimex|arp|devmem|freeramdisk|ipneigh|klogd| \
-           loadkmap|logread|mdev|run-init|syslogd|tunctl|uevent|vconfig| \
-           watchdog|arping|brctl|crond|fsfreeze|i2cdetect|i2cdump| \
-           i2cget|i2cset|i2ctransfer|loadfont|mim|partprobe| \
-           rdate|telnetd|ubirename|udhcpd)
-           ln $INITRD/bin/busybox $INITRD/sbin/$B
-           ;;
-       tar|dpkg|dpkg-deb)
-           : # ignore these
-           ;;
-       *)
-           ln $INITRD/bin/busybox $INITRD/bin/$B
-           ;;
-    esac
-done
-
-echo "# Patch to pretend debian-installer is installed" >&2
-STATUS=$INITRD/var/lib/dpkg/status
-if ! grep -q 'Package: debian-installer' ${STATUS} ; then
-    # Patch ${STATUS} file to pretend debian-installer is installed
-    VERSION="$(date +"%Y%m%d.%H%M%S-installer")"
-    cat <<EOF >> ${STATUS}
-Package: debian-installer
-Status: install ok installed
-Maintainer: $TARGET_ARCH installer
-Architecture: $TARGET_ARCH
-Version: $VERSION
-Description: devuan installation image
-
+# Register $TARGET_ARCH as the primary architecture
+heredoc $INITRD/var/lib/dpkg/arch <<EOF
+$TARGET_ARCH
 EOF
-fi
-
-mydpkg --force-overwrite --path-include="$UDEBSDIR/*.deb" \
-       --unpack $UDEBSDIR/*.udeb
-
-# Configure in good order
-configured() {
-    local F="$INITRD/var/lib/dpkg/status"
-    local X="$(sed '/Package: '$1'$/,/^$/!d;/^Status:/!d' $F)"
-    [ -z "${X#*installed}" ]
-}
-
-for DEB in $UDEBSDIR/*.udeb ; do
-    F="${DEB##*/}"
-    P="${F%%_*}"
-    for D in $(install_order $P) ; do
-       configured $D && continue
-       mydpkg -E --path-include="$UDEBSDIR/*.deb" --configure $D
-    done
-done
-
-# libc6 cannot be unpacked in fakechroot .. do it by hand
-ar p $UDEBSDIR/libc6_*.deb data.tar.xz | \
-    tar xJf - --keep-directory-symlink -C $INITRD
-cat <<EOF >> $STATUS
-Package: libc6
-Status: install ok installed
-Maintainer: $TARGET_ARCH installer
-Architecture: $TARGET_ARCH
-Version: $(cd $UDEBSDIR ; echo libc6_*.deb | sed 's/^[^_]*_\([^_]*\).*$/\1/')
-Description: libc6 manual
 
+######################################################################
+# Unback a static busybox for the target architecture for a temporary
+# installation of $INITRD/bin/sh as a do-nothing script. This setup is
+# only used for installing libc6 and it will be overridden by
+# installing busybox-udeb later. The purpose of this is only to
+# install libc6, which has a troublesome preinst script that can and
+# should be ignored in this use case.
+target_dpkg -E --unpack $(debs busybox-static)
+executable $INITRD/bin/sh <<EOF
+#!$(pwd)/$INITRD/bin/busybox sh
+echo "*** The do-nothing /bin/sh is used here ***" >&2
 EOF
+target_dpkg -E --install $(debs libc6)
+
+######################################################################
+# Install the $UDEBSLIST packages in given order, with dependencies.
+# This list defines the installer core system that is installed into
+# the initrd. Upon booting, this will locate the media pool and expand
+# itself and progress by installing further udeb packages from the
+# pool as enumerated by pool-packages-installer.list.
+UDEBS=(
+    $( KERNELVERSION="${LINUX#linux-image-}" envsubst '${KERNELVERSION}' \
+                   < $UDEBSLIST | sed '/#/d;/^$/d' )
+)
+for P in ${UDEBS[@]} ; do
+    echo "UDEB install = $P" >&2
+    target_dpkg -E --install --force-overwrite $(debs $P)
+done
 
-# Helper function to generate .list and .md5sums from a tar listing
-dpkg_info_files() {
-    local P
-    cd $INITRD
-    sed '/^.\/$/{s|..|/.|;n};s|^\.||;s|/$||' | \
-       tee "var/lib/dpkg/info/$1.list" | while read P ; do
-       [ -f "${P#/}" ] && md5sum ${P#/}
-    done > "var/lib/dpkg/info/$1.md5sums"
-}
-ar p $UDEBSDIR/libc6_*.deb data.tar.xz | tar tJf - | \
-    dpkg_info_files "libc6:$TARGET_ARCH"
-
-mydpkg -E --install $UDEBSDIR/gcc-12-base_*.deb
-mydpkg -E --install $UDEBSDIR/libgcc-s1_*.deb
-
-# dpkg via tar has wide dependecy graph
-mydpkg -E --install $UDEBSDIR/libbz2-1.0_*.deb
-mydpkg -E --install $UDEBSDIR/liblzma5_*.deb
-mydpkg -E --install $UDEBSDIR/libmd0_*.deb
-mydpkg -E --install --force-overwrite $UDEBSDIR/libpcre2-8-0_*.deb
-mydpkg -E --install $UDEBSDIR/libselinux1_*.deb
-mydpkg -E --install $UDEBSDIR/libzstd1_*.deb
-mydpkg -E --install $UDEBSDIR/zlib1g_*.deb
-mydpkg -E --install $UDEBSDIR/tar_*.deb
-mydpkg -E --install $UDEBSDIR/dpkg_*.deb
-
-# 3f This is set up for choose-mirror and console-setup
+######################################################################
+# Make some additional patches in the initrd to support the
+# installation process. 
 echo ${DISTNAME} > $INITRD/etc/default-release
 mkdir $INITRD/etc/console-setup
 mkdir -p $INITRD/cdrom
 
-# 3g Install "initrd-init" as the initrd /init
+# Install "initrd-init" as the initrd /init to run at boot time
 cp initrd-init $INITRD/init
 
-#==== Step 4. Set up a package pool
+######################################################################
+# Set up package pool media.
 #
 # This will populate $MEDIA/pool/* with deb files and $MEDIA/dists
 # with Packages.xz to describe them. First PKGS is extended with
 # pool_packages, 
-
-# Extend PKGS table with pool packages;
 for P in $(pool_packages) ; do
     F="${DEBURL[$P]}"
     [ -z "$F" ] || PKGS["$P"]="$F"
@@ -340,7 +142,7 @@ echo -n "*** computing dependencies" >&2
 for P in ${!PKGS[@]} ; do expand_depends "$P" ; done
 echo
 
-# Download the PKGS table packages into their pool sections;
+# Download the PKGS table packages into their pool sections.
 for P in ${!PKGS[@]} ; do download "$P" ; done
 
 # Prepare the distribution indexes for the various sections.
@@ -362,21 +164,17 @@ apt-ftparchive \
     release $MEDIA/dists/$DISTNAME > $MEDIA/dists/$DISTNAME/Release
 ln -s $DISTNAME $MEDIA/dists/stable
 
-# Final media touch-up for bootstrap-base
+# Final media touch-up as expected by bootstrap-base
 mkdir $MEDIA/.disk/
 touch $MEDIA/.disk/base_installable
 echo full_cd > $MEDIA/.disk/cd_type
 date +"Devuan GNU/Linux $DISTVERS $DISTNAME $ARCH - bespoke %Y%m%d" \
      > $MEDIA/.disk/info
 
-# Finally prepare a squashfs of $MEDIA into $INITRD
+######################################################################
+# Prepare a squashfs of $MEDIA into $INITRD. Pack up $INITRD into a
+# top-level initrd.gz, and copy out vmlinuz as well
 fakeroot mksquashfs $MEDIA $INITRD/pool.squashfs
-
-#==== Step 5: Pack up the initrd
-
-# Pack up as initrd.gz and grab vmlinuz
 find $INITRD -not -name udebs -printf '%P\n' | \
     fakeroot cpio -o -H newc -D $INITRD | gzip > initrd.gz
 cp $INITRD/boot/vmlinuz .
-
-exit 0
diff --git a/installer-packages-arm64.list b/installer-packages-arm64.list
new file mode 100644 (file)
index 0000000..ab7e628
--- /dev/null
@@ -0,0 +1,123 @@
+# This is a list of packages that should be unpacked for the installer
+# Lines with # are ignored. Use envsubst with KERNELVERSION defined
+# 
+libc6-udeb
+cdebconf-udeb
+di-utils
+hw-detect
+rootskel
+cdrom-detect
+
+apt-cdrom-setup
+apt-mirror-setup
+apt-setup-udeb
+base-installer
+bogl-bterm-udeb
+bootstrap-base
+brltty-udeb
+ca-certificates-udeb
+cdebconf-newt-entropy
+cdebconf-newt-terminal
+cdebconf-newt-udeb
+cdebconf-priority
+cdebconf-text-entropy
+cdebconf-text-udeb
+cdrom-checker
+cdrom-detect
+choose-init
+console-setup-pc-ekmap
+console-setup-udeb
+console-setup-linux-fonts-udeb
+di-utils-exit-installer
+di-utils-reboot
+di-utils-shell
+eject-udeb
+env-preseed
+espeakup-udeb
+f2fs-tools-udeb
+fdisk-udeb
+file-preseed
+finish-install
+gpgv-udeb
+haveged-udeb
+initrd-preseed
+installation-locale
+kbd-chooser
+kmod-udeb
+libfribidi0-udeb
+libkmod2
+libpcre3-udeb
+libelogind0
+libtinfo6-udeb
+#lilo-installer
+load-cdrom
+localechooser
+lowmemcheck
+main-menu
+#mbr-udeb
+mountmedia
+nano-udeb
+netcfg
+nobootloader
+openssh-client-udeb
+open-iscsi-udeb
+pcmciautils-udeb
+pkgsel
+rescue-mode
+rfkill
+save-logs
+screen-udeb
+tzsetup-udeb
+wget-udeb
+kernel-image-${KERNELVERSION}-di
+#acpi-modules-${KERNELVERSION}-di
+ata-modules-${KERNELVERSION}-di
+btrfs-modules-${KERNELVERSION}-di
+cdrom-core-modules-${KERNELVERSION}-di
+#compress-modules-${KERNELVERSION}-di
+crc-modules-${KERNELVERSION}-di
+crypto-dm-modules-${KERNELVERSION}-di
+crypto-modules-${KERNELVERSION}-di
+efi-modules-${KERNELVERSION}-di
+event-modules-${KERNELVERSION}-di
+ext4-modules-${KERNELVERSION}-di
+f2fs-modules-${KERNELVERSION}-di
+fat-modules-${KERNELVERSION}-di
+fb-modules-${KERNELVERSION}-di
+#firewire-core-modules-${KERNELVERSION}-di
+fuse-modules-${KERNELVERSION}-di
+i2c-modules-${KERNELVERSION}-di
+input-modules-${KERNELVERSION}-di
+isofs-modules-${KERNELVERSION}-di
+jfs-modules-${KERNELVERSION}-di
+loop-modules-${KERNELVERSION}-di
+md-modules-${KERNELVERSION}-di
+#mmc-core-modules-${KERNELVERSION}-di
+mmc-modules-${KERNELVERSION}-di
+#mouse-modules-${KERNELVERSION}-di
+mtd-core-modules-${KERNELVERSION}-di
+multipath-modules-${KERNELVERSION}-di
+nbd-modules-${KERNELVERSION}-di
+nic-modules-${KERNELVERSION}-di
+#nic-pcmcia-modules-${KERNELVERSION}-di
+nic-shared-modules-${KERNELVERSION}-di
+nic-usb-modules-${KERNELVERSION}-di
+nic-wireless-modules-${KERNELVERSION}-di
+#pata-modules-${KERNELVERSION}-di
+#pcmcia-modules-${KERNELVERSION}-di
+#pcmcia-storage-modules-${KERNELVERSION}-di
+ppp-modules-${KERNELVERSION}-di
+sata-modules-${KERNELVERSION}-di
+scsi-core-modules-${KERNELVERSION}-di
+scsi-modules-${KERNELVERSION}-di
+scsi-nic-modules-${KERNELVERSION}-di
+#serial-modules-${KERNELVERSION}-di
+sound-modules-${KERNELVERSION}-di
+speakup-modules-${KERNELVERSION}-di
+squashfs-modules-${KERNELVERSION}-di
+udf-modules-${KERNELVERSION}-di
+uinput-modules-${KERNELVERSION}-di
+usb-modules-${KERNELVERSION}-di
+usb-serial-modules-${KERNELVERSION}-di
+usb-storage-modules-${KERNELVERSION}-di
+xfs-modules-${KERNELVERSION}-di