📄 flash.c
字号:
//
// 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.
//
//------------------------------------------------------------------------------
//
// File: flash.c
//
// Flash routines for the Intel Mainstone II bootloader.
//
#include <windows.h>
#include <mainstoneii.h>
#include <oal_memory.h>
#include <fmd.h>
#include "loader.h"
// Defines.
//
#define FLASH_DEVICE_ID_L18_MIN 0x880C
#define FLASH_DEVICE_ID_L18_MAX 0x8810
#define FLASH_DEVICE_ID_L30_MIN 0x8812
#define FLASH_DEVICE_ID_L30_MAX 0x8815
#define FLASH_DEVICE_ID_K3_MIN 0x8801
#define FLASH_DEVICE_ID_K3_MAX 0x8803
#define FLASH_DEVICE_ID_K18_MIN 0x8805
#define FLASH_DEVICE_ID_K18_MAX 0x8807
#define FLASH_DEVICE_ID_J3_MIN 0x0016
#define FLASH_DEVICE_ID_J3_MAX 0x0018
#define FLASH_DEVICE_ID_P30_MIN 0x881a
#define FLASH_DEVICE_ID_P30_MAX 0x891c
// Type definitions.
//
#define FIOW UINT16 // flash io width
typedef enum _FLASH_BLOCK_ARRAY_TYPE_
{
CONSTANT_SIZE,
BOTTOM_PARAMETER,
TOP_PARAMETER
} FLASH_BLOCK_ARRAY_TYPE, *PFLASH_BLOC_ARRAY_TYPE;
typedef enum _FLASH_DEVICE_TYPE_
{
NONE,
L18,
L30,
K3,
K18,
J3,
P30
} FLASH_DEVICE_TYPE, *PFLASH_DEVICE_TYPE;
// Local variables.
//
static FLASH_BLOCK_ARRAY_TYPE g_BlockArrayType = CONSTANT_SIZE;
static FLASH_DEVICE_TYPE g_FlashDeviceType = NONE;
//#ifdef MCPII_MODULE
//static UINT32 FLASH_SIZE = 0x04000000; // 64MB.
//static UINT32 ERASE_BLOCKS = 256; // Total number of blocks (hiding parameter blocks).
//#else
static UINT32 FLASH_SIZE = 0x02000000; // 32MB.
static UINT32 ERASE_BLOCKS = 256; // Total number of blocks (hiding parameter blocks).
//#endif
static UINT32 L3_BLOCK_SIZE = 0x10000; // 64KB per block on L3 (blocks 0 - 3).
// Global variables.
//
extern IMAGE_TYPE g_ImageType;
extern UINT16 g_UniqueDeviceID[4];
//------------------------------------------------------------------------------
//
// Function: OEMIsFlashAddr
//
// Checks the virtual address provided and determines if it's a flash address or not.
//
BOOL OEMIsFlashAddr(DWORD dwAddr)
{
DWORD dwPhysAddr = (DWORD) OALVAtoPA((void*) dwAddr);
if ((dwPhysAddr >= MAINSTONEII_BASE_PA_BOOT_FLASH) && (dwPhysAddr < (MAINSTONEII_BASE_PA_BOOT_FLASH + MAINSTONEII_SIZE_BOOT_FLASH )))
{
return(TRUE);
}
return(FALSE);
}
//------------------------------------------------------------------------------
//
// Function: OEMMapMemAddr
//
// Maps a flash address to a RAM address (used when temporarily caching a
// flash-destined download image to RAM).
//
LPBYTE OEMMapMemAddr (DWORD dwImageStart, DWORD dwAddr)
{
if (OEMIsFlashAddr(dwAddr))
{
// The image being downloaded is a flash image - temporarily
// cache the image in RAM until it's completely downloaded.
//
dwAddr -= dwImageStart;
dwAddr += 0x80100000;
}
return((LPBYTE) (dwAddr));
}
//------------------------------------------------------------------------------
//
// Function: OEMStartEraseFlash
//
// Begins the flash erase procedure.
//
BOOL OEMStartEraseFlash (DWORD dwStartAddr, DWORD dwLength)
{
return(TRUE);
}
//------------------------------------------------------------------------------
//
// Function: main
//
// Continues the flash erase procedure (erases are incrementally done during
// download to speed up the overall flash operation from the user's perspective).
//
void OEMContinueEraseFlash(void)
{
}
//------------------------------------------------------------------------------
//
// Function: OEMFinishEraseFlash
//
// Finished the flash erase procedure.
//
BOOL OEMFinishEraseFlash(void)
{
return(TRUE);
}
BOOL OEMWriteFlash(DWORD dwImageStart, DWORD dwImageLength)
{
BOOL retVal = FALSE;
UINT8 *pDataBuffer = (UINT8 *) OEMMapMemAddr(dwImageStart, dwImageStart);
// FlashWrite uses virtual uncached addresses
// dwImageStart could be either virtual uncached (eboot.bin) or virtual cached (nk.bin)
dwImageStart = (DWORD) OALCAtoUA(dwImageStart);
retVal = FlashWrite(dwImageStart, pDataBuffer, dwImageLength);
// If we just wrote the bootloader to flash, halt and require the system to be rebooted.
if (g_ImageType == IMAGE_TYPE_BOOTLOADER)
{
KITLOutputDebugString("INFO: bootloader image stored successfully.\r\n");
KITLOutputDebugString("Reboot the system manually. ");
SpinForever();
}
return(retVal);
}
// START: these routines will be replaced by the FMD when it's done.
static FLASH_DEVICE_TYPE DetectFlashDevice(UINT32 FlashBaseAddress)
{
UINT32 nDeviceID = 0;
volatile FIOW *pFlash = (volatile FIOW *)(FlashBaseAddress);
// Get the flash part ID.
//
*pFlash = (FIOW) 0x00900090;
nDeviceID = (*(pFlash + 1) & 0xFFFF);
// Get the flash part Unique ID and store for later use
g_UniqueDeviceID[0] = *(pFlash + 0x81);
g_UniqueDeviceID[1] = *(pFlash + 0x82);
g_UniqueDeviceID[2] = *(pFlash + 0x83);
g_UniqueDeviceID[3] = *(pFlash + 0x84);
// Put the flash part in read array mode.
//
*pFlash = (FIOW) 0x00FF00FF;
if ((nDeviceID >= FLASH_DEVICE_ID_L18_MIN) && (nDeviceID <= FLASH_DEVICE_ID_L18_MAX))
{
//KITLOutputDebugString("INFO: DetectFlashDevice: flash type is L18.\r\n");
return(L18);
}
if ((nDeviceID >= FLASH_DEVICE_ID_L30_MIN) && (nDeviceID <= FLASH_DEVICE_ID_L30_MAX))
{
//KITLOutputDebugString("INFO: DetectFlashDevice: flash type is L30.\r\n");
return(L30);
}
if ((nDeviceID >= FLASH_DEVICE_ID_K3_MIN) && (nDeviceID <= FLASH_DEVICE_ID_K3_MAX))
{
//KITLOutputDebugString("INFO: DetectFlashDevice: flash type is K3.\r\n");
return(K3);
}
if ((nDeviceID >= FLASH_DEVICE_ID_K18_MIN) && (nDeviceID <= FLASH_DEVICE_ID_K18_MAX))
{
//KITLOutputDebugString("INFO: DetectFlashDevice: flash type is K18.\r\n");
return(K18);
}
if ((nDeviceID >= FLASH_DEVICE_ID_J3_MIN) && (nDeviceID <= FLASH_DEVICE_ID_J3_MAX))
{
//KITLOutputDebugString("INFO: DetectFlashDevice: flash type is J3.\r\n");
return(J3);
}
if ((nDeviceID >= FLASH_DEVICE_ID_P30_MIN) && (nDeviceID <= FLASH_DEVICE_ID_P30_MAX))
{
// KITLOutputDebugString("INFO: DetectFlashDevice: flash type is P30.\r\n");
return(P30);
}
KITLOutputDebugString("INFO: DetectFlashDevice: flash type is undetermined.\r\n");
return(NONE);
}
static BOOL FlashErase(UINT32 FlashStart, UINT32 FlashLength)
{
UINT32 j;
UINT32 num_blocks;
UINT32 num_blocks_to_erase;
UINT32 num_l3_blocks_to_erase = 0;
UINT32 num_l3_blocks_erased;
UINT32 flash_start_address = (UINT32) OALPAtoVA(MAINSTONEII_BASE_PA_BOOT_FLASH, FALSE);
volatile FIOW *pFlash;
FIOW status;
UINT32 BLOCK_SIZE = (FLASH_SIZE / ERASE_BLOCKS);
// Make sure we know what kind of flash part we have.
//
if (g_FlashDeviceType == NONE)
{
KITLOutputDebugString("ERROR: FlashErase: unrecognized flash part.\r\n");
return(FALSE);
}
FlashStart = (UINT32) OALCAtoUA(FlashStart);
// Determine the number of blocks to erase.
num_blocks = (FlashLength / (BLOCK_SIZE));
if (FlashLength % (BLOCK_SIZE))
{
num_blocks++;
}
if (num_blocks < 1)
{
num_blocks = 1;
KITLOutputDebugString("WARNING: FlashErase: calculation error. Erase blocks = %d\n\r", num_blocks);
}
else if (num_blocks > ERASE_BLOCKS)
{
num_blocks = ERASE_BLOCKS;
KITLOutputDebugString("WARNING: FlashErase: calculation error. Erase blocks = %d\n\r", num_blocks);
}
// If flash, need to change block count based on if we're in the first 4 blocks
// as the first 4 blocks are 16KWords (vs. 64KWords/block)
if ((g_FlashDeviceType == L18) || (g_FlashDeviceType == L30))
{
// Is start address within the first 4 blocks. As there are 2 devices in parallel,
// are we within the first 128KWords (2 x 64KWords)? If so, we need to account for
// increased number of blocks - which is the first 256K of addy range
if ((FlashStart >= flash_start_address) && (FlashStart < (flash_start_address + 0x40000)))
{
// If we're within the first 128K words (256K), we need to treat the block as a special case
num_l3_blocks_to_erase = 4;
num_blocks--; // Decrease the num_blocks count, as it assumes the first block is 64K
// Now add the # of L3 blocks to the # blocks calc.'ed at the beginning to get total
// # of blocks to erase on a given L3 device INCLUDING the first 4 16kWord blocks
num_blocks = num_blocks + num_l3_blocks_to_erase;
}
}
pFlash = (volatile FIOW *)(FlashStart);
// Issue the clear lock bits and confirm command.
if (g_FlashDeviceType == J3)
{
// For J3 FLASH, unlock all blocks at once with one command
num_blocks_to_erase = 1;
}
else if ((g_FlashDeviceType == K3) || (g_FlashDeviceType == K18)||
(g_FlashDeviceType == L18) || (g_FlashDeviceType == L30) || (g_FlashDeviceType == P30))
{
// For K3/K18 FLASH, unlock individual blocks one at a time
num_blocks_to_erase = num_blocks;
}
// For L3, need to set for use within the FOR loop
num_l3_blocks_erased = num_l3_blocks_to_erase;
for (j = 0; j < num_blocks_to_erase; j++)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -