📄 nor.c
字号:
// Just to avoid possible problems
memset(pInfo, 0, sizeof(*pInfo));
// Make sure that we talk to uncached address
base = (UINT32)OALCAtoUA(pBase);
// Try 32-bit geometry
//OUTREG32((UINT32*)(base + 4 * 0x5555), 0xAAAAAAAA);
//OUTREG32((UINT32*)(base + 4 * 0x2AAA), 0x55555555);
OUTREG32((UINT32*)(base + 4 * 0x5555), 0x98989898);
code1 = INREG32((UINT32*)(base + 4 * 0x10));
code2 = INREG32((UINT32*)(base + 4 * 0x11));
code3 = INREG32((UINT32*)(base + 4 * 0x12));
if (code1 == 'QQQQ' && code2 == 'RRRR' && code3 == 'YYYY') {
pInfo->width = 4;
pInfo->parallel = 4;
} else if (code1 == 'Q\0Q\0' && code2 == 'R\0R\0' && code3 == 'Y\0Y\0') {
pInfo->width = 4;
pInfo->parallel = 2;
} else if (code1 == 'Q\0\0\0' && code2 == 'R\0\0\0' && code3 == 'Y\0\0\0') {
pInfo->width = 4;
pInfo->parallel = 1;
} else {
// Now try luck with 16-bit geometry
//OUTREG16((UINT16*)(base + 2 * 0x5555), 0xAAAA);
//OUTREG16((UINT16*)(base + 2 * 0x2AAA), 0x5555);
OUTREG16((UINT16*)(base + 2 * 0x5555), 0x9898);
code1 = INREG16((UINT16*)(base + 2 * 0x10));
code2 = INREG16((UINT16*)(base + 2 * 0x11));
code3 = INREG16((UINT16*)(base + 2 * 0x12));
if (code1 == 'QQ' && code2 == 'RR' && code3 == 'YY') {
pInfo->width = 2;
pInfo->parallel = 2;
} else if (code1 == '\0Q' && code2 == '\0R' && code3 == '\0Y') {
pInfo->width = 2;
pInfo->parallel = 1;
} else {
// So last oppurtinity is 8-bit mode
//OUTREG8((UINT8*)(base + 0x5555), 0xAA);
//OUTREG8((UINT8*)(base + 0x2AAA), 0x55);
OUTREG8((UINT8*)(base + 0x5555), 0x98);
code1 = INREG8((UINT8*)(base + 0x10));
code2 = INREG8((UINT8*)(base + 0x11));
code3 = INREG8((UINT8*)(base + 0x12));
if (code1 == 'Q' && code2 == 'R' && code3 == 'Y') {
pInfo->width = 1;
pInfo->parallel = 1;
} else {
goto cleanUp;
}
}
}
// Read primary command set, size, burst size and number of regions
pInfo->set = ReadInfo(base, 0x13, 2, pInfo->width);
pInfo->size = 1 << ReadInfo(base, 0x27, 1, pInfo->width);
pInfo->burst = 1 << ReadInfo(base, 0x2A, 1, pInfo->width);
pInfo->regions = ReadInfo(base, 0x2C, 1, pInfo->width);
// If there is more regions than expected
if (pInfo->regions > 8) goto cleanUp;
// Read region info
for (i = 0; i < pInfo->regions; i++) {
code1 = ReadInfo(base, 0x2d + (i << 2), 4, pInfo->width);
pInfo->aBlocks[i] = (code1 & 0xFFFF) + 1;
pInfo->aBlockSize[i] = (code1 >> 8) & 0x00FFFF00;
if (pInfo->aBlockSize[i] == 0) pInfo->aBlockSize[i] = 128;
}
// Switch back to read mode
switch (pInfo->set) {
case 1: // Intel/Sharp
case 3: // New Intel parts
WriteCommand(base, 0, 0xFF, pInfo->width, pInfo->parallel);
break;
case 2: // AMD/Fujitsu
case 0x0701: // SST
WriteCommand(base, 0, 0xF0, pInfo->width, pInfo->parallel);
break;
}
rc = TRUE;
cleanUp:
OALMSG(OAL_FUNC, (L"-OALFlashInfo(rc = %d)\r\n", rc));
return rc;
}
//------------------------------------------------------------------------------
BOOL OALFlashErase(VOID *pBase, VOID *pStart, UINT32 size)
{
BOOL rc = FALSE;
OAL_FLASH_INFO info;
UINT32 base, start, end, chip, block;
UINT32 ixReg, ixBlock;
OALMSG(OAL_FUNC, (
L"+OALFlashErase(0x%08x, 0x%08x, 0x%08x)\r\n", pBase, pStart, size
));
// Erase must work from uncached memory
base = (UINT32)OALCAtoUA(pBase);
start = (UINT32)OALCAtoUA(pStart);
// First get end address
end = start + size;
// Ther read first chip info
if (!OALFlashInfo((VOID*)base, &info)) {
OALMSG(OAL_ERROR, (
L"ERROR: OALFlashErase failed get flash memory info\r\n"
));
goto cleanUp;
}
ixReg = ixBlock = 0;
block = chip = base;
while (block < end) {
// Should block be erased?
if (
start < (block + info.aBlockSize[ixReg] * info.parallel) &&
end >= block
) {
switch (info.set) {
case 1: // Intel/Sharp
case 3: // New Intel parts
if (!UnlockBlock1(chip, block, &info)) {
goto cleanUp;
}
if (!EraseBlock1(chip, block, &info)) {
goto cleanUp;
}
break;
case 2: // AMD
case 0x0701: // SST
if (!EraseBlock2(chip, block, &info)) {
goto cleanUp;
}
break;
default:
OALMSG(OAL_ERROR, (
L"ERROR: Flash type %d isn't supported\r\n", info.set
));
goto cleanUp;
}
}
// Move to next block
block += info.aBlockSize[ixReg] * info.parallel;
if (block >= end) break;
if (++ixBlock >= info.aBlocks[ixReg]) {
ixBlock = 0;
if (++ixReg >= info.regions) {
// Try read next chip info
if (!OALFlashInfo((VOID*)block, &info)) break;
ixReg = 0;
chip = block;
}
}
}
rc = TRUE;
cleanUp:
OALMSG(OAL_FUNC, (L"-OALFlashErase(rc = %d)\r\n", rc));
return rc;
}
//------------------------------------------------------------------------------
BOOL OALFlashWrite(VOID *pBase, VOID *pStart, UINT32 size, VOID *pBuffer)
{
BOOL rc = FALSE;
OAL_FLASH_INFO info;
UINT32 base, start, end, chip, pos, count;
UINT8 *pPos;
OALMSG(OAL_FUNC, (
L"+OALFlashWrite(0x%08x, 0x%08x, 0x%08x, 0x%08x)\r\n",
pBase, pStart, size, pBuffer
));
// Flash must work from uncached memory
base = (UINT32)OALCAtoUA(pBase);
start = (UINT32)OALCAtoUA(pStart);
// First get end address
end = start + size;
chip = base;
pPos = (UINT8*)pBuffer;
// First read first chip info
while (TRUE) {
if (!OALFlashInfo((VOID*)chip, &info)) {
OALMSG(OAL_ERROR, (
L"ERROR: OALFlashWrite - failed get flash info at 0x%08x\r\n",
chip
));
goto cleanUp;
}
// Is start address on this chip
if (start >= chip && start < (chip + info.size * info.parallel)) break;
// Move to next chip
chip += info.size * info.parallel;
}
pos = start;
while (pos < end) {
// Program data chunk
switch (info.set) {
case 1:
case 3:
count = WriteData1(chip, pos, &info, pPos);
break;
case 2:
case 0x0701: // SST
count = WriteData2(chip, pos, &info, pPos);
break;
default:
OALMSG(OAL_ERROR, (
L"ERROR: Flash type %d isn't supported\r\n", info.set
));
goto cleanUp;
}
// If we write nothing some problem happen
if (count == 0) {
rc = FALSE;
OALMSG(OAL_ERROR, (
L"ERROR: Flash write at 0x%08x failed\r\n", pos
));
goto cleanUp;
}
// Move position
pos += count;
pPos += count;
// If we run out of chip move to next one
if (pos > (chip + info.size * info.parallel)) {
switch (info.set) {
case 1:
case 3:
WriteCommand(chip, 0, 0xFF, info.width, info.parallel);
break;
case 2:
WriteCommand(chip, 0, 0xF0, info.width, info.parallel);
break;
}
chip += info.size * info.parallel;
if (!OALFlashInfo((VOID*)chip, &info)) break;
}
}
switch (info.set) {
case 1:
case 3:
WriteCommand(chip, 0, 0xFF, info.width, info.parallel);
break;
case 2:
case 0x0701: // SST
WriteCommand(chip, 0, 0xF0, info.width, info.parallel);
break;
}
// Do final check
pPos = (UINT8*)pBuffer;
for (pos = start; pos < end - sizeof(UINT32) + 1; pos += sizeof(UINT32)) {
if (*(UINT32*)pPos != *(UINT32*)pos) break;
pPos += sizeof(UINT32);
}
// If we reach end, all is ok
rc = (pos >= end - sizeof(UINT32) + 1);
OALMSG(!rc&&OAL_ERROR, (
L"ERROR: Flash failed at 0x%08x -- write 0x%08x, but read 0x%08x\r\n",
pos, *(UINT32*)pPos, *(UINT32*)pos
));
cleanUp:
OALMSG(OAL_FUNC, (L"-OALFlashWrite(rc = %d)", rc));
return rc;
}
//------------------------------------------------------------------------------
BOOL OALFlashIdentifier(VOID *pBase, BYTE* pIdent, DWORD* pdwSize)
{
BOOL rc = FALSE;
OAL_FLASH_INFO info;
UINT32 base;
OALMSG(OAL_FUNC, (L"+OALFlashIdentifier(0x%08x, ...)\r\n", pBase));
if (pdwSize == NULL || *pdwSize == 0)
{
goto cleanUp;
}
// Make sure that we talk to uncached address
base = (UINT32)OALCAtoUA(pBase);
if (pIdent == NULL)
goto cleanUp;
if (!OALFlashInfo((VOID*)base, &info)) {
OALMSG(OAL_ERROR, (
L"ERROR: OALFlashIdentifier - failed get flash info at 0x%08x\r\n",
base
));
goto cleanUp;
}
// TODO: This works for Intel parts. How about others?
switch (info.set) {
case 1:
case 3:
if (*pdwSize < 8 * info.parallel)
goto cleanUp;
*pdwSize = 8 * info.parallel;
// read 8 bytes of protection register from each chip into pIdent buffer
rc = ReadIdent1(base, base, &info, pIdent, *pdwSize);
break;
case 2:
*pdwSize = 0; // I'm unaware of any chips with set=2 which have an ident
break;
default:
rc = FALSE;
}
cleanUp:
OALMSG(OAL_FUNC, (L"-OALFlashIdentifier(rc = %d)\r\n", rc));
return rc;
}
//------------------------------------------------------------------------------
//
// Function: NORLoadEBootCFG
//
// Retrieves bootloader configuration information (menu settings, etc.) from
// the NOR flash.
//
// Parameters:
// eBootCFG
// [out] Points to bootloader configuration that will be filled with
// loaded data.
//
// cbBootCfgSize
// [in] Size in bytes of the bootloader configuration.
//
// Returns:
// TRUE indicates success. FALSE indicates failure.
//
//-----------------------------------------------------------------------------
BOOL NORLoadEBootCFG(BYTE *pBootCfg, DWORD cbBootCfgSize)
{
VOID *pStart = (VOID *) OALPAtoUA(IMAGE_BOOT_BOOTCFG_NOR_PA_START);
KITLOutputDebugString("INFO: Reading boot configuaration in NOR flash (addr = 0x%x, size = 0x%x)\r\n",
pStart, cbBootCfgSize);
if (!pBootCfg) return FALSE;
memcpy((VOID *) pBootCfg, pStart, cbBootCfgSize);
KITLOutputDebugString("INORLoadEBootCFG end!\r\n");
return TRUE;
}
//------------------------------------------------------------------------------
//
// Function: NORStoreEBootCFG
//
// Stores bootloader configuration information (menu settings, etc.) to
// the NOR flash.
//
// Parameters:
// eBootCFG
// [out] Points to bootloader configuration that will be stored.
//
// cbBootCfgSize
// [in] Size in bytes of the bootloader configuration.
//
// Returns:
// TRUE indicates success. FALSE indicates failure.
//
//-----------------------------------------------------------------------------
BOOL NORStoreEBootCFG(BYTE *pBootCfg, DWORD cbBootCfgSize)
{
BOOL rc = FALSE;
VOID *pFlashBase = (VOID *) OALPAtoUA(IMAGE_BOOT_NOR_PA_START);
VOID *pStart = (VOID *) OALPAtoUA(IMAGE_BOOT_BOOTCFG_NOR_PA_START);
KITLOutputDebugString("INFO: Storing boot configuaration in NOR flash (addr = 0x%x, size = 0x%x)\r\n",
pStart, cbBootCfgSize);
if (!OALFlashErase(pFlashBase, pStart, cbBootCfgSize))
{
KITLOutputDebugString("ERROR: OEMWriteErase failed!\r\n");
goto cleanUp;
}
if (!OALFlashWrite(pFlashBase, pStart, cbBootCfgSize, (VOID *) pBootCfg))
{
KITLOutputDebugString("ERROR: OALFlashWrite failed!\r\n");
goto cleanUp;
}
KITLOutputDebugString("INFO: Boot configuration successfully stored.\r\n");
rc = TRUE;
cleanUp:
return rc;
}
//------------------------------------------------------------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -