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