3 Internal generic functions to operate flash block.
5 Copyright (c) 2006 - 2008, Intel Corporation
6 All rights reserved. This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
20 Check whether a flash buffer is erased.
23 @param Polarity All 1 or all 0
24 @param Buffer Buffer to check
25 @param BufferSize Size of the buffer
27 @return A BOOLEAN value indicating erased or not.
47 while ((BufferSize
--) != 0) {
48 if (*Ptr
++ != ErasedValue
) {
57 To erase the block with the spare block size.
60 @param FtwLiteDevice Calling context
61 @param FvBlock FVB Protocol interface
62 @param Lba Lba of the firmware block
64 @retval EFI_SUCCESS Block LBA is Erased successfully
65 @retval Others Error occurs
70 IN EFI_FTW_LITE_DEVICE
*FtwLiteDevice
,
71 EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL
*FvBlock
,
75 return FvBlock
->EraseBlocks (
78 FtwLiteDevice
->NumberOfSpareBlock
,
79 EFI_LBA_LIST_TERMINATOR
88 @param FtwLiteDevice Calling context
90 @retval EFI_SUCCESS The erase request was successfully
93 @retval EFI_ACCESS_DENIED The firmware volume is in the
95 @retval EFI_DEVICE_ERROR The block device is not functioning
96 correctly and could not be written.
97 The firmware device may have been
99 @retval EFI_INVALID_PARAMETER One or more of the LBAs listed
100 in the variable argument list do
101 not exist in the firmware volume.
107 IN EFI_FTW_LITE_DEVICE
*FtwLiteDevice
110 return FtwLiteDevice
->FtwBackupFvb
->EraseBlocks (
111 FtwLiteDevice
->FtwBackupFvb
,
112 FtwLiteDevice
->FtwSpareLba
,
113 FtwLiteDevice
->NumberOfSpareBlock
,
114 EFI_LBA_LIST_TERMINATOR
119 Retrive the proper FVB protocol interface by HANDLE.
122 @param FvBlockHandle The handle of FVB protocol that provides services for
123 reading, writing, and erasing the target block.
124 @param FvBlock The interface of FVB protocol
126 @retval EFI_SUCCESS The function completed successfully
127 @retval EFI_ABORTED The function could not complete successfully
132 IN EFI_HANDLE FvBlockHandle
,
133 OUT EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL
**FvBlock
137 // To get the FVB protocol interface on the handle
139 return gBS
->HandleProtocol (
141 &gEfiFirmwareVolumeBlockProtocolGuid
,
148 Get firmware block by address.
151 @param Address Address specified the block
152 @param FvBlock The block caller wanted
154 @retval EFI_SUCCESS The protocol instance if found.
155 @retval EFI_NOT_FOUND Block not found
160 IN EFI_PHYSICAL_ADDRESS Address
,
161 OUT EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL
**FvBlock
165 EFI_HANDLE
*HandleBuffer
;
168 EFI_PHYSICAL_ADDRESS FvbBaseAddress
;
169 EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL
*Fvb
;
170 EFI_FIRMWARE_VOLUME_HEADER
*FwVolHeader
;
174 // Locate all handles of Fvb protocol
176 Status
= gBS
->LocateHandleBuffer (
178 &gEfiFirmwareVolumeBlockProtocolGuid
,
183 if (EFI_ERROR (Status
)) {
184 return EFI_NOT_FOUND
;
187 // Search all FVB until find the right one
189 for (Index
= 0; Index
< HandleCount
; Index
+= 1) {
190 Status
= gBS
->HandleProtocol (
192 &gEfiFirmwareVolumeBlockProtocolGuid
,
195 if (EFI_ERROR (Status
)) {
196 Status
= EFI_NOT_FOUND
;
200 // Compare the address and select the right one
202 Status
= Fvb
->GetPhysicalAddress (Fvb
, &FvbBaseAddress
);
203 if (EFI_ERROR (Status
)) {
207 FwVolHeader
= (EFI_FIRMWARE_VOLUME_HEADER
*) ((UINTN
) FvbBaseAddress
);
208 if ((Address
>= FvbBaseAddress
) && (Address
<= (FvbBaseAddress
+ (FwVolHeader
->FvLength
- 1)))) {
210 Status
= EFI_SUCCESS
;
215 FreePool (HandleBuffer
);
221 Is it in working block?
224 @param FtwLiteDevice Calling context
225 @param FvBlock Fvb protocol instance
226 @param Lba The block specified
228 @return A BOOLEAN value indicating in working block or not.
233 EFI_FTW_LITE_DEVICE
*FtwLiteDevice
,
234 EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL
*FvBlock
,
239 // If matching the following condition, the target block is in working block.
240 // 1. Target block is on the FV of working block (Using the same FVB protocol instance).
241 // 2. Lba falls into the range of working block.
245 (FvBlock
== FtwLiteDevice
->FtwFvBlock
) &&
246 (Lba
>= FtwLiteDevice
->FtwWorkBlockLba
) &&
247 (Lba
<= FtwLiteDevice
->FtwWorkSpaceLba
)
252 Copy the content of spare block to a target block. Size is FTW_BLOCK_SIZE.
253 Spare block is accessed by FTW backup FVB protocol interface. LBA is
254 FtwLiteDevice->FtwSpareLba.
255 Target block is accessed by FvBlock protocol interface. LBA is Lba.
258 @param FtwLiteDevice The private data of FTW_LITE driver
259 @param FvBlock FVB Protocol interface to access target block
260 @param Lba Lba of the target block
262 @retval EFI_SUCCESS Spare block content is copied to target block
263 @retval EFI_INVALID_PARAMETER Input parameter error
264 @retval EFI_OUT_OF_RESOURCES Allocate memory error
265 @retval EFI_ABORTED The function could not complete successfully
269 FlushSpareBlockToTargetBlock (
270 EFI_FTW_LITE_DEVICE
*FtwLiteDevice
,
271 EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL
*FvBlock
,
282 if ((FtwLiteDevice
== NULL
) || (FvBlock
== NULL
)) {
283 return EFI_INVALID_PARAMETER
;
286 // Allocate a memory buffer
288 Length
= FtwLiteDevice
->SpareAreaLength
;
289 Buffer
= AllocatePool (Length
);
290 if (Buffer
== NULL
) {
291 return EFI_OUT_OF_RESOURCES
;
294 // Read all content of spare block to memory buffer
297 for (Index
= 0; Index
< FtwLiteDevice
->NumberOfSpareBlock
; Index
+= 1) {
298 Count
= FtwLiteDevice
->BlockSize
;
299 Status
= FtwLiteDevice
->FtwBackupFvb
->Read (
300 FtwLiteDevice
->FtwBackupFvb
,
301 FtwLiteDevice
->FtwSpareLba
+ Index
,
306 if (EFI_ERROR (Status
)) {
314 // Erase the target block
316 Status
= FtwEraseBlock (FtwLiteDevice
, FvBlock
, Lba
);
317 if (EFI_ERROR (Status
)) {
322 // Write memory buffer to block, using the FvbBlock protocol interface
325 for (Index
= 0; Index
< FtwLiteDevice
->NumberOfSpareBlock
; Index
+= 1) {
326 Count
= FtwLiteDevice
->BlockSize
;
327 Status
= FvBlock
->Write (FvBlock
, Lba
+ Index
, 0, &Count
, Ptr
);
328 if (EFI_ERROR (Status
)) {
329 DEBUG ((EFI_D_ERROR
, "FtwLite: FVB Write block - %r\n", Status
));
343 Copy the content of spare block to working block. Size is FTW_BLOCK_SIZE.
344 Spare block is accessed by FTW backup FVB protocol interface. LBA is
345 FtwLiteDevice->FtwSpareLba.
346 Working block is accessed by FTW working FVB protocol interface. LBA is
347 FtwLiteDevice->FtwWorkBlockLba.
350 @param FtwLiteDevice The private data of FTW_LITE driver
352 @retval EFI_SUCCESS Spare block content is copied to target block
353 @retval EFI_OUT_OF_RESOURCES Allocate memory error
354 @retval EFI_ABORTED The function could not complete successfully
356 Since the working block header is important when FTW initializes, the
357 state of the operation should be handled carefully. The Crc value is
358 calculated without STATE element.
362 FlushSpareBlockToWorkingBlock (
363 EFI_FTW_LITE_DEVICE
*FtwLiteDevice
369 EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER
*WorkingBlockHeader
;
370 EFI_LBA WorkSpaceLbaOffset
;
376 // Allocate a memory buffer
378 Length
= FtwLiteDevice
->SpareAreaLength
;
379 Buffer
= AllocatePool (Length
);
380 if (Buffer
== NULL
) {
381 return EFI_OUT_OF_RESOURCES
;
384 // To guarantee that the WorkingBlockValid is set on spare block
386 // Offset = OFFSET_OF(EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER,
387 // WorkingBlockValid);
388 // To skip Signature and Crc: sizeof(EFI_GUID)+sizeof(UINT32).
390 WorkSpaceLbaOffset
= FtwLiteDevice
->FtwWorkSpaceLba
- FtwLiteDevice
->FtwWorkBlockLba
;
392 FtwLiteDevice
->FtwBackupFvb
,
393 FtwLiteDevice
->FtwSpareLba
+ WorkSpaceLbaOffset
,
394 FtwLiteDevice
->FtwWorkSpaceBase
+ sizeof (EFI_GUID
) + sizeof (UINT32
),
398 // Read from spare block to memory buffer
401 for (Index
= 0; Index
< FtwLiteDevice
->NumberOfSpareBlock
; Index
+= 1) {
402 Count
= FtwLiteDevice
->BlockSize
;
403 Status
= FtwLiteDevice
->FtwBackupFvb
->Read (
404 FtwLiteDevice
->FtwBackupFvb
,
405 FtwLiteDevice
->FtwSpareLba
+ Index
,
410 if (EFI_ERROR (Status
)) {
418 // Clear the CRC and STATE, copy data from spare to working block.
420 WorkingBlockHeader
= (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER
*) (Buffer
+ (UINTN
) WorkSpaceLbaOffset
* FtwLiteDevice
->BlockSize
+ FtwLiteDevice
->FtwWorkSpaceBase
);
421 InitWorkSpaceHeader (WorkingBlockHeader
);
422 WorkingBlockHeader
->WorkingBlockValid
= FTW_ERASE_POLARITY
;
423 WorkingBlockHeader
->WorkingBlockInvalid
= FTW_ERASE_POLARITY
;
426 // target block is working block, then
427 // Set WorkingBlockInvalid in EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER
428 // before erase the working block.
430 // Offset = OFFSET_OF(EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER,
431 // WorkingBlockInvalid);
432 // To skip Signature and Crc: sizeof(EFI_GUID)+sizeof(UINT32).
434 Status
= FtwUpdateFvState (
435 FtwLiteDevice
->FtwFvBlock
,
436 FtwLiteDevice
->FtwWorkSpaceLba
,
437 FtwLiteDevice
->FtwWorkSpaceBase
+ sizeof (EFI_GUID
) + sizeof (UINT32
),
438 WORKING_BLOCK_INVALID
440 if (EFI_ERROR (Status
)) {
445 FtwLiteDevice
->FtwWorkSpaceHeader
->WorkingBlockInvalid
= FTW_VALID_STATE
;
448 // Erase the working block
450 Status
= FtwEraseBlock (
452 FtwLiteDevice
->FtwFvBlock
,
453 FtwLiteDevice
->FtwWorkBlockLba
455 if (EFI_ERROR (Status
)) {
460 // Write memory buffer to working block, using the FvbBlock protocol interface
463 for (Index
= 0; Index
< FtwLiteDevice
->NumberOfSpareBlock
; Index
+= 1) {
464 Count
= FtwLiteDevice
->BlockSize
;
465 Status
= FtwLiteDevice
->FtwFvBlock
->Write (
466 FtwLiteDevice
->FtwFvBlock
,
467 FtwLiteDevice
->FtwWorkBlockLba
+ Index
,
472 if (EFI_ERROR (Status
)) {
473 DEBUG ((EFI_D_ERROR
, "FtwLite: FVB Write block - %r\n", Status
));
481 // Since the memory buffer will not be used, free memory Buffer.
486 // Update the VALID of the working block
488 // Offset = OFFSET_OF(EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER,
489 // WorkingBlockValid);
490 // Hardcode offset sizeof(EFI_GUID)+sizeof(UINT32), to skip Signature and Crc
492 Status
= FtwUpdateFvState (
493 FtwLiteDevice
->FtwFvBlock
,
494 FtwLiteDevice
->FtwWorkSpaceLba
,
495 FtwLiteDevice
->FtwWorkSpaceBase
+ sizeof (EFI_GUID
) + sizeof (UINT32
),
498 if (EFI_ERROR (Status
)) {
502 FtwLiteDevice
->FtwWorkSpaceHeader
->WorkingBlockValid
= FTW_VALID_STATE
;