SMBIOS的內容在物理地址000F0000h到000FFFFFh之間,想要訪問SMBIOS,需要在32-bit 或 64-bit protected-mode之下。
在一個EFI系統中,SMBIOS Entry Point structure類似於EFI Configuration Table的布局。具體詳見smbios spec。
SMBIOS structure開始於一個4-byte header。
00h,Type,1-BYTE,指定structure的type
01h,Length,1-BYTE,指定structure formatted area的長度
02h,Handle,2-BYTE,指定其handle
之后的內容為Text Strings。
IN SMBIOS,Every string is separated by NULL byte.
在SMBIOS的entry point table中,18h定義了string的存儲位置。
Board上的設備信息均被記錄在SMBIOS table中,記錄的過程是由BIOS完成的。
SMBIOS entry point table 一般記錄在F段中,而string的信息一般記錄在E段中。
SMBIOS event log format
Event Log中的00位表示該Event Log為何type。
Trace code中如何實現SMBIOS type 15.
static EFI_SYSTEM_EVENT_LOG_TYPE_15 SystemEventLogType15Table = { 15, // Type 0x17+(2*NumOfSupportedSmbiosTypes), // Length 0x0000, // Handle or instance number (UINT16)LOCAL_EVENT_LOG_LENGTH, // Length, in bytes, of the overall // event log area, 1st byte of header // to last of data 0x0000, // offset of event log header from // access method address sizeof(EFI_GPNV_ERROR_HEADER_TYPE1), // offset of event log data from // access method address 0x03, // defines method of higher-level // software accessing table 0x01, // current status of the system event // log 0x00000001, // unique token changed every time log // changes LOCAL_EVENT_LOG_PHY_ADDR, // address associated with access // method 0x01, // identifies the format of the log // header area NumOfSupportedSmbiosTypes, // number of supported event log type // descriptors that follow 0x02 // Always 2 // SupportedEventLogTypesList[] to be added here // to build final type 15 entry };
DXE階段在dispatch每個driver時,會執行SMBIOS elog的driver。
借執行這個driver,系統會初始化SMBIOS log。
InitializeSmbiosElog()
在這個過程中,會安裝event log的protocol
mRedirSmbiosPrivate->SmbiosElog.ActivateEventLog = EfiActivateSmbiosElog; mRedirSmbiosPrivate->SmbiosElog.EraseEventLogData = EfiEraseSmbiosElogData; mRedirSmbiosPrivate->SmbiosElog.GetEventLogData = EfiGetSmbiosElogData; mRedirSmbiosPrivate->SmbiosElog.SetEventLogData = EfiSetSmbiosElogData; NewHandle = NULL; Status = EfiInstallProtocolInterface ( &NewHandle, &gEfiRedirElogProtocolGuid, EFI_NATIVE_INTERFACE, &mRedirSmbiosPrivate->SmbiosElog ); ASSERT_EFI_ERROR (Status);
在memory中,為event log分配一段空間
然后添加一個type15的SMBIOS structure,即為event log
AddSMBIOSType15Structure()
SMBIOS event log是如何記錄到一條error信息的呢?
追code的最大感觸就是code中實做部分大概占code的一般,另一半則是判斷每一段code執行的狀態是否正確。思考來也是必要的,如果發生錯誤,就可以快速定位排錯了。所以code中提供了很多記錄error的函數。
以ReportStatusCode()這個函數為例,它在PEI,DXE或是SMM等各種模式下均有對應函數。
在DXE階段,系統會對PEI傳來的HOB進行處理。Error通常以record的形式存在DataHub中。DataHub在DXE階段建立,每條record都有自己的RecordID。
CoreGetPeiProtocol(&gEfiStatusCodeRuntimeProtocolGuid,(VOID**)&gStatusCode->ReportStatusCode); if (gStatusCode->ReportStatusCode != NULL) { gRT->ReportStatusCode = gStatusCode->ReportStatusCode; }
每條record還有其type,這樣調用event log的protocol即可以抓到需要顯示的error的信息。這樣就可以在setup下顯示出來。
// // all protocols available, continue with displaying all errors // DataSize = 0xFF; Status = GenericElogProtocol->GetEventLogData( GenericElogProtocol, &ElogData[0], EfiSmSMBIOS, &DataSize, &RecordId );
最后展示一張圖,編程讀取到的SMBIOS信息: