Revision: 16131
          http://sourceforge.net/p/edk2/code/16131
Author:   sfu5
Date:     2014-09-18 11:44:36 +0000 (Thu, 18 Sep 2014)
Log Message:
-----------
1. Update PXE driver to support PXEv6 boot cross subnet.
2. Update IP6 driver to use previous configured prefix length if a pre-exist 
IP6 address with unspecified prefix length.
3. Add NULL check for Dhcp protocol pointer before it decline the address in 
Ip6ConfigSetStatefulAddrCallback() function.
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Fu, Siyuan <[email protected]>
Reviewed-By: Ye, Ting ([email protected])
Reviewed-By: Wu, Jiaxin <[email protected]>

Modified Paths:
--------------
    trunk/edk2/NetworkPkg/Ip6Dxe/Ip6ConfigImpl.c
    trunk/edk2/NetworkPkg/UefiPxeBcDxe/PxeBcBoot.c
    trunk/edk2/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp4.c
    trunk/edk2/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.c
    trunk/edk2/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.h
    trunk/edk2/NetworkPkg/UefiPxeBcDxe/PxeBcImpl.c
    trunk/edk2/NetworkPkg/UefiPxeBcDxe/PxeBcImpl.h

Modified: trunk/edk2/NetworkPkg/Ip6Dxe/Ip6ConfigImpl.c
===================================================================
--- trunk/edk2/NetworkPkg/Ip6Dxe/Ip6ConfigImpl.c        2014-09-18 09:02:57 UTC 
(rev 16130)
+++ trunk/edk2/NetworkPkg/Ip6Dxe/Ip6ConfigImpl.c        2014-09-18 11:44:36 UTC 
(rev 16131)
@@ -1,7 +1,7 @@
 /** @file
   The implementation of EFI IPv6 Configuration Protocol.
 
-  Copyright (c) 2009 - 2013, Intel Corporation. All rights reserved.<BR>
+  Copyright (c) 2009 - 2014, 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
@@ -1013,6 +1013,14 @@
         );
 
       //
+      // If the new address's prefix length is not specified, just use the 
previous configured
+      // prefix length for this address.
+      //
+      if (NewAddress->PrefixLength == 0) {
+        NewAddress->PrefixLength = CurrentAddrInfo->PrefixLength;
+      }
+
+      //
       // This manual address is already in use, see whether prefix length is 
changed.
       //
       if (NewAddress->PrefixLength != CurrentAddrInfo->PrefixLength) {
@@ -1594,11 +1602,13 @@
       //
       // Decline those duplicates.
       //
-      Instance->Dhcp6->Decline (
-                         Instance->Dhcp6,
-                         Instance->DeclineAddressCount,
-                         Instance->DeclineAddress
-                         );
+      if (Instance->Dhcp6 != NULL) {
+        Instance->Dhcp6->Decline (
+                           Instance->Dhcp6,
+                           Instance->DeclineAddressCount,
+                           Instance->DeclineAddress
+                           );
+      }
     }
 
     if (Instance->DeclineAddress != NULL) {

Modified: trunk/edk2/NetworkPkg/UefiPxeBcDxe/PxeBcBoot.c
===================================================================
--- trunk/edk2/NetworkPkg/UefiPxeBcDxe/PxeBcBoot.c      2014-09-18 09:02:57 UTC 
(rev 16130)
+++ trunk/edk2/NetworkPkg/UefiPxeBcDxe/PxeBcBoot.c      2014-09-18 11:44:36 UTC 
(rev 16131)
@@ -633,6 +633,14 @@
   }
 
   //
+  // Set the station address to IP layer.
+  //
+  Status = PxeBcSetIp6Address (Private);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+  
+  //
   // Parse the value of boot file size.
   //
   if (Cache6->OptList[PXEBC_DHCP6_IDX_BOOT_FILE_PARAM] != NULL) {

Modified: trunk/edk2/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp4.c
===================================================================
--- trunk/edk2/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp4.c     2014-09-18 09:02:57 UTC 
(rev 16130)
+++ trunk/edk2/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp4.c     2014-09-18 11:44:36 UTC 
(rev 16131)
@@ -512,7 +512,7 @@
   }
 
   //
-  // The offer with "yiaddr" is a proxy offer.
+  // The offer with zero "yiaddr" is a proxy offer.
   //
   if (Offer->Dhcp4.Header.YourAddr.Addr[0] == 0) {
     IsProxyOffer = TRUE;

Modified: trunk/edk2/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.c
===================================================================
--- trunk/edk2/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.c     2014-09-18 09:02:57 UTC 
(rev 16130)
+++ trunk/edk2/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.c     2014-09-18 11:44:36 UTC 
(rev 16131)
@@ -488,7 +488,7 @@
   }
 
   //
-  // The offer with assigned client address is a proxy offer.
+  // The offer with assigned client address is NOT a proxy offer.
   // An ia_na option, embeded with valid ia_addr option and a status_code of 
success.
   //
   Option = Options[PXEBC_DHCP6_IDX_IA_NA];
@@ -1235,9 +1235,128 @@
   }
 }
 
+/**
+  Check whether IP driver could route the message which will be sent to 
ServerIp address.
+  
+  This function will check the IP6 route table every 1 seconds until specified 
timeout is expired, if a valid
+  route is found in IP6 route table, the address will be filed in GatewayAddr 
and return.
 
+  @param[in]  Private             The pointer to PXEBC_PRIVATE_DATA.
+  @param[in]  TimeOutInSecond     Timeout value in seconds.
+  @param[out] GatewayAddr         Pointer to store the gateway IP address.
+
+  @retval     EFI_SUCCESS         Found a valid gateway address successfully.
+  @retval     EFI_TIMEOUT         The operation is time out.
+  @retval     Other               Unexpect error happened.
+  
+**/
+EFI_STATUS
+PxeBcCheckRouteTable (
+  IN  PXEBC_PRIVATE_DATA            *Private,
+  IN  UINTN                         TimeOutInSecond,
+  OUT EFI_IPv6_ADDRESS              *GatewayAddr
+  )
+{
+  EFI_STATUS                       Status;
+  EFI_IP6_PROTOCOL                 *Ip6;
+  EFI_IP6_MODE_DATA                Ip6ModeData;
+  UINTN                            Index;
+  EFI_EVENT                        TimeOutEvt;
+  UINTN                            RetryCount;
+  BOOLEAN                          GatewayIsFound;
+
+  ASSERT (GatewayAddr != NULL);
+  ASSERT (Private != NULL);
+
+  Ip6            = Private->Ip6;
+  GatewayIsFound = FALSE;
+  RetryCount     = 0;
+  TimeOutEvt     = NULL;
+  ZeroMem (GatewayAddr, sizeof (EFI_IPv6_ADDRESS));
+
+  while (TRUE) {
+    Status = Ip6->GetModeData (Ip6, &Ip6ModeData, NULL, NULL);
+    if (EFI_ERROR (Status)) {
+      goto ON_EXIT;
+    }
+
+    //
+    // Find out the gateway address which can route the message whcih send to 
ServerIp.
+    //
+    for (Index = 0; Index < Ip6ModeData.RouteCount; Index++) {
+      if (NetIp6IsNetEqual (&Private->ServerIp.v6, 
&Ip6ModeData.RouteTable[Index].Destination, 
Ip6ModeData.RouteTable[Index].PrefixLength)) {
+        IP6_COPY_ADDRESS (GatewayAddr, &Ip6ModeData.RouteTable[Index].Gateway);
+        GatewayIsFound = TRUE;
+        break;
+      }
+    }
+
+    if (Ip6ModeData.AddressList != NULL) {
+      FreePool (Ip6ModeData.AddressList);
+    }
+    if (Ip6ModeData.GroupTable != NULL) {
+      FreePool (Ip6ModeData.GroupTable);
+    }
+    if (Ip6ModeData.RouteTable != NULL) {
+      FreePool (Ip6ModeData.RouteTable);
+    }
+    if (Ip6ModeData.NeighborCache != NULL) {
+      FreePool (Ip6ModeData.NeighborCache);
+    }
+    if (Ip6ModeData.PrefixTable != NULL) {
+      FreePool (Ip6ModeData.PrefixTable);
+    }
+    if (Ip6ModeData.IcmpTypeList != NULL) {
+      FreePool (Ip6ModeData.IcmpTypeList);
+    }
+    
+    if (GatewayIsFound || RetryCount == TimeOutInSecond) {
+      break;
+    }
+    
+    RetryCount++;
+    
+    //
+    // Delay 1 second then recheck it again.
+    //
+    if (TimeOutEvt == NULL) {
+      Status = gBS->CreateEvent (
+                      EVT_TIMER,
+                      TPL_CALLBACK,
+                      NULL,
+                      NULL,
+                      &TimeOutEvt
+                      );
+      if (EFI_ERROR (Status)) {
+        goto ON_EXIT;
+      }
+    }
+
+    Status = gBS->SetTimer (TimeOutEvt, TimerRelative, TICKS_PER_SECOND);
+    if (EFI_ERROR (Status)) {
+      goto ON_EXIT;
+    }
+    while (EFI_ERROR (gBS->CheckEvent (TimeOutEvt))) {
+      Ip6->Poll (Ip6);
+    }
+  }
+  
+ON_EXIT:
+  if (TimeOutEvt != NULL) {
+    gBS->CloseEvent (TimeOutEvt);
+  }
+  
+  if (GatewayIsFound) {
+    Status = EFI_SUCCESS;
+  } else if (RetryCount == TimeOutInSecond) {
+    Status = EFI_TIMEOUT;
+  }
+
+  return Status; 
+}
+
 /**
-  Register the ready address by Ip6Config protocol.
+  Register the ready station address and gateway by Ip6Config protocol.
 
   @param[in]  Private             The pointer to PXEBC_PRIVATE_DATA.
   @param[in]  Address             The pointer to the ready address.
@@ -1256,6 +1375,7 @@
   EFI_IP6_CONFIG_PROTOCOL          *Ip6Cfg;
   EFI_IP6_CONFIG_POLICY            Policy;
   EFI_IP6_CONFIG_MANUAL_ADDRESS    CfgAddr;
+  EFI_IPv6_ADDRESS                 GatewayAddr;
   UINTN                            DataSize;
   EFI_EVENT                        TimeOutEvt;
   EFI_EVENT                        MappedEvt;
@@ -1273,19 +1393,19 @@
   ZeroMem (&CfgAddr, sizeof (EFI_IP6_CONFIG_MANUAL_ADDRESS));
   CopyMem (&CfgAddr.Address, Address, sizeof (EFI_IPv6_ADDRESS));
 
+  Status = Ip6->Configure (Ip6, &Private->Ip6CfgData);
+  if (EFI_ERROR (Status)) {
+    goto ON_EXIT;
+  }
+
   //
-  // Get and store the current policy of IP6 driver.
+  // Retrieve the gateway address from IP6 route table.
   //
-  Status = Ip6Cfg->GetData (
-                     Ip6Cfg,
-                     Ip6ConfigDataTypePolicy,
-                     &DataSize,
-                     &Private->Ip6Policy
-                     );
+  Status = PxeBcCheckRouteTable (Private, PXEBC_IP6_ROUTE_TABLE_TIMEOUT, 
&GatewayAddr);
   if (EFI_ERROR (Status)) {
     goto ON_EXIT;
   }
-
+  
   //
   // There is no channel between IP6 and PXE driver about address setting,
   // so it has to set the new address by Ip6ConfigProtocol manually.
@@ -1381,6 +1501,21 @@
     }
   }
 
+  //
+  // Set the default gateway address back if needed.
+  //
+  if (!NetIp6IsUnspecifiedAddr (&GatewayAddr)) {
+    Status = Ip6Cfg->SetData (
+                       Ip6Cfg,
+                       Ip6ConfigDataTypeGateway,
+                       sizeof (EFI_IPv6_ADDRESS),
+                       &GatewayAddr
+                       );
+    if (EFI_ERROR (Status)) {
+      goto ON_EXIT;
+    }
+  }
+
 ON_EXIT:
   if (MappedEvt != NULL) {
     Ip6Cfg->UnregisterDataNotify (
@@ -1396,8 +1531,102 @@
   return Status;
 }
 
+/**
+  Set the IP6 policy to Automatic.
 
+  @param[in]  Private             The pointer to PXEBC_PRIVATE_DATA.
+
+  @retval     EFI_SUCCESS         Switch the IP policy succesfully.
+  @retval     Others              Unexpect error happened.
+
+**/
+EFI_STATUS
+PxeBcSetIp6Policy (
+  IN PXEBC_PRIVATE_DATA            *Private
+  )
+{
+  EFI_IP6_CONFIG_POLICY            Policy;
+  EFI_STATUS                       Status;
+  EFI_IP6_CONFIG_PROTOCOL          *Ip6Cfg;
+  UINTN                            DataSize;
+
+  Ip6Cfg      = Private->Ip6Cfg;
+  DataSize    = sizeof (EFI_IP6_CONFIG_POLICY);
+
+  //
+  // Get and store the current policy of IP6 driver.
+  //
+  Status = Ip6Cfg->GetData (
+                     Ip6Cfg,
+                     Ip6ConfigDataTypePolicy,
+                     &DataSize,
+                     &Private->Ip6Policy
+                     );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  if (Private->Ip6Policy == Ip6ConfigPolicyManual) {
+    Policy = Ip6ConfigPolicyAutomatic;
+    Status = Ip6Cfg->SetData (
+                       Ip6Cfg,
+                       Ip6ConfigDataTypePolicy,
+                       sizeof(EFI_IP6_CONFIG_POLICY),
+                       &Policy
+                       );
+    if (EFI_ERROR (Status)) {
+      //
+      // There is no need to recover later.
+      //
+      Private->Ip6Policy = PXEBC_IP6_POLICY_MAX;
+    }
+  }
+
+  return Status;
+}
+
 /**
+  This function will register the station IP address and flush IP instance to 
start using the new IP address.
+  
+  @param[in]  Private             The pointer to PXEBC_PRIVATE_DATA.
+
+  @retval     EFI_SUCCESS         The new IP address has been configured 
successfully.
+  @retval     Others              Failed to configure the address.
+
+**/
+EFI_STATUS
+PxeBcSetIp6Address (
+  IN  PXEBC_PRIVATE_DATA              *Private
+  )
+{
+  EFI_STATUS                  Status;
+  EFI_DHCP6_PROTOCOL          *Dhcp6;
+    
+  Dhcp6 = Private->Dhcp6;
+
+  CopyMem (&Private->StationIp.v6, &Private->TmpStationIp.v6, sizeof 
(EFI_IPv6_ADDRESS));
+  CopyMem (&Private->PxeBc.Mode->StationIp.v6, &Private->StationIp.v6, sizeof 
(EFI_IPv6_ADDRESS));
+
+  Status = PxeBcRegisterIp6Address (Private, &Private->StationIp.v6);
+  if (EFI_ERROR (Status)) {
+    Dhcp6->Stop (Dhcp6);
+    return Status;
+  }
+
+  Status = PxeBcFlushStationIp (Private, &Private->StationIp, NULL);
+  if (EFI_ERROR (Status)) {
+    PxeBcUnregisterIp6Address (Private);
+    Dhcp6->Stop (Dhcp6);
+    return Status;
+  }
+
+  AsciiPrint ("\n  Station IP address is ");
+  PxeBcShowIp6Addr (&Private->StationIp.v6);
+
+  return EFI_SUCCESS;
+}
+
+/**
   EFI_DHCP6_CALLBACK is provided by the consumer of the EFI DHCPv6 Protocol 
driver
   to intercept events that occurred in the configuration process.
 
@@ -1843,36 +2072,23 @@
   }
 
   ASSERT (Mode.Ia->State == Dhcp6Bound);
-  CopyMem (&Private->StationIp.v6, &Mode.Ia->IaAddress[0].IpAddress, sizeof 
(EFI_IPv6_ADDRESS));
-  CopyMem (&PxeMode->StationIp.v6, &Private->StationIp.v6, sizeof 
(EFI_IPv6_ADDRESS));
+  //
+  // DHCP6 doesn't have an option to specify the router address on the subnet, 
the only way to get the
+  // router address in IP6 is the router discovery mechanism (the RS and RA, 
which only be handled when
+  // the IP policy is Automatic). So we just hold the station IP address here 
and leave the IP policy as
+  // Automatic, until we get the server IP address. This could let IP6 driver 
finish the router discovery 
+  // to find a valid router address.
+  //
+  CopyMem (&Private->TmpStationIp.v6, &Mode.Ia->IaAddress[0].IpAddress, sizeof 
(EFI_IPv6_ADDRESS));
 
-  Status = PxeBcRegisterIp6Address (Private, &Private->StationIp.v6);
-  if (EFI_ERROR (Status)) {
-    Dhcp6->Stop (Dhcp6);
-    return Status;
-  }
-
-  Status = PxeBcFlushStationIp (Private, &Private->StationIp, NULL);
-  if (EFI_ERROR (Status)) {
-    PxeBcUnregisterIp6Address (Private);
-    Dhcp6->Stop (Dhcp6);
-    return Status;
-  }
-
   //
   // Check the selected offer whether BINL retry is needed.
   //
   Status = PxeBcHandleDhcp6Offer (Private);
   if (EFI_ERROR (Status)) {
-    PxeBcUnregisterIp6Address (Private);
     Dhcp6->Stop (Dhcp6);
     return Status;
   }
-
-  AsciiPrint ("\n  Station IP address is ");
-
-  PxeBcShowIp6Addr (&Private->StationIp.v6);
-
+  
   return EFI_SUCCESS;
 }
-

Modified: trunk/edk2/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.h
===================================================================
--- trunk/edk2/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.h     2014-09-18 09:02:57 UTC 
(rev 16130)
+++ trunk/edk2/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.h     2014-09-18 11:44:36 UTC 
(rev 16131)
@@ -1,7 +1,7 @@
 /** @file
   Functions declaration related with DHCPv6 for UefiPxeBc Driver.
 
-  Copyright (c) 2009 - 2012, Intel Corporation. All rights reserved.<BR>
+  Copyright (c) 2009 - 2014, 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
@@ -20,6 +20,7 @@
 #define PXEBC_DHCP6_OPTION_MAX_SIZE       312
 #define PXEBC_DHCP6_PACKET_MAX_SIZE       1472
 #define PXEBC_IP6_POLICY_MAX              0xff
+#define PXEBC_IP6_ROUTE_TABLE_TIMEOUT     10
 
 #define PXEBC_DHCP6_S_PORT                547
 #define PXEBC_DHCP6_C_PORT                546
@@ -254,8 +255,35 @@
   IN  EFI_IP_ADDRESS                *DestIp
   );
 
+/**
+  Set the IP6 policy to Automatic.
 
+  @param[in]  Private             The pointer to PXEBC_PRIVATE_DATA.
+
+  @retval     EFI_SUCCESS         Switch the IP policy succesfully.
+  @retval     Others              Unexpect error happened.
+
+**/
+EFI_STATUS
+PxeBcSetIp6Policy (
+  IN PXEBC_PRIVATE_DATA            *Private
+  );
+
 /**
+  This function will register the station IP address and flush IP instance to 
start using the new IP address.
+  
+  @param[in]  Private             The pointer to PXEBC_PRIVATE_DATA.
+
+  @retval     EFI_SUCCESS         The new IP address has been configured 
successfully.
+  @retval     Others              Failed to configure the address.
+
+**/
+EFI_STATUS
+PxeBcSetIp6Address (
+  IN  PXEBC_PRIVATE_DATA              *Private
+  );
+
+/**
   Start the DHCPv6 S.A.R.R. process to acquire the IPv6 address and other PXE 
boot information.
 
   @param[in]  Private           The pointer to the PxeBc private data.

Modified: trunk/edk2/NetworkPkg/UefiPxeBcDxe/PxeBcImpl.c
===================================================================
--- trunk/edk2/NetworkPkg/UefiPxeBcDxe/PxeBcImpl.c      2014-09-18 09:02:57 UTC 
(rev 16130)
+++ trunk/edk2/NetworkPkg/UefiPxeBcDxe/PxeBcImpl.c      2014-09-18 11:44:36 UTC 
(rev 16131)
@@ -124,6 +124,14 @@
     if (EFI_ERROR (Status)) {
       goto ON_ERROR;
     }
+
+    //
+    // Set Ip6 policy to Automatic to start the IP6 router discovery.
+    //
+    Status = PxeBcSetIp6Policy (Private);
+    if (EFI_ERROR (Status)) {
+      goto ON_ERROR;
+    }
   } else {
     AsciiPrint ("\n>>Start PXE over IPv4");
     //

Modified: trunk/edk2/NetworkPkg/UefiPxeBcDxe/PxeBcImpl.h
===================================================================
--- trunk/edk2/NetworkPkg/UefiPxeBcDxe/PxeBcImpl.h      2014-09-18 09:02:57 UTC 
(rev 16130)
+++ trunk/edk2/NetworkPkg/UefiPxeBcDxe/PxeBcImpl.h      2014-09-18 11:44:36 UTC 
(rev 16131)
@@ -160,6 +160,7 @@
   BOOLEAN                                   IsProxyRecved;
   BOOLEAN                                   IsDoDiscover;
 
+  EFI_IP_ADDRESS                            TmpStationIp;
   EFI_IP_ADDRESS                            StationIp;
   EFI_IP_ADDRESS                            SubnetMask;
   EFI_IP_ADDRESS                            GatewayIp;


------------------------------------------------------------------------------
Want excitement?
Manually upgrade your production database.
When you want reliability, choose Perforce
Perforce version control. Predictably reliable.
http://pubads.g.doubleclick.net/gampad/clk?id=157508191&iu=/4140/ostg.clktrk
_______________________________________________
edk2-commits mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/edk2-commits

Reply via email to