//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this sample source code is subject to the terms of the Microsoft
// license agreement under which you licensed this sample source code. If
// you did not accept the terms of the license agreement, you are not
// authorized to use this sample source code. For the terms of the license,
// please see the license agreement between you and Microsoft or, if applicable,
// see the LICENSE.RTF on your install media or the root of your tools installation.
// THE SAMPLE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES.
//
#include <windows.h>
#ifdef NAND_FLASH
#include <bootarg.h>
#include <PCIReg.h>
#include <pci.h>
#include <ceddk.h>
#include <pehdr.h>
#include <bootpart.h>


#define FLASH_BASE 0x00000000
#define KSEG0_BASE 0xe0000000

#define NOT_FIXEDUP         (DWORD)-1
// Fix-up variable for total reserved area, which equals offset of the NK region in RAM
DWORD dwReservedArea = NOT_FIXEDUP;

// prototype
BOOL WriteAndVerifyFlash (DWORD dwStartAddr, LPBYTE pData, DWORD dwLength);
LPBYTE OEMMapMemAddr (DWORD dwImageStart, DWORD dwAddr);
HANDLE hBINFS =INVALID_HANDLE_VALUE;

BOOL ReadNANDStoredBootArgs(BOOT_ARGS *pBootArgs)
{
    KITLOutputDebugString("ReadNANDStoredBootArgs\r\n");
    if ( pBootArgs->NANDBootFlags == NAND_PCI_PRESENT ) { // Susscess
        HANDLE hPartition = BP_OpenPartition(-1,1,PART_BOOTSECTION,FALSE,PART_OPEN_EXISTING);
        if (hPartition!=INVALID_HANDLE_VALUE) {
            DWORD dwSize =min(SECTOR_SIZE, sizeof(BOOT_ARGS));
            if (BP_SetDataPointer(hPartition,0) && BP_ReadData(hPartition, (PBYTE)pBootArgs, dwSize))
                return TRUE;
            KITLOutputDebugString("ReadNANDStoredBootArgs : Can not Read Boot Partition Data \r\n");            
        }
        else 
            KITLOutputDebugString("ReadNANDStoredBootArgs : Can not opened Boot Partition\r\n");
    }
    KITLOutputDebugString("ReadNANDStoredBootArgs : Nand does not present\r\n");
    return FALSE;
}


BOOL WriteNANDStoredBootArgs(BOOT_ARGS * pBootArgs)
{
    KITLOutputDebugString("WriteNANDStoredBootArgs\r\n");
    if ( pBootArgs->NANDBootFlags == NAND_PCI_PRESENT ) { // Susscess
        HANDLE hPartition = BP_OpenPartition(-1,1,PART_BOOTSECTION,FALSE,PART_OPEN_ALWAYS);
        if (hPartition!=INVALID_HANDLE_VALUE) {
            DWORD dwSize =min(SECTOR_SIZE, sizeof(BOOT_ARGS));
            if (BP_SetDataPointer (hPartition,0) && BP_WriteData(hPartition, (PBYTE)pBootArgs, dwSize))
                return TRUE;
            KITLOutputDebugString("WriteNANDStoredBootArgs : Can not Write Boot Partition Data \r\n");            
        }
        else 
            KITLOutputDebugString("WriteNANDStoredBootArgs : Can not opened Boot Partition\r\n");
    }
    KITLOutputDebugString("WriteNANDStoredBootArgs : Nand does not present\r\n");
    return FALSE;
}
UCHAR uWorkingBuffer[0x9000];
BOOL FlashInit(BOOT_ARGS * pDriverGlobals)
{
    PCI_REG_INFO pciRegInfo;
    PCI_SLOT_NUMBER SlotNumber;
    KITLOutputDebugString("FlashInit\r\n");
    // Initialize the FMD flash interface and get flash information.
    //
    if (!BP_Init(uWorkingBuffer, 0x9000,NULL,NULL,&pciRegInfo)) {
        pDriverGlobals->NANDBootFlags = 0;
        KITLOutputDebugString("-FlashInit:Fails!!!!\r\n");
        return FALSE;
    }
    pDriverGlobals->NANDBootFlags    = NAND_PCI_PRESENT;
    pDriverGlobals->NANDBusNumber    =(UCHAR) pciRegInfo.Bus;
    SlotNumber.u.AsULONG = 0;
    SlotNumber.u.bits.DeviceNumber   = pciRegInfo.Device;
    SlotNumber.u.bits.FunctionNumber = pciRegInfo.Function;
    pDriverGlobals->NANDSlotNumber   = SlotNumber.u.AsULONG;
    hBINFS = INVALID_HANDLE_VALUE;

    if (dwReservedArea == NOT_FIXEDUP)
        dwReservedArea = 0;
    
    KITLOutputDebugString("-FlashInit\r\n");
    return TRUE;
}


// These functions are implemented in order to make the NAND FMD happy.
VOID
SetLastError( DWORD dwErrCode )
{
}



VOID
MmUnmapIoSpace (
    IN PVOID BaseAddress,
    IN ULONG NumberOfBytes
    )
{
}


BOOL OEMWriteFlash2 (DWORD dwStartAddr, LPBYTE pData, DWORD dwLength)
{
	BOOL fRet;

    KITLOutputDebugString("-------------------------------------------------------------------------------\r\n");

    fRet = WriteAndVerifyFlash (dwStartAddr, pData, dwLength);

    KITLOutputDebugString("-------------------------------------------------------------------------------\r\n");
    return fRet;
}


BOOL OEMWriteFlash (DWORD dwStartAddr, DWORD dwLength)
{
	LPBYTE pData = (LPBYTE)OEMMapMemAddr(dwStartAddr, dwStartAddr);
    BOOL fRet = OEMWriteFlash2 (dwStartAddr, pData, dwLength);
    return fRet;
}



/*
    @func   BOOL | FormatFlash | Called when preparing flash for a multiple-BIN download.  
	                             Erases, verifies, and writes logical sector numbers in the range to be written.
    @rdesc  TRUE returned on success and FALSE on failure.
    @comm    
    @xref   
*/
BOOL CreateBINFSPartition(DWORD dwStart, DWORD dwLength)
{
    dwStart = (dwStart & ~KSEG0_BASE) - FLASH_BASE - dwReservedArea;
    KITLOutputDebugString(" CreateBINFSPartition: Start =%x length =%len\r\n",dwStart,dwLength);
    hBINFS = BP_OpenPartition( -1,(dwStart+dwLength+SECTOR_SIZE)/SECTOR_SIZE,PART_BINFS,TRUE,PART_OPEN_ALWAYS);
    if (hBINFS == INVALID_HANDLE_VALUE ) {
        KITLOutputDebugString("CreateBINFSPartition: FIALS!!!!\r\n");
        return FALSE;
    }
    KITLOutputDebugString("-CreateBINFSPartition: \r\n");    
    return TRUE;
}
BOOL ReadNANDFlash(DWORD dwStartAddr, LPBYTE pBuffer, DWORD dwLength)
{
    KITLOutputDebugString(" ReadNANDFlash: dwStartAddr=%x,pBuffer=%x,dwLength=%x \r\n",dwStartAddr,pBuffer,dwLength);
	if (!pBuffer || dwLength == 0)
		return(FALSE);

	// Compute sector address and length.
    dwStartAddr = ((dwStartAddr & ~KSEG0_BASE) - FLASH_BASE - dwReservedArea) ;
    if (hBINFS == INVALID_HANDLE_VALUE) {
        hBINFS = BP_OpenPartition( -1,-1,PART_BINFS,TRUE,PART_OPEN_EXISTING);
    }
    if (hBINFS != INVALID_HANDLE_VALUE ) {
        return (BP_SetDataPointer(hBINFS,dwStartAddr) && BP_ReadData(hBINFS, pBuffer, dwLength));
    }
    KITLOutputDebugString(" ReadNANDFlash: FAILS!!!!!\r\n");
	return(TRUE);
}


BOOL WriteAndVerifyFlash (DWORD dwStartAddr, LPBYTE pData, DWORD dwLength)
{
    dwStartAddr = ((dwStartAddr & ~KSEG0_BASE) - FLASH_BASE - dwReservedArea) ;
    if (hBINFS == INVALID_HANDLE_VALUE) {
        hBINFS = BP_OpenPartition( -1,-1,PART_BINFS,TRUE,PART_OPEN_EXISTING);
    }
    if (hBINFS != INVALID_HANDLE_VALUE) {
        return (BP_SetDataPointer(hBINFS,dwStartAddr) && BP_WriteData(hBINFS, pData, dwLength));
    }
    KITLOutputDebugString(" ReadNANDFlash: FAILS!!!!!\r\n");
    return(FALSE);
}

BOOL CreateExtendedPartition()
{
    KITLOutputDebugString("CreateExtendedPartition\r\n");
    return (BP_OpenPartition(NEXT_FREE_LOC, USE_REMAINING_SPACE, PART_EXTENDED, TRUE, PART_OPEN_ALWAYS) != INVALID_HANDLE_VALUE);
}


#else
BOOL OEMWriteFlash (DWORD dwStartAddr, DWORD dwLength)
{
	return FALSE;
}
#endif



