#!/bin/sh # Get the mtd device number (mtdX) findmtd() { m="$(grep -xl "$1" /sys/class/mtd/*/name)" m="${m%/name}" m="${m##*/}" echo "${m}" } # Get the ubi device number (ubiX_Y) findubi() { u="$(grep -xl "$1" /sys/class/ubi/ubi?/subsystem/ubi*/name)" u="${u%/name}" u="${u##*/}" echo "${u}" } # Get the mount information is_mounted() { grep -q "$1" /proc/mounts return $? } # Attach the pnor mtd device to ubi. attach_ubi() { pnormtd="$(findmtd pnor)" pnor="${pnormtd#mtd}" pnordev="/dev/mtd${pnor}" if [ -d "/sys/class/ubi/ubi${pnor}" ]; then # Already attached return 0 fi ubiattach /dev/ubi_ctrl -m "${pnor}" -d "${pnor}" rc=$? if [ ${rc} -ne 0 ]; then # Check the pnor mtd device is formatted as ubi by reading the first 3 byes, # which should be the ascii chars 'UBI' magic="$(hexdump -C -n 3 ${pnordev})" if [[ "${magic}" =~ "UBI" ]]; then # Device already formatted as ubi, ubiattach failed for some other reason return ${rc} else # Format device as ubi echo "Starting ubiformat ${pnordev}" ubiformat "${pnordev}" -y -q # Retry the ubiattach ubiattach /dev/ubi_ctrl -m "${pnor}" -d "${pnor}" fi fi } mount_squashfs() { pnormtd="$(findmtd pnor)" ubidev="/dev/ubi${pnormtd#mtd}" mountdir="/media/${name}" vol="$(findubi "${name}")" img="/tmp/images/${version}/pnor.xz.squashfs" filesize="$(ls -sh $img | awk -F " " {'print $1'})" if is_mounted "${name}"; then echo "${name} is already mounted." return 0 fi if [ ! -z "${vol}" ]; then ubirmvol "${ubidev}" -N "${name}" fi if [ ! -d "${mountdir}" ]; then mkdir "${mountdir}" fi # Set size of read-only partition equal to pnor.xz.squashfs ubimkvol "${ubidev}" -N "${name}" -s "${filesize}"KiB --type=static vol="$(findubi "${name}")" if [ $? != 0 ]; then echo "Unable to create RO volume!" return 1 fi ubidevid="${vol#ubi}" ubiupdatevol "/dev/ubi${ubidevid}" "${img}" if [ $? != 0 ]; then echo "Unable to update RO volume!" return 1 fi ubiblock --create "/dev/ubi${ubidevid}" if [ $? != 0 ]; then echo "Unable to create UBI block for RO volume!" return 1 fi mount -t squashfs -o ro "/dev/ubiblock${ubidevid}" "${mountdir}" if [ $? != 0 ]; then echo "Unable to mount RO volume!" return 1 fi } mount_ubi() { pnormtd="$(findmtd pnor)" pnor="${pnormtd#mtd}" ubidev="/dev/ubi${pnor}" pnordev="/dev/mtd${pnor}" if [[ "${name}" == "pnor-patch" ]]; then if [[ "$(fw_printenv fieldmode 2>/dev/null)" == "fieldmode=true" ]]; then return 0 fi if [[ ! "$(hexdump -C -n 3 ${pnordev})" =~ "UBI" ]]; then return 0 fi mountdir="/usr/local/share/pnor" else mountdir="/media/${name}" fi if [[ "${name}" == "pnor-prsv" ]]; then size="2MiB" else size="16MiB" fi if [ ! -d "${mountdir}" ]; then mkdir -p "${mountdir}" fi vol="$(findubi "${name}")" if [ -z "${vol}" ]; then ubimkvol "${ubidev}" -N "${name}" -s "${size}" fi if ! is_mounted "${name}"; then mountdev="ubi${pnor}:${name}" mount -t ubifs "${mountdev}" "${mountdir}" fi } umount_ubi() { pnormtd="$(findmtd pnor)" pnor="${pnormtd#mtd}" ubidev="/dev/ubi${pnor}" mountdir="/media/${name}" if is_mounted "${name}"; then umount "${mountdir}" fi vol="$(findubi "${name}")" id="${vol##*_}" if [ -n "${id}" ]; then ubirmvol "${ubidev}" -n "${id}" fi if [ -d "${mountdir}" ]; then rm -r "${mountdir}" fi } remount_ubi() { pnormtd="$(findmtd pnor)" pnor="${pnormtd#mtd}" pnordev="/dev/mtd${pnor}" # Re-Attach the pnor mtd device to ubi if [[ $(hexdump -C -n 3 ${pnordev}) =~ "UBI" ]]; then ubiattach /dev/ubi_ctrl -m "${pnor}" -d "${pnor}" else # Device not formatted as ubi. return 0 fi # Get information on all ubi volumes ubinfo=$(ubinfo -d ${pnor}) presentVolumes=${ubinfo##*:} IFS=', ' read -r -a array <<< "$presentVolumes" for element in ${array[@]}; do elementProperties=$(ubinfo -d $pnor -n $element) # Get ubi volume name by getting rid of additional properties name=${elementProperties#*Name:} name="${name%Character*}" name="$(echo -e "${name}" | tr -d '[:space:]')" if [[ ${name} == pnor-prsv ]] || [[ ${name} == pnor-rw* ]] || [[ ${name} == pnor-ro* ]]; then mountdir="/media/${name}" if [ ! -d "${mountdir}" ]; then mkdir -p "${mountdir}" fi if [[ ${name} == pnor-ro* ]] then ubiblock --create /dev/ubi${pnor}_${element} mount -t squashfs -o ro "/dev/ubiblock${pnor}_${element}" "${mountdir}" else mount -t ubifs "ubi${pnor}:${name}" "${mountdir}" fi fi done } update_symlinks() { PNOR_ACTIVE_PATH="/var/lib/phosphor-software-manager/pnor/" PNOR_RO_ACTIVE_PATH="/var/lib/phosphor-software-manager/pnor/ro" PNOR_RO_PREFIX="/media/pnor-ro-" PNOR_RW_ACTIVE_PATH="/var/lib/phosphor-software-manager/pnor/rw" PNOR_RW_PREFIX="/media/pnor-rw-" PNOR_PRSV_ACTIVE_PATH="/var/lib/phosphor-software-manager/pnor/prsv" PNOR_PRSV="/media/pnor-prsv" PERSISTENCE_PATH="/var/lib/obmc/openpower-pnor-code-mgmt/" PNOR_PATCH_LOCATION="/usr/local/share/pnor/" # Get a list of all active PNOR versions data="$(ls -d ${PNOR_RO_PREFIX}*)" IFS=$'\n' array=(${data}) currentVersion="" lowestPriority=255 for element in ${array[@]}; do #Remove the PNOR_RO_PREFIX from the path to get version ID. versionId="${element#${PNOR_RO_PREFIX}}" # Get the priority of active versions from persistence files. if [[ -f "${PERSISTENCE_PATH}${versionId}" ]]; then data="$(grep -r "priority" ${PERSISTENCE_PATH}${versionId})" priority="${data: -1}" if [[ priority -le lowestPriority ]]; then lowestPriority=${priority} currentVersion=${versionId} fi fi done # Return if no active version found if [ -z $currentVersion ]; then return 0; fi if [ ! -d "${PNOR_ACTIVE_PATH}" ]; then mkdir -p "${PNOR_ACTIVE_PATH}" fi # If the RW or RO active links doesn't point to the version with # lowest priority, then remove the symlink and create new ones. if [[ $(readlink -f "${PNOR_RO_ACTIVE_PATH}") != ${PNOR_RO_PREFIX}${currentVersion} ]]; then rm -f ${PNOR_RO_ACTIVE_PATH} rm -rf ${PNOR_PATCH_LOCATION}* ln -sfv ${PNOR_RO_PREFIX}${currentVersion} ${PNOR_RO_ACTIVE_PATH} fi if [[ $(readlink -f "${PNOR_RW_ACTIVE_PATH}") != ${PNOR_RW_PREFIX}${currentVersion} ]]; then rm -f ${PNOR_RW_ACTIVE_PATH} ln -sfv ${PNOR_RW_PREFIX}${currentVersion} ${PNOR_RW_ACTIVE_PATH} fi if [[ ! -h ${PNOR_PRSV_ACTIVE_PATH} ]]; then ln -sfv ${PNOR_PRSV} ${PNOR_PRSV_ACTIVE_PATH} fi } ubi_cleanup() { # When ubi_cleanup is run, it expects one or no active version. activeVersion=$(busctl --list --no-pager tree \ org.open_power.Software.Host.Updater | \ grep /xyz/openbmc_project/software/ | tail -c 9) if [[ -z "$activeVersion" ]]; then vols=$(ubinfo -a | grep -e "pnor-ro-" -e "pnor-rw-" | cut -c 14-) vols=(${vols}) else vols=$(ubinfo -a | grep -e "pnor-ro-" -e "pnor-rw-" | \ grep -v "$activeVersion" | cut -c 14-) vols=(${vols}) fi for (( index=0; index<${#vols[@]}; index++ )); do name=${vols[index]} umount_ubi done } clear_volatile() { service=$(mapper get-service /org/open_power/control/volatile) clearVolatileEnabled=$(busctl get-property $service /org/open_power/control/volatile xyz.openbmc_project.Object.Enable Enabled) if [[ "$clearVolatileEnabled" != "b true" ]]; then return 0 fi PNOR_TOC_FILE="pnor.toc" PNOR_RO_ACTIVE_PATH="/var/lib/phosphor-software-manager/pnor/ro/" PNOR_RW_ACTIVE_PATH="/var/lib/phosphor-software-manager/pnor/rw/" PNOR_PRSV_ACTIVE_PATH="/var/lib/phosphor-software-manager/pnor/prsv/" # toc partition string format: # partition27=HB_VOLATILE,0x02ba9000,0x02bae000,00,ECC,VOLATILE,READWRITE tocFilePath="${PNOR_RO_ACTIVE_PATH}${PNOR_TOC_FILE}" volatiles=($(grep VOLATILE "${tocFilePath}" | grep -Eo '^partition([0-9]+)=([A-Za-z0-9_]+)')) for (( index=0; index<${#volatiles[@]}; index++ )); do volatileName="$(echo ${volatiles[${index}]} | awk -F '=' '{print $2}')" rwVolatile="${PNOR_RW_ACTIVE_PATH}${volatileName}" if [ -f "${rwVolatile}" ]; then echo "Clear $rwVolatile" rm "${rwVolatile}" fi prsvVolatile="${PNOR_PRSV_ACTIVE_PATH}${volatileName}" if [ -f "${prsvVolatile}" ]; then echo "Clear $prsvVolatile" rm "${prsvVolatile}" fi done # Always reset the sensor after clearing busctl set-property $service /org/open_power/control/volatile xyz.openbmc_project.Object.Enable Enabled b false } case "$1" in ubiattach) attach_ubi ;; squashfsmount) name="$2" version="$3" mount_squashfs ;; ubimount) name="$2" mount_ubi ;; ubiumount) name="$2" umount_ubi ;; ubiremount) remount_ubi ;; updatesymlinks) update_symlinks ;; ubicleanup) ubi_cleanup ;; clearvolatile) clear_volatile ;; *) echo "Invalid argument" exit 1 ;; esac rc=$? if [ ${rc} -ne 0 ]; then echo "$0: error ${rc}" exit ${rc} fi