main.c
资源名称:SMDK2440.rar [点击查看]
上传用户:qiulin1960
上传日期:2013-10-16
资源大小:2844k
文件大小:43k
源码类别:
Windows CE
开发平台:
Windows_Unix
- //
- // 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.
- //
- /*++
- 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.
- Module Name:
- main.c
- Abstract:
- Ethernet boot loader main module. This file contains the C main
- for the boot loader. NOTE: The firmware "entry" point (the real
- entry point is _EntryPoint in init assembler file.
- The Windows CE boot loader is the code that is executed on a Windows CE
- development system at power-on reset and loads the Windows CE
- operating system. The boot loader also provides code that monitors
- the behavior of a Windows CE platform between the time the boot loader
- starts running and the time the full operating system debugger is
- available. Windows CE OEMs are supplied with sample boot loader code
- that runs on a particular development platform and CPU.
- Functions:
- Notes:
- --*/
- #include <windows.h>
- #include <pcireg.h>
- #include <ethdbg.h>
- #include <drv_glob.h>
- #include <nkintr.h>
- #include <pehdr.h>
- #include <romldr.h>
- #include <blcommon.h>
- #include <bootpart.h>
- #include <kitlprot.h>
- #include "s2440.h"
- #include "loader.h"
- #include "fmd.h"
- #include "cfnand.h"
- #include "warning.h"
- PDRIVER_GLOBALS pDriverGlobals = ((PDRIVER_GLOBALS) DRIVER_GLOBALS_PHYSICAL_MEMORY_START);
- extern BOOL UbootReadData (DWORD cbData, LPBYTE pbData);
- extern BOOL InitUSB ();
- extern void Isr_Init();
- // Some global definitions
- #ifdef SIMULATOR
- void CleanExit(DWORD dwExitCode);
- #define SPIN_FOREVER CleanExit(41);
- #else
- #define SPIN_FOREVER {while(TRUE);}
- #endif
- //
- // Global variables
- //
- static BOOLEAN g_bDownloadImage = TRUE;
- BOOLEAN g_bWaitForConnect;
- DWORD g_dwImageStartBlock;
- DWORD g_ImageType;
- DWORD g_dwMinImageStart;
- MultiBINInfo g_BINRegionInfo;
- BOOL g_bBootMediaExist = FALSE;
- BOOLEAN g_bUSBDownload = FALSE;
- #pragma pack(1)
- // N.B: only uses 1 sector for now.
- UCHAR g_TOC[SECTOR_SIZE];
- #pragma pack()
- const PTOC g_pTOC = (PTOC)&g_TOC;
- PBOOT_CFG g_pBootCfg;
- DWORD g_dwTocEntry;
- #ifdef DEBUG
- DWORD EdbgDebugZone = 0;//ZONE_WARNING|ZONE_INIT; //ZONE_DHCP;
- #endif
- // External functions
- extern void InitClock();
- extern DWORD OEMAddressTable[];
- void Launch();
- void BootloaderMain (void);
- BOOL InitEthDevice(PBOOT_CFG pBootCfg);
- static void SetDelay();
- static void SetCS8900MACAddress();
- // Function prototypes
- static BOOL GetUserIPAddr (EDBG_ADDR *pMyAddr, LPDWORD pdwSubnetMask);
- #define LAST_LAUNCH_ADDR_VALID 0xBADBEEF6
- // Local util function
- //
- DWORD
- ToPhysicalAddr(DWORD add)
- {
- DWORD padd = add;
- DWORD * pt = OEMAddressTable;
- DWORD vir_start;
- DWORD vir_end;
- DWORD phy_start;
- DWORD sz;
- EdbgOutputDebugString("+ToPhysicalAddr:0x%xrn", add);
- do
- {
- vir_start = *pt++;
- phy_start = *pt++;
- sz = *pt++;
- if (vir_start == 0 && phy_start == 0 && sz == 0) break;
- vir_end = vir_start + sz * (1024 * 1024);
- if (add >= vir_start && add < vir_end)
- {
- padd = add - vir_start + phy_start;
- break;
- }
- } while (1);
- EdbgOutputDebugString("-ToPhysicalAddr:0x%xrn", padd);
- return padd;
- }
- // util function that should really be in blcommon
- //
- static void
- itoa10(
- int n,
- char s[]
- )
- {
- int i = 0;
- // Get absolute value of number
- unsigned int val = (unsigned int)((n < 0) ? -n : n);
- // Extract digits in reverse order
- do {
- s[i++] = (val % 10) + '0';
- } while (val /= 10);
- // Add sign if number negative
- if (n < 0) s[i++] = '-';
- s[i--] = ' ';
- // Reverse string
- for (n = 0; n < i; n++, i--) {
- char swap = s[n];
- s[n] = s[i];
- s[i] = swap;
- }
- }
- static void
- CreateDeviceName(
- EDBG_ADDR *pMyAddr,
- char *szBuf
- )
- {
- strcpy(szBuf,PLATFORM_STRING);
- szBuf += strlen(szBuf);
- itoa10(((pMyAddr->wMAC[2]>>8) | ((pMyAddr->wMAC[2] & 0x00ff) << 8)), szBuf);
- }
- #ifdef TODO
- // This routine programs the serial EEPROM and sets the
- // Ethernet Address to 00 50 F2 08 NN NN (N=Debug board number).
- static void SetSerialNumber(USHORT dbgBoardSerialNumber) {
- USHORT i;
- EdbgOutputDebugString("SetSerialNumber: %u rn", dbgBoardSerialNumber);
- if ((dbgBoardSerialNumber <0) || (dbgBoardSerialNumber > 32000)) {
- EdbgOutputDebugString("Error Serial Number between 0 and 32000n");
- }
- for (i=0;i<16;i+=2) {
- // Set all switch Areas to the same
- SMCWriteEEPROM((UINT16)(0x0+i), 0xB0);
- SMCWriteEEPROM((UINT16)(0x1+i), 0x1866);
- }
- for (i=16;i<0x20;i++) {
- SMCWriteEEPROM(i,0x0);
- }
- // Avenger is 00-50-F2-03-XX-XX
- // Trango is 00-50-F2-08-XX-XX
- // Catfish is 00-50-F2-08-XX-XX ??
- SMCWriteEEPROM(0x20, 0x5000); // Is 00-50-??-??-??-??
- SMCWriteEEPROM(0x21, 0x08F2); // Is ??-??-F2-08-??-??
- SMCWriteEEPROM(0x22, htons((UINT16)(dbgBoardSerialNumber)));
- SMCWriteEEPROM(0x23, 0x389D);
- SMCWriteEEPROM(0x24, 0x4595);
- SMCWriteEEPROM(0x25, 0xFFFF);
- SMCWriteEEPROM(0x26, 0x00FC);
- SMCWriteEEPROM(0x27, 0x0000);
- SMCWriteEEPROM(0x28, 0x5765);
- SMCWriteEEPROM(0x29, 0x2776);
- SMCWriteEEPROM(0x2A, 0x6520);
- SMCWriteEEPROM(0x2B, 0x7374);
- SMCWriteEEPROM(0x2C, 0x696C);
- SMCWriteEEPROM(0x2D, 0x6C20);
- SMCWriteEEPROM(0x2E, 0x676F);
- SMCWriteEEPROM(0x2F, 0x7420);
- }
- #endif
- //
- // Functions called from blcommon
- //
- /*
- @func BOOL | OEMVerifyMemory | Verify that the memory to be used by the downloaded BIN file is valid. This function also decides whether the image is the
- bootloader or not based on its address (this information is used later when deciding how to store the image in flash).
- @rdesc TRUE = Address specified is valid memory, FALSE = Address specified is *not* valid memory.
- @comm
- @xref
- */
- BOOL OEMVerifyMemory(DWORD dwStartAddr, DWORD dwLength)
- {
- RETAILMSG(1, (TEXT("OEMVerifyMemory: StartAddr: 0x%x, Length:0x%x rn"), dwStartAddr, dwLength));
- // Is the image being downloaded the bootloader?
- if ((dwStartAddr >= EBOOT_STORE_ADDRESS) &&
- ((dwStartAddr + dwLength - 1) < (EBOOT_STORE_ADDRESS + EBOOT_STORE_MAX_LENGTH)))
- {
- RETAILMSG(1, (TEXT("Downloading Bootloader imagern")));
- g_ImageType = IMAGE_TYPE_LOADER; // Bootloader image.
- return TRUE;
- }
- // if it's MXIP don't test address to allow PPC images using funky addresses in their .BIN regions
- else if ( g_BINRegionInfo.dwNumRegions > 1 )
- {
- RETAILMSG(1, (TEXT("Downloading %d regions of MXIP imagern"), g_BINRegionInfo.dwNumRegions));
- // 1st region is RAMIMAGE, remaining are MXIP
- g_ImageType = IMAGE_TYPE_RAMIMAGE | IMAGE_TYPE_BINFS | IMAGE_TYPE_MXIP;
- return TRUE;
- }
- // Is it a ram image?
- else if ((dwStartAddr >= ROM_RAMIMAGE_START) &&
- ((dwStartAddr + dwLength - 1) < (ROM_RAMIMAGE_START + ROM_RAMIMAGE_SIZE)))
- {
- RETAILMSG(1, (TEXT("Downloading RAM imagern")));
- g_ImageType = IMAGE_TYPE_RAMIMAGE;
- return TRUE;
- }
- // HACKHACK: get around MXIP images with funky addresses
- RETAILMSG(1, (TEXT("*** Downloading BIN image type ***rn")));
- return TRUE;
- }
- /*
- @func void | OEMMultiBINNotify | Called by blcommon to nofity the OEM code of the number, size, and location of one or more BIN regions,
- this routine collects the information and uses it when temporarily caching a flash image in RAM prior to final storage.
- @rdesc N/A.
- @comm
- @xref
- */
- void OEMMultiBINNotify(const PMultiBINInfo pInfo)
- {
- BYTE nCount;
- if (!pInfo || !pInfo->dwNumRegions)
- {
- EdbgOutputDebugString("WARNING: OEMMultiBINNotify: Invalid BIN region descriptor(s).rn");
- return;
- }
- g_dwMinImageStart = pInfo->Region[0].dwRegionStart;
- EdbgOutputDebugString("rnOEMMultiBINNotify: Download BIN file information:rn");
- EdbgOutputDebugString("-----------------------------------------------------rn");
- for (nCount = 0 ; nCount < pInfo->dwNumRegions ; nCount++)
- {
- EdbgOutputDebugString("[%d]: Base Address=0x%x Length=0x%xrn" ,
- nCount, pInfo->Region[nCount].dwRegionStart, pInfo->Region[nCount].dwRegionLength);
- if (pInfo->Region[nCount].dwRegionStart < g_dwMinImageStart)
- {
- g_dwMinImageStart = pInfo->Region[nCount].dwRegionStart;
- if (g_dwMinImageStart == 0)
- {
- EdbgOutputDebugString("WARNING: OEMMultiBINNotify: Bad start address for region (%d).rn", nCount);
- return;
- }
- }
- }
- memcpy((LPBYTE)&g_BINRegionInfo, (LPBYTE)pInfo, sizeof(MultiBINInfo));
- EdbgOutputDebugString("-----------------------------------------------------rn");
- }
- BOOL OEMReportError(DWORD dwReason, DWORD dwReserved)
- {
- EdbgOutputDebugString("OEMReportError(%d, %d)rn", dwReason, dwReserved);
- return TRUE;
- }
- /*
- @func BOOL | OEMDebugInit | Function wrapper for OEMInitDebugSerial.
- @rdesc TRUE = Success, FALSE = Failure.
- @comm
- @xref
- */
- BOOL OEMDebugInit()
- {
- // Assign callback functions to be usec by blcommon.
- //
- g_pOEMReportError = OEMReportError;
- g_pOEMVerifyMemory = OEMVerifyMemory; // Verify memory to be used by downloaded image...
- g_pOEMMultiBINNotify = OEMMultiBINNotify; // Notified of all the BIN files to be downloaded...
- OEMInitDebugSerial();
- return TRUE;
- }
- /*
- @func BOOL | BootMonitor | Manages the bootloader monitor.
- @rdesc TRUE = user selected download image, FALSE = user selected launch stored image.
- @comm
- @xref
- */
- static BOOLEAN BootMonitor( )
- {
- int KeySelect = 0;
- BOOLEAN bConfigChanged = FALSE;
- BOOLEAN bDownload = TRUE;
- while(1)
- {
- KeySelect = 0;
- EdbgOutputDebugString ( "rnEthernet Boot Loader Configuration:rn");
- EdbgOutputDebugString ( "---------------------------------------rn");
- EdbgOutputDebugString ( "1) IP address: %srn", inet_ntoa(g_pBootCfg->EdbgAddr.dwIP));
- EdbgOutputDebugString ( " Subnet mask: %srn", inet_ntoa(g_pBootCfg->SubnetMask));
- EdbgOutputDebugString ( "2) Boot delay: %d secondsrn", g_pBootCfg->BootDelay);
- EdbgOutputDebugString ( "3) DHCP: %srn", (g_pBootCfg->ConfigFlags & CONFIG_FLAGS_DHCP) ? "ENABLED" : "DISABLED");
- EdbgOutputDebugString ( "4) Reset TOC to defaultrn");
- EdbgOutputDebugString ( "5) Startup image: %srn", (g_pBootCfg->ConfigFlags & BOOT_TYPE_DIRECT) ? "LAUNCH EXISTING" : "DOWNLOAD NEW");
- EdbgOutputDebugString ( "6) Program RAM image into Boot Media: %srn", (g_pBootCfg->ConfigFlags & TARGET_TYPE_NAND) ? "ENABLED" : "DISABLED");
- EdbgOutputDebugString ( "7) MAC address: %B:%B:%B:%B:%B:%Brn",
- g_pBootCfg->EdbgAddr.wMAC[0] & 0x00FF, g_pBootCfg->EdbgAddr.wMAC[0] >> 8,
- g_pBootCfg->EdbgAddr.wMAC[1] & 0x00FF, g_pBootCfg->EdbgAddr.wMAC[1] >> 8,
- g_pBootCfg->EdbgAddr.wMAC[2] & 0x00FF, g_pBootCfg->EdbgAddr.wMAC[2] >> 8);
- EdbgOutputDebugString ( "8) Kernel Debugger: %srn", (g_pBootCfg->ConfigFlags & CONFIG_FLAGS_DEBUGGER) ? "ENABLED" : "DISABLED");
- EdbgOutputDebugString ( "9) Format Boot Media for BinFSrn");
- EdbgOutputDebugString ( "rn");
- // N.B: we need this option here since BinFS is really a RAM image, where you "format" the media
- // with an MBR. There is no way to parse the image to say it's ment to be BinFS enabled.
- EdbgOutputDebugString ( "B) Support BinFS: %srn", (g_pTOC->id[g_dwTocEntry].dwImageType & IMAGE_TYPE_BINFS) ? "ENABLED" : "DISABLED");
- EdbgOutputDebugString ( "D) DOWNLOAD image now(Etherent)rn");
- // EdbgOutputDebugString ( "E) Image descriptor Entry: %u rn", g_dwTocEntry);
- EdbgOutputDebugString ( "F) Low-level FORMAT Boot Mediarn");
- EdbgOutputDebugString ( "L) LAUNCH existing Boot Media imagern");
- EdbgOutputDebugString ( "R) Read Configuration rn");
- EdbgOutputDebugString ( "U) DOWNLOAD image now(USB)rn");
- EdbgOutputDebugString ( "W) Write Configuration Right Nowrn");
- EdbgOutputDebugString ( "X) DOWNLOAD image to boot media, then LAUNCH it off the mediarn");
- EdbgOutputDebugString ( "---------------------------------------rn");
- EdbgOutputDebugString ( "rnEnter your selection: ");
- while (! ( ( (KeySelect >= '0') && (KeySelect <= '9') ) ||
- ( (KeySelect == 'B') || (KeySelect == 'b') ) ||
- ( (KeySelect == 'E') || (KeySelect == 'e') ) ||
- ( (KeySelect == 'F') || (KeySelect == 'f') ) ||
- ( (KeySelect == 'D') || (KeySelect == 'd') ) ||
- ( (KeySelect == 'L') || (KeySelect == 'l') ) ||
- ( (KeySelect == 'R') || (KeySelect == 'r') ) ||
- ( (KeySelect == 'U') || (KeySelect == 'u') ) ||
- ( (KeySelect == 'W') || (KeySelect == 'w') ) ||
- ( (KeySelect == 'X') || (KeySelect == 'x') )
- ))
- {
- KeySelect = OEMReadDebugByte();
- }
- EdbgOutputDebugString ( "%crn", KeySelect);
- switch(KeySelect)
- {
- case '1': // Change IP/Subnet address.
- if ( GetUserIPAddr(&g_pBootCfg->EdbgAddr, &g_pBootCfg->SubnetMask) ) {
- g_pBootCfg->ConfigFlags &= ~CONFIG_FLAGS_DHCP; // clear DHCP flag
- bConfigChanged = TRUE;
- }
- continue;
- break;
- case '2': // Change autoboot delay.
- SetDelay(g_pBootCfg);
- bConfigChanged = TRUE;
- continue;
- break;
- case '3': // Toggle static/DHCP mode.
- g_pBootCfg->ConfigFlags = (g_pBootCfg->ConfigFlags ^ CONFIG_FLAGS_DHCP);
- bConfigChanged = TRUE;
- continue;
- break;
- case '4': // Reset TOC configuration.
- RETAILMSG(1, (TEXT("Resetting default TOC...rn")));
- TOC_Init(DEFAULT_IMAGE_DESCRIPTOR, (IMAGE_TYPE_RAMIMAGE|IMAGE_TYPE_BINFS), 0, 0, 0);
- if ( !TOC_Write() ) {
- RETAILMSG(1, (TEXT("TOC_Write Failed!rn")));
- }
- RETAILMSG(1, (TEXT("...TOC completern")));
- continue;
- break;
- case '5': // Toggle download/launch status.
- g_pBootCfg->ConfigFlags = (g_pBootCfg->ConfigFlags ^ BOOT_TYPE_DIRECT);
- bConfigChanged = TRUE;
- break;
- case '6': // Toggle boot media image store.
- g_pBootCfg->ConfigFlags = (g_pBootCfg->ConfigFlags ^ TARGET_TYPE_NAND);
- bConfigChanged = TRUE;
- break;
- case '7': // Configure MAC address.
- SetCS8900MACAddress();
- bConfigChanged = TRUE;
- continue;
- break;
- case '8': // Toggle KD
- g_pBootCfg->ConfigFlags = (g_pBootCfg->ConfigFlags ^ CONFIG_FLAGS_DEBUGGER);
- g_bWaitForConnect = (g_pBootCfg->ConfigFlags & CONFIG_FLAGS_DEBUGGER) ? TRUE : FALSE;
- bConfigChanged = TRUE;
- continue;
- break;
- case '9':
- // format the boot media for BinFS
- // N.B: this does not destroy our OEM reserved sections (TOC, bootloaders, etc)
- if ( !g_bBootMediaExist ) {
- RETAILMSG(1, (TEXT("ERROR: BootMonitor: boot media does not exist.rn")));
- continue;
- }
- // N.B: format offset by # of reserved blocks,
- // decrease the ttl # blocks available by that amount.
- if ( !BP_LowLevelFormat( g_dwImageStartBlock,
- NUM_BLOCKS - g_dwImageStartBlock,
- 0) )
- {
- RETAILMSG(1, (TEXT("ERROR: BootMonitor: Low-level boot media format failed.rn")));
- continue;
- }
- break;
- case 'B':
- case 'b':
- g_pTOC->id[g_dwTocEntry].dwImageType = (g_pTOC->id[g_dwTocEntry].dwImageType ^ IMAGE_TYPE_BINFS);
- g_ImageType = g_pTOC->id[g_dwTocEntry].dwImageType;
- bConfigChanged = TRUE;
- break;
- case 'E':
- case 'e':
- // TODO
- break;
- case 'F':
- case 'f':
- // low-level format
- // N.B: this erases images, BinFs, FATFS, user data, etc.
- // However, we don't format Bootloaders & TOC bolcks; use JTAG for this.
- if ( !g_bBootMediaExist ) {
- RETAILMSG(1, (TEXT("ERROR: BootMonitor: boot media does not exist.rn")));
- continue;
- } else {
- DWORD i;
- SectorInfo si;
- // to keep bootpart off of our reserved blocks we must mark it as bad, reserved & read-only
- si.bOEMReserved = OEM_BLOCK_RESERVED | OEM_BLOCK_READONLY;
- si.bBadBlock = BADBLOCKMARK;
- si.dwReserved1 = 0;
- si.wReserved2 = 0;
- RETAILMSG(1, (TEXT("Reserving Blocks [0x%x - 0x%x] ...rn"), 0, IMAGE_START_BLOCK-1));
- for (i = 0; i < IMAGE_START_SECTOR; i++) {
- FMD_WriteSector(i, NULL, &si, 1);
- }
- RETAILMSG(1, (TEXT("...reserve complete.rn")));
- RETAILMSG(1, (TEXT("Low-level format Blocks [0x%x - 0x%x] ...rn"), IMAGE_START_BLOCK, NUM_BLOCKS-1));
- for (i = IMAGE_START_BLOCK; i < NUM_BLOCKS; i++) {
- FMD_EraseBlock(i);
- }
- RETAILMSG(1, (TEXT("...erase complete.rn")));
- } break;
- case 'D': // Download? Yes.
- case 'd':
- bDownload = TRUE;
- goto MENU_DONE;
- case 'L': // Download? No.
- case 'l':
- bDownload = FALSE;
- goto MENU_DONE;
- case 'R':
- case 'r':
- TOC_Read();
- continue;
- // TODO
- break;
- case 'U': // Download? No.
- case 'u':
- g_bWaitForConnect = FALSE;
- bConfigChanged = TRUE;
- g_bUSBDownload = TRUE;
- bDownload = TRUE;
- goto MENU_DONE;
- case 'W': // Configuration Write
- case 'w':
- if (!TOC_Write())
- {
- RETAILMSG(1, (TEXT("WARNING: MainMenu: Failed to store updated eboot configuration in flash.rn")));
- }
- else
- {
- RETAILMSG(1, (TEXT("Successfully Writtenrn")));
- bConfigChanged = FALSE;
- }
- break;
- case 'X': // Download to media, then launch that
- case 'x':
- bDownload = TRUE;
- bConfigChanged = TRUE;
- g_pBootCfg->ConfigFlags |= TARGET_TYPE_NAND | BOOT_TYPE_DIRECT;
- goto MENU_DONE;
- default:
- break;
- }
- }
- MENU_DONE:
- // If eboot settings were changed by user, save them.
- //
- if (bConfigChanged && !TOC_Write( ) )
- {
- RETAILMSG(1, (TEXT("WARNING: BootMonitor: Failed to store updated eboot configuration in flash.rn")));
- }
- return(bDownload);
- }
- /*
- @func BOOL | OEMPlatformInit | Initialize the platform hardware.
- @rdesc TRUE = Success, FALSE = Failure.
- @comm
- @xref
- */
- BOOL OEMPlatformInit()
- {
- SYSTEMTIME st;
- SYSTEMTIME defst = {2002, 1, 0, 1, 12, 0, 0, 0};
- DWORD dwStartTime, dwPrevTime, dwCurrTime;
- int cKeySelect = 0;
- DWORD dwBootDelay = 10; // seconds. N.B: change for retail device!
- #ifdef SIMULATOR
- EdbgOutputDebugString("Microsoft Windows CE SMDK2440 Bootloader *** SIMULATOR *** rn");
- #else
- EdbgOutputDebugString("Microsoft Windows CE SMDK2440 Bootloader Version %d.%d Built %s %s rn",
- EBOOT_VERSION_MAJOR, EBOOT_VERSION_MINOR, __DATE__, __TIME__);
- #endif
- // Initialize the globals
- //
- memset((LPVOID) &(pDriverGlobals->eth), 0, DBG_ETH_GLOBALS_SIZE);
- memset((LPVOID) &g_TOC, 0, sizeof(g_TOC));
- // This should not change unless reserved blocks are added/removed;
- // made global to do the calc only once.
- g_dwImageStartBlock = IMAGE_START_BLOCK;
- // Check real time clock, initialize if necessary (used for polling in net routines)
- //
- OEMGetRealTime(&st);
- if ((st.wYear < 2000) ||
- (st.wMonth < 1) ||
- (st.wMonth > 12) ||
- (st.wDay < 1) ||
- (st.wDay > 31) ||
- (st.wHour > 23) ||
- (st.wMinute > 59) ||
- (st.wSecond > 59) ||
- (st.wMilliseconds > 999)) {
- OEMSetRealTime(&defst);
- }
- else {
- OEMSetRealTime(&st);
- }
- if (!InitUSB())
- {
- DEBUGMSG(1, (TEXT("OEMPlatformInit: Failed to initialize USB.rn")));
- return(FALSE);
- }
- Isr_Init();
- // Try to initialize the boot media block driver and BinFS partition.
- //
- if ( !BP_Init((LPBYTE)BINFS_RAM_START, BINFS_RAM_LENGTH, NULL, NULL, NULL) )
- {
- EdbgOutputDebugString("WARNING: OEMPlatformInit failed to initialize Boot Media.rnrn");
- g_bBootMediaExist = FALSE;
- }
- else
- g_bBootMediaExist = TRUE;
- // Try to retrieve TOC (and Boot config) from boot media
- //
- if ( !TOC_Read( ) ) {
- // use default settings
- TOC_Init(DEFAULT_IMAGE_DESCRIPTOR, (IMAGE_TYPE_RAMIMAGE|IMAGE_TYPE_BINFS), 0, 0, 0);
- }
- // Start boot monitor prompt
- //
- dwBootDelay = g_pBootCfg->BootDelay;
- if (g_pBootCfg->ConfigFlags & BOOT_TYPE_DIRECT)
- {
- EdbgOutputDebugString ( "Press [ENTER] to launch image stored on boot media, or [SPACE] to enter boot monitor.rn");
- EdbgOutputDebugString ( "rnInitiating image launch in %d seconds. ", dwBootDelay--);
- } else
- {
- EdbgOutputDebugString ( "Press [ENTER] to download image now, or [SPACE] to enter boot monitor.rn");
- EdbgOutputDebugString ( "rnInitiating image download in %d seconds. ", dwBootDelay--);
- }
- dwStartTime = OEMEthGetSecs();
- dwPrevTime = dwStartTime;
- dwCurrTime = dwStartTime;
- // allow the user to break into boot monitor
- while((dwCurrTime - dwStartTime) < dwBootDelay)
- {
- cKeySelect = OEMReadDebugByte();
- if ((cKeySelect == 0x20) || (cKeySelect == 0x0d))
- break;
- dwCurrTime = OEMEthGetSecs();
- if (dwCurrTime > dwPrevTime)
- {
- int i=0, j;
- // 1 Second has elapsed - update the countdown timer.
- dwPrevTime = dwCurrTime;
- if (dwBootDelay < 9)
- i = 11;
- else if (dwBootDelay < 99)
- i = 12;
- else if (dwBootDelay < 999)
- i = 13;
- for(j = 0; j < i; j++)
- OEMWriteDebugByte((BYTE)0x08); // print back space
- EdbgOutputDebugString ( "%d seconds. ", dwBootDelay--);
- }
- }
- EdbgOutputDebugString ( "rn");
- switch(cKeySelect)
- {
- case 0x20: // Boot monitor.
- g_bDownloadImage = BootMonitor( );
- break;
- case 0x00: // Fall through if no keys were pressed -or-
- case 0x0d: // the user cancelled the countdown.
- default:
- if (g_pBootCfg->ConfigFlags & BOOT_TYPE_DIRECT)
- {
- EdbgOutputDebugString ( "rnLaunching image from boot media ... rn");
- g_bDownloadImage = FALSE;
- }
- else
- {
- EdbgOutputDebugString ( "rnStarting auto-download ... rn");
- g_bDownloadImage = TRUE;
- }
- break;
- }
- // NOTE - right now, we assume that if we're downloading, it's done over Ethernet.
- // In the future, this may include other transports (USB, etc.).
- //
- if ( !g_bDownloadImage )
- {
- // User doesn't want to download image - load it from the boot media.
- // We could read an entire nk.bin or nk.nb0 into ram and jump.
- if ( !VALID_TOC(g_pTOC) ) {
- EdbgOutputDebugString("OEMPlatformInit: ERROR_INVALID_TOC, can not autoboot.rn");
- return FALSE;
- }
- switch (g_ImageType) {
- case IMAGE_TYPE_LOADER:
- EdbgOutputDebugString("OEMPlatformInit: IMAGE_TYPE_LOADERrn");
- break;
- case IMAGE_TYPE_RAMIMAGE:
- EdbgOutputDebugString("OEMPlatformInit: IMAGE_TYPE_RAMIMAGErn");
- if ( !ReadRamImageFromBootMedia( ) ) {
- RETAILMSG(1, (TEXT("OEMPlatformInit ERROR: Failed to load kernel region into RAM.rn")));
- return FALSE;
- }
- break;
- case (IMAGE_TYPE_RAMIMAGE|IMAGE_TYPE_BINFS):
- case (IMAGE_TYPE_RAMIMAGE|IMAGE_TYPE_BINFS|IMAGE_TYPE_MXIP):
- EdbgOutputDebugString("OEMPlatformInit: IMAGE_TYPE_RAMIMAGE|IMAGE_TYPE_BINFS|IMAGE_TYPE_MXIPrn");
- // N.B: this assumes the image is setup as multi-bin for BinFS.
- if ( !ReadKernelRegionFromBootMedia( ) ) {
- RETAILMSG(1, (TEXT("OEMPlatformInit ERROR: Failed to load kernel region into RAM.rn")));
- return FALSE;
- }
- break;
- default:
- EdbgOutputDebugString("OEMPlatformInit ERROR: unknown image type: 0x%x rn", g_ImageType );
- return FALSE;
- }
- }
- // If user specified a static IP address, use it (don't use DHCP).
- //
- if (g_bDownloadImage && !(g_pBootCfg->ConfigFlags & CONFIG_FLAGS_DHCP))
- {
- pDriverGlobals->eth.TargetAddr.dwIP = g_pBootCfg->EdbgAddr.dwIP;
- pDriverGlobals->eth.SubnetMask = g_pBootCfg->SubnetMask;
- }
- // Configure Ethernet controller.
- if ( g_pBootCfg->ConfigFlags & CONFIG_FLAGS_DEBUGGER )
- {
- if (!InitEthDevice(g_pBootCfg))
- {
- DEBUGMSG(1, (TEXT("OEMPlatformInit: Failed to initialize Ethernet controller.rn")));
- return(FALSE);
- }
- }
- return TRUE;
- }
- /*
- @func DWORD | OEMPreDownload | Complete pre-download tasks - get IP address, initialize TFTP, etc.
- @rdesc BL_DOWNLOAD = Platform Builder is asking us to download an image,
- BL_JUMP = Platform Builder is requesting we jump to an existing image,
- BL_ERROR = Failure.
- @comm
- @xref
- */
- DWORD OEMPreDownload()
- {
- char szDeviceName[EDBG_MAX_DEV_NAMELEN];
- BOOL fGotJumpImg = FALSE;
- DWORD DHCPLeaseTime = 0, *pDHCPLeaseTime = &DHCPLeaseTime;
- // If user wants to jump to existing image with no KD - skip download...
- //
- if ( !g_bDownloadImage && !g_bWaitForConnect)
- {
- return(BL_JUMP);
- }
- if ( !g_bDownloadImage && g_bWaitForConnect )
- fGotJumpImg = TRUE;
- //
- // Create device name based on MAC address.
- //
- memset(szDeviceName, 0, EDBG_MAX_DEV_NAMELEN);
- CreateDeviceName(&g_pBootCfg->EdbgAddr, szDeviceName);
- EdbgOutputDebugString("Using device name: '%s'n", szDeviceName);
- // initialize TFTP transport
- //
- if ( !(g_pBootCfg->ConfigFlags & CONFIG_FLAGS_DHCP) ) {
- pDHCPLeaseTime = NULL; // the pDHCPLeaseTime parameter is overloaded.
- // NULL indicates static IP
- pDriverGlobals->eth.EdbgFlags = EDBG_FLAGS_STATIC_IP;
- }
- #ifndef SIMULATOR
- if ( g_bUSBDownload == FALSE )
- {
- if (g_bDownloadImage &&
- !EbootInitEtherTransport (&g_pBootCfg->EdbgAddr, &g_pBootCfg->SubnetMask, &fGotJumpImg, pDHCPLeaseTime,
- EBOOT_VERSION_MAJOR, EBOOT_VERSION_MINOR, PLATFORM_STRING, szDeviceName, EDBG_CPUID, 0)) {
- return BL_ERROR;
- }
- }
- #endif
- // SMCSetOptions(OPT_BROADCAST_FILTERING);
- // update DHCP lease time
- pDriverGlobals->eth.DHCPLeaseTime = DHCPLeaseTime;
- if ( g_bUSBDownload == TRUE )
- EdbgOutputDebugString("Please send the Image through USBrn");
- return fGotJumpImg? BL_JUMP : BL_DOWNLOAD;
- }
- /*
- @func void | OEMLaunch | Executes the stored/downloaded image.
- @rdesc N/A.
- @comm
- @xref
- */
- void OEMLaunch(DWORD dwImageStart, DWORD dwImageLength, DWORD dwLaunchAddr, const ROMHDR *pRomHdr)
- {
- EDBG_OS_CONFIG_DATA *pCfgData;
- EDBG_ADDR EshellHostAddr = {0,0,0};
- EdbgOutputDebugString("::OEMLaunch, ImageStart:0x%x, ImageLength:0x%x, LaunchAddr:0x%xrn",
- dwImageStart, dwImageLength, dwLaunchAddr);
- // Wait for Platform Builder to connect after the download and send us IP and port settings for service
- // connections - also sends us KITL flags. This information is used later by the OS (KITL).
- //
- #ifndef SIMULATOR
- if ( g_bDownloadImage && g_bWaitForConnect )
- {
- EdbgOutputDebugString ("EbootWaitForHostConenctrn");
- pCfgData = EbootWaitForHostConnect (&g_pBootCfg->EdbgAddr, &EshellHostAddr);
- if (!pCfgData) {
- EdbgOutputDebugString ("EbootWaitForHostConenct failed, spin foreverrn");
- SPIN_FOREVER;
- }
- if (pCfgData->Flags & EDBG_FL_DBGMSG) {
- EdbgOutputDebugString("Enabling debug messages over Ethernet, IP: %s, port:%un",
- inet_ntoa(pCfgData->DbgMsgIPAddr),ntohs(pCfgData->DbgMsgPort));
- memcpy(&pDriverGlobals->eth.DbgHostAddr.wMAC,&EshellHostAddr.wMAC,6);
- pDriverGlobals->eth.DbgHostAddr.dwIP = pCfgData->DbgMsgIPAddr;
- pDriverGlobals->eth.DbgHostAddr.wPort = pCfgData->DbgMsgPort;
- }
- if (pCfgData->Flags & EDBG_FL_PPSH) {
- EdbgOutputDebugString("Enabling CESH over Ethernet, IP: %s, port:%un",
- inet_ntoa(pCfgData->PpshIPAddr),ntohs(pCfgData->PpshPort));
- memcpy(&pDriverGlobals->eth.PpshHostAddr.wMAC,&EshellHostAddr.wMAC,6);
- pDriverGlobals->eth.PpshHostAddr.dwIP = pCfgData->PpshIPAddr;
- pDriverGlobals->eth.PpshHostAddr.wPort = pCfgData->PpshPort;
- }
- if (pCfgData->Flags & EDBG_FL_KDBG) {
- EdbgOutputDebugString("Enabling KDBG over Ethernet, IP: %s, port:%un",
- inet_ntoa(pCfgData->KdbgIPAddr),ntohs(pCfgData->KdbgPort));
- memcpy(&pDriverGlobals->eth.KdbgHostAddr.wMAC,&EshellHostAddr.wMAC,6);
- pDriverGlobals->eth.KdbgHostAddr.dwIP = pCfgData->KdbgIPAddr;
- pDriverGlobals->eth.KdbgHostAddr.wPort = pCfgData->KdbgPort;
- }
- memcpy(&pDriverGlobals->eth.DownloadHostAddr,&EshellHostAddr,sizeof(EDBG_ADDR));
- pDriverGlobals->eth.etherFlags = pCfgData->Flags;
- pDriverGlobals->eth.KitlTransport = pCfgData->KitlTransport;
- EdbgOutputDebugString ("KitlTransport: 0x%xrn", pCfgData->KitlTransport);
- pDriverGlobals->eth.EbootMagicNum = EBOOT_MAGIC_NUM;
- }
- else if ( !g_bDownloadImage && g_bWaitForConnect)
- {
- EdbgOutputDebugString ("Eboot setup Kitl from media bootrn");
- pDriverGlobals->eth.KitlTransport = KTS_ETHER;
- pDriverGlobals->eth.EbootMagicNum = EBOOT_MAGIC_NUM;
- }
- #endif
- // Update address info, in driver globals, and in EEPROM if necessary
- memcpy (&pDriverGlobals->eth.TargetAddr, &g_pBootCfg->EdbgAddr, sizeof(g_pBootCfg->EdbgAddr));
- pDriverGlobals->eth.SubnetMask = g_pBootCfg->SubnetMask;
- // If the user requested an image be stored on media, do so now. For multiple RAM BIN files, we need to map
- // its RAM address to a flash address - the image base address offset in RAM is maintained in flash.
- //
- // Remember kernel launch address or recall stored address if this download didn't provide one
- // (i.e., we didn't download the kernel region).
- if (g_bDownloadImage && (g_pBootCfg->ConfigFlags & TARGET_TYPE_NAND))
- {
- if (dwImageStart && dwImageLength)
- {
- g_pTOC->id[g_dwTocEntry].dwLoadAddress = dwImageStart;
- g_pTOC->id[g_dwTocEntry].dwTtlSectors = FILE_TO_SECTOR_SIZE(dwImageLength);
- }
- switch ( g_ImageType ) {
- case IMAGE_TYPE_LOADER:
- EdbgOutputDebugString("OEMLaunch: IMAGE_TYPE_LOADERrn");
- if ( !WriteRamImageToBootMedia(g_dwTocEntry) ) {
- RETAILMSG(1, (TEXT("OEMLaunch ERROR: Failed to write image to boot media.rn")));
- SPIN_FOREVER;
- }
- break;
- case IMAGE_TYPE_RAMIMAGE:
- EdbgOutputDebugString("OEMLaunch: IMAGE_TYPE_RAMIMAGErn");
- if ( !WriteRamImageToBootMedia(g_dwTocEntry) ) {
- RETAILMSG(1, (TEXT("OEMLaunch ERROR: Failed to write image to boot media.rn")));
- SPIN_FOREVER;
- }
- break;
- case (IMAGE_TYPE_RAMIMAGE|IMAGE_TYPE_BINFS|IMAGE_TYPE_MXIP):
- case (IMAGE_TYPE_RAMIMAGE|IMAGE_TYPE_BINFS):
- EdbgOutputDebugString("OEMLaunch: (%s|IMAGE_TYPE_BINFS)rn",
- (g_ImageType & IMAGE_TYPE_MXIP) ? "IMAGE_TYPE_MXIP" : "IMAGE_TYPE_RAMIMAGE");
- if ( !WriteRegionsToBootMedia(dwImageStart, dwImageLength, dwLaunchAddr) ) {
- EdbgOutputDebugString("WARNING: OEMLaunch: Failed to store BinFS regions to boot media.rn");
- SPIN_FOREVER;
- }
- break;
- default:
- EdbgOutputDebugString("OEMLaunch ERROR: unknown image type: 0x%x rn",
- g_pTOC->id[g_dwTocEntry].dwImageType);
- SPIN_FOREVER;
- }
- }
- // Remember kernel launch address or recall stored address if this download didn't provide one (i.e., we didn't download the kernel region).
- //
- if (dwLaunchAddr && (g_pTOC->id[g_dwTocEntry].dwJumpAddress != dwLaunchAddr))
- {
- g_pTOC->id[g_dwTocEntry].dwJumpAddress = dwLaunchAddr;
- if ( !TOC_Write() ) {
- EdbgOutputDebugString("*** OEMLaunch ERROR: TOC_Write failed! Next boot may not load from disk *** rn");
- }
- TOC_Print();
- }
- else
- {
- dwLaunchAddr= g_pTOC->id[g_dwTocEntry].dwJumpAddress;
- EdbgOutputDebugString("INFO: using TOC[%d] dwJumpAddress: 0x%xrn", g_dwTocEntry, dwLaunchAddr);
- }
- EdbgOutputDebugString("rnJumping to image at virtual address 0x%Xhrn", dwLaunchAddr);
- // Our Launch function takes Physical address, so we need to convert it
- // to physical address
- dwLaunchAddr = ToPhysicalAddr(dwLaunchAddr);
- EdbgOutputDebugString("rn::: Physical Launch Address: 0x%Xhrn",dwLaunchAddr);
- Launch(dwLaunchAddr);
- // never returned
- SPIN_FOREVER;
- }
- /*
- @func BOOL | OEMReadData | Generically read download data (abstracts actual transport read call).
- @rdesc TRUE = Success, FALSE = Failure.
- @comm
- @xref
- */
- BOOL OEMReadData (DWORD cbData, LPBYTE pbData)
- {
- if ( g_bUSBDownload == FALSE )
- {
- return EbootEtherReadData(cbData, pbData);
- }
- else
- {
- return UbootReadData(cbData, pbData);
- }
- }
- /*
- @func void | OEMShowProgress | Displays download progress for the user.
- @rdesc N/A.
- @comm
- @xref
- */
- void OEMShowProgress (DWORD dwPacketNum)
- {
- }
- #define BACKSPACE 8
- #define IPADDR_MAX 15
- // Read IP from command line
- static BOOL ReadIPLine (char *pbuf, DWORD dwTimeout)
- {
- DWORD dwCurrSec = OEMEthGetSecs ();
- char ch;
- int nLen = 0;
- while (OEMEthGetSecs () - dwCurrSec < dwTimeout) {
- ch = (CHAR)OEMReadDebugByte();
- switch (ch) {
- case OEM_DEBUG_COM_ERROR:
- case OEM_DEBUG_READ_NODATA:
- // no data or error, keep reading
- break;
- case BACKSPACE:
- nLen --;
- OEMWriteDebugByte (ch);
- break;
- case 'r':
- case 'n':
- OEMWriteDebugByte ('n');
- pbuf[nLen] = 0;
- return TRUE;
- default:
- if ((ch == '.' || (ch >= '0' && ch <= '9')) && (nLen < IPADDR_MAX)) {
- pbuf[nLen ++] = ch;
- OEMWriteDebugByte (ch);
- }
- }
- }
- return FALSE; // timeout
- }
- // get users IP / SubnetMask
- // return TRUE is changes made to either, else FALSE.
- static BOOL GetUserIPAddr (EDBG_ADDR *pMyAddr, DWORD *pdwSubnetMask)
- {
- char szbuf[IPADDR_MAX+1];
- uchar changes = 0;
- memset(szbuf, 0, sizeof(szbuf));
- EdbgOutputDebugString ("rnEnter IP address, or CR for default (%s): ", inet_ntoa(pMyAddr->dwIP));
- ReadIPLine (szbuf, INFINITE);
- if (szbuf[0]) {
- pMyAddr->dwIP = inet_addr(szbuf);
- changes++;
- memset(szbuf, 0, sizeof(szbuf));
- }
- EdbgOutputDebugString ("rnEnter Subnet Masks, or CR for default (%s): ", inet_ntoa(*pdwSubnetMask));
- ReadIPLine (szbuf, INFINITE);
- if (szbuf[0]) {
- *pdwSubnetMask = inet_addr (szbuf);
- changes++;
- }
- EdbgOutputDebugString ( "rnUsing IP Address %s, subnet mask %srn",
- inet_ntoa (pMyAddr->dwIP), inet_ntoa (*pdwSubnetMask));
- return (changes ? TRUE : FALSE);
- }
- static ULONG mystrtoul(PUCHAR pStr, UCHAR nBase)
- {
- UCHAR nPos=0;
- BYTE c;
- ULONG nVal = 0;
- UCHAR nCnt=0;
- ULONG n=0;
- // 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));
- c = (*(pStr + strlen(pStr) - 1 - nPos));
- if (c >= '0' && c <= '9')
- c -= '0';
- else if (c >= 'a' && c <= 'f')
- {
- c -= 'a';
- c = (0xa + c);
- }
- for (nCnt = 0, n = 1 ; nCnt < nPos ; nCnt++)
- {
- n *= nBase;
- }
- nVal += (n * c);
- }
- return(nVal);
- }
- // since the startup code is in OAL and it branch to main, we'll just
- // implement a pseudo 'main' instead of changing the startup code
- void main (void)
- {
- BootloaderMain ();
- SPIN_FOREVER;
- }
- VOID SC_WriteDebugLED(WORD wIndex, DWORD dwPattern)
- {
- OEMWriteDebugLED(wIndex,dwPattern);
- }
- /*
- @func void | SetDelay | Accepts an autoboot delay value from user input.
- @rdesc N/A.
- @comm
- @xref
- */
- static void SetDelay()
- {
- CHAR szCount[16];
- USHORT cwNumChars = 0;
- USHORT InChar = 0;
- EdbgOutputDebugString("rnEnter maximum number of seconds to delay [1-255]: ");
- while(!((InChar == 0x0d) || (InChar == 0x0a)))
- {
- InChar = OEMReadDebugByte();
- if (InChar != OEM_DEBUG_COM_ERROR && InChar != OEM_DEBUG_READ_NODATA)
- {
- // If it's a number or a period, add it to the string.
- //
- if ((InChar >= '0' && InChar <= '9'))
- {
- if (cwNumChars < 16)
- {
- szCount[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)
- {
- szCount[cwNumChars] = ' ';
- g_pBootCfg->BootDelay = atoi(szCount);
- if (g_pBootCfg->BootDelay > 255)
- {
- g_pBootCfg->BootDelay = 255;
- }
- else if (g_pBootCfg->BootDelay < 1)
- {
- g_pBootCfg->BootDelay = 1;
- }
- }
- }
- static void CvtMAC(USHORT MacAddr[3], char *pszDottedD )
- {
- DWORD cBytes;
- char *pszLastNum;
- int atoi (const char *s);
- int i=0;
- BYTE *p = (BYTE *)MacAddr;
- // Replace the dots with NULL terminators
- pszLastNum = pszDottedD;
- for(cBytes = 0 ; cBytes < 6 ; cBytes++)
- {
- while(*pszDottedD != '.' && *pszDottedD != ' ')
- {
- pszDottedD++;
- }
- if (pszDottedD == ' ' && cBytes != 5)
- {
- // zero out the rest of MAC address
- while(i++ < 6)
- {
- *p++ = 0;
- }
- break;
- }
- *pszDottedD = ' ';
- *p++ = (BYTE)(mystrtoul(pszLastNum, 16) & 0xFF);
- i++;
- pszLastNum = ++pszDottedD;
- }
- }
- static void SetCS8900MACAddress()
- {
- CHAR szDottedD[24];
- USHORT cwNumChars = 0;
- USHORT InChar = 0;
- memset(szDottedD, '0', 24);
- EdbgOutputDebugString ( "rnEnter new MAC address in hexadecimal (hh.hh.hh.hh.hh.hh): ");
- while(!((InChar == 0x0d) || (InChar == 0x0a)))
- {
- InChar = OEMReadDebugByte();
- // InChar = tolower(InChar);
- if (InChar != OEM_DEBUG_COM_ERROR && InChar != OEM_DEBUG_READ_NODATA)
- {
- // If it's a hex number or a period, add it to the string.
- //
- if (InChar == '.' || (InChar >= '0' && InChar <= '9') || (InChar >= 'a' && InChar <= 'f'))
- {
- if (cwNumChars < 17)
- {
- szDottedD[cwNumChars++] = (char)InChar;
- OEMWriteDebugByte((BYTE)InChar);
- }
- }
- else if (InChar == 8) // If it's a backspace, back up.
- {
- if (cwNumChars > 0)
- {
- cwNumChars--;
- OEMWriteDebugByte((BYTE)InChar);
- }
- }
- }
- }
- EdbgOutputDebugString ( "rn");
- // If it's a carriage return with an empty string, don't change anything.
- //
- if (cwNumChars)
- {
- szDottedD[cwNumChars] = ' ';
- CvtMAC(g_pBootCfg->EdbgAddr.wMAC, szDottedD);
- EdbgOutputDebugString("INFO: MAC address set to: %x:%x:%x:%x:%x:%xrn",
- g_pBootCfg->EdbgAddr.wMAC[0] & 0x00FF, g_pBootCfg->EdbgAddr.wMAC[0] >> 8,
- g_pBootCfg->EdbgAddr.wMAC[1] & 0x00FF, g_pBootCfg->EdbgAddr.wMAC[1] >> 8,
- g_pBootCfg->EdbgAddr.wMAC[2] & 0x00FF, g_pBootCfg->EdbgAddr.wMAC[2] >> 8);
- }
- else
- {
- EdbgOutputDebugString("WARNING: SetCS8900MACAddress: Invalid MAC address.rn");
- }
- }