//
// 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.
//

#ifndef _LOADER_H_
#define _LOADER_H_

#include <blcommon.h>
#include <bootpart.h>
#include <clkinfo.h>

#ifdef SDMMC_BOOT
#include <hsmmcdrv.h>
#define USE_TRACE32_DOWNLOAD (0)
#else
#include <fmd.h>
#include <nand.h>
#endif
// Bootloader version.
//
#define EBOOT_VERSION_MAJOR     2
#define EBOOT_VERSION_MINOR     5


//------------------------------------------------------------------------------
//
//  Section Name:   Memory Configuration
//  Description.:   The constants defining memory layout below must match
//                  those defined in the .bib files.
//
//------------------------------------------------------------------------------

#define CACHED_TO_UNCACHED_OFFSET   0x20000000

#define STEPLDR_RAM_IMAGE_BASE      0x00000000
#define STEPLDR_RAM_IMAGE_SIZE      0x00001000 //stepldr.nb0  only use 0x00001000

#define BLOCK0_RAM_IMAGE_BASE       0x00000000
#define BLOCK0_RAM_IMAGE_SIZE       0x00020000 //block0img.nb0(nbl1.nb0 + nbl2.nb0)  only use 0x00020000

#define IPL_RAM_IMAGE_BASE          0x87780000
#define IPL_RAM_IMAGE_SIZE          0x00080000 //ipl.bin

#define BOOTIMAGE_RAM_IMAGE_BASE    0x00000000
#define BOOTIMAGE_RAM_IMAGE_SIZE    0x00140000 //bootimage.nb0(block0img.nb0 + eboot.nb0 + ipl.nb0)

#define UPLDR_RAM_IMAGE_BASE        0x00000000
#define UPLDR_RAM_IMAGE_SIZE        0x00200000 //only use 0x00200000

#define NAND_ROM_IMAGE_BASE         0x00000000
#define NAND_ROM_IMAGE_SIZE         0x03000000

#define EBOOT_RAM_IMAGE_BASE        0x87700000
#define EBOOT_RAM_IMAGE_SIZE        0x00080000

#define NK_RAM_IMAGE_BASE			0x80020000
#define NK_RAM_IMAGE_SIZE			0x05EE0000


//added by terry 2012.06.18
#define LOGBMP_RAM_IMAGE_BASE		0x87800000	//0x83A00000//0x82200000
#define LOGBMP_RAM_IMAGE_SIZE		0x00100000	// 0x00080000	 800x480x2=768000
//#define NF_SECTOR_SIZE			    		2048
//#define NF_SECTOR_SIZE			    		4096




#define DIONB0_RAM_IMAGE_BASE       0x00000000
#define DIONB0_SECTOR_SIZE          0x00040000

#define FLASHBIN_RAM_IMAGE_BASE     0x00000000
#define FLASHBIN_SECTOR_SIZE        0x00040000

#define EBOOT_STORE_OFFSET          0
#define EBOOT_STORE_ADDRESS         (EBOOT_RAM_IMAGE_BASE + EBOOT_STORE_OFFSET)
#define EBOOT_STORE_MAX_LENGTH      EBOOT_RAM_IMAGE_SIZE

// BinFS work area defined in boot.bib
#define BINFS_RAM_START             (BPART_BUFFER_U_VIRTUAL)   // uncached, changed for magneto...DonGo
#define BINFS_RAM_LENGTH            (BPART_BUFFER_LENGTH_BYTES)

//
// Nk Memory reigions defined in config.bib...
//
#define ROM_RAMIMAGE_START          0x80020000
#define ROM_RAMIMAGE_SIZE           0x03000000


//#define FILE_CACHE_START            (0x8c200000 | CACHED_TO_UNCACHED_OFFSET)        // Start of file cache (temporary store
// Changed for magneto... DonGo
#define FILE_CACHE_START            (0x80020000 | CACHED_TO_UNCACHED_OFFSET)        // Start of file cache (temporary store
#define FILE_CACHE_LENGTH	 	    0x03BE0000

// Driver globals pointer (parameter sharing memory used by bootloader and OS).
//
//#define pBSPArgs                    ((BSP_ARGS *) IMAGE_SHARE_ARGS_UA_START)


// Platform "BOOTME" root name.
//
#define PLATFORM_STRING         "SMDKV210"

#ifndef SECTOR_SIZE
#define SECTOR_SIZE				(512)
#endif

#define NAND_SECTOR_SIZE		(SECTOR_SIZE<<2)

#ifdef SDMMC_BOOT
#define TOC_SECTOR_SIZE					(4096)

__inline DWORD FILE_TO_SECTOR_SIZE(DWORD fs) {
    return ( (fs / SDMMC_SECTOR_SIZE) + ( (fs % SDMMC_SECTOR_SIZE) ? 1 : 0) );
}

// ns: number of sectors
// N.B: returns sector aligned value since we can't tell
__inline DWORD SECTOR_TO_FILE_SIZE(DWORD ns) {
    return ( ns * SDMMC_SECTOR_SIZE );
}
#define SECTOR_TO_BLOCK(sector)     ((sector) >> 6 )
#define BLOCK_TO_SECTOR(block)      ((block)  << 6 )

#else
#ifndef PAGES_PER_BLOCK
#define PAGES_PER_BLOCK			(64)
#endif

#define NAND_PAGES_PER_BLOCK	(64)

#ifndef BADBLOCKMARK
#define BADBLOCKMARK			(0x00)
#endif

//#define SECTOR_TO_BLOCK(sector)     ((sector) >> 8 )
//#define BLOCK_TO_SECTOR(block)      ((block)  << 8 )
#define SECTOR_TO_BLOCK(sector)     ((sector) >> 6 )
#define BLOCK_TO_SECTOR(block)      ((block)  << 6 )


#define SECTOR_TO_BLOCK_SIZE(sn)        ((sn / _SECTORS_PER_BLOCK) + ((sn % _SECTORS_PER_BLOCK) ? 1 : 0))
#define FILE_TO_SECTOR_SIZE(fs)         ((fs / _BYTES_PER_SECTOR) + ((fs % _BYTES_PER_SECTOR) ? 1 : 0))
#define FILE_TO_BLOCK_SIZE(fs)          ((fs / _BYTES_PER_BLOCK) + ((fs % _BYTES_PER_BLOCK) ? 1 : 0))
#define SECTOR_TO_FILE_SIZE(sn)         (sn * _BYTES_PER_SECTOR)

#endif
/*
// fs: sector number
// returns block aligned value
__inline DWORD SECTOR_TO_BLOCK_SIZE(DWORD sn) {
    return ( (sn / NAND_PAGES_PER_BLOCK) + ( (sn % NAND_PAGES_PER_BLOCK) ? 1 : 0) );
}

// fs: file size in bytes
// returns sector aligned value


__inline DWORD FILE_TO_SECTOR_SIZE(DWORD fs) {
    return ( (fs / NAND_SECTOR_SIZE) + ( (fs % NAND_SECTOR_SIZE) ? 1 : 0) );
}

// ns: number of sectors
// N.B: returns sector aligned value since we can't tell
__inline DWORD SECTOR_TO_FILE_SIZE(DWORD ns) {
    return ( ns * NAND_SECTOR_SIZE );
}
*/

//
// Boot Config Flags...
//

#define USE_SERIAL_MESSAGE	(1)         // add by shin..1024

// BOOT_MODE_ flags indicate where we are booting from
#define BOOT_MODE_NAND          0x00000001
#define BOOT_MODE_NOR_AMD       0x00000002
#define BOOT_MODE_NOR_STRATA    0x00000004
#define BOOT_MODE_TEST          0x00000008
#define BOOT_MODE_MASK(dw)     (0x0000000F & (dw))

// BOOT_TYPE_ flags indicate whether we are booting directly off media, or downloading an image
#define BOOT_TYPE_DIRECT        0x00000010  // boot off media?
#define BOOT_TYPE_MULTISTAGE    0x00000020  // multi-stage bootloaders?
#define BOOT_TYPE_MASK(dw)     (0x000000F0 & (dw))

// TARGET_TYPE_ flags indicate where the image is to be written to.
#define TARGET_TYPE_RAMIMAGE    0x00000100  // Directly to SDRAM
#define TARGET_TYPE_CACHE       0x00000200  // FLASH_CACHE
#define TARGET_TYPE_NOR         0x00000400  // NOR Flash
#define TARGET_TYPE_NAND        0x00000800  // NAND Flash
//...
#define TARGET_TYPE_MASK(dw)   (0x00000F00 & (dw))

#if 1 // add by shin..for SubEboot.. 1024
#define BOOT_OPTION_CLEAN	0x00004000
#if USE_SERIAL_MESSAGE
#define CONFIG_FLAGS_SERIALMSG	(0x00008000)
#endif  // USE_SERIAL_MESSAGE
#define CONFIG_RESET_BY_DL	(0x00010000)
#define CONFIG_USB_FULLSPD	(0x00020000)
#endif

#define CONFIG_FLAGS_DHCP       0x00001000
#define CONFIG_FLAGS_DEBUGGER   0x00002000
#define CONFIG_FLAGS_MASK(dw)  (0x0000F000 & (dw))
#define CONFIG_FLAGS_KITL		0x00008000

#define CONFIG_BOOTDELAY_DEFAULT       5
#define EBOOT_CFG_MAGIC_NUMBER  0x07020317

//
// Bootloader configuration parameters.
//
typedef struct _BOOTCFG {
    //---------------------------
    // BOOTCFG Header
    DWORD       ConfigMagicNumber;
    ULONG       ConfigFlags;

    //---------------------------
    // Reset/Booting Type
    BOOL        bCleanBoot;
    DWORD       fUpdateMode;
    BOOL        bKITLBoot;
    OAL_KITL_TYPE KITLType;
    
    //---------------------------
    // Bootdelay    
    ULONG       BootDelay;

    //---------------------------
    // Ethernet
    EDBG_ADDR   EdbgAddr;
    ULONG       SubnetMask;

    //---------------------------
    // Messages
    BOOL        bUARTPathPDA; 
    BOOL        bNoSerialMSG;
    BOOL        bUseOALLOG;
    BOOL        bUseDRVMSG;
    DWORD dwLogMask;
    DWORD       dwDrvMsgMask[DRVLOG_PART_NUM];
    
    // Clock Change Infomation
    SYSTEM_CLOCK   Clock_Info;
    BOOL        bDVFSDisable;
} BOOT_CFG, *PBOOT_CFG;


//
// On disk structures for NAND bootloaders...
//

//
// OEM Reserved (Nand) Blocks for TOC and various bootloaders
//
#define IMAGE_STEPLOADER_SIZE       (IMAGE_NBL1_SIZE)    //< S3C6410 support 8kbytes Steppingstone

// NAND Boot (loads into SteppingStone) @ Block 0
#define NBOOT_BLOCK                 0
#define NBOOT_BLOCK_SIZE            1
#define NBOOT_SECTOR                BLOCK_TO_SECTOR(NBOOT_BLOCK)

// Eboot @ Block 1
#define EBOOT_BLOCK                 1
#define EBOOT_SECTOR_SIZE           FILE_TO_SECTOR_SIZE(EBOOT_RAM_IMAGE_SIZE)
#define EBOOT_BLOCK_SIZE            SECTOR_TO_BLOCK(EBOOT_SECTOR_SIZE)
#define EBOOT_SECTOR                BLOCK_TO_SECTOR(EBOOT_BLOCK)


// TOC @ Block 5
#define TOC_BLOCK                   (EBOOT_BLOCK+EBOOT_BLOCK_SIZE)
#define TOC_BLOCK_SIZE              1
#define TOC_SECTOR                  BLOCK_TO_SECTOR(TOC_BLOCK)




#if 1  //added by terry for logo 800*480   2BLOCK  20120618

#define LOGO_BLOCK					(TOC_BLOCK+TOC_BLOCK_SIZE)
#define LOGO_BLOCK_SIZE				8
#define LGOO_SECTOR_SIZE			 BLOCK_TO_SECTOR(LOGO_BLOCK_SIZE)	

#define RESERVED_BOOT_BLOCKS        (NBOOT_BLOCK_SIZE + TOC_BLOCK_SIZE + EBOOT_BLOCK_SIZE+LOGO_BLOCK_SIZE)
#else

#define RESERVED_BOOT_BLOCKS        (NBOOT_BLOCK_SIZE + TOC_BLOCK_SIZE + EBOOT_BLOCK_SIZE)

#endif



// Images start after OEM Reserved Blocks
#define IMAGE_START_BLOCK           RESERVED_BOOT_BLOCKS
#define IMAGE_START_SECTOR          BLOCK_TO_SECTOR(IMAGE_START_BLOCK)


//added by terry for logo 20120618
#define IMAGE_TYPE_LOGO              0x00000010



// Image types
#define IMAGE_TYPE_UNKNOWN              0x00000000
#define IMAGE_TYPE_IPL                  0x00008000
#define IMAGE_TYPE_EBOOT                0x00000001
#define IMAGE_TYPE_BOOTIMAGE			0x00000004
#define IMAGE_TYPE_NK                   0x00000008      // nk.bin / chain.lst..
#define IMAGE_TYPE_DIOBIN               0x00000800      // FLASH.bin
#define IMAGE_TYPE_BOOTSCREEN           0x00001000      // Boot-screen image
#define IMAGE_TYPE_BLOCK0IMG            0x00002000      // Block 0 image (BL1 + BL2)
#define IMAGE_TYPE_SUPERIPL             0x00004000      // SuperIPL image (BL1 + BL2 + IPL)
// not implemented yet
#define IMAGE_TYPE_STEPLDR              0x00000080
#define IMAGE_TYPE_DIO                  0x00000200 
#define IMAGE_TYPE_DIONB0               0x00000400
#define IMAGE_TYPE_ULDR                 0x00000100





//
// OEM Defined TOC...
//
#define MAX_SG_SECTORS              14
#define IMAGE_STRING_LEN            16  // chars

#define MAX_TOC_DESCRIPTORS             5
#define TOC_SIGNATURE               0x434F544E  // (NAND TOC)

#define TOC_ENTRY_EBOOT                 0
#define TOC_ENTRY_IPL                   1
#define TOC_ENTRY_BOOTSCREEN            2
#define TOC_ENTRY_NK                    3
#define TOC_ENTRY_FLASHBIN              4


// IMAGE_DESCRIPTOR signatures
#define IMAGE_EBOOT_SIG                 0x544F4245          // "TOBE", EBOOT
#define IMAGE_IPL_SIG                   0x004C5049          // " LPI", IPL
#define IMAGE_SXIP_SIG                  0x48534643          // "PIXS", NK.BIN       Single-XIP
#define IMAGE_MXIP_SIG                  0x5049584D          // "PIXM", chain.lst    Multiple-XIP                        
#define IMAGE_DIOBIN_SIG                0x48534C46          // "HSLF", FLASH.BIN
#define IMAGE_BOOTSCREEN_SIG            0x52435342          // "RCSB", BOOTSCREEN



// Default image descriptor to load.
// We store Eboot as image 0, nk.nb0 as image 1
#define DEFAULT_IMAGE_DESCRIPTOR    1



// SG_SECTOR: supports chained (scatter gather) sectors.
// This structure equates to a sector-based MXIP RegionInfo in blcommon.
//
typedef struct _SG_SECTOR {

    DWORD dwSector;     // Starting sector of the image segment
    DWORD dwLength;     // Image length of this segment, in contigious sectors.

} SG_SECTOR, *PSG_SECTOR;


// IMAGE_DESCRIPTOR: describes the image to load.
// The image can be anything: bootloaders, RAMIMAGE, MXIP, ...
// Note: Our NAND uses H/W ECC, so no checksum needed.
//
typedef struct _IMAGE_DESCRIPTOR {

    // File version info
    DWORD dwVersion;                    // e.g: build number
    DWORD dwSignature;                  // e.g: "EBOT", "CFSH", etc
    UCHAR ucString[MAX_PATH];   // e.g: "PocketPC_2002"

    DWORD dwImageType;      // IMAGE_TYPE_ flags
    DWORD dwTtlSectors;     // TTL image size in sectors.
                            // We store size in sectors instead of bytes
                            // to simplify sector reads in Nboot.

    DWORD dwLoadAddress;    // Virtual address to load image (ImageStart)
    DWORD dwJumpAddress;    // Virtual address to jump (StartAddress/LaunchAddr)

    // This array equates to a sector-based MXIP MultiBINInfo in blcommon.
    // Unused entries are zeroed.
    // You could chain image descriptors if needed.
    SG_SECTOR sgList[MAX_SG_SECTORS];

    // BinFS support to load nk region only
	//struct
	//{
		ULONG dwStoreOffset;    // byte offset - not needed - remove!
		//ULONG RunAddress;     // nk dwRegionStart address
		//ULONG Length;         // nk dwRegionLength in bytes
		//ULONG LaunchAddress;  // nk dwLaunchAddr
	//} NKRegion;

} IMAGE_DESCRIPTOR, *PIMAGE_DESCRIPTOR;



__inline BOOL VALID_IMAGE_DESCRIPTOR(PIMAGE_DESCRIPTOR pid) {
    return ( (pid) &&
		((IMAGE_EBOOT_SIG == (pid)->dwSignature) ||
		(IMAGE_SXIP_SIG == (pid)->dwSignature) ||
		(IMAGE_MXIP_SIG == (pid)->dwSignature)));
}

//  This is for MXIP chain.bin, which needs to be loaded into the SDRAM
//  during the start up.
typedef struct _CHAININFO {

    DWORD   dwLoadAddress;          // Load address in SDRAM
    DWORD   dwFlashAddress;         // Start location on the NAND
    DWORD   dwLength;               // The length of the image
} CHAININFO, *PCHAININFO;

//
// TOC: Table Of Contents, OEM on disk structure.
// sizeof(TOC) = NAND_SECTOR_SIZE.
// Consider the g_TOC_BLOCK to contain an array of PAGES_PER_BLOCK
// TOC entries, since the entire block is reserved.
//
typedef struct _TOC {
    DWORD               dwSignature;
    // How to boot the images in this TOC.
    // This could be moved into the image descriptor if desired,
    // but I prefer to conserve space.
    BOOT_CFG            BootCfg;

    // Array of Image Descriptors.
    IMAGE_DESCRIPTOR    id[MAX_TOC_DESCRIPTORS];

    CHAININFO           chainInfo;
} TOC, *PTOC;           // NAND_SECTOR_SIZE

__inline BOOL VALID_TOC(PTOC ptoc) {
    return ((ptoc) &&  (TOC_SIGNATURE == (ptoc)->dwSignature));
}


// Halt function
#ifndef SPIN_FOREVER
// do not optimize this
#pragma optimize("", off)
#define SPIN_FOREVER        while(1)
#pragma optimize("", on)
#endif


// Loader function prototypes.
//
int     OEMReadDebugByte(void);
BOOL    OEMVerifyMemory( DWORD dwStartAddr, DWORD dwLength );
void    OEMMultiBINNotify(const PMultiBINInfo pInfo);
PVOID   GetKernelExtPointer(DWORD dwRegionStart, DWORD dwRegionLength);
void    Launch(DWORD dwLaunchAddr);

BOOL    WriteRawImageToBootMedia(DWORD dwImageStart, DWORD dwImageLength, DWORD dwLaunchAddr);

BOOL	TOC_Init(void);
BOOL    TOC_Read(void);
BOOL    TOC_Write(void);
void    TOC_Print(void);

BOOL    PocketStoreInitialize(void);
BOOL    PocketStoreIII_STL_Format(UINT32 nPartID);
void    EraseBMLPartition(UINT32 partID);
void    FlashRePartition(BOOL UpdateFSRPI, BOOL bFormatOpt);
void    DumpFSRPI();
BOOL    ReadIPL();

BOOL LoadNK();
BOOL WriteFlashNK(DWORD dwStartAddr, DWORD dwLength);

#endif  // _LOADER_H_.
