1
0

acpiext.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738
  1. /*++
  2. Copyright (c) 2012 Minoca Corp. All Rights Reserved
  3. Module Name:
  4. acpiext.c
  5. Abstract:
  6. This module implements ACPI related debugger extensions.
  7. Author:
  8. Evan Green 27-Nov-2012
  9. Environment:
  10. Debug Client
  11. --*/
  12. //
  13. // ------------------------------------------------------------------- Includes
  14. //
  15. //
  16. // Define away KERNEL_API to avoid it being defined as an import or export.
  17. //
  18. #define KERNEL_API
  19. #include <minoca/lib/types.h>
  20. #include <minoca/lib/status.h>
  21. #include <minoca/lib/rtl.h>
  22. #include <minoca/lib/im.h>
  23. #include <minoca/debug/dbgext.h>
  24. #include "../../drivers/acpi/acpiobj.h"
  25. #include <errno.h>
  26. #include <stdio.h>
  27. #include <stdlib.h>
  28. #include <string.h>
  29. //
  30. // ---------------------------------------------------------------- Definitions
  31. //
  32. #define ROOT_NAMESPACE_OBJECT_SYMBOL "acpi!AcpiNamespaceRoot"
  33. #define MALLOC(_x) malloc(_x)
  34. #define FREE(_x) free(_x)
  35. //
  36. // ------------------------------------------------------ Data Type Definitions
  37. //
  38. //
  39. // ----------------------------------------------- Internal Function Prototypes
  40. //
  41. VOID
  42. ExtAcpiNamespace (
  43. PDEBUGGER_CONTEXT Context,
  44. ULONG ArgumentCount,
  45. PSTR *ArgumentValues
  46. );
  47. INT
  48. ExtpPrintNamespaceAtRoot (
  49. PDEBUGGER_CONTEXT Context,
  50. ULONGLONG Address,
  51. PULONGLONG NextSibling,
  52. ULONG IndentationLevel
  53. );
  54. //
  55. // -------------------------------------------------------------------- Globals
  56. //
  57. //
  58. // ------------------------------------------------------------------ Functions
  59. //
  60. INT
  61. ExtAcpi (
  62. PDEBUGGER_CONTEXT Context,
  63. PSTR Command,
  64. ULONG ArgumentCount,
  65. PSTR *ArgumentValues
  66. )
  67. /*++
  68. Routine Description:
  69. This routine implements the ACPI debugger extension.
  70. Arguments:
  71. Context - Supplies a pointer to the debugger applicaton context, which is
  72. an argument to most of the API functions.
  73. Command - Supplies the subcommand entered.
  74. ArgumentCount - Supplies the number of arguments in the ArgumentValues
  75. array.
  76. ArgumentValues - Supplies the values of each argument. This memory will be
  77. reused when the function returns, so extensions must not touch this
  78. memory after returning from this call.
  79. Return Value:
  80. 0 if the debugger extension command was successful.
  81. Returns an error code if a failure occurred along the way.
  82. --*/
  83. {
  84. if (Command == NULL) {
  85. DbgOut("Error: A valid subcommand must be supplied. Try one of these:\n"
  86. "\t!acpi.ns\n\n");
  87. return EINVAL;
  88. }
  89. if (strcmp(Command, "ns") == 0) {
  90. ExtAcpiNamespace(Context, ArgumentCount - 1, ArgumentValues + 1);
  91. } else {
  92. DbgOut("Error: A valid subcommand must be supplied. Try one of these:\n"
  93. "\t!acpi.ns\n\n");
  94. }
  95. return 0;
  96. }
  97. //
  98. // --------------------------------------------------------- Internal Functions
  99. //
  100. VOID
  101. ExtAcpiNamespace (
  102. PDEBUGGER_CONTEXT Context,
  103. ULONG ArgumentCount,
  104. PSTR *ArgumentValues
  105. )
  106. /*++
  107. Routine Description:
  108. This routine implements the ACPI namespace debugger extension.
  109. Arguments:
  110. Context - Supplies a pointer to the debugger application context.
  111. ArgumentCount - Supplies the number of arguments in the ArgumentValues
  112. array.
  113. ArgumentValues - Supplies the values of each argument. This memory will be
  114. reused when the function returns, so extensions must not touch this
  115. memory after returning from this call.
  116. Return Value:
  117. None.
  118. --*/
  119. {
  120. ULONG AddressSize;
  121. ULONG ArgumentIndex;
  122. ULONG BytesRead;
  123. BOOL Result;
  124. ULONGLONG RootAddress;
  125. ULONGLONG RootAddressAddress;
  126. INT Success;
  127. RootAddress = 0;
  128. RootAddressAddress = 0;
  129. AddressSize = DbgGetTargetPointerSize(Context);
  130. //
  131. // If there are no arguments, try to find the root.
  132. //
  133. if (ArgumentCount == 0) {
  134. Result = DbgEvaluate(Context,
  135. ROOT_NAMESPACE_OBJECT_SYMBOL,
  136. &RootAddressAddress);
  137. if (Result != 0) {
  138. DbgOut("Error: Could not evaluate %s\n",
  139. ROOT_NAMESPACE_OBJECT_SYMBOL);
  140. return;
  141. }
  142. //
  143. // Now given the address of the pointer, read the value to get the
  144. // actual address of the root object.
  145. //
  146. Success = DbgReadMemory(Context,
  147. TRUE,
  148. RootAddressAddress,
  149. AddressSize,
  150. &RootAddress,
  151. &BytesRead);
  152. if ((Success != 0) || (BytesRead != AddressSize)) {
  153. DbgOut("Error: Could not read root object at 0x%I64x.\n",
  154. RootAddressAddress);
  155. return;
  156. }
  157. if (RootAddress == (UINTN)NULL) {
  158. DbgOut("ACPI Object root is NULL.\n");
  159. return;
  160. }
  161. DbgOut("%s: %I64x\n", ROOT_NAMESPACE_OBJECT_SYMBOL, RootAddress);
  162. ExtpPrintNamespaceAtRoot(Context, RootAddress, NULL, 0);
  163. } else {
  164. //
  165. // Loop through each argument, evaluate the address, and print the
  166. // namespace tree at that object.
  167. //
  168. for (ArgumentIndex = 0;
  169. ArgumentIndex < ArgumentCount;
  170. ArgumentIndex += 1) {
  171. Result = DbgEvaluate(Context,
  172. ArgumentValues[ArgumentIndex],
  173. &RootAddress);
  174. if (Result != 0) {
  175. DbgOut("Failed to evaluate address at \"%s\".\n",
  176. ArgumentValues[ArgumentIndex]);
  177. }
  178. ExtpPrintNamespaceAtRoot(Context, RootAddress, NULL, 0);
  179. if (ArgumentIndex != ArgumentCount - 1) {
  180. DbgOut("\n----");
  181. }
  182. }
  183. }
  184. return;
  185. }
  186. INT
  187. ExtpPrintNamespaceAtRoot (
  188. PDEBUGGER_CONTEXT Context,
  189. ULONGLONG Address,
  190. PULONGLONG NextSibling,
  191. ULONG IndentationLevel
  192. )
  193. /*++
  194. Routine Description:
  195. This routine prints out the ACPI namespace rooted at the given object.
  196. Arguments:
  197. Context - Supplies a pointer to the application context.
  198. Address - Supplies the address of the root object to print.
  199. NextSibling - Supplies an optional pointer where the next sibling pointer
  200. will be returned.
  201. IndentationLevel - Supplies the indentation level to print the object at.
  202. Return Value:
  203. 0 on success.
  204. Returns an error code on failure.
  205. --*/
  206. {
  207. PTYPE_SYMBOL AcpiObjectType;
  208. ULONGLONG ChildListHead;
  209. ULONG ChildListOffset;
  210. PVOID Data;
  211. ULONG DataSize;
  212. ULONG ListEntryOffset;
  213. ULONG Name;
  214. INT Status;
  215. ULONGLONG Value;
  216. //
  217. // Bail out if the indentation seems too deep.
  218. //
  219. if (IndentationLevel > 50) {
  220. return EINVAL;
  221. }
  222. //
  223. // Print out the indentation.
  224. //
  225. DbgOut("%*s", IndentationLevel, "");
  226. Status = DbgReadTypeByName(Context,
  227. Address,
  228. "acpi!ACPI_OBJECT",
  229. &AcpiObjectType,
  230. &Data,
  231. &DataSize);
  232. if (Status != 0) {
  233. DbgOut("Error: Could not read object at 0x%I64x: %s.\n",
  234. Address,
  235. strerror(Status));
  236. goto PrintNamespaceAtRootEnd;
  237. }
  238. //
  239. // Print the object.
  240. //
  241. Status = DbgReadIntegerMember(Context,
  242. AcpiObjectType,
  243. "Name",
  244. Address,
  245. Data,
  246. DataSize,
  247. &Value);
  248. if (Status != 0) {
  249. goto PrintNamespaceAtRootEnd;
  250. }
  251. Name = Value;
  252. DbgOut("%08I64x %c%c%c%c ",
  253. Address,
  254. (UCHAR)Name,
  255. (UCHAR)(Name >> 8),
  256. (UCHAR)(Name >> 16),
  257. (UCHAR)(Name >> 24));
  258. Status = DbgPrintTypeMember(Context,
  259. Address,
  260. Data,
  261. DataSize,
  262. AcpiObjectType,
  263. "Type",
  264. 0,
  265. 0);
  266. if (Status != 0) {
  267. goto PrintNamespaceAtRootEnd;
  268. }
  269. DbgOut(" ");
  270. Status = DbgReadIntegerMember(Context,
  271. AcpiObjectType,
  272. "Type",
  273. Address,
  274. Data,
  275. DataSize,
  276. &Value);
  277. switch (Value) {
  278. case AcpiObjectInteger:
  279. DbgOut("Value: ");
  280. Status = DbgPrintTypeMember(Context,
  281. Address,
  282. Data,
  283. DataSize,
  284. AcpiObjectType,
  285. "U.Integer.Value",
  286. 0,
  287. 0);
  288. break;
  289. case AcpiObjectString:
  290. DbgOut("Address: ");
  291. Status = DbgPrintTypeMember(Context,
  292. Address,
  293. Data,
  294. DataSize,
  295. AcpiObjectType,
  296. "U.String.String",
  297. 0,
  298. 0);
  299. break;
  300. case AcpiObjectBuffer:
  301. Status = DbgPrintTypeMember(Context,
  302. Address,
  303. Data,
  304. DataSize,
  305. AcpiObjectType,
  306. "U.Buffer.Buffer",
  307. 0,
  308. 0);
  309. if (Status != 0) {
  310. break;
  311. }
  312. DbgOut(" Length: ");
  313. Status = DbgPrintTypeMember(Context,
  314. Address,
  315. Data,
  316. DataSize,
  317. AcpiObjectType,
  318. "U.Buffer.Length",
  319. 0,
  320. 0);
  321. break;
  322. case AcpiObjectPackage:
  323. Status = DbgPrintTypeMember(Context,
  324. Address,
  325. Data,
  326. DataSize,
  327. AcpiObjectType,
  328. "U.Package.Array",
  329. 0,
  330. 0);
  331. if (Status != 0) {
  332. break;
  333. }
  334. DbgOut(" Count: ");
  335. Status = DbgPrintTypeMember(Context,
  336. Address,
  337. Data,
  338. DataSize,
  339. AcpiObjectType,
  340. "U.Package.ElementCount",
  341. 0,
  342. 0);
  343. break;
  344. case AcpiObjectFieldUnit:
  345. DbgOut("OpRegion ");
  346. Status = DbgPrintTypeMember(Context,
  347. Address,
  348. Data,
  349. DataSize,
  350. AcpiObjectType,
  351. "U.FieldUnit.OperationRegion",
  352. 0,
  353. 0);
  354. if (Status != 0) {
  355. break;
  356. }
  357. DbgOut(" ( ");
  358. Status = DbgPrintTypeMember(Context,
  359. Address,
  360. Data,
  361. DataSize,
  362. AcpiObjectType,
  363. "U.FieldUnit.BitOffset",
  364. 0,
  365. 0);
  366. if (Status != 0) {
  367. break;
  368. }
  369. DbgOut(", ");
  370. Status = DbgPrintTypeMember(Context,
  371. Address,
  372. Data,
  373. DataSize,
  374. AcpiObjectType,
  375. "U.FieldUnit.BitLength",
  376. 0,
  377. 0);
  378. DbgOut(")");
  379. break;
  380. case AcpiObjectMethod:
  381. DbgOut("Args: ");
  382. Status = DbgPrintTypeMember(Context,
  383. Address,
  384. Data,
  385. DataSize,
  386. AcpiObjectType,
  387. "U.Method.ArgumentCount",
  388. 0,
  389. 0);
  390. if (Status != 0) {
  391. break;
  392. }
  393. DbgOut(", at ");
  394. Status = DbgPrintTypeMember(Context,
  395. Address,
  396. Data,
  397. DataSize,
  398. AcpiObjectType,
  399. "U.Method.AmlCode",
  400. 0,
  401. 0);
  402. if (Status != 0) {
  403. break;
  404. }
  405. DbgOut(" length ");
  406. Status = DbgPrintTypeMember(Context,
  407. Address,
  408. Data,
  409. DataSize,
  410. AcpiObjectType,
  411. "U.Method.AmlCodeSize",
  412. 0,
  413. 0);
  414. break;
  415. case AcpiObjectOperationRegion:
  416. DbgOut("(");
  417. Status = DbgPrintTypeMember(Context,
  418. Address,
  419. Data,
  420. DataSize,
  421. AcpiObjectType,
  422. "U.OperationRegion.Space",
  423. 0,
  424. 0);
  425. if (Status != 0) {
  426. break;
  427. }
  428. DbgOut(", ");
  429. Status = DbgPrintTypeMember(Context,
  430. Address,
  431. Data,
  432. DataSize,
  433. AcpiObjectType,
  434. "U.OperationRegion.Offset",
  435. 0,
  436. 0);
  437. if (Status != 0) {
  438. break;
  439. }
  440. DbgOut(", ");
  441. Status = DbgPrintTypeMember(Context,
  442. Address,
  443. Data,
  444. DataSize,
  445. AcpiObjectType,
  446. "U.OperationRegion.Length",
  447. 0,
  448. 0);
  449. if (Status != 0) {
  450. break;
  451. }
  452. DbgOut(")");
  453. break;
  454. case AcpiObjectBufferField:
  455. DbgOut("Destination Object: ");
  456. Status = DbgPrintTypeMember(Context,
  457. Address,
  458. Data,
  459. DataSize,
  460. AcpiObjectType,
  461. "U.BufferField.DestinationObject",
  462. 0,
  463. 0);
  464. if (Status != 0) {
  465. break;
  466. }
  467. DbgOut(", Bit Offset: ");
  468. Status = DbgPrintTypeMember(Context,
  469. Address,
  470. Data,
  471. DataSize,
  472. AcpiObjectType,
  473. "U.BufferField.BitOffset",
  474. 0,
  475. 0);
  476. if (Status != 0) {
  477. break;
  478. }
  479. DbgOut(", Bit Length ");
  480. Status = DbgPrintTypeMember(Context,
  481. Address,
  482. Data,
  483. DataSize,
  484. AcpiObjectType,
  485. "U.BufferField.BitLength",
  486. 0,
  487. 0);
  488. if (Status != 0) {
  489. break;
  490. }
  491. break;
  492. case AcpiObjectAlias:
  493. DbgOut("Destination: ");
  494. Status = DbgPrintTypeMember(Context,
  495. Address,
  496. Data,
  497. DataSize,
  498. AcpiObjectType,
  499. "U.Alias.DestinationObject",
  500. 0,
  501. 0);
  502. break;
  503. default:
  504. break;
  505. }
  506. DbgOut("\n");
  507. if (Status != 0) {
  508. goto PrintNamespaceAtRootEnd;
  509. }
  510. //
  511. // Get offsets into the structure for the list head and list entries.
  512. //
  513. IndentationLevel += 1;
  514. Status = DbgGetMemberOffset(AcpiObjectType,
  515. "ChildListHead",
  516. &ChildListOffset,
  517. NULL);
  518. if (Status != 0) {
  519. goto PrintNamespaceAtRootEnd;
  520. }
  521. ChildListHead = Address + (ChildListOffset / BITS_PER_BYTE);
  522. Status = DbgGetMemberOffset(AcpiObjectType,
  523. "SiblingListEntry",
  524. &ListEntryOffset,
  525. NULL);
  526. if (Status != 0) {
  527. goto PrintNamespaceAtRootEnd;
  528. }
  529. ListEntryOffset /= BITS_PER_BYTE;
  530. //
  531. // Read the sibling list entry's next pointer for the caller.
  532. //
  533. if (NextSibling != NULL) {
  534. Status = DbgReadIntegerMember(Context,
  535. AcpiObjectType,
  536. "SiblingListEntry.Next",
  537. Address,
  538. Data,
  539. DataSize,
  540. NextSibling);
  541. if (Status != 0) {
  542. goto PrintNamespaceAtRootEnd;
  543. }
  544. }
  545. //
  546. // Read the first element on the child list.
  547. //
  548. Status = DbgReadIntegerMember(Context,
  549. AcpiObjectType,
  550. "ChildListHead.Next",
  551. Address,
  552. Data,
  553. DataSize,
  554. &Address);
  555. free(Data);
  556. Data = NULL;
  557. //
  558. // Loop printing all children.
  559. //
  560. while (Address != ChildListHead) {
  561. Address -= ListEntryOffset;
  562. Status = ExtpPrintNamespaceAtRoot(Context,
  563. Address,
  564. &Address,
  565. IndentationLevel);
  566. if (Status != 0) {
  567. goto PrintNamespaceAtRootEnd;
  568. }
  569. }
  570. PrintNamespaceAtRootEnd:
  571. if (Data != NULL) {
  572. free(Data);
  573. }
  574. return Status;
  575. }