/** Update the structure buffer of a structure node in SMBIOS database. The function lead the structure pointer for SMBIOS record changed. @param StructureNode The structure node whose structure buffer is to be enlarged. @param NewRecord The new SMBIOS record. **/ VOID SmbiosUpdateStructureBuffer ( IN OUT SMBIOS_STRUCTURE_NODE *StructureNode, IN EFI_SMBIOS_TABLE_HEADER *NewRecord ) { EFI_SMBIOS_PROTOCOL *Smbios; EFI_STATUS Status; UINT8 CountOfString; Smbios = GetSmbiosProtocol(); ASSERT (Smbios != NULL); Status = Smbios->Remove (Smbios, StructureNode->SmbiosHandle); ASSERT_EFI_ERROR (Status); // // try to use original handle to enlarge the buffer. // Status = Smbios->Add (Smbios, NULL, &StructureNode->SmbiosHandle, NewRecord); ASSERT_EFI_ERROR (Status); StructureNode->Structure = GetSmbiosBufferFromHandle ( StructureNode->SmbiosHandle, StructureNode->SmbiosType, NULL ); GetSmbiosStructureSize ( StructureNode->Structure, &StructureNode->StructureSize, &CountOfString ); return ; }
/** Enlarge the structure buffer of a structure node in SMBIOS database. The function maybe lead the structure pointer for SMBIOS record changed. @param StructureNode The structure node whose structure buffer is to be enlarged. @param NewLength The new length of SMBIOS record which does not include unformat area. @param OldBufferSize The old size of SMBIOS record buffer. @param NewBufferSize The new size is targeted for enlarged. @retval EFI_OUT_OF_RESOURCES No more memory to allocate new record @retval EFI_SUCCESS Success to enlarge the record buffer size. **/ EFI_STATUS SmbiosEnlargeStructureBuffer ( IN OUT SMBIOS_STRUCTURE_NODE *StructureNode, UINT8 NewLength, UINTN OldBufferSize, UINTN NewBufferSize ) { EFI_SMBIOS_TABLE_HEADER *NewRecord; EFI_SMBIOS_PROTOCOL *Smbios; EFI_STATUS Status; UINT8 CountOfString; NewRecord = NULL; Smbios = GetSmbiosProtocol(); ASSERT (Smbios != NULL); NewRecord = (EFI_SMBIOS_TABLE_HEADER*) AllocateZeroPool (NewBufferSize); if (NewRecord == NULL) { return EFI_OUT_OF_RESOURCES; } CopyMem (NewRecord, StructureNode->Structure, OldBufferSize); Status = Smbios->Remove (Smbios, StructureNode->SmbiosHandle); ASSERT_EFI_ERROR (Status); // // try to use original handle to enlarge the buffer. // NewRecord->Length = NewLength; Status = Smbios->Add (Smbios, NULL, &StructureNode->SmbiosHandle, NewRecord); ASSERT_EFI_ERROR (Status); FreePool (NewRecord); StructureNode->Structure = GetSmbiosBufferFromHandle ( StructureNode->SmbiosHandle, StructureNode->SmbiosType, NULL ); GetSmbiosStructureSize ( StructureNode->Structure, &StructureNode->StructureSize, &CountOfString ); return EFI_SUCCESS; }
/** Fill a standard Smbios string field. This function will convert the unicode string to single byte chars, and only English language is supported. This function changes the Structure pointer value of the structure node, which should be noted by Caller. @param StructureNode Pointer to SMBIOS_STRUCTURE_NODE which is current processed. @param Offset Offset of SMBIOS record which RecordData will be filled. @param RecordData RecordData buffer will be filled. @param RecordDataSize The size of RecordData buffer. @retval EFI_INVALID_PARAMETER RecordDataSize is too larger @retval EFI_OUT_OF_RESOURCES No memory to allocate new buffer for string @retval EFI_SUCCESS Sucess append string for a SMBIOS record. **/ EFI_STATUS SmbiosFldString ( IN OUT SMBIOS_STRUCTURE_NODE *StructureNode, IN UINT32 Offset, IN VOID *RecordData, IN UINT32 RecordDataSize ) { EFI_STATUS Status; UINT16 *Data; CHAR8 AsciiData[SMBIOS_STRING_MAX_LENGTH]; UINT8 CountOfStrings; UINTN OrigStringNumber; EFI_SMBIOS_PROTOCOL *Smbios; EFI_SMBIOS_HANDLE SmbiosHandle; UINT32 OrigStructureSize; UINTN NewStructureSize; EFI_SMBIOS_TABLE_HEADER *NewRecord; UINT32 StringLength; Status = EFI_SUCCESS; OrigStringNumber = 0; OrigStructureSize = 0; // // if we have a NULL token, // if (0 == *((STRING_REF *) RecordData)) { *(UINT8 *) ((UINT8 *) (StructureNode->Structure) + Offset) = 0; return EFI_SUCCESS; } // // Get the String from the Hii Database // Data = HiiGetPackageString ( &(StructureNode->ProducerName), *((EFI_STRING_ID *) RecordData), NULL ); if (Data == NULL) { return EFI_INVALID_PARAMETER; } StringLength = (UINT32)StrLen (Data); // // Count the string size including the terminating 0. // if (StringLength == 0) { *(UINT8 *) ((UINT8 *) (StructureNode->Structure) + Offset) = 0; FreePool (Data); return EFI_SUCCESS; } if (StringLength > SMBIOS_STRING_MAX_LENGTH) { // // Too long a string // FreePool (Data); return EFI_INVALID_PARAMETER; } Smbios = GetSmbiosProtocol(); ASSERT (Smbios != NULL); // // Convert Unicode string to Ascii string which only supported by SMBIOS. // ZeroMem (AsciiData, SMBIOS_STRING_MAX_LENGTH); UnicodeStrToAsciiStr (Data, AsciiData); // // if the field at offset is already filled with some value, // find out the string it points to // OrigStringNumber = *(UINT8 *) ((UINT8 *) (StructureNode->Structure) + Offset); if (OrigStringNumber != 0) { DEBUG ((EFI_D_ERROR, "[SMBIOSThunk] Update %dth string for type[%d],offset[0x%x],handle[0x%x] to [%s]\n", OrigStringNumber, StructureNode->SmbiosType, Offset, StructureNode->SmbiosHandle, AsciiData)); // // If original string number is not zero, just update string // Status = Smbios->UpdateString (Smbios, &StructureNode->SmbiosHandle, &OrigStringNumber, AsciiData); if (EFI_ERROR (Status)) { DEBUG ((EFI_D_ERROR, "[SMBIOSThunk] Fail to update %dth string in offset 0x%x for handle:0x%x type:0x%x\n", OrigStringNumber, Offset, StructureNode->SmbiosHandle, StructureNode->SmbiosType)); ASSERT_EFI_ERROR (Status); return Status; } } else { // // If the string has not been filled in SMBIOS database, remove it and add again // with string appended. // Status = GetSmbiosStructureSize (StructureNode->Structure, &OrigStructureSize, &CountOfStrings); ASSERT_EFI_ERROR (Status); if (CountOfStrings == 0) { NewStructureSize = OrigStructureSize + StringLength; } else { NewStructureSize = OrigStructureSize + StringLength + 1; } NewRecord = AllocateZeroPool (NewStructureSize); if (NewRecord == NULL) { return EFI_OUT_OF_RESOURCES; } CopyMem (NewRecord, StructureNode->Structure, OrigStructureSize); // // Copy new string into tail of original SMBIOS record buffer. // if (CountOfStrings == 0) { AsciiStrCpy ((CHAR8 *)NewRecord + OrigStructureSize - 2, AsciiData); } else { AsciiStrCpy ((CHAR8 *)NewRecord + OrigStructureSize - 1, AsciiData); } DEBUG ((EFI_D_ERROR, "[SMBIOSThunk] Type(%d) offset(0x%x) StringNumber:%d\n", StructureNode->SmbiosType, Offset, CountOfStrings + 1)); // // Update string reference number // *(UINT8 *) ((UINT8 *) NewRecord + Offset) = (UINT8) (CountOfStrings + 1); SmbiosHandle = StructureNode->SmbiosHandle; // // Remove original SMBIOS record and add new one // Status = Smbios->Remove (Smbios, StructureNode->SmbiosHandle); ASSERT_EFI_ERROR (Status); // // Add new SMBIOS record // Status = Smbios->Add (Smbios, NULL, &SmbiosHandle, NewRecord); ASSERT_EFI_ERROR (Status); StructureNode->SmbiosHandle = SmbiosHandle; FreePool (NewRecord); } // // The SMBIOS record buffer maybe re-allocated in SMBIOS database, // so update cached buffer pointer in DataHub structure list. // StructureNode->Structure = GetSmbiosBufferFromHandle ( StructureNode->SmbiosHandle, StructureNode->SmbiosType, NULL ); ASSERT (StructureNode->Structure != NULL); // // The string update action maybe lead the record is re-allocated in SMBIOS database // so update cached record pointer // Status = GetSmbiosStructureSize (StructureNode->Structure, &StructureNode->StructureSize, &CountOfStrings); ASSERT_EFI_ERROR (Status); return EFI_SUCCESS; }