-
Notifications
You must be signed in to change notification settings - Fork 117
/
Copy pathabroot
120 lines (97 loc) · 3.54 KB
/
abroot
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
#!/bin/sh
# shellcheck disable=SC1091
. /usr/libexec/os-helpers-logging
. /usr/sbin/balena-config-defaults
BOOT_MOUNT="/bootfs"
BOOTENV_FILENAME="bootenv"
find_boot_partition() {
BOOT_LABEL_CANDIDATES="${BALENA_BOOT_LABEL} resin-boot"
if [ "${BALENA_NONENC_BOOT_LABEL}" != "${BALENA_BOOT_LABEL}" ]; then
BOOT_LABEL_CANDIDATES="${BALENA_NONENC_BOOT_LABEL} ${BOOT_LABEL_CANDIDATES}"
fi
for LABEL in ${BOOT_LABEL_CANDIDATES}; do
BY_LABEL_PATH="/dev/disk/by-label/${LABEL}"
if [ -L "${BY_LABEL_PATH}" ]; then
echo "${BY_LABEL_PATH}"
break
fi
done
}
get_bootenv() {
BOOTENV_FILE="$1"
KEY="$2"
grub-editenv "${BOOTENV_FILE}" list | grep "^${KEY}=" | sed -e "s,^${KEY}=\(.*\)$,\1,"
}
abroot_enabled() {
if [ "$bootparam_balena_stage2" != "true" ]
then
return 1
fi
if [ "$bootparam_flasher" = "true" ]
then
return 1
fi
return 0
}
abroot_run() {
BOOT_PART=$(find_boot_partition)
# Give the boot partition 5s to appear.
# This is necessary when the rootfs is on a device that takes
# a while to initialize, such as a USB disk.
# Similar waiting already happens in the rootfs script, because
# on most device types it is the first one that needs to access
# the root device. But in the case of balena bootloader, the abroot
# script is called before rootfs, so it needs to do the waiting.
C=0
delay=${bootparam_rootdelay:-1}
timeout=${bootparam_roottimeout:-5}
while [ -z "${BOOT_PART}" ]; do
C=$(( C + 1 ))
if [ $(( C * delay )) -gt "$timeout" ]; then
fail "Failed to identify boot partition"
fi
sleep "${delay}"
BOOT_PART=$(find_boot_partition)
done
BOOT_DEV="/dev/$(lsblk -nlo pkname ${BOOT_PART})"
mkdir -p "${BOOT_MOUNT}"
mount "${BOOT_PART}" "${BOOT_MOUNT}"
BOOTENV_FILE=$(find "${BOOT_MOUNT}" -name "${BOOTENV_FILENAME}")
BOOTENV_COUNT=$(echo "${BOOTENV_FILE}" | wc -w)
if [ "${BOOTENV_COUNT}" -eq 0 ]; then
umount "${BOOT_MOUNT}"
fail "Boot environment file not found"
fi
if [ "${BOOTENV_COUNT}" -gt 1 ]; then
# If multiple bootenv files are found, use the first one
# This is unexpected and non-deterministic and while normally
# it would be preferrable to fail at this point, this is early
# boot stage and in this particular situation we choose to guess
# as it increases the chance to succeed and not brick the device
for BOOTENV_ONE_FILE in ${BOOTENV_FILE}; do
BOOTENV_FILE="${BOOTENV_ONE_FILE}"
warn "Multiple boot environment files found"
warn "Will use '${BOOTENV_FILE}' and hope for the best"
break
done
fi
ROOT_PART=$(get_bootenv "${BOOTENV_FILE}" "resin_root_part")
BOOT_COUNT=$(get_bootenv "${BOOTENV_FILE}" "bootcount")
UPGRADE_AVAILABLE=$(get_bootenv "${BOOTENV_FILE}" "upgrade_available")
if [ "${UPGRADE_AVAILABLE}" -eq 1 ]; then
BOOT_COUNT=$["${BOOT_COUNT}" + 1]
grub-editenv "${BOOTENV_FILE}" set "bootcount=${BOOT_COUNT}"
fi
# Rollback if this is the 3rd boot attempt
if [ "${BOOT_COUNT}" -ge 3 ]; then
if [ "${ROOT_PART}" = "A" ]; then
ROOT_PART="B"
else
ROOT_PART="A"
fi
fi
ROOT_UUID=$(lsblk -nlo uuid,label "${BOOT_DEV}" | grep "\(balena\|resin\)-root${ROOT_PART}" | cut -f1 -d " ")
# Switch between rootA and rootB
export bootparam_root=UUID=${ROOT_UUID}
umount "${BOOT_MOUNT}"
}