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.
26 // Event for Exit Boot Services Callback
28 STATIC EFI_EVENT mExitBootServicesEvent
= NULL
;
31 // Lib will ASSERT if more FVB devices than this are added to the system.
33 STATIC FVB_ENTRY
*mFvbEntry
;
34 STATIC EFI_EVENT mFvbRegistration
;
35 STATIC BOOLEAN mEfiFvbInitialized
= FALSE
;
36 STATIC UINTN mFvbCount
;
39 Check whether an address is runtime memory or not.
41 @param Address The Address being checked.
43 @retval TRUE The address is runtime memory.
44 @retval FALSE The address is not runtime memory.
52 UINT8 TmpMemoryMap
[1];
55 UINT32 DescriptorVersion
;
57 EFI_MEMORY_DESCRIPTOR
*MemoryMap
;
58 EFI_MEMORY_DESCRIPTOR
*MemoryMapPtr
;
65 // Get System MemoryMapSize
68 Status
= gBS
->GetMemoryMap (
70 (EFI_MEMORY_DESCRIPTOR
*)TmpMemoryMap
,
75 ASSERT (Status
== EFI_BUFFER_TOO_SMALL
);
77 // Enlarge space here, because we will allocate pool now.
79 MemoryMapSize
+= EFI_PAGE_SIZE
;
80 Status
= gBS
->AllocatePool (
85 ASSERT_EFI_ERROR (Status
);
88 // Get System MemoryMap
90 Status
= gBS
->GetMemoryMap (
97 ASSERT_EFI_ERROR (Status
);
99 MemoryMapPtr
= MemoryMap
;
101 // Search the request Address
103 for (Index
= 0; Index
< (MemoryMapSize
/ DescriptorSize
); Index
++) {
104 if (((EFI_PHYSICAL_ADDRESS
)(UINTN
)Address
>= MemoryMap
->PhysicalStart
) &&
105 ((EFI_PHYSICAL_ADDRESS
)(UINTN
)Address
< MemoryMap
->PhysicalStart
106 + LShiftU64 (MemoryMap
->NumberOfPages
, EFI_PAGE_SHIFT
))) {
110 if (MemoryMap
->Attribute
& EFI_MEMORY_RUNTIME
) {
118 MemoryMap
= (EFI_MEMORY_DESCRIPTOR
*)((UINTN
)MemoryMap
+ DescriptorSize
);
124 gBS
->FreePool (MemoryMapPtr
);
130 Update mFvbEntry. Add new entry, or update existing entry if Fvb protocol is
133 @param Event The Event that is being processed
134 @param Context Event Context
140 FvbNotificationEvent (
152 BufferSize
= sizeof (Handle
);
153 Status
= gBS
->LocateHandle (
155 &gEfiFirmwareVolumeBlockProtocolGuid
,
160 if (EFI_ERROR (Status
)) {
162 // Exit Path of While Loop....
167 UpdateIndex
= MAX_FVB_COUNT
;
168 for (Index
= 0; Index
< mFvbCount
; Index
++) {
169 if (mFvbEntry
[Index
].Handle
== Handle
) {
171 // If the handle is already in the table just update the protocol
178 if (UpdateIndex
== MAX_FVB_COUNT
) {
180 // Use the next free slot for a new entry
182 UpdateIndex
= mFvbCount
++;
184 // Check the UpdateIndex whether exceed the maximum value.
186 ASSERT (UpdateIndex
< MAX_FVB_COUNT
);
187 mFvbEntry
[UpdateIndex
].Handle
= Handle
;
190 // The array does not have enough entries
192 ASSERT (UpdateIndex
< MAX_FVB_COUNT
);
195 // Get the interface pointer and if it's ours, skip it
197 Status
= gBS
->HandleProtocol (
199 &gEfiFirmwareVolumeBlockProtocolGuid
,
200 (VOID
**) &mFvbEntry
[UpdateIndex
].Fvb
202 ASSERT_EFI_ERROR (Status
);
204 Status
= gBS
->HandleProtocol (
206 &gEfiFvbExtensionProtocolGuid
,
207 (VOID
**) &mFvbEntry
[UpdateIndex
].FvbExtension
209 if (Status
!= EFI_SUCCESS
) {
210 mFvbEntry
[UpdateIndex
].FvbExtension
= NULL
;
214 // Check the FVB can be accessed in RUNTIME, The FVBs in FVB handle list comes
216 // 1) Dxe Core. (FVB information is transferred from FV HOB).
218 // The FVB produced Dxe core is used for discoverying DXE driver and dispatch. These
219 // FVBs can only be accessed in boot time.
220 // FVB driver will discovery all FV in FLASH and these FVBs can be accessed in runtime.
221 // The FVB itself produced by FVB driver is allocated in runtime memory. So we can
222 // determine the what FVB can be accessed in RUNTIME by judging whether FVB itself is allocated
223 // in RUNTIME memory.
225 mFvbEntry
[UpdateIndex
].IsRuntimeAccess
= IsRuntimeMemory (mFvbEntry
[UpdateIndex
].Fvb
);
230 Convert all pointers in mFvbEntry after ExitBootServices.
232 @param Event The Event that is being processed
233 @param Context Event Context
238 FvbVirtualAddressChangeNotifyEvent (
244 if (mFvbEntry
!= NULL
) {
245 for (Index
= 0; Index
< MAX_FVB_COUNT
; Index
++) {
246 if (!mFvbEntry
[Index
].IsRuntimeAccess
) {
250 if (NULL
!= mFvbEntry
[Index
].Fvb
) {
251 EfiConvertPointer (0x0, (VOID
**) &mFvbEntry
[Index
].Fvb
->GetBlockSize
);
252 EfiConvertPointer (0x0, (VOID
**) &mFvbEntry
[Index
].Fvb
->GetPhysicalAddress
);
253 EfiConvertPointer (0x0, (VOID
**) &mFvbEntry
[Index
].Fvb
->GetAttributes
);
254 EfiConvertPointer (0x0, (VOID
**) &mFvbEntry
[Index
].Fvb
->SetAttributes
);
255 EfiConvertPointer (0x0, (VOID
**) &mFvbEntry
[Index
].Fvb
->Read
);
256 EfiConvertPointer (0x0, (VOID
**) &mFvbEntry
[Index
].Fvb
->Write
);
257 EfiConvertPointer (0x0, (VOID
**) &mFvbEntry
[Index
].Fvb
->EraseBlocks
);
258 EfiConvertPointer (0x0, (VOID
**) &mFvbEntry
[Index
].Fvb
);
261 if (NULL
!= mFvbEntry
[Index
].FvbExtension
) {
262 EfiConvertPointer (0x0, (VOID
**) &mFvbEntry
[Index
].FvbExtension
->EraseFvbCustomBlock
);
263 EfiConvertPointer (0x0, (VOID
**) &mFvbEntry
[Index
].FvbExtension
);
267 EfiConvertPointer (0x0, (VOID
**) &mFvbEntry
);
272 Library constructor function entry.
274 @param ImageHandle The handle of image who call this libary.
275 @param SystemTable The point of System Table.
277 @retval EFI_SUCESS Sucess construct this library.
278 @retval Others Fail to contruct this libary.
283 IN EFI_HANDLE ImageHandle
,
284 IN EFI_SYSTEM_TABLE
*SystemTable
290 Status
= gBS
->AllocatePool (
291 EfiRuntimeServicesData
,
292 (UINTN
) sizeof (FVB_ENTRY
) * MAX_FVB_COUNT
,
296 if (EFI_ERROR (Status
)) {
300 ZeroMem (mFvbEntry
, sizeof (FVB_ENTRY
) * MAX_FVB_COUNT
);
302 EfiCreateProtocolNotifyEvent (
303 &gEfiFirmwareVolumeBlockProtocolGuid
,
305 FvbNotificationEvent
,
311 // Register SetVirtualAddressMap () notify function
313 Status
= gBS
->CreateEvent (
314 EVT_SIGNAL_EXIT_BOOT_SERVICES
,
316 FvbVirtualAddressChangeNotifyEvent
,
318 &mExitBootServicesEvent
320 ASSERT_EFI_ERROR (Status
);
322 mEfiFvbInitialized
= TRUE
;
328 // =============================================================================
329 // The following functions wrap Fvb protocol in the Runtime Lib functions.
330 // The Instance translates into Fvb instance. The Fvb order defined by HOBs and
331 // thus the sequence of FVB protocol addition define Instance.
333 // EfiFvbInitialize () must be called before any of the following functions
335 // =============================================================================
339 Reads specified number of bytes into a buffer from the specified block
341 @param Instance The FV instance to be read from.
342 @param Lba The logical block address to be read from
343 @param Offset Offset into the block at which to begin reading
344 @param NumBytes Pointer that on input contains the total size of
345 the buffer. On output, it contains the total number
347 @param Buffer Pointer to a caller allocated buffer that will be
348 used to hold the data read
350 @retval EFI_INVALID_PARAMETER Invalid parameter
351 @retval EFI_SUCESS Sucess to Read block
352 @retval Others Fail to read block
359 IN OUT UINTN
*NumBytes
,
363 if (Instance
>= mFvbCount
) {
364 return EFI_INVALID_PARAMETER
;
367 if (EfiAtRuntime() && !mFvbEntry
[Instance
].IsRuntimeAccess
) {
368 return EFI_INVALID_PARAMETER
;
371 return mFvbEntry
[Instance
].Fvb
->Read (mFvbEntry
[Instance
].Fvb
, Lba
, Offset
, NumBytes
, Buffer
);
375 Writes specified number of bytes from the input buffer to the block
377 @param Instance The FV instance to be written to
378 @param Lba The starting logical block index to write to
379 @param Offset Offset into the block at which to begin writing
380 @param NumBytes Pointer that on input contains the total size of
381 the buffer. On output, it contains the total number
382 of bytes actually written
383 @param Buffer Pointer to a caller allocated buffer that contains
384 the source for the write
386 @retval EFI_INVALID_PARAMETER Invalid parameter
387 @retval EFI_SUCESS Sucess to write block
388 @retval Others Fail to write block
395 IN OUT UINTN
*NumBytes
,
399 if (Instance
>= mFvbCount
) {
400 return EFI_INVALID_PARAMETER
;
403 if (EfiAtRuntime() && !mFvbEntry
[Instance
].IsRuntimeAccess
) {
404 return EFI_INVALID_PARAMETER
;
407 return mFvbEntry
[Instance
].Fvb
->Write (mFvbEntry
[Instance
].Fvb
, Lba
, Offset
, NumBytes
, Buffer
);
411 Erases and initializes a firmware volume block
413 @param Instance The FV instance to be erased
414 @param Lba The logical block index to be erased
416 @retval EFI_INVALID_PARAMETER Invalid parameter
417 @retval EFI_SUCESS Sucess to erase block
418 @retval Others Fail to erase block
426 if (Instance
>= mFvbCount
) {
427 return EFI_INVALID_PARAMETER
;
430 if (EfiAtRuntime() && !mFvbEntry
[Instance
].IsRuntimeAccess
) {
431 return EFI_INVALID_PARAMETER
;
434 return mFvbEntry
[Instance
].Fvb
->EraseBlocks (mFvbEntry
[Instance
].Fvb
, Lba
, -1);
438 Retrieves attributes, insures positive polarity of attribute bits, returns
439 resulting attributes in output parameter
441 @param Instance The FV instance whose attributes is going to be returned
442 @param Attributes Output buffer which contains attributes
444 @retval EFI_INVALID_PARAMETER Invalid parameter
445 @retval EFI_SUCESS Sucess to get Fv attribute
446 @retval Others Fail to get Fv attribute
449 EfiFvbGetVolumeAttributes (
451 OUT EFI_FVB_ATTRIBUTES
*Attributes
454 if (Instance
>= mFvbCount
) {
455 return EFI_INVALID_PARAMETER
;
458 if (EfiAtRuntime() && !mFvbEntry
[Instance
].IsRuntimeAccess
) {
459 return EFI_INVALID_PARAMETER
;
462 return mFvbEntry
[Instance
].Fvb
->GetAttributes (mFvbEntry
[Instance
].Fvb
, Attributes
);
466 Modifies the current settings of the firmware volume according to the
467 input parameter, and returns the new setting of the volume
469 @param Instance The FV instance whose attributes is going to be
471 @param Attributes On input, it is a pointer to EFI_FVB_ATTRIBUTES
472 containing the desired firmware volume settings.
473 On successful return, it contains the new settings
474 of the firmware volume
476 @retval EFI_INVALID_PARAMETER Invalid parameter
477 @retval EFI_SUCESS Sucess to set Fv attribute
478 @retval Others Fail to set Fv attribute
481 EfiFvbSetVolumeAttributes (
483 IN EFI_FVB_ATTRIBUTES Attributes
486 if (Instance
>= mFvbCount
) {
487 return EFI_INVALID_PARAMETER
;
490 if (EfiAtRuntime() && !mFvbEntry
[Instance
].IsRuntimeAccess
) {
491 return EFI_INVALID_PARAMETER
;
494 return mFvbEntry
[Instance
].Fvb
->SetAttributes (mFvbEntry
[Instance
].Fvb
, &Attributes
);
498 Retrieves the physical address of a memory mapped FV
500 @param Instance The FV instance whose base address is going to be
502 @param BaseAddress Pointer to a caller allocated EFI_PHYSICAL_ADDRESS
503 that on successful return, contains the base address
504 of the firmware volume.
506 @retval EFI_INVALID_PARAMETER Invalid parameter
507 @retval EFI_SUCESS Sucess to get physical address
508 @retval Others Fail to get physical address
511 EfiFvbGetPhysicalAddress (
513 OUT EFI_PHYSICAL_ADDRESS
*BaseAddress
516 if (Instance
>= mFvbCount
) {
517 return EFI_INVALID_PARAMETER
;
520 if (EfiAtRuntime() && !mFvbEntry
[Instance
].IsRuntimeAccess
) {
521 return EFI_INVALID_PARAMETER
;
524 return mFvbEntry
[Instance
].Fvb
->GetPhysicalAddress (mFvbEntry
[Instance
].Fvb
, BaseAddress
);
528 Retrieve the size of a logical block
530 @param Instance The FV instance whose block size is going to be
532 @param Lba Indicates which block to return the size for.
533 @param BlockSize A pointer to a caller allocated UINTN in which
534 the size of the block is returned
535 @param NumOfBlocks a pointer to a caller allocated UINTN in which the
536 number of consecutive blocks starting with Lba is
537 returned. All blocks in this range have a size of
540 @retval EFI_INVALID_PARAMETER Invalid parameter
541 @retval EFI_SUCESS Sucess to get block size
542 @retval Others Fail to get block size
548 OUT UINTN
*BlockSize
,
549 OUT UINTN
*NumOfBlocks
552 if (Instance
>= mFvbCount
) {
553 return EFI_INVALID_PARAMETER
;
556 if (EfiAtRuntime() && !mFvbEntry
[Instance
].IsRuntimeAccess
) {
557 return EFI_INVALID_PARAMETER
;
560 return mFvbEntry
[Instance
].Fvb
->GetBlockSize (mFvbEntry
[Instance
].Fvb
, Lba
, BlockSize
, NumOfBlocks
);
564 Erases and initializes a specified range of a firmware volume
566 @param Instance The FV instance to be erased
567 @param StartLba The starting logical block index to be erased
568 @param OffsetStartLba Offset into the starting block at which to
570 @param LastLba The last logical block index to be erased
571 @param OffsetLastLba Offset into the last block at which to end erasing
573 @retval EFI_INVALID_PARAMETER Invalid parameter
574 @retval EFI_SUCESS Sucess to erase custom block range
575 @retval Others Fail to erase custom block range
578 EfiFvbEraseCustomBlockRange (
581 IN UINTN OffsetStartLba
,
583 IN UINTN OffsetLastLba
586 if (Instance
>= mFvbCount
) {
587 return EFI_INVALID_PARAMETER
;
590 if (EfiAtRuntime() && !mFvbEntry
[Instance
].IsRuntimeAccess
) {
591 return EFI_INVALID_PARAMETER
;
594 if (!(mFvbEntry
[Instance
].FvbExtension
)) {
595 return EFI_UNSUPPORTED
;
598 if (!(mFvbEntry
[Instance
].FvbExtension
->EraseFvbCustomBlock
)) {
599 return EFI_UNSUPPORTED
;
602 return mFvbEntry
[Instance
].FvbExtension
->EraseFvbCustomBlock (
603 mFvbEntry
[Instance
].FvbExtension
,