Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
ading2210
GitHub Repository: ading2210/shimboot
Path: blob/main/build_complete.sh
402 views
1
#!/bin/bash
2
3
. ./common.sh
4
. ./image_utils.sh
5
6
print_help() {
7
echo "Usage: ./build_complete.sh board_name"
8
echo "Valid named arguments (specify with 'key=value'):"
9
echo " compress_img - Compress the final disk image into a zip file. Set this to any value to enable this option."
10
echo " rootfs_dir - Use a different rootfs for the build. The directory you select will be copied before any patches are applied."
11
echo " quiet - Don't use progress indicators which may clog up log files."
12
echo " desktop - The desktop environment to install. This defaults to 'xfce'. Valid options include:"
13
echo " gnome, xfce, kde, lxde, gnome-flashback, cinnamon, mate, lxqt"
14
echo " data_dir - The working directory for the scripts. This defaults to ./data"
15
echo " arch - The CPU architecture to build the shimboot image for. Set this to 'arm64' if you have an ARM Chromebook."
16
echo " release - Set this to either 'bookworm', 'trixie', or 'unstable' to build for Debian 12, 13, or unstable."
17
echo " distro - The Linux distro to use. This should be either 'debian', 'ubuntu', or 'alpine'."
18
echo " luks - Set this argument to encrypt the rootfs partition."
19
}
20
21
assert_root
22
assert_args "$1"
23
parse_args "$@"
24
25
base_dir="$(realpath -m $(dirname "$0"))"
26
board="$1"
27
28
compress_img="${args['compress_img']}"
29
rootfs_dir="${args['rootfs_dir']}"
30
quiet="${args['quiet']}"
31
desktop="${args['desktop']-'xfce'}"
32
data_dir="${args['data_dir']}"
33
arch="${args['arch']-amd64}"
34
release="${args['release']}"
35
distro="${args['distro']-debian}"
36
luks="${args['luks']}"
37
38
#a list of all arm board names
39
arm_boards="
40
corsola hana jacuzzi kukui strongbad nyan-big kevin bob
41
veyron-speedy veyron-jerry veyron-minnie scarlet elm
42
kukui peach-pi peach-pit stumpy daisy-spring trogdor
43
"
44
#a list of shims that have a patch for the sh1mmer vulnerability
45
bad_boards="reef sand pyro"
46
47
if grep -q "$board" <<< "$arm_boards" > /dev/null; then
48
print_info "automatically detected arm64 device name"
49
arch="arm64"
50
fi
51
if grep -q "$board" <<< "$bad_boards" > /dev/null; then
52
print_error "Warning: you are attempting to build Shimboot for a board which has a shim that includes a fix for the sh1mmer vulnerability. The resulting image will not boot if you are enrolled."
53
read -p "Press [enter] to continue "
54
fi
55
56
if [[ "$luks" == "true" && "$arch" == "arm64" ]]; then
57
print_error "Uh-oh, you are trying to use luks2 encryption on an arm64 board. Unfortunately, rootfs encryption is not available on arm64-based boards at this time. :("
58
exit
59
fi
60
61
kernel_arch="$(uname -m)"
62
host_arch="unknown"
63
if [ "$kernel_arch" = "x86_64" ]; then
64
host_arch="amd64"
65
elif [ "$kernel_arch" = "aarch64" ]; then
66
host_arch="arm64"
67
fi
68
69
needed_deps="wget python3 unzip zip git debootstrap cpio binwalk pcregrep cgpt mkfs.ext4 mkfs.ext2 fdisk depmod findmnt lz4 pv cryptsetup"
70
if [ "$(check_deps "$needed_deps")" ]; then
71
#install deps automatically on debian and ubuntu
72
if [ -f "/etc/debian_version" ]; then
73
print_title "attempting to install build deps"
74
apt-get install wget python3 unzip zip debootstrap cpio binwalk pcregrep cgpt kmod pv lz4 cryptsetup -y
75
fi
76
assert_deps "$needed_deps"
77
fi
78
79
#install qemu-user-static on debian if needed
80
if [ "$arch" != "$host_arch" ]; then
81
if [ -f "/etc/debian_version" ]; then
82
if ! dpkg --get-selections | grep -v deinstall | grep "qemu-user-static\|box64\|fex-emu" > /dev/null; then
83
print_info "automatically installing qemu-user-static because we are building for a different architecture"
84
apt-get install qemu-user-static binfmt-support -y
85
fi
86
else
87
print_error "Warning: You are building an image for a different CPU architecture. It may fail if you do not have qemu-user-static installed."
88
sleep 1
89
fi
90
fi
91
92
cleanup_path=""
93
sigint_handler() {
94
if [ $cleanup_path ]; then
95
rm -rf $cleanup_path
96
fi
97
exit 1
98
}
99
trap sigint_handler SIGINT
100
101
shim_url="" #set this if you want to download from a third party mirror
102
boards_url="https://chromiumdash.appspot.com/cros/fetch_serving_builds?deviceCategory=ChromeOS"
103
104
if [ -z "$data_dir" ]; then
105
data_dir="$base_dir/data"
106
else
107
data_dir="$(realpath -m "$data_dir")"
108
fi
109
110
print_title "downloading list of recovery images"
111
reco_url="$(wget -qO- --show-progress $boards_url | python3 -c '
112
import json, sys
113
114
all_builds = json.load(sys.stdin)
115
board_name = sys.argv[1]
116
if not board_name in all_builds["builds"]:
117
print("Invalid board name: " + board_name, file=sys.stderr)
118
sys.exit(1)
119
120
board = all_builds["builds"][board_name]
121
if "models" in board:
122
for device in board["models"].values():
123
if device["pushRecoveries"]:
124
board = device
125
break
126
127
reco_url = list(board["pushRecoveries"].values())[-1]
128
print(reco_url)
129
' $board)"
130
print_info "found url: $reco_url"
131
132
shim_bin="$data_dir/shim_$board.bin"
133
shim_zip="$data_dir/shim_$board.zip"
134
shim_dir="$data_dir/shim_${board}_chunks"
135
reco_bin="$data_dir/reco_$board.bin"
136
reco_zip="$data_dir/reco_$board.zip"
137
mkdir -p "$data_dir"
138
139
extract_zip() {
140
local zip_path="$1"
141
local bin_path="$2"
142
cleanup_path="$bin_path"
143
print_info "extracting $zip_path"
144
local total_bytes="$(unzip -lq "$zip_path" | tail -1 | xargs | cut -d' ' -f1)"
145
if [ ! "$quiet" ]; then
146
unzip -p "$zip_path" | pv -s "$total_bytes" > "$bin_path"
147
else
148
unzip -p "$zip_path" > "$bin_path"
149
fi
150
rm -rf "$zip_path"
151
cleanup_path=""
152
}
153
154
download_and_unzip() {
155
local url="$1"
156
local zip_path="$2"
157
local bin_path="$3"
158
if [ ! -f "$bin_path" ]; then
159
if [ ! "$quiet" ]; then
160
wget -q --show-progress $url -O "$zip_path" -c
161
else
162
wget -q "$url" -O "$zip_path" -c
163
fi
164
fi
165
166
if [ ! -f "$bin_path" ]; then
167
extract_zip "$zip_path" "$bin_path"
168
fi
169
}
170
171
download_shim() {
172
print_info "downloading shim file manifest"
173
local boards_index="$(curl --no-progress-meter "https://cdn.cros.download/boards.txt")"
174
local shim_url_path="$(echo "$boards_index" | grep "/$board/").manifest"
175
local shim_url_dir="$(dirname "$shim_url_path")"
176
local shim_manifest="$(curl --no-progress-meter "https://cdn.cros.download/$shim_url_path")"
177
local py_load_json="import json, sys; manifest = json.load(sys.stdin)"
178
179
local zip_size="$(echo "$shim_manifest" | python3 -c "$py_load_json; print(manifest['size'])")"
180
local zip_size_pretty="$(echo "$zip_size" | numfmt --format %.2f --to=iec)"
181
local shim_chunks="$(echo "$shim_manifest" | python3 -c "$py_load_json; print('\\n'.join(manifest['chunks']))")"
182
local chunk_count="$(echo "$shim_chunks" | wc -l)"
183
local chunk_size="$((25 * 1024 * 1024))"
184
185
print_info "downloading shim file chunks (total $zip_size_pretty across $chunk_count chunks)"
186
mkdir -p "$shim_dir"
187
local i="0"
188
for shim_chunk in $shim_chunks; do
189
local chunk_url="https://cdn.cros.download/$shim_url_dir/$shim_chunk"
190
local chunk_path="$shim_dir/$shim_chunk"
191
local i="$(($i + 1))"
192
if [ -f "$chunk_path" ]; then
193
local existing_size="$(du -b "$chunk_path" | cut -f1)"
194
if [ "$existing_size" = "$chunk_size" ]; then
195
continue
196
fi
197
fi
198
print_info "downloading chunk $i / $chunk_count"
199
if [ ! "$quiet" ]; then
200
wget -c -q --show-progress "$chunk_url" -O "$chunk_path"
201
else
202
wget -c -q "$chunk_url" -O "$chunk_path"
203
fi
204
done
205
206
print_info "joining shim file chunks"
207
cleanup_path="$shim_zip"
208
if [ ! -f "$shim_bin" ]; then
209
cat "$shim_dir/"* | pv -s "$zip_size" > "$shim_zip"
210
rm -rf "$shim_dir"
211
fi
212
cleanup_path=""
213
214
print_info "extracting shim file"
215
if [ ! -f "$shim_bin" ]; then
216
extract_zip "$shim_zip" "$shim_bin"
217
fi
218
}
219
220
retry_cmd() {
221
local cmd="$@"
222
for i in 1 2 3 4 5; do
223
$cmd && break
224
done
225
}
226
227
print_title "downloading recovery image"
228
download_and_unzip "$reco_url" "$reco_zip" "$reco_bin"
229
230
print_title "downloading shim image"
231
if [ ! -f "$shim_bin" ]; then
232
if [ "$shim_url" ]; then
233
download_and_unzip "$shim_url" "$shim_zip" "$shim_bin"
234
else
235
download_shim "$shim_url" "$shim_zip" "$shim_bin"
236
fi
237
fi
238
239
print_title "building $distro rootfs"
240
if [ ! "$rootfs_dir" ]; then
241
desktop_package="task-$desktop-desktop"
242
rootfs_dir="$(realpath -m data/rootfs_$board)"
243
if [ "$(findmnt -T "$rootfs_dir/dev")" ]; then
244
sudo umount -l $rootfs_dir/* 2>/dev/null || true
245
fi
246
rm -rf $rootfs_dir
247
mkdir -p $rootfs_dir
248
249
if [ "$distro" = "debian" ]; then
250
release="${release:-bookworm}"
251
elif [ "$distro" = "ubuntu" ]; then
252
release="${release:-noble}"
253
elif [ "$distro" = "alpine" ]; then
254
release="${release:-edge}"
255
else
256
print_error "invalid distro selection"
257
exit 1
258
fi
259
260
#install a newer debootstrap version if needed
261
if [ -f "/etc/debian_version" ] && [ "$distro" = "ubuntu" -o "$distro" = "debian" ]; then
262
if [ ! -f "/usr/share/debootstrap/scripts/$release" ]; then
263
print_info "installing newer debootstrap version"
264
mirror_url="https://deb.debian.org/debian/pool/main/d/debootstrap/"
265
deb_file="$(curl "https://deb.debian.org/debian/pool/main/d/debootstrap/" | pcregrep -o1 'href="(debootstrap_.+?\.deb)"' | tail -n1)"
266
deb_url="${mirror_url}${deb_file}"
267
wget -q --show-progress "$deb_url" -O "/tmp/$deb_file"
268
apt-get install -y "/tmp/$deb_file"
269
fi
270
fi
271
272
./build_rootfs.sh $rootfs_dir $release \
273
custom_packages=$desktop_package \
274
hostname=shimboot-$board \
275
username=user \
276
user_passwd=user \
277
arch=$arch \
278
distro=$distro
279
fi
280
281
print_title "patching $distro rootfs"
282
retry_cmd ./patch_rootfs.sh $shim_bin $reco_bin $rootfs_dir "quiet=$quiet"
283
284
print_title "building final disk image"
285
final_image="$data_dir/shimboot_$board.bin"
286
rm -rf $final_image
287
retry_cmd ./build.sh $final_image $shim_bin $rootfs_dir "quiet=$quiet" "arch=$arch" "name=$distro" "luks=$luks"
288
print_info "build complete! the final disk image is located at $final_image"
289
290
print_title "cleaning up"
291
clean_loops
292
293
if [ "$compress_img" ]; then
294
image_zip="$data_dir/shimboot_$board.zip"
295
print_title "compressing disk image into a zip file"
296
zip -j $image_zip $final_image
297
print_info "finished compressing the disk file"
298
print_info "the finished zip file can be found at $image_zip"
299
fi
300
301