Esempio n. 1
0
/**
  Load a binary file from BootMonFS.

  @param[in]  FileHandle    Handle of the file to load.

  @param[in]  FileData      Address  of the file data in memory.

  @param[out] EntryPoint    Will be filled with the ELF entry point address.

  @param[out] ImageSize     Will be filled with the file size in memory. This
                            will effectively be equal to the sum of the load
                            region sizes.

  This function assumes the file is valid and supported as checked with
  BootMonFsCheckFile().

  @retval EFI_SUCCESS on success.
  @retval EFI_INVALID_PARAMETER if the file is invalid.
**/
EFI_STATUS
BootMonFsLoadFile (
  IN  CONST EFI_FILE_HANDLE   FileHandle,
  IN  CONST VOID             *FileData,
  OUT VOID                  **EntryPoint,
  OUT LIST_ENTRY             *LoadList
  )
{
  EFI_STATUS            Status;
  BOOTMON_FS_FILE_INFO  Info;
  UINTN                 InfoSize;
  UINTN                 Index;
  UINTN                 ImageSize;
  RUNAXF_LOAD_LIST     *LoadNode;

  ASSERT (FileHandle != NULL);
  ASSERT (FileData   != NULL);
  ASSERT (EntryPoint != NULL);
  ASSERT (LoadList   != NULL);

  ImageSize = 0;

  InfoSize = sizeof (Info);
  Status = FileHandle->GetInfo (FileHandle, &gArmBootMonFsFileInfoGuid,
                               &InfoSize, &Info);

  if (!EFI_ERROR (Status)) {
    *EntryPoint = (VOID*)((UINTN)Info.EntryPoint);
    // Load all the regions to run-time memory
    for (Index = 0; Index < Info.RegionCount; Index++) {
      LoadNode = AllocateRuntimeZeroPool (sizeof (RUNAXF_LOAD_LIST));
      if (LoadNode == NULL) {
        Status = EFI_OUT_OF_RESOURCES;
        break;
      }

      LoadNode->MemOffset  = (UINTN)Info.Region[Index].LoadAddress;
      LoadNode->FileOffset = (UINTN)FileData + Info.Region[Index].Offset;
      LoadNode->Length     = (UINTN)Info.Region[Index].Size;
      InsertTailList (LoadList, &LoadNode->Link);

      ImageSize += LoadNode->Length;
    }
  }

  if ((!EFI_ERROR (Status)) && (ImageSize == 0)) {
    Status = EFI_INVALID_PARAMETER;
  }

  return Status;
}
Esempio n. 2
0
INT32
ShvOsPrepareProcessor (
    _In_ PSHV_VP_DATA VpData
    )
{
    PKGDTENTRY64 TssEntry, NewGdt;
    PKTSS64 Tss;
    KDESCRIPTOR Gdtr;

    //
    // Clear AC in case it's not been reset yet
    //
    __writeeflags(__readeflags() & ~EFLAGS_ALIGN_CHECK);

    //
    // Capture the current GDT
    //
    _sgdt(&Gdtr.Limit);

    //
    // Allocate a new GDT as big as the old one, or to cover selector 0x60
    //
    NewGdt = AllocateRuntimeZeroPool(MAX(Gdtr.Limit + 1,
                                     KGDT64_SYS_TSS + sizeof(*TssEntry)));
    if (NewGdt == NULL)
    {
        return SHV_STATUS_NO_RESOURCES;
    }

    //
    // Copy the old GDT
    //
    CopyMem(NewGdt, Gdtr.Base, Gdtr.Limit + 1);

    //
    // Allocate a TSS
    //
    Tss = AllocateRuntimeZeroPool(sizeof(*Tss));
    if (Tss == NULL)
    {
        FreePool(NewGdt);
        return SHV_STATUS_NO_RESOURCES;
    }

    //
    // Fill out the TSS Entry
    //
    TssEntry = (PKGDTENTRY64)((uintptr_t)NewGdt + KGDT64_SYS_TSS);
    TssEntry->BaseLow = (uintptr_t)Tss & 0xffff;
    TssEntry->Bits.BaseMiddle = ((uintptr_t)Tss >> 16) & 0xff;
    TssEntry->Bits.BaseHigh = ((uintptr_t)Tss >> 24) & 0xff;
    TssEntry->BaseUpper = (uintptr_t)Tss >> 32;
    TssEntry->LimitLow = sizeof(KTSS64) - 1;
    TssEntry->Bits.Type = AMD64_TSS;
    TssEntry->Bits.Dpl = 0;
    TssEntry->Bits.Present = 1;
    TssEntry->Bits.System = 0;
    TssEntry->Bits.LongMode = 0;
    TssEntry->Bits.DefaultBig = 0;
    TssEntry->Bits.Granularity = 0;
    TssEntry->MustBeZero = 0;

    //
    // Load the new GDT
    //
    Gdtr.Base = NewGdt;
    Gdtr.Limit = KGDT64_SYS_TSS + sizeof(*TssEntry) - 1;
    _lgdt(&Gdtr.Limit);

    //
    // Load the task register
    //
    _ltr(KGDT64_SYS_TSS);
    return SHV_STATUS_SUCCESS;
}
Esempio n. 3
0
File: Event.c Progetto: etiago/vbox
/**
  Creates a general-purpose event structure

  @param  Type                   The type of event to create and its mode and
                                 attributes
  @param  NotifyTpl              The task priority level of event notifications
  @param  NotifyFunction         Pointer to the events notification function
  @param  NotifyContext          Pointer to the notification functions context;
                                 corresponds to parameter "Context" in the
                                 notification function
  @param  EventGroup             GUID for EventGroup if NULL act the same as
                                 gBS->CreateEvent().
  @param  Event                  Pointer to the newly created event if the call
                                 succeeds; undefined otherwise

  @retval EFI_SUCCESS            The event structure was created
  @retval EFI_INVALID_PARAMETER  One of the parameters has an invalid value
  @retval EFI_OUT_OF_RESOURCES   The event could not be allocated

**/
EFI_STATUS
EFIAPI
CoreCreateEventInternal (
  IN UINT32                   Type,
  IN EFI_TPL                  NotifyTpl,
  IN EFI_EVENT_NOTIFY         NotifyFunction, OPTIONAL
  IN CONST VOID               *NotifyContext, OPTIONAL
  IN CONST EFI_GUID           *EventGroup,    OPTIONAL
  OUT EFI_EVENT               *Event
  )
{
  EFI_STATUS      Status;
  IEVENT          *IEvent;
  INTN            Index;


  if (Event == NULL) {
    return EFI_INVALID_PARAMETER;
  }

  //
  // Check to make sure no reserved flags are set
  //
  Status = EFI_INVALID_PARAMETER;
  for (Index = 0; Index < (sizeof (mEventTable) / sizeof (UINT32)); Index++) {
     if (Type == mEventTable[Index]) {
       Status = EFI_SUCCESS;
       break;
     }
  }
  if(EFI_ERROR (Status)) {
    return EFI_INVALID_PARAMETER;
  }

  //
  // Convert Event type for pre-defined Event groups
  //
  if (EventGroup != NULL) {
    //
    // For event group, type EVT_SIGNAL_EXIT_BOOT_SERVICES and EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE
    // are not valid
    //
    if ((Type == EVT_SIGNAL_EXIT_BOOT_SERVICES) || (Type == EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE)) {
      return EFI_INVALID_PARAMETER;
    }
    if (CompareGuid (EventGroup, &gEfiEventExitBootServicesGuid)) {
      Type = EVT_SIGNAL_EXIT_BOOT_SERVICES;
    } else if (CompareGuid (EventGroup, &gEfiEventVirtualAddressChangeGuid)) {
      Type = EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE;
    }
  } else {
    //
    // Convert EFI 1.10 Events to their UEFI 2.0 CreateEventEx mapping
    //
    if (Type == EVT_SIGNAL_EXIT_BOOT_SERVICES) {
      EventGroup = &gEfiEventExitBootServicesGuid;
    } else if (Type == EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE) {
      EventGroup = &gEfiEventVirtualAddressChangeGuid;
    }
  }

  //
  // If it's a notify type of event, check its parameters
  //
  if ((Type & (EVT_NOTIFY_WAIT | EVT_NOTIFY_SIGNAL)) != 0) {
    //
    // Check for an invalid NotifyFunction or NotifyTpl
    //
    if ((NotifyFunction == NULL) ||
        (NotifyTpl <= TPL_APPLICATION) ||
       (NotifyTpl >= TPL_HIGH_LEVEL)) {
      return EFI_INVALID_PARAMETER;
    }

  } else {
    //
    // No notification needed, zero ignored values
    //
    NotifyTpl = 0;
    NotifyFunction = NULL;
    NotifyContext = NULL;
  }

  //
  // Allocate and initialize a new event structure.
  //
  if ((Type & EVT_RUNTIME) != 0) {
    IEvent = AllocateRuntimeZeroPool (sizeof (IEVENT));
  } else {
    IEvent = AllocateZeroPool (sizeof (IEVENT));
  }
  if (IEvent == NULL) {
    return EFI_OUT_OF_RESOURCES;
  }

  IEvent->Signature = EVENT_SIGNATURE;
  IEvent->Type = Type;

  IEvent->NotifyTpl      = NotifyTpl;
  IEvent->NotifyFunction = NotifyFunction;
  IEvent->NotifyContext  = (VOID *)NotifyContext;
  if (EventGroup != NULL) {
    CopyGuid (&IEvent->EventGroup, EventGroup);
    IEvent->ExFlag = TRUE;
  }

  *Event = IEvent;

  if ((Type & EVT_RUNTIME) != 0) {
    //
    // Keep a list of all RT events so we can tell the RT AP.
    //
    IEvent->RuntimeData.Type           = Type;
    IEvent->RuntimeData.NotifyTpl      = NotifyTpl;
    IEvent->RuntimeData.NotifyFunction = NotifyFunction;
    IEvent->RuntimeData.NotifyContext  = (VOID *) NotifyContext;
    IEvent->RuntimeData.Event          = (EFI_EVENT *) IEvent;
    InsertTailList (&gRuntime->EventHead, &IEvent->RuntimeData.Link);
  }

  CoreAcquireEventLock ();

  if ((Type & EVT_NOTIFY_SIGNAL) != 0x00000000) {
    //
    // The Event's NotifyFunction must be queued whenever the event is signaled
    //
    InsertHeadList (&gEventSignalQueue, &IEvent->SignalLink);
  }

  CoreReleaseEventLock ();

  //
  // Done
  //
  return EFI_SUCCESS;
}
Esempio n. 4
0
/**
  Build Gather list for a list of capsule images.

  @param[in]  CapsuleBuffer    An array of pointer to capsule images
  @param[in]  FileSize         An array of UINTN to capsule images size
  @param[in]  CapsuleNum       The count of capsule images
  @param[out] BlockDescriptors The block descriptors for the capsule images

  @retval EFI_SUCCESS The block descriptors for the capsule images are constructed.
**/
EFI_STATUS
BuildGatherList (
  IN VOID                          **CapsuleBuffer,
  IN UINTN                         *FileSize,
  IN UINTN                         CapsuleNum,
  OUT EFI_CAPSULE_BLOCK_DESCRIPTOR **BlockDescriptors
  )
{
  EFI_STATUS                    Status;
  EFI_CAPSULE_BLOCK_DESCRIPTOR  *BlockDescriptors1;
  EFI_CAPSULE_BLOCK_DESCRIPTOR  *BlockDescriptors2;
  EFI_CAPSULE_BLOCK_DESCRIPTOR  *BlockDescriptorPre;
  EFI_CAPSULE_BLOCK_DESCRIPTOR  *BlockDescriptorsHeader;
  EFI_CAPSULE_BLOCK_DESCRIPTOR  *TempBlockPtr;
  UINT8                         *TempDataPtr;
  UINTN                         SizeLeft;
  UINTN                         Size;
  INT32                         Count;
  INT32                         Number;
  UINTN                         Index;

  TempBlockPtr           = NULL;
  BlockDescriptors1      = NULL;
  BlockDescriptors2      = NULL;
  BlockDescriptorPre     = NULL;
  BlockDescriptorsHeader = NULL;

  for (Index = 0; Index < CapsuleNum; Index++) {
    //
    // Allocate memory for the descriptors.
    //
    if (NumberOfDescriptors == 1) {
      Count = 2;
    } else {
      Count = (INT32)(NumberOfDescriptors + 2) / 2;
    }

    Size               = Count * sizeof (EFI_CAPSULE_BLOCK_DESCRIPTOR);
    BlockDescriptors1  = AllocateRuntimeZeroPool (Size);
    if (BlockDescriptors1 == NULL) {
      Print (L"CapsuleApp: failed to allocate memory for descriptors\n");
      Status = EFI_OUT_OF_RESOURCES;
      goto ERREXIT;
    } else {
      Print (L"CapsuleApp: creating capsule descriptors at 0x%X\n", (UINTN) BlockDescriptors1);
      Print (L"CapsuleApp: capsule data starts          at 0x%X with size 0x%X\n", (UINTN) CapsuleBuffer[Index], FileSize[Index]);
    }

    //
    // Record descirptor header
    //
    if (Index == 0) {
      BlockDescriptorsHeader = BlockDescriptors1;
    }

    if (BlockDescriptorPre != NULL) {
      BlockDescriptorPre->Union.ContinuationPointer = (UINTN) BlockDescriptors1;
      BlockDescriptorPre->Length = 0;
    }

    //
    // Fill them in
    //
    TempBlockPtr  = BlockDescriptors1;
    TempDataPtr   = CapsuleBuffer[Index];
    SizeLeft      = FileSize[Index];
    for (Number = 0; (Number < Count - 1) && (SizeLeft != 0); Number++) {
      //
      // Divide remaining data in half
      //
      if (NumberOfDescriptors != 1) {
        if (SizeLeft == 1) {
          Size = 1;
        } else {
          Size = SizeLeft / 2;
        }
      } else {
        Size = SizeLeft;
      }
      TempBlockPtr->Union.DataBlock    = (UINTN)TempDataPtr;
      TempBlockPtr->Length  = Size;
      Print (L"CapsuleApp: capsule block/size              0x%X/0x%X\n", (UINTN) TempDataPtr, Size);
      SizeLeft -= Size;
      TempDataPtr += Size;
      TempBlockPtr++;
    }

    //
    // Allocate the second list, point the first block's last entry to point
    // to this one, and fill this one in. Worst case is that the previous
    // list only had one element that pointed here, so we need at least two
    // elements -- one to point to all the data, another to terminate the list.
    //
    if ((NumberOfDescriptors != 1) && (SizeLeft != 0)) {
      Count = (INT32)(NumberOfDescriptors + 2) - Count;
      if (Count == 1) {
        Count++;
      }

      Size              = Count * sizeof (EFI_CAPSULE_BLOCK_DESCRIPTOR);
      BlockDescriptors2 = AllocateRuntimeZeroPool (Size);
      if (BlockDescriptors2 == NULL) {
        Print (L"CapsuleApp: failed to allocate memory for descriptors\n");
        Status = EFI_OUT_OF_RESOURCES;
        goto ERREXIT;
      }

      //
      // Point the first list's last element to point to this second list.
      //
      TempBlockPtr->Union.ContinuationPointer   = (UINTN) BlockDescriptors2;

      TempBlockPtr->Length  = 0;
      TempBlockPtr = BlockDescriptors2;
      for (Number = 0; Number < Count - 1; Number++) {
        //
        // If second-to-last one, then dump rest to this element
        //
        if (Number == (Count - 2)) {
          Size = SizeLeft;
        } else {
          //
          // Divide remaining data in half
          //
          if (SizeLeft == 1) {
            Size = 1;
          } else {
            Size = SizeLeft / 2;
          }
        }

        TempBlockPtr->Union.DataBlock    = (UINTN)TempDataPtr;
        TempBlockPtr->Length  = Size;
        Print (L"CapsuleApp: capsule block/size              0x%X/0x%X\n", (UINTN) TempDataPtr, Size);
        SizeLeft -= Size;
        TempDataPtr += Size;
        TempBlockPtr++;
        if (SizeLeft == 0) {
          break;
        }
      }
    }

    BlockDescriptorPre = TempBlockPtr;
    BlockDescriptors1  = NULL;
  }

  //
  // Null-terminate.
  //
  if (TempBlockPtr != NULL) {
    TempBlockPtr->Union.ContinuationPointer    = (UINTN)NULL;
    TempBlockPtr->Length  = 0;
    *BlockDescriptors = BlockDescriptorsHeader;
  }

  return EFI_SUCCESS;

ERREXIT:
  if (BlockDescriptors1 != NULL) {
    FreePool(BlockDescriptors1);
  }

  if (BlockDescriptors2 != NULL) {
    FreePool(BlockDescriptors2);
  }

  return Status;
}
Esempio n. 5
0
File: PchSpi.c Progetto: OznOg/edk2
EFI_STATUS
EFIAPI
InstallPchSpi (
  IN EFI_HANDLE            ImageHandle,
  IN EFI_SYSTEM_TABLE      *SystemTable
  )
/*++

Routine Description:

  Entry point for the SPI host controller driver.

Arguments:

  ImageHandle       Image handle of this driver.
  SystemTable       Global system service table.

Returns:

  EFI_SUCCESS           Initialization complete.
  EFI_UNSUPPORTED       The chipset is unsupported by this driver.
  EFI_OUT_OF_RESOURCES  Do not have enough resources to initialize the driver.
  EFI_DEVICE_ERROR      Device error, driver exits abnormally.

--*/
{
  EFI_STATUS                      Status;
  UINT64                          BaseAddress;
  UINT64                          Length;
  EFI_GCD_MEMORY_SPACE_DESCRIPTOR GcdMemorySpaceDescriptor;
  UINT64                          Attributes;
  EFI_EVENT                       Event;

  DEBUG ((DEBUG_INFO, "InstallPchSpi() Start\n"));

  //
  // Allocate Runtime memory for the SPI protocol instance.
  //
  mSpiInstance = AllocateRuntimeZeroPool (sizeof (SPI_INSTANCE));
  if (mSpiInstance == NULL) {
    return EFI_OUT_OF_RESOURCES;
  }
  //
  // Initialize the SPI protocol instance
  //
  Status = SpiProtocolConstructor (mSpiInstance);
  if (EFI_ERROR (Status)) {
    return Status;
  }
  //
  // Install the EFI_SPI_PROTOCOL interface
  //
  Status = gBS->InstallMultipleProtocolInterfaces (
                  &(mSpiInstance->Handle),
                  &gEfiSpiProtocolGuid,
                  &(mSpiInstance->SpiProtocol),
                  NULL
                  );
  if (EFI_ERROR (Status)) {
    FreePool (mSpiInstance);
    return EFI_DEVICE_ERROR;
  }
  //
  // Set RCBA space in GCD to be RUNTIME so that the range will be supported in
  // virtual address mode in EFI aware OS runtime.
  // It will assert if RCBA Memory Space is not allocated
  // The caller is responsible for the existence and allocation of the RCBA Memory Spaces
  //
  BaseAddress = (EFI_PHYSICAL_ADDRESS) (mSpiInstance->PchRootComplexBar);
  Length      = PcdGet64 (PcdRcbaMmioSize);

  Status      = gDS->GetMemorySpaceDescriptor (BaseAddress, &GcdMemorySpaceDescriptor);
  ASSERT_EFI_ERROR (Status);

  Attributes = GcdMemorySpaceDescriptor.Attributes | EFI_MEMORY_RUNTIME;

  Status = gDS->AddMemorySpace (
                  EfiGcdMemoryTypeMemoryMappedIo,
                  BaseAddress,
                  Length,
                  EFI_MEMORY_RUNTIME | EFI_MEMORY_UC
                  );
  ASSERT_EFI_ERROR(Status);

  Status = gDS->SetMemorySpaceAttributes (
                  BaseAddress,
                  Length,
                  Attributes
                  );
  ASSERT_EFI_ERROR (Status);

  Status = gBS->CreateEventEx (
                  EVT_NOTIFY_SIGNAL,
                  TPL_NOTIFY,
                  PchSpiVirtualddressChangeEvent,
                  NULL,
                  &gEfiEventVirtualAddressChangeGuid,
                  &Event
                  );
  ASSERT_EFI_ERROR (Status);

  DEBUG ((DEBUG_INFO, "InstallPchSpi() End\n"));

  return EFI_SUCCESS;
}
Esempio n. 6
0
/**
  The driver entry point for Firmware Volume Block Driver.

  The function does the necessary initialization work
  Firmware Volume Block Driver.

  @param[in]  ImageHandle       The firmware allocated handle for the UEFI image.
  @param[in]  SystemTable       A pointer to the EFI system table.

  @retval     EFI_SUCCESS       This funtion always return EFI_SUCCESS.
                                It will ASSERT on errors.

**/
EFI_STATUS
FvbInitialize (
  )
{
  EFI_FW_VOL_INSTANCE                   *FwhInstance;
  EFI_FIRMWARE_VOLUME_HEADER            *FwVolHeader;
  EFI_FIRMWARE_VOLUME_HEADER            *FvHeader;
  EFI_FV_BLOCK_MAP_ENTRY                *PtrBlockMapEntry;
  EFI_PHYSICAL_ADDRESS                  BaseAddress;
  EFI_STATUS                            Status;
  UINTN                                 BufferSize;
  UINTN                                 TmpHeaderLength;
  UINTN                                 Idx;
  UINT32                                MaxLbaSize;
  BOOLEAN                               FvHeaderValid;
  UINTN                                 FvFlashLinearAddress;
  EFI_BOOT_MODE                         BootMode;
  UINT32                                Index;
  UINT32                                PlatformFvBaseAddress[5];
  UINT32                                PlatformFvBaseAddressCount;
  UINT32                                PlatformFvLockList[4];
  UINT32                                PlatformFvLockListCount;
  
  //
  // This platform driver knows there are 3 FVs on
  // FD, which are FvRecovery, FvMain and FvNvStorage.
  //
  BootMode = GetBootModeHob ();
  if (BootMode == BOOT_IN_RECOVERY_MODE) {
    //
    // On recovery boot, don't report any firmware FV images except payload, because their data can't be trusted.
    //
    PlatformFvBaseAddressCount = 2;
    PlatformFvBaseAddress[0]   = PcdGet32 (PcdFlashNvStorageVariableBase);
    PlatformFvBaseAddress[1]   = PcdGet32 (PcdFlashPayloadBase);
  } else {
    PlatformFvBaseAddressCount = 5;
    PlatformFvBaseAddress[0]   = PcdGet32 (PcdFlashFvMainBase);
    PlatformFvBaseAddress[1]   = PcdGet32 (PcdFlashNvStorageVariableBase);
    PlatformFvBaseAddress[2]   = PcdGet32 (PcdFlashFvRecoveryBase);
    PlatformFvBaseAddress[3]   = PcdGet32 (PcdFlashFvRecovery2Base);
    PlatformFvBaseAddress[4]   = PcdGet32 (PcdFlashPayloadBase);
  }

  //
  // List of FVs that should be write protected on normal boots.
  //
  PlatformFvLockListCount = 4;
  PlatformFvLockList[0]   = PcdGet32 (PcdFlashFvMainBase);
  PlatformFvLockList[1]   = PcdGet32 (PcdFlashFvRecoveryBase);
  PlatformFvLockList[2]   = PcdGet32 (PcdFlashFvRecovery2Base);
  PlatformFvLockList[3]   = PcdGet32 (PcdFlashPayloadBase);

  //
  // Calculate the total size for all firmware volume block instances and
  // allocate a buffer to store them in.
  //
  BufferSize = 0;
  for (Idx = 0; Idx < PlatformFvBaseAddressCount; Idx++) {
    FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) (UINTN) PlatformFvBaseAddress[Idx];
    if (FvHeader == NULL) {
      continue;
    }
    BufferSize +=  (FvHeader->HeaderLength +
                    sizeof (EFI_FW_VOL_INSTANCE) -
                    sizeof (EFI_FIRMWARE_VOLUME_HEADER)
                   );
  }
  mFvbModuleGlobal.FvInstance =  (EFI_FW_VOL_INSTANCE *) AllocateRuntimeZeroPool (BufferSize);
  ASSERT (NULL != mFvbModuleGlobal.FvInstance);

  //
  // Perform other variable initialization.
  //
  MaxLbaSize = 0;
  FwhInstance = mFvbModuleGlobal.FvInstance;
  mFvbModuleGlobal.NumFv   = 0;

  for (Idx = 0; Idx < PlatformFvBaseAddressCount; Idx++) {
  
    if ((BootMode == BOOT_ASSUMING_NO_CONFIGURATION_CHANGES) && PlatformFvBaseAddress[Idx]!= PcdGet32 (PcdFlashNvStorageVariableBase) && PlatformFvBaseAddress[Idx]!= PcdGet32 (PcdFlashPayloadBase)) {
      continue;
    }
    //
    // Get base address information.
    //
    BaseAddress = PlatformFvBaseAddress[Idx];
    FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *) (UINTN) BaseAddress;
    if (FwVolHeader == NULL) {
      continue;
    }
    //
    // Find the flash linear address of the current FV.
    //
    FvFlashLinearAddress = (UINTN) FLASH_LINEAR_ADDRESS(BaseAddress);

    if (!IsFvHeaderValid (BaseAddress, FwVolHeader)) {
      FvHeaderValid = FALSE;

      //
      // If not valid, get FvbInfo from the information carried in
      // FVB driver.
      //
      DEBUG ((EFI_D_ERROR, "Fvb: FV header @ 0x%lx invalid\n", BaseAddress));
      Status = GetFvbInfo (BaseAddress, &FwVolHeader);
      ASSERT_EFI_ERROR(Status);

      //
      //  Write back a healthy FV header.
      //
      DEBUG ((EFI_D_INFO, "FwBlockService.c: Writing back healthy FV header\n"));
      mSpiDeviceProtocol->SpiLock (FvFlashLinearAddress, FwVolHeader->BlockMap->Length, FALSE);

      Status = mSpiDeviceProtocol->SpiErase (FvFlashLinearAddress, FwVolHeader->BlockMap->Length);

      TmpHeaderLength = (UINTN) FwVolHeader->HeaderLength;
      Status = mSpiDeviceProtocol->SpiWrite (
                                     FvFlashLinearAddress,
                                     &TmpHeaderLength,
                                     (UINT8 *) FwVolHeader
                                     );

      mSpiDeviceProtocol->SpiLock (FvFlashLinearAddress, FwVolHeader->BlockMap->Length, TRUE);

      WriteBackInvalidateDataCacheRange (
        (VOID *) (UINTN) BaseAddress,
        FwVolHeader->BlockMap->Length
        );

    }

    //
    // Copy FV header into local storage and assign base address.
    //
    CopyMem (&(FwhInstance->VolumeHeader), FwVolHeader, FwVolHeader->HeaderLength);
    FwVolHeader = &(FwhInstance->VolumeHeader);
    FwhInstance->FvBase = (UINTN)BaseAddress;
    FwhInstance->FvFlashLinearAddress = FvFlashLinearAddress;

    //
    // In some cases the Recovery and Main FVs should be considered locked from
    // write access by this protocol.  Only in the case of flash updates and
    // configuration mode should they be left unlocked.
    //
    if (BootMode != BOOT_IN_RECOVERY_MODE &&
        BootMode != BOOT_ON_FLASH_UPDATE) {
      for (Index = 0; Index < PlatformFvLockListCount; Index++) {
        if (FwhInstance->FvBase == PlatformFvLockList[Index]) {
          //
          // For all FVs in the lock list we need to clear the write status bit
          // and lock write status updates.  This will make sure this protocol
          // will not attempt to write to the FV.
          //
          FwhInstance->VolumeHeader.Attributes &= (UINT64) ~EFI_FVB2_WRITE_STATUS;
          FwhInstance->VolumeHeader.Attributes |= (EFI_FVB2_LOCK_STATUS | EFI_FVB2_WRITE_LOCK_STATUS);
        }
      }
    }

    //
    // Process the block map for each FV
    //
    FwhInstance->NumOfBlocks   = 0;
    for (PtrBlockMapEntry = FwVolHeader->BlockMap;
         PtrBlockMapEntry->NumBlocks != 0;
         PtrBlockMapEntry++) {
      //
      // Get the maximum size of a block.
      //
      if (MaxLbaSize < PtrBlockMapEntry->Length) {
        MaxLbaSize  = PtrBlockMapEntry->Length;
      }
      FwhInstance->NumOfBlocks += PtrBlockMapEntry->NumBlocks;
    }

    //
    // Add a FVB Protocol Instance
    //
    mFvbModuleGlobal.NumFv++;
    InstallFvbProtocol (FwhInstance, mFvbModuleGlobal.NumFv - 1);

    //
    // Move on to the next FwhInstance
    //
    FwhInstance = (EFI_FW_VOL_INSTANCE *) ((UINTN)((UINT8 *)FwhInstance) +
                                          FwVolHeader->HeaderLength +
                                          (sizeof (EFI_FW_VOL_INSTANCE) - sizeof (EFI_FIRMWARE_VOLUME_HEADER)));
  }

  if ((PcdGet32 (PcdFlashNvStorageFtwWorkingBase) == 0) || (PcdGet32 (PcdFlashNvStorageFtwSpareBase) == 0)) {
    return EFI_SUCCESS;
  }
  
  //
  // Install FVB protocols for FTW spare space and FTW working space.
  // These is no FV header for these 2 spaces.
  //
  mFvbModuleGlobal.FvInstance = (EFI_FW_VOL_INSTANCE *) ReallocateRuntimePool (
                                  BufferSize, 
                                  BufferSize + (sizeof (EFI_FW_VOL_INSTANCE) + sizeof (EFI_FV_BLOCK_MAP_ENTRY)) * 2, 
                                  mFvbModuleGlobal.FvInstance
                                  );
  ASSERT (NULL != mFvbModuleGlobal.FvInstance);
  PlatformFvBaseAddress[0] = PcdGet32 (PcdFlashNvStorageFtwWorkingBase);
  PlatformFvBaseAddress[1] = PcdGet32 (PcdFlashNvStorageFtwSpareBase);
  
  for (Idx = 0; Idx < 2; Idx++) {
    BaseAddress = PlatformFvBaseAddress[Idx];
    Status = GetFtwFvbInfo (BaseAddress, &FwVolHeader);
    ASSERT_EFI_ERROR(Status);
  
    //
    // Copy FV header into local storage and assign base address.
    //
    mFvbModuleGlobal.NumFv++;
    FwhInstance = GetFvbInstance (mFvbModuleGlobal.NumFv - 1);
    CopyMem (&(FwhInstance->VolumeHeader), FwVolHeader, FwVolHeader->HeaderLength);
    FwVolHeader = &(FwhInstance->VolumeHeader);

    //
    // Process the block map for each FV
    //
    FwhInstance->NumOfBlocks   = 0;
    for (PtrBlockMapEntry = FwVolHeader->BlockMap;
         PtrBlockMapEntry->NumBlocks != 0;
         PtrBlockMapEntry++) {
      FwhInstance->NumOfBlocks += PtrBlockMapEntry->NumBlocks;
    }

    FwhInstance->FvBase = (UINTN)BaseAddress;
    FwhInstance->FvFlashLinearAddress = (UINTN) FLASH_LINEAR_ADDRESS(BaseAddress);

    InstallFvbProtocol (FwhInstance, mFvbModuleGlobal.NumFv - 1);
  }    
  
  return EFI_SUCCESS;
}
Esempio n. 7
0
/**
 Load an ELF segment into memory.

 This function assumes the ELF file is valid.
 This function is meant to be called for PT_LOAD type segments only.
**/
STATIC
EFI_STATUS
ElfLoadSegment (
  IN  CONST VOID  *ElfImage,
  IN  CONST VOID  *PHdr,
  IN  LIST_ENTRY  *LoadList
  )
{
  VOID             *FileSegment;
  VOID             *MemSegment;
  UINTN             ExtraZeroes;
  UINTN             ExtraZeroesCount;
  RUNAXF_LOAD_LIST *LoadNode;

#ifdef MDE_CPU_ARM
  Elf32_Phdr  *ProgramHdr;
  ProgramHdr = (Elf32_Phdr *)PHdr;
#elif defined(MDE_CPU_AARCH64)
  Elf64_Phdr  *ProgramHdr;
  ProgramHdr = (Elf64_Phdr *)PHdr;
#endif

  ASSERT (ElfImage != NULL);
  ASSERT (ProgramHdr != NULL);

  FileSegment = (VOID *)((UINTN)ElfImage + ProgramHdr->p_offset);
  MemSegment = (VOID *)ProgramHdr->p_vaddr;

  // If the segment's memory size p_memsz is larger than the file size p_filesz,
  // the "extra" bytes are defined to hold the value 0 and to follow the
  // segment's initialised area.
  // This is typically the case for the .bss segment.
  // The file size may not be larger than the memory size.
  if (ProgramHdr->p_filesz > ProgramHdr->p_memsz) {
    ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_RUNAXF_ELFBADFORMAT), gRunAxfHiiHandle);
    return EFI_INVALID_PARAMETER;
  }

  // Load the segment in memory.
  if (ProgramHdr->p_filesz != 0) {
    DEBUG ((EFI_D_INFO, "Loading segment from 0x%lx to 0x%lx (size = %ld)\n",
                 FileSegment, MemSegment, ProgramHdr->p_filesz));

    LoadNode = AllocateRuntimeZeroPool (sizeof (RUNAXF_LOAD_LIST));
    if (LoadNode == NULL) {
      return EFI_OUT_OF_RESOURCES;
    }
    LoadNode->MemOffset  = (UINTN)MemSegment;
    LoadNode->FileOffset = (UINTN)FileSegment;
    LoadNode->Length     = (UINTN)ProgramHdr->p_filesz;
    InsertTailList (LoadList, &LoadNode->Link);
  }

  ExtraZeroes = ((UINTN)MemSegment + ProgramHdr->p_filesz);
  ExtraZeroesCount = ProgramHdr->p_memsz - ProgramHdr->p_filesz;
  DEBUG ((EFI_D_INFO, "Completing segment with %d zero bytes.\n", ExtraZeroesCount));
  if (ExtraZeroesCount > 0) {
    // Extra Node to add the Zeroes.
    LoadNode = AllocateRuntimeZeroPool (sizeof (RUNAXF_LOAD_LIST));
    if (LoadNode == NULL) {
      return EFI_OUT_OF_RESOURCES;
    }
    LoadNode->MemOffset  = (UINTN)ExtraZeroes;
    LoadNode->Zeroes     = TRUE;
    LoadNode->Length     = ExtraZeroesCount;
    InsertTailList (LoadList, &LoadNode->Link);
  }

  return EFI_SUCCESS;
}