//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//

#include <windows.h>
#include <bsp.h>
#include "loader.h"

#include <fmd.h>
#include <register_map.h>

extern DWORD g_ImageType;
extern DWORD _NUM_OF_BLOCKS;
extern DWORD _BYTES_PER_BLOCK;
extern WORD _SECTORS_PER_BLOCK;
extern WORD _BYTES_PER_SECTOR;

/*
    @func   BOOL | OEMIsFlashAddr | Tests whether the address provided resides in the Samsung's flash.
    @rdesc  TRUE = Specified address resides in flash, FALSE = Specified address doesn't reside in flash.
    @comm    
    @xref   
*/
BOOL OEMIsFlashAddr(DWORD dwAddr)
{
    //EdbgOutputDebugString("OEMIsFlashAddr: 0x%x, %d\r\n", dwPhysStart, bRc);
    return(TRUE);
}


/*
    @func   LPBYTE | OEMMapMemAddr | Remaps a specified address to a file cache location.  The file cache is used as a temporary store for flash images before they're written to flash.
    @rdesc  Corresponding address within a file cache area.
    @comm    
    @xref   
*/
LPBYTE OEMMapMemAddr(DWORD dwImageStart, DWORD dwAddr)
{
	switch(dwImageStart)
	{
		case BOOTIMAGE_RAM_IMAGE_BASE:
			// 0x00000000
			if(g_ImageType == IMAGE_TYPE_BOOTIMAGE || g_ImageType == IMAGE_TYPE_BLOCK0IMG || g_ImageType == IMAGE_TYPE_SUPERIPL)
			{
//				dwAddr = FILE_CACHE_START + FILE_CACHE_LENGTH - 0x00200000 + (NBOOT_BLOCK * _BYTES_PER_BLOCK) + (dwAddr - BOOTIMAGE_RAM_IMAGE_BASE);
				dwAddr = (FILE_CACHE_START + (dwAddr - STEPLDR_RAM_IMAGE_BASE));
				return (LPBYTE)dwAddr;

			}
			else if(g_ImageType == IMAGE_TYPE_DIOBIN)
			{
				dwAddr = (FILE_CACHE_START + dwAddr);
			}
			//added by terry for logo.bin 2012.06.18
			else if(g_ImageType == IMAGE_TYPE_LOGO)
			{
				dwAddr = NK_RAM_IMAGE_BASE;
				return (LPBYTE)dwAddr;
			}		
			else
			{

				// At the end of DownloadImage, BLCOMMON calls OEMMapMemAddr to get the ROMHDR of a image to be launched.
				// Because DIOBIN image(flash.bin) does not have any ROMHDR, BLCOMMON ignores this image.
				//
				// If multiple binaries are downloaded, there may be a problem.
				// While OEMMapMemAddr is being called with the address of any other image which has a ROMHDR,
				//   current image type could be unmatched with the passed address.
				//
				// For example, the address of EBOOT is passed, but the current image type is DIOBIN.
				// We need to cope with this corner case like following code.
				// Please refer to the code blcommon.c (case(BL_DOWNLOAD) @BootloaderMain)
				
				OALMSG(1, (TEXT("<ERROR> Invalid start address for the image type 0x%X\r\n"), g_ImageType));
				dwAddr = FILE_CACHE_START;
			};

			break;

		default:

			if(g_ImageType == IMAGE_TYPE_LOGO)
			{
				dwAddr = NK_RAM_IMAGE_BASE;
				return (LPBYTE)dwAddr;

			}
		
			if(dwImageStart >= NK_RAM_IMAGE_BASE)
			{
				dwAddr = dwAddr;
			}
			else
			{
				OALMSG(1, (TEXT("<ERROR> Invalid start address for the image type 0x%X\r\n"), g_ImageType));
				dwAddr = FILE_CACHE_START;
			}
			
			break;
			
	}

		
    return (LPBYTE)dwAddr;



/*
    //OALMSG(TRUE, (TEXT("OEMMapMemAddr 0x%x  0x%x\r\n"),dwImageStart, dwAddr));
	if ((g_ImageType & IMAGE_TYPE_STEPLDR) || (g_ImageType & IMAGE_TYPE_BOOTIMAGE))
	{
		dwAddr = (FILE_CACHE_START + (dwAddr - STEPLDR_RAM_IMAGE_BASE));
	    return (LPBYTE)dwAddr;
	}
    else
	if (g_ImageType & IMAGE_TYPE_IPL)
	{
		dwAddr = (FILE_CACHE_START + (dwAddr - IPL_RAM_IMAGE_BASE));
	    return (LPBYTE)dwAddr;
	}
    else
    if (g_ImageType & IMAGE_TYPE_EBOOT)
	{
		dwAddr = (FILE_CACHE_START + (dwAddr - EBOOT_RAM_IMAGE_BASE));
	    return (LPBYTE)dwAddr;
	}
    else
	if (g_ImageType & IMAGE_TYPE_DIOBIN)
	{
		//dwAddr = (FILE_CACHE_START + (dwAddr - FLASHBIN_RAM_IMAGE_BASE));
        //OALMSG(TRUE, (TEXT("OEMMapMemAddr return: 0x%x \r\n"),dwAddr));
	    return (LPBYTE)dwAddr;
	}
    else
	if (g_ImageType & IMAGE_TYPE_DIO)
	{
		dwAddr = (FILE_CACHE_START + (dwAddr - NAND_ROM_IMAGE_BASE));
	    return (LPBYTE)dwAddr;
	}
    else
	if (g_ImageType & IMAGE_TYPE_DIONB0)
    {
		dwAddr = (FILE_CACHE_START + (dwAddr - NAND_ROM_IMAGE_BASE));
	    return (LPBYTE)dwAddr;
	}
	else
    if (g_ImageType & IMAGE_TYPE_UNKNOWN)
    {
        OALMSG(TRUE, (TEXT("OEMMapMemAddr 0x%x  0x%x\r\n"),dwAddr,(FILE_CACHE_START + dwAddr)));
		dwAddr = FILE_CACHE_START + dwAddr;
	    return (LPBYTE)dwAddr;
	}

    return (LPBYTE)dwAddr;
*/    
}


/*
    @func   BOOL | OEMStartEraseFlash | Called at the start of image download, this routine begins the flash erase process.
    @rdesc  TRUE = Success, FALSE = Failure.
    @comm    
    @xref   
*/
BOOL OEMStartEraseFlash(DWORD dwStartAddr, DWORD dwLength)
{
    // Nothing to do (erase done in OEMWriteFlash)...
    //
//    OALMSG(OAL_INFO, (L"OEMStartEraseFlash: return TRUE\r\n"));
    return(TRUE);
}


/*
    @func   void | OEMContinueEraseFlash | Called frequenty during image download, this routine continues the flash erase process.
    @rdesc  N/A.
    @comm    
    @xref   
*/
void OEMContinueEraseFlash(void)
{
    // Nothing to do (erase done in OEMWriteFlash)...
    //
//    EdbgOutputDebugString("OEMContinueEraseFlash\r\n");
}


/*
    @func   BOOL | OEMFinishEraseFlash | Called following the image download, this routine completes the flash erase process.
    @rdesc  TRUE = Success, FALSE = Failure.
    @comm    
    @xref   
*/
BOOL OEMFinishEraseFlash(void)
{
    // Nothing to do (erase done in OEMWriteFlash)...
    //
//    EdbgOutputDebugString("OEMFinishEraseFlash\r\n");
    return(TRUE);
}


/*
    @func   BOOL | OEMWriteFlash | Writes data to flash (the source location is determined using OEMMapMemAddr).
    @rdesc  TRUE = Success, FALSE = Failure.
    @comm    
    @xref   
*/
BOOL OEMWriteFlash(DWORD dwStartAddr, DWORD dwLength)
{
	BOOL rc;

	UCHAR ackdata[4] = {'O', 'K', 'U', 'P'};

	//char KeySelect;

	//lqm masked.11.10.01
	return TRUE;//add by jerry

    EdbgOutputDebugString("OEMWriteFlash 0x%x 0x%x\r\n", dwStartAddr, dwLength);
    EdbgOutputDebugString("OEMWriteFlash 0x%x \r\n", g_ImageType);

	switch (g_ImageType) {
	case IMAGE_TYPE_STEPLDR:
	    rc = TRUE;
		break;	    
	case IMAGE_TYPE_IPL:
	    rc = TRUE;
		break;	    
	case IMAGE_TYPE_BOOTIMAGE:
	    rc = TRUE;
		break;	    
	case IMAGE_TYPE_EBOOT:
		rc = TRUE;
		break;
	case IMAGE_TYPE_DIOBIN:
		rc = TRUE;
		break;
	case IMAGE_TYPE_DIONB0:
	    rc = TRUE;
		break;
	case IMAGE_TYPE_NK:
		if (!WriteFlashNK(dwStartAddr, dwLength))
		{
			//bReturn = FALSE;
			OALMSG(1, (TEXT("<ERROR> Failed to write a XIP region to the flash memory.\r\n")));
			while(1);
		}
		else
		{
			// 1 file download success
			USBWriteString(ackdata, 4);
		}
		
		rc = TRUE;
		break;
	default:
		rc = FALSE;
	}
	return rc;

//    return(TRUE);
}

//------------------------------------------------------------------------------
