]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/FaultTolerantWriteDxe/UpdateWorkingBlock.c
MdeModulePkg: Apply uncrustify changes
[mirror_edk2.git] / MdeModulePkg / Universal / FaultTolerantWriteDxe / UpdateWorkingBlock.c
CommitLineData
85e923a5
LG
1/** @file\r
2\r
3 Internal functions to operate Working Block Space.\r
4\r
d1102dba 5Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>\r
9d510e61 6SPDX-License-Identifier: BSD-2-Clause-Patent\r
85e923a5
LG
7\r
8**/\r
9\r
85e923a5
LG
10#include "FaultTolerantWrite.h"\r
11\r
1436aea4 12EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER mWorkingBlockHeader = { ZERO_GUID, 0, 0, 0, 0, { 0, 0, 0 }, 0 };\r
85e923a5 13\r
05cfd5f2
SZ
14/**\r
15 Initialize a local work space header.\r
85e923a5 16\r
05cfd5f2
SZ
17 Since Signature and WriteQueueSize have been known, Crc can be calculated out,\r
18 then the work space header will be fixed.\r
85e923a5 19**/\r
05cfd5f2
SZ
20VOID\r
21InitializeLocalWorkSpaceHeader (\r
22 VOID\r
85e923a5
LG
23 )\r
24{\r
85e923a5 25 //\r
3e02ebb2 26 // Check signature with gEdkiiWorkingBlockSignatureGuid.\r
85e923a5 27 //\r
3e02ebb2 28 if (CompareGuid (&gEdkiiWorkingBlockSignatureGuid, &mWorkingBlockHeader.Signature)) {\r
05cfd5f2
SZ
29 //\r
30 // The local work space header has been initialized.\r
31 //\r
32 return;\r
85e923a5 33 }\r
05cfd5f2
SZ
34\r
35 SetMem (\r
36 &mWorkingBlockHeader,\r
37 sizeof (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER),\r
38 FTW_ERASED_BYTE\r
39 );\r
40\r
85e923a5 41 //\r
3e02ebb2 42 // Here using gEdkiiWorkingBlockSignatureGuid as the signature.\r
85e923a5
LG
43 //\r
44 CopyMem (\r
05cfd5f2 45 &mWorkingBlockHeader.Signature,\r
3e02ebb2 46 &gEdkiiWorkingBlockSignatureGuid,\r
05cfd5f2 47 sizeof (EFI_GUID)\r
85e923a5 48 );\r
16f69227 49 mWorkingBlockHeader.WriteQueueSize = PcdGet32 (PcdFlashNvStorageFtwWorkingSize) - sizeof (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER);\r
85e923a5
LG
50\r
51 //\r
05cfd5f2 52 // Crc is calculated with all the fields except Crc and STATE, so leave them as FTW_ERASED_BYTE.\r
85e923a5 53 //\r
85e923a5
LG
54\r
55 //\r
56 // Calculate the Crc of woking block header\r
57 //\r
1436aea4
MK
58 mWorkingBlockHeader.Crc = FtwCalculateCrc32 (\r
59 &mWorkingBlockHeader,\r
60 sizeof (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER)\r
61 );\r
05cfd5f2 62\r
1436aea4
MK
63 mWorkingBlockHeader.WorkingBlockValid = FTW_VALID_STATE;\r
64 mWorkingBlockHeader.WorkingBlockInvalid = FTW_INVALID_STATE;\r
05cfd5f2
SZ
65}\r
66\r
67/**\r
68 Check to see if it is a valid work space.\r
69\r
70\r
71 @param WorkingHeader Pointer of working block header\r
72\r
73 @retval TRUE The work space is valid.\r
74 @retval FALSE The work space is invalid.\r
75\r
76**/\r
77BOOLEAN\r
78IsValidWorkSpace (\r
1436aea4 79 IN EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *WorkingHeader\r
05cfd5f2
SZ
80 )\r
81{\r
82 if (WorkingHeader == NULL) {\r
85e923a5
LG
83 return FALSE;\r
84 }\r
85\r
05cfd5f2
SZ
86 if (CompareMem (WorkingHeader, &mWorkingBlockHeader, sizeof (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER)) == 0) {\r
87 return TRUE;\r
85e923a5
LG
88 }\r
89\r
87000d77 90 DEBUG ((DEBUG_INFO, "Ftw: Work block header check mismatch\n"));\r
05cfd5f2 91 return FALSE;\r
85e923a5
LG
92}\r
93\r
94/**\r
95 Initialize a work space when there is no work space.\r
96\r
97 @param WorkingHeader Pointer of working block header\r
98\r
99 @retval EFI_SUCCESS The function completed successfully\r
100 @retval EFI_ABORTED The function could not complete successfully.\r
101\r
102**/\r
103EFI_STATUS\r
104InitWorkSpaceHeader (\r
1436aea4 105 IN EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *WorkingHeader\r
85e923a5
LG
106 )\r
107{\r
85e923a5
LG
108 if (WorkingHeader == NULL) {\r
109 return EFI_INVALID_PARAMETER;\r
110 }\r
85e923a5 111\r
05cfd5f2 112 CopyMem (WorkingHeader, &mWorkingBlockHeader, sizeof (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER));\r
85e923a5
LG
113\r
114 return EFI_SUCCESS;\r
115}\r
116\r
0d3edd9d
SZ
117/**\r
118 Read work space data from work block or spare block.\r
119\r
0d3edd9d
SZ
120 @param FvBlock FVB Protocol interface to access the block.\r
121 @param BlockSize The size of the block.\r
122 @param Lba Lba of the block.\r
123 @param Offset The offset within the block.\r
124 @param Length The number of bytes to read from the block.\r
125 @param Buffer The data is read.\r
126\r
127 @retval EFI_SUCCESS The function completed successfully.\r
128 @retval EFI_ABORTED The function could not complete successfully.\r
129\r
130**/\r
131EFI_STATUS\r
132ReadWorkSpaceData (\r
1436aea4
MK
133 IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvBlock,\r
134 IN UINTN BlockSize,\r
135 IN EFI_LBA Lba,\r
136 IN UINTN Offset,\r
137 IN UINTN Length,\r
138 OUT UINT8 *Buffer\r
0d3edd9d
SZ
139 )\r
140{\r
1436aea4
MK
141 EFI_STATUS Status;\r
142 UINT8 *Ptr;\r
143 UINTN MyLength;\r
0d3edd9d
SZ
144\r
145 //\r
146 // Calculate the real Offset and Lba to write.\r
147 //\r
148 while (Offset >= BlockSize) {\r
149 Offset -= BlockSize;\r
150 Lba++;\r
151 }\r
152\r
153 Ptr = Buffer;\r
154 while (Length > 0) {\r
155 if ((Offset + Length) > BlockSize) {\r
156 MyLength = BlockSize - Offset;\r
157 } else {\r
158 MyLength = Length;\r
159 }\r
160\r
161 Status = FvBlock->Read (\r
162 FvBlock,\r
163 Lba,\r
164 Offset,\r
165 &MyLength,\r
166 Ptr\r
167 );\r
168 if (EFI_ERROR (Status)) {\r
169 return EFI_ABORTED;\r
170 }\r
1436aea4
MK
171\r
172 Offset = 0;\r
0d3edd9d 173 Length -= MyLength;\r
1436aea4 174 Ptr += MyLength;\r
0d3edd9d
SZ
175 Lba++;\r
176 }\r
177\r
178 return EFI_SUCCESS;\r
179}\r
180\r
181/**\r
182 Write work space data to work block.\r
183\r
184 @param FvBlock FVB Protocol interface to access the block.\r
185 @param BlockSize The size of the block.\r
186 @param Lba Lba of the block.\r
187 @param Offset The offset within the block to place the data.\r
188 @param Length The number of bytes to write to the block.\r
189 @param Buffer The data to write.\r
190\r
191 @retval EFI_SUCCESS The function completed successfully.\r
192 @retval EFI_ABORTED The function could not complete successfully.\r
193\r
194**/\r
195EFI_STATUS\r
196WriteWorkSpaceData (\r
1436aea4
MK
197 IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvBlock,\r
198 IN UINTN BlockSize,\r
199 IN EFI_LBA Lba,\r
200 IN UINTN Offset,\r
201 IN UINTN Length,\r
202 IN UINT8 *Buffer\r
0d3edd9d
SZ
203 )\r
204{\r
1436aea4
MK
205 EFI_STATUS Status;\r
206 UINT8 *Ptr;\r
207 UINTN MyLength;\r
0d3edd9d
SZ
208\r
209 //\r
210 // Calculate the real Offset and Lba to write.\r
211 //\r
212 while (Offset >= BlockSize) {\r
213 Offset -= BlockSize;\r
214 Lba++;\r
215 }\r
216\r
217 Ptr = Buffer;\r
218 while (Length > 0) {\r
219 if ((Offset + Length) > BlockSize) {\r
220 MyLength = BlockSize - Offset;\r
221 } else {\r
222 MyLength = Length;\r
223 }\r
224\r
225 Status = FvBlock->Write (\r
226 FvBlock,\r
227 Lba,\r
228 Offset,\r
229 &MyLength,\r
230 Ptr\r
231 );\r
232 if (EFI_ERROR (Status)) {\r
233 return EFI_ABORTED;\r
234 }\r
1436aea4
MK
235\r
236 Offset = 0;\r
0d3edd9d 237 Length -= MyLength;\r
1436aea4 238 Ptr += MyLength;\r
0d3edd9d
SZ
239 Lba++;\r
240 }\r
1436aea4 241\r
0d3edd9d
SZ
242 return EFI_SUCCESS;\r
243}\r
244\r
85e923a5
LG
245/**\r
246 Read from working block to refresh the work space in memory.\r
247\r
248 @param FtwDevice Point to private data of FTW driver\r
249\r
250 @retval EFI_SUCCESS The function completed successfully\r
251 @retval EFI_ABORTED The function could not complete successfully.\r
252\r
253**/\r
254EFI_STATUS\r
255WorkSpaceRefresh (\r
256 IN EFI_FTW_DEVICE *FtwDevice\r
257 )\r
258{\r
1436aea4
MK
259 EFI_STATUS Status;\r
260 UINTN RemainingSpaceSize;\r
85e923a5
LG
261\r
262 //\r
263 // Initialize WorkSpace as FTW_ERASED_BYTE\r
264 //\r
265 SetMem (\r
266 FtwDevice->FtwWorkSpace,\r
267 FtwDevice->FtwWorkSpaceSize,\r
268 FTW_ERASED_BYTE\r
269 );\r
270\r
271 //\r
272 // Read from working block\r
273 //\r
0d3edd9d
SZ
274 Status = ReadWorkSpaceData (\r
275 FtwDevice->FtwFvBlock,\r
276 FtwDevice->WorkBlockSize,\r
277 FtwDevice->FtwWorkSpaceLba,\r
278 FtwDevice->FtwWorkSpaceBase,\r
279 FtwDevice->FtwWorkSpaceSize,\r
280 FtwDevice->FtwWorkSpace\r
281 );\r
85e923a5
LG
282 if (EFI_ERROR (Status)) {\r
283 return EFI_ABORTED;\r
284 }\r
1436aea4 285\r
85e923a5
LG
286 //\r
287 // Refresh the FtwLastWriteHeader\r
288 //\r
289 Status = FtwGetLastWriteHeader (\r
1436aea4
MK
290 FtwDevice->FtwWorkSpaceHeader,\r
291 FtwDevice->FtwWorkSpaceSize,\r
292 &FtwDevice->FtwLastWriteHeader\r
293 );\r
294 RemainingSpaceSize = FtwDevice->FtwWorkSpaceSize - ((UINTN)FtwDevice->FtwLastWriteHeader - (UINTN)FtwDevice->FtwWorkSpace);\r
87000d77 295 DEBUG ((DEBUG_INFO, "Ftw: Remaining work space size - %x\n", RemainingSpaceSize));\r
d379cbc7
SZ
296 //\r
297 // If FtwGetLastWriteHeader() returns error, or the remaining space size is even not enough to contain\r
298 // one EFI_FAULT_TOLERANT_WRITE_HEADER + one EFI_FAULT_TOLERANT_WRITE_RECORD(It will cause that the header\r
299 // pointed by FtwDevice->FtwLastWriteHeader or record pointed by FtwDevice->FtwLastWriteRecord may contain invalid data),\r
300 // it needs to reclaim work space.\r
301 //\r
1436aea4 302 if (EFI_ERROR (Status) || (RemainingSpaceSize < sizeof (EFI_FAULT_TOLERANT_WRITE_HEADER) + sizeof (EFI_FAULT_TOLERANT_WRITE_RECORD))) {\r
85e923a5
LG
303 //\r
304 // reclaim work space in working block.\r
305 //\r
306 Status = FtwReclaimWorkSpace (FtwDevice, TRUE);\r
307 if (EFI_ERROR (Status)) {\r
87000d77 308 DEBUG ((DEBUG_ERROR, "Ftw: Reclaim workspace - %r\n", Status));\r
85e923a5
LG
309 return EFI_ABORTED;\r
310 }\r
1436aea4 311\r
85e923a5
LG
312 //\r
313 // Read from working block again\r
314 //\r
0d3edd9d
SZ
315 Status = ReadWorkSpaceData (\r
316 FtwDevice->FtwFvBlock,\r
317 FtwDevice->WorkBlockSize,\r
318 FtwDevice->FtwWorkSpaceLba,\r
319 FtwDevice->FtwWorkSpaceBase,\r
320 FtwDevice->FtwWorkSpaceSize,\r
321 FtwDevice->FtwWorkSpace\r
322 );\r
85e923a5
LG
323 if (EFI_ERROR (Status)) {\r
324 return EFI_ABORTED;\r
325 }\r
326\r
327 Status = FtwGetLastWriteHeader (\r
1436aea4
MK
328 FtwDevice->FtwWorkSpaceHeader,\r
329 FtwDevice->FtwWorkSpaceSize,\r
330 &FtwDevice->FtwLastWriteHeader\r
331 );\r
d26c7e82
SZ
332 if (EFI_ERROR (Status)) {\r
333 return EFI_ABORTED;\r
334 }\r
85e923a5 335 }\r
1436aea4 336\r
85e923a5
LG
337 //\r
338 // Refresh the FtwLastWriteRecord\r
339 //\r
340 Status = FtwGetLastWriteRecord (\r
1436aea4
MK
341 FtwDevice->FtwLastWriteHeader,\r
342 &FtwDevice->FtwLastWriteRecord\r
343 );\r
85e923a5
LG
344 if (EFI_ERROR (Status)) {\r
345 return EFI_ABORTED;\r
346 }\r
347\r
348 return EFI_SUCCESS;\r
349}\r
350\r
351/**\r
352 Reclaim the work space on the working block.\r
353\r
354 @param FtwDevice Point to private data of FTW driver\r
355 @param PreserveRecord Whether to preserve the working record is needed\r
356\r
357 @retval EFI_SUCCESS The function completed successfully\r
358 @retval EFI_OUT_OF_RESOURCES Allocate memory error\r
359 @retval EFI_ABORTED The function could not complete successfully\r
360\r
361**/\r
362EFI_STATUS\r
363FtwReclaimWorkSpace (\r
364 IN EFI_FTW_DEVICE *FtwDevice,\r
365 IN BOOLEAN PreserveRecord\r
366 )\r
367{\r
1436aea4
MK
368 EFI_STATUS Status;\r
369 UINTN Length;\r
370 EFI_FAULT_TOLERANT_WRITE_HEADER *Header;\r
371 UINT8 *TempBuffer;\r
372 UINTN TempBufferSize;\r
373 UINTN SpareBufferSize;\r
374 UINT8 *SpareBuffer;\r
375 EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *WorkingBlockHeader;\r
376 UINTN Index;\r
377 UINT8 *Ptr;\r
378 EFI_LBA WorkSpaceLbaOffset;\r
85e923a5 379\r
87000d77 380 DEBUG ((DEBUG_INFO, "Ftw: start to reclaim work space\n"));\r
85e923a5 381\r
d26c7e82
SZ
382 WorkSpaceLbaOffset = FtwDevice->FtwWorkSpaceLba - FtwDevice->FtwWorkBlockLba;\r
383\r
85e923a5
LG
384 //\r
385 // Read all original data from working block to a memory buffer\r
386 //\r
0d3edd9d 387 TempBufferSize = FtwDevice->NumberOfWorkBlock * FtwDevice->WorkBlockSize;\r
85e923a5
LG
388 TempBuffer = AllocateZeroPool (TempBufferSize);\r
389 if (TempBuffer == NULL) {\r
390 return EFI_OUT_OF_RESOURCES;\r
391 }\r
392\r
393 Ptr = TempBuffer;\r
0d3edd9d
SZ
394 for (Index = 0; Index < FtwDevice->NumberOfWorkBlock; Index += 1) {\r
395 Length = FtwDevice->WorkBlockSize;\r
85e923a5 396 Status = FtwDevice->FtwFvBlock->Read (\r
1436aea4
MK
397 FtwDevice->FtwFvBlock,\r
398 FtwDevice->FtwWorkBlockLba + Index,\r
399 0,\r
400 &Length,\r
401 Ptr\r
402 );\r
85e923a5
LG
403 if (EFI_ERROR (Status)) {\r
404 FreePool (TempBuffer);\r
405 return EFI_ABORTED;\r
406 }\r
407\r
408 Ptr += Length;\r
409 }\r
1436aea4 410\r
85e923a5
LG
411 //\r
412 // Clean up the workspace, remove all the completed records.\r
413 //\r
414 Ptr = TempBuffer +\r
1436aea4 415 (UINTN)WorkSpaceLbaOffset * FtwDevice->WorkBlockSize +\r
85e923a5
LG
416 FtwDevice->FtwWorkSpaceBase;\r
417\r
418 //\r
419 // Clear the content of buffer that will save the new work space data\r
420 //\r
421 SetMem (Ptr, FtwDevice->FtwWorkSpaceSize, FTW_ERASED_BYTE);\r
422\r
423 //\r
424 // Copy EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER to buffer\r
425 //\r
426 CopyMem (\r
427 Ptr,\r
428 FtwDevice->FtwWorkSpaceHeader,\r
429 sizeof (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER)\r
430 );\r
431 if (PreserveRecord) {\r
432 //\r
433 // Get the last record following the header,\r
434 //\r
435 Status = FtwGetLastWriteHeader (\r
436 FtwDevice->FtwWorkSpaceHeader,\r
437 FtwDevice->FtwWorkSpaceSize,\r
438 &FtwDevice->FtwLastWriteHeader\r
439 );\r
440 Header = FtwDevice->FtwLastWriteHeader;\r
8dc8879a 441 if (!EFI_ERROR (Status) && (Header != NULL) && (Header->Complete != FTW_VALID_STATE) && (Header->HeaderAllocated == FTW_VALID_STATE)) {\r
85e923a5
LG
442 CopyMem (\r
443 Ptr + sizeof (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER),\r
444 FtwDevice->FtwLastWriteHeader,\r
3e02ebb2 445 FTW_WRITE_TOTAL_SIZE (Header->NumberOfWrites, Header->PrivateDataSize)\r
85e923a5
LG
446 );\r
447 }\r
448 }\r
449\r
450 CopyMem (\r
451 FtwDevice->FtwWorkSpace,\r
452 Ptr,\r
453 FtwDevice->FtwWorkSpaceSize\r
454 );\r
455\r
456 FtwGetLastWriteHeader (\r
457 FtwDevice->FtwWorkSpaceHeader,\r
458 FtwDevice->FtwWorkSpaceSize,\r
459 &FtwDevice->FtwLastWriteHeader\r
460 );\r
461\r
d26c7e82
SZ
462 FtwGetLastWriteRecord (\r
463 FtwDevice->FtwLastWriteHeader,\r
464 &FtwDevice->FtwLastWriteRecord\r
465 );\r
466\r
85e923a5
LG
467 //\r
468 // Set the WorkingBlockValid and WorkingBlockInvalid as INVALID\r
469 //\r
1436aea4
MK
470 WorkingBlockHeader = (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *)(TempBuffer +\r
471 (UINTN)WorkSpaceLbaOffset * FtwDevice->WorkBlockSize +\r
472 FtwDevice->FtwWorkSpaceBase);\r
85e923a5
LG
473 WorkingBlockHeader->WorkingBlockValid = FTW_INVALID_STATE;\r
474 WorkingBlockHeader->WorkingBlockInvalid = FTW_INVALID_STATE;\r
475\r
476 //\r
477 // Try to keep the content of spare block\r
478 // Save spare block into a spare backup memory buffer (Sparebuffer)\r
479 //\r
480 SpareBufferSize = FtwDevice->SpareAreaLength;\r
481 SpareBuffer = AllocatePool (SpareBufferSize);\r
482 if (SpareBuffer == NULL) {\r
483 FreePool (TempBuffer);\r
484 return EFI_OUT_OF_RESOURCES;\r
485 }\r
486\r
487 Ptr = SpareBuffer;\r
488 for (Index = 0; Index < FtwDevice->NumberOfSpareBlock; Index += 1) {\r
0d3edd9d 489 Length = FtwDevice->SpareBlockSize;\r
85e923a5
LG
490 Status = FtwDevice->FtwBackupFvb->Read (\r
491 FtwDevice->FtwBackupFvb,\r
492 FtwDevice->FtwSpareLba + Index,\r
493 0,\r
494 &Length,\r
495 Ptr\r
496 );\r
497 if (EFI_ERROR (Status)) {\r
498 FreePool (TempBuffer);\r
499 FreePool (SpareBuffer);\r
500 return EFI_ABORTED;\r
501 }\r
502\r
503 Ptr += Length;\r
504 }\r
1436aea4 505\r
85e923a5
LG
506 //\r
507 // Write the memory buffer to spare block\r
508 //\r
1436aea4 509 Status = FtwEraseSpareBlock (FtwDevice);\r
de2d7497
SZ
510 if (EFI_ERROR (Status)) {\r
511 FreePool (TempBuffer);\r
512 FreePool (SpareBuffer);\r
513 return EFI_ABORTED;\r
514 }\r
1436aea4
MK
515\r
516 Ptr = TempBuffer;\r
0d3edd9d
SZ
517 for (Index = 0; TempBufferSize > 0; Index += 1) {\r
518 if (TempBufferSize > FtwDevice->SpareBlockSize) {\r
519 Length = FtwDevice->SpareBlockSize;\r
520 } else {\r
521 Length = TempBufferSize;\r
522 }\r
1436aea4 523\r
85e923a5 524 Status = FtwDevice->FtwBackupFvb->Write (\r
1436aea4
MK
525 FtwDevice->FtwBackupFvb,\r
526 FtwDevice->FtwSpareLba + Index,\r
527 0,\r
528 &Length,\r
529 Ptr\r
530 );\r
85e923a5
LG
531 if (EFI_ERROR (Status)) {\r
532 FreePool (TempBuffer);\r
533 FreePool (SpareBuffer);\r
534 return EFI_ABORTED;\r
535 }\r
536\r
1436aea4 537 Ptr += Length;\r
0d3edd9d 538 TempBufferSize -= Length;\r
85e923a5 539 }\r
1436aea4 540\r
85e923a5
LG
541 //\r
542 // Free TempBuffer\r
543 //\r
544 FreePool (TempBuffer);\r
545\r
546 //\r
547 // Set the WorkingBlockValid in spare block\r
548 //\r
549 Status = FtwUpdateFvState (\r
1436aea4
MK
550 FtwDevice->FtwBackupFvb,\r
551 FtwDevice->SpareBlockSize,\r
552 FtwDevice->FtwSpareLba + FtwDevice->FtwWorkSpaceLbaInSpare,\r
553 FtwDevice->FtwWorkSpaceBaseInSpare + sizeof (EFI_GUID) + sizeof (UINT32),\r
554 WORKING_BLOCK_VALID\r
555 );\r
85e923a5
LG
556 if (EFI_ERROR (Status)) {\r
557 FreePool (SpareBuffer);\r
558 return EFI_ABORTED;\r
559 }\r
1436aea4 560\r
85e923a5
LG
561 //\r
562 // Before erase the working block, set WorkingBlockInvalid in working block.\r
563 //\r
564 // Offset = OFFSET_OF(EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER,\r
565 // WorkingBlockInvalid);\r
566 //\r
567 Status = FtwUpdateFvState (\r
1436aea4
MK
568 FtwDevice->FtwFvBlock,\r
569 FtwDevice->WorkBlockSize,\r
570 FtwDevice->FtwWorkSpaceLba,\r
571 FtwDevice->FtwWorkSpaceBase + sizeof (EFI_GUID) + sizeof (UINT32),\r
572 WORKING_BLOCK_INVALID\r
573 );\r
85e923a5
LG
574 if (EFI_ERROR (Status)) {\r
575 FreePool (SpareBuffer);\r
576 return EFI_ABORTED;\r
577 }\r
578\r
579 FtwDevice->FtwWorkSpaceHeader->WorkingBlockInvalid = FTW_VALID_STATE;\r
580\r
581 //\r
582 // Write the spare block to working block\r
583 //\r
584 Status = FlushSpareBlockToWorkingBlock (FtwDevice);\r
585 if (EFI_ERROR (Status)) {\r
586 FreePool (SpareBuffer);\r
587 return Status;\r
588 }\r
1436aea4 589\r
85e923a5
LG
590 //\r
591 // Restore spare backup buffer into spare block , if no failure happened during FtwWrite.\r
592 //\r
1436aea4 593 Status = FtwEraseSpareBlock (FtwDevice);\r
de2d7497
SZ
594 if (EFI_ERROR (Status)) {\r
595 FreePool (SpareBuffer);\r
596 return EFI_ABORTED;\r
597 }\r
1436aea4
MK
598\r
599 Ptr = SpareBuffer;\r
85e923a5 600 for (Index = 0; Index < FtwDevice->NumberOfSpareBlock; Index += 1) {\r
0d3edd9d 601 Length = FtwDevice->SpareBlockSize;\r
85e923a5
LG
602 Status = FtwDevice->FtwBackupFvb->Write (\r
603 FtwDevice->FtwBackupFvb,\r
604 FtwDevice->FtwSpareLba + Index,\r
605 0,\r
606 &Length,\r
607 Ptr\r
608 );\r
609 if (EFI_ERROR (Status)) {\r
610 FreePool (SpareBuffer);\r
611 return EFI_ABORTED;\r
612 }\r
613\r
614 Ptr += Length;\r
615 }\r
616\r
617 FreePool (SpareBuffer);\r
618\r
87000d77 619 DEBUG ((DEBUG_INFO, "Ftw: reclaim work space successfully\n"));\r
85e923a5
LG
620\r
621 return EFI_SUCCESS;\r
622}\r