Home | History | Annotate | Download | only in HalRuntimeServicesExampleLib
      1 /** @file
      2   Generic Capsule services
      3 
      4   Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
      5 
      6   This program and the accompanying materials
      7   are licensed and made available under the terms and conditions of the BSD License
      8   which accompanies this distribution.  The full text of the license may be found at
      9   http://opensource.org/licenses/bsd-license.php
     10 
     11   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     12   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     13 
     14 **/
     15 
     16 #include <Common/CapsuleName.h>
     17 
     18 
     19 //
     20 //Max size capsule services support are platform policy,to populate capsules we just need
     21 //memory to maintain them across reset,it is not a problem. And to special capsules ,for
     22 //example,update flash,it is mostly decided by the platform. Here is a sample size for
     23 //different type capsules.
     24 //
     25 #define MAX_SIZE_POPULATE              (0)
     26 #define MAX_SIZE_NON_POPULATE          (0)
     27 #define MAX_SUPPORT_CAPSULE_NUM        0x10
     28 
     29 
     30 BOOLEAN
     31 EFIAPI
     32 SupportUpdateCapsuleRest (
     33   VOID
     34   )
     35 {
     36   //
     37   //If the platform has a way to guarantee the memory integrity across a system reset, return
     38   //TRUE, else FALSE.
     39   //
     40   return FALSE;
     41 }
     42 
     43 
     44 
     45 VOID
     46 EFIAPI
     47 SupportCapsuleSize (
     48   IN OUT UINT32 *MaxSizePopulate,
     49   IN OUT UINT32 *MaxSizeNonPopulate
     50   )
     51 {
     52   //
     53   //Here is a sample size, different platforms have different sizes.
     54   //
     55   *MaxSizePopulate    = MAX_SIZE_POPULATE;
     56   *MaxSizeNonPopulate = MAX_SIZE_NON_POPULATE;
     57   return;
     58 }
     59 
     60 
     61 
     62 
     63 EFI_STATUS
     64 LibUpdateCapsule (
     65   IN UEFI_CAPSULE_HEADER     **CapsuleHeaderArray,
     66   IN UINTN                   CapsuleCount,
     67   IN EFI_PHYSICAL_ADDRESS    ScatterGatherList OPTIONAL
     68   )
     69 /*++
     70 
     71 Routine Description:
     72 
     73   This code finds if the capsule needs reset to update, if no, update immediately.
     74 
     75 Arguments:
     76 
     77   CapsuleHeaderArray             A array of pointers to capsule headers passed in
     78   CapsuleCount                   The number of capsule
     79   ScatterGatherList              Physical address of datablock list points to capsule
     80 
     81 Returns:
     82 
     83   EFI STATUS
     84   EFI_SUCCESS                    Valid capsule was passed.If CAPSULE_FLAG_PERSIT_ACROSS_RESET is
     85                                  not set, the capsule has been successfully processed by the firmware.
     86                                  If it set, the ScattlerGatherList is successfully to be set.
     87   EFI_INVALID_PARAMETER          CapsuleCount is less than 1,CapsuleGuid is not supported.
     88   EFI_DEVICE_ERROR               Failed to SetVariable or AllocatePool or ProcessFirmwareVolume.
     89 
     90 --*/
     91 {
     92   UINTN                     CapsuleSize;
     93   UINTN                     ArrayNumber;
     94   VOID                      *BufferPtr;
     95   EFI_STATUS                Status;
     96   EFI_HANDLE                FvHandle;
     97   UEFI_CAPSULE_HEADER       *CapsuleHeader;
     98 
     99   if ((CapsuleCount < 1) || (CapsuleCount > MAX_SUPPORT_CAPSULE_NUM)){
    100     return EFI_INVALID_PARAMETER;
    101   }
    102 
    103   BufferPtr       = NULL;
    104   CapsuleHeader   = NULL;
    105 
    106   //
    107   //Compare GUIDs with EFI_CAPSULE_GUID, if capsule header contains CAPSULE_FLAGS_PERSIST_ACROSS_RESET
    108   //and CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE flags,whatever the GUID is ,the service supports.
    109   //
    110   for (ArrayNumber = 0; ArrayNumber < CapsuleCount; ArrayNumber++) {
    111     CapsuleHeader = CapsuleHeaderArray[ArrayNumber];
    112     if ((CapsuleHeader->Flags & (CAPSULE_FLAGS_PERSIST_ACROSS_RESET | CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE)) == CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE) {
    113       return EFI_INVALID_PARAMETER;
    114     }
    115     if (!CompareGuid (&CapsuleHeader->CapsuleGuid, &gEfiCapsuleGuid)) {
    116       if ((CapsuleHeader->Flags & CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE) == 0) {
    117         return EFI_UNSUPPORTED;
    118       }
    119     }
    120   }
    121 
    122   //
    123   //Assume that capsules have the same flags on reseting or not.
    124   //
    125   CapsuleHeader = CapsuleHeaderArray[0];
    126 
    127   if ((CapsuleHeader->Flags & CAPSULE_FLAGS_PERSIST_ACROSS_RESET) != 0) {
    128     //
    129     //Check if the platform supports update capsule across a system reset
    130     //
    131     if (!SupportUpdateCapsuleRest()) {
    132       return EFI_UNSUPPORTED;
    133     }
    134 
    135     if (ScatterGatherList == 0) {
    136       return EFI_INVALID_PARAMETER;
    137     } else {
    138       Status = EfiSetVariable (
    139                  EFI_CAPSULE_VARIABLE_NAME,
    140                  &gEfiCapsuleVendorGuid,
    141                  EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS,
    142                  sizeof (UINTN),
    143                  (VOID *) &ScatterGatherList
    144                  );
    145       if (Status != EFI_SUCCESS) {
    146         return EFI_DEVICE_ERROR;
    147       }
    148     }
    149     return EFI_SUCCESS;
    150   }
    151 
    152   //
    153   //The rest occurs in the condition of non-reset mode
    154   //
    155   if (EfiAtRuntime ()) {
    156     return EFI_INVALID_PARAMETER;
    157   }
    158 
    159   //
    160   //Here should be in the boot-time
    161   //
    162   for (ArrayNumber = 0; ArrayNumber < CapsuleCount ; ArrayNumber++) {
    163     CapsuleHeader = CapsuleHeaderArray[ArrayNumber];
    164     CapsuleSize = CapsuleHeader->CapsuleImageSize - CapsuleHeader->HeaderSize;
    165     Status = gBS->AllocatePool (EfiBootServicesData, CapsuleSize, &BufferPtr);
    166     if (Status != EFI_SUCCESS) {
    167       goto Done;
    168     }
    169     gBS->CopyMem (BufferPtr, (UINT8*)CapsuleHeader+ CapsuleHeader->HeaderSize, CapsuleSize);
    170 
    171     //
    172     //Call DXE service ProcessFirmwareVolume to process immediatelly
    173     //
    174     Status = gDS->ProcessFirmwareVolume (BufferPtr, CapsuleSize, &FvHandle);
    175     if (Status != EFI_SUCCESS) {
    176       gBS->FreePool (BufferPtr);
    177       return EFI_DEVICE_ERROR;
    178     }
    179     gDS->Dispatch ();
    180     gBS->FreePool (BufferPtr);
    181   }
    182   return EFI_SUCCESS;
    183 
    184 Done:
    185   if (BufferPtr != NULL) {
    186     gBS->FreePool (BufferPtr);
    187   }
    188   return EFI_DEVICE_ERROR;
    189 }
    190 
    191 
    192 EFI_STATUS
    193 QueryCapsuleCapabilities (
    194   IN  UEFI_CAPSULE_HEADER  **CapsuleHeaderArray,
    195   IN  UINTN                CapsuleCount,
    196   OUT UINT64               *MaxiumCapsuleSize,
    197   OUT EFI_RESET_TYPE       *ResetType
    198   )
    199 /*++
    200 
    201 Routine Description:
    202 
    203   This code is query about capsule capability.
    204 
    205 Arguments:
    206 
    207   CapsuleHeaderArray              A array of pointers to capsule headers passed in
    208   CapsuleCount                    The number of capsule
    209   MaxiumCapsuleSize               Max capsule size is supported
    210   ResetType                       Reset type the capsule indicates, if reset is not needed,return EfiResetCold.
    211                                   If reset is needed, return EfiResetWarm.
    212 
    213 Returns:
    214 
    215   EFI STATUS
    216   EFI_SUCCESS                     Valid answer returned
    217   EFI_INVALID_PARAMETER           MaxiumCapsuleSize is NULL,ResetType is NULL.CapsuleCount is less than 1,CapsuleGuid is not supported.
    218   EFI_UNSUPPORTED                 The capsule type is not supported.
    219 
    220 --*/
    221 {
    222   UINTN                     ArrayNumber;
    223   UEFI_CAPSULE_HEADER       *CapsuleHeader;
    224   UINT32                    MaxSizePopulate;
    225   UINT32                    MaxSizeNonPopulate;
    226 
    227 
    228   if ((CapsuleCount < 1) || (CapsuleCount > MAX_SUPPORT_CAPSULE_NUM)){
    229     return EFI_INVALID_PARAMETER;
    230   }
    231 
    232   if ((MaxiumCapsuleSize == NULL) ||(ResetType == NULL)) {
    233     return EFI_INVALID_PARAMETER;
    234   }
    235 
    236   CapsuleHeader = NULL;
    237 
    238   //
    239   //Compare GUIDs with EFI_CAPSULE_GUID, if capsule header contains CAPSULE_FLAGS_PERSIST_ACROSS_RESET
    240   //and CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE flags,whatever the GUID is ,the service supports.
    241   //
    242   for (ArrayNumber = 0; ArrayNumber < CapsuleCount; ArrayNumber++) {
    243     CapsuleHeader = CapsuleHeaderArray[ArrayNumber];
    244     if ((CapsuleHeader->Flags & (CAPSULE_FLAGS_PERSIST_ACROSS_RESET | CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE)) == CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE) {
    245       return EFI_INVALID_PARAMETER;
    246     }
    247     if (!CompareGuid (&CapsuleHeader->CapsuleGuid, &gEfiCapsuleGuid)) {
    248       if ((CapsuleHeader->Flags & CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE) == 0) {
    249         return EFI_UNSUPPORTED;
    250       }
    251     }
    252   }
    253 
    254   SupportCapsuleSize(&MaxSizePopulate,&MaxSizeNonPopulate);
    255   //
    256   //Assume that capsules have the same flags on reseting or not.
    257   //
    258   CapsuleHeader = CapsuleHeaderArray[0];
    259   if ((CapsuleHeader->Flags & CAPSULE_FLAGS_PERSIST_ACROSS_RESET) != 0) {
    260     //
    261     //Check if the platform supports update capsule across a system reset
    262     //
    263     if (!SupportUpdateCapsuleRest()) {
    264       return EFI_UNSUPPORTED;
    265     }
    266     *ResetType = EfiResetWarm;
    267     *MaxiumCapsuleSize = MaxSizePopulate;
    268   } else {
    269     *ResetType = EfiResetCold;
    270     *MaxiumCapsuleSize = MaxSizeNonPopulate;
    271   }
    272   return EFI_SUCCESS;
    273 }
    274 
    275 
    276 VOID
    277 LibCapsuleVirtualAddressChangeEvent (
    278   VOID
    279   )
    280 {
    281 }
    282 
    283 VOID
    284 LibCapsuleInitialize (
    285   VOID
    286   )
    287 {
    288 }
    289