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.

720 lines
15 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. char OemID[7]={0};
  328. char OemTableID[20]={0};
  329. ULONG i;
  330. strcpy(OemID, Image->OemID);
  331. strcpy(OemTableID, Image->OemTableID);
  332. for (i = 0; i < strlen(OemID); i++) {
  333. if (OemID[i] == ' ') {
  334. OemID[i] = '_';
  335. }
  336. }
  337. for (i = 0; i < strlen(OemTableID); i++) {
  338. if (OemTableID[i] == ' ') {
  339. OemTableID[i] = '_';
  340. }
  341. }
  342. sprintf (s, "System\\CurrentControlSet\\Services\\ACPI\\Parameters\\%c%c%c%c\\%s\\%s\\%.8x",
  343. signa[0],
  344. signa[1],
  345. signa[2],
  346. signa[3],
  347. OemID,
  348. OemTableID,
  349. Image->OemRevision
  350. );
  351. Status = RegCreateKey (HKEY_LOCAL_MACHINE, s, &RegKey);
  352. if (Status == ERROR_SUCCESS) {
  353. RegCloseKey (RegKey);
  354. }
  355. Status = RegOpenKeyEx (
  356. HKEY_LOCAL_MACHINE,
  357. s,
  358. 0L,
  359. KEY_ALL_ACCESS,
  360. &RegKey
  361. );
  362. if (Status != ERROR_SUCCESS) {
  363. RegKey = NULL;
  364. printf ("Count not access the registry path: %s\n", s);
  365. Abort ();
  366. }
  367. }
  368. VOID
  369. CheckImageHeader (
  370. IN PIFILE File
  371. ) {
  372. PUCHAR Image;
  373. PDSDT Dsdt; // Variable name kept as Dsdt even though this program can handle all types
  374. UCHAR check;
  375. ULONG i;
  376. BOOL found = FALSE;
  377. //ULONG signatures[] = SIGNATURES;
  378. ULONG signatures[] = SIGNATURES;
  379. if (File->FileSize < sizeof(DSDT)) {
  380. FAbort ("Invalid image size in", File);
  381. }
  382. Dsdt = (PDSDT) File->Image;
  383. for (i=0;i<sizeof(signatures);i++) {
  384. if (signatures[i] == Dsdt->Signature) {
  385. found = TRUE;
  386. signa = (PUCHAR)(&(Dsdt->Signature));
  387. break;
  388. }
  389. }
  390. if (!found && !Force) {
  391. UCHAR sig[64];
  392. sprintf(sig, "Image signature (%c%c%c%c) not recognized in",
  393. ((PUCHAR)(&Dsdt->Signature))[0],
  394. ((PUCHAR)(&Dsdt->Signature))[1],
  395. ((PUCHAR)(&Dsdt->Signature))[2],
  396. ((PUCHAR)(&Dsdt->Signature))[3]);
  397. FAbort (sig, File);
  398. }
  399. //
  400. // BUGBUG: remove? (Or at least revision should be "1")
  401. //
  402. // if (Dsdt->Revision != 0) {
  403. // FAbort ("DSDT revision not 0 in", File);
  404. // }
  405. if (File->FileSize != Dsdt->Length) {
  406. UCHAR sig[64];
  407. sprintf(sig, "File size in %c%c%c%c does not match image size in",
  408. signa[0],
  409. signa[1],
  410. signa[2],
  411. signa[3]);
  412. FAbort (sig, File);
  413. }
  414. check = 0;
  415. for (Image = File->Image; Image < File->EndOfImage; Image += 1) {
  416. check += *Image;
  417. }
  418. if (check) {
  419. FAbort ("Image checksum is incorrect in", File);
  420. }
  421. //
  422. // normalize fixed strings
  423. //
  424. File->OemID = FixString (Dsdt->OemID, 6);
  425. File->OemTableID = FixString (Dsdt->OemTableID, 8);
  426. File->OemRevision = Dsdt->OemRevision;
  427. // for (i=0; i < 4; i++) {
  428. // if (File->OemRevision[i] == 0 || File->OemRevision[i] == ' ') {
  429. // File->OemRevision[i] = '_';
  430. // }
  431. // }
  432. if (Verbose) {
  433. printf ("\n");
  434. printf ("%c%c%c%c info for %s (%s)\n",
  435. signa[0],
  436. signa[1],
  437. signa[2],
  438. signa[3],
  439. File->Desc, File->FileName);
  440. printf (" Size of image: %d\n", File->FileSize);
  441. printf (" OEM id.......: %s\n", File->OemID);
  442. printf (" OEM Table id.: %s\n", File->OemTableID);
  443. printf (" OEM revision.: %.8x\n", File->OemRevision);
  444. }
  445. }
  446. PUCHAR
  447. FixString (
  448. IN PUCHAR Str,
  449. IN ULONG Len
  450. ) {
  451. PUCHAR p;
  452. ULONG i;
  453. p = malloc(Len+1);
  454. memcpy (p, Str, Len);
  455. p[Len] = 0;
  456. for (i=Len; i; i--) {
  457. if (p[i] != ' ') {
  458. break;
  459. }
  460. p[i] = 0;
  461. }
  462. return p;
  463. }
  464. VOID
  465. FAbort (
  466. PUCHAR Text,
  467. PIFILE File
  468. ) {
  469. printf ("%s %s (%s)\n", Text, File->Desc, File->FileName);
  470. Abort();
  471. }
  472. VOID
  473. Abort(
  474. VOID
  475. ) {
  476. if (RegInProgress) {
  477. DeleteRegistryNode(RegKey);
  478. }
  479. if (!ArgsParsed) {
  480. printf ("amlload: UpdateImage [OriginalImage] [-v] [-d] [-f]\n");
  481. }
  482. exit (1);
  483. }
  484. VOID
  485. ParseArgs (
  486. IN int argc,
  487. IN char *argv[]
  488. ) {
  489. PIFILE File;
  490. OFSTRUCT OpenBuf;
  491. File = &Update;
  492. while (--argc) {
  493. argv += 1;
  494. //
  495. // If it's a flag crack it
  496. //
  497. if (argv[0][0] == '-') {
  498. switch (argv[0][1]) {
  499. case 'v':
  500. case 'V':
  501. Verbose = TRUE;
  502. break;
  503. case 'd':
  504. case 'D':
  505. DeleteUpdate = TRUE;
  506. break;
  507. case 'f':
  508. case 'F':
  509. Force = TRUE;
  510. break;
  511. default:
  512. printf ("Unknown flag %s\n", argv[0]);
  513. Abort ();
  514. }
  515. } else {
  516. if (!File) {
  517. printf ("Unexcepted parameter %s\n", argv[0]);
  518. Abort();
  519. }
  520. //
  521. // Open the file
  522. //
  523. File->FileName = argv[0];
  524. File->FileHandle = (HANDLE) OpenFile(
  525. argv[0],
  526. &OpenBuf,
  527. OF_READ
  528. );
  529. if (File->FileHandle == (HANDLE) HFILE_ERROR) {
  530. FAbort ("Can not open", File);
  531. }
  532. File->FileSize = GetFileSize(File->FileHandle, NULL);
  533. //
  534. // Map it
  535. //
  536. File->MapHandle =
  537. CreateFileMapping(
  538. File->FileHandle,
  539. NULL,
  540. PAGE_READONLY,
  541. 0,
  542. File->FileSize,
  543. NULL
  544. );
  545. if (!File->MapHandle) {
  546. FAbort ("Cannot map", File);
  547. }
  548. File->Image =
  549. MapViewOfFile (
  550. File->MapHandle,
  551. FILE_MAP_READ,
  552. 0,
  553. 0,
  554. File->FileSize
  555. );
  556. if (!File->Image) {
  557. FAbort ("Cannot map view of image", File);
  558. }
  559. File->EndOfImage = File->Image + File->FileSize;
  560. File->Opened = TRUE;
  561. //
  562. // Next file param
  563. //
  564. if (File == &Update) {
  565. File = &Orig;
  566. } else {
  567. File = NULL;
  568. }
  569. }
  570. }
  571. //
  572. // At least a update image is needed
  573. //
  574. if (!Update.Opened) {
  575. Abort ();
  576. }
  577. ArgsParsed = TRUE;
  578. return ;
  579. }