boot_flags: switch to new settings API

Change-Id: If7cd999889b3ce19b746c3223012920d79e63099
Signed-off-by: Deepak Kodihalli <dkodihal@in.ibm.com>
diff --git a/chassishandler.cpp b/chassishandler.cpp
index 506d628..6c8b8e0 100644
--- a/chassishandler.cpp
+++ b/chassishandler.cpp
@@ -1,6 +1,8 @@
 #include "chassishandler.h"
 #include "host-ipmid/ipmid-api.h"
 #include "types.hpp"
+#include "ipmid.hpp"
+#include "settings.hpp"
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -16,6 +18,7 @@
 #include <fstream>
 #include <experimental/filesystem>
 #include <string>
+#include <map>
 
 #include <phosphor-logging/log.hpp>
 #include <phosphor-logging/elog-errors.hpp>
@@ -24,6 +27,8 @@
 
 #include <sdbusplus/bus.hpp>
 #include <sdbusplus/server/object.hpp>
+#include <xyz/openbmc_project/Control/Boot/Source/server.hpp>
+#include <xyz/openbmc_project/Control/Boot/Mode/server.hpp>
 
 #include "config.h"
 
@@ -108,6 +113,25 @@
 using namespace phosphor::logging;
 using namespace sdbusplus::xyz::openbmc_project::Common::Error;
 
+namespace chassis
+{
+namespace internal
+{
+
+constexpr auto bootModeIntf = "xyz.openbmc_project.Control.Boot.Mode";
+constexpr auto bootSourceIntf = "xyz.openbmc_project.Control.Boot.Source";
+sdbusplus::bus::bus dbus(ipmid_get_sd_bus_connection());
+
+namespace cache
+{
+
+settings::Objects objects(dbus,
+                          {bootModeIntf, bootSourceIntf});
+
+} // namespace cache
+} // namespace internal
+} // namespace chassis
+
 /** @brief Gets the dbus object info implementing the given interface
  *         from the given subtree.
  *  @param[in] interface - Dbus interface.
@@ -1157,58 +1181,44 @@
     return ( (rc < 0) ? IPMI_CC_INVALID : IPMI_CC_OK);
 }
 
-struct bootOptionTypeMap_t {
-    uint8_t ipmibootflag;
-    char    dbusname[8];
+namespace boot_options
+{
+
+using namespace sdbusplus::xyz::openbmc_project::Control::Boot::server;
+using IpmiValue = uint8_t;
+constexpr auto ipmiDefault = 0;
+
+std::map<IpmiValue, Source::Sources> sourceIpmiToDbus =
+{
+    {0x01, Source::Sources::Network},
+    {0x02, Source::Sources::Disk},
+    {0x05, Source::Sources::ExternalMedia},
+    {ipmiDefault, Source::Sources::Default}
 };
 
-#define INVALID_STRING "Invalid"
-// dbus supports this list of boot devices.
-bootOptionTypeMap_t g_bootOptionTypeMap_t[] = {
-
-        {0x01, "Network"},
-        {0x02, "Disk"},
-        {0x03, "Safe"},
-        {0x05, "CDROM"},
-        {0x06, "Setup"},
-        {0x00, "Default"},
-        {0xFF, INVALID_STRING}
+std::map<IpmiValue, Mode::Modes> modeIpmiToDbus =
+{
+    {0x03, Mode::Modes::Safe},
+    {0x06, Mode::Modes::Setup},
+    {ipmiDefault, Mode::Modes::Regular}
 };
 
-uint8_t get_ipmi_boot_option(char *p) {
+std::map<Source::Sources, IpmiValue> sourceDbusToIpmi =
+{
+    {Source::Sources::Network, 0x01},
+    {Source::Sources::Disk, 0x02},
+    {Source::Sources::ExternalMedia, 0x05},
+    {Source::Sources::Default, ipmiDefault}
+};
 
-    bootOptionTypeMap_t *s = g_bootOptionTypeMap_t;
+std::map<Mode::Modes, IpmiValue> modeDbusToIpmi =
+{
+    {Mode::Modes::Safe, 0x03},
+    {Mode::Modes::Setup, 0x06},
+    {Mode::Modes::Regular, ipmiDefault}
+};
 
-    while (s->ipmibootflag != 0xFF) {
-        if (!strcmp(s->dbusname,p))
-            break;
-        s++;
-    }
-
-    if (!s->ipmibootflag)
-        printf("Failed to find Sensor Type %s\n", p);
-
-    return s->ipmibootflag;
-}
-
-char* get_boot_option_by_ipmi(uint8_t p) {
-
-    bootOptionTypeMap_t *s = g_bootOptionTypeMap_t;
-
-    while (s->ipmibootflag != 0xFF) {
-
-        if (s->ipmibootflag == p)
-            break;
-
-        s++;
-    }
-
-
-    if (!s->ipmibootflag)
-        printf("Failed to find Sensor Type 0x%x\n", p);
-
-    return s->dbusname;
-}
+} // namespace boot_options
 
 ipmi_ret_t ipmi_chassis_get_sys_boot_options(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
                                              ipmi_request_t request,
@@ -1216,11 +1226,12 @@
                                              ipmi_data_len_t data_len,
                                              ipmi_context_t context)
 {
+    using namespace boot_options;
     ipmi_ret_t rc = IPMI_CC_PARM_NOT_SUPPORTED;
     char *p = NULL;
     get_sys_boot_options_response_t *resp = (get_sys_boot_options_response_t *) response;
     get_sys_boot_options_t *reqptr = (get_sys_boot_options_t*) request;
-    uint8_t s;
+    IpmiValue bootOption = ipmiDefault;
 
     printf("IPMI GET_SYS_BOOT_OPTIONS\n");
 
@@ -1238,29 +1249,63 @@
     ( BootOptionParameter::BOOT_FLAGS )) {
 
         *data_len = static_cast<uint8_t>(BootOptionResponseSize::BOOT_FLAGS);
-        /* Get the boot device */
-        int r = dbus_get_property("boot_flags",&p);
+        using namespace chassis::internal;
+        using namespace chassis::internal::cache;
 
-        if (r < 0) {
-            fprintf(stderr, "Dbus get property(boot_flags) failed for get_sys_boot_options.\n");
-            rc = IPMI_CC_UNSPECIFIED_ERROR;
-
-        } else {
-
-            s = get_ipmi_boot_option(p);
-            resp->data[1] = (s << 2);
-            rc = IPMI_CC_OK;
-
-        }
-
-        if (p)
+        const auto& bootSourceSetting = objects.map.at(bootSourceIntf);
+        auto method =
+            dbus.new_method_call(
+                 objects.service(bootSourceSetting, bootSourceIntf).c_str(),
+                 bootSourceSetting.c_str(),
+                 PROP_INTF,
+                 "Get");
+        method.append(bootSourceIntf, "BootSource");
+        auto reply = dbus.call(method);
+        if (reply.is_method_error())
         {
-            free(p);
-            p = NULL;
+            log<level::ERR>("Error in BootSource Get");
+            report<InternalFailure>();
+            *data_len = 0;
+            return IPMI_CC_UNSPECIFIED_ERROR;
         }
+        sdbusplus::message::variant<std::string> result;
+        reply.read(result);
+        auto bootSource =
+            Source::convertSourcesFromString(result.get<std::string>());
+
+        const auto& bootModeSetting = objects.map.at(bootModeIntf);
+        method = dbus.new_method_call(
+                      objects.service(bootModeSetting, bootModeIntf).c_str(),
+                      bootModeSetting.c_str(),
+                      PROP_INTF,
+                      "Get");
+        method.append(bootModeIntf, "BootMode");
+        reply = dbus.call(method);
+        if (reply.is_method_error())
+        {
+            log<level::ERR>("Error in BootMode Get");
+            report<InternalFailure>();
+            *data_len = 0;
+            return IPMI_CC_UNSPECIFIED_ERROR;
+        }
+        reply.read(result);
+        auto bootMode = Mode::convertModesFromString(result.get<std::string>());
+
+        bootOption = sourceDbusToIpmi.at(bootSource);
+        if ((Mode::Modes::Regular == bootMode) &&
+            (Source::Sources::Default == bootSource))
+        {
+            bootOption = ipmiDefault;
+        }
+        else if (Source::Sources::Default == bootSource)
+        {
+            bootOption = modeDbusToIpmi.at(bootMode);
+        }
+        resp->data[1] = (bootOption << 2);
+        rc = IPMI_CC_OK;
 
         /* Get the boot policy */
-        r = dbus_get_property("boot_policy",&p);
+        int r = dbus_get_property("boot_policy",&p);
 
         if (r < 0) {
             fprintf(stderr, "Dbus get property(boot_policy) failed for get_sys_boot_options.\n");
@@ -1318,8 +1363,8 @@
                                              ipmi_data_len_t data_len,
                                              ipmi_context_t context)
 {
+    using namespace boot_options;
     ipmi_ret_t rc = IPMI_CC_OK;
-    char *s;
     set_sys_boot_options_t *reqptr = (set_sys_boot_options_t *) request;
 
     printf("IPMI SET_SYS_BOOT_OPTIONS reqptr->parameter =[%d]\n",reqptr->parameter);
@@ -1332,31 +1377,67 @@
      * This is the only parameter used by petitboot.
      */
 
-    if (reqptr->parameter == (uint8_t)BootOptionParameter::BOOT_FLAGS) {
+    if (reqptr->parameter == (uint8_t)BootOptionParameter::BOOT_FLAGS)
+    {
+        IpmiValue bootOption = ((reqptr->data[1] & 0x3C) >> 2);
+        using namespace chassis::internal;
+        using namespace chassis::internal::cache;
 
-        s = get_boot_option_by_ipmi(((reqptr->data[1] & 0x3C) >> 2));
-
-        printf("%d: %s\n", __LINE__, s);
-        if (!strcmp(s,INVALID_STRING)) {
-
-            rc = IPMI_CC_PARM_NOT_SUPPORTED;
-
-        } else {
-
-            int r = dbus_set_property("boot_flags",s);
-
-            if (r < 0) {
-                fprintf(stderr, "Dbus set property(boot_flags) failed for set_sys_boot_options.\n");
-                rc = IPMI_CC_UNSPECIFIED_ERROR;
+        auto modeItr = modeIpmiToDbus.find(bootOption);
+        auto sourceItr = sourceIpmiToDbus.find(bootOption);
+        if ((ipmiDefault == bootOption) ||
+            (sourceIpmiToDbus.end() != sourceItr))
+        {
+            sdbusplus::message::variant<std::string> property =
+                convertForMessage(sourceItr->second);
+            const auto& bootSourceSetting =
+                objects.map.at(bootSourceIntf);
+            auto method =
+                dbus.new_method_call(
+                     objects.service(bootSourceSetting, bootSourceIntf).c_str(),
+                     bootSourceSetting.c_str(),
+                     PROP_INTF,
+                     "Set");
+            method.append(bootSourceIntf, "BootSource", property);
+            auto reply = dbus.call(method);
+            if (reply.is_method_error())
+            {
+                log<level::ERR>("Error in BootSource Set");
+                report<InternalFailure>();
+                *data_len = 0;
+                return IPMI_CC_UNSPECIFIED_ERROR;
+            }
+        }
+        if ((ipmiDefault == bootOption) ||
+            (modeIpmiToDbus.end() != modeItr))
+        {
+            sdbusplus::message::variant<std::string> property =
+                convertForMessage(modeItr->second);
+            const auto& bootModeSetting = objects.map.at(bootModeIntf);
+            auto method =
+                dbus.new_method_call(
+                     objects.service(bootModeSetting, bootModeIntf).c_str(),
+                     bootModeSetting.c_str(),
+                     PROP_INTF,
+                     "Set");
+            method.append(bootModeIntf, "BootMode", property);
+            auto reply = dbus.call(method);
+            if (reply.is_method_error())
+            {
+                log<level::ERR>("Error in BootMode Set");
+                report<InternalFailure>();
+                *data_len = 0;
+                return IPMI_CC_UNSPECIFIED_ERROR;
             }
         }
 
         /* setting the boot policy */
-        s = (char *)(((reqptr->data[0] & SET_PARM_BOOT_FLAGS_PERMANENT) ==
+        std::string value =
+            (char *)(((reqptr->data[0] & SET_PARM_BOOT_FLAGS_PERMANENT) ==
                 SET_PARM_BOOT_FLAGS_PERMANENT) ?"PERMANENT":"ONETIME");
 
-        printf ( "\nBoot Policy is %s",s);
-        int r = dbus_set_property("boot_policy",s);
+        printf ( "\nBoot Policy is %s",value.c_str());
+        int r = dbus_set_property("boot_policy",value.c_str());
 
         if (r < 0) {
             fprintf(stderr, "Dbus set property(boot_policy) failed for set_sys_boot_options.\n");