add UndiRuntimeDxe from MdeModulePkg to OptionRomPkg.
[edk2.git] / OptionRomPkg / UndiRuntimeDxe / Init.c
blob42dd5fd21f7676a9e1b2f6cd8ca5338207916d9c
1 /** @file
2 Initialization functions for EFI UNDI32 driver.
4 Copyright (c) 2006 - 2008, Intel Corporation
5 All rights reserved. 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
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.
13 **/
15 #include "Undi32.h"
17 // Global Variables
20 PXE_SW_UNDI *pxe_31 = NULL; // 3.1 entry
21 UNDI32_DEV *UNDI32DeviceList[MAX_NIC_INTERFACES];
22 NII_TABLE *UndiDataPointer = NULL;
25 // UNDI Class Driver Global Variables
27 EFI_DRIVER_BINDING_PROTOCOL gUndiDriverBinding = {
28 UndiDriverSupported,
29 UndiDriverStart,
30 UndiDriverStop,
31 0xa,
32 NULL,
33 NULL
37 /**
38 When address mapping changes to virtual this should make the appropriate
39 address conversions.
41 (Standard Event handler)
43 @return None
45 **/
46 VOID
47 EFIAPI
48 UndiNotifyVirtual (
49 EFI_EVENT Event,
50 VOID *Context
53 UINT16 Index;
54 VOID *Pxe31Pointer;
56 if (pxe_31 != NULL) {
57 Pxe31Pointer = (VOID *) pxe_31;
59 EfiConvertPointer (
60 EFI_OPTIONAL_PTR,
61 (VOID **) &Pxe31Pointer
65 // UNDI32DeviceList is an array of pointers
67 for (Index = 0; Index < pxe_31->IFcnt; Index++) {
68 UNDI32DeviceList[Index]->NIIProtocol_31.Id = (UINT64) (UINTN) Pxe31Pointer;
69 EfiConvertPointer (
70 EFI_OPTIONAL_PTR,
71 (VOID **) &(UNDI32DeviceList[Index])
75 EfiConvertPointer (
76 EFI_OPTIONAL_PTR,
77 (VOID **) &(pxe_31->EntryPoint)
79 pxe_31 = Pxe31Pointer;
82 for (Index = 0; Index <= PXE_OPCODE_LAST_VALID; Index++) {
83 EfiConvertPointer (
84 EFI_OPTIONAL_PTR,
85 (VOID **) &api_table[Index].api_ptr
91 /**
92 When EFI is shuting down the boot services, we need to install a
93 configuration table for UNDI to work at runtime!
95 (Standard Event handler)
97 @return None
99 **/
100 VOID
101 EFIAPI
102 UndiNotifyExitBs (
103 EFI_EVENT Event,
104 VOID *Context
107 InstallConfigTable ();
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.
118 @param This Protocol instance pointer.
119 @param Controller Handle of device to test.
120 @param RemainingDevicePath Not used.
122 @retval EFI_SUCCESS This driver supports this device.
123 @retval other This driver does not support this device.
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
134 EFI_STATUS Status;
135 EFI_PCI_IO_PROTOCOL *PciIo;
136 PCI_TYPE00 Pci;
138 Status = gBS->OpenProtocol (
139 Controller,
140 &gEfiDevicePathProtocolGuid,
141 NULL,
142 This->DriverBindingHandle,
143 Controller,
144 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
146 if (EFI_ERROR (Status)) {
147 return Status;
150 Status = gBS->OpenProtocol (
151 Controller,
152 &gEfiPciIoProtocolGuid,
153 (VOID **) &PciIo,
154 This->DriverBindingHandle,
155 Controller,
156 EFI_OPEN_PROTOCOL_BY_DRIVER
158 if (EFI_ERROR (Status)) {
159 return Status;
162 Status = PciIo->Pci.Read (
163 PciIo,
164 EfiPciIoWidthUint8,
166 sizeof (PCI_CONFIG_HEADER),
167 &Pci
170 if (!EFI_ERROR (Status)) {
171 Status = EFI_UNSUPPORTED;
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;
206 gBS->CloseProtocol (
207 Controller,
208 &gEfiPciIoProtocolGuid,
209 This->DriverBindingHandle,
210 Controller
213 return Status;
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.
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.
227 @retval EFI_SUCCESS This driver is added to Controller.
228 @retval other This driver does not support this device.
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
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;
250 Status = gBS->OpenProtocol (
251 Controller,
252 &gEfiPciIoProtocolGuid,
253 (VOID **) &PciIoFncs,
254 This->DriverBindingHandle,
255 Controller,
256 EFI_OPEN_PROTOCOL_BY_DRIVER
259 if (EFI_ERROR (Status)) {
260 return Status;
263 Status = gBS->OpenProtocol (
264 Controller,
265 &gEfiDevicePathProtocolGuid,
266 (VOID **) &UndiDevicePath,
267 This->DriverBindingHandle,
268 Controller,
269 EFI_OPEN_PROTOCOL_BY_DRIVER
272 if (EFI_ERROR (Status)) {
273 gBS->CloseProtocol (
274 Controller,
275 &gEfiPciIoProtocolGuid,
276 This->DriverBindingHandle,
277 Controller
280 return Status;
283 PciAttributesSaved = FALSE;
285 Status = gBS->AllocatePool (
286 EfiRuntimeServicesData,
287 sizeof (UNDI32_DEV),
288 (VOID **) &UNDI32Device
291 if (EFI_ERROR (Status)) {
292 goto UndiError;
295 ZeroMem ((CHAR8 *) UNDI32Device, sizeof (UNDI32_DEV));
298 // Get original PCI attributes
300 Status = PciIoFncs->Attributes (
301 PciIoFncs,
302 EfiPciIoAttributeOperationGet,
304 &UNDI32Device->NicInfo.OriginalPciAttributes
307 if (EFI_ERROR (Status)) {
308 goto UndiErrorDeleteDevice;
310 PciAttributesSaved = TRUE;
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)
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
328 if (EFI_ERROR (Status)) {
329 goto UndiErrorDeleteDevice;
332 ZeroMem (
333 TmpPxePointer,
334 sizeof (PXE_SW_UNDI) + sizeof (PXE_SW_UNDI) + 32
337 // check for paragraph alignment here, assuming that the pointer is
338 // already 8 byte aligned.
340 if (((UINTN) TmpPxePointer & 0x0F) != 0) {
341 pxe_31 = (PXE_SW_UNDI *) ((UINTN) (TmpPxePointer + 8));
342 } else {
343 pxe_31 = (PXE_SW_UNDI *) TmpPxePointer;
346 PxeStructInit (pxe_31);
349 UNDI32Device->NIIProtocol_31.Id = (UINT64) (UINTN) (pxe_31);
351 Status = PciIoFncs->Attributes (
352 PciIoFncs,
353 EfiPciIoAttributeOperationSupported,
355 &Supports
357 if (!EFI_ERROR (Status)) {
358 Supports &= EFI_PCI_DEVICE_ENABLE;
359 Status = PciIoFncs->Attributes (
360 PciIoFncs,
361 EfiPciIoAttributeOperationEnable,
362 Supports,
363 NULL
367 // Read all the registers from device's PCI Configuration space
369 Status = PciIoFncs->Pci.Read (
370 PciIoFncs,
371 EfiPciIoWidthUint32,
373 MAX_PCI_CONFIG_LEN,
374 &UNDI32Device->NicInfo.Config
377 CfgHdr = (PCI_CONFIG_HEADER *) &(UNDI32Device->NicInfo.Config[0]);
380 // make sure that this device is a PCI bus master
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,
390 &NewCommand
392 CfgHdr->Command = NewCommand;
396 // make sure that the latency timer is at least 32
398 if (CfgHdr->LatencyTimer < 32) {
399 CfgHdr->LatencyTimer = 32;
400 PciIoFncs->Pci.Write (
401 PciIoFncs,
402 EfiPciIoWidthUint8,
403 PCI_LATENCY_TIMER,
405 &CfgHdr->LatencyTimer
409 // the IfNum index for the current interface will be the total number
410 // of interfaces initialized so far
412 UNDI32Device->NIIProtocol_31.IfNum = pxe_31->IFcnt;
414 PxeUpdate (&UNDI32Device->NicInfo, pxe_31);
416 UNDI32Device->NicInfo.Io_Function = PciIoFncs;
417 UNDI32DeviceList[UNDI32Device->NIIProtocol_31.IfNum] = UNDI32Device;
418 UNDI32Device->Undi32BaseDevPath = UndiDevicePath;
420 Status = AppendMac2DevPath (
421 &UNDI32Device->Undi32DevPath,
422 UNDI32Device->Undi32BaseDevPath,
423 &UNDI32Device->NicInfo
426 if (Status != 0) {
427 goto UndiErrorDeletePxe;
430 UNDI32Device->Signature = UNDI_DEV_SIGNATURE;
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 = FALSE;
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';
445 UNDI32Device->DeviceHandle = NULL;
448 // install both the 3.0 and 3.1 NII protocols.
450 Status = gBS->InstallMultipleProtocolInterfaces (
451 &UNDI32Device->DeviceHandle,
452 &gEfiNetworkInterfaceIdentifierProtocolGuid_31,
453 &UNDI32Device->NIIProtocol_31,
454 &gEfiDevicePathProtocolGuid,
455 UNDI32Device->Undi32DevPath,
456 NULL
459 if (EFI_ERROR (Status)) {
460 goto UndiErrorDeleteDevicePath;
464 // if the table exists, free it and alloc again, or alloc it directly
466 if (UndiDataPointer != NULL) {
467 Status = gBS->FreePool(UndiDataPointer);
469 if (EFI_ERROR (Status)) {
470 goto UndiErrorDeleteDevicePath;
473 Len = (pxe_31->IFcnt * sizeof (NII_ENTRY)) + sizeof (UndiDataPointer);
474 Status = gBS->AllocatePool (EfiRuntimeServicesData, Len, (VOID **) &UndiDataPointer);
476 if (EFI_ERROR (Status)) {
477 goto UndiErrorAllocDataPointer;
481 // Open For Child Device
483 Status = gBS->OpenProtocol (
484 Controller,
485 &gEfiPciIoProtocolGuid,
486 (VOID **) &PciIoFncs,
487 This->DriverBindingHandle,
488 UNDI32Device->DeviceHandle,
489 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
492 return EFI_SUCCESS;
493 UndiErrorAllocDataPointer:
494 gBS->UninstallMultipleProtocolInterfaces (
495 &UNDI32Device->DeviceHandle,
496 &gEfiNetworkInterfaceIdentifierProtocolGuid_31,
497 &UNDI32Device->NIIProtocol_31,
498 &gEfiDevicePathProtocolGuid,
499 UNDI32Device->Undi32DevPath,
500 NULL
503 UndiErrorDeleteDevicePath:
504 UNDI32DeviceList[UNDI32Device->NIIProtocol_31.IfNum] = NULL;
505 gBS->FreePool (UNDI32Device->Undi32DevPath);
507 UndiErrorDeletePxe:
508 PxeUpdate (NULL, pxe_31);
509 if (TmpPxePointer != NULL) {
510 gBS->FreePool (TmpPxePointer);
514 UndiErrorDeleteDevice:
515 if (PciAttributesSaved) {
517 // Restore original PCI attributes
519 PciIoFncs->Attributes (
520 PciIoFncs,
521 EfiPciIoAttributeOperationSet,
522 UNDI32Device->NicInfo.OriginalPciAttributes,
523 NULL
527 gBS->FreePool (UNDI32Device);
529 UndiError:
530 gBS->CloseProtocol (
531 Controller,
532 &gEfiDevicePathProtocolGuid,
533 This->DriverBindingHandle,
534 Controller
537 gBS->CloseProtocol (
538 Controller,
539 &gEfiPciIoProtocolGuid,
540 This->DriverBindingHandle,
541 Controller
544 return Status;
549 Stop this driver on Controller by removing NetworkInterfaceIdentifier protocol and
550 closing the DevicePath and PciIo protocols on Controller.
552 @param This Protocol instance pointer.
553 @param Controller Handle of device to stop driver on.
554 @param NumberOfChildren How many children need to be stopped.
555 @param ChildHandleBuffer Not used.
557 @retval EFI_SUCCESS This driver is removed Controller.
558 @retval other This driver was not removed from this device.
561 // TODO: EFI_DEVICE_ERROR - add return value to function comment
562 EFI_STATUS
563 EFIAPI
564 UndiDriverStop (
565 IN EFI_DRIVER_BINDING_PROTOCOL *This,
566 IN EFI_HANDLE Controller,
567 IN UINTN NumberOfChildren,
568 IN EFI_HANDLE *ChildHandleBuffer
571 EFI_STATUS Status;
572 BOOLEAN AllChildrenStopped;
573 UINTN Index;
574 UNDI32_DEV *UNDI32Device;
575 EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL *NIIProtocol;
576 EFI_PCI_IO_PROTOCOL *PciIo;
579 // Complete all outstanding transactions to Controller.
580 // Don't allow any new transaction to Controller to be started.
582 if (NumberOfChildren == 0) {
585 // Close the bus driver
587 Status = gBS->CloseProtocol (
588 Controller,
589 &gEfiDevicePathProtocolGuid,
590 This->DriverBindingHandle,
591 Controller
594 Status = gBS->CloseProtocol (
595 Controller,
596 &gEfiPciIoProtocolGuid,
597 This->DriverBindingHandle,
598 Controller
601 return Status;
604 AllChildrenStopped = TRUE;
606 for (Index = 0; Index < NumberOfChildren; Index++) {
608 Status = gBS->OpenProtocol (
609 ChildHandleBuffer[Index],
610 &gEfiNetworkInterfaceIdentifierProtocolGuid_31,
611 (VOID **) &NIIProtocol,
612 This->DriverBindingHandle,
613 Controller,
614 EFI_OPEN_PROTOCOL_GET_PROTOCOL
616 if (!EFI_ERROR (Status)) {
618 UNDI32Device = UNDI_DEV_FROM_THIS (NIIProtocol);
621 // Restore original PCI attributes
623 Status = UNDI32Device->NicInfo.Io_Function->Attributes (
624 UNDI32Device->NicInfo.Io_Function,
625 EfiPciIoAttributeOperationSet,
626 UNDI32Device->NicInfo.OriginalPciAttributes,
627 NULL
629 ASSERT_EFI_ERROR (Status);
631 Status = gBS->CloseProtocol (
632 Controller,
633 &gEfiPciIoProtocolGuid,
634 This->DriverBindingHandle,
635 ChildHandleBuffer[Index]
638 Status = gBS->UninstallMultipleProtocolInterfaces (
639 ChildHandleBuffer[Index],
640 &gEfiDevicePathProtocolGuid,
641 UNDI32Device->Undi32DevPath,
642 &gEfiNetworkInterfaceIdentifierProtocolGuid_31,
643 &UNDI32Device->NIIProtocol_31,
644 NULL
647 if (EFI_ERROR (Status)) {
648 gBS->OpenProtocol (
649 Controller,
650 &gEfiPciIoProtocolGuid,
651 (VOID **) &PciIo,
652 This->DriverBindingHandle,
653 ChildHandleBuffer[Index],
654 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
656 } else {
657 gBS->FreePool (UNDI32Device->Undi32DevPath);
658 gBS->FreePool (UNDI32Device);
662 if (EFI_ERROR (Status)) {
663 AllChildrenStopped = FALSE;
667 if (!AllChildrenStopped) {
668 return EFI_DEVICE_ERROR;
671 return EFI_SUCCESS;
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.
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.
685 @return none
688 VOID
689 TmpDelay (
690 IN UINT64 UnqId,
691 IN UINTN MicroSeconds
694 gBS->Stall ((UINT32) MicroSeconds);
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.
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.
710 @return none
713 VOID
714 TmpMemIo (
715 IN UINT64 UnqId,
716 IN UINT8 ReadWrite,
717 IN UINT8 Len,
718 IN UINT64 Port,
719 IN UINT64 BuffAddr
722 EFI_PCI_IO_PROTOCOL_WIDTH Width;
723 NIC_DATA_INSTANCE *AdapterInfo;
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;
732 case 4:
733 Width = (EFI_PCI_IO_PROTOCOL_WIDTH) 2;
734 break;
736 case 8:
737 Width = (EFI_PCI_IO_PROTOCOL_WIDTH) 3;
738 break;
741 switch (ReadWrite) {
742 case PXE_IO_READ:
743 AdapterInfo->Io_Function->Io.Read (
744 AdapterInfo->Io_Function,
745 Width,
747 Port,
749 (VOID *) (UINTN) (BuffAddr)
751 break;
753 case PXE_IO_WRITE:
754 AdapterInfo->Io_Function->Io.Write (
755 AdapterInfo->Io_Function,
756 Width,
758 Port,
760 (VOID *) (UINTN) (BuffAddr)
762 break;
764 case PXE_MEM_READ:
765 AdapterInfo->Io_Function->Mem.Read (
766 AdapterInfo->Io_Function,
767 Width,
769 Port,
771 (VOID *) (UINTN) (BuffAddr)
773 break;
775 case PXE_MEM_WRITE:
776 AdapterInfo->Io_Function->Mem.Write (
777 AdapterInfo->Io_Function,
778 Width,
780 Port,
782 (VOID *) (UINTN) (BuffAddr)
784 break;
787 return ;
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.
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..
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.
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
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;
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
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;
842 // these tmp call-backs follow 3.1 undi style
843 // i.e. they have the unique_id parameter.
845 AdapterInfo->VersionFlag = 0x31;
846 AdapterInfo->Unique_ID = (UINT64) (UINTN) AdapterInfo;
849 // undi init portion
851 CfgHdr = (PCI_CONFIG_HEADER *) &(AdapterInfo->Config[0]);
852 AdapterInfo->ioaddr = 0;
853 AdapterInfo->RevID = CfgHdr->RevID;
855 AddrLen = E100bGetEepromAddrLen (AdapterInfo);
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);
863 SetMem (MACAddress.Addr + Index2, sizeof (EFI_MAC_ADDRESS) - Index2, 0);
864 //for (; Index2 < sizeof (EFI_MAC_ADDRESS); Index2++) {
865 // MACAddress.Addr[Index2] = 0;
868 // stop undi
870 AdapterInfo->Delay = (VOID *) 0;
871 AdapterInfo->Mem_Io = (VOID *) 0;
874 // fill the mac address node first
876 ZeroMem ((CHAR8 *) &MacAddrNode, sizeof MacAddrNode);
877 CopyMem (
878 (CHAR8 *) &MacAddrNode.MacAddress,
879 (CHAR8 *) &MACAddress,
880 sizeof (EFI_MAC_ADDRESS)
883 MacAddrNode.Header.Type = MESSAGING_DEVICE_PATH;
884 MacAddrNode.Header.SubType = MSG_MAC_ADDR_DP;
885 MacAddrNode.Header.Length[0] = sizeof (MacAddrNode);
886 MacAddrNode.Header.Length[1] = 0;
889 // find the size of the base dev path.
891 EndNode = BaseDevPtr;
893 while (!IsDevicePathEnd (EndNode)) {
894 EndNode = NextDevicePathNode (EndNode);
897 BasePathLen = (UINT16) ((UINTN) (EndNode) - (UINTN) (BaseDevPtr));
900 // create space for full dev path
902 TotalPathLen = (UINT16) (BasePathLen + sizeof (MacAddrNode) + sizeof (EFI_DEVICE_PATH_PROTOCOL));
904 Status = gBS->AllocatePool (
905 EfiRuntimeServicesData,
906 TotalPathLen,
907 (VOID **) &DevicePtr
910 if (Status != EFI_SUCCESS) {
911 return Status;
914 // copy the base path, mac addr and end_dev_path nodes
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));
923 return EFI_SUCCESS;
928 Install a GUID/Pointer pair into the system's configuration table.
930 none
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.
938 // TODO: VOID - add argument and description to function comment
939 EFI_STATUS
940 InstallConfigTable (
941 IN VOID
944 EFI_STATUS Status;
945 EFI_CONFIGURATION_TABLE *CfgPtr;
946 NII_TABLE *TmpData;
947 UINT16 Index;
948 NII_TABLE *UndiData;
950 if (pxe_31 == NULL) {
951 return EFI_SUCCESS;
954 if(UndiDataPointer == NULL) {
955 return EFI_SUCCESS;
958 UndiData = (NII_TABLE *)UndiDataPointer;
960 UndiData->NumEntries = pxe_31->IFcnt;
961 UndiData->NextLink = NULL;
963 for (Index = 0; Index < pxe_31->IFcnt; Index++) {
964 UndiData->NiiEntry[Index].InterfacePointer = &UNDI32DeviceList[Index]->NIIProtocol_31;
965 UndiData->NiiEntry[Index].DevicePathPointer = UNDI32DeviceList[Index]->Undi32DevPath;
969 // see if there is an entry in the config table already
971 CfgPtr = gST->ConfigurationTable;
973 for (Index = 0; Index < gST->NumberOfTableEntries; Index++) {
974 Status = CompareGuid (
975 &CfgPtr->VendorGuid,
976 &gEfiNetworkInterfaceIdentifierProtocolGuid_31
978 if (Status != EFI_SUCCESS) {
979 break;
982 CfgPtr++;
985 if (Index < gST->NumberOfTableEntries) {
986 TmpData = (NII_TABLE *) CfgPtr->VendorTable;
989 // go to the last link
991 while (TmpData->NextLink != NULL) {
992 TmpData = TmpData->NextLink;
995 TmpData->NextLink = UndiData;
998 // 1st one in chain
1000 UndiData = (NII_TABLE *) CfgPtr->VendorTable;
1004 // create an entry in the configuration table for our GUID
1006 Status = gBS->InstallConfigurationTable (
1007 &gEfiNetworkInterfaceIdentifierProtocolGuid_31,
1008 UndiData
1010 return Status;
1016 EFI_STATUS
1017 EFIAPI
1018 InitializeUndi(
1019 IN EFI_HANDLE ImageHandle,
1020 IN EFI_SYSTEM_TABLE *SystemTable
1023 EFI_EVENT Event;
1024 EFI_STATUS Status;
1026 Status = EfiLibInstallDriverBinding (
1027 ImageHandle,
1028 SystemTable,
1029 &gUndiDriverBinding,
1030 ImageHandle
1032 ASSERT_EFI_ERROR (Status);
1034 Status = gBS->CreateEventEx (
1035 EVT_NOTIFY_SIGNAL,
1036 TPL_NOTIFY,
1037 UndiNotifyExitBs,
1038 NULL,
1039 &gEfiEventExitBootServicesGuid,
1040 &Event
1042 ASSERT_EFI_ERROR (Status);
1044 Status = gBS->CreateEventEx (
1045 EVT_NOTIFY_SIGNAL,
1046 TPL_NOTIFY,
1047 UndiNotifyVirtual,
1048 NULL,
1049 &gEfiEventVirtualAddressChangeGuid,
1050 &Event
1052 ASSERT_EFI_ERROR (Status);
1054 return Status;