Add support for post code handling/eventing

Add support to consume a JSON configuration which
will let a platform configuration to dictate if
we need to do special handling or logging based
on specific post codes received.

Tested:

1. Created the following config and after restarting
`xyz.openbmc_project.State.Boot.PostCode@0.service`:
```
[
    {
        "primary": [1,2,5],
        "event": {
            "name": "xyz.openbmc_project.State.SMC.SMCFailed",
            "arguments": {
                "IDENTIFIER": "test",
                "FAILURE_TYPE": "world"
            }
        }
    }
]
```

Created the primary post code:
```
root@bmc:~# busctl set-property xyz.openbmc_project.State.Boot.Raw /xyz/openbmc_project/state/boot/raw0 xyz.openbmc_project.State.Boot.Raw Value '(ayay)' 3 0x1 0x2 0x5 0x0
```
Check that the log is created:
```
root@bmc:~# busctl introspect -l xyz.openbmc_project.Logging /xyz/openbmc_project/logging/entry/2 xyz.openbmc_project.Logging.Entry | grep "AdditionalData\|Message"
.AdditionalData property  a{ss}     6 "FAILURE_TYPE" "world" "IDENTIFIER" "test" <snip>
.Message property  s "xyz.openbmc_project.State.SMC.SMCFailed"
```
2. Replace the config with:
```
[
    {
        "primary": [1,2,6],
        "targets": ["testservice.service"]
    }
]
```
Create a test unit file:
testservice.service:
```
[Unit]
Description=A simple oneshot service

[Service]
Type=oneshot
ExecStart=/bin/bash -c "echo Hello world > /tmp/test.txt"
```
Issue a new post code with the new config.
```
systemctl daemon-reload
systemctl restart xyz.openbmc_project.State.Boot.PostCode@0.service
root@bmc:/usr/lib/systemd/system# busctl set-property xyz.openbmc_project.State.Boot.Raw /xyz/openbmc_project/state/boot/raw0 xyz.openbmc_project.State.Boot.Raw Value '(ayay)' 3 0x1 0x2 0x5 0x0
root@bmc:/usr/lib/systemd/system# cat /tmp/test.txt
Hello world
```

Change-Id: Ibaa09fb88190a344fd7c4fadd24dda4aa4ae0633
Signed-off-by: Amithash Prasad <amithash@meta.com>
diff --git a/inc/post_code.hpp b/inc/post_code.hpp
index 9127cbf..262a773 100644
--- a/inc/post_code.hpp
+++ b/inc/post_code.hpp
@@ -18,6 +18,7 @@
 #include <fcntl.h>
 #include <unistd.h>
 
+#include <nlohmann/json.hpp>
 #include <phosphor-logging/elog-errors.hpp>
 #include <sdbusplus/timer.hpp>
 #include <xyz/openbmc_project/Collection/DeleteAll/server.hpp>
@@ -61,10 +62,33 @@
 using delete_all =
     sdbusplus::xyz::openbmc_project::Collection::server::DeleteAll;
 
+struct PostCodeEvent
+{
+    std::string name;
+    nlohmann::json args;
+    void raise() const;
+};
+
+struct PostCodeHandler
+{
+    primarycode_t primary;
+    std::optional<secondarycode_t> secondary;
+    std::vector<std::string> targets;
+    std::optional<PostCodeEvent> event;
+};
+
+struct PostCodeHandlers
+{
+    std::vector<PostCodeHandler> handlers;
+    void handle(postcode_t code);
+    const PostCodeHandler* find(postcode_t code);
+    void load(const std::string& path);
+};
+
 struct PostCode : sdbusplus::server::object_t<post_code, delete_all>
 {
     PostCode(sdbusplus::bus_t& bus, const char* path, EventPtr& event,
-             int nodeIndex) :
+             int nodeIndex, PostCodeHandlers& handlers) :
         sdbusplus::server::object_t<post_code, delete_all>(bus, path), bus(bus),
         event(event), node(nodeIndex),
         postCodeListPath(PostCodeListPathPrefix + std::to_string(node)),
@@ -116,7 +140,8 @@
                         }
                     }
                 }
-            })
+            }),
+        postCodeHandlers(std::move(handlers))
     {
         phosphor::logging::log<phosphor::logging::level::INFO>(
             "PostCode is created");
@@ -156,4 +181,5 @@
     bool deserialize(const fs::path& path, uint16_t& index);
     bool deserializePostCodes(const fs::path& path,
                               std::map<uint64_t, postcode_t>& codes);
+    PostCodeHandlers postCodeHandlers;
 };