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

init386.c

Go to the documentation of this file.
00001 /*++ 00002 00003 Copyright (c) 1990, 1991 Microsoft Corporation 00004 00005 00006 Module Name: 00007 00008 init386.c 00009 00010 Abstract: 00011 00012 This module is responsible to build any x86 specific entries in 00013 the hardware tree of registry. 00014 00015 Author: 00016 00017 Ken Reneris (kenr) 04-Aug-1992 00018 00019 00020 Environment: 00021 00022 Kernel mode. 00023 00024 Revision History: 00025 00026 shielint - add BIOS date and version detection. 00027 00028 --*/ 00029 00030 #include "cmp.h" 00031 #include "stdio.h" 00032 00033 #ifdef _WANT_MACHINE_IDENTIFICATION 00034 #include "string.h" 00035 #include "stdlib.h" 00036 #include "ntverp.h" 00037 #include "rules.h" 00038 #endif 00039 00040 // 00041 // Title Index is set to 0. 00042 // (from ..\cmconfig.c) 00043 // 00044 00045 #define TITLE_INDEX_VALUE 0 00046 00047 extern PCHAR SearchStrings[]; 00048 extern PCHAR BiosBegin; 00049 extern PCHAR Start; 00050 extern PCHAR End; 00051 extern UCHAR CmpID1[]; 00052 extern UCHAR CmpID2[]; 00053 extern WCHAR CmpVendorID[]; 00054 extern WCHAR CmpProcessorNameString[]; 00055 extern WCHAR CmpFeatureBits[]; 00056 extern WCHAR CmpMHz[]; 00057 extern WCHAR CmpUpdateSignature[]; 00058 extern WCHAR CmPhysicalAddressExtension[]; 00059 extern UCHAR CmpCyrixID[]; 00060 extern UCHAR CmpIntelID[]; 00061 extern UCHAR CmpAmdID[]; 00062 00063 // 00064 // Bios date and version definitions 00065 // 00066 00067 #define BIOS_DATE_LENGTH 11 00068 #define MAXIMUM_BIOS_VERSION_LENGTH 128 00069 #define SYSTEM_BIOS_START 0xF0000 00070 #define SYSTEM_BIOS_LENGTH 0x10000 00071 #define INT10_VECTOR 0x10 00072 #define VIDEO_BIOS_START 0xC0000 00073 #define VIDEO_BIOS_LENGTH 0x8000 00074 #define VERSION_DATA_LENGTH PAGE_SIZE 00075 00076 // 00077 // Extended CPUID function definitions 00078 // 00079 00080 #define CPUID_PROCESSOR_NAME_STRING_SZ 49 00081 #define CPUID_EXTFN_BASE 0x80000000 00082 #define CPUID_EXTFN_PROCESSOR_NAME 0x80000002 00083 00084 // 00085 // CPU Stepping mismatch. 00086 // 00087 00088 UCHAR CmProcessorMismatch; 00089 00090 #define CM_PROCESSOR_MISMATCH_VENDOR 0x01 00091 #define CM_PROCESSOR_MISMATCH_STEPPING 0x02 00092 #define CM_PROCESSOR_MISMATCH_L2 0x04 00093 00094 00095 extern ULONG CmpConfigurationAreaSize; 00096 extern PCM_FULL_RESOURCE_DESCRIPTOR CmpConfigurationData; 00097 00098 00099 BOOLEAN 00100 CmpGetBiosVersion ( 00101 PCHAR SearchArea, 00102 ULONG SearchLength, 00103 PCHAR VersionString 00104 ); 00105 00106 BOOLEAN 00107 CmpGetBiosDate ( 00108 PCHAR SearchArea, 00109 ULONG SearchLength, 00110 PCHAR DateString, 00111 BOOLEAN SystemBiosDate 00112 ); 00113 00114 ULONG 00115 Ke386CyrixId ( 00116 VOID 00117 ); 00118 00119 #ifdef _WANT_MACHINE_IDENTIFICATION 00120 00121 VOID 00122 CmpPerformMachineIdentification( 00123 IN PLOADER_PARAMETER_BLOCK LoaderBlock 00124 ); 00125 00126 #endif 00127 00128 #ifdef ALLOC_PRAGMA 00129 #pragma alloc_text(INIT,CmpGetBiosDate) 00130 #pragma alloc_text(INIT,CmpGetBiosVersion) 00131 #pragma alloc_text(INIT,CmpInitializeMachineDependentConfiguration) 00132 00133 #ifdef _WANT_MACHINE_IDENTIFICATION 00134 #pragma alloc_text(INIT,CmpPerformMachineIdentification) 00135 #endif 00136 00137 #endif 00138 00139 00140 BOOLEAN 00141 CmpGetBiosDate ( 00142 PCHAR SearchArea, 00143 ULONG SearchLength, 00144 PCHAR DateString, 00145 BOOLEAN SystemBiosDate 00146 ) 00147 00148 /*++ 00149 00150 Routine Description: 00151 00152 This routine finds the most recent date in the computer/video 00153 card's ROM. When GetRomDate encounters a datae, it checks the 00154 previously found date to see if the new date is more recent. 00155 00156 Arguments: 00157 00158 SearchArea - the area to search for a date. 00159 00160 SearchLength - Length of search. 00161 00162 DateString - Supplies a pointer to a fixed length memory to receive 00163 the date string. 00164 00165 Return Value: 00166 00167 NT_SUCCESS if a date is found. 00168 00169 --*/ 00170 00171 { 00172 CHAR prevDate[BIOS_DATE_LENGTH]; // Newest date found so far (CCYY/MM/DD) 00173 CHAR currDate[BIOS_DATE_LENGTH]; // Date currently being examined (CCYY/MM/DD) 00174 PCHAR start; // Start of the current search area. 00175 PCHAR end; // End of the search area. 00176 ULONG year; // YY 00177 ULONG month; // MM 00178 ULONG day; // DD 00179 ULONG count; 00180 00181 #define IS_DIGIT(c) ((c) >= '0' && (c) <= '9') 00182 00183 // 00184 // Initialize previous date 00185 // 00186 00187 RtlZeroMemory(prevDate, BIOS_DATE_LENGTH); 00188 00189 // 00190 // We need to look ahead 5 characters to determine the 00191 // validity of the date pattern. 00192 // 00193 00194 start = SearchArea + 2; 00195 end = SearchArea + SearchLength - 5; 00196 00197 // 00198 // Process the entire search area. 00199 // 00200 00201 while (start < end) { 00202 00203 // 00204 // We consider the following byte pattern as a potential date. 00205 // We are assuming the following date pattern Month/Day/Year. 00206 // "n/nn/nn" where n is any digit. We allow month to be single 00207 // digit only. 00208 // 00209 00210 if ( start[0] == '/' && start[3] == '/' && 00211 IS_DIGIT(*(start - 1)) && 00212 IS_DIGIT(start[1]) && IS_DIGIT(start[2]) && 00213 IS_DIGIT(start[4]) && IS_DIGIT(start[5])) { 00214 00215 // 00216 // Copy MM/DD part into the currDate. 00217 // 00218 00219 RtlMoveMemory(&currDate[5], start - 2, 5); 00220 00221 // 00222 // Handle single digit month correctly. 00223 // 00224 00225 if (!IS_DIGIT(currDate[5])) { 00226 currDate[5] = '0'; 00227 } 00228 00229 // 00230 // Copy the year YY into currDate 00231 // 00232 00233 currDate[2] = start[4]; 00234 currDate[3] = start[5]; 00235 currDate[4] = currDate[7] = currDate[10] = '\0'; 00236 00237 // 00238 // Do basic validation for the date. 00239 // Only one field (YY) can be 0. 00240 // Only one field (YY) can be greater than 31. 00241 // We assume the ROM date to be in the format MM/DD/YY. 00242 // 00243 00244 year = strtoul(&currDate[2], NULL, 16); 00245 month = strtoul(&currDate[5], NULL, 16); 00246 day = strtoul(&currDate[8], NULL, 16); 00247 00248 // 00249 // Count the number of fields that are 0. 00250 // 00251 00252 count = ((day == 0)? 1 : 0) + ((month == 0)? 1 : 0) + ((year == 0)? 1 : 0); 00253 if (count <= 1) { 00254 00255 // 00256 // Count number of field that are greater than 31. 00257 // 00258 00259 count = ((day > 0x31)? 1 : 0) + ((month > 0x31)? 1 : 0) + ((year > 0x31)? 1 : 0); 00260 if (count <= 1) { 00261 00262 // 00263 // See if the ROM already has a 4 digit date. We do this only for System ROM 00264 // since they have a consistent date format. 00265 // 00266 00267 if (SystemBiosDate && IS_DIGIT(start[6]) && IS_DIGIT(start[7]) && 00268 (memcmp(&start[4], "19", 2) == 0 || memcmp(&start[4], "20", 2) == 0)) { 00269 00270 currDate[0] = start[4]; 00271 currDate[1] = start[5]; 00272 currDate[2] = start[6]; 00273 currDate[3] = start[7]; 00274 00275 } else { 00276 00277 // 00278 // Internally, we treat year as a 4 digit quantity 00279 // for comparison to determine the newest date. 00280 // We treat year YY < 80 as 20YY, otherwise 19YY. 00281 // 00282 00283 if (year < 0x80) { 00284 currDate[0] = '2'; 00285 currDate[1] = '0'; 00286 } else { 00287 currDate[0] = '1'; 00288 currDate[1] = '9'; 00289 } 00290 } 00291 00292 // 00293 // Add the '/' delimiters into the date. 00294 // 00295 00296 currDate[4] = currDate[7] = '/'; 00297 00298 // 00299 // Compare the dates, and save the newer one. 00300 // 00301 00302 if (memcmp (prevDate, currDate, BIOS_DATE_LENGTH - 1) < 0) { 00303 RtlMoveMemory(prevDate, currDate, BIOS_DATE_LENGTH - 1); 00304 } 00305 00306 // 00307 // Next search should start at the second '/'. 00308 // 00309 00310 start += 2; 00311 } 00312 } 00313 } 00314 start++; 00315 } 00316 00317 if (prevDate[0] != '\0') { 00318 00319 // 00320 // Convert from the internal CCYY/MM/DD format to 00321 // return MM/DD//YY format. 00322 // 00323 00324 RtlMoveMemory(DateString, &prevDate[5], 5); 00325 DateString[5] = '/'; 00326 DateString[6] = prevDate[2]; 00327 DateString[7] = prevDate[3]; 00328 DateString[8] = '\0'; 00329 00330 return (TRUE); 00331 } 00332 00333 // 00334 // If we did not find a date, return an empty string. 00335 // 00336 00337 DateString[0] = '\0'; 00338 return (FALSE); 00339 } 00340 00341 BOOLEAN 00342 CmpGetBiosVersion ( 00343 PCHAR SearchArea, 00344 ULONG SearchLength, 00345 PCHAR VersionString 00346 ) 00347 00348 /*++ 00349 00350 Routine Description: 00351 00352 This routine finds the version number stored in ROM, if any. 00353 00354 Arguments: 00355 00356 SearchArea - the area to search for the version. 00357 00358 SearchLength - Length of search 00359 00360 VersionString - Supplies a pointer to a fixed length memory to receive 00361 the version string. 00362 00363 Return Value: 00364 00365 TRUE if a version number is found. Else a value of FALSE is returned. 00366 00367 --*/ 00368 { 00369 PCHAR String; 00370 USHORT Length; 00371 USHORT i; 00372 CHAR Buffer[MAXIMUM_BIOS_VERSION_LENGTH]; 00373 PCHAR BufferPointer; 00374 00375 if (SearchArea != NULL) { 00376 00377 // 00378 // If caller does not specify the search area, we will search 00379 // the area left from previous search. 00380 // 00381 00382 BiosBegin = SearchArea; 00383 Start = SearchArea + 1; 00384 End = SearchArea + SearchLength - 2; 00385 } 00386 00387 while (1) { 00388 00389 // 00390 // Search for a period with a digit on either side 00391 // 00392 00393 String = NULL; 00394 while (Start <= End) { 00395 if (*Start == '.' && *(Start+1) >= '0' && *(Start+1) <= '9' && 00396 *(Start-1) >= '0' && *(Start-1) <= '9') { 00397 String = Start; 00398 break; 00399 } else { 00400 Start++; 00401 } 00402 } 00403 00404 if (Start > End) { 00405 return(FALSE); 00406 } else { 00407 Start += 2; 00408 } 00409 00410 Length = 0; 00411 Buffer[MAXIMUM_BIOS_VERSION_LENGTH - 1] = '\0'; 00412 BufferPointer = &Buffer[MAXIMUM_BIOS_VERSION_LENGTH - 1]; 00413 00414 // 00415 // Search for the beginning of the string 00416 // 00417 00418 String--; 00419 while (Length < MAXIMUM_BIOS_VERSION_LENGTH - 8 && 00420 String >= BiosBegin && 00421 *String >= ' ' && *String <= 127 && 00422 *String != '$') { 00423 --BufferPointer; 00424 *BufferPointer = *String; 00425 --String, ++Length; 00426 } 00427 ++String; 00428 00429 // 00430 // Can one of the search strings be found 00431 // 00432 00433 for (i = 0; SearchStrings[i]; i++) { 00434 if (strstr(BufferPointer, SearchStrings[i])) { 00435 goto Found; 00436 } 00437 } 00438 } 00439 00440 Found: 00441 00442 // 00443 // Skip leading white space 00444 // 00445 00446 for (; *String == ' '; ++String) 00447 ; 00448 00449 // 00450 // Copy the string to user supplied buffer 00451 // 00452 00453 for (i = 0; i < MAXIMUM_BIOS_VERSION_LENGTH - 1 && 00454 String <= (End + 1) && 00455 *String >= ' ' && *String <= 127 && *String != '$'; 00456 ++i, ++String) { 00457 VersionString[i] = *String; 00458 } 00459 VersionString[i] = '\0'; 00460 return (TRUE); 00461 } 00462 00463 00464 NTSTATUS 00465 CmpInitializeMachineDependentConfiguration( 00466 IN PLOADER_PARAMETER_BLOCK LoaderBlock 00467 ) 00468 /*++ 00469 00470 Routine Description: 00471 00472 This routine creates x86 specific entries in the registry. 00473 00474 Arguments: 00475 00476 LoaderBlock - supplies a pointer to the LoaderBlock passed in from the 00477 OS Loader. 00478 00479 Returns: 00480 00481 NTSTATUS code for sucess or reason of failure. 00482 00483 --*/ 00484 { 00485 NTSTATUS Status; 00486 ULONG VideoBiosStart; 00487 UNICODE_STRING KeyName; 00488 UNICODE_STRING ValueName; 00489 UNICODE_STRING ValueData; 00490 ANSI_STRING AnsiString; 00491 OBJECT_ATTRIBUTES ObjectAttributes; 00492 ULONG Disposition; 00493 HANDLE ParentHandle; 00494 HANDLE BaseHandle, NpxHandle; 00495 HANDLE CurrentControlSet; 00496 CONFIGURATION_COMPONENT_DATA CurrentEntry; 00497 PUCHAR VendorID; 00498 UCHAR Buffer[MAXIMUM_BIOS_VERSION_LENGTH]; 00499 PKPRCB Prcb; 00500 ULONG i, Junk; 00501 ULONG VersionsLength = 0, Length; 00502 PCHAR VersionStrings, VersionPointer; 00503 UNICODE_STRING SectionName; 00504 ULONG ViewSize; 00505 LARGE_INTEGER ViewBase; 00506 PVOID BaseAddress; 00507 HANDLE SectionHandle; 00508 USHORT DeviceIndexTable[NUMBER_TYPES]; 00509 ULONG CpuIdFunction; 00510 ULONG MaxExtFn; 00511 PULONG NameString = NULL; 00512 ULONG P0L2Size = 0; 00513 ULONG ThisProcessorL2Size; 00514 struct { 00515 union { 00516 UCHAR Bytes[CPUID_PROCESSOR_NAME_STRING_SZ]; 00517 ULONG DWords[1]; 00518 } u; 00519 } ProcessorNameString; 00520 00521 #ifdef _WANT_MACHINE_IDENTIFICATION 00522 HANDLE BiosInfo; 00523 #endif 00524 00525 for (i = 0; i < NUMBER_TYPES; i++) { 00526 DeviceIndexTable[i] = 0; 00527 } 00528 00529 InitializeObjectAttributes( &ObjectAttributes, 00530 &CmRegistryMachineSystemCurrentControlSetControlSessionManagerMemoryManagement, 00531 OBJ_CASE_INSENSITIVE, 00532 NULL, 00533 NULL 00534 ); 00535 00536 Status = NtOpenKey( &BaseHandle, 00537 KEY_READ | KEY_WRITE, 00538 &ObjectAttributes 00539 ); 00540 00541 if (NT_SUCCESS(Status)) { 00542 00543 ULONG paeEnabled; 00544 00545 if (SharedUserData->ProcessorFeatures[PF_PAE_ENABLED] == FALSE) { 00546 paeEnabled = 0; 00547 } else { 00548 paeEnabled = 1; 00549 } 00550 00551 RtlInitUnicodeString( &ValueName, 00552 CmPhysicalAddressExtension ); 00553 00554 00555 NtSetValueKey( BaseHandle, 00556 &ValueName, 00557 TITLE_INDEX_VALUE, 00558 REG_DWORD, 00559 &paeEnabled, 00560 sizeof(paeEnabled) ); 00561 00562 NtClose( BaseHandle ); 00563 } 00564 00565 00566 00567 00568 00569 InitializeObjectAttributes( &ObjectAttributes, 00570 &CmRegistryMachineHardwareDescriptionSystemName, 00571 OBJ_CASE_INSENSITIVE, 00572 NULL, 00573 NULL 00574 ); 00575 00576 Status = NtOpenKey( &ParentHandle, 00577 KEY_READ, 00578 &ObjectAttributes 00579 ); 00580 00581 if (!NT_SUCCESS(Status)) { 00582 // Something is really wrong... 00583 return Status; 00584 } 00585 00586 #ifdef _WANT_MACHINE_IDENTIFICATION 00587 00588 InitializeObjectAttributes( &ObjectAttributes, 00589 &CmRegistryMachineSystemCurrentControlSetControlBiosInfo, 00590 OBJ_CASE_INSENSITIVE, 00591 NULL, 00592 NULL 00593 ); 00594 00595 Status = NtCreateKey( &BiosInfo, 00596 KEY_ALL_ACCESS, 00597 &ObjectAttributes, 00598 0, 00599 NULL, 00600 REG_OPTION_NON_VOLATILE, 00601 &Disposition 00602 ); 00603 00604 if (!NT_SUCCESS(Status)) { 00605 // Something is really wrong... 00606 return Status; 00607 } 00608 00609 #endif 00610 00611 // 00612 // On an ARC machine the processor(s) are included in the hardware 00613 // configuration passed in from bootup. Since there's no standard 00614 // way to get all the ARC information for each processor in an MP 00615 // machine via pc-ROMs the information will be added here (if it's 00616 // not already present). 00617 // 00618 00619 RtlInitUnicodeString( &KeyName, 00620 L"CentralProcessor" 00621 ); 00622 00623 InitializeObjectAttributes( 00624 &ObjectAttributes, 00625 &KeyName, 00626 0, 00627 ParentHandle, 00628 NULL 00629 ); 00630 00631 ObjectAttributes.Attributes |= OBJ_CASE_INSENSITIVE; 00632 00633 Status = NtCreateKey( 00634 &BaseHandle, 00635 KEY_READ | KEY_WRITE, 00636 &ObjectAttributes, 00637 TITLE_INDEX_VALUE, 00638 &CmClassName[ProcessorClass], 00639 0, 00640 &Disposition 00641 ); 00642 00643 NtClose (BaseHandle); 00644 00645 if (Disposition == REG_CREATED_NEW_KEY) { 00646 00647 // 00648 // The ARC rom didn't add the processor(s) into the registry. 00649 // Do it now. 00650 // 00651 00652 CmpConfigurationData = (PCM_FULL_RESOURCE_DESCRIPTOR)ExAllocatePool( 00653 PagedPool, 00654 CmpConfigurationAreaSize 00655 ); 00656 00657 // 00658 // if (CmpConfigurationData == 0) { 00659 // <do something useful> 00660 // Note: we don't actually use it so it doesn't matter for now 00661 // since it isn't used until the free. go figure. 00662 // } 00663 // 00664 00665 for (i=0; i < (ULONG)KeNumberProcessors; i++) { 00666 Prcb = KiProcessorBlock[i]; 00667 00668 RtlZeroMemory (&CurrentEntry, sizeof CurrentEntry); 00669 CurrentEntry.ComponentEntry.Class = ProcessorClass; 00670 CurrentEntry.ComponentEntry.Type = CentralProcessor; 00671 CurrentEntry.ComponentEntry.Key = i; 00672 CurrentEntry.ComponentEntry.AffinityMask = 1 << i; 00673 00674 CurrentEntry.ComponentEntry.Identifier = Buffer; 00675 if (Prcb->CpuID == 0) { 00676 00677 // 00678 // Old style stepping format 00679 // 00680 00681 sprintf (Buffer, CmpID1, 00682 Prcb->CpuType, 00683 (Prcb->CpuStep >> 8) + 'A', 00684 Prcb->CpuStep & 0xff 00685 ); 00686 00687 } else { 00688 00689 // 00690 // New style stepping format 00691 // 00692 00693 sprintf (Buffer, CmpID2, 00694 Prcb->CpuType, 00695 (Prcb->CpuStep >> 8), 00696 Prcb->CpuStep & 0xff 00697 ); 00698 } 00699 00700 CurrentEntry.ComponentEntry.IdentifierLength = 00701 strlen (Buffer) + 1; 00702 00703 Status = CmpInitializeRegistryNode( 00704 &CurrentEntry, 00705 ParentHandle, 00706 &BaseHandle, 00707 -1, 00708 (ULONG)-1, 00709 DeviceIndexTable 00710 ); 00711 00712 if (!NT_SUCCESS(Status)) { 00713 return(Status); 00714 } 00715 00716 00717 if (KeI386NpxPresent) { 00718 RtlZeroMemory (&CurrentEntry, sizeof CurrentEntry); 00719 CurrentEntry.ComponentEntry.Class = ProcessorClass; 00720 CurrentEntry.ComponentEntry.Type = FloatingPointProcessor; 00721 CurrentEntry.ComponentEntry.Key = i; 00722 CurrentEntry.ComponentEntry.AffinityMask = 1 << i; 00723 00724 CurrentEntry.ComponentEntry.Identifier = Buffer; 00725 00726 if (Prcb->CpuType == 3) { 00727 00728 // 00729 // 386 processors have 387's installed, else 00730 // use processor identifier as the NPX identifier 00731 // 00732 00733 strcpy (Buffer, "80387"); 00734 } 00735 00736 CurrentEntry.ComponentEntry.IdentifierLength = 00737 strlen (Buffer) + 1; 00738 00739 Status = CmpInitializeRegistryNode( 00740 &CurrentEntry, 00741 ParentHandle, 00742 &NpxHandle, 00743 -1, 00744 (ULONG)-1, 00745 DeviceIndexTable 00746 ); 00747 00748 if (!NT_SUCCESS(Status)) { 00749 NtClose(BaseHandle); 00750 return(Status); 00751 } 00752 00753 NtClose(NpxHandle); 00754 } 00755 00756 // 00757 // If processor supports Cpu Indentification then 00758 // go obtain that information for the registry 00759 // 00760 00761 VendorID = Prcb->CpuID ? Prcb->VendorString : NULL; 00762 00763 // 00764 // Move to target processor and get other related 00765 // processor information for the registery 00766 // 00767 00768 KeSetSystemAffinityThread(Prcb->SetMember); 00769 00770 if (!Prcb->CpuID) { 00771 00772 // 00773 // Test for Cyrix processor 00774 // 00775 00776 if (Ke386CyrixId ()) { 00777 VendorID = CmpCyrixID; 00778 } 00779 } else { 00780 00781 // 00782 // If this processor has extended CPUID functions, get 00783 // the ProcessorNameString. Although the Intel books 00784 // say that for CpuID functions > than the valued 00785 // returned for function 0 will return undefined results, 00786 // we have a guarantee from Intel that that result will 00787 // never have the highest order bit set. This enables 00788 // us to determine if the extended functions are supported 00789 // by issuing CpuID function 0x80000000. 00790 // 00791 // Note: It is not known that this is true for all x86 00792 // clones. If/when we find exceptions we will support 00793 // them. In the mean time we are asking the clone makers 00794 // to guarantee this behavior. 00795 // 00796 00797 CPUID(CPUID_EXTFN_BASE, &MaxExtFn, &Junk, &Junk, &Junk); 00798 00799 if (MaxExtFn >= (CPUID_EXTFN_PROCESSOR_NAME + 2)) { 00800 00801 // 00802 // This processor supports extended CPUID functions 00803 // up to and (at least) including processor name string. 00804 // 00805 // Each CPUID call for the processor name string will 00806 // return 16 bytes, 48 bytes in all, zero terminated. 00807 // 00808 00809 NameString = &ProcessorNameString.u.DWords[0]; 00810 00811 for (CpuIdFunction = CPUID_EXTFN_PROCESSOR_NAME; 00812 CpuIdFunction <= (CPUID_EXTFN_PROCESSOR_NAME+2); 00813 CpuIdFunction++) { 00814 00815 CPUID(CpuIdFunction, 00816 NameString, 00817 NameString + 1, 00818 NameString + 2, 00819 NameString + 3); 00820 NameString += 4; 00821 } 00822 00823 // 00824 // Enforce 0 byte terminator. 00825 // 00826 00827 ProcessorNameString.u.Bytes[CPUID_PROCESSOR_NAME_STRING_SZ-1] = 0; 00828 } 00829 } 00830 00831 ThisProcessorL2Size = KeGetPcr()->SecondLevelCacheSize; 00832 00833 // 00834 // Restore thread's affinity to all processors 00835 // 00836 00837 KeRevertToUserAffinityThread(); 00838 00839 if (NameString) { 00840 00841 // 00842 // Add Processor Name String to the registery 00843 // 00844 00845 RtlInitUnicodeString( 00846 &ValueName, 00847 CmpProcessorNameString 00848 ); 00849 00850 RtlInitAnsiString( 00851 &AnsiString, 00852 ProcessorNameString.u.Bytes 00853 ); 00854 00855 RtlAnsiStringToUnicodeString( 00856 &ValueData, 00857 &AnsiString, 00858 TRUE 00859 ); 00860 00861 Status = NtSetValueKey( 00862 BaseHandle, 00863 &ValueName, 00864 TITLE_INDEX_VALUE, 00865 REG_SZ, 00866 ValueData.Buffer, 00867 ValueData.Length + sizeof( UNICODE_NULL ) 00868 ); 00869 00870 RtlFreeUnicodeString(&ValueData); 00871 } 00872 00873 if (VendorID) { 00874 00875 // 00876 // Add Vendor Indentifier to the registery 00877 // 00878 00879 RtlInitUnicodeString( 00880 &ValueName, 00881 CmpVendorID 00882 ); 00883 00884 RtlInitAnsiString( 00885 &AnsiString, 00886 VendorID 00887 ); 00888 00889 RtlAnsiStringToUnicodeString( 00890 &ValueData, 00891 &AnsiString, 00892 TRUE 00893 ); 00894 00895 Status = NtSetValueKey( 00896 BaseHandle, 00897 &ValueName, 00898 TITLE_INDEX_VALUE, 00899 REG_SZ, 00900 ValueData.Buffer, 00901 ValueData.Length + sizeof( UNICODE_NULL ) 00902 ); 00903 00904 RtlFreeUnicodeString(&ValueData); 00905 } 00906 00907 if (Prcb->FeatureBits) { 00908 // 00909 // Add processor feature bits to the registery 00910 // 00911 00912 RtlInitUnicodeString( 00913 &ValueName, 00914 CmpFeatureBits 00915 ); 00916 00917 Status = NtSetValueKey( 00918 BaseHandle, 00919 &ValueName, 00920 TITLE_INDEX_VALUE, 00921 REG_DWORD, 00922 &Prcb->FeatureBits, 00923 sizeof (Prcb->FeatureBits) 00924 ); 00925 } 00926 00927 if (Prcb->MHz) { 00928 // 00929 // Add processor MHz to the registery 00930 // 00931 00932 RtlInitUnicodeString( 00933 &ValueName, 00934 CmpMHz 00935 ); 00936 00937 Status = NtSetValueKey( 00938 BaseHandle, 00939 &ValueName, 00940 TITLE_INDEX_VALUE, 00941 REG_DWORD, 00942 &Prcb->MHz, 00943 sizeof (Prcb->MHz) 00944 ); 00945 } 00946 00947 if (Prcb->UpdateSignature.QuadPart) { 00948 // 00949 // Add processor MHz to the registery 00950 // 00951 00952 RtlInitUnicodeString( 00953 &ValueName, 00954 CmpUpdateSignature 00955 ); 00956 00957 Status = NtSetValueKey( 00958 BaseHandle, 00959 &ValueName, 00960 TITLE_INDEX_VALUE, 00961 REG_BINARY, 00962 &Prcb->UpdateSignature, 00963 sizeof (Prcb->UpdateSignature) 00964 ); 00965 } 00966 00967 NtClose(BaseHandle); 00968 00969 // 00970 // Check processor steppings. 00971 // 00972 00973 if (i == 0) { 00974 00975 P0L2Size = ThisProcessorL2Size; 00976 00977 } else { 00978 00979 // 00980 // Check all processors against processor 0. Compare 00981 // CPUID supported, 00982 // Vendor ID String 00983 // Family and Stepping 00984 // L2 cache size. 00985 // 00986 00987 if (Prcb->CpuID) { 00988 if (strcmp(Prcb->VendorString, 00989 KiProcessorBlock[0]->VendorString)) { 00990 CmProcessorMismatch |= CM_PROCESSOR_MISMATCH_VENDOR; 00991 } 00992 if (ThisProcessorL2Size != P0L2Size) { 00993 CmProcessorMismatch |= CM_PROCESSOR_MISMATCH_L2; 00994 } 00995 if ((Prcb->CpuType != KiProcessorBlock[0]->CpuType) || 00996 (Prcb->CpuStep != KiProcessorBlock[0]->CpuStep)) { 00997 CmProcessorMismatch |= CM_PROCESSOR_MISMATCH_STEPPING; 00998 } 00999 } else { 01000 01001 // 01002 // If this processor doesn't support CPUID, P0 01003 // shouldn't support it either. 01004 // 01005 01006 if (KiProcessorBlock[0]->CpuID) { 01007 CmProcessorMismatch |= CM_PROCESSOR_MISMATCH_STEPPING; 01008 } 01009 } 01010 } 01011 } 01012 01013 if (0 != CmpConfigurationData) { 01014 ExFreePool((PVOID)CmpConfigurationData); 01015 } 01016 } 01017 01018 // 01019 // Next we try to collect System BIOS date and version strings. 01020 // BUGBUG This code should be moved to ntdetect.com after product 1. 01021 // 01022 01023 // 01024 // Open a physical memory section to map in physical memory. 01025 // 01026 01027 RtlInitUnicodeString( 01028 &SectionName, 01029 L"\\Device\\PhysicalMemory" 01030 ); 01031 01032 InitializeObjectAttributes( 01033 &ObjectAttributes, 01034 &SectionName, 01035 OBJ_CASE_INSENSITIVE, 01036 (HANDLE) NULL, 01037 (PSECURITY_DESCRIPTOR) NULL 01038 ); 01039 01040 Status = ZwOpenSection( 01041 &SectionHandle, 01042 SECTION_ALL_ACCESS, 01043 &ObjectAttributes 01044 ); 01045 01046 if (!NT_SUCCESS(Status)) { 01047 01048 // 01049 // If fail, forget the bios data and version 01050 // 01051 01052 goto AllDone; 01053 } 01054 01055 // 01056 // Examine the first page of physical memory for int 10 segment 01057 // address. 01058 // 01059 01060 BaseAddress = 0; 01061 ViewSize = 0x1000; 01062 ViewBase.LowPart = 0; 01063 ViewBase.HighPart = 0; 01064 01065 Status =ZwMapViewOfSection( 01066 SectionHandle, 01067 NtCurrentProcess(), 01068 &BaseAddress, 01069 0, 01070 ViewSize, 01071 &ViewBase, 01072 &ViewSize, 01073 ViewUnmap, 01074 MEM_DOS_LIM, 01075 PAGE_READWRITE 01076 ); 01077 01078 if (!NT_SUCCESS(Status)) { 01079 VideoBiosStart = VIDEO_BIOS_START; 01080 } else { 01081 VideoBiosStart = (*((PULONG)BaseAddress + INT10_VECTOR) & 0xFFFF0000) >> 12; 01082 VideoBiosStart += (*((PULONG)BaseAddress + INT10_VECTOR) & 0x0000FFFF); 01083 VideoBiosStart &= 0xffff8000; 01084 if (VideoBiosStart < VIDEO_BIOS_START) { 01085 VideoBiosStart = VIDEO_BIOS_START; 01086 } 01087 Status = ZwUnmapViewOfSection( 01088 NtCurrentProcess(), 01089 BaseAddress 01090 ); 01091 } 01092 01093 VersionStrings = ExAllocatePool(PagedPool, VERSION_DATA_LENGTH); 01094 BaseAddress = 0; 01095 ViewSize = SYSTEM_BIOS_LENGTH; 01096 ViewBase.LowPart = SYSTEM_BIOS_START; 01097 ViewBase.HighPart = 0; 01098 01099 Status =ZwMapViewOfSection( 01100 SectionHandle, 01101 NtCurrentProcess(), 01102 &BaseAddress, 01103 0, 01104 ViewSize, 01105 &ViewBase, 01106 &ViewSize, 01107 ViewUnmap, 01108 MEM_DOS_LIM, 01109 PAGE_READWRITE 01110 ); 01111 01112 if (NT_SUCCESS(Status)) { 01113 if (CmpGetBiosDate(BaseAddress, SYSTEM_BIOS_LENGTH, Buffer, TRUE)) { 01114 01115 // 01116 // Convert ascii date string to unicode string and 01117 // store it in registry. 01118 // 01119 01120 RtlInitUnicodeString( 01121 &ValueName, 01122 L"SystemBiosDate" 01123 ); 01124 01125 RtlInitAnsiString( 01126 &AnsiString, 01127 Buffer 01128 ); 01129 01130 RtlAnsiStringToUnicodeString( 01131 &ValueData, 01132 &AnsiString, 01133 TRUE 01134 ); 01135 01136 Status = NtSetValueKey( 01137 ParentHandle, 01138 &ValueName, 01139 TITLE_INDEX_VALUE, 01140 REG_SZ, 01141 ValueData.Buffer, 01142 ValueData.Length + sizeof( UNICODE_NULL ) 01143 ); 01144 01145 RtlFreeUnicodeString(&ValueData); 01146 01147 #ifdef _WANT_MACHINE_IDENTIFICATION 01148 01149 memcpy(Buffer, (PCHAR)BaseAddress + 0xFFF5, 8); 01150 Buffer[8] = '\0'; 01151 01152 RtlInitAnsiString( 01153 &AnsiString, 01154 Buffer 01155 ); 01156 01157 Status = RtlAnsiStringToUnicodeString( 01158 &ValueData, 01159 &AnsiString, 01160 TRUE 01161 ); 01162 01163 if (NT_SUCCESS(Status)) { 01164 01165 Status = NtSetValueKey( 01166 BiosInfo, 01167 &ValueName, 01168 TITLE_INDEX_VALUE, 01169 REG_SZ, 01170 ValueData.Buffer, 01171 ValueData.Length + sizeof( UNICODE_NULL ) 01172 ); 01173 01174 RtlFreeUnicodeString(&ValueData); 01175 } 01176 01177 NtClose (BiosInfo); 01178 01179 #endif 01180 01181 } 01182 01183 if (VersionStrings && CmpGetBiosVersion(BaseAddress, SYSTEM_BIOS_LENGTH, Buffer)) { 01184 VersionPointer = VersionStrings; 01185 do { 01186 01187 // 01188 // Try to detect ALL the possible BIOS version strings. 01189 // Convert them to unicode strings and copy them to our 01190 // VersionStrings buffer. 01191 // 01192 01193 RtlInitAnsiString( 01194 &AnsiString, 01195 Buffer 01196 ); 01197 01198 RtlAnsiStringToUnicodeString( 01199 &ValueData, 01200 &AnsiString, 01201 TRUE 01202 ); 01203 01204 Length = ValueData.Length + sizeof(UNICODE_NULL); 01205 RtlMoveMemory(VersionPointer, 01206 ValueData.Buffer, 01207 Length 01208 ); 01209 VersionsLength += Length; 01210 RtlFreeUnicodeString(&ValueData); 01211 if (VersionsLength + (MAXIMUM_BIOS_VERSION_LENGTH + 01212 sizeof(UNICODE_NULL)) * 2 > PAGE_SIZE) { 01213 break; 01214 } 01215 VersionPointer += Length; 01216 } while (CmpGetBiosVersion(NULL, 0, Buffer)); 01217 01218 if (VersionsLength != 0) { 01219 01220 // 01221 // Append a UNICODE_NULL to the end of VersionStrings 01222 // 01223 01224 *(PWSTR)VersionPointer = UNICODE_NULL; 01225 VersionsLength += sizeof(UNICODE_NULL); 01226 01227 // 01228 // If any version string is found, we set up a ValueName and 01229 // initialize its value to the string(s) we found. 01230 // 01231 01232 RtlInitUnicodeString( 01233 &ValueName, 01234 L"SystemBiosVersion" 01235 ); 01236 01237 Status = NtSetValueKey( 01238 ParentHandle, 01239 &ValueName, 01240 TITLE_INDEX_VALUE, 01241 REG_MULTI_SZ, 01242 VersionStrings, 01243 VersionsLength 01244 ); 01245 } 01246 } 01247 ZwUnmapViewOfSection(NtCurrentProcess(), BaseAddress); 01248 } 01249 01250 // 01251 // Next we try to collect Video BIOS date and version strings. 01252 // 01253 01254 BaseAddress = 0; 01255 ViewSize = VIDEO_BIOS_LENGTH; 01256 ViewBase.LowPart = VideoBiosStart; 01257 ViewBase.HighPart = 0; 01258 01259 Status =ZwMapViewOfSection( 01260 SectionHandle, 01261 NtCurrentProcess(), 01262 &BaseAddress, 01263 0, 01264 ViewSize, 01265 &ViewBase, 01266 &ViewSize, 01267 ViewUnmap, 01268 MEM_DOS_LIM, 01269 PAGE_READWRITE 01270 ); 01271 01272 if (NT_SUCCESS(Status)) { 01273 if (CmpGetBiosDate(BaseAddress, VIDEO_BIOS_LENGTH, Buffer, FALSE)) { 01274 01275 RtlInitUnicodeString( 01276 &ValueName, 01277 L"VideoBiosDate" 01278 ); 01279 01280 RtlInitAnsiString( 01281 &AnsiString, 01282 Buffer 01283 ); 01284 01285 RtlAnsiStringToUnicodeString( 01286 &ValueData, 01287 &AnsiString, 01288 TRUE 01289 ); 01290 01291 Status = NtSetValueKey( 01292 ParentHandle, 01293 &ValueName, 01294 TITLE_INDEX_VALUE, 01295 REG_SZ, 01296 ValueData.Buffer, 01297 ValueData.Length + sizeof( UNICODE_NULL ) 01298 ); 01299 01300 RtlFreeUnicodeString(&ValueData); 01301 } 01302 01303 if (VersionStrings && CmpGetBiosVersion(BaseAddress, VIDEO_BIOS_LENGTH, Buffer)) { 01304 VersionPointer = VersionStrings; 01305 do { 01306 01307 // 01308 // Try to detect ALL the possible BIOS version strings. 01309 // Convert them to unicode strings and copy them to our 01310 // VersionStrings buffer. 01311 // 01312 01313 RtlInitAnsiString( 01314 &AnsiString, 01315 Buffer 01316 ); 01317 01318 RtlAnsiStringToUnicodeString( 01319 &ValueData, 01320 &AnsiString, 01321 TRUE 01322 ); 01323 01324 Length = ValueData.Length + sizeof(UNICODE_NULL); 01325 RtlMoveMemory(VersionPointer, 01326 ValueData.Buffer, 01327 Length 01328 ); 01329 VersionsLength += Length; 01330 RtlFreeUnicodeString(&ValueData); 01331 if (VersionsLength + (MAXIMUM_BIOS_VERSION_LENGTH + 01332 sizeof(UNICODE_NULL)) * 2 > PAGE_SIZE) { 01333 break; 01334 } 01335 VersionPointer += Length; 01336 } while (CmpGetBiosVersion(NULL, 0, Buffer)); 01337 01338 if (VersionsLength != 0) { 01339 01340 // 01341 // Append a UNICODE_NULL to the end of VersionStrings 01342 // 01343 01344 *(PWSTR)VersionPointer = UNICODE_NULL; 01345 VersionsLength += sizeof(UNICODE_NULL); 01346 01347 RtlInitUnicodeString( 01348 &ValueName, 01349 L"VideoBiosVersion" 01350 ); 01351 01352 Status = NtSetValueKey( 01353 ParentHandle, 01354 &ValueName, 01355 TITLE_INDEX_VALUE, 01356 REG_MULTI_SZ, 01357 VersionStrings, 01358 VersionsLength 01359 ); 01360 } 01361 } 01362 ZwUnmapViewOfSection(NtCurrentProcess(), BaseAddress); 01363 } 01364 ZwClose(SectionHandle); 01365 if (VersionStrings) { 01366 ExFreePool((PVOID)VersionStrings); 01367 } 01368 01369 AllDone: 01370 01371 NtClose (ParentHandle); 01372 01373 // 01374 // Add any other x86 specific code here... 01375 // 01376 01377 #ifdef _WANT_MACHINE_IDENTIFICATION 01378 01379 // 01380 // Do machine identification. 01381 // 01382 01383 CmpPerformMachineIdentification(LoaderBlock); 01384 01385 #endif 01386 01387 return STATUS_SUCCESS; 01388 } 01389 01390 #ifdef _WANT_MACHINE_IDENTIFICATION 01391 01392 VOID 01393 CmpPerformMachineIdentification( 01394 IN PLOADER_PARAMETER_BLOCK LoaderBlock 01395 ) 01396 { 01397 ULONG majorVersion; 01398 ULONG minorVersion; 01399 CHAR versionBuffer[64]; 01400 PCHAR major; 01401 PCHAR minor; 01402 01403 if (LoaderBlock->Extension && LoaderBlock->Extension->Size >= sizeof(LOADER_PARAMETER_EXTENSION)) { 01404 01405 major = strcpy(versionBuffer, VER_PRODUCTVERSION_STR); 01406 minor = strchr(major, '.'); 01407 *minor++ = '\0'; 01408 majorVersion = atoi(major); 01409 minorVersion = atoi(minor); 01410 if ( LoaderBlock->Extension->MajorVersion > majorVersion || 01411 (LoaderBlock->Extension->MajorVersion == majorVersion && 01412 LoaderBlock->Extension->MinorVersion >= minorVersion)) { 01413 01414 if (LoaderBlock->Extension->InfFileImage && LoaderBlock->Extension->InfFileSize) { 01415 01416 CmpMatchInfList( 01417 LoaderBlock->Extension->InfFileImage, 01418 LoaderBlock->Extension->InfFileSize, 01419 "MachineDescription" 01420 ); 01421 } 01422 } 01423 } 01424 } 01425 01426 #endif

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