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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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