chromeos-nvt-tcon-updater: inhibit suspend during TCON FW updates

BUG=b:167075994
TEST=Performed multiple no-update reboots.
The TCON FW updater correctly logged the TCON FW version and exited,
confirmed from /var/log/messages.

Triggered TCON FW update at boot by pointing TCON FW symlink at
different version.
Closed lid 5 times during the update, including for 3+ seconds at a time.
The DUT did not suspend, confirmed from /var/log/messages.
The TCON FW update succeeded, confirmed from /var/log/messages.

Triggered TCON FW update at boot by pointing TCON FW symlink at
different version.
Closed lid during the update, and left it closed.
Watched DUT power state from CR50 and EC consoles.
Per CR50, AP remained on for expected duration of the update,
then turned off at expected end of update.
Per EC, lid closed was registered but did not trigger immediate suspend.
After expected update completion, DUT bounced between power states until
settling on fake G3 (AP off).
Opened lid many minutes later.  The TCON FW update had succeeded,
confirmed from /var/log/messages.

Change-Id: Ia77bffcd5493501db5cb6271eb72ff72b5aca573
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform2/+/2383935
Commit-Queue: Matthew Blecker <matthewb@chromium.org>
Tested-by: Matthew Blecker <matthewb@chromium.org>
Reviewed-by: Grant Grundler <grundler@chromium.org>
(cherry picked from commit f031e2d6a1c23615e945435faf4861f3da233ea8)
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform2/+/2384389
Reviewed-by: Matthew Blecker <matthewb@chromium.org>
diff --git a/chromeos-nvt-tcon-updater/scripts/chromeos-nvt-tcon-firmware-update.sh b/chromeos-nvt-tcon-updater/scripts/chromeos-nvt-tcon-firmware-update.sh
index 28cd789..9fff91b 100644
--- a/chromeos-nvt-tcon-updater/scripts/chromeos-nvt-tcon-firmware-update.sh
+++ b/chromeos-nvt-tcon-updater/scripts/chromeos-nvt-tcon-firmware-update.sh
@@ -17,24 +17,25 @@
 # which sources this library.
 #
 # If using this library for multiple displays on one device, it is recommended
-# to use each from a separate script, and append a unique suffix to
-# $NVT_TCON_LOG_TAG so that the source of log messages can be identified.
+# to use each from a separate script or invocation, and append a unique suffix
+# to $LOG_TAG so that the source of log messages can be identified.
 
-NVT_TCON_LOG_TAG="chromeos-nvt-tcon-firmware-update"
+LOG_TAG="chromeos-nvt-tcon-firmware-update"
+INHIBIT_SUSPEND_FILE="/run/lock/power_override/${LOG_TAG}.lock"
 
 # Require a minimum battery percentage to mitigate
 # https://issuetracker.google.com/144947174 as best we can.
 # This should NOT be necessary for most firmware update processes in the
 # Chromium OS ecosystem.
-NVT_TCON_MIN_BATTERY_PERCENT=15
+MIN_BATTERY_PERCENT=15
 
 loginfo() {
   echo "$*"
-  logger --tag="${NVT_TCON_LOG_TAG}" -- "$*"
+  logger --tag="${LOG_TAG}" -- "$*"
 }
 
 logerror() {
-  logger --stderr --tag="${NVT_TCON_LOG_TAG}" -- "$*"
+  logger --stderr --tag="${LOG_TAG}" -- "$*"
 }
 
 # Pipe a non-negative integer to this.
@@ -59,6 +60,25 @@
   grep -o -E '^0x[0-9A-F]{2}-0x[0-9A-F]{2}$'
 }
 
+# Block suspend while running a command.
+#
+# Args:
+#   $@ The command to run while suspend is blocked.
+block_suspend_and_run_cmd() {
+  local ret=0
+
+  trap 'rm -f -- "${INHIBIT_SUSPEND_FILE}"' EXIT
+  echo "$$" > "${INHIBIT_SUSPEND_FILE}"
+
+  "$@"
+  # Preserve the exit status in case we're running without set -e.
+  ret="$?"
+
+  rm -f "${INHIBIT_SUSPEND_FILE}"
+  trap - EXIT
+  return "${ret}"
+}
+
 # Prints display resolution string to stdout as one line, with trailing newline.
 #
 # Args:
@@ -263,11 +283,20 @@
   # Chromium OS ecosystem.
   local battery_percent
   battery_percent="$(get_battery_percent)"
-  if [ "${battery_percent}" -lt "${NVT_TCON_MIN_BATTERY_PERCENT}" ]; then
+  if [ "${battery_percent}" -lt "${MIN_BATTERY_PERCENT}" ]; then
     loginfo "skipping TCON firmware update due to low battery charge"
     return
   fi
 
+  block_suspend_and_run_cmd do_tcon_fw_update
+}
+
+# Only update_tcon_fw() should invoke this.
+#
+# Preconditions:
+# - Suspend must be inhibited.
+# - Battery state of charge must be sufficient to complete the update.
+do_tcon_fw_update() {
   hook_pre_display_reset || return
   show_message_and_reset_panel || return
   hook_post_display_reset || return