libpldm: Add API to find an attribute value entry

Add an API to find an attribute value entry by handle
and a pair of APIs to get the length and address of
the value field from the entry

Signed-off-by: John Wang <wangzqbj@inspur.com>
Change-Id: I955e3c1faa91abb951d823386e3360c6f6278cd3
diff --git a/libpldm/bios_table.c b/libpldm/bios_table.c
index 1b98c1d..6430923 100644
--- a/libpldm/bios_table.c
+++ b/libpldm/bios_table.c
@@ -699,6 +699,30 @@
 	return entry_length->entry_length_handler(entry);
 }
 
+uint16_t pldm_bios_table_attr_value_entry_decode_handle(
+    const struct pldm_bios_attr_val_table_entry *entry)
+{
+	return le16toh(entry->attr_handle);
+}
+
+size_t pldm_bios_table_attr_value_entry_value_length(
+    const struct pldm_bios_attr_val_table_entry *entry)
+{
+	size_t entry_length = attr_value_table_entry_length(entry);
+	size_t header_length =
+	    MEMBER_SIZE(pldm_bios_attr_val_table_entry, attr_handle) +
+	    MEMBER_SIZE(pldm_bios_attr_val_table_entry, attr_type);
+	assert(entry_length > header_length);
+
+	return (entry_length - header_length);
+}
+
+const uint8_t *pldm_bios_table_attr_value_entry_value(
+    const struct pldm_bios_attr_val_table_entry *entry)
+{
+	return entry->value;
+}
+
 static size_t pad_size_get(size_t size_without_pad)
 {
 	return ((size_without_pad % 4) ? (4 - size_without_pad % 4) : 0);
@@ -801,9 +825,11 @@
 	return iter->table_data + iter->current_pos;
 }
 
+typedef bool (*equal_handler)(const void *entry, const void *key);
+
 static const void *
-pldm_bios_table_entry_find(struct pldm_bios_table_iter *iter, const void *key,
-			   int (*equal)(const void *entry, const void *key))
+pldm_bios_table_entry_find_by_iter(struct pldm_bios_table_iter *iter,
+				   const void *key, equal_handler equal)
 {
 	const void *entry;
 	while (!pldm_bios_table_iter_is_end(iter)) {
@@ -815,7 +841,20 @@
 	return NULL;
 }
 
-static int string_table_handle_equal(const void *entry, const void *key)
+static const void *
+pldm_bios_table_entry_find_from_table(const void *table, size_t length,
+				      enum pldm_bios_table_types type,
+				      equal_handler equal, const void *key)
+{
+	struct pldm_bios_table_iter *iter =
+	    pldm_bios_table_iter_create(table, length, type);
+	const void *entry =
+	    pldm_bios_table_entry_find_by_iter(iter, key, equal);
+	pldm_bios_table_iter_free(iter);
+	return entry;
+}
+
+static bool string_table_handle_equal(const void *entry, const void *key)
 {
 	const struct pldm_bios_string_table_entry *string_entry = entry;
 	uint16_t handle = *(uint16_t *)key;
@@ -824,12 +863,21 @@
 	return false;
 }
 
+const struct pldm_bios_string_table_entry *
+pldm_bios_table_string_find_by_handle(const void *table, size_t length,
+				      uint16_t handle)
+{
+	return pldm_bios_table_entry_find_from_table(
+	    table, length, PLDM_BIOS_STRING_TABLE, string_table_handle_equal,
+	    &handle);
+}
+
 struct string_equal_arg {
 	uint16_t str_length;
 	const char *str;
 };
 
-static int string_table_string_equal(const void *entry, const void *key)
+static bool string_table_string_equal(const void *entry, const void *key)
 {
 	const struct pldm_bios_string_table_entry *string_entry = entry;
 	const struct string_equal_arg *arg = key;
@@ -847,22 +895,22 @@
 {
 	uint16_t str_length = strlen(str);
 	struct string_equal_arg arg = {str_length, str};
-	struct pldm_bios_table_iter *iter =
-	    pldm_bios_table_iter_create(table, length, PLDM_BIOS_STRING_TABLE);
-	const void *entry =
-	    pldm_bios_table_entry_find(iter, &arg, string_table_string_equal);
-	pldm_bios_table_iter_free(iter);
-	return entry;
+	return pldm_bios_table_entry_find_from_table(
+	    table, length, PLDM_BIOS_STRING_TABLE, string_table_string_equal,
+	    &arg);
 }
 
-const struct pldm_bios_string_table_entry *
-pldm_bios_table_string_find_by_handle(const void *table, size_t length,
-				      uint16_t handle)
+static bool attr_value_table_handle_equal(const void *entry, const void *key)
 {
-	struct pldm_bios_table_iter *iter =
-	    pldm_bios_table_iter_create(table, length, PLDM_BIOS_STRING_TABLE);
-	const void *entry = pldm_bios_table_entry_find(
-	    iter, &handle, string_table_handle_equal);
-	pldm_bios_table_iter_free(iter);
-	return entry;
+	uint16_t handle = *(uint16_t *)key;
+	return pldm_bios_table_attr_value_entry_decode_handle(entry) == handle;
+}
+
+const struct pldm_bios_attr_val_table_entry *
+pldm_bios_table_attr_value_find_by_handle(const void *table, size_t length,
+					  uint16_t handle)
+{
+	return pldm_bios_table_entry_find_from_table(
+	    table, length, PLDM_BIOS_ATTR_VAL_TABLE,
+	    attr_value_table_handle_equal, &handle);
 }
diff --git a/libpldm/bios_table.h b/libpldm/bios_table.h
index 0327c59..b1a7f51 100644
--- a/libpldm/bios_table.h
+++ b/libpldm/bios_table.h
@@ -517,6 +517,38 @@
 							  uint8_t attr_type,
 							  uint64_t cv);
 
+/** @brief Get the handle from the attribute value entry
+ *  @param[in] entry - Pointer to bios attribute value entry
+ *  @return handle to identify the attribute in the attribute value table
+ */
+uint16_t pldm_bios_table_attr_value_entry_decode_handle(
+    const struct pldm_bios_attr_val_table_entry *entry);
+
+/** @brief Get the value field length from the attribute value entry
+ *  @param[in] entry - Pointer to bios attribute value entry
+ *  @return Length of the value filed
+ */
+size_t pldm_bios_table_attr_value_entry_value_length(
+    const struct pldm_bios_attr_val_table_entry *entry);
+
+/** @brief Get the value field address from the attribute value entry
+ *  @param[in] entry - Pointer to bios attribute value entry
+ *  @return Pointer to the value field in the attribute value entry;
+ */
+const uint8_t *pldm_bios_table_attr_value_entry_value(
+    const struct pldm_bios_attr_val_table_entry *entry);
+
+/** @brief Find an entry in attribute value table by handle
+ *  @param[in] table - The BIOS Attribute Value Table
+ *  @param[in] length - Length of the BIOS Attribute Value Table
+ *  @param[in] handle - handle to identify the attribute in the attribute value
+ * table
+ *  @return Pointer to the entry
+ */
+const struct pldm_bios_attr_val_table_entry *
+pldm_bios_table_attr_value_find_by_handle(const void *table, size_t length,
+					  uint16_t handle);
+
 /** @brief Get the size of pad and checksum
  *  @param[in] size_without_pad - Table size without pad
  *  @return The size of pad and checksum
diff --git a/test/libpldm_bios_table_test.cpp b/test/libpldm_bios_table_test.cpp
index b5459c5..b573821 100644
--- a/test/libpldm_bios_table_test.cpp
+++ b/test/libpldm_bios_table_test.cpp
@@ -518,6 +518,14 @@
         stringEntry.data());
     auto length = pldm_bios_table_attr_value_entry_string_decode_length(entry);
     EXPECT_EQ(3, length);
+
+    auto handle = pldm_bios_table_attr_value_entry_decode_handle(entry);
+    EXPECT_EQ(0, handle);
+
+    auto valueLength = pldm_bios_table_attr_value_entry_value_length(entry);
+    EXPECT_EQ(5, valueLength);
+    auto value = pldm_bios_table_attr_value_entry_value(entry);
+    EXPECT_EQ(0, std::memcmp(value, stringEntry.data() + 3, valueLength));
 }
 
 TEST(AttrValTable, integerEntryEncodeTest)
@@ -618,6 +626,49 @@
     pldm_bios_table_iter_free(iter);
 }
 
+TEST(AttrValTable, FindTest)
+{
+    std::vector<uint8_t> enumEntry{
+        0, 0, /* attr handle */
+        0,    /* attr type */
+        2,    /* number of current value */
+        0,    /* current value string handle index */
+        1,    /* current value string handle index */
+    };
+    std::vector<uint8_t> stringEntry{
+        1,   0,        /* attr handle */
+        1,             /* attr type */
+        3,   0,        /* current string length */
+        'a', 'b', 'c', /* defaut value string handle index */
+    };
+    std::vector<uint8_t> integerEntry{
+        2,  0,                   /* attr handle */
+        3,                       /* attr type */
+        10, 0, 0, 0, 0, 0, 0, 0, /* current value */
+    };
+
+    Table table;
+    buildTable(table, enumEntry, stringEntry, integerEntry);
+
+    auto entry = pldm_bios_table_attr_value_find_by_handle(table.data(),
+                                                           table.size(), 1);
+    EXPECT_NE(entry, nullptr);
+    auto p = reinterpret_cast<const uint8_t*>(entry);
+    EXPECT_THAT(std::vector<uint8_t>(p, p + stringEntry.size()),
+                ElementsAreArray(stringEntry));
+
+    entry = pldm_bios_table_attr_value_find_by_handle(table.data(),
+                                                      table.size(), 3);
+    EXPECT_EQ(entry, nullptr);
+
+    auto firstEntry =
+        reinterpret_cast<struct pldm_bios_attr_val_table_entry*>(table.data());
+    firstEntry->attr_type = PLDM_BIOS_PASSWORD;
+    EXPECT_DEATH(pldm_bios_table_attr_value_find_by_handle(table.data(),
+                                                           table.size(), 1),
+                 "entry_length != NULL");
+}
+
 TEST(StringTable, EntryEncodeTest)
 {
     std::vector<uint8_t> stringEntry{