]> git.proxmox.com Git - mirror_edk2.git/commitdiff
1. Fix bugs for PXE-IPv6 to accommodate the situation:
authorhhuan13 <hhuan13@6f19259b-4bc3-4df7-8a09-765794883524>
Fri, 12 Aug 2011 06:18:29 +0000 (06:18 +0000)
committerhhuan13 <hhuan13@6f19259b-4bc3-4df7-8a09-765794883524>
Fri, 12 Aug 2011 06:18:29 +0000 (06:18 +0000)
   1.1 Proxy DHCP6 service and DHCP6 service on different servers.
   1.2 Proxy DHCP6 server with Response Delay setting.
2. Update to support percent-encoding in NBP file name in netboot6 BootFileURL.

Signed-off-by: hhuan13
Reviewed-by: xdu2, tye
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@12122 6f19259b-4bc3-4df7-8a09-765794883524

NetworkPkg/Dhcp6Dxe/Dhcp6Impl.h
NetworkPkg/Dhcp6Dxe/Dhcp6Io.c
NetworkPkg/Ip6Dxe/Ip6Output.c
NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.c
NetworkPkg/UefiPxeBcDxe/PxeBcImpl.c
NetworkPkg/UefiPxeBcDxe/PxeBcImpl.h
NetworkPkg/UefiPxeBcDxe/PxeBcSupport.c
NetworkPkg/UefiPxeBcDxe/PxeBcSupport.h

index 84d50ad24424df23a8ac78048a2d0587ebeab5e1..dda0cf37d56943b1babdeda2b33eb16b6ac63749 100644 (file)
@@ -212,6 +212,7 @@ struct _DHCP6_TX_CB {
   UINT32                        RetryLos;\r
   UINT32                        TickTime;\r
   UINT16                        *Elapsed;\r
+  BOOLEAN                       SolicitRetry;\r
 };\r
 \r
 //\r
index cca1468683782a58f1c43c55c16ee1dcda551f53..7320642eddf9b4498bbbe7207e9f43a507297393 100644 (file)
@@ -2817,7 +2817,7 @@ Dhcp6OnTimerTick (
       //\r
       // Handle the first rt in the transmission of solicit specially.\r
       //\r
-      if (TxCb->RetryCnt == 0 && TxCb->TxPacket->Dhcp6.Header.MessageType == Dhcp6MsgSolicit) {\r
+      if ((TxCb->RetryCnt == 0 || TxCb->SolicitRetry) && TxCb->TxPacket->Dhcp6.Header.MessageType == Dhcp6MsgSolicit) {\r
         if (Instance->AdSelect == NULL) {\r
           //\r
           // Set adpref as 0xff here to indicate select any advertisement\r
@@ -2893,6 +2893,10 @@ Dhcp6OnTimerTick (
       // Retransmit the last sent packet again.\r
       //\r
       Dhcp6TransmitPacket (Instance, TxCb->TxPacket, TxCb->Elapsed);\r
+      TxCb->SolicitRetry = FALSE;\r
+      if (TxCb->TxPacket->Dhcp6.Header.MessageType == Dhcp6MsgSolicit) {\r
+        TxCb->SolicitRetry = TRUE;\r
+      }\r
     }\r
   }\r
 \r
index ecbaf2d94ca9014f5fe1cbb2c81972673c9f6721..0e18c10c8303bd4d927442d5678734c83f179e38 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
   The internal functions and routines to transmit the IP6 packet.\r
 \r
-  Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>\r
+  Copyright (c) 2009 - 2011, 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
@@ -689,13 +689,25 @@ Ip6Output (
     // For unicast packets, use a combination of the Destination Cache, the Prefix List\r
     // and the Default Router List to determine the IP address of the appropriate next hop.\r
     //\r
-    RouteCache = Ip6Route (IpSb, &Head->DestinationAddress, &Head->SourceAddress);\r
-    if (RouteCache == NULL) {\r
-      return EFI_NOT_FOUND;\r
-    }\r
 \r
-    IP6_COPY_ADDRESS (&NextHop, &RouteCache->NextHop);\r
-    Ip6FreeRouteCacheEntry (RouteCache);\r
+    NeighborCache = Ip6FindNeighborEntry (IpSb, &Head->DestinationAddress);\r
+    if (NeighborCache != NULL) {\r
+      //\r
+      // Hit Neighbor Cache.\r
+      //\r
+      IP6_COPY_ADDRESS (&NextHop, &Head->DestinationAddress);\r
+    } else {\r
+      //\r
+      // Not in Neighbor Cache, check Router cache\r
+      //\r
+      RouteCache = Ip6Route (IpSb, &Head->DestinationAddress, &Head->SourceAddress);\r
+      if (RouteCache == NULL) {\r
+        return EFI_NOT_FOUND;\r
+      }\r
+\r
+      IP6_COPY_ADDRESS (&NextHop, &RouteCache->NextHop);\r
+      Ip6FreeRouteCacheEntry (RouteCache);\r
+    }\r
   }\r
 \r
   //\r
index 64e15030c5eb6ed154356a699b33cbbca3b960fc..23ec9e7fc9e42e5409e596c602fb093dd2c94b5d 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
   Functions implementation related with DHCPv6 for UefiPxeBc Driver.\r
 \r
-  Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>\r
+  Copyright (c) 2009 - 2011, 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
@@ -236,6 +236,7 @@ PxeBcExtractBootFileUrl (
   UINT8                      *BootFileName;\r
   UINT16                     BootFileNameLen;\r
   CHAR8                      *TmpStr;\r
+  CHAR8                      TmpChar;\r
   CHAR8                      *ServerAddressOption;\r
   CHAR8                      *ServerAddress;\r
   EFI_STATUS                 Status;\r
@@ -321,17 +322,35 @@ PxeBcExtractBootFileUrl (
   ++BootFileNamePtr;\r
   BootFileNameLen = (UINT16)(Length - (UINT16) ((UINTN)BootFileNamePtr - (UINTN)TmpStr) + 1);\r
   if (BootFileNameLen != 0 || FileName != NULL) {\r
+    //\r
+    // Extract boot file name from URL.\r
+    //\r
     BootFileName = (UINT8 *) AllocateZeroPool (BootFileNameLen);\r
     if (BootFileName == NULL) {\r
       FreePool (TmpStr);\r
       return EFI_OUT_OF_RESOURCES;\r
     }\r
-\r
-    CopyMem (BootFileName, BootFileNamePtr, BootFileNameLen);\r
-    BootFileName[BootFileNameLen - 1] = '\0';\r
     *FileName = BootFileName;\r
-  }\r
 \r
+    //\r
+    // Decode percent-encoding in boot file name.\r
+    //\r
+    while (*BootFileNamePtr != '\0') {\r
+      if (*BootFileNamePtr == '%') {\r
+        TmpChar = *(BootFileNamePtr+ 3);\r
+        *(BootFileNamePtr+ 3) = '\0';\r
+        *BootFileName = (UINT8) AsciiStrHexToUintn (BootFileNamePtr + 1);\r
+        BootFileName++;\r
+        *(BootFileNamePtr+ 3) = TmpChar;\r
+        BootFileNamePtr += 3;\r
+      } else {\r
+        *BootFileName = *BootFileNamePtr;\r
+        BootFileName++;\r
+        BootFileNamePtr++;\r
+      }\r
+    }\r
+    *BootFileName = '\0';\r
+  }\r
 \r
   FreePool (TmpStr);\r
 \r
@@ -455,13 +474,13 @@ PxeBcParseDhcp6Packet (
   // An ia_na option, embeded with valid ia_addr option and a status_code of success.\r
   //\r
   Option = Options[PXEBC_DHCP6_IDX_IA_NA];\r
-  if (Option != NULL && NTOHS(Option->OpLen) >= 12) {\r
+  if (Option != NULL) {\r
     Option = PxeBcParseDhcp6Options (\r
                Option->Data + 12,\r
                NTOHS (Option->OpLen),\r
                PXEBC_DHCP6_OPT_STATUS_CODE\r
                );\r
-    if (Option != NULL && Option->Data[0] == 0) {\r
+    if ((Option != NULL && Option->Data[0] == 0) || (Option == NULL)) {\r
       IsProxyOffer = FALSE;\r
     }\r
   }\r
@@ -470,11 +489,12 @@ PxeBcParseDhcp6Packet (
   // The offer with "PXEClient" is a pxe offer.\r
   //\r
   Option        = Options[PXEBC_DHCP6_IDX_VENDOR_CLASS];\r
-  EnterpriseNum = PXEBC_DHCP6_ENTERPRISE_NUM;\r
+  EnterpriseNum = HTONL(PXEBC_DHCP6_ENTERPRISE_NUM);\r
+\r
   if (Option != NULL &&\r
       NTOHS(Option->OpLen) >= 13 &&\r
       CompareMem (Option->Data, &EnterpriseNum, sizeof (UINT32)) == 0 &&\r
-      CompareMem (&Option->Data[4], DEFAULT_CLASS_ID_DATA, 9) == 0) {\r
+      CompareMem (&Option->Data[6], DEFAULT_CLASS_ID_DATA, 9) == 0) {\r
     IsPxeOffer = TRUE;\r
   }\r
 \r
@@ -566,6 +586,223 @@ PxeBcCopyDhcp6Proxy (
   Mode->ProxyOfferReceived = TRUE;\r
 }\r
 \r
+/**\r
+  Seek the address of the first byte of the option header.\r
+\r
+  @param[in]  Buf           The pointer to the buffer.\r
+  @param[in]  SeekLen       The length to seek.\r
+  @param[in]  OptType       The option type.\r
+\r
+  @retval     NULL          If it failed to seek the option.\r
+  @retval     others        The position to the option.\r
+\r
+**/\r
+UINT8 *\r
+PxeBcDhcp6SeekOption (\r
+  IN UINT8           *Buf,\r
+  IN UINT32          SeekLen,\r
+  IN UINT16          OptType\r
+  )\r
+{\r
+  UINT8              *Cursor;\r
+  UINT8              *Option;\r
+  UINT16             DataLen;\r
+  UINT16             OpCode;\r
+\r
+  Option = NULL;\r
+  Cursor = Buf;\r
+\r
+  while (Cursor < Buf + SeekLen) {\r
+    OpCode = ReadUnaligned16 ((UINT16 *) Cursor);\r
+    if (OpCode == HTONS (OptType)) {\r
+      Option = Cursor;\r
+      break;\r
+    }\r
+    DataLen = NTOHS (ReadUnaligned16 ((UINT16 *) (Cursor + 2)));\r
+    Cursor += (DataLen + 4);\r
+  }\r
+\r
+  return Option;\r
+}\r
+\r
+\r
+/**\r
+  Build and send out the request packet for the bootfile, and parse the reply.\r
+\r
+  @param[in]  Private               The pointer to PxeBc private data.\r
+  @param[in]  Index                 PxeBc option boot item type.\r
+\r
+  @retval     EFI_SUCCESS           Successfully discovered the boot file.\r
+  @retval     EFI_OUT_OF_RESOURCES  Failed to allocate resources.\r
+  @retval     EFI_NOT_FOUND         Can't get the PXE reply packet.\r
+  @retval     Others                Failed to discover the boot file.\r
+\r
+**/\r
+EFI_STATUS\r
+PxeBcRequestBootService (\r
+  IN  PXEBC_PRIVATE_DATA              *Private,\r
+  IN  UINT32                          Index\r
+  )\r
+{\r
+  EFI_PXE_BASE_CODE_UDP_PORT          SrcPort;\r
+  EFI_PXE_BASE_CODE_UDP_PORT          DestPort;\r
+  EFI_PXE_BASE_CODE_MODE              *Mode;\r
+  EFI_PXE_BASE_CODE_PROTOCOL          *PxeBc;\r
+  EFI_PXE_BASE_CODE_DHCPV6_PACKET     *Discover;\r
+  UINTN                               DiscoverLen;\r
+  EFI_DHCP6_PACKET                    *Request;\r
+  UINTN                               RequestLen;\r
+  EFI_DHCP6_PACKET                    *Reply;\r
+  UINT8                               *RequestOpt;\r
+  UINT8                               *DiscoverOpt;\r
+  UINTN                               ReadSize;\r
+  UINT16                              OpFlags;\r
+  UINT16                              OpCode;\r
+  UINT16                              OpLen;\r
+  EFI_STATUS                          Status;\r
+  EFI_DHCP6_PACKET                    *ProxyOffer;\r
+  UINT8                               *Option;\r
+\r
+  PxeBc       = &Private->PxeBc;\r
+  Mode        = PxeBc->Mode;\r
+  Request     = Private->Dhcp6Request;\r
+  ProxyOffer = &Private->OfferBuffer[Index].Dhcp6.Packet.Offer;\r
+  SrcPort     = PXEBC_BS_DISCOVER_PORT;\r
+  DestPort    = PXEBC_BS_DISCOVER_PORT;\r
+  OpFlags     = 0;\r
+\r
+  if (Request == NULL) {\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
+\r
+  Discover = AllocateZeroPool (sizeof (EFI_PXE_BASE_CODE_DHCPV6_PACKET));\r
+  if (Discover == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  //\r
+  // Build the request packet by the cached request packet before.\r
+  //\r
+  Discover->TransactionId = ProxyOffer->Dhcp6.Header.TransactionId;\r
+  Discover->MessageType   = Request->Dhcp6.Header.MessageType;\r
+  RequestOpt              = Request->Dhcp6.Option;\r
+  DiscoverOpt             = Discover->DhcpOptions;\r
+  DiscoverLen             = sizeof (EFI_DHCP6_HEADER);\r
+  RequestLen              = DiscoverLen;\r
+\r
+  //\r
+  // Find Server ID Option from ProxyOffer.\r
+  //\r
+  Option = PxeBcDhcp6SeekOption (\r
+             ProxyOffer->Dhcp6.Option,\r
+             ProxyOffer->Length - 4,\r
+             PXEBC_DHCP6_OPT_SERVER_ID\r
+             );\r
+  if (Option == NULL) {\r
+    return EFI_NOT_FOUND;\r
+  }\r
+  \r
+  //\r
+  // Add Server ID Option.\r
+  //\r
+  OpLen = NTOHS (((EFI_DHCP6_PACKET_OPTION *) Option)->OpLen);\r
+  CopyMem (DiscoverOpt, Option, OpLen + 4);\r
+  DiscoverOpt += (OpLen + 4);\r
+  DiscoverLen += (OpLen + 4);\r
+\r
+  while (RequestLen < Request->Length) {\r
+    OpCode = NTOHS (((EFI_DHCP6_PACKET_OPTION *) RequestOpt)->OpCode);\r
+    OpLen  = NTOHS (((EFI_DHCP6_PACKET_OPTION *) RequestOpt)->OpLen);\r
+    if (OpCode != EFI_DHCP6_IA_TYPE_NA &&\r
+        OpCode != EFI_DHCP6_IA_TYPE_TA &&\r
+        OpCode != PXEBC_DHCP6_OPT_SERVER_ID\r
+        ) {\r
+      //\r
+      // Copy all the options except IA option and Server ID\r
+      //\r
+      CopyMem (DiscoverOpt, RequestOpt, OpLen + 4);\r
+      DiscoverOpt += (OpLen + 4);\r
+      DiscoverLen += (OpLen + 4);\r
+    }\r
+    RequestOpt += (OpLen + 4);\r
+    RequestLen += (OpLen + 4);\r
+  }\r
+\r
+  //\r
+  // Update Elapsed option in the package \r
+  //\r
+  Option = PxeBcDhcp6SeekOption (\r
+             Discover->DhcpOptions,\r
+             (UINT32)(RequestLen - 4),\r
+             PXEBC_DHCP6_OPT_ELAPSED_TIME\r
+             );\r
+  if (Option != NULL) {\r
+    CalcElapsedTime (Private);\r
+    WriteUnaligned16 ((UINT16*)(Option + 4), HTONS((UINT16) Private->ElapsedTime));\r
+  }  \r
+\r
+  Status = PxeBc->UdpWrite (\r
+                    PxeBc,\r
+                    OpFlags,\r
+                    &Private->ServerIp,\r
+                    &DestPort,\r
+                    NULL,\r
+                    &Private->StationIp,\r
+                    &SrcPort,\r
+                    NULL,\r
+                    NULL,\r
+                    &DiscoverLen,\r
+                    (VOID *) Discover\r
+                    );\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Cache the right PXE reply packet here, set valid flag later.\r
+  // Especially for PXE discover packet, store it into mode data here.\r
+  //\r
+  Reply = &Private->ProxyOffer.Dhcp6.Packet.Offer;\r
+  ReadSize = (UINTN) Reply->Size;\r
+\r
+  //\r
+  // Start Udp6Read instance\r
+  //\r
+  Status = Private->Udp6Read->Configure (Private->Udp6Read, &Private->Udp6CfgData);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+    \r
+  Status = PxeBc->UdpRead (\r
+                    PxeBc,\r
+                    OpFlags,\r
+                    &Private->StationIp,\r
+                    &SrcPort,\r
+                    &Private->ServerIp,\r
+                    &DestPort,\r
+                    NULL,\r
+                    NULL,\r
+                    &ReadSize,\r
+                    (VOID *) &Reply->Dhcp6\r
+                    );\r
+  //\r
+  // Stop Udp6Read instance\r
+  //\r
+  Private->Udp6Read->Configure (Private->Udp6Read, NULL);\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Update length\r
+  //\r
+  Reply->Length = (UINT32) ReadSize;\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
 \r
 /**\r
   Retry to request bootfile name by the BINL offer.\r
@@ -586,7 +823,6 @@ PxeBcRetryDhcp6Binl (
   EFI_PXE_BASE_CODE_MODE    *Mode;\r
   PXEBC_DHCP6_PACKET_CACHE  *Offer;\r
   PXEBC_DHCP6_PACKET_CACHE  *Cache6;\r
-  EFI_IP_ADDRESS            ServerIp;\r
   EFI_STATUS                Status;\r
 \r
   ASSERT (Index < PXEBC_OFFER_MAX_NUM);\r
@@ -602,8 +838,8 @@ PxeBcRetryDhcp6Binl (
   // Parse out the next server address from the last offer, and store it\r
   //\r
   Status = PxeBcExtractBootFileUrl (\r
-             NULL,\r
-             &ServerIp.v6,\r
+             &Private->BootFileName,\r
+             &Private->ServerIp.v6,\r
              (CHAR8 *) (Offer->OptList[PXEBC_DHCP6_IDX_BOOT_FILE_URL]->Data),\r
              NTOHS (Offer->OptList[PXEBC_DHCP6_IDX_BOOT_FILE_URL]->OpLen)\r
              );\r
@@ -614,13 +850,8 @@ PxeBcRetryDhcp6Binl (
   //\r
   // Retry Dhcp6Binl again for the bootfile, and the reply cached into Private->ProxyOffer.\r
   //\r
-  Status = PxeBcDhcp6Discover (\r
-             Private,\r
-             0,\r
-             NULL,\r
-             FALSE,\r
-             &ServerIp\r
-             );\r
+  Status = PxeBcRequestBootService (Private, Index);\r
+\r
   if (EFI_ERROR (Status)) {\r
     return Status;\r
   }\r
@@ -1193,6 +1424,13 @@ PxeBcDhcp6CallBack (
   switch (Dhcp6Event) {\r
 \r
   case Dhcp6SendSolicit:\r
+    //\r
+    // Record the first Solicate msg time\r
+    //\r
+    if (Private->SolicitTimes == 0) {\r
+      CalcElapsedTime (Private);\r
+      Private->SolicitTimes++;\r
+    }\r
     //\r
     // Cache the dhcp discover packet to mode data directly.\r
     //\r
index cd8eab3df904d65d4ee57a957d5c003ff12e1626..f5825908385b1c25ba5ed211d45f16abdd30646a 100644 (file)
@@ -321,6 +321,8 @@ EfiPxeBcStop (
   gBS->CloseEvent (Private->UdpTimeOutEvent);\r
   Private->CurSrcPort   = 0;\r
   Private->BootFileSize = 0;\r
+  Private->SolicitTimes = 0;\r
+  Private->ElapsedTime  = 0;\r
 \r
   //\r
   // Reset the mode data.\r
index c4a0add1c92a3cd03622c399ddf5cb7d56fb0f9b..04e0617c6ee5a7faf988cc48d5abf434a116125c 100644 (file)
@@ -2,7 +2,7 @@
   This EFI_PXE_BASE_CODE_PROTOCOL and EFI_LOAD_FILE_PROTOCOL.\r
   interfaces declaration.\r
 \r
-  Copyright (c) 2007 - 2010, Intel Corporation. All rights reserved.<BR>\r
+  Copyright (c) 2007 - 2011, 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
@@ -43,6 +43,7 @@
 #include <Library/MemoryAllocationLib.h>\r
 #include <Library/UefiDriverEntryPoint.h>\r
 #include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/UefiRuntimeServicesTableLib.h>\r
 #include <Library/UefiLib.h>\r
 #include <Library/BaseLib.h>\r
 #include <Library/NetLib.h>\r
@@ -146,6 +147,8 @@ struct _PXEBC_PRIVATE_DATA {
   EFI_PXE_BASE_CODE_MODE                    Mode;\r
   EFI_PXE_BASE_CODE_FUNCTION                Function;\r
   UINT32                                    Ip6Policy;\r
+  UINT32                                    SolicitTimes;\r
+  UINT64                                    ElapsedTime;\r
 \r
   EFI_UDP4_CONFIG_DATA                      Udp4CfgData;\r
   EFI_UDP6_CONFIG_DATA                      Udp6CfgData;\r
index 30418c3b6a1c2d83483c738c511fbc361d6799fe..6ddcac718ed93b71737ac7e02f9b5965f2e10ec5 100644 (file)
@@ -1464,3 +1464,56 @@ PxeBcUniHexToUint8 (
 \r
   return EFI_INVALID_PARAMETER;\r
 }\r
+\r
+/**\r
+  Calculate the elapsed time\r
+\r
+  @param[in]      Private      The pointer to PXE private data\r
+\r
+**/\r
+VOID\r
+CalcElapsedTime (\r
+  IN     PXEBC_PRIVATE_DATA     *Private\r
+  )\r
+{\r
+  EFI_TIME          Time;\r
+  UINT64            CurrentStamp;\r
+  UINT64            ElapsedTimeValue;\r
+\r
+  //\r
+  // Generate a time stamp of the centiseconds from 1900/1/1, assume 30day/month.\r
+  //\r
+  ZeroMem (&Time, sizeof (EFI_TIME));\r
+  gRT->GetTime (&Time, NULL);\r
+  CurrentStamp = (UINT64)\r
+    (\r
+      ((((((Time.Year - 1900) * 360 +\r
+       (Time.Month - 1)) * 30 +\r
+       (Time.Day - 1)) * 24 + Time.Hour) * 60 +\r
+       Time.Minute) * 60 + Time.Second) * 100\r
+       + DivU64x32(Time.Nanosecond, 10000000)\r
+    );\r
+\r
+  //\r
+  // Sentinel value of 0 means that this is the first DHCP packet that we are\r
+  // sending and that we need to initialize the value.  First DHCP Solicit\r
+  // gets 0 elapsed-time.  Otherwise, calculate based on StartTime.\r
+  //\r
+  if (Private->ElapsedTime == 0) {\r
+    Private->ElapsedTime = CurrentStamp;\r
+  } else {\r
+    ElapsedTimeValue = CurrentStamp - Private->ElapsedTime;\r
+\r
+    //\r
+    // If elapsed time cannot fit in two bytes, set it to 0xffff.\r
+    //\r
+    if (ElapsedTimeValue > 0xffff) {\r
+      ElapsedTimeValue = 0xffff;\r
+    }\r
+    //\r
+    // Save the elapsed time\r
+    //\r
+    Private->ElapsedTime = ElapsedTimeValue;\r
+  }\r
+}\r
+\r
index a4f5d3131a1052240f88820413477c3d47f258ba..797f607642d8e739248cab5dc6aa9007bf9e1a8c 100644 (file)
@@ -474,4 +474,15 @@ PxeBcUniHexToUint8 (
   IN  CHAR16               Char\r
   );\r
 \r
+/**\r
+  Calculate the elapsed time\r
+\r
+  @param[in]      Private      The pointer to PXE private data\r
+\r
+**/\r
+VOID\r
+CalcElapsedTime (\r
+  IN     PXEBC_PRIVATE_DATA     *Private\r
+  );\r
+\r
 #endif\r