/** 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; }
/** 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; }
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; }
/** 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; }
/** 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; }
/** 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 ); }
/** 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; }
/** 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); } }
/** 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); } }