| /* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ |
| #pragma once |
| |
| #ifdef __cplusplus |
| extern "C" { |
| #endif |
| |
| #include <stdint.h> |
| #include <stdbool.h> |
| |
| #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 |
| * |
| * A PLDM Firmware Update Component representation, for use |
| * with pldm_fd_ops callbacks. |
| */ |
| struct pldm_firmware_component_standalone { |
| uint16_t comp_classification; |
| uint16_t comp_identifier; |
| uint8_t comp_classification_index; |
| |
| struct pldm_firmware_version active_ver; |
| struct pldm_firmware_version pending_ver; |
| |
| bitfield16_t comp_activation_methods; |
| bitfield32_t capabilities_during_update; |
| }; |
| |
| /** @struct pldm_firmware_update_component |
| * |
| * An entry for Pass Component Table or Update Component |
| */ |
| struct pldm_firmware_update_component { |
| uint16_t comp_classification; |
| uint16_t comp_identifier; |
| uint8_t comp_classification_index; |
| uint32_t comp_comparison_stamp; |
| struct pldm_firmware_string version; |
| |
| /* Not set for PassComponentTable */ |
| uint32_t comp_image_size; |
| /* Not set for PassComponentTable */ |
| bitfield32_t update_option_flags; |
| }; |
| |
| /** @struct pldm_fd_ops |
| * |
| * Device-specific callbacks provided by an application, |
| * to define the device update behaviour. |
| * |
| * These will be called by the FD responder when pldm_fd_handle_msg() |
| * or pldm_fd_progress() are called by the application. |
| * |
| * Note that return values vary between functions. Some return a PLDM |
| * completion code or status code which will be sent to the UA, others |
| * return a negative errno on failure. |
| */ |
| struct pldm_fd_ops { |
| /** @brief Provide PLDM descriptors |
| * |
| * @param[in] ctx - callback context |
| * @param[out] ret_descriptors_count - count of descriptors returned |
| * @param[out] ret_descriptors - array of descriptors. |
| * |
| * @return 0 on success, a negative errno value on failure. |
| * (specific errno value is ignored) |
| */ |
| int (*device_identifiers)( |
| void *ctx, uint8_t *ret_descriptors_count, |
| const struct pldm_descriptor **ret_descriptors); |
| |
| /** @brief Provide PLDM component table from the application |
| * |
| * @param[in] ctx - callback context |
| * @param[out] ret_entry_count - length of returned ret_entries |
| * @param[out] ret_entries - an array of component pointers |
| * |
| * @return 0 on success, a negative errno value on failure. |
| * (specific errno value is ignored) |
| * |
| * It will be called several times in an update flow. |
| */ |
| int (*components)( |
| void *ctx, uint16_t *ret_entry_count, |
| const struct pldm_firmware_component_standalone ***ret_entries); |
| |
| /** @brief Return imageset version from the application |
| * |
| * @param[in] ctx - callback context |
| * @param[out] ret_active - ActiveComponentVersion string |
| * @param[out] ret_active - PendingComponentVersion string |
| * |
| * @return 0 on success, a negative errno value on failure. |
| * (specific errno value is ignored) |
| * |
| * This is used by the FD responder for GetFirmwareParameters. |
| */ |
| int (*imageset_versions)(void *ctx, |
| struct pldm_firmware_string *ret_active, |
| struct pldm_firmware_string *ret_pending); |
| |
| /** @brief Called on PassComponentTable or UpdateComponent |
| * |
| * @param[in] ctx - callback context |
| * @param[in] update - will be set for UpdateComponent, and indicates that |
| * an update flow is starting, with the same comp used |
| * for subsequent firmware_data, verify, apply callbacks. |
| * @param[in] comp - the component being used. The FD implementation |
| * will only pass comp that has already been |
| * validated against the pldm_fd_ops.components callback. |
| * |
| * @return PLDM_CRC_COMP_CAN_BE_UPDATED if the component can be updated. |
| */ |
| enum pldm_component_response_codes (*update_component)( |
| void *ctx, bool update, |
| const struct pldm_firmware_update_component *comp); |
| |
| /** @brief Provide the transfer size to use |
| * |
| * @param[in] ctx - callback context |
| * @param[in] ua_max_transfer_size - size requested by the UA. |
| * |
| * @return The transfer size to use. This will be clamped to |
| * 32 <= size <= ua_max_transfer_size. |
| * The final data chunk may be shorter. |
| */ |
| uint32_t (*transfer_size)(void *ctx, uint32_t ua_max_transfer_size); |
| |
| /* @brief Provides firmware update data from the UA |
| * |
| * @param[in] ctx - callback context |
| * @param[in] offset - offset of the data |
| * @param[in] data - firmware data buffer |
| * @param[in] len - length of data |
| * @param[in] comp - the relevant component |
| * |
| * @return TransferComplete code - either |
| * enum pldm_firmware_update_common_error_codes or |
| * enum pldm_firmware_update_transfer_result_values. |
| * |
| * PLDM_FWUP_TRANSFER_SUCCESS will accept the data chunk, other codes will |
| * abort the transfer, returning that code as TransferComplete |
| */ |
| uint8_t (*firmware_data)( |
| void *ctx, uint32_t offset, const uint8_t *data, uint32_t len, |
| const struct pldm_firmware_update_component *comp); |
| |
| /* @brief Requests the application verify the update |
| * |
| * @param[in] ctx - callback context |
| * @param[in] comp - the relevant component |
| * @param[out] ret_pending - set when verify will run asynchronously |
| * @param[out] ret_progress_percent - can optionally be set |
| * during asynchronous verify, |
| * or leave defaulted (101). |
| * |
| * @return VerifyComplete code - either |
| * enum pldm_firmware_update_common_error_codes or |
| * enum pldm_firmware_update_verify_result_values. |
| * |
| * verify() will only be called once all firmware_data (up to the UA-specified |
| * comp_image_size) has been provided. Implementations should check that length |
| * as part of verification, if not already checked. |
| * |
| * If the verify is going to complete asynchronously, implementations set |
| * *ret_pending=true and return PLDM_FWUP_VERIFY_SUCCESS. The FD will then |
| * call verify() again when pldm_fd_progress() is called. |
| */ |
| uint8_t (*verify)(void *ctx, |
| const struct pldm_firmware_update_component *comp, |
| bool *ret_pending, uint8_t *ret_progress_percent); |
| |
| /* @brief Requests the application apply the update |
| * |
| * @param[in] ctx - callback context |
| * @param[in] comp - the relevant component |
| * @param[out] ret_pending - set when apply will run asynchronously |
| * @param[out] ret_progress_percent - can optionally be set |
| * during asynchronous apply, |
| * or leave defaulted (101). |
| * |
| * @return ApplyComplete code - either |
| * enum pldm_firmware_update_common_error_codes or |
| * enum pldm_firmware_update_apply_result_values. |
| * |
| * If the apply is going to complete asynchronously, implementations set |
| * *ret_pending=true and return PLDM_FWUP_APPLY_SUCCESS. The FD will then |
| * call apply() again when pldm_fd_progress() is called. |
| */ |
| uint8_t (*apply)(void *ctx, |
| const struct pldm_firmware_update_component *comp, |
| bool *ret_pending, uint8_t *ret_progress_percent); |
| |
| /* @brief Activates new firmware |
| * |
| * @param[in] ctx - callback context |
| * @param[in] self_contained - Self Contained Activation is requested |
| * @param[out] ret_estimated_time - a time in seconds to perform |
| * self activation, or may be left as 0. |
| * |
| * @return PLDM completion code |
| * |
| * The device implementation is responsible for checking that |
| * expected components have been updated, returning |
| * PLDM_FWUP_INCOMPLETE_UPDATE if not. |
| */ |
| uint8_t (*activate)(void *ctx, bool self_contained, |
| uint16_t *ret_estimated_time); |
| |
| /* @brief Cancel Update Component |
| * |
| * @param[in] ctx - callback context |
| * @param[in] comp - the relevant component |
| * |
| * Called when a component update is cancelled prior to being applied. |
| * This function is called for both Cancel Update Component |
| * and Cancel Update (when a component is currently in progress). */ |
| void (*cancel_update_component)( |
| void *ctx, const struct pldm_firmware_update_component *comp); |
| |
| /* @brief Returns a monotonic timestamp |
| * |
| * @param[in] ctx - callback context |
| * |
| * @return timestamp in milliseconds, from an arbitrary origin. |
| Must not go backwards. |
| */ |
| uint64_t (*now)(void *ctx); |
| }; |
| |
| /* Static storage can be allocated with |
| * PLDM_SIZEOF_PLDM_FD macro */ |
| #define PLDM_ALIGNOF_PLDM_FD 8 |
| struct pldm_fd; |
| |
| /** @brief Allocate and initialise a FD responder |
| * |
| * @param[in] ops - Application provided callbacks which define the device |
| * 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_control *control); |
| |
| /** @brief Initialise a FD responder struct |
| * |
| * @param[in] fd - A pointer to a struct pldm_fd. Applications can allocate this |
| * in static storage of size PLDM_SIZEOF_PLDM_FD if required. |
| * @param[in] pldm_fd_size - applications should pass PLDM_SIZEOF_PLDM_FD, to check |
| * for consistency with the fd pointer. |
| * @param[in] ops - Application provided callbacks which define the device |
| * 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, |
| struct pldm_control *control); |
| |
| /** @brief Handle a PLDM Firmware Update message |
| * |
| * @param[in] fd |
| * @param[in] remote_address - the source address of the message. |
| * @param[in] in_msg - PLDM incoming message payload |
| * @param[in] in_len - length of in_msg buffer |
| * @param[out] out_msg - PLDM outgoing message payload buffer |
| * @param[inout] out_len - length of available out_msg buffer, will be updated |
| * with the length written to out_msg. |
| * |
| * @return 0 on success, a negative errno value on failure. |
| * |
| * Will return a message to send if out_len > 0 |
| * and returning 0. |
| */ |
| int pldm_fd_handle_msg(struct pldm_fd *fd, pldm_tid_t remote_address, |
| const void *in_msg, size_t in_len, void *out_msg, |
| size_t *out_len); |
| |
| /** @brief Handle periodic progress events |
| * |
| * @param[in] fd |
| * @param[out] out_msg - PLDM outgoing message payload buffer |
| * @param[inout] out_len - length of available out_msg buffer, will be updated |
| * with the length written to out_msg. |
| * @param[out] remote_address - destination address for the message to send. |
| * This is the address used to initiate the update, |
| * from a previous pldm_fd_handle_msg call. |
| * |
| * @return 0 on success, a negative errno value on failure. |
| * |
| * Will return a message to send to remote_address if out_len > 0 |
| * and returning 0. |
| * |
| * This could be called periodically by the application to send retries |
| * during an update flow. A 1 second interval is recommended. |
| */ |
| int pldm_fd_progress(struct pldm_fd *fd, void *out_msg, size_t *out_len, |
| pldm_tid_t *remote_address); |
| |
| /** @brief Set update mode idle timeout |
| * |
| * @param[in] fd |
| * @param[in] time - Amount of time before the FD shall exit from update mode |
| * if no command is received, in milliseconds. FD_T1. |
| * Should be 60000-120000 (60-120 sec), initial default is |
| * 120000. |
| * |
| * @return 0 on success, a negative errno value on failure. |
| */ |
| int pldm_fd_set_update_idle_timeout(struct pldm_fd *fd, uint32_t time); |
| |
| /** @brief Set request retry time |
| * |
| * @param[in] fd |
| * @param[in] time - Time for retries of Request Firmware Data, |
| * Verify, Apply commands, in miliseconds. FD_T2. |
| * Should be 1000-5000, initial default is 1000. |
| * |
| * Will return a message to send to remote_address if out_len > 0 |
| * and returning 0. |
| * |
| * This could be called periodically by the application to send retries |
| * during an update flow. A 1 second interval is recommended. |
| * |
| * @return 0 on success, a negative errno value on failure. |
| */ |
| int pldm_fd_set_request_retry_time(struct pldm_fd *fd, uint32_t time); |
| |
| #ifdef __cplusplus |
| } |
| #endif |