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.

703 lines
14 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. Module Name:
  4. acpiload.c
  5. Abstract:
  6. This program installs an AML file into the NT registry
  7. Author:
  8. Ken Reneris
  9. Environment:
  10. Command-line.
  11. Revision History:
  12. 2-23-2000 - mmurph - Added support for images besides DSDTs
  13. 2-23-2000 - mmurph - Added support to force load for unknown image type
  14. --*/
  15. #include <windows.h>
  16. #include <stdio.h>
  17. #include <stdlib.h>
  18. #include <amlreg.h>
  19. //#include <varargs.h>
  20. #define SIGNATURES {'TDSD', 'TDSR', 'TDSS', 'TDSP', 'CIPA', 'PCAF', 'SCAF', 'TSBS'}
  21. #define DATA_SIZE 7*1024 // max value to write into registry
  22. typedef struct {
  23. ULONG Signature;
  24. ULONG Length;
  25. UCHAR Revision;
  26. UCHAR Checksum;
  27. UCHAR OemID[6];
  28. UCHAR OemTableID[8];
  29. ULONG OemRevision;
  30. UCHAR CreatorID[4];
  31. UCHAR CreatorRevision[4];
  32. } DSDT, *PDSDT;
  33. IFILE Update; // Image of updated aml file
  34. IFILE Orig; // Image of original aml file
  35. BOOLEAN Verbose;
  36. BOOLEAN DeleteUpdate;
  37. BOOLEAN Force;
  38. BOOLEAN ArgsParsed;
  39. BOOLEAN RegInProgress;
  40. HKEY RegKey;
  41. ULONG RegDataSequence;
  42. ULONG RegDataSize;
  43. UCHAR RegDataBuffer[DATA_SIZE];
  44. UCHAR s[500]; // Registry path
  45. PUCHAR signa;
  46. //
  47. // Internal prototypes
  48. //
  49. VOID
  50. ParseArgs (
  51. IN int argc,
  52. IN char *argv[]
  53. );
  54. VOID
  55. CheckImageHeader (
  56. IN PIFILE File
  57. );
  58. VOID
  59. GetRegistryKey (
  60. IN PIFILE Image
  61. );
  62. VOID
  63. FAbort (
  64. PUCHAR Text,
  65. PIFILE File
  66. );
  67. VOID
  68. Abort (
  69. VOID
  70. );
  71. VOID
  72. BuildUpdate (
  73. VOID
  74. );
  75. VOID
  76. AddRun (
  77. IN ULONG Offset,
  78. IN ULONG Length
  79. );
  80. VOID
  81. FlushRun (
  82. VOID
  83. );
  84. VOID
  85. DeleteRegistryNode (
  86. IN HKEY Handle
  87. );
  88. PUCHAR
  89. FixString (
  90. IN PUCHAR Str,
  91. IN ULONG Len
  92. );
  93. int
  94. __cdecl
  95. main(
  96. IN int argc,
  97. IN char *argv[]
  98. ) {
  99. //
  100. // Init globals
  101. //
  102. Update.Desc = "update image";
  103. Orig.Desc = "original image";
  104. //
  105. // Parse args
  106. //
  107. ParseArgs(argc, argv);
  108. //
  109. // Parse image headers
  110. //
  111. CheckImageHeader (&Update);
  112. if (Orig.Opened) {
  113. CheckImageHeader (&Orig);
  114. // verify oem info
  115. if (strcmp (Update.OemID, Orig.OemID)) {
  116. printf ("OEM id in update image mis-matches original image\n");
  117. Abort ();
  118. }
  119. if (strcmp (Update.OemTableID, Orig.OemTableID)) {
  120. printf ("OEM table id in update image mis-matches original image\n");
  121. Abort ();
  122. }
  123. if (Update.OemRevision != Orig.OemRevision) {
  124. printf ("OEM revision in update image revision does not match\n");
  125. Abort ();
  126. }
  127. }
  128. //
  129. // Open/create proper registry location
  130. //
  131. GetRegistryKey (&Update);
  132. //
  133. // Delete any existing stuff
  134. //
  135. DeleteRegistryNode (RegKey);
  136. if (DeleteUpdate) {
  137. printf ("Registry data deleted\n");
  138. exit (1);
  139. }
  140. //
  141. // For now hardcoded to "update" action
  142. //
  143. BuildUpdate ();
  144. return 0;
  145. }
  146. VOID
  147. BuildUpdate (
  148. VOID
  149. ) {
  150. LONG Status;
  151. ULONG i, Len, Offs, RunLen, match;
  152. RegDataSequence = 0;
  153. RegDataSize = 0;
  154. RegInProgress = TRUE;
  155. //
  156. // If there's no original image, just write the new one
  157. //
  158. if (!Orig.Opened) {
  159. AddRun (Update.FileSize, 0);
  160. AddRun (0, Update.FileSize);
  161. } else {
  162. if (Update.FileSize != Orig.FileSize) {
  163. AddRun (Update.FileSize, 0);
  164. }
  165. Len = Update.FileSize;
  166. if (Orig.FileSize < Update.FileSize) {
  167. Len = Orig.FileSize;
  168. }
  169. Offs=0;
  170. while (Offs < Len) {
  171. //
  172. // Skip matching bytes
  173. //
  174. if (Update.Image[Offs] == Orig.Image[Offs]) {
  175. Offs += 1;
  176. continue;
  177. }
  178. //
  179. // Count mismatching bytes
  180. //
  181. match = 0;
  182. for (RunLen=1; Offs+RunLen < Len; RunLen++) {
  183. if (Update.Image[Offs+RunLen] == Orig.Image[Offs+RunLen]) {
  184. match += 1;
  185. if (match > 8) {
  186. break;
  187. }
  188. } else {
  189. match = 0;
  190. }
  191. }
  192. RunLen -= match;
  193. AddRun (Offs, RunLen);
  194. Offs += RunLen;
  195. }
  196. //
  197. // If there's more at the end add it
  198. //
  199. if (Len < Update.FileSize) {
  200. AddRun (Len, Update.FileSize - Len);
  201. }
  202. }
  203. FlushRun();
  204. if (RegDataSequence) {
  205. if (Verbose) {
  206. printf ("SetValue Action\n");
  207. }
  208. i = 0; // BUGBUG: values need defined
  209. Status = RegSetValueEx (RegKey, "Action", 0L, REG_DWORD,(PUCHAR) &i, sizeof(i));
  210. }
  211. RegInProgress = FALSE;
  212. if (Verbose) {
  213. printf ("Registry path:\n%s\n", s);
  214. }
  215. }
  216. VOID
  217. AddRun (
  218. IN ULONG Offset,
  219. IN ULONG Length
  220. ) {
  221. PREGISTRY_HEADER regHdr;
  222. ULONG RunLength;
  223. do {
  224. if (RegDataSize + sizeof(REGISTRY_HEADER) > DATA_SIZE - 128) {
  225. FlushRun ();
  226. }
  227. regHdr = (PREGISTRY_HEADER) (RegDataBuffer + RegDataSize);
  228. RegDataSize += sizeof(REGISTRY_HEADER);
  229. if (DATA_SIZE - RegDataSize < Length) {
  230. RunLength = DATA_SIZE - RegDataSize;
  231. } else {
  232. RunLength = Length;
  233. }
  234. //printf ("Add Hdr %x %x\n", Offset, RunLength);
  235. regHdr->Offset = Offset;
  236. regHdr->Length = RunLength;
  237. RtlCopyMemory (RegDataBuffer + RegDataSize, Update.Image + Offset, RunLength);
  238. RegDataSize += RunLength;
  239. Offset += RunLength;
  240. Length -= RunLength;
  241. } while (Length);
  242. }
  243. VOID
  244. FlushRun
  245. (
  246. VOID
  247. ) {
  248. LONG Status;
  249. UCHAR s[50];
  250. if (RegDataSize) {
  251. sprintf (s, "%08x", RegDataSequence);
  252. RegDataSequence += 1;
  253. if (Verbose) {
  254. printf ("SetValue %s\n", s);
  255. }
  256. Status = RegSetValueEx (RegKey, s, 0L, REG_BINARY, RegDataBuffer, RegDataSize);
  257. RegDataSize = 0;
  258. if (Status != ERROR_SUCCESS) {
  259. printf ("Error writting registry value %s\n", s);
  260. Abort();
  261. }
  262. }
  263. }
  264. VOID
  265. DeleteRegistryNode (
  266. IN HKEY Handle
  267. ) {
  268. UCHAR s[500];
  269. ULONG i;
  270. LONG Status;
  271. HKEY SubKey;
  272. ULONG Type;
  273. ULONG DataSize;
  274. #if 0
  275. i = 0;
  276. for (; ;) {
  277. Status = RegEnumKey(Handle, i, s, sizeof(s));
  278. i += 1;
  279. if (Status == ERROR_NO_MORE_ITEMS) {
  280. break;
  281. }
  282. Status = RegOpenKey(Handle, s, &SubKey);
  283. if (Status == ERROR_SUCCESS) {
  284. DeleteRegistryNode (SubKey);
  285. RegCloseKey (SubKey);
  286. if (Verbose) {
  287. printf ("Delete key %s\n", s);
  288. }
  289. RegDeleteKey (Handle, s);
  290. i = 0;
  291. }
  292. }
  293. #endif
  294. i = 0;
  295. for (; ;) {
  296. s[0] = 0;
  297. DataSize = 0;
  298. Status = RegEnumValue(
  299. Handle,
  300. i,
  301. s,
  302. &DataSize,
  303. NULL,
  304. &Type,
  305. NULL,
  306. 0
  307. );
  308. i += 1;
  309. if (Status == ERROR_NO_MORE_ITEMS) {
  310. break;
  311. }
  312. s[DataSize] = 0;
  313. if (Verbose) {
  314. printf ("Delete value %s\n", s);
  315. }
  316. Status = RegDeleteValue (Handle, s);
  317. if (Status == ERROR_SUCCESS) {
  318. i = 0;
  319. }
  320. }
  321. }
  322. VOID
  323. GetRegistryKey (
  324. IN PIFILE Image
  325. ) {
  326. LONG Status;
  327. sprintf (s, "System\\CurrentControlSet\\Services\\ACPI\\Parameters\\%c%c%c%c\\%s\\%s\\%.8x",
  328. signa[0],
  329. signa[1],
  330. signa[2],
  331. signa[3],
  332. Image->OemID,
  333. Image->OemTableID,
  334. Image->OemRevision
  335. );
  336. Status = RegCreateKey (HKEY_LOCAL_MACHINE, s, &RegKey);
  337. if (Status == ERROR_SUCCESS) {
  338. RegCloseKey (RegKey);
  339. }
  340. Status = RegOpenKeyEx (
  341. HKEY_LOCAL_MACHINE,
  342. s,
  343. 0L,
  344. KEY_ALL_ACCESS,
  345. &RegKey
  346. );
  347. if (Status != ERROR_SUCCESS) {
  348. RegKey = NULL;
  349. printf ("Count not access the registry path: %s\n", s);
  350. Abort ();
  351. }
  352. }
  353. VOID
  354. CheckImageHeader (
  355. IN PIFILE File
  356. ) {
  357. PUCHAR Image;
  358. PDSDT Dsdt; // Variable name kept as Dsdt even though this program can handle all types
  359. UCHAR check;
  360. ULONG i;
  361. BOOL found = FALSE;
  362. //ULONG signatures[] = SIGNATURES;
  363. ULONG signatures[] = SIGNATURES;
  364. if (File->FileSize < sizeof(DSDT)) {
  365. FAbort ("Invalid image size in", File);
  366. }
  367. Dsdt = (PDSDT) File->Image;
  368. for (i=0;i<sizeof(signatures);i++) {
  369. if (signatures[i] == Dsdt->Signature) {
  370. found = TRUE;
  371. signa = (PUCHAR)(&(Dsdt->Signature));
  372. break;
  373. }
  374. }
  375. if (!found && !Force) {
  376. UCHAR sig[64];
  377. sprintf(sig, "Image signature (%c%c%c%c) not recognized in",
  378. ((PUCHAR)(&Dsdt->Signature))[0],
  379. ((PUCHAR)(&Dsdt->Signature))[1],
  380. ((PUCHAR)(&Dsdt->Signature))[2],
  381. ((PUCHAR)(&Dsdt->Signature))[3]);
  382. FAbort (sig, File);
  383. }
  384. //
  385. // BUGBUG: remove? (Or at least revision should be "1")
  386. //
  387. // if (Dsdt->Revision != 0) {
  388. // FAbort ("DSDT revision not 0 in", File);
  389. // }
  390. if (File->FileSize != Dsdt->Length) {
  391. UCHAR sig[64];
  392. sprintf(sig, "File size in %c%c%c%c does not match image size in",
  393. signa[0],
  394. signa[1],
  395. signa[2],
  396. signa[3]);
  397. FAbort (sig, File);
  398. }
  399. check = 0;
  400. for (Image = File->Image; Image < File->EndOfImage; Image += 1) {
  401. check += *Image;
  402. }
  403. if (check) {
  404. FAbort ("Image checksum is incorrect in", File);
  405. }
  406. //
  407. // normalize fixed strings
  408. //
  409. File->OemID = FixString (Dsdt->OemID, 6);
  410. File->OemTableID = FixString (Dsdt->OemTableID, 8);
  411. File->OemRevision = Dsdt->OemRevision;
  412. // for (i=0; i < 4; i++) {
  413. // if (File->OemRevision[i] == 0 || File->OemRevision[i] == ' ') {
  414. // File->OemRevision[i] = '_';
  415. // }
  416. // }
  417. if (Verbose) {
  418. printf ("\n");
  419. printf ("%c%c%c%c info for %s (%s)\n",
  420. signa[0],
  421. signa[1],
  422. signa[2],
  423. signa[3],
  424. File->Desc, File->FileName);
  425. printf (" Size of image: %d\n", File->FileSize);
  426. printf (" OEM id.......: %s\n", File->OemID);
  427. printf (" OEM Table id.: %s\n", File->OemTableID);
  428. printf (" OEM revision.: %.8x\n", File->OemRevision);
  429. }
  430. }
  431. PUCHAR
  432. FixString (
  433. IN PUCHAR Str,
  434. IN ULONG Len
  435. ) {
  436. PUCHAR p;
  437. ULONG i;
  438. p = malloc(Len+1);
  439. memcpy (p, Str, Len);
  440. p[Len] = 0;
  441. for (i=Len; i; i--) {
  442. if (p[i] != ' ') {
  443. break;
  444. }
  445. p[i] = 0;
  446. }
  447. return p;
  448. }
  449. VOID
  450. FAbort (
  451. PUCHAR Text,
  452. PIFILE File
  453. ) {
  454. printf ("%s %s (%s)\n", Text, File->Desc, File->FileName);
  455. Abort();
  456. }
  457. VOID
  458. Abort(
  459. VOID
  460. ) {
  461. if (RegInProgress) {
  462. DeleteRegistryNode(RegKey);
  463. }
  464. if (!ArgsParsed) {
  465. printf ("amlload: UpdateImage [OriginalImage] [-v] [-d] [-f]\n");
  466. }
  467. exit (1);
  468. }
  469. VOID
  470. ParseArgs (
  471. IN int argc,
  472. IN char *argv[]
  473. ) {
  474. PIFILE File;
  475. OFSTRUCT OpenBuf;
  476. File = &Update;
  477. while (--argc) {
  478. argv += 1;
  479. //
  480. // If it's a flag crack it
  481. //
  482. if (argv[0][0] == '-') {
  483. switch (argv[0][1]) {
  484. case 'v':
  485. case 'V':
  486. Verbose = TRUE;
  487. break;
  488. case 'd':
  489. case 'D':
  490. DeleteUpdate = TRUE;
  491. break;
  492. case 'f':
  493. case 'F':
  494. Force = TRUE;
  495. break;
  496. default:
  497. printf ("Unknown flag %s\n", argv[0]);
  498. Abort ();
  499. }
  500. } else {
  501. if (!File) {
  502. printf ("Unexcepted parameter %s\n", argv[0]);
  503. Abort();
  504. }
  505. //
  506. // Open the file
  507. //
  508. File->FileName = argv[0];
  509. File->FileHandle = (HANDLE) OpenFile(
  510. argv[0],
  511. &OpenBuf,
  512. OF_READ
  513. );
  514. if (File->FileHandle == (HANDLE) HFILE_ERROR) {
  515. FAbort ("Can not open", File);
  516. }
  517. File->FileSize = GetFileSize(File->FileHandle, NULL);
  518. //
  519. // Map it
  520. //
  521. File->MapHandle =
  522. CreateFileMapping(
  523. File->FileHandle,
  524. NULL,
  525. PAGE_READONLY,
  526. 0,
  527. File->FileSize,
  528. NULL
  529. );
  530. if (!File->MapHandle) {
  531. FAbort ("Cannot map", File);
  532. }
  533. File->Image =
  534. MapViewOfFile (
  535. File->MapHandle,
  536. FILE_MAP_READ,
  537. 0,
  538. 0,
  539. File->FileSize
  540. );
  541. if (!File->Image) {
  542. FAbort ("Cannot map view of image", File);
  543. }
  544. File->EndOfImage = File->Image + File->FileSize;
  545. File->Opened = TRUE;
  546. //
  547. // Next file param
  548. //
  549. if (File == &Update) {
  550. File = &Orig;
  551. } else {
  552. File = NULL;
  553. }
  554. }
  555. }
  556. //
  557. // At least a update image is needed
  558. //
  559. if (!Update.Opened) {
  560. Abort ();
  561. }
  562. ArgsParsed = TRUE;
  563. return ;
  564. }