bios: Move en/decodes for String Table to libpldm

Move encode/decode functions for BIOS String Table to libpldm.
And implement an iterator to traverse the string table.

Signed-off-by: John Wang <wangzqbj@inspur.com>
Change-Id: I409a935dc6fed0b8a16ac37e11401e82d070612c
diff --git a/libpldm/bios_table.c b/libpldm/bios_table.c
index 89f7241..d9c2505 100644
--- a/libpldm/bios_table.c
+++ b/libpldm/bios_table.c
@@ -26,6 +26,96 @@
 			return PLDM_ERROR_INVALID_LENGTH;                      \
 	} while (0)
 
+#define MEMBER_SIZE(type, member) sizeof(((struct type *)0)->member)
+
+static uint16_t get_bios_string_handle()
+{
+	static uint16_t handle = 0;
+	assert(handle != UINT16_MAX);
+
+	return handle++;
+}
+
+size_t pldm_bios_table_string_entry_encode_length(uint16_t string_length)
+{
+	return sizeof(struct pldm_bios_string_table_entry) -
+	       MEMBER_SIZE(pldm_bios_string_table_entry, name) + string_length;
+}
+
+void pldm_bios_table_string_entry_encode(void *entry, size_t entry_length,
+					 const char *str, uint16_t str_length)
+{
+	size_t length = pldm_bios_table_string_entry_encode_length(str_length);
+	assert(length <= entry_length);
+	struct pldm_bios_string_table_entry *string_entry = entry;
+	string_entry->string_handle = htole16(get_bios_string_handle());
+	string_entry->string_length = htole16(str_length);
+	memcpy(string_entry->name, str, str_length);
+}
+
+int pldm_bios_table_string_entry_encode_check(void *entry, size_t entry_length,
+					      const char *str,
+					      uint16_t str_length)
+{
+	if (str_length == 0)
+		return PLDM_ERROR_INVALID_DATA;
+	POINTER_CHECK(entry);
+	POINTER_CHECK(str);
+	size_t length = pldm_bios_table_string_entry_encode_length(str_length);
+	BUFFER_SIZE_EXPECT(entry_length, length);
+	pldm_bios_table_string_entry_encode(entry, entry_length, str,
+					    str_length);
+	return PLDM_SUCCESS;
+}
+
+uint16_t pldm_bios_table_string_entry_decode_handle(
+    const struct pldm_bios_string_table_entry *entry)
+{
+	return le16toh(entry->string_handle);
+}
+
+uint16_t pldm_bios_table_string_entry_decode_string_length(
+    const struct pldm_bios_string_table_entry *entry)
+{
+	return le16toh(entry->string_length);
+}
+
+uint16_t pldm_bios_table_string_entry_decode_string(
+    const struct pldm_bios_string_table_entry *entry, char *buffer, size_t size)
+{
+	uint16_t length =
+	    pldm_bios_table_string_entry_decode_string_length(entry);
+	length = length < size ? length : size;
+	memcpy(buffer, entry->name, length);
+	buffer[length] = 0;
+	return length;
+}
+
+int pldm_bios_table_string_entry_decode_string_check(
+    const struct pldm_bios_string_table_entry *entry, char *buffer, size_t size)
+{
+	POINTER_CHECK(entry);
+	POINTER_CHECK(buffer);
+	size_t length =
+	    pldm_bios_table_string_entry_decode_string_length(entry);
+	BUFFER_SIZE_EXPECT(size, length + 1);
+	pldm_bios_table_string_entry_decode_string(entry, buffer, size);
+	return PLDM_SUCCESS;
+}
+
+static size_t string_table_entry_length(const void *table_entry)
+{
+	const struct pldm_bios_string_table_entry *entry = table_entry;
+	return sizeof(*entry) - sizeof(entry->name) +
+	       pldm_bios_table_string_entry_decode_string_length(entry);
+}
+
+#define ATTR_TYPE_EXPECT(type, expected)                                       \
+	do {                                                                   \
+		if (type != expected && type != (expected | 0x80))             \
+			return PLDM_ERROR_INVALID_DATA;                        \
+	} while (0)
+
 uint8_t pldm_bios_table_attr_entry_enum_decode_pv_num(
     const struct pldm_bios_attr_table_entry *entry)
 {
@@ -275,6 +365,7 @@
 	iter->entry_length_handler = NULL;
 	switch (type) {
 	case PLDM_BIOS_STRING_TABLE:
+		iter->entry_length_handler = string_table_entry_length;
 		break;
 	case PLDM_BIOS_ATTR_TABLE:
 		iter->entry_length_handler = attr_table_entry_length;
@@ -311,3 +402,69 @@
 {
 	return iter->table_data + iter->current_pos;
 }
+
+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))
+{
+	const void *entry;
+	while (!pldm_bios_table_iter_is_end(iter)) {
+		entry = pldm_bios_table_iter_value(iter);
+		if (equal(entry, key))
+			return entry;
+		pldm_bios_table_iter_next(iter);
+	}
+	return NULL;
+}
+
+static int 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;
+	if (pldm_bios_table_string_entry_decode_handle(string_entry) == handle)
+		return true;
+	return false;
+}
+
+struct string_equal_arg {
+	uint16_t str_length;
+	const char *str;
+};
+
+static int 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;
+	if (arg->str_length !=
+	    pldm_bios_table_string_entry_decode_string_length(string_entry))
+		return false;
+	if (memcmp(string_entry->name, arg->str, arg->str_length) != 0)
+		return false;
+	return true;
+}
+
+const struct pldm_bios_string_table_entry *
+pldm_bios_table_string_find_by_string(const void *table, size_t length,
+				      const char *str)
+{
+	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;
+}
+
+const struct pldm_bios_string_table_entry *
+pldm_bios_table_string_find_by_handle(const void *table, size_t length,
+				      uint16_t handle)
+{
+	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;
+}
diff --git a/libpldm/bios_table.h b/libpldm/bios_table.h
index 0b20109..fc9c0eb 100644
--- a/libpldm/bios_table.h
+++ b/libpldm/bios_table.h
@@ -59,6 +59,99 @@
 	    pldm_bios_table_iter_value(iter);
 }
 
+/** @brief Get the bios string table entry that the iterator ponit to
+ *  @param[in] iter - Pointer the bios string table iterator
+ *  @return Pointer to an entry in bios string table
+ */
+static inline const struct pldm_bios_string_table_entry *
+pldm_bios_table_iter_string_entry_value(struct pldm_bios_table_iter *iter)
+{
+	return (const struct pldm_bios_string_table_entry *)
+	    pldm_bios_table_iter_value(iter);
+}
+
+/** @brief Get the length of an entry in the BIOS String Table
+ *  @param[in] string_length - Length of string
+ *  @return Length of an entry in bytes
+ */
+size_t pldm_bios_table_string_entry_encode_length(uint16_t string_length);
+
+/** @brief Create an entry of BIOS String Table
+ *  @param[out] entry - Pointer to a buffer to create an entry
+ *  @param[in] entry_length - Length of the buffer to create an entry
+ *  @param[in] str - String itself
+ *  @param[in] str_length - Length of the string
+ */
+void pldm_bios_table_string_entry_encode(void *entry, size_t entry_length,
+					 const char *str, uint16_t str_length);
+
+/** @brief Create an entry of BIOS String Table and check the validity of the
+ * parameters
+ *  @param[out] entry - Pointer to a buffer to create an entry
+ *  @param[in] entry_length - Length of the buffer to create an entry
+ *  @param[in] str - String itself
+ *  @param[in] str_length - Length of the string
+ *  @return pldm_completion_codes
+ */
+int pldm_bios_table_string_entry_encode_check(void *entry, size_t entry_length,
+					      const char *str,
+					      uint16_t str_length);
+
+/** @brief Get the string handle for the entry
+ *  @param[in] entry - Pointer to a bios string table entry
+ *  @return Handle to identify a string in the bios string table
+ */
+uint16_t pldm_bios_table_string_entry_decode_handle(
+    const struct pldm_bios_string_table_entry *entry);
+
+/** @brief Get the string length for the entry
+ *  @param[in] entry - Pointer to a bios string table entry
+ *  @return Length of string in bytes
+ */
+uint16_t pldm_bios_table_string_entry_decode_string_length(
+    const struct pldm_bios_string_table_entry *entry);
+
+/** @brief Get the string(at most one less than *size* characters) from the
+ * entry
+ *  @param[in] entry - Pointer to a bios string table entry
+ *  @param[out] buffer - Pointer to a buffer to store the string
+ *  @param[in] size - Size of the buffer to store the string
+ *  @return Length of the string decoded
+ */
+uint16_t pldm_bios_table_string_entry_decode_string(
+    const struct pldm_bios_string_table_entry *entry, char *buffer,
+    size_t size);
+
+/** @brief Get the string from the entry and check the validity of the
+ * parameters
+ *  @param[in] entry - Pointer to a bios string table entry
+ *  @param[out] buffer - Pointer to a buffer to store the string
+ *  @param[in] size - Size of the buffer to store the string
+ *  @return pldm_completion_codes
+ */
+int pldm_bios_table_string_entry_decode_string_check(
+    const struct pldm_bios_string_table_entry *entry, char *buffer,
+    size_t size);
+
+/** @brief Find an entry in bios string table by string
+ *  @param[in] table - The BIOS String Table
+ *  @param[in] length - Length of the BIOS String Table
+ *  @param[in] str - String itself
+ *  @return Pointer to an entry in the bios string table
+ */
+const struct pldm_bios_string_table_entry *
+pldm_bios_table_string_find_by_string(const void *table, size_t length,
+				      const char *str);
+/** @brief Find an entry in bios string table by handle
+ *  @param[in] table - The BIOS String Table
+ *  @param[in] length - Length of the BIOS String Table
+ *  @param[in] handle - Handle to identify a string in the bios string table
+ *  @return Pointer to an entry in the bios string table
+ */
+const struct pldm_bios_string_table_entry *
+pldm_bios_table_string_find_by_handle(const void *table, size_t length,
+				      uint16_t handle);
+
 /** @brief Get the total number of possible values for the entry
  *  @param[in] entry - Pointer to bios attribute table entry
  *  @return total number of possible values