Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1262 lines
39 KiB

  1. /*++
  2. Copyright (c) 1990, 1991 Microsoft Corporation
  3. Module Name:
  4. init386.c
  5. Abstract:
  6. This module is responsible to build any x86 specific entries in
  7. the hardware tree of registry.
  8. Author:
  9. Ken Reneris (kenr) 04-Aug-1992
  10. Environment:
  11. Kernel mode.
  12. Revision History:
  13. shielint - add BIOS date and version detection.
  14. --*/
  15. #include "cmp.h"
  16. #include "stdio.h"
  17. #include "smbios.h"
  18. //
  19. // Title Index is set to 0.
  20. // (from ..\cmconfig.c)
  21. //
  22. #define TITLE_INDEX_VALUE 0
  23. extern PCHAR SearchStrings[];
  24. extern PCHAR BiosBegin;
  25. extern PCHAR Start;
  26. extern PCHAR End;
  27. extern UCHAR CmpID[];
  28. extern WCHAR CmpVendorID[];
  29. extern WCHAR CmpProcessorNameString[];
  30. extern WCHAR CmpFeatureBits[];
  31. extern WCHAR CmpMHz[];
  32. extern WCHAR CmpUpdateSignature[];
  33. extern UCHAR CmpIntelID[];
  34. extern UCHAR CmpItanium[];
  35. extern UCHAR CmpMcKinley[];
  36. extern UCHAR CmpIA64Proc[];
  37. //
  38. // Bios date and version definitions
  39. //
  40. #define BIOS_DATE_LENGTH 64
  41. #define MAXIMUM_BIOS_VERSION_LENGTH 128
  42. WCHAR SystemBIOSDateString[BIOS_DATE_LENGTH];
  43. WCHAR SystemBIOSVersionString[MAXIMUM_BIOS_VERSION_LENGTH];
  44. WCHAR VideoBIOSDateString[BIOS_DATE_LENGTH];
  45. WCHAR VideoBIOSVersionString[MAXIMUM_BIOS_VERSION_LENGTH];
  46. //
  47. // Extended CPUID function definitions
  48. //
  49. #define CPUID_PROCESSOR_NAME_STRING_SZ 65
  50. #define CPUID_EXTFN_BASE 0x80000000
  51. #define CPUID_EXTFN_PROCESSOR_NAME 0x80000002
  52. extern ULONG CmpConfigurationAreaSize;
  53. extern PCM_FULL_RESOURCE_DESCRIPTOR CmpConfigurationData;
  54. BOOLEAN
  55. CmpGetBiosVersion (
  56. PCHAR SearchArea,
  57. ULONG SearchLength,
  58. PCHAR VersionString
  59. );
  60. BOOLEAN
  61. CmpGetBiosDate (
  62. PCHAR SearchArea,
  63. ULONG SearchLength,
  64. PCHAR DateString
  65. );
  66. ULONG
  67. Ke386CyrixId (
  68. VOID
  69. );
  70. VOID
  71. InitializeProcessorInformationFromSMBIOS(
  72. IN PLOADER_PARAMETER_BLOCK LoaderBlock
  73. );
  74. #ifdef ALLOC_PRAGMA
  75. #pragma alloc_text(INIT,CmpInitializeMachineDependentConfiguration)
  76. #pragma alloc_text(INIT,InitializeProcessorInformationFromSMBIOS)
  77. #endif
  78. #if 0
  79. //
  80. // Use SMBIOS to gather this information.
  81. //
  82. BOOLEAN
  83. CmpGetBiosDate (
  84. PCHAR SearchArea,
  85. ULONG SearchLength,
  86. PCHAR DateString
  87. )
  88. /*++
  89. Routine Description:
  90. This routine finds the most recent date in the computer/video
  91. card's ROM. When GetRomDate encounters a datae, it checks the
  92. previously found date to see if the new date is more recent.
  93. Arguments:
  94. SearchArea - the area to search for a date.
  95. SearchLength - Length of search.
  96. DateString - Supplies a pointer to a fixed length memory to receive
  97. the date string.
  98. Return Value:
  99. NT_SUCCESS if a date is found.
  100. --*/
  101. {
  102. BOOLEAN FoundFlag = TRUE; // Set to TRUE if the item was found
  103. CHAR PrevDate[BIOS_DATE_LENGTH]; // Date currently being examined
  104. CHAR CurrDate[BIOS_DATE_LENGTH]; // Date currently being examined
  105. PCHAR String;
  106. USHORT i; // Looping variable
  107. USHORT Length; // Number of characters to move
  108. PCHAR Start = SearchArea + 2;
  109. PCHAR End = SearchArea + SearchLength - 5;
  110. //
  111. // Clear out the previous date
  112. //
  113. RtlZeroMemory(PrevDate, BIOS_DATE_LENGTH);
  114. while (FoundFlag) {
  115. String = NULL;
  116. //
  117. // Search for '/' with a digit on either side and another
  118. // '/' 3 character away.
  119. //
  120. while (Start < End) {
  121. if (*Start == '/' && *(Start+3) == '/' &&
  122. (*(Start+1) <= '9' && *(Start+1) >= '0') &&
  123. (*(Start-1) <= '9' && *(Start-1) >= '0') &&
  124. (*(Start+5) <= '9' && *(Start+5) >= '0') &&
  125. (*(Start+4) <= '9' && *(Start+4) >= '0') &&
  126. (*(Start+2) <= '9' && *(Start+2) >= '0')) {
  127. String = Start;
  128. break;
  129. } else {
  130. Start++;
  131. }
  132. }
  133. if (String) {
  134. Start = String + 3;
  135. String -= 2; // Move String to the beginning of
  136. // date.
  137. //
  138. // Copy the year into CurrDate
  139. //
  140. CurrDate[0] = String[6];
  141. CurrDate[1] = String[7];
  142. CurrDate[2] = '/'; // The 1st "/" for YY/MM/DD
  143. //
  144. // Copy the month & day into CurrDate
  145. // (Process properly if this is a one digit month)
  146. //
  147. if (*String > '9' || *String < '0') {
  148. CurrDate[3] = '0';
  149. String++;
  150. i = 4;
  151. Length = 4;
  152. } else {
  153. i = 3;
  154. Length = 5;
  155. }
  156. RtlMoveMemory(&CurrDate[i], String, Length);
  157. //
  158. // Compare the dates, to see which is more recent
  159. //
  160. if (memcmp (PrevDate, CurrDate, BIOS_DATE_LENGTH - 1) < 0) {
  161. RtlMoveMemory(PrevDate, CurrDate, BIOS_DATE_LENGTH - 1);
  162. }
  163. } else {
  164. FoundFlag = FALSE;
  165. }
  166. }
  167. //
  168. // If we did not find a date
  169. //
  170. if (PrevDate[0] == '\0') {
  171. DateString[0] = '\0';
  172. return (FALSE);
  173. }
  174. //
  175. // Put the date from chPrevDate's YY/MM/DD format
  176. // into pchDateString's MM/DD/YY format
  177. DateString[5] = '/';
  178. DateString[6] = PrevDate[0];
  179. DateString[7] = PrevDate[1];
  180. RtlMoveMemory(DateString, &PrevDate[3], 5);
  181. DateString[8] = '\0';
  182. return (TRUE);
  183. }
  184. BOOLEAN
  185. CmpGetBiosVersion (
  186. PCHAR SearchArea,
  187. ULONG SearchLength,
  188. PCHAR VersionString
  189. )
  190. /*++
  191. Routine Description:
  192. This routine finds the version number stored in ROM, if any.
  193. Arguments:
  194. SearchArea - the area to search for the version.
  195. SearchLength - Length of search
  196. VersionString - Supplies a pointer to a fixed length memory to receive
  197. the version string.
  198. Return Value:
  199. TRUE if a version number is found. Else a value of FALSE is returned.
  200. --*/
  201. {
  202. PCHAR String;
  203. USHORT Length;
  204. USHORT i;
  205. CHAR Buffer[MAXIMUM_BIOS_VERSION_LENGTH];
  206. PCHAR BufferPointer;
  207. if (SearchArea != NULL) {
  208. //
  209. // If caller does not specify the search area, we will search
  210. // the area left from previous search.
  211. //
  212. BiosBegin = SearchArea;
  213. Start = SearchArea + 1;
  214. End = SearchArea + SearchLength - 2;
  215. }
  216. while (1) {
  217. //
  218. // Search for a period with a digit on either side
  219. //
  220. String = NULL;
  221. while (Start <= End) {
  222. if (*Start == '.' && *(Start+1) >= '0' && *(Start+1) <= '9' &&
  223. *(Start-1) >= '0' && *(Start-1) <= '9') {
  224. String = Start;
  225. break;
  226. } else {
  227. Start++;
  228. }
  229. }
  230. if (Start > End) {
  231. return(FALSE);
  232. } else {
  233. Start += 2;
  234. }
  235. Length = 0;
  236. Buffer[MAXIMUM_BIOS_VERSION_LENGTH - 1] = '\0';
  237. BufferPointer = &Buffer[MAXIMUM_BIOS_VERSION_LENGTH - 1];
  238. //
  239. // Search for the beginning of the string
  240. //
  241. String--;
  242. while (Length < MAXIMUM_BIOS_VERSION_LENGTH - 8 &&
  243. String >= BiosBegin &&
  244. *String >= ' ' && *String <= 127 &&
  245. *String != '$') {
  246. --BufferPointer;
  247. *BufferPointer = *String;
  248. --String, ++Length;
  249. }
  250. ++String;
  251. //
  252. // Can one of the search strings be found
  253. //
  254. for (i = 0; SearchStrings[i]; i++) {
  255. if (strstr(BufferPointer, SearchStrings[i])) {
  256. goto Found;
  257. }
  258. }
  259. }
  260. Found:
  261. //
  262. // Skip leading white space
  263. //
  264. for (; *String == ' '; ++String)
  265. ;
  266. //
  267. // Copy the string to user supplied buffer
  268. //
  269. for (i = 0; i < MAXIMUM_BIOS_VERSION_LENGTH - 1 &&
  270. String <= (End + 1) &&
  271. *String >= ' ' && *String <= 127 && *String != '$';
  272. ++i, ++String) {
  273. VersionString[i] = *String;
  274. }
  275. VersionString[i] = '\0';
  276. return (TRUE);
  277. }
  278. #endif // #if 0
  279. NTSTATUS
  280. CmpInitializeMachineDependentConfiguration(
  281. IN PLOADER_PARAMETER_BLOCK LoaderBlock
  282. )
  283. /*++
  284. Routine Description:
  285. This routine creates IA64 specific entries in the registry.
  286. Arguments:
  287. LoaderBlock - supplies a pointer to the LoaderBlock passed in from the
  288. OS Loader.
  289. Returns:
  290. NTSTATUS code for sucess or reason of failure.
  291. --*/
  292. {
  293. NTSTATUS Status;
  294. ULONG VideoBiosStart;
  295. UNICODE_STRING KeyName;
  296. UNICODE_STRING ValueName;
  297. UNICODE_STRING ValueData;
  298. ANSI_STRING AnsiString;
  299. OBJECT_ATTRIBUTES ObjectAttributes;
  300. ULONG Disposition;
  301. HANDLE ParentHandle;
  302. HANDLE BaseHandle, NpxHandle;
  303. HANDLE CurrentControlSet;
  304. CONFIGURATION_COMPONENT_DATA CurrentEntry;
  305. PUCHAR VendorID;
  306. UCHAR Buffer[MAXIMUM_BIOS_VERSION_LENGTH];
  307. PKPRCB Prcb;
  308. ULONG i, Junk;
  309. ULONG VersionsLength = 0, Length;
  310. PCHAR VersionStrings, VersionPointer;
  311. UNICODE_STRING SectionName;
  312. ULONG ViewSize;
  313. LARGE_INTEGER ViewBase;
  314. PVOID BaseAddress;
  315. USHORT DeviceIndexTable[NUMBER_TYPES];
  316. ULONG CpuIdFunction;
  317. ULONG MaxExtFn;
  318. PULONG NameString = NULL;
  319. ULONG ReturnedLength;
  320. struct {
  321. union {
  322. UCHAR Bytes[CPUID_PROCESSOR_NAME_STRING_SZ];
  323. ULONG DWords[1];
  324. } u;
  325. } ProcessorNameString;
  326. for (i = 0; i < NUMBER_TYPES; i++) {
  327. DeviceIndexTable[i] = 0;
  328. }
  329. //
  330. // Go get a bunch of information out of SMBIOS
  331. //
  332. InitializeProcessorInformationFromSMBIOS(LoaderBlock);
  333. InitializeObjectAttributes( &ObjectAttributes,
  334. &CmRegistryMachineHardwareDescriptionSystemName,
  335. OBJ_CASE_INSENSITIVE,
  336. NULL,
  337. NULL
  338. );
  339. Status = NtOpenKey( &ParentHandle,
  340. KEY_READ,
  341. &ObjectAttributes
  342. );
  343. if (!NT_SUCCESS(Status)) {
  344. // Something is really wrong...
  345. return Status;
  346. }
  347. //
  348. // On an ARC machine the processor(s) are included in the hardware
  349. // configuration passed in from bootup. Since there's no standard
  350. // way to get all the ARC information for each processor in an MP
  351. // machine via pc-ROMs the information will be added here (if it's
  352. // not already present).
  353. //
  354. RtlInitUnicodeString( &KeyName,
  355. L"CentralProcessor"
  356. );
  357. InitializeObjectAttributes(
  358. &ObjectAttributes,
  359. &KeyName,
  360. 0,
  361. ParentHandle,
  362. NULL
  363. );
  364. ObjectAttributes.Attributes |= OBJ_CASE_INSENSITIVE;
  365. Status = NtCreateKey(
  366. &BaseHandle,
  367. KEY_READ | KEY_WRITE,
  368. &ObjectAttributes,
  369. TITLE_INDEX_VALUE,
  370. &CmClassName[ProcessorClass],
  371. 0,
  372. &Disposition
  373. );
  374. NtClose (BaseHandle);
  375. if (Disposition == REG_CREATED_NEW_KEY) {
  376. //
  377. // The ARC rom didn't add the processor(s) into the registry.
  378. // Do it now.
  379. //
  380. CmpConfigurationData = (PCM_FULL_RESOURCE_DESCRIPTOR)ExAllocatePool(
  381. PagedPool,
  382. CmpConfigurationAreaSize
  383. );
  384. if (CmpConfigurationData == NULL) {
  385. // bail out
  386. NtClose (ParentHandle);
  387. return(STATUS_INSUFFICIENT_RESOURCES);
  388. }
  389. for (i=0; i < (ULONG)KeNumberProcessors; i++) {
  390. Prcb = KiProcessorBlock[i];
  391. RtlZeroMemory (&CurrentEntry, sizeof CurrentEntry);
  392. CurrentEntry.ComponentEntry.Class = ProcessorClass;
  393. CurrentEntry.ComponentEntry.Type = CentralProcessor;
  394. CurrentEntry.ComponentEntry.Key = i;
  395. CurrentEntry.ComponentEntry.AffinityMask = AFFINITY_MASK(i);
  396. CurrentEntry.ComponentEntry.Identifier = Buffer;
  397. sprintf( Buffer, CmpID,
  398. Prcb->ProcessorFamily,
  399. Prcb->ProcessorModel,
  400. Prcb->ProcessorRevision
  401. );
  402. CurrentEntry.ComponentEntry.IdentifierLength =
  403. strlen (Buffer) + 1;
  404. Status = CmpInitializeRegistryNode(
  405. &CurrentEntry,
  406. ParentHandle,
  407. &BaseHandle,
  408. -1,
  409. (ULONG)-1,
  410. DeviceIndexTable
  411. );
  412. if (!NT_SUCCESS(Status)) {
  413. return(Status);
  414. }
  415. VendorID = Prcb->ProcessorVendorString;
  416. if ( *VendorID == '\0' ) {
  417. VendorID = NULL;
  418. }
  419. if (VendorID) {
  420. //
  421. // Add Vendor Indentifier to the registry
  422. //
  423. RtlInitUnicodeString(
  424. &ValueName,
  425. CmpVendorID
  426. );
  427. RtlInitAnsiString(
  428. &AnsiString,
  429. VendorID
  430. );
  431. RtlAnsiStringToUnicodeString(
  432. &ValueData,
  433. &AnsiString,
  434. TRUE
  435. );
  436. Status = NtSetValueKey(
  437. BaseHandle,
  438. &ValueName,
  439. TITLE_INDEX_VALUE,
  440. REG_SZ,
  441. ValueData.Buffer,
  442. ValueData.Length + sizeof( UNICODE_NULL )
  443. );
  444. RtlFreeUnicodeString(&ValueData);
  445. }
  446. if ( VendorID && !strcmp( VendorID, CmpIntelID ) ) {
  447. ULONG processorModel;
  448. PUCHAR processorNameString = CmpItanium;
  449. //
  450. // Add Processor Name String to the registry
  451. //
  452. RtlInitUnicodeString(
  453. &ValueName,
  454. CmpProcessorNameString
  455. );
  456. //
  457. // ISSUE-2000/02/10-v-thief - Pseudo cases to be updated when known.
  458. //
  459. processorModel = Prcb->ProcessorModel;
  460. switch( processorModel ) {
  461. case 1: // Pseudo-Itanium:
  462. break;
  463. case 2: // Pseudo-McKinley:
  464. processorNameString = CmpMcKinley;
  465. break;
  466. default:
  467. processorNameString = CmpIA64Proc;
  468. break;
  469. }
  470. RtlInitAnsiString(
  471. &AnsiString,
  472. processorNameString
  473. );
  474. RtlAnsiStringToUnicodeString(
  475. &ValueData,
  476. &AnsiString,
  477. TRUE
  478. );
  479. Status = NtSetValueKey(
  480. BaseHandle,
  481. &ValueName,
  482. TITLE_INDEX_VALUE,
  483. REG_SZ,
  484. ValueData.Buffer,
  485. ValueData.Length + sizeof( UNICODE_NULL )
  486. );
  487. RtlFreeUnicodeString(&ValueData);
  488. }
  489. //
  490. // If more processor IDs have to be restored or initialized,
  491. // check non-IA64 implementations of this function.
  492. //
  493. if ( Prcb->ProcessorFeatureBits ) {
  494. //
  495. // Add processor feature bits to the registry
  496. //
  497. RtlInitUnicodeString(
  498. &ValueName,
  499. CmpFeatureBits
  500. );
  501. Status = NtSetValueKey(
  502. BaseHandle,
  503. &ValueName,
  504. TITLE_INDEX_VALUE,
  505. REG_QWORD,
  506. &Prcb->ProcessorFeatureBits,
  507. sizeof( Prcb->ProcessorFeatureBits )
  508. );
  509. }
  510. if (Prcb->MHz) {
  511. //
  512. // Add processor MHz to the registry
  513. //
  514. RtlInitUnicodeString(
  515. &ValueName,
  516. CmpMHz
  517. );
  518. Status = NtSetValueKey(
  519. BaseHandle,
  520. &ValueName,
  521. TITLE_INDEX_VALUE,
  522. REG_DWORD,
  523. &Prcb->MHz,
  524. sizeof (Prcb->MHz)
  525. );
  526. }
  527. #if 0
  528. //
  529. // ISSUE-2000/02/01-v-thief
  530. //
  531. if ( Prcb->ProcessorUpdateSignature ) {
  532. //
  533. // Add processor Update Signature to the registry
  534. //
  535. RtlInitUnicodeString(
  536. &ValueName,
  537. CmpUpdateSignature
  538. );
  539. Status = NtSetValueKey(
  540. BaseHandle,
  541. &ValueName,
  542. TITLE_INDEX_VALUE,
  543. REG_BINARY,
  544. &Prcb->ProcessorUpdateSignature,
  545. sizeof( Prcb->ProcessorUpdateSignature )
  546. );
  547. }
  548. #endif // 0
  549. //
  550. // Add ia32 floating point enties for iVE.
  551. //
  552. RtlZeroMemory (&CurrentEntry, sizeof CurrentEntry);
  553. CurrentEntry.ComponentEntry.Class = ProcessorClass;
  554. CurrentEntry.ComponentEntry.Type = FloatingPointProcessor;
  555. CurrentEntry.ComponentEntry.Key = i;
  556. CurrentEntry.ComponentEntry.AffinityMask = AFFINITY_MASK(i);
  557. CurrentEntry.ComponentEntry.Identifier = Buffer;
  558. //
  559. // The iVE is defined to look like the Pentium III FP
  560. // This is the value returned by the ia32 CPUID instruction
  561. // on Merced (Itanium)
  562. //
  563. strcpy (Buffer, "x86 Family 7 Model 0 Stepping 0");
  564. CurrentEntry.ComponentEntry.IdentifierLength =
  565. strlen (Buffer) + 1;
  566. Status = CmpInitializeRegistryNode(
  567. &CurrentEntry,
  568. ParentHandle,
  569. &NpxHandle,
  570. -1,
  571. (ULONG)-1,
  572. DeviceIndexTable
  573. );
  574. //
  575. // How odd. Some calls check the status return value
  576. // and others don't. Is this based on required vs. optional
  577. // keys? For the moment, since it was checked on the i386
  578. // then do the check here too...
  579. //
  580. if (!NT_SUCCESS(Status)) {
  581. NtClose(BaseHandle);
  582. return(Status);
  583. }
  584. //
  585. // Only need to close the handle if we succeeded
  586. //
  587. NtClose(NpxHandle);
  588. NtClose(BaseHandle);
  589. }
  590. ExFreePool((PVOID)CmpConfigurationData);
  591. }
  592. //
  593. // Next we try to collect System BIOS date and version strings.
  594. //
  595. if( SystemBIOSDateString[0] != 0 ) {
  596. RtlInitUnicodeString(
  597. &ValueName,
  598. L"SystemBiosDate"
  599. );
  600. Status = NtSetValueKey(
  601. ParentHandle,
  602. &ValueName,
  603. TITLE_INDEX_VALUE,
  604. REG_SZ,
  605. SystemBIOSDateString,
  606. (wcslen(SystemBIOSDateString)+1) * sizeof( WCHAR )
  607. );
  608. }
  609. if( SystemBIOSVersionString[0] != 0 ) {
  610. RtlInitUnicodeString(
  611. &ValueName,
  612. L"SystemBiosVersion"
  613. );
  614. Status = NtSetValueKey(
  615. ParentHandle,
  616. &ValueName,
  617. TITLE_INDEX_VALUE,
  618. REG_SZ,
  619. SystemBIOSVersionString,
  620. (wcslen(SystemBIOSVersionString)+1) * sizeof( WCHAR )
  621. );
  622. }
  623. //
  624. // Next we try to collect Video BIOS date and version strings.
  625. //
  626. if( VideoBIOSDateString[0] != 0 ) {
  627. RtlInitUnicodeString(
  628. &ValueName,
  629. L"VideoBiosDate"
  630. );
  631. Status = NtSetValueKey(
  632. ParentHandle,
  633. &ValueName,
  634. TITLE_INDEX_VALUE,
  635. REG_SZ,
  636. VideoBIOSDateString,
  637. (wcslen(VideoBIOSDateString)+1) * sizeof( WCHAR )
  638. );
  639. }
  640. if( VideoBIOSVersionString[0] != 0 ) {
  641. RtlInitUnicodeString(
  642. &ValueName,
  643. L"VideoBiosVersion"
  644. );
  645. Status = NtSetValueKey(
  646. ParentHandle,
  647. &ValueName,
  648. TITLE_INDEX_VALUE,
  649. REG_SZ,
  650. VideoBIOSVersionString,
  651. (wcslen(VideoBIOSVersionString)+1) * sizeof( WCHAR )
  652. );
  653. }
  654. NtClose (ParentHandle);
  655. //
  656. // Add any other x86 specific code here...
  657. //
  658. return STATUS_SUCCESS;
  659. }
  660. VOID
  661. InitializeProcessorInformationFromSMBIOS(
  662. IN PLOADER_PARAMETER_BLOCK LoaderBlock
  663. )
  664. /*++
  665. Routine Description:
  666. This function attempts to load processor-specific information
  667. out of the SMBIOS table. If present, that information will be
  668. used to initialize specific global variables.
  669. Arguments:
  670. LoaderBlock : Pointer to the loaderblock as sent in from the loader.
  671. Return Value:
  672. NONE.
  673. --*/
  674. {
  675. PLOADER_PARAMETER_EXTENSION LoaderExtension;
  676. NTSTATUS Status = STATUS_SUCCESS;
  677. PSMBIOS_EPS_HEADER SMBiosEPSHeader;
  678. PDMIBIOS_EPS_HEADER DMIBiosEPSHeader;
  679. BOOLEAN Found = FALSE;
  680. PHYSICAL_ADDRESS SMBiosTablePhysicalAddress = {0};
  681. PUCHAR StartPtr = NULL;
  682. PUCHAR EndPtr = NULL;
  683. PUCHAR SMBiosDataVirtualAddress = NULL;
  684. PSMBIOS_STRUCT_HEADER Header = NULL;
  685. ULONG i = 0;
  686. PKPRCB Prcb;
  687. UCHAR Checksum;
  688. PAGED_CODE();
  689. LoaderExtension = LoaderBlock->Extension;
  690. if (LoaderExtension->Size >= sizeof(LOADER_PARAMETER_EXTENSION)) {
  691. if (LoaderExtension->SMBiosEPSHeader != NULL) {
  692. //
  693. // Load the SMBIOS table address and checksum it just to make sure.
  694. //
  695. SMBiosEPSHeader = (PSMBIOS_EPS_HEADER)LoaderExtension->SMBiosEPSHeader;
  696. DMIBiosEPSHeader = (PDMIBIOS_EPS_HEADER)&SMBiosEPSHeader->Signature2[0];
  697. SMBiosTablePhysicalAddress.HighPart = 0;
  698. SMBiosTablePhysicalAddress.LowPart = DMIBiosEPSHeader->StructureTableAddress;
  699. StartPtr = (PUCHAR)SMBiosEPSHeader;
  700. Checksum = 0;
  701. for( i = 0; i < SMBiosEPSHeader->Length; i++ ) {
  702. Checksum += StartPtr[i];
  703. }
  704. if( Checksum != 0 ) {
  705. CmKdPrintEx((DPFLTR_CONFIG_ID,DPFLTR_TRACE_LEVEL,"InitializeProcessorInformationFromSMBIOS: _SM_ table has an incorrect checksum.\n"));
  706. return;
  707. }
  708. //
  709. // Map the table into a virtual address and search it.
  710. //
  711. SMBiosDataVirtualAddress = MmMapIoSpace( SMBiosTablePhysicalAddress,
  712. DMIBiosEPSHeader->StructureTableLength,
  713. MmCached );
  714. if( SMBiosDataVirtualAddress != NULL ) {
  715. //
  716. // Search...
  717. //
  718. StartPtr = SMBiosDataVirtualAddress;
  719. EndPtr = StartPtr + DMIBiosEPSHeader->StructureTableLength;
  720. Found = FALSE;
  721. while( (StartPtr < EndPtr) ) {
  722. Header = (PSMBIOS_STRUCT_HEADER)StartPtr;
  723. if( Header->Type == SMBIOS_BIOS_INFORMATION_TYPE ) {
  724. PSMBIOS_BIOS_INFORMATION_STRUCT InfoHeader = (PSMBIOS_BIOS_INFORMATION_STRUCT)StartPtr;
  725. PUCHAR StringPtr = NULL;
  726. KdPrintEx((DPFLTR_SYSTEM_ID, DPFLTR_INFO_LEVEL,"InitializeProcessorInformationFromSMBIOS: SMBIOS_BIOS_INFORMATION\n"));
  727. //
  728. // Load the System BIOS Version information.
  729. //
  730. // Now jump to the BiosInfoHeader->BIOSVersion-th string which
  731. // is appended onto the end of the formatted section of the table.
  732. KdPrintEx((DPFLTR_SYSTEM_ID, DPFLTR_INFO_LEVEL," I think the version string is at offset: %d\n", (ULONG)InfoHeader->Version));
  733. if( (ULONG)InfoHeader->Version > 0 ) {
  734. // Jump to the end of the formatted portion of the SMBIOS table.
  735. StringPtr = StartPtr + Header->Length;
  736. // Jump over some number of strings to get to our string.
  737. for( i = 0; i < ((ULONG)InfoHeader->Version-1); i++ ) {
  738. while( (*StringPtr != 0) && (StringPtr < EndPtr) ) {
  739. StringPtr++;
  740. }
  741. StringPtr++;
  742. }
  743. // StringPtr should be sitting at the BIOSVersion string. Convert him to
  744. // Unicode and save it off.
  745. if( StringPtr < EndPtr ) {
  746. UNICODE_STRING UnicodeString;
  747. ANSI_STRING AnsiString;
  748. KdPrintEx((DPFLTR_SYSTEM_ID, DPFLTR_INFO_LEVEL," I'm about to load the Version string %s\n", StringPtr));
  749. UnicodeString.Buffer = SystemBIOSVersionString;
  750. UnicodeString.MaximumLength = MAXIMUM_BIOS_VERSION_LENGTH;
  751. RtlInitAnsiString(
  752. &AnsiString,
  753. StringPtr
  754. );
  755. RtlAnsiStringToUnicodeString(
  756. &UnicodeString,
  757. &AnsiString,
  758. FALSE
  759. );
  760. }
  761. }
  762. //
  763. // Load the System BIOS Date information
  764. //
  765. // Now jump to the BiosInfoHeader->BIOSDate-th string which
  766. // is appended onto the end of the formatted section of the table.
  767. KdPrintEx((DPFLTR_SYSTEM_ID, DPFLTR_INFO_LEVEL," I think the ReleaseDate string is at offset: %d\n", (ULONG)InfoHeader->ReleaseDate));
  768. if( (ULONG)InfoHeader->ReleaseDate > 0 ) {
  769. // Jump to the end of the formatted portion of the SMBIOS table.
  770. StringPtr = StartPtr + Header->Length;
  771. // Jump over some number of strings to get to our string.
  772. for( i = 0; i < ((ULONG)InfoHeader->ReleaseDate-1); i++ ) {
  773. while( (*StringPtr != 0) && (StringPtr < EndPtr) ) {
  774. StringPtr++;
  775. }
  776. StringPtr++;
  777. }
  778. // StringPtr should be sitting at the BIOSDate string. Convert him to
  779. // Unicode and save it off.
  780. if( StringPtr < EndPtr ) {
  781. UNICODE_STRING UnicodeString;
  782. ANSI_STRING AnsiString;
  783. KdPrintEx((DPFLTR_SYSTEM_ID, DPFLTR_INFO_LEVEL," I'm about to load the Date string %s\n", StringPtr));
  784. UnicodeString.Buffer = SystemBIOSDateString;
  785. UnicodeString.MaximumLength = BIOS_DATE_LENGTH;
  786. RtlInitAnsiString(
  787. &AnsiString,
  788. StringPtr
  789. );
  790. RtlAnsiStringToUnicodeString(
  791. &UnicodeString,
  792. &AnsiString,
  793. FALSE
  794. );
  795. }
  796. }
  797. } else if( Header->Type == SMBIOS_BASE_BOARD_INFORMATION_TYPE ) {
  798. PSMBIOS_BASE_BOARD_INFORMATION_STRUCT InfoHeader = (PSMBIOS_BASE_BOARD_INFORMATION_STRUCT)StartPtr;
  799. PUCHAR StringPtr = NULL;
  800. KdPrintEx((DPFLTR_SYSTEM_ID, DPFLTR_INFO_LEVEL,"InitializeProcessorInformationFromSMBIOS: SMBIOS_BASE_BOARD_INFORMATION\n"));
  801. #if 0
  802. //
  803. // We aren't using any of this information right now.
  804. // -matth 4/2001
  805. //
  806. // Manufacturer
  807. KdPrintEx((DPFLTR_SYSTEM_ID, DPFLTR_INFO_LEVEL," I think the Manufacturer string is at offset: %d\n", (ULONG)InfoHeader->Manufacturer));
  808. if( (ULONG)InfoHeader->Manufacturer > 0 ) {
  809. // Jump to the end of the formatted portion of the SMBIOS table.
  810. StringPtr = StartPtr + Header->Length;
  811. // Jump over some number of strings to get to our string.
  812. for( i = 0; i < ((ULONG)InfoHeader->Manufacturer-1); i++ ) {
  813. while( (*StringPtr != 0) && (StringPtr < EndPtr) ) {
  814. StringPtr++;
  815. }
  816. StringPtr++;
  817. }
  818. KdPrintEx((DPFLTR_SYSTEM_ID, DPFLTR_INFO_LEVEL," Manufacturer: %s\n", StringPtr));
  819. }
  820. // Product
  821. KdPrintEx((DPFLTR_SYSTEM_ID, DPFLTR_INFO_LEVEL," I think the Product string is at offset: %d\n", (ULONG)InfoHeader->Product));
  822. if( (ULONG)InfoHeader->Product > 0 ) {
  823. // Jump to the end of the formatted portion of the SMBIOS table.
  824. StringPtr = StartPtr + Header->Length;
  825. // Jump over some number of strings to get to our string.
  826. for( i = 0; i < ((ULONG)InfoHeader->Product-1); i++ ) {
  827. while( (*StringPtr != 0) && (StringPtr < EndPtr) ) {
  828. StringPtr++;
  829. }
  830. StringPtr++;
  831. }
  832. KdPrintEx((DPFLTR_SYSTEM_ID, DPFLTR_INFO_LEVEL," Product: %s\n", StringPtr));
  833. }
  834. // Version
  835. KdPrintEx((DPFLTR_SYSTEM_ID, DPFLTR_INFO_LEVEL," I think the Version string is at offset: %d\n", (ULONG)InfoHeader->Version));
  836. if( (ULONG)InfoHeader->Version > 0 ) {
  837. // Jump to the end of the formatted portion of the SMBIOS table.
  838. StringPtr = StartPtr + Header->Length;
  839. // Jump over some number of strings to get to our string.
  840. for( i = 0; i < ((ULONG)InfoHeader->Version-1); i++ ) {
  841. while( (*StringPtr != 0) && (StringPtr < EndPtr) ) {
  842. StringPtr++;
  843. }
  844. StringPtr++;
  845. }
  846. KdPrintEx((DPFLTR_SYSTEM_ID, DPFLTR_INFO_LEVEL," Version: %s\n", StringPtr));
  847. }
  848. // SerialNumber
  849. KdPrintEx((DPFLTR_SYSTEM_ID, DPFLTR_INFO_LEVEL," I think the SerialNumber string is at offset: %d\n", (ULONG)InfoHeader->SerialNumber));
  850. if( (ULONG)InfoHeader->SerialNumber > 0 ) {
  851. // Jump to the end of the formatted portion of the SMBIOS table.
  852. StringPtr = StartPtr + Header->Length;
  853. // Jump over some number of strings to get to our string.
  854. for( i = 0; i < ((ULONG)InfoHeader->SerialNumber-1); i++ ) {
  855. while( (*StringPtr != 0) && (StringPtr < EndPtr) ) {
  856. StringPtr++;
  857. }
  858. StringPtr++;
  859. }
  860. KdPrintEx((DPFLTR_SYSTEM_ID, DPFLTR_INFO_LEVEL," SerialNumber: %s\n", StringPtr));
  861. }
  862. #endif
  863. } else if( Header->Type == SMBIOS_SYSTEM_CHASIS_INFORMATION_TYPE ) {
  864. PSMBIOS_SYSTEM_CHASIS_INFORMATION_STRUCT InfoHeader = (PSMBIOS_SYSTEM_CHASIS_INFORMATION_STRUCT)StartPtr;
  865. PUCHAR StringPtr = NULL;
  866. KdPrintEx((DPFLTR_SYSTEM_ID, DPFLTR_INFO_LEVEL,"InitializeProcessorInformationFromSMBIOS: SMBIOS_SYSTEM_CHASIS_INFORMATION\n"));
  867. #if 0
  868. //
  869. // We aren't using any of this information right now.
  870. // -matth 4/2001
  871. //
  872. // Manufacturer
  873. KdPrintEx((DPFLTR_SYSTEM_ID, DPFLTR_INFO_LEVEL," I think the Manufacturer string is at offset: %d\n", (ULONG)InfoHeader->Manufacturer));
  874. if( (ULONG)InfoHeader->Manufacturer > 0 ) {
  875. // Jump to the end of the formatted portion of the SMBIOS table.
  876. StringPtr = StartPtr + Header->Length;
  877. // Jump over some number of strings to get to our string.
  878. for( i = 0; i < ((ULONG)InfoHeader->Manufacturer-1); i++ ) {
  879. while( (*StringPtr != 0) && (StringPtr < EndPtr) ) {
  880. StringPtr++;
  881. }
  882. StringPtr++;
  883. }
  884. KdPrintEx((DPFLTR_SYSTEM_ID, DPFLTR_INFO_LEVEL," Manufacturer: %s\n", StringPtr));
  885. }
  886. // Product
  887. KdPrintEx((DPFLTR_SYSTEM_ID, DPFLTR_INFO_LEVEL," I think the Manufacturer string is at offset: %d\n", (ULONG)InfoHeader->ChasisType));
  888. if( (ULONG)InfoHeader->ChasisType > 0 ) {
  889. // Jump to the end of the formatted portion of the SMBIOS table.
  890. StringPtr = StartPtr + Header->Length;
  891. // Jump over some number of strings to get to our string.
  892. for( i = 0; i < ((ULONG)InfoHeader->ChasisType-1); i++ ) {
  893. while( (*StringPtr != 0) && (StringPtr < EndPtr) ) {
  894. StringPtr++;
  895. }
  896. StringPtr++;
  897. }
  898. KdPrintEx((DPFLTR_SYSTEM_ID, DPFLTR_INFO_LEVEL," ChasisType: %s\n", StringPtr));
  899. }
  900. // Version
  901. KdPrintEx((DPFLTR_SYSTEM_ID, DPFLTR_INFO_LEVEL," I think the Version string is at offset: %d\n", (ULONG)InfoHeader->Version));
  902. if( (ULONG)InfoHeader->Version > 0 ) {
  903. // Jump to the end of the formatted portion of the SMBIOS table.
  904. StringPtr = StartPtr + Header->Length;
  905. // Jump over some number of strings to get to our string.
  906. for( i = 0; i < ((ULONG)InfoHeader->Version-1); i++ ) {
  907. while( (*StringPtr != 0) && (StringPtr < EndPtr) ) {
  908. StringPtr++;
  909. }
  910. StringPtr++;
  911. }
  912. KdPrintEx((DPFLTR_SYSTEM_ID, DPFLTR_INFO_LEVEL," Version: %s\n", StringPtr));
  913. }
  914. // SerialNumber
  915. KdPrintEx((DPFLTR_SYSTEM_ID, DPFLTR_INFO_LEVEL," I think the SerialNumber string is at offset: %d\n", (ULONG)InfoHeader->SerialNumber));
  916. if( (ULONG)InfoHeader->SerialNumber > 0 ) {
  917. // Jump to the end of the formatted portion of the SMBIOS table.
  918. StringPtr = StartPtr + Header->Length;
  919. // Jump over some number of strings to get to our string.
  920. for( i = 0; i < ((ULONG)InfoHeader->SerialNumber-1); i++ ) {
  921. while( (*StringPtr != 0) && (StringPtr < EndPtr) ) {
  922. StringPtr++;
  923. }
  924. StringPtr++;
  925. }
  926. KdPrintEx((DPFLTR_SYSTEM_ID, DPFLTR_INFO_LEVEL," SerialNumber: %s\n", StringPtr));
  927. }
  928. #endif
  929. }
  930. //
  931. // Go to the next table.
  932. //
  933. KdPrintEx((DPFLTR_SYSTEM_ID, DPFLTR_INFO_LEVEL,"InitializeProcessorInformationFromSMBIOS: Haven't found the ProcessorInformation block yet. Just looked at a block of type: %d.\n", Header->Type));
  934. StartPtr += Header->Length;
  935. // jump over any trailing string-list too.
  936. while ( (*((USHORT UNALIGNED *)StartPtr) != 0) &&
  937. (StartPtr < EndPtr) )
  938. {
  939. StartPtr++;
  940. }
  941. StartPtr += 2;
  942. }
  943. MmUnmapIoSpace(SMBiosDataVirtualAddress, DMIBiosEPSHeader->StructureTableLength);
  944. } else {
  945. KdPrintEx((DPFLTR_SYSTEM_ID, DPFLTR_INFO_LEVEL,"InitializeProcessorInformationFromSMBIOS: Failed to map the SMBIOS physical address.\n"));
  946. }
  947. } else {
  948. KdPrintEx((DPFLTR_SYSTEM_ID, DPFLTR_INFO_LEVEL,"InitializeProcessorInformationFromSMBIOS: The SMBiosEPSHeader is NULL in the extension block.\n"));
  949. }
  950. } else {
  951. KdPrintEx((DPFLTR_SYSTEM_ID, DPFLTR_INFO_LEVEL,"InitializeProcessorInformationFromSMBIOS: LoaderBlock extension is out of sync with the kernel.\n"));
  952. }
  953. }