[NTOS] Remove some hacks that are not needed anymore, since a real registry hive...
[reactos.git] / ntoskrnl / config / powerpc / cmhardwr.c
1 /*
2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: ntoskrnl/config/powerpc/cmhardwr.c
5 * PURPOSE: Configuration Manager - Hardware-Specific Code
6 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
7 */
8
9 /* INCLUDES ******************************************************************/
10
11 #include "ntoskrnl.h"
12 #define NDEBUG
13 #include "debug.h"
14
15 /* GLOBALS *******************************************************************/
16
17 PCHAR CmpID1 = "PowerPC %u";
18 PCHAR CmpID2 = "No Data";
19 PCHAR CmpBiosStrings[] =
20 {
21 "Ver",
22 "Rev",
23 "Rel",
24 "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "v9",
25 "v 0", "v 1", "v 2", "v 3", "v 4", "v 5", "v 6", "v 7", "v 8", "v 9",
26 NULL
27 };
28
29 PCHAR CmpBiosBegin, CmpBiosSearchStart, CmpBiosSearchEnd;
30
31 /* FUNCTIONS *****************************************************************/
32
33 BOOLEAN
34 NTAPI
35 CmpGetBiosDate(IN PCHAR BiosStart,
36 IN ULONG BiosLength,
37 IN PCHAR BiosDate,
38 IN BOOLEAN FromBios)
39 {
40 CHAR LastDate[11] = {0}, CurrentDate[11];
41 PCHAR p, pp;
42
43 /* Skip the signature and the magic, and loop the BIOS ROM */
44 p = BiosStart + 2;
45 pp = BiosStart + BiosLength - 5;
46 while (p < pp)
47 {
48 /* Check for xx/yy/zz which we assume to be a date */
49 if ((p[0] == '/') &&
50 (p[3] == '/') &&
51 (isdigit(p[-1])) &&
52 (isdigit(p[1])) &&
53 (isdigit(p[2])) &&
54 (isdigit(p[4])) &&
55 (isdigit(p[5])))
56 {
57 /* Copy the string proper */
58 RtlMoveMemory(&CurrentDate[5], p - 2, 5);
59
60 /* Add a 0 if the month only has one digit */
61 if (!isdigit(CurrentDate[5])) CurrentDate[5] = '0';
62
63 /* Now copy the year */
64 CurrentDate[2] = p[4];
65 CurrentDate[3] = p[5];
66 CurrentDate[4] = CurrentDate[7] = CurrentDate[10] = ANSI_NULL;
67
68 /* If the date comes from the BIOS, check if it's a 4-digit year */
69 if ((FromBios) &&
70 (isdigit(p[6])) &&
71 (isdigit(p[7])) &&
72 ((RtlEqualMemory(&p[4], "19", 2)) ||
73 (RtlEqualMemory(&p[4], "20", 2))))
74 {
75 /* Copy the year proper */
76 CurrentDate[0] = p[4];
77 CurrentDate[1] = p[5];
78 CurrentDate[2] = p[6];
79 CurrentDate[3] = p[7];
80 }
81 else
82 {
83 /* Otherwise, we'll just assume anything under 80 is 2000 */
84 if (strtoul(&CurrentDate[2], NULL, 10) < 80)
85 {
86 /* Hopefully your BIOS wasn't made in 1979 */
87 CurrentDate[0] = '2';
88 CurrentDate[1] = '0';
89 }
90 else
91 {
92 /* Anything over 80, was probably made in the 1900s... */
93 CurrentDate[0] = '1';
94 CurrentDate[1] = '9';
95 }
96 }
97
98 /* Add slashes where we previously had NULLs */
99 CurrentDate[4] = CurrentDate[7] = '/';
100
101 /* Check which date is newer */
102 if (memcmp(LastDate, CurrentDate, 10) < 0)
103 {
104 /* Found a newer date, select it */
105 RtlMoveMemory(LastDate, CurrentDate, 10);
106 }
107
108 p += 2;
109 }
110 p++;
111 }
112
113 /* Make sure we found a date */
114 if (LastDate[0])
115 {
116 /* Copy the year at the pp, and keep only the last two digits */
117 RtlMoveMemory(BiosDate, &LastDate[5], 5);
118 BiosDate[5] = '/';
119 BiosDate[6] = LastDate[2];
120 BiosDate[7] = LastDate[3];
121 BiosDate[8] = ANSI_NULL;
122 return TRUE;
123 }
124
125 /* No date found, return empty string */
126 BiosDate[0] = ANSI_NULL;
127 return FALSE;
128 }
129
130 BOOLEAN
131 NTAPI
132 CmpGetBiosVersion(IN PCHAR BiosStart,
133 IN ULONG BiosLength,
134 IN PCHAR BiosVersion)
135 {
136 CHAR Buffer[128];
137 PCHAR p, pp;
138 USHORT i;
139
140 /* Check if we were given intitial data for the search */
141 if (BiosStart)
142 {
143 /* Save it for later use */
144 CmpBiosBegin = BiosStart;
145 CmpBiosSearchStart = BiosStart + 1;
146 CmpBiosSearchEnd = BiosStart + BiosLength - 2;
147 }
148
149 /* Now loop the BIOS area */
150 for (;;)
151 {
152 /* Start an initial search looking for numbers and periods */
153 pp = NULL;
154 while (CmpBiosSearchStart <= CmpBiosSearchEnd)
155 {
156 /* Check if we have an "x.y" version string */
157 if ((*CmpBiosSearchStart == '.') &&
158 (*(CmpBiosSearchStart + 1) >= '0') &&
159 (*(CmpBiosSearchStart + 1) <= '9') &&
160 (*(CmpBiosSearchStart - 1) >= '0') &&
161 (*(CmpBiosSearchStart - 1) <= '9'))
162 {
163 /* Start looking in this area for the actual BIOS Version */
164 pp = CmpBiosSearchStart;
165 break;
166 }
167 else
168 {
169 /* Keep searching */
170 CmpBiosSearchStart++;
171 }
172 }
173
174 /* Break out if we're went past the BIOS area */
175 if (CmpBiosSearchStart > CmpBiosSearchEnd) return FALSE;
176
177 /* Move to the next 2 bytes */
178 CmpBiosSearchStart += 2;
179
180 /* Null-terminate our scratch buffer and start the string here */
181 Buffer[127] = ANSI_NULL;
182 p = &Buffer[127];
183
184 /* Go back one character since we're doing this backwards */
185 pp--;
186
187 /* Loop the identifier we found as long as it's valid */
188 i = 0;
189 while ((i++ < 127) &&
190 (pp >= CmpBiosBegin) &&
191 (*pp >= ' ') &&
192 (*pp != '$'))
193 {
194 /* Copy the character */
195 *--p = *pp--;
196 }
197
198 /* Go past the last character since we went backwards */
199 pp++;
200
201 /* Loop the strings we recognize */
202 for (i = 0; CmpBiosStrings[i]; i++)
203 {
204 /* Check if a match was found */
205 if (strstr(p, CmpBiosStrings[i])) goto Match;
206 }
207 }
208
209 Match:
210 /* Skip until we find a space */
211 for (; *pp == ' '; pp++);
212
213 /* Loop the final string */
214 i = 0;
215 do
216 {
217 /* Copy the character into the final string */
218 BiosVersion[i] = *pp++;
219 } while ((++i < 127) &&
220 (pp <= (CmpBiosSearchEnd + 1)) &&
221 (*pp >= ' ') &&
222 (*pp != '$'));
223
224 /* Null-terminate the version string */
225 BiosVersion[i] = ANSI_NULL;
226 return TRUE;
227 }
228
229 NTSTATUS
230 NTAPI
231 CmpInitializeMachineDependentConfiguration(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
232 {
233 UNICODE_STRING KeyName, ValueName, Data, SectionName;
234 OBJECT_ATTRIBUTES ObjectAttributes;
235 ULONG HavePae, CacheSize, ViewSize, Length, TotalLength = 0, i, Disposition;
236 NTSTATUS Status;
237 HANDLE KeyHandle, BiosHandle, SystemHandle, FpuHandle, SectionHandle;
238 CONFIGURATION_COMPONENT_DATA ConfigData;
239 CHAR Buffer[128];
240 ULONG ExtendedId = 0; //, Dummy;
241 PKPRCB Prcb;
242 USHORT IndexTable[MaximumType + 1] = {0};
243 ANSI_STRING TempString;
244 PCHAR PartialString = NULL, BiosVersion;
245 CHAR CpuString[48];
246 PVOID BaseAddress = NULL;
247 LARGE_INTEGER ViewBase = {{0, 0}};
248 ULONG_PTR VideoRomBase;
249 PCHAR CurrentVersion;
250 extern UNICODE_STRING KeRosProcessorName, KeRosBiosDate, KeRosBiosVersion;
251 extern UNICODE_STRING KeRosVideoBiosDate, KeRosVideoBiosVersion;
252
253 /* Open the SMSS Memory Management key */
254 RtlInitUnicodeString(&KeyName,
255 L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\"
256 L"Control\\Session Manager\\Memory Management");
257 InitializeObjectAttributes(&ObjectAttributes,
258 &KeyName,
259 OBJ_CASE_INSENSITIVE,
260 NULL,
261 NULL);
262 Status = NtOpenKey(&KeyHandle, KEY_READ | KEY_WRITE, &ObjectAttributes);
263 if (NT_SUCCESS(Status))
264 {
265 /* Detect if PAE is enabled */
266 HavePae = SharedUserData->ProcessorFeatures[PF_PAE_ENABLED];
267
268 /* Set the value */
269 RtlInitUnicodeString(&ValueName, L"PhysicalAddressExtension");
270 NtSetValueKey(KeyHandle,
271 &ValueName,
272 0,
273 REG_DWORD,
274 &HavePae,
275 sizeof(HavePae));
276
277 /* Close the key */
278 NtClose(KeyHandle);
279 }
280
281 /* Open the hardware description key */
282 RtlInitUnicodeString(&KeyName,
283 L"\\Registry\\Machine\\Hardware\\Description\\System");
284 InitializeObjectAttributes(&ObjectAttributes,
285 &KeyName,
286 OBJ_CASE_INSENSITIVE,
287 NULL,
288 NULL);
289 Status = NtOpenKey(&SystemHandle, KEY_READ | KEY_WRITE, &ObjectAttributes);
290 if (!NT_SUCCESS(Status))
291 return Status;
292
293 /* Create the BIOS Information key */
294 RtlInitUnicodeString(&KeyName,
295 L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\"
296 L"Control\\BIOSINFO");
297 InitializeObjectAttributes(&ObjectAttributes,
298 &KeyName,
299 OBJ_CASE_INSENSITIVE,
300 NULL,
301 NULL);
302 Status = NtCreateKey(&BiosHandle,
303 KEY_ALL_ACCESS,
304 &ObjectAttributes,
305 0,
306 NULL,
307 REG_OPTION_NON_VOLATILE,
308 &Disposition);
309 if (!NT_SUCCESS(Status))
310 {
311 NtClose(SystemHandle);
312 return Status;
313 }
314
315 /* Create the CPU Key, and check if it already existed */
316 RtlInitUnicodeString(&KeyName, L"CentralProcessor");
317 InitializeObjectAttributes(&ObjectAttributes,
318 &KeyName,
319 OBJ_CASE_INSENSITIVE,
320 SystemHandle,
321 NULL);
322 Status = NtCreateKey(&KeyHandle,
323 KEY_READ | KEY_WRITE,
324 &ObjectAttributes,
325 0,
326 NULL,
327 0,
328 &Disposition);
329 NtClose(KeyHandle);
330
331 /* The key shouldn't already exist */
332 if (Disposition == REG_CREATED_NEW_KEY)
333 {
334 /* Allocate the configuration data for cmconfig.c */
335 CmpConfigurationData = ExAllocatePoolWithTag(PagedPool,
336 CmpConfigurationAreaSize,
337 TAG_CM);
338 if (!CmpConfigurationData)
339 {
340 // FIXME: Cleanup stuff!!
341 return STATUS_INSUFFICIENT_RESOURCES;
342 }
343
344 /* Loop all CPUs */
345 for (i = 0; i < KeNumberProcessors; i++)
346 {
347 /* Get the PRCB */
348 Prcb = KiProcessorBlock[i];
349
350 /* Setup the Configuration Entry for the Processor */
351 RtlZeroMemory(&ConfigData, sizeof(ConfigData));
352 ConfigData.ComponentEntry.Class = ProcessorClass;
353 ConfigData.ComponentEntry.Type = CentralProcessor;
354 ConfigData.ComponentEntry.Key = i;
355 ConfigData.ComponentEntry.AffinityMask = AFFINITY_MASK(i);
356 ConfigData.ComponentEntry.Identifier = Buffer;
357
358 /* Check if the CPU doesn't support CPUID */
359 if (!Prcb->CpuID)
360 {
361 /* Build ID1-style string for older CPUs */
362 sprintf(Buffer,
363 CmpID1,
364 Prcb->CpuType,
365 (Prcb->CpuStep >> 8) + 'A',
366 Prcb->CpuStep & 0xff);
367 }
368 else
369 {
370 /* Build ID2-style string for newer CPUs */
371 sprintf(Buffer,
372 CmpID2,
373 Prcb->CpuType,
374 (Prcb->CpuStep >> 8),
375 Prcb->CpuStep & 0xff);
376 }
377
378 /* Save the ID string length now that we've created it */
379 ConfigData.ComponentEntry.IdentifierLength = strlen(Buffer) + 1;
380
381 /* Initialize the registry configuration node for it */
382 Status = CmpInitializeRegistryNode(&ConfigData,
383 SystemHandle,
384 &KeyHandle,
385 InterfaceTypeUndefined,
386 0xFFFFFFFF,
387 IndexTable);
388 if (!NT_SUCCESS(Status))
389 {
390 NtClose(BiosHandle);
391 NtClose(SystemHandle);
392 return Status;
393 }
394
395 {
396 /* Setup the Configuration Entry for the FPU */
397 RtlZeroMemory(&ConfigData, sizeof(ConfigData));
398 ConfigData.ComponentEntry.Class = ProcessorClass;
399 ConfigData.ComponentEntry.Type = FloatingPointProcessor;
400 ConfigData.ComponentEntry.Key = i;
401 ConfigData.ComponentEntry.AffinityMask = AFFINITY_MASK(i);
402 ConfigData.ComponentEntry.Identifier = Buffer;
403
404 /* For 386 cpus, the CPU pp is the identifier */
405 if (Prcb->CpuType == 3) strcpy(Buffer, "80387");
406
407 /* Save the ID string length now that we've created it */
408 ConfigData.ComponentEntry.IdentifierLength = strlen(Buffer) + 1;
409
410 /* Initialize the registry configuration node for it */
411 Status = CmpInitializeRegistryNode(&ConfigData,
412 SystemHandle,
413 &FpuHandle,
414 InterfaceTypeUndefined,
415 0xFFFFFFFF,
416 IndexTable);
417 if (!NT_SUCCESS(Status))
418 {
419 /* We failed, close all the opened handles and return */
420 NtClose(KeyHandle);
421 NtClose(BiosHandle);
422 NtClose(SystemHandle);
423 return Status;
424 }
425
426 /* Close this new handle */
427 NtClose(FpuHandle);
428
429 /* Stay on this CPU only */
430 KeSetSystemAffinityThread(Prcb->SetMember);
431 if (!Prcb->CpuID)
432 {
433 /* Uh oh, no CPUID! */
434 }
435 else
436 {
437 /* Check if we have extended CPUID that supports name ID */
438 //Ki386Cpuid(0x80000000, &ExtendedId, &Dummy, &Dummy, &Dummy);
439 if (ExtendedId >= 0x80000004)
440 {
441 /* Do all the CPUIDs required to get the full name */
442 PartialString = CpuString;
443 for (ExtendedId = 2; ExtendedId <= 4; ExtendedId++)
444 {
445 #if 0
446 /* Do the CPUID and save the name string */
447 Ki386Cpuid(0x80000000 | ExtendedId,
448 (PULONG)PartialString,
449 (PULONG)PartialString + 1,
450 (PULONG)PartialString + 2,
451 (PULONG)PartialString + 3);
452 #endif
453
454 /* Go to the next name string */
455 PartialString += 16;
456 }
457
458 /* Null-terminate it */
459 CpuString[47] = ANSI_NULL;
460 }
461 }
462
463 /* Get the cache size while we're still localized */
464 CacheSize = 0; //((PKIPCR)KeGetPcr())->SecondLevelCacheSize;
465
466 /* Go back to user affinity */
467 KeRevertToUserAffinityThread();
468
469 /* Check if we have a CPU Name */
470 if (PartialString)
471 {
472 /* Convert it to Unicode */
473 RtlInitAnsiString(&TempString, CpuString);
474 RtlAnsiStringToUnicodeString(&Data, &TempString, TRUE);
475
476 /* Add it to the registry */
477 RtlInitUnicodeString(&ValueName, L"ProcessorNameString");
478 Status = NtSetValueKey(KeyHandle,
479 &ValueName,
480 0,
481 REG_SZ,
482 Data.Buffer,
483 Data.Length + sizeof(UNICODE_NULL));
484
485 /* ROS: Save a copy for bugzilla reporting */
486 RtlCreateUnicodeString(&KeRosProcessorName, Data.Buffer);
487
488 /* Free the temporary buffer */
489 RtlFreeUnicodeString(&Data);
490 }
491
492 /* Check if we had a Vendor ID */
493 if (Prcb->VendorString)
494 {
495 /* Convert it to Unicode */
496 RtlInitAnsiString(&TempString, Prcb->VendorString);
497 RtlAnsiStringToUnicodeString(&Data, &TempString, TRUE);
498
499 /* Add it to the registry */
500 RtlInitUnicodeString(&ValueName, L"VendorIdentifier");
501 Status = NtSetValueKey(KeyHandle,
502 &ValueName,
503 0,
504 REG_SZ,
505 Data.Buffer,
506 Data.Length + sizeof(UNICODE_NULL));
507
508 /* Free the temporary buffer */
509 RtlFreeUnicodeString(&Data);
510 }
511
512 /* Check if we have features bits */
513 if (Prcb->FeatureBits)
514 {
515 /* Add them to the registry */
516 RtlInitUnicodeString(&ValueName, L"FeatureSet");
517 Status = NtSetValueKey(KeyHandle,
518 &ValueName,
519 0,
520 REG_DWORD,
521 &Prcb->FeatureBits,
522 sizeof(Prcb->FeatureBits));
523 }
524
525 /* Check if we detected the CPU Speed */
526 if (Prcb->MHz)
527 {
528 /* Add it to the registry */
529 RtlInitUnicodeString(&ValueName, L"~MHz");
530 Status = NtSetValueKey(KeyHandle,
531 &ValueName,
532 0,
533 REG_DWORD,
534 &Prcb->MHz,
535 sizeof(Prcb->MHz));
536 }
537
538 /* Check if we have an update signature */
539 if (Prcb->UpdateSignature.QuadPart)
540 {
541 /* Add it to the registry */
542 RtlInitUnicodeString(&ValueName, L"Update Signature");
543 Status = NtSetValueKey(KeyHandle,
544 &ValueName,
545 0,
546 REG_BINARY,
547 &Prcb->UpdateSignature,
548 sizeof(Prcb->UpdateSignature));
549 }
550
551 /* Close the processor handle */
552 NtClose(KeyHandle);
553
554 /* FIXME: Detect CPU mismatches */
555 }
556 }
557
558 /* Free the configuration data */
559 ExFreePoolWithTag(CmpConfigurationData, TAG_CM);
560 }
561
562 /* Open physical memory */
563 RtlInitUnicodeString(&SectionName, L"\\Device\\PhysicalMemory");
564 InitializeObjectAttributes(&ObjectAttributes,
565 &SectionName,
566 OBJ_CASE_INSENSITIVE,
567 NULL,
568 NULL);
569 Status = ZwOpenSection(&SectionHandle,
570 SECTION_ALL_ACCESS,
571 &ObjectAttributes);
572 if (!NT_SUCCESS(Status))
573 {
574 /* We failed, close all the opened handles and return */
575 // NtClose(KeyHandle);
576 NtClose(BiosHandle);
577 NtClose(SystemHandle);
578 /* 'Quickie' closes KeyHandle */
579 goto Quickie;
580 }
581
582 /* Map the first 1KB of memory to get the IVT */
583 ViewSize = PAGE_SIZE;
584 Status = ZwMapViewOfSection(SectionHandle,
585 NtCurrentProcess(),
586 &BaseAddress,
587 0,
588 ViewSize,
589 &ViewBase,
590 &ViewSize,
591 ViewUnmap,
592 MEM_DOS_LIM,
593 PAGE_READWRITE);
594 if (!NT_SUCCESS(Status))
595 {
596 /* Assume default */
597 VideoRomBase = 0xC0000;
598 }
599 else
600 {
601 /* Calculate the base address from the vector */
602 VideoRomBase = (*((PULONG)BaseAddress + 0x10) >> 12) & 0xFFFF0;
603 VideoRomBase += *((PULONG)BaseAddress + 0x10) & 0xFFF0;
604
605 /* Now get to the actual ROM Start and make sure it's not invalid*/
606 VideoRomBase &= 0xFFFF8000;
607 if (VideoRomBase < 0xC0000) VideoRomBase = 0xC0000;
608
609 /* And unmap the section */
610 ZwUnmapViewOfSection(NtCurrentProcess(), BaseAddress);
611 }
612
613 /* Allocate BIOS Version pp Buffer */
614 BiosVersion = ExAllocatePoolWithTag(PagedPool, PAGE_SIZE, TAG_CM);
615
616 /* Setup settings to map the 64K BIOS ROM */
617 BaseAddress = 0;
618 ViewSize = 16 * PAGE_SIZE;
619 ViewBase.LowPart = 0xF0000;
620 ViewBase.HighPart = 0;
621
622 /* Map it */
623 Status = ZwMapViewOfSection(SectionHandle,
624 NtCurrentProcess(),
625 &BaseAddress,
626 0,
627 ViewSize,
628 &ViewBase,
629 &ViewSize,
630 ViewUnmap,
631 MEM_DOS_LIM,
632 PAGE_READWRITE);
633 if (NT_SUCCESS(Status))
634 {
635 /* Scan the ROM to get the BIOS Date */
636 if (CmpGetBiosDate(BaseAddress, 16 * PAGE_SIZE, Buffer, TRUE))
637 {
638 /* Convert it to Unicode */
639 RtlInitAnsiString(&TempString, Buffer);
640 RtlAnsiStringToUnicodeString(&Data, &TempString, TRUE);
641
642 /* Write the date into the registry */
643 RtlInitUnicodeString(&ValueName, L"SystemBiosDate");
644 Status = NtSetValueKey(SystemHandle,
645 &ValueName,
646 0,
647 REG_SZ,
648 Data.Buffer,
649 Data.Length + sizeof(UNICODE_NULL));
650
651 /* Free the string */
652 RtlFreeUnicodeString(&Data);
653
654 if (BiosHandle)
655 {
656 /* Get the BIOS Date Identifier */
657 RtlCopyMemory(Buffer, (PCHAR)BaseAddress + (16*PAGE_SIZE - 11), 8);
658 Buffer[8] = ANSI_NULL;
659
660 /* Convert it to unicode */
661 RtlInitAnsiString(&TempString, Buffer);
662 Status = RtlAnsiStringToUnicodeString(&Data, &TempString, TRUE);
663 if (NT_SUCCESS(Status))
664 {
665 /* Save it to the registry */
666 Status = NtSetValueKey(BiosHandle,
667 &ValueName,
668 0,
669 REG_SZ,
670 Data.Buffer,
671 Data.Length + sizeof(UNICODE_NULL));
672
673 /* ROS: Save a copy for bugzilla reporting */
674 RtlCreateUnicodeString(&KeRosBiosDate, Data.Buffer);
675
676 /* Free the string */
677 RtlFreeUnicodeString(&Data);
678 }
679
680 /* Close the bios information handle */
681 NtClose(BiosHandle);
682 }
683 }
684
685 /* Get the BIOS Version */
686 if (CmpGetBiosVersion(BaseAddress, 16* PAGE_SIZE, Buffer))
687 {
688 /* Start at the beginning of our buffer */
689 CurrentVersion = BiosVersion;
690 do
691 {
692 /* Convert to Unicode */
693 RtlInitAnsiString(&TempString, Buffer);
694 RtlAnsiStringToUnicodeString(&Data, &TempString, TRUE);
695
696 /* Calculate the length of this string and copy it in */
697 Length = Data.Length + sizeof(UNICODE_NULL);
698 RtlMoveMemory(CurrentVersion, Data.Buffer, Length);
699
700 /* Free the unicode string */
701 RtlFreeUnicodeString(&Data);
702
703 /* Update the total length and see if we're out of space */
704 TotalLength += Length;
705 if (TotalLength + 256 + sizeof(UNICODE_NULL) > PAGE_SIZE)
706 {
707 /* One more string would push us out, so stop here */
708 break;
709 }
710
711 /* Go to the next string inside the multi-string buffer */
712 CurrentVersion += Length;
713
714 /* Query the next BIOS Version */
715 } while (CmpGetBiosVersion(NULL, 0, Buffer));
716
717 /* Check if we found any strings at all */
718 if (TotalLength)
719 {
720 /* Add the final null-terminator */
721 *(PWSTR)CurrentVersion = UNICODE_NULL;
722 TotalLength += sizeof(UNICODE_NULL);
723
724 /* Write the BIOS Version to the registry */
725 RtlInitUnicodeString(&ValueName, L"SystemBiosVersion");
726 Status = NtSetValueKey(SystemHandle,
727 &ValueName,
728 0,
729 REG_MULTI_SZ,
730 BiosVersion,
731 TotalLength);
732
733 /* ROS: Save a copy for bugzilla reporting */
734 RtlCreateUnicodeString(&KeRosBiosVersion, (PWCH)BiosVersion);
735 }
736 }
737
738 /* Unmap the section */
739 ZwUnmapViewOfSection(NtCurrentProcess(), BaseAddress);
740 }
741
742 /* Now prepare for Video BIOS Mapping of 32KB */
743 BaseAddress = 0;
744 ViewSize = 8 * PAGE_SIZE;
745 ViewBase.LowPart = VideoRomBase;
746 ViewBase.HighPart = 0;
747
748 /* Map it */
749 Status = ZwMapViewOfSection(SectionHandle,
750 NtCurrentProcess(),
751 &BaseAddress,
752 0,
753 ViewSize,
754 &ViewBase,
755 &ViewSize,
756 ViewUnmap,
757 MEM_DOS_LIM,
758 PAGE_READWRITE);
759 if (NT_SUCCESS(Status))
760 {
761 /* Scan the ROM to get the BIOS Date */
762 if (CmpGetBiosDate(BaseAddress, 8 * PAGE_SIZE, Buffer, FALSE))
763 {
764 /* Convert it to Unicode */
765 RtlInitAnsiString(&TempString, Buffer);
766 RtlAnsiStringToUnicodeString(&Data, &TempString, TRUE);
767
768 /* Write the date into the registry */
769 RtlInitUnicodeString(&ValueName, L"VideoBiosDate");
770 Status = NtSetValueKey(SystemHandle,
771 &ValueName,
772 0,
773 REG_SZ,
774 Data.Buffer,
775 Data.Length + sizeof(UNICODE_NULL));
776
777 /* ROS: Save a copy for bugzilla reporting */
778 RtlCreateUnicodeString(&KeRosVideoBiosDate, Data.Buffer);
779
780 /* Free the string */
781 RtlFreeUnicodeString(&Data);
782 }
783
784 /* Get the Video BIOS Version */
785 if (CmpGetBiosVersion(BaseAddress, 8* PAGE_SIZE, Buffer))
786 {
787 /* Start at the beginning of our buffer */
788 CurrentVersion = BiosVersion;
789 do
790 {
791 /* Convert to Unicode */
792 RtlInitAnsiString(&TempString, Buffer);
793 RtlAnsiStringToUnicodeString(&Data, &TempString, TRUE);
794
795 /* Calculate the length of this string and copy it in */
796 Length = Data.Length + sizeof(UNICODE_NULL);
797 RtlMoveMemory(CurrentVersion, Data.Buffer, Length);
798
799 /* Free the unicode string */
800 RtlFreeUnicodeString(&Data);
801
802 /* Update the total length and see if we're out of space */
803 TotalLength += Length;
804 if (TotalLength + 256 + sizeof(UNICODE_NULL) > PAGE_SIZE)
805 {
806 /* One more string would push us out, so stop here */
807 break;
808 }
809
810 /* Go to the next string inside the multi-string buffer */
811 CurrentVersion += Length;
812
813 /* Query the next BIOS Version */
814 } while (CmpGetBiosVersion(NULL, 0, Buffer));
815
816 /* Check if we found any strings at all */
817 if (TotalLength)
818 {
819 /* Add the final null-terminator */
820 *(PWSTR)CurrentVersion = UNICODE_NULL;
821 TotalLength += sizeof(UNICODE_NULL);
822
823 /* Write the BIOS Version to the registry */
824 RtlInitUnicodeString(&ValueName, L"VideoBiosVersion");
825 Status = NtSetValueKey(SystemHandle,
826 &ValueName,
827 0,
828 REG_MULTI_SZ,
829 BiosVersion,
830 TotalLength);
831
832 /* ROS: Save a copy for bugzilla reporting */
833 RtlCreateUnicodeString(&KeRosVideoBiosVersion, (PWCH)BiosVersion);
834 }
835 }
836
837 /* Unmap the section */
838 ZwUnmapViewOfSection(NtCurrentProcess(), BaseAddress);
839 }
840
841 /* Close the section */
842 ZwClose(SectionHandle);
843
844 /* Free the BIOS version string buffer */
845 if (BiosVersion) ExFreePoolWithTag(BiosVersion, TAG_CM);
846
847 Quickie:
848 /* Close the processor handle */
849 NtClose(KeyHandle);
850 return STATUS_SUCCESS;
851 }