1#! @bash@/bin/sh
2
3# This can end up being called disregarding the shebang.
4set -e
5
6shopt -s nullglob
7
8export PATH=/empty
9for i in @path@; do PATH=$PATH:$i/bin; done
10
11usage() {
12 echo "usage: $0 -c <path-to-default-configuration> [-d <boot-dir>]" >&2
13 exit 1
14}
15
16default= # Default configuration
17target=/boot # Target directory
18
19while getopts "c:d:" opt; do
20 case "$opt" in
21 c) default="$OPTARG" ;;
22 d) target="$OPTARG" ;;
23 \?) usage ;;
24 esac
25done
26
27echo "updating the boot generations directory..."
28
29mkdir -p $target/old
30
31# Convert a path to a file in the Nix store such as
32# /nix/store/<hash>-<name>/file to <hash>-<name>-<file>.
33cleanName() {
34 local path="$1"
35 echo "$path" | sed 's|^/nix/store/||' | sed 's|/|-|g'
36}
37
38# Copy a file from the Nix store to $target/kernels.
39declare -A filesCopied
40
41copyToKernelsDir() {
42 local src="$1"
43 local dst="$target/old/$(cleanName $src)"
44 # Don't copy the file if $dst already exists. This means that we
45 # have to create $dst atomically to prevent partially copied
46 # kernels or initrd if this script is ever interrupted.
47 if ! test -e $dst; then
48 local dstTmp=$dst.tmp.$$
49 cp $src $dstTmp
50 mv $dstTmp $dst
51 fi
52 filesCopied[$dst]=1
53 result=$dst
54}
55
56copyForced() {
57 local src="$1"
58 local dst="$2"
59 cp $src $dst.tmp
60 mv $dst.tmp $dst
61}
62
63outdir=$target/old
64mkdir -p $outdir || true
65
66# Copy its kernel and initrd to $target/old.
67addEntry() {
68 local path="$1"
69 local generation="$2"
70
71 if ! test -e $path/kernel -a -e $path/initrd; then
72 return
73 fi
74
75 local kernel=$(readlink -f $path/kernel)
76 local initrd=$(readlink -f $path/initrd)
77 local dtb_path=$(readlink -f $path/dtbs)
78
79 if test -n "@copyKernels@"; then
80 copyToKernelsDir $kernel; kernel=$result
81 copyToKernelsDir $initrd; initrd=$result
82 fi
83
84 echo $(readlink -f $path) > $outdir/$generation-system
85 echo $(readlink -f $path/init) > $outdir/$generation-init
86 cp $path/kernel-params $outdir/$generation-cmdline.txt
87 echo $initrd > $outdir/$generation-initrd
88 echo $kernel > $outdir/$generation-kernel
89
90 if test "$generation" = "default"; then
91 copyForced $kernel $target/kernel.img
92 copyForced $initrd $target/initrd
93 for dtb in $dtb_path/{broadcom,}/bcm*.dtb; do
94 dst="$target/$(basename $dtb)"
95 copyForced $dtb "$dst"
96 filesCopied[$dst]=1
97 done
98 cp "$(readlink -f "$path/init")" $target/nixos-init
99 echo "`cat $path/kernel-params` init=$path/init" >$target/cmdline.txt
100 fi
101}
102
103addEntry $default default
104
105# Add all generations of the system profile to the menu, in reverse
106# (most recent to least recent) order.
107for generation in $(
108 (cd /nix/var/nix/profiles && ls -d system-*-link) \
109 | sed 's/system-\([0-9]\+\)-link/\1/' \
110 | sort -n -r); do
111 link=/nix/var/nix/profiles/system-$generation-link
112 addEntry $link $generation
113done
114
115# Add the firmware files
116fwdir=@firmware@/share/raspberrypi/boot/
117copyForced $fwdir/bootcode.bin $target/bootcode.bin
118copyForced $fwdir/fixup.dat $target/fixup.dat
119copyForced $fwdir/fixup4.dat $target/fixup4.dat
120copyForced $fwdir/fixup4cd.dat $target/fixup4cd.dat
121copyForced $fwdir/fixup4db.dat $target/fixup4db.dat
122copyForced $fwdir/fixup4x.dat $target/fixup4x.dat
123copyForced $fwdir/fixup_cd.dat $target/fixup_cd.dat
124copyForced $fwdir/fixup_db.dat $target/fixup_db.dat
125copyForced $fwdir/fixup_x.dat $target/fixup_x.dat
126copyForced $fwdir/start.elf $target/start.elf
127copyForced $fwdir/start4.elf $target/start4.elf
128copyForced $fwdir/start4cd.elf $target/start4cd.elf
129copyForced $fwdir/start4db.elf $target/start4db.elf
130copyForced $fwdir/start4x.elf $target/start4x.elf
131copyForced $fwdir/start_cd.elf $target/start_cd.elf
132copyForced $fwdir/start_db.elf $target/start_db.elf
133copyForced $fwdir/start_x.elf $target/start_x.elf
134
135# Add the config.txt
136copyForced @configTxt@ $target/config.txt
137
138# Remove obsolete files from $target and $target/old.
139for fn in $target/old/*linux* $target/old/*initrd-initrd* $target/bcm*.dtb; do
140 if ! test "${filesCopied[$fn]}" = 1; then
141 rm -vf -- "$fn"
142 fi
143done