📄 edbgprot.c
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// This source code is licensed under Microsoft Shared Source License
// Version 1.0 for Windows CE.
// For a copy of the license visit http://go.microsoft.com/fwlink/?LinkId=3223.
//
/*++
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
PARTICULAR PURPOSE.
Module Name:
edbgprot.c
Abstract:
Routines for kernel debug services over Ethernet (KITL). This file contains
the core functions to implement the KITL protocol over UDP.
Functions:
Notes:
--*/
#include <windows.h>
#include <types.h>
#include <nkintr.h>
#include <kitl.h>
#include <kitlprot.h>
#include "kernel.h"
#include "kitlp.h"
DWORD SC_WaitForMultiple(DWORD cObjects, CONST HANDLE *lphObjects, BOOL fWaitAll, DWORD dwTimeout);
// time to retransmit if using ticks
#define MIN_POLL_TIME 1000
#define MAX_POLL_TIME 8000
// time to retransmit if using iterations
#define MIN_POLL_ITER 10000
#define MAX_POLL_ITER 1600000
static UCHAR PollRecvBuf[KITL_MTU];
static BOOL ProcessRecvFrame(UCHAR *pFrame, WORD wMsgLen, BOOL fUseSysCalls, PFN_TRANSMIT pfnTransmit, LPVOID pData);
static void KITLDecodeFrame(char *LeadingText, KITL_HDR *pHdr, WORD wLen);
static BOOL ProcessAdminMsg(KITL_HDR *pHdr, WORD wMsgLen, BOOL fUseSysCalls, PFN_TRANSMIT pfnTransmit, LPVOID pData);
extern CRITICAL_SECTION KITLODScs;
extern CRITICAL_SECTION KITLKCallcs;
extern KITLTRANSPORT Kitl;
extern BOOL IsDesktopDbgrExist (void);
extern BOOL KernelIoctl (DWORD , LPVOID , DWORD , LPVOID , DWORD , LPDWORD );
extern DWORD g_dwKeys[];
extern CHAR* g_keyNames[];
#include "..\..\..\..\..\public\common\oak\dbgpub\dbgbrk.c" // For DoDebugBreak()
/* SetClientEvent
*
* Adjust proc permissions to match client and set event
*/
void SetClientEvent(KITL_CLIENT *pClient, HANDLE hEvent)
{
DWORD OldProcPerms;
if (pClient->ProcPerms) {
SWITCHKEY (OldProcPerms, pClient->ProcPerms);
}
if (hEvent && !SC_EventModify(hEvent, EVENT_SET)) {
KITL_DEBUGMSG(ZONE_ERROR,("!SetClientEvent:Error %u setting event %X..\n",GetLastError(),hEvent));
}
if (pClient->ProcPerms) {
SETCURKEY (OldProcPerms);
}
}
/* ResetClientState
*
* Reset all state associated with client struct.
* Must hold client CS while calling this function.
*/
void
ResetClientState(KITL_CLIENT *pClient)
{
// When system is coming up, we can't make any system calls.
UCHAR UseSysCalls = (pClient->State & KITL_USE_SYSCALLS);
// Cancel any timers
CancelTimersForClient(pClient);
// Reset our state
pClient->TxSeqNum = 0;
pClient->AckExpected = 0;
pClient->RxSeqNum = 0;
pClient->RxWinEnd = pClient->WindowSize;
memset(&pClient->TxFrameLen,0,sizeof(pClient->TxFrameLen));
memset(&pClient->RxFrameLen,0,sizeof(pClient->RxFrameLen));
pClient->NextRxIndex = 0;
pClient->State &= ~KITL_SYNCED;
// Unblock any threads which might be stuck
if (UseSysCalls) {
SetClientEvent(pClient,pClient->evTxFull);
// For now, let recv threads keep blocking. We might want to return an error
// here, investigate later.
// SetEvent(pClient->evRecv);
}
}
static BOOL KITLPollData(BOOL fUseSysCalls, PFN_TRANSMIT pfnTransmit, LPVOID pData)
{
LPBYTE pRecvBuf = PollRecvBuf;
if (fUseSysCalls && (KITLGlobalState & KITL_ST_MULTITHREADED)
&& !(pRecvBuf = _alloca(KITL_MTU))) {
KITLOutputDebugString("!KITLPollData: STACK OVERFLOW!\r\n");
return FALSE;
}
HandleRecvInterrupt(pRecvBuf, fUseSysCalls, pfnTransmit, pData);
return TRUE;
}
static BOOL CheckCfg (KITL_CLIENT *pClient)
{
return !(pClient->State & KITL_WAIT_CFG);
}
static BOOL RetransmitCfg (KITL_CLIENT *pClient, BOOL fUseSysCalls)
{
return SendConfig (pClient, FALSE);
}
/* ExchangeConfig
*
* If we have peer address (e.g. for default services, we get this info from eshell at boot),
* send config message to peer, indicating the service ID and window size to use. Otherwise,
* do passive connect (desktop app will get device address from eshell, then send us a config
* message).
*/
BOOL ExchangeConfig(KITL_CLIENT *pClient)
{
// When system is coming up, we can't make any system calls.
BOOL fUseSysCalls = (pClient->State & KITL_USE_SYSCALLS)? TRUE : FALSE;
if (!(pClient->State & KITL_WAIT_CFG))
return 0 != (pClient->State & KITL_CLIENT_REGISTERED);
KITL_DEBUGMSG(ZONE_INIT,("Waiting for service '%s' to connect..., fUseSysCalls = %d\n", pClient->ServiceName, fUseSysCalls));
if (fUseSysCalls && (KITLGlobalState & KITL_ST_INT_ENABLED)) {
DWORD Timeout = MIN_POLL_TIME;
while (pClient->State & KITL_WAIT_CFG) {
if (!SendConfig (pClient, FALSE)) {
return FALSE;
}
switch (SC_WaitForMultiple (1, &pClient->evCfg, 0, Timeout)) {
case WAIT_OBJECT_0:
return (0 != (pClient->State & KITL_CLIENT_REGISTERED));
case WAIT_TIMEOUT:
if (Timeout < MAX_POLL_TIME)
Timeout <<= 1;
break;
default:
KITLOutputDebugString("!ExchangeConfig: WaitForMultipleObjects failed\n");
return FALSE;
}
}
} else {
if (!SendConfig (pClient, FALSE))
return FALSE;
KITLPollResponse (fUseSysCalls, CheckCfg, RetransmitCfg, pClient);
}
return 0 != (pClient->State & KITL_CLIENT_REGISTERED);
}
BOOL SendConfig(KITL_CLIENT *pClient, BOOL fIsResp)
{
UCHAR *FmtBuf;
KITL_HDR *pHdr;
KITL_SVC_CONFIG_DATA *pConfigData;
FmtBuf = (UCHAR *) _alloca (Kitl.FrmHdrSize // for transport header
+ sizeof(KITL_HDR) // for protocol header
+ sizeof(KITL_SVC_CONFIG_DATA) // for data
+ Kitl.FrmTlrSize); // for transport tailer
if (!FmtBuf) {
KITLOutputDebugString ("!SendConfig: Stack overflow\r\n");
return FALSE;
}
pHdr = (KITL_HDR *)(FmtBuf + Kitl.FrmHdrSize); // pointer to the protocol header
pConfigData = (KITL_SVC_CONFIG_DATA *) KITLDATA(pHdr); // pointer to the data
// Format protocol header
pHdr->Id = KITL_ID;
pHdr->Service = KITL_SVC_ADMIN;
pHdr->Flags = KITL_FL_FROM_DEV;
if (fIsResp)
pHdr->Flags |= KITL_FL_ADMIN_RESP;
pHdr->SeqNum = 0;
pHdr->Cmd = KITL_CMD_SVC_CONFIG;
// Format service config message
pConfigData->ProtocolVersion = CURRENT_KITL_VERSION;
strcpy(pConfigData->ServiceName,pClient->ServiceName);
pConfigData->ServiceId = pClient->ServiceId;
pConfigData->WindowSize = pClient->WindowSize;
pConfigData->Flags = pClient->CfgFlags;
if (KITLDebugZone & ZONE_FRAMEDUMP)
KITLDecodeFrame(">>SendConfig", pHdr, sizeof(KITL_HDR) + sizeof(KITL_SVC_CONFIG_DATA));
if (!KitlSendFrame (FmtBuf, sizeof(KITL_HDR) + sizeof(KITL_SVC_CONFIG_DATA))) {
KITLOutputDebugString("!SendConfig: Error in KitlSendFrame\n");
return FALSE;
}
return TRUE;
}
BOOL KITLPollResponse (BOOL fUseSysCalls, PFN_CHECK pfnCheck, PFN_TRANSMIT pfnTransmit, LPVOID pData)
{
DWORD dwLoopCnt = 0, dwLoopMax = MIN_POLL_ITER;
DWORD dwStartTime = CurMSec;
int nTimeMax = MIN_POLL_TIME; // start with 1 sec
BOOL fUseIter = FALSE, fUseTick = FALSE;
while (!pfnCheck (pData)) {
//
// if we've already connected with desktop, use the desktop
// "Retransmit" package to determine if we need to retransmit
//
if (!(KITLGlobalState & KITL_ST_DESKTOP_CONNECTED)) {
if (fUseTick) {
if ((int) (CurMSec - dwStartTime) > nTimeMax) {
// retransmit
if (!pfnTransmit (pData, fUseSysCalls))
return FALSE;
dwStartTime = CurMSec;
if (nTimeMax < MAX_POLL_TIME)
nTimeMax <<= 1;
}
} else if (fUseIter || (dwStartTime == CurMSec)) {
// if time isn't moving for a while, we'll
// use iteration.
if (dwLoopCnt ++ > dwLoopMax) {
if (!pfnTransmit (pData, fUseSysCalls))
return FALSE;
if (dwLoopMax < MAX_POLL_ITER)
dwLoopMax <<= 1;
dwLoopCnt = 0;
fUseIter = TRUE;
}
} else {
// time is moving, just use tick from here
fUseTick = TRUE;
}
}
if (!KITLPollData(fUseSysCalls, pfnTransmit, pData)) {
return FALSE;
}
}
return TRUE;
}
static BOOL ChkAck (KITL_CLIENT *pClient)
{
return pClient->AckExpected == pClient->TxSeqNum;
}
static BOOL TranAck (KITL_CLIENT *pClient, BOOL fUseSysCalls)
{
UCHAR Seq;
for (Seq = pClient->AckExpected; Seq != pClient->TxSeqNum; SEQ_INC (Seq))
RetransmitFrame (pClient, (UCHAR) (Seq % pClient->WindowSize), fUseSysCalls);
return TRUE;
}
/* @doc KITL
* @func BOOL | KITLSend | Send a message over debug Ethernet interface.
* @rdesc Return TRUE if successful, FALSE if error occurrs.
* @comm Send a message to peer KITL client. Returns immediately unless the transmit
* window is full, or if we're in polling mode, in which case this function will
* block. Once sent, the message will be retried by the KITL subsystem until
* it is acknowledged by other side.
* @xref <f KITLRegisterClient> <f KITLRecv>
*/
static HANDLE hDbgMsgThread;
extern HANDLE hIntrThread;
extern HANDLE hTimerThread;
BOOL
KITLSend(
UCHAR Id, // @parm [IN] - KITL client id (returned from <f KITLRegisterClient>)
UCHAR *pUserData, // @parm [IN] - Data to send.
DWORD dwUserDataLen ) // @parm [IN] - Data length (up to KITL_MAX_DATA_SIZE).
{
KITL_CLIENT *pClient = KITLClients[Id];
PKITL_HDR pHdr;
UCHAR *pFrame, *pData;
BOOL fRet = TRUE;
DWORD dwPacketIndex;
UCHAR PrevSyscallState;
BOOL fRestoreClientState = FALSE, fRestoreGlobalState = FALSE;
BOOL fUseSysCalls;
if (!IS_VALID_ID(Id))
return FALSE;
// Check that client is registered
if (!pClient || (pClient->ServiceId != Id))
return FALSE;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -