3 Copyright (c) 2007 - 2015, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials are licensed and made available under
6 the terms and conditions of the BSD License that accompanies this distribution.
7 The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php.
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
16 #include "FirmwareUpdate.h"
18 EFI_HII_HANDLE HiiHandle
;
21 // MinnowMax Flash Layout
23 //Start (hex) End (hex) Length (hex) Area Name
24 //----------- --------- ------------ ---------
25 //00000000 007FFFFF 00800000 Flash Image
27 //00000000 00000FFF 00001000 Descriptor Region
28 //00001000 003FFFFF 003FF000 TXE Region
29 //00500000 007FFFFF 00400000 BIOS Region
31 FV_REGION_INFO mRegionInfo
[] = {
32 {FixedPcdGet32 (PcdFlashDescriptorBase
), FixedPcdGet32 (PcdFlashDescriptorSize
), TRUE
},
33 {FixedPcdGet32 (PcdTxeRomBase
), FixedPcdGet32 (PcdTxeRomSize
), TRUE
},
34 {FixedPcdGet32 (PcdBiosRomBase
), FixedPcdGet32 (PcdBiosRomSize
), TRUE
}
37 UINTN mRegionInfoCount
= ARRAY_SIZE (mRegionInfo
);
39 FV_INPUT_DATA mInputData
= {0};
41 EFI_SPI_PROTOCOL
*mSpiProtocol
;
45 IN EFI_PHYSICAL_ADDRESS Address
,
46 OUT UINTN
*RegionIndex
51 for (Index
= 0; Index
< mRegionInfoCount
; Index
++) {
52 if (Address
>= mRegionInfo
[Index
].Base
&&
53 Address
< (mRegionInfo
[Index
].Base
+ mRegionInfo
[Index
].Size
)
60 if (Index
>= mRegionInfoCount
) {
68 IN EFI_PHYSICAL_ADDRESS Address
74 if (mInputData
.FullFlashUpdate
) {
78 Status
= GetRegionIndex (Address
, &Index
);
79 if ((!EFI_ERROR(Status
)) && mRegionInfo
[Index
].Update
) {
88 IN EFI_PHYSICAL_ADDRESS Address
,
95 Status
= GetRegionIndex (Address
, &Index
);
96 if (!EFI_ERROR(Status
)) {
97 mRegionInfo
[Index
].Update
= Update
;
105 IN CONST CHAR16
*Format
,
106 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*Console
,
115 ASSERT (Format
!= NULL
);
116 ASSERT (((UINTN
) Format
& BIT0
) == 0);
117 ASSERT (Console
!= NULL
);
119 BufferSize
= (PcdGet32 (PcdUefiLibMaxPrintBufferSize
) + 1) * sizeof (CHAR16
);
121 Buffer
= (CHAR16
*) AllocatePool(BufferSize
);
122 ASSERT (Buffer
!= NULL
);
124 Return
= UnicodeVSPrint (Buffer
, BufferSize
, Format
, Marker
);
126 if (Console
!= NULL
&& Return
> 0) {
128 // To be extra safe make sure Console has been initialized.
130 Status
= Console
->OutputString (Console
, Buffer
);
131 if (EFI_ERROR (Status
)) {
145 IN EFI_HII_HANDLE Handle
,
153 VA_START (Marker
, Handle
);
155 Format
= HiiGetString (Handle
, Token
, NULL
);
156 ASSERT (Format
!= NULL
);
158 Return
= InternalPrintToken (Format
, gST
->ConOut
, Marker
);
177 // Check to make sure that the command line has enough arguments for minimal
178 // operation. The minimum is just the file name.
180 if (Argc
< 2 || Argc
> 4) {
181 return EFI_INVALID_PARAMETER
;
185 // Loop through command line arguments.
187 for (Index
= 1; Index
< Argc
; Index
++) {
189 // Make sure the string is valid.
191 if (StrLen (Argv
[Index
]) == 0) {;
192 PrintToken (STRING_TOKEN (STR_FWUPDATE_ZEROLENGTH_ARG
), HiiHandle
);
193 return EFI_INVALID_PARAMETER
;
197 // Check to see if this is an option or the file name.
199 if ((Argv
[Index
])[0] == L
'-' || (Argv
[Index
])[0] == L
'/') {
201 // Parse the arguments.
203 if ((StrCmp (Argv
[Index
], L
"-h") == 0) ||
204 (StrCmp (Argv
[Index
], L
"--help") == 0) ||
205 (StrCmp (Argv
[Index
], L
"/?") == 0) ||
206 (StrCmp (Argv
[Index
], L
"/h") == 0)) {
208 // Print Help Information.
210 return EFI_INVALID_PARAMETER
;
211 } else if (StrCmp (Argv
[Index
], L
"-m") == 0) {
213 // Parse the MAC address here.
215 Status
= ConvertMac(Argv
[Index
+1]);
216 if (EFI_ERROR(Status
)) {
217 PrintToken (STRING_TOKEN (STR_FWUPDATE_INVAILD_MAC
), HiiHandle
);
222 // Save the MAC address to mInputData.MacValue.
224 mInputData
.UpdateMac
= TRUE
;
228 // Invalid option was provided.
230 return EFI_INVALID_PARAMETER
;
233 if ((Index
== Argc
- 1) && (StrCmp (Argv
[Index
- 1], L
"-m") != 0)) {
235 // The only parameter that is not an option is the firmware image. Check
236 // to make sure that the file exists.
238 Status
= ShellIsFile (Argv
[Index
]);
239 if (EFI_ERROR (Status
)) {
240 PrintToken (STRING_TOKEN (STR_FWUPDATE_FILE_NOT_FOUND_ERROR
), HiiHandle
, Argv
[Index
]);
241 return EFI_INVALID_PARAMETER
;
243 if (StrLen (Argv
[Index
]) > INPUT_STRING_LEN
) {
244 PrintToken (STRING_TOKEN (STR_FWUPDATE_PATH_ERROR
), HiiHandle
, Argv
[Index
]);
245 return EFI_INVALID_PARAMETER
;
247 StrCpy (mInputData
.FileName
, Argv
[Index
]);
248 mInputData
.UpdateFromFile
= TRUE
;
268 EFI_PHYSICAL_ADDRESS Address
;
271 BOOLEAN ResetRequired
;
281 ResetRequired
= FALSE
;
284 Status
= EFI_SUCCESS
;
286 mInputData
.FullFlashUpdate
= TRUE
;
289 // Publish our HII data.
291 HiiHandle
= HiiAddPackages (
294 FirmwareUpdateStrings
,
297 if (HiiHandle
== NULL
) {
298 Status
= EFI_OUT_OF_RESOURCES
;
303 // Locate the SPI protocol.
305 Status
= gBS
->LocateProtocol (
306 &gEfiSpiProtocolGuid
,
308 (VOID
**)&mSpiProtocol
310 if (EFI_ERROR (Status
)) {
311 PrintToken (STRING_TOKEN (STR_SPI_NOT_FOUND
), HiiHandle
);
312 return EFI_DEVICE_ERROR
;
316 // Parse the command line.
318 Status
= ParseCommandLine (Argc
, Argv
);
319 if (EFI_ERROR (Status
)) {
321 Status
= EFI_SUCCESS
;
326 // Display sign-on information.
328 PrintToken (STRING_TOKEN (STR_FWUPDATE_FIRMWARE_VOL_UPDATE
), HiiHandle
);
329 PrintToken (STRING_TOKEN (STR_FWUPDATE_VERSION
), HiiHandle
);
330 PrintToken (STRING_TOKEN (STR_FWUPDATE_COPYRIGHT
), HiiHandle
);
333 // Test to see if the firmware needs to be updated.
335 if (mInputData
.UpdateFromFile
) {
337 // Get the file to use in the update.
339 PrintToken (STRING_TOKEN (STR_FWUPDATE_READ_FILE
), HiiHandle
, mInputData
.FileName
);
340 Status
= ReadFileData (mInputData
.FileName
, &FileBuffer
, &FileSize
);
341 if (EFI_ERROR (Status
)) {
342 PrintToken (STRING_TOKEN (STR_FWUPDATE_READ_FILE_ERROR
), HiiHandle
, mInputData
.FileName
);
347 // Check that the file and flash sizes match.
349 if (FileSize
!= PcdGet32 (PcdFlashChipSize
)) {
350 PrintToken (STRING_TOKEN (STR_FWUPDATE_SIZE
), HiiHandle
);
351 Status
= EFI_UNSUPPORTED
;
356 // Display flash update information.
358 PrintToken (STRING_TOKEN (STR_FWUPDATE_UPDATING_FIRMWARE
), HiiHandle
);
364 BufferSize
= FileSize
;
365 Address
= PcdGet32 (PcdFlashChipBase
);
366 CountOfBlocks
= (UINTN
) (BufferSize
/ BLOCK_SIZE
);
369 // Raise TPL to TPL_NOTIFY to block any event handler,
370 // while still allowing RaiseTPL(TPL_NOTIFY) within
371 // output driver during Print().
373 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
374 for (Index
= 0; Index
< CountOfBlocks
; Index
++) {
376 // Handle block based on address and contents.
378 if (!UpdateBlock (Address
)) {
379 DEBUG((EFI_D_INFO
, "Skipping block at 0x%lx\n", Address
));
380 } else if (!EFI_ERROR (InternalCompareBlock (Address
, Buffer
))) {
381 DEBUG((EFI_D_INFO
, "Skipping block at 0x%lx (already programmed)\n", Address
));
384 // Display a dot for each block being updated.
389 // Flag that the flash image will be changed and the system must be rebooted
390 // to use the change.
392 ResetRequired
= TRUE
;
395 // Make updating process uninterruptable,
396 // so that the flash memory area is not accessed by other entities
397 // which may interfere with the updating process.
399 Status
= InternalEraseBlock (Address
);
400 ASSERT_EFI_ERROR(Status
);
401 if (EFI_ERROR (Status
)) {
402 gBS
->RestoreTPL (OldTpl
);
406 Status
= InternalWriteBlock (
409 (BufferSize
> BLOCK_SIZE
? BLOCK_SIZE
: BufferSize
)
411 if (EFI_ERROR (Status
)) {
412 gBS
->RestoreTPL (OldTpl
);
419 // Move to next block to update.
421 Address
+= BLOCK_SIZE
;
422 Buffer
+= BLOCK_SIZE
;
423 if (BufferSize
> BLOCK_SIZE
) {
424 BufferSize
-= BLOCK_SIZE
;
429 gBS
->RestoreTPL (OldTpl
);
432 // Print result of update.
437 PrintToken (STRING_TOKEN (STR_FWUPDATE_UPDATE_SUCCESS
), HiiHandle
);
439 PrintToken (STRING_TOKEN (STR_FWUPDATE_NO_RESET
), HiiHandle
);
447 // All flash updates are done so see if the system needs to be reset.
449 if (ResetRequired
&& !FlashError
) {
451 // Update successful.
453 for (Index
= 5; Index
> 0; Index
--) {
454 PrintToken (STRING_TOKEN (STR_FWUPDATE_SHUTDOWN
), HiiHandle
, Index
);
455 gBS
->Stall (1000000);
458 gRT
->ResetSystem (EfiResetShutdown
, EFI_SUCCESS
, 0, NULL
);
459 PrintToken (STRING_TOKEN (STR_FWUPDATE_MANUAL_RESET
), HiiHandle
);
465 // Print flash update failure message if error detected.
468 PrintToken (STRING_TOKEN (STR_FWUPDATE_UPDATE_FAILED
), HiiHandle
, Index
);
474 if (HiiHandle
!= NULL
) {
475 HiiRemovePackages (HiiHandle
);
478 gBS
->FreePool (FileBuffer
);
487 IN EFI_PHYSICAL_ADDRESS BaseAddress
493 Erase the whole block.
497 BaseAddress - Base address of the block to be erased.
501 EFI_SUCCESS - The command completed successfully.
502 Other - Device error or wirte-locked, operation failed.
509 NumBytes
= BLOCK_SIZE
;
511 Status
= SpiFlashBlockErase ((UINTN
) BaseAddress
, &NumBytes
);
520 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
527 BlockSize
= BLOCK_SIZE
;
529 Status
= SpiFlashRead ((UINTN
) BaseAddress
, &BlockSize
, ReadBuffer
);
537 InternalCompareBlock (
538 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
547 NumBytes
= BLOCK_SIZE
;
548 CompareBuffer
= AllocatePool (NumBytes
);
549 if (CompareBuffer
== NULL
) {
550 Status
= EFI_OUT_OF_RESOURCES
;
554 Status
= SpiFlashRead ((UINTN
) BaseAddress
, &NumBytes
, CompareBuffer
);
555 if (EFI_ERROR (Status
)) {
558 CompareResult
= CompareMem (CompareBuffer
, Buffer
, BLOCK_SIZE
);
559 if (CompareResult
!= 0) {
560 Status
= EFI_VOLUME_CORRUPTED
;
564 if (CompareBuffer
!= NULL
) {
565 FreePool (CompareBuffer
);
574 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
582 Write a block of data.
586 BaseAddress - Base address of the block.
587 Buffer - Data buffer.
588 BufferSize - Size of the buffer.
592 EFI_SUCCESS - The command completed successfully.
593 EFI_INVALID_PARAMETER - Invalid parameter, can not proceed.
594 Other - Device error or wirte-locked, operation failed.
600 Status
= SpiFlashWrite ((UINTN
) BaseAddress
, &BufferSize
, Buffer
);
601 ASSERT_EFI_ERROR(Status
);
602 if (EFI_ERROR (Status
)) {
603 DEBUG((EFI_D_ERROR
, "\nFlash write error."));
607 WriteBackInvalidateDataCacheRange ((VOID
*) (UINTN
) BaseAddress
, BLOCK_SIZE
);
609 Status
= InternalCompareBlock (BaseAddress
, Buffer
);
610 if (EFI_ERROR (Status
)) {
611 DEBUG((EFI_D_ERROR
, "\nError when writing to BaseAddress %lx with different at offset %x.", BaseAddress
, Status
));
613 DEBUG((EFI_D_INFO
, "\nVerified data written to Block at %lx is correct.", BaseAddress
));
625 OUT UINT32
*BufferSize
629 SHELL_FILE_HANDLE FileHandle
;
638 Status
= ShellOpenFileByName (FileName
, &FileHandle
, EFI_FILE_MODE_READ
, 0);
639 if (EFI_ERROR (Status
)) {
643 Status
= FileHandleIsDirectory (FileHandle
);
644 if (!EFI_ERROR (Status
)) {
645 Status
= EFI_NOT_FOUND
;
649 Status
= FileHandleGetSize (FileHandle
, &Size
);
650 if (EFI_ERROR (Status
)) {
654 NewBuffer
= AllocatePool ((UINTN
) Size
);
656 ReadSize
= (UINTN
) Size
;
657 Status
= FileHandleRead (FileHandle
, &ReadSize
, NewBuffer
);
658 if (EFI_ERROR (Status
)) {
660 } else if (ReadSize
!= (UINTN
) Size
) {
661 Status
= EFI_INVALID_PARAMETER
;
666 if (FileHandle
!= NULL
) {
667 ShellCloseFile (&FileHandle
);
670 if (EFI_ERROR (Status
)) {
671 if (NewBuffer
!= NULL
) {
672 FreePool (NewBuffer
);
676 *BufferSize
= (UINT32
) Size
;
691 Print out help information.
703 PrintToken (STRING_TOKEN (STR_FWUPDATE_FIRMWARE_VOL_UPDATE
), HiiHandle
);
704 PrintToken (STRING_TOKEN (STR_FWUPDATE_VERSION
), HiiHandle
);
705 PrintToken (STRING_TOKEN (STR_FWUPDATE_COPYRIGHT
), HiiHandle
);
708 PrintToken (STRING_TOKEN (STR_FWUPDATE_USAGE
), HiiHandle
);
709 PrintToken (STRING_TOKEN (STR_FWUPDATE_USAGE_1
), HiiHandle
);
710 PrintToken (STRING_TOKEN (STR_FWUPDATE_USAGE_2
), HiiHandle
);
711 PrintToken (STRING_TOKEN (STR_FWUPDATE_USAGE_3
), HiiHandle
);
712 PrintToken (STRING_TOKEN (STR_FWUPDATE_USAGE_4
), HiiHandle
);
718 Read NumBytes bytes of data from the address specified by
719 PAddress into Buffer.
721 @param[in] Address The starting physical address of the read.
722 @param[in,out] NumBytes On input, the number of bytes to read. On output, the number
723 of bytes actually read.
724 @param[out] Buffer The destination data buffer for the read.
726 @retval EFI_SUCCESS Opertion is successful.
727 @retval EFI_DEVICE_ERROR If there is any device errors.
734 IN OUT UINT32
*NumBytes
,
738 EFI_STATUS Status
= EFI_SUCCESS
;
741 ASSERT ((NumBytes
!= NULL
) && (Buffer
!= NULL
));
743 Offset
= Address
- (UINTN
)PcdGet32 (PcdFlashChipBase
);
745 Status
= mSpiProtocol
->Execute (
762 Write NumBytes bytes of data from Buffer to the address specified by
765 @param[in] Address The starting physical address of the write.
766 @param[in,out] NumBytes On input, the number of bytes to write. On output,
767 the actual number of bytes written.
768 @param[in] Buffer The source data buffer for the write.
770 @retval EFI_SUCCESS Opertion is successful.
771 @retval EFI_DEVICE_ERROR If there is any device errors.
778 IN OUT UINT32
*NumBytes
,
785 UINT32 RemainingBytes
;
787 ASSERT ((NumBytes
!= NULL
) && (Buffer
!= NULL
));
788 ASSERT (Address
>= (UINTN
)PcdGet32 (PcdFlashChipBase
));
790 Offset
= Address
- (UINTN
)PcdGet32 (PcdFlashChipBase
);
792 ASSERT ((*NumBytes
+ Offset
) <= (UINTN
)PcdGet32 (PcdFlashChipSize
));
794 Status
= EFI_SUCCESS
;
795 RemainingBytes
= *NumBytes
;
797 while (RemainingBytes
> 0) {
798 if (RemainingBytes
> SIZE_4KB
) {
801 Length
= RemainingBytes
;
803 Status
= mSpiProtocol
->Execute (
815 if (EFI_ERROR (Status
)) {
818 RemainingBytes
-= Length
;
824 // Actual number of bytes written.
826 *NumBytes
-= RemainingBytes
;
832 Erase the block starting at Address.
834 @param[in] Address The starting physical address of the block to be erased.
835 This library assume that caller garantee that the PAddress
836 is at the starting address of this block.
837 @param[in] NumBytes On input, the number of bytes of the logical block to be erased.
838 On output, the actual number of bytes erased.
840 @retval EFI_SUCCESS. Opertion is successful.
841 @retval EFI_DEVICE_ERROR If there is any device errors.
853 UINTN RemainingBytes
;
855 ASSERT (NumBytes
!= NULL
);
856 ASSERT (Address
>= (UINTN
)PcdGet32 (PcdFlashChipBase
));
858 Offset
= Address
- (UINTN
)PcdGet32 (PcdFlashChipBase
);
860 ASSERT ((*NumBytes
% SIZE_4KB
) == 0);
861 ASSERT ((*NumBytes
+ Offset
) <= (UINTN
)PcdGet32 (PcdFlashChipSize
));
863 Status
= EFI_SUCCESS
;
864 RemainingBytes
= *NumBytes
;
866 while (RemainingBytes
> 0) {
867 Status
= mSpiProtocol
->Execute (
879 if (EFI_ERROR (Status
)) {
882 RemainingBytes
-= SIZE_4KB
;
887 // Actual number of bytes erased.
889 *NumBytes
-= RemainingBytes
;
901 UINT8 Temp
[MAC_ADD_STR_LEN
];
904 return EFI_INVALID_PARAMETER
;
906 if (StrLen(Str
) != MAC_ADD_STR_LEN
)
907 return EFI_INVALID_PARAMETER
;
909 for (Index
= 0; Index
< MAC_ADD_STR_LEN
; Index
++) {
910 if (Str
[Index
] >= 0x30 && Str
[Index
] <= 0x39) {
911 Temp
[Index
] = (UINT8
)Str
[Index
] - 0x30;
912 } else if (Str
[Index
] >= 0x41 && Str
[Index
] <= 0x46) {
913 Temp
[Index
] = (UINT8
)Str
[Index
] - 0x37;
914 } else if (Str
[Index
] >= 0x61 && Str
[Index
] <= 0x66) {
915 Temp
[Index
] = (UINT8
)Str
[Index
] - 0x57;
917 return EFI_INVALID_PARAMETER
;
921 for (Index
= 0; Index
< MAC_ADD_BYTE_COUNT
; Index
++) {
922 mInputData
.MacValue
[Index
] = (Temp
[2 * Index
] << 4) + Temp
[2 * Index
+ 1];