blob: 899d0f049f3ad3ef5e602fd665686e93ea1637b0 [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
Edward A. Jamesa1cb3232017-11-09 16:03:14 -060070# Set the u-boot env command that performs the factory reset if requested
71set_do_rwreset() {
72 if ! fw_printenv do_rwreset; then
73 fw_setenv do_rwreset "if test \"\${rwreset}\" = \"true\"; then ubi remove rwfs; ubi create rwfs 0x400000; fi"
74 fw_setenv obmc_bootcmd "ubi part obmc-ubi; run do_rwreset; ubi read \${loadaddr} \${kernelname}; bootm \${loadaddr}"
75 fi
76}
77
Adriana Kobylak582bdea2017-08-22 14:51:18 -050078# Make space on flash before creating new volumes. This can be enhanced
79# determine current flash usage. For now only keep a "keepmax" number of them
80ubi_remove_volumes()
81{
Adriana Kobylak582bdea2017-08-22 14:51:18 -050082 rootubi="$(findrootubi)"
Adriana Kobylakac5ce002017-09-13 12:59:26 -050083 rootname="$(findname "${rootubi}")"
84 rootversion="${rootname##*-}"
85 rootkernel="kernel-${rootversion}"
Adriana Kobylak582bdea2017-08-22 14:51:18 -050086
87 # Just keep max number of volumes before updating, don't delete the version
88 # the BMC is booted from, and when a version is identified to be deleted,
89 # delete both the rofs and kernel volumes for that version.
Adriana Kobylakac5ce002017-09-13 12:59:26 -050090 rmnames="$(findubiname_onmtd "${name%-*}-" "${ro}")"
Adriana Kobylak582bdea2017-08-22 14:51:18 -050091 rmnames=(${rmnames})
92 ubicount="${#rmnames[@]}"
93 while [ ${ubicount} -ge ${keepmax} ]; do
94 # Loop through existing volumes and skip currently active ones
95 for (( index=0; index<${#rmnames[@]}; index++ )); do
96 rmname="${rmnames[${index}]}"
97 rmversion="${rmname##*-}"
Adriana Kobylakac5ce002017-09-13 12:59:26 -050098 [ "${rmversion}" == "${version}" ] && continue
99 rmubi="$(findubi_onmtd "rofs-${rmversion}" "${ro}")"
Adriana Kobylak582bdea2017-08-22 14:51:18 -0500100 if [[ ( "${rmubi}" != "${rootubi}" ) &&
Adriana Kobylakac5ce002017-09-13 12:59:26 -0500101 ( "${rmname}" != "${rootkernel}" ) ]]; then
102 ubi_remove "rofs-${rmversion}" "${ro}"
103 ubi_remove "kernel-${rmversion}" "${ro}"
104 # Remove priority value
105 fw_setenv "${rmversion}"
Adriana Kobylak582bdea2017-08-22 14:51:18 -0500106 break
107 fi
108 done
109 # Decrease count regardless to avoid an infinite loop
110 (( ubicount-- ))
111 done
112}
113
Adriana Kobylaka290eff2017-06-27 09:39:57 -0500114ubi_rw() {
115 rwmtd="$(findmtd "${reqmtd}")"
116 rw="${rwmtd#mtd}"
117 ubidev="/dev/ubi${rw}"
118
119 # Create a ubi volume of size 4MB, that is the current size of the rwfs image
120 vol="$(findubi "${name}")"
121 if [ -z "${vol}" ]; then
122 ubimkvol "${ubidev}" -N "${name}" -s 4MiB
123 fi
124}
125
Adriana Kobylake9939492017-07-11 11:34:23 -0500126ubi_ro() {
Adriana Kobylak582bdea2017-08-22 14:51:18 -0500127 keepmax=2 # Default 2 volumes per mtd
Adriana Kobylake9939492017-07-11 11:34:23 -0500128 romtd="$(findmtd "${reqmtd}")"
Adriana Kobylak54c9f792017-08-17 14:08:20 -0500129 romtd2="$(findmtd "${reqmtd2}")"
130
131 if [ ! "${romtd}" == "${romtd2}" ]; then
132 # Request to use alternate mtd device, choose the non-root one
Adriana Kobylak582bdea2017-08-22 14:51:18 -0500133 keepmax=1 # 1 volume on each of the requested mtds
Adriana Kobylak54c9f792017-08-17 14:08:20 -0500134 rootmtd="$(findrootmtd)"
135 if [ "${rootmtd}" == "${romtd}" ]; then
136 romtd="${romtd2}"
137 fi
138 fi
Adriana Kobylake9939492017-07-11 11:34:23 -0500139 ro="${romtd#mtd}"
140 ubidev="/dev/ubi${ro}"
141
Adriana Kobylak582bdea2017-08-22 14:51:18 -0500142 ubi_remove_volumes
143
Michael Tritzd8ac7f22018-02-07 17:04:07 -0600144 if [ -z "${imgfile}" ]; then
145 echo "Unable to create read-only volume. Image file not specified."
146 return 1
147 fi
148
149 # Create a ubi volume, dynamically sized to fit BMC image if size unspecified
150 img="/tmp/images/${version}/${imgfile}"
151 imgsize="$(stat -c '%s' ${img})"
152
Adriana Kobylake9939492017-07-11 11:34:23 -0500153 vol="$(findubi "${name}")"
Adriana Kobylakddc9dca2017-09-05 15:44:35 -0500154 if [ ! -z "${vol}" ]; then
155 # Allow a duplicate kernel volume on the alt mtd
156 if [[ "${name}" =~ "kernel" ]]; then
Adriana Kobylakac5ce002017-09-13 12:59:26 -0500157 vol="$(findubi_onmtd "${name}" "${ro}")"
Adriana Kobylakddc9dca2017-09-05 15:44:35 -0500158 fi
159 fi
Adriana Kobylake9939492017-07-11 11:34:23 -0500160 if [ -z "${vol}" ]; then
161 ubimkvol "${ubidev}" -N "${name}" -s "${imgsize}" --type=static
162 vol="$(findubi "${name}")"
163 fi
164}
165
166# Squashfs images need a ubi block
167ubi_block() {
168 vol="$(findubi "${name}")"
169 ubidevid="${vol#ubi}"
170 block="/dev/ubiblock${ubidevid}"
171 if [ ! -e "$block" ]; then
172 ubiblock --create "/dev/ubi${ubidevid}"
173 fi
174}
175
176ubi_updatevol() {
177 vol="$(findubi "${name}")"
178 ubidevid="${vol#ubi}"
179 img="/tmp/images/${version}/${imgfile}"
180 ubiupdatevol "/dev/ubi${ubidevid}" "${img}"
181}
182
Michael Tritza694eed2017-07-13 16:26:15 -0500183ubi_remove() {
Adriana Kobylak582bdea2017-08-22 14:51:18 -0500184 rmname="$1"
Adriana Kobylakac5ce002017-09-13 12:59:26 -0500185 rmmtd="$2"
186 if [ ! -z "${rmmtd}" ]; then
187 vol="$(findubi_onmtd "${rmname}" "${rmmtd}")"
188 else
189 vol="$(findubi "${rmname}")"
190 fi
Michael Tritza694eed2017-07-13 16:26:15 -0500191
192 if [ ! -z "$vol" ]; then
193 vol="${vol%_*}"
194
Saqib Khanf8d2a662017-09-07 13:57:43 -0500195 if grep -q "$rmname" /proc/mounts; then
196 mountdir=$(grep "$rmname" /proc/mounts | cut -d " " -f 2)
Michael Tritza694eed2017-07-13 16:26:15 -0500197 umount "$mountdir"
198 rm -r "$mountdir"
199 fi
200
Adriana Kobylak582bdea2017-08-22 14:51:18 -0500201 ubirmvol "/dev/${vol}" -N "$rmname"
Michael Tritza694eed2017-07-13 16:26:15 -0500202 fi
203}
204
Michael Tritz18781172017-09-21 00:41:15 -0500205ubi_cleanup() {
206 # When ubi_cleanup is run, it expects one or no active version.
207 activeVersion=$(busctl --list --no-pager tree \
208 xyz.openbmc_project.Software.BMC.Updater | \
209 grep /xyz/openbmc_project/software/ | tail -c 9)
210
211 if [[ -z "$activeVersion" ]]; then
212 vols=$(ubinfo -a | grep -e "kernel-" -e "rofs-" | cut -c 14-)
213 vols=(${vols})
214 else
215 vols=$(ubinfo -a | grep -e "kernel-" -e "rofs-" | \
216 grep -v "$activeVersion" | cut -c 14-)
217 vols=(${vols})
218 fi
219
220 for (( index=0; index<${#vols[@]}; index++ )); do
221 ubi_remove ${vols[index]}
222 done
223}
224
Saqib Khanbb93e642017-08-10 11:24:38 -0500225remount_ubi() {
Saqib Khand6d1c442017-09-06 23:24:40 -0500226 bmcmtd="$(findmtd "bmc")"
227 altbmcmtd="$(findmtd "alt-bmc")"
228 mtds="${bmcmtd: -1}","${altbmcmtd: -1}"
Saqib Khanbb93e642017-08-10 11:24:38 -0500229
230 IFS=',' read -r -a mtds <<< "$mtds"
231 mtds=($(echo "${mtds[@]}" | tr ' ' '\n' | sort -u | tr '\n' ' '))
232 for mtd in ${mtds[@]}; do
Saqib Khanbb93e642017-08-10 11:24:38 -0500233 # Get information on all ubi volumes
234 ubinfo=$(ubinfo -d ${mtd})
235 presentVolumes=${ubinfo##*:}
236 IFS=', ' read -r -a array <<< "$presentVolumes"
237 for element in ${array[@]}; do
238 elementProperties=$(ubinfo -d $mtd -n $element)
239 # Get ubi volume name by getting rid of additional properties
240 name=${elementProperties#*Name:}
241 name="${name%Character*}"
242 name="$(echo -e "${name}" | tr -d '[:space:]')"
243
Adriana Kobylak2c7c8d12017-08-21 11:00:56 -0500244 if [[ ${name} == rofs-* ]]; then
Saqib Khanbb93e642017-08-10 11:24:38 -0500245 mountdir="/media/${name}"
Saqib Khand793f2d2017-09-13 14:05:31 -0500246
247 if [ ! -d ${mountdir} ]; then
248 mkdir -p "${mountdir}"
Gunnar Millsbde58222018-01-22 18:29:31 -0600249 # U-Boot will create the ubiblock for the running version, but not
250 # for the version on the other chip
251 if [ ! -e "/dev/ubiblock${mtd}_${element}" ]; then
252 ubiblock --create /dev/ubi${mtd}_${element}
253 fi
Saqib Khand793f2d2017-09-13 14:05:31 -0500254 mount -t squashfs -o ro "/dev/ubiblock${mtd}_${element}" "${mountdir}"
255 fi
Saqib Khanbb93e642017-08-10 11:24:38 -0500256 fi
257 done
258 done
Edward A. Jamesa1cb3232017-11-09 16:03:14 -0600259
260 set_do_rwreset
Saqib Khanbb93e642017-08-10 11:24:38 -0500261}
262
Adriana Kobylak8cdb82e2017-08-22 14:18:39 -0500263# Read the current env variable and set it on the alternate boot env
264copy_env_var_to_alt() {
265 varName=$1
266 value="$(fw_printenv -n "${varName}")"
267 fw_setenv -c /etc/alt_fw_env.config "${varName}" "${value}"
268}
269
Eddie Jamesa804bc42018-02-01 16:46:40 -0600270# When the alternate bmc chip boots, u-boot thinks its the primary mtdX.
271# Therefore need to swap the chip numbers when copying the ubiblock and root to
272# alternate bmc u-boot environment.
273copy_ubiblock_to_alt() {
274 value="$(fw_printenv -n ubiblock)"
275 bmcNum="$(findmtdnum "bmc")"
276 altNum="$(findmtdnum "alt-bmc")"
277 replaceAlt="${value/${altNum},/${bmcNum},}"
278
279 if [[ "${value}" == "${replaceAlt}" ]]; then
280 replaceBmc="${value/${bmcNum},/${altNum},}"
281 value=${replaceBmc}
282 else
283 value=${replaceAlt}
284 fi
285
286 fw_setenv -c /etc/alt_fw_env.config ubiblock "${value}"
287}
288
289copy_root_to_alt() {
290 value="$(fw_printenv -n root)"
291 bmcNum="$(findmtdnum "bmc")"
292 altNum="$(findmtdnum "alt-bmc")"
293 replaceAlt="${value/${altNum}_/${bmcNum}_}"
294
295 if [[ "${value}" == "${replaceAlt}" ]]; then
296 replaceBmc="${value/${bmcNum}_/${altNum}_}"
297 value=${replaceBmc}
298 else
299 value=${replaceAlt}
300 fi
301
302 fw_setenv -c /etc/alt_fw_env.config root "${value}"
303}
304
Michael Tritza694eed2017-07-13 16:26:15 -0500305ubi_setenv() {
Michael Tritz3e0b0672017-12-15 15:35:14 -0600306 # The U-Boot environment maintains two banks of environment variables.
307 # The banks need to be consistent with each other to ensure that these
308 # variables can reliably be read from file. In order to guarantee that the
309 # banks are both correct, we need to run fw_setenv twice.
Adriana Kobylak8cdb82e2017-08-22 14:18:39 -0500310 variable=$1
Michael Tritz8863f702017-08-25 15:47:07 -0500311 if [[ "$variable" == *"="* ]]; then
312 varName="${variable%=*}"
313 value="${variable##*=}"
Adriana Kobylakf5ac32c2018-02-09 11:21:57 -0600314 # Write only if var is not set already to the requested value
315 currentValue="$(fw_printenv -n "${varName}")"
316 if [[ "${currenValue}" != "${value}" ]]; then
317 fw_setenv "$varName" "$value"
318 fw_setenv "$varName" "$value"
319 fi
Michael Tritz8863f702017-08-25 15:47:07 -0500320 else
321 fw_setenv "$variable"
Michael Tritz3e0b0672017-12-15 15:35:14 -0600322 fw_setenv "$variable"
Michael Tritz8863f702017-08-25 15:47:07 -0500323 fi
Michael Tritza694eed2017-07-13 16:26:15 -0500324}
325
Adriana Kobylak1fa612c2017-08-17 21:56:14 -0500326mtd_write() {
327 flashmtd="$(findmtd "${reqmtd}")"
328 img="/tmp/images/${version}/${imgfile}"
329 flashcp -v ${img} /dev/${flashmtd}
330}
331
Adriana Kobylake2fd46d2017-09-05 12:38:19 -0500332backup_env_vars() {
333 copy_env_var_to_alt kernelname
Eddie Jamesa804bc42018-02-01 16:46:40 -0600334 copy_ubiblock_to_alt
335 copy_root_to_alt
Adriana Kobylake2fd46d2017-09-05 12:38:19 -0500336}
337
338update_env_vars() {
339 vol="$(findubi rofs-"${version}")"
340 if [ -z "${vol}" ]; then
341 return 1
342 fi
343 ubidevid="${vol#ubi}"
344 block="/dev/ubiblock${ubidevid}"
345 if [ ! -e "${block}" ]; then
346 return 1
347 fi
348 ubi_setenv "kernelname=kernel-${version}"
349 ubi_setenv "ubiblock=$(echo "${ubidevid}" | sed 's/_/,/')"
350 ubi_setenv "root=${block}"
351}
352
Saqib Khandfc9b0c2017-09-08 10:10:08 -0500353#TODO: Replace the implementation with systemd-inhibitors lock
354# once systemd/systemd#949 is resolved
355rebootguardenable() {
356 dir="/run/systemd/system/"
357 file="reboot-guard.conf"
358 units=("reboot" "poweroff" "halt")
359
360 for unit in "${units[@]}"; do
361 mkdir -p ${dir}${unit}.target.d
362 echo -e "[Unit]\nRefuseManualStart=yes" >> ${dir}${unit}.target.d/${file}
363 done
364}
365
366#TODO: Replace the implementation with systemd-inhibitors lock
367# once systemd/systemd#949 is resolved
368rebootguarddisable() {
369 dir="/run/systemd/system/"
370 file="reboot-guard.conf"
371 units=("reboot" "poweroff" "halt")
372
373 for unit in "${units[@]}"; do
374 rm -rf ${dir}${unit}.target.d/${file}
375 done
376}
377
Adriana Kobylakddc9dca2017-09-05 15:44:35 -0500378# Create a copy in the alt mtd
379create_vol_in_alt() {
380 alt="alt-bmc"
381 altmtd="$(findmtd "${alt}")"
382 if [ ! -z "${altmtd}" ]; then
383 reqmtd="${alt}"
384 reqmtd2="${alt}"
385 ubi_ro
386 ubi_updatevol
387 fi
388}
389
Adriana Kobylaka290eff2017-06-27 09:39:57 -0500390case "$1" in
Adriana Kobylak1fa612c2017-08-17 21:56:14 -0500391 mtduboot)
392 reqmtd="$2"
393 version="$3"
394 imgfile="image-u-boot"
395 mtd_write
396 ;;
Adriana Kobylaka290eff2017-06-27 09:39:57 -0500397 ubirw)
398 reqmtd="$2"
399 name="$3"
400 ubi_rw
401 ;;
Adriana Kobylake9939492017-07-11 11:34:23 -0500402 ubiro)
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-rofs"
Adriana Kobylake9939492017-07-11 11:34:23 -0500408 ubi_ro
Adriana Kobylake9939492017-07-11 11:34:23 -0500409 ubi_updatevol
Adriana Kobylak8cdb82e2017-08-22 14:18:39 -0500410 ubi_block
Adriana Kobylake9939492017-07-11 11:34:23 -0500411 ;;
412 ubikernel)
Adriana Kobylak54c9f792017-08-17 14:08:20 -0500413 reqmtd="$(echo "$2" | cut -d "+" -f 1)"
414 reqmtd2="$(echo "$2" | cut -d "+" -f 2)"
Adriana Kobylake9939492017-07-11 11:34:23 -0500415 name="$3"
416 version="$4"
417 imgfile="image-kernel"
Adriana Kobylake9939492017-07-11 11:34:23 -0500418 ubi_ro
419 ubi_updatevol
Adriana Kobylakddc9dca2017-09-05 15:44:35 -0500420 create_vol_in_alt
Adriana Kobylake9939492017-07-11 11:34:23 -0500421 ;;
Michael Tritza694eed2017-07-13 16:26:15 -0500422 ubiremove)
423 name="$2"
Adriana Kobylak582bdea2017-08-22 14:51:18 -0500424 ubi_remove "${name}"
Michael Tritza694eed2017-07-13 16:26:15 -0500425 ;;
Michael Tritz18781172017-09-21 00:41:15 -0500426 ubicleanup)
427 ubi_cleanup
428 ;;
Michael Tritza694eed2017-07-13 16:26:15 -0500429 ubisetenv)
Adriana Kobylak8cdb82e2017-08-22 14:18:39 -0500430 ubi_setenv "$2"
Michael Tritza694eed2017-07-13 16:26:15 -0500431 ;;
Saqib Khanbb93e642017-08-10 11:24:38 -0500432 ubiremount)
433 remount_ubi
434 ;;
Saqib Khan7e4a3f22017-09-12 09:23:28 -0500435 createenvbackup)
Adriana Kobylake2fd46d2017-09-05 12:38:19 -0500436 backup_env_vars
437 ;;
Saqib Khan7e4a3f22017-09-12 09:23:28 -0500438 updateubootvars)
Adriana Kobylake2fd46d2017-09-05 12:38:19 -0500439 version="$2"
440 update_env_vars
441 ;;
Saqib Khandfc9b0c2017-09-08 10:10:08 -0500442 rebootguardenable)
443 rebootguardenable
444 ;;
445 rebootguarddisable)
446 rebootguarddisable
447 ;;
Adriana Kobylaka290eff2017-06-27 09:39:57 -0500448 *)
449 echo "Invalid argument"
450 exit 1
451 ;;
452esac