]> git.sesse.net Git - debian-xu4/blob - mkimage.sh
Support building boot images for eMMC devices.
[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] 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" ]; then
52         echo "Card type must be 'sd' or 'mmc'."
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 # Partition the device.
71 parted ${DEVICE} mklabel msdos
72 parted ${DEVICE} mkpart primary fat32 2MB $(( BOOTPART_MB + 2 ))MB
73 parted ${DEVICE} set 1 boot on
74 parted ${DEVICE} mkpart primary ext2 $(( BOOTPART_MB + 2))MB 100%
75
76 # Figure out if the partitions are of type ${DEVICE}1 or ${DEVICE}p1.
77 if [ -b "${DEVICE}1" ]; then
78         DEVICE_STEM=${DEVICE}
79 elif [ -b "${DEVICE}p1" ]; then
80         DEVICE_STEM=${DEVICE}p
81 else
82         echo "Could not find device files for partitions of ${DEVICE}. Exiting."
83         exit 1
84 fi
85
86 # Put the different stages of U-Boot into the right place.
87 # The offsets come from /usr/share/doc/u-boot-exynos/README.odroid.gz.
88 if [ "$TYPE" = "sd" ]; then
89         UBOOT_DEVICE=${DEVICE}
90         UBOOT_OFFSET=1
91 else
92         UBOOT_DEVICE=${DEVICE}boot0
93         UBOOT_OFFSET=0
94 fi
95 dd if=u-boot/sd_fuse/hardkernel_1mb_uboot/bl1.bin.hardkernel of=${UBOOT_DEVICE} seek=${UBOOT_OFFSET} conv=sync
96 dd if=u-boot/sd_fuse/hardkernel_1mb_uboot/bl2.bin.hardkernel.1mb_uboot of=${UBOOT_DEVICE} seek=$((UBOOT_OFFSET + 30)) conv=sync
97 dd if=/usr/lib/u-boot/odroid-xu3/u-boot-dtb.bin of=${UBOOT_DEVICE} seek=$((UBOOT_OFFSET + 62)) conv=sync
98 dd if=u-boot/sd_fuse/hardkernel_1mb_uboot/tzsw.bin.hardkernel of=${UBOOT_DEVICE} seek=$((UBOOT_OFFSET + 2110)) conv=sync
99
100 # Clear out the environment.
101 dd if=/dev/zero of=${DEVICE} seek=2560 count=32 bs=512 conv=sync
102
103 # Create a /boot partition. Strictly speaking, almost everything could be loaded
104 # from ext4, but using FAT is somehow traditional and less likely to be broken
105 # at any given time. (It doesn't support symlinks, though, which breaks flash-kernel,
106 # but we don't use that anyway.)
107 BOOT_PART=${DEVICE_STEM}1
108 mkfs.vfat -F 32 ${BOOT_PART}
109
110 # Put an LVM on the other partition; it's easier to deal with when expanding
111 # partitions or otherwise moving them around.
112 vgchange -a n odroid || true  # Could be left around from a previous copy of the partition.
113 pvcreate -ff ${DEVICE_STEM}2
114 vgcreate odroid ${DEVICE_STEM}2
115 lvcreate -l 100%FREE -n root odroid
116
117 # And the main filesystem.
118 mkfs.ext4 /dev/odroid/root
119
120 # Mount the filesystem and debootstrap into it.
121 # isc-dhcp-client is, of course, not necessarily required, especially as
122 # systemd-networkd is included and can do networking just fine, but most people
123 # will probably find it very frustrating to install packages without it.
124 mkdir -p /mnt/xu4/
125 mount /dev/odroid/root /mnt/xu4
126 mkdir /mnt/xu4/boot/
127 mount ${BOOT_PART} /mnt/xu4/boot
128 debootstrap --include=linux-image-armmp-lpae,grub-efi-arm,lvm2,isc-dhcp-client --foreign --arch armhf ${SUITE} /mnt/xu4 "$@"
129
130 # Run the second stage debootstrap under qemu (via binfmt_misc).
131 cp /usr/bin/qemu-arm-static /mnt/xu4/usr/bin/
132 DEBIAN_FRONTEND=noninteractive DEBCONF_NONINTERACTIVE_SEEN=true LC_ALL=C LANGUAGE=C LANG=C chroot /mnt/xu4 /debootstrap/debootstrap --second-stage
133 DEBIAN_FRONTEND=noninteractive DEBCONF_NONINTERACTIVE_SEEN=true LC_ALL=C LANGUAGE=C LANG=C chroot /mnt/xu4 dpkg --configure -a
134
135 # Enable security updates, and apply any that might be waiting.
136 if [ "$SUITE" != "unstable" ] && [ "$SUITE" != "sid" ]; then
137         echo "deb http://security.debian.org $SUITE/updates main" >> /mnt/xu4/etc/apt/sources.list
138         DEBIAN_FRONTEND=noninteractive DEBCONF_NONINTERACTIVE_SEEN=true LC_ALL=C LANGUAGE=C LANG=C chroot /mnt/xu4 apt update
139         DEBIAN_FRONTEND=noninteractive DEBCONF_NONINTERACTIVE_SEEN=true LC_ALL=C LANGUAGE=C LANG=C chroot /mnt/xu4 apt dist-upgrade
140 fi
141
142 # Create an fstab (this is normally done by partconf, in d-i).
143 BOOT_UUID=$( blkid -s UUID -o value ${BOOT_PART} )
144 cat <<EOF > /mnt/xu4/etc/fstab
145 # /etc/fstab: static file system information.
146 #
147 # Use 'blkid' to print the universally unique identifier for a
148 # device; this may be used with UUID= as a more robust way to name devices
149 # that works even if disks are added and removed. See fstab(5).
150 #
151 # <file system> <mount point>   <type>  <options>       <dump>  <pass>
152 /dev/odroid/root / ext4 errors=remount-ro 0 1
153 UUID=${BOOT_UUID} /boot vfat defaults 0 2
154 EOF
155
156 # Set a hostname.
157 echo odroid > /mnt/xu4/etc/hostname
158
159 # Work around Debian bug #824391.
160 echo ttySAC2 >> /mnt/xu4/etc/securetty
161
162 # Install GRUB, chainloaded from U-Boot via UEFI.
163 mount --bind /dev /mnt/xu4/dev
164 mount --bind /proc /mnt/xu4/proc
165 chroot /mnt/xu4 /usr/sbin/grub-install --removable --target=arm-efi --boot-directory=/boot --efi-directory=/boot
166
167 # Get the device tree in place (we need it to load GRUB).
168 # flash-kernel can do this (if you also have u-boot-tools installed),
169 # but it also includes its own boot script (which has higher priority than
170 # GRUB) and just seems to lock up.
171 cp $( find /mnt/xu4 -name exynos5422-odroidxu4.dtb ) /mnt/xu4/boot/
172
173 # update-grub does not add “devicetree” statements for the
174 # each kernel (not that it's copied from /usr/lib without
175 # flash-kernel anyway), so we need to explicitly load it
176 # ourselves. See Debian bug #824399.
177 cat <<EOF > /mnt/xu4/etc/grub.d/25_devicetree
178 #! /bin/sh
179 set -e
180
181 # Hack added by prepare.sh when building the root image,
182 # to work around Debian bug #824399.
183 echo "echo 'Loading device tree ...'"
184 echo "devicetree /exynos5422-odroidxu4.dtb"
185 EOF
186 chmod 0755 /mnt/xu4/etc/grub.d/25_devicetree
187
188 # Work around Debian bug #823552.
189 sed -i 's/\(GRUB_CMDLINE_LINUX_DEFAULT=".*\)"/\1 loglevel=4"/' /mnt/xu4/etc/default/grub 
190
191 # Now we can create the GRUB boot menu.
192 chroot /mnt/xu4 /usr/sbin/update-grub
193
194 # Set the root password. (It should be okay to have a dumb one as default,
195 # since there's no ssh by default. Yet, it would be nice to have a way
196 # to ask on first boot, or better yet, invoke debian-installer after boot.)
197 echo root:odroid | chroot /mnt/xu4 /usr/sbin/chpasswd
198
199 # Zero any unused blocks on /boot, for better packing if we are to compress the
200 # filesystem and publish it somewhere. (See below for the root device.)
201 echo 'Please ignore the following error about full disk.'
202 dd if=/dev/zero of=/mnt/xu4/boot/zerofill bs=1M || true
203 rm -f /mnt/xu4/boot/zerofill
204
205 # All done, clean up.
206 rm /mnt/xu4/usr/bin/qemu-arm-static
207 umount /mnt/xu4/dev
208 umount /mnt/xu4/proc
209 umount /mnt/xu4/boot
210 umount /mnt/xu4
211
212 # The root file system is ext4, so we can use zerofree, which is
213 # supposedly faster than dd-ing a zero file onto it.
214 zerofree -v /dev/odroid/root
215
216 vgchange -a n odroid