git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@5377 6f19259b-4bc3-4df7-8a09-765794883524
		
			
				
	
	
		
			1056 lines
		
	
	
		
			30 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			1056 lines
		
	
	
		
			30 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/** @file
 | 
						|
  Initialization functions for EFI UNDI32 driver.
 | 
						|
 | 
						|
Copyright (c) 2006 - 2008, Intel Corporation
 | 
						|
All rights reserved. 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];
 | 
						|
NII_TABLE               *UndiDataPointer = NULL;
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
  When address mapping changes to virtual this should make the appropriate
 | 
						|
  address conversions.
 | 
						|
 | 
						|
  (Standard Event handler)
 | 
						|
 | 
						|
  @return None
 | 
						|
 | 
						|
**/
 | 
						|
// TODO:    Context - add argument and description to function comment
 | 
						|
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; 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
 | 
						|
 | 
						|
**/
 | 
						|
// TODO:    Context - add argument and description to function comment
 | 
						|
VOID
 | 
						|
EFIAPI
 | 
						|
UndiNotifyExitBs (
 | 
						|
  EFI_EVENT Event,
 | 
						|
  VOID      *Context
 | 
						|
  )
 | 
						|
{
 | 
						|
  InstallConfigTable ();
 | 
						|
}
 | 
						|
//
 | 
						|
// UNDI Class Driver Global Variables
 | 
						|
//
 | 
						|
EFI_DRIVER_BINDING_PROTOCOL  gUndiDriverBinding = {
 | 
						|
  UndiDriverSupported,
 | 
						|
  UndiDriverStart,
 | 
						|
  UndiDriverStop,
 | 
						|
  0xa,
 | 
						|
  NULL,
 | 
						|
  NULL
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
  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;
 | 
						|
 | 
						|
  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 * sizeof (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;
 | 
						|
  EFI_PCI_IO_PROTOCOL                       *PciIo;
 | 
						|
 | 
						|
  //
 | 
						|
  // 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);
 | 
						|
 | 
						|
      //
 | 
						|
      // Restore original PCI attributes
 | 
						|
      //
 | 
						|
      Status = UNDI32Device->NicInfo.Io_Function->Attributes (
 | 
						|
                            UNDI32Device->NicInfo.Io_Function,
 | 
						|
                            EfiPciIoAttributeOperationSet,
 | 
						|
                            UNDI32Device->NicInfo.OriginalPciAttributes,
 | 
						|
                            NULL
 | 
						|
                            );
 | 
						|
      ASSERT_EFI_ERROR (Status);
 | 
						|
 | 
						|
      Status = gBS->CloseProtocol (
 | 
						|
                      Controller,
 | 
						|
                      &gEfiPciIoProtocolGuid,
 | 
						|
                      This->DriverBindingHandle,
 | 
						|
                      ChildHandleBuffer[Index]
 | 
						|
                      );
 | 
						|
 | 
						|
      Status = gBS->UninstallMultipleProtocolInterfaces (
 | 
						|
                      ChildHandleBuffer[Index],
 | 
						|
                      &gEfiDevicePathProtocolGuid,
 | 
						|
                      UNDI32Device->Undi32DevPath,
 | 
						|
                      &gEfiNetworkInterfaceIdentifierProtocolGuid_31,
 | 
						|
                      &UNDI32Device->NIIProtocol_31,
 | 
						|
                      NULL
 | 
						|
                      );
 | 
						|
 | 
						|
      if (EFI_ERROR (Status)) {
 | 
						|
        gBS->OpenProtocol (
 | 
						|
              Controller,
 | 
						|
              &gEfiPciIoProtocolGuid,
 | 
						|
              (VOID **) &PciIo,
 | 
						|
              This->DriverBindingHandle,
 | 
						|
              ChildHandleBuffer[Index],
 | 
						|
              EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
 | 
						|
              );
 | 
						|
      } else {
 | 
						|
        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]  = 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;
 | 
						|
  NII_TABLE               *TmpData;
 | 
						|
  UINT16                  Index;
 | 
						|
  NII_TABLE               *UndiData;
 | 
						|
 | 
						|
  if (pxe_31 == NULL) {
 | 
						|
    return EFI_SUCCESS;
 | 
						|
  }
 | 
						|
 | 
						|
  if(UndiDataPointer == NULL) {
 | 
						|
    return EFI_SUCCESS;
 | 
						|
  }
 | 
						|
 | 
						|
  UndiData = (NII_TABLE *)UndiDataPointer;
 | 
						|
 | 
						|
  UndiData->NumEntries  = pxe_31->IFcnt;
 | 
						|
  UndiData->NextLink    = NULL;
 | 
						|
 | 
						|
  for (Index = 0; Index < pxe_31->IFcnt; Index++) {
 | 
						|
    UndiData->NiiEntry[Index].InterfacePointer  = &UNDI32DeviceList[Index]->NIIProtocol_31;
 | 
						|
    UndiData->NiiEntry[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 = (NII_TABLE *) CfgPtr->VendorTable;
 | 
						|
 | 
						|
    //
 | 
						|
    // go to the last link
 | 
						|
    //
 | 
						|
    while (TmpData->NextLink != NULL) {
 | 
						|
      TmpData = TmpData->NextLink;
 | 
						|
    }
 | 
						|
 | 
						|
    TmpData->NextLink = UndiData;
 | 
						|
 | 
						|
    //
 | 
						|
    // 1st one in chain
 | 
						|
    //
 | 
						|
    UndiData = (NII_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 = EfiLibInstallDriverBinding (
 | 
						|
             ImageHandle,
 | 
						|
             SystemTable,
 | 
						|
             &gUndiDriverBinding,
 | 
						|
             ImageHandle
 | 
						|
             );
 | 
						|
  ASSERT_EFI_ERROR (Status);
 | 
						|
 | 
						|
  Status = gBS->CreateEvent (
 | 
						|
                  EVT_SIGNAL_EXIT_BOOT_SERVICES,
 | 
						|
                  TPL_NOTIFY,
 | 
						|
                  UndiNotifyExitBs,
 | 
						|
                  NULL,
 | 
						|
                  &Event
 | 
						|
                  );
 | 
						|
  ASSERT_EFI_ERROR (Status);
 | 
						|
 | 
						|
  Status = gBS->CreateEvent (
 | 
						|
                  EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE,
 | 
						|
                  TPL_NOTIFY,
 | 
						|
                  UndiNotifyVirtual,
 | 
						|
                  NULL,
 | 
						|
                  &Event
 | 
						|
                  );
 | 
						|
  ASSERT_EFI_ERROR (Status);
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 |