File: mkimage-uc22

package info (click to toggle)
snapd 2.72-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 80,412 kB
  • sloc: sh: 16,506; ansic: 16,211; python: 11,213; makefile: 1,919; exp: 190; awk: 58; xml: 22
file content (566 lines) | stat: -rwxr-xr-x 20,720 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
#!/bin/bash

# create an image that looks like a classic image
# Note that "mk-image" is left as a script so that it can also be
# run outside of spread easily for quick interactive testing

DEFAULT_BASE_DIR="/tmp/mkimage"
DEFAULT_BOOT_IMG="boot.img"
DEFAULT_CACHE_DIR="cache"
DEFAULT_MNT_DIR="mnt"
DEFAULT_SNAPD_BINPATH="/usr/lib/snapd"
DEFAULT_BASE_IMAGE_URL="http://cdimage.ubuntu.com/ubuntu-base/releases/22.04/release/ubuntu-base-22.04-base-amd64.tar.gz"
DEFAULT_SNAPD_DEB_URL=https://storage.googleapis.com/snapd-spread-tests/snapd-tests/packages/ubuntu-22.04-64.tar 

show_help() {
    echo "usage: mkimage-uc22 [--boot-img BOOT_IMG] [--cache-dir CACHE_DIR] [--mnt-dir MNT_DIR] [--snap <SNAP_PATH> ...] model_assertion" 
    echo ""
    echo "create an image that looks like a classic image"
    echo ""
    echo "Available options:"
    echo "  -h --help   show this help message."
    echo ""
}

find_snap(){
    local SNAPS_DIR="$1"
    local SNAP="$2"
    find "$SNAPS_DIR" -maxdepth 1 -name "${SNAP}_*.snap" -printf "%f\n"
}

get_extra_snaps() {
    local SNAPS_DIR="$1"
    local EXTRA_SNAPS=""

    if [ -d "$CACHE_DIR" ]; then
        while IFS= read -r mysnap; do
            echo "$mysnap"
        done < <(find "$SNAPS_DIR" -name '*.snap')
    fi
}

get_assets() {
    local CACHE="$1"
    local BASE_IMAGE_URL="$2"
    local BASE_IMAGE_PATH="$3"
    shift 3
    # shellcheck disable=SC2124
    local SNAPS="$@"

    if [ -d "$CACHE" ]; then
        echo "mkimage-uc22: using existing cache dir $CACHE"
    fi

    for snap in $SNAPS; do
        if [ ! -f "$snap" ]; then
            echo "mkimage-uc22: the provided snap \"$snap\" does not exist" >&2
            return 1
        fi
    done

    mkdir -p "$CACHE"
    # shellcheck disable=SC2086
    cp $SNAPS "$CACHE"

    # get the snaps
    local NAME
    for snap in pc-kernel pc; do        
        NAME="$(find_snap "$CACHE" "$snap")"
        if [ -z "$NAME" ]; then
            echo "mkimage-uc22: downloading snap $snap"
            snap download --channel=22 --target-directory="$CACHE" "$snap"
        else
            echo "mkimage-uc22: using provided snap $NAME"
        fi
        unsquashfs -n -d "$CACHE"/snap-"$snap" "$CACHE"/"${snap}"_*.snap
    done
    for snap in snapd core22; do
        NAME="$(find_snap "$CACHE" "$snap")"
        if [ -z "$NAME" ]; then
            echo "mkimage-uc22: downloading snap $snap"
            snap download --target-directory="$CACHE" "$snap"
        else
            echo "mkimage-uc22: using provided snap $NAME"
        fi
    done

    if [ -n "$BASE_IMAGE_PATH" ]; then
        echo "mkimage-uc22: using local ubuntu classic base from $BASE_IMAGE_PATH"
        cp "$BASE_IMAGE_PATH" "$CACHE"
    else
        echo "mkimage-uc22: downloading the ubuntu classic base"
        wget -q -c -P "$CACHE" "$BASE_IMAGE_URL"
    fi    

    echo "mkimage-uc22: image assets ready"
}

# shellcheck disable=SC2317
cleanup() {
    local IMG MNT
    IMG="$(readlink -f "$1")"
    MNT="$(readlink -f "$2")"

    retry -n 3 --wait 1 sh -c "umount \"$MNT\"/*"
    retry -n 3 --wait 1 sh -c "kpartx -d \"$IMG\""
}

create_image() {
    local IMG
    IMG="$(readlink -f "$1")"

    rm -f "$IMG"
    # We need 6G to for the image as the partitions described below use 5,93G
    # In total the image has 12453854 sectors (512B each)
    truncate --size=6G "$IMG"
    echo "Creating partition on $IMG"
    cat <<EOF | sfdisk -q "$IMG"
label: gpt
device: boot.img
unit: sectors
first-lba: 34
last-lba: 12453854
sector-size: 512

boot.img1 : start=        2048, size=        2048, type=21686148-6449-6E6F-744E-656564454649, uuid=ECD24EAE-A687-4177-9223-6DDB4FCFF842, name="BIOS Boot"
##### no ubuntu-seed on the initial version but we need a EFI system
boot.img2 : start=        4096, size=     202752, type=C12A7328-F81F-11D2-BA4B-00A0C93EC93B, uuid=21A0079F-3E45-4669-8FF2-B3917819279F, name="EFI System partition"
boot.img3 : start=     2461696, size=     1536000, type=0FC63DAF-8483-4772-8E79-3D69D8477DE4, uuid=338DD9E7-CFE1-524A-A8B6-7D87DA8A4B34, name="ubuntu-boot"
boot.img4 : start=     3997696, size=       32768, type=0FC63DAF-8483-4772-8E79-3D69D8477DE4, uuid=1144DFB5-DFC2-0745-A1F2-AD311FEBE0DB, name="ubuntu-save"
boot.img5 : start=     4030464, size=     8423391, type=0FC63DAF-8483-4772-8E79-3D69D8477DE4, uuid=B84565A3-E9F8-8A40-AB04-810A4B891F8C, name="ubuntu-data"
EOF
}

install_data_partition() {    
    set -x

    local DESTDIR=$1
    local CACHE=$2
    local MODEL_ASSERTION=$3
    local SEED_LABEL
    SEED_LABEL="classic"

    echo "mkimage-uc22: copying base filesystem"
    sudo tar -C "$DESTDIR" -xf "$CACHE"/ubuntu-base-22.04-base-amd64.tar.gz

    echo "mkimage-uc22: creating basic devices to be able to install packages"
    [ -e "$DESTDIR"/dev/null ] || sudo mknod -m 666 "$DESTDIR"/dev/null c 1 3
    [ -e "$DESTDIR"/dev/zero ] || sudo mknod -m 666 "$DESTDIR"/dev/zero c 1 5
    [ -e "$DESTDIR"/dev/random ] || sudo mknod -m 666 "$DESTDIR"/dev/random c 1 8
    [ -e "$DESTDIR"/dev/urandom ] || sudo mknod -m 666 "$DESTDIR"/dev/urandom c 1 9

    # ensure the proxy and resolv configuration is set inside the chroot
    if [ "${SNAPD_USE_PROXY:-}" = true ]; then
        cp /etc/resolv.conf "$DESTDIR"/etc/resolv.conf
        cp /etc/environment "$DESTDIR"/etc/environment
    else
        echo "nameserver 8.8.8.8" | sudo tee -a "$DESTDIR"/etc/resolv.conf
    fi

    local pkgs="snapd ssh openssh-server sudo iproute2 iputils-ping isc-dhcp-client netplan.io vim-tiny kmod cloud-init jq update-notifier-common systemd-timesyncd"
    echo "mkimage-uc22: installing additional packages: $pkgs"
    sudo chroot "$DESTDIR" /usr/bin/sh -c "DEBIAN_FRONTEND=noninteractive apt -qq update"    
    sudo chroot "$DESTDIR" /usr/bin/sh -c \
         "DEBIAN_FRONTEND=noninteractive apt -qq install --no-install-recommends -y $pkgs" < /dev/null > /dev/null

    echo "mkimage-uc22: configuring netplan"
    cat > "$CACHE"/00-ethernet.yaml <<'EOF'
network:
  ethernets:
    any:
      match:
        name: e*
      dhcp4: true
  version: 2
EOF
    sudo cp "$CACHE"/00-ethernet.yaml "$DESTDIR"/etc/netplan

    echo "mkimage-uc22: mounting bits needed to be able to update boot assets"
    sudo mkdir -p "$DESTDIR"/boot/grub "$DESTDIR"/boot/efi
    sudo tee "$DESTDIR"/etc/fstab <<'EOF'
/run/mnt/ubuntu-boot/EFI/ubuntu /boot/grub none bind 0 0
EOF

    echo "mkimage-uc22: creating users"
    sudo chroot "$DESTDIR" /usr/sbin/adduser --disabled-password --gecos "" user1
    printf "ubuntu\nubuntu\n" | sudo chroot "$DESTDIR" /usr/bin/passwd user1
    echo "user1 ALL=(ALL) NOPASSWD:ALL" | sudo tee -a "$DESTDIR"/etc/sudoers

    # set password for root user
    sudo chroot "$DESTDIR" /usr/bin/sh -c 'echo root:root | chpasswd'
    sudo tee -a "$DESTDIR/etc/ssh/sshd_config" <<'EOF'
PermitRootLogin yes
PasswordAuthentication yes
EOF

    echo "mkimage-uc22: populating snapd data"
    cat > modeenv <<EOF
mode=run
recovery_system=$SEED_LABEL
current_recovery_systems=$SEED_LABEL
good_recovery_systems=$SEED_LABEL
base=$(find_snap "$CACHE" core22)
gadget=$(find_snap "$CACHE" pc)
current_kernels=$(find_snap "$CACHE" pc-kernel)
model=canonical/ubuntu-core-22-pc-amd64
grade=dangerous
model_sign_key_id=9tydnLa6MTJ-jaQTFUXEwHl1yRx7ZS4K5cyFDhYDcPzhS7uyEkDxdUjg9g08BtNn
current_kernel_command_lines=["snapd_recovery_mode=run console=ttyS0 console=tty1 panic=-1"]
EOF
    sudo cp modeenv "$DESTDIR"/var/lib/snapd/
    # needed from the beginning in ubuntu-data as these are mounted by snap-bootstrap
    # (UC also has base here, but we do not mount it from initramfs in classic)
    sudo mkdir -p "$DESTDIR"/var/lib/snapd/snaps/
    sudo cp "$CACHE"/"$(find_snap "$CACHE" pc-kernel)" "$CACHE"/"$(find_snap "$CACHE" pc)" \
         "$DESTDIR"/var/lib/snapd/snaps/

    # clean classic-seed dir
    rm -rf ./classic-seed/

    local EXTRA_SNAPS
    for mysnap in $(get_extra_snaps "$CACHE"); do
        EXTRA_SNAPS="$EXTRA_SNAPS --snap $mysnap"
    done

    # create the seed
    # shellcheck disable=SC2086
    snap prepare-image --classic \
         --channel=edge \
         $EXTRA_SNAPS \
         "$MODEL_ASSERTION" \
         ./classic-seed

    # rename seed-label
    mv ./classic-seed/system-seed/systems/"$(date +%Y%m%d)" ./classic-seed/system-seed/systems/"$SEED_LABEL"
    # and put the seed in place
    mkdir -p "$DESTDIR"/var/lib/snapd
    mv ./classic-seed/system-seed "$DESTDIR"/var/lib/snapd/seed
}

populate_image() {
    local IMG="$1"
    local CACHE="$2"
    local MNT="$3"
    local MODEL_ASSERTION="$4"
    local KERNEL_SNAP
    KERNEL_SNAP="$(find_snap "$CACHE" pc-kernel)"

    mkdir -p "$MNT"
    local loop loop_esp loop_boot loop_save loop_data
    loop=$(sudo kpartx -asv "$IMG" | head -n1 | cut -d' ' -f3)
    loop=${loop%p*}
    loop_esp="${loop}"p2
    loop_boot="${loop}"p3
    loop_save="${loop}"p4
    loop_data="${loop}"p5

    # XXX: on a real UC device this the ESP is "ubuntu-seed"
    sudo mkfs.fat -n ubuntu-seed /dev/mapper/"$loop_esp"
    sudo mkfs.ext4 -L ubuntu-boot -q /dev/mapper/"$loop_boot"
    sudo mkfs.ext4 -L ubuntu-save -q /dev/mapper/"$loop_save"
    sudo mkfs.ext4 -L ubuntu-data -q /dev/mapper/"$loop_data"
    for name in esp ubuntu-boot ubuntu-save ubuntu-data; do
        mkdir -p "$MNT"/"$name"
    done
    sudo mount /dev/mapper/"$loop_esp" "$MNT"/esp
    sudo mount /dev/mapper/"$loop_boot" "$MNT"/ubuntu-boot
    sudo mount /dev/mapper/"$loop_save" "$MNT"/ubuntu-save
    sudo mount /dev/mapper/"$loop_data" "$MNT"/ubuntu-data

    # install things into the image
    install_data_partition "$MNT"/ubuntu-data "$CACHE" "$MODEL_ASSERTION"

    # ESP partition just chainloads into ubuntu-boot
    # XXX: do we want this given that we don't have recovery systems?
    sudo mkdir -p "$MNT"/esp/EFI/boot
    sudo cp "$CACHE"/snap-pc/grubx64.efi "$MNT"/esp/EFI/boot
    sudo cp "$CACHE"/snap-pc/shim.efi.signed "$MNT"/esp/EFI/boot/bootx64.efi
    cat > "$CACHE"/esp-grub.cfg <<'EOF'
set default=0
set timeout=3

search --no-floppy --set=boot_fs --label ubuntu-boot
menuentry "Continue to run mode" --hotkey=n --id=run {
    chainloader ($boot_fs)/EFI/boot/grubx64.efi
}
EOF
    sudo mkdir -p "$MNT"/esp/EFI/ubuntu
    sudo cp "$CACHE"/esp-grub.cfg "$MNT"/esp/EFI/ubuntu/grub.cfg

    # ubuntu-boot
    sudo mkdir -p "$MNT"/ubuntu-boot/EFI/boot
    sudo cp -a "$CACHE"/snap-pc/grubx64.efi "$MNT"/ubuntu-boot/EFI/boot
    sudo cp -a "$CACHE"/snap-pc/shim.efi.signed "$MNT"/ubuntu-boot/EFI/boot/bootx64.efi

    sudo mkdir -p "$MNT"/ubuntu-boot/EFI/ubuntu
    cat > "$CACHE"/grub.cfg <<'EOF'
set default=0
set timeout=3

# load only kernel_status and kernel command line variables set by snapd from
# the bootenv
load_env --file /EFI/ubuntu/grubenv kernel_status snapd_extra_cmdline_args snapd_full_cmdline_args

set snapd_static_cmdline_args='console=ttyS0 console=tty1 panic=-1'
set cmdline_args="$snapd_static_cmdline_args $snapd_extra_cmdline_args"
if [ -n "$snapd_full_cmdline_args" ]; then
    set cmdline_args="$snapd_full_cmdline_args"
fi

set kernel=kernel.efi

if [ "$kernel_status" = "try" ]; then
    # a new kernel got installed
    set kernel_status="trying"
    save_env kernel_status

    # use try-kernel.efi
    set kernel=try-kernel.efi
elif [ "$kernel_status" = "trying" ]; then
    # nothing cleared the "trying snap" so the boot failed
    # we clear the mode and boot normally
    set kernel_status=""
    save_env kernel_status
elif [ -n "$kernel_status" ]; then
    # ERROR invalid kernel_status state, reset to empty
    echo "invalid kernel_status!!!"
    echo "resetting to empty"
    set kernel_status=""
    save_env kernel_status
fi

if [ -e $prefix/$kernel ]; then
menuentry "Run Ubuntu Core 22" {
    # use $prefix because the symlink manipulation at runtime for kernel snap
    # upgrades, etc. should only need the /boot/grub/ directory, not the
    # /EFI/ubuntu/ directory
    chainloader $prefix/$kernel snapd_recovery_mode=run $cmdline_args
}
else
    # nothing to boot :-/
    echo "missing kernel at $prefix/$kernel!"
fi
EOF
    sudo cp -a "$CACHE"/grub.cfg "$MNT"/ubuntu-boot/EFI/ubuntu/
    # This must be exactly 1024 bytes
    local GRUBENV="# GRUB Environment Block
#######################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################"
    printf "%s" "$GRUBENV" > "$CACHE"/grubenv
    sudo cp -a "$CACHE"/grubenv "$MNT"/ubuntu-boot/EFI/ubuntu/grubenv
    sudo mkdir -p "$MNT"/ubuntu-boot/device/
    sudo cp -a "$MODEL_ASSERTION" "$MNT"/ubuntu-boot/device/model

    # kernel
    sudo mkdir -p "$MNT"/ubuntu-boot/EFI/ubuntu/"$KERNEL_SNAP"
    sudo cp -a "$CACHE"/snap-pc-kernel/kernel.efi "$MNT"/ubuntu-boot/EFI/ubuntu/"$KERNEL_SNAP"
    sudo ln -sf "$KERNEL_SNAP"/kernel.efi "$MNT"/ubuntu-boot/EFI/ubuntu/kernel.efi

    # cleanup
    sync
    sudo umount "$MNT"/ubuntu-*
}

replace_initramfs_bits() {
    local CACHE="$1"
    local SNAPD_BINPATH="$2"
    # TODO is there code to share with uc20_build_initramfs_kernel_snap in prepare.sh?
    local KERNEL_EFI_ORIG="$CACHE"/snap-pc-kernel/kernel.efi
    if [ ! -d initrd ]; then
        objcopy -O binary -j .initrd "$KERNEL_EFI_ORIG" initrd.img
        unmkinitramfs initrd.img initrd
    fi

    # Retrieve efi stub from ppa so we can rebuild kernel.efi
    DEBIAN_FRONTEND=noninteractive apt install -y --no-install-recommends ubuntu-dev-tools lz4 < /dev/null > /dev/null
    pull-lp-debs -a amd64 -D ppa --ppa ppa:snappy-dev/image ubuntu-core-initramfs "jammy"
    dpkg --fsys-tarfile ubuntu-core-initramfs_*.deb |
        tar --wildcards -xf - './usr/lib/ubuntu-core-initramfs/efi/linux*.efi.stub'

    cp "$SNAPD_BINPATH"/snap-bootstrap initrd/main/usr/lib/snapd/
    ( cd initrd/main && find . | cpio --create --quiet --format=newc --owner=0:0 | lz4 -l -7 > ../../initrd.img.new )

    objcopy -O binary -j .linux "$KERNEL_EFI_ORIG" linux
    # Replace kernel.efi in unsquashed snap
    objcopy --add-section .linux=linux --change-section-vma .linux=0x2000000 \
            --add-section .initrd=initrd.img.new --change-section-vma .initrd=0x3000000 \
            usr/lib/ubuntu-core-initramfs/efi/linux*.efi.stub \
            "$KERNEL_EFI_ORIG"
}

replace_images_files() {
    local IMG="$1"
    local CACHE="$2"
    local MNT="$3"
    local SNAPD_DEB="$4"
    local SNAPD_BINPATH="$5"

    mkdir -p "$MNT"/ubuntu-boot "$MNT"/data

    replace_initramfs_bits "$CACHE" "$SNAPD_BINPATH"

    loop=$(sudo kpartx -asv "$IMG" | head -n1 | cut -d' ' -f3)
    loop=${loop%p*}
    loop_boot="$loop"p3
    sudo mount /dev/mapper/"$loop_boot" "$MNT"/ubuntu-boot

    # copy kernel.efi with modified initramfs
    local subpath
    subpath=$(readlink "$MNT"/ubuntu-boot/EFI/ubuntu/kernel.efi)
    # TODO we should also repack kernel snap and replace the one in the rootfs too, and also re-sign
    cp -a "$CACHE"/snap-pc-kernel/kernel.efi "$MNT"/ubuntu-boot/EFI/ubuntu/"$subpath"

    # when no snapd deb package provided, the prebuilt one from master is used
    if [ -z "$SNAPD_DEB" ]; then
        wget -q -c -P "$CACHE" "$DEFAULT_SNAPD_DEB_URL"
        tar -xvf "$CACHE"/"$(basename "$DEFAULT_SNAPD_DEB_URL")" -C "$CACHE"
        SNAPD_DEB="$CACHE"/"$(find "$CACHE" -maxdepth 1 -name "snapd_*.deb" -printf "%f\n")"
    fi
    # replace snapd in data partition with the one passed as parameter
    local data_mnt="$loop"p5
    sudo mount /dev/mapper/"$data_mnt" "$MNT"/data
    sudo cp "$SNAPD_DEB" "$MNT"/data/snapd.deb
    sudo chroot "$MNT"/data apt install -qq -y --no-install-recommends ./snapd.deb < /dev/null > /dev/null
    sudo rm "$MNT"/data/snapd.deb
    # enable debug traces
    sudo mkdir -p "$MNT"/data/etc/systemd/system/snapd.service.d/
    sudo tee "$MNT"/data/etc/systemd/system/snapd.service.d/override.conf <<'EOF'
[Service]
Environment=SNAPD_DEBUG=1
EOF
}

show_how_to_run_qemu() {
    local IMG="$1"

    echo "mkimage-uc22: mage ready, run as: "
    echo cp /usr/share/OVMF/OVMF_VARS_4M.fd .
    echo qemu-system-x86_64 -m q35,accel=kvm -m 1500 -snapshot \
        -netdev user,id=net.0,hostfwd=tcp::10022-:22 \
        -device rtl8139,netdev=net.0 \
        -drive file=/usr/share/OVMF/OVMF_CODE_4M.fd,if=pflash,format=raw,readonly=on \
        -drive file=OVMF_VARS_4M.fd,if=pflash,format=raw \
        -drive file="$1",if=virtio \
        -serial stdio

    echo "mkimage-uc22: grub will chainload from ESP to ubuntu-boot"
    echo "mkimage-uc22: there press ESC and add 'dangerous rd.systemd.debug-shell=1' after kernel.efi"
}

main() {
    local BASE_DIR="$DEFAULT_BASE_DIR"
    local BOOT_IMG="$DEFAULT_BOOT_IMG"
    local CACHE_DIR="$DEFAULT_CACHE_DIR"
    local MNT_DIR="$DEFAULT_MNT_DIR"
    local SNAPD_BINPATH="$DEFAULT_SNAPD_BINPATH"
    local BASE_IMAGE_URL="$DEFAULT_BASE_IMAGE_URL"
    
    local SNAPD_DEB=""
    local BASE_IMAGE_PATH=""
    local MODEL_ASSERTION=""
    local SNAPS=""
    while [ $# -gt 0 ]; do
        case "$1" in
            -h|--help)
                show_help
                exit 0
                ;;
            --base-dir)
                BASE_DIR="$2"
                shift 2
                ;;
            --boot-img)
                BOOT_IMG="$2"
                shift 2
                ;;
            --cache-dir)
                CACHE_DIR="$2"
                shift 2
                ;;
            --mnt-dir)
                MNT_DIR="$2"
                shift 2
                ;;
            --snapd-deb)
                SNAPD_DEB="$2"
                shift 2
                ;;
            --snapd-binpath)
                SNAPD_BINPATH="$2"
                shift 2
                ;;
            --base-image-url)
                BASE_IMAGE_URL="$2"
                shift 2
                ;;
            --base-image-path)
                BASE_IMAGE_PATH="$2"
                shift 2
                ;;
            --snap)
                if [ -z "$SNAPS" ]; then
                    SNAPS="$2"
                else
                    SNAPS="$SNAPS $2"
                fi
                shift 2
                ;;
            *)
                MODEL_ASSERTION="$1"
                shift
                ;;
        esac
    done

    if [ -z "$BASE_DIR" ]; then
        echo "mkimage-uc22: base dir cannot be empty" >&2
        return 1
    fi

    if [ "$BASE_DIR" = "/" ]; then
        echo "mkimage-uc22: base dir cannot be /" >&2
        return 1
    fi

    if [ -z "$MODEL_ASSERTION" ]; then
        echo "mkimage-uc22: model assert not provided" >&2
        show_help
        return 1
    fi
    if [ ! -f "$MODEL_ASSERTION" ] ; then
        echo "mkimage-uc22: $MODEL_ASSERTION not found, please sign an assertion using classic-model.json as model" >&2
        return 1
    fi

    if [ -n "$SNAPS" ]; then
        echo "mkimage-uc22: snaps provided: $SNAPS"
        echo "mkimage-uc22: remember that the names need to be SNAPNAME_*.snap"
    fi

    if [ -n "$BASE_IMAGE_PATH" ] && [ ! -f "$BASE_IMAGE_PATH" ]; then
        echo "mkimage-uc22: Base image file not found: $BASE_IMAGE_PATH" >&2
        return 1
    fi

    if [ -z "$BASE_IMAGE_PATH" ] && [ -z "$BASE_IMAGE_URL" ]; then
        echo "mkimage-uc22: either base image path or url needs to be provided" >&2
        return 1
    fi

    BOOT_IMG="$BASE_DIR/$BOOT_IMG"
    CACHE_DIR="$BASE_DIR/$CACHE_DIR"
    MNT_DIR="$BASE_DIR/$MNT_DIR"

    rm -rf "$BOOT_IMG" "$CACHE_DIR" "$MNT_DIR"
    # shellcheck disable=SC2064
    trap "cleanup \"$BOOT_IMG\" \"$MNT_DIR\"" EXIT INT

    get_assets "$CACHE_DIR" "$BASE_IMAGE_URL" "$BASE_IMAGE_PATH" "$SNAPS"
    create_image "$BOOT_IMG"
    populate_image "$BOOT_IMG" "$CACHE_DIR" "$MNT_DIR" "$MODEL_ASSERTION"
    replace_images_files "$BOOT_IMG" "$CACHE_DIR" "$MNT_DIR" "$SNAPD_DEB" "$SNAPD_BINPATH"

    show_how_to_run_qemu "$BOOT_IMG"
    # TODO: show how to mount/chroot into the dir to test seeding
}

main "$@"