vboot: Add --programmer and --servo flags to {get,set}_gbb_flags.sh.

Allow custom programmers to be used instead of host for getting and
setting GBB flags via a --programmer/-p flag similar to the same flag
for futility. Also support --servo with the same semantics as the
futility flag - detecting the programmer to use from the current servod
instance mirroring the logic in futility. Only CCD is supported at this
stage.

When reading, include the FMAP section as well as the GBB section. For
writes over CCD, avoiding rescanning for the FMAP can save up to 1.8s.

BUG=None
TEST={get,set}_gbb_flags.sh --servo with and without servod running
BRANCH=None

Change-Id: Iecedf4c3d0cad6923aed4405ef4a72910f3f9f05
Signed-off-by: Sam McNally <sammc@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/vboot_reference/+/3455562
Reviewed-by: Edward O'Callaghan <quasisec@chromium.org>
diff --git a/scripts/image_signing/gbb_flags_common.sh b/scripts/image_signing/gbb_flags_common.sh
index 63c3f12..ed51f15 100755
--- a/scripts/image_signing/gbb_flags_common.sh
+++ b/scripts/image_signing/gbb_flags_common.sh
@@ -51,9 +51,50 @@
   ${GBBFLAGS_DESCRIPTION}"
 
 flashrom_read() {
-  flashrom -p host -i GBB -r "$@"
+  local file="$1"
+  local programmer="$2"
+  flashrom -p "${programmer}" -i GBB -i FMAP -r "${file}"
 }
 
 flashrom_write() {
-  flashrom -p host -i GBB --noverify-all -w "$@"
+  local file="$1"
+  local programmer="$2"
+  flashrom -p "${programmer}"  -i GBB --noverify-all -w "${file}"
+}
+
+get_programmer_for_servo() {
+  local servo_type
+  local serial
+  local programmer
+  servo_type=$(dut-control -o servo_type 2>/dev/null) || \
+    die "Failed to get servo information. Is servod running?"
+  case "${servo_type}" in
+    *with_servo_micro*)
+      serial=$(dut-control -o servo_micro_serialname 2>/dev/null)
+      ;;
+    *with_c2d2*)
+      serial=$(dut-control -o c2d2_serialname 2>/dev/null)
+      ;;
+    *with_ccd*)
+      serial=$(dut-control -o ccd_serialname 2>/dev/null)
+      ;;
+    *)
+      serial=$(dut-control -o serialname 2>/dev/null)
+      ;;
+  esac
+  case "${servo_type}" in
+    *servo_micro*|*c2d2*)
+      # TODO(sammc): Support servo micro, servo v2 and C2D2. This requires
+      # toggling cpu_fw_spi via dut-control before and after running flashrom.
+      # C2D2 additionally requires a working cpu_fw_spi implementation.
+      die "Unsupported servo type ${servo_type}"
+      ;;
+    *ccd_cr50*|*ccd_gsc*)
+      programmer="raiden_debug_spi:target=AP,serial=${serial}"
+      ;;
+    *)
+      die "Unsupported servo type ${servo_type}"
+      ;;
+  esac
+  echo "${programmer}"
 }
diff --git a/scripts/image_signing/get_gbb_flags.sh b/scripts/image_signing/get_gbb_flags.sh
index 2b78af6..1191e9f 100755
--- a/scripts/image_signing/get_gbb_flags.sh
+++ b/scripts/image_signing/get_gbb_flags.sh
@@ -13,6 +13,8 @@
 # DEFINE_string name default_value description flag
 DEFINE_string file "" "Path to firmware image. Default to system firmware." "f"
 DEFINE_boolean explicit ${FLAGS_FALSE} "Print list of what flags are set." "e"
+DEFINE_string programmer "host" "Programmer to use when setting GBB flags" "p"
+DEFINE_boolean servo "${FLAGS_FALSE}"  "Determine programmer using servo" ""
 
 set -e
 
@@ -23,10 +25,14 @@
   fi
 
   local image_file="${FLAGS_file}"
+  local programmer="${FLAGS_programmer}"
 
   if [ -z "${FLAGS_file}" ]; then
     image_file="$(make_temp_file)"
-    flashrom_read "${image_file}"
+    if [ "${FLAGS_servo}" = "${FLAGS_TRUE}" ]; then
+      programmer=$(get_programmer_for_servo)
+    fi
+    flashrom_read "${image_file}" "${programmer}"
   fi
 
   # Process file.
diff --git a/scripts/image_signing/set_gbb_flags.sh b/scripts/image_signing/set_gbb_flags.sh
index 7a22b85..3057da5 100755
--- a/scripts/image_signing/set_gbb_flags.sh
+++ b/scripts/image_signing/set_gbb_flags.sh
@@ -13,6 +13,8 @@
 # DEFINE_string name default_value description flag
 DEFINE_string file "" "Path to firmware image. Default to system firmware." "f"
 DEFINE_boolean check_wp ${FLAGS_TRUE} "Check write protection states first." ""
+DEFINE_string programmer "host" "Programmer to use when setting GBB flags" "p"
+DEFINE_boolean servo "${FLAGS_FALSE}"  "Determine programmer using servo" ""
 
 set -e
 
@@ -20,12 +22,13 @@
 # ----------------------------------------------------------------------------
 check_write_protection() {
   local hw_wp="" sw_wp=""
-  if ! crossystem "wpsw_cur?0"; then
+  local programmer="$1"
+  if [ "${programmer}" = "host" ] && ! crossystem "wpsw_cur?0"; then
     hw_wp="on"
   fi
   # Keep 'local' declaration split from assignment so return code is checked.
   local wp_states
-  wp_states="$(flashrom -p host --wp-status 2>/dev/null | grep WP)"
+  wp_states="$(flashrom -p "${programmer}" --wp-status 2>/dev/null | grep WP)"
   local wp_disabled="$(echo "${wp_states}" | grep "WP:.*is disabled.")"
   local wp_zero_len="$(echo "${wp_states}" | grep "WP:.*, len=0x00000000")"
   if [ -z "${wp_disabled}" -a -z "${wp_zero_len}" ]; then
@@ -47,10 +50,15 @@
 
   local value="$(($1))"
   local image_file="${FLAGS_file}"
+  local programmer="${FLAGS_programmer}"
 
   if [ -z "${FLAGS_file}" ]; then
     image_file="$(make_temp_file)"
-    flashrom_read "${image_file}"
+    if [ "${FLAGS_servo}" = "${FLAGS_TRUE}" ]; then
+      programmer=$(get_programmer_for_servo)
+    fi
+
+    flashrom_read "${image_file}" "${programmer}"
   fi
 
   # Process file
@@ -62,14 +70,14 @@
 
   if [ -z "${FLAGS_file}" ]; then
     if [ "${FLAGS_check_wp}" = "${FLAGS_TRUE}" ]; then
-      if ! check_write_protection; then
+      if ! check_write_protection "${programmer}"; then
         echo ""
         echo "WARNING: System GBB Flags are NOT changed!!!"
         echo "ERROR: You must disable write protection before setting flags."
         exit 1
       fi
     fi
-    flashrom_write "$image_file"
+    flashrom_write "${image_file}" "${programmer}"
   fi
 }