Leaked source code of windows server 2003
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.

655 lines
16 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. Module Name:
  4. reg.c
  5. Abstract:
  6. These functions access the registry
  7. Author:
  8. Stephane Plante (splante)
  9. Environment:
  10. Kernel mode only.
  11. Revision History:
  12. 03-Jun-97 Initial Revision
  13. --*/
  14. #include "pch.h"
  15. #include "amlreg.h"
  16. #include <stdio.h>
  17. //
  18. // This controls wether or not the various tables will be dumped to the
  19. // registry
  20. //
  21. UCHAR DoAcpiTableDump = 0xFF;
  22. #ifdef ALLOC_PRAGMA
  23. #define alloc_text(PAGE,ACPIRegLocalCopyString)
  24. #define alloc_text(PAGE,ACPIRegDumpAcpiTable)
  25. #define alloc_text(PAGE,ACPIRegDumpAcpiTables)
  26. #define alloc_text(PAGE,ACPIRegReadEntireAcpiTable)
  27. #define alloc_text(PAGE,ACPIRegReadAMLRegistryEntry)
  28. #endif
  29. PUCHAR
  30. ACPIRegLocalCopyString (
  31. PUCHAR Destination,
  32. PUCHAR Source,
  33. ULONG MaxLength
  34. )
  35. /*++
  36. Routine Description:
  37. A little routine to copy short strings, since using sprintf here is
  38. like hitting a tack with a sledgehammer. Terminates when a null or
  39. the max length is reached, whichever comes first. Translates blanks
  40. to underscores, since everyone hates blanks embedded in registry keys.
  41. Arguments:
  42. Destination - Where to copy the string to
  43. Source - Source string pointer
  44. MaxLength - Max number of bytes to copy
  45. Return Value:
  46. Returns the destination pointer incremented past the copied string
  47. __*/
  48. {
  49. ULONG i;
  50. for (i = 0; i < MaxLength; i++) {
  51. if (Source[i] == 0) {
  52. break;
  53. } else if (Source[i] == ' ') { // Translate blanks to underscores
  54. Destination [i] = '_';
  55. } else {
  56. Destination [i] = Source[i];
  57. }
  58. }
  59. Destination [i] = 0;
  60. return (Destination + i);
  61. }
  62. BOOLEAN
  63. ACPIRegReadAMLRegistryEntry(
  64. IN PVOID *Table,
  65. IN BOOLEAN MemoryMapped
  66. )
  67. /*++
  68. Routine Description:
  69. This reads a table from the registry
  70. Arguments:
  71. Table - Where to store the pointer to the table. If non-null, this
  72. contains a pointer to where the Original Table is stored
  73. MemorMapped - Indicates wether or not the table is memory mapped and should
  74. be unmapped once we are done with it
  75. Return Value:
  76. TRUE - Success
  77. FALSE - Failure
  78. __*/
  79. {
  80. BOOLEAN rc = FALSE;
  81. HANDLE revisionKey = NULL;
  82. HANDLE tableIdKey = NULL;
  83. NTSTATUS status;
  84. PDESCRIPTION_HEADER header = (PDESCRIPTION_HEADER) *Table;
  85. PUCHAR key = NULL; // ACPI_PARAMETERS_REGISTRY_KEY;
  86. PUCHAR buffer;
  87. ULONG action;
  88. ULONG bytesRead;
  89. ULONG baseSize;
  90. ULONG totalSize;
  91. PAGED_CODE();
  92. //
  93. // Build a full path name to the thing we want in the registry
  94. //
  95. baseSize = strlen( ACPI_PARAMETERS_REGISTRY_KEY);
  96. totalSize = baseSize + ACPI_MAX_TABLE_STRINGS + 4;
  97. buffer = key = ExAllocatePool( PagedPool, totalSize );
  98. if (key == NULL) {
  99. return FALSE;
  100. }
  101. //
  102. // Generate the path name to the key. This avoids a costly sprintf
  103. //
  104. RtlZeroMemory( buffer, totalSize );
  105. RtlCopyMemory(
  106. buffer,
  107. ACPI_PARAMETERS_REGISTRY_KEY,
  108. baseSize
  109. );
  110. buffer += baseSize;
  111. *buffer++ = '\\';
  112. //
  113. // Table Signature (Up to 4 byte string)
  114. //
  115. buffer = ACPIRegLocalCopyString (buffer, (PUCHAR) &header->Signature, ACPI_MAX_SIGNATURE);
  116. *buffer++ = '\\';
  117. //
  118. // OEM ID field (Up to 6 byte string)
  119. //
  120. buffer = ACPIRegLocalCopyString (buffer, (PUCHAR) &header->OEMID, ACPI_MAX_OEM_ID);
  121. *buffer++ = '\\';
  122. //
  123. // OEM Table ID field (Up to 8 byte string)
  124. //
  125. buffer = ACPIRegLocalCopyString (buffer, (PUCHAR) &header->OEMTableID, ACPI_MAX_TABLE_ID);
  126. *buffer = 0; // Terminate
  127. ACPIPrint ((
  128. ACPI_PRINT_REGISTRY,
  129. "ReadAMLRegistryEntry: opening key: %s\n",
  130. key));
  131. //
  132. // Open the <TableId>/OemId>/<OemTableId> key
  133. //
  134. status = OSOpenHandle(key, NULL, &tableIdKey);
  135. if ( !NT_SUCCESS(status) ) {
  136. ACPIPrint ((
  137. ACPI_PRINT_WARNING,
  138. "ReadAMLRegistryEntry: failed to open AML registry entry (rc=%x)\n",
  139. status));
  140. goto ReadAMLRegistryEntryExit;
  141. }
  142. //
  143. // Find the largest subkey that is equal or greater than the ROM
  144. // BIOS version of the table
  145. //
  146. status = OSOpenLargestSubkey(
  147. tableIdKey,
  148. &revisionKey,
  149. header->OEMRevision
  150. );
  151. if (!NT_SUCCESS(status)) {
  152. ACPIPrint ((
  153. ACPI_PRINT_WARNING,
  154. "ReadAMLRegistryEntry: no valid <OemRevision> key (rc=%#08lx)\n",
  155. status));
  156. goto ReadAMLRegistryEntryExit;
  157. }
  158. //
  159. // Get the Action value for this table, which tells us what to do with
  160. // the table
  161. //
  162. bytesRead = sizeof(action);
  163. status = OSReadRegValue(
  164. "Action",
  165. revisionKey,
  166. &action,
  167. &bytesRead
  168. );
  169. if (!NT_SUCCESS(status) || bytesRead != sizeof(action)) {
  170. ACPIPrint( (
  171. ACPI_PRINT_CRITICAL,
  172. "ReadAMLRegistryEntry: read action value = %#08lx. BytesRead=%d\n",
  173. status, bytesRead
  174. ) );
  175. action = ACTION_LOAD_TABLE; // Default action
  176. }
  177. //
  178. // Do the action
  179. //
  180. switch (action) {
  181. case ACTION_LOAD_TABLE:
  182. //
  183. // Overload entire ROM table
  184. //
  185. status = ACPIRegReadEntireAcpiTable(revisionKey, Table, MemoryMapped);
  186. if (NT_SUCCESS( status ) ) {
  187. rc = TRUE;
  188. }
  189. break;
  190. case ACTION_LOAD_ROM:
  191. case ACTION_LOAD_NOTHING:
  192. //
  193. // Nothing to do for these cases (return FALSE however);
  194. //
  195. break;
  196. default:
  197. //
  198. // Unsupported actions (return FALSE)
  199. //
  200. ACPIPrint( (
  201. ACPI_PRINT_CRITICAL,
  202. "ReadAMLRegistryEntry: Unsupported action value (action=%d)\n",
  203. action
  204. ) );
  205. break;
  206. }
  207. //
  208. // Always close the open keys
  209. //
  210. ReadAMLRegistryEntryExit:
  211. if (key != NULL) {
  212. ExFreePool( key );
  213. }
  214. if (tableIdKey != NULL) {
  215. OSCloseHandle( tableIdKey );
  216. }
  217. if (revisionKey != NULL) {
  218. OSCloseHandle( revisionKey );
  219. }
  220. return rc;
  221. }
  222. NTSTATUS
  223. ACPIRegReadEntireAcpiTable (
  224. IN HANDLE RevisionKey,
  225. IN PVOID *Table,
  226. IN BOOLEAN MemoryMapped
  227. )
  228. /*++
  229. Routine Description:
  230. Reads the table from the registry into memory
  231. Arguments:
  232. RevisionKey - Handle to the key containing the table
  233. Table - Pointer to the pointer to the table
  234. MemorymMapped - If True, indicates that we need to MmUnmapIo the table
  235. otherwise, if False, we do no free the table (the
  236. memory is static)
  237. Return Value:
  238. NTSTATUS
  239. --*/
  240. {
  241. NTSTATUS status;
  242. PUCHAR buffer;
  243. PVOID table;
  244. UCHAR value[9];
  245. ULONG bytesRead;
  246. ULONG index = 0;
  247. ULONG entry;
  248. PREGISTRY_HEADER entryHeader;
  249. PDESCRIPTION_HEADER descHeader = (PDESCRIPTION_HEADER) *Table;
  250. PAGED_CODE();
  251. //
  252. // We need an 8k buffer
  253. //
  254. buffer = ExAllocatePool( PagedPool, 8 * 1024 );
  255. if (buffer == NULL) {
  256. return STATUS_INSUFFICIENT_RESOURCES;
  257. }
  258. //
  259. // Repeat this forever
  260. //
  261. for (index = 0; ;index++) {
  262. //
  263. // This is the first data value
  264. //
  265. sprintf(value, "%08lx", index );
  266. //
  267. // Read the entry header to get the size of the table. This is stored
  268. // before the actual table
  269. //
  270. bytesRead = 8 * 1024;
  271. status = OSReadRegValue(
  272. value,
  273. RevisionKey,
  274. buffer,
  275. &bytesRead
  276. );
  277. if (!NT_SUCCESS(status) ) {
  278. //
  279. // Not being able to read the table isn't a failure case
  280. //
  281. status = STATUS_SUCCESS;
  282. break;
  283. } else if (bytesRead < sizeof(REGISTRY_HEADER) ) {
  284. //
  285. // Not being to read the proper number of bytes is
  286. //
  287. ACPIPrint( (
  288. ACPI_PRINT_CRITICAL,
  289. "ReadEntireAcpiTable: read registry header (bytes=%d)\n",
  290. bytesRead
  291. ) );
  292. return STATUS_UNSUCCESSFUL;
  293. }
  294. //
  295. // Loop while we still have bytes to process
  296. //
  297. for (entry = 0;
  298. entry < bytesRead;
  299. entry += (entryHeader->Length + sizeof(REGISTRY_HEADER) )
  300. ) {
  301. //
  302. // Grab a pointer to the entry record
  303. //
  304. entryHeader = (PREGISTRY_HEADER) &(buffer[entry]);
  305. //
  306. // Crack the record
  307. //
  308. if (entryHeader->Length == 0) {
  309. //
  310. // Special Case
  311. //
  312. if (entryHeader->Offset != descHeader->Length) {
  313. //
  314. // Must change the table size
  315. //
  316. table = ExAllocatePoolWithTag(
  317. NonPagedPool,
  318. entryHeader->Offset,
  319. ACPI_SHARED_TABLE_POOLTAG
  320. );
  321. if (table == NULL) {
  322. ExFreePool( buffer );
  323. return STATUS_INSUFFICIENT_RESOURCES;
  324. }
  325. //
  326. // How much do we have to copy?
  327. //
  328. RtlCopyMemory(
  329. table,
  330. *Table,
  331. min( entryHeader->Offset, descHeader->Length )
  332. );
  333. //
  334. // Free the old table based on wether or not its mm mapped
  335. //
  336. if (MemoryMapped) {
  337. MmUnmapIoSpace(*Table, descHeader->Length);
  338. } else {
  339. ExFreePool( *Table );
  340. }
  341. //
  342. // Remember the address of the new table
  343. //
  344. descHeader = (PDESCRIPTION_HEADER) *Table = table;
  345. }
  346. //
  347. // Done with this record
  348. //
  349. continue;
  350. }
  351. //
  352. // Patch the memory
  353. //
  354. ASSERT( entryHeader->Offset < descHeader->Length );
  355. RtlCopyMemory(
  356. ( (PUCHAR) *Table) + entryHeader->Offset,
  357. (PUCHAR) entryHeader + sizeof( REGISTRY_HEADER ),
  358. entryHeader->Length
  359. );
  360. }
  361. }
  362. //
  363. // Normal exit
  364. //
  365. if (buffer != NULL) {
  366. ExFreePool( buffer );
  367. }
  368. return status;
  369. }
  370. /****************************************************************************
  371. *
  372. * DumpAcpiTable
  373. * Write an ACPI Table to the registry
  374. *
  375. * Not exported.
  376. *
  377. * ENTRY: pszName - Name of the table to write (4 byte string)
  378. * Table - Pointer to table data
  379. * Length - of the table
  380. * Header - Pointer to the table header
  381. *
  382. * EXIT: NONE
  383. *
  384. ***************************************************************************/
  385. VOID
  386. ACPIRegDumpAcpiTable (
  387. PSZ pszName,
  388. PVOID Table,
  389. ULONG Length,
  390. PDESCRIPTION_HEADER Header
  391. )
  392. {
  393. //NTSTATUS status;
  394. UCHAR buffer [80] = "\\Registry\\Machine\\Hardware\\ACPI";
  395. HANDLE hSubKey;
  396. HANDLE hPrefixKey;
  397. PAGED_CODE();
  398. //
  399. // Create /Registry/Machine/Hardware/ACPI subkey
  400. //
  401. if ( !NT_SUCCESS(OSCreateHandle (buffer, NULL, &hPrefixKey) ) ) {
  402. return;
  403. }
  404. //
  405. // Create table name subkey (DSDT, FACP, FACS, or RSDT) - 4 bytes
  406. //
  407. if ( !NT_SUCCESS(OSCreateHandle (pszName, hPrefixKey, &hSubKey) ) ) {
  408. goto DumpAcpiTableExit;
  409. }
  410. //
  411. // For tables with headers, add subkeys for
  412. // <OemId>/<OemTableID>/<OemRevision>
  413. //
  414. if (Header) {
  415. OSCloseHandle(hPrefixKey);
  416. hPrefixKey = hSubKey;
  417. //
  418. // OEM ID field (6 byte string)
  419. //
  420. ACPIRegLocalCopyString (buffer, Header->OEMID, ACPI_MAX_OEM_ID);
  421. if ( !NT_SUCCESS(OSCreateHandle (buffer, hPrefixKey, &hSubKey) ) ) {
  422. goto DumpAcpiTableExit;
  423. }
  424. OSCloseHandle (hPrefixKey);
  425. hPrefixKey = hSubKey;
  426. //
  427. // OEM Table ID field (8 byte string)
  428. //
  429. ACPIRegLocalCopyString (buffer, Header->OEMTableID, ACPI_MAX_TABLE_ID);
  430. if ( !NT_SUCCESS(OSCreateHandle (buffer, hPrefixKey, &hSubKey) ) ) {
  431. goto DumpAcpiTableExit;
  432. }
  433. OSCloseHandle (hPrefixKey);
  434. hPrefixKey = hSubKey;
  435. //
  436. // OEM Revision field (4 byte number)
  437. //
  438. sprintf (buffer, "%.8x", Header->OEMRevision);
  439. if ( !NT_SUCCESS(OSCreateHandle (buffer, hPrefixKey, &hSubKey) ) ) {
  440. goto DumpAcpiTableExit;
  441. }
  442. }
  443. //
  444. // Finally, write the entire table
  445. //
  446. OSWriteRegValue ("00000000", hSubKey, Table, Length);
  447. //
  448. // Delete open handles
  449. //
  450. OSCloseHandle (hSubKey);
  451. DumpAcpiTableExit:
  452. OSCloseHandle (hPrefixKey);
  453. return;
  454. }
  455. /****************************************************************************
  456. *
  457. * DumpAcpiTables
  458. * Write the ACPI Tables to the registry. Should be called only
  459. * after table pointers have been initialized.
  460. *
  461. * Not exported.
  462. *
  463. * ENTRY: NONE
  464. * EXIT: NONE.
  465. *
  466. ***************************************************************************/
  467. VOID
  468. ACPIRegDumpAcpiTables (VOID)
  469. {
  470. PDSDT dsdt = AcpiInformation->DiffSystemDescTable;
  471. PFACS facs = AcpiInformation->FirmwareACPIControlStructure;
  472. PFADT fadt = AcpiInformation->FixedACPIDescTable;
  473. PRSDT rsdt = AcpiInformation->RootSystemDescTable;
  474. if (DoAcpiTableDump) {
  475. ACPIPrint ((
  476. ACPI_PRINT_REGISTRY,
  477. "DumpAcpiTables: Writing DSDT/FACS/FADT/RSDT to registry\n"));
  478. if (dsdt) {
  479. ACPIRegDumpAcpiTable(
  480. "DSDT",
  481. dsdt,
  482. dsdt->Header.Length,
  483. &(dsdt->Header)
  484. );
  485. }
  486. if (facs) {
  487. ACPIRegDumpAcpiTable(
  488. "FACS",
  489. facs,
  490. facs->Length,
  491. NULL
  492. );
  493. }
  494. if (fadt) {
  495. ACPIRegDumpAcpiTable(
  496. "FADT",
  497. fadt,
  498. fadt->Header.Length,
  499. &(fadt->Header)
  500. );
  501. }
  502. if (rsdt) {
  503. ACPIRegDumpAcpiTable(
  504. "RSDT",
  505. rsdt,
  506. rsdt->Header.Length,
  507. &(rsdt->Header)
  508. );
  509. }
  510. }
  511. }