?? imgboot.c
字號:
// 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 + -