Select primary/secondary BOOT/MEASUREMENT SEEPROM based on boot count

Changes include:
   1) selection of primary/secondary seeprom before booting host
   2) structure name change from PACKED to PACK to avoid conflict with
      attributes_info.H

Tests done :
- Verified the right bit set for Primary Vs Secondary Boot path
- Verified attribute GET/SET working good

Signed-off-by: Lakshminarayana R. Kammath <lkammath@in.ibm.com>
Change-Id: I3017b0e9118119cc0a5e478f262641ce539ac4ff
diff --git a/configure.ac b/configure.ac
index fecae53..971be69 100644
--- a/configure.ac
+++ b/configure.ac
@@ -73,6 +73,10 @@
                AC_MSG_ERROR([EKB library not found])
        fi
 
+       PKG_CHECK_MODULES([LIBDT_API], [libdt-api])
+       LIBS="$LIBS $LIBDT_API_LIBS"
+       CFLAGS="$CFLAGS $LIBDT_API_CFLAGS"
+
        CHIPS+=" phal common"
        AC_CONFIG_FILES([set-spi-mux.service])
       ]
diff --git a/procedures/common/collect_sbe_hb_data.cpp b/procedures/common/collect_sbe_hb_data.cpp
index b29d194..6cba8ee 100644
--- a/procedures/common/collect_sbe_hb_data.cpp
+++ b/procedures/common/collect_sbe_hb_data.cpp
@@ -52,7 +52,7 @@
         uint32_t minorStep : 6;
         uint32_t reserved2 : 6;
 #endif
-    } PACKED;
+    } PACK;
 };
 
 // HB mailbox scratch register 5 - cfam 283C
@@ -78,7 +78,7 @@
         uint32_t majorStep : 8;    // 16:23
         uint32_t minorStep : 8;    // 24:31
 #endif
-    } PACKED;
+    } PACK;
 };
 
 static constexpr uint8_t HB_MBX5_VALID_FLAG = 0xAA;
@@ -105,8 +105,8 @@
             auto msg = reinterpret_cast<const sbeMsgReg_t*>(&readData);
             log<level::INFO>("SBE status register",
                              entry("PROC=%d", proc->getPos()),
-                             entry("SBE_MAJOR_ISTEP=%d", msg->PACKED.majorStep),
-                             entry("SBE_MINOR_ISTEP=%d", msg->PACKED.minorStep),
+                             entry("SBE_MAJOR_ISTEP=%d", msg->PACK.majorStep),
+                             entry("SBE_MINOR_ISTEP=%d", msg->PACK.minorStep),
                              entry("REG_VAL=0x%08X", msg->data32));
         }
         catch (const std::exception& e)
@@ -122,11 +122,11 @@
     {
         auto readData = readReg(master, P9_HB_MBX5_REG);
         auto msg = reinterpret_cast<const MboxScratch5_HB_t*>(&readData);
-        if (HB_MBX5_VALID_FLAG == msg->PACKED.magic)
+        if (HB_MBX5_VALID_FLAG == msg->PACK.magic)
         {
             log<level::INFO>("HB MBOX 5 register",
-                             entry("HB_MAJOR_ISTEP=%d", msg->PACKED.majorStep),
-                             entry("HB_MINOR_ISTEP=%d", msg->PACKED.minorStep),
+                             entry("HB_MAJOR_ISTEP=%d", msg->PACK.majorStep),
+                             entry("HB_MINOR_ISTEP=%d", msg->PACK.minorStep),
                              entry("REG_VAL=0x%08X", msg->data32));
         }
     }
diff --git a/procedures/phal/start_host.cpp b/procedures/phal/start_host.cpp
index 3899924..39229f4 100644
--- a/procedures/phal/start_host.cpp
+++ b/procedures/phal/start_host.cpp
@@ -7,8 +7,11 @@
 #include <libekb.H>
 #include <libipl.H>
 
+#include <ext_interface.hpp>
 #include <phosphor-logging/log.hpp>
 #include <registration.hpp>
+
+#include "attributes_info.H"
 namespace openpower
 {
 namespace phal
@@ -17,6 +20,99 @@
 using namespace phosphor::logging;
 
 /**
+ *  @brief  Check if master processor or not
+ *
+ *  @return True/False
+ */
+bool isMasterProc(struct pdbg_target* procTarget)
+{
+    ATTR_PROC_MASTER_TYPE_Type type;
+
+    // Get processor type (Master or Alt-master)
+    if (DT_GET_PROP(ATTR_PROC_MASTER_TYPE, procTarget, type))
+    {
+        log<level::ERR>("Attribute [ATTR_PROC_MASTER_TYPE] get failed");
+        throw std::runtime_error(
+            "Attribute [ATTR_PROC_MASTER_TYPE] get failed");
+    }
+
+    /* Attribute value 0 corresponds to master processor */
+    if (type == 0)
+    {
+        return true;
+    }
+    else
+    {
+        return false;
+    }
+}
+
+/**
+ *  @brief  Select BOOT SEEPROM and Measurement SEEPROM(PRIMARY/BACKUP) on POWER
+ *          processor position 0/1 depending on boot count before kicking off
+ *          the boot.
+ *
+ *  @return void
+ */
+void selectBootSeeprom()
+{
+    struct pdbg_target* procTarget;
+    ATTR_BACKUP_SEEPROM_SELECT_Enum bkpSeePromSelect;
+    ATTR_BACKUP_MEASUREMENT_SEEPROM_SELECT_Enum bkpMeaSeePromSelect;
+
+    pdbg_for_each_class_target("proc", procTarget)
+    {
+        if (!isMasterProc(procTarget))
+        {
+            continue;
+        }
+
+        // Choose seeprom side to boot from based on boot count
+        if (getBootCount() > 0)
+        {
+            log<level::INFO>("Setting SBE seeprom side to 0",
+                             entry("SBE_SIDE_SELECT=%d",
+                                   ENUM_ATTR_BACKUP_SEEPROM_SELECT_PRIMARY));
+
+            bkpSeePromSelect = ENUM_ATTR_BACKUP_SEEPROM_SELECT_PRIMARY;
+            bkpMeaSeePromSelect =
+                ENUM_ATTR_BACKUP_MEASUREMENT_SEEPROM_SELECT_PRIMARY;
+        }
+        else
+        {
+            log<level::INFO>("Setting SBE seeprom side to 1",
+                             entry("SBE_SIDE_SELECT=%d",
+                                   ENUM_ATTR_BACKUP_SEEPROM_SELECT_SECONDARY));
+            bkpSeePromSelect = ENUM_ATTR_BACKUP_SEEPROM_SELECT_SECONDARY;
+            bkpMeaSeePromSelect =
+                ENUM_ATTR_BACKUP_MEASUREMENT_SEEPROM_SELECT_SECONDARY;
+        }
+
+        // Set the Attribute as per bootcount policy for boot seeprom
+        if (DT_SET_PROP(ATTR_BACKUP_SEEPROM_SELECT, procTarget,
+                        bkpSeePromSelect))
+        {
+            log<level::ERR>(
+                "Attribute [ATTR_BACKUP_SEEPROM_SELECT] set failed");
+            throw std::runtime_error(
+                "Attribute [ATTR_BACKUP_SEEPROM_SELECT] set failed");
+        }
+
+        // Set the Attribute as per bootcount policy for measurement seeprom
+        if (DT_SET_PROP(ATTR_BACKUP_MEASUREMENT_SEEPROM_SELECT, procTarget,
+                        bkpMeaSeePromSelect))
+        {
+            log<level::ERR>(
+                "Attribute [ATTR_BACKUP_MEASUREMENT_SEEPROM_SELECT] set "
+                "failed");
+            throw std::runtime_error(
+                "Attribute [ATTR_BACKUP_MEASUREMENT_SEEPROM_SELECT] set "
+                "failed");
+        }
+    }
+}
+
+/**
  * @brief Starts the self boot engine on POWER processor position 0
  *        to kick off a boot.
  * @return void
@@ -53,6 +149,22 @@
     // To clear trace if success
     openpower::pel::detail::processBootErrorCallback(true);
 
+    // Run select seeprom before poweron
+    try
+    {
+        selectBootSeeprom();
+
+        // To clear trace as it is success
+        openpower::pel::detail::processBootErrorCallback(true);
+    }
+    catch (const std::exception& ex)
+    {
+        // create PEL in failure
+        openpower::pel::detail::processBootErrorCallback(false);
+        log<level::ERR>("SEEPROM selection failed", entry("ERR=%s", ex.what()));
+        throw ex;
+    }
+
     // callback method will be called upon failure which will create the PEL
     int rc = ipl_run_major(0);
     if (rc > 0)