102130c8184e329693b1c36ece87be2af33ce5a4
[people/asdlkf/gpxe.git] / src / interface / efi / efi_snp.c
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., 675 Mass Ave, Cambridge, MA 02139, USA.
17  */
18
19 #include <stdlib.h>
20 #include <string.h>
21 #include <errno.h>
22 #include <assert.h>
23 #include <byteswap.h>
24 #include <gpxe/netdevice.h>
25 #include <gpxe/iobuf.h>
26 #include <gpxe/in.h>
27 #include <gpxe/pci.h>
28 #include <gpxe/efi/efi.h>
29 #include <gpxe/efi/Protocol/DriverBinding.h>
30 #include <gpxe/efi/Protocol/PciIo.h>
31 #include <gpxe/efi/Protocol/SimpleNetwork.h>
32
33 /** @file
34  *
35  * gPXE EFI SNP interface
36  *
37  */
38
39 /** An SNP device */
40 struct efi_snp_device {
41         /** The underlying gPXE network device */
42         struct net_device *netdev;
43         /** The SNP structure itself */
44         EFI_SIMPLE_NETWORK_PROTOCOL snp;
45         /** The SNP "mode" (parameters) */
46         EFI_SIMPLE_NETWORK_MODE mode;
47         /** Outstanding TX packet count (via "interrupt status")
48          *
49          * Used in order to generate TX completions.
50          */
51         unsigned int tx_count_interrupts;
52         /** Outstanding TX packet count (via "recycled tx buffers")
53          *
54          * Used in order to generate TX completions.
55          */
56         unsigned int tx_count_txbufs;
57         /** Outstanding RX packet count (via "interrupt status") */
58         unsigned int rx_count_interrupts;
59         /** Outstanding RX packet count (via WaitForPacket event) */
60         unsigned int rx_count_events;
61 };
62
63 /** EFI simple network protocol GUID */
64 static EFI_GUID efi_simple_network_protocol_guid
65         = EFI_SIMPLE_NETWORK_PROTOCOL_GUID;
66
67 /** EFI driver binding protocol GUID */
68 static EFI_GUID efi_driver_binding_protocol_guid
69         = EFI_DRIVER_BINDING_PROTOCOL_GUID;
70
71 /** EFI PCI I/O protocol GUID */
72 static EFI_GUID efi_pci_io_protocol_guid
73         = EFI_PCI_IO_PROTOCOL_GUID;
74
75 /**
76  * Set EFI SNP mode based on gPXE net device parameters
77  *
78  * @v snp               SNP interface
79  */
80 static void efi_snp_set_mode ( struct efi_snp_device *snpdev ) {
81         struct net_device *netdev = snpdev->netdev;
82         EFI_SIMPLE_NETWORK_MODE *mode = &snpdev->mode;
83         unsigned int ll_addr_len = netdev->ll_protocol->ll_addr_len;
84
85         mode->HwAddressSize = ll_addr_len;
86         mode->MediaHeaderSize = netdev->ll_protocol->ll_header_len;
87         mode->MaxPacketSize = netdev->max_pkt_len;
88         mode->ReceiveFilterMask = ( EFI_SIMPLE_NETWORK_RECEIVE_UNICAST |
89                                     EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST |
90                                     EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST );
91         assert ( ll_addr_len <= sizeof ( mode->CurrentAddress ) );
92         memcpy ( &mode->CurrentAddress, netdev->ll_addr, ll_addr_len );
93         memcpy ( &mode->BroadcastAddress, netdev->ll_protocol->ll_broadcast,
94                  ll_addr_len );
95         memcpy ( &mode->PermanentAddress, netdev->ll_addr, ll_addr_len );
96         mode->IfType = ntohs ( netdev->ll_protocol->ll_proto );
97         mode->MacAddressChangeable = TRUE;
98         mode->MediaPresentSupported = TRUE;
99         mode->MediaPresent = ( netdev_link_ok ( netdev ) ? TRUE : FALSE );
100 }
101
102 /**
103  * Poll net device and count received packets
104  *
105  * @v snpdev            SNP device
106  */
107 static void efi_snp_poll ( struct efi_snp_device *snpdev ) {
108         struct io_buffer *iobuf;
109         unsigned int before = 0;
110         unsigned int after = 0;
111         unsigned int arrived;
112
113         /* We have to report packet arrivals, and this is the easiest
114          * way to fake it.
115          */
116         list_for_each_entry ( iobuf, &snpdev->netdev->rx_queue, list )
117                 before++;
118         netdev_poll ( snpdev->netdev );
119         list_for_each_entry ( iobuf, &snpdev->netdev->rx_queue, list )
120                 after++;
121         arrived = ( after - before );
122
123         snpdev->rx_count_interrupts += arrived;
124         snpdev->rx_count_events += arrived;
125 }
126
127 /**
128  * Change SNP state from "stopped" to "started"
129  *
130  * @v snp               SNP interface
131  * @ret efirc           EFI status code
132  */
133 static EFI_STATUS EFIAPI
134 efi_snp_start ( EFI_SIMPLE_NETWORK_PROTOCOL *snp ) {
135         struct efi_snp_device *snpdev =
136                 container_of ( snp, struct efi_snp_device, snp );
137
138         DBGC2 ( snpdev, "SNPDEV %p START\n", snpdev );
139
140         snpdev->mode.State = EfiSimpleNetworkStarted;
141         return 0;
142 }
143
144 /**
145  * Change SNP state from "started" to "stopped"
146  *
147  * @v snp               SNP interface
148  * @ret efirc           EFI status code
149  */
150 static EFI_STATUS EFIAPI
151 efi_snp_stop ( EFI_SIMPLE_NETWORK_PROTOCOL *snp ) {
152         struct efi_snp_device *snpdev =
153                 container_of ( snp, struct efi_snp_device, snp );
154
155         DBGC2 ( snpdev, "SNPDEV %p STOP\n", snpdev );
156
157         snpdev->mode.State = EfiSimpleNetworkStopped;
158         return 0;
159 }
160
161 /**
162  * Open the network device
163  *
164  * @v snp               SNP interface
165  * @v extra_rx_bufsize  Extra RX buffer size, in bytes
166  * @v extra_tx_bufsize  Extra TX buffer size, in bytes
167  * @ret efirc           EFI status code
168  */
169 static EFI_STATUS EFIAPI
170 efi_snp_initialize ( EFI_SIMPLE_NETWORK_PROTOCOL *snp,
171                      UINTN extra_rx_bufsize, UINTN extra_tx_bufsize ) {
172         struct efi_snp_device *snpdev =
173                 container_of ( snp, struct efi_snp_device, snp );
174         int rc;
175
176         DBGC2 ( snpdev, "SNPDEV %p INITIALIZE (%ld extra RX, %ld extra TX)\n",
177                 snpdev, ( ( unsigned long ) extra_rx_bufsize ),
178                 ( ( unsigned long ) extra_tx_bufsize ) );
179
180         if ( ( rc = netdev_open ( snpdev->netdev ) ) != 0 ) {
181                 DBGC ( snpdev, "SNPDEV %p could not open %s: %s\n",
182                        snpdev, snpdev->netdev->name, strerror ( rc ) );
183                 return RC_TO_EFIRC ( rc );
184         }
185
186         snpdev->mode.State = EfiSimpleNetworkInitialized;
187         return 0;
188 }
189
190 /**
191  * Reset the network device
192  *
193  * @v snp               SNP interface
194  * @v ext_verify        Extended verification required
195  * @ret efirc           EFI status code
196  */
197 static EFI_STATUS EFIAPI
198 efi_snp_reset ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, BOOLEAN ext_verify ) {
199         struct efi_snp_device *snpdev =
200                 container_of ( snp, struct efi_snp_device, snp );
201         int rc;
202
203         DBGC2 ( snpdev, "SNPDEV %p RESET (%s extended verification)\n",
204                 snpdev, ( ext_verify ? "with" : "without" ) );
205
206         netdev_close ( snpdev->netdev );
207         snpdev->mode.State = EfiSimpleNetworkStarted;
208
209         if ( ( rc = netdev_open ( snpdev->netdev ) ) != 0 ) {
210                 DBGC ( snpdev, "SNPDEV %p could not reopen %s: %s\n",
211                        snpdev, snpdev->netdev->name, strerror ( rc ) );
212                 return RC_TO_EFIRC ( rc );
213         }
214
215         snpdev->mode.State = EfiSimpleNetworkInitialized;
216         return 0;
217 }
218
219 /**
220  * Shut down the network device
221  *
222  * @v snp               SNP interface
223  * @ret efirc           EFI status code
224  */
225 static EFI_STATUS EFIAPI
226 efi_snp_shutdown ( EFI_SIMPLE_NETWORK_PROTOCOL *snp ) {
227         struct efi_snp_device *snpdev =
228                 container_of ( snp, struct efi_snp_device, snp );
229
230         DBGC2 ( snpdev, "SNPDEV %p SHUTDOWN\n", snpdev );
231
232         netdev_close ( snpdev->netdev );
233         snpdev->mode.State = EfiSimpleNetworkStarted;
234         return 0;
235 }
236
237 /**
238  * Manage receive filters
239  *
240  * @v snp               SNP interface
241  * @v enable            Receive filters to enable
242  * @v disable           Receive filters to disable
243  * @v mcast_reset       Reset multicast filters
244  * @v mcast_count       Number of multicast filters
245  * @v mcast             Multicast filters
246  * @ret efirc           EFI status code
247  */
248 static EFI_STATUS EFIAPI
249 efi_snp_receive_filters ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, UINT32 enable,
250                           UINT32 disable, BOOLEAN mcast_reset,
251                           UINTN mcast_count, EFI_MAC_ADDRESS *mcast ) {
252         struct efi_snp_device *snpdev =
253                 container_of ( snp, struct efi_snp_device, snp );
254         unsigned int i;
255
256         DBGC2 ( snpdev, "SNPDEV %p RECEIVE_FILTERS %08x&~%08x%s %ld mcast\n",
257                 snpdev, enable, disable, ( mcast_reset ? " reset" : "" ),
258                 ( ( unsigned long ) mcast_count ) );
259         for ( i = 0 ; i < mcast_count ; i++ ) {
260                 DBGC2_HDA ( snpdev, i, &mcast[i],
261                             snpdev->netdev->ll_protocol->ll_addr_len );
262         }
263
264         /* Lie through our teeth, otherwise MNP refuses to accept us */
265         return 0;
266 }
267
268 /**
269  * Set station address
270  *
271  * @v snp               SNP interface
272  * @v reset             Reset to permanent address
273  * @v new               New station address
274  * @ret efirc           EFI status code
275  */
276 static EFI_STATUS EFIAPI
277 efi_snp_station_address ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, BOOLEAN reset,
278                           EFI_MAC_ADDRESS *new ) {
279         struct efi_snp_device *snpdev =
280                 container_of ( snp, struct efi_snp_device, snp );
281         struct ll_protocol *ll_protocol = snpdev->netdev->ll_protocol;
282
283         DBGC2 ( snpdev, "SNPDEV %p STATION_ADDRESS %s\n", snpdev,
284                 ( reset ? "reset" : ll_protocol->ntoa ( new ) ) );
285
286         /* Set the MAC address */
287         if ( reset )
288                 new = &snpdev->mode.PermanentAddress;
289         memcpy ( snpdev->netdev->ll_addr, new, ll_protocol->ll_addr_len );
290
291         /* MAC address changes take effect only on netdev_open() */
292         if ( snpdev->netdev->state & NETDEV_OPEN ) {
293                 DBGC ( snpdev, "SNPDEV %p MAC address changed while net "
294                        "devive open\n", snpdev );
295         }
296
297         return 0;
298 }
299
300 /**
301  * Get (or reset) statistics
302  *
303  * @v snp               SNP interface
304  * @v reset             Reset statistics
305  * @v stats_len         Size of statistics table
306  * @v stats             Statistics table
307  * @ret efirc           EFI status code
308  */
309 static EFI_STATUS EFIAPI
310 efi_snp_statistics ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, BOOLEAN reset,
311                      UINTN *stats_len, EFI_NETWORK_STATISTICS *stats ) {
312         struct efi_snp_device *snpdev =
313                 container_of ( snp, struct efi_snp_device, snp );
314         EFI_NETWORK_STATISTICS stats_buf;
315
316         DBGC2 ( snpdev, "SNPDEV %p STATISTICS%s", snpdev,
317                 ( reset ? " reset" : "" ) );
318
319         /* Gather statistics */
320         memset ( &stats_buf, 0, sizeof ( stats_buf ) );
321         stats_buf.TxGoodFrames = snpdev->netdev->tx_stats.good;
322         stats_buf.TxDroppedFrames = snpdev->netdev->tx_stats.bad;
323         stats_buf.TxTotalFrames = ( snpdev->netdev->tx_stats.good +
324                                     snpdev->netdev->tx_stats.bad );
325         stats_buf.RxGoodFrames = snpdev->netdev->rx_stats.good;
326         stats_buf.RxDroppedFrames = snpdev->netdev->rx_stats.bad;
327         stats_buf.RxTotalFrames = ( snpdev->netdev->rx_stats.good +
328                                     snpdev->netdev->rx_stats.bad );
329         if ( *stats_len > sizeof ( stats_buf ) )
330                 *stats_len = sizeof ( stats_buf );
331         if ( stats )
332                 memcpy ( stats, &stats_buf, *stats_len );
333
334         /* Reset statistics if requested to do so */
335         if ( reset ) {
336                 memset ( &snpdev->netdev->tx_stats, 0,
337                          sizeof ( snpdev->netdev->tx_stats ) );
338                 memset ( &snpdev->netdev->rx_stats, 0,
339                          sizeof ( snpdev->netdev->rx_stats ) );
340         }
341
342         return 0;
343 }
344
345 /**
346  * Convert multicast IP address to MAC address
347  *
348  * @v snp               SNP interface
349  * @v ipv6              Address is IPv6
350  * @v ip                IP address
351  * @v mac               MAC address
352  * @ret efirc           EFI status code
353  */
354 static EFI_STATUS EFIAPI
355 efi_snp_mcast_ip_to_mac ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, BOOLEAN ipv6,
356                           EFI_IP_ADDRESS *ip, EFI_MAC_ADDRESS *mac ) {
357         struct efi_snp_device *snpdev =
358                 container_of ( snp, struct efi_snp_device, snp );
359         struct ll_protocol *ll_protocol = snpdev->netdev->ll_protocol;
360         const char *ip_str;
361         int rc;
362
363         ip_str = ( ipv6 ? "(IPv6)" /* FIXME when we have inet6_ntoa() */ :
364                    inet_ntoa ( *( ( struct in_addr * ) ip ) ) );
365         DBGC2 ( snpdev, "SNPDEV %p MCAST_IP_TO_MAC %s\n", snpdev, ip_str );
366
367         /* Try to hash the address */
368         if ( ( rc = ll_protocol->mc_hash ( ( ipv6 ? AF_INET6 : AF_INET ),
369                                            ip, mac ) ) != 0 ) {
370                 DBGC ( snpdev, "SNPDEV %p could not hash %s: %s\n",
371                        snpdev, ip_str, strerror ( rc ) );
372                 return RC_TO_EFIRC ( rc );
373         }
374
375         return 0;
376 }
377
378 /**
379  * Read or write non-volatile storage
380  *
381  * @v snp               SNP interface
382  * @v read              Operation is a read
383  * @v offset            Starting offset within NVRAM
384  * @v len               Length of data buffer
385  * @v data              Data buffer
386  * @ret efirc           EFI status code
387  */
388 static EFI_STATUS EFIAPI
389 efi_snp_nvdata ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, BOOLEAN read,
390                  UINTN offset, UINTN len, VOID *data ) {
391         struct efi_snp_device *snpdev =
392                 container_of ( snp, struct efi_snp_device, snp );
393
394         DBGC2 ( snpdev, "SNPDEV %p NVDATA %s %lx+%lx\n", snpdev,
395                 ( read ? "read" : "write" ), ( ( unsigned long ) offset ),
396                 ( ( unsigned long ) len ) );
397         if ( ! read )
398                 DBGC2_HDA ( snpdev, offset, data, len );
399
400         return EFI_UNSUPPORTED;
401 }
402
403 /**
404  * Read interrupt status and TX recycled buffer status
405  *
406  * @v snp               SNP interface
407  * @v interrupts        Interrupt status, or NULL
408  * @v txbufs            Recycled transmit buffer address, or NULL
409  * @ret efirc           EFI status code
410  */
411 static EFI_STATUS EFIAPI
412 efi_snp_get_status ( EFI_SIMPLE_NETWORK_PROTOCOL *snp,
413                      UINT32 *interrupts, VOID **txbufs ) {
414         struct efi_snp_device *snpdev =
415                 container_of ( snp, struct efi_snp_device, snp );
416
417         DBGC2 ( snpdev, "SNPDEV %p GET_STATUS", snpdev );
418
419         /* Poll the network device */
420         efi_snp_poll ( snpdev );
421
422         /* Interrupt status.  In practice, this seems to be used only
423          * to detect TX completions.
424          */
425         if ( interrupts ) {
426                 *interrupts = 0;
427                 /* Report TX completions once queue is empty; this
428                  * avoids having to add hooks in the net device layer.
429                  */
430                 if ( snpdev->tx_count_interrupts &&
431                      list_empty ( &snpdev->netdev->tx_queue ) ) {
432                         *interrupts |= EFI_SIMPLE_NETWORK_TRANSMIT_INTERRUPT;
433                         snpdev->tx_count_interrupts--;
434                 }
435                 /* Report RX */
436                 if ( snpdev->rx_count_interrupts ) {
437                         *interrupts |= EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT;
438                         snpdev->rx_count_interrupts--;
439                 }
440                 DBGC2 ( snpdev, " INTS:%02x", *interrupts );
441         }
442
443         /* TX completions.  It would be possible to design a more
444          * idiotic scheme for this, but it would be a challenge.
445          * According to the UEFI header file, txbufs will be filled in
446          * with a list of "recycled transmit buffers" (i.e. completed
447          * TX buffers).  Observant readers may care to note that
448          * *txbufs is a void pointer.  Precisely how a list of
449          * completed transmit buffers is meant to be represented as an
450          * array of voids is left as an exercise for the reader.
451          *
452          * The only users of this interface (MnpDxe/MnpIo.c and
453          * PxeBcDxe/Bc.c within the EFI dev kit) both just poll until
454          * seeing a non-NULL result return in txbufs.  This is valid
455          * provided that they do not ever attempt to transmit more
456          * than one packet concurrently (and that TX never times out).
457          */
458         if ( txbufs ) {
459                 if ( snpdev->tx_count_txbufs &&
460                      list_empty ( &snpdev->netdev->tx_queue ) ) {
461                         *txbufs = "Which idiot designed this API?";
462                         snpdev->tx_count_txbufs--;
463                 } else {
464                         *txbufs = NULL;
465                 }
466                 DBGC2 ( snpdev, " TX:%s", ( *txbufs ? "some" : "none" ) );
467         }
468
469         DBGC2 ( snpdev, "\n" );
470         return 0;
471 }
472
473 /**
474  * Start packet transmission
475  *
476  * @v snp               SNP interface
477  * @v ll_header_len     Link-layer header length, if to be filled in
478  * @v len               Length of data buffer
479  * @v data              Data buffer
480  * @v ll_src            Link-layer source address, if specified
481  * @v ll_dest           Link-layer destination address, if specified
482  * @v net_proto         Network-layer protocol (in host order)
483  * @ret efirc           EFI status code
484  */
485 static EFI_STATUS EFIAPI
486 efi_snp_transmit ( EFI_SIMPLE_NETWORK_PROTOCOL *snp,
487                    UINTN ll_header_len, UINTN len, VOID *data,
488                    EFI_MAC_ADDRESS *ll_src, EFI_MAC_ADDRESS *ll_dest,
489                    UINT16 *net_proto ) {
490         struct efi_snp_device *snpdev =
491                 container_of ( snp, struct efi_snp_device, snp );
492         struct ll_protocol *ll_protocol = snpdev->netdev->ll_protocol;
493         struct io_buffer *iobuf;
494         int rc;
495         EFI_STATUS efirc;
496
497         DBGC2 ( snpdev, "SNPDEV %p TRANSMIT %p+%lx", snpdev, data,
498                 ( ( unsigned long ) len ) );
499         if ( ll_header_len ) {
500                 if ( ll_src ) {
501                         DBGC2 ( snpdev, " src %s",
502                                 ll_protocol->ntoa ( ll_src ) );
503                 }
504                 if ( ll_dest ) {
505                         DBGC2 ( snpdev, " dest %s",
506                                 ll_protocol->ntoa ( ll_dest ) );
507                 }
508                 if ( net_proto ) {
509                         DBGC2 ( snpdev, " proto %04x", *net_proto );
510                 }
511         }
512         DBGC2 ( snpdev, "\n" );
513
514         /* Sanity checks */
515         if ( ll_header_len ) {
516                 if ( ll_header_len != ll_protocol->ll_header_len ) {
517                         DBGC ( snpdev, "SNPDEV %p TX invalid header length "
518                                "%ld\n", snpdev,
519                                ( ( unsigned long ) ll_header_len ) );
520                         efirc = EFI_INVALID_PARAMETER;
521                         goto err_sanity;
522                 }
523                 if ( len < ll_header_len ) {
524                         DBGC ( snpdev, "SNPDEV %p invalid packet length %ld\n",
525                                snpdev, ( ( unsigned long ) len ) );
526                         efirc = EFI_BUFFER_TOO_SMALL;
527                         goto err_sanity;
528                 }
529                 if ( ! ll_dest ) {
530                         DBGC ( snpdev, "SNPDEV %p TX missing destination "
531                                "address\n", snpdev );
532                         efirc = EFI_INVALID_PARAMETER;
533                         goto err_sanity;
534                 }
535                 if ( ! net_proto ) {
536                         DBGC ( snpdev, "SNPDEV %p TX missing network "
537                                "protocol\n", snpdev );
538                         efirc = EFI_INVALID_PARAMETER;
539                         goto err_sanity;
540                 }
541                 if ( ! ll_src )
542                         ll_src = &snpdev->mode.CurrentAddress;
543         }
544
545         /* Allocate buffer */
546         iobuf = alloc_iob ( len );
547         if ( ! iobuf ) {
548                 DBGC ( snpdev, "SNPDEV %p TX could not allocate %ld-byte "
549                        "buffer\n", snpdev, ( ( unsigned long ) len ) );
550                 efirc = EFI_DEVICE_ERROR;
551                 goto err_alloc_iob;
552         }
553         memcpy ( iob_put ( iobuf, len ), data, len );
554
555         /* Create link-layer header, if specified */
556         if ( ll_header_len ) {
557                 iob_pull ( iobuf, ll_header_len );
558                 if ( ( rc = ll_protocol->push ( iobuf, ll_dest, ll_src,
559                                                 htons ( *net_proto ) )) != 0 ){
560                         DBGC ( snpdev, "SNPDEV %p TX could not construct "
561                                "header: %s\n", snpdev, strerror ( rc ) );
562                         efirc = RC_TO_EFIRC ( rc );
563                         goto err_ll_push;
564                 }
565         }
566
567         /* Transmit packet */
568         if ( ( rc = netdev_tx ( snpdev->netdev, iobuf ) ) != 0 ) {
569                 DBGC ( snpdev, "SNPDEV %p TX could not transmit: %s\n",
570                        snpdev, strerror ( rc ) );
571                 iobuf = NULL;
572                 efirc = RC_TO_EFIRC ( rc );
573                 goto err_tx;
574         }
575
576         /* Record transmission as outstanding */
577         snpdev->tx_count_interrupts++;
578         snpdev->tx_count_txbufs++;
579
580         return 0;
581
582  err_tx:
583  err_ll_push:
584         free_iob ( iobuf );
585  err_alloc_iob:
586  err_sanity:
587         return efirc;
588 }
589
590 /**
591  * Receive packet
592  *
593  * @v snp               SNP interface
594  * @v ll_header_len     Link-layer header length, if to be filled in
595  * @v len               Length of data buffer
596  * @v data              Data buffer
597  * @v ll_src            Link-layer source address, if specified
598  * @v ll_dest           Link-layer destination address, if specified
599  * @v net_proto         Network-layer protocol (in host order)
600  * @ret efirc           EFI status code
601  */
602 static EFI_STATUS EFIAPI
603 efi_snp_receive ( EFI_SIMPLE_NETWORK_PROTOCOL *snp,
604                   UINTN *ll_header_len, UINTN *len, VOID *data,
605                   EFI_MAC_ADDRESS *ll_src, EFI_MAC_ADDRESS *ll_dest,
606                   UINT16 *net_proto ) {
607         struct efi_snp_device *snpdev =
608                 container_of ( snp, struct efi_snp_device, snp );
609         struct ll_protocol *ll_protocol = snpdev->netdev->ll_protocol;
610         struct io_buffer *iobuf;
611         const void *iob_ll_dest;
612         const void *iob_ll_src;
613         uint16_t iob_net_proto;
614         int rc;
615         EFI_STATUS efirc;
616
617         DBGC2 ( snpdev, "SNPDEV %p RECEIVE %p(+%lx)", snpdev, data,
618                 ( ( unsigned long ) *len ) );
619
620         /* Poll the network device */
621         efi_snp_poll ( snpdev );
622
623         /* Dequeue a packet, if one is available */
624         iobuf = netdev_rx_dequeue ( snpdev->netdev );
625         if ( ! iobuf ) {
626                 DBGC2 ( snpdev, "\n" );
627                 efirc = EFI_NOT_READY;
628                 goto out_no_packet;
629         }
630         DBGC2 ( snpdev, "+%zx\n", iob_len ( iobuf ) );
631
632         /* Return packet to caller */
633         memcpy ( data, iobuf->data, iob_len ( iobuf ) );
634         *len = iob_len ( iobuf );
635
636         /* Attempt to decode link-layer header */
637         if ( ( rc = ll_protocol->pull ( iobuf, &iob_ll_dest, &iob_ll_src,
638                                         &iob_net_proto ) ) != 0 ) {
639                 DBGC ( snpdev, "SNPDEV %p could not parse header: %s\n",
640                        snpdev, strerror ( rc ) );
641                 efirc = RC_TO_EFIRC ( rc );
642                 goto out_bad_ll_header;
643         }
644
645         /* Return link-layer header parameters to caller, if required */
646         if ( ll_header_len )
647                 *ll_header_len = ll_protocol->ll_header_len;
648         if ( ll_src )
649                 memcpy ( ll_src, iob_ll_src, ll_protocol->ll_addr_len );
650         if ( ll_dest )
651                 memcpy ( ll_dest, iob_ll_dest, ll_protocol->ll_addr_len );
652         if ( net_proto )
653                 *net_proto = ntohs ( iob_net_proto );
654
655         efirc = 0;
656
657  out_bad_ll_header:
658         free_iob ( iobuf );
659 out_no_packet:
660         return efirc;
661 }
662
663 /**
664  * Poll event
665  *
666  * @v event             Event
667  * @v context           Event context
668  */
669 static VOID EFIAPI efi_snp_wait_for_packet ( EFI_EVENT event,
670                                              VOID *context ) {
671         EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
672         struct efi_snp_device *snpdev = context;
673
674         DBGCP ( snpdev, "SNPDEV %p WAIT_FOR_PACKET\n", snpdev );
675
676         /* Do nothing unless the net device is open */
677         if ( ! ( snpdev->netdev->state & NETDEV_OPEN ) )
678                 return;
679
680         /* Poll the network device */
681         efi_snp_poll ( snpdev );
682
683         /* Fire event if packets have been received */
684         if ( snpdev->rx_count_events != 0 ) {
685                 DBGC2 ( snpdev, "SNPDEV %p firing WaitForPacket event\n",
686                         snpdev );
687                 bs->SignalEvent ( event );
688                 snpdev->rx_count_events--;
689         }
690 }
691
692 /** SNP interface */
693 static EFI_SIMPLE_NETWORK_PROTOCOL efi_snp_device_snp = {
694         .Revision       = EFI_SIMPLE_NETWORK_PROTOCOL_REVISION,
695         .Start          = efi_snp_start,
696         .Stop           = efi_snp_stop,
697         .Initialize     = efi_snp_initialize,
698         .Reset          = efi_snp_reset,
699         .Shutdown       = efi_snp_shutdown,
700         .ReceiveFilters = efi_snp_receive_filters,
701         .StationAddress = efi_snp_station_address,
702         .Statistics     = efi_snp_statistics,
703         .MCastIpToMac   = efi_snp_mcast_ip_to_mac,
704         .NvData         = efi_snp_nvdata,
705         .GetStatus      = efi_snp_get_status,
706         .Transmit       = efi_snp_transmit,
707         .Receive        = efi_snp_receive,
708 };
709
710 /**
711  * Locate net device corresponding to EFI device
712  *
713  * @v driver            EFI driver
714  * @v device            EFI device
715  * @ret netdev          Net device, or NULL if not found
716  */
717 static struct net_device *
718 efi_snp_netdev ( EFI_DRIVER_BINDING_PROTOCOL *driver, EFI_HANDLE device ) {
719         EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
720         union {
721                 EFI_PCI_IO_PROTOCOL *pci;
722                 void *interface;
723         } u;
724         UINTN pci_segment, pci_bus, pci_dev, pci_fn;
725         unsigned int pci_busdevfn;
726         struct net_device *netdev = NULL;
727         EFI_STATUS efirc;
728
729         /* See if device is a PCI device */
730         if ( ( efirc = bs->OpenProtocol ( device,
731                                           &efi_pci_io_protocol_guid,
732                                           &u.interface,
733                                           driver->DriverBindingHandle,
734                                           device,
735                                           EFI_OPEN_PROTOCOL_BY_DRIVER )) !=0 ){
736                 DBGCP ( driver, "SNPDRV %p device %p is not a PCI device\n",
737                         driver, device );
738                 goto out_no_pci_io;
739         }
740
741         /* Get PCI bus:dev.fn address */
742         if ( ( efirc = u.pci->GetLocation ( u.pci, &pci_segment, &pci_bus,
743                                             &pci_dev, &pci_fn ) ) != 0 ) {
744                 DBGC ( driver, "SNPDRV %p device %p could not get PCI "
745                        "location: %s\n",
746                        driver, device, efi_strerror ( efirc ) );
747                 goto out_no_pci_location;
748         }
749         DBGCP ( driver, "SNPDRV %p device %p is PCI %04lx:%02lx:%02lx.%lx\n",
750                 driver, device, ( ( unsigned long ) pci_segment ),
751                 ( ( unsigned long ) pci_bus ), ( ( unsigned long ) pci_dev ),
752                 ( ( unsigned long ) pci_fn ) );
753
754         /* Look up corresponding network device */
755         pci_busdevfn = PCI_BUSDEVFN ( pci_bus, PCI_DEVFN ( pci_dev, pci_fn ) );
756         if ( ( netdev = find_netdev_by_location ( BUS_TYPE_PCI,
757                                                   pci_busdevfn ) ) == NULL ) {
758                 DBGCP ( driver, "SNPDRV %p device %p is not a gPXE network "
759                         "device\n", driver, device );
760                 goto out_no_netdev;
761         }
762         DBGC ( driver, "SNPDRV %p device %p is %s\n",
763                driver, device, netdev->name );
764
765  out_no_netdev:
766  out_no_pci_location:
767         bs->CloseProtocol ( device, &efi_pci_io_protocol_guid,
768                             driver->DriverBindingHandle, device );
769  out_no_pci_io:
770         return netdev;
771 }
772
773 /**
774  * Locate SNP corresponding to EFI device
775  *
776  * @v driver            EFI driver
777  * @v device            EFI device
778  * @ret snp             EFI SNP, or NULL if not found
779  */
780 static struct efi_snp_device *
781 efi_snp_snpdev ( EFI_DRIVER_BINDING_PROTOCOL *driver, EFI_HANDLE device ) {
782         EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
783         union {
784                 EFI_SIMPLE_NETWORK_PROTOCOL *snp;
785                 void *interface;
786         } u;
787         struct efi_snp_device *snpdev;
788         EFI_STATUS efirc;
789
790         if ( ( efirc = bs->OpenProtocol ( device,
791                                           &efi_simple_network_protocol_guid,
792                                           &u.interface,
793                                           driver->DriverBindingHandle,
794                                           device,
795                                           EFI_OPEN_PROTOCOL_GET_PROTOCOL))!=0){
796                 DBGC ( driver, "SNPDRV %p device %p could not locate SNP: "
797                        "%s\n", driver, device, efi_strerror ( efirc ) );
798                 return NULL;
799         }
800
801         snpdev =  container_of ( u.snp, struct efi_snp_device, snp );
802         DBGCP ( driver, "SNPDRV %p device %p is SNPDEV %p\n",
803                 driver, device, snpdev );
804         return snpdev;
805 }
806
807 /**
808  * Check to see if driver supports a device
809  *
810  * @v driver            EFI driver
811  * @v device            EFI device
812  * @v child             Path to child device, if any
813  * @ret efirc           EFI status code
814  */
815 static EFI_STATUS EFIAPI
816 efi_snp_driver_supported ( EFI_DRIVER_BINDING_PROTOCOL *driver,
817                            EFI_HANDLE device,
818                            EFI_DEVICE_PATH_PROTOCOL *child ) {
819         struct net_device *netdev;
820
821         DBGCP ( driver, "SNPDRV %p DRIVER_SUPPORTED %p (%p)\n",
822                 driver, device, child );
823
824         netdev = efi_snp_netdev ( driver, device );
825         return ( netdev ? 0 : EFI_UNSUPPORTED );
826 }
827
828 /**
829  * Attach driver to device
830  *
831  * @v driver            EFI driver
832  * @v device            EFI device
833  * @v child             Path to child device, if any
834  * @ret efirc           EFI status code
835  */
836 static EFI_STATUS EFIAPI
837 efi_snp_driver_start ( EFI_DRIVER_BINDING_PROTOCOL *driver,
838                        EFI_HANDLE device,
839                        EFI_DEVICE_PATH_PROTOCOL *child ) {
840         EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
841         struct efi_snp_device *snpdev;
842         struct net_device *netdev;
843         EFI_STATUS efirc;
844
845         DBGCP ( driver, "SNPDRV %p DRIVER_START %p (%p)\n",
846                 driver, device, child );
847
848         /* Allocate the SNP device */
849         snpdev = zalloc ( sizeof ( *snpdev ) );
850         if ( ! snpdev ) {
851                 efirc = EFI_OUT_OF_RESOURCES;
852                 goto err_alloc_snp;
853         }
854
855         /* Identify the net device */
856         netdev = efi_snp_netdev ( driver, device );
857         if ( ! netdev ) {
858                 DBGC ( snpdev, "SNPDEV %p cannot find netdev for device %p\n",
859                        snpdev, device );
860                 efirc = EFI_UNSUPPORTED;
861                 goto err_no_netdev;
862         }
863         snpdev->netdev = netdev_get ( netdev );
864
865         /* Sanity check */
866         if ( netdev->ll_protocol->ll_addr_len > sizeof ( EFI_MAC_ADDRESS ) ) {
867                 DBGC ( snpdev, "SNPDEV %p cannot support link-layer address "
868                        "length %d for %s\n", snpdev,
869                        netdev->ll_protocol->ll_addr_len, netdev->name );
870                 efirc = EFI_INVALID_PARAMETER;
871                 goto err_ll_addr_len;
872         }
873
874         /* Populate the SNP structure */
875         memcpy ( &snpdev->snp, &efi_snp_device_snp, sizeof ( snpdev->snp ) );
876         snpdev->snp.Mode = &snpdev->mode;
877         if ( ( efirc = bs->CreateEvent ( EVT_NOTIFY_WAIT, TPL_NOTIFY,
878                                          efi_snp_wait_for_packet, snpdev,
879                                          &snpdev->snp.WaitForPacket ) ) != 0 ){
880                 DBGC ( snpdev, "SNPDEV %p could not create event: %s\n",
881                        snpdev, efi_strerror ( efirc ) );
882                 goto err_create_event;
883         }
884
885         /* Populate the SNP mode structure */
886         snpdev->mode.State = EfiSimpleNetworkStopped;
887         efi_snp_set_mode ( snpdev );
888
889         /* Install the SNP */
890         if ( ( efirc = bs->InstallProtocolInterface ( &device,
891                                 &efi_simple_network_protocol_guid,
892                                 EFI_NATIVE_INTERFACE, &snpdev->snp ) ) != 0 ) {
893                 DBGC ( snpdev, "SNPDEV %p could not install protocol: %s\n",
894                        snpdev, efi_strerror ( efirc ) );
895                 goto err_install_protocol_interface;
896         }
897
898         DBGC ( snpdev, "SNPDEV %p installed for %s on device %p\n",
899                snpdev, netdev->name, device );
900         return 0;
901
902         bs->UninstallProtocolInterface ( device,
903                                          &efi_simple_network_protocol_guid,
904                                          &snpdev->snp );
905  err_install_protocol_interface:
906         bs->CloseEvent ( snpdev->snp.WaitForPacket );
907  err_create_event:
908  err_ll_addr_len:
909         netdev_put ( netdev );
910  err_no_netdev:
911         free ( snpdev );
912  err_alloc_snp:
913         return efirc;
914 }
915
916 /**
917  * Detach driver from device
918  *
919  * @v driver            EFI driver
920  * @v device            EFI device
921  * @v num_children      Number of child devices
922  * @v children          List of child devices
923  * @ret efirc           EFI status code
924  */
925 static EFI_STATUS EFIAPI
926 efi_snp_driver_stop ( EFI_DRIVER_BINDING_PROTOCOL *driver,
927                       EFI_HANDLE device,
928                       UINTN num_children,
929                       EFI_HANDLE *children ) {
930         EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
931         struct efi_snp_device *snpdev;
932
933         DBGCP ( driver, "SNPDRV %p DRIVER_STOP %p (%ld %p)\n",
934                 driver, device, ( ( unsigned long ) num_children ), children );
935
936         /* Locate SNP device */
937         snpdev = efi_snp_snpdev ( driver, device );
938         if ( ! snpdev ) {
939                 DBGC ( driver, "SNPDRV %p device %p could not find SNPDEV\n",
940                        driver, device );
941                 return EFI_DEVICE_ERROR;
942         }
943
944         /* Uninstall the SNP */
945         bs->UninstallProtocolInterface ( device,
946                                          &efi_simple_network_protocol_guid,
947                                          &snpdev->snp );
948         bs->CloseEvent ( snpdev->snp.WaitForPacket );
949         netdev_put ( snpdev->netdev );
950         free ( snpdev );
951         return 0;
952 }
953
954 /** EFI SNP driver binding */
955 static EFI_DRIVER_BINDING_PROTOCOL efi_snp_binding = {
956         efi_snp_driver_supported,
957         efi_snp_driver_start,
958         efi_snp_driver_stop,
959         0x10,
960         NULL,
961         NULL
962 };
963
964 /**
965  * Install EFI SNP driver
966  *
967  * @ret rc              Return status code
968  */
969 int efi_snp_install ( void ) {
970         EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
971         EFI_DRIVER_BINDING_PROTOCOL *driver = &efi_snp_binding;
972         EFI_STATUS efirc;
973
974         driver->ImageHandle = efi_image_handle;
975         if ( ( efirc = bs->InstallProtocolInterface (
976                                         &driver->DriverBindingHandle,
977                                         &efi_driver_binding_protocol_guid,
978                                         EFI_NATIVE_INTERFACE,
979                                         driver ) ) != 0 ) {
980                 DBGC ( driver, "SNPDRV %p could not install driver binding: "
981                        "%s\n", driver, efi_strerror ( efirc ) );
982                 return EFIRC_TO_RC ( efirc );
983         }
984
985         DBGC ( driver, "SNPDRV %p driver binding installed as %p\n",
986                driver, driver->DriverBindingHandle );
987         return 0;
988 }