reslist.c 62 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503
  1. /*++
  2. Copyright (c) 2012 Minoca Corp. All Rights Reserved
  3. Module Name:
  4. reslist.c
  5. Abstract:
  6. This module implements resource list debugger extensions.
  7. Author:
  8. Evan Green 12-Dec-2012
  9. Environment:
  10. Debug Client
  11. --*/
  12. //
  13. // ------------------------------------------------------------------- Includes
  14. //
  15. #include <minoca/kernel/kernel.h>
  16. #include <minoca/debug/dbgext.h>
  17. #include "../../kernel/io/arb.h"
  18. #include <assert.h>
  19. #include <errno.h>
  20. #include <stdio.h>
  21. #include <stdlib.h>
  22. #include <string.h>
  23. //
  24. // ---------------------------------------------------------------- Definitions
  25. //
  26. #define MALLOC(_x) malloc(_x)
  27. #define FREE(_x) free(_x)
  28. //
  29. // ------------------------------------------------------ Data Type Definitions
  30. //
  31. //
  32. // ----------------------------------------------- Internal Function Prototypes
  33. //
  34. BOOL
  35. ExtpPrintDeviceResources (
  36. PDEBUGGER_CONTEXT Context,
  37. ULONGLONG Address,
  38. ULONG IndentationLevel
  39. );
  40. BOOL
  41. ExtpPrintResourceConfigurationList (
  42. PDEBUGGER_CONTEXT Context,
  43. ULONGLONG Address,
  44. ULONG IndentationLevel
  45. );
  46. BOOL
  47. ExtpPrintResourceRequirementList (
  48. PDEBUGGER_CONTEXT Context,
  49. ULONGLONG Address,
  50. ULONG IndentationLevel
  51. );
  52. BOOL
  53. ExtpPrintResourceRequirement (
  54. PDEBUGGER_CONTEXT Context,
  55. ULONGLONG Address,
  56. ULONG IndentationLevel
  57. );
  58. BOOL
  59. ExtpPrintResourceAllocationList (
  60. PDEBUGGER_CONTEXT Context,
  61. ULONGLONG Address,
  62. ULONG IndentationLevel
  63. );
  64. BOOL
  65. ExtpPrintResourceAllocation (
  66. PDEBUGGER_CONTEXT Context,
  67. ULONGLONG Address,
  68. ULONG IndentationLevel
  69. );
  70. BOOL
  71. ExtpPrintDeviceArbiters (
  72. PDEBUGGER_CONTEXT Context,
  73. ULONGLONG Address,
  74. ULONG IndentationLevel
  75. );
  76. BOOL
  77. ExtpPrintResourceArbiter (
  78. PDEBUGGER_CONTEXT Context,
  79. ULONGLONG Address,
  80. ULONG IndentationLevel
  81. );
  82. BOOL
  83. ExtpPrintArbiterEntry (
  84. PDEBUGGER_CONTEXT Context,
  85. ULONGLONG Address,
  86. ULONG IndentationLevel
  87. );
  88. PSTR
  89. ExtpGetResourceTypeString (
  90. RESOURCE_TYPE Type
  91. );
  92. //
  93. // -------------------------------------------------------------------- Globals
  94. //
  95. //
  96. // ------------------------------------------------------------------ Functions
  97. //
  98. INT
  99. ExtResource (
  100. PDEBUGGER_CONTEXT Context,
  101. PSTR Command,
  102. ULONG ArgumentCount,
  103. PSTR *ArgumentValues
  104. )
  105. /*++
  106. Routine Description:
  107. This routine implements the resource related debugger extension.
  108. Arguments:
  109. Context - Supplies a pointer to the debugger applicaton context, which is
  110. an argument to most of the API functions.
  111. Command - Supplies a pointer to the subcommand string.
  112. ArgumentCount - Supplies the number of arguments in the ArgumentValues
  113. array.
  114. ArgumentValues - Supplies the values of each argument. This memory will be
  115. reused when the function returns, so extensions must not touch this
  116. memory after returning from this call.
  117. Return Value:
  118. 0 if the debugger extension command was successful.
  119. Returns an error code if a failure occurred along the way.
  120. --*/
  121. {
  122. ULONGLONG Address;
  123. ULONG ArgumentIndex;
  124. INT Result;
  125. Address = 0;
  126. if (Command == NULL) {
  127. DbgOut("Error: Supply a subcommand. Valid subcommands are:\n"
  128. " !res.dev\n !res.req\n !res.reqlist\n "
  129. "!res.conflist\n !res.alloc\n !res.alloclist\n "
  130. "!res.arb\n !res.devarbs\n !res.arbentry\n");
  131. return EINVAL;
  132. }
  133. //
  134. // At least one parameter is required.
  135. //
  136. if (ArgumentCount < 2) {
  137. DbgOut("Error: Supply an address to dump.\n");
  138. } else {
  139. //
  140. // Loop through each argument, evaluate the address, and print the
  141. // namespace tree at that object.
  142. //
  143. for (ArgumentIndex = 1;
  144. ArgumentIndex < ArgumentCount;
  145. ArgumentIndex += 1) {
  146. Result = DbgEvaluate(Context,
  147. ArgumentValues[ArgumentIndex],
  148. &Address);
  149. if (Result != 0) {
  150. DbgOut("Failed to evaluate address at \"%s\".\n",
  151. ArgumentValues[ArgumentIndex]);
  152. return Result;
  153. }
  154. if (strcmp(Command, "dev") == 0) {
  155. ExtpPrintDeviceResources(Context, Address, 0);
  156. } else if (strcmp(Command, "req") == 0) {
  157. ExtpPrintResourceRequirement(Context, Address, 0);
  158. } else if (strcmp(Command, "reqlist") == 0) {
  159. ExtpPrintResourceRequirementList(Context, Address, 0);
  160. } else if (strcmp(Command, "conflist") == 0) {
  161. ExtpPrintResourceConfigurationList(Context, Address, 0);
  162. } else if (strcmp(Command, "alloc") == 0) {
  163. ExtpPrintResourceAllocation(Context, Address, 0);
  164. } else if (strcmp(Command, "alloclist") == 0) {
  165. ExtpPrintResourceAllocationList(Context, Address, 0);
  166. } else if (strcmp(Command, "arbentry") == 0) {
  167. ExtpPrintArbiterEntry(Context, Address, 0);
  168. } else if (strcmp(Command, "arb") == 0) {
  169. ExtpPrintResourceArbiter(Context, Address, 0);
  170. } else if (strcmp(Command, "devarbs") == 0) {
  171. ExtpPrintDeviceArbiters(Context, Address, 0);
  172. } else {
  173. DbgOut("Error: Invalid subcommand. Run !res for detailed"
  174. "usage.\n");
  175. }
  176. if (ArgumentIndex != ArgumentCount - 1) {
  177. DbgOut("\n----\n");
  178. }
  179. }
  180. }
  181. return 0;
  182. }
  183. //
  184. // --------------------------------------------------------- Internal Functions
  185. //
  186. BOOL
  187. ExtpPrintDeviceResources (
  188. PDEBUGGER_CONTEXT Context,
  189. ULONGLONG Address,
  190. ULONG IndentationLevel
  191. )
  192. /*++
  193. Routine Description:
  194. This routine prints out a device's resources.
  195. Arguments:
  196. Context - Supplies a pointer to the application context.
  197. Address - Supplies the address of the devices whose resources should be
  198. dumped.
  199. IndentationLevel - Supplies the indentation level to print the object at.
  200. Return Value:
  201. TRUE on success.
  202. FALSE on failure.
  203. --*/
  204. {
  205. ULONGLONG BootResources;
  206. ULONGLONG BusLocalResources;
  207. PVOID Data;
  208. ULONG DataSize;
  209. ULONGLONG DeviceAddress;
  210. PTYPE_SYMBOL DeviceType;
  211. ULONGLONG HeaderType;
  212. ULONGLONG ProcessorLocalResources;
  213. ULONGLONG ResourceRequirements;
  214. BOOL Result;
  215. ULONGLONG SelectedConfiguration;
  216. INT Status;
  217. Data = NULL;
  218. //
  219. // Bail out if the indentation seems too deep.
  220. //
  221. if (IndentationLevel > 50) {
  222. return FALSE;
  223. }
  224. //
  225. // Print out the indentation.
  226. //
  227. DbgOut("%*s", IndentationLevel, "");
  228. DeviceAddress = Address;
  229. DbgOut("Device %I64x:\n", DeviceAddress);
  230. Status = DbgReadTypeByName(Context,
  231. Address,
  232. "_DEVICE",
  233. &DeviceType,
  234. &Data,
  235. &DataSize);
  236. if (Status != 0) {
  237. DbgOut("Error: Could not read _DEVICE at 0x%I64x\n", Address);
  238. goto PrintDeviceResourcesEnd;
  239. }
  240. Status = DbgReadIntegerMember(Context,
  241. DeviceType,
  242. "Header.Type",
  243. Address,
  244. Data,
  245. DataSize,
  246. &HeaderType);
  247. if (Status != 0) {
  248. goto PrintDeviceResourcesEnd;
  249. }
  250. if (HeaderType != ObjectDevice) {
  251. DbgOut("Object header type %I64d, probably not a device!\n",
  252. HeaderType);
  253. Status = EINVAL;
  254. goto PrintDeviceResourcesEnd;
  255. }
  256. IndentationLevel += 1;
  257. //
  258. // Print the processor resources.
  259. //
  260. DbgOut("%*s", IndentationLevel, "");
  261. Status = DbgReadIntegerMember(Context,
  262. DeviceType,
  263. "ProcessorLocalResources",
  264. Address,
  265. Data,
  266. DataSize,
  267. &ProcessorLocalResources);
  268. if (Status != 0) {
  269. goto PrintDeviceResourcesEnd;
  270. }
  271. if (ProcessorLocalResources == 0) {
  272. DbgOut("No Processor Local Resources.\n");
  273. } else {
  274. DbgOut("Processor Local Resources @ %x\n", ProcessorLocalResources);
  275. ExtpPrintResourceAllocationList(Context,
  276. ProcessorLocalResources,
  277. IndentationLevel);
  278. }
  279. //
  280. // Print the bus local resources.
  281. //
  282. DbgOut("%*s", IndentationLevel, "");
  283. Status = DbgReadIntegerMember(Context,
  284. DeviceType,
  285. "BusLocalResources",
  286. Address,
  287. Data,
  288. DataSize,
  289. &BusLocalResources);
  290. if (Status != 0) {
  291. goto PrintDeviceResourcesEnd;
  292. }
  293. if (BusLocalResources == 0) {
  294. DbgOut("No Bus Local Resources.\n");
  295. } else {
  296. DbgOut("Bus Local Resources @ %x\n", BusLocalResources);
  297. ExtpPrintResourceAllocationList(Context,
  298. BusLocalResources,
  299. IndentationLevel);
  300. }
  301. //
  302. // Print the boot resources.
  303. //
  304. DbgOut("%*s", IndentationLevel, "");
  305. Status = DbgReadIntegerMember(Context,
  306. DeviceType,
  307. "BootResources",
  308. Address,
  309. Data,
  310. DataSize,
  311. &BootResources);
  312. if (Status != 0) {
  313. goto PrintDeviceResourcesEnd;
  314. }
  315. if (BootResources == 0) {
  316. DbgOut("No Boot Resources.\n");
  317. } else {
  318. DbgOut("Boot Resources @ %x\n", BootResources);
  319. ExtpPrintResourceAllocationList(Context,
  320. BootResources,
  321. IndentationLevel);
  322. }
  323. //
  324. // Print the selected configuration.
  325. //
  326. Status = DbgReadIntegerMember(Context,
  327. DeviceType,
  328. "SelectedConfiguration",
  329. Address,
  330. Data,
  331. DataSize,
  332. &SelectedConfiguration);
  333. if (Status != 0) {
  334. goto PrintDeviceResourcesEnd;
  335. }
  336. if (SelectedConfiguration != 0) {
  337. DbgOut("%*s", IndentationLevel, "");
  338. DbgOut("Selected Configuration %x\n", SelectedConfiguration);
  339. }
  340. //
  341. // Print the resource requirements.
  342. //
  343. DbgOut("%*s", IndentationLevel, "");
  344. Status = DbgReadIntegerMember(Context,
  345. DeviceType,
  346. "ResourceRequirements",
  347. Address,
  348. Data,
  349. DataSize,
  350. &ResourceRequirements);
  351. if (Status != 0) {
  352. goto PrintDeviceResourcesEnd;
  353. }
  354. if (ResourceRequirements == 0) {
  355. DbgOut("No Resource Requirements.\n");
  356. } else {
  357. DbgOut("Resource Requirements @ %x\n", ResourceRequirements);
  358. ExtpPrintResourceConfigurationList(Context,
  359. ResourceRequirements,
  360. IndentationLevel);
  361. }
  362. Status = 0;
  363. PrintDeviceResourcesEnd:
  364. if (Data != NULL) {
  365. free(Data);
  366. }
  367. Result = TRUE;
  368. if (Status != 0) {
  369. Result = FALSE;
  370. }
  371. return Result;
  372. }
  373. BOOL
  374. ExtpPrintResourceConfigurationList (
  375. PDEBUGGER_CONTEXT Context,
  376. ULONGLONG Address,
  377. ULONG IndentationLevel
  378. )
  379. /*++
  380. Routine Description:
  381. This routine prints out a resource configuration list.
  382. Arguments:
  383. Context - Supplies a pointer to the application context.
  384. Address - Supplies the address of the resource configuration list to print.
  385. IndentationLevel - Supplies the indentation level to print the object at.
  386. Return Value:
  387. TRUE on success.
  388. FALSE on failure.
  389. --*/
  390. {
  391. ULONGLONG ChildListHead;
  392. ULONGLONG ChildObjectAddress;
  393. PTYPE_SYMBOL ConfigurationListType;
  394. ULONGLONG CurrentEntryAddress;
  395. PVOID Data;
  396. ULONG DataSize;
  397. PTYPE_SYMBOL ListEntryType;
  398. ULONG RequirementHeadOffset;
  399. ULONG RequirementListEntryOffset;
  400. PTYPE_SYMBOL RequirementListType;
  401. BOOL Result;
  402. INT Status;
  403. Data = NULL;
  404. //
  405. // Bail out if the indentation seems too deep.
  406. //
  407. if (IndentationLevel > 50) {
  408. return FALSE;
  409. }
  410. //
  411. // Print out the indentation.
  412. //
  413. DbgOut("%*s", IndentationLevel, "");
  414. DbgOut("Resource Configuration List @ %08I64x\n", Address);
  415. Status = DbgReadTypeByName(Context,
  416. Address,
  417. "_RESOURCE_CONFIGURATION_LIST",
  418. &ConfigurationListType,
  419. &Data,
  420. &DataSize);
  421. if (Status != 0) {
  422. DbgOut("Error: Could not read configuration list at 0x%I64x.\n",
  423. Address);
  424. goto PrintResourceConfigurationListEnd;
  425. }
  426. Status = DbgGetMemberOffset(ConfigurationListType,
  427. "RequirementListListHead",
  428. &RequirementHeadOffset,
  429. NULL);
  430. if (Status != 0) {
  431. goto PrintResourceConfigurationListEnd;
  432. }
  433. RequirementHeadOffset /= BITS_PER_BYTE;
  434. Status = DbgGetTypeByName(Context, "LIST_ENTRY", &ListEntryType);
  435. if (Status != 0) {
  436. goto PrintResourceConfigurationListEnd;
  437. }
  438. Status = DbgGetTypeByName(Context,
  439. "_RESOURCE_REQUIREMENT_LIST",
  440. &RequirementListType);
  441. if (Status != 0) {
  442. goto PrintResourceConfigurationListEnd;
  443. }
  444. Status = DbgGetMemberOffset(RequirementListType,
  445. "ListEntry",
  446. &RequirementListEntryOffset,
  447. NULL);
  448. if (Status != 0) {
  449. goto PrintResourceConfigurationListEnd;
  450. }
  451. RequirementListEntryOffset /= BITS_PER_BYTE;
  452. //
  453. // Print out all children.
  454. //
  455. IndentationLevel += 1;
  456. ChildListHead = Address + RequirementHeadOffset;
  457. Status = DbgReadIntegerMember(Context,
  458. ConfigurationListType,
  459. "RequirementListListHead.Next",
  460. Address,
  461. Data,
  462. DataSize,
  463. &CurrentEntryAddress);
  464. if (Status != 0) {
  465. goto PrintResourceConfigurationListEnd;
  466. }
  467. free(Data);
  468. Data = NULL;
  469. while (CurrentEntryAddress != ChildListHead) {
  470. //
  471. // Read the list entry.
  472. //
  473. assert(Data == NULL);
  474. Status = DbgReadType(Context,
  475. CurrentEntryAddress,
  476. ListEntryType,
  477. &Data,
  478. &DataSize);
  479. if (Status != 0) {
  480. goto PrintResourceConfigurationListEnd;
  481. }
  482. //
  483. // Print the resource requirement list.
  484. //
  485. ChildObjectAddress = CurrentEntryAddress - RequirementListEntryOffset;
  486. Status = ExtpPrintResourceRequirementList(Context,
  487. ChildObjectAddress,
  488. IndentationLevel);
  489. if (Status == FALSE) {
  490. Status = EINVAL;
  491. goto PrintResourceConfigurationListEnd;
  492. }
  493. //
  494. // Move to the next child.
  495. //
  496. Status = DbgReadIntegerMember(Context,
  497. ListEntryType,
  498. "Next",
  499. CurrentEntryAddress,
  500. Data,
  501. DataSize,
  502. &CurrentEntryAddress);
  503. if (Status != 0) {
  504. goto PrintResourceConfigurationListEnd;
  505. }
  506. free(Data);
  507. Data = NULL;
  508. }
  509. PrintResourceConfigurationListEnd:
  510. if (Data != NULL) {
  511. free(Data);
  512. }
  513. Result = TRUE;
  514. if (Status != 0) {
  515. Result = FALSE;
  516. }
  517. return Result;
  518. }
  519. BOOL
  520. ExtpPrintResourceRequirementList (
  521. PDEBUGGER_CONTEXT Context,
  522. ULONGLONG Address,
  523. ULONG IndentationLevel
  524. )
  525. /*++
  526. Routine Description:
  527. This routine prints out a resource requirement list.
  528. Arguments:
  529. Context - Supplies a pointer to the application context.
  530. Address - Supplies the address of the resource requirement list to print.
  531. IndentationLevel - Supplies the indentation level to print the object at.
  532. Return Value:
  533. TRUE on success.
  534. FALSE on failure.
  535. --*/
  536. {
  537. ULONGLONG ChildListHead;
  538. ULONGLONG ChildObjectAddress;
  539. ULONGLONG CurrentEntryAddress;
  540. PVOID Data;
  541. ULONG DataSize;
  542. PTYPE_SYMBOL ListEntryType;
  543. ULONG RequirementEntryOffset;
  544. ULONG RequirementListHeadOffset;
  545. PTYPE_SYMBOL RequirementListType;
  546. PTYPE_SYMBOL RequirementType;
  547. BOOL Result;
  548. INT Status;
  549. //
  550. // Bail out if the indentation seems too deep.
  551. //
  552. if (IndentationLevel > 50) {
  553. return FALSE;
  554. }
  555. //
  556. // Print out the indentation.
  557. //
  558. DbgOut("%*s", IndentationLevel, "");
  559. DbgOut("Resource Requirement List @ %08I64x\n", Address);
  560. Status = DbgReadTypeByName(Context,
  561. Address,
  562. "_RESOURCE_REQUIREMENT_LIST",
  563. &RequirementListType,
  564. &Data,
  565. &DataSize);
  566. if (Status != 0) {
  567. DbgOut("Error: Could not read requirement list at 0x%I64x.\n",
  568. Address);
  569. goto PrintResourceRequirementListEnd;
  570. }
  571. Status = DbgGetMemberOffset(RequirementListType,
  572. "RequirementListHead",
  573. &RequirementListHeadOffset,
  574. NULL);
  575. if (Status != 0) {
  576. goto PrintResourceRequirementListEnd;
  577. }
  578. RequirementListHeadOffset /= BITS_PER_BYTE;
  579. Status = DbgGetTypeByName(Context, "LIST_ENTRY", &ListEntryType);
  580. if (Status != 0) {
  581. goto PrintResourceRequirementListEnd;
  582. }
  583. Status = DbgGetTypeByName(Context,
  584. "_RESOURCE_REQUIREMENT",
  585. &RequirementType);
  586. if (Status != 0) {
  587. goto PrintResourceRequirementListEnd;
  588. }
  589. Status = DbgGetMemberOffset(RequirementType,
  590. "ListEntry",
  591. &RequirementEntryOffset,
  592. NULL);
  593. if (Status != 0) {
  594. goto PrintResourceRequirementListEnd;
  595. }
  596. RequirementEntryOffset /= BITS_PER_BYTE;
  597. //
  598. // Print out all children.
  599. //
  600. IndentationLevel += 1;
  601. ChildListHead = Address + RequirementListHeadOffset;
  602. Status = DbgReadIntegerMember(Context,
  603. RequirementListType,
  604. "RequirementListHead.Next",
  605. Address,
  606. Data,
  607. DataSize,
  608. &CurrentEntryAddress);
  609. if (Status != 0) {
  610. goto PrintResourceRequirementListEnd;
  611. }
  612. free(Data);
  613. Data = NULL;
  614. while (CurrentEntryAddress != ChildListHead) {
  615. //
  616. // Read the list entry.
  617. //
  618. assert(Data == NULL);
  619. Status = DbgReadType(Context,
  620. CurrentEntryAddress,
  621. ListEntryType,
  622. &Data,
  623. &DataSize);
  624. if (Status != 0) {
  625. goto PrintResourceRequirementListEnd;
  626. }
  627. //
  628. // Print the resource requirement list.
  629. //
  630. ChildObjectAddress = CurrentEntryAddress - RequirementEntryOffset;
  631. Result = ExtpPrintResourceRequirement(Context,
  632. ChildObjectAddress,
  633. IndentationLevel);
  634. if (Result == FALSE) {
  635. Status = EINVAL;
  636. goto PrintResourceRequirementListEnd;
  637. }
  638. //
  639. // Move to the next child.
  640. //
  641. Status = DbgReadIntegerMember(Context,
  642. ListEntryType,
  643. "Next",
  644. CurrentEntryAddress,
  645. Data,
  646. DataSize,
  647. &CurrentEntryAddress);
  648. if (Status != 0) {
  649. goto PrintResourceRequirementListEnd;
  650. }
  651. free(Data);
  652. Data = NULL;
  653. }
  654. PrintResourceRequirementListEnd:
  655. if (Data != NULL) {
  656. free(Data);
  657. }
  658. Result = TRUE;
  659. if (Status != 0) {
  660. Result = FALSE;
  661. }
  662. return Result;
  663. }
  664. BOOL
  665. ExtpPrintResourceRequirement (
  666. PDEBUGGER_CONTEXT Context,
  667. ULONGLONG Address,
  668. ULONG IndentationLevel
  669. )
  670. /*++
  671. Routine Description:
  672. This routine prints out a resource requirement.
  673. Arguments:
  674. Context - Supplies a pointer to the application context.
  675. Address - Supplies the address of the resource requirement to print.
  676. IndentationLevel - Supplies the indentation level to print the object at.
  677. Return Value:
  678. TRUE on success.
  679. FALSE on failure.
  680. --*/
  681. {
  682. ULONG AlternativeListEntryOffset;
  683. ULONGLONG ChildListHead;
  684. ULONGLONG ChildObjectAddress;
  685. ULONGLONG CurrentEntryAddress;
  686. PVOID Data;
  687. ULONG DataSize;
  688. ULONGLONG Flags;
  689. PTYPE_SYMBOL ListEntryType;
  690. ULONGLONG RequirementDataSize;
  691. PTYPE_SYMBOL RequirementType;
  692. PSTR ResourceType;
  693. BOOL Result;
  694. INT Status;
  695. ULONGLONG Value;
  696. Data = NULL;
  697. //
  698. // Bail out if the indentation seems too deep.
  699. //
  700. if (IndentationLevel > 50) {
  701. return FALSE;
  702. }
  703. //
  704. // Print out the indentation.
  705. //
  706. DbgOut("%*s", IndentationLevel, "");
  707. Status = DbgReadTypeByName(Context,
  708. Address,
  709. "_RESOURCE_REQUIREMENT",
  710. &RequirementType,
  711. &Data,
  712. &DataSize);
  713. if (Status != 0) {
  714. DbgOut("Error: Could not read requirement at 0x%I64x.\n", Address);
  715. goto PrintResourceRequirementEnd;
  716. }
  717. Status = DbgReadIntegerMember(Context,
  718. RequirementType,
  719. "Type",
  720. Address,
  721. Data,
  722. DataSize,
  723. &Value);
  724. if (Status != 0) {
  725. goto PrintResourceRequirementEnd;
  726. }
  727. ResourceType = ExtpGetResourceTypeString(Value);
  728. DbgOut("%08I64x %16s: Range ", Address, ResourceType);
  729. Status = DbgReadIntegerMember(Context,
  730. RequirementType,
  731. "Minimum",
  732. Address,
  733. Data,
  734. DataSize,
  735. &Value);
  736. if (Status != 0) {
  737. goto PrintResourceRequirementEnd;
  738. }
  739. DbgOut("%08I64x - ", Value);
  740. Status = DbgReadIntegerMember(Context,
  741. RequirementType,
  742. "Maximum",
  743. Address,
  744. Data,
  745. DataSize,
  746. &Value);
  747. if (Status != 0) {
  748. goto PrintResourceRequirementEnd;
  749. }
  750. DbgOut("%08I64x, Len ", Value);
  751. Status = DbgReadIntegerMember(Context,
  752. RequirementType,
  753. "Length",
  754. Address,
  755. Data,
  756. DataSize,
  757. &Value);
  758. if (Status != 0) {
  759. goto PrintResourceRequirementEnd;
  760. }
  761. DbgOut("%08I64x, Align ", Value);
  762. Status = DbgReadIntegerMember(Context,
  763. RequirementType,
  764. "Alignment",
  765. Address,
  766. Data,
  767. DataSize,
  768. &Value);
  769. if (Status != 0) {
  770. goto PrintResourceRequirementEnd;
  771. }
  772. DbgOut("%I64x, Char ", Value);
  773. Status = DbgReadIntegerMember(Context,
  774. RequirementType,
  775. "Characteristics",
  776. Address,
  777. Data,
  778. DataSize,
  779. &Value);
  780. if (Status != 0) {
  781. goto PrintResourceRequirementEnd;
  782. }
  783. DbgOut("%I64x, Flags ", Value);
  784. Status = DbgReadIntegerMember(Context,
  785. RequirementType,
  786. "Flags",
  787. Address,
  788. Data,
  789. DataSize,
  790. &Flags);
  791. if (Status != 0) {
  792. goto PrintResourceRequirementEnd;
  793. }
  794. DbgOut("%I64x", Flags);
  795. Status = DbgReadIntegerMember(Context,
  796. RequirementType,
  797. "OwningRequirement",
  798. Address,
  799. Data,
  800. DataSize,
  801. &Value);
  802. if (Status != 0) {
  803. goto PrintResourceRequirementEnd;
  804. }
  805. if (Value != 0) {
  806. DbgOut(", Owner %I64x", Value);
  807. }
  808. if ((Flags & RESOURCE_FLAG_NOT_SHAREABLE) != 0) {
  809. DbgOut(" NotShared");
  810. }
  811. Status = DbgReadIntegerMember(Context,
  812. RequirementType,
  813. "Provider",
  814. Address,
  815. Data,
  816. DataSize,
  817. &Value);
  818. if (Status != 0) {
  819. goto PrintResourceRequirementEnd;
  820. }
  821. if (Value != 0) {
  822. DbgOut(", Provider %x", Value);
  823. }
  824. Status = DbgReadIntegerMember(Context,
  825. RequirementType,
  826. "DataSize",
  827. Address,
  828. Data,
  829. DataSize,
  830. &RequirementDataSize);
  831. if (Status != 0) {
  832. goto PrintResourceRequirementEnd;
  833. }
  834. if (RequirementDataSize != 0) {
  835. Status = DbgReadIntegerMember(Context,
  836. RequirementType,
  837. "Data",
  838. Address,
  839. Data,
  840. DataSize,
  841. &Value);
  842. if (Status != 0) {
  843. goto PrintResourceRequirementEnd;
  844. }
  845. DbgOut(", Data 0x%I64x Size 0x%I64x", Value, RequirementDataSize);
  846. }
  847. DbgOut("\n");
  848. //
  849. // If the requirement is not linked in, assume it is an alternative and
  850. // don't try to traverse alternatives.
  851. //
  852. Status = DbgReadIntegerMember(Context,
  853. RequirementType,
  854. "ListEntry.Next",
  855. Address,
  856. Data,
  857. DataSize,
  858. &Value);
  859. if (Status != 0) {
  860. goto PrintResourceRequirementEnd;
  861. }
  862. if (Value == 0) {
  863. Status = 0;
  864. goto PrintResourceRequirementEnd;
  865. }
  866. Status = DbgGetTypeByName(Context, "LIST_ENTRY", &ListEntryType);
  867. if (Status != 0) {
  868. goto PrintResourceRequirementEnd;
  869. }
  870. Status = DbgGetMemberOffset(RequirementType,
  871. "AlternativeListEntry",
  872. &AlternativeListEntryOffset,
  873. NULL);
  874. if (Status != 0) {
  875. goto PrintResourceRequirementEnd;
  876. }
  877. AlternativeListEntryOffset /= BITS_PER_BYTE;
  878. //
  879. // Print out all children.
  880. //
  881. IndentationLevel += 1;
  882. ChildListHead = Address + AlternativeListEntryOffset;
  883. Status = DbgReadIntegerMember(Context,
  884. RequirementType,
  885. "AlternativeListEntry.Next",
  886. Address,
  887. Data,
  888. DataSize,
  889. &CurrentEntryAddress);
  890. if (Status != 0) {
  891. goto PrintResourceRequirementEnd;
  892. }
  893. free(Data);
  894. Data = NULL;
  895. while (CurrentEntryAddress != ChildListHead) {
  896. //
  897. // Read the list entry.
  898. //
  899. assert(Data == NULL);
  900. Status = DbgReadType(Context,
  901. CurrentEntryAddress,
  902. ListEntryType,
  903. &Data,
  904. &DataSize);
  905. if (Status != 0) {
  906. goto PrintResourceRequirementEnd;
  907. }
  908. //
  909. // Print the resource requirement alternative.
  910. //
  911. ChildObjectAddress = CurrentEntryAddress - AlternativeListEntryOffset;
  912. Result = ExtpPrintResourceRequirement(Context,
  913. ChildObjectAddress,
  914. IndentationLevel);
  915. if (Result == FALSE) {
  916. Status = EINVAL;
  917. goto PrintResourceRequirementEnd;
  918. }
  919. //
  920. // Move to the next child.
  921. //
  922. Status = DbgReadIntegerMember(Context,
  923. ListEntryType,
  924. "Next",
  925. CurrentEntryAddress,
  926. Data,
  927. DataSize,
  928. &CurrentEntryAddress);
  929. if (Status != 0) {
  930. goto PrintResourceRequirementEnd;
  931. }
  932. free(Data);
  933. Data = NULL;
  934. }
  935. Status = 0;
  936. PrintResourceRequirementEnd:
  937. if (Data != NULL) {
  938. free(Data);
  939. }
  940. Result = TRUE;
  941. if (Status != 0) {
  942. Result = FALSE;
  943. }
  944. return Result;
  945. }
  946. BOOL
  947. ExtpPrintResourceAllocationList (
  948. PDEBUGGER_CONTEXT Context,
  949. ULONGLONG Address,
  950. ULONG IndentationLevel
  951. )
  952. /*++
  953. Routine Description:
  954. This routine prints out a resource allocation list.
  955. Arguments:
  956. Context - Supplies a pointer to the application context.
  957. Address - Supplies the address of the resource allocation list to print.
  958. IndentationLevel - Supplies the indentation level to print the object at.
  959. Return Value:
  960. TRUE on success.
  961. FALSE on failure.
  962. --*/
  963. {
  964. ULONG AllocationEntryOffset;
  965. ULONG AllocationListHeadOffset;
  966. PTYPE_SYMBOL AllocationListType;
  967. PTYPE_SYMBOL AllocationType;
  968. ULONGLONG ChildListHead;
  969. ULONGLONG ChildObjectAddress;
  970. ULONGLONG CurrentEntryAddress;
  971. PVOID Data;
  972. ULONG DataSize;
  973. PTYPE_SYMBOL ListEntryType;
  974. BOOL Result;
  975. INT Status;
  976. Data = NULL;
  977. //
  978. // Bail out if the indentation seems too deep.
  979. //
  980. if (IndentationLevel > 50) {
  981. return FALSE;
  982. }
  983. //
  984. // Print out the indentation.
  985. //
  986. DbgOut("%*s", IndentationLevel, "");
  987. DbgOut("Resource Allocation List @ %08I64x\n", Address);
  988. Status = DbgReadTypeByName(Context,
  989. Address,
  990. "_RESOURCE_ALLOCATION_LIST",
  991. &AllocationListType,
  992. &Data,
  993. &DataSize);
  994. if (Status != 0) {
  995. DbgOut("Error: Could not read allocation list at 0x%I64x.\n", Address);
  996. goto PrintResourceAllocationListEnd;
  997. }
  998. Status = DbgGetMemberOffset(AllocationListType,
  999. "AllocationListHead",
  1000. &AllocationListHeadOffset,
  1001. NULL);
  1002. if (Status != 0) {
  1003. goto PrintResourceAllocationListEnd;
  1004. }
  1005. AllocationListHeadOffset /= BITS_PER_BYTE;
  1006. Status = DbgGetTypeByName(Context, "LIST_ENTRY", &ListEntryType);
  1007. if (Status != 0) {
  1008. goto PrintResourceAllocationListEnd;
  1009. }
  1010. Status = DbgGetTypeByName(Context, "_RESOURCE_ALLOCATION", &AllocationType);
  1011. if (Status != 0) {
  1012. goto PrintResourceAllocationListEnd;
  1013. }
  1014. Status = DbgGetMemberOffset(AllocationType,
  1015. "ListEntry",
  1016. &AllocationEntryOffset,
  1017. NULL);
  1018. if (Status != 0) {
  1019. goto PrintResourceAllocationListEnd;
  1020. }
  1021. //
  1022. // Print out all children.
  1023. //
  1024. IndentationLevel += 1;
  1025. ChildListHead = Address + AllocationListHeadOffset;
  1026. Status = DbgReadIntegerMember(Context,
  1027. AllocationListType,
  1028. "AllocationListHead.Next",
  1029. Address,
  1030. Data,
  1031. DataSize,
  1032. &CurrentEntryAddress);
  1033. if (Status != 0) {
  1034. goto PrintResourceAllocationListEnd;
  1035. }
  1036. free(Data);
  1037. Data = NULL;
  1038. while (CurrentEntryAddress != ChildListHead) {
  1039. //
  1040. // Read the list entry.
  1041. //
  1042. assert(Data == NULL);
  1043. Status = DbgReadType(Context,
  1044. CurrentEntryAddress,
  1045. ListEntryType,
  1046. &Data,
  1047. &DataSize);
  1048. if (Status != 0) {
  1049. goto PrintResourceAllocationListEnd;
  1050. }
  1051. //
  1052. // Print the resource requirement list.
  1053. //
  1054. ChildObjectAddress = CurrentEntryAddress - AllocationEntryOffset;
  1055. Result = ExtpPrintResourceAllocation(Context,
  1056. ChildObjectAddress,
  1057. IndentationLevel);
  1058. if (Result == FALSE) {
  1059. Status = EINVAL;
  1060. goto PrintResourceAllocationListEnd;
  1061. }
  1062. //
  1063. // Move to the next child.
  1064. //
  1065. Status = DbgReadIntegerMember(Context,
  1066. ListEntryType,
  1067. "Next",
  1068. CurrentEntryAddress,
  1069. Data,
  1070. DataSize,
  1071. &CurrentEntryAddress);
  1072. if (Status != 0) {
  1073. goto PrintResourceAllocationListEnd;
  1074. }
  1075. free(Data);
  1076. Data = NULL;
  1077. }
  1078. Status = 0;
  1079. PrintResourceAllocationListEnd:
  1080. if (Data != NULL) {
  1081. free(Data);
  1082. }
  1083. Result = TRUE;
  1084. if (Status != 0) {
  1085. Result = FALSE;
  1086. }
  1087. return Result;
  1088. }
  1089. BOOL
  1090. ExtpPrintResourceAllocation (
  1091. PDEBUGGER_CONTEXT Context,
  1092. ULONGLONG Address,
  1093. ULONG IndentationLevel
  1094. )
  1095. /*++
  1096. Routine Description:
  1097. This routine prints out a resource allocation.
  1098. Arguments:
  1099. Context - Supplies a pointer to the application context.
  1100. Address - Supplies the address of the resource allocation to print.
  1101. IndentationLevel - Supplies the indentation level to print the object at.
  1102. Return Value:
  1103. TRUE on success.
  1104. FALSE on failure.
  1105. --*/
  1106. {
  1107. ULONGLONG AllocationDataSize;
  1108. PTYPE_SYMBOL AllocationType;
  1109. PVOID Data;
  1110. ULONG DataSize;
  1111. PSTR ResourceType;
  1112. BOOL Result;
  1113. INT Status;
  1114. ULONGLONG Value;
  1115. Data = NULL;
  1116. //
  1117. // Bail out if the indentation seems too deep.
  1118. //
  1119. if (IndentationLevel > 50) {
  1120. return FALSE;
  1121. }
  1122. //
  1123. // Print out the indentation.
  1124. //
  1125. DbgOut("%*s", IndentationLevel, "");
  1126. Status = DbgReadTypeByName(Context,
  1127. Address,
  1128. "_RESOURCE_ALLOCATION",
  1129. &AllocationType,
  1130. &Data,
  1131. &DataSize);
  1132. if (Status != 0) {
  1133. DbgOut("Error: Could not read allocation at 0x%I64x.\n",
  1134. Address);
  1135. goto PrintResourceAllocationEnd;
  1136. }
  1137. Status = DbgReadIntegerMember(Context,
  1138. AllocationType,
  1139. "Type",
  1140. Address,
  1141. Data,
  1142. DataSize,
  1143. &Value);
  1144. if (Status != 0) {
  1145. goto PrintResourceAllocationEnd;
  1146. }
  1147. ResourceType = ExtpGetResourceTypeString(Value);
  1148. DbgOut("%08I64x %16s: ", Address, ResourceType);
  1149. Status = DbgReadIntegerMember(Context,
  1150. AllocationType,
  1151. "Allocation",
  1152. Address,
  1153. Data,
  1154. DataSize,
  1155. &Value);
  1156. if (Status != 0) {
  1157. goto PrintResourceAllocationEnd;
  1158. }
  1159. DbgOut("%08I64x, Len ", Value);
  1160. Status = DbgReadIntegerMember(Context,
  1161. AllocationType,
  1162. "Length",
  1163. Address,
  1164. Data,
  1165. DataSize,
  1166. &Value);
  1167. if (Status != 0) {
  1168. goto PrintResourceAllocationEnd;
  1169. }
  1170. DbgOut("%08I64x, Char ", Value);
  1171. Status = DbgReadIntegerMember(Context,
  1172. AllocationType,
  1173. "Characteristics",
  1174. Address,
  1175. Data,
  1176. DataSize,
  1177. &Value);
  1178. if (Status != 0) {
  1179. goto PrintResourceAllocationEnd;
  1180. }
  1181. DbgOut("%I64x", Value);
  1182. Status = DbgReadIntegerMember(Context,
  1183. AllocationType,
  1184. "OwningAllocation",
  1185. Address,
  1186. Data,
  1187. DataSize,
  1188. &Value);
  1189. if (Status != 0) {
  1190. goto PrintResourceAllocationEnd;
  1191. }
  1192. if (Value != 0) {
  1193. DbgOut(", Owner %I64x", Value);
  1194. }
  1195. Status = DbgReadIntegerMember(Context,
  1196. AllocationType,
  1197. "Flags",
  1198. Address,
  1199. Data,
  1200. DataSize,
  1201. &Value);
  1202. if (Status != 0) {
  1203. goto PrintResourceAllocationEnd;
  1204. }
  1205. if ((Value & RESOURCE_FLAG_NOT_SHAREABLE) != 0) {
  1206. DbgOut(" NotShared");
  1207. }
  1208. Status = DbgReadIntegerMember(Context,
  1209. AllocationType,
  1210. "Provider",
  1211. Address,
  1212. Data,
  1213. DataSize,
  1214. &Value);
  1215. if (Status != 0) {
  1216. goto PrintResourceAllocationEnd;
  1217. }
  1218. if (Value != 0) {
  1219. DbgOut(", Provider %I64x", Value);
  1220. }
  1221. Status = DbgReadIntegerMember(Context,
  1222. AllocationType,
  1223. "DataSize",
  1224. Address,
  1225. Data,
  1226. DataSize,
  1227. &AllocationDataSize);
  1228. if (Status != 0) {
  1229. goto PrintResourceAllocationEnd;
  1230. }
  1231. if (AllocationDataSize != 0) {
  1232. Status = DbgReadIntegerMember(Context,
  1233. AllocationType,
  1234. "Data",
  1235. Address,
  1236. Data,
  1237. DataSize,
  1238. &Value);
  1239. if (Status != 0) {
  1240. goto PrintResourceAllocationEnd;
  1241. }
  1242. DbgOut(", Data %I64x Size 0x%I64x", Value, AllocationDataSize);
  1243. }
  1244. Status = 0;
  1245. PrintResourceAllocationEnd:
  1246. if (Data != NULL) {
  1247. free(Data);
  1248. }
  1249. Result = TRUE;
  1250. if (Status != 0) {
  1251. Result = FALSE;
  1252. }
  1253. DbgOut("\n");
  1254. return Result;
  1255. }
  1256. BOOL
  1257. ExtpPrintDeviceArbiters (
  1258. PDEBUGGER_CONTEXT Context,
  1259. ULONGLONG Address,
  1260. ULONG IndentationLevel
  1261. )
  1262. /*++
  1263. Routine Description:
  1264. This routine prints out the resource arbiters associated with a device.
  1265. Arguments:
  1266. Context - Supplies a pointer to the application context.
  1267. Address - Supplies the address of the device whose arbiters should be
  1268. dumped.
  1269. IndentationLevel - Supplies the indentation level to print the object at.
  1270. Return Value:
  1271. TRUE on success.
  1272. FALSE on failure.
  1273. --*/
  1274. {
  1275. ULONG ArbiterIndex;
  1276. ULONG ArbiterListEntryOffset;
  1277. ULONG ArbiterListHeadOffset;
  1278. PTYPE_SYMBOL ArbiterType;
  1279. ULONGLONG ChildListHead;
  1280. ULONGLONG ChildObjectAddress;
  1281. ULONGLONG CurrentEntryAddress;
  1282. PVOID Data;
  1283. ULONG DataSize;
  1284. ULONGLONG DeviceAddress;
  1285. ULONGLONG DeviceParentAddress;
  1286. PTYPE_SYMBOL DeviceType;
  1287. ULONGLONG HeaderType;
  1288. PVOID ListEntryData;
  1289. ULONG ListEntryDataSize;
  1290. PTYPE_SYMBOL ListEntryType;
  1291. ULONGLONG NextParent;
  1292. ULONGLONG OriginalDeviceAddress;
  1293. ULONGLONG ResourceType;
  1294. BOOL Result;
  1295. INT Status;
  1296. ChildObjectAddress = 0;
  1297. Data = NULL;
  1298. ListEntryData = NULL;
  1299. //
  1300. // Bail out if the indentation seems too deep.
  1301. //
  1302. if (IndentationLevel > 50) {
  1303. return FALSE;
  1304. }
  1305. //
  1306. // Print out the indentation.
  1307. //
  1308. DbgOut("%*s", IndentationLevel, "");
  1309. //
  1310. // Get the parent of the current device.
  1311. //
  1312. OriginalDeviceAddress = Address;
  1313. Status = DbgReadTypeByName(Context,
  1314. Address,
  1315. "_DEVICE",
  1316. &DeviceType,
  1317. &Data,
  1318. &DataSize);
  1319. if (Status != 0) {
  1320. DbgOut("Failed to read device at %I64x.\n", Address);
  1321. goto PrintDeviceArbitersEnd;
  1322. }
  1323. Status = DbgGetMemberOffset(DeviceType,
  1324. "ArbiterListHead",
  1325. &ArbiterListHeadOffset,
  1326. NULL);
  1327. if (Status != 0) {
  1328. goto PrintDeviceArbitersEnd;
  1329. }
  1330. ArbiterListHeadOffset /= BITS_PER_BYTE;
  1331. Status = DbgGetTypeByName(Context, "LIST_ENTRY", &ListEntryType);
  1332. if (Status != 0) {
  1333. goto PrintDeviceArbitersEnd;
  1334. }
  1335. Status = DbgGetTypeByName(Context, "_RESOURCE_ARBITER", &ArbiterType);
  1336. if (Status != 0) {
  1337. goto PrintDeviceArbitersEnd;
  1338. }
  1339. Status = DbgGetMemberOffset(ArbiterType,
  1340. "ListEntry",
  1341. &ArbiterListEntryOffset,
  1342. NULL);
  1343. if (Status != 0) {
  1344. goto PrintDeviceArbitersEnd;
  1345. }
  1346. Status = DbgReadIntegerMember(Context,
  1347. DeviceType,
  1348. "Header.Type",
  1349. Address,
  1350. Data,
  1351. DataSize,
  1352. &HeaderType);
  1353. if (Status != 0) {
  1354. goto PrintDeviceArbitersEnd;
  1355. }
  1356. if (HeaderType != ObjectDevice) {
  1357. DbgOut("Object header type %I64d, probably not a device!\n",
  1358. HeaderType);
  1359. return FALSE;
  1360. }
  1361. Status = DbgReadIntegerMember(Context,
  1362. DeviceType,
  1363. "ParentDevice",
  1364. Address,
  1365. Data,
  1366. DataSize,
  1367. &DeviceParentAddress);
  1368. if (Status != 0) {
  1369. goto PrintDeviceArbitersEnd;
  1370. }
  1371. DbgOut("Arbiters for device %I64x (parent %I64x):\n",
  1372. OriginalDeviceAddress,
  1373. DeviceParentAddress);
  1374. free(Data);
  1375. Data = NULL;
  1376. //
  1377. // Attempt to find each arbiter.
  1378. //
  1379. IndentationLevel += 1;
  1380. for (ArbiterIndex = 1; ArbiterIndex < ArbiterTypeCount; ArbiterIndex += 1) {
  1381. //
  1382. // Start at the original device address and look through all its
  1383. // arbiters.
  1384. //
  1385. DeviceAddress = DeviceParentAddress;
  1386. while (TRUE) {
  1387. assert(Data == NULL);
  1388. Status = DbgReadType(Context,
  1389. DeviceAddress,
  1390. DeviceType,
  1391. &Data,
  1392. &DataSize);
  1393. if (Status != 0) {
  1394. DbgOut("Failed to read device at %I64x.\n", DeviceAddress);
  1395. goto PrintDeviceArbitersEnd;
  1396. }
  1397. Status = DbgReadIntegerMember(Context,
  1398. DeviceType,
  1399. "Header.Type",
  1400. DeviceAddress,
  1401. Data,
  1402. DataSize,
  1403. &HeaderType);
  1404. if (Status != 0) {
  1405. goto PrintDeviceArbitersEnd;
  1406. }
  1407. if (HeaderType != ObjectDevice) {
  1408. DbgOut("Object header type %I64d, probably not a device!\n",
  1409. HeaderType);
  1410. Status = EINVAL;
  1411. goto PrintDeviceArbitersEnd;
  1412. }
  1413. Status = DbgReadIntegerMember(Context,
  1414. DeviceType,
  1415. "ParentDevice",
  1416. Address,
  1417. Data,
  1418. DataSize,
  1419. &NextParent);
  1420. if (Status != 0) {
  1421. goto PrintDeviceArbitersEnd;
  1422. }
  1423. //
  1424. // Loop through every arbiter in the device.
  1425. //
  1426. ChildListHead = DeviceAddress + ArbiterListHeadOffset;
  1427. Status = DbgReadIntegerMember(Context,
  1428. DeviceType,
  1429. "ArbiterListHead.Next",
  1430. DeviceAddress,
  1431. Data,
  1432. DataSize,
  1433. &CurrentEntryAddress);
  1434. if (Status != 0) {
  1435. goto PrintDeviceArbitersEnd;
  1436. }
  1437. free(Data);
  1438. Data = NULL;
  1439. while (CurrentEntryAddress != ChildListHead) {
  1440. //
  1441. // Read the list entry.
  1442. //
  1443. assert(ListEntryData == NULL);
  1444. Status = DbgReadType(Context,
  1445. CurrentEntryAddress,
  1446. ListEntryType,
  1447. &ListEntryData,
  1448. &ListEntryDataSize);
  1449. if (Status != 0) {
  1450. goto PrintDeviceArbitersEnd;
  1451. }
  1452. //
  1453. // Read in the arbiter.
  1454. //
  1455. ChildObjectAddress =
  1456. CurrentEntryAddress - ArbiterListEntryOffset;
  1457. assert(Data == NULL);
  1458. Status = DbgReadType(Context,
  1459. ChildObjectAddress,
  1460. ArbiterType,
  1461. &Data,
  1462. &DataSize);
  1463. if (Status != 0) {
  1464. DbgOut("Error: Could not read arbiter at 0x%I64x.\n",
  1465. ChildObjectAddress);
  1466. goto PrintDeviceArbitersEnd;
  1467. }
  1468. Status = DbgReadIntegerMember(Context,
  1469. ArbiterType,
  1470. "ResourceType",
  1471. ChildObjectAddress,
  1472. Data,
  1473. DataSize,
  1474. &ResourceType);
  1475. if (Status != 0) {
  1476. goto PrintDeviceArbitersEnd;
  1477. }
  1478. free(Data);
  1479. Data = NULL;
  1480. //
  1481. // Stop looking if this arbiter is the right type.
  1482. //
  1483. if (ResourceType == ArbiterIndex) {
  1484. free(ListEntryData);
  1485. ListEntryData = NULL;
  1486. break;
  1487. }
  1488. //
  1489. // Move to the next entry.
  1490. //
  1491. Status = DbgReadIntegerMember(Context,
  1492. ListEntryType,
  1493. "Next",
  1494. CurrentEntryAddress,
  1495. ListEntryData,
  1496. ListEntryDataSize,
  1497. &CurrentEntryAddress);
  1498. if (Status != 0) {
  1499. goto PrintDeviceArbitersEnd;
  1500. }
  1501. free(ListEntryData);
  1502. ListEntryData = NULL;
  1503. }
  1504. //
  1505. // If an arbiter was found, print it out and stop looking for this
  1506. // arbiter type.
  1507. //
  1508. if (CurrentEntryAddress != ChildListHead) {
  1509. ExtpPrintResourceArbiter(Context,
  1510. ChildObjectAddress,
  1511. IndentationLevel);
  1512. break;
  1513. }
  1514. //
  1515. // No arbiter was found in this device, so move to the parent
  1516. // device.
  1517. //
  1518. DeviceAddress = NextParent;
  1519. if (DeviceAddress == 0) {
  1520. DbgOut("Could not find %s arbiter.\n",
  1521. ExtpGetResourceTypeString(ArbiterIndex));
  1522. break;
  1523. }
  1524. }
  1525. }
  1526. PrintDeviceArbitersEnd:
  1527. if (Data != NULL) {
  1528. free(Data);
  1529. }
  1530. if (ListEntryData != NULL) {
  1531. free(ListEntryData);
  1532. }
  1533. Result = TRUE;
  1534. if (Status != 0) {
  1535. Result = FALSE;
  1536. }
  1537. return Result;
  1538. }
  1539. BOOL
  1540. ExtpPrintResourceArbiter (
  1541. PDEBUGGER_CONTEXT Context,
  1542. ULONGLONG Address,
  1543. ULONG IndentationLevel
  1544. )
  1545. /*++
  1546. Routine Description:
  1547. This routine prints out a resource arbiter.
  1548. Arguments:
  1549. Context - Supplies a pointer to the application context.
  1550. Address - Supplies the address of the arbiter to print.
  1551. IndentationLevel - Supplies the indentation level to print the object at.
  1552. Return Value:
  1553. TRUE on success.
  1554. FALSE on failure.
  1555. --*/
  1556. {
  1557. ULONG ArbiterEntryListHeadOffset;
  1558. ULONG ArbiterEntryOffset;
  1559. PTYPE_SYMBOL ArbiterType;
  1560. ULONGLONG ChildListHead;
  1561. ULONGLONG ChildObjectAddress;
  1562. ULONGLONG CurrentEntryAddress;
  1563. PVOID Data;
  1564. ULONG DataSize;
  1565. PTYPE_SYMBOL ListEntryType;
  1566. PSTR ResourceType;
  1567. BOOL Result;
  1568. INT Status;
  1569. ULONGLONG Value;
  1570. //
  1571. // Bail out if the indentation seems too deep.
  1572. //
  1573. if (IndentationLevel > 50) {
  1574. return FALSE;
  1575. }
  1576. //
  1577. // Print out the indentation.
  1578. //
  1579. DbgOut("%*s", IndentationLevel, "");
  1580. Status = DbgReadTypeByName(Context,
  1581. Address,
  1582. "_RESOURCE_ARBITER",
  1583. &ArbiterType,
  1584. &Data,
  1585. &DataSize);
  1586. if (Status != 0) {
  1587. DbgOut("Failed to read _RESOURCE_ARBITER at %I64x.\n", Address);
  1588. goto PrintResourceArbiterEnd;
  1589. }
  1590. Status = DbgReadIntegerMember(Context,
  1591. ArbiterType,
  1592. "ResourceType",
  1593. Address,
  1594. Data,
  1595. DataSize,
  1596. &Value);
  1597. if (Status != 0) {
  1598. goto PrintResourceArbiterEnd;
  1599. }
  1600. ResourceType = ExtpGetResourceTypeString(Value);
  1601. DbgOut("%s Arbiter @ 0x%I64x owned by device ", ResourceType, Address);
  1602. Status = DbgReadIntegerMember(Context,
  1603. ArbiterType,
  1604. "OwningDevice",
  1605. Address,
  1606. Data,
  1607. DataSize,
  1608. &Value);
  1609. if (Status != 0) {
  1610. goto PrintResourceArbiterEnd;
  1611. }
  1612. DbgOut("0x%I64x\n", Value);
  1613. Status = DbgGetMemberOffset(ArbiterType,
  1614. "EntryListHead",
  1615. &ArbiterEntryListHeadOffset,
  1616. NULL);
  1617. if (Status != 0) {
  1618. goto PrintResourceArbiterEnd;
  1619. }
  1620. ArbiterEntryListHeadOffset /= BITS_PER_BYTE;
  1621. Status = DbgGetMemberOffset(ArbiterType,
  1622. "ListEntry",
  1623. &ArbiterEntryOffset,
  1624. NULL);
  1625. if (Status != 0) {
  1626. goto PrintResourceArbiterEnd;
  1627. }
  1628. ArbiterEntryOffset /= BITS_PER_BYTE;
  1629. Status = DbgGetTypeByName(Context, "LIST_ENTRY", &ListEntryType);
  1630. if (Status != 0) {
  1631. goto PrintResourceArbiterEnd;
  1632. }
  1633. //
  1634. // Print out all entries.
  1635. //
  1636. IndentationLevel += 1;
  1637. ChildListHead = Address + ArbiterEntryListHeadOffset;
  1638. Status = DbgReadIntegerMember(Context,
  1639. ArbiterType,
  1640. "EntryListHead.Next",
  1641. Address,
  1642. Data,
  1643. DataSize,
  1644. &CurrentEntryAddress);
  1645. if (Status != 0) {
  1646. goto PrintResourceArbiterEnd;
  1647. }
  1648. free(Data);
  1649. Data = NULL;
  1650. while (CurrentEntryAddress != ChildListHead) {
  1651. //
  1652. // Read the list entry.
  1653. //
  1654. assert(Data == NULL);
  1655. Status = DbgReadType(Context,
  1656. CurrentEntryAddress,
  1657. ListEntryType,
  1658. &Data,
  1659. &DataSize);
  1660. if (Status != 0) {
  1661. goto PrintResourceArbiterEnd;
  1662. }
  1663. //
  1664. // Print the arbiter entry.
  1665. //
  1666. ChildObjectAddress = CurrentEntryAddress - ArbiterEntryOffset;
  1667. Result = ExtpPrintArbiterEntry(Context,
  1668. ChildObjectAddress,
  1669. IndentationLevel);
  1670. if (Result == FALSE) {
  1671. Status = EINVAL;
  1672. goto PrintResourceArbiterEnd;
  1673. }
  1674. //
  1675. // Move to the next entry.
  1676. //
  1677. Status = DbgReadIntegerMember(Context,
  1678. ListEntryType,
  1679. "Next",
  1680. CurrentEntryAddress,
  1681. Data,
  1682. DataSize,
  1683. &CurrentEntryAddress);
  1684. if (Status != 0) {
  1685. goto PrintResourceArbiterEnd;
  1686. }
  1687. free(Data);
  1688. Data = NULL;
  1689. }
  1690. Status = 0;
  1691. PrintResourceArbiterEnd:
  1692. if (Data != NULL) {
  1693. free(Data);
  1694. }
  1695. Result = TRUE;
  1696. if (Status != 0) {
  1697. Result = FALSE;
  1698. }
  1699. return Result;
  1700. }
  1701. BOOL
  1702. ExtpPrintArbiterEntry (
  1703. PDEBUGGER_CONTEXT Context,
  1704. ULONGLONG Address,
  1705. ULONG IndentationLevel
  1706. )
  1707. /*++
  1708. Routine Description:
  1709. This routine prints out an arbiter entry.
  1710. Arguments:
  1711. Context - Supplies a pointer to the application context.
  1712. Address - Supplies the address of the arbiter entry to print.
  1713. IndentationLevel - Supplies the indentation level to print the object at.
  1714. Return Value:
  1715. TRUE on success.
  1716. FALSE on failure.
  1717. --*/
  1718. {
  1719. PVOID Data;
  1720. ULONG DataSize;
  1721. PTYPE_SYMBOL EntryType;
  1722. BOOL Result;
  1723. PSTR SpaceType;
  1724. INT Status;
  1725. ULONGLONG Value;
  1726. Data = NULL;
  1727. //
  1728. // Bail out if the indentation seems too deep.
  1729. //
  1730. if (IndentationLevel > 50) {
  1731. return FALSE;
  1732. }
  1733. //
  1734. // Print out the indentation.
  1735. //
  1736. DbgOut("%*s", IndentationLevel, "");
  1737. Status = DbgReadTypeByName(Context,
  1738. Address,
  1739. "_ARBITER_ENTRY",
  1740. &EntryType,
  1741. &Data,
  1742. &DataSize);
  1743. if (Status != 0) {
  1744. DbgOut("Error: Could not read entry at 0x%I64x.\n",
  1745. Address);
  1746. goto PrintArbiterEntryEnd;
  1747. }
  1748. Status = DbgReadIntegerMember(Context,
  1749. EntryType,
  1750. "Type",
  1751. Address,
  1752. Data,
  1753. DataSize,
  1754. &Value);
  1755. if (Status != 0) {
  1756. goto PrintArbiterEntryEnd;
  1757. }
  1758. switch (Value) {
  1759. case ArbiterSpaceInvalid:
  1760. SpaceType = "Invalid";
  1761. break;
  1762. case ArbiterSpaceFree:
  1763. SpaceType = "Free";
  1764. break;
  1765. case ArbiterSpaceReserved:
  1766. SpaceType = "Reserved";
  1767. break;
  1768. case ArbiterSpaceAllocated:
  1769. SpaceType = "Allocated";
  1770. break;
  1771. default:
  1772. SpaceType = "INVALID";
  1773. break;
  1774. }
  1775. DbgOut("%08I64x %9s: ", Address, SpaceType);
  1776. Status = DbgReadIntegerMember(Context,
  1777. EntryType,
  1778. "Allocation",
  1779. Address,
  1780. Data,
  1781. DataSize,
  1782. &Value);
  1783. if (Status != 0) {
  1784. goto PrintArbiterEntryEnd;
  1785. }
  1786. DbgOut("%08I64x, Len ", Value);
  1787. Status = DbgReadIntegerMember(Context,
  1788. EntryType,
  1789. "Length",
  1790. Address,
  1791. Data,
  1792. DataSize,
  1793. &Value);
  1794. if (Status != 0) {
  1795. goto PrintArbiterEntryEnd;
  1796. }
  1797. DbgOut("%08I64x, Char ", Value);
  1798. Status = DbgReadIntegerMember(Context,
  1799. EntryType,
  1800. "Characteristics",
  1801. Address,
  1802. Data,
  1803. DataSize,
  1804. &Value);
  1805. if (Status != 0) {
  1806. goto PrintArbiterEntryEnd;
  1807. }
  1808. DbgOut("%I64x, Requirement ", Value);
  1809. Status = DbgReadIntegerMember(Context,
  1810. EntryType,
  1811. "CorrespondingRequirement",
  1812. Address,
  1813. Data,
  1814. DataSize,
  1815. &Value);
  1816. if (Status != 0) {
  1817. goto PrintArbiterEntryEnd;
  1818. }
  1819. DbgOut("0x%I64x, Device ", Value);
  1820. Status = DbgReadIntegerMember(Context,
  1821. EntryType,
  1822. "Device",
  1823. Address,
  1824. Data,
  1825. DataSize,
  1826. &Value);
  1827. if (Status != 0) {
  1828. goto PrintArbiterEntryEnd;
  1829. }
  1830. DbgOut("0x%I64x", Value);
  1831. Status = DbgReadIntegerMember(Context,
  1832. EntryType,
  1833. "DependentEntry",
  1834. Address,
  1835. Data,
  1836. DataSize,
  1837. &Value);
  1838. if (Status != 0) {
  1839. goto PrintArbiterEntryEnd;
  1840. }
  1841. if (Value != 0) {
  1842. DbgOut(", Dependent %I64x", Value);
  1843. }
  1844. Status = DbgReadIntegerMember(Context,
  1845. EntryType,
  1846. "Flags",
  1847. Address,
  1848. Data,
  1849. DataSize,
  1850. &Value);
  1851. if (Status != 0) {
  1852. goto PrintArbiterEntryEnd;
  1853. }
  1854. if ((Value & RESOURCE_FLAG_NOT_SHAREABLE) != 0) {
  1855. DbgOut(" NotShared");
  1856. }
  1857. if ((Value & RESOURCE_FLAG_BOOT) != 0) {
  1858. DbgOut(" Boot");
  1859. }
  1860. DbgOut("\n");
  1861. PrintArbiterEntryEnd:
  1862. if (Data != NULL) {
  1863. free(Data);
  1864. }
  1865. Result = TRUE;
  1866. if (Status != 0) {
  1867. Result = FALSE;
  1868. }
  1869. return Result;
  1870. }
  1871. PSTR
  1872. ExtpGetResourceTypeString (
  1873. RESOURCE_TYPE Type
  1874. )
  1875. /*++
  1876. Routine Description:
  1877. This routine returns a string representing the given resource type.
  1878. Arguments:
  1879. Type - Supplies the resource type.
  1880. Return Value:
  1881. Returns a pointer to a constant read-only string representing the given
  1882. resource type.
  1883. --*/
  1884. {
  1885. PSTR ResourceType;
  1886. switch (Type) {
  1887. case ResourceTypeInvalid:
  1888. ResourceType = "Invalid";
  1889. break;
  1890. case ResourceTypePhysicalAddressSpace:
  1891. ResourceType = "Physical Address";
  1892. break;
  1893. case ResourceTypeIoPort:
  1894. ResourceType = "I/O Port";
  1895. break;
  1896. case ResourceTypeInterruptLine:
  1897. ResourceType = "Interrupt Line";
  1898. break;
  1899. case ResourceTypeInterruptVector:
  1900. ResourceType = "Interrupt Vector";
  1901. break;
  1902. case ResourceTypeBusNumber:
  1903. ResourceType = "Bus Number";
  1904. break;
  1905. case ResourceTypeDmaChannel:
  1906. ResourceType = "DMA Channel";
  1907. break;
  1908. case ResourceTypeVendorSpecific:
  1909. ResourceType = "Vendor Specific";
  1910. break;
  1911. case ResourceTypeGpio:
  1912. ResourceType = "GPIO";
  1913. break;
  1914. case ResourceTypeSimpleBus:
  1915. ResourceType = "SPB";
  1916. break;
  1917. default:
  1918. ResourceType = "INVALID RESOURCE TYPE";
  1919. break;
  1920. }
  1921. return ResourceType;
  1922. }