TPM code updater
This commit introduces a TPM code updater that currently supports
reading the firmware version for both Infineon and Nuvoton TPM 2.0.
Support for firmware updates will be introduced in a future patch.
The updater's configuration are managed by the EM [1].
[1] https://gerrit.openbmc.org/c/openbmc/entity-manager/+/82416
Tested on Yosemite5 with the following steps:
1. Display the fw inventory:
```
curl --silent $creds https://$bmc/redfish/v1/UpdateService/FirmwareInventory
{
"@odata.id": "/redfish/v1/UpdateService/FirmwareInventory",
"@odata.type": "#SoftwareInventoryCollection.SoftwareInventoryCollection",
"Members": [
{...},
{
"@odata.id": "/redfish/v1/UpdateService/FirmwareInventory/Yosemite5_TPM_4945"
},
{...}
],
"Members@odata.count": 4,
"Name": "Software Inventory Collection"
}
```
2. Query TPM version:
```
curl --silent $creds https://$bmc/redfish/v1/UpdateService/FirmwareInventory/Yosemite5_TPM_4945
{
"@odata.id": "/redfish/v1/UpdateService/FirmwareInventory/Yosemite5_TPM_4945",
"@odata.type": "#SoftwareInventory.v1_1_0.SoftwareInventory",
"Description": "Unknown image",
"Id": "Yosemite5_TPM_4945",
"Name": "Software Inventory",
"Status": {
"Health": "Warning",
"HealthRollup": "OK",
"State": "Disabled"
},
"Updateable": false,
"Version": "15.23"
}
```
Change-Id: I42568242356d55fe005ba1f41ddf8aaf9f682fc8
Signed-off-by: Kevin Tung <kevin.tung.openbmc@gmail.com>
diff --git a/common/src/utils.cpp b/common/src/utils.cpp
index 683ca84..2e6d147 100644
--- a/common/src/utils.cpp
+++ b/common/src/utils.cpp
@@ -4,11 +4,14 @@
PHOSPHOR_LOG2_USING;
-sdbusplus::async::task<bool> asyncSystem(sdbusplus::async::context& ctx,
- const std::string& cmd)
+sdbusplus::async::task<bool> asyncSystem(
+ sdbusplus::async::context& ctx, const std::string& cmd,
+ std::optional<std::reference_wrapper<std::string>> result)
{
- int pipefd[2];
- if (pipe(pipefd) == -1)
+ int exitPipefd[2];
+ int resultPipefd[2];
+
+ if (pipe(exitPipefd) == -1 || (result && pipe(resultPipefd) == -1))
{
error("Failed to create pipe for command: {CMD}", "CMD", cmd);
co_return false;
@@ -17,32 +20,59 @@
pid_t pid = fork();
if (pid == 0)
{
- close(pipefd[0]);
+ close(exitPipefd[0]);
+
+ if (result)
+ {
+ close(resultPipefd[0]);
+ dup2(resultPipefd[1], STDOUT_FILENO);
+ dup2(resultPipefd[1], STDERR_FILENO);
+ close(resultPipefd[1]);
+ }
int exitCode = std::system(cmd.c_str());
- ssize_t status = write(pipefd[1], &exitCode, sizeof(exitCode));
+ ssize_t status = write(exitPipefd[1], &exitCode, sizeof(exitCode));
- close(pipefd[1]);
+ close(exitPipefd[1]);
_exit((status == sizeof(exitCode)) ? 0 : 1);
}
else if (pid > 0)
{
- close(pipefd[1]);
+ close(exitPipefd[1]);
- auto fdio = std::make_unique<sdbusplus::async::fdio>(ctx, pipefd[0]);
+ if (result)
+ {
+ close(resultPipefd[1]);
+ }
+
+ auto fdio =
+ std::make_unique<sdbusplus::async::fdio>(ctx, exitPipefd[0]);
if (!fdio)
{
error("Failed to create fdio for command: {CMD}", "CMD", cmd);
- close(pipefd[0]);
+ close(exitPipefd[0]);
co_return false;
}
co_await fdio->next();
+ if (result)
+ {
+ auto& resStr = result->get();
+ resStr.clear();
+ char buffer[1024];
+ ssize_t n;
+ while ((n = read(resultPipefd[0], buffer, sizeof(buffer))) > 0)
+ {
+ resStr.append(buffer, n);
+ }
+ close(resultPipefd[0]);
+ }
+
int exitCode = -1;
- ssize_t bytesRead = read(pipefd[0], &exitCode, sizeof(exitCode));
- close(pipefd[0]);
+ ssize_t bytesRead = read(exitPipefd[0], &exitCode, sizeof(exitCode));
+ close(exitPipefd[0]);
if (bytesRead != sizeof(exitCode))
{
@@ -72,8 +102,13 @@
else
{
error("Fork failed for command: {CMD}", "CMD", cmd);
- close(pipefd[0]);
- close(pipefd[1]);
+ close(exitPipefd[0]);
+ close(exitPipefd[1]);
+ if (result)
+ {
+ close(resultPipefd[0]);
+ close(resultPipefd[1]);
+ }
co_return false;
}
}