Fixed potential issues to release resources when error occurs.
[mirror_edk2.git] / MdeModulePkg / Bus / Pci / UndiRuntimeDxe / Init.c
index 8315bc4..413ef32 100644 (file)
@@ -1,13 +1,13 @@
 /*++\r
 \r
-Copyright (c) 2006, Intel Corporation                                                         \r
-All rights reserved. This program and the accompanying materials                          \r
-are licensed and made available under the terms and conditions of the BSD License         \r
-which accompanies this distribution.  The full text of the license may be found at        \r
-http://opensource.org/licenses/bsd-license.php                                            \r
-                                                                                          \r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     \r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             \r
+Copyright (c) 2006 - 2007, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
 \r
 Module Name:\r
 \r
@@ -22,15 +22,14 @@ Revision History
 --*/\r
 \r
 #include "Undi32.h"\r
-\r
+#include <Library/BaseLib.h>\r
 //\r
 // Global Variables\r
 //\r
-PXE_SW_UNDI             *pxe = 0;     // 3.0 entry point\r
-PXE_SW_UNDI             *pxe_31 = 0;  // 3.1 entry\r
-UNDI32_DEV              *UNDI32DeviceList[MAX_NIC_INTERFACES];\r
 \r
-NII_TABLE               *UnidiDataPointer=NULL;    \r
+PXE_SW_UNDI             *pxe_31 = NULL;  // 3.1 entry\r
+UNDI32_DEV              *UNDI32DeviceList[MAX_NIC_INTERFACES];\r
+NII_TABLE               *UndiDataPointer = NULL;\r
 \r
 VOID\r
 EFIAPI\r
@@ -103,7 +102,7 @@ UndiNotifyExitBs (
 \r
 Routine Description:\r
 \r
-  When EFI is shuting down the boot services, we need to install a \r
+  When EFI is shuting down the boot services, we need to install a\r
   configuration table for UNDI to work at runtime!\r
 \r
 Arguments:\r
@@ -152,15 +151,15 @@ Routine Description:
 Arguments:\r
 \r
   This                - Protocol instance pointer.\r
-  \r
+\r
   Controller          - Handle of device to test.\r
-  \r
+\r
   RemainingDevicePath - Not used.\r
 \r
 Returns:\r
 \r
   EFI_SUCCESS         - This driver supports this device.\r
-  \r
+\r
   other               - This driver does not support this device.\r
 \r
 --*/\r
@@ -266,15 +265,15 @@ Routine Description:
 Arguments:\r
 \r
   This                - Protocol instance pointer.\r
-  \r
+\r
   Controller          - Handle of device to work with.\r
-  \r
+\r
   RemainingDevicePath - Not used, always produce all possible children.\r
 \r
 Returns:\r
 \r
   EFI_SUCCESS         - This driver is added to Controller.\r
-  \r
+\r
   other               - This driver does not support this device.\r
 \r
 --*/\r
@@ -286,7 +285,9 @@ Returns:
   UINT16                    NewCommand;\r
   UINT8                     *TmpPxePointer;\r
   EFI_PCI_IO_PROTOCOL       *PciIoFncs;\r
-  UINTN                     Len;   \r
+  UINTN                     Len;\r
+  UINT64                    Supports;\r
+  BOOLEAN                   PciAttributesSaved;\r
 \r
   Status = gBS->OpenProtocol (\r
                   Controller,\r
@@ -321,6 +322,8 @@ Returns:
     return Status;\r
   }\r
 \r
+  PciAttributesSaved = FALSE;\r
+\r
   Status = gBS->AllocatePool (\r
                   EfiRuntimeServicesData,\r
                   sizeof (UNDI32_DEV),\r
@@ -333,6 +336,21 @@ Returns:
 \r
   ZeroMem ((CHAR8 *) UNDI32Device, sizeof (UNDI32_DEV));\r
 \r
+  //\r
+  // Get original PCI attributes\r
+  //\r
+  Status = PciIoFncs->Attributes (\r
+                    PciIoFncs,\r
+                    EfiPciIoAttributeOperationGet,\r
+                    0,\r
+                    &UNDI32Device->NicInfo.OriginalPciAttributes\r
+                    );\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    goto UndiErrorDeleteDevice;\r
+  }\r
+  PciAttributesSaved = TRUE;\r
+\r
   //\r
   // allocate and initialize both (old and new) the !pxe structures here,\r
   // there should only be one copy of each of these structure for any number\r
@@ -366,24 +384,27 @@ Returns:
     } else {\r
       pxe_31 = (PXE_SW_UNDI *) TmpPxePointer;\r
     }\r
-    //\r
-    // assuming that the sizeof pxe_31 is a 16 byte multiple\r
-    //\r
-    pxe = (PXE_SW_UNDI *) ((CHAR8 *) (pxe_31) + sizeof (PXE_SW_UNDI));\r
 \r
-    PxeStructInit (pxe, 0x30);\r
-    PxeStructInit (pxe_31, 0x31);\r
+    PxeStructInit (pxe_31);\r
   }\r
 \r
-  UNDI32Device->NIIProtocol.ID    = (UINT64) (UINTN) (pxe);\r
   UNDI32Device->NIIProtocol_31.ID = (UINT64) (UINTN) (pxe_31);\r
 \r
   Status = PciIoFncs->Attributes (\r
                         PciIoFncs,\r
-                        EfiPciIoAttributeOperationEnable,\r
-                        EFI_PCI_DEVICE_ENABLE | EFI_PCI_IO_ATTRIBUTE_MEMORY | EFI_PCI_IO_ATTRIBUTE_IO | EFI_PCI_IO_ATTRIBUTE_BUS_MASTER,\r
-                        NULL\r
+                        EfiPciIoAttributeOperationSupported,\r
+                        0,\r
+                        &Supports\r
                         );\r
+  if (!EFI_ERROR (Status)) {\r
+    Supports &= EFI_PCI_DEVICE_ENABLE;\r
+    Status = PciIoFncs->Attributes (\r
+                          PciIoFncs,\r
+                          EfiPciIoAttributeOperationEnable,\r
+                          Supports,\r
+                          NULL\r
+                          );\r
+  }\r
   //\r
   // Read all the registers from device's PCI Configuration space\r
   //\r
@@ -430,15 +451,13 @@ Returns:
   // the IfNum index for the current interface will be the total number\r
   // of interfaces initialized so far\r
   //\r
-  UNDI32Device->NIIProtocol.IfNum     = pxe->IFcnt;\r
   UNDI32Device->NIIProtocol_31.IfNum  = pxe_31->IFcnt;\r
 \r
-  PxeUpdate (&UNDI32Device->NicInfo, pxe);\r
   PxeUpdate (&UNDI32Device->NicInfo, pxe_31);\r
 \r
-  UNDI32Device->NicInfo.Io_Function                 = PciIoFncs;\r
-  UNDI32DeviceList[UNDI32Device->NIIProtocol.IfNum] = UNDI32Device;\r
-  UNDI32Device->Undi32BaseDevPath                   = UndiDevicePath;\r
+  UNDI32Device->NicInfo.Io_Function                    = PciIoFncs;\r
+  UNDI32DeviceList[UNDI32Device->NIIProtocol_31.IfNum] = UNDI32Device;\r
+  UNDI32Device->Undi32BaseDevPath                      = UndiDevicePath;\r
 \r
   Status = AppendMac2DevPath (\r
             &UNDI32Device->Undi32DevPath,\r
@@ -452,19 +471,6 @@ Returns:
 \r
   UNDI32Device->Signature                     = UNDI_DEV_SIGNATURE;\r
 \r
-  UNDI32Device->NIIProtocol.Revision          = EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL_REVISION;\r
-  UNDI32Device->NIIProtocol.Type              = EfiNetworkInterfaceUndi;\r
-  UNDI32Device->NIIProtocol.MajorVer          = PXE_ROMID_MAJORVER;\r
-  UNDI32Device->NIIProtocol.MinorVer          = PXE_ROMID_MINORVER;\r
-  UNDI32Device->NIIProtocol.ImageSize         = 0;\r
-  UNDI32Device->NIIProtocol.ImageAddr         = 0;\r
-  UNDI32Device->NIIProtocol.Ipv6Supported     = FALSE;\r
-\r
-  UNDI32Device->NIIProtocol.StringId[0]       = 'U';\r
-  UNDI32Device->NIIProtocol.StringId[1]       = 'N';\r
-  UNDI32Device->NIIProtocol.StringId[2]       = 'D';\r
-  UNDI32Device->NIIProtocol.StringId[3]       = 'I';\r
-\r
   UNDI32Device->NIIProtocol_31.Revision       = EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL_REVISION_31;\r
   UNDI32Device->NIIProtocol_31.Type           = EfiNetworkInterfaceUndi;\r
   UNDI32Device->NIIProtocol_31.MajorVer       = PXE_ROMID_MAJORVER;\r
@@ -487,8 +493,6 @@ Returns:
                   &UNDI32Device->DeviceHandle,\r
                   &gEfiNetworkInterfaceIdentifierProtocolGuid_31,\r
                   &UNDI32Device->NIIProtocol_31,\r
-                  &gEfiNetworkInterfaceIdentifierProtocolGuid,\r
-                  &UNDI32Device->NIIProtocol,\r
                   &gEfiDevicePathProtocolGuid,\r
                   UNDI32Device->Undi32DevPath,\r
                   NULL\r
@@ -499,22 +503,22 @@ Returns:
   }\r
 \r
   //\r
-  // if the table exists, free it and alloc again, or alloc it directly \r
+  // if the table exists, free it and alloc again, or alloc it directly\r
   //\r
-  if (UnidiDataPointer != NULL) {\r
-       Status = gBS->FreePool(UnidiDataPointer);\r
+  if (UndiDataPointer != NULL) {\r
+       Status = gBS->FreePool(UndiDataPointer);\r
   }\r
   if (EFI_ERROR (Status)) {\r
     goto UndiErrorDeleteDevicePath;\r
   }\r
 \r
-  Len = (pxe_31->IFcnt * sizeof (NII_ENTRY)) + sizeof (UnidiDataPointer);\r
-  Status = gBS->AllocatePool (EfiRuntimeServicesData, Len, (VOID **) &UnidiDataPointer);\r
+  Len = (pxe_31->IFcnt * sizeof (NII_ENTRY)) + sizeof (UndiDataPointer);\r
+  Status = gBS->AllocatePool (EfiRuntimeServicesData, Len, (VOID **) &UndiDataPointer);\r
 \r
   if (EFI_ERROR (Status)) {\r
     goto UndiErrorAllocDataPointer;\r
   }\r
-  \r
+\r
   //\r
   // Open For Child Device\r
   //\r
@@ -533,19 +537,16 @@ UndiErrorAllocDataPointer:
                   &UNDI32Device->DeviceHandle,\r
                   &gEfiNetworkInterfaceIdentifierProtocolGuid_31,\r
                   &UNDI32Device->NIIProtocol_31,\r
-                  &gEfiNetworkInterfaceIdentifierProtocolGuid,\r
-                  &UNDI32Device->NIIProtocol,\r
                   &gEfiDevicePathProtocolGuid,\r
                   UNDI32Device->Undi32DevPath,\r
                   NULL\r
                   );\r
 \r
 UndiErrorDeleteDevicePath:\r
-  UNDI32DeviceList[UNDI32Device->NIIProtocol.IfNum] = NULL;\r
+  UNDI32DeviceList[UNDI32Device->NIIProtocol_31.IfNum] = NULL;\r
   gBS->FreePool (UNDI32Device->Undi32DevPath);\r
 \r
 UndiErrorDeletePxe:\r
-  PxeUpdate (NULL, pxe);\r
   PxeUpdate (NULL, pxe_31);\r
   if (TmpPxePointer != NULL) {\r
     gBS->FreePool (TmpPxePointer);\r
@@ -553,6 +554,18 @@ UndiErrorDeletePxe:
   }\r
 \r
 UndiErrorDeleteDevice:\r
+  if (PciAttributesSaved == TRUE) {\r
+    //\r
+    // Restore original PCI attributes\r
+    //\r
+    PciIoFncs->Attributes (\r
+                    PciIoFncs,\r
+                    EfiPciIoAttributeOperationSet,\r
+                    UNDI32Device->NicInfo.OriginalPciAttributes,\r
+                    NULL\r
+                    );\r
+  }\r
+\r
   gBS->FreePool (UNDI32Device);\r
 \r
 UndiError:\r
@@ -639,7 +652,7 @@ Returns:
 \r
     Status = gBS->OpenProtocol (\r
                     ChildHandleBuffer[Index],\r
-                    &gEfiNetworkInterfaceIdentifierProtocolGuid,\r
+                    &gEfiNetworkInterfaceIdentifierProtocolGuid_31,\r
                     (VOID **) &NIIProtocol,\r
                     This->DriverBindingHandle,\r
                     Controller,\r
@@ -649,6 +662,17 @@ Returns:
 \r
       UNDI32Device = UNDI_DEV_FROM_THIS (NIIProtocol);\r
 \r
+      //\r
+      // Restore original PCI attributes\r
+      //\r
+      Status = UNDI32Device->NicInfo.Io_Function->Attributes (\r
+                            UNDI32Device->NicInfo.Io_Function,\r
+                            EfiPciIoAttributeOperationSet,\r
+                            UNDI32Device->NicInfo.OriginalPciAttributes,\r
+                            NULL\r
+                            );\r
+      ASSERT_EFI_ERROR (Status);\r
+\r
       Status = gBS->CloseProtocol (\r
                       Controller,\r
                       &gEfiPciIoProtocolGuid,\r
@@ -662,8 +686,6 @@ Returns:
                       UNDI32Device->Undi32DevPath,\r
                       &gEfiNetworkInterfaceIdentifierProtocolGuid_31,\r
                       &UNDI32Device->NIIProtocol_31,\r
-                      &gEfiNetworkInterfaceIdentifierProtocolGuid,\r
-                      &UNDI32Device->NIIProtocol,\r
                       NULL\r
                       );\r
 \r
@@ -711,7 +733,7 @@ Routine Description:
 Arguments:\r
 \r
   UnqId             - Runtime O/S routine might use this, this temp routine does not use it\r
-  \r
+\r
   MicroSeconds      - Determines the length of pause.\r
 \r
 Returns:\r
@@ -741,13 +763,13 @@ Routine Description:
 Arguments:\r
 \r
   UnqId             - Runtime O/S routine may use this field, this temp routine does not.\r
-  \r
+\r
   ReadWrite         - Determine if it is an I/O or Memory Read/Write Operation.\r
-  \r
+\r
   Len               - Determines the width of the data operation.\r
-  \r
+\r
   Port              - What port to Read/Write from.\r
-  \r
+\r
   BuffAddr          - Address to read to or write from.\r
 \r
 Returns:\r
@@ -841,15 +863,15 @@ Routine Description:
 Arguments:\r
 \r
   DevPtr            - Pointer which will point to the newly created device path with the MAC node attached.\r
-  \r
+\r
   BaseDevPtr        - Pointer to the device path which the UNDI device driver is latching on to.\r
-  \r
+\r
   AdapterInfo       - Pointer to the NIC data structure information which the UNDI driver is layering on..\r
 \r
 Returns:\r
 \r
   EFI_SUCCESS       - A MAC address was successfully appended to the Base Device Path.\r
-  \r
+\r
   other             - Not enough resources available to create new Device Path node.\r
 \r
 --*/\r
@@ -981,7 +1003,7 @@ Arguments:
 Returns:\r
 \r
   EFI_SUCCESS       - Install a GUID/Pointer pair into the system's configuration table.\r
-  \r
+\r
   other             - Did not successfully install the GUID/Pointer pair into the configuration table.\r
 \r
 --*/\r
@@ -997,12 +1019,12 @@ Returns:
     return EFI_SUCCESS;\r
   }\r
 \r
-  if(UnidiDataPointer == NULL) { \r
+  if(UndiDataPointer == NULL) {\r
        return EFI_SUCCESS;\r
   }\r
-  \r
-  UndiData = (NII_TABLE *)UnidiDataPointer;  \r
-  \r
+\r
+  UndiData = (NII_TABLE *)UndiDataPointer;\r
+\r
   UndiData->NumEntries  = pxe_31->IFcnt;\r
   UndiData->NextLink    = NULL;\r
 \r
@@ -1057,12 +1079,12 @@ Returns:
 }\r
 \r
 /**\r
-  \r
+\r
   Install driver binding protocol of UNDI.\r
-  \r
-  @param[in] ImageHandle    The firmware allocated handle for the EFI image.  \r
+\r
+  @param[in] ImageHandle    The firmware allocated handle for the EFI image.\r
   @param[in] SystemTable    A pointer to the EFI System Table.\r
-  \r
+\r
   @retval EFI_SUCCESS       The entry point is executed successfully.\r
   @retval other             Some error occurs when executing this entry point.\r
 \r