1 /** @file
2
3 Copyright (c) 2010, Apple, Inc. All rights reserved.<BR>
4 Copyright (c) 2011, Intel Corporation. All rights reserved.<BR>
5
6 This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
10
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13
14 Module Name:
15
16 EmuSnp.c
17
18 Abstract:
19
20 -**/
21
22 #include "EmuSnpDxe.h"
23
24
25
26 EFI_SIMPLE_NETWORK_PROTOCOL gEmuSnpTemplate = {
27 EFI_SIMPLE_NETWORK_PROTOCOL_REVISION,
28 EmuSnpStart,
29 EmuSnpStop,
30 EmuSnpInitialize,
31 EmuSnpReset,
32 EmuSnpShutdown,
33 EmuSnpReceiveFilters,
34 EmuSnpStationAddress,
35 EmuSnpStatistics,
36 EmuSnpMcastIptoMac,
37 EmuSnpNvdata,
38 EmuSnpGetStatus,
39 EmuSnpTransmit,
40 EmuSnpReceive,
41 NULL, // WaitForPacket
42 NULL // Mode
43 };
44
45 EFI_SIMPLE_NETWORK_MODE gEmuSnpModeTemplate = {
46 EfiSimpleNetworkStopped, // State
47 NET_ETHER_ADDR_LEN, // HwAddressSize
48 NET_ETHER_HEADER_SIZE, // MediaHeaderSize
49 1500, // MaxPacketSize
50 0, // NvRamSize
51 0, // NvRamAccessSize
52 0, // ReceiveFilterMask
53 0, // ReceiveFilterSetting
54 MAX_MCAST_FILTER_CNT, // MaxMCastFilterCount
55 0, // MCastFilterCount
56 {
57 { { 0 } }
58 }, // MCastFilter
59 {
60 { 0 }
61 }, // CurrentAddress
62 {
63 { 0 }
64 }, // BroadcastAddress
65 {
66 { 0 }
67 }, // PermanentAddress
68 NET_IFTYPE_ETHERNET, // IfType
69 FALSE, // MacAddressChangeable
70 FALSE, // MultipleTxSupported
71 FALSE, // MediaPresentSupported
72 TRUE // MediaPresent
73 };
74
75
76 /**
77 Changes the state of a network interface from "stopped" to "started".
78
79 @param This Protocol instance pointer.
80
81 @retval EFI_SUCCESS Always succeeds.
82
83 **/
84 EFI_STATUS
85 EFIAPI
EmuSnpStart(IN EFI_SIMPLE_NETWORK_PROTOCOL * This)86 EmuSnpStart(
87 IN EFI_SIMPLE_NETWORK_PROTOCOL *This
88 )
89 {
90 EFI_STATUS Status;
91 EMU_SNP_PRIVATE_DATA *Private;
92
93 Private = EMU_SNP_PRIVATE_DATA_FROM_SNP_THIS (This);
94
95 Status = Private->Io->Start (Private->Io);
96 return Status;
97 }
98
99
100 /**
101 Changes the state of a network interface from "started" to "stopped".
102
103 @param This Protocol instance pointer.
104
105 @retval EFI_SUCCESS Always succeeds.
106
107 **/
108 EFI_STATUS
109 EFIAPI
EmuSnpStop(IN EFI_SIMPLE_NETWORK_PROTOCOL * This)110 EmuSnpStop (
111 IN EFI_SIMPLE_NETWORK_PROTOCOL *This
112 )
113 {
114 EFI_STATUS Status;
115 EMU_SNP_PRIVATE_DATA *Private;
116
117 Private = EMU_SNP_PRIVATE_DATA_FROM_SNP_THIS (This);
118
119 Status = Private->Io->Stop (Private->Io);
120 return Status;
121 }
122
123
124 /**
125 Resets a network adapter and allocates the transmit and receive buffers
126 required by the network interface; optionally, also requests allocation
127 of additional transmit and receive buffers.
128
129 @param This Protocol instance pointer.
130 @param ExtraRxBufferSize The size, in bytes, of the extra receive buffer space
131 that the driver should allocate for the network interface.
132 Some network interfaces will not be able to use the extra
133 buffer, and the caller will not know if it is actually
134 being used.
135 @param ExtraTxBufferSize The size, in bytes, of the extra transmit buffer space
136 that the driver should allocate for the network interface.
137 Some network interfaces will not be able to use the extra
138 buffer, and the caller will not know if it is actually
139 being used.
140
141 @retval EFI_SUCCESS Always succeeds.
142
143 **/
144 EFI_STATUS
145 EFIAPI
EmuSnpInitialize(IN EFI_SIMPLE_NETWORK_PROTOCOL * This,IN UINTN ExtraRxBufferSize OPTIONAL,IN UINTN ExtraTxBufferSize OPTIONAL)146 EmuSnpInitialize (
147 IN EFI_SIMPLE_NETWORK_PROTOCOL *This,
148 IN UINTN ExtraRxBufferSize OPTIONAL,
149 IN UINTN ExtraTxBufferSize OPTIONAL
150 )
151 {
152 EFI_STATUS Status;
153 EMU_SNP_PRIVATE_DATA *Private;
154
155 Private = EMU_SNP_PRIVATE_DATA_FROM_SNP_THIS (This);
156
157 Status = Private->Io->Initialize (Private->Io, ExtraRxBufferSize, ExtraTxBufferSize);
158 return Status;
159 }
160
161 /**
162 Resets a network adapter and re-initializes it with the parameters that were
163 provided in the previous call to Initialize().
164
165 @param This Protocol instance pointer.
166 @param ExtendedVerification Indicates that the driver may perform a more
167 exhaustive verification operation of the device
168 during reset.
169
170 @retval EFI_SUCCESS Always succeeds.
171
172 **/
173 EFI_STATUS
174 EFIAPI
EmuSnpReset(IN EFI_SIMPLE_NETWORK_PROTOCOL * This,IN BOOLEAN ExtendedVerification)175 EmuSnpReset (
176 IN EFI_SIMPLE_NETWORK_PROTOCOL *This,
177 IN BOOLEAN ExtendedVerification
178 )
179 {
180 EFI_STATUS Status;
181 EMU_SNP_PRIVATE_DATA *Private;
182
183 Private = EMU_SNP_PRIVATE_DATA_FROM_SNP_THIS (This);
184
185 Status = Private->Io->Reset (Private->Io, ExtendedVerification);
186 return Status;
187 }
188
189 /**
190 Resets a network adapter and leaves it in a state that is safe for
191 another driver to initialize.
192
193 @param This Protocol instance pointer.
194
195 @retval EFI_SUCCESS Always succeeds.
196
197 **/
198 EFI_STATUS
199 EFIAPI
EmuSnpShutdown(IN EFI_SIMPLE_NETWORK_PROTOCOL * This)200 EmuSnpShutdown (
201 IN EFI_SIMPLE_NETWORK_PROTOCOL *This
202 )
203 {
204 EFI_STATUS Status;
205 EMU_SNP_PRIVATE_DATA *Private;
206
207 Private = EMU_SNP_PRIVATE_DATA_FROM_SNP_THIS (This);
208
209 Status = Private->Io->Shutdown (Private->Io);
210 return Status;
211 }
212
213 /**
214 Manages the multicast receive filters of a network interface.
215
216 @param This Protocol instance pointer.
217 @param EnableBits A bit mask of receive filters to enable on the network interface.
218 @param DisableBits A bit mask of receive filters to disable on the network interface.
219 @param ResetMcastFilter Set to TRUE to reset the contents of the multicast receive
220 filters on the network interface to their default values.
221 @param McastFilterCount Number of multicast HW MAC addresses in the new
222 MCastFilter list. This value must be less than or equal to
223 the MCastFilterCnt field of EFI_SIMPLE_NETWORK_MODE. This
224 field is optional if ResetMCastFilter is TRUE.
225 @param McastFilter A pointer to a list of new multicast receive filter HW MAC
226 addresses. This list will replace any existing multicast
227 HW MAC address list. This field is optional if
228 ResetMCastFilter is TRUE.
229
230 @retval EFI_SUCCESS The multicast receive filter list was updated.
231 @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.
232
233 **/
234 EFI_STATUS
235 EFIAPI
EmuSnpReceiveFilters(IN EFI_SIMPLE_NETWORK_PROTOCOL * This,IN UINT32 EnableBits,IN UINT32 DisableBits,IN BOOLEAN ResetMcastFilter,IN UINTN McastFilterCount OPTIONAL,IN EFI_MAC_ADDRESS * McastFilter OPTIONAL)236 EmuSnpReceiveFilters (
237 IN EFI_SIMPLE_NETWORK_PROTOCOL *This,
238 IN UINT32 EnableBits,
239 IN UINT32 DisableBits,
240 IN BOOLEAN ResetMcastFilter,
241 IN UINTN McastFilterCount OPTIONAL,
242 IN EFI_MAC_ADDRESS *McastFilter OPTIONAL
243 )
244 {
245 EFI_STATUS Status;
246 EMU_SNP_PRIVATE_DATA *Private;
247
248 Private = EMU_SNP_PRIVATE_DATA_FROM_SNP_THIS (This);
249
250 Status = Private->Io->ReceiveFilters (
251 Private->Io,
252 EnableBits,
253 DisableBits,
254 ResetMcastFilter,
255 McastFilterCount,
256 McastFilter
257 );
258 return Status;
259 }
260
261 /**
262 Modifies or resets the current station address, if supported.
263
264 @param This Protocol instance pointer.
265 @param Reset Flag used to reset the station address to the network interfaces
266 permanent address.
267 @param NewMacAddr New station address to be used for the network interface.
268
269 @retval EFI_UNSUPPORTED Not supported yet.
270
271 **/
272 EFI_STATUS
273 EFIAPI
EmuSnpStationAddress(IN EFI_SIMPLE_NETWORK_PROTOCOL * This,IN BOOLEAN Reset,IN EFI_MAC_ADDRESS * NewMacAddr OPTIONAL)274 EmuSnpStationAddress (
275 IN EFI_SIMPLE_NETWORK_PROTOCOL *This,
276 IN BOOLEAN Reset,
277 IN EFI_MAC_ADDRESS *NewMacAddr OPTIONAL
278 )
279 {
280 EFI_STATUS Status;
281 EMU_SNP_PRIVATE_DATA *Private;
282
283 Private = EMU_SNP_PRIVATE_DATA_FROM_SNP_THIS (This);
284
285 Status = Private->Io->StationAddress (Private->Io, Reset, NewMacAddr);
286 return Status;
287 }
288
289 /**
290 Resets or collects the statistics on a network interface.
291
292 @param This Protocol instance pointer.
293 @param Reset Set to TRUE to reset the statistics for the network interface.
294 @param StatisticsSize On input the size, in bytes, of StatisticsTable. On
295 output the size, in bytes, of the resulting table of
296 statistics.
297 @param StatisticsTable A pointer to the EFI_NETWORK_STATISTICS structure that
298 contains the statistics.
299
300 @retval EFI_SUCCESS The statistics were collected from the network interface.
301 @retval EFI_NOT_STARTED The network interface has not been started.
302 @retval EFI_BUFFER_TOO_SMALL The Statistics buffer was too small. The current buffer
303 size needed to hold the statistics is returned in
304 StatisticsSize.
305 @retval EFI_UNSUPPORTED Not supported yet.
306
307 **/
308 EFI_STATUS
309 EFIAPI
EmuSnpStatistics(IN EFI_SIMPLE_NETWORK_PROTOCOL * This,IN BOOLEAN Reset,IN OUT UINTN * StatisticsSize OPTIONAL,OUT EFI_NETWORK_STATISTICS * StatisticsTable OPTIONAL)310 EmuSnpStatistics (
311 IN EFI_SIMPLE_NETWORK_PROTOCOL *This,
312 IN BOOLEAN Reset,
313 IN OUT UINTN *StatisticsSize OPTIONAL,
314 OUT EFI_NETWORK_STATISTICS *StatisticsTable OPTIONAL
315 )
316 {
317 EFI_STATUS Status;
318 EMU_SNP_PRIVATE_DATA *Private;
319
320 Private = EMU_SNP_PRIVATE_DATA_FROM_SNP_THIS (This);
321
322 Status = Private->Io->Statistics (Private->Io, Reset, StatisticsSize, StatisticsTable);
323 return Status;
324 }
325
326 /**
327 Converts a multicast IP address to a multicast HW MAC address.
328
329 @param This Protocol instance pointer.
330 @param Ipv6 Set to TRUE if the multicast IP address is IPv6 [RFC 2460]. Set
331 to FALSE if the multicast IP address is IPv4 [RFC 791].
332 @param Ip The multicast IP address that is to be converted to a multicast
333 HW MAC address.
334 @param Mac The multicast HW MAC address that is to be generated from IP.
335
336 @retval EFI_SUCCESS The multicast IP address was mapped to the multicast
337 HW MAC address.
338 @retval EFI_NOT_STARTED The network interface has not been started.
339 @retval EFI_BUFFER_TOO_SMALL The Statistics buffer was too small. The current buffer
340 size needed to hold the statistics is returned in
341 StatisticsSize.
342 @retval EFI_UNSUPPORTED Not supported yet.
343
344 **/
345 EFI_STATUS
346 EFIAPI
EmuSnpMcastIptoMac(IN EFI_SIMPLE_NETWORK_PROTOCOL * This,IN BOOLEAN Ipv6,IN EFI_IP_ADDRESS * Ip,OUT EFI_MAC_ADDRESS * Mac)347 EmuSnpMcastIptoMac (
348 IN EFI_SIMPLE_NETWORK_PROTOCOL *This,
349 IN BOOLEAN Ipv6,
350 IN EFI_IP_ADDRESS *Ip,
351 OUT EFI_MAC_ADDRESS *Mac
352 )
353 {
354 EFI_STATUS Status;
355 EMU_SNP_PRIVATE_DATA *Private;
356
357 Private = EMU_SNP_PRIVATE_DATA_FROM_SNP_THIS (This);
358
359 Status = Private->Io->MCastIpToMac (Private->Io, Ipv6, Ip, Mac);
360 return Status;
361 }
362
363
364 /**
365 Performs read and write operations on the NVRAM device attached to a
366 network interface.
367
368 @param This Protocol instance pointer.
369 @param ReadOrWrite TRUE for read operations, FALSE for write operations.
370 @param Offset Byte offset in the NVRAM device at which to start the read or
371 write operation. This must be a multiple of NvRamAccessSize and
372 less than NvRamSize.
373 @param BufferSize The number of bytes to read or write from the NVRAM device.
374 This must also be a multiple of NvramAccessSize.
375 @param Buffer A pointer to the data buffer.
376
377 @retval EFI_UNSUPPORTED Not supported yet.
378
379 **/
380 EFI_STATUS
381 EFIAPI
EmuSnpNvdata(IN EFI_SIMPLE_NETWORK_PROTOCOL * This,IN BOOLEAN ReadOrWrite,IN UINTN Offset,IN UINTN BufferSize,IN OUT VOID * Buffer)382 EmuSnpNvdata (
383 IN EFI_SIMPLE_NETWORK_PROTOCOL *This,
384 IN BOOLEAN ReadOrWrite,
385 IN UINTN Offset,
386 IN UINTN BufferSize,
387 IN OUT VOID *Buffer
388 )
389 {
390 EFI_STATUS Status;
391 EMU_SNP_PRIVATE_DATA *Private;
392
393 Private = EMU_SNP_PRIVATE_DATA_FROM_SNP_THIS (This);
394
395 Status = Private->Io->NvData (Private->Io, ReadOrWrite, Offset, BufferSize, Buffer);
396 return Status;
397 }
398
399
400 /**
401 Reads the current interrupt status and recycled transmit buffer status from
402 a network interface.
403
404 @param This Protocol instance pointer.
405 @param InterruptStatus A pointer to the bit mask of the currently active interrupts
406 If this is NULL, the interrupt status will not be read from
407 the device. If this is not NULL, the interrupt status will
408 be read from the device. When the interrupt status is read,
409 it will also be cleared. Clearing the transmit interrupt
410 does not empty the recycled transmit buffer array.
411 @param TxBuffer Recycled transmit buffer address. The network interface will
412 not transmit if its internal recycled transmit buffer array
413 is full. Reading the transmit buffer does not clear the
414 transmit interrupt. If this is NULL, then the transmit buffer
415 status will not be read. If there are no transmit buffers to
416 recycle and TxBuf is not NULL, * TxBuf will be set to NULL.
417
418 @retval EFI_SUCCESS Always succeeds.
419
420 **/
421 EFI_STATUS
422 EFIAPI
EmuSnpGetStatus(IN EFI_SIMPLE_NETWORK_PROTOCOL * This,OUT UINT32 * InterruptStatus,OUT VOID ** TxBuffer)423 EmuSnpGetStatus (
424 IN EFI_SIMPLE_NETWORK_PROTOCOL *This,
425 OUT UINT32 *InterruptStatus,
426 OUT VOID **TxBuffer
427 )
428 {
429 EFI_STATUS Status;
430 EMU_SNP_PRIVATE_DATA *Private;
431
432 Private = EMU_SNP_PRIVATE_DATA_FROM_SNP_THIS (This);
433
434 Status = Private->Io->GetStatus (Private->Io, InterruptStatus, TxBuffer);
435 return Status;
436 }
437
438
439 /**
440 Places a packet in the transmit queue of a network interface.
441
442 @param This Protocol instance pointer.
443 @param HeaderSize The size, in bytes, of the media header to be filled in by
444 the Transmit() function. If HeaderSize is non-zero, then it
445 must be equal to This->Mode->MediaHeaderSize and the DestAddr
446 and Protocol parameters must not be NULL.
447 @param BufferSize The size, in bytes, of the entire packet (media header and
448 data) to be transmitted through the network interface.
449 @param Buffer A pointer to the packet (media header followed by data) to be
450 transmitted. This parameter cannot be NULL. If HeaderSize is zero,
451 then the media header in Buffer must already be filled in by the
452 caller. If HeaderSize is non-zero, then the media header will be
453 filled in by the Transmit() function.
454 @param SrcAddr The source HW MAC address. If HeaderSize is zero, then this parameter
455 is ignored. If HeaderSize is non-zero and SrcAddr is NULL, then
456 This->Mode->CurrentAddress is used for the source HW MAC address.
457 @param DestAddr The destination HW MAC address. If HeaderSize is zero, then this
458 parameter is ignored.
459 @param Protocol The type of header to build. If HeaderSize is zero, then this
460 parameter is ignored. See RFC 1700, section "Ether Types", for
461 examples.
462
463 @retval EFI_SUCCESS The packet was placed on the transmit queue.
464 @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.
465 @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value.
466 @retval EFI_NOT_STARTED The network interface has not been started.
467
468 **/
469 EFI_STATUS
470 EFIAPI
EmuSnpTransmit(IN EFI_SIMPLE_NETWORK_PROTOCOL * This,IN UINTN HeaderSize,IN UINTN BufferSize,IN VOID * Buffer,IN EFI_MAC_ADDRESS * SrcAddr OPTIONAL,IN EFI_MAC_ADDRESS * DestAddr OPTIONAL,IN UINT16 * Protocol OPTIONAL)471 EmuSnpTransmit (
472 IN EFI_SIMPLE_NETWORK_PROTOCOL *This,
473 IN UINTN HeaderSize,
474 IN UINTN BufferSize,
475 IN VOID* Buffer,
476 IN EFI_MAC_ADDRESS *SrcAddr OPTIONAL,
477 IN EFI_MAC_ADDRESS *DestAddr OPTIONAL,
478 IN UINT16 *Protocol OPTIONAL
479 )
480 {
481 EFI_STATUS Status;
482 EMU_SNP_PRIVATE_DATA *Private;
483
484 Private = EMU_SNP_PRIVATE_DATA_FROM_SNP_THIS (This);
485
486 Status = Private->Io->Transmit (
487 Private->Io,
488 HeaderSize,
489 BufferSize,
490 Buffer,
491 SrcAddr,
492 DestAddr,
493 Protocol
494 );
495 return Status;
496 }
497
498 /**
499 Receives a packet from a network interface.
500
501 @param This Protocol instance pointer.
502 @param HeaderSize The size, in bytes, of the media header received on the network
503 interface. If this parameter is NULL, then the media header size
504 will not be returned.
505 @param BuffSize On entry, the size, in bytes, of Buffer. On exit, the size, in
506 bytes, of the packet that was received on the network interface.
507 @param Buffer A pointer to the data buffer to receive both the media header and
508 the data.
509 @param SourceAddr The source HW MAC address. If this parameter is NULL, the
510 HW MAC source address will not be extracted from the media
511 header.
512 @param DestinationAddr The destination HW MAC address. If this parameter is NULL,
513 the HW MAC destination address will not be extracted from the
514 media header.
515 @param Protocol The media header type. If this parameter is NULL, then the
516 protocol will not be extracted from the media header. See
517 RFC 1700 section "Ether Types" for examples.
518
519 @retval EFI_SUCCESS The received data was stored in Buffer, and BufferSize has
520 been updated to the number of bytes received.
521 @retval EFI_NOT_READY The network interface is too busy to accept this transmit
522 request.
523 @retval EFI_NOT_STARTED The network interface has not been started.
524 @retval EFI_BUFFER_TOO_SMALL The BufferSize parameter is too small.
525 @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.
526
527 **/
528 EFI_STATUS
529 EFIAPI
EmuSnpReceive(IN EFI_SIMPLE_NETWORK_PROTOCOL * This,OUT UINTN * HeaderSize OPTIONAL,IN OUT UINTN * BuffSize,OUT VOID * Buffer,OUT EFI_MAC_ADDRESS * SourceAddr OPTIONAL,OUT EFI_MAC_ADDRESS * DestinationAddr OPTIONAL,OUT UINT16 * Protocol OPTIONAL)530 EmuSnpReceive (
531 IN EFI_SIMPLE_NETWORK_PROTOCOL *This,
532 OUT UINTN *HeaderSize OPTIONAL,
533 IN OUT UINTN *BuffSize,
534 OUT VOID *Buffer,
535 OUT EFI_MAC_ADDRESS *SourceAddr OPTIONAL,
536 OUT EFI_MAC_ADDRESS *DestinationAddr OPTIONAL,
537 OUT UINT16 *Protocol OPTIONAL
538 )
539 {
540 EFI_STATUS Status;
541 EMU_SNP_PRIVATE_DATA *Private;
542
543 Private = EMU_SNP_PRIVATE_DATA_FROM_SNP_THIS (This);
544
545 Status = Private->Io->Receive (
546 Private->Io,
547 HeaderSize,
548 BuffSize,
549 Buffer,
550 SourceAddr,
551 DestinationAddr,
552 Protocol
553 );
554 return Status;
555 }
556
557
558
559 /**
560 Test to see if this driver supports ControllerHandle. This service
561 is called by the EFI boot service ConnectController(). In
562 order to make drivers as small as possible, there are a few calling
563 restrictions for this service. ConnectController() must
564 follow these calling restrictions. If any other agent wishes to call
565 Supported() it must also follow these calling restrictions.
566
567 @param This Protocol instance pointer.
568 @param ControllerHandle Handle of device to test
569 @param RemainingDevicePath Optional parameter use to pick a specific child
570 device to start.
571
572 @retval EFI_SUCCESS This driver supports this device
573 @retval EFI_UNSUPPORTED This driver does not support this device
574
575 **/
576 EFI_STATUS
577 EFIAPI
EmuSnpDriverBindingSupported(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE ControllerHandle,IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath OPTIONAL)578 EmuSnpDriverBindingSupported (
579 IN EFI_DRIVER_BINDING_PROTOCOL *This,
580 IN EFI_HANDLE ControllerHandle,
581 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
582 )
583 {
584 EFI_STATUS Status;
585 EMU_IO_THUNK_PROTOCOL *EmuIoThunk;
586 MAC_ADDR_DEVICE_PATH *Node;
587 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
588
589 if (RemainingDevicePath != NULL) {
590 if (!IsDevicePathEnd (RemainingDevicePath)) {
591 Node = (MAC_ADDR_DEVICE_PATH *)RemainingDevicePath;
592 if (Node->Header.Type != MESSAGING_DEVICE_PATH ||
593 Node->Header.SubType != MSG_MAC_ADDR_DP) {
594 // If the remaining device path does not match we don't support the request
595 return EFI_UNSUPPORTED;
596 }
597 }
598 }
599
600
601 //
602 // Open the IO Abstraction(s) needed to perform the supported test
603 //
604 Status = gBS->OpenProtocol (
605 ControllerHandle,
606 &gEmuIoThunkProtocolGuid,
607 (VOID **)&EmuIoThunk,
608 This->DriverBindingHandle,
609 ControllerHandle,
610 EFI_OPEN_PROTOCOL_BY_DRIVER
611 );
612 if (EFI_ERROR (Status)) {
613 return Status;
614 }
615
616 //
617 // Close the I/O Abstraction(s) used to perform the supported test
618 //
619 gBS->CloseProtocol (
620 ControllerHandle,
621 &gEmuIoThunkProtocolGuid,
622 This->DriverBindingHandle,
623 ControllerHandle
624 );
625
626
627 //
628 // Open the EFI Device Path protocol needed to perform the supported test
629 //
630 Status = gBS->OpenProtocol (
631 ControllerHandle,
632 &gEfiDevicePathProtocolGuid,
633 (VOID **) &ParentDevicePath,
634 This->DriverBindingHandle,
635 ControllerHandle,
636 EFI_OPEN_PROTOCOL_BY_DRIVER
637 );
638 if (Status == EFI_ALREADY_STARTED) {
639 return EFI_SUCCESS;
640 }
641
642 if (EFI_ERROR (Status)) {
643 return Status;
644 }
645
646 //
647 // Make sure GUID is for a SNP handle.
648 //
649 Status = EFI_UNSUPPORTED;
650 if (CompareGuid (EmuIoThunk->Protocol, &gEmuSnpProtocolGuid)) {
651 Status = EFI_SUCCESS;
652 }
653
654 //
655 // Close protocol, don't use device path protocol in the Support() function
656 //
657 gBS->CloseProtocol (
658 ControllerHandle,
659 &gEfiDevicePathProtocolGuid,
660 This->DriverBindingHandle,
661 ControllerHandle
662 );
663
664 return Status;
665 }
666
667
668 /**
669 Start this driver on ControllerHandle. This service is called by the
670 EFI boot service ConnectController(). In order to make
671 drivers as small as possible, there are a few calling restrictions for
672 this service. ConnectController() must follow these
673 calling restrictions. If any other agent wishes to call Start() it
674 must also follow these calling restrictions.
675
676 @param This Protocol instance pointer.
677 @param ControllerHandle Handle of device to bind driver to
678 @param RemainingDevicePath Optional parameter use to pick a specific child
679 device to start.
680
681 @retval EFI_SUCCESS Always succeeds.
682
683 **/
684 EFI_STATUS
685 EFIAPI
EmuSnpDriverBindingStart(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE ControllerHandle,IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath OPTIONAL)686 EmuSnpDriverBindingStart (
687 IN EFI_DRIVER_BINDING_PROTOCOL *This,
688 IN EFI_HANDLE ControllerHandle,
689 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
690 )
691 {
692 EFI_STATUS Status;
693 EMU_IO_THUNK_PROTOCOL *EmuIoThunk;
694 EMU_SNP_PRIVATE_DATA *Private;
695 MAC_ADDR_DEVICE_PATH Node;
696 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
697
698 Private = NULL;
699
700 //
701 // Grab the protocols we need
702 //
703 Status = gBS->OpenProtocol(
704 ControllerHandle,
705 &gEfiDevicePathProtocolGuid,
706 ( VOID ** ) &ParentDevicePath,
707 This->DriverBindingHandle,
708 ControllerHandle,
709 EFI_OPEN_PROTOCOL_BY_DRIVER
710 );
711 if (EFI_ERROR (Status) && Status) {
712 return Status;
713 }
714
715 Status = gBS->OpenProtocol (
716 ControllerHandle,
717 &gEmuIoThunkProtocolGuid,
718 (VOID **)&EmuIoThunk,
719 This->DriverBindingHandle,
720 ControllerHandle,
721 EFI_OPEN_PROTOCOL_BY_DRIVER
722 );
723 if (EFI_ERROR (Status)) {
724 return Status;
725 }
726
727 if (!CompareGuid (EmuIoThunk->Protocol, &gEmuSnpProtocolGuid)) {
728 return EFI_UNSUPPORTED;
729 }
730
731 Status = EmuIoThunk->Open (EmuIoThunk);
732 if (EFI_ERROR (Status)) {
733 goto Done;
734 }
735
736 //
737 // Allocate the private data.
738 //
739 Private = AllocateZeroPool (sizeof (EMU_SNP_PRIVATE_DATA));
740 if (Private == NULL) {
741 Status = EFI_OUT_OF_RESOURCES;
742 goto Done;
743 }
744
745 CopyMem (&Private->Snp, &gEmuSnpTemplate, sizeof (EFI_SIMPLE_NETWORK_PROTOCOL));
746 CopyMem (&Private->Mode, &gEmuSnpModeTemplate, sizeof (EFI_SIMPLE_NETWORK_MODE));
747
748 Private->Signature = EMU_SNP_PRIVATE_DATA_SIGNATURE;
749 Private->IoThunk = EmuIoThunk;
750 Private->Io = EmuIoThunk->Interface;
751 Private->EfiHandle = ControllerHandle;
752 Private->DeviceHandle = NULL;
753 Private->Snp.Mode = &Private->Mode;
754 Private->ControllerNameTable = NULL;
755
756
757 Status = Private->Io->CreateMapping (Private->Io, &Private->Mode);
758 if (EFI_ERROR (Status)) {
759 goto Done;
760 }
761
762 //
763 // Build the device path by appending the MAC node to the ParentDevicePath
764 // from the EmuIo handle.
765 //
766 ZeroMem (&Node, sizeof (MAC_ADDR_DEVICE_PATH));
767
768 Node.Header.Type = MESSAGING_DEVICE_PATH;
769 Node.Header.SubType = MSG_MAC_ADDR_DP;
770 Node.IfType = Private->Mode.IfType;
771
772 SetDevicePathNodeLength ((EFI_DEVICE_PATH_PROTOCOL * )&Node, sizeof (MAC_ADDR_DEVICE_PATH));
773
774 CopyMem (&Node.MacAddress, &Private->Mode.CurrentAddress, sizeof (EFI_MAC_ADDRESS));
775
776 //
777 // Build the device path by appending the MAC node to the ParentDevicePath from the EmuIo handle.
778 //
779 Private->DevicePath = AppendDevicePathNode (ParentDevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&Node);
780 if ( Private->DevicePath == NULL ) {
781 Status = EFI_OUT_OF_RESOURCES;
782 goto Done;
783 }
784
785 AddUnicodeString2 (
786 "eng",
787 gEmuSnpDriverComponentName.SupportedLanguages,
788 &Private->ControllerNameTable,
789 EmuIoThunk->ConfigString,
790 TRUE
791 );
792
793 AddUnicodeString2 (
794 "en",
795 gEmuSnpDriverComponentName2.SupportedLanguages,
796 &Private->ControllerNameTable,
797 EmuIoThunk->ConfigString,
798 FALSE
799 );
800
801 //
802 // Create Child Handle
803 //
804 Status = gBS->InstallMultipleProtocolInterfaces(
805 &Private->DeviceHandle,
806 &gEfiSimpleNetworkProtocolGuid, &Private->Snp,
807 &gEfiDevicePathProtocolGuid, Private->DevicePath,
808 NULL
809 );
810 if (EFI_ERROR (Status)) {
811 goto Done;
812 }
813
814 //
815 // Open For Child Device
816 //
817 Status = gBS->OpenProtocol (
818 ControllerHandle,
819 &gEmuIoThunkProtocolGuid,
820 (VOID **)&EmuIoThunk,
821 This->DriverBindingHandle,
822 Private->DeviceHandle,
823 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
824 );
825
826 Done:
827 if (EFI_ERROR (Status)) {
828 if (Private != NULL) {
829 FreePool (Private);
830 }
831 if (ParentDevicePath != NULL) {
832 gBS->CloseProtocol(
833 ControllerHandle,
834 &gEfiDevicePathProtocolGuid,
835 This->DriverBindingHandle,
836 ControllerHandle
837 );
838 }
839 }
840
841 return Status;
842 }
843
844 /**
845 Stop this driver on ControllerHandle. This service is called by the
846 EFI boot service DisconnectController(). In order to
847 make drivers as small as possible, there are a few calling
848 restrictions for this service. DisconnectController()
849 must follow these calling restrictions. If any other agent wishes
850 to call Stop() it must also follow these calling restrictions.
851
852 @param This Protocol instance pointer.
853 @param ControllerHandle Handle of device to stop driver on
854 @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number of
855 children is zero stop the entire bus driver.
856 @param ChildHandleBuffer List of Child Handles to Stop.
857
858 @retval EFI_SUCCESS Always succeeds.
859
860 **/
861 EFI_STATUS
862 EFIAPI
EmuSnpDriverBindingStop(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE ControllerHandle,IN UINTN NumberOfChildren,IN EFI_HANDLE * ChildHandleBuffer)863 EmuSnpDriverBindingStop (
864 IN EFI_DRIVER_BINDING_PROTOCOL *This,
865 IN EFI_HANDLE ControllerHandle,
866 IN UINTN NumberOfChildren,
867 IN EFI_HANDLE *ChildHandleBuffer
868 )
869 {
870 EFI_STATUS Status;
871 EMU_SNP_PRIVATE_DATA *Private = NULL;
872 EFI_SIMPLE_NETWORK_PROTOCOL *Snp;
873
874 //
875 // Complete all outstanding transactions to Controller.
876 // Don't allow any new transaction to Controller to be started.
877 //
878 if (NumberOfChildren == 0) {
879 //
880 // Close the bus driver
881 //
882 Status = gBS->CloseProtocol (
883 ControllerHandle,
884 &gEmuIoThunkProtocolGuid,
885 This->DriverBindingHandle,
886 ControllerHandle
887 );
888
889 Status = gBS->CloseProtocol (
890 ControllerHandle,
891 &gEfiDevicePathProtocolGuid,
892 This->DriverBindingHandle,
893 ControllerHandle
894 );
895 return Status;
896 }
897
898 ASSERT (NumberOfChildren == 1);
899
900
901 //
902 // Get our context back.
903 //
904 Status = gBS->OpenProtocol(
905 ChildHandleBuffer[0],
906 &gEfiSimpleNetworkProtocolGuid,
907 ( VOID ** ) &Snp,
908 This->DriverBindingHandle,
909 ControllerHandle,
910 EFI_OPEN_PROTOCOL_GET_PROTOCOL
911 );
912 if (EFI_ERROR (Status)) {
913 return EFI_DEVICE_ERROR;
914 }
915
916 Private = EMU_SNP_PRIVATE_DATA_FROM_SNP_THIS (Snp);
917 Status = Private->IoThunk->Close (Private->IoThunk);
918
919 Status = gBS->CloseProtocol(
920 ChildHandleBuffer[0],
921 &gEmuIoThunkProtocolGuid,
922 This->DriverBindingHandle,
923 Private->DeviceHandle
924 );
925
926 Status = gBS->UninstallMultipleProtocolInterfaces(
927 ChildHandleBuffer[0],
928 &gEfiSimpleNetworkProtocolGuid, &Private->Snp,
929 &gEfiDevicePathProtocolGuid, Private->DevicePath,
930 NULL
931 );
932
933 FreePool (Private->DevicePath);
934 FreeUnicodeStringTable (Private->ControllerNameTable);
935 FreePool (Private);
936
937 return EFI_SUCCESS;
938 }
939
940
941 EFI_DRIVER_BINDING_PROTOCOL gEmuSnpDriverBinding = {
942 EmuSnpDriverBindingSupported,
943 EmuSnpDriverBindingStart,
944 EmuSnpDriverBindingStop,
945 0xA,
946 NULL,
947 NULL
948 };
949
950
951
952 /**
953 This is the declaration of an EFI image entry point. This entry point is
954 the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers including
955 both device drivers and bus drivers.
956
957 @param ImageHandle The firmware allocated handle for the UEFI image.
958 @param SystemTable A pointer to the EFI System Table.
959
960 @retval EFI_SUCCESS The operation completed successfully.
961 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
962
963 **/
964 EFI_STATUS
965 EFIAPI
InitializeEmuSnpDriver(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)966 InitializeEmuSnpDriver (
967 IN EFI_HANDLE ImageHandle,
968 IN EFI_SYSTEM_TABLE *SystemTable
969 )
970 {
971 EFI_STATUS Status;
972
973 //
974 // Install the Driver Protocols
975 //
976 Status = EfiLibInstallDriverBindingComponentName2(
977 ImageHandle,
978 SystemTable,
979 &gEmuSnpDriverBinding,
980 ImageHandle,
981 &gEmuSnpDriverComponentName,
982 &gEmuSnpDriverComponentName2
983 );
984
985 return Status;
986 }
987