Beispiel #1
0
/**
  Initialize all the stuff needed for on-demand paging hooks for PI<->Framework
  CpuSaveStates marshalling.

  @param[in] FrameworkSmst   Framework SMM system table pointer.

**/
VOID
InitHook (
  IN EFI_SMM_SYSTEM_TABLE  *FrameworkSmst
  )
{
  UINTN                 NumCpuStatePages;
  UINTN                 CpuStatePage;
  UINTN                 Bottom2MPage;
  UINTN                 Top2MPage;
  
  mPageTableHookEnabled = FALSE;
  NumCpuStatePages = EFI_SIZE_TO_PAGES (mNumberOfProcessors * sizeof (EFI_SMM_CPU_SAVE_STATE));
  //
  // Only hook page table for X64 image and less than 2MB needed to hold all CPU Save States
  //
  if (EFI_IMAGE_MACHINE_TYPE_SUPPORTED(EFI_IMAGE_MACHINE_X64) && NumCpuStatePages <= EFI_SIZE_TO_PAGES (SIZE_2MB)) {
    //
    // Allocate double page size to make sure all CPU Save States are in one 2MB page.
    //
    CpuStatePage = (UINTN)AllocatePages (NumCpuStatePages * 2);
    ASSERT (CpuStatePage != 0);
    Bottom2MPage = CpuStatePage & ~(SIZE_2MB-1);
    Top2MPage    = (CpuStatePage + EFI_PAGES_TO_SIZE (NumCpuStatePages * 2) - 1) & ~(SIZE_2MB-1);
    if (Bottom2MPage == Top2MPage ||
        CpuStatePage + EFI_PAGES_TO_SIZE (NumCpuStatePages * 2) - Top2MPage >= EFI_PAGES_TO_SIZE (NumCpuStatePages)
        ) {
      //
      // If the allocated 4KB pages are within the same 2MB page or higher portion is larger, use higher portion pages.
      //
      FrameworkSmst->CpuSaveState = (EFI_SMM_CPU_SAVE_STATE *)(CpuStatePage + EFI_PAGES_TO_SIZE (NumCpuStatePages));
      FreePages ((VOID*)CpuStatePage, NumCpuStatePages);
    } else {
      FrameworkSmst->CpuSaveState = (EFI_SMM_CPU_SAVE_STATE *)CpuStatePage;
      FreePages ((VOID*)(CpuStatePage + EFI_PAGES_TO_SIZE (NumCpuStatePages)), NumCpuStatePages);
    }
    //
    // Add temporary working buffer for hooking
    //
    mShadowSaveState = (EFI_SMM_CPU_SAVE_STATE*) AllocatePool (sizeof (EFI_SMM_CPU_SAVE_STATE));
    ASSERT (mShadowSaveState != NULL);
    //
    // Allocate and initialize 4KB Page Table for hooking CpuSaveState.
    // Replace the original 2MB PDE with new 4KB page table.
    //
    mCpuStatePageTable = InitCpuStatePageTable (FrameworkSmst->CpuSaveState);
    //
    // Mark PTE for CpuSaveState as non-exist.
    //
    HookCpuStateMemory (FrameworkSmst->CpuSaveState);
    HookPageFaultHandler ();
    CpuFlushTlb ();
    mPageTableHookEnabled = TRUE;
  }
  mHookInitialized = TRUE;
}
Beispiel #2
0
EFI_STATUS
XenGetSharedInfoPage (
  IN OUT XENBUS_DEVICE *Dev
  )
{
  xen_add_to_physmap_t Parameter;

  ASSERT (Dev->SharedInfo == NULL);

  Parameter.domid = DOMID_SELF;
  Parameter.space = XENMAPSPACE_shared_info;
  Parameter.idx = 0;

  //
  // using reserved page because the page is not released when Linux is
  // starting because of the add_to_physmap. QEMU might try to access the
  // page, and fail because it have no right to do so (segv).
  //
  Dev->SharedInfo = AllocateReservedPages (1);
  Parameter.gpfn = (UINTN) Dev->SharedInfo >> EFI_PAGE_SHIFT;
  if (XenHypercallMemoryOp (Dev, XENMEM_add_to_physmap, &Parameter) != 0) {
    FreePages (Dev->SharedInfo, 1);
    Dev->SharedInfo = NULL;
    return EFI_LOAD_ERROR;
  }

  return EFI_SUCCESS;
}
Beispiel #3
0
EFI_STATUS DestroyMmcHostInstance (
  IN MMC_HOST_INSTANCE* MmcHostInstance
  )
{
  EFI_STATUS Status;

  // Uninstall Protocol Interfaces
  Status = gBS->UninstallMultipleProtocolInterfaces (
        MmcHostInstance->MmcHandle,
        &gEfiBlockIoProtocolGuid,&(MmcHostInstance->BlockIo),
        &gEfiDevicePathProtocolGuid,MmcHostInstance->DevicePath,
        NULL
        );
  ASSERT_EFI_ERROR (Status);

  // Free Memory allocated for the instance
  if (MmcHostInstance->BlockIo.Media) {
    FreePool(MmcHostInstance->BlockIo.Media);
  }
  if (MmcHostInstance->CardInfo.ECSDData) {
    FreePages (MmcHostInstance->CardInfo.ECSDData, EFI_SIZE_TO_PAGES (sizeof (ECSD)));
  }
  FreePool (MmcHostInstance);

  return Status;
}
Beispiel #4
0
VOID
ShutdownEfi (
  VOID
  )
{
  EFI_STATUS              Status;
  UINTN                   MemoryMapSize;
  EFI_MEMORY_DESCRIPTOR   *MemoryMap;
  UINTN                   MapKey;
  UINTN                   DescriptorSize;
  UINTN                   DescriptorVersion;
  UINTN                   Pages;

  MemoryMap = NULL;
  MemoryMapSize = 0;
  do {
    Status = gBS->GetMemoryMap (
                    &MemoryMapSize,
                    MemoryMap,
                    &MapKey,
                    &DescriptorSize,
                    &DescriptorVersion
                    );
    if (Status == EFI_BUFFER_TOO_SMALL) {

      Pages = EFI_SIZE_TO_PAGES (MemoryMapSize) + 1;
      MemoryMap = AllocatePages (Pages);

      //
      // Get System MemoryMap
      //
      Status = gBS->GetMemoryMap (
                      &MemoryMapSize,
                      MemoryMap,
                      &MapKey,
                      &DescriptorSize,
                      &DescriptorVersion
                      );
      // Don't do anything between the GetMemoryMap() and ExitBootServices()
      if (!EFI_ERROR (Status)) {
        Status = gBS->ExitBootServices (gImageHandle, MapKey);
        if (EFI_ERROR (Status)) {
          FreePages (MemoryMap, Pages);
          MemoryMap = NULL;
          MemoryMapSize = 0;
        }
      }
    }
  } while (EFI_ERROR (Status));

  //Clean and invalidate caches.
  WriteBackInvalidateDataCache();
  InvalidateInstructionCache();

  //Turning off Caches and MMU
  ArmDisableDataCache ();
  ArmDisableInstructionCache ();
  ArmDisableMmu ();
}
Beispiel #5
0
/**
  Frees one or more 4KB pages that were previously allocated with one of the aligned page
  allocation functions in the Memory Allocation Library.

  Frees the number of 4KB pages specified by Pages from the buffer specified by Buffer.  Buffer
  must have been allocated on a previous call to the aligned page allocation services of the Memory
  Allocation Library.  If it is not possible to free allocated pages, then this function will
  perform no actions.

  If Buffer was not allocated with an aligned page allocation function in the Memory Allocation
  Library, then ASSERT().
  If Pages is zero, then ASSERT().

  @param  Buffer                The pointer to the buffer of pages to free.
  @param  Pages                 The number of 4 KB pages to free.

**/
VOID
EFIAPI
FreeAlignedPages (
  IN VOID   *Buffer,
  IN UINTN  Pages
  )
{
  FreePages (Buffer, Pages);
}
Beispiel #6
0
/**

  Tear down the internal resources of a configured virtio ring.

  The caller is responsible to stop the host from using this ring before
  invoking this function: the VSTAT_DRIVER_OK bit must be clear in
  VhdrDeviceStatus.

  @param[out] Ring  The virtio ring to clean up.

**/
VOID
EFIAPI
VirtioRingUninit (
  IN OUT VRING *Ring
  )
{
  FreePages (Ring->Base, Ring->NumPages);
  SetMem (Ring, sizeof *Ring, 0x00);
}
Beispiel #7
0
EFI_STATUS
ShutdownUefiBootServices (
  VOID
  )
{
  EFI_STATUS              Status;
  UINTN                   MemoryMapSize;
  EFI_MEMORY_DESCRIPTOR   *MemoryMap;
  UINTN                   MapKey;
  UINTN                   DescriptorSize;
  UINT32                  DescriptorVersion;
  UINTN                   Pages;

  MemoryMap = NULL;
  MemoryMapSize = 0;
  Pages = 0;

  do {
    Status = gBS->GetMemoryMap (
                    &MemoryMapSize,
                    MemoryMap,
                    &MapKey,
                    &DescriptorSize,
                    &DescriptorVersion
                    );
    if (Status == EFI_BUFFER_TOO_SMALL) {

      Pages = EFI_SIZE_TO_PAGES (MemoryMapSize) + 1;
      MemoryMap = AllocatePages (Pages);

      //
      // Get System MemoryMap
      //
      Status = gBS->GetMemoryMap (
                      &MemoryMapSize,
                      MemoryMap,
                      &MapKey,
                      &DescriptorSize,
                      &DescriptorVersion
                      );
    }

    // Don't do anything between the GetMemoryMap() and ExitBootServices()
    if (!EFI_ERROR(Status)) {
      Status = gBS->ExitBootServices (gImageHandle, MapKey);
      if (EFI_ERROR(Status)) {
        FreePages (MemoryMap, Pages);
        MemoryMap = NULL;
        MemoryMapSize = 0;
      }
    }
  } while (EFI_ERROR(Status));

  return Status;
}
Beispiel #8
0
/**
  Frees memory that was allocated with DmaAllocateBuffer().

  @param  Pages                 The number of pages to free.
  @param  HostAddress           The base system memory address of the allocated range.

  @retval EFI_SUCCESS           The requested memory pages were freed.
  @retval EFI_INVALID_PARAMETER The memory range specified by HostAddress and Pages
                                was not allocated with DmaAllocateBuffer().

**/
EFI_STATUS
EFIAPI
DmaFreeBuffer (
  IN  UINTN                        Pages,
  IN  VOID                         *HostAddress
  )
{
  if (HostAddress == NULL) {
     return EFI_INVALID_PARAMETER;
  }

  FreePages (HostAddress, Pages);
  return EFI_SUCCESS;
}
    DynamicStack& DynamicStack::operator=(DynamicStack&& other)
    {
        if (this != &other)
        {
            FreePages();

            _pageSize = other._pageSize;
            _firstPage = other._firstPage;
            other._pageSize = 0;
            other._firstPage = nullptr;
        }

        return *this;
    }
Beispiel #10
0
/**
  Frees memory that was allocated with AllocateBuffer().

  @param  This                  The protocol instance pointer.
  @param  Pages                 The number of pages to free.
  @param  HostAddress           The base system memory address of the allocated
                                range.

  @retval EFI_SUCCESS           The requested memory pages were freed.
  @retval EFI_INVALID_PARAMETER The memory range specified by HostAddress and
                                Pages was not allocated with AllocateBuffer().

**/
EFI_STATUS
EFIAPI
IoMmuFreeBuffer (
  IN  EDKII_IOMMU_PROTOCOL                     *This,
  IN  UINTN                                    Pages,
  IN  VOID                                     *HostAddress
  )
{
  UINTN                CommonBufferPages;
  COMMON_BUFFER_HEADER *CommonBufferHeader;

  CommonBufferPages = Pages + 1;
  CommonBufferHeader = (COMMON_BUFFER_HEADER *)(
                         (UINTN)HostAddress - EFI_PAGE_SIZE
                         );

  //
  // Check the signature.
  //
  ASSERT (CommonBufferHeader->Signature == COMMON_BUFFER_SIG);
  if (CommonBufferHeader->Signature != COMMON_BUFFER_SIG) {
    return EFI_INVALID_PARAMETER;
  }

  //
  // Free the stash buffer. This buffer was always encrypted, so no need to
  // zero it.
  //
  FreePages (CommonBufferHeader->StashBuffer, Pages);

  DEBUG ((
    DEBUG_VERBOSE,
    "%a Address 0x%Lx Pages 0x%Lx\n",
    __FUNCTION__,
    (UINT64)(UINTN)HostAddress,
    (UINT64)Pages
    ));

  //
  // Release the common buffer itself. Unmap() has re-encrypted it in-place, so
  // no need to zero it.
  //
  return gBS->FreePages ((UINTN)CommonBufferHeader, CommonBufferPages);
}
Beispiel #11
0
STATIC
EFI_STATUS
EFIAPI
EmmcIdentificationMode (
  IN MMC_HOST_INSTANCE     *MmcHostInstance,
  IN OCR_RESPONSE           Response
  )
{
  EFI_MMC_HOST_PROTOCOL *Host;
  EFI_BLOCK_IO_MEDIA    *Media;
  EFI_STATUS Status;
  EMMC_DEVICE_STATE     State;
  UINT32     RCA;

  Host  = MmcHostInstance->MmcHost;
  Media = MmcHostInstance->BlockIo.Media;

  // Fetch card identity register
  Status = Host->SendCommand (Host, MMC_CMD2, 0);
  if (EFI_ERROR (Status)) {
    DEBUG ((EFI_D_ERROR, "EmmcIdentificationMode(): Failed to send CMD2, Status=%r.\n", Status));
    return Status;
  }

  Status = Host->ReceiveResponse (Host, MMC_RESPONSE_TYPE_R2, (UINT32 *)&(MmcHostInstance->CardInfo.CIDData));
  if (EFI_ERROR (Status)) {
    DEBUG ((EFI_D_ERROR, "EmmcIdentificationMode(): CID retrieval error, Status=%r.\n", Status));
    return Status;
  }

  // Assign a relative address value to the card
  MmcHostInstance->CardInfo.RCA = ++mEmmcRcaCount; // TODO: might need a more sophisticated way of doing this
  RCA = MmcHostInstance->CardInfo.RCA << RCA_SHIFT_OFFSET;
  Status = Host->SendCommand (Host, MMC_CMD3, RCA);
  if (EFI_ERROR (Status)) {
    DEBUG ((EFI_D_ERROR, "EmmcIdentificationMode(): RCA set error, Status=%r.\n", Status));
    return Status;
  }

  // Fetch card specific data
  Status = Host->SendCommand (Host, MMC_CMD9, RCA);
  if (EFI_ERROR (Status)) {
    DEBUG ((EFI_D_ERROR, "EmmcIdentificationMode(): Failed to send CMD9, Status=%r.\n", Status));
    return Status;
  }

  Status = Host->ReceiveResponse (Host, MMC_RESPONSE_TYPE_R2, (UINT32 *)&(MmcHostInstance->CardInfo.CSDData));
  if (EFI_ERROR (Status)) {
    DEBUG ((EFI_D_ERROR, "EmmcIdentificationMode(): CSD retrieval error, Status=%r.\n", Status));
    return Status;
  }

  // Select the card
  Status = Host->SendCommand (Host, MMC_CMD7, RCA);
  if (EFI_ERROR (Status)) {
    DEBUG ((EFI_D_ERROR, "EmmcIdentificationMode(): Card selection error, Status=%r.\n", Status));
  }

  if (MMC_HOST_HAS_SETIOS(Host)) {
    // Set 1-bit bus width
    Status = Host->SetIos (Host, 0, 1, EMMCBACKWARD);
    if (EFI_ERROR (Status)) {
      DEBUG ((EFI_D_ERROR, "EmmcIdentificationMode(): Set 1-bit bus width error, Status=%r.\n", Status));
      return Status;
    }

    // Set 1-bit bus width for EXTCSD
    Status = EmmcSetEXTCSD (MmcHostInstance, EXTCSD_BUS_WIDTH, EMMC_BUS_WIDTH_1BIT);
    if (EFI_ERROR (Status)) {
      DEBUG ((EFI_D_ERROR, "EmmcIdentificationMode(): Set extcsd bus width error, Status=%r.\n", Status));
      return Status;
    }
  }

  // Fetch ECSD
  MmcHostInstance->CardInfo.ECSDData = AllocatePages (EFI_SIZE_TO_PAGES (sizeof (ECSD)));
  if (MmcHostInstance->CardInfo.ECSDData == NULL) {
    return EFI_OUT_OF_RESOURCES;
  }
  Status = Host->SendCommand (Host, MMC_CMD8, 0);
  if (EFI_ERROR (Status)) {
    DEBUG ((EFI_D_ERROR, "EmmcIdentificationMode(): ECSD fetch error, Status=%r.\n", Status));
  }

  Status = Host->ReadBlockData (Host, 0, 512, (UINT32 *)MmcHostInstance->CardInfo.ECSDData);
  if (EFI_ERROR (Status)) {
    DEBUG ((EFI_D_ERROR, "EmmcIdentificationMode(): ECSD read error, Status=%r.\n", Status));
    goto FreePageExit;
  }

  // Make sure device exiting data mode
  do {
    Status = EmmcGetDeviceState (MmcHostInstance, &State);
    if (EFI_ERROR (Status)) {
      DEBUG ((EFI_D_ERROR, "EmmcIdentificationMode(): Failed to get device state, Status=%r.\n", Status));
      goto FreePageExit;
    }
  } while (State == EMMC_DATA_STATE);

  // Set up media
  Media->BlockSize = EMMC_CARD_SIZE; // 512-byte support is mandatory for eMMC cards
  Media->MediaId = MmcHostInstance->CardInfo.CIDData.PSN;
  Media->ReadOnly = MmcHostInstance->CardInfo.CSDData.PERM_WRITE_PROTECT;
  Media->LogicalBlocksPerPhysicalBlock = 1;
  Media->IoAlign = 4;
  // Compute last block using bits [215:212] of the ECSD
  Media->LastBlock = MmcHostInstance->CardInfo.ECSDData->SECTOR_COUNT - 1; // eMMC isn't supposed to report this for
  // Cards <2GB in size, but the model does.

  // Setup card type
  MmcHostInstance->CardInfo.CardType = EMMC_CARD;
  return EFI_SUCCESS;

FreePageExit:
  FreePages (MmcHostInstance->CardInfo.ECSDData, EFI_SIZE_TO_PAGES (sizeof (ECSD)));
  return Status;
}
Beispiel #12
0
/**
  This function uses policy data from the platform to determine what operating
  system or system utility should be loaded and invoked.  This function call
  also optionally make the use of user input to determine the operating system
  or system utility to be loaded and invoked.  When the DXE Core has dispatched
  all the drivers on the dispatch queue, this function is called.  This
  function will attempt to connect the boot devices required to load and invoke
  the selected operating system or system utility.  During this process,
  additional firmware volumes may be discovered that may contain addition DXE
  drivers that can be dispatched by the DXE Core.   If a boot device cannot be
  fully connected, this function calls the DXE Service Dispatch() to allow the
  DXE drivers from any newly discovered firmware volumes to be dispatched.
  Then the boot device connection can be attempted again.  If the same boot
  device connection operation fails twice in a row, then that boot device has
  failed, and should be skipped.  This function should never return.

  @param  This             The EFI_BDS_ARCH_PROTOCOL instance.

  @return None.

**/
VOID
EFIAPI
BdsEntry (
  IN EFI_BDS_ARCH_PROTOCOL  *This
  )
{
  UINTN               Size;
  EFI_STATUS          Status;
  UINT16             *BootNext;
  UINTN               BootNextSize;
  CHAR16              BootVariableName[9];
  EFI_EVENT           EndOfDxeEvent;

  VOID *NewBase;

  //
  // Signal EndOfDxe PI Event
  //
  Status = gBS->CreateEventEx (
      EVT_NOTIFY_SIGNAL,
      TPL_NOTIFY,
      EmptyCallbackFunction,
      NULL,
      &gEfiEndOfDxeEventGroupGuid,
      &EndOfDxeEvent
      );
  if (!EFI_ERROR (Status)) {
    gBS->SignalEvent (EndOfDxeEvent);
  }

  PERF_END   (NULL, "DXE", NULL, 0);

  OemPostEndIndicator();

  //?им1??и▓бф?иж?б└бзиви┤и║б└1?б└и╣бд?бу?бъ?ж╠б└ижи║??2G?и▓бф?и║б└бъ??и▓бф?2?1?ио?бъ??ик?ив??HOB?D
  //memory reserved идидDикимивижy?asystem memory идидDик
  NewBase = AllocatePages (EFI_SIZE_TO_PAGES(SIZE_2GB));
  if (NULL == NewBase)
  {
    DEBUG ((EFI_D_ERROR, "There are not enough memory space..........\n"));
  }
  else
  {
    FreePages(NewBase,EFI_SIZE_TO_PAGES(SIZE_2GB));
  }

  //
  // Declare the Firmware Vendor
  //
  if (FixedPcdGetPtr(PcdFirmwareVendor) != NULL) {
    Size = 0x100;
    gST->FirmwareVendor = AllocateRuntimePool (Size);
    ASSERT (gST->FirmwareVendor != NULL);
    UnicodeSPrint (gST->FirmwareVendor, Size, L"%a EFI %a %a", PcdGetPtr(PcdFirmwareVendor), __DATE__, __TIME__);
  }

  //
  // Fixup Table CRC after we updated Firmware Vendor
  //
  gST->Hdr.CRC32 = 0;
  Status = gBS->CalculateCrc32 ((VOID*)gST, gST->Hdr.HeaderSize, &gST->Hdr.CRC32);
  ASSERT_EFI_ERROR (Status);
  if (EFI_ERROR (Status))
  {
        //for fortify
  }

  // If BootNext environment variable is defined then we just load it !
  BootNextSize = sizeof(UINT16);
  Status = GetGlobalEnvironmentVariable (L"BootNext", NULL, &BootNextSize, (VOID**)&BootNext);
  if (!EFI_ERROR(Status)) {
    ASSERT(BootNextSize == sizeof(UINT16));

    // Generate the requested Boot Entry variable name
    UnicodeSPrint (BootVariableName, 9 * sizeof(CHAR16), L"Boot%04X", *BootNext);

    // Set BootCurrent variable
    gRT->SetVariable (L"BootCurrent", &gEfiGlobalVariableGuid,
              EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
              BootNextSize, BootNext);

    FreePool (BootNext);

    // Start the requested Boot Entry
    Status = BdsStartBootOption (BootVariableName);
    if (Status != EFI_NOT_FOUND) {
      // BootNext has not been succeeded launched
      if (EFI_ERROR(Status)) {
        Print(L"Fail to start BootNext.\n");
      }

      // Delete the BootNext environment variable
      gRT->SetVariable (L"BootNext", &gEfiGlobalVariableGuid,
          EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
          0, NULL);
    }

    // Clear BootCurrent variable
    gRT->SetVariable (L"BootCurrent", &gEfiGlobalVariableGuid,
        EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
        0, NULL);
  }

  // If Boot Order does not exist then create a default entry
  DefineDefaultBootEntries ();

  // Now we need to setup the EFI System Table with information about the console devices.
  InitializeConsole ();

  //
  // Update the CRC32 in the EFI System Table header
  //
  gST->Hdr.CRC32 = 0;
  Status = gBS->CalculateCrc32 ((VOID*)gST, gST->Hdr.HeaderSize, &gST->Hdr.CRC32);
  ASSERT_EFI_ERROR (Status);
  if (EFI_ERROR (Status))
  {
        //for fortify
  }

  // Timer before initiating the default boot selection
  StartDefaultBootOnTimeout ();

  Status = VerifyBootLineEntry ();
  if(EFI_ERROR(Status))
  {
      DEBUG((EFI_D_ERROR,"Input Password Error, Boot failed!\n"));
      return;
  }

  // Start the Boot Menu
  Status = BootMenuMain ();
  ASSERT_EFI_ERROR (Status);
  if (EFI_ERROR (Status))
  {
        //for fortify
  }

}
Beispiel #13
0
EFI_STATUS
EFIAPI
InitializeQemuRamfb (
  IN EFI_HANDLE           ImageHandle,
  IN EFI_SYSTEM_TABLE     *SystemTable
  )
{
  EFI_DEVICE_PATH_PROTOCOL  *RamfbDevicePath;
  EFI_DEVICE_PATH_PROTOCOL  *GopDevicePath;
  VOID                      *DevicePath;
  VENDOR_DEVICE_PATH        VendorDeviceNode;
  ACPI_ADR_DEVICE_PATH      AcpiDeviceNode;
  EFI_STATUS                Status;
  EFI_PHYSICAL_ADDRESS      FbBase;
  UINTN                     FbSize, MaxFbSize, Pages;
  UINTN                     FwCfgSize;
  UINTN                     Index;

  if (!QemuFwCfgIsAvailable ()) {
    DEBUG ((DEBUG_INFO, "Ramfb: no FwCfg\n"));
    return EFI_NOT_FOUND;
  }

  Status = QemuFwCfgFindFile ("etc/ramfb", &mRamfbFwCfgItem, &FwCfgSize);
  if (EFI_ERROR (Status)) {
    return EFI_NOT_FOUND;
  }
  if (FwCfgSize != sizeof (RAMFB_CONFIG)) {
    DEBUG ((DEBUG_ERROR, "Ramfb: FwCfg size mismatch (expected %lu, got %lu)\n",
      (UINT64)sizeof (RAMFB_CONFIG), (UINT64)FwCfgSize));
    return EFI_PROTOCOL_ERROR;
  }

  MaxFbSize = 0;
  for (Index = 0; Index < ARRAY_SIZE (mQemuRamfbModeInfo); Index++) {
    mQemuRamfbModeInfo[Index].PixelsPerScanLine =
      mQemuRamfbModeInfo[Index].HorizontalResolution;
    mQemuRamfbModeInfo[Index].PixelFormat =
      PixelBlueGreenRedReserved8BitPerColor;
    FbSize = RAMFB_BPP *
      mQemuRamfbModeInfo[Index].HorizontalResolution *
      mQemuRamfbModeInfo[Index].VerticalResolution;
    if (MaxFbSize < FbSize) {
      MaxFbSize = FbSize;
    }
    DEBUG ((DEBUG_INFO, "Ramfb: Mode %lu: %ux%u, %lu kB\n", (UINT64)Index,
      mQemuRamfbModeInfo[Index].HorizontalResolution,
      mQemuRamfbModeInfo[Index].VerticalResolution,
      (UINT64)(FbSize / 1024)));
  }

  Pages = EFI_SIZE_TO_PAGES (MaxFbSize);
  MaxFbSize = EFI_PAGES_TO_SIZE (Pages);
  FbBase = (EFI_PHYSICAL_ADDRESS)(UINTN)AllocateReservedPages (Pages);
  if (FbBase == 0) {
    DEBUG ((DEBUG_ERROR, "Ramfb: memory allocation failed\n"));
    return EFI_OUT_OF_RESOURCES;
  }
  DEBUG ((DEBUG_INFO, "Ramfb: Framebuffer at 0x%lx, %lu kB, %lu pages\n",
    (UINT64)FbBase, (UINT64)(MaxFbSize / 1024), (UINT64)Pages));
  mQemuRamfbMode.FrameBufferSize = MaxFbSize;
  mQemuRamfbMode.FrameBufferBase = FbBase;

  //
  // 800 x 600
  //
  QemuRamfbGraphicsOutputSetMode (&mQemuRamfbGraphicsOutput, 1);

  //
  // ramfb vendor devpath
  //
  VendorDeviceNode.Header.Type = HARDWARE_DEVICE_PATH;
  VendorDeviceNode.Header.SubType = HW_VENDOR_DP;
  CopyGuid (&VendorDeviceNode.Guid, &gQemuRamfbGuid);
  SetDevicePathNodeLength (&VendorDeviceNode.Header,
    sizeof (VENDOR_DEVICE_PATH));

  RamfbDevicePath = AppendDevicePathNode (NULL,
    (EFI_DEVICE_PATH_PROTOCOL *) &VendorDeviceNode);
  if (RamfbDevicePath == NULL) {
    Status = EFI_OUT_OF_RESOURCES;
    goto FreeFramebuffer;
  }

  Status = gBS->InstallMultipleProtocolInterfaces (
                  &mRamfbHandle,
                  &gEfiDevicePathProtocolGuid,
                  RamfbDevicePath,
                  NULL
                  );
  if (EFI_ERROR (Status)) {
    DEBUG ((DEBUG_ERROR, "Ramfb: install Ramfb Vendor DevicePath failed: %r\n",
      Status));
    goto FreeRamfbDevicePath;
  }

  //
  // gop devpath + protocol
  //
  AcpiDeviceNode.Header.Type = ACPI_DEVICE_PATH;
  AcpiDeviceNode.Header.SubType = ACPI_ADR_DP;
  AcpiDeviceNode.ADR = ACPI_DISPLAY_ADR (
    1,                                       // DeviceIdScheme
    0,                                       // HeadId
    0,                                       // NonVgaOutput
    1,                                       // BiosCanDetect
    0,                                       // VendorInfo
    ACPI_ADR_DISPLAY_TYPE_EXTERNAL_DIGITAL,  // Type
    0,                                       // Port
    0                                        // Index
    );
  SetDevicePathNodeLength (&AcpiDeviceNode.Header,
    sizeof (ACPI_ADR_DEVICE_PATH));

  GopDevicePath = AppendDevicePathNode (RamfbDevicePath,
    (EFI_DEVICE_PATH_PROTOCOL *) &AcpiDeviceNode);
  if (GopDevicePath == NULL) {
    Status = EFI_OUT_OF_RESOURCES;
    goto FreeRamfbHandle;
  }

  Status = gBS->InstallMultipleProtocolInterfaces (
                  &mGopHandle,
                  &gEfiDevicePathProtocolGuid,
                  GopDevicePath,
                  &gEfiGraphicsOutputProtocolGuid,
                  &mQemuRamfbGraphicsOutput,
                  NULL
                  );
  if (EFI_ERROR (Status)) {
    DEBUG ((DEBUG_ERROR, "Ramfb: install GOP DevicePath failed: %r\n",
      Status));
    goto FreeGopDevicePath;
  }

  Status = gBS->OpenProtocol (
                  mRamfbHandle,
                  &gEfiDevicePathProtocolGuid,
                  &DevicePath,
                  gImageHandle,
                  mGopHandle,
                  EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
                  );
  if (EFI_ERROR (Status)) {
    DEBUG ((DEBUG_ERROR, "Ramfb: OpenProtocol failed: %r\n", Status));
    goto FreeGopHandle;
  }

  return EFI_SUCCESS;

FreeGopHandle:
  gBS->UninstallMultipleProtocolInterfaces (
         mGopHandle,
         &gEfiDevicePathProtocolGuid,
         GopDevicePath,
         &gEfiGraphicsOutputProtocolGuid,
         &mQemuRamfbGraphicsOutput,
         NULL
         );
FreeGopDevicePath:
  FreePool (GopDevicePath);
FreeRamfbHandle:
  gBS->UninstallMultipleProtocolInterfaces (
         mRamfbHandle,
         &gEfiDevicePathProtocolGuid,
         RamfbDevicePath,
         NULL
         );
FreeRamfbDevicePath:
  FreePool (RamfbDevicePath);
FreeFramebuffer:
  FreePages ((VOID*)(UINTN)mQemuRamfbMode.FrameBufferBase, Pages);
  return Status;
}
Beispiel #14
0
/**
  Load a given Framework SMM driver into SMRAM and invoke its entry point.

  @param[in]   ParentImageHandle     Parent Image Handle.
  @param[in]   FilePath              Location of the image to be installed as the handler.
  @param[in]   SourceBuffer          Optional source buffer in case the image file
                                     is in memory.
  @param[in]   SourceSize            Size of the source image file, if in memory.
  @param[out]  ImageHandle           The handle that the base driver uses to decode 
                                     the handler. Unique among SMM handlers only, 
                                     not unique across DXE/EFI.

  @retval      EFI_SUCCESS           The operation was successful.
  @retval      EFI_OUT_OF_RESOURCES  There were no additional SMRAM resources to load the handler
  @retval      EFI_UNSUPPORTED       Can not find its copy in normal memory.
  @retval      EFI_INVALID_PARAMETER The handlers was not the correct image type
**/
EFI_STATUS
LoadImage (
  IN      EFI_HANDLE                ParentImageHandle,
  IN      EFI_DEVICE_PATH_PROTOCOL  *FilePath,
  IN      VOID                      *SourceBuffer,
  IN      UINTN                     SourceSize,
  OUT     EFI_HANDLE                *ImageHandle
  )
{
  EFI_STATUS            Status;
  UINTN                 PageCount;
  UINTN                 OrgPageCount;
  EFI_PHYSICAL_ADDRESS  DstBuffer;

  if (FilePath == NULL || ImageHandle == NULL) {    
    return EFI_INVALID_PARAMETER;
  }

  PageCount = 1;
  do {
    OrgPageCount = PageCount;
    DstBuffer = (UINTN)-1;
    Status = gSmst->SmmAllocatePages (
                      AllocateMaxAddress,
                      EfiRuntimeServicesCode,
                      PageCount,
                      &DstBuffer
                      );
    if (EFI_ERROR (Status)) {
      return Status;
    }

    Status = mLoadPe32Image->LoadPeImage (
                               mLoadPe32Image,
                               ParentImageHandle,
                               FilePath,
                               SourceBuffer,
                               SourceSize,
                               DstBuffer,
                               &PageCount,
                               ImageHandle,
                               NULL,
                               EFI_LOAD_PE_IMAGE_ATTRIBUTE_NONE
                               );
    if (EFI_ERROR (Status)) {
      FreePages ((VOID *)(UINTN)DstBuffer, OrgPageCount);
    }
  } while (Status == EFI_BUFFER_TOO_SMALL);

  if (!EFI_ERROR (Status)) {
    ///
    /// Update MP state in Framework SMST before transferring control to Framework SMM driver entry point
    ///
    mFrameworkSmst->SmmStartupThisAp      = gSmst->SmmStartupThisAp;
    mFrameworkSmst->NumberOfCpus          = mNumberOfProcessors;
    mFrameworkSmst->CurrentlyExecutingCpu = gSmst->CurrentlyExecutingCpu;

    Status = gBS->StartImage (*ImageHandle, NULL, NULL);
    if (EFI_ERROR (Status)) {
      mLoadPe32Image->UnLoadPeImage (mLoadPe32Image, *ImageHandle);
      *ImageHandle = NULL;
      FreePages ((VOID *)(UINTN)DstBuffer, PageCount);
    }
  }

  return Status;
}
Beispiel #15
0
 DynamicStack::~DynamicStack()
 {
     FreePages();
 }
Beispiel #16
0
EFI_STATUS
MmCoreFfsFindMmDriver (
  IN  EFI_FIRMWARE_VOLUME_HEADER  *FwVolHeader
  )
/*++

Routine Description:
  Given the pointer to the Firmware Volume Header find the
  MM driver and return it's PE32 image.

Arguments:
  FwVolHeader - Pointer to memory mapped FV

Returns:
  other       - Failure

--*/
{
  EFI_STATUS                              Status;
  EFI_STATUS                              DepexStatus;
  EFI_FFS_FILE_HEADER                     *FileHeader;
  EFI_FV_FILETYPE                         FileType;
  VOID                                    *Pe32Data;
  UINTN                                   Pe32DataSize;
  VOID                                    *Depex;
  UINTN                                   DepexSize;
  UINTN                                   Index;
  EFI_COMMON_SECTION_HEADER               *Section;
  VOID                                    *SectionData;
  UINTN                                   SectionDataSize;
  UINT32                                  DstBufferSize;
  VOID                                    *ScratchBuffer;
  UINT32                                  ScratchBufferSize;
  VOID                                    *DstBuffer;
  UINT16                                  SectionAttribute;
  UINT32                                  AuthenticationStatus;
  EFI_FIRMWARE_VOLUME_HEADER              *InnerFvHeader;

  DEBUG ((DEBUG_INFO, "MmCoreFfsFindMmDriver - 0x%x\n", FwVolHeader));

  if (FvHasBeenProcessed (FwVolHeader)) {
    return EFI_SUCCESS;
  }

  FvIsBeingProcesssed (FwVolHeader);

  //
  // First check for encapsulated compressed firmware volumes
  //
  FileHeader = NULL;
  do {
    Status = FfsFindNextFile (EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE,
               FwVolHeader, &FileHeader);
    if (EFI_ERROR (Status)) {
      break;
    }
    Status = FfsFindSectionData (EFI_SECTION_GUID_DEFINED, FileHeader,
               &SectionData, &SectionDataSize);
    if (EFI_ERROR (Status)) {
      break;
    }
    Section = (EFI_COMMON_SECTION_HEADER *)(FileHeader + 1);
    Status = ExtractGuidedSectionGetInfo (Section, &DstBufferSize,
               &ScratchBufferSize, &SectionAttribute);
    if (EFI_ERROR (Status)) {
      break;
    }

    //
    // Allocate scratch buffer
    //
    ScratchBuffer = (VOID *)(UINTN)AllocatePages (EFI_SIZE_TO_PAGES (ScratchBufferSize));
    if (ScratchBuffer == NULL) {
      return EFI_OUT_OF_RESOURCES;
    }

    //
    // Allocate destination buffer, extra one page for adjustment
    //
    DstBuffer = (VOID *)(UINTN)AllocatePages (EFI_SIZE_TO_PAGES (DstBufferSize));
    if (DstBuffer == NULL) {
      return EFI_OUT_OF_RESOURCES;
    }

    //
    // Call decompress function
    //
    Status = ExtractGuidedSectionDecode (Section, &DstBuffer, ScratchBuffer,
                &AuthenticationStatus);
    FreePages (ScratchBuffer, EFI_SIZE_TO_PAGES (ScratchBufferSize));
    if (EFI_ERROR (Status)) {
      goto FreeDstBuffer;
    }

    DEBUG ((DEBUG_INFO,
      "Processing compressed firmware volume (AuthenticationStatus == %x)\n",
      AuthenticationStatus));

    Status = FindFfsSectionInSections (DstBuffer, DstBufferSize,
               EFI_SECTION_FIRMWARE_VOLUME_IMAGE, &Section);
    if (EFI_ERROR (Status)) {
      goto FreeDstBuffer;
    }

    InnerFvHeader = (VOID *)(Section + 1);
    Status = MmCoreFfsFindMmDriver (InnerFvHeader);
    if (EFI_ERROR (Status)) {
      goto FreeDstBuffer;
    }
  } while (TRUE);

  for (Index = 0; Index < sizeof (mMmFileTypes) / sizeof (mMmFileTypes[0]); Index++) {
    DEBUG ((DEBUG_INFO, "Check MmFileTypes - 0x%x\n", mMmFileTypes[Index]));
    FileType = mMmFileTypes[Index];
    FileHeader = NULL;
    do {
      Status = FfsFindNextFile (FileType, FwVolHeader, &FileHeader);
      if (!EFI_ERROR (Status)) {
        Status = FfsFindSectionData (EFI_SECTION_PE32, FileHeader, &Pe32Data, &Pe32DataSize);
        DEBUG ((DEBUG_INFO, "Find PE data - 0x%x\n", Pe32Data));
        DepexStatus = FfsFindSectionData (EFI_SECTION_MM_DEPEX, FileHeader, &Depex, &DepexSize);
        if (!EFI_ERROR (DepexStatus)) {
          MmAddToDriverList (FwVolHeader, Pe32Data, Pe32DataSize, Depex, DepexSize, &FileHeader->Name);
        }
      }
    } while (!EFI_ERROR (Status));
  }

  return EFI_SUCCESS;

FreeDstBuffer:
  FreePages (DstBuffer, EFI_SIZE_TO_PAGES (DstBufferSize));

  return Status;
}
Beispiel #17
0
/**
  Allocates one or more 4KB pages of a certain memory type at a specified alignment.

  Allocates the number of 4KB pages specified by Pages of a certain memory type with an alignment
  specified by Alignment.  The allocated buffer is returned.  If Pages is 0, then NULL is returned.
  If there is not enough memory at the specified alignment remaining to satisfy the request, then
  NULL is returned.
  If Alignment is not a power of two and Alignment is not zero, then ASSERT().

  @param  MemoryType            The type of memory to allocate.
  @param  Pages                 The number of 4 KB pages to allocate.
  @param  Alignment             The requested alignment of the allocation.  Must be a power of two.
                                If Alignment is zero, then byte alignment is used.

  @return A pointer to the allocated buffer or NULL if allocation fails.

**/
VOID *
InternalAllocateAlignedPages (
  IN EFI_MEMORY_TYPE  MemoryType,
  IN UINTN            Pages,
  IN UINTN            Alignment
  )
{
  EFI_STATUS            Status;
  VOID                  *Memory;
  UINTN                 AlignedMemory;
  UINTN                 AlignmentMask;
  UINTN                 UnalignedPages;
  UINTN                 RealPages;

  //
  // Alignment must be a power of two or zero.
  //
  ASSERT ((Alignment & (Alignment - 1)) == 0);

  if (Pages == 0) {
    return NULL;
  }
  if (Alignment > EFI_PAGE_SIZE) {
    //
    // Caculate the total number of pages since alignment is larger than page size.
    //
    AlignmentMask  = Alignment - 1;
    RealPages      = Pages + EFI_SIZE_TO_PAGES (Alignment);
    //
    // Make sure that Pages plus EFI_SIZE_TO_PAGES (Alignment) does not overflow.
    //
    ASSERT (RealPages > Pages);

    Memory = gEmuThunk->Valloc (Pages * EFI_PAGE_SIZE);
    if (Memory != NULL) {
      return NULL;
    }
    AlignedMemory  = ((UINTN) Memory + AlignmentMask) & ~AlignmentMask;
    UnalignedPages = EFI_SIZE_TO_PAGES (AlignedMemory - (UINTN) Memory);
    if (UnalignedPages > 0) {
      //
      // Free first unaligned page(s).
      //
      FreePages (Memory, UnalignedPages);
    }
    Memory         = (VOID *) (AlignedMemory + EFI_PAGES_TO_SIZE (Pages));
    UnalignedPages = RealPages - Pages - UnalignedPages;
    if (UnalignedPages > 0) {
      //
      // Free last unaligned page(s).
      //
      FreePages (Memory, UnalignedPages);
    }
  } else {
    //
    // Do not over-allocate pages in this case.
    //
    Memory = gEmuThunk->Valloc (Pages * EFI_PAGE_SIZE);
    if (Memory != NULL) {
      return NULL;
    }
    AlignedMemory  = (UINTN) Memory;
  }
  return (VOID *) AlignedMemory;
}
Beispiel #18
0
/**
  Exit the EBL. If the command processor sees EFI_ABORTED return status it will
  exit the EBL.

  Argv[0] - "exit"

  @param  Argc   Number of command arguments in Argv
  @param  Argv   Array of strings that represent the parsed command line.
                 Argv[0] is the command name

  @return EFI_ABORTED

**/
EFI_STATUS
EFIAPI
EblExitCmd (
  IN UINTN  Argc,
  IN CHAR8  **Argv
  )
{
  EFI_STATUS              Status;
  UINTN                   MemoryMapSize;
  EFI_MEMORY_DESCRIPTOR   *MemoryMap;
  UINTN                   MapKey;
  UINTN                   DescriptorSize;
  UINT32                  DescriptorVersion;
  UINTN                   Pages;

  if (Argc > 1) {
    if (AsciiStriCmp (Argv[1], "efi") != 0) {
      return EFI_ABORTED;
    }
  } else if (Argc == 1) {
    return EFI_ABORTED;
  }

  MemoryMap = NULL;
  MemoryMapSize = 0;
  do {
    Status = gBS->GetMemoryMap (
                    &MemoryMapSize,
                    MemoryMap,
                    &MapKey,
                    &DescriptorSize,
                    &DescriptorVersion
                    );
    if (Status == EFI_BUFFER_TOO_SMALL) {

      Pages = EFI_SIZE_TO_PAGES (MemoryMapSize) + 1;
      MemoryMap = AllocatePages (Pages);

      //
      // Get System MemoryMap
      //
      Status = gBS->GetMemoryMap (
                      &MemoryMapSize,
                      MemoryMap,
                      &MapKey,
                      &DescriptorSize,
                      &DescriptorVersion
                      );
      // Don't do anything between the GetMemoryMap() and ExitBootServices()
      if (!EFI_ERROR (Status)) {
        Status = gBS->ExitBootServices (gImageHandle, MapKey);
        if (EFI_ERROR (Status)) {
          FreePages (MemoryMap, Pages);
          MemoryMap = NULL;
          MemoryMapSize = 0;
        }
      }
    }
  } while (EFI_ERROR (Status));

  //
  // At this point it is very dangerous to do things EFI as most of EFI is now gone.
  // This command is useful if you are working with a debugger as it will shutdown
  // DMA and other things that could break a soft resets.
  //
  CpuDeadLoop ();

  // Should never get here, but makes the compiler happy
  return EFI_ABORTED;
}
Beispiel #19
0
EFI_STATUS
TryRunningQemuKernel (
  VOID
  )
{
  EFI_STATUS                Status;
  UINTN                     KernelSize;
  UINTN                     KernelInitialSize;
  VOID                      *KernelBuf;
  UINTN                     SetupSize;
  VOID                      *SetupBuf;
  UINTN                     CommandLineSize;
  CHAR8                     *CommandLine;
  UINTN                     InitrdSize;
  VOID*                     InitrdData;

  SetupBuf = NULL;
  SetupSize = 0;
  KernelBuf = NULL;
  KernelInitialSize = 0;
  CommandLine = NULL;
  CommandLineSize = 0;
  InitrdData = NULL;
  InitrdSize = 0;

  if (!QemuFwCfgIsAvailable ()) {
    return EFI_NOT_FOUND;
  }

  QemuFwCfgSelectItem (QemuFwCfgItemKernelSize);
  KernelSize = (UINTN) QemuFwCfgRead64 ();

  QemuFwCfgSelectItem (QemuFwCfgItemKernelSetupSize);
  SetupSize = (UINTN) QemuFwCfgRead64 ();

  if (KernelSize == 0 || SetupSize == 0) {
    DEBUG ((EFI_D_INFO, "qemu -kernel was not used.\n"));
    return EFI_NOT_FOUND;
  }

  SetupBuf = LoadLinuxAllocateKernelSetupPages (EFI_SIZE_TO_PAGES (SetupSize));
  if (SetupBuf == NULL) {
    DEBUG ((EFI_D_ERROR, "Unable to allocate memory for kernel setup!\n"));
    return EFI_OUT_OF_RESOURCES;
  }

  DEBUG ((EFI_D_INFO, "Setup size: 0x%x\n", (UINT32) SetupSize));
  DEBUG ((EFI_D_INFO, "Reading kernel setup image ..."));
  QemuFwCfgSelectItem (QemuFwCfgItemKernelSetupData);
  QemuFwCfgReadBytes (SetupSize, SetupBuf);
  DEBUG ((EFI_D_INFO, " [done]\n"));

  Status = LoadLinuxCheckKernelSetup (SetupBuf, SetupSize);
  if (EFI_ERROR (Status)) {
    goto FreeAndReturn;
  }

  Status = LoadLinuxInitializeKernelSetup (SetupBuf);
  if (EFI_ERROR (Status)) {
    goto FreeAndReturn;
  }

  KernelInitialSize = LoadLinuxGetKernelSize (SetupBuf, KernelSize);
  if (KernelInitialSize == 0) {
    Status = EFI_UNSUPPORTED;
    goto FreeAndReturn;
  }

  KernelBuf = LoadLinuxAllocateKernelPages (
                SetupBuf,
                EFI_SIZE_TO_PAGES (KernelInitialSize));
  if (KernelBuf == NULL) {
    DEBUG ((EFI_D_ERROR, "Unable to allocate memory for kernel!\n"));
    Status = EFI_OUT_OF_RESOURCES;
    goto FreeAndReturn;
  }

  DEBUG ((EFI_D_INFO, "Kernel size: 0x%x\n", (UINT32) KernelSize));
  DEBUG ((EFI_D_INFO, "Reading kernel image ..."));
  QemuFwCfgSelectItem (QemuFwCfgItemKernelData);
  QemuFwCfgReadBytes (KernelSize, KernelBuf);
  DEBUG ((EFI_D_INFO, " [done]\n"));

  QemuFwCfgSelectItem (QemuFwCfgItemCommandLineSize);
  CommandLineSize = (UINTN) QemuFwCfgRead64 ();

  if (CommandLineSize > 0) {
    CommandLine = LoadLinuxAllocateCommandLinePages (
                    EFI_SIZE_TO_PAGES (CommandLineSize));
    QemuFwCfgSelectItem (QemuFwCfgItemCommandLineData);
    QemuFwCfgReadBytes (CommandLineSize, CommandLine);
  } else {
    CommandLine = NULL;
  }

  Status = LoadLinuxSetCommandLine (SetupBuf, CommandLine);
  if (EFI_ERROR (Status)) {
    goto FreeAndReturn;
  }

  QemuFwCfgSelectItem (QemuFwCfgItemInitrdSize);
  InitrdSize = (UINTN) QemuFwCfgRead64 ();

  if (InitrdSize > 0) {
    InitrdData = LoadLinuxAllocateInitrdPages (
                   SetupBuf,
                   EFI_SIZE_TO_PAGES (InitrdSize)
                   );
    DEBUG ((EFI_D_INFO, "Initrd size: 0x%x\n", (UINT32) InitrdSize));
    DEBUG ((EFI_D_INFO, "Reading initrd image ..."));
    QemuFwCfgSelectItem (QemuFwCfgItemInitrdData);
    QemuFwCfgReadBytes (InitrdSize, InitrdData);
    DEBUG ((EFI_D_INFO, " [done]\n"));
  } else {
    InitrdData = NULL;
  }

  Status = LoadLinuxSetInitrd (SetupBuf, InitrdData, InitrdSize);
  if (EFI_ERROR (Status)) {
    goto FreeAndReturn;
  }

  Status = LoadLinux (KernelBuf, SetupBuf);

FreeAndReturn:
  if (SetupBuf != NULL) {
    FreePages (SetupBuf, EFI_SIZE_TO_PAGES (SetupSize));
  }
  if (KernelBuf != NULL) {
    FreePages (KernelBuf, EFI_SIZE_TO_PAGES (KernelInitialSize));
  }
  if (CommandLine != NULL) {
    FreePages (CommandLine, EFI_SIZE_TO_PAGES (CommandLineSize));
  }
  if (InitrdData != NULL) {
    FreePages (InitrdData, EFI_SIZE_TO_PAGES (InitrdSize));
  }

  return Status;
}
Beispiel #20
0
/**
  Install ACPI Firmware Performance Data Table (FPDT).

  @return Status code.

**/
EFI_STATUS
InstallFirmwarePerformanceDataTable (
  VOID
  )
{
  EFI_STATUS                    Status;
  EFI_ACPI_TABLE_PROTOCOL       *AcpiTableProtocol;
  UINTN                         Size;
  UINT8                         *SmmBootRecordCommBuffer;
  EFI_SMM_COMMUNICATE_HEADER    *SmmCommBufferHeader;
  SMM_BOOT_RECORD_COMMUNICATE   *SmmCommData;
  UINTN                         CommSize;
  UINTN                         BootPerformanceDataSize;
  UINT8                         *BootPerformanceData; 
  EFI_SMM_COMMUNICATION_PROTOCOL  *Communication;
  FIRMWARE_PERFORMANCE_VARIABLE PerformanceVariable;

  //
  // Get AcpiTable Protocol.
  //
  Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID **) &AcpiTableProtocol);
  if (EFI_ERROR (Status)) {
    return Status;
  }

  //
  // Collect boot records from SMM drivers.
  //
  SmmBootRecordCommBuffer = NULL;
  SmmCommData             = NULL;
  Status = gBS->LocateProtocol (&gEfiSmmCommunicationProtocolGuid, NULL, (VOID **) &Communication);
  if (!EFI_ERROR (Status)) {
    //
    // Initialize communicate buffer 
    //
    SmmBootRecordCommBuffer = AllocateZeroPool (SMM_BOOT_RECORD_COMM_SIZE);
    ASSERT (SmmBootRecordCommBuffer != NULL);
    SmmCommBufferHeader = (EFI_SMM_COMMUNICATE_HEADER*)SmmBootRecordCommBuffer;
    SmmCommData = (SMM_BOOT_RECORD_COMMUNICATE*)SmmCommBufferHeader->Data;
    ZeroMem((UINT8*)SmmCommData, sizeof(SMM_BOOT_RECORD_COMMUNICATE));

    CopyGuid (&SmmCommBufferHeader->HeaderGuid, &gEfiFirmwarePerformanceGuid);
    SmmCommBufferHeader->MessageLength = sizeof(SMM_BOOT_RECORD_COMMUNICATE);
    CommSize = SMM_BOOT_RECORD_COMM_SIZE;
  
    //
    // Get the size of boot records.
    //
    SmmCommData->Function       = SMM_FPDT_FUNCTION_GET_BOOT_RECORD_SIZE;
    SmmCommData->BootRecordData = NULL;
    Status = Communication->Communicate (Communication, SmmBootRecordCommBuffer, &CommSize);
    ASSERT_EFI_ERROR (Status);
  
    if (!EFI_ERROR (SmmCommData->ReturnStatus) && SmmCommData->BootRecordSize != 0) {
      //
      // Get all boot records
      //
      SmmCommData->Function       = SMM_FPDT_FUNCTION_GET_BOOT_RECORD_DATA;
      SmmCommData->BootRecordData = AllocateZeroPool(SmmCommData->BootRecordSize);
      ASSERT (SmmCommData->BootRecordData != NULL);
      
      Status = Communication->Communicate (Communication, SmmBootRecordCommBuffer, &CommSize);
      ASSERT_EFI_ERROR (Status);
      ASSERT_EFI_ERROR(SmmCommData->ReturnStatus);
    }
  }

  //
  // Prepare memory for Boot Performance table.
  // Boot Performance table includes BasicBoot record, and one or more appended Boot Records. 
  //
  BootPerformanceDataSize = sizeof (BOOT_PERFORMANCE_TABLE) + mBootRecordSize + PcdGet32 (PcdExtFpdtBootRecordPadSize);
  if (SmmCommData != NULL) {
    BootPerformanceDataSize += SmmCommData->BootRecordSize;
  }

  //
  // Try to allocate the same runtime buffer as last time boot.
  //
  ZeroMem (&PerformanceVariable, sizeof (PerformanceVariable));
  Size = sizeof (PerformanceVariable);
  Status = gRT->GetVariable (
                  EFI_FIRMWARE_PERFORMANCE_VARIABLE_NAME,
                  &gEfiFirmwarePerformanceGuid,
                  NULL,
                  &Size,
                  &PerformanceVariable
                  );
  if (!EFI_ERROR (Status)) {
    Status = gBS->AllocatePages (
                    AllocateAddress,
                    EfiReservedMemoryType,
                    EFI_SIZE_TO_PAGES (BootPerformanceDataSize),
                    &PerformanceVariable.BootPerformanceTablePointer
                    );
    if (!EFI_ERROR (Status)) {
      mAcpiBootPerformanceTable = (BOOT_PERFORMANCE_TABLE *) (UINTN) PerformanceVariable.BootPerformanceTablePointer;
    }
  }

  if (mAcpiBootPerformanceTable == NULL) {
    //
    // Fail to allocate at specified address, continue to allocate at any address.
    //
    mAcpiBootPerformanceTable = (BOOT_PERFORMANCE_TABLE *) FpdtAllocateReservedMemoryBelow4G (BootPerformanceDataSize);
  }
  DEBUG ((EFI_D_INFO, "FPDT: ACPI Boot Performance Table address = 0x%x\n", mAcpiBootPerformanceTable));

  if (mAcpiBootPerformanceTable == NULL) {
    if (SmmCommData != NULL && SmmCommData->BootRecordData != NULL) {
      FreePool (SmmCommData->BootRecordData);
    }
    if (SmmBootRecordCommBuffer != NULL) {
      FreePool (SmmBootRecordCommBuffer);
    }
    if (mAcpiS3PerformanceTable != NULL) {
      FreePages (mAcpiS3PerformanceTable, EFI_SIZE_TO_PAGES (sizeof (S3_PERFORMANCE_TABLE)));
    }
    return EFI_OUT_OF_RESOURCES;
  }

  //
  // Prepare Boot Performance Table.
  //
  BootPerformanceData = (UINT8 *) mAcpiBootPerformanceTable;
  //
  // Fill Basic Boot record to Boot Performance Table.
  //
  CopyMem (mAcpiBootPerformanceTable, &mBootPerformanceTableTemplate, sizeof (mBootPerformanceTableTemplate));
  BootPerformanceData = BootPerformanceData + mAcpiBootPerformanceTable->Header.Length;
  //
  // Fill Boot records from boot drivers.
  //
  CopyMem (BootPerformanceData, mBootRecordBuffer, mBootRecordSize);
  mAcpiBootPerformanceTable->Header.Length += mBootRecordSize;
  BootPerformanceData = BootPerformanceData + mBootRecordSize;
  if (SmmCommData != NULL && SmmCommData->BootRecordData != NULL) {
    //
    // Fill Boot records from SMM drivers.
    //
    CopyMem (BootPerformanceData, SmmCommData->BootRecordData, SmmCommData->BootRecordSize);
    FreePool (SmmCommData->BootRecordData);
    mAcpiBootPerformanceTable->Header.Length = (UINT32) (mAcpiBootPerformanceTable->Header.Length + SmmCommData->BootRecordSize);
    BootPerformanceData = BootPerformanceData + SmmCommData->BootRecordSize;
  }
  if (SmmBootRecordCommBuffer != NULL) {
    FreePool (SmmBootRecordCommBuffer);
  }

  //
  // Save Boot Performance Table address to Variable for use in S4 resume.
  //
  PerformanceVariable.BootPerformanceTablePointer = (EFI_PHYSICAL_ADDRESS) (UINTN) mAcpiBootPerformanceTable;
  //
  // Update Boot Performance Table Pointer in template.
  //
  mFirmwarePerformanceTableTemplate.BootPointerRecord.BootPerformanceTablePointer = (UINT64) (UINTN) mAcpiBootPerformanceTable;

  //
  // Save S3 Performance Table address to Variable for use in S4 resume.
  //
  PerformanceVariable.S3PerformanceTablePointer = (EFI_PHYSICAL_ADDRESS) (UINTN) mAcpiS3PerformanceTable;
  //
  // Update S3 Performance Table Pointer in template.
  //
  mFirmwarePerformanceTableTemplate.S3PointerRecord.S3PerformanceTablePointer = (UINT64) (UINTN) mAcpiS3PerformanceTable;
  //
  // Save Runtime Performance Table pointers to Variable.
  //
  Status = gRT->SetVariable (
                  EFI_FIRMWARE_PERFORMANCE_VARIABLE_NAME,
                  &gEfiFirmwarePerformanceGuid,
                  EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
                  sizeof (PerformanceVariable),
                  &PerformanceVariable
                  );
  ASSERT_EFI_ERROR (Status);

  //
  // Publish Firmware Performance Data Table.
  //
  FpdtAcpiTableChecksum ((UINT8 *) &mFirmwarePerformanceTableTemplate, mFirmwarePerformanceTableTemplate.Header.Length);
  Status = AcpiTableProtocol->InstallAcpiTable (
                                AcpiTableProtocol,
                                &mFirmwarePerformanceTableTemplate,
                                mFirmwarePerformanceTableTemplate.Header.Length,
                                &mFirmwarePerformanceTableTemplateKey
                                );
  if (EFI_ERROR (Status)) {
    FreePages (mAcpiBootPerformanceTable, EFI_SIZE_TO_PAGES (BootPerformanceDataSize));
    if (mAcpiS3PerformanceTable != NULL) {
      FreePages (mAcpiS3PerformanceTable, EFI_SIZE_TO_PAGES (sizeof (S3_PERFORMANCE_TABLE)));
    }
    mAcpiBootPerformanceTable = NULL;
    mAcpiS3PerformanceTable = NULL;
    return Status;
  }
  
  //
  // Free temp Boot record, and update Boot Record to point to Basic Boot performance table.
  //
  if (mBootRecordBuffer != NULL) {
    FreePool (mBootRecordBuffer);
  }
  mBootRecordBuffer  = (UINT8 *) mAcpiBootPerformanceTable;
  mBootRecordSize    = mAcpiBootPerformanceTable->Header.Length;
  mBootRecordMaxSize = mBootRecordSize + PcdGet32 (PcdExtFpdtBootRecordPadSize);
  
  return EFI_SUCCESS;
}
Beispiel #21
0
/**
  Sends SD command to an SD card that is attached to the SD controller.

  The PassThru() function sends the SD command specified by Packet to the SD card
  specified by Slot.

  If Packet is successfully sent to the SD card, then EFI_SUCCESS is returned.

  If a device error occurs while sending the Packet, then EFI_DEVICE_ERROR is returned.

  If Slot is not in a valid range for the SD controller, then EFI_INVALID_PARAMETER
  is returned.

  If Packet defines a data command but both InDataBuffer and OutDataBuffer are NULL,
  EFI_INVALID_PARAMETER is returned.

  @param[in]     This           A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
  @param[in]     Slot           The slot number of the SD card to send the command to.
  @param[in,out] Packet         A pointer to the SD command data structure.
  @param[in]     Event          If Event is NULL, blocking I/O is performed. If Event is
                                not NULL, then nonblocking I/O is performed, and Event
                                will be signaled when the Packet completes.

  @retval EFI_SUCCESS           The SD Command Packet was sent by the host.
  @retval EFI_DEVICE_ERROR      A device error occurred while attempting to send the SD
                                command Packet.
  @retval EFI_INVALID_PARAMETER Packet, Slot, or the contents of the Packet is invalid.
  @retval EFI_INVALID_PARAMETER Packet defines a data command but both InDataBuffer and
                                OutDataBuffer are NULL.
  @retval EFI_NO_MEDIA          SD Device not present in the Slot.
  @retval EFI_UNSUPPORTED       The command described by the SD Command Packet is not
                                supported by the host controller.
  @retval EFI_BAD_BUFFER_SIZE   The InTransferLength or OutTransferLength exceeds the
                                limit supported by SD card ( i.e. if the number of bytes
                                exceed the Last LBA).

**/
EFI_STATUS
EFIAPI
SdMmcPassThruPassThru (
  IN     EFI_SD_MMC_PASS_THRU_PROTOCOL         *This,
  IN     UINT8                                 Slot,
  IN OUT EFI_SD_MMC_PASS_THRU_COMMAND_PACKET   *Packet,
  IN     EFI_EVENT                             Event    OPTIONAL
  )
{
  EFI_STATUS                      Status;
  SD_MMC_HC_PRIVATE_DATA          *Private;
  SD_MMC_HC_TRB                   *Trb;
  EFI_TPL                         OldTpl;

  if ((This == NULL) || (Packet == NULL)) {
    return EFI_INVALID_PARAMETER;
  }

  if ((Packet->SdMmcCmdBlk == NULL) || (Packet->SdMmcStatusBlk == NULL)) {
    return EFI_INVALID_PARAMETER;
  }

  if ((Packet->OutDataBuffer == NULL) && (Packet->OutTransferLength != 0)) {
    return EFI_INVALID_PARAMETER;
  }

  if ((Packet->InDataBuffer == NULL) && (Packet->InTransferLength != 0)) {
    return EFI_INVALID_PARAMETER;
  }

  Private = SD_MMC_HC_PRIVATE_FROM_THIS (This);

  if (!Private->Slot[Slot].Enable) {
    return EFI_INVALID_PARAMETER;
  }

  if (!Private->Slot[Slot].MediaPresent) {
    return EFI_NO_MEDIA;
  }

  if (!Private->Slot[Slot].Initialized) {
    return EFI_DEVICE_ERROR;
  }

  Trb = SdMmcCreateTrb (Private, Slot, Packet, Event);
  if (Trb == NULL) {
    return EFI_OUT_OF_RESOURCES;
  }
  //
  // Immediately return for async I/O.
  //
  if (Event != NULL) {
    return EFI_SUCCESS;
  }

  //
  // Wait async I/O list is empty before execute sync I/O operation.
  //
  while (TRUE) {
    OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
    if (IsListEmpty (&Private->Queue)) {
      gBS->RestoreTPL (OldTpl);
      break;
    }
    gBS->RestoreTPL (OldTpl);
  }

  Status = SdMmcWaitTrbEnv (Private, Trb);
  if (EFI_ERROR (Status)) {
    goto Done;
  }

  Status = SdMmcExecTrb (Private, Trb);
  if (EFI_ERROR (Status)) {
    goto Done;
  }

  Status = SdMmcWaitTrbResult (Private, Trb);
  if (EFI_ERROR (Status)) {
    goto Done;
  }

Done:
  if ((Trb != NULL) && (Trb->AdmaDesc != NULL)) {
    FreePages (Trb->AdmaDesc, Trb->AdmaPages);
  }

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

  return Status;
}
/**
  Initialize DMA protection.

  @param VTdInfo        The VTd engine context information.

  @retval EFI_SUCCESS           the DMA protection is initialized.
  @retval EFI_OUT_OF_RESOURCES  no enough resource to initialize DMA protection.
**/
EFI_STATUS
InitDmaProtection (
  IN   VTD_INFO                    *VTdInfo
  )
{
  EFI_STATUS                  Status;
  UINT32                      LowMemoryAlignment;
  UINT64                      HighMemoryAlignment;
  UINTN                       MemoryAlignment;
  UINTN                       LowBottom;
  UINTN                       LowTop;
  UINTN                       HighBottom;
  UINT64                      HighTop;
  DMA_BUFFER_INFO             *DmaBufferInfo;
  VOID                        *Hob;
  EFI_PEI_PPI_DESCRIPTOR      *OldDescriptor;
  EDKII_IOMMU_PPI             *OldIoMmuPpi;

  Hob = GetFirstGuidHob (&mDmaBufferInfoGuid);
  DmaBufferInfo = GET_GUID_HOB_DATA(Hob);

  DEBUG ((DEBUG_INFO, " DmaBufferSize : 0x%x\n", DmaBufferInfo->DmaBufferSize));

  LowMemoryAlignment = GetLowMemoryAlignment (VTdInfo, VTdInfo->EngineMask);
  HighMemoryAlignment = GetHighMemoryAlignment (VTdInfo, VTdInfo->EngineMask);
  if (LowMemoryAlignment < HighMemoryAlignment) {
    MemoryAlignment = (UINTN)HighMemoryAlignment;
  } else {
    MemoryAlignment = LowMemoryAlignment;
  }
  ASSERT (DmaBufferInfo->DmaBufferSize == ALIGN_VALUE(DmaBufferInfo->DmaBufferSize, MemoryAlignment));
  DmaBufferInfo->DmaBufferBase = (UINTN)AllocateAlignedPages (EFI_SIZE_TO_PAGES(DmaBufferInfo->DmaBufferSize), MemoryAlignment);
  ASSERT (DmaBufferInfo->DmaBufferBase != 0);
  if (DmaBufferInfo->DmaBufferBase == 0) {
    DEBUG ((DEBUG_INFO, " InitDmaProtection : OutOfResource\n"));
    return EFI_OUT_OF_RESOURCES;
  }

  DEBUG ((DEBUG_INFO, " DmaBufferBase : 0x%x\n", DmaBufferInfo->DmaBufferBase));

  DmaBufferInfo->DmaBufferCurrentTop = DmaBufferInfo->DmaBufferBase + DmaBufferInfo->DmaBufferSize;
  DmaBufferInfo->DmaBufferCurrentBottom = DmaBufferInfo->DmaBufferBase;

  //
  // (Re)Install PPI.
  //
  Status = PeiServicesLocatePpi (
             &gEdkiiIoMmuPpiGuid,
             0,
             &OldDescriptor,
             (VOID **) &OldIoMmuPpi
             );
  if (!EFI_ERROR (Status)) {
    Status = PeiServicesReInstallPpi (OldDescriptor, &mIoMmuPpiList);
  } else {
    Status = PeiServicesInstallPpi (&mIoMmuPpiList);
  }
  ASSERT_EFI_ERROR (Status);

  LowBottom = 0;
  LowTop = DmaBufferInfo->DmaBufferBase;
  HighBottom = DmaBufferInfo->DmaBufferBase + DmaBufferInfo->DmaBufferSize;
  HighTop = LShiftU64 (1, VTdInfo->HostAddressWidth + 1);

  Status = SetDmaProtectedRange (
             VTdInfo,
             VTdInfo->EngineMask,
             (UINT32)LowBottom,
             (UINT32)(LowTop - LowBottom),
             HighBottom,
             HighTop - HighBottom
             );

  if (EFI_ERROR(Status)) {
    FreePages ((VOID *)DmaBufferInfo->DmaBufferBase, EFI_SIZE_TO_PAGES(DmaBufferInfo->DmaBufferSize));
  }

  return Status;
}
Beispiel #23
0
/**
  Allocates pages that are suitable for an OperationBusMasterCommonBuffer or
  OperationBusMasterCommonBuffer64 mapping.

  @param  This                  The protocol instance pointer.
  @param  Type                  This parameter is not used and must be ignored.
  @param  MemoryType            The type of memory to allocate,
                                EfiBootServicesData or EfiRuntimeServicesData.
  @param  Pages                 The number of pages to allocate.
  @param  HostAddress           A pointer to store the base system memory
                                address of the allocated range.
  @param  Attributes            The requested bit mask of attributes for the
                                allocated range.

  @retval EFI_SUCCESS           The requested memory pages were allocated.
  @retval EFI_UNSUPPORTED       Attributes is unsupported. The only legal
                                attribute bits are MEMORY_WRITE_COMBINE and
                                MEMORY_CACHED.
  @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
  @retval EFI_OUT_OF_RESOURCES  The memory pages could not be allocated.

**/
EFI_STATUS
EFIAPI
IoMmuAllocateBuffer (
  IN     EDKII_IOMMU_PROTOCOL                     *This,
  IN     EFI_ALLOCATE_TYPE                        Type,
  IN     EFI_MEMORY_TYPE                          MemoryType,
  IN     UINTN                                    Pages,
  IN OUT VOID                                     **HostAddress,
  IN     UINT64                                   Attributes
  )
{
  EFI_STATUS                Status;
  EFI_PHYSICAL_ADDRESS      PhysicalAddress;
  VOID                      *StashBuffer;
  UINTN                     CommonBufferPages;
  COMMON_BUFFER_HEADER      *CommonBufferHeader;

  //
  // Validate Attributes
  //
  if ((Attributes & EDKII_IOMMU_ATTRIBUTE_INVALID_FOR_ALLOCATE_BUFFER) != 0) {
    return EFI_UNSUPPORTED;
  }

  //
  // Check for invalid inputs
  //
  if (HostAddress == NULL) {
    return EFI_INVALID_PARAMETER;
  }

  //
  // The only valid memory types are EfiBootServicesData and
  // EfiRuntimeServicesData
  //
  if (MemoryType != EfiBootServicesData &&
      MemoryType != EfiRuntimeServicesData) {
    return EFI_INVALID_PARAMETER;
  }

  //
  // We'll need a header page for the COMMON_BUFFER_HEADER structure.
  //
  if (Pages > MAX_UINTN - 1) {
    return EFI_OUT_OF_RESOURCES;
  }
  CommonBufferPages = Pages + 1;

  //
  // Allocate the stash in EfiBootServicesData type memory.
  //
  // Map() will temporarily save encrypted data in the stash for
  // BusMasterCommonBuffer[64] operations, so the data can be decrypted to the
  // original location.
  //
  // Unmap() will temporarily save plaintext data in the stash for
  // BusMasterCommonBuffer[64] operations, so the data can be encrypted to the
  // original location.
  //
  // StashBuffer always resides in encrypted memory.
  //
  StashBuffer = AllocatePages (Pages);
  if (StashBuffer == NULL) {
    return EFI_OUT_OF_RESOURCES;
  }

  PhysicalAddress = (UINTN)-1;
  if ((Attributes & EDKII_IOMMU_ATTRIBUTE_DUAL_ADDRESS_CYCLE) == 0) {
    //
    // Limit allocations to memory below 4GB
    //
    PhysicalAddress = SIZE_4GB - 1;
  }
  Status = gBS->AllocatePages (
                  AllocateMaxAddress,
                  MemoryType,
                  CommonBufferPages,
                  &PhysicalAddress
                  );
  if (EFI_ERROR (Status)) {
    goto FreeStashBuffer;
  }

  CommonBufferHeader = (VOID *)(UINTN)PhysicalAddress;
  PhysicalAddress += EFI_PAGE_SIZE;

  CommonBufferHeader->Signature = COMMON_BUFFER_SIG;
  CommonBufferHeader->StashBuffer = StashBuffer;

  *HostAddress = (VOID *)(UINTN)PhysicalAddress;

  DEBUG ((
    DEBUG_VERBOSE,
    "%a Address 0x%Lx Pages 0x%Lx\n",
    __FUNCTION__,
    PhysicalAddress,
    (UINT64)Pages
    ));
  return EFI_SUCCESS;

FreeStashBuffer:
  FreePages (StashBuffer, Pages);
  return Status;
}