TcpDriver.c 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990
  1. /** @file
  2. The driver binding and service binding protocol for the TCP driver.
  3. Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>
  4. SPDX-License-Identifier: BSD-2-Clause-Patent
  5. **/
  6. #include "TcpMain.h"
  7. UINT16 mTcp4RandomPort;
  8. UINT16 mTcp6RandomPort;
  9. TCP_HEARTBEAT_TIMER mTcpTimer = {
  10. NULL,
  11. 0
  12. };
  13. EFI_TCP4_PROTOCOL gTcp4ProtocolTemplate = {
  14. Tcp4GetModeData,
  15. Tcp4Configure,
  16. Tcp4Routes,
  17. Tcp4Connect,
  18. Tcp4Accept,
  19. Tcp4Transmit,
  20. Tcp4Receive,
  21. Tcp4Close,
  22. Tcp4Cancel,
  23. Tcp4Poll
  24. };
  25. EFI_TCP6_PROTOCOL gTcp6ProtocolTemplate = {
  26. Tcp6GetModeData,
  27. Tcp6Configure,
  28. Tcp6Connect,
  29. Tcp6Accept,
  30. Tcp6Transmit,
  31. Tcp6Receive,
  32. Tcp6Close,
  33. Tcp6Cancel,
  34. Tcp6Poll
  35. };
  36. SOCK_INIT_DATA mTcpDefaultSockData = {
  37. SockStream,
  38. SO_CLOSED,
  39. NULL,
  40. TCP_BACKLOG,
  41. TCP_SND_BUF_SIZE,
  42. TCP_RCV_BUF_SIZE,
  43. IP_VERSION_4,
  44. NULL,
  45. TcpCreateSocketCallback,
  46. TcpDestroySocketCallback,
  47. NULL,
  48. NULL,
  49. 0,
  50. TcpDispatcher,
  51. NULL,
  52. };
  53. EFI_DRIVER_BINDING_PROTOCOL gTcp4DriverBinding = {
  54. Tcp4DriverBindingSupported,
  55. Tcp4DriverBindingStart,
  56. Tcp4DriverBindingStop,
  57. 0xa,
  58. NULL,
  59. NULL
  60. };
  61. EFI_DRIVER_BINDING_PROTOCOL gTcp6DriverBinding = {
  62. Tcp6DriverBindingSupported,
  63. Tcp6DriverBindingStart,
  64. Tcp6DriverBindingStop,
  65. 0xa,
  66. NULL,
  67. NULL
  68. };
  69. EFI_SERVICE_BINDING_PROTOCOL gTcpServiceBinding = {
  70. TcpServiceBindingCreateChild,
  71. TcpServiceBindingDestroyChild
  72. };
  73. /**
  74. Create and start the heartbeat timer for the TCP driver.
  75. @retval EFI_SUCCESS The timer was successfully created and started.
  76. @retval other The timer was not created.
  77. **/
  78. EFI_STATUS
  79. TcpCreateTimer (
  80. VOID
  81. )
  82. {
  83. EFI_STATUS Status;
  84. Status = EFI_SUCCESS;
  85. if (mTcpTimer.RefCnt == 0) {
  86. Status = gBS->CreateEvent (
  87. EVT_TIMER | EVT_NOTIFY_SIGNAL,
  88. TPL_NOTIFY,
  89. TcpTicking,
  90. NULL,
  91. &mTcpTimer.TimerEvent
  92. );
  93. if (!EFI_ERROR (Status)) {
  94. Status = gBS->SetTimer (
  95. mTcpTimer.TimerEvent,
  96. TimerPeriodic,
  97. (UINT64)(TICKS_PER_SECOND / TCP_TICK_HZ)
  98. );
  99. }
  100. }
  101. if (!EFI_ERROR (Status)) {
  102. mTcpTimer.RefCnt++;
  103. }
  104. return Status;
  105. }
  106. /**
  107. Stop and destroy the heartbeat timer for TCP driver.
  108. **/
  109. VOID
  110. TcpDestroyTimer (
  111. VOID
  112. )
  113. {
  114. ASSERT (mTcpTimer.RefCnt > 0);
  115. mTcpTimer.RefCnt--;
  116. if (mTcpTimer.RefCnt > 0) {
  117. return;
  118. }
  119. gBS->SetTimer (mTcpTimer.TimerEvent, TimerCancel, 0);
  120. gBS->CloseEvent (mTcpTimer.TimerEvent);
  121. mTcpTimer.TimerEvent = NULL;
  122. }
  123. /**
  124. The entry point for Tcp driver, which is used to install Tcp driver on the ImageHandle.
  125. @param[in] ImageHandle The firmware allocated handle for this driver image.
  126. @param[in] SystemTable Pointer to the EFI system table.
  127. @retval EFI_SUCCESS The driver loaded.
  128. @retval other The driver did not load.
  129. **/
  130. EFI_STATUS
  131. EFIAPI
  132. TcpDriverEntryPoint (
  133. IN EFI_HANDLE ImageHandle,
  134. IN EFI_SYSTEM_TABLE *SystemTable
  135. )
  136. {
  137. EFI_STATUS Status;
  138. UINT32 Seed;
  139. //
  140. // Install the TCP Driver Binding Protocol
  141. //
  142. Status = EfiLibInstallDriverBindingComponentName2 (
  143. ImageHandle,
  144. SystemTable,
  145. &gTcp4DriverBinding,
  146. ImageHandle,
  147. &gTcpComponentName,
  148. &gTcpComponentName2
  149. );
  150. if (EFI_ERROR (Status)) {
  151. return Status;
  152. }
  153. //
  154. // Install the TCP Driver Binding Protocol
  155. //
  156. Status = EfiLibInstallDriverBindingComponentName2 (
  157. ImageHandle,
  158. SystemTable,
  159. &gTcp6DriverBinding,
  160. NULL,
  161. &gTcpComponentName,
  162. &gTcpComponentName2
  163. );
  164. if (EFI_ERROR (Status)) {
  165. EfiLibUninstallDriverBindingComponentName2 (
  166. &gTcp4DriverBinding,
  167. &gTcpComponentName,
  168. &gTcpComponentName2
  169. );
  170. return Status;
  171. }
  172. //
  173. // Initialize ISS and random port.
  174. //
  175. Seed = NetRandomInitSeed ();
  176. mTcpGlobalIss = NET_RANDOM (Seed) % mTcpGlobalIss;
  177. mTcp4RandomPort = (UINT16)(TCP_PORT_KNOWN + (NET_RANDOM (Seed) % TCP_PORT_KNOWN));
  178. mTcp6RandomPort = mTcp4RandomPort;
  179. return EFI_SUCCESS;
  180. }
  181. /**
  182. Create a new TCP4 or TCP6 driver service binding protocol
  183. @param[in] Controller Controller handle of device to bind driver to.
  184. @param[in] Image The TCP driver's image handle.
  185. @param[in] IpVersion IP_VERSION_4 or IP_VERSION_6.
  186. @retval EFI_OUT_OF_RESOURCES Failed to allocate some resources.
  187. @retval EFI_SUCCESS A new IP6 service binding private was created.
  188. **/
  189. EFI_STATUS
  190. TcpCreateService (
  191. IN EFI_HANDLE Controller,
  192. IN EFI_HANDLE Image,
  193. IN UINT8 IpVersion
  194. )
  195. {
  196. EFI_STATUS Status;
  197. EFI_GUID *IpServiceBindingGuid;
  198. EFI_GUID *TcpServiceBindingGuid;
  199. TCP_SERVICE_DATA *TcpServiceData;
  200. IP_IO_OPEN_DATA OpenData;
  201. if (IpVersion == IP_VERSION_4) {
  202. IpServiceBindingGuid = &gEfiIp4ServiceBindingProtocolGuid;
  203. TcpServiceBindingGuid = &gEfiTcp4ServiceBindingProtocolGuid;
  204. } else {
  205. IpServiceBindingGuid = &gEfiIp6ServiceBindingProtocolGuid;
  206. TcpServiceBindingGuid = &gEfiTcp6ServiceBindingProtocolGuid;
  207. }
  208. Status = gBS->OpenProtocol (
  209. Controller,
  210. TcpServiceBindingGuid,
  211. NULL,
  212. Image,
  213. Controller,
  214. EFI_OPEN_PROTOCOL_TEST_PROTOCOL
  215. );
  216. if (!EFI_ERROR (Status)) {
  217. return EFI_ALREADY_STARTED;
  218. }
  219. Status = gBS->OpenProtocol (
  220. Controller,
  221. IpServiceBindingGuid,
  222. NULL,
  223. Image,
  224. Controller,
  225. EFI_OPEN_PROTOCOL_TEST_PROTOCOL
  226. );
  227. if (EFI_ERROR (Status)) {
  228. return EFI_UNSUPPORTED;
  229. }
  230. //
  231. // Create the TCP service data.
  232. //
  233. TcpServiceData = AllocateZeroPool (sizeof (TCP_SERVICE_DATA));
  234. if (TcpServiceData == NULL) {
  235. return EFI_OUT_OF_RESOURCES;
  236. }
  237. TcpServiceData->Signature = TCP_DRIVER_SIGNATURE;
  238. TcpServiceData->ControllerHandle = Controller;
  239. TcpServiceData->DriverBindingHandle = Image;
  240. TcpServiceData->IpVersion = IpVersion;
  241. CopyMem (
  242. &TcpServiceData->ServiceBinding,
  243. &gTcpServiceBinding,
  244. sizeof (EFI_SERVICE_BINDING_PROTOCOL)
  245. );
  246. TcpServiceData->IpIo = IpIoCreate (Image, Controller, IpVersion);
  247. if (TcpServiceData->IpIo == NULL) {
  248. Status = EFI_OUT_OF_RESOURCES;
  249. goto ON_ERROR;
  250. }
  251. InitializeListHead (&TcpServiceData->SocketList);
  252. ZeroMem (&OpenData, sizeof (IP_IO_OPEN_DATA));
  253. if (IpVersion == IP_VERSION_4) {
  254. CopyMem (
  255. &OpenData.IpConfigData.Ip4CfgData,
  256. &mIp4IoDefaultIpConfigData,
  257. sizeof (EFI_IP4_CONFIG_DATA)
  258. );
  259. OpenData.IpConfigData.Ip4CfgData.DefaultProtocol = EFI_IP_PROTO_TCP;
  260. } else {
  261. CopyMem (
  262. &OpenData.IpConfigData.Ip6CfgData,
  263. &mIp6IoDefaultIpConfigData,
  264. sizeof (EFI_IP6_CONFIG_DATA)
  265. );
  266. OpenData.IpConfigData.Ip6CfgData.DefaultProtocol = EFI_IP_PROTO_TCP;
  267. }
  268. OpenData.PktRcvdNotify = TcpRxCallback;
  269. Status = IpIoOpen (TcpServiceData->IpIo, &OpenData);
  270. if (EFI_ERROR (Status)) {
  271. goto ON_ERROR;
  272. }
  273. Status = TcpCreateTimer ();
  274. if (EFI_ERROR (Status)) {
  275. goto ON_ERROR;
  276. }
  277. Status = gBS->InstallMultipleProtocolInterfaces (
  278. &Controller,
  279. TcpServiceBindingGuid,
  280. &TcpServiceData->ServiceBinding,
  281. NULL
  282. );
  283. if (EFI_ERROR (Status)) {
  284. TcpDestroyTimer ();
  285. goto ON_ERROR;
  286. }
  287. return EFI_SUCCESS;
  288. ON_ERROR:
  289. if (TcpServiceData->IpIo != NULL) {
  290. IpIoDestroy (TcpServiceData->IpIo);
  291. TcpServiceData->IpIo = NULL;
  292. }
  293. FreePool (TcpServiceData);
  294. return Status;
  295. }
  296. /**
  297. Callback function which provided by user to remove one node in NetDestroyLinkList process.
  298. @param[in] Entry The entry to be removed.
  299. @param[in] Context Pointer to the callback context corresponds to the Context in NetDestroyLinkList.
  300. @retval EFI_SUCCESS The entry has been removed successfully.
  301. @retval Others Fail to remove the entry.
  302. **/
  303. EFI_STATUS
  304. EFIAPI
  305. TcpDestroyChildEntryInHandleBuffer (
  306. IN LIST_ENTRY *Entry,
  307. IN VOID *Context
  308. )
  309. {
  310. SOCKET *Sock;
  311. EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;
  312. UINTN NumberOfChildren;
  313. EFI_HANDLE *ChildHandleBuffer;
  314. if ((Entry == NULL) || (Context == NULL)) {
  315. return EFI_INVALID_PARAMETER;
  316. }
  317. Sock = NET_LIST_USER_STRUCT_S (Entry, SOCKET, Link, SOCK_SIGNATURE);
  318. ServiceBinding = ((TCP_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT *)Context)->ServiceBinding;
  319. NumberOfChildren = ((TCP_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT *)Context)->NumberOfChildren;
  320. ChildHandleBuffer = ((TCP_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT *)Context)->ChildHandleBuffer;
  321. if (!NetIsInHandleBuffer (Sock->SockHandle, NumberOfChildren, ChildHandleBuffer)) {
  322. return EFI_SUCCESS;
  323. }
  324. return ServiceBinding->DestroyChild (ServiceBinding, Sock->SockHandle);
  325. }
  326. /**
  327. Destroy a TCP6 or TCP4 service binding instance. It will release all
  328. the resources allocated by the instance.
  329. @param[in] Controller Controller handle of device to bind driver to.
  330. @param[in] ImageHandle The TCP driver's image handle.
  331. @param[in] NumberOfChildren Number of Handles in ChildHandleBuffer. If number
  332. of children is zero stop the entire bus driver.
  333. @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL
  334. if NumberOfChildren is 0.
  335. @param[in] IpVersion IP_VERSION_4 or IP_VERSION_6
  336. @retval EFI_SUCCESS The resources used by the instance were cleaned up.
  337. @retval Others Failed to clean up some of the resources.
  338. **/
  339. EFI_STATUS
  340. TcpDestroyService (
  341. IN EFI_HANDLE Controller,
  342. IN EFI_HANDLE ImageHandle,
  343. IN UINTN NumberOfChildren,
  344. IN EFI_HANDLE *ChildHandleBuffer OPTIONAL,
  345. IN UINT8 IpVersion
  346. )
  347. {
  348. EFI_HANDLE NicHandle;
  349. EFI_GUID *IpProtocolGuid;
  350. EFI_GUID *ServiceBindingGuid;
  351. EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;
  352. TCP_SERVICE_DATA *TcpServiceData;
  353. EFI_STATUS Status;
  354. LIST_ENTRY *List;
  355. TCP_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT Context;
  356. ASSERT ((IpVersion == IP_VERSION_4) || (IpVersion == IP_VERSION_6));
  357. if (IpVersion == IP_VERSION_4) {
  358. IpProtocolGuid = &gEfiIp4ProtocolGuid;
  359. ServiceBindingGuid = &gEfiTcp4ServiceBindingProtocolGuid;
  360. } else {
  361. IpProtocolGuid = &gEfiIp6ProtocolGuid;
  362. ServiceBindingGuid = &gEfiTcp6ServiceBindingProtocolGuid;
  363. }
  364. NicHandle = NetLibGetNicHandle (Controller, IpProtocolGuid);
  365. if (NicHandle == NULL) {
  366. return EFI_SUCCESS;
  367. }
  368. Status = gBS->OpenProtocol (
  369. NicHandle,
  370. ServiceBindingGuid,
  371. (VOID **)&ServiceBinding,
  372. ImageHandle,
  373. Controller,
  374. EFI_OPEN_PROTOCOL_GET_PROTOCOL
  375. );
  376. if (EFI_ERROR (Status)) {
  377. return EFI_DEVICE_ERROR;
  378. }
  379. TcpServiceData = TCP_SERVICE_FROM_THIS (ServiceBinding);
  380. if (NumberOfChildren != 0) {
  381. List = &TcpServiceData->SocketList;
  382. Context.ServiceBinding = ServiceBinding;
  383. Context.NumberOfChildren = NumberOfChildren;
  384. Context.ChildHandleBuffer = ChildHandleBuffer;
  385. Status = NetDestroyLinkList (
  386. List,
  387. TcpDestroyChildEntryInHandleBuffer,
  388. &Context,
  389. NULL
  390. );
  391. } else if (IsListEmpty (&TcpServiceData->SocketList)) {
  392. //
  393. // Uninstall TCP servicebinding protocol
  394. //
  395. gBS->UninstallMultipleProtocolInterfaces (
  396. NicHandle,
  397. ServiceBindingGuid,
  398. ServiceBinding,
  399. NULL
  400. );
  401. //
  402. // Destroy the IpIO consumed by TCP driver
  403. //
  404. IpIoDestroy (TcpServiceData->IpIo);
  405. TcpServiceData->IpIo = NULL;
  406. //
  407. // Destroy the heartbeat timer.
  408. //
  409. TcpDestroyTimer ();
  410. //
  411. // Release the TCP service data
  412. //
  413. FreePool (TcpServiceData);
  414. Status = EFI_SUCCESS;
  415. }
  416. return Status;
  417. }
  418. /**
  419. Test to see if this driver supports ControllerHandle.
  420. @param[in] This Protocol instance pointer.
  421. @param[in] ControllerHandle Handle of device to test.
  422. @param[in] RemainingDevicePath Optional parameter use to pick a specific
  423. child device to start.
  424. @retval EFI_SUCCESS This driver supports this device.
  425. @retval EFI_ALREADY_STARTED This driver is already running on this device.
  426. @retval other This driver does not support this device.
  427. **/
  428. EFI_STATUS
  429. EFIAPI
  430. Tcp4DriverBindingSupported (
  431. IN EFI_DRIVER_BINDING_PROTOCOL *This,
  432. IN EFI_HANDLE ControllerHandle,
  433. IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
  434. )
  435. {
  436. EFI_STATUS Status;
  437. //
  438. // Test for the Tcp4ServiceBinding Protocol
  439. //
  440. Status = gBS->OpenProtocol (
  441. ControllerHandle,
  442. &gEfiTcp4ServiceBindingProtocolGuid,
  443. NULL,
  444. This->DriverBindingHandle,
  445. ControllerHandle,
  446. EFI_OPEN_PROTOCOL_TEST_PROTOCOL
  447. );
  448. if (!EFI_ERROR (Status)) {
  449. return EFI_ALREADY_STARTED;
  450. }
  451. //
  452. // Test for the Ip4ServiceBinding Protocol
  453. //
  454. Status = gBS->OpenProtocol (
  455. ControllerHandle,
  456. &gEfiIp4ServiceBindingProtocolGuid,
  457. NULL,
  458. This->DriverBindingHandle,
  459. ControllerHandle,
  460. EFI_OPEN_PROTOCOL_TEST_PROTOCOL
  461. );
  462. return Status;
  463. }
  464. /**
  465. Start this driver on ControllerHandle.
  466. @param[in] This Protocol instance pointer.
  467. @param[in] ControllerHandle Handle of device to bind driver to.
  468. @param[in] RemainingDevicePath Optional parameter use to pick a specific child
  469. device to start.
  470. @retval EFI_SUCCESS The driver is added to ControllerHandle.
  471. @retval EFI_OUT_OF_RESOURCES There are not enough resources to start the
  472. driver.
  473. @retval other The driver cannot be added to ControllerHandle.
  474. **/
  475. EFI_STATUS
  476. EFIAPI
  477. Tcp4DriverBindingStart (
  478. IN EFI_DRIVER_BINDING_PROTOCOL *This,
  479. IN EFI_HANDLE ControllerHandle,
  480. IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
  481. )
  482. {
  483. EFI_STATUS Status;
  484. Status = TcpCreateService (ControllerHandle, This->DriverBindingHandle, IP_VERSION_4);
  485. if ((Status == EFI_ALREADY_STARTED) || (Status == EFI_UNSUPPORTED)) {
  486. Status = EFI_SUCCESS;
  487. }
  488. return Status;
  489. }
  490. /**
  491. Stop this driver on ControllerHandle.
  492. @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
  493. @param[in] ControllerHandle A handle to the device being stopped. The handle must
  494. support a bus specific I/O protocol for the driver
  495. to use to stop the device.
  496. @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.
  497. @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL
  498. if NumberOfChildren is 0.
  499. @retval EFI_SUCCESS The device was stopped.
  500. @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
  501. **/
  502. EFI_STATUS
  503. EFIAPI
  504. Tcp4DriverBindingStop (
  505. IN EFI_DRIVER_BINDING_PROTOCOL *This,
  506. IN EFI_HANDLE ControllerHandle,
  507. IN UINTN NumberOfChildren,
  508. IN EFI_HANDLE *ChildHandleBuffer OPTIONAL
  509. )
  510. {
  511. return TcpDestroyService (
  512. ControllerHandle,
  513. This->DriverBindingHandle,
  514. NumberOfChildren,
  515. ChildHandleBuffer,
  516. IP_VERSION_4
  517. );
  518. }
  519. /**
  520. Test to see if this driver supports ControllerHandle.
  521. @param[in] This Protocol instance pointer.
  522. @param[in] ControllerHandle Handle of device to test.
  523. @param[in] RemainingDevicePath Optional parameter use to pick a specific
  524. child device to start.
  525. @retval EFI_SUCCESS This driver supports this device.
  526. @retval EFI_ALREADY_STARTED This driver is already running on this device.
  527. @retval other This driver does not support this device.
  528. **/
  529. EFI_STATUS
  530. EFIAPI
  531. Tcp6DriverBindingSupported (
  532. IN EFI_DRIVER_BINDING_PROTOCOL *This,
  533. IN EFI_HANDLE ControllerHandle,
  534. IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
  535. )
  536. {
  537. EFI_STATUS Status;
  538. //
  539. // Test for the Tcp6ServiceBinding Protocol
  540. //
  541. Status = gBS->OpenProtocol (
  542. ControllerHandle,
  543. &gEfiTcp6ServiceBindingProtocolGuid,
  544. NULL,
  545. This->DriverBindingHandle,
  546. ControllerHandle,
  547. EFI_OPEN_PROTOCOL_TEST_PROTOCOL
  548. );
  549. if (!EFI_ERROR (Status)) {
  550. return EFI_ALREADY_STARTED;
  551. }
  552. //
  553. // Test for the Ip6ServiceBinding Protocol
  554. //
  555. Status = gBS->OpenProtocol (
  556. ControllerHandle,
  557. &gEfiIp6ServiceBindingProtocolGuid,
  558. NULL,
  559. This->DriverBindingHandle,
  560. ControllerHandle,
  561. EFI_OPEN_PROTOCOL_TEST_PROTOCOL
  562. );
  563. return Status;
  564. }
  565. /**
  566. Start this driver on ControllerHandle.
  567. @param[in] This Protocol instance pointer.
  568. @param[in] ControllerHandle Handle of device to bind driver to.
  569. @param[in] RemainingDevicePath Optional parameter use to pick a specific child
  570. device to start.
  571. @retval EFI_SUCCESS The driver is added to ControllerHandle.
  572. @retval EFI_OUT_OF_RESOURCES There are not enough resources to start the
  573. driver.
  574. @retval other The driver cannot be added to ControllerHandle.
  575. **/
  576. EFI_STATUS
  577. EFIAPI
  578. Tcp6DriverBindingStart (
  579. IN EFI_DRIVER_BINDING_PROTOCOL *This,
  580. IN EFI_HANDLE ControllerHandle,
  581. IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
  582. )
  583. {
  584. EFI_STATUS Status;
  585. Status = TcpCreateService (ControllerHandle, This->DriverBindingHandle, IP_VERSION_6);
  586. if ((Status == EFI_ALREADY_STARTED) || (Status == EFI_UNSUPPORTED)) {
  587. Status = EFI_SUCCESS;
  588. }
  589. return Status;
  590. }
  591. /**
  592. Stop this driver on ControllerHandle.
  593. @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
  594. @param[in] ControllerHandle A handle to the device being stopped. The handle must
  595. support a bus specific I/O protocol for the driver
  596. to use to stop the device.
  597. @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.
  598. @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL
  599. if NumberOfChildren is 0.
  600. @retval EFI_SUCCESS The device was stopped.
  601. @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
  602. **/
  603. EFI_STATUS
  604. EFIAPI
  605. Tcp6DriverBindingStop (
  606. IN EFI_DRIVER_BINDING_PROTOCOL *This,
  607. IN EFI_HANDLE ControllerHandle,
  608. IN UINTN NumberOfChildren,
  609. IN EFI_HANDLE *ChildHandleBuffer OPTIONAL
  610. )
  611. {
  612. return TcpDestroyService (
  613. ControllerHandle,
  614. This->DriverBindingHandle,
  615. NumberOfChildren,
  616. ChildHandleBuffer,
  617. IP_VERSION_6
  618. );
  619. }
  620. /**
  621. The Callback function called after the TCP socket was created.
  622. @param[in] This Pointer to the socket just created
  623. @param[in] Context Context of the socket
  624. @retval EFI_SUCCESS This protocol installed successfully.
  625. @retval other An error occurred.
  626. **/
  627. EFI_STATUS
  628. TcpCreateSocketCallback (
  629. IN SOCKET *This,
  630. IN VOID *Context
  631. )
  632. {
  633. EFI_STATUS Status;
  634. TCP_SERVICE_DATA *TcpServiceData;
  635. EFI_GUID *IpProtocolGuid;
  636. VOID *Ip;
  637. if (This->IpVersion == IP_VERSION_4) {
  638. IpProtocolGuid = &gEfiIp4ProtocolGuid;
  639. } else {
  640. IpProtocolGuid = &gEfiIp6ProtocolGuid;
  641. }
  642. TcpServiceData = ((TCP_PROTO_DATA *)This->ProtoReserved)->TcpService;
  643. //
  644. // Open the default IP protocol of IP_IO BY_DRIVER.
  645. //
  646. Status = gBS->OpenProtocol (
  647. TcpServiceData->IpIo->ChildHandle,
  648. IpProtocolGuid,
  649. &Ip,
  650. TcpServiceData->DriverBindingHandle,
  651. This->SockHandle,
  652. EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
  653. );
  654. if (EFI_ERROR (Status)) {
  655. return Status;
  656. }
  657. //
  658. // Open the device path on the handle where service binding resides on.
  659. //
  660. Status = gBS->OpenProtocol (
  661. TcpServiceData->ControllerHandle,
  662. &gEfiDevicePathProtocolGuid,
  663. (VOID **)&This->ParentDevicePath,
  664. TcpServiceData->DriverBindingHandle,
  665. This->SockHandle,
  666. EFI_OPEN_PROTOCOL_GET_PROTOCOL
  667. );
  668. if (EFI_ERROR (Status)) {
  669. gBS->CloseProtocol (
  670. TcpServiceData->IpIo->ChildHandle,
  671. IpProtocolGuid,
  672. TcpServiceData->DriverBindingHandle,
  673. This->SockHandle
  674. );
  675. } else {
  676. //
  677. // Insert this socket into the SocketList.
  678. //
  679. InsertTailList (&TcpServiceData->SocketList, &This->Link);
  680. }
  681. return Status;
  682. }
  683. /**
  684. The callback function called before the TCP socket was to be destroyed.
  685. @param[in] This The TCP socket to be destroyed.
  686. @param[in] Context The context of the socket.
  687. **/
  688. VOID
  689. TcpDestroySocketCallback (
  690. IN SOCKET *This,
  691. IN VOID *Context
  692. )
  693. {
  694. TCP_SERVICE_DATA *TcpServiceData;
  695. EFI_GUID *IpProtocolGuid;
  696. if (This->IpVersion == IP_VERSION_4) {
  697. IpProtocolGuid = &gEfiIp4ProtocolGuid;
  698. } else {
  699. IpProtocolGuid = &gEfiIp6ProtocolGuid;
  700. }
  701. TcpServiceData = ((TCP_PROTO_DATA *)This->ProtoReserved)->TcpService;
  702. //
  703. // Remove this node from the list.
  704. //
  705. RemoveEntryList (&This->Link);
  706. //
  707. // Close the IP protocol.
  708. //
  709. gBS->CloseProtocol (
  710. TcpServiceData->IpIo->ChildHandle,
  711. IpProtocolGuid,
  712. TcpServiceData->DriverBindingHandle,
  713. This->SockHandle
  714. );
  715. }
  716. /**
  717. Creates a child handle with a set of TCP services.
  718. The CreateChild() function installs a protocol on ChildHandle.
  719. If ChildHandle is a pointer to NULL, then a new handle is created and returned in ChildHandle.
  720. If ChildHandle is not a pointer to NULL, then the protocol installs on the existing ChildHandle.
  721. @param[in] This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.
  722. @param[in, out] ChildHandle Pointer to the handle of the child to create.
  723. If it is NULL, then a new handle is created.
  724. If it is a pointer to an existing UEFI handle,
  725. then the protocol is added to the existing UEFI handle.
  726. @retval EFI_SUCCESS The protocol was added to ChildHandle.
  727. @retval EFI_INVALID_PARAMETER ChildHandle is NULL.
  728. @retval EFI_OUT_OF_RESOURCES There are not enough resources available to create
  729. the child.
  730. @retval other The child handle was not created.
  731. **/
  732. EFI_STATUS
  733. EFIAPI
  734. TcpServiceBindingCreateChild (
  735. IN EFI_SERVICE_BINDING_PROTOCOL *This,
  736. IN OUT EFI_HANDLE *ChildHandle
  737. )
  738. {
  739. SOCKET *Sock;
  740. TCP_SERVICE_DATA *TcpServiceData;
  741. TCP_PROTO_DATA TcpProto;
  742. EFI_STATUS Status;
  743. EFI_TPL OldTpl;
  744. if ((NULL == This) || (NULL == ChildHandle)) {
  745. return EFI_INVALID_PARAMETER;
  746. }
  747. OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
  748. Status = EFI_SUCCESS;
  749. TcpServiceData = TCP_SERVICE_FROM_THIS (This);
  750. TcpProto.TcpService = TcpServiceData;
  751. TcpProto.TcpPcb = NULL;
  752. //
  753. // Create a tcp instance with default Tcp default
  754. // sock init data and TcpProto
  755. //
  756. mTcpDefaultSockData.ProtoData = &TcpProto;
  757. mTcpDefaultSockData.DataSize = sizeof (TCP_PROTO_DATA);
  758. mTcpDefaultSockData.DriverBinding = TcpServiceData->DriverBindingHandle;
  759. mTcpDefaultSockData.IpVersion = TcpServiceData->IpVersion;
  760. if (TcpServiceData->IpVersion == IP_VERSION_4) {
  761. mTcpDefaultSockData.Protocol = &gTcp4ProtocolTemplate;
  762. } else {
  763. mTcpDefaultSockData.Protocol = &gTcp6ProtocolTemplate;
  764. }
  765. Sock = SockCreateChild (&mTcpDefaultSockData);
  766. if (NULL == Sock) {
  767. DEBUG (
  768. (DEBUG_ERROR,
  769. "TcpDriverBindingCreateChild: No resource to create a Tcp Child\n")
  770. );
  771. Status = EFI_OUT_OF_RESOURCES;
  772. } else {
  773. *ChildHandle = Sock->SockHandle;
  774. }
  775. mTcpDefaultSockData.ProtoData = NULL;
  776. gBS->RestoreTPL (OldTpl);
  777. return Status;
  778. }
  779. /**
  780. Destroys a child handle with a set of TCP services.
  781. The DestroyChild() function does the opposite of CreateChild(). It removes a protocol
  782. that was installed by CreateChild() from ChildHandle. If the removed protocol is the
  783. last protocol on ChildHandle, then ChildHandle is destroyed.
  784. @param This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.
  785. @param ChildHandle Handle of the child to be destroyed.
  786. @retval EFI_SUCCESS The protocol was removed from ChildHandle.
  787. @retval EFI_UNSUPPORTED ChildHandle does not support the protocol that is being removed.
  788. @retval EFI_INVALID_PARAMETER Child handle is NULL.
  789. @retval EFI_ACCESS_DENIED The protocol could not be removed from the ChildHandle
  790. because its services are being used.
  791. @retval other The child handle was not destroyed.
  792. **/
  793. EFI_STATUS
  794. EFIAPI
  795. TcpServiceBindingDestroyChild (
  796. IN EFI_SERVICE_BINDING_PROTOCOL *This,
  797. IN EFI_HANDLE ChildHandle
  798. )
  799. {
  800. EFI_STATUS Status;
  801. VOID *Tcp;
  802. SOCKET *Sock;
  803. if ((NULL == This) || (NULL == ChildHandle)) {
  804. return EFI_INVALID_PARAMETER;
  805. }
  806. //
  807. // retrieve the Tcp4 protocol from ChildHandle
  808. //
  809. Status = gBS->OpenProtocol (
  810. ChildHandle,
  811. &gEfiTcp4ProtocolGuid,
  812. &Tcp,
  813. gTcp4DriverBinding.DriverBindingHandle,
  814. ChildHandle,
  815. EFI_OPEN_PROTOCOL_GET_PROTOCOL
  816. );
  817. if (EFI_ERROR (Status)) {
  818. //
  819. // No Tcp4, try the Tcp6 protocol
  820. //
  821. Status = gBS->OpenProtocol (
  822. ChildHandle,
  823. &gEfiTcp6ProtocolGuid,
  824. &Tcp,
  825. gTcp6DriverBinding.DriverBindingHandle,
  826. ChildHandle,
  827. EFI_OPEN_PROTOCOL_GET_PROTOCOL
  828. );
  829. if (EFI_ERROR (Status)) {
  830. Status = EFI_UNSUPPORTED;
  831. }
  832. }
  833. if (!EFI_ERROR (Status)) {
  834. //
  835. // destroy this sock and related Tcp protocol control
  836. // block
  837. //
  838. Sock = SOCK_FROM_THIS (Tcp);
  839. SockDestroyChild (Sock);
  840. }
  841. return Status;
  842. }