3 Firmware Volume Block Protocol Runtime Abstraction
5 mFvbEntry is an array of Handle Fvb pairs. The Fvb Lib Instance matches the
6 index in the mFvbEntry array. This should be the same sequence as the FVB's
7 were described in the HOB. We have to remember the handle so we can tell if
8 the protocol has been reinstalled and it needs updateing.
10 If you are using any of these lib functions.you must first call FvbInitialize ().
12 Copyright (c) 2006, Intel Corporation
13 All rights reserved. This program and the accompanying materials
14 are licensed and made available under the terms and conditions of the BSD License
15 which accompanies this distribution. The full text of the license may be found at
16 http://opensource.org/licenses/bsd-license.php
18 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
19 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
27 // Event for Exit Boot Services Callback
29 STATIC EFI_EVENT mExitBootServicesEvent
= NULL
;
32 // Lib will ASSERT if more FVB devices than this are added to the system.
34 STATIC FVB_ENTRY
*mFvbEntry
;
35 STATIC EFI_EVENT mFvbRegistration
;
36 STATIC BOOLEAN mEfiFvbInitialized
= FALSE
;
37 STATIC UINTN mFvbCount
;
40 Check whether an address is runtime memory or not.
42 @param Address The Address being checked.
44 @retval TRUE The address is runtime memory.
45 @retval FALSE The address is not runtime memory.
53 UINT8 TmpMemoryMap
[1];
56 UINT32 DescriptorVersion
;
58 EFI_MEMORY_DESCRIPTOR
*MemoryMap
;
59 EFI_MEMORY_DESCRIPTOR
*MemoryMapPtr
;
66 // Get System MemoryMapSize
69 Status
= gBS
->GetMemoryMap (
71 (EFI_MEMORY_DESCRIPTOR
*)TmpMemoryMap
,
76 ASSERT (Status
== EFI_BUFFER_TOO_SMALL
);
78 // Enlarge space here, because we will allocate pool now.
80 MemoryMapSize
+= EFI_PAGE_SIZE
;
81 Status
= gBS
->AllocatePool (
86 ASSERT_EFI_ERROR (Status
);
89 // Get System MemoryMap
91 Status
= gBS
->GetMemoryMap (
98 ASSERT_EFI_ERROR (Status
);
100 MemoryMapPtr
= MemoryMap
;
102 // Search the request Address
104 for (Index
= 0; Index
< (MemoryMapSize
/ DescriptorSize
); Index
++) {
105 if (((EFI_PHYSICAL_ADDRESS
)(UINTN
)Address
>= MemoryMap
->PhysicalStart
) &&
106 ((EFI_PHYSICAL_ADDRESS
)(UINTN
)Address
< MemoryMap
->PhysicalStart
107 + LShiftU64 (MemoryMap
->NumberOfPages
, EFI_PAGE_SHIFT
))) {
111 if (MemoryMap
->Attribute
& EFI_MEMORY_RUNTIME
) {
119 MemoryMap
= (EFI_MEMORY_DESCRIPTOR
*)((UINTN
)MemoryMap
+ DescriptorSize
);
125 gBS
->FreePool (MemoryMapPtr
);
131 Update mFvbEntry. Add new entry, or update existing entry if Fvb protocol is
134 @param Event The Event that is being processed
135 @param Context Event Context
141 FvbNotificationEvent (
153 BufferSize
= sizeof (Handle
);
154 Status
= gBS
->LocateHandle (
156 &gEfiFirmwareVolumeBlockProtocolGuid
,
161 if (EFI_ERROR (Status
)) {
163 // Exit Path of While Loop....
168 UpdateIndex
= MAX_FVB_COUNT
;
169 for (Index
= 0; Index
< mFvbCount
; Index
++) {
170 if (mFvbEntry
[Index
].Handle
== Handle
) {
172 // If the handle is already in the table just update the protocol
179 if (UpdateIndex
== MAX_FVB_COUNT
) {
181 // Use the next free slot for a new entry
183 UpdateIndex
= mFvbCount
++;
185 // Check the UpdateIndex whether exceed the maximum value.
187 ASSERT (UpdateIndex
< MAX_FVB_COUNT
);
188 mFvbEntry
[UpdateIndex
].Handle
= Handle
;
191 // The array does not have enough entries
193 ASSERT (UpdateIndex
< MAX_FVB_COUNT
);
196 // Get the interface pointer and if it's ours, skip it
198 Status
= gBS
->HandleProtocol (
200 &gEfiFirmwareVolumeBlockProtocolGuid
,
201 (VOID
**) &mFvbEntry
[UpdateIndex
].Fvb
203 ASSERT_EFI_ERROR (Status
);
205 Status
= gBS
->HandleProtocol (
207 &gEfiFvbExtensionProtocolGuid
,
208 (VOID
**) &mFvbEntry
[UpdateIndex
].FvbExtension
210 if (Status
!= EFI_SUCCESS
) {
211 mFvbEntry
[UpdateIndex
].FvbExtension
= NULL
;
215 // Check the FVB can be accessed in RUNTIME, The FVBs in FVB handle list comes
217 // 1) Dxe Core. (FVB information is transferred from FV HOB).
219 // The FVB produced Dxe core is used for discoverying DXE driver and dispatch. These
220 // FVBs can only be accessed in boot time.
221 // FVB driver will discovery all FV in FLASH and these FVBs can be accessed in runtime.
222 // The FVB itself produced by FVB driver is allocated in runtime memory. So we can
223 // determine the what FVB can be accessed in RUNTIME by judging whether FVB itself is allocated
224 // in RUNTIME memory.
226 mFvbEntry
[UpdateIndex
].IsRuntimeAccess
= IsRuntimeMemory (mFvbEntry
[UpdateIndex
].Fvb
);
231 Convert all pointers in mFvbEntry after ExitBootServices.
233 @param Event The Event that is being processed
234 @param Context Event Context
239 FvbVirtualAddressChangeNotifyEvent (
245 if (mFvbEntry
!= NULL
) {
246 for (Index
= 0; Index
< MAX_FVB_COUNT
; Index
++) {
247 if (!mFvbEntry
[Index
].IsRuntimeAccess
) {
251 if (NULL
!= mFvbEntry
[Index
].Fvb
) {
252 EfiConvertPointer (0x0, (VOID
**) &mFvbEntry
[Index
].Fvb
->GetBlockSize
);
253 EfiConvertPointer (0x0, (VOID
**) &mFvbEntry
[Index
].Fvb
->GetPhysicalAddress
);
254 EfiConvertPointer (0x0, (VOID
**) &mFvbEntry
[Index
].Fvb
->GetAttributes
);
255 EfiConvertPointer (0x0, (VOID
**) &mFvbEntry
[Index
].Fvb
->SetAttributes
);
256 EfiConvertPointer (0x0, (VOID
**) &mFvbEntry
[Index
].Fvb
->Read
);
257 EfiConvertPointer (0x0, (VOID
**) &mFvbEntry
[Index
].Fvb
->Write
);
258 EfiConvertPointer (0x0, (VOID
**) &mFvbEntry
[Index
].Fvb
->EraseBlocks
);
259 EfiConvertPointer (0x0, (VOID
**) &mFvbEntry
[Index
].Fvb
);
262 if (NULL
!= mFvbEntry
[Index
].FvbExtension
) {
263 EfiConvertPointer (0x0, (VOID
**) &mFvbEntry
[Index
].FvbExtension
->EraseFvbCustomBlock
);
264 EfiConvertPointer (0x0, (VOID
**) &mFvbEntry
[Index
].FvbExtension
);
268 EfiConvertPointer (0x0, (VOID
**) &mFvbEntry
);
273 Library constructor function entry.
275 @param ImageHandle The handle of image who call this libary.
276 @param SystemTable The point of System Table.
278 @retval EFI_SUCESS Sucess construct this library.
279 @retval Others Fail to contruct this libary.
284 IN EFI_HANDLE ImageHandle
,
285 IN EFI_SYSTEM_TABLE
*SystemTable
291 Status
= gBS
->AllocatePool (
292 EfiRuntimeServicesData
,
293 (UINTN
) sizeof (FVB_ENTRY
) * MAX_FVB_COUNT
,
297 if (EFI_ERROR (Status
)) {
301 ZeroMem (mFvbEntry
, sizeof (FVB_ENTRY
) * MAX_FVB_COUNT
);
303 EfiCreateProtocolNotifyEvent (
304 &gEfiFirmwareVolumeBlockProtocolGuid
,
306 FvbNotificationEvent
,
312 // Register SetVirtualAddressMap () notify function
314 Status
= gBS
->CreateEvent (
315 EVT_SIGNAL_EXIT_BOOT_SERVICES
,
317 FvbVirtualAddressChangeNotifyEvent
,
319 &mExitBootServicesEvent
321 ASSERT_EFI_ERROR (Status
);
323 mEfiFvbInitialized
= TRUE
;
329 // =============================================================================
330 // The following functions wrap Fvb protocol in the Runtime Lib functions.
331 // The Instance translates into Fvb instance. The Fvb order defined by HOBs and
332 // thus the sequence of FVB protocol addition define Instance.
334 // EfiFvbInitialize () must be called before any of the following functions
336 // =============================================================================
340 Reads specified number of bytes into a buffer from the specified block
342 @param Instance The FV instance to be read from.
343 @param Lba The logical block address to be read from
344 @param Offset Offset into the block at which to begin reading
345 @param NumBytes Pointer that on input contains the total size of
346 the buffer. On output, it contains the total number
348 @param Buffer Pointer to a caller allocated buffer that will be
349 used to hold the data read
351 @retval EFI_INVALID_PARAMETER Invalid parameter
352 @retval EFI_SUCESS Sucess to Read block
353 @retval Others Fail to read block
360 IN OUT UINTN
*NumBytes
,
364 if (Instance
>= mFvbCount
) {
365 return EFI_INVALID_PARAMETER
;
368 if (EfiAtRuntime() && !mFvbEntry
[Instance
].IsRuntimeAccess
) {
369 return EFI_INVALID_PARAMETER
;
372 return mFvbEntry
[Instance
].Fvb
->Read (mFvbEntry
[Instance
].Fvb
, Lba
, Offset
, NumBytes
, Buffer
);
376 Writes specified number of bytes from the input buffer to the block
378 @param Instance The FV instance to be written to
379 @param Lba The starting logical block index to write to
380 @param Offset Offset into the block at which to begin writing
381 @param NumBytes Pointer that on input contains the total size of
382 the buffer. On output, it contains the total number
383 of bytes actually written
384 @param Buffer Pointer to a caller allocated buffer that contains
385 the source for the write
387 @retval EFI_INVALID_PARAMETER Invalid parameter
388 @retval EFI_SUCESS Sucess to write block
389 @retval Others Fail to write block
396 IN OUT UINTN
*NumBytes
,
400 if (Instance
>= mFvbCount
) {
401 return EFI_INVALID_PARAMETER
;
404 if (EfiAtRuntime() && !mFvbEntry
[Instance
].IsRuntimeAccess
) {
405 return EFI_INVALID_PARAMETER
;
408 return mFvbEntry
[Instance
].Fvb
->Write (mFvbEntry
[Instance
].Fvb
, Lba
, Offset
, NumBytes
, Buffer
);
412 Erases and initializes a firmware volume block
414 @param Instance The FV instance to be erased
415 @param Lba The logical block index to be erased
417 @retval EFI_INVALID_PARAMETER Invalid parameter
418 @retval EFI_SUCESS Sucess to erase block
419 @retval Others Fail to erase block
427 if (Instance
>= mFvbCount
) {
428 return EFI_INVALID_PARAMETER
;
431 if (EfiAtRuntime() && !mFvbEntry
[Instance
].IsRuntimeAccess
) {
432 return EFI_INVALID_PARAMETER
;
435 return mFvbEntry
[Instance
].Fvb
->EraseBlocks (mFvbEntry
[Instance
].Fvb
, Lba
, -1);
439 Retrieves attributes, insures positive polarity of attribute bits, returns
440 resulting attributes in output parameter
442 @param Instance The FV instance whose attributes is going to be returned
443 @param Attributes Output buffer which contains attributes
445 @retval EFI_INVALID_PARAMETER Invalid parameter
446 @retval EFI_SUCESS Sucess to get Fv attribute
447 @retval Others Fail to get Fv attribute
450 EfiFvbGetVolumeAttributes (
452 OUT EFI_FVB_ATTRIBUTES
*Attributes
455 if (Instance
>= mFvbCount
) {
456 return EFI_INVALID_PARAMETER
;
459 if (EfiAtRuntime() && !mFvbEntry
[Instance
].IsRuntimeAccess
) {
460 return EFI_INVALID_PARAMETER
;
463 return mFvbEntry
[Instance
].Fvb
->GetAttributes (mFvbEntry
[Instance
].Fvb
, Attributes
);
467 Modifies the current settings of the firmware volume according to the
468 input parameter, and returns the new setting of the volume
470 @param Instance The FV instance whose attributes is going to be
472 @param Attributes On input, it is a pointer to EFI_FVB_ATTRIBUTES
473 containing the desired firmware volume settings.
474 On successful return, it contains the new settings
475 of the firmware volume
477 @retval EFI_INVALID_PARAMETER Invalid parameter
478 @retval EFI_SUCESS Sucess to set Fv attribute
479 @retval Others Fail to set Fv attribute
482 EfiFvbSetVolumeAttributes (
484 IN OUT EFI_FVB_ATTRIBUTES
*Attributes
487 if (Instance
>= mFvbCount
) {
488 return EFI_INVALID_PARAMETER
;
491 if (EfiAtRuntime() && !mFvbEntry
[Instance
].IsRuntimeAccess
) {
492 return EFI_INVALID_PARAMETER
;
495 return mFvbEntry
[Instance
].Fvb
->SetAttributes (mFvbEntry
[Instance
].Fvb
, Attributes
);
499 Retrieves the physical address of a memory mapped FV
501 @param Instance The FV instance whose base address is going to be
503 @param BaseAddress Pointer to a caller allocated EFI_PHYSICAL_ADDRESS
504 that on successful return, contains the base address
505 of the firmware volume.
507 @retval EFI_INVALID_PARAMETER Invalid parameter
508 @retval EFI_SUCESS Sucess to get physical address
509 @retval Others Fail to get physical address
512 EfiFvbGetPhysicalAddress (
514 OUT EFI_PHYSICAL_ADDRESS
*BaseAddress
517 if (Instance
>= mFvbCount
) {
518 return EFI_INVALID_PARAMETER
;
521 if (EfiAtRuntime() && !mFvbEntry
[Instance
].IsRuntimeAccess
) {
522 return EFI_INVALID_PARAMETER
;
525 return mFvbEntry
[Instance
].Fvb
->GetPhysicalAddress (mFvbEntry
[Instance
].Fvb
, BaseAddress
);
529 Retrieve the size of a logical block
531 @param Instance The FV instance whose block size is going to be
533 @param Lba Indicates which block to return the size for.
534 @param BlockSize A pointer to a caller allocated UINTN in which
535 the size of the block is returned
536 @param NumOfBlocks a pointer to a caller allocated UINTN in which the
537 number of consecutive blocks starting with Lba is
538 returned. All blocks in this range have a size of
541 @retval EFI_INVALID_PARAMETER Invalid parameter
542 @retval EFI_SUCESS Sucess to get block size
543 @retval Others Fail to get block size
549 OUT UINTN
*BlockSize
,
550 OUT UINTN
*NumOfBlocks
553 if (Instance
>= mFvbCount
) {
554 return EFI_INVALID_PARAMETER
;
557 if (EfiAtRuntime() && !mFvbEntry
[Instance
].IsRuntimeAccess
) {
558 return EFI_INVALID_PARAMETER
;
561 return mFvbEntry
[Instance
].Fvb
->GetBlockSize (mFvbEntry
[Instance
].Fvb
, Lba
, BlockSize
, NumOfBlocks
);
565 Erases and initializes a specified range of a firmware volume
567 @param Instance The FV instance to be erased
568 @param StartLba The starting logical block index to be erased
569 @param OffsetStartLba Offset into the starting block at which to
571 @param LastLba The last logical block index to be erased
572 @param OffsetLastLba Offset into the last block at which to end erasing
574 @retval EFI_INVALID_PARAMETER Invalid parameter
575 @retval EFI_SUCESS Sucess to erase custom block range
576 @retval Others Fail to erase custom block range
579 EfiFvbEraseCustomBlockRange (
582 IN UINTN OffsetStartLba
,
584 IN UINTN OffsetLastLba
587 if (Instance
>= mFvbCount
) {
588 return EFI_INVALID_PARAMETER
;
591 if (EfiAtRuntime() && !mFvbEntry
[Instance
].IsRuntimeAccess
) {
592 return EFI_INVALID_PARAMETER
;
595 if (!(mFvbEntry
[Instance
].FvbExtension
)) {
596 return EFI_UNSUPPORTED
;
599 if (!(mFvbEntry
[Instance
].FvbExtension
->EraseFvbCustomBlock
)) {
600 return EFI_UNSUPPORTED
;
603 return mFvbEntry
[Instance
].FvbExtension
->EraseFvbCustomBlock (
604 mFvbEntry
[Instance
].FvbExtension
,