Mtftp4Driver.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732
  1. /** @file
  2. Implementation of Mtftp drivers.
  3. Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
  4. SPDX-License-Identifier: BSD-2-Clause-Patent
  5. **/
  6. #include "Mtftp4Impl.h"
  7. EFI_DRIVER_BINDING_PROTOCOL gMtftp4DriverBinding = {
  8. Mtftp4DriverBindingSupported,
  9. Mtftp4DriverBindingStart,
  10. Mtftp4DriverBindingStop,
  11. 0xa,
  12. NULL,
  13. NULL
  14. };
  15. EFI_SERVICE_BINDING_PROTOCOL gMtftp4ServiceBindingTemplete = {
  16. Mtftp4ServiceBindingCreateChild,
  17. Mtftp4ServiceBindingDestroyChild
  18. };
  19. /**
  20. The driver entry point which installs multiple protocols to the ImageHandle.
  21. @param ImageHandle The MTFTP's image handle.
  22. @param SystemTable The system table.
  23. @retval EFI_SUCCESS The handles are successfully installed on the image.
  24. @retval others some EFI_ERROR occurred.
  25. **/
  26. EFI_STATUS
  27. EFIAPI
  28. Mtftp4DriverEntryPoint (
  29. IN EFI_HANDLE ImageHandle,
  30. IN EFI_SYSTEM_TABLE *SystemTable
  31. )
  32. {
  33. return EfiLibInstallDriverBindingComponentName2 (
  34. ImageHandle,
  35. SystemTable,
  36. &gMtftp4DriverBinding,
  37. ImageHandle,
  38. &gMtftp4ComponentName,
  39. &gMtftp4ComponentName2
  40. );
  41. }
  42. /**
  43. Test whether MTFTP driver support this controller.
  44. @param This The MTFTP driver binding instance
  45. @param Controller The controller to test
  46. @param RemainingDevicePath The remaining device path
  47. @retval EFI_SUCCESS The controller has UDP service binding protocol
  48. installed, MTFTP can support it.
  49. @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and
  50. RemainingDevicePath is already being managed by
  51. the driver specified by This.
  52. @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and
  53. RemainingDevicePath is already being managed by a
  54. different driver or an application that requires
  55. exclusive access.
  56. @retval EFI_UNSUPPORTED The device specified by ControllerHandle and
  57. RemainingDevicePath is not supported by the driver
  58. specified by This.
  59. **/
  60. EFI_STATUS
  61. EFIAPI
  62. Mtftp4DriverBindingSupported (
  63. IN EFI_DRIVER_BINDING_PROTOCOL *This,
  64. IN EFI_HANDLE Controller,
  65. IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
  66. )
  67. {
  68. EFI_STATUS Status;
  69. Status = gBS->OpenProtocol (
  70. Controller,
  71. &gEfiUdp4ServiceBindingProtocolGuid,
  72. NULL,
  73. This->DriverBindingHandle,
  74. Controller,
  75. EFI_OPEN_PROTOCOL_TEST_PROTOCOL
  76. );
  77. return Status;
  78. }
  79. /**
  80. Config a NULL UDP that is used to keep the connection between UDP and MTFTP.
  81. Just leave the Udp child unconfigured. When UDP is unloaded,
  82. MTFTP will be informed with DriverBinding Stop.
  83. @param UdpIo The UDP_IO to configure
  84. @param Context The opaque parameter to the callback
  85. @retval EFI_SUCCESS It always return EFI_SUCCESS directly.
  86. **/
  87. EFI_STATUS
  88. EFIAPI
  89. Mtftp4ConfigNullUdp (
  90. IN UDP_IO *UdpIo,
  91. IN VOID *Context
  92. )
  93. {
  94. return EFI_SUCCESS;
  95. }
  96. /**
  97. Create then initialize a MTFTP service binding instance.
  98. @param Controller The controller to install the MTFTP service
  99. binding on
  100. @param Image The driver binding image of the MTFTP driver
  101. @param Service The variable to receive the created service
  102. binding instance.
  103. @retval EFI_OUT_OF_RESOURCES Failed to allocate resource to create the instance
  104. @retval EFI_DEVICE_ERROR Failed to create a NULL UDP port to keep
  105. connection with UDP.
  106. @retval EFI_SUCCESS The service instance is created for the
  107. controller.
  108. **/
  109. EFI_STATUS
  110. Mtftp4CreateService (
  111. IN EFI_HANDLE Controller,
  112. IN EFI_HANDLE Image,
  113. OUT MTFTP4_SERVICE **Service
  114. )
  115. {
  116. MTFTP4_SERVICE *MtftpSb;
  117. EFI_STATUS Status;
  118. *Service = NULL;
  119. MtftpSb = AllocatePool (sizeof (MTFTP4_SERVICE));
  120. if (MtftpSb == NULL) {
  121. return EFI_OUT_OF_RESOURCES;
  122. }
  123. MtftpSb->Signature = MTFTP4_SERVICE_SIGNATURE;
  124. MtftpSb->ServiceBinding = gMtftp4ServiceBindingTemplete;
  125. MtftpSb->ChildrenNum = 0;
  126. InitializeListHead (&MtftpSb->Children);
  127. MtftpSb->Timer = NULL;
  128. MtftpSb->TimerNotifyLevel = NULL;
  129. MtftpSb->TimerToGetMap = NULL;
  130. MtftpSb->Controller = Controller;
  131. MtftpSb->Image = Image;
  132. MtftpSb->ConnectUdp = NULL;
  133. //
  134. // Create the timer and a udp to be notified when UDP is uninstalled
  135. //
  136. Status = gBS->CreateEvent (
  137. EVT_NOTIFY_SIGNAL | EVT_TIMER,
  138. TPL_CALLBACK,
  139. Mtftp4OnTimerTick,
  140. MtftpSb,
  141. &MtftpSb->Timer
  142. );
  143. if (EFI_ERROR (Status)) {
  144. FreePool (MtftpSb);
  145. return Status;
  146. }
  147. Status = gBS->CreateEvent (
  148. EVT_NOTIFY_SIGNAL | EVT_TIMER,
  149. TPL_NOTIFY,
  150. Mtftp4OnTimerTickNotifyLevel,
  151. MtftpSb,
  152. &MtftpSb->TimerNotifyLevel
  153. );
  154. if (EFI_ERROR (Status)) {
  155. gBS->CloseEvent (MtftpSb->Timer);
  156. FreePool (MtftpSb);
  157. return Status;
  158. }
  159. //
  160. // Create the timer used to time out the procedure which is used to
  161. // get the default IP address.
  162. //
  163. Status = gBS->CreateEvent (
  164. EVT_TIMER,
  165. TPL_CALLBACK,
  166. NULL,
  167. NULL,
  168. &MtftpSb->TimerToGetMap
  169. );
  170. if (EFI_ERROR (Status)) {
  171. gBS->CloseEvent (MtftpSb->TimerNotifyLevel);
  172. gBS->CloseEvent (MtftpSb->Timer);
  173. FreePool (MtftpSb);
  174. return Status;
  175. }
  176. MtftpSb->ConnectUdp = UdpIoCreateIo (
  177. Controller,
  178. Image,
  179. Mtftp4ConfigNullUdp,
  180. UDP_IO_UDP4_VERSION,
  181. NULL
  182. );
  183. if (MtftpSb->ConnectUdp == NULL) {
  184. gBS->CloseEvent (MtftpSb->TimerToGetMap);
  185. gBS->CloseEvent (MtftpSb->TimerNotifyLevel);
  186. gBS->CloseEvent (MtftpSb->Timer);
  187. FreePool (MtftpSb);
  188. return EFI_DEVICE_ERROR;
  189. }
  190. *Service = MtftpSb;
  191. return EFI_SUCCESS;
  192. }
  193. /**
  194. Release all the resource used the MTFTP service binding instance.
  195. @param MtftpSb The MTFTP service binding instance.
  196. **/
  197. VOID
  198. Mtftp4CleanService (
  199. IN MTFTP4_SERVICE *MtftpSb
  200. )
  201. {
  202. UdpIoFreeIo (MtftpSb->ConnectUdp);
  203. gBS->CloseEvent (MtftpSb->TimerToGetMap);
  204. gBS->CloseEvent (MtftpSb->TimerNotifyLevel);
  205. gBS->CloseEvent (MtftpSb->Timer);
  206. }
  207. /**
  208. Start the MTFTP driver on this controller.
  209. MTFTP driver will install a MTFTP SERVICE BINDING protocol on the supported
  210. controller, which can be used to create/destroy MTFTP children.
  211. @param This The MTFTP driver binding protocol.
  212. @param Controller The controller to manage.
  213. @param RemainingDevicePath Remaining device path.
  214. @retval EFI_ALREADY_STARTED The MTFTP service binding protocol has been
  215. started on the controller.
  216. @retval EFI_SUCCESS The MTFTP service binding is installed on the
  217. controller.
  218. **/
  219. EFI_STATUS
  220. EFIAPI
  221. Mtftp4DriverBindingStart (
  222. IN EFI_DRIVER_BINDING_PROTOCOL *This,
  223. IN EFI_HANDLE Controller,
  224. IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
  225. )
  226. {
  227. MTFTP4_SERVICE *MtftpSb;
  228. EFI_STATUS Status;
  229. //
  230. // Directly return if driver is already running.
  231. //
  232. Status = gBS->OpenProtocol (
  233. Controller,
  234. &gEfiMtftp4ServiceBindingProtocolGuid,
  235. NULL,
  236. This->DriverBindingHandle,
  237. Controller,
  238. EFI_OPEN_PROTOCOL_TEST_PROTOCOL
  239. );
  240. if (Status == EFI_SUCCESS) {
  241. return EFI_ALREADY_STARTED;
  242. }
  243. Status = Mtftp4CreateService (Controller, This->DriverBindingHandle, &MtftpSb);
  244. if (EFI_ERROR (Status)) {
  245. return Status;
  246. }
  247. ASSERT (MtftpSb != NULL);
  248. Status = gBS->SetTimer (MtftpSb->Timer, TimerPeriodic, TICKS_PER_SECOND);
  249. if (EFI_ERROR (Status)) {
  250. goto ON_ERROR;
  251. }
  252. Status = gBS->SetTimer (MtftpSb->TimerNotifyLevel, TimerPeriodic, TICKS_PER_SECOND);
  253. if (EFI_ERROR (Status)) {
  254. goto ON_ERROR;
  255. }
  256. //
  257. // Install the Mtftp4ServiceBinding Protocol onto Controller
  258. //
  259. Status = gBS->InstallMultipleProtocolInterfaces (
  260. &Controller,
  261. &gEfiMtftp4ServiceBindingProtocolGuid,
  262. &MtftpSb->ServiceBinding,
  263. NULL
  264. );
  265. if (EFI_ERROR (Status)) {
  266. goto ON_ERROR;
  267. }
  268. return EFI_SUCCESS;
  269. ON_ERROR:
  270. Mtftp4CleanService (MtftpSb);
  271. FreePool (MtftpSb);
  272. return Status;
  273. }
  274. /**
  275. Callback function which provided by user to remove one node in NetDestroyLinkList process.
  276. @param[in] Entry The entry to be removed.
  277. @param[in] Context Pointer to the callback context corresponds to the Context in NetDestroyLinkList.
  278. @retval EFI_SUCCESS The entry has been removed successfully.
  279. @retval Others Fail to remove the entry.
  280. **/
  281. EFI_STATUS
  282. EFIAPI
  283. Mtftp4DestroyChildEntryInHandleBuffer (
  284. IN LIST_ENTRY *Entry,
  285. IN VOID *Context
  286. )
  287. {
  288. MTFTP4_PROTOCOL *Instance;
  289. EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;
  290. UINTN NumberOfChildren;
  291. EFI_HANDLE *ChildHandleBuffer;
  292. if ((Entry == NULL) || (Context == NULL)) {
  293. return EFI_INVALID_PARAMETER;
  294. }
  295. Instance = NET_LIST_USER_STRUCT_S (Entry, MTFTP4_PROTOCOL, Link, MTFTP4_PROTOCOL_SIGNATURE);
  296. ServiceBinding = ((MTFTP4_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT *)Context)->ServiceBinding;
  297. NumberOfChildren = ((MTFTP4_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT *)Context)->NumberOfChildren;
  298. ChildHandleBuffer = ((MTFTP4_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT *)Context)->ChildHandleBuffer;
  299. if (!NetIsInHandleBuffer (Instance->Handle, NumberOfChildren, ChildHandleBuffer)) {
  300. return EFI_SUCCESS;
  301. }
  302. return ServiceBinding->DestroyChild (ServiceBinding, Instance->Handle);
  303. }
  304. /**
  305. Stop the MTFTP driver on controller. The controller is a UDP
  306. child handle.
  307. @param This The MTFTP driver binding protocol
  308. @param Controller The controller to stop
  309. @param NumberOfChildren The number of children
  310. @param ChildHandleBuffer The array of the child handle.
  311. @retval EFI_SUCCESS The driver is stopped on the controller.
  312. @retval EFI_DEVICE_ERROR Failed to stop the driver on the controller.
  313. **/
  314. EFI_STATUS
  315. EFIAPI
  316. Mtftp4DriverBindingStop (
  317. IN EFI_DRIVER_BINDING_PROTOCOL *This,
  318. IN EFI_HANDLE Controller,
  319. IN UINTN NumberOfChildren,
  320. IN EFI_HANDLE *ChildHandleBuffer
  321. )
  322. {
  323. EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;
  324. MTFTP4_SERVICE *MtftpSb;
  325. EFI_HANDLE NicHandle;
  326. EFI_STATUS Status;
  327. LIST_ENTRY *List;
  328. MTFTP4_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT Context;
  329. //
  330. // MTFTP driver opens UDP child, So, Controller is a UDP
  331. // child handle. Locate the Nic handle first. Then get the
  332. // MTFTP private data back.
  333. //
  334. NicHandle = NetLibGetNicHandle (Controller, &gEfiUdp4ProtocolGuid);
  335. if (NicHandle == NULL) {
  336. return EFI_SUCCESS;
  337. }
  338. Status = gBS->OpenProtocol (
  339. NicHandle,
  340. &gEfiMtftp4ServiceBindingProtocolGuid,
  341. (VOID **)&ServiceBinding,
  342. This->DriverBindingHandle,
  343. NicHandle,
  344. EFI_OPEN_PROTOCOL_GET_PROTOCOL
  345. );
  346. if (EFI_ERROR (Status)) {
  347. return EFI_DEVICE_ERROR;
  348. }
  349. MtftpSb = MTFTP4_SERVICE_FROM_THIS (ServiceBinding);
  350. if (!IsListEmpty (&MtftpSb->Children)) {
  351. //
  352. // Destroy the Mtftp4 child instance in ChildHandleBuffer.
  353. //
  354. List = &MtftpSb->Children;
  355. Context.ServiceBinding = ServiceBinding;
  356. Context.NumberOfChildren = NumberOfChildren;
  357. Context.ChildHandleBuffer = ChildHandleBuffer;
  358. Status = NetDestroyLinkList (
  359. List,
  360. Mtftp4DestroyChildEntryInHandleBuffer,
  361. &Context,
  362. NULL
  363. );
  364. }
  365. if ((NumberOfChildren == 0) && IsListEmpty (&MtftpSb->Children)) {
  366. gBS->UninstallProtocolInterface (
  367. NicHandle,
  368. &gEfiMtftp4ServiceBindingProtocolGuid,
  369. ServiceBinding
  370. );
  371. Mtftp4CleanService (MtftpSb);
  372. if (gMtftp4ControllerNameTable != NULL) {
  373. FreeUnicodeStringTable (gMtftp4ControllerNameTable);
  374. gMtftp4ControllerNameTable = NULL;
  375. }
  376. FreePool (MtftpSb);
  377. Status = EFI_SUCCESS;
  378. }
  379. return Status;
  380. }
  381. /**
  382. Initialize a MTFTP protocol instance which is the child of MtftpSb.
  383. @param MtftpSb The MTFTP service binding protocol.
  384. @param Instance The MTFTP instance to initialize.
  385. **/
  386. VOID
  387. Mtftp4InitProtocol (
  388. IN MTFTP4_SERVICE *MtftpSb,
  389. OUT MTFTP4_PROTOCOL *Instance
  390. )
  391. {
  392. ZeroMem (Instance, sizeof (MTFTP4_PROTOCOL));
  393. Instance->Signature = MTFTP4_PROTOCOL_SIGNATURE;
  394. InitializeListHead (&Instance->Link);
  395. CopyMem (&Instance->Mtftp4, &gMtftp4ProtocolTemplate, sizeof (Instance->Mtftp4));
  396. Instance->State = MTFTP4_STATE_UNCONFIGED;
  397. Instance->Service = MtftpSb;
  398. InitializeListHead (&Instance->Blocks);
  399. }
  400. /**
  401. Create a MTFTP child for the service binding instance, then
  402. install the MTFTP protocol to the ChildHandle.
  403. @param This The MTFTP service binding instance.
  404. @param ChildHandle The Child handle to install the MTFTP protocol.
  405. @retval EFI_INVALID_PARAMETER The parameter is invalid.
  406. @retval EFI_OUT_OF_RESOURCES Failed to allocate resource for the new child.
  407. @retval EFI_SUCCESS The child is successfully create.
  408. **/
  409. EFI_STATUS
  410. EFIAPI
  411. Mtftp4ServiceBindingCreateChild (
  412. IN EFI_SERVICE_BINDING_PROTOCOL *This,
  413. IN EFI_HANDLE *ChildHandle
  414. )
  415. {
  416. MTFTP4_SERVICE *MtftpSb;
  417. MTFTP4_PROTOCOL *Instance;
  418. EFI_STATUS Status;
  419. EFI_TPL OldTpl;
  420. VOID *Udp4;
  421. if ((This == NULL) || (ChildHandle == NULL)) {
  422. return EFI_INVALID_PARAMETER;
  423. }
  424. Instance = AllocatePool (sizeof (*Instance));
  425. if (Instance == NULL) {
  426. return EFI_OUT_OF_RESOURCES;
  427. }
  428. MtftpSb = MTFTP4_SERVICE_FROM_THIS (This);
  429. Mtftp4InitProtocol (MtftpSb, Instance);
  430. Instance->UnicastPort = UdpIoCreateIo (
  431. MtftpSb->Controller,
  432. MtftpSb->Image,
  433. Mtftp4ConfigNullUdp,
  434. UDP_IO_UDP4_VERSION,
  435. Instance
  436. );
  437. if (Instance->UnicastPort == NULL) {
  438. FreePool (Instance);
  439. return EFI_OUT_OF_RESOURCES;
  440. }
  441. //
  442. // Install the MTFTP protocol onto ChildHandle
  443. //
  444. Status = gBS->InstallMultipleProtocolInterfaces (
  445. ChildHandle,
  446. &gEfiMtftp4ProtocolGuid,
  447. &Instance->Mtftp4,
  448. NULL
  449. );
  450. if (EFI_ERROR (Status)) {
  451. UdpIoFreeIo (Instance->UnicastPort);
  452. FreePool (Instance);
  453. return Status;
  454. }
  455. Instance->Handle = *ChildHandle;
  456. //
  457. // Open the Udp4 protocol BY_CHILD.
  458. //
  459. Status = gBS->OpenProtocol (
  460. MtftpSb->ConnectUdp->UdpHandle,
  461. &gEfiUdp4ProtocolGuid,
  462. (VOID **)&Udp4,
  463. gMtftp4DriverBinding.DriverBindingHandle,
  464. Instance->Handle,
  465. EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
  466. );
  467. if (EFI_ERROR (Status)) {
  468. goto ON_ERROR;
  469. }
  470. //
  471. // Open the Udp4 protocol by child.
  472. //
  473. Status = gBS->OpenProtocol (
  474. Instance->UnicastPort->UdpHandle,
  475. &gEfiUdp4ProtocolGuid,
  476. (VOID **)&Udp4,
  477. gMtftp4DriverBinding.DriverBindingHandle,
  478. Instance->Handle,
  479. EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
  480. );
  481. if (EFI_ERROR (Status)) {
  482. //
  483. // Close the Udp4 protocol.
  484. //
  485. gBS->CloseProtocol (
  486. MtftpSb->ConnectUdp->UdpHandle,
  487. &gEfiUdp4ProtocolGuid,
  488. gMtftp4DriverBinding.DriverBindingHandle,
  489. *ChildHandle
  490. );
  491. goto ON_ERROR;
  492. }
  493. //
  494. // Add it to the parent's child list.
  495. //
  496. OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
  497. InsertTailList (&MtftpSb->Children, &Instance->Link);
  498. MtftpSb->ChildrenNum++;
  499. gBS->RestoreTPL (OldTpl);
  500. return EFI_SUCCESS;
  501. ON_ERROR:
  502. if (Instance->Handle != NULL) {
  503. gBS->UninstallMultipleProtocolInterfaces (
  504. Instance->Handle,
  505. &gEfiMtftp4ProtocolGuid,
  506. &Instance->Mtftp4,
  507. NULL
  508. );
  509. }
  510. UdpIoFreeIo (Instance->UnicastPort);
  511. FreePool (Instance);
  512. return Status;
  513. }
  514. /**
  515. Destroy one of the service binding's child.
  516. @param This The service binding instance
  517. @param ChildHandle The child handle to destroy
  518. @retval EFI_INVALID_PARAMETER The parameter is invalid.
  519. @retval EFI_UNSUPPORTED The child may have already been destroyed.
  520. @retval EFI_SUCCESS The child is destroyed and removed from the
  521. parent's child list.
  522. **/
  523. EFI_STATUS
  524. EFIAPI
  525. Mtftp4ServiceBindingDestroyChild (
  526. IN EFI_SERVICE_BINDING_PROTOCOL *This,
  527. IN EFI_HANDLE ChildHandle
  528. )
  529. {
  530. MTFTP4_SERVICE *MtftpSb;
  531. MTFTP4_PROTOCOL *Instance;
  532. EFI_MTFTP4_PROTOCOL *Mtftp4;
  533. EFI_STATUS Status;
  534. EFI_TPL OldTpl;
  535. if ((This == NULL) || (ChildHandle == NULL)) {
  536. return EFI_INVALID_PARAMETER;
  537. }
  538. //
  539. // Retrieve the private context data structures
  540. //
  541. Status = gBS->OpenProtocol (
  542. ChildHandle,
  543. &gEfiMtftp4ProtocolGuid,
  544. (VOID **)&Mtftp4,
  545. gMtftp4DriverBinding.DriverBindingHandle,
  546. ChildHandle,
  547. EFI_OPEN_PROTOCOL_GET_PROTOCOL
  548. );
  549. if (EFI_ERROR (Status)) {
  550. return EFI_UNSUPPORTED;
  551. }
  552. Instance = MTFTP4_PROTOCOL_FROM_THIS (Mtftp4);
  553. MtftpSb = MTFTP4_SERVICE_FROM_THIS (This);
  554. if (Instance->Service != MtftpSb) {
  555. return EFI_INVALID_PARAMETER;
  556. }
  557. if (Instance->InDestroy) {
  558. return EFI_SUCCESS;
  559. }
  560. Instance->InDestroy = TRUE;
  561. //
  562. // Close the Udp4 protocol.
  563. //
  564. gBS->CloseProtocol (
  565. MtftpSb->ConnectUdp->UdpHandle,
  566. &gEfiUdp4ProtocolGuid,
  567. gMtftp4DriverBinding.DriverBindingHandle,
  568. ChildHandle
  569. );
  570. gBS->CloseProtocol (
  571. Instance->UnicastPort->UdpHandle,
  572. &gEfiUdp4ProtocolGuid,
  573. gMtftp4DriverBinding.DriverBindingHandle,
  574. ChildHandle
  575. );
  576. if (Instance->McastUdpPort != NULL) {
  577. gBS->CloseProtocol (
  578. Instance->McastUdpPort->UdpHandle,
  579. &gEfiUdp4ProtocolGuid,
  580. gMtftp4DriverBinding.DriverBindingHandle,
  581. ChildHandle
  582. );
  583. }
  584. //
  585. // Uninstall the MTFTP4 protocol first to enable a top down destruction.
  586. //
  587. Status = gBS->UninstallProtocolInterface (
  588. ChildHandle,
  589. &gEfiMtftp4ProtocolGuid,
  590. Mtftp4
  591. );
  592. if (EFI_ERROR (Status)) {
  593. Instance->InDestroy = FALSE;
  594. return Status;
  595. }
  596. OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
  597. Mtftp4CleanOperation (Instance, EFI_DEVICE_ERROR);
  598. UdpIoFreeIo (Instance->UnicastPort);
  599. RemoveEntryList (&Instance->Link);
  600. MtftpSb->ChildrenNum--;
  601. gBS->RestoreTPL (OldTpl);
  602. FreePool (Instance);
  603. return EFI_SUCCESS;
  604. }