Ejemplo n.º 1
0
/**
  Allocate a block of memory to be used by the buffer pool.

  @param  Pages          How many pages to allocate.

  @return The allocated memory block or NULL if failed.

**/
SD_PEIM_MEM_BLOCK *
SdPeimAllocMemBlock (
  IN  UINTN                    Pages
  )
{
  SD_PEIM_MEM_BLOCK            *Block;
  VOID                         *BufHost;
  VOID                         *Mapping;
  EFI_PHYSICAL_ADDRESS         MappedAddr;
  EFI_STATUS                   Status;
  VOID                         *TempPtr;

  TempPtr = NULL;
  Block   = NULL;

  Status = PeiServicesAllocatePool (sizeof(SD_PEIM_MEM_BLOCK), &TempPtr);
  if (EFI_ERROR (Status)) {
    return NULL;
  }

  ZeroMem ((VOID*)(UINTN)TempPtr, sizeof(SD_PEIM_MEM_BLOCK));

  //
  // each bit in the bit array represents SD_PEIM_MEM_UNIT
  // bytes of memory in the memory block.
  //
  ASSERT (SD_PEIM_MEM_UNIT * 8 <= EFI_PAGE_SIZE);

  Block = (SD_PEIM_MEM_BLOCK*)(UINTN)TempPtr;
  Block->BufLen   = EFI_PAGES_TO_SIZE (Pages);
  Block->BitsLen  = Block->BufLen / (SD_PEIM_MEM_UNIT * 8);

  Status = PeiServicesAllocatePool (Block->BitsLen, &TempPtr);
  if (EFI_ERROR (Status)) {
    return NULL;
  }

  ZeroMem ((VOID*)(UINTN)TempPtr, Block->BitsLen);

  Block->Bits = (UINT8*)(UINTN)TempPtr;

  Status = IoMmuAllocateBuffer (
             Pages,
             &BufHost,
             &MappedAddr,
             &Mapping
             );
  if (EFI_ERROR (Status)) {
    return NULL;
  }

  ZeroMem ((VOID*)(UINTN)BufHost, EFI_PAGES_TO_SIZE (Pages));

  Block->BufHost = (UINT8 *) (UINTN) BufHost;
  Block->Buf     = (UINT8 *) (UINTN) MappedAddr;
  Block->Mapping = Mapping;
  Block->Next    = NULL;

  return Block;
}
Ejemplo n.º 2
0
/**
  Allocates pages at a specified alignment.

  If Alignment is not a power of two and Alignment is not zero, then ASSERT().

  @param  Pages                 The number of pages to allocate.
  @param  Alignment             The requested alignment of the allocation.  Must be a power of two.
  @param  HostAddress           The system memory address to map to the PCI controller.
  @param  DeviceAddress         The resulting map address for the bus master PCI controller to
                                use to access the hosts HostAddress.
  @param  Mapping               A resulting value to pass to Unmap().

  @retval EFI_SUCCESS           Success to allocate aligned pages.
  @retval EFI_INVALID_PARAMETER Pages or Alignment is not valid.
  @retval EFI_OUT_OF_RESOURCES  Do not have enough resources to allocate memory.

**/
EFI_STATUS
UsbHcAllocateAlignedPages (
  IN UINTN                      Pages,
  IN UINTN                      Alignment,
  OUT VOID                      **HostAddress,
  OUT EFI_PHYSICAL_ADDRESS      *DeviceAddress,
  OUT VOID                      **Mapping
  )
{
  EFI_STATUS            Status;
  VOID                  *Memory;
  UINTN                 AlignedMemory;
  UINTN                 AlignmentMask;
  EFI_PHYSICAL_ADDRESS  DeviceMemory;
  UINTN                 AlignedDeviceMemory;
  UINTN                 RealPages;

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

  if ((Alignment & (Alignment - 1)) != 0) {
    return EFI_INVALID_PARAMETER;
  }

  if (Pages == 0) {
    return EFI_INVALID_PARAMETER;
  }

  if (Alignment > EFI_PAGE_SIZE) {
    //
    // Calculate 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);

    Status = IoMmuAllocateBuffer (
               Pages,
               &Memory,
               &DeviceMemory,
               Mapping
               );
    if (EFI_ERROR (Status)) {
      return EFI_OUT_OF_RESOURCES;
    }
    AlignedMemory = ((UINTN) Memory + AlignmentMask) & ~AlignmentMask;
    AlignedDeviceMemory = ((UINTN) DeviceMemory + AlignmentMask) & ~AlignmentMask;
  } else {
    //
    // Do not over-allocate pages in this case.
    //
    Status = IoMmuAllocateBuffer (
               Pages,
               &Memory,
               &DeviceMemory,
               Mapping
               );
    if (EFI_ERROR (Status)) {
      return EFI_OUT_OF_RESOURCES;
    }
    AlignedMemory = (UINTN) Memory;
    AlignedDeviceMemory = (UINTN) DeviceMemory;
  }

  *HostAddress = (VOID *) AlignedMemory;
  *DeviceAddress = (EFI_PHYSICAL_ADDRESS) AlignedDeviceMemory;

  return EFI_SUCCESS;
}
Ejemplo n.º 3
0
/**
  Allocate a block of memory to be used by the buffer pool.

  @param  Pages         How many pages to allocate.

  @return Pointer to the allocated memory block or NULL if failed.

**/
USBHC_MEM_BLOCK *
UsbHcAllocMemBlock (
  IN UINTN              Pages
  )
{
  USBHC_MEM_BLOCK       *Block;
  VOID                  *BufHost;
  VOID                  *Mapping;
  EFI_PHYSICAL_ADDRESS  MappedAddr;
  EFI_STATUS            Status;
  UINTN                 PageNumber;
  EFI_PHYSICAL_ADDRESS  TempPtr;

  PageNumber = EFI_SIZE_TO_PAGES (sizeof (USBHC_MEM_BLOCK));
  Status = PeiServicesAllocatePages (
             EfiBootServicesData,
             PageNumber,
             &TempPtr
             );

  if (EFI_ERROR (Status)) {
    return NULL;
  }
  ZeroMem ((VOID *) (UINTN) TempPtr, EFI_PAGES_TO_SIZE (PageNumber));

  //
  // each bit in the bit array represents USBHC_MEM_UNIT
  // bytes of memory in the memory block.
  //
  ASSERT (USBHC_MEM_UNIT * 8 <= EFI_PAGE_SIZE);

  Block = (USBHC_MEM_BLOCK *) (UINTN) TempPtr;
  Block->BufLen = EFI_PAGES_TO_SIZE (Pages);
  Block->BitsLen = Block->BufLen / (USBHC_MEM_UNIT * 8);

  PageNumber = EFI_SIZE_TO_PAGES (Block->BitsLen);
  Status = PeiServicesAllocatePages (
             EfiBootServicesData,
             PageNumber,
             &TempPtr
             );

  if (EFI_ERROR (Status)) {
    return NULL;
  }
  ZeroMem ((VOID *) (UINTN) TempPtr, EFI_PAGES_TO_SIZE (PageNumber));

  Block->Bits = (UINT8 *) (UINTN) TempPtr;

  Status = IoMmuAllocateBuffer (
             Pages,
             &BufHost,
             &MappedAddr,
             &Mapping
             );
  if (EFI_ERROR (Status)) {
    return NULL;
  }
  ZeroMem ((VOID *) (UINTN) BufHost, EFI_PAGES_TO_SIZE (Pages));

  Block->BufHost = (UINT8 *) (UINTN) BufHost;
  Block->Buf = (UINT8 *) (UINTN) MappedAddr;
  Block->Mapping  = Mapping;
  Block->Next = NULL;

  return Block;
}
Ejemplo n.º 4
0
/**
  Entry point of the PEIM.

  @param[in] FileHandle     Handle of the file being invoked.
  @param[in] PeiServices    Describes the list of possible PEI Services.

  @retval EFI_SUCCESS    PPI successfully installed.

**/
EFI_STATUS
EFIAPI
NvmExpressPeimEntry (
  IN EFI_PEI_FILE_HANDLE    FileHandle,
  IN CONST EFI_PEI_SERVICES **PeiServices
  )
{
  EFI_STATUS                               Status;
  EFI_BOOT_MODE                            BootMode;
  EDKII_NVM_EXPRESS_HOST_CONTROLLER_PPI    *NvmeHcPpi;
  UINT8                                    Controller;
  UINTN                                    MmioBase;
  UINTN                                    DevicePathLength;
  EFI_DEVICE_PATH_PROTOCOL                 *DevicePath;
  PEI_NVME_CONTROLLER_PRIVATE_DATA         *Private;
  EFI_PHYSICAL_ADDRESS                     DeviceAddress;

  DEBUG ((DEBUG_INFO, "%a: Enters.\n", __FUNCTION__));

  //
  // Get the current boot mode.
  //
  Status = PeiServicesGetBootMode (&BootMode);
  if (EFI_ERROR (Status)) {
    DEBUG ((DEBUG_ERROR, "%a: Fail to get the current boot mode.\n", __FUNCTION__));
    return Status;
  }

  //
  // Locate the NVME host controller PPI
  //
  Status = PeiServicesLocatePpi (
             &gEdkiiPeiNvmExpressHostControllerPpiGuid,
             0,
             NULL,
             (VOID **) &NvmeHcPpi
             );
  if (EFI_ERROR (Status)) {
    DEBUG ((DEBUG_ERROR, "%a: Fail to locate NvmeHostControllerPpi.\n", __FUNCTION__));
    return EFI_UNSUPPORTED;
  }

  Controller = 0;
  MmioBase   = 0;
  while (TRUE) {
    Status = NvmeHcPpi->GetNvmeHcMmioBar (
                          NvmeHcPpi,
                          Controller,
                          &MmioBase
                          );
    //
    // When status is error, meant no controller is found
    //
    if (EFI_ERROR (Status)) {
      break;
    }

    Status = NvmeHcPpi->GetNvmeHcDevicePath (
                          NvmeHcPpi,
                          Controller,
                          &DevicePathLength,
                          &DevicePath
                          );
    if (EFI_ERROR (Status)) {
      DEBUG ((
        DEBUG_ERROR, "%a: Fail to allocate get the device path for Controller %d.\n",
        __FUNCTION__, Controller
        ));
      return Status;
    }

    //
    // Check validity of the device path of the NVM Express controller.
    //
    Status = NvmeIsHcDevicePathValid (DevicePath, DevicePathLength);
    if (EFI_ERROR (Status)) {
      DEBUG ((
        DEBUG_ERROR, "%a: The device path is invalid for Controller %d.\n",
        __FUNCTION__, Controller
        ));
      Controller++;
      continue;
    }

    //
    // For S3 resume performance consideration, not all NVM Express controllers
    // will be initialized. The driver consumes the content within
    // S3StorageDeviceInitList LockBox to see if a controller will be skipped
    // during S3 resume.
    //
    if ((BootMode == BOOT_ON_S3_RESUME) &&
        (NvmeS3SkipThisController (DevicePath, DevicePathLength))) {
      DEBUG ((
        DEBUG_ERROR, "%a: Controller %d is skipped during S3.\n",
        __FUNCTION__, Controller
        ));
      Controller++;
      continue;
    }

    //
    // Memory allocation for controller private data
    //
    Private = AllocateZeroPool (sizeof (PEI_NVME_CONTROLLER_PRIVATE_DATA));
    if (Private == NULL) {
      DEBUG ((
        DEBUG_ERROR, "%a: Fail to allocate private data for Controller %d.\n",
        __FUNCTION__, Controller
        ));
      return EFI_OUT_OF_RESOURCES;
    }

    //
    // Memory allocation for transfer-related data
    //
    Status = IoMmuAllocateBuffer (
               NVME_MEM_MAX_PAGES,
               &Private->Buffer,
               &DeviceAddress,
               &Private->BufferMapping
               );
    if (EFI_ERROR (Status)) {
      DEBUG ((
        DEBUG_ERROR, "%a: Fail to allocate DMA buffers for Controller %d.\n",
        __FUNCTION__, Controller
        ));
      return Status;
    }
    ASSERT (DeviceAddress == ((EFI_PHYSICAL_ADDRESS) (UINTN) Private->Buffer));
    DEBUG ((DEBUG_INFO, "%a: DMA buffer base at 0x%x\n", __FUNCTION__, Private->Buffer));

    //
    // Initialize controller private data
    //
    Private->Signature        = NVME_PEI_CONTROLLER_PRIVATE_DATA_SIGNATURE;
    Private->MmioBase         = MmioBase;
    Private->DevicePathLength = DevicePathLength;
    Private->DevicePath       = DevicePath;

    //
    // Initialize the NVME controller
    //
    Status = NvmeControllerInit (Private);
    if (EFI_ERROR (Status)) {
      DEBUG ((
        DEBUG_ERROR,
        "%a: Controller initialization fail for Controller %d with Status - %r.\n",
        __FUNCTION__, Controller, Status
        ));
      NvmeFreeDmaResource (Private);
      Controller++;
      continue;
    }

    //
    // Enumerate the NVME namespaces on the controller
    //
    Status = NvmeDiscoverNamespaces (Private);
    if (EFI_ERROR (Status)) {
      //
      // No active namespace was found on the controller
      //
      DEBUG ((
        DEBUG_ERROR,
        "%a: Namespaces discovery fail for Controller %d with Status - %r.\n",
        __FUNCTION__, Controller, Status
        ));
      NvmeFreeDmaResource (Private);
      Controller++;
      continue;
    }

    Private->BlkIoPpi.GetNumberOfBlockDevices  = NvmeBlockIoPeimGetDeviceNo;
    Private->BlkIoPpi.GetBlockDeviceMediaInfo  = NvmeBlockIoPeimGetMediaInfo;
    Private->BlkIoPpi.ReadBlocks               = NvmeBlockIoPeimReadBlocks;
    CopyMem (
      &Private->BlkIoPpiList,
      &mNvmeBlkIoPpiListTemplate,
      sizeof (EFI_PEI_PPI_DESCRIPTOR)
      );
    Private->BlkIoPpiList.Ppi                  = &Private->BlkIoPpi;

    Private->BlkIo2Ppi.Revision                = EFI_PEI_RECOVERY_BLOCK_IO2_PPI_REVISION;
    Private->BlkIo2Ppi.GetNumberOfBlockDevices = NvmeBlockIoPeimGetDeviceNo2;
    Private->BlkIo2Ppi.GetBlockDeviceMediaInfo = NvmeBlockIoPeimGetMediaInfo2;
    Private->BlkIo2Ppi.ReadBlocks              = NvmeBlockIoPeimReadBlocks2;
    CopyMem (
      &Private->BlkIo2PpiList,
      &mNvmeBlkIo2PpiListTemplate,
      sizeof (EFI_PEI_PPI_DESCRIPTOR)
      );
    Private->BlkIo2PpiList.Ppi                 = &Private->BlkIo2Ppi;
    PeiServicesInstallPpi (&Private->BlkIoPpiList);

    //
    // Check if the NVME controller supports the Security Receive/Send commands
    //
    if ((Private->ControllerData->Oacs & SECURITY_SEND_RECEIVE_SUPPORTED) != 0) {
      DEBUG ((
        DEBUG_INFO,
        "%a: Security Security Command PPI will be produced for Controller %d.\n",
        __FUNCTION__, Controller
        ));
      Private->StorageSecurityPpi.Revision           = EDKII_STORAGE_SECURITY_PPI_REVISION;
      Private->StorageSecurityPpi.GetNumberofDevices = NvmeStorageSecurityGetDeviceNo;
      Private->StorageSecurityPpi.GetDevicePath      = NvmeStorageSecurityGetDevicePath;
      Private->StorageSecurityPpi.ReceiveData        = NvmeStorageSecurityReceiveData;
      Private->StorageSecurityPpi.SendData           = NvmeStorageSecuritySendData;
      CopyMem (
        &Private->StorageSecurityPpiList,
        &mNvmeStorageSecurityPpiListTemplate,
        sizeof (EFI_PEI_PPI_DESCRIPTOR)
        );
      Private->StorageSecurityPpiList.Ppi            = &Private->StorageSecurityPpi;
      PeiServicesInstallPpi (&Private->StorageSecurityPpiList);
    }

    CopyMem (
      &Private->EndOfPeiNotifyList,
      &mNvmeEndOfPeiNotifyListTemplate,
      sizeof (EFI_PEI_NOTIFY_DESCRIPTOR)
      );
    PeiServicesNotifyPpi  (&Private->EndOfPeiNotifyList);

    DEBUG ((
      DEBUG_INFO, "%a: Controller %d has been successfully initialized.\n",
      __FUNCTION__, Controller
      ));
    Controller++;
  }

  return EFI_SUCCESS;
}