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 // Lib will ASSERT if more FVB devices than this are added to the system.
28 STATIC FVB_ENTRY
*mFvbEntry
;
29 STATIC EFI_EVENT mFvbRegistration
;
30 STATIC BOOLEAN mEfiFvbInitialized
= FALSE
;
31 STATIC UINTN mFvbCount
;
34 Check whether an address is runtime memory or not.
36 @param Address The Address being checked.
38 @retval TRUE The address is runtime memory.
39 @retval FALSE The address is not runtime memory.
47 UINT8 TmpMemoryMap
[1];
50 UINT32 DescriptorVersion
;
52 EFI_MEMORY_DESCRIPTOR
*MemoryMap
;
53 EFI_MEMORY_DESCRIPTOR
*MemoryMapPtr
;
60 // Get System MemoryMapSize
63 Status
= gBS
->GetMemoryMap (
65 (EFI_MEMORY_DESCRIPTOR
*)TmpMemoryMap
,
70 ASSERT (Status
== EFI_BUFFER_TOO_SMALL
);
72 // Enlarge space here, because we will allocate pool now.
74 MemoryMapSize
+= EFI_PAGE_SIZE
;
75 Status
= gBS
->AllocatePool (
80 ASSERT_EFI_ERROR (Status
);
83 // Get System MemoryMap
85 Status
= gBS
->GetMemoryMap (
92 ASSERT_EFI_ERROR (Status
);
94 MemoryMapPtr
= MemoryMap
;
96 // Search the request Address
98 for (Index
= 0; Index
< (MemoryMapSize
/ DescriptorSize
); Index
++) {
99 if (((EFI_PHYSICAL_ADDRESS
)(UINTN
)Address
>= MemoryMap
->PhysicalStart
) &&
100 ((EFI_PHYSICAL_ADDRESS
)(UINTN
)Address
< MemoryMap
->PhysicalStart
101 + LShiftU64 (MemoryMap
->NumberOfPages
, EFI_PAGE_SHIFT
))) {
105 if (MemoryMap
->Attribute
& EFI_MEMORY_RUNTIME
) {
113 MemoryMap
= (EFI_MEMORY_DESCRIPTOR
*)((UINTN
)MemoryMap
+ DescriptorSize
);
119 gBS
->FreePool (MemoryMapPtr
);
125 Update mFvbEntry. Add new entry, or update existing entry if Fvb protocol is
128 @param Event The Event that is being processed
129 @param Context Event Context
135 FvbNotificationEvent (
147 BufferSize
= sizeof (Handle
);
148 Status
= gBS
->LocateHandle (
150 &gEfiFirmwareVolumeBlockProtocolGuid
,
155 if (EFI_ERROR (Status
)) {
157 // Exit Path of While Loop....
162 UpdateIndex
= MAX_FVB_COUNT
;
163 for (Index
= 0; Index
< mFvbCount
; Index
++) {
164 if (mFvbEntry
[Index
].Handle
== Handle
) {
166 // If the handle is already in the table just update the protocol
173 if (UpdateIndex
== MAX_FVB_COUNT
) {
175 // Use the next free slot for a new entry
177 UpdateIndex
= mFvbCount
++;
179 // Check the UpdateIndex whether exceed the maximum value.
181 ASSERT (UpdateIndex
< MAX_FVB_COUNT
);
182 mFvbEntry
[UpdateIndex
].Handle
= Handle
;
185 // The array does not have enough entries
187 ASSERT (UpdateIndex
< MAX_FVB_COUNT
);
190 // Get the interface pointer and if it's ours, skip it
192 Status
= gBS
->HandleProtocol (
194 &gEfiFirmwareVolumeBlockProtocolGuid
,
195 (VOID
**) &mFvbEntry
[UpdateIndex
].Fvb
197 ASSERT_EFI_ERROR (Status
);
199 Status
= gBS
->HandleProtocol (
201 &gEfiFvbExtensionProtocolGuid
,
202 (VOID
**) &mFvbEntry
[UpdateIndex
].FvbExtension
204 if (Status
!= EFI_SUCCESS
) {
205 mFvbEntry
[UpdateIndex
].FvbExtension
= NULL
;
209 // Check the FVB can be accessed in RUNTIME, The FVBs in FVB handle list comes
211 // 1) Dxe Core. (FVB information is transferred from FV HOB).
213 // The FVB produced Dxe core is used for discoverying DXE driver and dispatch. These
214 // FVBs can only be accessed in boot time.
215 // FVB driver will discovery all FV in FLASH and these FVBs can be accessed in runtime.
216 // The FVB itself produced by FVB driver is allocated in runtime memory. So we can
217 // determine the what FVB can be accessed in RUNTIME by judging whether FVB itself is allocated
218 // in RUNTIME memory.
220 mFvbEntry
[UpdateIndex
].IsRuntimeAccess
= IsRuntimeMemory (mFvbEntry
[UpdateIndex
].Fvb
);
225 Convert all pointers in mFvbEntry after ExitBootServices.
227 @param Event The Event that is being processed
228 @param Context Event Context
233 FvbVirtualAddressChangeNotifyEvent (
239 if (mFvbEntry
!= NULL
) {
240 for (Index
= 0; Index
< MAX_FVB_COUNT
; Index
++) {
241 if (!mFvbEntry
[Index
].IsRuntimeAccess
) {
245 if (NULL
!= mFvbEntry
[Index
].Fvb
) {
246 EfiConvertPointer (0x0, (VOID
**) &mFvbEntry
[Index
].Fvb
->GetBlockSize
);
247 EfiConvertPointer (0x0, (VOID
**) &mFvbEntry
[Index
].Fvb
->GetPhysicalAddress
);
248 EfiConvertPointer (0x0, (VOID
**) &mFvbEntry
[Index
].Fvb
->GetVolumeAttributes
);
249 EfiConvertPointer (0x0, (VOID
**) &mFvbEntry
[Index
].Fvb
->SetVolumeAttributes
);
250 EfiConvertPointer (0x0, (VOID
**) &mFvbEntry
[Index
].Fvb
->Read
);
251 EfiConvertPointer (0x0, (VOID
**) &mFvbEntry
[Index
].Fvb
->Write
);
252 EfiConvertPointer (0x0, (VOID
**) &mFvbEntry
[Index
].Fvb
->EraseBlocks
);
253 EfiConvertPointer (0x0, (VOID
**) &mFvbEntry
[Index
].Fvb
);
256 if (NULL
!= mFvbEntry
[Index
].FvbExtension
) {
257 EfiConvertPointer (0x0, (VOID
**) &mFvbEntry
[Index
].FvbExtension
->EraseFvbCustomBlock
);
258 EfiConvertPointer (0x0, (VOID
**) &mFvbEntry
[Index
].FvbExtension
);
262 EfiConvertPointer (0x0, (VOID
**) &mFvbEntry
);
267 Library constructor function entry.
269 @param ImageHandle The handle of image who call this libary.
270 @param SystemTable The point of System Table.
272 @retval EFI_SUCESS Sucess construct this library.
273 @retval Others Fail to contruct this libary.
278 IN EFI_HANDLE ImageHandle
,
279 IN EFI_SYSTEM_TABLE
*SystemTable
285 Status
= gBS
->AllocatePool (
286 EfiRuntimeServicesData
,
287 (UINTN
) sizeof (FVB_ENTRY
) * MAX_FVB_COUNT
,
291 if (EFI_ERROR (Status
)) {
295 ZeroMem (mFvbEntry
, sizeof (FVB_ENTRY
) * MAX_FVB_COUNT
);
297 EfiCreateProtocolNotifyEvent (
298 &gEfiFirmwareVolumeBlockProtocolGuid
,
300 FvbNotificationEvent
,
306 // Register SetVirtualAddressMap () notify function
308 // Status = gBS->CreateEvent (
309 // EFI_EVENT_SIGNAL_VIRTUAL_ADDRESS_CHANGE,
311 // EfiRuntimeLibFvbVirtualNotifyEvent,
313 // &mEfiFvbVirtualNotifyEvent
315 // ASSERT_EFI_ERROR (Status);
319 // Register SetVirtualAddressMap () notify function
322 ASSERT_EFI_ERROR (Status
);
324 mEfiFvbInitialized
= TRUE
;
330 // =============================================================================
331 // The following functions wrap Fvb protocol in the Runtime Lib functions.
332 // The Instance translates into Fvb instance. The Fvb order defined by HOBs and
333 // thus the sequence of FVB protocol addition define Instance.
335 // EfiFvbInitialize () must be called before any of the following functions
337 // =============================================================================
341 Reads specified number of bytes into a buffer from the specified block
343 @param Instance The FV instance to be read from.
344 @param Lba The logical block address to be read from
345 @param Offset Offset into the block at which to begin reading
346 @param NumBytes Pointer that on input contains the total size of
347 the buffer. On output, it contains the total number
349 @param Buffer Pointer to a caller allocated buffer that will be
350 used to hold the data read
352 @retval EFI_INVALID_PARAMETER Invalid parameter
353 @retval EFI_SUCESS Sucess to Read block
354 @retval Others Fail to read block
361 IN OUT UINTN
*NumBytes
,
365 if (Instance
>= mFvbCount
) {
366 return EFI_INVALID_PARAMETER
;
369 if (EfiAtRuntime() && !mFvbEntry
[Instance
].IsRuntimeAccess
) {
370 return EFI_INVALID_PARAMETER
;
373 return mFvbEntry
[Instance
].Fvb
->Read (mFvbEntry
[Instance
].Fvb
, Lba
, Offset
, NumBytes
, Buffer
);
377 Writes specified number of bytes from the input buffer to the block
379 @param Instance The FV instance to be written to
380 @param Lba The starting logical block index to write to
381 @param Offset Offset into the block at which to begin writing
382 @param NumBytes Pointer that on input contains the total size of
383 the buffer. On output, it contains the total number
384 of bytes actually written
385 @param Buffer Pointer to a caller allocated buffer that contains
386 the source for the write
388 @retval EFI_INVALID_PARAMETER Invalid parameter
389 @retval EFI_SUCESS Sucess to write block
390 @retval Others Fail to write block
397 IN OUT UINTN
*NumBytes
,
401 if (Instance
>= mFvbCount
) {
402 return EFI_INVALID_PARAMETER
;
405 if (EfiAtRuntime() && !mFvbEntry
[Instance
].IsRuntimeAccess
) {
406 return EFI_INVALID_PARAMETER
;
409 return mFvbEntry
[Instance
].Fvb
->Write (mFvbEntry
[Instance
].Fvb
, Lba
, Offset
, NumBytes
, Buffer
);
413 Erases and initializes a firmware volume block
415 @param Instance The FV instance to be erased
416 @param Lba The logical block index to be erased
418 @retval EFI_INVALID_PARAMETER Invalid parameter
419 @retval EFI_SUCESS Sucess to erase block
420 @retval Others Fail to erase block
428 if (Instance
>= mFvbCount
) {
429 return EFI_INVALID_PARAMETER
;
432 if (EfiAtRuntime() && !mFvbEntry
[Instance
].IsRuntimeAccess
) {
433 return EFI_INVALID_PARAMETER
;
436 return mFvbEntry
[Instance
].Fvb
->EraseBlocks (mFvbEntry
[Instance
].Fvb
, Lba
, -1);
440 Retrieves attributes, insures positive polarity of attribute bits, returns
441 resulting attributes in output parameter
443 @param Instance The FV instance whose attributes is going to be returned
444 @param Attributes Output buffer which contains attributes
446 @retval EFI_INVALID_PARAMETER Invalid parameter
447 @retval EFI_SUCESS Sucess to get Fv attribute
448 @retval Others Fail to get Fv attribute
451 EfiFvbGetVolumeAttributes (
453 OUT EFI_FVB_ATTRIBUTES
*Attributes
456 if (Instance
>= mFvbCount
) {
457 return EFI_INVALID_PARAMETER
;
460 if (EfiAtRuntime() && !mFvbEntry
[Instance
].IsRuntimeAccess
) {
461 return EFI_INVALID_PARAMETER
;
464 return mFvbEntry
[Instance
].Fvb
->GetVolumeAttributes (mFvbEntry
[Instance
].Fvb
, Attributes
);
468 Modifies the current settings of the firmware volume according to the
469 input parameter, and returns the new setting of the volume
471 @param Instance The FV instance whose attributes is going to be
473 @param Attributes On input, it is a pointer to EFI_FVB_ATTRIBUTES
474 containing the desired firmware volume settings.
475 On successful return, it contains the new settings
476 of the firmware volume
478 @retval EFI_INVALID_PARAMETER Invalid parameter
479 @retval EFI_SUCESS Sucess to set Fv attribute
480 @retval Others Fail to set Fv attribute
483 EfiFvbSetVolumeAttributes (
485 IN EFI_FVB_ATTRIBUTES Attributes
488 if (Instance
>= mFvbCount
) {
489 return EFI_INVALID_PARAMETER
;
492 if (EfiAtRuntime() && !mFvbEntry
[Instance
].IsRuntimeAccess
) {
493 return EFI_INVALID_PARAMETER
;
496 return mFvbEntry
[Instance
].Fvb
->SetVolumeAttributes (mFvbEntry
[Instance
].Fvb
, &Attributes
);
500 Retrieves the physical address of a memory mapped FV
502 @param Instance The FV instance whose base address is going to be
504 @param BaseAddress Pointer to a caller allocated EFI_PHYSICAL_ADDRESS
505 that on successful return, contains the base address
506 of the firmware volume.
508 @retval EFI_INVALID_PARAMETER Invalid parameter
509 @retval EFI_SUCESS Sucess to get physical address
510 @retval Others Fail to get physical address
513 EfiFvbGetPhysicalAddress (
515 OUT EFI_PHYSICAL_ADDRESS
*BaseAddress
518 if (Instance
>= mFvbCount
) {
519 return EFI_INVALID_PARAMETER
;
522 if (EfiAtRuntime() && !mFvbEntry
[Instance
].IsRuntimeAccess
) {
523 return EFI_INVALID_PARAMETER
;
526 return mFvbEntry
[Instance
].Fvb
->GetPhysicalAddress (mFvbEntry
[Instance
].Fvb
, BaseAddress
);
530 Retrieve the size of a logical block
532 @param Instance The FV instance whose block size is going to be
534 @param Lba Indicates which block to return the size for.
535 @param BlockSize A pointer to a caller allocated UINTN in which
536 the size of the block is returned
537 @param NumOfBlocks a pointer to a caller allocated UINTN in which the
538 number of consecutive blocks starting with Lba is
539 returned. All blocks in this range have a size of
542 @retval EFI_INVALID_PARAMETER Invalid parameter
543 @retval EFI_SUCESS Sucess to get block size
544 @retval Others Fail to get block size
550 OUT UINTN
*BlockSize
,
551 OUT UINTN
*NumOfBlocks
554 if (Instance
>= mFvbCount
) {
555 return EFI_INVALID_PARAMETER
;
558 if (EfiAtRuntime() && !mFvbEntry
[Instance
].IsRuntimeAccess
) {
559 return EFI_INVALID_PARAMETER
;
562 return mFvbEntry
[Instance
].Fvb
->GetBlockSize (mFvbEntry
[Instance
].Fvb
, Lba
, BlockSize
, NumOfBlocks
);
566 Erases and initializes a specified range of a firmware volume
568 @param Instance The FV instance to be erased
569 @param StartLba The starting logical block index to be erased
570 @param OffsetStartLba Offset into the starting block at which to
572 @param LastLba The last logical block index to be erased
573 @param OffsetLastLba Offset into the last block at which to end erasing
575 @retval EFI_INVALID_PARAMETER Invalid parameter
576 @retval EFI_SUCESS Sucess to erase custom block range
577 @retval Others Fail to erase custom block range
580 EfiFvbEraseCustomBlockRange (
583 IN UINTN OffsetStartLba
,
585 IN UINTN OffsetLastLba
588 if (Instance
>= mFvbCount
) {
589 return EFI_INVALID_PARAMETER
;
592 if (EfiAtRuntime() && !mFvbEntry
[Instance
].IsRuntimeAccess
) {
593 return EFI_INVALID_PARAMETER
;
596 if (!(mFvbEntry
[Instance
].FvbExtension
)) {
597 return EFI_UNSUPPORTED
;
600 if (!(mFvbEntry
[Instance
].FvbExtension
->EraseFvbCustomBlock
)) {
601 return EFI_UNSUPPORTED
;
604 return mFvbEntry
[Instance
].FvbExtension
->EraseFvbCustomBlock (
605 mFvbEntry
[Instance
].FvbExtension
,