//***************************************************************************** // // // 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 "EcFlashShell.h" UINT8 OldSstDevID; UINT8 OldDevID; UINT8 SPIDeviceID[4]; 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: (Using 0x62/0x66 Port)\n"); //Print (L"Usage: (Using 0x68/0x6C Port)\n"); Print (L" EcFlash -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" EcFlash.efi -r -b:128 EC.ROM\n"); Print (L" Written the EC ROM from the file:\n"); Print (L" EcFlash.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", ECFLASH_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 ( UINT8 BlockNum ) { 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 ( UINT8 BlockNum ) { 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 ( UINT8 BlockNum, 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 ( UINT8 BlockNum, 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 ( UINT8 BlockNum, 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 ) { UINT8 BlockNum = 0; 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 BIOS post life phase. EFI_STATUS OpWrite1KRunBios ( UINT8* FileBuf, UINTN BlockCount ) { EFI_STATUS Status = EFI_SUCCESS; UINT8 BlockNum = 0; 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 /** UEFI application entry point which has an interface similar to a standard C main function. The ShellCEntryLib library instance wrappers the actual UEFI application entry point and calls this ShellAppMain function. @param ImageHandle The image handle of the UEFI Application. @param SystemTable A pointer to the EFI System Table. @retval 0 The application exited normally. @retval Other An error occurred. **/ INTN EFIAPI ShellAppMain64K ( IN UINTN Argc, IN CHAR16 **Argv ) { EFI_STATUS Status = EFI_SUCCESS; UINT8 *FileBuf = NULL; UINTN BufSize = 0; OPERATION_EC Operation = OP_HELP; SHELL_FILE_HANDLE FileHandle = NULL; BOOLEAN EcAd = FALSE; UINT64 IteSign; UINT64 FileSize; UINTN BlockCount; CHAR16 *ParamPtr = NULL; EFI_FILE_INFO *FileInfo = NULL; // Showing Copyright ShowVersion (); // Checking input parameters. if (Argc < 3) { Status = OpHelp(); goto Exit; } if (((StrCmp(Argv[1], L"-r") == 0) || (StrCmp(Argv[1], L"-R") == 0)) && (Argc == 4)) { // Reading EC Binary from EC ROM // Getting the block count for this EC ROM. ParamPtr = Argv[2]; // Checking the bank count. if ((ParamPtr[0] == L'-') && ((ParamPtr[1] ==L'b' ) ||(ParamPtr[1] ==L'B' )) && (ParamPtr[2] == L':') ) { BlockCount = StrDecimalToUintn(ParamPtr + 3); if (BlockCount == 0) { Print (L"It's not one valid bank number! [%s]\n", ParamPtr + 3); goto Exit; } } else { Print (L"It's not one valid bank count parameter! [%s]\n", Argv[2]); goto Exit; } Status = ShellOpenFileByName ( Argv[3], &FileHandle, (EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE), 0 ); if (EFI_ERROR (Status)) { Print (L"Create file is failed!\n"); goto Exit; } // Getting file information FileInfo = ShellGetFileInfo (FileHandle); if (FileInfo->FileSize != 0) { ShellDeleteFile (&FileHandle); Status = ShellOpenFileByName ( Argv[3], &FileHandle, (EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE), 0 ); if (EFI_ERROR (Status)) { Print (L"Create file is failed!\n"); goto Exit; } } // Allocating the file buffer. BufSize = BlockCount * BLOCK_SIZE_64K; Status = gBS->AllocatePages ( AllocateAnyPages, EfiBootServicesData, EFI_SIZE_TO_PAGES(BufSize), (EFI_PHYSICAL_ADDRESS *) (&FileBuf) ); if(EFI_ERROR(Status)){ Print (L"\n Allocate Memory Error %r\n", Status); goto Exit; } Operation = OP_DUMP; } else if (((StrCmp(Argv[1], L"-w") == 0) || (StrCmp(Argv[1], L"-W") == 0)) && (Argc == 3)) { // Written EC Binary to EC ROM Operation = OP_PROG; Status = ShellOpenFileByName( Argv[2], &FileHandle, (EFI_FILE_MODE_READ), 0 ); if (EFI_ERROR (Status)) { Print (L"Open file is failed!\n"); goto Exit; } // Getting the file size. Status = ShellGetFileSize (FileHandle, &FileSize); if (EFI_ERROR (Status)) { Print (L"Can't get the file size!\n"); goto Exit; } if (FileSize == 0 ) { Print (L"Invalid the file size!\n"); goto Exit; } //Print (L"File Size = %d Bytes\n", FileSize); // Get the block number with the file. BlockCount = FileSize / BLOCK_SIZE_64K; if ( (FileSize % 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 *) (&FileBuf) ); if(EFI_ERROR(Status)){ Print(L"\n Allocate Memory Error %r\n", Status); goto Exit; } // Using 0xFF to fill the file buffer. SetMem (FileBuf, BufSize, 0xFF); Status = ShellReadFile (FileHandle, &BufSize, FileBuf); if (EFI_ERROR(Status)) { Print (L"Reading EC File Error %r\n",Status); goto Exit; } IteSign = *(UINT64 *)(UINTN)(FileBuf + ITE_8386_ID_OFFSET); Print (L"EC ROM SIGNATURE = %lxH\n", IteSign); if (IteSign != ITE_8386_ID) { Print (L"It's not one valid EC ROM file!\n"); goto Exit; } } else { // Incorrectly input parameters. Status = OpHelp(); 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; } // Getting EC ID OpIdentify (); switch (Operation) { // Dump EC ROM case OP_DUMP: Status = OpRead64K (FileBuf, BlockCount); if (EFI_ERROR (Status)) { Print (L"Reading EC ROM Error %r\n", Status); goto Exit; } Status = ShellWriteFile (FileHandle, &BufSize, FileBuf); if (EFI_ERROR(Status)) { Print (L"Written File Error %r\n", Status); goto Exit; } ShellCloseFile (&FileHandle); if(FileBuf != NULL) { gBS->FreePages ((EFI_PHYSICAL_ADDRESS)(UINTN)FileBuf, EFI_SIZE_TO_PAGES(BufSize)); } Print (L" \nReading EC ROM onto [%s] successfully!\n", Argv[3]); break; // Program EC ROM case OP_PROG: Status = OpWrite64K (FileBuf, BlockCount); if (EFI_ERROR(Status)) { Print (L"Program EC ROM Error %r\n",Status); goto Exit; } break; // Helpping Message case OP_HELP: default: Status = OpHelp(); break; } Exit: if(EcAd) { SendKbCmd (0xAE); gBS->Stall (10 * 1000 * 1000); SendEcCmd (0xFE); // return to shell } if(FileBuf != NULL) { gBS->FreePages ((EFI_PHYSICAL_ADDRESS)(UINTN)FileBuf, EFI_SIZE_TO_PAGES(BufSize)); } if(FileHandle != NULL) { ShellCloseFile (&FileHandle); } gST->ConOut->EnableCursor (gST->ConOut, TRUE); return Status; } // 1K Unit /** UEFI application entry point which has an interface similar to a standard C main function. The ShellCEntryLib library instance wrappers the actual UEFI application entry point and calls this ShellAppMain function. @param ImageHandle The image handle of the UEFI Application. @param SystemTable A pointer to the EFI System Table. @retval 0 The application exited normally. @retval Other An error occurred. **/ INTN EFIAPI ShellAppMain ( IN UINTN Argc, IN CHAR16 **Argv ) { EFI_STATUS Status = EFI_SUCCESS; UINT8 *FileBuf = NULL; UINTN BufSize = 0; OPERATION_EC Operation = OP_HELP; SHELL_FILE_HANDLE FileHandle = NULL; BOOLEAN EcAd = FALSE; UINT64 IteSign; UINT64 FileSize; UINTN BlockCount; CHAR16 *ParamPtr = NULL; EFI_FILE_INFO *FileInfo = NULL; UINTN ProgRomRetryCount = 3; // Showing Copyright ShowVersion (); // Checking input parameters. if (Argc < 3) { Status = OpHelp(); goto Exit; } if (((StrCmp(Argv[1], L"-r") == 0) || (StrCmp(Argv[1], L"-R") == 0)) && (Argc == 4)) { // Reading EC Binary from EC ROM // Getting the block count for this EC ROM. ParamPtr = Argv[2]; // Checking the bank count. if ((ParamPtr[0] == L'-') && ((ParamPtr[1] ==L'b' ) ||(ParamPtr[1] ==L'B' )) && (ParamPtr[2] == L':') ) { BlockCount = StrDecimalToUintn(ParamPtr + 3); if (BlockCount == 0) { Print (L"It's not one valid EC ROM size! [%s]\n", ParamPtr + 3); goto Exit; } } else { Print (L"It's not one valid EC ROM size parameter! [%s]\n", Argv[2]); goto Exit; } Status = ShellOpenFileByName ( Argv[3], &FileHandle, (EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE), 0 ); if (EFI_ERROR (Status)) { Print (L"Create file is failed!\n"); goto Exit; } // Getting file information FileInfo = ShellGetFileInfo (FileHandle); if (FileInfo->FileSize != 0) { ShellDeleteFile (&FileHandle); Status = ShellOpenFileByName ( Argv[3], &FileHandle, (EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE), 0 ); if (EFI_ERROR (Status)) { Print (L"Create file is failed!\n"); goto Exit; } } // Allocating the file buffer. BufSize = BlockCount * BLOCK_SIZE_1K; Status = gBS->AllocatePages ( AllocateAnyPages, EfiBootServicesData, EFI_SIZE_TO_PAGES(BufSize), (EFI_PHYSICAL_ADDRESS *) (&FileBuf) ); if(EFI_ERROR(Status)){ Print (L"\n Allocate Memory Error %r\n", Status); goto Exit; } Operation = OP_DUMP; } else if (((StrCmp(Argv[1], L"-w") == 0) || (StrCmp(Argv[1], L"-W") == 0)) && (Argc == 3)) { // Written EC Binary to EC ROM Operation = OP_PROG; Status = ShellOpenFileByName( Argv[2], &FileHandle, (EFI_FILE_MODE_READ), 0 ); if (EFI_ERROR (Status)) { Print (L"Open file is failed!\n"); goto Exit; } // Getting the file size. Status = ShellGetFileSize (FileHandle, &FileSize); if (EFI_ERROR (Status)) { Print (L"Can't get the file size!\n"); goto Exit; } if (FileSize == 0 ) { Print (L"Invalid the file size, it must be integer times of 1K bytes.\n"); goto Exit; } //Print (L"File Size = %d Bytes\n", FileSize); // Get the block number with the file. BlockCount = FileSize / BLOCK_SIZE_1K; if ( (FileSize % BLOCK_SIZE_1K) != 0) { Print (L"Invalid the file size, it must be integer times of 1K bytes.\n"); goto Exit; } //Print (L"Total Blocks = %d (UNIT: 1K Byte)\n", BlockCount); // Allocating file buffer. BufSize = BlockCount * BLOCK_SIZE_1K; Status = gBS->AllocatePages ( AllocateAnyPages, EfiBootServicesData, EFI_SIZE_TO_PAGES(BufSize), (EFI_PHYSICAL_ADDRESS *) (&FileBuf) ); if(EFI_ERROR(Status)){ Print(L"\n Allocate Memory Error %r\n", Status); goto Exit; } // Using 0xFF to fill the file buffer. SetMem (FileBuf, BufSize, 0xFF); Status = ShellReadFile (FileHandle, &BufSize, FileBuf); if (EFI_ERROR(Status)) { Print (L"Reading EC File Error %r\n",Status); goto Exit; } IteSign = *(UINT64 *)(UINTN)(FileBuf + ITE_8386_ID_OFFSET); if (IteSign != ITE_8386_ID) { IteSign = *(UINT64 *)(UINTN)(FileBuf + ITE_8586_ID_OFFSET); if (IteSign != ITE_8586_ID) { Print (L"EC ROM SIGNATURE = %lxH\n", IteSign); Print (L"It's not one valid EC ROM file!\n"); goto Exit; } else { Print (L"EC ROM SIGNATURE = %lxH\n", IteSign); } } else { Print (L"EC ROM SIGNATURE = %lxH\n", IteSign); } } else { // Incorrectly input parameters. Status = OpHelp(); 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; } // Getting EC ID OpIdentify (); switch (Operation) { // Dump EC ROM case OP_DUMP: Status = OpRead1K (FileBuf, BlockCount); if (EFI_ERROR (Status)) { Print (L"Reading EC ROM Error %r\n", Status); goto Exit; } Status = ShellWriteFile (FileHandle, &BufSize, FileBuf); if (EFI_ERROR(Status)) { Print (L"Written File Error %r\n", Status); goto Exit; } ShellCloseFile (&FileHandle); if(FileBuf != NULL) { gBS->FreePages ((EFI_PHYSICAL_ADDRESS)(UINTN)FileBuf, EFI_SIZE_TO_PAGES(BufSize)); } Print (L"Reading EC ROM onto [%s] successfully!\n", Argv[3]); break; // Program EC ROM case OP_PROG: // 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 (FileBuf, 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" \nProgram EC ROM Failure \n "); ProgRomRetryCount--; }while (ProgRomRetryCount != 0); // Stopping the machine when program EC ROM failed. if (ProgRomRetryCount == 0) { while (1); } break; // Helpping Message case OP_HELP: default: Status = OpHelp(); break; } Exit: if(EcAd) { SendKbCmd (0xAE); gBS->Stall (10 * 1000 * 1000); SendEcCmd (0xFE); // return to shell } if(FileBuf != NULL) { gBS->FreePages ((EFI_PHYSICAL_ADDRESS)(UINTN)FileBuf, EFI_SIZE_TO_PAGES(BufSize)); } if(FileHandle != NULL) { ShellCloseFile (&FileHandle); } gST->ConOut->EnableCursor (gST->ConOut, TRUE); return Status; }