TianoCore EDK2 master
Loading...
Searching...
No Matches
FwVolBlock.c
Go to the documentation of this file.
1
12#include "DxeMain.h"
13#include "FwVolBlock.h"
14
15FV_MEMMAP_DEVICE_PATH mFvMemmapDevicePathTemplate = {
16 {
17 {
20 {
21 (UINT8)(sizeof (MEMMAP_DEVICE_PATH)),
22 (UINT8)(sizeof (MEMMAP_DEVICE_PATH) >> 8)
23 }
24 },
28 },
29 {
30 END_DEVICE_PATH_TYPE,
31 END_ENTIRE_DEVICE_PATH_SUBTYPE,
32 {
33 END_DEVICE_PATH_LENGTH,
34 0
35 }
36 }
37};
38
39FV_PIWG_DEVICE_PATH mFvPIWGDevicePathTemplate = {
40 {
41 {
42 MEDIA_DEVICE_PATH,
44 {
45 (UINT8)(sizeof (MEDIA_FW_VOL_DEVICE_PATH)),
46 (UINT8)(sizeof (MEDIA_FW_VOL_DEVICE_PATH) >> 8)
47 }
48 },
49 { 0 }
50 },
51 {
52 END_DEVICE_PATH_TYPE,
53 END_ENTIRE_DEVICE_PATH_SUBTYPE,
54 {
55 END_DEVICE_PATH_LENGTH,
56 0
57 }
58 }
59};
60
61EFI_FW_VOL_BLOCK_DEVICE mFwVolBlock = {
62 FVB_DEVICE_SIGNATURE,
63 NULL,
64 NULL,
65 {
73 NULL
74 },
75 0,
76 NULL,
77 0,
78 0,
79 0
80};
81
92EFIAPI
95 OUT EFI_FVB_ATTRIBUTES_2 *Attributes
96 )
97{
98 EFI_FW_VOL_BLOCK_DEVICE *FvbDevice;
99
100 FvbDevice = FVB_DEVICE_FROM_THIS (This);
101
102 //
103 // Since we are read only, it's safe to get attributes data from our in-memory copy.
104 //
105 *Attributes = FvbDevice->FvbAttributes & ~EFI_FVB2_WRITE_STATUS;
106
107 return EFI_SUCCESS;
108}
109
124EFIAPI
127 IN CONST EFI_FVB_ATTRIBUTES_2 *Attributes
128 )
129{
130 return EFI_UNSUPPORTED;
131}
132
157EFIAPI
160 ...
161 )
162{
163 return EFI_UNSUPPORTED;
164}
165
187EFIAPI
190 IN CONST EFI_LBA Lba,
191 IN CONST UINTN Offset,
192 IN OUT UINTN *NumBytes,
193 IN OUT UINT8 *Buffer
194 )
195{
196 EFI_FW_VOL_BLOCK_DEVICE *FvbDevice;
197 EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;
198 UINT8 *LbaOffset;
199 UINTN LbaStart;
200 UINTN NumOfBytesRead;
201 UINTN LbaIndex;
202
203 FvbDevice = FVB_DEVICE_FROM_THIS (This);
204
205 //
206 // Check if This FW can be read
207 //
208 if ((FvbDevice->FvbAttributes & EFI_FVB2_READ_STATUS) == 0) {
209 return EFI_ACCESS_DENIED;
210 }
211
212 LbaIndex = (UINTN)Lba;
213 if (LbaIndex >= FvbDevice->NumBlocks) {
214 //
215 // Invalid Lba, read nothing.
216 //
217 *NumBytes = 0;
218 return EFI_BAD_BUFFER_SIZE;
219 }
220
221 if (Offset > FvbDevice->LbaCache[LbaIndex].Length) {
222 //
223 // all exceed boundary, read nothing.
224 //
225 *NumBytes = 0;
226 return EFI_BAD_BUFFER_SIZE;
227 }
228
229 NumOfBytesRead = *NumBytes;
230 if (Offset + NumOfBytesRead > FvbDevice->LbaCache[LbaIndex].Length) {
231 //
232 // partial exceed boundary, read data from current postion to end.
233 //
234 NumOfBytesRead = FvbDevice->LbaCache[LbaIndex].Length - Offset;
235 }
236
237 LbaStart = FvbDevice->LbaCache[LbaIndex].Base;
238 FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *)((UINTN)FvbDevice->BaseAddress);
239 LbaOffset = (UINT8 *)FwVolHeader + LbaStart + Offset;
240
241 //
242 // Perform read operation
243 //
244 CopyMem (Buffer, LbaOffset, NumOfBytesRead);
245
246 if (NumOfBytesRead == *NumBytes) {
247 return EFI_SUCCESS;
248 }
249
250 *NumBytes = NumOfBytesRead;
251 return EFI_BAD_BUFFER_SIZE;
252}
253
279EFIAPI
282 IN EFI_LBA Lba,
283 IN UINTN Offset,
284 IN OUT UINTN *NumBytes,
285 IN UINT8 *Buffer
286 )
287{
288 return EFI_UNSUPPORTED;
289}
290
302EFIAPI
306 )
307{
308 EFI_FW_VOL_BLOCK_DEVICE *FvbDevice;
309
310 FvbDevice = FVB_DEVICE_FROM_THIS (This);
311
312 if ((FvbDevice->FvbAttributes & EFI_FVB2_MEMORY_MAPPED) != 0) {
313 *Address = FvbDevice->BaseAddress;
314 return EFI_SUCCESS;
315 }
316
317 return EFI_UNSUPPORTED;
318}
319
338EFIAPI
341 IN CONST EFI_LBA Lba,
342 IN OUT UINTN *BlockSize,
343 IN OUT UINTN *NumberOfBlocks
344 )
345{
346 UINTN TotalBlocks;
347 EFI_FW_VOL_BLOCK_DEVICE *FvbDevice;
348 EFI_FV_BLOCK_MAP_ENTRY *PtrBlockMapEntry;
349 EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;
350
351 FvbDevice = FVB_DEVICE_FROM_THIS (This);
352
353 //
354 // Do parameter checking
355 //
356 if (Lba >= FvbDevice->NumBlocks) {
357 return EFI_INVALID_PARAMETER;
358 }
359
360 FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *)((UINTN)FvbDevice->BaseAddress);
361
362 PtrBlockMapEntry = FwVolHeader->BlockMap;
363
364 //
365 // Search the block map for the given block
366 //
367 TotalBlocks = 0;
368 while ((PtrBlockMapEntry->NumBlocks != 0) || (PtrBlockMapEntry->Length != 0)) {
369 TotalBlocks += PtrBlockMapEntry->NumBlocks;
370 if (Lba < TotalBlocks) {
371 //
372 // We find the range
373 //
374 break;
375 }
376
377 PtrBlockMapEntry++;
378 }
379
380 *BlockSize = PtrBlockMapEntry->Length;
381 *NumberOfBlocks = TotalBlocks - (UINTN)Lba;
382
383 return EFI_SUCCESS;
384}
385
395UINT32
398 )
399{
400 EFI_FW_VOL_BLOCK_DEVICE *FvbDevice;
401 UINT32 AuthenticationStatus;
402
403 AuthenticationStatus = 0;
404 FvbDevice = BASE_CR (FvbProtocol, EFI_FW_VOL_BLOCK_DEVICE, FwVolBlockInstance);
405 if (FvbDevice->Signature == FVB_DEVICE_SIGNATURE) {
406 AuthenticationStatus = FvbDevice->AuthenticationStatus;
407 }
408
409 return AuthenticationStatus;
410}
411
433 IN EFI_PHYSICAL_ADDRESS BaseAddress,
434 IN UINT64 Length,
435 IN EFI_HANDLE ParentHandle,
436 IN UINT32 AuthenticationStatus,
437 OUT EFI_HANDLE *FvProtocol OPTIONAL
438 )
439{
440 EFI_STATUS Status;
442 EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;
443 UINTN BlockIndex;
444 UINTN BlockIndex2;
445 UINTN LinearOffset;
446 UINT32 FvAlignment;
447 EFI_FV_BLOCK_MAP_ENTRY *PtrBlockMapEntry;
448
449 FvAlignment = 0;
450 FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)BaseAddress;
451 //
452 // Validate FV Header, if not as expected, return
453 //
454 if (FwVolHeader->Signature != EFI_FVH_SIGNATURE) {
455 return EFI_VOLUME_CORRUPTED;
456 }
457
458 //
459 // If EFI_FVB2_WEAK_ALIGNMENT is set in the volume header then the first byte of the volume
460 // can be aligned on any power-of-two boundary. A weakly aligned volume can not be moved from
461 // its initial linked location and maintain its alignment.
462 //
463 if ((FwVolHeader->Attributes & EFI_FVB2_WEAK_ALIGNMENT) != EFI_FVB2_WEAK_ALIGNMENT) {
464 //
465 // Get FvHeader alignment
466 //
467 FvAlignment = 1 << ((FwVolHeader->Attributes & EFI_FVB2_ALIGNMENT) >> 16);
468 //
469 // FvAlignment must be greater than or equal to 8 bytes of the minimum FFS alignment value.
470 //
471 if (FvAlignment < 8) {
472 FvAlignment = 8;
473 }
474
475 if ((UINTN)BaseAddress % FvAlignment != 0) {
476 //
477 // FvImage buffer is not at its required alignment.
478 //
479 DEBUG ((
480 DEBUG_ERROR,
481 "Unaligned FvImage found at 0x%lx:0x%lx, the required alignment is 0x%x\n",
482 BaseAddress,
483 Length,
484 FvAlignment
485 ));
486 return EFI_VOLUME_CORRUPTED;
487 }
488 }
489
490 //
491 // Allocate EFI_FW_VOL_BLOCK_DEVICE
492 //
493 FvbDev = AllocateCopyPool (sizeof (EFI_FW_VOL_BLOCK_DEVICE), &mFwVolBlock);
494 if (FvbDev == NULL) {
495 return EFI_OUT_OF_RESOURCES;
496 }
497
498 FvbDev->BaseAddress = BaseAddress;
499 FvbDev->FvbAttributes = FwVolHeader->Attributes;
500 FvbDev->FwVolBlockInstance.ParentHandle = ParentHandle;
501 FvbDev->AuthenticationStatus = AuthenticationStatus;
502
503 //
504 // Init the block caching fields of the device
505 // First, count the number of blocks
506 //
507 FvbDev->NumBlocks = 0;
508 for (PtrBlockMapEntry = FwVolHeader->BlockMap;
509 PtrBlockMapEntry->NumBlocks != 0;
510 PtrBlockMapEntry++)
511 {
512 FvbDev->NumBlocks += PtrBlockMapEntry->NumBlocks;
513 }
514
515 //
516 // Second, allocate the cache
517 //
518 if (FvbDev->NumBlocks >= (MAX_ADDRESS / sizeof (LBA_CACHE))) {
519 CoreFreePool (FvbDev);
520 return EFI_OUT_OF_RESOURCES;
521 }
522
523 FvbDev->LbaCache = AllocatePool (FvbDev->NumBlocks * sizeof (LBA_CACHE));
524 if (FvbDev->LbaCache == NULL) {
525 CoreFreePool (FvbDev);
526 return EFI_OUT_OF_RESOURCES;
527 }
528
529 //
530 // Last, fill in the cache with the linear address of the blocks
531 //
532 BlockIndex = 0;
533 LinearOffset = 0;
534 for (PtrBlockMapEntry = FwVolHeader->BlockMap;
535 PtrBlockMapEntry->NumBlocks != 0; PtrBlockMapEntry++)
536 {
537 for (BlockIndex2 = 0; BlockIndex2 < PtrBlockMapEntry->NumBlocks; BlockIndex2++) {
538 FvbDev->LbaCache[BlockIndex].Base = LinearOffset;
539 FvbDev->LbaCache[BlockIndex].Length = PtrBlockMapEntry->Length;
540 LinearOffset += PtrBlockMapEntry->Length;
541 BlockIndex++;
542 }
543 }
544
545 //
546 // Judget whether FV name guid is produced in Fv extension header
547 //
548 if (FwVolHeader->ExtHeaderOffset == 0) {
549 //
550 // FV does not contains extension header, then produce MEMMAP_DEVICE_PATH
551 //
552 FvbDev->DevicePath = (EFI_DEVICE_PATH_PROTOCOL *)AllocateCopyPool (sizeof (FV_MEMMAP_DEVICE_PATH), &mFvMemmapDevicePathTemplate);
553 if (FvbDev->DevicePath == NULL) {
554 FreePool (FvbDev->LbaCache);
555 FreePool (FvbDev);
556 return EFI_OUT_OF_RESOURCES;
557 }
558
559 ((FV_MEMMAP_DEVICE_PATH *)FvbDev->DevicePath)->MemMapDevPath.StartingAddress = BaseAddress;
560 ((FV_MEMMAP_DEVICE_PATH *)FvbDev->DevicePath)->MemMapDevPath.EndingAddress = BaseAddress + FwVolHeader->FvLength - 1;
561 } else {
562 //
563 // FV contains extension header, then produce MEDIA_FW_VOL_DEVICE_PATH
564 //
565 FvbDev->DevicePath = (EFI_DEVICE_PATH_PROTOCOL *)AllocateCopyPool (sizeof (FV_PIWG_DEVICE_PATH), &mFvPIWGDevicePathTemplate);
566 if (FvbDev->DevicePath == NULL) {
567 FreePool (FvbDev->LbaCache);
568 FreePool (FvbDev);
569 return EFI_OUT_OF_RESOURCES;
570 }
571
572 CopyGuid (
573 &((FV_PIWG_DEVICE_PATH *)FvbDev->DevicePath)->FvDevPath.FvName,
574 (GUID *)(UINTN)(BaseAddress + FwVolHeader->ExtHeaderOffset)
575 );
576 }
577
578 //
579 //
580 // Attach FvVolBlock Protocol to new handle
581 //
583 &FvbDev->Handle,
584 &gEfiFirmwareVolumeBlockProtocolGuid,
585 &FvbDev->FwVolBlockInstance,
586 &gEfiDevicePathProtocolGuid,
587 FvbDev->DevicePath,
588 NULL
589 );
590
591 //
592 // If they want the handle back, set it.
593 //
594 if (FvProtocol != NULL) {
595 *FvProtocol = FvbDev->Handle;
596 }
597
598 return Status;
599}
600
612EFIAPI
614 IN EFI_HANDLE ImageHandle,
615 IN EFI_SYSTEM_TABLE *SystemTable
616 )
617{
620 UINT32 AuthenticationStatus;
621
622 //
623 // Core Needs Firmware Volumes to function
624 //
625 FvHob.Raw = GetHobList ();
626 while ((FvHob.Raw = GetNextHob (EFI_HOB_TYPE_FV, FvHob.Raw)) != NULL) {
627 AuthenticationStatus = 0;
628 //
629 // Get the authentication status propagated from PEI-phase to DXE.
630 //
631 Fv3Hob.Raw = GetHobList ();
632 while ((Fv3Hob.Raw = GetNextHob (EFI_HOB_TYPE_FV3, Fv3Hob.Raw)) != NULL) {
633 if ((Fv3Hob.FirmwareVolume3->BaseAddress == FvHob.FirmwareVolume->BaseAddress) &&
634 (Fv3Hob.FirmwareVolume3->Length == FvHob.FirmwareVolume->Length))
635 {
636 AuthenticationStatus = Fv3Hob.FirmwareVolume3->AuthenticationStatus;
637 break;
638 }
639
640 Fv3Hob.Raw = GET_NEXT_HOB (Fv3Hob);
641 }
642
643 //
644 // Produce an FVB protocol for it
645 //
646 ProduceFVBProtocolOnBuffer (FvHob.FirmwareVolume->BaseAddress, FvHob.FirmwareVolume->Length, NULL, AuthenticationStatus, NULL);
647 FvHob.Raw = GET_NEXT_HOB (FvHob);
648 }
649
650 return EFI_SUCCESS;
651}
652
675EFIAPI
677 IN VOID *FvHeader,
678 IN UINTN Size,
679 OUT EFI_HANDLE *FVProtocolHandle
680 )
681{
682 VOID *Ptr;
683 EFI_STATUS Status;
684
685 *FVProtocolHandle = NULL;
687 (EFI_PHYSICAL_ADDRESS)(UINTN)FvHeader,
688 (UINT64)Size,
689 NULL,
690 0,
691 FVProtocolHandle
692 );
693 //
694 // Since in our implementation we use register-protocol-notify to put a
695 // FV protocol on the FVB protocol handle, we can't directly verify that
696 // the FV protocol was produced. Therefore here we will check the handle
697 // and make sure an FV protocol is on it. This indicates that all went
698 // well. Otherwise we have to assume that the volume was corrupted
699 // somehow.
700 //
701 if (!EFI_ERROR (Status)) {
702 ASSERT (*FVProtocolHandle != NULL);
703 Ptr = NULL;
704 Status = CoreHandleProtocol (*FVProtocolHandle, &gEfiFirmwareVolume2ProtocolGuid, (VOID **)&Ptr);
705 if (EFI_ERROR (Status) || (Ptr == NULL)) {
706 return EFI_VOLUME_CORRUPTED;
707 }
708
709 return EFI_SUCCESS;
710 }
711
712 return Status;
713}
UINT64 UINTN
#define MAX_ADDRESS
VOID *EFIAPI GetNextHob(IN UINT16 Type, IN CONST VOID *HobStart)
Definition: HobLib.c:103
VOID *EFIAPI GetHobList(VOID)
Definition: HobLib.c:76
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
GUID *EFIAPI CopyGuid(OUT GUID *DestinationGuid, IN CONST GUID *SourceGuid)
Definition: MemLibGuid.c:39
#define HARDWARE_DEVICE_PATH
Definition: DevicePath.h:68
#define MEDIA_PIWG_FW_VOL_DP
Definition: DevicePath.h:1146
#define HW_MEMMAP_DP
Definition: DevicePath.h:109
EFI_STATUS EFIAPI CoreHandleProtocol(IN EFI_HANDLE UserHandle, IN EFI_GUID *Protocol, OUT VOID **Interface)
Definition: Handle.c:1040
EFI_STATUS EFIAPI CoreInstallMultipleProtocolInterfaces(IN OUT EFI_HANDLE *Handle,...)
Definition: Handle.c:630
EFI_STATUS EFIAPI CoreFreePool(IN VOID *Buffer)
Definition: Pool.c:591
VOID EFIAPI FreePool(IN VOID *Buffer)
VOID *EFIAPI AllocateCopyPool(IN UINTN AllocationSize, IN CONST VOID *Buffer)
EFI_STATUS(EFIAPI * EFI_FVB_WRITE)(IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This, IN EFI_LBA Lba, IN UINTN Offset, IN OUT UINTN *NumBytes, IN UINT8 *Buffer)
EFI_STATUS(EFIAPI * EFI_FVB_SET_ATTRIBUTES)(IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This, IN OUT EFI_FVB_ATTRIBUTES_2 *Attributes)
EFI_STATUS(EFIAPI * EFI_FVB_ERASE_BLOCKS)(IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,...)
EFI_STATUS EFIAPI FwVolBlockGetBlockSize(IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, IN CONST EFI_LBA Lba, IN OUT UINTN *BlockSize, IN OUT UINTN *NumberOfBlocks)
Definition: FwVolBlock.c:339
EFI_STATUS EFIAPI FwVolBlockGetPhysicalAddress(IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, OUT EFI_PHYSICAL_ADDRESS *Address)
Definition: FwVolBlock.c:303
EFI_STATUS ProduceFVBProtocolOnBuffer(IN EFI_PHYSICAL_ADDRESS BaseAddress, IN UINT64 Length, IN EFI_HANDLE ParentHandle, IN UINT32 AuthenticationStatus, OUT EFI_HANDLE *FvProtocol OPTIONAL)
Definition: FwVolBlock.c:432
EFI_STATUS EFIAPI FwVolBlockSetAttributes(IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, IN CONST EFI_FVB_ATTRIBUTES_2 *Attributes)
Definition: FwVolBlock.c:125
EFI_STATUS EFIAPI CoreProcessFirmwareVolume(IN VOID *FvHeader, IN UINTN Size, OUT EFI_HANDLE *FVProtocolHandle)
Definition: FwVolBlock.c:676
UINT32 GetFvbAuthenticationStatus(IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvbProtocol)
Definition: FwVolBlock.c:396
EFI_STATUS EFIAPI FwVolBlockWriteBlock(IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, IN EFI_LBA Lba, IN UINTN Offset, IN OUT UINTN *NumBytes, IN UINT8 *Buffer)
Definition: FwVolBlock.c:280
EFI_STATUS EFIAPI FwVolBlockReadBlock(IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, IN CONST EFI_LBA Lba, IN CONST UINTN Offset, IN OUT UINTN *NumBytes, IN OUT UINT8 *Buffer)
Definition: FwVolBlock.c:188
EFI_STATUS EFIAPI FwVolBlockDriverInit(IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable)
Definition: FwVolBlock.c:613
EFI_STATUS EFIAPI FwVolBlockGetAttributes(IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, OUT EFI_FVB_ATTRIBUTES_2 *Attributes)
Definition: FwVolBlock.c:93
EFI_STATUS EFIAPI FwVolBlockEraseBlock(IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This,...)
Definition: FwVolBlock.c:158
#define NULL
Definition: Base.h:319
#define CONST
Definition: Base.h:259
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
#define BASE_CR(Record, TYPE, Field)
Definition: Base.h:891
#define DEBUG(Expression)
Definition: DebugLib.h:434
UINT32 EFI_FVB_ATTRIBUTES_2
VOID *EFIAPI AllocatePool(IN UINTN AllocationSize)
UINT64 EFI_PHYSICAL_ADDRESS
Definition: UefiBaseType.h:50
UINT64 EFI_LBA
Definition: UefiBaseType.h:45
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
VOID * EFI_HANDLE
Definition: UefiBaseType.h:33
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
@ EfiMemoryMappedIO
EFI_FV_BLOCK_MAP_ENTRY BlockMap[1]
EFI_FVB_ATTRIBUTES_2 Attributes
UINT32 AuthenticationStatus
Definition: PiHob.h:418
EFI_PHYSICAL_ADDRESS BaseAddress
Definition: PiHob.h:410
EFI_PHYSICAL_ADDRESS BaseAddress
Definition: PiHob.h:364
Definition: Base.h:213