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

📄 imgboot.c

📁 老外的一个开源项目
💻 C
📖 第 1 页 / 共 2 页
字号:
// Copyright (c) David Vescovi.  All rights reserved.
// Part of Project DrumStix
// Windows Embedded Developers Interest Group (WE-DIG) community project.
// http://www.we-dig.org
// Copyright (c) Microsoft Corporation.  All rights reserved.
// Portions Copyright (c) SanDisk Corporation.  All rights reserved.
// Portions Copyright (c) BSQUARE Corporation.  All rights reserved.
//------------------------------------------------------------------------------
//
//  File:  imgboot.c
//
//  Storage device based image boot routines for the bootloader.
//
//------------------------------------------------------------------------------

#include <windows.h>
#include <oal_memory.h>
#include <ceddk.h>
#include "bsp.h"
#include "loader.h"
#include "mmcapi.h"
#include "mmcfldr.h"
#include "fat.h"


MMCF_DEVICE  BootDisk;


#include <pshpack1.h>		// byte packing
typedef struct _BINFILE_HEADER {
    UCHAR       SyncBytes[7];
    ULONG       ImageAddress;
    ULONG       ImageLength;
} BINFILE_HEADER, *PBINFILE_HEADER;

typedef struct _BINFILE_RECORD_HEADER {
    ULONG       LoadAddress;
    ULONG       Length;
    ULONG       CheckSum;
} BINFILE_RECORD_HEADER, *PBINFILE_RECORD_HEADER;
#include <poppack.h>

ULONG ReadSectors(IN ULONG Sector, IN ULONG Count,OUT PUCHAR SectorBuf);

static
void msWait(UINT32 msVal) 
{
    OALStall(msVal*1000);
}


static
void transposeString(PUCHAR pucIn, PUCHAR pucOut, ULONG size)
{	// swap odd and even bytes
	while(size > 1)
	{
		*pucOut++ = *(pucIn+1);
		*pucOut++ = *(pucIn);
		pucIn++;
		pucIn++;
		size--;
		size--;
	}
	if(size == 1)
	{ // pad
		*pucOut++ = 0x20;
		*pucOut++ = *pucIn;
	}
}


static
ULONG CFWaitForDisk( IN UCHAR WaitMask )
{
ULONG i;
UCHAR Status;
ATA_CMDREG *CmdReg = (ATA_CMDREG *)BootDisk.CmdBase;

//
// Poll the status register 100000 times with a 10 us retry interval
// before giving up.
//
	for (i = 0; i < 100000; i++)
	{
		OALStall(10);
		Status = CmdReg->Status;
		if (!(Status & ATA_STATUS_BUSY) && (Status & WaitMask))
		{
			return Status;
		}
	}

    DEBUGMSG(1, (L"CFWaitForDisk timeout.\r\n"));
	DEBUGMSG(1, (L"    Status = 0x%.2x\r\n",Status));
	DEBUGMSG(1, (L"    Error = 0x%.2x\r\n",CmdReg->Error));
	DEBUGMSG(1, (L"    SecCount = 0x%.2x\r\n",CmdReg->SecCount));
	DEBUGMSG(1, (L"    SecNum = 0x%.2x\r\n",CmdReg->SecNum));
	DEBUGMSG(1, (L"    CylinderLo = 0x%.2x\r\n",CmdReg->CylinderLo));
	DEBUGMSG(1, (L"    CylinderHi = 0x%.2x\r\n",CmdReg->CylinderHi));
	DEBUGMSG(1, (L"    Head = 0x%.2x\r\n",CmdReg->Head));

	return Status | 0x80000000;
}


ULONG CFIdend( void )
{
PUSHORT pIDData;
UCHAR ucMsg[128];
ULONG i;
IDENTIFY_DATA cfIdentifyData;
ULONG ulWaitStatus;
ATA_CMDREG *CmdReg = (ATA_CMDREG *)BootDisk.CmdBase;

// Identify the drive by writing 0xEC to the command register
// and 0xA0 to the drive/head register.
	*((PUSHORT)&CmdReg->Head) = 0xECA0;
	ulWaitStatus = CFWaitForDisk(ATA_STATUS_DATA_REQ);
	if((ulWaitStatus & 0x80000000) != 0)
	{
		DEBUGMSG(1, (L"CFIdent: Status reg is stuck busy or has no data: 0x%8.8X\r\n", ulWaitStatus));
		return(ulWaitStatus);
	}
    if((ulWaitStatus & 0x00000001) != 0)
    {
		DEBUGMSG(1, (L"CFIdent: error 0x%8.8X\r\n", ulWaitStatus));
		return(ulWaitStatus);
    }
    pIDData = (PUSHORT)&cfIdentifyData;
    for(i=0; i < (sizeof(IDENTIFY_DATA)/2); i++)
    {
		*(pIDData++) = *((PUSHORT)&CmdReg->Data);
		OALStall(5);
    }

    DEBUGMSG(1,(L"i=%d\r\n",i));
    DEBUGMSG(1, (L"CFIdent: [00]ID.GeneralConfiguration        : 0x%4.4X\r\n", cfIdentifyData.GeneralConfiguration        ));
    DEBUGMSG(1, (L"CFIdent: [01]ID.NumberOfCylinders           : 0x%4.4X\r\n", cfIdentifyData.NumberOfCylinders           ));
    DEBUGMSG(1, (L"CFIdent: [02]ID.Reserved1                   : 0x%4.4X\r\n", cfIdentifyData.Reserved1                   ));
    DEBUGMSG(1, (L"CFIdent: [03]ID.NumberOfHeads               : 0x%4.4X\r\n", cfIdentifyData.NumberOfHeads               ));
    DEBUGMSG(1, (L"CFIdent: [04]ID.UnformattedBytesPerTrack    : 0x%4.4X\r\n", cfIdentifyData.UnformattedBytesPerTrack    ));
    DEBUGMSG(1, (L"CFIdent: [05]ID.UnformattedBytesPerSector   : 0x%4.4X\r\n", cfIdentifyData.UnformattedBytesPerSector   ));
    DEBUGMSG(1, (L"CFIdent: [06]ID.SectorsPerTrack             : 0x%4.4X\r\n", cfIdentifyData.SectorsPerTrack             ));
    DEBUGMSG(1, (L"CFIdent: [07]ID.VendorUnique1[0]            : 0x%4.4X\r\n", cfIdentifyData.VendorUnique1[0]            ));
    DEBUGMSG(1, (L"CFIdent: [08]ID.VendorUnique1[1]            : 0x%4.4X\r\n", cfIdentifyData.VendorUnique1[1]            ));
    DEBUGMSG(1, (L"CFIdent: [09]ID.VendorUnique1[2]            : 0x%4.4X\r\n", cfIdentifyData.VendorUnique1[2]            ));
	transposeString((PUCHAR)cfIdentifyData.SerialNumber, ucMsg, sizeof(cfIdentifyData.SerialNumber));
	DEBUGMSG(1, (L"CFIdent: [10]ID.SerialNumber[10]            : %20.20S\r\n", ucMsg                                      ));
    DEBUGMSG(1, (L"CFIdent: [20]ID.BufferType                  : 0x%4.4X\r\n", cfIdentifyData.BufferType                  ));
    DEBUGMSG(1, (L"CFIdent: [21]ID.BufferSectorSize            : 0x%4.4X\r\n", cfIdentifyData.BufferSectorSize            ));
    DEBUGMSG(1, (L"CFIdent: [22]ID.NumberOfEccBytes            : 0x%4.4X\r\n", cfIdentifyData.NumberOfEccBytes            ));
	transposeString((PUCHAR)cfIdentifyData.FirmwareRevision, ucMsg, sizeof(cfIdentifyData.FirmwareRevision));
	DEBUGMSG(1, (L"CFIdent: [23]ID.FirmwareRevision[4]         : %8.8S\r\n",ucMsg                                         ));
	transposeString((PUCHAR)cfIdentifyData.ModelNumber, ucMsg, sizeof(cfIdentifyData.ModelNumber));
	DEBUGMSG(1, (L"CFIdent: [27]ID.ModelNumber[20]             : %40.40S\r\n", ucMsg                                      ));
    DEBUGMSG(1, (L"CFIdent: [47]ID.MaximumBlockTransfer        : 0x%2.2X\r\n", cfIdentifyData.MaximumBlockTransfer        ));
    DEBUGMSG(1, (L"CFIdent: [47]ID.VendorUnique2               : 0x%2.2X\r\n", cfIdentifyData.VendorUnique2               ));
    DEBUGMSG(1, (L"CFIdent: [48]ID.DoubleWordIo                : 0x%4.4X\r\n", cfIdentifyData.DoubleWordIo                ));
    DEBUGMSG(1, (L"CFIdent: [49]ID.Capabilities                : 0x%4.4X\r\n", cfIdentifyData.Capabilities                ));
    DEBUGMSG(1, (L"CFIdent: [50]ID.Reserved2                   : 0x%4.4X\r\n", cfIdentifyData.Reserved2                   ));
    DEBUGMSG(1, (L"CFIdent: [51]ID.VendorUnique3               : 0x%2.2X\r\n", cfIdentifyData.VendorUnique3               ));
    DEBUGMSG(1, (L"CFIdent: [51]ID.PioCycleTimingMode          : 0x%2.2X\r\n", cfIdentifyData.PioCycleTimingMode          ));
    DEBUGMSG(1, (L"CFIdent: [52]ID.VendorUnique4               : 0x%2.2X\r\n", cfIdentifyData.VendorUnique4               ));
    DEBUGMSG(1, (L"CFIdent: [52]ID.DmaCycleTimingMode          : 0x%2.2X\r\n", cfIdentifyData.DmaCycleTimingMode          ));
    DEBUGMSG(1, (L"CFIdent: [53]ID.TranslationFieldsValid      : 0x%4.4X\r\n", cfIdentifyData.TranslationFieldsValid      ));
    DEBUGMSG(1, (L"CFIdent: [54]ID.NumberOfCurrentCylinders    : 0x%4.4X\r\n", cfIdentifyData.NumberOfCurrentCylinders    ));
    DEBUGMSG(1, (L"CFIdent: [55]ID.NumberOfCurrentHeads        : 0x%4.4X\r\n", cfIdentifyData.NumberOfCurrentHeads        ));
    DEBUGMSG(1, (L"CFIdent: [56]ID.CurrentSectorsPerTrack      : 0x%4.4X\r\n", cfIdentifyData.CurrentSectorsPerTrack      ));
    DEBUGMSG(1, (L"CFIdent: [57]ID.CurrentSectorCapacity       : 0x%8.8X\r\n", cfIdentifyData.CurrentSectorCapacity       ));
    DEBUGMSG(1, (L"CFIdent: [59]ID.MultiSectorCount            : 0x%2.2X\r\n", cfIdentifyData.MultiSectorCount            ));
    DEBUGMSG(1, (L"CFIdent: [59]ID.MultiSectorSettingValid     : 0x%2.2X\r\n", cfIdentifyData.MultiSectorSettingValid     ));
    DEBUGMSG(1, (L"CFIdent: [60]ID.TotalUserAddressableSectors : 0x%8.8X\r\n", cfIdentifyData.TotalUserAddressableSectors ));
    DEBUGMSG(1, (L"CFIdent: [62]ID.SingleDmaModesSupported     : 0x%2.2X\r\n", cfIdentifyData.SingleDmaModesSupported     ));
    DEBUGMSG(1, (L"CFIdent: [62]ID.SingleDmaTransferActive     : 0x%2.2X\r\n", cfIdentifyData.SingleDmaTransferActive     ));
    DEBUGMSG(1, (L"CFIdent: [63]ID.MultiDmaModesSupported      : 0x%2.2X\r\n", cfIdentifyData.MultiDmaModesSupported      ));
    DEBUGMSG(1, (L"CFIdent: [63]ID.MultiDmaTransferActive      : 0x%2.2X\r\n", cfIdentifyData.MultiDmaTransferActive      ));
	return 0;
}


ULONG CFReadSectors(
	IN ULONG Sector,
	IN ULONG Count,
	OUT PUCHAR SectorBuf
	)
{
ULONG RetVal = 0;
ULONG WaitResult;
ULONG i;
UCHAR Status;
USHORT CFData;
ATA_CMDREG *CmdReg = (ATA_CMDREG *)BootDisk.CmdBase;

	if (Count == 0 || Count > 256)
	{
		return( ATA_ERROR_GENERAL );
	}

	CmdReg->SecNum = LOBYTE(Sector);
	CmdReg->CylinderLo = LOBYTE(Sector >> 8);
	CmdReg->CylinderHi = LOBYTE(Sector >> 16);
	CmdReg->Head = LOBYTE(0xE0 | (Sector>>24));
	CmdReg->SecCount = (UCHAR)(Count == 256 ? 0 : Count);
	CmdReg->Command = ATA_CMD_READ;

	WaitResult = CFWaitForDisk(ATA_STATUS_DATA_REQ);

	if (WaitResult & 0x80000000)
	{
		OALMSG(1, (L"CFReadSectors: error waiting for DRQ. 1\r\n"));
	}

	Status = (UCHAR)(WaitResult & 0xFF);
	if (Status & ATA_STATUS_ERROR) 
	{
		DEBUGMSG(1, (L"CF Command Status = 0x%B\r\n", Status));
		RetVal = CmdReg->Error;
		OALMSG(1, (L"Error During Read: 0x%B\r\n", RetVal));
	}
	else 
	{
		if (Count == 0) 
		{
			Count = 256;
		}

        while (Count--)
		{
			WaitResult = CFWaitForDisk(ATA_STATUS_DATA_REQ);

			if (WaitResult & 0x8000000)
			{
				OALMSG(1, (L"CFReadSectors: error waiting for DRQ.\r\n"));
			}

			if (Status & ATA_STATUS_ERROR)
			{
				DEBUGMSG(1, (L"CF Command Status = 0x%B\r\n", Status));
				RetVal = CmdReg->Error;
				OALMSG(1, (L"Error During Read: 0x%B\r\n", RetVal));
				break;
			}
//
// If the sector buffer is not aligned on a USHORT boundary, the
// data must be copied one byte at a time to prevent alignment
// exceptions on certain platforms.
//
			for (i=0;i<(ULONG)BootDisk.BytesPerSec/2;i+=1)
			{
				CFData = *((PUSHORT)&CmdReg->Data);
				*SectorBuf++ = LOBYTE(CFData);
				*SectorBuf++ = HIBYTE(CFData);
			}
		}
	}
	return(RetVal);
}




//******************************************************************************
//*  This routine accepts a filename from the calling program.
//*  If the named file is found on the storage device, this routine
//*  will assume that the file is in Microsoft BIN format, attempt to load
//*  the file to RAM and return the jump address.
//*
//******************************************************************************
BOOL FATReadBin(IN PUCHAR FileName,
                  OUT PULONG JumpAddress,
                  OUT PULONG pulSize,
                  OUT PULONG pulImageAddress)
{
BINFILE_HEADER BinFileHeader;
BINFILE_RECORD_HEADER BinRecordHeader;
FILEINFO fnFileInfo;
ULONG Destination;
ULONG BytesToRead;
ULONG BytesRead;
ULONG BytesProcessed;
ULONG FileSize;
LONG  CheckSum;
PUCHAR pData;
ULONG count=1;
int i=0;
int loops=0;
int retry;

ULONG StartAddress;
ULONG ImageLength;

	DEBUGMSG(1, (L"FATReadBin: Entry\r\n"));
//  ****************************************************************************
//  * The filename sent to us is a null terminated string.
//  * Attempt to open the file.
//  * 
//  ****************************************************************************
	if(!FATOpenFile(&fnFileInfo, FileName))
	{
		OALMSG(1, (L"FATReadBin: FatFileHandle == 0\r\n"));
		return FALSE;
	}

//  ****************************************************************************
//  * The file was found and opened.
//  * Determine the file size.
//  * 
//  ****************************************************************************
	OALMSG(1, (L"INFO: NK.BIN found.\r\n"));

	FileSize = FATGetFileSize(&fnFileInfo);
	DEBUGMSG(1, (L"FATReadBin: BIN file size:  %u bytes\r\n", FileSize));

	if(FileSize < sizeof(BINFILE_HEADER) + 2*sizeof(BINFILE_RECORD_HEADER))
	{
		OALMSG(1, (L"FATReadBin: BIN file size: %u bytes is too small.\r\n", FileSize));
		return FALSE;
	}

//  ****************************************************************************
//  * Read the BIN file header.
//  * Extract the image start address and length.
//  * 
//  ****************************************************************************
	DEBUGMSG(1, (L"\r\nFATReadBin: Read the BIN file header\r\n"));
	BytesToRead = sizeof(BINFILE_HEADER);
	BytesRead =FATReadFile(&fnFileInfo, (PUCHAR)&BinFileHeader, BytesToRead);
	if (BytesRead != BytesToRead)
	{
		OALMSG(1, (L"FATReadBin: Failed to read the BIN file header.\r\n"));
		return FALSE;
	}

	OALMSG(1, (L"INFO: Image Address = : %8.8X\r\n", BinFileHeader.ImageAddress));
	OALMSG(1, (L"INFO: Image Size =    : %8.8X\r\n", BinFileHeader.ImageLength));

⌨️ 快捷键说明

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