Add new google ipmi sys command: SysHostPowerOff

New google ipmi sys command to let the BMC knows host shutdown,
allow host to gracefully shutdown and disable the watchdog with given
time delay.

Signed-off-by: Yunyun Lin <linyuny@google.com>
Change-Id: I02171c9cfed57ae5d10d66b515e4ab7ee8856466
diff --git a/host_power_off.cpp b/host_power_off.cpp
new file mode 100644
index 0000000..57e45a1
--- /dev/null
+++ b/host_power_off.cpp
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2021 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "host_power_off.hpp"
+
+#include "commands.hpp"
+#include "errors.hpp"
+#include "handler.hpp"
+
+#include <cstdint>
+#include <cstring>
+
+namespace google
+{
+namespace ipmi
+{
+
+ipmi_ret_t hostPowerOff(const uint8_t* reqBuf, uint8_t* replyBuf,
+                        size_t* dataLen, const HandlerInterface* handler)
+{
+    struct HostPowerOffRequest request;
+
+    if ((*dataLen) < sizeof(request))
+    {
+        std::fprintf(stderr, "Invalid command length: %u\n",
+                     static_cast<uint32_t>(*dataLen));
+        return IPMI_CC_REQ_DATA_LEN_INVALID;
+    }
+
+    std::memcpy(&request, &reqBuf[0], sizeof(struct HostPowerOffRequest));
+    try
+    {
+        handler->hostPowerOffDelay(request.delay);
+    }
+    catch (const IpmiException& e)
+    {
+        return e.getIpmiError();
+    }
+
+    replyBuf[0] = SysHostPowerOff;
+    (*dataLen) = sizeof(uint8_t);
+
+    return IPMI_CC_OK;
+}
+} // namespace ipmi
+} // namespace google