Refactor: bios: Construct the attribute value table

when constructing the attribute value table, we need to traverse
the attribute table. But there is a bug in the previous version
when traversing the attribute table.

Now we use the iterator of the last commit implementation to rebuild
attribute value table.

Signed-off-by: John Wang <wangzqbj@inspur.com>
Change-Id: I9fe2b6eabf2b01e124b780fc0fc8615d492c1fed
diff --git a/libpldm/bios_table.c b/libpldm/bios_table.c
index 26d30bf..89f7241 100644
--- a/libpldm/bios_table.c
+++ b/libpldm/bios_table.c
@@ -20,6 +20,12 @@
 			return PLDM_ERROR_INVALID_DATA;                        \
 	} while (0)
 
+#define BUFFER_SIZE_EXPECT(current_size, expected_size)                        \
+	do {                                                                   \
+		if (current_size < expected_size)                              \
+			return PLDM_ERROR_INVALID_LENGTH;                      \
+	} while (0)
+
 uint8_t pldm_bios_table_attr_entry_enum_decode_pv_num(
     const struct pldm_bios_attr_table_entry *entry)
 {
@@ -54,6 +60,35 @@
 	return PLDM_SUCCESS;
 }
 
+uint8_t pldm_bios_table_attr_entry_enum_decode_pv_hdls(
+    const struct pldm_bios_attr_table_entry *entry, uint16_t *pv_hdls,
+    uint8_t pv_num)
+{
+	uint8_t num = pldm_bios_table_attr_entry_enum_decode_pv_num(entry);
+	num = num < pv_num ? num : pv_num;
+	size_t i;
+	for (i = 0; i < num; i++) {
+		uint16_t *hdl = (uint16_t *)(entry->metadata + sizeof(uint8_t) +
+					     i * sizeof(uint16_t));
+		pv_hdls[i] = le16toh(*hdl);
+	}
+	return num;
+}
+
+int pldm_bios_table_attr_entry_enum_decode_pv_hdls_check(
+    const struct pldm_bios_attr_table_entry *entry, uint16_t *pv_hdls,
+    uint8_t pv_num)
+{
+	POINTER_CHECK(entry);
+	POINTER_CHECK(pv_hdls);
+	ATTR_TYPE_EXPECT(entry->attr_type, PLDM_BIOS_ENUMERATION);
+	uint8_t num = pldm_bios_table_attr_entry_enum_decode_pv_num(entry);
+	if (num != pv_num)
+		return PLDM_ERROR_INVALID_DATA;
+	pldm_bios_table_attr_entry_enum_decode_pv_hdls(entry, pv_hdls, pv_num);
+	return PLDM_SUCCESS;
+}
+
 /** @brief Get length of an enum attribute entry
  */
 static size_t
@@ -142,6 +177,85 @@
 	return attr_table_entry->entry_length_handler(entry);
 }
 
+size_t pldm_bios_table_attr_value_entry_encode_enum_length(uint8_t count)
+{
+	return sizeof(struct pldm_bios_attr_val_table_entry) - 1 +
+	       sizeof(count) + count;
+}
+
+void pldm_bios_table_attr_value_entry_encode_enum(
+    void *entry, size_t entry_length, uint16_t attr_handle, uint8_t attr_type,
+    uint8_t count, uint8_t *handles)
+{
+	size_t length =
+	    pldm_bios_table_attr_value_entry_encode_enum_length(count);
+	assert(length <= entry_length);
+
+	struct pldm_bios_attr_val_table_entry *table_entry = entry;
+	table_entry->attr_handle = htole16(attr_handle);
+	table_entry->attr_type = attr_type;
+	table_entry->value[0] = count;
+	if (count != 0)
+		memcpy(&table_entry->value[1], handles, count);
+}
+
+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)
+{
+	POINTER_CHECK(entry);
+	if (count != 0 && handles == NULL)
+		return PLDM_ERROR_INVALID_DATA;
+	ATTR_TYPE_EXPECT(attr_type, PLDM_BIOS_ENUMERATION);
+	size_t length =
+	    pldm_bios_table_attr_value_entry_encode_enum_length(count);
+	BUFFER_SIZE_EXPECT(entry_length, length);
+	pldm_bios_table_attr_value_entry_encode_enum(
+	    entry, entry_length, attr_handle, attr_type, count, handles);
+	return PLDM_SUCCESS;
+}
+
+size_t
+pldm_bios_table_attr_value_entry_encode_string_length(uint16_t string_length)
+{
+	return sizeof(struct pldm_bios_attr_val_table_entry) - 1 +
+	       sizeof(string_length) + string_length;
+}
+
+void pldm_bios_table_attr_value_entry_encode_string(
+    void *entry, size_t entry_length, uint16_t attr_handle, uint8_t attr_type,
+    uint16_t str_length, const char *str)
+{
+	size_t length =
+	    pldm_bios_table_attr_value_entry_encode_string_length(str_length);
+	assert(length <= entry_length);
+
+	struct pldm_bios_attr_val_table_entry *table_entry = entry;
+	table_entry->attr_handle = htole16(attr_handle);
+	table_entry->attr_type = attr_type;
+	if (str_length != 0)
+		memcpy(table_entry->value + sizeof(str_length), str,
+		       str_length);
+	str_length = htole16(str_length);
+	memcpy(table_entry->value, &str_length, sizeof(str_length));
+}
+
+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)
+{
+	POINTER_CHECK(entry);
+	if (str_length != 0 && str == NULL)
+		return PLDM_ERROR_INVALID_DATA;
+	ATTR_TYPE_EXPECT(attr_type, PLDM_BIOS_STRING);
+	size_t length =
+	    pldm_bios_table_attr_value_entry_encode_string_length(str_length);
+	BUFFER_SIZE_EXPECT(entry_length, length);
+	pldm_bios_table_attr_value_entry_encode_string(
+	    entry, entry_length, attr_handle, attr_type, str_length, str);
+	return PLDM_SUCCESS;
+}
+
 struct pldm_bios_table_iter {
 	const uint8_t *table_data;
 	size_t table_len;
@@ -196,4 +310,4 @@
 const void *pldm_bios_table_iter_value(struct pldm_bios_table_iter *iter)
 {
 	return iter->table_data + iter->current_pos;
-}
\ No newline at end of file
+}
diff --git a/libpldm/bios_table.h b/libpldm/bios_table.h
index 3d17f3c..0b20109 100644
--- a/libpldm/bios_table.h
+++ b/libpldm/bios_table.h
@@ -91,6 +91,30 @@
 int pldm_bios_table_attr_entry_enum_decode_def_num_check(
     const struct pldm_bios_attr_table_entry *entry, uint8_t *def_num);
 
+/** @brief Get possible values string handles
+ *  @param[in] entry - Pointer to bios attribute table entry
+ *  @param[out] pv_hdls - Pointer to a buffer to stroe
+ * PossibleValuesStringHandles
+ *  @param[in] pv_num - Number of PossibleValuesStringHandles expected
+ *  @return pldm_completion_codes
+ */
+uint8_t pldm_bios_table_attr_entry_enum_decode_pv_hdls(
+    const struct pldm_bios_attr_table_entry *entry, uint16_t *pv_hdls,
+    uint8_t pv_num);
+
+/** @brief Get possible values string handles and check the validity of the
+ * parameters
+ *  @param[in] entry - Pointer to bios attribute table entry
+ *  @param[out] pv_hdls - Pointer to a buffer to stroe
+ * PossibleValuesStringHandles
+ *  @param[in] pv_num - Number of PossibleValuesStringHandles the buffer can
+ * stroe
+ *  @return Number of PossibleValuesStringHandles decoded
+ */
+int pldm_bios_table_attr_entry_enum_decode_pv_hdls_check(
+    const struct pldm_bios_attr_table_entry *entry, uint16_t *pv_hdls,
+    uint8_t pv_num);
+
 /** @brief Get the length of default string in bytes for the entry
  *  @param[in] entry - Pointer to bios attribute table entry
  *  @return length of default string in bytes
@@ -108,6 +132,83 @@
     const struct pldm_bios_attr_table_entry *entry,
     uint16_t *def_string_length);
 
+/** @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
+ */
+size_t pldm_bios_table_attr_value_entry_encode_enum_length(uint8_t count);
+
+/** @brief Create an attribute value entry(type: enum)
+ *  @param[out] entry - Pointer to bios attribute value entry
+ *  @param[in] entry_length - Length of attribute value entry
+ *  @param[in] attr_handle - This handle points to an attribute in the
+ *  BIOS Attribute Vlaue Table.
+ *  @param[in] attr_type - Type of this attribute in the BIOS Attribute Value
+ * Table
+ *  @param[in] count - Total number of current values for this enum attribute
+ *  @param[in] handle_indexes - Index into the array(provided in the BIOS
+ * Attribute Table) of the possible values of string handles for this attribute.
+ */
+void pldm_bios_table_attr_value_entry_encode_enum(
+    void *entry, size_t entry_length, uint16_t attr_handle, uint8_t attr_type,
+    uint8_t count, uint8_t *handle_indexes);
+
+/** @brief Create an attribute value entry(type: enum) and check the validity of
+ * the parameters
+ *  @param[out] entry - Pointer to bios attribute value entry
+ *  @param[in] entry_length - Length of attribute value entry
+ *  @param[in] attr_handle - This handle points to an attribute in the
+ *  BIOS Attribute Vlaue Table.
+ *  @param[in] attr_type - Type of this attribute in the BIOS Attribute Value
+ * Table
+ *  @param[in] count - Total number of current values for this enum attribute
+ *  @param[in] handle_indexes - Index into the array(provided in the BIOS
+ * Attribute Table) of the possible values of string handles for this attribute.
+ *  @return pldm_completion_codes
+ */
+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 *handle_indexes);
+
+/** @brief Get length that an attribute value entry(type: string) will take
+ *  @param[in] string_length - Length of the current string in byte, 0 indicates
+ *  that the current string value is not set.
+ *  @return The length that an entry(type: string) will take
+ */
+size_t
+pldm_bios_table_attr_value_entry_encode_string_length(uint16_t string_length);
+
+/** @brief Create an attribute value entry(type: string)
+ *  @param[out] entry - Pointer to bios attribute value entry
+ *  @param[in] entry_length - Length of attribute value entry
+ *  @param[in] attr_handle - This handle points to an attribute in the
+ *  BIOS Attribute Vlaue Table.
+ *  @param[in] attr_type - Type of this attribute in the BIOS Attribute Value
+ * Table
+ *  @param[in] string_length - Length of current string in bytes. 0 indicates
+ * that the current string value is not set.
+ *  @param[in] string - The current string itsel
+ */
+void pldm_bios_table_attr_value_entry_encode_string(
+    void *entry, size_t entry_length, uint16_t attr_handle, uint8_t attr_type,
+    uint16_t string_length, const char *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
+ *  @param[in] entry_length - Length of attribute value entry
+ *  @param[in] attr_handle - This handle points to an attribute in the
+ *  BIOS Attribute Vlaue Table.
+ *  @param[in] attr_type - Type of this attribute in the BIOS Attribute Value
+ * Table
+ *  @param[in] string_length - Length of current string in bytes. 0 indicates
+ * that the current string value is not set.
+ *  @param[in] string - The current string itsel
+ *  @return pldm_completion_codes
+ */
+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 string_length, const char *string);
+
 #ifdef __cplusplus
 }
 #endif