1#!/bin/bash
2
3clear_volatile() {
4  service=$(mapper get-service /org/open_power/control/volatile)
5  clearVolatileEnabled=$(busctl get-property "$service" /org/open_power/control/volatile xyz.openbmc_project.Object.Enable Enabled)
6  if [[ "$clearVolatileEnabled" != "b true" ]]; then
7    return 0
8  fi
9
10  PNOR_TOC_FILE="pnor.toc"
11  PNOR_RO_ACTIVE_PATH="/var/lib/phosphor-software-manager/pnor/ro/"
12  PNOR_RW_ACTIVE_PATH="/var/lib/phosphor-software-manager/pnor/rw/"
13  PNOR_PRSV_ACTIVE_PATH="/var/lib/phosphor-software-manager/pnor/prsv/"
14
15  # toc partition string format:
16  # partition27=HB_VOLATILE,0x02ba9000,0x02bae000,00,ECC,VOLATILE,READWRITE
17  tocFilePath="${PNOR_RO_ACTIVE_PATH}${PNOR_TOC_FILE}"
18  if [ ! -f "${tocFilePath}" ]; then
19    tocFilePath="${PNOR_RW_ACTIVE_PATH}${PNOR_TOC_FILE}"
20  fi
21  mapfile -t volatiles < <(grep VOLATILE "${tocFilePath}" | grep -Eo '^partition([0-9]+)=([A-Za-z0-9_]+)')
22  for (( index=0; index<${#volatiles[@]}; index++ )); do
23    volatileName="$(echo "${volatiles[${index}]}" | awk -F '=' '{print $2}')"
24
25    rwVolatile="${PNOR_RW_ACTIVE_PATH}${volatileName}"
26    if [ -f "${rwVolatile}" ]; then
27      echo "Clear $rwVolatile"
28      rm "${rwVolatile}"
29    fi
30    prsvVolatile="${PNOR_PRSV_ACTIVE_PATH}${volatileName}"
31    if [ -f "${prsvVolatile}" ]; then
32      echo "Clear $prsvVolatile"
33      rm "${prsvVolatile}"
34    fi
35
36    if [ ! -f "${PNOR_RO_ACTIVE_PATH}${volatileName}" ]; then
37      cp -a "${PNOR_RO_ACTIVE_PATH}81e0066f.lid" "${PNOR_PRSV_ACTIVE_PATH}"
38      ln -s "81e0066f.lid" "${PNOR_PRSV_ACTIVE_PATH}${volatileName}"
39    fi
40  done
41  # Always reset the sensor after clearing
42  busctl set-property "$service" /org/open_power/control/volatile xyz.openbmc_project.Object.Enable Enabled b false
43}
44
45update_symlinks() {
46  PNOR_ACTIVE_PATH="/var/lib/phosphor-software-manager/pnor/"
47  HOSTFW_ACTIVE_PATH="/var/lib/phosphor-software-manager/hostfw/"
48  PNOR_RO_ACTIVE_PATH="/var/lib/phosphor-software-manager/pnor/ro"
49  PNOR_RO_PREFIX="/media/pnor-ro-"
50  PNOR_RW_ACTIVE_PATH="/var/lib/phosphor-software-manager/pnor/rw"
51  PNOR_RW_PREFIX="/media/pnor-rw-"
52  PNOR_PRSV_ACTIVE_PATH="/var/lib/phosphor-software-manager/pnor/prsv"
53  PNOR_PRSV="/media/pnor-prsv"
54  PERSISTENCE_PATH="/var/lib/obmc/openpower-pnor-code-mgmt/"
55  PNOR_PATCH_LOCATION="/usr/local/share/pnor/"
56  MMC_BASE_PATH="/media/hostfw"
57  MMC_RO_PATH="${MMC_BASE_PATH}/running-ro"
58  MMC_RUNNING_PATH="${MMC_BASE_PATH}/running"
59  MMC_ALTERNATE_PATH="${MMC_BASE_PATH}/alternate"
60  MMC_STAGING_PATH="${MMC_BASE_PATH}/staging"
61  MMC_NVRAM_PATH="${MMC_BASE_PATH}/nvram"
62  HOSTFW_RUNNING_PATH="${HOSTFW_ACTIVE_PATH}/running"
63  HOSTFW_ALTERNATE_PATH="${HOSTFW_ACTIVE_PATH}/alternate"
64  HOSTFW_STAGING_PATH="${HOSTFW_ACTIVE_PATH}/staging"
65  HOSTFW_NVRAM_PATH="${HOSTFW_ACTIVE_PATH}/nvram"
66
67  # Get a list of all active PNOR versions
68  data="$(ls -d ${PNOR_RO_PREFIX}* 2>/dev/null)"
69  mapfile -t array <<< "${data}"
70
71  currentVersion=""
72  lowestPriority=255
73  for element in "${array[@]}"; do
74    #Remove the PNOR_RO_PREFIX from the path to get version ID.
75    versionId="${element#"${PNOR_RO_PREFIX}"}"
76
77    # Get the priority of active versions from persistence files.
78    if [[ -f "${PERSISTENCE_PATH}${versionId}" ]]; then
79      data="$(grep -r "priority" "${PERSISTENCE_PATH}${versionId}")"
80      priority="${data: -1}"
81      if [[ priority -le lowestPriority ]]; then
82        lowestPriority=${priority}
83        currentVersion=${versionId}
84      fi
85    fi
86  done
87
88  if [ -n "$currentVersion" ]; then
89      # Use active version
90      roTarget="${PNOR_RO_PREFIX}${currentVersion}"
91      rwTarget="${PNOR_RW_PREFIX}${currentVersion}"
92      prsvTarget="${PNOR_PRSV}"
93  elif [ -d "${MMC_BASE_PATH}" ]; then
94      # Use eMMC
95      roTarget="${MMC_RO_PATH}"
96      rwTarget="${MMC_RUNNING_PATH}"
97      prsvTarget="${MMC_RUNNING_PATH}"
98
99      if [ ! -d "${HOSTFW_ACTIVE_PATH}" ]; then
100          mkdir -p "${HOSTFW_ACTIVE_PATH}"
101      fi
102      # Symlinks used by PLDM
103      if [[ $(readlink -f "${HOSTFW_RUNNING_PATH}") != "${MMC_RUNNING_PATH}" ]]; then
104          rm -f ${HOSTFW_RUNNING_PATH}
105          ln -sfv ${MMC_RUNNING_PATH} ${HOSTFW_RUNNING_PATH}
106      fi
107      if [[ $(readlink -f "${HOSTFW_ALTERNATE_PATH}") != "${MMC_ALTERNATE_PATH}" ]]; then
108          rm -f ${HOSTFW_ALTERNATE_PATH}
109          ln -sfv ${MMC_ALTERNATE_PATH} ${HOSTFW_ALTERNATE_PATH}
110      fi
111      if [[ $(readlink -f "${HOSTFW_STAGING_PATH}") != "${MMC_STAGING_PATH}" ]]; then
112          rm -f ${HOSTFW_STAGING_PATH}
113          ln -sfv ${MMC_STAGING_PATH} ${HOSTFW_STAGING_PATH}
114      fi
115      if [[ $(readlink -f "${HOSTFW_NVRAM_PATH}") != "${MMC_NVRAM_PATH}" ]]; then
116          rm -f ${HOSTFW_NVRAM_PATH}
117          ln -sfv ${MMC_NVRAM_PATH} ${HOSTFW_NVRAM_PATH}
118      fi
119  fi
120
121  if [ ! -d "${PNOR_ACTIVE_PATH}" ]; then
122        mkdir -p "${PNOR_ACTIVE_PATH}"
123  fi
124
125  # If the RW or RO active links doesn't point to the version with
126  # lowest priority, then remove the symlink and create new ones.
127  if [[ $(readlink -f "${PNOR_RO_ACTIVE_PATH}") != "${roTarget}" ]]; then
128    rm -f ${PNOR_RO_ACTIVE_PATH}
129    rm -rf ${PNOR_PATCH_LOCATION}*
130    ln -sfv ${roTarget} ${PNOR_RO_ACTIVE_PATH}
131  fi
132
133  if [[ $(readlink -f "${PNOR_RW_ACTIVE_PATH}") != "${rwTarget}" ]]; then
134    rm -f ${PNOR_RW_ACTIVE_PATH}
135    ln -sfv ${rwTarget} ${PNOR_RW_ACTIVE_PATH}
136  fi
137
138  if [[ $(readlink -f "${PNOR_PRSV_ACTIVE_PATH}") != "${prsvTarget}" ]]; then
139    rm -f ${PNOR_PRSV_ACTIVE_PATH}
140    ln -sfv ${prsvTarget} ${PNOR_PRSV_ACTIVE_PATH}
141  fi
142}
143
144case "$1" in
145  clearvolatile)
146    clear_volatile
147    ;;
148  updatesymlinks)
149    update_symlinks
150    ;;
151  *)
152    echo "Invalid argument"
153    exit 1
154    ;;
155esac
156rc=$?
157if [ ${rc} -ne 0 ]; then
158  echo "$0: error ${rc}"
159  exit ${rc}
160fi
161