diff options
Diffstat (limited to 'Lesson_27')
-rw-r--r-- | Lesson_27/BIOS_menu.png | bin | 7868 -> 0 bytes | |||
-rw-r--r-- | Lesson_27/README.md | 696 | ||||
-rw-r--r-- | Lesson_27/SMBIOS_entry_structure.png | bin | 90357 -> 0 bytes | |||
-rw-r--r-- | Lesson_27/SMBIOS_entry_structure_dump.png | bin | 9665 -> 0 bytes | |||
-rw-r--r-- | Lesson_27/UefiLessonsPkg/SmbiosInfo/SmbiosInfo.c | 88 | ||||
-rw-r--r-- | Lesson_27/UefiLessonsPkg/SmbiosInfo/SmbiosInfo.inf | 24 |
6 files changed, 0 insertions, 808 deletions
diff --git a/Lesson_27/BIOS_menu.png b/Lesson_27/BIOS_menu.png Binary files differdeleted file mode 100644 index cd28ef5..0000000 --- a/Lesson_27/BIOS_menu.png +++ /dev/null diff --git a/Lesson_27/README.md b/Lesson_27/README.md deleted file mode 100644 index 5248b24..0000000 --- a/Lesson_27/README.md +++ /dev/null @@ -1,696 +0,0 @@ -Let's try to get information from one of the system tables that we've discovered. - -You can find the most recent version of the "System Management BIOS (SMBIOS) Reference Specification" on the DMTF site https://www.dmtf.org/dsp/DSP0134 -For example now 3.4.0 is the most recent version https://www.dmtf.org/sites/default/files/standards/documents/DSP0134_3.4.0.pdf - -From the previous lesson we now, that SMBIOS table is declared under `gEfiSmbiosTableGuid`. - -Let's create an app, that would print the address of this table. -``` -#include <Library/UefiBootServicesTableLib.h> -#include <Library/UefiLib.h> - -#include <Library/BaseMemoryLib.h> - -EFI_STATUS -EFIAPI -UefiMain ( - IN EFI_HANDLE ImageHandle, - IN EFI_SYSTEM_TABLE *SystemTable - ) -{ - for (UINTN i=0; i<SystemTable->NumberOfTableEntries; i++) { - if (CompareGuid(&(SystemTable->ConfigurationTable[i].VendorGuid), &gEfiSmbiosTableGuid)) { - Print(L"SMBIOS table is placed at %p\n", SystemTable->ConfigurationTable[i].VendorTable); - } - } - return EFI_SUCCESS; -} -``` - -In this code we've used `CompareGuid` function from the https://github.com/tianocore/edk2/blob/master/MdePkg/Include/Library/BaseMemoryLib.h: -``` -/** - Compares two GUIDs. - This function compares Guid1 to Guid2. If the GUIDs are identical then TRUE is returned. - If there are any bit differences in the two GUIDs, then FALSE is returned. - If Guid1 is NULL, then ASSERT(). - If Guid2 is NULL, then ASSERT(). - @param Guid1 A pointer to a 128 bit GUID. - @param Guid2 A pointer to a 128 bit GUID. - @retval TRUE Guid1 and Guid2 are identical. - @retval FALSE Guid1 and Guid2 are not identical. -**/ -BOOLEAN -EFIAPI -CompareGuid ( - IN CONST GUID *Guid1, - IN CONST GUID *Guid2 - ); -``` - -Don't forget to add: -``` -[Guids] - gEfiSmbiosTableGuid -``` -to app *inf file. - -Let's build our app and execute it under OVMF: -``` -FS0:\> SmbiosInfo.efi -SMBIOS table is placed at 7941000 -``` - -# Get SMBIOS tables with `dmem` - -UEFI shell has a command `dmem` for memory dump: -``` -FS0:\> dmem -? -b -Displays the contents of system or device memory. - -DMEM [-b] [address] [size] [-MMIO] - - -b - Displays one screen at a time. - -MMIO - Forces address cycles to the PCI bus. - address - Specifies a starting address in hexadecimal format. - size - Specifies the number of bytes to display in hexadecimal format. - -NOTES: - 1. This command displays the contents of system memory or device memory. - 2. Enter address and size in hexadecimal format. - 3. If address is not specified, the contents of the UEFI System Table - are displayed. Otherwise, memory starting at the specified address is displayed. - 4. Size specifies the number of bytes to display. If size is not specified, - 512 bytes are displayed. - 5. If MMIO is not specified, main system memory is displayed. Otherwise, - device memory is displayed through the use of the - EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL. - -EXAMPLES: - * To display the UEFI system table pointer entries: - fs0:\> dmem - - * To display memory contents from 1af3088 with size of 16 bytes: - Shell> dmem 1af3088 16 - - * To display memory mapped IO contents from 1af3088 with a size of 16 bytes: - Shell> dmem 1af3088 16 -MMIO -``` - -Let's use it to print 0x30 bytes from the 0x7941000 address that we count as a SMBIOS table pointer. -``` -FS0:\> dmem 7941000 30 -Memory Address 0000000007941000 30 Bytes - 07941000: 5F 53 4D 5F 26 1F 02 08-53 00 00 00 00 00 00 00 *_SM_&...S.......* - 07941010: 5F 44 4D 49 5F 0A 91 01-00 00 94 07 09 00 28 AF *_DMI_.........(.* - 07941020: AF AF AF AF AF AF AF AF-AF AF AF AF AF AF AF AF *................* -``` - -If you look at SMBIOS specification for SMBIOS Entry Point structure you'll see, that `_SM_` and `_DMI_` are predefined values in this structure. - -![SMBIOS_entry_structure](SMBIOS_entry_structure.png?raw=true "SMBIOS_entry_structure") - -You can find definition for the structure itself in edk2 under https://github.com/tianocore/edk2/blob/master/MdePkg/Include/IndustryStandard/SmBios.h -``` -typedef struct { - UINT8 AnchorString[4]; - UINT8 EntryPointStructureChecksum; - UINT8 EntryPointLength; - UINT8 MajorVersion; - UINT8 MinorVersion; - UINT16 MaxStructureSize; - UINT8 EntryPointRevision; - UINT8 FormattedArea[5]; - UINT8 IntermediateAnchorString[5]; - UINT8 IntermediateChecksum; - UINT16 TableLength; - UINT32 TableAddress; - UINT16 NumberOfSmbiosStructures; - UINT8 SmbiosBcdRevision; -} SMBIOS_TABLE_ENTRY_POINT; -``` - -If you calculate offsets for different fields you can parse memory dump: - -![SMBIOS_entry_structure_dump](SMBIOS_entry_structure_dump.png?raw=true "SMBIOS_entry_structure_dump") - -System has 9 SMBIOS structures placed from 0x07940000 to (0x07940000+0x191). - -Now when we know address for SMBIOS structures, we can dump them as well. -``` -FS0:\> dmem 07940000 191 -Memory Address 0000000007940000 191 Bytes - 07940000: 01 1B 00 01 01 02 03 00-00 00 00 00 00 00 00 00 *................* - 07940010: 00 00 00 00 00 00 00 00-06 00 00 51 45 4D 55 00 *...........QEMU.* - 07940020: 53 74 61 6E 64 61 72 64-20 50 43 20 28 69 34 34 *Standard PC (i44* - 07940030: 30 46 58 20 2B 20 50 49-49 58 2C 20 31 39 39 36 *0FX + PIIX, 1996* - 07940040: 29 00 70 63 2D 69 34 34-30 66 78 2D 66 6F 63 61 *).pc-i440fx-foca* - 07940050: 6C 00 00 03 16 00 03 01-01 02 00 00 03 03 03 02 *l...............* - 07940060: 00 00 00 00 00 00 00 00-00 51 45 4D 55 00 70 63 *.........QEMU.pc* - 07940070: 2D 69 34 34 30 66 78 2D-66 6F 63 61 6C 00 00 04 *-i440fx-focal...* - 07940080: 2A 00 04 01 03 01 02 63-06 00 00 FD FB 8B 07 03 **......c........* - 07940090: 00 00 00 D0 07 D0 07 41-01 FF FF FF FF FF FF 00 *.......A........* - 079400A0: 00 00 01 01 01 02 00 01-00 43 50 55 20 30 00 51 *.........CPU 0.Q* - 079400B0: 45 4D 55 00 70 63 2D 69-34 34 30 66 78 2D 66 6F *EMU.pc-i440fx-fo* - 079400C0: 63 61 6C 00 00 10 17 00-10 01 03 06 00 00 02 00 *cal.............* - 079400D0: FE FF 01 00 00 00 00 00-00 00 00 00 00 00 11 28 *...............(* - 079400E0: 00 11 00 10 FE FF FF FF-FF FF 80 00 09 00 01 00 *................* - 079400F0: 07 02 00 00 00 02 00 00-00 00 00 00 00 00 00 00 *................* - 07940100: 00 00 00 00 00 00 44 49-4D 4D 20 30 00 51 45 4D *......DIMM 0.QEM* - 07940110: 55 00 00 13 1F 00 13 00-00 00 00 FF FF 01 00 00 *U...............* - 07940120: 10 01 00 00 00 00 00 00-00 00 00 00 00 00 00 00 *................* - 07940130: 00 00 00 00 20 0B 00 20-00 00 00 00 00 00 00 00 *.... .. ........* - 07940140: 00 00 1A 00 00 01 02 00-E8 03 00 08 00 00 00 00 *................* - 07940150: 00 00 00 00 1C 00 00 FF-FF 00 00 45 46 49 20 44 *...........EFI D* - 07940160: 65 76 65 6C 6F 70 6D 65-6E 74 20 4B 69 74 20 49 *evelopment Kit I* - 07940170: 49 20 2F 20 4F 56 4D 46-00 30 2E 30 2E 30 00 30 *I / OVMF.0.0.0.0* - 07940180: 32 2F 30 36 2F 32 30 31-35 00 00 7F 04 FF FE 00 *2/06/2015.......* - 07940190: 00 *.* -``` - -# Use EFI_SMBIOS_PROTOCOL to parse SMBIOS data - -We can use direct pointer arithmetics to parse SMBIOS tables, but that would be very tedious. - -Luckily UEFI PI specification defines a `EFI_SMBIOS_PROTOCOL`, that we can use to get SMBIOS data. - -``` -EFI_SMBIOS_PROTOCOL - -Summary: -Allows consumers to log SMBIOS data records, and enables the producer to create the SMBIOS tables for a platform. - -Protocol Interface Structure: -typedef struct _EFI_SMBIOS_PROTOCOL { - EFI_SMBIOS_ADD Add; - EFI_SMBIOS_UPDATE_STRINGUpdateString; - EFI_SMBIOS_REMOVE Remove; - EFI_SMBIOS_GET_NEXT GetNext; - UINT8 MajorVersion; - UINT8 MinorVersion; -} EFI_SMBIOS_PROTOCOL; - -Member Description: -Add Add an SMBIOS record including the formatted area and the optional strings - that follow the formatted area. -UpdateString Update a string in the SMBIOS record. -Remove Remove an SMBIOS record. -GetNext Discover all SMBIOS records. -MajorVersion The major revision of the SMBIOS specification supported. -MinorVersion The minor revision of the SMBIOS specification supported. - -Description: -This protocol provides an interface to add, remove or discover SMBIOS records. The driver which -produces this protocol is responsible for creating the SMBIOS data tables and installing the pointer -to the tables in the EFI System Configuration Table. -``` - -Right now we are interested in SMBIOS table parsing, so we need to utilize `GetNext` function: -``` -EFI_SMBIOS_PROTOCOL.GetNext() - -Summary: -Allow the caller to discover all or some of the SMBIOS records. -Prototype -typedef -EFI_STATUS -(EFIAPI *EFI_SMBIOS_GET_NEXT) ( - IN CONST EFI_SMBIOS_PROTOCOL *This, - IN OUT EFI_SMBIOS_HANDLE *SmbiosHandle, - IN EFI_SMBIOS_TYPE *Type, OPTIONAL - OUT EFI_SMBIOS_TABLE_HEADER **Record, - OUT EFI_HANDLE *ProducerHandle OPTIONAL - ); - -Parameters: -This The EFI_SMBIOS_PROTOCOL instance. -SmbiosHandle On entry, points to the previous handle of the SMBIOS record. On exit, points to the - next SMBIOS record handle. If it is FFFEh on entry, then the first SMBIOS record - handle will be returned. If it returns FFFEh on exit, then there are no more SMBIOS - records. -Type On entry, it points to the type of the next SMBIOS record to return. If NULL, it - indicates that the next record of any type will be returned. Type is not modified by - the this function. -Record On exit, points to a pointer to the the SMBIOS Record consisting of the formatted area - followed by the unformatted area. The unformatted area optionally contains text - strings. -ProducerHandle On exit, points to the ProducerHandle registered by Add(). If no - ProducerHandle was passed into Add() NULL is returned. If a NULL pointer is - passed in no data will be returned - -Description -This function allows all of the SMBIOS records to be discovered. It's possible to find -only the SMBIOS records that match the optional Type argument. - -Status Codes Returned: -EFI_SUCCESS .SMBIOS record information was successfully returned in Record. - SmbiosHandle is the handle of the current SMBIOS record -EFI_NOT_FOUND The SMBIOS record with SmbiosHandle was the last available record. -``` - -First let's get this protocol in our app. -``` -EFI_SMBIOS_PROTOCOL* SmbiosProtocol; -EFI_STATUS Status = gBS->LocateProtocol ( - &gEfiSmbiosProtocolGuid, - NULL, - (VOID**)&SmbiosProtocol - ); -if (EFI_ERROR (Status)) { - return Status; -} -``` -To use it we need to add include to our app https://github.com/tianocore/edk2/blob/master/MdePkg/Include/Protocol/Smbios.h: -``` -#include <Protocol/Smbios.h> -``` -And add protocol guid to our *.inf file: -``` -[Protocols] - gEfiSmbiosProtocolGuid -``` - -Now let's try to get SMBIOS tables. We would be using `SMBIOS_HANDLE_PI_RESERVED` as `EFI_SMBIOS_HANDLE` in protocol calls. You can find explanation in https://github.com/tianocore/edk2/blob/master/MdePkg/Include/IndustryStandard/SmBios.h: -``` -/// -/// Reference SMBIOS 2.7, chapter 6.1.2. -/// The UEFI Platform Initialization Specification reserves handle number FFFEh for its -/// EFI_SMBIOS_PROTOCOL.Add() function to mean "assign an unused handle number automatically." -/// This number is not used for any other purpose by the SMBIOS specification. -/// -#define SMBIOS_HANDLE_PI_RESERVED 0xFFFE -``` - -Also before we start writing code look at the definition of `EFI_SMBIOS_TABLE_HEADER` structure, that we would receive on `GetNext` calls. -https://github.com/tianocore/edk2/blob/master/MdePkg/Include/Protocol/Smbios.h -``` -typedef SMBIOS_STRUCTURE EFI_SMBIOS_TABLE_HEADER; -``` -https://github.com/tianocore/edk2/blob/master/MdePkg/Include/IndustryStandard/SmBios.h -``` -/// -/// The Smbios structure header. -/// -typedef struct { - SMBIOS_TYPE Type; - UINT8 Length; - SMBIOS_HANDLE Handle; -} SMBIOS_STRUCTURE; -``` - -Now we are ready to write some code. Write a code to print all types of Smbios tables that are present in the system: -``` -EFI_SMBIOS_HANDLE SmbiosHandle = SMBIOS_HANDLE_PI_RESERVED; -EFI_SMBIOS_TABLE_HEADER* Record; -Status = SmbiosProtocol->GetNext(SmbiosProtocol, - &SmbiosHandle, - NULL, - &Record, - NULL); -while (!EFI_ERROR(Status)) { - Print (L"SMBIOS Type %d \n", Record->Type); - Status = SmbiosProtocol->GetNext(SmbiosProtocol, - &SmbiosHandle, - NULL, - &Record, - NULL); -} -``` - -If you build our app and test it under OVMF you would get: -``` -SMBIOS table is placed at 7941000 -SMBIOS Type 1 -SMBIOS Type 3 -SMBIOS Type 4 -SMBIOS Type 16 -SMBIOS Type 17 -SMBIOS Type 19 -SMBIOS Type 32 -SMBIOS Type 0 -``` - -Ok, now let's write code that can parse information in these tables. - -Let's start with Type 0 table. edk2 has a structure description at https://github.com/tianocore/edk2/blob/master/MdePkg/Include/IndustryStandard/SmBios.h: -``` -/// -/// BIOS Information (Type 0). -/// -typedef struct { - SMBIOS_STRUCTURE Hdr; - SMBIOS_TABLE_STRING Vendor; - SMBIOS_TABLE_STRING BiosVersion; - UINT16 BiosSegment; - SMBIOS_TABLE_STRING BiosReleaseDate; - UINT8 BiosSize; - MISC_BIOS_CHARACTERISTICS BiosCharacteristics; - UINT8 BIOSCharacteristicsExtensionBytes[2]; - UINT8 SystemBiosMajorRelease; - UINT8 SystemBiosMinorRelease; - UINT8 EmbeddedControllerFirmwareMajorRelease; - UINT8 EmbeddedControllerFirmwareMinorRelease; - // - // Add for smbios 3.1.0 - // - EXTENDED_BIOS_ROM_SIZE ExtendedBiosSize; -} SMBIOS_TABLE_TYPE0; -``` - -In this structure `SMBIOS_STRUCTURE Hdr` is a mandatory field that is the same as `EFI_SMBIOS_TABLE_HEADER` that we receive from our protocol function call. - -Also `SMBIOS_TABLE_STRING` is just an UINT8 value that defines a string number in an ASCII string array that is placed directly after the structure. - -``` -/// -/// Text strings associated with a given SMBIOS structure are returned in the dmiStrucBuffer, appended directly after -/// the formatted portion of the structure. This method of returning string information eliminates the need for -/// application software to deal with pointers embedded in the SMBIOS structure. Each string is terminated with a null -/// (00h) BYTE and the set of strings is terminated with an additional null (00h) BYTE. When the formatted portion of -/// a SMBIOS structure references a string, it does so by specifying a non-zero string number within the structure's -/// string-set. For example, if a string field contains 02h, it references the second string following the formatted portion -/// of the SMBIOS structure. If a string field references no string, a null (0) is placed in that string field. 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. -/// -typedef UINT8 SMBIOS_TABLE_STRING; -``` - -So let's write a simple function that returns actual ASCII string from a `EFI_SMBIOS_TABLE_HEADER*` and a string number: -``` -CHAR8* GetRecordString(EFI_SMBIOS_TABLE_HEADER* Record, UINTN number) -{ - if (!number) - return ""; - - CHAR8* String = (CHAR8*)Record + Record->Length; - UINTN i=1; - while (i < number) { - String = String + AsciiStrSize(String); - i++; - } - return String; -} -``` -Here we've used `AsciiStrSize` function that is defined in https://github.com/tianocore/edk2/blob/master/MdePkg/Library/BaseLib/String.c file. -``` -/** - Returns the size of a Null-terminated ASCII string in bytes, including the - Null terminator. - This function returns the size, in bytes, of the Null-terminated ASCII string - specified by String. - If String is NULL, then ASSERT(). - If PcdMaximumAsciiStringLength is not zero and String contains more than - PcdMaximumAsciiStringLength ASCII characters, not including the Null-terminator, - then ASSERT(). - @param String A pointer to a Null-terminated ASCII string. - @return The size of String. -**/ -UINTN -EFIAPI -AsciiStrSize ( - IN CONST CHAR8 *String - ) -``` - -Now we have everything to write actual parsing code in our `while` loop: - -``` -while (!EFI_ERROR(Status)) { - Print (L"SMBIOS Type %d \n", Record->Type); - switch (Record->Type) { - case EFI_SMBIOS_TYPE_BIOS_INFORMATION: { - SMBIOS_TABLE_TYPE0* Type0Record = (SMBIOS_TABLE_TYPE0*) Record; - Print(L"\tVendor=%a\n", GetRecordString(Record, Type0Record->Vendor)); - Print(L"\tBiosVersion=%a\n", GetRecordString(Record, Type0Record->BiosVersion)); - Print(L"\tBiosReleaseDate=%a\n", GetRecordString(Record, Type0Record->BiosReleaseDate)); - Print(L"\tBiosSegment=0x%x\n", Type0Record->BiosSegment); - Print(L"\tSystemBiosMajorRelease=0x%x\n", Type0Record->SystemBiosMajorRelease); - Print(L"\tSystemBiosMinorRelease=0x%x\n", Type0Record->SystemBiosMinorRelease); - break; - } - default: - Print(L"\tTODO: Parsing for this table is not ready yet\n"); - break; - } - Status = SmbiosProtocol->GetNext(SmbiosProtocol, - &SmbiosHandle, - NULL, - &Record, - NULL); -} -``` -To print ASCII strings here we've used `%a` format code (https://github.com/tianocore/edk/blob/master/Foundation/Library/Pei/PeiLib/Print/Print.c). - - -If you build and execute our app under OVMF you would get: -``` -FS0:\> SmbiosInfo.efi -SMBIOS table is placed at 7941000 - -SMBIOS Type 1 - TODO: Parsing for this table is not ready yet -SMBIOS Type 3 - TODO: Parsing for this table is not ready yet -SMBIOS Type 4 - TODO: Parsing for this table is not ready yet -SMBIOS Type 16 - TODO: Parsing for this table is not ready yet -SMBIOS Type 17 - TODO: Parsing for this table is not ready yet -SMBIOS Type 19 - TODO: Parsing for this table is not ready yet -SMBIOS Type 32 - TODO: Parsing for this table is not ready yet -SMBIOS Type 0 - Vendor=EFI Development Kit II / OVMF - BiosVersion=0.0.0 - BiosReleaseDate=02/06/2015 - BiosSegment=0xE800 - SystemBiosMajorRelease=0x0 - SystemBiosMinorRelease=0x0 -``` - -If you look closely at `dmem` dump from earlier, you'll see that these are the exact strings that were actually present in memory. - -We can easily to add code to parse other SMBIOS tables. - -For example here is some parsing code for table type 1 structure: -``` -case EFI_SMBIOS_TYPE_SYSTEM_INFORMATION: { - SMBIOS_TABLE_TYPE1* Type1Record = (SMBIOS_TABLE_TYPE1*) Record; - Print(L"\tManufacturer=%a\n", GetRecordString(Record, Type1Record->Manufacturer)); - Print(L"\tProductName=%a\n", GetRecordString(Record, Type1Record->ProductName)); - Print(L"\tVersion=%a\n", GetRecordString(Record, Type1Record->Version)); - Print(L"\tSerialNumber=%a\n", GetRecordString(Record, Type1Record->SerialNumber)); - Print(L"\tUUID=%g\n", Type1Record->Uuid); - Print(L"\tWakeUpType=%d\n", Type1Record->WakeUpType); - Print(L"\tSKUNumber=%a\n", GetRecordString(Record, Type1Record->SKUNumber)); - Print(L"\tFamily=%a\n", GetRecordString(Record, Type1Record->Family)); - break; -} -``` -Structure itself is: -``` -typedef struct { - SMBIOS_STRUCTURE Hdr; - SMBIOS_TABLE_STRING Manufacturer; - SMBIOS_TABLE_STRING ProductName; - SMBIOS_TABLE_STRING Version; - SMBIOS_TABLE_STRING SerialNumber; - GUID Uuid; - UINT8 WakeUpType; ///< The enumeration value from MISC_SYSTEM_WAKEUP_TYPE. - SMBIOS_TABLE_STRING SKUNumber; - SMBIOS_TABLE_STRING Family; -} SMBIOS_TABLE_TYPE1; -``` - -Build and execute: -``` -FS0:\> SmbiosInfo.efi -SMBIOS table is placed at 7941000 - -SMBIOS Type 1 - Manufacturer=QEMU - ProductName=Standard PC (i440FX + PIIX, 1996) - Version=pc-i440fx-focal - SerialNumber= - UUID=00000000-0000-0000-0000-000000000000 - WakeUpType=6 - SKUNumber= - Family= -SMBIOS Type 3 - TODO: Parsing for this table is not ready yet -SMBIOS Type 4 - TODO: Parsing for this table is not ready yet -SMBIOS Type 16 - TODO: Parsing for this table is not ready yet -SMBIOS Type 17 - TODO: Parsing for this table is not ready yet -SMBIOS Type 19 - TODO: Parsing for this table is not ready yet -SMBIOS Type 32 - TODO: Parsing for this table is not ready yet -SMBIOS Type 0 - Vendor=EFI Development Kit II / OVMF - BiosVersion=0.0.0 - BiosReleaseDate=02/06/2015 - BiosSegment=0xE800 - SystemBiosMajorRelease=0x0 - SystemBiosMinorRelease=0x0 -``` - -As you remember the same information that is present in these SMBIOS tables is present in the main BIOS menu: - -![BIOS_menu](BIOS_menu.png?raw=true "BIOS_menu") - -And in case you wonder where OVMF defines all these information for its SMBIOS structures, checkout https://github.com/tianocore/edk2/blob/master/OvmfPkg/SmbiosPlatformDxe/SmbiosPlatformDxe.c and implementation of a `EFI_SMBIOS_PROTOCOL` is placed here https://github.com/tianocore/edk2/blob/master/MdeModulePkg/Universal/SmbiosDxe/SmbiosDxe.c - -# `smbiosview` command - -We can use `EFI_SMBIOS_PROTOCOL` to parse SMBIOS table information, but actually if you just want to see SMBIOS information there is a better option. - -UEFI shell has a `smbiosview` command that does exactly what we need. - -You can checkout sources for this command here: https://github.com/tianocore/edk2/tree/master/ShellPkg/Library/UefiShellDebug1CommandsLib/SmbiosView - -First checkout help for this command: -``` -FS0:\> smbiosview -? -Displays SMBIOS information. - -SMBIOSVIEW [-t SmbiosType]|[-h SmbiosHandle]|[-s]|[-a] - - -t - Displays all structures of SmbiosType. - -h - Displays structure of SmbiosHandle. - -s - Displays a statistics table. - -a - Displays all information. - SmbiosType - Specifies a SMBIOS structure type. - SmbiosHandle - Specifies a SMBIOS structure unique 16-bit handle. - -NOTES: - 1. The SmbiosType parameter supports the following types: - 0 - BIOS Information - 1 - System Information - 2 - Baseboard Information - 3 - System Enclosure - 4 - Processor Information - 5 - Memory Controller Information - 6 - Memory Module Information - 7 - Cache Information - 8 - Port Connector Information - 9 - System Slots - 10 - On Board Devices Information - 11 - OEM Strings - 12 - System Configuration Options - 13 - BIOS Language Information - 14 - Group Associations - 15 - System Event Log - 16 - Physical Memory Array - 17 - Memory Device - 18 - 32-bit Memory Error Information - 19 - Memory Array Mapped Address - 20 - Memory Device Mapped Address - 21 - Built-in Pointing Device - 22 - Portable Battery - 23 - System Reset - 24 - Hardware Security - 25 - System Power Controls - 26 - Voltage Probe - 27 - Cooling Device - 28 - Temperature Probe - 29 - Electrical Current Probe - 30 - Out-Of-Band Remote Access - 31 - Boot Integrity Services (BIS) Entry Point - 32 - System Boot Information - 33 - 64-Bit Memory Error Information - 34 - Management Device - 35 - Management Device Component - 36 - Management Device Threshold Data - 37 - Memory Channel - 38 - IPMI Device Information - 39 - System Power Supply - 40 - Additional Information - 41 - Onboard Devices Extended Information - 42 - Management Controller Host Interface - 43 - TPM Device - 44 - Processor Additional Information - 2. Enter the SmbiosHandle parameter in hexadecimal format. - Do not use the '0x' prefix format for hexadecimal values. - 3. Internal commands: - :q -------- quit smbiosview - :0 -------- Change smbiosview display NONE info - :1 -------- Change smbiosview display OUTLINE info - :2 -------- Change smbiosview display NORMAL info - :3 -------- Change smbiosview display DETAIL info - /? -------- Show help -``` - -Try to dump one of the structures that we've tried to parse manually: -``` -FS0:\> smbiosview -t 0 -SMBIOS Entry Point Structure: -Anchor String: _SM_ -EPS Checksum: 0x26 -Entry Point Len: 31 -Version: 2.8 -Number of Structures: 9 -Max Struct size: 83 -Table Address: 0x7940000 -Table Length: 401 -Entry Point revision: 0x0 -SMBIOS BCD Revision: 0x28 -Inter Anchor: _DMI_ -Inter Checksum: 0xA -Formatted Area: - 00000000: 00 00 00 00 00 *.....* - -========================================================= -Query Structure, conditions are: -QueryType = 0 -QueryHandle = Random -ShowType = SHOW_DETAIL - - -========================================================= -Type=0, Handle=0x0 -Dump Structure as: -Index=7,Length=0x4A,Addr=0x7940141 -00000000: 00 1A 00 00 01 02 00 E8-03 00 08 00 00 00 00 00 *................* -FS0:\> 0: 00 00 00 1C 00 00 FF FF-00 00 45 46 49 20 44 65 *..........EFI De* -00000020: 76 65 6C 6F 70 6D 65 6E-74 20 4B 69 74 20 49 49 *velopment Kit II* -00000030: 20 2F 20 4F 56 4D 46 00-30 2E 30 2E 30 00 30 32 * / OVMF.0.0.0.02* -00000040: 2F 30 36 2F 32 30 31 35-00 00 */06/2015..* -Structure Type: BIOS Information -Format part Len : 26 -Structure Handle: 0 -Vendor: EFI Development Kit II / OVMF -BiosVersion: 0.0.0 -BiosSegment: 0xE800 -BiosReleaseDate: 02/06/2015 -BiosSize: 64 KB -BIOS Characteristics: -BIOS Characteristics Not Supported - Bits 32:47 are reserved for BIOS Vendor - Bits 48:64 are reserved for System Vendor -BIOS Characteristics Extension Byte1: -BIOS Characteristics Extension Byte2: -Enable Targeted Content Distribution -UEFI Specification is supported -The SMBIOS table describes a virtual machine - Bits 5:7 are reserved for future assignment -SystemBiosMajorRelease: 0 -SystemBiosMinorRelease: 0 -EmbeddedControllerFirmwareMajorRelease: 255 -EmbeddedControllerFirmwareMinorRelease: 255 -``` -As you can see it is all the same info that we've received using `EFI_SMBIOS_PROTOCOL`. - -You can use this command to see what is inside all of the SMBIOS structures using: -``` -FS0:\> smbiosview -b -... -``` - -The output is too big to paste here, so check it out yourself! diff --git a/Lesson_27/SMBIOS_entry_structure.png b/Lesson_27/SMBIOS_entry_structure.png Binary files differdeleted file mode 100644 index f488425..0000000 --- a/Lesson_27/SMBIOS_entry_structure.png +++ /dev/null diff --git a/Lesson_27/SMBIOS_entry_structure_dump.png b/Lesson_27/SMBIOS_entry_structure_dump.png Binary files differdeleted file mode 100644 index ff27b9b..0000000 --- a/Lesson_27/SMBIOS_entry_structure_dump.png +++ /dev/null diff --git a/Lesson_27/UefiLessonsPkg/SmbiosInfo/SmbiosInfo.c b/Lesson_27/UefiLessonsPkg/SmbiosInfo/SmbiosInfo.c deleted file mode 100644 index b75026d..0000000 --- a/Lesson_27/UefiLessonsPkg/SmbiosInfo/SmbiosInfo.c +++ /dev/null @@ -1,88 +0,0 @@ -#include <Library/UefiBootServicesTableLib.h> -#include <Library/UefiLib.h> - -#include <Library/BaseMemoryLib.h> -#include <Protocol/Smbios.h> - -CHAR8* GetRecordString(EFI_SMBIOS_TABLE_HEADER* Record, UINTN number) -{ - if (!number) - return ""; - - CHAR8* String = (CHAR8*)Record + Record->Length; - UINTN i=1; - while (i < number) { - String = String + AsciiStrSize(String); - i++; - } - return String; -} - -EFI_STATUS -EFIAPI -UefiMain ( - IN EFI_HANDLE ImageHandle, - IN EFI_SYSTEM_TABLE *SystemTable - ) -{ - for (UINTN i=0; i<SystemTable->NumberOfTableEntries; i++) { - if (CompareGuid(&(SystemTable->ConfigurationTable[i].VendorGuid), &gEfiSmbiosTableGuid)) { - Print(L"SMBIOS table is placed at %p\n\n", SystemTable->ConfigurationTable[i].VendorTable); - } - } - - EFI_SMBIOS_PROTOCOL* SmbiosProtocol; - EFI_STATUS Status = gBS->LocateProtocol ( - &gEfiSmbiosProtocolGuid, - NULL, - (VOID**)&SmbiosProtocol - ); - if (EFI_ERROR (Status)) { - return Status; - } - - EFI_SMBIOS_HANDLE SmbiosHandle = SMBIOS_HANDLE_PI_RESERVED; - EFI_SMBIOS_TABLE_HEADER* Record; - Status = SmbiosProtocol->GetNext(SmbiosProtocol, - &SmbiosHandle, - NULL, - &Record, - NULL); - while (!EFI_ERROR(Status)) { - Print (L"SMBIOS Type %d \n", Record->Type); - switch (Record->Type) { - case EFI_SMBIOS_TYPE_BIOS_INFORMATION: { - SMBIOS_TABLE_TYPE0* Type0Record = (SMBIOS_TABLE_TYPE0*) Record; - Print(L"\tVendor=%a\n", GetRecordString(Record, Type0Record->Vendor)); - Print(L"\tBiosVersion=%a\n", GetRecordString(Record, Type0Record->BiosVersion)); - Print(L"\tBiosReleaseDate=%a\n", GetRecordString(Record, Type0Record->BiosReleaseDate)); - Print(L"\tBiosSegment=0x%x\n", Type0Record->BiosSegment); - Print(L"\tSystemBiosMajorRelease=0x%x\n", Type0Record->SystemBiosMajorRelease); - Print(L"\tSystemBiosMinorRelease=0x%x\n", Type0Record->SystemBiosMinorRelease); - break; - } - case EFI_SMBIOS_TYPE_SYSTEM_INFORMATION: { - SMBIOS_TABLE_TYPE1* Type1Record = (SMBIOS_TABLE_TYPE1*) Record; - Print(L"\tManufacturer=%a\n", GetRecordString(Record, Type1Record->Manufacturer)); - Print(L"\tProductName=%a\n", GetRecordString(Record, Type1Record->ProductName)); - Print(L"\tVersion=%a\n", GetRecordString(Record, Type1Record->Version)); - Print(L"\tSerialNumber=%a\n", GetRecordString(Record, Type1Record->SerialNumber)); - Print(L"\tUUID=%g\n", Type1Record->Uuid); - Print(L"\tWakeUpType=%d\n", Type1Record->WakeUpType); - Print(L"\tSKUNumber=%a\n", GetRecordString(Record, Type1Record->SKUNumber)); - Print(L"\tFamily=%a\n", GetRecordString(Record, Type1Record->Family)); - break; - } - default: - Print(L"\tTODO: Parsing for this table is not ready yet\n"); - break; - } - Status = SmbiosProtocol->GetNext(SmbiosProtocol, - &SmbiosHandle, - NULL, - &Record, - NULL); - } - - return EFI_SUCCESS; -} diff --git a/Lesson_27/UefiLessonsPkg/SmbiosInfo/SmbiosInfo.inf b/Lesson_27/UefiLessonsPkg/SmbiosInfo/SmbiosInfo.inf deleted file mode 100644 index ab6013a..0000000 --- a/Lesson_27/UefiLessonsPkg/SmbiosInfo/SmbiosInfo.inf +++ /dev/null @@ -1,24 +0,0 @@ -[Defines] - INF_VERSION = 1.25 - BASE_NAME = SmbiosInfo - FILE_GUID = 4a8836db-9e1d-4b7d-a785-f552340fba59 - MODULE_TYPE = UEFI_APPLICATION - VERSION_STRING = 1.0 - ENTRY_POINT = UefiMain - -[Sources] - SmbiosInfo.c - -[Packages] - MdePkg/MdePkg.dec - -[LibraryClasses] - UefiApplicationEntryPoint - UefiLib - -[Guids] - gEfiSmbiosTableGuid - -[Protocols] - gEfiSmbiosProtocolGuid - |