ASR_BASE
Change-Id: Icf3719cc0afe3eeb3edc7fa80a2eb5199ca9dda1
diff --git a/marvell/obm/Common/Download/ProtocolManager.c b/marvell/obm/Common/Download/ProtocolManager.c
new file mode 100644
index 0000000..fac7f0a
--- /dev/null
+++ b/marvell/obm/Common/Download/ProtocolManager.c
@@ -0,0 +1,1382 @@
+/******************************************************************************
+**
+** INTEL CONFIDENTIAL
+** Copyright 2003-2004 Intel Corporation All Rights Reserved.
+**
+** The source code contained or described herein and all documents
+** related to the source code (Material) are owned by Intel Corporation
+** or its suppliers or licensors. Title to the Material remains with
+** Intel Corporation or its suppliers and licensors. The Material contains
+** trade secrets and proprietary and confidential information of Intel
+** or its suppliers and licensors. The Material is protected by worldwide
+** copyright and trade secret laws and treaty provisions. No part of the
+** Material may be used, copied, reproduced, modified, published, uploaded,
+** posted, transmitted, distributed, or disclosed in any way without Intel's
+** prior express written permission.
+**
+** No license under any patent, copyright, trade secret or other intellectual
+** property right is granted to or conferred upon you by disclosure or
+** delivery of the Materials, either expressly, by implication, inducement,
+** estoppel or otherwise. Any license under such intellectual property rights
+** must be express and approved by Intel in writing.
+**
+** ProtocolManager.c
+******************************************************************************/
+
+/******************************************************************************
+ *
+ * (C)Copyright 2005 - 2011 Marvell. All Rights Reserved.
+ *
+ * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MARVELL.
+ * The copyright notice above does not evidence any actual or intended
+ * publication of such source code.
+ * This Module contains Proprietary Information of Marvell and should be
+ * treated as Confidential.
+ * The information in this file is provided for the exclusive use of the
+ * licensees of Marvell.
+ * Such users have the right to use, modify, and incorporate this code into
+ * products for purposes authorized by the license agreement provided they
+ * include this notice and the associated copyright notice with any such
+ * product.
+ * The information in this file is provided "AS IS" without warranty.
+
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * The boot ROM protocol is documented in the boot ROM specification. This
+ * implements the protocol over the USB or UART port. It is expected that
+ * the driver for the port has a minimal set of routines to handle receiving
+ * and responding to commands. This file will interpret the data and prepare
+ * the response data for a particular command. The driver is resonsible for
+ * sending and receiving the data over the port.
+ *
+ * Basic process:
+ * - Interrupt is received from one of the ports
+ * - The HandleRequest routine is called to get the command from the port
+ * - Based on the request type either a download request or a JTAG request
+ * is started. At this point the other ports are disabled until the
+ * request is completed.
+ *
+ *
+ ******************************************************************************/
+
+#include "ProtocolManager.h"
+#include "Errors.h"
+#include "misc.h"
+#include "Flash.h"
+#include "FM.h"
+#include "ICU.h"
+#include "tim.h"
+#include "PlatformConfig.h"
+#include "loadoffsets.h"
+#include "nand.h"
+#include "downloader.h"
+#include "TIMDownload.h"
+
+
+#define MAX_RECV_FIFO_LEN (8192)
+__attribute__((aligned(8)))UINT8 receiveBuff[MAX_RECV_FIFO_LEN];
+UCHAR *pRXbuff = receiveBuff;
+
+__attribute__((aligned(8)))UINT8 transmitBuff[MAX_RECV_FIFO_LEN];
+// Here's how to interprit the version
+// MAJOR
+// A (stepping) = 1
+// B (stepping) = 2
+// C (stepping) = 3
+// D (stepping) = 4
+// MINOR
+// This is basically the stepping number, 0=0, 1=1, 2=2 etc
+// For example:
+// A0 = 1000
+// A1 = 1001
+// B2 = 2002
+// C0 = 3000
+// C2 = 3002
+
+
+__attribute__((aligned(4))) UINT8_T preambleString[] = { 0x00, 0xD3, 0x02, 0x2B };
+UINT8_T upload_config_flash_flag = 0;
+UINT8_T upload_get_times_flag = 0;
+UINT8_T upload_times = 1;
+UINT8_T ResetUE = 0;
+UINT8_T ResetDelay = 0;
+extern UINT8_T FlashInitDone;
+
+#if NAND_CODE
+extern UINT_T NandID;
+#endif
+
+#if REPORT_DDR_INFO
+extern UINT_T swd_ddr_vendor_id, swd_ddr_size, swd_flash_id;
+#endif
+
+static ProtocolISR GProtocolISR;
+static pProtocolCmd pGProtocolCmd;
+static __attribute__((aligned(4))) ProtocolRsp GProtocolRsp;
+static ProtocolMsg GProtocolMsg;
+static UINT8_T sProtocolError = NoError;
+
+//Protocol Manager helper routines - should all be 'inline' routines
+pProtocolISR getProtocolISR(void) { return &GProtocolISR; }
+pProtocolCmd getProtocolCmd(void) { return pGProtocolCmd; }
+pProtocolCmd setProtocolCmd(void *addr) { return pGProtocolCmd = (pProtocolCmd) addr; }
+pProtocolRsp getProtocolRsp(void) { return &GProtocolRsp; }
+pProtocolMsg getProtocolMsg(void) { return &GProtocolMsg; }
+void setProtocolError(UINT8_T Error) { sProtocolError = Error; }
+UINT8_T getProtocolError(void) { return sProtocolError; }
+UCHAR * getProtoBuff() { return pRXbuff; }
+void setProtoBuff(UCHAR* pAddr) { pRXbuff = pAddr; }
+void resetProtoBuff() { pRXbuff = receiveBuff; }
+
+
+//Protocol Manager reply routines. Will call into USB API to do the actual send
+UINT_T SendResponse(UINT8_T *pAckBuff, UINT_T size)
+{
+ P_USBAPI_T pUsbApi = getProtocolISR()->plinkedUSB;
+
+ //pointer to the current USB Handle
+ pUsbApi->USB_Send((UINT *)pAckBuff, size, pUsbApi);
+
+ return NoError;
+}
+
+UINT_T SendAck(void)
+{
+ UINT_T Retval = NoError;
+ pProtocolCmd pCmd = getProtocolCmd();
+ pProtocolRsp pRsp = getProtocolRsp();
+
+ pRsp->Command = pCmd->Command;
+ pRsp->Sequence = pCmd->Sequence;
+ pRsp->CID = pCmd->CID;
+ pRsp->Status = Ack;
+ pRsp->Flags = pRsp->Flags & ~(MESSAGE_FLAG);
+ pRsp->Flags = pRsp->Flags | getProtocolMsg()->MessageFlag;
+
+ Retval = SendResponse(&pRsp->Command, pRsp->Length + 6);
+
+ return Retval;
+}
+
+UINT_T SendError(UINT_T ErrorCode){
+
+ UINT_T Retval = NoError;
+ UINT_T RspSize;
+ //UINT_T i;
+ pProtocolCmd pCmd = getProtocolCmd();
+ pProtocolRsp pRsp = getProtocolRsp();
+
+ pRsp->Command = pCmd->Command;
+ pRsp->Sequence = pCmd->Sequence;
+ pRsp->CID = pCmd->CID;
+ pRsp->Status = Nack;
+ pRsp->Flags = getProtocolMsg()->MessageFlag;
+ if(ErrorCode)
+ {
+ pRsp->Length = 4;
+ *(UINT16_T*)&pRsp->Data[0] = ErrorCode & 0x0000FFFF;
+ *(UINT16_T*)&pRsp->Data[2] = (ErrorCode & 0xFFFF0000) >> 16;
+ }
+ else
+ pRsp->Length = 0;
+
+ RspSize = ErrorCode ? 6 + pRsp->Length : 6;
+ Retval = SendResponse(&pRsp->Command, RspSize);
+
+ return Retval;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+// Functions to handle specific commands
+////////////////////////////////////////////////////////////////////////
+
+UINT_T HandleGetVersionCmd()
+{
+ UINT_T Retval= 0, i;
+ pProtocolRsp pRsp;
+
+// UINT8_T *Version = (UINT8_T *)(VERSION_OFFSET + BOOTROMBASEADDR); // legacy way to get version info...
+// Version used to come from BootROM's version info.
+// But now the BootROM's memory space is unavailable to BootLoader.
+// Furthermore, it is probably more appropriate to return the version
+// info of whichever executable is running: BootROM or BootLoader.
+ extern UINT8_T ExecutableVersionInfo[]; // defined in [TBR|BL]_startup.s
+ UINT8_T *pVersion = ExecutableVersionInfo; // new way to get version info.
+
+ pRsp = getProtocolRsp();
+
+ pRsp->Length = 12;
+ memcpy( (void *)&(pRsp->Data[0]), pVersion, 12);
+
+#if REPORT_DDR_INFO
+ pRsp->Length += 8;
+
+ for (i = 0; i < 4; i++)
+ pRsp->Data[12+i] = (swd_ddr_vendor_id >> (8 * i)) & 0xff;
+
+ for (i = 0; i < 4; i++)
+ pRsp->Data[16+i] = (swd_ddr_size >> (8 * i)) & 0xff;
+
+ pRsp->Length += 4;
+
+ for (i = 0; i < 4; i++)
+ pRsp->Data[20+i] = (swd_flash_id >> (8 * i)) & 0xff;
+#endif
+
+ Retval = SendAck();
+
+ return Retval;
+}
+
+UINT_T HandleSelectImageCmd(UINT_T imageType)
+{
+ UINT_T Retval;
+ pProtocolRsp pRsp = getProtocolRsp();
+
+ pRsp->Length = 4;
+
+ *(UINT16_T *)&pRsp->Data[0] = imageType & 0x0000FFFF;
+ *(UINT16_T *)&pRsp->Data[2] = (imageType & 0xFFFF0000) >> 16;
+
+ Retval = SendAck();
+
+ return Retval;
+}
+
+UINT_T HandleVerifyImageCmd()
+{
+ UINT_T Retval= 0;
+
+ getProtocolRsp()->Length = 0;
+
+ if(getProtocolCmd()->Data[0] == Nack)
+ getProtocolISR()->ErrorCode = UnknownImageError;
+
+ Retval = SendAck();
+ return Retval;
+
+}
+
+UINT_T HandleDataHeaderCmd()
+{
+ UINT_T RemainingLen = 0;
+ UINT_T BufferSize = 0;
+ UINT_T NextSize = 0;
+
+ pProtocolRsp pRsp = getProtocolRsp();
+ pProtocolISR pISR = getProtocolISR();
+ pProtocolCmd pCmd = getProtocolCmd();
+
+ pRsp->Length = 4;
+ RemainingLen = *(UINT32_T *)&pCmd->Data[0];
+
+ //check to make sure the data will fit
+ if(RemainingLen > pISR->MaxImageSize)
+ {
+ AddMessageError(REPORT_NOTIFICATION, DownloadImageTooBigError);
+ SendError(DownloadImageTooBigError);
+ pISR->ErrorCode = DownloadImageTooBigError;
+ return NULL;
+ }
+
+ pISR->DataLeft = RemainingLen; //DataLeft indicates how much of the total image remains
+
+ if (pCmd->Flags & FAST_DOWNLOAD)
+ {
+ pRsp->Flags = pRsp->Flags | FAST_DOWNLOAD;
+ pISR->FastDLInProgress = 1;
+ //setup next read for 2KB
+ NextSize = BufferSize = (RemainingLen > FD_BLOCK_SIZE) ? FD_BLOCK_SIZE : RemainingLen;
+ }
+ else
+ {
+ pRsp->Flags = pRsp->Flags & ~FAST_DOWNLOAD;
+ pISR->FastDLInProgress = 0;
+ //setup next read for 2KB
+ BufferSize = (RemainingLen > DATA_BLOCK_SIZE) ? DATA_BLOCK_SIZE : RemainingLen;
+ NextSize = BufferSize + COMMAND_SIZE;
+ }
+
+
+ *(UINT16_T*)&pRsp->Data[0] = BufferSize & 0x0000FFFF;
+ *(UINT16_T*)&pRsp->Data[2] = (BufferSize & 0xFFFF0000) >> 16;
+
+ SendAck();
+
+
+ return NextSize;
+}
+
+UINT_T HandleDataCmd()
+{
+ UINT_T Retval = 0;
+
+ getProtocolCmd()->Command = DownloadDataCmd;
+ getProtocolRsp()->Length = 0;
+
+ SendAck();
+ return Retval;
+}
+
+UINT_T HandleDoneCmd()
+{
+ UINT_T Retval= 0;
+ pProtocolISR pISR = getProtocolISR();
+
+ getProtocolRsp()->Length = 0;
+
+ //reset the status flags
+ pISR->PreambleReceived = FALSE;
+
+ SendAck();
+ return Retval;
+
+}
+
+UINT_T HandleMessageCmd(void){
+ UINT_T Retval= 0;
+
+#if VERBOSE_MODE
+
+ UINT_T mIndex;
+ UINT_T size;
+ UINT_T i;
+ //UINT8_T Buff[LENGTHOFMESSAGES + 6];
+ UINT8_T *Buff = transmitBuff;
+ pProtocolCmd pCmd = getProtocolCmd();
+ pProtocolMsg pMsg = getProtocolMsg();
+
+ //tool sending extra message commands to catch messages
+ //if we don't have any messages, just NACK the message and continue
+ if(pMsg->NumMessagesQueued == 0){
+ SendError(0);
+ return NoError;
+ }
+
+ //must use Buff instead of GProtocolRsp
+ Buff[0] = pCmd->Command;
+ Buff[1] = pCmd->Sequence;
+ Buff[2] = pCmd->CID;
+ Buff[3] = Ack;
+
+ mIndex = pMsg->CurrentMessageIndex;
+ size = pMsg->Lengths[mIndex];
+
+ Buff[5] = size;
+ for(i = 0; i < size; i++)
+ Buff[6+i] = pMsg->Messages[mIndex][i];
+
+ //increment the pointer to the new current message
+ pMsg->CurrentMessageIndex++;
+ pMsg->CurrentMessageIndex %= MAXNUMOFMESSAGES;
+
+ pMsg->NumMessagesQueued--;
+
+ if(pMsg->NumMessagesQueued == 0)
+ pMsg->MessageFlag = 0;
+ else
+ pMsg->MessageFlag = 1;
+
+ //mark flags (message flag message type flag )
+ Buff[4] = (pMsg->MessageFlag | (pMsg->MessageType[mIndex] << 1));
+
+ SendResponse(&Buff[0], 6+size);
+
+#else // end if VERBOSE_MODE
+
+ SendError(0);
+#endif
+ return Retval;
+}
+
+UINT_T HandleDisconnect()
+{
+ UINT start_time;
+ pProtocolISR pISR = getProtocolISR();
+
+ //if there is no linked USB Device, then there was never any protocol transaction
+ if(pISR->plinkedUSB == NULL)
+ return NoError;
+
+ //check to see if there are queued up messages.
+ if( (pISR->DisconnectReceived == TRUE) && getProtocolMsg()->MessageFlag)
+ { //clear disconnect received flag as we now need to wait for a new one
+ pISR->DisconnectReceived = FALSE;
+ //reply with a NAK to allow messages to get sent
+ SendError(0);
+ }
+
+ //give the tool a short time to get all the messages and then reply with a disconnect
+ start_time = GetOSCR0();
+ while(pISR->DisconnectReceived == FALSE)
+ {
+ //if a download is waiting, terminate it and break out of loop: wtptp tool quits on a NACK
+ if(pISR->DLWaiting == TRUE)
+ {
+ SendError(UnknownImageError);
+ break;
+ }
+
+ if(OSCR0IntervalInSec(start_time, GetOSCR0()) > PM_DISCONNET_MS)
+ break;
+ }
+
+ //lastly, reply with an ACK
+ if(pISR->DisconnectReceived == TRUE)
+ SendAck();
+
+ //need to release PM semaphore and reset all flags!
+ //Semaphore_Release(PROTOCOL_semaphore);
+ memset(pISR, 0, sizeof(ProtocolISR));
+
+ return NoError;
+}
+
+/* InitPort()
+ *
+ * Call into the driver to setup the ports and enable interrupts
+ *
+ */
+UINT_T InitPort(UINT_T port)
+{
+ return USBAPI_InitializeDevice(port);
+}
+
+UINT ImageDownloadWaiting(UINT_T media_num)
+{
+ pProtocolISR pISR = getProtocolISR();
+
+ //check to see if a USB is linked and said linked USB is the matching one
+ // if so, return whether a GetVersion request was made (i.e. a download is waiting)
+ if( (pISR->plinkedUSB != NULL) &&
+ (pISR->plinkedUSB->bootNum == media_num) )
+ return pISR->DLWaiting;
+ else
+ return FALSE;
+}
+
+
+UINT PreambleReceived()
+{
+ return getProtocolISR()->PreambleReceived;
+}
+
+void ClearPreambleReceived()
+{
+ getProtocolISR()->PreambleReceived = FALSE;
+}
+
+// ShutdownPorts: shutdown all ports
+void ShutdownPorts ()
+{
+ //call into USB API to shutdown all enabled USB devices
+ USBAPI_ShutdownAll();
+}
+
+//Protocol Manager ISR
+// There are three possible scenarios when this routine is called:
+// 1. PM is already used by another USB device (unusual scenario)
+// 2. PM is being used by the calling device (most likely scenario)
+// 3. PM is free (starting scenario)
+// The numbered comments in this routine will match up to the three mentioned scenarios
+void PM_ISR(P_USBAPI_T this, UINT bytes, UINT * buffer)
+{
+ UINT next_size, dummy = NULL;
+ pProtocolISR pISR = getProtocolISR();
+
+ //1. Is someone else using the protocol?
+ if( (pISR->plinkedUSB != this) && (pISR->plinkedUSB != NULL) )
+ { //Yes. Another USB is using protocol. Transmit a NAK
+ this->USB_Send(&dummy, PREAMBLE_SIZE, this);
+ //reprime so it will try again later
+ this->USB_Receive(buffer, PREAMBLE_SIZE, this);
+ //time to leave
+ return;
+ }
+
+ //2. We're already good friends
+ if(pISR->plinkedUSB == this)
+ {
+ if((bytes == PREAMBLE_SIZE ) && (pISR->PreambleReceived == FALSE))
+ { //check the validity of the preamble
+ if( PM_VerifyPreamble((UCHAR *)buffer) )
+ { //good Preamble!
+ pISR->PreambleReceived = TRUE;
+ // clear out any errors, as a new Preamble mean a new Image DL
+ pISR->ErrorCode = 0;
+ //respond with the preamble
+ SendResponse(preambleString, PREAMBLE_SIZE);
+ //set the pRXBuff to protocol area
+ resetProtoBuff();
+ //Setup for a new CMD
+ this->USB_Receive((UINT *)getProtoBuff(), this->maxpacketsize, this);
+ }
+ else
+ { //bad Preamble!
+ //Transmit a NAK
+ this->USB_Send(&dummy, PREAMBLE_SIZE, this);
+ //Reset USB control to download again
+ this->USB_Receive(buffer, PREAMBLE_SIZE, this);
+ }
+ }
+ else
+ {
+ //4. call into PM handler
+ next_size = PM_Handler(bytes);
+
+ //5. call into USBAPI to set up next RECEIVE
+ this->USB_Receive((UINT *)getProtoBuff(), next_size, this);
+ }
+ //all done, exit now
+ return;
+ }
+
+ //3. Newbie! Must receive a preamble or else we can't be friends.
+ if(pISR->plinkedUSB == NULL)
+ { //check the validity of the preamble
+ if( (bytes == PREAMBLE_SIZE) && PM_VerifyPreamble((UCHAR *)buffer) )
+ { //good Preamble!
+ pISR->PreambleReceived = TRUE;
+ // clear out any errors, as a new Preamble mean a new Image DL
+ pISR->ErrorCode = 0;
+ //Check out using semaphore and store the USB API pointer
+ pISR->plinkedUSB = this;
+ //Semaphore_Acquire(PROTOCOL_semaphore);
+ //respond with the preamble
+ SendResponse(preambleString, PREAMBLE_SIZE);
+ //set the pRXBuff to protocol area
+ resetProtoBuff();
+ //Setup for a new CMD
+ this->USB_Receive((UINT *)getProtoBuff(), this->maxpacketsize, this);
+ }
+ else
+ { //Premable was not valid
+ //Transmit a NAK
+ this->USB_Send(&dummy, PREAMBLE_SIZE, this);
+ //Reset USB control to download again
+ this->USB_Receive(buffer, PREAMBLE_SIZE, this);
+ }
+ return;
+ }
+}
+
+
+// PROTOCOL HANDLER
+// This routine is the singular handler for protocol commands
+// - JTAG over USB (CMD 36)
+// - Image Downloading
+//
+// Inputs:
+// - pUSBhandle: pointer the calling USB handler
+// - packetlength: length of the packet that triggered this call
+// Outputs:
+// - PrimeSize: the size to prime the next input packet for
+UINT PM_Handler(UINT packetLength)
+{
+ pProtocolCmd pCmd;
+ pProtocolISR pISR = getProtocolISR();
+ UINT next_size = pISR->plinkedUSB->maxpacketsize; //defualt is a full packet
+
+ //1st check if a fast download command is in progress
+ if(pISR->FastDLInProgress)
+ {
+ //Update counters
+ pISR->CurrentTransferAddress += packetLength;
+ pISR->DataLeft -= packetLength;
+ pISR->MaxImageSize = (packetLength > pISR->MaxImageSize) ? 0 : (pISR->MaxImageSize - packetLength);
+
+ //When DataLeft = 0, then the command is finally finished. respond back
+ if(pISR->DataLeft == 0)
+ {
+ pISR->FastDLInProgress = 0;
+ HandleDataCmd(); //send the response
+ resetProtoBuff(); //restore the location back to protocol area
+ }
+ else
+ { // Fast Download continues... set up info for next descriprots
+ //security check: can only download "MaxImageSize" per image DL. If malicious software tries to download more,
+ //this line of code will restrict the size dTD and force USB NACKs for any additional data
+ next_size = (pISR->DataLeft > pISR->MaxImageSize) ? pISR->MaxImageSize : pISR->DataLeft;
+ next_size = (next_size < FD_BLOCK_SIZE ) ? next_size : FD_BLOCK_SIZE;
+ setProtoBuff((UINT8 *)pISR->CurrentTransferAddress); //set location for USB to put data
+ }
+ return next_size;
+ }
+
+ //normal commands
+ //Overlay the Command structure over the buffer
+ pCmd = setProtocolCmd(getProtoBuff());
+
+ //All normal commands will load the data to the protocol buffer
+ resetProtoBuff();
+
+ //Sanity check - make sure the size read in matches the size defined in the ProtocolCmd packet
+ //if ( packetLength != (8+pCmd->Length) )
+ //{
+ // pISR->ErrorCode = UnknownProtocolCmd;
+ // SendError(UnknownProtocolCmd);
+ // return next_size;
+ //}
+
+ // update Interrupt Status Flags
+ //pISR->CurrentCommand = pCmd->Command;
+
+ switch( pCmd->Command )
+ {
+ case MessageCmd:
+ //try and send a message
+ // clear the upload command flag for upload
+ pISR->CommandReceived = FALSE;
+ HandleMessageCmd();
+ break;
+ #if !BOOTROM
+ case ProtocolVersionCmd:
+ // Send the major and minor protocol version bacl
+ HandleProtocolVersionCmd();
+ break;
+ case GetParametersCmd:
+ // Send Protocol Parameters to host.
+ HandleGetParametersCmd();
+ break;
+ case GetImageCrcCmd:
+ HandleGetCrcCmd();
+ break;
+ case GetBadBlockCmd:
+ HandleGetBadBlock();
+ break;
+ #endif
+ #if JTAG_OVER_JTAG_SUPPORTED
+ case JtagOverMediaCmd:
+ //copy the JTAG data into the JTAG structure
+ memcpy( (void *)pJTAG_CPCData->CommandFromHost, (void*)&pCmd->Data[0], pCmd->Length);
+ Jtag_Media_Handler();
+ break;
+ #endif
+ case GetVersionCmd:
+ //Indicate that a download is pending, but do NOT respond yet
+ pISR->DLWaiting = TRUE;
+ pISR->CommandReceived = TRUE; // mark it as download command
+ break;
+ case UploadDataHeaderCmd:
+ pISR->DLWaiting = TRUE; // indicate that a upload is pending
+ pISR->CommandReceived = TRUE; // mark it as upload command
+ break;
+ case UploadDataCmd:
+ pISR->CommandReceived = TRUE; // mark it as upload command
+ break;
+ case SelectImageCmd:
+ HandleSelectImageCmd(pISR->CurrentImageID);
+ next_size = 9; //the next command will be larger than normal
+ break;
+ case VerifyImageCmd:
+ HandleVerifyImageCmd();
+ next_size = 12; //the next command will be larger than normal
+ break;
+ case DataHeaderCmd:
+ next_size = HandleDataHeaderCmd();
+ if (pISR->FastDLInProgress) //override the download address for fast download
+ setProtoBuff((UINT8 *)pISR->CurrentTransferAddress); //set location for USB to put data
+ break;
+ case DownloadDataCmd:
+ //Note: this will only be triggered for "slow" download.
+ //move data from the buffer to boot address
+ memcpy((void *)(pISR->CurrentTransferAddress), (void*)&pCmd->Data[0], pCmd->Length);
+ //Update counters
+ pISR->CurrentTransferAddress += pCmd->Length;
+ pISR->MaxImageSize -= (pCmd->Length > pISR->MaxImageSize) ? pISR->MaxImageSize : pCmd->Length;
+ HandleDataCmd();
+ break;
+ case DoneCmd:
+ //Indicate that a download has finished, but do NOT respond yet
+ pISR->DLWaiting = FALSE;
+ pISR->CommandReceived = TRUE; // exit for upload while loop
+ break;
+ case DisconnectCmd:
+ pISR->DisconnectReceived = TRUE;
+ break;
+ default:
+ break;
+ }
+
+
+
+
+
+ return next_size;
+}
+
+
+
+
+
+
+// PM_ReceiveImage()
+//
+// This is the Protocol Recieve image routine. It does the following:
+// 1. Set the parameters for the download:
+// -- destination address
+// -- max size
+// -- image ID
+// 2. Check and wait for a pending image download request (GetVersion command from host)
+// 3. Download will be kicked off by sending the GetVersion response.
+// 4. Wait until the download has finished (DoneCommand will indicate that)
+//
+UINT_T PM_ReceiveImage(UINT_T dummy, UINT_T address, UINT_T size, UINT_T image_id)
+{
+ UINT retval = NoError, start_time, wait_time = 0;
+ //pProtocolCmd pCmd = getProtocolCmd();
+ pProtocolISR pISR = getProtocolISR();
+
+ //1. set up initial DL perameters:
+ pISR->CurrentTransferAddress = address;
+ pISR->MaxImageSize = size;
+ pISR->CurrentImageID = image_id;
+
+ //AddMessageCompound((UINT8_T*) ("*** PM_ReceiveImage pISR->CurrentTransferAddress...\0"), pISR->CurrentTransferAddress);
+
+ do
+ {
+ //2. wait for the download request
+ start_time = GetOSCR0();
+ do
+ { //Check for timeout
+ if( OSCR0IntervalInMilli(start_time, GetOSCR0()) > PM_DL_STARTTIME_MS )
+ {
+ retval = PM_ReceiveTimeOutError_1;
+ break;
+ }
+ }
+ while(pISR->DLWaiting == FALSE);
+
+ //check for an error
+ if(retval != NoError)
+ break;
+
+ //3. send the Get Version response to kick off the download
+ retval = HandleGetVersionCmd();
+
+ //check for an error
+ if(retval != NoError)
+ break;
+
+ /*
+ * Suppose the worst USB transfer speed is 0.5MB/s(in fact, it's about 12MB/s
+ * for HS mode but should also consider FS mode)
+ * Then, the wait time should not exceed (size / 1024 /4) milli seconds.
+ * The extra 2000 ms is to ensure the wait time is none-zero
+ */
+ wait_time = (size >> 9) + 2000;
+
+ //4. Wait for the Image DL to complete or an error
+ start_time = GetOSCR0();
+ do
+ { //Check for timeout
+ if( OSCR0IntervalInMilli(start_time, GetOSCR0()) > wait_time )
+ {
+ retval = PM_ReceiveTimeOutError_2;
+ break;
+ }
+ }
+ while( (pISR->DLWaiting == TRUE) && (pISR->ErrorCode == NoError) );
+
+ }while(FALSE);
+
+ //If there is an protocol error, override local error status
+ if(pISR->ErrorCode)
+ retval = pISR->ErrorCode;
+
+ //clear the flags to indicate an image dl is done
+ pISR->ErrorCode = NoError;
+ pISR->PreambleReceived = FALSE;
+ pISR->DLWaiting = FALSE;
+
+ //finish off the download by sending either the DONE cmd on success or NAK on failure
+ if(retval == PM_ReceiveTimeOutError_1 || retval == PM_ReceiveTimeOutError_2)
+ SendError(retval);
+ else
+ HandleDoneCmd();
+
+ //returns 0 if complete or an error code
+ return retval;
+}
+
+UINT_T GetUploadCommand(void)
+{
+ UINT_T Retval = NoError;
+ UINT_T StartTime;
+
+ pProtocolISR pISR = getProtocolISR();
+
+ StartTime = GetOSCR0(); //Dummy read to flush potentially bad data
+ StartTime = GetOSCR0();
+
+ while(pISR->CommandReceived == FALSE)
+ {
+ Retval = CheckProtocolTimeOut(StartTime);
+ if(Retval != NoError)
+ return Retval;
+ }
+ pISR->CommandReceived = FALSE;
+
+ return Retval;
+}
+
+/*
+ * HandleDownloadFlow()
+ *
+ * This function will handle a upload request unitl it completes or fails
+ * and return the status
+ */
+
+UINT_T HandleUploadFlow(UINT_T address)
+{
+ UINT_T Retval = NoError;
+ pProtocolCmd pCmd = getProtocolCmd();
+ pProtocolISR pISR = getProtocolISR();
+
+ pISR->CurrentTransferAddress = address;
+
+ do{
+ switch(pCmd->Command)
+ {
+ case UploadDataHeaderCmd:
+ Retval = HandleUploadDataHeaderCmd();
+ break;
+ case UploadDataCmd:
+ Retval = HandleUploadDataCmd();
+ break;
+ default:
+ if(pISR->CommandReceived == TRUE)
+ {
+ Retval = SendError(0);
+ Retval = UnknownProtocolCmd;
+ }else
+ Retval = NoError;
+ break;
+ }
+ if(Retval != NoError){
+ break;
+ }
+
+ GetUploadCommand();
+
+ }while (pCmd->Command != DoneCmd);
+
+ return Retval;
+}
+
+/**
+ * Debug Commands
+ **/
+UINT_T HandleUploadDataHeaderCmd(void)
+{
+ UINT_T Retval = NoError;
+ pProtocolCmd pCommand;
+ pProtocolISR pISR;
+ UploadDataParameters uploadParams, *pUploadParams;
+
+#if NAND_CODE || QSPINAND_CODE || SPINAND_CODE
+ UINT_T spare_size, page_size;
+ UINT_T numbers, total_spare_size;
+#endif
+
+
+ pUploadParams = &uploadParams;
+ pCommand = getProtocolCmd();
+ pISR = getProtocolISR();
+ memcpy((void*)pUploadParams,(void*)&pCommand->Data[0],sizeof(UploadDataParameters));
+
+ if (!upload_get_times_flag)
+ {
+ upload_times = pUploadParams->Times; // upload_times >= 1
+
+#if USE_SERIAL_DEBUG
+ obm_printf("upload_times: %d\n\r", upload_times);
+#endif
+
+ ResetUE = pUploadParams->ResetUE;
+ ResetDelay = pUploadParams->ResetTimeDelay;
+
+ obm_printf("ResetUE: %d, ResetDelay: %d\n\r", ResetUE, ResetDelay);
+
+ upload_get_times_flag = 1;
+ }
+
+ // Are the upload parameters ok?
+ Retval = VerifyUploadParameters(pUploadParams);
+ AddMessageError(REPORT_NOTIFICATION, PlatformBusy);
+
+ if(Retval != NoError)
+ {
+ AddMessageError(REPORT_NOTIFICATION, PlatformReady);
+ SendError(Retval);
+ return Retval;
+ }
+ else
+ {
+ getProtocolRsp()->Length = 0;
+ SendAck();
+ }
+
+ // Copy data requested into upload buffer
+
+ //AddMessageError(PlatformBusy);
+ //This could take a while
+
+ if(pUploadParams->Type == UPLOAD_DDR)
+ pISR->CurrentTransferAddress = pUploadParams->Offset;
+ else
+ Retval = CopyUploadDataIntoBuffer(pISR->CurrentTransferAddress, pUploadParams);
+
+ AddMessageError(REPORT_NOTIFICATION, PlatformReady);
+ // data should in buffer now
+
+ if(Retval != NoError)
+ {
+ setProtocolError(Retval);
+ // This was probably an error reading from source as UploadParams checked out ok.
+ // Set to No Error so that error can be sent to Host in HandleUploadDataCmd.
+ Retval = NoError;
+ }
+ else
+ {
+#if NAND_CODE || QSPINAND_CODE || SPINAND_CODE
+ if (upload_nand_spare == TRUE)
+ {
+ spare_size = GetSpareAreaSize(BOOT_FLASH); // get nand spare areas size
+ page_size = GetPageSize(BOOT_FLASH);
+ numbers = pUploadParams->DataSize / page_size; // calculate spare areas number
+ total_spare_size = numbers * spare_size; // total spare size
+
+ pISR->DataLeft = pUploadParams->DataSize + total_spare_size; // data length + total spare length
+ }
+ else
+#endif
+ {
+ pISR->DataLeft = pUploadParams->DataSize;
+ }
+ }
+
+ return Retval;
+
+}
+
+UINT_T HandleUploadDataCmd(void)
+{
+ UINT_T Retval = NoError,txDataSize = 0;
+ pProtocolRsp pRsp = (pProtocolRsp)transmitBuff;
+ pProtocolCmd pCmd = getProtocolCmd();
+ pProtocolISR pISR = getProtocolISR();
+
+ Retval = getProtocolError();
+ if(Retval!= NoError)
+ {
+ // We had a problem reading data for Data Upload
+ SendError(Retval);
+ return Retval;
+ }
+
+ if(pISR->DataLeft <= 0)
+ {
+ Retval = SeqError;
+ SendError(Retval);
+ return Retval;
+ }
+
+ pRsp->Command = UploadDataCmd;
+ pRsp->Sequence = pCmd->Sequence;
+ pRsp->CID = pCmd->CID;
+ pRsp->Status = Ack;
+
+ // Too bad length is only a byte. Not using it.
+ pRsp->Length = 0;
+
+ txDataSize = pISR->DataLeft < UPLOAD_BLOCK_SIZE ? pISR->DataLeft : UPLOAD_BLOCK_SIZE;
+ // Not a fan but have to do this. We have 6 byte status and arbitrary data.
+ memcpy((void*)&pRsp->Data[0], (void*)pISR->CurrentTransferAddress, txDataSize);
+
+
+ // Message bit should NOT be set in flags.
+ // At this point getProtocolMsg()->MessageFlag will be 0.
+ pRsp->Flags = pRsp->Flags & ~(MESSAGE_FLAG);
+ pRsp->Flags = pRsp->Flags | getProtocolMsg()->MessageFlag;
+
+ Retval = SendResponse(&pRsp->Command, txDataSize + 6);
+
+ pISR->CurrentTransferAddress += txDataSize;
+ pISR->DataLeft -= txDataSize;
+
+ return Retval;
+}
+
+UINT_T CopyUploadDataIntoBuffer(UINT_T address, pUploadDataParameters pUploadParams)
+{
+ UINT_T Retval = NoError;
+
+ switch(pUploadParams->Type)
+ {
+ case UPLOAD_FLASH:
+ // Fix me. Need code to check if sub type of flash is supported.
+ if (!upload_config_flash_flag && !FlashInitDone)
+ {
+ /* sub type of flash is not supported */
+ //Retval = PlatformInitFlash(pUploadParams->SubType & 0x1F);
+ Retval = Configure_Flashes(pUploadParams->SubType & 0x1F, BOOT_FLASH);
+ if( Retval != NoError)
+ FatalError(Retval, NULL, NULL);
+
+ InitializeFM(LEGACY_METHOD, BOOT_FLASH);
+
+ upload_config_flash_flag = 1; // configure flash for upload only one time
+ }
+
+ #if NAND_CODE || QSPINAND_CODE || SPINAND_CODE
+
+ #if NAND_CODE
+ if (pUploadParams->ResetUE == 1)
+ {
+ AddMessageError(REPORT_UPLOAD_NOTIFICATION, NandID);
+ }
+ #endif
+
+ upload_nand_spare = pUploadParams->IncludeOOB;
+
+ upload_disable_ecc = pUploadParams->DisableECC;
+ #endif
+
+ // Set the partition.
+ #if MMC_CODE
+ SetPartition(pUploadParams->Partition, BOOT_FLASH);
+ #endif
+
+#if defined(NEZHA701) || defined(NEZHA702)
+ if ((pUploadParams->Offset <= MEP_FALSH_START &&
+ pUploadParams->Offset + pUploadParams->DataSize > MEP_FALSH_START) ||
+ (pUploadParams->Offset >= MEP_FALSH_START &&
+ pUploadParams->Offset < MEP_FALSH_START + MEP_FLASH_LEN))
+ Retval = NotSupportedError;
+ else
+#endif
+ Retval = ReadFlash(pUploadParams->Offset, address, pUploadParams->DataSize, BOOT_FLASH);
+ break;
+ default:
+ // Not supported.
+ Retval = NotSupportedError;
+ break;
+
+ }
+ return Retval;
+}
+
+UINT_T VerifyUploadParameters(pUploadDataParameters pUploadParams)
+{
+ UINT_T Retval = NoError, flashNum;
+ pTIM pTIM_h = GetTimPointer();
+ switch(pUploadParams->Type)
+ {
+ case UPLOAD_FLASH:
+ // Is flash subtype supported. Looking in Tim.
+ flashNum = pTIM_h->pConsTIM->FlashInfo.BootFlashSign & 0xFF;
+ if(flashNum != pUploadParams->SubType & 0xFF &&
+ flashNum != CI2_USB_D) //Empty board upload
+ Retval = UnsupportedFlashError;
+
+ if(pUploadParams->UploadBypassBBT) {
+ obm_printf("Upload Flash with BBT bypassed\n\r");
+ GetFlashProperties(BOOT_FLASH)->FlashSettings.UseBBM = 0;
+ }
+ break;
+ case UPLOAD_DDR:
+ break;
+ default:
+ // Not supported.
+ Retval = NotSupportedError;
+ break;
+
+ }
+ return Retval;
+}
+
+UINT_T HandleProtocolVersionCmd()
+{
+ UINT_T Retval = 0;
+ pProtocolRsp pRsp;
+ pProtocolCmd pCmd;
+
+ pCmd = getProtocolCmd();
+ pRsp = getProtocolRsp();
+
+ pRsp->Command = pCmd->Command;
+ pRsp->Sequence = pCmd->Sequence;
+ pRsp->CID = pCmd->CID;
+ pRsp->Status = Ack;
+ pRsp->Length = 4;
+
+ pRsp->Data[0] = COMM_PROTOCOL_MAJOR_VERSION;
+ pRsp->Data[1] = COMM_PROTOCOL_MINOR_VERSION;
+ *(UINT16_T*)&pRsp->Data[2] = COMM_PROTOCOL_REV_VERSION;
+
+ pRsp->Flags = pRsp->Flags & ~(MESSAGE_FLAG);
+ pRsp->Flags = pRsp->Flags | getProtocolMsg()->MessageFlag;
+
+ SendResponse(&pRsp->Command, 6 + pRsp->Length);
+ return Retval;
+}
+
+UINT_T HandleGetParametersCmd()
+{
+ UINT_T Retval = 0;
+ pProtocolRsp pRsp;
+ pProtocolCmd pCmd;
+
+ pCmd = getProtocolCmd();
+ pRsp = getProtocolRsp();
+
+ pRsp->Command = pCmd->Command;
+ pRsp->Sequence = pCmd->Sequence;
+ pRsp->CID = pCmd->CID;
+ pRsp->Status = Ack;
+ // Currently only sending buffer size. But we have 3 more reserved paramters.
+ // Note: Rsp structure only has space for 12 bytes of data ( 3 params). If we
+ // are going to use all 4 parameters, we need a buffer and memcpy.
+ pRsp->Length = 16;
+
+ *(UINT16_T *)&pRsp->Data[0] = COMM_PROTOCOL_BUFFER_SIZE & 0xffff;
+ *(UINT16_T *)&pRsp->Data[2] = (COMM_PROTOCOL_BUFFER_SIZE & 0xffff0000)>> 16;
+ pRsp->Flags = pRsp->Flags & ~(MESSAGE_FLAG);
+ pRsp->Flags = pRsp->Flags | getProtocolMsg()->MessageFlag;
+
+ // This should be
+ // SendResponse(&pRsp->Command, 6 + pRsp->Length);
+ // See note above
+ SendResponse(&pRsp->Command, 6 + pRsp->Length);
+ return Retval;
+}
+
+UINT_T HandleGetCrcCmd()
+{
+ UINT_T Retval = 0;
+ pProtocolRsp pRsp = (pProtocolRsp)transmitBuff;
+ pProtocolCmd pCmd;
+ UINT_T BufferAddr;
+ INT_T BufferLen = 4; //Nack
+
+ pCmd = getProtocolCmd();
+
+ pRsp->Command = pCmd->Command;
+ pRsp->Sequence = pCmd->Sequence;
+ pRsp->CID = pCmd->CID;
+ Retval = GetImageReadBackCrcBuffer(&BufferAddr, &BufferLen);
+
+ pRsp->Flags = pRsp->Flags & ~(MESSAGE_FLAG);
+ pRsp->Flags = pRsp->Flags | getProtocolMsg()->MessageFlag;
+
+ if(Retval == NoError){
+ pRsp->Status = Ack;
+ //pRsp->Length is UINT8, BufferLen exceed 255
+ pRsp->Length = BufferLen;
+ memcpy(&pRsp->Data[0], (UINT8 *)BufferAddr, BufferLen);
+ }else{
+ pRsp->Status = Nack;
+ pRsp->Length = 4;
+ *(UINT16_T *)&pRsp->Data[0] = Retval & 0xffff;
+ *(UINT16_T *)&pRsp->Data[2] = (Retval & 0xffff0000)>> 16;
+ }
+
+ //pRsp->Length is UINT8, BufferLen exceed 255, use BufferLen instead
+ SendResponse(&pRsp->Command, 6 + BufferLen);
+ return Retval;
+}
+
+UINT_T HandleGetBadBlock()
+{
+ UINT_T Retval = 0;
+ pProtocolRsp pRsp = (pProtocolRsp)transmitBuff;
+ pProtocolCmd pCmd;
+ P_FlashProperties_T pFlashProp = GetFlashProperties(BOOT_FLASH);
+ pBadBlockData bbData;
+
+ pCmd = getProtocolCmd();
+
+ pRsp->Command = pCmd->Command;
+ pRsp->Sequence = pCmd->Sequence;
+ pRsp->CID = pCmd->CID;
+ pRsp->Status = Ack;
+
+ bbData = (pBadBlockData)(&pRsp->Data[0]);
+ bbData->TotalBadBlocks = GetBadBlockNum();
+ bbData->TotalBlocks = pFlashProp->NumBlocks;
+ pRsp->Length = 8;
+
+ pRsp->Flags = pRsp->Flags & ~(MESSAGE_FLAG);
+ pRsp->Flags = pRsp->Flags | getProtocolMsg()->MessageFlag;
+
+ SendResponse(&pRsp->Command, 6 + pRsp->Length);
+ return Retval;
+}
+
+UINT_T AddMessageError(UINT_T ReportType, UINT_T ReportCode)
+{
+ UINT_T Retval = 0;
+
+ #if VERBOSE_MODE
+ UINT_T mIndex, i;
+ pProtocolMsg pMsg = getProtocolMsg();
+ MessageReport Report;
+
+ if(pMsg->NumMessagesQueued == MAXNUMOFMESSAGES)
+ return MessageBufferFullError; //this is when message buffer is full
+
+ //find the next open slot in the Queue
+ //It will be right after the last good message
+ //this is a circular queue, so we use the '%' operation
+ mIndex = (pMsg->CurrentMessageIndex + pMsg->NumMessagesQueued) % MAXNUMOFMESSAGES;
+
+ Report.ReportType = ReportType;
+ Report.Reserved = 0;
+
+ for (i = 0; i < 4; i++)
+ {
+ Report.ReportCode[i] = (ReportCode >> (8 * i)) & 0xff;
+ }
+
+ // copy message to buffer
+ pMsg->Lengths[mIndex] = 6;
+
+ pMsg->Messages[mIndex][0] = Report.ReportType;
+ pMsg->Messages[mIndex][1] = Report.Reserved;
+
+ for (i = 0; i < 4; i++)
+ {
+ pMsg->Messages[mIndex][i + 2] = Report.ReportCode[i];
+ }
+
+ pMsg->MessageType[mIndex] = 1; // Message type 1 indicate report code
+ //set flag
+ pMsg->MessageFlag = MESSAGE_FLAG;
+
+ pMsg->NumMessagesQueued++;
+
+ #endif //endif VERBOSE_MODE
+ return NoError;
+}
+
+void InitProtocol(void)
+{
+ pProtocolMsg pMsg = getProtocolMsg();
+ //pProtocolCmd pCMD = getProtocolCmd();
+ pProtocolRsp pRsp = getProtocolRsp();
+ pProtocolISR pISR = getProtocolISR();
+
+ memset(pMsg, 0, sizeof(ProtocolMsg));
+ //memset(pCMD, 0, sizeof(ProtocolCmd));
+ memset(pRsp, 0, sizeof(ProtocolRsp));
+ memset(pISR, 0, sizeof(ProtocolISR));
+}
+
+
+
+/*
+ * HandleRequest()
+ *
+ * This is the main function of the protocol manager. It is the entry point
+ * to start a request over a port after an interrupt is received. The process
+ * for handling a request is as follows:
+ *
+ * 1) Get the preamble from the port and verify it
+ * 2) Get the first command packet from the port
+ * 3) Send back and ack with proper flag settings
+ * 4) Based on the command jump to the download flow or the JTAG flow
+ * 5) Complete the download or JTAG request and when complete disconnect
+ * 6) return status to the caller
+ *
+ *
+ */
+
+UINT_T HandleRequest(UINT_T src_addr, UINT_T dest_addr, UINT_T max_size, UINT_T image_id)
+{
+ UINT_T Retval = NoError;
+ pProtocolCmd pCmd = getProtocolCmd();
+
+ do
+ {
+ switch(pCmd->Command)
+ {
+ case GetVersionCmd:
+ //Retval = HandleDownloadFlow(dest_addr, image_id, max_size);
+ break;
+
+#if!BOOTROM
+ case UploadDataHeaderCmd:
+ Retval = HandleUploadFlow(src_addr);
+ if(Retval != NoError)
+ return Retval;
+ break;
+#endif
+ case DisconnectCmd:
+ //if there was an issue with a download, then tool will try to disconnect
+ //handle the disconnect, but return an error since we couldn't do a download
+ //getProtocolISR()->CommandReceived = TRUE; // This hack is needed for optimization. Handledisconnect waits for a command again
+ Retval = HandleDisconnect();
+ return Retval;
+ default:
+ //Retval.ErrorCode = SendError(0);
+ //Retval.ErrorCode = UnknownProtocolCmd;
+ break;
+ }
+ if(Retval != NoError)
+ break;
+
+ }while(pCmd->Command != DoneCmd);
+
+ if(pCmd->Command == DoneCmd)
+ HandleDoneCmd();
+ else
+ Retval = SendError(0);
+
+ return Retval;
+}
+
+//--------------------------------------------------------
+// Utility routines
+//--------------------------------------------------------
+
+
+
+/*
+ * Verify that the Preamble matches
+ */
+UINT8_T PM_VerifyPreamble( UINT8_T *candidateString )
+{
+ //Compare the candidate preamble to the defined string
+ if( 0 == memcmp(candidateString, preambleString, sizeof(preambleString)) )
+ { //MATCH
+ //return that all is good
+ return TRUE;
+ }
+ else
+ { //Bad String
+ return FALSE;
+ }
+}
+
+/*
+ * Check to see if routine has timed out
+ */
+UINT8_T CheckProtocolTimeOut(UINT_T StartTime)
+{
+ UINT_T WaitTime = 0;
+ UINT_T CurrentTime;
+
+ CurrentTime = GetOSCR0();
+
+ WaitTime = OSCR0IntervalInSec(StartTime, CurrentTime); // measure wait time in sec
+
+ if (WaitTime >= PROTOCOL_WAITTIME)
+ return (CheckProtocolTimeOutError);
+ else return NoError;
+}
+