]> git.proxmox.com Git - mirror_edk2.git/blobdiff - NetworkPkg/UefiPxeBcDxe/PxeBcDriver.c
1. Fix a bug in PXE driver that the PXE boot do not restart if a new boot option...
[mirror_edk2.git] / NetworkPkg / UefiPxeBcDxe / PxeBcDriver.c
index f78525546a1e0b87180a2639bb16eaa9c3e5940d..080b751cb19637541e81ef9bdec8db16c3302aaf 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
   Driver Binding functions implementationfor for UefiPxeBc Driver.\r
 \r
-  Copyright (c) 2007 - 2010, Intel Corporation. All rights reserved.<BR>\r
+  Copyright (c) 2007 - 2012, Intel Corporation. All rights reserved.<BR>\r
 \r
   This program and the accompanying materials\r
   are licensed and made available under the terms and conditions of the BSD License\r
@@ -25,7 +25,6 @@ EFI_DRIVER_BINDING_PROTOCOL gPxeBcDriverBinding = {
   NULL\r
 };\r
 \r
-\r
 /**\r
   Get the Nic handle using any child handle in the IPv4 stack.\r
 \r
@@ -226,11 +225,11 @@ PxeBcDestroyIp4Children (
 \r
   if (Private->Ip4Nic != NULL) {\r
     //\r
-    // Close PxeBc from the parent Nic handle and destroy the virtual handle.\r
+    // Close PxeBcPrivate from the parent Nic handle and destroy the virtual handle.\r
     //\r
     gBS->CloseProtocol (\r
            Private->Controller,\r
-           &gEfiPxeBaseCodeProtocolGuid,\r
+           &gEfiCallerIdGuid,\r
            This->DriverBindingHandle,\r
            Private->Ip4Nic->Controller\r
            );\r
@@ -241,8 +240,28 @@ PxeBcDestroyIp4Children (
            Private->Ip4Nic->DevicePath,\r
            &gEfiLoadFileProtocolGuid,\r
            &Private->Ip4Nic->LoadFile,\r
+           &gEfiPxeBaseCodeProtocolGuid,\r
+           &Private->PxeBc,\r
            NULL\r
            );\r
+\r
+    if (Private->Snp != NULL) { \r
+      //\r
+      // Close SNP from the child virtual handle\r
+      //\r
+      gBS->CloseProtocol (\r
+             Private->Ip4Nic->Controller,\r
+             &gEfiSimpleNetworkProtocolGuid,\r
+             This->DriverBindingHandle,\r
+             Private->Ip4Nic->Controller\r
+             );\r
+             \r
+      gBS->UninstallProtocolInterface (\r
+             Private->Ip4Nic->Controller,\r
+             &gEfiSimpleNetworkProtocolGuid,\r
+             Private->Snp\r
+             );\r
+    }\r
     FreePool (Private->Ip4Nic);\r
   }\r
 \r
@@ -366,22 +385,41 @@ PxeBcDestroyIp6Children (
 \r
   if (Private->Ip6Nic != NULL) {\r
     //\r
-    // Close PxeBc from the parent Nic handle and destroy the virtual handle.\r
+    // Close PxeBcPrivate from the parent Nic handle and destroy the virtual handle.\r
     //\r
     gBS->CloseProtocol (\r
            Private->Controller,\r
-           &gEfiPxeBaseCodeProtocolGuid,\r
+           &gEfiCallerIdGuid,\r
            This->DriverBindingHandle,\r
            Private->Ip6Nic->Controller\r
            );\r
+\r
     gBS->UninstallMultipleProtocolInterfaces (\r
            Private->Ip6Nic->Controller,\r
            &gEfiDevicePathProtocolGuid,\r
            Private->Ip6Nic->DevicePath,\r
            &gEfiLoadFileProtocolGuid,\r
            &Private->Ip6Nic->LoadFile,\r
+           &gEfiPxeBaseCodeProtocolGuid,\r
+           &Private->PxeBc,\r
            NULL\r
            );\r
+    if (Private->Snp != NULL) {\r
+      //\r
+      // Close SNP from the child virtual handle\r
+      //\r
+      gBS->CloseProtocol (\r
+             Private->Ip6Nic->Controller,\r
+             &gEfiSimpleNetworkProtocolGuid,\r
+             This->DriverBindingHandle,\r
+             Private->Ip6Nic->Controller\r
+             );\r
+      gBS->UninstallProtocolInterface (\r
+             Private->Ip6Nic->Controller,\r
+             &gEfiSimpleNetworkProtocolGuid,\r
+             Private->Snp\r
+             );\r
+    }\r
     FreePool (Private->Ip6Nic);\r
   }\r
 \r
@@ -415,11 +453,12 @@ PxeBcCreateIp4Children (
 {\r
   EFI_STATUS                      Status;\r
   IPv4_DEVICE_PATH                Ip4Node;\r
-  EFI_PXE_BASE_CODE_PROTOCOL      *PxeBc;\r
   EFI_PXE_BASE_CODE_MODE          *Mode;\r
   EFI_UDP4_CONFIG_DATA            *Udp4CfgData;\r
   EFI_IP4_CONFIG_DATA             *Ip4CfgData;\r
   EFI_IP4_MODE_DATA               Ip4ModeData;\r
+  PXEBC_PRIVATE_PROTOCOL          *Id;\r
+  EFI_SIMPLE_NETWORK_PROTOCOL     *Snp;\r
 \r
   if (Private->Ip4Nic != NULL) {\r
     //\r
@@ -629,20 +668,54 @@ PxeBcCreateIp4Children (
                   Private->Ip4Nic->DevicePath,\r
                   &gEfiLoadFileProtocolGuid,\r
                   &Private->Ip4Nic->LoadFile,\r
+                  &gEfiPxeBaseCodeProtocolGuid,\r
+                  &Private->PxeBc,\r
                   NULL\r
                   );\r
   if (EFI_ERROR (Status)) {\r
     goto ON_ERROR;\r
   }\r
 \r
+  if (Private->Snp != NULL) {\r
+    //\r
+    // Install SNP protocol on purpose is for some OS loader backward\r
+    // compatibility consideration.\r
+    //\r
+    Status = gBS->InstallProtocolInterface (\r
+                    &Private->Ip4Nic->Controller,\r
+                    &gEfiSimpleNetworkProtocolGuid,\r
+                    EFI_NATIVE_INTERFACE,\r
+                    Private->Snp\r
+                    );\r
+    if (EFI_ERROR (Status)) {\r
+      goto ON_ERROR;\r
+    }\r
+\r
+    //\r
+    // Open SNP on the child handle BY_DRIVER. It will prevent any additionally \r
+    // layering to perform the experiment.\r
+    //\r
+    Status = gBS->OpenProtocol (\r
+                    Private->Ip4Nic->Controller,\r
+                    &gEfiSimpleNetworkProtocolGuid,\r
+                    (VOID **) &Snp,\r
+                    This->DriverBindingHandle,\r
+                    Private->Ip4Nic->Controller,\r
+                    EFI_OPEN_PROTOCOL_BY_DRIVER\r
+                    );\r
+    if (EFI_ERROR (Status)) {\r
+      goto ON_ERROR;\r
+    }\r
+  }\r
+\r
   //\r
-  // Open PxeBaseCode protocol by child to setup a parent-child relationship between\r
+  // Open PxeBaseCodePrivate protocol by child to setup a parent-child relationship between\r
   // real NIC handle and the virtual IPv4 NIC handle.\r
   //\r
   Status = gBS->OpenProtocol (\r
                   ControllerHandle,\r
-                  &gEfiPxeBaseCodeProtocolGuid,\r
-                  (VOID **) &PxeBc,\r
+                  &gEfiCallerIdGuid,\r
+                  (VOID **) &Id,\r
                   This->DriverBindingHandle,\r
                   Private->Ip4Nic->Controller,\r
                   EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
@@ -654,11 +727,11 @@ PxeBcCreateIp4Children (
   //\r
   // Set default configure data for Udp4Read and Ip4 instance.\r
   //\r
-  Mode                            = PxeBc->Mode;\r
+  Mode                            = Private->PxeBc.Mode;\r
   Udp4CfgData                     = &Private->Udp4CfgData;\r
   Ip4CfgData                      = &Private->Ip4CfgData;\r
 \r
-  Udp4CfgData->AcceptBroadcast    = TRUE;\r
+  Udp4CfgData->AcceptBroadcast    = FALSE;\r
   Udp4CfgData->AcceptAnyPort      = TRUE;\r
   Udp4CfgData->AllowDuplicatePort = TRUE;\r
   Udp4CfgData->TypeOfService      = Mode->ToS;\r
@@ -701,10 +774,12 @@ PxeBcCreateIp6Children (
 {\r
   EFI_STATUS                      Status;\r
   IPv6_DEVICE_PATH                Ip6Node;\r
-  EFI_PXE_BASE_CODE_PROTOCOL      *PxeBc;\r
   EFI_UDP6_CONFIG_DATA            *Udp6CfgData;\r
   EFI_IP6_CONFIG_DATA             *Ip6CfgData;\r
   EFI_IP6_MODE_DATA               Ip6ModeData;\r
+  PXEBC_PRIVATE_PROTOCOL          *Id;\r
+  EFI_SIMPLE_NETWORK_PROTOCOL     *Snp;\r
+  UINTN                           Index;\r
 \r
   if (Private->Ip6Nic != NULL) {\r
     //\r
@@ -747,6 +822,16 @@ PxeBcCreateIp6Children (
     goto ON_ERROR;\r
   }\r
 \r
+  //\r
+  // Generate a random IAID for the Dhcp6 assigned address.\r
+  //\r
+  Private->IaId = NET_RANDOM (NetRandomInitSeed ());\r
+  if (Private->Snp != NULL) {\r
+    for (Index = 0; Index < Private->Snp->Mode->HwAddressSize; Index++) {\r
+      Private->IaId |= (Private->Snp->Mode->CurrentAddress.Addr[Index] << ((Index << 3) & 31));\r
+    }  \r
+  }\r
+\r
   //\r
   // Create Mtftp6 child and open Mtftp6 protocol for PxeBc->Mtftp.\r
   //\r
@@ -875,7 +960,7 @@ PxeBcCreateIp6Children (
   ZeroMem (&Ip6Node, sizeof (IPv6_DEVICE_PATH));\r
   Ip6Node.Header.Type     = MESSAGING_DEVICE_PATH;\r
   Ip6Node.Header.SubType  = MSG_IPv6_DP;\r
-  Ip6Node.StaticIpAddress = FALSE;\r
+  Ip6Node.PrefixLength    = IP6_PREFIX_LENGTH;\r
 \r
   SetDevicePathNodeLength (&Ip6Node.Header, sizeof (Ip6Node));\r
 \r
@@ -902,20 +987,54 @@ PxeBcCreateIp6Children (
                   Private->Ip6Nic->DevicePath,\r
                   &gEfiLoadFileProtocolGuid,\r
                   &Private->Ip6Nic->LoadFile,\r
+                  &gEfiPxeBaseCodeProtocolGuid,\r
+                  &Private->PxeBc,\r
                   NULL\r
                   );\r
   if (EFI_ERROR (Status)) {\r
     goto ON_ERROR;\r
   }\r
+  \r
+  if (Private->Snp != NULL) {\r
+    //\r
+    // Install SNP protocol on purpose is for some OS loader backward\r
+    // compatibility consideration.\r
+    //\r
+    Status = gBS->InstallProtocolInterface (\r
+                    &Private->Ip6Nic->Controller,\r
+                    &gEfiSimpleNetworkProtocolGuid,\r
+                    EFI_NATIVE_INTERFACE,\r
+                    Private->Snp\r
+                    );\r
+    if (EFI_ERROR (Status)) {\r
+      goto ON_ERROR;\r
+    }\r
+\r
+    //\r
+    // Open SNP on the child handle BY_DRIVER. It will prevent any additionally \r
+    // layering to perform the experiment.\r
+    //\r
+    Status = gBS->OpenProtocol (\r
+                    Private->Ip6Nic->Controller,\r
+                    &gEfiSimpleNetworkProtocolGuid,\r
+                    (VOID **) &Snp,\r
+                    This->DriverBindingHandle,\r
+                    Private->Ip6Nic->Controller,\r
+                    EFI_OPEN_PROTOCOL_BY_DRIVER\r
+                    );\r
+    if (EFI_ERROR (Status)) {\r
+      goto ON_ERROR;\r
+    }\r
+  }\r
 \r
   //\r
-  // Open PxeBaseCode protocol by child to setup a parent-child relationship between\r
+  // Open PxeBaseCodePrivate protocol by child to setup a parent-child relationship between\r
   // real NIC handle and the virtual IPv6 NIC handle.\r
   //\r
   Status = gBS->OpenProtocol (\r
                   ControllerHandle,\r
-                  &gEfiPxeBaseCodeProtocolGuid,\r
-                  (VOID **) &PxeBc,\r
+                  &gEfiCallerIdGuid,\r
+                  (VOID **) &Id,\r
                   This->DriverBindingHandle,\r
                   Private->Ip6Nic->Controller,\r
                   EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
@@ -1091,15 +1210,15 @@ PxeBcDriverBindingStart (
   )\r
 {\r
   PXEBC_PRIVATE_DATA              *Private;\r
-  EFI_PXE_BASE_CODE_PROTOCOL      *PxeBc;\r
   EFI_STATUS                      Status;\r
   EFI_STATUS                      Ip4Status;\r
   EFI_STATUS                      Ip6Status;\r
+  PXEBC_PRIVATE_PROTOCOL          *Id;\r
 \r
   Status = gBS->OpenProtocol (\r
                   ControllerHandle,\r
-                  &gEfiPxeBaseCodeProtocolGuid,\r
-                  (VOID **) &PxeBc,\r
+                  &gEfiCallerIdGuid,\r
+                  (VOID **) &Id,\r
                   This->DriverBindingHandle,\r
                   ControllerHandle,\r
                   EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
@@ -1108,7 +1227,7 @@ PxeBcDriverBindingStart (
     //\r
     // Skip the initialization if the driver has been started already.\r
     //\r
-    Private = PXEBC_PRIVATE_DATA_FROM_PXEBC (PxeBc);\r
+    Private = PXEBC_PRIVATE_DATA_FROM_ID (Id);\r
   } else {\r
     //\r
     // If the driver has not been started yet, it should do initialization.\r
@@ -1165,17 +1284,25 @@ PxeBcDriverBindingStart (
     }\r
 \r
     //\r
-    // Install PxeBaseCode protocol onto the real NIC handler.\r
+    // Install PxeBaseCodePrivate protocol onto the real NIC handler.\r
+    // PxeBaseCodePrivate protocol is only used to keep the relationship between \r
+    // NIC handle and virtual child handles.\r
+    // gEfiCallerIdGuid will be used as its protocol guid.\r
     //\r
     Status = gBS->InstallProtocolInterface (\r
                     &ControllerHandle,\r
-                    &gEfiPxeBaseCodeProtocolGuid,\r
+                    &gEfiCallerIdGuid,\r
                     EFI_NATIVE_INTERFACE,\r
-                    &Private->PxeBc\r
+                    &Private->Id\r
                     );\r
     if (EFI_ERROR (Status)) {\r
       goto ON_ERROR;\r
     }\r
+\r
+    //\r
+    // Try to locate SNP protocol.\r
+    //\r
+    NetLibGetSnpHandle(ControllerHandle, &Private->Snp);    \r
   }\r
 \r
   //\r
@@ -1201,8 +1328,8 @@ PxeBcDriverBindingStart (
 ON_ERROR:\r
   gBS->UninstallProtocolInterface (\r
          ControllerHandle,\r
-         &gEfiPxeBaseCodeProtocolGuid,\r
-         &Private->PxeBc\r
+         &gEfiCallerIdGuid,\r
+         &Private->Id\r
          );\r
   PxeBcDestroyIp4Children (This, Private);\r
   PxeBcDestroyIp6Children (This, Private);\r
@@ -1242,17 +1369,17 @@ PxeBcDriverBindingStop (
 {\r
   PXEBC_PRIVATE_DATA              *Private;\r
   PXEBC_VIRTUAL_NIC               *VirtualNic;\r
-  EFI_PXE_BASE_CODE_PROTOCOL      *PxeBc;\r
   EFI_LOAD_FILE_PROTOCOL          *LoadFile;\r
   EFI_STATUS                      Status;\r
   EFI_HANDLE                      NicHandle;\r
   BOOLEAN                         IsIpv6;\r
+  PXEBC_PRIVATE_PROTOCOL          *Id;\r
 \r
   Private    = NULL;\r
   NicHandle  = NULL;\r
   VirtualNic = NULL;\r
   LoadFile   = NULL;\r
-  PxeBc      = NULL;\r
+  Id         = NULL;\r
   IsIpv6     = FALSE;\r
 \r
   Status = gBS->OpenProtocol (\r
@@ -1278,12 +1405,12 @@ PxeBcDriverBindingStop (
     }\r
 \r
     //\r
-    // Try to retrieve the private data by PxeBc protocol.\r
+    // Try to retrieve the private data by PxeBcPrivate protocol.\r
     //\r
     Status = gBS->OpenProtocol (\r
                     NicHandle,\r
-                    &gEfiPxeBaseCodeProtocolGuid,\r
-                    (VOID **) &PxeBc,\r
+                    &gEfiCallerIdGuid,\r
+                    (VOID **) &Id,\r
                     This->DriverBindingHandle,\r
                     ControllerHandle,\r
                     EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
@@ -1291,7 +1418,7 @@ PxeBcDriverBindingStop (
     if (EFI_ERROR (Status)) {\r
       return Status;\r
     }\r
-    Private = PXEBC_PRIVATE_DATA_FROM_PXEBC (PxeBc);\r
+    Private = PXEBC_PRIVATE_DATA_FROM_ID (Id);\r
 \r
   } else {\r
     //\r
@@ -1318,6 +1445,15 @@ PxeBcDriverBindingStop (
     }\r
   }\r
 \r
+  //\r
+  // Stop functionality of PXE Base Code protocol\r
+  //\r
+  Status = Private->PxeBc.Stop (&Private->PxeBc);\r
+  if (Status != EFI_SUCCESS && Status != EFI_NOT_STARTED) {\r
+    return Status;\r
+  }\r
+\r
+\r
   if (Private->Ip4Nic != NULL && !IsIpv6) {\r
     PxeBcDestroyIp4Children (This, Private);\r
   }\r
@@ -1329,8 +1465,8 @@ PxeBcDriverBindingStop (
   if (Private->Ip4Nic == NULL && Private->Ip6Nic == NULL) {\r
     gBS->UninstallProtocolInterface (\r
            NicHandle,\r
-           &gEfiPxeBaseCodeProtocolGuid,\r
-           &Private->PxeBc\r
+           &gEfiCallerIdGuid,\r
+           &Private->Id\r
            );\r
     FreePool (Private);\r
   }\r