-
Notifications
You must be signed in to change notification settings - Fork 120
/
Copy path1-bootfiles
187 lines (172 loc) · 5.89 KB
/
1-bootfiles
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
#!/bin/sh
#
#
# Script to deploy the boot files from rootfs to the boot partition
#
# This hook is meant to run in the `next` resinOS container
#
# Will skip files that are either blacklisted, or are flagged by the do_skip()
# function. The latter is typically defined in the `os-helpers-sb` script
# used in secure boot enabled systems to discriminate the destination boot
# partition to install into.
set -o errexit
# shellcheck disable=SC1091
. /usr/sbin/balena-config-vars
# shellcheck disable=SC1091
. /usr/libexec/os-helpers-logging
# shellcheck disable=SC1091
[ -f /usr/libexec/os-helpers-sb ] && . /usr/libexec/os-helpers-sb
# shellcheck disable=SC1091
. /usr/sbin/balena-config-defaults
# shellcheck disable=SC1091
command -v generate_bootpart_fingerprint > /dev/null || . /usr/libexec/os-helpers-fs
# Define the boot partition mountpoint depending on the calling script name
# On secure boot systems that split the boot partition the script is called with different names
boot_mountpoint="${BALENA_BOOT_MOUNTPOINT}"
[ $(basename "$0") != "1-bootfiles" ] && boot_mountpoint="${BALENA_NONENC_BOOT_MOUNTPOINT}"
# Variables
boot_fingerprint="@BALENA_BOOT_FINGERPRINT@"
bootfiles_blacklist="@BALENA_BOOTFILES_BLACKLIST@"
DURING_UPDATE=${DURING_UPDATE:-0}
# Checks if a file is present in the blacklist
# Arguments:
# $1: file to be checked
# Return value:
# 0: file is blacklisted
# 1: file is not blacklisted
isBlacklisted() {
local _file="$1"
for b in $bootfiles_blacklist; do
if [ "$b" = "$_file" ]; then
return 0
fi
done
return 1
}
# Checks if a file was modified by verifying its fingerprint
# Arguments:
# $1: file to be checked
# Return value:
# 0: file is modified
# 1: file is not modified
isModified() {
local _file="$1"
local _current_md5
_current_md5=$("${CAT}" "$boot_mountpoint/$_file" | md5sum | awk '{print $1}')
local _initial_md5
# Boot partition fingerprint use relative paths
_initial_md5=$("${CAT}" "$boot_mountpoint/$boot_fingerprint" | grep "$(echo "${_file}" | sed 's/^\///')" | awk '{print $1}')
if [ "$_current_md5" != "$_initial_md5" ]; then
return 0
else
return 1
fi
}
# Copies a file from /resin-boot to boot partition filesystem atomically and durable
# Arguments:
# $1: boot partition file
copyBootFile() {
local _file="$1"
mkdir -p "$boot_mountpoint/$(dirname "$_file")"
if ! "${UCP}" "/resin-boot/$_file" "$boot_mountpoint/$_file"; then
if [ "$DURING_UPDATE" = "1" ]; then
# Cleanup all new files we deployed
for file in $new_deployed_files; do
rm -f "$boot_mountpoint/$file"
done
exit 1
fi
fi
}
# Deploys files to boot partition
# Arguments:
# $1: file path relative to boot partition's root
deploy() {
local _file="$1"
if type do_skip >/dev/null 2>&1 && do_skip "$_file"; then
return
fi
info "Deploying ${boot_mountpoint}${_file}"
if isBlacklisted "$_file"; then
if [ "$_file" = "/splash/balena-logo.png" ]; then
if [ -f "$boot_mountpoint/splash/resin-logo.png" ]; then
if isModified "/splash/resin-logo.png"; then
# Keep custom logo
info "renaming resin-logo to balena-logo..."
sync -f "$boot_mountpoint"
"${MV}" "$boot_mountpoint/splash/resin-logo.png" "$boot_mountpoint/splash/balena-logo.png"
sync -f "$boot_mountpoint"
else
# This rebrands from old resin logo
info "replacing resin-logo with balena-logo..."
copyBootFile "$_file"
rm "$boot_mountpoint/splash/resin-logo.png"
fi
info "Deployed ${boot_mountpoint}${_file}.\n"
return
fi
elif [ "$_file" = "/config.json" ]; then
development_mode="$("${CAT}" "${boot_mountpoint}$_file" | jq -r ".developmentMode")"
if [ -z "${development_mode}" ] || [ "${development_mode}" = "null" ]; then
# Only configure developmentMode if updating from a legacy development image
old_os_os_release=$(find "/mnt/sysroot/active" -path "*/etc/os-release")
if grep -i -q 'VARIANT="Development"' "${old_os_os_release}"; then
"${CAT}" "${boot_mountpoint}/config.json" | jq -S ".developmentMode=true" | "${WR}" "${boot_mountpoint}/config.json"
info "Development mode set in new OS... "
fi
fi
fi
info "${boot_mountpoint}${_file} blacklisted. Ignoring."
else
if [ -f "$boot_mountpoint/$_file" ]; then
if isModified "$_file"; then
info " overwriting modified file ${boot_mountpoint}${_file}..."
copyBootFile "$_file"
else
copyBootFile "$_file"
fi
else
new_deployed_files="$new_deployed_files $_file"
info " new file ${boot_mountpoint}${_file}..."
copyBootFile "$_file"
fi
fi
}
#
# MAIN
#
# Do a dry run for copying the boot files and figure out if we would get in an
# out of space situation
boot_space="$(df -B1 --output=avail "$boot_mountpoint" | grep -v Avail)"
available="$boot_space"
available_threshold="524288" # All sizes in bytes
for filepath in $(find /resin-boot -type f | sed 's#^/resin-boot##g'); do
if type do_skip >/dev/null 2>&1 && do_skip "$filepath"; then
continue
fi
if isBlacklisted "$filepath"; then
continue
fi
filesize=$(stat --format %s "/resin-boot${filepath}")
available="$((available - filesize))"
if [ "$available" -lt "$available_threshold" ]; then
error "Boot files copy operations will fail with out of space error."
if [ "$DURING_UPDATE" = "1" ]; then
exit 1
fi
fi
if [ -f "${boot_mountpoint}${filepath}" ]; then
available="$((available + $(stat --format %s "${boot_mountpoint}${filepath}")))"
fi
done
info "Boot partition can accomodate the new update."
find -L "${boot_mountpoint}" $(printf "! -name %s " $(for blacklisted_file in $bootfiles_blacklist; do echo $blacklisted_file | awk -F'/' '{print $NF}'; done)) -exec touch {} +
info "Updated timestamps for all files in ${boot_mountpoint}"
# Deploy all files in the bootfiles list except fingerprint
new_deployed_files=""
for filepath in $(find /resin-boot -type f | sed 's#^/resin-boot##g'); do
if [ "$filepath" != "/$boot_fingerprint" ]; then
deploy "$filepath"
fi
done
generate_bootpart_fingerprint "${boot_mountpoint}"