1 /** @file 2 Initialization functions for EFI UNDI32 driver. 3 4 Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.<BR> 5 This program and the accompanying materials 6 are licensed and made available under the terms and conditions of the BSD License 7 which accompanies this distribution. The full text of the license may be found at 8 http://opensource.org/licenses/bsd-license.php 9 10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 12 13 **/ 14 15 #include "Undi32.h" 16 // 17 // Global Variables 18 // 19 20 PXE_SW_UNDI *pxe_31 = NULL; // 3.1 entry 21 UNDI32_DEV *UNDI32DeviceList[MAX_NIC_INTERFACES]; 22 UNDI_CONFIG_TABLE *UndiDataPointer = NULL; 23 24 // 25 // UNDI Class Driver Global Variables 26 // 27 EFI_DRIVER_BINDING_PROTOCOL gUndiDriverBinding = { 28 UndiDriverSupported, 29 UndiDriverStart, 30 UndiDriverStop, 31 0xa, 32 NULL, 33 NULL 34 }; 35 36 37 /** 38 When address mapping changes to virtual this should make the appropriate 39 address conversions. 40 41 (Standard Event handler) 42 43 @return None 44 45 **/ 46 VOID 47 EFIAPI 48 UndiNotifyVirtual ( 49 EFI_EVENT Event, 50 VOID *Context 51 ) 52 { 53 UINT16 Index; 54 VOID *Pxe31Pointer; 55 56 if (pxe_31 != NULL) { 57 Pxe31Pointer = (VOID *) pxe_31; 58 59 EfiConvertPointer ( 60 EFI_OPTIONAL_PTR, 61 (VOID **) &Pxe31Pointer 62 ); 63 64 // 65 // UNDI32DeviceList is an array of pointers 66 // 67 for (Index = 0; Index < (pxe_31->IFcnt | pxe_31->IFcntExt << 8); Index++) { 68 UNDI32DeviceList[Index]->NIIProtocol_31.Id = (UINT64) (UINTN) Pxe31Pointer; 69 EfiConvertPointer ( 70 EFI_OPTIONAL_PTR, 71 (VOID **) &(UNDI32DeviceList[Index]) 72 ); 73 } 74 75 EfiConvertPointer ( 76 EFI_OPTIONAL_PTR, 77 (VOID **) &(pxe_31->EntryPoint) 78 ); 79 pxe_31 = Pxe31Pointer; 80 } 81 82 for (Index = 0; Index <= PXE_OPCODE_LAST_VALID; Index++) { 83 EfiConvertPointer ( 84 EFI_OPTIONAL_PTR, 85 (VOID **) &api_table[Index].api_ptr 86 ); 87 } 88 } 89 90 91 /** 92 When EFI is shuting down the boot services, we need to install a 93 configuration table for UNDI to work at runtime! 94 95 (Standard Event handler) 96 97 @return None 98 99 **/ 100 VOID 101 EFIAPI 102 UndiNotifyReadyToBoot ( 103 EFI_EVENT Event, 104 VOID *Context 105 ) 106 { 107 InstallConfigTable (); 108 } 109 110 111 /** 112 Test to see if this driver supports ControllerHandle. Any ControllerHandle 113 than contains a DevicePath, PciIo protocol, Class code of 2, Vendor ID of 0x8086, 114 and DeviceId of (D100_DEVICE_ID || D102_DEVICE_ID || ICH3_DEVICE_ID_1 || 115 ICH3_DEVICE_ID_2 || ICH3_DEVICE_ID_3 || ICH3_DEVICE_ID_4 || ICH3_DEVICE_ID_5 || 116 ICH3_DEVICE_ID_6 || ICH3_DEVICE_ID_7 || ICH3_DEVICE_ID_8) can be supported. 117 118 @param This Protocol instance pointer. 119 @param Controller Handle of device to test. 120 @param RemainingDevicePath Not used. 121 122 @retval EFI_SUCCESS This driver supports this device. 123 @retval other This driver does not support this device. 124 125 **/ 126 EFI_STATUS 127 EFIAPI 128 UndiDriverSupported ( 129 IN EFI_DRIVER_BINDING_PROTOCOL *This, 130 IN EFI_HANDLE Controller, 131 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath 132 ) 133 { 134 EFI_STATUS Status; 135 EFI_PCI_IO_PROTOCOL *PciIo; 136 PCI_TYPE00 Pci; 137 138 Status = gBS->OpenProtocol ( 139 Controller, 140 &gEfiDevicePathProtocolGuid, 141 NULL, 142 This->DriverBindingHandle, 143 Controller, 144 EFI_OPEN_PROTOCOL_TEST_PROTOCOL 145 ); 146 if (EFI_ERROR (Status)) { 147 return Status; 148 } 149 150 Status = gBS->OpenProtocol ( 151 Controller, 152 &gEfiPciIoProtocolGuid, 153 (VOID **) &PciIo, 154 This->DriverBindingHandle, 155 Controller, 156 EFI_OPEN_PROTOCOL_BY_DRIVER 157 ); 158 if (EFI_ERROR (Status)) { 159 return Status; 160 } 161 162 Status = PciIo->Pci.Read ( 163 PciIo, 164 EfiPciIoWidthUint8, 165 0, 166 sizeof (PCI_CONFIG_HEADER), 167 &Pci 168 ); 169 170 if (!EFI_ERROR (Status)) { 171 Status = EFI_UNSUPPORTED; 172 173 if (Pci.Hdr.ClassCode[2] == 0x02 && Pci.Hdr.VendorId == PCI_VENDOR_ID_INTEL) { 174 switch (Pci.Hdr.DeviceId) { 175 case D100_DEVICE_ID: 176 case D102_DEVICE_ID: 177 case ICH3_DEVICE_ID_1: 178 case ICH3_DEVICE_ID_2: 179 case ICH3_DEVICE_ID_3: 180 case ICH3_DEVICE_ID_4: 181 case ICH3_DEVICE_ID_5: 182 case ICH3_DEVICE_ID_6: 183 case ICH3_DEVICE_ID_7: 184 case ICH3_DEVICE_ID_8: 185 case 0x1039: 186 case 0x103A: 187 case 0x103B: 188 case 0x103C: 189 case 0x103D: 190 case 0x103E: 191 case 0x1050: 192 case 0x1051: 193 case 0x1052: 194 case 0x1053: 195 case 0x1054: 196 case 0x1055: 197 case 0x1056: 198 case 0x1057: 199 case 0x1059: 200 case 0x1064: 201 Status = EFI_SUCCESS; 202 } 203 } 204 } 205 206 gBS->CloseProtocol ( 207 Controller, 208 &gEfiPciIoProtocolGuid, 209 This->DriverBindingHandle, 210 Controller 211 ); 212 213 return Status; 214 } 215 216 217 /** 218 Start this driver on Controller by opening PciIo and DevicePath protocol. 219 Initialize PXE structures, create a copy of the Controller Device Path with the 220 NIC's MAC address appended to it, install the NetworkInterfaceIdentifier protocol 221 on the newly created Device Path. 222 223 @param This Protocol instance pointer. 224 @param Controller Handle of device to work with. 225 @param RemainingDevicePath Not used, always produce all possible children. 226 227 @retval EFI_SUCCESS This driver is added to Controller. 228 @retval other This driver does not support this device. 229 230 **/ 231 EFI_STATUS 232 EFIAPI 233 UndiDriverStart ( 234 IN EFI_DRIVER_BINDING_PROTOCOL *This, 235 IN EFI_HANDLE Controller, 236 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath 237 ) 238 { 239 EFI_STATUS Status; 240 EFI_DEVICE_PATH_PROTOCOL *UndiDevicePath; 241 PCI_CONFIG_HEADER *CfgHdr; 242 UNDI32_DEV *UNDI32Device; 243 UINT16 NewCommand; 244 UINT8 *TmpPxePointer; 245 EFI_PCI_IO_PROTOCOL *PciIoFncs; 246 UINTN Len; 247 UINT64 Supports; 248 BOOLEAN PciAttributesSaved; 249 250 Status = gBS->OpenProtocol ( 251 Controller, 252 &gEfiPciIoProtocolGuid, 253 (VOID **) &PciIoFncs, 254 This->DriverBindingHandle, 255 Controller, 256 EFI_OPEN_PROTOCOL_BY_DRIVER 257 ); 258 259 if (EFI_ERROR (Status)) { 260 return Status; 261 } 262 263 Status = gBS->OpenProtocol ( 264 Controller, 265 &gEfiDevicePathProtocolGuid, 266 (VOID **) &UndiDevicePath, 267 This->DriverBindingHandle, 268 Controller, 269 EFI_OPEN_PROTOCOL_BY_DRIVER 270 ); 271 272 if (EFI_ERROR (Status)) { 273 gBS->CloseProtocol ( 274 Controller, 275 &gEfiPciIoProtocolGuid, 276 This->DriverBindingHandle, 277 Controller 278 ); 279 280 return Status; 281 } 282 283 PciAttributesSaved = FALSE; 284 285 Status = gBS->AllocatePool ( 286 EfiRuntimeServicesData, 287 sizeof (UNDI32_DEV), 288 (VOID **) &UNDI32Device 289 ); 290 291 if (EFI_ERROR (Status)) { 292 goto UndiError; 293 } 294 295 ZeroMem ((CHAR8 *) UNDI32Device, sizeof (UNDI32_DEV)); 296 297 // 298 // Get original PCI attributes 299 // 300 Status = PciIoFncs->Attributes ( 301 PciIoFncs, 302 EfiPciIoAttributeOperationGet, 303 0, 304 &UNDI32Device->NicInfo.OriginalPciAttributes 305 ); 306 307 if (EFI_ERROR (Status)) { 308 goto UndiErrorDeleteDevice; 309 } 310 PciAttributesSaved = TRUE; 311 312 // 313 // allocate and initialize both (old and new) the !pxe structures here, 314 // there should only be one copy of each of these structure for any number 315 // of NICs this undi supports. Also, these structures need to be on a 316 // paragraph boundary as per the spec. so, while allocating space for these, 317 // make sure that there is space for 2 !pxe structures (old and new) and a 318 // 32 bytes padding for alignment adjustment (in case) 319 // 320 TmpPxePointer = NULL; 321 if (pxe_31 == NULL) { 322 Status = gBS->AllocatePool ( 323 EfiRuntimeServicesData, 324 (sizeof (PXE_SW_UNDI) + sizeof (PXE_SW_UNDI) + 32), 325 (VOID **) &TmpPxePointer 326 ); 327 328 if (EFI_ERROR (Status)) { 329 goto UndiErrorDeleteDevice; 330 } 331 332 ZeroMem ( 333 TmpPxePointer, 334 sizeof (PXE_SW_UNDI) + sizeof (PXE_SW_UNDI) + 32 335 ); 336 // 337 // check for paragraph alignment here, assuming that the pointer is 338 // already 8 byte aligned. 339 // 340 if (((UINTN) TmpPxePointer & 0x0F) != 0) { 341 pxe_31 = (PXE_SW_UNDI *) ((UINTN) (TmpPxePointer + 8)); 342 } else { 343 pxe_31 = (PXE_SW_UNDI *) TmpPxePointer; 344 } 345 346 PxeStructInit (pxe_31); 347 } 348 349 UNDI32Device->NIIProtocol_31.Id = (UINT64) (UINTN) (pxe_31); 350 351 Status = PciIoFncs->Attributes ( 352 PciIoFncs, 353 EfiPciIoAttributeOperationSupported, 354 0, 355 &Supports 356 ); 357 if (!EFI_ERROR (Status)) { 358 Supports &= EFI_PCI_DEVICE_ENABLE; 359 Status = PciIoFncs->Attributes ( 360 PciIoFncs, 361 EfiPciIoAttributeOperationEnable, 362 Supports, 363 NULL 364 ); 365 } 366 // 367 // Read all the registers from device's PCI Configuration space 368 // 369 Status = PciIoFncs->Pci.Read ( 370 PciIoFncs, 371 EfiPciIoWidthUint32, 372 0, 373 MAX_PCI_CONFIG_LEN, 374 &UNDI32Device->NicInfo.Config 375 ); 376 377 CfgHdr = (PCI_CONFIG_HEADER *) &(UNDI32Device->NicInfo.Config[0]); 378 379 // 380 // make sure that this device is a PCI bus master 381 // 382 383 NewCommand = (UINT16) (CfgHdr->Command | PCI_COMMAND_MASTER | PCI_COMMAND_IO); 384 if (CfgHdr->Command != NewCommand) { 385 PciIoFncs->Pci.Write ( 386 PciIoFncs, 387 EfiPciIoWidthUint16, 388 PCI_COMMAND, 389 1, 390 &NewCommand 391 ); 392 CfgHdr->Command = NewCommand; 393 } 394 395 // 396 // make sure that the latency timer is at least 32 397 // 398 if (CfgHdr->LatencyTimer < 32) { 399 CfgHdr->LatencyTimer = 32; 400 PciIoFncs->Pci.Write ( 401 PciIoFncs, 402 EfiPciIoWidthUint8, 403 PCI_LATENCY_TIMER, 404 1, 405 &CfgHdr->LatencyTimer 406 ); 407 } 408 // 409 // the IfNum index for the current interface will be the total number 410 // of interfaces initialized so far 411 // 412 UNDI32Device->NIIProtocol_31.IfNum = pxe_31->IFcnt | pxe_31->IFcntExt << 8; 413 414 PxeUpdate (&UNDI32Device->NicInfo, pxe_31); 415 416 UNDI32Device->NicInfo.Io_Function = PciIoFncs; 417 UNDI32DeviceList[UNDI32Device->NIIProtocol_31.IfNum] = UNDI32Device; 418 UNDI32Device->Undi32BaseDevPath = UndiDevicePath; 419 420 Status = AppendMac2DevPath ( 421 &UNDI32Device->Undi32DevPath, 422 UNDI32Device->Undi32BaseDevPath, 423 &UNDI32Device->NicInfo 424 ); 425 426 if (Status != 0) { 427 goto UndiErrorDeletePxe; 428 } 429 430 UNDI32Device->Signature = UNDI_DEV_SIGNATURE; 431 432 UNDI32Device->NIIProtocol_31.Revision = EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL_REVISION_31; 433 UNDI32Device->NIIProtocol_31.Type = EfiNetworkInterfaceUndi; 434 UNDI32Device->NIIProtocol_31.MajorVer = PXE_ROMID_MAJORVER; 435 UNDI32Device->NIIProtocol_31.MinorVer = PXE_ROMID_MINORVER_31; 436 UNDI32Device->NIIProtocol_31.ImageSize = 0; 437 UNDI32Device->NIIProtocol_31.ImageAddr = 0; 438 UNDI32Device->NIIProtocol_31.Ipv6Supported = TRUE; 439 440 UNDI32Device->NIIProtocol_31.StringId[0] = 'U'; 441 UNDI32Device->NIIProtocol_31.StringId[1] = 'N'; 442 UNDI32Device->NIIProtocol_31.StringId[2] = 'D'; 443 UNDI32Device->NIIProtocol_31.StringId[3] = 'I'; 444 445 UNDI32Device->DeviceHandle = NULL; 446 447 UNDI32Device->Aip.GetInformation = UndiAipGetInfo; 448 UNDI32Device->Aip.SetInformation = UndiAipSetInfo; 449 UNDI32Device->Aip.GetSupportedTypes = UndiAipGetSupportedTypes; 450 451 // 452 // install both the 3.0 and 3.1 NII protocols. 453 // 454 Status = gBS->InstallMultipleProtocolInterfaces ( 455 &UNDI32Device->DeviceHandle, 456 &gEfiNetworkInterfaceIdentifierProtocolGuid_31, 457 &UNDI32Device->NIIProtocol_31, 458 &gEfiDevicePathProtocolGuid, 459 UNDI32Device->Undi32DevPath, 460 &gEfiAdapterInformationProtocolGuid, 461 &UNDI32Device->Aip, 462 NULL 463 ); 464 465 if (EFI_ERROR (Status)) { 466 goto UndiErrorDeleteDevicePath; 467 } 468 469 // 470 // if the table exists, free it and alloc again, or alloc it directly 471 // 472 if (UndiDataPointer != NULL) { 473 Status = gBS->FreePool(UndiDataPointer); 474 } 475 if (EFI_ERROR (Status)) { 476 goto UndiErrorDeleteDevicePath; 477 } 478 479 Len = ((pxe_31->IFcnt|pxe_31->IFcntExt << 8)* sizeof (UndiDataPointer->NII_entry)) + sizeof (UndiDataPointer); 480 Status = gBS->AllocatePool (EfiRuntimeServicesData, Len, (VOID **) &UndiDataPointer); 481 482 if (EFI_ERROR (Status)) { 483 goto UndiErrorAllocDataPointer; 484 } 485 486 // 487 // Open For Child Device 488 // 489 Status = gBS->OpenProtocol ( 490 Controller, 491 &gEfiPciIoProtocolGuid, 492 (VOID **) &PciIoFncs, 493 This->DriverBindingHandle, 494 UNDI32Device->DeviceHandle, 495 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER 496 ); 497 498 return EFI_SUCCESS; 499 UndiErrorAllocDataPointer: 500 gBS->UninstallMultipleProtocolInterfaces ( 501 &UNDI32Device->DeviceHandle, 502 &gEfiNetworkInterfaceIdentifierProtocolGuid_31, 503 &UNDI32Device->NIIProtocol_31, 504 &gEfiDevicePathProtocolGuid, 505 UNDI32Device->Undi32DevPath, 506 &gEfiAdapterInformationProtocolGuid, 507 &UNDI32Device->Aip, 508 NULL 509 ); 510 511 UndiErrorDeleteDevicePath: 512 UNDI32DeviceList[UNDI32Device->NIIProtocol_31.IfNum] = NULL; 513 gBS->FreePool (UNDI32Device->Undi32DevPath); 514 515 UndiErrorDeletePxe: 516 PxeUpdate (NULL, pxe_31); 517 if (TmpPxePointer != NULL) { 518 gBS->FreePool (TmpPxePointer); 519 520 } 521 522 UndiErrorDeleteDevice: 523 if (PciAttributesSaved) { 524 // 525 // Restore original PCI attributes 526 // 527 PciIoFncs->Attributes ( 528 PciIoFncs, 529 EfiPciIoAttributeOperationSet, 530 UNDI32Device->NicInfo.OriginalPciAttributes, 531 NULL 532 ); 533 } 534 535 gBS->FreePool (UNDI32Device); 536 537 UndiError: 538 gBS->CloseProtocol ( 539 Controller, 540 &gEfiDevicePathProtocolGuid, 541 This->DriverBindingHandle, 542 Controller 543 ); 544 545 gBS->CloseProtocol ( 546 Controller, 547 &gEfiPciIoProtocolGuid, 548 This->DriverBindingHandle, 549 Controller 550 ); 551 552 return Status; 553 } 554 555 556 /** 557 Stop this driver on Controller by removing NetworkInterfaceIdentifier protocol and 558 closing the DevicePath and PciIo protocols on Controller. 559 560 @param This Protocol instance pointer. 561 @param Controller Handle of device to stop driver on. 562 @param NumberOfChildren How many children need to be stopped. 563 @param ChildHandleBuffer Not used. 564 565 @retval EFI_SUCCESS This driver is removed Controller. 566 @retval other This driver was not removed from this device. 567 568 **/ 569 // TODO: EFI_DEVICE_ERROR - add return value to function comment 570 EFI_STATUS 571 EFIAPI 572 UndiDriverStop ( 573 IN EFI_DRIVER_BINDING_PROTOCOL *This, 574 IN EFI_HANDLE Controller, 575 IN UINTN NumberOfChildren, 576 IN EFI_HANDLE *ChildHandleBuffer 577 ) 578 { 579 EFI_STATUS Status; 580 BOOLEAN AllChildrenStopped; 581 UINTN Index; 582 UNDI32_DEV *UNDI32Device; 583 EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL *NIIProtocol; 584 585 // 586 // Complete all outstanding transactions to Controller. 587 // Don't allow any new transaction to Controller to be started. 588 // 589 if (NumberOfChildren == 0) { 590 591 // 592 // Close the bus driver 593 // 594 Status = gBS->CloseProtocol ( 595 Controller, 596 &gEfiDevicePathProtocolGuid, 597 This->DriverBindingHandle, 598 Controller 599 ); 600 601 Status = gBS->CloseProtocol ( 602 Controller, 603 &gEfiPciIoProtocolGuid, 604 This->DriverBindingHandle, 605 Controller 606 ); 607 608 return Status; 609 } 610 611 AllChildrenStopped = TRUE; 612 613 for (Index = 0; Index < NumberOfChildren; Index++) { 614 615 Status = gBS->OpenProtocol ( 616 ChildHandleBuffer[Index], 617 &gEfiNetworkInterfaceIdentifierProtocolGuid_31, 618 (VOID **) &NIIProtocol, 619 This->DriverBindingHandle, 620 Controller, 621 EFI_OPEN_PROTOCOL_GET_PROTOCOL 622 ); 623 if (!EFI_ERROR (Status)) { 624 625 UNDI32Device = UNDI_DEV_FROM_THIS (NIIProtocol); 626 627 Status = gBS->CloseProtocol ( 628 Controller, 629 &gEfiPciIoProtocolGuid, 630 This->DriverBindingHandle, 631 ChildHandleBuffer[Index] 632 ); 633 if (!EFI_ERROR (Status)) { 634 Status = gBS->UninstallMultipleProtocolInterfaces ( 635 ChildHandleBuffer[Index], 636 &gEfiDevicePathProtocolGuid, 637 UNDI32Device->Undi32DevPath, 638 &gEfiNetworkInterfaceIdentifierProtocolGuid_31, 639 &UNDI32Device->NIIProtocol_31, 640 NULL 641 ); 642 if (!EFI_ERROR (Status)) { 643 // 644 // Restore original PCI attributes 645 // 646 Status = UNDI32Device->NicInfo.Io_Function->Attributes ( 647 UNDI32Device->NicInfo.Io_Function, 648 EfiPciIoAttributeOperationSet, 649 UNDI32Device->NicInfo.OriginalPciAttributes, 650 NULL 651 ); 652 653 ASSERT_EFI_ERROR (Status); 654 655 gBS->FreePool (UNDI32Device->Undi32DevPath); 656 gBS->FreePool (UNDI32Device); 657 658 } 659 } 660 } 661 662 if (EFI_ERROR (Status)) { 663 AllChildrenStopped = FALSE; 664 } 665 } 666 667 if (!AllChildrenStopped) { 668 return EFI_DEVICE_ERROR; 669 } 670 671 return EFI_SUCCESS; 672 673 } 674 675 676 /** 677 Use the EFI boot services to produce a pause. This is also the routine which 678 gets replaced during RunTime by the O/S in the NIC_DATA_INSTANCE so it can 679 do it's own pause. 680 681 @param UnqId Runtime O/S routine might use this, this temp 682 routine does not use it 683 @param MicroSeconds Determines the length of pause. 684 685 @return none 686 687 **/ 688 VOID 689 TmpDelay ( 690 IN UINT64 UnqId, 691 IN UINTN MicroSeconds 692 ) 693 { 694 gBS->Stall ((UINT32) MicroSeconds); 695 } 696 697 698 /** 699 Use the PCI IO abstraction to issue memory or I/O reads and writes. This is also the routine which 700 gets replaced during RunTime by the O/S in the NIC_DATA_INSTANCE so it can do it's own I/O abstractions. 701 702 @param UnqId Runtime O/S routine may use this field, this temp 703 routine does not. 704 @param ReadWrite Determine if it is an I/O or Memory Read/Write 705 Operation. 706 @param Len Determines the width of the data operation. 707 @param Port What port to Read/Write from. 708 @param BuffAddr Address to read to or write from. 709 710 @return none 711 712 **/ 713 VOID 714 TmpMemIo ( 715 IN UINT64 UnqId, 716 IN UINT8 ReadWrite, 717 IN UINT8 Len, 718 IN UINT64 Port, 719 IN UINT64 BuffAddr 720 ) 721 { 722 EFI_PCI_IO_PROTOCOL_WIDTH Width; 723 NIC_DATA_INSTANCE *AdapterInfo; 724 725 Width = (EFI_PCI_IO_PROTOCOL_WIDTH) 0; 726 AdapterInfo = (NIC_DATA_INSTANCE *) (UINTN) UnqId; 727 switch (Len) { 728 case 2: 729 Width = (EFI_PCI_IO_PROTOCOL_WIDTH) 1; 730 break; 731 732 case 4: 733 Width = (EFI_PCI_IO_PROTOCOL_WIDTH) 2; 734 break; 735 736 case 8: 737 Width = (EFI_PCI_IO_PROTOCOL_WIDTH) 3; 738 break; 739 } 740 741 switch (ReadWrite) { 742 case PXE_IO_READ: 743 AdapterInfo->Io_Function->Io.Read ( 744 AdapterInfo->Io_Function, 745 Width, 746 1, 747 Port, 748 1, 749 (VOID *) (UINTN) (BuffAddr) 750 ); 751 break; 752 753 case PXE_IO_WRITE: 754 AdapterInfo->Io_Function->Io.Write ( 755 AdapterInfo->Io_Function, 756 Width, 757 1, 758 Port, 759 1, 760 (VOID *) (UINTN) (BuffAddr) 761 ); 762 break; 763 764 case PXE_MEM_READ: 765 AdapterInfo->Io_Function->Mem.Read ( 766 AdapterInfo->Io_Function, 767 Width, 768 0, 769 Port, 770 1, 771 (VOID *) (UINTN) (BuffAddr) 772 ); 773 break; 774 775 case PXE_MEM_WRITE: 776 AdapterInfo->Io_Function->Mem.Write ( 777 AdapterInfo->Io_Function, 778 Width, 779 0, 780 Port, 781 1, 782 (VOID *) (UINTN) (BuffAddr) 783 ); 784 break; 785 } 786 787 return ; 788 } 789 790 791 /** 792 Using the NIC data structure information, read the EEPROM to get the MAC address and then allocate space 793 for a new devicepath (**DevPtr) which will contain the original device path the NIC was found on (*BaseDevPtr) 794 and an added MAC node. 795 796 @param DevPtr Pointer which will point to the newly created device 797 path with the MAC node attached. 798 @param BaseDevPtr Pointer to the device path which the UNDI device 799 driver is latching on to. 800 @param AdapterInfo Pointer to the NIC data structure information which 801 the UNDI driver is layering on.. 802 803 @retval EFI_SUCCESS A MAC address was successfully appended to the Base 804 Device Path. 805 @retval other Not enough resources available to create new Device 806 Path node. 807 808 **/ 809 EFI_STATUS 810 AppendMac2DevPath ( 811 IN OUT EFI_DEVICE_PATH_PROTOCOL **DevPtr, 812 IN EFI_DEVICE_PATH_PROTOCOL *BaseDevPtr, 813 IN NIC_DATA_INSTANCE *AdapterInfo 814 ) 815 { 816 EFI_MAC_ADDRESS MACAddress; 817 PCI_CONFIG_HEADER *CfgHdr; 818 INT32 Val; 819 INT32 Index; 820 INT32 Index2; 821 UINT8 AddrLen; 822 MAC_ADDR_DEVICE_PATH MacAddrNode; 823 EFI_DEVICE_PATH_PROTOCOL *EndNode; 824 UINT8 *DevicePtr; 825 UINT16 TotalPathLen; 826 UINT16 BasePathLen; 827 EFI_STATUS Status; 828 829 // 830 // set the environment ready (similar to UNDI_Start call) so that we can 831 // execute the other UNDI_ calls to get the mac address 832 // we are using undi 3.1 style 833 // 834 AdapterInfo->Delay = TmpDelay; 835 AdapterInfo->Virt2Phys = (VOID *) 0; 836 AdapterInfo->Block = (VOID *) 0; 837 AdapterInfo->Map_Mem = (VOID *) 0; 838 AdapterInfo->UnMap_Mem = (VOID *) 0; 839 AdapterInfo->Sync_Mem = (VOID *) 0; 840 AdapterInfo->Mem_Io = TmpMemIo; 841 // 842 // these tmp call-backs follow 3.1 undi style 843 // i.e. they have the unique_id parameter. 844 // 845 AdapterInfo->VersionFlag = 0x31; 846 AdapterInfo->Unique_ID = (UINT64) (UINTN) AdapterInfo; 847 848 // 849 // undi init portion 850 // 851 CfgHdr = (PCI_CONFIG_HEADER *) &(AdapterInfo->Config[0]); 852 AdapterInfo->ioaddr = 0; 853 AdapterInfo->RevID = CfgHdr->RevID; 854 855 AddrLen = E100bGetEepromAddrLen (AdapterInfo); 856 857 for (Index = 0, Index2 = 0; Index < 3; Index++) { 858 Val = E100bReadEeprom (AdapterInfo, Index, AddrLen); 859 MACAddress.Addr[Index2++] = (UINT8) Val; 860 MACAddress.Addr[Index2++] = (UINT8) (Val >> 8); 861 } 862 863 SetMem (MACAddress.Addr + Index2, sizeof (EFI_MAC_ADDRESS) - Index2, 0); 864 //for (; Index2 < sizeof (EFI_MAC_ADDRESS); Index2++) { 865 // MACAddress.Addr[Index2] = 0; 866 //} 867 // 868 // stop undi 869 // 870 AdapterInfo->Delay = (VOID *) 0; 871 AdapterInfo->Mem_Io = (VOID *) 0; 872 873 // 874 // fill the mac address node first 875 // 876 ZeroMem ((CHAR8 *) &MacAddrNode, sizeof MacAddrNode); 877 CopyMem ( 878 (CHAR8 *) &MacAddrNode.MacAddress, 879 (CHAR8 *) &MACAddress, 880 sizeof (EFI_MAC_ADDRESS) 881 ); 882 883 MacAddrNode.Header.Type = MESSAGING_DEVICE_PATH; 884 MacAddrNode.Header.SubType = MSG_MAC_ADDR_DP; 885 MacAddrNode.Header.Length[0] = (UINT8) sizeof (MacAddrNode); 886 MacAddrNode.Header.Length[1] = 0; 887 888 // 889 // find the size of the base dev path. 890 // 891 EndNode = BaseDevPtr; 892 893 while (!IsDevicePathEnd (EndNode)) { 894 EndNode = NextDevicePathNode (EndNode); 895 } 896 897 BasePathLen = (UINT16) ((UINTN) (EndNode) - (UINTN) (BaseDevPtr)); 898 899 // 900 // create space for full dev path 901 // 902 TotalPathLen = (UINT16) (BasePathLen + sizeof (MacAddrNode) + sizeof (EFI_DEVICE_PATH_PROTOCOL)); 903 904 Status = gBS->AllocatePool ( 905 EfiRuntimeServicesData, 906 TotalPathLen, 907 (VOID **) &DevicePtr 908 ); 909 910 if (Status != EFI_SUCCESS) { 911 return Status; 912 } 913 // 914 // copy the base path, mac addr and end_dev_path nodes 915 // 916 *DevPtr = (EFI_DEVICE_PATH_PROTOCOL *) DevicePtr; 917 CopyMem (DevicePtr, (CHAR8 *) BaseDevPtr, BasePathLen); 918 DevicePtr += BasePathLen; 919 CopyMem (DevicePtr, (CHAR8 *) &MacAddrNode, sizeof (MacAddrNode)); 920 DevicePtr += sizeof (MacAddrNode); 921 CopyMem (DevicePtr, (CHAR8 *) EndNode, sizeof (EFI_DEVICE_PATH_PROTOCOL)); 922 923 return EFI_SUCCESS; 924 } 925 926 927 /** 928 Install a GUID/Pointer pair into the system's configuration table. 929 930 none 931 932 @retval EFI_SUCCESS Install a GUID/Pointer pair into the system's 933 configuration table. 934 @retval other Did not successfully install the GUID/Pointer pair 935 into the configuration table. 936 937 **/ 938 // TODO: VOID - add argument and description to function comment 939 EFI_STATUS 940 InstallConfigTable ( 941 IN VOID 942 ) 943 { 944 EFI_STATUS Status; 945 EFI_CONFIGURATION_TABLE *CfgPtr; 946 UNDI_CONFIG_TABLE *TmpData; 947 UINT16 Index; 948 UNDI_CONFIG_TABLE *UndiData; 949 950 if (pxe_31 == NULL) { 951 return EFI_SUCCESS; 952 } 953 954 if(UndiDataPointer == NULL) { 955 return EFI_SUCCESS; 956 } 957 958 UndiData = (UNDI_CONFIG_TABLE *)UndiDataPointer; 959 960 UndiData->NumberOfInterfaces = (pxe_31->IFcnt | pxe_31->IFcntExt << 8); 961 UndiData->nextlink = NULL; 962 963 for (Index = 0; Index < (pxe_31->IFcnt | pxe_31->IFcntExt << 8); Index++) { 964 UndiData->NII_entry[Index].NII_InterfacePointer = &UNDI32DeviceList[Index]->NIIProtocol_31; 965 UndiData->NII_entry[Index].DevicePathPointer = UNDI32DeviceList[Index]->Undi32DevPath; 966 } 967 968 // 969 // see if there is an entry in the config table already 970 // 971 CfgPtr = gST->ConfigurationTable; 972 973 for (Index = 0; Index < gST->NumberOfTableEntries; Index++) { 974 Status = CompareGuid ( 975 &CfgPtr->VendorGuid, 976 &gEfiNetworkInterfaceIdentifierProtocolGuid_31 977 ); 978 if (Status != EFI_SUCCESS) { 979 break; 980 } 981 982 CfgPtr++; 983 } 984 985 if (Index < gST->NumberOfTableEntries) { 986 TmpData = (UNDI_CONFIG_TABLE *) CfgPtr->VendorTable; 987 988 // 989 // go to the last link 990 // 991 while (TmpData->nextlink != NULL) { 992 TmpData = TmpData->nextlink; 993 } 994 995 TmpData->nextlink = UndiData; 996 997 // 998 // 1st one in chain 999 // 1000 UndiData = (UNDI_CONFIG_TABLE *) CfgPtr->VendorTable; 1001 } 1002 1003 // 1004 // create an entry in the configuration table for our GUID 1005 // 1006 Status = gBS->InstallConfigurationTable ( 1007 &gEfiNetworkInterfaceIdentifierProtocolGuid_31, 1008 UndiData 1009 ); 1010 return Status; 1011 } 1012 1013 /** 1014 1015 **/ 1016 EFI_STATUS 1017 EFIAPI 1018 InitializeUndi( 1019 IN EFI_HANDLE ImageHandle, 1020 IN EFI_SYSTEM_TABLE *SystemTable 1021 ) 1022 { 1023 EFI_EVENT Event; 1024 EFI_STATUS Status; 1025 1026 Status = EfiLibInstallDriverBindingComponentName2 ( 1027 ImageHandle, 1028 SystemTable, 1029 &gUndiDriverBinding, 1030 ImageHandle, 1031 &gUndiComponentName, 1032 &gUndiComponentName2 1033 ); 1034 ASSERT_EFI_ERROR (Status); 1035 1036 Status = gBS->CreateEventEx ( 1037 EVT_NOTIFY_SIGNAL, 1038 TPL_NOTIFY, 1039 UndiNotifyReadyToBoot, 1040 NULL, 1041 &gEfiEventReadyToBootGuid, 1042 &Event 1043 ); 1044 ASSERT_EFI_ERROR (Status); 1045 1046 Status = gBS->CreateEventEx ( 1047 EVT_NOTIFY_SIGNAL, 1048 TPL_NOTIFY, 1049 UndiNotifyVirtual, 1050 NULL, 1051 &gEfiEventVirtualAddressChangeGuid, 1052 &Event 1053 ); 1054 ASSERT_EFI_ERROR (Status); 1055 1056 return Status; 1057 } 1058