FastbootTransportTcp.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660
  1. /** @file
  2. #
  3. # Copyright (c) 2014, ARM Ltd. All rights reserved.<BR>
  4. #
  5. # SPDX-License-Identifier: BSD-2-Clause-Patent
  6. #
  7. #
  8. #**/
  9. #include <Protocol/AndroidFastbootTransport.h>
  10. #include <Protocol/Dhcp4.h>
  11. #include <Protocol/Tcp4.h>
  12. #include <Protocol/ServiceBinding.h>
  13. #include <Protocol/SimpleTextOut.h>
  14. #include <Library/BaseLib.h>
  15. #include <Library/BaseMemoryLib.h>
  16. #include <Library/DebugLib.h>
  17. #include <Library/MemoryAllocationLib.h>
  18. #include <Library/PrintLib.h>
  19. #include <Library/UefiBootServicesTableLib.h>
  20. #include <Library/UefiDriverEntryPoint.h>
  21. #include <Library/UefiRuntimeServicesTableLib.h>
  22. #define IP4_ADDR_TO_STRING(IpAddr, IpAddrString) UnicodeSPrint ( \
  23. IpAddrString, \
  24. 16 * 2, \
  25. L"%d.%d.%d.%d", \
  26. IpAddr.Addr[0], \
  27. IpAddr.Addr[1], \
  28. IpAddr.Addr[2], \
  29. IpAddr.Addr[3] \
  30. );
  31. // Fastboot says max packet size is 512, but FASTBOOT_TRANSPORT_PROTOCOL
  32. // doesn't place a limit on the size of buffers returned by Receive.
  33. // (This isn't actually a packet size - it's just the size of the buffers we
  34. // pass to the TCP driver to fill with received data.)
  35. // We can achieve much better performance by doing this in larger chunks.
  36. #define RX_FRAGMENT_SIZE 2048
  37. STATIC EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *mTextOut;
  38. STATIC EFI_TCP4_PROTOCOL *mTcpConnection;
  39. STATIC EFI_TCP4_PROTOCOL *mTcpListener;
  40. STATIC EFI_EVENT mReceiveEvent;
  41. STATIC EFI_SERVICE_BINDING_PROTOCOL *mTcpServiceBinding;
  42. STATIC EFI_HANDLE mTcpHandle = NULL;
  43. // We only ever use one IO token for receive and one for transmit. To save
  44. // repeatedly allocating and freeing, just allocate statically and re-use.
  45. #define NUM_RX_TOKENS 16
  46. #define TOKEN_NEXT(Index) (((Index) + 1) % NUM_RX_TOKENS)
  47. STATIC UINTN mNextSubmitIndex;
  48. STATIC UINTN mNextReceiveIndex;
  49. STATIC EFI_TCP4_IO_TOKEN mReceiveToken[NUM_RX_TOKENS];
  50. STATIC EFI_TCP4_RECEIVE_DATA mRxData[NUM_RX_TOKENS];
  51. STATIC EFI_TCP4_IO_TOKEN mTransmitToken;
  52. STATIC EFI_TCP4_TRANSMIT_DATA mTxData;
  53. // We also reuse the accept token
  54. STATIC EFI_TCP4_LISTEN_TOKEN mAcceptToken;
  55. // .. and the close token
  56. STATIC EFI_TCP4_CLOSE_TOKEN mCloseToken;
  57. // List type for queued received packets
  58. typedef struct _FASTBOOT_TCP_PACKET_LIST {
  59. LIST_ENTRY Link;
  60. VOID *Buffer;
  61. UINTN BufferSize;
  62. } FASTBOOT_TCP_PACKET_LIST;
  63. STATIC LIST_ENTRY mPacketListHead;
  64. STATIC
  65. VOID
  66. EFIAPI
  67. DataReceived (
  68. IN EFI_EVENT Event,
  69. IN VOID *Context
  70. );
  71. /*
  72. Helper function to set up a receive IO token and call Tcp->Receive
  73. */
  74. STATIC
  75. EFI_STATUS
  76. SubmitRecieveToken (
  77. VOID
  78. )
  79. {
  80. EFI_STATUS Status;
  81. VOID *FragmentBuffer;
  82. Status = EFI_SUCCESS;
  83. FragmentBuffer = AllocatePool (RX_FRAGMENT_SIZE);
  84. ASSERT (FragmentBuffer != NULL);
  85. if (FragmentBuffer == NULL) {
  86. DEBUG ((EFI_D_ERROR, "TCP Fastboot out of resources"));
  87. return EFI_OUT_OF_RESOURCES;
  88. }
  89. mRxData[mNextSubmitIndex].DataLength = RX_FRAGMENT_SIZE;
  90. mRxData[mNextSubmitIndex].FragmentTable[0].FragmentLength = RX_FRAGMENT_SIZE;
  91. mRxData[mNextSubmitIndex].FragmentTable[0].FragmentBuffer = FragmentBuffer;
  92. Status = mTcpConnection->Receive (mTcpConnection, &mReceiveToken[mNextSubmitIndex]);
  93. if (EFI_ERROR (Status)) {
  94. DEBUG ((EFI_D_ERROR, "TCP Receive: %r\n", Status));
  95. FreePool (FragmentBuffer);
  96. }
  97. mNextSubmitIndex = TOKEN_NEXT (mNextSubmitIndex);
  98. return Status;
  99. }
  100. /*
  101. Event notify function for when we have closed our TCP connection.
  102. We can now start listening for another connection.
  103. */
  104. STATIC
  105. VOID
  106. ConnectionClosed (
  107. IN EFI_EVENT Event,
  108. IN VOID *Context
  109. )
  110. {
  111. EFI_STATUS Status;
  112. // Possible bug in EDK2 TCP4 driver: closing a connection doesn't remove its
  113. // PCB from the list of live connections. Subsequent attempts to Configure()
  114. // a TCP instance with the same local port will fail with INVALID_PARAMETER.
  115. // Calling Configure with NULL is a workaround for this issue.
  116. Status = mTcpConnection->Configure (mTcpConnection, NULL);
  117. mTcpConnection = NULL;
  118. Status = mTcpListener->Accept (mTcpListener, &mAcceptToken);
  119. if (EFI_ERROR (Status)) {
  120. DEBUG ((EFI_D_ERROR, "TCP Accept: %r\n", Status));
  121. }
  122. }
  123. STATIC
  124. VOID
  125. CloseReceiveEvents (
  126. VOID
  127. )
  128. {
  129. UINTN Index;
  130. for (Index = 0; Index < NUM_RX_TOKENS; Index++) {
  131. gBS->CloseEvent (mReceiveToken[Index].CompletionToken.Event);
  132. }
  133. }
  134. /*
  135. Event notify function to be called when we receive TCP data.
  136. */
  137. STATIC
  138. VOID
  139. EFIAPI
  140. DataReceived (
  141. IN EFI_EVENT Event,
  142. IN VOID *Context
  143. )
  144. {
  145. EFI_STATUS Status;
  146. FASTBOOT_TCP_PACKET_LIST *NewEntry;
  147. EFI_TCP4_IO_TOKEN *ReceiveToken;
  148. ReceiveToken = &mReceiveToken[mNextReceiveIndex];
  149. Status = ReceiveToken->CompletionToken.Status;
  150. if (Status == EFI_CONNECTION_FIN) {
  151. //
  152. // Remote host closed connection. Close our end.
  153. //
  154. CloseReceiveEvents ();
  155. Status = mTcpConnection->Close (mTcpConnection, &mCloseToken);
  156. ASSERT_EFI_ERROR (Status);
  157. return;
  158. }
  159. //
  160. // Add an element to the receive queue
  161. //
  162. NewEntry = AllocatePool (sizeof (FASTBOOT_TCP_PACKET_LIST));
  163. if (NewEntry == NULL) {
  164. DEBUG ((EFI_D_ERROR, "TCP Fastboot: Out of resources\n"));
  165. return;
  166. }
  167. mNextReceiveIndex = TOKEN_NEXT (mNextReceiveIndex);
  168. if (!EFI_ERROR (Status)) {
  169. NewEntry->Buffer
  170. = ReceiveToken->Packet.RxData->FragmentTable[0].FragmentBuffer;
  171. NewEntry->BufferSize
  172. = ReceiveToken->Packet.RxData->FragmentTable[0].FragmentLength;
  173. // Prepare to receive more data
  174. SubmitRecieveToken();
  175. } else {
  176. // Fatal receive error. Put an entry with NULL in the queue, signifying
  177. // to return EFI_DEVICE_ERROR from TcpFastbootTransportReceive.
  178. NewEntry->Buffer = NULL;
  179. NewEntry->BufferSize = 0;
  180. DEBUG ((EFI_D_ERROR, "\nTCP Fastboot Receive error: %r\n", Status));
  181. }
  182. InsertTailList (&mPacketListHead, &NewEntry->Link);
  183. Status = gBS->SignalEvent (mReceiveEvent);
  184. ASSERT_EFI_ERROR (Status);
  185. }
  186. /*
  187. Event notify function to be called when we accept an incoming TCP connection.
  188. */
  189. STATIC
  190. VOID
  191. EFIAPI
  192. ConnectionAccepted (
  193. IN EFI_EVENT Event,
  194. IN VOID *Context
  195. )
  196. {
  197. EFI_TCP4_LISTEN_TOKEN *AcceptToken;
  198. EFI_STATUS Status;
  199. UINTN Index;
  200. AcceptToken = (EFI_TCP4_LISTEN_TOKEN *) Context;
  201. Status = AcceptToken->CompletionToken.Status;
  202. if (EFI_ERROR (Status)) {
  203. DEBUG ((EFI_D_ERROR, "TCP Fastboot: Connection Error: %r\n", Status));
  204. return;
  205. }
  206. DEBUG ((EFI_D_ERROR, "TCP Fastboot: Connection Received.\n"));
  207. //
  208. // Accepting a new TCP connection creates a new instance of the TCP protocol.
  209. // Open it and prepare to receive on it.
  210. //
  211. Status = gBS->OpenProtocol (
  212. AcceptToken->NewChildHandle,
  213. &gEfiTcp4ProtocolGuid,
  214. (VOID **) &mTcpConnection,
  215. gImageHandle,
  216. NULL,
  217. EFI_OPEN_PROTOCOL_GET_PROTOCOL
  218. );
  219. if (EFI_ERROR (Status)) {
  220. DEBUG ((EFI_D_ERROR, "Open TCP Connection: %r\n", Status));
  221. return;
  222. }
  223. mNextSubmitIndex = 0;
  224. mNextReceiveIndex = 0;
  225. for (Index = 0; Index < NUM_RX_TOKENS; Index++) {
  226. Status = gBS->CreateEvent (
  227. EVT_NOTIFY_SIGNAL,
  228. TPL_CALLBACK,
  229. DataReceived,
  230. NULL,
  231. &(mReceiveToken[Index].CompletionToken.Event)
  232. );
  233. ASSERT_EFI_ERROR (Status);
  234. }
  235. for (Index = 0; Index < NUM_RX_TOKENS; Index++) {
  236. SubmitRecieveToken();
  237. }
  238. }
  239. /*
  240. Set up TCP Fastboot transport: Configure the network device via DHCP then
  241. start waiting for a TCP connection on the Fastboot port.
  242. */
  243. EFI_STATUS
  244. TcpFastbootTransportStart (
  245. EFI_EVENT ReceiveEvent
  246. )
  247. {
  248. EFI_STATUS Status;
  249. EFI_HANDLE NetDeviceHandle;
  250. EFI_HANDLE *HandleBuffer;
  251. EFI_IP4_MODE_DATA Ip4ModeData;
  252. UINTN NumHandles;
  253. CHAR16 IpAddrString[16];
  254. UINTN Index;
  255. EFI_TCP4_CONFIG_DATA TcpConfigData = {
  256. 0x00, // IPv4 Type of Service
  257. 255, // IPv4 Time to Live
  258. { // AccessPoint:
  259. TRUE, // Use default address
  260. { {0, 0, 0, 0} }, // IP Address (ignored - use default)
  261. { {0, 0, 0, 0} }, // Subnet mask (ignored - use default)
  262. FixedPcdGet32 (PcdAndroidFastbootTcpPort), // Station port
  263. { {0, 0, 0, 0} }, // Remote address: accept any
  264. 0, // Remote Port: accept any
  265. FALSE // ActiveFlag: be a "server"
  266. },
  267. NULL // Default advanced TCP options
  268. };
  269. mReceiveEvent = ReceiveEvent;
  270. InitializeListHead (&mPacketListHead);
  271. mTextOut->OutputString (mTextOut, L"Initialising TCP Fastboot transport...\r\n");
  272. //
  273. // Open a passive TCP instance
  274. //
  275. Status = gBS->LocateHandleBuffer (
  276. ByProtocol,
  277. &gEfiTcp4ServiceBindingProtocolGuid,
  278. NULL,
  279. &NumHandles,
  280. &HandleBuffer
  281. );
  282. if (EFI_ERROR (Status)) {
  283. DEBUG ((EFI_D_ERROR, "Find TCP Service Binding: %r\n", Status));
  284. return Status;
  285. }
  286. // We just use the first network device
  287. NetDeviceHandle = HandleBuffer[0];
  288. Status = gBS->OpenProtocol (
  289. NetDeviceHandle,
  290. &gEfiTcp4ServiceBindingProtocolGuid,
  291. (VOID **) &mTcpServiceBinding,
  292. gImageHandle,
  293. NULL,
  294. EFI_OPEN_PROTOCOL_GET_PROTOCOL
  295. );
  296. if (EFI_ERROR (Status)) {
  297. DEBUG ((EFI_D_ERROR, "Open TCP Service Binding: %r\n", Status));
  298. return Status;
  299. }
  300. Status = mTcpServiceBinding->CreateChild (mTcpServiceBinding, &mTcpHandle);
  301. if (EFI_ERROR (Status)) {
  302. DEBUG ((EFI_D_ERROR, "TCP ServiceBinding Create: %r\n", Status));
  303. return Status;
  304. }
  305. Status = gBS->OpenProtocol (
  306. mTcpHandle,
  307. &gEfiTcp4ProtocolGuid,
  308. (VOID **) &mTcpListener,
  309. gImageHandle,
  310. NULL,
  311. EFI_OPEN_PROTOCOL_GET_PROTOCOL
  312. );
  313. if (EFI_ERROR (Status)) {
  314. DEBUG ((EFI_D_ERROR, "Open TCP Protocol: %r\n", Status));
  315. }
  316. //
  317. // Set up re-usable tokens
  318. //
  319. for (Index = 0; Index < NUM_RX_TOKENS; Index++) {
  320. mRxData[Index].UrgentFlag = FALSE;
  321. mRxData[Index].FragmentCount = 1;
  322. mReceiveToken[Index].Packet.RxData = &mRxData[Index];
  323. }
  324. mTxData.Push = TRUE;
  325. mTxData.Urgent = FALSE;
  326. mTxData.FragmentCount = 1;
  327. mTransmitToken.Packet.TxData = &mTxData;
  328. Status = gBS->CreateEvent (
  329. EVT_NOTIFY_SIGNAL,
  330. TPL_CALLBACK,
  331. ConnectionAccepted,
  332. &mAcceptToken,
  333. &mAcceptToken.CompletionToken.Event
  334. );
  335. ASSERT_EFI_ERROR (Status);
  336. Status = gBS->CreateEvent (
  337. EVT_NOTIFY_SIGNAL,
  338. TPL_CALLBACK,
  339. ConnectionClosed,
  340. &mCloseToken,
  341. &mCloseToken.CompletionToken.Event
  342. );
  343. ASSERT_EFI_ERROR (Status);
  344. //
  345. // Configure the TCP instance
  346. //
  347. Status = mTcpListener->Configure (mTcpListener, &TcpConfigData);
  348. if (Status == EFI_NO_MAPPING) {
  349. // Wait until the IP configuration process (probably DHCP) has finished
  350. do {
  351. Status = mTcpListener->GetModeData (mTcpListener,
  352. NULL, NULL,
  353. &Ip4ModeData,
  354. NULL, NULL
  355. );
  356. ASSERT_EFI_ERROR (Status);
  357. } while (!Ip4ModeData.IsConfigured);
  358. Status = mTcpListener->Configure (mTcpListener, &TcpConfigData);
  359. } else if (EFI_ERROR (Status)) {
  360. DEBUG ((EFI_D_ERROR, "TCP Configure: %r\n", Status));
  361. return Status;
  362. }
  363. //
  364. // Tell the user our address and hostname
  365. //
  366. IP4_ADDR_TO_STRING (Ip4ModeData.ConfigData.StationAddress, IpAddrString);
  367. mTextOut->OutputString (mTextOut, L"TCP Fastboot transport configured.");
  368. mTextOut->OutputString (mTextOut, L"\r\nIP address: ");
  369. mTextOut->OutputString (mTextOut ,IpAddrString);
  370. mTextOut->OutputString (mTextOut, L"\r\n");
  371. //
  372. // Start listening for a connection
  373. //
  374. Status = mTcpListener->Accept (mTcpListener, &mAcceptToken);
  375. if (EFI_ERROR (Status)) {
  376. DEBUG ((EFI_D_ERROR, "TCP Accept: %r\n", Status));
  377. return Status;
  378. }
  379. mTextOut->OutputString (mTextOut, L"TCP Fastboot transport initialised.\r\n");
  380. FreePool (HandleBuffer);
  381. return EFI_SUCCESS;
  382. }
  383. EFI_STATUS
  384. TcpFastbootTransportStop (
  385. VOID
  386. )
  387. {
  388. EFI_TCP4_CLOSE_TOKEN CloseToken;
  389. EFI_STATUS Status;
  390. UINTN EventIndex;
  391. FASTBOOT_TCP_PACKET_LIST *Entry;
  392. FASTBOOT_TCP_PACKET_LIST *NextEntry;
  393. // Close any existing TCP connection, blocking until it's done.
  394. if (mTcpConnection != NULL) {
  395. CloseReceiveEvents ();
  396. CloseToken.AbortOnClose = FALSE;
  397. Status = gBS->CreateEvent (0, 0, NULL, NULL, &CloseToken.CompletionToken.Event);
  398. ASSERT_EFI_ERROR (Status);
  399. Status = mTcpConnection->Close (mTcpConnection, &CloseToken);
  400. ASSERT_EFI_ERROR (Status);
  401. Status = gBS->WaitForEvent (
  402. 1,
  403. &CloseToken.CompletionToken.Event,
  404. &EventIndex
  405. );
  406. ASSERT_EFI_ERROR (Status);
  407. ASSERT_EFI_ERROR (CloseToken.CompletionToken.Status);
  408. // Possible bug in EDK2 TCP4 driver: closing a connection doesn't remove its
  409. // PCB from the list of live connections. Subsequent attempts to Configure()
  410. // a TCP instance with the same local port will fail with INVALID_PARAMETER.
  411. // Calling Configure with NULL is a workaround for this issue.
  412. Status = mTcpConnection->Configure (mTcpConnection, NULL);
  413. ASSERT_EFI_ERROR (Status);
  414. }
  415. gBS->CloseEvent (mAcceptToken.CompletionToken.Event);
  416. // Stop listening for connections.
  417. // Ideally we would do this with Cancel, but it isn't implemented by EDK2.
  418. // So we just "reset this TCPv4 instance brutally".
  419. Status = mTcpListener->Configure (mTcpListener, NULL);
  420. ASSERT_EFI_ERROR (Status);
  421. Status = mTcpServiceBinding->DestroyChild (mTcpServiceBinding, &mTcpHandle);
  422. // Free any data the user didn't pick up
  423. Entry = (FASTBOOT_TCP_PACKET_LIST *) GetFirstNode (&mPacketListHead);
  424. while (!IsNull (&mPacketListHead, &Entry->Link)) {
  425. NextEntry = (FASTBOOT_TCP_PACKET_LIST *) GetNextNode (&mPacketListHead, &Entry->Link);
  426. RemoveEntryList (&Entry->Link);
  427. if (Entry->Buffer) {
  428. FreePool (Entry->Buffer);
  429. }
  430. FreePool (Entry);
  431. Entry = NextEntry;
  432. }
  433. return EFI_SUCCESS;
  434. }
  435. /*
  436. Event notify function for when data has been sent. Free resources and report
  437. errors.
  438. Context should point to the transmit IO token passed to
  439. TcpConnection->Transmit.
  440. */
  441. STATIC
  442. VOID
  443. DataSent (
  444. EFI_EVENT Event,
  445. VOID *Context
  446. )
  447. {
  448. EFI_STATUS Status;
  449. Status = mTransmitToken.CompletionToken.Status;
  450. if (EFI_ERROR (Status)) {
  451. DEBUG ((EFI_D_ERROR, "TCP Fastboot transmit result: %r\n", Status));
  452. gBS->SignalEvent (*(EFI_EVENT *) Context);
  453. }
  454. FreePool (mTransmitToken.Packet.TxData->FragmentTable[0].FragmentBuffer);
  455. }
  456. EFI_STATUS
  457. TcpFastbootTransportSend (
  458. IN UINTN BufferSize,
  459. IN CONST VOID *Buffer,
  460. IN EFI_EVENT *FatalErrorEvent
  461. )
  462. {
  463. EFI_STATUS Status;
  464. if (BufferSize > 512) {
  465. return EFI_INVALID_PARAMETER;
  466. }
  467. //
  468. // Build transmit IO token
  469. //
  470. // Create an event so we are notified when a transmission is complete.
  471. // We use this to free resources and report errors.
  472. Status = gBS->CreateEvent (
  473. EVT_NOTIFY_SIGNAL,
  474. TPL_CALLBACK,
  475. DataSent,
  476. FatalErrorEvent,
  477. &mTransmitToken.CompletionToken.Event
  478. );
  479. ASSERT_EFI_ERROR (Status);
  480. mTxData.DataLength = BufferSize;
  481. mTxData.FragmentTable[0].FragmentLength = BufferSize;
  482. mTxData.FragmentTable[0].FragmentBuffer = AllocateCopyPool (
  483. BufferSize,
  484. Buffer
  485. );
  486. Status = mTcpConnection->Transmit (mTcpConnection, &mTransmitToken);
  487. if (EFI_ERROR (Status)) {
  488. DEBUG ((EFI_D_ERROR, "TCP Transmit: %r\n", Status));
  489. return Status;
  490. }
  491. return EFI_SUCCESS;
  492. }
  493. EFI_STATUS
  494. TcpFastbootTransportReceive (
  495. OUT UINTN *BufferSize,
  496. OUT VOID **Buffer
  497. )
  498. {
  499. FASTBOOT_TCP_PACKET_LIST *Entry;
  500. if (IsListEmpty (&mPacketListHead)) {
  501. return EFI_NOT_READY;
  502. }
  503. Entry = (FASTBOOT_TCP_PACKET_LIST *) GetFirstNode (&mPacketListHead);
  504. if (Entry->Buffer == NULL) {
  505. // There was an error receiving this packet.
  506. return EFI_DEVICE_ERROR;
  507. }
  508. *Buffer = Entry->Buffer;
  509. *BufferSize = Entry->BufferSize;
  510. RemoveEntryList (&Entry->Link);
  511. FreePool (Entry);
  512. return EFI_SUCCESS;
  513. }
  514. FASTBOOT_TRANSPORT_PROTOCOL mTransportProtocol = {
  515. TcpFastbootTransportStart,
  516. TcpFastbootTransportStop,
  517. TcpFastbootTransportSend,
  518. TcpFastbootTransportReceive
  519. };
  520. EFI_STATUS
  521. TcpFastbootTransportEntryPoint (
  522. IN EFI_HANDLE ImageHandle,
  523. IN EFI_SYSTEM_TABLE *SystemTable
  524. )
  525. {
  526. EFI_STATUS Status;
  527. Status = gBS->LocateProtocol(
  528. &gEfiSimpleTextOutProtocolGuid,
  529. NULL,
  530. (VOID **) &mTextOut
  531. );
  532. if (EFI_ERROR (Status)) {
  533. DEBUG ((EFI_D_ERROR, "Fastboot: Open Text Output Protocol: %r\n", Status));
  534. return Status;
  535. }
  536. Status = gBS->InstallProtocolInterface (
  537. &ImageHandle,
  538. &gAndroidFastbootTransportProtocolGuid,
  539. EFI_NATIVE_INTERFACE,
  540. &mTransportProtocol
  541. );
  542. if (EFI_ERROR (Status)) {
  543. DEBUG ((EFI_D_ERROR, "Fastboot: Install transport Protocol: %r\n", Status));
  544. }
  545. return Status;
  546. }