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.

609 lines
13 KiB

  1. /*++
  2. Copyright (c) 1992-2001 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. #define PHYS_READ_MATCH_DUMPSIZE 0x100
  15. #define PHYS_FLAG_MESSAGE \
  16. "If you know the caching attributes used for the memory,\n" \
  17. "try specifying [c], [uc] or [wc], as in !dd [c] <params>.\n" \
  18. "WARNING: Incorrect use of these flags will cause unpredictable\n" \
  19. "processor corruption. This may immediately (or at any time in\n" \
  20. "the future until reboot) result in a system hang, incorrect data\n" \
  21. "being displayed or other strange crashes and corruption.\n"
  22. ULONG64 g_LastAddress = 0;
  23. VOID
  24. ReadPhysicalInChunks(
  25. ULONG64 Address,
  26. PUCHAR Buffer,
  27. ULONG BufferSize,
  28. ULONG Flags,
  29. ULONG ChunkSize,
  30. PULONG ActualRead
  31. )
  32. {
  33. if ((Flags & PHYS_READ_MATCH_DUMPSIZE) &&
  34. (ChunkSize != 0)) {
  35. DWORD i, ret;
  36. PUCHAR pReadBuff;
  37. Flags &= 0xf;
  38. for (i=0, pReadBuff = Buffer; i<BufferSize;
  39. i+=ChunkSize, pReadBuff+=ChunkSize) {
  40. ReadPhysicalWithFlags(Address + i,
  41. pReadBuff,ChunkSize,Flags,&ret);
  42. if (ret != ChunkSize) {
  43. break;
  44. }
  45. *ActualRead += ret;
  46. }
  47. } else {
  48. Flags &= 0xf;
  49. ReadPhysicalWithFlags(Address,Buffer,BufferSize,Flags,ActualRead);
  50. }
  51. return;
  52. }
  53. /*++
  54. Routine Description:
  55. Dumps specified range of physical memory in given format
  56. Arguments:
  57. Address - Address to start
  58. NumEntries - Number of entries to dump
  59. EntrySize - Size of each entry
  60. ShowAsAscii - print corresponding ascii chars
  61. Return Value:
  62. None.
  63. --*/
  64. BOOL
  65. DumpPhysicalMemory(
  66. ULONG64 Address,
  67. ULONG NumEntries,
  68. ULONG EntrySize,
  69. BOOL ShowAsAscii,
  70. ULONG Flags
  71. )
  72. {
  73. #define NumberBytesToRead 32*4
  74. UCHAR Buffer[NumberBytesToRead];
  75. ULONG ActualRead=0;
  76. if ((EntrySize != 1) && (EntrySize != 2) && (EntrySize != 4) && (EntrySize != 8)) {
  77. EntrySize=4;
  78. }
  79. while (1) {
  80. if (CheckControlC()) {
  81. break;
  82. }
  83. ReadPhysicalInChunks(Address,Buffer,sizeof(Buffer),Flags, EntrySize,&ActualRead);
  84. if (ActualRead != sizeof(Buffer) &&
  85. ActualRead < NumEntries*EntrySize) {
  86. dprintf("Physical memory read at %I64lx failed\n", Address);
  87. if (Flags == PHYS_FLAG_DEFAULT && ActualRead == 0) {
  88. dprintf(PHYS_FLAG_MESSAGE);
  89. }
  90. return FALSE;
  91. } else {
  92. PCHAR DumpByte = (PCHAR)&Buffer[0], pRow;
  93. ULONG cnt;
  94. for(cnt=0;cnt<NumberBytesToRead;DumpByte+=EntrySize) {
  95. if (!(cnt & 0xf)) {
  96. dprintf("#%8I64lx", Address+cnt);
  97. pRow = DumpByte;
  98. }
  99. switch (EntrySize) {
  100. case 1:
  101. dprintf("%c%02lx", ((cnt&0xf) == 8 ? '-' : ' '),*((PUCHAR)DumpByte));
  102. break;
  103. case 2:
  104. dprintf(" %04lx", *((PUSHORT) DumpByte));
  105. break;
  106. case 4:
  107. dprintf(" %08lx", *((PULONG) DumpByte));
  108. break;
  109. case 8:
  110. dprintf(" %08lx'%08lx", *((PULONG) DumpByte), *((PULONG) (DumpByte+4)));
  111. break;
  112. }
  113. cnt+=EntrySize, NumEntries--;
  114. if ((cnt && !(cnt & 0xf)) || !NumEntries) {
  115. if (ShowAsAscii) {
  116. unsigned char ch;
  117. dprintf(" ");
  118. for (ULONG d=0; d < 16; d++) {
  119. ch = (UCHAR) pRow[d];
  120. if (ch < 0x20 || ch > 0x7e) {
  121. ch = '.';
  122. }
  123. dprintf("%c", ch);
  124. }
  125. }
  126. dprintf("\n");
  127. }
  128. if (!NumEntries) {
  129. break;
  130. }
  131. }
  132. Address += cnt;
  133. if (!NumEntries) {
  134. break;
  135. }
  136. }
  137. }
  138. g_LastAddress = Address;
  139. return TRUE;
  140. }
  141. /*++
  142. Routine Description:
  143. Reverse sign extension of the value returned by GetExpression()
  144. based on the assumption that no physical address may be bigger
  145. than 0xfffffff00000000.
  146. Arguments:
  147. Val - points to the value to reverse sign extension
  148. Return Value:
  149. None.
  150. --*/
  151. void
  152. ReverseSignExtension(ULONG64* Val)
  153. {
  154. if ((*Val & 0xffffffff00000000) == 0xffffffff00000000)
  155. {
  156. *Val &= 0x00000000ffffffff;
  157. }
  158. }
  159. PCSTR
  160. GetPhyFlags(PCSTR Args, PULONG Flags)
  161. {
  162. *Flags = PHYS_FLAG_DEFAULT;
  163. while (*Args && (*Args == ' ' || *Args == '\t')) {
  164. ++Args;
  165. }
  166. if (*Args == '[') {
  167. Args++;
  168. if (*Args == 'c') {
  169. *Flags = PHYS_FLAG_CACHED;
  170. Args++;
  171. } else if (*Args == 'u' && *(Args + 1) == 'c') {
  172. *Flags = PHYS_FLAG_UNCACHED;
  173. Args += 2;
  174. } else if (*Args == 'w' && *(Args + 1) == 'c') {
  175. *Flags = PHYS_FLAG_WRITE_COMBINED;
  176. Args += 2;
  177. }
  178. if (*Args != ']') {
  179. *Flags = PHYS_FLAG_DEFAULT;
  180. dprintf("Unknown physical memory caching attribute\n");
  181. } else {
  182. Args++;
  183. }
  184. }
  185. if (*Args == '-' || *Args == '\\') {
  186. ++Args;
  187. if (tolower(*Args) == 'm') {
  188. *Flags |= PHYS_READ_MATCH_DUMPSIZE;
  189. } else {
  190. dprintf("Bad argument -%s\n", Args);
  191. }
  192. ++Args;
  193. }
  194. return Args;
  195. }
  196. void
  197. GetPhyDumpArgs(
  198. PCSTR Args,
  199. PULONG64 Address,
  200. PULONG Range,
  201. PULONG Flags
  202. )
  203. {
  204. CHAR Buffer[100]={0};
  205. *Flags = PHYS_FLAG_DEFAULT;
  206. if(*Args == '\0') {
  207. *Address=g_LastAddress;
  208. } else {
  209. Args = GetPhyFlags(Args, Flags);
  210. while (*Args && (*Args == ' ' || *Args == '\t')) {
  211. ++Args;
  212. }
  213. if(*Args == '\0') {
  214. *Address=g_LastAddress;
  215. } else {
  216. GetExpressionEx(Args, Address, &Args);
  217. ReverseSignExtension(Address);
  218. *Address &= (~0x3); // Truncate to dword boundary
  219. g_LastAddress=*Address;
  220. while (*Args && (*Args == ' ' || *Args == '\t')) {
  221. ++Args;
  222. }
  223. if (*Args == 'l' || *Args == 'L') {
  224. ++Args;
  225. *Range = (ULONG) GetExpression(Args);
  226. }
  227. }
  228. }
  229. return;
  230. }
  231. DECLARE_API( db )
  232. /*++
  233. Routine Description:
  234. Does a read of 16 ULONGS from the physical memory of the target machine
  235. Arguments:
  236. args - Supplies physical address
  237. Return Value:
  238. None.
  239. --*/
  240. {
  241. ULONG64 Address = 0;
  242. ULONG Range = 0;
  243. ULONG Flags;
  244. GetPhyDumpArgs(args, &Address, &Range, &Flags);
  245. if (!Range) {
  246. Range = 128;
  247. }
  248. DumpPhysicalMemory(Address, Range, 1, TRUE, Flags);
  249. return S_OK;
  250. }
  251. DECLARE_API( dd )
  252. /*++
  253. Routine Description:
  254. Does a read of 16 ULONGS from the physical memory of the target machine
  255. Arguments:
  256. args - Supplies physical address
  257. Return Value:
  258. None.
  259. --*/
  260. {
  261. ULONG64 Address = 0;
  262. ULONG Range = 0;
  263. ULONG Flags;
  264. GetPhyDumpArgs(args, &Address, &Range, &Flags);
  265. if (!Range) {
  266. Range = 32;
  267. }
  268. DumpPhysicalMemory(Address, Range, 4, FALSE, Flags);
  269. return S_OK;
  270. }
  271. DECLARE_API( dw )
  272. /*++
  273. Routine Description:
  274. Does a read of 16 ULONGS from the physical memory of the target machine
  275. Arguments:
  276. args - Supplies physical address
  277. Return Value:
  278. None.
  279. --*/
  280. {
  281. ULONG64 Address = 0;
  282. ULONG Range = 0;
  283. ULONG Flags;
  284. GetPhyDumpArgs(args, &Address, &Range, &Flags);
  285. if (!Range) {
  286. Range = 64;
  287. }
  288. DumpPhysicalMemory(Address, Range, 2, FALSE, Flags);
  289. return S_OK;
  290. }
  291. DECLARE_API( dp )
  292. /*++
  293. Routine Description:
  294. Does a read of 16 ULONGS from the physical memory of the target machine
  295. Arguments:
  296. args - Supplies physical address
  297. Return Value:
  298. None.
  299. --*/
  300. {
  301. ULONG64 Address = 0;
  302. ULONG Range = 0;
  303. ULONG Flags;
  304. GetPhyDumpArgs(args, &Address, &Range, &Flags);
  305. if (!Range) {
  306. Range = IsPtr64() ? 16 : 32;
  307. }
  308. DumpPhysicalMemory(Address, Range, IsPtr64() ? 8 : 4, FALSE, Flags);
  309. return S_OK;
  310. }
  311. DECLARE_API( dc )
  312. /*++
  313. Routine Description:
  314. Does a read of N ULONGS from the physical memory of the target machine,
  315. dumping both hex and ASCII.
  316. Arguments:
  317. args - Supplies physical address
  318. Return Value:
  319. None.
  320. --*/
  321. {
  322. ULONG64 Address = 0;
  323. ULONG Range = 0;
  324. ULONG Flags;
  325. GetPhyDumpArgs(args, &Address, &Range, &Flags);
  326. if (!Range) {
  327. Range = 32;
  328. }
  329. DumpPhysicalMemory(Address, Range, 4, TRUE, Flags);
  330. return S_OK;
  331. }
  332. DECLARE_API( du )
  333. /*++
  334. Routine Description:
  335. Does a read of 16 ULONGS from the physical memory of the target machine
  336. Arguments:
  337. args - Supplies physical address
  338. Return Value:
  339. None.
  340. --*/
  341. {
  342. ULONG64 Address = 0;
  343. ULONG Range = 0, ActualRead;
  344. WCHAR Buffer[MAX_PATH]={0};
  345. ULONG Flags;
  346. GetPhyDumpArgs(args, &Address, &Range, &Flags);
  347. if (Range>MAX_PATH) {
  348. Range = MAX_PATH;
  349. }
  350. if (!Range) {
  351. Range = 16;
  352. }
  353. ReadPhysicalWithFlags(Address,Buffer,Range * sizeof(WCHAR),Flags,&ActualRead);
  354. if (ActualRead != Range*sizeof(WCHAR)) {
  355. dprintf("Physical memory read at %I64lx failed\n", Address);
  356. if (Flags == PHYS_FLAG_DEFAULT && ActualRead == 0) {
  357. dprintf(PHYS_FLAG_MESSAGE);
  358. }
  359. return FALSE;
  360. } else {
  361. ULONG cnt;
  362. dprintf("#%8I64lx \"", Address);
  363. for (ULONG d=0; d < Range; d++) {
  364. WCHAR ch = Buffer[d];
  365. if (ch == 0) {
  366. break;
  367. }
  368. if (ch < 0x20 || ch > 0x7e) {
  369. ch = '.';
  370. }
  371. dprintf("%wc", ch);
  372. }
  373. dprintf("\"\n");
  374. }
  375. return S_OK;
  376. }
  377. DECLARE_API( ed )
  378. /*++
  379. Routine Description:
  380. Writes a sequence of ULONGs into a given physical address on the
  381. target machine.
  382. Arguments:
  383. arg - Supplies both the target address and the data in the form of
  384. "PHYSICAL_ADDRESS ULONG [ULONG, ULONG,...]"
  385. Return Value:
  386. None.
  387. --*/
  388. {
  389. ULONG64 Address = 0;
  390. ULONG Buffer;
  391. ULONG ActualWritten=0;
  392. PCHAR NextToken;
  393. ULONG Flags;
  394. args = GetPhyFlags(args, &Flags);
  395. Address = GetExpression(args);
  396. strtok((PSTR)args," \t,"); // The first token is the address
  397. // Since we're picking off one ULONG at a time, we'll make
  398. // one DbgKdWritePhysicalMemoryAddress call per ULONG. This
  399. // is slow, but easy to code.
  400. while((NextToken=strtok(NULL," \t,")) != NULL) {
  401. if (!sscanf(NextToken,"%lx",&Buffer)) {
  402. break;
  403. }
  404. WritePhysicalWithFlags(Address,&Buffer,sizeof(Buffer),Flags,
  405. &ActualWritten);
  406. if (ActualWritten != sizeof(Buffer)) {
  407. dprintf("Physical memory write at %I64lx failed\n", Address);
  408. if (Flags == PHYS_FLAG_DEFAULT && ActualWritten == 0) {
  409. dprintf(PHYS_FLAG_MESSAGE);
  410. }
  411. }
  412. Address+=sizeof(Buffer);
  413. }
  414. return S_OK;
  415. }
  416. DECLARE_API( eb )
  417. /*++
  418. Routine Description:
  419. Writes a sequence of BYTEs into a given physical address on the
  420. target machine.
  421. Arguments:
  422. arg - Supplies both the target address and the data in the form of
  423. "PHYSICAL_ADDRESS ULONG [ULONG, ULONG,...]"
  424. Return Value:
  425. None.
  426. --*/
  427. {
  428. ULONG64 Address = 0;
  429. ULONG Buffer;
  430. UCHAR c;
  431. ULONG ActualWritten;
  432. PCHAR NextToken;
  433. ULONG Flags;
  434. UNREFERENCED_PARAMETER (Client);
  435. args = GetPhyFlags(args, &Flags);
  436. Address = GetExpression(args);
  437. strtok((PSTR)args," \t,"); // The first token is the address
  438. // Since we're picking off one BYTE at a time, we'll make
  439. // one DbgKdWritePhysicalMemoryAddress call per BYTE. This
  440. // is slow, but easy to code.
  441. while((NextToken=strtok(NULL," \t,")) != NULL) {
  442. if (!sscanf(NextToken,"%lx",&Buffer)) {
  443. break;
  444. }
  445. c = (UCHAR)Buffer;
  446. WritePhysicalWithFlags(Address,&c,sizeof(UCHAR),Flags,&ActualWritten);
  447. if (ActualWritten != sizeof(UCHAR)) {
  448. dprintf("Physical memory write at %I64lx failed\n", Address);
  449. if (Flags == PHYS_FLAG_DEFAULT && ActualWritten == 0) {
  450. dprintf(PHYS_FLAG_MESSAGE);
  451. }
  452. }
  453. Address+=sizeof(UCHAR);
  454. }
  455. return S_OK;
  456. }