/*++ | |
Copyright (c) 2006 - 2007, Intel Corporation | |
All rights reserved. This program and the accompanying materials | |
are licensed and made available under the terms and conditions of the BSD License | |
which accompanies this distribution. The full text of the license may be found at | |
http://opensource.org/licenses/bsd-license.php | |
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, | |
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. | |
Module Name: | |
MiscSubclassDriverEntryPoint.c | |
Abstract: | |
This driver parses the mMiscSubclassDataTable structure and reports | |
any generated data to the DataHub. | |
--*/ | |
#include "MiscSubclassDriver.h" | |
extern UINT8 MiscSubclassStrings[]; | |
// | |
// | |
// | |
EFI_STATUS | |
LogRecordDataToDataHub ( | |
EFI_DATA_HUB_PROTOCOL *DataHub, | |
UINT32 RecordType, | |
UINT32 RecordLen, | |
VOID *RecordData | |
) | |
/*++ | |
Description: | |
Parameters: | |
DataHub | |
%%TBD | |
RecordType | |
%%TBD | |
RecordLen | |
%%TBD | |
RecordData | |
%%TBD | |
Returns: | |
EFI_INVALID_PARAMETER | |
EFI_SUCCESS | |
Other Data Hub errors | |
--*/ | |
{ | |
EFI_MISC_SUBCLASS_DRIVER_DATA MiscSubclass; | |
EFI_STATUS Status; | |
// | |
// Do nothing if data parameters are not valid. | |
// | |
if (RecordLen == 0 || RecordData == NULL) { | |
DEBUG ( | |
(EFI_D_ERROR, | |
"RecordLen == %d RecordData == %xh\n", | |
RecordLen, | |
RecordData) | |
); | |
return EFI_INVALID_PARAMETER; | |
} | |
// | |
// Assemble Data Hub record. | |
// | |
MiscSubclass.Header.Version = EFI_MISC_SUBCLASS_VERSION; | |
MiscSubclass.Header.HeaderSize = sizeof (EFI_SUBCLASS_TYPE1_HEADER); | |
MiscSubclass.Header.Instance = 1; | |
MiscSubclass.Header.SubInstance = 1; | |
MiscSubclass.Header.RecordType = RecordType; | |
CopyMem ( | |
&MiscSubclass.Record, | |
RecordData, | |
RecordLen | |
); | |
// | |
// Log Data Hub record. | |
// | |
Status = DataHub->LogData ( | |
DataHub, | |
&gEfiMiscSubClassGuid, | |
&gEfiMiscSubClassGuid, | |
EFI_DATA_RECORD_CLASS_DATA, | |
&MiscSubclass, | |
sizeof (EFI_SUBCLASS_TYPE1_HEADER) + RecordLen | |
); | |
if (EFI_ERROR (Status)) { | |
DEBUG ( | |
(EFI_D_ERROR, | |
"LogData(%d bytes) == %r\n", | |
sizeof (EFI_SUBCLASS_TYPE1_HEADER) + RecordLen, | |
Status) | |
); | |
} | |
return Status; | |
} | |
EFI_STATUS | |
EFIAPI | |
MiscSubclassDriverEntryPoint ( | |
IN EFI_HANDLE ImageHandle, | |
IN EFI_SYSTEM_TABLE *SystemTable | |
) | |
/*++ | |
Description: | |
Standard EFI driver point. This driver parses the mMiscSubclassDataTable | |
structure and reports any generated data to the DataHub. | |
Arguments: | |
ImageHandle | |
Handle for the image of this driver | |
SystemTable | |
Pointer to the EFI System Table | |
Returns: | |
EFI_SUCCESS | |
The data was successfully reported to the Data Hub. | |
--*/ | |
{ | |
EFI_MISC_SUBCLASS_DRIVER_DATA RecordData; | |
EFI_DATA_HUB_PROTOCOL *DataHub; | |
EFI_HII_PROTOCOL *Hii; | |
EFI_HII_PACKAGES *PackageList; | |
EFI_HII_HANDLE HiiHandle; | |
EFI_STATUS Status; | |
UINTN Index; | |
BOOLEAN LogRecordData; | |
EFI_MEMORY_SUBCLASS_DRIVER_DATA MemorySubClassData; | |
UINT64 TotalMemorySize; | |
CHAR16 *Nt32MemString; | |
// | |
// Initialize constant portion of subclass header. | |
// | |
RecordData.Header.Version = EFI_MISC_SUBCLASS_VERSION; | |
RecordData.Header.HeaderSize = sizeof (EFI_SUBCLASS_TYPE1_HEADER); | |
RecordData.Header.Instance = 1; | |
RecordData.Header.SubInstance = 1; | |
// | |
// Locate data hub protocol. | |
// | |
Status = gBS->LocateProtocol (&gEfiDataHubProtocolGuid, NULL, &DataHub); | |
if (EFI_ERROR (Status)) { | |
DEBUG ((EFI_D_ERROR, "Could not locate DataHub protocol. %r\n", Status)); | |
return Status; | |
} else if (DataHub == NULL) { | |
DEBUG ((EFI_D_ERROR, "LocateProtocol(DataHub) returned NULL pointer!\n")); | |
return EFI_DEVICE_ERROR; | |
} | |
// | |
// Locate hii protocol. | |
// | |
Status = gBS->LocateProtocol (&gEfiHiiProtocolGuid, NULL, &Hii); | |
if (EFI_ERROR (Status)) { | |
DEBUG ((EFI_D_ERROR, "Could not locate Hii protocol. %r\n", Status)); | |
return Status; | |
} else if (Hii == NULL) { | |
DEBUG ((EFI_D_ERROR, "LocateProtocol(Hii) returned NULL pointer!\n")); | |
return EFI_DEVICE_ERROR; | |
} | |
// | |
// Add our default strings to the HII database. They will be modified later. | |
// | |
PackageList = PreparePackages (1, &gEfiMiscSubClassGuid, MiscSubclassStrings); | |
Status = Hii->NewPack (Hii, PackageList, &HiiHandle); | |
FreePool (PackageList); | |
if (EFI_ERROR (Status)) { | |
DEBUG ((EFI_D_ERROR, "Could not log default strings to Hii. %r\n", Status)); | |
return Status; | |
} | |
// | |
// | |
// | |
for (Index = 0; Index < mMiscSubclassDataTableEntries; ++Index) { | |
// | |
// Stupidity check! Do nothing if RecordLen is zero. | |
// %%TBD - Should this be an error or a mechanism for ignoring | |
// records in the Data Table? | |
// | |
if (mMiscSubclassDataTable[Index].RecordLen == 0) { | |
DEBUG ( | |
(EFI_D_ERROR, | |
"mMiscSubclassDataTable[%d].RecordLen == 0\n", | |
Index) | |
); | |
continue; | |
} | |
// | |
// Initialize per-record portion of subclass header and | |
// copy static data into data portion of subclass record. | |
// | |
RecordData.Header.RecordType = mMiscSubclassDataTable[Index].RecordType; | |
if (mMiscSubclassDataTable[Index].RecordData == NULL) { | |
ZeroMem ( | |
&RecordData.Record, | |
mMiscSubclassDataTable[Index].RecordLen | |
); | |
} else { | |
CopyMem ( | |
&RecordData.Record, | |
mMiscSubclassDataTable[Index].RecordData, | |
mMiscSubclassDataTable[Index].RecordLen | |
); | |
} | |
// | |
// If the entry does not have a function pointer, just log the data. | |
// | |
if (mMiscSubclassDataTable[Index].Function == NULL) { | |
// | |
// Log RecordData to Data Hub. | |
// | |
Status = DataHub->LogData ( | |
DataHub, | |
&gEfiMiscSubClassGuid, | |
&gEfiMiscSubClassGuid, | |
EFI_DATA_RECORD_CLASS_DATA, | |
&RecordData, | |
sizeof (EFI_SUBCLASS_TYPE1_HEADER) + mMiscSubclassDataTable[Index].RecordLen | |
); | |
if (EFI_ERROR (Status)) { | |
DEBUG ( | |
(EFI_D_ERROR, | |
"LogData(%d bytes) == %r\n", | |
sizeof (EFI_SUBCLASS_TYPE1_HEADER) + mMiscSubclassDataTable[Index].RecordLen, | |
Status) | |
); | |
} | |
continue; | |
} | |
// | |
// The entry has a valid function pointer. | |
// Keep calling the function and logging data until there | |
// is no more data to log. | |
// | |
for (;;) { | |
Status = (*mMiscSubclassDataTable[Index].Function)(mMiscSubclassDataTable[Index].RecordType, &mMiscSubclassDataTable[Index].RecordLen, &RecordData.Record, &LogRecordData); | |
if (EFI_ERROR (Status)) { | |
break; | |
} | |
if (!LogRecordData) { | |
break; | |
} | |
Status = DataHub->LogData ( | |
DataHub, | |
&gEfiMiscSubClassGuid, | |
&gEfiMiscSubClassGuid, | |
EFI_DATA_RECORD_CLASS_DATA, | |
&RecordData, | |
sizeof (EFI_SUBCLASS_TYPE1_HEADER) + mMiscSubclassDataTable[Index].RecordLen | |
); | |
if (EFI_ERROR (Status)) { | |
DEBUG ( | |
(EFI_D_ERROR, | |
"LogData(%d bytes) == %r\n", | |
sizeof (EFI_SUBCLASS_TYPE1_HEADER) + mMiscSubclassDataTable[Index].RecordLen, | |
Status) | |
); | |
} | |
} | |
} | |
// | |
// Log Memory Size info based on PCD setting. | |
// | |
MemorySubClassData.Header.Instance = 1; | |
MemorySubClassData.Header.SubInstance = EFI_SUBCLASS_INSTANCE_NON_APPLICABLE; | |
MemorySubClassData.Header.RecordType = EFI_MEMORY_ARRAY_START_ADDRESS_RECORD_NUMBER; | |
// | |
// Process Memory String in form size!size ... | |
// So 64!64 is 128 MB | |
// | |
Nt32MemString = PcdGetPtr (PcdWinNtMemorySize); | |
for (TotalMemorySize = 0; *Nt32MemString != '\0';) { | |
TotalMemorySize += StrDecimalToUint64 (Nt32MemString); | |
while (*Nt32MemString != '\0') { | |
if (*Nt32MemString == '!') { | |
Nt32MemString++; | |
break; | |
} | |
Nt32MemString++; | |
} | |
} | |
MemorySubClassData.Record.ArrayStartAddress.MemoryArrayStartAddress = 0; | |
MemorySubClassData.Record.ArrayStartAddress.MemoryArrayEndAddress = LShiftU64 (TotalMemorySize, 20) - 1; | |
MemorySubClassData.Record.ArrayStartAddress.PhysicalMemoryArrayLink.ProducerName = gEfiMemoryProducerGuid; | |
MemorySubClassData.Record.ArrayStartAddress.PhysicalMemoryArrayLink.Instance = 1; | |
MemorySubClassData.Record.ArrayStartAddress.PhysicalMemoryArrayLink.SubInstance = EFI_SUBCLASS_INSTANCE_NON_APPLICABLE; | |
MemorySubClassData.Record.ArrayStartAddress.MemoryArrayPartitionWidth = 0; | |
// | |
// Store memory size data record to data hub. | |
// | |
Status = DataHub->LogData ( | |
DataHub, | |
&gEfiMemorySubClassGuid, | |
&gEfiMemoryProducerGuid, | |
EFI_DATA_RECORD_CLASS_DATA, | |
&MemorySubClassData, | |
sizeof (EFI_SUBCLASS_TYPE1_HEADER) + sizeof (EFI_MEMORY_ARRAY_START_ADDRESS_DATA) | |
); | |
return EFI_SUCCESS; | |
} | |