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

📄 blcommon.c

📁 Windows CE 6.0 BSP for VOIP sample phone. Intel PXA270 platform.
💻 C
📖 第 1 页 / 共 4 页
字号:
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this sample source code is subject to the terms of the Microsoft
// license agreement under which you licensed this sample source code. If
// you did not accept the terms of the license agreement, you are not
// authorized to use this sample source code. For the terms of the license,
// please see the license agreement between you and Microsoft or, if applicable,
// see the LICENSE.RTF on your install media or the root of your tools installation.
// THE SAMPLE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES.
//
/*++
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:  
    blcommon.c
    
Abstract:  
    Bootloader common main module. This file contains the C BootloaderMain
    function for the boot loader.    NOTE: The firmware "entry" point (the real
    entry point) is _StartUp 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: 

    PACKET: a signed blob of data.  Contains ONE of the following:
        array of bytes from a raw .nb0 image
        one .bin record
        one .bin record chunk

    RECORD: a .bin record created by romimage.  

    CHUNK:  a fragment of a .bin record.  Chunks are created if a record is
            larger than the PACKET size.

--*/
#include <windows.h>
#include <halether.h>
#include <blcommon.h>

#ifdef SECURE_BOOTLOADER
#include <sbl.h>

// One or more public keys for validation of images.
// Provided by the platform's boot loader at link time.
extern const BYTE  *g_rgpbPublicKeys[];
extern const DWORD  g_rgdwKeyLengths[];
extern const WORD   g_wNumPublicKeys;

// Buffer to hold packet signature (output of hash algorithm).
// SHA-1 produces a 160-bit hash (20 bytes) but some algorithms use 128 bytes.
#define MAX_HASH_LENGTH 128
static BYTE          g_rgpbSignature[MAX_HASH_LENGTH];
static PUBLICKEYDATA g_keyData;
#endif // SECURE_BOOTLOADER


// Global buffer to contain the 7-byte image header.
// Unsigned .nb0 files don't have a header, so the data
// read into this buffer must be copied back into the 
// destination memory after probing for image type.
#define BL_HDRSIG_SIZE 7
static BYTE g_hdr[BL_HDRSIG_SIZE];

// Only provide download manifest to the OAL once per session
static BOOL g_fOEMNotified = FALSE;


#define SPIN_FOREVER        while (1)

ROMHDR * volatile const pTOC = (ROMHDR *)-1;     // Gets replaced by RomLoader with real address
static DownloadManifest g_DownloadManifest;
static BOOLEAN g_bBINDownload = TRUE;
static BYTE g_downloadFilesRemaining = 1;


static BOOL KernelRelocate    (ROMHDR *const pTOC);
static BOOL DownloadImage     (LPDWORD pdwImageStart, LPDWORD pdwImageLength, LPDWORD pdwLaunchAddr);
static BOOL IsKernelRegion    (DWORD   dwRegionStart, DWORD   dwRegionLength);

#ifdef SECURE_BOOTLOADER
static BOOL InitSecureBootLoader();
static BOOL DownloadSignedBin (LPDWORD pdwImageStart, LPDWORD pdwImageLength, LPDWORD pdwLaunchAddr);
static BOOL DownloadSignedNB0 (LPDWORD pdwImageStart, LPDWORD pdwImageLength, LPDWORD pdwLaunchAddr);
static VOID PrintPacketData   (PACKETDATA packetData);
#else
static BOOL DownloadBin       (LPDWORD pdwImageStart, LPDWORD pdwImageLength, LPDWORD pdwLaunchAddr);
static BOOL DownloadNB0       (LPDWORD pdwImageStart, LPDWORD pdwImageLength, LPDWORD pdwLaunchAddr);
#endif

static BOOL GetImageType      ();
static BOOL CheckImageManifest();
static BOOL WriteImageToFlash ();

static VOID DumpMem (PBYTE Ptr, ULONG Len);
static VOID ComputeChecksum();

#define CURRENT_VERSION_MAJOR       1
#define CURRENT_VERSION_MINOR       4

#ifdef SECURE_BOOTLOADER

// List of public keys that may be used to verify images.
// Provided at link time by the platform.
extern PUBLICKEYDATA KeyData;

const unsigned char NKSignon[] = {
    "\nMicrosoft Windows CE Secure Bootloader Common Library Version %d.%d Built "
    __DATE__ " " __TIME__ "\r\n"
};

#else

const unsigned char NKSignon[] = {
    "\nMicrosoft Windows CE Bootloader Common Library Version %d.%d Built "
    __DATE__ " " __TIME__ "\r\n"
};

#endif // SECURE_BOOTLOADER


DWORD g_dwROMOffset;

PFN_OEMVERIFYMEMORY     g_pOEMVerifyMemory;
PFN_OEMREPORTERROR      g_pOEMReportError;
PFN_OEMCHECKSIGNATURE   g_pOEMCheckSignature;
PFN_OEMMULTIBINNOTIFY   g_pOEMMultiBINNotify;


static void HALT (DWORD dwReason)
{
    if (g_pOEMReportError)
    {
        g_pOEMReportError (dwReason, 0);
    }
    SPIN_FOREVER;
}


void BootloaderMain (void)
{
    DWORD dwAction;   
    DWORD dwpToc = 0;
    DWORD dwImageStart = 0, dwImageLength = 0, dwLaunchAddr = 0;
    BOOL bDownloaded = FALSE;

    // relocate globals to RAM
    if (!KernelRelocate (pTOC))
    {
        // spin forever
        HALT (BLERR_KERNELRELOCATE);
    }

    // (1) Init debug support. We can use OEMWriteDebugString afterward.
    if (!OEMDebugInit ())
    {
        // spin forever
        HALT (BLERR_DBGINIT);
    }

    // output banner
    KITLOutputDebugString (NKSignon, CURRENT_VERSION_MAJOR, CURRENT_VERSION_MINOR);

    // (3) initialize platform (clock, drivers, transports, etc)
    if (!OEMPlatformInit ())
    {
        // spin forever
        HALT (BLERR_PLATINIT);
    }

    // system ready, preparing for download
    KITLOutputDebugString ("System ready!\r\nPreparing for download...\r\n");

    // (4) call OEM specific pre-download function
    switch (dwAction = OEMPreDownload ())
    {
    case BL_DOWNLOAD:
        // (5) download image
        if (!DownloadImage (&dwImageStart, &dwImageLength, &dwLaunchAddr))
        {
            // error already reported in DownloadImage
            SPIN_FOREVER;
        }
        bDownloaded = TRUE;

        // Check for pTOC signature ("CECE") here, after image in place
        if (*(LPDWORD) OEMMapMemAddr (dwImageStart, dwImageStart + ROM_SIGNATURE_OFFSET) == ROM_SIGNATURE)
        {
            dwpToc = *(LPDWORD) OEMMapMemAddr (dwImageStart, dwImageStart + ROM_SIGNATURE_OFFSET + sizeof(ULONG));
            // need to map the content again since the pointer is going to be in a fixup address
            dwpToc = (DWORD) OEMMapMemAddr (dwImageStart, dwpToc + g_dwROMOffset);

            KITLOutputDebugString ("ROMHDR at Address %Xh\r\n", dwImageStart + ROM_SIGNATURE_OFFSET + sizeof (DWORD)); // right after signature
        }

        // fall through
    case BL_JUMP:
        // Before jumping to the image, optionally check the image signature.
        // NOTE: if we haven't downloaded the image by now, we assume that it'll be loaded from local storage in OEMLaunch (or it
        // already resides in RAM from an earlier download), and in this case, the image start address might be 0.  This means 
        // that the image signature routine will need to find the image in storage or in RAM to validate it.  Since the OEM"s 
        // OEMLaunch function will need to do this anyways, we trust that it's within their abilities to do it here.
        //
        if (g_bBINDownload && g_pOEMCheckSignature)
        {
            if (!g_pOEMCheckSignature(dwImageStart, g_dwROMOffset, dwLaunchAddr, bDownloaded))
                HALT(BLERR_CAT_SIGNATURE);
        }
        // (5) final call to launch the image. never returned
        OEMLaunch (dwImageStart, dwImageLength, dwLaunchAddr, (const ROMHDR *)dwpToc);
        // should never return
        // fall through
    default:
        // ERROR! spin forever
        HALT (BLERR_INVALIDCMD);
    }
}


//
// KernelRelocate: move global variables to RAM
//
static BOOL KernelRelocate (ROMHDR *const pTOC)
{
    ULONG loop;
    COPYentry *cptr;
    if (pTOC == (ROMHDR *const) -1)
    {
        return (FALSE); // spin forever!
    }
    // This is where the data sections become valid... don't read globals until after this
    for (loop = 0; loop < pTOC->ulCopyEntries; loop++)
    {
        cptr = (COPYentry *)(pTOC->ulCopyOffset + loop*sizeof(COPYentry));
        if (cptr->ulCopyLen)
            memcpy((LPVOID)cptr->ulDest,(LPVOID)cptr->ulSource,cptr->ulCopyLen);
        if (cptr->ulCopyLen != cptr->ulDestLen)
            memset((LPVOID)(cptr->ulDest+cptr->ulCopyLen),0,cptr->ulDestLen-cptr->ulCopyLen);
    }
    return (TRUE);
}

static BOOL VerifyChecksum (DWORD cbRecord, LPBYTE pbRecord, DWORD dwChksum)
{
    // Check the CRC
    DWORD dwCRC = 0;
    DWORD i;
    for (i = 0; i < cbRecord; i++)
        dwCRC += *pbRecord ++;

    if (dwCRC != dwChksum)
        KITLOutputDebugString ("ERROR: Checksum failure (expected=0x%x  computed=0x%x)\r\n", dwChksum, dwCRC);

    return (dwCRC == dwChksum);
}


static BL_IMAGE_TYPE GetImageType()
{
    BL_IMAGE_TYPE rval = BL_IMAGE_TYPE_UNKNOWN;

    // read the 7 byte "magic number"
    //
    if (!OEMReadData (BL_HDRSIG_SIZE, g_hdr))
    {
        KITLOutputDebugString ("\r\nERROR: Unable to read image signature.\r\n");
        rval =  BL_IMAGE_TYPE_NOT_FOUND;
    }

    
    // The N000FF packet indicates a manifest, which is constructed by Platform 
    // Builder when we're downloading multiple .bin files or an .nb0 file.
    //
    if (!memcmp (g_hdr, "N000FF\x0A", BL_HDRSIG_SIZE))
    {
        KITLOutputDebugString("\r\nBL_IMAGE_TYPE_MANIFEST\r\n\r\n");
        rval =  BL_IMAGE_TYPE_MANIFEST;
    }
    else if (!memcmp (g_hdr, "X000FF\x0A", BL_HDRSIG_SIZE))
    {
        KITLOutputDebugString("\r\nBL_IMAGE_TYPE_MULTIXIP\r\n\r\n");
        rval =  BL_IMAGE_TYPE_MULTIXIP;
    }
    else if (!memcmp (g_hdr, "B000FF\x0A", BL_HDRSIG_SIZE))
    {
        KITLOutputDebugString("\r\nBL_IMAGE_TYPE_BIN\r\n\r\n");
        rval =  BL_IMAGE_TYPE_BIN;
    }
    else if (!memcmp (g_hdr, "S000FF\x0A", BL_HDRSIG_SIZE))
    {
        KITLOutputDebugString("\r\nBL_IMAGE_TYPE_SIGNED_BIN\r\n\r\n");
        rval =  BL_IMAGE_TYPE_SIGNED_BIN;
    }
    else if (!memcmp (g_hdr, "R000FF\x0A", BL_HDRSIG_SIZE))
    {
        KITLOutputDebugString("\r\nBL_IMAGE_TYPE_SIGNED_NB0\r\n\r\n");
        rval =  BL_IMAGE_TYPE_SIGNED_NB0;
    }
    else
    {
        KITLOutputDebugString("\r\nBL_IMAGE_TYPE_UNKNOWN\r\n\r\n");
        rval =  BL_IMAGE_TYPE_UNKNOWN;
    }

    return rval;  
}


static BOOL CheckImageManifest()
{
    DWORD dwRecChk;

    // read the packet checksum.
    //
    if (!OEMReadData (sizeof (DWORD), (LPBYTE) &dwRecChk))
    {
        KITLOutputDebugString("\r\nERROR: Unable to read download manifest checksum.\r\n");
        HALT (BLERR_MAGIC);
        return FALSE;
    }

    // read region descriptions (start address and length).
    //
    if (!OEMReadData (sizeof (DWORD), (LPBYTE) &g_DownloadManifest.dwNumRegions) ||
        !OEMReadData ((g_DownloadManifest.dwNumRegions * sizeof(RegionInfo)), (LPBYTE) &g_DownloadManifest.Region[0]))
    {
        KITLOutputDebugString("\r\nERROR: Unable to read download manifest information.\r\n");
        HALT (BLERR_MAGIC);
        return FALSE;
    }

    // verify the packet checksum.
    //
    if (!VerifyChecksum((g_DownloadManifest.dwNumRegions * sizeof(RegionInfo)), (LPBYTE) &g_DownloadManifest.Region[0], dwRecChk))
    {
        KITLOutputDebugString ("\r\nERROR: Download manifest packet failed checksum verification.\r\n");
        HALT (BLERR_CHECKSUM);
        return FALSE;
    }

    return TRUE;
}


static BOOL DownloadImage (LPDWORD pdwImageStart, LPDWORD pdwImageLength, LPDWORD pdwLaunchAddr)
{
    BOOL        rval = TRUE;
    DWORD       dwImageType;

    *pdwImageStart = *pdwImageLength = *pdwLaunchAddr = 0;

#ifdef SECURE_BOOTLOADER
    InitSecureBootLoader();
#endif


    //
    // Download each region (multiple can be sent)
    //
    do
    {
        dwImageType = GetImageType();
        
        switch(dwImageType) 
        {
            case BL_IMAGE_TYPE_MANIFEST:
                // Platform Builder sends a manifest to indicate the following 
                // data consists of multiple .bin files /OR/ one .nb0 file.
                if (!CheckImageManifest()) {

⌨️ 快捷键说明

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