www.pudn.com > iMx31_WCE600.rar > menu.c


// 
// Copyright (c) Microsoft Corporation.  All rights reserved. 
// 
// 
// Use of this source code is subject to the terms of the Microsoft end-user 
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT. 
// If you did not accept the terms of the EULA, you are not authorized to use 
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your 
// install media. 
// 
//------------------------------------------------------------------------------ 
// 
//  Copyright (C) 2004-2007, Freescale Semiconductor, Inc. All Rights Reserved. 
//  THIS SOURCE CODE, AND ITS USE AND DISTRIBUTION, IS SUBJECT TO THE TERMS 
//  AND CONDITIONS OF THE APPLICABLE LICENSE AGREEMENT 
// 
//------------------------------------------------------------------------------ 
// 
//  File:  menu.c 
// 
//  Menu routines for the ethernet bootloader. 
// 
//------------------------------------------------------------------------------ 
#include  
#include "loader.h" 
 
//----------------------------------------------------------------------------- 
// External Functions 
extern void ResetDefaultBootCFG(BOOT_CFG *pBootCFG); 
extern BOOL StoreBootCFG(BOOT_CFG *BootCFG); 
extern BOOL NANDFormatNK(void); 
extern BOOL NANDFormatAll(void); 
extern void SetMAC(BOOT_CFG *pBootCFG); 
extern void CvtMAC(USHORT MacAddr [ 3 ], char * pszDottedD); 
extern void SetBootMe(BOOT_CFG *pBootCFG); 
extern void SetDelay(BOOT_CFG *pBootCFG); 
 
 
 
 
//----------------------------------------------------------------------------- 
// External Variables 
extern BSP_ARGS     *g_pBSPArgs; 
extern BOOT_CFG     g_BootCFG; 
extern BOOL         g_DownloadImage; 
extern UINT32 EthDevice;  // To determine if Ethernet has been initailized for download/KITL usage 
 
//----------------------------------------------------------------------------- 
// Defines 
 
 
//----------------------------------------------------------------------------- 
// Types 
 
 
//----------------------------------------------------------------------------- 
// Global Variables 
 
 
//----------------------------------------------------------------------------- 
// Local Variables 
 
 
//------------------------------------------------------------------------------ 
// Local Functions 
// 
static void SetIP(BOOT_CFG *pBootCFG); 
static void SetMask(BOOT_CFG *pBootCFG); 
 
 
//------------------------------------------------------------------------------ 
// 
//  Function:  BLMenu 
// 
//  Provides boot loader menu interface. 
// 
//  Parameters: 
//      None. 
// 
//  Returns: 
//      TRUE indicates success. FALSE indicates failure. 
// 
//------------------------------------------------------------------------------ 
BOOL BLMenu() 
{ 
    UINT32 AutoBootDelay = 0; 
    BOOLEAN bCFGChanged  = FALSE; 
    UINT32 StartTime, CurrTime, PrevTime; 
    UINT32 Selection; 
     
    // If mac address has not been programmed, immediately drop into menu 
    // so user can give us one.  The ADS EEPROM connected to the CS8900A 
    // does not contain the proper values to allow the MAC to be obtained 
    // automatically. 
    if (!g_BootCFG.mac[0] && !g_BootCFG.mac[1] && !g_BootCFG.mac[2]) 
    { 
        EdbgOutputDebugString("WARNING:  Uninitialized MAC address.  Select valid address using menu.\r\n"); 
        Selection = 0x20; 
    } 
    else 
    { 
        AutoBootDelay = g_BootCFG.delay; 
        switch(g_BootCFG.autoDownloadImage) 
        { 
        case BOOT_CFG_AUTODOWNLOAD_NK_NOR: 
            g_DownloadImage = FALSE; 
            EdbgOutputDebugString("\r\nPress [ENTER] to launch image stored in NOR flash or [SPACE] to cancel.\r\n"); 
            EdbgOutputDebugString("\r\nInitiating image launch in %d seconds. ", AutoBootDelay--); 
            break; 
 
        case BOOT_CFG_AUTODOWNLOAD_NK_NAND: 
            g_DownloadImage = FALSE; 
            EdbgOutputDebugString("\r\nPress [ENTER] to launch image stored in NAND flash or [SPACE] to cancel.\r\n"); 
            EdbgOutputDebugString("\r\nInitiating image launch in %d seconds. ", AutoBootDelay--); 
            break; 
 
        case BOOT_CFG_AUTODOWNLOAD_IPL_NAND: 
            g_DownloadImage = FALSE; 
            EdbgOutputDebugString("\r\nPress [ENTER] to launch IPL stored in NAND flash or [SPACE] to cancel.\r\n"); 
            EdbgOutputDebugString("\r\nInitiating IPL launch in %d seconds. ", AutoBootDelay--); 
            break; 
 
        default: 
            g_DownloadImage = TRUE; 
            EdbgOutputDebugString("\r\nPress [ENTER] to download now or [SPACE] to cancel.\r\n"); 
            EdbgOutputDebugString("\r\nInitiating image download in %d seconds. ", AutoBootDelay--); 
            break; 
        } 
 
        // Get a snapshot of the RTC seconds count. 
        // 
        StartTime     = OEMEthGetSecs(); 
        PrevTime      = StartTime; 
        CurrTime      = StartTime; 
        Selection     = (UINT32)OEM_DEBUG_READ_NODATA; 
 
        // Allow the user an amount of time to halt the auto boot/download process. 
        // Count down to 0 before proceeding with default operation. 
        // 
        while ((CurrTime - StartTime) < g_BootCFG.delay) 
        { 
            UINT8 i=0; 
            UINT8 j; 
 
            Selection = OEMReadDebugByte();  
            if ((Selection == 0x20) || (Selection == 0x0d)) 
            { 
                break; 
            } 
            CurrTime = OEMEthGetSecs();    
            if (CurrTime > PrevTime) 
            { 
                PrevTime = CurrTime; 
                if (AutoBootDelay < 9) 
                    i = 11; 
                else if (AutoBootDelay < 99) 
                    i = 12; 
                else if (AutoBootDelay < 999) 
                    i = 13; 
 
                for (j = 0; j < i; j++) 
                { 
                    OEMWriteDebugByte((BYTE)0x08); // print back space 
                } 
 
                KITLOutputDebugString ( "%d seconds. ", AutoBootDelay--); 
            } 
        } 
    } 
 
    switch (Selection) 
    { 
    case OEM_DEBUG_READ_NODATA: // fall through if nothing typed 
    case 0x0d: // user canceled wait 
        { 
            if (g_BootCFG.autoDownloadImage) 
            { 
                KITLOutputDebugString ( "\r\nLaunching flash image  ... \r\n"); 
            } 
            else 
            { 
                KITLOutputDebugString ( "\r\nStarting auto download ... \r\n"); 
            } 
            break; 
        } 
    case 0x20: 
        { 
            Selection = 0; 
            for (;;) 
            { 
                // Show menu 
                KITLOutputDebugString ( "\r\n\r\nBoot Loader Configuration%s:\r\n\r\n", bCFGChanged ? " (UNSAVED CHANGES)" : ""); 
                KITLOutputDebugString ( "0) IP address: %s\r\n",inet_ntoa(g_BootCFG.IP)); 
                KITLOutputDebugString ( "1) Subnet Mask: %s\r\n", inet_ntoa(g_BootCFG.subnetMask)); 
                KITLOutputDebugString ( "2) Boot delay: %d seconds\r\n", g_BootCFG.delay); 
                KITLOutputDebugString ( "3) DHCP:  %s\r\n", (g_BootCFG.DHCPEnable == TRUE ? "Enabled" : "Disabled")); 
                KITLOutputDebugString ( "4) Reset to factory default configuration\r\n"); 
                switch(g_BootCFG.autoDownloadImage) 
                { 
                case BOOT_CFG_AUTODOWNLOAD_NK_NOR: 
                    KITLOutputDebugString("5) Autoboot:  NK from NOR\r\n"); 
                    break; 
                case BOOT_CFG_AUTODOWNLOAD_NK_NAND: 
                    KITLOutputDebugString("5) Autoboot:  NK from NAND\r\n"); 
                    break; 
                case BOOT_CFG_AUTODOWNLOAD_IPL_NAND: 
                    KITLOutputDebugString("5) Autoboot:  IPL from NAND\r\n"); 
                    break; 
                default: 
                    KITLOutputDebugString("5) Autoboot:  Disabled\r\n"); 
                    break; 
                    
                } 
                KITLOutputDebugString ( "6) MAC address: %x-%x-%x-%x-%x-%x\r\n",  
                    g_BootCFG.mac[0] & 0x00FF, g_BootCFG.mac[0] >> 8, 
                    g_BootCFG.mac[1] & 0x00FF, g_BootCFG.mac[1] >> 8, 
                    g_BootCFG.mac[2] & 0x00FF, g_BootCFG.mac[2] >> 8); 
                KITLOutputDebugString ( "7) Format OS NAND region.\r\n"); 
                KITLOutputDebugString ( "8) Format ALL NAND regions.\r\n"); 
                KITLOutputDebugString ( "S) Save configuration\r\n");                 
                KITLOutputDebugString ( "D) Download image now\r\n"); 
                KITLOutputDebugString ( "L) Launch existing flash resident image now\r\n"); 
                KITLOutputDebugString ( "\r\n\r\nEnter your selection: "); 
 
                // Read user selection 
                Selection = 0; 
                while (! ( ( (Selection >= '0') && (Selection <= '8') ) ||  
                           ( (Selection == 'D') || (Selection == 'd') ) ||  
                           ( (Selection == 'L') || (Selection == 'l') ) || 
                           ( (Selection == 'S') || (Selection == 's') ) )) 
                { 
                    Selection = OEMReadDebugByte(); 
                } 
                KITLOutputDebugString ( "%c\r\n", Selection); 
 
                // Process user selection 
                switch (Selection) 
                { 
                case '0': 
                    SetIP(&g_BootCFG); 
                    bCFGChanged=TRUE; 
                    break; 
                case '1': 
                    SetMask(&g_BootCFG); 
                    bCFGChanged=TRUE; 
                    break; 
                case '2': 
                    SetDelay(&g_BootCFG); 
                    bCFGChanged=TRUE; 
                    break; 
                case '3': 
                    if (g_BootCFG.DHCPEnable == TRUE) 
                        g_BootCFG.DHCPEnable = FALSE; 
                    else 
                        g_BootCFG.DHCPEnable = TRUE; 
                    bCFGChanged=TRUE; 
                    break; 
                case '4': 
                    ResetDefaultBootCFG(&g_BootCFG); 
                    break; 
                case '5': 
                    switch(g_BootCFG.autoDownloadImage) 
                    { 
                    case BOOT_CFG_AUTODOWNLOAD_NONE: 
                        g_BootCFG.autoDownloadImage = BOOT_CFG_AUTODOWNLOAD_NK_NOR; 
                        break; 
                    case BOOT_CFG_AUTODOWNLOAD_NK_NOR: 
                        g_BootCFG.autoDownloadImage = BOOT_CFG_AUTODOWNLOAD_NK_NAND; 
                        break; 
                    case BOOT_CFG_AUTODOWNLOAD_NK_NAND: 
                        g_BootCFG.autoDownloadImage = BOOT_CFG_AUTODOWNLOAD_IPL_NAND; 
                        break; 
                    default: 
                        g_BootCFG.autoDownloadImage = BOOT_CFG_AUTODOWNLOAD_NONE; 
                        break;                        
                    } 
                    bCFGChanged=TRUE; 
                    break; 
                case '6': 
                    SetMAC(&g_BootCFG); 
                    bCFGChanged=TRUE; 
                    break; 
                case '7': 
                    KITLOutputDebugString("\r\nWARNING:  Format of OS NAND region requested.\r\n"); 
                    KITLOutputDebugString("Do you want to continue (y/n)? "); 
                    do { 
                        Selection = tolower(OEMReadDebugByte()); 
                    } while ((Selection != 'y') && (Selection != 'n')); 
                    KITLOutputDebugString("\r\n"); 
        
                    if (Selection == 'y') 
                    { 
                        NANDFormatNK(); 
                    } 
                    break; 
                case '8': 
                    KITLOutputDebugString("\r\nWARNING:  Format of all NAND regions requested.\r\n"); 
                    KITLOutputDebugString("Boot loader and boot configuration regions will be erased!!!\r\n"); 
                    KITLOutputDebugString("Do you want to continue (y/n)? "); 
                    do { 
                        Selection = tolower(OEMReadDebugByte()); 
                    } while ((Selection != 'y') && (Selection != 'n')); 
                    KITLOutputDebugString("\r\n"); 
                     
                    if (Selection == 'y') 
                    { 
                        NANDFormatAll(); 
                    } 
                    break; 
                case 'D': 
                case 'd': 
                    g_DownloadImage = TRUE; 
                    goto exitMenu; 
                    break; 
                case 'L': 
                case 'l': 
                    if (g_BootCFG.autoDownloadImage == BOOT_CFG_AUTODOWNLOAD_NONE) 
                    { 
                        KITLOutputDebugString("\r\nWARNING:  You must select NOR/NAND/SD-MMC using Autoboot menu option.\r\n"); 
                    } 
                    else 
                    { 
                        g_DownloadImage = FALSE; 
                        goto exitMenu; 
                    } 
                    break; 
 
                case 'S': 
                case 's': 
                    StoreBootCFG(&g_BootCFG); 
                    bCFGChanged=FALSE; 
                    break; 
 
                default: 
                    break; 
                } 
            } 
        } 
    } 
 
exitMenu: 
 
    if (bCFGChanged == TRUE) 
    { 
        StoreBootCFG(&g_BootCFG); 
    }     
     
    // EEPROM on ADS does not have proper contents to allow CS8900 to automatically 
    // read MAC address during initialization.  We must provide MAC from the Boot 
    // configuration parameters previously loaded. 
    memcpy(g_pBSPArgs->kitl.mac, g_BootCFG.mac, 6); 
 
    // If active KITL is enabled at boot, or user selected the download option, 
    // locate and initialize an Ethernet controller. 
    // 
    if ((!(g_pBSPArgs->kitl.flags & OAL_KITL_FLAGS_PASSIVE)) || g_DownloadImage) 
    { 
        // Make default Ethernet CS8900A.  Later we may want this to be configured with 
        // the menu so we can support other download/KITL transports 
         
        EthDevice = InitSpecifiedEthDevice(&g_pBSPArgs->kitl,  ETH_DEVICE_CS8900A); 
        if (EthDevice == -1) 
        { 
            // No device was found ...  
            // 
            KITLOutputDebugString("ERROR: Failed to detect and initialize Ethernet controller.\r\n"); 
            return(FALSE); 
        } 
 
        // Make sure MAC address has been programmed. 
        // 
        if (!g_pBSPArgs->kitl.mac[0] && !g_pBSPArgs->kitl.mac[1] && !g_pBSPArgs->kitl.mac[2]) 
        { 
            KITLOutputDebugString("ERROR: Invalid Ethernet address read from Ethernet controller.\n"); 
            return(FALSE); 
        } 
 
        KITLOutputDebugString("INFO: MAC address: %x-%x-%x-%x-%x-%x\r\n", 
            g_pBSPArgs->kitl.mac[0] & 0x00FF, g_pBSPArgs->kitl.mac[0] >> 8, 
            g_pBSPArgs->kitl.mac[1] & 0x00FF, g_pBSPArgs->kitl.mac[1] >> 8, 
            g_pBSPArgs->kitl.mac[2] & 0x00FF, g_pBSPArgs->kitl.mac[2] >> 8); 
         
    } 
 
    return(TRUE); 
} 
 
 
//------------------------------------------------------------------------------ 
// 
//  Function:  SetIP 
// 
//  Allows user to set an IP address using the boot loader menu. 
// 
//  Parameters: 
//      eBootCFG  
//          [out] Points to bootloader configuration that will be updated with 
//          the IP address entered by the user. 
// 
//  Returns: 
//      None. 
// 
//------------------------------------------------------------------------------ 
static void SetIP(BOOT_CFG *pBootCFG) 
{ 
    char szDottedD[16]; // The string used to collect the dotted decimal IP address 
    WORD cwNumChars = 0; 
    UINT16 InChar = 0; 
	INT32  dwCharRead = OEM_DEBUG_READ_NODATA; 
 
    KITLOutputDebugString ( "\r\nEnter new IP address: "); 
 
    while (!((InChar == 0x0d) || (InChar == 0x0a))) 
    { 
        dwCharRead = OEMReadDebugByte(); 
        if (dwCharRead != OEM_DEBUG_COM_ERROR && dwCharRead != OEM_DEBUG_READ_NODATA) 
        { 
			InChar = (UINT16)dwCharRead; 
            // If it's a number or a period, add it to the string 
            if (InChar == '.' || (InChar >= '0' && InChar <= '9')) 
            { 
                if (cwNumChars < 16) 
                { 
                    szDottedD[cwNumChars++] = (char)InChar; 
                    OEMWriteDebugByte((BYTE)InChar); 
                } 
            } 
            // If it's a backspace, back up 
            else if (InChar == 8) 
            { 
                if (cwNumChars > 0) 
                { 
                    cwNumChars--; 
                    OEMWriteDebugByte((BYTE)InChar); 
                } 
            } 
        } 
    } 
 
    // If it's a carriage return with an empty string, don't change anything. 
    if (cwNumChars) 
    { 
        szDottedD[cwNumChars] = '\0'; 
        pBootCFG->IP = inet_addr( szDottedD ); 
    } 
} 
 
 
//------------------------------------------------------------------------------ 
// 
//  Function:  SetMask 
// 
//  Allows user to set a subnet mask using the boot loader menu. 
// 
//  Parameters: 
//      eBootCFG  
//          [out] Points to bootloader configuration that will be updated with 
//          the subnet mask entered by the user. 
// 
//  Returns: 
//      None. 
// 
//------------------------------------------------------------------------------ 
static void SetMask(BOOT_CFG *pBootCFG) 
{ 
    char szDottedD[16]; // The string used to collect the dotted masks 
    WORD cwNumChars = 0; 
    UINT16 InChar = 0; 
    INT32  dwCharRead = OEM_DEBUG_READ_NODATA; 
 
    KITLOutputDebugString ( "\r\nEnter new subnet mask: "); 
 
    while (!((InChar == 0x0d) || (InChar == 0x0a))) 
    { 
        dwCharRead = OEMReadDebugByte(); 
        if (dwCharRead != OEM_DEBUG_COM_ERROR && dwCharRead != OEM_DEBUG_READ_NODATA) 
        { 
	    InChar = (UINT16)dwCharRead; 
            // If it's a number or a period, add it to the string 
            if (InChar == '.' || (InChar >= '0' && InChar <= '9')) 
            { 
                if (cwNumChars < 16) 
                { 
                    szDottedD[cwNumChars++] = (char)InChar; 
                    OEMWriteDebugByte((BYTE)InChar); 
                } 
            } 
            // If it's a backspace, back up 
            else if (InChar == 8) 
            { 
                if (cwNumChars > 0) 
                { 
                    cwNumChars--; 
                    OEMWriteDebugByte((BYTE)InChar); 
                } 
            } 
        } 
    } 
 
    // If it's a carriage return with an empty string, don't change anything. 
    if (cwNumChars) 
    { 
        szDottedD[cwNumChars] = '\0'; 
        pBootCFG->subnetMask = inet_addr( szDottedD ); 
    } 
}