main.c

来自「SAMSUNG S3C6410 CPU BSP for winmobile6」· C语言 代码 · 共 348 行

C
348
字号
//
// 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: OEM IPL routines for the Samsung SMDK6410 hardware platform.

Functions:

Notes:

--*/
#include <windows.h>
#include <bsp.h>
#include <pehdr.h>
#include <romldr.h>

#include <XsrTypes.h>
#include <XsrConfig.h>
#include <BML.h>
#include <OAM.h>
#include <STL.h>

ROMHDR * volatile const pTOC = (ROMHDR *)-1;


// Base address of the image flash part.
//
// NOTE: This is the base address of the NAND flash controller...
//
#define EBOOT_VIRTUAL_BASEADDR	0x80038000
#define IPL_VIRTUAL_BASEADDR		0x80138000


void Launch(UINT32 ulLaunchAddr);
void OEMInitDebugSerial(void);
void OEMWriteDebugString(unsigned short *str);


void OEMLaunchImage(UINT32 ulLaunchAddr)
{
    UINT32 ulPhysicalJump = 0;

    // The IPL is running with the MMU on - before we jump to the loaded image, we need to convert
    // the launch address to a physical address and turn off the MMU.
    //

    // Convert jump address to a physical address.
    ulPhysicalJump = OALVAtoPA((void *)ulLaunchAddr);

	RETAILMSG(1, (L"LaunchAddr=0x%x PhysicalJump=0x%x\r\n", ulLaunchAddr, ulPhysicalJump));
    // Jump...
    Launch(ulPhysicalJump);
}

// --- These are used by iplcommon (end)   ---

static BOOL
_ReadImage(UINT32 nVol, UINT32 nStartVsn, UINT32 nNumOfScts, UINT32 nSrcAddr, BMLVolSpec *pstVolSpec)
{
    UINT32      nVsnAlign;
    UINT32      nSctToRead;
    UINT8      *pSrcAddr = (UINT8*)nSrcAddr;
    INT32       nRet;

    while(nNumOfScts)
    {
        nVsnAlign = nStartVsn % pstVolSpec->nSctsPerPg;

        if (nVsnAlign != 0)
        {
            if (nNumOfScts >= (pstVolSpec->nSctsPerPg - nVsnAlign))
            {
                nSctToRead = pstVolSpec->nSctsPerPg - nVsnAlign;
            }
            else
            {
                nSctToRead = nNumOfScts;
            }
        }
        else
        {
            if (nNumOfScts >= pstVolSpec->nSctsPerPg)
            {
                nSctToRead = pstVolSpec->nSctsPerPg;
            }
            else
            {
                nSctToRead = nNumOfScts;
            }
        }

        nRet = BML_Read(nVol,                                  /* Volume Number     */
                        nStartVsn,                             /* Vsn               */
                        nSctToRead,                            /* Number of Scts    */
                        pSrcAddr,                              /* pMBuf             */
                        NULL,                                  /* pSBuf             */
                        BML_FLAG_ECC_ON | BML_FLAG_BBM_ON);    /* Operation Flag    */

        if (nRet != BML_SUCCESS)
        {
            OEMWriteDebugString(L"[NBL2:ERR]  BML_Read Erro\r\n");
            return FALSE;
        }

        nNumOfScts  -= nSctToRead;
        nStartVsn   += nSctToRead;
        pSrcAddr    += nSctToRead * XSR_SECTOR_SIZE;
    }    
    
    return TRUE;
}

void ShadowEboot()
{
	UINT32			nVol = 0;
    UINT32          nStartVsn;
    UINT32          nNumOfScts;
    UINT32          nSctsPerPg;
    XSRPartEntry    stPEntry;
    BMLVolSpec      stVolSpec;
	UINT32 ulLaunchAddr = EBOOT_VIRTUAL_BASEADDR;
	
    OEMWriteDebugString(L"++ Shadow Eboot ++\r\n");    
    
    if (BML_GetVolInfo(nVol, &stVolSpec) != BML_SUCCESS)
    {
        OEMWriteDebugString(L"BML_GetVolInfo Error\r\n");
        while(1);
    }
    
    if (BML_LoadPIEntry(nVol, PARTITION_ID_EBOOT, &stPEntry) != BML_SUCCESS)
    {
        OEMWriteDebugString(L"BML_LoadPIEntry Error!\r\n");
        while(1);
    }

    nSctsPerPg  = stVolSpec.nSctsPerPg;

    nStartVsn   = stPEntry.n1stVbn    * stVolSpec.nPgsPerBlk * nSctsPerPg;
    nNumOfScts  = stPEntry.nNumOfBlks * stVolSpec.nPgsPerBlk * nSctsPerPg;

    if(!_ReadImage(nVol, nStartVsn, nNumOfScts, ulLaunchAddr, &stVolSpec)) {
	    OEMWriteDebugString(L"In ShadowEboot,can't read image.\r\n");
	    while(1);
    }
    
    BML_Close(0);
    
    OEMWriteDebugString(L"-- Shadow Eboot --\r\n");
	OEMLaunchImage(ulLaunchAddr);
}

void ShadowIPL()
{
	UINT32			nVol = 0;
    UINT32          nStartVsn;
    UINT32          nNumOfScts;
    UINT32          nSctsPerPg;
    XSRPartEntry    stPEntry;
    BMLVolSpec      stVolSpec;
	UINT32 ulLaunchAddr = IPL_VIRTUAL_BASEADDR;
	
    OEMWriteDebugString(L"++ Shadow IPL ++\r\n");    
    
    if (BML_GetVolInfo(nVol, &stVolSpec) != BML_SUCCESS)
    {
        OEMWriteDebugString(L"BML_GetVolInfo Error\r\n");
        while(1);
    }
    
    if (BML_LoadPIEntry(nVol, PARTITION_ID_IPL, &stPEntry) != BML_SUCCESS)
    {
        OEMWriteDebugString(L"BML_LoadPIEntry Error!\r\n");
        while(1);
    }

    nSctsPerPg  = stVolSpec.nSctsPerPg;

    nStartVsn   = stPEntry.n1stVbn    * stVolSpec.nPgsPerBlk * nSctsPerPg;
    nNumOfScts  = stPEntry.nNumOfBlks * stVolSpec.nPgsPerBlk * nSctsPerPg;

    if(!_ReadImage(nVol, nStartVsn, nNumOfScts, ulLaunchAddr, &stVolSpec)) {
	    OEMWriteDebugString(L"In ShadowIPL,can't read image.\r\n");
	    while(1);
    }
    
    BML_Close(0);
    
    OEMWriteDebugString(L"-- Shadow IPL --\r\n");
	OEMLaunchImage(ulLaunchAddr);
}

static BOOLEAN SetupCopySection(ROMHDR *const pTOC)
{
    UINT32 ulLoop;
    COPYentry *pCopyEntry;

    if (pTOC == (ROMHDR *const) -1)
    {
        return(FALSE);
    }

    // This is where the data sections become valid... don't read globals until after this
    //
    for (ulLoop = 0; ulLoop < pTOC->ulCopyEntries; ulLoop++)
    {
        pCopyEntry = (COPYentry *)(pTOC->ulCopyOffset + ulLoop*sizeof(COPYentry));
        if (pCopyEntry->ulCopyLen)
        {
            memcpy((LPVOID)pCopyEntry->ulDest, (LPVOID)pCopyEntry->ulSource, pCopyEntry->ulCopyLen);
        }
        if (pCopyEntry->ulCopyLen != pCopyEntry->ulDestLen)
        {
            memset((LPVOID)(pCopyEntry->ulDest+pCopyEntry->ulCopyLen), 0, pCopyEntry->ulDestLen-pCopyEntry->ulCopyLen);
        }
    }

    return(TRUE);

}

#define FROM_BCD(n)    ((((n) >> 4) * 10) + ((n) & 0xf))

static BOOL OEMGetRealTime(LPSYSTEMTIME lpst) 
{
    volatile S3C6410_RTC_REG *s6410RTC = (S3C6410_RTC_REG *)OALPAtoVA(S3C6410_BASE_REG_PA_RTC, FALSE);

    do
    {
        lpst->wYear         = FROM_BCD(s6410RTC->BCDYEAR) + 2000 ;
        lpst->wMonth        = FROM_BCD(s6410RTC->BCDMON   & 0x1f);
        lpst->wDay          = FROM_BCD(s6410RTC->BCDDATE  & 0x3f);

        lpst->wDayOfWeek    = (s6410RTC->BCDDAY - 1);

        lpst->wHour         = FROM_BCD(s6410RTC->BCDHOUR  & 0x3f);
        lpst->wMinute       = FROM_BCD(s6410RTC->BCDMIN   & 0x7f);
        lpst->wSecond       = FROM_BCD(s6410RTC->BCDSEC   & 0x7f);
        lpst->wMilliseconds = 0;
    }
    while (!(lpst->wSecond));

    return(TRUE);
}

DWORD OEMEthGetSecs(void)
{
    SYSTEMTIME sTime;

    OEMGetRealTime(&sTime);
    return((60UL * (60UL * (24UL * (31UL * sTime.wMonth + sTime.wDay) + sTime.wHour) + sTime.wMinute)) + sTime.wSecond);
}

void main(void)
{
	UINT32 nVol = 0;
    BOOL   bLoadIPL = TRUE;

    // Set up the copy section data.
    //
    if (!SetupCopySection(pTOC))
    {
        while(1);
    }

	OEMInitDebugSerial();
    OEMWriteDebugString(L"++ ONBL2 : main ++\r\n");

	//BML_Init
    if (BML_Init() != BML_SUCCESS)
    {
	    OEMWriteDebugString(L"++ ONBL2 : main : BML_Init failed++\r\n");
        while(1);
    }
	OEMWriteDebugString(L"++ ONBL2 : main : BML_Init ok++\r\n");
	
	//BML_Open
    if (BML_Open(nVol) != BML_SUCCESS)
    {
	    OEMWriteDebugString(L"++ ONBL2 : main : BML_Open failed++\r\n");
        while(1);
    }
	OEMWriteDebugString(L"++ ONBL2 : main : BML_Open ok++\r\n");

#if 0  // use button
	{
		volatile S3C6410_GPIO_REG *pGPIOReg = (S3C6410_GPIO_REG *)OALPAtoVA(S3C6410_BASE_REG_PA_GPIO, FALSE);
		UINT32 backup_GPNCON;
		UINT32 nGPNDAT;
		UINT32 backup_GPNPUD;

		backup_GPNCON = pGPIOReg->GPNCON;
		backup_GPNPUD = pGPIOReg->GPNPUD;
		pGPIOReg->GPNCON = (backup_GPNCON & ~(0x3<<20)) | (0x0<<20);  // EINT10(GPN20) is input
		pGPIOReg->GPNPUD = (backup_GPNPUD & ~(0x3<<20)) | (0x0<<20);  // EINT10(GPN20) is input
		nGPNDAT = pGPIOReg->GPNDAT;
		pGPIOReg->GPNCON = backup_GPNCON;
		pGPIOReg->GPNPUD = backup_GPNPUD;

		OEMWriteDebugString(L"++ ONBL2 : main : Check boot mode++\r\n");

		if ((nGPNDAT & (0x1<<10)) == 0) bLoadIPL = FALSE;
	}
#elif 1  // use rtc timer.  if 0, onbl2 load ipl directly.
	{
		UINT32 nDelay;
	    UINT8  KeySelect;
	    UINT32 dwStartTime, dwCurrTime;

		RETAILMSG(1, (L"Press [SPACE] to enter EBOOT within 2 sec.\r\n"));

		nDelay = 3;
	    dwStartTime = OEMEthGetSecs();
	    dwCurrTime  = dwStartTime;
	    KeySelect   = 0;

	    while((dwCurrTime - dwStartTime) < nDelay)
	    {
	        KeySelect = OEMReadDebugByte();
	        if ((KeySelect == 0x20) || (KeySelect == 0x0d))
	        {
	        	bLoadIPL = FALSE;
	            break;
	        }

	        dwCurrTime = OEMEthGetSecs();
	    }
    }
#endif

	if (bLoadIPL) ShadowIPL();
	else ShadowEboot();
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?