[opentitantool] Propagate `transport init` to backend

The existing command `opentitantool transport init` will send a series
of instructions to the backend to configure pins according to a set of
configuration files.  Ideally, that would bring the transport into a
known state.  However, sometimes the configuration is under-specified,
that is, maybe it omits declaring the direction of a pin as "Input",
relying on that being the default for all pins at power-on.  Doing so
opens up the possibility that if the debugger device has previously been
used with a different configuration file, which used the same pin as
output, then after `transport init` the pin would remain an output, to
the surprise of automated tests or operators.

This PR makes `transport init` first tell the backend transport to reset
to power-on state, before sending the usual series of pin-specific
instructions, hopefully reducing the risk of surprises.

Some backends, such as UltraDebug, do not support re-configuraion of
pin direction, and others, such as Verilator, do not have backend
hardware which could carry over state from one test to the next, so a
default empty implementation of the new method is provided.

Signed-off-by: Jes B. Klinke <jbk@chromium.org>
Change-Id: I0cee4a994ff72c653f0522fcfe92ce1be1ecf6af
diff --git a/WORKSPACE b/WORKSPACE
index be6828f..9eb984c 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -114,6 +114,6 @@
 load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_file")
 http_file(
     name = "hyperdebug_firmware",
-    urls = ["https://storage.googleapis.com/aoa-recovery-test-images/hyperdebug_v2.0.20420-ca113941b.bin"],
-    sha256 = "9a7fbc166a3cac25909a5dc8239be1f9e50e803246c4e9276cc1954871ffc88c",
+    urls = ["https://storage.googleapis.com/aoa-recovery-test-images/hyperdebug_v2.0.20491-956ccf530.bin"],
+    sha256 = "e9c93d2935b9b6a571b547f20fe6177c48a909535d87533b7a0c64fb049bd643",
 )
diff --git a/sw/host/opentitanlib/src/app/mod.rs b/sw/host/opentitanlib/src/app/mod.rs
index 52a5bef..8a30666 100644
--- a/sw/host/opentitanlib/src/app/mod.rs
+++ b/sw/host/opentitanlib/src/app/mod.rs
@@ -408,6 +408,7 @@
     /// Configure all pins as input/output, pullup, etc. as declared in configuration files.
     /// Also configure SPI port mode/speed, and other similar settings.
     pub fn apply_default_configuration(&self) -> Result<()> {
+        self.transport.borrow().apply_default_configuration()?;
         self.apply_pin_configurations(&self.pin_conf_map)?;
         self.apply_spi_configurations(&self.spi_conf_map)?;
         Ok(())
diff --git a/sw/host/opentitanlib/src/proxy/handler.rs b/sw/host/opentitanlib/src/proxy/handler.rs
index bb194c6..a20c001 100644
--- a/sw/host/opentitanlib/src/proxy/handler.rs
+++ b/sw/host/opentitanlib/src/proxy/handler.rs
@@ -45,6 +45,10 @@
             Request::GetCapabilities => {
                 Ok(Response::GetCapabilities(self.transport.capabilities()?))
             }
+            Request::ApplyDefaultConfiguration => {
+                self.transport.apply_default_configuration()?;
+                Ok(Response::ApplyDefaultConfiguration)
+            }
             Request::Gpio { id, command } => {
                 let instance = self.transport.gpio_pin(id)?;
                 match command {
diff --git a/sw/host/opentitanlib/src/proxy/protocol.rs b/sw/host/opentitanlib/src/proxy/protocol.rs
index 6e7e539..3bb4d24 100644
--- a/sw/host/opentitanlib/src/proxy/protocol.rs
+++ b/sw/host/opentitanlib/src/proxy/protocol.rs
@@ -22,6 +22,7 @@
 #[derive(Serialize, Deserialize)]
 pub enum Request {
     GetCapabilities,
+    ApplyDefaultConfiguration,
     Gpio { id: String, command: GpioRequest },
     Uart { id: String, command: UartRequest },
     Spi { id: String, command: SpiRequest },
@@ -33,6 +34,7 @@
 #[derive(Serialize, Deserialize)]
 pub enum Response {
     GetCapabilities(Capabilities),
+    ApplyDefaultConfiguration,
     Gpio(GpioResponse),
     Uart(UartResponse),
     Spi(SpiResponse),
diff --git a/sw/host/opentitanlib/src/transport/hyperdebug/mod.rs b/sw/host/opentitanlib/src/transport/hyperdebug/mod.rs
index 524ecc2..41bf63f 100644
--- a/sw/host/opentitanlib/src/transport/hyperdebug/mod.rs
+++ b/sw/host/opentitanlib/src/transport/hyperdebug/mod.rs
@@ -479,6 +479,10 @@
         ))
     }
 
+    fn apply_default_configuration(&self) -> Result<()> {
+        self.inner.cmd_no_output("reinit")
+    }
+
     // Create SPI Target instance, or return one from a cache of previously created instances.
     fn spi(&self, instance: &str) -> Result<Rc<dyn Target>> {
         // Execute a "spi info" command to look up the numeric index corresponding to the given
diff --git a/sw/host/opentitanlib/src/transport/mod.rs b/sw/host/opentitanlib/src/transport/mod.rs
index b174f14..634c1f0 100644
--- a/sw/host/opentitanlib/src/transport/mod.rs
+++ b/sw/host/opentitanlib/src/transport/mod.rs
@@ -95,6 +95,12 @@
     /// transport object.
     fn capabilities(&self) -> Result<Capabilities>;
 
+    /// Resets the transport to power-on condition.  That is, pin/uart/spi configuration reverts
+    /// to default, ongoing operations are cancelled, etc.
+    fn apply_default_configuration(&self) -> Result<()> {
+        Ok(())
+    }
+
     /// Returns a SPI [`Target`] implementation.
     fn spi(&self, _instance: &str) -> Result<Rc<dyn Target>> {
         Err(TransportError::InvalidInterface(TransportInterfaceType::Spi).into())
diff --git a/sw/host/opentitanlib/src/transport/proxy/mod.rs b/sw/host/opentitanlib/src/transport/proxy/mod.rs
index ef36527..c931f15 100644
--- a/sw/host/opentitanlib/src/transport/proxy/mod.rs
+++ b/sw/host/opentitanlib/src/transport/proxy/mod.rs
@@ -151,6 +151,16 @@
         }
     }
 
+    fn apply_default_configuration(&self) -> Result<()> {
+        match self
+            .inner
+            .execute_command(Request::ApplyDefaultConfiguration)?
+        {
+            Response::ApplyDefaultConfiguration => Ok(()),
+            _ => bail!(ProxyError::UnexpectedReply()),
+        }
+    }
+
     // Create SPI Target instance, or return one from a cache of previously created instances.
     fn spi(&self, instance: &str) -> Result<Rc<dyn Target>> {
         Ok(Rc::new(spi::ProxySpi::open(self, instance)?))