c3459656b59ff00a6746289c93f0562f2a117571
[people/mcb30/edk2.git] / edk2 / MdeModulePkg / Library / EdkFvbServiceLib / X64 / Fvb.c
1 /**@file\r
2 \r
3   Firmware Volume Block Protocol Runtime Abstraction\r
4 \r
5   mFvbEntry is an array of Handle Fvb pairs. The Fvb Lib Instance matches the\r
6   index in the mFvbEntry array. This should be the same sequence as the FVB's\r
7   were described in the HOB. We have to remember the handle so we can tell if\r
8   the protocol has been reinstalled and it needs updateing.\r
9 \r
10   If you are using any of these lib functions.you must first call FvbInitialize ().\r
11 \r
12 Copyright (c) 2006, Intel Corporation\r
13 All rights reserved. This program and the accompanying materials\r
14 are licensed and made available under the terms and conditions of the BSD License\r
15 which accompanies this distribution.  The full text of the license may be found at\r
16 http://opensource.org/licenses/bsd-license.php\r
17 \r
18 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
19 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
20 \r
21 **/\r
22 \r
23 #include "Fvb.h"\r
24 \r
25 //\r
26 // Event for Set Virtual Map Changed Event\r
27 //\r
28 STATIC EFI_EVENT mSetVirtualMapChangedEvent = NULL;\r
29 \r
30 //\r
31 // Lib will ASSERT if more FVB devices than this are added to the system.\r
32 //\r
33 STATIC FVB_ENTRY          *mFvbEntry;\r
34 STATIC EFI_EVENT          mFvbRegistration;\r
35 STATIC UINTN              mFvbCount;\r
36 \r
37 /**\r
38   Check whether an address is runtime memory or not.\r
39 \r
40   @param    Address   The Address being checked.\r
41 \r
42   @retval   TRUE      The address is runtime memory.\r
43   @retval   FALSE     The address is not runtime memory.\r
44 **/\r
45 BOOLEAN\r
46 IsRuntimeMemory (\r
47   IN VOID   *Address\r
48   )\r
49 {\r
50   EFI_STATUS                           Status;\r
51   UINT8                                TmpMemoryMap[1];\r
52   UINTN                                MapKey;\r
53   UINTN                                DescriptorSize;\r
54   UINT32                               DescriptorVersion;\r
55   UINTN                                MemoryMapSize;\r
56   EFI_MEMORY_DESCRIPTOR                *MemoryMap;\r
57   EFI_MEMORY_DESCRIPTOR                *MemoryMapPtr;\r
58   BOOLEAN                              IsRuntime;\r
59   UINTN                                Index;\r
60 \r
61   IsRuntime = FALSE;\r
62 \r
63   //\r
64   // Get System MemoryMapSize\r
65   //\r
66   MemoryMapSize = 1;\r
67   Status = gBS->GetMemoryMap (\r
68                   &MemoryMapSize,\r
69                   (EFI_MEMORY_DESCRIPTOR *)TmpMemoryMap,\r
70                   &MapKey,\r
71                   &DescriptorSize,\r
72                   &DescriptorVersion\r
73                   );\r
74   ASSERT (Status == EFI_BUFFER_TOO_SMALL);\r
75   //\r
76   // Enlarge space here, because we will allocate pool now.\r
77   //\r
78   MemoryMapSize += EFI_PAGE_SIZE;\r
79   Status = gBS->AllocatePool (\r
80                   EfiBootServicesData,\r
81                   MemoryMapSize,\r
82                   (VOID**)&MemoryMap\r
83                   );\r
84   ASSERT_EFI_ERROR (Status);\r
85 \r
86   //\r
87   // Get System MemoryMap\r
88   //\r
89   Status = gBS->GetMemoryMap (\r
90                   &MemoryMapSize,\r
91                   MemoryMap,\r
92                   &MapKey,\r
93                   &DescriptorSize,\r
94                   &DescriptorVersion\r
95                   );\r
96   ASSERT_EFI_ERROR (Status);\r
97 \r
98   MemoryMapPtr = MemoryMap;\r
99   //\r
100   // Search the request Address\r
101   //\r
102   for (Index = 0; Index < (MemoryMapSize / DescriptorSize); Index++) {\r
103     if (((EFI_PHYSICAL_ADDRESS)(UINTN)Address >= MemoryMap->PhysicalStart) &&\r
104         ((EFI_PHYSICAL_ADDRESS)(UINTN)Address < MemoryMap->PhysicalStart\r
105                                               + LShiftU64 (MemoryMap->NumberOfPages, EFI_PAGE_SHIFT))) {\r
106       //\r
107       // Found it\r
108       //\r
109       if (MemoryMap->Attribute & EFI_MEMORY_RUNTIME) {\r
110         IsRuntime = TRUE;\r
111       }\r
112       break;\r
113     }\r
114     //\r
115     // Get next item\r
116     //\r
117     MemoryMap = (EFI_MEMORY_DESCRIPTOR *)((UINTN)MemoryMap + DescriptorSize);\r
118   }\r
119 \r
120   //\r
121   // Done\r
122   //\r
123   gBS->FreePool (MemoryMapPtr);\r
124 \r
125   return IsRuntime;\r
126 }\r
127 \r
128 /**\r
129   Update mFvbEntry. Add new entry, or update existing entry if Fvb protocol is\r
130   reinstalled.\r
131 \r
132   @param Event      The Event that is being processed\r
133   @param Context    Event Context\r
134 \r
135 **/\r
136 STATIC\r
137 VOID\r
138 EFIAPI\r
139 FvbNotificationEvent (\r
140   IN  EFI_EVENT       Event,\r
141   IN  VOID            *Context\r
142   )\r
143 {\r
144   EFI_STATUS  Status;\r
145   UINTN       BufferSize;\r
146   EFI_HANDLE  Handle;\r
147   UINTN       Index;\r
148   UINTN       UpdateIndex;\r
149 \r
150   while (TRUE) {\r
151     BufferSize = sizeof (Handle);\r
152     Status = gBS->LocateHandle (\r
153                     ByRegisterNotify,\r
154                     &gEfiFirmwareVolumeBlockProtocolGuid,\r
155                     mFvbRegistration,\r
156                     &BufferSize,\r
157                     &Handle\r
158                     );\r
159     if (EFI_ERROR (Status)) {\r
160       //\r
161       // Exit Path of While Loop....\r
162       //\r
163       break;\r
164     }\r
165 \r
166     UpdateIndex = MAX_FVB_COUNT;\r
167     for (Index = 0; Index < mFvbCount; Index++) {\r
168       if (mFvbEntry[Index].Handle == Handle) {\r
169         //\r
170         //  If the handle is already in the table just update the protocol\r
171         //\r
172         UpdateIndex = Index;\r
173         break;\r
174       }\r
175     }\r
176 \r
177     if (UpdateIndex == MAX_FVB_COUNT) {\r
178       //\r
179       // Use the next free slot for a new entry\r
180       //\r
181       UpdateIndex                   = mFvbCount++;\r
182       //\r
183       // Check the UpdateIndex whether exceed the maximum value.\r
184       //\r
185       ASSERT (UpdateIndex < MAX_FVB_COUNT);\r
186       mFvbEntry[UpdateIndex].Handle = Handle;\r
187     }\r
188     //\r
189     // The array does not have enough entries\r
190     //\r
191     ASSERT (UpdateIndex < MAX_FVB_COUNT);\r
192 \r
193     //\r
194     //  Get the interface pointer and if it's ours, skip it\r
195     //\r
196     Status = gBS->HandleProtocol (\r
197                     Handle,\r
198                     &gEfiFirmwareVolumeBlockProtocolGuid,\r
199                     (VOID **) &mFvbEntry[UpdateIndex].Fvb\r
200                     );\r
201     ASSERT_EFI_ERROR (Status);\r
202 \r
203     Status = gBS->HandleProtocol (\r
204                     Handle,\r
205                     &gEfiFvbExtensionProtocolGuid,\r
206                     (VOID **) &mFvbEntry[UpdateIndex].FvbExtension\r
207                     );\r
208     if (Status != EFI_SUCCESS) {\r
209       mFvbEntry[UpdateIndex].FvbExtension = NULL;\r
210     }\r
211 \r
212     //\r
213     // Check the FVB can be accessed in RUNTIME, The FVBs in FVB handle list comes\r
214     // from two way:\r
215     // 1) Dxe Core. (FVB information is transferred from FV HOB).\r
216     // 2) FVB driver.\r
217     // The FVB produced Dxe core is used for discoverying DXE driver and dispatch. These\r
218     // FVBs can only be accessed in boot time.\r
219     // FVB driver will discovery all FV in FLASH and these FVBs can be accessed in runtime.\r
220     // The FVB itself produced by FVB driver is allocated in runtime memory. So we can\r
221     // determine the what FVB can be accessed in RUNTIME by judging whether FVB itself is allocated\r
222     // in RUNTIME memory.\r
223     //\r
224     mFvbEntry[UpdateIndex].IsRuntimeAccess = IsRuntimeMemory (mFvbEntry[UpdateIndex].Fvb);\r
225   }\r
226 }\r
227 \r
228 /**\r
229   Convert all pointers in mFvbEntry after ExitBootServices.\r
230 \r
231   @param Event      The Event that is being processed\r
232   @param Context    Event Context\r
233 \r
234 **/\r
235 VOID\r
236 EFIAPI\r
237 FvbVirtualAddressChangeNotifyEvent (\r
238   IN EFI_EVENT        Event,\r
239   IN VOID             *Context\r
240   )\r
241 {\r
242   UINTN Index;\r
243   if (mFvbEntry != NULL) {\r
244     for (Index = 0; Index < MAX_FVB_COUNT; Index++) {\r
245       if (!mFvbEntry[Index].IsRuntimeAccess) {\r
246         continue;\r
247       }\r
248 \r
249       if (NULL != mFvbEntry[Index].Fvb) {\r
250         EfiConvertPointer (0x0, (VOID **) &mFvbEntry[Index].Fvb->GetBlockSize);\r
251         EfiConvertPointer (0x0, (VOID **) &mFvbEntry[Index].Fvb->GetPhysicalAddress);\r
252         EfiConvertPointer (0x0, (VOID **) &mFvbEntry[Index].Fvb->GetAttributes);\r
253         EfiConvertPointer (0x0, (VOID **) &mFvbEntry[Index].Fvb->SetAttributes);\r
254         EfiConvertPointer (0x0, (VOID **) &mFvbEntry[Index].Fvb->Read);\r
255         EfiConvertPointer (0x0, (VOID **) &mFvbEntry[Index].Fvb->Write);\r
256         EfiConvertPointer (0x0, (VOID **) &mFvbEntry[Index].Fvb->EraseBlocks);\r
257         EfiConvertPointer (0x0, (VOID **) &mFvbEntry[Index].Fvb);\r
258       }\r
259 \r
260       if (NULL != mFvbEntry[Index].FvbExtension) {\r
261         EfiConvertPointer (0x0, (VOID **) &mFvbEntry[Index].FvbExtension->EraseFvbCustomBlock);\r
262         EfiConvertPointer (0x0, (VOID **) &mFvbEntry[Index].FvbExtension);\r
263       }\r
264     }\r
265 \r
266     EfiConvertPointer (0x0, (VOID **) &mFvbEntry);\r
267   }\r
268 }\r
269 \r
270 /**\r
271   Library constructor function entry.\r
272 \r
273   @param ImageHandle    The handle of image who call this libary.\r
274   @param SystemTable    The point of System Table.\r
275 \r
276   @retval EFI_SUCESS    Sucess construct this library.\r
277   @retval Others        Fail to contruct this libary.\r
278 **/\r
279 EFI_STATUS\r
280 EFIAPI\r
281 FvbLibInitialize (\r
282   IN EFI_HANDLE         ImageHandle,\r
283   IN EFI_SYSTEM_TABLE   *SystemTable\r
284   )\r
285 {\r
286   UINTN Status;\r
287   mFvbCount = 0;\r
288 \r
289   Status = gBS->AllocatePool (\r
290                   EfiRuntimeServicesData,\r
291                   (UINTN) sizeof (FVB_ENTRY) * MAX_FVB_COUNT,\r
292                   (VOID *) &mFvbEntry\r
293                   );\r
294 \r
295   if (EFI_ERROR (Status)) {\r
296     return Status;\r
297   }\r
298 \r
299   ZeroMem (mFvbEntry, sizeof (FVB_ENTRY) * MAX_FVB_COUNT);\r
300 \r
301   EfiCreateProtocolNotifyEvent (\r
302     &gEfiFirmwareVolumeBlockProtocolGuid,\r
303     TPL_CALLBACK,\r
304     FvbNotificationEvent,\r
305     NULL,\r
306     &mFvbRegistration\r
307     );\r
308 \r
309   //\r
310   // Register SetVirtualAddressMap () notify function\r
311   //\r
312   Status = gBS->CreateEvent (\r
313                   EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE,\r
314                   TPL_NOTIFY,\r
315                   FvbVirtualAddressChangeNotifyEvent,\r
316                   NULL,\r
317                   &mSetVirtualMapChangedEvent\r
318                   );\r
319   ASSERT_EFI_ERROR (Status);\r
320 \r
321   return EFI_SUCCESS;\r
322 }\r
323 \r
324 //\r
325 // =============================================================================\r
326 // The following functions wrap Fvb protocol in the Runtime Lib functions.\r
327 // The Instance translates into Fvb instance. The Fvb order defined by HOBs and\r
328 // thus the sequence of FVB protocol addition define Instance.\r
329 //\r
330 // EfiFvbInitialize () must be called before any of the following functions\r
331 // must be called.\r
332 // =============================================================================\r
333 //\r
334 \r
335 /**\r
336   Reads specified number of bytes into a buffer from the specified block\r
337 \r
338   @param Instance     The FV instance to be read from.\r
339   @param Lba          The logical block address to be read from\r
340   @param Offset       Offset into the block at which to begin reading\r
341   @param NumBytes     Pointer that on input contains the total size of\r
342                       the buffer. On output, it contains the total number\r
343                       of bytes read\r
344   @param Buffer       Pointer to a caller allocated buffer that will be\r
345                       used to hold the data read\r
346 \r
347   @retval EFI_INVALID_PARAMETER  Invalid parameter\r
348   @retval EFI_SUCESS             Sucess to Read block\r
349   @retval Others                 Fail to read block\r
350 **/\r
351 EFI_STATUS\r
352 EfiFvbReadBlock (\r
353   IN UINTN                                        Instance,\r
354   IN EFI_LBA                                      Lba,\r
355   IN UINTN                                        Offset,\r
356   IN OUT UINTN                                    *NumBytes,\r
357   IN UINT8                                        *Buffer\r
358   )\r
359 {\r
360   if (Instance >= mFvbCount) {\r
361     return EFI_INVALID_PARAMETER;\r
362   }\r
363 \r
364   if (EfiAtRuntime() && !mFvbEntry[Instance].IsRuntimeAccess) {\r
365     return EFI_INVALID_PARAMETER;\r
366   }\r
367 \r
368   return mFvbEntry[Instance].Fvb->Read (mFvbEntry[Instance].Fvb, Lba, Offset, NumBytes, Buffer);\r
369 }\r
370 \r
371 /**\r
372    Writes specified number of bytes from the input buffer to the block\r
373 \r
374   @param Instance         The FV instance to be written to\r
375   @param Lba              The starting logical block index to write to\r
376   @param Offset           Offset into the block at which to begin writing\r
377   @param NumBytes         Pointer that on input contains the total size of\r
378                           the buffer. On output, it contains the total number\r
379                           of bytes actually written\r
380   @param Buffer           Pointer to a caller allocated buffer that contains\r
381                           the source for the write\r
382 \r
383   @retval EFI_INVALID_PARAMETER  Invalid parameter\r
384   @retval EFI_SUCESS             Sucess to write block\r
385   @retval Others                 Fail to write block\r
386 **/\r
387 EFI_STATUS\r
388 EfiFvbWriteBlock (\r
389   IN UINTN                                        Instance,\r
390   IN EFI_LBA                                      Lba,\r
391   IN UINTN                                        Offset,\r
392   IN OUT UINTN                                    *NumBytes,\r
393   IN UINT8                                        *Buffer\r
394   )\r
395 {\r
396   if (Instance >= mFvbCount) {\r
397     return EFI_INVALID_PARAMETER;\r
398   }\r
399 \r
400   if (EfiAtRuntime() && !mFvbEntry[Instance].IsRuntimeAccess) {\r
401     return EFI_INVALID_PARAMETER;\r
402   }\r
403 \r
404   return mFvbEntry[Instance].Fvb->Write (mFvbEntry[Instance].Fvb, Lba, Offset, NumBytes, Buffer);\r
405 }\r
406 \r
407 /**\r
408    Erases and initializes a firmware volume block\r
409 \r
410    @param Instance      The FV instance to be erased\r
411    @param Lba           The logical block index to be erased\r
412 \r
413    @retval EFI_INVALID_PARAMETER  Invalid parameter\r
414    @retval EFI_SUCESS             Sucess to erase block\r
415    @retval Others                 Fail to erase block\r
416 **/\r
417 EFI_STATUS\r
418 EfiFvbEraseBlock (\r
419   IN UINTN                                Instance,\r
420   IN EFI_LBA                              Lba\r
421   )\r
422 {\r
423   if (Instance >= mFvbCount) {\r
424     return EFI_INVALID_PARAMETER;\r
425   }\r
426 \r
427   if (EfiAtRuntime() && !mFvbEntry[Instance].IsRuntimeAccess) {\r
428     return EFI_INVALID_PARAMETER;\r
429   }\r
430 \r
431   return mFvbEntry[Instance].Fvb->EraseBlocks (mFvbEntry[Instance].Fvb, Lba, -1);\r
432 }\r
433 \r
434 /**\r
435   Retrieves attributes, insures positive polarity of attribute bits, returns\r
436   resulting attributes in output parameter\r
437 \r
438   @param Instance       The FV instance whose attributes is going to be returned\r
439   @param Attributes     Output buffer which contains attributes\r
440 \r
441   @retval EFI_INVALID_PARAMETER  Invalid parameter\r
442   @retval EFI_SUCESS             Sucess to get Fv attribute\r
443   @retval Others                 Fail to get Fv attribute\r
444 **/\r
445 EFI_STATUS\r
446 EfiFvbGetVolumeAttributes (\r
447   IN UINTN                                Instance,\r
448   OUT EFI_FVB_ATTRIBUTES                  *Attributes\r
449   )\r
450 {\r
451   if (Instance >= mFvbCount) {\r
452     return EFI_INVALID_PARAMETER;\r
453   }\r
454 \r
455   if (EfiAtRuntime() && !mFvbEntry[Instance].IsRuntimeAccess) {\r
456     return EFI_INVALID_PARAMETER;\r
457   }\r
458 \r
459   return mFvbEntry[Instance].Fvb->GetAttributes (mFvbEntry[Instance].Fvb, Attributes);\r
460 }\r
461 \r
462 /**\r
463    Modifies the current settings of the firmware volume according to the\r
464    input parameter, and returns the new setting of the volume\r
465 \r
466    @param Instance        The FV instance whose attributes is going to be\r
467                           modified\r
468    @param Attributes      On input, it is a pointer to EFI_FVB_ATTRIBUTES\r
469                           containing the desired firmware volume settings.\r
470                           On successful return, it contains the new settings\r
471                           of the firmware volume\r
472 \r
473   @retval EFI_INVALID_PARAMETER  Invalid parameter\r
474   @retval EFI_SUCESS             Sucess to set Fv attribute\r
475   @retval Others                 Fail to set Fv attribute\r
476 **/\r
477 EFI_STATUS\r
478 EfiFvbSetVolumeAttributes (\r
479   IN     UINTN                                Instance,\r
480   IN OUT EFI_FVB_ATTRIBUTES                   *Attributes\r
481   )\r
482 {\r
483   if (Instance >= mFvbCount) {\r
484     return EFI_INVALID_PARAMETER;\r
485   }\r
486 \r
487   if (EfiAtRuntime() && !mFvbEntry[Instance].IsRuntimeAccess) {\r
488     return EFI_INVALID_PARAMETER;\r
489   }\r
490 \r
491   return mFvbEntry[Instance].Fvb->SetAttributes (mFvbEntry[Instance].Fvb, Attributes);\r
492 }\r
493 \r
494 /**\r
495    Retrieves the physical address of a memory mapped FV\r
496 \r
497    @param Instance      The FV instance whose base address is going to be\r
498                         returned\r
499    @param BaseAddress   Pointer to a caller allocated EFI_PHYSICAL_ADDRESS\r
500                         that on successful return, contains the base address\r
501                         of the firmware volume.\r
502 \r
503   @retval EFI_INVALID_PARAMETER  Invalid parameter\r
504   @retval EFI_SUCESS             Sucess to get physical address\r
505   @retval Others                 Fail to get physical address\r
506 **/\r
507 EFI_STATUS\r
508 EfiFvbGetPhysicalAddress (\r
509   IN UINTN                                Instance,\r
510   OUT EFI_PHYSICAL_ADDRESS                *BaseAddress\r
511   )\r
512 {\r
513   if (Instance >= mFvbCount) {\r
514     return EFI_INVALID_PARAMETER;\r
515   }\r
516 \r
517   if (EfiAtRuntime() && !mFvbEntry[Instance].IsRuntimeAccess) {\r
518     return EFI_INVALID_PARAMETER;\r
519   }\r
520 \r
521   return mFvbEntry[Instance].Fvb->GetPhysicalAddress (mFvbEntry[Instance].Fvb, BaseAddress);\r
522 }\r
523 \r
524 /**\r
525    Retrieve the size of a logical block\r
526 \r
527    @param Instance            The FV instance whose block size is going to be\r
528                               returned\r
529    @param Lba                 Indicates which block to return the size for.\r
530    @param BlockSize           A pointer to a caller allocated UINTN in which\r
531                               the size of the block is returned\r
532    @param NumOfBlocks         a pointer to a caller allocated UINTN in which the\r
533                               number of consecutive blocks starting with Lba is\r
534                               returned. All blocks in this range have a size of\r
535                               BlockSize\r
536 \r
537   @retval EFI_INVALID_PARAMETER  Invalid parameter\r
538   @retval EFI_SUCESS             Sucess to get block size\r
539   @retval Others                 Fail to get block size\r
540 **/\r
541 EFI_STATUS\r
542 EfiFvbGetBlockSize (\r
543   IN UINTN                                        Instance,\r
544   IN EFI_LBA                                      Lba,\r
545   OUT UINTN                                       *BlockSize,\r
546   OUT UINTN                                       *NumOfBlocks\r
547   )\r
548 {\r
549   if (Instance >= mFvbCount) {\r
550     return EFI_INVALID_PARAMETER;\r
551   }\r
552 \r
553   if (EfiAtRuntime() && !mFvbEntry[Instance].IsRuntimeAccess) {\r
554     return EFI_INVALID_PARAMETER;\r
555   }\r
556 \r
557   return mFvbEntry[Instance].Fvb->GetBlockSize (mFvbEntry[Instance].Fvb, Lba, BlockSize, NumOfBlocks);\r
558 }\r
559 \r
560 /**\r
561    Erases and initializes a specified range of a firmware volume\r
562 \r
563    @param Instance          The FV instance to be erased\r
564    @param StartLba          The starting logical block index to be erased\r
565    @param OffsetStartLba    Offset into the starting block at which to\r
566                             begin erasing\r
567    @param LastLba           The last logical block index to be erased\r
568    @param OffsetLastLba     Offset into the last block at which to end erasing\r
569 \r
570   @retval EFI_INVALID_PARAMETER  Invalid parameter\r
571   @retval EFI_SUCESS             Sucess to erase custom block range\r
572   @retval Others                 Fail to erase custom block range\r
573 **/\r
574 EFI_STATUS\r
575 EfiFvbEraseCustomBlockRange (\r
576   IN UINTN                                Instance,\r
577   IN EFI_LBA                              StartLba,\r
578   IN UINTN                                OffsetStartLba,\r
579   IN EFI_LBA                              LastLba,\r
580   IN UINTN                                OffsetLastLba\r
581   )\r
582 {\r
583   if (Instance >= mFvbCount) {\r
584     return EFI_INVALID_PARAMETER;\r
585   }\r
586 \r
587   if (EfiAtRuntime() && !mFvbEntry[Instance].IsRuntimeAccess) {\r
588     return EFI_INVALID_PARAMETER;\r
589   }\r
590 \r
591   if (!(mFvbEntry[Instance].FvbExtension)) {\r
592     return EFI_UNSUPPORTED;\r
593   }\r
594 \r
595   if (!(mFvbEntry[Instance].FvbExtension->EraseFvbCustomBlock)) {\r
596     return EFI_UNSUPPORTED;\r
597   }\r
598 \r
599   return mFvbEntry[Instance].FvbExtension->EraseFvbCustomBlock (\r
600                                             mFvbEntry[Instance].FvbExtension,\r
601                                             StartLba,\r
602                                             OffsetStartLba,\r
603                                             LastLba,\r
604                                             OffsetLastLba\r
605                                             );\r
606 }\r