1#!/bin/sh
2
3bios_reset_if_needed() {
4  resetval=$(fw_printenv -n rwreset 2>/dev/nell)
5  if [ "$resetval" = "0" ] || [ "$resetval" = "1" ]; then
6    varstore="/media/hostfw/reset-gpio-val"
7    if [ -f "$varstore" ]; then
8      if [ "$resetval" != "$(cat $varstore)" ]; then
9        if busctl call org.open_power.Software.Host.Updater /xyz/openbmc_project/software xyz.openbmc_project.Common.FactoryReset Reset; then
10          echo "$resetval" > "$varstore"
11        fi
12      fi
13    else
14      echo "$resetval" > "$varstore"
15    fi
16  fi
17}
18
19mmc_init() {
20  base_dir="/media/hostfw"
21  ro_dir="${base_dir}/running-ro"
22  running_dir="${base_dir}/running"
23  prsv_dir="${base_dir}/prsv"
24  staging_dir="${base_dir}/staging"
25
26  if [ ! -d "${ro_dir}" ]; then
27    mkdir -p "${ro_dir}"
28  fi
29  if [ ! -d "${running_dir}" ]; then
30    mkdir -p ${running_dir}
31  fi
32  if [ ! -d "${prsv_dir}" ]; then
33    mkdir -p "${prsv_dir}"
34  fi
35  if [ ! -d "${staging_dir}" ]; then
36    mkdir -p "${staging_dir}"
37  fi
38
39  # Mount the image that corresponds to the boot label as read-only to be used
40  # to populate the running directory.
41  boot_label="$(fw_printenv -n bootside)"
42  if ! grep -q "${ro_dir}" /proc/mounts; then
43    mount ${base_dir}/hostfw-"${boot_label}" ${ro_dir} -o ro
44  fi
45
46  # Determine if the running dir contains the running version
47  running_label=""
48  running_label_file="${running_dir}/partlabel"
49  if [ -f "${running_label_file}" ]; then
50    running_label=$(cat ${running_label_file})
51  fi
52  if [ "${running_label}" != "${boot_label}" ]; then
53    # Copy off the preserved partitions
54    # A line in the pnor.toc (81e00994.lid) looks like this:
55    # partition05=SECBOOT,0x00381000,0x003a5000,00,ECC,PRESERVED
56    rm -f ${prsv_dir}/*
57    if [ -f "${ro_dir}/81e00994.lid" ]; then
58      prsvs=$(grep PRESERVED "${ro_dir}/81e00994.lid")
59      for prsv in ${prsvs}; do
60        prsv=${prsv##partition*=}
61        prsv=$(echo "${prsv}" | cut -d "," -f 1)
62        if [ -L "${running_dir}/${prsv}" ]; then
63          # Preserve the symlink target file
64          prsv="$(readlink "${running_dir}/${prsv}")"
65          cp -p ${running_dir}/"${prsv}" ${prsv_dir}
66        fi
67      done
68    fi
69
70    # Copy lid contents of running image to running dir
71    rm -f ${running_dir}/*
72    cp -p ${ro_dir}/*.lid ${running_dir}/
73
74    # Restore the preserved partitions. Ignore error, there may be none.
75    cp -p ${prsv_dir}/* ${running_dir}/ 2>/dev/null || true
76    rm -f "${prsv_dir:?}/"*
77
78    # Clean up the staging dir in case of a failed update
79    rm -rf "${staging_dir:?}/"*
80
81    # Save the label
82    echo "${boot_label}" > "${running_label_file}"
83
84  fi
85
86  # Mount alternate dir
87  if [ "${boot_label}" = "a" ]; then
88    alternate_label="b"
89  else
90    alternate_label="a"
91  fi
92  alternate_dir="${base_dir}/alternate"
93  if [ ! -d "${alternate_dir}" ]; then
94    mkdir -p ${alternate_dir}
95  fi
96  if ! grep -q "${alternate_dir}" /proc/mounts; then
97    mount ${base_dir}/hostfw-${alternate_label} ${alternate_dir} -o ro
98  fi
99}
100
101mmc_patch() {
102  # Patching is disabled if field mode is set
103  if [ "$(fw_printenv fieldmode 2>/dev/null)" = "fieldmode=true" ]; then
104    return 0
105  fi
106
107  boot_label="$(fw_printenv -n bootside)"
108  if [ "${boot_label}" = "a" ]; then
109    alternate_label="b"
110  else
111    alternate_label="a"
112  fi
113
114  # Create patch directories
115  patch_dir="/media/hostfw/patch-"
116  running_patch_dir="${patch_dir}${boot_label}"
117  if [ ! -d "${running_patch_dir}" ]; then
118    mkdir -p "${running_patch_dir}"
119  fi
120  alternate_patch_dir="${patch_dir}${alternate_label}"
121  if [ ! -d "${alternate_patch_dir}" ]; then
122    mkdir -p "${alternate_patch_dir}"
123  fi
124
125  # Create patch symlinks
126  symlink_base="/usr/local/share"
127  if [ ! -d "${symlink_base}" ]; then
128    mkdir -p "${symlink_base}"
129  fi
130  hostfw_symlink_base="${symlink_base}/hostfw"
131  if [ ! -d "${hostfw_symlink_base}" ]; then
132    mkdir -p "${hostfw_symlink_base}"
133  fi
134
135  if [ "$(readlink -f "${symlink_base}/pnor")" != "${running_patch_dir}" ]; then
136    ln -s "${running_patch_dir}" "${symlink_base}/pnor"
137  fi
138  if [ "$(readlink -f "${hostfw_symlink_base}/running")" != "${running_patch_dir}" ]; then
139    ln -s "${running_patch_dir}" "${hostfw_symlink_base}/running"
140  fi
141  if [ "$(readlink -f "${hostfw_symlink_base}/alternate")" != "${alternate_patch_dir}" ]; then
142    ln -s "${alternate_patch_dir}" "${hostfw_symlink_base}/alternate"
143  fi
144}
145
146case "$1" in
147  bios-reset-if-needed)
148    bios_reset_if_needed
149    ;;
150  mmc-init)
151    mmc_init
152    ;;
153  mmc-patch)
154    mmc_patch
155    ;;
156  *)
157    echo "Invalid argument: $1" >&2
158    exit 1
159    ;;
160esac
161