Receive.c 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  1. /** @file
  2. Implementation of receiving a packet from a network interface.
  3. Copyright (c) 2004 - 2010, Intel Corporation. All rights reserved.<BR>
  4. SPDX-License-Identifier: BSD-2-Clause-Patent
  5. **/
  6. #include "Snp.h"
  7. /**
  8. Call UNDI to receive a packet and fills in the data in the input pointers.
  9. @param Snp Pointer to snp driver structure
  10. @param Buffer Pointer to the memory for the received data
  11. @param BufferSize Pointer to the length of the buffer on entry and contains
  12. the length of the received data on return
  13. @param HeaderSize Pointer to the header portion of the data received.
  14. @param SrcAddr Pointer to contain the source ethernet address on return
  15. @param DestAddr Pointer to contain the destination ethernet address on
  16. return
  17. @param Protocol Pointer to contain the protocol type from the ethernet
  18. header on return
  19. @retval EFI_SUCCESS The received data was stored in Buffer, and
  20. BufferSize has been updated to the number of
  21. bytes received.
  22. @retval EFI_DEVICE_ERROR Fail to execute UNDI command.
  23. @retval EFI_NOT_READY No packets have been received on the network
  24. interface.
  25. @retval EFI_BUFFER_TOO_SMALL BufferSize is too small for the received
  26. packets. BufferSize has been updated to the
  27. required size.
  28. **/
  29. EFI_STATUS
  30. PxeReceive (
  31. SNP_DRIVER *Snp,
  32. VOID *Buffer,
  33. UINTN *BufferSize,
  34. UINTN *HeaderSize,
  35. EFI_MAC_ADDRESS *SrcAddr,
  36. EFI_MAC_ADDRESS *DestAddr,
  37. UINT16 *Protocol
  38. )
  39. {
  40. PXE_CPB_RECEIVE *Cpb;
  41. PXE_DB_RECEIVE *Db;
  42. UINTN BuffSize;
  43. Cpb = Snp->Cpb;
  44. Db = Snp->Db;
  45. BuffSize = *BufferSize;
  46. Cpb->BufferAddr = (UINT64)(UINTN)Buffer;
  47. Cpb->BufferLen = (UINT32)*BufferSize;
  48. Cpb->reserved = 0;
  49. Snp->Cdb.OpCode = PXE_OPCODE_RECEIVE;
  50. Snp->Cdb.OpFlags = PXE_OPFLAGS_NOT_USED;
  51. Snp->Cdb.CPBsize = (UINT16)sizeof (PXE_CPB_RECEIVE);
  52. Snp->Cdb.CPBaddr = (UINT64)(UINTN)Cpb;
  53. Snp->Cdb.DBsize = (UINT16)sizeof (PXE_DB_RECEIVE);
  54. Snp->Cdb.DBaddr = (UINT64)(UINTN)Db;
  55. Snp->Cdb.StatCode = PXE_STATCODE_INITIALIZE;
  56. Snp->Cdb.StatFlags = PXE_STATFLAGS_INITIALIZE;
  57. Snp->Cdb.IFnum = Snp->IfNum;
  58. Snp->Cdb.Control = PXE_CONTROL_LAST_CDB_IN_LIST;
  59. //
  60. // Issue UNDI command and check result.
  61. //
  62. DEBUG ((DEBUG_NET, "\nsnp->undi.receive () "));
  63. (*Snp->IssueUndi32Command)((UINT64)(UINTN)&Snp->Cdb);
  64. switch (Snp->Cdb.StatCode) {
  65. case PXE_STATCODE_SUCCESS:
  66. break;
  67. case PXE_STATCODE_NO_DATA:
  68. DEBUG (
  69. (DEBUG_NET,
  70. "\nsnp->undi.receive () %xh:%xh\n",
  71. Snp->Cdb.StatFlags,
  72. Snp->Cdb.StatCode)
  73. );
  74. return EFI_NOT_READY;
  75. default:
  76. DEBUG (
  77. (DEBUG_ERROR,
  78. "\nsnp->undi.receive() %xh:%xh\n",
  79. Snp->Cdb.StatFlags,
  80. Snp->Cdb.StatCode)
  81. );
  82. return EFI_DEVICE_ERROR;
  83. }
  84. *BufferSize = Db->FrameLen;
  85. if (HeaderSize != NULL) {
  86. *HeaderSize = Db->MediaHeaderLen;
  87. }
  88. if (SrcAddr != NULL) {
  89. CopyMem (SrcAddr, &Db->SrcAddr, Snp->Mode.HwAddressSize);
  90. }
  91. if (DestAddr != NULL) {
  92. CopyMem (DestAddr, &Db->DestAddr, Snp->Mode.HwAddressSize);
  93. }
  94. if (Protocol != NULL) {
  95. //
  96. // We need to do the byte swapping
  97. //
  98. *Protocol = (UINT16)PXE_SWAP_UINT16 (Db->Protocol);
  99. }
  100. //
  101. // We have received a packet from network interface, which implies that the
  102. // network cable should be present. While, some UNDI driver may not report
  103. // correct media status during Snp->Initialize(). So, we need ensure
  104. // MediaPresent in SNP mode data is set to correct value.
  105. //
  106. if (Snp->Mode.MediaPresentSupported && !Snp->Mode.MediaPresent) {
  107. Snp->Mode.MediaPresent = TRUE;
  108. }
  109. return (*BufferSize <= BuffSize) ? EFI_SUCCESS : EFI_BUFFER_TOO_SMALL;
  110. }
  111. /**
  112. Receives a packet from a network interface.
  113. This function retrieves one packet from the receive queue of a network interface.
  114. If there are no packets on the receive queue, then EFI_NOT_READY will be
  115. returned. If there is a packet on the receive queue, and the size of the packet
  116. is smaller than BufferSize, then the contents of the packet will be placed in
  117. Buffer, and BufferSize will be updated with the actual size of the packet.
  118. In addition, if SrcAddr, DestAddr, and Protocol are not NULL, then these values
  119. will be extracted from the media header and returned. EFI_SUCCESS will be
  120. returned if a packet was successfully received.
  121. If BufferSize is smaller than the received packet, then the size of the receive
  122. packet will be placed in BufferSize and EFI_BUFFER_TOO_SMALL will be returned.
  123. If the driver has not been initialized, EFI_DEVICE_ERROR will be returned.
  124. @param This A pointer to the EFI_SIMPLE_NETWORK_PROTOCOL instance.
  125. @param HeaderSize The size, in bytes, of the media header received on the network
  126. interface. If this parameter is NULL, then the media header size
  127. will not be returned.
  128. @param BufferSize On entry, the size, in bytes, of Buffer. On exit, the size, in
  129. bytes, of the packet that was received on the network interface.
  130. @param Buffer A pointer to the data buffer to receive both the media
  131. header and the data.
  132. @param SrcAddr The source HW MAC address. If this parameter is NULL, the HW
  133. MAC source address will not be extracted from the media header.
  134. @param DestAddr The destination HW MAC address. If this parameter is NULL,
  135. the HW MAC destination address will not be extracted from
  136. the media header.
  137. @param Protocol The media header type. If this parameter is NULL, then the
  138. protocol will not be extracted from the media header. See
  139. RFC 1700 section "Ether Types" for examples.
  140. @retval EFI_SUCCESS The received data was stored in Buffer, and
  141. BufferSize has been updated to the number of
  142. bytes received.
  143. @retval EFI_NOT_STARTED The network interface has not been started.
  144. @retval EFI_NOT_READY No packets have been received on the network interface.
  145. @retval EFI_BUFFER_TOO_SMALL BufferSize is too small for the received packets.
  146. BufferSize has been updated to the required size.
  147. @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE:
  148. * The This parameter is NULL
  149. * The This parameter does not point to a valid
  150. EFI_SIMPLE_NETWORK_PROTOCOL structure.
  151. * The BufferSize parameter is NULL
  152. * The Buffer parameter is NULL
  153. @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.
  154. **/
  155. EFI_STATUS
  156. EFIAPI
  157. SnpUndi32Receive (
  158. IN EFI_SIMPLE_NETWORK_PROTOCOL *This,
  159. OUT UINTN *HeaderSize OPTIONAL,
  160. IN OUT UINTN *BufferSize,
  161. OUT VOID *Buffer,
  162. OUT EFI_MAC_ADDRESS *SrcAddr OPTIONAL,
  163. OUT EFI_MAC_ADDRESS *DestAddr OPTIONAL,
  164. OUT UINT16 *Protocol OPTIONAL
  165. )
  166. {
  167. SNP_DRIVER *Snp;
  168. EFI_TPL OldTpl;
  169. EFI_STATUS Status;
  170. if (This == NULL) {
  171. return EFI_INVALID_PARAMETER;
  172. }
  173. Snp = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);
  174. OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
  175. switch (Snp->Mode.State) {
  176. case EfiSimpleNetworkInitialized:
  177. break;
  178. case EfiSimpleNetworkStopped:
  179. Status = EFI_NOT_STARTED;
  180. goto ON_EXIT;
  181. default:
  182. Status = EFI_DEVICE_ERROR;
  183. goto ON_EXIT;
  184. }
  185. if ((BufferSize == NULL) || (Buffer == NULL)) {
  186. Status = EFI_INVALID_PARAMETER;
  187. goto ON_EXIT;
  188. }
  189. if (Snp->Mode.ReceiveFilterSetting == 0) {
  190. Status = EFI_DEVICE_ERROR;
  191. goto ON_EXIT;
  192. }
  193. Status = PxeReceive (
  194. Snp,
  195. Buffer,
  196. BufferSize,
  197. HeaderSize,
  198. SrcAddr,
  199. DestAddr,
  200. Protocol
  201. );
  202. ON_EXIT:
  203. gBS->RestoreTPL (OldTpl);
  204. return Status;
  205. }