EDK2 doxygen online documents - Firmware Encoding Index 1
EDK2 doxygen online documents - Firmware Encoding Index

UnixPkg/FvbServicesRuntimeDxe/FWBlockService.c

Go to the documentation of this file.
00001 /*++
00002 
00003 Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.<BR>
00004 This program and the accompanying materials                          
00005 are licensed and made available under the terms and conditions of the BSD License         
00006 which accompanies this distribution.  The full text of the license may be found at        
00007 http://opensource.org/licenses/bsd-license.php                                            
00008                                                                                           
00009 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     
00010 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             
00011 
00012 Module Name:
00013 
00014   FWBlockService.c
00015     
00016 Abstract:
00017 
00018 Revision History
00019 
00020 --*/
00021 
00022 #include "PiDxe.h"
00023 #include <Guid/EventGroup.h>
00024 #include <Protocol/FirmwareVolumeBlock.h>
00025 #include <Protocol/DevicePath.h>
00026 
00027 #include <Library/UefiLib.h>
00028 #include <Library/UefiDriverEntryPoint.h>
00029 #include <Library/BaseLib.h>
00030 #include <Library/DxeServicesTableLib.h>
00031 #include <Library/UefiRuntimeLib.h>
00032 #include <Library/DebugLib.h>
00033 #include <Library/HobLib.h>
00034 #include <Library/BaseMemoryLib.h>
00035 #include <Library/MemoryAllocationLib.h>
00036 #include <Library/UefiBootServicesTableLib.h>
00037 #include <Library/DevicePathLib.h>
00038 
00039 #include "FwBlockService.h"
00040 
00041 ESAL_FWB_GLOBAL         *mFvbModuleGlobal;
00042 
00043 #define EFI_FVB2_STATUS (EFI_FVB2_READ_STATUS | EFI_FVB2_WRITE_STATUS | EFI_FVB2_LOCK_STATUS)
00044 
00045 EFI_FW_VOL_BLOCK_DEVICE mFvbDeviceTemplate = {
00046   FVB_DEVICE_SIGNATURE,
00047   {
00048     {
00049       {
00050         HARDWARE_DEVICE_PATH,
00051         HW_MEMMAP_DP,
00052         {
00053           sizeof (MEMMAP_DEVICE_PATH),
00054           0
00055         }
00056       },
00057       EfiMemoryMappedIO,
00058       0,
00059       0,
00060     },
00061     {
00062       END_DEVICE_PATH_TYPE,
00063       END_ENTIRE_DEVICE_PATH_SUBTYPE,
00064       {
00065         sizeof (EFI_DEVICE_PATH_PROTOCOL),
00066         0
00067       }
00068     }
00069   },
00070   0,
00071   {
00072     FvbProtocolGetAttributes,
00073     FvbProtocolSetAttributes,
00074     FvbProtocolGetPhysicalAddress,
00075     FvbProtocolGetBlockSize,
00076     FvbProtocolRead,
00077     FvbProtocolWrite,
00078     FvbProtocolEraseBlocks,
00079     NULL
00080   }
00081 };
00082 
00083 
00084 
00085 VOID
00086 EFIAPI
00087 FvbVirtualddressChangeEvent (
00088   IN EFI_EVENT        Event,
00089   IN VOID             *Context
00090   )
00091 /*++
00092 
00093 Routine Description:
00094 
00095   Fixup internal data so that EFI and SAL can be call in virtual mode.
00096   Call the passed in Child Notify event and convert the mFvbModuleGlobal
00097   date items to there virtual address.
00098 
00099   mFvbModuleGlobal->FvInstance[FVB_PHYSICAL]  - Physical copy of instance data
00100   mFvbModuleGlobal->FvInstance[FVB_VIRTUAL]   - Virtual pointer to common 
00101                                                 instance data.
00102 
00103 Arguments:
00104 
00105   (Standard EFI notify event - EFI_EVENT_NOTIFY)
00106 
00107 Returns: 
00108 
00109   None
00110 
00111 --*/
00112 {
00113   EFI_FW_VOL_INSTANCE *FwhInstance;
00114   UINTN               Index;
00115 
00116   EfiConvertPointer (0x0, (VOID **) &mFvbModuleGlobal->FvInstance[FVB_VIRTUAL]);
00117 
00118   //
00119   // Convert the base address of all the instances
00120   //
00121   Index       = 0;
00122   FwhInstance = mFvbModuleGlobal->FvInstance[FVB_PHYSICAL];
00123   while (Index < mFvbModuleGlobal->NumFv) {
00124     EfiConvertPointer (0x0, (VOID **) &FwhInstance->FvBase[FVB_VIRTUAL]);
00125     FwhInstance = (EFI_FW_VOL_INSTANCE *)
00126       (
00127         (UINTN) ((UINT8 *) FwhInstance) + FwhInstance->VolumeHeader.HeaderLength +
00128           (sizeof (EFI_FW_VOL_INSTANCE) - sizeof (EFI_FIRMWARE_VOLUME_HEADER))
00129       );
00130     Index++;
00131   }
00132 
00133   EfiConvertPointer (0x0, (VOID **) &mFvbModuleGlobal);
00134 }
00135 
00136 EFI_STATUS
00137 GetFvbInstance (
00138   IN  UINTN                               Instance,
00139   IN  ESAL_FWB_GLOBAL                     *Global,
00140   OUT EFI_FW_VOL_INSTANCE                 **FwhInstance,
00141   IN BOOLEAN                              Virtual
00142   )
00143 /*++
00144 
00145 Routine Description:
00146   Retrieves the physical address of a memory mapped FV
00147 
00148 Arguments:
00149   Instance              - The FV instance whose base address is going to be
00150                           returned
00151   Global                - Pointer to ESAL_FWB_GLOBAL that contains all
00152                           instance data
00153   FwhInstance           - The EFI_FW_VOL_INSTANCE fimrware instance structure
00154   Virtual               - Whether CPU is in virtual or physical mode
00155 
00156 Returns: 
00157   EFI_SUCCESS           - Successfully returns
00158   EFI_INVALID_PARAMETER - Instance not found
00159 
00160 --*/
00161 {
00162   EFI_FW_VOL_INSTANCE *FwhRecord;
00163 
00164   if (Instance >= Global->NumFv) {
00165     return EFI_INVALID_PARAMETER;
00166   }
00167   //
00168   // Find the right instance of the FVB private data
00169   //
00170   FwhRecord = Global->FvInstance[Virtual];
00171   while (Instance > 0) {
00172     FwhRecord = (EFI_FW_VOL_INSTANCE *)
00173       (
00174         (UINTN) ((UINT8 *) FwhRecord) + FwhRecord->VolumeHeader.HeaderLength +
00175           (sizeof (EFI_FW_VOL_INSTANCE) - sizeof (EFI_FIRMWARE_VOLUME_HEADER))
00176       );
00177     Instance--;
00178   }
00179 
00180   *FwhInstance = FwhRecord;
00181 
00182   return EFI_SUCCESS;
00183 }
00184 
00185 EFI_STATUS
00186 FvbGetPhysicalAddress (
00187   IN UINTN                                Instance,
00188   OUT EFI_PHYSICAL_ADDRESS                *Address,
00189   IN ESAL_FWB_GLOBAL                      *Global,
00190   IN BOOLEAN                              Virtual
00191   )
00192 /*++
00193 
00194 Routine Description:
00195   Retrieves the physical address of a memory mapped FV
00196 
00197 Arguments:
00198   Instance              - The FV instance whose base address is going to be
00199                           returned
00200   Address               - Pointer to a caller allocated EFI_PHYSICAL_ADDRESS 
00201                           that on successful return, contains the base address
00202                           of the firmware volume. 
00203   Global                - Pointer to ESAL_FWB_GLOBAL that contains all
00204                           instance data
00205   Virtual               - Whether CPU is in virtual or physical mode
00206 
00207 Returns: 
00208   EFI_SUCCESS           - Successfully returns
00209   EFI_INVALID_PARAMETER - Instance not found
00210 
00211 --*/
00212 {
00213   EFI_FW_VOL_INSTANCE *FwhInstance = NULL;
00214   EFI_STATUS          Status;
00215 
00216   //
00217   // Find the right instance of the FVB private data
00218   //
00219   Status = GetFvbInstance (Instance, Global, &FwhInstance, Virtual);
00220   ASSERT_EFI_ERROR (Status);
00221   *Address = FwhInstance->FvBase[Virtual];
00222 
00223   return EFI_SUCCESS;
00224 }
00225 
00226 EFI_STATUS
00227 FvbGetVolumeAttributes (
00228   IN UINTN                                Instance,
00229   OUT EFI_FVB_ATTRIBUTES_2                *Attributes,
00230   IN ESAL_FWB_GLOBAL                      *Global,
00231   IN BOOLEAN                              Virtual
00232   )
00233 /*++
00234 
00235 Routine Description:
00236   Retrieves attributes, insures positive polarity of attribute bits, returns
00237   resulting attributes in output parameter
00238 
00239 Arguments:
00240   Instance              - The FV instance whose attributes is going to be 
00241                           returned
00242   Attributes            - Output buffer which contains attributes
00243   Global                - Pointer to ESAL_FWB_GLOBAL that contains all
00244                           instance data
00245   Virtual               - Whether CPU is in virtual or physical mode
00246 
00247 Returns: 
00248   EFI_SUCCESS           - Successfully returns
00249   EFI_INVALID_PARAMETER - Instance not found
00250 
00251 --*/
00252 {
00253   EFI_FW_VOL_INSTANCE *FwhInstance = NULL;
00254   EFI_STATUS          Status;
00255 
00256   //
00257   // Find the right instance of the FVB private data
00258   //
00259   Status = GetFvbInstance (Instance, Global, &FwhInstance, Virtual);
00260   ASSERT_EFI_ERROR (Status);
00261   *Attributes = FwhInstance->VolumeHeader.Attributes;
00262 
00263   return EFI_SUCCESS;
00264 }
00265 
00266 EFI_STATUS
00267 FvbGetLbaAddress (
00268   IN  UINTN                               Instance,
00269   IN  EFI_LBA                             Lba,
00270   OUT UINTN                               *LbaAddress,
00271   OUT UINTN                               *LbaLength,
00272   OUT UINTN                               *NumOfBlocks,
00273   IN  ESAL_FWB_GLOBAL                     *Global,
00274   IN  BOOLEAN                             Virtual
00275   )
00276 /*++
00277 
00278 Routine Description:
00279   Retrieves the starting address of an LBA in an FV
00280 
00281 Arguments:
00282   Instance              - The FV instance which the Lba belongs to
00283   Lba                   - The logical block address
00284   LbaAddress            - On output, contains the physical starting address 
00285                           of the Lba
00286   LbaLength             - On output, contains the length of the block
00287   NumOfBlocks           - A pointer to a caller allocated UINTN in which the
00288                           number of consecutive blocks starting with Lba is
00289                           returned. All blocks in this range have a size of
00290                           BlockSize
00291   Global                - Pointer to ESAL_FWB_GLOBAL that contains all
00292                           instance data
00293   Virtual               - Whether CPU is in virtual or physical mode
00294 
00295 Returns: 
00296   EFI_SUCCESS           - Successfully returns
00297   EFI_INVALID_PARAMETER - Instance not found
00298 
00299 --*/
00300 {
00301   UINT32                  NumBlocks;
00302   UINT32                  BlockLength;
00303   UINTN                   Offset;
00304   EFI_LBA                 StartLba;
00305   EFI_LBA                 NextLba;
00306   EFI_FW_VOL_INSTANCE     *FwhInstance = NULL;
00307   EFI_FV_BLOCK_MAP_ENTRY  *BlockMap;
00308   EFI_STATUS              Status;
00309 
00310   //
00311   // Find the right instance of the FVB private data
00312   //
00313   Status = GetFvbInstance (Instance, Global, &FwhInstance, Virtual);
00314   ASSERT_EFI_ERROR (Status);
00315 
00316   StartLba  = 0;
00317   Offset    = 0;
00318   BlockMap  = &(FwhInstance->VolumeHeader.BlockMap[0]);
00319 
00320   //
00321   // Parse the blockmap of the FV to find which map entry the Lba belongs to
00322   //
00323   while (TRUE) {
00324     NumBlocks   = BlockMap->NumBlocks;
00325     BlockLength = BlockMap->Length;
00326 
00327     if (NumBlocks == 0 || BlockLength == 0) {
00328       return EFI_INVALID_PARAMETER;
00329     }
00330 
00331     NextLba = StartLba + NumBlocks;
00332 
00333     //
00334     // The map entry found
00335     //
00336     if (Lba >= StartLba && Lba < NextLba) {
00337       Offset = Offset + (UINTN) MultU64x32 ((Lba - StartLba), BlockLength);
00338       if (LbaAddress != NULL) {
00339         *LbaAddress = FwhInstance->FvBase[Virtual] + Offset;
00340       }
00341 
00342       if (LbaLength != NULL) {
00343         *LbaLength = BlockLength;
00344       }
00345 
00346       if (NumOfBlocks != NULL) {
00347         *NumOfBlocks = (UINTN) (NextLba - Lba);
00348       }
00349 
00350       return EFI_SUCCESS;
00351     }
00352 
00353     StartLba  = NextLba;
00354     Offset    = Offset + NumBlocks * BlockLength;
00355     BlockMap++;
00356   }
00357 }
00358 
00359 EFI_STATUS
00360 FvbReadBlock (
00361   IN UINTN                                Instance,
00362   IN EFI_LBA                              Lba,
00363   IN UINTN                                BlockOffset,
00364   IN OUT UINTN                            *NumBytes,
00365   IN UINT8                                *Buffer,
00366   IN ESAL_FWB_GLOBAL                      *Global,
00367   IN BOOLEAN                              Virtual
00368   )
00369 /*++
00370 
00371 Routine Description:
00372   Reads specified number of bytes into a buffer from the specified block
00373 
00374 Arguments:
00375   Instance              - The FV instance to be read from
00376   Lba                   - The logical block address to be read from
00377   BlockOffset           - Offset into the block at which to begin reading
00378   NumBytes              - Pointer that on input contains the total size of
00379                           the buffer. On output, it contains the total number
00380                           of bytes read
00381   Buffer                - Pointer to a caller allocated buffer that will be
00382                           used to hold the data read
00383   Global                - Pointer to ESAL_FWB_GLOBAL that contains all
00384                           instance data
00385   Virtual               - Whether CPU is in virtual or physical mode
00386 
00387 Returns: 
00388   EFI_SUCCESS           - The firmware volume was read successfully and 
00389                           contents are in Buffer
00390   EFI_BAD_BUFFER_SIZE   - Read attempted across a LBA boundary. On output,
00391                           NumBytes contains the total number of bytes returned
00392                           in Buffer
00393   EFI_ACCESS_DENIED     - The firmware volume is in the ReadDisabled state
00394   EFI_DEVICE_ERROR      - The block device is not functioning correctly and 
00395                           could not be read
00396   EFI_INVALID_PARAMETER - Instance not found, or NumBytes, Buffer are NULL
00397 
00398 --*/
00399 {
00400   EFI_FVB_ATTRIBUTES_2  Attributes;
00401   UINTN               LbaAddress;
00402   UINTN               LbaLength;
00403   EFI_STATUS          Status;
00404 
00405   //
00406   // Check for invalid conditions
00407   //
00408   if ((NumBytes == NULL) || (Buffer == NULL)) {
00409     return EFI_INVALID_PARAMETER;
00410   }
00411 
00412   if (*NumBytes == 0) {
00413     return EFI_INVALID_PARAMETER;
00414   }
00415 
00416   Status = FvbGetLbaAddress (Instance, Lba, &LbaAddress, &LbaLength, NULL, Global, Virtual);
00417   if (EFI_ERROR (Status)) {
00418     return Status;
00419   }
00420   //
00421   // Check if the FV is read enabled
00422   //
00423   FvbGetVolumeAttributes (Instance, &Attributes, Global, Virtual);
00424 
00425   if ((Attributes & EFI_FVB2_READ_STATUS) == 0) {
00426     return EFI_ACCESS_DENIED;
00427   }
00428   //
00429   // Perform boundary checks and adjust NumBytes
00430   //
00431   if (BlockOffset > LbaLength) {
00432     return EFI_INVALID_PARAMETER;
00433   }
00434 
00435   if (LbaLength < (*NumBytes + BlockOffset)) {
00436     *NumBytes = (UINT32) (LbaLength - BlockOffset);
00437     Status    = EFI_BAD_BUFFER_SIZE;
00438   }
00439 
00440   CopyMem (Buffer, (UINT8 *) (LbaAddress + BlockOffset), (UINTN) (*NumBytes));
00441 
00442   return Status;
00443 }
00444 
00445 EFI_STATUS
00446 FvbWriteBlock (
00447   IN UINTN                                Instance,
00448   IN EFI_LBA                              Lba,
00449   IN UINTN                                BlockOffset,
00450   IN OUT UINTN                            *NumBytes,
00451   IN UINT8                                *Buffer,
00452   IN ESAL_FWB_GLOBAL                      *Global,
00453   IN BOOLEAN                              Virtual
00454   )
00455 /*++
00456 
00457 Routine Description:
00458   Writes specified number of bytes from the input buffer to the block
00459 
00460 Arguments:
00461   Instance              - The FV instance to be written to
00462   Lba                   - The starting logical block index to write to
00463   BlockOffset           - Offset into the block at which to begin writing
00464   NumBytes              - Pointer that on input contains the total size of
00465                           the buffer. On output, it contains the total number
00466                           of bytes actually written
00467   Buffer                - Pointer to a caller allocated buffer that contains
00468                           the source for the write
00469   Global                - Pointer to ESAL_FWB_GLOBAL that contains all
00470                           instance data
00471   Virtual               - Whether CPU is in virtual or physical mode
00472 
00473 Returns: 
00474   EFI_SUCCESS           - The firmware volume was written successfully
00475   EFI_BAD_BUFFER_SIZE   - Write attempted across a LBA boundary. On output,
00476                           NumBytes contains the total number of bytes
00477                           actually written
00478   EFI_ACCESS_DENIED     - The firmware volume is in the WriteDisabled state
00479   EFI_DEVICE_ERROR      - The block device is not functioning correctly and 
00480                           could not be written
00481   EFI_INVALID_PARAMETER - Instance not found, or NumBytes, Buffer are NULL
00482 
00483 --*/
00484 {
00485   EFI_FVB_ATTRIBUTES_2  Attributes;
00486   UINTN               LbaAddress;
00487   UINTN               LbaLength;
00488   EFI_STATUS          Status;
00489 
00490   //
00491   // Check for invalid conditions
00492   //
00493   if ((NumBytes == NULL) || (Buffer == NULL)) {
00494     return EFI_INVALID_PARAMETER;
00495   }
00496 
00497   if (*NumBytes == 0) {
00498     return EFI_INVALID_PARAMETER;
00499   }
00500 
00501   Status = FvbGetLbaAddress (Instance, Lba, &LbaAddress, &LbaLength, NULL, Global, Virtual);
00502   if (EFI_ERROR (Status)) {
00503     return Status;
00504   }
00505   //
00506   // Check if the FV is write enabled
00507   //
00508   FvbGetVolumeAttributes (Instance, &Attributes, Global, Virtual);
00509 
00510   if ((Attributes & EFI_FVB2_WRITE_STATUS) == 0) {
00511     return EFI_ACCESS_DENIED;
00512   }
00513   //
00514   // Perform boundary checks and adjust NumBytes
00515   //
00516   if (BlockOffset > LbaLength) {
00517     return EFI_INVALID_PARAMETER;
00518   }
00519 
00520   if (LbaLength < (*NumBytes + BlockOffset)) {
00521     *NumBytes = (UINT32) (LbaLength - BlockOffset);
00522     Status    = EFI_BAD_BUFFER_SIZE;
00523   }
00524   //
00525   // Write data
00526   //
00527   CopyMem ((UINT8 *) (LbaAddress + BlockOffset), Buffer, (UINTN) (*NumBytes));
00528 
00529   return Status;
00530 }
00531 
00532 EFI_STATUS
00533 FvbEraseBlock (
00534   IN UINTN                                Instance,
00535   IN EFI_LBA                              Lba,
00536   IN ESAL_FWB_GLOBAL                      *Global,
00537   IN BOOLEAN                              Virtual
00538   )
00539 /*++
00540 
00541 Routine Description:
00542   Erases and initializes a firmware volume block
00543 
00544 Arguments:
00545   Instance              - The FV instance to be erased
00546   Lba                   - The logical block index to be erased
00547   Global                - Pointer to ESAL_FWB_GLOBAL that contains all
00548                           instance data
00549   Virtual               - Whether CPU is in virtual or physical mode
00550 
00551 Returns: 
00552   EFI_SUCCESS           - The erase request was successfully completed
00553   EFI_ACCESS_DENIED     - The firmware volume is in the WriteDisabled state
00554   EFI_DEVICE_ERROR      - The block device is not functioning correctly and 
00555                           could not be written. Firmware device may have been
00556                           partially erased
00557   EFI_INVALID_PARAMETER - Instance not found
00558 
00559 --*/
00560 {
00561 
00562   EFI_FVB_ATTRIBUTES_2  Attributes;
00563   UINTN                 LbaAddress;
00564   UINTN                 LbaLength;
00565   EFI_STATUS            Status;
00566   UINT8                 Data;
00567 
00568   //
00569   // Check if the FV is write enabled
00570   //
00571   FvbGetVolumeAttributes (Instance, &Attributes, Global, Virtual);
00572 
00573   if ((Attributes & EFI_FVB2_WRITE_STATUS) == 0) {
00574     return EFI_ACCESS_DENIED;
00575   }
00576   //
00577   // Get the starting address of the block for erase.
00578   //
00579   Status = FvbGetLbaAddress (Instance, Lba, &LbaAddress, &LbaLength, NULL, Global, Virtual);
00580 
00581   if (EFI_ERROR (Status)) {
00582     return Status;
00583   }
00584 
00585   if ((Attributes & EFI_FVB2_ERASE_POLARITY) != 0) {
00586     Data = 0xFF;
00587   } else {
00588     Data = 0x0;
00589   }
00590 
00591   SetMem ((UINT8 *) LbaAddress, LbaLength, Data);
00592 
00593   return EFI_SUCCESS;
00594 }
00595 
00596 EFI_STATUS
00597 FvbSetVolumeAttributes (
00598   IN UINTN                                Instance,
00599   IN OUT EFI_FVB_ATTRIBUTES_2             *Attributes,
00600   IN ESAL_FWB_GLOBAL                      *Global,
00601   IN BOOLEAN                              Virtual
00602   )
00603 /*++
00604 
00605 Routine Description:
00606   Modifies the current settings of the firmware volume according to the 
00607   input parameter, and returns the new setting of the volume
00608 
00609 Arguments:
00610   Instance              - The FV instance whose attributes is going to be 
00611                           modified
00612   Attributes            - On input, it is a pointer to EFI_FVB_ATTRIBUTES_2 
00613                           containing the desired firmware volume settings.
00614                           On successful return, it contains the new settings
00615                           of the firmware volume
00616   Global                - Pointer to ESAL_FWB_GLOBAL that contains all
00617                           instance data
00618   Virtual               - Whether CPU is in virtual or physical mode
00619 
00620 Returns: 
00621   EFI_SUCCESS           - Successfully returns
00622   EFI_ACCESS_DENIED     - The volume setting is locked and cannot be modified
00623   EFI_INVALID_PARAMETER - Instance not found, or The attributes requested are
00624                           in conflict with the capabilities as declared in the
00625                           firmware volume header
00626 
00627 --*/
00628 {
00629   EFI_FW_VOL_INSTANCE   *FwhInstance = NULL;
00630   EFI_FVB_ATTRIBUTES_2  OldAttributes;
00631   EFI_FVB_ATTRIBUTES_2  *AttribPtr;
00632   UINT32                Capabilities;
00633   UINT32                OldStatus;
00634   UINT32                NewStatus;
00635   EFI_STATUS            Status;
00636   EFI_FVB_ATTRIBUTES_2  UnchangedAttributes;
00637 
00638 
00639   //
00640   // Find the right instance of the FVB private data
00641   //
00642   Status = GetFvbInstance (Instance, Global, &FwhInstance, Virtual);
00643   ASSERT_EFI_ERROR (Status);
00644 
00645   AttribPtr     = (EFI_FVB_ATTRIBUTES_2 *) &(FwhInstance->VolumeHeader.Attributes);
00646   OldAttributes = *AttribPtr;
00647   Capabilities  = OldAttributes & (EFI_FVB2_READ_DISABLED_CAP | \
00648                                    EFI_FVB2_READ_ENABLED_CAP | \
00649                                    EFI_FVB2_WRITE_DISABLED_CAP | \
00650                                    EFI_FVB2_WRITE_ENABLED_CAP | \
00651                                    EFI_FVB2_LOCK_CAP \
00652                                    );
00653 
00654   OldStatus     = OldAttributes & EFI_FVB2_STATUS;
00655   NewStatus     = *Attributes & EFI_FVB2_STATUS;
00656   UnchangedAttributes = EFI_FVB2_READ_DISABLED_CAP  | \
00657                         EFI_FVB2_READ_ENABLED_CAP   | \
00658                         EFI_FVB2_WRITE_DISABLED_CAP | \
00659                         EFI_FVB2_WRITE_ENABLED_CAP  | \
00660                         EFI_FVB2_LOCK_CAP           | \
00661                         EFI_FVB2_STICKY_WRITE       | \
00662                         EFI_FVB2_MEMORY_MAPPED      | \
00663                         EFI_FVB2_ERASE_POLARITY     | \
00664                         EFI_FVB2_READ_LOCK_CAP      | \
00665                         EFI_FVB2_WRITE_LOCK_CAP     | \
00666                         EFI_FVB2_ALIGNMENT;
00667 
00668   //
00669   // Some attributes of FV is read only can *not* be set
00670   //
00671   if ((OldAttributes & UnchangedAttributes) ^ (*Attributes & UnchangedAttributes)) {
00672     return EFI_INVALID_PARAMETER;
00673   }
00674 
00675   //
00676   // If firmware volume is locked, no status bit can be updated
00677   //
00678   if (OldAttributes & EFI_FVB2_LOCK_STATUS) {
00679     if (OldStatus ^ NewStatus) {
00680       return EFI_ACCESS_DENIED;
00681     }
00682   }
00683   //
00684   // Test read disable
00685   //
00686   if ((Capabilities & EFI_FVB2_READ_DISABLED_CAP) == 0) {
00687     if ((NewStatus & EFI_FVB2_READ_STATUS) == 0) {
00688       return EFI_INVALID_PARAMETER;
00689     }
00690   }
00691   //
00692   // Test read enable
00693   //
00694   if ((Capabilities & EFI_FVB2_READ_ENABLED_CAP) == 0) {
00695     if (NewStatus & EFI_FVB2_READ_STATUS) {
00696       return EFI_INVALID_PARAMETER;
00697     }
00698   }
00699   //
00700   // Test write disable
00701   //
00702   if ((Capabilities & EFI_FVB2_WRITE_DISABLED_CAP) == 0) {
00703     if ((NewStatus & EFI_FVB2_WRITE_STATUS) == 0) {
00704       return EFI_INVALID_PARAMETER;
00705     }
00706   }
00707   //
00708   // Test write enable
00709   //
00710   if ((Capabilities & EFI_FVB2_WRITE_ENABLED_CAP) == 0) {
00711     if (NewStatus & EFI_FVB2_WRITE_STATUS) {
00712       return EFI_INVALID_PARAMETER;
00713     }
00714   }
00715   //
00716   // Test lock
00717   //
00718   if ((Capabilities & EFI_FVB2_LOCK_CAP) == 0) {
00719     if (NewStatus & EFI_FVB2_LOCK_STATUS) {
00720       return EFI_INVALID_PARAMETER;
00721     }
00722   }
00723 
00724   *AttribPtr  = (*AttribPtr) & (0xFFFFFFFF & (~EFI_FVB2_STATUS));
00725   *AttribPtr  = (*AttribPtr) | NewStatus;
00726   *Attributes = *AttribPtr;
00727 
00728   return EFI_SUCCESS;
00729 }
00730 //
00731 // FVB protocol APIs
00732 //
00733 EFI_STATUS
00734 EFIAPI
00735 FvbProtocolGetPhysicalAddress (
00736   IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL     *This,
00737   OUT EFI_PHYSICAL_ADDRESS                        *Address
00738   )
00739 /*++
00740 
00741 Routine Description:
00742 
00743   Retrieves the physical address of the device.
00744 
00745 Arguments:
00746 
00747   This                  - Calling context
00748   Address               - Output buffer containing the address.
00749 
00750 Returns:
00751 
00752 Returns: 
00753   EFI_SUCCESS           - Successfully returns
00754 
00755 --*/
00756 {
00757   EFI_FW_VOL_BLOCK_DEVICE *FvbDevice;
00758 
00759   FvbDevice = FVB_DEVICE_FROM_THIS (This);
00760 
00761   return FvbGetPhysicalAddress (FvbDevice->Instance, Address, mFvbModuleGlobal, EfiGoneVirtual ());
00762 }
00763 
00764 EFI_STATUS
00765 EFIAPI
00766 FvbProtocolGetBlockSize (
00767   IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL     *This,
00768   IN  EFI_LBA                                     Lba,
00769   OUT UINTN                                       *BlockSize,
00770   OUT UINTN                                       *NumOfBlocks
00771   )
00772 /*++
00773 
00774 Routine Description:
00775   Retrieve the size of a logical block
00776 
00777 Arguments:
00778   This                  - Calling context
00779   Lba                   - Indicates which block to return the size for.
00780   BlockSize             - A pointer to a caller allocated UINTN in which
00781                           the size of the block is returned
00782   NumOfBlocks           - a pointer to a caller allocated UINTN in which the
00783                           number of consecutive blocks starting with Lba is
00784                           returned. All blocks in this range have a size of
00785                           BlockSize
00786 
00787 Returns: 
00788   EFI_SUCCESS           - The firmware volume was read successfully and 
00789                           contents are in Buffer
00790 
00791 --*/
00792 {
00793   EFI_FW_VOL_BLOCK_DEVICE *FvbDevice;
00794 
00795   FvbDevice = FVB_DEVICE_FROM_THIS (This);
00796 
00797   return FvbGetLbaAddress (
00798           FvbDevice->Instance,
00799           Lba,
00800           NULL,
00801           BlockSize,
00802           NumOfBlocks,
00803           mFvbModuleGlobal,
00804           EfiGoneVirtual ()
00805           );
00806 }
00807 
00808 EFI_STATUS
00809 EFIAPI
00810 FvbProtocolGetAttributes (
00811   IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL     *This,
00812   OUT EFI_FVB_ATTRIBUTES_2                        *Attributes
00813   )
00814 /*++
00815 
00816 Routine Description:
00817     Retrieves Volume attributes.  No polarity translations are done.
00818 
00819 Arguments:
00820     This                - Calling context
00821     Attributes          - output buffer which contains attributes
00822 
00823 Returns: 
00824   EFI_SUCCESS           - Successfully returns
00825 
00826 --*/
00827 {
00828   EFI_FW_VOL_BLOCK_DEVICE *FvbDevice;
00829 
00830   FvbDevice = FVB_DEVICE_FROM_THIS (This);
00831 
00832   return FvbGetVolumeAttributes (FvbDevice->Instance, Attributes, mFvbModuleGlobal, EfiGoneVirtual ());
00833 }
00834 
00835 EFI_STATUS
00836 EFIAPI
00837 FvbProtocolSetAttributes (
00838   IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL     *This,
00839   IN OUT EFI_FVB_ATTRIBUTES_2                     *Attributes
00840   )
00841 /*++
00842 
00843 Routine Description:
00844   Sets Volume attributes. No polarity translations are done.
00845 
00846 Arguments:
00847   This                  - Calling context
00848   Attributes            - output buffer which contains attributes
00849 
00850 Returns: 
00851   EFI_SUCCESS           - Successfully returns
00852 
00853 --*/
00854 {
00855   EFI_FW_VOL_BLOCK_DEVICE *FvbDevice;
00856 
00857   FvbDevice = FVB_DEVICE_FROM_THIS (This);
00858 
00859   return FvbSetVolumeAttributes (FvbDevice->Instance, Attributes, mFvbModuleGlobal, EfiGoneVirtual ());
00860 }
00861 
00862 EFI_STATUS
00863 EFIAPI
00864 FvbProtocolEraseBlocks (
00865   IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL    *This,
00866   ...  
00867   )
00868 /*++
00869 
00870 Routine Description:
00871 
00872   The EraseBlock() function erases one or more blocks as denoted by the 
00873   variable argument list. The entire parameter list of blocks must be verified
00874   prior to erasing any blocks.  If a block is requested that does not exist 
00875   within the associated firmware volume (it has a larger index than the last 
00876   block of the firmware volume), the EraseBlock() function must return
00877   EFI_INVALID_PARAMETER without modifying the contents of the firmware volume.
00878 
00879 Arguments:
00880   This                  - Calling context
00881   ...                   - Starting LBA followed by Number of Lba to erase. 
00882                           a -1 to terminate the list.
00883 
00884 Returns: 
00885   EFI_SUCCESS           - The erase request was successfully completed
00886   EFI_ACCESS_DENIED     - The firmware volume is in the WriteDisabled state
00887   EFI_DEVICE_ERROR      - The block device is not functioning correctly and 
00888                           could not be written. Firmware device may have been
00889                           partially erased
00890 
00891 --*/
00892 {
00893   EFI_FW_VOL_BLOCK_DEVICE *FvbDevice;
00894   EFI_FW_VOL_INSTANCE     *FwhInstance = NULL;
00895   UINTN                   NumOfBlocks;
00896   VA_LIST                 args;
00897   EFI_LBA                 StartingLba;
00898   UINTN                   NumOfLba;
00899   EFI_STATUS              Status;
00900 
00901   FvbDevice = FVB_DEVICE_FROM_THIS (This);
00902 
00903   Status    = GetFvbInstance (FvbDevice->Instance, mFvbModuleGlobal, &FwhInstance, EfiGoneVirtual ());
00904   ASSERT_EFI_ERROR (Status);
00905 
00906   NumOfBlocks = FwhInstance->NumOfBlocks;
00907 
00908   VA_START (args, This);
00909 
00910   do {
00911     StartingLba = VA_ARG (args, EFI_LBA);
00912     if (StartingLba == EFI_LBA_LIST_TERMINATOR) {
00913       break;
00914     }
00915 
00916     NumOfLba = VA_ARG (args, UINT32);
00917 
00918     //
00919     // Check input parameters
00920     //
00921     if (NumOfLba == 0) {
00922       VA_END (args);
00923       return EFI_INVALID_PARAMETER;
00924     }
00925 
00926     if ((StartingLba + NumOfLba) > NumOfBlocks) {
00927       return EFI_INVALID_PARAMETER;
00928     }
00929   } while (1);
00930 
00931   VA_END (args);
00932 
00933   VA_START (args, This);
00934   do {
00935     StartingLba = VA_ARG (args, EFI_LBA);
00936     if (StartingLba == EFI_LBA_LIST_TERMINATOR) {
00937       break;
00938     }
00939 
00940     NumOfLba = VA_ARG (args, UINT32);
00941 
00942     while (NumOfLba > 0) {
00943       Status = FvbEraseBlock (FvbDevice->Instance, StartingLba, mFvbModuleGlobal, EfiGoneVirtual ());
00944       if (EFI_ERROR (Status)) {
00945         VA_END (args);
00946         return Status;
00947       }
00948 
00949       StartingLba++;
00950       NumOfLba--;
00951     }
00952 
00953   } while (1);
00954 
00955   VA_END (args);
00956 
00957   return EFI_SUCCESS;
00958 }
00959 
00960 EFI_STATUS
00961 EFIAPI
00962 FvbProtocolWrite (
00963   IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL     *This,
00964   IN EFI_LBA                                      Lba,
00965   IN UINTN                                        Offset,
00966   IN OUT UINTN                                    *NumBytes,
00967   IN UINT8                                        *Buffer
00968   )
00969 /*++
00970 
00971 Routine Description:
00972 
00973   Writes data beginning at Lba:Offset from FV. The write terminates either
00974   when *NumBytes of data have been written, or when a block boundary is
00975   reached.  *NumBytes is updated to reflect the actual number of bytes
00976   written. The write opertion does not include erase. This routine will
00977   attempt to write only the specified bytes. If the writes do not stick,
00978   it will return an error.
00979 
00980 Arguments:
00981   This                  - Calling context
00982   Lba                   - Block in which to begin write
00983   Offset                - Offset in the block at which to begin write
00984   NumBytes              - On input, indicates the requested write size. On
00985                           output, indicates the actual number of bytes written
00986   Buffer                - Buffer containing source data for the write.
00987 
00988 Returns: 
00989   EFI_SUCCESS           - The firmware volume was written successfully
00990   EFI_BAD_BUFFER_SIZE   - Write attempted across a LBA boundary. On output,
00991                           NumBytes contains the total number of bytes
00992                           actually written
00993   EFI_ACCESS_DENIED     - The firmware volume is in the WriteDisabled state
00994   EFI_DEVICE_ERROR      - The block device is not functioning correctly and 
00995                           could not be written
00996   EFI_INVALID_PARAMETER - NumBytes or Buffer are NULL
00997 
00998 --*/
00999 {
01000 
01001   EFI_FW_VOL_BLOCK_DEVICE *FvbDevice;
01002 
01003   FvbDevice = FVB_DEVICE_FROM_THIS (This);
01004 
01005   return FvbWriteBlock (FvbDevice->Instance, Lba, Offset, NumBytes, Buffer, mFvbModuleGlobal, EfiGoneVirtual ());
01006 }
01007 
01008 EFI_STATUS
01009 EFIAPI
01010 FvbProtocolRead (
01011   IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL     *This,
01012   IN EFI_LBA                                      Lba,
01013   IN UINTN                                        Offset,
01014   IN OUT UINTN                                    *NumBytes,
01015   IN UINT8                                        *Buffer
01016   )
01017 /*++
01018 
01019 Routine Description:
01020 
01021   Reads data beginning at Lba:Offset from FV. The Read terminates either
01022   when *NumBytes of data have been read, or when a block boundary is
01023   reached.  *NumBytes is updated to reflect the actual number of bytes
01024   written. The write opertion does not include erase. This routine will
01025   attempt to write only the specified bytes. If the writes do not stick,
01026   it will return an error.
01027 
01028 Arguments:
01029   This                  - Calling context
01030   Lba                   - Block in which to begin Read
01031   Offset                - Offset in the block at which to begin Read
01032   NumBytes              - On input, indicates the requested write size. On
01033                           output, indicates the actual number of bytes Read
01034   Buffer                - Buffer containing source data for the Read.
01035 
01036 Returns: 
01037   EFI_SUCCESS           - The firmware volume was read successfully and 
01038                           contents are in Buffer
01039   EFI_BAD_BUFFER_SIZE   - Read attempted across a LBA boundary. On output,
01040                           NumBytes contains the total number of bytes returned
01041                           in Buffer
01042   EFI_ACCESS_DENIED     - The firmware volume is in the ReadDisabled state
01043   EFI_DEVICE_ERROR      - The block device is not functioning correctly and 
01044                           could not be read
01045   EFI_INVALID_PARAMETER - NumBytes or Buffer are NULL
01046 
01047 --*/
01048 {
01049 
01050   EFI_FW_VOL_BLOCK_DEVICE *FvbDevice;
01051 
01052   FvbDevice = FVB_DEVICE_FROM_THIS (This);
01053 
01054   return FvbReadBlock (FvbDevice->Instance, Lba, Offset, NumBytes, Buffer, mFvbModuleGlobal, EfiGoneVirtual ());
01055 }
01056 EFI_STATUS
01057 ValidateFvHeader (
01058   EFI_FIRMWARE_VOLUME_HEADER            *FwVolHeader
01059   )
01060 /*++
01061 
01062 Routine Description:
01063   Check the integrity of firmware volume header
01064 
01065 Arguments:
01066   FwVolHeader           - A pointer to a firmware volume header
01067 
01068 Returns: 
01069   EFI_SUCCESS           - The firmware volume is consistent
01070   EFI_NOT_FOUND         - The firmware volume has corrupted. So it is not an FV
01071 
01072 --*/
01073 {
01074   UINT16  *Ptr;
01075   UINT16  HeaderLength;
01076   UINT16  Checksum;
01077 
01078   //
01079   // Verify the header revision, header signature, length
01080   // Length of FvBlock cannot be 2**64-1
01081   // HeaderLength cannot be an odd number
01082   //
01083   if ((FwVolHeader->Revision != EFI_FVH_REVISION) ||
01084       (FwVolHeader->Signature != EFI_FVH_SIGNATURE) ||
01085       (FwVolHeader->FvLength == ((UINTN) -1)) ||
01086       ((FwVolHeader->HeaderLength & 0x01) != 0)
01087       ) {
01088     return EFI_NOT_FOUND;
01089   }
01090   //
01091   // Verify the header checksum
01092   //
01093   HeaderLength  = (UINT16) (FwVolHeader->HeaderLength / 2);
01094   Ptr           = (UINT16 *) FwVolHeader;
01095   Checksum      = 0;
01096   while (HeaderLength > 0) {
01097     Checksum = Checksum + (*Ptr);
01098     HeaderLength--;
01099     Ptr++;
01100   }
01101 
01102   if (Checksum != 0) {
01103     return EFI_NOT_FOUND;
01104   }
01105 
01106   return EFI_SUCCESS;
01107 }
01108 
01109 EFI_STATUS
01110 EFIAPI
01111 FvbInitialize (
01112   IN EFI_HANDLE         ImageHandle,
01113   IN EFI_SYSTEM_TABLE   *SystemTable
01114   )
01115 /*++
01116 
01117 Routine Description:
01118   This function does common initialization for FVB services
01119 
01120 Arguments:
01121 
01122 Returns:
01123 
01124 --*/
01125 {
01126   EFI_STATUS                          Status;
01127   EFI_FW_VOL_INSTANCE                 *FwhInstance = NULL;
01128   EFI_FIRMWARE_VOLUME_HEADER          *FwVolHeader;
01129   EFI_DXE_SERVICES                    *DxeServices;
01130   EFI_GCD_MEMORY_SPACE_DESCRIPTOR     Descriptor;
01131   UINT32                              BufferSize;
01132   EFI_FV_BLOCK_MAP_ENTRY              *PtrBlockMapEntry;
01133   EFI_HANDLE                          FwbHandle;
01134   EFI_FW_VOL_BLOCK_DEVICE             *FvbDevice;
01135   EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL  *OldFwbInterface;
01136   EFI_DEVICE_PATH_PROTOCOL            *TempFwbDevicePath;
01137   FV_DEVICE_PATH                      TempFvbDevicePathData;
01138   UINT32                              MaxLbaSize;
01139   EFI_PHYSICAL_ADDRESS                BaseAddress;
01140   UINT64                              Length;
01141   UINTN                               NumOfBlocks;
01142   EFI_PEI_HOB_POINTERS                FvHob;
01143 
01144    //
01145   // Get the DXE services table
01146   //
01147   DxeServices = gDS;
01148 
01149   //
01150   // Allocate runtime services data for global variable, which contains
01151   // the private data of all firmware volume block instances
01152   //
01153   Status = gBS->AllocatePool (
01154                   EfiRuntimeServicesData,
01155                   sizeof (ESAL_FWB_GLOBAL),
01156                   (VOID**) &mFvbModuleGlobal
01157                   );
01158   ASSERT_EFI_ERROR (Status);
01159 
01160   //
01161   // Calculate the total size for all firmware volume block instances
01162   //
01163   BufferSize            = 0;
01164 
01165   FvHob.Raw = GetHobList ();
01166   while ((FvHob.Raw = GetNextHob (EFI_HOB_TYPE_FV, FvHob.Raw)) != NULL) {
01167     BaseAddress = FvHob.FirmwareVolume->BaseAddress;
01168     Length      = FvHob.FirmwareVolume->Length;
01169     //
01170     // Check if it is a "real" flash
01171     //
01172     Status = DxeServices->GetMemorySpaceDescriptor (
01173                             BaseAddress,
01174                             &Descriptor
01175                             );
01176     if (EFI_ERROR (Status)) {
01177       break;
01178     }
01179 
01180     if (Descriptor.GcdMemoryType != EfiGcdMemoryTypeMemoryMappedIo) {
01181       FvHob.Raw = GET_NEXT_HOB (FvHob);
01182       continue;
01183     }
01184 
01185     FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *) (UINTN) BaseAddress;
01186     Status      = ValidateFvHeader (FwVolHeader);
01187     if (EFI_ERROR (Status)) {
01188       //
01189       // Get FvbInfo
01190       //
01191       Status = GetFvbInfo (Length, &FwVolHeader);
01192       if (EFI_ERROR (Status)) {
01193         FvHob.Raw = GET_NEXT_HOB (FvHob);
01194         continue;
01195       }
01196     }
01197 
01198     BufferSize += (sizeof (EFI_FW_VOL_INSTANCE) + FwVolHeader->HeaderLength - sizeof (EFI_FIRMWARE_VOLUME_HEADER));
01199     FvHob.Raw = GET_NEXT_HOB (FvHob);
01200   }
01201 
01202   //
01203   // Only need to allocate once. There is only one copy of physical memory for
01204   // the private data of each FV instance. But in virtual mode or in physical
01205   // mode, the address of the the physical memory may be different.
01206   //
01207   Status = gBS->AllocatePool (
01208                   EfiRuntimeServicesData,
01209                   BufferSize,
01210                   (VOID**) &mFvbModuleGlobal->FvInstance[FVB_PHYSICAL]
01211                   );
01212   ASSERT_EFI_ERROR (Status);
01213 
01214   //
01215   // Make a virtual copy of the FvInstance pointer.
01216   //
01217   FwhInstance = mFvbModuleGlobal->FvInstance[FVB_PHYSICAL];
01218   mFvbModuleGlobal->FvInstance[FVB_VIRTUAL] = FwhInstance;
01219 
01220   mFvbModuleGlobal->NumFv                   = 0;
01221   MaxLbaSize = 0;
01222 
01223   FvHob.Raw = GetHobList ();
01224   while (NULL != (FvHob.Raw = GetNextHob (EFI_HOB_TYPE_FV, FvHob.Raw))) {
01225     BaseAddress = FvHob.FirmwareVolume->BaseAddress;
01226     Length      = FvHob.FirmwareVolume->Length;
01227     //
01228     // Check if it is a "real" flash
01229     //
01230     Status = DxeServices->GetMemorySpaceDescriptor (
01231                             BaseAddress,
01232                             &Descriptor
01233                             );
01234     if (EFI_ERROR (Status)) {
01235       break;
01236     }
01237 
01238     if (Descriptor.GcdMemoryType != EfiGcdMemoryTypeMemoryMappedIo) {
01239       FvHob.Raw = GET_NEXT_HOB (FvHob);
01240       continue;
01241     }
01242 
01243     FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *) (UINTN) BaseAddress;
01244     Status      = ValidateFvHeader (FwVolHeader);
01245     if (EFI_ERROR (Status)) {
01246       //
01247       // Get FvbInfo to provide in FwhInstance.
01248       //
01249       Status = GetFvbInfo (Length, &FwVolHeader);
01250       if (EFI_ERROR (Status)) {
01251         FvHob.Raw = GET_NEXT_HOB (FvHob);
01252         continue;
01253       }
01254       //
01255       //  Write healthy FV header back.
01256       //
01257       CopyMem (
01258         (VOID *) (UINTN) BaseAddress,
01259         (VOID *) FwVolHeader,
01260         FwVolHeader->HeaderLength
01261         );
01262     }
01263 
01264     FwhInstance->FvBase[FVB_PHYSICAL] = (UINTN) BaseAddress;
01265     FwhInstance->FvBase[FVB_VIRTUAL]  = (UINTN) BaseAddress;
01266 
01267     CopyMem ((UINTN *) &(FwhInstance->VolumeHeader), (UINTN *) FwVolHeader, FwVolHeader->HeaderLength);
01268     FwVolHeader = &(FwhInstance->VolumeHeader);
01269     EfiInitializeLock (&(FwhInstance->FvbDevLock), TPL_HIGH_LEVEL);
01270 
01271     NumOfBlocks = 0;
01272 
01273     for (PtrBlockMapEntry = FwVolHeader->BlockMap; PtrBlockMapEntry->NumBlocks != 0; PtrBlockMapEntry++) {
01274       //
01275       // Get the maximum size of a block. The size will be used to allocate
01276       // buffer for Scratch space, the intermediate buffer for FVB extension
01277       // protocol
01278       //
01279       if (MaxLbaSize < PtrBlockMapEntry->Length) {
01280         MaxLbaSize = PtrBlockMapEntry->Length;
01281       }
01282 
01283       NumOfBlocks = NumOfBlocks + PtrBlockMapEntry->NumBlocks;
01284     }
01285     //
01286     // The total number of blocks in the FV.
01287     //
01288     FwhInstance->NumOfBlocks = NumOfBlocks;
01289 
01290     //
01291     // Add a FVB Protocol Instance
01292     //
01293     Status = gBS->AllocatePool (
01294                     EfiRuntimeServicesData,
01295                     sizeof (EFI_FW_VOL_BLOCK_DEVICE),
01296                     (VOID**) &FvbDevice
01297                     );
01298     ASSERT_EFI_ERROR (Status);
01299 
01300     CopyMem (FvbDevice, &mFvbDeviceTemplate, sizeof (EFI_FW_VOL_BLOCK_DEVICE));
01301 
01302     FvbDevice->Instance = mFvbModuleGlobal->NumFv;
01303     mFvbModuleGlobal->NumFv++;
01304 
01305     //
01306     // Set up the devicepath
01307     //
01308     FvbDevice->DevicePath.MemMapDevPath.StartingAddress = BaseAddress;
01309     FvbDevice->DevicePath.MemMapDevPath.EndingAddress   = BaseAddress + (FwVolHeader->FvLength - 1);
01310 
01311     //
01312     // Find a handle with a matching device path that has supports FW Block protocol
01313     //
01314     TempFwbDevicePath = (EFI_DEVICE_PATH_PROTOCOL *) &TempFvbDevicePathData;
01315     CopyMem (TempFwbDevicePath, &FvbDevice->DevicePath, sizeof (FV_DEVICE_PATH));
01316     Status = gBS->LocateDevicePath (&gEfiFirmwareVolumeBlockProtocolGuid, &TempFwbDevicePath, &FwbHandle);
01317     if (EFI_ERROR (Status)) {
01318       //
01319       // LocateDevicePath fails so install a new interface and device path
01320       //
01321       FwbHandle = NULL;
01322       Status = gBS->InstallMultipleProtocolInterfaces (
01323                       &FwbHandle,
01324                       &gEfiFirmwareVolumeBlockProtocolGuid,
01325                       &FvbDevice->FwVolBlockInstance,
01326                       &gEfiDevicePathProtocolGuid,
01327                       &FvbDevice->DevicePath,
01328                       NULL
01329                       );
01330       ASSERT_EFI_ERROR (Status);
01331     } else if (IsDevicePathEnd (TempFwbDevicePath)) {
01332       //
01333       // Device allready exists, so reinstall the FVB protocol
01334       //
01335       Status = gBS->HandleProtocol (
01336                       FwbHandle,
01337                       &gEfiFirmwareVolumeBlockProtocolGuid,
01338                       (VOID**)&OldFwbInterface
01339                       );
01340       ASSERT_EFI_ERROR (Status);
01341 
01342       Status = gBS->ReinstallProtocolInterface (
01343                       FwbHandle,
01344                       &gEfiFirmwareVolumeBlockProtocolGuid,
01345                       OldFwbInterface,
01346                       &FvbDevice->FwVolBlockInstance
01347                       );
01348       ASSERT_EFI_ERROR (Status);
01349 
01350     } else {
01351       //
01352       // There was a FVB protocol on an End Device Path node
01353       //
01354       ASSERT (FALSE);
01355     }
01356 
01357     FwhInstance = (EFI_FW_VOL_INSTANCE *)
01358       (
01359         (UINTN) ((UINT8 *) FwhInstance) + FwVolHeader->HeaderLength +
01360           (sizeof (EFI_FW_VOL_INSTANCE) - sizeof (EFI_FIRMWARE_VOLUME_HEADER))
01361       );
01362 
01363     FvHob.Raw = GET_NEXT_HOB (FvHob);
01364   }
01365 
01366   return EFI_SUCCESS;
01367 }
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Defines