]> git.proxmox.com Git - mirror_edk2.git/commitdiff
1. Import UEFI PxeBc module in MdeModulePkg
authorvanjeff <vanjeff@6f19259b-4bc3-4df7-8a09-765794883524>
Fri, 4 Jan 2008 02:29:30 +0000 (02:29 +0000)
committervanjeff <vanjeff@6f19259b-4bc3-4df7-8a09-765794883524>
Fri, 4 Jan 2008 02:29:30 +0000 (02:29 +0000)
2. Remove some SMBIOS definitions defined in PxeBc module, use those who are defined in MdePkg.

git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@4495 6f19259b-4bc3-4df7-8a09-765794883524

19 files changed:
MdeModulePkg/MdeModulePkg.dsc
MdeModulePkg/Universal/Network/PxeBcDxe/Bc.h
MdeModulePkg/Universal/Network/PxeBcDxe/Pxe_bc_dhcp.c
MdeModulePkg/Universal/Network/UefiPxeBcDxe/ComponentName.c [new file with mode: 0644]
MdeModulePkg/Universal/Network/UefiPxeBcDxe/Ia32/PxeArch.h [new file with mode: 0644]
MdeModulePkg/Universal/Network/UefiPxeBcDxe/Ipf/PxeArch.h [new file with mode: 0644]
MdeModulePkg/Universal/Network/UefiPxeBcDxe/PxeBcDhcp.c [new file with mode: 0644]
MdeModulePkg/Universal/Network/UefiPxeBcDxe/PxeBcDhcp.h [new file with mode: 0644]
MdeModulePkg/Universal/Network/UefiPxeBcDxe/PxeBcDriver.c [new file with mode: 0644]
MdeModulePkg/Universal/Network/UefiPxeBcDxe/PxeBcDriver.h [new file with mode: 0644]
MdeModulePkg/Universal/Network/UefiPxeBcDxe/PxeBcImpl.c [new file with mode: 0644]
MdeModulePkg/Universal/Network/UefiPxeBcDxe/PxeBcImpl.h [new file with mode: 0644]
MdeModulePkg/Universal/Network/UefiPxeBcDxe/PxeBcMtftp.c [new file with mode: 0644]
MdeModulePkg/Universal/Network/UefiPxeBcDxe/PxeBcMtftp.h [new file with mode: 0644]
MdeModulePkg/Universal/Network/UefiPxeBcDxe/PxeBcSupport.c [new file with mode: 0644]
MdeModulePkg/Universal/Network/UefiPxeBcDxe/PxeBcSupport.h [new file with mode: 0644]
MdeModulePkg/Universal/Network/UefiPxeBcDxe/UefiPxeBcDxe.inf [new file with mode: 0644]
MdeModulePkg/Universal/Network/UefiPxeBcDxe/UefiPxeBcDxe.msa [new file with mode: 0644]
MdeModulePkg/Universal/Network/UefiPxeBcDxe/X64/PxeArch.h [new file with mode: 0644]

index 5c57569da6862705d1f729c50c14afbfece9adc2..5f53c67b2c4deee953351769c9af4050008cf503 100644 (file)
   MdeModulePkg/Universal/Network/MnpDxe/MnpDxe.inf\r
   MdeModulePkg/Universal/Network/Mtftp4Dxe/Mtftp4Dxe.inf\r
   MdeModulePkg/Universal/Network/PxeBcDxe/PxeBcDxe.inf\r
+  MdeModulePkg/Universal/Network/UefiPxeBcDxe/UefiPxeBcDxe.inf\r
   MdeModulePkg/Universal/Network/PxeDhcp4Dxe/PxeDhcp4Dxe.inf\r
   MdeModulePkg/Universal/Network/SnpDxe/SnpDxe.inf\r
   MdeModulePkg/Universal/Network/Tcp4Dxe/Tcp4Dxe.inf\r
index 715a9f15627f5f13810cd4cf674001e2f7235e01..8d09ee6e7141335cf1ce10346483123c2c71367e 100644 (file)
@@ -23,6 +23,7 @@ Abstract:
 #include <PiDxe.h>\r
 \r
 #include <Guid/SmBios.h>\r
+#include <IndustryStandard/Smbios.h>\r
 #include <Protocol/Bis.h>\r
 #include <Protocol/PxeBaseCode.h>\r
 #include <Protocol/PxeBaseCodeCallBack.h>\r
@@ -437,117 +438,6 @@ PxeBcLibGetSmbiosSystemGuidAndSerialNumber (
   )\r
 ;\r
 \r
-\r
-//\r
-// Define SMBIOS tables.\r
-//\r
-#pragma pack(1)\r
-typedef struct {\r
-  UINT8   AnchorString[4];\r
-  UINT8   EntryPointStructureChecksum;\r
-  UINT8   EntryPointLength;\r
-  UINT8   MajorVersion;\r
-  UINT8   MinorVersion;\r
-  UINT16  MaxStructureSize;\r
-  UINT8   EntryPointRevision;\r
-  UINT8   FormattedArea[5];\r
-  UINT8   IntermediateAnchorString[5];\r
-  UINT8   IntermediateChecksum;\r
-  UINT16  TableLength;\r
-  UINT32  TableAddress;\r
-  UINT16  NumberOfSmbiosStructures;\r
-  UINT8   SmbiosBcdRevision;\r
-} SMBIOS_STRUCTURE_TABLE;\r
-\r
-//\r
-// Please note that SMBIOS structures can be odd byte aligned since the\r
-//  unformated section of each record is a set of arbitrary size strings.\r
-//\r
-typedef struct {\r
-  UINT8 Type;\r
-  UINT8 Length;\r
-  UINT8 Handle[2];\r
-} SMBIOS_HEADER;\r
-\r
-typedef UINT8 SMBIOS_STRING;\r
-\r
-typedef struct {\r
-  SMBIOS_HEADER Hdr;\r
-  SMBIOS_STRING Vendor;\r
-  SMBIOS_STRING BiosVersion;\r
-  UINT8         BiosSegment[2];\r
-  SMBIOS_STRING BiosReleaseDate;\r
-  UINT8         BiosSize;\r
-  UINT8         BiosCharacteristics[8];\r
-} SMBIOS_TYPE0;\r
-\r
-typedef struct {\r
-  SMBIOS_HEADER Hdr;\r
-  SMBIOS_STRING Manufacturer;\r
-  SMBIOS_STRING ProductName;\r
-  SMBIOS_STRING Version;\r
-  SMBIOS_STRING SerialNumber;\r
-\r
-  //\r
-  // always byte copy this data to prevent alignment faults!\r
-  //\r
-  EFI_GUID      Uuid;\r
-\r
-  UINT8         WakeUpType;\r
-} SMBIOS_TYPE1;\r
-\r
-typedef struct {\r
-  SMBIOS_HEADER Hdr;\r
-  SMBIOS_STRING Manufacturer;\r
-  SMBIOS_STRING ProductName;\r
-  SMBIOS_STRING Version;\r
-  SMBIOS_STRING SerialNumber;\r
-} SMBIOS_TYPE2;\r
-\r
-typedef struct {\r
-  SMBIOS_HEADER Hdr;\r
-  SMBIOS_STRING Manufacturer;\r
-  UINT8         Type;\r
-  SMBIOS_STRING Version;\r
-  SMBIOS_STRING SerialNumber;\r
-  SMBIOS_STRING AssetTag;\r
-  UINT8         BootupState;\r
-  UINT8         PowerSupplyState;\r
-  UINT8         ThermalState;\r
-  UINT8         SecurityStatus;\r
-  UINT8         OemDefined[4];\r
-} SMBIOS_TYPE3;\r
-\r
-typedef struct {\r
-  SMBIOS_HEADER Hdr;\r
-  UINT8         Socket;\r
-  UINT8         ProcessorType;\r
-  UINT8         ProcessorFamily;\r
-  SMBIOS_STRING ProcessorManufacture;\r
-  UINT8         ProcessorId[8];\r
-  SMBIOS_STRING ProcessorVersion;\r
-  UINT8         Voltage;\r
-  UINT8         ExternalClock[2];\r
-  UINT8         MaxSpeed[2];\r
-  UINT8         CurrentSpeed[2];\r
-  UINT8         Status;\r
-  UINT8         ProcessorUpgrade;\r
-  UINT8         L1CacheHandle[2];\r
-  UINT8         L2CacheHandle[2];\r
-  UINT8         L3CacheHandle[2];\r
-} SMBIOS_TYPE4;\r
-\r
-typedef union {\r
-  SMBIOS_HEADER *Hdr;\r
-  SMBIOS_TYPE0  *Type0;\r
-  SMBIOS_TYPE1  *Type1;\r
-  SMBIOS_TYPE2  *Type2;\r
-  SMBIOS_TYPE3  *Type3;\r
-  SMBIOS_TYPE4  *Type4;\r
-  UINT8         *Raw;\r
-} SMBIOS_STRUCTURE_POINTER;\r
-#pragma pack()\r
-\r
 #include "ip.h"\r
 #include "dhcp.h"\r
 #include "tftp.h"\r
index a61b6acff7865a3ebb94366567154da4ad4dec7c..3c5b197c16a948237794f1c75ac4704e1125f55e 100644 (file)
@@ -473,7 +473,7 @@ PxeBcLibGetSmbiosSystemGuidAndSerialNumber (
   )\r
 {\r
   EFI_STATUS                Status;\r
-  SMBIOS_STRUCTURE_TABLE    *SmbiosTable;\r
+  SMBIOS_TABLE_ENTRY_POINT  *SmbiosTable;\r
   SMBIOS_STRUCTURE_POINTER  Smbios;\r
   SMBIOS_STRUCTURE_POINTER  SmbiosEnd;\r
   UINT16                    Index;\r
@@ -484,7 +484,7 @@ PxeBcLibGetSmbiosSystemGuidAndSerialNumber (
     return EFI_NOT_FOUND;\r
   }\r
 \r
-  Smbios.Hdr    = (SMBIOS_HEADER *) (UINTN) SmbiosTable->TableAddress;\r
+  Smbios.Hdr    = (SMBIOS_STRUCTURE *) (UINTN) SmbiosTable->TableAddress;\r
   SmbiosEnd.Raw = (UINT8 *) (UINTN) (SmbiosTable->TableAddress + SmbiosTable->TableLength);\r
 \r
   for (Index = 0; Index < SmbiosTable->TableLength; Index++) {\r
diff --git a/MdeModulePkg/Universal/Network/UefiPxeBcDxe/ComponentName.c b/MdeModulePkg/Universal/Network/UefiPxeBcDxe/ComponentName.c
new file mode 100644 (file)
index 0000000..8deac91
--- /dev/null
@@ -0,0 +1,168 @@
+/** @file\r
+\r
+Copyright (c) 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
+  ComponentName.c\r
+\r
+Abstract:\r
+\r
+\r
+**/\r
+\r
+\r
+#include "PxeBcImpl.h"\r
+\r
+//\r
+// EFI Component Name Functions\r
+//\r
+EFI_STATUS\r
+EFIAPI\r
+PxeBcComponentNameGetDriverName (\r
+  IN  EFI_COMPONENT_NAME_PROTOCOL  * This,\r
+  IN  CHAR8                        *Language,\r
+  OUT CHAR16                       **DriverName\r
+  );\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PxeBcComponentNameGetControllerName (\r
+  IN  EFI_COMPONENT_NAME_PROTOCOL  * This,\r
+  IN  EFI_HANDLE                   ControllerHandle,\r
+  IN  EFI_HANDLE                   ChildHandle        OPTIONAL,\r
+  IN  CHAR8                        *Language,\r
+  OUT CHAR16                       **ControllerName\r
+  );\r
+\r
+//\r
+// EFI Component Name Protocol\r
+//\r
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL     gPxeBcComponentName = {\r
+  PxeBcComponentNameGetDriverName,\r
+  PxeBcComponentNameGetControllerName,\r
+  "eng"\r
+};\r
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL    gPxeBcComponentName2 = {\r
+  (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) PxeBcComponentNameGetDriverName,\r
+  (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) PxeBcComponentNameGetControllerName,\r
+  "en"\r
+};\r
+\r
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mPxeBcDriverNameTable[] = {\r
+  {\r
+    "eng;en",\r
+    L"UEFI PXE Base Code Driver"\r
+  },\r
+  {\r
+    NULL,\r
+    NULL\r
+  }\r
+};\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PxeBcComponentNameGetDriverName (\r
+  IN  EFI_COMPONENT_NAME_PROTOCOL  * This,\r
+  IN  CHAR8                        *Language,\r
+  OUT CHAR16                       **DriverName\r
+  )\r
+/*++\r
+\r
+  Routine Description:\r
+    Retrieves a Unicode string that is the user readable name of the EFI Driver.\r
+\r
+  Arguments:\r
+    This       - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.\r
+    Language   - A pointer to a three character ISO 639-2 language identifier.\r
+                 This is the language of the driver name that that the caller\r
+                 is requesting, and it must match one of the languages specified\r
+                 in SupportedLanguages.  The number of languages supported by a\r
+                 driver is up to the driver writer.\r
+    DriverName - A pointer to the Unicode string to return.  This Unicode string\r
+                 is the name of the driver specified by This in the language\r
+                 specified by Language.\r
+\r
+  Returns:\r
+    EFI_SUCCESS           - The Unicode string for the Driver specified by This\r
+                            and the language specified by Language was returned\r
+                            in DriverName.\r
+    EFI_INVALID_PARAMETER - Language is NULL.\r
+    EFI_INVALID_PARAMETER - DriverName is NULL.\r
+    EFI_UNSUPPORTED       - The driver specified by This does not support the\r
+                            language specified by Language.\r
+\r
+--*/\r
+{\r
+  return LookupUnicodeString2 (\r
+          Language,\r
+          This->SupportedLanguages,\r
+          mPxeBcDriverNameTable,\r
+          DriverName,\r
+          (BOOLEAN)(This == &gPxeBcComponentName)\r
+          );\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PxeBcComponentNameGetControllerName (\r
+  IN  EFI_COMPONENT_NAME_PROTOCOL  * This,\r
+  IN  EFI_HANDLE                   ControllerHandle,\r
+  IN  EFI_HANDLE                   ChildHandle        OPTIONAL,\r
+  IN  CHAR8                        *Language,\r
+  OUT CHAR16                       **ControllerNameString\r
+  )\r
+/*++\r
+\r
+  Routine Description:\r
+    Retrieves a Unicode string that is the user readable name of the controller\r
+    that is being managed by an EFI Driver.\r
+\r
+  Arguments:\r
+    This             - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.\r
+    ControllerHandle - The handle of a controller that the driver specified by\r
+                       This is managing.  This handle specifies the controller\r
+                       whose name is to be returned.\r
+    ChildHandle      - The handle of the child controller to retrieve the name\r
+                       of.  This is an optional parameter that may be NULL.  It\r
+                       will be NULL for device drivers.  It will also be NULL\r
+                       for a bus drivers that wish to retrieve the name of the\r
+                       bus controller.  It will not be NULL for a bus driver\r
+                       that wishes to retrieve the name of a child controller.\r
+    Language         - A pointer to a three character ISO 639-2 language\r
+                       identifier.  This is the language of the controller name\r
+                       that that the caller is requesting, and it must match one\r
+                       of the languages specified in SupportedLanguages.  The\r
+                       number of languages supported by a driver is up to the\r
+                       driver writer.\r
+    ControllerName   - A pointer to the Unicode string to return.  This Unicode\r
+                       string is the name of the controller specified by\r
+                       ControllerHandle and ChildHandle in the language specified\r
+                       by Language from the point of view of the driver specified\r
+                       by This.\r
+\r
+  Returns:\r
+    EFI_SUCCESS           - The Unicode string for the user readable name in the\r
+                            language specified by Language for the driver\r
+                            specified by This was returned in DriverName.\r
+    EFI_INVALID_PARAMETER - ControllerHandle is not a valid EFI_HANDLE.\r
+    EFI_INVALID_PARAMETER - ChildHandle is not NULL and it is not a valid EFI_HANDLE.\r
+    EFI_INVALID_PARAMETER - Language is NULL.\r
+    EFI_INVALID_PARAMETER - ControllerName is NULL.\r
+    EFI_UNSUPPORTED       - The driver specified by This is not currently managing\r
+                            the controller specified by ControllerHandle and\r
+                            ChildHandle.\r
+    EFI_UNSUPPORTED       - The driver specified by This does not support the\r
+                            language specified by Language.\r
+\r
+--*/\r
+{\r
+  return EFI_UNSUPPORTED;\r
+}\r
+\r
diff --git a/MdeModulePkg/Universal/Network/UefiPxeBcDxe/Ia32/PxeArch.h b/MdeModulePkg/Universal/Network/UefiPxeBcDxe/Ia32/PxeArch.h
new file mode 100644 (file)
index 0000000..cc878d8
--- /dev/null
@@ -0,0 +1,26 @@
+/** @file
+
+Copyright (c) 2006, 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.
+
+Module Name:
+  PxeArch.h
+
+Abstract:
+  Defines PXE Arch type
+
+
+**/
+
+#ifndef _EFI_PXE_ARCH_H_
+#define _EFI_PXE_ARCH_H_
+
+#define SYS_ARCH  0x6
+
+#endif
diff --git a/MdeModulePkg/Universal/Network/UefiPxeBcDxe/Ipf/PxeArch.h b/MdeModulePkg/Universal/Network/UefiPxeBcDxe/Ipf/PxeArch.h
new file mode 100644 (file)
index 0000000..6d06045
--- /dev/null
@@ -0,0 +1,26 @@
+/** @file
+
+Copyright (c) 2006, 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.
+
+Module Name:
+  PxeArch.h
+
+Abstract:
+  Defines PXE Arch type
+
+
+**/
+
+#ifndef _EFI_PXE_ARCH_H_
+#define _EFI_PXE_ARCH_H_
+
+#define SYS_ARCH  0x2
+
+#endif
diff --git a/MdeModulePkg/Universal/Network/UefiPxeBcDxe/PxeBcDhcp.c b/MdeModulePkg/Universal/Network/UefiPxeBcDxe/PxeBcDhcp.c
new file mode 100644 (file)
index 0000000..b76461a
--- /dev/null
@@ -0,0 +1,1746 @@
+/** @file\r
+\r
+Copyright (c) 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
+  PxeBcDhcp.c\r
+\r
+Abstract:\r
+\r
+  Support for PxeBc dhcp functions\r
+\r
+\r
+**/\r
+\r
+\r
+#include "PxeBcImpl.h"\r
+\r
+//\r
+// This is a map from the interested DHCP4 option tags' index to the tag value.\r
+//\r
+UINT8 mInterestedDhcp4Tags[PXEBC_DHCP4_TAG_INDEX_MAX] = {\r
+  PXEBC_DHCP4_TAG_BOOTFILE_LEN,\r
+  PXEBC_DHCP4_TAG_VENDOR,\r
+  PXEBC_DHCP4_TAG_OVERLOAD,\r
+  PXEBC_DHCP4_TAG_MSG_TYPE,\r
+  PXEBC_DHCP4_TAG_SERVER_ID,\r
+  PXEBC_DHCP4_TAG_CLASS_ID,\r
+  PXEBC_DHCP4_TAG_BOOTFILE\r
+};\r
+\r
+\r
+/**\r
+  GC_NOTO: Add function description\r
+\r
+  @param  Seed                  GC_NOTO: add argument description\r
+  @param  Udp4                  GC_NOTO: add argument description\r
+\r
+  @return GC_NOTO: add return values\r
+\r
+**/\r
+VOID\r
+PxeBcInitSeedPacket (\r
+  IN EFI_DHCP4_PACKET  *Seed,\r
+  IN EFI_UDP4_PROTOCOL *Udp4\r
+  )\r
+{\r
+  EFI_SIMPLE_NETWORK_MODE Mode;\r
+  EFI_DHCP4_HEADER        *Header;\r
+\r
+  Udp4->GetModeData (Udp4, NULL, NULL, NULL, &Mode);\r
+\r
+  Seed->Size    = sizeof (EFI_DHCP4_PACKET);\r
+  Seed->Length  = sizeof (Seed->Dhcp4);\r
+\r
+  Header        = &Seed->Dhcp4.Header;\r
+\r
+  NetZeroMem (Header, sizeof (EFI_DHCP4_HEADER));\r
+  Header->OpCode    = PXEBC_DHCP4_OPCODE_REQUEST;\r
+  Header->HwType    = Mode.IfType;\r
+  Header->HwAddrLen = (UINT8) Mode.HwAddressSize;\r
+  NetCopyMem (Header->ClientHwAddr, &Mode.CurrentAddress, Header->HwAddrLen);\r
+\r
+  Seed->Dhcp4.Magik     = PXEBC_DHCP4_MAGIC;\r
+  Seed->Dhcp4.Option[0] = PXEBC_DHCP4_TAG_EOP;\r
+}\r
+\r
+\r
+/**\r
+  GC_NOTO: Add function description\r
+\r
+  @param  Dst                   GC_NOTO: add argument description\r
+  @param  Src                   GC_NOTO: add argument description\r
+\r
+  @return GC_NOTO: add return values\r
+\r
+**/\r
+VOID\r
+PxeBcCopyEfiDhcp4Packet (\r
+  IN EFI_DHCP4_PACKET  *Dst,\r
+  IN EFI_DHCP4_PACKET  *Src\r
+  )\r
+{\r
+  ASSERT (Dst->Size >= Src->Length);\r
+\r
+  NetCopyMem (&Dst->Dhcp4, &Src->Dhcp4, Src->Length);\r
+  Dst->Length = Src->Length;\r
+}\r
+\r
+\r
+/**\r
+  GC_NOTO: Add function description\r
+\r
+  @param  Private               GC_NOTO: add argument description\r
+  @param  OfferIndex            GC_NOTO: add argument description\r
+\r
+  @return GC_NOTO: add return values\r
+\r
+**/\r
+VOID\r
+PxeBcCopyProxyOffer (\r
+  IN PXEBC_PRIVATE_DATA  *Private,\r
+  IN UINT32              OfferIndex\r
+  )\r
+{\r
+  EFI_PXE_BASE_CODE_MODE  *Mode;\r
+  EFI_DHCP4_PACKET        *Offer;\r
+\r
+  ASSERT (OfferIndex < Private->NumOffers);\r
+\r
+  Mode  = Private->PxeBc.Mode;\r
+  Offer = &Private->Dhcp4Offers[OfferIndex].Packet.Offer;\r
+\r
+  PxeBcCopyEfiDhcp4Packet (&Private->ProxyOffer.Packet.Offer, Offer);\r
+  NetCopyMem (&Mode->ProxyOffer, &Offer->Dhcp4, Offer->Length);\r
+  Mode->ProxyOfferReceived = TRUE;\r
+\r
+  PxeBcParseCachedDhcpPacket (&Private->ProxyOffer);\r
+}\r
+\r
+\r
+/**\r
+  Parse the cached dhcp packet.\r
+\r
+  @param  CachedPacket          Pointer to cached dhcp packet\r
+\r
+  @return TRUE  : Success to parse and validation\r
+  @return FALSE : Fail to parse or validation\r
+\r
+**/\r
+BOOLEAN\r
+PxeBcParseCachedDhcpPacket (\r
+  IN PXEBC_CACHED_DHCP4_PACKET  *CachedPacket\r
+  )\r
+{\r
+  EFI_DHCP4_PACKET        *Offer;\r
+  EFI_DHCP4_PACKET_OPTION **Options;\r
+  EFI_DHCP4_PACKET_OPTION *Option;\r
+  UINT8                   OfferType;\r
+  UINTN                   Index;\r
+\r
+  CachedPacket->IsPxeOffer = FALSE;\r
+  NetZeroMem (CachedPacket->Dhcp4Option, sizeof (CachedPacket->Dhcp4Option));\r
+  NetZeroMem (&CachedPacket->PxeVendorOption, sizeof (CachedPacket->PxeVendorOption));\r
+\r
+  Offer   = &CachedPacket->Packet.Offer;\r
+  Options = CachedPacket->Dhcp4Option;\r
+\r
+  //\r
+  // Parse interested dhcp options and store their pointers in CachedPacket->Dhcp4Option.\r
+  //\r
+  for (Index = 0; Index < PXEBC_DHCP4_TAG_INDEX_MAX; Index++) {\r
+    Options[Index] = PxeBcParseExtendOptions (\r
+                      Offer->Dhcp4.Option,\r
+                      GET_OPTION_BUFFER_LEN (Offer),\r
+                      mInterestedDhcp4Tags[Index]\r
+                      );\r
+  }\r
+\r
+  //\r
+  // Check whether is an offer with PXEClient or not.\r
+  //\r
+  Option = Options[PXEBC_DHCP4_TAG_INDEX_CLASS_ID];\r
+  if ((Option != NULL) && (Option->Length >= 9) &&\r
+    (NetCompareMem (Option->Data, DEFAULT_CLASS_ID_DATA, 9) == 0)) {\r
+\r
+    CachedPacket->IsPxeOffer = TRUE;\r
+  }\r
+\r
+  //\r
+  // Parse pxe vendor options and store their content/pointers in CachedPacket->PxeVendorOption.\r
+  //\r
+  Option = Options[PXEBC_DHCP4_TAG_INDEX_VENDOR];\r
+  if (CachedPacket->IsPxeOffer && (Option != NULL)) {\r
+\r
+    if (!PxeBcParseVendorOptions (Option, &CachedPacket->PxeVendorOption)) {\r
+      return FALSE;\r
+    }\r
+  }\r
+\r
+  //\r
+  // Check whether bootfilename/serverhostname overloaded (See details in dhcp spec).\r
+  // If overloaded, parse this buffer as nested dhcp options, or just parse bootfilename/\r
+  // serverhostname option.\r
+  //\r
+  Option = Options[PXEBC_DHCP4_TAG_INDEX_OVERLOAD];\r
+  if ((Option != NULL) && (Option->Data[0] & PXEBC_DHCP4_OVERLOAD_FILE)) {\r
+\r
+    Options[PXEBC_DHCP4_TAG_INDEX_BOOTFILE] = PxeBcParseExtendOptions (\r
+                                                (UINT8 *) Offer->Dhcp4.Header.BootFileName,\r
+                                                sizeof (Offer->Dhcp4.Header.BootFileName),\r
+                                                PXEBC_DHCP4_TAG_BOOTFILE\r
+                                                );\r
+\r
+  } else if ((Options[PXEBC_DHCP4_TAG_INDEX_BOOTFILE] == NULL) &&\r
+            (Offer->Dhcp4.Header.BootFileName[0] != 0)) {\r
+    //\r
+    // If the bootfile is not present and bootfilename is present in dhcp packet, just parse it.\r
+    // And do not count dhcp option header, or else will destory the serverhostname.\r
+    //\r
+    Options[PXEBC_DHCP4_TAG_INDEX_BOOTFILE] = (EFI_DHCP4_PACKET_OPTION *) (&Offer->Dhcp4.Header.BootFileName[0] -\r
+                                            EFI_FIELD_OFFSET (EFI_DHCP4_PACKET_OPTION, Data[0]));\r
+\r
+  }\r
+\r
+  //\r
+  // Determine offer type of the dhcp packet.\r
+  //\r
+  Option = Options[PXEBC_DHCP4_TAG_INDEX_MSG_TYPE];\r
+  if ((Option == NULL) || (Option->Data[0] == 0)) {\r
+    //\r
+    // It's a bootp offer\r
+    //\r
+    Option = CachedPacket->Dhcp4Option[PXEBC_DHCP4_TAG_INDEX_BOOTFILE];\r
+    if (Option == NULL) {\r
+      //\r
+      // bootp offer without bootfilename, discard it.\r
+      //\r
+      return FALSE;\r
+    }\r
+\r
+    OfferType = DHCP4_PACKET_TYPE_BOOTP;\r
+\r
+  } else {\r
+\r
+    if (IS_VALID_DISCOVER_VENDOR_OPTION (CachedPacket->PxeVendorOption.BitMap)) {\r
+      //\r
+      // It's a pxe10 offer with PXEClient and discover vendor option.\r
+      //\r
+      OfferType = DHCP4_PACKET_TYPE_PXE10;\r
+    } else if (IS_VALID_MTFTP_VENDOR_OPTION (CachedPacket->PxeVendorOption.BitMap)) {\r
+      //\r
+      // It's a wfm11a offer with PXEClient and mtftp vendor option, and\r
+      // return false since mtftp not supported currently.\r
+      //\r
+      return FALSE;\r
+#if 0\r
+      //\r
+      // WFM11A, make sure bootfile is present\r
+      //\r
+      if (CachedPacket->Dhcp4Option[PXEBC_DHCP4_TAG_INDEX_BOOTFILE] == NULL) {\r
+        //\r
+        // Discard this offer.\r
+        //\r
+        return ;\r
+      }\r
+\r
+      OfferType = DHCP4_PACKET_TYPE_WFM11A;\r
+#endif\r
+    } else {\r
+      //\r
+      // If the binl offer with only PXEClient.\r
+      //\r
+      OfferType = (UINT8) ((CachedPacket->IsPxeOffer) ? DHCP4_PACKET_TYPE_BINL : DHCP4_PACKET_TYPE_DHCP_ONLY);\r
+    }\r
+  }\r
+\r
+  CachedPacket->OfferType = OfferType;\r
+\r
+  return TRUE;\r
+}\r
+\r
+\r
+/**\r
+  GC_NOTO: Add function description\r
+\r
+  @param  Private               GC_NOTO: add argument description\r
+  @param  Index                 GC_NOTO: add argument description\r
+\r
+  @return GC_NOTO: add return values\r
+\r
+**/\r
+BOOLEAN\r
+PxeBcTryBinl (\r
+  IN PXEBC_PRIVATE_DATA  *Private,\r
+  IN UINT32              Index\r
+  )\r
+{\r
+  EFI_DHCP4_PACKET          *Offer;\r
+  EFI_IP_ADDRESS            ServerIp;\r
+  EFI_STATUS                Status;\r
+  PXEBC_CACHED_DHCP4_PACKET *CachedPacket;\r
+  EFI_DHCP4_PACKET          *Reply;\r
+\r
+  ASSERT (Private->Dhcp4Offers[Index].OfferType == DHCP4_PACKET_TYPE_BINL);\r
+\r
+  Offer = &Private->Dhcp4Offers[Index].Packet.Offer;\r
+  if (Offer->Dhcp4.Header.ServerAddr.Addr[0] == 0) {\r
+    //\r
+    // next server ip address is zero, use server id option instead.\r
+    //\r
+    NetCopyMem (\r
+      &ServerIp.Addr[0],\r
+      Private->Dhcp4Offers[Index].Dhcp4Option[PXEBC_DHCP4_TAG_INDEX_SERVER_ID]->Data,\r
+      sizeof (EFI_IPv4_ADDRESS)\r
+      );\r
+  } else {\r
+    //\r
+    // use next server ip address.\r
+    //\r
+    NetCopyMem (&ServerIp.Addr[0], &Offer->Dhcp4.Header.ServerAddr, sizeof (EFI_IPv4_ADDRESS));\r
+  }\r
+\r
+  CachedPacket = &Private->ProxyOffer;\r
+  Reply        = &CachedPacket->Packet.Offer;\r
+\r
+  Status = PxeBcDiscvBootService (\r
+            Private,\r
+            0,\r
+            NULL,\r
+            FALSE,\r
+            &ServerIp,\r
+            0,\r
+            NULL,\r
+            FALSE,\r
+            Reply\r
+            );\r
+  if (EFI_ERROR (Status)) {\r
+    return FALSE;\r
+  }\r
+\r
+  if (!PxeBcParseCachedDhcpPacket (CachedPacket)) {\r
+    return FALSE;\r
+  }\r
+\r
+  if ((CachedPacket->OfferType != DHCP4_PACKET_TYPE_PXE10) &&\r
+      (CachedPacket->Dhcp4Option[PXEBC_DHCP4_TAG_INDEX_BOOTFILE] == NULL)) {\r
+    //\r
+    // This BINL ack doesn't have discovery options set or bootfile name\r
+    // specified.\r
+    //\r
+    return FALSE;\r
+  }\r
+\r
+  Private->PxeBc.Mode->ProxyOfferReceived = TRUE;\r
+  NetCopyMem (&Private->PxeBc.Mode->ProxyOffer, &Reply->Dhcp4, Reply->Length);\r
+\r
+  return TRUE;\r
+}\r
+\r
+\r
+/**\r
+  GC_NOTO: Add function description\r
+\r
+  @param  Private               GC_NOTO: add argument description\r
+  @param  OfferIndex            GC_NOTO: add argument description\r
+\r
+  @return GC_NOTO: add return values\r
+\r
+**/\r
+BOOLEAN\r
+PxeBcTryBinlProxy (\r
+  IN  PXEBC_PRIVATE_DATA  *Private,\r
+  OUT UINT32              *OfferIndex\r
+  )\r
+{\r
+  UINT32  Index;\r
+\r
+  for (Index = 0; Index < Private->ProxyIndex[DHCP4_PACKET_TYPE_BINL]; Index++) {\r
+\r
+    *OfferIndex = Private->BinlIndex[Index];\r
+    //\r
+    // Try this BINL proxy offer\r
+    //\r
+    if (PxeBcTryBinl (Private, *OfferIndex)) {\r
+      return TRUE;\r
+    }\r
+  }\r
+\r
+  return FALSE;\r
+}\r
+\r
+\r
+/**\r
+  GC_NOTO: Add function description\r
+\r
+  @param  Private               GC_NOTO: add argument description\r
+\r
+  @return GC_NOTO: add return values\r
+\r
+**/\r
+EFI_STATUS\r
+PxeBcCheckSelectedOffer (\r
+  IN PXEBC_PRIVATE_DATA  *Private\r
+  )\r
+{\r
+  PXEBC_CACHED_DHCP4_PACKET *SelectedOffer;\r
+  EFI_DHCP4_PACKET_OPTION   **Options;\r
+  UINT32                    Index;\r
+  EFI_DHCP4_PACKET          *Offer;\r
+  UINT32                    ProxyOfferIndex;\r
+  EFI_STATUS                Status;\r
+  EFI_PXE_BASE_CODE_MODE    *Mode;\r
+  EFI_DHCP4_PACKET          *Ack;\r
+\r
+  ASSERT (Private->SelectedOffer != 0);\r
+\r
+  Status        = EFI_SUCCESS;\r
+  SelectedOffer = &Private->Dhcp4Offers[Private->SelectedOffer - 1];\r
+  Options       = SelectedOffer->Dhcp4Option;\r
+\r
+  if (SelectedOffer->OfferType == DHCP4_PACKET_TYPE_BINL) {\r
+    //\r
+    // The addresses are acquired from a BINL dhcp offer, try BINL to get\r
+    // the bootfile name\r
+    //\r
+    if (!PxeBcTryBinl (Private, Private->SelectedOffer - 1)) {\r
+      Status = EFI_NO_RESPONSE;\r
+    }\r
+  } else if ((SelectedOffer->OfferType == DHCP4_PACKET_TYPE_DHCP_ONLY) &&\r
+           (Options[PXEBC_DHCP4_TAG_INDEX_BOOTFILE] == NULL)) {\r
+    //\r
+    // The selected offer to finish the D.O.R.A. is a DHCP only offer and\r
+    // bootfile name is not provided in this offer, we need try proxy offers\r
+    // to get the bootfile name or the discovery info\r
+    //\r
+    ProxyOfferIndex = Private->NumOffers;\r
+\r
+    if (Private->SortOffers) {\r
+      //\r
+      // Choose proxy offer from the type we stored during DHCP offer selection\r
+      //\r
+      ASSERT (Private->ProxyIndex[Private->ProxyOfferType] > 0);\r
+\r
+      if (Private->ProxyOfferType == DHCP4_PACKET_TYPE_BINL) {\r
+        //\r
+        // We buffer all received BINL proxy offers, try them all one by one\r
+        //\r
+        if (!PxeBcTryBinlProxy (Private, &ProxyOfferIndex)) {\r
+          Status = EFI_NO_RESPONSE;\r
+        }\r
+      } else {\r
+        //\r
+        // For other types, only one proxy offer is buffered.\r
+        //\r
+        ProxyOfferIndex = Private->ProxyIndex[Private->ProxyOfferType] - 1;\r
+      }\r
+    } else {\r
+      //\r
+      // Choose proxy offer in the received order.\r
+      //\r
+      Status = EFI_NO_RESPONSE;\r
+\r
+      for (Index = 0; Index < Private->NumOffers; Index++) {\r
+\r
+        Offer = &Private->Dhcp4Offers[Index].Packet.Offer;\r
+        if (!IS_PROXY_DHCP_OFFER (Offer)) {\r
+          //\r
+          // Skip non proxy dhcp offers.\r
+          //\r
+          continue;\r
+        }\r
+\r
+        if (Private->Dhcp4Offers[Index].OfferType == DHCP4_PACKET_TYPE_BINL) {\r
+          //\r
+          // Try BINL\r
+          //\r
+          if (!PxeBcTryBinl (Private, Index)) {\r
+            //\r
+            // Failed, skip to the next offer\r
+            //\r
+            continue;\r
+          }\r
+        }\r
+\r
+        Status = EFI_SUCCESS;\r
+        break;\r
+      }\r
+    }\r
+\r
+    if (!EFI_ERROR (Status) && (Private->ProxyOfferType != DHCP4_PACKET_TYPE_BINL)) {\r
+      //\r
+      // Copy the proxy offer to Mode and set the flag\r
+      //\r
+      PxeBcCopyProxyOffer (Private, ProxyOfferIndex);\r
+    }\r
+  }\r
+\r
+  if (!EFI_ERROR (Status)) {\r
+    //\r
+    // Everything is OK, set the flag and copy the DHCP packets.\r
+    //\r
+    Mode  = Private->PxeBc.Mode;\r
+    Offer = &SelectedOffer->Packet.Offer;\r
+\r
+    //\r
+    // The discover packet is already copied, just set flag here.\r
+    //\r
+    Mode->DhcpDiscoverValid = TRUE;\r
+\r
+    Ack                     = &Private->Dhcp4Ack.Packet.Ack;\r
+    if (SelectedOffer->OfferType == DHCP4_PACKET_TYPE_BOOTP) {\r
+      //\r
+      // Other type of ACK is already cached. Bootp is special that we should\r
+      // use the bootp reply as the ACK and put it into the DHCP_ONLY buffer.\r
+      //\r
+      PxeBcCopyEfiDhcp4Packet (&Private->Dhcp4Ack.Packet.Ack, Offer);\r
+    }\r
+\r
+    PxeBcParseCachedDhcpPacket (&Private->Dhcp4Ack);\r
+\r
+    Mode->DhcpAckReceived = TRUE;\r
+\r
+    //\r
+    // Copy the dhcp ack.\r
+    //\r
+    NetCopyMem (&Mode->DhcpAck, &Ack->Dhcp4, Ack->Length);\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  GC_NOTO: Add function description\r
+\r
+  @param  Private               GC_NOTO: add argument description\r
+  @param  RcvdOffer             GC_NOTO: add argument description\r
+\r
+  @return GC_NOTO: add return values\r
+\r
+**/\r
+VOID\r
+PxeBcCacheDhcpOffer (\r
+  IN PXEBC_PRIVATE_DATA  *Private,\r
+  IN EFI_DHCP4_PACKET    *RcvdOffer\r
+  )\r
+{\r
+  PXEBC_CACHED_DHCP4_PACKET *CachedOffer;\r
+  EFI_DHCP4_PACKET          *Offer;\r
+  UINT8                     OfferType;\r
+\r
+  CachedOffer = &Private->Dhcp4Offers[Private->NumOffers];\r
+  Offer       = &CachedOffer->Packet.Offer;\r
+\r
+  //\r
+  // Cache the orignal dhcp packet\r
+  //\r
+  PxeBcCopyEfiDhcp4Packet (Offer, RcvdOffer);\r
+\r
+  //\r
+  // Parse and validate the options (including dhcp option and vendor option)\r
+  //\r
+  if (!PxeBcParseCachedDhcpPacket (CachedOffer)) {\r
+    return ;\r
+  }\r
+\r
+  OfferType = CachedOffer->OfferType;\r
+\r
+  if (OfferType == DHCP4_PACKET_TYPE_BOOTP) {\r
+\r
+    if (Private->BootpIndex != 0) {\r
+      //\r
+      // Only cache the first bootp offer, discard others.\r
+      //\r
+      return ;\r
+    } else {\r
+      //\r
+      // Take as a dhcp only offer, but record index specifically.\r
+      //\r
+      Private->BootpIndex = Private->NumOffers + 1;\r
+    }\r
+  } else {\r
+\r
+    if (IS_PROXY_DHCP_OFFER (Offer)) {\r
+      //\r
+      // It's a proxy dhcp offer with no your address, including pxe10, wfm11a or binl offer.\r
+      //\r
+      if (OfferType == DHCP4_PACKET_TYPE_BINL) {\r
+        //\r
+        // Cache all binl offers.\r
+        //\r
+        Private->BinlIndex[Private->ProxyIndex[DHCP4_PACKET_TYPE_BINL]] = Private->NumOffers;\r
+        Private->ProxyIndex[DHCP4_PACKET_TYPE_BINL]++;\r
+      } else if (Private->ProxyIndex[OfferType] != 0) {\r
+        //\r
+        // Only cache the first pxe10/wfm11a offers each, discard the others.\r
+        //\r
+        return ;\r
+      } else {\r
+        //\r
+        // Record index of the proxy dhcp offer with type other than binl.\r
+        //\r
+        Private->ProxyIndex[OfferType] = Private->NumOffers + 1;\r
+      }\r
+    } else {\r
+      //\r
+      // It's a dhcp offer with your address.\r
+      //\r
+      Private->OfferIndex[OfferType][Private->ServerCount[OfferType]] = Private->NumOffers;\r
+      Private->ServerCount[OfferType]++;\r
+    }\r
+  }\r
+\r
+  //\r
+  // Count the accepted offers.\r
+  //\r
+  Private->NumOffers++;\r
+}\r
+\r
+\r
+/**\r
+  GC_NOTO: Add function description\r
+\r
+  @param  Private               GC_NOTO: add argument description\r
+\r
+  @return GC_NOTO: add return values\r
+\r
+**/\r
+VOID\r
+PxeBcSelectOffer (\r
+  IN PXEBC_PRIVATE_DATA  *Private\r
+  )\r
+{\r
+  UINT32            Index;\r
+  UINT32            OfferIndex;\r
+  EFI_DHCP4_PACKET  *Offer;\r
+  BOOLEAN           GotProxyOffer;\r
+\r
+  Private->SelectedOffer = 0;\r
+\r
+  if (Private->SortOffers) {\r
+    //\r
+    // Select offer according to the priority\r
+    //\r
+    if (Private->ServerCount[DHCP4_PACKET_TYPE_PXE10] > 0) {\r
+      //\r
+      // DHCP with PXE10\r
+      //\r
+      Private->SelectedOffer = Private->OfferIndex[DHCP4_PACKET_TYPE_PXE10][0] + 1;\r
+\r
+    } else if (Private->ServerCount[DHCP4_PACKET_TYPE_WFM11A] > 0) {\r
+      //\r
+      // DHCP with WfM\r
+      //\r
+      Private->SelectedOffer = Private->OfferIndex[DHCP4_PACKET_TYPE_WFM11A][0] + 1;\r
+\r
+    } else if ((Private->ProxyIndex[DHCP4_PACKET_TYPE_PXE10] > 0) &&\r
+             (Private->ServerCount[DHCP4_PACKET_TYPE_DHCP_ONLY] > 0)\r
+            ) {\r
+      //\r
+      // DHCP only and proxy DHCP with PXE10\r
+      //\r
+      Private->SelectedOffer = Private->OfferIndex[DHCP4_PACKET_TYPE_DHCP_ONLY][0] + 1;\r
+      Private->ProxyOfferType     = DHCP4_PACKET_TYPE_PXE10;\r
+\r
+    } else if ((Private->ProxyIndex[DHCP4_PACKET_TYPE_WFM11A] > 0) &&\r
+             (Private->ServerCount[DHCP4_PACKET_TYPE_DHCP_ONLY] > 0)\r
+            ) {\r
+      //\r
+      // DHCP only and proxy DHCP with WfM\r
+      //\r
+      Private->SelectedOffer = Private->OfferIndex[DHCP4_PACKET_TYPE_DHCP_ONLY][0] + 1;\r
+      Private->ProxyOfferType     = DHCP4_PACKET_TYPE_WFM11A;\r
+\r
+    } else if (Private->ServerCount[DHCP4_PACKET_TYPE_BINL] > 0) {\r
+      //\r
+      // DHCP with BINL\r
+      //\r
+      Private->SelectedOffer = Private->OfferIndex[DHCP4_PACKET_TYPE_BINL][0] + 1;\r
+\r
+    } else if ((Private->ProxyIndex[DHCP4_PACKET_TYPE_BINL] > 0) &&\r
+             (Private->ServerCount[DHCP4_PACKET_TYPE_DHCP_ONLY] > 0)\r
+            ) {\r
+      //\r
+      // DHCP only and proxy DHCP with BINL\r
+      //\r
+      Private->SelectedOffer = Private->OfferIndex[DHCP4_PACKET_TYPE_DHCP_ONLY][0] + 1;\r
+      Private->ProxyOfferType     = DHCP4_PACKET_TYPE_BINL;\r
+\r
+    } else {\r
+      //\r
+      // Try offers with bootfile\r
+      //\r
+      for (Index = 0; Index < Private->ServerCount[DHCP4_PACKET_TYPE_DHCP_ONLY]; Index++) {\r
+        //\r
+        // Select the first DHCP only offer with bootfile\r
+        //\r
+        OfferIndex = Private->OfferIndex[DHCP4_PACKET_TYPE_DHCP_ONLY][Index];\r
+        if (Private->Dhcp4Offers[OfferIndex].Dhcp4Option[PXEBC_DHCP4_TAG_INDEX_BOOTFILE] != NULL) {\r
+          Private->SelectedOffer = OfferIndex + 1;\r
+          break;\r
+        }\r
+      }\r
+\r
+      if (Private->SelectedOffer == 0) {\r
+        //\r
+        // Select the Bootp reply with bootfile if any\r
+        //\r
+        Private->SelectedOffer = Private->BootpIndex;\r
+      }\r
+    }\r
+  } else {\r
+    //\r
+    // Try the offers in the received order.\r
+    //\r
+    GotProxyOffer = FALSE;\r
+    for (Index = 0; Index < DHCP4_PACKET_TYPE_MAX; Index++) {\r
+\r
+      GotProxyOffer = (BOOLEAN) (Private->ProxyIndex[Index] > 0);\r
+      if (GotProxyOffer) {\r
+        break;\r
+      }\r
+    }\r
+\r
+    for (Index = 0; Index < Private->NumOffers; Index++) {\r
+\r
+      Offer = &Private->Dhcp4Offers[Index].Packet.Offer;\r
+\r
+      if (IS_PROXY_DHCP_OFFER (Offer)) {\r
+        //\r
+        // Skip proxy offers\r
+        //\r
+        continue;\r
+      }\r
+\r
+      if ((Private->Dhcp4Offers[Index].OfferType == DHCP4_PACKET_TYPE_DHCP_ONLY) &&\r
+          ((!GotProxyOffer) && (Private->Dhcp4Offers[Index].Dhcp4Option[PXEBC_DHCP4_TAG_INDEX_BOOTFILE] == NULL))) {\r
+        //\r
+        // DHCP only offer but no proxy offer received and no bootfile option in this offer\r
+        //\r
+        continue;\r
+      }\r
+\r
+      Private->SelectedOffer = Index + 1;\r
+      break;\r
+    }\r
+  }\r
+}\r
+\r
+\r
+/**\r
+  GC_NOTO: Add function description\r
+\r
+  @param  This                  GC_NOTO: add argument description\r
+  @param  Context               GC_NOTO: add argument description\r
+  @param  CurrentState          GC_NOTO: add argument description\r
+  @param  Dhcp4Event            GC_NOTO: add argument description\r
+  @param  Packet                GC_NOTO: add argument description\r
+  @param  NewPacket             GC_NOTO: add argument description\r
+\r
+  @retval EFI_SUCCESS           GC_NOTO: Add description for return value\r
+  @retval EFI_ABORTED           GC_NOTO: Add description for return value\r
+\r
+**/\r
+EFI_STATUS\r
+PxeBcDhcpCallBack (\r
+  IN EFI_DHCP4_PROTOCOL                * This,\r
+  IN VOID                              *Context,\r
+  IN EFI_DHCP4_STATE                   CurrentState,\r
+  IN EFI_DHCP4_EVENT                   Dhcp4Event,\r
+  IN EFI_DHCP4_PACKET                  * Packet OPTIONAL,\r
+  OUT EFI_DHCP4_PACKET                 **NewPacket OPTIONAL\r
+  )\r
+{\r
+  PXEBC_PRIVATE_DATA                  *Private;\r
+  EFI_PXE_BASE_CODE_MODE              *Mode;\r
+  EFI_PXE_BASE_CODE_CALLBACK_PROTOCOL *Callback;\r
+  EFI_DHCP4_PACKET_OPTION             *MaxMsgSize;\r
+  UINT16                              Value;\r
+  EFI_STATUS                          Status;\r
+  BOOLEAN                             Received;\r
+\r
+  if ((Dhcp4Event != Dhcp4RcvdOffer) &&\r
+      (Dhcp4Event != Dhcp4SelectOffer) &&\r
+      (Dhcp4Event != Dhcp4SendDiscover) &&\r
+      (Dhcp4Event != Dhcp4RcvdAck)) {\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  Private   = (PXEBC_PRIVATE_DATA *) Context;\r
+  Mode      = Private->PxeBc.Mode;\r
+  Callback  = Private->PxeBcCallback;\r
+\r
+  //\r
+  // Override the Maximum DHCP Message Size.\r
+  //\r
+  MaxMsgSize = PxeBcParseExtendOptions (\r
+                Packet->Dhcp4.Option,\r
+                GET_OPTION_BUFFER_LEN (Packet),\r
+                PXEBC_DHCP4_TAG_MAXMSG\r
+                );\r
+  if (MaxMsgSize != NULL) {\r
+    Value = HTONS (PXEBC_DHCP4_MAX_PACKET_SIZE);\r
+    NetCopyMem (MaxMsgSize->Data, &Value, sizeof (Value));\r
+  }\r
+\r
+  if ((Dhcp4Event != Dhcp4SelectOffer) && (Callback != NULL)) {\r
+    Received = (BOOLEAN) ((Dhcp4Event == Dhcp4RcvdOffer) || (Dhcp4Event == Dhcp4RcvdAck));\r
+    Status = Callback->Callback (\r
+                        Callback,\r
+                        Private->Function,\r
+                        Received,\r
+                        Packet->Length,\r
+                        (EFI_PXE_BASE_CODE_PACKET *) &Packet->Dhcp4\r
+                        );\r
+    if (Status != EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE) {\r
+      return EFI_ABORTED;\r
+    }\r
+  }\r
+\r
+  Status = EFI_SUCCESS;\r
+\r
+  switch (Dhcp4Event) {\r
+\r
+  case Dhcp4SendDiscover:\r
+    //\r
+    // Cache the dhcp discover packet, of which some information will be used later.\r
+    //\r
+    NetCopyMem (Mode->DhcpDiscover.Raw, &Packet->Dhcp4, Packet->Length);\r
+\r
+    break;\r
+\r
+  case Dhcp4RcvdOffer:\r
+    Status = EFI_NOT_READY;\r
+    if (Private->NumOffers < PXEBC_MAX_OFFER_NUM) {\r
+      //\r
+      // Cache the dhcp offers in Private->Dhcp4Offers[]\r
+      //\r
+      PxeBcCacheDhcpOffer (Private, Packet);\r
+    }\r
+\r
+    break;\r
+\r
+  case Dhcp4SelectOffer:\r
+    //\r
+    // Select an offer, if succeeded, Private->SelectedOffer points to\r
+    // the index of the selected one.\r
+    //\r
+    PxeBcSelectOffer (Private);\r
+\r
+    if (Private->SelectedOffer == 0) {\r
+      Status = EFI_ABORTED;\r
+    } else {\r
+      *NewPacket = &Private->Dhcp4Offers[Private->SelectedOffer - 1].Packet.Offer;\r
+    }\r
+\r
+    break;\r
+\r
+  case Dhcp4RcvdAck:\r
+    //\r
+    // Cache Ack\r
+    //\r
+    ASSERT (Private->SelectedOffer != 0);\r
+\r
+    PxeBcCopyEfiDhcp4Packet (&Private->Dhcp4Ack.Packet.Ack, Packet);\r
+    break;\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  GC_NOTO: Add function description\r
+\r
+  @param  Private               GC_NOTO: add argument description\r
+  @param  OptList               GC_NOTO: add argument description\r
+  @param  IsDhcpDiscover        GC_NOTO: add argument description\r
+\r
+  @return GC_NOTO: add return values\r
+\r
+**/\r
+UINT32\r
+PxeBcBuildDhcpOptions (\r
+  IN PXEBC_PRIVATE_DATA            *Private,\r
+  IN EFI_DHCP4_PACKET_OPTION       **OptList,\r
+  IN BOOLEAN                       IsDhcpDiscover\r
+  )\r
+{\r
+  UINT32                    Index;\r
+  PXEBC_DHCP4_OPTION_ENTRY  OptEnt;\r
+  UINT16                    Value;\r
+  CHAR8                     *SystemSerialNumber;\r
+\r
+  Index       = 0;\r
+  OptList[0]  = (EFI_DHCP4_PACKET_OPTION *) Private->OptionBuffer;\r
+\r
+  if (!IsDhcpDiscover) {\r
+    //\r
+    // Append message type.\r
+    //\r
+    OptList[Index]->OpCode  = PXEBC_DHCP4_TAG_MSG_TYPE;\r
+    OptList[Index]->Length  = 1;\r
+    OptEnt.Mesg             = (PXEBC_DHCP4_OPTION_MESG *) OptList[Index]->Data;\r
+    OptEnt.Mesg->Type       = PXEBC_DHCP4_MSG_TYPE_REQUEST;\r
+    Index++;\r
+    OptList[Index]          = GET_NEXT_DHCP_OPTION (OptList[Index - 1]);\r
+\r
+    //\r
+    // Append max message size.\r
+    //\r
+    OptList[Index]->OpCode  = PXEBC_DHCP4_TAG_MAXMSG;\r
+    OptList[Index]->Length  = sizeof (PXEBC_DHCP4_OPTION_MAX_MESG_SIZE);\r
+    OptEnt.MaxMesgSize      = (PXEBC_DHCP4_OPTION_MAX_MESG_SIZE *) OptList[Index]->Data;\r
+    Value                   = NTOHS (PXEBC_DHCP4_MAX_PACKET_SIZE);\r
+    NetCopyMem (&OptEnt.MaxMesgSize->Size, &Value, sizeof (UINT16));\r
+    Index++;\r
+    OptList[Index]          = GET_NEXT_DHCP_OPTION (OptList[Index - 1]);\r
+  }\r
+  //\r
+  // Parameter request list option.\r
+  //\r
+  OptList[Index]->OpCode    = PXEBC_DHCP4_TAG_PARA_LIST;\r
+  OptList[Index]->Length    = 35;\r
+  OptEnt.Para               = (PXEBC_DHCP4_OPTION_PARA *) OptList[Index]->Data;\r
+  OptEnt.Para->ParaList[0]  = PXEBC_DHCP4_TAG_NETMASK;\r
+  OptEnt.Para->ParaList[1]  = PXEBC_DHCP4_TAG_TIME_OFFSET;\r
+  OptEnt.Para->ParaList[2]  = PXEBC_DHCP4_TAG_ROUTER;\r
+  OptEnt.Para->ParaList[3]  = PXEBC_DHCP4_TAG_TIME_SERVER;\r
+  OptEnt.Para->ParaList[4]  = PXEBC_DHCP4_TAG_NAME_SERVER;\r
+  OptEnt.Para->ParaList[5]  = PXEBC_DHCP4_TAG_DNS_SERVER;\r
+  OptEnt.Para->ParaList[6]  = PXEBC_DHCP4_TAG_HOSTNAME;\r
+  OptEnt.Para->ParaList[7]  = PXEBC_DHCP4_TAG_BOOTFILE_LEN;\r
+  OptEnt.Para->ParaList[8]  = PXEBC_DHCP4_TAG_DOMAINNAME;\r
+  OptEnt.Para->ParaList[9]  = PXEBC_DHCP4_TAG_ROOTPATH;\r
+  OptEnt.Para->ParaList[10] = PXEBC_DHCP4_TAG_EXTEND_PATH;\r
+  OptEnt.Para->ParaList[11] = PXEBC_DHCP4_TAG_EMTU;\r
+  OptEnt.Para->ParaList[12] = PXEBC_DHCP4_TAG_TTL;\r
+  OptEnt.Para->ParaList[13] = PXEBC_DHCP4_TAG_BROADCAST;\r
+  OptEnt.Para->ParaList[14] = PXEBC_DHCP4_TAG_NIS_DOMAIN;\r
+  OptEnt.Para->ParaList[15] = PXEBC_DHCP4_TAG_NIS_SERVER;\r
+  OptEnt.Para->ParaList[16] = PXEBC_DHCP4_TAG_NTP_SERVER;\r
+  OptEnt.Para->ParaList[17] = PXEBC_DHCP4_TAG_VENDOR;\r
+  OptEnt.Para->ParaList[18] = PXEBC_DHCP4_TAG_REQUEST_IP;\r
+  OptEnt.Para->ParaList[19] = PXEBC_DHCP4_TAG_LEASE;\r
+  OptEnt.Para->ParaList[20] = PXEBC_DHCP4_TAG_SERVER_ID;\r
+  OptEnt.Para->ParaList[21] = PXEBC_DHCP4_TAG_T1;\r
+  OptEnt.Para->ParaList[22] = PXEBC_DHCP4_TAG_T2;\r
+  OptEnt.Para->ParaList[23] = PXEBC_DHCP4_TAG_CLASS_ID;\r
+  OptEnt.Para->ParaList[24] = PXEBC_DHCP4_TAG_TFTP;\r
+  OptEnt.Para->ParaList[25] = PXEBC_DHCP4_TAG_BOOTFILE;\r
+  OptEnt.Para->ParaList[26] = PXEBC_PXE_DHCP4_TAG_UUID;\r
+  OptEnt.Para->ParaList[27] = 0x80;\r
+  OptEnt.Para->ParaList[28] = 0x81;\r
+  OptEnt.Para->ParaList[29] = 0x82;\r
+  OptEnt.Para->ParaList[30] = 0x83;\r
+  OptEnt.Para->ParaList[31] = 0x84;\r
+  OptEnt.Para->ParaList[32] = 0x85;\r
+  OptEnt.Para->ParaList[33] = 0x86;\r
+  OptEnt.Para->ParaList[34] = 0x87;\r
+  Index++;\r
+  OptList[Index]            = GET_NEXT_DHCP_OPTION (OptList[Index - 1]);\r
+\r
+  //\r
+  // Append UUID/Guid-based client identifier option\r
+  //\r
+  OptList[Index]->OpCode  = PXEBC_PXE_DHCP4_TAG_UUID;\r
+  OptList[Index]->Length  = sizeof (PXEBC_DHCP4_OPTION_UUID);\r
+  OptEnt.Uuid             = (PXEBC_DHCP4_OPTION_UUID *) OptList[Index]->Data;\r
+  OptEnt.Uuid->Type       = 0;\r
+  Index++;\r
+  OptList[Index]          = GET_NEXT_DHCP_OPTION (OptList[Index - 1]);\r
+\r
+  if (EFI_ERROR (GetSmbiosSystemGuidAndSerialNumber ((EFI_GUID *) OptEnt.Uuid->Guid, &SystemSerialNumber))) {\r
+    //\r
+    // GUID not yet set - send all 0xff's to show programable (via SetVariable)\r
+    // SetMem(DHCPV4_OPTIONS_BUFFER.DhcpPlatformId.Guid, sizeof(EFI_GUID), 0xff);\r
+    // GUID not yet set - send all 0's to show not programable\r
+    //\r
+    ZeroMem (OptEnt.Uuid->Guid, sizeof (EFI_GUID));\r
+  }\r
+\r
+  //\r
+  // Append client network device interface option\r
+  //\r
+  OptList[Index]->OpCode  = PXEBC_PXE_DHCP4_TAG_UNDI;\r
+  OptList[Index]->Length  = sizeof (PXEBC_DHCP4_OPTION_UNDI);\r
+  OptEnt.Undi             = (PXEBC_DHCP4_OPTION_UNDI *) OptList[Index]->Data;\r
+  OptEnt.Undi->Type       = Private->Nii->Type;\r
+  OptEnt.Undi->MajorVer   = Private->Nii->MajorVer;\r
+  OptEnt.Undi->MinorVer   = Private->Nii->MinorVer;\r
+\r
+  Index++;\r
+  OptList[Index] = GET_NEXT_DHCP_OPTION (OptList[Index - 1]);\r
+\r
+  //\r
+  // Append client system architecture option\r
+  //\r
+  OptList[Index]->OpCode  = PXEBC_PXE_DHCP4_TAG_ARCH;\r
+  OptList[Index]->Length  = sizeof (PXEBC_DHCP4_OPTION_ARCH);\r
+  OptEnt.Arch             = (PXEBC_DHCP4_OPTION_ARCH *) OptList[Index]->Data;\r
+  Value                   = HTONS (SYS_ARCH);\r
+  NetCopyMem (&OptEnt.Arch->Type, &Value, sizeof (UINT16));\r
+  Index++;\r
+  OptList[Index]          = GET_NEXT_DHCP_OPTION (OptList[Index - 1]);\r
+\r
+  //\r
+  // Append client system architecture option\r
+  //\r
+  OptList[Index]->OpCode  = PXEBC_DHCP4_TAG_CLASS_ID;\r
+  OptList[Index]->Length  = sizeof (PXEBC_DHCP4_OPTION_CLID);\r
+  OptEnt.Clid             = (PXEBC_DHCP4_OPTION_CLID *) OptList[Index]->Data;\r
+  NetCopyMem (OptEnt.Clid, DEFAULT_CLASS_ID_DATA, sizeof (PXEBC_DHCP4_OPTION_CLID));\r
+  CvtNum (SYS_ARCH, OptEnt.Clid->ArchitectureType, sizeof (OptEnt.Clid->ArchitectureType));\r
+  NetCopyMem (OptEnt.Clid->InterfaceName, Private->Nii->StringId, sizeof (OptEnt.Clid->InterfaceName));\r
+  CvtNum (Private->Nii->MajorVer, OptEnt.Clid->UndiMajor, sizeof (OptEnt.Clid->UndiMajor));\r
+  CvtNum (Private->Nii->MinorVer, OptEnt.Clid->UndiMinor, sizeof (OptEnt.Clid->UndiMinor));\r
+  Index++;\r
+\r
+  return Index;\r
+}\r
+\r
+\r
+/**\r
+  GC_NOTO: Add function description\r
+\r
+  @param  Private               GC_NOTO: add argument description\r
+  @param  Type                  GC_NOTO: add argument description\r
+  @param  Layer                 GC_NOTO: add argument description\r
+  @param  UseBis                GC_NOTO: add argument description\r
+  @param  DestIp                GC_NOTO: add argument description\r
+  @param  IpCount               GC_NOTO: add argument description\r
+  @param  SrvList               GC_NOTO: add argument description\r
+  @param  IsDiscv               GC_NOTO: add argument description\r
+  @param  Reply                 GC_NOTO: add argument description\r
+\r
+  @retval EFI_OUT_OF_RESOURCES  GC_NOTO: Add description for return value\r
+\r
+**/\r
+EFI_STATUS\r
+PxeBcDiscvBootService (\r
+  IN PXEBC_PRIVATE_DATA                * Private,\r
+  IN UINT16                            Type,\r
+  IN UINT16                            *Layer,\r
+  IN BOOLEAN                           UseBis,\r
+  IN EFI_IP_ADDRESS                    * DestIp,\r
+  IN UINT16                            IpCount,\r
+  IN EFI_PXE_BASE_CODE_SRVLIST         * SrvList,\r
+  IN BOOLEAN                           IsDiscv,\r
+  OUT EFI_DHCP4_PACKET                 * Reply OPTIONAL\r
+  )\r
+{\r
+  EFI_PXE_BASE_CODE_UDP_PORT          Sport;\r
+  EFI_PXE_BASE_CODE_MODE              *Mode;\r
+  EFI_DHCP4_PROTOCOL                  *Dhcp4;\r
+  EFI_DHCP4_TRANSMIT_RECEIVE_TOKEN    Token;\r
+  BOOLEAN                             IsBCast;\r
+  EFI_STATUS                          Status;\r
+  UINT16                              RepIndex;\r
+  UINT16                              SrvIndex;\r
+  UINT16                              TryIndex;\r
+  EFI_DHCP4_LISTEN_POINT              ListenPoint;\r
+  EFI_DHCP4_PACKET                    *Response;\r
+  EFI_DHCP4_PACKET_OPTION             *OptList[PXEBC_DHCP4_MAX_OPTION_NUM];\r
+  UINT32                              OptCount;\r
+  EFI_DHCP4_PACKET_OPTION             *PxeOpt;\r
+  PXEBC_OPTION_BOOT_ITEM              *PxeBootItem;\r
+  UINT8                               VendorOptLen;\r
+\r
+  Mode      = Private->PxeBc.Mode;\r
+  Dhcp4     = Private->Dhcp4;\r
+  Status    = EFI_SUCCESS;\r
+\r
+  ZeroMem (&Token, sizeof (EFI_DHCP4_TRANSMIT_RECEIVE_TOKEN));\r
+\r
+  if (DestIp == NULL) {\r
+    Sport   = PXEBC_DHCP4_S_PORT;\r
+    IsBCast = TRUE;\r
+  } else {\r
+    Sport   = PXEBC_BS_DISCOVER_PORT;\r
+    IsBCast = FALSE;\r
+  }\r
+\r
+  if (!UseBis && Layer != NULL) {\r
+    *Layer &= EFI_PXE_BASE_CODE_BOOT_LAYER_MASK;\r
+  }\r
+\r
+  OptCount = PxeBcBuildDhcpOptions (Private, OptList, FALSE);\r
+\r
+  if (IsDiscv) {\r
+    //\r
+    // Add vendor option of PXE_BOOT_ITEM\r
+    //\r
+    VendorOptLen      = (sizeof (EFI_DHCP4_PACKET_OPTION) - 1) * 2 + sizeof (PXEBC_OPTION_BOOT_ITEM) + 1;\r
+    OptList[OptCount] = NetAllocatePool (VendorOptLen);\r
+    if (OptList[OptCount] == NULL) {\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+\r
+    OptList[OptCount]->OpCode     = PXEBC_DHCP4_TAG_VENDOR;\r
+    OptList[OptCount]->Length     = (UINT8) (VendorOptLen - 2);\r
+    PxeOpt                        = (EFI_DHCP4_PACKET_OPTION *) OptList[OptCount]->Data;\r
+    PxeOpt->OpCode                = PXEBC_VENDOR_TAG_BOOT_ITEM;\r
+    PxeOpt->Length                = sizeof (PXEBC_OPTION_BOOT_ITEM);\r
+    PxeBootItem                   = (PXEBC_OPTION_BOOT_ITEM *) PxeOpt->Data;\r
+    PxeBootItem->Type             = HTONS (Type);\r
+    PxeBootItem->Layer            = HTONS (*Layer);\r
+    PxeOpt->Data[PxeOpt->Length]  = PXEBC_DHCP4_TAG_EOP;\r
+\r
+    OptCount++;\r
+  }\r
+\r
+  Status = Dhcp4->Build (Dhcp4, &Private->SeedPacket, 0, NULL, OptCount, OptList, &Token.Packet);\r
+\r
+  if (IsDiscv) {\r
+    NetFreePool (OptList[OptCount - 1]);\r
+  }\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  Token.Packet->Dhcp4.Header.Xid      = NET_RANDOM (NetRandomInitSeed ());\r
+  Token.Packet->Dhcp4.Header.Reserved = (UINT16) ((IsBCast) ? 0xf000 : 0x0);\r
+  NetCopyMem (&Token.Packet->Dhcp4.Header.ClientAddr, &Private->StationIp, sizeof (EFI_IPv4_ADDRESS));\r
+\r
+  Token.RemotePort = Sport;\r
+\r
+  if (DestIp == NULL) {\r
+    NetSetMem (&Token.RemoteAddress, sizeof (EFI_IPv4_ADDRESS), 0xff);\r
+  } else {\r
+    NetCopyMem (&Token.RemoteAddress, DestIp, sizeof (EFI_IPv4_ADDRESS));\r
+  }\r
+\r
+  NetCopyMem (&Token.GatewayAddress, &Private->GatewayIp, sizeof (EFI_IPv4_ADDRESS));\r
+\r
+  if (!IsBCast) {\r
+    Token.ListenPointCount            = 1;\r
+    Token.ListenPoints                = &ListenPoint;\r
+    Token.ListenPoints[0].ListenPort  = PXEBC_BS_DISCOVER_PORT;\r
+    NetCopyMem (&Token.ListenPoints[0].ListenAddress, &Private->StationIp, sizeof(EFI_IPv4_ADDRESS));\r
+    NetCopyMem (&Token.ListenPoints[0].SubnetMask, &Private->SubnetMask, sizeof(EFI_IPv4_ADDRESS));\r
+  }\r
+  //\r
+  // Send Pxe Discover\r
+  //\r
+  for (TryIndex = 1; TryIndex <= PXEBC_BOOT_REQUEST_RETRIES; TryIndex++) {\r
+\r
+    Token.TimeoutValue  = PXEBC_BOOT_REQUEST_TIMEOUT * TryIndex;\r
+\r
+    Status              = Dhcp4->TransmitReceive (Dhcp4, &Token);\r
+\r
+    if (Token.Status != EFI_TIMEOUT) {\r
+      break;\r
+    }\r
+  }\r
+\r
+  if (!EFI_ERROR (Status)) {\r
+    //\r
+    // Find Pxe Reply\r
+    //\r
+    RepIndex  = 0;\r
+    SrvIndex  = 0;\r
+    Response  = Token.ResponseList;\r
+\r
+    while (RepIndex < Token.ResponseCount) {\r
+\r
+      while (SrvIndex < IpCount) {\r
+\r
+        if (SrvList[SrvIndex].AcceptAnyResponse) {\r
+          break;\r
+        }\r
+\r
+        if ((SrvList[SrvIndex].Type == Type) && EFI_IP4_EQUAL (&(Response->Dhcp4.Header.ServerAddr), &(Private->ServerIp))) {\r
+          break;\r
+        }\r
+\r
+        SrvIndex++;\r
+      }\r
+\r
+      if ((IpCount != SrvIndex) || (IpCount == 0)) {\r
+        break;\r
+      }\r
+\r
+      SrvIndex = 0;\r
+      RepIndex++;\r
+\r
+      Response = (EFI_DHCP4_PACKET *) ((UINT8 *) Response + Response->Size);\r
+    }\r
+\r
+    if (RepIndex < Token.ResponseCount) {\r
+\r
+      if (Reply != NULL) {\r
+        PxeBcCopyEfiDhcp4Packet (Reply, Response);\r
+      }\r
+\r
+      if (IsDiscv) {\r
+        NetCopyMem (&(Mode->PxeDiscover), &(Token.Packet->Dhcp4), Token.Packet->Length);\r
+        Mode->PxeDiscoverValid = TRUE;\r
+\r
+        NetCopyMem (Mode->PxeReply.Raw, &Response->Dhcp4, Response->Length);\r
+        Mode->PxeReplyReceived = TRUE;\r
+      }\r
+    } else {\r
+      Status = EFI_NOT_FOUND;\r
+    }\r
+\r
+    //\r
+    // free the responselist\r
+    //\r
+    NetFreePool (Token.ResponseList);\r
+  }\r
+  //\r
+  // Free the dhcp packet\r
+  //\r
+  NetFreePool (Token.Packet);\r
+\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  GC_NOTO: Add function description\r
+\r
+  @param  Buffer                GC_NOTO: add argument description\r
+  @param  Length                GC_NOTO: add argument description\r
+  @param  OptTag                GC_NOTO: add argument description\r
+\r
+  @return GC_NOTO: add return values\r
+\r
+**/\r
+EFI_DHCP4_PACKET_OPTION *\r
+PxeBcParseExtendOptions (\r
+  IN UINT8                         *Buffer,\r
+  IN UINT32                        Length,\r
+  IN UINT8                         OptTag\r
+  )\r
+{\r
+  EFI_DHCP4_PACKET_OPTION *Option;\r
+  UINT32                  Offset;\r
+\r
+  Option  = (EFI_DHCP4_PACKET_OPTION *) Buffer;\r
+  Offset  = 0;\r
+\r
+  while (Offset < Length && Option->OpCode != PXEBC_DHCP4_TAG_EOP) {\r
+\r
+    if (Option->OpCode == OptTag) {\r
+\r
+      return Option;\r
+    }\r
+\r
+    if (Option->OpCode == PXEBC_DHCP4_TAG_PAD) {\r
+      Offset++;\r
+    } else {\r
+      Offset += Option->Length + 2;\r
+    }\r
+\r
+    Option = (EFI_DHCP4_PACKET_OPTION *) (Buffer + Offset);\r
+  }\r
+\r
+  return NULL;\r
+}\r
+\r
+\r
+/**\r
+  This function is to parse and check vendor options.\r
+\r
+  @param  Dhcp4Option           Pointer to dhcp options\r
+  @param  VendorOption          Pointer to vendor options\r
+\r
+  @return TRUE  : Valid vendor options\r
+  @return FALSE : Invalid vendor options\r
+\r
+**/\r
+BOOLEAN\r
+PxeBcParseVendorOptions (\r
+  IN EFI_DHCP4_PACKET_OPTION       *Dhcp4Option,\r
+  IN PXEBC_VENDOR_OPTION           *VendorOption\r
+  )\r
+{\r
+  UINT32                  *BitMap;\r
+  UINT8                   VendorOptionLen;\r
+  EFI_DHCP4_PACKET_OPTION *PxeOption;\r
+  UINT8                   Offset;\r
+\r
+  BitMap          = VendorOption->BitMap;\r
+  VendorOptionLen = Dhcp4Option->Length;\r
+  PxeOption       = (EFI_DHCP4_PACKET_OPTION *) &Dhcp4Option->Data[0];\r
+  Offset          = 0;\r
+\r
+  while ((Offset < VendorOptionLen) && (PxeOption->OpCode != PXEBC_DHCP4_TAG_EOP)) {\r
+    //\r
+    // Parse every Vendor Option and set its BitMap\r
+    //\r
+    switch (PxeOption->OpCode) {\r
+\r
+    case PXEBC_VENDOR_TAG_MTFTP_IP:\r
+\r
+      NetCopyMem (&VendorOption->MtftpIp, PxeOption->Data, sizeof (EFI_IPv4_ADDRESS));\r
+      break;\r
+\r
+    case PXEBC_VENDOR_TAG_MTFTP_CPORT:\r
+\r
+      NetCopyMem (&VendorOption->MtftpCPort, PxeOption->Data, sizeof (VendorOption->MtftpCPort));\r
+      break;\r
+\r
+    case PXEBC_VENDOR_TAG_MTFTP_SPORT:\r
+\r
+      NetCopyMem (&VendorOption->MtftpSPort, PxeOption->Data, sizeof (VendorOption->MtftpSPort));\r
+      break;\r
+\r
+    case PXEBC_VENDOR_TAG_MTFTP_TIMEOUT:\r
+\r
+      VendorOption->MtftpTimeout = *PxeOption->Data;\r
+      break;\r
+\r
+    case PXEBC_VENDOR_TAG_MTFTP_DELAY:\r
+\r
+      VendorOption->MtftpDelay = *PxeOption->Data;\r
+      break;\r
+\r
+    case PXEBC_VENDOR_TAG_DISCOVER_CTRL:\r
+\r
+      VendorOption->DiscoverCtrl = *PxeOption->Data;\r
+      break;\r
+\r
+    case PXEBC_VENDOR_TAG_DISCOVER_MCAST:\r
+\r
+      NetCopyMem (&VendorOption->DiscoverMcastIp, PxeOption->Data, sizeof (EFI_IPv4_ADDRESS));\r
+      break;\r
+\r
+    case PXEBC_VENDOR_TAG_BOOT_SERVERS:\r
+\r
+      VendorOption->BootSvrLen  = PxeOption->Length;\r
+      VendorOption->BootSvr     = (PXEBC_BOOT_SVR_ENTRY *) PxeOption->Data;\r
+      break;\r
+\r
+    case PXEBC_VENDOR_TAG_BOOT_MENU:\r
+\r
+      VendorOption->BootMenuLen = PxeOption->Length;\r
+      VendorOption->BootMenu    = (PXEBC_BOOT_MENU_ENTRY *) PxeOption->Data;\r
+      break;\r
+\r
+    case PXEBC_VENDOR_TAG_MENU_PROMPT:\r
+\r
+      VendorOption->MenuPromptLen = PxeOption->Length;\r
+      VendorOption->MenuPrompt    = (PXEBC_MENU_PROMPT *) PxeOption->Data;\r
+      break;\r
+\r
+    case PXEBC_VENDOR_TAG_MCAST_ALLOC:\r
+\r
+      NetCopyMem (&VendorOption->McastIpBase, PxeOption->Data, sizeof (EFI_IPv4_ADDRESS));\r
+      NetCopyMem (&VendorOption->McastIpBlock, PxeOption->Data + 4, sizeof (VendorOption->McastIpBlock));\r
+      NetCopyMem (&VendorOption->McastIpRange, PxeOption->Data + 6, sizeof (VendorOption->McastIpRange));\r
+      break;\r
+\r
+    case PXEBC_VENDOR_TAG_CREDENTIAL_TYPES:\r
+\r
+      VendorOption->CredTypeLen = PxeOption->Length;\r
+      VendorOption->CredType    = (UINT32 *) PxeOption->Data;\r
+      break;\r
+\r
+    case PXEBC_VENDOR_TAG_BOOT_ITEM:\r
+\r
+      NetCopyMem (&VendorOption->BootSrvType, PxeOption->Data, sizeof (VendorOption->BootSrvType));\r
+      NetCopyMem (&VendorOption->BootSrvLayer, PxeOption->Data + 2, sizeof (VendorOption->BootSrvLayer));\r
+      break;\r
+    }\r
+\r
+    SET_VENDOR_OPTION_BIT_MAP (BitMap, PxeOption->OpCode);\r
+\r
+    if (PxeOption->OpCode == PXEBC_DHCP4_TAG_PAD) {\r
+      Offset++;\r
+    } else {\r
+      Offset = (UINT8) (Offset + PxeOption->Length + 2);\r
+    }\r
+\r
+    PxeOption = (EFI_DHCP4_PACKET_OPTION *) (Dhcp4Option->Data + Offset);\r
+  }\r
+\r
+  //\r
+  // FixMe, return falas if invalid of any vendor option\r
+  //\r
+\r
+  return TRUE;\r
+}\r
+\r
+\r
+/**\r
+  GC_NOTO: Add function description\r
+\r
+  @param  Str                   GC_NOTO: add argument description\r
+  @param  Len                   GC_NOTO: add argument description\r
+\r
+  @return GC_NOTO: add return values\r
+\r
+**/\r
+VOID\r
+PxeBcDisplayBootItem (\r
+  IN UINT8                 *Str,\r
+  IN UINT8                 Len\r
+  )\r
+{\r
+  UINT8 Tmp;\r
+\r
+  Len       = (UINT8) MIN (70, Len);\r
+  Tmp       = Str[Len];\r
+  Str[Len]  = 0;\r
+  AsciiPrint ("%a \n", Str);\r
+  Str[Len] = Tmp;\r
+}\r
+\r
+\r
+/**\r
+  GC_NOTO: Add function description\r
+\r
+  @param  Private               GC_NOTO: add argument description\r
+\r
+  @retval EFI_SUCCESS           GC_NOTO: Add description for return value\r
+  @retval EFI_TIMEOUT           GC_NOTO: Add description for return value\r
+\r
+**/\r
+EFI_STATUS\r
+PxeBcSelectBootPrompt (\r
+  IN PXEBC_PRIVATE_DATA              *Private\r
+  )\r
+{\r
+  PXEBC_CACHED_DHCP4_PACKET  *Packet;\r
+  PXEBC_VENDOR_OPTION       *VendorOpt;\r
+  EFI_EVENT                  TimeoutEvent;\r
+  EFI_EVENT                  DescendEvent;\r
+  EFI_INPUT_KEY              InputKey;\r
+  EFI_STATUS                 Status;\r
+  UINT8                      Timeout;\r
+  UINT8                      *Prompt;\r
+  UINT8                      PromptLen;\r
+  INT32                      SecCol;\r
+  INT32                      SecRow;\r
+\r
+  TimeoutEvent  = NULL;\r
+  DescendEvent  = NULL;\r
+\r
+  if (Private->PxeBc.Mode->ProxyOfferReceived) {\r
+\r
+    Packet  = &Private->ProxyOffer;\r
+  } else {\r
+\r
+    Packet  = &Private->Dhcp4Ack;\r
+  }\r
+\r
+  if (Packet->OfferType != DHCP4_PACKET_TYPE_PXE10) {\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  VendorOpt = &Packet->PxeVendorOption;\r
+\r
+  if (!IS_VALID_BOOT_PROMPT (VendorOpt->BitMap)) {\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  Timeout   = VendorOpt->MenuPrompt->Timeout;\r
+  Prompt    = VendorOpt->MenuPrompt->Prompt;\r
+  PromptLen = (UINT8) (VendorOpt->MenuPromptLen - 1);\r
+\r
+  if (Timeout == 0) {\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  if (Timeout == 255) {\r
+    return EFI_TIMEOUT;\r
+  }\r
+\r
+  Status = gBS->CreateEvent (\r
+                  EVT_TIMER,\r
+                  TPL_CALLBACK,\r
+                  NULL,\r
+                  NULL,\r
+                  &TimeoutEvent\r
+                  );\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  Status = gBS->SetTimer (\r
+                  TimeoutEvent,\r
+                  TimerRelative,\r
+                  Timeout * TICKS_PER_SECOND\r
+                  );\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    goto ON_EXIT;\r
+  }\r
+\r
+  Status = gBS->CreateEvent (\r
+                  EVT_TIMER,\r
+                  TPL_CALLBACK,\r
+                  NULL,\r
+                  NULL,\r
+                  &DescendEvent\r
+                  );\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    goto ON_EXIT;\r
+  }\r
+\r
+  Status = gBS->SetTimer (\r
+                  DescendEvent,\r
+                  TimerPeriodic,\r
+                  TICKS_PER_SECOND\r
+                  );\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    goto ON_EXIT;\r
+  }\r
+\r
+  SecCol = gST->ConOut->Mode->CursorColumn;\r
+  SecRow = gST->ConOut->Mode->CursorRow;\r
+\r
+  PxeBcDisplayBootItem (Prompt, PromptLen);\r
+\r
+  gST->ConOut->SetCursorPosition (gST->ConOut, SecCol + PromptLen, SecRow);\r
+  AsciiPrint ("(%d) ", Timeout--);\r
+\r
+  while (EFI_ERROR (gBS->CheckEvent (TimeoutEvent))) {\r
+\r
+    if (!EFI_ERROR (gBS->CheckEvent (DescendEvent))) {\r
+      gST->ConOut->SetCursorPosition (gST->ConOut, SecCol + PromptLen, SecRow);\r
+      AsciiPrint ("(%d) ", Timeout--);\r
+    }\r
+\r
+    if (gST->ConIn->ReadKeyStroke (gST->ConIn, &InputKey) == EFI_NOT_READY) {\r
+\r
+      gBS->Stall (10 * TICKS_PER_MS);\r
+      continue;\r
+    }\r
+\r
+    if (InputKey.ScanCode == 0) {\r
+\r
+      switch (InputKey.UnicodeChar) {\r
+      case CTRL ('c'):\r
+        Status = EFI_ABORTED;\r
+        break;\r
+\r
+      case CTRL ('m'):\r
+      case 'm':\r
+      case 'M':\r
+        Status = EFI_TIMEOUT;\r
+        break;\r
+\r
+      default:\r
+        continue;\r
+      }\r
+    } else {\r
+\r
+      switch (InputKey.ScanCode) {\r
+      case SCAN_F8:\r
+        Status = EFI_TIMEOUT;\r
+        break;\r
+\r
+      case SCAN_ESC:\r
+        Status = EFI_ABORTED;\r
+        break;\r
+\r
+      default:\r
+        continue;\r
+      }\r
+    }\r
+\r
+    break;\r
+  }\r
+\r
+  gST->ConOut->SetCursorPosition (gST->ConOut, 0 , SecRow + 1);\r
+\r
+ON_EXIT:\r
+\r
+  if (DescendEvent != NULL) {\r
+    gBS->CloseEvent (DescendEvent);\r
+  }\r
+\r
+  if (TimeoutEvent != NULL) {\r
+    gBS->CloseEvent (TimeoutEvent);\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  GC_NOTO: Add function description\r
+\r
+  @param  Private               GC_NOTO: add argument description\r
+  @param  Type                  GC_NOTO: add argument description\r
+\r
+  @retval EFI_ABORTED           GC_NOTO: Add description for return value\r
+  @retval EFI_SUCCESS           GC_NOTO: Add description for return value\r
+\r
+**/\r
+EFI_STATUS\r
+PxeBcSelectBootMenu (\r
+  IN  PXEBC_PRIVATE_DATA              *Private,\r
+  OUT UINT16                          *Type,\r
+  IN  BOOLEAN                         UseDefaultItem\r
+  )\r
+{\r
+  PXEBC_CACHED_DHCP4_PACKET  *Packet;\r
+  PXEBC_VENDOR_OPTION       *VendorOpt;\r
+  EFI_INPUT_KEY              InputKey;\r
+  UINT8                      MenuSize;\r
+  UINT8                      MenuNum;\r
+  INT32                      TopRow;\r
+  UINT16                     Select;\r
+  UINT16                     LastSelect;\r
+  UINT8                      Index;\r
+  BOOLEAN                    Finish;\r
+  CHAR8                      Blank[70];\r
+  PXEBC_BOOT_MENU_ENTRY      *MenuItem;\r
+  PXEBC_BOOT_MENU_ENTRY      *MenuArray[PXEBC_MAX_MENU_NUM];\r
+\r
+  Finish  = FALSE;\r
+  Select  = 1;\r
+  Index   = 0;\r
+  *Type   = 0;\r
+\r
+  if (Private->PxeBc.Mode->ProxyOfferReceived) {\r
+\r
+    Packet  = &Private->ProxyOffer;\r
+  } else {\r
+\r
+    Packet  = &Private->Dhcp4Ack;\r
+  }\r
+\r
+  ASSERT (Packet->OfferType == DHCP4_PACKET_TYPE_PXE10);\r
+\r
+  VendorOpt = &Packet->PxeVendorOption;\r
+\r
+  if (!IS_VALID_BOOT_MENU (VendorOpt->BitMap)) {\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  SetMem (Blank, sizeof(Blank), ' ');\r
+\r
+  MenuSize  = VendorOpt->BootMenuLen;\r
+  MenuItem  = VendorOpt->BootMenu;\r
+\r
+  while (MenuSize > 0) {\r
+    MenuArray[Index]  = MenuItem;\r
+    MenuSize          = (UINT8) (MenuSize - (MenuItem->DescLen + 3));\r
+    MenuItem          = (PXEBC_BOOT_MENU_ENTRY *) ((UINT8 *) MenuItem + MenuItem->DescLen + 3);\r
+    Index++;\r
+  }\r
+\r
+  if (UseDefaultItem) {\r
+    *Type = NTOHS (MenuArray[0]->Type);\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  MenuNum = Index;\r
+\r
+  for (Index = 0; Index < MenuNum; Index++) {\r
+    PxeBcDisplayBootItem (MenuArray[Index]->DescStr, MenuArray[Index]->DescLen);\r
+  }\r
+\r
+  TopRow  = gST->ConOut->Mode->CursorRow - MenuNum;\r
+\r
+  do {\r
+    //\r
+    // highlight selected row\r
+    //\r
+    gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_BLACK, EFI_LIGHTGRAY));\r
+    gST->ConOut->SetCursorPosition (gST->ConOut, 0, TopRow + Select);\r
+    Blank[MenuArray[Select]->DescLen] = 0;\r
+    AsciiPrint ("%a\r", Blank);\r
+    PxeBcDisplayBootItem (MenuArray[Select]->DescStr, MenuArray[Select]->DescLen);\r
+    gST->ConOut->SetCursorPosition (gST->ConOut, 0, TopRow + MenuNum);\r
+    LastSelect = Select;\r
+\r
+    while (gST->ConIn->ReadKeyStroke (gST->ConIn, &InputKey) == EFI_NOT_READY) {\r
+      gBS->Stall (10 * TICKS_PER_MS);\r
+    }\r
+\r
+    if (!InputKey.ScanCode) {\r
+      switch (InputKey.UnicodeChar) {\r
+      case CTRL ('c'):\r
+        InputKey.ScanCode = SCAN_ESC;\r
+        break;\r
+\r
+      case CTRL ('j'):  /* linefeed */\r
+      case CTRL ('m'):  /* return */\r
+        Finish = TRUE;\r
+        break;\r
+\r
+      case CTRL ('i'):  /* tab */\r
+      case ' ':\r
+      case 'd':\r
+      case 'D':\r
+        InputKey.ScanCode = SCAN_DOWN;\r
+        break;\r
+\r
+      case CTRL ('h'):  /* backspace */\r
+      case 'u':\r
+      case 'U':\r
+        InputKey.ScanCode = SCAN_UP;\r
+        break;\r
+\r
+      default:\r
+        InputKey.ScanCode = 0;\r
+      }\r
+    }\r
+\r
+    switch (InputKey.ScanCode) {\r
+    case SCAN_LEFT:\r
+    case SCAN_UP:\r
+      if (Select) {\r
+        --Select;\r
+      }\r
+\r
+      break;\r
+\r
+    case SCAN_DOWN:\r
+    case SCAN_RIGHT:\r
+      if (++Select == MenuNum) {\r
+        --Select;\r
+      }\r
+\r
+      break;\r
+\r
+    case SCAN_PAGE_UP:\r
+    case SCAN_HOME:\r
+      Select = 0;\r
+      break;\r
+\r
+    case SCAN_PAGE_DOWN:\r
+    case SCAN_END:\r
+      Select = (UINT16) (MenuNum - 1);\r
+      break;\r
+\r
+    case SCAN_ESC:\r
+      return EFI_ABORTED;\r
+    }\r
+\r
+    /* unhighlight last selected row */\r
+    gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));\r
+    gST->ConOut->SetCursorPosition (gST->ConOut, 0, TopRow + LastSelect);\r
+    Blank[MenuArray[LastSelect]->DescLen] = 0;\r
+    AsciiPrint ("%a\r", Blank);\r
+    PxeBcDisplayBootItem (MenuArray[LastSelect]->DescStr, MenuArray[LastSelect]->DescLen);\r
+    gST->ConOut->SetCursorPosition (gST->ConOut, 0, TopRow + MenuNum);\r
+  } while (!Finish);\r
+\r
+  //\r
+  // Swap the byte order\r
+  //\r
+  *Type = NTOHS (MenuArray[Select]->Type);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
diff --git a/MdeModulePkg/Universal/Network/UefiPxeBcDxe/PxeBcDhcp.h b/MdeModulePkg/Universal/Network/UefiPxeBcDxe/PxeBcDhcp.h
new file mode 100644 (file)
index 0000000..4cb9aef
--- /dev/null
@@ -0,0 +1,542 @@
+/** @file
+
+Copyright (c) 2007, 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.
+
+Module Name:
+
+  PxeBcDhcp.h
+
+Abstract:
+
+  Dhcp and Discover routines for PxeBc
+
+
+**/
+
+#ifndef __EFI_PXEBC_DHCP_H__
+#define __EFI_PXEBC_DHCP_H__
+
+enum {
+  PXEBC_DHCP4_MAX_OPTION_NUM        = 16,
+  PXEBC_DHCP4_MAX_OPTION_SIZE       = 312,
+  PXEBC_DHCP4_MAX_PACKET_SIZE       = 1472,
+
+  PXEBC_DHCP4_S_PORT                = 67,
+  PXEBC_DHCP4_C_PORT                = 68,
+  PXEBC_BS_DOWNLOAD_PORT            = 69,
+  PXEBC_BS_DISCOVER_PORT            = 4011,
+
+  PXEBC_DHCP4_OPCODE_REQUEST        = 1,
+  PXEBC_DHCP4_OPCODE_REPLY          = 2,
+  PXEBC_DHCP4_MSG_TYPE_REQUEST      = 3,
+  PXEBC_DHCP4_MAGIC                 = 0x63538263, // network byte order
+  //
+  // Dhcp Options
+  //
+  PXEBC_DHCP4_TAG_PAD               = 0,    // Pad Option
+  PXEBC_DHCP4_TAG_EOP               = 255,  // End Option
+  PXEBC_DHCP4_TAG_NETMASK           = 1,    // Subnet Mask
+  PXEBC_DHCP4_TAG_TIME_OFFSET       = 2,    // Time Offset from UTC
+  PXEBC_DHCP4_TAG_ROUTER            = 3,    // Router option,
+  PXEBC_DHCP4_TAG_TIME_SERVER       = 4,    // Time Server
+  PXEBC_DHCP4_TAG_NAME_SERVER       = 5,    // Name Server
+  PXEBC_DHCP4_TAG_DNS_SERVER        = 6,    // Domain Name Server
+  PXEBC_DHCP4_TAG_HOSTNAME          = 12,   // Host Name
+  PXEBC_DHCP4_TAG_BOOTFILE_LEN      = 13,   // Boot File Size
+  PXEBC_DHCP4_TAG_DUMP              = 14,   // Merit Dump File
+  PXEBC_DHCP4_TAG_DOMAINNAME        = 15,   // Domain Name
+  PXEBC_DHCP4_TAG_ROOTPATH          = 17,   // Root path
+  PXEBC_DHCP4_TAG_EXTEND_PATH       = 18,   // Extensions Path
+  PXEBC_DHCP4_TAG_EMTU              = 22,   // Maximum Datagram Reassembly Size
+  PXEBC_DHCP4_TAG_TTL               = 23,   // Default IP Time-to-live
+  PXEBC_DHCP4_TAG_BROADCAST         = 28,   // Broadcast Address
+  PXEBC_DHCP4_TAG_NIS_DOMAIN        = 40,   // Network Information Service Domain
+  PXEBC_DHCP4_TAG_NIS_SERVER        = 41,   // Network Information Servers
+  PXEBC_DHCP4_TAG_NTP_SERVER        = 42,   // Network Time Protocol Servers
+  PXEBC_DHCP4_TAG_VENDOR            = 43,   // Vendor Specific Information
+  PXEBC_DHCP4_TAG_REQUEST_IP        = 50,   // Requested IP Address
+  PXEBC_DHCP4_TAG_LEASE             = 51,   // IP Address Lease Time
+  PXEBC_DHCP4_TAG_OVERLOAD          = 52,   // Option Overload
+  PXEBC_DHCP4_TAG_MSG_TYPE          = 53,   // DHCP Message Type
+  PXEBC_DHCP4_TAG_SERVER_ID         = 54,   // Server Identifier
+  PXEBC_DHCP4_TAG_PARA_LIST         = 55,   // Parameter Request List
+  PXEBC_DHCP4_TAG_MAXMSG            = 57,   // Maximum DHCP Message Size
+  PXEBC_DHCP4_TAG_T1                = 58,   // Renewal (T1) Time Value
+  PXEBC_DHCP4_TAG_T2                = 59,   // Rebinding (T2) Time Value
+  PXEBC_DHCP4_TAG_CLASS_ID          = 60,   // Vendor class identifier
+  PXEBC_DHCP4_TAG_CLIENT_ID         = 61,   // Client-identifier
+  PXEBC_DHCP4_TAG_TFTP              = 66,   // TFTP server name
+  PXEBC_DHCP4_TAG_BOOTFILE          = 67,   // Bootfile name
+  PXEBC_PXE_DHCP4_TAG_ARCH          = 93,
+  PXEBC_PXE_DHCP4_TAG_UNDI          = 94,
+  PXEBC_PXE_DHCP4_TAG_UUID          = 97,
+  //
+  // Sub-Options in Dhcp Vendor Option
+  //
+  PXEBC_VENDOR_TAG_MTFTP_IP         = 1,
+  PXEBC_VENDOR_TAG_MTFTP_CPORT      = 2,
+  PXEBC_VENDOR_TAG_MTFTP_SPORT      = 3,
+  PXEBC_VENDOR_TAG_MTFTP_TIMEOUT    = 4,
+  PXEBC_VENDOR_TAG_MTFTP_DELAY      = 5,
+  PXEBC_VENDOR_TAG_DISCOVER_CTRL    = 6,
+  PXEBC_VENDOR_TAG_DISCOVER_MCAST   = 7,
+  PXEBC_VENDOR_TAG_BOOT_SERVERS     = 8,
+  PXEBC_VENDOR_TAG_BOOT_MENU        = 9,
+  PXEBC_VENDOR_TAG_MENU_PROMPT      = 10,
+  PXEBC_VENDOR_TAG_MCAST_ALLOC      = 11,
+  PXEBC_VENDOR_TAG_CREDENTIAL_TYPES = 12,
+  PXEBC_VENDOR_TAG_BOOT_ITEM        = 71,
+
+  PXEBC_DHCP4_DISCOVER_INIT_TIMEOUT = 4,
+  PXEBC_DHCP4_DISCOVER_RETRIES      = 4,
+
+  PXEBC_MAX_MENU_NUM                = 24,
+  PXEBC_MAX_OFFER_NUM               = 16,
+
+  PXEBC_BOOT_REQUEST_TIMEOUT        = 1,
+  PXEBC_BOOT_REQUEST_RETRIES        = 4,
+
+  PXEBC_DHCP4_OVERLOAD_FILE         = 1,
+  PXEBC_DHCP4_OVERLOAD_SERVER_NAME  = 2
+};
+
+//
+// The array index of the DHCP4 option tag interested
+//
+enum {
+  PXEBC_DHCP4_TAG_INDEX_BOOTFILE_LEN,
+  PXEBC_DHCP4_TAG_INDEX_VENDOR,
+  PXEBC_DHCP4_TAG_INDEX_OVERLOAD,
+  PXEBC_DHCP4_TAG_INDEX_MSG_TYPE,
+  PXEBC_DHCP4_TAG_INDEX_SERVER_ID,
+  PXEBC_DHCP4_TAG_INDEX_CLASS_ID,
+  PXEBC_DHCP4_TAG_INDEX_BOOTFILE,
+  PXEBC_DHCP4_TAG_INDEX_MAX
+};
+
+//
+// The type of DHCP OFFER, arranged by priority, PXE10 has the highest priority.
+//
+enum {
+  DHCP4_PACKET_TYPE_PXE10,
+  DHCP4_PACKET_TYPE_WFM11A,
+  DHCP4_PACKET_TYPE_BINL,
+  DHCP4_PACKET_TYPE_DHCP_ONLY,
+  DHCP4_PACKET_TYPE_MAX,
+  DHCP4_PACKET_TYPE_BOOTP           = DHCP4_PACKET_TYPE_MAX
+};
+
+#define BIT(x)  (1 << x)
+#define CTRL(x) (0x1F & (x))
+
+//
+// WfM11a options
+//
+#define MTFTP_VENDOR_OPTION_BIT_MAP (BIT (PXEBC_VENDOR_TAG_MTFTP_IP) | \
+                                     BIT (PXEBC_VENDOR_TAG_MTFTP_CPORT) | \
+                                     BIT (PXEBC_VENDOR_TAG_MTFTP_SPORT) | \
+                                     BIT (PXEBC_VENDOR_TAG_MTFTP_TIMEOUT) | \
+                                     BIT (PXEBC_VENDOR_TAG_MTFTP_DELAY))
+//
+// Discoverty options
+//
+#define DISCOVER_VENDOR_OPTION_BIT_MAP  (BIT (PXEBC_VENDOR_TAG_DISCOVER_CTRL) | \
+                                         BIT (PXEBC_VENDOR_TAG_DISCOVER_MCAST) | \
+                                         BIT (PXEBC_VENDOR_TAG_BOOT_SERVERS) | \
+                                         BIT (PXEBC_VENDOR_TAG_BOOT_MENU) | \
+                                         BIT (PXEBC_VENDOR_TAG_MENU_PROMPT))
+
+#define IS_VALID_BOOT_PROMPT(x) \
+  ((((x)[0]) & BIT (PXEBC_VENDOR_TAG_MENU_PROMPT)) == BIT (PXEBC_VENDOR_TAG_MENU_PROMPT))
+
+#define IS_VALID_BOOT_MENU(x) \
+  ((((x)[0]) & BIT (PXEBC_VENDOR_TAG_BOOT_MENU)) == BIT (PXEBC_VENDOR_TAG_BOOT_MENU))
+
+#define IS_VALID_MTFTP_VENDOR_OPTION(x) \
+    (((UINT32) ((x)[0]) & MTFTP_VENDOR_OPTION_BIT_MAP) == MTFTP_VENDOR_OPTION_BIT_MAP)
+
+#define IS_VALID_DISCOVER_VENDOR_OPTION(x)  (((UINT32) ((x)[0]) & DISCOVER_VENDOR_OPTION_BIT_MAP) != 0)
+
+#define IS_VALID_CREDENTIAL_VENDOR_OPTION(x) \
+    (((UINT32) ((x)[0]) & BIT (PXEBC_VENDOR_TAG_CREDENTIAL_TYPES)) == BIT (PXEBC_VENDOR_TAG_CREDENTIAL_TYPES))
+
+#define IS_VALID_BOOTITEM_VENDOR_OPTION(x) \
+    (((UINT32) ((x)[PXEBC_VENDOR_TAG_BOOT_ITEM / 32]) & BIT (PXEBC_VENDOR_TAG_BOOT_ITEM % 32)) \
+      == BIT (PXEBC_VENDOR_TAG_BOOT_ITEM % 32))
+
+#define IS_DISABLE_BCAST_DISCOVER(x)    (((x) & BIT (0)) == BIT (0))
+#define IS_DISABLE_MCAST_DISCOVER(x)    (((x) & BIT (1)) == BIT (1))
+#define IS_ENABLE_USE_SERVER_LIST(x)    (((x) & BIT (2)) == BIT (2))
+#define IS_ENABLE_BOOT_FILE_NAME(x)     (((x) & BIT (3)) == BIT (3))
+
+#define SET_VENDOR_OPTION_BIT_MAP(x, y) ((UINT32) ((x)[(y) / 32]) = (UINT32) ((x)[(y) / 32]) | BIT ((y) % 32))
+
+#pragma pack(1)
+typedef struct {
+  UINT8 ParaList[135];
+} PXEBC_DHCP4_OPTION_PARA;
+
+typedef struct {
+  UINT16  Size;
+} PXEBC_DHCP4_OPTION_MAX_MESG_SIZE;
+
+typedef struct {
+  UINT8 Type;
+  UINT8 MajorVer;
+  UINT8 MinorVer;
+} PXEBC_DHCP4_OPTION_UNDI;
+
+typedef struct {
+  UINT8 Type;
+} PXEBC_DHCP4_OPTION_MESG;
+
+typedef struct {
+  UINT16  Type;
+} PXEBC_DHCP4_OPTION_ARCH;
+
+#define DEFAULT_CLASS_ID_DATA "PXEClient:Arch:?????:????:??????"
+
+typedef struct {
+  UINT8 ClassIdentifier[10];
+  UINT8 ArchitecturePrefix[5];
+  UINT8 ArchitectureType[5];
+  UINT8 Lit3[1];
+  UINT8 InterfaceName[4];
+  UINT8 Lit4[1];
+  UINT8 UndiMajor[3];
+  UINT8 UndiMinor[3];
+} PXEBC_DHCP4_OPTION_CLID;
+
+typedef struct {
+  UINT8 Type;
+  UINT8 Guid[16];
+} PXEBC_DHCP4_OPTION_UUID;
+
+typedef struct {
+  UINT16  Type;
+  UINT16  Layer;
+} PXEBC_OPTION_BOOT_ITEM;
+
+#pragma pack()
+
+typedef union {
+  PXEBC_DHCP4_OPTION_PARA           *Para;
+  PXEBC_DHCP4_OPTION_UNDI           *Undi;
+  PXEBC_DHCP4_OPTION_ARCH           *Arch;
+  PXEBC_DHCP4_OPTION_CLID           *Clid;
+  PXEBC_DHCP4_OPTION_UUID           *Uuid;
+  PXEBC_DHCP4_OPTION_MESG           *Mesg;
+  PXEBC_DHCP4_OPTION_MAX_MESG_SIZE  *MaxMesgSize;
+} PXEBC_DHCP4_OPTION_ENTRY;
+
+typedef struct {
+  UINT16            Type;
+  UINT8             IpCnt;
+  EFI_IPv4_ADDRESS  IpAddr[1];
+} PXEBC_BOOT_SVR_ENTRY;
+
+typedef struct {
+  UINT16  Type;
+  UINT8   DescLen;
+  UINT8   DescStr[1];
+} PXEBC_BOOT_MENU_ENTRY;
+
+typedef struct {
+  UINT8 Timeout;
+  UINT8 Prompt[1];
+} PXEBC_MENU_PROMPT;
+
+typedef struct {
+  UINT32                BitMap[8];
+  EFI_IPv4_ADDRESS      MtftpIp;
+  UINT16                MtftpCPort;
+  UINT16                MtftpSPort;
+  UINT8                 MtftpTimeout;
+  UINT8                 MtftpDelay;
+  UINT8                 DiscoverCtrl;
+  EFI_IPv4_ADDRESS      DiscoverMcastIp;
+  EFI_IPv4_ADDRESS      McastIpBase;
+  UINT16                McastIpBlock;
+  UINT16                McastIpRange;
+  UINT16                BootSrvType;
+  UINT16                BootSrvLayer;
+  PXEBC_BOOT_SVR_ENTRY  *BootSvr;
+  UINT8                 BootSvrLen;
+  PXEBC_BOOT_MENU_ENTRY *BootMenu;
+  UINT8                 BootMenuLen;
+  PXEBC_MENU_PROMPT     *MenuPrompt;
+  UINT8                 MenuPromptLen;
+  UINT32                *CredType;
+  UINT8                 CredTypeLen;
+} PXEBC_VENDOR_OPTION;
+
+#define PXEBC_CACHED_DHCP4_PACKET_MAX_SIZE  (EFI_FIELD_OFFSET (EFI_DHCP4_PACKET, Dhcp4) + PXEBC_DHCP4_MAX_PACKET_SIZE)
+
+typedef struct {
+  union {
+    EFI_DHCP4_PACKET  Offer;
+    EFI_DHCP4_PACKET  Ack;
+    UINT8             Buffer[PXEBC_CACHED_DHCP4_PACKET_MAX_SIZE];
+  } Packet;
+
+  BOOLEAN                 IsPxeOffer;
+  UINT8                   OfferType;
+  EFI_DHCP4_PACKET_OPTION *Dhcp4Option[PXEBC_DHCP4_TAG_INDEX_MAX];
+  PXEBC_VENDOR_OPTION    PxeVendorOption;
+} PXEBC_CACHED_DHCP4_PACKET;
+
+#define GET_NEXT_DHCP_OPTION(Opt) \
+  (EFI_DHCP4_PACKET_OPTION *) ((UINT8 *) (Opt) + sizeof (EFI_DHCP4_PACKET_OPTION) + (Opt)->Length - 1)
+
+#define GET_OPTION_BUFFER_LEN(Pkt)  ((Pkt)->Length - sizeof (EFI_DHCP4_HEADER) - 4)
+#define IS_PROXY_DHCP_OFFER(Offer)  EFI_IP4_EQUAL (&((Offer)->Dhcp4.Header.YourAddr), &mZeroIp4Addr)
+
+#define GET_NEXT_BOOT_SVR_ENTRY(Ent) \
+  (PXEBC_BOOT_SVR_ENTRY *) ((UINT8 *) Ent + sizeof (*(Ent)) + ((Ent)->IpCnt - 1) * sizeof (EFI_IPv4_ADDRESS))
+
+VOID
+PxeBcInitSeedPacket (
+  IN EFI_DHCP4_PACKET  *Seed,
+  IN EFI_UDP4_PROTOCOL *Udp4
+  )
+/*++
+
+Routine Description:
+
+  GC_NOTO: Add function description
+
+Arguments:
+
+  Seed  - GC_NOTO: add argument description
+  Udp4  - GC_NOTO: add argument description
+
+Returns:
+
+  GC_NOTO: add return values
+
+--*/
+;
+
+
+/**
+  GC_NOTO: Add function description
+
+  @param  CachedPacket    GC_NOTO: add argument description
+
+  @return GC_NOTO: add return values
+
+**/
+BOOLEAN
+PxeBcParseCachedDhcpPacket (
+  IN PXEBC_CACHED_DHCP4_PACKET  *CachedPacket
+  )
+;
+
+
+/**
+  GC_NOTO: Add function description
+
+  @param  Private         GC_NOTO: add argument description
+
+  @return GC_NOTO: add return values
+
+**/
+EFI_STATUS
+PxeBcCheckSelectedOffer (
+  IN PXEBC_PRIVATE_DATA  *Private
+  )
+;
+
+
+/**
+  GC_NOTO: Add function description
+
+  @param  This            GC_NOTO: add argument description
+  @param  Context         GC_NOTO: add argument description
+  @param  CurrentState    GC_NOTO: add argument description
+  @param  Dhcp4Event      GC_NOTO: add argument description
+  @param  Packet          GC_NOTO: add argument description
+  @param  NewPacket       GC_NOTO: add argument description
+
+  @return GC_NOTO: add return values
+
+**/
+EFI_STATUS
+PxeBcDhcpCallBack (
+  IN EFI_DHCP4_PROTOCOL                * This,
+  IN VOID                              *Context,
+  IN EFI_DHCP4_STATE                   CurrentState,
+  IN EFI_DHCP4_EVENT                   Dhcp4Event,
+  IN EFI_DHCP4_PACKET                  * Packet OPTIONAL,
+  OUT EFI_DHCP4_PACKET                 **NewPacket OPTIONAL
+  )
+;
+
+
+/**
+  GC_NOTO: Add function description
+
+  @param  Private         GC_NOTO: add argument description
+  @param  Type            GC_NOTO: add argument description
+  @param  Layer           GC_NOTO: add argument description
+  @param  UseBis          GC_NOTO: add argument description
+  @param  DestIp          GC_NOTO: add argument description
+  @param  IpCount         GC_NOTO: add argument description
+  @param  SrvList         GC_NOTO: add argument description
+  @param  IsDiscv         GC_NOTO: add argument description
+  @param  Reply           GC_NOTO: add argument description
+
+  @return GC_NOTO: add return values
+
+**/
+EFI_STATUS
+PxeBcDiscvBootService (
+  IN PXEBC_PRIVATE_DATA                * Private,
+  IN UINT16                            Type,
+  IN UINT16                            *Layer,
+  IN BOOLEAN                           UseBis,
+  IN EFI_IP_ADDRESS                    * DestIp,
+  IN UINT16                            IpCount,
+  IN EFI_PXE_BASE_CODE_SRVLIST         * SrvList,
+  IN BOOLEAN                           IsDiscv,
+  OUT EFI_DHCP4_PACKET                 * Reply OPTIONAL
+  )
+;
+
+
+/**
+  GC_NOTO: Add function description
+
+  @param  Private         GC_NOTO: add argument description
+  @param  OptList         GC_NOTO: add argument description
+  @param  IsDhcpDiscover  GC_NOTO: add argument description
+
+  @return GC_NOTO: add return values
+
+**/
+UINT32
+PxeBcBuildDhcpOptions (
+  IN PXEBC_PRIVATE_DATA            *Private,
+  IN EFI_DHCP4_PACKET_OPTION       **OptList,
+  IN BOOLEAN                       IsDhcpDiscover
+  )
+;
+
+
+/**
+  GC_NOTO: Add function description
+
+  @param  OptList         GC_NOTO: add argument description
+  @param  Type            GC_NOTO: add argument description
+  @param  Layer           GC_NOTO: add argument description
+  @param  OptLen          GC_NOTO: add argument description
+
+  @return GC_NOTO: add return values
+
+**/
+VOID
+PxeBcCreateBootOptions (
+  IN  EFI_DHCP4_PACKET_OPTION          *OptList,
+  IN  UINT16                           Type,
+  IN  UINT16                           *Layer,
+  OUT UINT32                           *OptLen
+  )
+;
+
+
+/**
+  GC_NOTO: Add function description
+
+  @param  Buffer          GC_NOTO: add argument description
+  @param  Length          GC_NOTO: add argument description
+  @param  OptTag          GC_NOTO: add argument description
+
+  @return GC_NOTO: add return values
+
+**/
+EFI_DHCP4_PACKET_OPTION *
+PxeBcParseExtendOptions (
+  IN UINT8                         *Buffer,
+  IN UINT32                        Length,
+  IN UINT8                         OptTag
+  )
+;
+
+
+/**
+  GC_NOTO: Add function description
+
+  @param  Dhcp4Option     GC_NOTO: add argument description
+  @param  VendorOption    GC_NOTO: add argument description
+
+  @return GC_NOTO: add return values
+
+**/
+BOOLEAN
+PxeBcParseVendorOptions (
+  IN EFI_DHCP4_PACKET_OPTION       *Dhcp4Option,
+  IN PXEBC_VENDOR_OPTION          *VendorOption
+  )
+;
+
+
+/**
+  GC_NOTO: Add function description
+
+  @param  Private         GC_NOTO: add argument description
+  @param  Info            GC_NOTO: add argument description
+  @param  Type            GC_NOTO: add argument description
+
+  @return GC_NOTO: add return values
+
+**/
+EFI_STATUS
+PxeBcSelectBootServers (
+  IN  PXEBC_PRIVATE_DATA               *Private,
+  OUT EFI_PXE_BASE_CODE_DISCOVER_INFO  **Info,
+  OUT UINT16                           *Type
+  )
+;
+
+
+/**
+  GC_NOTO: Add function description
+
+  @param  Private         GC_NOTO: add argument description
+
+  @return GC_NOTO: add return values
+
+**/
+EFI_STATUS
+PxeBcSelectBootPrompt (
+  IN PXEBC_PRIVATE_DATA              *Private
+  )
+;
+
+
+/**
+  GC_NOTO: Add function description
+
+  @param  Private         GC_NOTO: add argument description
+  @param  Type            GC_NOTO: add argument description
+
+  @return GC_NOTO: add return values
+
+**/
+EFI_STATUS
+PxeBcSelectBootMenu (
+  IN  PXEBC_PRIVATE_DATA              *Private,
+  OUT UINT16                          *Type,
+  IN  BOOLEAN                         UseDefaultItem
+  )
+;
+
+#endif
+
diff --git a/MdeModulePkg/Universal/Network/UefiPxeBcDxe/PxeBcDriver.c b/MdeModulePkg/Universal/Network/UefiPxeBcDxe/PxeBcDriver.c
new file mode 100644 (file)
index 0000000..546e6ae
--- /dev/null
@@ -0,0 +1,451 @@
+/** @file\r
+\r
+Copyright (c) 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
+  PxeBcDriver.c\r
+\r
+Abstract:\r
+\r
+  The driver binding for IP4 CONFIG protocol.\r
+\r
+\r
+**/\r
+\r
+\r
+#include "PxeBcImpl.h"\r
+\r
+\r
+/**\r
+  The entry point for PxeBc driver which install the driver\r
+  binding and component name protocol on its image.\r
+\r
+  @param  ImageHandle          The Image handle of the driver\r
+  @param  SystemTable          The system table\r
+\r
+  @return EFI_SUCCESS\r
+  @return Others\r
+\r
+**/\r
+EFI_STATUS\r
+PxeBcDriverEntryPoint (\r
+  IN EFI_HANDLE             ImageHandle,\r
+  IN EFI_SYSTEM_TABLE       *SystemTable\r
+  )\r
+{\r
+  return EfiLibInstallDriverBindingComponentName2 (\r
+          ImageHandle,\r
+          SystemTable,\r
+          &gPxeBcDriverBinding,\r
+          ImageHandle,\r
+          &gPxeBcComponentName,\r
+          &gPxeBcComponentName2\r
+          );\r
+}\r
+\r
+\r
+/**\r
+  Test to see if this driver supports ControllerHandle.\r
+\r
+  @param  This                 Protocol instance pointer.\r
+  @param  ControllerHandle     Handle of device to test\r
+  @param  RemainingDevicePath  Optional parameter use to pick a specific child\r
+                               device to start.\r
+\r
+  @return EFI_SUCCES\r
+  @return EFI_ALREADY_STARTED\r
+  @return Others\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PxeBcDriverBindingSupported (\r
+  IN EFI_DRIVER_BINDING_PROTOCOL  * This,\r
+  IN EFI_HANDLE                   ControllerHandle,\r
+  IN EFI_DEVICE_PATH_PROTOCOL     * RemainingDevicePath OPTIONAL\r
+  )\r
+{\r
+  EFI_PXE_BASE_CODE_PROTOCOL  *PxeBc;\r
+  EFI_STATUS                  Status;\r
+\r
+  Status = gBS->OpenProtocol (\r
+                  ControllerHandle,\r
+                  &gEfiPxeBaseCodeProtocolGuid,\r
+                  (VOID **) &PxeBc,\r
+                  This->DriverBindingHandle,\r
+                  ControllerHandle,\r
+                  EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+                  );\r
+\r
+  if (!EFI_ERROR (Status)) {\r
+    return EFI_ALREADY_STARTED;\r
+  }\r
+\r
+  Status = gBS->OpenProtocol (\r
+                  ControllerHandle,\r
+                  &gEfiDhcp4ServiceBindingProtocolGuid,\r
+                  NULL,\r
+                  This->DriverBindingHandle,\r
+                  ControllerHandle,\r
+                  EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
+                  );\r
+\r
+  if (!EFI_ERROR (Status)) {\r
+\r
+    Status = gBS->OpenProtocol (\r
+                    ControllerHandle,\r
+                    &gEfiMtftp4ServiceBindingProtocolGuid,\r
+                    NULL,\r
+                    This->DriverBindingHandle,\r
+                    ControllerHandle,\r
+                    EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
+                    );\r
+\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  Start this driver on ControllerHandle.\r
+\r
+  @param  This                 Protocol instance pointer.\r
+  @param  ControllerHandle     Handle of device to bind driver to\r
+  @param  RemainingDevicePath  Optional parameter use to pick a specific child\r
+                               device to start.\r
+\r
+  @return EFI_SUCCES\r
+  @return EFI_ALREADY_STARTED\r
+  @return EFI_OUT_OF_RESOURCES\r
+  @return Others\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PxeBcDriverBindingStart (\r
+  IN EFI_DRIVER_BINDING_PROTOCOL  * This,\r
+  IN EFI_HANDLE                   ControllerHandle,\r
+  IN EFI_DEVICE_PATH_PROTOCOL     * RemainingDevicePath OPTIONAL\r
+  )\r
+{\r
+  PXEBC_PRIVATE_DATA  *Private;\r
+  UINTN               Index;\r
+  EFI_STATUS          Status;\r
+\r
+  Private = NetAllocateZeroPool (sizeof (PXEBC_PRIVATE_DATA));\r
+  if (Private == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  Private->Signature                    = PXEBC_PRIVATE_DATA_SIGNATURE;\r
+  Private->Controller                   = ControllerHandle;\r
+  Private->Image                        = This->DriverBindingHandle;\r
+  CopyMem (&Private->PxeBc, &mPxeBcProtocolTemplate, sizeof (Private->PxeBc));\r
+  Private->PxeBc.Mode                   = &Private->Mode;\r
+  CopyMem (&Private->LoadFile, &mLoadFileProtocolTemplate, sizeof (Private->LoadFile));\r
+\r
+  Private->ProxyOffer.Packet.Offer.Size = PXEBC_CACHED_DHCP4_PACKET_MAX_SIZE;\r
+  Private->Dhcp4Ack.Packet.Ack.Size     = PXEBC_CACHED_DHCP4_PACKET_MAX_SIZE;\r
+  Private->PxeReply.Packet.Ack.Size     = PXEBC_CACHED_DHCP4_PACKET_MAX_SIZE;\r
+\r
+  for (Index = 0; Index < PXEBC_MAX_OFFER_NUM; Index++) {\r
+    Private->Dhcp4Offers[Index].Packet.Offer.Size = PXEBC_CACHED_DHCP4_PACKET_MAX_SIZE;\r
+  }\r
+\r
+  //\r
+  // Get the NII interface\r
+  //\r
+  Status = gBS->OpenProtocol (\r
+                  ControllerHandle,\r
+                  &gEfiNetworkInterfaceIdentifierProtocolGuid_31,\r
+                  (VOID **) &Private->Nii,\r
+                  This->DriverBindingHandle,\r
+                  ControllerHandle,\r
+                  EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    goto ON_ERROR;\r
+  }\r
+\r
+  Status = NetLibCreateServiceChild (\r
+            ControllerHandle,\r
+            This->DriverBindingHandle,\r
+            &gEfiDhcp4ServiceBindingProtocolGuid,\r
+            &Private->Dhcp4Child\r
+            );\r
+  if (EFI_ERROR (Status)) {\r
+    goto ON_ERROR;\r
+  }\r
+\r
+  Status = gBS->OpenProtocol (\r
+                  Private->Dhcp4Child,\r
+                  &gEfiDhcp4ProtocolGuid,\r
+                  (VOID **) &Private->Dhcp4,\r
+                  This->DriverBindingHandle,\r
+                  ControllerHandle,\r
+                  EFI_OPEN_PROTOCOL_BY_DRIVER\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    goto ON_ERROR;\r
+  }\r
+\r
+  Status = NetLibCreateServiceChild (\r
+             ControllerHandle,\r
+             This->DriverBindingHandle,\r
+             &gEfiMtftp4ServiceBindingProtocolGuid,\r
+             &Private->Mtftp4Child\r
+             );\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    goto ON_ERROR;\r
+  }\r
+\r
+  Status = gBS->OpenProtocol (\r
+                  Private->Mtftp4Child,\r
+                  &gEfiMtftp4ProtocolGuid,\r
+                  (VOID **) &Private->Mtftp4,\r
+                  This->DriverBindingHandle,\r
+                  ControllerHandle,\r
+                  EFI_OPEN_PROTOCOL_BY_DRIVER\r
+                  );\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    goto ON_ERROR;\r
+  }\r
+\r
+  Status = NetLibCreateServiceChild (\r
+             ControllerHandle,\r
+             This->DriverBindingHandle,\r
+             &gEfiUdp4ServiceBindingProtocolGuid,\r
+             &Private->Udp4Child\r
+             );\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    goto ON_ERROR;\r
+  }\r
+\r
+  Status = gBS->OpenProtocol (\r
+                  Private->Udp4Child,\r
+                  &gEfiUdp4ProtocolGuid,\r
+                  (VOID **) &Private->Udp4,\r
+                  This->DriverBindingHandle,\r
+                  ControllerHandle,\r
+                  EFI_OPEN_PROTOCOL_BY_DRIVER\r
+                  );\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    goto ON_ERROR;\r
+  }\r
+\r
+  NetZeroMem (&Private->Udp4CfgData, sizeof (EFI_UDP4_CONFIG_DATA));\r
+  Private->Udp4CfgData.AcceptBroadcast    = TRUE;\r
+  Private->Udp4CfgData.AcceptPromiscuous  = FALSE;\r
+  Private->Udp4CfgData.AcceptAnyPort      = FALSE;\r
+  Private->Udp4CfgData.AllowDuplicatePort = TRUE;\r
+  Private->Udp4CfgData.TypeOfService      = DEFAULT_ToS;\r
+  Private->Udp4CfgData.TimeToLive         = DEFAULT_TTL;\r
+  Private->Udp4CfgData.DoNotFragment      = FALSE;\r
+  Private->Udp4CfgData.ReceiveTimeout     = 10000;  // 10 milliseconds\r
+  Private->Udp4CfgData.UseDefaultAddress  = FALSE;\r
+\r
+  PxeBcInitSeedPacket (&Private->SeedPacket, Private->Udp4);\r
+\r
+  Status = gBS->InstallMultipleProtocolInterfaces (\r
+                  &ControllerHandle,\r
+                  &gEfiPxeBaseCodeProtocolGuid,\r
+                  &Private->PxeBc,\r
+                  &gEfiLoadFileProtocolGuid,\r
+                  &Private->LoadFile,\r
+                  NULL\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    goto ON_ERROR;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+\r
+ON_ERROR:\r
+\r
+  if (Private->Udp4Child != NULL) {\r
+    gBS->CloseProtocol (\r
+          Private->Udp4Child,\r
+          &gEfiUdp4ProtocolGuid,\r
+          This->DriverBindingHandle,\r
+          ControllerHandle\r
+          );\r
+    NetLibDestroyServiceChild (\r
+      ControllerHandle,\r
+      This->DriverBindingHandle,\r
+      &gEfiUdp4ProtocolGuid,\r
+      Private->Udp4Child\r
+      );\r
+  }\r
+\r
+  if (Private->Mtftp4Child != NULL) {\r
+    gBS->CloseProtocol (\r
+          Private->Mtftp4Child,\r
+          &gEfiMtftp4ProtocolGuid,\r
+          This->DriverBindingHandle,\r
+          ControllerHandle\r
+          );\r
+\r
+    NetLibDestroyServiceChild (\r
+      ControllerHandle,\r
+      This->DriverBindingHandle,\r
+      &gEfiMtftp4ProtocolGuid,\r
+      Private->Mtftp4Child\r
+      );\r
+  }\r
+\r
+  if (Private->Dhcp4Child != NULL) {\r
+    gBS->CloseProtocol (\r
+          Private->Dhcp4Child,\r
+          &gEfiDhcp4ProtocolGuid,\r
+          This->DriverBindingHandle,\r
+          ControllerHandle\r
+          );\r
+\r
+    NetLibDestroyServiceChild (\r
+      ControllerHandle,\r
+      This->DriverBindingHandle,\r
+      &gEfiDhcp4ProtocolGuid,\r
+      Private->Dhcp4Child\r
+      );\r
+  }\r
+\r
+  NetFreePool (Private);\r
+\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  Stop this driver on ControllerHandle.\r
+\r
+  @param  This                 Protocol instance pointer.\r
+  @param  ControllerHandle     Handle of device to stop driver on\r
+  @param  NumberOfChildren     Number of Handles in ChildHandleBuffer. If number of\r
+                                children is zero stop the entire bus driver.\r
+  @param  ChildHandleBuffer    List of Child Handles to Stop.\r
+\r
+  @return EFI_SUCCESS\r
+  @return EFI_DEVICE_ERROR\r
+  @return Others\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PxeBcDriverBindingStop (\r
+  IN EFI_DRIVER_BINDING_PROTOCOL  *This,\r
+  IN EFI_HANDLE                   ControllerHandle,\r
+  IN UINTN                        NumberOfChildren,\r
+  IN EFI_HANDLE                   *ChildHandleBuffer\r
+  )\r
+{\r
+  PXEBC_PRIVATE_DATA          *Private;\r
+  EFI_PXE_BASE_CODE_PROTOCOL  *PxeBc;\r
+  EFI_HANDLE                  NicHandle;\r
+  EFI_STATUS                  Status;\r
+\r
+  NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiDhcp4ProtocolGuid);\r
+\r
+  if (NicHandle == NULL) {\r
+\r
+    NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiMtftp4ProtocolGuid);\r
+\r
+    if (NicHandle == NULL) {\r
+\r
+      return EFI_DEVICE_ERROR;\r
+    }\r
+  }\r
+\r
+  Status = gBS->OpenProtocol (\r
+                  NicHandle,\r
+                  &gEfiPxeBaseCodeProtocolGuid,\r
+                  (VOID **) &PxeBc,\r
+                  This->DriverBindingHandle,\r
+                  ControllerHandle,\r
+                  EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+                  );\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  Private = PXEBC_PRIVATE_DATA_FROM_PXEBC (PxeBc);\r
+\r
+  Status = gBS->UninstallMultipleProtocolInterfaces (\r
+                  NicHandle,\r
+                  &gEfiPxeBaseCodeProtocolGuid,\r
+                  &Private->PxeBc,\r
+                  &gEfiLoadFileProtocolGuid,\r
+                  &Private->LoadFile,\r
+                  NULL\r
+                  );\r
+\r
+  if (!EFI_ERROR (Status)) {\r
+\r
+    gBS->CloseProtocol (\r
+          Private->Udp4Child,\r
+          &gEfiUdp4ProtocolGuid,\r
+          This->DriverBindingHandle,\r
+          ControllerHandle\r
+          );\r
+    NetLibDestroyServiceChild (\r
+      ControllerHandle,\r
+      This->DriverBindingHandle,\r
+      &gEfiUdp4ServiceBindingProtocolGuid,\r
+      Private->Udp4Child\r
+      );\r
+\r
+    gBS->CloseProtocol (\r
+          Private->Dhcp4Child,\r
+          &gEfiDhcp4ProtocolGuid,\r
+          This->DriverBindingHandle,\r
+          ControllerHandle\r
+          );\r
+    NetLibDestroyServiceChild (\r
+      ControllerHandle,\r
+      This->DriverBindingHandle,\r
+      &gEfiDhcp4ServiceBindingProtocolGuid,\r
+      Private->Dhcp4Child\r
+      );\r
+\r
+    gBS->CloseProtocol (\r
+          Private->Mtftp4Child,\r
+          &gEfiMtftp4ProtocolGuid,\r
+          This->DriverBindingHandle,\r
+          ControllerHandle\r
+          );\r
+    NetLibDestroyServiceChild (\r
+      ControllerHandle,\r
+      This->DriverBindingHandle,\r
+      &gEfiMtftp4ServiceBindingProtocolGuid,\r
+      Private->Mtftp4Child\r
+      );\r
+\r
+    NetFreePool (Private);\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+EFI_DRIVER_BINDING_PROTOCOL gPxeBcDriverBinding = {\r
+  PxeBcDriverBindingSupported,\r
+  PxeBcDriverBindingStart,\r
+  PxeBcDriverBindingStop,\r
+  0xa,\r
+  NULL,\r
+  NULL\r
+};\r
+\r
+\r
diff --git a/MdeModulePkg/Universal/Network/UefiPxeBcDxe/PxeBcDriver.h b/MdeModulePkg/Universal/Network/UefiPxeBcDxe/PxeBcDriver.h
new file mode 100644 (file)
index 0000000..4cb1e2b
--- /dev/null
@@ -0,0 +1,103 @@
+/** @file
+
+Copyright (c) 2007, 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.
+
+Module Name:
+
+  PxeBcDriver.h
+
+Abstract:
+
+
+**/
+
+#ifndef __EFI_PXEBC_DRIVER_H__
+#define __EFI_PXEBC_DRIVER_H__
+
+EFI_STATUS
+PxeBcDriverBindingSupported (
+  IN EFI_DRIVER_BINDING_PROTOCOL  *This,
+  IN EFI_HANDLE                   Controller,
+  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath
+  )
+/*++
+
+  Routine Description:
+    Test to see if this driver supports ControllerHandle.
+
+  Arguments:
+    This                - Protocol instance pointer.
+    ControllerHandle    - Handle of device to test
+    RemainingDevicePath - Optional parameter use to pick a specific child
+                          device to start.
+
+  Returns:
+    EFI_SUCCES
+    EFI_ALREADY_STARTED
+    Others
+
+--*/
+// GC_NOTO:    Controller - add argument and description to function comment
+;
+
+
+/**
+  Start this driver on ControllerHandle.
+
+  @param  This                 Protocol instance pointer.
+  @param  ControllerHandle     Handle of device to bind driver to
+  @param  RemainingDevicePath  Optional parameter use to pick a specific child
+                               device to start.
+
+  @return EFI_SUCCES
+  @return EFI_ALREADY_STARTED
+  @return EFI_OUT_OF_RESOURCES
+  @return Others
+
+**/
+// GC_NOTO:    Controller - add argument and description to function comment
+EFI_STATUS
+PxeBcDriverBindingStart (
+  IN EFI_DRIVER_BINDING_PROTOCOL  *This,
+  IN EFI_HANDLE                   Controller,
+  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath
+  )
+;
+
+
+/**
+  Stop this driver on ControllerHandle.
+
+  @param  This                 Protocol instance pointer.
+  @param  ControllerHandle     Handle of device to stop driver on
+  @param  NumberOfChildren     Number of Handles in ChildHandleBuffer. If number of
+                                children is zero stop the entire bus driver.
+  @param  ChildHandleBuffer    List of Child Handles to Stop.
+
+  @return EFI_SUCCESS
+  @return EFI_DEVICE_ERROR
+  @return Others
+
+**/
+// GC_NOTO:    Controller - add argument and description to function comment
+EFI_STATUS
+PxeBcDriverBindingStop (
+  IN  EFI_DRIVER_BINDING_PROTOCOL *This,
+  IN  EFI_HANDLE                  Controller,
+  IN  UINTN                       NumberOfChildren,
+  IN  EFI_HANDLE                  *ChildHandleBuffer
+  )
+;
+
+extern EFI_COMPONENT_NAME2_PROTOCOL gPxeBcComponentName2;
+extern EFI_COMPONENT_NAME_PROTOCOL  gPxeBcComponentName;
+extern EFI_DRIVER_BINDING_PROTOCOL  gPxeBcDriverBinding;
+#endif
+
diff --git a/MdeModulePkg/Universal/Network/UefiPxeBcDxe/PxeBcImpl.c b/MdeModulePkg/Universal/Network/UefiPxeBcDxe/PxeBcImpl.c
new file mode 100644 (file)
index 0000000..8d7b3d0
--- /dev/null
@@ -0,0 +1,1866 @@
+/** @file\r
+\r
+Copyright (c) 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
+  PxeBcImpl.c\r
+\r
+Abstract:\r
+\r
+  Interface routines for PxeBc\r
+\r
+\r
+**/\r
+\r
+\r
+#include "PxeBcImpl.h"\r
+\r
+\r
+/**\r
+  GC_NOTO: Add function description\r
+\r
+  @param  This                                        GC_NOTO: add argument\r
+                                                      description\r
+  @param  UseIpv6                                     GC_NOTO: add argument\r
+                                                      description\r
+\r
+  @retval EFI_INVALID_PARAMETER                       GC_NOTO: Add description for\r
+                                                      return value\r
+  @retval EFI_ALREADY_STARTED                         GC_NOTO: Add description for\r
+                                                      return value\r
+  @retval EFI_UNSUPPORTED                             GC_NOTO: Add description for\r
+                                                      return value\r
+  @retval EFI_SUCCESS                                 GC_NOTO: Add description for\r
+                                                      return value\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+EfiPxeBcStart (\r
+  IN EFI_PXE_BASE_CODE_PROTOCOL       *This,\r
+  IN BOOLEAN                          UseIpv6\r
+  )\r
+{\r
+  PXEBC_PRIVATE_DATA      *Private;\r
+  EFI_PXE_BASE_CODE_MODE  *Mode;\r
+  EFI_STATUS              Status;\r
+\r
+  if (This == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  Private = PXEBC_PRIVATE_DATA_FROM_PXEBC (This);\r
+  Mode    = Private->PxeBc.Mode;\r
+\r
+  if (Mode->Started) {\r
+    return EFI_ALREADY_STARTED;\r
+  }\r
+\r
+  if (UseIpv6) {\r
+    //\r
+    // IPv6 is not supported now.\r
+    //\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  //\r
+  // Configure the udp4 instance to let it receive data\r
+  //\r
+  Status = Private->Udp4->Configure (Private->Udp4, &Private->Udp4CfgData);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  Private->AddressIsOk = FALSE;\r
+\r
+  ZeroMem (Mode, sizeof (EFI_PXE_BASE_CODE_MODE));\r
+\r
+  Mode->Started = TRUE;\r
+  Mode->TTL     = DEFAULT_TTL;\r
+  Mode->ToS     = DEFAULT_ToS;\r
+  Mode->AutoArp = TRUE;\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+  GC_NOTO: Add function description\r
+\r
+  @param  This                                        GC_NOTO: add argument\r
+                                                      description\r
+\r
+  @retval EFI_INVALID_PARAMETER                       GC_NOTO: Add description for\r
+                                                      return value\r
+  @retval EFI_NOT_STARTED                             GC_NOTO: Add description for\r
+                                                      return value\r
+  @retval EFI_SUCCESS                                 GC_NOTO: Add description for\r
+                                                      return value\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+EfiPxeBcStop (\r
+  IN EFI_PXE_BASE_CODE_PROTOCOL       *This\r
+  )\r
+{\r
+  PXEBC_PRIVATE_DATA      *Private;\r
+  EFI_PXE_BASE_CODE_MODE  *Mode;\r
+\r
+  if (This == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  Private = PXEBC_PRIVATE_DATA_FROM_PXEBC (This);\r
+  Mode    = Private->PxeBc.Mode;\r
+\r
+  if (!Mode->Started) {\r
+    return EFI_NOT_STARTED;\r
+  }\r
+\r
+  Mode->Started = FALSE;\r
+\r
+  Private->Udp4->Configure (Private->Udp4, NULL);\r
+\r
+  Private->Dhcp4->Stop (Private->Dhcp4);\r
+  Private->Dhcp4->Configure (Private->Dhcp4, NULL);\r
+\r
+  Private->FileSize = 0;\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+  GC_NOTO: Add function description\r
+\r
+  @param  This                                        GC_NOTO: add argument\r
+                                                      description\r
+  @param  SortOffers                                  GC_NOTO: add argument\r
+                                                      description\r
+\r
+  @retval EFI_INVALID_PARAMETER                       GC_NOTO: Add description for\r
+                                                      return value\r
+  @retval EFI_NOT_STARTED                             GC_NOTO: Add description for\r
+                                                      return value\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+EfiPxeBcDhcp (\r
+  IN EFI_PXE_BASE_CODE_PROTOCOL       *This,\r
+  IN BOOLEAN                          SortOffers\r
+  )\r
+{\r
+  PXEBC_PRIVATE_DATA      *Private;\r
+  EFI_PXE_BASE_CODE_MODE  *Mode;\r
+  EFI_DHCP4_PROTOCOL      *Dhcp4;\r
+  EFI_DHCP4_CONFIG_DATA   Dhcp4CfgData;\r
+  EFI_DHCP4_MODE_DATA     Dhcp4Mode;\r
+  EFI_DHCP4_PACKET_OPTION *OptList[PXEBC_DHCP4_MAX_OPTION_NUM];\r
+  UINT32                  OptCount;\r
+  UINT32                  DiscoverTimeout;\r
+  UINTN                   Index;\r
+  EFI_STATUS              Status;\r
+\r
+  if (This == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  Status              = EFI_SUCCESS;\r
+  Private             = PXEBC_PRIVATE_DATA_FROM_PXEBC (This);\r
+  Mode                = Private->PxeBc.Mode;\r
+  Dhcp4               = Private->Dhcp4;\r
+  Private->Function   = EFI_PXE_BASE_CODE_FUNCTION_DHCP;\r
+  Private->SortOffers = SortOffers;\r
+\r
+  if (!Mode->Started) {\r
+    return EFI_NOT_STARTED;\r
+  }\r
+  //\r
+  // Initialize the DHCP options and build the option list\r
+  //\r
+  OptCount = PxeBcBuildDhcpOptions (Private, OptList, TRUE);\r
+\r
+  //\r
+  // Set the DHCP4 config data.\r
+  //\r
+  NetZeroMem (&Dhcp4CfgData, sizeof (EFI_DHCP4_CONFIG_DATA));\r
+  Dhcp4CfgData.OptionCount      = OptCount;\r
+  Dhcp4CfgData.OptionList       = OptList;\r
+  Dhcp4CfgData.Dhcp4Callback    = PxeBcDhcpCallBack;\r
+  Dhcp4CfgData.CallbackContext  = Private;\r
+  Dhcp4CfgData.DiscoverTryCount = 1;\r
+  Dhcp4CfgData.DiscoverTimeout  = &DiscoverTimeout;\r
+\r
+  for (Index = 0; Index < PXEBC_DHCP4_DISCOVER_RETRIES; Index++) {\r
+    //\r
+    // The four discovery timeouts are 4, 8, 16, 32 seconds respectively.\r
+    //\r
+    DiscoverTimeout = (PXEBC_DHCP4_DISCOVER_INIT_TIMEOUT << Index);\r
+\r
+    Status          = Dhcp4->Configure (Dhcp4, &Dhcp4CfgData);\r
+    if (EFI_ERROR (Status)) {\r
+      break;\r
+    }\r
+    //\r
+    // Zero those arrays to record the varies numbers of DHCP OFFERS.\r
+    //\r
+    Private->NumOffers   = 0;\r
+    Private->BootpIndex  = 0;\r
+    NetZeroMem (Private->ServerCount, sizeof (Private->ServerCount));\r
+    NetZeroMem (Private->ProxyIndex, sizeof (Private->ProxyIndex));\r
+\r
+    Status = Dhcp4->Start (Dhcp4, NULL);\r
+    if (EFI_ERROR (Status)) {\r
+      if (Status == EFI_TIMEOUT) {\r
+        //\r
+        // If no response is received or all received offers don't match\r
+        // the PXE boot requirements, EFI_TIMEOUT will be returned.\r
+        //\r
+        continue;\r
+      }\r
+      //\r
+      // Other error status means the DHCP really fails.\r
+      //\r
+      break;\r
+    }\r
+\r
+    Status = Dhcp4->GetModeData (Dhcp4, &Dhcp4Mode);\r
+    if (EFI_ERROR (Status)) {\r
+      break;\r
+    }\r
+\r
+    ASSERT (Dhcp4Mode.State == Dhcp4Bound);\r
+\r
+    NetCopyMem (&Private->StationIp, &Dhcp4Mode.ClientAddress, sizeof (EFI_IPv4_ADDRESS));\r
+    NetCopyMem (&Private->SubnetMask, &Dhcp4Mode.SubnetMask, sizeof (EFI_IPv4_ADDRESS));\r
+    NetCopyMem (&Private->GatewayIp, &Dhcp4Mode.RouterAddress, sizeof (EFI_IPv4_ADDRESS));\r
+\r
+    //\r
+    // Check the selected offer to see whether BINL is required, if no or BINL is\r
+    // finished, set the various Mode members.\r
+    //\r
+    Status = PxeBcCheckSelectedOffer (Private);\r
+    if (!EFI_ERROR (Status)) {\r
+      break;\r
+    }\r
+  }\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    Dhcp4->Stop (Dhcp4);\r
+    Dhcp4->Configure (Dhcp4, NULL);\r
+  } else {\r
+    //\r
+    // Remove the previously configured option list and callback function\r
+    //\r
+    NetZeroMem (&Dhcp4CfgData, sizeof (EFI_DHCP4_CONFIG_DATA));\r
+    Dhcp4->Configure (Dhcp4, &Dhcp4CfgData);\r
+\r
+    Private->AddressIsOk = TRUE;\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  GC_NOTO: Add function description\r
+\r
+  @param  This                                        GC_NOTO: add argument\r
+                                                      description\r
+  @param  Type                                        GC_NOTO: add argument\r
+                                                      description\r
+  @param  Layer                                       GC_NOTO: add argument\r
+                                                      description\r
+  @param  UseBis                                      GC_NOTO: add argument\r
+                                                      description\r
+  @param  Info                                        GC_NOTO: add argument\r
+                                                      description\r
+\r
+  @retval EFI_INVALID_PARAMETER                       GC_NOTO: Add description for\r
+                                                      return value\r
+  @retval EFI_NOT_STARTED                             GC_NOTO: Add description for\r
+                                                      return value\r
+  @retval EFI_INVALID_PARAMETER                       GC_NOTO: Add description for\r
+                                                      return value\r
+  @retval EFI_INVALID_PARAMETER                       GC_NOTO: Add description for\r
+                                                      return value\r
+  @retval EFI_INVALID_PARAMETER                       GC_NOTO: Add description for\r
+                                                      return value\r
+  @retval EFI_INVALID_PARAMETER                       GC_NOTO: Add description for\r
+                                                      return value\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+EfiPxeBcDiscover (\r
+  IN EFI_PXE_BASE_CODE_PROTOCOL       *This,\r
+  IN UINT16                           Type,\r
+  IN UINT16                           *Layer,\r
+  IN BOOLEAN                          UseBis,\r
+  IN EFI_PXE_BASE_CODE_DISCOVER_INFO  *Info   OPTIONAL\r
+  )\r
+{\r
+  PXEBC_PRIVATE_DATA              *Private;\r
+  EFI_PXE_BASE_CODE_MODE          *Mode;\r
+  EFI_PXE_BASE_CODE_DISCOVER_INFO DefaultInfo;\r
+  EFI_PXE_BASE_CODE_SRVLIST       *SrvList;\r
+  EFI_PXE_BASE_CODE_SRVLIST       DefaultSrvList;\r
+  PXEBC_CACHED_DHCP4_PACKET       *Packet;\r
+  PXEBC_VENDOR_OPTION            *VendorOpt;\r
+  UINT16                          Index;\r
+  EFI_STATUS                      Status;\r
+  PXEBC_BOOT_SVR_ENTRY            *BootSvrEntry;\r
+\r
+  if (This == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  Private           = PXEBC_PRIVATE_DATA_FROM_PXEBC (This);\r
+  Mode              = Private->PxeBc.Mode;\r
+  BootSvrEntry      = NULL;\r
+  SrvList           = NULL;\r
+  Status            = EFI_DEVICE_ERROR;\r
+  Private->Function = EFI_PXE_BASE_CODE_FUNCTION_DISCOVER;\r
+\r
+  if (!Private->AddressIsOk) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if (!Mode->Started) {\r
+    return EFI_NOT_STARTED;\r
+  }\r
+\r
+  //\r
+  // If layer isn't EFI_PXE_BASE_CODE_BOOT_LAYER_INITIAL,\r
+  //   use the previous setting;\r
+  // If info isn't offered,\r
+  //   use the cached DhcpAck and ProxyOffer packets.\r
+  //\r
+  if (*Layer != EFI_PXE_BASE_CODE_BOOT_LAYER_INITIAL) {\r
+\r
+    if (!Mode->PxeDiscoverValid || !Mode->PxeReplyReceived || (!Mode->PxeBisReplyReceived && UseBis)) {\r
+\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
+\r
+    DefaultInfo.IpCnt                 = 1;\r
+    DefaultInfo.UseUCast              = TRUE;\r
+\r
+    DefaultSrvList.Type               = Type;\r
+    DefaultSrvList.AcceptAnyResponse  = FALSE;\r
+    DefaultSrvList.IpAddr.Addr[0]     = Private->ServerIp.Addr[0];\r
+\r
+    SrvList = &DefaultSrvList;\r
+    Info = &DefaultInfo;\r
+  } else if (Info == NULL) {\r
+    //\r
+    // Create info by the cached packet before\r
+    //\r
+    Packet    = (Mode->ProxyOfferReceived) ? &Private->ProxyOffer : &Private->Dhcp4Ack;\r
+    VendorOpt = &Packet->PxeVendorOption;\r
+\r
+    if (!Mode->DhcpAckReceived || !IS_VALID_DISCOVER_VENDOR_OPTION (VendorOpt->BitMap)) {\r
+      //\r
+      // Address is not acquired or no discovery options.\r
+      //\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
+\r
+    DefaultInfo.UseMCast    = (BOOLEAN)!IS_DISABLE_MCAST_DISCOVER (VendorOpt->DiscoverCtrl);\r
+    DefaultInfo.UseBCast    = (BOOLEAN)!IS_DISABLE_BCAST_DISCOVER (VendorOpt->DiscoverCtrl);\r
+    DefaultInfo.MustUseList = (BOOLEAN) IS_ENABLE_USE_SERVER_LIST (VendorOpt->DiscoverCtrl);\r
+    DefaultInfo.UseUCast    = DefaultInfo.MustUseList;\r
+\r
+    if (DefaultInfo.UseMCast) {\r
+      //\r
+      // Get the multicast discover ip address from vendor option.\r
+      //\r
+      NetCopyMem (&DefaultInfo.ServerMCastIp.Addr, &VendorOpt->DiscoverMcastIp, sizeof (EFI_IPv4_ADDRESS));\r
+    }\r
+\r
+    DefaultInfo.IpCnt = 0;\r
+\r
+    if (DefaultInfo.MustUseList) {\r
+      BootSvrEntry  = VendorOpt->BootSvr;\r
+      Status        = EFI_INVALID_PARAMETER;\r
+\r
+      while (((UINT8) (BootSvrEntry - VendorOpt->BootSvr)) < VendorOpt->BootSvrLen) {\r
+\r
+        if (BootSvrEntry->Type == HTONS (Type)) {\r
+          Status = EFI_SUCCESS;\r
+          break;\r
+        }\r
+\r
+        BootSvrEntry = GET_NEXT_BOOT_SVR_ENTRY (BootSvrEntry);\r
+      }\r
+\r
+      if (EFI_ERROR (Status)) {\r
+        return Status;\r
+      }\r
+\r
+      DefaultInfo.IpCnt = BootSvrEntry->IpCnt;\r
+    }\r
+\r
+    Info = &DefaultInfo;\r
+  } else {\r
+\r
+    SrvList = Info->SrvList;\r
+\r
+    if (!SrvList[0].AcceptAnyResponse) {\r
+\r
+      for (Index = 1; Index < Info->IpCnt; Index++) {\r
+        if (SrvList[Index].AcceptAnyResponse) {\r
+          break;\r
+        }\r
+      }\r
+\r
+      if (Index != Info->IpCnt) {\r
+        return EFI_INVALID_PARAMETER;\r
+      }\r
+    }\r
+  }\r
+\r
+  if ((!Info->UseUCast && !Info->UseBCast && !Info->UseMCast) || (Info->MustUseList && Info->IpCnt == 0)) {\r
+\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+  //\r
+  // Execute discover by UniCast/BroadCast/MultiCast\r
+  //\r
+  if (Info->UseUCast) {\r
+\r
+    for (Index = 0; Index < Info->IpCnt; Index++) {\r
+\r
+      if (BootSvrEntry == NULL) {\r
+        Private->ServerIp.Addr[0] = SrvList[Index].IpAddr.Addr[0];\r
+      } else {\r
+        NetCopyMem (&Private->ServerIp, &BootSvrEntry->IpAddr[Index], sizeof (EFI_IPv4_ADDRESS));\r
+      }\r
+\r
+      Status = PxeBcDiscvBootService (\r
+                Private,\r
+                Type,\r
+                Layer,\r
+                UseBis,\r
+                &SrvList[Index].IpAddr,\r
+                0,\r
+                NULL,\r
+                TRUE,\r
+                &Private->PxeReply.Packet.Ack\r
+                );\r
+    }\r
+\r
+  } else if (Info->UseMCast) {\r
+\r
+    Status = PxeBcDiscvBootService (\r
+              Private,\r
+              Type,\r
+              Layer,\r
+              UseBis,\r
+              &Info->ServerMCastIp,\r
+              0,\r
+              NULL,\r
+              TRUE,\r
+              &Private->PxeReply.Packet.Ack\r
+              );\r
+\r
+  } else if (Info->UseBCast) {\r
+\r
+    Status = PxeBcDiscvBootService (\r
+              Private,\r
+              Type,\r
+              Layer,\r
+              UseBis,\r
+              NULL,\r
+              Info->IpCnt,\r
+              SrvList,\r
+              TRUE,\r
+              &Private->PxeReply.Packet.Ack\r
+              );\r
+  }\r
+\r
+  if (EFI_ERROR (Status) || !Mode->PxeReplyReceived || (!Mode->PxeBisReplyReceived && UseBis)) {\r
+\r
+    Status = EFI_DEVICE_ERROR;\r
+  } else {\r
+    PxeBcParseCachedDhcpPacket (&Private->PxeReply);\r
+  }\r
+\r
+  if (Mode->PxeBisReplyReceived) {\r
+    NetCopyMem (&Private->ServerIp, &Mode->PxeReply.Dhcpv4.BootpSiAddr, sizeof (EFI_IPv4_ADDRESS));\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  GC_NOTO: Add function description\r
+\r
+  @param  This                                        GC_NOTO: add argument\r
+                                                      description\r
+  @param  Operation                                   GC_NOTO: add argument\r
+                                                      description\r
+  @param  BufferPtr                                   GC_NOTO: add argument\r
+                                                      description\r
+  @param  Overwrite                                   GC_NOTO: add argument\r
+                                                      description\r
+  @param  BufferSize                                  GC_NOTO: add argument\r
+                                                      description\r
+  @param  BlockSize                                   GC_NOTO: add argument\r
+                                                      description\r
+  @param  ServerIp                                    GC_NOTO: add argument\r
+                                                      description\r
+  @param  Filename                                    GC_NOTO: add argument\r
+                                                      description\r
+  @param  Info                                        GC_NOTO: add argument\r
+                                                      description\r
+  @param  DontUseBuffer                               GC_NOTO: add argument\r
+                                                      description\r
+\r
+  @retval EFI_INVALID_PARAMETER                       GC_NOTO: Add description for\r
+                                                      return value\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+EfiPxeBcMtftp (\r
+  IN EFI_PXE_BASE_CODE_PROTOCOL       *This,\r
+  IN EFI_PXE_BASE_CODE_TFTP_OPCODE    Operation,\r
+  IN OUT VOID                         *BufferPtr,\r
+  IN BOOLEAN                          Overwrite,\r
+  IN OUT UINT64                       *BufferSize,\r
+  IN UINTN                            *BlockSize    OPTIONAL,\r
+  IN EFI_IP_ADDRESS                   *ServerIp,\r
+  IN UINT8                            *Filename,\r
+  IN EFI_PXE_BASE_CODE_MTFTP_INFO     *Info         OPTIONAL,\r
+  IN BOOLEAN                          DontUseBuffer\r
+  )\r
+{\r
+  PXEBC_PRIVATE_DATA      *Private;\r
+  EFI_MTFTP4_CONFIG_DATA  Mtftp4Config;\r
+  EFI_STATUS              Status;\r
+\r
+  if ((This == NULL) ||\r
+      (Filename == NULL) ||\r
+      (BufferSize == NULL) ||\r
+      ((ServerIp == NULL) || !Ip4IsUnicast (NTOHL (ServerIp->Addr[0]), 0)) ||\r
+      ((BufferPtr == NULL) && DontUseBuffer) ||\r
+      ((BlockSize != NULL) && (*BlockSize < 512))) {\r
+\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  Status  = EFI_DEVICE_ERROR;\r
+  Private = PXEBC_PRIVATE_DATA_FROM_PXEBC (This);\r
+\r
+  Mtftp4Config.UseDefaultSetting = FALSE;\r
+  Mtftp4Config.TimeoutValue      = PXEBC_MTFTP_TIMEOUT;\r
+  Mtftp4Config.TryCount          = PXEBC_MTFTP_RETRIES;\r
+\r
+  NetCopyMem (&Mtftp4Config.StationIp, &Private->StationIp, sizeof (EFI_IPv4_ADDRESS));\r
+  NetCopyMem (&Mtftp4Config.SubnetMask, &Private->SubnetMask, sizeof (EFI_IPv4_ADDRESS));\r
+  NetCopyMem (&Mtftp4Config.GatewayIp, &Private->GatewayIp, sizeof (EFI_IPv4_ADDRESS));\r
+  NetCopyMem (&Mtftp4Config.ServerIp, ServerIp, sizeof (EFI_IPv4_ADDRESS));\r
+\r
+  switch (Operation) {\r
+\r
+  case EFI_PXE_BASE_CODE_TFTP_GET_FILE_SIZE:\r
+\r
+    Status = PxeBcTftpGetFileSize (\r
+              Private,\r
+              &Mtftp4Config,\r
+              Filename,\r
+              BlockSize,\r
+              BufferSize\r
+              );\r
+\r
+    if (!EFI_ERROR (Status)) {\r
+      Status = EFI_BUFFER_TOO_SMALL;\r
+    }\r
+\r
+    break;\r
+\r
+  case EFI_PXE_BASE_CODE_TFTP_READ_FILE:\r
+\r
+    Status = PxeBcTftpReadFile (\r
+              Private,\r
+              &Mtftp4Config,\r
+              Filename,\r
+              BlockSize,\r
+              BufferPtr,\r
+              BufferSize,\r
+              DontUseBuffer\r
+              );\r
+\r
+    break;\r
+\r
+  case EFI_PXE_BASE_CODE_TFTP_WRITE_FILE:\r
+\r
+    Status = PxeBcTftpWriteFile (\r
+              Private,\r
+              &Mtftp4Config,\r
+              Filename,\r
+              Overwrite,\r
+              BlockSize,\r
+              BufferPtr,\r
+              BufferSize\r
+              );\r
+\r
+    break;\r
+\r
+  case EFI_PXE_BASE_CODE_TFTP_READ_DIRECTORY:\r
+\r
+    Status = PxeBcTftpReadDirectory (\r
+              Private,\r
+              &Mtftp4Config,\r
+              Filename,\r
+              BlockSize,\r
+              BufferPtr,\r
+              BufferSize,\r
+              DontUseBuffer\r
+              );\r
+\r
+    break;\r
+\r
+  case EFI_PXE_BASE_CODE_MTFTP_GET_FILE_SIZE:\r
+  case EFI_PXE_BASE_CODE_MTFTP_READ_FILE:\r
+  case EFI_PXE_BASE_CODE_MTFTP_READ_DIRECTORY:\r
+    Status = EFI_UNSUPPORTED;\r
+    break;\r
+\r
+  default:\r
+\r
+    Status = EFI_INVALID_PARAMETER;\r
+    break;\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  GC_NOTO: Add function description\r
+\r
+  @param  This                                        GC_NOTO: add argument\r
+                                                      description\r
+  @param  OpFlags                                     GC_NOTO: add argument\r
+                                                      description\r
+  @param  DestIp                                      GC_NOTO: add argument\r
+                                                      description\r
+  @param  DestPort                                    GC_NOTO: add argument\r
+                                                      description\r
+  @param  GatewayIp                                   GC_NOTO: add argument\r
+                                                      description\r
+  @param  SrcIp                                       GC_NOTO: add argument\r
+                                                      description\r
+  @param  SrcPort                                     GC_NOTO: add argument\r
+                                                      description\r
+  @param  HeaderSize                                  GC_NOTO: add argument\r
+                                                      description\r
+  @param  HeaderPtr                                   GC_NOTO: add argument\r
+                                                      description\r
+  @param  BufferSize                                  GC_NOTO: add argument\r
+                                                      description\r
+  @param  BufferPtr                                   GC_NOTO: add argument\r
+                                                      description\r
+\r
+  @retval EFI_INVALID_PARAMETER                       GC_NOTO: Add description for\r
+                                                      return value\r
+  @retval EFI_INVALID_PARAMETER                       GC_NOTO: Add description for\r
+                                                      return value\r
+  @retval EFI_INVALID_PARAMETER                       GC_NOTO: Add description for\r
+                                                      return value\r
+  @retval EFI_INVALID_PARAMETER                       GC_NOTO: Add description for\r
+                                                      return value\r
+  @retval EFI_OUT_OF_RESOURCES                        GC_NOTO: Add description for\r
+                                                      return value\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+EfiPxeBcUdpWrite (\r
+  IN EFI_PXE_BASE_CODE_PROTOCOL       *This,\r
+  IN UINT16                           OpFlags,\r
+  IN EFI_IP_ADDRESS                   *DestIp,\r
+  IN EFI_PXE_BASE_CODE_UDP_PORT       *DestPort,\r
+  IN EFI_IP_ADDRESS                   *GatewayIp  OPTIONAL,\r
+  IN EFI_IP_ADDRESS                   *SrcIp      OPTIONAL,\r
+  IN OUT EFI_PXE_BASE_CODE_UDP_PORT   *SrcPort    OPTIONAL,\r
+  IN UINTN                            *HeaderSize OPTIONAL,\r
+  IN VOID                             *HeaderPtr  OPTIONAL,\r
+  IN UINTN                            *BufferSize,\r
+  IN VOID                             *BufferPtr\r
+  )\r
+{\r
+  PXEBC_PRIVATE_DATA        *Private;\r
+  EFI_UDP4_PROTOCOL         *Udp4;\r
+  EFI_UDP4_COMPLETION_TOKEN Token;\r
+  EFI_UDP4_TRANSMIT_DATA    *Udp4TxData;\r
+  UINT32                    FragCount;\r
+  UINT32                    DataLength;\r
+  EFI_UDP4_SESSION_DATA     Udp4Session;\r
+  EFI_STATUS                Status;\r
+  BOOLEAN                   IsDone;\r
+  UINT16                    RandomSrcPort;\r
+\r
+  IsDone = FALSE;\r
+\r
+  if ((This == NULL) || (DestIp == NULL) || (DestPort == NULL)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if ((GatewayIp != NULL) && !Ip4IsUnicast (NTOHL (GatewayIp->Addr[0]), 0)) {\r
+    //\r
+    // Gateway is provided but it's not a unicast IP address.\r
+    //\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if ((HeaderSize != NULL) && ((*HeaderSize == 0) || (HeaderPtr == NULL))) {\r
+    //\r
+    // The HeaderSize ptr isn't NULL and: 1. the value is zero; or 2. the HeaderPtr\r
+    // is NULL.\r
+    //\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if ((BufferSize == NULL) || ((*BufferSize != 0) && (BufferPtr == NULL))) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  Private = PXEBC_PRIVATE_DATA_FROM_PXEBC (This);\r
+  Udp4    = Private->Udp4;\r
+\r
+  if (!Private->AddressIsOk && (SrcIp == NULL)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if (SrcIp == NULL) {\r
+    SrcIp = &Private->StationIp;\r
+\r
+    if (GatewayIp == NULL) {\r
+      GatewayIp = &Private->GatewayIp;\r
+    }\r
+  }\r
+\r
+  if ((SrcPort == NULL) || (OpFlags & EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_PORT)) {\r
+    RandomSrcPort = (UINT16) (NET_RANDOM (NetRandomInitSeed ()) % 10000 + 1024);\r
+\r
+    if (SrcPort == NULL) {\r
+\r
+      SrcPort  = &RandomSrcPort;\r
+    } else {\r
+\r
+      *SrcPort = RandomSrcPort;\r
+    }\r
+  }\r
+\r
+  ZeroMem (&Token, sizeof (EFI_UDP4_COMPLETION_TOKEN));\r
+  ZeroMem (&Udp4Session, sizeof (EFI_UDP4_SESSION_DATA));\r
+\r
+  NetCopyMem (&Udp4Session.DestinationAddress, DestIp, sizeof (EFI_IPv4_ADDRESS));\r
+  Udp4Session.DestinationPort = *DestPort;\r
+  NetCopyMem (&Udp4Session.SourceAddress, SrcIp, sizeof (EFI_IPv4_ADDRESS));\r
+  Udp4Session.SourcePort = *SrcPort;\r
+\r
+  FragCount = (HeaderSize != NULL) ? 2 : 1;\r
+  Udp4TxData = (EFI_UDP4_TRANSMIT_DATA *) NetAllocatePool (sizeof (EFI_UDP4_TRANSMIT_DATA) + (FragCount - 1) * sizeof (EFI_UDP4_FRAGMENT_DATA));\r
+  if (Udp4TxData == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  Udp4TxData->FragmentCount = FragCount;\r
+  Udp4TxData->FragmentTable[FragCount - 1].FragmentLength = (UINT32) *BufferSize;\r
+  Udp4TxData->FragmentTable[FragCount - 1].FragmentBuffer = BufferPtr;\r
+  DataLength = (UINT32) *BufferSize;\r
+\r
+  if (FragCount == 2) {\r
+\r
+    Udp4TxData->FragmentTable[0].FragmentLength = (UINT32) *HeaderSize;\r
+    Udp4TxData->FragmentTable[0].FragmentBuffer = HeaderPtr;\r
+    DataLength += (UINT32) *HeaderSize;\r
+  }\r
+\r
+  Udp4TxData->GatewayAddress  = (EFI_IPv4_ADDRESS *) GatewayIp;\r
+  Udp4TxData->UdpSessionData  = &Udp4Session;\r
+  Udp4TxData->DataLength      = DataLength;\r
+  Token.Packet.TxData         = Udp4TxData;\r
+\r
+  Status = gBS->CreateEvent (\r
+                  EVT_NOTIFY_SIGNAL,\r
+                  NET_TPL_EVENT,\r
+                  PxeBcCommonNotify,\r
+                  &IsDone,\r
+                  &Token.Event\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    goto ON_EXIT;\r
+  }\r
+\r
+  Status = Udp4->Transmit (Udp4, &Token);\r
+  if (EFI_ERROR (Status)) {\r
+    goto ON_EXIT;\r
+  }\r
+\r
+  while (!IsDone) {\r
+\r
+    Udp4->Poll (Udp4);\r
+  }\r
+\r
+  Status = Token.Status;\r
+\r
+ON_EXIT:\r
+\r
+  if (Token.Event != NULL) {\r
+    gBS->CloseEvent (Token.Event);\r
+  }\r
+\r
+  NetFreePool (Udp4TxData);\r
+\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  GC_NOTO: Add function description\r
+\r
+  @param  This                                        GC_NOTO: add argument\r
+                                                      description\r
+  @param  OpFlags                                     GC_NOTO: add argument\r
+                                                      description\r
+  @param  DestIp                                      GC_NOTO: add argument\r
+                                                      description\r
+  @param  DestPort                                    GC_NOTO: add argument\r
+                                                      description\r
+  @param  SrcIp                                       GC_NOTO: add argument\r
+                                                      description\r
+  @param  SrcPort                                     GC_NOTO: add argument\r
+                                                      description\r
+  @param  HeaderSize                                  GC_NOTO: add argument\r
+                                                      description\r
+  @param  HeaderPtr                                   GC_NOTO: add argument\r
+                                                      description\r
+  @param  BufferSize                                  GC_NOTO: add argument\r
+                                                      description\r
+  @param  BufferPtr                                   GC_NOTO: add argument\r
+                                                      description\r
+\r
+  @retval EFI_INVALID_PARAMETER                       GC_NOTO: Add description for\r
+                                                      return value\r
+  @retval EFI_INVALID_PARAMETER                       GC_NOTO: Add description for\r
+                                                      return value\r
+  @retval EFI_INVALID_PARAMETER                       GC_NOTO: Add description for\r
+                                                      return value\r
+  @retval EFI_INVALID_PARAMETER                       GC_NOTO: Add description for\r
+                                                      return value\r
+  @retval EFI_NOT_STARTED                             GC_NOTO: Add description for\r
+                                                      return value\r
+  @retval EFI_OUT_OF_RESOURCES                        GC_NOTO: Add description for\r
+                                                      return value\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+EfiPxeBcUdpRead (\r
+  IN EFI_PXE_BASE_CODE_PROTOCOL       *This,\r
+  IN UINT16                           OpFlags,\r
+  IN OUT EFI_IP_ADDRESS               *DestIp, OPTIONAL\r
+  IN OUT EFI_PXE_BASE_CODE_UDP_PORT   *DestPort, OPTIONAL\r
+  IN OUT EFI_IP_ADDRESS               *SrcIp, OPTIONAL\r
+  IN OUT EFI_PXE_BASE_CODE_UDP_PORT   *SrcPort, OPTIONAL\r
+  IN UINTN                            *HeaderSize, OPTIONAL\r
+  IN VOID                             *HeaderPtr, OPTIONAL\r
+  IN OUT UINTN                        *BufferSize,\r
+  IN VOID                             *BufferPtr\r
+  )\r
+{\r
+  PXEBC_PRIVATE_DATA        *Private;\r
+  EFI_PXE_BASE_CODE_MODE    *Mode;\r
+  EFI_UDP4_PROTOCOL         *Udp4;\r
+  EFI_UDP4_COMPLETION_TOKEN Token;\r
+  EFI_UDP4_RECEIVE_DATA     *RxData;\r
+  EFI_UDP4_SESSION_DATA     *Session;\r
+  EFI_STATUS                Status;\r
+  BOOLEAN                   IsDone;\r
+  BOOLEAN                   Matched;\r
+  UINTN                     CopyLen;\r
+\r
+  if (This == NULL || DestIp == NULL || DestPort == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if (OpFlags & EFI_PXE_BASE_CODE_UDP_OPFLAGS_USE_FILTER) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  if ((!(OpFlags & EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_DEST_PORT) && (DestPort == NULL)) ||\r
+      (!(OpFlags & EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_DEST_PORT) && (SrcIp == NULL)) ||\r
+      (!(OpFlags & EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_PORT) && (SrcPort == NULL))) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if (((HeaderSize != NULL) && (*HeaderSize == 0)) || ((HeaderPtr == NULL) && (*HeaderSize != 0))) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if ((BufferSize == NULL) || ((BufferPtr == NULL) && (*BufferSize != 0))) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  Private = PXEBC_PRIVATE_DATA_FROM_PXEBC (This);\r
+  Mode    = Private->PxeBc.Mode;\r
+  Udp4    = Private->Udp4;\r
+\r
+  if (!Mode->Started) {\r
+    return EFI_NOT_STARTED;\r
+  }\r
+\r
+  Status = gBS->CreateEvent (\r
+                  EVT_NOTIFY_SIGNAL,\r
+                  NET_TPL_EVENT,\r
+                  PxeBcCommonNotify,\r
+                  &IsDone,\r
+                  &Token.Event\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  IsDone = FALSE;\r
+  Status = Udp4->Receive (Udp4, &Token);\r
+  if (EFI_ERROR (Status)) {\r
+    goto ON_EXIT;\r
+  }\r
+\r
+  Udp4->Poll (Udp4);\r
+\r
+  if (!IsDone) {\r
+    Status = EFI_TIMEOUT;\r
+  } else {\r
+\r
+    //\r
+    // check whether this packet matches the filters\r
+    //\r
+    if (EFI_ERROR (Token.Status)){\r
+      goto ON_EXIT;\r
+    }\r
+\r
+    RxData  = Token.Packet.RxData;\r
+    Session = &RxData->UdpSession;\r
+\r
+    Matched = FALSE;\r
+\r
+    //\r
+    // Match the destination ip of the received udp dgram\r
+    //\r
+    if (OpFlags & EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_DEST_IP) {\r
+      Matched = TRUE;\r
+\r
+      if (DestIp != NULL) {\r
+        NetCopyMem (DestIp, &Session->DestinationAddress, sizeof (EFI_IPv4_ADDRESS));\r
+      }\r
+    } else {\r
+      if (DestIp != NULL) {\r
+        if (EFI_IP4_EQUAL (DestIp, &Session->DestinationAddress)) {\r
+          Matched = TRUE;\r
+        }\r
+      } else {\r
+        if (EFI_IP4_EQUAL (&Private->StationIp, &Session->DestinationAddress)) {\r
+          Matched = TRUE;\r
+        }\r
+      }\r
+    }\r
+\r
+    if (Matched) {\r
+      //\r
+      // Match the destination port of the received udp dgram\r
+      //\r
+      if (OpFlags & EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_DEST_PORT) {\r
+\r
+        if (DestPort != NULL) {\r
+          *DestPort = Session->DestinationPort;\r
+        }\r
+      } else {\r
+\r
+        if (*DestPort != Session->DestinationPort) {\r
+          Matched = FALSE;\r
+        }\r
+      }\r
+    }\r
+\r
+    if (Matched) {\r
+      //\r
+      // Match the source ip of the received udp dgram\r
+      //\r
+      if (OpFlags & EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_IP) {\r
+\r
+        if (SrcIp != NULL) {\r
+          NetCopyMem (SrcIp, &Session->SourceAddress, sizeof (EFI_IPv4_ADDRESS));\r
+        }\r
+      } else {\r
+\r
+        if (!EFI_IP4_EQUAL (SrcIp, &Session->SourceAddress)) {\r
+          Matched = FALSE;\r
+        }\r
+      }\r
+    }\r
+\r
+    if (Matched) {\r
+      //\r
+      // Match the source port of the received udp dgram\r
+      //\r
+      if (OpFlags & EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_PORT) {\r
+\r
+        if (SrcPort != NULL) {\r
+          *SrcPort = Session->SourcePort;\r
+        }\r
+      } else {\r
+\r
+        if (*SrcPort != Session->SourcePort) {\r
+          Matched = FALSE;\r
+        }\r
+      }\r
+    }\r
+\r
+    if (Matched) {\r
+\r
+      CopyLen = 0;\r
+\r
+      if (HeaderSize != NULL) {\r
+        CopyLen = MIN (*HeaderSize, RxData->DataLength);\r
+        NetCopyMem (HeaderPtr, RxData->FragmentTable[0].FragmentBuffer, CopyLen);\r
+        *HeaderSize = CopyLen;\r
+      }\r
+\r
+      if (RxData->DataLength - CopyLen > *BufferSize) {\r
+\r
+        Status = EFI_BUFFER_TOO_SMALL;\r
+      } else {\r
+\r
+        *BufferSize = RxData->DataLength - CopyLen;\r
+        NetCopyMem (BufferPtr, (UINT8 *) RxData->FragmentTable[0].FragmentBuffer + CopyLen, *BufferSize);\r
+      }\r
+    } else {\r
+\r
+      Status = EFI_TIMEOUT;\r
+    }\r
+\r
+    //\r
+    // Recycle the RxData\r
+    //\r
+    gBS->SignalEvent (RxData->RecycleSignal);\r
+  }\r
+\r
+ON_EXIT:\r
+\r
+  Udp4->Cancel (Udp4, &Token);\r
+\r
+  gBS->CloseEvent (Token.Event);\r
+\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  GC_NOTO: Add function description\r
+\r
+  @param  This                                        GC_NOTO: add argument\r
+                                                      description\r
+  @param  NewFilter                                   GC_NOTO: add argument\r
+                                                      description\r
+\r
+  @retval EFI_UNSUPPORTED                             GC_NOTO: Add description for\r
+                                                      return value\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+EfiPxeBcSetIpFilter (\r
+  IN EFI_PXE_BASE_CODE_PROTOCOL       *This,\r
+  IN EFI_PXE_BASE_CODE_IP_FILTER      *NewFilter\r
+  )\r
+{\r
+  return EFI_UNSUPPORTED;\r
+}\r
+\r
+\r
+/**\r
+  GC_NOTO: Add function description\r
+\r
+  @param  This                                        GC_NOTO: add argument\r
+                                                      description\r
+  @param  IpAddr                                      GC_NOTO: add argument\r
+                                                      description\r
+  @param  MacAddr                                     GC_NOTO: add argument\r
+                                                      description\r
+\r
+  @retval EFI_UNSUPPORTED                             GC_NOTO: Add description for\r
+                                                      return value\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+EfiPxeBcArp (\r
+  IN EFI_PXE_BASE_CODE_PROTOCOL       * This,\r
+  IN EFI_IP_ADDRESS                   * IpAddr,\r
+  IN EFI_MAC_ADDRESS                  * MacAddr OPTIONAL\r
+  )\r
+{\r
+  return EFI_UNSUPPORTED;\r
+}\r
+\r
+\r
+/**\r
+  GC_NOTO: Add function description\r
+\r
+  @param  This                                        GC_NOTO: add argument\r
+                                                      description\r
+  @param  NewAutoArp                                  GC_NOTO: add argument\r
+                                                      description\r
+  @param  NewSendGUID                                 GC_NOTO: add argument\r
+                                                      description\r
+  @param  NewTTL                                      GC_NOTO: add argument\r
+                                                      description\r
+  @param  NewToS                                      GC_NOTO: add argument\r
+                                                      description\r
+  @param  NewMakeCallback                             GC_NOTO: add argument\r
+                                                      description\r
+\r
+  @return GC_NOTO: add return values\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+EfiPxeBcSetParameters (\r
+  IN EFI_PXE_BASE_CODE_PROTOCOL       *This,\r
+  IN BOOLEAN                          *NewAutoArp, OPTIONAL\r
+  IN BOOLEAN                          *NewSendGUID, OPTIONAL\r
+  IN UINT8                            *NewTTL, OPTIONAL\r
+  IN UINT8                            *NewToS, OPTIONAL\r
+  IN BOOLEAN                          *NewMakeCallback  // OPTIONAL\r
+  )\r
+{\r
+  PXEBC_PRIVATE_DATA      *Private;\r
+  EFI_PXE_BASE_CODE_MODE  *Mode;\r
+  EFI_STATUS              Status;\r
+\r
+  Status = EFI_SUCCESS;\r
+\r
+  if (This == NULL) {\r
+    Status = EFI_INVALID_PARAMETER;\r
+    goto ON_EXIT;\r
+  }\r
+\r
+  Private = PXEBC_PRIVATE_DATA_FROM_PXEBC (This);\r
+  Mode    = Private->PxeBc.Mode;\r
+\r
+  if (NewSendGUID != NULL && *NewSendGUID == TRUE) {\r
+    //\r
+    // FixMe, cann't locate SendGuid\r
+    //\r
+  }\r
+\r
+  if (NewMakeCallback != NULL && *NewMakeCallback == TRUE) {\r
+\r
+    Status = gBS->HandleProtocol (\r
+                    Private->Controller,\r
+                    &gEfiPxeBaseCodeCallbackProtocolGuid,\r
+                    (VOID **) &Private->PxeBcCallback\r
+                    );\r
+    if (EFI_ERROR (Status) || (Private->PxeBcCallback->Callback == NULL)) {\r
+\r
+      Status = EFI_INVALID_PARAMETER;\r
+      goto ON_EXIT;\r
+    }\r
+  }\r
+\r
+  if (!Mode->Started) {\r
+    Status = EFI_NOT_STARTED;\r
+    goto ON_EXIT;\r
+  }\r
+\r
+  if (NewMakeCallback != NULL) {\r
+\r
+    if (*NewMakeCallback) {\r
+      //\r
+      // Update the Callback protocol.\r
+      //\r
+      Status = gBS->HandleProtocol (\r
+                      Private->Controller,\r
+                      &gEfiPxeBaseCodeCallbackProtocolGuid,\r
+                      (VOID **) &Private->PxeBcCallback\r
+                      );\r
+\r
+      if (EFI_ERROR (Status) || (Private->PxeBcCallback->Callback == NULL)) {\r
+        Status = EFI_INVALID_PARAMETER;\r
+        goto ON_EXIT;\r
+      }\r
+    } else {\r
+      Private->PxeBcCallback = NULL;\r
+    }\r
+\r
+    Mode->MakeCallbacks = *NewMakeCallback;\r
+  }\r
+\r
+  if (NewAutoArp != NULL) {\r
+    Mode->AutoArp = *NewAutoArp;\r
+  }\r
+\r
+  if (NewSendGUID != NULL) {\r
+    Mode->SendGUID = *NewSendGUID;\r
+  }\r
+\r
+  if (NewTTL != NULL) {\r
+    Mode->TTL = *NewTTL;\r
+  }\r
+\r
+  if (NewToS != NULL) {\r
+    Mode->ToS = *NewToS;\r
+  }\r
+\r
+ON_EXIT:\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  GC_NOTO: Add function description\r
+\r
+  @param  This                                        GC_NOTO: add argument\r
+                                                      description\r
+  @param  NewStationIp                                GC_NOTO: add argument\r
+                                                      description\r
+  @param  NewSubnetMask                               GC_NOTO: add argument\r
+                                                      description\r
+\r
+  @retval EFI_INVALID_PARAMETER                       GC_NOTO: Add description for\r
+                                                      return value\r
+  @retval EFI_INVALID_PARAMETER                       GC_NOTO: Add description for\r
+                                                      return value\r
+  @retval EFI_INVALID_PARAMETER                       GC_NOTO: Add description for\r
+                                                      return value\r
+  @retval EFI_NOT_STARTED                             GC_NOTO: Add description for\r
+                                                      return value\r
+  @retval EFI_SUCCESS                                 GC_NOTO: Add description for\r
+                                                      return value\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+EfiPxeBcSetStationIP (\r
+  IN EFI_PXE_BASE_CODE_PROTOCOL       * This,\r
+  IN EFI_IP_ADDRESS                   * NewStationIp, OPTIONAL\r
+  IN EFI_IP_ADDRESS                   * NewSubnetMask OPTIONAL\r
+  )\r
+{\r
+  PXEBC_PRIVATE_DATA      *Private;\r
+  EFI_PXE_BASE_CODE_MODE  *Mode;\r
+\r
+  if (This == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if (NewStationIp != NULL && !Ip4IsUnicast (NTOHL (NewStationIp->Addr[0]), 0)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if (NewSubnetMask != NULL && !IP4_IS_VALID_NETMASK (NTOHL (NewSubnetMask->Addr[0]))) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  Private = PXEBC_PRIVATE_DATA_FROM_PXEBC (This);\r
+  Mode    = Private->PxeBc.Mode;\r
+\r
+  if (!Mode->Started) {\r
+    return EFI_NOT_STARTED;\r
+  }\r
+\r
+  if (NewStationIp != NULL) {\r
+    Mode->StationIp = *NewStationIp;\r
+  }\r
+\r
+  if (NewSubnetMask != NULL) {\r
+    Mode->SubnetMask = *NewSubnetMask;\r
+  }\r
+\r
+  Private->AddressIsOk = TRUE;\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+  GC_NOTO: Add function description\r
+\r
+  @param  This                                        GC_NOTO: add argument\r
+                                                      description\r
+  @param  NewDhcpDiscoverValid                        GC_NOTO: add argument\r
+                                                      description\r
+  @param  NewDhcpAckReceived                          GC_NOTO: add argument\r
+                                                      description\r
+  @param  NewProxyOfferReceived                       GC_NOTO: add argument\r
+                                                      description\r
+  @param  NewPxeDiscoverValid                         GC_NOTO: add argument\r
+                                                      description\r
+  @param  NewPxeReplyReceived                         GC_NOTO: add argument\r
+                                                      description\r
+  @param  NewPxeBisReplyReceived                      GC_NOTO: add argument\r
+                                                      description\r
+  @param  NewDhcpDiscover                             GC_NOTO: add argument\r
+                                                      description\r
+  @param  NewDhcpAck                                  GC_NOTO: add argument\r
+                                                      description\r
+  @param  NewProxyOffer                               GC_NOTO: add argument\r
+                                                      description\r
+  @param  NewPxeDiscover                              GC_NOTO: add argument\r
+                                                      description\r
+  @param  NewPxeReply                                 GC_NOTO: add argument\r
+                                                      description\r
+  @param  NewPxeBisReply                              GC_NOTO: add argument\r
+                                                      description\r
+\r
+  @retval EFI_INVALID_PARAMETER                       GC_NOTO: Add description for\r
+                                                      return value\r
+  @retval EFI_NOT_STARTED                             GC_NOTO: Add description for\r
+                                                      return value\r
+  @retval EFI_SUCCESS                                 GC_NOTO: Add description for\r
+                                                      return value\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+EfiPxeBcSetPackets (\r
+  IN EFI_PXE_BASE_CODE_PROTOCOL       * This,\r
+  IN BOOLEAN                          * NewDhcpDiscoverValid, OPTIONAL\r
+  IN BOOLEAN                          * NewDhcpAckReceived, OPTIONAL\r
+  IN BOOLEAN                          * NewProxyOfferReceived, OPTIONAL\r
+  IN BOOLEAN                          * NewPxeDiscoverValid, OPTIONAL\r
+  IN BOOLEAN                          * NewPxeReplyReceived, OPTIONAL\r
+  IN BOOLEAN                          * NewPxeBisReplyReceived, OPTIONAL\r
+  IN EFI_PXE_BASE_CODE_PACKET         * NewDhcpDiscover, OPTIONAL\r
+  IN EFI_PXE_BASE_CODE_PACKET         * NewDhcpAck, OPTIONAL\r
+  IN EFI_PXE_BASE_CODE_PACKET         * NewProxyOffer, OPTIONAL\r
+  IN EFI_PXE_BASE_CODE_PACKET         * NewPxeDiscover, OPTIONAL\r
+  IN EFI_PXE_BASE_CODE_PACKET         * NewPxeReply, OPTIONAL\r
+  IN EFI_PXE_BASE_CODE_PACKET         * NewPxeBisReply OPTIONAL\r
+  )\r
+{\r
+  PXEBC_PRIVATE_DATA      *Private;\r
+  EFI_PXE_BASE_CODE_MODE  *Mode;\r
+\r
+  if (This == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  Private = PXEBC_PRIVATE_DATA_FROM_PXEBC (This);\r
+  Mode    = Private->PxeBc.Mode;\r
+\r
+  if (!Mode->Started) {\r
+    return EFI_NOT_STARTED;\r
+  }\r
+\r
+  Private->FileSize = 0;\r
+\r
+  if (NewDhcpDiscoverValid != NULL) {\r
+    Mode->DhcpDiscoverValid = *NewDhcpDiscoverValid;\r
+  }\r
+\r
+  if (NewDhcpAckReceived != NULL) {\r
+    Mode->DhcpAckReceived = *NewDhcpAckReceived;\r
+  }\r
+\r
+  if (NewProxyOfferReceived != NULL) {\r
+    Mode->ProxyOfferReceived = *NewProxyOfferReceived;\r
+  }\r
+\r
+  if (NewPxeDiscoverValid != NULL) {\r
+    Mode->PxeDiscoverValid = *NewPxeDiscoverValid;\r
+  }\r
+\r
+  if (NewPxeReplyReceived != NULL) {\r
+    Mode->PxeReplyReceived = *NewPxeReplyReceived;\r
+  }\r
+\r
+  if (NewPxeBisReplyReceived != NULL) {\r
+    Mode->PxeBisReplyReceived = *NewPxeBisReplyReceived;\r
+  }\r
+\r
+  if (NewDhcpDiscover != NULL) {\r
+    NetCopyMem (&Mode->DhcpDiscover, NewDhcpDiscover, sizeof (EFI_PXE_BASE_CODE_PACKET));\r
+  }\r
+\r
+  if (NewDhcpAck != NULL) {\r
+    NetCopyMem (&Mode->DhcpAck, NewDhcpAck, sizeof (EFI_PXE_BASE_CODE_PACKET));\r
+  }\r
+\r
+  if (NewProxyOffer != NULL) {\r
+    NetCopyMem (&Mode->ProxyOffer, NewProxyOffer, sizeof (EFI_PXE_BASE_CODE_PACKET));\r
+  }\r
+\r
+  if (NewPxeDiscover != NULL) {\r
+    NetCopyMem (&Mode->PxeDiscover, NewPxeDiscover, sizeof (EFI_PXE_BASE_CODE_PACKET));\r
+  }\r
+\r
+  if (NewPxeReply != NULL) {\r
+    NetCopyMem (&Mode->PxeReply, NewPxeReply, sizeof (EFI_PXE_BASE_CODE_PACKET));\r
+  }\r
+\r
+  if (NewPxeBisReply != NULL) {\r
+    NetCopyMem (&Mode->PxeBisReply, NewPxeBisReply, sizeof (EFI_PXE_BASE_CODE_PACKET));\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_PXE_BASE_CODE_PROTOCOL  mPxeBcProtocolTemplate = {\r
+  EFI_PXE_BASE_CODE_PROTOCOL_REVISION,\r
+  EfiPxeBcStart,\r
+  EfiPxeBcStop,\r
+  EfiPxeBcDhcp,\r
+  EfiPxeBcDiscover,\r
+  EfiPxeBcMtftp,\r
+  EfiPxeBcUdpWrite,\r
+  EfiPxeBcUdpRead,\r
+  EfiPxeBcSetIpFilter,\r
+  EfiPxeBcArp,\r
+  EfiPxeBcSetParameters,\r
+  EfiPxeBcSetStationIP,\r
+  EfiPxeBcSetPackets,\r
+  NULL\r
+};\r
+\r
+\r
+/**\r
+  GC_NOTO: Add function description\r
+\r
+  @param  This                                        GC_NOTO: add argument\r
+                                                      description\r
+  @param  Function                                    GC_NOTO: add argument\r
+                                                      description\r
+  @param  Received                                    GC_NOTO: add argument\r
+                                                      description\r
+  @param  PacketLength                                GC_NOTO: add argument\r
+                                                      description\r
+  @param  PacketPtr                                   GC_NOTO: add argument\r
+                                                      description\r
+\r
+  @retval EFI_PXE_BASE_CODE_CALLBACK_STATUS_ABORT     GC_NOTO: Add description for\r
+                                                      return value\r
+  @retval EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE  GC_NOTO: Add description for\r
+                                                      return value\r
+  @retval EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE  GC_NOTO: Add description for\r
+                                                      return value\r
+  @retval EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE  GC_NOTO: Add description for\r
+                                                      return value\r
+  @retval EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE  GC_NOTO: Add description for\r
+                                                      return value\r
+\r
+**/\r
+EFI_PXE_BASE_CODE_CALLBACK_STATUS\r
+EFIAPI\r
+EfiPxeLoadFileCallback (\r
+  IN EFI_PXE_BASE_CODE_CALLBACK_PROTOCOL  * This,\r
+  IN EFI_PXE_BASE_CODE_FUNCTION           Function,\r
+  IN BOOLEAN                              Received,\r
+  IN UINT32                               PacketLength,\r
+  IN EFI_PXE_BASE_CODE_PACKET             * PacketPtr OPTIONAL\r
+  )\r
+{\r
+  EFI_INPUT_KEY Key;\r
+  EFI_STATUS    Status;\r
+\r
+  //\r
+  // Catch Ctrl-C or ESC to abort.\r
+  //\r
+  Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r
+\r
+  if (!EFI_ERROR (Status)) {\r
+\r
+    if (Key.ScanCode == SCAN_ESC || Key.UnicodeChar == (0x1F & 'c')) {\r
+\r
+      return EFI_PXE_BASE_CODE_CALLBACK_STATUS_ABORT;\r
+    }\r
+  }\r
+  //\r
+  // No print if receive packet\r
+  //\r
+  if (Received) {\r
+    return EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE;\r
+  }\r
+  //\r
+  // Print only for three functions\r
+  //\r
+  switch (Function) {\r
+\r
+  case EFI_PXE_BASE_CODE_FUNCTION_MTFTP:\r
+    //\r
+    // Print only for open MTFTP packets, not every MTFTP packets\r
+    //\r
+    if (PacketLength != 0 && PacketPtr != NULL) {\r
+      if (PacketPtr->Raw[0x1C] != 0x00 || PacketPtr->Raw[0x1D] != 0x01) {\r
+        return EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE;\r
+      }\r
+    }\r
+    break;\r
+\r
+  case EFI_PXE_BASE_CODE_FUNCTION_DHCP:\r
+  case EFI_PXE_BASE_CODE_FUNCTION_DISCOVER:\r
+    break;\r
+\r
+  default:\r
+    return EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE;\r
+  }\r
+\r
+  if (PacketLength != 0 && PacketPtr != NULL) {\r
+    //\r
+    // Print '.' when transmit a packet\r
+    //\r
+    AsciiPrint (".");\r
+\r
+  }\r
+\r
+  return EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE;\r
+}\r
+\r
+EFI_PXE_BASE_CODE_CALLBACK_PROTOCOL mPxeBcCallBackTemplate = {\r
+  EFI_PXE_BASE_CODE_CALLBACK_PROTOCOL_REVISION,\r
+  EfiPxeLoadFileCallback\r
+};\r
+\r
+\r
+/**\r
+  GC_NOTO: Add function description\r
+\r
+  @param  Private                                     GC_NOTO: add argument\r
+                                                      description\r
+  @param  BufferSize                                  GC_NOTO: add argument\r
+                                                      description\r
+  @param  Buffer                                      GC_NOTO: add argument\r
+                                                      description\r
+\r
+  @return GC_NOTO: add return values\r
+\r
+**/\r
+EFI_STATUS\r
+DiscoverBootFile (\r
+  IN     PXEBC_PRIVATE_DATA  *Private,\r
+  IN OUT UINT64              *BufferSize,\r
+  IN     VOID                *Buffer\r
+  )\r
+{\r
+  EFI_PXE_BASE_CODE_PROTOCOL  *PxeBc;\r
+  EFI_PXE_BASE_CODE_MODE      *Mode;\r
+  EFI_STATUS                  Status;\r
+  UINT16                      Type;\r
+  UINT16                      Layer;\r
+  BOOLEAN                     UseBis;\r
+  UINTN                       BlockSize;\r
+  PXEBC_CACHED_DHCP4_PACKET   *Packet;\r
+  UINT16                      Value;\r
+\r
+  PxeBc = &Private->PxeBc;\r
+  Mode  = PxeBc->Mode;\r
+  Type  = EFI_PXE_BASE_CODE_BOOT_TYPE_BOOTSTRAP;\r
+  Layer = EFI_PXE_BASE_CODE_BOOT_LAYER_INITIAL;\r
+\r
+  //\r
+  // do DHCP.\r
+  //\r
+  Status = PxeBc->Dhcp (PxeBc, TRUE);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Select a boot server\r
+  //\r
+  Status = PxeBcSelectBootPrompt (Private);\r
+\r
+  if (Status == EFI_SUCCESS) {\r
+    Status = PxeBcSelectBootMenu (Private, &Type, TRUE);\r
+  } else if (Status == EFI_TIMEOUT) {\r
+    Status = PxeBcSelectBootMenu (Private, &Type, FALSE);\r
+  }\r
+\r
+  if (!EFI_ERROR (Status)) {\r
+\r
+    if (Type == EFI_PXE_BASE_CODE_BOOT_TYPE_BOOTSTRAP) {\r
+      //\r
+      // Local boot(PXE bootstrap server) need abort\r
+      //\r
+      return EFI_ABORTED;\r
+    }\r
+\r
+    UseBis  = (BOOLEAN) (Mode->BisSupported && Mode->BisDetected);\r
+    Status  = PxeBc->Discover (PxeBc, Type, &Layer, UseBis, NULL);\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+  }\r
+\r
+  *BufferSize = 0;\r
+  BlockSize   = 0x8000;\r
+\r
+  //\r
+  // Get bootfile name and (m)tftp server ip addresss\r
+  //\r
+  if (Mode->PxeReplyReceived) {\r
+    Packet = &Private->PxeReply;\r
+  } else if (Mode->ProxyOfferReceived) {\r
+    Packet = &Private->ProxyOffer;\r
+  } else {\r
+    Packet = &Private->Dhcp4Ack;\r
+  }\r
+\r
+  NetCopyMem (&Private->ServerIp, &Packet->Packet.Offer.Dhcp4.Header.ServerAddr, sizeof (EFI_IPv4_ADDRESS));\r
+  if (Private->ServerIp.Addr[0] == 0) {\r
+    //\r
+    // next server ip address is zero, use option 54 instead\r
+    //\r
+    NetCopyMem (\r
+      &Private->ServerIp,\r
+      Packet->Dhcp4Option[PXEBC_DHCP4_TAG_INDEX_SERVER_ID]->Data,\r
+      sizeof (EFI_IPv4_ADDRESS)\r
+      );\r
+  }\r
+\r
+  ASSERT (Packet->Dhcp4Option[PXEBC_DHCP4_TAG_INDEX_BOOTFILE] != NULL);\r
+\r
+  //\r
+  // bootlfile name\r
+  //\r
+  Private->BootFileName = (CHAR8 *) (Packet->Dhcp4Option[PXEBC_DHCP4_TAG_INDEX_BOOTFILE]->Data);\r
+\r
+  if (Packet->Dhcp4Option[PXEBC_DHCP4_TAG_INDEX_BOOTFILE_LEN] != NULL) {\r
+    //\r
+    // Already have the bootfile length option, compute the file size\r
+    //\r
+    NetCopyMem (&Value, Packet->Dhcp4Option[PXEBC_DHCP4_TAG_INDEX_BOOTFILE_LEN]->Data, sizeof (Value));\r
+    Value       = NTOHS (Value);\r
+    *BufferSize = 512 * Value;\r
+    Status      = EFI_BUFFER_TOO_SMALL;\r
+  } else {\r
+    //\r
+    // Get the bootfile size from tftp\r
+    //\r
+    Status = PxeBc->Mtftp (\r
+                      PxeBc,\r
+                      EFI_PXE_BASE_CODE_TFTP_GET_FILE_SIZE,\r
+                      Buffer,\r
+                      FALSE,\r
+                      BufferSize,\r
+                      &BlockSize,\r
+                      &Private->ServerIp,\r
+                      (UINT8 *) Private->BootFileName,\r
+                      NULL,\r
+                      FALSE\r
+                      );\r
+  }\r
+\r
+  Private->FileSize = (UINTN) *BufferSize;\r
+\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  GC_NOTO: Add function description\r
+\r
+  @param  This                                        GC_NOTO: add argument\r
+                                                      description\r
+  @param  FilePath                                    GC_NOTO: add argument\r
+                                                      description\r
+  @param  BootPolicy                                  GC_NOTO: add argument\r
+                                                      description\r
+  @param  BufferSize                                  GC_NOTO: add argument\r
+                                                      description\r
+  @param  Buffer                                      GC_NOTO: add argument\r
+                                                      description\r
+\r
+  @retval EFI_INVALID_PARAMETER                       GC_NOTO: Add description for\r
+                                                      return value\r
+  @retval EFI_UNSUPPORTED                             GC_NOTO: Add description for\r
+                                                      return value\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+EfiPxeLoadFile (\r
+  IN EFI_LOAD_FILE_PROTOCOL           * This,\r
+  IN EFI_DEVICE_PATH_PROTOCOL         * FilePath,\r
+  IN BOOLEAN                          BootPolicy,\r
+  IN OUT UINTN                        *BufferSize,\r
+  IN VOID                             *Buffer OPTIONAL\r
+  )\r
+{\r
+  PXEBC_PRIVATE_DATA          *Private;\r
+  EFI_PXE_BASE_CODE_PROTOCOL  *PxeBc;\r
+  BOOLEAN                     NewMakeCallback;\r
+  UINTN                       BlockSize;\r
+  EFI_STATUS                  Status;\r
+  UINT64                      TmpBufSize;\r
+\r
+  Private         = PXEBC_PRIVATE_DATA_FROM_LOADFILE (This);\r
+  PxeBc           = &Private->PxeBc;\r
+  NewMakeCallback = FALSE;\r
+  BlockSize       = 0x8000;\r
+  Status          = EFI_DEVICE_ERROR;\r
+\r
+  if (This == NULL || BufferSize == NULL) {\r
+\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  //\r
+  // Only support BootPolicy\r
+  //\r
+  if (!BootPolicy) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  Status = PxeBc->Start (PxeBc, FALSE);\r
+  if (EFI_ERROR (Status) && (Status != EFI_ALREADY_STARTED)) {\r
+    return Status;\r
+  }\r
+\r
+  Status = gBS->HandleProtocol (\r
+                  Private->Controller,\r
+                  &gEfiPxeBaseCodeCallbackProtocolGuid,\r
+                  (VOID **) &Private->PxeBcCallback\r
+                  );\r
+  if (Status == EFI_UNSUPPORTED) {\r
+\r
+    CopyMem (&Private->LoadFileCallback, &mPxeBcCallBackTemplate, sizeof (Private->LoadFileCallback));\r
+\r
+    Status = gBS->InstallProtocolInterface (\r
+                    &Private->Controller,\r
+                    &gEfiPxeBaseCodeCallbackProtocolGuid,\r
+                    EFI_NATIVE_INTERFACE,\r
+                    &Private->LoadFileCallback\r
+                    );\r
+\r
+    NewMakeCallback = (BOOLEAN) (Status == EFI_SUCCESS);\r
+\r
+    Status          = PxeBc->SetParameters (PxeBc, NULL, NULL, NULL, NULL, &NewMakeCallback);\r
+    if (EFI_ERROR (Status)) {\r
+      PxeBc->Stop (PxeBc);\r
+      return Status;\r
+    }\r
+  }\r
+\r
+  if (Private->FileSize == 0) {\r
+    TmpBufSize  = 0;\r
+    Status      = DiscoverBootFile (Private, &TmpBufSize, Buffer);\r
+\r
+    if (sizeof (UINTN) < sizeof (UINT64) && (TmpBufSize > 0xFFFFFFFF)) {\r
+      Status = EFI_DEVICE_ERROR;\r
+    } else {\r
+      *BufferSize = (UINTN) TmpBufSize;\r
+    }\r
+  } else if (Buffer == NULL) {\r
+    *BufferSize = Private->FileSize;\r
+    Status      = EFI_BUFFER_TOO_SMALL;\r
+  } else {\r
+    //\r
+    // Download the file.\r
+    //\r
+    TmpBufSize = (UINT64) (*BufferSize);\r
+    Status = PxeBc->Mtftp (\r
+                      PxeBc,\r
+                      EFI_PXE_BASE_CODE_TFTP_READ_FILE,\r
+                      Buffer,\r
+                      FALSE,\r
+                      &TmpBufSize,\r
+                      &BlockSize,\r
+                      &Private->ServerIp,\r
+                      (UINT8 *) Private->BootFileName,\r
+                      NULL,\r
+                      FALSE\r
+                      );\r
+  }\r
+  //\r
+  // If we added a callback protocol, now is the time to remove it.\r
+  //\r
+  if (NewMakeCallback) {\r
+\r
+    NewMakeCallback = FALSE;\r
+\r
+    PxeBc->SetParameters (PxeBc, NULL, NULL, NULL, NULL, &NewMakeCallback);\r
+\r
+    gBS->UninstallProtocolInterface (\r
+          Private->Controller,\r
+          &gEfiPxeBaseCodeCallbackProtocolGuid,\r
+          &Private->LoadFileCallback\r
+          );\r
+  }\r
+  //\r
+  // Check download status\r
+  //\r
+  switch (Status) {\r
+\r
+  case EFI_SUCCESS:\r
+    break;\r
+\r
+  case EFI_BUFFER_TOO_SMALL:\r
+    if (Buffer != NULL) {\r
+      AsciiPrint ("PXE-E05: Download buffer is smaller than requested file.\n");\r
+    } else {\r
+      return Status;\r
+    }\r
+    break;\r
+\r
+  case EFI_DEVICE_ERROR:\r
+    AsciiPrint ("PXE-E07: Network device error.\n");\r
+    break;\r
+\r
+  case EFI_OUT_OF_RESOURCES:\r
+    AsciiPrint ("PXE-E09: Could not allocate I/O buffers.\n");\r
+    break;\r
+\r
+  case EFI_NO_MEDIA:\r
+    AsciiPrint ("PXE-E12: Could not detect network connection.\n");\r
+    break;\r
+\r
+  case EFI_NO_RESPONSE:\r
+    AsciiPrint ("PXE-E16: No offer received.\n");\r
+    break;\r
+\r
+  case EFI_TIMEOUT:\r
+    AsciiPrint ("PXE-E18: Server response timeout.\n");\r
+    break;\r
+\r
+  case EFI_ABORTED:\r
+    AsciiPrint ("PXE-E21: Remote boot cancelled.\n");\r
+    break;\r
+\r
+  case EFI_ICMP_ERROR:\r
+    AsciiPrint ("PXE-E22: Client received ICMP error from server.\n");\r
+    break;\r
+\r
+  case EFI_TFTP_ERROR:\r
+    AsciiPrint ("PXE-E23: Client received TFTP error from server.\n");\r
+    break;\r
+\r
+  default:\r
+    AsciiPrint ("PXE-E99: Unexpected network error.\n");\r
+    break;\r
+  }\r
+\r
+  PxeBc->Stop (PxeBc);\r
+\r
+  return Status;\r
+}\r
+\r
+EFI_LOAD_FILE_PROTOCOL  mLoadFileProtocolTemplate = { EfiPxeLoadFile };\r
+\r
diff --git a/MdeModulePkg/Universal/Network/UefiPxeBcDxe/PxeBcImpl.h b/MdeModulePkg/Universal/Network/UefiPxeBcDxe/PxeBcImpl.h
new file mode 100644 (file)
index 0000000..6199252
--- /dev/null
@@ -0,0 +1,126 @@
+/** @file
+
+Copyright (c) 2007, 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.
+
+Module Name:
+
+  PxeBcImpl.h
+
+Abstract:
+
+
+**/
+
+#ifndef __EFI_PXEBC_IMPL_H__
+#define __EFI_PXEBC_IMPL_H__
+
+
+typedef struct _PXEBC_PRIVATE_DATA  PXEBC_PRIVATE_DATA;
+
+#include <PiDxe.h>\r
+\r
+#include <Guid/SmBios.h>\r
+#include <IndustryStandard/Smbios.h>\r
+#include <Protocol/Dhcp4.h>\r
+#include <Protocol/PxeBaseCode.h>\r
+#include <Protocol/Mtftp4.h>\r
+#include <Protocol/Udp4.h>\r
+#include <Protocol/LoadFile.h>\r
+#include <Protocol/NetworkInterfaceIdentifier.h>\r
+#include <Protocol/PxeBaseCodeCallBack.h>\r
+\r
+#include <Library/DebugLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/UefiDriverEntryPoint.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/UefiLib.h>\r
+#include <Library/BaseLib.h>\r
+#include <Library/NetLib.h>
+
+#include "PxeBcDriver.h"
+#include "PxeArch.h"
+#include "PxeBcDhcp.h"
+#include "PxeBcMtftp.h"
+#include "PxeBcSupport.h"
+
+#define PXEBC_PRIVATE_DATA_SIGNATURE  EFI_SIGNATURE_32 ('P', 'X', 'E', 'P')
+#define PXEBC_MTFTP_TIMEOUT           4
+#define PXEBC_MTFTP_RETRIES           6
+
+struct _PXEBC_PRIVATE_DATA {
+  UINT32                                    Signature;
+  EFI_HANDLE                                Controller;
+  EFI_HANDLE                                Image;
+  EFI_HANDLE                                Dhcp4Child;
+  EFI_HANDLE                                Mtftp4Child;
+  EFI_HANDLE                                Udp4Child;
+
+  EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL *Nii;
+
+  EFI_PXE_BASE_CODE_PROTOCOL                PxeBc;
+  EFI_LOAD_FILE_PROTOCOL                    LoadFile;
+  EFI_PXE_BASE_CODE_CALLBACK_PROTOCOL       LoadFileCallback;
+  EFI_PXE_BASE_CODE_CALLBACK_PROTOCOL       *PxeBcCallback;
+  EFI_DHCP4_PROTOCOL                        *Dhcp4;
+  EFI_MTFTP4_PROTOCOL                       *Mtftp4;
+  EFI_UDP4_PROTOCOL                         *Udp4;
+  EFI_UDP4_CONFIG_DATA                      Udp4CfgData;
+
+  EFI_PXE_BASE_CODE_MODE                    Mode;
+  EFI_PXE_BASE_CODE_FUNCTION                Function;
+
+  CHAR8                                     *BootFileName;
+
+  EFI_IP_ADDRESS                            StationIp;
+  EFI_IP_ADDRESS                            SubnetMask;
+  EFI_IP_ADDRESS                            GatewayIp;
+  EFI_IP_ADDRESS                            ServerIp;
+  BOOLEAN                                   AddressIsOk;
+
+  UINTN                                     FileSize;
+
+  UINT8                                     OptionBuffer[PXEBC_DHCP4_MAX_OPTION_SIZE];
+  EFI_DHCP4_PACKET                          SeedPacket;
+
+  BOOLEAN                                   SortOffers;
+  UINT32                                    NumOffers;
+  UINT32                                    SelectedOffer;
+  UINT32                                    ProxyOfferType;
+
+  //
+  // Cached packets as complements of pxe mode data
+  //
+  PXEBC_CACHED_DHCP4_PACKET                 ProxyOffer;
+  PXEBC_CACHED_DHCP4_PACKET                 Dhcp4Ack;
+  PXEBC_CACHED_DHCP4_PACKET                 PxeReply;
+  PXEBC_CACHED_DHCP4_PACKET                 Dhcp4Offers[PXEBC_MAX_OFFER_NUM];
+
+  //
+  // Arrays for different types of offers:
+  //   ServerCount records the count of the servers we got the offers,
+  //   OfferIndex records the index of the offer sent by the server indexed by ServerCount.
+  //
+  UINT32                                    ServerCount[DHCP4_PACKET_TYPE_MAX];
+  UINT32                                    OfferIndex[DHCP4_PACKET_TYPE_MAX][PXEBC_MAX_OFFER_NUM];
+  UINT32                                    BootpIndex;
+  UINT32                                    ProxyIndex[DHCP4_PACKET_TYPE_MAX];
+  UINT32                                    BinlIndex[PXEBC_MAX_OFFER_NUM];
+};
+
+#define PXEBC_PRIVATE_DATA_FROM_PXEBC(a)          CR (a, PXEBC_PRIVATE_DATA, PxeBc, PXEBC_PRIVATE_DATA_SIGNATURE)
+
+#define PXEBC_PRIVATE_DATA_FROM_LOADFILE(a)       CR (a, PXEBC_PRIVATE_DATA, LoadFile, PXEBC_PRIVATE_DATA_SIGNATURE)
+
+#define PXEBC_PRIVATE_DATA_FROM_PXEBCCALLBACK(a)  CR (a, PXEBC_PRIVATE_DATA, PxeBcCallback, PXEBC_PRIVATE_DATA_SIGNATURE)
+
+extern EFI_PXE_BASE_CODE_PROTOCOL mPxeBcProtocolTemplate;
+extern EFI_LOAD_FILE_PROTOCOL     mLoadFileProtocolTemplate;
+
+#endif
diff --git a/MdeModulePkg/Universal/Network/UefiPxeBcDxe/PxeBcMtftp.c b/MdeModulePkg/Universal/Network/UefiPxeBcDxe/PxeBcMtftp.c
new file mode 100644 (file)
index 0000000..08cdb31
--- /dev/null
@@ -0,0 +1,437 @@
+/** @file\r
+\r
+Copyright (c) 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
+  PxeBcMtftp.c\r
+\r
+Abstract:\r
+\r
+  PxeBc MTFTP functions\r
+\r
+\r
+**/\r
+\r
+#include "PxeBcImpl.h"\r
+\r
+VOID *TokenContext = NULL;\r
+\r
+UINT8 *mMtftpOptions[PXE_MTFTP_OPTION_MAXIMUM_INDEX] = {\r
+  "blksize",\r
+  "timeout",\r
+  "tsize",\r
+  "multicast"\r
+};\r
+\r
+\r
+/**\r
+  This is a callback function when packets received/transmitted in Mtftp driver.\r
+\r
+  @param  This           Pointer to Mtftp protocol instance\r
+  @param  Token          Pointer to Mtftp token\r
+  @param  PacketLen      Length of Mtftp packet\r
+  @param  Packet         Pointer to Mtftp packet\r
+\r
+  @return EFI_SUCCESS\r
+  @return EFI_ABORTED\r
+\r
+**/\r
+EFI_STATUS\r
+PxeBcCheckPacket (\r
+  IN EFI_MTFTP4_PROTOCOL        *This,\r
+  IN EFI_MTFTP4_TOKEN           *Token,\r
+  IN UINT16                     PacketLen,\r
+  IN EFI_MTFTP4_PACKET          *Packet\r
+  )\r
+{\r
+  PXEBC_PRIVATE_DATA                  *Private;\r
+  EFI_PXE_BASE_CODE_CALLBACK_PROTOCOL *Callback;\r
+  EFI_STATUS                          Status;\r
+\r
+  Private   = (PXEBC_PRIVATE_DATA *) TokenContext;\r
+  Callback  = Private->PxeBcCallback;\r
+  Status    = EFI_SUCCESS;\r
+\r
+  if (Callback != NULL) {\r
+\r
+    Status = Callback->Callback (\r
+                        Callback,\r
+                        Private->Function,\r
+                        TRUE,\r
+                        PacketLen,\r
+                        (EFI_PXE_BASE_CODE_PACKET *) Packet\r
+                        );\r
+    if (Status != EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE) {\r
+\r
+      Status = EFI_ABORTED;\r
+    } else {\r
+\r
+      Status = EFI_SUCCESS;\r
+    }\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  This function is to get size of a file by Tftp.\r
+\r
+  @param  Private        Pointer to PxeBc private data\r
+  @param  Config         Pointer to Mtftp configuration data\r
+  @param  Filename       Pointer to file name\r
+  @param  BlockSize      Pointer to block size\r
+  @param  BufferSize     Pointer to buffer size\r
+\r
+  @return EFI_SUCCESS\r
+  @return EFI_NOT_FOUND\r
+  @return EFI_DEVICE_ERROR\r
+\r
+**/\r
+EFI_STATUS\r
+PxeBcTftpGetFileSize (\r
+  IN PXEBC_PRIVATE_DATA         *Private,\r
+  IN EFI_MTFTP4_CONFIG_DATA     *Config,\r
+  IN UINT8                      *Filename,\r
+  IN UINTN                      *BlockSize,\r
+  IN OUT UINT64                 *BufferSize\r
+  )\r
+{\r
+  EFI_MTFTP4_PROTOCOL *Mtftp4;\r
+  EFI_MTFTP4_OPTION   ReqOpt[2];\r
+  EFI_MTFTP4_PACKET   *Packet;\r
+  EFI_MTFTP4_OPTION   *Option;\r
+  UINT32              PktLen;\r
+  UINT8               OptBuf[128];\r
+  UINT32              OptCnt;\r
+  EFI_STATUS          Status;\r
+\r
+  *BufferSize               = 0;\r
+  Status                    = EFI_DEVICE_ERROR;\r
+  Mtftp4                    = Private->Mtftp4;\r
+  Packet                    = NULL;\r
+  Option                    = NULL;\r
+  PktLen                    = 0;\r
+  OptCnt                    = 1;\r
+  Config->InitialServerPort = PXEBC_BS_DOWNLOAD_PORT;\r
+\r
+  Status = Mtftp4->Configure (Mtftp4, Config);\r
+  if (EFI_ERROR (Status)) {\r
+\r
+    return Status;\r
+  }\r
+\r
+  ReqOpt[0].OptionStr = mMtftpOptions[PXE_MTFTP_OPTION_TSIZE_INDEX];\r
+  UtoA10 (0, (CHAR8 *) OptBuf);\r
+  ReqOpt[0].ValueStr = OptBuf;\r
+\r
+  if (BlockSize != NULL) {\r
+    ReqOpt[1].OptionStr = mMtftpOptions[PXE_MTFTP_OPTION_BLKSIZE_INDEX];\r
+    ReqOpt[1].ValueStr  = ReqOpt[0].ValueStr + AsciiStrLen ((CHAR8 *) ReqOpt[0].ValueStr) + 1;\r
+    UtoA10 (*BlockSize, (CHAR8 *) ReqOpt[1].ValueStr);\r
+    OptCnt++;\r
+  }\r
+\r
+  Status = Mtftp4->GetInfo (\r
+                    Mtftp4,\r
+                    FALSE,\r
+                    Filename,\r
+                    NULL,\r
+                    (UINT8) OptCnt,\r
+                    ReqOpt,\r
+                    &PktLen,\r
+                    &Packet\r
+                    );\r
+\r
+  if (EFI_ERROR (Status)) {\r
+\r
+    goto ON_ERROR;\r
+  }\r
+\r
+  OptCnt = 0;\r
+\r
+  Status = Mtftp4->ParseOptions (\r
+                    Mtftp4,\r
+                    PktLen,\r
+                    Packet,\r
+                    (UINT32 *) &OptCnt,\r
+                    &Option\r
+                    );\r
+\r
+  if (EFI_ERROR (Status)) {\r
+\r
+    goto ON_ERROR;\r
+  }\r
+\r
+  Status = EFI_NOT_FOUND;\r
+\r
+  while (OptCnt != 0) {\r
+\r
+    if (AsciiStrnCmp ((CHAR8 *) Option[OptCnt - 1].OptionStr, "tsize", 5) == 0) {\r
+\r
+      *BufferSize = AtoU64 (Option[OptCnt - 1].ValueStr);\r
+      Status      = EFI_SUCCESS;\r
+    }\r
+\r
+    OptCnt--;\r
+  }\r
+\r
+  NetFreePool (Option);\r
+\r
+ON_ERROR:\r
+\r
+  if (Packet != NULL) {\r
+    NetFreePool (Packet);\r
+  }\r
+\r
+  Mtftp4->Configure (Mtftp4, NULL);\r
+\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  This function is to get data of a file by Tftp.\r
+\r
+  @param  Private        Pointer to PxeBc private data\r
+  @param  Config         Pointer to Mtftp configuration data\r
+  @param  Filename       Pointer to file name\r
+  @param  BlockSize      Pointer to block size\r
+  @param  BufferPtr      Pointer to buffer\r
+  @param  BufferSize     Pointer to buffer size\r
+  @param  DontUseBuffer  Indicate whether with a receive buffer\r
+\r
+  @return EFI_SUCCESS\r
+  @return EFI_DEVICE_ERROR\r
+\r
+**/\r
+EFI_STATUS\r
+PxeBcTftpReadFile (\r
+  IN PXEBC_PRIVATE_DATA         *Private,\r
+  IN EFI_MTFTP4_CONFIG_DATA     *Config,\r
+  IN UINT8                      *Filename,\r
+  IN UINTN                      *BlockSize,\r
+  IN UINT8                      *BufferPtr,\r
+  IN OUT UINT64                 *BufferSize,\r
+  IN BOOLEAN                    DontUseBuffer\r
+  )\r
+{\r
+  EFI_MTFTP4_PROTOCOL *Mtftp4;\r
+  EFI_MTFTP4_TOKEN    Token;\r
+  EFI_MTFTP4_OPTION   ReqOpt[1];\r
+  UINT32              OptCnt;\r
+  UINT8               OptBuf[128];\r
+  EFI_STATUS          Status;\r
+\r
+  Status                    = EFI_DEVICE_ERROR;\r
+  Mtftp4                    = Private->Mtftp4;\r
+  OptCnt                    = 0;\r
+  Config->InitialServerPort = PXEBC_BS_DOWNLOAD_PORT;\r
+\r
+  Status = Mtftp4->Configure (Mtftp4, Config);\r
+  if (EFI_ERROR (Status)) {\r
+\r
+    return Status;\r
+  }\r
+\r
+  if (BlockSize != NULL) {\r
+\r
+    ReqOpt[0].OptionStr = mMtftpOptions[PXE_MTFTP_OPTION_BLKSIZE_INDEX];\r
+    ReqOpt[0].ValueStr  = OptBuf;\r
+    UtoA10 (*BlockSize, (CHAR8 *) ReqOpt[0].ValueStr);\r
+    OptCnt++;\r
+  }\r
+\r
+  Token.Event         = NULL;\r
+  Token.OverrideData  = NULL;\r
+  Token.Filename      = Filename;\r
+  Token.ModeStr       = NULL;\r
+  Token.OptionCount   = OptCnt;\r
+  Token.OptionList    = ReqOpt;\r
+  TokenContext        = Private;\r
+\r
+  if (DontUseBuffer) {\r
+    Token.BufferSize  = 0;\r
+    Token.Buffer      = NULL;\r
+  } else {\r
+    Token.BufferSize  = *BufferSize;\r
+    Token.Buffer      = BufferPtr;\r
+  }\r
+\r
+  Token.CheckPacket     = PxeBcCheckPacket;\r
+  Token.TimeoutCallback = NULL;\r
+  Token.PacketNeeded    = NULL;\r
+\r
+  Status = Mtftp4->ReadFile (Mtftp4, &Token);\r
+\r
+  *BufferSize = Token.BufferSize;\r
+\r
+  Mtftp4->Configure (Mtftp4, NULL);\r
+\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  This function is put data of a file by Tftp.\r
+\r
+  @param  Private        Pointer to PxeBc private data\r
+  @param  Config         Pointer to Mtftp configuration data\r
+  @param  Filename       Pointer to file name\r
+  @param  Overwrite      Indicate whether with overwrite attribute\r
+  @param  BlockSize      Pointer to block size\r
+  @param  BufferPtr      Pointer to buffer\r
+  @param  BufferSize     Pointer to buffer size\r
+\r
+  @return EFI_SUCCESS\r
+  @return EFI_DEVICE_ERROR\r
+\r
+**/\r
+EFI_STATUS\r
+PxeBcTftpWriteFile (\r
+  IN PXEBC_PRIVATE_DATA         *Private,\r
+  IN EFI_MTFTP4_CONFIG_DATA     *Config,\r
+  IN UINT8                      *Filename,\r
+  IN BOOLEAN                    Overwrite,\r
+  IN UINTN                      *BlockSize,\r
+  IN UINT8                      *BufferPtr,\r
+  IN OUT UINT64                 *BufferSize\r
+  )\r
+{\r
+  EFI_MTFTP4_PROTOCOL *Mtftp4;\r
+  EFI_MTFTP4_TOKEN    Token;\r
+  EFI_MTFTP4_OPTION   ReqOpt[1];\r
+  UINT32              OptCnt;\r
+  UINT8               OptBuf[128];\r
+  EFI_STATUS          Status;\r
+\r
+  Status                    = EFI_DEVICE_ERROR;\r
+  Mtftp4                    = Private->Mtftp4;\r
+  OptCnt                    = 0;\r
+  Config->InitialServerPort = PXEBC_BS_DOWNLOAD_PORT;\r
+\r
+  Status  = Mtftp4->Configure (Mtftp4, Config);\r
+  if (EFI_ERROR (Status)) {\r
+\r
+    return Status;\r
+  }\r
+\r
+  if (BlockSize != NULL) {\r
+\r
+    ReqOpt[0].OptionStr = mMtftpOptions[PXE_MTFTP_OPTION_BLKSIZE_INDEX];\r
+    ReqOpt[0].ValueStr  = OptBuf;\r
+    UtoA10 (*BlockSize, (CHAR8 *) ReqOpt[0].ValueStr);\r
+    OptCnt++;\r
+  }\r
+\r
+  Token.Event           = NULL;\r
+  Token.OverrideData    = NULL;\r
+  Token.Filename        = Filename;\r
+  Token.ModeStr         = NULL;\r
+  Token.OptionCount     = OptCnt;\r
+  Token.OptionList      = ReqOpt;\r
+  Token.BufferSize      = *BufferSize;\r
+  Token.Buffer          = BufferPtr;\r
+  Token.CheckPacket     = PxeBcCheckPacket;\r
+  Token.TimeoutCallback = NULL;\r
+  Token.PacketNeeded    = NULL;\r
+\r
+  Status      = Mtftp4->WriteFile (Mtftp4, &Token);\r
+  *BufferSize = Token.BufferSize;\r
+\r
+  Mtftp4->Configure (Mtftp4, NULL);\r
+\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  This function is to get data of a directory by Tftp.\r
+\r
+  @param  Private        Pointer to PxeBc private data\r
+  @param  Config         Pointer to Mtftp configuration data\r
+  @param  Filename       Pointer to file name\r
+  @param  BlockSize      Pointer to block size\r
+  @param  BufferPtr      Pointer to buffer\r
+  @param  BufferSize     Pointer to buffer size\r
+  @param  DontUseBuffer  Indicate whether with a receive buffer\r
+\r
+  @return EFI_SUCCES\r
+  @return EFI_DEVICE_ERROR\r
+\r
+**/\r
+// GC_NOTO:    EFI_SUCCESS - add return value to function comment\r
+EFI_STATUS\r
+PxeBcTftpReadDirectory (\r
+  IN PXEBC_PRIVATE_DATA            *Private,\r
+  IN EFI_MTFTP4_CONFIG_DATA        *Config,\r
+  IN UINT8                         *Filename,\r
+  IN UINTN                         *BlockSize,\r
+  IN UINT8                         *BufferPtr,\r
+  IN OUT UINT64                    *BufferSize,\r
+  IN BOOLEAN                       DontUseBuffer\r
+  )\r
+{\r
+  EFI_MTFTP4_PROTOCOL *Mtftp4;\r
+  EFI_MTFTP4_TOKEN    Token;\r
+  EFI_MTFTP4_OPTION   ReqOpt[1];\r
+  UINT32              OptCnt;\r
+  UINT8               OptBuf[128];\r
+  EFI_STATUS          Status;\r
+\r
+  Status                    = EFI_DEVICE_ERROR;\r
+  Mtftp4                    = Private->Mtftp4;\r
+  OptCnt                    = 0;\r
+  Config->InitialServerPort = PXEBC_BS_DOWNLOAD_PORT;\r
+\r
+  Status = Mtftp4->Configure (Mtftp4, Config);\r
+  if (EFI_ERROR (Status)) {\r
+\r
+    return Status;\r
+  }\r
+\r
+  if (BlockSize != NULL) {\r
+\r
+    ReqOpt[0].OptionStr = mMtftpOptions[PXE_MTFTP_OPTION_BLKSIZE_INDEX];\r
+    ReqOpt[0].ValueStr  = OptBuf;\r
+    UtoA10 (*BlockSize, (CHAR8 *) ReqOpt[0].ValueStr);\r
+    OptCnt++;\r
+  }\r
+\r
+  Token.Event         = NULL;\r
+  Token.OverrideData  = NULL;\r
+  Token.Filename      = Filename;\r
+  Token.ModeStr       = NULL;\r
+  Token.OptionCount   = OptCnt;\r
+  Token.OptionList    = ReqOpt;\r
+  TokenContext        = Private;\r
+\r
+  if (DontUseBuffer) {\r
+    Token.BufferSize  = 0;\r
+    Token.Buffer      = NULL;\r
+  } else {\r
+    Token.BufferSize  = *BufferSize;\r
+    Token.Buffer      = BufferPtr;\r
+  }\r
+\r
+  Token.CheckPacket     = PxeBcCheckPacket;\r
+  Token.TimeoutCallback = NULL;\r
+  Token.PacketNeeded    = NULL;\r
+\r
+  Status = Mtftp4->ReadDirectory (Mtftp4, &Token);\r
+\r
+  *BufferSize = Token.BufferSize;\r
+\r
+  Mtftp4->Configure (Mtftp4, NULL);\r
+\r
+  return Status;\r
+}\r
+\r
diff --git a/MdeModulePkg/Universal/Network/UefiPxeBcDxe/PxeBcMtftp.h b/MdeModulePkg/Universal/Network/UefiPxeBcDxe/PxeBcMtftp.h
new file mode 100644 (file)
index 0000000..ac8dd2f
--- /dev/null
@@ -0,0 +1,144 @@
+/** @file
+
+Copyright (c) 2007, 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.
+
+Module Name:
+
+  PxeBcMtftp.h
+
+Abstract:
+
+  Mtftp routines for PxeBc
+
+
+**/
+
+#ifndef __EFI_PXEBC_MTFTP_H__
+#define __EFI_PXEBC_MTFTP_H__
+
+enum {
+  PXE_MTFTP_OPTION_BLKSIZE_INDEX,
+  PXE_MTFTP_OPTION_TIMEOUT_INDEX,
+  PXE_MTFTP_OPTION_TSIZE_INDEX,
+  PXE_MTFTP_OPTION_MULTICAST_INDEX,
+  PXE_MTFTP_OPTION_MAXIMUM_INDEX
+};
+
+
+/**
+  This function is to get size of a file by Tftp.
+
+  @param  Private        Pointer to PxeBc private data
+  @param  Config         Pointer to Mtftp configuration data
+  @param  Filename       Pointer to file name
+  @param  BlockSize      Pointer to block size
+  @param  BufferSize     Pointer to buffer size
+
+  @return EFI_SUCCESS
+  @return EFI_NOT_FOUND
+  @return EFI_DEVICE_ERROR
+
+**/
+EFI_STATUS
+PxeBcTftpGetFileSize (
+  IN PXEBC_PRIVATE_DATA         *Private,
+  IN EFI_MTFTP4_CONFIG_DATA     *Config,
+  IN UINT8                      *Filename,
+  IN UINTN                      *BlockSize,
+  IN OUT UINT64                 *BufferSize
+  )
+;
+
+
+/**
+  This function is to get data of a file by Tftp.
+
+  @param  Private        Pointer to PxeBc private data
+  @param  Config         Pointer to Mtftp configuration data
+  @param  Filename       Pointer to file name
+  @param  BlockSize      Pointer to block size
+  @param  BufferPtr      Pointer to buffer
+  @param  BufferSize     Pointer to buffer size
+  @param  DontUseBuffer  Indicate whether with a receive buffer
+
+  @return EFI_SUCCESS
+  @return EFI_DEVICE_ERROR
+
+**/
+EFI_STATUS
+PxeBcTftpReadFile (
+  IN PXEBC_PRIVATE_DATA         *Private,
+  IN EFI_MTFTP4_CONFIG_DATA     *Config,
+  IN UINT8                      *Filename,
+  IN UINTN                      *BlockSize,
+  IN UINT8                      *BufferPtr,
+  IN OUT UINT64                 *BufferSize,
+  IN BOOLEAN                    DontUseBuffer
+  )
+;
+
+
+/**
+  This function is put data of a file by Tftp.
+
+  @param  Private        Pointer to PxeBc private data
+  @param  Config         Pointer to Mtftp configuration data
+  @param  Filename       Pointer to file name
+  @param  Overwrite      Indicate whether with overwrite attribute
+  @param  BlockSize      Pointer to block size
+  @param  BufferPtr      Pointer to buffer
+  @param  BufferSize     Pointer to buffer size
+
+  @return EFI_SUCCESS
+  @return EFI_DEVICE_ERROR
+
+**/
+EFI_STATUS
+PxeBcTftpWriteFile (
+  IN PXEBC_PRIVATE_DATA         *Private,
+  IN EFI_MTFTP4_CONFIG_DATA     *Config,
+  IN UINT8                      *Filename,
+  IN BOOLEAN                    Overwrite,
+  IN UINTN                      *BlockSize,
+  IN UINT8                      *BufferPtr,
+  IN OUT UINT64                 *BufferSize
+  )
+;
+
+
+/**
+  This function is to get data of a directory by Tftp.
+
+  @param  Private        Pointer to PxeBc private data
+  @param  Config         Pointer to Mtftp configuration data
+  @param  Filename       Pointer to file name
+  @param  BlockSize      Pointer to block size
+  @param  BufferPtr      Pointer to buffer
+  @param  BufferSize     Pointer to buffer size
+  @param  DontUseBuffer  Indicate whether with a receive buffer
+
+  @return EFI_SUCCES
+  @return EFI_DEVICE_ERROR
+
+**/
+EFI_STATUS
+PxeBcTftpReadDirectory (
+  IN PXEBC_PRIVATE_DATA            *Private,
+  IN EFI_MTFTP4_CONFIG_DATA        *Config,
+  IN UINT8                         *Filename,
+  IN UINTN                         *BlockSize,
+  IN UINT8                         *BufferPtr,
+  IN OUT UINT64                    *BufferSize,
+  IN BOOLEAN                       DontUseBuffer
+  )
+;
+
+#endif
+
diff --git a/MdeModulePkg/Universal/Network/UefiPxeBcDxe/PxeBcSupport.c b/MdeModulePkg/Universal/Network/UefiPxeBcDxe/PxeBcSupport.c
new file mode 100644 (file)
index 0000000..200d431
--- /dev/null
@@ -0,0 +1,250 @@
+/** @file\r
+\r
+Copyright (c) 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
+  PxeBcSupport.c\r
+\r
+Abstract:\r
+\r
+  Support routines for PxeBc\r
+\r
+\r
+**/\r
+\r
+\r
+#include "PxeBcImpl.h"\r
+\r
+\r
+/**\r
+\r
+  @param  Smbios              Pointer to SMBIOS structure\r
+  @param  StringNumber        String number to return. 0 is used to skip all\r
+                              strings and  point to the next SMBIOS structure.\r
+\r
+  @return Pointer to string, or pointer to next SMBIOS strcuture if StringNumber == 0\r
+\r
+**/\r
+// GC_NOTO: function comment is missing 'Routine Description:'\r
+CHAR8 *\r
+GetSmbiosString (\r
+  IN  SMBIOS_STRUCTURE_POINTER  *Smbios,\r
+  IN  UINT16                    StringNumber\r
+  )\r
+{\r
+  UINT16  Index;\r
+  CHAR8   *String;\r
+\r
+  //\r
+  // Skip over formatted section\r
+  //\r
+  String = (CHAR8 *) (Smbios->Raw + Smbios->Hdr->Length);\r
+\r
+  //\r
+  // Look through unformated section\r
+  //\r
+  for (Index = 1; Index <= StringNumber || StringNumber == 0; Index++) {\r
+    if (StringNumber == Index) {\r
+      return String;\r
+    }\r
+    //\r
+    // Skip string\r
+    //\r
+    for (; *String != 0; String++)\r
+      ;\r
+    String++;\r
+\r
+    if (*String == 0) {\r
+      //\r
+      // If double NULL then we are done.\r
+      //  Return pointer to next structure in Smbios.\r
+      //  if you pass in a 0 you will always get here\r
+      //\r
+      Smbios->Raw = (UINT8 *)++String;\r
+      return NULL;\r
+    }\r
+  }\r
+\r
+  return NULL;\r
+}\r
+\r
+\r
+/**\r
+  This function gets system guid and serial number from the smbios table\r
+\r
+  @param  SystemGuid          The pointer of returned system guid\r
+  @param  SystemSerialNumber  The pointer of returned system serial number\r
+\r
+  @retval EFI_SUCCESS         Successfully get the system guid and system serial\r
+                              number\r
+  @retval EFI_NOT_FOUND       Not find the SMBIOS table\r
+\r
+**/\r
+EFI_STATUS\r
+GetSmbiosSystemGuidAndSerialNumber (\r
+  IN  EFI_GUID  *SystemGuid,\r
+  OUT CHAR8     **SystemSerialNumber\r
+  )\r
+{\r
+  EFI_STATUS                Status;\r
+  SMBIOS_TABLE_ENTRY_POINT  *SmbiosTable;\r
+  SMBIOS_STRUCTURE_POINTER  Smbios;\r
+  SMBIOS_STRUCTURE_POINTER  SmbiosEnd;\r
+  UINT16                    Index;\r
+\r
+  Status = EfiGetSystemConfigurationTable (&gEfiSmbiosTableGuid, (VOID **) &SmbiosTable);\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  Smbios.Hdr    = (SMBIOS_STRUCTURE *) (UINTN) SmbiosTable->TableAddress;\r
+  SmbiosEnd.Raw = (UINT8 *) (UINTN) (SmbiosTable->TableAddress + SmbiosTable->TableLength);\r
+\r
+  for (Index = 0; Index < SmbiosTable->TableLength; Index++) {\r
+    if (Smbios.Hdr->Type == 1) {\r
+      if (Smbios.Hdr->Length < 0x19) {\r
+        //\r
+        // Older version did not support Guid and Serial number\r
+        //\r
+        continue;\r
+      }\r
+      //\r
+      // SMBIOS tables are byte packed so we need to do a byte copy to\r
+      // prevend alignment faults on Itanium-based platform.\r
+      //\r
+      CopyMem (SystemGuid, &Smbios.Type1->Uuid, sizeof (EFI_GUID));\r
+      *SystemSerialNumber = GetSmbiosString (&Smbios, Smbios.Type1->SerialNumber);\r
+\r
+      return EFI_SUCCESS;\r
+    }\r
+    //\r
+    // Make Smbios point to the next record\r
+    //\r
+    GetSmbiosString (&Smbios, 0);\r
+\r
+    if (Smbios.Raw >= SmbiosEnd.Raw) {\r
+      //\r
+      // SMBIOS 2.1 incorrectly stated the length of SmbiosTable as 0x1e.\r
+      // given this we must double check against the length of the structure.\r
+      //\r
+      return EFI_SUCCESS;\r
+    }\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+  GC_NOTO: Add function description\r
+\r
+  @param  Event               GC_NOTO: add argument description\r
+  @param  Context             GC_NOTO: add argument description\r
+\r
+  @return GC_NOTO: add return values\r
+\r
+**/\r
+VOID\r
+PxeBcCommonNotify (\r
+  IN EFI_EVENT           Event,\r
+  IN VOID                *Context\r
+  )\r
+{\r
+  *((BOOLEAN *) Context) = TRUE;\r
+}\r
+\r
+\r
+/**\r
+  Convert number to ASCII value\r
+\r
+  @param  Number              Numeric value to convert to decimal ASCII value.\r
+  @param  Buffer              Buffer to place ASCII version of the Number\r
+  @param  Length              Length of Buffer.\r
+\r
+  @retval none                none\r
+\r
+**/\r
+VOID\r
+CvtNum (\r
+  IN UINTN  Number,\r
+  IN UINT8  *Buffer,\r
+  IN INTN   Length\r
+  )\r
+{\r
+  UINTN Remainder;\r
+\r
+  while (Length--) {\r
+    Remainder = Number % 10;\r
+    Number /= 10;\r
+    Buffer[Length] = (UINT8) ('0' + Remainder);\r
+  }\r
+}\r
+\r
+\r
+/**\r
+  GC_NOTO: Add function description\r
+\r
+  @param  Number              GC_NOTO: add argument description\r
+  @param  Buffer              GC_NOTO: add argument description\r
+\r
+  @return GC_NOTO: add return values\r
+\r
+**/\r
+UINTN\r
+UtoA10 (\r
+  IN UINTN Number,\r
+  IN CHAR8 *Buffer\r
+  )\r
+{\r
+  UINTN Index;\r
+  CHAR8 TempStr[64];\r
+\r
+  Index           = 63;\r
+  TempStr[Index]  = 0;\r
+\r
+  do {\r
+    Index--;\r
+    TempStr[Index]  = (CHAR8) ('0' + (Number % 10));\r
+    Number          = Number / 10;\r
+  } while (Number != 0);\r
+\r
+  AsciiStrCpy (Buffer, &TempStr[Index]);\r
+\r
+  return AsciiStrLen (Buffer);\r
+}\r
+\r
+\r
+/**\r
+  Convert ASCII numeric string to a UINTN value\r
+\r
+  @param  Number              Numeric value to convert to decimal ASCII value.\r
+  @param  Buffer              Buffer to place ASCII version of the Number\r
+\r
+  @retval Value               UINTN value of the ASCII string.\r
+\r
+**/\r
+UINT64\r
+AtoU64 (\r
+  IN UINT8 *Buffer\r
+  )\r
+{\r
+  UINT64  Value;\r
+  UINT8   Character;\r
+\r
+  Value = 0;\r
+  while ((Character = *Buffer++) != '\0') {\r
+    Value = MultU64x32 (Value, 10) + (Character - '0');\r
+  }\r
+\r
+  return Value;\r
+}\r
+\r
diff --git a/MdeModulePkg/Universal/Network/UefiPxeBcDxe/PxeBcSupport.h b/MdeModulePkg/Universal/Network/UefiPxeBcDxe/PxeBcSupport.h
new file mode 100644 (file)
index 0000000..79210c1
--- /dev/null
@@ -0,0 +1,89 @@
+/** @file
+
+Copyright (c) 2007, 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.
+
+Module Name:
+
+  PxeBcSupport.h
+
+Abstract:
+
+  Support routines for PxeBc
+
+
+**/
+
+#ifndef __EFI_PXEBC_SUPPORT_H__
+#define __EFI_PXEBC_SUPPORT_H__
+
+EFI_STATUS
+GetSmbiosSystemGuidAndSerialNumber (
+  IN  EFI_GUID  *SystemGuid,
+  OUT CHAR8     **SystemSerialNumber
+  );
+
+
+/**
+  GC_NOTO: Add function description
+
+  @param  Event      GC_NOTO: add argument description
+  @param  Context    GC_NOTO: add argument description
+
+  @return GC_NOTO: add return values
+
+**/
+VOID
+PxeBcCommonNotify (
+  IN EFI_EVENT           Event,
+  IN VOID                *Context
+  )
+;
+
+VOID
+CvtNum (
+  IN UINTN  Number,
+  IN UINT8  *Buffer,
+  IN INTN   Length
+  );
+
+
+/**
+  GC_NOTO: Add function description
+
+  @param  Number     GC_NOTO: add argument description
+  @param  BufferPtr  GC_NOTO: add argument description
+
+  @return GC_NOTO: add return values
+
+**/
+UINTN
+UtoA10 (
+  UINTN Number,
+  CHAR8 *BufferPtr
+  )
+;
+
+
+/**
+  GC_NOTO: Add function description
+
+  @param  BufferPtr  GC_NOTO: add argument description
+
+  @return GC_NOTO: add return values
+
+**/
+UINT64
+AtoU64 (
+  UINT8 *BufferPtr
+  )
+;
+
+#endif
+
diff --git a/MdeModulePkg/Universal/Network/UefiPxeBcDxe/UefiPxeBcDxe.inf b/MdeModulePkg/Universal/Network/UefiPxeBcDxe/UefiPxeBcDxe.inf
new file mode 100644 (file)
index 0000000..4412d37
--- /dev/null
@@ -0,0 +1,93 @@
+#/** @file\r
+# Component name for module UefiPxeBc\r
+#\r
+# FIX ME!\r
+# Copyright (c) 2007, Intel Corporation. All rights reserved.\r
+#\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
+#\r
+#**/\r
+\r
+\r
+[Defines]\r
+  INF_VERSION                    = 0x00010005\r
+  BASE_NAME                      = UefiPxeBcDxe\r
+  FILE_GUID                      = 3B1DEAB5-C75D-442e-9238-8E2FFB62B0BB\r
+  MODULE_TYPE                    = DXE_DRIVER\r
+  VERSION_STRING                 = 1.0\r
+  EDK_RELEASE_VERSION            = 0x00020000\r
+  EFI_SPECIFICATION_VERSION      = 0x00020000\r
+\r
+  ENTRY_POINT                    = PxeBcDriverEntryPoint\r
+\r
+#\r
+# The following information is for reference only and not required by the build tools.\r
+#\r
+#  VALID_ARCHITECTURES           = IA32 X64 IPF\r
+#\r
+\r
+\r
+[Sources.common]\r
+  PxeBcMtftp.c\r
+  PxeBcSupport.h\r
+  PxeBcSupport.c\r
+  PxeBcDriver.c\r
+  PxeBcDhcp.h\r
+  ComponentName.c\r
+  PxeBcImpl.c\r
+  PxeBcImpl.h\r
+  PxeBcDhcp.c\r
+  PxeBcMtftp.h\r
+  PxeBcDriver.h\r
+\r
+[Sources.IA32]\r
+  Ia32\PxeArch.h\r
+\r
+[Sources.X64]\r
+  X64\PxeArch.h\r
+\r
+[Sources.IPF]\r
+  Ipf\PxeArch.h\r
+\r
+\r
+[Packages]\r
+  MdePkg/MdePkg.dec\r
+  MdeModulePkg/MdeModulePkg.dec\r
+\r
+\r
+\r
+[LibraryClasses]\r
+  BaseLib\r
+  UefiLib\r
+  UefiBootServicesTableLib\r
+  UefiDriverEntryPoint\r
+  BaseMemoryLib\r
+  DebugLib\r
+  NetLib\r
+\r
+\r
+[Guids]\r
+  gEfiSmbiosTableGuid                              # ALWAYS_CONSUMED\r
+\r
+\r
+\r
+[Protocols]\r
+  gEfiMtftp4ServiceBindingProtocolGuid             # PROTOCOL ALWAYS_CONSUMED\r
+  gEfiMtftp4ProtocolGuid                           # PROTOCOL ALWAYS_CONSUMED\r
+  gEfiUdp4ServiceBindingProtocolGuid               # PROTOCOL ALWAYS_CONSUMED\r
+  gEfiDhcp4ServiceBindingProtocolGuid              # PROTOCOL ALWAYS_CONSUMED\r
+  gEfiPxeBaseCodeCallbackProtocolGuid              # PROTOCOL ALWAYS_CONSUMED\r
+  gEfiPxeBaseCodeProtocolGuid                      # PROTOCOL ALWAYS_CONSUMED\r
+  gEfiLoadFileProtocolGuid                         # PROTOCOL ALWAYS_CONSUMED\r
+  gEfiDhcp4ProtocolGuid                            # PROTOCOL ALWAYS_CONSUMED\r
+  gEfiUdp4ProtocolGuid                             # PROTOCOL ALWAYS_CONSUMED\r
+  gEfiNetworkInterfaceIdentifierProtocolGuid_31    # PROTOCOL ALWAYS_CONSUMED\r
+\r
+\r
diff --git a/MdeModulePkg/Universal/Network/UefiPxeBcDxe/UefiPxeBcDxe.msa b/MdeModulePkg/Universal/Network/UefiPxeBcDxe/UefiPxeBcDxe.msa
new file mode 100644 (file)
index 0000000..cbf131a
--- /dev/null
@@ -0,0 +1,108 @@
+<ModuleSurfaceArea xmlns="http://www.TianoCore.org/2006/Edk2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">\r
+  <MsaHeader>\r
+    <ModuleName>UefiPxeBcDxe</ModuleName>\r
+    <ModuleType>DXE_DRIVER</ModuleType>\r
+    <GuidValue>3B1DEAB5-C75D-442e-9238-8E2FFB62B0BB</GuidValue>\r
+    <Version>1.0</Version>\r
+    <Abstract>Component name for module UefiPxeBc</Abstract>\r
+    <Description>FIX ME!</Description>\r
+    <Copyright>Copyright (c) 2007, Intel Corporation. All rights reserved.</Copyright>\r
+    <License>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.</License>\r
+    <Specification>FRAMEWORK_BUILD_PACKAGING_SPECIFICATION   0x00000052</Specification>\r
+  </MsaHeader>\r
+  <ModuleDefinitions>\r
+    <SupportedArchitectures>IA32 X64 IPF EBC</SupportedArchitectures>\r
+    <BinaryModule>false</BinaryModule>\r
+    <OutputFileBasename>UefiPxeBcDxe</OutputFileBasename>\r
+  </ModuleDefinitions>\r
+  <LibraryClassDefinitions>\r
+    <LibraryClass Usage="ALWAYS_CONSUMED">\r
+      <Keyword>DebugLib</Keyword>\r
+    </LibraryClass>\r
+    <LibraryClass Usage="ALWAYS_CONSUMED">\r
+      <Keyword>BaseMemoryLib</Keyword>\r
+    </LibraryClass>\r
+    <LibraryClass Usage="ALWAYS_CONSUMED">\r
+      <Keyword>UefiDriverEntryPoint</Keyword>\r
+    </LibraryClass>\r
+    <LibraryClass Usage="ALWAYS_CONSUMED">\r
+      <Keyword>UefiBootServicesTableLib</Keyword>\r
+    </LibraryClass>\r
+    <LibraryClass Usage="ALWAYS_CONSUMED">\r
+      <Keyword>UefiLib</Keyword>\r
+    </LibraryClass>\r
+    <LibraryClass Usage="ALWAYS_CONSUMED">\r
+      <Keyword>BaseLib</Keyword>\r
+    </LibraryClass>\r
+  </LibraryClassDefinitions>\r
+  <SourceFiles>\r
+    <Filename>PxeBcDriver.h</Filename>\r
+    <Filename>PxeBcMtftp.h</Filename>\r
+    <Filename>PxeBcDhcp.c</Filename>\r
+    <Filename>PxeBcImpl.h</Filename>\r
+    <Filename>PxeBcImpl.c</Filename>\r
+    <Filename>ComponentName.c</Filename>\r
+    <Filename>PxeBcDhcp.h</Filename>\r
+    <Filename>ipf\PxeArch.h</Filename>\r
+    <Filename>PxeBcDriver.c</Filename>\r
+    <Filename SupArchList="X64">x64\PxeArch.h</Filename>\r
+    <Filename>PxeBcSupport.c</Filename>\r
+    <Filename>PxeBcSupport.h</Filename>\r
+    <Filename>ia32\PxeArch.h</Filename>\r
+    <Filename>PxeBcMtftp.c</Filename>\r
+  </SourceFiles>\r
+  <PackageDependencies>\r
+    <Package PackageGuid="5e0e9358-46b6-4ae2-8218-4ab8b9bbdcec"/>\r
+    <Package PackageGuid="68169ab0-d41b-4009-9060-292c253ac43d"/>\r
+  </PackageDependencies>\r
+  <Protocols>\r
+    <Protocol Usage="ALWAYS_CONSUMED">\r
+      <ProtocolCName>gEfiNetworkInterfaceIdentifierProtocolGuid_31</ProtocolCName>\r
+    </Protocol>\r
+    <Protocol Usage="ALWAYS_CONSUMED">\r
+      <ProtocolCName>gEfiUdp4ProtocolGuid</ProtocolCName>\r
+    </Protocol>\r
+    <Protocol Usage="ALWAYS_CONSUMED">\r
+      <ProtocolCName>gEfiDhcp4ProtocolGuid</ProtocolCName>\r
+    </Protocol>\r
+    <Protocol Usage="ALWAYS_CONSUMED">\r
+      <ProtocolCName>gEfiLoadFileProtocolGuid</ProtocolCName>\r
+    </Protocol>\r
+    <Protocol Usage="ALWAYS_CONSUMED">\r
+      <ProtocolCName>gEfiPxeBaseCodeProtocolGuid</ProtocolCName>\r
+    </Protocol>\r
+    <Protocol Usage="ALWAYS_CONSUMED">\r
+      <ProtocolCName>gEfiPxeBaseCodeCallbackProtocolGuid</ProtocolCName>\r
+    </Protocol>\r
+    <Protocol Usage="ALWAYS_CONSUMED">\r
+      <ProtocolCName>gEfiDhcp4ServiceBindingProtocolGuid</ProtocolCName>\r
+    </Protocol>\r
+    <Protocol Usage="ALWAYS_CONSUMED">\r
+      <ProtocolCName>gEfiUdp4ServiceBindingProtocolGuid</ProtocolCName>\r
+    </Protocol>\r
+    <Protocol Usage="ALWAYS_CONSUMED">\r
+      <ProtocolCName>gEfiMtftp4ProtocolGuid</ProtocolCName>\r
+    </Protocol>\r
+    <Protocol Usage="ALWAYS_CONSUMED">\r
+      <ProtocolCName>gEfiMtftp4ServiceBindingProtocolGuid</ProtocolCName>\r
+    </Protocol>\r
+  </Protocols>\r
+  <Guids>\r
+    <GuidCNames Usage="ALWAYS_CONSUMED">\r
+      <GuidCName>gEfiSmbiosTableGuid</GuidCName>\r
+    </GuidCNames>\r
+  </Guids>\r
+  <Externs>\r
+    <Specification>EFI_SPECIFICATION_VERSION 0x00020000</Specification>\r
+    <Specification>EDK_RELEASE_VERSION 0x00020000</Specification>\r
+    <Extern>\r
+      <ModuleEntryPoint>PxeBcDriverEntryPoint</ModuleEntryPoint>\r
+    </Extern>\r
+  </Externs>\r
+</ModuleSurfaceArea>
\ No newline at end of file
diff --git a/MdeModulePkg/Universal/Network/UefiPxeBcDxe/X64/PxeArch.h b/MdeModulePkg/Universal/Network/UefiPxeBcDxe/X64/PxeArch.h
new file mode 100644 (file)
index 0000000..a8fa293
--- /dev/null
@@ -0,0 +1,26 @@
+/** @file
+
+Copyright (c) 2006, 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.
+
+Module Name:
+  PxeArch.h
+
+Abstract:
+  Defines PXE Arch type
+
+
+**/
+
+#ifndef _EFI_PXE_ARCH_H_
+#define _EFI_PXE_ARCH_H_
+
+#define SYS_ARCH  0x7
+
+#endif