libpldm: bios_table: Add required decode functions

Prepare for setBIOSAttributeCurrentValue, add required
`decode` and `find` functions

Signed-off-by: John Wang <wangzqbj@inspur.com>
Change-Id: Ia3be30099d8573c13e563e73457b077bb13436e4
diff --git a/libpldm/bios_table.c b/libpldm/bios_table.c
index a1db7eb..9d71819 100644
--- a/libpldm/bios_table.c
+++ b/libpldm/bios_table.c
@@ -7,7 +7,6 @@
 
 #include "bios.h"
 #include "bios_table.h"
-#include "utils.h"
 
 #define POINTER_CHECK(pointer)                                                 \
 	do {                                                                   \
@@ -141,6 +140,18 @@
 	attr_entry->string_handle = htole16(string_handle);
 }
 
+uint16_t pldm_bios_table_attr_entry_decode_attribute_handle(
+    const struct pldm_bios_attr_table_entry *entry)
+{
+	return le16toh(entry->attr_handle);
+}
+
+uint16_t pldm_bios_table_attr_entry_decode_string_handle(
+    const struct pldm_bios_attr_table_entry *entry)
+{
+	return le16toh(entry->string_handle);
+}
+
 size_t pldm_bios_table_attr_entry_enum_encode_length(uint8_t pv_num,
 						     uint8_t def_num)
 {
@@ -377,6 +388,14 @@
 	return PLDM_SUCCESS;
 }
 
+uint8_t pldm_bios_table_attr_entry_string_decode_string_type(
+    const struct pldm_bios_attr_table_entry *entry)
+{
+	struct attr_table_string_entry_fields *fields =
+	    (struct attr_table_string_entry_fields *)entry->metadata;
+	return fields->string_type;
+}
+
 /** @brief Get length of a string attribute entry
  */
 static size_t attr_table_entry_length_string(const void *entry)
@@ -524,6 +543,18 @@
 	return attr_table_entry->entry_length_handler(entry);
 }
 
+uint16_t pldm_bios_table_attr_value_entry_decode_attribute_handle(
+    const struct pldm_bios_attr_val_table_entry *entry)
+{
+	return le16toh(entry->attr_handle);
+}
+
+uint8_t pldm_bios_table_attr_value_entry_decode_attribute_type(
+    const struct pldm_bios_attr_val_table_entry *entry)
+{
+	return entry->attr_type;
+}
+
 size_t pldm_bios_table_attr_value_entry_encode_enum_length(uint8_t count)
 {
 	return sizeof(struct pldm_bios_attr_val_table_entry) - 1 +
@@ -552,6 +583,18 @@
 	return entry->value[0];
 }
 
+uint8_t pldm_bios_table_attr_value_entry_enum_decode_handles(
+    const struct pldm_bios_attr_val_table_entry *entry, uint8_t *handles,
+    uint8_t number)
+{
+	uint8_t curr_num =
+	    pldm_bios_table_attr_value_entry_enum_decode_number(entry);
+	number = number < curr_num ? number : curr_num;
+	memcpy(handles, &entry->value[1], number);
+
+	return number;
+}
+
 int pldm_bios_table_attr_value_entry_encode_enum_check(
     void *entry, size_t entry_length, uint16_t attr_handle, uint8_t attr_type,
     uint8_t count, uint8_t *handles)
@@ -608,6 +651,16 @@
 	return le16toh(str_length);
 }
 
+void pldm_bios_table_attr_value_entry_string_decode_string(
+    const struct pldm_bios_attr_val_table_entry *entry,
+    struct variable_field *current_string)
+{
+	current_string->length =
+	    pldm_bios_table_attr_value_entry_string_decode_length(entry);
+	current_string->ptr =
+	    entry->value + sizeof(uint16_t); // sizeof(CurrentStringLength)
+}
+
 int pldm_bios_table_attr_value_entry_encode_string_check(
     void *entry, size_t entry_length, uint16_t attr_handle, uint8_t attr_type,
     uint16_t str_length, const char *str)
@@ -670,6 +723,15 @@
 	return PLDM_SUCCESS;
 }
 
+uint64_t pldm_bios_table_attr_value_entry_integer_decode_cv(
+    const struct pldm_bios_attr_val_table_entry *entry)
+{
+	uint64_t cv = 0;
+	memcpy(&cv, entry->value, sizeof(cv));
+	cv = le64toh(cv);
+	return cv;
+}
+
 static size_t attr_value_table_entry_length_integer(const void *entry)
 {
 	(void)entry;
@@ -896,6 +958,22 @@
 	    &arg);
 }
 
+static bool attr_table_handle_equal(const void *entry, const void *key)
+{
+	uint16_t handle = *(uint16_t *)key;
+	return pldm_bios_table_attr_entry_decode_attribute_handle(entry) ==
+	       handle;
+}
+
+const struct pldm_bios_attr_table_entry *
+pldm_bios_table_attr_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_TABLE, attr_table_handle_equal,
+	    &handle);
+}
+
 static bool attr_value_table_handle_equal(const void *entry, const void *key)
 {
 	uint16_t handle = *(uint16_t *)key;
diff --git a/libpldm/bios_table.h b/libpldm/bios_table.h
index 262f423..298ba7e 100644
--- a/libpldm/bios_table.h
+++ b/libpldm/bios_table.h
@@ -6,6 +6,7 @@
 #endif
 
 #include "bios.h"
+#include "utils.h"
 #include <stdbool.h>
 #include <stddef.h>
 #include <stdint.h>
@@ -163,6 +164,31 @@
 pldm_bios_table_string_find_by_handle(const void *table, size_t length,
 				      uint16_t handle);
 
+/** @brief Get the attribute handle from the attribute table entry
+ *  @param[in] entry - Pointer to bios attribute table entry
+ *  @return handle to identify the attribute in the attribute table
+ */
+uint16_t pldm_bios_table_attr_entry_decode_attribute_handle(
+    const struct pldm_bios_attr_table_entry *entry);
+
+/** @brief Get the attribute name handle from the attribute table entry
+ *  @param[in] entry - Pointer to bios attribute table entry
+ *  @return handle to identify the name of the attribute, this handle points
+ *          to a string in the bios string table.
+ */
+uint16_t pldm_bios_table_attr_entry_decode_string_handle(
+    const struct pldm_bios_attr_table_entry *entry);
+
+/** @brief Find an entry in attribute table by handle
+ *  @param[in] table - The BIOS Attribute Table
+ *  @param[in] length - Length of the BIOS Attribute Table
+ *  @param[in] handle - handle to identify the attribute in the attribute table
+ *  @return Pointer to the entry
+ */
+const struct pldm_bios_attr_table_entry *
+pldm_bios_table_attr_find_by_handle(const void *table, size_t length,
+				    uint16_t handle);
+
 /** @struct pldm_bios_table_attr_entry_enum_info
  *
  *  An auxiliary structure for passing parameters to @ref
@@ -335,6 +361,13 @@
     const struct pldm_bios_attr_table_entry *entry,
     uint16_t *def_string_length);
 
+/** @brief Get the type of string of bios attribute table entry
+ *  @param[in] entry - Pointer to bios attribute table entry
+ *  @return Type of the string
+ */
+uint8_t pldm_bios_table_attr_entry_string_decode_string_type(
+    const struct pldm_bios_attr_table_entry *entry);
+
 /** @struct pldm_bios_table_attr_entry_integer_info
  *
  *  An auxiliary structure for passing parameters to @ref
@@ -388,6 +421,20 @@
     void *entry, size_t entry_length,
     const struct pldm_bios_table_attr_entry_integer_info *info);
 
+/** @brief Get the attribute handle from the attribute value table entry
+ *  @param[in] entry - Pointer to bios attribute value table entry
+ *  @return handle to identify the attribute in the attribute value table
+ */
+uint16_t pldm_bios_table_attr_value_entry_decode_attribute_handle(
+    const struct pldm_bios_attr_val_table_entry *entry);
+
+/** @brief Get the attribute type from the attribute value table entry
+ *  @param[in] entry - Pointer to bios attribute value table entry
+ *  @return Type of the attribute value entry
+ */
+uint8_t pldm_bios_table_attr_value_entry_decode_attribute_type(
+    const struct pldm_bios_attr_val_table_entry *entry);
+
 /** @brief Get length that an attribute value entry(type: enum) will take
  *  @param[in] count - Total number of current values for this enumeration
  *  @return The length that an entry(type: enum) will take
@@ -416,6 +463,17 @@
 uint8_t pldm_bios_table_attr_value_entry_enum_decode_number(
     const struct pldm_bios_attr_val_table_entry *entry);
 
+/** @brief Get CurrentValueStringHandleIndex
+ *  @param[in] entry - Pointer to bios attribute value table entry
+ *  @param[in, out] handles - Pointer to a buffer to store
+ *                            CurrentValueStringHandleIndex
+ *  @param[in] number - Number of PossibleValuesStringHandles expected
+ *  @return Number of CurrentValueStringHandleIndex decoded.
+ */
+uint8_t pldm_bios_table_attr_value_entry_enum_decode_handles(
+    const struct pldm_bios_attr_val_table_entry *entry, uint8_t *handles,
+    uint8_t number);
+
 /** @brief Create an attribute value entry(type: enum) and check the validity of
  * the parameters
  *  @param[out] entry - Pointer to bios attribute value entry
@@ -463,6 +521,17 @@
 uint16_t pldm_bios_table_attr_value_entry_string_decode_length(
     const struct pldm_bios_attr_val_table_entry *entry);
 
+/** @brief Get Current String Itself
+ *  @param[in] entry - Pointer to bios attribute value table entry
+ *  @param[in, out] current_string - Struct variable_field, contains a pointer
+ *                                   to the CurrentString field in the buffer of
+ *                                    \p entry, \p entry must be valid
+ *                                    when \p current_string is used.
+ */
+void pldm_bios_table_attr_value_entry_string_decode_string(
+    const struct pldm_bios_attr_val_table_entry *entry,
+    struct variable_field *current_string);
+
 /** @brief Create an attribute value entry(type: string) and check the validity
  * of the parameters
  *  @param[out] entry - Pointer to bios attribute value entry
@@ -500,6 +569,13 @@
 						     uint8_t attr_type,
 						     uint64_t cv);
 
+/** @brief Get current values for the integer entry
+ *  @param[in] entry - Pointer to bios attribute value table entry
+ *  @return Current Value
+ */
+uint64_t pldm_bios_table_attr_value_entry_integer_decode_cv(
+    const struct pldm_bios_attr_val_table_entry *entry);
+
 /** @brief Create an attribute value entry(type: integer) and check the validity
  * of the parameters
  *  @param[out] entry - Pointer to bios attribute value entry
diff --git a/test/libpldm_bios_table_test.cpp b/test/libpldm_bios_table_test.cpp
index 5ab1dfe..49eeb31 100644
--- a/test/libpldm_bios_table_test.cpp
+++ b/test/libpldm_bios_table_test.cpp
@@ -34,6 +34,26 @@
     buildTable(table, rest...);
 }
 
+TEST(AttrTable, HeaderDecodeTest)
+{
+    std::vector<uint8_t> enumEntry{
+        2, 0, /* attr handle */
+        0,    /* attr type */
+        1, 0, /* attr name handle (string handle) */
+        2,    /* number of possible value */
+        2, 0, /* possible value handle */
+        3, 0, /* possible value handle */
+        1,    /* number of default value */
+        0     /* defaut value string handle index */
+    };
+    auto entry =
+        reinterpret_cast<struct pldm_bios_attr_table_entry*>(enumEntry.data());
+    auto attrHandle = pldm_bios_table_attr_entry_decode_attribute_handle(entry);
+    EXPECT_EQ(attrHandle, 2);
+    auto stringHandle = pldm_bios_table_attr_entry_decode_string_handle(entry);
+    EXPECT_EQ(stringHandle, 1);
+}
+
 TEST(AttrTable, EnumEntryDecodeTest)
 {
     std::vector<uint8_t> enumEntry{
@@ -172,6 +192,10 @@
 
     auto entry = reinterpret_cast<struct pldm_bios_attr_table_entry*>(
         stringEntry.data());
+    auto stringType =
+        pldm_bios_table_attr_entry_string_decode_string_type(entry);
+    EXPECT_EQ(stringType, 1);
+
     uint16_t def_string_length =
         pldm_bios_table_attr_entry_string_decode_def_string_length(entry);
     EXPECT_EQ(def_string_length, 3);
@@ -406,6 +430,71 @@
     pldm_bios_table_iter_free(iter);
 }
 
+TEST(AttrTable, FindTest)
+{
+    std::vector<uint8_t> enumEntry{
+        0, 0, /* attr handle */
+        0,    /* attr type */
+        1, 0, /* attr name handle */
+        2,    /* number of possible value */
+        2, 0, /* possible value handle */
+        3, 0, /* possible value handle */
+        1,    /* number of default value */
+        0     /* defaut value string handle index */
+    };
+    std::vector<uint8_t> stringEntry{
+        1,   0,       /* attr handle */
+        1,            /* attr type */
+        12,  0,       /* attr name handle */
+        1,            /* string type */
+        1,   0,       /* minimum length of the string in bytes */
+        100, 0,       /* maximum length of the string in bytes */
+        3,   0,       /* length of default string in length */
+        'a', 'b', 'c' /* default string  */
+    };
+    std::vector<uint8_t> integerEntry{
+        0,  0,                   /* attr handle */
+        3,                       /* attr type */
+        1,  0,                   /* attr name handle */
+        1,  0, 0, 0, 0, 0, 0, 0, /* lower bound */
+        10, 0, 0, 0, 0, 0, 0, 0, /* upper bound */
+        2,  0, 0, 0,             /* scalar increment */
+        3,  0, 0, 0, 0, 0, 0, 0, /* defaut value */
+    };
+
+    Table table;
+    buildTable(table, enumEntry, stringEntry, integerEntry, enumEntry);
+
+    auto entry =
+        pldm_bios_table_attr_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_find_by_handle(table.data(), table.size(), 3);
+    EXPECT_EQ(entry, nullptr);
+}
+
+TEST(AttrValTable, HeaderDecodeTest)
+{
+    std::vector<uint8_t> enumEntry{
+        1, 0, /* attr handle */
+        0,    /* attr type */
+        2,    /* number of current value */
+        0,    /* current value string handle index */
+        1,    /* current value string handle index */
+    };
+    auto entry = reinterpret_cast<struct pldm_bios_attr_val_table_entry*>(
+        enumEntry.data());
+    auto attrHandle =
+        pldm_bios_table_attr_value_entry_decode_attribute_handle(entry);
+    EXPECT_EQ(attrHandle, 1);
+    auto attrType =
+        pldm_bios_table_attr_value_entry_decode_attribute_type(entry);
+    EXPECT_EQ(attrType, 0);
+}
+
 TEST(AttrValTable, EnumEntryEncodeTest)
 {
     std::vector<uint8_t> enumEntry{
@@ -466,6 +555,13 @@
         enumEntry.data());
     auto number = pldm_bios_table_attr_value_entry_enum_decode_number(entry);
     EXPECT_EQ(2, number);
+
+    std::vector<uint8_t> handles(2, 0);
+    auto rc = pldm_bios_table_attr_value_entry_enum_decode_handles(
+        entry, handles.data(), handles.size());
+    EXPECT_EQ(rc, 2);
+    EXPECT_EQ(handles[0], 0);
+    EXPECT_EQ(handles[1], 1);
 }
 
 TEST(AttrValTable, stringEntryEncodeTest)
@@ -530,6 +626,13 @@
 
     auto entryLength = pldm_bios_table_attr_value_entry_length(entry);
     EXPECT_EQ(stringEntry.size(), entryLength);
+
+    variable_field currentString{};
+    pldm_bios_table_attr_value_entry_string_decode_string(entry,
+                                                          &currentString);
+    EXPECT_THAT(std::vector<uint8_t>(currentString.ptr,
+                                     currentString.ptr + currentString.length),
+                ElementsAreArray(std::vector<uint8_t>{'a', 'b', 'c'}));
 }
 
 TEST(AttrValTable, integerEntryEncodeTest)
@@ -574,6 +677,20 @@
     EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
 }
 
+TEST(AttrValTable, integerEntryDecodeTest)
+{
+    std::vector<uint8_t> integerEntry{
+        0,  0,                   /* attr handle */
+        3,                       /* attr type */
+        10, 0, 0, 0, 0, 0, 0, 0, /* current value */
+    };
+
+    auto entry = reinterpret_cast<struct pldm_bios_attr_val_table_entry*>(
+        integerEntry.data());
+    auto cv = pldm_bios_table_attr_value_entry_integer_decode_cv(entry);
+    EXPECT_EQ(cv, 10);
+}
+
 TEST(AttrValTable, IteratorTest)
 {
     std::vector<uint8_t> enumEntry{