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 ); } }