PHAL: import devtree tool support

Added tool to import devtree attributes from BMC predefined
location to current phal devtree in the system. This tool
is used to override that r/w attribute data after concurrent
code update BMC reboot path.

./openpower-proc-control importDevtree

Tested :  regular reboot path ( with attribute data file)

~# systemctl status phal-import-devtree@0.service
○ phal-import-devtree@0.service - Import Host0 PHAL devtree attributes
     Loaded: loaded (/lib/systemd/system/phal-import-devtree@.service; static)
     Active: inactive (dead) since Mon 2021-08-02 12:03:09 UTC; 2min 55s ago
    Process: 493 ExecStart=/usr/bin/openpower-proc-control importDevtree (code=exited, status=0/SUCCESS)
   Main PID: 493 (code=exited, status=0/SUCCESS)

Aug 02 12:03:02 rain71bmc systemd[1]: Starting Import Host0 PHAL devtree attributes...
Aug 02 12:03:03 rain71bmc systemd[1]: Finished Import Host0 PHAL devtree attributes.
Aug 02 12:03:09 rain71bmc systemd[1]: phal-import-devtree@0.service: Deactivated successfully.
Aug 02 12:03:09 rain71bmc systemd[1]: Stopped Import Host0 PHAL devtree attributes.

Signed-off-by: Jayanth Othayoth <ojayanth@in.ibm.com>
Change-Id: I6ea5e78b4d87a53f45b60ba33a658294feec7c1d
diff --git a/meson.build b/meson.build
index 8a2d7bd..7492300 100644
--- a/meson.build
+++ b/meson.build
@@ -80,9 +80,10 @@
         'procedures/phal/start_host.cpp',
         'procedures/phal/set_SPI_mux.cpp',
         'procedures/phal/proc_pre_poweroff.cpp',
+        'procedures/phal/check_host_running.cpp',
+        'procedures/phal/import_devtree.cpp',
         'extensions/phal/common_utils.cpp',
         'extensions/phal/pdbg_utils.cpp',
-        'procedures/phal/check_host_running.cpp',
         'extensions/phal/create_pel.cpp',
         'extensions/phal/phal_error.cpp',
     ]
diff --git a/procedures/phal/import_devtree.cpp b/procedures/phal/import_devtree.cpp
new file mode 100644
index 0000000..75f1828
--- /dev/null
+++ b/procedures/phal/import_devtree.cpp
@@ -0,0 +1,93 @@
+#include "config.h"
+
+#include "extensions/phal/create_pel.hpp"
+#include "extensions/phal/pdbg_utils.hpp"
+#include "registration.hpp"
+
+#include <fmt/format.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#include <phosphor-logging/elog-errors.hpp>
+#include <phosphor-logging/elog.hpp>
+#include <phosphor-logging/log.hpp>
+#include <xyz/openbmc_project/Common/error.hpp>
+
+#include <filesystem>
+
+namespace openpower
+{
+namespace phal
+{
+
+using namespace phosphor::logging;
+
+void importDevtree()
+{
+    namespace fs = std::filesystem;
+
+    // check import data file is present
+    auto path = fs::path(DEVTREE_EXP_FILE);
+    if (!fs::exists(path))
+    {
+        // No import data file skip devtree import
+        return;
+    }
+
+    // Update PDBG_DTB value
+    openpower::phal::setDevtreeEnv();
+
+    int status = 0;
+    pid_t pid = fork();
+    if (pid == 0)
+    {
+        std::string cmd("/usr/bin/attributes ");
+        cmd += "import ";
+        cmd += DEVTREE_EXP_FILE;
+        execl("/bin/sh", "sh", "-c", cmd.c_str(), 0);
+
+        auto error = errno;
+        log<level::ERR>(fmt::format("Error occurred during attributes import "
+                                    "execution, errno({})",
+                                    error)
+                            .c_str());
+    }
+    else if (pid > 0)
+    {
+        waitpid(pid, &status, 0);
+        if (WEXITSTATUS(status))
+        {
+            log<level::ERR>("Failed to import attribute data");
+            openpower::pel::createPEL("org.open_power.PHAL.Error.devtreeSync");
+            return;
+        }
+    }
+    else
+    {
+        log<level::ERR>("fork() failed.");
+        throw std::runtime_error("importDevtree: fork() failed.");
+    }
+
+    try
+    {
+        // Delete attribute data file once updated.
+        if (fs::exists(path))
+        {
+            // delete export data file
+            fs::remove_all(path);
+        }
+    }
+    catch (fs::filesystem_error& e)
+    { // Log message and continue. Data already applied successfully.
+        log<level::ERR>(fmt::format("File({}) delete failed Error:({})",
+                                    DEVTREE_EXP_FILE, e.what())
+                            .c_str());
+    }
+
+    log<level::INFO>("Successfully imported devtree attribute data");
+}
+
+REGISTER_PROCEDURE("importDevtree", importDevtree)
+
+} // namespace phal
+} // namespace openpower