Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
ading2210
GitHub Repository: ading2210/shimboot
Path: blob/main/image_utils.sh
402 views
1
#!/bin/bash
2
create_loop() {
3
local loop_device=$(losetup -f)
4
if [ ! -b "$loop_device" ]; then
5
#we might run out of loop devices, see https://stackoverflow.com/a/66020349
6
local major=$(grep loop /proc/devices | cut -c3)
7
local number="$(echo "$loop_device" | grep -Eo '[0-9]+' | tail -n1)"
8
mknod $loop_device b $major $number
9
fi
10
losetup -P $loop_device "${1}"
11
echo $loop_device
12
}
13
14
#set required flags on the kernel partition
15
make_bootable() {
16
cgpt add -i 2 -S 1 -T 5 -P 10 -l kernel $1
17
}
18
19
partition_disk() {
20
local image_path=$(realpath -m "${1}")
21
local bootloader_size="$2"
22
local rootfs_name="$3"
23
#create partition table with fdisk
24
(
25
echo g #new gpt disk label
26
27
#create 1MB stateful
28
echo n #new partition
29
echo #accept default parition number
30
echo #accept default first sector
31
echo +1M #partition size is 1M
32
33
#create 32MB kernel partition
34
echo n
35
echo #accept default parition number
36
echo #accept default first sector
37
echo +32M #partition size is 32M
38
echo t #change partition type
39
echo #accept default parition number
40
echo FE3A2A5D-4F32-41A7-B725-ACCC3285A309 #chromeos kernel type
41
42
#create bootloader partition
43
echo n
44
echo #accept default parition number
45
echo #accept default first sector
46
echo "+${bootloader_size}M" #set partition size
47
echo t #change partition type
48
echo #accept default parition number
49
echo 3CB8E202-3B7E-47DD-8A3C-7FF2A13CFCEC #chromeos rootfs type
50
51
#create rootfs partition
52
echo n
53
echo #accept default parition number
54
echo #accept default first sector
55
echo #accept default size to fill rest of image
56
echo x #enter expert mode
57
echo n #change the partition name
58
echo #accept default partition number
59
echo "shimboot_rootfs:$rootfs_name" #set partition name
60
echo r #return to normal more
61
62
#write changes
63
echo w
64
) | fdisk $image_path > /dev/null
65
}
66
67
safe_mount() {
68
local source="$1"
69
local dest="$2"
70
local opts="$3"
71
72
umount $dest 2> /dev/null || /bin/true
73
rm -rf $dest
74
mkdir -p $dest
75
if [ "$opts" ]; then
76
mount $source $dest -o $opts
77
else
78
mount $source $dest
79
fi
80
}
81
82
create_partitions() {
83
local image_loop=$(realpath -m "${1}")
84
local kernel_path=$(realpath -m "${2}")
85
local is_luks="${3}"
86
local crypt_password="${4}"
87
88
#create stateful
89
mkfs.ext4 "${image_loop}p1"
90
#copy kernel
91
dd if=$kernel_path of="${image_loop}p2" bs=1M oflag=sync
92
make_bootable $image_loop
93
#create bootloader partition
94
mkfs.ext2 "${image_loop}p3"
95
#create rootfs partition
96
if [ "$is_luks" ]; then
97
echo "$crypt_password" | cryptsetup luksFormat "${image_loop}p4"
98
echo "$crypt_password" | cryptsetup luksOpen "${image_loop}p4" rootfs
99
mkfs.ext4 /dev/mapper/rootfs
100
else
101
mkfs.ext4 "${image_loop}p4"
102
fi
103
}
104
105
populate_partitions() {
106
local image_loop=$(realpath -m "${1}")
107
local bootloader_dir=$(realpath -m "${2}")
108
local rootfs_dir=$(realpath -m "${3}")
109
local quiet="$4"
110
local luks_enabled="$5"
111
112
#figure out if we are on a stable release
113
local git_tag="$(git tag -l --contains HEAD)"
114
local git_hash="$(git rev-parse --short HEAD)"
115
116
#mount and write empty file to stateful
117
local stateful_mount=/tmp/shim_stateful
118
safe_mount "${image_loop}p1" $stateful_mount
119
mkdir -p $stateful_mount/dev_image/etc/
120
mkdir -p $stateful_mount/dev_image/factory/sh
121
touch $stateful_mount/dev_image/etc/lsb-factory
122
umount $stateful_mount
123
124
#mount and write to bootloader rootfs
125
local bootloader_mount="/tmp/shim_bootloader"
126
safe_mount "${image_loop}p3" "$bootloader_mount"
127
cp -arv $bootloader_dir/* "$bootloader_mount"
128
if [ ! "$git_tag" ]; then #mark it as a dev version if needed
129
printf "$git_hash" > "$bootloader_mount/opt/.shimboot_version_dev"
130
fi
131
umount "$bootloader_mount"
132
133
#write rootfs to image
134
local rootfs_mount=/tmp/new_rootfs
135
if [ "$luks_enabled" ]; then
136
safe_mount /dev/mapper/rootfs $rootfs_mount
137
else
138
safe_mount "${image_loop}p4" $rootfs_mount
139
fi
140
141
if [ "$quiet" ]; then
142
cp -ar $rootfs_dir/* $rootfs_mount
143
else
144
copy_progress $rootfs_dir $rootfs_mount
145
fi
146
umount $rootfs_mount
147
if [ "$luks_enabled" ]; then
148
cryptsetup close rootfs
149
fi
150
}
151
152
create_image() {
153
local image_path=$(realpath -m "${1}")
154
local bootloader_size="$2"
155
local rootfs_size="$3"
156
local rootfs_name="$4"
157
158
#stateful + kernel + bootloader + rootfs
159
local total_size=$((1 + 32 + $bootloader_size + $rootfs_size))
160
rm -rf "${image_path}"
161
fallocate -l "${total_size}M" "${image_path}"
162
partition_disk $image_path $bootloader_size $rootfs_name
163
}
164
165
patch_initramfs() {
166
local initramfs_path=$(realpath -m $1)
167
168
rm "${initramfs_path}/init" -f
169
cp -r bootloader/* "${initramfs_path}/"
170
171
find ${initramfs_path}/bin -name "*" -exec chmod +x {} \;
172
}
173
174
#clean up unused loop devices
175
clean_loops() {
176
local loop_devices="$(losetup -a | awk -F':' {'print $1'})"
177
for loop_device in $loop_devices; do
178
local mountpoints="$(cat /proc/mounts | grep "$loop_device")"
179
if [ ! "$mountpoints" ]; then
180
losetup -d $loop_device
181
fi
182
done
183
}
184
185
copy_progress() {
186
local source="$1"
187
local destination="$2"
188
local total_bytes="$(du -sb "$source" | cut -f1)"
189
mkdir -p "$destination"
190
tar -cf - -C "${source}" . | pv -f -s $total_bytes | tar -xf - -C "${destination}"
191
}
192
193