FastbootTransportTcp.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668
  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 ((DEBUG_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 ((DEBUG_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 ((DEBUG_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 ((DEBUG_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 ((DEBUG_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 ((DEBUG_ERROR, "TCP Fastboot: Connection Error: %r\n", Status));
  204. return;
  205. }
  206. DEBUG ((DEBUG_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 ((DEBUG_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. {
  261. { 0, 0, 0, 0 }
  262. }, // IP Address (ignored - use default)
  263. {
  264. { 0, 0, 0, 0 }
  265. }, // Subnet mask (ignored - use default)
  266. FixedPcdGet32 (PcdAndroidFastbootTcpPort), // Station port
  267. {
  268. { 0, 0, 0, 0 }
  269. }, // Remote address: accept any
  270. 0, // Remote Port: accept any
  271. FALSE // ActiveFlag: be a "server"
  272. },
  273. NULL // Default advanced TCP options
  274. };
  275. mReceiveEvent = ReceiveEvent;
  276. InitializeListHead (&mPacketListHead);
  277. mTextOut->OutputString (mTextOut, L"Initialising TCP Fastboot transport...\r\n");
  278. //
  279. // Open a passive TCP instance
  280. //
  281. Status = gBS->LocateHandleBuffer (
  282. ByProtocol,
  283. &gEfiTcp4ServiceBindingProtocolGuid,
  284. NULL,
  285. &NumHandles,
  286. &HandleBuffer
  287. );
  288. if (EFI_ERROR (Status)) {
  289. DEBUG ((DEBUG_ERROR, "Find TCP Service Binding: %r\n", Status));
  290. return Status;
  291. }
  292. // We just use the first network device
  293. NetDeviceHandle = HandleBuffer[0];
  294. Status = gBS->OpenProtocol (
  295. NetDeviceHandle,
  296. &gEfiTcp4ServiceBindingProtocolGuid,
  297. (VOID **)&mTcpServiceBinding,
  298. gImageHandle,
  299. NULL,
  300. EFI_OPEN_PROTOCOL_GET_PROTOCOL
  301. );
  302. if (EFI_ERROR (Status)) {
  303. DEBUG ((DEBUG_ERROR, "Open TCP Service Binding: %r\n", Status));
  304. return Status;
  305. }
  306. Status = mTcpServiceBinding->CreateChild (mTcpServiceBinding, &mTcpHandle);
  307. if (EFI_ERROR (Status)) {
  308. DEBUG ((DEBUG_ERROR, "TCP ServiceBinding Create: %r\n", Status));
  309. return Status;
  310. }
  311. Status = gBS->OpenProtocol (
  312. mTcpHandle,
  313. &gEfiTcp4ProtocolGuid,
  314. (VOID **)&mTcpListener,
  315. gImageHandle,
  316. NULL,
  317. EFI_OPEN_PROTOCOL_GET_PROTOCOL
  318. );
  319. if (EFI_ERROR (Status)) {
  320. DEBUG ((DEBUG_ERROR, "Open TCP Protocol: %r\n", Status));
  321. }
  322. //
  323. // Set up re-usable tokens
  324. //
  325. for (Index = 0; Index < NUM_RX_TOKENS; Index++) {
  326. mRxData[Index].UrgentFlag = FALSE;
  327. mRxData[Index].FragmentCount = 1;
  328. mReceiveToken[Index].Packet.RxData = &mRxData[Index];
  329. }
  330. mTxData.Push = TRUE;
  331. mTxData.Urgent = FALSE;
  332. mTxData.FragmentCount = 1;
  333. mTransmitToken.Packet.TxData = &mTxData;
  334. Status = gBS->CreateEvent (
  335. EVT_NOTIFY_SIGNAL,
  336. TPL_CALLBACK,
  337. ConnectionAccepted,
  338. &mAcceptToken,
  339. &mAcceptToken.CompletionToken.Event
  340. );
  341. ASSERT_EFI_ERROR (Status);
  342. Status = gBS->CreateEvent (
  343. EVT_NOTIFY_SIGNAL,
  344. TPL_CALLBACK,
  345. ConnectionClosed,
  346. &mCloseToken,
  347. &mCloseToken.CompletionToken.Event
  348. );
  349. ASSERT_EFI_ERROR (Status);
  350. //
  351. // Configure the TCP instance
  352. //
  353. Status = mTcpListener->Configure (mTcpListener, &TcpConfigData);
  354. if (Status == EFI_NO_MAPPING) {
  355. // Wait until the IP configuration process (probably DHCP) has finished
  356. do {
  357. Status = mTcpListener->GetModeData (
  358. mTcpListener,
  359. NULL,
  360. NULL,
  361. &Ip4ModeData,
  362. NULL,
  363. NULL
  364. );
  365. ASSERT_EFI_ERROR (Status);
  366. } while (!Ip4ModeData.IsConfigured);
  367. Status = mTcpListener->Configure (mTcpListener, &TcpConfigData);
  368. } else if (EFI_ERROR (Status)) {
  369. DEBUG ((DEBUG_ERROR, "TCP Configure: %r\n", Status));
  370. return Status;
  371. }
  372. //
  373. // Tell the user our address and hostname
  374. //
  375. IP4_ADDR_TO_STRING (Ip4ModeData.ConfigData.StationAddress, IpAddrString);
  376. mTextOut->OutputString (mTextOut, L"TCP Fastboot transport configured.");
  377. mTextOut->OutputString (mTextOut, L"\r\nIP address: ");
  378. mTextOut->OutputString (mTextOut, IpAddrString);
  379. mTextOut->OutputString (mTextOut, L"\r\n");
  380. //
  381. // Start listening for a connection
  382. //
  383. Status = mTcpListener->Accept (mTcpListener, &mAcceptToken);
  384. if (EFI_ERROR (Status)) {
  385. DEBUG ((DEBUG_ERROR, "TCP Accept: %r\n", Status));
  386. return Status;
  387. }
  388. mTextOut->OutputString (mTextOut, L"TCP Fastboot transport initialised.\r\n");
  389. FreePool (HandleBuffer);
  390. return EFI_SUCCESS;
  391. }
  392. EFI_STATUS
  393. TcpFastbootTransportStop (
  394. VOID
  395. )
  396. {
  397. EFI_TCP4_CLOSE_TOKEN CloseToken;
  398. EFI_STATUS Status;
  399. UINTN EventIndex;
  400. FASTBOOT_TCP_PACKET_LIST *Entry;
  401. FASTBOOT_TCP_PACKET_LIST *NextEntry;
  402. // Close any existing TCP connection, blocking until it's done.
  403. if (mTcpConnection != NULL) {
  404. CloseReceiveEvents ();
  405. CloseToken.AbortOnClose = FALSE;
  406. Status = gBS->CreateEvent (0, 0, NULL, NULL, &CloseToken.CompletionToken.Event);
  407. ASSERT_EFI_ERROR (Status);
  408. Status = mTcpConnection->Close (mTcpConnection, &CloseToken);
  409. ASSERT_EFI_ERROR (Status);
  410. Status = gBS->WaitForEvent (
  411. 1,
  412. &CloseToken.CompletionToken.Event,
  413. &EventIndex
  414. );
  415. ASSERT_EFI_ERROR (Status);
  416. ASSERT_EFI_ERROR (CloseToken.CompletionToken.Status);
  417. // Possible bug in EDK2 TCP4 driver: closing a connection doesn't remove its
  418. // PCB from the list of live connections. Subsequent attempts to Configure()
  419. // a TCP instance with the same local port will fail with INVALID_PARAMETER.
  420. // Calling Configure with NULL is a workaround for this issue.
  421. Status = mTcpConnection->Configure (mTcpConnection, NULL);
  422. ASSERT_EFI_ERROR (Status);
  423. }
  424. gBS->CloseEvent (mAcceptToken.CompletionToken.Event);
  425. // Stop listening for connections.
  426. // Ideally we would do this with Cancel, but it isn't implemented by EDK2.
  427. // So we just "reset this TCPv4 instance brutally".
  428. Status = mTcpListener->Configure (mTcpListener, NULL);
  429. ASSERT_EFI_ERROR (Status);
  430. Status = mTcpServiceBinding->DestroyChild (mTcpServiceBinding, mTcpHandle);
  431. // Free any data the user didn't pick up
  432. Entry = (FASTBOOT_TCP_PACKET_LIST *)GetFirstNode (&mPacketListHead);
  433. while (!IsNull (&mPacketListHead, &Entry->Link)) {
  434. NextEntry = (FASTBOOT_TCP_PACKET_LIST *)GetNextNode (&mPacketListHead, &Entry->Link);
  435. RemoveEntryList (&Entry->Link);
  436. if (Entry->Buffer) {
  437. FreePool (Entry->Buffer);
  438. }
  439. FreePool (Entry);
  440. Entry = NextEntry;
  441. }
  442. return EFI_SUCCESS;
  443. }
  444. /*
  445. Event notify function for when data has been sent. Free resources and report
  446. errors.
  447. Context should point to the transmit IO token passed to
  448. TcpConnection->Transmit.
  449. */
  450. STATIC
  451. VOID
  452. DataSent (
  453. EFI_EVENT Event,
  454. VOID *Context
  455. )
  456. {
  457. EFI_STATUS Status;
  458. Status = mTransmitToken.CompletionToken.Status;
  459. if (EFI_ERROR (Status)) {
  460. DEBUG ((DEBUG_ERROR, "TCP Fastboot transmit result: %r\n", Status));
  461. gBS->SignalEvent (*(EFI_EVENT *)Context);
  462. }
  463. FreePool (mTransmitToken.Packet.TxData->FragmentTable[0].FragmentBuffer);
  464. }
  465. EFI_STATUS
  466. TcpFastbootTransportSend (
  467. IN UINTN BufferSize,
  468. IN CONST VOID *Buffer,
  469. IN EFI_EVENT *FatalErrorEvent
  470. )
  471. {
  472. EFI_STATUS Status;
  473. if (BufferSize > 512) {
  474. return EFI_INVALID_PARAMETER;
  475. }
  476. //
  477. // Build transmit IO token
  478. //
  479. // Create an event so we are notified when a transmission is complete.
  480. // We use this to free resources and report errors.
  481. Status = gBS->CreateEvent (
  482. EVT_NOTIFY_SIGNAL,
  483. TPL_CALLBACK,
  484. DataSent,
  485. FatalErrorEvent,
  486. &mTransmitToken.CompletionToken.Event
  487. );
  488. ASSERT_EFI_ERROR (Status);
  489. mTxData.DataLength = BufferSize;
  490. mTxData.FragmentTable[0].FragmentLength = BufferSize;
  491. mTxData.FragmentTable[0].FragmentBuffer = AllocateCopyPool (
  492. BufferSize,
  493. Buffer
  494. );
  495. Status = mTcpConnection->Transmit (mTcpConnection, &mTransmitToken);
  496. if (EFI_ERROR (Status)) {
  497. DEBUG ((DEBUG_ERROR, "TCP Transmit: %r\n", Status));
  498. return Status;
  499. }
  500. return EFI_SUCCESS;
  501. }
  502. EFI_STATUS
  503. TcpFastbootTransportReceive (
  504. OUT UINTN *BufferSize,
  505. OUT VOID **Buffer
  506. )
  507. {
  508. FASTBOOT_TCP_PACKET_LIST *Entry;
  509. if (IsListEmpty (&mPacketListHead)) {
  510. return EFI_NOT_READY;
  511. }
  512. Entry = (FASTBOOT_TCP_PACKET_LIST *)GetFirstNode (&mPacketListHead);
  513. if (Entry->Buffer == NULL) {
  514. // There was an error receiving this packet.
  515. return EFI_DEVICE_ERROR;
  516. }
  517. *Buffer = Entry->Buffer;
  518. *BufferSize = Entry->BufferSize;
  519. RemoveEntryList (&Entry->Link);
  520. FreePool (Entry);
  521. return EFI_SUCCESS;
  522. }
  523. FASTBOOT_TRANSPORT_PROTOCOL mTransportProtocol = {
  524. TcpFastbootTransportStart,
  525. TcpFastbootTransportStop,
  526. TcpFastbootTransportSend,
  527. TcpFastbootTransportReceive
  528. };
  529. EFI_STATUS
  530. TcpFastbootTransportEntryPoint (
  531. IN EFI_HANDLE ImageHandle,
  532. IN EFI_SYSTEM_TABLE *SystemTable
  533. )
  534. {
  535. EFI_STATUS Status;
  536. Status = gBS->LocateProtocol (
  537. &gEfiSimpleTextOutProtocolGuid,
  538. NULL,
  539. (VOID **)&mTextOut
  540. );
  541. if (EFI_ERROR (Status)) {
  542. DEBUG ((DEBUG_ERROR, "Fastboot: Open Text Output Protocol: %r\n", Status));
  543. return Status;
  544. }
  545. Status = gBS->InstallProtocolInterface (
  546. &ImageHandle,
  547. &gAndroidFastbootTransportProtocolGuid,
  548. EFI_NATIVE_INTERFACE,
  549. &mTransportProtocol
  550. );
  551. if (EFI_ERROR (Status)) {
  552. DEBUG ((DEBUG_ERROR, "Fastboot: Install transport Protocol: %r\n", Status));
  553. }
  554. return Status;
  555. }