ncsid: Import from gBMC

This is the initial code drop from gBMC.

Google-Bug-Id: 179618516
Upstream: 1e71af914bc8c54d8b91d0a1cf377e2696713c2f
Change-Id: Ic653e8271dacd205e04f2bc713071ef2ec5936a4
Signed-off-by: William A. Kennington III <wak@google.com>
diff --git a/ncsid/src/ncsi_state_machine.h b/ncsid/src/ncsi_state_machine.h
new file mode 100644
index 0000000..d55bba7
--- /dev/null
+++ b/ncsid/src/ncsi_state_machine.h
@@ -0,0 +1,112 @@
+#pragma once
+#include "ncsi_sockio.h"
+#include "net_config.h"
+#include "net_iface.h"
+#include "platforms/nemora/portable/ncsi_client.h"
+#include "platforms/nemora/portable/ncsi_fsm.h"
+#include "platforms/nemora/portable/net_types.h"
+
+#include <optional>
+
+namespace ncsi
+{
+
+typedef ncsi_response_type_t (*ncsi_simple_poll_f)(ncsi_state_t*,
+                                                   network_debug_t*,
+                                                   ncsi_buf_t*, mac_addr_t*,
+                                                   uint32_t, uint16_t);
+
+// This class encapsulates three state machines:
+//  * L2 -- performs basic NC-SI setup, reads NIC MAC addr
+//  * L3/4 -- once network is configured on the interface,
+//      sets up NC-SI filter in the NIC.
+//  * Test -- runs several basic NC-SI link tests, like
+//      ECHO Request/Reply, checks filter setup etc.
+//      Also, reads hostless/host-based flag from the NIC, see
+//      ncsi_fsm.c:is_nic_hostless() for details.
+class StateMachine
+{
+  public:
+    StateMachine();
+
+    void set_sockio(net::SockIO* sock_io);
+
+    void set_net_config(net::ConfigBase* net_config);
+
+    // NC-SI State Machine's main function.
+    // max_rounds = 0 means run forever.
+    void run(int max_rounds = 0);
+
+    // How often Test FSM re-runs, in seconds.
+    void set_retest_delay(unsigned int delay);
+
+  private:
+    // Reset the state machine
+    void reset();
+
+    // Poll L2 state machine. Each call advances it by one step.
+    // Its implementation is taken directly from EC.
+    size_t poll_l2_config();
+
+    // This function is used to poll both L3/4 and Test state machine,
+    // depending on the function passed in as an argument.
+    size_t poll_simple(ncsi_simple_poll_f poll_func);
+
+    // Helper function for printing NC-SI error to stdout.
+    void report_ncsi_error(ncsi_response_type_t response_type);
+
+    int receive_ncsi();
+
+    // Helper function for advancing the test FSM.
+    void run_test_fsm(size_t* tx_len);
+
+    // Clear the state and reset all state machines.
+    void clear_state();
+
+    // In current implementation this is the same as clear state,
+    // except that it also increments the failure counter.
+    void fail();
+
+    // Return true if the test state machine finished successfully.
+    bool is_test_done() const
+    {
+        return ncsi_state_.test_state == NCSI_STATE_TEST_END;
+    }
+
+    // Max number of times a state machine is going to retry a command.
+    static constexpr auto MAX_TRIES = 5;
+
+    // How long (in seconds) to wait before re-running NC-SI test state
+    // machine.
+    unsigned int retest_delay_s_ = 1;
+
+    // The last known state of the link on the NIC
+    std::optional<bool> link_up_;
+
+    // The last known hostless mode of the NIC
+    std::optional<bool> hostless_;
+
+    // net_config_ is used to query and set network configuration.
+    // The StateMachine does not own the pointer and it is the
+    // responsibility of the client to make sure that it outlives the
+    // StateMachine.
+    net::ConfigBase* net_config_ = nullptr;
+
+    // sock_io_ is used to read and write NC-SI packets.
+    // The StateMachine does not own the pointer. It is the responsibility
+    // of the client to make sure that sock_io_ outlives the StateMachine.
+    net::SockIO* sock_io_ = nullptr;
+
+    // Both ncsi_state_ and network_debug_ parameters represent the state of
+    // the NC-SI state machine. The names and definitions are taken directly
+    // from EC.
+    ncsi_state_t ncsi_state_;
+    network_debug_t network_debug_;
+
+    // Depending on the state ncsi_buf_ represents either the NC-SI packet
+    // received from the NIC or NC-SI packet that was (or about to be)
+    // sent to the NIC.
+    ncsi_buf_t ncsi_buf_;
+};
+
+} // namespace ncsi