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.
24 // Include common header file for this module.
26 #include "CommonHeader.h"
31 // Event for Exit Boot Services Callback
33 STATIC EFI_EVENT mExitBootServicesEvent
= NULL
;
36 // Lib will ASSERT if more FVB devices than this are added to the system.
38 STATIC FVB_ENTRY
*mFvbEntry
;
39 STATIC EFI_EVENT mFvbRegistration
;
40 STATIC BOOLEAN mEfiFvbInitialized
= FALSE
;
41 STATIC UINTN mFvbCount
;
44 Check whether an address is runtime memory or not.
46 @param Address The Address being checked.
48 @retval TRUE The address is runtime memory.
49 @retval FALSE The address is not runtime memory.
57 UINT8 TmpMemoryMap
[1];
60 UINT32 DescriptorVersion
;
62 EFI_MEMORY_DESCRIPTOR
*MemoryMap
;
63 EFI_MEMORY_DESCRIPTOR
*MemoryMapPtr
;
70 // Get System MemoryMapSize
73 Status
= gBS
->GetMemoryMap (
75 (EFI_MEMORY_DESCRIPTOR
*)TmpMemoryMap
,
80 ASSERT (Status
== EFI_BUFFER_TOO_SMALL
);
82 // Enlarge space here, because we will allocate pool now.
84 MemoryMapSize
+= EFI_PAGE_SIZE
;
85 Status
= gBS
->AllocatePool (
90 ASSERT_EFI_ERROR (Status
);
93 // Get System MemoryMap
95 Status
= gBS
->GetMemoryMap (
102 ASSERT_EFI_ERROR (Status
);
104 MemoryMapPtr
= MemoryMap
;
106 // Search the request Address
108 for (Index
= 0; Index
< (MemoryMapSize
/ DescriptorSize
); Index
++) {
109 if (((EFI_PHYSICAL_ADDRESS
)(UINTN
)Address
>= MemoryMap
->PhysicalStart
) &&
110 ((EFI_PHYSICAL_ADDRESS
)(UINTN
)Address
< MemoryMap
->PhysicalStart
111 + LShiftU64 (MemoryMap
->NumberOfPages
, EFI_PAGE_SHIFT
))) {
115 if (MemoryMap
->Attribute
& EFI_MEMORY_RUNTIME
) {
123 MemoryMap
= (EFI_MEMORY_DESCRIPTOR
*)((UINTN
)MemoryMap
+ DescriptorSize
);
129 gBS
->FreePool (MemoryMapPtr
);
135 Update mFvbEntry. Add new entry, or update existing entry if Fvb protocol is
138 @param Event The Event that is being processed
139 @param Context Event Context
145 FvbNotificationEvent (
157 BufferSize
= sizeof (Handle
);
158 Status
= gBS
->LocateHandle (
160 &gEfiFirmwareVolumeBlockProtocolGuid
,
165 if (EFI_ERROR (Status
)) {
167 // Exit Path of While Loop....
172 UpdateIndex
= MAX_FVB_COUNT
;
173 for (Index
= 0; Index
< mFvbCount
; Index
++) {
174 if (mFvbEntry
[Index
].Handle
== Handle
) {
176 // If the handle is already in the table just update the protocol
183 if (UpdateIndex
== MAX_FVB_COUNT
) {
185 // Use the next free slot for a new entry
187 UpdateIndex
= mFvbCount
++;
189 // Check the UpdateIndex whether exceed the maximum value.
191 ASSERT (UpdateIndex
< MAX_FVB_COUNT
);
192 mFvbEntry
[UpdateIndex
].Handle
= Handle
;
195 // The array does not have enough entries
197 ASSERT (UpdateIndex
< MAX_FVB_COUNT
);
200 // Get the interface pointer and if it's ours, skip it
202 Status
= gBS
->HandleProtocol (
204 &gEfiFirmwareVolumeBlockProtocolGuid
,
205 (VOID
**) &mFvbEntry
[UpdateIndex
].Fvb
207 ASSERT_EFI_ERROR (Status
);
209 Status
= gBS
->HandleProtocol (
211 &gEfiFvbExtensionProtocolGuid
,
212 (VOID
**) &mFvbEntry
[UpdateIndex
].FvbExtension
214 if (Status
!= EFI_SUCCESS
) {
215 mFvbEntry
[UpdateIndex
].FvbExtension
= NULL
;
219 // Check the FVB can be accessed in RUNTIME, The FVBs in FVB handle list comes
221 // 1) Dxe Core. (FVB information is transferred from FV HOB).
223 // The FVB produced Dxe core is used for discoverying DXE driver and dispatch. These
224 // FVBs can only be accessed in boot time.
225 // FVB driver will discovery all FV in FLASH and these FVBs can be accessed in runtime.
226 // The FVB itself produced by FVB driver is allocated in runtime memory. So we can
227 // determine the what FVB can be accessed in RUNTIME by judging whether FVB itself is allocated
228 // in RUNTIME memory.
230 mFvbEntry
[UpdateIndex
].IsRuntimeAccess
= IsRuntimeMemory (mFvbEntry
[UpdateIndex
].Fvb
);
235 Convert all pointers in mFvbEntry after ExitBootServices.
237 @param Event The Event that is being processed
238 @param Context Event Context
243 FvbVirtualAddressChangeNotifyEvent (
249 if (mFvbEntry
!= NULL
) {
250 for (Index
= 0; Index
< MAX_FVB_COUNT
; Index
++) {
251 if (!mFvbEntry
[Index
].IsRuntimeAccess
) {
255 if (NULL
!= mFvbEntry
[Index
].Fvb
) {
256 EfiConvertPointer (0x0, (VOID
**) &mFvbEntry
[Index
].Fvb
->GetBlockSize
);
257 EfiConvertPointer (0x0, (VOID
**) &mFvbEntry
[Index
].Fvb
->GetPhysicalAddress
);
258 EfiConvertPointer (0x0, (VOID
**) &mFvbEntry
[Index
].Fvb
->GetVolumeAttributes
);
259 EfiConvertPointer (0x0, (VOID
**) &mFvbEntry
[Index
].Fvb
->SetVolumeAttributes
);
260 EfiConvertPointer (0x0, (VOID
**) &mFvbEntry
[Index
].Fvb
->Read
);
261 EfiConvertPointer (0x0, (VOID
**) &mFvbEntry
[Index
].Fvb
->Write
);
262 EfiConvertPointer (0x0, (VOID
**) &mFvbEntry
[Index
].Fvb
->EraseBlocks
);
263 EfiConvertPointer (0x0, (VOID
**) &mFvbEntry
[Index
].Fvb
);
266 if (NULL
!= mFvbEntry
[Index
].FvbExtension
) {
267 EfiConvertPointer (0x0, (VOID
**) &mFvbEntry
[Index
].FvbExtension
->EraseFvbCustomBlock
);
268 EfiConvertPointer (0x0, (VOID
**) &mFvbEntry
[Index
].FvbExtension
);
272 EfiConvertPointer (0x0, (VOID
**) &mFvbEntry
);
277 Library constructor function entry.
279 @param ImageHandle The handle of image who call this libary.
280 @param SystemTable The point of System Table.
282 @retval EFI_SUCESS Sucess construct this library.
283 @retval Others Fail to contruct this libary.
288 IN EFI_HANDLE ImageHandle
,
289 IN EFI_SYSTEM_TABLE
*SystemTable
295 Status
= gBS
->AllocatePool (
296 EfiRuntimeServicesData
,
297 (UINTN
) sizeof (FVB_ENTRY
) * MAX_FVB_COUNT
,
301 if (EFI_ERROR (Status
)) {
305 ZeroMem (mFvbEntry
, sizeof (FVB_ENTRY
) * MAX_FVB_COUNT
);
307 EfiCreateProtocolNotifyEvent (
308 &gEfiFirmwareVolumeBlockProtocolGuid
,
310 FvbNotificationEvent
,
316 // Register SetVirtualAddressMap () notify function
318 Status
= gBS
->CreateEvent (
319 EVT_SIGNAL_EXIT_BOOT_SERVICES
,
321 FvbVirtualAddressChangeNotifyEvent
,
323 &mExitBootServicesEvent
325 ASSERT_EFI_ERROR (Status
);
327 mEfiFvbInitialized
= TRUE
;
333 // =============================================================================
334 // The following functions wrap Fvb protocol in the Runtime Lib functions.
335 // The Instance translates into Fvb instance. The Fvb order defined by HOBs and
336 // thus the sequence of FVB protocol addition define Instance.
338 // EfiFvbInitialize () must be called before any of the following functions
340 // =============================================================================
344 Reads specified number of bytes into a buffer from the specified block
346 @param Instance The FV instance to be read from.
347 @param Lba The logical block address to be read from
348 @param Offset Offset into the block at which to begin reading
349 @param NumBytes Pointer that on input contains the total size of
350 the buffer. On output, it contains the total number
352 @param Buffer Pointer to a caller allocated buffer that will be
353 used to hold the data read
355 @retval EFI_INVALID_PARAMETER Invalid parameter
356 @retval EFI_SUCESS Sucess to Read block
357 @retval Others Fail to read block
364 IN OUT UINTN
*NumBytes
,
368 if (Instance
>= mFvbCount
) {
369 return EFI_INVALID_PARAMETER
;
372 if (EfiAtRuntime() && !mFvbEntry
[Instance
].IsRuntimeAccess
) {
373 return EFI_INVALID_PARAMETER
;
376 return mFvbEntry
[Instance
].Fvb
->Read (mFvbEntry
[Instance
].Fvb
, Lba
, Offset
, NumBytes
, Buffer
);
380 Writes specified number of bytes from the input buffer to the block
382 @param Instance The FV instance to be written to
383 @param Lba The starting logical block index to write to
384 @param Offset Offset into the block at which to begin writing
385 @param NumBytes Pointer that on input contains the total size of
386 the buffer. On output, it contains the total number
387 of bytes actually written
388 @param Buffer Pointer to a caller allocated buffer that contains
389 the source for the write
391 @retval EFI_INVALID_PARAMETER Invalid parameter
392 @retval EFI_SUCESS Sucess to write block
393 @retval Others Fail to write block
400 IN OUT UINTN
*NumBytes
,
404 if (Instance
>= mFvbCount
) {
405 return EFI_INVALID_PARAMETER
;
408 if (EfiAtRuntime() && !mFvbEntry
[Instance
].IsRuntimeAccess
) {
409 return EFI_INVALID_PARAMETER
;
412 return mFvbEntry
[Instance
].Fvb
->Write (mFvbEntry
[Instance
].Fvb
, Lba
, Offset
, NumBytes
, Buffer
);
416 Erases and initializes a firmware volume block
418 @param Instance The FV instance to be erased
419 @param Lba The logical block index to be erased
421 @retval EFI_INVALID_PARAMETER Invalid parameter
422 @retval EFI_SUCESS Sucess to erase block
423 @retval Others Fail to erase block
431 if (Instance
>= mFvbCount
) {
432 return EFI_INVALID_PARAMETER
;
435 if (EfiAtRuntime() && !mFvbEntry
[Instance
].IsRuntimeAccess
) {
436 return EFI_INVALID_PARAMETER
;
439 return mFvbEntry
[Instance
].Fvb
->EraseBlocks (mFvbEntry
[Instance
].Fvb
, Lba
, -1);
443 Retrieves attributes, insures positive polarity of attribute bits, returns
444 resulting attributes in output parameter
446 @param Instance The FV instance whose attributes is going to be returned
447 @param Attributes Output buffer which contains attributes
449 @retval EFI_INVALID_PARAMETER Invalid parameter
450 @retval EFI_SUCESS Sucess to get Fv attribute
451 @retval Others Fail to get Fv attribute
454 EfiFvbGetVolumeAttributes (
456 OUT EFI_FVB_ATTRIBUTES
*Attributes
459 if (Instance
>= mFvbCount
) {
460 return EFI_INVALID_PARAMETER
;
463 if (EfiAtRuntime() && !mFvbEntry
[Instance
].IsRuntimeAccess
) {
464 return EFI_INVALID_PARAMETER
;
467 return mFvbEntry
[Instance
].Fvb
->GetVolumeAttributes (mFvbEntry
[Instance
].Fvb
, Attributes
);
471 Modifies the current settings of the firmware volume according to the
472 input parameter, and returns the new setting of the volume
474 @param Instance The FV instance whose attributes is going to be
476 @param Attributes On input, it is a pointer to EFI_FVB_ATTRIBUTES
477 containing the desired firmware volume settings.
478 On successful return, it contains the new settings
479 of the firmware volume
481 @retval EFI_INVALID_PARAMETER Invalid parameter
482 @retval EFI_SUCESS Sucess to set Fv attribute
483 @retval Others Fail to set Fv attribute
486 EfiFvbSetVolumeAttributes (
488 IN EFI_FVB_ATTRIBUTES Attributes
491 if (Instance
>= mFvbCount
) {
492 return EFI_INVALID_PARAMETER
;
495 if (EfiAtRuntime() && !mFvbEntry
[Instance
].IsRuntimeAccess
) {
496 return EFI_INVALID_PARAMETER
;
499 return mFvbEntry
[Instance
].Fvb
->SetVolumeAttributes (mFvbEntry
[Instance
].Fvb
, &Attributes
);
503 Retrieves the physical address of a memory mapped FV
505 @param Instance The FV instance whose base address is going to be
507 @param BaseAddress Pointer to a caller allocated EFI_PHYSICAL_ADDRESS
508 that on successful return, contains the base address
509 of the firmware volume.
511 @retval EFI_INVALID_PARAMETER Invalid parameter
512 @retval EFI_SUCESS Sucess to get physical address
513 @retval Others Fail to get physical address
516 EfiFvbGetPhysicalAddress (
518 OUT EFI_PHYSICAL_ADDRESS
*BaseAddress
521 if (Instance
>= mFvbCount
) {
522 return EFI_INVALID_PARAMETER
;
525 if (EfiAtRuntime() && !mFvbEntry
[Instance
].IsRuntimeAccess
) {
526 return EFI_INVALID_PARAMETER
;
529 return mFvbEntry
[Instance
].Fvb
->GetPhysicalAddress (mFvbEntry
[Instance
].Fvb
, BaseAddress
);
533 Retrieve the size of a logical block
535 @param Instance The FV instance whose block size is going to be
537 @param Lba Indicates which block to return the size for.
538 @param BlockSize A pointer to a caller allocated UINTN in which
539 the size of the block is returned
540 @param NumOfBlocks a pointer to a caller allocated UINTN in which the
541 number of consecutive blocks starting with Lba is
542 returned. All blocks in this range have a size of
545 @retval EFI_INVALID_PARAMETER Invalid parameter
546 @retval EFI_SUCESS Sucess to get block size
547 @retval Others Fail to get block size
553 OUT UINTN
*BlockSize
,
554 OUT UINTN
*NumOfBlocks
557 if (Instance
>= mFvbCount
) {
558 return EFI_INVALID_PARAMETER
;
561 if (EfiAtRuntime() && !mFvbEntry
[Instance
].IsRuntimeAccess
) {
562 return EFI_INVALID_PARAMETER
;
565 return mFvbEntry
[Instance
].Fvb
->GetBlockSize (mFvbEntry
[Instance
].Fvb
, Lba
, BlockSize
, NumOfBlocks
);
569 Erases and initializes a specified range of a firmware volume
571 @param Instance The FV instance to be erased
572 @param StartLba The starting logical block index to be erased
573 @param OffsetStartLba Offset into the starting block at which to
575 @param LastLba The last logical block index to be erased
576 @param OffsetLastLba Offset into the last block at which to end erasing
578 @retval EFI_INVALID_PARAMETER Invalid parameter
579 @retval EFI_SUCESS Sucess to erase custom block range
580 @retval Others Fail to erase custom block range
583 EfiFvbEraseCustomBlockRange (
586 IN UINTN OffsetStartLba
,
588 IN UINTN OffsetLastLba
591 if (Instance
>= mFvbCount
) {
592 return EFI_INVALID_PARAMETER
;
595 if (EfiAtRuntime() && !mFvbEntry
[Instance
].IsRuntimeAccess
) {
596 return EFI_INVALID_PARAMETER
;
599 if (!(mFvbEntry
[Instance
].FvbExtension
)) {
600 return EFI_UNSUPPORTED
;
603 if (!(mFvbEntry
[Instance
].FvbExtension
->EraseFvbCustomBlock
)) {
604 return EFI_UNSUPPORTED
;
607 return mFvbEntry
[Instance
].FvbExtension
->EraseFvbCustomBlock (
608 mFvbEntry
[Instance
].FvbExtension
,