1877 lines
42 KiB
C
1877 lines
42 KiB
C
/*****************************************************************************
|
|
*
|
|
*
|
|
* Copyright (c) 2012 - 2015, Hefei LCFC Information Technology Co.Ltd.
|
|
* And/or its affiliates. All rights reserved.
|
|
* Hefei LCFC Information Technology Co.Ltd. PROPRIETARY/CONFIDENTIAL.
|
|
* Use is subject to license terms.
|
|
*
|
|
*****************************************************************************/
|
|
|
|
#include "EcFlashSmm.h"
|
|
#include <Library/LfcEcLib.h>
|
|
#include <LfcCmos.h>
|
|
#include <Library/CmosLib.h>
|
|
#include <Library/SeamlessRecoveryLib.h>
|
|
#include <Library/PcdLib.h>
|
|
UINT8 OldSstDevID;
|
|
UINT8 OldDevID;
|
|
|
|
UINT8 SPIDeviceID[4];
|
|
|
|
EC_ROM_HEADER LcfcECRomHeader [] = {
|
|
// ITE 8386
|
|
{
|
|
{0x45, 0x43, 0x52, 0x4F, 0x4D, 0x00, 0x00, 0x00}, // EcRomName[8]
|
|
0x01, // EcVerMajor
|
|
0x01, // EcVerMinor
|
|
0x00, // Reserved0
|
|
0x00, // Reserved1
|
|
0x00020000, // EcRomSize
|
|
ITE_8386_ID_OFFSET, // EcRomIdOffset
|
|
ITE_8386_ID // EcRomSignature
|
|
},
|
|
// ITE 8586
|
|
{
|
|
{0x45, 0x43, 0x52, 0x4F, 0x4D, 0x00, 0x00, 0x00}, // EcRomName[8]
|
|
0x01, // EcVerMajor
|
|
0x01, // EcVerMinor
|
|
0x00, // Reserved0
|
|
0x00, // Reserved1
|
|
0x00020000, // EcRomSize
|
|
ITE_8586_ID_OFFSET, // EcRomIdOffset
|
|
ITE_8586_ID // EcRomSignature
|
|
}
|
|
};
|
|
|
|
EFI_STATUS
|
|
MyAsciiToUnicodeStr (
|
|
IN CHAR8 *AsciiString,
|
|
IN CHAR16 *UnicodeString
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
Function to convert ASCII string to Unicode
|
|
|
|
Arguments:
|
|
|
|
Returns:
|
|
|
|
--*/
|
|
{
|
|
UINT8 Index;
|
|
|
|
Index = 0;
|
|
while (AsciiString[Index] != 0) {
|
|
UnicodeString[Index] = (CHAR16)AsciiString[Index];
|
|
Index++;
|
|
}
|
|
UnicodeString[Index] = 0;
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
VOID
|
|
Usage(
|
|
VOID
|
|
)
|
|
{
|
|
Print (L"Usage: \n");
|
|
Print (L" EcRead -r|w -b:EcRomSize(Unit: KByte) FileName\n");
|
|
Print (L" Example:\n");
|
|
Print (L" Reading EC ROM to file with 128K Bytes:\n");
|
|
Print (L" EcRead.efi -r -b:128 EC.ROM\n");
|
|
Print (L" Written the EC ROM from the file:\n");
|
|
Print (L" EcRead.efi -w EC.ROM\n");
|
|
return;
|
|
}
|
|
|
|
VOID
|
|
Stall (
|
|
UINTN ms
|
|
)
|
|
{
|
|
gBS->Stall (ms);
|
|
}
|
|
|
|
VOID
|
|
ShowSSTID (
|
|
VOID
|
|
)
|
|
{
|
|
Print (L"SPI Vendor : SST \n");
|
|
}
|
|
|
|
VOID
|
|
ShowWinbondID (
|
|
VOID
|
|
)
|
|
{
|
|
Print(L"SPI Vendor : Winbond \n");
|
|
}
|
|
|
|
VOID
|
|
ShowAtmelID (
|
|
VOID
|
|
)
|
|
{
|
|
Print (L"SPI Vendor : Atmel \n");
|
|
}
|
|
|
|
VOID
|
|
ShowSTID (
|
|
VOID
|
|
)
|
|
{
|
|
Print(L"SPI Vendor : ST \n");
|
|
}
|
|
|
|
VOID
|
|
ShowSpansionID (
|
|
VOID
|
|
)
|
|
{
|
|
Print (L"SPI Vendor : Spansion \n");
|
|
}
|
|
|
|
VOID
|
|
ShowMXICID (
|
|
VOID
|
|
)
|
|
{
|
|
Print (L"SPI Vendor : MXIC \n");
|
|
}
|
|
|
|
VOID
|
|
ShowAMICID (
|
|
VOID
|
|
)
|
|
{
|
|
Print (L"SPI Vendor : AMIC \n");
|
|
}
|
|
|
|
VOID
|
|
ShowEONID (
|
|
VOID
|
|
)
|
|
{
|
|
Print (L"SPI Vendor : EON \n");
|
|
}
|
|
|
|
VOID
|
|
ShowESMTID (
|
|
VOID
|
|
)
|
|
{
|
|
Print (L"SPI Vendor : ESMT \n");
|
|
}
|
|
|
|
VOID
|
|
ShowIteID (
|
|
VOID
|
|
)
|
|
{
|
|
Print (L"SPI Vendor : ITE \n");
|
|
}
|
|
|
|
FLASH_DEV_VENDOR SpiVendor[]= {
|
|
{ SSTID, ShowSSTID },
|
|
{ WINBOND_ID, ShowWinbondID },
|
|
{ ATMEL_ID, ShowAtmelID },
|
|
{ ST_ID, ShowSTID },
|
|
{ SPANSION_ID, ShowSpansionID },
|
|
{ MXIC_ID, ShowMXICID },
|
|
{ AMIC_ID, ShowAMICID },
|
|
{ EON_ID, ShowEONID },
|
|
{ ESMT_ID, ShowESMTID },
|
|
{ ITE_ID, ShowIteID },
|
|
};
|
|
//------------------------------------
|
|
// wait EC output buffer full
|
|
//------------------------------------
|
|
VOID
|
|
WaitEcObf (
|
|
VOID
|
|
)
|
|
{
|
|
while (!(IoRead8(EC_STATUS_PORT) & EC_OBF));
|
|
}
|
|
|
|
//------------------------------------
|
|
// wait EC input buffer empty
|
|
//------------------------------------
|
|
VOID
|
|
WaitEcIbe (
|
|
VOID
|
|
)
|
|
{
|
|
while (IoRead8(EC_STATUS_PORT) & EC_IBF);
|
|
}
|
|
|
|
|
|
VOID
|
|
SendEcCmd (
|
|
UINT8 EcCmd
|
|
)
|
|
{
|
|
WaitEcIbe ();
|
|
|
|
IoWrite8 (EC_CMD_PORT, EcCmd);
|
|
|
|
WaitEcIbe ();
|
|
}
|
|
|
|
//------------------------------------
|
|
// send EC data
|
|
//------------------------------------
|
|
VOID
|
|
SendEcData (
|
|
UINT8 EcData
|
|
)
|
|
{
|
|
WaitEcIbe ();
|
|
|
|
IoWrite8 (EC_DATA_PORT, EcData);
|
|
|
|
WaitEcIbe ();
|
|
}
|
|
|
|
UINT8
|
|
ReadEcData (
|
|
VOID
|
|
)
|
|
{
|
|
WaitEcObf ();
|
|
|
|
return IoRead8(EC_DATA_PORT);
|
|
}
|
|
|
|
//------------------------------------
|
|
// wait KB output buffer full
|
|
//------------------------------------
|
|
VOID
|
|
WaitKbObf (
|
|
VOID
|
|
)
|
|
{
|
|
while (!(IoRead8(KB_STATUS_PORT) & KB_OBF));
|
|
}
|
|
|
|
VOID
|
|
WaitKbObe (
|
|
VOID
|
|
)
|
|
{
|
|
while (IoRead8 (KB_STATUS_PORT) & KB_OBF) {
|
|
IoRead8 (KB_DATA_PORT);
|
|
}
|
|
}
|
|
|
|
//------------------------------------
|
|
// wait KB input buffer empty
|
|
//------------------------------------
|
|
VOID
|
|
WaitKbIbe (
|
|
VOID
|
|
)
|
|
{
|
|
while (IoRead8(KB_STATUS_PORT) & KB_IBF);
|
|
}
|
|
|
|
|
|
VOID
|
|
SendKbCmd (
|
|
UINT8 KBCmd
|
|
)
|
|
{
|
|
WaitKbObe ();
|
|
WaitKbIbe ();
|
|
IoWrite8 (KB_CMD_PORT, KBCmd);
|
|
WaitKbIbe ();
|
|
}
|
|
|
|
//------------------------------------
|
|
// send KB data
|
|
//------------------------------------
|
|
VOID
|
|
SendKbData (
|
|
UINT8 KBData
|
|
)
|
|
{
|
|
WaitKbObe ();
|
|
WaitKbIbe ();
|
|
IoWrite8 (KB_DATA_PORT, KBData);
|
|
WaitKbIbe ();
|
|
}
|
|
|
|
UINT8
|
|
ReadKbData (
|
|
VOID
|
|
)
|
|
{
|
|
WaitKbObf ();
|
|
return IoRead8(0x62);
|
|
}
|
|
|
|
|
|
VOID
|
|
EnterFollowMode (
|
|
VOID
|
|
)
|
|
{
|
|
SendEcCmd (0x01);
|
|
}
|
|
|
|
VOID
|
|
ExitFollowMode (
|
|
VOID
|
|
)
|
|
{
|
|
SendEcCmd (0x05);
|
|
}
|
|
|
|
VOID
|
|
SendSPICommand (
|
|
UINT8 Cmd
|
|
)
|
|
{
|
|
SendEcCmd (0x02);
|
|
SendEcCmd (Cmd);
|
|
}
|
|
|
|
VOID
|
|
SendSPIByte (
|
|
UINT8 Index
|
|
)
|
|
{
|
|
SendEcCmd (0x03);
|
|
SendEcCmd (Index);
|
|
}
|
|
|
|
UINT8
|
|
BReadByteFromSPI (
|
|
VOID
|
|
)
|
|
{
|
|
SendEcCmd (0x04);
|
|
return ReadEcData();
|
|
}
|
|
|
|
VOID
|
|
WaitSPIFree (
|
|
VOID
|
|
)
|
|
{
|
|
EnterFollowMode ();
|
|
SendSPICommand (SPICMD_READ_STATUS);
|
|
|
|
while (1) {
|
|
if((BReadByteFromSPI ()&0x01) == 0x00) {
|
|
break;
|
|
}
|
|
}
|
|
ExitFollowMode();
|
|
}
|
|
|
|
VOID
|
|
WaitWriteEnable (
|
|
VOID
|
|
)
|
|
{
|
|
EnterFollowMode ();
|
|
SendSPICommand (SPICMD_READ_STATUS);
|
|
|
|
while (1) {
|
|
if((BReadByteFromSPI ()&0x03) == 0x02) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
VOID
|
|
ShowVersion (
|
|
VOID
|
|
)
|
|
{
|
|
// Clear Screen
|
|
gST->ConOut->ClearScreen (gST->ConOut);
|
|
gST->ConOut->SetMode (gST->ConOut, 0);
|
|
gST->ConOut->EnableCursor (gST->ConOut, FALSE);
|
|
gST->ConOut->SetCursorPosition (gST->ConOut, 0, 0);
|
|
gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR(EFI_WHITE, EFI_BACKGROUND_BLACK));
|
|
|
|
Print(L"******************************************************************************\n");
|
|
Print(L" LCFC EC ROM Flash Utility Version : %s\n", ECREAD_VERSION);
|
|
Print(L" Company: Hefei LCFC Information Technology Co.Ltd.\n");
|
|
Print(L"******************************************************************************\n");
|
|
}
|
|
|
|
VOID
|
|
ShowDeviceID (
|
|
VOID
|
|
)
|
|
{
|
|
Print(L"Device ID : %x %x %x %x\n", SPIDeviceID[0], SPIDeviceID[1], SPIDeviceID[2], SPIDeviceID[3]);
|
|
}
|
|
|
|
VOID
|
|
ShowVendorID (
|
|
VOID
|
|
)
|
|
{
|
|
UINT8 Index;
|
|
|
|
for(Index = 0x00; Index < (sizeof (SpiVendor) / sizeof (FLASH_DEV_VENDOR)); Index++){
|
|
if(SPIDeviceID[0] == SpiVendor[Index].Muid) {
|
|
(SpiVendor[Index].ShowId)();
|
|
}
|
|
}
|
|
}
|
|
|
|
VOID
|
|
ReadSPIDeviceIDCmdAB (
|
|
VOID
|
|
)
|
|
{
|
|
UINT8 Index;
|
|
|
|
WaitSPIFree ();
|
|
EnterFollowMode ();
|
|
|
|
SendSPICommand (SPICMD_RDID);
|
|
SendSPIByte (0x00);
|
|
SendSPIByte (0x00);
|
|
SendSPIByte (0x00);
|
|
for(Index = 0x00; Index < 4; Index++) {
|
|
SPIDeviceID[Index] = BReadByteFromSPI();
|
|
}
|
|
|
|
if(SPIDeviceID[0] == SSTID) {
|
|
OldSstDevID = 1;
|
|
OldDevID = 0;
|
|
} else {
|
|
OldSstDevID = 0;
|
|
OldDevID = 1;
|
|
}
|
|
ExitFollowMode();
|
|
}
|
|
|
|
VOID
|
|
ReadSPIDeviceID (
|
|
VOID
|
|
)
|
|
{
|
|
UINT8 Index;
|
|
|
|
SPIDeviceID[0] = 0x00;
|
|
|
|
WaitSPIFree ();
|
|
EnterFollowMode ();
|
|
SendSPICommand (SPICMD__DEVICE_ID);
|
|
|
|
for(Index=0x00; Index < 4; Index++) {
|
|
SPIDeviceID[Index] = BReadByteFromSPI ();
|
|
}
|
|
if (SPIDeviceID[0] == 0x00) {
|
|
ReadSPIDeviceIDCmdAB ();
|
|
}
|
|
|
|
ExitFollowMode ();
|
|
}
|
|
|
|
|
|
VOID
|
|
SpiWriteDisable (
|
|
VOID
|
|
)
|
|
{
|
|
WaitSPIFree ();
|
|
EnterFollowMode ();
|
|
SendSPICommand (SPICMD_WRDI);
|
|
|
|
EnterFollowMode ();
|
|
SendSPICommand (SPICMD_READ_STATUS);
|
|
|
|
while(1) {
|
|
if((BReadByteFromSPI()&0x02 )== 0x00){
|
|
break;
|
|
}
|
|
}
|
|
ExitFollowMode ();
|
|
}
|
|
|
|
VOID
|
|
SPIUnlockAll (
|
|
VOID
|
|
)
|
|
{
|
|
WaitSPIFree ();
|
|
EnterFollowMode ();
|
|
SendSPICommand (SPICMD_WREN);
|
|
|
|
EnterFollowMode ();
|
|
SendSPICommand (SPICMD_READ_STATUS);
|
|
while(1) {
|
|
if((BReadByteFromSPI ()&0x02) != 0x00){
|
|
break;
|
|
}
|
|
}
|
|
|
|
if(SPIDeviceID[0] == SSTID) {
|
|
EnterFollowMode ();
|
|
SendSPICommand (SPICMD_EWSR);
|
|
}
|
|
|
|
EnterFollowMode ();
|
|
SendSPICommand (SPICMD_WRSR);
|
|
SendSPIByte (0x00);
|
|
|
|
WaitSPIFree ();
|
|
}
|
|
|
|
VOID
|
|
SpiWriteEnable (
|
|
VOID
|
|
)
|
|
{
|
|
|
|
WaitSPIFree ();
|
|
|
|
EnterFollowMode ();
|
|
SendSPICommand (SPICMD_WREN);
|
|
|
|
if(SPIDeviceID[0] == SSTID) {
|
|
EnterFollowMode ();
|
|
SendSPICommand (SPICMD_EWSR);
|
|
}
|
|
|
|
EnterFollowMode ();
|
|
SendSPICommand (SPICMD_READ_STATUS);
|
|
while (1) {
|
|
if((BReadByteFromSPI ()&0x03 ) == 0x02) {
|
|
break;
|
|
}
|
|
}
|
|
ExitFollowMode ();
|
|
}
|
|
|
|
UINT8
|
|
SpiVerifyErase64KByte (
|
|
UINT8 BlockNum
|
|
)
|
|
{
|
|
UINT32 AddrInBlock = 0;
|
|
UINT32 Index = 0;
|
|
|
|
AddrInBlock = BlockNum * BLOCK_SIZE_64K;
|
|
|
|
SpiWriteDisable ();
|
|
|
|
WaitSPIFree ();
|
|
EnterFollowMode ();
|
|
SendSPICommand (SPICMD_HIGH_SPEED_READ);
|
|
SendSPIByte ((UINT8)(((AddrInBlock>>16)&0xFF))); //Addr2
|
|
SendSPIByte ((UINT8)(((AddrInBlock>>8)&0xFF))); //Addr1
|
|
SendSPIByte ((UINT8)(((AddrInBlock)&0xFF))); // fast read dummy byte
|
|
SendSPIByte (0x00);
|
|
|
|
|
|
Print (L"Erase Verify... : ");
|
|
|
|
for (Index = 0; Index < BLOCK_SIZE_64K; Index++) {
|
|
if(BReadByteFromSPI () != 0xFF) {
|
|
WaitSPIFree ();
|
|
Print (L" -- Verify Fail. \n");
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
WaitSPIFree ();
|
|
|
|
Print (L" -- Verify OK. \n");
|
|
return 1;
|
|
}
|
|
|
|
UINT8
|
|
SpiVerifyErase1KByte (
|
|
//[-start-210616-YUNLEI0102-modify]//
|
|
// UINT8 BlockNum
|
|
UINT16 BlockNum
|
|
//[-end-210616-YUNLEI0102-modify]//
|
|
)
|
|
{
|
|
UINT32 AddrInBlock = 0;
|
|
UINT32 Index = 0;
|
|
|
|
AddrInBlock = BlockNum * BLOCK_SIZE_1K;
|
|
|
|
SpiWriteDisable ();
|
|
|
|
WaitSPIFree ();
|
|
EnterFollowMode ();
|
|
SendSPICommand (SPICMD_HIGH_SPEED_READ);
|
|
SendSPIByte ((UINT8)(((AddrInBlock>>16)&0xFF))); //Addr2
|
|
SendSPIByte ((UINT8)(((AddrInBlock>>8)&0xFF))); //Addr1
|
|
SendSPIByte ((UINT8)(((AddrInBlock)&0xFF))); // fast read dummy byte
|
|
SendSPIByte (0x00);
|
|
|
|
for (Index = 0; Index < BLOCK_SIZE_1K; Index++) {
|
|
if(BReadByteFromSPI () != 0xFF) {
|
|
WaitSPIFree ();
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
WaitSPIFree ();
|
|
return 1;
|
|
}
|
|
|
|
VOID
|
|
SpiBlockErase64KByte (
|
|
UINT8 BlockNum
|
|
)
|
|
{
|
|
UINT8 Counter;
|
|
//SpiWriteEnable();
|
|
SpiWriteEnable ();
|
|
EnterFollowMode ();
|
|
|
|
SendSPICommand (SPICMD_64K_BYTE_BE);
|
|
WaitSPIFree ();
|
|
|
|
if( OldDevID == 0x01 ) {
|
|
SpiWriteEnable ();
|
|
EnterFollowMode ();
|
|
|
|
SendSPICommand (SPICMD_64K_BYTE_BE);
|
|
ExitFollowMode ();
|
|
WaitSPIFree ();
|
|
}
|
|
//ExitFollowMode();
|
|
|
|
Print (L"Eraseing... : ");
|
|
for(Counter=0x00; Counter < 22; Counter++){
|
|
Print (L"%c", 0xDB);
|
|
}
|
|
Print (L" -- Erase OK. \n");
|
|
|
|
}
|
|
|
|
VOID
|
|
SpiBlockErase1KByte (
|
|
//[-start-210616-YUNLEI0102-modify]//
|
|
// UINT8 BlockNum
|
|
UINT16 BlockNum
|
|
//[-end-210616-YUNLEI0102-modify]//
|
|
)
|
|
{
|
|
UINT32 AddrInBlock = 0;
|
|
|
|
AddrInBlock = BlockNum * BLOCK_SIZE_1K;
|
|
|
|
SpiWriteEnable ();
|
|
EnterFollowMode ();
|
|
|
|
SendSPICommand (SPICMD_1K_BYTE_BE);
|
|
SendSPIByte ((UINT8)((AddrInBlock>>16)&0xFF));
|
|
SendSPIByte ((UINT8)((AddrInBlock>>8)&0xFF));
|
|
SendSPIByte ((UINT8)((AddrInBlock)&0xFF));
|
|
|
|
WaitSPIFree ();
|
|
}
|
|
|
|
VOID
|
|
ByteProgram64KByte (
|
|
UINT8 BlockNum,
|
|
UINT8* FileBuf
|
|
)
|
|
{
|
|
UINT8 Addr0,Addr1;
|
|
UINT32 AddrInBlock = 0;
|
|
|
|
Print(L"Programing... : ");
|
|
|
|
for (Addr1=0x00; Addr1 < 0x100; Addr1++){
|
|
SpiWriteEnable ();
|
|
EnterFollowMode();
|
|
|
|
SendSPICommand (SPICMD_BYTE_PROG);
|
|
SendSPIByte (BlockNum); //Addr2
|
|
SendSPIByte (Addr1); //Addr1
|
|
SendSPIByte (0x00); //Addr0
|
|
|
|
for(Addr0=0x00; Addr0 < 0x100; Addr0++) {
|
|
SendSPIByte (FileBuf[AddrInBlock]);
|
|
AddrInBlock++;
|
|
}
|
|
|
|
WaitSPIFree ();
|
|
//SpiWriteDisable();
|
|
}
|
|
|
|
SpiWriteDisable ();
|
|
Print (L" -- Programing OK. \n");
|
|
}
|
|
|
|
VOID
|
|
AAIWordProgram64KByte (
|
|
UINT8 BlockNum,
|
|
UINT8* FileBuf
|
|
)
|
|
{
|
|
UINT8 Index;
|
|
UINT32 Counter, AddrInBlock = 0;
|
|
|
|
AddrInBlock = BlockNum * BLOCK_SIZE_64K;
|
|
Index = 0;
|
|
|
|
SpiWriteEnable();
|
|
EnterFollowMode();
|
|
|
|
SendSPICommand (SPICMD_AAI_WORD_PROG);
|
|
SendSPIByte ((UINT8)((AddrInBlock>>16)&0xFF));
|
|
SendSPIByte ((UINT8)((AddrInBlock>>8)&0xFF));
|
|
SendSPIByte ((UINT8)((AddrInBlock)&0xFF));
|
|
|
|
Print (L"Programing... : ");
|
|
|
|
for(Counter = 0; Counter < BLOCK_SIZE_64K; Counter++){
|
|
SendSPIByte (FileBuf[AddrInBlock+Counter]);
|
|
Index++;
|
|
|
|
if(Index == 0x02) {
|
|
Index = 0x00;
|
|
WaitSPIFree ();
|
|
EnterFollowMode ();
|
|
SendSPICommand (SPICMD_AAI_WORD_PROG);
|
|
}
|
|
}
|
|
|
|
SpiWriteDisable ();
|
|
WaitSPIFree ();
|
|
|
|
Print(L" -- Programing 64K bytes OK. \n");
|
|
}
|
|
|
|
VOID
|
|
AAIWordProgram1KByte (
|
|
//[-start-210616-YUNLEI0102-modify]//
|
|
// UINT8 BlockNum
|
|
UINT16 BlockNum,
|
|
//[-end-210616-YUNLEI0102-modify]//
|
|
UINT8* FileBuf
|
|
)
|
|
{
|
|
UINT8 Index;
|
|
UINT32 Counter, AddrInBlock = 0;
|
|
|
|
AddrInBlock = BlockNum * BLOCK_SIZE_1K;
|
|
Index = 0;
|
|
|
|
SpiWriteEnable();
|
|
EnterFollowMode();
|
|
|
|
SendSPICommand (SPICMD_AAI_WORD_PROG);
|
|
SendSPIByte ((UINT8)((AddrInBlock>>16)&0xFF));
|
|
SendSPIByte ((UINT8)((AddrInBlock>>8)&0xFF));
|
|
SendSPIByte ((UINT8)((AddrInBlock)&0xFF));
|
|
|
|
for(Counter = 0; Counter < BLOCK_SIZE_1K; Counter++){
|
|
SendSPIByte (FileBuf[AddrInBlock + Counter]);
|
|
Index++;
|
|
|
|
if(Index == 0x02) {
|
|
Index = 0x00;
|
|
WaitSPIFree ();
|
|
EnterFollowMode ();
|
|
SendSPICommand (SPICMD_AAI_WORD_PROG);
|
|
}
|
|
}
|
|
|
|
SpiWriteDisable ();
|
|
WaitSPIFree ();
|
|
}
|
|
|
|
BOOLEAN
|
|
SpiVerify64KByte (
|
|
UINT8 BlockNum,
|
|
UINT8* FileBuf
|
|
)
|
|
{
|
|
UINT8 Index;
|
|
UINT32 Counter, AddrInBlock = 0;
|
|
|
|
AddrInBlock = BlockNum*BLOCK_SIZE_64K;
|
|
Index = 0;
|
|
|
|
SpiWriteDisable();
|
|
|
|
WaitSPIFree();
|
|
EnterFollowMode();
|
|
|
|
SendSPICommand (SPICMD_HIGH_SPEED_READ);
|
|
SendSPIByte ((UINT8)((AddrInBlock>>16)&0xFF));
|
|
SendSPIByte ((UINT8)((AddrInBlock>>8)&0xFF));
|
|
SendSPIByte ((UINT8)((AddrInBlock)&0xFF));
|
|
SendSPIByte (0x00); // fast read dummy byte
|
|
|
|
Print (L"Verify... : ");
|
|
|
|
for(Counter = 0; Counter < BLOCK_SIZE_64K; Counter++){
|
|
if (FileBuf[AddrInBlock + Counter]!=BReadByteFromSPI()){
|
|
WaitSPIFree ();
|
|
Print (L" -- Verify Fail. \n");
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
WaitSPIFree ();
|
|
|
|
Print (L" -- Verify OK. \n");
|
|
return 1;
|
|
}
|
|
|
|
BOOLEAN
|
|
SpiVerify1KByte (
|
|
//[-start-210616-YUNLEI0102-modify]//
|
|
// UINT8 BlockNum
|
|
UINT16 BlockNum,
|
|
//[-end-210616-YUNLEI0102-modify]//
|
|
UINT8* FileBuf
|
|
)
|
|
{
|
|
UINT8 Index;
|
|
UINT32 Counter, AddrInBlock = 0;
|
|
|
|
AddrInBlock = BlockNum*BLOCK_SIZE_1K;
|
|
Index = 0;
|
|
|
|
SpiWriteDisable();
|
|
|
|
WaitSPIFree();
|
|
EnterFollowMode();
|
|
|
|
SendSPICommand (SPICMD_HIGH_SPEED_READ);
|
|
SendSPIByte ((UINT8)((AddrInBlock>>16)&0xFF));
|
|
SendSPIByte ((UINT8)((AddrInBlock>>8)&0xFF));
|
|
SendSPIByte ((UINT8)((AddrInBlock)&0xFF));
|
|
SendSPIByte (0x00); // fast read dummy byte
|
|
|
|
for(Counter = 0; Counter < BLOCK_SIZE_1K; Counter++){
|
|
if (FileBuf[AddrInBlock + Counter]!=BReadByteFromSPI()){
|
|
WaitSPIFree ();
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
WaitSPIFree ();
|
|
return 1;
|
|
}
|
|
|
|
VOID
|
|
SpiRead64KByte (
|
|
UINT8 BlockNum,
|
|
UINT8* ReadBuf
|
|
)
|
|
{
|
|
UINT32 AddrInBlock = 0;
|
|
|
|
SpiWriteDisable ();
|
|
|
|
WaitSPIFree ();
|
|
EnterFollowMode ();
|
|
|
|
SendSPICommand (SPICMD_HIGH_SPEED_READ);
|
|
SendSPIByte (BlockNum); //Addr2
|
|
SendSPIByte (0x00); //Addr1
|
|
SendSPIByte (0x00); //Addr0
|
|
SendSPIByte (0x00); // fast read dummy byte
|
|
|
|
|
|
for (AddrInBlock = 0x00; AddrInBlock < BLOCK_SIZE_64K; AddrInBlock++){
|
|
ReadBuf[AddrInBlock] = BReadByteFromSPI();
|
|
|
|
if((AddrInBlock % (1024 * 8)) == 0x00){
|
|
Print (L".");
|
|
}
|
|
}
|
|
|
|
WaitSPIFree ();
|
|
}
|
|
|
|
VOID
|
|
SpiRead1KByte (
|
|
//[-start-210616-YUNLEI0102-modify]//
|
|
// UINT8 BlockNum
|
|
UINT16 BlockNum,
|
|
//[-end-210616-YUNLEI0102-modify]//
|
|
UINT8* ReadBuf
|
|
)
|
|
{
|
|
UINT32 AddrInBlock = 0;
|
|
UINT32 BlockAddr = 0;
|
|
|
|
BlockAddr = BlockNum * BLOCK_SIZE_1K;
|
|
|
|
SpiWriteDisable ();
|
|
|
|
WaitSPIFree ();
|
|
EnterFollowMode ();
|
|
|
|
SendSPICommand (SPICMD_HIGH_SPEED_READ);
|
|
SendSPIByte ((UINT8)(((BlockAddr>>16)&0xFF))); //Addr2
|
|
SendSPIByte ((UINT8)(((BlockAddr>>8)&0xFF))); //Addr1
|
|
SendSPIByte ((UINT8)(((BlockAddr)&0xFF))); // fast read dummy byte
|
|
SendSPIByte (0x00);
|
|
|
|
for (AddrInBlock = 0x00; AddrInBlock < BLOCK_SIZE_1K; AddrInBlock++){
|
|
ReadBuf[AddrInBlock] = BReadByteFromSPI();
|
|
}
|
|
|
|
ExitFollowMode ();
|
|
WaitSPIFree ();
|
|
}
|
|
|
|
EFI_STATUS
|
|
OpHelp (
|
|
VOID
|
|
)
|
|
{
|
|
Usage ();
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
EFI_STATUS
|
|
OpIdentify (
|
|
VOID
|
|
)
|
|
{
|
|
|
|
ReadSPIDeviceID ();
|
|
//ShowDeviceID ();
|
|
//ShowVendorID ();
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
EFI_STATUS
|
|
OpRead64K (
|
|
UINT8 *ReadBuf,
|
|
UINTN BlockCount
|
|
)
|
|
{
|
|
UINT8 BlockNum = 0;
|
|
|
|
for (BlockNum = 0; BlockNum < BlockCount; BlockNum++){
|
|
Print (L"\nBlock Number : %d \n",BlockNum);
|
|
SpiRead64KByte (BlockNum, (ReadBuf + (BlockNum * BLOCK_SIZE_64K)));
|
|
}
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
// Showing progress bar.
|
|
EFI_STATUS
|
|
ShowProgressBar (
|
|
UINTN Col,
|
|
UINTN Row,
|
|
UINTN MaxCount
|
|
)
|
|
{
|
|
UINTN Index;
|
|
|
|
// Checking input parameter.
|
|
if (MaxCount == 0) {
|
|
Print (L"MaxCount can't equal to 0\n");
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
// Output the progress bar in the screen.
|
|
gST->ConOut->SetCursorPosition(gST->ConOut, Col, Row);
|
|
gST->ConOut->SetAttribute (gST->ConOut, EFI_BLUE);
|
|
for (Index = 0; Index < PROGRESS_BAR_LEN; Index++){
|
|
Print (L"%c", BLOCKELEMENT_FULL_BLOCK);
|
|
}
|
|
|
|
gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR(EFI_WHITE, EFI_BACKGROUND_BLACK));
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
// Setting the progress bar item.
|
|
EFI_STATUS
|
|
SetProgressBarItem (
|
|
UINTN Col,
|
|
UINTN Row,
|
|
UINTN MaxCount,
|
|
UINTN CurValue
|
|
)
|
|
{
|
|
UINTN PrintUnit;
|
|
|
|
// Checking input parameter.
|
|
if (MaxCount == 0 || CurValue >= MaxCount) {
|
|
Print (L"MaxCount can't equal to 0\n");
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
// Output current value in the progress bar.
|
|
PrintUnit = ((PROGRESS_BAR_LEN - 1) * CurValue) / (MaxCount - 1);
|
|
gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR(EFI_WHITE, EFI_BACKGROUND_BLACK));
|
|
gST->ConOut->SetCursorPosition(gST->ConOut, Col + PrintUnit, Row);
|
|
Print (L"%c", BLOCKELEMENT_FULL_BLOCK);
|
|
|
|
gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR(EFI_WHITE, EFI_BACKGROUND_BLACK));
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
EFI_STATUS
|
|
OpRead1K (
|
|
UINT8 *ReadBuf,
|
|
UINTN BlockCount
|
|
)
|
|
{
|
|
//[-start-210616-YUNLEI0102-modify]//
|
|
// UINT8 BlockNum = 0;
|
|
UINT16 BlockNum = 0;
|
|
//[-end-210616-YUNLEI0102-modify]//
|
|
UINTN Col = 0;
|
|
UINTN Row = 0;
|
|
UINTN ProgBarOffset = PROGRESS_BAR_OFFSET;
|
|
|
|
Col = 9;
|
|
Row = 7;
|
|
ShowProgressBar (Col + ProgBarOffset, Row, BlockCount);
|
|
gST->ConOut->SetCursorPosition(gST->ConOut, Col + ProgBarOffset + PROGRESS_BAR_LEN, Row);
|
|
Print (L"]");
|
|
for (BlockNum = 0; BlockNum < BlockCount; BlockNum++){
|
|
gST->ConOut->SetCursorPosition(gST->ConOut, Col, Row);
|
|
Print (L"Reading EC ROM [Bank: %3d] [", BlockNum + 1);
|
|
|
|
SpiRead1KByte (BlockNum, (ReadBuf + (BlockNum * BLOCK_SIZE_1K)));
|
|
|
|
// Output message onto the screen.
|
|
SetProgressBarItem (Col + ProgBarOffset, Row, BlockCount, BlockNum);
|
|
}
|
|
|
|
Row += 2;
|
|
gST->ConOut->SetCursorPosition(gST->ConOut, 0, Row);
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
VOID
|
|
SpiChipEraseEflash (
|
|
VOID
|
|
)
|
|
{
|
|
Print (L"\nEraseing... : ");
|
|
SpiWriteEnable ();
|
|
EnterFollowMode ();
|
|
|
|
SendSPICommand (SPICMD_CHIP_ERASE);
|
|
ExitFollowMode ();
|
|
WaitSPIFree ();
|
|
Print (L" -- Erase full EC ROM OK. \n");
|
|
}
|
|
|
|
EFI_STATUS
|
|
OpWrite64K (
|
|
UINT8* FileBuf,
|
|
UINTN BlockCount
|
|
)
|
|
{
|
|
UINT8 BlockNum = 0;
|
|
EFI_STATUS Status = EFI_SUCCESS;
|
|
|
|
SPIUnlockAll ();
|
|
|
|
SpiChipEraseEflash ();
|
|
|
|
for(BlockNum = 0; BlockNum < BlockCount; BlockNum++) {
|
|
Print (L"\nBlock Number : %d \n",BlockNum);
|
|
|
|
if(!SpiVerifyErase64KByte (BlockNum)){
|
|
Print (L" Erase Verify Fail \n");
|
|
Status = EFI_DEVICE_ERROR;
|
|
break;
|
|
}
|
|
|
|
AAIWordProgram64KByte (BlockNum,FileBuf);
|
|
if(!SpiVerify64KByte (BlockNum,FileBuf)){
|
|
Print (L" Program Verify Fail \n");
|
|
Status = EFI_DEVICE_ERROR;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if(EFI_ERROR(Status)){
|
|
|
|
Print(L" \nProgram Fail \n");
|
|
gBS->Stall (10 * 1000 * 1000);
|
|
SendEcCmd (0xFC); // return to shell
|
|
} else {
|
|
Print (L" \nProgram OK \n");
|
|
gBS->Stall (10 * 1000 * 1000);
|
|
SendEcCmd (0xFE); // Watch dog reset EC
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
// This API only run in OS environment, for example: DOS and WIN OS.
|
|
EFI_STATUS
|
|
OpWrite1KRunOs (
|
|
UINT8* FileBuf,
|
|
UINTN BlockCount
|
|
)
|
|
{
|
|
EFI_STATUS Status = EFI_SUCCESS;
|
|
//[-start-210616-YUNLEI0102-modify]//
|
|
// UINT8 BlockNum = 0;
|
|
UINT16 BlockNum = 0;
|
|
//[-end-210616-YUNLEI0102-modify]//
|
|
|
|
SPIUnlockAll ();
|
|
|
|
|
|
// Erase EC ROM based on unit 1K byte.
|
|
for(BlockNum = 0; BlockNum < BlockCount; BlockNum++) {
|
|
// Erase 1K block.
|
|
SpiBlockErase1KByte (BlockNum);
|
|
}
|
|
|
|
// Verify the erased EC ROM based on unit 1K byte.
|
|
for(BlockNum = 0; BlockNum < BlockCount; BlockNum++) {
|
|
// Verify the erased 1K block.
|
|
if(!SpiVerifyErase1KByte (BlockNum)){
|
|
Status = EFI_DEVICE_ERROR;
|
|
return Status;
|
|
}
|
|
}
|
|
|
|
// Program the erased EC ROM based on unit 1K byte.
|
|
for(BlockNum = 0; BlockNum < BlockCount; BlockNum++) {
|
|
// Programming 1K block.
|
|
AAIWordProgram1KByte (BlockNum, FileBuf);
|
|
}
|
|
|
|
// Verify the programmed EC ROM based on unit 1K byte.
|
|
for(BlockNum = 0; BlockNum < BlockCount; BlockNum++) {
|
|
// Verify the programmed 1K block.
|
|
if(!SpiVerify1KByte (BlockNum ,FileBuf)){
|
|
Status = EFI_DEVICE_ERROR;
|
|
return Status;
|
|
}
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
// This API only run in BIOS post life phase.
|
|
EFI_STATUS
|
|
OpWrite1KRunBios (
|
|
UINT8* FileBuf,
|
|
UINTN BlockCount
|
|
)
|
|
{
|
|
EFI_STATUS Status = EFI_SUCCESS;
|
|
//[-start-210616-YUNLEI0102-modify]//
|
|
// UINT8 BlockNum = 0;
|
|
UINT16 BlockNum = 0;
|
|
//[-end-210616-YUNLEI0102-modify]//
|
|
UINTN Col = 0;
|
|
UINTN Row = 0;
|
|
UINTN RowIndex = 0;
|
|
UINTN ProgBarOffset = PROGRESS_BAR_OFFSET;
|
|
|
|
SPIUnlockAll ();
|
|
|
|
// Set the initialization coordinates for the programming window
|
|
Col = 9;
|
|
Row = 9;
|
|
|
|
// Clear the programming window
|
|
gST->ConOut->SetCursorPosition (gST->ConOut, 0, Row);
|
|
for (RowIndex = 0; RowIndex < 11; RowIndex++) {
|
|
Print(L" ");
|
|
}
|
|
gST->ConOut->SetCursorPosition (gST->ConOut, Col, Row);
|
|
|
|
// Erase EC ROM based on unit 1K byte.
|
|
ShowProgressBar (Col + ProgBarOffset, Row, BlockCount);
|
|
gST->ConOut->SetCursorPosition(gST->ConOut, Col + ProgBarOffset + PROGRESS_BAR_LEN, Row);
|
|
Print (L"]");
|
|
for(BlockNum = 0; BlockNum < BlockCount; BlockNum++) {
|
|
gST->ConOut->SetCursorPosition(gST->ConOut, Col, Row);
|
|
Print (L"Erase EC ROM [Bank: %3d] [", BlockNum + 1);
|
|
|
|
// Erase 1K block.
|
|
SpiBlockErase1KByte (BlockNum);
|
|
|
|
// Output message onto the screen.
|
|
SetProgressBarItem (Col + ProgBarOffset, Row, BlockCount, BlockNum);
|
|
}
|
|
|
|
// Verify the erased EC ROM based on unit 1K byte.
|
|
Row += 2;
|
|
ShowProgressBar (Col + ProgBarOffset, Row, BlockCount);
|
|
gST->ConOut->SetCursorPosition(gST->ConOut, Col + ProgBarOffset + PROGRESS_BAR_LEN, Row);
|
|
Print (L"]");
|
|
for(BlockNum = 0; BlockNum < BlockCount; BlockNum++) {
|
|
gST->ConOut->SetCursorPosition(gST->ConOut, Col, Row);
|
|
Print (L"Verify EC ROM [Bank: %3d] [", BlockNum + 1);
|
|
|
|
// Verify the erased 1K block.
|
|
if(!SpiVerifyErase1KByte (BlockNum)){
|
|
gST->ConOut->SetCursorPosition(gST->ConOut, Col, Row + 1);
|
|
Print (L" Erase Verify Failure!\n");
|
|
Status = EFI_DEVICE_ERROR;
|
|
return Status;
|
|
}
|
|
|
|
// Output message onto the screen.
|
|
SetProgressBarItem (Col + ProgBarOffset, Row, BlockCount, BlockNum);
|
|
}
|
|
|
|
// Program the erased EC ROM based on unit 1K byte.
|
|
Row += 2;
|
|
ShowProgressBar (Col + ProgBarOffset, Row, BlockCount);
|
|
gST->ConOut->SetCursorPosition(gST->ConOut, Col + ProgBarOffset + PROGRESS_BAR_LEN, Row);
|
|
Print (L"]");
|
|
for(BlockNum = 0; BlockNum < BlockCount; BlockNum++) {
|
|
gST->ConOut->SetCursorPosition(gST->ConOut, Col, Row);
|
|
Print (L"Program EC ROM [Bank: %3d] [", BlockNum + 1);
|
|
|
|
// Programming 1K block.
|
|
AAIWordProgram1KByte (BlockNum, FileBuf);
|
|
|
|
// Output message onto the screen.
|
|
SetProgressBarItem (Col + ProgBarOffset, Row, BlockCount, BlockNum);
|
|
}
|
|
|
|
// Verify the programmed EC ROM based on unit 1K byte.
|
|
Row += 2;
|
|
ShowProgressBar (Col + ProgBarOffset, Row, BlockCount);
|
|
gST->ConOut->SetCursorPosition(gST->ConOut, Col + ProgBarOffset + PROGRESS_BAR_LEN, Row);
|
|
Print (L"]");
|
|
for(BlockNum = 0; BlockNum < BlockCount; BlockNum++) {
|
|
gST->ConOut->SetCursorPosition(gST->ConOut, Col, Row);
|
|
Print (L"Verify EC ROM [Bank: %3d] [", BlockNum + 1);
|
|
|
|
// Verify the programmed 1K block.
|
|
if(!SpiVerify1KByte (BlockNum ,FileBuf)){
|
|
gST->ConOut->SetCursorPosition(gST->ConOut, Col, Row + 1);
|
|
Print (L" Program Verify Failure! \n");
|
|
Status = EFI_DEVICE_ERROR;
|
|
return Status;
|
|
}
|
|
|
|
// Output message onto the screen.
|
|
SetProgressBarItem (Col + ProgBarOffset, Row, BlockCount, BlockNum);
|
|
}
|
|
|
|
Row ++;
|
|
gST->ConOut->SetCursorPosition(gST->ConOut, Col, Row);
|
|
|
|
return Status;
|
|
}
|
|
|
|
// 64K Unit
|
|
/**
|
|
|
|
EcUpgradeEcRom
|
|
|
|
@param this Pointer to EFI_ECFLASH_PROTOCOL
|
|
|
|
@retval EFI_SUCCESS
|
|
|
|
**/
|
|
EFI_STATUS
|
|
EcUpgradeEcRom64K (
|
|
IN EFI_ECFLASH_PROTOCOL *this
|
|
)
|
|
{
|
|
EFI_STATUS Status = EFI_SUCCESS;
|
|
UINT8* EcBuf = NULL;
|
|
UINTN EcAddr = 0;
|
|
UINTN EcSize = 0;
|
|
BOOLEAN EcAd = FALSE;
|
|
UINT64 IteSign;
|
|
UINTN BlockCount;
|
|
UINTN BufSize = 0;
|
|
|
|
UINT8 Index = 0;
|
|
|
|
// Showing Copyright
|
|
ShowVersion ();
|
|
|
|
EcAddr = FixedPcdGet32 (PcdFlashEcBase);
|
|
if (EcAddr == 0) {
|
|
Print (L"Invalid EC ROM Address.\n");
|
|
goto Exit;
|
|
}
|
|
|
|
EcSize = FixedPcdGet32 (PcdFlashEcSize);
|
|
if (EcSize == 0) {
|
|
Print (L"Invalid EC ROM Size.\n");
|
|
goto Exit;
|
|
}
|
|
|
|
// Print (L"EC ROM Address = %0xH EC ROM Size = %dK bytes\n", EcAddr, EcSize/1024 );
|
|
|
|
// Get the block number with the file.
|
|
BlockCount = EcSize / BLOCK_SIZE_64K;
|
|
if ( (EcSize % BLOCK_SIZE_64K) != 0) {
|
|
BlockCount++;
|
|
}
|
|
//Print (L"Total Blocks = %d (UNIT: 64K Byte)\n", BlockCount);
|
|
|
|
// Allocating file buffer.
|
|
BufSize = BlockCount * BLOCK_SIZE_64K;
|
|
Status = gBS->AllocatePages (
|
|
AllocateAnyPages,
|
|
EfiBootServicesData,
|
|
EFI_SIZE_TO_PAGES(BufSize),
|
|
(EFI_PHYSICAL_ADDRESS *)(&EcBuf)
|
|
);
|
|
if(EFI_ERROR(Status)){
|
|
Print (L"\n Allocate Memory Error %r\n", Status);
|
|
goto Exit;
|
|
}
|
|
|
|
// Using 0xFF to fill the EC buffer.
|
|
SetMem (EcBuf, BufSize, 0xFF);
|
|
|
|
// Transfer the EC ROM data onto the EC buffer.
|
|
CopyMem (EcBuf, (UINT8 *)(UINTN)(EcAddr), EcSize);
|
|
|
|
for(Index = 0; (sizeof(LcfcECRomHeader)/sizeof(EC_ROM_HEADER)); Index++) {
|
|
IteSign = *(UINT64 *)(UINTN)(EcBuf + LcfcECRomHeader[Index].EcRomIdOffset);
|
|
if (IteSign == LcfcECRomHeader[Index].EcRomSignature) {
|
|
// Print (L"EC ROM SIGNATURE = %lxH\n", IteSign);
|
|
break;
|
|
}
|
|
}
|
|
|
|
if(Index == (sizeof(LcfcECRomHeader)/sizeof(EC_ROM_HEADER))) {
|
|
Print (L"Invalid EC ROM Signature.\n");
|
|
goto Exit;
|
|
}
|
|
|
|
// Disabled Keyboard
|
|
SendKbCmd (0xAD);
|
|
EcAd = TRUE;
|
|
|
|
// Checking EC status
|
|
SendEcCmd (0xDC);
|
|
if(ReadEcData () == 0x33) {
|
|
// Print (L"EC ACK is OK.\n");
|
|
} else {
|
|
Print (L"EC ACK is Fail.\n");
|
|
Status = EFI_DEVICE_ERROR;
|
|
goto Exit;
|
|
}
|
|
|
|
OpIdentify ();
|
|
|
|
//Program
|
|
Status = OpWrite64K (EcBuf, BlockCount);
|
|
if (EFI_ERROR(Status)) {
|
|
Print (L"Program EC ROM Error %r\n", Status);
|
|
goto Exit;
|
|
}
|
|
|
|
Exit:
|
|
|
|
if (EcAd) {
|
|
SendKbCmd (0xAE);
|
|
}
|
|
|
|
if(EcBuf != NULL) {
|
|
gBS->FreePages ((EFI_PHYSICAL_ADDRESS)(UINTN)EcBuf, EFI_SIZE_TO_PAGES(BufSize));
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
// This API only run in OS environment, for example: DOS and WIN OS.
|
|
// 1K Unit
|
|
EFI_STATUS
|
|
UpgradeEcRomRunOs (
|
|
VOID
|
|
)
|
|
{
|
|
EFI_STATUS Status = EFI_SUCCESS;
|
|
UINT8* EcBuf = NULL;
|
|
UINTN EcAddr = 0;
|
|
UINTN EcSize = 0;
|
|
BOOLEAN EcAd = FALSE;
|
|
UINT64 IteSign;
|
|
UINTN BlockCount;
|
|
|
|
UINT8 Index = 0;
|
|
|
|
UINTN ProgRomRetryCount = 3;
|
|
|
|
EcAddr = FixedPcdGet32 (PcdFlashEcBase);
|
|
if (EcAddr == 0) {
|
|
Print (L"Invalid EC ROM Address.\n");
|
|
goto Exit;
|
|
}
|
|
|
|
EcSize = FixedPcdGet32 (PcdFlashEcSize);
|
|
if (EcSize == 0) {
|
|
Print (L"Invalid EC ROM Size.\n");
|
|
goto Exit;
|
|
}
|
|
|
|
// Get the block number with the file.
|
|
BlockCount = EcSize / BLOCK_SIZE_1K;
|
|
if ( (EcSize % BLOCK_SIZE_1K) != 0) {
|
|
//Print (L"Invalid the EC ROM size, it must be integer times of 1K bytes.\n");
|
|
goto Exit;
|
|
}
|
|
//Print (L"Total Blocks = %d (UNIT: 64K Byte)\n", BlockCount);
|
|
|
|
EcBuf = (UINT8 *)EcAddr;
|
|
|
|
for(Index = 0; Index < (sizeof(LcfcECRomHeader)/sizeof(EC_ROM_HEADER)); Index++) {
|
|
IteSign = *(UINT64 *)(UINTN)(EcBuf + LcfcECRomHeader[Index].EcRomIdOffset);
|
|
if (IteSign == LcfcECRomHeader[Index].EcRomSignature) {
|
|
// Print (L"EC ROM SIGNATURE = %lxH\n", IteSign);
|
|
break;
|
|
}
|
|
}
|
|
|
|
if(Index == (sizeof(LcfcECRomHeader)/sizeof(EC_ROM_HEADER))) {
|
|
Print (L"Invalid EC ROM Signature.\n");
|
|
goto Exit;
|
|
}
|
|
|
|
// Disabled Keyboard
|
|
SendKbCmd (0xAD);
|
|
EcAd = TRUE;
|
|
|
|
// Checking EC status
|
|
SendEcCmd (0xDC);
|
|
if(ReadEcData () == 0x33) {
|
|
//Print (L"EC ACK is OK.\n");
|
|
} else {
|
|
//Print (L"EC ACK is Fail.\n");
|
|
Status = EFI_DEVICE_ERROR;
|
|
goto Exit;
|
|
}
|
|
|
|
//OpIdentify ();
|
|
|
|
// Try to program EC ROM within retry count times. The default retry count time is 3.
|
|
ProgRomRetryCount = PROG_ROM_RETRY_COUNT;
|
|
do {
|
|
//Program
|
|
Status = OpWrite1KRunOs (EcBuf, BlockCount);
|
|
if (!EFI_ERROR(Status)) {
|
|
//Print (L" \nProgram EC ROM OK \n");
|
|
//gBS->Stall(10 * 1000 * 1000);
|
|
SendEcCmd (0xFE); // Watch dog reset EC
|
|
break;
|
|
}
|
|
//Print (L"Program EC ROM Error %r\n", Status);
|
|
ProgRomRetryCount--;
|
|
Print (L"\nProgram EC ROM Error Retry Count %d\n", ProgRomRetryCount);
|
|
}while (ProgRomRetryCount != 0);
|
|
|
|
// Stopping the machine when program EC ROM failed.
|
|
if (ProgRomRetryCount == 0) {
|
|
Print (L"\nProgram EC ROM Error, and please find the LCFC BIOS/EC team to deal with this issue!!\n");
|
|
gBS->Stall(30000000);
|
|
}
|
|
|
|
Exit:
|
|
|
|
if (EcAd) {
|
|
SendKbCmd (0xAE);
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
// This API only run in BIOS post life phase.
|
|
// 1K Unit
|
|
EFI_STATUS
|
|
UpgradeEcRomRunBios (
|
|
VOID
|
|
)
|
|
{
|
|
EFI_STATUS Status = EFI_SUCCESS;
|
|
UINT8* EcBuf = NULL;
|
|
UINTN EcAddr = 0;
|
|
UINTN EcSize = 0;
|
|
BOOLEAN EcAd = FALSE;
|
|
UINT64 IteSign;
|
|
UINTN BlockCount;
|
|
UINTN BufSize = 0;
|
|
UINT8 Index = 0;
|
|
UINTN ProgRomRetryCount = 3;
|
|
BOOLEAN ShowErrorMsg = TRUE;
|
|
|
|
// UINT8 CurrentProjectIDH = 0;
|
|
// UINT8 CurrentProjectIDL = 0;
|
|
// UINT8 CurrentScope = 0;
|
|
// UINT8 BinScope = 0;
|
|
// UINT8 DataH, DataL;
|
|
// UINT8 SecondData=0xAA;
|
|
// UINT16 BinProjectID = 0;
|
|
// UINT32 Temp64 = 0;
|
|
|
|
//[-start-190926-ElvisYang-add]// If EC support this feature,you need to set it.
|
|
// LfcEcLibEcRamWrite (0x2a, 0xA5);//Set EC Flash flag to allow ec flash via BIOS update only, FEPL
|
|
// LfcEcLibEcRamWrite (0x2b, 0x5A);//Set EC Flash flag to allow ec flash via BIOS update only, FEPH
|
|
//[-end-190926-ElvisYang-add]//
|
|
|
|
//Set FirmwareUpdatingFlag FALSE during flash EC when secure flash supported to avoid FirmwareUpdatingFlag not cleared and trigger the recovery mode.
|
|
if (FeaturePcdGet(PcdSecureFlashSupported)) {
|
|
SetFirmwareUpdatingFlag (FALSE);
|
|
}
|
|
// Showing Copyright
|
|
ShowVersion ();
|
|
|
|
EcAddr = FixedPcdGet32 (PcdFlashEcBase);
|
|
if (EcAddr == 0) {
|
|
Print (L"Invalid EC ROM Address.\n");
|
|
goto Exit;
|
|
}
|
|
|
|
EcSize = FixedPcdGet32 (PcdFlashEcSize);
|
|
if (EcSize == 0) {
|
|
Print (L"Invalid EC ROM Size.\n");
|
|
goto Exit;
|
|
}
|
|
|
|
// Print (L"EC ROM Address = %0xH EC ROM Size = %dK bytes\n", EcAddr, EcSize/1024 );
|
|
|
|
//[-start-211201-BAIN000063-add]//
|
|
#ifdef LCFC_SUPPORT
|
|
EcSize = EcSize - (80 * BLOCK_SIZE_1K); // BIOS can only erase 176K of EC Block that can keep EC UUID and BSH Flag in EC EEProm.
|
|
#endif
|
|
//[-end-211201-BAIN000063-add]//
|
|
|
|
// Get the block number with the file.
|
|
BlockCount = EcSize / BLOCK_SIZE_1K;
|
|
if ( (EcSize % BLOCK_SIZE_1K) != 0) {
|
|
Print (L"Invalid the EC ROM size, it must be integer times of 1K bytes.\n");
|
|
goto Exit;
|
|
}
|
|
//Print (L"Total Blocks = %d (UNIT: 64K Byte)\n", BlockCount);
|
|
|
|
/*
|
|
//EC flash todo
|
|
// Guard EC ->
|
|
IoWrite8(LFC_CMOS_INDEX, LFC_FLASH_EC_ONCE_H_INDEX);
|
|
DataH = IoRead8(LFC_CMOS_DATA);
|
|
IoWrite8(LFC_CMOS_INDEX, LFC_FLASH_EC_ONCE_L_INDEX);
|
|
DataL = IoRead8(LFC_CMOS_DATA);
|
|
|
|
if((SecondData != DataH) || (SecondData != DataL) ){
|
|
|
|
// get bin file's Project_ID and Scope from bin
|
|
Temp64 = *(UINT32 *)(UINTN)(EcAddr + 0x5D); // that's the EC bin file offset for Project ID and Scope
|
|
BinProjectID = Temp64 & 0xffff;
|
|
BinScope = (Temp64 >> 16) & 0xff;
|
|
Print (L"EC Project ID = %04X, Scope = %2X\n", BinProjectID, BinScope);
|
|
|
|
// get current EC's Project_ID and Scope from bin
|
|
SendEcCmd (0x44);
|
|
CurrentScope = ReadEcData();
|
|
CurrentProjectIDH = ReadEcData();
|
|
CurrentProjectIDL = ReadEcData();
|
|
|
|
// compare BinProjectID and scope between bin and current EC
|
|
if ((CurrentProjectIDL != (BinProjectID & 0xff)) || (CurrentProjectIDH != ((BinProjectID >> 8) & 0xff))){
|
|
Print (L"Current EC Project ID = %02X%02x\n", CurrentProjectIDH, CurrentProjectIDL);
|
|
Print (L"Error! Project ID not matched.\n");
|
|
goto Exit;
|
|
}
|
|
if (CurrentScope != BinScope) {
|
|
Print (L"Current EC Scope = %02x\n", CurrentScope);
|
|
Print (L"Error! Scope not matched.\n");
|
|
goto Exit;
|
|
}
|
|
} else {
|
|
Print (L"\nSkip this time EC flash by engineer command.\n");
|
|
goto Exit;
|
|
}
|
|
// Guard EC -<
|
|
*/
|
|
|
|
// Allocating file buffer.
|
|
BufSize = BlockCount * BLOCK_SIZE_1K;
|
|
Status = gBS->AllocatePages (
|
|
AllocateAnyPages,
|
|
EfiBootServicesData,
|
|
EFI_SIZE_TO_PAGES(BufSize),
|
|
(EFI_PHYSICAL_ADDRESS *)(&EcBuf)
|
|
);
|
|
if(EFI_ERROR(Status)){
|
|
Print (L"\n Allocate Memory Error %r\n", Status);
|
|
goto Exit;
|
|
}
|
|
|
|
// Using 0xFF to fill the EC buffer.
|
|
SetMem (EcBuf, BufSize, 0xFF);
|
|
|
|
// Transfer the EC ROM data onto the EC buffer.
|
|
CopyMem (EcBuf, (UINT8 *)(UINTN)(EcAddr), EcSize);
|
|
|
|
for(Index = 0; Index < (sizeof(LcfcECRomHeader)/sizeof(EC_ROM_HEADER)); Index++) {
|
|
IteSign = *(UINT64 *)(UINTN)(EcBuf + LcfcECRomHeader[Index].EcRomIdOffset);
|
|
if (IteSign == LcfcECRomHeader[Index].EcRomSignature) {
|
|
// Print (L"EC ROM SIGNATURE = %lxH\n", IteSign);
|
|
break;
|
|
}
|
|
}
|
|
|
|
if(Index == (sizeof(LcfcECRomHeader)/sizeof(EC_ROM_HEADER))) {
|
|
Print (L"Invalid EC ROM Signature.\n");
|
|
goto Exit;
|
|
}
|
|
|
|
// Disabled Keyboard
|
|
SendKbCmd (0xAD);
|
|
EcAd = TRUE;
|
|
|
|
// Checking EC status
|
|
SendEcCmd (0xDC);
|
|
if(ReadEcData () == 0x33) {
|
|
// Print (L"EC ACK is OK.\n");
|
|
} else {
|
|
Print (L"EC ACK is Fail.\n");
|
|
Status = EFI_DEVICE_ERROR;
|
|
goto Exit;
|
|
}
|
|
|
|
OpIdentify ();
|
|
|
|
// Try to program EC ROM within retry count times. The default retry count time is 3.
|
|
ProgRomRetryCount = PROG_ROM_RETRY_COUNT;
|
|
do {
|
|
//Program
|
|
Status = OpWrite1KRunBios (EcBuf, BlockCount);
|
|
if (!EFI_ERROR(Status)) {
|
|
Print (L" \nProgram EC ROM OK \n");
|
|
Print (L"Please wait EC reset system...\n");
|
|
gBS->Stall(10 * 1000 * 1000);
|
|
SendEcCmd (0xFE); // Watch dog reset EC
|
|
break;
|
|
}
|
|
ProgRomRetryCount--;
|
|
Print (L"\nProgram EC ROM Error Retry Count %d\n", ProgRomRetryCount);
|
|
}while (ProgRomRetryCount != 0);
|
|
|
|
// Stopping the machine when program EC ROM failed.
|
|
if (ProgRomRetryCount == 0) {
|
|
Print (L"\nProgram EC ROM Error, and please find the LCFC BIOS/EC team to deal with this issue!!\n");
|
|
gBS->Stall(30000000);
|
|
}
|
|
else {
|
|
ShowErrorMsg = FALSE;
|
|
}
|
|
|
|
Exit:
|
|
|
|
if (EcAd) {
|
|
SendKbCmd (0xAE);
|
|
}
|
|
|
|
if(EcBuf != NULL) {
|
|
gBS->FreePages ((EFI_PHYSICAL_ADDRESS)(UINTN)EcBuf, EFI_SIZE_TO_PAGES(BufSize));
|
|
}
|
|
|
|
// wait here for show error message
|
|
if (TRUE == ShowErrorMsg) {
|
|
gBS->Stall (10 * 1000 * 1000);
|
|
}
|
|
|
|
//gBS->Stall (10 * 1000 * 1000);
|
|
return Status;
|
|
}
|
|
|
|
// 1K Unit
|
|
/**
|
|
|
|
EcUpgradeEcRom
|
|
|
|
@param this Pointer to EFI_ECFLASH_PROTOCOL
|
|
|
|
@retval EFI_SUCCESS
|
|
|
|
**/
|
|
EFI_STATUS
|
|
EcUpgradeEcRom (
|
|
IN EFI_ECFLASH_PROTOCOL *this
|
|
)
|
|
{
|
|
EFI_STATUS Status = EFI_SUCCESS;
|
|
UINT8 Data = 0;
|
|
|
|
if (FeaturePcdGet (PcdSecureFlashSupported)) {
|
|
// Upgraed the EC ROM after upgraded BIOS ROM.
|
|
Status = UpgradeEcRomRunBios ();
|
|
} else {
|
|
// Upgraded the EC ROM in the next boot.
|
|
// Set Ec Ram Offset 0x8C Bit2 to 1 If want to Flash EC Rom.
|
|
LfcEcLibEcRamRead(0x8C, &Data);
|
|
Data |= BIT2;
|
|
LfcEcLibEcRamWrite(0x8C, Data); // BSFU
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
/**
|
|
Upgraded ECROM funcion.
|
|
|
|
@param[in] Event Event whose notification function is being invoked.
|
|
@param[in] Context Pointer to the notification function's context.
|
|
**/
|
|
VOID
|
|
EFIAPI
|
|
UpgradedEcRomFunction (
|
|
IN EFI_EVENT Event,
|
|
IN VOID *Context
|
|
)
|
|
{
|
|
EFI_STATUS Status = EFI_SUCCESS;
|
|
UINT8 Data = 0;
|
|
|
|
Status = gBS->CloseEvent (Event);
|
|
|
|
// Read Ec Ram Offset 0x8C bit2 Value
|
|
// Checking the Ec Ram Offset 0x8C bit2 value before upgrading EC ROM.
|
|
LfcEcLibEcRamRead(0x8C, &Data);
|
|
|
|
if(Data & BIT2) {
|
|
Data &= ~BIT2;
|
|
LfcEcLibEcRamWrite(0x8C, Data); // BSFU
|
|
// Upgraed the EC ROM after upgraded BIOS ROM.
|
|
Status = UpgradeEcRomRunBios ();
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
/**
|
|
Entry Point.
|
|
Create one Upgraded EC ROM event.
|
|
|
|
@param[in] VOID
|
|
|
|
@retval EFI_SUCEESS
|
|
@return Others Some error occurs.
|
|
**/
|
|
EFI_STATUS
|
|
CreateUpgradedEcRomEvent (
|
|
VOID
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
EFI_EVENT UpgradedEcRomEvent;
|
|
|
|
Status = EfiCreateEventReadyToBootEx (
|
|
TPL_CALLBACK,
|
|
UpgradedEcRomFunction,
|
|
NULL,
|
|
&UpgradedEcRomEvent
|
|
);
|
|
|
|
return Status;
|
|
}
|
|
|
|
/**
|
|
|
|
Initialize the EC FLash protocol
|
|
|
|
@param ImageHandle ImageHandle of the loaded driver
|
|
@param SystemTable Pointer to the System Table
|
|
|
|
@retval EFI_SUCCESS thread can be successfully created
|
|
@retval EFI_OUT_OF_RESOURCES cannot allocate protocol data structure
|
|
@retval EFI_DEVICE_ERROR cannot create the timer service
|
|
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
InitializeEcFlashEntryPoint (
|
|
IN EFI_HANDLE ImageHandle,
|
|
IN EFI_SYSTEM_TABLE *SystemTable
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
EFI_HANDLE Handle;
|
|
|
|
EFI_ECFLASH_PROTOCOL *EcFlashDxe;
|
|
EFI_ECFLASH_PROTOCOL *EcFlashSmm;
|
|
|
|
EFI_SMM_BASE2_PROTOCOL *SmmBase2;
|
|
BOOLEAN InSmm;
|
|
|
|
SmmBase2 = NULL;
|
|
Status = gBS->LocateProtocol (&gEfiSmmBase2ProtocolGuid, NULL, &SmmBase2);
|
|
InSmm = FALSE;
|
|
if (!EFI_ERROR (Status)) {
|
|
SmmBase2->InSmm (SmmBase2, &InSmm);
|
|
}
|
|
|
|
if (!InSmm) {
|
|
// Initialize the DXE driver.
|
|
|
|
//Allocated EcFlashDxe variable.
|
|
gBS->AllocatePool (EfiBootServicesData, sizeof (EFI_ECFLASH_PROTOCOL), &EcFlashDxe);
|
|
ASSERT (EcFlashDxe != NULL);
|
|
SetMem (EcFlashDxe, sizeof (EFI_ECFLASH_PROTOCOL), 0);
|
|
|
|
//
|
|
// Initialize the interfaces
|
|
//
|
|
EcFlashDxe->UpgradeEcRom = EcUpgradeEcRom;
|
|
Status = gBS->InstallMultipleProtocolInterfaces (
|
|
&ImageHandle,
|
|
&gEfiEcFlashProtocolGuid,
|
|
EcFlashDxe,
|
|
NULL
|
|
);
|
|
DEBUG ((EFI_D_ERROR, "Install EcFlash protocol interface. Status = %r.\n", Status));
|
|
ASSERT_EFI_ERROR (Status);
|
|
|
|
if (FeaturePcdGet (PcdSecureFlashSupported) == FALSE) {
|
|
// Create one boot event to upgrade the EC ROM in the BDS life phase.
|
|
CreateUpgradedEcRomEvent ();
|
|
}
|
|
}
|
|
else {
|
|
// Initialize the SMM driver.
|
|
|
|
//Allocated EcFlashSmm variable.
|
|
gSmst->SmmAllocatePool (EfiRuntimeServicesData, sizeof (EFI_ECFLASH_PROTOCOL), &EcFlashSmm);
|
|
ASSERT (EcFlashSmm != NULL);
|
|
SetMem (EcFlashSmm, sizeof (EFI_ECFLASH_PROTOCOL), 0);
|
|
|
|
//
|
|
// Initialize the interfaces
|
|
//
|
|
EcFlashSmm->UpgradeEcRom = EcUpgradeEcRom;
|
|
|
|
Handle = NULL;
|
|
Status = gSmst->SmmInstallProtocolInterface (
|
|
&Handle,
|
|
&gEfiEcFlashProtocolGuid,
|
|
EFI_NATIVE_INTERFACE,
|
|
EcFlashSmm
|
|
);
|
|
ASSERT_EFI_ERROR (Status);
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
|
|
}
|