firmware fd: Add PLDM Control version/commands
Supported PLDM firmware (type 5) commands are registered with the PLDM
control responder.
Change-Id: I6a4840a820bf2a1a7967ab9fe927f69681f375d8
Signed-off-by: Matt Johnston <matt@codeconstruct.com.au>
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 5d21dea..ab359ea 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -70,6 +70,9 @@
11. Add PLDM control responder. PLDM types and support commands/versions can be
registered.
+12. PLDM FD responder accepts a PLDM control handle and will register its
+ version.
+
### Fixed
1. dsp: platform: Fix location of closing paren in overflow detection
diff --git a/include/libpldm/firmware_fd.h b/include/libpldm/firmware_fd.h
index 5c45390..d7200b1 100644
--- a/include/libpldm/firmware_fd.h
+++ b/include/libpldm/firmware_fd.h
@@ -11,6 +11,7 @@
#include <libpldm/pldm.h>
#include <libpldm/base.h>
#include <libpldm/utils.h>
+#include <libpldm/control.h>
#include <libpldm/firmware_update.h>
/** @struct pldm_firmware_component_standalone
@@ -243,13 +244,17 @@
* update behaviour
* @param[in] ops_ctx - opaque context pointer that will be passed as ctx
* to ops callbacks
+ * @param[in] control - an optional struct pldm_control. If provided
+ * the FD responder will set PLDM FW update type
+ * and commands for the control.
*
* @return a malloced struct pldm_fd, owned by the caller. It should be released
* with free(). Returns NULL on failure.
*
* This will call pldm_fd_setup() on the allocated pldm_fd.
*/
-struct pldm_fd *pldm_fd_new(const struct pldm_fd_ops *ops, void *ops_ctx);
+struct pldm_fd *pldm_fd_new(const struct pldm_fd_ops *ops, void *ops_ctx,
+ struct pldm_control *control);
/** @brief Initialise a FD responder struct
*
@@ -261,11 +266,15 @@
* update behaviour
* @param[in] ops_ctx - opaque context pointer that will be passed as ctx
* to ops callbacks
+ * @param[in] control - an optional struct pldm_control. If provided
+ * the FD responder will set PLDM FW update type
+ * and commands for the control.
*
* @return 0 on success, a negative errno value on failure.
*/
int pldm_fd_setup(struct pldm_fd *fd, size_t pldm_fd_size,
- const struct pldm_fd_ops *ops, void *ops_ctx);
+ const struct pldm_fd_ops *ops, void *ops_ctx,
+ struct pldm_control *control);
/** @brief Handle a PLDM Firmware Update message
*
diff --git a/src/firmware_device/fd.c b/src/firmware_device/fd.c
index 116657c..f65cfcd 100644
--- a/src/firmware_device/fd.c
+++ b/src/firmware_device/fd.c
@@ -22,6 +22,33 @@
static const uint8_t INSTANCE_ID_COUNT = 32;
static const uint8_t PROGRESS_PERCENT_NOT_SUPPORTED = 101;
+#define PLDM_FD_VERSIONS_COUNT 2
+static const uint32_t PLDM_FD_VERSIONS[PLDM_FD_VERSIONS_COUNT] = {
+ /* Only PLDM Firmware 1.1.0 is current implemented. */
+ 0xf1f1f000,
+ /* CRC. Calculated with python:
+ hex(crccheck.crc.Crc32.calc(struct.pack('<I', 0xf1f1f000)))
+ */
+ 0x539dbeba,
+};
+const bitfield8_t PLDM_FD_COMMANDS[32] = {
+ // 0x00..0x07
+ { .byte = (1 << PLDM_QUERY_DEVICE_IDENTIFIERS |
+ 1 << PLDM_GET_FIRMWARE_PARAMETERS) },
+ { 0 },
+ // 0x10..0x17
+ { .byte = (1u << PLDM_REQUEST_UPDATE | 1u << PLDM_PASS_COMPONENT_TABLE |
+ 1u << PLDM_UPDATE_COMPONENT) >>
+ 0x10 },
+ // 0x18..0x1f
+ {
+ .byte = (1u << PLDM_ACTIVATE_FIRMWARE | 1u << PLDM_GET_STATUS |
+ 1u << PLDM_CANCEL_UPDATE_COMPONENT |
+ 1u << PLDM_CANCEL_UPDATE) >>
+ 0x18,
+ },
+};
+
/* Ensure that public definition is kept updated */
static_assert(alignof(struct pldm_fd) == PLDM_ALIGNOF_PLDM_FD,
"PLDM_ALIGNOF_PLDM_FD wrong");
@@ -1174,11 +1201,13 @@
}
LIBPLDM_ABI_TESTING
-struct pldm_fd *pldm_fd_new(const struct pldm_fd_ops *ops, void *ops_ctx)
+struct pldm_fd *pldm_fd_new(const struct pldm_fd_ops *ops, void *ops_ctx,
+ struct pldm_control *control)
{
struct pldm_fd *fd = malloc(sizeof(*fd));
if (fd) {
- if (pldm_fd_setup(fd, sizeof(*fd), ops, ops_ctx) == 0) {
+ if (pldm_fd_setup(fd, sizeof(*fd), ops, ops_ctx, control) ==
+ 0) {
return fd;
}
free(fd);
@@ -1189,8 +1218,11 @@
LIBPLDM_ABI_TESTING
int pldm_fd_setup(struct pldm_fd *fd, size_t pldm_fd_size,
- const struct pldm_fd_ops *ops, void *ops_ctx)
+ const struct pldm_fd_ops *ops, void *ops_ctx,
+ struct pldm_control *control)
{
+ int rc;
+
if (fd == NULL || ops == NULL) {
return -EINVAL;
}
@@ -1214,6 +1246,16 @@
fd->fd_t1_timeout = DEFAULT_FD_T1_TIMEOUT;
fd->fd_t2_retry_time = DEFAULT_FD_T2_RETRY_TIME;
+ if (control) {
+ rc = pldm_control_add_type(control, PLDM_FWUP,
+ &PLDM_FD_VERSIONS,
+ PLDM_FD_VERSIONS_COUNT,
+ PLDM_FD_COMMANDS);
+ if (rc) {
+ return rc;
+ }
+ }
+
return 0;
}
@@ -1297,7 +1339,8 @@
break;
}
- /* Dispatch command */
+ /* Dispatch command.
+ Update PLDM_FD_COMMANDS if adding new handlers */
switch (hdr.command) {
case PLDM_QUERY_DEVICE_IDENTIFIERS:
rc = pldm_fd_qdi(fd, &hdr, req, req_payload_len, resp,