Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygencmhardwr.c
Go to the documentation of this file.
00001 /* 00002 * PROJECT: ReactOS Kernel 00003 * LICENSE: GPL - See COPYING in the top level directory 00004 * FILE: ntoskrnl/config/i386/cmhardwr.c 00005 * PURPOSE: Configuration Manager - Hardware-Specific Code 00006 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) 00007 */ 00008 00009 /* INCLUDES ******************************************************************/ 00010 00011 #include "ntoskrnl.h" 00012 #define NDEBUG 00013 #include "debug.h" 00014 00015 /* GLOBALS *******************************************************************/ 00016 00017 PCHAR CmpID1 = "80%u86-%c%x"; 00018 PCHAR CmpID2 = "x86 Family %u Model %u Stepping %u"; 00019 PCHAR CmpBiosStrings[] = 00020 { 00021 "Ver", 00022 "Rev", 00023 "Rel", 00024 "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "v9", 00025 "v 0", "v 1", "v 2", "v 3", "v 4", "v 5", "v 6", "v 7", "v 8", "v 9", 00026 NULL 00027 }; 00028 00029 PCHAR CmpBiosBegin, CmpBiosSearchStart, CmpBiosSearchEnd; 00030 00031 /* FUNCTIONS *****************************************************************/ 00032 00033 BOOLEAN 00034 NTAPI 00035 CmpGetBiosDate(IN PCHAR BiosStart, 00036 IN ULONG BiosLength, 00037 IN PCHAR BiosDate, 00038 IN BOOLEAN FromBios) 00039 { 00040 CHAR LastDate[11] = {0}, CurrentDate[11]; 00041 PCHAR p, pp; 00042 00043 /* Skip the signature and the magic, and loop the BIOS ROM */ 00044 p = BiosStart + 2; 00045 pp = BiosStart + BiosLength - 5; 00046 while (p < pp) 00047 { 00048 /* Check for xx/yy/zz which we assume to be a date */ 00049 if ((p[0] == '/') && 00050 (p[3] == '/') && 00051 (isdigit(p[-1])) && 00052 (isdigit(p[1])) && 00053 (isdigit(p[2])) && 00054 (isdigit(p[4])) && 00055 (isdigit(p[5]))) 00056 { 00057 /* Copy the string proper */ 00058 RtlMoveMemory(&CurrentDate[5], p - 2, 5); 00059 00060 /* Add a 0 if the month only has one digit */ 00061 if (!isdigit(CurrentDate[5])) CurrentDate[5] = '0'; 00062 00063 /* Now copy the year */ 00064 CurrentDate[2] = p[4]; 00065 CurrentDate[3] = p[5]; 00066 CurrentDate[4] = CurrentDate[7] = CurrentDate[10] = ANSI_NULL; 00067 00068 /* If the date comes from the BIOS, check if it's a 4-digit year */ 00069 if ((FromBios) && 00070 (isdigit(p[6])) && 00071 (isdigit(p[7])) && 00072 ((RtlEqualMemory(&p[4], "19", 2)) || 00073 (RtlEqualMemory(&p[4], "20", 2)))) 00074 { 00075 /* Copy the year proper */ 00076 CurrentDate[0] = p[4]; 00077 CurrentDate[1] = p[5]; 00078 CurrentDate[2] = p[6]; 00079 CurrentDate[3] = p[7]; 00080 } 00081 else 00082 { 00083 /* Otherwise, we'll just assume anything under 80 is 2000 */ 00084 if (strtoul(&CurrentDate[2], NULL, 10) < 80) 00085 { 00086 /* Hopefully your BIOS wasn't made in 1979 */ 00087 CurrentDate[0] = '2'; 00088 CurrentDate[1] = '0'; 00089 } 00090 else 00091 { 00092 /* Anything over 80, was probably made in the 1900s... */ 00093 CurrentDate[0] = '1'; 00094 CurrentDate[1] = '9'; 00095 } 00096 } 00097 00098 /* Add slashes where we previously had NULLs */ 00099 CurrentDate[4] = CurrentDate[7] = '/'; 00100 00101 /* Check which date is newer */ 00102 if (memcmp(LastDate, CurrentDate, 10) < 0) 00103 { 00104 /* Found a newer date, select it */ 00105 RtlMoveMemory(LastDate, CurrentDate, 10); 00106 } 00107 00108 p += 2; 00109 } 00110 p++; 00111 } 00112 00113 /* Make sure we found a date */ 00114 if (LastDate[0]) 00115 { 00116 /* Copy the year at the pp, and keep only the last two digits */ 00117 RtlMoveMemory(BiosDate, &LastDate[5], 5); 00118 BiosDate[5] = '/'; 00119 BiosDate[6] = LastDate[2]; 00120 BiosDate[7] = LastDate[3]; 00121 BiosDate[8] = ANSI_NULL; 00122 return TRUE; 00123 } 00124 00125 /* No date found, return empty string */ 00126 BiosDate[0] = ANSI_NULL; 00127 return FALSE; 00128 } 00129 00130 BOOLEAN 00131 NTAPI 00132 CmpGetBiosVersion(IN PCHAR BiosStart, 00133 IN ULONG BiosLength, 00134 IN PCHAR BiosVersion) 00135 { 00136 CHAR Buffer[128]; 00137 PCHAR p, pp; 00138 USHORT i; 00139 00140 /* Check if we were given intitial data for the search */ 00141 if (BiosStart) 00142 { 00143 /* Save it for later use */ 00144 CmpBiosBegin = BiosStart; 00145 CmpBiosSearchStart = BiosStart + 1; 00146 CmpBiosSearchEnd = BiosStart + BiosLength - 2; 00147 } 00148 00149 /* Now loop the BIOS area */ 00150 for (;;) 00151 { 00152 /* Start an initial search looking for numbers and periods */ 00153 pp = NULL; 00154 while (CmpBiosSearchStart <= CmpBiosSearchEnd) 00155 { 00156 /* Check if we have an "x.y" version string */ 00157 if ((*CmpBiosSearchStart == '.') && 00158 (*(CmpBiosSearchStart + 1) >= '0') && 00159 (*(CmpBiosSearchStart + 1) <= '9') && 00160 (*(CmpBiosSearchStart - 1) >= '0') && 00161 (*(CmpBiosSearchStart - 1) <= '9')) 00162 { 00163 /* Start looking in this area for the actual BIOS Version */ 00164 pp = CmpBiosSearchStart; 00165 break; 00166 } 00167 else 00168 { 00169 /* Keep searching */ 00170 CmpBiosSearchStart++; 00171 } 00172 } 00173 00174 /* Break out if we're went past the BIOS area */ 00175 if (CmpBiosSearchStart > CmpBiosSearchEnd) return FALSE; 00176 00177 /* Move to the next 2 bytes */ 00178 CmpBiosSearchStart += 2; 00179 00180 /* Null-terminate our scratch buffer and start the string here */ 00181 Buffer[127] = ANSI_NULL; 00182 p = &Buffer[127]; 00183 00184 /* Go back one character since we're doing this backwards */ 00185 pp--; 00186 00187 /* Loop the identifier we found as long as it's valid */ 00188 i = 0; 00189 while ((i++ < 127) && 00190 (pp >= CmpBiosBegin) && 00191 (*pp >= ' ') && 00192 (*pp != '$')) 00193 { 00194 /* Copy the character */ 00195 *--p = *pp--; 00196 } 00197 00198 /* Go past the last character since we went backwards */ 00199 pp++; 00200 00201 /* Loop the strings we recognize */ 00202 for (i = 0; CmpBiosStrings[i]; i++) 00203 { 00204 /* Check if a match was found */ 00205 if (strstr(p, CmpBiosStrings[i])) goto Match; 00206 } 00207 } 00208 00209 Match: 00210 /* Skip until we find a space */ 00211 for (; *pp == ' '; pp++); 00212 00213 /* Loop the final string */ 00214 i = 0; 00215 do 00216 { 00217 /* Copy the character into the final string */ 00218 BiosVersion[i] = *pp++; 00219 } while ((++i < 127) && 00220 (pp <= (CmpBiosSearchEnd + 1)) && 00221 (*pp >= ' ') && 00222 (*pp != '$')); 00223 00224 /* Null-terminate the version string */ 00225 BiosVersion[i] = ANSI_NULL; 00226 return TRUE; 00227 } 00228 00229 NTSTATUS 00230 NTAPI 00231 CmpInitializeMachineDependentConfiguration(IN PLOADER_PARAMETER_BLOCK LoaderBlock) 00232 { 00233 UNICODE_STRING KeyName, ValueName, Data, SectionName; 00234 OBJECT_ATTRIBUTES ObjectAttributes; 00235 ULONG HavePae, Length, TotalLength = 0, i, Disposition; 00236 SIZE_T ViewSize; 00237 NTSTATUS Status; 00238 HANDLE KeyHandle, BiosHandle, SystemHandle, FpuHandle, SectionHandle; 00239 CONFIGURATION_COMPONENT_DATA ConfigData; 00240 CHAR Buffer[128]; 00241 ULONG ExtendedId, Dummy; 00242 PKPRCB Prcb; 00243 USHORT IndexTable[MaximumType + 1] = {0}; 00244 ANSI_STRING TempString; 00245 PCHAR PartialString = NULL, BiosVersion; 00246 CHAR CpuString[48]; 00247 PVOID BaseAddress = NULL; 00248 LARGE_INTEGER ViewBase = {{0, 0}}; 00249 ULONG_PTR VideoRomBase; 00250 PCHAR CurrentVersion; 00251 extern UNICODE_STRING KeRosProcessorName, KeRosBiosDate, KeRosBiosVersion; 00252 extern UNICODE_STRING KeRosVideoBiosDate, KeRosVideoBiosVersion; 00253 00254 /* Open the SMSS Memory Management key */ 00255 RtlInitUnicodeString(&KeyName, 00256 L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\" 00257 L"Control\\Session Manager\\Memory Management"); 00258 InitializeObjectAttributes(&ObjectAttributes, 00259 &KeyName, 00260 OBJ_CASE_INSENSITIVE, 00261 NULL, 00262 NULL); 00263 Status = NtOpenKey(&KeyHandle, KEY_READ | KEY_WRITE, &ObjectAttributes); 00264 if (NT_SUCCESS(Status)) 00265 { 00266 /* Detect if PAE is enabled */ 00267 HavePae = SharedUserData->ProcessorFeatures[PF_PAE_ENABLED]; 00268 00269 /* Set the value */ 00270 RtlInitUnicodeString(&ValueName, L"PhysicalAddressExtension"); 00271 NtSetValueKey(KeyHandle, 00272 &ValueName, 00273 0, 00274 REG_DWORD, 00275 &HavePae, 00276 sizeof(HavePae)); 00277 00278 /* Close the key */ 00279 NtClose(KeyHandle); 00280 } 00281 00282 /* Open the hardware description key */ 00283 RtlInitUnicodeString(&KeyName, 00284 L"\\Registry\\Machine\\Hardware\\Description\\System"); 00285 InitializeObjectAttributes(&ObjectAttributes, 00286 &KeyName, 00287 OBJ_CASE_INSENSITIVE, 00288 NULL, 00289 NULL); 00290 Status = NtOpenKey(&SystemHandle, KEY_READ | KEY_WRITE, &ObjectAttributes); 00291 if (!NT_SUCCESS(Status)) return Status; 00292 00293 /* Create the BIOS Information key */ 00294 RtlInitUnicodeString(&KeyName, 00295 L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\" 00296 L"Control\\BIOSINFO"); 00297 InitializeObjectAttributes(&ObjectAttributes, 00298 &KeyName, 00299 OBJ_CASE_INSENSITIVE, 00300 NULL, 00301 NULL); 00302 Status = NtCreateKey(&BiosHandle, 00303 KEY_ALL_ACCESS, 00304 &ObjectAttributes, 00305 0, 00306 NULL, 00307 REG_OPTION_NON_VOLATILE, 00308 &Disposition); 00309 if (ExpInTextModeSetup) 00310 { 00311 if (!NT_SUCCESS(Status)) 00312 BiosHandle = NULL; 00313 } 00314 else if (!NT_SUCCESS(Status)) 00315 return Status; 00316 00317 /* Create the CPU Key, and check if it already existed */ 00318 RtlInitUnicodeString(&KeyName, L"CentralProcessor"); 00319 InitializeObjectAttributes(&ObjectAttributes, 00320 &KeyName, 00321 OBJ_CASE_INSENSITIVE, 00322 SystemHandle, 00323 NULL); 00324 Status = NtCreateKey(&KeyHandle, 00325 KEY_READ | KEY_WRITE, 00326 &ObjectAttributes, 00327 0, 00328 NULL, 00329 0, 00330 &Disposition); 00331 NtClose(KeyHandle); 00332 00333 /* The key shouldn't already exist */ 00334 if (Disposition == REG_CREATED_NEW_KEY) 00335 { 00336 /* Allocate the configuration data for cmconfig.c */ 00337 CmpConfigurationData = ExAllocatePoolWithTag(PagedPool, 00338 CmpConfigurationAreaSize, 00339 TAG_CM); 00340 if (!CmpConfigurationData) return STATUS_INSUFFICIENT_RESOURCES; 00341 00342 /* Loop all CPUs */ 00343 for (i = 0; i < KeNumberProcessors; i++) 00344 { 00345 /* Get the PRCB */ 00346 Prcb = KiProcessorBlock[i]; 00347 00348 /* Setup the Configuration Entry for the Processor */ 00349 RtlZeroMemory(&ConfigData, sizeof (ConfigData)); 00350 ConfigData.ComponentEntry.Class = ProcessorClass; 00351 ConfigData.ComponentEntry.Type = CentralProcessor; 00352 ConfigData.ComponentEntry.Key = i; 00353 ConfigData.ComponentEntry.AffinityMask = AFFINITY_MASK(i); 00354 ConfigData.ComponentEntry.Identifier = Buffer; 00355 00356 /* Check if the CPU doesn't support CPUID */ 00357 if (!Prcb->CpuID) 00358 { 00359 /* Build ID1-style string for older CPUs */ 00360 sprintf(Buffer, 00361 CmpID1, 00362 Prcb->CpuType, 00363 (Prcb->CpuStep >> 8) + 'A', 00364 Prcb->CpuStep & 0xff); 00365 } 00366 else 00367 { 00368 /* Build ID2-style string for newer CPUs */ 00369 sprintf(Buffer, 00370 CmpID2, 00371 Prcb->CpuType, 00372 (Prcb->CpuStep >> 8), 00373 Prcb->CpuStep & 0xff); 00374 } 00375 00376 /* Save the ID string length now that we've created it */ 00377 ConfigData.ComponentEntry.IdentifierLength = (ULONG)strlen(Buffer) + 1; 00378 00379 /* Initialize the registry configuration node for it */ 00380 Status = CmpInitializeRegistryNode(&ConfigData, 00381 SystemHandle, 00382 &KeyHandle, 00383 InterfaceTypeUndefined, 00384 0xFFFFFFFF, 00385 IndexTable); 00386 if (!NT_SUCCESS(Status)) return(Status); 00387 00388 /* Check if we have an FPU */ 00389 if (KeI386NpxPresent) 00390 { 00391 /* Setup the Configuration Entry for the FPU */ 00392 RtlZeroMemory(&ConfigData, sizeof(ConfigData)); 00393 ConfigData.ComponentEntry.Class = ProcessorClass; 00394 ConfigData.ComponentEntry.Type = FloatingPointProcessor; 00395 ConfigData.ComponentEntry.Key = i; 00396 ConfigData.ComponentEntry.AffinityMask = AFFINITY_MASK(i); 00397 ConfigData.ComponentEntry.Identifier = Buffer; 00398 00399 /* For 386 cpus, the CPU pp is the identifier */ 00400 if (Prcb->CpuType == 3) strcpy(Buffer, "80387"); 00401 00402 /* Save the ID string length now that we've created it */ 00403 ConfigData.ComponentEntry.IdentifierLength = (ULONG)strlen(Buffer) + 1; 00404 00405 /* Initialize the registry configuration node for it */ 00406 Status = CmpInitializeRegistryNode(&ConfigData, 00407 SystemHandle, 00408 &FpuHandle, 00409 InterfaceTypeUndefined, 00410 0xFFFFFFFF, 00411 IndexTable); 00412 if (!NT_SUCCESS(Status)) 00413 { 00414 /* Failed, close the CPU handle and return */ 00415 NtClose(KeyHandle); 00416 return Status; 00417 } 00418 00419 /* Close this new handle */ 00420 NtClose(FpuHandle); 00421 00422 /* Stay on this CPU only */ 00423 KeSetSystemAffinityThread(Prcb->SetMember); 00424 if (!Prcb->CpuID) 00425 { 00426 /* Uh oh, no CPUID! */ 00427 } 00428 else 00429 { 00430 /* Check if we have extended CPUID that supports name ID */ 00431 CPUID(0x80000000, &ExtendedId, &Dummy, &Dummy, &Dummy); 00432 if (ExtendedId >= 0x80000004) 00433 { 00434 /* Do all the CPUIDs required to get the full name */ 00435 PartialString = CpuString; 00436 for (ExtendedId = 2; ExtendedId <= 4; ExtendedId++) 00437 { 00438 /* Do the CPUID and save the name string */ 00439 CPUID(0x80000000 | ExtendedId, 00440 (PULONG)PartialString, 00441 (PULONG)PartialString + 1, 00442 (PULONG)PartialString + 2, 00443 (PULONG)PartialString + 3); 00444 00445 /* Go to the next name string */ 00446 PartialString += 16; 00447 } 00448 00449 /* Null-terminate it */ 00450 CpuString[47] = ANSI_NULL; 00451 } 00452 } 00453 00454 /* Go back to user affinity */ 00455 KeRevertToUserAffinityThread(); 00456 00457 /* Check if we have a CPU Name */ 00458 if (PartialString) 00459 { 00460 /* Convert it to Unicode */ 00461 RtlInitAnsiString(&TempString, CpuString); 00462 RtlAnsiStringToUnicodeString(&Data, &TempString, TRUE); 00463 00464 /* Add it to the registry */ 00465 RtlInitUnicodeString(&ValueName, L"ProcessorNameString"); 00466 Status = NtSetValueKey(KeyHandle, 00467 &ValueName, 00468 0, 00469 REG_SZ, 00470 Data.Buffer, 00471 Data.Length + sizeof(UNICODE_NULL)); 00472 00473 /* ROS: Save a copy for bugzilla reporting */ 00474 RtlCreateUnicodeString(&KeRosProcessorName, Data.Buffer); 00475 00476 /* Free the temporary buffer */ 00477 RtlFreeUnicodeString(&Data); 00478 } 00479 00480 /* Check if we had a Vendor ID */ 00481 if (Prcb->VendorString[0]) 00482 { 00483 /* Convert it to Unicode */ 00484 RtlInitAnsiString(&TempString, Prcb->VendorString); 00485 RtlAnsiStringToUnicodeString(&Data, &TempString, TRUE); 00486 00487 /* Add it to the registry */ 00488 RtlInitUnicodeString(&ValueName, L"VendorIdentifier"); 00489 Status = NtSetValueKey(KeyHandle, 00490 &ValueName, 00491 0, 00492 REG_SZ, 00493 Data.Buffer, 00494 Data.Length + sizeof(UNICODE_NULL)); 00495 00496 /* Free the temporary buffer */ 00497 RtlFreeUnicodeString(&Data); 00498 } 00499 00500 /* Check if we have features bits */ 00501 if (Prcb->FeatureBits) 00502 { 00503 /* Add them to the registry */ 00504 RtlInitUnicodeString(&ValueName, L"FeatureSet"); 00505 Status = NtSetValueKey(KeyHandle, 00506 &ValueName, 00507 0, 00508 REG_DWORD, 00509 &Prcb->FeatureBits, 00510 sizeof(Prcb->FeatureBits)); 00511 } 00512 00513 /* Check if we detected the CPU Speed */ 00514 if (Prcb->MHz) 00515 { 00516 /* Add it to the registry */ 00517 RtlInitUnicodeString(&ValueName, L"~MHz"); 00518 Status = NtSetValueKey(KeyHandle, 00519 &ValueName, 00520 0, 00521 REG_DWORD, 00522 &Prcb->MHz, 00523 sizeof(Prcb->MHz)); 00524 } 00525 00526 /* Check if we have an update signature */ 00527 if (Prcb->UpdateSignature.QuadPart) 00528 { 00529 /* Add it to the registry */ 00530 RtlInitUnicodeString(&ValueName, L"Update Signature"); 00531 Status = NtSetValueKey(KeyHandle, 00532 &ValueName, 00533 0, 00534 REG_BINARY, 00535 &Prcb->UpdateSignature, 00536 sizeof(Prcb->UpdateSignature)); 00537 } 00538 00539 /* Close the processor handle */ 00540 NtClose(KeyHandle); 00541 00542 /* FIXME: Detect CPU mismatches */ 00543 } 00544 } 00545 00546 /* Free the configuration data */ 00547 ExFreePoolWithTag(CmpConfigurationData, TAG_CM); 00548 } 00549 00550 /* Open physical memory */ 00551 RtlInitUnicodeString(&SectionName, L"\\Device\\PhysicalMemory"); 00552 InitializeObjectAttributes(&ObjectAttributes, 00553 &SectionName, 00554 OBJ_CASE_INSENSITIVE, 00555 NULL, 00556 NULL); 00557 Status = ZwOpenSection(&SectionHandle, 00558 SECTION_ALL_ACCESS, 00559 &ObjectAttributes); 00560 if (!NT_SUCCESS(Status)) goto Quickie; 00561 00562 /* Map the first 1KB of memory to get the IVT */ 00563 ViewSize = PAGE_SIZE; 00564 Status = ZwMapViewOfSection(SectionHandle, 00565 NtCurrentProcess(), 00566 &BaseAddress, 00567 0, 00568 ViewSize, 00569 &ViewBase, 00570 &ViewSize, 00571 ViewUnmap, 00572 MEM_DOS_LIM, 00573 PAGE_READWRITE); 00574 if (!NT_SUCCESS(Status)) 00575 { 00576 /* Assume default */ 00577 VideoRomBase = 0xC0000; 00578 } 00579 else 00580 { 00581 /* Calculate the base address from the vector */ 00582 VideoRomBase = (*((PULONG)BaseAddress + 0x10) >> 12) & 0xFFFF0; 00583 VideoRomBase += *((PULONG)BaseAddress + 0x10) & 0xFFF0; 00584 00585 /* Now get to the actual ROM Start and make sure it's not invalid*/ 00586 VideoRomBase &= 0xFFFF8000; 00587 if (VideoRomBase < 0xC0000) VideoRomBase = 0xC0000; 00588 00589 /* And unmap the section */ 00590 ZwUnmapViewOfSection(NtCurrentProcess(), BaseAddress); 00591 } 00592 00593 /* Allocate BIOS Version pp Buffer */ 00594 BiosVersion = ExAllocatePoolWithTag(PagedPool, PAGE_SIZE, TAG_CM); 00595 00596 /* Setup settings to map the 64K BIOS ROM */ 00597 BaseAddress = 0; 00598 ViewSize = 16 * PAGE_SIZE; 00599 ViewBase.LowPart = 0xF0000; 00600 ViewBase.HighPart = 0; 00601 00602 /* Map it */ 00603 Status = ZwMapViewOfSection(SectionHandle, 00604 NtCurrentProcess(), 00605 &BaseAddress, 00606 0, 00607 ViewSize, 00608 &ViewBase, 00609 &ViewSize, 00610 ViewUnmap, 00611 MEM_DOS_LIM, 00612 PAGE_READWRITE); 00613 if (NT_SUCCESS(Status)) 00614 { 00615 /* Scan the ROM to get the BIOS Date */ 00616 if (CmpGetBiosDate(BaseAddress, 16 * PAGE_SIZE, Buffer, TRUE)) 00617 { 00618 /* Convert it to Unicode */ 00619 RtlInitAnsiString(&TempString, Buffer); 00620 RtlAnsiStringToUnicodeString(&Data, &TempString, TRUE); 00621 00622 /* Write the date into the registry */ 00623 RtlInitUnicodeString(&ValueName, L"SystemBiosDate"); 00624 Status = NtSetValueKey(SystemHandle, 00625 &ValueName, 00626 0, 00627 REG_SZ, 00628 Data.Buffer, 00629 Data.Length + sizeof(UNICODE_NULL)); 00630 00631 /* Free the string */ 00632 RtlFreeUnicodeString(&Data); 00633 00634 if (BiosHandle) 00635 { 00636 /* Get the BIOS Date Identifier */ 00637 RtlCopyMemory(Buffer, (PCHAR)BaseAddress + (16 * PAGE_SIZE - 11), 8); 00638 Buffer[8] = ANSI_NULL; 00639 00640 /* Convert it to unicode */ 00641 RtlInitAnsiString(&TempString, Buffer); 00642 Status = RtlAnsiStringToUnicodeString(&Data, &TempString, TRUE); 00643 if (NT_SUCCESS(Status)) 00644 { 00645 /* Save it to the registry */ 00646 Status = NtSetValueKey(BiosHandle, 00647 &ValueName, 00648 0, 00649 REG_SZ, 00650 Data.Buffer, 00651 Data.Length + sizeof(UNICODE_NULL)); 00652 00653 /* ROS: Save a copy for bugzilla reporting */ 00654 RtlCreateUnicodeString(&KeRosBiosDate, Data.Buffer); 00655 00656 /* Free the string */ 00657 RtlFreeUnicodeString(&Data); 00658 } 00659 00660 /* Close the bios information handle */ 00661 NtClose(BiosHandle); 00662 } 00663 } 00664 00665 /* Get the BIOS Version */ 00666 if (CmpGetBiosVersion(BaseAddress, 16 * PAGE_SIZE, Buffer)) 00667 { 00668 /* Start at the beginning of our buffer */ 00669 CurrentVersion = BiosVersion; 00670 do 00671 { 00672 /* Convert to Unicode */ 00673 RtlInitAnsiString(&TempString, Buffer); 00674 RtlAnsiStringToUnicodeString(&Data, &TempString, TRUE); 00675 00676 /* Calculate the length of this string and copy it in */ 00677 Length = Data.Length + sizeof(UNICODE_NULL); 00678 RtlMoveMemory(CurrentVersion, Data.Buffer, Length); 00679 00680 /* Free the unicode string */ 00681 RtlFreeUnicodeString(&Data); 00682 00683 /* Update the total length and see if we're out of space */ 00684 TotalLength += Length; 00685 if (TotalLength + 256 + sizeof(UNICODE_NULL) > PAGE_SIZE) 00686 { 00687 /* One more string would push us out, so stop here */ 00688 break; 00689 } 00690 00691 /* Go to the next string inside the multi-string buffer */ 00692 CurrentVersion += Length; 00693 00694 /* Query the next BIOS Version */ 00695 } while (CmpGetBiosVersion(NULL, 0, Buffer)); 00696 00697 /* Check if we found any strings at all */ 00698 if (TotalLength) 00699 { 00700 /* Add the final null-terminator */ 00701 *(PWSTR)CurrentVersion = UNICODE_NULL; 00702 TotalLength += sizeof(UNICODE_NULL); 00703 00704 /* Write the BIOS Version to the registry */ 00705 RtlInitUnicodeString(&ValueName, L"SystemBiosVersion"); 00706 Status = NtSetValueKey(SystemHandle, 00707 &ValueName, 00708 0, 00709 REG_MULTI_SZ, 00710 BiosVersion, 00711 TotalLength); 00712 00713 /* ROS: Save a copy for bugzilla reporting */ 00714 RtlCreateUnicodeString(&KeRosBiosVersion, (PWCH)BiosVersion); 00715 } 00716 } 00717 00718 /* Unmap the section */ 00719 ZwUnmapViewOfSection(NtCurrentProcess(), BaseAddress); 00720 } 00721 00722 /* Now prepare for Video BIOS Mapping of 32KB */ 00723 BaseAddress = 0; 00724 ViewSize = 8 * PAGE_SIZE; 00725 ViewBase.QuadPart = VideoRomBase; 00726 00727 /* Map it */ 00728 Status = ZwMapViewOfSection(SectionHandle, 00729 NtCurrentProcess(), 00730 &BaseAddress, 00731 0, 00732 ViewSize, 00733 &ViewBase, 00734 &ViewSize, 00735 ViewUnmap, 00736 MEM_DOS_LIM, 00737 PAGE_READWRITE); 00738 if (NT_SUCCESS(Status)) 00739 { 00740 /* Scan the ROM to get the BIOS Date */ 00741 if (CmpGetBiosDate(BaseAddress, 8 * PAGE_SIZE, Buffer, FALSE)) 00742 { 00743 /* Convert it to Unicode */ 00744 RtlInitAnsiString(&TempString, Buffer); 00745 RtlAnsiStringToUnicodeString(&Data, &TempString, TRUE); 00746 00747 /* Write the date into the registry */ 00748 RtlInitUnicodeString(&ValueName, L"VideoBiosDate"); 00749 Status = NtSetValueKey(SystemHandle, 00750 &ValueName, 00751 0, 00752 REG_SZ, 00753 Data.Buffer, 00754 Data.Length + sizeof(UNICODE_NULL)); 00755 00756 /* ROS: Save a copy for bugzilla reporting */ 00757 RtlCreateUnicodeString(&KeRosVideoBiosDate, Data.Buffer); 00758 00759 /* Free the string */ 00760 RtlFreeUnicodeString(&Data); 00761 } 00762 00763 /* Get the Video BIOS Version */ 00764 if (CmpGetBiosVersion(BaseAddress, 8 * PAGE_SIZE, Buffer)) 00765 { 00766 /* Start at the beginning of our buffer */ 00767 CurrentVersion = BiosVersion; 00768 do 00769 { 00770 /* Convert to Unicode */ 00771 RtlInitAnsiString(&TempString, Buffer); 00772 RtlAnsiStringToUnicodeString(&Data, &TempString, TRUE); 00773 00774 /* Calculate the length of this string and copy it in */ 00775 Length = Data.Length + sizeof(UNICODE_NULL); 00776 RtlMoveMemory(CurrentVersion, Data.Buffer, Length); 00777 00778 /* Free the unicode string */ 00779 RtlFreeUnicodeString(&Data); 00780 00781 /* Update the total length and see if we're out of space */ 00782 TotalLength += Length; 00783 if (TotalLength + 256 + sizeof(UNICODE_NULL) > PAGE_SIZE) 00784 { 00785 /* One more string would push us out, so stop here */ 00786 break; 00787 } 00788 00789 /* Go to the next string inside the multi-string buffer */ 00790 CurrentVersion += Length; 00791 00792 /* Query the next BIOS Version */ 00793 } while (CmpGetBiosVersion(NULL, 0, Buffer)); 00794 00795 /* Check if we found any strings at all */ 00796 if (TotalLength) 00797 { 00798 /* Add the final null-terminator */ 00799 *(PWSTR)CurrentVersion = UNICODE_NULL; 00800 TotalLength += sizeof(UNICODE_NULL); 00801 00802 /* Write the BIOS Version to the registry */ 00803 RtlInitUnicodeString(&ValueName, L"VideoBiosVersion"); 00804 Status = NtSetValueKey(SystemHandle, 00805 &ValueName, 00806 0, 00807 REG_MULTI_SZ, 00808 BiosVersion, 00809 TotalLength); 00810 00811 /* ROS: Save a copy for bugzilla reporting */ 00812 RtlCreateUnicodeString(&KeRosVideoBiosVersion, (PWCH)BiosVersion); 00813 } 00814 } 00815 00816 /* Unmap the section */ 00817 ZwUnmapViewOfSection(NtCurrentProcess(), BaseAddress); 00818 } 00819 00820 /* Close the section */ 00821 ZwClose(SectionHandle); 00822 00823 /* Free the BIOS version string buffer */ 00824 if (BiosVersion) ExFreePoolWithTag(BiosVersion, TAG_CM); 00825 00826 Quickie: 00827 /* Close the procesor handle */ 00828 NtClose(KeyHandle); 00829 return STATUS_SUCCESS; 00830 } Generated on Sat May 26 2012 04:35:57 for ReactOS by
1.7.6.1
|