📄 ui.c
字号:
/*++
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.
Copyright (c) 1995-2000 Microsoft Corporation
Module Name: ui.c
Abstract: Boot loader user interface (menu) functions.
Functions:
UIWait
UIMenu
UIWatchForBootHalt
Notes:
--*/
#include <windows.h>
#include <nkintr.h>
#include <halether.h>
#include "bldr.h"
typedef enum
{
BLOCK_BLACK,
BLOCK_GRAY
} BLOCK_COLOR;
#define MAX_CMD_LEN 512
ULONG MyStrToUL(PUCHAR pStr, UCHAR nBase);
BOOL StoreEnvVars(PLOADER_VARS pVars);
int OEMReadDebugString(unsigned char *pBuff, unsigned long nLen);
BOOL SetCmdHdlr(char **argv, int argc);
BOOL StoreCmdHdlr(char **argv, int argc);
BOOL HelpCmdHdlr(char **argv, int argc);
BOOL GoCmdHdlr(char **argv, int argc);
extern LOADER_VARS gLoaderVars;
void *gCmdTable[][3] =
{
{ TEXT("set\0") , SetCmdHdlr , TEXT("assign/show loader settings\0")},
{ TEXT("store\0") , StoreCmdHdlr , TEXT("store settings to CMOS\0") },
{ TEXT("help\0") , HelpCmdHdlr , TEXT("display help\0") },
{ TEXT("?\0") , HelpCmdHdlr , TEXT(" \" \" \0") },
{ TEXT("go\0") , GoCmdHdlr , TEXT("continue booting\0") },
{ NULL , NULL , NULL }
};
typedef enum
{
TYPE_NOCONV, // Variable doesn't require conversion for display.
TYPE_INETADDR, // Variable is IP or subnet mask.
TYPE_IMGLOC, // Variable denotes image location (enet, disk, etc.)
} VAR_CONV_TYPE, *PVAR_CONV_TYPE;
void *gVarTable[][3] =
{
{ TEXT("ip\0") , &gLoaderVars.nIPAddr , (void*)TYPE_INETADDR },
{ TEXT("subnet\0") , &gLoaderVars.nSubnetMask , (void*)TYPE_INETADDR },
{ TEXT("imgloc\0") , &gLoaderVars.nImgLoc , (void*)TYPE_IMGLOC },
{ TEXT("usedhcp\0") , &gLoaderVars.nUseDHCP , (void*)TYPE_NOCONV },
{ TEXT("autocount\0"), &gLoaderVars.nAutoCount , (void*)TYPE_NOCONV },
{ NULL , NULL , NULL }
};
UCHAR gcImgLocTbl[][2] =
{
{BL_ENET, 'E'}, // Ethernet
{BL_ATAHDD, 'D'} // Hard disk drive
};
#define NUM_IMG_LOCS (sizeof(gcImgLocTbl) / sizeof(UCHAR))
BOOL gbExit = FALSE;
BOOL SetCmdHdlr(char **argv, int argc)
{
UCHAR nCnt=0;
BOOL bDisplay = FALSE;
BOOL bFindVar = FALSE;
ULONG nVal=0;
// Three options: list all variables, list a single variable, set a single
// variable. Option is determined by argc value.
bDisplay = (argc <= 2 ? TRUE : FALSE);
bFindVar = (argc >= 2 ? TRUE : FALSE);
RETAILMSG(1, (TEXT("\r\n")));
if (bDisplay)
RETAILMSG(1, (TEXT("\r\n")));
for(nCnt=0 ; gVarTable[nCnt][0] != NULL ; nCnt++)
{
if (bFindVar && _stricmp(argv[1], gVarTable[nCnt][0]))
continue;
nVal = *(PULONG)(gVarTable[nCnt][1]);
if (bDisplay) // Display variable.
{
RETAILMSG(1, (TEXT("%s = "), gVarTable[nCnt][0]));
switch((VAR_CONV_TYPE)gVarTable[nCnt][2])
{
case TYPE_INETADDR:
RETAILMSG(1, (TEXT("%s\r\n"), inet_ntoa(nVal)));
break;
case TYPE_IMGLOC:
if ((nVal+1) > NUM_IMG_LOCS)
RETAILMSG(1, (TEXT("{invalid}\r\n")));
else
RETAILMSG(1, (TEXT("%c\r\n"), gcImgLocTbl[nVal][1]));
break;
case TYPE_NOCONV:
default:
RETAILMSG(1, (TEXT("%x\r\n"), nVal));
}
}
else // Set variable.
{
switch((VAR_CONV_TYPE)gVarTable[nCnt][2])
{
case TYPE_INETADDR:
*(PULONG)(gVarTable[nCnt][1]) = inet_addr(argv[2]);
break;
case TYPE_IMGLOC:
{
UCHAR nIndex=0;
for(nIndex=0 ; nIndex < NUM_IMG_LOCS && TO_UPPER(argv[2][0]) != gcImgLocTbl[nIndex][1] ; nIndex++)
{
;
}
if (nIndex == NUM_IMG_LOCS)
{
RETAILMSG(1, (TEXT("ERROR: Valid values are: ")));
for(nIndex=0 ; nIndex < NUM_IMG_LOCS ; nIndex++)
{
RETAILMSG(1, (TEXT("%c "), gcImgLocTbl[nIndex][1]));
}
RETAILMSG(1, (TEXT("\r\n")));
return(FALSE);
}
else
*(PULONG)(gVarTable[nCnt][1]) = gcImgLocTbl[nIndex][0];
}
break;
case TYPE_NOCONV:
default:
*(PULONG)(gVarTable[nCnt][1]) = MyStrToUL(argv[2], 16);
}
}
// Done?
if (bFindVar)
break;
}
if (gVarTable[nCnt][0] == NULL && bFindVar)
RETAILMSG(1, (TEXT("Can't assign/show variable (%s).\r\n"), argv[1]));
return(TRUE);
}
BOOL StoreCmdHdlr(char **argv, int argc)
{
BOOL bRet = FALSE;
RETAILMSG(1, (TEXT("\r\n")));
bRet = StoreEnvVars(&gLoaderVars);
if(bRet)
RETAILMSG(1, (TEXT("Stored variables to CMOS.\r\n")));
else
RETAILMSG(1, (TEXT("ERROR: Unable to store variables to CMOS.\r\n")));
return(bRet);
}
BOOL HelpCmdHdlr(char **argv, int argc)
{
UCHAR nCnt=0;
#define MAXCMDNAMELEN 10
CHAR szFill[MAXCMDNAMELEN];
UCHAR nTmp=0;
RETAILMSG(1, (TEXT("\r\n\r\n")));
for(nCnt=0 ; gCmdTable[nCnt][0] != NULL ; nCnt++)
{
memset(szFill, ' ', MAXCMDNAMELEN);
nTmp = ((strlen(gCmdTable[nCnt][0]) < MAXCMDNAMELEN) ? (MAXCMDNAMELEN - strlen(gCmdTable[nCnt][0])) : 0);
szFill[nTmp] = '\0';
RETAILMSG(1, (TEXT("%s%s - %s\r\n"), gCmdTable[nCnt][0], szFill, gCmdTable[nCnt][2]));
}
return(TRUE);
}
BOOL GoCmdHdlr(char **argv, int argc)
{
gbExit=TRUE;
return(TRUE);
}
void UIWait(ULONG nSecs)
{
ULONG nCurSecs = OEMGetSecs();
while((nCurSecs + nSecs) > OEMGetSecs())
{
;
}
}
void UIParseCmdLine(PUCHAR pszCmdBuf)
{
// *** NOTE: this function marches on the caller-provided buffer ***
UCHAR nCount=0;
#define MAX_ARGC 10
#define SKIP_CHAR(c) (c == ' ' || c == '\t' || c == '\r' || c == '\n' || c == '=' || c == '"')
UCHAR nArgc=0;
PUCHAR pArgv[MAX_ARGC];
PUCHAR pTmp=NULL;
if (pszCmdBuf == NULL)
return;
for (pTmp=pszCmdBuf ; SKIP_CHAR(*pTmp) ; pTmp++)
{
;
}
if (*pTmp == '\0')
return;
// Tokenize the command line (must be null-terminted).
for (nArgc=1, pArgv[0]=pTmp ; *pTmp != '\0' ; pTmp++)
{
if(SKIP_CHAR(*pTmp))
{
*pTmp = '\0';
do
{
++pTmp;
} while(*pTmp != '\0' && SKIP_CHAR(*pTmp));
if (*pTmp != '\0')
{
if (++nArgc > MAX_ARGC)
{
DEBUGMSG(ZONE_WARNING, (TEXT("WARNING: Command is too long.\r\n")));
break;
}
pArgv[nArgc - 1]=pTmp;
}
}
}
// Look up command in command table.
while(gCmdTable[nCount][0] != NULL)
{
if(!_stricmp(pArgv[0], gCmdTable[nCount][0]))
{
void (*fp)(char **, int) = gCmdTable[nCount][1];
fp(pArgv, nArgc);
return;
}
++nCount;
}
RETAILMSG(1, (TEXT("\r\nERROR: Unknown command (%s)\r\n"), pszCmdBuf));
}
void UIMenu(void)
{
UCHAR szCmdBuf[MAX_CMD_LEN];
memset(szCmdBuf, 0, MAX_CMD_LEN);
RETAILMSG(1, (TEXT("\r\n\r\n")));
RETAILMSG(1, (TEXT("Type \"help\" to get a list of commands.\r\n")));
do
{
RETAILMSG(1, (TEXT("\r\n>> ")));
if (!OEMReadDebugString(szCmdBuf, MAX_CMD_LEN))
UIParseCmdLine(szCmdBuf);
}
while (!gbExit);
}
void UIWatchForBootHalt(void)
{
UCHAR nCount = 0;
// Check CMOS setting to determine how long to wait for user break.
nCount = (UCHAR)gLoaderVars.nAutoCount;
while(nCount)
{
RETAILMSG(1, (TEXT("\rPress any key to break into configuration menu %d ..."), nCount));
if (OEMReadDebugByte() != OEM_DEBUG_READ_NODATA)
{
UIMenu();
break;
}
else
UIWait(1);
--nCount;
}
EdbgOutputDebugString("\r\n");
}
ULONG MyStrToUL(PUCHAR pStr, UCHAR nBase)
{
UCHAR nPos=0;
BYTE c;
ULONG nVal = 0;
UCHAR nCnt=0;
ULONG n=0;
// TODO - fulllibc doesn't implement isctype or iswctype, which are needed by
// strtoul, rather than including coredll code, here's our own simple strtoul.
if (pStr == NULL)
return(0);
for (nPos=0 ; nPos < strlen(pStr) ; nPos++)
{
c = tolower(*(pStr + strlen(pStr) - 1 - nPos));
if (c >= '0' && c <= '9')
c -= '0';
else if (c >= 'a' && c <= 'f')
{
c -= 'a';
c = (c + 1) * 0x10;
}
for (nCnt=0, n=1 ; nCnt < nPos ; nCnt++)
n *= nBase;
nVal += (n * c);
}
return(nVal);
}
int draw_block(BLOCK_COLOR clr)
{
switch(clr)
{
case BLOCK_GRAY:
OEMWriteDebugByte('.');
break;
case BLOCK_BLACK:
default:
OEMWriteDebugByte('#');
}
return(0);
}
int create_statusbar(PSTATUSBAR pbar, ULONG sval, ULONG eval)
{
unsigned char i = 0;
if (pbar == NULL || eval <= sval)
return(-1);
pbar->sval = sval;
pbar->cval = sval;
pbar->eval = eval;
pbar->last_percent = 0;
for (i=0 ; i < SB_BAR_WIDTH ; i++)
draw_block(BLOCK_GRAY);
return(0);
}
int update_statusbar(PSTATUSBAR pbar, ULONG cval)
{
unsigned char percent = 0;
unsigned char numblks = 0;
unsigned char i = 0;
if (pbar == NULL)
return(-1);
if (cval > pbar->eval)
return(0);
pbar->cval = cval;
percent = (unsigned char)(((cval - pbar->sval) * 100) / (pbar->eval - pbar->sval));
if (percent == pbar->last_percent)
return(0);
pbar->last_percent = percent;
numblks = (unsigned char)((SB_BAR_WIDTH * percent) / 100);
// TODO - only needed for terminal emulator - clean up.
for (i=0 ; i < SB_BAR_WIDTH ; i++)
OEMWriteDebugByte(BACKSPACE);
for (i = 0 ; i < numblks ; i++)
draw_block(BLOCK_BLACK);
return(0);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -