762 lines
24 KiB
C
762 lines
24 KiB
C
|
/*++
|
|||
|
|
|||
|
Copyright (c) 1990, 1991 Microsoft Corporation
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
hwpbiosc.c
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
This modules contains PnP BIOS C supporting routines
|
|||
|
|
|||
|
Author:
|
|||
|
|
|||
|
Shie-Lin Tzong (shielint) 20-Apr-1995
|
|||
|
|
|||
|
Environment:
|
|||
|
|
|||
|
Real mode.
|
|||
|
|
|||
|
Revision History:
|
|||
|
|
|||
|
Doug Fritz (dfritz) 02-Oct-1997
|
|||
|
- Add: get docking station info from PnP BIOS and pass to NTLDR
|
|||
|
|
|||
|
Alan Warwick (alanwar) 10-Feb-1998
|
|||
|
- Add: get SMBIOS tables from PnP BIOS and pass to NTLDR
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
#include "hwdetect.h"
|
|||
|
#include <string.h>
|
|||
|
#include "smbios.h"
|
|||
|
#include "pnpbios.h"
|
|||
|
|
|||
|
//
|
|||
|
// Some global variables referenced by other routines
|
|||
|
//
|
|||
|
BOOLEAN SystemHas8259 = FALSE;
|
|||
|
BOOLEAN SystemHas8253 = FALSE;
|
|||
|
|
|||
|
USHORT HwSMBIOSStructureLength(
|
|||
|
FPSMBIOS_STRUCT_HEADER StructHeader,
|
|||
|
USHORT MaxStructLen
|
|||
|
)
|
|||
|
{
|
|||
|
USHORT length;
|
|||
|
UCHAR type;
|
|||
|
FPUCHAR stringPtr;
|
|||
|
|
|||
|
type = StructHeader->Type;
|
|||
|
length = StructHeader->Length;
|
|||
|
|
|||
|
//
|
|||
|
// The length of an SMBIOS structure can be computed by adding the size
|
|||
|
// specified in the structure header plus the space used by the string
|
|||
|
// table that immediately follows the structure header. The size of the
|
|||
|
// string table is determined by scanning for a double NUL. A problem is
|
|||
|
// that those structures that do not contain strings do not have a
|
|||
|
// double NUL to indicate an empty string table. However since we do
|
|||
|
// initialize the entire buffer to 0 before calling the bios there
|
|||
|
// will always be a double nul at the end regardless of how the bios
|
|||
|
// fills writes the structure.
|
|||
|
|
|||
|
stringPtr = (FPUCHAR)StructHeader + StructHeader->Length;
|
|||
|
|
|||
|
//
|
|||
|
// Loop one byte at a time until double NUL is found
|
|||
|
while ((*((FPUSHORT)stringPtr) != 0) && (length < MaxStructLen))
|
|||
|
{
|
|||
|
stringPtr++;
|
|||
|
length++;
|
|||
|
}
|
|||
|
|
|||
|
#if DBG
|
|||
|
if (length == MaxStructLen)
|
|||
|
{
|
|||
|
BlPrint("HwSMBIOSStructureLength: structure overflow 0x%x\n", length);
|
|||
|
}
|
|||
|
#endif
|
|||
|
|
|||
|
return(length);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
USHORT HwGetSMBIOSInfo(
|
|||
|
ENTRY_POINT BiosEntry,
|
|||
|
USHORT RealModeDataBaseAddress,
|
|||
|
USHORT StructBufferSize,
|
|||
|
FPUCHAR StructBuffer
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine determine if SMBIOS information is available in the system
|
|||
|
and if so then collect the size needed for all of the information and
|
|||
|
actually collect the information.
|
|||
|
|
|||
|
The SMBIOS tables are packed into a buffer end to end. The length of each
|
|||
|
SMBIOS table is determined by the length in the structure header plus
|
|||
|
any memory used by the stirng space immediately after the fixed portion
|
|||
|
of the structure. The string space is terminated by a double NUL. However
|
|||
|
some structure types do not contain strings and thus do not have a
|
|||
|
string space so the length of the structure is simply the length specified
|
|||
|
in the structure header. However this routine will append a double NUL
|
|||
|
to those structures anyway so that the total length of each structure
|
|||
|
within the buffer can be determined by finding the first double NUL after
|
|||
|
the length declared in the structure header.
|
|||
|
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
BiosEntry is the real mode entrypoint to the PnP bios
|
|||
|
|
|||
|
RealModeDataBaseAddress
|
|||
|
|
|||
|
StructBufferSize is the maximum number of bytes available to write in
|
|||
|
StructBuffer
|
|||
|
|
|||
|
StructBuffer is the buffer in which to write the SMBIOS data. If this is
|
|||
|
NULL then only the size needed to write the data is determined.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
Size of SMBIOS structures
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
USHORT retCode;
|
|||
|
USHORT numberStructures;
|
|||
|
USHORT maxStructSize;
|
|||
|
ULONG dmiStorageBase;
|
|||
|
USHORT dmiStorageSize;
|
|||
|
UCHAR dmiBiosRevision;
|
|||
|
ULONG romAddr, romEnd;
|
|||
|
FPSMBIOS_EPS_HEADER header;
|
|||
|
FPDMIBIOS_EPS_HEADER dmiHeader;
|
|||
|
FPUCHAR current;
|
|||
|
UCHAR sum;
|
|||
|
USHORT j;
|
|||
|
USHORT structCount;
|
|||
|
USHORT structNumber;
|
|||
|
USHORT dmiStorageSegment;
|
|||
|
USHORT totalStructSize = 0;
|
|||
|
USHORT checkLength;
|
|||
|
FPSMBIOS_STRUCT_HEADER structHeader;
|
|||
|
USHORT length, lengthNeeded;
|
|||
|
FPUCHAR tempStructBuffer;
|
|||
|
|
|||
|
#if DBG
|
|||
|
BlPrint("GetSMBIOSInfo: Determining SMBIOS - Try for table\n");
|
|||
|
#endif
|
|||
|
|
|||
|
MAKE_FP(current, PNP_BIOS_START);
|
|||
|
romAddr = PNP_BIOS_START;
|
|||
|
romEnd = PNP_BIOS_END;
|
|||
|
|
|||
|
checkLength = 0;
|
|||
|
while (romAddr < romEnd) {
|
|||
|
header = (FPSMBIOS_EPS_HEADER)current;
|
|||
|
dmiHeader = (FPDMIBIOS_EPS_HEADER)current;
|
|||
|
|
|||
|
if ((dmiHeader->Signature2[0] == '_') &&
|
|||
|
(dmiHeader->Signature2[1] == 'D') &&
|
|||
|
(dmiHeader->Signature2[2] == 'M') &&
|
|||
|
(dmiHeader->Signature2[3] == 'I') &&
|
|||
|
(dmiHeader->Signature2[4] == '_')) {
|
|||
|
#if DBG
|
|||
|
BlPrint("GetSMBIOSInfo: found _DMI_ anchor string installation %lx\n",
|
|||
|
dmiHeader);
|
|||
|
#endif
|
|||
|
checkLength = sizeof(DMIBIOS_EPS_HEADER);
|
|||
|
} else if (header->Signature[0] == '_' &&
|
|||
|
header->Signature[1] == 'S' &&
|
|||
|
header->Signature[2] == 'M' &&
|
|||
|
header->Signature[3] == '_' &&
|
|||
|
header->Length >= sizeof(SMBIOS_EPS_HEADER) &&
|
|||
|
header->Signature2[0] == '_' &&
|
|||
|
header->Signature2[1] == 'D' &&
|
|||
|
header->Signature2[2] == 'M' &&
|
|||
|
header->Signature2[3] == 'I' &&
|
|||
|
header->Signature2[4] == '_' ) {
|
|||
|
#if DBG
|
|||
|
BlPrint("GetSMBIOSInfo: found _SM_ anchor string installation %lx\n",
|
|||
|
header);
|
|||
|
#endif
|
|||
|
checkLength = header->Length;
|
|||
|
dmiHeader = (FPDMIBIOS_EPS_HEADER)&header->Signature2[0];
|
|||
|
}
|
|||
|
|
|||
|
if (checkLength != 0)
|
|||
|
{
|
|||
|
sum = 0;
|
|||
|
for (j = 0; j < checkLength; j++) {
|
|||
|
sum += current[j];
|
|||
|
}
|
|||
|
|
|||
|
if (sum == 0) {
|
|||
|
break;
|
|||
|
}
|
|||
|
#if DBG
|
|||
|
BlPrint("GetSMBIOSInfo: Checksum fails\n");
|
|||
|
#endif
|
|||
|
checkLength = 0;
|
|||
|
}
|
|||
|
|
|||
|
romAddr += PNP_BIOS_HEADER_INCREMENT;
|
|||
|
MAKE_FP(current, romAddr);
|
|||
|
}
|
|||
|
|
|||
|
if (romAddr >= romEnd) {
|
|||
|
//
|
|||
|
// We could not find the table so try the calling method
|
|||
|
dmiBiosRevision = 0;
|
|||
|
numberStructures = 0;
|
|||
|
retCode = BiosEntry(GET_DMI_INFORMATION,
|
|||
|
(FPUCHAR)&dmiBiosRevision,
|
|||
|
(FPUSHORT)&numberStructures,
|
|||
|
(FPUSHORT)&maxStructSize,
|
|||
|
(FPULONG)&dmiStorageBase,
|
|||
|
(FPUSHORT)&dmiStorageSize,
|
|||
|
RealModeDataBaseAddress);
|
|||
|
|
|||
|
if ((retCode != DMI_SUCCESS) ||
|
|||
|
(dmiBiosRevision < 0x20))
|
|||
|
{
|
|||
|
#if DBG
|
|||
|
BlPrint("GetSMBIOSInfo: GET_DMI_INFORMATION failed %x\n", retCode);
|
|||
|
#endif
|
|||
|
return(0);
|
|||
|
#if DBG
|
|||
|
} else {
|
|||
|
BlPrint("GetSMBIOSInfo: GET_DMI_INFORMATION\n");
|
|||
|
BlPrint(" BiosRevision %x Number Structures %x Structure Size %x\n", dmiBiosRevision, numberStructures, maxStructSize);
|
|||
|
BlPrint(" StorageBase %lx StorageSize %x\n", dmiStorageBase, dmiStorageSize);
|
|||
|
#endif
|
|||
|
}
|
|||
|
|
|||
|
maxStructSize += 3;
|
|||
|
tempStructBuffer = HwAllocateHeap(maxStructSize, FALSE);
|
|||
|
if (tempStructBuffer == NULL)
|
|||
|
{
|
|||
|
#if DBG
|
|||
|
BlPrint("GetSMBIOSInfo: HwAllocateHeap(structureSize = 0x%x\n",
|
|||
|
maxStructSize);
|
|||
|
#endif
|
|||
|
return(0);
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Loop calling Get_DMI_STRUCTURE to get next structure until we
|
|||
|
// hit the end of structure or receive an error.
|
|||
|
structCount = 0;
|
|||
|
structNumber = 0;
|
|||
|
dmiStorageSegment = (USHORT)(dmiStorageBase >> 4);
|
|||
|
while ((structCount < numberStructures) &&
|
|||
|
(retCode == DMI_SUCCESS) &&
|
|||
|
(structNumber != 0xffff))
|
|||
|
{
|
|||
|
_fmemset(tempStructBuffer, 0, maxStructSize);
|
|||
|
retCode = BiosEntry(GET_DMI_STRUCTURE,
|
|||
|
(FPUSHORT)&structNumber,
|
|||
|
(FPUCHAR)tempStructBuffer,
|
|||
|
dmiStorageSegment,
|
|||
|
RealModeDataBaseAddress
|
|||
|
);
|
|||
|
#if DBG
|
|||
|
BlPrint("GetSMBIOSInfo: GET_DMI_STRUCTURE --> %x\n", retCode);
|
|||
|
#endif
|
|||
|
if (retCode == DMI_SUCCESS)
|
|||
|
{
|
|||
|
structCount++;
|
|||
|
structHeader = (FPSMBIOS_STRUCT_HEADER)tempStructBuffer;
|
|||
|
|
|||
|
length = HwSMBIOSStructureLength(structHeader, maxStructSize);
|
|||
|
|
|||
|
lengthNeeded = length + 2;
|
|||
|
if (StructBuffer != NULL)
|
|||
|
{
|
|||
|
//
|
|||
|
// if caller wants the data then lets copy into it buffer
|
|||
|
if (StructBufferSize >= lengthNeeded)
|
|||
|
{
|
|||
|
_fmemcpy(StructBuffer,
|
|||
|
tempStructBuffer,
|
|||
|
length);
|
|||
|
|
|||
|
*((FPUSHORT)&StructBuffer[length]) = 0;
|
|||
|
|
|||
|
StructBufferSize -= lengthNeeded;
|
|||
|
StructBuffer += lengthNeeded;
|
|||
|
totalStructSize += lengthNeeded;
|
|||
|
#if DBG
|
|||
|
} else {
|
|||
|
BlPrint("GetSMBIOSInfo: Struct too large 0x%x bytes left\n",
|
|||
|
StructBufferSize);
|
|||
|
#endif
|
|||
|
}
|
|||
|
} else {
|
|||
|
//
|
|||
|
// Caller is only interested in length required
|
|||
|
totalStructSize += lengthNeeded;
|
|||
|
}
|
|||
|
|
|||
|
#if DBG
|
|||
|
BlPrint("GetSMBIOSInfo: Number 0x%x Type 0x%x Length 0x%x/0x%x Handle 0x%x\n",
|
|||
|
structNumber,
|
|||
|
structHeader->Type,
|
|||
|
structHeader->Length,
|
|||
|
length,
|
|||
|
structHeader->Handle);
|
|||
|
for (j = 0; j < structHeader->Length; j = j + 16)
|
|||
|
{
|
|||
|
BlPrint(" %x %x %x %x %x %x %x %x\n %x %x %x %x %x %x %x %x\n",
|
|||
|
structHeader->Data[j],
|
|||
|
structHeader->Data[j+1],
|
|||
|
structHeader->Data[j+2],
|
|||
|
structHeader->Data[j+3],
|
|||
|
structHeader->Data[j+4],
|
|||
|
structHeader->Data[j+5],
|
|||
|
structHeader->Data[j+6],
|
|||
|
structHeader->Data[j+7],
|
|||
|
structHeader->Data[j+8],
|
|||
|
structHeader->Data[j+9],
|
|||
|
structHeader->Data[j+10],
|
|||
|
structHeader->Data[j+11],
|
|||
|
structHeader->Data[j+12],
|
|||
|
structHeader->Data[j+13],
|
|||
|
structHeader->Data[j+14],
|
|||
|
structHeader->Data[j]+15);
|
|||
|
}
|
|||
|
|
|||
|
for (j = structHeader->Length; j < length; j++)
|
|||
|
{
|
|||
|
BlPrint("%c", structHeader->Data[j-sizeof(SMBIOS_STRUCT_HEADER)]);
|
|||
|
if (structHeader->Data[j-sizeof(SMBIOS_STRUCT_HEADER)] == 0)
|
|||
|
{
|
|||
|
BlPrint("\n");
|
|||
|
}
|
|||
|
}
|
|||
|
BlPrint("\n");
|
|||
|
#endif
|
|||
|
}
|
|||
|
#if DBG
|
|||
|
while ( !HwGetKey() ) ; // wait until key pressed to continue
|
|||
|
#endif
|
|||
|
}
|
|||
|
HwFreeHeap(maxStructSize);
|
|||
|
#if DBG
|
|||
|
BlPrint("GetSMBIOSInfo: %x/%x structures read, total size 0x%x\n",
|
|||
|
structCount, numberStructures, totalStructSize);
|
|||
|
#endif
|
|||
|
|
|||
|
#if DBG
|
|||
|
} else {
|
|||
|
if ((FPVOID)dmiHeader != (FPVOID)header)
|
|||
|
{
|
|||
|
BlPrint("GetSMBIOSInfo: _SM_ Structure Table\n");
|
|||
|
BlPrint(" Length %x MajorVersion %x MinorVersion %x\n",
|
|||
|
header->Length, header->MajorVersion, header->MinorVersion);
|
|||
|
BlPrint(" MaximumStructureSize %x EntryPointRevision %x StructureTableLength %x\n",
|
|||
|
header->MaximumStructureSize, header->EntryPointRevision, header->StructureTableLength);
|
|||
|
BlPrint(" StructureTableAddress %x NumberStructures %x Revision %x\n",
|
|||
|
header->StructureTableAddress, header->NumberStructures, header->Revision);
|
|||
|
} else {
|
|||
|
BlPrint("GetSMBIOSInfo: _DMI_ Structure Table\n");
|
|||
|
BlPrint(" StructureTableLength %x\n",
|
|||
|
dmiHeader->StructureTableLength);
|
|||
|
BlPrint(" StructureTableAddress %x NumberStructures %x Revision %x\n",
|
|||
|
dmiHeader->StructureTableAddress, dmiHeader->NumberStructures, dmiHeader->Revision);
|
|||
|
}
|
|||
|
#endif
|
|||
|
}
|
|||
|
|
|||
|
#if DBG
|
|||
|
while ( !HwGetKey() ) ; // wait until key pressed to continue
|
|||
|
#endif
|
|||
|
|
|||
|
return(totalStructSize);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
#if 0
|
|||
|
VOID
|
|||
|
HwDisablePnPBiosDevnode(
|
|||
|
ENTRY_POINT biosEntry,
|
|||
|
FPPNP_BIOS_INSTALLATION_CHECK header,
|
|||
|
UCHAR node,
|
|||
|
FPPNP_BIOS_DEVICE_NODE deviceNode
|
|||
|
)
|
|||
|
{
|
|||
|
USHORT control = GET_CURRENT_CONFIGURATION;
|
|||
|
USHORT retCode;
|
|||
|
FPUCHAR buffer;
|
|||
|
USHORT i;
|
|||
|
UCHAR code;
|
|||
|
#if 0
|
|||
|
BlPrint("DisablePnPBiosDevnode: found it\n");
|
|||
|
while ( !HwGetKey() ) ; // wait until key pressed to continue
|
|||
|
|
|||
|
buffer = (FPUCHAR)deviceNode;
|
|||
|
|
|||
|
for (i = 0; i < deviceNode->Size; i++) {
|
|||
|
BlPrint("%x ", *buffer++);
|
|||
|
if ( ((i+1)%16) == 0) {
|
|||
|
BlPrint("\n");
|
|||
|
}
|
|||
|
}
|
|||
|
BlPrint("\n");
|
|||
|
#endif
|
|||
|
|
|||
|
//
|
|||
|
// Zero out allocated resources
|
|||
|
//
|
|||
|
buffer = (FPUCHAR)(deviceNode+1);
|
|||
|
|
|||
|
if (deviceNode->Size <= sizeof(PNP_BIOS_DEVICE_NODE)) {
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
for (i = 0; i < (deviceNode->Size - sizeof(PNP_BIOS_DEVICE_NODE)); i++) {
|
|||
|
|
|||
|
code = *buffer;
|
|||
|
#define PNP_BIOS_END_TAG 0x79
|
|||
|
if (code == PNP_BIOS_END_TAG) {
|
|||
|
//
|
|||
|
// found END TAG
|
|||
|
// write checksum
|
|||
|
//
|
|||
|
*(++buffer) = (UCHAR) (0 - PNP_BIOS_END_TAG);
|
|||
|
break;
|
|||
|
}
|
|||
|
*buffer++ = 0;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
#if 0
|
|||
|
buffer = (FPUCHAR)deviceNode;
|
|||
|
|
|||
|
for (i = 0; i < deviceNode->Size; i++) {
|
|||
|
BlPrint("%x ", *buffer++);
|
|||
|
if ( ((i+1)%16) == 0) {
|
|||
|
BlPrint("\n");
|
|||
|
}
|
|||
|
}
|
|||
|
BlPrint("\n");
|
|||
|
|
|||
|
while ( !HwGetKey() ) ; // wait until key pressed to continue
|
|||
|
#endif
|
|||
|
|
|||
|
retCode = biosEntry(PNP_BIOS_SET_DEVICE_NODE,
|
|||
|
node,
|
|||
|
deviceNode,
|
|||
|
control,
|
|||
|
header->RealModeDataBaseAddress
|
|||
|
);
|
|||
|
|
|||
|
#if DBG
|
|||
|
if (retCode != 0) {
|
|||
|
BlPrint("HwDisablePnPBiosDevnode: PnP Bios func 2 returns failure = %x.\n", retCode);
|
|||
|
}
|
|||
|
#endif
|
|||
|
}
|
|||
|
#endif
|
|||
|
|
|||
|
//
|
|||
|
// Global Variable within NTDETECT
|
|||
|
// - structure definition in dockinfo.h
|
|||
|
// - extern declaration in hwdetect.h
|
|||
|
// - used in hwpbios.c and hwdetect.c
|
|||
|
//
|
|||
|
|
|||
|
|
|||
|
BOOLEAN
|
|||
|
HwGetPnpBiosSystemData(
|
|||
|
IN FPUCHAR *Configuration,
|
|||
|
OUT PUSHORT PnPBiosLength,
|
|||
|
OUT PUSHORT SMBIOSLength,
|
|||
|
IN OUT FPDOCKING_STATION_INFO DockInfo
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine checks if PNP BIOS is present in the machine. If yes, it
|
|||
|
also create a registry descriptor to collect the BIOS data.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Configuration - Supplies a variable to receive the PNP BIOS data.
|
|||
|
|
|||
|
PnPBiosLength - Supplies a variable to receive the size of the PnP Bios
|
|||
|
data (Does not include HEADER)
|
|||
|
|
|||
|
SMBIOSBiosLength - Supplies a variable to receive the size of the SMBIOS
|
|||
|
data (Does not include HEADER). Total size of buffer
|
|||
|
returned is in *Configuration is (*PnPBiosLength +
|
|||
|
*SMBIOSLength + 2 * DATA_HEADER_SIZE)
|
|||
|
|
|||
|
DockInfo -
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
A value of TRUE is returned if success. Otherwise, a value of
|
|||
|
FALSE is returned.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
ULONG romAddr, romEnd;
|
|||
|
FPUCHAR current;
|
|||
|
FPPNP_BIOS_INSTALLATION_CHECK header;
|
|||
|
UCHAR sum, node = 0;
|
|||
|
UCHAR currentNode;
|
|||
|
USHORT i, totalSize = 0, nodeSize, numberNodes, retCode;
|
|||
|
ENTRY_POINT biosEntry;
|
|||
|
FPPNP_BIOS_DEVICE_NODE deviceNode;
|
|||
|
USHORT control = GET_CURRENT_CONFIGURATION;
|
|||
|
USHORT sMBIOSBufferSize;
|
|||
|
FPUCHAR sMBIOSBuffer;
|
|||
|
|
|||
|
//
|
|||
|
// Perform PNP BIOS installation Check
|
|||
|
//
|
|||
|
|
|||
|
MAKE_FP(current, PNP_BIOS_START);
|
|||
|
romAddr = PNP_BIOS_START;
|
|||
|
romEnd = PNP_BIOS_END;
|
|||
|
|
|||
|
while (romAddr < romEnd) {
|
|||
|
header = (FPPNP_BIOS_INSTALLATION_CHECK)current;
|
|||
|
if (header->Signature[0] == '$' && header->Signature[1] == 'P' &&
|
|||
|
header->Signature[2] == 'n' && header->Signature[3] == 'P' &&
|
|||
|
header->Length >= sizeof(PNP_BIOS_INSTALLATION_CHECK)) {
|
|||
|
#if DBG
|
|||
|
BlPrint("GetPnpBiosData: find Pnp installation\n");
|
|||
|
#endif
|
|||
|
sum = 0;
|
|||
|
for (i = 0; i < header->Length; i++) {
|
|||
|
sum += current[i];
|
|||
|
}
|
|||
|
if (sum == 0) {
|
|||
|
break;
|
|||
|
}
|
|||
|
#if DBG
|
|||
|
BlPrint("GetPnpBiosData: Checksum fails\n");
|
|||
|
#endif
|
|||
|
}
|
|||
|
romAddr += PNP_BIOS_HEADER_INCREMENT;
|
|||
|
MAKE_FP(current, romAddr);
|
|||
|
}
|
|||
|
if (romAddr >= romEnd) {
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
#if DBG
|
|||
|
BlPrint("PnP installation check at %lx\n", romAddr);
|
|||
|
#endif
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Determine how much space we will need and allocate heap space
|
|||
|
//
|
|||
|
|
|||
|
totalSize += sizeof(PNP_BIOS_INSTALLATION_CHECK);
|
|||
|
biosEntry = *(ENTRY_POINT far *)&header->RealModeEntryOffset;
|
|||
|
|
|||
|
//
|
|||
|
// Determine size needed for SMBIOS data
|
|||
|
sMBIOSBufferSize = HwGetSMBIOSInfo(biosEntry,
|
|||
|
header->RealModeDataBaseAddress,
|
|||
|
0,
|
|||
|
NULL);
|
|||
|
|
|||
|
if (sMBIOSBufferSize > MAXSMBIOS20SIZE)
|
|||
|
{
|
|||
|
#if DBG
|
|||
|
BlPrint("GetPnpBiosData: SMBIOS data structures are too large 0x%x bytes\n",
|
|||
|
sMBIOSBufferSize);
|
|||
|
while ( !HwGetKey() ) ; // wait until key pressed to continue
|
|||
|
#endif
|
|||
|
sMBIOSBufferSize = 0;
|
|||
|
}
|
|||
|
|
|||
|
retCode = biosEntry(PNP_BIOS_GET_NUMBER_DEVICE_NODES,
|
|||
|
(FPUSHORT)&numberNodes,
|
|||
|
(FPUSHORT)&nodeSize,
|
|||
|
header->RealModeDataBaseAddress
|
|||
|
);
|
|||
|
if (retCode != 0) {
|
|||
|
#if DBG
|
|||
|
BlPrint("GetPnpBiosData: PnP Bios GetNumberNodes func returns failure %x.\n", retCode);
|
|||
|
#endif
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
#if DBG
|
|||
|
BlPrint("GetPnpBiosData: Pnp Bios GetNumberNodes returns %x nodes\n", numberNodes);
|
|||
|
#endif
|
|||
|
deviceNode = (FPPNP_BIOS_DEVICE_NODE) HwAllocateHeap(nodeSize, FALSE);
|
|||
|
if (!deviceNode) {
|
|||
|
#if DBG
|
|||
|
BlPrint("GetPnpBiosData: Out of heap space.\n");
|
|||
|
#endif
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
while (node != 0xFF) {
|
|||
|
retCode = biosEntry(PNP_BIOS_GET_DEVICE_NODE,
|
|||
|
(FPUCHAR)&node,
|
|||
|
deviceNode,
|
|||
|
control,
|
|||
|
header->RealModeDataBaseAddress
|
|||
|
);
|
|||
|
if (retCode != 0) {
|
|||
|
#if DBG
|
|||
|
BlPrint("GetPnpBiosData: PnP Bios GetDeviceNode func returns failure = %x.\n", retCode);
|
|||
|
#endif
|
|||
|
HwFreeHeap((ULONG)nodeSize);
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
#if DBG
|
|||
|
BlPrint("GetPnpBiosData: PnpBios GetDeviceNode returns nodesize %x for node %x\n", deviceNode->Size, node);
|
|||
|
#endif
|
|||
|
totalSize += deviceNode->Size;
|
|||
|
}
|
|||
|
|
|||
|
#if DBG
|
|||
|
BlPrint("GetPnpBiosData: PnpBios total size of nodes %x\n", totalSize);
|
|||
|
#endif
|
|||
|
|
|||
|
HwFreeHeap((ULONG)nodeSize); // Free temporary buffer
|
|||
|
|
|||
|
|
|||
|
*PnPBiosLength = totalSize;
|
|||
|
*SMBIOSLength = sMBIOSBufferSize;
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Allocate enough room for 2 HWPARTIAL_RESOURCE_DESCRIPTORS (one for
|
|||
|
// PnP bios and one for SMBios) plus room to keep the data.
|
|||
|
totalSize += sMBIOSBufferSize + DATA_HEADER_SIZE + sizeof(HWPARTIAL_RESOURCE_DESCRIPTOR);
|
|||
|
current = (FPUCHAR) HwAllocateHeap(totalSize, FALSE);
|
|||
|
if (!current) {
|
|||
|
#if DBG
|
|||
|
BlPrint("GetPnpBiosData: Out of heap space.\n");
|
|||
|
#endif
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Collect PnP Bios installation check data and device node data.
|
|||
|
//
|
|||
|
|
|||
|
_fmemcpy (current + DATA_HEADER_SIZE,
|
|||
|
(FPUCHAR)header,
|
|||
|
sizeof(PNP_BIOS_INSTALLATION_CHECK)
|
|||
|
);
|
|||
|
deviceNode = (FPPNP_BIOS_DEVICE_NODE)(current + DATA_HEADER_SIZE +
|
|||
|
sizeof(PNP_BIOS_INSTALLATION_CHECK));
|
|||
|
node = 0;
|
|||
|
while (node != 0xFF) {
|
|||
|
currentNode = node;
|
|||
|
|
|||
|
retCode = biosEntry(PNP_BIOS_GET_DEVICE_NODE,
|
|||
|
(FPUCHAR)&node,
|
|||
|
deviceNode,
|
|||
|
control,
|
|||
|
header->RealModeDataBaseAddress
|
|||
|
);
|
|||
|
if (retCode != 0) {
|
|||
|
#if DBG
|
|||
|
BlPrint("GetPnpBiosData: PnP Bios func 1 returns failure = %x.\n", retCode);
|
|||
|
#endif
|
|||
|
HwFreeHeap((ULONG)totalSize);
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Record the existance of certain devices for the benefit of other
|
|||
|
// routines in ntdetect. For example, the pccard irq detection code
|
|||
|
// uses the PIC and an 8237... this insures that we actually have
|
|||
|
// those devices.
|
|||
|
//
|
|||
|
|
|||
|
if (deviceNode->ProductId == 0xd041) { // PNP0000
|
|||
|
SystemHas8259 = TRUE;
|
|||
|
} else if (deviceNode->ProductId == 0x1d041) { // PNP0100
|
|||
|
SystemHas8253 = TRUE;
|
|||
|
}
|
|||
|
|
|||
|
deviceNode = (FPPNP_BIOS_DEVICE_NODE)((FPUCHAR)deviceNode + deviceNode->Size);
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Collect SMBIOS Data, skipping over PartialDescriptor which is filled in
|
|||
|
// by the caller of this routine
|
|||
|
if (sMBIOSBufferSize != 0)
|
|||
|
{
|
|||
|
|
|||
|
sMBIOSBuffer = (FPUCHAR)deviceNode;
|
|||
|
sMBIOSBuffer += sizeof(HWPARTIAL_RESOURCE_DESCRIPTOR);
|
|||
|
retCode = HwGetSMBIOSInfo(biosEntry,
|
|||
|
header->RealModeDataBaseAddress,
|
|||
|
sMBIOSBufferSize,
|
|||
|
sMBIOSBuffer);
|
|||
|
#if DBG
|
|||
|
BlPrint("SMBIOS asked for 0x%x bytes and filled 0x%x bytes into %lx\n",
|
|||
|
sMBIOSBufferSize, retCode, sMBIOSBuffer);
|
|||
|
#endif
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
*Configuration = current;
|
|||
|
|
|||
|
//
|
|||
|
// call PnP BIOS to get docking station information
|
|||
|
//
|
|||
|
|
|||
|
DockInfo->ReturnCode = biosEntry(PNP_BIOS_GET_DOCK_INFORMATION,
|
|||
|
(FPUCHAR) DockInfo,
|
|||
|
header->RealModeDataBaseAddress
|
|||
|
);
|
|||
|
|
|||
|
#if DBG
|
|||
|
BlPrint("\npress any key to continue...\n");
|
|||
|
while ( !HwGetKey() ) ; // wait until key pressed to continue
|
|||
|
clrscrn();
|
|||
|
BlPrint("*** DockInfo - BEGIN ***\n\n");
|
|||
|
|
|||
|
BlPrint("ReturnCode= 0x%x (Other fields undefined if ReturnCode != 0)\n",
|
|||
|
DockInfo->ReturnCode
|
|||
|
);
|
|||
|
BlPrint(" 0x0000 = SUCCESS (docked)\n");
|
|||
|
BlPrint(" 0x0082 = FUNCTION_NOT_SUPPORTED\n");
|
|||
|
BlPrint(" 0x0087 = SYSTEM_NOT_DOCKED\n");
|
|||
|
BlPrint(" 0x0089 = UNABLE_TO_DETERMINE_DOCK_CAPABILITIES\n\n");
|
|||
|
|
|||
|
BlPrint("DockID = 0x%lx\n", DockInfo->DockID);
|
|||
|
BlPrint(" 0xFFFFFFFF if product has no identifier (DockID)\n\n");
|
|||
|
|
|||
|
BlPrint("SerialNumber = 0x%lx\n", DockInfo->SerialNumber);
|
|||
|
BlPrint(" 0 if docking station has no SerialNumber\n\n");
|
|||
|
|
|||
|
BlPrint("Capabilities = 0x%x\n" , DockInfo->Capabilities);
|
|||
|
BlPrint(" Bits 15:3 - reserved (0)\n");
|
|||
|
BlPrint(" Bits 2:1 - docking: 00=cold, 01=warm, 10=hot, 11=reserved\n");
|
|||
|
BlPrint(" Bit 0 - docking/undocking: 0=surprise style, 1=vcr style\n\n");
|
|||
|
|
|||
|
BlPrint("*** DockInfo - END ***\n\n");
|
|||
|
|
|||
|
BlPrint("press any key to continue...\n");
|
|||
|
while ( !HwGetKey() ) ; // wait until key pressed to continue
|
|||
|
clrscrn();
|
|||
|
#endif // DBG
|
|||
|
|
|||
|
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
|
|||
|
|