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