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