set -e
-### Step 1. Download original .deb file from the source
-REPO="deb.devuan.org/merged"
-SUITE="daedalus"
-SECTION="main"
+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_excalibur_main
+ #deb.devuan.org/merged_ceres_main
+)
ARCH="amd64"
+MBR=dos # gpt
+# silly-links setup
+LIB=/usr/lib
+BIN=/usr/bin
-PKGFILE=${REPO//\//_}_${SUITE}_${SECTION}_binary-${ARCH}_Packages
-if [ ! -r $PKGFILE ] ; then
- wget -O - http://$REPO/dists/$SUITE/$SECTION/binary-$ARCH/Packages.xz | \
- xzcat - > ${PKGFILE}
-fi
+: > $MAPFILE
+: > $DEPFILE
-# Reduce that Packages file into two maps for finding filename and depends
-echo "# Creating mapdepends.txt and mapfile.txt"
-awk '
-BEGIN { print "###" > "mapdepends.txt"; print "###" > "mapfile.txt"; }
+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=="Depends:" {print P,$2 >> "mapdepends.txt";next }
-$1=="Filename:" {print P,$2 >> "mapfile.txt";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
-# Function to find the filename (or an map file) for a given package
+# Append any additional saved deb files
+for DEB in $(ls save/*.deb 2>/dev/null); do
+ P="${DEB%%_*}"
+ P="${P#save/}"
+ echo "$P save/$DEB" >> $MAPFILE
+ dpkg-deb -f "$DEB" Depends Pre-Depends | sed "s/^/$P/" >> $DEPFILE
+done
+
+# Function to find the filename for a given package in the given mapfile
maplookup() {
- awk -v P="$1" '$1==P {$1="" ;print; exit}' ${2-mapfile.txt} | \
- sed 's/ //'
+ local FN=${3:-tail}
+ echo "maplookup $1 $2" >&2
+ grep "^$1 " $2 >&2
+ grep "^$1 " $2 | $FN -n 1 | sed 's/[^ ]* //'
+}
+
+# Function to clean up a "depends' line
+depclean() {
+ sed 's/^[^:]*: //;s/([^)]*)//g;s/|[^,]*/ /g;s/,/ /g;s/\s\+/ /g'
+}
+
+# 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
}
# Function to download a deb file and return its name
debfile() {
- local F="$(maplookup $1 mapfile.txt)"
- if [ ! -e "${F##*/}" ] ; then
- wget "http://$REPO/$F" || return 1
+ 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
fi
- echo "${F##*/}"
+ echo "save/$P"
}
# Function to extract from a deb without executing and pre/post scripts
}
# Deteremine which kernel to use; this is
-echo -n "# Determining kernel: "
-KERNEL="$(maplookup linux-image-amd64 mapdepends.txt | \
+echo "# Determine kernel"
+KERNEL="$(maplookup linux-image-amd64 $DEPFILE head | \
sed 's/.*\(linux-image[^ ]*\).*/\1/')"
-echo $KERNEL
+echo "# ... $KERNEL"
-### Step 2. Create and populate the initrd, and packit up.
+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 -r initrd
+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
+}
+
+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 "# Install busybox, and fluff it up"
-fakechroot fakeroot \
-dpkg --log=dpkg.log --root=initrd -i $(debfile busybox-static)
-for L in $(initrd/bin/busybox --listfull) ; do
- mkdir -p $(dirname initrd/$L)
+echo "# Extract static busybox, and fluff it up for more utilities"
+mkdir -p initrd
+debextract initrd $(debfile busybox-static head)
+if [ "$BIN" = "/usr/bin" ] ; then
+ for D in bin sbin lib ; do
+ mkdir -p initrd/usr/$D
+ ln -s usr/$D initrd/$D
+ done
+else
+ for D in bin sbin lib ; do
+ mkdir -p initrd/$D initrd/usr/$D
+ done
+fi
+for L in $(initrd$BIN/busybox --listfull) ; do
+ [ -e "initrd/$L" ] && continue
case "$L" in
- bin/busybox) : ;;
+ bin/busybox) [ -e initrd/$L ] || ln -s usr/$L initrd/$L ;;
usr/*) ln -s ../../bin/busybox initrd/$L ;;
sbin/*) ln -s ../bin/busybox initrd/$L ;;
bin/*) ln -s busybox initrd/$L ;;
echo "# .. and syslinux stuff if needed"
if [ ! -d kernel ] ; then
mkdir kernel
- debextract kernel $(debfile $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 ext4 isofs
+ crc32-pclmul crc32c_generic crc16
+ #crct10dif_common crc-t10dif crc64 crc64-rocksoft t10-pi
+ sd_mod sg nls_cp437 nls_ascii fat vfat jbd2 mbcache 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)
+ km=$(find kernel$LIB/modules -name "$m.ko*")
if [ -z "$km" ] ; then
echo "Missing module $m"
continue
fi
im=initrd/${km#kernel/}
+ im=${im%.xz}
MOODLES+=" $B/$im"
mkdir -p $(dirname $im)
- cp -n $km $im
+ if [ -z "${km##*xz}" ] ; then
+ xzcat $km > $im
+ else
+ cp -n $km $im
+ fi
done
V=${KERNEL#linux-image-}
-mkdir -p initrd/boot initrd/lib/modules/$V
+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
+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 -o initrd $V
echo "# setup a scripted init. The kernel runs this via the #! interpreter"
rm -f initrd/sbin/init # just in case
-cat <<EOF > initrd/init
-#!/bin/sh
-echo
-echo
-echo "Hi there, tiniest lover!"
-
-mkdir /proc
-mount -t proc proc /proc
-mount -t devtmpfs devtmpfs /dev
-mkdir /dev/pts
-mount -t devpts devpts /dev/pts
-mkdir /sys
-mount -t sysfs sysfs /sys
-$(for m in ${MODULES[@]} ; do echo modprobe $m ; done)
-exec /bin/sh
-EOF
+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
-### Step 3. create a 32 Mb fat filesystem with bios and UEFI boot
+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 dos partition table with a first partition marked as EFI
+EFILDR="kernel/usr/lib/SYSLINUX.EFI/efi64/syslinux.efi"
+EFIMODS="kernel/usr/lib/syslinux/modules/efi64/*"
+LCYMODS="kernel/usr/lib/syslinux/modules/bios/*"
+VMLINUZ="kernel/boot/vm*"
+
+SIZE=$(du -c $EFILDR $EFIMODS $LCYMODS $VMLINUZ \
+ initrd.gz splash.png syslinux-legacy.cfg \
+ muffin.lua syslinux-uefi.cfg | sed '$!d;s|\s.*||' )
+echo "du = $SIZE kb"
+SIZE=$(( ( ( 2 * SIZE + 4096 ) / 2048 ) * 2048 ))
+echo "SIZE = $SIZE sectors"
+
+# Prepare a gpt/dos partition table with a first partition marked as EFI
sfdisk bootimage.raw <<EOF
-2048 32767 U *
+label: $MBR
+
+2048 $SIZE U *
- - L
EOF
-# Add a fat filesystem at 2048 61440
-mkfs.fat -n TINIEST --offset 2048 -F 16 bootimage.raw
+# Add a fat filesystem at 2048
+mkfs.fat -n TINIEST --offset 2048 bootimage.raw
IMG="-i bootimage.raw@@$((2048*512))"
-# Add an ext2 filesystem at offset 61440*512
+# Add an ext2 filesystem at offset
# Copy initrd.gz and kernel into the fat filesystem root
-mke2fs -E offset=$((61440*512)) -F bootimage.raw
-
-mcopy $IMG initrd.gz ::
-mcopy $IMG kernel/boot/vm* ::/vmlinuz
-mcopy $IMG bootmenu.cfg ::/
-mcopy $IMG splash.png ::/
-
-echo "# Set up legacy boot"
-cat <<EOF > syslinux-legacy.cfg
-path /boot/syslinux/bios
-include /bootmenu.cfg
-EOF
+PART2=( $(fdisk -lo START,SECTORS bootimage.raw | sed '$!d') )
+EXT=offset=$(( ${PART2[0]} * 512 ))
+echo mke2fs -t ext4 -E $EXT -F bootimage.raw $(( ${PART2[1]} / 2 ))
+mke2fs -t ext4 -E $EXT -F bootimage.raw $(( ${PART2[1]} / 2 ))
+# Note that this is unsafe copying that might spill outside the partition
+mmd $IMG ::/EFI
+mmd $IMG ::/EFI/BOOT
mmd $IMG ::/boot
mmd $IMG ::/boot/syslinux
mmd $IMG ::/boot/syslinux/bios
-mcopy $IMG \
- kernel/usr/lib/syslinux/modules/bios/* ::/boot/syslinux/bios
-mcopy $IMG syslinux-legacy.cfg ::/syslinux.cfg
-echo "# Set up UEFI boot"
-cat <<EOF > syslinux-uefi.cfg
-path /EFI/BOOT/efi64
-include /bootmenu.cfg
-EOF
+mcopy $IMG initrd.gz ::/
+mcopy $IMG $VMLINUZ ::/vmlinuz
+mcopy $IMG splash.png ::/
+mcopy $IMG syslinux-legacy.cfg ::/syslinux.cfg
-mmd $IMG ::/EFI
-mmd $IMG ::/EFI/BOOT
-mmd $IMG ::/EFI/BOOT/efi64
-mcopy $IMG kernel/usr/lib/SYSLINUX.EFI/efi64/syslinux.efi \
- ::/EFI/BOOT/bootx64.efi
-mcopy $IMG \
- kernel/usr/lib/syslinux/modules/efi64/* ::/EFI/BOOT
-mcopy $IMG syslinux-uefi.cfg ::/EFI/BOOT/syslx64.cfg
+mcopy $IMG muffin.lua ::/EFI/BOOT/muffin.lua
+mcopy $IMG $EFILDR ::/EFI/BOOT/bootx64.efi
+mcopy $IMG syslinux-uefi.cfg ::/EFI/BOOT/syslinux.cfg
+mcopy $IMG $EFIMODS ::/EFI/BOOT/
+mcopy $IMG $LCYMODS ::/boot/syslinux/bios/
syslinux --install --offset=${IMG#*@@} bootimage.raw
+
+case "$MBR" in
+ dos) MBRBIN=mbr.bin ;;
+ gpt)
+ MBRBIN=gptmbr.bin
+ sfdisk --relocate gpt-bak-std bootimage.raw
+ sfdisk -f --part-attrs bootimage.raw 1 LegacyBIOSBootable
+ ;;
+ *) exit 1 ;;
+esac
dd conv=notrunc of=bootimage.raw bs=440 count=1 \
- if=kernel/usr/lib/syslinux/mbr/mbr.bin
+ if=kernel/usr/lib/syslinux/mbr/$MBRBIN
+
+echo "# populate the extra partition"
+if [ -d extra ] ; then
+ mkdir -p X
+ fuse2fs -o fakeroot -o$EXT bootimage.raw X
+ rsync -r extra/. X/.
+ umount X
+fi
exit