efi_net.c 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Simple network protocol
  4. * PXE base code protocol
  5. *
  6. * Copyright (c) 2016 Alexander Graf
  7. *
  8. * The simple network protocol has the following statuses and services
  9. * to move between them:
  10. *
  11. * Start(): EfiSimpleNetworkStopped -> EfiSimpleNetworkStarted
  12. * Initialize(): EfiSimpleNetworkStarted -> EfiSimpleNetworkInitialized
  13. * Shutdown(): EfiSimpleNetworkInitialized -> EfiSimpleNetworkStarted
  14. * Stop(): EfiSimpleNetworkStarted -> EfiSimpleNetworkStopped
  15. * Reset(): EfiSimpleNetworkInitialized -> EfiSimpleNetworkInitialized
  16. */
  17. #include <common.h>
  18. #include <efi_loader.h>
  19. #include <malloc.h>
  20. #include <net.h>
  21. static const efi_guid_t efi_net_guid = EFI_SIMPLE_NETWORK_PROTOCOL_GUID;
  22. static const efi_guid_t efi_pxe_base_code_protocol_guid =
  23. EFI_PXE_BASE_CODE_PROTOCOL_GUID;
  24. static struct efi_pxe_packet *dhcp_ack;
  25. static void *new_tx_packet;
  26. static void *transmit_buffer;
  27. static uchar **receive_buffer;
  28. static size_t *receive_lengths;
  29. static int rx_packet_idx;
  30. static int rx_packet_num;
  31. /*
  32. * The notification function of this event is called in every timer cycle
  33. * to check if a new network packet has been received.
  34. */
  35. static struct efi_event *network_timer_event;
  36. /*
  37. * This event is signaled when a packet has been received.
  38. */
  39. static struct efi_event *wait_for_packet;
  40. /**
  41. * struct efi_net_obj - EFI object representing a network interface
  42. *
  43. * @header: EFI object header
  44. * @net: simple network protocol interface
  45. * @net_mode: status of the network interface
  46. * @pxe: PXE base code protocol interface
  47. * @pxe_mode: status of the PXE base code protocol
  48. */
  49. struct efi_net_obj {
  50. struct efi_object header;
  51. struct efi_simple_network net;
  52. struct efi_simple_network_mode net_mode;
  53. struct efi_pxe_base_code_protocol pxe;
  54. struct efi_pxe_mode pxe_mode;
  55. };
  56. /*
  57. * efi_net_start() - start the network interface
  58. *
  59. * This function implements the Start service of the
  60. * EFI_SIMPLE_NETWORK_PROTOCOL. See the Unified Extensible Firmware Interface
  61. * (UEFI) specification for details.
  62. *
  63. * @this: pointer to the protocol instance
  64. * Return: status code
  65. */
  66. static efi_status_t EFIAPI efi_net_start(struct efi_simple_network *this)
  67. {
  68. efi_status_t ret = EFI_SUCCESS;
  69. EFI_ENTRY("%p", this);
  70. /* Check parameters */
  71. if (!this) {
  72. ret = EFI_INVALID_PARAMETER;
  73. goto out;
  74. }
  75. if (this->mode->state != EFI_NETWORK_STOPPED) {
  76. ret = EFI_ALREADY_STARTED;
  77. } else {
  78. this->int_status = 0;
  79. wait_for_packet->is_signaled = false;
  80. this->mode->state = EFI_NETWORK_STARTED;
  81. }
  82. out:
  83. return EFI_EXIT(ret);
  84. }
  85. /*
  86. * efi_net_stop() - stop the network interface
  87. *
  88. * This function implements the Stop service of the
  89. * EFI_SIMPLE_NETWORK_PROTOCOL. See the Unified Extensible Firmware Interface
  90. * (UEFI) specification for details.
  91. *
  92. * @this: pointer to the protocol instance
  93. * Return: status code
  94. */
  95. static efi_status_t EFIAPI efi_net_stop(struct efi_simple_network *this)
  96. {
  97. efi_status_t ret = EFI_SUCCESS;
  98. EFI_ENTRY("%p", this);
  99. /* Check parameters */
  100. if (!this) {
  101. ret = EFI_INVALID_PARAMETER;
  102. goto out;
  103. }
  104. if (this->mode->state == EFI_NETWORK_STOPPED) {
  105. ret = EFI_NOT_STARTED;
  106. } else {
  107. /* Disable hardware and put it into the reset state */
  108. eth_halt();
  109. /* Clear cache of packets */
  110. rx_packet_num = 0;
  111. this->mode->state = EFI_NETWORK_STOPPED;
  112. }
  113. out:
  114. return EFI_EXIT(ret);
  115. }
  116. /*
  117. * efi_net_initialize() - initialize the network interface
  118. *
  119. * This function implements the Initialize service of the
  120. * EFI_SIMPLE_NETWORK_PROTOCOL. See the Unified Extensible Firmware Interface
  121. * (UEFI) specification for details.
  122. *
  123. * @this: pointer to the protocol instance
  124. * @extra_rx: extra receive buffer to be allocated
  125. * @extra_tx: extra transmit buffer to be allocated
  126. * Return: status code
  127. */
  128. static efi_status_t EFIAPI efi_net_initialize(struct efi_simple_network *this,
  129. ulong extra_rx, ulong extra_tx)
  130. {
  131. int ret;
  132. efi_status_t r = EFI_SUCCESS;
  133. EFI_ENTRY("%p, %lx, %lx", this, extra_rx, extra_tx);
  134. /* Check parameters */
  135. if (!this) {
  136. r = EFI_INVALID_PARAMETER;
  137. goto out;
  138. }
  139. switch (this->mode->state) {
  140. case EFI_NETWORK_INITIALIZED:
  141. case EFI_NETWORK_STARTED:
  142. break;
  143. default:
  144. r = EFI_NOT_STARTED;
  145. goto out;
  146. }
  147. /* Setup packet buffers */
  148. net_init();
  149. /* Disable hardware and put it into the reset state */
  150. eth_halt();
  151. /* Clear cache of packets */
  152. rx_packet_num = 0;
  153. /* Set current device according to environment variables */
  154. eth_set_current();
  155. /* Get hardware ready for send and receive operations */
  156. ret = eth_init();
  157. if (ret < 0) {
  158. eth_halt();
  159. this->mode->state = EFI_NETWORK_STOPPED;
  160. r = EFI_DEVICE_ERROR;
  161. goto out;
  162. } else {
  163. this->int_status = 0;
  164. wait_for_packet->is_signaled = false;
  165. this->mode->state = EFI_NETWORK_INITIALIZED;
  166. }
  167. out:
  168. return EFI_EXIT(r);
  169. }
  170. /*
  171. * efi_net_reset() - reinitialize the network interface
  172. *
  173. * This function implements the Reset service of the
  174. * EFI_SIMPLE_NETWORK_PROTOCOL. See the Unified Extensible Firmware Interface
  175. * (UEFI) specification for details.
  176. *
  177. * @this: pointer to the protocol instance
  178. * @extended_verification: execute exhaustive verification
  179. * Return: status code
  180. */
  181. static efi_status_t EFIAPI efi_net_reset(struct efi_simple_network *this,
  182. int extended_verification)
  183. {
  184. efi_status_t ret;
  185. EFI_ENTRY("%p, %x", this, extended_verification);
  186. /* Check parameters */
  187. if (!this) {
  188. ret = EFI_INVALID_PARAMETER;
  189. goto out;
  190. }
  191. switch (this->mode->state) {
  192. case EFI_NETWORK_INITIALIZED:
  193. break;
  194. case EFI_NETWORK_STOPPED:
  195. ret = EFI_NOT_STARTED;
  196. goto out;
  197. default:
  198. ret = EFI_DEVICE_ERROR;
  199. goto out;
  200. }
  201. this->mode->state = EFI_NETWORK_STARTED;
  202. ret = EFI_CALL(efi_net_initialize(this, 0, 0));
  203. out:
  204. return EFI_EXIT(ret);
  205. }
  206. /*
  207. * efi_net_shutdown() - shut down the network interface
  208. *
  209. * This function implements the Shutdown service of the
  210. * EFI_SIMPLE_NETWORK_PROTOCOL. See the Unified Extensible Firmware Interface
  211. * (UEFI) specification for details.
  212. *
  213. * @this: pointer to the protocol instance
  214. * Return: status code
  215. */
  216. static efi_status_t EFIAPI efi_net_shutdown(struct efi_simple_network *this)
  217. {
  218. efi_status_t ret = EFI_SUCCESS;
  219. EFI_ENTRY("%p", this);
  220. /* Check parameters */
  221. if (!this) {
  222. ret = EFI_INVALID_PARAMETER;
  223. goto out;
  224. }
  225. switch (this->mode->state) {
  226. case EFI_NETWORK_INITIALIZED:
  227. break;
  228. case EFI_NETWORK_STOPPED:
  229. ret = EFI_NOT_STARTED;
  230. goto out;
  231. default:
  232. ret = EFI_DEVICE_ERROR;
  233. goto out;
  234. }
  235. eth_halt();
  236. this->int_status = 0;
  237. wait_for_packet->is_signaled = false;
  238. this->mode->state = EFI_NETWORK_STARTED;
  239. out:
  240. return EFI_EXIT(ret);
  241. }
  242. /*
  243. * efi_net_receive_filters() - mange multicast receive filters
  244. *
  245. * This function implements the ReceiveFilters service of the
  246. * EFI_SIMPLE_NETWORK_PROTOCOL. See the Unified Extensible Firmware Interface
  247. * (UEFI) specification for details.
  248. *
  249. * @this: pointer to the protocol instance
  250. * @enable: bit mask of receive filters to enable
  251. * @disable: bit mask of receive filters to disable
  252. * @reset_mcast_filter: true resets contents of the filters
  253. * @mcast_filter_count: number of hardware MAC addresses in the new filters list
  254. * @mcast_filter: list of new filters
  255. * Return: status code
  256. */
  257. static efi_status_t EFIAPI efi_net_receive_filters
  258. (struct efi_simple_network *this, u32 enable, u32 disable,
  259. int reset_mcast_filter, ulong mcast_filter_count,
  260. struct efi_mac_address *mcast_filter)
  261. {
  262. EFI_ENTRY("%p, %x, %x, %x, %lx, %p", this, enable, disable,
  263. reset_mcast_filter, mcast_filter_count, mcast_filter);
  264. return EFI_EXIT(EFI_UNSUPPORTED);
  265. }
  266. /*
  267. * efi_net_station_address() - set the hardware MAC address
  268. *
  269. * This function implements the StationAddress service of the
  270. * EFI_SIMPLE_NETWORK_PROTOCOL. See the Unified Extensible Firmware Interface
  271. * (UEFI) specification for details.
  272. *
  273. * @this: pointer to the protocol instance
  274. * @reset: if true reset the address to default
  275. * @new_mac: new MAC address
  276. * Return: status code
  277. */
  278. static efi_status_t EFIAPI efi_net_station_address
  279. (struct efi_simple_network *this, int reset,
  280. struct efi_mac_address *new_mac)
  281. {
  282. EFI_ENTRY("%p, %x, %p", this, reset, new_mac);
  283. return EFI_EXIT(EFI_UNSUPPORTED);
  284. }
  285. /*
  286. * efi_net_statistics() - reset or collect statistics of the network interface
  287. *
  288. * This function implements the Statistics service of the
  289. * EFI_SIMPLE_NETWORK_PROTOCOL. See the Unified Extensible Firmware Interface
  290. * (UEFI) specification for details.
  291. *
  292. * @this: pointer to the protocol instance
  293. * @reset: if true, the statistics are reset
  294. * @stat_size: size of the statistics table
  295. * @stat_table: table to receive the statistics
  296. * Return: status code
  297. */
  298. static efi_status_t EFIAPI efi_net_statistics(struct efi_simple_network *this,
  299. int reset, ulong *stat_size,
  300. void *stat_table)
  301. {
  302. EFI_ENTRY("%p, %x, %p, %p", this, reset, stat_size, stat_table);
  303. return EFI_EXIT(EFI_UNSUPPORTED);
  304. }
  305. /*
  306. * efi_net_mcastiptomac() - translate multicast IP address to MAC address
  307. *
  308. * This function implements the MCastIPtoMAC service of the
  309. * EFI_SIMPLE_NETWORK_PROTOCOL. See the Unified Extensible Firmware Interface
  310. * (UEFI) specification for details.
  311. *
  312. * @this: pointer to the protocol instance
  313. * @ipv6: true if the IP address is an IPv6 address
  314. * @ip: IP address
  315. * @mac: MAC address
  316. * Return: status code
  317. */
  318. static efi_status_t EFIAPI efi_net_mcastiptomac(struct efi_simple_network *this,
  319. int ipv6,
  320. struct efi_ip_address *ip,
  321. struct efi_mac_address *mac)
  322. {
  323. efi_status_t ret = EFI_SUCCESS;
  324. EFI_ENTRY("%p, %x, %p, %p", this, ipv6, ip, mac);
  325. if (!this || !ip || !mac) {
  326. ret = EFI_INVALID_PARAMETER;
  327. goto out;
  328. }
  329. if (ipv6) {
  330. ret = EFI_UNSUPPORTED;
  331. goto out;
  332. }
  333. /* Multi-cast addresses are in the range 224.0.0.0 - 239.255.255.255 */
  334. if ((ip->ip_addr[0] & 0xf0) != 0xe0) {
  335. ret = EFI_INVALID_PARAMETER;
  336. goto out;
  337. };
  338. switch (this->mode->state) {
  339. case EFI_NETWORK_INITIALIZED:
  340. case EFI_NETWORK_STARTED:
  341. break;
  342. default:
  343. ret = EFI_NOT_STARTED;
  344. goto out;
  345. }
  346. memset(mac, 0, sizeof(struct efi_mac_address));
  347. /*
  348. * Copy lower 23 bits of IPv4 multi-cast address
  349. * RFC 1112, RFC 7042 2.1.1.
  350. */
  351. mac->mac_addr[0] = 0x01;
  352. mac->mac_addr[1] = 0x00;
  353. mac->mac_addr[2] = 0x5E;
  354. mac->mac_addr[3] = ip->ip_addr[1] & 0x7F;
  355. mac->mac_addr[4] = ip->ip_addr[2];
  356. mac->mac_addr[5] = ip->ip_addr[3];
  357. out:
  358. return EFI_EXIT(ret);
  359. }
  360. /**
  361. * efi_net_nvdata() - read or write NVRAM
  362. *
  363. * This function implements the GetStatus service of the Simple Network
  364. * Protocol. See the UEFI spec for details.
  365. *
  366. * @this: the instance of the Simple Network Protocol
  367. * @read_write: true for read, false for write
  368. * @offset: offset in NVRAM
  369. * @buffer_size: size of buffer
  370. * @buffer: buffer
  371. * Return: status code
  372. */
  373. static efi_status_t EFIAPI efi_net_nvdata(struct efi_simple_network *this,
  374. int read_write, ulong offset,
  375. ulong buffer_size, char *buffer)
  376. {
  377. EFI_ENTRY("%p, %x, %lx, %lx, %p", this, read_write, offset, buffer_size,
  378. buffer);
  379. return EFI_EXIT(EFI_UNSUPPORTED);
  380. }
  381. /**
  382. * efi_net_get_status() - get interrupt status
  383. *
  384. * This function implements the GetStatus service of the Simple Network
  385. * Protocol. See the UEFI spec for details.
  386. *
  387. * @this: the instance of the Simple Network Protocol
  388. * @int_status: interface status
  389. * @txbuf: transmission buffer
  390. */
  391. static efi_status_t EFIAPI efi_net_get_status(struct efi_simple_network *this,
  392. u32 *int_status, void **txbuf)
  393. {
  394. efi_status_t ret = EFI_SUCCESS;
  395. EFI_ENTRY("%p, %p, %p", this, int_status, txbuf);
  396. efi_timer_check();
  397. /* Check parameters */
  398. if (!this) {
  399. ret = EFI_INVALID_PARAMETER;
  400. goto out;
  401. }
  402. switch (this->mode->state) {
  403. case EFI_NETWORK_STOPPED:
  404. ret = EFI_NOT_STARTED;
  405. goto out;
  406. case EFI_NETWORK_STARTED:
  407. ret = EFI_DEVICE_ERROR;
  408. goto out;
  409. default:
  410. break;
  411. }
  412. if (int_status) {
  413. *int_status = this->int_status;
  414. this->int_status = 0;
  415. }
  416. if (txbuf)
  417. *txbuf = new_tx_packet;
  418. new_tx_packet = NULL;
  419. out:
  420. return EFI_EXIT(ret);
  421. }
  422. /**
  423. * efi_net_transmit() - transmit a packet
  424. *
  425. * This function implements the Transmit service of the Simple Network Protocol.
  426. * See the UEFI spec for details.
  427. *
  428. * @this: the instance of the Simple Network Protocol
  429. * @header_size: size of the media header
  430. * @buffer_size: size of the buffer to receive the packet
  431. * @buffer: buffer to receive the packet
  432. * @src_addr: source hardware MAC address
  433. * @dest_addr: destination hardware MAC address
  434. * @protocol: type of header to build
  435. * Return: status code
  436. */
  437. static efi_status_t EFIAPI efi_net_transmit
  438. (struct efi_simple_network *this, size_t header_size,
  439. size_t buffer_size, void *buffer,
  440. struct efi_mac_address *src_addr,
  441. struct efi_mac_address *dest_addr, u16 *protocol)
  442. {
  443. efi_status_t ret = EFI_SUCCESS;
  444. EFI_ENTRY("%p, %lu, %lu, %p, %p, %p, %p", this,
  445. (unsigned long)header_size, (unsigned long)buffer_size,
  446. buffer, src_addr, dest_addr, protocol);
  447. efi_timer_check();
  448. /* Check parameters */
  449. if (!this || !buffer) {
  450. ret = EFI_INVALID_PARAMETER;
  451. goto out;
  452. }
  453. /* We do not support jumbo packets */
  454. if (buffer_size > PKTSIZE_ALIGN) {
  455. ret = EFI_INVALID_PARAMETER;
  456. goto out;
  457. }
  458. /* At least the IP header has to fit into the buffer */
  459. if (buffer_size < this->mode->media_header_size) {
  460. ret = EFI_BUFFER_TOO_SMALL;
  461. goto out;
  462. }
  463. /*
  464. * TODO:
  465. * Support VLANs. Use net_set_ether() for copying the header. Use a
  466. * U_BOOT_ENV_CALLBACK to update the media header size.
  467. */
  468. if (header_size) {
  469. struct ethernet_hdr *header = buffer;
  470. if (!dest_addr || !protocol ||
  471. header_size != this->mode->media_header_size) {
  472. ret = EFI_INVALID_PARAMETER;
  473. goto out;
  474. }
  475. if (!src_addr)
  476. src_addr = &this->mode->current_address;
  477. memcpy(header->et_dest, dest_addr, ARP_HLEN);
  478. memcpy(header->et_src, src_addr, ARP_HLEN);
  479. header->et_protlen = htons(*protocol);
  480. }
  481. switch (this->mode->state) {
  482. case EFI_NETWORK_STOPPED:
  483. ret = EFI_NOT_STARTED;
  484. goto out;
  485. case EFI_NETWORK_STARTED:
  486. ret = EFI_DEVICE_ERROR;
  487. goto out;
  488. default:
  489. break;
  490. }
  491. /* Ethernet packets always fit, just bounce */
  492. memcpy(transmit_buffer, buffer, buffer_size);
  493. net_send_packet(transmit_buffer, buffer_size);
  494. new_tx_packet = buffer;
  495. this->int_status |= EFI_SIMPLE_NETWORK_TRANSMIT_INTERRUPT;
  496. out:
  497. return EFI_EXIT(ret);
  498. }
  499. /**
  500. * efi_net_receive() - receive a packet from a network interface
  501. *
  502. * This function implements the Receive service of the Simple Network Protocol.
  503. * See the UEFI spec for details.
  504. *
  505. * @this: the instance of the Simple Network Protocol
  506. * @header_size: size of the media header
  507. * @buffer_size: size of the buffer to receive the packet
  508. * @buffer: buffer to receive the packet
  509. * @src_addr: source MAC address
  510. * @dest_addr: destination MAC address
  511. * @protocol: protocol
  512. * Return: status code
  513. */
  514. static efi_status_t EFIAPI efi_net_receive
  515. (struct efi_simple_network *this, size_t *header_size,
  516. size_t *buffer_size, void *buffer,
  517. struct efi_mac_address *src_addr,
  518. struct efi_mac_address *dest_addr, u16 *protocol)
  519. {
  520. efi_status_t ret = EFI_SUCCESS;
  521. struct ethernet_hdr *eth_hdr;
  522. size_t hdr_size = sizeof(struct ethernet_hdr);
  523. u16 protlen;
  524. EFI_ENTRY("%p, %p, %p, %p, %p, %p, %p", this, header_size,
  525. buffer_size, buffer, src_addr, dest_addr, protocol);
  526. /* Execute events */
  527. efi_timer_check();
  528. /* Check parameters */
  529. if (!this || !buffer || !buffer_size) {
  530. ret = EFI_INVALID_PARAMETER;
  531. goto out;
  532. }
  533. switch (this->mode->state) {
  534. case EFI_NETWORK_STOPPED:
  535. ret = EFI_NOT_STARTED;
  536. goto out;
  537. case EFI_NETWORK_STARTED:
  538. ret = EFI_DEVICE_ERROR;
  539. goto out;
  540. default:
  541. break;
  542. }
  543. if (!rx_packet_num) {
  544. ret = EFI_NOT_READY;
  545. goto out;
  546. }
  547. /* Fill export parameters */
  548. eth_hdr = (struct ethernet_hdr *)receive_buffer[rx_packet_idx];
  549. protlen = ntohs(eth_hdr->et_protlen);
  550. if (protlen == 0x8100) {
  551. hdr_size += 4;
  552. protlen = ntohs(*(u16 *)&receive_buffer[rx_packet_idx][hdr_size - 2]);
  553. }
  554. if (header_size)
  555. *header_size = hdr_size;
  556. if (dest_addr)
  557. memcpy(dest_addr, eth_hdr->et_dest, ARP_HLEN);
  558. if (src_addr)
  559. memcpy(src_addr, eth_hdr->et_src, ARP_HLEN);
  560. if (protocol)
  561. *protocol = protlen;
  562. if (*buffer_size < receive_lengths[rx_packet_idx]) {
  563. /* Packet doesn't fit, try again with bigger buffer */
  564. *buffer_size = receive_lengths[rx_packet_idx];
  565. ret = EFI_BUFFER_TOO_SMALL;
  566. goto out;
  567. }
  568. /* Copy packet */
  569. memcpy(buffer, receive_buffer[rx_packet_idx],
  570. receive_lengths[rx_packet_idx]);
  571. *buffer_size = receive_lengths[rx_packet_idx];
  572. rx_packet_idx = (rx_packet_idx + 1) % ETH_PACKETS_BATCH_RECV;
  573. rx_packet_num--;
  574. if (rx_packet_num)
  575. wait_for_packet->is_signaled = true;
  576. else
  577. this->int_status &= ~EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT;
  578. out:
  579. return EFI_EXIT(ret);
  580. }
  581. /**
  582. * efi_net_set_dhcp_ack() - take note of a selected DHCP IP address
  583. *
  584. * This function is called by dhcp_handler().
  585. *
  586. * @pkt: packet received by dhcp_handler()
  587. * @len: length of the packet received
  588. */
  589. void efi_net_set_dhcp_ack(void *pkt, int len)
  590. {
  591. int maxsize = sizeof(*dhcp_ack);
  592. if (!dhcp_ack)
  593. dhcp_ack = malloc(maxsize);
  594. memcpy(dhcp_ack, pkt, min(len, maxsize));
  595. }
  596. /**
  597. * efi_net_push() - callback for received network packet
  598. *
  599. * This function is called when a network packet is received by eth_rx().
  600. *
  601. * @pkt: network packet
  602. * @len: length
  603. */
  604. static void efi_net_push(void *pkt, int len)
  605. {
  606. int rx_packet_next;
  607. /* Check that we at least received an Ethernet header */
  608. if (len < sizeof(struct ethernet_hdr))
  609. return;
  610. /* Check that the buffer won't overflow */
  611. if (len > PKTSIZE_ALIGN)
  612. return;
  613. /* Can't store more than pre-alloced buffer */
  614. if (rx_packet_num >= ETH_PACKETS_BATCH_RECV)
  615. return;
  616. rx_packet_next = (rx_packet_idx + rx_packet_num) %
  617. ETH_PACKETS_BATCH_RECV;
  618. memcpy(receive_buffer[rx_packet_next], pkt, len);
  619. receive_lengths[rx_packet_next] = len;
  620. rx_packet_num++;
  621. }
  622. /**
  623. * efi_network_timer_notify() - check if a new network packet has been received
  624. *
  625. * This notification function is called in every timer cycle.
  626. *
  627. * @event: the event for which this notification function is registered
  628. * @context: event context - not used in this function
  629. */
  630. static void EFIAPI efi_network_timer_notify(struct efi_event *event,
  631. void *context)
  632. {
  633. struct efi_simple_network *this = (struct efi_simple_network *)context;
  634. EFI_ENTRY("%p, %p", event, context);
  635. /*
  636. * Some network drivers do not support calling eth_rx() before
  637. * initialization.
  638. */
  639. if (!this || this->mode->state != EFI_NETWORK_INITIALIZED)
  640. goto out;
  641. if (!rx_packet_num) {
  642. push_packet = efi_net_push;
  643. eth_rx();
  644. push_packet = NULL;
  645. if (rx_packet_num) {
  646. this->int_status |=
  647. EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT;
  648. wait_for_packet->is_signaled = true;
  649. }
  650. }
  651. out:
  652. EFI_EXIT(EFI_SUCCESS);
  653. }
  654. static efi_status_t EFIAPI efi_pxe_base_code_start(
  655. struct efi_pxe_base_code_protocol *this,
  656. u8 use_ipv6)
  657. {
  658. return EFI_UNSUPPORTED;
  659. }
  660. static efi_status_t EFIAPI efi_pxe_base_code_stop(
  661. struct efi_pxe_base_code_protocol *this)
  662. {
  663. return EFI_UNSUPPORTED;
  664. }
  665. static efi_status_t EFIAPI efi_pxe_base_code_dhcp(
  666. struct efi_pxe_base_code_protocol *this,
  667. u8 sort_offers)
  668. {
  669. return EFI_UNSUPPORTED;
  670. }
  671. static efi_status_t EFIAPI efi_pxe_base_code_discover(
  672. struct efi_pxe_base_code_protocol *this,
  673. u16 type, u16 *layer, u8 bis,
  674. struct efi_pxe_base_code_discover_info *info)
  675. {
  676. return EFI_UNSUPPORTED;
  677. }
  678. static efi_status_t EFIAPI efi_pxe_base_code_mtftp(
  679. struct efi_pxe_base_code_protocol *this,
  680. u32 operation, void *buffer_ptr,
  681. u8 overwrite, efi_uintn_t *buffer_size,
  682. struct efi_ip_address server_ip, char *filename,
  683. struct efi_pxe_base_code_mtftp_info *info,
  684. u8 dont_use_buffer)
  685. {
  686. return EFI_UNSUPPORTED;
  687. }
  688. static efi_status_t EFIAPI efi_pxe_base_code_udp_write(
  689. struct efi_pxe_base_code_protocol *this,
  690. u16 op_flags, struct efi_ip_address *dest_ip,
  691. u16 *dest_port,
  692. struct efi_ip_address *gateway_ip,
  693. struct efi_ip_address *src_ip, u16 *src_port,
  694. efi_uintn_t *header_size, void *header_ptr,
  695. efi_uintn_t *buffer_size, void *buffer_ptr)
  696. {
  697. return EFI_UNSUPPORTED;
  698. }
  699. static efi_status_t EFIAPI efi_pxe_base_code_udp_read(
  700. struct efi_pxe_base_code_protocol *this,
  701. u16 op_flags, struct efi_ip_address *dest_ip,
  702. u16 *dest_port, struct efi_ip_address *src_ip,
  703. u16 *src_port, efi_uintn_t *header_size,
  704. void *header_ptr, efi_uintn_t *buffer_size,
  705. void *buffer_ptr)
  706. {
  707. return EFI_UNSUPPORTED;
  708. }
  709. static efi_status_t EFIAPI efi_pxe_base_code_set_ip_filter(
  710. struct efi_pxe_base_code_protocol *this,
  711. struct efi_pxe_base_code_filter *new_filter)
  712. {
  713. return EFI_UNSUPPORTED;
  714. }
  715. static efi_status_t EFIAPI efi_pxe_base_code_arp(
  716. struct efi_pxe_base_code_protocol *this,
  717. struct efi_ip_address *ip_addr,
  718. struct efi_mac_address *mac_addr)
  719. {
  720. return EFI_UNSUPPORTED;
  721. }
  722. static efi_status_t EFIAPI efi_pxe_base_code_set_parameters(
  723. struct efi_pxe_base_code_protocol *this,
  724. u8 *new_auto_arp, u8 *new_send_guid,
  725. u8 *new_ttl, u8 *new_tos,
  726. u8 *new_make_callback)
  727. {
  728. return EFI_UNSUPPORTED;
  729. }
  730. static efi_status_t EFIAPI efi_pxe_base_code_set_station_ip(
  731. struct efi_pxe_base_code_protocol *this,
  732. struct efi_ip_address *new_station_ip,
  733. struct efi_ip_address *new_subnet_mask)
  734. {
  735. return EFI_UNSUPPORTED;
  736. }
  737. static efi_status_t EFIAPI efi_pxe_base_code_set_packets(
  738. struct efi_pxe_base_code_protocol *this,
  739. u8 *new_dhcp_discover_valid,
  740. u8 *new_dhcp_ack_received,
  741. u8 *new_proxy_offer_received,
  742. u8 *new_pxe_discover_valid,
  743. u8 *new_pxe_reply_received,
  744. u8 *new_pxe_bis_reply_received,
  745. EFI_PXE_BASE_CODE_PACKET *new_dchp_discover,
  746. EFI_PXE_BASE_CODE_PACKET *new_dhcp_acc,
  747. EFI_PXE_BASE_CODE_PACKET *new_proxy_offer,
  748. EFI_PXE_BASE_CODE_PACKET *new_pxe_discover,
  749. EFI_PXE_BASE_CODE_PACKET *new_pxe_reply,
  750. EFI_PXE_BASE_CODE_PACKET *new_pxe_bis_reply)
  751. {
  752. return EFI_UNSUPPORTED;
  753. }
  754. /**
  755. * efi_net_register() - register the simple network protocol
  756. *
  757. * This gets called from do_bootefi_exec().
  758. */
  759. efi_status_t efi_net_register(void)
  760. {
  761. struct efi_net_obj *netobj = NULL;
  762. efi_status_t r;
  763. int i;
  764. if (!eth_get_dev()) {
  765. /* No network device active, don't expose any */
  766. return EFI_SUCCESS;
  767. }
  768. /* We only expose the "active" network device, so one is enough */
  769. netobj = calloc(1, sizeof(*netobj));
  770. if (!netobj)
  771. goto out_of_resources;
  772. /* Allocate an aligned transmit buffer */
  773. transmit_buffer = calloc(1, PKTSIZE_ALIGN + PKTALIGN);
  774. if (!transmit_buffer)
  775. goto out_of_resources;
  776. transmit_buffer = (void *)ALIGN((uintptr_t)transmit_buffer, PKTALIGN);
  777. /* Allocate a number of receive buffers */
  778. receive_buffer = calloc(ETH_PACKETS_BATCH_RECV,
  779. sizeof(*receive_buffer));
  780. if (!receive_buffer)
  781. goto out_of_resources;
  782. for (i = 0; i < ETH_PACKETS_BATCH_RECV; i++) {
  783. receive_buffer[i] = malloc(PKTSIZE_ALIGN);
  784. if (!receive_buffer[i])
  785. goto out_of_resources;
  786. }
  787. receive_lengths = calloc(ETH_PACKETS_BATCH_RECV,
  788. sizeof(*receive_lengths));
  789. if (!receive_lengths)
  790. goto out_of_resources;
  791. /* Hook net up to the device list */
  792. efi_add_handle(&netobj->header);
  793. /* Fill in object data */
  794. r = efi_add_protocol(&netobj->header, &efi_net_guid,
  795. &netobj->net);
  796. if (r != EFI_SUCCESS)
  797. goto failure_to_add_protocol;
  798. r = efi_add_protocol(&netobj->header, &efi_guid_device_path,
  799. efi_dp_from_eth());
  800. if (r != EFI_SUCCESS)
  801. goto failure_to_add_protocol;
  802. r = efi_add_protocol(&netobj->header, &efi_pxe_base_code_protocol_guid,
  803. &netobj->pxe);
  804. if (r != EFI_SUCCESS)
  805. goto failure_to_add_protocol;
  806. netobj->net.revision = EFI_SIMPLE_NETWORK_PROTOCOL_REVISION;
  807. netobj->net.start = efi_net_start;
  808. netobj->net.stop = efi_net_stop;
  809. netobj->net.initialize = efi_net_initialize;
  810. netobj->net.reset = efi_net_reset;
  811. netobj->net.shutdown = efi_net_shutdown;
  812. netobj->net.receive_filters = efi_net_receive_filters;
  813. netobj->net.station_address = efi_net_station_address;
  814. netobj->net.statistics = efi_net_statistics;
  815. netobj->net.mcastiptomac = efi_net_mcastiptomac;
  816. netobj->net.nvdata = efi_net_nvdata;
  817. netobj->net.get_status = efi_net_get_status;
  818. netobj->net.transmit = efi_net_transmit;
  819. netobj->net.receive = efi_net_receive;
  820. netobj->net.mode = &netobj->net_mode;
  821. netobj->net_mode.state = EFI_NETWORK_STOPPED;
  822. memcpy(netobj->net_mode.current_address.mac_addr, eth_get_ethaddr(), 6);
  823. netobj->net_mode.hwaddr_size = ARP_HLEN;
  824. netobj->net_mode.media_header_size = ETHER_HDR_SIZE;
  825. netobj->net_mode.max_packet_size = PKTSIZE;
  826. netobj->net_mode.if_type = ARP_ETHER;
  827. netobj->pxe.revision = EFI_PXE_BASE_CODE_PROTOCOL_REVISION;
  828. netobj->pxe.start = efi_pxe_base_code_start;
  829. netobj->pxe.stop = efi_pxe_base_code_stop;
  830. netobj->pxe.dhcp = efi_pxe_base_code_dhcp;
  831. netobj->pxe.discover = efi_pxe_base_code_discover;
  832. netobj->pxe.mtftp = efi_pxe_base_code_mtftp;
  833. netobj->pxe.udp_write = efi_pxe_base_code_udp_write;
  834. netobj->pxe.udp_read = efi_pxe_base_code_udp_read;
  835. netobj->pxe.set_ip_filter = efi_pxe_base_code_set_ip_filter;
  836. netobj->pxe.arp = efi_pxe_base_code_arp;
  837. netobj->pxe.set_parameters = efi_pxe_base_code_set_parameters;
  838. netobj->pxe.set_station_ip = efi_pxe_base_code_set_station_ip;
  839. netobj->pxe.set_packets = efi_pxe_base_code_set_packets;
  840. netobj->pxe.mode = &netobj->pxe_mode;
  841. if (dhcp_ack)
  842. netobj->pxe_mode.dhcp_ack = *dhcp_ack;
  843. /*
  844. * Create WaitForPacket event.
  845. */
  846. r = efi_create_event(EVT_NOTIFY_WAIT, TPL_CALLBACK,
  847. efi_network_timer_notify, NULL, NULL,
  848. &wait_for_packet);
  849. if (r != EFI_SUCCESS) {
  850. printf("ERROR: Failed to register network event\n");
  851. return r;
  852. }
  853. netobj->net.wait_for_packet = wait_for_packet;
  854. /*
  855. * Create a timer event.
  856. *
  857. * The notification function is used to check if a new network packet
  858. * has been received.
  859. *
  860. * iPXE is running at TPL_CALLBACK most of the time. Use a higher TPL.
  861. */
  862. r = efi_create_event(EVT_TIMER | EVT_NOTIFY_SIGNAL, TPL_NOTIFY,
  863. efi_network_timer_notify, &netobj->net, NULL,
  864. &network_timer_event);
  865. if (r != EFI_SUCCESS) {
  866. printf("ERROR: Failed to register network event\n");
  867. return r;
  868. }
  869. /* Network is time critical, create event in every timer cycle */
  870. r = efi_set_timer(network_timer_event, EFI_TIMER_PERIODIC, 0);
  871. if (r != EFI_SUCCESS) {
  872. printf("ERROR: Failed to set network timer\n");
  873. return r;
  874. }
  875. return EFI_SUCCESS;
  876. failure_to_add_protocol:
  877. printf("ERROR: Failure to add protocol\n");
  878. return r;
  879. out_of_resources:
  880. free(netobj);
  881. free(transmit_buffer);
  882. if (receive_buffer)
  883. for (i = 0; i < ETH_PACKETS_BATCH_RECV; i++)
  884. free(receive_buffer[i]);
  885. free(receive_buffer);
  886. free(receive_lengths);
  887. printf("ERROR: Out of memory\n");
  888. return EFI_OUT_OF_RESOURCES;
  889. }