]>
Commit | Line | Data |
---|---|---|
b3d47d2d SI |
1 | #!/bin/sh |
2 | ||
3 | set -e | |
4 | ||
5 | . /usr/share/pve-kernel-helper/scripts/functions | |
6 | ||
2955b2b7 FG |
7 | _add_entry_to_list_file() { |
8 | file="$1" | |
9 | entry="$2" | |
10 | ||
11 | if [ -e "$file" ]; then | |
12 | cp "$file" "$file.new" | |
13 | fi | |
14 | echo "$entry" >> "$file.new" | |
15 | sort -uo "$file.new" "$file.new" | |
16 | mv "$file.new" "$file" | |
17 | } | |
18 | ||
19 | _remove_entry_from_list_file() { | |
20 | file="$1" | |
21 | entry="$2" | |
22 | ||
23 | # guard against removing whole file by accident! | |
24 | if [ -z "$entry" ]; then | |
25 | echo "cannot remove empty entry from '$file'." | |
26 | return | |
27 | fi | |
28 | ||
29 | if [ -e "$file" ]; then | |
30 | grep -vFx "$entry" "$file" > "$file.new" || true | |
31 | mv "$file.new" "$file" | |
32 | else | |
33 | echo "'$file' does not exist.." | |
34 | fi | |
35 | } | |
b3d47d2d SI |
36 | |
37 | _get_partition_info() { | |
38 | if [ ! -e "$1" ]; then | |
39 | warn "E: '$1' does not exist!" | |
40 | exit 1 | |
41 | fi | |
42 | bdev=$(realpath "$1") | |
43 | if [ ! -b "$bdev" ]; then | |
44 | warn "E: '$bdev' is not a block device!" | |
45 | exit 1 | |
46 | fi | |
47 | ||
48 | bdev_info=$( \ | |
49 | lsblk \ | |
50 | --bytes \ | |
51 | --pairs \ | |
52 | -o 'UUID,SIZE,FSTYPE,PARTTYPE,PKNAME,MOUNTPOINT' \ | |
53 | "$bdev" \ | |
54 | ) | |
55 | if [ -z "$bdev_info" ]; then | |
56 | warn "E: unable to get information about block device '$1'!" | |
57 | exit 1 | |
58 | fi | |
59 | ||
60 | count=$(echo "$bdev_info" | grep -c '^') | |
61 | if [ "$count" -ne '1' ]; then | |
62 | echo "$bdev_info" | |
63 | warn "E: block device '$1' has children!" | |
64 | exit 1 | |
65 | fi | |
66 | ||
67 | echo "$bdev_info" | |
68 | eval "$bdev_info" | |
69 | ||
70 | if [ -z "$PKNAME" ]; then | |
71 | warn "E: cannot determine parent device of '$1' - please provide a partition, not a full disk." | |
72 | exit 1 | |
73 | fi | |
74 | ||
75 | if [ -n "$SIZE" ] && [ "$SIZE" -lt 268435456 ]; then | |
76 | warn "E: '$1' is too small (<256M)." | |
77 | exit 1 | |
78 | fi | |
79 | ||
80 | if [ -n "$MOUNTPOINT" ]; then | |
81 | warn "E: '$1' is mounted on '$MOUNTPOINT' - exiting." | |
82 | exit 1 | |
83 | fi | |
84 | } | |
85 | ||
86 | format() { | |
87 | part="$1" | |
88 | force="$2" | |
89 | ||
90 | _get_partition_info "$part" | |
91 | ||
92 | if [ -n "$FSTYPE" ]; then | |
93 | if [ -z "$force" ] || [ "$force" != '--force' ]; then | |
94 | warn "E: '$part' contains a filesystem ('$FSTYPE') - exiting (use --force to override)" | |
95 | exit 1 | |
96 | fi | |
97 | fi | |
98 | ||
99 | part_basename=$(basename "$part") | |
100 | if [ -z "$part_basename" ]; then | |
101 | warn "E: unable to determine basename of '$part'" | |
102 | exit 1 | |
103 | fi | |
104 | ||
105 | part_num=$(cat /sys/block/"$PKNAME"/"$part_basename"/partition) | |
106 | if [ -z "$part_num" ]; then | |
107 | warn "E: unable to determine partition number of '$part'" | |
108 | exit 1 | |
109 | fi | |
110 | ||
111 | if [ -z "$PARTTYPE" ] || [ "$PARTTYPE" != "$ESPTYPE" ]; then | |
112 | echo "Setting partition type of '$part' to '$ESPTYPE'.." | |
113 | sgdisk "-t$part_num:$ESPTYPE" "/dev/$PKNAME" | |
114 | echo "Calling 'udevadm settle'.." | |
115 | udevadm settle --timeout=5 | |
116 | fi | |
117 | ||
118 | echo "Formatting '$part' as vfat.." | |
119 | mkfs.vfat -F 32 "$part" | |
120 | echo "Done." | |
121 | exit 0 | |
122 | } | |
123 | ||
124 | init() { | |
125 | part="$1" | |
126 | ||
127 | _get_partition_info "$part" | |
128 | ||
129 | if [ -z "$PARTTYPE" ] || [ "$PARTTYPE" != "$ESPTYPE" ]; then | |
130 | warn "E: '$part' has wrong partition type (!= $ESPTYPE)." | |
131 | exit 1 | |
132 | fi | |
133 | ||
134 | if [ -z "$FSTYPE" ] || [ "$FSTYPE" != 'vfat' ]; then | |
135 | warn "E: '$part' has wrong filesystem (!= vfat)." | |
136 | exit 1 | |
137 | fi | |
138 | ||
139 | if [ -z "$UUID" ]; then | |
140 | warn "E: '$part' has no UUID set, required for mounting." | |
141 | exit 1 | |
142 | fi | |
143 | ||
144 | esp_mp="/var/tmp/espmounts/$UUID" | |
145 | ||
146 | mkdir -p "$esp_mp" | |
147 | echo "Mounting '$part' on '$esp_mp'." | |
148 | mount -t vfat "$part" "$esp_mp" | |
149 | ||
150 | echo "Installing systemd-boot.." | |
151 | mkdir -p "$esp_mp/$PMX_ESP_DIR" | |
152 | bootctl --path "$esp_mp" install | |
153 | ||
154 | echo "Configuring systemd-boot.." | |
155 | echo "timeout 3" > "$esp_mp/$PMX_LOADER_CONF.tmp" | |
156 | echo "default proxmox-*" >> "$esp_mp/$PMX_LOADER_CONF.tmp" | |
157 | mv "$esp_mp/$PMX_LOADER_CONF.tmp" "$esp_mp/$PMX_LOADER_CONF" | |
158 | echo "Unmounting '$part'." | |
159 | umount "$part" | |
160 | ||
161 | echo "Adding '$part' to list of synced ESPs.." | |
2955b2b7 | 162 | _add_entry_to_list_file "$ESP_LIST" "$UUID" |
b3d47d2d SI |
163 | |
164 | echo "Refreshing kernels and initrds.." | |
165 | refresh | |
166 | } | |
167 | ||
0956bd22 FG |
168 | _clean_impl() { |
169 | if [ ! -e "/dev/disk/by-uuid/" ]; then | |
170 | warn 'E: /dev/disk/by-uuid does not exist, aborting!' | |
171 | exit 1 | |
172 | fi | |
173 | echo -n "Checking whether ESP '$curr_uuid' exists.. " | |
174 | if [ -e "/dev/disk/by-uuid/$curr_uuid" ]; then | |
175 | echo "Found!" | |
176 | else | |
177 | echo "Not found!" | |
178 | if [ -z "$dry_run" ] || [ "$dry_run" != '--dry-run' ]; then | |
179 | _remove_entry_from_list_file "$ESP_LIST" "$curr_uuid" | |
180 | fi | |
181 | fi | |
182 | } | |
183 | ||
184 | clean() { | |
185 | dry_run="$1" | |
186 | rm -f "$ESP_LIST".tmp | |
187 | loop_esp_list _clean_impl | |
188 | if [ "$?" -eq 2 ]; then | |
189 | warn "E: $ESP_LIST does not exist." | |
190 | exit 1 | |
191 | fi | |
192 | if [ -e "$ESP_LIST".tmp ]; then | |
193 | mv "$ESP_LIST".tmp "$ESP_LIST" | |
194 | fi | |
195 | } | |
196 | ||
b3d47d2d SI |
197 | refresh() { |
198 | hookscript='/etc/kernel/postinst.d/zz-pve-efiboot' | |
199 | echo "Running hook script '$hookscript'.." | |
200 | exec $hookscript | |
201 | } | |
202 | ||
427fba71 FG |
203 | add_kernel() { |
204 | ver="$1" | |
205 | ||
206 | if [ -z "$ver" ]; then | |
207 | warn "E: <kernel-version> is mandatory" | |
208 | warn "" | |
209 | exit 1 | |
210 | fi | |
211 | ||
212 | if [ ! -e "/boot/vmlinuz-$ver" ]; then | |
213 | warn "E: no kernel image found in /boot for '$ver', not adding." | |
214 | exit 1 | |
215 | fi | |
216 | _add_entry_to_list_file "$MANUAL_KERNEL_LIST" "$ver" | |
217 | echo "Added kernel '$ver' to manual kernel list." | |
218 | } | |
219 | ||
220 | remove_kernel() { | |
221 | ver="$1" | |
222 | ||
223 | if [ -z "$ver" ]; then | |
224 | warn "E: <kernel-version> is mandatory" | |
225 | warn "" | |
226 | exit 1 | |
227 | fi | |
228 | ||
229 | if grep -sqFx "$ver" "$MANUAL_KERNEL_LIST"; then | |
230 | _remove_entry_from_list_file "$MANUAL_KERNEL_LIST" "$ver" | |
231 | echo "Removed kernel '$ver' from manual kernel list." | |
232 | else | |
233 | echo "Kernel '$ver' not found in manual kernel list." | |
234 | fi | |
235 | } | |
236 | ||
2d7389fb FG |
237 | list_kernels() { |
238 | boot_kernels="$(boot_kernel_list)" | |
239 | ||
240 | if [ -e "$MANUAL_KERNEL_LIST" ]; then | |
241 | manual_kernels="$(echo "$boot_kernels" | grep -Fx -f "$MANUAL_KERNEL_LIST")" | |
242 | boot_kernels="$(echo "$boot_kernels" | grep -Fxv -f "$MANUAL_KERNEL_LIST")" | |
243 | fi | |
244 | ||
245 | if [ -z "$manual_kernels" ]; then | |
246 | manual_kernels="None." | |
247 | fi | |
248 | ||
249 | echo "Manually selected kernels:" | |
250 | echo "$manual_kernels" | |
251 | echo "" | |
252 | echo "Automatically selected kernels:" | |
253 | echo "$boot_kernels" | |
254 | } | |
255 | ||
b3d47d2d SI |
256 | usage() { |
257 | warn "USAGE: $0 <commands> [ARGS]" | |
258 | warn "" | |
259 | warn " $0 format <partition> [--force]" | |
260 | warn " $0 init <partition>" | |
0956bd22 | 261 | warn " $0 clean [--dry-run]" |
b3d47d2d | 262 | warn " $0 refresh" |
427fba71 | 263 | warn " $0 kernels <add|remove> <kernel-version>" |
2d7389fb | 264 | warn " $0 kernels list" |
0b99d576 | 265 | warn " $0 help" |
b3d47d2d SI |
266 | } |
267 | ||
268 | help() { | |
269 | echo "USAGE: $0 format <partition> [--force]" | |
270 | echo "" | |
271 | echo " format <partition> as EFI system partition. Use --force to format even if <partition> is currently in use." | |
272 | echo "" | |
273 | echo "USAGE: $0 init <partition>" | |
274 | echo "" | |
275 | echo " initialize EFI system partition at <partition> for automatic synchronization of pve-kernels and their associated initrds." | |
276 | echo "" | |
0956bd22 FG |
277 | echo "USAGE: $0 clean [--dry-run]" |
278 | echo "" | |
279 | echo " remove no longer existing EFI system partition UUIDs from $ESP_LIST. Use --dry-run to only print outdated entries instead of removing them." | |
280 | echo "" | |
b3d47d2d SI |
281 | echo "USAGE: $0 refresh" |
282 | echo "" | |
283 | echo " refresh all configured EFI system partitions." | |
284 | echo "" | |
427fba71 FG |
285 | echo "USAGE: $0 kernels <add|remove> <kernel-version>" |
286 | echo "" | |
287 | echo " add/remove pve-kernel with ABI <kernel-version> to list of synced kernels, in addition to automatically selected ones." | |
288 | echo "" | |
2d7389fb FG |
289 | echo "USAGE: $0 kernels list" |
290 | echo "" | |
291 | echo " list kernel versions currently selected for inclusion on ESPs." | |
292 | echo "" | |
b3d47d2d SI |
293 | } |
294 | ||
295 | if [ -z "$1" ]; then | |
296 | usage | |
297 | exit 0 | |
298 | fi | |
299 | ||
300 | case "$1" in | |
301 | 'format') | |
302 | shift | |
303 | if [ -z "$1" ]; then | |
304 | warn "E: <partition> is mandatory." | |
305 | warn "" | |
306 | usage | |
307 | exit 1 | |
308 | fi | |
309 | format "$@" | |
310 | exit 0 | |
311 | ;; | |
312 | 'init') | |
420039cd | 313 | reexec_in_mountns "$@" |
b3d47d2d SI |
314 | shift |
315 | if [ -z "$1" ]; then | |
316 | warn "E: <partition> is mandatory." | |
317 | warn "" | |
318 | usage | |
319 | exit 1 | |
320 | fi | |
321 | init "$@" | |
322 | exit 0 | |
323 | ;; | |
0956bd22 FG |
324 | 'clean') |
325 | shift | |
326 | clean "$@" | |
327 | exit 0 | |
328 | ;; | |
b3d47d2d SI |
329 | 'refresh') |
330 | shift | |
331 | refresh | |
332 | exit 0 | |
333 | ;; | |
427fba71 FG |
334 | 'kernels') |
335 | shift | |
336 | if [ -z "$1" ]; then | |
337 | warn "E: subcommand is mandatory." | |
338 | warn "" | |
339 | usage | |
340 | exit 1 | |
341 | fi | |
342 | cmd="$1" | |
343 | case "$cmd" in | |
344 | 'add') | |
345 | add_kernel "$2" | |
346 | exit 0 | |
347 | ;; | |
348 | 'remove') | |
349 | remove_kernel "$2" | |
350 | exit 0 | |
351 | ;; | |
2d7389fb FG |
352 | 'list') |
353 | list_kernels | |
354 | exit 0 | |
355 | ;; | |
427fba71 FG |
356 | *) |
357 | warn "E: invalid subcommand '$cmd'." | |
358 | warn "" | |
359 | usage | |
360 | exit 1 | |
361 | ;; | |
362 | esac | |
363 | ;; | |
b3d47d2d SI |
364 | 'help') |
365 | shift | |
366 | help | |
367 | exit 0 | |
368 | ;; | |
369 | *) | |
370 | warn "Invalid/unknown command '$1'." | |
371 | warn "" | |
372 | usage | |
373 | exit 1 | |
374 | ;; | |
375 | esac | |
376 | ||
377 | exit 1 |