⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ui.c

📁 WinCE 3.0 BSP, 包含Inter SA1110, Intel_815E, Advantech_PCM9574 等
💻 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 + -