Support for add and get boot order

Added support for oem command add and set boot order. Also added
default boot order.

Tested: Verified this with ipmitool command

Change-Id: I4cdb7ac2c10a1815ce84da05b64e3b3a3c96feba
Signed-off-by: Vijay Khemka <vijaykhemka@fb.com>
diff --git a/include/oemcommands.hpp b/include/oemcommands.hpp
index c309318..8599af4 100644
--- a/include/oemcommands.hpp
+++ b/include/oemcommands.hpp
@@ -136,6 +136,8 @@
 #define PPR_ROW_ADDR_LEN 8
 #define PPR_HST_DATA_LEN 17
 
+#define BOOT_SEQ_ARRAY_SIZE 10
+
 const char *bootSeq[] = {"USB_DEV", "NET_IPV4", "SATA_HDD", "SATA_CD",
                          "OTHER",   "",         "",         "",
                          "",        "NET_IPV6"};
diff --git a/src/oemcommands.cpp b/src/oemcommands.cpp
index 9fbcc90..94958a5 100644
--- a/src/oemcommands.cpp
+++ b/src/oemcommands.cpp
@@ -631,6 +631,32 @@
     return IPMI_CC_OK;
 }
 
+/* Helper functions to set boot order */
+void setBootOrder(uint8_t *data)
+{
+    nlohmann::json bootMode;
+    uint8_t mode = data[0];
+    int i;
+
+    bootMode["UEFI"] = (mode & BOOT_MODE_UEFI ? true : false);
+    bootMode["CMOS_CLR"] = (mode & BOOT_MODE_CMOS_CLR ? true : false);
+    bootMode["FORCE_BOOT"] = (mode & BOOT_MODE_FORCE_BOOT ? true : false);
+    bootMode["BOOT_FLAG"] = (mode & BOOT_MODE_BOOT_FLAG ? true : false);
+    oemData[KEY_BOOT_ORDER][KEY_BOOT_MODE] = bootMode;
+
+    /* Initialize boot sequence array */
+    oemData[KEY_BOOT_ORDER][KEY_BOOT_SEQ] = {};
+    for (i = 1; i < SIZE_BOOT_ORDER; i++)
+    {
+        if (data[i] >= BOOT_SEQ_ARRAY_SIZE)
+            oemData[KEY_BOOT_ORDER][KEY_BOOT_SEQ][i - 1] = "NA";
+        else
+            oemData[KEY_BOOT_ORDER][KEY_BOOT_SEQ][i - 1] = bootSeq[data[i]];
+    }
+
+    flushOemData();
+}
+
 //----------------------------------------------------------------------
 // Set Boot Order (CMD_OEM_SET_BOOT_ORDER)
 //----------------------------------------------------------------------
@@ -640,9 +666,6 @@
 {
     uint8_t *req = reinterpret_cast<uint8_t *>(request);
     uint8_t len = *data_len;
-    uint8_t mode = req[0];
-    nlohmann::json bootMode;
-    int i;
 
     *data_len = 0;
 
@@ -653,19 +676,7 @@
         return IPMI_CC_REQ_DATA_LEN_INVALID;
     }
 
-    bootMode["UEFI"] = (mode & BOOT_MODE_UEFI ? true : false);
-    bootMode["CMOS_CLR"] = (mode & BOOT_MODE_CMOS_CLR ? true : false);
-    bootMode["FORCE_BOOT"] = (mode & BOOT_MODE_FORCE_BOOT ? true : false);
-    bootMode["BOOT_FLAG"] = (mode & BOOT_MODE_BOOT_FLAG ? true : false);
-
-    oemData[KEY_BOOT_ORDER][KEY_BOOT_MODE] = bootMode;
-
-    /* Initialize boot sequence array */
-    oemData[KEY_BOOT_ORDER][KEY_BOOT_SEQ] = {};
-    for (i = 1; i < SIZE_BOOT_ORDER; i++)
-        oemData[KEY_BOOT_ORDER][KEY_BOOT_SEQ][i - 1] = bootSeq[req[i]];
-
-    flushOemData();
+    setBootOrder(req);
 
     return IPMI_CC_OK;
 }
@@ -678,23 +689,44 @@
                                ipmi_data_len_t data_len, ipmi_context_t context)
 {
     uint8_t *res = reinterpret_cast<uint8_t *>(response);
-    nlohmann::json bootMode = oemData[KEY_BOOT_ORDER][KEY_BOOT_MODE];
     uint8_t mode = 0;
     int i;
 
     *data_len = SIZE_BOOT_ORDER;
 
-    if (bootMode["UEFI"])
-        mode |= BOOT_MODE_UEFI;
-    if (bootMode["CMOS_CLR"])
-        mode |= BOOT_MODE_CMOS_CLR;
-    if (bootMode["BOOT_FLAG"])
-        mode |= BOOT_MODE_BOOT_FLAG;
+    if (oemData.find(KEY_BOOT_ORDER) == oemData.end())
+    {
+        /* Return default boot order 0100090203ff */
+        uint8_t defaultBoot[SIZE_BOOT_ORDER] = {
+            BOOT_MODE_UEFI,      bootMap["USB_DEV"], bootMap["NET_IPV6"],
+            bootMap["SATA_HDD"], bootMap["SATA_CD"], 0xff};
 
-    res[0] = mode;
+        memcpy(res, defaultBoot, SIZE_BOOT_ORDER);
+        phosphor::logging::log<phosphor::logging::level::INFO>(
+            "Set default boot order");
+        setBootOrder(defaultBoot);
+    }
+    else
+    {
+        nlohmann::json bootMode = oemData[KEY_BOOT_ORDER][KEY_BOOT_MODE];
+        if (bootMode["UEFI"])
+            mode |= BOOT_MODE_UEFI;
+        if (bootMode["CMOS_CLR"])
+            mode |= BOOT_MODE_CMOS_CLR;
+        if (bootMode["BOOT_FLAG"])
+            mode |= BOOT_MODE_BOOT_FLAG;
 
-    for (i = 1; i < SIZE_BOOT_ORDER; i++)
-        res[i] = bootMap[oemData[KEY_BOOT_ORDER][KEY_BOOT_SEQ][i - 1]];
+        res[0] = mode;
+
+        for (i = 1; i < SIZE_BOOT_ORDER; i++)
+        {
+            std::string seqStr = oemData[KEY_BOOT_ORDER][KEY_BOOT_SEQ][i - 1];
+            if (bootMap.find(seqStr) != bootMap.end())
+                res[i] = bootMap[seqStr];
+            else
+                res[i] = 0xff;
+        }
+    }
 
     return IPMI_CC_OK;
 }