3 Copyright (c) 2006 - 2007, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 Internal functions to support fault tolerant write.
36 Check whether a flash buffer is erased.
40 Polarity - All 1 or all 0
41 Buffer - Buffer to check
42 BufferSize - Size of the buffer
60 while (BufferSize
--) {
61 if (*Ptr
++ != ErasedValue
) {
71 IN EFI_FTW_LITE_DEVICE
*FtwLiteDevice
,
72 EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL
*FvBlock
,
78 To Erase one block. The size is FTW_BLOCK_SIZE
81 FtwLiteDevice - Calling context
82 FvBlock - FVB Protocol interface
83 Lba - Lba of the firmware block
86 EFI_SUCCESS - Block LBA is Erased successfully
91 return FvBlock
->EraseBlocks (
94 FtwLiteDevice
->NumberOfSpareBlock
,
95 EFI_LBA_LIST_TERMINATOR
101 IN EFI_FTW_LITE_DEVICE
*FtwLiteDevice
111 FtwLiteDevice - Calling context
119 return FtwLiteDevice
->FtwBackupFvb
->EraseBlocks (
120 FtwLiteDevice
->FtwBackupFvb
,
121 FtwLiteDevice
->FtwSpareLba
,
122 FtwLiteDevice
->NumberOfSpareBlock
,
123 EFI_LBA_LIST_TERMINATOR
129 IN EFI_HANDLE FvBlockHandle
,
130 OUT EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL
**FvBlock
135 Retrive the proper FVB protocol interface by HANDLE.
138 FvBlockHandle - The handle of FVB protocol that provides services for
139 reading, writing, and erasing the target block.
140 FvBlock - The interface of FVB protocol
143 EFI_SUCCESS - The function completed successfully
144 EFI_ABORTED - The function could not complete successfully
148 // To get the FVB protocol interface on the handle
150 return gBS
->HandleProtocol (
152 &gEfiFirmwareVolumeBlockProtocolGuid
,
159 IN EFI_PHYSICAL_ADDRESS Address
,
160 OUT EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL
**FvBlock
166 Get firmware block by address.
170 Address - Address specified the block
171 FvBlock - The block caller wanted
177 EFI_NOT_FOUND - Block not found
182 EFI_HANDLE
*HandleBuffer
;
185 EFI_PHYSICAL_ADDRESS FvbBaseAddress
;
186 EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL
*Fvb
;
187 EFI_FIRMWARE_VOLUME_HEADER
*FwVolHeader
;
191 // Locate all handles of Fvb protocol
193 Status
= gBS
->LocateHandleBuffer (
195 &gEfiFirmwareVolumeBlockProtocolGuid
,
200 if (EFI_ERROR (Status
)) {
201 return EFI_NOT_FOUND
;
204 // Search all FVB until find the right one
206 for (Index
= 0; Index
< HandleCount
; Index
+= 1) {
207 Status
= gBS
->HandleProtocol (
209 &gEfiFirmwareVolumeBlockProtocolGuid
,
212 if (EFI_ERROR (Status
)) {
213 Status
= EFI_NOT_FOUND
;
217 // Compare the address and select the right one
219 Status
= Fvb
->GetPhysicalAddress (Fvb
, &FvbBaseAddress
);
220 if (EFI_ERROR (Status
)) {
224 FwVolHeader
= (EFI_FIRMWARE_VOLUME_HEADER
*) ((UINTN
) FvbBaseAddress
);
225 if ((Address
>= FvbBaseAddress
) && (Address
<= (FvbBaseAddress
+ (FwVolHeader
->FvLength
- 1)))) {
227 Status
= EFI_SUCCESS
;
232 FreePool (HandleBuffer
);
238 EFI_FTW_LITE_DEVICE
*FtwLiteDevice
,
239 EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL
*FvBlock
,
246 Is it in working block?
250 FtwLiteDevice - Calling context
251 FvBlock - Fvb protocol instance
252 Lba - The block specified
256 In working block or not
261 // If matching the following condition, the target block is in working block.
262 // 1. Target block is on the FV of working block (Using the same FVB protocol instance).
263 // 2. Lba falls into the range of working block.
267 (FvBlock
== FtwLiteDevice
->FtwFvBlock
) &&
268 (Lba
>= FtwLiteDevice
->FtwWorkBlockLba
) &&
269 (Lba
<= FtwLiteDevice
->FtwWorkSpaceLba
)
274 FlushSpareBlockToTargetBlock (
275 EFI_FTW_LITE_DEVICE
*FtwLiteDevice
,
276 EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL
*FvBlock
,
282 Copy the content of spare block to a target block. Size is FTW_BLOCK_SIZE.
283 Spare block is accessed by FTW backup FVB protocol interface. LBA is
284 FtwLiteDevice->FtwSpareLba.
285 Target block is accessed by FvBlock protocol interface. LBA is Lba.
288 FtwLiteDevice - The private data of FTW_LITE driver
289 FvBlock - FVB Protocol interface to access target block
290 Lba - Lba of the target block
293 EFI_SUCCESS - Spare block content is copied to target block
294 EFI_INVALID_PARAMETER - Input parameter error
295 EFI_OUT_OF_RESOURCES - Allocate memory error
296 EFI_ABORTED - The function could not complete successfully
307 if ((FtwLiteDevice
== NULL
) || (FvBlock
== NULL
)) {
308 return EFI_INVALID_PARAMETER
;
311 // Allocate a memory buffer
313 Length
= FtwLiteDevice
->SpareAreaLength
;
314 Buffer
= AllocatePool (Length
);
315 if (Buffer
== NULL
) {
316 return EFI_OUT_OF_RESOURCES
;
319 // Read all content of spare block to memory buffer
322 for (Index
= 0; Index
< FtwLiteDevice
->NumberOfSpareBlock
; Index
+= 1) {
323 Count
= FtwLiteDevice
->SizeOfSpareBlock
;
324 Status
= FtwLiteDevice
->FtwBackupFvb
->Read (
325 FtwLiteDevice
->FtwBackupFvb
,
326 FtwLiteDevice
->FtwSpareLba
+ Index
,
331 if (EFI_ERROR (Status
)) {
339 // Erase the target block
341 Status
= FtwEraseBlock (FtwLiteDevice
, FvBlock
, Lba
);
342 if (EFI_ERROR (Status
)) {
347 // Write memory buffer to block, using the FvbBlock protocol interface
350 for (Index
= 0; Index
< FtwLiteDevice
->NumberOfSpareBlock
; Index
+= 1) {
351 Count
= FtwLiteDevice
->SizeOfSpareBlock
;
352 Status
= FvBlock
->Write (FvBlock
, Lba
+ Index
, 0, &Count
, Ptr
);
353 if (EFI_ERROR (Status
)) {
354 DEBUG ((EFI_D_FTW_LITE
, "FtwLite: FVB Write block - %r\n", Status
));
368 FlushSpareBlockToWorkingBlock (
369 EFI_FTW_LITE_DEVICE
*FtwLiteDevice
374 Copy the content of spare block to working block. Size is FTW_BLOCK_SIZE.
375 Spare block is accessed by FTW backup FVB protocol interface. LBA is
376 FtwLiteDevice->FtwSpareLba.
377 Working block is accessed by FTW working FVB protocol interface. LBA is
378 FtwLiteDevice->FtwWorkBlockLba.
381 FtwLiteDevice - The private data of FTW_LITE driver
384 EFI_SUCCESS - Spare block content is copied to target block
385 EFI_OUT_OF_RESOURCES - Allocate memory error
386 EFI_ABORTED - The function could not complete successfully
389 Since the working block header is important when FTW initializes, the
390 state of the operation should be handled carefully. The Crc value is
391 calculated without STATE element.
398 EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER
*WorkingBlockHeader
;
399 EFI_LBA WorkSpaceLbaOffset
;
405 // Allocate a memory buffer
407 Length
= FtwLiteDevice
->SpareAreaLength
;
408 Buffer
= AllocatePool (Length
);
409 if (Buffer
== NULL
) {
410 return EFI_OUT_OF_RESOURCES
;
413 // To guarantee that the WorkingBlockValid is set on spare block
415 WorkSpaceLbaOffset
= FtwLiteDevice
->FtwWorkSpaceLba
- FtwLiteDevice
->FtwWorkBlockLba
;
417 FtwLiteDevice
->FtwBackupFvb
,
418 FtwLiteDevice
->FtwSpareLba
+ WorkSpaceLbaOffset
,
419 FtwLiteDevice
->FtwWorkSpaceBase
+ sizeof (EFI_GUID
) + sizeof (UINT32
),
423 // Read from spare block to memory buffer
426 for (Index
= 0; Index
< FtwLiteDevice
->NumberOfSpareBlock
; Index
+= 1) {
427 Count
= FtwLiteDevice
->SizeOfSpareBlock
;
428 Status
= FtwLiteDevice
->FtwBackupFvb
->Read (
429 FtwLiteDevice
->FtwBackupFvb
,
430 FtwLiteDevice
->FtwSpareLba
+ Index
,
435 if (EFI_ERROR (Status
)) {
443 // Clear the CRC and STATE, copy data from spare to working block.
445 WorkingBlockHeader
= (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER
*) (Buffer
+ (UINTN
) WorkSpaceLbaOffset
* FtwLiteDevice
->SizeOfSpareBlock
+ FtwLiteDevice
->FtwWorkSpaceBase
);
446 InitWorkSpaceHeader (WorkingBlockHeader
);
447 WorkingBlockHeader
->WorkingBlockValid
= FTW_ERASE_POLARITY
;
448 WorkingBlockHeader
->WorkingBlockInvalid
= FTW_ERASE_POLARITY
;
451 // target block is working block, then
452 // Set WorkingBlockInvalid in EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER
453 // before erase the working block.
455 // Offset = EFI_FIELD_OFFSET(EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER,
456 // WorkingBlockInvalid);
457 // To skip Signature and Crc: sizeof(EFI_GUID)+sizeof(UINT32).
459 Status
= FtwUpdateFvState (
460 FtwLiteDevice
->FtwFvBlock
,
461 FtwLiteDevice
->FtwWorkSpaceLba
,
462 FtwLiteDevice
->FtwWorkSpaceBase
+ sizeof (EFI_GUID
) + sizeof (UINT32
),
463 WORKING_BLOCK_INVALID
465 if (EFI_ERROR (Status
)) {
470 FtwLiteDevice
->FtwWorkSpaceHeader
->WorkingBlockInvalid
= FTW_VALID_STATE
;
473 // Erase the working block
475 Status
= FtwEraseBlock (
477 FtwLiteDevice
->FtwFvBlock
,
478 FtwLiteDevice
->FtwWorkBlockLba
480 if (EFI_ERROR (Status
)) {
485 // Write memory buffer to working block, using the FvbBlock protocol interface
488 for (Index
= 0; Index
< FtwLiteDevice
->NumberOfSpareBlock
; Index
+= 1) {
489 Count
= FtwLiteDevice
->SizeOfSpareBlock
;
490 Status
= FtwLiteDevice
->FtwFvBlock
->Write (
491 FtwLiteDevice
->FtwFvBlock
,
492 FtwLiteDevice
->FtwWorkBlockLba
+ Index
,
497 if (EFI_ERROR (Status
)) {
498 DEBUG ((EFI_D_FTW_LITE
, "FtwLite: FVB Write block - %r\n", Status
));
506 // Since the memory buffer will not be used, free memory Buffer.
511 // Update the VALID of the working block
513 // Offset = EFI_FIELD_OFFSET(EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER,
514 // WorkingBlockValid);
515 // Hardcode offset sizeof(EFI_GUID)+sizeof(UINT32), to skip Signature and Crc
517 Status
= FtwUpdateFvState (
518 FtwLiteDevice
->FtwFvBlock
,
519 FtwLiteDevice
->FtwWorkSpaceLba
,
520 FtwLiteDevice
->FtwWorkSpaceBase
+ sizeof (EFI_GUID
) + sizeof (UINT32
),
523 if (EFI_ERROR (Status
)) {
527 FtwLiteDevice
->FtwWorkSpaceHeader
->WorkingBlockValid
= FTW_VALID_STATE
;