Home | History | Annotate | Download | only in Ia32
      1 /*++
      2 
      3 Copyright (c) 2004 - 2008, Intel Corporation. All rights reserved.<BR>
      4 This program and the accompanying materials
      5 are licensed and made available under the terms and conditions of the BSD License
      6 which accompanies this distribution.  The full text of the license may be found at
      7 http://opensource.org/licenses/bsd-license.php
      8 
      9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     11 
     12 Module Name:
     13 
     14     Fvb.c
     15 
     16 Abstract:
     17 
     18   Firmware Volume Block Protocol Runtime Abstraction
     19 
     20   mFvbEntry is an array of Handle Fvb pairs. The Fvb Lib Instance matches the
     21   index in the mFvbEntry array. This should be the same sequence as the FVB's
     22   were described in the HOB. We have to remember the handle so we can tell if
     23   the protocol has been reinstalled and it needs updateing.
     24 
     25   If you are using any of these lib functions.you must first call FvbInitialize ().
     26 
     27 Key:
     28   FVB - Firmware Volume Block
     29 
     30 --*/
     31 
     32 #include "Tiano.h"
     33 #include "EfiRuntimeLib.h"
     34 #include EFI_PROTOCOL_DEFINITION (FirmwareVolumeBlock)
     35 #include EFI_PROTOCOL_DEFINITION (FvbExtension)
     36 
     37 //
     38 // Lib will ASSERT if more FVB devices than this are added to the system.
     39 //
     40 UINTN             mFvbCount;
     41 VOID              *mFvbRegistration;
     42 VOID              *mFvbExtRegistration;
     43 //static EFI_EVENT  mEfiFvbVirtualNotifyEvent;
     44 BOOLEAN           gEfiFvbInitialized = FALSE;
     45 EFI_EVENT         mFvbEvent;
     46 
     47 BOOLEAN
     48 IsMemoryRuntime (
     49   IN VOID   *Address
     50   )
     51 /*++
     52 
     53 Routine Description:
     54   Check whether an address is runtime memory or not.
     55 
     56 Arguments:
     57 
     58   Address - The Address being checked.
     59 
     60 Returns:
     61   TRUE    - The address is runtime memory.
     62   FALSE   - The address is not runtime memory.
     63 
     64 --*/
     65 {
     66   EFI_STATUS                           Status;
     67   UINT8                                TmpMemoryMap[1];
     68   UINTN                                MapKey;
     69   UINTN                                DescriptorSize;
     70   UINT32                               DescriptorVersion;
     71   UINTN                                MemoryMapSize;
     72   EFI_MEMORY_DESCRIPTOR                *MemoryMap;
     73   EFI_MEMORY_DESCRIPTOR                *MemoryMapPtr;
     74   BOOLEAN                              IsRuntime;
     75   UINTN                                Index;
     76 
     77   IsRuntime = FALSE;
     78 
     79   //
     80   // Get System MemoryMapSize
     81   //
     82   MemoryMapSize = 1;
     83   Status = gBS->GetMemoryMap (
     84                   &MemoryMapSize,
     85                   (EFI_MEMORY_DESCRIPTOR *)TmpMemoryMap,
     86                   &MapKey,
     87                   &DescriptorSize,
     88                   &DescriptorVersion
     89                   );
     90   ASSERT (Status == EFI_BUFFER_TOO_SMALL);
     91   //
     92   // Enlarge space here, because we will allocate pool now.
     93   //
     94   MemoryMapSize += EFI_PAGE_SIZE;
     95   Status = gBS->AllocatePool (
     96                   EfiBootServicesData,
     97                   MemoryMapSize,
     98                   (VOID**)&MemoryMap
     99                   );
    100   ASSERT_EFI_ERROR (Status);
    101 
    102   //
    103   // Get System MemoryMap
    104   //
    105   Status = gBS->GetMemoryMap (
    106                   &MemoryMapSize,
    107                   MemoryMap,
    108                   &MapKey,
    109                   &DescriptorSize,
    110                   &DescriptorVersion
    111                   );
    112   ASSERT_EFI_ERROR (Status);
    113 
    114   MemoryMapPtr = MemoryMap;
    115   //
    116   // Search the request Address
    117   //
    118   for (Index = 0; Index < (MemoryMapSize / DescriptorSize); Index++) {
    119     if (((EFI_PHYSICAL_ADDRESS)(UINTN)Address >= MemoryMap->PhysicalStart) &&
    120         ((EFI_PHYSICAL_ADDRESS)(UINTN)Address < MemoryMap->PhysicalStart
    121                                               + LShiftU64 (MemoryMap->NumberOfPages, EFI_PAGE_SHIFT))) {
    122       //
    123       // Found it
    124       //
    125       if (MemoryMap->Attribute & EFI_MEMORY_RUNTIME) {
    126         IsRuntime = TRUE;
    127       }
    128       break;
    129     }
    130     //
    131     // Get next item
    132     //
    133     MemoryMap = (EFI_MEMORY_DESCRIPTOR *)((UINTN)MemoryMap + DescriptorSize);
    134   }
    135 
    136   //
    137   // Done
    138   //
    139   gBS->FreePool (MemoryMapPtr);
    140 
    141   return IsRuntime;
    142 }
    143 
    144 VOID
    145 EFIAPI
    146 FvbNotificationFunction (
    147   IN  EFI_EVENT       Event,
    148   IN  VOID            *Context
    149   )
    150 /*++
    151 
    152 Routine Description:
    153   Update mFvbEntry. Add new entry, or update existing entry if Fvb protocol is
    154   reinstalled.
    155 
    156 Arguments:
    157 
    158   Event   - The Event that is being processed
    159 
    160   Context - Event Context
    161 
    162 Returns:
    163   None
    164 
    165 --*/
    166 {
    167   EFI_STATUS                         Status;
    168   UINTN                              BufferSize;
    169   EFI_HANDLE                         Handle;
    170   UINTN                              Index;
    171   UINTN                              UpdateIndex;
    172   EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb;
    173   EFI_FVB_EXTENSION_PROTOCOL         *FvbExtension;
    174 
    175   while (TRUE) {
    176     BufferSize = sizeof (Handle);
    177     Status = gBS->LocateHandle (
    178                     ByRegisterNotify,
    179                     &gEfiFirmwareVolumeBlockProtocolGuid,
    180                     mFvbRegistration,
    181                     &BufferSize,
    182                     &Handle
    183                     );
    184     if (EFI_ERROR (Status)) {
    185       //
    186       // Exit Path of While Loop....
    187       //
    188       break;
    189     }
    190 
    191     UpdateIndex = MAX_FVB_COUNT;
    192     for (Index = 0; Index < mFvbCount; Index++) {
    193       if (mFvbEntry[Index].Handle == Handle) {
    194         //
    195         //  If the handle is already in the table just update the protocol
    196         //
    197         UpdateIndex = Index;
    198         break;
    199       }
    200     }
    201 
    202     if (UpdateIndex == MAX_FVB_COUNT) {
    203       //
    204       // Use the next free slot for a new entry
    205       //
    206       UpdateIndex                   = mFvbCount;
    207     }
    208     //
    209     // The array does not have enough entries
    210     //
    211     ASSERT (UpdateIndex < MAX_FVB_COUNT);
    212 
    213     //
    214     //  Get the interface pointer and if it's ours, skip it.
    215     //  We check Runtime here, because it has no reason to register
    216     //  a boot time FVB protocol.
    217     //
    218     Status = gBS->HandleProtocol (Handle, &gEfiFirmwareVolumeBlockProtocolGuid, (VOID **) &Fvb);
    219     ASSERT_EFI_ERROR (Status);
    220     if (IsMemoryRuntime (Fvb)) {
    221       //
    222       // Increase mFvbCount if we need to add a new entry
    223       //
    224       if (UpdateIndex == mFvbCount) {
    225         mFvbCount++;
    226       }
    227       mFvbEntry[UpdateIndex].Handle       = Handle;
    228       mFvbEntry[UpdateIndex].Fvb          = Fvb;
    229       mFvbEntry[UpdateIndex].FvbExtension = NULL;
    230 
    231       Status = gBS->HandleProtocol (Handle, &gEfiFvbExtensionProtocolGuid, (VOID **) &FvbExtension);
    232       if ((Status == EFI_SUCCESS) && IsMemoryRuntime (FvbExtension)) {
    233         mFvbEntry[UpdateIndex].FvbExtension = FvbExtension;
    234       }
    235     }
    236   }
    237 }
    238 
    239 EFI_STATUS
    240 EfiFvbInitialize (
    241   VOID
    242   )
    243 /*++
    244 
    245 Routine Description:
    246   Initialize globals and register Fvb Protocol notification function.
    247 
    248 Arguments:
    249   None
    250 
    251 Returns:
    252   EFI_SUCCESS - Fvb is successfully initialized
    253   others                - Fail to initialize
    254 
    255 --*/
    256 {
    257   UINTN Status;
    258   mFvbCount = 0;
    259 
    260   Status = gBS->AllocatePool (
    261                   EfiRuntimeServicesData,
    262                   (UINTN) sizeof (FVB_ENTRY) * MAX_FVB_COUNT,
    263                   (VOID *) &mFvbEntry
    264                   );
    265 
    266   if (EFI_ERROR (Status)) {
    267     return Status;
    268   }
    269 
    270   EfiZeroMem (mFvbEntry, sizeof (FVB_ENTRY) * MAX_FVB_COUNT);
    271 
    272   mFvbEvent = RtEfiLibCreateProtocolNotifyEvent (
    273     &gEfiFirmwareVolumeBlockProtocolGuid,
    274     EFI_TPL_CALLBACK,
    275     FvbNotificationFunction,
    276     NULL,
    277     &mFvbRegistration
    278     );
    279 
    280   //
    281   // Register SetVirtualAddressMap () notify function
    282   //
    283   //  Status = gBS->CreateEvent (
    284   //                EFI_EVENT_SIGNAL_VIRTUAL_ADDRESS_CHANGE,
    285   //                EFI_TPL_NOTIFY,
    286   //                EfiRuntimeLibFvbVirtualNotifyEvent,
    287   //                NULL,
    288   //                &mEfiFvbVirtualNotifyEvent
    289   //                );
    290   //  ASSERT_EFI_ERROR (Status);
    291   //
    292   gEfiFvbInitialized = TRUE;
    293 
    294   return EFI_SUCCESS;
    295 }
    296 
    297 EFI_STATUS
    298 EfiFvbShutdown (
    299   VOID
    300   )
    301 /*++
    302 
    303 Routine Description:
    304   Release resources allocated in EfiFvbInitialize.
    305 
    306 Arguments:
    307   None
    308 
    309 Returns:
    310   EFI_SUCCESS
    311 
    312 --*/
    313 {
    314   gBS->FreePool ((VOID *) mFvbEntry);
    315   gBS->CloseEvent (mFvbEvent);
    316   gEfiFvbInitialized = FALSE;
    317   return EFI_SUCCESS;
    318 }
    319 
    320 //
    321 // The following functions wrap Fvb protocol in the Runtime Lib functions.
    322 // The Instance translates into Fvb instance. The Fvb order defined by HOBs and
    323 // thus the sequence of FVB protocol addition define Instance.
    324 //
    325 // EfiFvbInitialize () must be called before any of the following functions
    326 // must be called.
    327 //
    328 
    329 EFI_STATUS
    330 EfiFvbReadBlock (
    331   IN UINTN                                        Instance,
    332   IN EFI_LBA                                      Lba,
    333   IN UINTN                                        Offset,
    334   IN OUT UINTN                                    *NumBytes,
    335   IN UINT8                                        *Buffer
    336   )
    337 /*++
    338 
    339 Routine Description:
    340   Reads specified number of bytes into a buffer from the specified block
    341 
    342 Arguments:
    343   Instance              - The FV instance to be read from
    344   Lba                   - The logical block address to be read from
    345   Offset                - Offset into the block at which to begin reading
    346   NumBytes              - Pointer that on input contains the total size of
    347                           the buffer. On output, it contains the total number
    348                           of bytes read
    349   Buffer                - Pointer to a caller allocated buffer that will be
    350                           used to hold the data read
    351 
    352 Returns:
    353 
    354   Status code
    355 
    356   EFI_INVALID_PARAMETER - invalid parameter
    357 
    358 --*/
    359 {
    360   if (Instance >= mFvbCount) {
    361     return EFI_INVALID_PARAMETER;
    362   }
    363 
    364   return mFvbEntry[Instance].Fvb->Read (mFvbEntry[Instance].Fvb, Lba, Offset, NumBytes, Buffer);
    365 }
    366 
    367 EFI_STATUS
    368 EfiFvbWriteBlock (
    369   IN UINTN                                        Instance,
    370   IN EFI_LBA                                      Lba,
    371   IN UINTN                                        Offset,
    372   IN OUT UINTN                                    *NumBytes,
    373   IN UINT8                                        *Buffer
    374   )
    375 /*++
    376 
    377 Routine Description:
    378   Writes specified number of bytes from the input buffer to the block
    379 
    380 Arguments:
    381   Instance              - The FV instance to be written to
    382   Lba                   - The starting logical block index to write to
    383   Offset                - Offset into the block at which to begin writing
    384   NumBytes              - Pointer that on input contains the total size of
    385                           the buffer. On output, it contains the total number
    386                           of bytes actually written
    387   Buffer                - Pointer to a caller allocated buffer that contains
    388                           the source for the write
    389 
    390 Returns:
    391 
    392   Status code
    393 
    394   EFI_INVALID_PARAMETER - invalid parameter
    395 
    396 --*/
    397 {
    398   if (Instance >= mFvbCount) {
    399     return EFI_INVALID_PARAMETER;
    400   }
    401 
    402   return mFvbEntry[Instance].Fvb->Write (mFvbEntry[Instance].Fvb, Lba, Offset, NumBytes, Buffer);
    403 }
    404 
    405 EFI_STATUS
    406 EfiFvbEraseBlock (
    407   IN UINTN                                Instance,
    408   IN EFI_LBA                              Lba
    409   )
    410 /*++
    411 
    412 Routine Description:
    413   Erases and initializes a firmware volume block
    414 
    415 Arguments:
    416   Instance              - The FV instance to be erased
    417   Lba                   - The logical block index to be erased
    418 
    419 Returns:
    420 
    421   Status code
    422 
    423   EFI_INVALID_PARAMETER - invalid parameter
    424 
    425 --*/
    426 {
    427   if (Instance >= mFvbCount) {
    428     return EFI_INVALID_PARAMETER;
    429   }
    430 
    431   return mFvbEntry[Instance].Fvb->EraseBlocks (mFvbEntry[Instance].Fvb, Lba, -1);
    432 }
    433 
    434 EFI_STATUS
    435 EfiFvbGetVolumeAttributes (
    436   IN UINTN                                Instance,
    437   OUT EFI_FVB_ATTRIBUTES                  *Attributes
    438   )
    439 /*++
    440 
    441 Routine Description:
    442   Retrieves attributes, insures positive polarity of attribute bits, returns
    443   resulting attributes in output parameter
    444 
    445 Arguments:
    446   Instance              - The FV instance whose attributes is going to be
    447                           returned
    448   Attributes            - Output buffer which contains attributes
    449 
    450 Returns:
    451   Status code
    452 
    453   EFI_INVALID_PARAMETER - invalid parameter
    454 
    455 --*/
    456 {
    457   if (Instance >= mFvbCount) {
    458     return EFI_INVALID_PARAMETER;
    459   }
    460 
    461   return mFvbEntry[Instance].Fvb->GetVolumeAttributes (mFvbEntry[Instance].Fvb, Attributes);
    462 }
    463 
    464 EFI_STATUS
    465 EfiFvbSetVolumeAttributes (
    466   IN UINTN                                Instance,
    467   IN EFI_FVB_ATTRIBUTES                   Attributes
    468   )
    469 /*++
    470 
    471 Routine Description:
    472   Modifies the current settings of the firmware volume according to the
    473   input parameter.
    474 
    475 Arguments:
    476   Instance              - The FV instance whose attributes is going to be
    477                           modified
    478   Attributes            - It is a pointer to EFI_FVB_ATTRIBUTES
    479                           containing the desired firmware volume settings.
    480 
    481 Returns:
    482   Status code
    483 
    484   EFI_INVALID_PARAMETER - invalid parameter
    485 
    486 --*/
    487 {
    488   if (Instance >= mFvbCount) {
    489     return EFI_INVALID_PARAMETER;
    490   }
    491 
    492   return mFvbEntry[Instance].Fvb->SetVolumeAttributes (mFvbEntry[Instance].Fvb, &Attributes);
    493 }
    494 
    495 EFI_STATUS
    496 EfiFvbGetPhysicalAddress (
    497   IN UINTN                                Instance,
    498   OUT EFI_PHYSICAL_ADDRESS                *BaseAddress
    499   )
    500 /*++
    501 
    502 Routine Description:
    503   Retrieves the physical address of a memory mapped FV
    504 
    505 Arguments:
    506   Instance              - The FV instance whose base address is going to be
    507                           returned
    508   BaseAddress           - Pointer to a caller allocated EFI_PHYSICAL_ADDRESS
    509                           that on successful return, contains the base address
    510                           of the firmware volume.
    511 
    512 Returns:
    513 
    514   Status code
    515 
    516   EFI_INVALID_PARAMETER - invalid parameter
    517 
    518 --*/
    519 {
    520   if (Instance >= mFvbCount) {
    521     return EFI_INVALID_PARAMETER;
    522   }
    523 
    524   return mFvbEntry[Instance].Fvb->GetPhysicalAddress (mFvbEntry[Instance].Fvb, BaseAddress);
    525 }
    526 
    527 EFI_STATUS
    528 EfiFvbGetBlockSize (
    529   IN UINTN                                        Instance,
    530   IN EFI_LBA                                      Lba,
    531   OUT UINTN                                       *BlockSize,
    532   OUT UINTN                                       *NumOfBlocks
    533   )
    534 /*++
    535 
    536 Routine Description:
    537   Retrieve the size of a logical block
    538 
    539 Arguments:
    540   Instance              - The FV instance whose block size is going to be
    541                           returned
    542   Lba                   - Indicates which block to return the size for.
    543   BlockSize             - A pointer to a caller allocated UINTN in which
    544                           the size of the block is returned
    545   NumOfBlocks           - a pointer to a caller allocated UINTN in which the
    546                           number of consecutive blocks starting with Lba is
    547                           returned. All blocks in this range have a size of
    548                           BlockSize
    549 
    550 Returns:
    551   EFI_SUCCESS           - The firmware volume was read successfully and
    552                           contents are in Buffer
    553 
    554   EFI_INVALID_PARAMETER - invalid parameter
    555 
    556 --*/
    557 {
    558   if (Instance >= mFvbCount) {
    559     return EFI_INVALID_PARAMETER;
    560   }
    561 
    562   return mFvbEntry[Instance].Fvb->GetBlockSize (mFvbEntry[Instance].Fvb, Lba, BlockSize, NumOfBlocks);
    563 }
    564 
    565 EFI_STATUS
    566 EfiFvbEraseCustomBlockRange (
    567   IN UINTN                                Instance,
    568   IN EFI_LBA                              StartLba,
    569   IN UINTN                                OffsetStartLba,
    570   IN EFI_LBA                              LastLba,
    571   IN UINTN                                OffsetLastLba
    572   )
    573 /*++
    574 
    575 Routine Description:
    576   Erases and initializes a specified range of a firmware volume
    577 
    578 Arguments:
    579   Instance              - The FV instance to be erased
    580   StartLba              - The starting logical block index to be erased
    581   OffsetStartLba        - Offset into the starting block at which to
    582                           begin erasing
    583   LastLba               - The last logical block index to be erased
    584   OffsetLastLba         - Offset into the last block at which to end erasing
    585 
    586 Returns:
    587 
    588   Status code
    589 
    590   EFI_INVALID_PARAMETER - invalid parameter
    591 
    592   EFI_UNSUPPORTED       - not support
    593 
    594 --*/
    595 {
    596   if (Instance >= mFvbCount) {
    597     return EFI_INVALID_PARAMETER;
    598   }
    599 
    600   if (!(mFvbEntry[Instance].FvbExtension)) {
    601     return EFI_UNSUPPORTED;
    602   }
    603 
    604   if (!(mFvbEntry[Instance].FvbExtension->EraseFvbCustomBlock)) {
    605     return EFI_UNSUPPORTED;
    606   }
    607 
    608   return mFvbEntry[Instance].FvbExtension->EraseFvbCustomBlock (
    609                                             mFvbEntry[Instance].FvbExtension,
    610                                             StartLba,
    611                                             OffsetStartLba,
    612                                             LastLba,
    613                                             OffsetLastLba
    614                                             );
    615 }
    616