📄 ethdbg.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:
ethdbg.c
Abstract:
Routines for kernel debug services over Ethernet (KITL). For platforms
that have a debug ethernet controller, this will allow the following
services to be configured to run over the ethernet:
o Debug messages
o Kernel debugger
o Text shell and PPFS file system
o Other user defined applications (e.g. profiling, test apps, etc)
To provide reliability and data integrity, communication with the desktop is
done via UDP, with the KITL protocol on top to provide reliability. For efficiency,
the KITL protocol maintains a simple sliding window algorithm, so that multiple
packets may be outstanding
Functions:
Notes:
--*/
#include <windows.h>
#include <types.h>
#include <nkintr.h>
#include <kitl.h>
#include <kitlpriv.h>
#include "kitlp.h"
#include "kernel.h"
DWORD SC_WaitForMultiple(DWORD cObjects, CONST HANDLE *lphObjects, BOOL fWaitAll, DWORD dwTimeout);
// Priority for IST. Since the SMC chip has a fairly small Rx packet buffer,
// run at high priority to avoid overruns. Note the OEM can modify this value in
// the OAL (OEMInit()).
#define KITL_IST_PRIORITY 130
#define KITL_TIMER_PRIORITY 247 // lowest RT priority
DWORD g_dwKITLThreadPriority = KITL_IST_PRIORITY;
DWORD g_dwKITLTimerThreadPriority = KITL_TIMER_PRIORITY;
// Priority for timer thread. This just processes retransmissions, can run at
// lower priority.
// Bitmask which indicates global state
DWORD KITLGlobalState;
// Structures to maintain state of registered clients. Reserve space for the
// three default services, plus some for user defined applications. The ServiceId
// identifiers are indices into this array.
// we now do dynamic allocation for clients. The name of a service, except
// for default services, is now used to hash into the structure to provide
// some level of uniqueness of service id. Note that client structure will
// NOT be de-allocated once allocated.
#define HEAP_KITLCLIENT HEAP_MUTEX
ERRFALSE(sizeof(KITL_CLIENT) <= sizeof(MUTEX));
KITL_CLIENT DfltClnts[NUM_DFLT_KITL_SERVICES];
PKITL_CLIENT KITLClients[MAX_KITL_CLIENTS];
// Buffers for default services - since PPFS and windbg use byte at a time operations, we need
// to format commands in a buffer before sending to other side. Since both PPFS and windbg are
// serialized while sending commands, we can share a single buffer for send and receive.
static UCHAR PpfsFmtBuf[(KITL_MAX_DATA_SIZE+3)&~3]; // make it DWORD aligned
static UCHAR KdbgFmtBuf[(KITL_MAX_DATA_SIZE+3)&~3]; // make it DWORD aligned
// Receive buffers for ISR routine. Need two, because we may have filled a buffer in the
// ISR, then get swapped out and another thread may need to do polled I/O.
static UCHAR ISTRecvBuf[KITL_MTU];
KITLTRANSPORT Kitl;
HANDLE hIntrThread;
HANDLE hTimerThread;
// To prevent interleaving of our debug output
CRITICAL_SECTION KITLODScs;
// cs to pretect timer list
CRITICAL_SECTION TimerListCS;
// critical section in place of KCall
CRITICAL_SECTION KITLKCallcs;
#define KITL_BUFFER_POOL_SIZE (KITL_MAX_WINDOW_SIZE * 2 * KITL_MTU)
// buffer for default clients, must be DWORD aligned
static DWORD g_KitlBuffer[((KITL_BUFFER_POOL_SIZE * NUM_DFLT_KITL_SERVICES) + (sizeof(DWORD) - 1)) / sizeof(DWORD)];
// cs to protect client list
extern CRITICAL_SECTION KITLcs;
extern BOOL fKITLcsInitialized;
void ResetClientState(KITL_CLIENT *pClient);
void SetClientEvent(KITL_CLIENT *pClient, HANDLE hEvent);
// Local functions
static BOOL StartKitl (BOOL fInit);
static BOOL RegisterClientPart2(UCHAR Id);
static void EnableInts();
static DWORD KITLInterruptThread(DWORD fEnableInts);
static BOOL DoRegisterClient (UCHAR *pId, char *ServiceName, UCHAR Flags, UCHAR WindowSize, UCHAR *pBufferPool);
/*
* @doc KITL
* @func VOID | KITLSetDebug | Controls debug print output for KITL subsystem.
* @comm Used to debug the KITL routines (only enabled for DEBUG versions of ethdbg.dll).
* Debug messages are written to the debug serial port, based on the value
* of the DebugZoneMask parameter. Some of the more useful zones are ZONE_INIT
* (messages related to client registration), ZONE_WARNING (unusual conditions
* and lost frames), and ZONE_FRAMEDUMP (dump of all packets sent - verbose!).
* See ethdbg.h for all zone definitions.
*/
DWORD KITLDebugZone = ZONE_INIT|ZONE_ERROR;//|ZONE_WARNING|ZONE_FRAMEDUMP|ZONE_RECV;
void KITLSetDebug (DWORD DebugZoneMask)
{
KITLOutputDebugString("Changed KITL zone mask to 0x%X\n",DebugZoneMask);
KITLDebugZone = DebugZoneMask;
}
BOOL IsDesktopDbgrExist ()
{
return (DfltClnts[KERNEL_SVC_KDBG].State & KITL_CLIENT_REGISTERED);
}
//
// NewClient: create a new client structure and initialized it
//
static PKITL_CLIENT NewClient (UCHAR uId, LPCSTR pszSvcName, BOOL fAlloc)
{
DEBUGCHK(IS_VALID_ID(uId));
DEBUGCHK (!KITLClients[uId]);
if (strlen(pszSvcName) >= MAX_SVC_NAMELEN)
return NULL;
if (!fAlloc) {
DEBUGCHK(IS_DFLT_SVC(uId));
KITLClients[uId] = &DfltClnts[uId];
} else if (!(KITLClients[uId] = (PKITL_CLIENT) AllocMem (HEAP_KITLCLIENT))) {
return NULL;
}
memset (KITLClients[uId], 0, sizeof(KITL_CLIENT));
KITLClients[uId]->ServiceId = uId;
strcpy (KITLClients[uId]->ServiceName, pszSvcName);
return KITLClients[uId];
}
//
// ChkDfltSvc: return id if it's a default service, -1 if not
//
int ChkDfltSvc (LPCSTR ServiceName)
{
int i;
for (i = 0; i < NUM_DFLT_KITL_SERVICES; i ++) {
if (strcmp (KITLClients[i]->ServiceName, ServiceName) == 0)
return i;
}
return -1;
}
/* KITLRegisterDfltClient
*
* Register one of the 3 default services (DBGMSG, PPSH, KDBG). These are registered
* differently from other KITL services - the window size and buffer pools are
* supplied in the HAL. Additionally, we provide a couple of buffers for use by the
* kernel in formatting KITL messages - Since PPSH and KDBG use byte at a time I/O,
* these buffers are used to gather up to KITL_MAX_DATA_SIZE bytes to ship across KITL.
*/
BOOL
KITLRegisterDfltClient(
UCHAR Service, // IN - Service ID (one of KITL_SVC_ defs from ethdbg.h)
UCHAR Flags, // IN - Flags (one of KITL_CFGFL_ defs from ethdbg.h)
UCHAR **ppTxBuffer, // OUT- Receives pointer to formatting buffer, if appropriate
UCHAR **ppRxBuffer) // OUT- Receives pointer to formatting buffer, if appropriate
{
UCHAR Id, *pBufferPool;
KITL_CLIENT *pClient;
BOOL fRet = TRUE;
KITL_DEBUGMSG(ZONE_INIT,("+KITLRegisterDfltClient, service:%u\n",Service));
if (!IS_DFLT_SVC(Service)) {
return FALSE;
}
if (fKITLcsInitialized && !InSysCall ()) {
EnterCriticalSection (&KITLcs);
}
if (!StartKitl (FALSE)) {
KITLOutputDebugString ("!KITLRegisterDfltClient: Fail to initialize KITL\n");
fRet = FALSE;
} else {
pClient = KITLClients[Service];
DEBUGCHK (pClient);
switch (Service) {
case KITL_SVC_DBGMSG:
// start DBGMSG service?
if (!(Kitl.dwBootFlags & KITL_FL_DBGMSG)) {
fRet = FALSE;
goto exit;
}
pBufferPool = (LPBYTE) Kitl.dwPhysBuffer;
// No special buffer needed for debug messages
break;
case KITL_SVC_PPSH:
// start PPSH service?
if (!(Kitl.dwBootFlags & KITL_FL_PPSH)) {
fRet = FALSE;
goto exit;
}
pBufferPool = (LPBYTE) (Kitl.dwPhysBuffer + KITL_BUFFER_POOL_SIZE);
*ppTxBuffer = *ppRxBuffer = PpfsFmtBuf;
break;
case KITL_SVC_KDBG:
// start KD service?
if (!(Kitl.dwBootFlags & KITL_FL_KDBG)) {
fRet = FALSE;
goto exit;
}
pBufferPool = (LPBYTE) (Kitl.dwPhysBuffer + 2 * KITL_BUFFER_POOL_SIZE);
*ppTxBuffer = *ppRxBuffer = KdbgFmtBuf;
break;
default:
fRet = FALSE;
}
}
if (fRet)
fRet = DoRegisterClient(&Id, pClient->ServiceName, Flags, Kitl.WindowSize, pBufferPool);
exit:
if (fKITLcsInitialized && !InSysCall ()) {
LeaveCriticalSection (&KITLcs);
}
return fRet;
}
/*
* @func BOOL | KITLRegisterClient | Register a client for debug Ethernet (KITL) service.
* @rdesc Returns TRUE if registration succeeds, FALSE if another client has already
* registered for service, or error occurs connecting to peer.
* @comm Function to register a client for an KITL service. Each service has a unique
* name which identifies it. Certain service names are reserved for default OS
* services (e.g. "DBGMSG"). Other names may be used for user defined applications.
* Registration will not complete until a peer client has registered for this service.
* If the peer address is known (e.g. for default OS clients, eshell sends this
* information in JUMPIMG command when device is booted), then we'll start sending
* config messages to the other side. Otherwise, a passive connect is performed,
* and we wait for the peer to connect to us. For user applications, this means that
* this function will block until the peer application is started on the desktop.
* @xref <f KITLDeregisterClient>
*/
BOOL
KITLRegisterClient(
UCHAR *pId, // @parm [OUT] - Receives identifier to pass in to KITLSend/Recv
char *ServiceName, // @parm [IN] - Service name (NULL terminated, up to MAX_SVCNAME_LEN chars)
UCHAR Flags, // @parm [IN] - KITL_CFGFL_ flags, defined in ethdbg.h
UCHAR WindowSize, // @parm [IN] - Protocol window size (default is 8)
UCHAR *pBufferPool) // @parm [IN] - Buffer pool to use for KITL packet buffers - must be WindowSize*2*1500 bytes, unless STOP_AND_WAIT flag is set, in which
// case, need only be 2*1500 bytes. For default OS services, may be NULL.
{
BOOL fRet = FALSE;
KITL_DEBUGMSG(ZONE_INIT,("+KITLRegisterClient(%s): Flags: %u, WindowSize: %u, BufferPool: %X\n",
ServiceName,Flags,WindowSize,pBufferPool));
EnterCriticalSection (&KITLcs);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -