Exemplo n.º 1
0
/**
  This function flushes the range of addresses from Start to Start+Length
  from the processor's data cache. If Start is not aligned to a cache line
  boundary, then the bytes before Start to the preceding cache line boundary
  are also flushed. If Start+Length is not aligned to a cache line boundary,
  then the bytes past Start+Length to the end of the next cache line boundary
  are also flushed. The FlushType of EfiCpuFlushTypeWriteBackInvalidate must be
  supported. If the data cache is fully coherent with all DMA operations, then
  this function can just return EFI_SUCCESS. If the processor does not support
  flushing a range of the data cache, then the entire data cache can be flushed.

  @param  This             The EFI_CPU_ARCH_PROTOCOL instance.
  @param  Start            The beginning physical address to flush from the processor's data
                           cache.
  @param  Length           The number of bytes to flush from the processor's data cache. This
                           function may flush more bytes than Length specifies depending upon
                           the granularity of the flush operation that the processor supports.
  @param  FlushType        Specifies the type of flush operation to perform.

  @retval EFI_SUCCESS           The address range from Start to Start+Length was flushed from
                                the processor's data cache.
  @retval EFI_UNSUPPORTED       The processor does not support the cache flush type specified
                                by FlushType.
  @retval EFI_DEVICE_ERROR      The address range from Start to Start+Length could not be flushed
                                from the processor's data cache.

**/
EFI_STATUS
EFIAPI
CpuFlushCpuDataCache (
  IN EFI_CPU_ARCH_PROTOCOL           *This,
  IN EFI_PHYSICAL_ADDRESS            Start,
  IN UINT64                          Length,
  IN EFI_CPU_FLUSH_TYPE              FlushType
  )
{

  switch (FlushType) {
    case EfiCpuFlushTypeWriteBack:
      WriteBackDataCacheRange ((VOID *)(UINTN)Start, (UINTN)Length);
      break;
    case EfiCpuFlushTypeInvalidate:
      InvalidateDataCacheRange ((VOID *)(UINTN)Start, (UINTN)Length);
      break;
    case EfiCpuFlushTypeWriteBackInvalidate:
      WriteBackInvalidateDataCacheRange ((VOID *)(UINTN)Start, (UINTN)Length);
      break;
    default:
      return EFI_INVALID_PARAMETER;
  }

  return EFI_SUCCESS;
}
Exemplo n.º 2
0
VOID
PrePiMain (
  IN  UINTN                     UefiMemoryBase,
  IN  UINTN                     StacksBase,
  IN  UINT64                    StartTimeStamp
  )
{
  EFI_HOB_HANDOFF_INFO_TABLE*   HobList;
  EFI_STATUS                    Status;
  CHAR8                         Buffer[100];
  UINTN                         CharCount;
  UINTN                         StacksSize;

  // Initialize the architecture specific bits
  ArchInitialize ();

  // Declare the PI/UEFI memory region
  HobList = HobConstructor (
    (VOID*)UefiMemoryBase,
    FixedPcdGet32 (PcdSystemMemoryUefiRegionSize),
    (VOID*)UefiMemoryBase,
    (VOID*)StacksBase  // The top of the UEFI Memory is reserved for the stacks
    );
  PrePeiSetHobList (HobList);

  //
  // Ensure that the loaded image is invalidated in the caches, so that any
  // modifications we made with the caches and MMU off (such as the applied
  // relocations) don't become invisible once we turn them on.
  //
  InvalidateDataCacheRange((VOID *)(UINTN)PcdGet64 (PcdFdBaseAddress), PcdGet32 (PcdFdSize));

  // Initialize MMU and Memory HOBs (Resource Descriptor HOBs)
  Status = MemoryPeim (UefiMemoryBase, FixedPcdGet32 (PcdSystemMemoryUefiRegionSize));
  ASSERT_EFI_ERROR (Status);

  // Initialize the Serial Port
  SerialPortInitialize ();
  CharCount = AsciiSPrint (Buffer,sizeof (Buffer),"UEFI firmware (version %s built at %a on %a)\n\r",
    (CHAR16*)PcdGetPtr(PcdFirmwareVersionString), __TIME__, __DATE__);
  SerialPortWrite ((UINT8 *) Buffer, CharCount);

  // Create the Stacks HOB (reserve the memory for all stacks)
  StacksSize = PcdGet32 (PcdCPUCorePrimaryStackSize);
  BuildStackHob (StacksBase, StacksSize);

  //TODO: Call CpuPei as a library
  BuildCpuHob (PcdGet8 (PcdPrePiCpuMemorySize), PcdGet8 (PcdPrePiCpuIoSize));

  // Set the Boot Mode
  SetBootMode (ArmPlatformGetBootMode ());

  // Initialize Platform HOBs (CpuHob and FvHob)
  Status = PlatformPeim ();
  ASSERT_EFI_ERROR (Status);

  // Now, the HOB List has been initialized, we can register performance information
  PERF_START (NULL, "PEI", NULL, StartTimeStamp);

  // SEC phase needs to run library constructors by hand.
  ExtractGuidedSectionLibConstructor ();
  LzmaDecompressLibConstructor ();

  // Build HOBs to pass up our version of stuff the DXE Core needs to save space
  BuildPeCoffLoaderHob ();
  BuildExtractSectionHob (
    &gLzmaCustomDecompressGuid,
    LzmaGuidedSectionGetInfo,
    LzmaGuidedSectionExtraction
    );

  // Assume the FV that contains the SEC (our code) also contains a compressed FV.
  Status = DecompressFirstFv ();
  ASSERT_EFI_ERROR (Status);

  // Load the DXE Core and transfer control to it
  Status = LoadDxeCoreFromFv (NULL, 0);
  ASSERT_EFI_ERROR (Status);
}
Exemplo n.º 3
0
EFI_STATUS
EFIAPI
MemoryPeim (
  IN EFI_PHYSICAL_ADDRESS               UefiMemoryBase,
  IN UINT64                             UefiMemorySize
  )
{
  EFI_RESOURCE_ATTRIBUTE_TYPE ResourceAttributes;
  UINT64                      SystemMemoryTop;

  // Ensure PcdSystemMemorySize has been set
  ASSERT (PcdGet64 (PcdSystemMemorySize) != 0);

  //
  // Now, the permanent memory has been installed, we can call AllocatePages()
  //
  ResourceAttributes = (
      EFI_RESOURCE_ATTRIBUTE_PRESENT |
      EFI_RESOURCE_ATTRIBUTE_INITIALIZED |
      EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE |
      EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE |
      EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE |
      EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE |
      EFI_RESOURCE_ATTRIBUTE_TESTED
  );

  SystemMemoryTop = PcdGet64 (PcdSystemMemoryBase) +
                    PcdGet64 (PcdSystemMemorySize);

  if (SystemMemoryTop - 1 > MAX_ADDRESS) {
    BuildResourceDescriptorHob (
        EFI_RESOURCE_SYSTEM_MEMORY,
        ResourceAttributes,
        PcdGet64 (PcdSystemMemoryBase),
        (UINT64)MAX_ADDRESS - PcdGet64 (PcdSystemMemoryBase) + 1
        );
    BuildResourceDescriptorHob (
        EFI_RESOURCE_SYSTEM_MEMORY,
        ResourceAttributes,
        (UINT64)MAX_ADDRESS + 1,
        SystemMemoryTop - MAX_ADDRESS - 1
        );
  } else {
    BuildResourceDescriptorHob (
        EFI_RESOURCE_SYSTEM_MEMORY,
        ResourceAttributes,
        PcdGet64 (PcdSystemMemoryBase),
        PcdGet64 (PcdSystemMemorySize)
        );
  }

  //
  // When running under virtualization, the PI/UEFI memory region may be
  // clean but not invalidated in system caches or in lower level caches
  // on other CPUs. So invalidate the region by virtual address, to ensure
  // that the contents we put there with the caches and MMU off will still
  // be visible after turning them on.
  //
  InvalidateDataCacheRange ((VOID*)(UINTN)UefiMemoryBase, UefiMemorySize);

  // Build Memory Allocation Hob
  InitMmu ();

  if (FeaturePcdGet (PcdPrePiProduceMemoryTypeInformationHob)) {
    // Optional feature that helps prevent EFI memory map fragmentation.
    BuildMemoryTypeInformationHob ();
  }

  return EFI_SUCCESS;
}
Exemplo n.º 4
0
STATIC EFI_STATUS prepare_cmd (
  struct hisi_hba *hba,
  EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET    *Packet
  )
{
	struct hisi_sas_slot *slot;
	struct hisi_sas_cmd_hdr *hdr;
	struct hisi_sas_sge_page *sge;
	struct hisi_sas_sts	*sts;
	struct hisi_sas_cmd	*cmd;
	EFI_SCSI_SENSE_DATA *SensePtr = Packet->SenseData;
	VOID   *Buffer = NULL;
	UINT32 BufferSize = 0;
	int queue = hba->queue;
	UINT32 r, w = 0, slot_idx = 0;
	UINT8 *p;

	while (1) {
		w = READ_REG32(DLVRY_Q_0_WR_PTR + (queue * 0x14));
		r = READ_REG32(DLVRY_Q_0_RD_PTR + (queue * 0x14));
		slot_idx = queue * QUEUE_SLOTS + w;
		slot = &hba->slots[slot_idx];
		if (slot->used || (r == (w+1) % QUEUE_SLOTS)) {
			queue = (queue + 1) % QUEUE_CNT;
			if (queue == hba->queue) {
				DEBUG ((EFI_D_ERROR, "could not find free slot\n"));
				return EFI_NOT_READY;
			}
			continue;
		}
		break;
	}

	hdr = &hba->cmd_hdr[queue][w];
	cmd = &hba->command_table[queue][w];
	sts = &hba->status_buf[queue][w];
	sge = &hba->sge[queue][w];

	ZeroMem (cmd, sizeof (struct hisi_sas_cmd));
	ZeroMem (sts, sizeof (struct hisi_sas_sts));
	if (SensePtr)
		ZeroMem (SensePtr, sizeof (EFI_SCSI_SENSE_DATA));

	slot->used = TRUE;
	slot->sts = sts;
	hba->queue = (queue + 1) % QUEUE_CNT;

	//only consider ssp
	//prep_ssp_v1_hw
	/* create header */
	hdr->dw0 = (1 << CMD_HDR_RESP_REPORT_OFF) |
		   (0x2 << CMD_HDR_TLR_CTRL_OFF) |
		   (hba->port_id << CMD_HDR_PORT_OFF) |
		   (1 << CMD_HDR_MODE_OFF) | /* ini mode */
		   (1 << CMD_HDR_CMD_OFF); /* ssp */
	hdr->dw1 = 1 << CMD_HDR_VERIFY_DTL_OFF;
	/* device_id = 0 */
	hdr->dw1 |= 0 << CMD_HDR_DEVICE_ID_OFF;
	hdr->dw2 = 0x83000d;
	hdr->transfer_tags = slot_idx << CMD_HDR_IPTT_OFF;

	if (Packet->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_READ) {
		Buffer = Packet->InDataBuffer;
		BufferSize = Packet->InTransferLength;
		if (Buffer) {
			hdr->dw1 |= 1 << CMD_HDR_SSP_FRAME_TYPE_OFF;
			InvalidateDataCacheRange (Buffer, BufferSize);
		}
	} else if (Packet->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_WRITE) {
		Buffer = Packet->OutDataBuffer;
		BufferSize = Packet->OutTransferLength;
		if (Buffer)
			hdr->dw1 |= 2 << CMD_HDR_SSP_FRAME_TYPE_OFF;
	} else {
		hdr->dw1 |= 0 << CMD_HDR_SSP_FRAME_TYPE_OFF;
	}

	if (Buffer != NULL) {
		struct hisi_sas_sge *sg;
		UINT32 remain, len, pos = 0;
		int i = 0;

		remain = len = BufferSize;

		while (remain) {
			if (len > SGE_LIMIT)
				len = SGE_LIMIT;
			sg = &sge->sg[i];
			sg->addr = (UINT64)(Buffer + pos);
			sg->page_ctrl_0 = sg->page_ctrl_1 = 0;
			sg->data_len = len;
			sg->data_off = 0;
			remain -= len;
			pos += len;
			len = remain;
			i++;
		}

		hdr->prd_table_addr = (UINT64)sge;
		hdr->sg_len = i << CMD_HDR_DATA_SGL_LEN_OFF;
	}

	hdr->data_transfer_len = BufferSize;
	hdr->cmd_table_addr = (UINT64)cmd;
	hdr->sts_buffer_addr = (UINT64)sts;

	CopyMem (&cmd->cmd[36], Packet->Cdb, Packet->CdbLength);

	if (Packet->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_WRITE)
		WriteBackDataCacheRange (Buffer, BufferSize);

	asm("dsb  sy");
	asm("isb  sy");

	//start_delivery_v1_hw
	WRITE_REG32(DLVRY_Q_0_WR_PTR + queue * 0x14, ++w % QUEUE_SLOTS);

	//waiting for slot free, dma completed
	while (slot->used) {
		if (READ_REG32(OQ_INT_SRC) & BIT(queue)) {
      MicroSecondDelay(500);
			break;
		}
		NanoSecondDelay (100);
	}

	p = (UINT8 *)&slot->sts->status[0];
	if (p[SENSE_DATA_PRES]) {
		/* hack for spin up */
		SensePtr->Sense_Key = EFI_SCSI_SK_NOT_READY;
		SensePtr->Addnl_Sense_Code = EFI_SCSI_ASC_NOT_READY;
		SensePtr->Addnl_Sense_Code_Qualifier = EFI_SCSI_ASCQ_IN_PROGRESS;
		MicroSecondDelay(1000000);
	}
	return EFI_SUCCESS;
}