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

📄 blcommon.c

📁 Windows CE 6.0 BSP for VOIP sample phone. Intel PXA270 platform.
💻 C
📖 第 1 页 / 共 4 页
字号:
                    HALT (BLERR_MAGIC);
                    return (FALSE);   
                }

                // Continue with download of next file
                // +1 to account for the manifest
                g_downloadFilesRemaining = (BYTE)(g_DownloadManifest.dwNumRegions + 1);
                continue;

#ifdef SECURE_BOOTLOADER
            case BL_IMAGE_TYPE_BIN:
                KITLOutputDebugString("\r\n**\r\n");
                KITLOutputDebugString("** ERROR: This boot loader does not support unsigned .bin images.\r\n");
                KITLOutputDebugString("**        Image must be signed with a recognized private key.\r\n");
                KITLOutputDebugString("**\r\n");
                HALT (BLERR_SIGNATURE);
                return (FALSE);

            case BL_IMAGE_TYPE_SIGNED_BIN:
                rval &= DownloadSignedBin( pdwImageStart, pdwImageLength, pdwLaunchAddr );
                break;

            case BL_IMAGE_TYPE_SIGNED_NB0:
                rval &= DownloadSignedNB0( pdwImageStart, pdwImageLength, pdwLaunchAddr );
                break;

#else // not SECURE_BOOTLOADER

            case BL_IMAGE_TYPE_BIN:
                rval &= DownloadBin( pdwImageStart, pdwImageLength, pdwLaunchAddr );
                break;

            case BL_IMAGE_TYPE_SIGNED_BIN:
                KITLOutputDebugString("\r\n**\r\n");
                KITLOutputDebugString("** ERROR: This boot loader does not support signed .bin images.\r\n");
                KITLOutputDebugString("**\r\n");
                HALT (BLERR_SIGNATURE);
                return (FALSE);

            case BL_IMAGE_TYPE_SIGNED_NB0:
                KITLOutputDebugString("\r\n**\r\n");
                KITLOutputDebugString("** ERROR: This boot loader does not support signed .nb0 images.\r\n");
                KITLOutputDebugString("**\r\n");
                HALT (BLERR_SIGNATURE);
                return (FALSE);
#endif // SECURE_BOOTLOADER

            case BL_IMAGE_TYPE_MULTIXIP:
                KITLOutputDebugString("\r\n**\r\n");
                KITLOutputDebugString("** ERROR: The X000FF packet is an old-style multi-bin download manifest and it's no longer supported.\r\n");
                KITLOutputDebugString("** Please update your Platform Builder installation in you want to download multiple files.\r\n");
                KITLOutputDebugString("**\r\n");
                HALT (BLERR_MAGIC);
                return (FALSE);

            case BL_IMAGE_TYPE_UNKNOWN:
#ifdef SECURE_BOOTLOADER
                KITLOutputDebugString("\r\n**\r\n");
                KITLOutputDebugString("** ERROR: Unrecognized image type (possibly unsigned .nb0).\r\n");
                KITLOutputDebugString("**        This boot loader does not support unsigned images.\r\n");
                KITLOutputDebugString("**        Image must be signed with a recognized private key.\r\n");
                KITLOutputDebugString("**\r\n");
                HALT (BLERR_MAGIC);
                return (FALSE);
#else
                // Assume files without a "type" header (e.g. raw data) are unsigned .nb0
                rval &= DownloadNB0( pdwImageStart, pdwImageLength, pdwLaunchAddr );
                break;
#endif                

            default:
                // should never get here
                return (FALSE);
                
        }
    }
    while (--g_downloadFilesRemaining);

    ComputeChecksum();
    rval &= WriteImageToFlash();

    return rval;
}


#ifdef SECURE_BOOTLOADER
static BOOL InitSecureBootLoader()
{
    // Initialize public keys for signature validation
    g_keyData.rgpbPublicKeys  = g_rgpbPublicKeys;       // pointer to array of public keys        
    g_keyData.rgdwKeyLengths  = g_rgdwKeyLengths;       // pointer to array of public key lengths 
    g_keyData.wNumPublicKeys  = g_wNumPublicKeys;       // number of public keys in rgpbPublicKeys
    g_keyData.wMinSearchIndex = 0;                      // starting array index of search         
    g_keyData.wMaxSearchIndex = g_wNumPublicKeys - 1;   // ending array index of search           

    KITLOutputDebugString("Secure Boot Loader includes %d public keys\r\n",
        g_keyData.wNumPublicKeys);
        
    return TRUE;
}
#endif


#ifdef SECURE_BOOTLOADER
static BOOL DownloadSignedBin (LPDWORD pdwImageStart, LPDWORD pdwImageLength, LPDWORD pdwLaunchAddr)
{
    RegionInfo *pCurDownloadFile;
    BOOL        fIsFlash = FALSE;
    LPBYTE      lpDest = NULL;
    DWORD       dwImageStart, dwImageLength;
    DWORD       dwSignedDataLength, dwSigLength;
    BYTE        bFlags;
    DWORD       dwRecNum = 0;
    DWORD       dwRecAddr, dwRecLen, dwRecChk;
    DWORD       dwPacketNum = 1;
    DWORD       dwChunksRemaining = 0;
    DWORD       dwChunkOffset = 0;
    HRESULT     hr;
    PACKETDATA  packetData;

    g_bBINDownload = TRUE;


    if (!OEMReadData (sizeof (DWORD), (LPBYTE) &dwImageStart)   ||
        !OEMReadData (sizeof (DWORD), (LPBYTE) &dwImageLength))
    {
        KITLOutputDebugString ("Unable to read image start/length\r\n");
        HALT (BLERR_MAGIC);
        return (FALSE);
    }


    // If Platform Builder didn't provide a manifest (i.e., we're
    // only downloading a single .bin file), manufacture a manifest so we
    // can notify the OEM.
    //
    if (!g_DownloadManifest.dwNumRegions)
    {
        g_DownloadManifest.dwNumRegions             = 1;
        g_DownloadManifest.Region[0].dwRegionStart  = dwImageStart;
        g_DownloadManifest.Region[0].dwRegionLength = dwImageLength;
    }

    // Provide the download manifest to the OEM.
    //
    if (!g_fOEMNotified && g_pOEMMultiBINNotify)
    {
        g_pOEMMultiBINNotify((PDownloadManifest)&g_DownloadManifest);
        g_fOEMNotified = TRUE;
    }


    // Locate the current download manifest entry (current download file).
    //
    pCurDownloadFile = &g_DownloadManifest.Region[g_DownloadManifest.dwNumRegions - g_downloadFilesRemaining];

    // give the OEM a chance to verify memory
    if (g_pOEMVerifyMemory && !g_pOEMVerifyMemory (pCurDownloadFile->dwRegionStart, pCurDownloadFile->dwRegionLength))
    {
        KITLOutputDebugString ("!OEMVERIFYMEMORY: Invalid image\r\n");
        HALT (BLERR_OEMVERIFY);
        return (FALSE);
    }

#ifdef DEBUG
    // Clearing memory ensures no garbage between sparse .bin records, so that 
    // our post-download checksum will be accurate.
    memset( (LPVOID) OEMMapMemAddr(pCurDownloadFile->dwRegionStart, pCurDownloadFile->dwRegionStart),
                0, pCurDownloadFile->dwRegionLength );
#endif

    // Check for flash image. Start erasing if it is.
    // This is risky iff:
    //      We're downloading the bootloader
    //      OEM has implemented OEMStartEraseFlash()/OEMContinueEraseFlash()
    //      Download fails (e.g. image has been tampered with)
    //
    // In this scenario only, the device will be unbootable and require
    // JTAG recovery.
    //
    // The OEM should implement the flash functions to skip erase if the image
    // is a bootloader (i.e. defer erase until OEMFinishEraseFlash()). 
    // That prevents bricking the device.  
    //
    // It's safe to erase flash and/or flush RAM to flash when download the OS.
    // In fact this improves download speed, and lets you download images
    // much larger than available RAM.
    if ((fIsFlash = OEMIsFlashAddr (pCurDownloadFile->dwRegionStart)) 
        && !OEMStartEraseFlash (pCurDownloadFile->dwRegionStart, pCurDownloadFile->dwRegionLength))
    {
        KITLOutputDebugString ("Invalid flash address/length\r\n");
        HALT (BLERR_FLASHADDR);
        return (FALSE);
    }

    //------------------------------------------------------------------------
    //  Signed files are prefixed with a 16-byte random seed, which
    //  is included in the hash.
    //------------------------------------------------------------------------
    if (!OEMReadData (RANDOM_SEED_LENGTH, (LPBYTE) &packetData.bRandomSeed))
    {
        KITLOutputDebugString ("ERROR: Failed to read random seed at start of signed .bin file\r\n");
        HALT (BLERR_MAGIC);
        return (FALSE);
    }


    //------------------------------------------------------------------------
    //  Download signed packets (.bin records or record chunks)
    //------------------------------------------------------------------------

    while ( OEMReadData (sizeof (DWORD), (LPBYTE) &dwSignedDataLength) &&
            OEMReadData (sizeof (DWORD), (LPBYTE) &dwSigLength)        &&
            OEMReadData (sizeof (BYTE),  (LPBYTE) &bFlags) )
    {
#ifdef DEBUG
        KITLOutputDebugString("\r\n------------------------------------------------------------------------------\r\n");
        KITLOutputDebugString(" <> Packet [ %d ] dwSignedDataLength = 0x%x, dwSigLen = 0x%x, bFlags = 0x%x\r\n", 
            dwPacketNum, dwSignedDataLength, dwSigLength, bFlags);
#endif

        // Check if what we just read was a chunk header instead of a
        // signed packet header.
        //
        // If a .bin record is larger than the <packet size> parameter to 
        // ImageHash.exe, it will be broken into multiple chunks.
        //
        // This theoretically allows download of .bin records that are larger
        // than the bootloader's available RAM.  However BLCommon doesn't 
        // implement that.  The OEM can do it by creatively using 
        // OEMMapMemAddr() and OEMContinueEraseFlash() to periodically flush 
        // the RAM buffer to flash.

        if (bFlags & SBL_FLAG_CHUNK_HEADER)
        {
            // It's a chunk header; we must reinterpret the data we just read:
            //
            //  field 0: ignore             (always zero for a chunk header)
            //  field 1: dwChunksRemaining  (multiple chunks = one .bin record)
            //  field 2: bFlags             (no change)
            dwChunksRemaining = dwSigLength;
            dwChunkOffset     = 0;
#ifdef DEBUG
            KITLOutputDebugString(" <> Record chunk (dwChunksRemaining = %d)\r\n", dwChunksRemaining);
#endif             
            
            // Read the signed packet header
            if ( !(OEMReadData (sizeof (DWORD), (LPBYTE) &dwSignedDataLength) &&
                   OEMReadData (sizeof (DWORD), (LPBYTE) &dwSigLength)        &&
                   OEMReadData (sizeof (BYTE),  (LPBYTE) &bFlags)))
            {
                KITLOutputDebugString ("ERROR: Failed to read signed packet header %d, ABORT!\r\n", dwPacketNum);
                HALT (BLERR_CORRUPTED_DATA);
                return (FALSE);
            }
#ifdef DEBUG
            KITLOutputDebugString(" <> Packet [ %d ] dwSignedDataLength = 0x%x, dwSigLen = 0x%x, bFlags = 0x%x\r\n", 
                dwPacketNum, dwSignedDataLength, dwSigLength, bFlags);
#endif            
        }


        // Read the .bin record header
        if ( !(OEMReadData (sizeof (DWORD), (LPBYTE) &dwRecAddr) &&
               OEMReadData (sizeof (DWORD), (LPBYTE) &dwRecLen)  &&
               OEMReadData (sizeof (DWORD), (LPBYTE) &dwRecChk)) )
        {
            KITLOutputDebugString ("ERROR: Failed to read .bin record header %d, ABORT!\r\n", dwPacketNum);
            HALT (BLERR_CORRUPTED_DATA);
            return (FALSE);
        }
#ifdef DEBUG
        KITLOutputDebugString(" <> Record [ %d ] dwRecAddr = 0x%x, dwRecLen = 0x%x, dwRecChk = 0x%x\r\n", 
            dwRecNum, dwRecAddr, dwRecLen, dwRecChk);
#endif

        if (bFlags & SBL_FLAG_END_FILE)
        {
            // last packet always has unused signature block, read it!
            ASSERT(dwSignedDataLength == 0);
            ASSERT(dwSigLength <= sizeof(g_rgpbSignature));
            OEMReadData(dwSigLength, (LPBYTE) &g_rgpbSignature);
            KITLOutputDebugString("Reached last record of signed .bin file\r\n");
            break;
        }

        // map the record address (FLASH data is cached, for example)
        // add offset if this is a record chunk
        lpDest = OEMMapMemAddr (pCurDownloadFile->dwRegionStart, dwRecAddr + dwChunkOffset);

        // read record (or record chunk)
        if (!OEMReadData (dwSignedDataLength, lpDest))
        {
            KITLOutputDebugString ("ERROR: Data packet %d corrupted, ABORT!\r\n", dwPacketNum);
            HALT (BLERR_CORRUPTED_DATA);
            return (FALSE);
        }
#ifdef DEBUG
        else
        {
            KITLOutputDebugString ("Read 0x%x bytes into cache: 0x%x (final address: 0x%x)\r\n", 
                dwSignedDataLength,
                lpDest,
                dwRecAddr + dwChunkOffset);   
                
            DumpMem( lpDest, 64 );                
        }
#endif
        
        
        // Check for last chunk in a fragmented .bin record
        if (0 != dwChunksRemaining) 
        {
            if (--dwChunksRemaining > 0) 
            {
                dwChunkOffset += dwSignedDataLength;
            } 
            else 
            {
                dwChunkOffset = 0;  
            }
#ifdef DEBUG
            KITLOutputDebugString("dwChunksRemaining = %d, offset = 0x%x\r\n", 
                dwChunksRemaining, dwChunkOffset);
#endif            
        }
        

        if (0 == dwChunksRemaining) 
        {
            LPBYTE cacheAddress = OEMMapMemAddr (pCurDownloadFile->dwRegionStart, dwRecAddr);
            
            // The packet signature makes this redundant, but we check anyway.
            if (!VerifyChecksum (dwRecLen, cacheAddress, dwRecChk))
            {
                HALT (BLERR_CHECKSUM);
                return (FALSE);
            }

            dwRecNum++; 
        }

        // Look for ROMHDR to compute ROM offset.  NOTE: romimage guarantees that the record containing
        // the TOC signature and pointer will always come before the record that contains the ROMHDR contents.
        //
        if (dwRecLen == sizeof(ROMHDR) && (*(LPDWORD) OEMMapMemAddr(pCurDownloadFile->dwRegionStart, pCurDownloadFile->dwRegionStart + ROM_SIGNATURE_OFFSET) == ROM_SIGNATURE))
        {
            DWORD dwTempOffset = (dwRecAddr - *(LPDWORD)OEMMapMemAddr(pCurDownloadFile->dwRegionStart, pCurDownloadFile->dwRegionStart + ROM_SIGNATURE_OFFSET + sizeof(ULONG)));
            ROMHDR *pROMHdr = (ROMHDR *)lpDest;

            // Check to make sure this record really contains the ROMHDR.
            //
            if ((pROMHdr->physfirst == (pCurDownloadFile->dwRegionStart - dwTempOffset)) &&
                (pROMHdr->physlast  == (pCurDownloadFile->dwRegionStart - dwTempOffset + pCurDownloadFile->dwRegionLength)) &&
                (DWORD)(HIWORD(pROMHdr->dllfirst << 16) <= pROMHdr->dlllast) &&
                (DWORD)(LOWORD(pROMHdr->dllfirst << 16) <= pROMHdr->dlllast))
            {
                g_dwROMOffset = dwTempOffset;
                KITLOutputDebugString("rom_offset=0x%x.\r\n", g_dwROMOffset); 
            }
        }

        // read packet signature
        ASSERT(dwSigLength <= sizeof(g_rgpbSignature));
        if (!OEMReadData (dwSigLength, (LPBYTE) &g_rgpbSignature))
        {
            KITLOutputDebugString ("ERROR: Failed to read signature for packet %d, ABORT!\r\n", dwPacketNum);
            HALT (BLERR_SIGNATURE);
            return (FALSE);
        }
    
        //------------------------------------------------------------------------
        //  Validate signature for this record or chunk
        //------------------------------------------------------------------------

        packetData.pbData       = lpDest;               // data to verify               
        packetData.dwDataLength = dwSignedDataLength;   // length of data in bytes              
        packetData.pbSig        = g_rgpbSignature;      // signature to verify               
        packetData.dwSigLength  = dwSigLength;          // length of signature in bytes                
        packetData.dwRecAddress = dwRecAddr;            // record address              
        packetData.dwRecLength  = dwRecLen;             // record length   
        packetData.dwRecCheck   = dwRecChk;             // record checksum  
        packetData.dwSequenceNumber = dwPacketNum;      // packet sequence number           

⌨️ 快捷键说明

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