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
diff --git a/libpldmresponder/bios.cpp b/libpldmresponder/bios.cpp
index 8dbc80e..5bfe0ae 100644
--- a/libpldmresponder/bios.cpp
+++ b/libpldmresponder/bios.cpp
@@ -138,16 +138,6 @@
     return attrHdl++;
 }
 
-/** @brief Generate the next string handle
- *  *
- *  @return - uint16_t - next string handle
- */
-StringHandle nextStringHandle()
-{
-    static StringHandle strHdl = 0;
-    return strHdl++;
-}
-
 /** @brief Construct the BIOS string table
  *
  *  @param[in] BIOSStringTable - the string table
@@ -164,66 +154,52 @@
     Response response(sizeof(pldm_msg_hdr) + PLDM_GET_BIOS_TABLE_MIN_RESP_BYTES,
                       0);
     auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
-
-    if (BIOSStringTable.isEmpty())
-    { // no persisted table, constructing fresh table and file
-        auto biosStrings = bios_parser::getStrings();
-        std::sort(biosStrings.begin(), biosStrings.end());
-        // remove all duplicate strings received from bios json
-        biosStrings.erase(std::unique(biosStrings.begin(), biosStrings.end()),
-                          biosStrings.end());
-        size_t allStringsLen =
-            std::accumulate(biosStrings.begin(), biosStrings.end(), 0,
-                            [](size_t sum, const std::string& elem) {
-                                return sum + elem.size();
-                            });
-        size_t sizeWithoutPad =
-            allStringsLen +
-            (biosStrings.size() * (sizeof(pldm_bios_string_table_entry) - 1));
-        Table stringTable;
-        stringTable.reserve(utils::getTableTotalsize(sizeWithoutPad));
-
-        stringTable.resize(sizeWithoutPad);
-        auto tablePtr = stringTable.data();
-        for (const auto& elem : biosStrings)
-        {
-            auto stringPtr =
-                reinterpret_cast<struct pldm_bios_string_table_entry*>(
-                    tablePtr);
-
-            stringPtr->string_handle = nextStringHandle();
-            stringPtr->string_length = elem.length();
-            memcpy(stringPtr->name, elem.c_str(), elem.length());
-            tablePtr += sizeof(stringPtr->string_handle) +
-                        sizeof(stringPtr->string_length);
-            tablePtr += elem.length();
-        }
-
-        utils::padAndChecksum(stringTable);
-        BIOSStringTable.store(stringTable);
-        response.resize(sizeof(pldm_msg_hdr) +
-                            PLDM_GET_BIOS_TABLE_MIN_RESP_BYTES +
-                            stringTable.size(),
-                        0);
-        responsePtr = reinterpret_cast<pldm_msg*>(response.data());
-        size_t respPayloadLength = response.size();
-        uint32_t nxtTransferHandle = 0;
-        uint8_t transferFlag = PLDM_START_AND_END;
-        encode_get_bios_table_resp(instanceID, PLDM_SUCCESS, nxtTransferHandle,
-                                   transferFlag, stringTable.data(),
-                                   respPayloadLength, responsePtr);
-    }
-    else
-    { // persisted table present, constructing response
-        size_t respPayloadLength = response.size();
-        uint32_t nxtTransferHandle = 0;
-        uint8_t transferFlag = PLDM_START_AND_END;
-        encode_get_bios_table_resp(instanceID, PLDM_SUCCESS, nxtTransferHandle,
-                                   transferFlag, nullptr, respPayloadLength,
+    if (!BIOSStringTable.isEmpty())
+    {
+        encode_get_bios_table_resp(instanceID, PLDM_SUCCESS,
+                                   0, /* next transfer handle */
+                                   PLDM_START_AND_END, nullptr, response.size(),
                                    responsePtr); // filling up the header here
         BIOSStringTable.load(response);
+        return response;
+    }
+    auto biosStrings = bios_parser::getStrings();
+    std::sort(biosStrings.begin(), biosStrings.end());
+    // remove all duplicate strings received from bios json
+    biosStrings.erase(std::unique(biosStrings.begin(), biosStrings.end()),
+                      biosStrings.end());
+
+    size_t sizeWithoutPad = std::accumulate(
+        biosStrings.begin(), biosStrings.end(), 0,
+        [](size_t sum, const std::string& elem) {
+            return sum +
+                   pldm_bios_table_string_entry_encode_length(elem.length());
+        });
+
+    Table stringTable;
+    stringTable.reserve(utils::getTableTotalsize(sizeWithoutPad));
+
+    stringTable.resize(sizeWithoutPad);
+    auto tablePtr = stringTable.data();
+    for (const auto& elem : biosStrings)
+    {
+        auto entry_length =
+            pldm_bios_table_string_entry_encode_length(elem.length());
+        pldm_bios_table_string_entry_encode(tablePtr, sizeWithoutPad,
+                                            elem.c_str(), elem.length());
+        tablePtr += entry_length;
+        sizeWithoutPad -= entry_length;
     }
 
+    utils::padAndChecksum(stringTable);
+    BIOSStringTable.store(stringTable);
+    response.resize(sizeof(pldm_msg_hdr) + PLDM_GET_BIOS_TABLE_MIN_RESP_BYTES +
+                        stringTable.size(),
+                    0);
+    responsePtr = reinterpret_cast<pldm_msg*>(response.data());
+    encode_get_bios_table_resp(
+        instanceID, PLDM_SUCCESS, 0 /* nxtTransferHandle */, PLDM_START_AND_END,
+        stringTable.data(), response.size(), responsePtr);
     return response;
 }
 
@@ -236,38 +212,19 @@
 StringHandle findStringHandle(const std::string& name,
                               const BIOSTable& BIOSStringTable)
 {
-    StringHandle hdl{};
-    Response response;
-    BIOSStringTable.load(response);
-
-    auto tableData = response.data();
-    size_t tableLen = response.size();
-    auto tableEntry =
-        reinterpret_cast<struct pldm_bios_string_table_entry*>(response.data());
-    while (1)
+    Table table;
+    BIOSStringTable.load(table);
+    auto stringEntry = pldm_bios_table_string_find_by_string(
+        table.data(), table.size(), name.c_str());
+    if (stringEntry == nullptr)
     {
-        hdl = tableEntry->string_handle;
-        uint16_t len = tableEntry->string_length;
-        if (name.compare(0, name.length(), tableEntry->name, len) == 0)
-        {
-            break;
-        }
-        tableData += (sizeof(struct pldm_bios_string_table_entry) - 1) + len;
-
-        if (std::distance(tableData, response.data() + tableLen) <=
-            padChksumMax)
-        {
-            log<level::ERR>("Reached end of BIOS string table,did not find the "
-                            "handle for the string",
-                            entry("STRING=%s", name.c_str()));
-            elog<InternalFailure>();
-            break;
-        }
-
-        tableEntry =
-            reinterpret_cast<struct pldm_bios_string_table_entry*>(tableData);
+        log<level::ERR>("Reached end of BIOS string table,did not find the "
+                        "handle for the string",
+                        entry("STRING=%s", name.c_str()));
+        elog<InternalFailure>();
     }
-    return hdl;
+
+    return pldm_bios_table_string_entry_decode_handle(stringEntry);
 }
 
 /** @brief Find the string name from the BIOS string table for a string handle
@@ -280,38 +237,22 @@
 std::string findStringName(StringHandle stringHdl,
                            const BIOSTable& BIOSStringTable)
 {
+    Table table;
+    BIOSStringTable.load(table);
+    auto stringEntry = pldm_bios_table_string_find_by_handle(
+        table.data(), table.size(), stringHdl);
     std::string name;
-    Response response;
-    BIOSStringTable.load(response);
-
-    auto tableData = response.data();
-    size_t tableLen = response.size();
-    auto tableEntry =
-        reinterpret_cast<struct pldm_bios_string_table_entry*>(response.data());
-    while (1)
+    if (stringEntry == nullptr)
     {
-        StringHandle currHdl = tableEntry->string_handle;
-        uint16_t len = tableEntry->string_length;
-        if (currHdl == stringHdl)
-        {
-            name.resize(len);
-            memcpy(name.data(), tableEntry->name, len);
-            break;
-        }
-        tableData += (sizeof(struct pldm_bios_string_table_entry) - 1) + len;
-
-        if (std::distance(tableData, response.data() + tableLen) <=
-            padChksumMax)
-        {
-            log<level::ERR>("Reached end of BIOS string table,did not find "
-                            "string name for handle",
-                            entry("STRING_HANDLE=%d", stringHdl));
-            break;
-        }
-
-        tableEntry =
-            reinterpret_cast<struct pldm_bios_string_table_entry*>(tableData);
+        log<level::ERR>("Reached end of BIOS string table,did not find "
+                        "string name for handle",
+                        entry("STRING_HANDLE=%d", stringHdl));
     }
+    auto strLength =
+        pldm_bios_table_string_entry_decode_string_length(stringEntry);
+    name.resize(strLength);
+    pldm_bios_table_string_entry_decode_string(stringEntry, name.data(),
+                                               name.size());
     return name;
 }
 
diff --git a/test/libpldm_bios_table_test.cpp b/test/libpldm_bios_table_test.cpp
index bc4ec09..8a808a5 100644
--- a/test/libpldm_bios_table_test.cpp
+++ b/test/libpldm_bios_table_test.cpp
@@ -271,6 +271,148 @@
     EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
 }
 
+TEST(StringTable, EntryEncodeTest)
+{
+    std::vector<uint8_t> stringEntry{
+        0,   0,                            /* string handle*/
+        7,   0,                            /* string length */
+        'A', 'l', 'l', 'o', 'w', 'e', 'd', /* string */
+    };
+
+    const char* str = "Allowed";
+    auto str_length = std::strlen(str);
+    auto encodeLength = pldm_bios_table_string_entry_encode_length(str_length);
+    EXPECT_EQ(encodeLength, stringEntry.size());
+
+    std::vector<uint8_t> encodeEntry(encodeLength, 0);
+    pldm_bios_table_string_entry_encode(encodeEntry.data(), encodeEntry.size(),
+                                        str, str_length);
+    // set string handle = 0
+    encodeEntry[0] = 0;
+    encodeEntry[1] = 0;
+
+    EXPECT_EQ(stringEntry, encodeEntry);
+
+    EXPECT_DEATH(pldm_bios_table_string_entry_encode(encodeEntry.data(),
+                                                     encodeEntry.size() - 1,
+                                                     str, str_length),
+                 "length <= entry_length");
+    auto rc = pldm_bios_table_string_entry_encode_check(
+        encodeEntry.data(), encodeEntry.size() - 1, str, str_length);
+    EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
+}
+
+TEST(StringTable, EntryDecodeTest)
+{
+    std::vector<uint8_t> stringEntry{
+        4,   0,                            /* string handle*/
+        7,   0,                            /* string length */
+        'A', 'l', 'l', 'o', 'w', 'e', 'd', /* string */
+    };
+    auto entry = reinterpret_cast<struct pldm_bios_string_table_entry*>(
+        stringEntry.data());
+    auto handle = pldm_bios_table_string_entry_decode_handle(entry);
+    EXPECT_EQ(handle, 4);
+    auto strLength = pldm_bios_table_string_entry_decode_string_length(entry);
+    EXPECT_EQ(strLength, 7);
+
+    std::vector<char> buffer(strLength + 1, 0);
+    auto decodedLength = pldm_bios_table_string_entry_decode_string(
+        entry, buffer.data(), buffer.size());
+    EXPECT_EQ(decodedLength, strLength);
+    EXPECT_EQ(std::strcmp("Allowed", buffer.data()), 0);
+    decodedLength =
+        pldm_bios_table_string_entry_decode_string(entry, buffer.data(), 2);
+    EXPECT_EQ(decodedLength, 2);
+    EXPECT_EQ(std::strcmp("Al", buffer.data()), 0);
+
+    auto rc = pldm_bios_table_string_entry_decode_string_check(
+        entry, buffer.data(), buffer.size());
+    EXPECT_EQ(rc, PLDM_SUCCESS);
+    EXPECT_EQ(std::strcmp("Allowed", buffer.data()), 0);
+
+    rc = pldm_bios_table_string_entry_decode_string_check(entry, buffer.data(),
+                                                          buffer.size() - 1);
+    EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
+}
+
+TEST(StringTable, IteratorTest)
+{
+    std::vector<uint8_t> stringHello{
+        0,   0,                  /* string handle*/
+        5,   0,                  /* string length */
+        'H', 'e', 'l', 'l', 'o', /* string */
+    };
+    std::vector<uint8_t> stringWorld{
+        1,   0,                       /* string handle*/
+        6,   0,                       /* string length */
+        'W', 'o', 'r', 'l', 'd', '!', /* string */
+    };
+
+    Table table;
+    buildTable(table, stringHello, stringWorld);
+
+    auto iter = pldm_bios_table_iter_create(table.data(), table.size(),
+                                            PLDM_BIOS_STRING_TABLE);
+    auto entry = pldm_bios_table_iter_string_entry_value(iter);
+    auto rc = std::memcmp(entry, stringHello.data(), stringHello.size());
+    EXPECT_EQ(rc, 0);
+    pldm_bios_table_iter_next(iter);
+    entry = pldm_bios_table_iter_string_entry_value(iter);
+    rc = std::memcmp(entry, stringWorld.data(), stringWorld.size());
+    EXPECT_EQ(rc, 0);
+    pldm_bios_table_iter_next(iter);
+    EXPECT_TRUE(pldm_bios_table_iter_is_end(iter));
+    pldm_bios_table_iter_free(iter);
+}
+
+TEST(StringTable, FindTest)
+{
+    std::vector<uint8_t> stringHello{
+        1,   0,                  /* string handle*/
+        5,   0,                  /* string length */
+        'H', 'e', 'l', 'l', 'o', /* string */
+    };
+    std::vector<uint8_t> stringWorld{
+        2,   0,                       /* string handle*/
+        6,   0,                       /* string length */
+        'W', 'o', 'r', 'l', 'd', '!', /* string */
+    };
+    std::vector<uint8_t> stringHi{
+        3,   0,   /* string handle*/
+        2,   0,   /* string length */
+        'H', 'i', /* string */
+    };
+
+    Table table;
+    buildTable(table, stringHello, stringWorld, stringHi);
+
+    auto entry = pldm_bios_table_string_find_by_string(table.data(),
+                                                       table.size(), "World!");
+    EXPECT_NE(entry, nullptr);
+    auto handle = pldm_bios_table_string_entry_decode_handle(entry);
+    EXPECT_EQ(handle, 2);
+
+    entry = pldm_bios_table_string_find_by_string(table.data(), table.size(),
+                                                  "Worl");
+    EXPECT_EQ(entry, nullptr);
+
+    entry =
+        pldm_bios_table_string_find_by_handle(table.data(), table.size(), 3);
+    EXPECT_NE(entry, nullptr);
+    auto str_length = pldm_bios_table_string_entry_decode_string_length(entry);
+    EXPECT_EQ(str_length, 2);
+    std::vector<char> strBuf(str_length + 1, 0);
+    auto rc = pldm_bios_table_string_entry_decode_string_check(
+        entry, strBuf.data(), strBuf.size());
+    EXPECT_EQ(rc, PLDM_SUCCESS);
+    EXPECT_EQ(std::strcmp("Hi", strBuf.data()), 0);
+
+    entry =
+        pldm_bios_table_string_find_by_handle(table.data(), table.size(), 4);
+    EXPECT_EQ(entry, nullptr);
+}
+
 TEST(Itearator, DeathTest)
 {