Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

pnpmap.c

Go to the documentation of this file.
00001 00002 /*++ 00003 00004 Copyright (c) 1994 Microsoft Corporation 00005 00006 Module Name: 00007 00008 pnpmap.c 00009 00010 Abstract: 00011 00012 This module contains the code that translates the device info returned from 00013 the PnP BIOS into root enumerated devices. 00014 00015 Author: 00016 00017 Robert B. Nelson (RobertN) 22-Sep-1997 00018 00019 Environment: 00020 00021 Kernel mode 00022 00023 Revision History : 00024 00025 --*/ 00026 00027 #include "iop.h" 00028 #pragma hdrstop 00029 #include "pnpcvrt.h" 00030 #include "pbios.h" 00031 00032 #if UMODETEST 00033 #undef IsNEC_98 00034 #define IsNEC_98 0 00035 #endif 00036 00037 #ifdef POOL_TAGGING 00038 #undef ExAllocatePool 00039 #define ExAllocatePool(a,b) ExAllocatePoolWithTag(a,b,'PpaM') 00040 #endif 00041 00042 // 00043 // Debugging stuff 00044 // 00045 00046 #if DBG 00047 00048 #define MAPPER_ERROR 0x00000001 00049 #define MAPPER_INFORMATION 0x00000002 00050 #define MAPPER_PNP_ID 0x00000004 00051 #define MAPPER_RESOURCES 0x00000008 00052 #define MAPPER_REGISTRY 0x00000010 00053 #define MAPPER_VERBOSE 0x00008000 00054 00055 ULONG PnPBiosMapperDebugMask = MAPPER_ERROR | 00056 // MAPPER_INFORMATION | 00057 // MAPPER_REGISTRY | 00058 // MAPPER_PNP_ID | 00059 // MAPPER_RESOURCES | 00060 // MAPPER_VERBOSE | 00061 0; 00062 00063 #define DebugPrint(X) PnPBiosDebugPrint X 00064 00065 VOID 00066 PnPBiosDebugPrint( 00067 ULONG DebugMask, 00068 PCCHAR DebugMessage, 00069 ... 00070 ); 00071 00072 #else 00073 00074 #define DebugPrint(X) 00075 00076 #endif // DBG 00077 00078 #if UMODETEST 00079 #define MULTIFUNCTION_KEY_NAME L"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\TestSystem\\MultifunctionAdapter" 00080 #define ENUMROOT_KEY_NAME L"\\Registry\\Machine\\System\\TestControlSet\\Enum\\Root" 00081 #else 00082 #define MULTIFUNCTION_KEY_NAME L"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System\\MultifunctionAdapter" 00083 #define ENUMROOT_KEY_NAME L"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\Root" 00084 #endif 00085 00086 #define BIOSINFO_KEY_NAME L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Biosinfo\\PNPBios" 00087 #define BIOSINFO_VALUE_NAME L"DisableNodes" 00088 #define DECODEINFO_VALUE_NAME L"FullDecodeChipsetOverride" 00089 00090 #define INSTANCE_ID_PREFIX L"PnPBIOS_" 00091 00092 #define DEFAULT_STRING_SIZE 80 00093 #define DEFAULT_VALUE_SIZE 80 00094 00095 #define DEFAULT_DEVICE_DESCRIPTION L"Unknown device class" 00096 00097 00098 #define EXCLUSION_ENTRY(a) { a, sizeof(a) - sizeof(UNICODE_NULL) } 00099 00100 typedef struct _EXCLUDED_PNPNODE { 00101 PWCHAR Id; 00102 ULONG IdLength; 00103 } EXCLUDED_PNPNODE, *PEXCLUDED_PNPNODE; 00104 00105 EXCLUDED_PNPNODE ExcludedDevices[] = { 00106 EXCLUSION_ENTRY(L"*PNP03"), // Keyboards 00107 EXCLUSION_ENTRY(L"*PNP0A"), // PCI Busses 00108 EXCLUSION_ENTRY(L"*PNP0E"), // PCMCIA Busses 00109 EXCLUSION_ENTRY(L"*PNP0F"), // Mice 00110 EXCLUSION_ENTRY(L"*nEC13"), // Keyboard for NEC98 00111 EXCLUSION_ENTRY(L"*nEC1E"), // PCMCIA Busses for NEC98 00112 EXCLUSION_ENTRY(L"*nEC1F"), // Mouse for NEC98 00113 EXCLUSION_ENTRY(L"*IBM3780"), // IBM Trackpoint Mouse 00114 EXCLUSION_ENTRY(L"*IBM3781") // IBM Trackpoint Mouse 00115 }; 00116 00117 #define EXCLUDED_DEVICES_COUNT (sizeof(ExcludedDevices) / sizeof(ExcludedDevices[0])) 00118 00119 EXCLUDED_PNPNODE ExcludeIfDisabled[] = { 00120 EXCLUSION_ENTRY(L"*PNP0C01"), // Motherboard resources 00121 EXCLUSION_ENTRY(L"*PNP0C02") // Motherboard resources 00122 }; 00123 00124 #define EXCLUDE_DISABLED_COUNT (sizeof(ExcludeIfDisabled) / sizeof(ExcludeIfDisabled[0])) 00125 00126 typedef struct _CLASSDATA { 00127 ULONG Value; 00128 PWCHAR Description; 00129 } CLASSDATA; 00130 00131 CLASSDATA Class1Descriptions[] = { 00132 { 0x0000, L"SCSI Controller" }, 00133 { 0x0100, L"IDE Controller" }, 00134 { 0x0200, L"Floppy Controller" }, 00135 { 0x0300, L"IPI Controller" }, 00136 { 0x0400, L"RAID Controller" }, 00137 { 0x8000, L"Other Mass Storage" } 00138 }; 00139 00140 CLASSDATA Class2Descriptions[] = { 00141 { 0x0000, L"Ethernet" }, 00142 { 0x0100, L"Token ring" }, 00143 { 0x0200, L"FDDI" }, 00144 { 0x0300, L"ATM" }, 00145 { 0x8000, L"Other network" } 00146 }; 00147 00148 CLASSDATA Class3Descriptions[] = { 00149 { 0x0000, L"VGA" }, 00150 { 0x0001, L"SVGA" }, 00151 { 0x0100, L"XGA" }, 00152 { 0x8000, L"Other display" } 00153 }; 00154 00155 CLASSDATA Class4Descriptions[] = { 00156 { 0x0000, L"Video device" }, 00157 { 0x0100, L"Audio device" }, 00158 { 0x8000, L"Other multimedia" } 00159 }; 00160 00161 CLASSDATA Class5Descriptions[] = { 00162 { 0x0000, L"RAM memory" }, 00163 { 0x0100, L"Flash memory" }, 00164 { 0x8000, L"Other memory" } 00165 }; 00166 00167 CLASSDATA Class6Descriptions[] = { 00168 { 0x0000, L"HOST / PCI" }, 00169 { 0x0100, L"PCI / ISA" }, 00170 { 0x0200, L"PCI / EISA" }, 00171 { 0x0300, L"PCI / MCA" }, 00172 { 0x0400, L"PCI / PCI" }, 00173 { 0x0500, L"PCI / PCMCIA" }, 00174 { 0x0600, L"NuBus" }, 00175 { 0x0700, L"Cardbus" }, 00176 { 0x8000, L"Other bridge" } 00177 }; 00178 00179 CLASSDATA Class7Descriptions[] = { 00180 { 0x0000, L"XT Serial" }, 00181 { 0x0001, L"16450" }, 00182 { 0x0002, L"16550" }, 00183 { 0x0100, L"Parallel output only" }, 00184 { 0x0101, L"BiDi Parallel" }, 00185 { 0x0102, L"ECP 1.x parallel" }, 00186 { 0x8000, L"Other comm" } 00187 }; 00188 00189 CLASSDATA Class8Descriptions[] = { 00190 { 0x0000, L"Generic 8259" }, 00191 { 0x0001, L"ISA PIC" }, 00192 { 0x0002, L"EISA PIC" }, 00193 { 0x0100, L"Generic 8237" }, 00194 { 0x0101, L"ISA DMA" }, 00195 { 0x0102, L"EISA DMA" }, 00196 { 0x0200, L"Generic 8254" }, 00197 { 0x0201, L"ISA timer" }, 00198 { 0x0202, L"EISA timer" }, 00199 { 0x0300, L"Generic RTC" }, 00200 { 0x0301, L"ISA RTC" }, 00201 { 0x8000, L"Other system device" } 00202 }; 00203 00204 CLASSDATA Class9Descriptions[] = { 00205 { 0x0000, L"Keyboard" }, 00206 { 0x0100, L"Digitizer" }, 00207 { 0x0200, L"Mouse" }, 00208 { 0x8000, L"Other input" } 00209 }; 00210 00211 CLASSDATA Class10Descriptions[] = { 00212 { 0x0000, L"Generic dock" }, 00213 { 0x8000, L"Other dock" }, 00214 }; 00215 00216 CLASSDATA Class11Descriptions[] = { 00217 { 0x0000, L"386" }, 00218 { 0x0100, L"486" }, 00219 { 0x0200, L"Pentium" }, 00220 { 0x1000, L"Alpha" }, 00221 { 0x4000, L"Co-processor" } 00222 }; 00223 00224 CLASSDATA Class12Descriptions[] = { 00225 { 0x0000, L"Firewire" }, 00226 { 0x0100, L"Access bus" }, 00227 { 0x0200, L"SSA" }, 00228 { 0x8000, L"Other serial bus" } 00229 }; 00230 00231 #define CLASSLIST_ENTRY(a) { a, sizeof(a) / sizeof(a[0]) } 00232 00233 struct _CLASS_DESCRIPTIONS_LIST { 00234 00235 CLASSDATA *Descriptions; 00236 ULONG Count; 00237 00238 } ClassDescriptionsList[] = { 00239 { NULL, 0 }, 00240 CLASSLIST_ENTRY( Class1Descriptions ), 00241 CLASSLIST_ENTRY( Class2Descriptions ), 00242 CLASSLIST_ENTRY( Class3Descriptions ), 00243 CLASSLIST_ENTRY( Class4Descriptions ), 00244 CLASSLIST_ENTRY( Class5Descriptions ), 00245 CLASSLIST_ENTRY( Class6Descriptions ), 00246 CLASSLIST_ENTRY( Class7Descriptions ), 00247 CLASSLIST_ENTRY( Class8Descriptions ), 00248 CLASSLIST_ENTRY( Class9Descriptions ), 00249 CLASSLIST_ENTRY( Class10Descriptions ), 00250 CLASSLIST_ENTRY( Class11Descriptions ), 00251 CLASSLIST_ENTRY( Class12Descriptions ) 00252 00253 }; 00254 00255 #define CLASSLIST_COUNT ( sizeof(ClassDescriptionsList) / sizeof(ClassDescriptionsList[0]) ) 00256 00257 typedef struct _BIOS_DEVNODE_INFO { 00258 WCHAR ProductId[10]; // '*' + 7 char ID + NUL + NUL for REG_MULTI_SZ 00259 UCHAR Handle; // BIOS Node # / Handle 00260 UCHAR TypeCode[3]; 00261 USHORT Attributes; 00262 PWSTR Replaces; // Instance ID of Root enumerated device being replaced 00263 00264 PCM_RESOURCE_LIST BootConfig; 00265 ULONG BootConfigLength; 00266 PIO_RESOURCE_REQUIREMENTS_LIST BasicConfig; 00267 ULONG BasicConfigLength; 00268 PWSTR CompatibleIDs; // REG_MULTI_SZ list of compatible IDs (including ProductId) 00269 ULONG CompatibleIDsLength; 00270 BOOLEAN FirmwareDisabled; // determined that it's disabled by firmware 00271 00272 } BIOS_DEVNODE_INFO, *PBIOS_DEVNODE_INFO; 00273 00274 NTSTATUS 00275 PbBiosResourcesToNtResources ( 00276 IN ULONG BusNumber, 00277 IN ULONG SlotNumber, 00278 IN OUT PUCHAR *BiosData, 00279 OUT PIO_RESOURCE_REQUIREMENTS_LIST *ReturnedList, 00280 OUT PULONG ReturnedLength 00281 ); 00282 00283 VOID 00284 PnPBiosExpandProductId( 00285 PUCHAR CompressedId, 00286 PWCHAR ProductIDStr 00287 ); 00288 00289 NTSTATUS 00290 PnPBiosIoResourceListToCmResourceList( 00291 IN PIO_RESOURCE_REQUIREMENTS_LIST IoResourceList, 00292 OUT PCM_RESOURCE_LIST *CmResourceList, 00293 OUT ULONG *CmResourceListSize 00294 ); 00295 00296 NTSTATUS 00297 PnPBiosExtractCompatibleIDs( 00298 IN PUCHAR *DevNodeData, 00299 IN ULONG DevNodeDataLength, 00300 OUT PWSTR *CompatibleIDs, 00301 OUT ULONG *CompatibleIDsLength 00302 ); 00303 00304 NTSTATUS 00305 PnPBiosTranslateInfo( 00306 IN VOID *BiosInfo, 00307 IN ULONG BiosInfoLength, 00308 OUT PBIOS_DEVNODE_INFO *DevNodeInfoList, 00309 OUT ULONG *NumberNodes 00310 ); 00311 00312 LONG 00313 PnPBiosFindMatchingDevNode( 00314 IN PWCHAR MapperName, 00315 IN PCM_RESOURCE_LIST ResourceList, 00316 IN PBIOS_DEVNODE_INFO DevNodeInfoList, 00317 IN ULONG NumberNodes 00318 ); 00319 00320 NTSTATUS 00321 PnPBiosEliminateDupes( 00322 IN PBIOS_DEVNODE_INFO DevNodeInfoList, 00323 IN ULONG NumberNodes 00324 ); 00325 00326 PWCHAR 00327 PnPBiosGetDescription( 00328 IN PBIOS_DEVNODE_INFO DevNodeInfoEntry 00329 ); 00330 00331 NTSTATUS 00332 PnPBiosWriteInfo( 00333 IN PBIOS_DEVNODE_INFO DevNodeInfoList, 00334 IN ULONG NumberNodes 00335 ); 00336 00337 VOID 00338 PnPBiosCopyIoDecode( 00339 IN HANDLE EnumRootKey, 00340 IN PBIOS_DEVNODE_INFO DevNodeInfo 00341 ); 00342 00343 NTSTATUS 00344 PnPBiosFreeDevNodeInfo( 00345 IN PBIOS_DEVNODE_INFO DevNodeInfoList, 00346 IN ULONG NumberNodes 00347 ); 00348 00349 NTSTATUS 00350 PnPBiosCheckForHardwareDisabled( 00351 IN PIO_RESOURCE_REQUIREMENTS_LIST IoResourceList, 00352 IN OUT PBOOLEAN Disabled 00353 ); 00354 00355 BOOLEAN 00356 PnPBiosCheckForExclusion( 00357 IN PEXCLUDED_PNPNODE ExclusionArray, 00358 IN ULONG ExclusionCount, 00359 IN PWCHAR PnpDeviceName, 00360 IN PWCHAR PnpCompatIds 00361 ); 00362 00363 NTSTATUS 00364 PnPBiosMapper( 00365 VOID 00366 ); 00367 00368 VOID 00369 PpFilterNtResource ( 00370 IN PWCHAR PnpDeviceName, 00371 PIO_RESOURCE_REQUIREMENTS_LIST ResReqList 00372 ); 00373 00374 NTSTATUS 00375 ComPortDBAdd( 00376 IN HANDLE DeviceParamKey, 00377 IN PWSTR PortName 00378 ); 00379 00380 #ifdef ALLOC_PRAGMA 00381 #pragma alloc_text(INIT, PnPBiosExpandProductId) 00382 #pragma alloc_text(INIT, PnPBiosIoResourceListToCmResourceList) 00383 #pragma alloc_text(INIT, PnPBiosExtractCompatibleIDs) 00384 #pragma alloc_text(INIT, PnPBiosTranslateInfo) 00385 #pragma alloc_text(INIT, PnPBiosFindMatchingDevNode) 00386 #pragma alloc_text(INIT, PnPBiosEliminateDupes) 00387 #pragma alloc_text(INIT, PnPBiosGetDescription) 00388 #pragma alloc_text(INIT, PnPBiosWriteInfo) 00389 #pragma alloc_text(INIT, PnPBiosCopyIoDecode) 00390 #pragma alloc_text(INIT, PnPBiosFreeDevNodeInfo) 00391 #pragma alloc_text(INIT, PnPBiosCheckForHardwareDisabled) 00392 #pragma alloc_text(INIT, PnPBiosCheckForExclusion) 00393 #pragma alloc_text(INIT, PnPBiosMapper) 00394 #pragma alloc_text(INIT, PpFilterNtResource) 00395 #pragma alloc_text(PAGE, PnPBiosGetBiosInfo) 00396 #endif 00397 00398 NTSTATUS 00399 PnPBiosGetBiosInfo( 00400 OUT PVOID *BiosInfo, 00401 OUT ULONG *BiosInfoLength 00402 ) 00403 /*++ 00404 00405 Routine Description: 00406 00407 This function retrieves the PnP BIOS info accumulated by NTDETECT.COM and 00408 placed in the registry. 00409 00410 Arguments: 00411 00412 BiosInfo - Set to a dynamically allocated block of information retrieved 00413 from the PnP BIOS by NTDETECT. This block should be freed using 00414 ExFreePool. The contents of the block are the PnP BIOS 00415 Installation Check Structure followed by the DevNode Structures reported 00416 by the BIOS. The detailed format is documented in the PnP BIOS spec. 00417 00418 BiosInfoLength - Length of the block whose address is stored in BiosInfo. 00419 00420 00421 Return Value: 00422 00423 STATUS_SUCCESS if no errors, otherwise the appropriate error. 00424 00425 --*/ 00426 { 00427 UNICODE_STRING multifunctionKeyName, biosKeyName, valueName; 00428 HANDLE multifunctionKey = NULL, biosKey = NULL; 00429 PKEY_BASIC_INFORMATION keyBasicInfo = NULL; 00430 ULONG keyBasicInfoLength; 00431 PKEY_VALUE_PARTIAL_INFORMATION valueInfo = NULL; 00432 ULONG valueInfoLength; 00433 ULONG returnedLength; 00434 00435 PCM_FULL_RESOURCE_DESCRIPTOR biosValue; 00436 00437 ULONG index; 00438 NTSTATUS status = STATUS_UNSUCCESSFUL; 00439 00440 // 00441 // The PnP BIOS info is written to one of the subkeys under 00442 // MULTIFUNCTION_KEY_NAME. The appropriate key is determined by 00443 // enumerating the subkeys and using the first one which has a value named 00444 // "Identifier" that is "PNP BIOS". 00445 // 00446 00447 RtlInitUnicodeString(&multifunctionKeyName, MULTIFUNCTION_KEY_NAME); 00448 00449 status = IopOpenRegistryKeyEx( &multifunctionKey, 00450 NULL, 00451 &multifunctionKeyName, 00452 KEY_READ 00453 ); 00454 00455 if (!NT_SUCCESS(status)) { 00456 00457 DebugPrint( (MAPPER_ERROR, 00458 "Could not open %S, status = %8.8X\n", 00459 MULTIFUNCTION_KEY_NAME, 00460 status) ); 00461 00462 return STATUS_UNSUCCESSFUL; 00463 } 00464 00465 // 00466 // Allocate memory for key names returned from ZwEnumerateKey and values 00467 // returned from ZwQueryValueKey. 00468 // 00469 keyBasicInfoLength = sizeof(KEY_BASIC_INFORMATION) + DEFAULT_STRING_SIZE; 00470 keyBasicInfo = ExAllocatePool(PagedPool, keyBasicInfoLength + sizeof(UNICODE_NULL)); 00471 00472 if (keyBasicInfo == NULL) { 00473 00474 ZwClose( multifunctionKey ); 00475 00476 return STATUS_NO_MEMORY; 00477 } 00478 00479 valueInfoLength = sizeof(KEY_VALUE_PARTIAL_INFORMATION) + DEFAULT_STRING_SIZE; 00480 valueInfo = ExAllocatePool(PagedPool, valueInfoLength); 00481 00482 if (valueInfo == NULL) { 00483 00484 ExFreePool( keyBasicInfo ); 00485 00486 ZwClose( multifunctionKey ); 00487 00488 return STATUS_NO_MEMORY; 00489 } 00490 00491 // 00492 // Enumerate each key under HKLM\HARDWARE\\DESCRIPTION\\System\\MultifunctionAdapter 00493 // to locate the one representing the PnP BIOS information. 00494 // 00495 for (index = 0; ; index++) { 00496 00497 status = ZwEnumerateKey( multifunctionKey, // handle of key to enumerate 00498 index, // index of subkey to enumerate 00499 KeyBasicInformation, 00500 keyBasicInfo, 00501 keyBasicInfoLength, 00502 &returnedLength); 00503 00504 if (!NT_SUCCESS(status)) { 00505 00506 if (status != STATUS_NO_MORE_ENTRIES) { 00507 00508 DebugPrint( (MAPPER_ERROR, 00509 "Could not enumerate under key %S, status = %8.8X\n", 00510 MULTIFUNCTION_KEY_NAME, 00511 status) ); 00512 } 00513 00514 break; 00515 } 00516 00517 // 00518 // We found a subkey, NUL terminate the name and open the subkey. 00519 // 00520 keyBasicInfo->Name[ keyBasicInfo->NameLength / 2 ] = L'\0'; 00521 00522 RtlInitUnicodeString(&biosKeyName, keyBasicInfo->Name); 00523 00524 status = IopOpenRegistryKeyEx( &biosKey, 00525 multifunctionKey, 00526 &biosKeyName, 00527 KEY_READ 00528 ); 00529 00530 if (!NT_SUCCESS(status)) { 00531 00532 DebugPrint( (MAPPER_ERROR, 00533 "Could not open registry key %S\\%S, status = %8.8X\n", 00534 MULTIFUNCTION_KEY_NAME, 00535 keyBasicInfo->Name, 00536 status) ); 00537 break; 00538 } 00539 00540 // 00541 // Now we need to check the Identifier value in the subkey to see if 00542 // it is PNP BIOS. 00543 // 00544 RtlInitUnicodeString(&valueName, L"Identifier"); 00545 00546 status = ZwQueryValueKey( biosKey, 00547 &valueName, 00548 KeyValuePartialInformation, 00549 valueInfo, 00550 valueInfoLength, 00551 &returnedLength); 00552 00553 00554 // lets see if its the PNP BIOS identifier 00555 if (NT_SUCCESS(status)) { 00556 00557 if (wcscmp((PWSTR)valueInfo->Data, L"PNP BIOS") == 0) { 00558 00559 // 00560 // We found the PnP BIOS subkey, retrieve the BIOS info which 00561 // is stored in the "Configuration Data" value. 00562 // 00563 // We'll start off with our default value buffer and increase 00564 // its size if necessary. 00565 // 00566 00567 RtlInitUnicodeString(&valueName, L"Configuration Data"); 00568 00569 status = ZwQueryValueKey( biosKey, 00570 &valueName, 00571 KeyValuePartialInformation, 00572 valueInfo, 00573 valueInfoLength, 00574 &returnedLength); 00575 00576 if (!NT_SUCCESS(status)) { 00577 00578 if (status == STATUS_BUFFER_TOO_SMALL || status == STATUS_BUFFER_OVERFLOW) { 00579 00580 // 00581 // The default buffer was too small, free it and reallocate 00582 // it to the required size. 00583 // 00584 ExFreePool( valueInfo ); 00585 00586 valueInfoLength = returnedLength; 00587 valueInfo = ExAllocatePool( PagedPool, valueInfoLength ); 00588 00589 if (valueInfo != NULL) { 00590 00591 status = ZwQueryValueKey( biosKey, 00592 &valueName, 00593 KeyValuePartialInformation, 00594 valueInfo, 00595 valueInfoLength, 00596 &returnedLength ); 00597 } else { 00598 00599 status = STATUS_NO_MEMORY; 00600 } 00601 } 00602 } 00603 00604 if (NT_SUCCESS(status)) { 00605 00606 // 00607 // We now have the PnP BIOS data but it is buried inside 00608 // the resource structures. Do some consistency checks and 00609 // then extract it into its own buffer. 00610 // 00611 00612 ASSERT(valueInfo->Type == REG_FULL_RESOURCE_DESCRIPTOR); 00613 00614 biosValue = (PCM_FULL_RESOURCE_DESCRIPTOR)valueInfo->Data; 00615 00616 // 00617 // BUGBUG - The WMI folks added another list so we should 00618 // search for the PnPBIOS one, but for now the BIOS one is 00619 // always first. 00620 // 00621 //ASSERT(biosValue->PartialResourceList.Count == 1); 00622 00623 *BiosInfoLength = biosValue->PartialResourceList.PartialDescriptors[0].u.DeviceSpecificData.DataSize; 00624 *BiosInfo = ExAllocatePool(PagedPool, *BiosInfoLength); 00625 00626 if (*BiosInfo != NULL) { 00627 00628 RtlCopyMemory( *BiosInfo, 00629 &biosValue->PartialResourceList.PartialDescriptors[1], 00630 *BiosInfoLength ); 00631 00632 status = STATUS_SUCCESS; 00633 00634 } else { 00635 00636 *BiosInfoLength = 0; 00637 00638 status = STATUS_NO_MEMORY; 00639 } 00640 00641 } else { 00642 00643 DebugPrint( (MAPPER_ERROR, 00644 "Error retrieving %S\\%S\\Configuration Data, status = %8.8X\n", 00645 MULTIFUNCTION_KEY_NAME, 00646 keyBasicInfo->Name, 00647 status) ); 00648 } 00649 00650 // 00651 // We found the PnP BIOS entry, so close the key handle and 00652 // return. 00653 // 00654 00655 ZwClose(biosKey); 00656 00657 break; 00658 } 00659 } 00660 00661 // 00662 // That wasn't it so close this handle and try the next subkey. 00663 // 00664 ZwClose(biosKey); 00665 } 00666 00667 // 00668 // Cleanup the dynamically allocated temporary buffers. 00669 // 00670 00671 if (valueInfo != NULL) { 00672 00673 ExFreePool(valueInfo); 00674 } 00675 00676 if (keyBasicInfo != NULL) { 00677 00678 ExFreePool(keyBasicInfo); 00679 } 00680 00681 ZwClose(multifunctionKey); 00682 00683 return status; 00684 } 00685 00686 VOID 00687 PnPBiosExpandProductId( 00688 PUCHAR CompressedId, 00689 PWCHAR ProductIDStr 00690 ) 00691 /*++ 00692 00693 Routine Description: 00694 00695 This function expands a PnP Device ID from the 4 byte compressed form into 00696 an 7 character unicode string. The string is then NUL terminated. 00697 00698 Arguments: 00699 00700 CompressedId - Pointer to the 4 byte compressed Device ID as defined in the 00701 PnP Specification. 00702 00703 ProductIDStr - Pointer to the 16 byte buffer in which the unicode string 00704 version of the ID is placed. 00705 00706 00707 Return Value: 00708 00709 NONE. 00710 00711 --*/ 00712 { 00713 static CHAR HexDigits[16] = "0123456789ABCDEF"; 00714 00715 ProductIDStr[0] = (CompressedId[0] >> 2) + 0x40; 00716 ProductIDStr[1] = (((CompressedId[0] & 0x03) << 3) | (CompressedId[1] >> 5)) + 0x40; 00717 ProductIDStr[2] = (CompressedId[1] & 0x1f) + 0x40; 00718 ProductIDStr[3] = HexDigits[CompressedId[2] >> 4]; 00719 ProductIDStr[4] = HexDigits[CompressedId[2] & 0x0F]; 00720 ProductIDStr[5] = HexDigits[CompressedId[3] >> 4]; 00721 ProductIDStr[6] = HexDigits[CompressedId[3] & 0x0F]; 00722 ProductIDStr[7] = 0x00; 00723 } 00724 00725 BOOLEAN 00726 PnPBiosIgnoreNode ( 00727 PWCHAR PnpID, 00728 PWCHAR excludeNodes 00729 ) 00730 { 00731 BOOLEAN bRet=FALSE; 00732 ULONG keyLen; 00733 PWCHAR pTmp; 00734 00735 ASSERT (excludeNodes); 00736 00737 // 00738 //excludeNodes is multi-sz, so walk through each one and check it. 00739 // 00740 pTmp=excludeNodes; 00741 00742 while (*pTmp != '\0') { 00743 00744 keyLen = wcslen (pTmp); 00745 00746 if (RtlCompareMemory (PnpID,pTmp,keyLen*sizeof (WCHAR)) == keyLen*sizeof (WCHAR)) { 00747 bRet=TRUE; 00748 break; 00749 } 00750 pTmp=pTmp+keyLen+1; 00751 00752 } 00753 00754 00755 return bRet; 00756 } 00757 00758 VOID 00759 PnPGetDevnodeExcludeList ( 00760 OUT PKEY_VALUE_FULL_INFORMATION *ExcludeList 00761 ) 00762 { 00763 UNICODE_STRING biosKeyName; 00764 HANDLE biosKey; 00765 NTSTATUS status; 00766 00767 RtlInitUnicodeString(&biosKeyName, BIOSINFO_KEY_NAME); 00768 status = IopOpenRegistryKeyEx( &biosKey, 00769 NULL, 00770 &biosKeyName, 00771 KEY_READ 00772 ); 00773 00774 if (!NT_SUCCESS(status)) { 00775 00776 // 00777 // Don't really need to complain, likely not there. 00778 // 00779 return; 00780 } 00781 00782 (VOID) IopGetRegistryValue (biosKey,BIOSINFO_VALUE_NAME,ExcludeList); 00783 00784 ZwClose (biosKey); 00785 } 00786 00787 BOOLEAN 00788 PnPCheckFixedIoOverrideDecodes( 00789 VOID 00790 ) 00791 { 00792 PKEY_VALUE_FULL_INFORMATION decodeFlagInfo=NULL; 00793 UNICODE_STRING biosKeyName; 00794 HANDLE biosKey; 00795 NTSTATUS status; 00796 BOOLEAN overrideDecodes = FALSE; 00797 00798 RtlInitUnicodeString(&biosKeyName, BIOSINFO_KEY_NAME); 00799 status = IopOpenRegistryKeyEx( &biosKey, 00800 NULL, 00801 &biosKeyName, 00802 KEY_READ 00803 ); 00804 00805 if (!NT_SUCCESS(status)) { 00806 00807 // 00808 // Don't really need to complain, likely not there. 00809 // 00810 return FALSE; 00811 } 00812 00813 status = IopGetRegistryValue(biosKey, DECODEINFO_VALUE_NAME, &decodeFlagInfo); 00814 00815 if (NT_SUCCESS(status)) { 00816 00817 ASSERT(decodeFlagInfo->Type == REG_DWORD); 00818 if (decodeFlagInfo->DataLength == sizeof(ULONG)) { 00819 00820 overrideDecodes = (BOOLEAN) *((PULONG) decodeFlagInfo->Name); 00821 } 00822 } 00823 00824 if (decodeFlagInfo) { 00825 00826 ExFreePool(decodeFlagInfo); 00827 } 00828 00829 ZwClose (biosKey); 00830 00831 return overrideDecodes; 00832 } 00833 00834 BOOLEAN 00835 PnPBiosCheckForExclusion( 00836 IN EXCLUDED_PNPNODE *Exclusions, 00837 IN ULONG ExclusionCount, 00838 IN PWCHAR PnpDeviceName, 00839 IN PWCHAR PnpCompatIds 00840 ) 00841 { 00842 PWCHAR idPtr; 00843 ULONG exclusionIndex; 00844 00845 for (exclusionIndex = 0; exclusionIndex < ExclusionCount; exclusionIndex++) { 00846 00847 idPtr = PnpDeviceName; 00848 00849 if (RtlCompareMemory( idPtr, 00850 Exclusions[ exclusionIndex ].Id, 00851 Exclusions[ exclusionIndex ].IdLength) != Exclusions[ exclusionIndex ].IdLength ) { 00852 00853 idPtr = PnpCompatIds; 00854 00855 if (idPtr != NULL) { 00856 00857 while (*idPtr != '\0') { 00858 00859 if (RtlCompareMemory( idPtr, 00860 Exclusions[ exclusionIndex ].Id, 00861 Exclusions[ exclusionIndex ].IdLength) == Exclusions[ exclusionIndex ].IdLength ) { 00862 00863 break; 00864 } 00865 00866 idPtr += 9; 00867 } 00868 00869 if (*idPtr == '\0') { 00870 00871 idPtr = NULL; 00872 } 00873 } 00874 } 00875 00876 if (idPtr != NULL) { 00877 00878 break; 00879 } 00880 } 00881 00882 if (exclusionIndex < ExclusionCount) { 00883 return TRUE; 00884 } 00885 00886 return FALSE; 00887 } 00888 00889 NTSTATUS 00890 PnPBiosIoResourceListToCmResourceList( 00891 IN PIO_RESOURCE_REQUIREMENTS_LIST IoResourceList, 00892 OUT PCM_RESOURCE_LIST *CmResourceList, 00893 OUT ULONG *CmResourceListSize 00894 ) 00895 /*++ 00896 00897 Routine Description: 00898 00899 Converts an IO_RESOURCE_REQUIREMENTS_LIST into a CM_RESOURCE_LIST. This 00900 routine is used to convert the list of resources currently being used by a 00901 device into a form suitable for writing to the BootConfig registry value. 00902 00903 Arguments: 00904 00905 IoResourceList - Pointer to the input list. 00906 00907 CmResourceList - Pointer to a PCM_RESOURCE_LIST which is set to the 00908 dynamically allocated and filled in using the data from IoResourceList. 00909 00910 CmResourceListSize - Pointer to a variable which is set to the size in bytes 00911 of the dynamically allocated *CmResourceList. 00912 00913 Return Value: 00914 00915 STATUS_SUCCESS if no errors, otherwise the appropriate error. 00916 00917 --*/ 00918 { 00919 PCM_PARTIAL_RESOURCE_LIST partialList; 00920 PCM_PARTIAL_RESOURCE_DESCRIPTOR partialDescriptor; 00921 PIO_RESOURCE_DESCRIPTOR ioDescriptor; 00922 ULONG descIndex; 00923 00924 // 00925 // Since this routine is only used to translate the allocated resources 00926 // returned by the PnP BIOS, we can assume that there is only 1 alternative 00927 // list 00928 // 00929 00930 ASSERT(IoResourceList->AlternativeLists == 1); 00931 00932 // 00933 // Calculate the size of the translated list and allocate memory for it. 00934 // 00935 *CmResourceListSize = sizeof(CM_RESOURCE_LIST) + 00936 (IoResourceList->AlternativeLists - 1) * sizeof(CM_FULL_RESOURCE_DESCRIPTOR) + 00937 (IoResourceList->List[0].Count - 1) * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR); 00938 00939 *CmResourceList = ExAllocatePool( PagedPool, *CmResourceListSize ); 00940 00941 if (*CmResourceList == NULL) { 00942 00943 *CmResourceListSize = 0; 00944 00945 return STATUS_NO_MEMORY; 00946 } 00947 00948 // 00949 // Copy the header info from the requirements list to the resource list. 00950 // 00951 (*CmResourceList)->Count = 1; 00952 00953 (*CmResourceList)->List[ 0 ].InterfaceType = IoResourceList->InterfaceType; 00954 (*CmResourceList)->List[ 0 ].BusNumber = IoResourceList->BusNumber; 00955 00956 partialList = &(*CmResourceList)->List[ 0 ].PartialResourceList; 00957 00958 partialList->Version = IoResourceList->List[ 0 ].Version; 00959 partialList->Revision = IoResourceList->List[ 0 ].Revision; 00960 partialList->Count = 0; 00961 00962 // 00963 // Translate each resource descriptor, currently we only handle ports, 00964 // memory, interrupts, and dma. The current implementation of the routine 00965 // which converts from ISA PnP Resource data to IO_RESOURCE_REQUIREMENTS 00966 // won't generate any other descriptor types given the data returned from 00967 // the BIOS. 00968 // 00969 00970 partialDescriptor = &partialList->PartialDescriptors[ 0 ]; 00971 for (descIndex = 0; descIndex < IoResourceList->List[ 0 ].Count; descIndex++) { 00972 00973 ioDescriptor = &IoResourceList->List[ 0 ].Descriptors[ descIndex ]; 00974 00975 switch (ioDescriptor->Type) { 00976 00977 case CmResourceTypePort: 00978 partialDescriptor->u.Port.Start = ioDescriptor->u.Port.MinimumAddress; 00979 partialDescriptor->u.Port.Length = ioDescriptor->u.Port.Length; 00980 break; 00981 00982 case CmResourceTypeInterrupt: 00983 if (ioDescriptor->u.Interrupt.MinimumVector == (ULONG)(IsNEC_98 ? 7 : 2) ) { 00984 *CmResourceListSize -= sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR); 00985 continue; 00986 } 00987 partialDescriptor->u.Interrupt.Level = ioDescriptor->u.Interrupt.MinimumVector; 00988 partialDescriptor->u.Interrupt.Vector = ioDescriptor->u.Interrupt.MinimumVector; 00989 partialDescriptor->u.Interrupt.Affinity = ~0; 00990 break; 00991 00992 case CmResourceTypeMemory: 00993 partialDescriptor->u.Memory.Start = ioDescriptor->u.Memory.MinimumAddress; 00994 partialDescriptor->u.Memory.Length = ioDescriptor->u.Memory.Length; 00995 break; 00996 00997 case CmResourceTypeDma: 00998 partialDescriptor->u.Dma.Channel = ioDescriptor->u.Dma.MinimumChannel; 00999 partialDescriptor->u.Dma.Port = 0; 01000 partialDescriptor->u.Dma.Reserved1 = 0; 01001 break; 01002 01003 default: 01004 DebugPrint( (MAPPER_ERROR, 01005 "Unexpected ResourceType (%d) in I/O Descriptor\n", 01006 ioDescriptor->Type) ); 01007 01008 #if DBG 01009 // DbgBreakPoint(); 01010 #endif 01011 break; 01012 } 01013 01014 partialDescriptor->Type = ioDescriptor->Type; 01015 partialDescriptor->ShareDisposition = ioDescriptor->ShareDisposition; 01016 partialDescriptor->Flags = ioDescriptor->Flags; 01017 partialDescriptor++; 01018 01019 partialList->Count++; 01020 } 01021 01022 return STATUS_SUCCESS; 01023 } 01024 01025 NTSTATUS 01026 PnPBiosExtractCompatibleIDs( 01027 IN PUCHAR *DevNodeData, 01028 IN ULONG DevNodeDataLength, 01029 OUT PWSTR *CompatibleIDs, 01030 OUT ULONG *CompatibleIDsLength 01031 ) 01032 { 01033 PWCHAR idPtr; 01034 PUCHAR currentPtr, endPtr; 01035 UCHAR tagName; 01036 ULONG increment; 01037 ULONG compatibleCount; 01038 01039 endPtr = &(*DevNodeData)[DevNodeDataLength]; 01040 01041 compatibleCount = 0; 01042 01043 for (currentPtr = *DevNodeData; currentPtr < endPtr; currentPtr += increment) { 01044 01045 tagName = *currentPtr; 01046 01047 if (tagName == TAG_COMPLETE_END) { 01048 01049 break; 01050 } 01051 01052 // 01053 // Determine the size of the BIOS resource descriptor 01054 // 01055 01056 if (!(tagName & LARGE_RESOURCE_TAG)) { 01057 increment = (USHORT)(tagName & SMALL_TAG_SIZE_MASK); 01058 increment++; // length of small tag 01059 tagName &= SMALL_TAG_MASK; 01060 } else { 01061 increment = *(USHORT UNALIGNED *)(&currentPtr[1]); 01062 increment += 3; // length of large tag 01063 } 01064 01065 if (tagName == TAG_COMPATIBLE_ID) { 01066 01067 compatibleCount++; 01068 } 01069 } 01070 01071 if (compatibleCount == 0) { 01072 *CompatibleIDs = NULL; 01073 *CompatibleIDsLength = 0; 01074 01075 return STATUS_SUCCESS; 01076 } 01077 01078 *CompatibleIDsLength = (compatibleCount * 9 + 1) * sizeof(WCHAR); 01079 *CompatibleIDs = ExAllocatePool(PagedPool, *CompatibleIDsLength); 01080 01081 if (*CompatibleIDs == NULL) { 01082 01083 *CompatibleIDsLength = 0; 01084 return STATUS_NO_MEMORY; 01085 } 01086 01087 idPtr = *CompatibleIDs; 01088 01089 for (currentPtr = *DevNodeData; currentPtr < endPtr; currentPtr += increment) { 01090 01091 tagName = *currentPtr; 01092 01093 if (tagName == TAG_COMPLETE_END) { 01094 01095 break; 01096 } 01097 01098 // 01099 // Determine the size of the BIOS resource descriptor 01100 // 01101 01102 if (!(tagName & LARGE_RESOURCE_TAG)) { 01103 increment = (USHORT)(tagName & SMALL_TAG_SIZE_MASK); 01104 increment++; // length of small tag 01105 tagName &= SMALL_TAG_MASK; 01106 } else { 01107 increment = *(USHORT UNALIGNED *)(&currentPtr[1]); 01108 increment += 3; // length of large tag 01109 } 01110 01111 if (tagName == TAG_COMPATIBLE_ID) { 01112 01113 *idPtr = '*'; 01114 PnPBiosExpandProductId(&currentPtr[1], &idPtr[1]); 01115 idPtr += 9; 01116 } 01117 } 01118 01119 *idPtr++ = '\0'; // Extra NUL for REG_MULTI_SZ 01120 *CompatibleIDsLength = (ULONG)(idPtr - *CompatibleIDs) * sizeof(WCHAR); 01121 01122 return STATUS_SUCCESS; 01123 } 01124 01125 NTSTATUS 01126 PnPBiosTranslateInfo( 01127 IN VOID *BiosInfo, 01128 IN ULONG BiosInfoLength, 01129 OUT PBIOS_DEVNODE_INFO *DevNodeInfoList, 01130 OUT ULONG *NumberNodes 01131 ) 01132 /*++ 01133 01134 Routine Description: 01135 01136 Translates the devnode info retrieved from the BIOS. 01137 01138 Arguments: 01139 01140 BiosInfo - The PnP BIOS Installation Check Structure followed by the 01141 DevNode Structures reported by the BIOS. The detailed format is 01142 documented in the PnP BIOS spec. 01143 01144 BiosInfoLength - Length in bytes of the block whose address is stored in 01145 BiosInfo. 01146 01147 DevNodeInfoList - Dynamically allocated array of BIOS_DEVNODE_INFO 01148 structures, one for each device reported by the BIOS. The information 01149 supplied by the BIOS: device ID, type, current resources, and supported 01150 configurations is converted into a more useful format. For example the 01151 current resource allocation is converted from ISA PnP descriptors into 01152 an IO_RESOURCE_REQUIREMENTS_LIST and then into a CM_RESOURCE_LIST for 01153 storing into the BootConfig registry value. 01154 01155 NumberNodes - Number of BIOS_DEVNODE_INFO elements pointed to by 01156 DevNodeInfoList. 01157 01158 Return Value: 01159 01160 STATUS_SUCCESS if no errors, otherwise the appropriate error. 01161 01162 --*/ 01163 { 01164 PCM_PNP_BIOS_INSTALLATION_CHECK biosInstallCheck; 01165 PCM_PNP_BIOS_DEVICE_NODE devNodeHeader; 01166 PBIOS_DEVNODE_INFO devNodeInfo; 01167 PKEY_VALUE_FULL_INFORMATION excludeList=NULL; 01168 01169 PIO_RESOURCE_REQUIREMENTS_LIST tempResReqList; 01170 01171 PUCHAR currentPtr; 01172 LONG lengthRemaining; 01173 01174 LONG remainingNodeLength; 01175 01176 ULONG numNodes; 01177 ULONG nodeIndex; 01178 PUCHAR configPtr; 01179 ULONG configListLength; 01180 NTSTATUS status; 01181 ULONG convertFlags = 0; 01182 01183 // 01184 // Make sure the data is at least large enough to hold the BIOS Installation 01185 // Check structure and check that the PnP signature is correct. 01186 // 01187 if (BiosInfoLength < sizeof(CM_PNP_BIOS_INSTALLATION_CHECK)) { 01188 01189 DebugPrint( (MAPPER_ERROR, 01190 "BiosInfoLength (%d) is smaller than sizeof(PNPBIOS_INSTALLATION_CHECK) (%d)\n", 01191 BiosInfoLength, 01192 sizeof(CM_PNP_BIOS_INSTALLATION_CHECK)) ); 01193 01194 return STATUS_UNSUCCESSFUL; 01195 } 01196 01197 biosInstallCheck = (PCM_PNP_BIOS_INSTALLATION_CHECK)BiosInfo; 01198 01199 if (biosInstallCheck->Signature[0] != '$' || 01200 biosInstallCheck->Signature[1] != 'P' || 01201 biosInstallCheck->Signature[2] != 'n' || 01202 biosInstallCheck->Signature[3] != 'P') { 01203 01204 return STATUS_UNSUCCESSFUL; 01205 } 01206 01207 // 01208 // First scan the data and count the devnodes to determine the size of our 01209 // allocated data structures. 01210 // 01211 currentPtr = (PUCHAR)BiosInfo + biosInstallCheck->Length; 01212 lengthRemaining = BiosInfoLength - biosInstallCheck->Length; 01213 01214 for (numNodes = 0; lengthRemaining > sizeof(CM_PNP_BIOS_DEVICE_NODE); numNodes++) { 01215 01216 devNodeHeader = (PCM_PNP_BIOS_DEVICE_NODE)currentPtr; 01217 01218 if (devNodeHeader->Size > lengthRemaining) { 01219 01220 DebugPrint( (MAPPER_ERROR, 01221 "Node # %d, invalid size (%d), length remaining (%d)\n", 01222 devNodeHeader->Node, 01223 devNodeHeader->Size, 01224 lengthRemaining) ); 01225 01226 return STATUS_UNSUCCESSFUL; 01227 } 01228 01229 currentPtr += devNodeHeader->Size; 01230 lengthRemaining -= devNodeHeader->Size; 01231 } 01232 01233 // 01234 // Allocate the list of translated devnodes. 01235 // 01236 devNodeInfo = ExAllocatePool( PagedPool, numNodes * sizeof(BIOS_DEVNODE_INFO) ); 01237 01238 if (devNodeInfo == NULL) { 01239 01240 return STATUS_NO_MEMORY; 01241 } 01242 01243 // 01244 // Should we force all fixed IO decodes to 16bit? 01245 // 01246 if (PnPCheckFixedIoOverrideDecodes()) { 01247 01248 convertFlags |= PPCONVERTFLAG_FORCE_FIXED_IO_16BIT_DECODE; 01249 } 01250 01251 // 01252 // Now scan the data translating the info for each devnode into an entry in 01253 // our devNodeInfo array. 01254 // 01255 01256 currentPtr = (PUCHAR)BiosInfo + biosInstallCheck->Length; 01257 lengthRemaining = BiosInfoLength - biosInstallCheck->Length; 01258 01259 for (nodeIndex = 0; nodeIndex < numNodes; nodeIndex++) { 01260 01261 devNodeHeader = (PCM_PNP_BIOS_DEVICE_NODE)currentPtr; 01262 01263 if (devNodeHeader->Size > lengthRemaining) { 01264 01265 DebugPrint( (MAPPER_ERROR, 01266 "Node # %d, invalid size (%d), length remaining (%d)\n", 01267 devNodeHeader->Node, 01268 devNodeHeader->Size, 01269 lengthRemaining) ); 01270 01271 break; 01272 } 01273 01274 // 01275 // We use the Product ID field as the DeviceID key name. So we insert 01276 // an initial asterisk so we don't have to copy and mangle it later. 01277 // 01278 devNodeInfo[nodeIndex].ProductId[0] = '*'; 01279 01280 PnPBiosExpandProductId((PUCHAR)&devNodeHeader->ProductId, &devNodeInfo[nodeIndex].ProductId[1]); 01281 01282 devNodeInfo[nodeIndex].ProductId[9] = '\0'; // Extra NUL for REG_MULTI_SZ 01283 01284 // 01285 // The handle is used as part of the Instance ID 01286 devNodeInfo[nodeIndex].Handle = devNodeHeader->Node; 01287 01288 // 01289 // The type code and attributes aren't currently used but are copied 01290 // for completeness. 01291 // 01292 RtlCopyMemory( &devNodeInfo[nodeIndex].TypeCode, 01293 devNodeHeader->DeviceType, 01294 sizeof(devNodeInfo[nodeIndex].TypeCode) ); 01295 01296 devNodeInfo[nodeIndex].Attributes = devNodeHeader->DeviceAttributes; 01297 01298 // 01299 // Replaces will eventually be set to the path of the Firmware 01300 // Enumerated devnode which duplicates this one (if a duplicate exists). 01301 // 01302 devNodeInfo[nodeIndex].Replaces = NULL; 01303 01304 // 01305 // CompatibleIDs will be set to the list of compatible IDs. 01306 // 01307 devNodeInfo[nodeIndex].CompatibleIDs = NULL; 01308 01309 // 01310 // Convert the allocated resources from ISA PnP resource descriptor 01311 // format to an IO_RESOURCE_REQUIREMENTS_LIST. 01312 // 01313 configPtr = currentPtr + sizeof(*devNodeHeader); 01314 remainingNodeLength = devNodeHeader->Size - sizeof(*devNodeHeader); 01315 01316 devNodeInfo[nodeIndex].BootConfig = NULL; 01317 devNodeInfo[nodeIndex].FirmwareDisabled = FALSE; 01318 01319 status = PpBiosResourcesToNtResources( 0, /* BusNumber */ 01320 0, /* SlotNumber */ 01321 &configPtr, /* BiosData */ 01322 convertFlags, /* ConvertFlags */ 01323 &tempResReqList, /* ReturnedList */ 01324 &configListLength); /* ReturnedLength */ 01325 01326 remainingNodeLength = devNodeHeader->Size - (LONG)(configPtr - (PUCHAR)devNodeHeader); 01327 01328 if (NT_SUCCESS( status )) { 01329 01330 if (tempResReqList != NULL) { 01331 01332 PpFilterNtResource ( 01333 devNodeInfo[nodeIndex].ProductId, 01334 tempResReqList 01335 ); 01336 01337 // 01338 // Now we need to convert from a IO_RESOURCE_REQUIREMENTS_LIST to a 01339 // CM_RESOURCE_LIST. 01340 // 01341 status = PnPBiosIoResourceListToCmResourceList( tempResReqList, 01342 &devNodeInfo[nodeIndex].BootConfig, 01343 &devNodeInfo[nodeIndex].BootConfigLength ); 01344 01345 status = PnPBiosCheckForHardwareDisabled(tempResReqList,&devNodeInfo[nodeIndex].FirmwareDisabled); 01346 01347 ExFreePool( tempResReqList ); 01348 01349 } 01350 01351 } else { 01352 01353 DebugPrint( (MAPPER_ERROR, 01354 "Error converting allocated resources for devnode # %d, status = %8.8X\n", 01355 devNodeInfo[nodeIndex].Handle, 01356 status) ); 01357 } 01358 01359 // 01360 // Convert the supported resource configurations from ISA PnP resource 01361 // descriptor format to an IO_RESOURCE_REQUIREMENTS_LIST. 01362 // 01363 status = PpBiosResourcesToNtResources( 0, /* BusNumber */ 01364 0, /* SlotNumber */ 01365 &configPtr, /* BiosData */ 01366 convertFlags | PPCONVERTFLAG_SET_RESTART_LCPRI, /* ConvertFlags */ 01367 &devNodeInfo[nodeIndex].BasicConfig, /* ReturnedList */ 01368 &devNodeInfo[nodeIndex].BasicConfigLength ); /* ReturnedLength */ 01369 01370 remainingNodeLength = devNodeHeader->Size - (LONG)(configPtr - (PUCHAR)devNodeHeader); 01371 01372 if (!NT_SUCCESS( status )) { 01373 01374 devNodeInfo[nodeIndex].BasicConfig = NULL; 01375 01376 DebugPrint( (MAPPER_ERROR, 01377 "Error converting allowed resources for devnode # %d, status = %8.8X\n", 01378 devNodeInfo[nodeIndex].Handle, 01379 status) ); 01380 } else { 01381 01382 PpFilterNtResource ( 01383 devNodeInfo[nodeIndex].ProductId, 01384 devNodeInfo[nodeIndex].BasicConfig 01385 ); 01386 } 01387 01388 // 01389 // Convert the list of compatible IDs if present 01390 // 01391 01392 ASSERT(remainingNodeLength >= 0); 01393 01394 status = PnPBiosExtractCompatibleIDs( &configPtr, // BiosData 01395 (ULONG)remainingNodeLength, 01396 &devNodeInfo[nodeIndex].CompatibleIDs, 01397 &devNodeInfo[nodeIndex].CompatibleIDsLength ); 01398 01399 currentPtr += devNodeHeader->Size; 01400 lengthRemaining -= devNodeHeader->Size; 01401 01402 } 01403 01404 *DevNodeInfoList = devNodeInfo; 01405 *NumberNodes = numNodes; 01406 return STATUS_SUCCESS; 01407 } 01408 01409 LONG 01410 PnPBiosFindMatchingDevNode( 01411 IN PWCHAR MapperName, 01412 IN PCM_RESOURCE_LIST ResourceList, 01413 IN PBIOS_DEVNODE_INFO DevNodeInfoList, 01414 IN ULONG NumberNodes 01415 ) 01416 /*++ 01417 01418 Routine Description: 01419 01420 Given a list of resources this routine finds an entry in the 01421 DevNodeInfoList whose BootConfig resources match. A match is defined as 01422 having at least overlapping I/O Ports or Memory Ranges. If ResourceList doesn't 01423 include any I/O Ports or Memory Ranges then a match is defined as exactly 01424 the same interrupts and/or DMA channels. 01425 01426 This routine is used to find PnP BIOS reported devices which match devices 01427 created by the Firmware Mapper. 01428 01429 Arguments: 01430 01431 ResourceList - Pointer to CM_RESOURCE_LIST describing the resources 01432 currently used by the device for which a match is being searched. 01433 01434 DevNodeInfoList - Array of BIOS_DEVNODE_INFO structures, one for each device 01435 reported by the BIOS. 01436 01437 NumberNodes - Number of BIOS_DEVNODE_INFO elements pointed to by 01438 DevNodeInfoList. 01439 01440 01441 Return Value: 01442 01443 Index of the entry in DevNodeInfoList whose BootConfig matches the resources 01444 listed in ResourceList. If no matching entry is found then -1 is returned. 01445 01446 --*/ 01447 { 01448 PCM_PARTIAL_RESOURCE_LIST sourceList; 01449 PCM_PARTIAL_RESOURCE_LIST targetList; 01450 PCM_PARTIAL_RESOURCE_DESCRIPTOR sourceDescriptor; 01451 PCM_PARTIAL_RESOURCE_DESCRIPTOR targetDescriptor; 01452 ULONG nodeIndex, sourceIndex, targetIndex; 01453 LONG firstMatch = -1; 01454 LONG bestMatch = -1; 01455 ULONG numResourcesMatch; 01456 ULONG score, possibleScore, bestScore = 0; 01457 PWCHAR idPtr; 01458 BOOLEAN idsMatch; 01459 BOOLEAN bestIdsMatch = FALSE; 01460 01461 #if DEBUG_DUP_MATCH 01462 CHAR sourceMapping[256]; 01463 CHAR targetMapping[256]; 01464 #endif 01465 01466 // 01467 // In order to simplify the problem we assume there is only one list. This 01468 // assumption holds true in the BootConfig structures generated by the 01469 // current firmware mapper. 01470 // 01471 ASSERT( ResourceList->Count == 1 ); 01472 01473 sourceList = &ResourceList->List[0].PartialResourceList; 01474 01475 #if DEBUG_DUP_MATCH 01476 // 01477 // For debugging purposes we keep track of which resource entries map to 01478 // each other. These relationships are stored in a fixed CHAR array, thus 01479 // the restriction on the number of descriptors. 01480 // 01481 ASSERT( sourceList->Count < 255 ); 01482 #endif 01483 01484 // 01485 // Loop through each devnode and try and match it to the source resource 01486 // list. 01487 // 01488 for (nodeIndex = 0; nodeIndex < NumberNodes; nodeIndex++) { 01489 01490 if (DevNodeInfoList[ nodeIndex ].BootConfig == NULL) { 01491 01492 continue; 01493 } 01494 01495 // 01496 // We found at least one potential match. Let's double check if 01497 // the PNP ids also match. We use a lack of ID match to disqualify 01498 // entries which don't match at least I/O ports or memory. 01499 // 01500 01501 idPtr = DevNodeInfoList[ nodeIndex ].ProductId; 01502 01503 if (RtlCompareMemory( idPtr, MapperName, 12 ) != 12) { 01504 01505 idPtr = DevNodeInfoList[ nodeIndex ].CompatibleIDs; 01506 01507 if (idPtr != NULL) { 01508 01509 while (*idPtr != '\0') { 01510 01511 if (RtlCompareMemory( idPtr, MapperName, 12 ) == 12) { 01512 01513 break; 01514 } 01515 01516 idPtr += 9; 01517 } 01518 01519 if (*idPtr == '\0') { 01520 01521 idPtr = NULL; 01522 } 01523 } 01524 } 01525 01526 idsMatch = idPtr != NULL; 01527 01528 ASSERT( DevNodeInfoList[ nodeIndex ].BootConfig->Count == 1 ); 01529 01530 targetList = &DevNodeInfoList[ nodeIndex ].BootConfig->List[0].PartialResourceList; 01531 01532 #if DEBUG_DUP_MATCH 01533 RtlFillMemory( sourceMapping, sizeof(sourceMapping), -1 ); 01534 RtlFillMemory( targetMapping, sizeof(targetMapping), -1 ); 01535 #endif 01536 01537 numResourcesMatch = 0; 01538 possibleScore = 0; 01539 score = 0; 01540 01541 // 01542 // Loop through each source descriptor (resource) and try and match it 01543 // to one of this devnode's descriptors. 01544 // 01545 01546 for (sourceIndex = 0; sourceIndex < sourceList->Count; sourceIndex++) { 01547 01548 sourceDescriptor = &sourceList->PartialDescriptors[sourceIndex]; 01549 01550 // 01551 // We are recalculating the possible score unnecessarily each time 01552 // we process a devnode. We might save a small amount of time by 01553 // looping through the source descriptors once at the beginning but 01554 // its not clear it would make all that much difference given the 01555 // few devices reported by the BIOS. 01556 // 01557 01558 switch (sourceDescriptor->Type) { 01559 01560 case CmResourceTypePort: 01561 possibleScore += 0x1100; 01562 break; 01563 01564 case CmResourceTypeInterrupt: 01565 possibleScore += 0x0001; 01566 break; 01567 01568 case CmResourceTypeMemory: 01569 possibleScore += 0x1100; 01570 break; 01571 01572 case CmResourceTypeDma: 01573 possibleScore += 0x0010; 01574 break; 01575 01576 default: 01577 continue; 01578 } 01579 01580 // 01581 // Try to find a resource in the target devnode which matches the 01582 // current source resource. 01583 // 01584 for (targetIndex = 0; targetIndex < targetList->Count; targetIndex++) { 01585 01586 targetDescriptor = &targetList->PartialDescriptors[targetIndex]; 01587 01588 if (sourceDescriptor->Type == targetDescriptor->Type) { 01589 switch (sourceDescriptor->Type) { 01590 case CmResourceTypePort: 01591 if ((sourceDescriptor->u.Port.Start.LowPart + sourceDescriptor->u.Port.Length) <= 01592 targetDescriptor->u.Port.Start.LowPart || 01593 (targetDescriptor->u.Port.Start.LowPart + targetDescriptor->u.Port.Length) <= 01594 sourceDescriptor->u.Port.Start.LowPart) { 01595 continue; 01596 } 01597 if (sourceDescriptor->u.Port.Start.LowPart == 01598 targetDescriptor->u.Port.Start.LowPart && 01599 sourceDescriptor->u.Port.Length == 01600 targetDescriptor->u.Port.Length) { 01601 01602 score += 0x1100; 01603 01604 } else { 01605 01606 DebugPrint( (MAPPER_INFORMATION, 01607 "Overlapping port resources, source = %4.4X-%4.4X, target = %4.4X-%4.4X\n", 01608 sourceDescriptor->u.Port.Start.LowPart, 01609 sourceDescriptor->u.Port.Start.LowPart + sourceDescriptor->u.Port.Length - 1, 01610 targetDescriptor->u.Port.Start.LowPart, 01611 targetDescriptor->u.Port.Start.LowPart + targetDescriptor->u.Port.Length - 1) ); 01612 01613 score += 0x1000; 01614 01615 } 01616 break; 01617 01618 case CmResourceTypeInterrupt: 01619 if (sourceDescriptor->u.Interrupt.Level != 01620 targetDescriptor->u.Interrupt.Level) { 01621 continue; 01622 } 01623 score += 0x0001; 01624 break; 01625 01626 case CmResourceTypeMemory: 01627 if ((sourceDescriptor->u.Memory.Start.LowPart + sourceDescriptor->u.Memory.Length) <= 01628 targetDescriptor->u.Memory.Start.LowPart || 01629 (targetDescriptor->u.Memory.Start.LowPart + targetDescriptor->u.Memory.Length) <= 01630 sourceDescriptor->u.Memory.Start.LowPart) { 01631 01632 continue; 01633 } 01634 if (sourceDescriptor->u.Memory.Start.LowPart == 01635 targetDescriptor->u.Memory.Start.LowPart && 01636 sourceDescriptor->u.Memory.Length == 01637 targetDescriptor->u.Memory.Length) { 01638 01639 score += 0x1100; 01640 01641 } else { 01642 01643 score += 0x1000; 01644 01645 } 01646 break; 01647 01648 case CmResourceTypeDma: 01649 if (sourceDescriptor->u.Dma.Channel != 01650 targetDescriptor->u.Dma.Channel) { 01651 01652 continue; 01653 } 01654 score += 0x0010; 01655 break; 01656 01657 } 01658 break; 01659 } 01660 } 01661 01662 if (targetIndex < targetList->Count) { 01663 #if DEBUG_DUP_MATCH 01664 sourceMapping[sourceIndex] = (CHAR)targetIndex; 01665 targetMapping[targetIndex] = (CHAR)sourceIndex; 01666 #endif 01667 numResourcesMatch++; 01668 } 01669 } 01670 01671 if (numResourcesMatch != 0) { 01672 if (firstMatch == -1) { 01673 firstMatch = nodeIndex; 01674 } 01675 01676 if ((score > bestScore) || (score == bestScore && !bestIdsMatch && idsMatch)) { 01677 bestScore = score; 01678 bestMatch = nodeIndex; 01679 bestIdsMatch = idsMatch; 01680 } 01681 } 01682 } 01683 01684 if (bestMatch != -1) { 01685 01686 if (bestScore == possibleScore) { 01687 01688 DebugPrint( (MAPPER_INFORMATION, 01689 "Perfect match, score = %4.4X, possible = %4.4X, index = %d\n", 01690 bestScore, 01691 possibleScore, 01692 bestMatch) ); 01693 01694 if (possibleScore < 0x1000 && !bestIdsMatch) { 01695 01696 bestMatch = -1; 01697 01698 } 01699 01700 } else if (possibleScore > 0x1000 && bestScore >= 0x1000) { 01701 01702 DebugPrint( (MAPPER_INFORMATION, 01703 "Best match is close enough, score = %4.4X, possible = %4.4X, index = %d\n", 01704 bestScore, 01705 possibleScore, 01706 bestMatch) ); 01707 01708 } else { 01709 01710 DebugPrint( (MAPPER_INFORMATION, 01711 "Best match is less than threshold, score = %4.4X, possible = %4.4X, index = %d\n", 01712 bestScore, 01713 possibleScore, 01714 bestMatch) ); 01715 01716 bestMatch = -1; 01717 01718 } 01719 } 01720 01721 return bestMatch; 01722 } 01723 01724 NTSTATUS 01725 PnPBiosEliminateDupes( 01726 IN PBIOS_DEVNODE_INFO DevNodeInfoList, 01727 IN ULONG NumberNodes 01728 ) 01729 /*++ 01730 01731 Routine Description: 01732 01733 This routine enumerates the Firmware Mapper generated devices under 01734 Enum\Root. Those that match entries in DevNodeInfoList have their registry 01735 key name stored in the DevNodeInfoList entry so that the Firmare Mapper 01736 instance may be removed later. 01737 01738 Arguments: 01739 01740 DevNodeInfoList - Array of BIOS_DEVNODE_INFO structures, one for each device 01741 reported by the BIOS. 01742 01743 NumberNodes - Number of BIOS_DEVNODE_INFO elements pointed to by 01744 DevNodeInfoList. 01745 01746 Return Value: 01747 01748 STATUS_SUCCESS if no errors, otherwise the appropriate error. 01749 01750 --*/ 01751 { 01752 UNICODE_STRING enumRootKeyName, valueName; 01753 HANDLE enumRootKey; 01754 PKEY_BASIC_INFORMATION deviceBasicInfo = NULL; 01755 ULONG deviceBasicInfoLength; 01756 UNICODE_STRING deviceKeyName; 01757 HANDLE deviceKey = NULL; 01758 PKEY_BASIC_INFORMATION instanceBasicInfo = NULL; 01759 ULONG instanceBasicInfoLength; 01760 WCHAR logConfStr[DEFAULT_STRING_SIZE]; 01761 UNICODE_STRING logConfKeyName; 01762 HANDLE logConfKey = NULL; 01763 01764 PKEY_VALUE_PARTIAL_INFORMATION valueInfo = NULL; 01765 ULONG valueInfoLength; 01766 ULONG returnedLength; 01767 01768 ULONG deviceIndex, instanceIndex; 01769 NTSTATUS status = STATUS_UNSUCCESSFUL; 01770 01771 RtlInitUnicodeString(&enumRootKeyName, ENUMROOT_KEY_NAME); 01772 01773 status = IopOpenRegistryKeyEx( &enumRootKey, 01774 NULL, 01775 &enumRootKeyName, 01776 KEY_READ 01777 ); 01778 01779 if (!NT_SUCCESS(status)) { 01780 01781 DebugPrint( (MAPPER_ERROR, 01782 "Could not open registry key %S, status = %8.8X\n", 01783 ENUMROOT_KEY_NAME, 01784 status) ); 01785 01786 return STATUS_UNSUCCESSFUL; 01787 } 01788 01789 deviceBasicInfoLength = sizeof(KEY_BASIC_INFORMATION) + DEFAULT_STRING_SIZE; 01790 deviceBasicInfo = ExAllocatePool(PagedPool, deviceBasicInfoLength); 01791 01792 instanceBasicInfoLength = sizeof(KEY_BASIC_INFORMATION) + DEFAULT_STRING_SIZE; 01793 instanceBasicInfo = ExAllocatePool(PagedPool, instanceBasicInfoLength); 01794 01795 valueInfoLength = sizeof(KEY_VALUE_PARTIAL_INFORMATION) + DEFAULT_STRING_SIZE; 01796 valueInfo = ExAllocatePool(PagedPool, valueInfoLength); 01797 01798 if (deviceBasicInfo != NULL && instanceBasicInfo != NULL && valueInfo != NULL) { 01799 01800 for (deviceIndex = 0; ; deviceIndex++) { 01801 01802 status = ZwEnumerateKey( enumRootKey, 01803 deviceIndex, 01804 KeyBasicInformation, 01805 deviceBasicInfo, 01806 deviceBasicInfoLength, 01807 &returnedLength); 01808 01809 if (!NT_SUCCESS(status)) { 01810 01811 if (status != STATUS_NO_MORE_ENTRIES) { 01812 01813 DebugPrint( (MAPPER_ERROR, 01814 "Could not enumerate under key %S, status = %8.8X\n", 01815 ENUMROOT_KEY_NAME, 01816 status) ); 01817 } else { 01818 status = STATUS_SUCCESS; 01819 } 01820 break; 01821 } 01822 01823 if (deviceBasicInfo->Name[0] != '*') { 01824 continue; 01825 } 01826 01827 deviceBasicInfo->Name[ deviceBasicInfo->NameLength / 2 ] = L'\0'; 01828 RtlInitUnicodeString(&deviceKeyName, deviceBasicInfo->Name); 01829 01830 status = IopOpenRegistryKeyEx( &deviceKey, 01831 enumRootKey, 01832 &deviceKeyName, 01833 KEY_READ 01834 ); 01835 01836 if (!NT_SUCCESS(status)) { 01837 01838 DebugPrint( (MAPPER_ERROR, 01839 "Could not open registry key %S\\%S, status = %8.8X\n", 01840 ENUMROOT_KEY_NAME, 01841 deviceBasicInfo->Name, 01842 status) ); 01843 break; 01844 } 01845 01846 for (instanceIndex = 0; ; instanceIndex++) { 01847 01848 status = ZwEnumerateKey( deviceKey, 01849 instanceIndex, 01850 KeyBasicInformation, 01851 instanceBasicInfo, 01852 instanceBasicInfoLength, 01853 &returnedLength); 01854 01855 if (!NT_SUCCESS(status)) { 01856 01857 if (status != STATUS_NO_MORE_ENTRIES) { 01858 DebugPrint( (MAPPER_ERROR, 01859 "Could not enumerate under key %S\\%S, status = %8.8X\n", 01860 ENUMROOT_KEY_NAME, 01861 deviceBasicInfo->Name, 01862 status) ); 01863 } else { 01864 status = STATUS_SUCCESS; 01865 } 01866 break; 01867 } 01868 01869 if (RtlCompareMemory( instanceBasicInfo->Name, 01870 INSTANCE_ID_PREFIX, 01871 sizeof(INSTANCE_ID_PREFIX) - sizeof(UNICODE_NULL) 01872 ) == (sizeof(INSTANCE_ID_PREFIX) - sizeof(UNICODE_NULL))) { 01873 01874 continue; 01875 } 01876 01877 instanceBasicInfo->Name[ instanceBasicInfo->NameLength / 2 ] = L'\0'; 01878 01879 RtlCopyMemory( logConfStr, 01880 instanceBasicInfo->Name, 01881 instanceBasicInfo->NameLength ); 01882 01883 logConfStr[ instanceBasicInfo->NameLength / 2 ] = L'\\'; 01884 01885 RtlCopyMemory( &logConfStr[ instanceBasicInfo->NameLength / 2 + 1 ], 01886 REGSTR_KEY_LOGCONF, 01887 sizeof(REGSTR_KEY_LOGCONF) ); 01888 01889 RtlInitUnicodeString( &logConfKeyName, logConfStr ); 01890 01891 status = IopOpenRegistryKeyEx( &logConfKey, 01892 deviceKey, 01893 &logConfKeyName, 01894 KEY_READ 01895 ); 01896 01897 if (!NT_SUCCESS(status)) { 01898 01899 DebugPrint( (MAPPER_ERROR, 01900 "Could not open registry key %S\\%S\\%S, status = %8.8X\n", 01901 ENUMROOT_KEY_NAME, 01902 deviceBasicInfo->Name, 01903 logConfStr, 01904 status) ); 01905 continue; 01906 } 01907 01908 RtlInitUnicodeString( &valueName, REGSTR_VAL_BOOTCONFIG ); 01909 01910 status = ZwQueryValueKey( logConfKey, 01911 &valueName, 01912 KeyValuePartialInformation, 01913 valueInfo, 01914 valueInfoLength, 01915 &returnedLength ); 01916 01917 if (!NT_SUCCESS(status)) { 01918 01919 if (status == STATUS_BUFFER_TOO_SMALL || status == STATUS_BUFFER_OVERFLOW) { 01920 01921 ExFreePool( valueInfo ); 01922 01923 valueInfoLength = returnedLength; 01924 valueInfo = ExAllocatePool( PagedPool, valueInfoLength ); 01925 01926 if (valueInfo != NULL) { 01927 01928 status = ZwQueryValueKey( logConfKey, 01929 &valueName, 01930 KeyValuePartialInformation, 01931 valueInfo, 01932 valueInfoLength, 01933 &returnedLength ); 01934 } else { 01935 DebugPrint( (MAPPER_ERROR, 01936 "Error allocating memory for %S\\%S\\LogConf\\BootConfig value\n", 01937 ENUMROOT_KEY_NAME, 01938 deviceBasicInfo->Name) ); 01939 valueInfoLength = 0; 01940 status = STATUS_NO_MEMORY; 01941 01942 break; 01943 } 01944 01945 } else { 01946 DebugPrint( (MAPPER_ERROR, 01947 "Error retrieving %S\\%S\\LogConf\\BootConfig size, status = %8.8X\n", 01948 ENUMROOT_KEY_NAME, 01949 deviceBasicInfo->Name, 01950 status) ); 01951 01952 status = STATUS_UNSUCCESSFUL; 01953 } 01954 } 01955 01956 if (NT_SUCCESS( status )) { 01957 PCM_RESOURCE_LIST resourceList; 01958 LONG matchingIndex; 01959 01960 resourceList = (PCM_RESOURCE_LIST)valueInfo->Data; 01961 01962 matchingIndex = PnPBiosFindMatchingDevNode( deviceBasicInfo->Name, 01963 resourceList, 01964 DevNodeInfoList, 01965 NumberNodes ); 01966 01967 if (matchingIndex != -1) { 01968 01969 DevNodeInfoList[ matchingIndex ].Replaces = ExAllocatePool( PagedPool, 01970 deviceBasicInfo->NameLength + instanceBasicInfo->NameLength + 2 * sizeof(UNICODE_NULL)); 01971 01972 if (DevNodeInfoList[ matchingIndex ].Replaces != NULL) { 01973 01974 RtlCopyMemory( DevNodeInfoList[ matchingIndex ].Replaces, 01975 deviceBasicInfo->Name, 01976 deviceBasicInfo->NameLength ); 01977 01978 DevNodeInfoList[ matchingIndex ].Replaces[ deviceBasicInfo->NameLength / 2 ] = '\\'; 01979 01980 RtlCopyMemory( &DevNodeInfoList[ matchingIndex ].Replaces[ deviceBasicInfo->NameLength / 2 + 1 ], 01981 instanceBasicInfo->Name, 01982 instanceBasicInfo->NameLength ); 01983 01984 DevNodeInfoList[ matchingIndex ].Replaces[ (deviceBasicInfo->NameLength + instanceBasicInfo->NameLength) / 2 + 1 ] = '\0'; 01985 01986 DebugPrint( (MAPPER_INFORMATION, 01987 "Match found: %S\\%S%d replaces %S\n", 01988 DevNodeInfoList[ matchingIndex ].ProductId, 01989 INSTANCE_ID_PREFIX, 01990 DevNodeInfoList[ matchingIndex ].Handle, 01991 DevNodeInfoList[ matchingIndex ].Replaces) ); 01992 } else { 01993 DebugPrint( (MAPPER_ERROR, 01994 "Error allocating memory for %S\\%S%d\\Replaces\n", 01995 DevNodeInfoList[ matchingIndex ].ProductId, 01996 INSTANCE_ID_PREFIX, 01997 DevNodeInfoList[ matchingIndex ].Handle) ); 01998 } 01999 } else { 02000 DebugPrint( (MAPPER_INFORMATION, 02001 "No matching PnP Bios DevNode found for FW Enumerated device %S\\%S\n", 02002 deviceBasicInfo->Name, 02003 instanceBasicInfo->Name) ); 02004 } 02005 } else { 02006 DebugPrint( (MAPPER_ERROR, 02007 "Error retrieving %S\\%S\\%S\\BootConfig, status = %8.8X\n", 02008 ENUMROOT_KEY_NAME, 02009 deviceBasicInfo->Name, 02010 logConfStr, 02011 status) ); 02012 } 02013 02014 ZwClose(logConfKey); 02015 02016 logConfKey = NULL; 02017 } 02018 02019 ZwClose(deviceKey); 02020 02021 deviceKey = NULL; 02022 } 02023 } else { 02024 status = STATUS_NO_MEMORY; 02025 } 02026 02027 if (valueInfo != NULL) { 02028 ExFreePool(valueInfo); 02029 } 02030 02031 if (instanceBasicInfo != NULL) { 02032 ExFreePool(instanceBasicInfo); 02033 } 02034 02035 if (deviceBasicInfo != NULL) { 02036 ExFreePool(deviceBasicInfo); 02037 } 02038 02039 if (logConfKey != NULL) { 02040 ZwClose(logConfKey); 02041 } 02042 02043 if (deviceKey != NULL) { 02044 ZwClose(deviceKey); 02045 } 02046 02047 ZwClose(enumRootKey); 02048 02049 return status; 02050 } 02051 02052 PWCHAR 02053 PnPBiosGetDescription( 02054 IN PBIOS_DEVNODE_INFO DevNodeInfoEntry 02055 ) 02056 { 02057 ULONG class, subClass; 02058 LONG index; 02059 CLASSDATA *classDescriptions; 02060 LONG descriptionCount; 02061 02062 class = DevNodeInfoEntry->TypeCode[0]; 02063 subClass = (DevNodeInfoEntry->TypeCode[1] << 8) | DevNodeInfoEntry->TypeCode[2]; 02064 02065 if (class > 0 && class < CLASSLIST_COUNT) { 02066 02067 classDescriptions = ClassDescriptionsList[ class ].Descriptions; 02068 descriptionCount = ClassDescriptionsList[ class ].Count; 02069 02070 // 02071 // The last description entry is the default so there is no use 02072 // comparing it, if we get that far just use it. 02073 // 02074 for (index = 0; index < (descriptionCount - 1); index++) { 02075 02076 if (subClass == classDescriptions[ index ].Value) { 02077 02078 break; 02079 } 02080 } 02081 02082 return classDescriptions[ index ].Description; 02083 } 02084 02085 return DEFAULT_DEVICE_DESCRIPTION; 02086 } 02087 02088 NTSTATUS 02089 PnPBiosCopyDeviceParamKey( 02090 IN HANDLE EnumRootKey, 02091 IN PWCHAR SourcePath, 02092 IN PWCHAR DestinationPath 02093 ) 02094 /*++ 02095 02096 Routine Description: 02097 02098 Copy the Device Parameters key from the firmware mapper node in 02099 DevNodeInfo->Replaces to the BIOS mapper node represented by DevNodeInfo. 02100 02101 Arguments: 02102 02103 EnumRootKey - Handle to Enum\Root. 02104 02105 SourcePath - Instance path of FW Mapper node relative to Enum\Root. 02106 02107 DestinationKey - Handle to destination instance key. 02108 02109 Return Value: 02110 02111 STATUS_SUCCESS if no errors, otherwise the appropriate error. 02112 02113 --*/ 02114 { 02115 NTSTATUS status; 02116 UNICODE_STRING sourceInstanceKeyName; 02117 HANDLE sourceInstanceKey = NULL; 02118 02119 UNICODE_STRING deviceParamKeyName; 02120 HANDLE sourceDeviceParamKey = NULL; 02121 HANDLE destinationDeviceParamKey = NULL; 02122 UNICODE_STRING destinationInstanceKeyName; 02123 02124 PKEY_VALUE_FULL_INFORMATION valueFullInfo = NULL; 02125 ULONG valueFullInfoLength; 02126 ULONG resultLength; 02127 02128 UNICODE_STRING valueName; 02129 02130 ULONG index; 02131 02132 RtlInitUnicodeString( &sourceInstanceKeyName, SourcePath ); 02133 02134 status = IopOpenRegistryKeyEx( &sourceInstanceKey, 02135 EnumRootKey, 02136 &sourceInstanceKeyName, 02137 KEY_ALL_ACCESS 02138 ); 02139 02140 if (!NT_SUCCESS(status)) { 02141 02142 DebugPrint( (MAPPER_ERROR, 02143 "PnPBiosCopyDeviceParamKey() - Could not open source instance key %S, status = %8.8X\n", 02144 SourcePath, 02145 status) ); 02146 02147 return status; 02148 } 02149 02150 RtlInitUnicodeString(&deviceParamKeyName, REGSTR_KEY_DEVICEPARAMETERS); 02151 02152 status = IopOpenRegistryKeyEx( &sourceDeviceParamKey, 02153 sourceInstanceKey, 02154 &deviceParamKeyName, 02155 KEY_ALL_ACCESS 02156 ); 02157 02158 if (!NT_SUCCESS(status)) { 02159 02160 if (status != STATUS_OBJECT_NAME_NOT_FOUND) { 02161 02162 DebugPrint( (MAPPER_ERROR, 02163 "PnPBiosCopyDeviceParamKey() - Could not open source device parameter key %S\\%S, status = %8.8X\n", 02164 SourcePath, 02165 deviceParamKeyName.Buffer, 02166 status) ); 02167 } 02168 02169 goto Cleanup; 02170 } 02171 02172 RtlInitUnicodeString(&destinationInstanceKeyName, DestinationPath); 02173 02174 status = IopOpenDeviceParametersSubkey( &destinationDeviceParamKey, 02175 EnumRootKey, 02176 &destinationInstanceKeyName, 02177 KEY_ALL_ACCESS ); 02178 02179 if (!NT_SUCCESS(status)) { 02180 02181 DebugPrint( (MAPPER_ERROR, 02182 "PnPBiosCopyDeviceParamKey() - Could not open destination device parameter key %S\\%S, status = %8.8X\n", 02183 DestinationPath, 02184 REGSTR_KEY_DEVICEPARAMETERS, 02185 status) ); 02186 02187 goto Cleanup; 02188 } 02189 02190 valueFullInfoLength = sizeof(KEY_VALUE_FULL_INFORMATION) + DEFAULT_STRING_SIZE + DEFAULT_VALUE_SIZE; 02191 valueFullInfo = ExAllocatePool(PagedPool, valueFullInfoLength); 02192 02193 if (valueFullInfo == NULL) { 02194 02195 goto Cleanup; 02196 } 02197 02198 for (index = 0; ; index++) { 02199 status = ZwEnumerateValueKey( sourceDeviceParamKey, 02200 index, 02201 KeyValueFullInformation, 02202 valueFullInfo, 02203 valueFullInfoLength, 02204 &resultLength ); 02205 02206 if (NT_SUCCESS(status)) { 02207 UNICODE_STRING sourcePathString; 02208 UNICODE_STRING serialPrefixString; 02209 UNICODE_STRING portNameString; 02210 02211 valueName.Length = (USHORT)valueFullInfo->NameLength; 02212 valueName.MaximumLength = valueName.Length; 02213 valueName.Buffer = valueFullInfo->Name; 02214 02215 RtlInitUnicodeString(&sourcePathString, SourcePath); 02216 RtlInitUnicodeString(&serialPrefixString, L"*PNP0501"); 02217 02218 if (sourcePathString.Length > serialPrefixString.Length) { 02219 sourcePathString.Length = serialPrefixString.Length; 02220 } 02221 02222 if (RtlCompareUnicodeString(&sourcePathString, &serialPrefixString, TRUE) == 0) { 02223 02224 RtlInitUnicodeString(&portNameString, L"PortName"); 02225 02226 if (valueName.Length == 16 && 02227 RtlCompareUnicodeString(&valueName, &portNameString, TRUE) == 0) { 02228 02229 // ComPortDBRemove(SourcePath, &unicodeValue); 02230 ComPortDBAdd(destinationDeviceParamKey, (PWSTR)((PUCHAR)valueFullInfo + valueFullInfo->DataOffset)); 02231 continue; 02232 } 02233 } 02234 02235 status = ZwSetValueKey( destinationDeviceParamKey, 02236 &valueName, 02237 valueFullInfo->TitleIndex, 02238 valueFullInfo->Type, 02239 (PUCHAR)valueFullInfo + valueFullInfo->DataOffset, 02240 valueFullInfo->DataLength ); 02241 } else { 02242 if (status == STATUS_BUFFER_OVERFLOW) { 02243 ExFreePool( valueFullInfo ); 02244 02245 valueFullInfoLength = resultLength; 02246 valueFullInfo = ExAllocatePool(PagedPool, valueFullInfoLength); 02247 02248 if (valueFullInfo == NULL) { 02249 status = STATUS_NO_MEMORY; 02250 } else { 02251 index--; 02252 continue; 02253 } 02254 } else if (status != STATUS_NO_MORE_ENTRIES) { 02255 DebugPrint( (MAPPER_ERROR, 02256 "Could not enumerate under key %S\\%S, status = %8.8X\n", 02257 SourcePath, 02258 deviceParamKeyName.Buffer, 02259 status) ); 02260 } else { 02261 status = STATUS_SUCCESS; 02262 } 02263 02264 break; 02265 } 02266 } 02267 02268 Cleanup: 02269 if (sourceInstanceKey != NULL) { 02270 ZwClose( sourceInstanceKey ); 02271 } 02272 02273 if (sourceDeviceParamKey != NULL) { 02274 ZwClose( sourceDeviceParamKey ); 02275 } 02276 02277 if (destinationDeviceParamKey != NULL) { 02278 ZwClose( destinationDeviceParamKey ); 02279 } 02280 02281 if (valueFullInfo != NULL) { 02282 ExFreePool( valueFullInfo ); 02283 } 02284 02285 return status; 02286 } 02287 02288 NTSTATUS 02289 PnPBiosWriteInfo( 02290 IN PBIOS_DEVNODE_INFO DevNodeInfoList, 02291 IN ULONG NumberNodes 02292 ) 02293 /*++ 02294 02295 Routine Description: 02296 02297 Creates an entry under Enum\Root for each DevNodeInfoList element. Also 02298 removes any duplicate entries which were created by the Firmware Mapper. 02299 02300 Note: Currently entries for the Keyboard, Mouse, and PCI bus are ignored. 02301 02302 Arguments: 02303 02304 DevNodeInfoList - Array of BIOS_DEVNODE_INFO structures, one for each device 02305 reported by the BIOS. 02306 02307 NumberNodes - Number of BIOS_DEVNODE_INFO elements pointed to by 02308 DevNodeInfoList. 02309 02310 Return Value: 02311 02312 STATUS_SUCCESS if no errors, otherwise the appropriate error. 02313 02314 --*/ 02315 { 02316 PKEY_VALUE_FULL_INFORMATION excludeList=NULL; 02317 02318 UNICODE_STRING enumRootKeyName; 02319 HANDLE enumRootKey; 02320 WCHAR instanceNameStr[DEFAULT_STRING_SIZE]; 02321 UNICODE_STRING instanceKeyName; 02322 HANDLE instanceKey; 02323 UNICODE_STRING controlKeyName; 02324 HANDLE controlKey; 02325 UNICODE_STRING logConfKeyName; 02326 HANDLE logConfKey; 02327 02328 UNICODE_STRING valueName; 02329 ULONG dwordValue; 02330 ULONG disposition; 02331 02332 PWCHAR descriptionStr; 02333 ULONG descriptionStrLength; 02334 02335 ULONG nodeIndex; 02336 NTSTATUS status; 02337 02338 BOOLEAN isNewDevice; 02339 02340 RtlInitUnicodeString(&enumRootKeyName, ENUMROOT_KEY_NAME); 02341 02342 status = IopOpenRegistryKeyEx( &enumRootKey, 02343 NULL, 02344 &enumRootKeyName, 02345 KEY_ALL_ACCESS 02346 ); 02347 02348 if (!NT_SUCCESS(status)) { 02349 02350 DebugPrint( (MAPPER_ERROR, 02351 "Could not open registry key %S, status = %8.8X\n", 02352 ENUMROOT_KEY_NAME, 02353 status) ); 02354 02355 return STATUS_UNSUCCESSFUL; 02356 02357 } 02358 02359 // 02360 // Reasons why a node might be excluded (i.e not enumerated) 02361 // * included in ExcludedDevices array (non-conditional) 02362 // * included in CCS\Control\BiosInfo\PnpBios\DisableNodes via biosinfo.inf 02363 // * resources are disabled and device is included in the 02364 // ExcludeIfDisabled array 02365 02366 PnPGetDevnodeExcludeList (&excludeList); 02367 02368 for (nodeIndex = 0; nodeIndex < NumberNodes; nodeIndex++) { 02369 02370 // 02371 // Check if this node is in the 'ignore on this machine' list. 02372 // 02373 02374 if ( excludeList && 02375 PnPBiosIgnoreNode( &DevNodeInfoList[ nodeIndex ].ProductId[1], 02376 (PWCHAR)((PUCHAR)excludeList+excludeList->DataOffset))) { 02377 continue; 02378 } 02379 02380 // Checking for nodes we always exclude 02381 if ( PnPBiosCheckForExclusion( ExcludedDevices, 02382 EXCLUDED_DEVICES_COUNT, 02383 DevNodeInfoList[ nodeIndex ].ProductId, 02384 DevNodeInfoList[ nodeIndex ].CompatibleIDs)) { 02385 // 02386 // If we are skipping the device, we need to first copy the decode 02387 // info that the BIOS supplied to the ntdetected device's Boot 02388 // Config which was generated by the FW mapper. 02389 // 02390 PnPBiosCopyIoDecode( enumRootKey, &DevNodeInfoList[ nodeIndex ] ); 02391 02392 // 02393 // Skip excluded devices, ie busses, mice and keyboards for now. 02394 // 02395 02396 continue; 02397 } 02398 02399 // Checking for nodes we exclude if disabled 02400 if ( DevNodeInfoList[ nodeIndex ].FirmwareDisabled && 02401 PnPBiosCheckForExclusion( ExcludeIfDisabled, 02402 EXCLUDE_DISABLED_COUNT, 02403 DevNodeInfoList[ nodeIndex ].ProductId, 02404 NULL)) { 02405 continue; 02406 } 02407 02408 swprintf( instanceNameStr, 02409 L"%s\\%s%d", 02410 DevNodeInfoList[ nodeIndex ].ProductId, 02411 INSTANCE_ID_PREFIX, 02412 DevNodeInfoList[ nodeIndex ].Handle ); 02413 02414 RtlInitUnicodeString( &instanceKeyName, instanceNameStr ); 02415 02416 status = IopCreateRegistryKeyEx( &instanceKey, 02417 enumRootKey, 02418 &instanceKeyName, 02419 KEY_ALL_ACCESS, 02420 REG_OPTION_NON_VOLATILE, 02421 &disposition 02422 ); 02423 02424 if (NT_SUCCESS(status)) { 02425 02426 isNewDevice = disposition == REG_CREATED_NEW_KEY; 02427 02428 if (isNewDevice) { 02429 02430 RtlInitUnicodeString( &valueName, L"DeviceDesc" ); 02431 02432 descriptionStr = PnPBiosGetDescription( &DevNodeInfoList[ nodeIndex ] ); 02433 descriptionStrLength = wcslen(descriptionStr) * 2 + sizeof(UNICODE_NULL); 02434 02435 status = ZwSetValueKey( instanceKey, 02436 &valueName, 02437 0, 02438 REG_SZ, 02439 descriptionStr, 02440 descriptionStrLength ); 02441 } 02442 02443 RtlInitUnicodeString( &valueName, REGSTR_VAL_FIRMWAREIDENTIFIED ); 02444 dwordValue = 1; 02445 02446 status = ZwSetValueKey( instanceKey, 02447 &valueName, 02448 0, 02449 REG_DWORD, 02450 &dwordValue, 02451 sizeof(dwordValue) ); 02452 02453 if (isNewDevice) { 02454 02455 RtlInitUnicodeString( &valueName, L"HardwareID" ); 02456 02457 status = ZwSetValueKey( instanceKey, 02458 &valueName, 02459 0, 02460 REG_MULTI_SZ, 02461 DevNodeInfoList[ nodeIndex ].ProductId, 02462 sizeof(DevNodeInfoList[ nodeIndex ].ProductId) ); 02463 02464 if (DevNodeInfoList[ nodeIndex ].CompatibleIDs != NULL) { 02465 02466 RtlInitUnicodeString( &valueName, L"CompatibleIDs" ); 02467 02468 status = ZwSetValueKey( instanceKey, 02469 &valueName, 02470 0, 02471 REG_MULTI_SZ, 02472 DevNodeInfoList[ nodeIndex ].CompatibleIDs, 02473 DevNodeInfoList[ nodeIndex ].CompatibleIDsLength ); 02474 } 02475 } 02476 02477 RtlInitUnicodeString( &valueName, L"Replaces" ); 02478 02479 if (DevNodeInfoList[ nodeIndex ].Replaces != NULL) { 02480 02481 status = ZwSetValueKey( instanceKey, 02482 &valueName, 02483 0, 02484 REG_SZ, 02485 DevNodeInfoList[ nodeIndex ].Replaces, 02486 wcslen(DevNodeInfoList[ nodeIndex ].Replaces) * 2 + sizeof(UNICODE_NULL) ); 02487 02488 } else if (!isNewDevice) { 02489 02490 status = ZwDeleteValueKey( instanceKey, 02491 &valueName ); 02492 } 02493 02494 RtlInitUnicodeString( &controlKeyName, REGSTR_KEY_DEVICECONTROL ); 02495 02496 status = IopCreateRegistryKeyEx( &controlKey, 02497 instanceKey, 02498 &controlKeyName, 02499 KEY_ALL_ACCESS, 02500 REG_OPTION_VOLATILE, 02501 NULL 02502 ); 02503 02504 if (NT_SUCCESS(status)) { 02505 02506 RtlInitUnicodeString( &valueName, REGSTR_VAL_FIRMWAREMEMBER ); 02507 dwordValue = 1; 02508 02509 status = ZwSetValueKey( controlKey, 02510 &valueName, 02511 0, 02512 REG_DWORD, 02513 &dwordValue, 02514 sizeof(dwordValue) ); 02515 02516 RtlInitUnicodeString( &valueName, L"PnpBiosDeviceHandle" ); 02517 dwordValue = DevNodeInfoList[ nodeIndex ].Handle; 02518 02519 status = ZwSetValueKey( controlKey, 02520 &valueName, 02521 0, 02522 REG_DWORD, 02523 &dwordValue, 02524 sizeof(dwordValue) ); 02525 02526 RtlInitUnicodeString( &valueName, REGSTR_VAL_FIRMWAREDISABLED ); 02527 dwordValue = DevNodeInfoList[ nodeIndex ].FirmwareDisabled; 02528 02529 status = ZwSetValueKey( controlKey, 02530 &valueName, 02531 0, 02532 REG_DWORD, 02533 &dwordValue, 02534 sizeof(dwordValue) ); 02535 02536 RtlInitUnicodeString( &valueName, L"PnpBiosDeviceHandle" ); 02537 dwordValue = DevNodeInfoList[ nodeIndex ].Handle; 02538 02539 ZwClose( controlKey ); 02540 02541 } else { 02542 02543 DebugPrint( (MAPPER_ERROR, 02544 "Could not open registry key %S\\%S\\%S\\Control, status = %8.8X\n", 02545 ENUMROOT_KEY_NAME, 02546 DevNodeInfoList[ nodeIndex ].ProductId, 02547 instanceNameStr, 02548 status) ); 02549 02550 ZwClose( instanceKey ); 02551 status = STATUS_UNSUCCESSFUL; 02552 02553 goto Cleanup; 02554 } 02555 02556 RtlInitUnicodeString( &logConfKeyName, REGSTR_KEY_LOGCONF ); 02557 02558 status = IopCreateRegistryKeyEx( &logConfKey, 02559 instanceKey, 02560 &logConfKeyName, 02561 KEY_ALL_ACCESS, 02562 REG_OPTION_NON_VOLATILE, 02563 NULL 02564 ); 02565 02566 if (NT_SUCCESS(status)) { 02567 02568 if (DevNodeInfoList[ nodeIndex ].BootConfig != NULL) { 02569 02570 RtlInitUnicodeString( &valueName, REGSTR_VAL_BOOTCONFIG ); 02571 02572 status = ZwSetValueKey( logConfKey, 02573 &valueName, 02574 0, 02575 REG_RESOURCE_LIST, 02576 DevNodeInfoList[ nodeIndex ].BootConfig, 02577 DevNodeInfoList[ nodeIndex ].BootConfigLength ); 02578 02579 } 02580 02581 if (DevNodeInfoList[ nodeIndex ].BasicConfig != NULL) { 02582 02583 RtlInitUnicodeString( &valueName, REGSTR_VAL_BASICCONFIGVECTOR ); 02584 02585 status = ZwSetValueKey( logConfKey, 02586 &valueName, 02587 0, 02588 REG_RESOURCE_REQUIREMENTS_LIST, 02589 DevNodeInfoList[ nodeIndex ].BasicConfig, 02590 DevNodeInfoList[ nodeIndex ].BasicConfigLength ); 02591 02592 } 02593 02594 ZwClose( logConfKey ); 02595 02596 } else { 02597 02598 DebugPrint( (MAPPER_ERROR, 02599 "Could not open registry key %S\\%S\\%S\\LogConf, status = %8.8X\n", 02600 ENUMROOT_KEY_NAME, 02601 DevNodeInfoList[ nodeIndex ].ProductId, 02602 instanceNameStr, 02603 status) ); 02604 02605 ZwClose( instanceKey ); 02606 status = STATUS_UNSUCCESSFUL; 02607 02608 goto Cleanup; 02609 } 02610 02611 // 02612 // If we are replacing a FW Mapper devnode we need to copy the 02613 // Device Parameters subkey. 02614 // 02615 if (isNewDevice && DevNodeInfoList[ nodeIndex ].Replaces != NULL) { 02616 02617 status = PnPBiosCopyDeviceParamKey( enumRootKey, 02618 DevNodeInfoList[ nodeIndex ].Replaces, 02619 instanceNameStr ); 02620 } 02621 02622 ZwClose( instanceKey ); 02623 02624 } else { 02625 02626 DebugPrint( (MAPPER_ERROR, 02627 "Could not open registry key %S\\%S\\%S, status = %8.8X\n", 02628 ENUMROOT_KEY_NAME, 02629 DevNodeInfoList[ nodeIndex ].ProductId, 02630 instanceNameStr, 02631 status) ); 02632 02633 ZwClose( instanceKey ); 02634 status = STATUS_UNSUCCESSFUL; 02635 02636 goto Cleanup; 02637 } 02638 02639 // 02640 // Now check if the entry just written duplicates one written by the 02641 // Firmware Mapper. If it does then remove the Firmware Mapper entry. 02642 // 02643 02644 if (DevNodeInfoList[ nodeIndex ].Replaces != NULL) { 02645 02646 IopDeleteKeyRecursive( enumRootKey, DevNodeInfoList[ nodeIndex ].Replaces ); 02647 02648 } 02649 } 02650 02651 status = STATUS_SUCCESS; 02652 02653 Cleanup: 02654 ZwClose( enumRootKey ); 02655 02656 if (excludeList) { 02657 ExFreePool (excludeList); 02658 } 02659 02660 return status; 02661 } 02662 VOID 02663 PnPBiosCopyIoDecode( 02664 IN HANDLE EnumRootKey, 02665 IN PBIOS_DEVNODE_INFO DevNodeInfo 02666 ) 02667 { 02668 HANDLE deviceKey; 02669 WCHAR logConfKeyNameStr[DEFAULT_STRING_SIZE]; 02670 UNICODE_STRING logConfKeyName; 02671 HANDLE logConfKey; 02672 UNICODE_STRING valueName; 02673 PKEY_VALUE_PARTIAL_INFORMATION valueInfo = NULL; 02674 ULONG valueInfoLength; 02675 ULONG returnedLength; 02676 NTSTATUS status; 02677 PCM_PARTIAL_RESOURCE_LIST partialResourceList; 02678 PCM_PARTIAL_RESOURCE_DESCRIPTOR partialDescriptor; 02679 ULONG index; 02680 USHORT flags; 02681 02682 if (DevNodeInfo->Replaces == NULL || DevNodeInfo->BootConfig == NULL) { 02683 02684 // 02685 // If we didn't find a FW Mapper created devnode then there is nothing 02686 // to do. 02687 // 02688 return; 02689 } 02690 02691 // 02692 // Search through the Boot Config and see if the device's I/O ports are 02693 // 16 bit decode. 02694 // 02695 02696 ASSERT(DevNodeInfo->BootConfig->Count == 1); 02697 02698 partialResourceList = &DevNodeInfo->BootConfig->List[0].PartialResourceList; 02699 02700 partialDescriptor = &partialResourceList->PartialDescriptors[0]; 02701 02702 flags = (USHORT)~0; 02703 02704 #define DECODE_FLAGS ( CM_RESOURCE_PORT_10_BIT_DECODE | \ 02705 CM_RESOURCE_PORT_12_BIT_DECODE | \ 02706 CM_RESOURCE_PORT_16_BIT_DECODE | \ 02707 CM_RESOURCE_PORT_POSITIVE_DECODE ) 02708 02709 for ( index = 0; index < partialResourceList->Count; index++ ) { 02710 if (partialDescriptor->Type == CmResourceTypePort) { 02711 if (flags == (USHORT)~0) { 02712 flags = partialDescriptor->Flags & DECODE_FLAGS; 02713 } else { 02714 ASSERT(flags == (partialDescriptor->Flags & DECODE_FLAGS)); 02715 } 02716 } 02717 partialDescriptor++; 02718 } 02719 02720 if (!(flags & (CM_RESOURCE_PORT_16_BIT_DECODE | CM_RESOURCE_PORT_POSITIVE_DECODE))) { 02721 return; 02722 } 02723 02724 swprintf( logConfKeyNameStr, 02725 L"%s\\%s", 02726 DevNodeInfo->Replaces, 02727 REGSTR_KEY_LOGCONF 02728 ); 02729 02730 RtlInitUnicodeString( &logConfKeyName, logConfKeyNameStr ); 02731 02732 status = IopCreateRegistryKeyEx( &logConfKey, 02733 EnumRootKey, 02734 &logConfKeyName, 02735 KEY_ALL_ACCESS, 02736 REG_OPTION_NON_VOLATILE, 02737 NULL 02738 ); 02739 02740 if (!NT_SUCCESS(status)) { 02741 02742 DebugPrint( (MAPPER_ERROR, 02743 "Could not open registry key %S\\%S\\%S, status = %8.8X\n", 02744 ENUMROOT_KEY_NAME, 02745 DevNodeInfo->Replaces, 02746 REGSTR_KEY_LOGCONF, 02747 status) ); 02748 02749 return; 02750 } 02751 02752 valueInfoLength = sizeof(KEY_VALUE_PARTIAL_INFORMATION) + DEFAULT_STRING_SIZE; 02753 valueInfo = ExAllocatePool(PagedPool, valueInfoLength); 02754 02755 if (valueInfo == NULL) { 02756 02757 ZwClose( logConfKey ); 02758 02759 return; 02760 } 02761 02762 RtlInitUnicodeString( &valueName, REGSTR_VAL_BOOTCONFIG ); 02763 02764 status = ZwQueryValueKey( logConfKey, 02765 &valueName, 02766 KeyValuePartialInformation, 02767 valueInfo, 02768 valueInfoLength, 02769 &returnedLength); 02770 02771 if (!NT_SUCCESS(status)) { 02772 02773 if (status == STATUS_BUFFER_TOO_SMALL || status == STATUS_BUFFER_OVERFLOW) { 02774 02775 // 02776 // The default buffer was too small, free it and reallocate 02777 // it to the required size. 02778 // 02779 ExFreePool( valueInfo ); 02780 02781 valueInfoLength = returnedLength; 02782 valueInfo = ExAllocatePool( PagedPool, valueInfoLength ); 02783 02784 if (valueInfo != NULL) { 02785 02786 status = ZwQueryValueKey( logConfKey, 02787 &valueName, 02788 KeyValuePartialInformation, 02789 valueInfo, 02790 valueInfoLength, 02791 &returnedLength ); 02792 02793 if (!NT_SUCCESS(status)) { 02794 DebugPrint( (MAPPER_ERROR, 02795 "Could not query registry value %S\\%S\\LogConf\\BootConfig, status = %8.8X\n", 02796 ENUMROOT_KEY_NAME, 02797 DevNodeInfo->Replaces, 02798 status) ); 02799 02800 ExFreePool( valueInfo ); 02801 02802 ZwClose( logConfKey ); 02803 02804 return; 02805 } 02806 } else { 02807 02808 DebugPrint( (MAPPER_ERROR, 02809 "Could not allocate memory for BootConfig value\n" 02810 ) ); 02811 02812 ZwClose( logConfKey ); 02813 02814 return; 02815 } 02816 } 02817 } 02818 02819 partialResourceList = &((PCM_RESOURCE_LIST)valueInfo->Data)->List[0].PartialResourceList; 02820 02821 partialDescriptor = &partialResourceList->PartialDescriptors[0]; 02822 02823 for ( index = 0; index < partialResourceList->Count; index++ ) { 02824 if (partialDescriptor->Type == CmResourceTypePort) { 02825 partialDescriptor->Flags &= ~DECODE_FLAGS; 02826 partialDescriptor->Flags |= flags; 02827 } 02828 partialDescriptor++; 02829 } 02830 02831 status = ZwSetValueKey( logConfKey, 02832 &valueName, 02833 0, 02834 REG_RESOURCE_LIST, 02835 valueInfo->Data, 02836 valueInfo->DataLength ); 02837 02838 if (!NT_SUCCESS(status)) { 02839 DebugPrint( (MAPPER_ERROR, 02840 "Could not set registry value %S\\%S\\LogConf\\BootConfig, status = %8.8X\n", 02841 ENUMROOT_KEY_NAME, 02842 DevNodeInfo->Replaces, 02843 status) ); 02844 } 02845 02846 ExFreePool(valueInfo); 02847 02848 ZwClose(logConfKey); 02849 } 02850 02851 NTSTATUS 02852 PnPBiosCheckForHardwareDisabled( 02853 IN PIO_RESOURCE_REQUIREMENTS_LIST IoResourceList, 02854 IN OUT PBOOLEAN Disabled 02855 ) 02856 /*++ 02857 02858 Routine Description: 02859 02860 If this device has been assigned one or more resources, and each resource has a length of zero, then it is 02861 hardware disabled. 02862 02863 Arguments: 02864 02865 IoResourceList - Resource obtained from BIOS that we're about to map to a CmResourceList 02866 02867 Disabled - Set to TRUE if the device is deemed to be disabled 02868 02869 Return Value: 02870 02871 STATUS_SUCCESS if no errors, otherwise the appropriate error. 02872 02873 --*/ 02874 { 02875 BOOLEAN ParsedResource = FALSE; 02876 PIO_RESOURCE_DESCRIPTOR ioDescriptor; 02877 ULONG descIndex; 02878 // 02879 // Since this routine is only used to translate the allocated resources 02880 // returned by the PnP BIOS, we can assume that there is only 1 alternative 02881 // list 02882 // 02883 02884 ASSERT(IoResourceList->AlternativeLists == 1); 02885 ASSERT(Disabled != NULL); 02886 02887 *Disabled = FALSE; 02888 02889 // 02890 // Translate each resource descriptor, currently we only handle ports, 02891 // memory, interrupts, and dma. The current implementation of the routine 02892 // which converts from ISA PnP Resource data to IO_RESOURCE_REQUIREMENTS 02893 // won't generate any other descriptor types given the data returned from 02894 // the BIOS. 02895 // 02896 02897 for (descIndex = 0; descIndex < IoResourceList->List[ 0 ].Count; descIndex++) { 02898 02899 ioDescriptor = &IoResourceList->List[ 0 ].Descriptors[ descIndex ]; 02900 02901 switch (ioDescriptor->Type) { 02902 02903 case CmResourceTypePort: 02904 if (ioDescriptor->u.Port.Length) { 02905 return STATUS_SUCCESS; 02906 } 02907 ParsedResource = TRUE; 02908 break; 02909 02910 case CmResourceTypeInterrupt: 02911 if (ioDescriptor->u.Interrupt.MinimumVector != (ULONG)(-1)) { 02912 return STATUS_SUCCESS; 02913 } 02914 ParsedResource = TRUE; 02915 break; 02916 02917 case CmResourceTypeMemory: 02918 if (ioDescriptor->u.Memory.Length) { 02919 return STATUS_SUCCESS; 02920 } 02921 ParsedResource = TRUE; 02922 break; 02923 02924 case CmResourceTypeDma: 02925 if (ioDescriptor->u.Dma.MinimumChannel != (ULONG)(-1)) { 02926 return STATUS_SUCCESS; 02927 } 02928 ParsedResource = TRUE; 02929 break; 02930 02931 default: 02932 DebugPrint( (MAPPER_ERROR, 02933 "Unexpected ResourceType (%d) in I/O Descriptor\n", 02934 ioDescriptor->Type) ); 02935 02936 #if DBG 02937 // DbgBreakPoint(); 02938 #endif 02939 break; 02940 } 02941 } 02942 02943 if (ParsedResource) { 02944 // 02945 // at least one empty resource, no non-empty resources 02946 // 02947 *Disabled = TRUE; 02948 } 02949 02950 return STATUS_SUCCESS; 02951 02952 } 02953 02954 02955 NTSTATUS 02956 PnPBiosFreeDevNodeInfo( 02957 IN PBIOS_DEVNODE_INFO DevNodeInfoList, 02958 IN ULONG NumberNodes 02959 ) 02960 /*++ 02961 02962 Routine Description: 02963 02964 Free the dynamically allocated DevNodeInfoList as well as any dynamically 02965 allocated dependent structures. 02966 02967 Arguments: 02968 02969 DevNodeInfoList - Array of BIOS_DEVNODE_INFO structures, one for each device 02970 reported by the BIOS. 02971 02972 NumberNodes - Number of BIOS_DEVNODE_INFO elements pointed to by 02973 DevNodeInfoList. 02974 02975 Return Value: 02976 02977 STATUS_SUCCESS if no errors, otherwise the appropriate error. 02978 02979 --*/ 02980 { 02981 ULONG nodeIndex; 02982 02983 for (nodeIndex = 0; nodeIndex < NumberNodes; nodeIndex++) { 02984 02985 if (DevNodeInfoList[nodeIndex].Replaces != NULL) { 02986 ExFreePool( DevNodeInfoList[nodeIndex].Replaces ); 02987 } 02988 02989 if (DevNodeInfoList[nodeIndex].CompatibleIDs != NULL) { 02990 ExFreePool( DevNodeInfoList[nodeIndex].CompatibleIDs ); 02991 } 02992 02993 if (DevNodeInfoList[nodeIndex].BootConfig != NULL) { 02994 ExFreePool( DevNodeInfoList[nodeIndex].BootConfig ); 02995 } 02996 02997 if (DevNodeInfoList[nodeIndex].BasicConfig != NULL) { 02998 ExFreePool( DevNodeInfoList[nodeIndex].BasicConfig ); 02999 } 03000 } 03001 03002 ExFreePool( DevNodeInfoList ); 03003 03004 return STATUS_SUCCESS; 03005 } 03006 03007 NTSTATUS 03008 PnPBiosMapper() 03009 /*++ 03010 03011 Routine Description: 03012 03013 Map the information provided from the PnP BIOS and stored in the registry by 03014 NTDETECT into root enumerated devices. 03015 03016 Arguments: 03017 03018 NONE 03019 03020 Return Value: 03021 03022 STATUS_SUCCESS if no errors, otherwise the appropriate error. 03023 03024 --*/ 03025 { 03026 PCM_RESOURCE_LIST biosInfo; 03027 ULONG length; 03028 NTSTATUS status; 03029 PBIOS_DEVNODE_INFO devNodeInfoList; 03030 ULONG numberNodes; 03031 03032 status = PnPBiosGetBiosInfo( &biosInfo, &length ); 03033 03034 if (!NT_SUCCESS( status )) { 03035 03036 return status; 03037 } 03038 03039 status = PnPBiosTranslateInfo( biosInfo, 03040 length, 03041 &devNodeInfoList, 03042 &numberNodes ); 03043 03044 ExFreePool( biosInfo ); 03045 03046 if (!NT_SUCCESS( status )) { 03047 03048 return status; 03049 } 03050 03051 status = PnPBiosEliminateDupes( devNodeInfoList, numberNodes ); 03052 03053 if (NT_SUCCESS( status )) { 03054 03055 status = PnPBiosWriteInfo( devNodeInfoList, numberNodes ); 03056 03057 } 03058 03059 PnPBiosFreeDevNodeInfo( devNodeInfoList, numberNodes ); 03060 03061 return status; 03062 } 03063 03064 VOID 03065 PpFilterNtResource ( 03066 IN PWCHAR PnpDeviceName, 03067 PIO_RESOURCE_REQUIREMENTS_LIST ResReqList 03068 ) 03069 { 03070 PIO_RESOURCE_LIST ioResourceList; 03071 PIO_RESOURCE_DESCRIPTOR ioResourceDescriptors; 03072 03073 if (ResReqList == NULL) { 03074 return; 03075 } 03076 03077 if (IsNEC_98) { 03078 return; 03079 } 03080 03081 #if 0 //_X86_ 03082 if (KeI386MachineType == MACHINE_TYPE_EISA) { 03083 03084 PCM_FULL_RESOURCE_DESCRIPTOR fullDescriptor; 03085 PCM_PARTIAL_RESOURCE_DESCRIPTOR partialDescriptor; 03086 PUCHAR nextDescriptor; 03087 ULONG j; 03088 ULONG lastResourceIndex; 03089 03090 fullDescriptor = &ResourceList->List[0]; 03091 03092 for (i = 0; i < ResourceList->Count; i++) { 03093 03094 partialResourceList = &fullDescriptor->PartialResourceList; 03095 03096 for (j = 0; j < partialResourceList->Count; j++) { 03097 partialDescriptor = &partialResourceList->PartialDescriptors[j]; 03098 03099 if (partialDescriptor->Type == CmResourceTypePort) { 03100 if (partialDescriptor->u.Port.Start.HighPart == 0 && 03101 (partialDescriptor->u.Port.Start.LowPart & 0x00000300) == 0) { 03102 partialDescriptor->Flags |= CM_RESOURCE_PORT_16_BIT_DECODE; 03103 } 03104 } 03105 } 03106 03107 nextDescriptor = (PUCHAR)fullDescriptor + sizeof(CM_FULL_RESOURCE_DESCRIPTOR); 03108 03109 // 03110 // account for any resource descriptors in addition to the single 03111 // imbedded one I've already accounted for (if there aren't any, 03112 // then I'll end up subtracting off the extra imbedded descriptor 03113 // from the previous step) 03114 // 03115 // 03116 // finally, account for any extra device specific data at the end of 03117 // the last partial resource descriptor (if any) 03118 // 03119 if (partialResourceList->Count > 0) { 03120 03121 nextDescriptor += (partialResourceList->Count - 1) * 03122 sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR); 03123 03124 lastResourceIndex = partialResourceList->Count - 1; 03125 03126 if (partialResourceList->PartialDescriptors[lastResourceIndex].Type == 03127 CmResourceTypeDeviceSpecific) { 03128 03129 nextDescriptor += partialResourceList->PartialDescriptors[lastResourceIndex]. 03130 u.DeviceSpecificData.DataSize; 03131 } 03132 } 03133 03134 fullDescriptor = (PCM_FULL_RESOURCE_DESCRIPTOR)nextDescriptor; 03135 } 03136 } 03137 #endif 03138 03139 if (RtlCompareMemory(PnpDeviceName, 03140 L"*PNP06", 03141 sizeof(L"*PNP06") - sizeof(WCHAR)) == 03142 sizeof(L"*PNP06") - sizeof(WCHAR)) { 03143 03144 ULONG i, j; 03145 03146 ioResourceList = ResReqList->List; 03147 03148 for (j = 0; j < ResReqList->AlternativeLists; j++) { 03149 03150 ioResourceDescriptors = ioResourceList->Descriptors; 03151 03152 for (i = 0; i < ioResourceList->Count; i++) { 03153 03154 if (ioResourceDescriptors[i].Type == CmResourceTypePort) { 03155 03156 // 03157 // some bios asks for 1 too many io port for ide channel 03158 // 03159 if ((ioResourceDescriptors[i].u.Port.Length == 2) && 03160 (ioResourceDescriptors[i].u.Port.MaximumAddress.QuadPart == 03161 (ioResourceDescriptors[i].u.Port.MinimumAddress.QuadPart + 1))) { 03162 03163 ioResourceDescriptors[i].u.Port.Length = 1; 03164 ioResourceDescriptors[i].u.Port.MaximumAddress = 03165 ioResourceDescriptors[i].u.Port.MinimumAddress; 03166 } 03167 } 03168 } 03169 03170 ioResourceList = (PIO_RESOURCE_LIST) (ioResourceDescriptors + ioResourceList->Count); 03171 } 03172 } 03173 } 03174 03175 03176 03177 #if DBG 03178 VOID 03179 PnPBiosDebugPrint( 03180 ULONG DebugMask, 03181 PCCHAR DebugMessage, 03182 ... 03183 ) 03184 03185 /*++ 03186 03187 Routine Description: 03188 03189 Debug print for the firmware mapper 03190 03191 Arguments: 03192 03193 Check the mask value to see if the debug message is requested. 03194 03195 Return Value: 03196 03197 None 03198 03199 --*/ 03200 03201 { 03202 va_list ap; 03203 CHAR buffer[256]; 03204 03205 va_start( ap, DebugMessage ); 03206 03207 #define DBG_MSG_PREFIX "BiosMapper: " 03208 03209 strcpy(buffer, DBG_MSG_PREFIX); 03210 03211 if ( DebugMask & PnPBiosMapperDebugMask ) { 03212 03213 _vsnprintf( &buffer[sizeof(DBG_MSG_PREFIX) - 1], 03214 sizeof(buffer) - sizeof(DBG_MSG_PREFIX), 03215 DebugMessage, 03216 ap ); 03217 03218 DbgPrint( buffer ); 03219 } 03220 03221 va_end(ap); 03222 03223 } 03224 #endif 03225

Generated on Sat May 15 19:41:18 2004 for test by doxygen 1.3.7