hikey: Add UEFI sources for reference

UEFI needs to be built outside Android build system.
Please follow the instructions in README.

The sources correspond to:
https://github.com/96boards/edk2/commit/14eae0c12e71fd33c4c0fc51e4475e8db02566cf
https://github.com/96boards/arm-trusted-firmware/commit/e9b4909dcd75fc4ae7041cfb83d28ab9adb7afdf
https://github.com/96boards/l-loader/commit/6b784ad5c4ab00e2b1c6f53cd5f74054e5d00a78
https://git.linaro.org/uefi/uefi-tools.git/commit/abe618f8ab72034fff1ce46c9c006a2c6bd40a7e

Change-Id: Ieeefdb63e673e0c8e64e0a1f02c7bddc63b2c7fb
Signed-off-by: Vishal Bhoj <vishal.bhoj@linaro.org>
diff --git a/uefi/linaro-edk2/OptionRomPkg/UndiRuntimeDxe/Init.c b/uefi/linaro-edk2/OptionRomPkg/UndiRuntimeDxe/Init.c
new file mode 100644
index 0000000..9410fe1
--- /dev/null
+++ b/uefi/linaro-edk2/OptionRomPkg/UndiRuntimeDxe/Init.c
@@ -0,0 +1,1049 @@
+/** @file

+  Initialization functions for EFI UNDI32 driver.

+

+Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR>

+This program and the accompanying materials

+are licensed and made available under the terms and conditions of the BSD License

+which accompanies this distribution.  The full text of the license may be found at

+http://opensource.org/licenses/bsd-license.php

+

+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,

+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

+

+**/

+

+#include "Undi32.h"

+//

+// Global Variables

+//

+

+PXE_SW_UNDI             *pxe_31 = NULL;  // 3.1 entry

+UNDI32_DEV              *UNDI32DeviceList[MAX_NIC_INTERFACES];

+UNDI_CONFIG_TABLE       *UndiDataPointer = NULL;

+

+//

+// UNDI Class Driver Global Variables

+//

+EFI_DRIVER_BINDING_PROTOCOL  gUndiDriverBinding = {

+  UndiDriverSupported,

+  UndiDriverStart,

+  UndiDriverStop,

+  0xa,

+  NULL,

+  NULL

+};

+

+

+/**

+  When address mapping changes to virtual this should make the appropriate

+  address conversions.

+

+  (Standard Event handler)

+

+  @return None

+

+**/

+VOID

+EFIAPI

+UndiNotifyVirtual (

+  EFI_EVENT Event,

+  VOID      *Context

+  )

+{

+  UINT16  Index;

+  VOID    *Pxe31Pointer;

+

+  if (pxe_31 != NULL) {

+    Pxe31Pointer = (VOID *) pxe_31;

+

+    EfiConvertPointer (

+      EFI_OPTIONAL_PTR,

+      (VOID **) &Pxe31Pointer

+      );

+

+    //

+    // UNDI32DeviceList is an array of pointers

+    //

+    for (Index = 0; Index < (pxe_31->IFcnt | pxe_31->IFcntExt << 8); Index++) {

+      UNDI32DeviceList[Index]->NIIProtocol_31.Id = (UINT64) (UINTN) Pxe31Pointer;

+      EfiConvertPointer (

+        EFI_OPTIONAL_PTR,

+        (VOID **) &(UNDI32DeviceList[Index])

+        );

+    }

+

+    EfiConvertPointer (

+      EFI_OPTIONAL_PTR,

+      (VOID **) &(pxe_31->EntryPoint)

+      );

+    pxe_31 = Pxe31Pointer;

+  }

+

+  for (Index = 0; Index <= PXE_OPCODE_LAST_VALID; Index++) {

+    EfiConvertPointer (

+      EFI_OPTIONAL_PTR,

+      (VOID **) &api_table[Index].api_ptr

+      );

+  }

+}

+

+

+/**

+  When EFI is shuting down the boot services, we need to install a

+  configuration table for UNDI to work at runtime!

+

+  (Standard Event handler)

+

+  @return None

+

+**/

+VOID

+EFIAPI

+UndiNotifyExitBs (

+  EFI_EVENT Event,

+  VOID      *Context

+  )

+{

+  InstallConfigTable ();

+}

+

+

+/**

+  Test to see if this driver supports ControllerHandle. Any ControllerHandle

+  than contains a  DevicePath, PciIo protocol, Class code of 2, Vendor ID of 0x8086,

+  and DeviceId of (D100_DEVICE_ID || D102_DEVICE_ID || ICH3_DEVICE_ID_1 ||

+  ICH3_DEVICE_ID_2 || ICH3_DEVICE_ID_3 || ICH3_DEVICE_ID_4 || ICH3_DEVICE_ID_5 ||

+  ICH3_DEVICE_ID_6 || ICH3_DEVICE_ID_7 || ICH3_DEVICE_ID_8) can be supported.

+

+  @param  This                 Protocol instance pointer.

+  @param  Controller           Handle of device to test.

+  @param  RemainingDevicePath  Not used.

+

+  @retval EFI_SUCCESS          This driver supports this device.

+  @retval other                This driver does not support this device.

+

+**/

+EFI_STATUS

+EFIAPI

+UndiDriverSupported (

+  IN EFI_DRIVER_BINDING_PROTOCOL    *This,

+  IN EFI_HANDLE                     Controller,

+  IN EFI_DEVICE_PATH_PROTOCOL       *RemainingDevicePath

+  )

+{

+  EFI_STATUS          Status;

+  EFI_PCI_IO_PROTOCOL *PciIo;

+  PCI_TYPE00          Pci;

+

+  Status = gBS->OpenProtocol (

+                  Controller,

+                  &gEfiDevicePathProtocolGuid,

+                  NULL,

+                  This->DriverBindingHandle,

+                  Controller,

+                  EFI_OPEN_PROTOCOL_TEST_PROTOCOL

+                  );

+  if (EFI_ERROR (Status)) {

+    return Status;

+  }

+

+  Status = gBS->OpenProtocol (

+                  Controller,

+                  &gEfiPciIoProtocolGuid,

+                  (VOID **) &PciIo,

+                  This->DriverBindingHandle,

+                  Controller,

+                  EFI_OPEN_PROTOCOL_BY_DRIVER

+                  );

+  if (EFI_ERROR (Status)) {

+    return Status;

+  }

+

+  Status = PciIo->Pci.Read (

+                        PciIo,

+                        EfiPciIoWidthUint8,

+                        0,

+                        sizeof (PCI_CONFIG_HEADER),

+                        &Pci

+                        );

+

+  if (!EFI_ERROR (Status)) {

+    Status = EFI_UNSUPPORTED;

+

+    if (Pci.Hdr.ClassCode[2] == 0x02 && Pci.Hdr.VendorId == PCI_VENDOR_ID_INTEL) {

+      switch (Pci.Hdr.DeviceId) {

+      case D100_DEVICE_ID:

+      case D102_DEVICE_ID:

+      case ICH3_DEVICE_ID_1:

+      case ICH3_DEVICE_ID_2:

+      case ICH3_DEVICE_ID_3:

+      case ICH3_DEVICE_ID_4:

+      case ICH3_DEVICE_ID_5:

+      case ICH3_DEVICE_ID_6:

+      case ICH3_DEVICE_ID_7:

+      case ICH3_DEVICE_ID_8:

+      case 0x1039:

+      case 0x103A:

+      case 0x103B:

+      case 0x103C:

+      case 0x103D:

+      case 0x103E:

+      case 0x1050:

+      case 0x1051:

+      case 0x1052:

+      case 0x1053:

+      case 0x1054:

+      case 0x1055:

+      case 0x1056:

+      case 0x1057:

+      case 0x1059:

+      case 0x1064:

+        Status = EFI_SUCCESS;

+      }

+    }

+  }

+

+  gBS->CloseProtocol (

+        Controller,

+        &gEfiPciIoProtocolGuid,

+        This->DriverBindingHandle,

+        Controller

+        );

+

+  return Status;

+}

+

+

+/**

+  Start this driver on Controller by opening PciIo and DevicePath protocol.

+  Initialize PXE structures, create a copy of the Controller Device Path with the

+  NIC's MAC address appended to it, install the NetworkInterfaceIdentifier protocol

+  on the newly created Device Path.

+

+  @param  This                 Protocol instance pointer.

+  @param  Controller           Handle of device to work with.

+  @param  RemainingDevicePath  Not used, always produce all possible children.

+

+  @retval EFI_SUCCESS          This driver is added to Controller.

+  @retval other                This driver does not support this device.

+

+**/

+EFI_STATUS

+EFIAPI

+UndiDriverStart (

+  IN EFI_DRIVER_BINDING_PROTOCOL    *This,

+  IN EFI_HANDLE                     Controller,

+  IN EFI_DEVICE_PATH_PROTOCOL       *RemainingDevicePath

+  )

+{

+  EFI_STATUS                Status;

+  EFI_DEVICE_PATH_PROTOCOL  *UndiDevicePath;

+  PCI_CONFIG_HEADER         *CfgHdr;

+  UNDI32_DEV                *UNDI32Device;

+  UINT16                    NewCommand;

+  UINT8                     *TmpPxePointer;

+  EFI_PCI_IO_PROTOCOL       *PciIoFncs;

+  UINTN                     Len;

+  UINT64                    Supports;

+  BOOLEAN                   PciAttributesSaved;

+

+  Status = gBS->OpenProtocol (

+                  Controller,

+                  &gEfiPciIoProtocolGuid,

+                  (VOID **) &PciIoFncs,

+                  This->DriverBindingHandle,

+                  Controller,

+                  EFI_OPEN_PROTOCOL_BY_DRIVER

+                  );

+

+  if (EFI_ERROR (Status)) {

+    return Status;

+  }

+

+  Status = gBS->OpenProtocol (

+                  Controller,

+                  &gEfiDevicePathProtocolGuid,

+                  (VOID **) &UndiDevicePath,

+                  This->DriverBindingHandle,

+                  Controller,

+                  EFI_OPEN_PROTOCOL_BY_DRIVER

+                  );

+

+  if (EFI_ERROR (Status)) {

+    gBS->CloseProtocol (

+          Controller,

+          &gEfiPciIoProtocolGuid,

+          This->DriverBindingHandle,

+          Controller

+          );

+

+    return Status;

+  }

+

+  PciAttributesSaved = FALSE;

+

+  Status = gBS->AllocatePool (

+                  EfiRuntimeServicesData,

+                  sizeof (UNDI32_DEV),

+                  (VOID **) &UNDI32Device

+                  );

+

+  if (EFI_ERROR (Status)) {

+    goto UndiError;

+  }

+

+  ZeroMem ((CHAR8 *) UNDI32Device, sizeof (UNDI32_DEV));

+

+  //

+  // Get original PCI attributes

+  //

+  Status = PciIoFncs->Attributes (

+                    PciIoFncs,

+                    EfiPciIoAttributeOperationGet,

+                    0,

+                    &UNDI32Device->NicInfo.OriginalPciAttributes

+                    );

+

+  if (EFI_ERROR (Status)) {

+    goto UndiErrorDeleteDevice;

+  }

+  PciAttributesSaved = TRUE;

+

+  //

+  // allocate and initialize both (old and new) the !pxe structures here,

+  // there should only be one copy of each of these structure for any number

+  // of NICs this undi supports. Also, these structures need to be on a

+  // paragraph boundary as per the spec. so, while allocating space for these,

+  // make sure that there is space for 2 !pxe structures (old and new) and a

+  // 32 bytes padding for alignment adjustment (in case)

+  //

+  TmpPxePointer = NULL;

+  if (pxe_31 == NULL) {

+    Status = gBS->AllocatePool (

+                    EfiRuntimeServicesData,

+                    (sizeof (PXE_SW_UNDI) + sizeof (PXE_SW_UNDI) + 32),

+                    (VOID **) &TmpPxePointer

+                    );

+

+    if (EFI_ERROR (Status)) {

+      goto UndiErrorDeleteDevice;

+    }

+

+    ZeroMem (

+      TmpPxePointer,

+      sizeof (PXE_SW_UNDI) + sizeof (PXE_SW_UNDI) + 32

+      );

+    //

+    // check for paragraph alignment here, assuming that the pointer is

+    // already 8 byte aligned.

+    //

+    if (((UINTN) TmpPxePointer & 0x0F) != 0) {

+      pxe_31 = (PXE_SW_UNDI *) ((UINTN) (TmpPxePointer + 8));

+    } else {

+      pxe_31 = (PXE_SW_UNDI *) TmpPxePointer;

+    }

+

+    PxeStructInit (pxe_31);

+  }

+

+  UNDI32Device->NIIProtocol_31.Id = (UINT64) (UINTN) (pxe_31);

+

+  Status = PciIoFncs->Attributes (

+                        PciIoFncs,

+                        EfiPciIoAttributeOperationSupported,

+                        0,

+                        &Supports

+                        );

+  if (!EFI_ERROR (Status)) {

+    Supports &= EFI_PCI_DEVICE_ENABLE;

+    Status = PciIoFncs->Attributes (

+                          PciIoFncs,

+                          EfiPciIoAttributeOperationEnable,

+                          Supports,

+                          NULL

+                          );

+  }

+  //

+  // Read all the registers from device's PCI Configuration space

+  //

+  Status = PciIoFncs->Pci.Read (

+                            PciIoFncs,

+                            EfiPciIoWidthUint32,

+                            0,

+                            MAX_PCI_CONFIG_LEN,

+                            &UNDI32Device->NicInfo.Config

+                            );

+

+  CfgHdr = (PCI_CONFIG_HEADER *) &(UNDI32Device->NicInfo.Config[0]);

+

+  //

+  // make sure that this device is a PCI bus master

+  //

+

+  NewCommand = (UINT16) (CfgHdr->Command | PCI_COMMAND_MASTER | PCI_COMMAND_IO);

+  if (CfgHdr->Command != NewCommand) {

+    PciIoFncs->Pci.Write (

+                    PciIoFncs,

+                    EfiPciIoWidthUint16,

+                    PCI_COMMAND,

+                    1,

+                    &NewCommand

+                    );

+    CfgHdr->Command = NewCommand;

+  }

+

+  //

+  // make sure that the latency timer is at least 32

+  //

+  if (CfgHdr->LatencyTimer < 32) {

+    CfgHdr->LatencyTimer = 32;

+    PciIoFncs->Pci.Write (

+                    PciIoFncs,

+                    EfiPciIoWidthUint8,

+                    PCI_LATENCY_TIMER,

+                    1,

+                    &CfgHdr->LatencyTimer

+                    );

+  }

+  //

+  // the IfNum index for the current interface will be the total number

+  // of interfaces initialized so far

+  //

+  UNDI32Device->NIIProtocol_31.IfNum  = pxe_31->IFcnt | pxe_31->IFcntExt << 8;

+

+  PxeUpdate (&UNDI32Device->NicInfo, pxe_31);

+

+  UNDI32Device->NicInfo.Io_Function                    = PciIoFncs;

+  UNDI32DeviceList[UNDI32Device->NIIProtocol_31.IfNum] = UNDI32Device;

+  UNDI32Device->Undi32BaseDevPath                      = UndiDevicePath;

+

+  Status = AppendMac2DevPath (

+            &UNDI32Device->Undi32DevPath,

+            UNDI32Device->Undi32BaseDevPath,

+            &UNDI32Device->NicInfo

+            );

+

+  if (Status != 0) {

+    goto UndiErrorDeletePxe;

+  }

+

+  UNDI32Device->Signature                     = UNDI_DEV_SIGNATURE;

+

+  UNDI32Device->NIIProtocol_31.Revision       = EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL_REVISION_31;

+  UNDI32Device->NIIProtocol_31.Type           = EfiNetworkInterfaceUndi;

+  UNDI32Device->NIIProtocol_31.MajorVer       = PXE_ROMID_MAJORVER;

+  UNDI32Device->NIIProtocol_31.MinorVer       = PXE_ROMID_MINORVER_31;

+  UNDI32Device->NIIProtocol_31.ImageSize      = 0;

+  UNDI32Device->NIIProtocol_31.ImageAddr      = 0;

+  UNDI32Device->NIIProtocol_31.Ipv6Supported  = FALSE;

+

+  UNDI32Device->NIIProtocol_31.StringId[0]    = 'U';

+  UNDI32Device->NIIProtocol_31.StringId[1]    = 'N';

+  UNDI32Device->NIIProtocol_31.StringId[2]    = 'D';

+  UNDI32Device->NIIProtocol_31.StringId[3]    = 'I';

+

+  UNDI32Device->DeviceHandle                  = NULL;

+

+  //

+  // install both the 3.0 and 3.1 NII protocols.

+  //

+  Status = gBS->InstallMultipleProtocolInterfaces (

+                  &UNDI32Device->DeviceHandle,

+                  &gEfiNetworkInterfaceIdentifierProtocolGuid_31,

+                  &UNDI32Device->NIIProtocol_31,

+                  &gEfiDevicePathProtocolGuid,

+                  UNDI32Device->Undi32DevPath,

+                  NULL

+                  );

+

+  if (EFI_ERROR (Status)) {

+    goto UndiErrorDeleteDevicePath;

+  }

+

+  //

+  // if the table exists, free it and alloc again, or alloc it directly

+  //

+  if (UndiDataPointer != NULL) {

+    Status = gBS->FreePool(UndiDataPointer);

+  }

+  if (EFI_ERROR (Status)) {

+    goto UndiErrorDeleteDevicePath;

+  }

+

+  Len = ((pxe_31->IFcnt|pxe_31->IFcntExt << 8)* sizeof (UndiDataPointer->NII_entry)) + sizeof (UndiDataPointer);

+  Status = gBS->AllocatePool (EfiRuntimeServicesData, Len, (VOID **) &UndiDataPointer);

+

+  if (EFI_ERROR (Status)) {

+    goto UndiErrorAllocDataPointer;

+  }

+

+  //

+  // Open For Child Device

+  //

+  Status = gBS->OpenProtocol (

+                  Controller,

+                  &gEfiPciIoProtocolGuid,

+                  (VOID **) &PciIoFncs,

+                  This->DriverBindingHandle,

+                  UNDI32Device->DeviceHandle,

+                  EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER

+                  );

+

+  return EFI_SUCCESS;

+UndiErrorAllocDataPointer:

+  gBS->UninstallMultipleProtocolInterfaces (

+                  &UNDI32Device->DeviceHandle,

+                  &gEfiNetworkInterfaceIdentifierProtocolGuid_31,

+                  &UNDI32Device->NIIProtocol_31,

+                  &gEfiDevicePathProtocolGuid,

+                  UNDI32Device->Undi32DevPath,

+                  NULL

+                  );

+

+UndiErrorDeleteDevicePath:

+  UNDI32DeviceList[UNDI32Device->NIIProtocol_31.IfNum] = NULL;

+  gBS->FreePool (UNDI32Device->Undi32DevPath);

+

+UndiErrorDeletePxe:

+  PxeUpdate (NULL, pxe_31);

+  if (TmpPxePointer != NULL) {

+    gBS->FreePool (TmpPxePointer);

+

+  }

+

+UndiErrorDeleteDevice:

+  if (PciAttributesSaved) {

+    //

+    // Restore original PCI attributes

+    //

+    PciIoFncs->Attributes (

+                    PciIoFncs,

+                    EfiPciIoAttributeOperationSet,

+                    UNDI32Device->NicInfo.OriginalPciAttributes,

+                    NULL

+                    );

+  }

+

+  gBS->FreePool (UNDI32Device);

+

+UndiError:

+  gBS->CloseProtocol (

+        Controller,

+        &gEfiDevicePathProtocolGuid,

+        This->DriverBindingHandle,

+        Controller

+        );

+

+  gBS->CloseProtocol (

+        Controller,

+        &gEfiPciIoProtocolGuid,

+        This->DriverBindingHandle,

+        Controller

+        );

+

+  return Status;

+}

+

+

+/**

+  Stop this driver on Controller by removing NetworkInterfaceIdentifier protocol and

+  closing the DevicePath and PciIo protocols on Controller.

+

+  @param  This                 Protocol instance pointer.

+  @param  Controller           Handle of device to stop driver on.

+  @param  NumberOfChildren     How many children need to be stopped.

+  @param  ChildHandleBuffer    Not used.

+

+  @retval EFI_SUCCESS          This driver is removed Controller.

+  @retval other                This driver was not removed from this device.

+

+**/

+// TODO:    EFI_DEVICE_ERROR - add return value to function comment

+EFI_STATUS

+EFIAPI

+UndiDriverStop (

+  IN  EFI_DRIVER_BINDING_PROTOCOL    *This,

+  IN  EFI_HANDLE                     Controller,

+  IN  UINTN                          NumberOfChildren,

+  IN  EFI_HANDLE                     *ChildHandleBuffer

+  )

+{

+  EFI_STATUS                                Status;

+  BOOLEAN                                   AllChildrenStopped;

+  UINTN                                     Index;

+  UNDI32_DEV                                *UNDI32Device;

+  EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL *NIIProtocol;

+

+  //

+  // Complete all outstanding transactions to Controller.

+  // Don't allow any new transaction to Controller to be started.

+  //

+  if (NumberOfChildren == 0) {

+

+    //

+    // Close the bus driver

+    //

+    Status = gBS->CloseProtocol (

+                    Controller,

+                    &gEfiDevicePathProtocolGuid,

+                    This->DriverBindingHandle,

+                    Controller

+                    );

+

+    Status = gBS->CloseProtocol (

+                    Controller,

+                    &gEfiPciIoProtocolGuid,

+                    This->DriverBindingHandle,

+                    Controller

+                    );

+

+    return Status;

+  }

+

+  AllChildrenStopped = TRUE;

+

+  for (Index = 0; Index < NumberOfChildren; Index++) {

+

+    Status = gBS->OpenProtocol (

+                    ChildHandleBuffer[Index],

+                    &gEfiNetworkInterfaceIdentifierProtocolGuid_31,

+                    (VOID **) &NIIProtocol,

+                    This->DriverBindingHandle,

+                    Controller,

+                    EFI_OPEN_PROTOCOL_GET_PROTOCOL

+                    );

+    if (!EFI_ERROR (Status)) {

+

+      UNDI32Device = UNDI_DEV_FROM_THIS (NIIProtocol);

+

+      Status = gBS->CloseProtocol (

+                      Controller,

+                      &gEfiPciIoProtocolGuid,

+                      This->DriverBindingHandle,

+                      ChildHandleBuffer[Index]

+                      );

+      if (!EFI_ERROR (Status)) {

+        Status = gBS->UninstallMultipleProtocolInterfaces (

+                        ChildHandleBuffer[Index],

+                        &gEfiDevicePathProtocolGuid,

+                        UNDI32Device->Undi32DevPath,

+                        &gEfiNetworkInterfaceIdentifierProtocolGuid_31,

+                        &UNDI32Device->NIIProtocol_31,

+                        NULL

+                        );

+        if (!EFI_ERROR (Status)) {

+          //

+          // Restore original PCI attributes

+          //

+          Status = UNDI32Device->NicInfo.Io_Function->Attributes (

+                                                        UNDI32Device->NicInfo.Io_Function,

+                                                        EfiPciIoAttributeOperationSet,

+                                                        UNDI32Device->NicInfo.OriginalPciAttributes,

+                                                        NULL

+                                                        );

+

+          ASSERT_EFI_ERROR (Status);

+

+          gBS->FreePool (UNDI32Device->Undi32DevPath);

+          gBS->FreePool (UNDI32Device);

+

+        }

+      }

+    }

+

+    if (EFI_ERROR (Status)) {

+      AllChildrenStopped = FALSE;

+    }

+  }

+

+  if (!AllChildrenStopped) {

+    return EFI_DEVICE_ERROR;

+  }

+

+  return EFI_SUCCESS;

+

+}

+

+

+/**

+  Use the EFI boot services to produce a pause. This is also the routine which

+  gets replaced during RunTime by the O/S in the NIC_DATA_INSTANCE so it can

+  do it's own pause.

+

+  @param  UnqId                Runtime O/S routine might use this, this temp

+                               routine does not use it

+  @param  MicroSeconds         Determines the length of pause.

+

+  @return none

+

+**/

+VOID

+TmpDelay (

+  IN UINT64 UnqId,

+  IN UINTN  MicroSeconds

+  )

+{

+  gBS->Stall ((UINT32) MicroSeconds);

+}

+

+

+/**

+  Use the PCI IO abstraction to issue memory or I/O reads and writes.  This is also the routine which

+  gets replaced during RunTime by the O/S in the NIC_DATA_INSTANCE so it can do it's own I/O abstractions.

+

+  @param  UnqId                Runtime O/S routine may use this field, this temp

+                               routine does not.

+  @param  ReadWrite            Determine if it is an I/O or Memory Read/Write

+                               Operation.

+  @param  Len                  Determines the width of the data operation.

+  @param  Port                 What port to Read/Write from.

+  @param  BuffAddr             Address to read to or write from.

+

+  @return none

+

+**/

+VOID

+TmpMemIo (

+  IN UINT64 UnqId,

+  IN UINT8  ReadWrite,

+  IN UINT8  Len,

+  IN UINT64 Port,

+  IN UINT64 BuffAddr

+  )

+{

+  EFI_PCI_IO_PROTOCOL_WIDTH Width;

+  NIC_DATA_INSTANCE         *AdapterInfo;

+

+  Width       = (EFI_PCI_IO_PROTOCOL_WIDTH) 0;

+  AdapterInfo = (NIC_DATA_INSTANCE *) (UINTN) UnqId;

+  switch (Len) {

+  case 2:

+    Width = (EFI_PCI_IO_PROTOCOL_WIDTH) 1;

+    break;

+

+  case 4:

+    Width = (EFI_PCI_IO_PROTOCOL_WIDTH) 2;

+    break;

+

+  case 8:

+    Width = (EFI_PCI_IO_PROTOCOL_WIDTH) 3;

+    break;

+  }

+

+  switch (ReadWrite) {

+  case PXE_IO_READ:

+    AdapterInfo->Io_Function->Io.Read (

+                                  AdapterInfo->Io_Function,

+                                  Width,

+                                  1,

+                                  Port,

+                                  1,

+                                  (VOID *) (UINTN) (BuffAddr)

+                                  );

+    break;

+

+  case PXE_IO_WRITE:

+    AdapterInfo->Io_Function->Io.Write (

+                                  AdapterInfo->Io_Function,

+                                  Width,

+                                  1,

+                                  Port,

+                                  1,

+                                  (VOID *) (UINTN) (BuffAddr)

+                                  );

+    break;

+

+  case PXE_MEM_READ:

+    AdapterInfo->Io_Function->Mem.Read (

+                                    AdapterInfo->Io_Function,

+                                    Width,

+                                    0,

+                                    Port,

+                                    1,

+                                    (VOID *) (UINTN) (BuffAddr)

+                                    );

+    break;

+

+  case PXE_MEM_WRITE:

+    AdapterInfo->Io_Function->Mem.Write (

+                                    AdapterInfo->Io_Function,

+                                    Width,

+                                    0,

+                                    Port,

+                                    1,

+                                    (VOID *) (UINTN) (BuffAddr)

+                                    );

+    break;

+  }

+

+  return ;

+}

+

+

+/**

+  Using the NIC data structure information, read the EEPROM to get the MAC address and then allocate space

+  for a new devicepath (**DevPtr) which will contain the original device path the NIC was found on (*BaseDevPtr)

+  and an added MAC node.

+

+  @param  DevPtr               Pointer which will point to the newly created device

+                               path with the MAC node attached.

+  @param  BaseDevPtr           Pointer to the device path which the UNDI device

+                               driver is latching on to.

+  @param  AdapterInfo          Pointer to the NIC data structure information which

+                               the UNDI driver is layering on..

+

+  @retval EFI_SUCCESS          A MAC address was successfully appended to the Base

+                               Device Path.

+  @retval other                Not enough resources available to create new Device

+                               Path node.

+

+**/

+EFI_STATUS

+AppendMac2DevPath (

+  IN OUT  EFI_DEVICE_PATH_PROTOCOL **DevPtr,

+  IN      EFI_DEVICE_PATH_PROTOCOL *BaseDevPtr,

+  IN      NIC_DATA_INSTANCE        *AdapterInfo

+  )

+{

+  EFI_MAC_ADDRESS           MACAddress;

+  PCI_CONFIG_HEADER         *CfgHdr;

+  INT32                     Val;

+  INT32                     Index;

+  INT32                     Index2;

+  UINT8                     AddrLen;

+  MAC_ADDR_DEVICE_PATH      MacAddrNode;

+  EFI_DEVICE_PATH_PROTOCOL  *EndNode;

+  UINT8                     *DevicePtr;

+  UINT16                    TotalPathLen;

+  UINT16                    BasePathLen;

+  EFI_STATUS                Status;

+

+  //

+  // set the environment ready (similar to UNDI_Start call) so that we can

+  // execute the other UNDI_ calls to get the mac address

+  // we are using undi 3.1 style

+  //

+  AdapterInfo->Delay      = TmpDelay;

+  AdapterInfo->Virt2Phys  = (VOID *) 0;

+  AdapterInfo->Block      = (VOID *) 0;

+  AdapterInfo->Map_Mem    = (VOID *) 0;

+  AdapterInfo->UnMap_Mem  = (VOID *) 0;

+  AdapterInfo->Sync_Mem   = (VOID *) 0;

+  AdapterInfo->Mem_Io     = TmpMemIo;

+  //

+  // these tmp call-backs follow 3.1 undi style

+  // i.e. they have the unique_id parameter.

+  //

+  AdapterInfo->VersionFlag  = 0x31;

+  AdapterInfo->Unique_ID    = (UINT64) (UINTN) AdapterInfo;

+

+  //

+  // undi init portion

+  //

+  CfgHdr              = (PCI_CONFIG_HEADER *) &(AdapterInfo->Config[0]);

+  AdapterInfo->ioaddr = 0;

+  AdapterInfo->RevID  = CfgHdr->RevID;

+

+  AddrLen             = E100bGetEepromAddrLen (AdapterInfo);

+

+  for (Index = 0, Index2 = 0; Index < 3; Index++) {

+    Val                       = E100bReadEeprom (AdapterInfo, Index, AddrLen);

+    MACAddress.Addr[Index2++] = (UINT8) Val;

+    MACAddress.Addr[Index2++] = (UINT8) (Val >> 8);

+  }

+

+  SetMem (MACAddress.Addr + Index2, sizeof (EFI_MAC_ADDRESS) - Index2, 0);

+  //for (; Index2 < sizeof (EFI_MAC_ADDRESS); Index2++) {

+  //  MACAddress.Addr[Index2] = 0;

+  //}

+  //

+  // stop undi

+  //

+  AdapterInfo->Delay  = (VOID *) 0;

+  AdapterInfo->Mem_Io = (VOID *) 0;

+

+  //

+  // fill the mac address node first

+  //

+  ZeroMem ((CHAR8 *) &MacAddrNode, sizeof MacAddrNode);

+  CopyMem (

+    (CHAR8 *) &MacAddrNode.MacAddress,

+    (CHAR8 *) &MACAddress,

+    sizeof (EFI_MAC_ADDRESS)

+    );

+

+  MacAddrNode.Header.Type       = MESSAGING_DEVICE_PATH;

+  MacAddrNode.Header.SubType    = MSG_MAC_ADDR_DP;

+  MacAddrNode.Header.Length[0]  = (UINT8) sizeof (MacAddrNode);

+  MacAddrNode.Header.Length[1]  = 0;

+

+  //

+  // find the size of the base dev path.

+  //

+  EndNode = BaseDevPtr;

+

+  while (!IsDevicePathEnd (EndNode)) {

+    EndNode = NextDevicePathNode (EndNode);

+  }

+

+  BasePathLen = (UINT16) ((UINTN) (EndNode) - (UINTN) (BaseDevPtr));

+

+  //

+  // create space for full dev path

+  //

+  TotalPathLen = (UINT16) (BasePathLen + sizeof (MacAddrNode) + sizeof (EFI_DEVICE_PATH_PROTOCOL));

+

+  Status = gBS->AllocatePool (

+                  EfiRuntimeServicesData,

+                  TotalPathLen,

+                  (VOID **) &DevicePtr

+                  );

+

+  if (Status != EFI_SUCCESS) {

+    return Status;

+  }

+  //

+  // copy the base path, mac addr and end_dev_path nodes

+  //

+  *DevPtr = (EFI_DEVICE_PATH_PROTOCOL *) DevicePtr;

+  CopyMem (DevicePtr, (CHAR8 *) BaseDevPtr, BasePathLen);

+  DevicePtr += BasePathLen;

+  CopyMem (DevicePtr, (CHAR8 *) &MacAddrNode, sizeof (MacAddrNode));

+  DevicePtr += sizeof (MacAddrNode);

+  CopyMem (DevicePtr, (CHAR8 *) EndNode, sizeof (EFI_DEVICE_PATH_PROTOCOL));

+

+  return EFI_SUCCESS;

+}

+

+

+/**

+  Install a GUID/Pointer pair into the system's configuration table.

+

+  none

+

+  @retval EFI_SUCCESS          Install a GUID/Pointer pair into the system's

+                               configuration table.

+  @retval other                Did not successfully install the GUID/Pointer pair

+                               into the configuration table.

+

+**/

+// TODO:    VOID - add argument and description to function comment

+EFI_STATUS

+InstallConfigTable (

+  IN VOID

+  )

+{

+  EFI_STATUS              Status;

+  EFI_CONFIGURATION_TABLE *CfgPtr;

+  UNDI_CONFIG_TABLE       *TmpData;

+  UINT16                  Index;

+  UNDI_CONFIG_TABLE       *UndiData;

+

+  if (pxe_31 == NULL) {

+    return EFI_SUCCESS;

+  }

+

+  if(UndiDataPointer == NULL) {

+    return EFI_SUCCESS;

+  }

+

+  UndiData = (UNDI_CONFIG_TABLE *)UndiDataPointer;

+

+  UndiData->NumberOfInterfaces  = (pxe_31->IFcnt | pxe_31->IFcntExt << 8);

+  UndiData->nextlink            = NULL;

+

+  for (Index = 0; Index < (pxe_31->IFcnt | pxe_31->IFcntExt << 8); Index++) {

+    UndiData->NII_entry[Index].NII_InterfacePointer = &UNDI32DeviceList[Index]->NIIProtocol_31;

+    UndiData->NII_entry[Index].DevicePathPointer    = UNDI32DeviceList[Index]->Undi32DevPath;

+  }

+

+  //

+  // see if there is an entry in the config table already

+  //

+  CfgPtr = gST->ConfigurationTable;

+

+  for (Index = 0; Index < gST->NumberOfTableEntries; Index++) {

+    Status = CompareGuid (

+              &CfgPtr->VendorGuid,

+              &gEfiNetworkInterfaceIdentifierProtocolGuid_31

+              );

+    if (Status != EFI_SUCCESS) {

+      break;

+    }

+

+    CfgPtr++;

+  }

+

+  if (Index < gST->NumberOfTableEntries) {

+    TmpData = (UNDI_CONFIG_TABLE *) CfgPtr->VendorTable;

+

+    //

+    // go to the last link

+    //

+    while (TmpData->nextlink != NULL) {

+      TmpData = TmpData->nextlink;

+    }

+

+    TmpData->nextlink = UndiData;

+

+    //

+    // 1st one in chain

+    //

+    UndiData = (UNDI_CONFIG_TABLE *) CfgPtr->VendorTable;

+  }

+

+  //

+  // create an entry in the configuration table for our GUID

+  //

+  Status = gBS->InstallConfigurationTable (

+                  &gEfiNetworkInterfaceIdentifierProtocolGuid_31,

+                  UndiData

+                  );

+  return Status;

+}

+

+/**

+

+**/

+EFI_STATUS

+EFIAPI

+InitializeUndi(

+  IN EFI_HANDLE           ImageHandle,

+  IN EFI_SYSTEM_TABLE     *SystemTable

+  )

+{

+  EFI_EVENT     Event;

+  EFI_STATUS    Status;

+

+  Status = EfiLibInstallDriverBindingComponentName2 (

+             ImageHandle,

+             SystemTable,

+             &gUndiDriverBinding,

+             ImageHandle,

+             &gUndiComponentName,

+             &gUndiComponentName2

+             );

+  ASSERT_EFI_ERROR (Status);

+

+  Status = gBS->CreateEventEx (

+                  EVT_NOTIFY_SIGNAL,

+                  TPL_NOTIFY,

+                  UndiNotifyExitBs,

+                  NULL,

+                  &gEfiEventExitBootServicesGuid,

+                  &Event

+                  );

+  ASSERT_EFI_ERROR (Status);

+

+  Status = gBS->CreateEventEx (

+                  EVT_NOTIFY_SIGNAL,

+                  TPL_NOTIFY,

+                  UndiNotifyVirtual,

+                  NULL,

+                  &gEfiEventVirtualAddressChangeGuid,

+                  &Event

+                  );

+  ASSERT_EFI_ERROR (Status);

+

+  return Status;

+}