VOID EFIAPI WinNtIoProtocolNotifyFunction ( 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_WIN_NT_IO_PROTOCOL *WinNtIo; 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, &gEfiWinNtIoProtocolGuid, 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], &gEfiWinNtIoProtocolGuid, &WinNtIo, Context, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL ); if (EFI_ERROR (Status)) { continue; } if ((WinNtIo->WinNtThunk->Signature == EFI_WIN_NT_THUNK_PROTOCOL_SIGNATURE) && EfiCompareGuid (WinNtIo->TypeGuid, &gEfiWinNtMemoryGuid) ) { // // 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 (EfiCompareGuid (&Record->DataRecordGuid, &gProcessorSubClassName) && (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 (WinNtIo->EnvString); MemorySubClassData.Record.ArrayStartAddress.MemoryArrayStartAddress = 0; MemorySubClassData.Record.ArrayStartAddress.MemoryArrayEndAddress = LShiftU64 (TotalMemorySize, 20) - 1; MemorySubClassData.Record.ArrayStartAddress.PhysicalMemoryArrayLink.ProducerName = gMemoryProducerGuid; 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, &gMemoryProducerGuid, EFI_DATA_RECORD_CLASS_DATA, &MemorySubClassData, sizeof (EFI_SUBCLASS_TYPE1_HEADER) + sizeof (EFI_MEMORY_ARRAY_START_ADDRESS) ); } gBS->CloseProtocol ( HandleBuffer[HandleIndex], &gEfiWinNtIoProtocolGuid, Context, NULL ); } }
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; #if (EFI_SPECIFICATION_VERSION >= 0x0002000A) EFI_HII_DATABASE_PROTOCOL *HiiDatabase; EFI_HII_PACKAGE_LIST_HEADER *PackageList; #else EFI_HII_PROTOCOL *Hii; EFI_HII_PACKAGES *PackageList; #endif EFI_HII_HANDLE HiiHandle; EFI_STATUS EfiStatus; UINTN Index; BOOLEAN LogRecordData; EFI_EVENT Event; VOID *Registration; // // // EfiInitializeDriverLib (ImageHandle, SystemTable); // // 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. // #if (EFI_SPECIFICATION_VERSION >= 0x0002000A) EfiStatus = gBS->LocateProtocol (&gEfiHiiDatabaseProtocolGuid, NULL, &HiiDatabase); if (EFI_ERROR (EfiStatus)) { DEBUG ((EFI_D_ERROR, "Could not locate HiiDatabase protocol. %r\n", EfiStatus)); return EfiStatus; } else if (HiiDatabase == NULL) { DEBUG ((EFI_D_ERROR, "LocateProtocol(HiiDatabase) returned NULL pointer!\n")); return EFI_DEVICE_ERROR; } // // Add our default strings to the HII database. They will be modified later. // PackageList = PreparePackageList (1, &gEfiMiscSubClassGuid, MiscSubclassStrings); EfiStatus = HiiDatabase->NewPackageList (HiiDatabase, PackageList, ImageHandle, &HiiHandle); #else 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); #endif 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) { EfiZeroMem ( &RecordData.Record, mMiscSubclassDataTable[Index].RecordLen ); } else { EfiCopyMem ( &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 WinNtIo protocol and store to data hub. // EfiStatus = gBS->CreateEvent ( EFI_EVENT_NOTIFY_SIGNAL, EFI_TPL_CALLBACK, WinNtIoProtocolNotifyFunction, ImageHandle, &Event ); ASSERT (!EFI_ERROR (EfiStatus)); EfiStatus = gBS->RegisterProtocolNotify ( &gEfiWinNtIoProtocolGuid, Event, &Registration ); ASSERT (!EFI_ERROR (EfiStatus)); return EFI_SUCCESS; }