/* ---------------------------------------------------------------------------
 * appImage.c - v0.1                                (c) 2008 Micro-key bv
 * ---------------------------------------------------------------------------
 * Micro-key bv
 * Industrieweg 28, 9804 TG Noordhorn
 * Postbus 92, 9800 AB Zuidhorn
 * The Netherlands
 * Tel: +31 594 503020
 * Fax: +31 594 505825
 * Email: support@microkey.nl  
 * Web: www.microkey.nl
 * ---------------------------------------------------------------------------
 * Description: 
 * ---------------------------------------------------------------------------
 * Version(s):  0.1, Feb 12, 2008, FSc
 *                   Creation.
 * ---------------------------------------------------------------------------
 */

/* ---------------------------------------------------------------------------
 * System include files
 * ---------------------------------------------------------------------------
 */

/* ---------------------------------------------------------------------------
 * Application include files
 * ---------------------------------------------------------------------------
 */
#include "types.h"
#include "appImage.h"
#include "LPC23xx.h"
#include "crc.h"
#include "IspProtocol.h"
#include "bootloader.h"

/* ---------------------------------------------------------------------------
 * Local constant and macro definitions
 * ---------------------------------------------------------------------------
 */
typedef void (*t_application_startup)(void);

#define APPI_FLASH_START_ADDR    0x5000
#define APPI_FLASH_END_ADDR      0x7E000
#define APPI_C_ENTRY_OFFS        0x0020    
#define APPI_IMAGE_LENGTH_OFFS   0x0008
#define APPI_IMAGE_CRC_OFFS      0x000C

/* ---------------------------------------------------------------------------
 * Global variable definitions
 * ---------------------------------------------------------------------------
 */

/* ---------------------------------------------------------------------------
 * Local variable definitions
 * ---------------------------------------------------------------------------
 */

/* ---------------------------------------------------------------------------
 * Local function definitions
 * ---------------------------------------------------------------------------
 */
void appiCalculateCrc( UINT32 imageLength, UINT16 *crc );


/** \brief Checks if the Application image requests a Image update
 * 
 * When the application image wants to start an image update, it sets
 * a pattern on a known RAM-location and resets the CPU. Now the bootloader
 * can verify this pattern.
 * 
 * \retval TRUE Application did request an update
 * \retval FALSE Application did not request an update
 */ 
BOOLEAN appiApplicationRequestsUpdate()
{
	if (blGetBootmode() == STAY_IN_BOOTLOADER)
	{
		return TRUE;
	}
	else
	{
		return FALSE;
	}
}


 /** \brief Checks if a valid Application image.
  * 
  * \retval TRUE Flash contains a valid Application image
  * \retval FALSE Flash doesn't contain a valid Application image
  */
BOOLEAN appiValidAppImageAvail()
{
	static UINT32 imageSize = 0;
	static UINT16 recordedCrc = 0;
	UINT8 index;
	static UINT16 calculatedCrc;
	
	index = APPI_IMAGE_LENGTH_OFFS;
	imageSize = ispGet32bit((UINT8 *)APPI_FLASH_START_ADDR, &index); 
	recordedCrc = ispGet16bit((UINT8 *)APPI_FLASH_START_ADDR, &index);
 
	if (    (imageSize >= 100) 
		 && (imageSize <= (APPI_FLASH_START_ADDR - APPI_FLASH_END_ADDR))
	   )
	{
		appiCalculateCrc(imageSize, &calculatedCrc);
	
		if (recordedCrc != calculatedCrc)
		{
			return FALSE;
		}
		else
		{
			return TRUE;
		}
	}
	else
	{
		if (imageSize == 0)
		{
			// escape for debugging
			return TRUE;
		}
		else
		{
			return FALSE;
		}
			
	}
}

/** \brief Jumps to the Application image. Function won't return.
 */   
void appiJumpToAppImage()
{
	unsigned int application_start_addr = APPI_FLASH_START_ADDR + APPI_C_ENTRY_OFFS;
	
	blResetBootmode(); 

    DISABLE_INTERRUPTS();
	
    ((t_application_startup)application_start_addr)();
}

void appiCalculateCrc( UINT32 imageLength, UINT16 *crc )
{
	UINT8 *image = (UINT8 *)(APPI_FLASH_START_ADDR);
	*crc = 0;

	// Calculate Crc over part before Length & CRC
	*crc = crcCalc(image, APPI_IMAGE_LENGTH_OFFS, *crc);

	// Calculate Crc over part after Length & CRC
	image = (UINT8 *)(APPI_FLASH_START_ADDR + APPI_IMAGE_CRC_OFFS + 4);
	*crc = crcCalc(image, imageLength - (APPI_IMAGE_CRC_OFFS + 4), *crc);
}

