common: update: fix error handling

An empty string is not a valid object path [1].

Handle the error by throwing a generated exception as per the
example [3]. This should result in bmcweb receiving the error.

The exception is generated from [2] and caught in a wrapper function to
set the error.

Tested: on Tyan S8030

First, apply patch to disallow the `OnReset` apply time.

Then trigger the update with a tiny pldm package.

```
curl -k --insecure --user root:root -H Content-Type:multipart/form-data -X POST -F 'UpdateParameters={"Targets":["/redfish/v1/UpdateService/FirmwareInventory/HostSPIFlash_4102"],"@Redfish.OperationApplyTime":"OnReset"};type=application/json' -F 'UpdateFile=@pldm-package-s8030-host-fake.bin;type=application/octet-stream' ${bmc}/redfish/v1/UpdateService/update-multipart
```

Instead of a task we now get
```
{
  "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."
  }
}
```

The updater log is

```
Aug 11 14:16:43 s8030-bmc-30303035c0c1 phosphor-bios-software-update[1101]: the selected apply time xyz.openbmc_project.Software.ApplyTime.RequestedApplyTimes.OnReset is not allowed by the device
Aug 11 14:16:43 s8030-bmc-30303035c0c1 phosphor-bios-software-update[1101]: The system component has a software version which is incompatible with the new image or the image is not meant for the system component.
```

The bmcweb log is

```
Aug 11 14:16:43 s8030-bmc-30303035c0c1 bmcwebd[431]: [update_service.hpp:876] Found 2 software version paths
Aug 11 14:16:43 s8030-bmc-30303035c0c1 bmcwebd[431]: [update_service.hpp:894] Found software version path /xyz/openbmc_project/software/HostSPIFlash_4102 serviceName xyz.openbmc_project.Software.BIOS
Aug 11 14:16:43 s8030-bmc-30303035c0c1 bmcwebd[431]: [update_service.hpp:831] error_code = Input/output error [generic:5]
Aug 11 14:16:43 s8030-bmc-30303035c0c1 bmcwebd[431]: [update_service.hpp:832] error msg = Input/output error
Aug 11 14:16:43 s8030-bmc-30303035c0c1 bmcwebd[431]: [error_messages.cpp:1250] Internal Error ../git/redfish-core/lib/update_service.hpp(833:32) `void redfish::handleStartUpdate(const std::shared_ptr<bmcweb::AsyncResp>&, task::Payload, const std::string&, const boost::system::error_code&, const sdbusplus::message::object_path&)`:
```

Now testing the second case, started an immediate update with a real fw
image which will be running for some time.

```
curl -k --insecure --user root:root -H Content-Type:multipart/form-data -X POST -F 'UpdateParameters={"Targets":["/redfish/v1/UpdateService/FirmwareInventory/HostSPIFlash_4102"],"@Redfish.OperationApplyTime":"Immediate"};type=application/json' -F 'UpdateFile=@pldm-package-s8030-host-v4.03.bin;type=application/octet-stream' ${bmc}/redfish/v1/UpdateService/update-multipart
```

get following task

```
{
  "@odata.id": "/redfish/v1/TaskService/Tasks/1",
  "@odata.type": "#Task.v1_4_3.Task",
  "HidePayload": false,
  "Id": "1",
  "Messages": [
    {
      "@odata.type": "#Message.v1_1_1.Message",
      "Message": "The task with Id '1' has started.",
      "MessageArgs": [
        "1"
      ],
      "MessageId": "TaskEvent.1.0.TaskStarted",
      "MessageSeverity": "OK",
      "Resolution": "None."
    }
  ],
  "Name": "Task 1",
  "Payload": {
    "HttpHeaders": [],
    "HttpOperation": "POST",
    "TargetUri": "/redfish/v1/UpdateService/update-multipart"
  },
  "PercentComplete": 0,
  "StartTime": "2025-08-11T14:27:25+00:00",
  "TaskMonitor": "/redfish/v1/TaskService/TaskMonitors/1",
  "TaskState": "Running",
  "TaskStatus": "OK"
}
```

and bmcweb logs
```
Aug 11 14:31:24 s8030-bmc-30303035c0c1 bmcwebd[431]: [update_service.hpp:876] Found 2 software version paths
Aug 11 14:31:24 s8030-bmc-30303035c0c1 bmcwebd[431]: [update_service.hpp:894] Found software version path /xyz/openbmc_project/software/HostSPIFlash_4102 serviceName xyz.openbmc_project.Software.BIOS
Aug 11 14:31:24 s8030-bmc-30303035c0c1 bmcwebd[431]: [update_service.hpp:838] Call to StartUpdate on /xyz/openbmc_project/software/HostSPIFlash_4102 Success, retPath = /xyz/openbmc_project/software/HostSPIFlash_2903
```

Now quickly start a second update to get following logs

Redfish response:
```
{
  "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."
  }
}
```

Updater:
```
Aug 11 14:31:24 s8030-bmc-30303035c0c1 phosphor-bios-software-update[1101]: An update is already in progress, cannot update.
Aug 11 14:31:24 s8030-bmc-30303035c0c1 phosphor-bios-software-update[1101]: The service is temporarily unavailable.
```

bmcweb logs:
```
Aug 11 14:31:25 s8030-bmc-30303035c0c1 bmcwebd[431]: [error_messages.cpp:1250] Internal Error ../git/redfish-core/lib/update_service.hpp(833:32) `void redfish::handleStartUpdate(const std::shared_ptr<bmcweb::Asyn
cResp>&, task::Payload, const std::string&, const boost::system::error_code&, const sdbusplus::message::object_path&)`:
Aug 11 14:31:25 s8030-bmc-30303035c0c1 bmcwebd[431]: [update_service.hpp:832] error msg = Input/output error
Aug 11 14:31:25 s8030-bmc-30303035c0c1 bmcwebd[431]: [update_service.hpp:831] error_code = Input/output error [generic:5]
```

So in both error cases both daemons stay running, but the error
reporting to the user can be improved in bmcweb to let them know the
failure reason.

References:

[1] https://dbus.freedesktop.org/doc/dbus-specification.html#message-protocol-marshaling-object-path
[2] https://github.com/openbmc/phosphor-dbus-interfaces/blob/master/yaml/xyz/openbmc_project/Software/Update.interface.yaml
[3] https://github.com/openbmc/sdbusplus/blob/7413ccc1740397239eee9ba79973c285bf6b3e5d/example/calculator-aserver.cpp#L28

Change-Id: I292687652dbeefb15a150757289aebe8fd763482
Signed-off-by: Alexander Hansen <alexander.hansen@9elements.com>
1 file changed
tree: 678e84a0bbd4c9408bc6806b4def7c9bdd760423
  1. bios/
  2. bmc/
  3. common/
  4. cpld/
  5. eeprom-device/
  6. i2c-vr/
  7. subprojects/
  8. test/
  9. .clang-format
  10. .clang-tidy
  11. .gitignore
  12. .shellcheck
  13. LICENSE
  14. meson.build
  15. meson.options
  16. OWNERS
  17. README.md
README.md

phosphor-bmc-code-mgmt

Phosphor BMC Code Management provides a set of system software management applications. More information can be found at Software Architecture

To Build

To build this package, do the following steps:

  1. meson build
  2. ninja -C build

To clean the repository run rm -r build.