/** @file SMBIOS String Table Helper Copyright (c) 2022, Arm Limited. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent @par Reference(s): - DSP0134 - SMBIOS Specification Version 3.6.0, 2022-06-17 **/ #include #include #include #include #include /** Add a string to the string table. @param[in] StrTable Pointer to the string table @param[in] Str Pointer to the string @param[out] StrRef Optional pointer to retrieve the string field reference of the string in the string table @return EFI_SUCCESS Success @return EFI_INVALID_PARAMETER Invalid string table pointer @return EFI_BUFFER_TOO_SMALL Insufficient space to add string **/ EFI_STATUS EFIAPI StringTableAddString ( IN STRING_TABLE *CONST StrTable, IN CONST CHAR8 *Str, OUT UINT8 *StrRef OPTIONAL ) { UINTN StrLength; STRING_ELEMENT *StrElement; if ((StrTable == NULL) || (Str == NULL)) { return EFI_INVALID_PARAMETER; } if (StrTable->StrCount >= StrTable->MaxStringElements) { return EFI_BUFFER_TOO_SMALL; } StrLength = AsciiStrLen (Str); if (StrLength == 0) { return EFI_INVALID_PARAMETER; } // Update the string element StrElement = &StrTable->Elements[StrTable->StrCount]; StrElement->StringLen = StrLength; StrElement->String = Str; // Update String table information StrTable->TotalStrLen += StrLength; StrTable->StrCount++; // Return the index of the string in the string table if requested if (StrRef != NULL) { // Note: SMBIOS string field references start at 1. So, return the // StrCount as the string reference after it is updated. *StrRef = StrTable->StrCount; } return EFI_SUCCESS; } /** Returns the total size required to publish the strings to the SMBIOS string area. @param[in] StrTable Pointer to the string table @return Total size required to publish the strings in the SMBIOS string area. **/ UINTN EFIAPI StringTableGetStringSetSize ( IN STRING_TABLE *CONST StrTable ) { if (StrTable == NULL) { ASSERT (0); return 0; } // See Section 6.1.3 Text strings, SMBIOS Specification Version 3.6.0 // - If the formatted portion of the structure contains string-reference // fields and all the string fields are set to 0 (no string references), // the formatted section of the structure is followed by two null (00h) // BYTES. // - Each string is terminated with a null (00h) BYTE // - and the set of strings is terminated with an additional null (00h) BYTE. // Therefore, if string count = 0, return 2 // if string count > 0, the string set size = // StrTable->TotalStrLen (total length of the strings in the string table) // + StrTable->StrCount (add string count to include '\0' for each string) // +1 (an additional '\0' is required at the end of the string set). return (StrTable->StrCount == 0) ? 2 : (StrTable->TotalStrLen + StrTable->StrCount + 1); } /** Iterate through the string table and publish the strings in the SMBIOS string area. @param[in] StrTable Pointer to the string table @param[in] SmbiosStringAreaStart Start address of the SMBIOS string area. @param[in] SmbiosStringAreaSize Size of the SMBIOS string area. @return EFI_SUCCESS Success @return EFI_INVALID_PARAMETER Invalid string table pointer @return EFI_BUFFER_TOO_SMALL Insufficient space to publish strings **/ EFI_STATUS EFIAPI StringTablePublishStringSet ( IN STRING_TABLE *CONST StrTable, IN CHAR8 *CONST SmbiosStringAreaStart, IN CONST UINTN SmbiosStringAreaSize ) { UINT8 Index; STRING_ELEMENT *StrElement; CHAR8 *SmbiosString; UINTN BytesRemaining; UINTN BytesCopied; if ((StrTable == NULL) || (SmbiosStringAreaStart == NULL)) { return EFI_INVALID_PARAMETER; } if (SmbiosStringAreaSize < StringTableGetStringSetSize (StrTable)) { return EFI_BUFFER_TOO_SMALL; } SmbiosString = SmbiosStringAreaStart; BytesRemaining = SmbiosStringAreaSize; if (StrTable->StrCount == 0) { // See Section 6.1.3 Text strings, SMBIOS Specification Version 3.6.0 // If the formatted portion of the structure contains string-reference // fields and all the string fields are set to 0 (no string references), // the formatted section of the structure is followed by two null (00h) // BYTES. *SmbiosString++ = '\0'; } else { for (Index = 0; Index < StrTable->StrCount; Index++) { StrElement = &StrTable->Elements[Index]; AsciiStrCpyS (SmbiosString, BytesRemaining, StrElement->String); // See Section 6.1.3 Text strings, SMBIOS Specification Version 3.6.0 // - Each string is terminated with a null (00h) BYTE // Bytes Copied = String length + 1 for the string NULL terminator. BytesCopied = StrElement->StringLen + 1; BytesRemaining -= BytesCopied; SmbiosString += BytesCopied; } } // See Section 6.1.3 Text strings, SMBIOS Specification Version 3.6.0 // - the set of strings is terminated with an additional null (00h) BYTE. *SmbiosString = '\0'; return EFI_SUCCESS; } /** Initialise the string table and allocate memory for the string elements. @param[in] StrTable Pointer to the string table @param[in] MaxStringElements Maximum number of strings that the string table can hold. @return EFI_SUCCESS Success @return EFI_INVALID_PARAMETER Invalid string table pointer @return EFI_OUT_OF_RESOURCES Failed to allocate memory for string elements **/ EFI_STATUS EFIAPI StringTableInitialize ( IN STRING_TABLE *CONST StrTable, IN UINTN MaxStringElements ) { STRING_ELEMENT *Elements; if ((StrTable == NULL) || (MaxStringElements > MAX_UINT8)) { return EFI_INVALID_PARAMETER; } ZeroMem (StrTable, sizeof (STRING_TABLE)); Elements = (STRING_ELEMENT *)AllocateZeroPool ( sizeof (STRING_ELEMENT) * MaxStringElements ); if (Elements == NULL) { return EFI_OUT_OF_RESOURCES; } StrTable->Elements = Elements; StrTable->MaxStringElements = (UINT8)MaxStringElements; return EFI_SUCCESS; } /** Free memory allocated for the string elements in the string table. @param[in] StrTable Pointer to the string table @return EFI_SUCCESS Success @return EFI_INVALID_PARAMETER Invalid string table pointer or string elements **/ EFI_STATUS EFIAPI StringTableFree ( IN STRING_TABLE *CONST StrTable ) { if ((StrTable == NULL) || (StrTable->Elements == NULL)) { return EFI_INVALID_PARAMETER; } FreePool (StrTable->Elements); ZeroMem (StrTable, sizeof (STRING_TABLE)); return EFI_SUCCESS; }