1dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff/** @file
2f737cfb953905f42f3324e8e53ec324a15314210jgong  Interface routines for PxeBc.
3e285199897e538523f762cb5b3900e81f872035avanjeff
414e84fd8888bfcc0f0d8fae8b69c6428b4226d1dZhang LuboCopyright (c) 2007 - 2015, Intel Corporation. All rights reserved.<BR>
5e5eed7d3641d71d7ea539e5379ea9c6a5cd97004hhtianThis program and the accompanying materials
6dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeffare licensed and made available under the terms and conditions of the BSD License
7dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeffwhich accompanies this distribution.  The full text of the license may be found at
8dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeffhttp://opensource.org/licenses/bsd-license.php
9dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
10dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeffTHE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeffWITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
13dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff**/
14dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
15dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
16dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff#include "PxeBcImpl.h"
17dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
18434ce3feca7f5a430db3d5853c54a06343d02ed2vanjeffUINT32  mPxeDhcpTimeout[4] = { 4, 8, 16, 32 };
19f737cfb953905f42f3324e8e53ec324a15314210jgong
20982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff/**
21f737cfb953905f42f3324e8e53ec324a15314210jgong  Get and record the arp cache.
22982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff
23982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  @param  This                    Pointer to EFI_PXE_BC_PROTOCOL
24982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff
25982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  @retval EFI_SUCCESS             Arp cache updated successfully
26f737cfb953905f42f3324e8e53ec324a15314210jgong  @retval others                  If error occurs when getting arp cache
27982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff
28982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff**/
29982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeffEFI_STATUS
30982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeffUpdateArpCache (
31982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  IN EFI_PXE_BASE_CODE_PROTOCOL     * This
32982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  )
33982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff{
34982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  PXEBC_PRIVATE_DATA      *Private;
35982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  EFI_PXE_BASE_CODE_MODE  *Mode;
36982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  EFI_STATUS              Status;
37982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  UINT32                  EntryLength;
38982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  UINT32                  EntryCount;
39982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  EFI_ARP_FIND_DATA       *Entries;
40982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  UINT32                  Index;
41982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff
42982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  Private = PXEBC_PRIVATE_DATA_FROM_PXEBC (This);
43982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  Mode    = Private->PxeBc.Mode;
44982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff
45f737cfb953905f42f3324e8e53ec324a15314210jgong  Status = Private->Arp->Find (
46f737cfb953905f42f3324e8e53ec324a15314210jgong                     Private->Arp,
47f737cfb953905f42f3324e8e53ec324a15314210jgong                     TRUE,
48f737cfb953905f42f3324e8e53ec324a15314210jgong                     NULL,
49f737cfb953905f42f3324e8e53ec324a15314210jgong                     &EntryLength,
50f737cfb953905f42f3324e8e53ec324a15314210jgong                     &EntryCount,
51f737cfb953905f42f3324e8e53ec324a15314210jgong                     &Entries,
52f737cfb953905f42f3324e8e53ec324a15314210jgong                     TRUE
53f737cfb953905f42f3324e8e53ec324a15314210jgong                     );
54982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  if (EFI_ERROR (Status)) {
55982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff    return Status;
56982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  }
57982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff
58f737cfb953905f42f3324e8e53ec324a15314210jgong  Mode->ArpCacheEntries = MIN (
59f737cfb953905f42f3324e8e53ec324a15314210jgong                           EntryCount,
60f737cfb953905f42f3324e8e53ec324a15314210jgong                           EFI_PXE_BASE_CODE_MAX_ARP_ENTRIES
61f737cfb953905f42f3324e8e53ec324a15314210jgong                           );
62982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  for (Index = 0; Index < Mode->ArpCacheEntries; Index ++) {
63f737cfb953905f42f3324e8e53ec324a15314210jgong    CopyMem (
64e285199897e538523f762cb5b3900e81f872035avanjeff      &Mode->ArpCache[Index].IpAddr,
65e285199897e538523f762cb5b3900e81f872035avanjeff      Entries + 1,
66f737cfb953905f42f3324e8e53ec324a15314210jgong      Entries->SwAddressLength
67f737cfb953905f42f3324e8e53ec324a15314210jgong      );
68f737cfb953905f42f3324e8e53ec324a15314210jgong    CopyMem (
69f737cfb953905f42f3324e8e53ec324a15314210jgong      &Mode->ArpCache[Index].MacAddr,
70f737cfb953905f42f3324e8e53ec324a15314210jgong      (UINT8 *) (Entries + 1) + Entries->SwAddressLength,
71f737cfb953905f42f3324e8e53ec324a15314210jgong      Entries->HwAddressLength
72f737cfb953905f42f3324e8e53ec324a15314210jgong      );
73982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff    //
74982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff    // Slip to the next FindData.
75982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff    //
76f737cfb953905f42f3324e8e53ec324a15314210jgong    Entries = (EFI_ARP_FIND_DATA *) ((UINT8 *) Entries + EntryLength);
77982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  }
78982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff
79982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  return EFI_SUCCESS;
80982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff}
81982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff
82982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff/**
83f737cfb953905f42f3324e8e53ec324a15314210jgong  Timeout routine to update arp cache.
84982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff
85982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  @param  Event              Pointer to EFI_PXE_BC_PROTOCOL
86982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  @param  Context            Context of the timer event
87982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff
88982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff**/
89982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeffVOID
90982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeffEFIAPI
91982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeffArpCacheUpdateTimeout (
92982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  IN EFI_EVENT    Event,
93982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  IN VOID         *Context
94982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  )
95982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff{
96982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  UpdateArpCache ((EFI_PXE_BASE_CODE_PROTOCOL *) Context);
97982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff}
98982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff
99982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff/**
100f737cfb953905f42f3324e8e53ec324a15314210jgong  Do arp resolution from arp cache in PxeBcMode.
101e285199897e538523f762cb5b3900e81f872035avanjeff
102f737cfb953905f42f3324e8e53ec324a15314210jgong  @param  PxeBcMode      The PXE BC mode to look into.
103f737cfb953905f42f3324e8e53ec324a15314210jgong  @param  Ip4Addr        The Ip4 address for resolution.
104f737cfb953905f42f3324e8e53ec324a15314210jgong  @param  MacAddress     The resoluted MAC address if the resolution is successful.
105f737cfb953905f42f3324e8e53ec324a15314210jgong                         The value is undefined if resolution fails.
106e285199897e538523f762cb5b3900e81f872035avanjeff
107f737cfb953905f42f3324e8e53ec324a15314210jgong  @retval TRUE           The resolution is successful.
108f737cfb953905f42f3324e8e53ec324a15314210jgong  @retval FALSE          Otherwise.
109982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff
110982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff**/
111982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeffBOOLEAN
112982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeffFindInArpCache (
113f737cfb953905f42f3324e8e53ec324a15314210jgong  IN  EFI_PXE_BASE_CODE_MODE    *PxeBcMode,
114f737cfb953905f42f3324e8e53ec324a15314210jgong  IN  EFI_IPv4_ADDRESS          *Ip4Addr,
115f737cfb953905f42f3324e8e53ec324a15314210jgong  OUT EFI_MAC_ADDRESS           *MacAddress
116982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  )
117982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff{
118982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  UINT32                  Index;
119982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff
120982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  for (Index = 0; Index < PxeBcMode->ArpCacheEntries; Index ++) {
121982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff    if (EFI_IP4_EQUAL (&PxeBcMode->ArpCache[Index].IpAddr.v4, Ip4Addr)) {
122f737cfb953905f42f3324e8e53ec324a15314210jgong      CopyMem (
123f737cfb953905f42f3324e8e53ec324a15314210jgong        MacAddress,
124f737cfb953905f42f3324e8e53ec324a15314210jgong        &PxeBcMode->ArpCache[Index].MacAddr,
125f737cfb953905f42f3324e8e53ec324a15314210jgong        sizeof (EFI_MAC_ADDRESS)
126f737cfb953905f42f3324e8e53ec324a15314210jgong        );
127982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff      return TRUE;
128982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff    }
129982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  }
130982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff
131982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  return FALSE;
132982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff}
133982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff
134982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff/**
135982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  Notify function for the ICMP receive token, used to process
136982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  the received ICMP packets.
137982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff
138f737cfb953905f42f3324e8e53ec324a15314210jgong  @param  Context               The PXEBC private data.
139982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff
140982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff**/
141982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeffVOID
142982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeffEFIAPI
143982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeffIcmpErrorListenHandlerDpc (
144982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  IN VOID      *Context
145982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  )
146982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff{
147982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  EFI_STATUS              Status;
148982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  EFI_IP4_RECEIVE_DATA    *RxData;
149982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  EFI_IP4_PROTOCOL        *Ip4;
150982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  PXEBC_PRIVATE_DATA      *Private;
151982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  EFI_PXE_BASE_CODE_MODE  *Mode;
152982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  UINTN                   Index;
153982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  UINT32                  CopiedLen;
154982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  UINT8                   *CopiedPointer;
155982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff
156982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  Private = (PXEBC_PRIVATE_DATA *) Context;
157982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  Mode    = &Private->Mode;
158982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  Status  = Private->IcmpErrorRcvToken.Status;
159982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  RxData  = Private->IcmpErrorRcvToken.Packet.RxData;
160982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  Ip4     = Private->Ip4;
161982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff
162f737cfb953905f42f3324e8e53ec324a15314210jgong  if (Status == EFI_ABORTED) {
163982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff    //
164982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff    // The reception is actively aborted by the consumer, directly return.
165982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff    //
166982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff    return;
167982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  }
168982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff
169f737cfb953905f42f3324e8e53ec324a15314210jgong  if (EFI_ERROR (Status) || (RxData == NULL)) {
170982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff    //
171982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff    // Only process the normal packets and the icmp error packets, if RxData is NULL
172982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff    // with Status == EFI_SUCCESS or EFI_ICMP_ERROR, just resume the receive although
173982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff    // this should be a bug of the low layer (IP).
174982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff    //
175982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff    goto Resume;
176982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  }
177982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff
178f737cfb953905f42f3324e8e53ec324a15314210jgong  if (EFI_IP4 (RxData->Header->SourceAddress) != 0 &&
179f6b7393ceb34c9b3a27434268bf2ce517047641ftye      !NetIp4IsUnicast (EFI_NTOHL (RxData->Header->SourceAddress), 0)) {
180982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff    //
181982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff    // The source address is not zero and it's not a unicast IP address, discard it.
182982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff    //
183982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff    goto CleanUp;
184982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  }
185982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff
186982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  if (!EFI_IP4_EQUAL (&RxData->Header->DestinationAddress, &Mode->StationIp.v4)) {
187982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff    //
188982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff    // The dest address is not equal to Station Ip address, discard it.
189982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff    //
190982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff    goto CleanUp;
191982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  }
192982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff
193982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  //
194982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  // Constructor ICMP error packet
195982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  //
196982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  CopiedLen = 0;
197982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  CopiedPointer = (UINT8 *) &Mode->IcmpError;
198982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff
199982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  for (Index = 0; Index < RxData->FragmentCount; Index ++) {
200982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff    CopiedLen += RxData->FragmentTable[Index].FragmentLength;
201982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff    if (CopiedLen <= sizeof (EFI_PXE_BASE_CODE_ICMP_ERROR)) {
202f737cfb953905f42f3324e8e53ec324a15314210jgong      CopyMem (
203f737cfb953905f42f3324e8e53ec324a15314210jgong        CopiedPointer,
204f737cfb953905f42f3324e8e53ec324a15314210jgong        RxData->FragmentTable[Index].FragmentBuffer,
205f737cfb953905f42f3324e8e53ec324a15314210jgong        RxData->FragmentTable[Index].FragmentLength
206f737cfb953905f42f3324e8e53ec324a15314210jgong        );
207982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff    } else {
208f737cfb953905f42f3324e8e53ec324a15314210jgong      CopyMem (
209f737cfb953905f42f3324e8e53ec324a15314210jgong        CopiedPointer,
210f737cfb953905f42f3324e8e53ec324a15314210jgong        RxData->FragmentTable[Index].FragmentBuffer,
211f737cfb953905f42f3324e8e53ec324a15314210jgong        CopiedLen - sizeof (EFI_PXE_BASE_CODE_ICMP_ERROR)
212f737cfb953905f42f3324e8e53ec324a15314210jgong        );
213982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff    }
214982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff    CopiedPointer += CopiedLen;
215982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  }
216982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff
217982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  goto Resume;
218982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff
219982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeffCleanUp:
220982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  gBS->SignalEvent (RxData->RecycleSignal);
221982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff
222982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeffResume:
223982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  Ip4->Receive (Ip4, &(Private->IcmpErrorRcvToken));
224982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff}
225982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff
226982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff/**
227982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  Request IcmpErrorListenHandlerDpc as a DPC at TPL_CALLBACK
228982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff
229982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  @param  Event                 The event signaled.
230982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  @param  Context               The context passed in by the event notifier.
231982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff
232982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff**/
233982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeffVOID
234982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeffEFIAPI
235982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeffIcmpErrorListenHandler (
236982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  IN EFI_EVENT Event,
237982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  IN VOID      *Context
238982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  )
239982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff{
240982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  //
241982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  // Request IpIoListenHandlerDpc as a DPC at TPL_CALLBACK
242982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  //
243d8d26fb207e02aa5ef57e2bcb213f9dda16166ccmdkinney  QueueDpc (TPL_CALLBACK, IcmpErrorListenHandlerDpc, Context);
244982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff}
245dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
246e285199897e538523f762cb5b3900e81f872035avanjeff/**
247f737cfb953905f42f3324e8e53ec324a15314210jgong  Enables the use of the PXE Base Code Protocol functions.
248f737cfb953905f42f3324e8e53ec324a15314210jgong
249f737cfb953905f42f3324e8e53ec324a15314210jgong  This function enables the use of the PXE Base Code Protocol functions. If the
250f737cfb953905f42f3324e8e53ec324a15314210jgong  Started field of the EFI_PXE_BASE_CODE_MODE structure is already TRUE, then
251f737cfb953905f42f3324e8e53ec324a15314210jgong  EFI_ALREADY_STARTED will be returned. If UseIpv6 is TRUE, then IPv6 formatted
252f737cfb953905f42f3324e8e53ec324a15314210jgong  addresses will be used in this session. If UseIpv6 is FALSE, then IPv4 formatted
253f737cfb953905f42f3324e8e53ec324a15314210jgong  addresses will be used in this session. If UseIpv6 is TRUE, and the Ipv6Supported
254f737cfb953905f42f3324e8e53ec324a15314210jgong  field of the EFI_PXE_BASE_CODE_MODE structure is FALSE, then EFI_UNSUPPORTED will
255f737cfb953905f42f3324e8e53ec324a15314210jgong  be returned. If there is not enough memory or other resources to start the PXE
256f737cfb953905f42f3324e8e53ec324a15314210jgong  Base Code Protocol, then EFI_OUT_OF_RESOURCES will be returned. Otherwise, the
257f737cfb953905f42f3324e8e53ec324a15314210jgong  PXE Base Code Protocol will be started, and all of the fields of the EFI_PXE_BASE_CODE_MODE
258f737cfb953905f42f3324e8e53ec324a15314210jgong  structure will be initialized as follows:
259f737cfb953905f42f3324e8e53ec324a15314210jgong    StartedSet to TRUE.
260f737cfb953905f42f3324e8e53ec324a15314210jgong    Ipv6SupportedUnchanged.
261f737cfb953905f42f3324e8e53ec324a15314210jgong    Ipv6AvailableUnchanged.
262f737cfb953905f42f3324e8e53ec324a15314210jgong    UsingIpv6Set to UseIpv6.
263f737cfb953905f42f3324e8e53ec324a15314210jgong    BisSupportedUnchanged.
264f737cfb953905f42f3324e8e53ec324a15314210jgong    BisDetectedUnchanged.
265f737cfb953905f42f3324e8e53ec324a15314210jgong    AutoArpSet to TRUE.
266f737cfb953905f42f3324e8e53ec324a15314210jgong    SendGUIDSet to FALSE.
267f737cfb953905f42f3324e8e53ec324a15314210jgong    TTLSet to DEFAULT_TTL.
268f737cfb953905f42f3324e8e53ec324a15314210jgong    ToSSet to DEFAULT_ToS.
269f737cfb953905f42f3324e8e53ec324a15314210jgong    DhcpCompletedSet to FALSE.
270f737cfb953905f42f3324e8e53ec324a15314210jgong    ProxyOfferReceivedSet to FALSE.
271f737cfb953905f42f3324e8e53ec324a15314210jgong    StationIpSet to an address of all zeros.
272f737cfb953905f42f3324e8e53ec324a15314210jgong    SubnetMaskSet to a subnet mask of all zeros.
273f737cfb953905f42f3324e8e53ec324a15314210jgong    DhcpDiscoverZero-filled.
274f737cfb953905f42f3324e8e53ec324a15314210jgong    DhcpAckZero-filled.
275f737cfb953905f42f3324e8e53ec324a15314210jgong    ProxyOfferZero-filled.
276f737cfb953905f42f3324e8e53ec324a15314210jgong    PxeDiscoverValidSet to FALSE.
277f737cfb953905f42f3324e8e53ec324a15314210jgong    PxeDiscoverZero-filled.
278f737cfb953905f42f3324e8e53ec324a15314210jgong    PxeReplyValidSet to FALSE.
279f737cfb953905f42f3324e8e53ec324a15314210jgong    PxeReplyZero-filled.
280f737cfb953905f42f3324e8e53ec324a15314210jgong    PxeBisReplyValidSet to FALSE.
281f737cfb953905f42f3324e8e53ec324a15314210jgong    PxeBisReplyZero-filled.
282f737cfb953905f42f3324e8e53ec324a15314210jgong    IpFilterSet the Filters field to 0 and the IpCnt field to 0.
283f737cfb953905f42f3324e8e53ec324a15314210jgong    ArpCacheEntriesSet to 0.
284f737cfb953905f42f3324e8e53ec324a15314210jgong    ArpCacheZero-filled.
285f737cfb953905f42f3324e8e53ec324a15314210jgong    RouteTableEntriesSet to 0.
286f737cfb953905f42f3324e8e53ec324a15314210jgong    RouteTableZero-filled.
287f737cfb953905f42f3324e8e53ec324a15314210jgong    IcmpErrorReceivedSet to FALSE.
288f737cfb953905f42f3324e8e53ec324a15314210jgong    IcmpErrorZero-filled.
289f737cfb953905f42f3324e8e53ec324a15314210jgong    TftpErroReceivedSet to FALSE.
290f737cfb953905f42f3324e8e53ec324a15314210jgong    TftpErrorZero-filled.
291f737cfb953905f42f3324e8e53ec324a15314210jgong    MakeCallbacksSet to TRUE if the PXE Base Code Callback Protocol is available.
292f737cfb953905f42f3324e8e53ec324a15314210jgong    Set to FALSE if the PXE Base Code Callback Protocol is not available.
293e285199897e538523f762cb5b3900e81f872035avanjeff
294f737cfb953905f42f3324e8e53ec324a15314210jgong  @param  This                  Pointer to the EFI_PXE_BASE_CODE_PROTOCOL instance.
295f737cfb953905f42f3324e8e53ec324a15314210jgong  @param  UseIpv6               Specifies the type of IP addresses that are to be used during the session
296e285199897e538523f762cb5b3900e81f872035avanjeff                                that is being started. Set to TRUE for IPv6 addresses, and FALSE for
297e285199897e538523f762cb5b3900e81f872035avanjeff                                IPv4 addresses.
298e285199897e538523f762cb5b3900e81f872035avanjeff
299f737cfb953905f42f3324e8e53ec324a15314210jgong  @retval EFI_SUCCESS           The PXE Base Code Protocol was started.
300e285199897e538523f762cb5b3900e81f872035avanjeff  @retval EFI_DEVICE_ERROR      The network device encountered an error during this oper
301f737cfb953905f42f3324e8e53ec324a15314210jgong  @retval EFI_UNSUPPORTED       UseIpv6 is TRUE, but the Ipv6Supported field of the
302e285199897e538523f762cb5b3900e81f872035avanjeff                                EFI_PXE_BASE_CODE_MODE structure is FALSE.
303e285199897e538523f762cb5b3900e81f872035avanjeff  @retval EFI_ALREADY_STARTED   The PXE Base Code Protocol is already in the started state.
304f737cfb953905f42f3324e8e53ec324a15314210jgong  @retval EFI_INVALID_PARAMETER The This parameter is NULL or does not point to a valid
305e285199897e538523f762cb5b3900e81f872035avanjeff                                EFI_PXE_BASE_CODE_PROTOCOL structure.
306e285199897e538523f762cb5b3900e81f872035avanjeff  @retval EFI_OUT_OF_RESOURCES  Could not allocate enough memory or other resources to start the
307e285199897e538523f762cb5b3900e81f872035avanjeff                                PXE Base Code Protocol.
308e285199897e538523f762cb5b3900e81f872035avanjeff
309dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff**/
310dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeffEFI_STATUS
311dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeffEFIAPI
312dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeffEfiPxeBcStart (
313dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  IN EFI_PXE_BASE_CODE_PROTOCOL       *This,
314dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  IN BOOLEAN                          UseIpv6
315dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  )
316dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff{
317dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  PXEBC_PRIVATE_DATA      *Private;
318dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  EFI_PXE_BASE_CODE_MODE  *Mode;
319dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  EFI_STATUS              Status;
320dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
321dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  if (This == NULL) {
322dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    return EFI_INVALID_PARAMETER;
323dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  }
324dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
325dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  Private = PXEBC_PRIVATE_DATA_FROM_PXEBC (This);
326dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  Mode    = Private->PxeBc.Mode;
327dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
328dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  if (Mode->Started) {
329dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    return EFI_ALREADY_STARTED;
330dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  }
331dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
332dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  if (UseIpv6) {
333dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    //
334dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    // IPv6 is not supported now.
335dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    //
336dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    return EFI_UNSUPPORTED;
337dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  }
338dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
339dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  //
340dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  // Configure the udp4 instance to let it receive data
341dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  //
342f737cfb953905f42f3324e8e53ec324a15314210jgong  Status = Private->Udp4Read->Configure (
343e285199897e538523f762cb5b3900e81f872035avanjeff                               Private->Udp4Read,
344f737cfb953905f42f3324e8e53ec324a15314210jgong                               &Private->Udp4CfgData
345f737cfb953905f42f3324e8e53ec324a15314210jgong                               );
346dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  if (EFI_ERROR (Status)) {
347dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    return Status;
348dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  }
349dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
350cfbc1a7537d55ff0066b5635855f5739d02d15dchhuan
351cfbc1a7537d55ff0066b5635855f5739d02d15dchhuan  //
352cfbc1a7537d55ff0066b5635855f5739d02d15dchhuan  // Configure block size for TFTP as a default value to handle all link layers.
353cfbc1a7537d55ff0066b5635855f5739d02d15dchhuan  //
354cfbc1a7537d55ff0066b5635855f5739d02d15dchhuan  Private->BlockSize   = (UINTN) (MIN (Private->Ip4MaxPacketSize, PXEBC_DEFAULT_PACKET_SIZE) -
355cfbc1a7537d55ff0066b5635855f5739d02d15dchhuan                           PXEBC_DEFAULT_UDP_OVERHEAD_SIZE - PXEBC_DEFAULT_TFTP_OVERHEAD_SIZE);
356cfbc1a7537d55ff0066b5635855f5739d02d15dchhuan  //
357cfbc1a7537d55ff0066b5635855f5739d02d15dchhuan  // If PcdTftpBlockSize is set to non-zero, override the default value.
358cfbc1a7537d55ff0066b5635855f5739d02d15dchhuan  //
359cfbc1a7537d55ff0066b5635855f5739d02d15dchhuan  if (PcdGet64 (PcdTftpBlockSize) != 0) {
360cfbc1a7537d55ff0066b5635855f5739d02d15dchhuan    Private->BlockSize   = (UINTN) PcdGet64 (PcdTftpBlockSize);
361cfbc1a7537d55ff0066b5635855f5739d02d15dchhuan  }
362cfbc1a7537d55ff0066b5635855f5739d02d15dchhuan
363dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  Private->AddressIsOk = FALSE;
364dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
365dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  ZeroMem (Mode, sizeof (EFI_PXE_BASE_CODE_MODE));
366dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
367dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  Mode->Started = TRUE;
368dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  Mode->TTL     = DEFAULT_TTL;
369dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  Mode->ToS     = DEFAULT_ToS;
370dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  Mode->AutoArp = TRUE;
371dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
372982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  //
373982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  // Create the event for Arp Cache checking.
374982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  //
375982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  Status = gBS->CreateEvent (
376982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff                  EVT_TIMER | EVT_NOTIFY_SIGNAL,
377982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff                  TPL_CALLBACK,
378982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff                  ArpCacheUpdateTimeout,
379982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff                  This,
380982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff                  &Private->GetArpCacheEvent
381982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff                  );
382982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  if (EFI_ERROR (Status)) {
383982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff    goto ON_EXIT;
384982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  }
385982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff
386982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  //
387982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  // Start the timeout timer event.
388982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  //
389982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  Status = gBS->SetTimer (
390982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff                  Private->GetArpCacheEvent,
391982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff                  TimerPeriodic,
392982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff                  TICKS_PER_SECOND
393982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff                  );
394982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff
395982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  if (EFI_ERROR (Status)) {
396982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff    goto ON_EXIT;
397982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  }
398982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff
399982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  //
400982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  // Create ICMP error receiving event
401982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  //
402982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  Status = gBS->CreateEvent (
403982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff                  EVT_NOTIFY_SIGNAL,
404982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff                  TPL_NOTIFY,
405982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff                  IcmpErrorListenHandler,
406982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff                  Private,
407982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff                  &(Private->IcmpErrorRcvToken.Event)
408982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff                  );
409982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  if (EFI_ERROR (Status)) {
410982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff    goto ON_EXIT;
411982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  }
412982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff
41314e84fd8888bfcc0f0d8fae8b69c6428b4226d1dZhang Lubo  //
41414e84fd8888bfcc0f0d8fae8b69c6428b4226d1dZhang Lubo  //DHCP4 service allows only one of its children to be configured in
41514e84fd8888bfcc0f0d8fae8b69c6428b4226d1dZhang Lubo  //the active state, If the DHCP4 D.O.R.A started by IP4 auto
41614e84fd8888bfcc0f0d8fae8b69c6428b4226d1dZhang Lubo  //configuration and has not been completed, the Dhcp4 state machine
41714e84fd8888bfcc0f0d8fae8b69c6428b4226d1dZhang Lubo  //will not be in the right state for the PXE to start a new round D.O.R.A.
41814e84fd8888bfcc0f0d8fae8b69c6428b4226d1dZhang Lubo  //so we need to switch it's policy to static.
41914e84fd8888bfcc0f0d8fae8b69c6428b4226d1dZhang Lubo  //
42014e84fd8888bfcc0f0d8fae8b69c6428b4226d1dZhang Lubo  Status = PxeBcSetIp4Policy (Private);
42114e84fd8888bfcc0f0d8fae8b69c6428b4226d1dZhang Lubo  if (EFI_ERROR (Status)) {
42214e84fd8888bfcc0f0d8fae8b69c6428b4226d1dZhang Lubo    goto ON_EXIT;
42314e84fd8888bfcc0f0d8fae8b69c6428b4226d1dZhang Lubo  }
42414e84fd8888bfcc0f0d8fae8b69c6428b4226d1dZhang Lubo
425982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  Status = Private->Ip4->Configure (Private->Ip4, &Private->Ip4ConfigData);
426982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  if (EFI_ERROR (Status)) {
427982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff    goto ON_EXIT;
428982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  }
429982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff
430982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  //
431982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  // start to listen incoming packet
432982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  //
433982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  Status = Private->Ip4->Receive (Private->Ip4, &Private->IcmpErrorRcvToken);
434982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  if (!EFI_ERROR (Status)) {
435982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff    return Status;
436982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  }
437982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff
438982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeffON_EXIT:
439982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  Private->Ip4->Configure (Private->Ip4, NULL);
440982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff
441982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  if (Private->IcmpErrorRcvToken.Event != NULL) {
442982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff    gBS->CloseEvent (Private->IcmpErrorRcvToken.Event);
443982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  }
444982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff
445982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  if (Private->GetArpCacheEvent != NULL) {
446982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff    gBS->SetTimer (Private->GetArpCacheEvent, TimerCancel, 0);
447982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff    gBS->CloseEvent (Private->GetArpCacheEvent);
448982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  }
449982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff
450982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  Mode->Started = FALSE;
451982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  Mode->TTL     = 0;
452982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  Mode->ToS     = 0;
453982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  Mode->AutoArp = FALSE;
454982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff
455982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  return Status;
456dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff}
457dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
458dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
459e285199897e538523f762cb5b3900e81f872035avanjeff/**
460f737cfb953905f42f3324e8e53ec324a15314210jgong  Disables the use of the PXE Base Code Protocol functions.
461f737cfb953905f42f3324e8e53ec324a15314210jgong
462f737cfb953905f42f3324e8e53ec324a15314210jgong  This function stops all activity on the network device. All the resources allocated
463f737cfb953905f42f3324e8e53ec324a15314210jgong  in Start() are released, the Started field of the EFI_PXE_BASE_CODE_MODE structure is
464f737cfb953905f42f3324e8e53ec324a15314210jgong  set to FALSE and EFI_SUCCESS is returned. If the Started field of the EFI_PXE_BASE_CODE_MODE
465f737cfb953905f42f3324e8e53ec324a15314210jgong  structure is already FALSE, then EFI_NOT_STARTED will be returned.
466e285199897e538523f762cb5b3900e81f872035avanjeff
467f737cfb953905f42f3324e8e53ec324a15314210jgong  @param  This                  Pointer to the EFI_PXE_BASE_CODE_PROTOCOL instance.
468e285199897e538523f762cb5b3900e81f872035avanjeff
469f737cfb953905f42f3324e8e53ec324a15314210jgong  @retval EFI_SUCCESS           The PXE Base Code Protocol was stopped.
470e285199897e538523f762cb5b3900e81f872035avanjeff  @retval EFI_NOT_STARTED       The PXE Base Code Protocol is already in the stopped state.
471f737cfb953905f42f3324e8e53ec324a15314210jgong  @retval EFI_INVALID_PARAMETER The This parameter is NULL or does not point to a valid
472e285199897e538523f762cb5b3900e81f872035avanjeff                                EFI_PXE_BASE_CODE_PROTOCOL structure.
473e285199897e538523f762cb5b3900e81f872035avanjeff  @retval EFI_DEVICE_ERROR      The network device encountered an error during this operation.
474e285199897e538523f762cb5b3900e81f872035avanjeff
475dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff**/
476dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeffEFI_STATUS
477dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeffEFIAPI
478dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeffEfiPxeBcStop (
479dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  IN EFI_PXE_BASE_CODE_PROTOCOL       *This
480dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  )
481dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff{
482dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  PXEBC_PRIVATE_DATA      *Private;
483dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  EFI_PXE_BASE_CODE_MODE  *Mode;
484dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
485dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  if (This == NULL) {
486dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    return EFI_INVALID_PARAMETER;
487dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  }
488dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
489dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  Private = PXEBC_PRIVATE_DATA_FROM_PXEBC (This);
490dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  Mode    = Private->PxeBc.Mode;
491dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
492dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  if (!Mode->Started) {
493dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    return EFI_NOT_STARTED;
494dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  }
495dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
496982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  Private->Ip4->Cancel (Private->Ip4, NULL);
497982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  //
498982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  // Dispatch the DPCs queued by the NotifyFunction of the canceled rx token's
499982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  // events.
500982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  //
501d8d26fb207e02aa5ef57e2bcb213f9dda16166ccmdkinney  DispatchDpc ();
502982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff
503982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  Private->Ip4->Configure (Private->Ip4, NULL);
504982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff
505982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  //
506982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  // Close the ICMP error receiving event.
507982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  //
508982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  gBS->CloseEvent (Private->IcmpErrorRcvToken.Event);
509982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff
510982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  //
511982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  // Cancel the TimeoutEvent timer.
512982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  //
513982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  gBS->SetTimer (Private->GetArpCacheEvent, TimerCancel, 0);
514982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff
515982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  //
516982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  // Close the TimeoutEvent event.
517982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  //
518982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  gBS->CloseEvent (Private->GetArpCacheEvent);
519982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff
520dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  Mode->Started = FALSE;
521dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
5228792362f22e4fac66aeec04b13b7a6b70cb571e9vanjeff  Private->CurrentUdpSrcPort = 0;
5238792362f22e4fac66aeec04b13b7a6b70cb571e9vanjeff  Private->Udp4Write->Configure (Private->Udp4Write, NULL);
524434ce3feca7f5a430db3d5853c54a06343d02ed2vanjeff  Private->Udp4Read->Groups (Private->Udp4Read, FALSE, NULL);
5258792362f22e4fac66aeec04b13b7a6b70cb571e9vanjeff  Private->Udp4Read->Configure (Private->Udp4Read, NULL);
526dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
527dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  Private->Dhcp4->Stop (Private->Dhcp4);
528dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  Private->Dhcp4->Configure (Private->Dhcp4, NULL);
529dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
530dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  Private->FileSize = 0;
531dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
532dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  return EFI_SUCCESS;
533dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff}
534dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
535dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
536e285199897e538523f762cb5b3900e81f872035avanjeff/**
537f737cfb953905f42f3324e8e53ec324a15314210jgong  Attempts to complete a DHCPv4 D.O.R.A. (discover / offer / request / acknowledge) or DHCPv6
538f737cfb953905f42f3324e8e53ec324a15314210jgong  S.A.R.R (solicit / advertise / request / reply) sequence.
539f737cfb953905f42f3324e8e53ec324a15314210jgong
540f737cfb953905f42f3324e8e53ec324a15314210jgong  This function attempts to complete the DHCP sequence. If this sequence is completed,
541f737cfb953905f42f3324e8e53ec324a15314210jgong  then EFI_SUCCESS is returned, and the DhcpCompleted, ProxyOfferReceived, StationIp,
542f737cfb953905f42f3324e8e53ec324a15314210jgong  SubnetMask, DhcpDiscover, DhcpAck, and ProxyOffer fields of the EFI_PXE_BASE_CODE_MODE
543f737cfb953905f42f3324e8e53ec324a15314210jgong  structure are filled in.
544f737cfb953905f42f3324e8e53ec324a15314210jgong  If SortOffers is TRUE, then the cached DHCP offer packets will be sorted before
545f737cfb953905f42f3324e8e53ec324a15314210jgong  they are tried. If SortOffers is FALSE, then the cached DHCP offer packets will
546f737cfb953905f42f3324e8e53ec324a15314210jgong  be tried in the order in which they are received. Please see the Preboot Execution
547f737cfb953905f42f3324e8e53ec324a15314210jgong  Environment (PXE) Specification for additional details on the implementation of DHCP.
548f737cfb953905f42f3324e8e53ec324a15314210jgong  This function can take at least 31 seconds to timeout and return control to the
549f737cfb953905f42f3324e8e53ec324a15314210jgong  caller. If the DHCP sequence does not complete, then EFI_TIMEOUT will be returned.
550f737cfb953905f42f3324e8e53ec324a15314210jgong  If the Callback Protocol does not return EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE,
551f737cfb953905f42f3324e8e53ec324a15314210jgong  then the DHCP sequence will be stopped and EFI_ABORTED will be returned.
552e285199897e538523f762cb5b3900e81f872035avanjeff
553f737cfb953905f42f3324e8e53ec324a15314210jgong  @param  This                  Pointer to the EFI_PXE_BASE_CODE_PROTOCOL instance.
554f737cfb953905f42f3324e8e53ec324a15314210jgong  @param  SortOffers            TRUE if the offers received should be sorted. Set to FALSE to try the
555e285199897e538523f762cb5b3900e81f872035avanjeff                                offers in the order that they are received.
556e285199897e538523f762cb5b3900e81f872035avanjeff
557f737cfb953905f42f3324e8e53ec324a15314210jgong  @retval EFI_SUCCESS           Valid DHCP has completed.
558f737cfb953905f42f3324e8e53ec324a15314210jgong  @retval EFI_NOT_STARTED       The PXE Base Code Protocol is in the stopped state.
559f737cfb953905f42f3324e8e53ec324a15314210jgong  @retval EFI_INVALID_PARAMETER The This parameter is NULL or does not point to a valid
560e285199897e538523f762cb5b3900e81f872035avanjeff                                EFI_PXE_BASE_CODE_PROTOCOL structure.
561e285199897e538523f762cb5b3900e81f872035avanjeff  @retval EFI_DEVICE_ERROR      The network device encountered an error during this operation.
562f737cfb953905f42f3324e8e53ec324a15314210jgong  @retval EFI_OUT_OF_RESOURCES  Could not allocate enough memory to complete the DHCP Protocol.
563f737cfb953905f42f3324e8e53ec324a15314210jgong  @retval EFI_ABORTED           The callback function aborted the DHCP Protocol.
564f737cfb953905f42f3324e8e53ec324a15314210jgong  @retval EFI_TIMEOUT           The DHCP Protocol timed out.
565f737cfb953905f42f3324e8e53ec324a15314210jgong  @retval EFI_ICMP_ERROR        An ICMP error packet was received during the DHCP session.
566f737cfb953905f42f3324e8e53ec324a15314210jgong  @retval EFI_NO_RESPONSE       Valid PXE offer was not received.
567e285199897e538523f762cb5b3900e81f872035avanjeff
568dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff**/
569dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeffEFI_STATUS
570dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeffEFIAPI
571dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeffEfiPxeBcDhcp (
572dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  IN EFI_PXE_BASE_CODE_PROTOCOL       *This,
573dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  IN BOOLEAN                          SortOffers
574dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  )
575dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff{
5768730386e6d669ded738c6f846aa26bf1c96228bfhhuan  PXEBC_PRIVATE_DATA           *Private;
5778730386e6d669ded738c6f846aa26bf1c96228bfhhuan  EFI_PXE_BASE_CODE_MODE       *Mode;
5788730386e6d669ded738c6f846aa26bf1c96228bfhhuan  EFI_DHCP4_PROTOCOL           *Dhcp4;
5798730386e6d669ded738c6f846aa26bf1c96228bfhhuan  EFI_DHCP4_CONFIG_DATA        Dhcp4CfgData;
5808730386e6d669ded738c6f846aa26bf1c96228bfhhuan  EFI_DHCP4_MODE_DATA          Dhcp4Mode;
5818730386e6d669ded738c6f846aa26bf1c96228bfhhuan  EFI_DHCP4_PACKET_OPTION      *OptList[PXEBC_DHCP4_MAX_OPTION_NUM];
5828730386e6d669ded738c6f846aa26bf1c96228bfhhuan  UINT32                       OptCount;
5838730386e6d669ded738c6f846aa26bf1c96228bfhhuan  EFI_STATUS                   Status;
5848730386e6d669ded738c6f846aa26bf1c96228bfhhuan  EFI_ARP_CONFIG_DATA          ArpConfigData;
5858730386e6d669ded738c6f846aa26bf1c96228bfhhuan  EFI_PXE_BASE_CODE_IP_FILTER  IpFilter;
586dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
587dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  if (This == NULL) {
588dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    return EFI_INVALID_PARAMETER;
589dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  }
590dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
591dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  Status              = EFI_SUCCESS;
592dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  Private             = PXEBC_PRIVATE_DATA_FROM_PXEBC (This);
593dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  Mode                = Private->PxeBc.Mode;
594dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  Dhcp4               = Private->Dhcp4;
595dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  Private->Function   = EFI_PXE_BASE_CODE_FUNCTION_DHCP;
596dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  Private->SortOffers = SortOffers;
597dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
598dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  if (!Mode->Started) {
599dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    return EFI_NOT_STARTED;
600dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  }
601982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff
602982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  Mode->IcmpErrorReceived = FALSE;
603982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff
604dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  //
6058730386e6d669ded738c6f846aa26bf1c96228bfhhuan  // Stop Udp4Read instance
6068730386e6d669ded738c6f846aa26bf1c96228bfhhuan  //
6078730386e6d669ded738c6f846aa26bf1c96228bfhhuan  Private->Udp4Read->Configure (Private->Udp4Read, NULL);
6088730386e6d669ded738c6f846aa26bf1c96228bfhhuan
6098730386e6d669ded738c6f846aa26bf1c96228bfhhuan  //
610dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  // Initialize the DHCP options and build the option list
611dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  //
612dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  OptCount = PxeBcBuildDhcpOptions (Private, OptList, TRUE);
613dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
614dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  //
615dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  // Set the DHCP4 config data.
616434ce3feca7f5a430db3d5853c54a06343d02ed2vanjeff  // The four discovery timeouts are 4, 8, 16, 32 seconds respectively.
617dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  //
618e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff  ZeroMem (&Dhcp4CfgData, sizeof (EFI_DHCP4_CONFIG_DATA));
619dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  Dhcp4CfgData.OptionCount      = OptCount;
620dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  Dhcp4CfgData.OptionList       = OptList;
621dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  Dhcp4CfgData.Dhcp4Callback    = PxeBcDhcpCallBack;
622dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  Dhcp4CfgData.CallbackContext  = Private;
623434ce3feca7f5a430db3d5853c54a06343d02ed2vanjeff  Dhcp4CfgData.DiscoverTryCount = 4;
624434ce3feca7f5a430db3d5853c54a06343d02ed2vanjeff  Dhcp4CfgData.DiscoverTimeout  = mPxeDhcpTimeout;
625dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
626434ce3feca7f5a430db3d5853c54a06343d02ed2vanjeff  Status          = Dhcp4->Configure (Dhcp4, &Dhcp4CfgData);
627434ce3feca7f5a430db3d5853c54a06343d02ed2vanjeff  if (EFI_ERROR (Status)) {
628434ce3feca7f5a430db3d5853c54a06343d02ed2vanjeff    goto ON_EXIT;
629434ce3feca7f5a430db3d5853c54a06343d02ed2vanjeff  }
630e285199897e538523f762cb5b3900e81f872035avanjeff
631434ce3feca7f5a430db3d5853c54a06343d02ed2vanjeff  //
632434ce3feca7f5a430db3d5853c54a06343d02ed2vanjeff  // Zero those arrays to record the varies numbers of DHCP OFFERS.
633434ce3feca7f5a430db3d5853c54a06343d02ed2vanjeff  //
634434ce3feca7f5a430db3d5853c54a06343d02ed2vanjeff  Private->GotProxyOffer = FALSE;
635434ce3feca7f5a430db3d5853c54a06343d02ed2vanjeff  Private->NumOffers     = 0;
636434ce3feca7f5a430db3d5853c54a06343d02ed2vanjeff  Private->BootpIndex    = 0;
637434ce3feca7f5a430db3d5853c54a06343d02ed2vanjeff  ZeroMem (Private->ServerCount, sizeof (Private->ServerCount));
638434ce3feca7f5a430db3d5853c54a06343d02ed2vanjeff  ZeroMem (Private->ProxyIndex, sizeof (Private->ProxyIndex));
639dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
640434ce3feca7f5a430db3d5853c54a06343d02ed2vanjeff  Status = Dhcp4->Start (Dhcp4, NULL);
641cbfb9e5eaf51aa351842aaa58efd1c2a8a38ef3aZhang Lubo  if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {
642434ce3feca7f5a430db3d5853c54a06343d02ed2vanjeff    if (Status == EFI_ICMP_ERROR) {
643434ce3feca7f5a430db3d5853c54a06343d02ed2vanjeff      Mode->IcmpErrorReceived = TRUE;
644dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    }
645434ce3feca7f5a430db3d5853c54a06343d02ed2vanjeff    goto ON_EXIT;
646434ce3feca7f5a430db3d5853c54a06343d02ed2vanjeff  }
647dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
648434ce3feca7f5a430db3d5853c54a06343d02ed2vanjeff  Status = Dhcp4->GetModeData (Dhcp4, &Dhcp4Mode);
649434ce3feca7f5a430db3d5853c54a06343d02ed2vanjeff  if (EFI_ERROR (Status)) {
650434ce3feca7f5a430db3d5853c54a06343d02ed2vanjeff    goto ON_EXIT;
651434ce3feca7f5a430db3d5853c54a06343d02ed2vanjeff  }
652dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
653434ce3feca7f5a430db3d5853c54a06343d02ed2vanjeff  ASSERT (Dhcp4Mode.State == Dhcp4Bound);
654dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
655434ce3feca7f5a430db3d5853c54a06343d02ed2vanjeff  CopyMem (&Private->StationIp, &Dhcp4Mode.ClientAddress, sizeof (EFI_IPv4_ADDRESS));
656434ce3feca7f5a430db3d5853c54a06343d02ed2vanjeff  CopyMem (&Private->SubnetMask, &Dhcp4Mode.SubnetMask, sizeof (EFI_IPv4_ADDRESS));
657434ce3feca7f5a430db3d5853c54a06343d02ed2vanjeff  CopyMem (&Private->GatewayIp, &Dhcp4Mode.RouterAddress, sizeof (EFI_IPv4_ADDRESS));
658319075ff6e1d1fb470667453ec24a2ba685f60a0vanjeff
659434ce3feca7f5a430db3d5853c54a06343d02ed2vanjeff  CopyMem (&Mode->StationIp, &Private->StationIp, sizeof (EFI_IPv4_ADDRESS));
660434ce3feca7f5a430db3d5853c54a06343d02ed2vanjeff  CopyMem (&Mode->SubnetMask, &Private->SubnetMask, sizeof (EFI_IPv4_ADDRESS));
661dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
662434ce3feca7f5a430db3d5853c54a06343d02ed2vanjeff  //
663434ce3feca7f5a430db3d5853c54a06343d02ed2vanjeff  // Check the selected offer to see whether BINL is required, if no or BINL is
664434ce3feca7f5a430db3d5853c54a06343d02ed2vanjeff  // finished, set the various Mode members.
665434ce3feca7f5a430db3d5853c54a06343d02ed2vanjeff  //
666434ce3feca7f5a430db3d5853c54a06343d02ed2vanjeff  Status = PxeBcCheckSelectedOffer (Private);
667dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
668434ce3feca7f5a430db3d5853c54a06343d02ed2vanjeffON_EXIT:
669dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  if (EFI_ERROR (Status)) {
670dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    Dhcp4->Stop (Dhcp4);
671dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    Dhcp4->Configure (Dhcp4, NULL);
672dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  } else {
673dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    //
674dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    // Remove the previously configured option list and callback function
675dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    //
676e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff    ZeroMem (&Dhcp4CfgData, sizeof (EFI_DHCP4_CONFIG_DATA));
677dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    Dhcp4->Configure (Dhcp4, &Dhcp4CfgData);
678dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
679dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    Private->AddressIsOk = TRUE;
6808d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff
6818d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff    if (!Mode->UsingIpv6) {
6828d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff      //
6838d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff      // If in IPv4 mode, configure the corresponding ARP with this new
6848d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff      // station IP address.
6858d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff      //
6868d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff      ZeroMem (&ArpConfigData, sizeof (EFI_ARP_CONFIG_DATA));
6878d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff
6888d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff      ArpConfigData.SwAddressType   = 0x0800;
689c9325700d0ef25eaf45077928af3f93b15ac5fe0ydong      ArpConfigData.SwAddressLength = (UINT8) sizeof (EFI_IPv4_ADDRESS);
6908d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff      ArpConfigData.StationAddress  = &Private->StationIp.v4;
6918d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff
6928d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff      Private->Arp->Configure (Private->Arp, NULL);
6938d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff      Private->Arp->Configure (Private->Arp, &ArpConfigData);
694982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff
695982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff      //
696982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff      // Updated the route table. Fill the first entry.
697982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff      //
698982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff      Mode->RouteTableEntries                = 1;
699982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff      Mode->RouteTable[0].IpAddr.Addr[0]     = Private->StationIp.Addr[0] & Private->SubnetMask.Addr[0];
700982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff      Mode->RouteTable[0].SubnetMask.Addr[0] = Private->SubnetMask.Addr[0];
701982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff      Mode->RouteTable[0].GwAddr.Addr[0]     = 0;
702982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff
703982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff      //
704982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff      // Create the default route entry if there is a default router.
705982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff      //
706982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff      if (Private->GatewayIp.Addr[0] != 0) {
707982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff        Mode->RouteTableEntries                = 2;
708982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff        Mode->RouteTable[1].IpAddr.Addr[0]     = 0;
709982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff        Mode->RouteTable[1].SubnetMask.Addr[0] = 0;
710982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff        Mode->RouteTable[1].GwAddr.Addr[0]     = Private->GatewayIp.Addr[0];
711982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff      }
7128730386e6d669ded738c6f846aa26bf1c96228bfhhuan
7138730386e6d669ded738c6f846aa26bf1c96228bfhhuan      //
7148730386e6d669ded738c6f846aa26bf1c96228bfhhuan      // Flush new station IP address into Udp4CfgData and Ip4ConfigData
7158730386e6d669ded738c6f846aa26bf1c96228bfhhuan      //
7168730386e6d669ded738c6f846aa26bf1c96228bfhhuan      CopyMem (&Private->Udp4CfgData.StationAddress, &Private->StationIp, sizeof (EFI_IPv4_ADDRESS));
7178730386e6d669ded738c6f846aa26bf1c96228bfhhuan      CopyMem (&Private->Udp4CfgData.SubnetMask, &Private->SubnetMask, sizeof (EFI_IPv4_ADDRESS));
7188730386e6d669ded738c6f846aa26bf1c96228bfhhuan      CopyMem (&Private->Ip4ConfigData.StationAddress, &Private->StationIp, sizeof (EFI_IPv4_ADDRESS));
7198730386e6d669ded738c6f846aa26bf1c96228bfhhuan      CopyMem (&Private->Ip4ConfigData.SubnetMask, &Private->SubnetMask, sizeof (EFI_IPv4_ADDRESS));
7208730386e6d669ded738c6f846aa26bf1c96228bfhhuan
7218730386e6d669ded738c6f846aa26bf1c96228bfhhuan      //
7228730386e6d669ded738c6f846aa26bf1c96228bfhhuan      // Reconfigure the Ip4 instance to capture background ICMP packets with new station Ip address.
7238730386e6d669ded738c6f846aa26bf1c96228bfhhuan      //
7248730386e6d669ded738c6f846aa26bf1c96228bfhhuan      Private->Ip4->Cancel (Private->Ip4, &Private->IcmpErrorRcvToken);
7258730386e6d669ded738c6f846aa26bf1c96228bfhhuan      Private->Ip4->Configure (Private->Ip4, NULL);
7268730386e6d669ded738c6f846aa26bf1c96228bfhhuan
7278730386e6d669ded738c6f846aa26bf1c96228bfhhuan      Status = Private->Ip4->Configure (Private->Ip4, &Private->Ip4ConfigData);
7288730386e6d669ded738c6f846aa26bf1c96228bfhhuan      if (EFI_ERROR (Status)) {
7298730386e6d669ded738c6f846aa26bf1c96228bfhhuan        goto ON_EXIT;
7308730386e6d669ded738c6f846aa26bf1c96228bfhhuan      }
7318730386e6d669ded738c6f846aa26bf1c96228bfhhuan
7328730386e6d669ded738c6f846aa26bf1c96228bfhhuan      Status = Private->Ip4->Receive (Private->Ip4, &Private->IcmpErrorRcvToken);
7338730386e6d669ded738c6f846aa26bf1c96228bfhhuan      if (EFI_ERROR (Status)) {
7348730386e6d669ded738c6f846aa26bf1c96228bfhhuan        goto ON_EXIT;
7358730386e6d669ded738c6f846aa26bf1c96228bfhhuan      }
7368d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff    }
737dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  }
738dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
739357af28525c3a5be6ca0a201f2533dc0a372dbfbsfu  Private->Udp4Read->Configure (Private->Udp4Read, &Private->Udp4CfgData);
740c82291bc3108c948a66d659da0fd76731351f530hhuan
7418730386e6d669ded738c6f846aa26bf1c96228bfhhuan  //
7428730386e6d669ded738c6f846aa26bf1c96228bfhhuan  // Dhcp(), Discover(), and Mtftp() set the IP filter, and return with the IP
7438730386e6d669ded738c6f846aa26bf1c96228bfhhuan  // receive filter list emptied and the filter set to EFI_PXE_BASE_CODE_IP_FILTER_STATION_IP.
7448730386e6d669ded738c6f846aa26bf1c96228bfhhuan  //
7458730386e6d669ded738c6f846aa26bf1c96228bfhhuan  ZeroMem(&IpFilter, sizeof (EFI_PXE_BASE_CODE_IP_FILTER));
7468730386e6d669ded738c6f846aa26bf1c96228bfhhuan  IpFilter.Filters = EFI_PXE_BASE_CODE_IP_FILTER_STATION_IP;
7478730386e6d669ded738c6f846aa26bf1c96228bfhhuan  This->SetIpFilter (This, &IpFilter);
7488730386e6d669ded738c6f846aa26bf1c96228bfhhuan
749dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  return Status;
750dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff}
751dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
752dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
753e285199897e538523f762cb5b3900e81f872035avanjeff/**
754f737cfb953905f42f3324e8e53ec324a15314210jgong  Attempts to complete the PXE Boot Server and/or boot image discovery sequence.
755f737cfb953905f42f3324e8e53ec324a15314210jgong
756f737cfb953905f42f3324e8e53ec324a15314210jgong  This function attempts to complete the PXE Boot Server and/or boot image discovery
757f737cfb953905f42f3324e8e53ec324a15314210jgong  sequence. If this sequence is completed, then EFI_SUCCESS is returned, and the
758f737cfb953905f42f3324e8e53ec324a15314210jgong  PxeDiscoverValid, PxeDiscover, PxeReplyReceived, and PxeReply fields of the
759f737cfb953905f42f3324e8e53ec324a15314210jgong  EFI_PXE_BASE_CODE_MODE structure are filled in. If UseBis is TRUE, then the
760f737cfb953905f42f3324e8e53ec324a15314210jgong  PxeBisReplyReceived and PxeBisReply fields of the EFI_PXE_BASE_CODE_MODE structure
761f737cfb953905f42f3324e8e53ec324a15314210jgong  will also be filled in. If UseBis is FALSE, then PxeBisReplyValid will be set to FALSE.
762f737cfb953905f42f3324e8e53ec324a15314210jgong  In the structure referenced by parameter Info, the PXE Boot Server list, SrvList[],
763f737cfb953905f42f3324e8e53ec324a15314210jgong  has two uses: It is the Boot Server IP address list used for unicast discovery
764f737cfb953905f42f3324e8e53ec324a15314210jgong  (if the UseUCast field is TRUE), and it is the list used for Boot Server verification
765f737cfb953905f42f3324e8e53ec324a15314210jgong  (if the MustUseList field is TRUE). Also, if the MustUseList field in that structure
766f737cfb953905f42f3324e8e53ec324a15314210jgong  is TRUE and the AcceptAnyResponse field in the SrvList[] array is TRUE, any Boot
767f737cfb953905f42f3324e8e53ec324a15314210jgong  Server reply of that type will be accepted. If the AcceptAnyResponse field is
768f737cfb953905f42f3324e8e53ec324a15314210jgong  FALSE, only responses from Boot Servers with matching IP addresses will be accepted.
769f737cfb953905f42f3324e8e53ec324a15314210jgong  This function can take at least 10 seconds to timeout and return control to the
770f737cfb953905f42f3324e8e53ec324a15314210jgong  caller. If the Discovery sequence does not complete, then EFI_TIMEOUT will be
771f737cfb953905f42f3324e8e53ec324a15314210jgong  returned. Please see the Preboot Execution Environment (PXE) Specification for
772f737cfb953905f42f3324e8e53ec324a15314210jgong  additional details on the implementation of the Discovery sequence.
773f737cfb953905f42f3324e8e53ec324a15314210jgong  If the Callback Protocol does not return EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE,
774f737cfb953905f42f3324e8e53ec324a15314210jgong  then the Discovery sequence is stopped and EFI_ABORTED will be returned.
775e285199897e538523f762cb5b3900e81f872035avanjeff
776f737cfb953905f42f3324e8e53ec324a15314210jgong  @param  This                  Pointer to the EFI_PXE_BASE_CODE_PROTOCOL instance.
777f737cfb953905f42f3324e8e53ec324a15314210jgong  @param  Type                  The type of bootstrap to perform.
778f737cfb953905f42f3324e8e53ec324a15314210jgong  @param  Layer                 Pointer to the boot server layer number to discover, which must be
779e285199897e538523f762cb5b3900e81f872035avanjeff                                PXE_BOOT_LAYER_INITIAL when a new server type is being
780e285199897e538523f762cb5b3900e81f872035avanjeff                                discovered.
781e285199897e538523f762cb5b3900e81f872035avanjeff  @param  UseBis                TRUE if Boot Integrity Services are to be used. FALSE otherwise.
782f737cfb953905f42f3324e8e53ec324a15314210jgong  @param  Info                  Pointer to a data structure that contains additional information on the
783e285199897e538523f762cb5b3900e81f872035avanjeff                                type of discovery operation that is to be performed.
784e285199897e538523f762cb5b3900e81f872035avanjeff
785f737cfb953905f42f3324e8e53ec324a15314210jgong  @retval EFI_SUCCESS           The Discovery sequence has been completed.
786f737cfb953905f42f3324e8e53ec324a15314210jgong  @retval EFI_NOT_STARTED       The PXE Base Code Protocol is in the stopped state.
787e285199897e538523f762cb5b3900e81f872035avanjeff  @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
788e285199897e538523f762cb5b3900e81f872035avanjeff  @retval EFI_DEVICE_ERROR      The network device encountered an error during this operation.
789f737cfb953905f42f3324e8e53ec324a15314210jgong  @retval EFI_OUT_OF_RESOURCES  Could not allocate enough memory to complete Discovery.
790f737cfb953905f42f3324e8e53ec324a15314210jgong  @retval EFI_ABORTED           The callback function aborted the Discovery sequence.
791f737cfb953905f42f3324e8e53ec324a15314210jgong  @retval EFI_TIMEOUT           The Discovery sequence timed out.
792f737cfb953905f42f3324e8e53ec324a15314210jgong  @retval EFI_ICMP_ERROR        An ICMP error packet was received during the PXE discovery
793e285199897e538523f762cb5b3900e81f872035avanjeff                                session.
794e285199897e538523f762cb5b3900e81f872035avanjeff
795dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff**/
796dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeffEFI_STATUS
797dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeffEFIAPI
798dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeffEfiPxeBcDiscover (
799dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  IN EFI_PXE_BASE_CODE_PROTOCOL       *This,
800dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  IN UINT16                           Type,
801dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  IN UINT16                           *Layer,
802dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  IN BOOLEAN                          UseBis,
803dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  IN EFI_PXE_BASE_CODE_DISCOVER_INFO  *Info   OPTIONAL
804dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  )
805dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff{
806dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  PXEBC_PRIVATE_DATA              *Private;
807dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  EFI_PXE_BASE_CODE_MODE          *Mode;
808dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  EFI_PXE_BASE_CODE_DISCOVER_INFO DefaultInfo;
80929a4f92d814896a7c15e5fd0559defa4d7232c53hhuan  EFI_PXE_BASE_CODE_DISCOVER_INFO *CreatedInfo;
810dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  EFI_PXE_BASE_CODE_SRVLIST       *SrvList;
811dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  EFI_PXE_BASE_CODE_SRVLIST       DefaultSrvList;
812dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  PXEBC_CACHED_DHCP4_PACKET       *Packet;
813f737cfb953905f42f3324e8e53ec324a15314210jgong  PXEBC_VENDOR_OPTION             *VendorOpt;
814dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  UINT16                          Index;
815dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  EFI_STATUS                      Status;
816dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  PXEBC_BOOT_SVR_ENTRY            *BootSvrEntry;
8178730386e6d669ded738c6f846aa26bf1c96228bfhhuan  EFI_PXE_BASE_CODE_IP_FILTER     IpFilter;
818dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
819dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  if (This == NULL) {
820dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    return EFI_INVALID_PARAMETER;
821dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  }
822dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
823dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  Private           = PXEBC_PRIVATE_DATA_FROM_PXEBC (This);
824dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  Mode              = Private->PxeBc.Mode;
825dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  BootSvrEntry      = NULL;
826dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  SrvList           = NULL;
82729a4f92d814896a7c15e5fd0559defa4d7232c53hhuan  CreatedInfo       = NULL;
828dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  Status            = EFI_DEVICE_ERROR;
829dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  Private->Function = EFI_PXE_BASE_CODE_FUNCTION_DISCOVER;
830dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
831dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  if (!Private->AddressIsOk) {
832dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    return EFI_INVALID_PARAMETER;
833dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  }
834dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
835dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  if (!Mode->Started) {
836dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    return EFI_NOT_STARTED;
837dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  }
838dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
8398730386e6d669ded738c6f846aa26bf1c96228bfhhuan  //
8408730386e6d669ded738c6f846aa26bf1c96228bfhhuan  // Stop Udp4Read instance
8418730386e6d669ded738c6f846aa26bf1c96228bfhhuan  //
8428730386e6d669ded738c6f846aa26bf1c96228bfhhuan  Private->Udp4Read->Configure (Private->Udp4Read, NULL);
8438730386e6d669ded738c6f846aa26bf1c96228bfhhuan
844982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  Mode->IcmpErrorReceived = FALSE;
845982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff
846dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  //
847dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  // If layer isn't EFI_PXE_BASE_CODE_BOOT_LAYER_INITIAL,
848dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  //   use the previous setting;
849dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  // If info isn't offered,
850dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  //   use the cached DhcpAck and ProxyOffer packets.
851dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  //
852f402291bf98d9e380f00d35033570e851f5318b2sfu  ZeroMem (&DefaultInfo, sizeof (EFI_PXE_BASE_CODE_DISCOVER_INFO));
853dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  if (*Layer != EFI_PXE_BASE_CODE_BOOT_LAYER_INITIAL) {
854dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
855dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    if (!Mode->PxeDiscoverValid || !Mode->PxeReplyReceived || (!Mode->PxeBisReplyReceived && UseBis)) {
856dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
8578730386e6d669ded738c6f846aa26bf1c96228bfhhuan      Status = EFI_INVALID_PARAMETER;
8588730386e6d669ded738c6f846aa26bf1c96228bfhhuan      goto ON_EXIT;
859dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    }
860dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
861dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    DefaultInfo.IpCnt                 = 1;
862dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    DefaultInfo.UseUCast              = TRUE;
863dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
864dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    DefaultSrvList.Type               = Type;
865dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    DefaultSrvList.AcceptAnyResponse  = FALSE;
866dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    DefaultSrvList.IpAddr.Addr[0]     = Private->ServerIp.Addr[0];
867dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
868dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    SrvList = &DefaultSrvList;
869dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    Info = &DefaultInfo;
870dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  } else if (Info == NULL) {
871dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    //
872dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    // Create info by the cached packet before
873dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    //
874dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    Packet    = (Mode->ProxyOfferReceived) ? &Private->ProxyOffer : &Private->Dhcp4Ack;
875dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    VendorOpt = &Packet->PxeVendorOption;
876dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
877dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    if (!Mode->DhcpAckReceived || !IS_VALID_DISCOVER_VENDOR_OPTION (VendorOpt->BitMap)) {
878dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff      //
879dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff      // Address is not acquired or no discovery options.
880dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff      //
8818730386e6d669ded738c6f846aa26bf1c96228bfhhuan      Status = EFI_INVALID_PARAMETER;
8828730386e6d669ded738c6f846aa26bf1c96228bfhhuan      goto ON_EXIT;
883dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    }
884dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
885dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    DefaultInfo.UseMCast    = (BOOLEAN)!IS_DISABLE_MCAST_DISCOVER (VendorOpt->DiscoverCtrl);
886dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    DefaultInfo.UseBCast    = (BOOLEAN)!IS_DISABLE_BCAST_DISCOVER (VendorOpt->DiscoverCtrl);
887dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    DefaultInfo.MustUseList = (BOOLEAN) IS_ENABLE_USE_SERVER_LIST (VendorOpt->DiscoverCtrl);
888dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    DefaultInfo.UseUCast    = DefaultInfo.MustUseList;
889dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
890dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    if (DefaultInfo.UseMCast) {
891dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff      //
892dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff      // Get the multicast discover ip address from vendor option.
893dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff      //
894f737cfb953905f42f3324e8e53ec324a15314210jgong      CopyMem (
895e285199897e538523f762cb5b3900e81f872035avanjeff        &DefaultInfo.ServerMCastIp.Addr,
896e285199897e538523f762cb5b3900e81f872035avanjeff        &VendorOpt->DiscoverMcastIp,
897f737cfb953905f42f3324e8e53ec324a15314210jgong        sizeof (EFI_IPv4_ADDRESS)
898f737cfb953905f42f3324e8e53ec324a15314210jgong        );
899dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    }
900dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
901dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    DefaultInfo.IpCnt = 0;
90229a4f92d814896a7c15e5fd0559defa4d7232c53hhuan    Info    = &DefaultInfo;
90329a4f92d814896a7c15e5fd0559defa4d7232c53hhuan    SrvList = Info->SrvList;
904dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
905dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    if (DefaultInfo.MustUseList) {
906dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff      BootSvrEntry  = VendorOpt->BootSvr;
907dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff      Status        = EFI_INVALID_PARAMETER;
908dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
909dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff      while (((UINT8) (BootSvrEntry - VendorOpt->BootSvr)) < VendorOpt->BootSvrLen) {
910dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
911dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff        if (BootSvrEntry->Type == HTONS (Type)) {
912dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff          Status = EFI_SUCCESS;
913dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff          break;
914dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff        }
915dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
916dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff        BootSvrEntry = GET_NEXT_BOOT_SVR_ENTRY (BootSvrEntry);
917dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff      }
918dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
919dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff      if (EFI_ERROR (Status)) {
9208730386e6d669ded738c6f846aa26bf1c96228bfhhuan        goto ON_EXIT;
921dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff      }
922dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
923dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff      DefaultInfo.IpCnt = BootSvrEntry->IpCnt;
92429a4f92d814896a7c15e5fd0559defa4d7232c53hhuan
92529a4f92d814896a7c15e5fd0559defa4d7232c53hhuan      if (DefaultInfo.IpCnt >= 1) {
92629a4f92d814896a7c15e5fd0559defa4d7232c53hhuan        CreatedInfo = AllocatePool (sizeof (DefaultInfo) + (DefaultInfo.IpCnt - 1) * sizeof (*SrvList));
92729a4f92d814896a7c15e5fd0559defa4d7232c53hhuan        if (CreatedInfo == NULL) {
9288730386e6d669ded738c6f846aa26bf1c96228bfhhuan          Status = EFI_OUT_OF_RESOURCES;
9298730386e6d669ded738c6f846aa26bf1c96228bfhhuan          goto ON_EXIT;
9308730386e6d669ded738c6f846aa26bf1c96228bfhhuan
93129a4f92d814896a7c15e5fd0559defa4d7232c53hhuan        }
93229a4f92d814896a7c15e5fd0559defa4d7232c53hhuan
93329a4f92d814896a7c15e5fd0559defa4d7232c53hhuan        CopyMem (CreatedInfo, &DefaultInfo, sizeof (DefaultInfo));
93429a4f92d814896a7c15e5fd0559defa4d7232c53hhuan        Info    = CreatedInfo;
93529a4f92d814896a7c15e5fd0559defa4d7232c53hhuan        SrvList = Info->SrvList;
93629a4f92d814896a7c15e5fd0559defa4d7232c53hhuan      }
93729a4f92d814896a7c15e5fd0559defa4d7232c53hhuan
93829a4f92d814896a7c15e5fd0559defa4d7232c53hhuan      for (Index = 0; Index < DefaultInfo.IpCnt; Index++) {
93929a4f92d814896a7c15e5fd0559defa4d7232c53hhuan        CopyMem (&SrvList[Index].IpAddr, &BootSvrEntry->IpAddr[Index], sizeof (EFI_IPv4_ADDRESS));
94029a4f92d814896a7c15e5fd0559defa4d7232c53hhuan        SrvList[Index].AcceptAnyResponse   = FALSE;
94129a4f92d814896a7c15e5fd0559defa4d7232c53hhuan        SrvList[Index].Type                = BootSvrEntry->Type;
94229a4f92d814896a7c15e5fd0559defa4d7232c53hhuan      }
943dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    }
944dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
945dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  } else {
946dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
947dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    SrvList = Info->SrvList;
948dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
949dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    if (!SrvList[0].AcceptAnyResponse) {
950dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
951dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff      for (Index = 1; Index < Info->IpCnt; Index++) {
952dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff        if (SrvList[Index].AcceptAnyResponse) {
953dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff          break;
954dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff        }
955dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff      }
956dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
957dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff      if (Index != Info->IpCnt) {
9588730386e6d669ded738c6f846aa26bf1c96228bfhhuan        Status = EFI_INVALID_PARAMETER;
9598730386e6d669ded738c6f846aa26bf1c96228bfhhuan        goto ON_EXIT;
960dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff      }
961dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    }
962dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  }
963dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
964dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  if ((!Info->UseUCast && !Info->UseBCast && !Info->UseMCast) || (Info->MustUseList && Info->IpCnt == 0)) {
965dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
9668730386e6d669ded738c6f846aa26bf1c96228bfhhuan    Status = EFI_INVALID_PARAMETER;
9678730386e6d669ded738c6f846aa26bf1c96228bfhhuan    goto ON_EXIT;
968dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  }
969dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  //
970dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  // Execute discover by UniCast/BroadCast/MultiCast
971dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  //
972dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  if (Info->UseUCast) {
973dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
974dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    for (Index = 0; Index < Info->IpCnt; Index++) {
975dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
976dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff      if (BootSvrEntry == NULL) {
977dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff        Private->ServerIp.Addr[0] = SrvList[Index].IpAddr.Addr[0];
978dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff      } else {
979f737cfb953905f42f3324e8e53ec324a15314210jgong        CopyMem (
980e285199897e538523f762cb5b3900e81f872035avanjeff          &Private->ServerIp,
981e285199897e538523f762cb5b3900e81f872035avanjeff          &BootSvrEntry->IpAddr[Index],
982f737cfb953905f42f3324e8e53ec324a15314210jgong          sizeof (EFI_IPv4_ADDRESS)
983f737cfb953905f42f3324e8e53ec324a15314210jgong          );
984dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff      }
985dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
986dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff      Status = PxeBcDiscvBootService (
987dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff                Private,
988dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff                Type,
989dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff                Layer,
990dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff                UseBis,
991dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff                &SrvList[Index].IpAddr,
992dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff                0,
993dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff                NULL,
994dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff                TRUE,
995dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff                &Private->PxeReply.Packet.Ack
996dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff                );
99729a4f92d814896a7c15e5fd0559defa4d7232c53hhuan      if (!EFI_ERROR (Status)) {
99829a4f92d814896a7c15e5fd0559defa4d7232c53hhuan        break;
99929a4f92d814896a7c15e5fd0559defa4d7232c53hhuan      }
1000dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    }
1001dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
1002dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  } else if (Info->UseMCast) {
1003dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
1004dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    Status = PxeBcDiscvBootService (
1005dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff              Private,
1006dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff              Type,
1007dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff              Layer,
1008dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff              UseBis,
1009dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff              &Info->ServerMCastIp,
1010dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff              0,
1011dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff              NULL,
1012dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff              TRUE,
1013dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff              &Private->PxeReply.Packet.Ack
1014dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff              );
1015dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
1016dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  } else if (Info->UseBCast) {
1017dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
1018dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    Status = PxeBcDiscvBootService (
1019dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff              Private,
1020dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff              Type,
1021dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff              Layer,
1022dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff              UseBis,
1023dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff              NULL,
1024dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff              Info->IpCnt,
1025dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff              SrvList,
1026dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff              TRUE,
1027dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff              &Private->PxeReply.Packet.Ack
1028dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff              );
1029dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  }
1030dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
1031dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  if (EFI_ERROR (Status) || !Mode->PxeReplyReceived || (!Mode->PxeBisReplyReceived && UseBis)) {
1032982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff    if (Status == EFI_ICMP_ERROR) {
1033982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff      Mode->IcmpErrorReceived = TRUE;
1034982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff    } else {
1035982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff      Status = EFI_DEVICE_ERROR;
1036982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff    }
1037357af28525c3a5be6ca0a201f2533dc0a372dbfbsfu    goto ON_EXIT;
1038dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  } else {
1039dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    PxeBcParseCachedDhcpPacket (&Private->PxeReply);
1040dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  }
1041dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
1042dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  if (Mode->PxeBisReplyReceived) {
1043f737cfb953905f42f3324e8e53ec324a15314210jgong    CopyMem (
1044e285199897e538523f762cb5b3900e81f872035avanjeff      &Private->ServerIp,
1045e285199897e538523f762cb5b3900e81f872035avanjeff      &Mode->PxeReply.Dhcpv4.BootpSiAddr,
1046f737cfb953905f42f3324e8e53ec324a15314210jgong      sizeof (EFI_IPv4_ADDRESS)
1047f737cfb953905f42f3324e8e53ec324a15314210jgong      );
1048dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  }
1049dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
105029a4f92d814896a7c15e5fd0559defa4d7232c53hhuan  if (CreatedInfo != NULL) {
105129a4f92d814896a7c15e5fd0559defa4d7232c53hhuan    FreePool (CreatedInfo);
105229a4f92d814896a7c15e5fd0559defa4d7232c53hhuan  }
10538730386e6d669ded738c6f846aa26bf1c96228bfhhuan
10548730386e6d669ded738c6f846aa26bf1c96228bfhhuanON_EXIT:
10558730386e6d669ded738c6f846aa26bf1c96228bfhhuan
1056357af28525c3a5be6ca0a201f2533dc0a372dbfbsfu  Private->Udp4Read->Configure (Private->Udp4Read, &Private->Udp4CfgData);
1057c82291bc3108c948a66d659da0fd76731351f530hhuan
10588730386e6d669ded738c6f846aa26bf1c96228bfhhuan  //
10598730386e6d669ded738c6f846aa26bf1c96228bfhhuan  // Dhcp(), Discover(), and Mtftp() set the IP filter, and return with the IP
10608730386e6d669ded738c6f846aa26bf1c96228bfhhuan  // receive filter list emptied and the filter set to EFI_PXE_BASE_CODE_IP_FILTER_STATION_IP.
10618730386e6d669ded738c6f846aa26bf1c96228bfhhuan  //
10628730386e6d669ded738c6f846aa26bf1c96228bfhhuan  ZeroMem(&IpFilter, sizeof (EFI_PXE_BASE_CODE_IP_FILTER));
10638730386e6d669ded738c6f846aa26bf1c96228bfhhuan  IpFilter.Filters = EFI_PXE_BASE_CODE_IP_FILTER_STATION_IP;
10648730386e6d669ded738c6f846aa26bf1c96228bfhhuan  This->SetIpFilter (This, &IpFilter);
106529a4f92d814896a7c15e5fd0559defa4d7232c53hhuan
1066dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  return Status;
1067dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff}
1068dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
1069dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
1070e285199897e538523f762cb5b3900e81f872035avanjeff/**
1071f737cfb953905f42f3324e8e53ec324a15314210jgong  Used to perform TFTP and MTFTP services.
1072f737cfb953905f42f3324e8e53ec324a15314210jgong
1073f737cfb953905f42f3324e8e53ec324a15314210jgong  This function is used to perform TFTP and MTFTP services. This includes the
1074f737cfb953905f42f3324e8e53ec324a15314210jgong  TFTP operations to get the size of a file, read a directory, read a file, and
1075f737cfb953905f42f3324e8e53ec324a15314210jgong  write a file. It also includes the MTFTP operations to get the size of a file,
1076f737cfb953905f42f3324e8e53ec324a15314210jgong  read a directory, and read a file. The type of operation is specified by Operation.
1077f737cfb953905f42f3324e8e53ec324a15314210jgong  If the callback function that is invoked during the TFTP/MTFTP operation does
1078f737cfb953905f42f3324e8e53ec324a15314210jgong  not return EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE, then EFI_ABORTED will
1079f737cfb953905f42f3324e8e53ec324a15314210jgong  be returned.
1080f737cfb953905f42f3324e8e53ec324a15314210jgong  For read operations, the return data will be placed in the buffer specified by
1081f737cfb953905f42f3324e8e53ec324a15314210jgong  BufferPtr. If BufferSize is too small to contain the entire downloaded file,
1082f737cfb953905f42f3324e8e53ec324a15314210jgong  then EFI_BUFFER_TOO_SMALL will be returned and BufferSize will be set to zero
1083f737cfb953905f42f3324e8e53ec324a15314210jgong  or the size of the requested file (the size of the requested file is only returned
1084f737cfb953905f42f3324e8e53ec324a15314210jgong  if the TFTP server supports TFTP options). If BufferSize is large enough for the
1085f737cfb953905f42f3324e8e53ec324a15314210jgong  read operation, then BufferSize will be set to the size of the downloaded file,
1086f737cfb953905f42f3324e8e53ec324a15314210jgong  and EFI_SUCCESS will be returned. Applications using the PxeBc.Mtftp() services
1087f737cfb953905f42f3324e8e53ec324a15314210jgong  should use the get-file-size operations to determine the size of the downloaded
1088f737cfb953905f42f3324e8e53ec324a15314210jgong  file prior to using the read-file operations-especially when downloading large
1089f737cfb953905f42f3324e8e53ec324a15314210jgong  (greater than 64 MB) files-instead of making two calls to the read-file operation.
1090f737cfb953905f42f3324e8e53ec324a15314210jgong  Following this recommendation will save time if the file is larger than expected
1091f737cfb953905f42f3324e8e53ec324a15314210jgong  and the TFTP server does not support TFTP option extensions. Without TFTP option
1092f737cfb953905f42f3324e8e53ec324a15314210jgong  extension support, the client has to download the entire file, counting and discarding
1093f737cfb953905f42f3324e8e53ec324a15314210jgong  the received packets, to determine the file size.
1094f737cfb953905f42f3324e8e53ec324a15314210jgong  For write operations, the data to be sent is in the buffer specified by BufferPtr.
1095f737cfb953905f42f3324e8e53ec324a15314210jgong  BufferSize specifies the number of bytes to send. If the write operation completes
1096f737cfb953905f42f3324e8e53ec324a15314210jgong  successfully, then EFI_SUCCESS will be returned.
1097f737cfb953905f42f3324e8e53ec324a15314210jgong  For TFTP "get file size" operations, the size of the requested file or directory
1098f737cfb953905f42f3324e8e53ec324a15314210jgong  is returned in BufferSize, and EFI_SUCCESS will be returned. If the TFTP server
1099f737cfb953905f42f3324e8e53ec324a15314210jgong  does not support options, the file will be downloaded into a bit bucket and the
1100f737cfb953905f42f3324e8e53ec324a15314210jgong  length of the downloaded file will be returned. For MTFTP "get file size" operations,
1101f737cfb953905f42f3324e8e53ec324a15314210jgong  if the MTFTP server does not support the "get file size" option, EFI_UNSUPPORTED
1102f737cfb953905f42f3324e8e53ec324a15314210jgong  will be returned.
1103f737cfb953905f42f3324e8e53ec324a15314210jgong  This function can take up to 10 seconds to timeout and return control to the caller.
1104f737cfb953905f42f3324e8e53ec324a15314210jgong  If the TFTP sequence does not complete, EFI_TIMEOUT will be returned.
1105f737cfb953905f42f3324e8e53ec324a15314210jgong  If the Callback Protocol does not return EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE,
1106f737cfb953905f42f3324e8e53ec324a15314210jgong  then the TFTP sequence is stopped and EFI_ABORTED will be returned.
1107f737cfb953905f42f3324e8e53ec324a15314210jgong  The format of the data returned from a TFTP read directory operation is a null-terminated
1108f737cfb953905f42f3324e8e53ec324a15314210jgong  filename followed by a null-terminated information string, of the form
1109f737cfb953905f42f3324e8e53ec324a15314210jgong  "size year-month-day hour:minute:second" (i.e. %d %d-%d-%d %d:%d:%f - note that
1110f737cfb953905f42f3324e8e53ec324a15314210jgong  the seconds field can be a decimal number), where the date and time are UTC. For
1111f737cfb953905f42f3324e8e53ec324a15314210jgong  an MTFTP read directory command, there is additionally a null-terminated multicast
1112f737cfb953905f42f3324e8e53ec324a15314210jgong  IP address preceding the filename of the form %d.%d.%d.%d for IP v4. The final
1113f737cfb953905f42f3324e8e53ec324a15314210jgong  entry is itself null-terminated, so that the final information string is terminated
1114f737cfb953905f42f3324e8e53ec324a15314210jgong  with two null octets.
1115e285199897e538523f762cb5b3900e81f872035avanjeff
1116f737cfb953905f42f3324e8e53ec324a15314210jgong  @param  This                  Pointer to the EFI_PXE_BASE_CODE_PROTOCOL instance.
1117f737cfb953905f42f3324e8e53ec324a15314210jgong  @param  Operation             The type of operation to perform.
1118e285199897e538523f762cb5b3900e81f872035avanjeff  @param  BufferPtr             A pointer to the data buffer.
1119f737cfb953905f42f3324e8e53ec324a15314210jgong  @param  Overwrite             Only used on write file operations. TRUE if a file on a remote server can
1120e285199897e538523f762cb5b3900e81f872035avanjeff                                be overwritten.
1121f737cfb953905f42f3324e8e53ec324a15314210jgong  @param  BufferSize            For get-file-size operations, *BufferSize returns the size of the
1122e285199897e538523f762cb5b3900e81f872035avanjeff                                requested file.
1123f737cfb953905f42f3324e8e53ec324a15314210jgong  @param  BlockSize             The requested block size to be used during a TFTP transfer.
1124f737cfb953905f42f3324e8e53ec324a15314210jgong  @param  ServerIp              The TFTP / MTFTP server IP address.
1125f737cfb953905f42f3324e8e53ec324a15314210jgong  @param  Filename              A Null-terminated ASCII string that specifies a directory name or a file
1126e285199897e538523f762cb5b3900e81f872035avanjeff                                name.
1127f737cfb953905f42f3324e8e53ec324a15314210jgong  @param  Info                  Pointer to the MTFTP information.
1128e285199897e538523f762cb5b3900e81f872035avanjeff  @param  DontUseBuffer         Set to FALSE for normal TFTP and MTFTP read file operation.
1129e285199897e538523f762cb5b3900e81f872035avanjeff
1130f737cfb953905f42f3324e8e53ec324a15314210jgong  @retval EFI_SUCCESS           The TFTP/MTFTP operation was completed.
1131f737cfb953905f42f3324e8e53ec324a15314210jgong  @retval EFI_NOT_STARTED       The PXE Base Code Protocol is in the stopped state.
1132e285199897e538523f762cb5b3900e81f872035avanjeff  @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
1133e285199897e538523f762cb5b3900e81f872035avanjeff  @retval EFI_DEVICE_ERROR      The network device encountered an error during this operation.
1134e285199897e538523f762cb5b3900e81f872035avanjeff  @retval EFI_BUFFER_TOO_SMALL  The buffer is not large enough to complete the read operation.
1135f737cfb953905f42f3324e8e53ec324a15314210jgong  @retval EFI_ABORTED           The callback function aborted the TFTP/MTFTP operation.
1136f737cfb953905f42f3324e8e53ec324a15314210jgong  @retval EFI_TIMEOUT           The TFTP/MTFTP operation timed out.
1137f737cfb953905f42f3324e8e53ec324a15314210jgong  @retval EFI_ICMP_ERROR        An ICMP error packet was received during the MTFTP session.
1138f737cfb953905f42f3324e8e53ec324a15314210jgong  @retval EFI_TFTP_ERROR        A TFTP error packet was received during the MTFTP session.
1139e285199897e538523f762cb5b3900e81f872035avanjeff
1140dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff**/
1141dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeffEFI_STATUS
1142dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeffEFIAPI
1143dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeffEfiPxeBcMtftp (
1144dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  IN EFI_PXE_BASE_CODE_PROTOCOL       *This,
1145dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  IN EFI_PXE_BASE_CODE_TFTP_OPCODE    Operation,
1146dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  IN OUT VOID                         *BufferPtr,
1147dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  IN BOOLEAN                          Overwrite,
1148dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  IN OUT UINT64                       *BufferSize,
1149dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  IN UINTN                            *BlockSize    OPTIONAL,
1150dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  IN EFI_IP_ADDRESS                   *ServerIp,
1151dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  IN UINT8                            *Filename,
1152dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  IN EFI_PXE_BASE_CODE_MTFTP_INFO     *Info         OPTIONAL,
1153dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  IN BOOLEAN                          DontUseBuffer
1154dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  )
1155dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff{
11568730386e6d669ded738c6f846aa26bf1c96228bfhhuan  PXEBC_PRIVATE_DATA           *Private;
11578730386e6d669ded738c6f846aa26bf1c96228bfhhuan  EFI_MTFTP4_CONFIG_DATA       Mtftp4Config;
11588730386e6d669ded738c6f846aa26bf1c96228bfhhuan  EFI_STATUS                   Status;
11598730386e6d669ded738c6f846aa26bf1c96228bfhhuan  EFI_PXE_BASE_CODE_MODE       *Mode;
11608730386e6d669ded738c6f846aa26bf1c96228bfhhuan  EFI_MAC_ADDRESS              TempMacAddr;
11618730386e6d669ded738c6f846aa26bf1c96228bfhhuan  EFI_PXE_BASE_CODE_IP_FILTER  IpFilter;
1162dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
1163f6b7393ceb34c9b3a27434268bf2ce517047641ftye  if ((This == NULL)                                                          ||
1164f6b7393ceb34c9b3a27434268bf2ce517047641ftye      (Filename == NULL)                                                      ||
1165f6b7393ceb34c9b3a27434268bf2ce517047641ftye      (BufferSize == NULL)                                                    ||
1166f6b7393ceb34c9b3a27434268bf2ce517047641ftye      ((ServerIp == NULL) || !NetIp4IsUnicast (NTOHL (ServerIp->Addr[0]), 0)) ||
1167f6b7393ceb34c9b3a27434268bf2ce517047641ftye      ((BufferPtr == NULL) && DontUseBuffer)                                  ||
1168dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff      ((BlockSize != NULL) && (*BlockSize < 512))) {
1169dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
1170dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    return EFI_INVALID_PARAMETER;
1171dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  }
1172dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
1173dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  Status  = EFI_DEVICE_ERROR;
1174dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  Private = PXEBC_PRIVATE_DATA_FROM_PXEBC (This);
1175982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  Mode    = &Private->Mode;
1176982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff
1177982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  if (!Mode->AutoArp) {
1178982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff    //
1179982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff    // If AutoArp is set false, check arp cache
1180982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff    //
1181982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff    UpdateArpCache (This);
1182982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff    if (!FindInArpCache (Mode, &ServerIp->v4, &TempMacAddr)) {
1183982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff      return EFI_DEVICE_ERROR;
1184982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff    }
1185982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  }
1186982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff
11878730386e6d669ded738c6f846aa26bf1c96228bfhhuan  //
11888730386e6d669ded738c6f846aa26bf1c96228bfhhuan  // Stop Udp4Read instance
11898730386e6d669ded738c6f846aa26bf1c96228bfhhuan  //
11908730386e6d669ded738c6f846aa26bf1c96228bfhhuan  Private->Udp4Read->Configure (Private->Udp4Read, NULL);
11918730386e6d669ded738c6f846aa26bf1c96228bfhhuan
1192982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  Mode->TftpErrorReceived = FALSE;
1193982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  Mode->IcmpErrorReceived = FALSE;
1194dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
1195dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  Mtftp4Config.UseDefaultSetting = FALSE;
1196dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  Mtftp4Config.TimeoutValue      = PXEBC_MTFTP_TIMEOUT;
1197dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  Mtftp4Config.TryCount          = PXEBC_MTFTP_RETRIES;
1198dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
1199f737cfb953905f42f3324e8e53ec324a15314210jgong  CopyMem (
1200e285199897e538523f762cb5b3900e81f872035avanjeff    &Mtftp4Config.StationIp,
1201e285199897e538523f762cb5b3900e81f872035avanjeff    &Private->StationIp,
1202f737cfb953905f42f3324e8e53ec324a15314210jgong    sizeof (EFI_IPv4_ADDRESS)
1203f737cfb953905f42f3324e8e53ec324a15314210jgong    );
1204f737cfb953905f42f3324e8e53ec324a15314210jgong  CopyMem (
1205e285199897e538523f762cb5b3900e81f872035avanjeff    &Mtftp4Config.SubnetMask,
1206e285199897e538523f762cb5b3900e81f872035avanjeff    &Private->SubnetMask,
1207f737cfb953905f42f3324e8e53ec324a15314210jgong    sizeof (EFI_IPv4_ADDRESS)
1208f737cfb953905f42f3324e8e53ec324a15314210jgong    );
1209f737cfb953905f42f3324e8e53ec324a15314210jgong  CopyMem (
1210e285199897e538523f762cb5b3900e81f872035avanjeff    &Mtftp4Config.GatewayIp,
1211e285199897e538523f762cb5b3900e81f872035avanjeff    &Private->GatewayIp,
1212f737cfb953905f42f3324e8e53ec324a15314210jgong    sizeof (EFI_IPv4_ADDRESS)
1213f737cfb953905f42f3324e8e53ec324a15314210jgong    );
1214f737cfb953905f42f3324e8e53ec324a15314210jgong  CopyMem (
1215e285199897e538523f762cb5b3900e81f872035avanjeff    &Mtftp4Config.ServerIp,
1216e285199897e538523f762cb5b3900e81f872035avanjeff    ServerIp,
1217f737cfb953905f42f3324e8e53ec324a15314210jgong    sizeof (EFI_IPv4_ADDRESS)
1218f737cfb953905f42f3324e8e53ec324a15314210jgong    );
1219dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
1220dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  switch (Operation) {
1221dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
1222dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  case EFI_PXE_BASE_CODE_TFTP_GET_FILE_SIZE:
1223dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
1224dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    Status = PxeBcTftpGetFileSize (
1225dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff              Private,
1226dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff              &Mtftp4Config,
1227dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff              Filename,
1228dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff              BlockSize,
1229dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff              BufferSize
1230dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff              );
1231dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
1232dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    break;
1233dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
1234dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  case EFI_PXE_BASE_CODE_TFTP_READ_FILE:
1235dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
1236dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    Status = PxeBcTftpReadFile (
1237dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff              Private,
1238dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff              &Mtftp4Config,
1239dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff              Filename,
1240dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff              BlockSize,
1241dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff              BufferPtr,
1242dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff              BufferSize,
1243dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff              DontUseBuffer
1244dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff              );
1245dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
1246dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    break;
1247dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
1248dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  case EFI_PXE_BASE_CODE_TFTP_WRITE_FILE:
1249dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
1250dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    Status = PxeBcTftpWriteFile (
1251dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff              Private,
1252dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff              &Mtftp4Config,
1253dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff              Filename,
1254dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff              Overwrite,
1255dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff              BlockSize,
1256dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff              BufferPtr,
1257dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff              BufferSize
1258dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff              );
1259dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
1260dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    break;
1261dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
1262dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  case EFI_PXE_BASE_CODE_TFTP_READ_DIRECTORY:
1263dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
1264dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    Status = PxeBcTftpReadDirectory (
1265dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff              Private,
1266dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff              &Mtftp4Config,
1267dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff              Filename,
1268dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff              BlockSize,
1269dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff              BufferPtr,
1270dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff              BufferSize,
1271dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff              DontUseBuffer
1272dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff              );
1273dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
1274dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    break;
1275dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
1276dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  case EFI_PXE_BASE_CODE_MTFTP_GET_FILE_SIZE:
1277dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  case EFI_PXE_BASE_CODE_MTFTP_READ_FILE:
1278dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  case EFI_PXE_BASE_CODE_MTFTP_READ_DIRECTORY:
1279dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    Status = EFI_UNSUPPORTED;
1280dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    break;
1281dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
1282dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  default:
1283dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
1284dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    Status = EFI_INVALID_PARAMETER;
1285dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    break;
1286dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  }
1287dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
1288982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  if (Status == EFI_ICMP_ERROR) {
1289982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff    Mode->IcmpErrorReceived = TRUE;
1290982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  }
1291982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff
12920bc17488fe1e70a9fce92503739bc60e7471ad29sfu  if (EFI_ERROR (Status)) {
1293357af28525c3a5be6ca0a201f2533dc0a372dbfbsfu    goto ON_EXIT;
12940bc17488fe1e70a9fce92503739bc60e7471ad29sfu  }
12950bc17488fe1e70a9fce92503739bc60e7471ad29sfu
1296357af28525c3a5be6ca0a201f2533dc0a372dbfbsfuON_EXIT:
1297357af28525c3a5be6ca0a201f2533dc0a372dbfbsfu  Private->Udp4Read->Configure (Private->Udp4Read, &Private->Udp4CfgData);
12988730386e6d669ded738c6f846aa26bf1c96228bfhhuan  //
12998730386e6d669ded738c6f846aa26bf1c96228bfhhuan  // Dhcp(), Discover(), and Mtftp() set the IP filter, and return with the IP
13008730386e6d669ded738c6f846aa26bf1c96228bfhhuan  // receive filter list emptied and the filter set to EFI_PXE_BASE_CODE_IP_FILTER_STATION_IP.
13018730386e6d669ded738c6f846aa26bf1c96228bfhhuan  //
13028730386e6d669ded738c6f846aa26bf1c96228bfhhuan  ZeroMem(&IpFilter, sizeof (EFI_PXE_BASE_CODE_IP_FILTER));
13038730386e6d669ded738c6f846aa26bf1c96228bfhhuan  IpFilter.Filters = EFI_PXE_BASE_CODE_IP_FILTER_STATION_IP;
13048730386e6d669ded738c6f846aa26bf1c96228bfhhuan  This->SetIpFilter (This, &IpFilter);
13058730386e6d669ded738c6f846aa26bf1c96228bfhhuan
1306dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  return Status;
1307dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff}
1308dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
1309dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
1310e285199897e538523f762cb5b3900e81f872035avanjeff/**
1311f737cfb953905f42f3324e8e53ec324a15314210jgong  Writes a UDP packet to the network interface.
1312f737cfb953905f42f3324e8e53ec324a15314210jgong
1313f737cfb953905f42f3324e8e53ec324a15314210jgong  This function writes a UDP packet specified by the (optional HeaderPtr and)
1314f737cfb953905f42f3324e8e53ec324a15314210jgong  BufferPtr parameters to the network interface. The UDP header is automatically
1315f737cfb953905f42f3324e8e53ec324a15314210jgong  built by this routine. It uses the parameters OpFlags, DestIp, DestPort, GatewayIp,
1316f737cfb953905f42f3324e8e53ec324a15314210jgong  SrcIp, and SrcPort to build this header. If the packet is successfully built and
1317f737cfb953905f42f3324e8e53ec324a15314210jgong  transmitted through the network interface, then EFI_SUCCESS will be returned.
1318f737cfb953905f42f3324e8e53ec324a15314210jgong  If a timeout occurs during the transmission of the packet, then EFI_TIMEOUT will
1319f737cfb953905f42f3324e8e53ec324a15314210jgong  be returned. If an ICMP error occurs during the transmission of the packet, then
1320f737cfb953905f42f3324e8e53ec324a15314210jgong  the IcmpErrorReceived field is set to TRUE, the IcmpError field is filled in and
1321f737cfb953905f42f3324e8e53ec324a15314210jgong  EFI_ICMP_ERROR will be returned. If the Callback Protocol does not return
1322f737cfb953905f42f3324e8e53ec324a15314210jgong  EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE, then EFI_ABORTED will be returned.
1323e285199897e538523f762cb5b3900e81f872035avanjeff
1324f737cfb953905f42f3324e8e53ec324a15314210jgong  @param  This                  Pointer to the EFI_PXE_BASE_CODE_PROTOCOL instance.
1325e285199897e538523f762cb5b3900e81f872035avanjeff  @param  OpFlags               The UDP operation flags.
1326f737cfb953905f42f3324e8e53ec324a15314210jgong  @param  DestIp                The destination IP address.
1327e285199897e538523f762cb5b3900e81f872035avanjeff  @param  DestPort              The destination UDP port number.
1328e285199897e538523f762cb5b3900e81f872035avanjeff  @param  GatewayIp             The gateway IP address.
1329f737cfb953905f42f3324e8e53ec324a15314210jgong  @param  SrcIp                 The source IP address.
1330f737cfb953905f42f3324e8e53ec324a15314210jgong  @param  SrcPort               The source UDP port number.
1331f737cfb953905f42f3324e8e53ec324a15314210jgong  @param  HeaderSize            An optional field which may be set to the length of a header at
1332e285199897e538523f762cb5b3900e81f872035avanjeff                                HeaderPtr to be prefixed to the data at BufferPtr.
1333f737cfb953905f42f3324e8e53ec324a15314210jgong  @param  HeaderPtr             If HeaderSize is not NULL, a pointer to a header to be prefixed to the
1334e285199897e538523f762cb5b3900e81f872035avanjeff                                data at BufferPtr.
1335f737cfb953905f42f3324e8e53ec324a15314210jgong  @param  BufferSize            A pointer to the size of the data at BufferPtr.
1336f737cfb953905f42f3324e8e53ec324a15314210jgong  @param  BufferPtr             A pointer to the data to be written.
1337e285199897e538523f762cb5b3900e81f872035avanjeff
1338f737cfb953905f42f3324e8e53ec324a15314210jgong  @retval EFI_SUCCESS           The UDP Write operation was completed.
1339f737cfb953905f42f3324e8e53ec324a15314210jgong  @retval EFI_NOT_STARTED       The PXE Base Code Protocol is in the stopped state.
1340e285199897e538523f762cb5b3900e81f872035avanjeff  @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
1341e285199897e538523f762cb5b3900e81f872035avanjeff  @retval EFI_BAD_BUFFER_SIZE   The buffer is too long to be transmitted.
1342f737cfb953905f42f3324e8e53ec324a15314210jgong  @retval EFI_ABORTED           The callback function aborted the UDP Write operation.
1343f737cfb953905f42f3324e8e53ec324a15314210jgong  @retval EFI_TIMEOUT           The UDP Write operation timed out.
1344e285199897e538523f762cb5b3900e81f872035avanjeff  @retval EFI_ICMP_ERROR        An ICMP error packet was received during the UDP write session.
1345e285199897e538523f762cb5b3900e81f872035avanjeff
1346dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff**/
1347dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeffEFI_STATUS
1348dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeffEFIAPI
1349dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeffEfiPxeBcUdpWrite (
1350dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  IN EFI_PXE_BASE_CODE_PROTOCOL       *This,
1351dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  IN UINT16                           OpFlags,
1352dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  IN EFI_IP_ADDRESS                   *DestIp,
1353dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  IN EFI_PXE_BASE_CODE_UDP_PORT       *DestPort,
1354dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  IN EFI_IP_ADDRESS                   *GatewayIp  OPTIONAL,
1355dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  IN EFI_IP_ADDRESS                   *SrcIp      OPTIONAL,
1356dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  IN OUT EFI_PXE_BASE_CODE_UDP_PORT   *SrcPort    OPTIONAL,
1357dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  IN UINTN                            *HeaderSize OPTIONAL,
1358dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  IN VOID                             *HeaderPtr  OPTIONAL,
1359dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  IN UINTN                            *BufferSize,
1360dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  IN VOID                             *BufferPtr
1361dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  )
1362dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff{
1363dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  PXEBC_PRIVATE_DATA        *Private;
1364dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  EFI_UDP4_PROTOCOL         *Udp4;
1365dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  EFI_UDP4_COMPLETION_TOKEN Token;
1366dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  EFI_UDP4_TRANSMIT_DATA    *Udp4TxData;
1367dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  UINT32                    FragCount;
1368dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  UINT32                    DataLength;
1369dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  EFI_UDP4_SESSION_DATA     Udp4Session;
1370dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  EFI_STATUS                Status;
1371dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  BOOLEAN                   IsDone;
1372982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  EFI_PXE_BASE_CODE_MODE    *Mode;
1373982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  EFI_MAC_ADDRESS           TempMacAddr;
1374dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
1375dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  IsDone = FALSE;
1376dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
1377dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  if ((This == NULL) || (DestIp == NULL) || (DestPort == NULL)) {
1378dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    return EFI_INVALID_PARAMETER;
1379dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  }
1380dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
1381f6b7393ceb34c9b3a27434268bf2ce517047641ftye  if ((GatewayIp != NULL) && !NetIp4IsUnicast (NTOHL (GatewayIp->Addr[0]), 0)) {
1382dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    //
1383dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    // Gateway is provided but it's not a unicast IP address.
1384dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    //
1385dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    return EFI_INVALID_PARAMETER;
1386dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  }
1387dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
1388dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  if ((HeaderSize != NULL) && ((*HeaderSize == 0) || (HeaderPtr == NULL))) {
1389dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    //
1390dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    // The HeaderSize ptr isn't NULL and: 1. the value is zero; or 2. the HeaderPtr
1391dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    // is NULL.
1392dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    //
1393dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    return EFI_INVALID_PARAMETER;
1394dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  }
1395dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
1396dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  if ((BufferSize == NULL) || ((*BufferSize != 0) && (BufferPtr == NULL))) {
1397dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    return EFI_INVALID_PARAMETER;
1398dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  }
1399dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
1400dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  Private = PXEBC_PRIVATE_DATA_FROM_PXEBC (This);
14018792362f22e4fac66aeec04b13b7a6b70cb571e9vanjeff  Udp4    = Private->Udp4Write;
1402982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  Mode    = &Private->Mode;
14038792362f22e4fac66aeec04b13b7a6b70cb571e9vanjeff  if (!Mode->Started) {
14048792362f22e4fac66aeec04b13b7a6b70cb571e9vanjeff    return EFI_NOT_STARTED;
14058792362f22e4fac66aeec04b13b7a6b70cb571e9vanjeff  }
1406dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
1407dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  if (!Private->AddressIsOk && (SrcIp == NULL)) {
1408dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    return EFI_INVALID_PARAMETER;
1409dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  }
1410dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
1411982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  if (!Mode->AutoArp) {
1412982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff    //
1413982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff    // If AutoArp is set false, check arp cache
1414982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff    //
1415982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff    UpdateArpCache (This);
1416982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff    if (!FindInArpCache (Mode, &DestIp->v4, &TempMacAddr)) {
1417982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff      return EFI_DEVICE_ERROR;
1418982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff    }
1419982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  }
1420982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff
1421982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  Mode->IcmpErrorReceived = FALSE;
1422982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff
14238792362f22e4fac66aeec04b13b7a6b70cb571e9vanjeff  if ((Private->CurrentUdpSrcPort == 0) ||
1424f737cfb953905f42f3324e8e53ec324a15314210jgong      ((SrcPort != NULL) && (*SrcPort != Private->CurrentUdpSrcPort))) {
14258792362f22e4fac66aeec04b13b7a6b70cb571e9vanjeff    //
14268792362f22e4fac66aeec04b13b7a6b70cb571e9vanjeff    // Port is changed, (re)configure the Udp4Write instance
14278792362f22e4fac66aeec04b13b7a6b70cb571e9vanjeff    //
14288792362f22e4fac66aeec04b13b7a6b70cb571e9vanjeff    if (SrcPort != NULL) {
14298792362f22e4fac66aeec04b13b7a6b70cb571e9vanjeff      Private->CurrentUdpSrcPort = *SrcPort;
1430dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    }
1431dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  }
1432dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
14332e4c2a049be0cfebb2caa79884f22e80ee96eca7hhuan  Status = PxeBcConfigureUdpWriteInstance (
14342e4c2a049be0cfebb2caa79884f22e80ee96eca7hhuan             Udp4,
14352e4c2a049be0cfebb2caa79884f22e80ee96eca7hhuan             &Private->StationIp.v4,
14362e4c2a049be0cfebb2caa79884f22e80ee96eca7hhuan             &Private->SubnetMask.v4,
14372e4c2a049be0cfebb2caa79884f22e80ee96eca7hhuan             &Private->GatewayIp.v4,
14382e4c2a049be0cfebb2caa79884f22e80ee96eca7hhuan             &Private->CurrentUdpSrcPort
14392e4c2a049be0cfebb2caa79884f22e80ee96eca7hhuan             );
14402e4c2a049be0cfebb2caa79884f22e80ee96eca7hhuan  if (EFI_ERROR (Status)) {
14412e4c2a049be0cfebb2caa79884f22e80ee96eca7hhuan    Private->CurrentUdpSrcPort = 0;
14422e4c2a049be0cfebb2caa79884f22e80ee96eca7hhuan    return EFI_INVALID_PARAMETER;
14432e4c2a049be0cfebb2caa79884f22e80ee96eca7hhuan  }
14442e4c2a049be0cfebb2caa79884f22e80ee96eca7hhuan
1445dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  ZeroMem (&Token, sizeof (EFI_UDP4_COMPLETION_TOKEN));
1446dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  ZeroMem (&Udp4Session, sizeof (EFI_UDP4_SESSION_DATA));
1447dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
1448e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff  CopyMem (&Udp4Session.DestinationAddress, DestIp, sizeof (EFI_IPv4_ADDRESS));
1449dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  Udp4Session.DestinationPort = *DestPort;
14508792362f22e4fac66aeec04b13b7a6b70cb571e9vanjeff  if (SrcIp != NULL) {
14518792362f22e4fac66aeec04b13b7a6b70cb571e9vanjeff    CopyMem (&Udp4Session.SourceAddress, SrcIp, sizeof (EFI_IPv4_ADDRESS));
14528792362f22e4fac66aeec04b13b7a6b70cb571e9vanjeff  }
14538792362f22e4fac66aeec04b13b7a6b70cb571e9vanjeff  if (SrcPort != NULL) {
14548792362f22e4fac66aeec04b13b7a6b70cb571e9vanjeff    Udp4Session.SourcePort = *SrcPort;
14558792362f22e4fac66aeec04b13b7a6b70cb571e9vanjeff  }
1456dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
1457dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  FragCount = (HeaderSize != NULL) ? 2 : 1;
145805c0e3cb8ad921c94ef51fc972e117baa32ce82fvanjeff  Udp4TxData = (EFI_UDP4_TRANSMIT_DATA *) AllocateZeroPool (sizeof (EFI_UDP4_TRANSMIT_DATA) + (FragCount - 1) * sizeof (EFI_UDP4_FRAGMENT_DATA));
1459dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  if (Udp4TxData == NULL) {
1460dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    return EFI_OUT_OF_RESOURCES;
1461dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  }
1462dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
1463dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  Udp4TxData->FragmentCount = FragCount;
1464dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  Udp4TxData->FragmentTable[FragCount - 1].FragmentLength = (UINT32) *BufferSize;
1465dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  Udp4TxData->FragmentTable[FragCount - 1].FragmentBuffer = BufferPtr;
1466dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  DataLength = (UINT32) *BufferSize;
1467dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
1468dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  if (FragCount == 2) {
1469dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
1470dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    Udp4TxData->FragmentTable[0].FragmentLength = (UINT32) *HeaderSize;
1471dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    Udp4TxData->FragmentTable[0].FragmentBuffer = HeaderPtr;
1472dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    DataLength += (UINT32) *HeaderSize;
1473dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  }
1474dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
14758792362f22e4fac66aeec04b13b7a6b70cb571e9vanjeff  if (GatewayIp != NULL) {
14768792362f22e4fac66aeec04b13b7a6b70cb571e9vanjeff    Udp4TxData->GatewayAddress  = (EFI_IPv4_ADDRESS *) GatewayIp;
14778792362f22e4fac66aeec04b13b7a6b70cb571e9vanjeff  }
1478dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  Udp4TxData->UdpSessionData  = &Udp4Session;
1479dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  Udp4TxData->DataLength      = DataLength;
1480dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  Token.Packet.TxData         = Udp4TxData;
1481dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
1482dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  Status = gBS->CreateEvent (
1483dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff                  EVT_NOTIFY_SIGNAL,
1484e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff                  TPL_NOTIFY,
1485dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff                  PxeBcCommonNotify,
1486dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff                  &IsDone,
1487dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff                  &Token.Event
1488dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff                  );
1489dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  if (EFI_ERROR (Status)) {
1490dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    goto ON_EXIT;
1491dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  }
1492dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
1493dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  Status = Udp4->Transmit (Udp4, &Token);
1494dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  if (EFI_ERROR (Status)) {
1495982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff    if (Status == EFI_ICMP_ERROR) {
1496982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff      Mode->IcmpErrorReceived = TRUE;
1497982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff    }
1498dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    goto ON_EXIT;
1499dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  }
1500dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
1501dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  while (!IsDone) {
1502dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
1503dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    Udp4->Poll (Udp4);
1504dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  }
1505dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
1506dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  Status = Token.Status;
1507dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
1508dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeffON_EXIT:
1509dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
1510dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  if (Token.Event != NULL) {
1511dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    gBS->CloseEvent (Token.Event);
1512dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  }
1513dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
1514766c7483c335931b190a78d78d62e5a5e69dc8b9xdu  FreePool (Udp4TxData);
1515dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
15162e4c2a049be0cfebb2caa79884f22e80ee96eca7hhuan  //
15172e4c2a049be0cfebb2caa79884f22e80ee96eca7hhuan  // Reset the instance.
15182e4c2a049be0cfebb2caa79884f22e80ee96eca7hhuan  //
15192e4c2a049be0cfebb2caa79884f22e80ee96eca7hhuan  Udp4->Configure (Udp4, NULL);
1520dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  return Status;
1521dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff}
1522dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
15238d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff/**
1524f737cfb953905f42f3324e8e53ec324a15314210jgong  Decide whether the incoming UDP packet is acceptable per IP filter settings
1525f737cfb953905f42f3324e8e53ec324a15314210jgong  in provided PxeBcMode.
15268d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff
1527f737cfb953905f42f3324e8e53ec324a15314210jgong  @param  PxeBcMode          Pointer to EFI_PXE_BASE_CODE_MODE.
1528f737cfb953905f42f3324e8e53ec324a15314210jgong  @param  Session            Received UDP session.
15298d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff
1530f737cfb953905f42f3324e8e53ec324a15314210jgong  @retval TRUE               The UDP package matches IP filters.
1531f737cfb953905f42f3324e8e53ec324a15314210jgong  @retval FALSE              The UDP package doesn't matches IP filters.
15328d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff
15338d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff**/
15348d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeffBOOLEAN
15358d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeffCheckIpByFilter (
1536f737cfb953905f42f3324e8e53ec324a15314210jgong  IN EFI_PXE_BASE_CODE_MODE    *PxeBcMode,
1537f737cfb953905f42f3324e8e53ec324a15314210jgong  IN EFI_UDP4_SESSION_DATA     *Session
15388d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff  )
15398d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff{
15408d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff  UINTN                   Index;
15418d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff  EFI_IPv4_ADDRESS        Ip4Address;
15428d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff  EFI_IPv4_ADDRESS        DestIp4Address;
15438d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff
1544f737cfb953905f42f3324e8e53ec324a15314210jgong  if ((PxeBcMode->IpFilter.Filters & EFI_PXE_BASE_CODE_IP_FILTER_PROMISCUOUS) != 0) {
15458d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff    return TRUE;
15468d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff  }
15478d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff
15488d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff  CopyMem (&DestIp4Address, &Session->DestinationAddress, sizeof (DestIp4Address));
1549e285199897e538523f762cb5b3900e81f872035avanjeff  if (((PxeBcMode->IpFilter.Filters & EFI_PXE_BASE_CODE_IP_FILTER_PROMISCUOUS_MULTICAST) != 0) &&
1550982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff      IP4_IS_MULTICAST (EFI_NTOHL (DestIp4Address))
15518d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff      ) {
15528d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff    return TRUE;
15538d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff  }
15548d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff
1555e285199897e538523f762cb5b3900e81f872035avanjeff  if (((PxeBcMode->IpFilter.Filters & EFI_PXE_BASE_CODE_IP_FILTER_BROADCAST) != 0) &&
15568d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff      IP4_IS_LOCAL_BROADCAST (EFI_NTOHL (DestIp4Address))
15578d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff      ) {
15588d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff    return TRUE;
15598d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff  }
15608d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff
15618d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff  CopyMem (&Ip4Address, &PxeBcMode->StationIp.v4, sizeof (Ip4Address));
1562e285199897e538523f762cb5b3900e81f872035avanjeff  if (((PxeBcMode->IpFilter.Filters & EFI_PXE_BASE_CODE_IP_FILTER_STATION_IP) != 0) &&
1563982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff      EFI_IP4_EQUAL (&Ip4Address, &DestIp4Address)
15648d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff      ) {
15658d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff    return TRUE;
15668d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff  }
15678d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff
1568894d038a8d0e99d456042e2b6d1554c4a406ea70vanjeff  ASSERT (PxeBcMode->IpFilter.IpCnt < EFI_PXE_BASE_CODE_MAX_IPCNT);
1569894d038a8d0e99d456042e2b6d1554c4a406ea70vanjeff
1570f737cfb953905f42f3324e8e53ec324a15314210jgong  for (Index = 0; Index < PxeBcMode->IpFilter.IpCnt; Index++) {
1571f737cfb953905f42f3324e8e53ec324a15314210jgong    CopyMem (
1572e285199897e538523f762cb5b3900e81f872035avanjeff      &Ip4Address,
1573e285199897e538523f762cb5b3900e81f872035avanjeff      &PxeBcMode->IpFilter.IpList[Index].v4,
1574f737cfb953905f42f3324e8e53ec324a15314210jgong      sizeof (Ip4Address)
1575f737cfb953905f42f3324e8e53ec324a15314210jgong      );
15768d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff    if (EFI_IP4_EQUAL (&Ip4Address, &DestIp4Address)) {
15778d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff      return TRUE;
15788d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff    }
15798d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff  }
15808d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff
15818d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff  return FALSE;
15828d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff}
1583dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
1584e285199897e538523f762cb5b3900e81f872035avanjeff/**
1585f737cfb953905f42f3324e8e53ec324a15314210jgong  Reads a UDP packet from the network interface.
1586f737cfb953905f42f3324e8e53ec324a15314210jgong
1587f737cfb953905f42f3324e8e53ec324a15314210jgong  This function reads a UDP packet from a network interface. The data contents
1588f737cfb953905f42f3324e8e53ec324a15314210jgong  are returned in (the optional HeaderPtr and) BufferPtr, and the size of the
1589f737cfb953905f42f3324e8e53ec324a15314210jgong  buffer received is returned in BufferSize . If the input BufferSize is smaller
1590f737cfb953905f42f3324e8e53ec324a15314210jgong  than the UDP packet received (less optional HeaderSize), it will be set to the
1591f737cfb953905f42f3324e8e53ec324a15314210jgong  required size, and EFI_BUFFER_TOO_SMALL will be returned. In this case, the
1592f737cfb953905f42f3324e8e53ec324a15314210jgong  contents of BufferPtr are undefined, and the packet is lost. If a UDP packet is
1593f737cfb953905f42f3324e8e53ec324a15314210jgong  successfully received, then EFI_SUCCESS will be returned, and the information
1594f737cfb953905f42f3324e8e53ec324a15314210jgong  from the UDP header will be returned in DestIp, DestPort, SrcIp, and SrcPort if
1595e285199897e538523f762cb5b3900e81f872035avanjeff  they are not NULL. Depending on the values of OpFlags and the DestIp, DestPort,
1596e285199897e538523f762cb5b3900e81f872035avanjeff  SrcIp, and SrcPort input values, different types of UDP packet receive filtering
1597f737cfb953905f42f3324e8e53ec324a15314210jgong  will be performed. The following tables summarize these receive filter operations.
1598e285199897e538523f762cb5b3900e81f872035avanjeff
1599f737cfb953905f42f3324e8e53ec324a15314210jgong  @param  This                  Pointer to the EFI_PXE_BASE_CODE_PROTOCOL instance.
1600e285199897e538523f762cb5b3900e81f872035avanjeff  @param  OpFlags               The UDP operation flags.
1601f737cfb953905f42f3324e8e53ec324a15314210jgong  @param  DestIp                The destination IP address.
1602f737cfb953905f42f3324e8e53ec324a15314210jgong  @param  DestPort              The destination UDP port number.
1603f737cfb953905f42f3324e8e53ec324a15314210jgong  @param  SrcIp                 The source IP address.
1604f737cfb953905f42f3324e8e53ec324a15314210jgong  @param  SrcPort               The source UDP port number.
1605f737cfb953905f42f3324e8e53ec324a15314210jgong  @param  HeaderSize            An optional field which may be set to the length of a header at
1606e285199897e538523f762cb5b3900e81f872035avanjeff                                HeaderPtr to be prefixed to the data at BufferPtr.
1607f737cfb953905f42f3324e8e53ec324a15314210jgong  @param  HeaderPtr             If HeaderSize is not NULL, a pointer to a header to be prefixed to the
1608e285199897e538523f762cb5b3900e81f872035avanjeff                                data at BufferPtr.
1609f737cfb953905f42f3324e8e53ec324a15314210jgong  @param  BufferSize            A pointer to the size of the data at BufferPtr.
1610f737cfb953905f42f3324e8e53ec324a15314210jgong  @param  BufferPtr             A pointer to the data to be read.
1611e285199897e538523f762cb5b3900e81f872035avanjeff
1612f737cfb953905f42f3324e8e53ec324a15314210jgong  @retval EFI_SUCCESS           The UDP Read operation was completed.
1613f737cfb953905f42f3324e8e53ec324a15314210jgong  @retval EFI_NOT_STARTED       The PXE Base Code Protocol is in the stopped state.
1614e285199897e538523f762cb5b3900e81f872035avanjeff  @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
1615f737cfb953905f42f3324e8e53ec324a15314210jgong  @retval EFI_DEVICE_ERROR      The network device encountered an error during this operation.
1616f737cfb953905f42f3324e8e53ec324a15314210jgong  @retval EFI_BUFFER_TOO_SMALL  The packet is larger than Buffer can hold.
1617f737cfb953905f42f3324e8e53ec324a15314210jgong  @retval EFI_ABORTED           The callback function aborted the UDP Read operation.
1618e285199897e538523f762cb5b3900e81f872035avanjeff  @retval EFI_TIMEOUT           The UDP Read operation timed out.
1619e285199897e538523f762cb5b3900e81f872035avanjeff
1620dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff**/
1621dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeffEFI_STATUS
1622dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeffEFIAPI
1623dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeffEfiPxeBcUdpRead (
1624f737cfb953905f42f3324e8e53ec324a15314210jgong  IN EFI_PXE_BASE_CODE_PROTOCOL                *This,
1625f737cfb953905f42f3324e8e53ec324a15314210jgong  IN UINT16                                    OpFlags,
1626f737cfb953905f42f3324e8e53ec324a15314210jgong  IN OUT EFI_IP_ADDRESS                        *DestIp     OPTIONAL,
1627f737cfb953905f42f3324e8e53ec324a15314210jgong  IN OUT EFI_PXE_BASE_CODE_UDP_PORT            *DestPort   OPTIONAL,
1628f737cfb953905f42f3324e8e53ec324a15314210jgong  IN OUT EFI_IP_ADDRESS                        *SrcIp      OPTIONAL,
1629f737cfb953905f42f3324e8e53ec324a15314210jgong  IN OUT EFI_PXE_BASE_CODE_UDP_PORT            *SrcPort    OPTIONAL,
1630f737cfb953905f42f3324e8e53ec324a15314210jgong  IN UINTN                                     *HeaderSize OPTIONAL,
1631f737cfb953905f42f3324e8e53ec324a15314210jgong  IN VOID                                      *HeaderPtr  OPTIONAL,
1632f737cfb953905f42f3324e8e53ec324a15314210jgong  IN OUT UINTN                                 *BufferSize,
1633f737cfb953905f42f3324e8e53ec324a15314210jgong  IN VOID                                      *BufferPtr
1634dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  )
1635dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff{
1636dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  PXEBC_PRIVATE_DATA        *Private;
1637dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  EFI_PXE_BASE_CODE_MODE    *Mode;
1638dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  EFI_UDP4_PROTOCOL         *Udp4;
1639dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  EFI_UDP4_COMPLETION_TOKEN Token;
1640dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  EFI_UDP4_RECEIVE_DATA     *RxData;
1641dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  EFI_UDP4_SESSION_DATA     *Session;
1642dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  EFI_STATUS                Status;
1643dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  BOOLEAN                   IsDone;
1644dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  BOOLEAN                   Matched;
1645c3cd46d421cef32077ae6caf860b50d00ba2aa7fsfu  UINTN                     CopiedLen;
1646c3cd46d421cef32077ae6caf860b50d00ba2aa7fsfu  UINTN                     HeaderLen;
1647c3cd46d421cef32077ae6caf860b50d00ba2aa7fsfu  UINTN                     HeaderCopiedLen;
1648c3cd46d421cef32077ae6caf860b50d00ba2aa7fsfu  UINTN                     BufferCopiedLen;
1649c3cd46d421cef32077ae6caf860b50d00ba2aa7fsfu  UINT32                    FragmentLength;
1650c3cd46d421cef32077ae6caf860b50d00ba2aa7fsfu  UINTN                     FragmentIndex;
1651c3cd46d421cef32077ae6caf860b50d00ba2aa7fsfu  UINT8                     *FragmentBuffer;
1652dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
1653dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  if (This == NULL || DestIp == NULL || DestPort == NULL) {
1654dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    return EFI_INVALID_PARAMETER;
1655dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  }
1656dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
1657f737cfb953905f42f3324e8e53ec324a15314210jgong  if (((OpFlags & EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_DEST_PORT) == 0 && (DestPort == NULL)) ||
1658f737cfb953905f42f3324e8e53ec324a15314210jgong      ((OpFlags & EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_DEST_PORT) == 0 && (SrcIp == NULL)) ||
1659f737cfb953905f42f3324e8e53ec324a15314210jgong      ((OpFlags & EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_PORT) == 0 && (SrcPort == NULL))) {
1660dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    return EFI_INVALID_PARAMETER;
1661dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  }
1662dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
16638792362f22e4fac66aeec04b13b7a6b70cb571e9vanjeff  if (((HeaderSize != NULL) && (*HeaderSize == 0)) || ((HeaderSize != NULL) && (HeaderPtr == NULL))) {
1664dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    return EFI_INVALID_PARAMETER;
1665dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  }
1666dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
166729a4f92d814896a7c15e5fd0559defa4d7232c53hhuan  if ((BufferSize == NULL) || (BufferPtr == NULL)) {
1668dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    return EFI_INVALID_PARAMETER;
1669dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  }
1670dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
1671dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  Private = PXEBC_PRIVATE_DATA_FROM_PXEBC (This);
1672dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  Mode    = Private->PxeBc.Mode;
16738792362f22e4fac66aeec04b13b7a6b70cb571e9vanjeff  Udp4    = Private->Udp4Read;
1674dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
1675dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  if (!Mode->Started) {
1676dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    return EFI_NOT_STARTED;
1677dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  }
1678dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
1679982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  Mode->IcmpErrorReceived = FALSE;
1680982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff
1681dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  Status = gBS->CreateEvent (
1682dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff                  EVT_NOTIFY_SIGNAL,
1683e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff                  TPL_NOTIFY,
1684dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff                  PxeBcCommonNotify,
1685dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff                  &IsDone,
1686dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff                  &Token.Event
1687dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff                  );
1688dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  if (EFI_ERROR (Status)) {
1689dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    return EFI_OUT_OF_RESOURCES;
1690dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  }
1691dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
16928792362f22e4fac66aeec04b13b7a6b70cb571e9vanjeffTRY_AGAIN:
16938792362f22e4fac66aeec04b13b7a6b70cb571e9vanjeff
1694dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  IsDone = FALSE;
1695dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  Status = Udp4->Receive (Udp4, &Token);
1696dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  if (EFI_ERROR (Status)) {
1697982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff    if (Status == EFI_ICMP_ERROR) {
1698982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff      Mode->IcmpErrorReceived = TRUE;
1699982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff    }
1700dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    goto ON_EXIT;
1701dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  }
1702dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
1703dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  Udp4->Poll (Udp4);
1704dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
1705dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  if (!IsDone) {
1706dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    Status = EFI_TIMEOUT;
1707dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  } else {
1708dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
1709dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    //
1710dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    // check whether this packet matches the filters
1711dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    //
1712dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    if (EFI_ERROR (Token.Status)){
1713dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff      goto ON_EXIT;
1714dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    }
1715dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
1716dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    RxData  = Token.Packet.RxData;
1717dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    Session = &RxData->UdpSession;
1718dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
1719319075ff6e1d1fb470667453ec24a2ba685f60a0vanjeff    Matched = TRUE;
1720dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
1721f737cfb953905f42f3324e8e53ec324a15314210jgong    if ((OpFlags & EFI_PXE_BASE_CODE_UDP_OPFLAGS_USE_FILTER) != 0) {
1722319075ff6e1d1fb470667453ec24a2ba685f60a0vanjeff      Matched = FALSE;
17238d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff      //
17248d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff      // Check UDP package by IP filter settings
17258d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff      //
17268d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff      if (CheckIpByFilter (Mode, Session)) {
17278d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff        Matched = TRUE;
1728dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff      }
17298d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff    }
17308d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff
17318d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff    if (Matched) {
17328792362f22e4fac66aeec04b13b7a6b70cb571e9vanjeff      Matched = FALSE;
17338792362f22e4fac66aeec04b13b7a6b70cb571e9vanjeff
17348d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff      //
17358d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff      // Match the destination ip of the received udp dgram
17368d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff      //
1737f737cfb953905f42f3324e8e53ec324a15314210jgong      if ((OpFlags & EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_DEST_IP) != 0) {
17388d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff        Matched = TRUE;
17398d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff
17408d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff        if (DestIp != NULL) {
17418d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff          CopyMem (DestIp, &Session->DestinationAddress, sizeof (EFI_IPv4_ADDRESS));
1742dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff        }
1743dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff      } else {
17448d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff        if (DestIp != NULL) {
17458d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff          if (EFI_IP4_EQUAL (DestIp, &Session->DestinationAddress)) {
17468d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff            Matched = TRUE;
17478d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff          }
17488d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff        } else {
17498d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff          if (EFI_IP4_EQUAL (&Private->StationIp, &Session->DestinationAddress)) {
17508d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff            Matched = TRUE;
17518d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff          }
1752dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff        }
1753dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff      }
1754dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    }
1755dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
1756dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    if (Matched) {
1757dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff      //
1758dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff      // Match the destination port of the received udp dgram
1759dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff      //
1760f737cfb953905f42f3324e8e53ec324a15314210jgong      if ((OpFlags & EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_DEST_PORT) != 0) {
1761dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
1762dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff        if (DestPort != NULL) {
1763dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff          *DestPort = Session->DestinationPort;
1764dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff        }
1765dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff      } else {
1766dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
1767dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff        if (*DestPort != Session->DestinationPort) {
1768dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff          Matched = FALSE;
1769dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff        }
1770dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff      }
1771dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    }
1772dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
1773dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    if (Matched) {
1774dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff      //
1775dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff      // Match the source ip of the received udp dgram
1776dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff      //
1777f737cfb953905f42f3324e8e53ec324a15314210jgong      if ((OpFlags & EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_IP) != 0) {
1778dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
1779dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff        if (SrcIp != NULL) {
1780e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff          CopyMem (SrcIp, &Session->SourceAddress, sizeof (EFI_IPv4_ADDRESS));
1781dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff        }
1782dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff      } else {
1783dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
1784dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff        if (!EFI_IP4_EQUAL (SrcIp, &Session->SourceAddress)) {
1785dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff          Matched = FALSE;
1786dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff        }
1787dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff      }
1788dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    }
1789dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
1790dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    if (Matched) {
1791dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff      //
1792dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff      // Match the source port of the received udp dgram
1793dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff      //
1794f737cfb953905f42f3324e8e53ec324a15314210jgong      if ((OpFlags & EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_PORT) != 0) {
1795dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
1796dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff        if (SrcPort != NULL) {
1797dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff          *SrcPort = Session->SourcePort;
1798dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff        }
1799dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff      } else {
1800dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
1801dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff        if (*SrcPort != Session->SourcePort) {
1802dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff          Matched = FALSE;
1803dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff        }
1804dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff      }
1805dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    }
1806dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
1807dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    if (Matched) {
1808c3cd46d421cef32077ae6caf860b50d00ba2aa7fsfu      ASSERT (RxData != NULL);
1809dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
1810c3cd46d421cef32077ae6caf860b50d00ba2aa7fsfu      HeaderLen = 0;
1811dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff      if (HeaderSize != NULL) {
1812c3cd46d421cef32077ae6caf860b50d00ba2aa7fsfu        HeaderLen = MIN (*HeaderSize, RxData->DataLength);
1813dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff      }
1814dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
1815c3cd46d421cef32077ae6caf860b50d00ba2aa7fsfu      if (RxData->DataLength - HeaderLen > *BufferSize) {
1816dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff        Status = EFI_BUFFER_TOO_SMALL;
1817dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff      } else {
1818c3cd46d421cef32077ae6caf860b50d00ba2aa7fsfu        *HeaderSize = HeaderLen;
1819c3cd46d421cef32077ae6caf860b50d00ba2aa7fsfu        *BufferSize = RxData->DataLength - HeaderLen;
1820c3cd46d421cef32077ae6caf860b50d00ba2aa7fsfu
1821c3cd46d421cef32077ae6caf860b50d00ba2aa7fsfu        HeaderCopiedLen = 0;
1822c3cd46d421cef32077ae6caf860b50d00ba2aa7fsfu        BufferCopiedLen = 0;
1823c3cd46d421cef32077ae6caf860b50d00ba2aa7fsfu        for (FragmentIndex = 0; FragmentIndex < RxData->FragmentCount; FragmentIndex++) {
1824c3cd46d421cef32077ae6caf860b50d00ba2aa7fsfu          FragmentLength = RxData->FragmentTable[FragmentIndex].FragmentLength;
1825c3cd46d421cef32077ae6caf860b50d00ba2aa7fsfu          FragmentBuffer = RxData->FragmentTable[FragmentIndex].FragmentBuffer;
1826c3cd46d421cef32077ae6caf860b50d00ba2aa7fsfu          if (HeaderCopiedLen + FragmentLength < HeaderLen) {
1827c3cd46d421cef32077ae6caf860b50d00ba2aa7fsfu            //
1828c3cd46d421cef32077ae6caf860b50d00ba2aa7fsfu            // Copy the header part of received data.
1829c3cd46d421cef32077ae6caf860b50d00ba2aa7fsfu            //
1830c3cd46d421cef32077ae6caf860b50d00ba2aa7fsfu            CopyMem ((UINT8 *) HeaderPtr + HeaderCopiedLen, FragmentBuffer, FragmentLength);
1831c3cd46d421cef32077ae6caf860b50d00ba2aa7fsfu            HeaderCopiedLen += FragmentLength;
1832c3cd46d421cef32077ae6caf860b50d00ba2aa7fsfu          } else if (HeaderCopiedLen < HeaderLen) {
1833c3cd46d421cef32077ae6caf860b50d00ba2aa7fsfu            //
1834c3cd46d421cef32077ae6caf860b50d00ba2aa7fsfu            // Copy the header part of received data.
1835c3cd46d421cef32077ae6caf860b50d00ba2aa7fsfu            //
1836c3cd46d421cef32077ae6caf860b50d00ba2aa7fsfu            CopiedLen = HeaderLen - HeaderCopiedLen;
1837c3cd46d421cef32077ae6caf860b50d00ba2aa7fsfu            CopyMem ((UINT8 *) HeaderPtr + HeaderCopiedLen, FragmentBuffer, CopiedLen);
1838c3cd46d421cef32077ae6caf860b50d00ba2aa7fsfu            HeaderCopiedLen += CopiedLen;
1839c3cd46d421cef32077ae6caf860b50d00ba2aa7fsfu
1840c3cd46d421cef32077ae6caf860b50d00ba2aa7fsfu            //
1841c3cd46d421cef32077ae6caf860b50d00ba2aa7fsfu            // Copy the other part of received data.
1842c3cd46d421cef32077ae6caf860b50d00ba2aa7fsfu            //
1843c3cd46d421cef32077ae6caf860b50d00ba2aa7fsfu            CopyMem ((UINT8 *) BufferPtr + BufferCopiedLen, FragmentBuffer + CopiedLen, FragmentLength - CopiedLen);
1844c3cd46d421cef32077ae6caf860b50d00ba2aa7fsfu            BufferCopiedLen += (FragmentLength - CopiedLen);
1845c3cd46d421cef32077ae6caf860b50d00ba2aa7fsfu          } else {
1846c3cd46d421cef32077ae6caf860b50d00ba2aa7fsfu            //
1847c3cd46d421cef32077ae6caf860b50d00ba2aa7fsfu            // Copy the other part of received data.
1848c3cd46d421cef32077ae6caf860b50d00ba2aa7fsfu            //
1849c3cd46d421cef32077ae6caf860b50d00ba2aa7fsfu            CopyMem ((UINT8 *) BufferPtr + BufferCopiedLen, FragmentBuffer, FragmentLength);
1850c3cd46d421cef32077ae6caf860b50d00ba2aa7fsfu            BufferCopiedLen += FragmentLength;
1851c3cd46d421cef32077ae6caf860b50d00ba2aa7fsfu          }
1852c3cd46d421cef32077ae6caf860b50d00ba2aa7fsfu        }
1853dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff      }
1854dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    } else {
1855dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
1856dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff      Status = EFI_TIMEOUT;
1857dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    }
1858dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
1859dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    //
1860dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    // Recycle the RxData
1861dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    //
1862dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    gBS->SignalEvent (RxData->RecycleSignal);
18638792362f22e4fac66aeec04b13b7a6b70cb571e9vanjeff
18648792362f22e4fac66aeec04b13b7a6b70cb571e9vanjeff    if (!Matched) {
18658792362f22e4fac66aeec04b13b7a6b70cb571e9vanjeff      goto TRY_AGAIN;
18668792362f22e4fac66aeec04b13b7a6b70cb571e9vanjeff    }
1867dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  }
1868dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
1869dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeffON_EXIT:
1870dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
1871dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  Udp4->Cancel (Udp4, &Token);
1872dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
1873dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  gBS->CloseEvent (Token.Event);
1874dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
1875dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  return Status;
1876dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff}
1877dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
1878e285199897e538523f762cb5b3900e81f872035avanjeff/**
1879f737cfb953905f42f3324e8e53ec324a15314210jgong  Updates the IP receive filters of a network device and enables software filtering.
1880e285199897e538523f762cb5b3900e81f872035avanjeff
1881f737cfb953905f42f3324e8e53ec324a15314210jgong  The NewFilter field is used to modify the network device's current IP receive
1882f737cfb953905f42f3324e8e53ec324a15314210jgong  filter settings and to enable a software filter. This function updates the IpFilter
1883f737cfb953905f42f3324e8e53ec324a15314210jgong  field of the EFI_PXE_BASE_CODE_MODE structure with the contents of NewIpFilter.
1884f737cfb953905f42f3324e8e53ec324a15314210jgong  The software filter is used when the USE_FILTER in OpFlags is set to UdpRead().
1885f737cfb953905f42f3324e8e53ec324a15314210jgong  The current hardware filter remains in effect no matter what the settings of OpFlags
1886f737cfb953905f42f3324e8e53ec324a15314210jgong  are, so that the meaning of ANY_DEST_IP set in OpFlags to UdpRead() is from those
1887f737cfb953905f42f3324e8e53ec324a15314210jgong  packets whose reception is enabled in hardware-physical NIC address (unicast),
1888f737cfb953905f42f3324e8e53ec324a15314210jgong  broadcast address, logical address or addresses (multicast), or all (promiscuous).
1889f737cfb953905f42f3324e8e53ec324a15314210jgong  UdpRead() does not modify the IP filter settings.
1890f737cfb953905f42f3324e8e53ec324a15314210jgong  Dhcp(), Discover(), and Mtftp() set the IP filter, and return with the IP receive
1891f737cfb953905f42f3324e8e53ec324a15314210jgong  filter list emptied and the filter set to EFI_PXE_BASE_CODE_IP_FILTER_STATION_IP.
1892f737cfb953905f42f3324e8e53ec324a15314210jgong  If an application or driver wishes to preserve the IP receive filter settings,
1893f737cfb953905f42f3324e8e53ec324a15314210jgong  it will have to preserve the IP receive filter settings before these calls, and
1894f737cfb953905f42f3324e8e53ec324a15314210jgong  use SetIpFilter() to restore them after the calls. If incompatible filtering is
1895f737cfb953905f42f3324e8e53ec324a15314210jgong  requested (for example, PROMISCUOUS with anything else) or if the device does not
1896f737cfb953905f42f3324e8e53ec324a15314210jgong  support a requested filter setting and it cannot be accommodated in software
1897f737cfb953905f42f3324e8e53ec324a15314210jgong  (for example, PROMISCUOUS not supported), EFI_INVALID_PARAMETER will be returned.
1898f737cfb953905f42f3324e8e53ec324a15314210jgong  The IPlist field is used to enable IPs other than the StationIP. They may be
1899f737cfb953905f42f3324e8e53ec324a15314210jgong  multicast or unicast. If IPcnt is set as well as EFI_PXE_BASE_CODE_IP_FILTER_STATION_IP,
1900f737cfb953905f42f3324e8e53ec324a15314210jgong  then both the StationIP and the IPs from the IPlist will be used.
1901e285199897e538523f762cb5b3900e81f872035avanjeff
1902f737cfb953905f42f3324e8e53ec324a15314210jgong  @param  This                  Pointer to the EFI_PXE_BASE_CODE_PROTOCOL instance.
1903f737cfb953905f42f3324e8e53ec324a15314210jgong  @param  NewFilter             Pointer to the new set of IP receive filters.
1904e285199897e538523f762cb5b3900e81f872035avanjeff
1905f737cfb953905f42f3324e8e53ec324a15314210jgong  @retval EFI_SUCCESS           The IP receive filter settings were updated.
1906f737cfb953905f42f3324e8e53ec324a15314210jgong  @retval EFI_NOT_STARTED       The PXE Base Code Protocol is in the stopped state.
1907e285199897e538523f762cb5b3900e81f872035avanjeff  @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
1908e285199897e538523f762cb5b3900e81f872035avanjeff
1909dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff**/
1910dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeffEFI_STATUS
1911dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeffEFIAPI
1912dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeffEfiPxeBcSetIpFilter (
1913dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  IN EFI_PXE_BASE_CODE_PROTOCOL       *This,
1914dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  IN EFI_PXE_BASE_CODE_IP_FILTER      *NewFilter
1915dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  )
1916dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff{
19178d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff  EFI_STATUS                Status;
19188d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff  PXEBC_PRIVATE_DATA        *Private;
19198d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff  EFI_PXE_BASE_CODE_MODE    *Mode;
19208d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff  UINTN                     Index;
1921c82291bc3108c948a66d659da0fd76731351f530hhuan  EFI_UDP4_CONFIG_DATA      *Udp4Cfg;
19228d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff  BOOLEAN                   PromiscuousNeed;
1923c82291bc3108c948a66d659da0fd76731351f530hhuan  BOOLEAN                   AcceptPromiscuous;
1924c82291bc3108c948a66d659da0fd76731351f530hhuan  BOOLEAN                   AcceptBroadcast;
1925c82291bc3108c948a66d659da0fd76731351f530hhuan  BOOLEAN                   MultiCastUpdate;
19268d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff
19278d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff  if (This == NULL) {
1928894d038a8d0e99d456042e2b6d1554c4a406ea70vanjeff    DEBUG ((EFI_D_ERROR, "This == NULL.\n"));
19298d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff    return EFI_INVALID_PARAMETER;
19308d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff  }
19318d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff
19328d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff  Private = PXEBC_PRIVATE_DATA_FROM_PXEBC (This);
19338d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff  Mode = Private->PxeBc.Mode;
19348d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff
1935894d038a8d0e99d456042e2b6d1554c4a406ea70vanjeff  if (NewFilter == NULL) {
1936894d038a8d0e99d456042e2b6d1554c4a406ea70vanjeff    DEBUG ((EFI_D_ERROR, "NewFilter == NULL.\n"));
19378d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff    return EFI_INVALID_PARAMETER;
19388d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff  }
19398d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff
1940894d038a8d0e99d456042e2b6d1554c4a406ea70vanjeff  if (NewFilter->IpCnt > EFI_PXE_BASE_CODE_MAX_IPCNT) {
1941894d038a8d0e99d456042e2b6d1554c4a406ea70vanjeff    DEBUG ((EFI_D_ERROR, "NewFilter->IpCnt > %d.\n", EFI_PXE_BASE_CODE_MAX_IPCNT));
19428d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff    return EFI_INVALID_PARAMETER;
19438d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff  }
19448d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff
19458d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff  if (!Mode->Started) {
19468d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff    DEBUG ((EFI_D_ERROR, "BC was not started.\n"));
19478d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff    return EFI_NOT_STARTED;
19488d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff  }
19498d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff
1950c82291bc3108c948a66d659da0fd76731351f530hhuan  if (Mode->UsingIpv6) {
1951c82291bc3108c948a66d659da0fd76731351f530hhuan    DEBUG ((EFI_D_ERROR, "This driver is PXE for IPv4 Only.\n"));
1952c82291bc3108c948a66d659da0fd76731351f530hhuan    return EFI_INVALID_PARAMETER;
1953c82291bc3108c948a66d659da0fd76731351f530hhuan  }
1954c82291bc3108c948a66d659da0fd76731351f530hhuan
19558d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff  PromiscuousNeed = FALSE;
1956894d038a8d0e99d456042e2b6d1554c4a406ea70vanjeff
19578d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff  for (Index = 0; Index < NewFilter->IpCnt; ++Index) {
19588d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff    if (IP4_IS_LOCAL_BROADCAST (EFI_IP4 (NewFilter->IpList[Index].v4))) {
19598d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff      //
19608d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff      // The IP is a broadcast address.
19618d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff      //
19628d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff      DEBUG ((EFI_D_ERROR, "There is broadcast address in NewFilter.\n"));
19638d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff      return EFI_INVALID_PARAMETER;
19648d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff    }
1965f6b7393ceb34c9b3a27434268bf2ce517047641ftye    if (NetIp4IsUnicast (EFI_IP4 (NewFilter->IpList[Index].v4), 0) &&
1966e285199897e538523f762cb5b3900e81f872035avanjeff        ((NewFilter->Filters & EFI_PXE_BASE_CODE_IP_FILTER_STATION_IP) != 0)
19678d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff       ) {
19688d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff      //
19698d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff      // If EFI_PXE_BASE_CODE_IP_FILTER_STATION_IP is set and IP4 address is in IpList,
19708d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff      // promiscuous mode is needed.
19718d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff      //
19728d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff      PromiscuousNeed = TRUE;
19738d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff    }
19748d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff  }
19758d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff
1976c82291bc3108c948a66d659da0fd76731351f530hhuan  AcceptPromiscuous = FALSE;
1977c82291bc3108c948a66d659da0fd76731351f530hhuan  AcceptBroadcast   = FALSE;
1978c82291bc3108c948a66d659da0fd76731351f530hhuan  MultiCastUpdate   = FALSE;
19798d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff
19808d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff  if (PromiscuousNeed ||
1981e285199897e538523f762cb5b3900e81f872035avanjeff      ((NewFilter->Filters & EFI_PXE_BASE_CODE_IP_FILTER_PROMISCUOUS) != 0) ||
1982e285199897e538523f762cb5b3900e81f872035avanjeff      ((NewFilter->Filters & EFI_PXE_BASE_CODE_IP_FILTER_PROMISCUOUS_MULTICAST) != 0)
19838d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff     ) {
19848d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff    //
1985c82291bc3108c948a66d659da0fd76731351f530hhuan    // Configure the udp4 filter to receive all packages.
19868d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff    //
1987c82291bc3108c948a66d659da0fd76731351f530hhuan    AcceptPromiscuous  = TRUE;
1988c82291bc3108c948a66d659da0fd76731351f530hhuan  } else if ((NewFilter->Filters & EFI_PXE_BASE_CODE_IP_FILTER_BROADCAST) != 0) {
19898d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff    //
1990c82291bc3108c948a66d659da0fd76731351f530hhuan    // Configure the udp4 filter to receive all broadcast packages.
19918d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff    //
1992c82291bc3108c948a66d659da0fd76731351f530hhuan    AcceptBroadcast   = TRUE;
1993c82291bc3108c948a66d659da0fd76731351f530hhuan  }
19948d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff
1995c82291bc3108c948a66d659da0fd76731351f530hhuan  //
1996c82291bc3108c948a66d659da0fd76731351f530hhuan  // In multicast condition when Promiscuous FALSE and IpCnt no-zero.
1997c82291bc3108c948a66d659da0fd76731351f530hhuan  // Here check if there is any update of the multicast ip address. If yes,
1998c82291bc3108c948a66d659da0fd76731351f530hhuan  // we need leave the old multicast group (by Config UDP instance to NULL),
1999c82291bc3108c948a66d659da0fd76731351f530hhuan  // and join the new multicast group.
2000c82291bc3108c948a66d659da0fd76731351f530hhuan  //
2001c82291bc3108c948a66d659da0fd76731351f530hhuan  if (!AcceptPromiscuous) {
2002c82291bc3108c948a66d659da0fd76731351f530hhuan    if ((NewFilter->Filters & EFI_PXE_BASE_CODE_IP_FILTER_STATION_IP) != 0) {
2003c82291bc3108c948a66d659da0fd76731351f530hhuan      if (Mode->IpFilter.IpCnt != NewFilter->IpCnt) {
2004c82291bc3108c948a66d659da0fd76731351f530hhuan        MultiCastUpdate = TRUE;
2005c82291bc3108c948a66d659da0fd76731351f530hhuan      } else if (CompareMem (Mode->IpFilter.IpList, NewFilter->IpList, NewFilter->IpCnt * sizeof (EFI_IP_ADDRESS)) != 0 ) {
2006c82291bc3108c948a66d659da0fd76731351f530hhuan        MultiCastUpdate = TRUE;
2007c82291bc3108c948a66d659da0fd76731351f530hhuan      }
20088d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff    }
2009c82291bc3108c948a66d659da0fd76731351f530hhuan  }
2010c82291bc3108c948a66d659da0fd76731351f530hhuan
2011c82291bc3108c948a66d659da0fd76731351f530hhuan  //
2012c82291bc3108c948a66d659da0fd76731351f530hhuan  // Check whether we need reconfigure the UDP instance.
2013c82291bc3108c948a66d659da0fd76731351f530hhuan  //
2014c82291bc3108c948a66d659da0fd76731351f530hhuan  Udp4Cfg = &Private->Udp4CfgData;
2015c82291bc3108c948a66d659da0fd76731351f530hhuan  if ((AcceptPromiscuous != Udp4Cfg->AcceptPromiscuous) ||
2016c82291bc3108c948a66d659da0fd76731351f530hhuan  	  (AcceptBroadcast != Udp4Cfg->AcceptBroadcast)     || MultiCastUpdate) {
2017c82291bc3108c948a66d659da0fd76731351f530hhuan    //
2018c82291bc3108c948a66d659da0fd76731351f530hhuan    // Clear the UDP instance configuration, all joined groups will be left
2019c82291bc3108c948a66d659da0fd76731351f530hhuan    // during the operation.
2020c82291bc3108c948a66d659da0fd76731351f530hhuan    //
2021c82291bc3108c948a66d659da0fd76731351f530hhuan    Private->Udp4Read->Configure (Private->Udp4Read, NULL);
20228d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff
20238d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff    //
20248d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff    // Configure the UDP instance with the new configuration.
20258d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff    //
2026c82291bc3108c948a66d659da0fd76731351f530hhuan    Udp4Cfg->AcceptPromiscuous = AcceptPromiscuous;
2027c82291bc3108c948a66d659da0fd76731351f530hhuan    Udp4Cfg->AcceptBroadcast   = AcceptBroadcast;
2028c82291bc3108c948a66d659da0fd76731351f530hhuan    Status = Private->Udp4Read->Configure (Private->Udp4Read, Udp4Cfg);
20298d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff    if (EFI_ERROR (Status)) {
20308d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff      return Status;
20318d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff    }
20328d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff
2033c82291bc3108c948a66d659da0fd76731351f530hhuan    //
2034c82291bc3108c948a66d659da0fd76731351f530hhuan    // In not Promiscuous mode, need to join the new multicast group.
2035c82291bc3108c948a66d659da0fd76731351f530hhuan    //
2036c82291bc3108c948a66d659da0fd76731351f530hhuan    if (!AcceptPromiscuous) {
20378d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff      for (Index = 0; Index < NewFilter->IpCnt; ++Index) {
20388d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff        if (IP4_IS_MULTICAST (EFI_NTOHL (NewFilter->IpList[Index].v4))) {
20398d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff          //
2040c82291bc3108c948a66d659da0fd76731351f530hhuan          // Join the mutilcast group.
20418d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff          //
20428792362f22e4fac66aeec04b13b7a6b70cb571e9vanjeff          Status = Private->Udp4Read->Groups (Private->Udp4Read, TRUE, &NewFilter->IpList[Index].v4);
20438d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff          if (EFI_ERROR (Status)) {
20448d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff            return Status;
20458d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff          }
20468d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff        }
20478d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff      }
20488d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff    }
20498d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff  }
20508d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff
20518d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff
20528d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff  //
20538d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff  // Save the new filter.
20548d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff  //
20558d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff  CopyMem (&Mode->IpFilter, NewFilter, sizeof (Mode->IpFilter));
20568d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff
20578d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff  return EFI_SUCCESS;
2058dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff}
2059dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
2060dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
2061e285199897e538523f762cb5b3900e81f872035avanjeff/**
2062f737cfb953905f42f3324e8e53ec324a15314210jgong  Uses the ARP protocol to resolve a MAC address.
2063e285199897e538523f762cb5b3900e81f872035avanjeff
2064f737cfb953905f42f3324e8e53ec324a15314210jgong  This function uses the ARP protocol to resolve a MAC address. The UsingIpv6 field
2065f737cfb953905f42f3324e8e53ec324a15314210jgong  of the EFI_PXE_BASE_CODE_MODE structure is used to determine if IPv4 or IPv6
2066f737cfb953905f42f3324e8e53ec324a15314210jgong  addresses are being used. The IP address specified by IpAddr is used to resolve
2067f737cfb953905f42f3324e8e53ec324a15314210jgong  a MAC address. If the ARP protocol succeeds in resolving the specified address,
2068f737cfb953905f42f3324e8e53ec324a15314210jgong  then the ArpCacheEntries and ArpCache fields of the EFI_PXE_BASE_CODE_MODE structure
2069f737cfb953905f42f3324e8e53ec324a15314210jgong  are updated, and EFI_SUCCESS is returned. If MacAddr is not NULL, the resolved
2070e285199897e538523f762cb5b3900e81f872035avanjeff  MAC address is placed there as well.  If the PXE Base Code protocol is in the
2071e285199897e538523f762cb5b3900e81f872035avanjeff  stopped state, then EFI_NOT_STARTED is returned. If the ARP protocol encounters
2072e285199897e538523f762cb5b3900e81f872035avanjeff  a timeout condition while attempting to resolve an address, then EFI_TIMEOUT is
2073e285199897e538523f762cb5b3900e81f872035avanjeff  returned. If the Callback Protocol does not return EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE,
2074f737cfb953905f42f3324e8e53ec324a15314210jgong  then EFI_ABORTED is returned.
2075e285199897e538523f762cb5b3900e81f872035avanjeff
2076f737cfb953905f42f3324e8e53ec324a15314210jgong  @param  This                  Pointer to the EFI_PXE_BASE_CODE_PROTOCOL instance.
2077f737cfb953905f42f3324e8e53ec324a15314210jgong  @param  IpAddr                Pointer to the IP address that is used to resolve a MAC address.
2078f737cfb953905f42f3324e8e53ec324a15314210jgong  @param  MacAddr               If not NULL, a pointer to the MAC address that was resolved with the
2079e285199897e538523f762cb5b3900e81f872035avanjeff                                ARP protocol.
2080e285199897e538523f762cb5b3900e81f872035avanjeff
2081f737cfb953905f42f3324e8e53ec324a15314210jgong  @retval EFI_SUCCESS           The IP or MAC address was resolved.
2082f737cfb953905f42f3324e8e53ec324a15314210jgong  @retval EFI_NOT_STARTED       The PXE Base Code Protocol is in the stopped state.
2083e285199897e538523f762cb5b3900e81f872035avanjeff  @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
2084e285199897e538523f762cb5b3900e81f872035avanjeff  @retval EFI_DEVICE_ERROR      The network device encountered an error during this operation.
2085e285199897e538523f762cb5b3900e81f872035avanjeff  @retval EFI_ICMP_ERROR        Something error occur with the ICMP packet message.
2086e285199897e538523f762cb5b3900e81f872035avanjeff
2087dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff**/
2088dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeffEFI_STATUS
2089dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeffEFIAPI
2090dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeffEfiPxeBcArp (
2091dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  IN EFI_PXE_BASE_CODE_PROTOCOL       * This,
2092dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  IN EFI_IP_ADDRESS                   * IpAddr,
2093dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  IN EFI_MAC_ADDRESS                  * MacAddr OPTIONAL
2094dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  )
2095dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff{
20968d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff  PXEBC_PRIVATE_DATA      *Private;
20978d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff  EFI_PXE_BASE_CODE_MODE  *Mode;
20988d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff  EFI_STATUS              Status;
20998d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff  EFI_MAC_ADDRESS         TempMacAddr;
21008d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff
21018d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff  if (This == NULL || IpAddr == NULL) {
21028d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff    return EFI_INVALID_PARAMETER;
21038d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff  }
21048d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff
21058d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff  Private = PXEBC_PRIVATE_DATA_FROM_PXEBC (This);
21068d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff  Mode    = Private->PxeBc.Mode;
21078d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff
21088d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff  if (!Mode->Started) {
21098d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff    return EFI_NOT_STARTED;
21108d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff  }
21118d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff
21128d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff  if (!Private->AddressIsOk || Mode->UsingIpv6) {
21138d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff    //
21148d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff    // We can't resolve the IP address if we don't have a local address now.
21158d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff    // Don't have ARP for IPv6.
21168d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff    //
21178d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff    return EFI_INVALID_PARAMETER;
21188d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff  }
21198d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff
2120982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  Mode->IcmpErrorReceived = FALSE;
2121982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff
2122982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  if (!Mode->AutoArp) {
2123982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff    //
2124982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff    // If AutoArp is set false, check arp cache
2125982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff    //
2126982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff    UpdateArpCache (This);
2127982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff    if (!FindInArpCache (Mode, &IpAddr->v4, &TempMacAddr)) {
2128982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff      return EFI_DEVICE_ERROR;
2129982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff    }
2130982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff  } else {
2131982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff    Status = Private->Arp->Request (Private->Arp, &IpAddr->v4, NULL, &TempMacAddr);
2132982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff    if (EFI_ERROR (Status)) {
2133982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff      if (Status == EFI_ICMP_ERROR) {
2134982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff        Mode->IcmpErrorReceived = TRUE;
2135982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff      }
2136982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff      return Status;
2137982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff    }
21388d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff  }
21398d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff
21408d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff  if (MacAddr != NULL) {
21418d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff    CopyMem (MacAddr, &TempMacAddr, sizeof (EFI_MAC_ADDRESS));
21428d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff  }
21438d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff
21448d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff  return EFI_SUCCESS;
2145dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff}
2146dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
2147e285199897e538523f762cb5b3900e81f872035avanjeff/**
2148f737cfb953905f42f3324e8e53ec324a15314210jgong  Updates the parameters that affect the operation of the PXE Base Code Protocol.
2149e285199897e538523f762cb5b3900e81f872035avanjeff
2150f737cfb953905f42f3324e8e53ec324a15314210jgong  This function sets parameters that affect the operation of the PXE Base Code Protocol.
2151f737cfb953905f42f3324e8e53ec324a15314210jgong  The parameter specified by NewAutoArp is used to control the generation of ARP
2152f737cfb953905f42f3324e8e53ec324a15314210jgong  protocol packets. If NewAutoArp is TRUE, then ARP Protocol packets will be generated
2153f737cfb953905f42f3324e8e53ec324a15314210jgong  as required by the PXE Base Code Protocol. If NewAutoArp is FALSE, then no ARP
2154f737cfb953905f42f3324e8e53ec324a15314210jgong  Protocol packets will be generated. In this case, the only mappings that are
2155f737cfb953905f42f3324e8e53ec324a15314210jgong  available are those stored in the ArpCache of the EFI_PXE_BASE_CODE_MODE structure.
2156f737cfb953905f42f3324e8e53ec324a15314210jgong  If there are not enough mappings in the ArpCache to perform a PXE Base Code Protocol
2157f737cfb953905f42f3324e8e53ec324a15314210jgong  service, then the service will fail. This function updates the AutoArp field of
2158f737cfb953905f42f3324e8e53ec324a15314210jgong  the EFI_PXE_BASE_CODE_MODE structure to NewAutoArp.
2159f737cfb953905f42f3324e8e53ec324a15314210jgong  The SetParameters() call must be invoked after a Callback Protocol is installed
2160f737cfb953905f42f3324e8e53ec324a15314210jgong  to enable the use of callbacks.
2161e285199897e538523f762cb5b3900e81f872035avanjeff
2162f737cfb953905f42f3324e8e53ec324a15314210jgong  @param  This                  Pointer to the EFI_PXE_BASE_CODE_PROTOCOL instance.
2163f737cfb953905f42f3324e8e53ec324a15314210jgong  @param  NewAutoArp            If not NULL, a pointer to a value that specifies whether to replace the
2164e285199897e538523f762cb5b3900e81f872035avanjeff                                current value of AutoARP.
2165f737cfb953905f42f3324e8e53ec324a15314210jgong  @param  NewSendGUID           If not NULL, a pointer to a value that specifies whether to replace the
2166e285199897e538523f762cb5b3900e81f872035avanjeff                                current value of SendGUID.
2167f737cfb953905f42f3324e8e53ec324a15314210jgong  @param  NewTTL                If not NULL, a pointer to be used in place of the current value of TTL,
2168e285199897e538523f762cb5b3900e81f872035avanjeff                                the "time to live" field of the IP header.
2169f737cfb953905f42f3324e8e53ec324a15314210jgong  @param  NewToS                If not NULL, a pointer to be used in place of the current value of ToS,
2170e285199897e538523f762cb5b3900e81f872035avanjeff                                the "type of service" field of the IP header.
2171f737cfb953905f42f3324e8e53ec324a15314210jgong  @param  NewMakeCallback       If not NULL, a pointer to a value that specifies whether to replace the
2172e285199897e538523f762cb5b3900e81f872035avanjeff                                current value of the MakeCallback field of the Mode structure.
2173e285199897e538523f762cb5b3900e81f872035avanjeff
2174f737cfb953905f42f3324e8e53ec324a15314210jgong  @retval EFI_SUCCESS           The new parameters values were updated.
2175f737cfb953905f42f3324e8e53ec324a15314210jgong  @retval EFI_NOT_STARTED       The PXE Base Code Protocol is in the stopped state.
2176e285199897e538523f762cb5b3900e81f872035avanjeff  @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
2177e285199897e538523f762cb5b3900e81f872035avanjeff
2178dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff**/
2179dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeffEFI_STATUS
2180dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeffEFIAPI
2181dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeffEfiPxeBcSetParameters (
2182dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  IN EFI_PXE_BASE_CODE_PROTOCOL       *This,
2183f737cfb953905f42f3324e8e53ec324a15314210jgong  IN BOOLEAN                          *NewAutoArp OPTIONAL,
2184f737cfb953905f42f3324e8e53ec324a15314210jgong  IN BOOLEAN                          *NewSendGUID OPTIONAL,
2185f737cfb953905f42f3324e8e53ec324a15314210jgong  IN UINT8                            *NewTTL OPTIONAL,
2186f737cfb953905f42f3324e8e53ec324a15314210jgong  IN UINT8                            *NewToS OPTIONAL,
2187dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  IN BOOLEAN                          *NewMakeCallback  // OPTIONAL
2188dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  )
2189dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff{
2190dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  PXEBC_PRIVATE_DATA      *Private;
2191dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  EFI_PXE_BASE_CODE_MODE  *Mode;
2192dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  EFI_STATUS              Status;
2193dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
2194dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  Status = EFI_SUCCESS;
2195dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
2196dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  if (This == NULL) {
2197dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    Status = EFI_INVALID_PARAMETER;
2198dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    goto ON_EXIT;
2199dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  }
2200dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
2201dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  Private = PXEBC_PRIVATE_DATA_FROM_PXEBC (This);
2202dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  Mode    = Private->PxeBc.Mode;
2203dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
2204f737cfb953905f42f3324e8e53ec324a15314210jgong  if (NewSendGUID != NULL && *NewSendGUID) {
2205dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    //
2206dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    // FixMe, cann't locate SendGuid
2207dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    //
2208dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  }
2209dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
2210f737cfb953905f42f3324e8e53ec324a15314210jgong  if (NewMakeCallback != NULL && *NewMakeCallback) {
2211dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
2212dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    Status = gBS->HandleProtocol (
2213dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff                    Private->Controller,
2214dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff                    &gEfiPxeBaseCodeCallbackProtocolGuid,
2215dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff                    (VOID **) &Private->PxeBcCallback
2216dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff                    );
2217dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    if (EFI_ERROR (Status) || (Private->PxeBcCallback->Callback == NULL)) {
2218dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
2219dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff      Status = EFI_INVALID_PARAMETER;
2220dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff      goto ON_EXIT;
2221dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    }
2222dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  }
2223dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
2224dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  if (!Mode->Started) {
2225dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    Status = EFI_NOT_STARTED;
2226dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    goto ON_EXIT;
2227dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  }
2228dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
2229dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  if (NewMakeCallback != NULL) {
2230dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
2231dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    if (*NewMakeCallback) {
2232dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff      //
2233dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff      // Update the Callback protocol.
2234dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff      //
2235dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff      Status = gBS->HandleProtocol (
2236dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff                      Private->Controller,
2237dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff                      &gEfiPxeBaseCodeCallbackProtocolGuid,
2238dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff                      (VOID **) &Private->PxeBcCallback
2239dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff                      );
2240dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
2241dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff      if (EFI_ERROR (Status) || (Private->PxeBcCallback->Callback == NULL)) {
2242dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff        Status = EFI_INVALID_PARAMETER;
2243dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff        goto ON_EXIT;
2244dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff      }
2245dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    } else {
2246dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff      Private->PxeBcCallback = NULL;
2247dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    }
2248dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
2249dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    Mode->MakeCallbacks = *NewMakeCallback;
2250dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  }
2251dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
2252dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  if (NewAutoArp != NULL) {
2253dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    Mode->AutoArp = *NewAutoArp;
2254dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  }
2255dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
2256dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  if (NewSendGUID != NULL) {
2257dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    Mode->SendGUID = *NewSendGUID;
2258dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  }
2259dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
2260dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  if (NewTTL != NULL) {
2261dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    Mode->TTL = *NewTTL;
2262dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  }
2263dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
2264dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  if (NewToS != NULL) {
2265dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    Mode->ToS = *NewToS;
2266dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  }
2267dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
2268dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeffON_EXIT:
2269dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  return Status;
2270dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff}
2271dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
2272e285199897e538523f762cb5b3900e81f872035avanjeff/**
2273f737cfb953905f42f3324e8e53ec324a15314210jgong  Updates the station IP address and/or subnet mask values of a network device.
2274e285199897e538523f762cb5b3900e81f872035avanjeff
2275f737cfb953905f42f3324e8e53ec324a15314210jgong  This function updates the station IP address and/or subnet mask values of a network
2276f737cfb953905f42f3324e8e53ec324a15314210jgong  device. The NewStationIp field is used to modify the network device's current IP address.
2277f737cfb953905f42f3324e8e53ec324a15314210jgong  If NewStationIP is NULL, then the current IP address will not be modified. Otherwise,
2278f737cfb953905f42f3324e8e53ec324a15314210jgong  this function updates the StationIp field of the EFI_PXE_BASE_CODE_MODE structure
2279f737cfb953905f42f3324e8e53ec324a15314210jgong  with NewStationIp. The NewSubnetMask field is used to modify the network device's current subnet
2280f737cfb953905f42f3324e8e53ec324a15314210jgong  mask. If NewSubnetMask is NULL, then the current subnet mask will not be modified.
2281f737cfb953905f42f3324e8e53ec324a15314210jgong  Otherwise, this function updates the SubnetMask field of the EFI_PXE_BASE_CODE_MODE
2282f737cfb953905f42f3324e8e53ec324a15314210jgong  structure with NewSubnetMask.
2283e285199897e538523f762cb5b3900e81f872035avanjeff
2284f737cfb953905f42f3324e8e53ec324a15314210jgong  @param  This                  Pointer to the EFI_PXE_BASE_CODE_PROTOCOL instance.
2285e285199897e538523f762cb5b3900e81f872035avanjeff  @param  NewStationIp          Pointer to the new IP address to be used by the network device.
2286e285199897e538523f762cb5b3900e81f872035avanjeff  @param  NewSubnetMask         Pointer to the new subnet mask to be used by the network device.
2287e285199897e538523f762cb5b3900e81f872035avanjeff
2288f737cfb953905f42f3324e8e53ec324a15314210jgong  @retval EFI_SUCCESS           The new station IP address and/or subnet mask were updated.
2289f737cfb953905f42f3324e8e53ec324a15314210jgong  @retval EFI_NOT_STARTED       The PXE Base Code Protocol is in the stopped state.
2290e285199897e538523f762cb5b3900e81f872035avanjeff  @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
2291e285199897e538523f762cb5b3900e81f872035avanjeff
2292dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff**/
2293dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeffEFI_STATUS
2294dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeffEFIAPI
2295dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeffEfiPxeBcSetStationIP (
2296dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  IN EFI_PXE_BASE_CODE_PROTOCOL       * This,
2297f737cfb953905f42f3324e8e53ec324a15314210jgong  IN EFI_IP_ADDRESS                   * NewStationIp  OPTIONAL,
2298dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  IN EFI_IP_ADDRESS                   * NewSubnetMask OPTIONAL
2299dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  )
2300dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff{
2301dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  PXEBC_PRIVATE_DATA      *Private;
2302dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  EFI_PXE_BASE_CODE_MODE  *Mode;
23038d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff  EFI_ARP_CONFIG_DATA     ArpConfigData;
2304dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
2305dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  if (This == NULL) {
2306dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    return EFI_INVALID_PARAMETER;
2307dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  }
2308dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
2309f6b7393ceb34c9b3a27434268bf2ce517047641ftye  if (NewStationIp != NULL && !NetIp4IsUnicast (NTOHL (NewStationIp->Addr[0]), 0)) {
2310dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    return EFI_INVALID_PARAMETER;
2311dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  }
2312dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
2313dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  if (NewSubnetMask != NULL && !IP4_IS_VALID_NETMASK (NTOHL (NewSubnetMask->Addr[0]))) {
2314dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    return EFI_INVALID_PARAMETER;
2315dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  }
2316dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
2317dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  Private = PXEBC_PRIVATE_DATA_FROM_PXEBC (This);
2318dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  Mode    = Private->PxeBc.Mode;
2319dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
2320dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  if (!Mode->Started) {
2321dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    return EFI_NOT_STARTED;
2322dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  }
2323dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
2324dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  if (NewStationIp != NULL) {
2325555e76f83f0ccf60434d3c72720f0a79f5ff4639xli    CopyMem (&Mode->StationIp, NewStationIp, sizeof (EFI_IP_ADDRESS));
2326555e76f83f0ccf60434d3c72720f0a79f5ff4639xli    CopyMem (&Private->StationIp, NewStationIp, sizeof (EFI_IP_ADDRESS));
2327dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  }
2328dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
2329dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  if (NewSubnetMask != NULL) {
2330555e76f83f0ccf60434d3c72720f0a79f5ff4639xli    CopyMem (&Mode->SubnetMask, NewSubnetMask, sizeof (EFI_IP_ADDRESS));
2331555e76f83f0ccf60434d3c72720f0a79f5ff4639xli    CopyMem (&Private->SubnetMask ,NewSubnetMask, sizeof (EFI_IP_ADDRESS));
2332dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  }
2333dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
2334dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  Private->AddressIsOk = TRUE;
2335dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
23368d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff  if (!Mode->UsingIpv6) {
23378d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff    //
23388d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff    // If in IPv4 mode, configure the corresponding ARP with this new
23398d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff    // station IP address.
23408d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff    //
23418d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff    ZeroMem (&ArpConfigData, sizeof (EFI_ARP_CONFIG_DATA));
23428d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff
23438d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff    ArpConfigData.SwAddressType   = 0x0800;
2344c9325700d0ef25eaf45077928af3f93b15ac5fe0ydong    ArpConfigData.SwAddressLength = (UINT8) sizeof (EFI_IPv4_ADDRESS);
23458d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff    ArpConfigData.StationAddress  = &Private->StationIp.v4;
23468d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff
23478d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff    Private->Arp->Configure (Private->Arp, NULL);
23488d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff    Private->Arp->Configure (Private->Arp, &ArpConfigData);
2349982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff
2350982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff    //
2351982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff    // Update the route table.
2352982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff    //
2353982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff    Mode->RouteTableEntries                = 1;
2354982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff    Mode->RouteTable[0].IpAddr.Addr[0]     = Private->StationIp.Addr[0] & Private->SubnetMask.Addr[0];
2355982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff    Mode->RouteTable[0].SubnetMask.Addr[0] = Private->SubnetMask.Addr[0];
2356982a9eaea270fdc05d60d570e3d0e4d168654c05vanjeff    Mode->RouteTable[0].GwAddr.Addr[0]     = 0;
23578d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff  }
23588d285ec0ce8b4c85f8e98b98ed95cbc801817fb9vanjeff
2359dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  return EFI_SUCCESS;
2360dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff}
2361dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
2362e285199897e538523f762cb5b3900e81f872035avanjeff/**
2363f737cfb953905f42f3324e8e53ec324a15314210jgong  Updates the contents of the cached DHCP and Discover packets.
2364e285199897e538523f762cb5b3900e81f872035avanjeff
2365f737cfb953905f42f3324e8e53ec324a15314210jgong  The pointers to the new packets are used to update the contents of the cached
2366f737cfb953905f42f3324e8e53ec324a15314210jgong  packets in the EFI_PXE_BASE_CODE_MODE structure.
2367e285199897e538523f762cb5b3900e81f872035avanjeff
2368f737cfb953905f42f3324e8e53ec324a15314210jgong  @param  This                   Pointer to the EFI_PXE_BASE_CODE_PROTOCOL instance.
2369f737cfb953905f42f3324e8e53ec324a15314210jgong  @param  NewDhcpDiscoverValid   Pointer to a value that will replace the current
2370e285199897e538523f762cb5b3900e81f872035avanjeff                                 DhcpDiscoverValid field.
2371f737cfb953905f42f3324e8e53ec324a15314210jgong  @param  NewDhcpAckReceived     Pointer to a value that will replace the current
2372e285199897e538523f762cb5b3900e81f872035avanjeff                                 DhcpAckReceived field.
2373f737cfb953905f42f3324e8e53ec324a15314210jgong  @param  NewProxyOfferReceived  Pointer to a value that will replace the current
2374e285199897e538523f762cb5b3900e81f872035avanjeff                                 ProxyOfferReceived field.
2375e285199897e538523f762cb5b3900e81f872035avanjeff  @param  NewPxeDiscoverValid    Pointer to a value that will replace the current
2376e285199897e538523f762cb5b3900e81f872035avanjeff                                 ProxyOfferReceived field.
2377f737cfb953905f42f3324e8e53ec324a15314210jgong  @param  NewPxeReplyReceived    Pointer to a value that will replace the current
2378e285199897e538523f762cb5b3900e81f872035avanjeff                                 PxeReplyReceived field.
2379f737cfb953905f42f3324e8e53ec324a15314210jgong  @param  NewPxeBisReplyReceived Pointer to a value that will replace the current
2380e285199897e538523f762cb5b3900e81f872035avanjeff                                 PxeBisReplyReceived field.
2381e285199897e538523f762cb5b3900e81f872035avanjeff  @param  NewDhcpDiscover        Pointer to the new cached DHCP Discover packet contents.
2382f737cfb953905f42f3324e8e53ec324a15314210jgong  @param  NewDhcpAck             Pointer to the new cached DHCP Ack packet contents.
2383f737cfb953905f42f3324e8e53ec324a15314210jgong  @param  NewProxyOffer          Pointer to the new cached Proxy Offer packet contents.
2384f737cfb953905f42f3324e8e53ec324a15314210jgong  @param  NewPxeDiscover         Pointer to the new cached PXE Discover packet contents.
2385f737cfb953905f42f3324e8e53ec324a15314210jgong  @param  NewPxeReply            Pointer to the new cached PXE Reply packet contents.
2386f737cfb953905f42f3324e8e53ec324a15314210jgong  @param  NewPxeBisReply         Pointer to the new cached PXE BIS Reply packet contents.
2387e285199897e538523f762cb5b3900e81f872035avanjeff
2388f737cfb953905f42f3324e8e53ec324a15314210jgong  @retval EFI_SUCCESS            The cached packet contents were updated.
2389f737cfb953905f42f3324e8e53ec324a15314210jgong  @retval EFI_NOT_STARTED        The PXE Base Code Protocol is in the stopped state.
2390f737cfb953905f42f3324e8e53ec324a15314210jgong  @retval EFI_INVALID_PARAMETER  This is NULL or not point to a valid EFI_PXE_BASE_CODE_PROTOCOL structure.
2391e285199897e538523f762cb5b3900e81f872035avanjeff
2392dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff**/
2393dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeffEFI_STATUS
2394dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeffEFIAPI
2395dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeffEfiPxeBcSetPackets (
2396dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  IN EFI_PXE_BASE_CODE_PROTOCOL       * This,
2397f737cfb953905f42f3324e8e53ec324a15314210jgong  IN BOOLEAN                          * NewDhcpDiscoverValid OPTIONAL,
2398f737cfb953905f42f3324e8e53ec324a15314210jgong  IN BOOLEAN                          * NewDhcpAckReceived OPTIONAL,
2399f737cfb953905f42f3324e8e53ec324a15314210jgong  IN BOOLEAN                          * NewProxyOfferReceived OPTIONAL,
2400f737cfb953905f42f3324e8e53ec324a15314210jgong  IN BOOLEAN                          * NewPxeDiscoverValid OPTIONAL,
2401f737cfb953905f42f3324e8e53ec324a15314210jgong  IN BOOLEAN                          * NewPxeReplyReceived OPTIONAL,
2402f737cfb953905f42f3324e8e53ec324a15314210jgong  IN BOOLEAN                          * NewPxeBisReplyReceived OPTIONAL,
2403f737cfb953905f42f3324e8e53ec324a15314210jgong  IN EFI_PXE_BASE_CODE_PACKET         * NewDhcpDiscover OPTIONAL,
2404f737cfb953905f42f3324e8e53ec324a15314210jgong  IN EFI_PXE_BASE_CODE_PACKET         * NewDhcpAck OPTIONAL,
2405f737cfb953905f42f3324e8e53ec324a15314210jgong  IN EFI_PXE_BASE_CODE_PACKET         * NewProxyOffer OPTIONAL,
2406f737cfb953905f42f3324e8e53ec324a15314210jgong  IN EFI_PXE_BASE_CODE_PACKET         * NewPxeDiscover OPTIONAL,
2407f737cfb953905f42f3324e8e53ec324a15314210jgong  IN EFI_PXE_BASE_CODE_PACKET         * NewPxeReply OPTIONAL,
2408dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  IN EFI_PXE_BASE_CODE_PACKET         * NewPxeBisReply OPTIONAL
2409dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  )
2410dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff{
2411dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  PXEBC_PRIVATE_DATA      *Private;
2412dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  EFI_PXE_BASE_CODE_MODE  *Mode;
2413dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
2414dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  if (This == NULL) {
2415dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    return EFI_INVALID_PARAMETER;
2416dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  }
2417dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
2418dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  Private = PXEBC_PRIVATE_DATA_FROM_PXEBC (This);
2419dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  Mode    = Private->PxeBc.Mode;
2420dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
2421dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  if (!Mode->Started) {
2422dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    return EFI_NOT_STARTED;
2423dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  }
2424dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
2425dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  if (NewDhcpDiscoverValid != NULL) {
2426dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    Mode->DhcpDiscoverValid = *NewDhcpDiscoverValid;
2427dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  }
2428dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
2429dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  if (NewDhcpAckReceived != NULL) {
2430dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    Mode->DhcpAckReceived = *NewDhcpAckReceived;
2431dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  }
2432dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
2433dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  if (NewProxyOfferReceived != NULL) {
2434dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    Mode->ProxyOfferReceived = *NewProxyOfferReceived;
2435dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  }
2436dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
2437dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  if (NewPxeDiscoverValid != NULL) {
2438dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    Mode->PxeDiscoverValid = *NewPxeDiscoverValid;
2439dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  }
2440dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
2441dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  if (NewPxeReplyReceived != NULL) {
2442dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    Mode->PxeReplyReceived = *NewPxeReplyReceived;
2443dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  }
2444dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
2445dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  if (NewPxeBisReplyReceived != NULL) {
2446dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    Mode->PxeBisReplyReceived = *NewPxeBisReplyReceived;
2447dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  }
2448dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
2449dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  if (NewDhcpDiscover != NULL) {
2450e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff    CopyMem (&Mode->DhcpDiscover, NewDhcpDiscover, sizeof (EFI_PXE_BASE_CODE_PACKET));
2451dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  }
2452dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
2453dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  if (NewDhcpAck != NULL) {
2454e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff    CopyMem (&Mode->DhcpAck, NewDhcpAck, sizeof (EFI_PXE_BASE_CODE_PACKET));
2455dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  }
2456dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
2457dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  if (NewProxyOffer != NULL) {
2458e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff    CopyMem (&Mode->ProxyOffer, NewProxyOffer, sizeof (EFI_PXE_BASE_CODE_PACKET));
2459dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  }
2460dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
2461dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  if (NewPxeDiscover != NULL) {
2462e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff    CopyMem (&Mode->PxeDiscover, NewPxeDiscover, sizeof (EFI_PXE_BASE_CODE_PACKET));
2463dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  }
2464dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
2465dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  if (NewPxeReply != NULL) {
2466e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff    CopyMem (&Mode->PxeReply, NewPxeReply, sizeof (EFI_PXE_BASE_CODE_PACKET));
2467dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  }
2468dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
2469dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  if (NewPxeBisReply != NULL) {
2470e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff    CopyMem (&Mode->PxeBisReply, NewPxeBisReply, sizeof (EFI_PXE_BASE_CODE_PACKET));
2471dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  }
2472dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
2473dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  return EFI_SUCCESS;
2474dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff}
2475dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
2476dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeffEFI_PXE_BASE_CODE_PROTOCOL  mPxeBcProtocolTemplate = {
2477dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  EFI_PXE_BASE_CODE_PROTOCOL_REVISION,
2478dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  EfiPxeBcStart,
2479dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  EfiPxeBcStop,
2480dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  EfiPxeBcDhcp,
2481dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  EfiPxeBcDiscover,
2482dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  EfiPxeBcMtftp,
2483dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  EfiPxeBcUdpWrite,
2484dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  EfiPxeBcUdpRead,
2485dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  EfiPxeBcSetIpFilter,
2486dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  EfiPxeBcArp,
2487dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  EfiPxeBcSetParameters,
2488dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  EfiPxeBcSetStationIP,
2489dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  EfiPxeBcSetPackets,
2490dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  NULL
2491dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff};
2492dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
2493e285199897e538523f762cb5b3900e81f872035avanjeff/**
2494f737cfb953905f42f3324e8e53ec324a15314210jgong  Callback function that is invoked when the PXE Base Code Protocol is about to transmit, has
2495e285199897e538523f762cb5b3900e81f872035avanjeff  received, or is waiting to receive a packet.
2496e285199897e538523f762cb5b3900e81f872035avanjeff
2497f737cfb953905f42f3324e8e53ec324a15314210jgong  This function is invoked when the PXE Base Code Protocol is about to transmit, has received,
2498f737cfb953905f42f3324e8e53ec324a15314210jgong  or is waiting to receive a packet. Parameters Function and Received specify the type of event.
2499f737cfb953905f42f3324e8e53ec324a15314210jgong  Parameters PacketLen and Packet specify the packet that generated the event. If these fields
2500f737cfb953905f42f3324e8e53ec324a15314210jgong  are zero and NULL respectively, then this is a status update callback. If the operation specified
2501f737cfb953905f42f3324e8e53ec324a15314210jgong  by Function is to continue, then CALLBACK_STATUS_CONTINUE should be returned. If the operation
2502f737cfb953905f42f3324e8e53ec324a15314210jgong  specified by Function should be aborted, then CALLBACK_STATUS_ABORT should be returned. Due to
2503f737cfb953905f42f3324e8e53ec324a15314210jgong  the polling nature of UEFI device drivers, a callback function should not execute for more than 5 ms.
2504f737cfb953905f42f3324e8e53ec324a15314210jgong  The SetParameters() function must be called after a Callback Protocol is installed to enable the
2505f737cfb953905f42f3324e8e53ec324a15314210jgong  use of callbacks.
2506e285199897e538523f762cb5b3900e81f872035avanjeff
2507f737cfb953905f42f3324e8e53ec324a15314210jgong  @param  This                  Pointer to the EFI_PXE_BASE_CODE_CALLBACK_PROTOCOL instance.
2508e285199897e538523f762cb5b3900e81f872035avanjeff  @param  Function              The PXE Base Code Protocol function that is waiting for an event.
2509f737cfb953905f42f3324e8e53ec324a15314210jgong  @param  Received              TRUE if the callback is being invoked due to a receive event. FALSE if
2510e285199897e538523f762cb5b3900e81f872035avanjeff                                the callback is being invoked due to a transmit event.
2511f737cfb953905f42f3324e8e53ec324a15314210jgong  @param  PacketLength          The length, in bytes, of Packet. This field will have a value of zero if
2512e285199897e538523f762cb5b3900e81f872035avanjeff                                this is a wait for receive event.
2513f737cfb953905f42f3324e8e53ec324a15314210jgong  @param  PacketPtr             If Received is TRUE, a pointer to the packet that was just received;
2514e285199897e538523f762cb5b3900e81f872035avanjeff                                otherwise a pointer to the packet that is about to be transmitted.
2515e285199897e538523f762cb5b3900e81f872035avanjeff
2516e285199897e538523f762cb5b3900e81f872035avanjeff  @retval EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE if Function specifies a continue operation
2517f737cfb953905f42f3324e8e53ec324a15314210jgong  @retval EFI_PXE_BASE_CODE_CALLBACK_STATUS_ABORT    if Function specifies an abort operation
2518e285199897e538523f762cb5b3900e81f872035avanjeff
2519dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff**/
2520dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeffEFI_PXE_BASE_CODE_CALLBACK_STATUS
2521dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeffEFIAPI
2522dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeffEfiPxeLoadFileCallback (
2523dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  IN EFI_PXE_BASE_CODE_CALLBACK_PROTOCOL  * This,
2524dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  IN EFI_PXE_BASE_CODE_FUNCTION           Function,
2525dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  IN BOOLEAN                              Received,
2526dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  IN UINT32                               PacketLength,
2527dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  IN EFI_PXE_BASE_CODE_PACKET             * PacketPtr OPTIONAL
2528dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  )
2529dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff{
2530dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  EFI_INPUT_KEY Key;
2531dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  EFI_STATUS    Status;
2532dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
2533dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  //
2534dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  // Catch Ctrl-C or ESC to abort.
2535dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  //
2536dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
2537dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
2538dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  if (!EFI_ERROR (Status)) {
2539dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
2540dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    if (Key.ScanCode == SCAN_ESC || Key.UnicodeChar == (0x1F & 'c')) {
2541dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
2542dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff      return EFI_PXE_BASE_CODE_CALLBACK_STATUS_ABORT;
2543dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    }
2544dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  }
2545dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  //
2546dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  // No print if receive packet
2547dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  //
2548dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  if (Received) {
2549dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    return EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE;
2550dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  }
2551dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  //
2552dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  // Print only for three functions
2553dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  //
2554dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  switch (Function) {
2555dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
2556dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  case EFI_PXE_BASE_CODE_FUNCTION_MTFTP:
2557dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    //
2558dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    // Print only for open MTFTP packets, not every MTFTP packets
2559dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    //
2560dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    if (PacketLength != 0 && PacketPtr != NULL) {
2561dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff      if (PacketPtr->Raw[0x1C] != 0x00 || PacketPtr->Raw[0x1D] != 0x01) {
2562dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff        return EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE;
2563dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff      }
2564dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    }
2565dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    break;
2566dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
2567dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  case EFI_PXE_BASE_CODE_FUNCTION_DHCP:
2568dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  case EFI_PXE_BASE_CODE_FUNCTION_DISCOVER:
2569dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    break;
2570dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
2571dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  default:
2572dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    return EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE;
2573dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  }
2574dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
2575dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  if (PacketLength != 0 && PacketPtr != NULL) {
2576dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    //
2577dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    // Print '.' when transmit a packet
2578dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    //
2579dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    AsciiPrint (".");
2580dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
2581dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  }
2582dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
2583dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  return EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE;
2584dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff}
2585dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
2586dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeffEFI_PXE_BASE_CODE_CALLBACK_PROTOCOL mPxeBcCallBackTemplate = {
2587dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  EFI_PXE_BASE_CODE_CALLBACK_PROTOCOL_REVISION,
2588dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  EfiPxeLoadFileCallback
2589dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff};
2590dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
2591dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
2592dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff/**
2593f737cfb953905f42f3324e8e53ec324a15314210jgong  Find the boot file.
2594dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
2595e285199897e538523f762cb5b3900e81f872035avanjeff  @param  Private      Pointer to PxeBc private data.
2596e285199897e538523f762cb5b3900e81f872035avanjeff  @param  BufferSize   Pointer to buffer size.
2597e285199897e538523f762cb5b3900e81f872035avanjeff  @param  Buffer       Pointer to buffer.
2598dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
2599f737cfb953905f42f3324e8e53ec324a15314210jgong  @retval EFI_SUCCESS          Discover the boot file successfully.
2600f737cfb953905f42f3324e8e53ec324a15314210jgong  @retval EFI_TIMEOUT          The TFTP/MTFTP operation timed out.
2601f737cfb953905f42f3324e8e53ec324a15314210jgong  @retval EFI_ABORTED          PXE bootstrap server, so local boot need abort.
2602f737cfb953905f42f3324e8e53ec324a15314210jgong  @retval EFI_BUFFER_TOO_SMALL The buffer is too small to load the boot file.
2603e285199897e538523f762cb5b3900e81f872035avanjeff
2604dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff**/
2605dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeffEFI_STATUS
2606dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeffDiscoverBootFile (
2607dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  IN     PXEBC_PRIVATE_DATA  *Private,
2608dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  IN OUT UINT64              *BufferSize,
2609dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  IN     VOID                *Buffer
2610dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  )
2611dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff{
2612dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  EFI_PXE_BASE_CODE_PROTOCOL  *PxeBc;
2613dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  EFI_PXE_BASE_CODE_MODE      *Mode;
2614dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  EFI_STATUS                  Status;
2615dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  UINT16                      Type;
2616dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  UINT16                      Layer;
2617dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  BOOLEAN                     UseBis;
2618dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  PXEBC_CACHED_DHCP4_PACKET   *Packet;
2619dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  UINT16                      Value;
2620dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
2621dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  PxeBc = &Private->PxeBc;
2622dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  Mode  = PxeBc->Mode;
2623dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  Type  = EFI_PXE_BASE_CODE_BOOT_TYPE_BOOTSTRAP;
2624dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  Layer = EFI_PXE_BASE_CODE_BOOT_LAYER_INITIAL;
2625dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
2626dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  //
2627dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  // do DHCP.
2628dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  //
2629dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  Status = PxeBc->Dhcp (PxeBc, TRUE);
2630dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  if (EFI_ERROR (Status)) {
2631dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    return Status;
2632dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  }
2633dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
2634dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  //
2635dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  // Select a boot server
2636dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  //
2637dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  Status = PxeBcSelectBootPrompt (Private);
2638dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
2639dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  if (Status == EFI_SUCCESS) {
2640dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    Status = PxeBcSelectBootMenu (Private, &Type, TRUE);
2641dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  } else if (Status == EFI_TIMEOUT) {
2642dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    Status = PxeBcSelectBootMenu (Private, &Type, FALSE);
2643dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  }
2644dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
2645dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  if (!EFI_ERROR (Status)) {
2646dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
2647dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    if (Type == EFI_PXE_BASE_CODE_BOOT_TYPE_BOOTSTRAP) {
2648dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff      //
2649dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff      // Local boot(PXE bootstrap server) need abort
2650dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff      //
2651dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff      return EFI_ABORTED;
2652dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    }
2653dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
2654dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    UseBis  = (BOOLEAN) (Mode->BisSupported && Mode->BisDetected);
2655dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    Status  = PxeBc->Discover (PxeBc, Type, &Layer, UseBis, NULL);
2656dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    if (EFI_ERROR (Status)) {
2657dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff      return Status;
2658dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    }
2659dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  }
2660dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
2661dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  *BufferSize = 0;
2662dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
2663dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  //
2664dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  // Get bootfile name and (m)tftp server ip addresss
2665dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  //
2666dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  if (Mode->PxeReplyReceived) {
2667dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    Packet = &Private->PxeReply;
2668dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  } else if (Mode->ProxyOfferReceived) {
2669dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    Packet = &Private->ProxyOffer;
2670dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  } else {
2671dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    Packet = &Private->Dhcp4Ack;
2672dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  }
2673dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
2674319075ff6e1d1fb470667453ec24a2ba685f60a0vanjeff  //
26752ce5c88a7adaea3eeeccc932b18da5f02440f8cdvanjeff  // Use siaddr(next server) in DHCPOFFER packet header, if zero, use option 54(server identifier)
26762ce5c88a7adaea3eeeccc932b18da5f02440f8cdvanjeff  // in DHCPOFFER packet.
26772ce5c88a7adaea3eeeccc932b18da5f02440f8cdvanjeff  // (It does not comply with PXE Spec, Ver2.1)
2678319075ff6e1d1fb470667453ec24a2ba685f60a0vanjeff  //
26792ce5c88a7adaea3eeeccc932b18da5f02440f8cdvanjeff  if (EFI_IP4_EQUAL (&Packet->Packet.Offer.Dhcp4.Header.ServerAddr, &mZeroIp4Addr)) {
2680e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff    CopyMem (
2681dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff      &Private->ServerIp,
2682dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff      Packet->Dhcp4Option[PXEBC_DHCP4_TAG_INDEX_SERVER_ID]->Data,
2683dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff      sizeof (EFI_IPv4_ADDRESS)
2684dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff      );
2685319075ff6e1d1fb470667453ec24a2ba685f60a0vanjeff  } else {
2686319075ff6e1d1fb470667453ec24a2ba685f60a0vanjeff    CopyMem (
2687e285199897e538523f762cb5b3900e81f872035avanjeff      &Private->ServerIp,
2688e285199897e538523f762cb5b3900e81f872035avanjeff      &Packet->Packet.Offer.Dhcp4.Header.ServerAddr,
2689319075ff6e1d1fb470667453ec24a2ba685f60a0vanjeff      sizeof (EFI_IPv4_ADDRESS)
2690319075ff6e1d1fb470667453ec24a2ba685f60a0vanjeff      );
2691319075ff6e1d1fb470667453ec24a2ba685f60a0vanjeff  }
2692319075ff6e1d1fb470667453ec24a2ba685f60a0vanjeff  if (Private->ServerIp.Addr[0] == 0) {
2693319075ff6e1d1fb470667453ec24a2ba685f60a0vanjeff    return EFI_DEVICE_ERROR;
2694dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  }
2695dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
2696dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  ASSERT (Packet->Dhcp4Option[PXEBC_DHCP4_TAG_INDEX_BOOTFILE] != NULL);
2697dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
2698dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  //
2699dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  // bootlfile name
2700dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  //
2701dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  Private->BootFileName = (CHAR8 *) (Packet->Dhcp4Option[PXEBC_DHCP4_TAG_INDEX_BOOTFILE]->Data);
2702dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
2703dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  if (Packet->Dhcp4Option[PXEBC_DHCP4_TAG_INDEX_BOOTFILE_LEN] != NULL) {
2704dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    //
2705dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    // Already have the bootfile length option, compute the file size
2706dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    //
2707e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff    CopyMem (&Value, Packet->Dhcp4Option[PXEBC_DHCP4_TAG_INDEX_BOOTFILE_LEN]->Data, sizeof (Value));
2708dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    Value       = NTOHS (Value);
2709dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    *BufferSize = 512 * Value;
2710dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    Status      = EFI_BUFFER_TOO_SMALL;
2711dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  } else {
2712dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    //
2713dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    // Get the bootfile size from tftp
2714dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    //
2715dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    Status = PxeBc->Mtftp (
2716dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff                      PxeBc,
2717dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff                      EFI_PXE_BASE_CODE_TFTP_GET_FILE_SIZE,
2718dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff                      Buffer,
2719dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff                      FALSE,
2720dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff                      BufferSize,
2721fa6d3ee4913eaf3b0fd9ddb8a4e3b618584bd965ljin                      &Private->BlockSize,
2722dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff                      &Private->ServerIp,
2723dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff                      (UINT8 *) Private->BootFileName,
2724dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff                      NULL,
2725dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff                      FALSE
2726dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff                      );
2727dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  }
2728dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
2729dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  Private->FileSize = (UINTN) *BufferSize;
2730dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
2731dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  return Status;
2732dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff}
2733dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
2734dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff/**
2735f737cfb953905f42f3324e8e53ec324a15314210jgong  Causes the driver to load a specified file.
2736f737cfb953905f42f3324e8e53ec324a15314210jgong
2737f737cfb953905f42f3324e8e53ec324a15314210jgong  @param  This                  Protocol instance pointer.
2738f737cfb953905f42f3324e8e53ec324a15314210jgong  @param  FilePath              The device specific path of the file to load.
2739e285199897e538523f762cb5b3900e81f872035avanjeff  @param  BootPolicy            If TRUE, indicates that the request originates from the
2740f737cfb953905f42f3324e8e53ec324a15314210jgong                                boot manager is attempting to load FilePath as a boot
2741f737cfb953905f42f3324e8e53ec324a15314210jgong                                selection. If FALSE, then FilePath must match as exact file
2742f737cfb953905f42f3324e8e53ec324a15314210jgong                                to be loaded.
2743f737cfb953905f42f3324e8e53ec324a15314210jgong  @param  BufferSize            On input the size of Buffer in bytes. On output with a return
2744e285199897e538523f762cb5b3900e81f872035avanjeff                                code of EFI_SUCCESS, the amount of data transferred to
2745f737cfb953905f42f3324e8e53ec324a15314210jgong                                Buffer. On output with a return code of EFI_BUFFER_TOO_SMALL,
2746f737cfb953905f42f3324e8e53ec324a15314210jgong                                the size of Buffer required to retrieve the requested file.
2747f737cfb953905f42f3324e8e53ec324a15314210jgong  @param  Buffer                The memory buffer to transfer the file to. IF Buffer is NULL,
2748e285199897e538523f762cb5b3900e81f872035avanjeff                                then no the size of the requested file is returned in
2749f737cfb953905f42f3324e8e53ec324a15314210jgong                                BufferSize.
2750f737cfb953905f42f3324e8e53ec324a15314210jgong
2751f737cfb953905f42f3324e8e53ec324a15314210jgong  @retval EFI_SUCCESS                 The file was loaded.
2752f737cfb953905f42f3324e8e53ec324a15314210jgong  @retval EFI_UNSUPPORTED             The device does not support the provided BootPolicy
2753e285199897e538523f762cb5b3900e81f872035avanjeff  @retval EFI_INVALID_PARAMETER       FilePath is not a valid device path, or
2754f737cfb953905f42f3324e8e53ec324a15314210jgong                                      BufferSize is NULL.
2755f737cfb953905f42f3324e8e53ec324a15314210jgong  @retval EFI_NO_MEDIA                No medium was present to load the file.
2756f737cfb953905f42f3324e8e53ec324a15314210jgong  @retval EFI_DEVICE_ERROR            The file was not loaded due to a device error.
2757f737cfb953905f42f3324e8e53ec324a15314210jgong  @retval EFI_NO_RESPONSE             The remote system did not respond.
2758f737cfb953905f42f3324e8e53ec324a15314210jgong  @retval EFI_NOT_FOUND               The file was not found.
2759f737cfb953905f42f3324e8e53ec324a15314210jgong  @retval EFI_ABORTED                 The file load process was manually cancelled.
2760dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
2761dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff**/
2762dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeffEFI_STATUS
2763dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeffEFIAPI
2764dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeffEfiPxeLoadFile (
2765dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  IN EFI_LOAD_FILE_PROTOCOL           * This,
2766dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  IN EFI_DEVICE_PATH_PROTOCOL         * FilePath,
2767dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  IN BOOLEAN                          BootPolicy,
2768dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  IN OUT UINTN                        *BufferSize,
2769dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  IN VOID                             *Buffer OPTIONAL
2770dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  )
2771dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff{
2772dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  PXEBC_PRIVATE_DATA          *Private;
2773dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  EFI_PXE_BASE_CODE_PROTOCOL  *PxeBc;
2774dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  BOOLEAN                     NewMakeCallback;
2775dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  EFI_STATUS                  Status;
2776dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  UINT64                      TmpBufSize;
2777dd29f3edb9849b7bb51f0ae4be8941a760846ef3xdu  BOOLEAN                     MediaPresent;
2778dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
27796758032da90bda58cb49e1823637bc19a1f4cc32Zhang Lubo  if (FilePath == NULL || !IsDevicePathEnd (FilePath)) {
27806758032da90bda58cb49e1823637bc19a1f4cc32Zhang Lubo    return EFI_INVALID_PARAMETER;
27816758032da90bda58cb49e1823637bc19a1f4cc32Zhang Lubo  }
27826758032da90bda58cb49e1823637bc19a1f4cc32Zhang Lubo
2783dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  Private         = PXEBC_PRIVATE_DATA_FROM_LOADFILE (This);
2784dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  PxeBc           = &Private->PxeBc;
2785dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  NewMakeCallback = FALSE;
2786dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  Status          = EFI_DEVICE_ERROR;
2787dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
2788dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  if (This == NULL || BufferSize == NULL) {
2789dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
2790dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    return EFI_INVALID_PARAMETER;
2791dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  }
2792dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
2793dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  //
2794dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  // Only support BootPolicy
2795dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  //
2796dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  if (!BootPolicy) {
2797dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    return EFI_UNSUPPORTED;
2798dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  }
2799dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
2800dd29f3edb9849b7bb51f0ae4be8941a760846ef3xdu  //
2801dd29f3edb9849b7bb51f0ae4be8941a760846ef3xdu  // Check media status before PXE start
2802dd29f3edb9849b7bb51f0ae4be8941a760846ef3xdu  //
2803dd29f3edb9849b7bb51f0ae4be8941a760846ef3xdu  MediaPresent = TRUE;
2804dd29f3edb9849b7bb51f0ae4be8941a760846ef3xdu  NetLibDetectMedia (Private->Controller, &MediaPresent);
2805dd29f3edb9849b7bb51f0ae4be8941a760846ef3xdu  if (!MediaPresent) {
2806dd29f3edb9849b7bb51f0ae4be8941a760846ef3xdu    return EFI_NO_MEDIA;
2807dd29f3edb9849b7bb51f0ae4be8941a760846ef3xdu  }
2808dd29f3edb9849b7bb51f0ae4be8941a760846ef3xdu
2809dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  Status = PxeBc->Start (PxeBc, FALSE);
2810dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  if (EFI_ERROR (Status) && (Status != EFI_ALREADY_STARTED)) {
2811dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    return Status;
2812dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  }
2813dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
2814dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  Status = gBS->HandleProtocol (
2815dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff                  Private->Controller,
2816dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff                  &gEfiPxeBaseCodeCallbackProtocolGuid,
2817dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff                  (VOID **) &Private->PxeBcCallback
2818dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff                  );
2819dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  if (Status == EFI_UNSUPPORTED) {
2820dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
2821dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    CopyMem (&Private->LoadFileCallback, &mPxeBcCallBackTemplate, sizeof (Private->LoadFileCallback));
2822dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
2823dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    Status = gBS->InstallProtocolInterface (
2824dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff                    &Private->Controller,
2825dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff                    &gEfiPxeBaseCodeCallbackProtocolGuid,
2826dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff                    EFI_NATIVE_INTERFACE,
2827dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff                    &Private->LoadFileCallback
2828dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff                    );
2829dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
2830dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    NewMakeCallback = (BOOLEAN) (Status == EFI_SUCCESS);
2831dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
2832dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    Status          = PxeBc->SetParameters (PxeBc, NULL, NULL, NULL, NULL, &NewMakeCallback);
2833dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    if (EFI_ERROR (Status)) {
2834dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff      PxeBc->Stop (PxeBc);
2835dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff      return Status;
2836dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    }
2837dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  }
2838dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
2839dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  if (Private->FileSize == 0) {
2840dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    TmpBufSize  = 0;
2841dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    Status      = DiscoverBootFile (Private, &TmpBufSize, Buffer);
2842dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
2843dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    if (sizeof (UINTN) < sizeof (UINT64) && (TmpBufSize > 0xFFFFFFFF)) {
2844dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff      Status = EFI_DEVICE_ERROR;
284539941daf90572c818328de50fbcb7a5e5e0e7eb2gikidy    } else if (TmpBufSize > 0 && *BufferSize >= (UINTN) TmpBufSize && Buffer != NULL) {
2846319075ff6e1d1fb470667453ec24a2ba685f60a0vanjeff      *BufferSize = (UINTN) TmpBufSize;
2847319075ff6e1d1fb470667453ec24a2ba685f60a0vanjeff      Status = PxeBc->Mtftp (
2848319075ff6e1d1fb470667453ec24a2ba685f60a0vanjeff                        PxeBc,
2849319075ff6e1d1fb470667453ec24a2ba685f60a0vanjeff                        EFI_PXE_BASE_CODE_TFTP_READ_FILE,
2850319075ff6e1d1fb470667453ec24a2ba685f60a0vanjeff                        Buffer,
2851319075ff6e1d1fb470667453ec24a2ba685f60a0vanjeff                        FALSE,
2852319075ff6e1d1fb470667453ec24a2ba685f60a0vanjeff                        &TmpBufSize,
2853fa6d3ee4913eaf3b0fd9ddb8a4e3b618584bd965ljin                        &Private->BlockSize,
2854319075ff6e1d1fb470667453ec24a2ba685f60a0vanjeff                        &Private->ServerIp,
2855319075ff6e1d1fb470667453ec24a2ba685f60a0vanjeff                        (UINT8 *) Private->BootFileName,
2856319075ff6e1d1fb470667453ec24a2ba685f60a0vanjeff                        NULL,
2857319075ff6e1d1fb470667453ec24a2ba685f60a0vanjeff                        FALSE
2858319075ff6e1d1fb470667453ec24a2ba685f60a0vanjeff                        );
285939941daf90572c818328de50fbcb7a5e5e0e7eb2gikidy    } else if (TmpBufSize > 0) {
2860dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff      *BufferSize = (UINTN) TmpBufSize;
2861319075ff6e1d1fb470667453ec24a2ba685f60a0vanjeff      Status      = EFI_BUFFER_TOO_SMALL;
2862dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    }
2863319075ff6e1d1fb470667453ec24a2ba685f60a0vanjeff  } else if (Buffer == NULL || Private->FileSize > *BufferSize) {
2864dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    *BufferSize = Private->FileSize;
2865dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    Status      = EFI_BUFFER_TOO_SMALL;
2866dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  } else {
2867dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    //
2868dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    // Download the file.
2869dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    //
2870dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    TmpBufSize = (UINT64) (*BufferSize);
2871dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    Status = PxeBc->Mtftp (
2872dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff                      PxeBc,
2873dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff                      EFI_PXE_BASE_CODE_TFTP_READ_FILE,
2874dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff                      Buffer,
2875dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff                      FALSE,
2876dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff                      &TmpBufSize,
2877fa6d3ee4913eaf3b0fd9ddb8a4e3b618584bd965ljin                      &Private->BlockSize,
2878dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff                      &Private->ServerIp,
2879dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff                      (UINT8 *) Private->BootFileName,
2880dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff                      NULL,
2881dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff                      FALSE
2882dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff                      );
2883dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  }
2884dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  //
2885dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  // If we added a callback protocol, now is the time to remove it.
2886dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  //
2887dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  if (NewMakeCallback) {
2888dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
2889dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    NewMakeCallback = FALSE;
2890dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
2891dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    PxeBc->SetParameters (PxeBc, NULL, NULL, NULL, NULL, &NewMakeCallback);
2892dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
2893dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    gBS->UninstallProtocolInterface (
2894dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff          Private->Controller,
2895dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff          &gEfiPxeBaseCodeCallbackProtocolGuid,
2896dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff          &Private->LoadFileCallback
2897dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff          );
2898dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  }
2899619eff3f290c7e893d858c16e70b641471a5a704vanjeff
2900dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  //
2901dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  // Check download status
2902dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  //
2903619eff3f290c7e893d858c16e70b641471a5a704vanjeff  if (Status == EFI_SUCCESS) {
29046ee21b60a8adb82452a15afef4bf4938e3eec4b0vanjeff    //
290530268f29bd38a8e07b9914a1be00583c172c4c40Fu Siyuan    // The DHCP4 can have only one configured child instance so we need to stop
290630268f29bd38a8e07b9914a1be00583c172c4c40Fu Siyuan    // reset the DHCP4 child before we return. Otherwise the other programs which
290730268f29bd38a8e07b9914a1be00583c172c4c40Fu Siyuan    // also need to use DHCP4 will be impacted.
29086ee21b60a8adb82452a15afef4bf4938e3eec4b0vanjeff    // The functionality of PXE Base Code protocol will not be stopped,
29096ee21b60a8adb82452a15afef4bf4938e3eec4b0vanjeff    // when downloading is successfully.
29106ee21b60a8adb82452a15afef4bf4938e3eec4b0vanjeff    //
291130268f29bd38a8e07b9914a1be00583c172c4c40Fu Siyuan    Private->Dhcp4->Stop (Private->Dhcp4);
291230268f29bd38a8e07b9914a1be00583c172c4c40Fu Siyuan    Private->Dhcp4->Configure (Private->Dhcp4, NULL);
29138792362f22e4fac66aeec04b13b7a6b70cb571e9vanjeff    return EFI_SUCCESS;
2914dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
2915619eff3f290c7e893d858c16e70b641471a5a704vanjeff  } else if (Status == EFI_BUFFER_TOO_SMALL) {
2916dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    if (Buffer != NULL) {
2917dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff      AsciiPrint ("PXE-E05: Download buffer is smaller than requested file.\n");
2918dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    } else {
2919ee6e8714a08e845e3d4b46c022e7da717dd7fbacvanjeff      //
2920ee6e8714a08e845e3d4b46c022e7da717dd7fbacvanjeff      // The functionality of PXE Base Code protocol will not be stopped.
2921ee6e8714a08e845e3d4b46c022e7da717dd7fbacvanjeff      //
2922dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff      return Status;
2923dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    }
2924dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
2925619eff3f290c7e893d858c16e70b641471a5a704vanjeff  } else if (Status == EFI_DEVICE_ERROR) {
2926dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    AsciiPrint ("PXE-E07: Network device error.\n");
2927dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
2928619eff3f290c7e893d858c16e70b641471a5a704vanjeff  } else if (Status == EFI_OUT_OF_RESOURCES) {
2929dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    AsciiPrint ("PXE-E09: Could not allocate I/O buffers.\n");
2930dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
2931619eff3f290c7e893d858c16e70b641471a5a704vanjeff  } else if (Status == EFI_NO_MEDIA) {
2932dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    AsciiPrint ("PXE-E12: Could not detect network connection.\n");
2933dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
2934619eff3f290c7e893d858c16e70b641471a5a704vanjeff  } else if (Status == EFI_NO_RESPONSE) {
2935dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    AsciiPrint ("PXE-E16: No offer received.\n");
2936dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
2937619eff3f290c7e893d858c16e70b641471a5a704vanjeff  } else if (Status == EFI_TIMEOUT) {
2938dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    AsciiPrint ("PXE-E18: Server response timeout.\n");
2939dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
2940619eff3f290c7e893d858c16e70b641471a5a704vanjeff  } else if (Status == EFI_ABORTED) {
2941dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    AsciiPrint ("PXE-E21: Remote boot cancelled.\n");
2942dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
2943619eff3f290c7e893d858c16e70b641471a5a704vanjeff  } else if (Status == EFI_ICMP_ERROR) {
2944dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    AsciiPrint ("PXE-E22: Client received ICMP error from server.\n");
2945dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
2946619eff3f290c7e893d858c16e70b641471a5a704vanjeff  } else if (Status == EFI_TFTP_ERROR) {
2947dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    AsciiPrint ("PXE-E23: Client received TFTP error from server.\n");
2948dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
2949619eff3f290c7e893d858c16e70b641471a5a704vanjeff  } else {
2950dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff    AsciiPrint ("PXE-E99: Unexpected network error.\n");
2951dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  }
2952dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
2953dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  PxeBc->Stop (PxeBc);
2954dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
2955dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff  return Status;
2956dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff}
2957dc361cc5a04657ddc8c74bd8f044f7ad30c4118avanjeff
2958434ce3feca7f5a430db3d5853c54a06343d02ed2vanjeffEFI_LOAD_FILE_PROTOCOL  mLoadFileProtocolTemplate = { EfiPxeLoadFile };
2959434ce3feca7f5a430db3d5853c54a06343d02ed2vanjeff
2960