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.

2824 lines
66 KiB

  1. /*++
  2. Copyright (c) 1990-2001 Microsoft Corporation
  3. Module Name:
  4. dbgkdapi.cpp
  5. Abstract:
  6. This module implements the DbgKd APIs
  7. --*/
  8. #include "ntsdp.hpp"
  9. BOOL DbgKdApi64;
  10. ULONG g_KdMaxPacketType;
  11. ULONG g_KdMaxStateChange;
  12. ULONG g_KdMaxManipulate;
  13. //++
  14. //
  15. // VOID
  16. // DbgKdpWaitPacketForever (
  17. // IN ULONG PacketType,
  18. // IN PVOID Buffer
  19. // )
  20. //
  21. // Routine Description:
  22. //
  23. // This macro is invoked to wait for specifi type of message without
  24. // timeout.
  25. //
  26. // Arguments:
  27. //
  28. // PacketType - Type of the message we are expecting.
  29. //
  30. // Buffer - Buffer to store the message.
  31. //
  32. // Return Value:
  33. //
  34. // None.
  35. //
  36. //--
  37. #define DbgKdpWaitPacketForever( PacketType, Buffer ) { \
  38. ULONG WaitStatus; \
  39. do { \
  40. WaitStatus = g_DbgKdTransport->WaitForPacket( \
  41. PacketType, \
  42. Buffer \
  43. ); \
  44. } while (WaitStatus != DBGKD_WAIT_PACKET); \
  45. }
  46. #define COPYSE(p64, p32, f) p64->f = (ULONG64)(LONG64)(LONG)p32->f
  47. void
  48. WaitStateChange32ToAny(
  49. IN PDBGKD_WAIT_STATE_CHANGE32 Ws32,
  50. IN ULONG ControlReportSize,
  51. OUT PDBGKD_ANY_WAIT_STATE_CHANGE WsAny
  52. )
  53. {
  54. WsAny->NewState = Ws32->NewState;
  55. WsAny->ProcessorLevel = Ws32->ProcessorLevel;
  56. WsAny->Processor = Ws32->Processor;
  57. WsAny->NumberProcessors = Ws32->NumberProcessors;
  58. COPYSE(WsAny, Ws32, Thread);
  59. COPYSE(WsAny, Ws32, ProgramCounter);
  60. memcpy(&WsAny->ControlReport, Ws32 + 1, ControlReportSize);
  61. if (Ws32->NewState == DbgKdLoadSymbolsStateChange)
  62. {
  63. DbgkdLoadSymbols32To64(&Ws32->u.LoadSymbols, &WsAny->u.LoadSymbols);
  64. }
  65. else
  66. {
  67. DbgkmException32To64(&Ws32->u.Exception, &WsAny->u.Exception);
  68. }
  69. }
  70. #undef COPYSE
  71. NTSTATUS
  72. DbgKdWaitStateChange(
  73. OUT PDBGKD_ANY_WAIT_STATE_CHANGE StateChange,
  74. OUT PVOID Buffer,
  75. IN ULONG BufferLength,
  76. IN BOOL SuspendEngine
  77. )
  78. /*++
  79. Routine Description:
  80. This function causes the calling user interface to wait for a state
  81. change to occur in the system being debugged. Once a state change
  82. occurs, the user interface can either continue the system using
  83. DbgKdContinue, or it can manipulate system state using anyone of the
  84. DbgKd state manipulation APIs.
  85. Arguments:
  86. StateChange - Supplies the address of state change record that
  87. will contain the state change information.
  88. Buffer - Supplies the address of a buffer that returns additional
  89. information.
  90. BufferLength - Supplies the length of Buffer.
  91. Return Value:
  92. STATUS_SUCCESS - A state change occured. Valid state change information
  93. was returned.
  94. --*/
  95. {
  96. PVOID LocalStateChange;
  97. NTSTATUS Status;
  98. PUCHAR Data;
  99. ULONG SizeofStateChange;
  100. //
  101. // Waiting for a state change message. Copy the message to the callers
  102. // buffer.
  103. //
  104. DBG_ASSERT(g_DbgKdTransport->m_WaitingThread == 0);
  105. g_DbgKdTransport->m_WaitingThread = GetCurrentThreadId();
  106. if (SuspendEngine)
  107. {
  108. SUSPEND_ENGINE();
  109. }
  110. DbgKdpWaitPacketForever(
  111. PACKET_TYPE_KD_STATE_CHANGE64,
  112. &LocalStateChange
  113. );
  114. if (SuspendEngine)
  115. {
  116. RESUME_ENGINE();
  117. }
  118. g_DbgKdTransport->m_WaitingThread = 0;
  119. Status = STATUS_SUCCESS;
  120. // If this is the very first wait we don't know what machine
  121. // type we've connected to. Update the version information
  122. // right away.
  123. if (g_TargetMachineType == IMAGE_FILE_MACHINE_UNKNOWN)
  124. {
  125. g_DbgKdTransport->SaveReadPacket();
  126. g_Target->GetKdVersion();
  127. g_DbgKdTransport->RestoreReadPacket();
  128. if (g_TargetMachineType == IMAGE_FILE_MACHINE_UNKNOWN)
  129. {
  130. //
  131. // We were unable to determine what kind of machine
  132. // has connected so we cannot properly communicate with it.
  133. //
  134. return STATUS_UNSUCCESSFUL;
  135. }
  136. }
  137. if (DbgKdApi64)
  138. {
  139. if (g_KdVersion.ProtocolVersion < DBGKD_64BIT_PROTOCOL_VERSION2)
  140. {
  141. PDBGKD_WAIT_STATE_CHANGE64 Ws64 =
  142. (PDBGKD_WAIT_STATE_CHANGE64)LocalStateChange;
  143. ULONG Offset, Align, Pad;
  144. //
  145. // The 64-bit structures contain 64-bit quantities and
  146. // therefore the compiler rounds the total size up to
  147. // an even multiple of 64 bits (or even more, the IA64
  148. // structures are 16-byte aligned). Internal structures
  149. // are also aligned, so make sure that we account for any
  150. // padding. Knowledge of which structures need which
  151. // padding pretty much has to be hard-coded in.
  152. //
  153. C_ASSERT((sizeof(DBGKD_WAIT_STATE_CHANGE64) & 15) == 0);
  154. SizeofStateChange =
  155. sizeof(DBGKD_WAIT_STATE_CHANGE64) +
  156. g_TargetMachine->m_SizeControlReport +
  157. g_TargetMachine->m_SizeTargetContext;
  158. // We shouldn't need to align the base of the control report
  159. // so copy the base data and control report.
  160. Offset = sizeof(DBGKD_WAIT_STATE_CHANGE64) +
  161. g_TargetMachine->m_SizeControlReport;
  162. memcpy(StateChange, Ws64, Offset);
  163. //
  164. // Add alignment padding before the context.
  165. //
  166. switch(g_TargetMachineType)
  167. {
  168. case IMAGE_FILE_MACHINE_IA64:
  169. Align = 15;
  170. break;
  171. default:
  172. Align = 7;
  173. break;
  174. }
  175. Pad = ((Offset + Align) & ~Align) - Offset;
  176. Offset += Pad;
  177. SizeofStateChange += Pad;
  178. //
  179. // Add alignment padding after the context.
  180. //
  181. Offset += g_TargetMachine->m_SizeTargetContext;
  182. Pad = ((Offset + Align) & ~Align) - Offset;
  183. SizeofStateChange += Pad;
  184. }
  185. else
  186. {
  187. PDBGKD_ANY_WAIT_STATE_CHANGE WsAny =
  188. (PDBGKD_ANY_WAIT_STATE_CHANGE)LocalStateChange;
  189. SizeofStateChange = sizeof(*WsAny);
  190. *StateChange = *WsAny;
  191. }
  192. }
  193. else
  194. {
  195. SizeofStateChange =
  196. sizeof(DBGKD_WAIT_STATE_CHANGE32) +
  197. g_TargetMachine->m_SizeControlReport +
  198. g_TargetMachine->m_SizeTargetContext;
  199. WaitStateChange32ToAny((PDBGKD_WAIT_STATE_CHANGE32)LocalStateChange,
  200. g_TargetMachine->m_SizeControlReport,
  201. StateChange);
  202. }
  203. switch(StateChange->NewState)
  204. {
  205. case DbgKdExceptionStateChange:
  206. case DbgKdCommandStringStateChange:
  207. if (BufferLength <
  208. (g_DbgKdTransport->s_PacketHeader.ByteCount - SizeofStateChange))
  209. {
  210. Status = STATUS_BUFFER_OVERFLOW;
  211. }
  212. else
  213. {
  214. Data = (UCHAR *)LocalStateChange + SizeofStateChange;
  215. memcpy(Buffer, Data,
  216. g_DbgKdTransport->s_PacketHeader.ByteCount -
  217. SizeofStateChange);
  218. }
  219. break;
  220. case DbgKdLoadSymbolsStateChange:
  221. if ( BufferLength < StateChange->u.LoadSymbols.PathNameLength )
  222. {
  223. Status = STATUS_BUFFER_OVERFLOW;
  224. }
  225. else
  226. {
  227. Data = ((UCHAR *) LocalStateChange) +
  228. g_DbgKdTransport->s_PacketHeader.ByteCount -
  229. (int)StateChange->u.LoadSymbols.PathNameLength;
  230. memcpy(Buffer, Data,
  231. (int)StateChange->u.LoadSymbols.PathNameLength);
  232. }
  233. break;
  234. default:
  235. ErrOut("Unknown state change type %X\n", StateChange->NewState);
  236. Status = STATUS_INVALID_PARAMETER;
  237. break;
  238. }
  239. return Status;
  240. }
  241. NTSTATUS
  242. DbgKdContinue (
  243. IN NTSTATUS ContinueStatus
  244. )
  245. /*++
  246. Routine Description:
  247. Continuing a system that previously reported a state change causes
  248. the system to continue executiontion using the context in effect at
  249. the time the state change was reported (of course this context could
  250. have been modified using the DbgKd state manipulation APIs).
  251. Arguments:
  252. ContinueStatus - Supplies the continuation status to the thread
  253. being continued. Valid values for this are
  254. DBG_EXCEPTION_HANDLED, DBG_EXCEPTION_NOT_HANDLED
  255. or DBG_CONTINUE.
  256. Return Value:
  257. STATUS_SUCCESS - Successful call to DbgUiContinue
  258. STATUS_INVALID_PARAMETER - An invalid continue status or was
  259. specified.
  260. --*/
  261. {
  262. DBGKD_MANIPULATE_STATE64 m;
  263. PDBGKD_CONTINUE a = &m.u.Continue;
  264. NTSTATUS st;
  265. if ( ContinueStatus == DBG_EXCEPTION_HANDLED ||
  266. ContinueStatus == DBG_EXCEPTION_NOT_HANDLED ||
  267. ContinueStatus == DBG_CONTINUE )
  268. {
  269. m.ApiNumber = DbgKdContinueApi;
  270. m.ReturnStatus = ContinueStatus;
  271. a->ContinueStatus = ContinueStatus;
  272. g_DbgKdTransport->WritePacket(&m, sizeof(m),
  273. PACKET_TYPE_KD_STATE_MANIPULATE,
  274. NULL, 0);
  275. st = STATUS_SUCCESS;
  276. }
  277. else
  278. {
  279. st = STATUS_INVALID_PARAMETER;
  280. }
  281. KdOut("DbgKdContinue returns %08lx\n", st);
  282. return st;
  283. }
  284. NTSTATUS
  285. DbgKdContinue2 (
  286. IN NTSTATUS ContinueStatus,
  287. IN DBGKD_ANY_CONTROL_SET ControlSet
  288. )
  289. /*++
  290. Routine Description:
  291. Continuing a system that previously reported a state change causes
  292. the system to continue executiontion using the context in effect at
  293. the time the state change was reported, modified by the values set
  294. in the ControlSet structure. (And, of course, the context could have
  295. been modified by used the DbgKd state manipulation APIs.)
  296. Arguments:
  297. ContinueStatus - Supplies the continuation status to the thread
  298. being continued. Valid values for this are
  299. DBG_EXCEPTION_HANDLED, DBG_EXCEPTION_NOT_HANDLED
  300. or DBG_CONTINUE.
  301. ControlSet - Supplies a pointer to a structure containing the machine
  302. specific control data to set. For the x86 this is the TraceFlag
  303. and Dr7.
  304. Return Value:
  305. STATUS_SUCCESS - Successful call to DbgUiContinue
  306. STATUS_INVALID_PARAMETER - An invalid continue status or was
  307. specified.
  308. --*/
  309. {
  310. DBGKD_MANIPULATE_STATE64 m;
  311. NTSTATUS st;
  312. if ( ContinueStatus == DBG_EXCEPTION_HANDLED ||
  313. ContinueStatus == DBG_EXCEPTION_NOT_HANDLED ||
  314. ContinueStatus == DBG_CONTINUE)
  315. {
  316. m.ApiNumber = DbgKdContinueApi2;
  317. m.ReturnStatus = ContinueStatus;
  318. m.u.Continue2.ContinueStatus = ContinueStatus;
  319. m.u.Continue2.AnyControlSet = ControlSet;
  320. g_DbgKdTransport->WritePacket(&m, sizeof(m),
  321. PACKET_TYPE_KD_STATE_MANIPULATE,
  322. NULL, 0);
  323. st = STATUS_SUCCESS;
  324. }
  325. else
  326. {
  327. st = STATUS_INVALID_PARAMETER;
  328. }
  329. KdOut("DbgKdContinue2 returns %08lx\n", st);
  330. return st;
  331. }
  332. NTSTATUS
  333. DbgKdSetSpecialCalls (
  334. IN ULONG NumSpecialCalls,
  335. IN PULONG64 Calls
  336. )
  337. /*++
  338. Routine Description:
  339. Inform the debugged kernel that calls to these addresses
  340. are "special" calls, and they should result in callbacks
  341. to the kernel debugger rather than continued local stepping.
  342. The new values *replace* any old ones that may have previously
  343. set (not that you're likely to want to change this).
  344. Arguments:
  345. NumSpecialCalls - how many special calls there are
  346. Calls - pointer to an array of calls.
  347. Return Value:
  348. STATUS_SUCCESS - Successful call to DbgUiContinue
  349. STATUS_INVALID_PARAMETER - The number of special calls
  350. wasn't between 0 and MAX_SPECIAL_CALLS.
  351. --*/
  352. {
  353. DBGKD_MANIPULATE_STATE64 m;
  354. ULONG i;
  355. m.ApiNumber = DbgKdClearSpecialCallsApi;
  356. m.ReturnStatus = STATUS_PENDING;
  357. g_DbgKdTransport->WritePacket(&m, sizeof(m),
  358. PACKET_TYPE_KD_STATE_MANIPULATE,
  359. NULL, 0);
  360. InvalidateMemoryCaches();
  361. for (i = 0; i < NumSpecialCalls; i++)
  362. {
  363. m.ApiNumber = DbgKdSetSpecialCallApi;
  364. m.ReturnStatus = STATUS_PENDING;
  365. m.u.SetSpecialCall.SpecialCall = Calls[i];
  366. g_DbgKdTransport->WritePacket(&m, sizeof(m),
  367. PACKET_TYPE_KD_STATE_MANIPULATE,
  368. NULL, 0);
  369. }
  370. KdOut("DbgKdSetSpecialCalls returns 0x00000000\n");
  371. return STATUS_SUCCESS;
  372. }
  373. NTSTATUS
  374. DbgKdSetInternalBp (
  375. ULONG64 addr,
  376. ULONG flags
  377. )
  378. /*++
  379. Routine Description:
  380. Inform the debugged kernel that a breakpoint at this address
  381. is to be internally counted, and not result in a callback to the
  382. remote debugger (us). This function DOES NOT cause the kernel to
  383. set the breakpoint; the debugger must do that independently.
  384. Arguments:
  385. Addr - address of the breakpoint
  386. Flags - the breakpoint flags to set (note: if the invalid bit
  387. is set, this CLEARS a breakpoint).
  388. Return Value:
  389. STATUS_SUCCESS - Successful call to DbgUiContinue
  390. --*/
  391. {
  392. DBGKD_MANIPULATE_STATE64 m;
  393. NTSTATUS st;
  394. m.ApiNumber = DbgKdSetInternalBreakPointApi;
  395. m.ReturnStatus = STATUS_PENDING;
  396. #ifdef IBP_WORKAROUND
  397. // The kernel code keeps a ULONG64 for an internal breakpoint
  398. // address but older kernels did not sign-extend the current IP
  399. // when comparing against them. In order to work with both
  400. // broken and fixed kernels send down zero-extended addresses.
  401. // Don't actually enable this workaround right now as other
  402. // internal breakpoint bugs can cause the machine to bugcheck.
  403. addr = g_TargetMachine->m_Ptr64 ? addr : (ULONG)addr;
  404. #endif
  405. m.u.SetInternalBreakpoint.BreakpointAddress = addr;
  406. m.u.SetInternalBreakpoint.Flags = flags;
  407. g_DbgKdTransport->WritePacket(&m, sizeof(m),
  408. PACKET_TYPE_KD_STATE_MANIPULATE,
  409. NULL, 0);
  410. KdOut("DbgKdSetInternalBp returns 0x00000000\n");
  411. return STATUS_SUCCESS;
  412. }
  413. NTSTATUS
  414. DbgKdGetInternalBp (
  415. ULONG64 addr,
  416. PULONG flags,
  417. PULONG calls,
  418. PULONG minInstr,
  419. PULONG maxInstr,
  420. PULONG totInstr,
  421. PULONG maxCPS
  422. )
  423. /*++
  424. Routine Description:
  425. Query the status of an internal breakpoint from the debugged
  426. kernel and return the data to the caller.
  427. Arguments:
  428. Addr - address of the breakpoint
  429. flags, calls, minInstr, maxInstr, totInstr - values returned
  430. describing the particular breakpoint. flags will contain
  431. the invalid bit if the breakpoint is bogus.
  432. Return Value:
  433. STATUS_SUCCESS - Successful call to DbgUiContinue
  434. --*/
  435. {
  436. DBGKD_MANIPULATE_STATE64 m;
  437. PDBGKD_MANIPULATE_STATE64 Reply;
  438. NTSTATUS st;
  439. ULONG rc;
  440. m.ApiNumber = DbgKdGetInternalBreakPointApi;
  441. m.ReturnStatus = STATUS_PENDING;
  442. #ifdef IBP_WORKAROUND
  443. // The kernel code keeps a ULONG64 for an internal breakpoint
  444. // address but older kernels did not sign-extend the current IP
  445. // when comparing against them. In order to work with both
  446. // broken and fixed kernels send down zero-extended addresses.
  447. // Don't actually enable this workaround right now as other
  448. // internal breakpoint bugs can cause the machine to bugcheck.
  449. addr = g_TargetMachine->m_Ptr64 ? addr : (ULONG)addr;
  450. #endif
  451. m.u.GetInternalBreakpoint.BreakpointAddress = addr;
  452. do
  453. {
  454. g_DbgKdTransport->WritePacket(&m, sizeof(m),
  455. PACKET_TYPE_KD_STATE_MANIPULATE,
  456. NULL, 0);
  457. rc = g_DbgKdTransport->
  458. WaitForPacket(PACKET_TYPE_KD_STATE_MANIPULATE, &Reply);
  459. }
  460. while (rc != DBGKD_WAIT_PACKET);
  461. *flags = Reply->u.GetInternalBreakpoint.Flags;
  462. *calls = Reply->u.GetInternalBreakpoint.Calls;
  463. *maxCPS = Reply->u.GetInternalBreakpoint.MaxCallsPerPeriod;
  464. *maxInstr = Reply->u.GetInternalBreakpoint.MaxInstructions;
  465. *minInstr = Reply->u.GetInternalBreakpoint.MinInstructions;
  466. *totInstr = Reply->u.GetInternalBreakpoint.TotalInstructions;
  467. KdOut("DbgKdGetInternalBp returns 0x00000000\n");
  468. return STATUS_SUCCESS;
  469. }
  470. NTSTATUS
  471. DbgKdClearAllInternalBreakpoints(
  472. void
  473. )
  474. {
  475. if (g_KdMaxManipulate <= DbgKdClearAllInternalBreakpointsApi)
  476. {
  477. return STATUS_NOT_IMPLEMENTED;
  478. }
  479. DBGKD_MANIPULATE_STATE64 Request;
  480. NTSTATUS Status = STATUS_SUCCESS;
  481. Request.ApiNumber = DbgKdClearAllInternalBreakpointsApi;
  482. Request.ReturnStatus = STATUS_PENDING;
  483. g_DbgKdTransport->WritePacket(&Request, sizeof(Request),
  484. PACKET_TYPE_KD_STATE_MANIPULATE,
  485. NULL, 0);
  486. KdOut("DbgKdClearAllInternalBreakpoints returns 0x%08X\n", Status);
  487. return Status;
  488. }
  489. NTSTATUS
  490. DbgKdReadVirtualMemoryNow(
  491. IN ULONG64 TargetBaseAddress,
  492. OUT PVOID UserInterfaceBuffer,
  493. IN ULONG TransferCount,
  494. OUT PULONG ActualBytesRead
  495. )
  496. /*++
  497. Routine Description:
  498. This function reads the specified data from the system being debugged
  499. using the current mapping of the processor.
  500. Arguments:
  501. TargetBaseAddress - Supplies the base address of the memory to read
  502. from the system being debugged. The virtual address is in terms
  503. of the current mapping for the processor that reported the last
  504. state change. Until we figure out how to do this differently,
  505. the virtual address must refer to a valid page (although it does
  506. not necesserily have to be in the TB).
  507. UserInterfaceBuffer - Supplies the address of the buffer in the user
  508. interface that data read is to be placed.
  509. TransferCount - Specifies the number of bytes to read.
  510. ActualBytesRead - Supplies a pointer to the variable that receives the
  511. the number of bytes actually read.
  512. Return Value:
  513. If the read operation is successful, then a success status is returned.
  514. Otherwise, and unsuccessful status is returned.
  515. --*/
  516. {
  517. ULONG cb;
  518. DBGKD_MANIPULATE_STATE64 m;
  519. ULONG rc;
  520. PDBGKD_MANIPULATE_STATE64 Reply;
  521. NTSTATUS Status = STATUS_SUCCESS;
  522. if (g_VirtualCache.m_ForceDecodePTEs)
  523. {
  524. return DbgKdReadVirtualTranslatedMemory(TargetBaseAddress,
  525. UserInterfaceBuffer,
  526. TransferCount,
  527. ActualBytesRead);
  528. }
  529. cb = 0;
  530. while (TransferCount != 0)
  531. {
  532. //
  533. // Exit on user interrupt
  534. //
  535. if (g_EngStatus & ENG_STATUS_USER_INTERRUPT)
  536. {
  537. // dprintf("User interrupt during memory read - exiting.\n");
  538. ActualBytesRead = 0;
  539. return STATUS_CONTROL_C_EXIT;
  540. }
  541. //
  542. // Initialize state manipulate message to read virtual memory.
  543. //
  544. m.ApiNumber = DbgKdReadVirtualMemoryApi;
  545. m.u.ReadMemory.TargetBaseAddress = TargetBaseAddress + cb;
  546. m.u.ReadMemory.TransferCount = min(TransferCount, PACKET_MAX_SIZE);
  547. //
  548. // Send the read virtual message to the target system and wait for
  549. // a reply.
  550. //
  551. do
  552. {
  553. g_DbgKdTransport->WritePacket(&m, sizeof(m),
  554. PACKET_TYPE_KD_STATE_MANIPULATE,
  555. NULL, 0);
  556. rc = g_DbgKdTransport->
  557. WaitForPacket(PACKET_TYPE_KD_STATE_MANIPULATE, &Reply);
  558. }
  559. while ((rc != DBGKD_WAIT_PACKET) ||
  560. (Reply->ApiNumber != DbgKdReadVirtualMemoryApi));
  561. //
  562. // If the read virtual is successful, then copy the next segment
  563. // of data to the target buffer. Otherwise, terminate the read and
  564. // return the number of bytes read.
  565. //
  566. Status = Reply->ReturnStatus;
  567. if (!NT_SUCCESS(Status))
  568. {
  569. break;
  570. }
  571. else if (Reply->u.ReadMemory.ActualBytesRead == 0)
  572. {
  573. Status = STATUS_UNSUCCESSFUL;
  574. break;
  575. }
  576. else
  577. {
  578. ULONG Copy;
  579. if (Reply->u.ReadMemory.ActualBytesRead > TransferCount)
  580. {
  581. ErrOut("DbgKdReadVirtualMemoryNow: Asked for %d, got %d\n",
  582. TransferCount, Reply->u.ReadMemory.ActualBytesRead);
  583. Copy = TransferCount;
  584. }
  585. else
  586. {
  587. Copy = Reply->u.ReadMemory.ActualBytesRead;
  588. }
  589. memcpy((PUCHAR)UserInterfaceBuffer + cb,
  590. Reply + 1,
  591. Copy);
  592. TransferCount -= Copy;
  593. cb += Copy;
  594. }
  595. }
  596. //
  597. // Set the number of bytes actually read and return the status of the
  598. // read operation.
  599. //
  600. *ActualBytesRead = cb;
  601. KdOut("DbgKdReadVirtualMemoryNow(%s) returns %08lx, %X read\n",
  602. FormatAddr64(TargetBaseAddress), Status, cb);
  603. return Status;
  604. }
  605. NTSTATUS
  606. DbgKdWriteVirtualMemoryNow(
  607. IN ULONG64 TargetBaseAddress,
  608. OUT PVOID UserInterfaceBuffer,
  609. IN ULONG TransferCount,
  610. OUT PULONG ActualBytesWritten
  611. )
  612. /*++
  613. Routine Description:
  614. This function writes the specified data to the system being debugged
  615. using the current mapping of the processor.
  616. Arguments:
  617. TargetBaseAddress - Supplies the base address of the memory to be written
  618. into the system being debugged. The virtual address is in terms
  619. of the current mapping for the processor that reported the last
  620. state change. Until we figure out how to do this differently,
  621. the virtual address must refer to a valid page (although it does
  622. not necessarily have to be in the TB).
  623. UserInterfaceBuffer - Supplies the address of the buffer in the user
  624. interface that contains the data to be written.
  625. TransferCount - Specifies the number of bytes to write.
  626. ActualBytesWritten - Supplies a pointer to a variable that receives the
  627. actual number of bytes written.
  628. Return Value:
  629. If the write operation is successful, then a success status is returned.
  630. Otherwise, and unsuccessful status is returned.
  631. --*/
  632. {
  633. ULONG cb;
  634. DBGKD_MANIPULATE_STATE64 m;
  635. ULONG rc;
  636. PDBGKD_MANIPULATE_STATE64 Reply;
  637. NTSTATUS Status = STATUS_SUCCESS;
  638. DBG_ASSERT(g_TargetMachine->m_Ptr64 ||
  639. EXTEND64((ULONG)TargetBaseAddress) == TargetBaseAddress);
  640. if (g_VirtualCache.m_ForceDecodePTEs)
  641. {
  642. return DbgKdWriteVirtualTranslatedMemory(TargetBaseAddress,
  643. UserInterfaceBuffer,
  644. TransferCount,
  645. ActualBytesWritten);
  646. }
  647. cb = 0;
  648. while (TransferCount != 0)
  649. {
  650. //
  651. // Initialize state manipulate message to write virtual memory.
  652. //
  653. m.ApiNumber = DbgKdWriteVirtualMemoryApi;
  654. m.u.WriteMemory.TargetBaseAddress = TargetBaseAddress + cb;
  655. m.u.WriteMemory.TransferCount = min(TransferCount, PACKET_MAX_SIZE);
  656. //
  657. // Send the write message and data to the target system and wait
  658. // for a reply.
  659. //
  660. do
  661. {
  662. g_DbgKdTransport->WritePacket(&m, sizeof(m),
  663. PACKET_TYPE_KD_STATE_MANIPULATE,
  664. (PUCHAR)UserInterfaceBuffer + cb,
  665. (USHORT)m.u.WriteMemory.
  666. TransferCount);
  667. rc = g_DbgKdTransport->
  668. WaitForPacket(PACKET_TYPE_KD_STATE_MANIPULATE, &Reply);
  669. }
  670. while ((rc != DBGKD_WAIT_PACKET) ||
  671. (Reply->ApiNumber != DbgKdWriteVirtualMemoryApi));
  672. //
  673. // If the write virtual is successful, then update the byte count
  674. // and write the next data segment. Otherwise, terminate the write
  675. // and return the number of bytes written.
  676. //
  677. Status = Reply->ReturnStatus;
  678. if (!NT_SUCCESS(Status))
  679. {
  680. break;
  681. }
  682. else
  683. {
  684. TransferCount -= Reply->u.ReadMemory.ActualBytesRead;
  685. cb += Reply->u.ReadMemory.ActualBytesRead;
  686. }
  687. }
  688. //
  689. // Set the number of bytes actually written and return the status of the
  690. // write operation.
  691. //
  692. *ActualBytesWritten = cb;
  693. KdOut("DbgKdWriteVirtualMemory returns %08lx\n", Status);
  694. return Status;
  695. }
  696. NTSTATUS
  697. DbgKdReadVirtualTranslatedMemory(
  698. IN ULONG64 TargetBaseAddress,
  699. OUT PVOID UserInterfaceBuffer,
  700. IN ULONG TransferCount,
  701. OUT PULONG ActualBytesRead
  702. )
  703. {
  704. NTSTATUS Status;
  705. ULONG64 TargetPhysicalAddress;
  706. if (TransferCount == 0)
  707. {
  708. return STATUS_SUCCESS;
  709. }
  710. ULONG Levels;
  711. ULONG PfIndex;
  712. if (g_TargetMachine->
  713. GetVirtualTranslationPhysicalOffsets(TargetBaseAddress, NULL, 0,
  714. &Levels, &PfIndex,
  715. &TargetPhysicalAddress) == S_OK)
  716. {
  717. Status = DbgKdReadPhysicalMemory(TargetPhysicalAddress,
  718. UserInterfaceBuffer,
  719. TransferCount,
  720. ActualBytesRead);
  721. }
  722. else
  723. {
  724. Status = STATUS_UNSUCCESSFUL;
  725. }
  726. return Status;
  727. }
  728. NTSTATUS
  729. DbgKdWriteVirtualTranslatedMemory(
  730. IN ULONG64 TargetBaseAddress,
  731. OUT PVOID UserInterfaceBuffer,
  732. IN ULONG TransferCount,
  733. OUT PULONG ActualBytesWritten OPTIONAL
  734. )
  735. {
  736. NTSTATUS Status;
  737. ULONG64 TargetPhysicalAddress;
  738. ULONG Levels;
  739. ULONG PfIndex;
  740. if (g_TargetMachine->
  741. GetVirtualTranslationPhysicalOffsets(TargetBaseAddress, NULL, 0,
  742. &Levels, &PfIndex,
  743. &TargetPhysicalAddress) == S_OK)
  744. {
  745. Status = DbgKdWritePhysicalMemory(TargetPhysicalAddress,
  746. UserInterfaceBuffer,
  747. TransferCount,
  748. ActualBytesWritten);
  749. }
  750. else
  751. {
  752. Status = STATUS_UNSUCCESSFUL;
  753. }
  754. return Status;
  755. }
  756. NTSTATUS
  757. DbgKdReadControlSpace(
  758. IN ULONG Processor,
  759. IN ULONG OffsetAddress,
  760. OUT PVOID UserInterfaceBuffer,
  761. IN ULONG TransferCount,
  762. OUT PULONG ActualBytesRead
  763. )
  764. /*++
  765. Routine Description:
  766. This function reads the specified data from the control space of
  767. the system being debugged.
  768. Control space is processor dependent. TargetBaseAddress is mapped
  769. to control space in a processor/implementation defined manner.
  770. Arguments:
  771. Processor - Supplies the processor whoes control space is desired.
  772. OffsetAddress - Supplies the base address in control space to
  773. read. This address is interpreted in an implementation defined
  774. manner.
  775. UserInterfaceBuffer - Supplies the address of the buffer in the user
  776. interface that data read is to be placed.
  777. TransferCount - Specifies the number of bytes to read.
  778. ActualBytesRead - Specifies the number of bytes actually read.
  779. Return Value:
  780. STATUS_SUCCESS - The specified read occured.
  781. STATUS_BUFFER_OVERFLOW - A read that is to large was specified.
  782. --*/
  783. {
  784. DBGKD_MANIPULATE_STATE64 m;
  785. PDBGKD_MANIPULATE_STATE64 Reply;
  786. PDBGKD_READ_MEMORY64 a = &m.u.ReadMemory;
  787. NTSTATUS st = STATUS_UNSUCCESSFUL;
  788. ULONG rc;
  789. ULONG Read;
  790. if ( TransferCount + sizeof(m) > PACKET_MAX_SIZE )
  791. {
  792. st = STATUS_BUFFER_OVERFLOW;
  793. }
  794. else
  795. {
  796. //
  797. // Format state manipulate message
  798. //
  799. m.ApiNumber = DbgKdReadControlSpaceApi;
  800. m.ReturnStatus = STATUS_PENDING;
  801. m.Processor = (SHORT)Processor;
  802. a->TargetBaseAddress = OffsetAddress;
  803. a->TransferCount = TransferCount;
  804. a->ActualBytesRead = 0L;
  805. //
  806. // Send the message and then wait for reply
  807. //
  808. do
  809. {
  810. g_DbgKdTransport->WritePacket(&m, sizeof(m),
  811. PACKET_TYPE_KD_STATE_MANIPULATE,
  812. NULL, 0);
  813. rc = g_DbgKdTransport->
  814. WaitForPacket(PACKET_TYPE_KD_STATE_MANIPULATE, &Reply);
  815. } while (rc != DBGKD_WAIT_PACKET ||
  816. Reply->ApiNumber != DbgKdReadControlSpaceApi);
  817. st = Reply->ReturnStatus;
  818. //
  819. // Reset message address to reply.
  820. //
  821. a = &Reply->u.ReadMemory;
  822. DBG_ASSERT(a->ActualBytesRead <= TransferCount);
  823. //
  824. // Return actual bytes read, and then transfer the bytes
  825. //
  826. if (ARGUMENT_PRESENT(ActualBytesRead)) {
  827. *ActualBytesRead = a->ActualBytesRead;
  828. }
  829. //
  830. // Since read response data follows message, Reply+1 should point
  831. // at the data
  832. //
  833. memcpy(UserInterfaceBuffer, Reply+1, (int)a->ActualBytesRead);
  834. }
  835. KdOut("DbgKdReadControlSpace returns %08lx\n", st);
  836. return st;
  837. }
  838. NTSTATUS
  839. DbgKdWriteControlSpace(
  840. IN ULONG Processor,
  841. IN ULONG OffsetAddress,
  842. IN PVOID UserInterfaceBuffer,
  843. IN ULONG TransferCount,
  844. OUT PULONG ActualBytesWritten
  845. )
  846. /*++
  847. Routine Description:
  848. This function writes the specified data to control space on the system
  849. being debugged.
  850. Control space is processor dependent. TargetBaseAddress is mapped
  851. to control space in a processor/implementation defined manner.
  852. Arguments:
  853. Processor - Supplies the processor whoes control space is desired.
  854. OffsetAddress - Supplies the base address in control space to be
  855. written.
  856. UserInterfaceBuffer - Supplies the address of the buffer in the user
  857. interface that contains the data to be written.
  858. TransferCount - Specifies the number of bytes to write.
  859. ActualBytesWritten - Specifies the number of bytes actually written.
  860. Return Value:
  861. STATUS_SUCCESS - The specified read occured.
  862. STATUS_BUFFER_OVERFLOW - A read that is to large was specified.
  863. --*/
  864. {
  865. DBGKD_MANIPULATE_STATE64 m;
  866. PDBGKD_MANIPULATE_STATE64 Reply;
  867. PDBGKD_WRITE_MEMORY64 a = &m.u.WriteMemory;
  868. NTSTATUS st;
  869. ULONG rc;
  870. if ( TransferCount + sizeof(m) > PACKET_MAX_SIZE ) {
  871. return STATUS_BUFFER_OVERFLOW;
  872. }
  873. //
  874. // Format state manipulate message
  875. //
  876. m.ApiNumber = DbgKdWriteControlSpaceApi;
  877. m.ReturnStatus = STATUS_PENDING;
  878. m.Processor = (USHORT) Processor;
  879. a->TargetBaseAddress = OffsetAddress;
  880. a->TransferCount = TransferCount;
  881. a->ActualBytesWritten = 0L;
  882. //
  883. // Send the message and data to write and then wait for reply
  884. //
  885. do
  886. {
  887. g_DbgKdTransport->WritePacket(&m, sizeof(m),
  888. PACKET_TYPE_KD_STATE_MANIPULATE,
  889. UserInterfaceBuffer,
  890. (USHORT)TransferCount);
  891. rc = g_DbgKdTransport->
  892. WaitForPacket(PACKET_TYPE_KD_STATE_MANIPULATE, &Reply);
  893. } while (rc != DBGKD_WAIT_PACKET ||
  894. Reply->ApiNumber != DbgKdWriteControlSpaceApi);
  895. st = Reply->ReturnStatus;
  896. a = &Reply->u.WriteMemory;
  897. DBG_ASSERT(a->ActualBytesWritten <= TransferCount);
  898. //
  899. // Return actual bytes written
  900. //
  901. *ActualBytesWritten = a->ActualBytesWritten;
  902. KdOut("DbgWriteControlSpace returns %08lx\n", st);
  903. return st;
  904. }
  905. NTSTATUS
  906. DbgKdGetContext(
  907. IN ULONG Processor,
  908. PCROSS_PLATFORM_CONTEXT Context
  909. )
  910. /*++
  911. Routine Description:
  912. This function reads the context from the system being debugged.
  913. The ContextFlags field determines how much context is read.
  914. Arguments:
  915. Processor - Supplies a processor number to get context from.
  916. Context - On input, the ContextFlags field controls what portions of
  917. the context record the caller as interested in reading. On
  918. output, the context record returns the current context for the
  919. processor that reported the last state change.
  920. Return Value:
  921. STATUS_SUCCESS - The specified get context occured.
  922. --*/
  923. {
  924. DBGKD_MANIPULATE_STATE64 m;
  925. PDBGKD_MANIPULATE_STATE64 Reply;
  926. PDBGKD_GET_CONTEXT a = &m.u.GetContext;
  927. NTSTATUS st;
  928. ULONG rc;
  929. if (g_TargetMachine == NULL) {
  930. return STATUS_DEVICE_NOT_READY;
  931. }
  932. //
  933. // Format state manipulate message
  934. //
  935. m.ApiNumber = DbgKdGetContextApi;
  936. m.ReturnStatus = STATUS_PENDING;
  937. m.Processor = (USHORT) Processor;
  938. //
  939. // Send the message and then wait for reply
  940. //
  941. do
  942. {
  943. g_DbgKdTransport->WritePacket(&m, sizeof(m),
  944. PACKET_TYPE_KD_STATE_MANIPULATE,
  945. NULL, 0);
  946. rc = g_DbgKdTransport->
  947. WaitForPacket(PACKET_TYPE_KD_STATE_MANIPULATE, &Reply);
  948. } while (rc != DBGKD_WAIT_PACKET ||
  949. Reply->ApiNumber != DbgKdGetContextApi);
  950. st = Reply->ReturnStatus;
  951. //
  952. // Since get context response data follows message, Reply+1 should point
  953. // at the data
  954. //
  955. memcpy(Context, Reply+1, g_TargetMachine->m_SizeTargetContext);
  956. KdOut("DbgKdGetContext returns %08lx\n", st);
  957. return st;
  958. }
  959. NTSTATUS
  960. DbgKdSetContext(
  961. IN ULONG Processor,
  962. PCROSS_PLATFORM_CONTEXT Context
  963. )
  964. /*++
  965. Routine Description:
  966. This function writes the specified context to the system being debugged.
  967. Arguments:
  968. Processor - Supplies a processor number to set the context to.
  969. Context - Supplies a context record used to set the context for the
  970. processor that reported the last state change. Only the
  971. portions of the context indicated by the ContextFlags field are
  972. actually written.
  973. Return Value:
  974. STATUS_SUCCESS - The specified set context occured.
  975. --*/
  976. {
  977. DBGKD_MANIPULATE_STATE64 m;
  978. PDBGKD_MANIPULATE_STATE64 Reply;
  979. PDBGKD_SET_CONTEXT a = &m.u.SetContext;
  980. NTSTATUS st;
  981. ULONG rc;
  982. if (g_TargetMachine == NULL) {
  983. return STATUS_DEVICE_NOT_READY;
  984. }
  985. //
  986. // Format state manipulate message
  987. //
  988. m.ApiNumber = DbgKdSetContextApi;
  989. m.ReturnStatus = STATUS_PENDING;
  990. m.Processor = (USHORT) Processor;
  991. //
  992. // Send the message and context and then wait for reply
  993. //
  994. do
  995. {
  996. g_DbgKdTransport->WritePacket(&m, sizeof(m),
  997. PACKET_TYPE_KD_STATE_MANIPULATE,
  998. Context,
  999. (USHORT)g_TargetMachine->
  1000. m_SizeTargetContext);
  1001. rc = g_DbgKdTransport->
  1002. WaitForPacket(PACKET_TYPE_KD_STATE_MANIPULATE, &Reply);
  1003. } while (rc != DBGKD_WAIT_PACKET ||
  1004. Reply->ApiNumber != DbgKdSetContextApi);
  1005. st = Reply->ReturnStatus;
  1006. KdOut("DbgKdSetContext returns %08lx\n", st);
  1007. return st;
  1008. }
  1009. NTSTATUS
  1010. DbgKdWriteBreakPoint(
  1011. IN ULONG64 BreakPointAddress,
  1012. OUT PULONG_PTR BreakPointHandle
  1013. )
  1014. /*++
  1015. Routine Description:
  1016. This function is used to write a breakpoint at the address specified.
  1017. Arguments:
  1018. BreakPointAddress - Supplies the address that a breakpoint
  1019. instruction is to be written. This address is interpreted using
  1020. the current mapping on the processor reporting the previous
  1021. state change. If the address refers to a page that is not
  1022. valid, the the breakpoint is remembered by the system. As each
  1023. page is made valid, the system will check for pending
  1024. breakpoints and install breakpoints as necessary.
  1025. BreakPointHandle - Returns a handle to a breakpoint. This handle
  1026. may be used in a subsequent call to DbgKdRestoreBreakPoint.
  1027. Return Value:
  1028. STATUS_SUCCESS - The specified breakpoint write occured.
  1029. --*/
  1030. {
  1031. DBGKD_MANIPULATE_STATE64 m;
  1032. PDBGKD_MANIPULATE_STATE64 Reply;
  1033. PDBGKD_WRITE_BREAKPOINT64 a = &m.u.WriteBreakPoint;
  1034. NTSTATUS st;
  1035. ULONG rc;
  1036. //
  1037. // Format state manipulate message
  1038. //
  1039. m.ApiNumber = DbgKdWriteBreakPointApi;
  1040. m.ReturnStatus = STATUS_PENDING;
  1041. a->BreakPointAddress = BreakPointAddress;
  1042. //
  1043. // Send the message and context and then wait for reply
  1044. //
  1045. do
  1046. {
  1047. g_DbgKdTransport->WritePacket(&m, sizeof(m),
  1048. PACKET_TYPE_KD_STATE_MANIPULATE,
  1049. NULL, 0);
  1050. rc = g_DbgKdTransport->
  1051. WaitForPacket(PACKET_TYPE_KD_STATE_MANIPULATE, &Reply);
  1052. } while (rc != DBGKD_WAIT_PACKET ||
  1053. Reply->ApiNumber != DbgKdWriteBreakPointApi);
  1054. st = Reply->ReturnStatus;
  1055. *BreakPointHandle = Reply->u.WriteBreakPoint.BreakPointHandle;
  1056. KdOut("DbgKdWriteBreakPoint(%s) returns %08lx, %x\n",
  1057. FormatAddr64(BreakPointAddress), st,
  1058. (ULONG)*BreakPointHandle);
  1059. return st;
  1060. }
  1061. NTSTATUS
  1062. DbgKdRestoreBreakPoint(
  1063. IN ULONG_PTR BreakPointHandle
  1064. )
  1065. /*++
  1066. Routine Description:
  1067. This function is used to restore a breakpoint to its original
  1068. value.
  1069. Arguments:
  1070. BreakPointHandle - Supplies a handle returned by
  1071. DbgKdWriteBreakPoint. This handle must refer to a valid
  1072. address. The contents of the address must also be a breakpoint
  1073. instruction. If both of these are true, then the original value
  1074. at the breakpoint address is restored.
  1075. Return Value:
  1076. STATUS_SUCCESS - The specified breakpoint restore occured.
  1077. --*/
  1078. {
  1079. DBGKD_MANIPULATE_STATE64 m;
  1080. PDBGKD_MANIPULATE_STATE64 Reply;
  1081. PDBGKD_RESTORE_BREAKPOINT a = &m.u.RestoreBreakPoint;
  1082. NTSTATUS st;
  1083. ULONG rc;
  1084. //
  1085. // Format state manipulate message
  1086. //
  1087. m.ApiNumber = DbgKdRestoreBreakPointApi;
  1088. m.ReturnStatus = STATUS_PENDING;
  1089. a->BreakPointHandle = (ULONG)BreakPointHandle;
  1090. //
  1091. // Send the message and context and then wait for reply
  1092. //
  1093. do
  1094. {
  1095. g_DbgKdTransport->WritePacket(&m, sizeof(m),
  1096. PACKET_TYPE_KD_STATE_MANIPULATE,
  1097. NULL, 0);
  1098. rc = g_DbgKdTransport->
  1099. WaitForPacket(PACKET_TYPE_KD_STATE_MANIPULATE, &Reply);
  1100. } while (rc != DBGKD_WAIT_PACKET ||
  1101. Reply->ApiNumber != DbgKdRestoreBreakPointApi);
  1102. st = Reply->ReturnStatus;
  1103. KdOut("DbgKdRestoreBreakPoint(%x) returns %08lx\n",
  1104. (ULONG)BreakPointHandle, st);
  1105. return st;
  1106. }
  1107. NTSTATUS
  1108. DbgKdReadIoSpace(
  1109. IN ULONG64 IoAddress,
  1110. OUT PVOID ReturnedData,
  1111. IN ULONG DataSize
  1112. )
  1113. /*++
  1114. Routine Description:
  1115. This function is used read a byte, short, or long (1,2,4 bytes) from
  1116. the specified I/O address.
  1117. Arguments:
  1118. IoAddress - Supplies the Io address to read from.
  1119. ReturnedData - Supplies the value read from the I/O address.
  1120. DataSize - Supplies the size in bytes to read. Values of 1, 2, or
  1121. 4 are accepted.
  1122. Return Value:
  1123. STATUS_SUCCESS - Data was successfully read from the I/O
  1124. address.
  1125. STATUS_INVALID_PARAMETER - A DataSize value other than 1,2, or 4 was
  1126. specified.
  1127. --*/
  1128. {
  1129. DBGKD_MANIPULATE_STATE64 m;
  1130. PDBGKD_MANIPULATE_STATE64 Reply;
  1131. PDBGKD_READ_WRITE_IO64 a = &m.u.ReadWriteIo;
  1132. NTSTATUS st;
  1133. ULONG rc;
  1134. switch ( DataSize )
  1135. {
  1136. case 1:
  1137. case 2:
  1138. case 4:
  1139. break;
  1140. default:
  1141. return STATUS_INVALID_PARAMETER;
  1142. }
  1143. //
  1144. // Format state manipulate message
  1145. //
  1146. m.ApiNumber = DbgKdReadIoSpaceApi;
  1147. m.ReturnStatus = STATUS_PENDING;
  1148. a->DataSize = DataSize;
  1149. a->IoAddress = IoAddress;
  1150. //
  1151. // Send the message and then wait for reply
  1152. //
  1153. do
  1154. {
  1155. g_DbgKdTransport->WritePacket(&m, sizeof(m),
  1156. PACKET_TYPE_KD_STATE_MANIPULATE,
  1157. NULL, 0);
  1158. rc = g_DbgKdTransport->
  1159. WaitForPacket(PACKET_TYPE_KD_STATE_MANIPULATE, &Reply);
  1160. } while (rc != DBGKD_WAIT_PACKET ||
  1161. Reply->ApiNumber != DbgKdReadIoSpaceApi);
  1162. st = Reply->ReturnStatus;
  1163. a = &Reply->u.ReadWriteIo;
  1164. switch ( DataSize )
  1165. {
  1166. case 1:
  1167. *(PUCHAR)ReturnedData = (UCHAR)a->DataValue;
  1168. break;
  1169. case 2:
  1170. *(PUSHORT)ReturnedData = (USHORT)a->DataValue;
  1171. break;
  1172. case 4:
  1173. *(PULONG)ReturnedData = a->DataValue;
  1174. break;
  1175. }
  1176. KdOut("DbgKdReadIoSpace returns %08lx\n", st);
  1177. return st;
  1178. }
  1179. NTSTATUS
  1180. DbgKdWriteIoSpace(
  1181. IN ULONG64 IoAddress,
  1182. IN ULONG DataValue,
  1183. IN ULONG DataSize
  1184. )
  1185. /*++
  1186. Routine Description:
  1187. This function is used write a byte, short, or long (1,2,4 bytes) to
  1188. the specified I/O address.
  1189. Arguments:
  1190. IoAddress - Supplies the Io address to write to.
  1191. DataValue - Supplies the value to write to the I/O address.
  1192. DataSize - Supplies the size in bytes to write. Values of 1, 2, or
  1193. 4 are accepted.
  1194. Return Value:
  1195. STATUS_SUCCESS - Data was successfully written to the I/O
  1196. address.
  1197. STATUS_INVALID_PARAMETER - A DataSize value other than 1,2, or 4 was
  1198. specified.
  1199. --*/
  1200. {
  1201. DBGKD_MANIPULATE_STATE64 m;
  1202. PDBGKD_MANIPULATE_STATE64 Reply;
  1203. PDBGKD_READ_WRITE_IO64 a = &m.u.ReadWriteIo;
  1204. NTSTATUS st;
  1205. ULONG rc;
  1206. switch ( DataSize ) {
  1207. case 1:
  1208. case 2:
  1209. case 4:
  1210. break;
  1211. default:
  1212. return STATUS_INVALID_PARAMETER;
  1213. }
  1214. //
  1215. // Format state manipulate message
  1216. //
  1217. m.ApiNumber = DbgKdWriteIoSpaceApi;
  1218. m.ReturnStatus = STATUS_PENDING;
  1219. a->DataSize = DataSize;
  1220. a->IoAddress = IoAddress;
  1221. a->DataValue = DataValue;
  1222. //
  1223. // Send the message and then wait for reply
  1224. //
  1225. do
  1226. {
  1227. g_DbgKdTransport->WritePacket(&m, sizeof(m),
  1228. PACKET_TYPE_KD_STATE_MANIPULATE,
  1229. NULL, 0);
  1230. rc = g_DbgKdTransport->
  1231. WaitForPacket(PACKET_TYPE_KD_STATE_MANIPULATE, &Reply);
  1232. } while (rc != DBGKD_WAIT_PACKET ||
  1233. Reply->ApiNumber != DbgKdWriteIoSpaceApi);
  1234. st = Reply->ReturnStatus;
  1235. KdOut("DbgKdWriteIoSpace returns %08lx\n", st);
  1236. return st;
  1237. }
  1238. NTSTATUS
  1239. DbgKdReadMsr(
  1240. IN ULONG MsrReg,
  1241. OUT PULONGLONG MsrValue
  1242. )
  1243. /*++
  1244. Routine Description:
  1245. This function is used read a MSR at the specified location
  1246. Arguments:
  1247. MsrReg - Which model specific register to read
  1248. MsrValue - Its value
  1249. Return Value:
  1250. STATUS_SUCCESS - Data was successfully read from the I/O
  1251. address.
  1252. STATUS_INVALID_PARAMETER - A DataSize value other than 1,2, or 4 was
  1253. specified.
  1254. --*/
  1255. {
  1256. DBGKD_MANIPULATE_STATE64 m;
  1257. PDBGKD_MANIPULATE_STATE64 Reply;
  1258. PDBGKD_READ_WRITE_MSR a = &m.u.ReadWriteMsr;
  1259. LARGE_INTEGER li;
  1260. NTSTATUS st;
  1261. ULONG rc;
  1262. //
  1263. // Format state manipulate message
  1264. //
  1265. m.ApiNumber = DbgKdReadMachineSpecificRegister;
  1266. m.ReturnStatus = STATUS_PENDING;
  1267. a->Msr = MsrReg;
  1268. //
  1269. // Send the message and then wait for reply
  1270. //
  1271. do
  1272. {
  1273. g_DbgKdTransport->WritePacket(&m, sizeof(m),
  1274. PACKET_TYPE_KD_STATE_MANIPULATE,
  1275. NULL, 0);
  1276. rc = g_DbgKdTransport->
  1277. WaitForPacket(PACKET_TYPE_KD_STATE_MANIPULATE, &Reply);
  1278. } while (rc != DBGKD_WAIT_PACKET ||
  1279. Reply->ApiNumber != DbgKdReadMachineSpecificRegister);
  1280. st = Reply->ReturnStatus;
  1281. a = &Reply->u.ReadWriteMsr;
  1282. li.LowPart = a->DataValueLow;
  1283. li.HighPart = a->DataValueHigh;
  1284. *MsrValue = li.QuadPart;
  1285. KdOut("DbgKdReadMsr returns %08lx\n", st);
  1286. return st;
  1287. }
  1288. NTSTATUS
  1289. DbgKdWriteMsr(
  1290. IN ULONG MsrReg,
  1291. IN ULONGLONG MsrValue
  1292. )
  1293. /*++
  1294. Routine Description:
  1295. This function is used write a MSR to the specified location
  1296. Arguments:
  1297. MsrReg - Which model specific register to read
  1298. MsrValue - It's value
  1299. Return Value:
  1300. STATUS_SUCCESS - Data was successfully written to the I/O
  1301. address.
  1302. STATUS_INVALID_PARAMETER - A DataSize value other than 1,2, or 4 was
  1303. specified.
  1304. --*/
  1305. {
  1306. DBGKD_MANIPULATE_STATE64 m;
  1307. PDBGKD_MANIPULATE_STATE64 Reply;
  1308. PDBGKD_READ_WRITE_MSR a = &m.u.ReadWriteMsr;
  1309. LARGE_INTEGER li;
  1310. NTSTATUS st;
  1311. ULONG rc;
  1312. li.QuadPart = MsrValue;
  1313. //
  1314. // Format state manipulate message
  1315. //
  1316. m.ApiNumber = DbgKdWriteMachineSpecificRegister;
  1317. m.ReturnStatus = STATUS_PENDING;
  1318. // Quiet PREfix warnings.
  1319. m.Processor = 0;
  1320. m.ProcessorLevel = 0;
  1321. a->Msr = MsrReg;
  1322. a->DataValueLow = li.LowPart;
  1323. a->DataValueHigh = li.HighPart;
  1324. //
  1325. // Send the message and then wait for reply
  1326. //
  1327. do
  1328. {
  1329. g_DbgKdTransport->WritePacket(&m, sizeof(m),
  1330. PACKET_TYPE_KD_STATE_MANIPULATE,
  1331. NULL, 0);
  1332. rc = g_DbgKdTransport->
  1333. WaitForPacket(PACKET_TYPE_KD_STATE_MANIPULATE, &Reply);
  1334. } while (rc != DBGKD_WAIT_PACKET ||
  1335. Reply->ApiNumber != DbgKdWriteMachineSpecificRegister);
  1336. st = Reply->ReturnStatus;
  1337. KdOut("DbgKdWriteMsr returns %08lx\n", st);
  1338. return st;
  1339. }
  1340. NTSTATUS
  1341. DbgKdReadIoSpaceExtended(
  1342. IN ULONG64 IoAddress,
  1343. OUT PVOID ReturnedData,
  1344. IN ULONG DataSize,
  1345. IN INTERFACE_TYPE InterfaceType,
  1346. IN ULONG BusNumber,
  1347. IN ULONG AddressSpace
  1348. )
  1349. /*++
  1350. Routine Description:
  1351. This function is used read a byte, short, or long (1,2,4 bytes) from
  1352. the specified I/O address.
  1353. Arguments:
  1354. IoAddress - Supplies the Io address to read from.
  1355. ReturnedData - Supplies the value read from the I/O address.
  1356. DataSize - Supplies the size in bytes to read. Values of 1, 2, or
  1357. 4 are accepted.
  1358. InterfaceType - The type of interface for the bus.
  1359. BusNumber - The bus number of the bus to be used. Normally this would
  1360. be zero.
  1361. AddressSpace - This contains a zero if we are using I/O memory space,
  1362. else it contains a one if we are using I/O port space.
  1363. Return Value:
  1364. STATUS_SUCCESS - Data was successfully read from the I/O
  1365. address.
  1366. STATUS_INVALID_PARAMETER - A DataSize value other than 1,2, or 4 was
  1367. specified.
  1368. --*/
  1369. {
  1370. DBGKD_MANIPULATE_STATE64 m;
  1371. PDBGKD_MANIPULATE_STATE64 Reply;
  1372. PDBGKD_READ_WRITE_IO_EXTENDED64 a = &m.u.ReadWriteIoExtended;
  1373. NTSTATUS st;
  1374. ULONG rc;
  1375. switch ( DataSize )
  1376. {
  1377. case 1:
  1378. case 2:
  1379. case 4:
  1380. break;
  1381. default:
  1382. return STATUS_INVALID_PARAMETER;
  1383. }
  1384. if ( !(AddressSpace == 0 || AddressSpace == 1) )
  1385. {
  1386. return STATUS_INVALID_PARAMETER;
  1387. }
  1388. //
  1389. // Format state manipulate message
  1390. //
  1391. m.ApiNumber = DbgKdReadIoSpaceExtendedApi;
  1392. m.ReturnStatus = STATUS_PENDING;
  1393. a->DataSize = DataSize;
  1394. a->IoAddress = IoAddress;
  1395. a->InterfaceType = InterfaceType;
  1396. a->BusNumber = BusNumber;
  1397. a->AddressSpace = AddressSpace;
  1398. //
  1399. // Send the message and then wait for reply
  1400. //
  1401. do
  1402. {
  1403. g_DbgKdTransport->WritePacket(&m, sizeof(m),
  1404. PACKET_TYPE_KD_STATE_MANIPULATE,
  1405. NULL, 0);
  1406. rc = g_DbgKdTransport->
  1407. WaitForPacket(PACKET_TYPE_KD_STATE_MANIPULATE, &Reply);
  1408. } while (rc != DBGKD_WAIT_PACKET ||
  1409. Reply->ApiNumber != DbgKdReadIoSpaceExtendedApi);
  1410. st = Reply->ReturnStatus;
  1411. a = &Reply->u.ReadWriteIoExtended;
  1412. switch ( DataSize )
  1413. {
  1414. case 1:
  1415. *(PUCHAR)ReturnedData = (UCHAR)a->DataValue;
  1416. break;
  1417. case 2:
  1418. *(PUSHORT)ReturnedData = (USHORT)a->DataValue;
  1419. break;
  1420. case 4:
  1421. *(PULONG)ReturnedData = a->DataValue;
  1422. break;
  1423. }
  1424. KdOut("DbgKdReadIoSpaceExtended returns %08lx\n", st);
  1425. return st;
  1426. }
  1427. NTSTATUS
  1428. DbgKdWriteIoSpaceExtended(
  1429. IN ULONG64 IoAddress,
  1430. IN ULONG DataValue,
  1431. IN ULONG DataSize,
  1432. IN INTERFACE_TYPE InterfaceType,
  1433. IN ULONG BusNumber,
  1434. IN ULONG AddressSpace
  1435. )
  1436. /*++
  1437. Routine Description:
  1438. This function is used write a byte, short, or long (1,2,4 bytes) to
  1439. the specified I/O address.
  1440. Arguments:
  1441. IoAddress - Supplies the Io address to write to.
  1442. DataValue - Supplies the value to write to the I/O address.
  1443. DataSize - Supplies the size in bytes to write. Values of 1, 2, or
  1444. 4 are accepted.
  1445. Return Value:
  1446. STATUS_SUCCESS - Data was successfully written to the I/O
  1447. address.
  1448. STATUS_INVALID_PARAMETER - A DataSize value other than 1,2, or 4 was
  1449. specified.
  1450. --*/
  1451. {
  1452. DBGKD_MANIPULATE_STATE64 m;
  1453. PDBGKD_MANIPULATE_STATE64 Reply;
  1454. PDBGKD_READ_WRITE_IO_EXTENDED64 a = &m.u.ReadWriteIoExtended;
  1455. NTSTATUS st;
  1456. ULONG rc;
  1457. switch ( DataSize )
  1458. {
  1459. case 1:
  1460. case 2:
  1461. case 4:
  1462. break;
  1463. default:
  1464. return STATUS_INVALID_PARAMETER;
  1465. }
  1466. if ( !(AddressSpace == 0 || AddressSpace == 1) )
  1467. {
  1468. return STATUS_INVALID_PARAMETER;
  1469. }
  1470. //
  1471. // Format state manipulate message
  1472. //
  1473. m.ApiNumber = DbgKdWriteIoSpaceExtendedApi;
  1474. m.ReturnStatus = STATUS_PENDING;
  1475. a->DataSize = DataSize;
  1476. a->IoAddress = IoAddress;
  1477. a->DataValue = DataValue;
  1478. a->InterfaceType = InterfaceType;
  1479. a->BusNumber = BusNumber;
  1480. a->AddressSpace = AddressSpace;
  1481. //
  1482. // Send the message and then wait for reply
  1483. //
  1484. do
  1485. {
  1486. g_DbgKdTransport->WritePacket(&m, sizeof(m),
  1487. PACKET_TYPE_KD_STATE_MANIPULATE,
  1488. NULL, 0);
  1489. rc = g_DbgKdTransport->
  1490. WaitForPacket(PACKET_TYPE_KD_STATE_MANIPULATE, &Reply);
  1491. } while (rc != DBGKD_WAIT_PACKET ||
  1492. Reply->ApiNumber != DbgKdWriteIoSpaceExtendedApi);
  1493. st = Reply->ReturnStatus;
  1494. KdOut("DbgKdWriteIoSpaceExtended returns %08lx\n", st);
  1495. return st;
  1496. }
  1497. NTSTATUS
  1498. DbgKdGetBusData(
  1499. IN ULONG BusDataType,
  1500. IN ULONG BusNumber,
  1501. IN ULONG SlotNumber,
  1502. OUT PVOID Buffer,
  1503. IN ULONG Offset,
  1504. IN OUT PULONG Length
  1505. )
  1506. /*++
  1507. Routine Description:
  1508. This function is used to read I/O configuration space.
  1509. Arguments:
  1510. BusDataType - BUS_DATA_TYPE
  1511. BusNumber - Bus number.
  1512. SlotNumber - Slot number.
  1513. Buffer - Buffer to receive bus data.
  1514. Offset - Offset.
  1515. Length - Length.
  1516. Return Value:
  1517. STATUS_SUCCESS - Data was successfully read from
  1518. configuration space.
  1519. --*/
  1520. {
  1521. DBGKD_MANIPULATE_STATE64 m;
  1522. PDBGKD_MANIPULATE_STATE64 Reply;
  1523. PDBGKD_GET_SET_BUS_DATA a = &m.u.GetSetBusData;
  1524. NTSTATUS st;
  1525. ULONG rc;
  1526. //
  1527. // Check the buffer size.
  1528. //
  1529. if (*Length > PACKET_MAX_SIZE - sizeof (DBGKD_MANIPULATE_STATE64))
  1530. {
  1531. return STATUS_BUFFER_OVERFLOW;
  1532. }
  1533. //
  1534. // Format state manipulate message
  1535. //
  1536. m.ApiNumber = DbgKdGetBusDataApi;
  1537. m.ReturnStatus = STATUS_PENDING;
  1538. a->BusDataType = BusDataType;
  1539. a->BusNumber = BusNumber;
  1540. a->SlotNumber = SlotNumber;
  1541. a->Offset = Offset;
  1542. a->Length = *Length;
  1543. //
  1544. // Send the message and then wait for reply
  1545. //
  1546. do
  1547. {
  1548. g_DbgKdTransport->WritePacket(&m, sizeof(m),
  1549. PACKET_TYPE_KD_STATE_MANIPULATE,
  1550. NULL, 0);
  1551. rc = g_DbgKdTransport->
  1552. WaitForPacket(PACKET_TYPE_KD_STATE_MANIPULATE, &Reply);
  1553. } while (rc != DBGKD_WAIT_PACKET ||
  1554. Reply->ApiNumber != DbgKdGetBusDataApi);
  1555. st = Reply->ReturnStatus;
  1556. a = &Reply->u.GetSetBusData;
  1557. if (NT_SUCCESS(st))
  1558. {
  1559. memcpy(Buffer, Reply + 1, a->Length);
  1560. *Length = a->Length;
  1561. }
  1562. KdOut("DbgKdGetBusData returns %08lx\n", st);
  1563. return st;
  1564. }
  1565. NTSTATUS
  1566. DbgKdSetBusData(
  1567. IN ULONG BusDataType,
  1568. IN ULONG BusNumber,
  1569. IN ULONG SlotNumber,
  1570. IN PVOID Buffer,
  1571. IN ULONG Offset,
  1572. IN OUT PULONG Length
  1573. )
  1574. /*++
  1575. Routine Description:
  1576. This function is used to write I/O configuration space.
  1577. Arguments:
  1578. BusDataType - BUS_DATA_TYPE
  1579. BusNumber - Bus number.
  1580. SlotNumber - Slot number.
  1581. Buffer - Buffer containing bus data.
  1582. Offset - Offset.
  1583. Length - Length.
  1584. Return Value:
  1585. STATUS_SUCCESS - Data was successfully written to
  1586. configuration space.
  1587. --*/
  1588. {
  1589. DBGKD_MANIPULATE_STATE64 m;
  1590. PDBGKD_MANIPULATE_STATE64 Reply;
  1591. PDBGKD_GET_SET_BUS_DATA a = &m.u.GetSetBusData;
  1592. NTSTATUS st;
  1593. ULONG rc;
  1594. //
  1595. // Check the buffer size.
  1596. //
  1597. if (*Length > PACKET_MAX_SIZE - sizeof (DBGKD_MANIPULATE_STATE64))
  1598. {
  1599. return STATUS_BUFFER_OVERFLOW;
  1600. }
  1601. //
  1602. // Format state manipulate message
  1603. //
  1604. m.ApiNumber = DbgKdSetBusDataApi;
  1605. m.ReturnStatus = STATUS_PENDING;
  1606. a->BusDataType = BusDataType;
  1607. a->BusNumber = BusNumber;
  1608. a->SlotNumber = SlotNumber;
  1609. a->Offset = Offset;
  1610. a->Length = *Length;
  1611. //
  1612. // Send the message and then wait for reply
  1613. //
  1614. do
  1615. {
  1616. g_DbgKdTransport->WritePacket(&m, sizeof(m),
  1617. PACKET_TYPE_KD_STATE_MANIPULATE,
  1618. Buffer, (USHORT)*Length);
  1619. rc = g_DbgKdTransport->
  1620. WaitForPacket(PACKET_TYPE_KD_STATE_MANIPULATE, &Reply);
  1621. } while (rc != DBGKD_WAIT_PACKET ||
  1622. Reply->ApiNumber != DbgKdSetBusDataApi);
  1623. st = Reply->ReturnStatus;
  1624. if (NT_SUCCESS(st))
  1625. {
  1626. a = &Reply->u.GetSetBusData;
  1627. *Length = a->Length;
  1628. }
  1629. KdOut("DbgKdSetBusData returns %08lx\n", st);
  1630. return st;
  1631. }
  1632. NTSTATUS
  1633. DbgKdGetVersion (
  1634. PDBGKD_GET_VERSION64 GetVersion
  1635. )
  1636. {
  1637. DBGKD_MANIPULATE_STATE64 m;
  1638. PDBGKD_MANIPULATE_STATE64 Reply;
  1639. PDBGKD_GET_VERSION64 a = &m.u.GetVersion64;
  1640. DWORD st;
  1641. ULONG rc;
  1642. m.ApiNumber = DbgKdGetVersionApi;
  1643. m.ReturnStatus = STATUS_PENDING;
  1644. a->ProtocolVersion = 1; // request context records on state changes
  1645. do
  1646. {
  1647. g_DbgKdTransport->WritePacket(&m, sizeof(m),
  1648. PACKET_TYPE_KD_STATE_MANIPULATE,
  1649. NULL, 0);
  1650. rc = g_DbgKdTransport->
  1651. WaitForPacket(PACKET_TYPE_KD_STATE_MANIPULATE, &Reply);
  1652. } while (rc != DBGKD_WAIT_PACKET);
  1653. st = Reply->ReturnStatus;
  1654. *GetVersion = Reply->u.GetVersion64;
  1655. KdOut("DbgKdGetVersion returns %08lx\n", st);
  1656. return st;
  1657. }
  1658. NTSTATUS
  1659. DbgKdReboot(
  1660. VOID
  1661. )
  1662. /*++
  1663. Routine Description:
  1664. This function reboots being debugged.
  1665. Arguments:
  1666. None.
  1667. Return Value:
  1668. None.
  1669. --*/
  1670. {
  1671. DBGKD_MANIPULATE_STATE64 m;
  1672. //
  1673. // Format state manipulate message
  1674. //
  1675. m.ApiNumber = DbgKdRebootApi;
  1676. m.ReturnStatus = STATUS_PENDING;
  1677. //
  1678. // Send the message.
  1679. //
  1680. g_DbgKdTransport->WritePacket(&m, sizeof(m),
  1681. PACKET_TYPE_KD_STATE_MANIPULATE,
  1682. NULL, 0);
  1683. InvalidateMemoryCaches();
  1684. KdOut("DbgKdReboot returns 0x00000000\n");
  1685. return STATUS_SUCCESS;
  1686. }
  1687. NTSTATUS
  1688. DbgKdCrash(
  1689. DWORD BugCheckCode
  1690. )
  1691. /*++
  1692. Routine Description:
  1693. This function reboots being debugged.
  1694. Arguments:
  1695. None.
  1696. Return Value:
  1697. None.
  1698. --*/
  1699. {
  1700. DBGKD_MANIPULATE_STATE64 m;
  1701. //
  1702. // Format state manipulate message
  1703. //
  1704. m.ApiNumber = DbgKdCauseBugCheckApi;
  1705. m.ReturnStatus = STATUS_PENDING;
  1706. *(PULONG)&m.u = BugCheckCode;
  1707. //
  1708. // Send the message.
  1709. //
  1710. g_DbgKdTransport->WritePacket(&m, sizeof(m),
  1711. PACKET_TYPE_KD_STATE_MANIPULATE,
  1712. NULL, 0);
  1713. InvalidateMemoryCaches();
  1714. KdOut("DbgKdCrash returns 0x00000000\n");
  1715. return STATUS_SUCCESS;
  1716. }
  1717. NTSTATUS
  1718. DbgKdReadPhysicalMemory(
  1719. IN ULONG64 TargetBaseAddress,
  1720. OUT PVOID UserInterfaceBuffer,
  1721. IN ULONG TransferCount,
  1722. OUT PULONG ActualBytesRead OPTIONAL
  1723. )
  1724. /*++
  1725. Routine Description:
  1726. This function reads the specified data from the physical memory of
  1727. the system being debugged.
  1728. Arguments:
  1729. TargetBaseAddress - Supplies the physical address of the memory to read
  1730. from the system being debugged.
  1731. UserInterfaceBuffer - Supplies the address of the buffer in the user
  1732. interface that data read is to be placed.
  1733. TransferCount - Specifies the number of bytes to read.
  1734. ActualBytesRead - An optional parameter that if supplied, returns
  1735. the number of bytes actually read.
  1736. Return Value:
  1737. STATUS_SUCCESS - The specified read occured.
  1738. STATUS_BUFFER_OVERFLOW - A read that is too large was specified.
  1739. --*/
  1740. {
  1741. DBGKD_MANIPULATE_STATE64 m;
  1742. PDBGKD_MANIPULATE_STATE64 Reply;
  1743. PDBGKD_READ_MEMORY64 a;
  1744. NTSTATUS st;
  1745. ULONG rc;
  1746. ULONG cb, cb2;
  1747. cb2 = 0;
  1748. if (ARGUMENT_PRESENT(ActualBytesRead)) {
  1749. *ActualBytesRead = 0;
  1750. }
  1751. readmore:
  1752. cb = TransferCount;
  1753. if (cb > PACKET_MAX_SIZE) {
  1754. cb = PACKET_MAX_SIZE;
  1755. }
  1756. //
  1757. // Format state manipulate message
  1758. //
  1759. m.ApiNumber = DbgKdReadPhysicalMemoryApi;
  1760. m.ReturnStatus = STATUS_PENDING;
  1761. a = &m.u.ReadMemory;
  1762. a->TargetBaseAddress = TargetBaseAddress+cb2;
  1763. a->TransferCount = cb;
  1764. a->ActualBytesRead = 0L;
  1765. //
  1766. // Send the message and then wait for reply
  1767. //
  1768. do
  1769. {
  1770. g_DbgKdTransport->WritePacket(&m, sizeof(m),
  1771. PACKET_TYPE_KD_STATE_MANIPULATE,
  1772. NULL, 0);
  1773. rc = g_DbgKdTransport->
  1774. WaitForPacket(PACKET_TYPE_KD_STATE_MANIPULATE, &Reply);
  1775. } while (rc != DBGKD_WAIT_PACKET ||
  1776. Reply->ApiNumber != DbgKdReadPhysicalMemoryApi);
  1777. st = Reply->ReturnStatus;
  1778. a = &Reply->u.ReadMemory;
  1779. DBG_ASSERT(a->ActualBytesRead <= cb);
  1780. //
  1781. // Return actual bytes read, and then transfer the bytes
  1782. //
  1783. if (ARGUMENT_PRESENT(ActualBytesRead)) {
  1784. *ActualBytesRead += a->ActualBytesRead;
  1785. }
  1786. //
  1787. // Since read response data follows message, Reply+1 should point
  1788. // at the data
  1789. //
  1790. if (NT_SUCCESS(st))
  1791. {
  1792. memcpy((PCHAR)((ULONG_PTR) UserInterfaceBuffer+cb2), Reply+1, (int)a->ActualBytesRead);
  1793. TransferCount -= a->ActualBytesRead;
  1794. if (TransferCount)
  1795. {
  1796. cb2 += a->ActualBytesRead;
  1797. goto readmore;
  1798. }
  1799. }
  1800. KdOut("DbgKdReadPhysical memory TargetBaseAddress %s, status %08lx\n",
  1801. FormatAddr64(TargetBaseAddress), st);
  1802. return st;
  1803. }
  1804. NTSTATUS
  1805. DbgKdWritePhysicalMemory(
  1806. IN ULONG64 TargetBaseAddress,
  1807. OUT PVOID UserInterfaceBuffer,
  1808. IN ULONG TransferCount,
  1809. OUT PULONG ActualBytesWritten OPTIONAL
  1810. )
  1811. /*++
  1812. Routine Description:
  1813. This function writes the specified data to the physical memory of the
  1814. system being debugged.
  1815. Arguments:
  1816. TargetBaseAddress - Supplies the physical address of the memory to write
  1817. to the system being debugged.
  1818. UserInterfaceBuffer - Supplies the address of the buffer in the user
  1819. interface that contains the data to be written.
  1820. TransferCount - Specifies the number of bytes to write.
  1821. ActualBytesWritten - An optional parameter that if supplied, returns
  1822. the number of bytes actually written.
  1823. Return Value:
  1824. STATUS_SUCCESS - The specified read occured.
  1825. STATUS_BUFFER_OVERFLOW - A read that is to large was specified.
  1826. --*/
  1827. {
  1828. DBGKD_MANIPULATE_STATE64 m;
  1829. PDBGKD_MANIPULATE_STATE64 Reply;
  1830. PDBGKD_WRITE_MEMORY64 a;
  1831. NTSTATUS st;
  1832. ULONG rc;
  1833. ULONG cb, cb2;
  1834. g_VirtualCache.Empty ();
  1835. cb2 = 0;
  1836. if (ARGUMENT_PRESENT(ActualBytesWritten)) {
  1837. *ActualBytesWritten = 0;
  1838. }
  1839. writemore:
  1840. cb = TransferCount;
  1841. if (cb > PACKET_MAX_SIZE) {
  1842. cb = PACKET_MAX_SIZE;
  1843. }
  1844. //
  1845. // Format state manipulate message
  1846. //
  1847. m.ApiNumber = DbgKdWritePhysicalMemoryApi;
  1848. m.ReturnStatus = STATUS_PENDING;
  1849. a = &m.u.WriteMemory;
  1850. a->TargetBaseAddress = TargetBaseAddress+cb2;
  1851. a->TransferCount = cb;
  1852. a->ActualBytesWritten = 0L;
  1853. //
  1854. // Send the message and data to write and then wait for reply
  1855. //
  1856. do
  1857. {
  1858. g_DbgKdTransport->WritePacket(&m, sizeof(m),
  1859. PACKET_TYPE_KD_STATE_MANIPULATE,
  1860. (PVOID)
  1861. ((ULONG_PTR)UserInterfaceBuffer+cb2),
  1862. (USHORT)cb);
  1863. rc = g_DbgKdTransport->
  1864. WaitForPacket(PACKET_TYPE_KD_STATE_MANIPULATE, &Reply);
  1865. } while (rc != DBGKD_WAIT_PACKET ||
  1866. Reply->ApiNumber != DbgKdWritePhysicalMemoryApi);
  1867. st = Reply->ReturnStatus;
  1868. a = &Reply->u.WriteMemory;
  1869. DBG_ASSERT(a->ActualBytesWritten <= cb);
  1870. //
  1871. // Return actual bytes written
  1872. //
  1873. if (ARGUMENT_PRESENT(ActualBytesWritten)) {
  1874. *ActualBytesWritten += a->ActualBytesWritten;
  1875. }
  1876. if (NT_SUCCESS(st))
  1877. {
  1878. TransferCount -= a->ActualBytesWritten;
  1879. if (TransferCount)
  1880. {
  1881. cb2 += a->ActualBytesWritten;
  1882. goto writemore;
  1883. }
  1884. }
  1885. KdOut("DbgKdWritePhysical memory %08lx\n", st);
  1886. return st;
  1887. }
  1888. NTSTATUS
  1889. DbgKdCheckLowMemory(
  1890. )
  1891. /*++
  1892. Routine Description:
  1893. This function forces a call on the system being debugged that will check
  1894. if physical pages lower than 4gb have a specific fill pattern.
  1895. Arguments:
  1896. None.
  1897. Return Value:
  1898. STATUS_SUCCESS - The specified read occured.
  1899. --*/
  1900. {
  1901. DBGKD_MANIPULATE_STATE64 m;
  1902. PDBGKD_MANIPULATE_STATE64 Reply;
  1903. ULONG rc;
  1904. //
  1905. // Format state manipulate message
  1906. //
  1907. RtlZeroMemory (&m, sizeof(m));
  1908. m.ApiNumber = DbgKdCheckLowMemoryApi;
  1909. m.ReturnStatus = STATUS_PENDING;
  1910. //
  1911. // We wait for an answer from the kernel side.
  1912. //
  1913. do
  1914. {
  1915. g_DbgKdTransport->WritePacket(&m, sizeof(m),
  1916. PACKET_TYPE_KD_STATE_MANIPULATE,
  1917. NULL, 0);
  1918. rc = g_DbgKdTransport->
  1919. WaitForPacket(PACKET_TYPE_KD_STATE_MANIPULATE, &Reply);
  1920. } while (rc != DBGKD_WAIT_PACKET);
  1921. if (Reply->ReturnStatus != STATUS_SUCCESS)
  1922. {
  1923. dprintf ("Corrupted page with pfn %x \n", Reply->ReturnStatus);
  1924. }
  1925. KdOut("DbgKdCheckLowMemory 0x00000000\n");
  1926. return STATUS_SUCCESS;
  1927. }
  1928. NTSTATUS
  1929. DbgKdSwitchActiveProcessor (
  1930. IN ULONG ProcessorNumber
  1931. )
  1932. /*++
  1933. Routine Description:
  1934. Arguments:
  1935. ProcessorNumber -
  1936. Return Value:
  1937. STATUS_SUCCESS - Successful call to DbgUiContinue
  1938. STATUS_INVALID_PARAMETER - An invalid continue status or was
  1939. specified.
  1940. --*/
  1941. {
  1942. DBGKD_MANIPULATE_STATE64 m;
  1943. m.ApiNumber = (USHORT)DbgKdSwitchProcessor;
  1944. m.Processor = (USHORT)ProcessorNumber;
  1945. // Quiet PREfix warnings.
  1946. m.ProcessorLevel = 0;
  1947. g_DbgKdTransport->WritePacket(&m, sizeof(m),
  1948. PACKET_TYPE_KD_STATE_MANIPULATE,
  1949. NULL, 0);
  1950. g_VirtualCache.Empty ();
  1951. KdOut("DbgKdSwitchActiveProcessor 0x00000000\n");
  1952. return STATUS_SUCCESS;
  1953. }
  1954. NTSTATUS
  1955. DbgKdSearchMemory(
  1956. IN ULONG64 SearchAddress,
  1957. IN ULONG64 SearchLength,
  1958. IN PUCHAR Pattern,
  1959. IN ULONG PatternLength,
  1960. OUT PULONG64 FoundAddress
  1961. )
  1962. {
  1963. DBGKD_MANIPULATE_STATE64 m;
  1964. PDBGKD_MANIPULATE_STATE64 Reply;
  1965. PDBGKD_SEARCH_MEMORY a = &m.u.SearchMemory;
  1966. ULONG rc;
  1967. NTSTATUS st;
  1968. KdOut("Search called %s, length %I64x\n",
  1969. FormatAddr64(SearchAddress), SearchLength);
  1970. *FoundAddress = 0;
  1971. a->SearchAddress = SearchAddress;
  1972. a->SearchLength = SearchLength;
  1973. a->PatternLength = PatternLength;
  1974. m.ApiNumber = DbgKdSearchMemoryApi;
  1975. m.ReturnStatus = STATUS_PENDING;
  1976. //
  1977. // Send the message and data to write and then wait for reply
  1978. //
  1979. do
  1980. {
  1981. g_DbgKdTransport->WritePacket(&m, sizeof(m),
  1982. PACKET_TYPE_KD_STATE_MANIPULATE,
  1983. Pattern, (USHORT)PatternLength);
  1984. rc = g_DbgKdTransport->
  1985. WaitForPacket(PACKET_TYPE_KD_STATE_MANIPULATE, &Reply);
  1986. } while (rc != DBGKD_WAIT_PACKET ||
  1987. Reply->ApiNumber != DbgKdSearchMemoryApi);
  1988. st = Reply->ReturnStatus;
  1989. if (NT_SUCCESS(st))
  1990. {
  1991. if (g_TargetMachine->m_Ptr64)
  1992. {
  1993. *FoundAddress = Reply->u.SearchMemory.FoundAddress;
  1994. }
  1995. else
  1996. {
  1997. *FoundAddress = EXTEND64(Reply->u.SearchMemory.FoundAddress);
  1998. }
  1999. }
  2000. KdOut("DbgKdSearchMemory %08lx\n", st);
  2001. return st;
  2002. }
  2003. NTSTATUS
  2004. DbgKdFillMemory(
  2005. IN ULONG Flags,
  2006. IN ULONG64 Start,
  2007. IN ULONG Size,
  2008. IN PVOID Pattern,
  2009. IN ULONG PatternSize,
  2010. OUT PULONG Filled
  2011. )
  2012. {
  2013. DBGKD_MANIPULATE_STATE64 Manip;
  2014. PDBGKD_MANIPULATE_STATE64 Reply;
  2015. NTSTATUS Status = STATUS_SUCCESS;
  2016. DBG_ASSERT(g_KdMaxManipulate > DbgKdFillMemoryApi &&
  2017. (Flags & 0xffff0000) == 0 &&
  2018. PatternSize <= PACKET_MAX_SIZE);
  2019. // Invalidate any cached memory.
  2020. if (Flags & DBGKD_FILL_MEMORY_VIRTUAL)
  2021. {
  2022. g_VirtualCache.Remove(Start, Size);
  2023. }
  2024. else if (Flags & DBGKD_FILL_MEMORY_PHYSICAL)
  2025. {
  2026. g_PhysicalCache.Remove(Start, Size);
  2027. }
  2028. //
  2029. // Initialize state manipulate message to fill memory.
  2030. //
  2031. Manip.ApiNumber = DbgKdFillMemoryApi;
  2032. Manip.u.FillMemory.Address = Start;
  2033. Manip.u.FillMemory.Length = Size;
  2034. Manip.u.FillMemory.Flags = (USHORT)Flags;
  2035. Manip.u.FillMemory.PatternLength = (USHORT)PatternSize;
  2036. //
  2037. // Send the message and data to the target system and wait
  2038. // for a reply.
  2039. //
  2040. ULONG Recv;
  2041. do
  2042. {
  2043. g_DbgKdTransport->WritePacket(&Manip, sizeof(Manip),
  2044. PACKET_TYPE_KD_STATE_MANIPULATE,
  2045. Pattern, (USHORT)PatternSize);
  2046. Recv = g_DbgKdTransport->
  2047. WaitForPacket(PACKET_TYPE_KD_STATE_MANIPULATE, &Reply);
  2048. }
  2049. while ((Recv != DBGKD_WAIT_PACKET) ||
  2050. (Reply->ApiNumber != DbgKdFillMemoryApi));
  2051. Status = Reply->ReturnStatus;
  2052. *Filled = Reply->u.FillMemory.Length;
  2053. KdOut("DbgKdFillMemory returns %08lx\n", Status);
  2054. return Status;
  2055. }
  2056. NTSTATUS
  2057. DbgKdQueryMemory(
  2058. IN ULONG64 Address,
  2059. IN ULONG InSpace,
  2060. OUT PULONG OutSpace,
  2061. OUT PULONG OutFlags
  2062. )
  2063. {
  2064. DBGKD_MANIPULATE_STATE64 Manip;
  2065. PDBGKD_MANIPULATE_STATE64 Reply;
  2066. NTSTATUS Status = STATUS_SUCCESS;
  2067. DBG_ASSERT(g_KdMaxManipulate > DbgKdQueryMemoryApi);
  2068. //
  2069. // Initialize state manipulate message to query memory.
  2070. //
  2071. Manip.ApiNumber = DbgKdQueryMemoryApi;
  2072. Manip.u.QueryMemory.Address = Address;
  2073. Manip.u.QueryMemory.Reserved = 0;
  2074. Manip.u.QueryMemory.AddressSpace = InSpace;
  2075. Manip.u.QueryMemory.Flags = 0;
  2076. //
  2077. // Send the message and data to the target system and wait
  2078. // for a reply.
  2079. //
  2080. ULONG Recv;
  2081. do
  2082. {
  2083. g_DbgKdTransport->WritePacket(&Manip, sizeof(Manip),
  2084. PACKET_TYPE_KD_STATE_MANIPULATE,
  2085. NULL, 0);
  2086. Recv = g_DbgKdTransport->
  2087. WaitForPacket(PACKET_TYPE_KD_STATE_MANIPULATE, &Reply);
  2088. }
  2089. while ((Recv != DBGKD_WAIT_PACKET) ||
  2090. (Reply->ApiNumber != DbgKdQueryMemoryApi));
  2091. Status = Reply->ReturnStatus;
  2092. *OutSpace = Reply->u.QueryMemory.AddressSpace;
  2093. *OutFlags = Reply->u.QueryMemory.Flags;
  2094. KdOut("DbgKdQueryMemory returns %08lx\n", Status);
  2095. return Status;
  2096. }