📄 flash.c
字号:
//
// 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.
//
//------------------------------------------------------------------------------
//
// 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 0x880F
#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
// Type definitions.
//
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
} FLASH_DEVICE_TYPE, *PFLASH_DEVICE_TYPE;
// Local variables.
//
static FLASH_BLOCK_ARRAY_TYPE g_BlockArrayType = CONSTANT_SIZE;
static FLASH_DEVICE_TYPE g_FlashDeviceType = NONE;
static UINT32 FLASH_SIZE = (16777216 * 2); // Paired 16MB parts.
static UINT32 ERASE_BLOCKS = 128; // Total number of blocks (hiding parameter blocks).
static UINT32 L3_BLOCK_SIZE = 65536; // 64KB per block on L3 (blocks 0 - 3).
// Global variables.
//
extern IMAGE_TYPE g_ImageType;
//------------------------------------------------------------------------------
//
// Function: OEMIsFlashAddr
//
// Checks the address provided and determines if it's a flash address or not.
//
BOOL OEMIsFlashAddr(DWORD dwAddr)
{
DWORD dwVirtFlashStart = (DWORD) OALPAtoVA(MAINSTONEII_BASE_PA_BOOT_FLASH, FALSE);
if ((dwAddr >= dwVirtFlashStart) && (dwAddr <= (dwVirtFlashStart + 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;
//TODO - constant.
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);
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)
{
EdbgOutputDebugString("INFO: bootloader image stored successfully.\r\n");
EdbgOutputDebugString("Reboot the system manually. ");
SpinForever();
}
return(retVal);
}
// START: these routines will be replaced by the FMD when it's done.
// TODO - clean these routines up.
static FLASH_DEVICE_TYPE DetectFlashDevice(UINT32 FlashBaseAddress)
{
UINT32 nDeviceID = 0;
volatile UINT32 *pFlash = (volatile UINT32 *)(FlashBaseAddress);
// Get the flash part ID.
//
*pFlash = 0x00900090;
nDeviceID = (*(pFlash + 1) & 0xFFFF);
// Put the flash part in read array mode.
//
*pFlash = 0x00FF00FF;
if ((nDeviceID >= FLASH_DEVICE_ID_L18_MIN) && (nDeviceID <= FLASH_DEVICE_ID_L18_MAX))
{
//EdbgOutputDebugString("INFO: DetectFlashDevice: flash type is L18.\r\n");
return(L18);
}
if ((nDeviceID >= FLASH_DEVICE_ID_L30_MIN) && (nDeviceID <= FLASH_DEVICE_ID_L30_MAX))
{
//EdbgOutputDebugString("INFO: DetectFlashDevice: flash type is L30.\r\n");
return(L30);
}
if ((nDeviceID >= FLASH_DEVICE_ID_K3_MIN) && (nDeviceID <= FLASH_DEVICE_ID_K3_MAX))
{
//EdbgOutputDebugString("INFO: DetectFlashDevice: flash type is K3.\r\n");
return(K3);
}
if ((nDeviceID >= FLASH_DEVICE_ID_K18_MIN) && (nDeviceID <= FLASH_DEVICE_ID_K18_MAX))
{
//EdbgOutputDebugString("INFO: DetectFlashDevice: flash type is K18.\r\n");
return(K18);
}
if ((nDeviceID >= FLASH_DEVICE_ID_J3_MIN) && (nDeviceID <= FLASH_DEVICE_ID_J3_MAX))
{
//EdbgOutputDebugString("INFO: DetectFlashDevice: flash type is J3.\r\n");
return(J3);
}
EdbgOutputDebugString("INFO: DetectFlashDevice: flash type is undetermined.\r\n");
return(NONE);
}
static BOOL FlashErase(UINT32 FlashStart, UINT32 FlashLength)
{
UINT32 i,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 UINT32 *pFlash;
UINT32 status;
UINT32 BLOCK_SIZE = (FLASH_SIZE / ERASE_BLOCKS);
// Make sure we know what kind of flash part we have.
//
if (g_FlashDeviceType == NONE)
{
EdbgOutputDebugString("ERROR: FlashErase: unrecognized flash part.\r\n");
return(FALSE);
}
// 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;
EdbgOutputDebugString("WARNING: FlashErase: calculation error. Erase blocks = %d\n\r", num_blocks);
}
else if (num_blocks > 128)
{
num_blocks = 128;
EdbgOutputDebugString("WARNING: FlashErase: calculation error. Erase blocks = %d\n\r", num_blocks);
}
// If Tyax 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 UINT32 *)(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))
{
// 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++)
{
*pFlash = 0x00600060;
*pFlash = 0x00d000d0;
i = 0;
while ((i & 0x00800080) != 0x00800080)
{
i = *pFlash;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -