📄 monitor.c
字号:
/*++
Copyright (c) 1997 Microsoft Corporation
Module Name:
monitor.c
Abstract:
This file contains the monitor for the firmware.
Author:
Lluis Abello (lluis) 09-Sep-91
Revision History:
Jun Liu 8/6/96 Modified for Puzzle
John Cooper (johncoop) 97-Oct-21: Modified for LC2
--*/
#include <windows.h>
#include <halether.h>
#include "workitem.h"
#ifdef MONITOR_USED
#include "monitor.h"
#define BYTE_SIZE 1
#define HALF_SIZE 2
#define WORD_SIZE 4
extern PCHAR RegisterNameTable[];
//
// declare static variables.
//
ULONG Argc;
ULONG CurrentArg;
COMMAND_NAME_ID CurrentCommand;
ULONG DataSize;
ULONG DataSizeMask;
ULONG DataSizeShift;
ULONG DefaultAddress;
PCHAR CommandNameTable[(COMMAND_NAME_ID)invalidcommand] = {
"d",
"db",
"dw",
"dd",
"e",
"eb",
"ew",
"ed",
"o",
"ob",
"ow",
"od",
"i",
"ib",
"iw",
"id",
"r",
"z",
"f",
"a",
"rm",
"tlb",
"cache",
"h",
"?",
"q",
"j"
};
REGISTER_NAME_ID
GetRegister(
IN PCHAR RegName
)
/*++
Routine Description:
This routine returns the index in the register table for the
given register. Or invalid if the given register name doesn't
match any register.
Arguments:
RegName - Null terminated string that contains the name of the register.
Return Value:
Index on the Register Table for the requested register.
--*/
{
REGISTER_NAME_ID RegId;
//for (RegId = 0; RegId < MON_INVALID_REGISTER_MSG; RegId++) {
for (RegId = 0; RegId < invalidregister; RegId++) {
if (strcmp(RegisterNameTable[RegId],RegName) == 0) {
break;
}
}
return RegId;
}
ULONG
StrToUlong(
IN PCHAR String,
OUT CHAR ** Terminator
)
/*++
Routine Description:
This routine converts an ascii string to an unsigned long
Arguments:
String - Null terminated string that contains the value to convert.
Terminator - Address of a pointer to a character. This routine
sets it to point to the cahracter in String that terminated
the conversion. This is '\0' in a normal case or whatever
garbage the string contained.
Return Value:
Returns the converted string
--*/
{
ULONG Ulong = 0;
ULONG Index;
for (Index=0;String[Index]; Index++) {
if ((String[Index] >= '0') && (String[Index] <= '9')) {
Ulong <<= 4;
Ulong |= String[Index] - '0';
continue;
}
//
// Strings are always lower case so this is not needed.
//
//if ((String[Index] >= 'A') && (String[Index] <= 'F')) {
// Ulong <<= 4;
// Ulong |= String[Index] - 'A' + 10;
// continue;
//}
if ((String[Index] >= 'a') && (String[Index] <= 'f')) {
Ulong <<= 4;
Ulong |= String[Index] - 'a' + 10;
continue;
}
*Terminator = &String[Index];
return 0xFFFFFFF;
}
//
// Check for overflow
//
if (Index > 8) {
*Terminator = &String[0];
} else {
*Terminator = &String[Index];
}
return Ulong;
}
BOOLEAN
GetAddress(
IN PUCHAR String,
OUT PULONG Address,
PULONG pRegTable
)
/*++
Routine Description:
This routine converts an ascii string to an address. The string
is the form:
[@reg | value]
Arguments:
String - Null terminated string that contains the address to convert.
Address - Supplies a pointer to where the converted address is stored
Return Value:
Returns TRUE if the string can be converted.
FALSE otherwise.
--*/
{
PUCHAR Terminator;
//UCHAR Delimiter;
REGISTER_NAME_ID RegId;
if (*String == '@') {
String++; // skip @
if ((RegId = GetRegister(String)) == invalidregister) {
EdbgOutputDebugString(String);
EdbgOutputDebugString(MON_INVALID_REGISTER_MSG);
return FALSE;
} else {
*Address = *(pRegTable+RegId);
}
} else {
*Address=StrToUlong(String,&Terminator);
if (*Terminator != '\0') {
//
// Not the whole string was converted.
//
EdbgOutputDebugString(Terminator);
EdbgOutputDebugString(MON_NOT_VALID_ADDRESS_MSG);
return FALSE;
}
}
return TRUE;
}
BOOLEAN
GetAddressRange(
IN PCHAR Argv[],
OUT PULONG StartAddress,
OUT PULONG EndAddress,
IN PULONG pregTable
)
/*++
Routine Description:
This routine converts an ascii string to a range, returning the starting
and end address.
The syntax for an address range is one of the following
startaddress endaddres
startaddress l numberofelements
Arguments:
Argv - array of zero terminated argument strings.
StartAddress - Supplies a pointer to where the Start address is stored
EndAddress - Supplies a pointer to where the End address is stored
Return Value:
Returns TRUE if Argv specifies a valid address range.
FALSE otherwise.
--*/
{
//PCHAR Tmp;
//CHAR Delimiter;
if (CurrentArg == Argc) {
return TRUE;
}
if (GetAddress(Argv[CurrentArg],StartAddress,pregTable) == FALSE) {
return FALSE;
}
CurrentArg++;
if (CurrentArg == Argc) {
*EndAddress = *StartAddress+128;
return TRUE;
}
//if (strcmp(Argv[CurrentArg],"l") == 0 ) {
if ( Argv[CurrentArg][0] == 'l' && Argv[CurrentArg][1] == '\0') {
//
// this is a range of the form "startaddress l count"
//
CurrentArg++;
if (CurrentArg == Argc) {
EdbgOutputDebugString(MON_INVALID_ARGUMENT_COUNT_MSG);
return FALSE;
}
if (GetAddress(Argv[CurrentArg],EndAddress,pregTable) == FALSE) {
return FALSE;
}
CurrentArg++;
*EndAddress = (*EndAddress<<DataSizeShift) + *StartAddress;
} else {
if (GetAddress(Argv[CurrentArg],EndAddress,pregTable) == FALSE) {
//
// the argument didn't convert the range is Start+128
//
*EndAddress = *StartAddress+128;
} else {
CurrentArg++;
}
}
//
// Check that the range is correct End > Start
//
if (*EndAddress <= *StartAddress) {
EdbgOutputDebugString(MON_INVALID_ADDRESS_RANGE_MSG);
return FALSE;
}
return TRUE;
}
COMMAND_NAME_ID
GetCommand(
IN PCHAR CommandName
)
/*++
Routine Description:
This routine tries to match the supplied string
with one of the recognized commands.
Arguments:
CommandName - Supplies a string to be matched with one of the monitor commands.
Return Value:
Returns a value that identifies the command.
--*/
{
COMMAND_NAME_ID Index;
for (Index=0;Index<invalidcommand;Index++) {
if (strcmp(CommandNameTable[Index],CommandName) == 0) {
break;
}
}
return Index;
}
BOOLEAN
ModifyRegisterCommand(
IN PCHAR Argv[], IN PULONG pRegTable
)
/*++
Routine Description:
This routine will implement the REGISTER MODIFY command given the
arguments in the argc,Argv form.
Arguments:
Argv - array of zero terminated argument strings.
Return Value:
Returns TRUE if the command is valid, FALSE otherwise.
--*/
{
REGISTER_NAME_ID RegId;
PCHAR Terminator;
ULONG Value;
GETSTRING_ACTION Action;
CHAR ValueStr[128];
PCHAR pValueStr = ValueStr;
switch(Argc) {
case 2:
if ((RegId = GetRegister(Argv[1])) == invalidregister) {
EdbgOutputDebugString(Argv[1]);
EdbgOutputDebugString(MON_INVALID_REGISTER_MSG);
return FALSE;
}
EdbgOutputDebugString(FW_CRLF_MSG);
//EdbgOutputDebugString("%s: %08lx", RegisterNameTable[RegId],*(pRegTable+RegId));
EdbgOutputDebugString("%s: %x", RegisterNameTable[RegId],*(pRegTable+RegId));
EdbgOutputDebugString(FW_CRLF_MSG);
EdbgOutputDebugString(":");
Action = FwGetString(ValueStr,128,NULL);
if (Action != GetStringSuccess) return FALSE;
break;
case 3:
if ((RegId = GetRegister(Argv[1])) == invalidregister) {
EdbgOutputDebugString(Argv[1]);
EdbgOutputDebugString(MON_INVALID_REGISTER_MSG);
return FALSE;
}
pValueStr = Argv[2];
break;
default:
return FALSE;
}
Value = StrToUlong(pValueStr,&Terminator);
if (*Terminator != '\0') {
EdbgOutputDebugString(Terminator);
EdbgOutputDebugString(MON_INVALID_VALUE_MSG);
return FALSE;
}
*(pRegTable+RegId) = Value;
EdbgOutputDebugString(FW_CRLF_MSG);
return TRUE;
}
BOOLEAN
RegisterCommand(
IN PCHAR Argv[], IN PULONG pRegTable
)
/*++
Routine Description:
This routine will implement the REGISTER command given the
arguments in the argc,Argv form.
Arguments:
Argv - array of zero terminated argument strings.
Return Value:
Returns TRUE if the command is valid, FALSE otherwise.
--*/
{
REGISTER_NAME_ID RegId;
switch(Argc) {
case 1:
//
// Dump the value of all the registers
//
#ifdef MIPS
for (RegId=1;RegId<32;RegId++) {
EdbgOutputDebugString(MON_FORMAT1_MSG,RegisterNameTable[RegId],*(pRegTable+RegId));
if ((RegId%6) == 0) {
EdbgOutputDebugString(FW_CRLF_MSG);
}
}
EdbgOutputDebugString(MON_FORMAT1_MSG,RegisterNameTable[psr],*(pRegTable+psr));
EdbgOutputDebugString(MON_FORMAT1_MSG,RegisterNameTable[epc],*(pRegTable+epc));
EdbgOutputDebugString(MON_FORMAT1_MSG,RegisterNameTable[cause],*(pRegTable+cause));
EdbgOutputDebugString(MON_FORMAT1_MSG,RegisterNameTable[errorepc],*(pRegTable+errorepc));
EdbgOutputDebugString(FW_CRLF_MSG);
EdbgOutputDebugString(MON_FORMAT1_MSG,RegisterNameTable[badvaddr],*(pRegTable+badvaddr));
#endif /* MIPS */
#ifdef SHx
for (RegId=r0RegTable; RegId>=spcRegTable; RegId--) {
EdbgOutputDebugString(MON_FORMAT1_MSG,RegisterNameTable[RegId],*(pRegTable+RegId));
if (((r0RegTable-RegId+1)%5) == 0) {
EdbgOutputDebugString(FW_CRLF_MSG);
}
}
for (RegId=ar0RegTable; RegId>=ar7RegTable; RegId--) {
EdbgOutputDebugString(MON_FORMAT1_MSG,RegisterNameTable[RegId],*(pRegTable+RegId));
if (((r0RegTable-RegId+1)%4) == 0) {
EdbgOutputDebugString(FW_CRLF_MSG);
}
}
EdbgOutputDebugString(MON_FORMAT1_MSG,RegisterNameTable[gbrRegTable],*(pRegTable+gbrRegTable));
EdbgOutputDebugString(MON_FORMAT1_MSG,RegisterNameTable[vbrRegTable],*(pRegTable+vbrRegTable));
#endif /* SH3 */
EdbgOutputDebugString(FW_CRLF_MSG);
return TRUE;
case 2:
//
// Dump the value of the specified register.
//
if ((RegId = GetRegister(Argv[1])) == invalidregister) {
EdbgOutputDebugString(Argv[1]);
EdbgOutputDebugString(MON_INVALID_REGISTER_MSG);
return FALSE;
} else {
//EdbgOutputDebugString("%s = %08lx\r\n",RegisterNameTable[RegId],*(pRegTable+RegId));
EdbgOutputDebugString("%s = %x\r\n",RegisterNameTable[RegId],*(pRegTable+RegId));
return TRUE;
}
default:
EdbgOutputDebugString(MON_INVALID_ARGUMENT_COUNT_MSG);
return FALSE;
}
}
VOID
InputValue(
IN ULONG Address,
OUT PVOID Value
)
/*++
Routine Description:
This routine reads a value from the supplied address and displays
it. DataSize is set to the size of the value to read.
Arguments:
Address - Supplies the address where the value is to be read from.
Value - Pointer to where the value read is stored.
Return Value:
None.
--*/
{
switch(DataSize) {
case BYTE_SIZE:
*(PUCHAR)Value = *(volatile PUCHAR)Address; // read byte
//EdbgOutputDebugString("%02x ",*(PUCHAR)Value);
EdbgOutputDebugString("%x ",*(PUCHAR)Value);
break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -