3 Internal generic functions to support fault tolerant write.
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.
28 Check whether a flash buffer is erased.
32 Polarity - All 1 or all 0
33 Buffer - Buffer to check
34 BufferSize - Size of the buffer
52 while (BufferSize
--) {
53 if (*Ptr
++ != ErasedValue
) {
63 IN EFI_FTW_LITE_DEVICE
*FtwLiteDevice
,
64 EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL
*FvBlock
,
70 To Erase one block. The size is FTW_BLOCK_SIZE
73 FtwLiteDevice - Calling context
74 FvBlock - FVB Protocol interface
75 Lba - Lba of the firmware block
78 EFI_SUCCESS - Block LBA is Erased successfully
83 return FvBlock
->EraseBlocks (
86 FtwLiteDevice
->NumberOfSpareBlock
,
87 EFI_LBA_LIST_TERMINATOR
93 IN EFI_FTW_LITE_DEVICE
*FtwLiteDevice
103 FtwLiteDevice - Calling context
111 return FtwLiteDevice
->FtwBackupFvb
->EraseBlocks (
112 FtwLiteDevice
->FtwBackupFvb
,
113 FtwLiteDevice
->FtwSpareLba
,
114 FtwLiteDevice
->NumberOfSpareBlock
,
115 EFI_LBA_LIST_TERMINATOR
121 IN EFI_HANDLE FvBlockHandle
,
122 OUT EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL
**FvBlock
127 Retrive the proper FVB protocol interface by HANDLE.
130 FvBlockHandle - The handle of FVB protocol that provides services for
131 reading, writing, and erasing the target block.
132 FvBlock - The interface of FVB protocol
135 EFI_SUCCESS - The function completed successfully
136 EFI_ABORTED - The function could not complete successfully
140 // To get the FVB protocol interface on the handle
142 return gBS
->HandleProtocol (
144 &gEfiFirmwareVolumeBlockProtocolGuid
,
151 IN EFI_PHYSICAL_ADDRESS Address
,
152 OUT EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL
**FvBlock
158 Get firmware block by address.
162 Address - Address specified the block
163 FvBlock - The block caller wanted
169 EFI_NOT_FOUND - Block not found
174 EFI_HANDLE
*HandleBuffer
;
177 EFI_PHYSICAL_ADDRESS FvbBaseAddress
;
178 EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL
*Fvb
;
179 EFI_FIRMWARE_VOLUME_HEADER
*FwVolHeader
;
183 // Locate all handles of Fvb protocol
185 Status
= gBS
->LocateHandleBuffer (
187 &gEfiFirmwareVolumeBlockProtocolGuid
,
192 if (EFI_ERROR (Status
)) {
193 return EFI_NOT_FOUND
;
196 // Search all FVB until find the right one
198 for (Index
= 0; Index
< HandleCount
; Index
+= 1) {
199 Status
= gBS
->HandleProtocol (
201 &gEfiFirmwareVolumeBlockProtocolGuid
,
204 if (EFI_ERROR (Status
)) {
205 Status
= EFI_NOT_FOUND
;
209 // Compare the address and select the right one
211 Status
= Fvb
->GetPhysicalAddress (Fvb
, &FvbBaseAddress
);
212 if (EFI_ERROR (Status
)) {
216 FwVolHeader
= (EFI_FIRMWARE_VOLUME_HEADER
*) ((UINTN
) FvbBaseAddress
);
217 if ((Address
>= FvbBaseAddress
) && (Address
<= (FvbBaseAddress
+ (FwVolHeader
->FvLength
- 1)))) {
219 Status
= EFI_SUCCESS
;
224 FreePool (HandleBuffer
);
230 EFI_FTW_LITE_DEVICE
*FtwLiteDevice
,
231 EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL
*FvBlock
,
238 Is it in working block?
242 FtwLiteDevice - Calling context
243 FvBlock - Fvb protocol instance
244 Lba - The block specified
248 In working block or not
253 // If matching the following condition, the target block is in working block.
254 // 1. Target block is on the FV of working block (Using the same FVB protocol instance).
255 // 2. Lba falls into the range of working block.
259 (FvBlock
== FtwLiteDevice
->FtwFvBlock
) &&
260 (Lba
>= FtwLiteDevice
->FtwWorkBlockLba
) &&
261 (Lba
<= FtwLiteDevice
->FtwWorkSpaceLba
)
266 FlushSpareBlockToTargetBlock (
267 EFI_FTW_LITE_DEVICE
*FtwLiteDevice
,
268 EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL
*FvBlock
,
274 Copy the content of spare block to a target block. Size is FTW_BLOCK_SIZE.
275 Spare block is accessed by FTW backup FVB protocol interface. LBA is
276 FtwLiteDevice->FtwSpareLba.
277 Target block is accessed by FvBlock protocol interface. LBA is Lba.
280 FtwLiteDevice - The private data of FTW_LITE driver
281 FvBlock - FVB Protocol interface to access target block
282 Lba - Lba of the target block
285 EFI_SUCCESS - Spare block content is copied to target block
286 EFI_INVALID_PARAMETER - Input parameter error
287 EFI_OUT_OF_RESOURCES - Allocate memory error
288 EFI_ABORTED - The function could not complete successfully
299 if ((FtwLiteDevice
== NULL
) || (FvBlock
== NULL
)) {
300 return EFI_INVALID_PARAMETER
;
303 // Allocate a memory buffer
305 Length
= FtwLiteDevice
->SpareAreaLength
;
306 Buffer
= AllocatePool (Length
);
307 if (Buffer
== NULL
) {
308 return EFI_OUT_OF_RESOURCES
;
311 // Read all content of spare block to memory buffer
314 for (Index
= 0; Index
< FtwLiteDevice
->NumberOfSpareBlock
; Index
+= 1) {
315 Count
= FtwLiteDevice
->SizeOfSpareBlock
;
316 Status
= FtwLiteDevice
->FtwBackupFvb
->Read (
317 FtwLiteDevice
->FtwBackupFvb
,
318 FtwLiteDevice
->FtwSpareLba
+ Index
,
323 if (EFI_ERROR (Status
)) {
331 // Erase the target block
333 Status
= FtwEraseBlock (FtwLiteDevice
, FvBlock
, Lba
);
334 if (EFI_ERROR (Status
)) {
339 // Write memory buffer to block, using the FvbBlock protocol interface
342 for (Index
= 0; Index
< FtwLiteDevice
->NumberOfSpareBlock
; Index
+= 1) {
343 Count
= FtwLiteDevice
->SizeOfSpareBlock
;
344 Status
= FvBlock
->Write (FvBlock
, Lba
+ Index
, 0, &Count
, Ptr
);
345 if (EFI_ERROR (Status
)) {
346 DEBUG ((EFI_D_FTW_LITE
, "FtwLite: FVB Write block - %r\n", Status
));
360 FlushSpareBlockToWorkingBlock (
361 EFI_FTW_LITE_DEVICE
*FtwLiteDevice
366 Copy the content of spare block to working block. Size is FTW_BLOCK_SIZE.
367 Spare block is accessed by FTW backup FVB protocol interface. LBA is
368 FtwLiteDevice->FtwSpareLba.
369 Working block is accessed by FTW working FVB protocol interface. LBA is
370 FtwLiteDevice->FtwWorkBlockLba.
373 FtwLiteDevice - The private data of FTW_LITE driver
376 EFI_SUCCESS - Spare block content is copied to target block
377 EFI_OUT_OF_RESOURCES - Allocate memory error
378 EFI_ABORTED - The function could not complete successfully
381 Since the working block header is important when FTW initializes, the
382 state of the operation should be handled carefully. The Crc value is
383 calculated without STATE element.
390 EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER
*WorkingBlockHeader
;
391 EFI_LBA WorkSpaceLbaOffset
;
397 // Allocate a memory buffer
399 Length
= FtwLiteDevice
->SpareAreaLength
;
400 Buffer
= AllocatePool (Length
);
401 if (Buffer
== NULL
) {
402 return EFI_OUT_OF_RESOURCES
;
405 // To guarantee that the WorkingBlockValid is set on spare block
407 WorkSpaceLbaOffset
= FtwLiteDevice
->FtwWorkSpaceLba
- FtwLiteDevice
->FtwWorkBlockLba
;
409 FtwLiteDevice
->FtwBackupFvb
,
410 FtwLiteDevice
->FtwSpareLba
+ WorkSpaceLbaOffset
,
411 FtwLiteDevice
->FtwWorkSpaceBase
+ sizeof (EFI_GUID
) + sizeof (UINT32
),
415 // Read from spare block to memory buffer
418 for (Index
= 0; Index
< FtwLiteDevice
->NumberOfSpareBlock
; Index
+= 1) {
419 Count
= FtwLiteDevice
->SizeOfSpareBlock
;
420 Status
= FtwLiteDevice
->FtwBackupFvb
->Read (
421 FtwLiteDevice
->FtwBackupFvb
,
422 FtwLiteDevice
->FtwSpareLba
+ Index
,
427 if (EFI_ERROR (Status
)) {
435 // Clear the CRC and STATE, copy data from spare to working block.
437 WorkingBlockHeader
= (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER
*) (Buffer
+ (UINTN
) WorkSpaceLbaOffset
* FtwLiteDevice
->SizeOfSpareBlock
+ FtwLiteDevice
->FtwWorkSpaceBase
);
438 InitWorkSpaceHeader (WorkingBlockHeader
);
439 WorkingBlockHeader
->WorkingBlockValid
= FTW_ERASE_POLARITY
;
440 WorkingBlockHeader
->WorkingBlockInvalid
= FTW_ERASE_POLARITY
;
443 // target block is working block, then
444 // Set WorkingBlockInvalid in EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER
445 // before erase the working block.
447 // Offset = EFI_FIELD_OFFSET(EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER,
448 // WorkingBlockInvalid);
449 // To skip Signature and Crc: sizeof(EFI_GUID)+sizeof(UINT32).
451 Status
= FtwUpdateFvState (
452 FtwLiteDevice
->FtwFvBlock
,
453 FtwLiteDevice
->FtwWorkSpaceLba
,
454 FtwLiteDevice
->FtwWorkSpaceBase
+ sizeof (EFI_GUID
) + sizeof (UINT32
),
455 WORKING_BLOCK_INVALID
457 if (EFI_ERROR (Status
)) {
462 FtwLiteDevice
->FtwWorkSpaceHeader
->WorkingBlockInvalid
= FTW_VALID_STATE
;
465 // Erase the working block
467 Status
= FtwEraseBlock (
469 FtwLiteDevice
->FtwFvBlock
,
470 FtwLiteDevice
->FtwWorkBlockLba
472 if (EFI_ERROR (Status
)) {
477 // Write memory buffer to working block, using the FvbBlock protocol interface
480 for (Index
= 0; Index
< FtwLiteDevice
->NumberOfSpareBlock
; Index
+= 1) {
481 Count
= FtwLiteDevice
->SizeOfSpareBlock
;
482 Status
= FtwLiteDevice
->FtwFvBlock
->Write (
483 FtwLiteDevice
->FtwFvBlock
,
484 FtwLiteDevice
->FtwWorkBlockLba
+ Index
,
489 if (EFI_ERROR (Status
)) {
490 DEBUG ((EFI_D_FTW_LITE
, "FtwLite: FVB Write block - %r\n", Status
));
498 // Since the memory buffer will not be used, free memory Buffer.
503 // Update the VALID of the working block
505 // Offset = EFI_FIELD_OFFSET(EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER,
506 // WorkingBlockValid);
507 // Hardcode offset sizeof(EFI_GUID)+sizeof(UINT32), to skip Signature and Crc
509 Status
= FtwUpdateFvState (
510 FtwLiteDevice
->FtwFvBlock
,
511 FtwLiteDevice
->FtwWorkSpaceLba
,
512 FtwLiteDevice
->FtwWorkSpaceBase
+ sizeof (EFI_GUID
) + sizeof (UINT32
),
515 if (EFI_ERROR (Status
)) {
519 FtwLiteDevice
->FtwWorkSpaceHeader
->WorkingBlockValid
= FTW_VALID_STATE
;