public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
* DMA Buffer write operation not persisted
@ 2018-01-25 18:53 Rafael Machado
  2018-01-25 19:04 ` Andrew Fish
  2018-01-25 19:52 ` Paulo Alcantara
  0 siblings, 2 replies; 4+ messages in thread
From: Rafael Machado @ 2018-01-25 18:53 UTC (permalink / raw)
  To: edk2-devel@lists.01.org

Hi everyone.

I'm currently work on a task, and I need to write some data at a DMA buffer.
At the UEFI Driver Writer's guide, at page 359 there is a sample code of
how to do that.

Considering that code and adapting to my scenario I got the following
function (some debug prints are present for clarification):

EFI_STATUS
EFIAPI
DoBusMasterWrite (
  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciIo,
  IN UINT8 *HostAddress,
  IN UINTN *Length,
  IN UINT32 Value
)
{
  EFI_STATUS Status;
  UINTN NumberOfBytes;
  EFI_PHYSICAL_ADDRESS DeviceAddress;
  VOID *Mapping;
  UINT64 ReadValue;

  //
  // Call Map() to retrieve the DeviceAddress to use for the bus
  // master write operation. The Map() function may not support
  // performing a DMA operation for the entire length, so it may
  // be broken up into smaller DMA operations.
  //
  NumberOfBytes = *Length;
  Status = PciIo->Map (PciIo, // This

 EfiPciIoOperationBusMasterCommonBuffer, // Operation
                                     (VOID *)HostAddress, // HostAddress
                                     &NumberOfBytes, // NumberOfBytes
                                     &DeviceAddress, //DeviceAddress
                                     &Mapping //Mapping);

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

  //
  // Write the data to the desired address
  // This write operation also starts the DMA transaction
  //
  Status = PciIo->Mem.Write (PciIo, // This
                                               EfiPciIoWidthUint32, // Width
                                               *HostAddress,
                                               1, // Count
                                               &Value // Buffer
                                               );

  Print(L"NumberOfBytes: %d\r\n", NumberOfBytes);
  Print(L"address: 0x%x\r\n", HostAddress);
  Print(L"Value: 0x%x\r\n", Value);
  Print(L"Status: %r\r\n", Status);

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

  //
  // The operations performed by PollMem() also flush all posted
  // writes from the PCI bus master and through PCI-to-PCI bridges.
  //
  Status = PciIo->PollMem (PciIo, // This
                                               EfiPciIoWidthUint32, // Width
                                               *HostAddress, // Offset
                                               0xFFFFFFFF,// Mask
                                               Value,// Value
                                               EFI_TIMER_PERIOD_SECONDS
(1), // Timeout
                                               &ReadValue // Result
                                               );
  Print(L"Status2: %r\r\n", Status);

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

  //
  // Call Flush() to flush all write transactions to system memory
  //
  Status = PciIo->Flush (PciIo);
  Print(L"Status3: %r\r\n", Status);

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

  //
  // Call Unmap() to complete the bus master write operation
  //
  Status = PciIo->Unmap (PciIo, Mapping);
  Print(L"Status4: %r\r\n", Status);

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

The output of this function is this:
  NumberOfBytes: 4
  address: 0xCCCAC000
  Value: 0xAAAAA
  Status: Success
  Status2: Success
  Status3: Success
  Status4: Success

The problem is that when I try to read this memory content using the dmem
command at the efiShell the value 0xAAAAA cannot be found. Seems something
is locking the DMA trasaction.
Can someone give me some light?

Thanks and Regard
Rafael R. Machado


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: DMA Buffer write operation not persisted
  2018-01-25 18:53 DMA Buffer write operation not persisted Rafael Machado
@ 2018-01-25 19:04 ` Andrew Fish
  2018-01-25 19:15   ` Rafael Machado
  2018-01-25 19:52 ` Paulo Alcantara
  1 sibling, 1 reply; 4+ messages in thread
From: Andrew Fish @ 2018-01-25 19:04 UTC (permalink / raw)
  To: Rafael Machado; +Cc: edk2-devel@lists.01.org

Rafeal,

There are some good summaries in the UEFI Spec that really help. 

DMA Bus Master Common Buffer Operation
• Call AllocateBuffer() to allocate a common buffer.
• Call Map() for EfiPciOperationBusMasterCommonBuffer or EfiPciOperationBusMasterCommonBuffer64.
• Program the DMA Bus Master with the DeviceAddress returned by Map().
• The common buffer can now be accessed equally by the processor and the DMA bus master.
• Call Unmap().
• Call FreeBuffer().

Did you miss the PciIo->AllocateBuffer() call?

For x86 it can abstract things like DMA only supported < 4GB. 
For ARM it may need to change the cacheability of the region etc. 

Thanks,

Andrew Fish

> On Jan 25, 2018, at 10:53 AM, Rafael Machado <rafaelrodrigues.machado@gmail.com> wrote:
> 
> Hi everyone.
> 
> I'm currently work on a task, and I need to write some data at a DMA buffer.
> At the UEFI Driver Writer's guide, at page 359 there is a sample code of
> how to do that.
> 
> Considering that code and adapting to my scenario I got the following
> function (some debug prints are present for clarification):
> 
> EFI_STATUS
> EFIAPI
> DoBusMasterWrite (
>  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciIo,
>  IN UINT8 *HostAddress,
>  IN UINTN *Length,
>  IN UINT32 Value
> )
> {
>  EFI_STATUS Status;
>  UINTN NumberOfBytes;
>  EFI_PHYSICAL_ADDRESS DeviceAddress;
>  VOID *Mapping;
>  UINT64 ReadValue;
> 
>  //
>  // Call Map() to retrieve the DeviceAddress to use for the bus
>  // master write operation. The Map() function may not support
>  // performing a DMA operation for the entire length, so it may
>  // be broken up into smaller DMA operations.
>  //
>  NumberOfBytes = *Length;
>  Status = PciIo->Map (PciIo, // This
> 
> EfiPciIoOperationBusMasterCommonBuffer, // Operation
>                                     (VOID *)HostAddress, // HostAddress
>                                     &NumberOfBytes, // NumberOfBytes
>                                     &DeviceAddress, //DeviceAddress
>                                     &Mapping //Mapping);
> 
>  if (EFI_ERROR (Status)) {
>    return Status;
>  }
> 
>  //
>  // Write the data to the desired address
>  // This write operation also starts the DMA transaction
>  //
>  Status = PciIo->Mem.Write (PciIo, // This
>                                               EfiPciIoWidthUint32, // Width
>                                               *HostAddress,
>                                               1, // Count
>                                               &Value // Buffer
>                                               );
> 
>  Print(L"NumberOfBytes: %d\r\n", NumberOfBytes);
>  Print(L"address: 0x%x\r\n", HostAddress);
>  Print(L"Value: 0x%x\r\n", Value);
>  Print(L"Status: %r\r\n", Status);
> 
>  if (EFI_ERROR (Status)) {
> return Status;
>  }
> 
>  //
>  // The operations performed by PollMem() also flush all posted
>  // writes from the PCI bus master and through PCI-to-PCI bridges.
>  //
>  Status = PciIo->PollMem (PciIo, // This
>                                               EfiPciIoWidthUint32, // Width
>                                               *HostAddress, // Offset
>                                               0xFFFFFFFF,// Mask
>                                               Value,// Value
>                                               EFI_TIMER_PERIOD_SECONDS
> (1), // Timeout
>                                               &ReadValue // Result
>                                               );
>  Print(L"Status2: %r\r\n", Status);
> 
>  if (EFI_ERROR (Status)) {
> return Status;
>  }
> 
>  //
>  // Call Flush() to flush all write transactions to system memory
>  //
>  Status = PciIo->Flush (PciIo);
>  Print(L"Status3: %r\r\n", Status);
> 
>  if (EFI_ERROR (Status)) {
> return Status;
>  }
> 
>  //
>  // Call Unmap() to complete the bus master write operation
>  //
>  Status = PciIo->Unmap (PciIo, Mapping);
>  Print(L"Status4: %r\r\n", Status);
> 
>  if (EFI_ERROR (Status)) {
> return Status;
>  }
>  return Status;
> }
> 
> The output of this function is this:
>  NumberOfBytes: 4
>  address: 0xCCCAC000
>  Value: 0xAAAAA
>  Status: Success
>  Status2: Success
>  Status3: Success
>  Status4: Success
> 
> The problem is that when I try to read this memory content using the dmem
> command at the efiShell the value 0xAAAAA cannot be found. Seems something
> is locking the DMA trasaction.
> Can someone give me some light?
> 
> Thanks and Regard
> Rafael R. Machado
> _______________________________________________
> edk2-devel mailing list
> edk2-devel@lists.01.org
> https://lists.01.org/mailman/listinfo/edk2-devel



^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: DMA Buffer write operation not persisted
  2018-01-25 19:04 ` Andrew Fish
@ 2018-01-25 19:15   ` Rafael Machado
  0 siblings, 0 replies; 4+ messages in thread
From: Rafael Machado @ 2018-01-25 19:15 UTC (permalink / raw)
  To: Andrew Fish; +Cc: edk2-devel@lists.01.org

Hi Andrew

Thanks for the answer.

The allocation was done at other part of the code. But yet, I used the
PciI->AllocateBuffer() function.

One question, about the topics retrieved from the spec.
When the spec says "• The common buffer can now be accessed equally by the
processor and the DMA bus master."

Does this means that I can write some data using a simple pointer, like for
example copying some data using MemCopy? Or should I still use the
PciIo->Mem.Write...?

I'll really this part of the spec carefully.

Thanks and Regards
Rafael R. Machado

Em qui, 25 de jan de 2018 às 17:04, Andrew Fish <afish@apple.com> escreveu:

> Rafeal,
>
> There are some good summaries in the UEFI Spec that really help.
>
> DMA Bus Master Common Buffer Operation
> • Call AllocateBuffer() to allocate a common buffer.
> • Call Map() for EfiPciOperationBusMasterCommonBuffer or
> EfiPciOperationBusMasterCommonBuffer64.
> • Program the DMA Bus Master with the DeviceAddress returned by Map().
> • The common buffer can now be accessed equally by the processor and the
> DMA bus master.
> • Call Unmap().
> • Call FreeBuffer().
>
> Did you miss the PciIo->AllocateBuffer() call?
>
> For x86 it can abstract things like DMA only supported < 4GB.
> For ARM it may need to change the cacheability of the region etc.
>
> Thanks,
>
> Andrew Fish
>
> > On Jan 25, 2018, at 10:53 AM, Rafael Machado <
> rafaelrodrigues.machado@gmail.com> wrote:
> >
> > Hi everyone.
> >
> > I'm currently work on a task, and I need to write some data at a DMA
> buffer.
> > At the UEFI Driver Writer's guide, at page 359 there is a sample code of
> > how to do that.
> >
> > Considering that code and adapting to my scenario I got the following
> > function (some debug prints are present for clarification):
> >
> > EFI_STATUS
> > EFIAPI
> > DoBusMasterWrite (
> >  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciIo,
> >  IN UINT8 *HostAddress,
> >  IN UINTN *Length,
> >  IN UINT32 Value
> > )
> > {
> >  EFI_STATUS Status;
> >  UINTN NumberOfBytes;
> >  EFI_PHYSICAL_ADDRESS DeviceAddress;
> >  VOID *Mapping;
> >  UINT64 ReadValue;
> >
> >  //
> >  // Call Map() to retrieve the DeviceAddress to use for the bus
> >  // master write operation. The Map() function may not support
> >  // performing a DMA operation for the entire length, so it may
> >  // be broken up into smaller DMA operations.
> >  //
> >  NumberOfBytes = *Length;
> >  Status = PciIo->Map (PciIo, // This
> >
> > EfiPciIoOperationBusMasterCommonBuffer, // Operation
> >                                     (VOID *)HostAddress, // HostAddress
> >                                     &NumberOfBytes, // NumberOfBytes
> >                                     &DeviceAddress, //DeviceAddress
> >                                     &Mapping //Mapping);
> >
> >  if (EFI_ERROR (Status)) {
> >    return Status;
> >  }
> >
> >  //
> >  // Write the data to the desired address
> >  // This write operation also starts the DMA transaction
> >  //
> >  Status = PciIo->Mem.Write (PciIo, // This
> >                                               EfiPciIoWidthUint32, //
> Width
> >                                               *HostAddress,
> >                                               1, // Count
> >                                               &Value // Buffer
> >                                               );
> >
> >  Print(L"NumberOfBytes: %d\r\n", NumberOfBytes);
> >  Print(L"address: 0x%x\r\n", HostAddress);
> >  Print(L"Value: 0x%x\r\n", Value);
> >  Print(L"Status: %r\r\n", Status);
> >
> >  if (EFI_ERROR (Status)) {
> > return Status;
> >  }
> >
> >  //
> >  // The operations performed by PollMem() also flush all posted
> >  // writes from the PCI bus master and through PCI-to-PCI bridges.
> >  //
> >  Status = PciIo->PollMem (PciIo, // This
> >                                               EfiPciIoWidthUint32, //
> Width
> >                                               *HostAddress, // Offset
> >                                               0xFFFFFFFF,// Mask
> >                                               Value,// Value
> >                                               EFI_TIMER_PERIOD_SECONDS
> > (1), // Timeout
> >                                               &ReadValue // Result
> >                                               );
> >  Print(L"Status2: %r\r\n", Status);
> >
> >  if (EFI_ERROR (Status)) {
> > return Status;
> >  }
> >
> >  //
> >  // Call Flush() to flush all write transactions to system memory
> >  //
> >  Status = PciIo->Flush (PciIo);
> >  Print(L"Status3: %r\r\n", Status);
> >
> >  if (EFI_ERROR (Status)) {
> > return Status;
> >  }
> >
> >  //
> >  // Call Unmap() to complete the bus master write operation
> >  //
> >  Status = PciIo->Unmap (PciIo, Mapping);
> >  Print(L"Status4: %r\r\n", Status);
> >
> >  if (EFI_ERROR (Status)) {
> > return Status;
> >  }
> >  return Status;
> > }
> >
> > The output of this function is this:
> >  NumberOfBytes: 4
> >  address: 0xCCCAC000
> >  Value: 0xAAAAA
> >  Status: Success
> >  Status2: Success
> >  Status3: Success
> >  Status4: Success
> >
> > The problem is that when I try to read this memory content using the dmem
> > command at the efiShell the value 0xAAAAA cannot be found. Seems
> something
> > is locking the DMA trasaction.
> > Can someone give me some light?
> >
> > Thanks and Regard
> > Rafael R. Machado
> > _______________________________________________
> > edk2-devel mailing list
> > edk2-devel@lists.01.org
> > https://lists.01.org/mailman/listinfo/edk2-devel
>
>


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: DMA Buffer write operation not persisted
  2018-01-25 18:53 DMA Buffer write operation not persisted Rafael Machado
  2018-01-25 19:04 ` Andrew Fish
@ 2018-01-25 19:52 ` Paulo Alcantara
  1 sibling, 0 replies; 4+ messages in thread
From: Paulo Alcantara @ 2018-01-25 19:52 UTC (permalink / raw)
  To: edk2-devel, Rafael Machado, edk2-devel@lists.01.org



On January 25, 2018 4:53:06 PM GMT-02:00, Rafael Machado <rafaelrodrigues.machado@gmail.com> wrote:
>Hi everyone.
>
>I'm currently work on a task, and I need to write some data at a DMA
>buffer.
>At the UEFI Driver Writer's guide, at page 359 there is a sample code
>of
>how to do that.
>
>Considering that code and adapting to my scenario I got the following
>function (some debug prints are present for clarification):
>
>EFI_STATUS
>EFIAPI
>DoBusMasterWrite (
>  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciIo,
>  IN UINT8 *HostAddress,
>  IN UINTN *Length,
>  IN UINT32 Value
>)
>{
>  EFI_STATUS Status;
>  UINTN NumberOfBytes;
>  EFI_PHYSICAL_ADDRESS DeviceAddress;
>  VOID *Mapping;
>  UINT64 ReadValue;
>
>  //
>  // Call Map() to retrieve the DeviceAddress to use for the bus
>  // master write operation. The Map() function may not support
>  // performing a DMA operation for the entire length, so it may
>  // be broken up into smaller DMA operations.
>  //
>  NumberOfBytes = *Length;
>  Status = PciIo->Map (PciIo, // This
>
> EfiPciIoOperationBusMasterCommonBuffer, // Operation
>                                    (VOID *)HostAddress, // HostAddress
>                                     &NumberOfBytes, // NumberOfBytes
>                                     &DeviceAddress, //DeviceAddress
>                                     &Mapping //Mapping);
>
>  if (EFI_ERROR (Status)) {
>    return Status;
>  }
>
>  //
>  // Write the data to the desired address
>  // This write operation also starts the DMA transaction
>  //
>  Status = PciIo->Mem.Write (PciIo, // This
>                                          EfiPciIoWidthUint32, // Width
>                                               *HostAddress,
>                                               1, // Count
>                                               &Value // Buffer
>                                               );

I'm not sure, but I think you're passing the wrong value to the 3rd parameter (Address). Shouldn't that be "(UINT64)(UINTN)HostAddress"?

Paulo

>
>  Print(L"NumberOfBytes: %d\r\n", NumberOfBytes);
>  Print(L"address: 0x%x\r\n", HostAddress);
>  Print(L"Value: 0x%x\r\n", Value);
>  Print(L"Status: %r\r\n", Status);
>
>  if (EFI_ERROR (Status)) {
>return Status;
>  }
>
>  //
>  // The operations performed by PollMem() also flush all posted
>  // writes from the PCI bus master and through PCI-to-PCI bridges.
>  //
>  Status = PciIo->PollMem (PciIo, // This
>                                          EfiPciIoWidthUint32, // Width
>                                               *HostAddress, // Offset
>                                               0xFFFFFFFF,// Mask
>                                               Value,// Value
>                                               EFI_TIMER_PERIOD_SECONDS
>(1), // Timeout
>                                               &ReadValue // Result
>                                               );
>  Print(L"Status2: %r\r\n", Status);
>
>  if (EFI_ERROR (Status)) {
>return Status;
>  }
>
>  //
>  // Call Flush() to flush all write transactions to system memory
>  //
>  Status = PciIo->Flush (PciIo);
>  Print(L"Status3: %r\r\n", Status);
>
>  if (EFI_ERROR (Status)) {
>return Status;
>  }
>
>  //
>  // Call Unmap() to complete the bus master write operation
>  //
>  Status = PciIo->Unmap (PciIo, Mapping);
>  Print(L"Status4: %r\r\n", Status);
>
>  if (EFI_ERROR (Status)) {
>return Status;
>  }
>  return Status;
>}
>
>The output of this function is this:
>  NumberOfBytes: 4
>  address: 0xCCCAC000
>  Value: 0xAAAAA
>  Status: Success
>  Status2: Success
>  Status3: Success
>  Status4: Success
>
>The problem is that when I try to read this memory content using the
>dmem
>command at the efiShell the value 0xAAAAA cannot be found. Seems
>something
>is locking the DMA trasaction.
>Can someone give me some light?
>
>Thanks and Regard
>Rafael R. Machado
>_______________________________________________
>edk2-devel mailing list
>edk2-devel@lists.01.org
>https://lists.01.org/mailman/listinfo/edk2-devel

-- 
Sent from my Android device with K-9 Mail. Please excuse my brevity.


^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2018-01-25 19:47 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2018-01-25 18:53 DMA Buffer write operation not persisted Rafael Machado
2018-01-25 19:04 ` Andrew Fish
2018-01-25 19:15   ` Rafael Machado
2018-01-25 19:52 ` Paulo Alcantara

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox