diff -r 000000000000 -r 83f4b4db085c toolsandutils/e32tools/w32repro/w32repro.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/toolsandutils/e32tools/w32repro/w32repro.cpp Tue Feb 02 01:39:43 2010 +0200 @@ -0,0 +1,428 @@ +// Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of the License "Eclipse Public License v1.0" +// which accompanies this distribution, and is available +// at the URL "http://www.eclipse.org/legal/epl-v10.html". +// +// Initial Contributors: +// Nokia Corporation - initial contribution. +// +// Contributors: +// +// Description: +// Based on PREPRO.CPP and ROMBUILD.CPP +// +// + +#define WIN32_LEAN_AND_MEAN +#pragma warning( disable : 4201 ) // nonstandard extension used : nameless struct/union +#include +#include + +#include +#include +#include +#include "h_utl.h" +#include "h_ver.h" + +// need to pretend we've done e32image.h, to avoid clashes with winnt.h +#define __E32IMAGE_H__ +struct E32ImageFile + { + }; +class CBytePair; +#include "r_rom.h" + +#define READ_BUFFER_SIZE 0x1000 // allows for exuberant T_REPRO without delays in it +#define WRITE_BUFFER_SIZE 0x1000 + +TRomLoad TheRomHeader; +TUint ImageDataSize=0; +TUint FileSize=0; +TText PortNumber='1'; +TUint BaudRate=115200; +TBool Kick=EFalse; +TBool UseHex=EFalse; +TBool Verbose=EFalse; +TBool RawImage=EFalse; +TText* BootstrapName=NULL; + +const TUint KReproWrapperSize = 0x100; // REPRO protocol assumes a wrapper size of 256 bytes + +HANDLE comPort; +TUint32 BytesWritten; + +TText *processCommandLine(int argc, char *argv[]) +// +// Process the command line arguments, printing a helpful message if none are supplied +// + { + + char HelpText[] = + "* Syntax: W32REPRO [options] filename[.bin]\n" + "* \n" + "* Option: -P port number, defaults to COM1,\n" + "* Option: -K kick the other end, to force another repro attempt\n" + "* Option: -B baud rate, minimum 9600, defaults to 115200\n" + "* Option: -RAW raw image with no header\n" + "* Option: -BOOT bootstrap with transmitted at 9600 baud\n" + "* Option: -HEX use base 16 (for use with ReproC)\n" + "* Option: -V display raw protocol messages\n" + "* \n" + "* All messages from W32REPRO begin with '*', every thing else comes from the\n" + "* machine being reprogrammed.\n"; + + TText *filename=NULL; + if (argc == 1) + { + cout << HelpText; + return NULL; + } + for (int i=1; i=9600) + { + BaudRate=rate; + } + else + { + cout << "**** Invalid baud rate: " << argv[i] << "\n*\n"; + cout << HelpText; + return NULL; + } + } + else if (argv[i][1] == '?') + { + cout << HelpText; + return NULL; + } + else + { + cout << "**** Unrecognised argument " << argv[i] << "\n*\n"; + cout << HelpText; + return NULL; + } + } + else // Must be the image filename + filename=(TText *)argv[i]; + } + if (filename==NULL) + { + cout << "**** Missing image filename\n*\n"; + cout << HelpText; + } + return filename; + } + +TInt openComPort() +// +// Open the com port and configure it +// + { + char port[5]="COM1"; + port[3]=PortNumber; + comPort=CreateFile(port,GENERIC_READ+GENERIC_WRITE,0,0,OPEN_EXISTING,0,NULL); + if (comPort==INVALID_HANDLE_VALUE) + return Print(EError,"* Cannot open %s\n",port); + + DCB settings; + if (!GetCommState(comPort,&settings)) + return Print(EError,"* Cannot read settings for %s\n",port); + + if (!SetupComm(comPort,READ_BUFFER_SIZE,WRITE_BUFFER_SIZE)) + return Print(EError,"* Cannot set buffer sizes for %s\n",port); + + settings.fBinary=TRUE; + settings.fParity=FALSE; + settings.fAbortOnError=TRUE; // overrides EV_ERR + settings.BaudRate=BaudRate; + settings.ByteSize=8; + settings.Parity=NOPARITY; + settings.StopBits=ONESTOPBIT; + settings.fRtsControl=RTS_CONTROL_ENABLE; + settings.fDtrControl=DTR_CONTROL_ENABLE; + settings.fOutxCtsFlow=FALSE; + settings.fOutxDsrFlow=FALSE; + settings.fDsrSensitivity=FALSE; + settings.fOutX=FALSE; // no XON/XOFF for transmission + settings.fInX=FALSE; // no XON/XOFF for reception + settings.fNull=FALSE; // don't discard null bytes + + settings.EvtChar='\001'; // REPRO command separator + + if (!SetCommState(comPort,&settings)) + return Print(EError,"* Cannot configure %s\n",port); + + if (!SetCommMask(comPort,EV_RXFLAG+EV_ERR)) + return Print(EError,"* Cannot set CommMask for %s\n",port); + + COMMTIMEOUTS timeouts = { + //20,0,0, // allow up to 20 milliseconds between characters, i.e. buffer them properly + MAXDWORD,0,0, // return immediately + 0,0 // no write timeouts + }; + if (!SetCommTimeouts(comPort,&timeouts)) + return Print(EError,"* Cannot set timeouts for %s\n",port); + + if (!SetThreadPriority(GetCurrentThread(),THREAD_PRIORITY_HIGHEST)) + Print(EError,"* Failed to raise priority of this thread err=%d\n",GetLastError()); + if (!SetPriorityClass(GetCurrentProcess(),HIGH_PRIORITY_CLASS)) + Print(EError,"* Failed to raise priority of this process err=%d\n",GetLastError()); + + Print(EScreen,"* Using %s at %d baud\n\n",port,BaudRate); + return KErrNone; + } + +BOOL WriteToComPort(char* data, DWORD length, char* comment) + { + if (Verbose) + { + if (comment==NULL) + Print(EScreen, "* TX=%*s\n", length, data); + else + Print(EScreen, "* TX <%d bytes of %s>\n", length, comment); + } + return WriteFile(comPort, data, length, &BytesWritten, NULL); + } + +TInt Bootstrap9600() + { + DCB settings; + if (!GetCommState(comPort,&settings)) + return Print(EError,"* Cannot read COM settings\n"); + + settings.BaudRate=9600; + if (!SetCommState(comPort,&settings)) + return Print(EError,"* Cannot reconfigure to 9600 baud\n"); + + FILE* bootstrapFile=fopen((const char*)BootstrapName,"rb"); + if (bootstrapFile==NULL) + return Print(EError,"* Cannot open bootstrap file %s for input (errno=%d)\n",BootstrapName,errno); + + Print(EScreen,"* Sending bootstrap %s at 9600 baud\n",BootstrapName,BaudRate); + + char bootdata[WRITE_BUFFER_SIZE]; + TUint32 imageBytes=0; + + while (!feof(bootstrapFile)) + { + imageBytes=fread(bootdata,1,WRITE_BUFFER_SIZE,bootstrapFile); + if (imageBytes==0 && feof(bootstrapFile)) + break; + if (imageBytes!=WRITE_BUFFER_SIZE && ferror(bootstrapFile)) + { + return Print(ESevereError,"* Read only %d bytes of bootstrap err=%d\n",imageBytes,ferror(bootstrapFile)); + } + if (!WriteToComPort(bootdata,imageBytes,"bootstrap data")) + return Print(ESevereError,"* Wrote only %d of %d bytes of bootstrap err=%d\n", + BytesWritten,imageBytes,GetLastError()); + } + fclose(bootstrapFile); + + settings.BaudRate=BaudRate; + if (!SetCommState(comPort,&settings)) + return Print(EError,"* Cannot reconfigure to %d baud\n",BaudRate); + + Print(EScreen,"* Bootstrap downloaded\n\n"); + + return KErrNone; + } + +TInt main(int argc, char *argv[]) + { + TInt err=KErrNone; + + Print(EScreen,"\n* W32REPRO - Win32 version of PREPRO"); + Print(EScreen," V%02d.%02d (Build %03d)\n",MajorVersion,MinorVersion,Build); + Print(EScreen,"* %s",Copyright); + + TText *imageFileName = processCommandLine(argc, argv); + if (imageFileName==NULL) + return KErrGeneral; + + FILE* romFile=fopen((const char*)imageFileName,"rb"); + if (romFile==NULL) + return Print(EError,"* Cannot open ROM Image file %s for input (errno=%d)\n",imageFileName,errno); + + if (RawImage) + TheRomHeader.wrapSize=0; + else + { + if (fread(&TheRomHeader,sizeof(TheRomHeader),1,romFile)!=1) + return Print(EError,"* Cannot read ROM Image header\n"); + if (TheRomHeader.wrapSize!=KRomWrapperSize) + return Print(EError,"* Incorrect ROM header - wrong wrapper size\n"); + } + if (fseek(romFile,0,SEEK_END)!=0) + return Print(EError,"* Cannot seek in ROM Image file\n"); + FileSize=ftell(romFile); + ImageDataSize=FileSize-TheRomHeader.wrapSize; + + Print(EAlways,"\n* ROM Image %s - 0x%06x bytes\n",imageFileName,ImageDataSize); + + err=openComPort(); + if (err!=KErrNone) + return err; + + if (BootstrapName != NULL) + { + err=Bootstrap9600(); + if (err!=KErrNone) + return err; + } + + char romdata[WRITE_BUFFER_SIZE]; + if (Kick) + { + memset(romdata,'!',64); // string of non-numeric characters, won't harm old REPRO + WriteToComPort(romdata,64,NULL); + } + // + // Wait around for REPRO on the other end to send us commands + // + char command[READ_BUFFER_SIZE+1]; + char* cp=command; + TInt length=READ_BUFFER_SIZE; + TUint expectedOffset=0; + TInt done=0; + while (!done) + { + TUint32 bytesRead=0,imageBytes=0,offset=0; + + TUint32 event; + if (!WaitCommEvent(comPort,&event,NULL)) + { + if (GetLastError()!=ERROR_OPERATION_ABORTED) + Print(EAlways,"\n* Unexpected WaitCommEvent failure %d event %x\n",GetLastError(),event); + TUint32 commError; + if (!ClearCommError(comPort,&commError,NULL)) + { + Print(ESevereError,"\n* Failed to clear CommError - give up now!\n"); + return KErrGeneral; + } + if (commError!=CE_OVERRUN) + Print(EAlways,"\n* Unexpected comms error %x\n",commError); + } + if (!ReadFile(comPort,cp,length,&bytesRead,NULL)) + { + if (GetLastError()!=ERROR_OPERATION_ABORTED) + Print(EAlways,"\n* Unexpected ReadFile failure %d bytes %d\n",GetLastError(),bytesRead); + } + if (bytesRead==0) + continue; + + char* next; + char* end = cp+bytesRead; + *end='\0'; // stick a terminator on the end, just in case + + for (cp=(char*)command; (next=(char*)memchr(cp,'\001',end-cp))!=NULL ;cp=next+1) + { + *next='\0'; // drop the terminator + if (Verbose) + Print(EScreen, " * RX=%s\n", cp); + switch (cp[0]) + { + case 'D': // disconnect after successful REPRO + Print(EScreen,"* Disconnect\n"); + done=1; + break; + case 'M': // print message + Print(EScreen,"%s",cp+1); + break; + case 'P': // panic + Print(ESevereError,"%s",cp+1); + break; + case 'R': // request for data from the image at specified address + if (end-next>1) + break; // must be the last command in the buffer + offset=strtoul(cp+1,NULL,UseHex?16:10)-KReproWrapperSize; // REPRO assumes wrapSize=256 + if ((offset&4095)!=0) + { + Print(ESevereError,"* Image offset %x not a multiple of 4k (%s)\n", offset,cp); + break; + } + if (offset>expectedOffset) + { + Print(ESevereError,"* Image offset %x should have been %x\n", offset,expectedOffset); + break; + } + Print(EScreen,"%x \r",offset); // in case we lost the message + expectedOffset=offset+WRITE_BUFFER_SIZE; // what we expect next time + offset+=TheRomHeader.wrapSize; // offset into the file + if (fseek(romFile,offset,SEEK_SET)!=0) + { + Print(ESevereError,"* Can't seek to file offset %x", offset); + break; + } + + memset(romdata,0xff,WRITE_BUFFER_SIZE); + imageBytes=fread(romdata,1,WRITE_BUFFER_SIZE,romFile); + if (imageBytes!=WRITE_BUFFER_SIZE && offset+imageBytes!=FileSize) + { + Print(ESevereError,"* Read only %d bytes of image data err=%d\n",imageBytes,ferror(romFile)); + break; + } + if (!WriteToComPort(romdata,WRITE_BUFFER_SIZE,"image data")) + Print(ESevereError,"* Wrote only %d bytes of image data err=%x\n",BytesWritten,GetLastError()); + break; + case 'S': // request for the size of the image + if (end-next>1) + break; // must be the last command in the buffer + if (next-cp==1) + { + sprintf((char*)romdata,"%010d\n",ImageDataSize+KReproWrapperSize); + if (!WriteToComPort(romdata,strlen(romdata),NULL) + || BytesWritten!=strlen(romdata)) + Print(ESevereError,"* Failed to write file size\n"); + expectedOffset=0; // because we are starting again + break; + } + // otherwise fall through + default: + Print(EAlways,"\n* Unrecognised command >%s<\n", cp); + } + } + if (cp