]> git.proxmox.com Git - mirror_edk2.git/blob - OvmfPkg/QemuFlashFvbServicesRuntimeDxe/FwBlockService.c
BaseTools/BinToPcd: Fix Python 2.7.x compatibility issue
[mirror_edk2.git] / OvmfPkg / QemuFlashFvbServicesRuntimeDxe / FwBlockService.c
1 /**@file
2
3 Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>
4
5 This program and the accompanying materials are licensed and made available
6 under the terms and conditions of the BSD License which accompanies this
7 distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
9
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12
13 Module Name:
14
15 FWBlockService.c
16
17 Abstract:
18
19 Revision History
20
21 **/
22
23 //
24 // The protocols, PPI and GUID defintions for this module
25 //
26 #include <Protocol/DevicePath.h>
27 #include <Protocol/FirmwareVolumeBlock.h>
28
29 //
30 // The Library classes this module consumes
31 //
32 #include <Library/BaseLib.h>
33 #include <Library/BaseMemoryLib.h>
34 #include <Library/DebugLib.h>
35 #include <Library/DevicePathLib.h>
36 #include <Library/DxeServicesTableLib.h>
37 #include <Library/MemoryAllocationLib.h>
38 #include <Library/UefiBootServicesTableLib.h>
39
40 #include "FwBlockService.h"
41 #include "QemuFlash.h"
42
43 #define EFI_FVB2_STATUS \
44 (EFI_FVB2_READ_STATUS | EFI_FVB2_WRITE_STATUS | EFI_FVB2_LOCK_STATUS)
45
46 ESAL_FWB_GLOBAL *mFvbModuleGlobal;
47
48 FV_MEMMAP_DEVICE_PATH mFvMemmapDevicePathTemplate = {
49 {
50 {
51 HARDWARE_DEVICE_PATH,
52 HW_MEMMAP_DP,
53 {
54 (UINT8)(sizeof (MEMMAP_DEVICE_PATH)),
55 (UINT8)(sizeof (MEMMAP_DEVICE_PATH) >> 8)
56 }
57 },
58 EfiMemoryMappedIO,
59 (EFI_PHYSICAL_ADDRESS) 0,
60 (EFI_PHYSICAL_ADDRESS) 0,
61 },
62 {
63 END_DEVICE_PATH_TYPE,
64 END_ENTIRE_DEVICE_PATH_SUBTYPE,
65 {
66 END_DEVICE_PATH_LENGTH,
67 0
68 }
69 }
70 };
71
72 FV_PIWG_DEVICE_PATH mFvPIWGDevicePathTemplate = {
73 {
74 {
75 MEDIA_DEVICE_PATH,
76 MEDIA_PIWG_FW_VOL_DP,
77 {
78 (UINT8)(sizeof (MEDIA_FW_VOL_DEVICE_PATH)),
79 (UINT8)(sizeof (MEDIA_FW_VOL_DEVICE_PATH) >> 8)
80 }
81 },
82 { 0 }
83 },
84 {
85 END_DEVICE_PATH_TYPE,
86 END_ENTIRE_DEVICE_PATH_SUBTYPE,
87 {
88 END_DEVICE_PATH_LENGTH,
89 0
90 }
91 }
92 };
93
94 EFI_FW_VOL_BLOCK_DEVICE mFvbDeviceTemplate = {
95 FVB_DEVICE_SIGNATURE,
96 NULL,
97 0,
98 {
99 FvbProtocolGetAttributes,
100 FvbProtocolSetAttributes,
101 FvbProtocolGetPhysicalAddress,
102 FvbProtocolGetBlockSize,
103 FvbProtocolRead,
104 FvbProtocolWrite,
105 FvbProtocolEraseBlocks,
106 NULL
107 }
108 };
109
110
111 EFI_STATUS
112 GetFvbInstance (
113 IN UINTN Instance,
114 IN ESAL_FWB_GLOBAL *Global,
115 OUT EFI_FW_VOL_INSTANCE **FwhInstance
116 )
117 /*++
118
119 Routine Description:
120 Retrieves the physical address of a memory mapped FV
121
122 Arguments:
123 Instance - The FV instance whose base address is going to be
124 returned
125 Global - Pointer to ESAL_FWB_GLOBAL that contains all
126 instance data
127 FwhInstance - The EFI_FW_VOL_INSTANCE fimrware instance structure
128
129 Returns:
130 EFI_SUCCESS - Successfully returns
131 EFI_INVALID_PARAMETER - Instance not found
132
133 --*/
134 {
135 EFI_FW_VOL_INSTANCE *FwhRecord;
136
137 *FwhInstance = NULL;
138 if (Instance >= Global->NumFv) {
139 return EFI_INVALID_PARAMETER;
140 }
141 //
142 // Find the right instance of the FVB private data
143 //
144 FwhRecord = Global->FvInstance;
145 while (Instance > 0) {
146 FwhRecord = (EFI_FW_VOL_INSTANCE *)
147 (
148 (UINTN) ((UINT8 *) FwhRecord) + FwhRecord->VolumeHeader.HeaderLength +
149 (sizeof (EFI_FW_VOL_INSTANCE) - sizeof (EFI_FIRMWARE_VOLUME_HEADER))
150 );
151 Instance--;
152 }
153
154 *FwhInstance = FwhRecord;
155
156 return EFI_SUCCESS;
157 }
158
159 EFI_STATUS
160 FvbGetPhysicalAddress (
161 IN UINTN Instance,
162 OUT EFI_PHYSICAL_ADDRESS *Address,
163 IN ESAL_FWB_GLOBAL *Global
164 )
165 /*++
166
167 Routine Description:
168 Retrieves the physical address of a memory mapped FV
169
170 Arguments:
171 Instance - The FV instance whose base address is going to be
172 returned
173 Address - Pointer to a caller allocated EFI_PHYSICAL_ADDRESS
174 that on successful return, contains the base
175 address of the firmware volume.
176 Global - Pointer to ESAL_FWB_GLOBAL that contains all
177 instance data
178
179 Returns:
180 EFI_SUCCESS - Successfully returns
181 EFI_INVALID_PARAMETER - Instance not found
182
183 --*/
184 {
185 EFI_FW_VOL_INSTANCE *FwhInstance;
186 EFI_STATUS Status;
187
188 //
189 // Find the right instance of the FVB private data
190 //
191 Status = GetFvbInstance (Instance, Global, &FwhInstance);
192 ASSERT_EFI_ERROR (Status);
193 *Address = FwhInstance->FvBase;
194
195 return EFI_SUCCESS;
196 }
197
198 EFI_STATUS
199 FvbGetVolumeAttributes (
200 IN UINTN Instance,
201 OUT EFI_FVB_ATTRIBUTES_2 *Attributes,
202 IN ESAL_FWB_GLOBAL *Global
203 )
204 /*++
205
206 Routine Description:
207 Retrieves attributes, insures positive polarity of attribute bits, returns
208 resulting attributes in output parameter
209
210 Arguments:
211 Instance - The FV instance whose attributes is going to be
212 returned
213 Attributes - Output buffer which contains attributes
214 Global - Pointer to ESAL_FWB_GLOBAL that contains all
215 instance data
216
217 Returns:
218 EFI_SUCCESS - Successfully returns
219 EFI_INVALID_PARAMETER - Instance not found
220
221 --*/
222 {
223 EFI_FW_VOL_INSTANCE *FwhInstance;
224 EFI_STATUS Status;
225
226 //
227 // Find the right instance of the FVB private data
228 //
229 Status = GetFvbInstance (Instance, Global, &FwhInstance);
230 ASSERT_EFI_ERROR (Status);
231 *Attributes = FwhInstance->VolumeHeader.Attributes;
232
233 return EFI_SUCCESS;
234 }
235
236 EFI_STATUS
237 FvbGetLbaAddress (
238 IN UINTN Instance,
239 IN EFI_LBA Lba,
240 OUT UINTN *LbaAddress,
241 OUT UINTN *LbaLength,
242 OUT UINTN *NumOfBlocks,
243 IN ESAL_FWB_GLOBAL *Global
244 )
245 /*++
246
247 Routine Description:
248 Retrieves the starting address of an LBA in an FV
249
250 Arguments:
251 Instance - The FV instance which the Lba belongs to
252 Lba - The logical block address
253 LbaAddress - On output, contains the physical starting address
254 of the Lba
255 LbaLength - On output, contains the length of the block
256 NumOfBlocks - A pointer to a caller allocated UINTN in which the
257 number of consecutive blocks starting with Lba is
258 returned. All blocks in this range have a size of
259 BlockSize
260 Global - Pointer to ESAL_FWB_GLOBAL that contains all
261 instance data
262
263 Returns:
264 EFI_SUCCESS - Successfully returns
265 EFI_INVALID_PARAMETER - Instance not found
266
267 --*/
268 {
269 UINT32 NumBlocks;
270 UINT32 BlockLength;
271 UINTN Offset;
272 EFI_LBA StartLba;
273 EFI_LBA NextLba;
274 EFI_FW_VOL_INSTANCE *FwhInstance;
275 EFI_FV_BLOCK_MAP_ENTRY *BlockMap;
276 EFI_STATUS Status;
277
278 //
279 // Find the right instance of the FVB private data
280 //
281 Status = GetFvbInstance (Instance, Global, &FwhInstance);
282 ASSERT_EFI_ERROR (Status);
283
284 StartLba = 0;
285 Offset = 0;
286 BlockMap = &(FwhInstance->VolumeHeader.BlockMap[0]);
287
288 //
289 // Parse the blockmap of the FV to find which map entry the Lba belongs to
290 //
291 while (TRUE) {
292 NumBlocks = BlockMap->NumBlocks;
293 BlockLength = BlockMap->Length;
294
295 if (NumBlocks == 0 || BlockLength == 0) {
296 return EFI_INVALID_PARAMETER;
297 }
298
299 NextLba = StartLba + NumBlocks;
300
301 //
302 // The map entry found
303 //
304 if (Lba >= StartLba && Lba < NextLba) {
305 Offset = Offset + (UINTN) MultU64x32 ((Lba - StartLba), BlockLength);
306 if (LbaAddress != NULL) {
307 *LbaAddress = FwhInstance->FvBase + Offset;
308 }
309
310 if (LbaLength != NULL) {
311 *LbaLength = BlockLength;
312 }
313
314 if (NumOfBlocks != NULL) {
315 *NumOfBlocks = (UINTN) (NextLba - Lba);
316 }
317
318 return EFI_SUCCESS;
319 }
320
321 StartLba = NextLba;
322 Offset = Offset + NumBlocks * BlockLength;
323 BlockMap++;
324 }
325 }
326
327 EFI_STATUS
328 FvbSetVolumeAttributes (
329 IN UINTN Instance,
330 IN OUT EFI_FVB_ATTRIBUTES_2 *Attributes,
331 IN ESAL_FWB_GLOBAL *Global
332 )
333 /*++
334
335 Routine Description:
336 Modifies the current settings of the firmware volume according to the
337 input parameter, and returns the new setting of the volume
338
339 Arguments:
340 Instance - The FV instance whose attributes is going to be
341 modified
342 Attributes - On input, it is a pointer to EFI_FVB_ATTRIBUTES_2
343 containing the desired firmware volume settings.
344 On successful return, it contains the new settings
345 of the firmware volume
346 Global - Pointer to ESAL_FWB_GLOBAL that contains all
347 instance data
348
349 Returns:
350 EFI_SUCCESS - Successfully returns
351 EFI_ACCESS_DENIED - The volume setting is locked and cannot be modified
352 EFI_INVALID_PARAMETER - Instance not found, or The attributes requested are
353 in conflict with the capabilities as declared in
354 the firmware volume header
355
356 --*/
357 {
358 EFI_FW_VOL_INSTANCE *FwhInstance;
359 EFI_FVB_ATTRIBUTES_2 OldAttributes;
360 EFI_FVB_ATTRIBUTES_2 *AttribPtr;
361 UINT32 Capabilities;
362 UINT32 OldStatus;
363 UINT32 NewStatus;
364 EFI_STATUS Status;
365 EFI_FVB_ATTRIBUTES_2 UnchangedAttributes;
366
367 //
368 // Find the right instance of the FVB private data
369 //
370 Status = GetFvbInstance (Instance, Global, &FwhInstance);
371 ASSERT_EFI_ERROR (Status);
372
373 AttribPtr =
374 (EFI_FVB_ATTRIBUTES_2 *) &(FwhInstance->VolumeHeader.Attributes);
375 OldAttributes = *AttribPtr;
376 Capabilities = OldAttributes & (EFI_FVB2_READ_DISABLED_CAP | \
377 EFI_FVB2_READ_ENABLED_CAP | \
378 EFI_FVB2_WRITE_DISABLED_CAP | \
379 EFI_FVB2_WRITE_ENABLED_CAP | \
380 EFI_FVB2_LOCK_CAP \
381 );
382 OldStatus = OldAttributes & EFI_FVB2_STATUS;
383 NewStatus = *Attributes & EFI_FVB2_STATUS;
384
385 UnchangedAttributes = EFI_FVB2_READ_DISABLED_CAP | \
386 EFI_FVB2_READ_ENABLED_CAP | \
387 EFI_FVB2_WRITE_DISABLED_CAP | \
388 EFI_FVB2_WRITE_ENABLED_CAP | \
389 EFI_FVB2_LOCK_CAP | \
390 EFI_FVB2_STICKY_WRITE | \
391 EFI_FVB2_MEMORY_MAPPED | \
392 EFI_FVB2_ERASE_POLARITY | \
393 EFI_FVB2_READ_LOCK_CAP | \
394 EFI_FVB2_WRITE_LOCK_CAP | \
395 EFI_FVB2_ALIGNMENT;
396
397 //
398 // Some attributes of FV is read only can *not* be set
399 //
400 if ((OldAttributes & UnchangedAttributes) ^
401 (*Attributes & UnchangedAttributes)) {
402 return EFI_INVALID_PARAMETER;
403 }
404 //
405 // If firmware volume is locked, no status bit can be updated
406 //
407 if (OldAttributes & EFI_FVB2_LOCK_STATUS) {
408 if (OldStatus ^ NewStatus) {
409 return EFI_ACCESS_DENIED;
410 }
411 }
412 //
413 // Test read disable
414 //
415 if ((Capabilities & EFI_FVB2_READ_DISABLED_CAP) == 0) {
416 if ((NewStatus & EFI_FVB2_READ_STATUS) == 0) {
417 return EFI_INVALID_PARAMETER;
418 }
419 }
420 //
421 // Test read enable
422 //
423 if ((Capabilities & EFI_FVB2_READ_ENABLED_CAP) == 0) {
424 if (NewStatus & EFI_FVB2_READ_STATUS) {
425 return EFI_INVALID_PARAMETER;
426 }
427 }
428 //
429 // Test write disable
430 //
431 if ((Capabilities & EFI_FVB2_WRITE_DISABLED_CAP) == 0) {
432 if ((NewStatus & EFI_FVB2_WRITE_STATUS) == 0) {
433 return EFI_INVALID_PARAMETER;
434 }
435 }
436 //
437 // Test write enable
438 //
439 if ((Capabilities & EFI_FVB2_WRITE_ENABLED_CAP) == 0) {
440 if (NewStatus & EFI_FVB2_WRITE_STATUS) {
441 return EFI_INVALID_PARAMETER;
442 }
443 }
444 //
445 // Test lock
446 //
447 if ((Capabilities & EFI_FVB2_LOCK_CAP) == 0) {
448 if (NewStatus & EFI_FVB2_LOCK_STATUS) {
449 return EFI_INVALID_PARAMETER;
450 }
451 }
452
453 *AttribPtr = (*AttribPtr) & (0xFFFFFFFF & (~EFI_FVB2_STATUS));
454 *AttribPtr = (*AttribPtr) | NewStatus;
455 *Attributes = *AttribPtr;
456
457 return EFI_SUCCESS;
458 }
459
460 //
461 // FVB protocol APIs
462 //
463 EFI_STATUS
464 EFIAPI
465 FvbProtocolGetPhysicalAddress (
466 IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This,
467 OUT EFI_PHYSICAL_ADDRESS *Address
468 )
469 /*++
470
471 Routine Description:
472
473 Retrieves the physical address of the device.
474
475 Arguments:
476
477 This - Calling context
478 Address - Output buffer containing the address.
479
480 Returns:
481 EFI_SUCCESS - Successfully returns
482
483 --*/
484 {
485 EFI_FW_VOL_BLOCK_DEVICE *FvbDevice;
486
487 FvbDevice = FVB_DEVICE_FROM_THIS (This);
488
489 return FvbGetPhysicalAddress (FvbDevice->Instance, Address,
490 mFvbModuleGlobal);
491 }
492
493 EFI_STATUS
494 EFIAPI
495 FvbProtocolGetBlockSize (
496 IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This,
497 IN CONST EFI_LBA Lba,
498 OUT UINTN *BlockSize,
499 OUT UINTN *NumOfBlocks
500 )
501 /*++
502
503 Routine Description:
504 Retrieve the size of a logical block
505
506 Arguments:
507 This - Calling context
508 Lba - Indicates which block to return the size for.
509 BlockSize - A pointer to a caller allocated UINTN in which
510 the size of the block is returned
511 NumOfBlocks - a pointer to a caller allocated UINTN in which the
512 number of consecutive blocks starting with Lba is
513 returned. All blocks in this range have a size of
514 BlockSize
515
516 Returns:
517 EFI_SUCCESS - The firmware volume was read successfully and
518 contents are in Buffer
519
520 --*/
521 {
522 EFI_FW_VOL_BLOCK_DEVICE *FvbDevice;
523
524 FvbDevice = FVB_DEVICE_FROM_THIS (This);
525
526 return FvbGetLbaAddress (
527 FvbDevice->Instance,
528 Lba,
529 NULL,
530 BlockSize,
531 NumOfBlocks,
532 mFvbModuleGlobal
533 );
534 }
535
536 EFI_STATUS
537 EFIAPI
538 FvbProtocolGetAttributes (
539 IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This,
540 OUT EFI_FVB_ATTRIBUTES_2 *Attributes
541 )
542 /*++
543
544 Routine Description:
545 Retrieves Volume attributes. No polarity translations are done.
546
547 Arguments:
548 This - Calling context
549 Attributes - output buffer which contains attributes
550
551 Returns:
552 EFI_SUCCESS - Successfully returns
553
554 --*/
555 {
556 EFI_FW_VOL_BLOCK_DEVICE *FvbDevice;
557
558 FvbDevice = FVB_DEVICE_FROM_THIS (This);
559
560 return FvbGetVolumeAttributes (FvbDevice->Instance, Attributes,
561 mFvbModuleGlobal);
562 }
563
564 EFI_STATUS
565 EFIAPI
566 FvbProtocolSetAttributes (
567 IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This,
568 IN OUT EFI_FVB_ATTRIBUTES_2 *Attributes
569 )
570 /*++
571
572 Routine Description:
573 Sets Volume attributes. No polarity translations are done.
574
575 Arguments:
576 This - Calling context
577 Attributes - output buffer which contains attributes
578
579 Returns:
580 EFI_SUCCESS - Successfully returns
581
582 --*/
583 {
584 EFI_FW_VOL_BLOCK_DEVICE *FvbDevice;
585
586 FvbDevice = FVB_DEVICE_FROM_THIS (This);
587
588 return FvbSetVolumeAttributes (FvbDevice->Instance, Attributes,
589 mFvbModuleGlobal);
590 }
591
592 EFI_STATUS
593 EFIAPI
594 FvbProtocolEraseBlocks (
595 IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This,
596 ...
597 )
598 /*++
599
600 Routine Description:
601
602 The EraseBlock() function erases one or more blocks as denoted by the
603 variable argument list. The entire parameter list of blocks must be
604 verified prior to erasing any blocks. If a block is requested that does
605 not exist within the associated firmware volume (it has a larger index than
606 the last block of the firmware volume), the EraseBlock() function must
607 return EFI_INVALID_PARAMETER without modifying the contents of the firmware
608 volume.
609
610 Arguments:
611 This - Calling context
612 ... - Starting LBA followed by Number of Lba to erase.
613 a -1 to terminate the list.
614
615 Returns:
616 EFI_SUCCESS - The erase request was successfully completed
617 EFI_ACCESS_DENIED - The firmware volume is in the WriteDisabled state
618 EFI_DEVICE_ERROR - The block device is not functioning correctly and
619 could not be written. Firmware device may have been
620 partially erased
621
622 --*/
623 {
624 EFI_FW_VOL_BLOCK_DEVICE *FvbDevice;
625 EFI_FW_VOL_INSTANCE *FwhInstance;
626 UINTN NumOfBlocks;
627 VA_LIST args;
628 EFI_LBA StartingLba;
629 UINTN NumOfLba;
630 EFI_STATUS Status;
631
632 FvbDevice = FVB_DEVICE_FROM_THIS (This);
633
634 Status = GetFvbInstance (FvbDevice->Instance, mFvbModuleGlobal,
635 &FwhInstance);
636 ASSERT_EFI_ERROR (Status);
637
638 NumOfBlocks = FwhInstance->NumOfBlocks;
639
640 VA_START (args, This);
641
642 do {
643 StartingLba = VA_ARG (args, EFI_LBA);
644 if (StartingLba == EFI_LBA_LIST_TERMINATOR) {
645 break;
646 }
647
648 NumOfLba = VA_ARG (args, UINTN);
649
650 //
651 // Check input parameters
652 //
653 if ((NumOfLba == 0) || ((StartingLba + NumOfLba) > NumOfBlocks)) {
654 VA_END (args);
655 return EFI_INVALID_PARAMETER;
656 }
657 } while (1);
658
659 VA_END (args);
660
661 VA_START (args, This);
662 do {
663 StartingLba = VA_ARG (args, EFI_LBA);
664 if (StartingLba == EFI_LBA_LIST_TERMINATOR) {
665 break;
666 }
667
668 NumOfLba = VA_ARG (args, UINTN);
669
670 while (NumOfLba > 0) {
671 Status = QemuFlashEraseBlock (StartingLba);
672 if (EFI_ERROR (Status)) {
673 VA_END (args);
674 return Status;
675 }
676
677 StartingLba++;
678 NumOfLba--;
679 }
680
681 } while (1);
682
683 VA_END (args);
684
685 return EFI_SUCCESS;
686 }
687
688 EFI_STATUS
689 EFIAPI
690 FvbProtocolWrite (
691 IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This,
692 IN EFI_LBA Lba,
693 IN UINTN Offset,
694 IN OUT UINTN *NumBytes,
695 IN UINT8 *Buffer
696 )
697 /*++
698
699 Routine Description:
700
701 Writes data beginning at Lba:Offset from FV. The write terminates either
702 when *NumBytes of data have been written, or when a block boundary is
703 reached. *NumBytes is updated to reflect the actual number of bytes
704 written. The write opertion does not include erase. This routine will
705 attempt to write only the specified bytes. If the writes do not stick,
706 it will return an error.
707
708 Arguments:
709 This - Calling context
710 Lba - Block in which to begin write
711 Offset - Offset in the block at which to begin write
712 NumBytes - On input, indicates the requested write size. On
713 output, indicates the actual number of bytes
714 written
715 Buffer - Buffer containing source data for the write.
716
717 Returns:
718 EFI_SUCCESS - The firmware volume was written successfully
719 EFI_BAD_BUFFER_SIZE - Write attempted across a LBA boundary. On output,
720 NumBytes contains the total number of bytes
721 actually written
722 EFI_ACCESS_DENIED - The firmware volume is in the WriteDisabled state
723 EFI_DEVICE_ERROR - The block device is not functioning correctly and
724 could not be written
725 EFI_INVALID_PARAMETER - NumBytes or Buffer are NULL
726
727 --*/
728 {
729 return QemuFlashWrite ((EFI_LBA)Lba, (UINTN)Offset, NumBytes,
730 (UINT8 *)Buffer);
731 }
732
733 EFI_STATUS
734 EFIAPI
735 FvbProtocolRead (
736 IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This,
737 IN CONST EFI_LBA Lba,
738 IN CONST UINTN Offset,
739 IN OUT UINTN *NumBytes,
740 IN UINT8 *Buffer
741 )
742 /*++
743
744 Routine Description:
745
746 Reads data beginning at Lba:Offset from FV. The Read terminates either
747 when *NumBytes of data have been read, or when a block boundary is
748 reached. *NumBytes is updated to reflect the actual number of bytes
749 written. The write opertion does not include erase. This routine will
750 attempt to write only the specified bytes. If the writes do not stick,
751 it will return an error.
752
753 Arguments:
754 This - Calling context
755 Lba - Block in which to begin Read
756 Offset - Offset in the block at which to begin Read
757 NumBytes - On input, indicates the requested write size. On
758 output, indicates the actual number of bytes Read
759 Buffer - Buffer containing source data for the Read.
760
761 Returns:
762 EFI_SUCCESS - The firmware volume was read successfully and
763 contents are in Buffer
764 EFI_BAD_BUFFER_SIZE - Read attempted across a LBA boundary. On output,
765 NumBytes contains the total number of bytes
766 returned in Buffer
767 EFI_ACCESS_DENIED - The firmware volume is in the ReadDisabled state
768 EFI_DEVICE_ERROR - The block device is not functioning correctly and
769 could not be read
770 EFI_INVALID_PARAMETER - NumBytes or Buffer are NULL
771
772 --*/
773 {
774 return QemuFlashRead ((EFI_LBA)Lba, (UINTN)Offset, NumBytes,
775 (UINT8 *)Buffer);
776 }
777
778 EFI_STATUS
779 ValidateFvHeader (
780 EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader
781 )
782 /*++
783
784 Routine Description:
785 Check the integrity of firmware volume header
786
787 Arguments:
788 FwVolHeader - A pointer to a firmware volume header
789
790 Returns:
791 EFI_SUCCESS - The firmware volume is consistent
792 EFI_NOT_FOUND - The firmware volume has corrupted. So it is not an
793 FV
794
795 --*/
796 {
797 UINT16 Checksum;
798
799 //
800 // Verify the header revision, header signature, length
801 // Length of FvBlock cannot be 2**64-1
802 // HeaderLength cannot be an odd number
803 //
804 if ((FwVolHeader->Revision != EFI_FVH_REVISION) ||
805 (FwVolHeader->Signature != EFI_FVH_SIGNATURE) ||
806 (FwVolHeader->FvLength == ((UINTN) -1)) ||
807 ((FwVolHeader->HeaderLength & 0x01) != 0)
808 ) {
809 return EFI_NOT_FOUND;
810 }
811
812 //
813 // Verify the header checksum
814 //
815
816 Checksum = CalculateSum16 ((UINT16 *) FwVolHeader,
817 FwVolHeader->HeaderLength);
818 if (Checksum != 0) {
819 UINT16 Expected;
820
821 Expected =
822 (UINT16) (((UINTN) FwVolHeader->Checksum + 0x10000 - Checksum) & 0xffff);
823
824 DEBUG ((EFI_D_INFO, "FV@%p Checksum is 0x%x, expected 0x%x\n",
825 FwVolHeader, FwVolHeader->Checksum, Expected));
826 return EFI_NOT_FOUND;
827 }
828
829 return EFI_SUCCESS;
830 }
831
832 STATIC
833 EFI_STATUS
834 InitializeVariableFvHeader (
835 VOID
836 )
837 {
838 EFI_STATUS Status;
839 EFI_FIRMWARE_VOLUME_HEADER *GoodFwVolHeader;
840 EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;
841 UINTN Length;
842 UINTN WriteLength;
843 UINTN BlockSize;
844
845 FwVolHeader =
846 (EFI_FIRMWARE_VOLUME_HEADER *) (UINTN)
847 PcdGet32 (PcdOvmfFlashNvStorageVariableBase);
848
849 Length =
850 (FixedPcdGet32 (PcdFlashNvStorageVariableSize) +
851 FixedPcdGet32 (PcdFlashNvStorageFtwWorkingSize) +
852 FixedPcdGet32 (PcdFlashNvStorageFtwSpareSize) +
853 FixedPcdGet32 (PcdOvmfFlashNvStorageEventLogSize));
854
855 BlockSize = PcdGet32 (PcdOvmfFirmwareBlockSize);
856
857 Status = ValidateFvHeader (FwVolHeader);
858 if (!EFI_ERROR (Status)) {
859 if (FwVolHeader->FvLength != Length ||
860 FwVolHeader->BlockMap[0].Length != BlockSize) {
861 Status = EFI_VOLUME_CORRUPTED;
862 }
863 }
864 if (EFI_ERROR (Status)) {
865 UINTN Offset;
866 UINTN Start;
867
868 DEBUG ((EFI_D_INFO,
869 "Variable FV header is not valid. It will be reinitialized.\n"));
870
871 //
872 // Get FvbInfo to provide in FwhInstance.
873 //
874 Status = GetFvbInfo (Length, &GoodFwVolHeader);
875 ASSERT (!EFI_ERROR (Status));
876
877 Start = (UINTN)(UINT8*) FwVolHeader - PcdGet32 (PcdOvmfFdBaseAddress);
878 ASSERT (Start % BlockSize == 0 && Length % BlockSize == 0);
879 ASSERT (GoodFwVolHeader->HeaderLength <= BlockSize);
880
881 //
882 // Erase all the blocks
883 //
884 for (Offset = Start; Offset < Start + Length; Offset += BlockSize) {
885 Status = QemuFlashEraseBlock (Offset / BlockSize);
886 ASSERT_EFI_ERROR (Status);
887 }
888
889 //
890 // Write good FV header
891 //
892 WriteLength = GoodFwVolHeader->HeaderLength;
893 Status = QemuFlashWrite (
894 Start / BlockSize,
895 0,
896 &WriteLength,
897 (UINT8 *) GoodFwVolHeader);
898 ASSERT_EFI_ERROR (Status);
899 ASSERT (WriteLength == GoodFwVolHeader->HeaderLength);
900 }
901
902 return Status;
903 }
904
905 EFI_STATUS
906 EFIAPI
907 FvbInitialize (
908 IN EFI_HANDLE ImageHandle,
909 IN EFI_SYSTEM_TABLE *SystemTable
910 )
911 /*++
912
913 Routine Description:
914 This function does common initialization for FVB services
915
916 Arguments:
917
918 Returns:
919
920 --*/
921 {
922 EFI_STATUS Status;
923 EFI_FW_VOL_INSTANCE *FwhInstance;
924 EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;
925 UINT32 BufferSize;
926 EFI_FV_BLOCK_MAP_ENTRY *PtrBlockMapEntry;
927 EFI_FW_VOL_BLOCK_DEVICE *FvbDevice;
928 UINT32 MaxLbaSize;
929 EFI_PHYSICAL_ADDRESS BaseAddress;
930 UINTN Length;
931 UINTN NumOfBlocks;
932 RETURN_STATUS PcdStatus;
933
934 if (EFI_ERROR (QemuFlashInitialize ())) {
935 //
936 // Return an error so image will be unloaded
937 //
938 DEBUG ((EFI_D_INFO,
939 "QEMU flash was not detected. Writable FVB is not being installed.\n"));
940 return EFI_WRITE_PROTECTED;
941 }
942
943 //
944 // Allocate runtime services data for global variable, which contains
945 // the private data of all firmware volume block instances
946 //
947 mFvbModuleGlobal = AllocateRuntimePool (sizeof (ESAL_FWB_GLOBAL));
948 ASSERT (mFvbModuleGlobal != NULL);
949
950 BaseAddress = (UINTN) PcdGet32 (PcdOvmfFdBaseAddress);
951 Length = PcdGet32 (PcdOvmfFirmwareFdSize);
952
953 Status = InitializeVariableFvHeader ();
954 if (EFI_ERROR (Status)) {
955 DEBUG ((EFI_D_INFO,
956 "QEMU Flash: Unable to initialize variable FV header\n"));
957 return EFI_WRITE_PROTECTED;
958 }
959
960 FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *) (UINTN) BaseAddress;
961 Status = ValidateFvHeader (FwVolHeader);
962 if (EFI_ERROR (Status)) {
963 //
964 // Get FvbInfo
965 //
966 Status = GetFvbInfo (Length, &FwVolHeader);
967 if (EFI_ERROR (Status)) {
968 DEBUG ((EFI_D_INFO, "EFI_ERROR (GetFvbInfo (Length, &FwVolHeader))\n"));
969 return EFI_WRITE_PROTECTED;
970 }
971 }
972
973 BufferSize = (sizeof (EFI_FW_VOL_INSTANCE) +
974 FwVolHeader->HeaderLength -
975 sizeof (EFI_FIRMWARE_VOLUME_HEADER)
976 );
977 mFvbModuleGlobal->FvInstance = AllocateRuntimePool (BufferSize);
978 ASSERT (mFvbModuleGlobal->FvInstance != NULL);
979
980 FwhInstance = mFvbModuleGlobal->FvInstance;
981
982 mFvbModuleGlobal->NumFv = 0;
983 MaxLbaSize = 0;
984
985 FwVolHeader =
986 (EFI_FIRMWARE_VOLUME_HEADER *) (UINTN)
987 PcdGet32 (PcdOvmfFlashNvStorageVariableBase);
988
989 FwhInstance->FvBase = (UINTN) BaseAddress;
990
991 CopyMem ((UINTN *) &(FwhInstance->VolumeHeader), (UINTN *) FwVolHeader,
992 FwVolHeader->HeaderLength);
993 FwVolHeader = &(FwhInstance->VolumeHeader);
994
995 NumOfBlocks = 0;
996
997 for (PtrBlockMapEntry = FwVolHeader->BlockMap;
998 PtrBlockMapEntry->NumBlocks != 0;
999 PtrBlockMapEntry++) {
1000 //
1001 // Get the maximum size of a block.
1002 //
1003 if (MaxLbaSize < PtrBlockMapEntry->Length) {
1004 MaxLbaSize = PtrBlockMapEntry->Length;
1005 }
1006
1007 NumOfBlocks = NumOfBlocks + PtrBlockMapEntry->NumBlocks;
1008 }
1009
1010 //
1011 // The total number of blocks in the FV.
1012 //
1013 FwhInstance->NumOfBlocks = NumOfBlocks;
1014
1015 //
1016 // Add a FVB Protocol Instance
1017 //
1018 FvbDevice = AllocateRuntimePool (sizeof (EFI_FW_VOL_BLOCK_DEVICE));
1019 ASSERT (FvbDevice != NULL);
1020
1021 CopyMem (FvbDevice, &mFvbDeviceTemplate, sizeof (EFI_FW_VOL_BLOCK_DEVICE));
1022
1023 FvbDevice->Instance = mFvbModuleGlobal->NumFv;
1024 mFvbModuleGlobal->NumFv++;
1025
1026 //
1027 // Set up the devicepath
1028 //
1029 if (FwVolHeader->ExtHeaderOffset == 0) {
1030 FV_MEMMAP_DEVICE_PATH *FvMemmapDevicePath;
1031
1032 //
1033 // FV does not contains extension header, then produce MEMMAP_DEVICE_PATH
1034 //
1035 FvMemmapDevicePath = AllocateCopyPool (sizeof (FV_MEMMAP_DEVICE_PATH),
1036 &mFvMemmapDevicePathTemplate);
1037 FvMemmapDevicePath->MemMapDevPath.StartingAddress = BaseAddress;
1038 FvMemmapDevicePath->MemMapDevPath.EndingAddress =
1039 BaseAddress + FwVolHeader->FvLength - 1;
1040 FvbDevice->DevicePath = (EFI_DEVICE_PATH_PROTOCOL *)FvMemmapDevicePath;
1041 } else {
1042 FV_PIWG_DEVICE_PATH *FvPiwgDevicePath;
1043
1044 FvPiwgDevicePath = AllocateCopyPool (sizeof (FV_PIWG_DEVICE_PATH),
1045 &mFvPIWGDevicePathTemplate);
1046 CopyGuid (
1047 &FvPiwgDevicePath->FvDevPath.FvName,
1048 (GUID *)(UINTN)(BaseAddress + FwVolHeader->ExtHeaderOffset)
1049 );
1050 FvbDevice->DevicePath = (EFI_DEVICE_PATH_PROTOCOL *)FvPiwgDevicePath;
1051 }
1052
1053 //
1054 // Module type specific hook.
1055 //
1056 InstallProtocolInterfaces (FvbDevice);
1057
1058 MarkIoMemoryRangeForRuntimeAccess (BaseAddress, Length);
1059
1060 //
1061 // Set several PCD values to point to flash
1062 //
1063 PcdStatus = PcdSet64S (
1064 PcdFlashNvStorageVariableBase64,
1065 (UINTN) PcdGet32 (PcdOvmfFlashNvStorageVariableBase)
1066 );
1067 ASSERT_RETURN_ERROR (PcdStatus);
1068 PcdStatus = PcdSet32S (
1069 PcdFlashNvStorageFtwWorkingBase,
1070 PcdGet32 (PcdOvmfFlashNvStorageFtwWorkingBase)
1071 );
1072 ASSERT_RETURN_ERROR (PcdStatus);
1073 PcdStatus = PcdSet32S (
1074 PcdFlashNvStorageFtwSpareBase,
1075 PcdGet32 (PcdOvmfFlashNvStorageFtwSpareBase)
1076 );
1077 ASSERT_RETURN_ERROR (PcdStatus);
1078
1079 FwhInstance = (EFI_FW_VOL_INSTANCE *)
1080 (
1081 (UINTN) ((UINT8 *) FwhInstance) + FwVolHeader->HeaderLength +
1082 (sizeof (EFI_FW_VOL_INSTANCE) - sizeof (EFI_FIRMWARE_VOLUME_HEADER))
1083 );
1084
1085 //
1086 // Module type specific hook.
1087 //
1088 InstallVirtualAddressChangeHandler ();
1089
1090 PcdStatus = PcdSetBoolS (PcdOvmfFlashVariablesEnable, TRUE);
1091 ASSERT_RETURN_ERROR (PcdStatus);
1092 return EFI_SUCCESS;
1093 }