/***************************************************************************** * * * 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 #include #include #include #include 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; }