00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 FILE_LICENCE ( GPL2_OR_LATER );
00020
00021 #include <stdlib.h>
00022 #include <string.h>
00023 #include <errno.h>
00024 #include <assert.h>
00025 #include <byteswap.h>
00026 #include <gpxe/netdevice.h>
00027 #include <gpxe/iobuf.h>
00028 #include <gpxe/in.h>
00029 #include <gpxe/pci.h>
00030 #include <gpxe/efi/efi.h>
00031 #include <gpxe/efi/Protocol/DriverBinding.h>
00032 #include <gpxe/efi/Protocol/PciIo.h>
00033 #include <gpxe/efi/Protocol/SimpleNetwork.h>
00034 #include <gpxe/efi/Protocol/ComponentName2.h>
00035 #include <gpxe/efi/Protocol/NetworkInterfaceIdentifier.h>
00036 #include <config/general.h>
00037
00038
00039
00040
00041
00042
00043
00044
00045 struct efi_snp_device {
00046
00047 struct net_device *netdev;
00048
00049 EFI_HANDLE handle;
00050
00051 EFI_SIMPLE_NETWORK_PROTOCOL snp;
00052
00053 EFI_SIMPLE_NETWORK_MODE mode;
00054
00055
00056
00057
00058 unsigned int tx_count_interrupts;
00059
00060
00061
00062
00063 unsigned int tx_count_txbufs;
00064
00065 unsigned int rx_count_interrupts;
00066
00067 unsigned int rx_count_events;
00068
00069 EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL nii;
00070
00071 wchar_t name[ sizeof ( ( ( struct net_device * ) NULL )->name ) ];
00072
00073
00074
00075
00076
00077 EFI_DEVICE_PATH_PROTOCOL path;
00078 };
00079
00080
00081 static EFI_GUID efi_simple_network_protocol_guid
00082 = EFI_SIMPLE_NETWORK_PROTOCOL_GUID;
00083
00084
00085 static EFI_GUID efi_driver_binding_protocol_guid
00086 = EFI_DRIVER_BINDING_PROTOCOL_GUID;
00087
00088
00089 static EFI_GUID efi_component_name2_protocol_guid
00090 = EFI_COMPONENT_NAME2_PROTOCOL_GUID;
00091
00092
00093 static EFI_GUID efi_device_path_protocol_guid
00094 = EFI_DEVICE_PATH_PROTOCOL_GUID;
00095
00096
00097 static EFI_GUID efi_nii_protocol_guid
00098 = EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL_GUID;
00099
00100
00101 static EFI_GUID efi_nii31_protocol_guid = {
00102
00103
00104
00105
00106 0x1ACED566, 0x76ED, 0x4218,
00107 { 0xBC, 0x81, 0x76, 0x7F, 0x1F, 0x97, 0x7A, 0x89 }
00108 };
00109
00110
00111 static EFI_GUID efi_pci_io_protocol_guid
00112 = EFI_PCI_IO_PROTOCOL_GUID;
00113
00114
00115
00116
00117
00118
00119 static void efi_snp_set_mode ( struct efi_snp_device *snpdev ) {
00120 struct net_device *netdev = snpdev->netdev;
00121 EFI_SIMPLE_NETWORK_MODE *mode = &snpdev->mode;
00122 struct ll_protocol *ll_protocol = netdev->ll_protocol;
00123 unsigned int ll_addr_len = ll_protocol->ll_addr_len;
00124
00125 mode->HwAddressSize = ll_addr_len;
00126 mode->MediaHeaderSize = ll_protocol->ll_header_len;
00127 mode->MaxPacketSize = netdev->max_pkt_len;
00128 mode->ReceiveFilterMask = ( EFI_SIMPLE_NETWORK_RECEIVE_UNICAST |
00129 EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST |
00130 EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST );
00131 assert ( ll_addr_len <= sizeof ( mode->CurrentAddress ) );
00132 memcpy ( &mode->CurrentAddress, netdev->ll_addr, ll_addr_len );
00133 memcpy ( &mode->BroadcastAddress, netdev->ll_broadcast, ll_addr_len );
00134 ll_protocol->init_addr ( netdev->hw_addr, &mode->PermanentAddress );
00135 mode->IfType = ntohs ( ll_protocol->ll_proto );
00136 mode->MacAddressChangeable = TRUE;
00137 mode->MediaPresentSupported = TRUE;
00138 mode->MediaPresent = ( netdev_link_ok ( netdev ) ? TRUE : FALSE );
00139 }
00140
00141
00142
00143
00144
00145
00146 static void efi_snp_poll ( struct efi_snp_device *snpdev ) {
00147 struct io_buffer *iobuf;
00148 unsigned int before = 0;
00149 unsigned int after = 0;
00150 unsigned int arrived;
00151
00152
00153
00154
00155 list_for_each_entry ( iobuf, &snpdev->netdev->rx_queue, list )
00156 before++;
00157 netdev_poll ( snpdev->netdev );
00158 list_for_each_entry ( iobuf, &snpdev->netdev->rx_queue, list )
00159 after++;
00160 arrived = ( after - before );
00161
00162 snpdev->rx_count_interrupts += arrived;
00163 snpdev->rx_count_events += arrived;
00164 }
00165
00166
00167
00168
00169
00170
00171
00172 static EFI_STATUS EFIAPI
00173 efi_snp_start ( EFI_SIMPLE_NETWORK_PROTOCOL *snp ) {
00174 struct efi_snp_device *snpdev =
00175 container_of ( snp, struct efi_snp_device, snp );
00176
00177 DBGC2 ( snpdev, "SNPDEV %p START\n", snpdev );
00178
00179 snpdev->mode.State = EfiSimpleNetworkStarted;
00180 return 0;
00181 }
00182
00183
00184
00185
00186
00187
00188
00189 static EFI_STATUS EFIAPI
00190 efi_snp_stop ( EFI_SIMPLE_NETWORK_PROTOCOL *snp ) {
00191 struct efi_snp_device *snpdev =
00192 container_of ( snp, struct efi_snp_device, snp );
00193
00194 DBGC2 ( snpdev, "SNPDEV %p STOP\n", snpdev );
00195
00196 snpdev->mode.State = EfiSimpleNetworkStopped;
00197 return 0;
00198 }
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208 static EFI_STATUS EFIAPI
00209 efi_snp_initialize ( EFI_SIMPLE_NETWORK_PROTOCOL *snp,
00210 UINTN extra_rx_bufsize, UINTN extra_tx_bufsize ) {
00211 struct efi_snp_device *snpdev =
00212 container_of ( snp, struct efi_snp_device, snp );
00213 int rc;
00214
00215 DBGC2 ( snpdev, "SNPDEV %p INITIALIZE (%ld extra RX, %ld extra TX)\n",
00216 snpdev, ( ( unsigned long ) extra_rx_bufsize ),
00217 ( ( unsigned long ) extra_tx_bufsize ) );
00218
00219 if ( ( rc = netdev_open ( snpdev->netdev ) ) != 0 ) {
00220 DBGC ( snpdev, "SNPDEV %p could not open %s: %s\n",
00221 snpdev, snpdev->netdev->name, strerror ( rc ) );
00222 return RC_TO_EFIRC ( rc );
00223 }
00224
00225 snpdev->mode.State = EfiSimpleNetworkInitialized;
00226 return 0;
00227 }
00228
00229
00230
00231
00232
00233
00234
00235
00236 static EFI_STATUS EFIAPI
00237 efi_snp_reset ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, BOOLEAN ext_verify ) {
00238 struct efi_snp_device *snpdev =
00239 container_of ( snp, struct efi_snp_device, snp );
00240 int rc;
00241
00242 DBGC2 ( snpdev, "SNPDEV %p RESET (%s extended verification)\n",
00243 snpdev, ( ext_verify ? "with" : "without" ) );
00244
00245 netdev_close ( snpdev->netdev );
00246 snpdev->mode.State = EfiSimpleNetworkStarted;
00247
00248 if ( ( rc = netdev_open ( snpdev->netdev ) ) != 0 ) {
00249 DBGC ( snpdev, "SNPDEV %p could not reopen %s: %s\n",
00250 snpdev, snpdev->netdev->name, strerror ( rc ) );
00251 return RC_TO_EFIRC ( rc );
00252 }
00253
00254 snpdev->mode.State = EfiSimpleNetworkInitialized;
00255 return 0;
00256 }
00257
00258
00259
00260
00261
00262
00263
00264 static EFI_STATUS EFIAPI
00265 efi_snp_shutdown ( EFI_SIMPLE_NETWORK_PROTOCOL *snp ) {
00266 struct efi_snp_device *snpdev =
00267 container_of ( snp, struct efi_snp_device, snp );
00268
00269 DBGC2 ( snpdev, "SNPDEV %p SHUTDOWN\n", snpdev );
00270
00271 netdev_close ( snpdev->netdev );
00272 snpdev->mode.State = EfiSimpleNetworkStarted;
00273 return 0;
00274 }
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287 static EFI_STATUS EFIAPI
00288 efi_snp_receive_filters ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, UINT32 enable,
00289 UINT32 disable, BOOLEAN mcast_reset,
00290 UINTN mcast_count, EFI_MAC_ADDRESS *mcast ) {
00291 struct efi_snp_device *snpdev =
00292 container_of ( snp, struct efi_snp_device, snp );
00293 unsigned int i;
00294
00295 DBGC2 ( snpdev, "SNPDEV %p RECEIVE_FILTERS %08x&~%08x%s %ld mcast\n",
00296 snpdev, enable, disable, ( mcast_reset ? " reset" : "" ),
00297 ( ( unsigned long ) mcast_count ) );
00298 for ( i = 0 ; i < mcast_count ; i++ ) {
00299 DBGC2_HDA ( snpdev, i, &mcast[i],
00300 snpdev->netdev->ll_protocol->ll_addr_len );
00301 }
00302
00303
00304 return 0;
00305 }
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315 static EFI_STATUS EFIAPI
00316 efi_snp_station_address ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, BOOLEAN reset,
00317 EFI_MAC_ADDRESS *new ) {
00318 struct efi_snp_device *snpdev =
00319 container_of ( snp, struct efi_snp_device, snp );
00320 struct ll_protocol *ll_protocol = snpdev->netdev->ll_protocol;
00321
00322 DBGC2 ( snpdev, "SNPDEV %p STATION_ADDRESS %s\n", snpdev,
00323 ( reset ? "reset" : ll_protocol->ntoa ( new ) ) );
00324
00325
00326 if ( reset )
00327 new = &snpdev->mode.PermanentAddress;
00328 memcpy ( snpdev->netdev->ll_addr, new, ll_protocol->ll_addr_len );
00329
00330
00331 if ( netdev_is_open ( snpdev->netdev ) ) {
00332 DBGC ( snpdev, "SNPDEV %p MAC address changed while net "
00333 "devive open\n", snpdev );
00334 }
00335
00336 return 0;
00337 }
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348 static EFI_STATUS EFIAPI
00349 efi_snp_statistics ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, BOOLEAN reset,
00350 UINTN *stats_len, EFI_NETWORK_STATISTICS *stats ) {
00351 struct efi_snp_device *snpdev =
00352 container_of ( snp, struct efi_snp_device, snp );
00353 EFI_NETWORK_STATISTICS stats_buf;
00354
00355 DBGC2 ( snpdev, "SNPDEV %p STATISTICS%s", snpdev,
00356 ( reset ? " reset" : "" ) );
00357
00358
00359 memset ( &stats_buf, 0, sizeof ( stats_buf ) );
00360 stats_buf.TxGoodFrames = snpdev->netdev->tx_stats.good;
00361 stats_buf.TxDroppedFrames = snpdev->netdev->tx_stats.bad;
00362 stats_buf.TxTotalFrames = ( snpdev->netdev->tx_stats.good +
00363 snpdev->netdev->tx_stats.bad );
00364 stats_buf.RxGoodFrames = snpdev->netdev->rx_stats.good;
00365 stats_buf.RxDroppedFrames = snpdev->netdev->rx_stats.bad;
00366 stats_buf.RxTotalFrames = ( snpdev->netdev->rx_stats.good +
00367 snpdev->netdev->rx_stats.bad );
00368 if ( *stats_len > sizeof ( stats_buf ) )
00369 *stats_len = sizeof ( stats_buf );
00370 if ( stats )
00371 memcpy ( stats, &stats_buf, *stats_len );
00372
00373
00374 if ( reset ) {
00375 memset ( &snpdev->netdev->tx_stats, 0,
00376 sizeof ( snpdev->netdev->tx_stats ) );
00377 memset ( &snpdev->netdev->rx_stats, 0,
00378 sizeof ( snpdev->netdev->rx_stats ) );
00379 }
00380
00381 return 0;
00382 }
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393 static EFI_STATUS EFIAPI
00394 efi_snp_mcast_ip_to_mac ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, BOOLEAN ipv6,
00395 EFI_IP_ADDRESS *ip, EFI_MAC_ADDRESS *mac ) {
00396 struct efi_snp_device *snpdev =
00397 container_of ( snp, struct efi_snp_device, snp );
00398 struct ll_protocol *ll_protocol = snpdev->netdev->ll_protocol;
00399 const char *ip_str;
00400 int rc;
00401
00402 ip_str = ( ipv6 ? "(IPv6)" :
00403 inet_ntoa ( *( ( struct in_addr * ) ip ) ) );
00404 DBGC2 ( snpdev, "SNPDEV %p MCAST_IP_TO_MAC %s\n", snpdev, ip_str );
00405
00406
00407 if ( ( rc = ll_protocol->mc_hash ( ( ipv6 ? AF_INET6 : AF_INET ),
00408 ip, mac ) ) != 0 ) {
00409 DBGC ( snpdev, "SNPDEV %p could not hash %s: %s\n",
00410 snpdev, ip_str, strerror ( rc ) );
00411 return RC_TO_EFIRC ( rc );
00412 }
00413
00414 return 0;
00415 }
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427 static EFI_STATUS EFIAPI
00428 efi_snp_nvdata ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, BOOLEAN read,
00429 UINTN offset, UINTN len, VOID *data ) {
00430 struct efi_snp_device *snpdev =
00431 container_of ( snp, struct efi_snp_device, snp );
00432
00433 DBGC2 ( snpdev, "SNPDEV %p NVDATA %s %lx+%lx\n", snpdev,
00434 ( read ? "read" : "write" ), ( ( unsigned long ) offset ),
00435 ( ( unsigned long ) len ) );
00436 if ( ! read )
00437 DBGC2_HDA ( snpdev, offset, data, len );
00438
00439 return EFI_UNSUPPORTED;
00440 }
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450 static EFI_STATUS EFIAPI
00451 efi_snp_get_status ( EFI_SIMPLE_NETWORK_PROTOCOL *snp,
00452 UINT32 *interrupts, VOID **txbufs ) {
00453 struct efi_snp_device *snpdev =
00454 container_of ( snp, struct efi_snp_device, snp );
00455
00456 DBGC2 ( snpdev, "SNPDEV %p GET_STATUS", snpdev );
00457
00458
00459 efi_snp_poll ( snpdev );
00460
00461
00462
00463
00464 if ( interrupts ) {
00465 *interrupts = 0;
00466
00467
00468
00469 if ( snpdev->tx_count_interrupts &&
00470 list_empty ( &snpdev->netdev->tx_queue ) ) {
00471 *interrupts |= EFI_SIMPLE_NETWORK_TRANSMIT_INTERRUPT;
00472 snpdev->tx_count_interrupts--;
00473 }
00474
00475 if ( snpdev->rx_count_interrupts ) {
00476 *interrupts |= EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT;
00477 snpdev->rx_count_interrupts--;
00478 }
00479 DBGC2 ( snpdev, " INTS:%02x", *interrupts );
00480 }
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497 if ( txbufs ) {
00498 if ( snpdev->tx_count_txbufs &&
00499 list_empty ( &snpdev->netdev->tx_queue ) ) {
00500 *txbufs = "Which idiot designed this API?";
00501 snpdev->tx_count_txbufs--;
00502 } else {
00503 *txbufs = NULL;
00504 }
00505 DBGC2 ( snpdev, " TX:%s", ( *txbufs ? "some" : "none" ) );
00506 }
00507
00508 DBGC2 ( snpdev, "\n" );
00509 return 0;
00510 }
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524 static EFI_STATUS EFIAPI
00525 efi_snp_transmit ( EFI_SIMPLE_NETWORK_PROTOCOL *snp,
00526 UINTN ll_header_len, UINTN len, VOID *data,
00527 EFI_MAC_ADDRESS *ll_src, EFI_MAC_ADDRESS *ll_dest,
00528 UINT16 *net_proto ) {
00529 struct efi_snp_device *snpdev =
00530 container_of ( snp, struct efi_snp_device, snp );
00531 struct ll_protocol *ll_protocol = snpdev->netdev->ll_protocol;
00532 struct io_buffer *iobuf;
00533 int rc;
00534 EFI_STATUS efirc;
00535
00536 DBGC2 ( snpdev, "SNPDEV %p TRANSMIT %p+%lx", snpdev, data,
00537 ( ( unsigned long ) len ) );
00538 if ( ll_header_len ) {
00539 if ( ll_src ) {
00540 DBGC2 ( snpdev, " src %s",
00541 ll_protocol->ntoa ( ll_src ) );
00542 }
00543 if ( ll_dest ) {
00544 DBGC2 ( snpdev, " dest %s",
00545 ll_protocol->ntoa ( ll_dest ) );
00546 }
00547 if ( net_proto ) {
00548 DBGC2 ( snpdev, " proto %04x", *net_proto );
00549 }
00550 }
00551 DBGC2 ( snpdev, "\n" );
00552
00553
00554 if ( ll_header_len ) {
00555 if ( ll_header_len != ll_protocol->ll_header_len ) {
00556 DBGC ( snpdev, "SNPDEV %p TX invalid header length "
00557 "%ld\n", snpdev,
00558 ( ( unsigned long ) ll_header_len ) );
00559 efirc = EFI_INVALID_PARAMETER;
00560 goto err_sanity;
00561 }
00562 if ( len < ll_header_len ) {
00563 DBGC ( snpdev, "SNPDEV %p invalid packet length %ld\n",
00564 snpdev, ( ( unsigned long ) len ) );
00565 efirc = EFI_BUFFER_TOO_SMALL;
00566 goto err_sanity;
00567 }
00568 if ( ! ll_dest ) {
00569 DBGC ( snpdev, "SNPDEV %p TX missing destination "
00570 "address\n", snpdev );
00571 efirc = EFI_INVALID_PARAMETER;
00572 goto err_sanity;
00573 }
00574 if ( ! net_proto ) {
00575 DBGC ( snpdev, "SNPDEV %p TX missing network "
00576 "protocol\n", snpdev );
00577 efirc = EFI_INVALID_PARAMETER;
00578 goto err_sanity;
00579 }
00580 if ( ! ll_src )
00581 ll_src = &snpdev->mode.CurrentAddress;
00582 }
00583
00584
00585 iobuf = alloc_iob ( len );
00586 if ( ! iobuf ) {
00587 DBGC ( snpdev, "SNPDEV %p TX could not allocate %ld-byte "
00588 "buffer\n", snpdev, ( ( unsigned long ) len ) );
00589 efirc = EFI_DEVICE_ERROR;
00590 goto err_alloc_iob;
00591 }
00592 memcpy ( iob_put ( iobuf, len ), data, len );
00593
00594
00595 if ( ll_header_len ) {
00596 iob_pull ( iobuf, ll_header_len );
00597 if ( ( rc = ll_protocol->push ( snpdev->netdev,
00598 iobuf, ll_dest, ll_src,
00599 htons ( *net_proto ) )) != 0 ){
00600 DBGC ( snpdev, "SNPDEV %p TX could not construct "
00601 "header: %s\n", snpdev, strerror ( rc ) );
00602 efirc = RC_TO_EFIRC ( rc );
00603 goto err_ll_push;
00604 }
00605 }
00606
00607
00608 if ( ( rc = netdev_tx ( snpdev->netdev, iob_disown ( iobuf ) ) ) != 0){
00609 DBGC ( snpdev, "SNPDEV %p TX could not transmit: %s\n",
00610 snpdev, strerror ( rc ) );
00611 efirc = RC_TO_EFIRC ( rc );
00612 goto err_tx;
00613 }
00614
00615
00616 snpdev->tx_count_interrupts++;
00617 snpdev->tx_count_txbufs++;
00618
00619 return 0;
00620
00621 err_tx:
00622 err_ll_push:
00623 free_iob ( iobuf );
00624 err_alloc_iob:
00625 err_sanity:
00626 return efirc;
00627 }
00628
00629
00630
00631
00632
00633
00634
00635
00636
00637
00638
00639
00640
00641 static EFI_STATUS EFIAPI
00642 efi_snp_receive ( EFI_SIMPLE_NETWORK_PROTOCOL *snp,
00643 UINTN *ll_header_len, UINTN *len, VOID *data,
00644 EFI_MAC_ADDRESS *ll_src, EFI_MAC_ADDRESS *ll_dest,
00645 UINT16 *net_proto ) {
00646 struct efi_snp_device *snpdev =
00647 container_of ( snp, struct efi_snp_device, snp );
00648 struct ll_protocol *ll_protocol = snpdev->netdev->ll_protocol;
00649 struct io_buffer *iobuf;
00650 const void *iob_ll_dest;
00651 const void *iob_ll_src;
00652 uint16_t iob_net_proto;
00653 int rc;
00654 EFI_STATUS efirc;
00655
00656 DBGC2 ( snpdev, "SNPDEV %p RECEIVE %p(+%lx)", snpdev, data,
00657 ( ( unsigned long ) *len ) );
00658
00659
00660 efi_snp_poll ( snpdev );
00661
00662
00663 iobuf = netdev_rx_dequeue ( snpdev->netdev );
00664 if ( ! iobuf ) {
00665 DBGC2 ( snpdev, "\n" );
00666 efirc = EFI_NOT_READY;
00667 goto out_no_packet;
00668 }
00669 DBGC2 ( snpdev, "+%zx\n", iob_len ( iobuf ) );
00670
00671
00672 memcpy ( data, iobuf->data, iob_len ( iobuf ) );
00673 *len = iob_len ( iobuf );
00674
00675
00676 if ( ( rc = ll_protocol->pull ( snpdev->netdev, iobuf, &iob_ll_dest,
00677 &iob_ll_src, &iob_net_proto ) ) != 0 ){
00678 DBGC ( snpdev, "SNPDEV %p could not parse header: %s\n",
00679 snpdev, strerror ( rc ) );
00680 efirc = RC_TO_EFIRC ( rc );
00681 goto out_bad_ll_header;
00682 }
00683
00684
00685 if ( ll_header_len )
00686 *ll_header_len = ll_protocol->ll_header_len;
00687 if ( ll_src )
00688 memcpy ( ll_src, iob_ll_src, ll_protocol->ll_addr_len );
00689 if ( ll_dest )
00690 memcpy ( ll_dest, iob_ll_dest, ll_protocol->ll_addr_len );
00691 if ( net_proto )
00692 *net_proto = ntohs ( iob_net_proto );
00693
00694 efirc = 0;
00695
00696 out_bad_ll_header:
00697 free_iob ( iobuf );
00698 out_no_packet:
00699 return efirc;
00700 }
00701
00702
00703
00704
00705
00706
00707
00708 static VOID EFIAPI efi_snp_wait_for_packet ( EFI_EVENT event,
00709 VOID *context ) {
00710 EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
00711 struct efi_snp_device *snpdev = context;
00712
00713 DBGCP ( snpdev, "SNPDEV %p WAIT_FOR_PACKET\n", snpdev );
00714
00715
00716 if ( ! netdev_is_open ( snpdev->netdev ) )
00717 return;
00718
00719
00720 efi_snp_poll ( snpdev );
00721
00722
00723 if ( snpdev->rx_count_events != 0 ) {
00724 DBGC2 ( snpdev, "SNPDEV %p firing WaitForPacket event\n",
00725 snpdev );
00726 bs->SignalEvent ( event );
00727 snpdev->rx_count_events--;
00728 }
00729 }
00730
00731
00732 static EFI_SIMPLE_NETWORK_PROTOCOL efi_snp_device_snp = {
00733 .Revision = EFI_SIMPLE_NETWORK_PROTOCOL_REVISION,
00734 .Start = efi_snp_start,
00735 .Stop = efi_snp_stop,
00736 .Initialize = efi_snp_initialize,
00737 .Reset = efi_snp_reset,
00738 .Shutdown = efi_snp_shutdown,
00739 .ReceiveFilters = efi_snp_receive_filters,
00740 .StationAddress = efi_snp_station_address,
00741 .Statistics = efi_snp_statistics,
00742 .MCastIpToMac = efi_snp_mcast_ip_to_mac,
00743 .NvData = efi_snp_nvdata,
00744 .GetStatus = efi_snp_get_status,
00745 .Transmit = efi_snp_transmit,
00746 .Receive = efi_snp_receive,
00747 };
00748
00749
00750
00751
00752
00753
00754
00755
00756 static struct net_device *
00757 efi_snp_netdev ( EFI_DRIVER_BINDING_PROTOCOL *driver, EFI_HANDLE device ) {
00758 EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
00759 union {
00760 EFI_PCI_IO_PROTOCOL *pci;
00761 void *interface;
00762 } u;
00763 UINTN pci_segment, pci_bus, pci_dev, pci_fn;
00764 unsigned int pci_busdevfn;
00765 struct net_device *netdev = NULL;
00766 EFI_STATUS efirc;
00767
00768
00769 if ( ( efirc = bs->OpenProtocol ( device,
00770 &efi_pci_io_protocol_guid,
00771 &u.interface,
00772 driver->DriverBindingHandle,
00773 device,
00774 EFI_OPEN_PROTOCOL_BY_DRIVER )) !=0 ){
00775 DBGCP ( driver, "SNPDRV %p device %p is not a PCI device\n",
00776 driver, device );
00777 goto out_no_pci_io;
00778 }
00779
00780
00781 if ( ( efirc = u.pci->GetLocation ( u.pci, &pci_segment, &pci_bus,
00782 &pci_dev, &pci_fn ) ) != 0 ) {
00783 DBGC ( driver, "SNPDRV %p device %p could not get PCI "
00784 "location: %s\n",
00785 driver, device, efi_strerror ( efirc ) );
00786 goto out_no_pci_location;
00787 }
00788 DBGCP ( driver, "SNPDRV %p device %p is PCI %04lx:%02lx:%02lx.%lx\n",
00789 driver, device, ( ( unsigned long ) pci_segment ),
00790 ( ( unsigned long ) pci_bus ), ( ( unsigned long ) pci_dev ),
00791 ( ( unsigned long ) pci_fn ) );
00792
00793
00794 pci_busdevfn = PCI_BUSDEVFN ( pci_bus, PCI_DEVFN ( pci_dev, pci_fn ) );
00795 if ( ( netdev = find_netdev_by_location ( BUS_TYPE_PCI,
00796 pci_busdevfn ) ) == NULL ) {
00797 DBGCP ( driver, "SNPDRV %p device %p is not a gPXE network "
00798 "device\n", driver, device );
00799 goto out_no_netdev;
00800 }
00801 DBGC ( driver, "SNPDRV %p device %p is %s\n",
00802 driver, device, netdev->name );
00803
00804 out_no_netdev:
00805 out_no_pci_location:
00806 bs->CloseProtocol ( device, &efi_pci_io_protocol_guid,
00807 driver->DriverBindingHandle, device );
00808 out_no_pci_io:
00809 return netdev;
00810 }
00811
00812
00813
00814
00815
00816
00817
00818
00819 static struct efi_snp_device *
00820 efi_snp_snpdev ( EFI_DRIVER_BINDING_PROTOCOL *driver, EFI_HANDLE device ) {
00821 EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
00822 union {
00823 EFI_SIMPLE_NETWORK_PROTOCOL *snp;
00824 void *interface;
00825 } u;
00826 struct efi_snp_device *snpdev = NULL;
00827 EFI_STATUS efirc;
00828
00829 if ( ( efirc = bs->OpenProtocol ( device,
00830 &efi_simple_network_protocol_guid,
00831 &u.interface,
00832 driver->DriverBindingHandle,
00833 device,
00834 EFI_OPEN_PROTOCOL_GET_PROTOCOL))!=0){
00835 DBGC ( driver, "SNPDRV %p device %p could not locate SNP: "
00836 "%s\n", driver, device, efi_strerror ( efirc ) );
00837 goto err_no_snp;
00838 }
00839
00840 snpdev = container_of ( u.snp, struct efi_snp_device, snp );
00841 DBGCP ( driver, "SNPDRV %p device %p is SNPDEV %p\n",
00842 driver, device, snpdev );
00843
00844 bs->CloseProtocol ( device, &efi_simple_network_protocol_guid,
00845 driver->DriverBindingHandle, device );
00846 err_no_snp:
00847 return snpdev;
00848 }
00849
00850
00851
00852
00853
00854
00855
00856
00857
00858 static EFI_STATUS EFIAPI
00859 efi_snp_driver_supported ( EFI_DRIVER_BINDING_PROTOCOL *driver,
00860 EFI_HANDLE device,
00861 EFI_DEVICE_PATH_PROTOCOL *child ) {
00862 struct net_device *netdev;
00863
00864 DBGCP ( driver, "SNPDRV %p DRIVER_SUPPORTED %p (%p)\n",
00865 driver, device, child );
00866
00867 netdev = efi_snp_netdev ( driver, device );
00868 return ( netdev ? 0 : EFI_UNSUPPORTED );
00869 }
00870
00871
00872
00873
00874
00875
00876
00877
00878
00879 static EFI_STATUS EFIAPI
00880 efi_snp_driver_start ( EFI_DRIVER_BINDING_PROTOCOL *driver,
00881 EFI_HANDLE device,
00882 EFI_DEVICE_PATH_PROTOCOL *child ) {
00883 EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
00884 EFI_DEVICE_PATH_PROTOCOL *path;
00885 EFI_DEVICE_PATH_PROTOCOL *subpath;
00886 MAC_ADDR_DEVICE_PATH *macpath;
00887 struct efi_snp_device *snpdev;
00888 struct net_device *netdev;
00889 size_t subpath_len;
00890 size_t path_prefix_len = 0;
00891 unsigned int i;
00892 EFI_STATUS efirc;
00893
00894 DBGCP ( driver, "SNPDRV %p DRIVER_START %p (%p)\n",
00895 driver, device, child );
00896
00897
00898 if ( ( efirc = bs->OpenProtocol ( device,
00899 &efi_device_path_protocol_guid,
00900 ( void * ) &path,
00901 driver->DriverBindingHandle,
00902 device,
00903 EFI_OPEN_PROTOCOL_BY_DRIVER )) !=0 ){
00904 DBGCP ( driver, "SNPDRV %p device %p has no device path\n",
00905 driver, device );
00906 goto err_no_device_path;
00907 }
00908 subpath = path;
00909 while ( subpath->Type != END_DEVICE_PATH_TYPE ) {
00910 subpath_len = ( ( subpath->Length[1] << 8 ) |
00911 subpath->Length[0] );
00912 path_prefix_len += subpath_len;
00913 subpath = ( ( ( void * ) subpath ) + subpath_len );
00914 }
00915
00916
00917 snpdev = zalloc ( sizeof ( *snpdev ) + path_prefix_len +
00918 sizeof ( *macpath ) );
00919 if ( ! snpdev ) {
00920 efirc = EFI_OUT_OF_RESOURCES;
00921 goto err_alloc_snp;
00922 }
00923
00924
00925 netdev = efi_snp_netdev ( driver, device );
00926 if ( ! netdev ) {
00927 DBGC ( snpdev, "SNPDEV %p cannot find netdev for device %p\n",
00928 snpdev, device );
00929 efirc = EFI_UNSUPPORTED;
00930 goto err_no_netdev;
00931 }
00932 snpdev->netdev = netdev_get ( netdev );
00933
00934
00935 if ( netdev->ll_protocol->ll_addr_len > sizeof ( EFI_MAC_ADDRESS ) ) {
00936 DBGC ( snpdev, "SNPDEV %p cannot support link-layer address "
00937 "length %d for %s\n", snpdev,
00938 netdev->ll_protocol->ll_addr_len, netdev->name );
00939 efirc = EFI_INVALID_PARAMETER;
00940 goto err_ll_addr_len;
00941 }
00942
00943
00944 memcpy ( &snpdev->snp, &efi_snp_device_snp, sizeof ( snpdev->snp ) );
00945 snpdev->snp.Mode = &snpdev->mode;
00946 if ( ( efirc = bs->CreateEvent ( EVT_NOTIFY_WAIT, TPL_NOTIFY,
00947 efi_snp_wait_for_packet, snpdev,
00948 &snpdev->snp.WaitForPacket ) ) != 0 ){
00949 DBGC ( snpdev, "SNPDEV %p could not create event: %s\n",
00950 snpdev, efi_strerror ( efirc ) );
00951 goto err_create_event;
00952 }
00953
00954
00955 snpdev->mode.State = EfiSimpleNetworkStopped;
00956 efi_snp_set_mode ( snpdev );
00957
00958
00959 snpdev->nii.Revision =
00960 EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL_REVISION;
00961 strncpy ( snpdev->nii.StringId, "gPXE",
00962 sizeof ( snpdev->nii.StringId ) );
00963
00964
00965 for ( i = 0 ; i < sizeof ( netdev->name ) ; i++ ) {
00966
00967 assert ( i < ( sizeof ( snpdev->name ) /
00968 sizeof ( snpdev->name[0] ) ) );
00969 snpdev->name[i] = netdev->name[i];
00970 }
00971
00972
00973 memcpy ( &snpdev->path, path, path_prefix_len );
00974 macpath = ( ( ( void * ) &snpdev->path ) + path_prefix_len );
00975 subpath = ( ( void * ) ( macpath + 1 ) );
00976 memset ( macpath, 0, sizeof ( *macpath ) );
00977 macpath->Header.Type = MESSAGING_DEVICE_PATH;
00978 macpath->Header.SubType = MSG_MAC_ADDR_DP;
00979 macpath->Header.Length[0] = sizeof ( *macpath );
00980 memcpy ( &macpath->MacAddress, netdev->ll_addr,
00981 sizeof ( macpath->MacAddress ) );
00982 macpath->IfType = ntohs ( netdev->ll_protocol->ll_proto );
00983 memset ( subpath, 0, sizeof ( *subpath ) );
00984 subpath->Type = END_DEVICE_PATH_TYPE;
00985 subpath->SubType = END_ENTIRE_DEVICE_PATH_SUBTYPE;
00986 subpath->Length[0] = sizeof ( *subpath );
00987
00988
00989 if ( ( efirc = bs->InstallMultipleProtocolInterfaces (
00990 &snpdev->handle,
00991 &efi_simple_network_protocol_guid, &snpdev->snp,
00992 &efi_device_path_protocol_guid, &snpdev->path,
00993 &efi_nii_protocol_guid, &snpdev->nii,
00994 &efi_nii31_protocol_guid, &snpdev->nii,
00995 NULL ) ) != 0 ) {
00996 DBGC ( snpdev, "SNPDEV %p could not install protocols: "
00997 "%s\n", snpdev, efi_strerror ( efirc ) );
00998 goto err_install_protocol_interface;
00999 }
01000
01001 DBGC ( snpdev, "SNPDEV %p installed for %s as device %p\n",
01002 snpdev, netdev->name, snpdev->handle );
01003 return 0;
01004
01005 bs->UninstallMultipleProtocolInterfaces (
01006 snpdev->handle,
01007 &efi_simple_network_protocol_guid, &snpdev->snp,
01008 &efi_device_path_protocol_guid, &snpdev->path,
01009 &efi_nii_protocol_guid, &snpdev->nii,
01010 &efi_nii31_protocol_guid, &snpdev->nii,
01011 NULL );
01012 err_install_protocol_interface:
01013 bs->CloseEvent ( snpdev->snp.WaitForPacket );
01014 err_create_event:
01015 err_ll_addr_len:
01016 netdev_put ( netdev );
01017 err_no_netdev:
01018 free ( snpdev );
01019 err_alloc_snp:
01020 bs->CloseProtocol ( device, &efi_device_path_protocol_guid,
01021 driver->DriverBindingHandle, device );
01022 err_no_device_path:
01023 return efirc;
01024 }
01025
01026
01027
01028
01029
01030
01031
01032
01033
01034
01035 static EFI_STATUS EFIAPI
01036 efi_snp_driver_stop ( EFI_DRIVER_BINDING_PROTOCOL *driver,
01037 EFI_HANDLE device,
01038 UINTN num_children,
01039 EFI_HANDLE *children ) {
01040 EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
01041 struct efi_snp_device *snpdev;
01042
01043 DBGCP ( driver, "SNPDRV %p DRIVER_STOP %p (%ld %p)\n",
01044 driver, device, ( ( unsigned long ) num_children ), children );
01045
01046
01047 snpdev = efi_snp_snpdev ( driver, device );
01048 if ( ! snpdev ) {
01049 DBGC ( driver, "SNPDRV %p device %p could not find SNPDEV\n",
01050 driver, device );
01051 return EFI_DEVICE_ERROR;
01052 }
01053
01054
01055 bs->UninstallMultipleProtocolInterfaces (
01056 snpdev->handle,
01057 &efi_simple_network_protocol_guid, &snpdev->snp,
01058 &efi_device_path_protocol_guid, &snpdev->path,
01059 &efi_nii_protocol_guid, &snpdev->nii,
01060 &efi_nii31_protocol_guid, &snpdev->nii,
01061 NULL );
01062 bs->CloseEvent ( snpdev->snp.WaitForPacket );
01063 netdev_put ( snpdev->netdev );
01064 free ( snpdev );
01065 bs->CloseProtocol ( device, &efi_device_path_protocol_guid,
01066 driver->DriverBindingHandle, device );
01067 return 0;
01068 }
01069
01070
01071 static EFI_DRIVER_BINDING_PROTOCOL efi_snp_binding = {
01072 efi_snp_driver_supported,
01073 efi_snp_driver_start,
01074 efi_snp_driver_stop,
01075 0x10,
01076 NULL,
01077 NULL
01078 };
01079
01080
01081
01082
01083
01084
01085
01086
01087
01088 static EFI_STATUS EFIAPI
01089 efi_snp_get_driver_name ( EFI_COMPONENT_NAME2_PROTOCOL *wtf __unused,
01090 CHAR8 *language __unused, CHAR16 **driver_name ) {
01091
01092 *driver_name = L"" PRODUCT_SHORT_NAME " Driver";
01093 return 0;
01094 }
01095
01096
01097
01098
01099
01100
01101
01102
01103
01104
01105
01106 static EFI_STATUS EFIAPI
01107 efi_snp_get_controller_name ( EFI_COMPONENT_NAME2_PROTOCOL *wtf __unused,
01108 EFI_HANDLE device __unused,
01109 EFI_HANDLE child __unused,
01110 CHAR8 *language __unused,
01111 CHAR16 **controller_name __unused ) {
01112
01113
01114 return EFI_UNSUPPORTED;
01115 }
01116
01117
01118 static EFI_COMPONENT_NAME2_PROTOCOL efi_snp_name = {
01119 efi_snp_get_driver_name,
01120 efi_snp_get_controller_name,
01121 "en"
01122 };
01123
01124
01125
01126
01127
01128
01129 int efi_snp_install ( void ) {
01130 EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
01131 EFI_DRIVER_BINDING_PROTOCOL *driver = &efi_snp_binding;
01132 EFI_STATUS efirc;
01133
01134 driver->ImageHandle = efi_image_handle;
01135 if ( ( efirc = bs->InstallMultipleProtocolInterfaces (
01136 &driver->DriverBindingHandle,
01137 &efi_driver_binding_protocol_guid, driver,
01138 &efi_component_name2_protocol_guid, &efi_snp_name,
01139 NULL ) ) != 0 ) {
01140 DBGC ( driver, "SNPDRV %p could not install protocols: "
01141 "%s\n", driver, efi_strerror ( efirc ) );
01142 return EFIRC_TO_RC ( efirc );
01143 }
01144
01145 DBGC ( driver, "SNPDRV %p driver binding installed as %p\n",
01146 driver, driver->DriverBindingHandle );
01147 return 0;
01148 }