pdr: Introduce pldm_pdr_add_check()
pldm_pdr_add() relied on assert() to communicate failure to the caller.
Introduce pldm_pdr_add_check() which instead returns a value indicating
success or failure. pldm_pdr_add() will be deprecated once
pldm_pdr_add_check() is stabilised.
Signed-off-by: Andrew Jeffery <andrew@aj.id.au>
Change-Id: I43542e8e7411edb32a7afa242f1ae68d6fe3ad89
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 2b86199..f944cf6 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -22,6 +22,7 @@
1. bios_table: Introduce pldm_bios_table_append_pad_checksum_check()
2. fru: Introduce get_fru_record_by_option_check()
3. pdr: Introduce pldm_entity_association_pdr_add_from_node_check()
+4. pdr: Introduce pldm_pdr_add_check()
### Changed
diff --git a/include/libpldm/pdr.h b/include/libpldm/pdr.h
index 8ace295..621974a 100644
--- a/include/libpldm/pdr.h
+++ b/include/libpldm/pdr.h
@@ -77,6 +77,25 @@
uint32_t record_handle, bool is_remote,
uint16_t terminus_handle);
+/** @brief Add a PDR record to a PDR repository, or return an error
+ *
+ * @param[in/out] repo - opaque pointer acting as a PDR repo handle
+ * @param[in] data - pointer to a PDR record, pointing to a PDR definition as
+ * per DSP0248. This data is memcpy'd.
+ * @param[in] size - size of input PDR record in bytes
+ * @param[in] is_remote - if true, then the PDR is not from this terminus
+ * @param[in] terminus_handle - terminus handle of the input PDR record
+ * @param[in,out] record_handle - record handle of input PDR record. If this is set to 0 then a
+ * record handle is computed. The computed handle is assigned to both the PDR record and back into
+ * record_handle for the caller to consume.
+ *
+ * @return 0 on success, -EINVAL if the arguments are invalid, -ENOMEM if an internal memory
+ * allocation fails, or -EOVERFLOW if a record handle could not be allocated
+ */
+int pldm_pdr_add_check(pldm_pdr *repo, const uint8_t *data, uint32_t size,
+ bool is_remote, uint16_t terminus_handle,
+ uint32_t *record_handle);
+
/** @brief Get record handle of a PDR record
*
* @pre repo must point to a valid object
diff --git a/src/pdr.c b/src/pdr.c
index 0ef9163..01f5002 100644
--- a/src/pdr.c
+++ b/src/pdr.c
@@ -39,40 +39,68 @@
uint32_t record_handle, bool is_remote,
uint16_t terminus_handle)
{
+ int rc = pldm_pdr_add_check(repo, data, size, is_remote,
+ terminus_handle, &record_handle);
+ (void)rc;
+ assert(!rc);
+ return record_handle;
+}
+
+LIBPLDM_ABI_TESTING
+int pldm_pdr_add_check(pldm_pdr *repo, const uint8_t *data, uint32_t size,
+ bool is_remote, uint16_t terminus_handle,
+ uint32_t *record_handle)
+{
assert(repo != NULL);
assert(data != NULL);
assert(size != 0);
+ assert(record_handle != NULL);
+ if (!repo || !data || !size || !record_handle) {
+ return -EINVAL;
+ }
pldm_pdr_record *record = malloc(sizeof(pldm_pdr_record));
assert(record != NULL);
+ if (!record) {
+ return -ENOMEM;
+ }
- if (record_handle) {
- record->record_handle = record_handle;
- } else {
- uint32_t curr = repo->last ? repo->last->record_handle : 0;
- assert(curr != UINT32_MAX);
- record->record_handle = curr + 1;
+ if (data) {
+ record->data = malloc(size);
+ assert(record->data != NULL);
+ if (!record->data) {
+ free(record);
+ return -ENOMEM;
+ }
+ memcpy(record->data, data, size);
}
record->size = size;
record->is_remote = is_remote;
record->terminus_handle = terminus_handle;
- if (data != NULL) {
- record->data = malloc(size);
- assert(record->data != NULL);
- memcpy(record->data, data, size);
- /* If record handle is 0, that is an indication for this API to
- * compute a new handle. For that reason, the computed handle
- * needs to be populated in the PDR header. For a case where the
- * caller supplied the record handle, it would exist in the
- * header already.
- */
- if (!record_handle) {
- struct pldm_pdr_hdr *hdr =
- (struct pldm_pdr_hdr *)(record->data);
+
+ if (*record_handle) {
+ record->record_handle = *record_handle;
+ } else {
+ uint32_t curr = repo->last ? repo->last->record_handle : 0;
+ assert(curr != UINT32_MAX);
+ if (curr == UINT32_MAX) {
+ return -EOVERFLOW;
+ }
+ record->record_handle = curr + 1;
+
+ if (data != NULL) {
+ /* If record handle is 0, that is an indication for this API to
+ * compute a new handle. For that reason, the computed handle
+ * needs to be populated in the PDR header. For a case where the
+ * caller supplied the record handle, it would exist in the
+ * header already.
+ */
+ struct pldm_pdr_hdr *hdr = (void *)record->data;
hdr->record_handle = htole32(record->record_handle);
}
}
+
record->next = NULL;
assert(!repo->first == !repo->last);
@@ -87,7 +115,9 @@
repo->size += record->size;
++repo->record_count;
- return record->record_handle;
+ *record_handle = record->record_handle;
+
+ return 0;
}
LIBPLDM_ABI_STABLE