VOID *
UncachedInternalAllocateAlignedPool (
  IN EFI_MEMORY_TYPE  PoolType,
  IN UINTN            AllocationSize,
  IN UINTN            Alignment
  )
{
  VOID      *AlignedAddress;

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

  if (Alignment < EFI_PAGE_SIZE) {
    Alignment = EFI_PAGE_SIZE;
  }

  AlignedAddress = UncachedInternalAllocateAlignedPages (PoolType, EFI_SIZE_TO_PAGES (AllocationSize), Alignment);
  if (AlignedAddress == NULL) {
    return NULL;
  }

  AddPagesToList ((VOID *)(UINTN)ConvertToPhysicalAddress (AlignedAddress), (VOID *)(UINTN)AlignedAddress, EFI_SIZE_TO_PAGES (AllocationSize));

  return (VOID *) AlignedAddress;
}
VOID
EFIAPI
UncachedFreeAlignedPages (
  IN VOID   *Buffer,
  IN UINTN  Pages
  )
{
  EFI_STATUS            Status;
  EFI_PHYSICAL_ADDRESS  Memory;

  ASSERT (Pages != 0);

  Memory = ConvertToPhysicalAddress (Buffer);

  Status = gVirtualUncachedPages->RevertPages (gVirtualUncachedPages, Memory, Pages * EFI_PAGE_SIZE, PcdGet64 (PcdArmUncachedMemoryMask), gAttributes);


  Status = gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) Memory, Pages);
  ASSERT_EFI_ERROR (Status);
}
Пример #3
0
void FlashOperation(UINT32 op, void* addr, UINT32 data32)
{
    //UINT32 status;

    // NVMADDR only accept Physical Address
    NVMADDR = ConvertToPhysicalAddress(addr);

    #if 0 && defined(DEBUG)
        SerialPrint("FlashOperation / ");
        if (op == FLASH_WORD_WRITE)
        {
            SerialPrint("Write Address 0x");
            SerialPrintNumber(NVMADDR,16);
            SerialPrint("\r\n");
            mLED_1_Toggle();
        }
        if (op == FLASH_PAGE_ERASE)
        {
            SerialPrint("Erase Address 0x");
            SerialPrintNumber(NVMADDR,16);
            SerialPrint("\r\n");
            mLED_2_Toggle();
        }
    #endif

    // Load data into NVMDATA register
    NVMDATA = data32;

    // Suspend or Disable all Interrupts
    //status = DisableInterrupt();

    // Enable Flash Write/Erase Operations

    // 1-Select Flash operation to perform
    // Enable writes to WR bit and LVD circuit
    NVMCON = _NVMCON_WREN_MASK | op;

    // 2-Wait for LVD to become stable (at least 6us).
    Delayus(7);

    // 3-Write unlock sequence before the WR bit is set
    NVMKEY = 0xAA996655;
    NVMKEY = 0x556699AA;

    // 4-Start the operation (WR=1)
    NVMCONSET = _NVMCON_WR_MASK;

    // 5-Wait for operation to complete (WR=0)
    while (NVMCON & _NVMCON_WR_MASK);

    // 6-Disable Flash Write/Erase operations
    NVMCONCLR = _NVMCON_WREN_MASK;

    // Restore Interrupts if necessary
    #if 0
    if (status & 1)
    {
        EnableInterrupt();
    }
    else
        DisableInterrupt();
    #endif

    #if 0
    // Return NVMERR and LVDERR Error Status Bits
    if (NVMCON & (_NVMCON_WRERR_MASK | _NVMCON_LVDERR_MASK))
    {
        while (1)
        {
            mLED_2_Toggle();
            DelayUs(500);
        }
    }
    #endif
}
Пример #4
0
/**
  Provides the DMA controller-specific addresses needed to access system memory.

  Operation is relative to the DMA bus master.

  @param  Operation             Indicates if the bus master is going to read or write to system memory.
  @param  HostAddress           The system memory address to map to the DMA controller.
  @param  NumberOfBytes         On input the number of bytes to map. On output the number of bytes
                                that were mapped.
  @param  DeviceAddress         The resulting map address for the bus master controller to use to
                                access the hosts HostAddress.
  @param  Mapping               A resulting value to pass to Unmap().

  @retval EFI_SUCCESS           The range was mapped for the returned NumberOfBytes.
  @retval EFI_UNSUPPORTED       The HostAddress cannot be mapped as a common buffer.
  @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
  @retval EFI_OUT_OF_RESOURCES  The request could not be completed due to a lack of resources.
  @retval EFI_DEVICE_ERROR      The system hardware could not map the requested address.

**/
EFI_STATUS
EFIAPI
DmaMap (
  IN     DMA_MAP_OPERATION              Operation,
  IN     VOID                           *HostAddress,
  IN OUT UINTN                          *NumberOfBytes,
  OUT    PHYSICAL_ADDRESS               *DeviceAddress,
  OUT    VOID                           **Mapping
  )
{
  EFI_STATUS                      Status;
  MAP_INFO_INSTANCE               *Map;
  VOID                            *Buffer;
  EFI_GCD_MEMORY_SPACE_DESCRIPTOR GcdDescriptor;

  if (HostAddress == NULL || NumberOfBytes == NULL || DeviceAddress == NULL || Mapping == NULL ) {
    return EFI_INVALID_PARAMETER;
  }

  if (Operation >= MapOperationMaximum) {
    return EFI_INVALID_PARAMETER;
  }

  *DeviceAddress = ConvertToPhysicalAddress (HostAddress);

  // Remember range so we can flush on the other side
  Map = AllocatePool (sizeof (MAP_INFO_INSTANCE));
  if (Map == NULL) {
    return  EFI_OUT_OF_RESOURCES;
  }

  *Mapping = Map;

  if ((((UINTN)HostAddress & (gCacheAlignment - 1)) != 0) ||
      ((*NumberOfBytes % gCacheAlignment) != 0)) {

    // Get the cacheability of the region
    Status = gDS->GetMemorySpaceDescriptor (*DeviceAddress, &GcdDescriptor);
    if (EFI_ERROR(Status)) {
      return Status;
    }

    // If the mapped buffer is not an uncached buffer
    if ( (GcdDescriptor.Attributes != EFI_MEMORY_WC) &&
         (GcdDescriptor.Attributes != EFI_MEMORY_UC) )
    {
      //
      // If the buffer does not fill entire cache lines we must double buffer into
      // uncached memory. Device (PCI) address becomes uncached page.
      //
      Map->DoubleBuffer  = TRUE;
      Status = DmaAllocateBuffer (EfiBootServicesData, EFI_SIZE_TO_PAGES (*NumberOfBytes), &Buffer);
      if (EFI_ERROR (Status)) {
        return Status;
      }

      if ((Operation == MapOperationBusMasterRead) || (Operation == MapOperationBusMasterCommonBuffer)) {
        CopyMem (Buffer, HostAddress, *NumberOfBytes);
      }

      *DeviceAddress = (PHYSICAL_ADDRESS)(UINTN)Buffer;
    } else {
      Map->DoubleBuffer  = FALSE;
    }
  } else {
    Map->DoubleBuffer  = FALSE;

    // Flush the Data Cache (should not have any effect if the memory region is uncached)
    gCpu->FlushDataCache (gCpu, *DeviceAddress, *NumberOfBytes, EfiCpuFlushTypeWriteBackInvalidate);

    if ((Operation == MapOperationBusMasterRead) || (Operation == MapOperationBusMasterCommonBuffer)) {
      // In case the buffer is used for instance to send command to a PCI controller, we must ensure the memory is uncached
      Status = gDS->SetMemorySpaceAttributes (*DeviceAddress & ~(BASE_4KB - 1), ALIGN_VALUE (*NumberOfBytes, BASE_4KB), EFI_MEMORY_WC);
      ASSERT_EFI_ERROR (Status);
    }
  }

  Map->HostAddress   = (UINTN)HostAddress;
  Map->DeviceAddress = *DeviceAddress;
  Map->NumberOfBytes = *NumberOfBytes;
  Map->Operation     = Operation;

  return EFI_SUCCESS;
}
Пример #5
0
/**
  Provides the DMA controller-specific addresses needed to access system memory.

  Operation is relative to the DMA bus master.

  @param  Operation             Indicates if the bus master is going to read or write to system memory.
  @param  HostAddress           The system memory address to map to the DMA controller.
  @param  NumberOfBytes         On input the number of bytes to map. On output the number of bytes
                                that were mapped.
  @param  DeviceAddress         The resulting map address for the bus master controller to use to
                                access the hosts HostAddress.
  @param  Mapping               A resulting value to pass to Unmap().

  @retval EFI_SUCCESS           The range was mapped for the returned NumberOfBytes.
  @retval EFI_UNSUPPORTED       The HostAddress cannot be mapped as a common buffer.
  @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
  @retval EFI_OUT_OF_RESOURCES  The request could not be completed due to a lack of resources.
  @retval EFI_DEVICE_ERROR      The system hardware could not map the requested address.

**/
EFI_STATUS
EFIAPI
DmaMap (
  IN     DMA_MAP_OPERATION              Operation,
  IN     VOID                           *HostAddress,
  IN OUT UINTN                          *NumberOfBytes,
  OUT    PHYSICAL_ADDRESS               *DeviceAddress,
  OUT    VOID                           **Mapping
  )
{
  EFI_STATUS                      Status;
  MAP_INFO_INSTANCE               *Map;
  VOID                            *Buffer;
  EFI_GCD_MEMORY_SPACE_DESCRIPTOR GcdDescriptor;

  if (HostAddress == NULL || NumberOfBytes == NULL || DeviceAddress == NULL || Mapping == NULL ) {
    return EFI_INVALID_PARAMETER;
  }

  if (Operation >= MapOperationMaximum) {
    return EFI_INVALID_PARAMETER;
  }

  //
  // The debug implementation of UncachedMemoryAllocationLib in ArmPkg returns
  // a virtual uncached alias, and unmaps the cached ID mapping of the buffer,
  // in order to catch inadvertent references to the cached mapping.
  // Since HostToDeviceAddress () expects ID mapped input addresses, convert
  // the host address to an ID mapped address first.
  //
  *DeviceAddress = HostToDeviceAddress (ConvertToPhysicalAddress (HostAddress));

  // Remember range so we can flush on the other side
  Map = AllocatePool (sizeof (MAP_INFO_INSTANCE));
  if (Map == NULL) {
    return  EFI_OUT_OF_RESOURCES;
  }

  if ((((UINTN)HostAddress & (mCpu->DmaBufferAlignment - 1)) != 0) ||
      ((*NumberOfBytes & (mCpu->DmaBufferAlignment - 1)) != 0)) {

    // Get the cacheability of the region
    Status = gDS->GetMemorySpaceDescriptor ((UINTN)HostAddress, &GcdDescriptor);
    if (EFI_ERROR(Status)) {
      goto FreeMapInfo;
    }

    // If the mapped buffer is not an uncached buffer
    if ((GcdDescriptor.Attributes & (EFI_MEMORY_WB | EFI_MEMORY_WT)) != 0) {
      //
      // Operations of type MapOperationBusMasterCommonBuffer are only allowed
      // on uncached buffers.
      //
      if (Operation == MapOperationBusMasterCommonBuffer) {
        DEBUG ((EFI_D_ERROR,
          "%a: Operation type 'MapOperationBusMasterCommonBuffer' is only supported\n"
          "on memory regions that were allocated using DmaAllocateBuffer ()\n",
          __FUNCTION__));
        Status = EFI_UNSUPPORTED;
        goto FreeMapInfo;
      }

      //
      // If the buffer does not fill entire cache lines we must double buffer into
      // uncached memory. Device (PCI) address becomes uncached page.
      //
      Map->DoubleBuffer  = TRUE;
      Status = DmaAllocateBuffer (EfiBootServicesData, EFI_SIZE_TO_PAGES (*NumberOfBytes), &Buffer);
      if (EFI_ERROR (Status)) {
        goto FreeMapInfo;
      }

      if (Operation == MapOperationBusMasterRead) {
        CopyMem (Buffer, HostAddress, *NumberOfBytes);
      }

      *DeviceAddress = HostToDeviceAddress (ConvertToPhysicalAddress (Buffer));
      Map->BufferAddress = Buffer;
    } else {
      Map->DoubleBuffer  = FALSE;
    }
  } else {
    Map->DoubleBuffer  = FALSE;

    DEBUG_CODE_BEGIN ();

    //
    // The operation type check above only executes if the buffer happens to be
    // misaligned with respect to CWG, but even if it is aligned, we should not
    // allow arbitrary buffers to be used for creating consistent mappings.
    // So duplicate the check here when running in DEBUG mode, just to assert
    // that we are not trying to create a consistent mapping for cached memory.
    //
    Status = gDS->GetMemorySpaceDescriptor ((UINTN)HostAddress, &GcdDescriptor);
    ASSERT_EFI_ERROR(Status);

    ASSERT (Operation != MapOperationBusMasterCommonBuffer ||
            (GcdDescriptor.Attributes & (EFI_MEMORY_WB | EFI_MEMORY_WT)) == 0);

    DEBUG_CODE_END ();

    // Flush the Data Cache (should not have any effect if the memory region is uncached)
    mCpu->FlushDataCache (mCpu, (UINTN)HostAddress, *NumberOfBytes,
            EfiCpuFlushTypeWriteBackInvalidate);
  }

  Map->HostAddress   = (UINTN)HostAddress;
  Map->NumberOfBytes = *NumberOfBytes;
  Map->Operation     = Operation;

  *Mapping = Map;

  return EFI_SUCCESS;

FreeMapInfo:
  FreePool (Map);

  return Status;
}