Unix version of EFI emulator
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@2182 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
@ -0,0 +1,518 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) 2006, 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[];
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
UnixIoProtocolNotifyFunction (
|
||||
IN EFI_EVENT Event,
|
||||
IN VOID *Context
|
||||
);
|
||||
|
||||
//
|
||||
//
|
||||
//
|
||||
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 EfiStatus;
|
||||
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
EfiStatus = DataHub->LogData (
|
||||
DataHub,
|
||||
&gEfiMiscSubClassGuid,
|
||||
&gEfiMiscSubClassGuid,
|
||||
EFI_DATA_RECORD_CLASS_DATA,
|
||||
&MiscSubclass,
|
||||
sizeof (EFI_SUBCLASS_TYPE1_HEADER) + RecordLen
|
||||
);
|
||||
|
||||
if (EFI_ERROR (EfiStatus)) {
|
||||
DEBUG (
|
||||
(EFI_D_ERROR,
|
||||
"LogData(%d bytes) == %r\n",
|
||||
sizeof (EFI_SUBCLASS_TYPE1_HEADER) + RecordLen,
|
||||
EfiStatus)
|
||||
);
|
||||
}
|
||||
|
||||
return EfiStatus;
|
||||
}
|
||||
|
||||
|
||||
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 EfiStatus;
|
||||
UINTN Index;
|
||||
BOOLEAN LogRecordData;
|
||||
EFI_EVENT Event;
|
||||
VOID *Registration;
|
||||
|
||||
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
EfiStatus = gBS->LocateProtocol (&gEfiDataHubProtocolGuid, NULL, &DataHub);
|
||||
|
||||
if (EFI_ERROR (EfiStatus)) {
|
||||
DEBUG ((EFI_D_ERROR, "Could not locate DataHub protocol. %r\n", EfiStatus));
|
||||
return EfiStatus;
|
||||
} else if (DataHub == NULL) {
|
||||
DEBUG ((EFI_D_ERROR, "LocateProtocol(DataHub) returned NULL pointer!\n"));
|
||||
return EFI_DEVICE_ERROR;
|
||||
}
|
||||
//
|
||||
// Locate hii protocol.
|
||||
//
|
||||
EfiStatus = gBS->LocateProtocol (&gEfiHiiProtocolGuid, NULL, &Hii);
|
||||
|
||||
if (EFI_ERROR (EfiStatus)) {
|
||||
DEBUG ((EFI_D_ERROR, "Could not locate Hii protocol. %r\n", EfiStatus));
|
||||
return EfiStatus;
|
||||
} 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);
|
||||
EfiStatus = Hii->NewPack (Hii, PackageList, &HiiHandle);
|
||||
gBS->FreePool (PackageList);
|
||||
|
||||
if (EFI_ERROR (EfiStatus)) {
|
||||
DEBUG ((EFI_D_ERROR, "Could not log default strings to Hii. %r\n", EfiStatus));
|
||||
return EfiStatus;
|
||||
}
|
||||
//
|
||||
//
|
||||
//
|
||||
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.
|
||||
//
|
||||
EfiStatus = DataHub->LogData (
|
||||
DataHub,
|
||||
&gEfiMiscSubClassGuid,
|
||||
&gEfiMiscSubClassGuid,
|
||||
EFI_DATA_RECORD_CLASS_DATA,
|
||||
&RecordData,
|
||||
sizeof (EFI_SUBCLASS_TYPE1_HEADER) + mMiscSubclassDataTable[Index].RecordLen
|
||||
);
|
||||
|
||||
if (EFI_ERROR (EfiStatus)) {
|
||||
DEBUG (
|
||||
(EFI_D_ERROR,
|
||||
"LogData(%d bytes) == %r\n",
|
||||
sizeof (EFI_SUBCLASS_TYPE1_HEADER) + mMiscSubclassDataTable[Index].RecordLen,
|
||||
EfiStatus)
|
||||
);
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
//
|
||||
// The entry has a valid function pointer.
|
||||
// Keep calling the function and logging data until there
|
||||
// is no more data to log.
|
||||
//
|
||||
for (;;) {
|
||||
//
|
||||
//
|
||||
//
|
||||
EfiStatus = (*mMiscSubclassDataTable[Index].Function)
|
||||
(
|
||||
mMiscSubclassDataTable[Index].RecordType, &mMiscSubclassDataTable[Index].RecordLen, &RecordData.Record, &
|
||||
LogRecordData
|
||||
);
|
||||
|
||||
//
|
||||
//
|
||||
//
|
||||
if (EFI_ERROR (EfiStatus)) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (!LogRecordData) {
|
||||
break;
|
||||
}
|
||||
//
|
||||
//
|
||||
//
|
||||
EfiStatus = DataHub->LogData (
|
||||
DataHub,
|
||||
&gEfiMiscSubClassGuid,
|
||||
&gEfiMiscSubClassGuid,
|
||||
EFI_DATA_RECORD_CLASS_DATA,
|
||||
&RecordData,
|
||||
sizeof (EFI_SUBCLASS_TYPE1_HEADER) + mMiscSubclassDataTable[Index].RecordLen
|
||||
);
|
||||
|
||||
if (EFI_ERROR (EfiStatus)) {
|
||||
DEBUG (
|
||||
(EFI_D_ERROR,
|
||||
"LogData(%d bytes) == %r\n",
|
||||
sizeof (EFI_SUBCLASS_TYPE1_HEADER) + mMiscSubclassDataTable[Index].RecordLen,
|
||||
EfiStatus)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
//
|
||||
// Install notify function to fetch memory data through UnixIo protocol and store to data hub.
|
||||
//
|
||||
EfiStatus = gBS->CreateEvent (
|
||||
EFI_EVENT_NOTIFY_SIGNAL,
|
||||
EFI_TPL_CALLBACK,
|
||||
UnixIoProtocolNotifyFunction,
|
||||
ImageHandle,
|
||||
&Event
|
||||
);
|
||||
ASSERT (!EFI_ERROR (EfiStatus));
|
||||
|
||||
EfiStatus = gBS->RegisterProtocolNotify (
|
||||
&gEfiUnixIoProtocolGuid,
|
||||
Event,
|
||||
&Registration
|
||||
);
|
||||
ASSERT (!EFI_ERROR (EfiStatus));
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
UINTN
|
||||
Atoi (
|
||||
CHAR16 *String
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
Convert a unicode string to a UINTN
|
||||
|
||||
Arguments:
|
||||
String - Unicode string.
|
||||
|
||||
Returns:
|
||||
UINTN of the number represented by String.
|
||||
|
||||
--*/
|
||||
{
|
||||
UINTN Number;
|
||||
CHAR16 *Str;
|
||||
|
||||
//
|
||||
// skip preceeding white space
|
||||
//
|
||||
Str = String;
|
||||
while ((*Str) && (*Str == ' ' || *Str == '"')) {
|
||||
Str++;
|
||||
}
|
||||
//
|
||||
// Convert ot a Number
|
||||
//
|
||||
Number = 0;
|
||||
while (*Str != '\0') {
|
||||
if ((*Str >= '0') && (*Str <= '9')) {
|
||||
Number = (Number * 10) +*Str - '0';
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
|
||||
Str++;
|
||||
}
|
||||
|
||||
return Number;
|
||||
}
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
UnixIoProtocolNotifyFunction (
|
||||
IN EFI_EVENT Event,
|
||||
IN VOID *Context
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
This function will log memory size data to data hub.
|
||||
|
||||
Arguments:
|
||||
Event - Event whose notification function is being invoked.
|
||||
Context - Pointer to the notification function's context.
|
||||
|
||||
Returns:
|
||||
EFI_STATUS.
|
||||
|
||||
--*/
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
EFI_MEMORY_SUBCLASS_DRIVER_DATA MemorySubClassData;
|
||||
EFI_DATA_RECORD_HEADER *Record;
|
||||
EFI_SUBCLASS_TYPE1_HEADER *DataHeader;
|
||||
UINTN HandleCount;
|
||||
UINTN HandleIndex;
|
||||
UINT64 MonotonicCount;
|
||||
BOOLEAN RecordFound;
|
||||
EFI_HANDLE *HandleBuffer;
|
||||
EFI_UNIX_IO_PROTOCOL *UnixIo;
|
||||
EFI_DATA_HUB_PROTOCOL *DataHub;
|
||||
UINT64 TotalMemorySize;
|
||||
|
||||
DataHub = NULL;
|
||||
MonotonicCount = 0;
|
||||
RecordFound = FALSE;
|
||||
|
||||
//
|
||||
// Retrieve the list of all handles from the handle database.
|
||||
//
|
||||
Status = gBS->LocateHandleBuffer (
|
||||
AllHandles,
|
||||
&gEfiUnixIoProtocolGuid,
|
||||
NULL,
|
||||
&HandleCount,
|
||||
&HandleBuffer
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return ;
|
||||
}
|
||||
//
|
||||
// Locate DataHub protocol.
|
||||
//
|
||||
Status = gBS->LocateProtocol (&gEfiDataHubProtocolGuid, NULL, &DataHub);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return ;
|
||||
}
|
||||
//
|
||||
// Search the Handle array to find the meory size information.
|
||||
//
|
||||
for (HandleIndex = 0; HandleIndex < HandleCount; HandleIndex++) {
|
||||
Status = gBS->OpenProtocol (
|
||||
HandleBuffer[HandleIndex],
|
||||
&gEfiUnixIoProtocolGuid,
|
||||
&UnixIo,
|
||||
Context,
|
||||
NULL,
|
||||
EFI_OPEN_PROTOCOL_GET_PROTOCOL
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((UnixIo->UnixThunk->Signature == EFI_UNIX_THUNK_PROTOCOL_SIGNATURE) &&
|
||||
CompareGuid (UnixIo->TypeGuid, &gEfiUnixMemoryGuid)
|
||||
) {
|
||||
//
|
||||
// Check if this record has been stored in data hub.
|
||||
//
|
||||
do {
|
||||
Status = DataHub->GetNextRecord (DataHub, &MonotonicCount, NULL, &Record);
|
||||
if (Record->DataRecordClass == EFI_DATA_RECORD_CLASS_DATA) {
|
||||
DataHeader = (EFI_SUBCLASS_TYPE1_HEADER *) (Record + 1);
|
||||
if (CompareGuid (&Record->DataRecordGuid, &gEfiProcessorSubClassGuid) &&
|
||||
(DataHeader->RecordType == EFI_MEMORY_ARRAY_START_ADDRESS_RECORD_NUMBER)
|
||||
) {
|
||||
RecordFound = TRUE;
|
||||
}
|
||||
}
|
||||
} while (MonotonicCount != 0);
|
||||
|
||||
if (RecordFound) {
|
||||
RecordFound = FALSE;
|
||||
continue;
|
||||
}
|
||||
//
|
||||
// Initialize data record.
|
||||
//
|
||||
MemorySubClassData.Header.Instance = 1;
|
||||
MemorySubClassData.Header.SubInstance = EFI_SUBCLASS_INSTANCE_NON_APPLICABLE;
|
||||
MemorySubClassData.Header.RecordType = EFI_MEMORY_ARRAY_START_ADDRESS_RECORD_NUMBER;
|
||||
|
||||
TotalMemorySize = (UINT64) Atoi (UnixIo->EnvString);
|
||||
|
||||
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)
|
||||
);
|
||||
}
|
||||
|
||||
gBS->CloseProtocol (
|
||||
HandleBuffer[HandleIndex],
|
||||
&gEfiUnixIoProtocolGuid,
|
||||
Context,
|
||||
NULL
|
||||
);
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user