SnpReceive.c 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. /** @file
  2. Implementation of the SNP.Receive() function and its private helpers if any.
  3. Copyright (C) 2013, Red Hat, Inc.
  4. Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR>
  5. SPDX-License-Identifier: BSD-2-Clause-Patent
  6. **/
  7. #include <Library/BaseLib.h>
  8. #include <Library/BaseMemoryLib.h>
  9. #include <Library/UefiBootServicesTableLib.h>
  10. #include "VirtioNet.h"
  11. /**
  12. Receives a packet from a network interface.
  13. @param This The protocol instance pointer.
  14. @param HeaderSize The size, in bytes, of the media header received on the
  15. network interface. If this parameter is NULL, then the
  16. media header size will not be returned.
  17. @param BufferSize On entry, the size, in bytes, of Buffer. On exit, the
  18. size, in bytes, of the packet that was received on the
  19. network interface.
  20. @param Buffer A pointer to the data buffer to receive both the media
  21. header and the data.
  22. @param SrcAddr The source HW MAC address. If this parameter is NULL, the
  23. HW MAC source address will not be extracted from the media
  24. header.
  25. @param DestAddr The destination HW MAC address. If this parameter is NULL,
  26. the HW MAC destination address will not be extracted from
  27. the media header.
  28. @param Protocol The media header type. If this parameter is NULL, then the
  29. protocol will not be extracted from the media header. See
  30. RFC 1700 section "Ether Types" for examples.
  31. @retval EFI_SUCCESS The received data was stored in Buffer, and
  32. BufferSize has been updated to the number of
  33. bytes received.
  34. @retval EFI_NOT_STARTED The network interface has not been started.
  35. @retval EFI_NOT_READY The network interface is too busy to accept
  36. this transmit request.
  37. @retval EFI_BUFFER_TOO_SMALL The BufferSize parameter is too small.
  38. @retval EFI_INVALID_PARAMETER One or more of the parameters has an
  39. unsupported value.
  40. @retval EFI_DEVICE_ERROR The command could not be sent to the network
  41. interface.
  42. @retval EFI_UNSUPPORTED This function is not supported by the network
  43. interface.
  44. **/
  45. EFI_STATUS
  46. EFIAPI
  47. VirtioNetReceive (
  48. IN EFI_SIMPLE_NETWORK_PROTOCOL *This,
  49. OUT UINTN *HeaderSize OPTIONAL,
  50. IN OUT UINTN *BufferSize,
  51. OUT VOID *Buffer,
  52. OUT EFI_MAC_ADDRESS *SrcAddr OPTIONAL,
  53. OUT EFI_MAC_ADDRESS *DestAddr OPTIONAL,
  54. OUT UINT16 *Protocol OPTIONAL
  55. )
  56. {
  57. VNET_DEV *Dev;
  58. EFI_TPL OldTpl;
  59. EFI_STATUS Status;
  60. UINT16 RxCurUsed;
  61. UINT16 UsedElemIdx;
  62. UINT32 DescIdx;
  63. UINT32 RxLen;
  64. UINTN OrigBufferSize;
  65. UINT8 *RxPtr;
  66. UINT16 AvailIdx;
  67. EFI_STATUS NotifyStatus;
  68. UINTN RxBufOffset;
  69. if ((This == NULL) || (BufferSize == NULL) || (Buffer == NULL)) {
  70. return EFI_INVALID_PARAMETER;
  71. }
  72. Dev = VIRTIO_NET_FROM_SNP (This);
  73. OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
  74. switch (Dev->Snm.State) {
  75. case EfiSimpleNetworkStopped:
  76. Status = EFI_NOT_STARTED;
  77. goto Exit;
  78. case EfiSimpleNetworkStarted:
  79. Status = EFI_DEVICE_ERROR;
  80. goto Exit;
  81. default:
  82. break;
  83. }
  84. //
  85. // virtio-0.9.5, 2.4.2 Receiving Used Buffers From the Device
  86. //
  87. MemoryFence ();
  88. RxCurUsed = *Dev->RxRing.Used.Idx;
  89. MemoryFence ();
  90. if (Dev->RxLastUsed == RxCurUsed) {
  91. Status = EFI_NOT_READY;
  92. goto Exit;
  93. }
  94. UsedElemIdx = Dev->RxLastUsed % Dev->RxRing.QueueSize;
  95. DescIdx = Dev->RxRing.Used.UsedElem[UsedElemIdx].Id;
  96. RxLen = Dev->RxRing.Used.UsedElem[UsedElemIdx].Len;
  97. //
  98. // the virtio-net request header must be complete; we skip it
  99. //
  100. ASSERT (RxLen >= Dev->RxRing.Desc[DescIdx].Len);
  101. RxLen -= Dev->RxRing.Desc[DescIdx].Len;
  102. //
  103. // the host must not have filled in more data than requested
  104. //
  105. ASSERT (RxLen <= Dev->RxRing.Desc[DescIdx + 1].Len);
  106. OrigBufferSize = *BufferSize;
  107. *BufferSize = RxLen;
  108. if (OrigBufferSize < RxLen) {
  109. Status = EFI_BUFFER_TOO_SMALL;
  110. goto Exit; // keep the packet
  111. }
  112. if (RxLen < Dev->Snm.MediaHeaderSize) {
  113. Status = EFI_DEVICE_ERROR;
  114. goto RecycleDesc; // drop useless short packet
  115. }
  116. if (HeaderSize != NULL) {
  117. *HeaderSize = Dev->Snm.MediaHeaderSize;
  118. }
  119. RxBufOffset = (UINTN)(Dev->RxRing.Desc[DescIdx + 1].Addr -
  120. Dev->RxBufDeviceBase);
  121. RxPtr = Dev->RxBuf + RxBufOffset;
  122. CopyMem (Buffer, RxPtr, RxLen);
  123. if (DestAddr != NULL) {
  124. CopyMem (DestAddr, RxPtr, SIZE_OF_VNET (Mac));
  125. }
  126. RxPtr += SIZE_OF_VNET (Mac);
  127. if (SrcAddr != NULL) {
  128. CopyMem (SrcAddr, RxPtr, SIZE_OF_VNET (Mac));
  129. }
  130. RxPtr += SIZE_OF_VNET (Mac);
  131. if (Protocol != NULL) {
  132. *Protocol = (UINT16)((RxPtr[0] << 8) | RxPtr[1]);
  133. }
  134. RxPtr += sizeof (UINT16);
  135. Status = EFI_SUCCESS;
  136. RecycleDesc:
  137. ++Dev->RxLastUsed;
  138. //
  139. // virtio-0.9.5, 2.4.1 Supplying Buffers to The Device
  140. //
  141. AvailIdx = *Dev->RxRing.Avail.Idx;
  142. Dev->RxRing.Avail.Ring[AvailIdx++ % Dev->RxRing.QueueSize] =
  143. (UINT16)DescIdx;
  144. MemoryFence ();
  145. *Dev->RxRing.Avail.Idx = AvailIdx;
  146. MemoryFence ();
  147. NotifyStatus = Dev->VirtIo->SetQueueNotify (Dev->VirtIo, VIRTIO_NET_Q_RX);
  148. if (!EFI_ERROR (Status)) {
  149. // earlier error takes precedence
  150. Status = NotifyStatus;
  151. }
  152. Exit:
  153. gBS->RestoreTPL (OldTpl);
  154. return Status;
  155. }