fmd_tyax.cpp

来自「该BSP是基于PXA270+WINCE的BSP」· C++ 代码 · 共 1,678 行 · 第 1/5 页

CPP
1,678
字号

PVOID FMD_Init(LPCTSTR lpActiveReg, PPCI_REG_INFO pRegIn, PPCI_REG_INFO pRegOut)
{
    ULONG* pBaseAddress = NULL;
    ULONG FlashLength = 0;
#ifndef UNDER_BOOTLOADER
    BOOL bLastMode;
#endif
    DWORD dwLen = sizeof(DWORD);
    struct FMDHAL_CmdStruct CurrCmd;

    DBGMSG(1, (TEXT("FMD_Init@ 0x%x:\r\n"), FMD_Init));

#ifdef READ_FROM_REGISTRY
    if (lpActiveReg != NULL)
    {
        DDKWINDOWINFO dwi;
        HKEY hConfig;

        // Get flash information from the registry.
        hConfig = OpenDeviceKey((LPCTSTR)lpActiveReg);
        if (hConfig == NULL)
        {
            LOGMSG(1, (TEXT("ERROR: FMD_Init: OpenDeviceKey failed.\r\n")));
            return(NULL);
        }
        dwi.cbSize = sizeof(dwi);
        if (DDKReg_GetWindowInfo(hConfig, &dwi) != ERROR_SUCCESS)
        {
            LOGMSG(1, (TEXT("ERROR: FMD_Init: DDKReg_GetWindowInfo() failed.\r\n")));
            return(NULL);
        }
        // The first memory window contains the base address and length of our flash part.
        if (dwi.dwNumMemWindows)
        {
            pBaseAddress = (ULONG*)(dwi.memWindows[0].dwBase);
            FlashLength  = (ULONG)(dwi.memWindows[0].dwLen);
        }

        HINSTANCE hCoreDll = LoadLibrary (TEXT("coredll.dll"));
        if (hCoreDll)
        {
            pRegQueryValueEx fnRegQueryValueEx = (pRegQueryValueEx)GetProcAddress(hCoreDll, TEXT("RegQueryValueExW"));
            if (fnRegQueryValueEx)
            {
                fnRegQueryValueEx(hConfig, L"XIPEntireFlash", 0, NULL, (LPBYTE)&g_bXIPEntire, &dwLen);
                fnRegQueryValueEx(hConfig, L"UpdateMode", 0, NULL, (LPBYTE)&g_bUpdateMode, &dwLen);
                fnRegQueryValueEx(hConfig, L"BlockSize", 0, NULL, (LPBYTE)&g_FMDInfo.BlockSize, &dwLen);
                fnRegQueryValueEx(hConfig, L"WriteBufferSize", 0, NULL, (LPBYTE)&g_dwWriteBufferSize, &dwLen);

                // new
                fnRegQueryValueEx(hConfig, L"ActualFlashBase", 0, NULL, (LPBYTE)&g_FMDInfo.ActualFlashBase, &dwLen);

                if (fnRegQueryValueEx(hConfig, L"IsPairedFlash", 0, NULL, (LPBYTE)&g_bPairedFlash, &dwLen) != ERROR_SUCCESS)
                {
                    LOGMSG(1, (TEXT("FMD_Init: Warning, IsPairedFlash not specified in registry.  Using value of 0.\r\n")));
                }

                if (fnRegQueryValueEx(hConfig, L"SectorSize", 0, NULL, (LPBYTE)&g_FMDInfo.SectorSize, &dwLen)  != ERROR_SUCCESS)
                {
                    SYSTEM_INFO SystemInfo;
                    GetSystemInfo (&SystemInfo);
                    g_FMDInfo.SectorSize = SystemInfo.dwPageSize;
                }
            }
            FreeLibrary (hCoreDll);
        }

    }
#else
    // Get flash base address and length from caller.

    DBGMSG(1, (TEXT("FMD_Init:  pMemBaseNum = %x MemLenNum = %x \r\n"), pRegIn->MemBase.Num, pRegIn->MemLen.Num));
    DBGMSG(1, (TEXT("FMD_Init:  pMemBaseREG = %x MemLenNum = %x \r\n"), pRegIn->MemBase.Reg[0], pRegIn->MemLen.Num));

    //if (!pRegIn || !pRegIn->MemLen.Num)           // Use this line for Eboot FMD testing - MemLen.Num is arriving as 0 in eboot
    if (!pRegIn || !pRegIn->MemBase.Num || !pRegIn->MemLen.Num)
    {
        LOGMSG(1, (TEXT("ERROR: FMD_Init: invalid flash memory base and/or length specified by caller.\r\n")));
        return(NULL);
    } else
    {
        pBaseAddress = (ULONG*)pRegIn->MemBase.Reg[0];
        FlashLength  = pRegIn->MemLen.Reg[0];
        g_FMDInfo.ActualFlashBase = pRegIn->IoBase.Reg[0];      // the KVA of the base address of Flash

        DBGMSG(1, (TEXT("FMD_Init:  pBaseAddress = %x IO = %x \r\n"), pBaseAddress   ,g_FMDInfo.ActualFlashBase));

        // Temporary work-arounds for the bootloader
        if (!g_FMDInfo.SectorSize)
        {
            g_FMDInfo.SectorSize = 4 * 1024;
        }
    }
#endif    // READ_FROM_REGISTRY.


#ifndef UNDER_BOOTLOADER
    DBGMSG(1,(TEXT("FMD_Init: ->SetKMode\r\n")));

    // Run in kernel mode.
    bLastMode = SetKMode(TRUE);
    /*    // Make a RAM copy of the flash init code in case this driver is executing directly from the flash part
        //
        DWORD codeSize = (DWORD)UserKInfo[KINX_PAGESIZE]; // Copy 1 page of code, should be sufficient to contain InitializeFlash() funciton
        BOOL (*pfnInitializeFlash)(volatile ULONG*, ULONG) = (BOOL (*)(volatile ULONG*, ULONG))VirtualAlloc(NULL, 0, MEM_COMMIT, PAGE_READWRITE);
        if (!pfnInitializeFlash)
        {
            DEBUGMSG(1, (TEXT("ERROR: FMD_Init: Failed VirtualAlloc for InitializeFlash\r\n")));
            return(NULL);
        }


        NKDbgPrintfW(TEXT("FMD_Init:  About to set copy code to pfn\r\n"));

        // Copy the init function to RAM
        memcpy(pfnInitializeFlash, InitializeFlash, codeSize);

        // Change protection to allow execute from the RAM copy of the init function
        DWORD oldProtect;
        if (!VirtualProtect(pfnInitializeFlash, codeSize, PAGE_EXECUTE_READ, &oldProtect))
        {
            DEBUGMSG(1, (TEXT("ERROR: FMD_Init: Failed VirtualProtect for InitializeFlash\r\n")));
            return(NULL);
        }
    #else
        // Directly call the init function
        BOOL (*pfnInitializeFlash)(volatile ULONG*, ULONG) = (BOOL (*)(volatile ULONG*, ULONG))InitializeFlash;
    */
#endif

#ifdef FMD_FLASH_GLOBAL_MUTEX
    /* Initialize flash mutex */
    ghFlashMutex = CreateMutex(NULL, FALSE, TEXT("_RAMDISK_STRATAFMD_MUTEX_"));


    if (NULL == ghFlashMutex)
    {
        LOGMSG(1, (TEXT("CreateMutex failed (x%08x)\r\n"), GetLastError()));
        return(NULL);
    }
    else
    {
        DBGMSG(1, (TEXT("FMD_Init: CreateMutex OK\r\n")));
    }

#endif

    // Identify the flash part and collect device information.
    //
    CurrCmd.pTargetAddress = pBaseAddress;
    CurrCmd.uCmd = FMDHAL_CMD_INIT;

    if (!FMD_OEMIoControl(IOCTL_FMDHAL_FLASH_CMD,(PBYTE) &CurrCmd, sizeof(FMD_FLASH_INFO),
                          (PBYTE) &g_FMDInfo, sizeof(FMD_FLASH_INFO), NULL))
    {
        LOGMSG(1, (TEXT("FMD_Init: IOCTL_FMDHAL_FLASH_CMD:FMDHAL_CMD_INIT failed\r\n")));
#ifndef UNDER_BOOTLOADER
        SetKMode(bLastMode);
#endif
        return(NULL);
    }
    else
    {
        DBGMSG(1, (TEXT("FMD_Init: InitializeFlash OK\r\n")));
    }

    g_FMDInfo.FlashLength        = FlashLength;
    g_FMDInfo.SectorSize         = 4096;
    g_FMDInfo.BaseAddress        = (ULONG)pBaseAddress;
    g_FMDInfo.TotalFlashBlocks    = (FlashLength / g_FMDInfo.BlockSize);
    g_dwWriteBufferSize = g_bPairedFlash ? (1 << g_FMDInfo.Geometry.WriteBuffSize) * 2 : (1 << g_FMDInfo.Geometry.WriteBuffSize);

#ifdef DEBUG
    DumpFlashInfo();
    DumpGeometry();
#endif

    if (!DefineLayout())
    {
        LOGMSG(1, (TEXT("FMD_Init:DefineLayOut Failed\r\n")));
#ifndef UNDER_BOOTLOADER
        SetKMode(bLastMode);
#endif
        return(NULL);
    }

#ifndef UNDER_BOOTLOADER
    // Free the RAM copy of the initialization function
    //    VirtualFree(pfnInitializeFlash, 0, MEM_RELEASE);
    {
        ULONG unlock_ret;
        unlock_ret = UnlockFILESYSRegions();
        DBGMSG(1, (TEXT("FMD_Init: %u blocks in %u regions unlocked\r\n"), unlock_ret & 0xffff, unlock_ret >> 16));
    }

    // Verify that the block signatures are all intact
    if (!VerifySignatures())
    {
        LOGMSG(1, (TEXT("ERROR: FMD_Init: VerifySignatures failed\r\n")));
    }
#endif

    LOGMSG(1, (TEXT("FMD:FMD_Init: Flash Address=0x%x, Length=0x%x.\r\n"), (ULONG)pBaseAddress, FlashLength));

#ifndef UNDER_BOOTLOADER
    SetKMode(bLastMode);
#endif

    //return((PVOID) pBaseAddress);
    return((PVOID) TRUE);
}


/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function:       FMD_Deinit()

Description:    De-initializes the Flash memory device.

Returns:        Boolean indicating success.
------------------------------------------------------------------------------*/
BOOL  FMD_Deinit(PVOID pBaseAddress)
{
    DBGMSG(1, (TEXT("FMD_Deinit:\r\n")));
#ifdef FMD_FLASH_GLOBAL_MUTEX
    /* Destroy the Mutex created for the FMD */
    if ( !CloseHandle(ghFlashMutex) )
    {
        LOGMSG(1, (TEXT("FMD_Deinit: CloseHandle on FlashMutex Failed.\r\n")));
    }
#endif

    return(TRUE);
}



/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function:       FMD_GetInfo()

Description:    Determines the size characteristics for the Flash memory device.

Notes:          Notice that although each byte of a NOR Flash block is individually
                addressable, the media is still logically broken up into sectors.
                To compute the number of sectors per block, you have to divide the
                total Flash block size by the number of bytes per sector and the number
                bytes for the sector metadata.

Returns:        Boolean indicating success.
------------------------------------------------------------------------------*/
BOOL  FMD_GetInfo(PFlashInfo pFlashInfo)
{
    DBGMSG(1, (TEXT("FMD_GetInfo:\r\n")));
    pFlashInfo->flashType           = NOR;
    pFlashInfo->dwNumBlocks         = g_FMDInfo.TotalFlashBlocks;
    pFlashInfo->dwBytesPerBlock     = g_FMDInfo.BlockSize;
    pFlashInfo->wDataBytesPerSector = (WORD)g_FMDInfo.SectorSize;
    pFlashInfo->wSectorsPerBlock    = (WORD)g_pRegionTable[0].dwSectorsPerBlock;

    return(TRUE);
}

/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function:       FMD_GetInfoEx()

Description:    Determines the size characteristics for the Flash memory device.
                     Includes support for multiple regions.

Notes:          If pFlashInfo is NULL, then this just returns the number of reserved regions.

Returns:        Boolean indicating success.
------------------------------------------------------------------------------*/
BOOL  FMD_GetInfoEx(PFlashInfoEx pFlashInfo, PDWORD pdwNumRegions)
{
    DBGMSG(1, (TEXT("FMD_GetInfoEx:\r\n")));
#ifdef UNDER_BOOTLOADER
    if (g_dwNumRegions > MAX_REGIONS)
    {
        return(FALSE);
    }
#endif
    if (!pdwNumRegions)
    {
        return(FALSE);
    }

    if (!pFlashInfo)
    {
        // Return required buffer size to caller
        *pdwNumRegions = g_dwNumRegions;
        return(TRUE);
    }

    if (*pdwNumRegions < g_dwNumRegions)
    {
        *pdwNumRegions = g_dwNumRegions;
        LOGMSG (1, (TEXT("FMD_GetInfoEx: Insufficient buffer for number of regions")));
        return(FALSE);
    }

    memcpy (pFlashInfo->region, g_pRegionTable, g_dwNumRegions * sizeof(FlashRegion));

    *pdwNumRegions = g_dwNumRegions;

    pFlashInfo->cbSize                  = sizeof(FlashInfoEx);
    pFlashInfo->flashType               = NOR;
    pFlashInfo->dwNumBlocks             = g_FMDInfo.TotalFlashBlocks;
    pFlashInfo->dwDataBytesPerSector    = (WORD)g_FMDInfo.SectorSize;
    pFlashInfo->dwNumRegions            = g_dwNumRegions;

    return(TRUE);
}


/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function:       FMD_GetPhysSectorAddr()

Description:    Returns the physical address for the physical sector passed in.

Returns:        None
------------------------------------------------------------------------------*/
VOID FMD_GetPhysSectorAddr (DWORD dwSector, PSECTOR_ADDR pStartSectorAddr)
{
    GetPhysicalSectorAddress (dwSector, pStartSectorAddr, NULL, NULL);
}


/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function:       FMD_ReadSector()

Description:    Reads the requested sector data and/or sector metadata from the
                Flash media.

Notes:          Notice that although each byte of a NOR Flash block is individually
                addressable, the media is still logically broken up into sectors.
                Thus, for each sector request, we must determine where this data

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?