Fix mapdepends to full dependency lines and also include Pre-Depends.
[rrq/tiniest.git] / mkit.sh
1 #!/bin/bash
2 #
3 # A script to prepare the tiniest "linux system". It's a kernel and an
4 # initrd within a FAT with a syslinux boot loader. The initrd contains
5 # a fully expanded busybox and uses /bin/sh as its init.
6 #
7 # This script creates and packs that initrd, as well as the whole,
8 # boot image. 
9
10 set -e
11
12 ### Step 1. Download original .deb file from the source
13 REPO="deb.devuan.org/merged"
14 SUITE="daedalus"
15 SECTION="main"
16 ARCH="amd64"
17
18 PKGFILE=${REPO//\//_}_${SUITE}_${SECTION}_binary-${ARCH}_Packages
19 if [ ! -r $PKGFILE ] ; then
20     wget -O - http://$REPO/dists/$SUITE/$SECTION/binary-$ARCH/Packages.xz | \
21         xzcat - > ${PKGFILE}
22 fi
23
24 # Reduce that Packages file into two maps for finding filename and depends
25 echo "# Creating mapdepends.txt and mapfile.txt"
26 awk '
27 BEGIN { print "###" > "mapdepends.txt"; print "###" > "mapfile.txt"; }
28 $1=="Package:" {P=$2; next}
29 $1=="Pre-Depends:" {print P,$0 >> "mapdepends.txt";next }
30 $1=="Depends:" {print P,$0 >> "mapdepends.txt";next }
31 $1=="Filename:" {print P,$2 >> "mapfile.txt";next }
32 ' ${PKGFILE}
33
34 # Function to find the filename (or an map file) for a given package
35 maplookup() {
36     awk -v P="$1" '$1==P {$1="" ;print; exit}' ${2-mapfile.txt} | \
37         sed 's/ //'
38 }
39
40 # Function to download a deb file and return its name
41 debfile() {
42     local F="$(maplookup $1 mapfile.txt)"
43     if [ ! -e "${F##*/}" ] ; then
44         wget "http://$REPO/$F" || return 1
45     fi
46     echo "${F##*/}"
47 }
48
49 # Function to extract from a deb without executing and pre/post scripts
50 # $1 = rootfs $2 = package
51 debextract() {
52     ar p $2 data.tar.xz | tar xJf - -C $1
53 }
54
55 # Deteremine which kernel to use; this is
56 echo -n "# Determining kernel: "
57 KERNEL="$(maplookup linux-image-amd64 mapdepends.txt | \
58                     sed 's/.*\(linux-image[^ ]*\).*/\1/')"
59 echo $KERNEL
60
61 ### Step 2. Create and populate the initrd, and packit up.
62 # The initrd contains only a few kernel modules for coping with a
63 # later pivoting onto a "full" filesystem.
64
65 echo "# Create initrd filesystem"
66 rm -fr initrd
67
68 echo "# Extract busybox, and fluff it up"
69 mkdir initrd
70 debextract initrd $(debfile busybox-static)
71 for L in $(initrd/bin/busybox --listfull) ; do
72     mkdir -p $(dirname initrd/$L)
73     case "$L" in
74         bin/busybox) : ;;
75         usr/*) ln -s ../../bin/busybox initrd/$L ;;
76         sbin/*) ln -s ../bin/busybox initrd/$L ;;
77         bin/*)  ln -s busybox initrd/$L ;;
78         linuxrc) ln -s bin/busybox initrd/$L ;;
79     esac
80 done
81
82 echo "# Extract the kernel package ($KERNEL)"
83 echo "# .. and syslinux stuff if needed"
84 if [ ! -d kernel ] ; then
85     mkdir kernel
86     debextract kernel $(debfile $KERNEL)
87     debextract kernel $(debfile syslinux)
88     debextract kernel $(debfile syslinux-common)
89     debextract kernel $(debfile syslinux-efi)
90     debextract kernel $(debfile syslinux-utils)
91     debextract kernel $(debfile isolinux)
92 fi
93
94 echo "# Include some kernel modules in the initrd"
95 MODULES=(
96     # disk
97     scsi_common scsi_mod libata ata_piix ata_generic cdrom sr_mod
98     crc32-pclmul crct10dif_common crc-t10dif crc64 crc64-rocksoft
99     t10-pi sd_mod sg
100     nls_cp437 nls_ascii fat vfat
101     crc32c_generic jbd2 mbcache crc16 ext4
102     isofs
103     overlay
104     # input
105     psmouse evdev
106     # network
107     e1000
108 )
109 MOODLES=""
110 B=$(pwd)
111 for m in ${MODULES[@]} ; do
112     km=$(find kernel/lib/modules -name $m.ko)
113     if [ -z "$km" ] ; then
114         echo "Missing module $m"
115         continue
116     fi
117     im=initrd/${km#kernel/}
118     MOODLES+=" $B/$im"
119     mkdir -p $(dirname $im)
120     cp -n $km $im
121 done
122 V=${KERNEL#linux-image-}
123 mkdir -p initrd/boot initrd/lib/modules/$V
124 cp kernel/boot/System.map-$V initrd/
125 cp kernel/lib/modules/$V/modules.order initrd/lib/modules/$V/
126 cp kernel/lib/modules/$V/modules.builtin initrd/lib/modules/$V/
127 depmod -F initrd/System.map-$V -b initrd $V $MOODLES
128
129 echo "# setup a scripted init. The kernel runs this via the #! interpreter"
130 rm -f initrd/sbin/init # just in case
131 cat <<EOF > initrd/init
132 #!/bin/sh
133 echo 
134 echo 
135 echo "Hi there, tiniest lover!"
136
137 mkdir /proc
138 mount -t proc proc /proc
139 mount -t devtmpfs devtmpfs /dev
140 mkdir /dev/pts
141 mount -t devpts devpts /dev/pts
142 mkdir /sys
143 mount -t sysfs sysfs /sys
144 $(for m in ${MODULES[@]} ; do echo modprobe $m ; done)
145 exec /bin/sh
146 EOF
147 chmod a+x initrd/init
148
149 echo "# Now pack up that initrd as initrd.gz"
150 ( cd initrd ; find . | fakeroot cpio -H newc -o | gzip ) >initrd.gz
151
152 ### Step 3. create a 32  Mb fat filesystem with bios and UEFI boot
153 rm -f bootimage.raw
154 dd if=/dev/zero of=bootimage.raw bs=32M count=1
155
156 # Prepare a dos partition table with a first partition marked as EFI
157 sfdisk bootimage.raw <<EOF
158 2048 32767 U *
159 - - L
160 EOF
161
162 # Add a fat filesystem at 2048 61440
163 mkfs.fat -n TINIEST --offset 2048 -F 16 bootimage.raw
164 IMG="-i bootimage.raw@@$((2048*512))"
165
166 # Add an ext2 filesystem at offset 61440*512
167 # Copy initrd.gz and kernel into the fat filesystem root
168 mke2fs -t ext4 -E offset=$((34816*512)) -F bootimage.raw
169
170 mcopy $IMG initrd.gz ::
171 mcopy $IMG kernel/boot/vm* ::/vmlinuz
172 mcopy $IMG bootmenu.cfg ::/
173 mcopy $IMG splash.png ::/
174
175 echo "# Set up legacy boot"
176 cat <<EOF > syslinux-legacy.cfg
177 path /boot/syslinux/bios
178 include /bootmenu.cfg
179 EOF
180
181 mmd $IMG ::/boot
182 mmd $IMG ::/boot/syslinux
183 mmd $IMG ::/boot/syslinux/bios
184 mcopy $IMG \
185       kernel/usr/lib/syslinux/modules/bios/* ::/boot/syslinux/bios
186 mcopy $IMG syslinux-legacy.cfg ::/syslinux.cfg
187
188 echo "# Set up UEFI boot"
189 cat <<EOF > syslinux-uefi.cfg
190 path /EFI/BOOT/efi64
191 include /bootmenu.cfg
192 EOF
193
194 mmd $IMG ::/EFI
195 mmd $IMG ::/EFI/BOOT
196 mmd $IMG ::/EFI/BOOT/efi64
197 mcopy $IMG kernel/usr/lib/SYSLINUX.EFI/efi64/syslinux.efi \
198       ::/EFI/BOOT/bootx64.efi
199 mcopy $IMG \
200       kernel/usr/lib/syslinux/modules/efi64/* ::/EFI/BOOT
201 mcopy $IMG syslinux-uefi.cfg ::/EFI/BOOT/syslx64.cfg
202
203 syslinux --install --offset=${IMG#*@@} bootimage.raw
204 dd conv=notrunc of=bootimage.raw bs=440 count=1 \
205    if=kernel/usr/lib/syslinux/mbr/mbr.bin
206
207 exit