Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

483 lines
8.9 KiB

  1. /*++
  2. Copyright (c) 1992-2000 Microsoft Corporation
  3. Module Name:
  4. physical.cpp
  5. Abstract:
  6. Extensions to read/display physocal memory
  7. Environment:
  8. User Mode.
  9. Revision History:
  10. Kshitiz K. Sharma (kksharma) 5/9/2001
  11. --*/
  12. #include "precomp.h"
  13. #pragma hdrstop
  14. ULONG64 g_LastAddress = 0;
  15. /*++
  16. Routine Description:
  17. Dumps specified range of physical memory in given format
  18. Arguments:
  19. Address - Address to start
  20. NumEntries - Number of entries to dump
  21. EntrySize - Size of each entry
  22. ShowAsAscii - print corresponding ascii chars
  23. Return Value:
  24. None.
  25. --*/
  26. BOOL
  27. DumpPhysicalMemory(
  28. ULONG64 Address,
  29. ULONG NumEntries,
  30. ULONG EntrySize,
  31. BOOL ShowAsAscii
  32. )
  33. {
  34. #define NumberBytesToRead 32*4
  35. UCHAR Buffer[NumberBytesToRead];
  36. ULONG ActualRead=0;
  37. if ((EntrySize != 1) && (EntrySize != 2) && (EntrySize != 4) && (EntrySize != 8)) {
  38. EntrySize=4;
  39. }
  40. while (1) {
  41. if (CheckControlC()) {
  42. break;
  43. }
  44. ReadPhysical(Address,Buffer,sizeof(Buffer),&ActualRead);
  45. if (ActualRead != sizeof(Buffer)) {
  46. dprintf("Physical memory read at %I64lx failed\n", Address);
  47. return FALSE;
  48. } else {
  49. PCHAR DumpByte = (PCHAR)&Buffer[0], pRow;
  50. ULONG cnt;
  51. pRow = DumpByte;
  52. for(cnt=0;cnt<NumberBytesToRead;DumpByte+=EntrySize) {
  53. if (!(cnt & 0xf)) {
  54. dprintf("#%8I64lx", Address+cnt);
  55. }
  56. switch (EntrySize) {
  57. case 1:
  58. dprintf("%c%02lx", ((cnt&0xf) == 8 ? '-' : ' '),*((PUCHAR)DumpByte));
  59. break;
  60. case 2:
  61. dprintf(" %04lx", *((PUSHORT) DumpByte));
  62. break;
  63. case 4:
  64. dprintf(" %08lx", *((PULONG) DumpByte));
  65. break;
  66. case 8:
  67. dprintf(" %08lx'%08lx", *((PULONG) DumpByte), *((PULONG) (DumpByte+4)));
  68. break;
  69. }
  70. cnt+=EntrySize, NumEntries--;
  71. if ((cnt && !(cnt & 0xf)) || !NumEntries) {
  72. if (ShowAsAscii) {
  73. char ch;
  74. dprintf(" ");
  75. for (ULONG d=0; d < 16; d++) {
  76. ch = pRow[d];
  77. if (ch < 0x20 || ch > 0x7e) {
  78. ch = '.';
  79. }
  80. dprintf("%c", ch);
  81. }
  82. }
  83. dprintf("\n");
  84. pRow = DumpByte;
  85. }
  86. if (!NumEntries) {
  87. break;
  88. }
  89. }
  90. Address += cnt;
  91. if (!NumEntries) {
  92. break;
  93. }
  94. }
  95. }
  96. g_LastAddress = Address;
  97. return TRUE;
  98. }
  99. /*++
  100. Routine Description:
  101. Reverse sign extension of the value returned by GetExpression()
  102. based on the assumption that no physical address may be bigger
  103. than 0xfffffff00000000.
  104. Arguments:
  105. Val - points to the value to reverse sign extension
  106. Return Value:
  107. None.
  108. --*/
  109. void
  110. ReverseSignExtension(ULONG64* Val)
  111. {
  112. if ((*Val & 0xffffffff00000000) == 0xffffffff00000000)
  113. {
  114. *Val &= 0x00000000ffffffff;
  115. }
  116. }
  117. void
  118. GetPhyDumpArgs(
  119. PCSTR Args,
  120. PULONG64 Address,
  121. PULONG Range
  122. )
  123. {
  124. CHAR Buffer[100]={0};
  125. if(*Args == '\0') {
  126. *Address=g_LastAddress;
  127. } else {
  128. sscanf(Args, "%s", Buffer);
  129. *Address = GetExpression((PCSTR) &Buffer[0]);
  130. ReverseSignExtension(Address);
  131. *Address &= (~0x3); // Truncate to dword boundary
  132. g_LastAddress=*Address;
  133. Args += strlen(&Buffer[0]);
  134. while (*Args && (*Args == ' ' || *Args == '\t')) {
  135. ++Args;
  136. }
  137. if (*Args == 'l' || *Args == 'L') {
  138. ++Args;
  139. *Range = (ULONG) GetExpression(Args);
  140. }
  141. }
  142. return;
  143. }
  144. DECLARE_API( db )
  145. /*++
  146. Routine Description:
  147. Does a read of 16 ULONGS from the physical memory of the target machine
  148. Arguments:
  149. args - Supplies physical address
  150. Return Value:
  151. None.
  152. --*/
  153. {
  154. ULONG64 Address = 0;
  155. ULONG Range = 0;
  156. GetPhyDumpArgs(args, &Address, &Range);
  157. if (!Range) {
  158. Range = 128;
  159. }
  160. DumpPhysicalMemory(Address, Range, 1, TRUE);
  161. return S_OK;
  162. }
  163. DECLARE_API( dd )
  164. /*++
  165. Routine Description:
  166. Does a read of 16 ULONGS from the physical memory of the target machine
  167. Arguments:
  168. args - Supplies physical address
  169. Return Value:
  170. None.
  171. --*/
  172. {
  173. ULONG64 Address = 0;
  174. ULONG Range = 0;
  175. GetPhyDumpArgs(args, &Address, &Range);
  176. if (!Range) {
  177. Range = 32;
  178. }
  179. DumpPhysicalMemory(Address, Range, 4, FALSE);
  180. return S_OK;
  181. }
  182. DECLARE_API( dw )
  183. /*++
  184. Routine Description:
  185. Does a read of 16 ULONGS from the physical memory of the target machine
  186. Arguments:
  187. args - Supplies physical address
  188. Return Value:
  189. None.
  190. --*/
  191. {
  192. ULONG64 Address = 0;
  193. ULONG Range = 0;
  194. GetPhyDumpArgs(args, &Address, &Range);
  195. if (!Range) {
  196. Range = 64;
  197. }
  198. DumpPhysicalMemory(Address, Range, 2, FALSE);
  199. return S_OK;
  200. }
  201. DECLARE_API( dp )
  202. /*++
  203. Routine Description:
  204. Does a read of 16 ULONGS from the physical memory of the target machine
  205. Arguments:
  206. args - Supplies physical address
  207. Return Value:
  208. None.
  209. --*/
  210. {
  211. ULONG64 Address = 0;
  212. ULONG Range = 0;
  213. GetPhyDumpArgs(args, &Address, &Range);
  214. if (!Range) {
  215. Range = IsPtr64() ? 16 : 32;
  216. }
  217. DumpPhysicalMemory(Address, Range, IsPtr64() ? 8 : 4, FALSE);
  218. return S_OK;
  219. }
  220. DECLARE_API( dc )
  221. /*++
  222. Routine Description:
  223. Does a read of N ULONGS from the physical memory of the target machine,
  224. dumping both hex and ASCII.
  225. Arguments:
  226. args - Supplies physical address
  227. Return Value:
  228. None.
  229. --*/
  230. {
  231. ULONG64 Address = 0;
  232. ULONG Range = 0;
  233. GetPhyDumpArgs(args, &Address, &Range);
  234. if (!Range) {
  235. Range = 32;
  236. }
  237. DumpPhysicalMemory(Address, Range, 4, TRUE);
  238. return S_OK;
  239. }
  240. DECLARE_API( du )
  241. /*++
  242. Routine Description:
  243. Does a read of 16 ULONGS from the physical memory of the target machine
  244. Arguments:
  245. args - Supplies physical address
  246. Return Value:
  247. None.
  248. --*/
  249. {
  250. ULONG64 Address = 0;
  251. ULONG Range = 0, ActualRead;
  252. WCHAR Buffer[MAX_PATH]={0};
  253. GetPhyDumpArgs(args, &Address, &Range);
  254. if (Range>MAX_PATH) {
  255. Range = MAX_PATH;
  256. }
  257. if (!Range) {
  258. Range = 16;
  259. }
  260. ReadPhysical(Address,Buffer,Range,&ActualRead);
  261. if (ActualRead != Range) {
  262. dprintf("Physical memory read at %I64lx failed\n", Address);
  263. return FALSE;
  264. } else {
  265. ULONG cnt;
  266. dprintf("#%8I64lx \"", Address);
  267. for (ULONG d=0; d < Range; d++) {
  268. WCHAR ch = Buffer[d];
  269. if (ch < 0x20 || ch > 0x7e) {
  270. ch = '.';
  271. }
  272. dprintf("%wc", ch);
  273. }
  274. dprintf("\"\n", Address);
  275. }
  276. return S_OK;
  277. }
  278. DECLARE_API( ed )
  279. /*++
  280. Routine Description:
  281. Writes a sequence of ULONGs into a given physical address on the
  282. target machine.
  283. Arguments:
  284. arg - Supplies both the target address and the data in the form of
  285. "PHYSICAL_ADDRESS ULONG [ULONG, ULONG,...]"
  286. Return Value:
  287. None.
  288. --*/
  289. {
  290. ULONG64 Address = 0;
  291. ULONG Buffer;
  292. ULONG ActualWritten=0;
  293. PCHAR NextToken;
  294. Address = GetExpression(args);
  295. strtok((PSTR)args," \t,"); // The first token is the address
  296. // Since we're picking off one ULONG at a time, we'll make
  297. // one DbgKdWritePhysicalMemoryAddress call per ULONG. This
  298. // is slow, but easy to code.
  299. while((NextToken=strtok(NULL," \t,")) != NULL) {
  300. if (!sscanf(NextToken,"%lx",&Buffer)) {
  301. break;
  302. }
  303. WritePhysical(Address,&Buffer,sizeof(Buffer),&ActualWritten);
  304. Address+=sizeof(Buffer);
  305. }
  306. return S_OK;
  307. }
  308. DECLARE_API( eb )
  309. /*++
  310. Routine Description:
  311. Writes a sequence of BYTEs into a given physical address on the
  312. target machine.
  313. Arguments:
  314. arg - Supplies both the target address and the data in the form of
  315. "PHYSICAL_ADDRESS ULONG [ULONG, ULONG,...]"
  316. Return Value:
  317. None.
  318. --*/
  319. {
  320. ULONG64 Address = 0;
  321. ULONG Buffer;
  322. UCHAR c;
  323. ULONG ActualWritten;
  324. PCHAR NextToken;
  325. UNREFERENCED_PARAMETER (Client);
  326. Address = GetExpression(args);
  327. strtok((PSTR)args," \t,"); // The first token is the address
  328. // Since we're picking off one BYTE at a time, we'll make
  329. // one DbgKdWritePhysicalMemoryAddress call per BYTE. This
  330. // is slow, but easy to code.
  331. while((NextToken=strtok(NULL," \t,")) != NULL) {
  332. if (!sscanf(NextToken,"%lx",&Buffer)) {
  333. break;
  334. }
  335. c = (UCHAR)Buffer;
  336. WritePhysical(Address,&c,sizeof(UCHAR),&ActualWritten);
  337. Address+=sizeof(UCHAR);
  338. }
  339. return S_OK;
  340. }