You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

efi_snp.c 29KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022
  1. /*
  2. * Copyright (C) 2008 Michael Brown <mbrown@fensystems.co.uk>.
  3. *
  4. * This program is free software; you can redistribute it and/or
  5. * modify it under the terms of the GNU General Public License as
  6. * published by the Free Software Foundation; either version 2 of the
  7. * License, or any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful, but
  10. * WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. * General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program; if not, write to the Free Software
  16. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  17. * 02110-1301, USA.
  18. */
  19. FILE_LICENCE ( GPL2_OR_LATER );
  20. #include <stdlib.h>
  21. #include <string.h>
  22. #include <errno.h>
  23. #include <assert.h>
  24. #include <byteswap.h>
  25. #include <ipxe/netdevice.h>
  26. #include <ipxe/iobuf.h>
  27. #include <ipxe/in.h>
  28. #include <ipxe/pci.h>
  29. #include <ipxe/efi/efi.h>
  30. #include <ipxe/efi/efi_pci.h>
  31. #include <ipxe/efi/efi_driver.h>
  32. #include <ipxe/efi/efi_strings.h>
  33. #include <ipxe/efi/efi_snp.h>
  34. #include <config/general.h>
  35. /** EFI simple network protocol GUID */
  36. static EFI_GUID efi_simple_network_protocol_guid
  37. = EFI_SIMPLE_NETWORK_PROTOCOL_GUID;
  38. /** EFI device path protocol GUID */
  39. static EFI_GUID efi_device_path_protocol_guid
  40. = EFI_DEVICE_PATH_PROTOCOL_GUID;
  41. /** EFI network interface identifier GUID */
  42. static EFI_GUID efi_nii_protocol_guid
  43. = EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL_GUID;
  44. /** EFI network interface identifier GUID (extra special version) */
  45. static EFI_GUID efi_nii31_protocol_guid = {
  46. /* At some point, it seems that someone decided to change the
  47. * GUID. Current EFI builds ignore the older GUID, older EFI
  48. * builds ignore the newer GUID, so we have to expose both.
  49. */
  50. 0x1ACED566, 0x76ED, 0x4218,
  51. { 0xBC, 0x81, 0x76, 0x7F, 0x1F, 0x97, 0x7A, 0x89 }
  52. };
  53. /** EFI component name protocol */
  54. static EFI_GUID efi_component_name2_protocol_guid
  55. = EFI_COMPONENT_NAME2_PROTOCOL_GUID;
  56. /** List of SNP devices */
  57. static LIST_HEAD ( efi_snp_devices );
  58. /**
  59. * Set EFI SNP mode based on iPXE net device parameters
  60. *
  61. * @v snp SNP interface
  62. */
  63. static void efi_snp_set_mode ( struct efi_snp_device *snpdev ) {
  64. struct net_device *netdev = snpdev->netdev;
  65. EFI_SIMPLE_NETWORK_MODE *mode = &snpdev->mode;
  66. struct ll_protocol *ll_protocol = netdev->ll_protocol;
  67. unsigned int ll_addr_len = ll_protocol->ll_addr_len;
  68. mode->HwAddressSize = ll_addr_len;
  69. mode->MediaHeaderSize = ll_protocol->ll_header_len;
  70. mode->MaxPacketSize = netdev->max_pkt_len;
  71. mode->ReceiveFilterMask = ( EFI_SIMPLE_NETWORK_RECEIVE_UNICAST |
  72. EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST |
  73. EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST );
  74. assert ( ll_addr_len <= sizeof ( mode->CurrentAddress ) );
  75. memcpy ( &mode->CurrentAddress, netdev->ll_addr, ll_addr_len );
  76. memcpy ( &mode->BroadcastAddress, netdev->ll_broadcast, ll_addr_len );
  77. ll_protocol->init_addr ( netdev->hw_addr, &mode->PermanentAddress );
  78. mode->IfType = ntohs ( ll_protocol->ll_proto );
  79. mode->MacAddressChangeable = TRUE;
  80. mode->MediaPresentSupported = TRUE;
  81. mode->MediaPresent = ( netdev_link_ok ( netdev ) ? TRUE : FALSE );
  82. }
  83. /**
  84. * Poll net device and count received packets
  85. *
  86. * @v snpdev SNP device
  87. */
  88. static void efi_snp_poll ( struct efi_snp_device *snpdev ) {
  89. struct io_buffer *iobuf;
  90. unsigned int before = 0;
  91. unsigned int after = 0;
  92. unsigned int arrived;
  93. /* We have to report packet arrivals, and this is the easiest
  94. * way to fake it.
  95. */
  96. list_for_each_entry ( iobuf, &snpdev->netdev->rx_queue, list )
  97. before++;
  98. netdev_poll ( snpdev->netdev );
  99. list_for_each_entry ( iobuf, &snpdev->netdev->rx_queue, list )
  100. after++;
  101. arrived = ( after - before );
  102. snpdev->rx_count_interrupts += arrived;
  103. snpdev->rx_count_events += arrived;
  104. }
  105. /**
  106. * Change SNP state from "stopped" to "started"
  107. *
  108. * @v snp SNP interface
  109. * @ret efirc EFI status code
  110. */
  111. static EFI_STATUS EFIAPI
  112. efi_snp_start ( EFI_SIMPLE_NETWORK_PROTOCOL *snp ) {
  113. struct efi_snp_device *snpdev =
  114. container_of ( snp, struct efi_snp_device, snp );
  115. DBGC2 ( snpdev, "SNPDEV %p START\n", snpdev );
  116. snpdev->mode.State = EfiSimpleNetworkStarted;
  117. return 0;
  118. }
  119. /**
  120. * Change SNP state from "started" to "stopped"
  121. *
  122. * @v snp SNP interface
  123. * @ret efirc EFI status code
  124. */
  125. static EFI_STATUS EFIAPI
  126. efi_snp_stop ( EFI_SIMPLE_NETWORK_PROTOCOL *snp ) {
  127. struct efi_snp_device *snpdev =
  128. container_of ( snp, struct efi_snp_device, snp );
  129. DBGC2 ( snpdev, "SNPDEV %p STOP\n", snpdev );
  130. snpdev->mode.State = EfiSimpleNetworkStopped;
  131. return 0;
  132. }
  133. /**
  134. * Open the network device
  135. *
  136. * @v snp SNP interface
  137. * @v extra_rx_bufsize Extra RX buffer size, in bytes
  138. * @v extra_tx_bufsize Extra TX buffer size, in bytes
  139. * @ret efirc EFI status code
  140. */
  141. static EFI_STATUS EFIAPI
  142. efi_snp_initialize ( EFI_SIMPLE_NETWORK_PROTOCOL *snp,
  143. UINTN extra_rx_bufsize, UINTN extra_tx_bufsize ) {
  144. struct efi_snp_device *snpdev =
  145. container_of ( snp, struct efi_snp_device, snp );
  146. int rc;
  147. DBGC2 ( snpdev, "SNPDEV %p INITIALIZE (%ld extra RX, %ld extra TX)\n",
  148. snpdev, ( ( unsigned long ) extra_rx_bufsize ),
  149. ( ( unsigned long ) extra_tx_bufsize ) );
  150. if ( ( rc = netdev_open ( snpdev->netdev ) ) != 0 ) {
  151. DBGC ( snpdev, "SNPDEV %p could not open %s: %s\n",
  152. snpdev, snpdev->netdev->name, strerror ( rc ) );
  153. return RC_TO_EFIRC ( rc );
  154. }
  155. snpdev->mode.State = EfiSimpleNetworkInitialized;
  156. return 0;
  157. }
  158. /**
  159. * Reset the network device
  160. *
  161. * @v snp SNP interface
  162. * @v ext_verify Extended verification required
  163. * @ret efirc EFI status code
  164. */
  165. static EFI_STATUS EFIAPI
  166. efi_snp_reset ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, BOOLEAN ext_verify ) {
  167. struct efi_snp_device *snpdev =
  168. container_of ( snp, struct efi_snp_device, snp );
  169. int rc;
  170. DBGC2 ( snpdev, "SNPDEV %p RESET (%s extended verification)\n",
  171. snpdev, ( ext_verify ? "with" : "without" ) );
  172. netdev_close ( snpdev->netdev );
  173. snpdev->mode.State = EfiSimpleNetworkStarted;
  174. if ( ( rc = netdev_open ( snpdev->netdev ) ) != 0 ) {
  175. DBGC ( snpdev, "SNPDEV %p could not reopen %s: %s\n",
  176. snpdev, snpdev->netdev->name, strerror ( rc ) );
  177. return RC_TO_EFIRC ( rc );
  178. }
  179. snpdev->mode.State = EfiSimpleNetworkInitialized;
  180. return 0;
  181. }
  182. /**
  183. * Shut down the network device
  184. *
  185. * @v snp SNP interface
  186. * @ret efirc EFI status code
  187. */
  188. static EFI_STATUS EFIAPI
  189. efi_snp_shutdown ( EFI_SIMPLE_NETWORK_PROTOCOL *snp ) {
  190. struct efi_snp_device *snpdev =
  191. container_of ( snp, struct efi_snp_device, snp );
  192. DBGC2 ( snpdev, "SNPDEV %p SHUTDOWN\n", snpdev );
  193. netdev_close ( snpdev->netdev );
  194. snpdev->mode.State = EfiSimpleNetworkStarted;
  195. return 0;
  196. }
  197. /**
  198. * Manage receive filters
  199. *
  200. * @v snp SNP interface
  201. * @v enable Receive filters to enable
  202. * @v disable Receive filters to disable
  203. * @v mcast_reset Reset multicast filters
  204. * @v mcast_count Number of multicast filters
  205. * @v mcast Multicast filters
  206. * @ret efirc EFI status code
  207. */
  208. static EFI_STATUS EFIAPI
  209. efi_snp_receive_filters ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, UINT32 enable,
  210. UINT32 disable, BOOLEAN mcast_reset,
  211. UINTN mcast_count, EFI_MAC_ADDRESS *mcast ) {
  212. struct efi_snp_device *snpdev =
  213. container_of ( snp, struct efi_snp_device, snp );
  214. unsigned int i;
  215. DBGC2 ( snpdev, "SNPDEV %p RECEIVE_FILTERS %08x&~%08x%s %ld mcast\n",
  216. snpdev, enable, disable, ( mcast_reset ? " reset" : "" ),
  217. ( ( unsigned long ) mcast_count ) );
  218. for ( i = 0 ; i < mcast_count ; i++ ) {
  219. DBGC2_HDA ( snpdev, i, &mcast[i],
  220. snpdev->netdev->ll_protocol->ll_addr_len );
  221. }
  222. /* Lie through our teeth, otherwise MNP refuses to accept us */
  223. return 0;
  224. }
  225. /**
  226. * Set station address
  227. *
  228. * @v snp SNP interface
  229. * @v reset Reset to permanent address
  230. * @v new New station address
  231. * @ret efirc EFI status code
  232. */
  233. static EFI_STATUS EFIAPI
  234. efi_snp_station_address ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, BOOLEAN reset,
  235. EFI_MAC_ADDRESS *new ) {
  236. struct efi_snp_device *snpdev =
  237. container_of ( snp, struct efi_snp_device, snp );
  238. struct ll_protocol *ll_protocol = snpdev->netdev->ll_protocol;
  239. DBGC2 ( snpdev, "SNPDEV %p STATION_ADDRESS %s\n", snpdev,
  240. ( reset ? "reset" : ll_protocol->ntoa ( new ) ) );
  241. /* Set the MAC address */
  242. if ( reset )
  243. new = &snpdev->mode.PermanentAddress;
  244. memcpy ( snpdev->netdev->ll_addr, new, ll_protocol->ll_addr_len );
  245. /* MAC address changes take effect only on netdev_open() */
  246. if ( netdev_is_open ( snpdev->netdev ) ) {
  247. DBGC ( snpdev, "SNPDEV %p MAC address changed while net "
  248. "devive open\n", snpdev );
  249. }
  250. return 0;
  251. }
  252. /**
  253. * Get (or reset) statistics
  254. *
  255. * @v snp SNP interface
  256. * @v reset Reset statistics
  257. * @v stats_len Size of statistics table
  258. * @v stats Statistics table
  259. * @ret efirc EFI status code
  260. */
  261. static EFI_STATUS EFIAPI
  262. efi_snp_statistics ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, BOOLEAN reset,
  263. UINTN *stats_len, EFI_NETWORK_STATISTICS *stats ) {
  264. struct efi_snp_device *snpdev =
  265. container_of ( snp, struct efi_snp_device, snp );
  266. EFI_NETWORK_STATISTICS stats_buf;
  267. DBGC2 ( snpdev, "SNPDEV %p STATISTICS%s", snpdev,
  268. ( reset ? " reset" : "" ) );
  269. /* Gather statistics */
  270. memset ( &stats_buf, 0, sizeof ( stats_buf ) );
  271. stats_buf.TxGoodFrames = snpdev->netdev->tx_stats.good;
  272. stats_buf.TxDroppedFrames = snpdev->netdev->tx_stats.bad;
  273. stats_buf.TxTotalFrames = ( snpdev->netdev->tx_stats.good +
  274. snpdev->netdev->tx_stats.bad );
  275. stats_buf.RxGoodFrames = snpdev->netdev->rx_stats.good;
  276. stats_buf.RxDroppedFrames = snpdev->netdev->rx_stats.bad;
  277. stats_buf.RxTotalFrames = ( snpdev->netdev->rx_stats.good +
  278. snpdev->netdev->rx_stats.bad );
  279. if ( *stats_len > sizeof ( stats_buf ) )
  280. *stats_len = sizeof ( stats_buf );
  281. if ( stats )
  282. memcpy ( stats, &stats_buf, *stats_len );
  283. /* Reset statistics if requested to do so */
  284. if ( reset ) {
  285. memset ( &snpdev->netdev->tx_stats, 0,
  286. sizeof ( snpdev->netdev->tx_stats ) );
  287. memset ( &snpdev->netdev->rx_stats, 0,
  288. sizeof ( snpdev->netdev->rx_stats ) );
  289. }
  290. return 0;
  291. }
  292. /**
  293. * Convert multicast IP address to MAC address
  294. *
  295. * @v snp SNP interface
  296. * @v ipv6 Address is IPv6
  297. * @v ip IP address
  298. * @v mac MAC address
  299. * @ret efirc EFI status code
  300. */
  301. static EFI_STATUS EFIAPI
  302. efi_snp_mcast_ip_to_mac ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, BOOLEAN ipv6,
  303. EFI_IP_ADDRESS *ip, EFI_MAC_ADDRESS *mac ) {
  304. struct efi_snp_device *snpdev =
  305. container_of ( snp, struct efi_snp_device, snp );
  306. struct ll_protocol *ll_protocol = snpdev->netdev->ll_protocol;
  307. const char *ip_str;
  308. int rc;
  309. ip_str = ( ipv6 ? "(IPv6)" /* FIXME when we have inet6_ntoa() */ :
  310. inet_ntoa ( *( ( struct in_addr * ) ip ) ) );
  311. DBGC2 ( snpdev, "SNPDEV %p MCAST_IP_TO_MAC %s\n", snpdev, ip_str );
  312. /* Try to hash the address */
  313. if ( ( rc = ll_protocol->mc_hash ( ( ipv6 ? AF_INET6 : AF_INET ),
  314. ip, mac ) ) != 0 ) {
  315. DBGC ( snpdev, "SNPDEV %p could not hash %s: %s\n",
  316. snpdev, ip_str, strerror ( rc ) );
  317. return RC_TO_EFIRC ( rc );
  318. }
  319. return 0;
  320. }
  321. /**
  322. * Read or write non-volatile storage
  323. *
  324. * @v snp SNP interface
  325. * @v read Operation is a read
  326. * @v offset Starting offset within NVRAM
  327. * @v len Length of data buffer
  328. * @v data Data buffer
  329. * @ret efirc EFI status code
  330. */
  331. static EFI_STATUS EFIAPI
  332. efi_snp_nvdata ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, BOOLEAN read,
  333. UINTN offset, UINTN len, VOID *data ) {
  334. struct efi_snp_device *snpdev =
  335. container_of ( snp, struct efi_snp_device, snp );
  336. DBGC2 ( snpdev, "SNPDEV %p NVDATA %s %lx+%lx\n", snpdev,
  337. ( read ? "read" : "write" ), ( ( unsigned long ) offset ),
  338. ( ( unsigned long ) len ) );
  339. if ( ! read )
  340. DBGC2_HDA ( snpdev, offset, data, len );
  341. return EFI_UNSUPPORTED;
  342. }
  343. /**
  344. * Read interrupt status and TX recycled buffer status
  345. *
  346. * @v snp SNP interface
  347. * @v interrupts Interrupt status, or NULL
  348. * @v txbufs Recycled transmit buffer address, or NULL
  349. * @ret efirc EFI status code
  350. */
  351. static EFI_STATUS EFIAPI
  352. efi_snp_get_status ( EFI_SIMPLE_NETWORK_PROTOCOL *snp,
  353. UINT32 *interrupts, VOID **txbufs ) {
  354. struct efi_snp_device *snpdev =
  355. container_of ( snp, struct efi_snp_device, snp );
  356. DBGC2 ( snpdev, "SNPDEV %p GET_STATUS", snpdev );
  357. /* Poll the network device */
  358. efi_snp_poll ( snpdev );
  359. /* Interrupt status. In practice, this seems to be used only
  360. * to detect TX completions.
  361. */
  362. if ( interrupts ) {
  363. *interrupts = 0;
  364. /* Report TX completions once queue is empty; this
  365. * avoids having to add hooks in the net device layer.
  366. */
  367. if ( snpdev->tx_count_interrupts &&
  368. list_empty ( &snpdev->netdev->tx_queue ) ) {
  369. *interrupts |= EFI_SIMPLE_NETWORK_TRANSMIT_INTERRUPT;
  370. snpdev->tx_count_interrupts--;
  371. }
  372. /* Report RX */
  373. if ( snpdev->rx_count_interrupts ) {
  374. *interrupts |= EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT;
  375. snpdev->rx_count_interrupts--;
  376. }
  377. DBGC2 ( snpdev, " INTS:%02x", *interrupts );
  378. }
  379. /* TX completions. It would be possible to design a more
  380. * idiotic scheme for this, but it would be a challenge.
  381. * According to the UEFI header file, txbufs will be filled in
  382. * with a list of "recycled transmit buffers" (i.e. completed
  383. * TX buffers). Observant readers may care to note that
  384. * *txbufs is a void pointer. Precisely how a list of
  385. * completed transmit buffers is meant to be represented as an
  386. * array of voids is left as an exercise for the reader.
  387. *
  388. * The only users of this interface (MnpDxe/MnpIo.c and
  389. * PxeBcDxe/Bc.c within the EFI dev kit) both just poll until
  390. * seeing a non-NULL result return in txbufs. This is valid
  391. * provided that they do not ever attempt to transmit more
  392. * than one packet concurrently (and that TX never times out).
  393. */
  394. if ( txbufs ) {
  395. if ( snpdev->tx_count_txbufs &&
  396. list_empty ( &snpdev->netdev->tx_queue ) ) {
  397. *txbufs = "Which idiot designed this API?";
  398. snpdev->tx_count_txbufs--;
  399. } else {
  400. *txbufs = NULL;
  401. }
  402. DBGC2 ( snpdev, " TX:%s", ( *txbufs ? "some" : "none" ) );
  403. }
  404. DBGC2 ( snpdev, "\n" );
  405. return 0;
  406. }
  407. /**
  408. * Start packet transmission
  409. *
  410. * @v snp SNP interface
  411. * @v ll_header_len Link-layer header length, if to be filled in
  412. * @v len Length of data buffer
  413. * @v data Data buffer
  414. * @v ll_src Link-layer source address, if specified
  415. * @v ll_dest Link-layer destination address, if specified
  416. * @v net_proto Network-layer protocol (in host order)
  417. * @ret efirc EFI status code
  418. */
  419. static EFI_STATUS EFIAPI
  420. efi_snp_transmit ( EFI_SIMPLE_NETWORK_PROTOCOL *snp,
  421. UINTN ll_header_len, UINTN len, VOID *data,
  422. EFI_MAC_ADDRESS *ll_src, EFI_MAC_ADDRESS *ll_dest,
  423. UINT16 *net_proto ) {
  424. struct efi_snp_device *snpdev =
  425. container_of ( snp, struct efi_snp_device, snp );
  426. struct ll_protocol *ll_protocol = snpdev->netdev->ll_protocol;
  427. struct io_buffer *iobuf;
  428. size_t payload_len;
  429. int rc;
  430. EFI_STATUS efirc;
  431. DBGC2 ( snpdev, "SNPDEV %p TRANSMIT %p+%lx", snpdev, data,
  432. ( ( unsigned long ) len ) );
  433. if ( ll_header_len ) {
  434. if ( ll_src ) {
  435. DBGC2 ( snpdev, " src %s",
  436. ll_protocol->ntoa ( ll_src ) );
  437. }
  438. if ( ll_dest ) {
  439. DBGC2 ( snpdev, " dest %s",
  440. ll_protocol->ntoa ( ll_dest ) );
  441. }
  442. if ( net_proto ) {
  443. DBGC2 ( snpdev, " proto %04x", *net_proto );
  444. }
  445. }
  446. DBGC2 ( snpdev, "\n" );
  447. /* Sanity checks */
  448. if ( ll_header_len ) {
  449. if ( ll_header_len != ll_protocol->ll_header_len ) {
  450. DBGC ( snpdev, "SNPDEV %p TX invalid header length "
  451. "%ld\n", snpdev,
  452. ( ( unsigned long ) ll_header_len ) );
  453. efirc = EFI_INVALID_PARAMETER;
  454. goto err_sanity;
  455. }
  456. if ( len < ll_header_len ) {
  457. DBGC ( snpdev, "SNPDEV %p invalid packet length %ld\n",
  458. snpdev, ( ( unsigned long ) len ) );
  459. efirc = EFI_BUFFER_TOO_SMALL;
  460. goto err_sanity;
  461. }
  462. if ( ! ll_dest ) {
  463. DBGC ( snpdev, "SNPDEV %p TX missing destination "
  464. "address\n", snpdev );
  465. efirc = EFI_INVALID_PARAMETER;
  466. goto err_sanity;
  467. }
  468. if ( ! net_proto ) {
  469. DBGC ( snpdev, "SNPDEV %p TX missing network "
  470. "protocol\n", snpdev );
  471. efirc = EFI_INVALID_PARAMETER;
  472. goto err_sanity;
  473. }
  474. if ( ! ll_src )
  475. ll_src = &snpdev->mode.CurrentAddress;
  476. }
  477. /* Allocate buffer */
  478. payload_len = ( len - ll_protocol->ll_header_len );
  479. iobuf = alloc_iob ( MAX_LL_HEADER_LEN + ( ( payload_len > IOB_ZLEN ) ?
  480. payload_len : IOB_ZLEN ) );
  481. if ( ! iobuf ) {
  482. DBGC ( snpdev, "SNPDEV %p TX could not allocate %ld-byte "
  483. "buffer\n", snpdev, ( ( unsigned long ) len ) );
  484. efirc = EFI_DEVICE_ERROR;
  485. goto err_alloc_iob;
  486. }
  487. iob_reserve ( iobuf, ( MAX_LL_HEADER_LEN -
  488. ll_protocol->ll_header_len ) );
  489. memcpy ( iob_put ( iobuf, len ), data, len );
  490. /* Create link-layer header, if specified */
  491. if ( ll_header_len ) {
  492. iob_pull ( iobuf, ll_protocol->ll_header_len );
  493. if ( ( rc = ll_protocol->push ( snpdev->netdev,
  494. iobuf, ll_dest, ll_src,
  495. htons ( *net_proto ) )) != 0 ){
  496. DBGC ( snpdev, "SNPDEV %p TX could not construct "
  497. "header: %s\n", snpdev, strerror ( rc ) );
  498. efirc = RC_TO_EFIRC ( rc );
  499. goto err_ll_push;
  500. }
  501. }
  502. /* Transmit packet */
  503. if ( ( rc = netdev_tx ( snpdev->netdev, iob_disown ( iobuf ) ) ) != 0){
  504. DBGC ( snpdev, "SNPDEV %p TX could not transmit: %s\n",
  505. snpdev, strerror ( rc ) );
  506. efirc = RC_TO_EFIRC ( rc );
  507. goto err_tx;
  508. }
  509. /* Record transmission as outstanding */
  510. snpdev->tx_count_interrupts++;
  511. snpdev->tx_count_txbufs++;
  512. return 0;
  513. err_tx:
  514. err_ll_push:
  515. free_iob ( iobuf );
  516. err_alloc_iob:
  517. err_sanity:
  518. return efirc;
  519. }
  520. /**
  521. * Receive packet
  522. *
  523. * @v snp SNP interface
  524. * @v ll_header_len Link-layer header length, if to be filled in
  525. * @v len Length of data buffer
  526. * @v data Data buffer
  527. * @v ll_src Link-layer source address, if specified
  528. * @v ll_dest Link-layer destination address, if specified
  529. * @v net_proto Network-layer protocol (in host order)
  530. * @ret efirc EFI status code
  531. */
  532. static EFI_STATUS EFIAPI
  533. efi_snp_receive ( EFI_SIMPLE_NETWORK_PROTOCOL *snp,
  534. UINTN *ll_header_len, UINTN *len, VOID *data,
  535. EFI_MAC_ADDRESS *ll_src, EFI_MAC_ADDRESS *ll_dest,
  536. UINT16 *net_proto ) {
  537. struct efi_snp_device *snpdev =
  538. container_of ( snp, struct efi_snp_device, snp );
  539. struct ll_protocol *ll_protocol = snpdev->netdev->ll_protocol;
  540. struct io_buffer *iobuf;
  541. const void *iob_ll_dest;
  542. const void *iob_ll_src;
  543. uint16_t iob_net_proto;
  544. unsigned int iob_flags;
  545. int rc;
  546. EFI_STATUS efirc;
  547. DBGC2 ( snpdev, "SNPDEV %p RECEIVE %p(+%lx)", snpdev, data,
  548. ( ( unsigned long ) *len ) );
  549. /* Poll the network device */
  550. efi_snp_poll ( snpdev );
  551. /* Dequeue a packet, if one is available */
  552. iobuf = netdev_rx_dequeue ( snpdev->netdev );
  553. if ( ! iobuf ) {
  554. DBGC2 ( snpdev, "\n" );
  555. efirc = EFI_NOT_READY;
  556. goto out_no_packet;
  557. }
  558. DBGC2 ( snpdev, "+%zx\n", iob_len ( iobuf ) );
  559. /* Return packet to caller */
  560. memcpy ( data, iobuf->data, iob_len ( iobuf ) );
  561. *len = iob_len ( iobuf );
  562. /* Attempt to decode link-layer header */
  563. if ( ( rc = ll_protocol->pull ( snpdev->netdev, iobuf, &iob_ll_dest,
  564. &iob_ll_src, &iob_net_proto,
  565. &iob_flags ) ) != 0 ) {
  566. DBGC ( snpdev, "SNPDEV %p could not parse header: %s\n",
  567. snpdev, strerror ( rc ) );
  568. efirc = RC_TO_EFIRC ( rc );
  569. goto out_bad_ll_header;
  570. }
  571. /* Return link-layer header parameters to caller, if required */
  572. if ( ll_header_len )
  573. *ll_header_len = ll_protocol->ll_header_len;
  574. if ( ll_src )
  575. memcpy ( ll_src, iob_ll_src, ll_protocol->ll_addr_len );
  576. if ( ll_dest )
  577. memcpy ( ll_dest, iob_ll_dest, ll_protocol->ll_addr_len );
  578. if ( net_proto )
  579. *net_proto = ntohs ( iob_net_proto );
  580. efirc = 0;
  581. out_bad_ll_header:
  582. free_iob ( iobuf );
  583. out_no_packet:
  584. return efirc;
  585. }
  586. /**
  587. * Poll event
  588. *
  589. * @v event Event
  590. * @v context Event context
  591. */
  592. static VOID EFIAPI efi_snp_wait_for_packet ( EFI_EVENT event,
  593. VOID *context ) {
  594. EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
  595. struct efi_snp_device *snpdev = context;
  596. DBGCP ( snpdev, "SNPDEV %p WAIT_FOR_PACKET\n", snpdev );
  597. /* Do nothing unless the net device is open */
  598. if ( ! netdev_is_open ( snpdev->netdev ) )
  599. return;
  600. /* Poll the network device */
  601. efi_snp_poll ( snpdev );
  602. /* Fire event if packets have been received */
  603. if ( snpdev->rx_count_events != 0 ) {
  604. DBGC2 ( snpdev, "SNPDEV %p firing WaitForPacket event\n",
  605. snpdev );
  606. bs->SignalEvent ( event );
  607. snpdev->rx_count_events--;
  608. }
  609. }
  610. /** SNP interface */
  611. static EFI_SIMPLE_NETWORK_PROTOCOL efi_snp_device_snp = {
  612. .Revision = EFI_SIMPLE_NETWORK_PROTOCOL_REVISION,
  613. .Start = efi_snp_start,
  614. .Stop = efi_snp_stop,
  615. .Initialize = efi_snp_initialize,
  616. .Reset = efi_snp_reset,
  617. .Shutdown = efi_snp_shutdown,
  618. .ReceiveFilters = efi_snp_receive_filters,
  619. .StationAddress = efi_snp_station_address,
  620. .Statistics = efi_snp_statistics,
  621. .MCastIpToMac = efi_snp_mcast_ip_to_mac,
  622. .NvData = efi_snp_nvdata,
  623. .GetStatus = efi_snp_get_status,
  624. .Transmit = efi_snp_transmit,
  625. .Receive = efi_snp_receive,
  626. };
  627. /******************************************************************************
  628. *
  629. * Component name protocol
  630. *
  631. ******************************************************************************
  632. */
  633. /**
  634. * Look up driver name
  635. *
  636. * @v name2 Component name protocol
  637. * @v language Language to use
  638. * @v driver_name Driver name to fill in
  639. * @ret efirc EFI status code
  640. */
  641. static EFI_STATUS EFIAPI
  642. efi_snp_get_driver_name ( EFI_COMPONENT_NAME2_PROTOCOL *name2,
  643. CHAR8 *language __unused, CHAR16 **driver_name ) {
  644. struct efi_snp_device *snpdev =
  645. container_of ( name2, struct efi_snp_device, name2 );
  646. *driver_name = snpdev->driver_name;
  647. return 0;
  648. }
  649. /**
  650. * Look up controller name
  651. *
  652. * @v name2 Component name protocol
  653. * @v device Device
  654. * @v child Child device, or NULL
  655. * @v language Language to use
  656. * @v driver_name Device name to fill in
  657. * @ret efirc EFI status code
  658. */
  659. static EFI_STATUS EFIAPI
  660. efi_snp_get_controller_name ( EFI_COMPONENT_NAME2_PROTOCOL *name2,
  661. EFI_HANDLE device __unused,
  662. EFI_HANDLE child __unused,
  663. CHAR8 *language __unused,
  664. CHAR16 **controller_name ) {
  665. struct efi_snp_device *snpdev =
  666. container_of ( name2, struct efi_snp_device, name2 );
  667. *controller_name = snpdev->controller_name;
  668. return 0;
  669. }
  670. /******************************************************************************
  671. *
  672. * iPXE network driver
  673. *
  674. ******************************************************************************
  675. */
  676. /**
  677. * Locate SNP device corresponding to network device
  678. *
  679. * @v netdev Network device
  680. * @ret snp SNP device, or NULL if not found
  681. */
  682. static struct efi_snp_device * efi_snp_demux ( struct net_device *netdev ) {
  683. struct efi_snp_device *snpdev;
  684. list_for_each_entry ( snpdev, &efi_snp_devices, list ) {
  685. if ( snpdev->netdev == netdev )
  686. return snpdev;
  687. }
  688. return NULL;
  689. }
  690. /**
  691. * Create SNP device
  692. *
  693. * @v netdev Network device
  694. * @ret rc Return status code
  695. */
  696. static int efi_snp_probe ( struct net_device *netdev ) {
  697. EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
  698. struct efi_pci_device *efipci;
  699. struct efi_snp_device *snpdev;
  700. EFI_DEVICE_PATH_PROTOCOL *path_end;
  701. MAC_ADDR_DEVICE_PATH *macpath;
  702. size_t path_prefix_len = 0;
  703. EFI_STATUS efirc;
  704. int rc;
  705. /* Find EFI PCI device */
  706. efipci = efipci_find ( netdev->dev );
  707. if ( ! efipci ) {
  708. DBG ( "SNP skipping non-PCI device %s\n", netdev->name );
  709. rc = 0;
  710. goto err_no_pci;
  711. }
  712. /* Calculate device path prefix length */
  713. path_end = efi_devpath_end ( efipci->path );
  714. path_prefix_len = ( ( ( void * ) path_end ) -
  715. ( ( void * ) efipci->path ) );
  716. /* Allocate the SNP device */
  717. snpdev = zalloc ( sizeof ( *snpdev ) + path_prefix_len +
  718. sizeof ( *macpath ) );
  719. if ( ! snpdev ) {
  720. rc = -ENOMEM;
  721. goto err_alloc_snp;
  722. }
  723. snpdev->netdev = netdev_get ( netdev );
  724. snpdev->efipci = efipci;
  725. /* Sanity check */
  726. if ( netdev->ll_protocol->ll_addr_len > sizeof ( EFI_MAC_ADDRESS ) ) {
  727. DBGC ( snpdev, "SNPDEV %p cannot support link-layer address "
  728. "length %d for %s\n", snpdev,
  729. netdev->ll_protocol->ll_addr_len, netdev->name );
  730. rc = -ENOTSUP;
  731. goto err_ll_addr_len;
  732. }
  733. /* Populate the SNP structure */
  734. memcpy ( &snpdev->snp, &efi_snp_device_snp, sizeof ( snpdev->snp ) );
  735. snpdev->snp.Mode = &snpdev->mode;
  736. if ( ( efirc = bs->CreateEvent ( EVT_NOTIFY_WAIT, TPL_NOTIFY,
  737. efi_snp_wait_for_packet, snpdev,
  738. &snpdev->snp.WaitForPacket ) ) != 0 ){
  739. DBGC ( snpdev, "SNPDEV %p could not create event: %s\n",
  740. snpdev, efi_strerror ( efirc ) );
  741. rc = EFIRC_TO_RC ( efirc );
  742. goto err_create_event;
  743. }
  744. /* Populate the SNP mode structure */
  745. snpdev->mode.State = EfiSimpleNetworkStopped;
  746. efi_snp_set_mode ( snpdev );
  747. /* Populate the NII structure */
  748. snpdev->nii.Revision =
  749. EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL_REVISION;
  750. strncpy ( snpdev->nii.StringId, "iPXE",
  751. sizeof ( snpdev->nii.StringId ) );
  752. /* Populate the component name structure */
  753. efi_snprintf ( snpdev->driver_name,
  754. ( sizeof ( snpdev->driver_name ) /
  755. sizeof ( snpdev->driver_name[0] ) ),
  756. PRODUCT_SHORT_NAME " %s", netdev->dev->driver_name );
  757. efi_snprintf ( snpdev->controller_name,
  758. ( sizeof ( snpdev->controller_name ) /
  759. sizeof ( snpdev->controller_name[0] ) ),
  760. PRODUCT_SHORT_NAME " %s (%s)",
  761. netdev->name, netdev_addr ( netdev ) );
  762. snpdev->name2.GetDriverName = efi_snp_get_driver_name;
  763. snpdev->name2.GetControllerName = efi_snp_get_controller_name;
  764. snpdev->name2.SupportedLanguages = "en";
  765. /* Populate the device name */
  766. efi_snprintf ( snpdev->name, ( sizeof ( snpdev->name ) /
  767. sizeof ( snpdev->name[0] ) ),
  768. "%s", netdev->name );
  769. /* Populate the device path */
  770. memcpy ( &snpdev->path, efipci->path, path_prefix_len );
  771. macpath = ( ( ( void * ) &snpdev->path ) + path_prefix_len );
  772. path_end = ( ( void * ) ( macpath + 1 ) );
  773. memset ( macpath, 0, sizeof ( *macpath ) );
  774. macpath->Header.Type = MESSAGING_DEVICE_PATH;
  775. macpath->Header.SubType = MSG_MAC_ADDR_DP;
  776. macpath->Header.Length[0] = sizeof ( *macpath );
  777. memcpy ( &macpath->MacAddress, netdev->ll_addr,
  778. sizeof ( macpath->MacAddress ) );
  779. macpath->IfType = ntohs ( netdev->ll_protocol->ll_proto );
  780. memset ( path_end, 0, sizeof ( *path_end ) );
  781. path_end->Type = END_DEVICE_PATH_TYPE;
  782. path_end->SubType = END_ENTIRE_DEVICE_PATH_SUBTYPE;
  783. path_end->Length[0] = sizeof ( *path_end );
  784. /* Install the SNP */
  785. if ( ( efirc = bs->InstallMultipleProtocolInterfaces (
  786. &snpdev->handle,
  787. &efi_simple_network_protocol_guid, &snpdev->snp,
  788. &efi_device_path_protocol_guid, &snpdev->path,
  789. &efi_nii_protocol_guid, &snpdev->nii,
  790. &efi_nii31_protocol_guid, &snpdev->nii,
  791. &efi_component_name2_protocol_guid, &snpdev->name2,
  792. NULL ) ) != 0 ) {
  793. DBGC ( snpdev, "SNPDEV %p could not install protocols: "
  794. "%s\n", snpdev, efi_strerror ( efirc ) );
  795. rc = EFIRC_TO_RC ( efirc );
  796. goto err_install_protocol_interface;
  797. }
  798. /* Add as child of PCI device */
  799. if ( ( efirc = efipci_child_add ( efipci, snpdev->handle ) ) != 0 ) {
  800. DBGC ( snpdev, "SNPDEV %p could not become child of " PCI_FMT
  801. ": %s\n", snpdev, PCI_ARGS ( &efipci->pci ),
  802. efi_strerror ( efirc ) );
  803. rc = EFIRC_TO_RC ( efirc );
  804. goto err_efipci_child_add;
  805. }
  806. /* Install HII */
  807. if ( ( rc = efi_snp_hii_install ( snpdev ) ) != 0 ) {
  808. DBGC ( snpdev, "SNPDEV %p could not install HII: %s\n",
  809. snpdev, strerror ( rc ) );
  810. goto err_hii_install;
  811. }
  812. /* Add to list of SNP devices */
  813. list_add ( &snpdev->list, &efi_snp_devices );
  814. DBGC ( snpdev, "SNPDEV %p installed for %s as device %p\n",
  815. snpdev, netdev->name, snpdev->handle );
  816. return 0;
  817. efi_snp_hii_uninstall ( snpdev );
  818. err_hii_install:
  819. efipci_child_del ( efipci, snpdev->handle );
  820. err_efipci_child_add:
  821. bs->UninstallMultipleProtocolInterfaces (
  822. snpdev->handle,
  823. &efi_simple_network_protocol_guid, &snpdev->snp,
  824. &efi_device_path_protocol_guid, &snpdev->path,
  825. &efi_nii_protocol_guid, &snpdev->nii,
  826. &efi_nii31_protocol_guid, &snpdev->nii,
  827. &efi_component_name2_protocol_guid, &snpdev->name2,
  828. NULL );
  829. err_install_protocol_interface:
  830. bs->CloseEvent ( snpdev->snp.WaitForPacket );
  831. err_create_event:
  832. err_ll_addr_len:
  833. netdev_put ( netdev );
  834. free ( snpdev );
  835. err_alloc_snp:
  836. err_no_pci:
  837. return rc;
  838. }
  839. /**
  840. * Handle SNP device or link state change
  841. *
  842. * @v netdev Network device
  843. */
  844. static void efi_snp_notify ( struct net_device *netdev ) {
  845. struct efi_snp_device *snpdev;
  846. /* Locate SNP device */
  847. snpdev = efi_snp_demux ( netdev );
  848. if ( ! snpdev ) {
  849. DBG ( "SNP skipping non-SNP device %s\n", netdev->name );
  850. return;
  851. }
  852. /* Update link state */
  853. snpdev->mode.MediaPresent =
  854. ( netdev_link_ok ( netdev ) ? TRUE : FALSE );
  855. DBGC ( snpdev, "SNPDEV %p link is %s\n", snpdev,
  856. ( snpdev->mode.MediaPresent ? "up" : "down" ) );
  857. }
  858. /**
  859. * Destroy SNP device
  860. *
  861. * @v netdev Network device
  862. */
  863. static void efi_snp_remove ( struct net_device *netdev ) {
  864. EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
  865. struct efi_snp_device *snpdev;
  866. /* Locate SNP device */
  867. snpdev = efi_snp_demux ( netdev );
  868. if ( ! snpdev ) {
  869. DBG ( "SNP skipping non-SNP device %s\n", netdev->name );
  870. return;
  871. }
  872. /* Uninstall the SNP */
  873. efi_snp_hii_uninstall ( snpdev );
  874. efipci_child_del ( snpdev->efipci, snpdev->handle );
  875. list_del ( &snpdev->list );
  876. bs->UninstallMultipleProtocolInterfaces (
  877. snpdev->handle,
  878. &efi_simple_network_protocol_guid, &snpdev->snp,
  879. &efi_device_path_protocol_guid, &snpdev->path,
  880. &efi_nii_protocol_guid, &snpdev->nii,
  881. &efi_nii31_protocol_guid, &snpdev->nii,
  882. &efi_component_name2_protocol_guid, &snpdev->name2,
  883. NULL );
  884. bs->CloseEvent ( snpdev->snp.WaitForPacket );
  885. netdev_put ( snpdev->netdev );
  886. free ( snpdev );
  887. }
  888. /** SNP driver */
  889. struct net_driver efi_snp_driver __net_driver = {
  890. .name = "SNP",
  891. .probe = efi_snp_probe,
  892. .notify = efi_snp_notify,
  893. .remove = efi_snp_remove,
  894. };
  895. /**
  896. * Get most recently opened SNP device
  897. *
  898. * @ret snpdev Most recently opened SNP device, or NULL
  899. */
  900. struct efi_snp_device * last_opened_snpdev ( void ) {
  901. struct net_device *netdev;
  902. netdev = last_opened_netdev();
  903. if ( ! netdev )
  904. return NULL;
  905. return efi_snp_demux ( netdev );
  906. }