]> git.sesse.net Git - debian-xu4/blob - mkimage.sh
Drop the /etc/default/grub hacks now that Debian ships a kernel with my deferred...
[debian-xu4] / mkimage.sh
1 #! /bin/bash
2
3 # Install a bog-standard Debian bootable for ODROID XU3/XU4.
4 #
5 # Note: You will need u-boot-exynos >= 2016.05~rc3+dfsg1-1,
6 # which at the time of writing is in experimental (it will
7 # probably eventually hit stretch).
8 #
9 # Beware: This will ERASE ALL DATA on the target SD card
10 # or MMC partition.
11 #
12 #
13 # Copyright 2016 Steinar H. Gunderson <steinar+odroid@gunderson.no>.
14 # Licensed under the GNU GPL, v2 or (at your option) any later version.
15
16 set -e
17
18 DEVICE=
19 BOOTPART_MB=256
20 SUITE=stretch
21 TYPE=sd
22
23 while getopts "b:s:t:" opt; do
24         case $opt in
25                 b)
26                         BOOTPART_MB=$OPTARG
27                         ;;
28                 s)
29                         # Sorry, jessie won't work; the kernel doesn't support XU3/XU4.
30                         SUITE=$OPTARG
31                         ;;
32                 t)
33                         TYPE=$OPTARG
34                         ;;
35                 :)
36                         echo "Option -$OPTARG requires an argument."
37                         exit 1
38                         ;;
39         esac
40 done
41 shift $((OPTIND - 1))
42
43 DEVICE=$1
44 if [ ! -b "$DEVICE" ]; then
45         echo "Usage: $0 [-b BOOTPARTITION_SIZE] [-s SUITE] [-t sd|mmc|mmcbootonly] DEVICE [OTHER_DEBOOTSTRAP_ARGS...]"
46         echo "DEVICE is an SD card device, e.g. /dev/sdb."
47         exit 1
48 fi
49 shift
50
51 if [ "$TYPE" != "sd" ] && [ "$TYPE" != "mmc" ] && [ "$TYPE" != "mmcbootonly" ]; then
52         echo "Card type must be 'sd', 'mmc' or 'mmcbootonly'."
53         exit 1
54 fi
55
56 set -x
57
58 # Prerequisites.
59 dpkg --add-architecture armhf
60 apt update
61 apt install git parted dosfstools e2fsprogs binfmt-support qemu qemu-user-static debootstrap zerofree u-boot-exynos:armhf
62
63 # Get first stages of bootloader. (BL1 must be signed by Hardkernel,
64 # and TZSW comes without source anyway, so we can't build these ourselves)
65 # This is the only part that doesn't strictly need root.
66 if [ ! -d u-boot ]; then
67         git clone https://github.com/hardkernel/u-boot -b odroidxu3-v2012.07
68 fi
69
70 if [ "$TYPE" != "mmcbootonly" ]; then
71         # Partition the device.
72         parted ${DEVICE} mklabel msdos
73         parted ${DEVICE} mkpart primary fat32 2MB $(( BOOTPART_MB + 2 ))MB
74         parted ${DEVICE} set 1 boot on
75         parted ${DEVICE} mkpart primary ext2 $(( BOOTPART_MB + 2))MB 100%
76
77         # Figure out if the partitions are of type ${DEVICE}1 or ${DEVICE}p1.
78         if [ -b "${DEVICE}1" ]; then
79                 DEVICE_STEM=${DEVICE}
80         elif [ -b "${DEVICE}p1" ]; then
81                 DEVICE_STEM=${DEVICE}p
82         else
83                 echo "Could not find device files for partitions of ${DEVICE}. Exiting."
84                 exit 1
85         fi
86 fi
87
88 # Put the different stages of U-Boot into the right place.
89 # The offsets come from /usr/share/doc/u-boot-exynos/README.odroid.gz.
90 if [ "$TYPE" = "sd" ]; then
91         UBOOT_DEVICE=${DEVICE}
92         UBOOT_OFFSET=1
93 elif [ "$TYPE" = "mmcbootonly" ]; then
94         UBOOT_DEVICE=${DEVICE}
95         UBOOT_OFFSET=0
96 else
97         UBOOT_DEVICE=${DEVICE}boot0
98         UBOOT_OFFSET=0
99 fi
100 dd if=u-boot/sd_fuse/hardkernel_1mb_uboot/bl1.bin.hardkernel of=${UBOOT_DEVICE} seek=${UBOOT_OFFSET} conv=sync
101 dd if=u-boot/sd_fuse/hardkernel_1mb_uboot/bl2.bin.hardkernel.1mb_uboot of=${UBOOT_DEVICE} seek=$((UBOOT_OFFSET + 30)) conv=sync
102 dd if=/usr/lib/u-boot/odroid-xu3/u-boot-dtb.bin of=${UBOOT_DEVICE} seek=$((UBOOT_OFFSET + 62)) conv=sync
103 dd if=u-boot/sd_fuse/hardkernel_1mb_uboot/tzsw.bin.hardkernel of=${UBOOT_DEVICE} seek=$((UBOOT_OFFSET + 2110)) conv=sync
104
105 # Clear out the environment.
106 dd if=/dev/zero of=${DEVICE} seek=2560 count=32 bs=512 conv=sync
107
108 if [ "$TYPE" = "mmcbootonly" ]; then
109         # The user asked us to only create the MMC boot partition, so exit.
110         exit 0
111 fi
112
113 # Create a /boot partition. Strictly speaking, almost everything could be loaded
114 # from ext4, but using FAT is somehow traditional and less likely to be broken
115 # at any given time. (It doesn't support symlinks, though, which breaks flash-kernel,
116 # but we don't use that anyway.)
117 BOOT_PART=${DEVICE_STEM}1
118 mkfs.vfat -F 32 ${BOOT_PART}
119
120 # Put an LVM on the other partition; it's easier to deal with when expanding
121 # partitions or otherwise moving them around.
122 vgchange -a n odroid || true  # Could be left around from a previous copy of the partition.
123 pvcreate -ff ${DEVICE_STEM}2
124 vgcreate odroid ${DEVICE_STEM}2
125 lvcreate -l 100%FREE -n root odroid
126
127 # And the main filesystem.
128 mkfs.ext4 /dev/odroid/root
129
130 # Mount the filesystem and debootstrap into it.
131 # isc-dhcp-client is, of course, not necessarily required, especially as
132 # systemd-networkd is included and can do networking just fine, but most people
133 # will probably find it very frustrating to install packages without it.
134 mkdir -p /mnt/xu4/
135 mount /dev/odroid/root /mnt/xu4
136 mkdir /mnt/xu4/boot/
137 mount ${BOOT_PART} /mnt/xu4/boot
138 debootstrap --include=linux-image-armmp-lpae,grub-efi-arm,lvm2,isc-dhcp-client --foreign --arch armhf ${SUITE} /mnt/xu4 "$@"
139
140 # Run the second stage debootstrap under qemu (via binfmt_misc).
141 cp /usr/bin/qemu-arm-static /mnt/xu4/usr/bin/
142 DEBIAN_FRONTEND=noninteractive DEBCONF_NONINTERACTIVE_SEEN=true LC_ALL=C LANGUAGE=C LANG=C chroot /mnt/xu4 /debootstrap/debootstrap --second-stage
143 DEBIAN_FRONTEND=noninteractive DEBCONF_NONINTERACTIVE_SEEN=true LC_ALL=C LANGUAGE=C LANG=C chroot /mnt/xu4 dpkg --configure -a
144
145 # Enable security updates, and apply any that might be waiting.
146 if [ "$SUITE" != "unstable" ] && [ "$SUITE" != "sid" ]; then
147         echo "deb http://security.debian.org $SUITE/updates main" >> /mnt/xu4/etc/apt/sources.list
148         DEBIAN_FRONTEND=noninteractive DEBCONF_NONINTERACTIVE_SEEN=true LC_ALL=C LANGUAGE=C LANG=C chroot /mnt/xu4 apt update
149         DEBIAN_FRONTEND=noninteractive DEBCONF_NONINTERACTIVE_SEEN=true LC_ALL=C LANGUAGE=C LANG=C chroot /mnt/xu4 apt dist-upgrade
150 fi
151
152 # Create an fstab (this is normally done by partconf, in d-i).
153 BOOT_UUID=$( blkid -s UUID -o value ${BOOT_PART} )
154 cat <<EOF > /mnt/xu4/etc/fstab
155 # /etc/fstab: static file system information.
156 #
157 # Use 'blkid' to print the universally unique identifier for a
158 # device; this may be used with UUID= as a more robust way to name devices
159 # that works even if disks are added and removed. See fstab(5).
160 #
161 # <file system> <mount point>   <type>  <options>       <dump>  <pass>
162 /dev/odroid/root / ext4 errors=remount-ro 0 1
163 UUID=${BOOT_UUID} /boot vfat defaults 0 2
164 EOF
165
166 # Set a hostname.
167 echo odroid > /mnt/xu4/etc/hostname
168
169 # Work around Debian bug #824391.
170 echo ttySAC2 >> /mnt/xu4/etc/securetty
171
172 # Work around Debian bug #825026.
173 echo ledtrig-heartbeat >> /mnt/xu4/etc/modules
174
175 # Install GRUB, chainloaded from U-Boot via UEFI.
176 mount --bind /dev /mnt/xu4/dev
177 mount --bind /proc /mnt/xu4/proc
178 chroot /mnt/xu4 /usr/sbin/grub-install --removable --target=arm-efi --boot-directory=/boot --efi-directory=/boot
179
180 # Get the device tree in place (we need it to load GRUB).
181 # flash-kernel can do this (if you also have u-boot-tools installed),
182 # but it also includes its own boot script (which has higher priority than
183 # GRUB) and just seems to lock up.
184 cp $( find /mnt/xu4 -name exynos5422-odroidxu4.dtb ) /mnt/xu4/boot/
185
186 # update-grub does not add “devicetree” statements for the
187 # each kernel (not that it's copied from /usr/lib without
188 # flash-kernel anyway), so we need to explicitly load it
189 # ourselves. See Debian bug #824399.
190 cat <<EOF > /mnt/xu4/etc/grub.d/25_devicetree
191 #! /bin/sh
192 set -e
193
194 # Hack added by mkimage.sh when building the root image,
195 # to work around Debian bug #824399.
196 echo "echo 'Loading device tree ...'"
197 echo "devicetree /exynos5422-odroidxu4.dtb"
198 EOF
199 chmod 0755 /mnt/xu4/etc/grub.d/25_devicetree
200
201 # Now we can create the GRUB boot menu.
202 chroot /mnt/xu4 /usr/sbin/update-grub
203
204 # Set the root password. (It should be okay to have a dumb one as default,
205 # since there's no ssh by default. Yet, it would be nice to have a way
206 # to ask on first boot, or better yet, invoke debian-installer after boot.)
207 echo root:odroid | chroot /mnt/xu4 /usr/sbin/chpasswd
208
209 # Zero any unused blocks on /boot, for better packing if we are to compress the
210 # filesystem and publish it somewhere. (See below for the root device.)
211 echo 'Please ignore the following error about full disk.'
212 dd if=/dev/zero of=/mnt/xu4/boot/zerofill bs=1M || true
213 rm -f /mnt/xu4/boot/zerofill
214
215 # All done, clean up.
216 rm /mnt/xu4/usr/bin/qemu-arm-static
217 umount /mnt/xu4/dev
218 umount /mnt/xu4/proc
219 umount /mnt/xu4/boot
220 umount /mnt/xu4
221
222 # The root file system is ext4, so we can use zerofree, which is
223 # supposedly faster than dd-ing a zero file onto it.
224 zerofree -v /dev/odroid/root
225
226 vgchange -a n odroid