Windows2003-3790/base/ntos/wmi/smbios.c
2020-09-30 16:53:55 +02:00

1664 lines
53 KiB
C

/*++
Copyright (c) 1997-1999 Microsoft Corporation
Module Name:
smbios.c.c
Abstract:
SMBIOS interface for WMI
Author:
AlanWar
Environment:
Kernel mode
Revision History:
--*/
#if defined(_AMD64_) || defined(_IA64_) || defined(i386)
#include "wmikmp.h"
#include "arc.h"
#include "smbios.h"
void WmipGetSMBiosFromLoaderBlock(
PVOID LoaderBlockPtr
);
NTSTATUS WmipSMBiosDataRegQueryRoutine(
IN PWSTR ValueName,
IN ULONG ValueType,
IN PVOID ValueData,
IN ULONG ValueLength,
IN PVOID Context,
IN PVOID EntryContext
);
BOOLEAN WmipIsSMBiosKey(
HANDLE ParentKeyHandle,
PWCHAR KeyName,
PUCHAR *SMBiosTableVirtualAddress,
PULONG SMBiosTableLength
);
NTSTATUS WmipSMBiosIdentifierRegQueryRoutine(
IN PWSTR ValueName,
IN ULONG ValueType,
IN PVOID ValueData,
IN ULONG ValueLength,
IN PVOID Context,
IN PVOID EntryContext
);
BOOLEAN WmipFindSMBiosEPSHeader(
PUCHAR SMBiosVirtualAddress,
ULONG BiosSize,
PSMBIOS_EPS_HEADER EPSHeader
);
NTSTATUS WmipFindSMBiosStructure(
IN UCHAR Type,
OUT PVOID *StructPtr,
OUT PVOID *MapPtr,
OUT PULONG MapSize
);
NTSTATUS WmipFindSysIdTable(
PPHYSICAL_ADDRESS SysidTablePhysicalAddress,
PUCHAR SysIdBiosRevision,
PULONG NumberEntries
);
NTSTATUS WmipParseSysIdTable(
PHYSICAL_ADDRESS PhysicalAddress,
ULONG NumberEntries,
PSYSID_UUID SysIdUuid,
ULONG *SysIdUuidCount,
PSYSID_1394 SysId1394,
ULONG *SysId1394Count
);
NTSTATUS WmipGetSysIds(
PSYSID_UUID *SysIdUuid,
ULONG *SysIdUuidCount,
PSYSID_1394 *SysId1394,
ULONG *SysId1394Count
);
#ifdef ALLOC_DATA_PRAGMA
#pragma data_seg("PAGEDATA")
#endif
//
// These hold pointers to the SMBIOS data. If SMBIOS data is in the table
// format then WmipSMBiosTablePhysicalAddress holds the physical address of
// the table. If the SMBIOS was gathered at boot time by NTDETECT then
// WmipSMBiosTableVirtualAddress holds a pointer to a paged pool buffer that
// contains the SMBIOS data. In both cases WmipSMBiosTableLength holds the
// actual length of the SMBIOS table. If both the physical and virtual
// addresses are 0 then SMBIOS data is not available.
PHYSICAL_ADDRESS WmipSMBiosTablePhysicalAddress = {0};
PUCHAR WmipSMBiosTableVirtualAddress = NULL;
ULONG WmipSMBiosTableLength = 0;
SMBIOSVERSIONINFO WmipSMBiosVersionInfo = {0};
BOOLEAN WmipSMBiosChecked = FALSE;
//
// Have we tried to get SYSID yet and if so what was the utilmate status
BOOLEAN WmipSysIdRead;
NTSTATUS WmipSysIdStatus;
//
// Count and arrays of UUIDs and 1394 ids
PSYSID_UUID WmipSysIdUuid;
ULONG WmipSysIdUuidCount;
PSYSID_1394 WmipSysId1394;
ULONG WmipSysId1394Count;
#ifdef ALLOC_PRAGMA
#pragma alloc_text(INIT,WmipGetSMBiosFromLoaderBlock)
#pragma alloc_text(PAGE,WmipFindSMBiosEPSHeader)
#pragma alloc_text(PAGE,WmipFindSMBiosTable)
#pragma alloc_text(PAGE,WmipFindSMBiosStructure)
#pragma alloc_text(PAGE,WmipFindSysIdTable)
#pragma alloc_text(PAGE,WmipParseSysIdTable)
#pragma alloc_text(PAGE,WmipGetSysIds)
#pragma alloc_text(PAGE,WmipGetSMBiosTableData)
#pragma alloc_text(PAGE,WmipGetSMBiosEventlog)
#pragma alloc_text(PAGE,WmipDockUndockEventCallback)
#pragma alloc_text(PAGE,WmipSMBiosDataRegQueryRoutine)
#pragma alloc_text(PAGE,WmipSMBiosIdentifierRegQueryRoutine)
#pragma alloc_text(PAGE,WmipIsSMBiosKey)
#endif
BOOLEAN WmipFindSMBiosEPSHeader(
PUCHAR SMBiosVirtualAddress,
ULONG BiosSize,
PSMBIOS_EPS_HEADER EPSHeader
)
/*++
Routine Description:
Search for the SMBIOS 2.1 EPS structure and copy it.
Arguments:
SMBiosVirtualAddress is the beginning virtual address to start searching
for the SMBIOS 2.1 EPS anchor string.
BiosSize is the number of bytes to search for the anchor string
EPSHeader is the memory into which the EPS header is copied
Return Value:
Pointer to SMBIOS 2.1 EPS or NULL if EPS not found
--*/
{
PUCHAR SearchEnd;
UCHAR CheckSum;
PSMBIOS_EPS_HEADER SMBiosEPSHeader;
PDMIBIOS_EPS_HEADER DMIBiosEPSHeader;
ULONG i;
ULONG CheckLength;
PAGED_CODE();
UNREFERENCED_PARAMETER (BiosSize);
RtlZeroMemory(EPSHeader, sizeof(SMBIOS_EPS_HEADER));
//
// Scan the bios for the two anchor strings that that signal the SMBIOS
// table.
SearchEnd = SMBiosVirtualAddress + SMBIOS_EPS_SEARCH_SIZE -
2 * SMBIOS_EPS_SEARCH_INCREMENT;
while (SMBiosVirtualAddress < SearchEnd)
{
SMBiosEPSHeader = (PSMBIOS_EPS_HEADER)SMBiosVirtualAddress;
DMIBiosEPSHeader = (PDMIBIOS_EPS_HEADER)SMBiosVirtualAddress;
//
// First check for _DMI_ anchor string
if ((*((PULONG)DMIBiosEPSHeader->Signature2) == DMI_EPS_SIGNATURE) &&
(DMIBiosEPSHeader->Signature2[4] == '_'))
{
WmipDebugPrintEx((DPFLTR_WMICORE_ID, DPFLTR_INFO_LEVEL,"WMI: Found possible DMIBIOS EPS Header at %x\n", SMBiosEPSHeader));
CheckLength = sizeof(DMIBIOS_EPS_HEADER);
}
//
// Then check for full _SM_ anchor string
else if ((*((PULONG)SMBiosEPSHeader->Signature) == SMBIOS_EPS_SIGNATURE) &&
(SMBiosEPSHeader->Length >= sizeof(SMBIOS_EPS_HEADER)) &&
(*((PULONG)SMBiosEPSHeader->Signature2) == DMI_EPS_SIGNATURE) &&
(SMBiosEPSHeader->Signature2[4] == '_' ))
{
WmipDebugPrintEx((DPFLTR_WMICORE_ID, DPFLTR_INFO_LEVEL,"WMI: Found possible SMBIOS EPS Header at %p\n", SMBiosEPSHeader));
CheckLength = SMBiosEPSHeader->Length;
} else {
//
// Did not find anchor string, go search next paragraph
SMBiosVirtualAddress += SMBIOS_EPS_SEARCH_INCREMENT;
continue;
}
//
// Verify anchor string with checksum
CheckSum = 0;
for (i = 0; i < CheckLength ; i++)
{
CheckSum = (UCHAR)(CheckSum + SMBiosVirtualAddress[i]);
}
if (CheckSum == 0)
{
WmipDebugPrintEx((DPFLTR_WMICORE_ID, DPFLTR_INFO_LEVEL,"WMI: Found SMBIOS EPS Header at %p\n", SMBiosEPSHeader));
if (CheckLength == sizeof(DMIBIOS_EPS_HEADER))
{
//
// We only had got a DMI header so copy that
//
RtlCopyMemory(&EPSHeader->Signature2[0],
DMIBiosEPSHeader,
sizeof(DMIBIOS_EPS_HEADER));
} else {
//
// We got the full SMBIOS header so copy that
//
RtlCopyMemory(EPSHeader,
SMBiosEPSHeader,
sizeof(SMBIOS_EPS_HEADER));
}
return(TRUE);
}
SMBiosVirtualAddress += SMBIOS_EPS_SEARCH_INCREMENT;
}
WmipDebugPrintEx((DPFLTR_WMICORE_ID, DPFLTR_INFO_LEVEL,"WMI: SMBIOS EPS Header not found\n"));
return(FALSE);
}
#ifndef _IA64_
//
// On X86 we look at the hardware device description keys to find the
// one that contains the SMBIOS data. The key is created by NTDETECT in
// the case that the machine only supports the 2.0 calling mechanism
//
//
// For x86 and ia64 the key is Someplace like
// HKLM\Hardware\System\MultiFunctionAdapter\<some number>
//
NTSTATUS WmipSMBiosIdentifierRegQueryRoutine(
IN PWSTR ValueName,
IN ULONG ValueType,
IN PVOID ValueData,
IN ULONG ValueLength,
IN PVOID Context,
IN PVOID EntryContext
)
/*++
Routine Description:
Registry query values callback routine for reading SMBIOS data from
registry.
Arguments:
ValueName - the name of the value
ValueType - the type of the value
ValueData - the data in the value (unicode string data)
ValueLength - the number of bytes in the value data
Context - Not used
EntryContext - Pointer to PUCHAR to store a pointer to
store the SMBIOS data read from the registry value. If this is NULL
then the caller is not interested in the SMBIOS data
Return Value:
NT Status code -
STATUS_SUCCESS - Identifier is valid for SMBIOS key
STATUS_UNSUCCESSFUL - Identifier is not valid for SMBIOS key
--*/
{
NTSTATUS Status;
PAGED_CODE();
UNREFERENCED_PARAMETER (ValueName);
UNREFERENCED_PARAMETER (ValueLength);
UNREFERENCED_PARAMETER (Context);
UNREFERENCED_PARAMETER (EntryContext);
Status = ((ValueType == REG_SZ) &&
(ValueData != NULL) &&
(wcscmp(ValueData, SMBIOSIDENTIFIERVALUEDATA) == 0)) ?
STATUS_SUCCESS :
STATUS_UNSUCCESSFUL;
return(Status);
}
NTSTATUS WmipSMBiosDataRegQueryRoutine(
IN PWSTR ValueName,
IN ULONG ValueType,
IN PVOID ValueData,
IN ULONG ValueLength,
IN PVOID Context,
IN PVOID EntryContext
)
/*++
Routine Description:
Registry query values callback routine for reading SMBIOS data from
registry.
Arguments:
ValueName - the name of the value
ValueType - the type of the value
ValueData - the data in the value (unicode string data)
ValueLength - the number of bytes in the value data
Context - Not used
EntryContext - Pointer to PUCHAR to store a pointer to
store the SMBIOS data read from the registry value. If this is NULL
then the caller is not interested in the SMBIOS data
Return Value:
NT Status code -
STATUS_SUCCESS - SMBIOS data is present in the value
STATUS_INSUFFICIENT_RESOURCES - Not enough memory to keep SMBIOS data
STATUS_UNSUCCESSFUL - SMBios data is not present in the value
--*/
{
NTSTATUS Status;
PCM_PARTIAL_RESOURCE_LIST PartialResourceList;
PUCHAR Buffer;
PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor;
ULONG BufferSize;
PREGQUERYBUFFERXFER RegQueryBufferXfer;
PAGED_CODE();
UNREFERENCED_PARAMETER (ValueName);
UNREFERENCED_PARAMETER (ValueLength);
UNREFERENCED_PARAMETER (Context);
WmipAssert(EntryContext != NULL);
if ((ValueType == REG_FULL_RESOURCE_DESCRIPTOR) &&
(ValueData != NULL))
{
//
// On x86 get the actual SMBIOS data out of the registry and
// place it into a buffer
//
RegQueryBufferXfer = (PREGQUERYBUFFERXFER)EntryContext;
PartialResourceList = &(((PCM_FULL_RESOURCE_DESCRIPTOR)ValueData)->PartialResourceList);
if (PartialResourceList->Count > 1)
{
//
// Second partial resource descriptor contains SMBIOS data. There
// should ALWAYS be a second partial resource descriptor and it
// may have 0 bytes in the case that SMBIOS data was not collected
// by NTDETECT.
PartialDescriptor = &PartialResourceList->PartialDescriptors[0];
Buffer = (PUCHAR)PartialDescriptor +
sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR) +
PartialDescriptor->u.DeviceSpecificData.DataSize;
PartialDescriptor = (PCM_PARTIAL_RESOURCE_DESCRIPTOR)Buffer;
BufferSize = PartialDescriptor->u.DeviceSpecificData.DataSize;
RegQueryBufferXfer->BufferSize = BufferSize;
Status = STATUS_SUCCESS;
if (BufferSize > 0)
{
RegQueryBufferXfer->Buffer = (PUCHAR)ExAllocatePoolWithTag(
PagedPool,
BufferSize,
WMIPOOLTAG);
if (RegQueryBufferXfer->Buffer != NULL)
{
Buffer += sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR);
RtlCopyMemory(RegQueryBufferXfer->Buffer,
Buffer,
BufferSize);
} else {
Status = STATUS_INSUFFICIENT_RESOURCES;
}
}
} else {
WmipDebugPrintEx((DPFLTR_WMICORE_ID, DPFLTR_INFO_LEVEL,"WMI: Old NTDETECT.COM - No SMBIOS partial resource descriptor\n"));
Status = STATUS_SUCCESS;
RegQueryBufferXfer->BufferSize = 0;
}
} else {
Status = STATUS_UNSUCCESSFUL;
}
return(Status);
}
BOOLEAN WmipIsSMBiosKey(
HANDLE ParentKeyHandle,
PWCHAR KeyName,
PUCHAR *SMBiosTableVirtualAddress,
PULONG SMBiosTableLength
)
{
NTSTATUS Status;
OBJECT_ATTRIBUTES ObjectAttributes;
UNICODE_STRING BaseKeyName;
HANDLE KeyHandle;
RTL_QUERY_REGISTRY_TABLE QueryTable[3];
REGQUERYBUFFERXFER RegQueryBufferXfer = {0, NULL};
PAGED_CODE();
RtlInitUnicodeString(&BaseKeyName,
KeyName);
InitializeObjectAttributes(&ObjectAttributes,
&BaseKeyName,
OBJ_CASE_INSENSITIVE,
ParentKeyHandle,
NULL);
Status = ZwOpenKey(&KeyHandle,
KEY_READ,
&ObjectAttributes);
if (NT_SUCCESS(Status))
{
RtlZeroMemory(QueryTable, sizeof(QueryTable));
QueryTable[0].Name = SMBIOSIDENTIFIERVALUENAME;
QueryTable[0].Flags = RTL_QUERY_REGISTRY_REQUIRED;
QueryTable[0].DefaultType = REG_SZ;
QueryTable[0].QueryRoutine = WmipSMBiosIdentifierRegQueryRoutine;
QueryTable[1].Name = SMBIOSDATAVALUENAME;
QueryTable[1].Flags = RTL_QUERY_REGISTRY_REQUIRED;
QueryTable[1].EntryContext = &RegQueryBufferXfer;
QueryTable[1].DefaultType = REG_FULL_RESOURCE_DESCRIPTOR;
QueryTable[1].QueryRoutine = WmipSMBiosDataRegQueryRoutine;
Status = RtlQueryRegistryValues(RTL_REGISTRY_HANDLE | RTL_REGISTRY_ABSOLUTE,
(PWCHAR)KeyHandle,
QueryTable,
NULL,
NULL);
if (NT_SUCCESS(Status))
{
*SMBiosTableVirtualAddress = RegQueryBufferXfer.Buffer;
*SMBiosTableLength = RegQueryBufferXfer.BufferSize;
}
ZwClose(KeyHandle);
} else {
WmipDebugPrintEx((DPFLTR_WMICORE_ID, DPFLTR_INFO_LEVEL,"WMI: H/D/S/MultifunctionAdapter subkey open error %x\n",
Status));
}
return(NT_SUCCESS(Status) ? TRUE : FALSE);
}
#endif
BOOLEAN WmipFindSMBiosTable(
PPHYSICAL_ADDRESS SMBiosTablePhysicalAddress,
PUCHAR *SMBiosTableVirtualAddress,
PULONG SMBiosTableLength,
PSMBIOSVERSIONINFO SMBiosVersionInfo
)
/*++
Routine Description:
Determines if the SMBIOS data is available
Arguments:
SMBiosTablePhysicalAddress points to a variable to return the physical
address of the SMBIOS 2.1 table. If table is not available then
it returns with 0.
SMBiosTableVirtualAddress points to a variable to return the virtual
address of the SMBIOS 2.0 table as collected by NTDETECT. If the
SMBIOS 2.0 data was not collected by NTDETECT it returns with 0.
SMBiosTableLength points to a variable to return the length of the
SMBIOS table data.
SMBiosVersionInfo returns with the version information for SMBIOS
Return Value:
TRUE if SMBIOS data is available, else FALSE
--*/
{
PHYSICAL_ADDRESS BiosPhysicalAddress;
PUCHAR BiosVirtualAddress;
PDMIBIOS_EPS_HEADER DMIBiosEPSHeader;
#ifndef _IA64_
NTSTATUS Status;
UNICODE_STRING BaseKeyName;
HANDLE KeyHandle;
OBJECT_ATTRIBUTES ObjectAttributes;
ULONG KeyIndex;
ULONG KeyInformationLength;
UCHAR KeyInformationBuffer[sizeof(KEY_BASIC_INFORMATION) +
(sizeof(WCHAR) * MAXSMBIOSKEYNAMESIZE)];
PKEY_BASIC_INFORMATION KeyInformation;
#endif
SMBIOS_EPS_HEADER SMBiosEPSHeader;
BOOLEAN HaveEPSHeader = FALSE;
BOOLEAN SearchForHeader = TRUE;
PAGED_CODE();
SMBiosTablePhysicalAddress->QuadPart = 0;
*SMBiosTableVirtualAddress = NULL;
*SMBiosTableLength = 0;
#ifndef _IA64_
//
// First check registry to see if we captured SMBIOS 2.0 data in
// NTDETECT. Search the keys under
// MultiFunctionAdapter for the one
// with the "PnP Bios" (x86)
//
RtlInitUnicodeString(&BaseKeyName,
SMBIOSPARENTKEYNAME);
InitializeObjectAttributes(&ObjectAttributes,
&BaseKeyName,
OBJ_CASE_INSENSITIVE,
NULL,
NULL);
Status = ZwOpenKey(&KeyHandle,
KEY_READ,
&ObjectAttributes);
if (NT_SUCCESS(Status))
{
KeyIndex = 0;
KeyInformation = (PKEY_BASIC_INFORMATION)KeyInformationBuffer;
while (NT_SUCCESS(Status))
{
Status = ZwEnumerateKey(KeyHandle,
KeyIndex++,
KeyBasicInformation,
KeyInformation,
sizeof(KeyInformationBuffer) - sizeof(WCHAR),
&KeyInformationLength);
if (NT_SUCCESS(Status))
{
KeyInformation->Name[KeyInformation->NameLength / sizeof(WCHAR)] = UNICODE_NULL;
if (WmipIsSMBiosKey(KeyHandle,
KeyInformation->Name,
SMBiosTableVirtualAddress,
SMBiosTableLength))
{
if (*SMBiosTableLength != 0)
{
SMBiosVersionInfo->Used20CallingMethod = TRUE;
SearchForHeader = FALSE;
}
break;
}
} else {
WmipDebugPrintEx((DPFLTR_WMICORE_ID, DPFLTR_INFO_LEVEL,"WMI: Status %x enum H\\D\\S\\MultiFunctionAdapter key, index %d\n",
Status, KeyIndex-1));
}
}
ZwClose(KeyHandle);
} else {
WmipDebugPrintEx((DPFLTR_WMICORE_ID, DPFLTR_INFO_LEVEL,"WMI: Status %x opening H\\D\\S\\MultiFunctionAdapter key\n",
Status));
}
#endif
if (SearchForHeader)
{
//
// If not in registry then check for EPS in the BIOS
BiosPhysicalAddress.QuadPart = SMBIOS_EPS_SEARCH_START;
BiosVirtualAddress = MmMapIoSpace(BiosPhysicalAddress,
SMBIOS_EPS_SEARCH_SIZE,
MmNonCached);
if (BiosVirtualAddress != NULL)
{
HaveEPSHeader = WmipFindSMBiosEPSHeader(BiosVirtualAddress,
SMBIOS_EPS_SEARCH_SIZE,
&SMBiosEPSHeader);
MmUnmapIoSpace(BiosVirtualAddress, SMBIOS_EPS_SEARCH_SIZE);
}
} else {
WmipDebugPrintEx((DPFLTR_WMICORE_ID, DPFLTR_INFO_LEVEL,"WMI: SMBIOS data recovered from loader\n"));
}
if (HaveEPSHeader)
{
//
// We found the EPS so just extract the physical
// address of the table
//
DMIBiosEPSHeader = (PDMIBIOS_EPS_HEADER)&SMBiosEPSHeader.Signature2[0];
SMBiosVersionInfo->Used20CallingMethod = FALSE;
SMBiosTablePhysicalAddress->HighPart = 0;
SMBiosTablePhysicalAddress->LowPart = DMIBiosEPSHeader->StructureTableAddress;
*SMBiosTableLength = DMIBiosEPSHeader->StructureTableLength;
SMBiosVersionInfo->SMBiosMajorVersion = SMBiosEPSHeader.MajorVersion;
SMBiosVersionInfo->SMBiosMinorVersion = SMBiosEPSHeader.MinorVersion;
SMBiosVersionInfo->DMIBiosRevision = DMIBiosEPSHeader->Revision;
WmipDebugPrintEx((DPFLTR_WMICORE_ID, DPFLTR_INFO_LEVEL,"WMI: SMBIOS 2.1 data at (%x%x) size %x \n",
SMBiosTablePhysicalAddress->HighPart,
SMBiosTablePhysicalAddress->LowPart,
*SMBiosTableLength));
}
return(*SMBiosTableLength > 0 ? TRUE : FALSE);
}
NTSTATUS WmipGetSMBiosTableData(
OUT PUCHAR Buffer,
IN OUT PULONG BufferSize,
OUT PSMBIOSVERSIONINFO SMBiosVersionInfo
)
/*++
Routine Description:
Registry query values callback routine for reading SMBIOS data from
registry.
Arguments:
Buffer is a pointer to a buffer in which to write the SMBIOS data
*BufferSize has the maximum number of bytes available to write into
Buffer. On return it has the actual size of the SMBIOS data.
Return Value:
NT Status code -
STATUS_SUCCESS - Buffer filled with SMBIOS data
STATUS_BUFFER_TOO_SMALL - Buffer not filled with SMBIOS data,
*BufferSize returns with buffer size neeeded
--*/
{
NTSTATUS status;
PUCHAR SMBiosDataVirtualAddress;
PAGED_CODE();
WmipEnterSMCritSection();
if (! WmipSMBiosChecked)
{
//
// See if there is any SMBIOS information and if so register
WmipFindSMBiosTable(&WmipSMBiosTablePhysicalAddress,
&WmipSMBiosTableVirtualAddress,
&WmipSMBiosTableLength,
&WmipSMBiosVersionInfo);
WmipSMBiosChecked = TRUE;
}
WmipLeaveSMCritSection();
if (SMBiosVersionInfo != NULL)
{
*SMBiosVersionInfo = WmipSMBiosVersionInfo;
}
if (*BufferSize >= WmipSMBiosTableLength)
{
if (WmipSMBiosTablePhysicalAddress.QuadPart != 0)
{
//
// 2.1 table format - map in table and copy
SMBiosDataVirtualAddress = MmMapIoSpace(WmipSMBiosTablePhysicalAddress,
WmipSMBiosTableLength,
MmNonCached);
if (SMBiosDataVirtualAddress != NULL)
{
RtlCopyMemory(Buffer,
SMBiosDataVirtualAddress,
WmipSMBiosTableLength);
MmUnmapIoSpace(SMBiosDataVirtualAddress,
WmipSMBiosTableLength);
status = STATUS_SUCCESS;
} else {
status = STATUS_INSUFFICIENT_RESOURCES;
}
} else if (WmipSMBiosTableVirtualAddress != NULL) {
RtlCopyMemory(Buffer,
WmipSMBiosTableVirtualAddress,
WmipSMBiosTableLength);
status = STATUS_SUCCESS;
} else {
status = STATUS_INVALID_DEVICE_REQUEST;
}
} else {
status = STATUS_BUFFER_TOO_SMALL;
}
*BufferSize = WmipSMBiosTableLength;
return(status);
}
#if defined(_IA64_) // EFI actually
void WmipGetSMBiosFromLoaderBlock(
PVOID LoaderBlockPtr
)
{
PLOADER_PARAMETER_BLOCK LoaderBlock = (PLOADER_PARAMETER_BLOCK)LoaderBlockPtr;
PLOADER_PARAMETER_EXTENSION LoaderExtension = LoaderBlock->Extension;
PSMBIOS_EPS_HEADER SMBiosEPSHeader;
PDMIBIOS_EPS_HEADER DMIBiosEPSHeader;
PAGED_CODE();
if (LoaderExtension->Size >= sizeof(LOADER_PARAMETER_EXTENSION))
{
SMBiosEPSHeader = LoaderExtension->SMBiosEPSHeader;
if (SMBiosEPSHeader != NULL)
{
DMIBiosEPSHeader = (PDMIBIOS_EPS_HEADER)&SMBiosEPSHeader->Signature2[0];
WmipSMBiosVersionInfo.Used20CallingMethod = FALSE;
WmipSMBiosTablePhysicalAddress.HighPart = 0;
WmipSMBiosTablePhysicalAddress.LowPart = DMIBiosEPSHeader->StructureTableAddress;
WmipSMBiosTableLength = DMIBiosEPSHeader->StructureTableLength;
WmipSMBiosVersionInfo.SMBiosMajorVersion = SMBiosEPSHeader->MajorVersion;
WmipSMBiosVersionInfo.SMBiosMinorVersion = SMBiosEPSHeader->MinorVersion;
WmipSMBiosVersionInfo.DMIBiosRevision = DMIBiosEPSHeader->Revision;
WmipSMBiosChecked = TRUE;
WmipDebugPrintEx((DPFLTR_WMICORE_ID, DPFLTR_INFO_LEVEL,
"WMI: SMBIOS 2.1 data from EFI at (%x%x) size %x \n",
WmipSMBiosTablePhysicalAddress.HighPart,
WmipSMBiosTablePhysicalAddress.LowPart,
WmipSMBiosTableLength));
} else {
WmipDebugPrintEx((DPFLTR_WMICORE_ID, DPFLTR_INFO_LEVEL,
"WMI: No SMBIOS data in loader block\n"));
}
} else {
WmipDebugPrintEx((DPFLTR_WMICORE_ID, DPFLTR_INFO_LEVEL,
"WMI: Loader extension does not contain SMBIOS header\n"));
}
}
#endif
#define WmipUnmapSMBiosStructure(Address, Size) \
if ((Address) != NULL) MmUnmapIoSpace((Address), (Size));
NTSTATUS WmipFindSMBiosStructure(
IN UCHAR Type,
OUT PVOID *StructPtr,
OUT PVOID *MapPtr,
OUT PULONG MapSize
)
/*++
Routine Description:
Find a specific SMBIOS structure in the SMBIOS information.
WmipUnmapSNVuisStructure should be called if this function returns
successfully.
Arguments:
Type is structure type to find
*StructPtr returns with pointer to beginning of structure
*MapPtr returns with pointer to address SMBIOS data was mapped.
*MapSize returns with size mapped
Return Value:
STATUS
--*/
{
NTSTATUS Status;
BOOLEAN Found;
PUCHAR Ptr;
PUCHAR PtrEnd;
PSMBIOS_STRUCT_HEADER StructHeader;
PAGED_CODE();
//
// Make sure SMBIOS table has been obtained. Note we already hold
// the critical section
if (! WmipSMBiosChecked)
{
//
// See if there is any SMBIOS information and if so register
Found = WmipFindSMBiosTable(&WmipSMBiosTablePhysicalAddress,
&WmipSMBiosTableVirtualAddress,
&WmipSMBiosTableLength,
&WmipSMBiosVersionInfo);
WmipSMBiosChecked = TRUE;
} else {
Found = (WmipSMBiosTableLength > 0 ? TRUE : FALSE);
}
if (Found)
{
Status = STATUS_SUCCESS;
if (WmipSMBiosTablePhysicalAddress.QuadPart != 0)
{
//
// SMBIOS is available in physical memory
*MapPtr = MmMapIoSpace(WmipSMBiosTablePhysicalAddress,
WmipSMBiosTableLength,
MmCached);
if (*MapPtr != NULL)
{
*MapSize = WmipSMBiosTableLength;
Ptr = *MapPtr;
} else {
//
// Lets hope this is a temporary problem
Status = STATUS_INSUFFICIENT_RESOURCES;
Ptr = NULL;
}
} else if (WmipSMBiosTableVirtualAddress != NULL) {
*MapPtr = NULL;
Ptr = WmipSMBiosTableVirtualAddress;
} else {
WmipDebugPrintEx((DPFLTR_WMICORE_ID, DPFLTR_INFO_LEVEL,"WMI: SMBIOS table was found, but is not in physical or virtual memory\n"));
WmipAssert(FALSE);
Status = STATUS_UNSUCCESSFUL;
Ptr = NULL;
}
if (NT_SUCCESS(Status))
{
//
// Now scan the SMBIOS table to find our structure
*StructPtr = NULL;
PtrEnd = (PVOID)((PUCHAR)Ptr + WmipSMBiosTableLength);
Status = STATUS_UNSUCCESSFUL;
StructHeader = NULL;
try
{
while (Ptr < PtrEnd)
{
StructHeader = (PSMBIOS_STRUCT_HEADER)Ptr;
if (StructHeader->Type == Type)
{
WmipDebugPrintEx((DPFLTR_WMICORE_ID, DPFLTR_INFO_LEVEL,"WMI: SMBIOS struct for type %d found at %p\n",
Type, Ptr));
*StructPtr = Ptr;
Status = STATUS_SUCCESS;
break;
}
Ptr+= StructHeader->Length;
while ( (*((USHORT UNALIGNED *)Ptr) != 0) &&
(Ptr < PtrEnd) )
{
Ptr++;
}
Ptr += 2;
}
} except(EXCEPTION_EXECUTE_HANDLER) {
WmipDebugPrintEx((DPFLTR_WMICORE_ID, DPFLTR_INFO_LEVEL,"WMI: Invalid SMBIOS data table %p at %p\n",
*MapPtr, StructHeader));
WmipAssert(FALSE);
}
if (! NT_SUCCESS(Status) )
{
WmipUnmapSMBiosStructure(*MapPtr, *MapSize);
}
}
} else {
Status = STATUS_UNSUCCESSFUL;
}
return(Status);
}
NTSTATUS WmipFindSysIdTable(
PPHYSICAL_ADDRESS SysidTablePhysicalAddress,
PUCHAR SysIdBiosRevision,
PULONG NumberEntries
)
/*++
Routine Description:
Scan the system bios to search for the SYSID table
Arguments:
*SysidTablePhysicalAddress returns with the physical address of the
sysid table
*SysIdBiosRevision returns with the bios revision of the sysid table
*NumberEntries returns the number of SYSID entries in the table
Return Value:
STATUS
--*/
{
UCHAR Checksum;
PUCHAR p;
PSYSID_EPS_HEADER SysIdEps, SearchEnd;
PHYSICAL_ADDRESS BiosPhysicalAddress;
PUCHAR BiosVirtualAddress;
ULONG i;
NTSTATUS Status;
PAGED_CODE();
BiosPhysicalAddress.QuadPart = SYSID_EPS_SEARCH_START;
BiosVirtualAddress = MmMapIoSpace(BiosPhysicalAddress,
SYSID_EPS_SEARCH_SIZE,
MmCached);
SearchEnd = (PSYSID_EPS_HEADER)(BiosVirtualAddress + SYSID_EPS_SEARCH_SIZE);
SysIdEps = (PSYSID_EPS_HEADER)BiosVirtualAddress;
if (BiosVirtualAddress != NULL)
{
try
{
while (SysIdEps < SearchEnd)
{
if (((*(PULONG)SysIdEps->Signature) == SYSID_EPS_SIGNATURE) &&
(*(PUSHORT)(&SysIdEps->Signature[4]) == SYSID_EPS_SIGNATURE2) &&
(SysIdEps->Signature[6] == '_') )
{
//
// This may be the SYSID table, check the checksum
Checksum = 0;
p = (PUCHAR)SysIdEps;
for (i = 0; i < sizeof(SYSID_EPS_HEADER); i++)
{
Checksum = (UCHAR)(Checksum + p[i]);
}
if (Checksum == 0)
{
WmipDebugPrintEx((DPFLTR_WMICORE_ID, DPFLTR_INFO_LEVEL,"WMI: SYSID EPS found at %p\n",
SysIdEps));
break;
} else {
WmipDebugPrintEx((DPFLTR_WMICORE_ID, DPFLTR_INFO_LEVEL,"WMI: Invalis SYSID EPS checksum at %p\n",
SysIdEps));
}
}
SysIdEps = (PSYSID_EPS_HEADER)( ((PUCHAR)SysIdEps) +
SYSID_EPS_SEARCH_INCREMENT);
}
if (SysIdEps != SearchEnd)
{
SysidTablePhysicalAddress->HighPart = 0;
SysidTablePhysicalAddress->LowPart = SysIdEps->SysIdTableAddress;
*SysIdBiosRevision = SysIdEps->BiosRev;
*NumberEntries = SysIdEps->SysIdCount;
Status = STATUS_SUCCESS;
} else {
//
// Not finding the SYSID EPS is a terminal error
Status = STATUS_UNSUCCESSFUL;
}
} except(EXCEPTION_EXECUTE_HANDLER) {
WmipDebugPrintEx((DPFLTR_WMICORE_ID, DPFLTR_INFO_LEVEL,"WMI: Invalid SYSID EPS Table at %p\n", SysIdEps));
Status = STATUS_UNSUCCESSFUL;
}
MmUnmapIoSpace(BiosVirtualAddress, SYSID_EPS_SEARCH_SIZE);
} else {
//
// Lets hope that failure to map memory is a temporary problem
Status = STATUS_INSUFFICIENT_RESOURCES;
}
return(Status);
}
typedef enum
{
SYSID_UNKNOWN_TYPE,
SYSID_UUID_TYPE,
SYSID_1394_TYPE
} SYSID_ENTRY_TYPE, *PSYSID_ENTRY_TYPE;
NTSTATUS WmipParseSysIdTable(
PHYSICAL_ADDRESS PhysicalAddress,
ULONG NumberEntries,
PSYSID_UUID SysIdUuid,
ULONG *SysIdUuidCount,
PSYSID_1394 SysId1394,
ULONG *SysId1394Count
)
/*++
Routine Description:
Determine the set of UUIDs and 1394 Ids that are in the sysid table
Arguments:
PhysicalAddress is the physical address of the SysId table
NumberEntries is the number of entries in the SysId table
SysIdUuid returns filled with an array of UUIDs. If NULL then no
UUIDs are returned.
*SysIdUuidCount returns with the number of UUIDs in the table
SysId1394 returns filled with an array of 1394 ids. If NULL then no
1394 ids are returned.
*SysId1394Count returns with the number of 1394 ids in the table
Return Value:
STATUS
--*/
{
NTSTATUS Status;
ULONG TableSize = NumberEntries * LARGEST_SYSID_TABLE_ENTRY;
ULONG i;
ULONG j;
PUCHAR VirtualAddress;
PSYSID_TABLE_ENTRY SysId;
PUCHAR p;
UCHAR Checksum;
ULONG Length;
ULONG x1394Count, UuidCount;
ULONG BytesLeft;
SYSID_ENTRY_TYPE SysidType;
PAGED_CODE();
VirtualAddress = MmMapIoSpace(PhysicalAddress,
TableSize,
MmCached);
if (VirtualAddress != NULL)
{
UuidCount = 0;
x1394Count = 0;
SysId = (PSYSID_TABLE_ENTRY)VirtualAddress;
BytesLeft = TableSize;
Status = STATUS_SUCCESS;
for (i = 0; i < NumberEntries; i++)
{
//
// Make sure we have not moved beyond the end of the mapped
// memory.
if (BytesLeft >= sizeof(SYSID_TABLE_ENTRY))
{
Length = SysId->Length;
//
// Determine what kind of sysid we have
//
if ((RtlCompareMemory(&SysId->Type,
SYSID_TYPE_UUID, 6) == 6) &&
(Length == sizeof(SYSID_UUID_ENTRY)))
{
SysidType = SYSID_UUID_TYPE;
} else if ((RtlCompareMemory(&SysId->Type,
SYSID_TYPE_1394, 6) == 6) &&
(Length == sizeof(SYSID_1394_ENTRY))) {
SysidType = SYSID_1394_TYPE;
} else {
//
// unknown type SYSID
//
WmipDebugPrintEx((DPFLTR_WMICORE_ID, DPFLTR_INFO_LEVEL,"WMI: Unknown SYSID type %c%c%c%c%c%c found at %p\n",
SysId->Type[0],
SysId->Type[1],
SysId->Type[2],
SysId->Type[3],
SysId->Type[4],
SysId->Type[5],
SysId
));
Status = STATUS_UNSUCCESSFUL;
break;
}
//
// Validate checksum for this table entry
if (BytesLeft >= Length)
{
Checksum = 0;
p = (PUCHAR)SysId;
for (j = 0; j < Length; j++)
{
Checksum = (UCHAR)(Checksum + p[j]);
}
if (Checksum != 0)
{
WmipDebugPrintEx((DPFLTR_WMICORE_ID, DPFLTR_INFO_LEVEL,"WMI: SYSID Table checksum is not valid at %p\n",
SysId));
Status = STATUS_UNSUCCESSFUL;
break;
}
//
// Determine what kind of SYSID we have
if (SysidType == SYSID_UUID_TYPE)
{
if (BytesLeft >= sizeof(SYSID_UUID_ENTRY))
{
//
// _UUID_ type SYSID
UuidCount++;
if (SysIdUuid != NULL)
{
RtlCopyMemory(SysIdUuid,
SysId->Data,
sizeof(SYSID_UUID));
SysIdUuid++;
}
} else {
Status = STATUS_UNSUCCESSFUL;
break;
}
} else if (SysidType == SYSID_1394_TYPE) {
if (BytesLeft >= sizeof(SYSID_1394_ENTRY))
{
//
// _1394_ type SYSID
x1394Count++;
if (SysId1394 != NULL)
{
RtlCopyMemory(SysId1394,
SysId->Data,
sizeof(SYSID_1394));
SysId1394++;
}
} else {
Status = STATUS_UNSUCCESSFUL;
break;
}
} else {
WmipAssert(FALSE);
Status = STATUS_UNSUCCESSFUL;
break;
}
//
// Advance to next sysid in table
SysId = (PSYSID_TABLE_ENTRY)(((PUCHAR)SysId) + Length);
BytesLeft -= Length;
} else {
WmipDebugPrintEx((DPFLTR_WMICORE_ID, DPFLTR_INFO_LEVEL,"WMI: SYSID Table at %p is larger at %p than expected",
VirtualAddress, SysId));
Status = STATUS_UNSUCCESSFUL;
break;
}
} else {
WmipDebugPrintEx((DPFLTR_WMICORE_ID, DPFLTR_INFO_LEVEL,"WMI: SYSID Table at %p is larger at %p than expected",
VirtualAddress, SysId));
Status = STATUS_UNSUCCESSFUL;
break;
}
}
*SysIdUuidCount = UuidCount;
*SysId1394Count = x1394Count;
MmUnmapIoSpace(VirtualAddress, TableSize);
} else {
//
// Lets hope that the failure to map is a temporary condition
Status = STATUS_INSUFFICIENT_RESOURCES;
}
return(Status);
}
NTSTATUS WmipGetSysIds(
PSYSID_UUID *SysIdUuid,
ULONG *SysIdUuidCount,
PSYSID_1394 *SysId1394,
ULONG *SysId1394Count
)
/*++
Routine Description:
This routine will obtain the 1394 and UUID sysids from the bios. First
we look for a specific memory signature that contains a list of 1394 and
UUID sysids. If we do not find that we then look at the SMBIOS information
structure SYSTEM INFORMATION (type 1) which may have it embedded within
it. If not then we give up.
Arguments:
*SysIdUuid returns pointing to an array of UUID Sysids
*SysIdUuidCount returns with the number of UUID Sysids in *SysIdUuid
*SysId1394 returns pointing to an array of 1394 Sysids
*SysId1394Count returns with the number of 1394 Sysids in *SysIdUuid
Return Value:
NT Status code
--*/
{
NTSTATUS Status;
PHYSICAL_ADDRESS PhysicalAddress;
UCHAR BiosRevision;
ULONG NumberEntries;
ULONG UuidCount, x1394Count;
PSYSID_UUID Uuid;
PSYSID_1394 x1394;
ULONG TotalSize, x1394Size, UuidSize;
PAGED_CODE();
WmipEnterSMCritSection();
//
// First See if we have already obtained the SYSIDS
if (! WmipSysIdRead)
{
//
// First see if the sysids are maintained in a separate SYSID table
Status = WmipFindSysIdTable(&PhysicalAddress,
&BiosRevision,
&NumberEntries);
if (NT_SUCCESS(Status))
{
//
// Get the count of entries in each table
Status = WmipParseSysIdTable(PhysicalAddress,
NumberEntries,
NULL,
&UuidCount,
NULL,
&x1394Count);
if (NT_SUCCESS(Status))
{
//
// Get the entire SYSID table
UuidSize = UuidCount * sizeof(SYSID_UUID);
x1394Size = x1394Count * sizeof(SYSID_1394);
TotalSize = UuidSize+x1394Size;
if (TotalSize > 0)
{
Uuid = ExAllocatePoolWithTag(PagedPool,
TotalSize,
WMISYSIDPOOLTAG);
if (Uuid == NULL)
{
WmipLeaveSMCritSection();
return(STATUS_INSUFFICIENT_RESOURCES);
}
x1394 = (PSYSID_1394)( ((PUCHAR)Uuid) + UuidSize );
//
// Now get the SYSIDs
Status = WmipParseSysIdTable(PhysicalAddress,
NumberEntries,
Uuid,
&UuidCount,
x1394,
&x1394Count);
if (NT_SUCCESS(Status))
{
WmipSysIdUuid = Uuid;
WmipSysIdUuidCount = UuidCount;
WmipSysId1394 = x1394;
WmipSysId1394Count = x1394Count;
} else {
ExFreePool(Uuid);
}
}
}
} else {
//
// Get SYSID information from SMBIOS
PVOID MapAddress;
PSMBIOS_SYSTEM_INFORMATION_STRUCT Info;
ULONG MapSize;
Status = WmipFindSMBiosStructure(SMBIOS_SYSTEM_INFORMATION,
(PVOID *)&Info,
&MapAddress,
&MapSize);
if (NT_SUCCESS(Status))
{
Uuid = NULL;
WmipSysId1394 = NULL;
WmipSysId1394Count = 0;
try
{
if (Info->Length > SMBIOS_SYSTEM_INFORMATION_LENGTH_20)
{
Uuid = ExAllocatePoolWithTag(PagedPool,
sizeof(SYSID_UUID),
WMISYSIDPOOLTAG);
if (Uuid != NULL)
{
RtlCopyMemory(Uuid,
Info->Uuid,
sizeof(SYSID_UUID));
WmipSysIdUuidCount = 1;
WmipSysIdUuid = Uuid;
Status = STATUS_SUCCESS;
} else {
ExFreePool(Uuid);
Status = STATUS_UNSUCCESSFUL;
}
} else {
WmipSysIdUuid = NULL;
WmipSysIdUuidCount = 0;
}
} except(EXCEPTION_EXECUTE_HANDLER) {
WmipDebugPrintEx((DPFLTR_WMICORE_ID, DPFLTR_INFO_LEVEL,"WMI: Invalid SMBIOS SYSTEM INFO structure %p\n",
Info));
WmipAssert(FALSE);
Status = STATUS_UNSUCCESSFUL;
}
WmipUnmapSMBiosStructure(MapAddress, MapSize);
}
}
//
// Mark that we were not able to obtain SysId Information
WmipSysIdRead = (Status != STATUS_INSUFFICIENT_RESOURCES) ? TRUE : FALSE;
WmipSysIdStatus = Status;
}
WmipLeaveSMCritSection();
if (NT_SUCCESS(WmipSysIdStatus))
{
*SysIdUuid = WmipSysIdUuid;
*SysIdUuidCount = WmipSysIdUuidCount;
*SysId1394 = WmipSysId1394;
*SysId1394Count = WmipSysId1394Count;
}
return(WmipSysIdStatus);
}
NTSTATUS WmipGetSMBiosEventlog(
PUCHAR Buffer,
PULONG BufferSize
)
/*++
Routine Description:
Return the contents of the SMBios eventlog
Arguments:
Buffer is a pointer to a buffer that receives the eventlog
*BufferSize on entry has the size of the buffer that can receive
the eventlog data, on return it has the number of bytes used
by the smbios eventlog data or the number of bytes needed for
the smbios eventlog data.
Return Value:
NT Status code -
STATUS_SUCCESS - Buffer filled with SMBIOS eventlog data
STATUS_BUFFER_TOO_SMALL - Buffer not filled with SMBIOS eventlog data,
*BufferSize returns with buffer size neeeded
--*/
{
PVOID MapAddress;
PSMBIOS_SYSTEM_EVENTLOG_STRUCT SystemEventlog;
ULONG MapSize;
USHORT LogAreaLength;
UCHAR AccessMethod;
ACCESS_METHOD_ADDRESS AccessMethodAddress;
PSMBIOS_EVENTLOG_INFO EventlogInfo;
UCHAR LogHeaderDescExists;
PUCHAR EventlogArea;
NTSTATUS Status;
USHORT LogTypeDescLength;
ULONG SizeNeeded;
PAGED_CODE();
Status = WmipFindSMBiosStructure(SMBIOS_SYSTEM_EVENTLOG,
(PVOID *)&SystemEventlog,
&MapAddress,
&MapSize);
if (NT_SUCCESS(Status))
{
//
// Copy data out of SMBIOS eventlog header so we can unmap quickly
//
LogAreaLength = SystemEventlog->LogAreaLength;
AccessMethod = SystemEventlog->AccessMethod;
AccessMethodAddress = SystemEventlog->AccessMethodAddress;
if (SystemEventlog->Length >= SMBIOS_SYSTEM_EVENTLOG_LENGTH)
{
LogTypeDescLength = SystemEventlog->NumLogTypeDescriptors *
SystemEventlog->LenLogTypeDescriptors;
LogHeaderDescExists = 1;
if (SystemEventlog->Length != (LogTypeDescLength +
FIELD_OFFSET(SMBIOS_SYSTEM_EVENTLOG_STRUCT,
LogTypeDescriptor)))
{
//
// The SMBIOS spec says that the Length of the structure
// is the length of the base part of the structures plus
// the length of the type descriptors. Since this is not
// the case we may have run into a buggy bios
//
WmipDebugPrintEx((DPFLTR_WMICORE_ID, DPFLTR_INFO_LEVEL,"WMI: SMBIOS System Eventlog struture %p size is %x, but expecting %x\n",
SystemEventlog,
SystemEventlog->Length,
(LogTypeDescLength +
FIELD_OFFSET(SMBIOS_SYSTEM_EVENTLOG_STRUCT,
LogTypeDescriptor)) ));
WmipAssert(FALSE);
WmipUnmapSMBiosStructure(MapAddress, MapSize);
Status = STATUS_UNSUCCESSFUL;
return(Status);
}
} else {
LogTypeDescLength = 0;
LogHeaderDescExists = 0;
}
SizeNeeded = FIELD_OFFSET(SMBIOS_EVENTLOG_INFO, VariableData) +
LogTypeDescLength +
LogAreaLength;
if (*BufferSize >= SizeNeeded)
{
EventlogInfo = (PSMBIOS_EVENTLOG_INFO)Buffer;
EventlogInfo->LogTypeDescLength = LogTypeDescLength;
EventlogInfo->LogHeaderDescExists = LogHeaderDescExists;
EventlogInfo->Reserved = 0;
EventlogArea = &EventlogInfo->VariableData[LogTypeDescLength];
if (LogHeaderDescExists == 1)
{
//
// if log header descriptors exist (smbios 2.1+) then copy
// rest of smbios header plus log type descriptors
//
RtlCopyMemory(&EventlogInfo->LogAreaLength,
&SystemEventlog->LogAreaLength,
(SystemEventlog->Length -
FIELD_OFFSET(SMBIOS_SYSTEM_EVENTLOG_STRUCT,
LogAreaLength)));
} else {
//
// if no log header descriptors then just copy smbios 2.0
// defined fields and zero out rest of structure
//
RtlCopyMemory(&EventlogInfo->LogAreaLength,
&SystemEventlog->LogAreaLength,
FIELD_OFFSET(SMBIOS_EVENTLOG_INFO, LogHeaderFormat) -
FIELD_OFFSET(SMBIOS_EVENTLOG_INFO, LogAreaLength));
*((PUSHORT)&EventlogInfo->LogHeaderFormat) = 0;
EventlogInfo->LengthEachLogTypeDesc = 0;
}
WmipUnmapSMBiosStructure(MapAddress, MapSize);
switch(AccessMethod)
{
case ACCESS_METHOD_MEMMAP:
{
//
// Eventlog is maintained in physical memory
//
PHYSICAL_ADDRESS PhysicalAddress;
PUCHAR EventlogVirtualAddress;
PhysicalAddress.HighPart = 0;
PhysicalAddress.LowPart = AccessMethodAddress.AccessMethodAddress.PhysicalAddress32;
EventlogVirtualAddress = MmMapIoSpace(PhysicalAddress,
LogAreaLength,
MmCached);
if ((EventlogArea != NULL) &&
(EventlogVirtualAddress != NULL))
{
RtlCopyMemory(EventlogArea,
EventlogVirtualAddress,
LogAreaLength);
MmUnmapIoSpace(EventlogVirtualAddress,
LogAreaLength);
Status = STATUS_SUCCESS;
} else {
Status = STATUS_UNSUCCESSFUL;
}
break;
};
case ACCESS_METHOD_INDEXIO_1:
{
// break;
};
case ACCESS_METHOD_INDEXIO_2:
{
// break;
};
case ACCESS_METHOD_INDEXIO_3:
{
// break;
};
case ACCESS_METHOD_GPNV:
{
WmipDebugPrintEx((DPFLTR_WMICORE_ID, DPFLTR_INFO_LEVEL,"WMI: SMBIOS Eventlog access method GPNV %x\n",
AccessMethod));
Status = STATUS_UNSUCCESSFUL;
break;
};
default:
{
WmipDebugPrintEx((DPFLTR_WMICORE_ID, DPFLTR_INFO_LEVEL,"WMI: SMBIOS Eventlog access method %x\n",
AccessMethod));
WmipAssert(FALSE);
Status = STATUS_UNSUCCESSFUL;
}
};
} else {
WmipUnmapSMBiosStructure(MapAddress, MapSize);
Status = STATUS_BUFFER_TOO_SMALL;
}
*BufferSize = SizeNeeded;
}
return(Status);
}
NTSTATUS
WmipDockUndockEventCallback(
IN PVOID NotificationStructure,
IN PVOID Context
)
{
PAGED_CODE();
UNREFERENCED_PARAMETER (NotificationStructure);
UNREFERENCED_PARAMETER (Context);
//
// if SMBIOS data is obtained via the table in the bios, then reset
// the flag to indicate that we need to rescan for the table. It is
// possible that a dock or undock could have changed the data. If we
// obtained the data from ntdetect then there is nothing we can do
// since we cannot call the bios.
if (WmipSMBiosTablePhysicalAddress.QuadPart != 0)
{
WmipEnterSMCritSection();
WmipSMBiosChecked = FALSE;
WmipLeaveSMCritSection();
}
return(STATUS_SUCCESS);
}
#endif
#ifdef ALLOC_DATA_PRAGMA
#pragma data_seg()
#endif