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