blob: 12c6c762b3714d2622171fa0c754e5a9c4ca9054 [file] [log] [blame]
Gunnar Millsbde58222018-01-22 18:29:31 -06001#!/bin/bash
2set -eo pipefail
Adriana Kobylaka290eff2017-06-27 09:39:57 -05003
Adriana Kobylak54c9f792017-08-17 14:08:20 -05004# Get the root mtd device number (mtdX) from "/dev/ubiblockX_Y on /"
5findrootmtd() {
6 rootmatch=" on / "
7 m="$(mount | grep "${rootmatch}" | grep "ubiblock")"
8 m="${m##*ubiblock}"
9 m="${m%_*}"
10 if [ -z "${m}" ]; then
11 # default to bmc mtd (0)
12 m=0
13 fi
14 echo "mtd${m}"
15}
16
Adriana Kobylak582bdea2017-08-22 14:51:18 -050017findrootubi() {
18 rootmatch=" on / "
19 m="$(mount | grep "${rootmatch}")"
20 m="${m##*ubiblock}"
21 m="${m% on*}"
22 echo "ubi${m}"
23}
24
Adriana Kobylaka290eff2017-06-27 09:39:57 -050025# Get the mtd device number (mtdX)
26findmtd() {
27 m="$(grep -xl "$1" /sys/class/mtd/*/name)"
28 m="${m%/name}"
29 m="${m##*/}"
30 echo "${m}"
31}
32
Eddie Jamesa804bc42018-02-01 16:46:40 -060033# Get the mtd device number only (return X of mtdX)
34findmtdnum() {
35 m="$(findmtd "$1")"
36 m="${m##mtd}"
37 echo "${m}"
38}
39
Adriana Kobylaka290eff2017-06-27 09:39:57 -050040# Get the ubi device number (ubiX_Y)
41findubi() {
42 u="$(grep -xl "$1" /sys/class/ubi/ubi?/subsystem/ubi*/name)"
43 u="${u%/name}"
44 u="${u##*/}"
45 echo "${u}"
46}
47
Adriana Kobylakac5ce002017-09-13 12:59:26 -050048# Get the ubi device number (ubiX_Y) on a specific mtd
Adriana Kobylak582bdea2017-08-22 14:51:18 -050049findubi_onmtd() {
Adriana Kobylakac5ce002017-09-13 12:59:26 -050050 u="$(grep -xl "$1" /sys/class/ubi/ubi"$2"/subsystem/ubi"$2"*/name)"
51 u="${u%/name}"
52 u="${u##*/}"
53 echo "${u}"
54}
55
56# Get all ubi device names on a specific mtd that match requested string
57findubiname_onmtd() {
Adriana Kobylak582bdea2017-08-22 14:51:18 -050058 u="$(grep -h "$1" /sys/class/ubi/ubi"$2"/subsystem/ubi"$2"*/name)"
59 u="${u%/name}"
60 u="${u##*/}"
61 echo "${u}"
62}
63
Adriana Kobylakac5ce002017-09-13 12:59:26 -050064# Get the name from the requested ubiX_Y volume
65findname() {
66 n="$(cat /sys/class/ubi/$1/name)"
67 echo "${n}"
68}
69
Adriana Kobylak582bdea2017-08-22 14:51:18 -050070# Make space on flash before creating new volumes. This can be enhanced
71# determine current flash usage. For now only keep a "keepmax" number of them
72ubi_remove_volumes()
73{
Adriana Kobylak582bdea2017-08-22 14:51:18 -050074 rootubi="$(findrootubi)"
Adriana Kobylakac5ce002017-09-13 12:59:26 -050075 rootname="$(findname "${rootubi}")"
76 rootversion="${rootname##*-}"
77 rootkernel="kernel-${rootversion}"
Adriana Kobylak582bdea2017-08-22 14:51:18 -050078
79 # Just keep max number of volumes before updating, don't delete the version
80 # the BMC is booted from, and when a version is identified to be deleted,
81 # delete both the rofs and kernel volumes for that version.
Adriana Kobylakac5ce002017-09-13 12:59:26 -050082 rmnames="$(findubiname_onmtd "${name%-*}-" "${ro}")"
Adriana Kobylak582bdea2017-08-22 14:51:18 -050083 rmnames=(${rmnames})
84 ubicount="${#rmnames[@]}"
85 while [ ${ubicount} -ge ${keepmax} ]; do
86 # Loop through existing volumes and skip currently active ones
87 for (( index=0; index<${#rmnames[@]}; index++ )); do
88 rmname="${rmnames[${index}]}"
89 rmversion="${rmname##*-}"
Adriana Kobylakac5ce002017-09-13 12:59:26 -050090 [ "${rmversion}" == "${version}" ] && continue
91 rmubi="$(findubi_onmtd "rofs-${rmversion}" "${ro}")"
Adriana Kobylak582bdea2017-08-22 14:51:18 -050092 if [[ ( "${rmubi}" != "${rootubi}" ) &&
Adriana Kobylakac5ce002017-09-13 12:59:26 -050093 ( "${rmname}" != "${rootkernel}" ) ]]; then
94 ubi_remove "rofs-${rmversion}" "${ro}"
95 ubi_remove "kernel-${rmversion}" "${ro}"
96 # Remove priority value
97 fw_setenv "${rmversion}"
Adriana Kobylak582bdea2017-08-22 14:51:18 -050098 break
99 fi
100 done
101 # Decrease count regardless to avoid an infinite loop
102 (( ubicount-- ))
103 done
104}
105
Adriana Kobylaka290eff2017-06-27 09:39:57 -0500106ubi_rw() {
107 rwmtd="$(findmtd "${reqmtd}")"
108 rw="${rwmtd#mtd}"
109 ubidev="/dev/ubi${rw}"
110
111 # Create a ubi volume of size 4MB, that is the current size of the rwfs image
112 vol="$(findubi "${name}")"
113 if [ -z "${vol}" ]; then
114 ubimkvol "${ubidev}" -N "${name}" -s 4MiB
115 fi
116}
117
Adriana Kobylake9939492017-07-11 11:34:23 -0500118ubi_ro() {
Adriana Kobylak582bdea2017-08-22 14:51:18 -0500119 keepmax=2 # Default 2 volumes per mtd
Adriana Kobylake9939492017-07-11 11:34:23 -0500120 romtd="$(findmtd "${reqmtd}")"
Adriana Kobylak54c9f792017-08-17 14:08:20 -0500121 romtd2="$(findmtd "${reqmtd2}")"
122
123 if [ ! "${romtd}" == "${romtd2}" ]; then
124 # Request to use alternate mtd device, choose the non-root one
Adriana Kobylak582bdea2017-08-22 14:51:18 -0500125 keepmax=1 # 1 volume on each of the requested mtds
Adriana Kobylak54c9f792017-08-17 14:08:20 -0500126 rootmtd="$(findrootmtd)"
127 if [ "${rootmtd}" == "${romtd}" ]; then
128 romtd="${romtd2}"
129 fi
130 fi
Adriana Kobylake9939492017-07-11 11:34:23 -0500131 ro="${romtd#mtd}"
132 ubidev="/dev/ubi${ro}"
133
Adriana Kobylak582bdea2017-08-22 14:51:18 -0500134 ubi_remove_volumes
135
Michael Tritzd8ac7f22018-02-07 17:04:07 -0600136 if [ -z "${imgfile}" ]; then
137 echo "Unable to create read-only volume. Image file not specified."
138 return 1
139 fi
140
141 # Create a ubi volume, dynamically sized to fit BMC image if size unspecified
142 img="/tmp/images/${version}/${imgfile}"
143 imgsize="$(stat -c '%s' ${img})"
144
Adriana Kobylake9939492017-07-11 11:34:23 -0500145 vol="$(findubi "${name}")"
Adriana Kobylakddc9dca2017-09-05 15:44:35 -0500146 if [ ! -z "${vol}" ]; then
147 # Allow a duplicate kernel volume on the alt mtd
148 if [[ "${name}" =~ "kernel" ]]; then
Adriana Kobylakac5ce002017-09-13 12:59:26 -0500149 vol="$(findubi_onmtd "${name}" "${ro}")"
Adriana Kobylakddc9dca2017-09-05 15:44:35 -0500150 fi
151 fi
Adriana Kobylake9939492017-07-11 11:34:23 -0500152 if [ -z "${vol}" ]; then
153 ubimkvol "${ubidev}" -N "${name}" -s "${imgsize}" --type=static
154 vol="$(findubi "${name}")"
155 fi
156}
157
158# Squashfs images need a ubi block
159ubi_block() {
160 vol="$(findubi "${name}")"
161 ubidevid="${vol#ubi}"
162 block="/dev/ubiblock${ubidevid}"
163 if [ ! -e "$block" ]; then
164 ubiblock --create "/dev/ubi${ubidevid}"
165 fi
166}
167
168ubi_updatevol() {
169 vol="$(findubi "${name}")"
170 ubidevid="${vol#ubi}"
171 img="/tmp/images/${version}/${imgfile}"
172 ubiupdatevol "/dev/ubi${ubidevid}" "${img}"
173}
174
Michael Tritza694eed2017-07-13 16:26:15 -0500175ubi_remove() {
Adriana Kobylak582bdea2017-08-22 14:51:18 -0500176 rmname="$1"
Adriana Kobylakac5ce002017-09-13 12:59:26 -0500177 rmmtd="$2"
178 if [ ! -z "${rmmtd}" ]; then
179 vol="$(findubi_onmtd "${rmname}" "${rmmtd}")"
180 else
181 vol="$(findubi "${rmname}")"
182 fi
Michael Tritza694eed2017-07-13 16:26:15 -0500183
184 if [ ! -z "$vol" ]; then
185 vol="${vol%_*}"
186
Saqib Khanf8d2a662017-09-07 13:57:43 -0500187 if grep -q "$rmname" /proc/mounts; then
188 mountdir=$(grep "$rmname" /proc/mounts | cut -d " " -f 2)
Michael Tritza694eed2017-07-13 16:26:15 -0500189 umount "$mountdir"
190 rm -r "$mountdir"
191 fi
192
Adriana Kobylak582bdea2017-08-22 14:51:18 -0500193 ubirmvol "/dev/${vol}" -N "$rmname"
Michael Tritza694eed2017-07-13 16:26:15 -0500194 fi
195}
196
Michael Tritz18781172017-09-21 00:41:15 -0500197ubi_cleanup() {
198 # When ubi_cleanup is run, it expects one or no active version.
199 activeVersion=$(busctl --list --no-pager tree \
200 xyz.openbmc_project.Software.BMC.Updater | \
201 grep /xyz/openbmc_project/software/ | tail -c 9)
202
203 if [[ -z "$activeVersion" ]]; then
204 vols=$(ubinfo -a | grep -e "kernel-" -e "rofs-" | cut -c 14-)
205 vols=(${vols})
206 else
207 vols=$(ubinfo -a | grep -e "kernel-" -e "rofs-" | \
208 grep -v "$activeVersion" | cut -c 14-)
209 vols=(${vols})
210 fi
211
212 for (( index=0; index<${#vols[@]}; index++ )); do
213 ubi_remove ${vols[index]}
214 done
215}
216
Saqib Khanbb93e642017-08-10 11:24:38 -0500217remount_ubi() {
Saqib Khand6d1c442017-09-06 23:24:40 -0500218 bmcmtd="$(findmtd "bmc")"
219 altbmcmtd="$(findmtd "alt-bmc")"
220 mtds="${bmcmtd: -1}","${altbmcmtd: -1}"
Saqib Khanbb93e642017-08-10 11:24:38 -0500221
222 IFS=',' read -r -a mtds <<< "$mtds"
223 mtds=($(echo "${mtds[@]}" | tr ' ' '\n' | sort -u | tr '\n' ' '))
224 for mtd in ${mtds[@]}; do
Saqib Khanbb93e642017-08-10 11:24:38 -0500225 # Get information on all ubi volumes
226 ubinfo=$(ubinfo -d ${mtd})
227 presentVolumes=${ubinfo##*:}
228 IFS=', ' read -r -a array <<< "$presentVolumes"
229 for element in ${array[@]}; do
230 elementProperties=$(ubinfo -d $mtd -n $element)
231 # Get ubi volume name by getting rid of additional properties
232 name=${elementProperties#*Name:}
233 name="${name%Character*}"
234 name="$(echo -e "${name}" | tr -d '[:space:]')"
235
Adriana Kobylak2c7c8d12017-08-21 11:00:56 -0500236 if [[ ${name} == rofs-* ]]; then
Saqib Khanbb93e642017-08-10 11:24:38 -0500237 mountdir="/media/${name}"
Saqib Khand793f2d2017-09-13 14:05:31 -0500238
239 if [ ! -d ${mountdir} ]; then
240 mkdir -p "${mountdir}"
Gunnar Millsbde58222018-01-22 18:29:31 -0600241 # U-Boot will create the ubiblock for the running version, but not
242 # for the version on the other chip
243 if [ ! -e "/dev/ubiblock${mtd}_${element}" ]; then
244 ubiblock --create /dev/ubi${mtd}_${element}
245 fi
Saqib Khand793f2d2017-09-13 14:05:31 -0500246 mount -t squashfs -o ro "/dev/ubiblock${mtd}_${element}" "${mountdir}"
247 fi
Saqib Khanbb93e642017-08-10 11:24:38 -0500248 fi
249 done
250 done
251}
252
Adriana Kobylak8cdb82e2017-08-22 14:18:39 -0500253# Read the current env variable and set it on the alternate boot env
254copy_env_var_to_alt() {
255 varName=$1
256 value="$(fw_printenv -n "${varName}")"
257 fw_setenv -c /etc/alt_fw_env.config "${varName}" "${value}"
258}
259
Eddie Jamesa804bc42018-02-01 16:46:40 -0600260# When the alternate bmc chip boots, u-boot thinks its the primary mtdX.
261# Therefore need to swap the chip numbers when copying the ubiblock and root to
262# alternate bmc u-boot environment.
263copy_ubiblock_to_alt() {
264 value="$(fw_printenv -n ubiblock)"
265 bmcNum="$(findmtdnum "bmc")"
266 altNum="$(findmtdnum "alt-bmc")"
267 replaceAlt="${value/${altNum},/${bmcNum},}"
268
269 if [[ "${value}" == "${replaceAlt}" ]]; then
270 replaceBmc="${value/${bmcNum},/${altNum},}"
271 value=${replaceBmc}
272 else
273 value=${replaceAlt}
274 fi
275
276 fw_setenv -c /etc/alt_fw_env.config ubiblock "${value}"
277}
278
279copy_root_to_alt() {
280 value="$(fw_printenv -n root)"
281 bmcNum="$(findmtdnum "bmc")"
282 altNum="$(findmtdnum "alt-bmc")"
283 replaceAlt="${value/${altNum}_/${bmcNum}_}"
284
285 if [[ "${value}" == "${replaceAlt}" ]]; then
286 replaceBmc="${value/${bmcNum}_/${altNum}_}"
287 value=${replaceBmc}
288 else
289 value=${replaceAlt}
290 fi
291
292 fw_setenv -c /etc/alt_fw_env.config root "${value}"
293}
294
Michael Tritza694eed2017-07-13 16:26:15 -0500295ubi_setenv() {
Michael Tritz3e0b0672017-12-15 15:35:14 -0600296 # The U-Boot environment maintains two banks of environment variables.
297 # The banks need to be consistent with each other to ensure that these
298 # variables can reliably be read from file. In order to guarantee that the
299 # banks are both correct, we need to run fw_setenv twice.
Adriana Kobylak8cdb82e2017-08-22 14:18:39 -0500300 variable=$1
Michael Tritz8863f702017-08-25 15:47:07 -0500301 if [[ "$variable" == *"="* ]]; then
302 varName="${variable%=*}"
303 value="${variable##*=}"
Adriana Kobylakf5ac32c2018-02-09 11:21:57 -0600304 # Write only if var is not set already to the requested value
305 currentValue="$(fw_printenv -n "${varName}")"
306 if [[ "${currenValue}" != "${value}" ]]; then
307 fw_setenv "$varName" "$value"
308 fw_setenv "$varName" "$value"
309 fi
Michael Tritz8863f702017-08-25 15:47:07 -0500310 else
311 fw_setenv "$variable"
Michael Tritz3e0b0672017-12-15 15:35:14 -0600312 fw_setenv "$variable"
Michael Tritz8863f702017-08-25 15:47:07 -0500313 fi
Michael Tritza694eed2017-07-13 16:26:15 -0500314}
315
Adriana Kobylak1fa612c2017-08-17 21:56:14 -0500316mtd_write() {
317 flashmtd="$(findmtd "${reqmtd}")"
318 img="/tmp/images/${version}/${imgfile}"
319 flashcp -v ${img} /dev/${flashmtd}
320}
321
Adriana Kobylake2fd46d2017-09-05 12:38:19 -0500322backup_env_vars() {
323 copy_env_var_to_alt kernelname
Eddie Jamesa804bc42018-02-01 16:46:40 -0600324 copy_ubiblock_to_alt
325 copy_root_to_alt
Adriana Kobylake2fd46d2017-09-05 12:38:19 -0500326}
327
328update_env_vars() {
329 vol="$(findubi rofs-"${version}")"
330 if [ -z "${vol}" ]; then
331 return 1
332 fi
333 ubidevid="${vol#ubi}"
334 block="/dev/ubiblock${ubidevid}"
335 if [ ! -e "${block}" ]; then
336 return 1
337 fi
338 ubi_setenv "kernelname=kernel-${version}"
339 ubi_setenv "ubiblock=$(echo "${ubidevid}" | sed 's/_/,/')"
340 ubi_setenv "root=${block}"
341}
342
Saqib Khandfc9b0c2017-09-08 10:10:08 -0500343#TODO: Replace the implementation with systemd-inhibitors lock
344# once systemd/systemd#949 is resolved
345rebootguardenable() {
346 dir="/run/systemd/system/"
347 file="reboot-guard.conf"
348 units=("reboot" "poweroff" "halt")
349
350 for unit in "${units[@]}"; do
351 mkdir -p ${dir}${unit}.target.d
352 echo -e "[Unit]\nRefuseManualStart=yes" >> ${dir}${unit}.target.d/${file}
353 done
354}
355
356#TODO: Replace the implementation with systemd-inhibitors lock
357# once systemd/systemd#949 is resolved
358rebootguarddisable() {
359 dir="/run/systemd/system/"
360 file="reboot-guard.conf"
361 units=("reboot" "poweroff" "halt")
362
363 for unit in "${units[@]}"; do
364 rm -rf ${dir}${unit}.target.d/${file}
365 done
366}
367
Adriana Kobylakddc9dca2017-09-05 15:44:35 -0500368# Create a copy in the alt mtd
369create_vol_in_alt() {
370 alt="alt-bmc"
371 altmtd="$(findmtd "${alt}")"
372 if [ ! -z "${altmtd}" ]; then
373 reqmtd="${alt}"
374 reqmtd2="${alt}"
375 ubi_ro
376 ubi_updatevol
377 fi
378}
379
Adriana Kobylaka290eff2017-06-27 09:39:57 -0500380case "$1" in
Adriana Kobylak1fa612c2017-08-17 21:56:14 -0500381 mtduboot)
382 reqmtd="$2"
383 version="$3"
384 imgfile="image-u-boot"
385 mtd_write
386 ;;
Adriana Kobylaka290eff2017-06-27 09:39:57 -0500387 ubirw)
388 reqmtd="$2"
389 name="$3"
390 ubi_rw
391 ;;
Adriana Kobylake9939492017-07-11 11:34:23 -0500392 ubiro)
Adriana Kobylak54c9f792017-08-17 14:08:20 -0500393 reqmtd="$(echo "$2" | cut -d "+" -f 1)"
394 reqmtd2="$(echo "$2" | cut -d "+" -f 2)"
Adriana Kobylake9939492017-07-11 11:34:23 -0500395 name="$3"
396 version="$4"
397 imgfile="image-rofs"
Adriana Kobylake9939492017-07-11 11:34:23 -0500398 ubi_ro
Adriana Kobylake9939492017-07-11 11:34:23 -0500399 ubi_updatevol
Adriana Kobylak8cdb82e2017-08-22 14:18:39 -0500400 ubi_block
Adriana Kobylake9939492017-07-11 11:34:23 -0500401 ;;
402 ubikernel)
Adriana Kobylak54c9f792017-08-17 14:08:20 -0500403 reqmtd="$(echo "$2" | cut -d "+" -f 1)"
404 reqmtd2="$(echo "$2" | cut -d "+" -f 2)"
Adriana Kobylake9939492017-07-11 11:34:23 -0500405 name="$3"
406 version="$4"
407 imgfile="image-kernel"
Adriana Kobylake9939492017-07-11 11:34:23 -0500408 ubi_ro
409 ubi_updatevol
Adriana Kobylakddc9dca2017-09-05 15:44:35 -0500410 create_vol_in_alt
Adriana Kobylake9939492017-07-11 11:34:23 -0500411 ;;
Michael Tritza694eed2017-07-13 16:26:15 -0500412 ubiremove)
413 name="$2"
Adriana Kobylak582bdea2017-08-22 14:51:18 -0500414 ubi_remove "${name}"
Michael Tritza694eed2017-07-13 16:26:15 -0500415 ;;
Michael Tritz18781172017-09-21 00:41:15 -0500416 ubicleanup)
417 ubi_cleanup
418 ;;
Michael Tritza694eed2017-07-13 16:26:15 -0500419 ubisetenv)
Adriana Kobylak8cdb82e2017-08-22 14:18:39 -0500420 ubi_setenv "$2"
Michael Tritza694eed2017-07-13 16:26:15 -0500421 ;;
Saqib Khanbb93e642017-08-10 11:24:38 -0500422 ubiremount)
423 remount_ubi
424 ;;
Saqib Khan7e4a3f22017-09-12 09:23:28 -0500425 createenvbackup)
Adriana Kobylake2fd46d2017-09-05 12:38:19 -0500426 backup_env_vars
427 ;;
Saqib Khan7e4a3f22017-09-12 09:23:28 -0500428 updateubootvars)
Adriana Kobylake2fd46d2017-09-05 12:38:19 -0500429 version="$2"
430 update_env_vars
431 ;;
Saqib Khandfc9b0c2017-09-08 10:10:08 -0500432 rebootguardenable)
433 rebootguardenable
434 ;;
435 rebootguarddisable)
436 rebootguarddisable
437 ;;
Adriana Kobylaka290eff2017-06-27 09:39:57 -0500438 *)
439 echo "Invalid argument"
440 exit 1
441 ;;
442esac