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

rules.c

Go to the documentation of this file.
00001 /*++ 00002 00003 Copyright (c) 1998 Microsoft Corporation 00004 00005 00006 Module Name: 00007 00008 rules.c 00009 00010 Abstract: 00011 00012 This modules contains routines to implement rules to describe a machine. 00013 This is based on the detection code from W9x. 00014 00015 Author: 00016 00017 Santosh Jodh (santoshj) 08-Aug-1998 00018 00019 Environment: 00020 00021 Kernel mode. 00022 00023 Revision History: 00024 00025 --*/ 00026 00027 #include "cmp.h" 00028 #include "stdlib.h" 00029 #include "parseini.h" 00030 #include "geninst.h" 00031 #include "rules.h" 00032 #include "acpitabl.h" 00033 #include "ntacpi.h" 00034 00035 #define TABLE_ENTRIES_FROM_RSDT_POINTER(p) (((p)->Header.Length-min((p)->Header.Length, sizeof(DESCRIPTION_HEADER))) / 4) 00036 00037 00038 // 00039 // Size of the ROM BIOS segment. 00040 // 00041 00042 #define SYSTEM_BIOS_LENGTH 0x10000 00043 00044 // 00045 // PnP BIOS structure signature. 00046 // 00047 00048 #define PNPBIOS_SIGNATURE 'PnP$' 00049 00050 typedef 00051 BOOLEAN 00052 (* PFN_RULE)( 00053 IN PVOID InfHandle, 00054 IN PCHAR Description, 00055 IN ULONG RuleIndex 00056 ); 00057 00058 typedef struct _PNP_BIOS_TABLE PNP_BIOS_TABLE, *PPNP_BIOS_TABLE; 00059 00060 #pragma pack(push, 1) 00061 00062 struct _PNP_BIOS_TABLE 00063 { 00064 ULONG Signature; 00065 UCHAR Version; 00066 UCHAR Length; 00067 USHORT ControlField; 00068 UCHAR CheckSum; 00069 ULONG EventNotification; 00070 USHORT RMOffset; 00071 USHORT RMSegment; 00072 USHORT PMOffset; 00073 ULONG PMSegment; 00074 ULONG Oem; 00075 USHORT RMData; 00076 ULONG PMData; 00077 }; 00078 00079 #pragma pack(pop) 00080 00081 ULONG 00082 CmpComputeChecksum( 00083 IN PCHAR Address, 00084 IN ULONG Size 00085 ); 00086 00087 NTSTATUS 00088 CmpFindRSDTTable( 00089 OUT PACPI_BIOS_MULTI_NODE *Rsdt 00090 ); 00091 00092 NTSTATUS 00093 CmpGetRegistryValue( 00094 IN HANDLE KeyName, 00095 IN PWSTR ValueName, 00096 OUT PKEY_VALUE_PARTIAL_INFORMATION *Information 00097 ); 00098 00099 PDESCRIPTION_HEADER 00100 CmpFindACPITable( 00101 IN ULONG Signature, 00102 IN OUT PULONG Length 00103 ); 00104 00105 BOOLEAN 00106 CmpCheckOperator( 00107 IN PCHAR Operator, 00108 IN ULONG Lhs, 00109 IN ULONG Rhs 00110 ); 00111 00112 PVOID 00113 CmpMapPhysicalAddress( 00114 IN OUT PVOID *BaseAddress, 00115 IN ULONG Address, 00116 IN ULONG Size 00117 ); 00118 00119 BOOLEAN 00120 CmpGetInfData( 00121 IN PVOID InfHandle, 00122 IN PCHAR Section, 00123 IN ULONG KeyIndex, 00124 IN ULONG LineIndex, 00125 IN OUT PCHAR Buffer, 00126 IN OUT PULONG BufferSize 00127 ); 00128 00129 PVOID 00130 CmpFindPattern( 00131 IN PCHAR Buffer, 00132 IN ULONG BufSize, 00133 IN PCHAR Pattern, 00134 IN ULONG PatSize, 00135 IN BOOLEAN IgnoreCase, 00136 IN ULONG Step 00137 ); 00138 00139 ULONG 00140 CmpGetPnPBIOSTableAddress( 00141 VOID 00142 ); 00143 00144 BOOLEAN 00145 CmpMatchDescription( 00146 IN PVOID InfHandle, 00147 IN PCHAR Description 00148 ); 00149 00150 BOOLEAN 00151 CmpMatchDateRule( 00152 IN PVOID InfHandle, 00153 IN PCHAR Description, 00154 IN ULONG RuleIndex 00155 ); 00156 00157 BOOLEAN 00158 CmpMatchMemoryRule( 00159 IN PVOID InfHandle, 00160 IN PCHAR Description, 00161 IN ULONG RuleIndex 00162 ); 00163 00164 BOOLEAN 00165 CmpMatchSearchRule( 00166 IN PVOID InfHandle, 00167 IN PCHAR Description, 00168 IN ULONG RuleIndex 00169 ); 00170 00171 BOOLEAN 00172 CmpMatchNextMatchRule( 00173 IN PVOID InfHandle, 00174 IN PCHAR Description, 00175 IN ULONG RuleIndex 00176 ); 00177 00178 BOOLEAN 00179 CmpMatchPointerRule( 00180 IN PVOID InfHandle, 00181 IN PCHAR Description, 00182 IN ULONG RuleIndex 00183 ); 00184 00185 BOOLEAN 00186 CmpMatchOemIdRule( 00187 IN PVOID InfHandle, 00188 IN PCHAR Description, 00189 IN ULONG RuleIndex 00190 ); 00191 00192 BOOLEAN 00193 CmpMatchPModeRule( 00194 IN PVOID InfHandle, 00195 IN PCHAR Description, 00196 IN ULONG RuleIndex 00197 ); 00198 00199 BOOLEAN 00200 CmpMatchRmPmSameRule( 00201 IN PVOID InfHandle, 00202 IN PCHAR Description, 00203 IN ULONG RuleIndex 00204 ); 00205 00206 BOOLEAN 00207 CmpMatchInstallRule( 00208 IN PVOID InfHandle, 00209 IN PCHAR Description, 00210 IN ULONG RuleIndex 00211 ); 00212 00213 BOOLEAN 00214 CmpMatchAcpiOemIdRule( 00215 IN PVOID InfHandle, 00216 IN PCHAR Description, 00217 IN ULONG RuleIndex 00218 ); 00219 00220 BOOLEAN 00221 CmpMatchAcpiOemTableIdRule( 00222 IN PVOID InfHandle, 00223 IN PCHAR Description, 00224 IN ULONG RuleIndex 00225 ); 00226 00227 BOOLEAN 00228 CmpMatchAcpiOemRevisionRule( 00229 IN PVOID InfHandle, 00230 IN PCHAR Description, 00231 IN ULONG RuleIndex 00232 ); 00233 00234 BOOLEAN 00235 CmpMatchAcpiRevisionRule( 00236 IN PVOID InfHandle, 00237 IN PCHAR Description, 00238 IN ULONG RuleIndex 00239 ); 00240 00241 BOOLEAN 00242 CmpMatchAcpiCreatorRevisionRule( 00243 IN PVOID InfHandle, 00244 IN PCHAR Description, 00245 IN ULONG RuleIndex 00246 ); 00247 00248 // 00249 // Number of rules currently implemented. 00250 // 00251 00252 #define NUM_OF_RULES 14 00253 00254 // 00255 // Rule table. 00256 // 00257 00258 struct { 00259 PCHAR Name; 00260 PFN_RULE Action; 00261 } gRuleTable[NUM_OF_RULES] = 00262 { 00263 {"Date", CmpMatchDateRule}, 00264 {"Memory", CmpMatchMemoryRule}, 00265 {"Search", CmpMatchSearchRule}, 00266 {"NextMatch", CmpMatchNextMatchRule}, 00267 {"Pointer", CmpMatchPointerRule}, 00268 {"OemId", CmpMatchOemIdRule}, 00269 {"PMode", CmpMatchPModeRule}, 00270 {"RmPmSame", CmpMatchRmPmSameRule}, 00271 {"Install", CmpMatchInstallRule}, 00272 {"ACPIOemId", CmpMatchAcpiOemIdRule}, 00273 {"ACPIOemTableId", CmpMatchAcpiOemTableIdRule}, 00274 {"ACPIOemRevision", CmpMatchAcpiOemRevisionRule}, 00275 {"ACPIRevision", CmpMatchAcpiRevisionRule}, 00276 {"ACPICreatorRevision", CmpMatchAcpiCreatorRevisionRule} 00277 }; 00278 00279 PVOID gSearchAddress = NULL; 00280 00281 static WCHAR rgzMultiFunctionAdapter[] = L"\\Registry\\Machine\\Hardware\\Description\\System\\MultifunctionAdapter"; 00282 static WCHAR rgzAcpiConfigurationData[] = L"Configuration Data"; 00283 static WCHAR rgzAcpiIdentifier[] = L"Identifier"; 00284 static WCHAR rgzBIOSIdentifier[] = L"ACPI BIOS"; 00285 00286 #ifdef ALLOC_PRAGMA 00287 #pragma alloc_text(INIT,CmpFindACPITable) 00288 #pragma alloc_text(INIT,CmpFindRSDTTable) 00289 #pragma alloc_text(INIT,CmpComputeChecksum) 00290 #pragma alloc_text(INIT,CmpCheckOperator) 00291 #pragma alloc_text(INIT,CmpMapPhysicalAddress) 00292 #pragma alloc_text(INIT,CmpGetInfData) 00293 #pragma alloc_text(INIT,CmpFindPattern) 00294 #pragma alloc_text(INIT,CmpGetPnPBIOSTableAddress) 00295 #pragma alloc_text(INIT,CmpMatchInfList) 00296 #pragma alloc_text(INIT,CmpMatchDescription) 00297 #pragma alloc_text(INIT,CmpMatchDateRule) 00298 #pragma alloc_text(INIT,CmpMatchMemoryRule) 00299 #pragma alloc_text(INIT,CmpMatchSearchRule) 00300 #pragma alloc_text(INIT,CmpMatchNextMatchRule) 00301 #pragma alloc_text(INIT,CmpMatchPointerRule) 00302 #pragma alloc_text(INIT,CmpMatchOemIdRule) 00303 #pragma alloc_text(INIT,CmpMatchPModeRule) 00304 #pragma alloc_text(INIT,CmpMatchRmPmSameRule) 00305 #pragma alloc_text(INIT,CmpMatchInstallRule) 00306 #pragma alloc_text(INIT,CmpMatchAcpiOemIdRule) 00307 #pragma alloc_text(INIT,CmpMatchAcpiOemTableIdRule) 00308 #pragma alloc_text(INIT,CmpMatchAcpiOemRevisionRule) 00309 #pragma alloc_text(INIT,CmpMatchAcpiRevisionRule) 00310 #pragma alloc_text(INIT,CmpMatchAcpiCreatorRevisionRule) 00311 #endif 00312 00313 00314 BOOLEAN 00315 CmpMatchInfList( 00316 IN PVOID InfImage, 00317 IN ULONG ImageSize, 00318 IN PCHAR Section 00319 ) 00320 00321 /*++ 00322 00323 Routine Description: 00324 00325 Input Parameters: 00326 00327 InfImage - Pointer to the inf image in memory. 00328 00329 ImageSize - Size of the inf image. 00330 00331 Section - Section name containing the descriptions. 00332 00333 Description - 00334 00335 Return Value: 00336 00337 TRUE if the machine matches any one of the descriptions in the inf. 00338 00339 --*/ 00340 00341 { 00342 PCHAR computerName; 00343 ULONG i = 0; 00344 PVOID infHandle; 00345 BOOLEAN result = FALSE; 00346 00347 infHandle = CmpOpenInfFile(InfImage, ImageSize); 00348 00349 if (infHandle) 00350 { 00351 // 00352 // Do any clean-up specified in the inf. 00353 // 00354 00355 CmpGenInstall(infHandle, "Cleanup"); 00356 00357 // 00358 // Go through each description in this section and try to match 00359 // this machine to it. 00360 // 00361 00362 while ((computerName = CmpGetSectionLineIndex(infHandle, Section, i++, 0))) 00363 { 00364 // 00365 // Reset search result from previous description. 00366 // 00367 00368 gSearchAddress = NULL; 00369 00370 // 00371 // If this description matches, we are done. 00372 // NOTE: IF MORE THAN ONE DESCRIPTION MATCHES, 00373 // WE STOP AT THE FIRST ONE. 00374 // 00375 00376 if (CmpMatchDescription(infHandle, computerName)) 00377 { 00378 DbgPrint("CmpMatchInfList: Machine matches %s description!\n", computerName); 00379 result = TRUE; 00380 } 00381 } 00382 00383 CmpCloseInfFile(infHandle); 00384 } 00385 00386 // 00387 // None of the descriptions match. 00388 // 00389 00390 return (result); 00391 } 00392 00393 BOOLEAN 00394 CmpMatchDescription( 00395 IN PVOID InfHandle, 00396 IN PCHAR Description 00397 ) 00398 00399 /*++ 00400 00401 Routine Description: 00402 00403 This routine processes all the rules in the specified description. 00404 00405 Input Parameters: 00406 00407 InfHandle - Handle to the inf containing the description. 00408 00409 Description - Section name containing the rules. 00410 00411 Return Value: 00412 00413 TRUE iff all the rules in the description succeed. 00414 00415 --*/ 00416 00417 { 00418 ULONG ruleNumber; 00419 ULONG i; 00420 PCHAR ruleName; 00421 00422 // 00423 // Proceed only if the section does exist. 00424 // 00425 00426 if (CmpSearchInfSection(InfHandle, Description)) 00427 { 00428 // 00429 // Go through all the rules in the description and try to match 00430 // each of them. 00431 // 00432 00433 ruleNumber = 0; 00434 while ((ruleName = CmpGetKeyName(InfHandle, Description, ruleNumber))) 00435 { 00436 // 00437 // Search for the rule in our table. 00438 // 00439 00440 for ( i = 0; 00441 i < NUM_OF_RULES && 00442 _stricmp(ruleName, gRuleTable[i].Name); 00443 i++); 00444 00445 // 00446 // If we did not find the rule or the rule failed, 00447 // return failure. 00448 // 00449 00450 if ( i >= NUM_OF_RULES || 00451 !(*gRuleTable[i].Action)(InfHandle, Description, ruleNumber++)) 00452 { 00453 return (FALSE); 00454 } 00455 } 00456 00457 // 00458 // Description matches if we found at least one rule and all rules 00459 // succeeded. 00460 // 00461 00462 if (ruleNumber) 00463 { 00464 return (TRUE); 00465 } 00466 } 00467 00468 // 00469 // Description did not match. 00470 // 00471 00472 return (FALSE); 00473 } 00474 00475 BOOLEAN 00476 CmpMatchDateRule( 00477 IN PVOID InfHandle, 00478 IN PCHAR Description, 00479 IN ULONG RuleIndex 00480 ) 00481 00482 /*++ 00483 00484 Routine Description: 00485 00486 This routine checks if the machine satisfies the DATE rule. The BIOS date 00487 is stored in a standard location in the BIOS ROM at FFFF:5. 00488 00489 Syntax - 00490 00491 DATE=operator,month,day,year 00492 where operator [=, ==, !=, <>, <, <=, =<, >, >=, =>] 00493 00494 Examples - 00495 00496 date="<=",2,1,95 00497 is TRUE if the BIOS date on this machine is less than or equal to 00498 02/01/95. 00499 00500 Input Parameters: 00501 00502 InfHandle - Handle to the inf to be read. 00503 00504 Description - Name of the section containing the rule info. 00505 00506 RuleIndex - Line number for the rule in the description section. 00507 00508 Return Value: 00509 00510 TRUE if the BIOS on this machine has the specified relation with the 00511 date specified in the rule. 00512 00513 --*/ 00514 00515 { 00516 PCHAR op; 00517 PCHAR month; 00518 PCHAR day; 00519 PCHAR year; 00520 ULONG infDate; 00521 ULONG yr; 00522 ULONG biosDate; 00523 CHAR temp[3]; 00524 PVOID baseAddress; 00525 PCHAR address; 00526 00527 op = CmpGetSectionLineIndex(InfHandle, Description, RuleIndex, 0); 00528 month = CmpGetSectionLineIndex(InfHandle, Description, RuleIndex, 1); 00529 day = CmpGetSectionLineIndex(InfHandle, Description, RuleIndex, 2); 00530 year = CmpGetSectionLineIndex(InfHandle, Description, RuleIndex, 3); 00531 00532 if (op && month && day && year) 00533 { 00534 yr = strtoul(year, NULL, 16); 00535 infDate = ((yr < 0x80) ? 0x20000000 : 0x19000000) + 00536 (yr << 16) + 00537 (strtoul(month, NULL, 16) << 8) + 00538 (strtoul(day, NULL, 16)); 00539 00540 address = CmpMapPhysicalAddress(&baseAddress, 0xFFFF5, 8); 00541 if (address) 00542 { 00543 temp[2] = '\0'; 00544 00545 RtlCopyBytes(temp, address + 6, 2); 00546 yr = strtoul(temp, NULL, 16); 00547 biosDate = ((yr < 0x80) ? 0x20000000 : 0x19000000) + 00548 (yr << 16); 00549 00550 RtlCopyBytes(temp, address, 2); 00551 biosDate |= (strtoul(temp, NULL, 16) << 8); 00552 00553 RtlCopyBytes(temp, address + 3, 2); 00554 biosDate |= strtoul(temp, NULL, 16); 00555 00556 ZwUnmapViewOfSection(NtCurrentProcess(), baseAddress); 00557 00558 if (CmpCheckOperator(op, biosDate, infDate)) 00559 { 00560 return (TRUE); 00561 } 00562 } 00563 } 00564 00565 return (FALSE); 00566 } 00567 00568 BOOLEAN 00569 CmpMatchMemoryRule( 00570 IN PVOID InfHandle, 00571 IN PCHAR Description, 00572 IN ULONG RuleIndex 00573 ) 00574 00575 /*++ 00576 00577 Routine Description: 00578 00579 This routine checks if the machine satisfies the MEMORY rule. 00580 00581 Syntax - 00582 00583 MEMORY=segment,offset,type,data 00584 where type ["S", "B"] 00585 00586 Examples - 00587 00588 memory=f000,e000,S,"TOSHIBA" 00589 is TRUE if the memory in this machine at physical address f000:e000 00590 has the string "TOSHIBA". 00591 00592 memory=ffff,5,B,01,02 00593 is TRUE if the memory in this machine at physical memory ffff:5 00594 has the bytes 0x01 and 0x02. 00595 00596 Input Parameters: 00597 00598 InfHandle - Handle to the inf to be read. 00599 00600 Description - Name of the section containing the rule info. 00601 00602 RuleIndex - Line number for the rule in the description section. 00603 00604 Return Value: 00605 00606 TRUE iff the MEMORY in this machine at the specified address 00607 contains the specified data. 00608 00609 --*/ 00610 00611 { 00612 BOOLEAN match = FALSE; 00613 PCHAR segment; 00614 PCHAR offset; 00615 CHAR data[MAX_DESCRIPTION_LEN + 1]; 00616 ULONG cbData; 00617 PVOID baseAddress; 00618 PCHAR address; 00619 ULONG memory; 00620 00621 // 00622 // Read in the segment and offset of the address specified. 00623 // 00624 00625 segment = CmpGetSectionLineIndex(InfHandle, Description, RuleIndex, 0); 00626 offset = CmpGetSectionLineIndex(InfHandle, Description, RuleIndex, 1); 00627 00628 if (segment && offset) 00629 { 00630 // 00631 // Get the data specified in the inf. 00632 // 00633 00634 cbData = sizeof(data); 00635 if (CmpGetInfData(InfHandle, Description, RuleIndex, 2, data, &cbData)) 00636 { 00637 memory = (strtoul(segment, NULL, 16) << 4) + strtoul(offset, NULL, 16); 00638 00639 // 00640 // Map in the physical address. 00641 // 00642 00643 address = CmpMapPhysicalAddress(&baseAddress, memory, cbData); 00644 if (address) 00645 { 00646 00647 // 00648 // Check if the inf data matches data in memory. 00649 // 00650 00651 match = (RtlCompareMemory(address, data, cbData) == cbData); 00652 00653 // 00654 // Unmap the physical address. 00655 // 00656 00657 ZwUnmapViewOfSection(NtCurrentProcess(), baseAddress); 00658 } 00659 } 00660 } 00661 00662 return (match); 00663 } 00664 00665 BOOLEAN 00666 CmpMatchSearchRule( 00667 IN PVOID InfHandle, 00668 IN PCHAR Description, 00669 IN ULONG RuleIndex 00670 ) 00671 00672 /*++ 00673 00674 Routine Description: 00675 00676 This routine checks to see if the machine matches the SEARCH rule. 00677 00678 Syntax - 00679 00680 SEARCH=segment,offset,length,type,data 00681 where type ["S", "B"] 00682 00683 Examples - 00684 00685 search=f000,e000,7f,S,"SurePath" 00686 is TRUE if the string "SurePath" is somewhere in memory range 00687 F000:E000 to F000:E07F (inclusive). 00688 00689 Input Parameters: 00690 00691 InfHandle - Handle to the inf to be read. 00692 00693 Description - Name of the section containing the rule info. 00694 00695 RuleIndex - Line number for the rule in the description section. 00696 00697 Return Value: 00698 00699 TRUE iff the specified pattern is found within the specified address 00700 range. 00701 00702 --*/ 00703 00704 { 00705 BOOLEAN match = FALSE; 00706 PCHAR segment; 00707 PCHAR offset; 00708 PCHAR size; 00709 CHAR data[MAX_DESCRIPTION_LEN + 1]; 00710 ULONG cbData; 00711 ULONG memory; 00712 ULONG length; 00713 PVOID baseAddress; 00714 PCHAR address; 00715 00716 segment = CmpGetSectionLineIndex(InfHandle, Description, RuleIndex, 0); 00717 offset = CmpGetSectionLineIndex(InfHandle, Description, RuleIndex, 1); 00718 size = CmpGetSectionLineIndex(InfHandle, Description, RuleIndex, 2); 00719 00720 if (segment && offset && size) 00721 { 00722 // 00723 // Get the data specified in the inf. 00724 // 00725 00726 cbData = sizeof(data); 00727 if (CmpGetInfData(InfHandle, Description, RuleIndex, 3, data, &cbData)) 00728 { 00729 memory = (strtoul(segment, NULL, 16) << 4) + strtoul(offset, NULL, 16); 00730 00731 // 00732 // Map in the physical address. 00733 // 00734 00735 length = strtoul(size, NULL, 16); 00736 address = CmpMapPhysicalAddress(&baseAddress, memory, length); 00737 if (address) 00738 { 00739 gSearchAddress = CmpFindPattern(address, length, data, cbData, FALSE, 0); 00740 if (gSearchAddress) 00741 { 00742 // 00743 // If we found the pattern, compute the actual address for it. 00744 // 00745 00746 (PCHAR)gSearchAddress -= (ULONG)address; 00747 (PCHAR)gSearchAddress += memory; 00748 match = TRUE; 00749 } 00750 00751 // 00752 // Unmap the physical address. 00753 // 00754 00755 ZwUnmapViewOfSection(NtCurrentProcess(), baseAddress); 00756 } 00757 } 00758 } 00759 00760 return (match); 00761 } 00762 00763 BOOLEAN 00764 CmpMatchNextMatchRule( 00765 IN PVOID InfHandle, 00766 IN PCHAR Description, 00767 IN ULONG RuleIndex 00768 ) 00769 00770 /*++ 00771 00772 Routine Description: 00773 00774 This routine checks to see if the machine matches the NEXTMATCH rule. 00775 00776 Syntax - 00777 00778 NEXTMATCH=offset,type,data 00779 where type ["S", "B"] 00780 00781 Examples - 00782 00783 nextmatch=f0,S,"Atlanta" 00784 is TRUE if the string "Atlanta" is at offset 0xF0 from the previous 00785 successful SEARCH or NEXTMATCH rule. 00786 00787 Input Parameters: 00788 00789 InfHandle - Handle to the inf to be read. 00790 00791 Description - Name of the section containing the rule info. 00792 00793 RuleIndex - Line number for the rule in the description section. 00794 00795 Return Value: 00796 00797 TRUE iff the specified pattern is found at the specified offset 00798 from the previous successful SEARCH or NEXTMATCH. 00799 00800 --*/ 00801 00802 { 00803 BOOLEAN match = FALSE; 00804 PCHAR offset; 00805 CHAR data[MAX_DESCRIPTION_LEN + 1]; 00806 ULONG cbData; 00807 PVOID baseAddress; 00808 PCHAR address; 00809 00810 if (gSearchAddress) 00811 { 00812 offset = CmpGetSectionLineIndex(InfHandle, Description, RuleIndex, 0); 00813 if (offset) 00814 { 00815 // 00816 // Get the data specified in the inf. 00817 // 00818 00819 cbData = sizeof(data); 00820 00821 if (CmpGetInfData(InfHandle, Description, RuleIndex, 1, data, &cbData)) 00822 { 00823 (PCHAR)gSearchAddress += strtoul(offset, NULL, 16); 00824 00825 // 00826 // Map in the physical address. 00827 // 00828 00829 address = CmpMapPhysicalAddress(&baseAddress, (ULONG)gSearchAddress, cbData); 00830 if (address) 00831 { 00832 00833 // 00834 // Check if the inf data matches data in memory. 00835 // 00836 00837 match = (RtlCompareMemory(address, data, cbData) == cbData); 00838 00839 // 00840 // Unmap the physical address. 00841 // 00842 00843 ZwUnmapViewOfSection(NtCurrentProcess(), baseAddress); 00844 } 00845 } 00846 } 00847 } 00848 00849 return (match); 00850 } 00851 00852 BOOLEAN 00853 CmpMatchPointerRule( 00854 IN PVOID InfHandle, 00855 IN PCHAR Description, 00856 IN ULONG RuleIndex 00857 ) 00858 { 00859 BOOLEAN match = FALSE; 00860 PCHAR segment1; 00861 PCHAR offset1; 00862 PCHAR segment2; 00863 PCHAR offset2; 00864 PCHAR index; 00865 PCHAR op; 00866 CHAR data[MAX_DESCRIPTION_LEN + 1]; 00867 ULONG cbData; 00868 ULONG memory; 00869 ULONG pointer; 00870 PVOID baseAddress; 00871 PCHAR address; 00872 00873 segment1 = CmpGetSectionLineIndex(InfHandle, Description, RuleIndex, 0); 00874 offset1 = CmpGetSectionLineIndex(InfHandle, Description, RuleIndex, 1); 00875 segment2 = CmpGetSectionLineIndex(InfHandle, Description, RuleIndex, 2); 00876 offset2 = CmpGetSectionLineIndex(InfHandle, Description, RuleIndex, 3); 00877 index = CmpGetSectionLineIndex(InfHandle, Description, RuleIndex, 4); 00878 op = CmpGetSectionLineIndex(InfHandle, Description, RuleIndex, 5); 00879 00880 if ( segment1 && offset1 && 00881 segment2 && offset2 && 00882 index && op) 00883 { 00884 // 00885 // Get the data specified in the inf. 00886 // 00887 00888 cbData = sizeof(data); 00889 00890 if (CmpGetInfData(InfHandle, Description, RuleIndex, 6, data, &cbData)) 00891 { 00892 if (strlen(offset2) == 0) 00893 { 00894 memory = strtoul(segment2, NULL, 16) << 4; 00895 } 00896 else 00897 { 00898 memory = (strtoul(segment2, NULL, 16) << 4) + strtoul(offset2, NULL, 16); 00899 } 00900 00901 address = CmpMapPhysicalAddress(&baseAddress, memory, 4); 00902 if (address) 00903 { 00904 pointer = *((PUSHORT)address); 00905 00906 // 00907 // Unmap the physical address. 00908 // 00909 00910 ZwUnmapViewOfSection(NtCurrentProcess(), baseAddress); 00911 00912 if (strlen(offset1) == 0) 00913 { 00914 memory = (strtoul(segment1, NULL, 16) << 4) + pointer; 00915 } 00916 else 00917 { 00918 memory = (strtoul(segment1, NULL, 16) << 4) + strtoul(offset1, NULL, 16); 00919 address = CmpMapPhysicalAddress(&baseAddress, memory, 2); 00920 if (address) 00921 { 00922 memory = ((*(PUSHORT)address) << 4) + pointer; 00923 00924 // 00925 // Unmap the physical address. 00926 // 00927 00928 ZwUnmapViewOfSection(NtCurrentProcess(), baseAddress); 00929 } 00930 } 00931 00932 memory += strtoul(index, NULL, 16); 00933 00934 // 00935 // Map in the physical address. 00936 // 00937 00938 address = CmpMapPhysicalAddress(&baseAddress, memory, cbData); 00939 if (address) 00940 { 00941 match = CmpCheckOperator(op, RtlCompareMemory(address, data, cbData), cbData); 00942 00943 // 00944 // Unmap the physical address. 00945 // 00946 00947 ZwUnmapViewOfSection(NtCurrentProcess(), baseAddress); 00948 } 00949 } 00950 } 00951 } 00952 00953 return (match); 00954 } 00955 00956 BOOLEAN 00957 CmpMatchOemIdRule( 00958 IN PVOID InfHandle, 00959 IN PCHAR Description, 00960 IN ULONG RuleIndex 00961 ) 00962 { 00963 BOOLEAN match = FALSE; 00964 ULONG address; 00965 PCHAR op; 00966 PCHAR oemIdStr; 00967 ULONG oemId; 00968 PCHAR baseAddress; 00969 PPNP_BIOS_TABLE biosTable; 00970 00971 // 00972 // Search for the PnPBIOS structure in the BIOS ROM. 00973 // 00974 00975 address = CmpGetPnPBIOSTableAddress(); 00976 00977 // 00978 // Proceed if we found the PnP BIOS structure. 00979 // 00980 00981 if (address) 00982 { 00983 op = CmpGetSectionLineIndex(InfHandle, Description, RuleIndex, 0); 00984 oemIdStr = CmpGetSectionLineIndex(InfHandle, Description, RuleIndex, 1); 00985 if (op && oemIdStr) 00986 { 00987 00988 if ( strlen(oemIdStr) == 7 && 00989 isalpha(oemIdStr[0]) && 00990 isalpha(oemIdStr[1]) && 00991 isalpha(oemIdStr[2]) && 00992 isxdigit(oemIdStr[3]) && 00993 isxdigit(oemIdStr[4]) && 00994 isxdigit(oemIdStr[5]) && 00995 isxdigit(oemIdStr[6])) 00996 { 00997 00998 biosTable = (PPNP_BIOS_TABLE)CmpMapPhysicalAddress(&baseAddress, address, sizeof(PNP_BIOS_TABLE)); 00999 if (biosTable) 01000 { 01001 oemId = ((ULONG)(oemIdStr[0] & 0x1F) << 26) + 01002 ((ULONG)(oemIdStr[1] & 0x1F) << 21) + 01003 ((ULONG)(oemIdStr[2] & 0x1F) << 16) + 01004 strtoul(&oemIdStr[3], NULL, 16); 01005 01006 // 01007 // We only support EQUAL and NOT EQUAL operators. 01008 // 01009 01010 if (strcmp(op, "=") == 0 || strcmp(op, "==") == 0) 01011 { 01012 match = (oemId == biosTable->Oem); 01013 } 01014 else if( strcmp(op, "<>") == 0 || 01015 strcmp(op, "!=") == 0 || 01016 strcmp(op, "=!") == 0) 01017 { 01018 match = (oemId != biosTable->Oem); 01019 } 01020 01021 // 01022 // Unmap the physical address. 01023 // 01024 01025 ZwUnmapViewOfSection(NtCurrentProcess(), baseAddress); 01026 } 01027 } 01028 } 01029 } 01030 01031 return (match); 01032 } 01033 01034 BOOLEAN 01035 CmpMatchPModeRule( 01036 IN PVOID InfHandle, 01037 IN PCHAR Description, 01038 IN ULONG RuleIndex 01039 ) 01040 { 01041 BOOLEAN match = FALSE; 01042 ULONG address; 01043 CHAR data[MAX_DESCRIPTION_LEN + 1]; 01044 ULONG cbData; 01045 PVOID baseAddress; 01046 PPNP_BIOS_TABLE biosTable; 01047 ULONG pmAddress; 01048 PCHAR pmodeEntry; 01049 01050 // 01051 // Search for the PnPBIOS structure in the BIOS ROM. 01052 // 01053 01054 address = CmpGetPnPBIOSTableAddress(); 01055 01056 // 01057 // Proceed if we found the PnP BIOS structure. 01058 // 01059 01060 if (address) 01061 { 01062 // 01063 // Get the data specified in the inf. 01064 // 01065 01066 cbData = sizeof(data); 01067 if (CmpGetInfData(InfHandle, Description, RuleIndex, 0, data, &cbData)) 01068 { 01069 biosTable = (PPNP_BIOS_TABLE)CmpMapPhysicalAddress(&baseAddress, address, sizeof(PNP_BIOS_TABLE)); 01070 if (biosTable) 01071 { 01072 pmAddress = (biosTable->PMSegment << 4) + biosTable->PMOffset; 01073 01074 // 01075 // Unmap the physical address. 01076 // 01077 01078 ZwUnmapViewOfSection(NtCurrentProcess(), baseAddress); 01079 01080 pmodeEntry = CmpMapPhysicalAddress(&baseAddress, pmAddress, SYSTEM_BIOS_LENGTH); 01081 if (pmodeEntry) 01082 { 01083 if (*pmodeEntry == 0xE9) 01084 { 01085 pmodeEntry += (3 + (*((PUSHORT)&pmodeEntry[1]))); 01086 } 01087 01088 match = (RtlCompareMemory(pmodeEntry, data, cbData) == cbData); 01089 01090 // 01091 // Unmap the physical address. 01092 // 01093 01094 ZwUnmapViewOfSection(NtCurrentProcess(), baseAddress); 01095 } 01096 } 01097 } 01098 } 01099 01100 return (match); 01101 } 01102 01103 BOOLEAN 01104 CmpMatchRmPmSameRule( 01105 IN PVOID InfHandle, 01106 IN PCHAR Description, 01107 IN ULONG RuleIndex 01108 ) 01109 { 01110 BOOLEAN match = FALSE; 01111 ULONG address; 01112 PCHAR baseAddress; 01113 PPNP_BIOS_TABLE biosTable; 01114 01115 // 01116 // Search for the PnPBIOS structure in the BIOS ROM. 01117 // 01118 01119 address = CmpGetPnPBIOSTableAddress(); 01120 01121 // 01122 // Proceed if we found the PnP BIOS structure. 01123 // 01124 01125 if (address) 01126 { 01127 biosTable = CmpMapPhysicalAddress(&baseAddress, address, sizeof(PNP_BIOS_TABLE)); 01128 if (biosTable) 01129 { 01130 match = ( biosTable->RMSegment == biosTable->PMSegment && 01131 biosTable->RMOffset == biosTable->PMOffset); 01132 01133 // 01134 // Unmap the physical address. 01135 // 01136 01137 ZwUnmapViewOfSection(NtCurrentProcess(), baseAddress); 01138 } 01139 } 01140 01141 return (match); 01142 } 01143 01144 BOOLEAN 01145 CmpMatchInstallRule( 01146 IN PVOID InfHandle, 01147 IN PCHAR Description, 01148 IN ULONG RuleIndex 01149 ) 01150 { 01151 BOOLEAN match = FALSE; 01152 PCHAR install; 01153 01154 install = CmpGetSectionLineIndex(InfHandle, Description, RuleIndex, 0); 01155 if (install) 01156 { 01157 if (CmpGenInstall(InfHandle, install)) 01158 { 01159 // 01160 // Successfully installed the specified section. 01161 // 01162 01163 match = TRUE; 01164 } 01165 } 01166 01167 return (match); 01168 } 01169 01170 BOOLEAN 01171 CmpMatchAcpiOemIdRule( 01172 IN PVOID InfHandle, 01173 IN PCHAR Description, 01174 IN ULONG RuleIndex 01175 ) 01176 /*++ 01177 01178 Routine Description: 01179 01180 This function processes a ACPI OEM ID rule from an INF file 01181 01182 Examples: 01183 01184 AcpiOemId="RSDT", "123456" 01185 01186 is true if the RSDT has the OEM ID of 123456. 01187 01188 AcpiOemId="DSDT", "768000" 01189 01190 is true if the DSDT has the OEM ID of 768000. 01191 01192 Arguments: 01193 01194 InfHandle - Handle of the inf containing the rule. 01195 01196 Description - Specifies the section name the rule is in 01197 01198 RuleIndex - Specifies the index of the rule in the section 01199 01200 Return Value: 01201 01202 TRUE - the computer has the specified ACPI OEM ID. 01203 01204 FALSE - the computer does not have the specified ACPI OEM ID. 01205 01206 --*/ 01207 01208 { 01209 BOOLEAN anyCase = FALSE; 01210 BOOLEAN match = FALSE; 01211 PCHAR tableName; 01212 PCHAR oemId; 01213 PCHAR optionalArgs; 01214 ULONG length; 01215 PDESCRIPTION_HEADER header; 01216 CHAR tableOemId[7]; 01217 STRING acpiString; 01218 STRING tableString; 01219 01220 tableName = CmpGetSectionLineIndex( 01221 InfHandle, 01222 Description, 01223 RuleIndex, 01224 0 01225 ); 01226 oemId = CmpGetSectionLineIndex( 01227 InfHandle, 01228 Description, 01229 RuleIndex, 01230 1 01231 ); 01232 if (tableName && oemId) { 01233 01234 // 01235 // See if we have to do a case insensitive match 01236 // 01237 optionalArgs = CmpGetSectionLineIndex( 01238 InfHandle, 01239 Description, 01240 RuleIndex, 01241 2 01242 ); 01243 if (optionalArgs) { 01244 01245 if (_stricmp(optionalArgs,"any") == 0) { 01246 01247 anyCase = TRUE; 01248 01249 } 01250 01251 } 01252 01253 // 01254 // Find the specified table in the BIOS ROM. 01255 // 01256 header = CmpFindACPITable(*(PULONG)tableName, &length); 01257 if (header) { 01258 01259 // 01260 // Build the OEM id from the table 01261 // 01262 RtlZeroMemory(tableOemId, sizeof(tableOemId)); 01263 RtlCopyMemory(tableOemId, header->OEMID, sizeof(header->OEMID)); 01264 RtlInitString( &tableString, tableOemId ); 01265 01266 // 01267 // And one from the string in the file 01268 // 01269 RtlInitString( &acpiString, oemId ); 01270 01271 // 01272 // Now see if they are equal 01273 // 01274 match = RtlEqualString( &acpiString, &tableString, anyCase ); 01275 01276 // 01277 // Unmap the table 01278 // 01279 MmUnmapIoSpace(header, length ); 01280 01281 } 01282 01283 } 01284 return (match); 01285 } 01286 01287 BOOLEAN 01288 CmpMatchAcpiOemTableIdRule( 01289 IN PVOID InfHandle, 01290 IN PCHAR Description, 01291 IN ULONG RuleIndex 01292 ) 01293 /*++ 01294 01295 Routine Description: 01296 01297 This function processes a ACPI OEM Table ID rule from an INF file. 01298 01299 Examples: 01300 01301 AcpiOemTableId="RSDT", "12345678" 01302 01303 is true if the RSDT has the Oem Table ID of 12345678. 01304 01305 AcpiOemTableId="DSDT", "87654321" 01306 01307 is true if the DSDT has the Oem Table ID of 87654321. 01308 01309 Arguments: 01310 01311 InfHandle - Handle of the inf containing the rule. 01312 01313 Description - Specifies the section name the rule is in 01314 01315 RuleIndex - Specifies the index of the rule in the section 01316 01317 Return Value: 01318 01319 TRUE - the computer has the specified ACPI OEM Table ID. 01320 01321 FALSE - the computer does not have the specified ACPI OEM Table ID. 01322 01323 --*/ 01324 01325 { 01326 BOOLEAN match = FALSE; 01327 PCHAR tableName; 01328 PCHAR oemTableId; 01329 ULONG length; 01330 PDESCRIPTION_HEADER header; 01331 ULONG idLength; 01332 CHAR acpiOemTableId[8]; 01333 01334 tableName = CmpGetSectionLineIndex( 01335 InfHandle, 01336 Description, 01337 RuleIndex, 01338 0 01339 ); 01340 oemTableId = CmpGetSectionLineIndex( 01341 InfHandle, 01342 Description, 01343 RuleIndex, 01344 1 01345 ); 01346 if (tableName && oemTableId) { 01347 01348 // 01349 // Find the specified table in the BIOS ROM. 01350 // 01351 header = CmpFindACPITable(*(PULONG)tableName, &length); 01352 if (header) { 01353 01354 RtlZeroMemory(acpiOemTableId, sizeof(acpiOemTableId)); 01355 idLength = strlen(oemTableId); 01356 if (idLength > sizeof(acpiOemTableId)) { 01357 01358 idLength = sizeof(acpiOemTableId); 01359 01360 } 01361 RtlCopyMemory(acpiOemTableId, oemTableId, idLength); 01362 match = RtlEqualMemory(acpiOemTableId, header->OEMTableID, sizeof(header->OEMTableID)); 01363 MmUnmapIoSpace( header, length ); 01364 01365 } 01366 01367 } 01368 return (match); 01369 } 01370 01371 BOOLEAN 01372 CmpMatchAcpiOemRevisionRule( 01373 IN PVOID InfHandle, 01374 IN PCHAR Description, 01375 IN ULONG RuleIndex 01376 ) 01377 /*++ 01378 01379 Routine Description: 01380 01381 This function processes a ACPI Oem Revision rule from an INF file. 01382 01383 Examples: 01384 01385 AcpiOemRevision="=","RSDT", 1234 01386 01387 is true if the RSDT has the Oem Revision EQUAL to 1234. 01388 01389 AcpiOemRevision=">","DSDT", 4321 01390 01391 is true if the DSDT has the Oem Revision GREATER than 4321. 01392 01393 Arguments: 01394 01395 InfHandle - Handle of the inf containing the rule. 01396 01397 Description - Specifies the section name the rule is in 01398 01399 RuleIndex - Specifies the index of the rule in the section 01400 01401 Return Value: 01402 01403 TRUE - the computer has the specified ACPI Oem Revision. 01404 01405 FALSE - the computer does not have the specified ACPI Oem Revision. 01406 01407 --*/ 01408 01409 { 01410 BOOLEAN match = FALSE; 01411 PCHAR op; 01412 PCHAR tableName; 01413 PCHAR oemRevisionStr; 01414 ULONG oemRevision; 01415 ULONG length; 01416 PDESCRIPTION_HEADER header; 01417 01418 op = CmpGetSectionLineIndex( 01419 InfHandle, 01420 Description, 01421 RuleIndex, 01422 0 01423 ); 01424 tableName = CmpGetSectionLineIndex( 01425 InfHandle, 01426 Description, 01427 RuleIndex, 01428 1 01429 ); 01430 oemRevisionStr = CmpGetSectionLineIndex( 01431 InfHandle, 01432 Description, 01433 RuleIndex, 01434 2 01435 ); 01436 if (op && tableName && oemRevisionStr) { 01437 01438 // 01439 // Find the specified table. 01440 // 01441 header = CmpFindACPITable(*(PULONG)tableName, &length); 01442 if (header) { 01443 01444 RtlCharToInteger(oemRevisionStr, 16, &oemRevision); 01445 match = CmpCheckOperator(op, header->OEMRevision, oemRevision); 01446 MmUnmapIoSpace(header, length); 01447 01448 } 01449 01450 } 01451 return(match); 01452 01453 } 01454 01455 BOOLEAN 01456 CmpMatchAcpiRevisionRule( 01457 IN PVOID InfHandle, 01458 IN PCHAR Description, 01459 IN ULONG RuleIndex 01460 ) 01461 /*++ 01462 01463 Routine Description: 01464 01465 This function processes a ACPI Revision rule from an INF file. 01466 01467 Examples: 01468 01469 AcpiRevision="=", "RSDT", 1234 01470 01471 is true if the RSDT ACPI Revision is EQUAL to 1234. 01472 01473 AcpiRevision=">", "DSDT", 4321 01474 01475 is true if the DSDT ACPI Revision is GREATER than 4321. 01476 01477 Arguments: 01478 01479 InfHandle - Handle of the inf containing the rule. 01480 01481 Description - Specifies the section name the rule is in 01482 01483 RuleIndex - Specifies the index of the rule in the section 01484 01485 Return Value: 01486 01487 TRUE - the computer has the specified ACPI Revision. 01488 01489 FALSE - the computer does not have the specified ACPI Revision. 01490 01491 --*/ 01492 01493 { 01494 BOOLEAN match = FALSE; 01495 PCHAR op; 01496 PCHAR tableName; 01497 PCHAR revisionStr; 01498 ULONG revision; 01499 ULONG length; 01500 PDESCRIPTION_HEADER header; 01501 01502 op = CmpGetSectionLineIndex( 01503 InfHandle, 01504 Description, 01505 RuleIndex, 01506 0 01507 ); 01508 tableName = CmpGetSectionLineIndex( 01509 InfHandle, 01510 Description, 01511 RuleIndex, 01512 1 01513 ); 01514 revisionStr = CmpGetSectionLineIndex( 01515 InfHandle, 01516 Description, 01517 RuleIndex, 01518 2 01519 ); 01520 if (op && tableName && revisionStr){ 01521 01522 // 01523 // Find the specified table. 01524 // 01525 header = CmpFindACPITable(*(PULONG)tableName, &length); 01526 if (header) { 01527 01528 RtlCharToInteger(revisionStr, 16, &revision); 01529 match = CmpCheckOperator(op, header->Revision, revision); 01530 MmUnmapIoSpace(header, length); 01531 01532 } 01533 01534 } 01535 return(match); 01536 01537 } 01538 01539 BOOLEAN 01540 CmpMatchAcpiCreatorRevisionRule( 01541 IN PVOID InfHandle, 01542 IN PCHAR Description, 01543 IN ULONG RuleIndex 01544 ) 01545 /*++ 01546 01547 Routine Description: 01548 01549 This function processes a ACPI Creator Revision rule from an INF file. 01550 01551 Examples: 01552 01553 AcpiCreatorRevision="=", "RSDT", 1234 01554 01555 is true if the RSDT ACPI Creator Revision is EQUAL to 1234. 01556 01557 AcpiCreatorRevision=">", "DSDT", 4321 01558 01559 is true if the DSDT ACPI Creator Revision is GREATER than 4321. 01560 01561 Arguments: 01562 01563 InfHandle - Handle of the inf containing the rule. 01564 01565 Description - Specifies the section name the rule is in 01566 01567 RuleIndex - Specifies the index of the rule in the section 01568 01569 Return Value: 01570 01571 TRUE - the computer has the specified ACPI Creator Revision. 01572 01573 FALSE - the computer does not have the specified ACPI Creator Revision. 01574 01575 --*/ 01576 01577 { 01578 BOOLEAN match = FALSE; 01579 PCHAR op; 01580 PCHAR tableName; 01581 PCHAR creatorRevisionStr; 01582 ULONG creatorRevision; 01583 ULONG length; 01584 PDESCRIPTION_HEADER header; 01585 01586 op = CmpGetSectionLineIndex( 01587 InfHandle, 01588 Description, 01589 RuleIndex, 01590 0 01591 ); 01592 tableName = CmpGetSectionLineIndex( 01593 InfHandle, 01594 Description, 01595 RuleIndex, 01596 1 01597 ); 01598 creatorRevisionStr = CmpGetSectionLineIndex( 01599 InfHandle, 01600 Description, 01601 RuleIndex, 01602 2 01603 ); 01604 if (op && tableName && creatorRevisionStr) { 01605 01606 // 01607 // Find the specified table. 01608 // 01609 header = CmpFindACPITable(*(PULONG)tableName, &length); 01610 if (header){ 01611 01612 RtlCharToInteger(creatorRevisionStr, 16, &creatorRevision); 01613 match = CmpCheckOperator(op, header->CreatorRev, creatorRevision); 01614 MmUnmapIoSpace( header, length ); 01615 01616 } 01617 01618 } 01619 return(match); 01620 } 01621 01622 BOOLEAN 01623 CmpMatchAcpiCreatorIdRule( 01624 IN PVOID InfHandle, 01625 IN PCHAR Description, 01626 IN ULONG RuleIndex 01627 ) 01628 /*++ 01629 01630 Routine Description: 01631 01632 This function processes a ACPI Creator ID rule from an INF file. 01633 01634 Examples: 01635 01636 AcpiCreatorId="RSDT", "MSFT" 01637 01638 is true if the RSDT has the Creator ID of MSFT. 01639 01640 Arguments: 01641 01642 InfHandle - Handle of the inf containing the rule. 01643 01644 Description - Specifies the section name the rule is in 01645 01646 RuleIndex - Specifies the index of the rule in the section 01647 01648 Return Value: 01649 01650 TRUE - the computer has the specified ACPI Creator ID. 01651 01652 FALSE - the computer does not have the specified ACPI Creator ID. 01653 01654 --*/ 01655 01656 { 01657 BOOLEAN match = FALSE; 01658 PCHAR tableName; 01659 PCHAR creatorId; 01660 ULONG length; 01661 PDESCRIPTION_HEADER header; 01662 ULONG idLength; 01663 CHAR acpiCreatorId[6]; 01664 01665 tableName = CmpGetSectionLineIndex( 01666 InfHandle, 01667 Description, 01668 RuleIndex, 01669 0 01670 ); 01671 creatorId = CmpGetSectionLineIndex( 01672 InfHandle, 01673 Description, 01674 RuleIndex, 01675 1 01676 ); 01677 if (tableName && creatorId) { 01678 01679 // 01680 // Find the specified table. 01681 // 01682 header = CmpFindACPITable(*(PULONG)tableName, &length); 01683 if (header) { 01684 01685 RtlZeroMemory(acpiCreatorId, sizeof(acpiCreatorId)); 01686 idLength = strlen(creatorId); 01687 if (idLength > sizeof(acpiCreatorId)) { 01688 01689 idLength = sizeof(acpiCreatorId); 01690 01691 } 01692 RtlCopyMemory(acpiCreatorId, creatorId, idLength); 01693 match = RtlEqualMemory(acpiCreatorId, header->CreatorID, sizeof(header->CreatorID)); 01694 MmUnmapIoSpace( header, length ); 01695 01696 } 01697 01698 } 01699 return(match); 01700 } 01701 01702 BOOLEAN 01703 CmpGetInfData( 01704 IN PVOID InfHandle, 01705 IN PCHAR Section, 01706 IN ULONG LineIndex, 01707 IN ULONG ValueIndex, 01708 IN OUT PCHAR Buffer, 01709 IN OUT PULONG BufferSize 01710 ) 01711 01712 /*++ 01713 01714 Routine Description: 01715 01716 This routine reads and parses data from the inf. It understands 01717 two kinds of data 1. String 2. Binary. 01718 01719 Examples- 01720 01721 B,02 - byte 0x02 01722 B,72,0D,FF,0F - sequence of bytes 0x72 0x0D 0xFF 0x0F or the DWORD 0x0FFF0D72 01723 S,COMPAQ - ASCII string "COMPAQ" 01724 01725 Input Parameters: 01726 01727 InfHandle - Handle to the inf to be read. 01728 01729 Section - Section name to be read. 01730 01731 LineIndex - Index of the line in the Section to be read. 01732 01733 ValueIndex - First value to be read on the LineIndex. 01734 01735 Buffer - Parsed data gets returned in this buffer. 01736 01737 BufferSize - On entry, contains the size of Buffer. 01738 The number of bytes parsed in gets returned in this 01739 variable. 01740 01741 Return Value: 01742 01743 TRUE iff data was parsed in successfully. Else FALSE. 01744 01745 --*/ 01746 01747 { 01748 BOOLEAN result = FALSE; 01749 ULONG cbData; 01750 PCHAR data; 01751 ULONG remainingBytes; 01752 01753 // 01754 // Validate input parameters. 01755 // 01756 01757 if (Buffer && BufferSize && *BufferSize) 01758 { 01759 // 01760 // Read in the data type "S" or "B". 01761 // 01762 01763 PCHAR type = CmpGetSectionLineIndex(InfHandle, Section, LineIndex, ValueIndex++); 01764 if (type) 01765 { 01766 // 01767 // Initialize local data. 01768 // 01769 01770 remainingBytes = *BufferSize; 01771 01772 // 01773 // Process Binary data. 01774 // 01775 01776 if (_stricmp(type, "B") == 0) 01777 { 01778 01779 // 01780 // Parse data as long as there is more data and the buffer is not full. 01781 // 01782 01783 for (result = TRUE; result == TRUE && remainingBytes; remainingBytes--) 01784 { 01785 CHAR value; 01786 01787 // 01788 // Read in the data. 01789 // 01790 01791 data = CmpGetSectionLineIndex(InfHandle, Section, LineIndex, ValueIndex++); 01792 if (data) 01793 { 01794 // 01795 // Convert the data read in and validate that is indeed a HEX value. 01796 // 01797 01798 value = (CHAR)strtoul(data, NULL, 16); 01799 if (value == 0 && strcmp(data, "00") && strcmp(data, "0")) 01800 { 01801 result = FALSE; 01802 } 01803 else 01804 { 01805 *Buffer++ = value; 01806 } 01807 } 01808 else 01809 { 01810 break; 01811 } 01812 } 01813 01814 // 01815 // Return the number of bytes parsed in. 01816 // 01817 01818 *BufferSize -= remainingBytes; 01819 } 01820 01821 // 01822 // Process String data. 01823 // 01824 01825 else if(_stricmp(type, "S") == 0) 01826 { 01827 // 01828 // Read in the string. 01829 // 01830 01831 data = CmpGetSectionLineIndex(InfHandle, Section, LineIndex, ValueIndex); 01832 01833 // 01834 // Only copy as much data as the buffer can hold. 01835 // 01836 01837 cbData = min(remainingBytes, strlen(data)); 01838 RtlCopyBytes(Buffer, data, cbData); 01839 01840 // 01841 // Return the number of bytes actually copied. 01842 // 01843 01844 *BufferSize = cbData; 01845 result = TRUE; 01846 } 01847 } 01848 } 01849 01850 return (result); 01851 } 01852 01853 PVOID 01854 CmpMapPhysicalAddress( 01855 IN OUT PVOID *BaseAddress, 01856 IN ULONG Address, 01857 IN ULONG Size 01858 ) 01859 01860 /*++ 01861 01862 Routine Description: 01863 01864 This routine maps the specified physical segment into the process 01865 virtual memory. 01866 01867 Input Parameters: 01868 01869 Segment - Segment to be mapped. 01870 01871 Size - Segment size to be mapped. 01872 01873 Return Value: 01874 01875 Virtual address for the mapped segment. 01876 01877 --*/ 01878 01879 { 01880 UNICODE_STRING sectionName; 01881 OBJECT_ATTRIBUTES objectAttributes; 01882 HANDLE sectionHandle; 01883 NTSTATUS status; 01884 PVOID baseAddress; 01885 ULONG viewSize; 01886 LARGE_INTEGER viewBase; 01887 PVOID ptr = NULL; 01888 01889 *BaseAddress = NULL; 01890 01891 RtlInitUnicodeString(&sectionName, L"\\Device\\PhysicalMemory"); 01892 InitializeObjectAttributes( &objectAttributes, 01893 &sectionName, 01894 OBJ_CASE_INSENSITIVE, 01895 (HANDLE)NULL, 01896 (PSECURITY_DESCRIPTOR)NULL); 01897 status = ZwOpenSection( &sectionHandle, 01898 SECTION_MAP_READ, 01899 &objectAttributes); 01900 if (NT_SUCCESS(status)) 01901 { 01902 baseAddress = NULL; 01903 viewSize = Size; 01904 viewBase.LowPart = Address & ~(0xFFF); 01905 viewBase.HighPart = 0; 01906 status = ZwMapViewOfSection( sectionHandle, 01907 NtCurrentProcess(), 01908 &baseAddress, 01909 0, 01910 viewSize, 01911 &viewBase, 01912 &viewSize, 01913 ViewUnmap, 01914 MEM_DOS_LIM, 01915 PAGE_READWRITE); 01916 if (NT_SUCCESS(status)) 01917 { 01918 ptr = (PVOID)((PCHAR)baseAddress + (Address & 0xFFF)); 01919 *BaseAddress = baseAddress; 01920 } 01921 } 01922 01923 return (ptr); 01924 } 01925 01926 BOOLEAN 01927 CmpCheckOperator( 01928 IN PCHAR Operator, 01929 IN ULONG Lhs, 01930 IN ULONG Rhs 01931 ) 01932 01933 /*++ 01934 01935 Routine Description: 01936 01937 This routine tests condition specified by the operator by 01938 applying it to the specified LHS and RHS arguments. 01939 01940 Input Parameters: 01941 01942 Operator - Is the operator to be tested. 01943 01944 Lhs - Left Hand Side argument for the Operator. 01945 01946 Rhs - Right Hand Side argument for the Operator. 01947 01948 Return Value: 01949 01950 True iff the condition Lhs Operator Rhs is satisfied. 01951 01952 --*/ 01953 01954 { 01955 BOOLEAN result = FALSE; 01956 01957 // 01958 // We are pretty lenient about which operators we support. 01959 // 01960 01961 // 01962 // "=" or "==" for EQUAL. 01963 // 01964 01965 if (strcmp(Operator, "=") == 0 || strcmp(Operator, "==") == 0) 01966 { 01967 result = (Lhs == Rhs); 01968 } 01969 01970 // 01971 // "!=" or "=!" or "<>" for NOT EQUAL. 01972 // 01973 01974 else if( strcmp(Operator, "!=") == 0 || 01975 strcmp(Operator, "<>") == 0 || 01976 strcmp(Operator, "=!") == 0) 01977 { 01978 result = (Lhs != Rhs); 01979 } 01980 01981 // 01982 // "<" for LESS THAN. 01983 // 01984 01985 else if(strcmp(Operator, "<") == 0) 01986 { 01987 result = (Lhs < Rhs); 01988 } 01989 01990 // 01991 // "<=" or "=<" for LESS THAN or EQUAL. 01992 // 01993 01994 else if(strcmp(Operator, "<=") == 0 || strcmp(Operator, "=<") == 0) 01995 { 01996 result = (Lhs <= Rhs); 01997 } 01998 01999 // 02000 // ">" for GREATER THAN. 02001 // 02002 02003 else if(strcmp(Operator, ">") == 0) 02004 { 02005 result = (Lhs > Rhs); 02006 } 02007 02008 // 02009 // ">=" or "=>" for GREATER THAN or EQUAL. 02010 // 02011 02012 else if(strcmp(Operator, ">=") == 0 || strcmp(Operator, "=>") == 0) 02013 { 02014 result = (Lhs >= Rhs); 02015 } 02016 else 02017 { 02018 DbgPrint("Invalid operator %s used!\n", Operator); 02019 } 02020 02021 return (result); 02022 } 02023 02024 PVOID 02025 CmpFindPattern( 02026 IN PCHAR Buffer, 02027 IN ULONG BufSize, 02028 IN PCHAR Pattern, 02029 IN ULONG PatSize, 02030 IN BOOLEAN IgnoreCase, 02031 IN ULONG Step 02032 ) 02033 02034 /*++ 02035 02036 Routine Description: 02037 02038 This routine searches the buffer for the specified pattern of data. 02039 02040 Input Parameters: 02041 02042 Buffer - Buffer to be searched. 02043 02044 BufSize - Size of this buffer. 02045 02046 Pattern - Pattern to be searched. 02047 02048 PatSize - Size of the pattern. 02049 02050 IgnoreCase - TRUE if the search is to be case insensitive. 02051 02052 Return Value: 02053 02054 Returns the pointer into the buffer where the pattern is first found. 02055 02056 --*/ 02057 02058 { 02059 PCHAR bufEnd; 02060 02061 if (PatSize > BufSize) 02062 { 02063 return (NULL); 02064 } 02065 02066 if (PatSize == 0) 02067 { 02068 PatSize = strlen(Pattern); 02069 } 02070 02071 if (Step == 0) 02072 { 02073 Step = 1; 02074 } 02075 02076 for ( bufEnd = Buffer + BufSize; 02077 Buffer + PatSize < bufEnd; 02078 Buffer += Step) 02079 { 02080 if (IgnoreCase) 02081 { 02082 if (_strnicmp(Buffer, Pattern, PatSize) == 0) 02083 { 02084 return (Buffer); 02085 } 02086 } 02087 else 02088 { 02089 if (strncmp(Buffer, Pattern, PatSize) == 0) 02090 { 02091 return (Buffer); 02092 } 02093 } 02094 } 02095 02096 return (NULL); 02097 } 02098 02099 ULONG 02100 CmpGetPnPBIOSTableAddress( 02101 VOID 02102 ) 02103 02104 /*++ 02105 02106 Routine Description: 02107 02108 This routine searches the BIOS ROM for the PnP BIOS installation 02109 structure. 02110 02111 Input Parameters: 02112 02113 None. 02114 02115 Return Value: 02116 02117 Returns the physical address in the ROM BIOS where the PnP 02118 BIOS structure is located. 02119 02120 --*/ 02121 02122 { 02123 static ULONG tableAddress = (ULONG)-1; 02124 PVOID baseAddress; 02125 PPNP_BIOS_TABLE address; 02126 PPNP_BIOS_TABLE lastAddress; 02127 ULONG i; 02128 ULONG checksum; 02129 02130 if (tableAddress == (ULONG)-1) 02131 { 02132 // 02133 // Search for the PnPBIOS structure in the BIOS ROM. 02134 // 02135 02136 address = (PPNP_BIOS_TABLE)CmpMapPhysicalAddress(&baseAddress, 0xF0000, SYSTEM_BIOS_LENGTH); 02137 if (address) 02138 { 02139 for ( lastAddress = (PPNP_BIOS_TABLE)((PCHAR)address + SYSTEM_BIOS_LENGTH - 0x10); 02140 address < lastAddress; 02141 (PCHAR)address += 0x10) 02142 { 02143 if (address->Signature == PNPBIOS_SIGNATURE) 02144 { 02145 for ( i = 0, checksum = 0; 02146 i < address->Length; 02147 i++) 02148 { 02149 checksum += ((PUCHAR)address)[i]; 02150 } 02151 02152 if ( (checksum & 0xFF) == 0 && 02153 address->Length >= 0x21) 02154 { 02155 tableAddress = 0xF0000 + (SYSTEM_BIOS_LENGTH - 10) - ((PCHAR)lastAddress - (PCHAR)address); 02156 break; 02157 } 02158 } 02159 } 02160 02161 // 02162 // Unmap the physical address. 02163 // 02164 02165 ZwUnmapViewOfSection(NtCurrentProcess(), baseAddress); 02166 } 02167 } 02168 02169 return (tableAddress); 02170 } 02171 02172 PDESCRIPTION_HEADER 02173 CmpFindACPITable( 02174 IN ULONG Signature, 02175 IN OUT PULONG Length 02176 ) 02177 { 02178 PDESCRIPTION_HEADER header = NULL; 02179 PDESCRIPTION_HEADER tempHeader = NULL; 02180 static PHYSICAL_ADDRESS rsdtAddress = { -1, -1 }; 02181 ULONG length = 0; 02182 02183 // 02184 // Use the cached location of RSDT address if available. 02185 // 02186 if (rsdtAddress.QuadPart == -1) { 02187 02188 NTSTATUS status; 02189 PACPI_BIOS_MULTI_NODE rsdpMulti; 02190 02191 rsdtAddress.QuadPart = 0; 02192 // 02193 // Get the multinode 02194 // 02195 status = CmpFindRSDTTable( &rsdpMulti ); 02196 if (!NT_SUCCESS(status)) { 02197 02198 return NULL; 02199 02200 } 02201 02202 // 02203 // Map the address 02204 // 02205 rsdtAddress.LowPart = rsdpMulti->RsdtAddress.LowPart; 02206 rsdtAddress.HighPart = rsdpMulti->RsdtAddress.HighPart; 02207 02208 // 02209 // Done with the multinode 02210 // 02211 ExFreePool( rsdpMulti ); 02212 02213 } 02214 02215 // 02216 // If we have an address 02217 // 02218 if (rsdtAddress.QuadPart) { 02219 02220 // 02221 // Map in the the rsdt table 02222 // 02223 tempHeader = MmMapIoSpace( 02224 rsdtAddress, 02225 sizeof(DESCRIPTION_HEADER), 02226 MmCached 02227 ); 02228 if (tempHeader == NULL) { 02229 02230 DbgPrint("CmpFindACPITable: Cannot map RSDT at %I64x\n", rsdtAddress.QuadPart); 02231 return NULL; 02232 02233 } 02234 02235 // 02236 // If what we are looking for is the RSDT, then we are done 02237 // 02238 if (Signature == RSDT_SIGNATURE) { 02239 02240 header = tempHeader; 02241 length = sizeof(DESCRIPTION_HEADER); 02242 02243 } else if (Signature == DSDT_SIGNATURE) { 02244 02245 PFADT fadt; 02246 PHYSICAL_ADDRESS dsdtAddress; 02247 ULONG tempLength; 02248 02249 fadt = (PFADT) CmpFindACPITable( FADT_SIGNATURE, &length ); 02250 if (fadt) { 02251 02252 dsdtAddress.HighPart = 0; 02253 dsdtAddress.LowPart = fadt->dsdt; 02254 02255 // 02256 // Done with the FADT 02257 // 02258 MmUnmapIoSpace( fadt, length ); 02259 02260 // 02261 // Map in the dsdt table 02262 // 02263 header = MmMapIoSpace( 02264 dsdtAddress, 02265 sizeof(DESCRIPTION_HEADER), 02266 MmCached 02267 ); 02268 if (header == NULL) { 02269 02270 DbgPrint( 02271 "CmpFindACPITable: Cannot map DSDT at %I64x\n", 02272 dsdtAddress.QuadPart 02273 ); 02274 MmUnmapIoSpace( tempHeader, sizeof(DESCRIPTION_HEADER) ); 02275 return NULL; 02276 02277 } 02278 length = sizeof(DESCRIPTION_HEADER); 02279 02280 } else { 02281 02282 DbgPrint("CmpFindACPITable: Cannot find FADT\n"); 02283 MmUnmapIoSpace( tempHeader, sizeof(DESCRIPTION_HEADER) ); 02284 return NULL; 02285 02286 } 02287 02288 } else { 02289 02290 PHYSICAL_ADDRESS tableAddress; 02291 PRSDT rsdt; 02292 ULONG i; 02293 ULONG num; 02294 ULONG rsdtLength; 02295 02296 // 02297 // Map in the entire RSDT 02298 // 02299 rsdtLength = tempHeader->Length; 02300 rsdt = (PRSDT) MmMapIoSpace( rsdtAddress, rsdtLength, MmCached ); 02301 if (rsdt == NULL) { 02302 02303 DbgPrint( 02304 "CmpFindACPITable: Cannot map RSDT at %I64x\n", 02305 rsdtAddress.QuadPart 02306 ); 02307 MmUnmapIoSpace( tempHeader, sizeof(DESCRIPTION_HEADER) ); 02308 return NULL; 02309 02310 } 02311 02312 // 02313 // Done with the temp header 02314 // 02315 MmUnmapIoSpace( tempHeader, sizeof(DESCRIPTION_HEADER) ); 02316 02317 // 02318 // Look at all the table entries for the header that we care about 02319 // 02320 num = TABLE_ENTRIES_FROM_RSDT_POINTER( rsdt ); 02321 for (i = 0; i < num ; i ++) { 02322 02323 // 02324 // Get the address of the table 02325 // 02326 tableAddress.HighPart = 0; 02327 tableAddress.LowPart = rsdt->Tables[i]; 02328 02329 // 02330 // Map in the header 02331 // 02332 tempHeader = MmMapIoSpace( 02333 tableAddress, 02334 sizeof(DESCRIPTION_HEADER), 02335 MmCached 02336 ); 02337 if (!tempHeader) { 02338 02339 DbgPrint( 02340 "CmpFindACPITable: Cannot map header at %I64x\n", 02341 tableAddress.QuadPart 02342 ); 02343 MmUnmapIoSpace( rsdt, rsdtLength ); 02344 return NULL; 02345 02346 } 02347 02348 // 02349 // Signature check 02350 // 02351 if (tempHeader->Signature != Signature) { 02352 02353 MmUnmapIoSpace( tempHeader, sizeof(DESCRIPTION_HEADER) ); 02354 continue; 02355 02356 } 02357 02358 // 02359 // Are we looking at the FADT? 02360 // 02361 if (Signature == FADT_SIGNATURE) { 02362 02363 // 02364 // Map the entire table for this one 02365 // 02366 length = tempHeader->Length; 02367 header = MmMapIoSpace( tableAddress, length, MmCached ); 02368 02369 // 02370 // Unmap the old table 02371 // 02372 MmUnmapIoSpace( tempHeader, sizeof(DESCRIPTION_HEADER) ); 02373 02374 // 02375 // Did we successfully map the header? 02376 // 02377 if (header == NULL ) { 02378 02379 DbgPrint( 02380 "CmpFindACPITable: Cannot map FADT at %I64x\n", 02381 tableAddress.QuadPart 02382 ); 02383 MmUnmapIoSpace( rsdt, rsdtLength ); 02384 return NULL; 02385 02386 } 02387 02388 } else { 02389 02390 // 02391 // Remember where the table and length are stored 02392 // 02393 length = sizeof(DESCRIPTION_HEADER); 02394 header = tempHeader; 02395 02396 } 02397 02398 } // for 02399 02400 // 02401 // Done with the rsdt 02402 // 02403 MmUnmapIoSpace( rsdt, rsdtLength ); 02404 02405 } 02406 02407 // 02408 // If we found the table, return its length. 02409 // 02410 if (Length) { 02411 02412 if (header) { 02413 02414 *Length = length; 02415 02416 } else { 02417 02418 *Length = 0; 02419 02420 } 02421 02422 } 02423 02424 } 02425 02426 return (header); 02427 } 02428 02429 NTSTATUS 02430 CmpFindRSDTTable( 02431 OUT PACPI_BIOS_MULTI_NODE *Rsdt 02432 ) 02433 /*++ 02434 02435 Routine Description: 02436 02437 This function looks into the registry to find the ACPI RSDT, 02438 which was stored there by ntdetect.com 02439 02440 Arguments: 02441 02442 RsdtPtr - Pointer to a buffer that contains the ACPI 02443 Root System Description Pointer Structure. 02444 The caller is responsible for freeing this 02445 buffer. Note: This is returned in non-paged 02446 pool. 02447 02448 Return Value: 02449 02450 A NTSTATUS code to indicate the result of the initialization. 02451 02452 --*/ 02453 { 02454 BOOLEAN same; 02455 HANDLE hMFunc; 02456 HANDLE hBus; 02457 NTSTATUS status; 02458 OBJECT_ATTRIBUTES objectAttributes; 02459 PACPI_BIOS_MULTI_NODE multiNode; 02460 PCM_PARTIAL_RESOURCE_DESCRIPTOR prd; 02461 PCM_PARTIAL_RESOURCE_LIST prl; 02462 PKEY_VALUE_PARTIAL_INFORMATION valueInfo; 02463 PWSTR p; 02464 ULONG i; 02465 ULONG length; 02466 ULONG multiNodeSize; 02467 UNICODE_STRING unicodeString; 02468 UNICODE_STRING unicodeValueName; 02469 UNICODE_STRING biosId; 02470 WCHAR wbuffer[10]; 02471 02472 PAGED_CODE(); 02473 02474 // 02475 // Look in the registry for the "ACPI BIOS bus" data 02476 // 02477 RtlInitUnicodeString( &unicodeString, rgzMultiFunctionAdapter ); 02478 InitializeObjectAttributes( 02479 &objectAttributes, 02480 &unicodeString, 02481 OBJ_CASE_INSENSITIVE, 02482 NULL, // handle 02483 NULL 02484 ); 02485 status = ZwOpenKey( &hMFunc, KEY_READ, &objectAttributes ); 02486 if (!NT_SUCCESS(status)) { 02487 02488 DbgPrint("CmpFindRSDTTable: Cannot open MultifunctionAdapter registry key.\n"); 02489 return status; 02490 02491 } 02492 02493 // 02494 // We will need to make a unicode string that we can use to enumerate 02495 // the subkeys of the MFA key 02496 // 02497 unicodeString.Buffer = wbuffer; 02498 unicodeString.MaximumLength = sizeof(wbuffer); 02499 RtlInitUnicodeString( &biosId, rgzBIOSIdentifier ); 02500 02501 // 02502 // Loop over all subkeys 02503 // 02504 for (i = 0; TRUE; i++) { 02505 02506 // 02507 // Turn the number into a key name 02508 // 02509 RtlIntegerToUnicodeString( i, 10, &unicodeString); 02510 InitializeObjectAttributes( 02511 &objectAttributes, 02512 &unicodeString, 02513 OBJ_CASE_INSENSITIVE, 02514 hMFunc, 02515 NULL 02516 ); 02517 02518 // 02519 // Open the named subkey 02520 // 02521 status = ZwOpenKey( &hBus, KEY_READ, &objectAttributes ); 02522 if (!NT_SUCCESS(status)) { 02523 02524 // 02525 // Out of Multifunction adapter entries... 02526 // 02527 DbgPrint("CmpFindRSDTTable: ACPI BIOS MultifunctionAdapter registry key not found.\n"); 02528 ZwClose (hMFunc); 02529 return STATUS_UNSUCCESSFUL; 02530 02531 } 02532 02533 // 02534 // Check the Indentifier to see if this is an ACPI BIOS entry 02535 // 02536 status = CmpGetRegistryValue( hBus, rgzAcpiIdentifier, &valueInfo ); 02537 if (!NT_SUCCESS (status)) { 02538 02539 ZwClose( hBus ); 02540 continue; 02541 02542 } 02543 02544 p = (PWSTR) ((PUCHAR) valueInfo->Data); 02545 unicodeValueName.Buffer = p; 02546 unicodeValueName.MaximumLength = (USHORT)valueInfo->DataLength; 02547 length = valueInfo->DataLength; 02548 02549 // 02550 // Determine the real length of the ID string 02551 // 02552 while (length) { 02553 02554 if (p[length / sizeof(WCHAR) - 1] == UNICODE_NULL) { 02555 02556 length -= 2; 02557 02558 } else { 02559 02560 break; 02561 } 02562 02563 } 02564 02565 // 02566 // Do we have a match the "ACPI BIOS" identifier? 02567 // 02568 unicodeValueName.Length = (USHORT)length; 02569 same = RtlEqualUnicodeString( &biosId, &unicodeValueName, TRUE ); 02570 ExFreePool( valueInfo ); 02571 if (!same) { 02572 02573 ZwClose( hBus ); 02574 continue; 02575 02576 } 02577 02578 // 02579 // We do, so get the configuration data 02580 // 02581 status = CmpGetRegistryValue( 02582 hBus, 02583 rgzAcpiConfigurationData, 02584 &valueInfo 02585 ); 02586 ZwClose( hBus ); 02587 if (!NT_SUCCESS(status)) { 02588 02589 continue ; 02590 02591 } 02592 02593 // 02594 // The data that we want is at the end of the PARTIAL_RESOURCE_LIST 02595 // descriptor 02596 // 02597 prl = (PCM_PARTIAL_RESOURCE_LIST)(valueInfo->Data); 02598 prd = &prl->PartialDescriptors[0]; 02599 multiNode = (PACPI_BIOS_MULTI_NODE) 02600 ( (PCHAR) prd + sizeof(CM_PARTIAL_RESOURCE_LIST) ); 02601 break; 02602 02603 } 02604 02605 // 02606 // Calculate the size of the data so that we can make a copy 02607 // 02608 multiNodeSize = sizeof(ACPI_BIOS_MULTI_NODE) + 02609 ( (ULONG)(multiNode->Count - 1) * sizeof(ACPI_E820_ENTRY) ); 02610 *Rsdt = (PACPI_BIOS_MULTI_NODE) ExAllocatePoolWithTag( 02611 NonPagedPool, 02612 multiNodeSize, 02613 'IPCA' 02614 ); 02615 if (*Rsdt == NULL) { 02616 02617 ExFreePool( valueInfo ); 02618 return STATUS_INSUFFICIENT_RESOURCES; 02619 02620 } 02621 RtlCopyMemory(*Rsdt, multiNode, multiNodeSize); 02622 02623 // 02624 // Done with the key memory 02625 // 02626 ExFreePool(valueInfo); 02627 02628 // 02629 // Done 02630 // 02631 return STATUS_SUCCESS; 02632 } 02633 02634 NTSTATUS 02635 CmpGetRegistryValue( 02636 IN HANDLE KeyHandle, 02637 IN PWSTR ValueName, 02638 OUT PKEY_VALUE_PARTIAL_INFORMATION *Information 02639 ) 02640 /*++ 02641 02642 Routine Description: 02643 02644 This routine is invoked to retrieve the data for a registry key's value. 02645 This is done by querying the value of the key with a zero-length buffer 02646 to determine the size of the value, and then allocating a buffer and 02647 actually querying the value into the buffer. 02648 02649 It is the responsibility of the caller to free the buffer. 02650 02651 Arguments: 02652 02653 KeyHandle - Supplies the key handle whose value is to be queried 02654 02655 ValueName - Supplies the null-terminated Unicode name of the value. 02656 02657 Information - Returns a pointer to the allocated data buffer. 02658 02659 Return Value: 02660 02661 The function value is the final status of the query operation. 02662 02663 --*/ 02664 02665 { 02666 NTSTATUS status; 02667 PKEY_VALUE_PARTIAL_INFORMATION infoBuffer; 02668 ULONG keyValueLength; 02669 UNICODE_STRING unicodeString; 02670 02671 PAGED_CODE(); 02672 02673 RtlInitUnicodeString( &unicodeString, ValueName ); 02674 02675 // 02676 // Figure out how big the data value is so that a buffer of the 02677 // appropriate size can be allocated. 02678 // 02679 status = ZwQueryValueKey( 02680 KeyHandle, 02681 &unicodeString, 02682 KeyValuePartialInformation, 02683 (PVOID) NULL, 02684 0, 02685 &keyValueLength 02686 ); 02687 if (status != STATUS_BUFFER_OVERFLOW && 02688 status != STATUS_BUFFER_TOO_SMALL) { 02689 02690 return status; 02691 02692 } 02693 02694 // 02695 // Allocate a buffer large enough to contain the entire key data value. 02696 // 02697 infoBuffer = ExAllocatePoolWithTag( 02698 NonPagedPool, 02699 keyValueLength, 02700 'IPCA' 02701 ); 02702 if (!infoBuffer) { 02703 02704 return STATUS_INSUFFICIENT_RESOURCES; 02705 02706 } 02707 02708 // 02709 // Query the data for the key value. 02710 // 02711 status = ZwQueryValueKey( 02712 KeyHandle, 02713 &unicodeString, 02714 KeyValuePartialInformation, 02715 infoBuffer, 02716 keyValueLength, 02717 &keyValueLength 02718 ); 02719 if (!NT_SUCCESS( status )) { 02720 02721 ExFreePool( infoBuffer ); 02722 02723 return status; 02724 02725 } 02726 02727 // 02728 // Everything worked, so simply return the address of the allocated 02729 // buffer to the caller, who is now responsible for freeing it. 02730 // 02731 *Information = infoBuffer; 02732 return STATUS_SUCCESS; 02733 02734 } 02735 02736

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