📄 parallel.c
字号:
/*++
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.
Copyright (c) 1995, 1996, 1997, 1998 Microsoft Corporation
Module Name:
parallel.c
Abstract:
This contains parallel bootloader support
Functions:
Notes:
--*/
#define BOOT_LOADER
#include "..\kernel\hal\mdppfs.c"
#include <pehdr.h>
#include <romldr.h>
#include <halether.h>
#include "p2.h"
#include "p2debug.h"
#include "loader.h"
#include "ethdown.h"
#define DL_SUCCESS 0 // successful download
#define DL_PARALLEL_ERROR 1 // error on parallel port
#define DL_FLASH_ERROR 2 // error on flash
#define DL_CHECKSUM_ERROR 3 // checksum error
#define DL_TIMEOUT 4 // inactivity timeout
//
// Global defines and declarations
//
const unsigned char BootHeader[] = {
0xAA, // header = 4 bytes
0x55,
0x55,
0xAA,
0x00, // opcode = 2 bytes (0 = BOOT)
0x00,
};
#define BOOT_HEADER_SIZE (sizeof(BootHeader) / sizeof(BootHeader[0]))
const unsigned char BootTail[] = {
0x5A, // trail = 4 bytes
0xA5,
0x0A,
0x1A
};
#define BOOT_TAIL_SIZE (sizeof(BootTail) / sizeof(BootTail[0]))
const unsigned char BootPacket[] = {
0xAA, // header = 4 bytes
0x55,
0x55,
0xAA,
0x00, // opcode = 2 bytes (0 = BOOT)
0x00,
0x05, // length = 2 bytes
0x00,
0xFA, // checksum = 1 byte
0x5A, // trail = 4 bytes
0xA5,
0x0A,
0x1A
};
#define BOOT_PACKET_SIZE (sizeof(BootPacket) / sizeof(BootPacket[0]))
const unsigned char SyncBytes[] = {
'0',
'0',
'0',
'F',
'F'
};
#define SIZE_OF_SYNC_BYTES 7
extern DWORD dwPhysStart; // image physical starting address
extern DWORD dwPhysLen; // image physical length
extern DWORD dwOffset;
extern DWORD dwLaunchAddr;
extern DWORD *dwFlashCache;
extern LPDWORD pdwRecStart, pdwRecNext; // saved record address, length and checksum pointers
// Flash routines
UINT16 IsFlash( DWORD dwPhysStart, DWORD dwPhysLen );
UINT16 FlashErase(FlashCommands FlashCommand, DWORD dwPhysStart, DWORD dwPhysLen, char **ppszErrorMsg );
UINT16 FlashWrite( DWORD dwPhysStart, DWORD dwPhysLen, char **ppszErrorMsg );
DWORD OEMEthGetSecs( void );
//***************************************************************************
// ParallelPortRead - read bytes from parallel port
//
// Syntax:
//
// int
// ParallelPortRead(
// unsigned char * pByteReceived,
// unsigned int cb
// );
//
// Arguments:
//
// pByteReceived (a0) : points to the buffer to receive data
// cb (a1) : number of bytes to read
//
//Return Value:
//
// returns the number of bytes left to read (in our case, always 0)
//***************************************************************************
int ParallelPortRead(unsigned char *pByteReceived, unsigned int cb) {
int result;
while (cb && (result=OEMParallelPortGetByte()) != -1) {
*pByteReceived++= (unsigned char)result;
cb--;
}
return cb;
}
/*++
ParallelPortWrite:
This routine has been optimized for parallel port output.
Syntax:
int
ParallelPortWrite(
unsigned char * pByteReceived,
unsigned int cb
);
Arguments:
pByteReceived (a0) : points to the buffer to send
cb (a1) : number of bytes to send
Return Value:
in v0, the number bytes left to write
--*/
//***************************************************************************
// ParallelPortWrite
//***************************************************************************
int ParallelPortWrite(const unsigned char *pByteSend, unsigned int cb) {
while (cb--)
OEMParallelPortSendByte(*pByteSend++);
return cb;
}
//***************************************************************************
// IsParallelReady - is parallel port connected and ready for transfer
//
//
//***************************************************************************
BOOL IsParallelReady(void) {
// parallel port status
DWORD dwStatus = (DWORD)PAR_BUSY_NFAULT | PAR_SELECT;
DWORD dwStart;
dwStart= OEMEthGetSecs();
// set direction to write
*(PVDWORD)(PAR_CONTROL_REG) = dwStatus;
// wait for AUTOFD
while (!((dwStatus= *(PVDWORD)(PAR_CONTROL_REG)) & PAR_AUTOFD)) {
if (OEMEthGetSecs()-dwStart > 3)
return FALSE;
}
return TRUE;
}
//***************************************************************************
// Download2Flash - download image to flash
//
//
//***************************************************************************
unsigned int Download2Flash(void) {
unsigned int Vaddr; // record starting address
unsigned int cbRecord; // record length
unsigned int checksum; // record checksu,
unsigned int result;
char *pszErrorMsg;
// record header buffer
unsigned int ParallelRecvBuffer[3];
if (FlashErase( FLASH_START_ERASE, dwPhysStart, dwPhysLen, &pszErrorMsg )) {
EdbgOutputDebugString("ERROR: FlashErase FLASH_START_ERASE PhysStart %Xh PhysLen %Xh failed\r\n",dwPhysStart,dwPhysLen);
EdbgOutputDebugString(pszErrorMsg);
return DL_FLASH_ERROR;
}
while (1) {
if (FlashErase( FLASH_CONT_ERASE, dwPhysStart, dwPhysLen, &pszErrorMsg )) {
EdbgOutputDebugString("ERROR: FlashErase FLASH_CONT_ERASE PhysStart %Xh PhysLen %Xh failed\r\n",dwPhysStart,dwPhysLen);
EdbgOutputDebugString(pszErrorMsg);
return DL_FLASH_ERROR;
}
// Read in the starting address and length in bytes
ParallelPortRead((unsigned char *)ParallelRecvBuffer, 3 * sizeof(unsigned int ));
Vaddr = ParallelRecvBuffer[0];
cbRecord = ParallelRecvBuffer[1];
checksum = ParallelRecvBuffer[2];
*pdwRecNext++= Vaddr;
*pdwRecNext++= cbRecord;
*pdwRecNext++= checksum;
if (!Vaddr && !checksum) { // if this is the last record, launch it
if (FlashWrite(dwPhysStart, dwPhysLen, &pszErrorMsg )) {
EdbgOutputDebugString("ERROR: FlashWrite PhysStart %Xh PhysLen %Xh failed\r\n",dwPhysStart,dwPhysLen);
EdbgOutputDebugString(pszErrorMsg);
return DL_FLASH_ERROR;
}
cbRecord -= dwOffset;
break;
}
// otherwise copy directly to RAM
Vaddr-=dwPhysStart;
Vaddr+=FLASH_CACHE;
if (cbRecord) {
result= ParallelPortRead((unsigned char *)Vaddr, cbRecord);
}
} // while 1
dwLaunchAddr=cbRecord;
return DL_SUCCESS;
}
//***************************************************************************
// Download2RAM - download image to RAM
//
//
//***************************************************************************
unsigned int Download2RAM(void)
{
unsigned int Vaddr; // record starting address
unsigned int cbRecord; // record length
unsigned int checksum; // record checksu,
unsigned int result;
// record header buffer
unsigned int ParallelRecvBuffer[3];
while (1) {
// Read in the starting address and length in bytes
ParallelPortRead((unsigned char *)ParallelRecvBuffer, 3 * sizeof(unsigned int ));
Vaddr = ParallelRecvBuffer[0];
cbRecord = ParallelRecvBuffer[1];
checksum = ParallelRecvBuffer[2];
*pdwRecNext++= Vaddr;
*pdwRecNext++= cbRecord;
*pdwRecNext++= checksum;
if (!Vaddr && !checksum) { // if this is the last record, launch it
cbRecord -= dwOffset;
break;
}
Vaddr -= dwOffset;
// otherwise copy directly to RAM
if (cbRecord) {
result= ParallelPortRead((unsigned char *)Vaddr, cbRecord);
// Read data into destination directly
}
} // while 1
dwLaunchAddr=cbRecord;
return DL_SUCCESS;
}
/*****************************************************************************
*
*
* @func int | DownloadImage | Down loads image from host
*
* @rdesc Returns 1 if sucessfully downloaded, 0 otherwise
*
* @parm const unsigned char * | pPathName |
* points to a ASCIIZ string for a file on the host file
* system to be downloaded. The file must be in the format
* of SRE or BIN (preprocessed SRE file).
*
* @parm unsigned int * | pStartingAddr |
* points to a buffer to receive the starting address of
* the program.
*
* @parm int | fLaunch |
* Flag indicating if the downloaded image should be
* automatically launched or not.
*
* @comm
* Initially sends a packet to host (running ppfs) to initiate a
* SRE or binary image file transfer.
*
*/
int ParallelDownloadImage(void)
{
// const unsigned char * pTemp;
unsigned char ParallelRecvBuffer[512];
unsigned int chksum;
unsigned int uiTemp;
int bootType;
unsigned len;
unsigned char * pDestByte;
int fSre=0;
int nReturn=0;
int j;
int i;
#ifndef ARM720
if (!IsParallelReady()) {
EdbgOutputDebugString("Parallel connection failed.\r\n");
return 0;
}
#endif
EdbgOutputDebugString("Ready to down load BIN file");
for (j = 0; j < 100; j++) {
EdbgOutputDebugString(".");
//
// Prepare boot packet
//
pDestByte = ParallelRecvBuffer;
for (i = 0; i < BOOT_HEADER_SIZE; i++) {
*pDestByte++ = BootHeader[i];
}
chksum = 0;
len = sizeof(unsigned int) + 5;
bootType = BOOT_TYPE;
uiTemp = len;
for (i = 0; i < 2; i++) {
*pDestByte++ = (unsigned char)(uiTemp & 0xFF);
chksum += (uiTemp & 0xFF);
uiTemp >>= 8;
}
uiTemp = bootType;
for (i = 0; i < sizeof(int); i++) {
*pDestByte++ = (unsigned char)(uiTemp & 0xFF);
chksum += (uiTemp & 0xFF);
uiTemp >>= 8;
}
*pDestByte++ = (unsigned char)((~chksum) & 0xFF);
for (i = 0; i < BOOT_TAIL_SIZE; i++) {
*pDestByte++ = BootTail[i];
}
nReturn=ParallelPortWrite(ParallelRecvBuffer,
(unsigned int)(pDestByte - ParallelRecvBuffer));
//
// The first six bytes should be "S000FF" (for SRE file) or
// "B000FF" (for files with internal binary format)
//
nReturn=ParallelPortRead(ParallelRecvBuffer, SIZE_OF_SYNC_BYTES);
if (ParallelRecvBuffer[0] == 'S') {
fSre = 1;
break;
} else if (ParallelRecvBuffer[0] == 'B') {
fSre = 0;
break;
} else {
nReturn = - 4;
continue;
}
for (i = 1; i < SIZE_OF_SYNC_BYTES; i++) {
if (ParallelRecvBuffer[i] != SyncBytes[i - 1]) {
nReturn = - 4;
goto cont;
}
}
cont:;
}
//
// display any errors returned
//
switch (nReturn) {
case - 1:
EdbgOutputDebugString("\nCan't set parallel port direction to write\nLaunching existing image...\r\n");
// LaunchExisting();
case - 2:
EdbgOutputDebugString("\nHost computer not responding\n");
goto doom;
case - 3:
EdbgOutputDebugString("\nCan't set parallel port direction to read\n");
return 0;
case - 4:
EdbgOutputDebugString("\nFail to synchonize with the host\n");
doom:
EdbgOutputDebugString("Make sure you have ppfs running on the host computer\n");
EdbgOutputDebugString("and reset the client to restart\r\nLaunching existing image...\r\n");
// LaunchExisting();
}
//
// Ok, we are synchronized with the host now
// start streaming the data records
//
// if file type is .BIN, read physical start and length
if (!fSre)
{
// get the next 8 bytes
if (ParallelPortRead(ParallelRecvBuffer, 8)==-1) {
EdbgOutputDebugString("\r\nFailed to read sync bytes.\r\nLaunching existing image...\r\n");
// LaunchExisting();
}
// get physical start and length
dwPhysStart = *((unsigned int *)ParallelRecvBuffer);
dwPhysLen = *(((unsigned int *)ParallelRecvBuffer) + 1);
EdbgOutputDebugString("\r\nImage start %Xh length %Xh. ",dwPhysStart,dwPhysLen);
dwOffset = 0;
#ifdef ARM
// translate to 8cxxxxxx for arm
switch (dwPhysStart & 0xff000000) {
case 0xc7000000:
// SA1100
dwOffset = 0x3b000000;
break;
case 0x0c000000: // RAM, ARM720/ARM920
case 0x0: // FLASH, any ARM
dwOffset = 0x80000000;
break;
default:
EdbgOutputDebugString ("Physical Start not translated: 0x%x\r\n", dwPhysStart);
}
#endif
// if image is going to flash area
// it will first be downloaded to RAM
if (IsFlash(dwPhysStart,dwPhysLen))
{
EdbgOutputDebugString("Image going to FLASH.\r\n");
pdwRecStart=pdwRecNext=(LPDWORD)(FLASH_CACHE+dwPhysLen);
nReturn= Download2Flash();
}
else
{
EdbgOutputDebugString("Image going to RAM.\r\n");
pdwRecStart=pdwRecNext=(LPDWORD)(dwPhysStart+dwPhysLen-dwOffset);
nReturn= Download2RAM();
}
switch (nReturn) {
case DL_PARALLEL_ERROR: // error on parallel port
EdbgOutputDebugString("ERROR: parallel port error. Download aborted.\r\n");
break;
case DL_FLASH_ERROR: // error on flash
EdbgOutputDebugString("ERROR: flash error. Download aborted.\r\n");
break;
case DL_CHECKSUM_ERROR: // checksum error
EdbgOutputDebugString("ERROR: checksum mismatch. Download aborted.\r\n");
break;
case DL_TIMEOUT: // inactivity timeout
EdbgOutputDebugString("ERROR: inactivity timeout. Download aborted.\r\n");
break;
}
}
return DL_SUCCESS;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -