2 * Copyright (C) 2014 Michael Brown <mbrown@fensystems.co.uk>.
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.
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.
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
20 FILE_LICENCE ( GPL2_OR_LATER );
26 #include <ipxe/iobuf.h>
27 #include <ipxe/netdevice.h>
28 #include <ipxe/ethernet.h>
29 #include <ipxe/vsprintf.h>
30 #include <ipxe/efi/efi.h>
31 #include <ipxe/efi/Protocol/SimpleNetwork.h>
32 #include <ipxe/efi/efi_driver.h>
33 #include <ipxe/efi/efi_utils.h>
45 struct efi_device *efidev;
46 /** Simple network protocol */
47 EFI_SIMPLE_NETWORK_PROTOCOL *snp;
51 /** Maximum packet size
53 * This is calculated as the sum of MediaHeaderSize and
54 * MaxPacketSize, and may therefore be an overestimate.
58 /** Current transmit buffer */
59 struct io_buffer *txbuf;
60 /** Current receive buffer */
61 struct io_buffer *rxbuf;
64 /** Maximum number of received packets per poll */
65 #define SNP_RX_QUOTA 4
68 * Format SNP MAC address (for debugging)
71 * @v len Length of MAC address
72 * @ret text MAC address as text
74 static const char * snpnet_mac_text ( EFI_MAC_ADDRESS *mac, size_t len ) {
75 static char buf[ sizeof ( *mac ) * 3 /* "xx:" or "xx\0" */ ];
79 for ( i = 0 ; i < len ; i++ ) {
80 used += ssnprintf ( &buf[used], ( sizeof ( buf ) - used ),
81 "%s%02x", ( used ? ":" : "" ),
88 * Dump SNP mode information (for debugging)
90 * @v netdev Network device
92 static void snpnet_dump_mode ( struct net_device *netdev ) {
93 struct snp_nic *snp = netdev_priv ( netdev );
94 EFI_SIMPLE_NETWORK_MODE *mode = snp->snp->Mode;
95 size_t mac_len = mode->HwAddressSize;
98 /* Do nothing unless debugging is enabled */
102 DBGC2 ( snp, "SNP %s st %d type %d hdr %d pkt %d rxflt %#x/%#x%s "
103 "nvram %d acc %d mcast %d/%d\n", netdev->name, mode->State,
104 mode->IfType, mode->MediaHeaderSize, mode->MaxPacketSize,
105 mode->ReceiveFilterSetting, mode->ReceiveFilterMask,
106 ( mode->MultipleTxSupported ? " multitx" : "" ),
107 mode->NvRamSize, mode->NvRamAccessSize,
108 mode->MCastFilterCount, mode->MaxMCastFilterCount );
109 DBGC2 ( snp, "SNP %s hw %s", netdev->name,
110 snpnet_mac_text ( &mode->PermanentAddress, mac_len ) );
111 DBGC2 ( snp, " addr %s%s",
112 snpnet_mac_text ( &mode->CurrentAddress, mac_len ),
113 ( mode->MacAddressChangeable ? "" : "(f)" ) );
114 DBGC2 ( snp, " bcast %s\n",
115 snpnet_mac_text ( &mode->BroadcastAddress, mac_len ) );
116 for ( i = 0 ; i < mode->MCastFilterCount ; i++ ) {
117 DBGC2 ( snp, "SNP %s mcast %s\n", netdev->name,
118 snpnet_mac_text ( &mode->MCastFilter[i], mac_len ) );
120 DBGC2 ( snp, "SNP %s media %s\n", netdev->name,
121 ( mode->MediaPresentSupported ?
122 ( mode->MediaPresent ? "present" : "not present" ) :
123 "presence not supported" ) );
129 * @v netdev Network device
131 static void snpnet_check_link ( struct net_device *netdev ) {
132 struct snp_nic *snp = netdev_priv ( netdev );
133 EFI_SIMPLE_NETWORK_MODE *mode = snp->snp->Mode;
135 /* Do nothing unless media presence detection is supported */
136 if ( ! mode->MediaPresentSupported )
139 /* Report any link status change */
140 if ( mode->MediaPresent && ( ! netdev_link_ok ( netdev ) ) ) {
141 netdev_link_up ( netdev );
142 } else if ( ( ! mode->MediaPresent ) && netdev_link_ok ( netdev ) ) {
143 netdev_link_down ( netdev );
150 * @v netdev Network device
151 * @v iobuf I/O buffer
152 * @ret rc Return status code
154 static int snpnet_transmit ( struct net_device *netdev,
155 struct io_buffer *iobuf ) {
156 struct snp_nic *snp = netdev_priv ( netdev );
160 /* Defer the packet if there is already a transmission in progress */
162 netdev_tx_defer ( netdev, iobuf );
166 /* Transmit packet */
167 if ( ( efirc = snp->snp->Transmit ( snp->snp, 0, iob_len ( iobuf ),
168 iobuf->data, NULL, NULL,
170 rc = -EEFI ( efirc );
171 DBGC ( snp, "SNP %s could not transmit: %s\n",
172 netdev->name, strerror ( rc ) );
181 * Poll for completed packets
183 * @v netdev Network device
185 static void snpnet_poll_tx ( struct net_device *netdev ) {
186 struct snp_nic *snp = netdev->priv;
187 struct io_buffer *iobuf;
194 if ( ( efirc = snp->snp->GetStatus ( snp->snp, &irq, &txbuf ) ) != 0 ) {
195 rc = -EEFI ( efirc );
196 DBGC ( snp, "SNP %s could not get status: %s\n",
197 netdev->name, strerror ( rc ) );
198 netdev_rx_err ( netdev, NULL, rc );
202 /* Do nothing unless we have a completion */
207 if ( ! snp->txbuf ) {
208 DBGC ( snp, "SNP %s reported spurious TX completion\n",
210 netdev_tx_err ( netdev, NULL, -EPIPE );
214 /* Complete transmission */
217 netdev_tx_complete ( netdev, iobuf );
221 * Poll for received packets
223 * @v netdev Network device
225 static void snpnet_poll_rx ( struct net_device *netdev ) {
226 struct snp_nic *snp = netdev->priv;
232 /* Retrieve up to SNP_RX_QUOTA packets */
233 for ( quota = SNP_RX_QUOTA ; quota ; quota-- ) {
235 /* Allocate buffer, if required */
236 if ( ! snp->rxbuf ) {
237 snp->rxbuf = alloc_iob ( snp->mtu );
238 if ( ! snp->rxbuf ) {
239 /* Leave for next poll */
245 len = iob_tailroom ( snp->rxbuf );
246 if ( ( efirc = snp->snp->Receive ( snp->snp, NULL, &len,
247 snp->rxbuf->data, NULL,
248 NULL, NULL ) ) != 0 ) {
250 /* EFI_NOT_READY is just the usual "no packet"
251 * status indication; ignore it.
253 if ( efirc == EFI_NOT_READY )
256 /* Anything else is an error */
257 rc = -EEFI ( efirc );
258 DBGC ( snp, "SNP %s could not receive: %s\n",
259 netdev->name, strerror ( rc ) );
260 netdev_rx_err ( netdev, NULL, rc );
264 /* Hand off to network stack */
265 iob_put ( snp->rxbuf, len );
266 netdev_rx ( netdev, snp->rxbuf );
272 * Poll for completed packets
274 * @v netdev Network device
276 static void snpnet_poll ( struct net_device *netdev ) {
278 /* Process any TX completions */
279 snpnet_poll_tx ( netdev );
281 /* Process any RX completions */
282 snpnet_poll_rx ( netdev );
284 /* Check for link state changes */
285 snpnet_check_link ( netdev );
289 * Set receive filters
291 * @v netdev Network device
292 * @ret rc Return status code
294 static int snpnet_rx_filters ( struct net_device *netdev ) {
295 struct snp_nic *snp = netdev->priv;
297 snp->snp->Mode->ReceiveFilterMask,
298 ( EFI_SIMPLE_NETWORK_RECEIVE_UNICAST |
299 EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST |
300 EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST ),
301 ( EFI_SIMPLE_NETWORK_RECEIVE_UNICAST |
302 EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST ),
303 ( EFI_SIMPLE_NETWORK_RECEIVE_UNICAST ),
309 /* Try possible receive filters in turn */
310 for ( i = 0; i < ( sizeof ( filters ) / sizeof ( filters[0] ) ); i++ ) {
311 efirc = snp->snp->ReceiveFilters ( snp->snp, filters[i],
315 rc = -EEFI ( efirc );
316 DBGC ( snp, "SNP %s could not set receive filters %#02x (have "
317 "%#02x): %s\n", netdev->name, filters[i],
318 snp->snp->Mode->ReceiveFilterSetting, strerror ( rc ) );
325 * Open network device
327 * @v netdev Network device
328 * @ret rc Return status code
330 static int snpnet_open ( struct net_device *netdev ) {
331 struct snp_nic *snp = netdev->priv;
332 EFI_MAC_ADDRESS *mac = ( ( void * ) netdev->ll_addr );
336 /* Try setting MAC address (before initialising) */
337 if ( ( efirc = snp->snp->StationAddress ( snp->snp, FALSE, mac ) ) !=0){
338 rc = -EEFI ( efirc );
339 DBGC ( snp, "SNP %s could not set station address before "
340 "initialising: %s\n", netdev->name, strerror ( rc ) );
345 if ( ( efirc = snp->snp->Initialize ( snp->snp, 0, 0 ) ) != 0 ) {
346 rc = -EEFI ( efirc );
347 snpnet_dump_mode ( netdev );
348 DBGC ( snp, "SNP %s could not initialise: %s\n",
349 netdev->name, strerror ( rc ) );
353 /* Try setting MAC address (after initialising) */
354 if ( ( efirc = snp->snp->StationAddress ( snp->snp, FALSE, mac ) ) !=0){
355 rc = -EEFI ( efirc );
356 DBGC ( snp, "SNP %s could not set station address after "
357 "initialising: %s\n", netdev->name, strerror ( rc ) );
361 /* Set receive filters */
362 if ( ( rc = snpnet_rx_filters ( netdev ) ) != 0 ) {
366 /* Dump mode information (for debugging) */
367 snpnet_dump_mode ( netdev );
373 * Close network device
375 * @v netdev Network device
377 static void snpnet_close ( struct net_device *netdev ) {
378 struct snp_nic *snp = netdev->priv;
383 if ( ( efirc = snp->snp->Shutdown ( snp->snp ) ) != 0 ) {
384 rc = -EEFI ( efirc );
385 DBGC ( snp, "SNP %s could not shut down: %s\n",
386 netdev->name, strerror ( rc ) );
387 /* Nothing we can do about this */
390 /* Discard transmit buffer, if applicable */
392 netdev_tx_complete_err ( netdev, snp->txbuf, -ECANCELED );
396 /* Discard receive buffer, if applicable */
398 free_iob ( snp->rxbuf );
403 /** SNP network device operations */
404 static struct net_device_operations snpnet_operations = {
406 .close = snpnet_close,
407 .transmit = snpnet_transmit,
412 * Attach driver to device
414 * @v efidev EFI device
415 * @ret rc Return status code
417 int snpnet_start ( struct efi_device *efidev ) {
418 EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
419 EFI_HANDLE device = efidev->device;
420 EFI_SIMPLE_NETWORK_MODE *mode;
421 struct net_device *netdev;
427 /* Open SNP protocol */
428 if ( ( efirc = bs->OpenProtocol ( device,
429 &efi_simple_network_protocol_guid,
430 &interface, efi_image_handle, device,
431 ( EFI_OPEN_PROTOCOL_BY_DRIVER |
432 EFI_OPEN_PROTOCOL_EXCLUSIVE )))!=0){
433 rc = -EEFI ( efirc );
434 DBGC ( device, "SNP %p %s cannot open SNP protocol: %s\n",
435 device, efi_handle_name ( device ), strerror ( rc ) );
436 DBGC_EFI_OPENERS ( device, device,
437 &efi_simple_network_protocol_guid );
438 goto err_open_protocol;
441 /* Allocate and initialise structure */
442 netdev = alloc_etherdev ( sizeof ( *snp ) );
447 netdev_init ( netdev, &snpnet_operations );
449 snp->efidev = efidev;
450 snp->snp = interface;
451 mode = snp->snp->Mode;
452 efidev_set_drvdata ( efidev, netdev );
454 /* Populate underlying device information */
455 efi_device_info ( device, "SNP", &snp->dev );
456 snp->dev.driver_name = "SNP";
457 snp->dev.parent = &efidev->dev;
458 list_add ( &snp->dev.siblings, &efidev->dev.children );
459 INIT_LIST_HEAD ( &snp->dev.children );
460 netdev->dev = &snp->dev;
462 /* Bring to the Started state */
463 if ( ( mode->State == EfiSimpleNetworkStopped ) &&
464 ( ( efirc = snp->snp->Start ( snp->snp ) ) != 0 ) ) {
465 rc = -EEFI ( efirc );
466 DBGC ( device, "SNP %p %s could not start: %s\n", device,
467 efi_handle_name ( device ), strerror ( rc ) );
470 if ( ( mode->State == EfiSimpleNetworkInitialized ) &&
471 ( ( efirc = snp->snp->Shutdown ( snp->snp ) ) != 0 ) ) {
472 rc = -EEFI ( efirc );
473 DBGC ( device, "SNP %p %s could not shut down: %s\n", device,
474 efi_handle_name ( device ), strerror ( rc ) );
478 /* Populate network device parameters */
479 if ( mode->HwAddressSize != netdev->ll_protocol->hw_addr_len ) {
480 DBGC ( device, "SNP %p %s has invalid hardware address "
481 "length %d\n", device, efi_handle_name ( device ),
482 mode->HwAddressSize );
484 goto err_hw_addr_len;
486 memcpy ( netdev->hw_addr, &mode->PermanentAddress,
487 netdev->ll_protocol->hw_addr_len );
488 if ( mode->HwAddressSize != netdev->ll_protocol->ll_addr_len ) {
489 DBGC ( device, "SNP %p %s has invalid link-layer address "
490 "length %d\n", device, efi_handle_name ( device ),
491 mode->HwAddressSize );
493 goto err_ll_addr_len;
495 memcpy ( netdev->ll_addr, &mode->CurrentAddress,
496 netdev->ll_protocol->ll_addr_len );
497 snp->mtu = ( snp->snp->Mode->MaxPacketSize +
498 snp->snp->Mode->MediaHeaderSize );
500 /* Register network device */
501 if ( ( rc = register_netdev ( netdev ) ) != 0 )
502 goto err_register_netdev;
503 DBGC ( device, "SNP %p %s registered as %s\n",
504 device, efi_handle_name ( device ), netdev->name );
506 /* Set initial link state */
507 if ( snp->snp->Mode->MediaPresentSupported ) {
508 snpnet_check_link ( netdev );
510 netdev_link_up ( netdev );
515 unregister_netdev ( netdev );
521 list_del ( &snp->dev.siblings );
522 netdev_nullify ( netdev );
523 netdev_put ( netdev );
525 bs->CloseProtocol ( device, &efi_simple_network_protocol_guid,
526 efi_image_handle, device );
532 * Detach driver from device
534 * @v efidev EFI device
536 void snpnet_stop ( struct efi_device *efidev ) {
537 EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
538 struct net_device *netdev = efidev_get_drvdata ( efidev );
539 struct snp_nic *snp = netdev->priv;
540 EFI_HANDLE device = efidev->device;
544 /* Unregister network device */
545 unregister_netdev ( netdev );
547 /* Stop SNP protocol */
548 if ( ( efirc = snp->snp->Stop ( snp->snp ) ) != 0 ) {
549 rc = -EEFI ( efirc );
550 DBGC ( device, "SNP %p %s could not stop: %s\n", device,
551 efi_handle_name ( device ), strerror ( rc ) );
552 /* Nothing we can do about this */
555 /* Free network device */
556 list_del ( &snp->dev.siblings );
557 netdev_nullify ( netdev );
558 netdev_put ( netdev );
560 /* Close SNP protocol */
561 bs->CloseProtocol ( device, &efi_simple_network_protocol_guid,
562 efi_image_handle, device );