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