Beispiel #1
0
/**

  Override function for SDHCI capability bits

  @param[in]      PassThru              A pointer to the
                                        EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
  @param[in]      ControllerHandle      The EFI_HANDLE of the controller.
  @param[in]      Slot                  The 0 based slot index.
  @param[in,out]  SdMmcHcSlotCapability The SDHCI capability structure.

  @retval EFI_SUCCESS           The override function completed successfully.
  @retval EFI_NOT_FOUND         The specified controller or slot does not exist.
  @retval EFI_INVALID_PARAMETER SdMmcHcSlotCapability is NULL

**/
STATIC
EFI_STATUS
EFIAPI
SynQuacerSdMmcCapability (
  IN      EFI_HANDLE                      ControllerHandle,
  IN      UINT8                           Slot,
  IN  OUT VOID                            *SdMmcHcSlotCapability
  )
{
  UINT64 Capability;

  if (ControllerHandle != mSdMmcControllerHandle) {
    return EFI_SUCCESS;
  }

  ASSERT (Slot == 0);

  //
  // Clear the SDR104 capability bit. This avoids the need for a HS200 tuning
  // quirk that is difficult to support using the generic driver.
  // Clear the DDR50 bit as well to work around an issue with the Kingston
  // EMMC08G-M325-A52 part that was fitted on 96board DeveloperBox samples.
  //
  Capability = ReadUnaligned64 (SdMmcHcSlotCapability);
  Capability &= ~(UINT64)(SD_HC_CAP_SDR104 | SD_HC_CAP_DDR50);
  WriteUnaligned64 (SdMmcHcSlotCapability, Capability);

  return EFI_SUCCESS;
}
Beispiel #2
0
/**
  Read some blocks from the device by SCSI 16 byte cmd.

  @param  UsbMass                The USB mass storage device to read from
  @param  Lba                    The start block number
  @param  TotalBlock             Total block number to read
  @param  Buffer                 The buffer to read to

  @retval EFI_SUCCESS            Data are read into the buffer
  @retval Others                 Failed to read all the data

**/
EFI_STATUS
UsbBootReadBlocks16 (
  IN  USB_MASS_DEVICE       *UsbMass,
  IN  UINT64                Lba,
  IN  UINTN                 TotalBlock,
  OUT UINT8                 *Buffer
  )
{
  UINT8                     ReadCmd[16];
  EFI_STATUS                Status;
  UINT16                    Count;
  UINT32                    BlockSize;
  UINT32                    ByteSize;
  UINT32                    Timeout;

  BlockSize = UsbMass->BlockIoMedia.BlockSize;
  Status    = EFI_SUCCESS;

  while (TotalBlock > 0) {
    //
    // Split the total blocks into smaller pieces.
    //
    Count     = (UINT16)((TotalBlock < USB_BOOT_IO_BLOCKS) ? TotalBlock : USB_BOOT_IO_BLOCKS);
    ByteSize  = (UINT32)Count * BlockSize;

    //
    // USB command's upper limit timeout is 5s. [USB2.0-9.2.6.1]
    //
    Timeout = (UINT32) USB_BOOT_GENERAL_CMD_TIMEOUT;

    //
    // Fill in the command then execute
    //
    ZeroMem (ReadCmd, sizeof (ReadCmd));

    ReadCmd[0]  = EFI_SCSI_OP_READ16;
    ReadCmd[1]  = (UINT8) ((USB_BOOT_LUN (UsbMass->Lun) & 0xE0));
    WriteUnaligned64 ((UINT64 *) &ReadCmd[2], SwapBytes64 (Lba));
    WriteUnaligned32 ((UINT32 *) &ReadCmd[10], SwapBytes32 (Count));

    Status = UsbBootExecCmdWithRetry (
               UsbMass,
               ReadCmd,
               (UINT8) sizeof (ReadCmd),
               EfiUsbDataIn,
               Buffer,
               ByteSize,
               Timeout
               );
    if (EFI_ERROR (Status)) {
      return Status;
    }
    DEBUG ((EFI_D_BLKIO, "UsbBootReadBlocks16: LBA (0x%lx), Blk (0x%x)\n", Lba, Count));
    Lba        += Count;
    Buffer     += Count * BlockSize;
    TotalBlock -= Count;
  }

  return Status;
}
Beispiel #3
0
EFIAPI
CopyGuid (
  OUT GUID       *DestinationGuid,
  IN CONST GUID  *SourceGuid
  )
{
  WriteUnaligned64 (
    (UINT64*)DestinationGuid,
    ReadUnaligned64 ((CONST UINT64*)SourceGuid)
    );
  WriteUnaligned64 (
    (UINT64*)DestinationGuid + 1,
    ReadUnaligned64 ((CONST UINT64*)SourceGuid + 1)
    );
  return DestinationGuid;
}
Beispiel #4
0
/**
  Read Nvm Express admin completion queue base address register.

  @param  Private          The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure.
  @param  Acq              The buffer used to store admin completion queue base address register content.

  @return EFI_SUCCESS      Successfully read the admin completion queue base address register content.
  @return EFI_DEVICE_ERROR Fail to read the admin completion queue base address register.

**/
EFI_STATUS
ReadNvmeAdminCompletionQueueBaseAddress (
  IN NVME_CONTROLLER_PRIVATE_DATA     *Private,
  IN NVME_ACQ                         *Acq
  )
{
  EFI_PCI_IO_PROTOCOL   *PciIo;
  EFI_STATUS            Status;
  UINT64                Data;

  PciIo  = Private->PciIo;

  Status = PciIo->Mem.Read (
                        PciIo,
                        EfiPciIoWidthUint32,
                        NVME_BAR,
                        NVME_ACQ_OFFSET,
                        2,
                        &Data
                        );

  if (EFI_ERROR(Status)) {
    return Status;
  }

  WriteUnaligned64 ((UINT64*)Acq, Data);
  return EFI_SUCCESS;
}
Beispiel #5
0
/**
  Read Nvm Express controller capability register.

  @param  Private          The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure.
  @param  Cap              The buffer used to store capability register content.

  @return EFI_SUCCESS      Successfully read the controller capability register content.
  @return EFI_DEVICE_ERROR Fail to read the controller capability register.

**/
EFI_STATUS
ReadNvmeControllerCapabilities (
  IN NVME_CONTROLLER_PRIVATE_DATA     *Private,
  IN NVME_CAP                         *Cap
  )
{
  EFI_PCI_IO_PROTOCOL   *PciIo;
  EFI_STATUS            Status;
  UINT64                Data;

  PciIo  = Private->PciIo;
  Status = PciIo->Mem.Read (
                        PciIo,
                        EfiPciIoWidthUint32,
                        NVME_BAR,
                        NVME_CAP_OFFSET,
                        2,
                        &Data
                        );

  if (EFI_ERROR(Status)) {
    return Status;
  }

  WriteUnaligned64 ((UINT64*)Cap, Data);
  return EFI_SUCCESS;
}
Beispiel #6
0
/**

  Prints a debug message to the debug output device if the specified error level is enabled.

  If any bit in ErrorLevel is also set in PcdDebugPrintErrorLevel, then print 
  the message specified by Format and the associated variable argument list to 
  the debug output device.

  If Format is NULL, then ASSERT().

  @param  ErrorLevel  The error level of the debug message.
  @param  Format      Format string for the debug message to print.

**/
VOID
EFIAPI
DebugPrint (
  IN  UINTN        ErrorLevel,
  IN  CONST CHAR8  *Format,
  ...
  )
{
  UINT64          Buffer[EFI_STATUS_CODE_DATA_MAX_SIZE / sizeof (UINT64)];
  EFI_DEBUG_INFO  *DebugInfo;
  UINTN           TotalSize;
  UINTN           Index;
  VA_LIST         Marker;
  UINT64          *ArgumentPointer;

  //
  // If Format is NULL, then ASSERT().
  //
  ASSERT (Format != NULL);

  //
  // Check driver Debug Level value and global debug level
  //
  if ((ErrorLevel & PcdGet32(PcdDebugPrintErrorLevel)) == 0) {
    return;
  }

  TotalSize = sizeof (EFI_DEBUG_INFO) + 12 * sizeof (UINT64) + AsciiStrLen (Format) + 1;
  if (TotalSize > EFI_STATUS_CODE_DATA_MAX_SIZE) {
    return;
  }

  //
  // Then EFI_DEBUG_INFO
  //
  DebugInfo = (EFI_DEBUG_INFO *)Buffer;
  DebugInfo->ErrorLevel = (UINT32)ErrorLevel;

  //
  // 256 byte mini Var Arg stack. That is followed by the format string.
  //
  VA_START (Marker, Format);
  for (Index = 0, ArgumentPointer = (UINT64 *)(DebugInfo + 1); Index < 12; Index++, ArgumentPointer++) {
    WriteUnaligned64(ArgumentPointer, VA_ARG (Marker, UINT64));
  }
  VA_END (Marker);
  AsciiStrCpy ((CHAR8 *)ArgumentPointer, Format);

  REPORT_STATUS_CODE_EX (
    EFI_DEBUG_CODE,
    (EFI_SOFTWARE_DXE_BS_DRIVER | EFI_DC_UNSPECIFIED),
    0,
    NULL,
    &gEfiStatusCodeDataTypeDebugGuid,
    DebugInfo,
    TotalSize
    );
}
Beispiel #7
0
/**
  Reads memory-mapped registers.

  @param[in]  PeiServices  An indirect pointer to the PEI Services Table
                           published by the PEI Foundation.
  @param[in]  This         Pointer to local data for the interface.
  @param[in]  Width        The width of the access. Enumerated in bytes.
  @param[in]  Address      The physical address of the access.
  @param[in]  Count        The number of accesses to perform.
  @param[out] Buffer       A pointer to the buffer of data.

  @retval EFI_SUCCESS            The function completed successfully.
  @retval EFI_INVALID_PARAMETER  Width is invalid for this EFI system.
  @retval EFI_INVALID_PARAMETER  Buffer is NULL.
  @retval EFI_UNSUPPORTED        The address range specified by Address, Width,
                                 and Count is not valid for this EFI system.

**/
EFI_STATUS
EFIAPI
CpuMemoryServiceRead (
  IN  CONST EFI_PEI_SERVICES    **PeiServices,
  IN  CONST EFI_PEI_CPU_IO_PPI  *This,
  IN  EFI_PEI_CPU_IO_PPI_WIDTH  Width,
  IN  UINT64                    Address,
  IN  UINTN                     Count,
  OUT VOID                      *Buffer
  )
{
  EFI_STATUS                Status;
  UINT8                     InStride;
  UINT8                     OutStride;
  EFI_PEI_CPU_IO_PPI_WIDTH  OperationWidth;
  BOOLEAN                   Aligned;
  UINT8                     *Uint8Buffer;

  Status = CpuIoCheckParameter (TRUE, Width, Address, Count, Buffer);
  if (EFI_ERROR (Status)) {
    return Status;
  }

  //
  // Select loop based on the width of the transfer
  //
  InStride = mInStride[Width];
  OutStride = mOutStride[Width];
  OperationWidth = (EFI_PEI_CPU_IO_PPI_WIDTH) (Width & 0x03);
  Aligned = (BOOLEAN)(((UINTN)Buffer & (mInStride[OperationWidth] - 1)) == 0x00);
  for (Uint8Buffer = Buffer; Count > 0; Address += InStride, Uint8Buffer += OutStride, Count--) {
    if (OperationWidth == EfiPeiCpuIoWidthUint8) {
      *Uint8Buffer = MmioRead8 ((UINTN)Address);
    } else if (OperationWidth == EfiPeiCpuIoWidthUint16) {
      if (Aligned) {
        *((UINT16 *)Uint8Buffer) = MmioRead16 ((UINTN)Address);
      } else {
        WriteUnaligned16 ((UINT16 *)Uint8Buffer, MmioRead16 ((UINTN)Address));
      }
    } else if (OperationWidth == EfiPeiCpuIoWidthUint32) {
      if (Aligned) {
        *((UINT32 *)Uint8Buffer) = MmioRead32 ((UINTN)Address);
      } else {
        WriteUnaligned32 ((UINT32 *)Uint8Buffer, MmioRead32 ((UINTN)Address));
      }
    } else if (OperationWidth == EfiPeiCpuIoWidthUint64) {
      if (Aligned) {
        *((UINT64 *)Uint8Buffer) = MmioRead64 ((UINTN)Address);
      } else {
        WriteUnaligned64 ((UINT64 *)Uint8Buffer, MmioRead64 ((UINTN)Address));
      }
    }
  }
  return EFI_SUCCESS;
}
Beispiel #8
0
/**
  Execute READ (16) SCSI command on a specific UFS device.

  @param[in]  Private              A pointer to UFS_PEIM_HC_PRIVATE_DATA data structure.
  @param[in]  Lun                  The lun on which the SCSI cmd executed.
  @param[in]  StartLba             The start LBA.
  @param[in]  SectorNum            The sector number to be read.
  @param[out] DataBuffer           A pointer to data buffer.
  @param[out] DataLength           The length of output data.
  @param[out] SenseData            A pointer to output sense data.
  @param[out] SenseDataLength      The length of output sense data.

  @retval EFI_SUCCESS              The command executed successfully.
  @retval EFI_DEVICE_ERROR         A device error occurred while attempting to send SCSI Request Packet.
  @retval EFI_TIMEOUT              A timeout occurred while waiting for the SCSI Request Packet to execute.

**/
EFI_STATUS
UfsPeimRead16 (
  IN     UFS_PEIM_HC_PRIVATE_DATA     *Private,
  IN     UINTN                        Lun,
  IN     UINTN                        StartLba,
  IN     UINT32                       SectorNum,
     OUT VOID                         *DataBuffer,
     OUT UINT32                       *DataLength,
     OUT VOID                         *SenseData,  OPTIONAL
     OUT UINT8                        *SenseDataLength
  )  
{
  UFS_SCSI_REQUEST_PACKET             Packet;
  UINT8                               Cdb[UFS_SCSI_OP_LENGTH_SIXTEEN];
  EFI_STATUS                          Status;

  ZeroMem (&Packet, sizeof (UFS_SCSI_REQUEST_PACKET));
  ZeroMem (Cdb, sizeof (Cdb));

  Cdb[0] = EFI_SCSI_OP_READ16;
  WriteUnaligned64 ((UINT64 *)&Cdb[2], SwapBytes64 (StartLba));
  WriteUnaligned32 ((UINT32 *)&Cdb[10], SwapBytes32 (SectorNum));

  Packet.Timeout          = UFS_TIMEOUT;
  Packet.Cdb              = Cdb;
  Packet.CdbLength        = sizeof (Cdb);
  Packet.InDataBuffer     = DataBuffer;
  Packet.InTransferLength = *DataLength;
  Packet.DataDirection    = UfsDataIn;
  Packet.SenseData        = SenseData;
  Packet.SenseDataLength  = *SenseDataLength;

  Status = UfsExecScsiCmds (Private, (UINT8)Lun, &Packet);

  if (*SenseDataLength != 0) {
    *SenseDataLength = Packet.SenseDataLength;
  }

  if (!EFI_ERROR (Status)) {
    *DataLength = Packet.InTransferLength;
  }

  return Status;
}
VOID
ArmPlatformSetGlobalVariable (
  IN  UINTN     VariableOffset,
  IN  UINTN     VariableSize,
  OUT VOID*     Variable
  )
{
  UINTN  GlobalVariableBase;

  // Ensure the Global Variable Size have been initialized
  ASSERT (VariableOffset < PcdGet32 (PcdSecGlobalVariableSize));

  GlobalVariableBase = PcdGet32 (PcdCPUCoresSecStackBase) + PcdGet32 (PcdCPUCoreSecPrimaryStackSize) - PcdGet32 (PcdSecGlobalVariableSize);

  if (VariableSize == 4) {
    WriteUnaligned32 ((UINT32*)(GlobalVariableBase + VariableOffset), *(UINT32*)Variable);
  } else if (VariableSize == 8) {
    WriteUnaligned64 ((UINT64*)(GlobalVariableBase + VariableOffset), *(UINT64*)Variable);
  } else {
    CopyMem ((VOID*)(GlobalVariableBase + VariableOffset), Variable, VariableSize);
  }
}
Beispiel #10
0
/**
  Patch the immediate operand of an IA32 or X64 instruction such that the byte,
  word, dword or qword operand is encoded at the end of the instruction's
  binary representation.

  This function should be used to update object code that was compiled with
  NASM from assembly source code. Example:

  NASM source code:

        mov     eax, strict dword 0 ; the imm32 zero operand will be patched
    ASM_PFX(gPatchCr3):
        mov     cr3, eax

  C source code:

    X86_ASSEMBLY_PATCH_LABEL gPatchCr3;
    PatchInstructionX86 (gPatchCr3, AsmReadCr3 (), 4);

  @param[out] InstructionEnd  Pointer right past the instruction to patch. The
                              immediate operand to patch is expected to
                              comprise the trailing bytes of the instruction.
                              If InstructionEnd is closer to address 0 than
                              ValueSize permits, then ASSERT().

  @param[in] PatchValue       The constant to write to the immediate operand.
                              The caller is responsible for ensuring that
                              PatchValue can be represented in the byte, word,
                              dword or qword operand (as indicated through
                              ValueSize); otherwise ASSERT().

  @param[in] ValueSize        The size of the operand in bytes; must be 1, 2,
                              4, or 8. ASSERT() otherwise.
**/
VOID
EFIAPI
PatchInstructionX86 (
  OUT X86_ASSEMBLY_PATCH_LABEL *InstructionEnd,
  IN  UINT64                   PatchValue,
  IN  UINTN                    ValueSize
  )
{
  //
  // The equality ((UINTN)InstructionEnd == ValueSize) would assume a zero-size
  // instruction at address 0; forbid it.
  //
  ASSERT ((UINTN)InstructionEnd > ValueSize);

  switch (ValueSize) {
  case 1:
    ASSERT (PatchValue <= MAX_UINT8);
    *((UINT8 *)(UINTN)InstructionEnd - 1) = (UINT8)PatchValue;
    break;

  case 2:
    ASSERT (PatchValue <= MAX_UINT16);
    WriteUnaligned16 ((UINT16 *)(UINTN)InstructionEnd - 1, (UINT16)PatchValue);
    break;

  case 4:
    ASSERT (PatchValue <= MAX_UINT32);
    WriteUnaligned32 ((UINT32 *)(UINTN)InstructionEnd - 1, (UINT32)PatchValue);
    break;

  case 8:
    WriteUnaligned64 ((UINT64 *)(UINTN)InstructionEnd - 1, PatchValue);
    break;

  default:
    ASSERT (FALSE);
  }
}