📄 iplmain.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.
//
#include <windows.h>
#include <pehdr.h>
#include <romldr.h>
#include <bootpart.h>
#include <iplcommon.h>
#include <bsp.h>
#include <fmd.h>
#include <cecompress.h>
#include <fallite.h>
#include <image_cfg.h>
// the minimum data we need from the first page of a partition
#define PARTITION_HEADER_BYTES ROM_TOC_OFFSET_OFFSET + sizeof(DWORD)
// Globals.
//
// The IPL's table of contents pointer.
extern ROMHDR * volatile const pTOC;
extern Launch(DWORD dwLaunchAddr);
// Message handler callback function pointer.
PFN_MessageHandler g_pfnMessageHandler = NULL;
// Compressed Partition flag
BOOL g_fCompressed = FALSE;
// Compression Decoder Stream
CeCompressDecodeStream g_DecodeStream = NULL;
// Compression Header
PCOMPRESSED_RAMIMAGE_HEADER g_CompressionHeader = NULL;
// buffer for reading compression data
BYTE CompressedData[RAMIMAGE_COMPRESSION_BLOCK_SIZE];
// External variable definitions.
//
UINT32 g_ulFlashBase = 0x90E00000; // Flash start and length.
UINT32 g_ulFlashLengthBytes = NAND_FLASH_SIZE - IMAGE_IPL_SIZE;
// Functions used for compression
BOOL InitDecompressor(HANDLE hPartition, DWORD dwHeaderSize);
VOID DeInitDecompressor();
LPVOID MyAlloc(LPVOID pIgnored, DWORD dwAllocSize);
VOID MyDeAlloc(LPVOID pIgnored, LPVOID pAddress);
BOOL CopyToRAM(HANDLE hPartition, DWORD dwPartitionBase);
// Local variables.
//
static UINT16 g_wSectorSize;
static void *g_pMessageTable[] =
{
TEXT("ERROR: Unable to find IPL table of contents.\0"), // IPL_ERROR_BAD_IPLTOC
TEXT("ERROR: Failed to initialize bootpart library.\0"), // IPL_ERROR_BPINIT_FAILED
TEXT("ERROR: Failed to open storage partition.\0"), // IPL_ERROR_OPENPARTITION_FAILED
TEXT("ERROR: Failed to get storage type information.\0"), // IPL_ERROR_GETSTRORAGETYPE_FAILED
TEXT("ERROR: Failed to retrieve stored image information.\0"), // IPL_ERROR_GETIMAGEINFO_FAILED
TEXT("ERROR: Failed to translate image address.\0"), // IPL_ERROR_TRANSLATEADDR_FAILED
TEXT("ERROR: Failed to read image data from storage partition.\0"), // IPL_ERROR_READDATA_FAILED
TEXT("ERROR: Failed to jump to loaded image.\0"), // IPL_ERROR_JUMP_FAILED
TEXT("INFO: Loading image ...\r\n\0"), // IPL_INFO_LOADING_IMAGE
TEXT("INFO: Jumping to image...\r\n\0") // IPL_INFO_JUMPING_IMAGE
};
/*
@func void | SpinForever | Halts execution.
@rdesc None.
@comm
@xref
*/
static void SpinForever(void)
{
while(1)
{
// Do nothing.
}
}
/*
@func void | MessageDispatch | Dispatches debug messages to the OEM message handler.
@rdesc None.
@comm
@xref
*/
static void MessageDispatch(IPL_MESSAGE_CODE MessageCode)
{
// Dispatch the message to the OEM-provided message handler (if there is one).
//
if (g_pfnMessageHandler)
{
// Make sure we don't overstep the array boundary.
//
if (MessageCode >= (sizeof(g_pMessageTable)/sizeof(g_pMessageTable[0])))
{
return;
}
// Call the OEM's messange handler routine.
//
g_pfnMessageHandler(MessageCode, g_pMessageTable[MessageCode]);
}
}
/*
@func BOOLEAN | SetupCopySection | Copies the IPL image's copy section data (initialized globals) to the correct fix-up location. Once completed, the IPLs initialized globals are valid.
@rdesc TRUE == Success and FALSE == Failure.
@comm
@xref
*/
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);
}
/*
@func BOOLEAN | ReadTOC | Locates the load image's table of contents (TOC) and reads the TOC into the caller-provided buffer.
@rdesc TRUE == Success and FALSE == Failure.
@comm
@xref
*/
static BOOLEAN ReadTOC(HANDLE hPartition, ROMHDR *pTOC)
{
// TODO: statically allocate some big sector buffer size on the stack...
BYTE SectorData[PARTITION_HEADER_BYTES];
UINT32 TOCoffset = 0;
if (hPartition == INVALID_HANDLE_VALUE || pTOC == NULL)
{
return(FALSE);
}
// Restore the file pointer to the start of the partition.
//
if (!BP_SetDataPointer(hPartition, 0))
{
return(FALSE);
}
// Read the first sector - this contains the address of the table of contents.
//
if (!BP_ReadData(hPartition, SectorData, PARTITION_HEADER_BYTES))
{
return(FALSE);
}
// Valid table of contents address signature?
//
if (*(UINT32 *)(&SectorData[ROM_SIGNATURE_OFFSET]) != ROM_SIGNATURE)
{
return(FALSE);
}
TOCoffset = (*(UINT32 *)(&SectorData[ROM_TOC_OFFSET_OFFSET]));
// Move the file pointer to the correct offset.
//
if (!BP_SetDataPointer(hPartition, TOCoffset))
{
return(FALSE);
}
// Read the table of contents.
//
if (!BP_ReadData(hPartition, (BYTE *)pTOC, sizeof(ROMHDR)))
{
return(FALSE);
}
// Restore the file pointer to the start of the partition.
//
if (!BP_SetDataPointer(hPartition, 0))
{
return(FALSE);
}
return(TRUE);
}
/*
@func BOOLEAN | GetImageInfo | Uses the image's table of contents (TOC) to locate the image start address, length, and jump address.
@rdesc TRUE == Success and FALSE == Failure.
@comm
@xref
*/
static BOOLEAN GetImageInfo(HANDLE hPartition, UINT32 *ulImageStartAddr)
{
BYTE SectorData[PARTITION_HEADER_BYTES];
PCOMPRESSED_RAMIMAGE_HEADER pCompHeader = NULL;
DWORD dwTocLoc = 0, dwTocOffset = 0, dwBytesRead = 0;
WORD wBlockSize = 0;
if (hPartition == INVALID_HANDLE_VALUE || ulImageStartAddr == NULL)
{
return(FALSE);
}
// set the pointer to the beginning of the partition
if (!BP_SetDataPointer(hPartition, 0))
{
return(FALSE);
}
// read the first page
if (!BP_ReadData(hPartition, SectorData, PARTITION_HEADER_BYTES))
{
return(FALSE);
}
// is the partition compressed?
pCompHeader = (PCOMPRESSED_RAMIMAGE_HEADER) SectorData;
if ((pCompHeader->dwSignature == RAMIMAGE_COMPRESSION_SIGNATURE) &&
(pCompHeader->dwVersion == RAMIMAGE_COMPRESSION_VERSION) &&
(pCompHeader->dwCompressedBlockSize == RAMIMAGE_COMPRESSION_BLOCK_SIZE))
{
// initialize the compressor
if (!InitDecompressor(hPartition, pCompHeader->dwHeaderSize))
{
return(FALSE);
}
// update the global "partition is compressed" flag
g_fCompressed = TRUE;
// set the data pointer to the first byte after the compressed header
if (!BP_SetDataPointer(hPartition, g_CompressionHeader->dwHeaderSize))
{
return(FALSE);
}
// the compressed size of the first block is stored in pCompHeader
wBlockSize = g_CompressionHeader->wBlockSizeTable[0];
// read the first page into our compressed data buffer
if (!BP_ReadData(hPartition, CompressedData, wBlockSize))
{
return(FALSE);
}
// if block size = max size, this block is not compressed
if (wBlockSize == RAMIMAGE_COMPRESSION_BLOCK_SIZE)
{
// just copy data over into SectorData
memcpy(SectorData, CompressedData, PARTITION_HEADER_BYTES);
}
else
{
// decompress the first page back into SectorData
dwBytesRead = CeCompressDecode(g_DecodeStream, SectorData, RAMIMAGE_COMPRESSION_BLOCK_SIZE, PARTITION_HEADER_BYTES, CompressedData, wBlockSize);
if (dwBytesRead != PARTITION_HEADER_BYTES)
{
return(FALSE);
}
}
}
// Valid table of contents address signature?
if (*(UINT32 *)(&SectorData[ROM_SIGNATURE_OFFSET]) != ROM_SIGNATURE)
{
return(FALSE);
}
// Extract the start address, length, and jump address from the table of contents.
//
dwTocLoc = *(UINT32 *)(&SectorData[ROM_TOC_POINTER_OFFSET]);
dwTocOffset= *(UINT32 *)(&SectorData[ROM_TOC_OFFSET_OFFSET]);
*ulImageStartAddr = dwTocLoc - dwTocOffset;
return(TRUE);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -