Add i2c voltage regulator updater

- /i2c-vr: Classes following the design in [1]
- /i2c-vr/vr.cpp, vr.hpp: General representation of a voltage regulators
  communication interface
- /vr-i2c/xdpe1x2xx: Support for Infineon XDPE1x2xx class of voltage
  regulators
- /common/i2c/: Basic I2C communication interface

The configuration of a voltage regulator relies on the EM-Schema in [2]

1: https://github.com/openbmc/docs/blob/master/designs/code-update.md
2: https://gerrit.openbmc.org/c/openbmc/entity-manager/+/77463

Tested on QEMU/Yosemite4:

1. Display the firmware inventory
```
curl --insecure --user root:0penBmc \
https://127.0.0.1:2443/redfish/v1/UpdateService/FirmwareInventory
```

Output:
```
{
  "@odata.id": "/redfish/v1/UpdateService/FirmwareInventory",
  "@odata.type": "#SoftwareInventoryCollection.SoftwareInventoryCollection",
  "Members": [
    {
      "@odata.id": "/redfish/v1/UpdateService/FirmwareInventory/16bae6fd"
    },
    {
      "@odata.id": "/redfish/v1/UpdateService/FirmwareInventory/DummyDeviceFirmwareName_6637"
    },
    {
      "@odata.id": "/redfish/v1/UpdateService/FirmwareInventory/Management_Board_cpld"
    },
    {...}
```

2. Query voltage regulator version

The dummy device sets the default version to 0xBEEF (Decimal: 48879)
```
curl --insecure --user root:0penBmc \
https://127.0.0.1:2443/redfish/v1/UpdateService/FirmwareInventory/
DummyDeviceFirmwareName_4390
```

Output:
```
{
  "@odata.id": "/redfish/v1/UpdateService/FirmwareInventory/DummyDeviceFirmwareName_4390",
  "@odata.type": "#SoftwareInventory.v1_1_0.SoftwareInventory",
  "Description": "Other image",
  "Id": "DummyDeviceFirmwareName_4390",
  "Name": "Software Inventory",
  "Status": {
    "Health": "Warning",
    "HealthRollup": "OK",
    "State": "Disabled"
  },
  "Updateable": false,
  "Version": "48879"
}
```

3. Trigger the update
```
curl -k --insecure --user root:0penBmc \
-H "Content-Type:multipart/form-data" \
-X POST \
-F UpdateParameters="{\"Targets\":[\"/redfish/v1/UpdateService/FirmwareInventory/DummyDeviceFirmwareName_4390\"],\"@Redfish.OperationApplyTime\":\"Immediate\"};type=application/json" \
-F "UpdateFile=@fw_vr_update.bin;type=application/octet-stream" \
https://127.0.0.1:2443/redfish/v1/UpdateService/update
```

4. Task is returned
```
{
  "@odata.id": "/redfish/v1/TaskService/Tasks/0",
  "@odata.type": "#Task.v1_4_3.Task",
  "Id": "0",
  "TaskState": "Running",
  "TaskStatus": "OK"
}
```
5. Query the task
```
curl --insecure --user root:0penBmc \
https://127.0.0.1:2443/redfish/v1/TaskService/Tasks/0
```

Output:
```
{
  "@odata.id": "/redfish/v1/TaskService/Tasks/0",
  "@odata.type": "#Task.v1_4_3.Task",
  "EndTime": "2025-03-10T13:47:34+00:00",
  "HidePayload": false,
  "Id": "0",
  "Messages": [
    {
      "@odata.type": "#Message.v1_1_1.Message",
      "Message": "The task with Id '0' has started.",
      "MessageArgs": [
        "0"
      ],
      "MessageId": "TaskEvent.1.0.TaskStarted",
      "MessageSeverity": "OK",
      "Resolution": "None."
    },
    {
      "@odata.type": "#Message.v1_1_1.Message",
      "Message": "The task with Id '0' has completed.",
      "MessageArgs": [
        "0"
      ],
      "MessageId": "TaskEvent.1.0.TaskCompletedOK",
      "MessageSeverity": "OK",
      "Resolution": "None."
    }
  ],
  "Name": "Task 0",
  "Payload": {
    "HttpHeaders": [],
    "HttpOperation": "POST",
    "JsonBody": "null",
    "TargetUri": "/redfish/v1/UpdateService/update"
  },
  "PercentComplete": 0,
  "StartTime": "2025-03-10T13:47:34+00:00",
  "TaskMonitor": "/redfish/v1/TaskService/TaskMonitors/0",
  "TaskState": "Completed",
  "TaskStatus": "OK"
}
```

6. Display fw inventory after update
```
curl --insecure --user root:0penBmc \
https://127.0.0.1:2443/redfish/v1/UpdateService/FirmwareInventory
```

Output:
```
{
  "@odata.id": "/redfish/v1/UpdateService/FirmwareInventory",
  "@odata.type": "#SoftwareInventoryCollection.SoftwareInventoryCollection",
  "Members": [
    {
      "@odata.id": "/redfish/v1/UpdateService/FirmwareInventory/16bae6fd"
    },
    {
      "@odata.id": "/redfish/v1/UpdateService/FirmwareInventory/DummyDeviceFirmwareName_282"
    },
    {...}
}
```

7. Query the new fw version.

The version is 'mycompversion' since that's what has been set in the
pldm fw update package for testing.

```
curl --insecure --user root:0penBmc \
https://127.0.0.1:2443/redfish/v1/UpdateService/FirmwareInventory/
DummyDeviceFirmwareName_282
```

Output:
```
{
  "@odata.id": "/redfish/v1/UpdateService/FirmwareInventory/DummyDeviceFirmwareName_282",
  "@odata.type": "#SoftwareInventory.v1_1_0.SoftwareInventory",
  "Description": "Other image",
  "Id": "DummyDeviceFirmwareName_282",
  "Name": "Software Inventory",
  "Status": {
    "Health": "OK",
    "HealthRollup": "OK",
    "State": "Enabled"
  },
  "Updateable": false,
  "Version": "mycompversion"
}
```

8. Update in progress error

```
curl -k --insecure --user root:0penBmc \
-H "Content-Type:multipart/form-data" \
-X POST \
-F UpdateParameters="{\"Targets\":[\"/redfish/v1/UpdateService/FirmwareInventory/${TARGET}\"],\"@Redfish.OperationApplyTime\":\"Immediate\"};type=application/json" \
-F "UpdateFile=@${FWPATH};type=application/octet-stream" \
https://127.0.0.1:2443/redfish/v1/UpdateService/update
```

Output:
```
{
  "error": {
    "@Message.ExtendedInfo": [
      {
        "@odata.type": "#Message.v1_1_1.Message",
        "Message": "The request failed due to an internal service error.  The service is still operational.",
        "MessageArgs": [],
        "MessageId": "Base.1.19.InternalError",
        "MessageSeverity": "Critical",
        "Resolution": "Resubmit the request.  If the problem persists, consider resetting the service."
      }
    ],
    "code": "Base.1.19.InternalError",
    "message": "The request failed due to an internal service error.  The service is still operational."
  }
```

Change-Id: I2e11a6c10ae40ed7719ceb86dfd6a38dd5b27017
Signed-off-by: Christopher Meis <christopher.meis@9elements.com>
diff --git a/i2c-vr/vr.cpp b/i2c-vr/vr.cpp
new file mode 100644
index 0000000..f7c7c0f
--- /dev/null
+++ b/i2c-vr/vr.cpp
@@ -0,0 +1,40 @@
+#include "vr.hpp"
+
+#include "xdpe1x2xx/xdpe1x2xx.hpp"
+
+#include <map>
+
+namespace phosphor::software::VR
+{
+
+std::unique_ptr<VoltageRegulator> create(sdbusplus::async::context& ctx,
+                                         enum VRType vrType, uint16_t bus,
+                                         uint16_t address)
+{
+    std::unique_ptr<VoltageRegulator> ret;
+    switch (vrType)
+    {
+        case VRType::XDPE1X2XX:
+            ret = std::make_unique<XDPE1X2XX>(ctx, bus, address);
+            break;
+        default:
+            return NULL;
+    }
+    return ret;
+}
+
+bool stringToEnum(std::string& vrStr, VRType& vrType)
+{
+    std::map<std::string, enum VRType> VRTypeToString{
+        {"XDPE1X2XXFirmware", VRType::XDPE1X2XX},
+    };
+
+    if (VRTypeToString.contains(vrStr))
+    {
+        vrType = VRTypeToString[vrStr];
+        return true;
+    }
+    return false;
+}
+
+} // namespace phosphor::software::VR