MnpIo.c 32 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115
  1. /** @file
  2. Implementation of Managed Network Protocol I/O functions.
  3. Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.<BR>
  4. SPDX-License-Identifier: BSD-2-Clause-Patent
  5. **/
  6. #include "MnpImpl.h"
  7. #include "MnpVlan.h"
  8. /**
  9. Validates the Mnp transmit token.
  10. @param[in] Instance Pointer to the Mnp instance context data.
  11. @param[in] Token Pointer to the transmit token to check.
  12. @return The Token is valid or not.
  13. **/
  14. BOOLEAN
  15. MnpIsValidTxToken (
  16. IN MNP_INSTANCE_DATA *Instance,
  17. IN EFI_MANAGED_NETWORK_COMPLETION_TOKEN *Token
  18. )
  19. {
  20. MNP_SERVICE_DATA *MnpServiceData;
  21. EFI_MANAGED_NETWORK_TRANSMIT_DATA *TxData;
  22. UINT32 Index;
  23. UINT32 TotalLength;
  24. EFI_MANAGED_NETWORK_FRAGMENT_DATA *FragmentTable;
  25. MnpServiceData = Instance->MnpServiceData;
  26. NET_CHECK_SIGNATURE (MnpServiceData, MNP_SERVICE_DATA_SIGNATURE);
  27. TxData = Token->Packet.TxData;
  28. if ((Token->Event == NULL) || (TxData == NULL) || (TxData->FragmentCount == 0)) {
  29. //
  30. // The token is invalid if the Event is NULL, or the TxData is NULL, or
  31. // the fragment count is zero.
  32. //
  33. DEBUG ((DEBUG_WARN, "MnpIsValidTxToken: Invalid Token.\n"));
  34. return FALSE;
  35. }
  36. if ((TxData->DestinationAddress != NULL) && (TxData->HeaderLength != 0)) {
  37. //
  38. // The token is invalid if the HeaderLength isn't zero while the DestinationAddress
  39. // is NULL (The destination address is already put into the packet).
  40. //
  41. DEBUG ((DEBUG_WARN, "MnpIsValidTxToken: DestinationAddress isn't NULL, HeaderLength must be 0.\n"));
  42. return FALSE;
  43. }
  44. TotalLength = 0;
  45. FragmentTable = TxData->FragmentTable;
  46. for (Index = 0; Index < TxData->FragmentCount; Index++) {
  47. if ((FragmentTable[Index].FragmentLength == 0) || (FragmentTable[Index].FragmentBuffer == NULL)) {
  48. //
  49. // The token is invalid if any FragmentLength is zero or any FragmentBuffer is NULL.
  50. //
  51. DEBUG ((DEBUG_WARN, "MnpIsValidTxToken: Invalid FragmentLength or FragmentBuffer.\n"));
  52. return FALSE;
  53. }
  54. TotalLength += FragmentTable[Index].FragmentLength;
  55. }
  56. if ((TxData->DestinationAddress == NULL) && (FragmentTable[0].FragmentLength < TxData->HeaderLength)) {
  57. //
  58. // Media header is split between fragments.
  59. //
  60. return FALSE;
  61. }
  62. if (TotalLength != (TxData->DataLength + TxData->HeaderLength)) {
  63. //
  64. // The length calculated from the fragment information doesn't equal to the
  65. // sum of the DataLength and the HeaderLength.
  66. //
  67. DEBUG ((DEBUG_WARN, "MnpIsValidTxData: Invalid Datalength compared with the sum of fragment length.\n"));
  68. return FALSE;
  69. }
  70. if (TxData->DataLength > MnpServiceData->Mtu) {
  71. //
  72. // The total length is larger than the MTU.
  73. //
  74. DEBUG ((DEBUG_WARN, "MnpIsValidTxData: TxData->DataLength exceeds Mtu.\n"));
  75. return FALSE;
  76. }
  77. return TRUE;
  78. }
  79. /**
  80. Build the packet to transmit from the TxData passed in.
  81. @param[in] MnpServiceData Pointer to the mnp service context data.
  82. @param[in] TxData Pointer to the transmit data containing the information
  83. to build the packet.
  84. @param[out] PktBuf Pointer to record the address of the packet.
  85. @param[out] PktLen Pointer to a UINT32 variable used to record the packet's
  86. length.
  87. @retval EFI_SUCCESS TxPackage is built.
  88. @retval EFI_OUT_OF_RESOURCES The deliver fails due to lack of memory resource.
  89. **/
  90. EFI_STATUS
  91. MnpBuildTxPacket (
  92. IN MNP_SERVICE_DATA *MnpServiceData,
  93. IN EFI_MANAGED_NETWORK_TRANSMIT_DATA *TxData,
  94. OUT UINT8 **PktBuf,
  95. OUT UINT32 *PktLen
  96. )
  97. {
  98. EFI_SIMPLE_NETWORK_MODE *SnpMode;
  99. UINT8 *DstPos;
  100. UINT16 Index;
  101. MNP_DEVICE_DATA *MnpDeviceData;
  102. UINT8 *TxBuf;
  103. MnpDeviceData = MnpServiceData->MnpDeviceData;
  104. TxBuf = MnpAllocTxBuf (MnpDeviceData);
  105. if (TxBuf == NULL) {
  106. return EFI_OUT_OF_RESOURCES;
  107. }
  108. //
  109. // Reserve space for vlan tag if needed.
  110. //
  111. if (MnpServiceData->VlanId != 0) {
  112. *PktBuf = TxBuf + NET_VLAN_TAG_LEN;
  113. } else {
  114. *PktBuf = TxBuf;
  115. }
  116. if ((TxData->DestinationAddress == NULL) && (TxData->FragmentCount == 1)) {
  117. CopyMem (
  118. *PktBuf,
  119. TxData->FragmentTable[0].FragmentBuffer,
  120. TxData->FragmentTable[0].FragmentLength
  121. );
  122. *PktLen = TxData->FragmentTable[0].FragmentLength;
  123. } else {
  124. //
  125. // Either media header isn't in FragmentTable or there is more than
  126. // one fragment, copy the data into the packet buffer. Reserve the
  127. // media header space if necessary.
  128. //
  129. SnpMode = MnpDeviceData->Snp->Mode;
  130. DstPos = *PktBuf;
  131. *PktLen = 0;
  132. if (TxData->DestinationAddress != NULL) {
  133. //
  134. // If dest address is not NULL, move DstPos to reserve space for the
  135. // media header. Add the media header length to buflen.
  136. //
  137. DstPos += SnpMode->MediaHeaderSize;
  138. *PktLen += SnpMode->MediaHeaderSize;
  139. }
  140. for (Index = 0; Index < TxData->FragmentCount; Index++) {
  141. //
  142. // Copy the data.
  143. //
  144. CopyMem (
  145. DstPos,
  146. TxData->FragmentTable[Index].FragmentBuffer,
  147. TxData->FragmentTable[Index].FragmentLength
  148. );
  149. DstPos += TxData->FragmentTable[Index].FragmentLength;
  150. }
  151. //
  152. // Set the buffer length.
  153. //
  154. *PktLen += TxData->DataLength + TxData->HeaderLength;
  155. }
  156. return EFI_SUCCESS;
  157. }
  158. /**
  159. Synchronously send out the packet.
  160. This function places the packet buffer to SNP driver's tansmit queue. The packet
  161. can be considered successfully sent out once SNP accept the packet, while the
  162. packet buffer recycle is deferred for better performance.
  163. @param[in] MnpServiceData Pointer to the mnp service context data.
  164. @param[in] Packet Pointer to the packet buffer.
  165. @param[in] Length The length of the packet.
  166. @param[in, out] Token Pointer to the token the packet generated from.
  167. @retval EFI_SUCCESS The packet is sent out.
  168. @retval EFI_TIMEOUT Time out occurs, the packet isn't sent.
  169. @retval EFI_DEVICE_ERROR An unexpected network error occurs.
  170. **/
  171. EFI_STATUS
  172. MnpSyncSendPacket (
  173. IN MNP_SERVICE_DATA *MnpServiceData,
  174. IN UINT8 *Packet,
  175. IN UINT32 Length,
  176. IN OUT EFI_MANAGED_NETWORK_COMPLETION_TOKEN *Token
  177. )
  178. {
  179. EFI_STATUS Status;
  180. EFI_SIMPLE_NETWORK_PROTOCOL *Snp;
  181. EFI_MANAGED_NETWORK_TRANSMIT_DATA *TxData;
  182. UINT32 HeaderSize;
  183. MNP_DEVICE_DATA *MnpDeviceData;
  184. UINT16 ProtocolType;
  185. MnpDeviceData = MnpServiceData->MnpDeviceData;
  186. Snp = MnpDeviceData->Snp;
  187. TxData = Token->Packet.TxData;
  188. Token->Status = EFI_SUCCESS;
  189. HeaderSize = Snp->Mode->MediaHeaderSize - TxData->HeaderLength;
  190. //
  191. // Check media status before transmit packet.
  192. // Note: media status will be updated by periodic timer MediaDetectTimer.
  193. //
  194. if (Snp->Mode->MediaPresentSupported && !Snp->Mode->MediaPresent) {
  195. //
  196. // Media not present, skip packet transmit and report EFI_NO_MEDIA
  197. //
  198. DEBUG ((DEBUG_WARN, "MnpSyncSendPacket: No network cable detected.\n"));
  199. Token->Status = EFI_NO_MEDIA;
  200. goto SIGNAL_TOKEN;
  201. }
  202. if (MnpServiceData->VlanId != 0) {
  203. //
  204. // Insert VLAN tag
  205. //
  206. MnpInsertVlanTag (MnpServiceData, TxData, &ProtocolType, &Packet, &Length);
  207. } else {
  208. ProtocolType = TxData->ProtocolType;
  209. }
  210. //
  211. // Transmit the packet through SNP.
  212. //
  213. Status = Snp->Transmit (
  214. Snp,
  215. HeaderSize,
  216. Length,
  217. Packet,
  218. TxData->SourceAddress,
  219. TxData->DestinationAddress,
  220. &ProtocolType
  221. );
  222. if (Status == EFI_NOT_READY) {
  223. Status = MnpRecycleTxBuf (MnpDeviceData);
  224. if (EFI_ERROR (Status)) {
  225. Token->Status = EFI_DEVICE_ERROR;
  226. goto SIGNAL_TOKEN;
  227. }
  228. Status = Snp->Transmit (
  229. Snp,
  230. HeaderSize,
  231. Length,
  232. Packet,
  233. TxData->SourceAddress,
  234. TxData->DestinationAddress,
  235. &ProtocolType
  236. );
  237. }
  238. if (EFI_ERROR (Status)) {
  239. Token->Status = EFI_DEVICE_ERROR;
  240. }
  241. SIGNAL_TOKEN:
  242. gBS->SignalEvent (Token->Event);
  243. //
  244. // Dispatch the DPC queued by the NotifyFunction of Token->Event.
  245. //
  246. DispatchDpc ();
  247. return EFI_SUCCESS;
  248. }
  249. /**
  250. Try to deliver the received packet to the instance.
  251. @param[in, out] Instance Pointer to the mnp instance context data.
  252. @retval EFI_SUCCESS The received packet is delivered, or there is no
  253. packet to deliver, or there is no available receive
  254. token.
  255. @retval EFI_OUT_OF_RESOURCES The deliver fails due to lack of memory resource.
  256. **/
  257. EFI_STATUS
  258. MnpInstanceDeliverPacket (
  259. IN OUT MNP_INSTANCE_DATA *Instance
  260. )
  261. {
  262. MNP_DEVICE_DATA *MnpDeviceData;
  263. MNP_RXDATA_WRAP *RxDataWrap;
  264. NET_BUF *DupNbuf;
  265. EFI_MANAGED_NETWORK_RECEIVE_DATA *RxData;
  266. EFI_SIMPLE_NETWORK_MODE *SnpMode;
  267. EFI_MANAGED_NETWORK_COMPLETION_TOKEN *RxToken;
  268. MnpDeviceData = Instance->MnpServiceData->MnpDeviceData;
  269. NET_CHECK_SIGNATURE (MnpDeviceData, MNP_DEVICE_DATA_SIGNATURE);
  270. if (NetMapIsEmpty (&Instance->RxTokenMap) || IsListEmpty (&Instance->RcvdPacketQueue)) {
  271. //
  272. // No pending received data or no available receive token, return.
  273. //
  274. return EFI_SUCCESS;
  275. }
  276. ASSERT (Instance->RcvdPacketQueueSize != 0);
  277. RxDataWrap = NET_LIST_HEAD (&Instance->RcvdPacketQueue, MNP_RXDATA_WRAP, WrapEntry);
  278. if (RxDataWrap->Nbuf->RefCnt > 2) {
  279. //
  280. // There are other instances share this Nbuf, duplicate to get a
  281. // copy to allow the instance to do R/W operations.
  282. //
  283. DupNbuf = MnpAllocNbuf (MnpDeviceData);
  284. if (DupNbuf == NULL) {
  285. DEBUG ((DEBUG_WARN, "MnpDeliverPacket: Failed to allocate a free Nbuf.\n"));
  286. return EFI_OUT_OF_RESOURCES;
  287. }
  288. //
  289. // Duplicate the net buffer.
  290. //
  291. NetbufDuplicate (RxDataWrap->Nbuf, DupNbuf, 0);
  292. MnpFreeNbuf (MnpDeviceData, RxDataWrap->Nbuf);
  293. RxDataWrap->Nbuf = DupNbuf;
  294. }
  295. //
  296. // All resources are OK, remove the packet from the queue.
  297. //
  298. NetListRemoveHead (&Instance->RcvdPacketQueue);
  299. Instance->RcvdPacketQueueSize--;
  300. RxData = &RxDataWrap->RxData;
  301. SnpMode = MnpDeviceData->Snp->Mode;
  302. //
  303. // Set all the buffer pointers.
  304. //
  305. RxData->MediaHeader = NetbufGetByte (RxDataWrap->Nbuf, 0, NULL);
  306. RxData->DestinationAddress = RxData->MediaHeader;
  307. RxData->SourceAddress = (UINT8 *)RxData->MediaHeader + SnpMode->HwAddressSize;
  308. RxData->PacketData = (UINT8 *)RxData->MediaHeader + SnpMode->MediaHeaderSize;
  309. //
  310. // Insert this RxDataWrap into the delivered queue.
  311. //
  312. InsertTailList (&Instance->RxDeliveredPacketQueue, &RxDataWrap->WrapEntry);
  313. //
  314. // Get the receive token from the RxTokenMap.
  315. //
  316. RxToken = NetMapRemoveHead (&Instance->RxTokenMap, NULL);
  317. //
  318. // Signal this token's event.
  319. //
  320. RxToken->Packet.RxData = &RxDataWrap->RxData;
  321. RxToken->Status = EFI_SUCCESS;
  322. gBS->SignalEvent (RxToken->Event);
  323. return EFI_SUCCESS;
  324. }
  325. /**
  326. Deliver the received packet for the instances belonging to the MnpServiceData.
  327. @param[in] MnpServiceData Pointer to the mnp service context data.
  328. **/
  329. VOID
  330. MnpDeliverPacket (
  331. IN MNP_SERVICE_DATA *MnpServiceData
  332. )
  333. {
  334. LIST_ENTRY *Entry;
  335. MNP_INSTANCE_DATA *Instance;
  336. NET_CHECK_SIGNATURE (MnpServiceData, MNP_SERVICE_DATA_SIGNATURE);
  337. NET_LIST_FOR_EACH (Entry, &MnpServiceData->ChildrenList) {
  338. Instance = NET_LIST_USER_STRUCT (Entry, MNP_INSTANCE_DATA, InstEntry);
  339. NET_CHECK_SIGNATURE (Instance, MNP_INSTANCE_DATA_SIGNATURE);
  340. //
  341. // Try to deliver packet for this instance.
  342. //
  343. MnpInstanceDeliverPacket (Instance);
  344. }
  345. }
  346. /**
  347. Recycle the RxData and other resources used to hold and deliver the received
  348. packet.
  349. @param[in] Event The event this notify function registered to.
  350. @param[in] Context Pointer to the context data registered to the Event.
  351. **/
  352. VOID
  353. EFIAPI
  354. MnpRecycleRxData (
  355. IN EFI_EVENT Event,
  356. IN VOID *Context
  357. )
  358. {
  359. MNP_RXDATA_WRAP *RxDataWrap;
  360. MNP_DEVICE_DATA *MnpDeviceData;
  361. ASSERT (Context != NULL);
  362. RxDataWrap = (MNP_RXDATA_WRAP *)Context;
  363. NET_CHECK_SIGNATURE (RxDataWrap->Instance, MNP_INSTANCE_DATA_SIGNATURE);
  364. ASSERT (RxDataWrap->Nbuf != NULL);
  365. MnpDeviceData = RxDataWrap->Instance->MnpServiceData->MnpDeviceData;
  366. NET_CHECK_SIGNATURE (MnpDeviceData, MNP_DEVICE_DATA_SIGNATURE);
  367. //
  368. // Free this Nbuf.
  369. //
  370. MnpFreeNbuf (MnpDeviceData, RxDataWrap->Nbuf);
  371. RxDataWrap->Nbuf = NULL;
  372. //
  373. // Close the recycle event.
  374. //
  375. gBS->CloseEvent (RxDataWrap->RxData.RecycleEvent);
  376. //
  377. // Remove this Wrap entry from the list.
  378. //
  379. RemoveEntryList (&RxDataWrap->WrapEntry);
  380. FreePool (RxDataWrap);
  381. }
  382. /**
  383. Queue the received packet into instance's receive queue.
  384. @param[in, out] Instance Pointer to the mnp instance context data.
  385. @param[in, out] RxDataWrap Pointer to the Wrap structure containing the
  386. received data and other information.
  387. **/
  388. VOID
  389. MnpQueueRcvdPacket (
  390. IN OUT MNP_INSTANCE_DATA *Instance,
  391. IN OUT MNP_RXDATA_WRAP *RxDataWrap
  392. )
  393. {
  394. MNP_RXDATA_WRAP *OldRxDataWrap;
  395. NET_CHECK_SIGNATURE (Instance, MNP_INSTANCE_DATA_SIGNATURE);
  396. //
  397. // Check the queue size. If it exceeds the limit, drop one packet
  398. // from the head.
  399. //
  400. if (Instance->RcvdPacketQueueSize == MNP_MAX_RCVD_PACKET_QUE_SIZE) {
  401. DEBUG ((DEBUG_WARN, "MnpQueueRcvdPacket: Drop one packet bcz queue size limit reached.\n"));
  402. //
  403. // Get the oldest packet.
  404. //
  405. OldRxDataWrap = NET_LIST_HEAD (
  406. &Instance->RcvdPacketQueue,
  407. MNP_RXDATA_WRAP,
  408. WrapEntry
  409. );
  410. //
  411. // Recycle this OldRxDataWrap, this entry will be removed by the callee.
  412. //
  413. MnpRecycleRxData (NULL, (VOID *)OldRxDataWrap);
  414. Instance->RcvdPacketQueueSize--;
  415. }
  416. //
  417. // Update the timeout tick using the configured parameter.
  418. //
  419. RxDataWrap->TimeoutTick = Instance->ConfigData.ReceivedQueueTimeoutValue;
  420. //
  421. // Insert this Wrap into the instance queue.
  422. //
  423. InsertTailList (&Instance->RcvdPacketQueue, &RxDataWrap->WrapEntry);
  424. Instance->RcvdPacketQueueSize++;
  425. }
  426. /**
  427. Match the received packet with the instance receive filters.
  428. @param[in] Instance Pointer to the mnp instance context data.
  429. @param[in] RxData Pointer to the EFI_MANAGED_NETWORK_RECEIVE_DATA.
  430. @param[in] GroupAddress Pointer to the GroupAddress, the GroupAddress is
  431. non-NULL and it contains the destination multicast
  432. mac address of the received packet if the packet
  433. destinated to a multicast mac address.
  434. @param[in] PktAttr The received packets attribute.
  435. @return The received packet matches the instance's receive filters or not.
  436. **/
  437. BOOLEAN
  438. MnpMatchPacket (
  439. IN MNP_INSTANCE_DATA *Instance,
  440. IN EFI_MANAGED_NETWORK_RECEIVE_DATA *RxData,
  441. IN MNP_GROUP_ADDRESS *GroupAddress OPTIONAL,
  442. IN UINT8 PktAttr
  443. )
  444. {
  445. EFI_MANAGED_NETWORK_CONFIG_DATA *ConfigData;
  446. LIST_ENTRY *Entry;
  447. MNP_GROUP_CONTROL_BLOCK *GroupCtrlBlk;
  448. NET_CHECK_SIGNATURE (Instance, MNP_INSTANCE_DATA_SIGNATURE);
  449. ConfigData = &Instance->ConfigData;
  450. //
  451. // Check the protocol type.
  452. //
  453. if ((ConfigData->ProtocolTypeFilter != 0) && (ConfigData->ProtocolTypeFilter != RxData->ProtocolType)) {
  454. return FALSE;
  455. }
  456. if (ConfigData->EnablePromiscuousReceive) {
  457. //
  458. // Always match if this instance is configured to be promiscuous.
  459. //
  460. return TRUE;
  461. }
  462. //
  463. // The protocol type is matched, check receive filter, include unicast and broadcast.
  464. //
  465. if ((Instance->ReceiveFilter & PktAttr) != 0) {
  466. return TRUE;
  467. }
  468. //
  469. // Check multicast addresses.
  470. //
  471. if (ConfigData->EnableMulticastReceive && RxData->MulticastFlag) {
  472. ASSERT (GroupAddress != NULL);
  473. NET_LIST_FOR_EACH (Entry, &Instance->GroupCtrlBlkList) {
  474. GroupCtrlBlk = NET_LIST_USER_STRUCT (Entry, MNP_GROUP_CONTROL_BLOCK, CtrlBlkEntry);
  475. if (GroupCtrlBlk->GroupAddress == GroupAddress) {
  476. //
  477. // The instance is configured to receiveing packets destinated to this
  478. // multicast address.
  479. //
  480. return TRUE;
  481. }
  482. }
  483. }
  484. //
  485. // No match.
  486. //
  487. return FALSE;
  488. }
  489. /**
  490. Analyse the received packets.
  491. @param[in] MnpServiceData Pointer to the mnp service context data.
  492. @param[in] Nbuf Pointer to the net buffer holding the received
  493. packet.
  494. @param[in, out] RxData Pointer to the buffer used to save the analysed
  495. result in EFI_MANAGED_NETWORK_RECEIVE_DATA.
  496. @param[out] GroupAddress Pointer to pointer to a MNP_GROUP_ADDRESS used to
  497. pass out the address of the multicast address the
  498. received packet destinated to.
  499. @param[out] PktAttr Pointer to the buffer used to save the analysed
  500. packet attribute.
  501. **/
  502. VOID
  503. MnpAnalysePacket (
  504. IN MNP_SERVICE_DATA *MnpServiceData,
  505. IN NET_BUF *Nbuf,
  506. IN OUT EFI_MANAGED_NETWORK_RECEIVE_DATA *RxData,
  507. OUT MNP_GROUP_ADDRESS **GroupAddress,
  508. OUT UINT8 *PktAttr
  509. )
  510. {
  511. EFI_SIMPLE_NETWORK_MODE *SnpMode;
  512. MNP_DEVICE_DATA *MnpDeviceData;
  513. UINT8 *BufPtr;
  514. LIST_ENTRY *Entry;
  515. MnpDeviceData = MnpServiceData->MnpDeviceData;
  516. SnpMode = MnpDeviceData->Snp->Mode;
  517. //
  518. // Get the packet buffer.
  519. //
  520. BufPtr = NetbufGetByte (Nbuf, 0, NULL);
  521. ASSERT (BufPtr != NULL);
  522. //
  523. // Set the initial values.
  524. //
  525. RxData->BroadcastFlag = FALSE;
  526. RxData->MulticastFlag = FALSE;
  527. RxData->PromiscuousFlag = FALSE;
  528. *PktAttr = UNICAST_PACKET;
  529. if (!NET_MAC_EQUAL (&SnpMode->CurrentAddress, BufPtr, SnpMode->HwAddressSize)) {
  530. //
  531. // This packet isn't destinated to our current mac address, it't not unicast.
  532. //
  533. *PktAttr = 0;
  534. if (NET_MAC_EQUAL (&SnpMode->BroadcastAddress, BufPtr, SnpMode->HwAddressSize)) {
  535. //
  536. // It's broadcast.
  537. //
  538. RxData->BroadcastFlag = TRUE;
  539. *PktAttr = BROADCAST_PACKET;
  540. } else if ((*BufPtr & 0x01) == 0x1) {
  541. //
  542. // It's multicast, try to match the multicast filters.
  543. //
  544. NET_LIST_FOR_EACH (Entry, &MnpDeviceData->GroupAddressList) {
  545. *GroupAddress = NET_LIST_USER_STRUCT (Entry, MNP_GROUP_ADDRESS, AddrEntry);
  546. if (NET_MAC_EQUAL (BufPtr, &((*GroupAddress)->Address), SnpMode->HwAddressSize)) {
  547. RxData->MulticastFlag = TRUE;
  548. break;
  549. }
  550. }
  551. if (!RxData->MulticastFlag) {
  552. //
  553. // No match, set GroupAddress to NULL. This multicast packet must
  554. // be the result of PROMISUCOUS or PROMISUCOUS_MULTICAST flag is on.
  555. //
  556. *GroupAddress = NULL;
  557. RxData->PromiscuousFlag = TRUE;
  558. if (MnpDeviceData->PromiscuousCount == 0) {
  559. //
  560. // Skip the below code, there is no receiver of this packet.
  561. //
  562. return;
  563. }
  564. }
  565. } else {
  566. RxData->PromiscuousFlag = TRUE;
  567. }
  568. }
  569. ZeroMem (&RxData->Timestamp, sizeof (EFI_TIME));
  570. //
  571. // Fill the common parts of RxData.
  572. //
  573. RxData->PacketLength = Nbuf->TotalSize;
  574. RxData->HeaderLength = SnpMode->MediaHeaderSize;
  575. RxData->AddressLength = SnpMode->HwAddressSize;
  576. RxData->DataLength = RxData->PacketLength - RxData->HeaderLength;
  577. RxData->ProtocolType = NTOHS (*(UINT16 *)(BufPtr + 2 * SnpMode->HwAddressSize));
  578. }
  579. /**
  580. Wrap the RxData.
  581. @param[in] Instance Pointer to the mnp instance context data.
  582. @param[in] RxData Pointer to the receive data to wrap.
  583. @return Pointer to a MNP_RXDATA_WRAP which wraps the RxData.
  584. **/
  585. MNP_RXDATA_WRAP *
  586. MnpWrapRxData (
  587. IN MNP_INSTANCE_DATA *Instance,
  588. IN EFI_MANAGED_NETWORK_RECEIVE_DATA *RxData
  589. )
  590. {
  591. EFI_STATUS Status;
  592. MNP_RXDATA_WRAP *RxDataWrap;
  593. //
  594. // Allocate memory.
  595. //
  596. RxDataWrap = AllocatePool (sizeof (MNP_RXDATA_WRAP));
  597. if (RxDataWrap == NULL) {
  598. DEBUG ((DEBUG_ERROR, "MnpDispatchPacket: Failed to allocate a MNP_RXDATA_WRAP.\n"));
  599. return NULL;
  600. }
  601. RxDataWrap->Instance = Instance;
  602. //
  603. // Fill the RxData in RxDataWrap,
  604. //
  605. CopyMem (&RxDataWrap->RxData, RxData, sizeof (RxDataWrap->RxData));
  606. //
  607. // Create the recycle event.
  608. //
  609. Status = gBS->CreateEvent (
  610. EVT_NOTIFY_SIGNAL,
  611. TPL_NOTIFY,
  612. MnpRecycleRxData,
  613. RxDataWrap,
  614. &RxDataWrap->RxData.RecycleEvent
  615. );
  616. if (EFI_ERROR (Status)) {
  617. DEBUG ((DEBUG_ERROR, "MnpDispatchPacket: gBS->CreateEvent failed, %r.\n", Status));
  618. FreePool (RxDataWrap);
  619. return NULL;
  620. }
  621. return RxDataWrap;
  622. }
  623. /**
  624. Enqueue the received the packets to the instances belonging to the
  625. MnpServiceData.
  626. @param[in] MnpServiceData Pointer to the mnp service context data.
  627. @param[in] Nbuf Pointer to the net buffer representing the received
  628. packet.
  629. **/
  630. VOID
  631. MnpEnqueuePacket (
  632. IN MNP_SERVICE_DATA *MnpServiceData,
  633. IN NET_BUF *Nbuf
  634. )
  635. {
  636. LIST_ENTRY *Entry;
  637. MNP_INSTANCE_DATA *Instance;
  638. EFI_MANAGED_NETWORK_RECEIVE_DATA RxData;
  639. UINT8 PktAttr;
  640. MNP_GROUP_ADDRESS *GroupAddress;
  641. MNP_RXDATA_WRAP *RxDataWrap;
  642. GroupAddress = NULL;
  643. //
  644. // First, analyse the packet header.
  645. //
  646. MnpAnalysePacket (MnpServiceData, Nbuf, &RxData, &GroupAddress, &PktAttr);
  647. if (RxData.PromiscuousFlag && (MnpServiceData->MnpDeviceData->PromiscuousCount == 0)) {
  648. //
  649. // No receivers, no more action need.
  650. //
  651. return;
  652. }
  653. //
  654. // Iterate the children to find match.
  655. //
  656. NET_LIST_FOR_EACH (Entry, &MnpServiceData->ChildrenList) {
  657. Instance = NET_LIST_USER_STRUCT (Entry, MNP_INSTANCE_DATA, InstEntry);
  658. NET_CHECK_SIGNATURE (Instance, MNP_INSTANCE_DATA_SIGNATURE);
  659. if (!Instance->Configured) {
  660. continue;
  661. }
  662. //
  663. // Check the packet against the instance receive filters.
  664. //
  665. if (MnpMatchPacket (Instance, &RxData, GroupAddress, PktAttr)) {
  666. //
  667. // Wrap the RxData.
  668. //
  669. RxDataWrap = MnpWrapRxData (Instance, &RxData);
  670. if (RxDataWrap == NULL) {
  671. continue;
  672. }
  673. //
  674. // Associate RxDataWrap with Nbuf and increase the RefCnt.
  675. //
  676. RxDataWrap->Nbuf = Nbuf;
  677. NET_GET_REF (RxDataWrap->Nbuf);
  678. //
  679. // Queue the packet into the instance queue.
  680. //
  681. MnpQueueRcvdPacket (Instance, RxDataWrap);
  682. }
  683. }
  684. }
  685. /**
  686. Try to receive a packet and deliver it.
  687. @param[in, out] MnpDeviceData Pointer to the mnp device context data.
  688. @retval EFI_SUCCESS add return value to function comment
  689. @retval EFI_NOT_STARTED The simple network protocol is not started.
  690. @retval EFI_NOT_READY No packet received.
  691. @retval EFI_DEVICE_ERROR An unexpected error occurs.
  692. **/
  693. EFI_STATUS
  694. MnpReceivePacket (
  695. IN OUT MNP_DEVICE_DATA *MnpDeviceData
  696. )
  697. {
  698. EFI_STATUS Status;
  699. EFI_SIMPLE_NETWORK_PROTOCOL *Snp;
  700. NET_BUF *Nbuf;
  701. UINT8 *BufPtr;
  702. UINTN BufLen;
  703. UINTN HeaderSize;
  704. UINT32 Trimmed;
  705. MNP_SERVICE_DATA *MnpServiceData;
  706. UINT16 VlanId;
  707. BOOLEAN IsVlanPacket;
  708. NET_CHECK_SIGNATURE (MnpDeviceData, MNP_DEVICE_DATA_SIGNATURE);
  709. Snp = MnpDeviceData->Snp;
  710. if (Snp->Mode->State != EfiSimpleNetworkInitialized) {
  711. //
  712. // The simple network protocol is not started.
  713. //
  714. return EFI_NOT_STARTED;
  715. }
  716. if (MnpDeviceData->RxNbufCache == NULL) {
  717. //
  718. // Try to get a new buffer as there may be buffers recycled.
  719. //
  720. MnpDeviceData->RxNbufCache = MnpAllocNbuf (MnpDeviceData);
  721. if (MnpDeviceData->RxNbufCache == NULL) {
  722. //
  723. // No available buffer in the buffer pool.
  724. //
  725. return EFI_DEVICE_ERROR;
  726. }
  727. NetbufAllocSpace (
  728. MnpDeviceData->RxNbufCache,
  729. MnpDeviceData->BufferLength,
  730. NET_BUF_TAIL
  731. );
  732. }
  733. Nbuf = MnpDeviceData->RxNbufCache;
  734. BufLen = Nbuf->TotalSize;
  735. BufPtr = NetbufGetByte (Nbuf, 0, NULL);
  736. ASSERT (BufPtr != NULL);
  737. //
  738. // Receive packet through Snp.
  739. //
  740. Status = Snp->Receive (Snp, &HeaderSize, &BufLen, BufPtr, NULL, NULL, NULL);
  741. if (EFI_ERROR (Status)) {
  742. DEBUG_CODE_BEGIN ();
  743. if (Status != EFI_NOT_READY) {
  744. DEBUG ((DEBUG_WARN, "MnpReceivePacket: Snp->Receive() = %r.\n", Status));
  745. }
  746. DEBUG_CODE_END ();
  747. return Status;
  748. }
  749. //
  750. // Sanity check.
  751. //
  752. if ((HeaderSize != Snp->Mode->MediaHeaderSize) || (BufLen < HeaderSize)) {
  753. DEBUG (
  754. (DEBUG_WARN,
  755. "MnpReceivePacket: Size error, HL:TL = %d:%d.\n",
  756. HeaderSize,
  757. BufLen)
  758. );
  759. return EFI_DEVICE_ERROR;
  760. }
  761. Trimmed = 0;
  762. if (Nbuf->TotalSize != BufLen) {
  763. //
  764. // Trim the packet from tail.
  765. //
  766. Trimmed = NetbufTrim (Nbuf, Nbuf->TotalSize - (UINT32)BufLen, NET_BUF_TAIL);
  767. ASSERT (Nbuf->TotalSize == BufLen);
  768. }
  769. VlanId = 0;
  770. if (MnpDeviceData->NumberOfVlan != 0) {
  771. //
  772. // VLAN is configured, remove the VLAN tag if any
  773. //
  774. IsVlanPacket = MnpRemoveVlanTag (MnpDeviceData, Nbuf, &VlanId);
  775. } else {
  776. IsVlanPacket = FALSE;
  777. }
  778. MnpServiceData = MnpFindServiceData (MnpDeviceData, VlanId);
  779. if (MnpServiceData == NULL) {
  780. //
  781. // VLAN is not set for this tagged frame, ignore this packet
  782. //
  783. if (Trimmed > 0) {
  784. NetbufAllocSpace (Nbuf, Trimmed, NET_BUF_TAIL);
  785. }
  786. if (IsVlanPacket) {
  787. NetbufAllocSpace (Nbuf, NET_VLAN_TAG_LEN, NET_BUF_HEAD);
  788. }
  789. goto EXIT;
  790. }
  791. //
  792. // Enqueue the packet to the matched instances.
  793. //
  794. MnpEnqueuePacket (MnpServiceData, Nbuf);
  795. if (Nbuf->RefCnt > 2) {
  796. //
  797. // RefCnt > 2 indicates there is at least one receiver of this packet.
  798. // Free the current RxNbufCache and allocate a new one.
  799. //
  800. MnpFreeNbuf (MnpDeviceData, Nbuf);
  801. Nbuf = MnpAllocNbuf (MnpDeviceData);
  802. MnpDeviceData->RxNbufCache = Nbuf;
  803. if (Nbuf == NULL) {
  804. DEBUG ((DEBUG_ERROR, "MnpReceivePacket: Alloc packet for receiving cache failed.\n"));
  805. return EFI_DEVICE_ERROR;
  806. }
  807. NetbufAllocSpace (Nbuf, MnpDeviceData->BufferLength, NET_BUF_TAIL);
  808. } else {
  809. //
  810. // No receiver for this packet.
  811. //
  812. if (Trimmed > 0) {
  813. NetbufAllocSpace (Nbuf, Trimmed, NET_BUF_TAIL);
  814. }
  815. if (IsVlanPacket) {
  816. NetbufAllocSpace (Nbuf, NET_VLAN_TAG_LEN, NET_BUF_HEAD);
  817. }
  818. goto EXIT;
  819. }
  820. //
  821. // Deliver the queued packets.
  822. //
  823. MnpDeliverPacket (MnpServiceData);
  824. EXIT:
  825. ASSERT (Nbuf->TotalSize == MnpDeviceData->BufferLength);
  826. return Status;
  827. }
  828. /**
  829. Remove the received packets if timeout occurs.
  830. @param[in] Event The event this notify function registered to.
  831. @param[in] Context Pointer to the context data registered to the event.
  832. **/
  833. VOID
  834. EFIAPI
  835. MnpCheckPacketTimeout (
  836. IN EFI_EVENT Event,
  837. IN VOID *Context
  838. )
  839. {
  840. MNP_DEVICE_DATA *MnpDeviceData;
  841. MNP_SERVICE_DATA *MnpServiceData;
  842. LIST_ENTRY *Entry;
  843. LIST_ENTRY *ServiceEntry;
  844. LIST_ENTRY *RxEntry;
  845. LIST_ENTRY *NextEntry;
  846. MNP_INSTANCE_DATA *Instance;
  847. MNP_RXDATA_WRAP *RxDataWrap;
  848. EFI_TPL OldTpl;
  849. MnpDeviceData = (MNP_DEVICE_DATA *)Context;
  850. NET_CHECK_SIGNATURE (MnpDeviceData, MNP_DEVICE_DATA_SIGNATURE);
  851. NET_LIST_FOR_EACH (ServiceEntry, &MnpDeviceData->ServiceList) {
  852. MnpServiceData = MNP_SERVICE_DATA_FROM_LINK (ServiceEntry);
  853. NET_LIST_FOR_EACH (Entry, &MnpServiceData->ChildrenList) {
  854. Instance = NET_LIST_USER_STRUCT (Entry, MNP_INSTANCE_DATA, InstEntry);
  855. NET_CHECK_SIGNATURE (Instance, MNP_INSTANCE_DATA_SIGNATURE);
  856. if (!Instance->Configured || (Instance->ConfigData.ReceivedQueueTimeoutValue == 0)) {
  857. //
  858. // This instance is not configured or there is no receive time out,
  859. // just skip to the next instance.
  860. //
  861. continue;
  862. }
  863. OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
  864. NET_LIST_FOR_EACH_SAFE (RxEntry, NextEntry, &Instance->RcvdPacketQueue) {
  865. RxDataWrap = NET_LIST_USER_STRUCT (RxEntry, MNP_RXDATA_WRAP, WrapEntry);
  866. //
  867. // TimeoutTick unit is microsecond, MNP_TIMEOUT_CHECK_INTERVAL unit is 100ns.
  868. //
  869. if (RxDataWrap->TimeoutTick >= (MNP_TIMEOUT_CHECK_INTERVAL / 10)) {
  870. RxDataWrap->TimeoutTick -= (MNP_TIMEOUT_CHECK_INTERVAL / 10);
  871. } else {
  872. //
  873. // Drop the timeout packet.
  874. //
  875. DEBUG ((DEBUG_WARN, "MnpCheckPacketTimeout: Received packet timeout.\n"));
  876. MnpRecycleRxData (NULL, RxDataWrap);
  877. Instance->RcvdPacketQueueSize--;
  878. }
  879. }
  880. gBS->RestoreTPL (OldTpl);
  881. }
  882. }
  883. }
  884. /**
  885. Poll to update MediaPresent field in SNP ModeData by Snp->GetStatus().
  886. @param[in] Event The event this notify function registered to.
  887. @param[in] Context Pointer to the context data registered to the event.
  888. **/
  889. VOID
  890. EFIAPI
  891. MnpCheckMediaStatus (
  892. IN EFI_EVENT Event,
  893. IN VOID *Context
  894. )
  895. {
  896. MNP_DEVICE_DATA *MnpDeviceData;
  897. EFI_SIMPLE_NETWORK_PROTOCOL *Snp;
  898. UINT32 InterruptStatus;
  899. MnpDeviceData = (MNP_DEVICE_DATA *)Context;
  900. NET_CHECK_SIGNATURE (MnpDeviceData, MNP_DEVICE_DATA_SIGNATURE);
  901. Snp = MnpDeviceData->Snp;
  902. if (Snp->Mode->MediaPresentSupported) {
  903. //
  904. // Upon successful return of GetStatus(), the MediaPresent field of
  905. // EFI_SIMPLE_NETWORK_MODE will be updated to reflect any change of media status
  906. //
  907. Snp->GetStatus (Snp, &InterruptStatus, NULL);
  908. }
  909. }
  910. /**
  911. Poll to receive the packets from Snp. This function is either called by upperlayer
  912. protocols/applications or the system poll timer notify mechanism.
  913. @param[in] Event The event this notify function registered to.
  914. @param[in] Context Pointer to the context data registered to the event.
  915. **/
  916. VOID
  917. EFIAPI
  918. MnpSystemPoll (
  919. IN EFI_EVENT Event,
  920. IN VOID *Context
  921. )
  922. {
  923. MNP_DEVICE_DATA *MnpDeviceData;
  924. MnpDeviceData = (MNP_DEVICE_DATA *)Context;
  925. NET_CHECK_SIGNATURE (MnpDeviceData, MNP_DEVICE_DATA_SIGNATURE);
  926. //
  927. // Try to receive packets from Snp.
  928. //
  929. MnpReceivePacket (MnpDeviceData);
  930. //
  931. // Dispatch the DPC queued by the NotifyFunction of rx token's events.
  932. //
  933. DispatchDpc ();
  934. }