1/** @file 2 Initialization functions for EFI UNDI32 driver. 3 4Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.<BR> 5This program and the accompanying materials 6are licensed and made available under the terms and conditions of the BSD License 7which accompanies this distribution. The full text of the license may be found at 8http://opensource.org/licenses/bsd-license.php 9 10THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 11WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 12 13**/ 14 15#include "Undi32.h" 16// 17// Global Variables 18// 19 20PXE_SW_UNDI *pxe_31 = NULL; // 3.1 entry 21UNDI32_DEV *UNDI32DeviceList[MAX_NIC_INTERFACES]; 22UNDI_CONFIG_TABLE *UndiDataPointer = NULL; 23 24// 25// UNDI Class Driver Global Variables 26// 27EFI_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**/ 46VOID 47EFIAPI 48UndiNotifyVirtual ( 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**/ 100VOID 101EFIAPI 102UndiNotifyReadyToBoot ( 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**/ 126EFI_STATUS 127EFIAPI 128UndiDriverSupported ( 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**/ 231EFI_STATUS 232EFIAPI 233UndiDriverStart ( 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; 499UndiErrorAllocDataPointer: 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 511UndiErrorDeleteDevicePath: 512 UNDI32DeviceList[UNDI32Device->NIIProtocol_31.IfNum] = NULL; 513 gBS->FreePool (UNDI32Device->Undi32DevPath); 514 515UndiErrorDeletePxe: 516 PxeUpdate (NULL, pxe_31); 517 if (TmpPxePointer != NULL) { 518 gBS->FreePool (TmpPxePointer); 519 520 } 521 522UndiErrorDeleteDevice: 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 537UndiError: 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 570EFI_STATUS 571EFIAPI 572UndiDriverStop ( 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**/ 688VOID 689TmpDelay ( 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**/ 713VOID 714TmpMemIo ( 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**/ 809EFI_STATUS 810AppendMac2DevPath ( 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 939EFI_STATUS 940InstallConfigTable ( 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**/ 1016EFI_STATUS 1017EFIAPI 1018InitializeUndi( 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