1772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff/** @file
20c323d071d8951fe0c8f41fad08939722d436b12jgong  Implementation of EFI Address Resolution Protocol (ARP) Protocol interface functions.
3c6d0ee4b41589bcf5806b457bb3de596d455d4a1jgong
4e5eed7d3641d71d7ea539e5379ea9c6a5cd97004hhtianCopyright (c) 2006 - 2009, Intel Corporation. All rights reserved.<BR>
5e5eed7d3641d71d7ea539e5379ea9c6a5cd97004hhtianThis program and the accompanying materials
6772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeffare licensed and made available under the terms and conditions of the BSD License
7c6d0ee4b41589bcf5806b457bb3de596d455d4a1jgongwhich accompanies this distribution.  The full text of the license may be found at<BR>
8772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeffhttp://opensource.org/licenses/bsd-license.php
9772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff
10772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeffTHE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeffWITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff
13772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff**/
14772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff
15772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff#include "ArpImpl.h"
16772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff
17772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff
18772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff/**
19772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  This function is used to assign a station address to the ARP cache for this instance
200c323d071d8951fe0c8f41fad08939722d436b12jgong  of the ARP driver.
210c323d071d8951fe0c8f41fad08939722d436b12jgong
220c323d071d8951fe0c8f41fad08939722d436b12jgong  Each ARP instance has one station address. The EFI_ARP_PROTOCOL driver will
230c323d071d8951fe0c8f41fad08939722d436b12jgong  respond to ARP requests that match this registered station address. A call to
240c323d071d8951fe0c8f41fad08939722d436b12jgong  this function with the ConfigData field set to NULL will reset this ARP instance.
25c6d0ee4b41589bcf5806b457bb3de596d455d4a1jgong
26c6d0ee4b41589bcf5806b457bb3de596d455d4a1jgong  Once a protocol type and station address have been assigned to this ARP instance,
27c6d0ee4b41589bcf5806b457bb3de596d455d4a1jgong  all the following ARP functions will use this information. Attempting to change
28c6d0ee4b41589bcf5806b457bb3de596d455d4a1jgong  the protocol type or station address to a configured ARP instance will result in errors.
29772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff
30772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  @param  This                   Pointer to the EFI_ARP_PROTOCOL instance.
31772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  @param  ConfigData             Pointer to the EFI_ARP_CONFIG_DATA structure.
32772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff
33772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  @retval EFI_SUCCESS            The new station address was successfully
34772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff                                 registered.
35772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  @retval EFI_INVALID_PARAMETER  One or more of the following conditions is TRUE:
36772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff                                 This is NULL. SwAddressLength is zero when
37772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff                                 ConfigData is not NULL. StationAddress is NULL
38772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff                                 when ConfigData is not NULL.
39772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  @retval EFI_ACCESS_DENIED      The SwAddressType, SwAddressLength, or
40772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff                                 StationAddress is different from the one that is
41772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff                                 already registered.
42772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  @retval EFI_OUT_OF_RESOURCES   Storage for the new StationAddress could not be
43772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff                                 allocated.
44772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff
45772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff**/
46772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeffEFI_STATUS
47772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeffEFIAPI
48772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeffArpConfigure (
49772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  IN EFI_ARP_PROTOCOL     *This,
50772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  IN EFI_ARP_CONFIG_DATA  *ConfigData OPTIONAL
51772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  )
52772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff{
53772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  EFI_STATUS         Status;
54772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  ARP_INSTANCE_DATA  *Instance;
5536ee91ca3661d3d020a7841aacbf858d885c4728vanjeff  EFI_TPL            OldTpl;
56772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff
57772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  if (This == NULL) {
58772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff    return EFI_INVALID_PARAMETER;
59772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  }
60772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff
61772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  if ((ConfigData != NULL) &&
62772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff    ((ConfigData->SwAddressLength == 0) ||
63772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff    (ConfigData->StationAddress == NULL) ||
64772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff    (ConfigData->SwAddressType <= 1500))) {
65772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff    return EFI_INVALID_PARAMETER;
66772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  }
67772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff
68772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  Instance = ARP_INSTANCE_DATA_FROM_THIS (This);
69772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff
70e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff  OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
71772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff
72772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  //
73772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  // Configure this instance, the ConfigData has already passed the basic checks.
74772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  //
75772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  Status = ArpConfigureInstance (Instance, ConfigData);
76772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff
77e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff  gBS->RestoreTPL (OldTpl);
78772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff
79772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  return Status;
80772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff}
81772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff
82772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff
83772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff/**
84772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  This function is used to insert entries into the ARP cache.
85772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff
86c6d0ee4b41589bcf5806b457bb3de596d455d4a1jgong  ARP cache entries are typically inserted and updated by network protocol drivers
87c6d0ee4b41589bcf5806b457bb3de596d455d4a1jgong  as network traffic is processed. Most ARP cache entries will time out and be
88c6d0ee4b41589bcf5806b457bb3de596d455d4a1jgong  deleted if the network traffic stops. ARP cache entries that were inserted
89c6d0ee4b41589bcf5806b457bb3de596d455d4a1jgong  by the Add() function may be static (will not time out) or dynamic (will time out).
90c6d0ee4b41589bcf5806b457bb3de596d455d4a1jgong  Default ARP cache timeout values are not covered in most network protocol
91c6d0ee4b41589bcf5806b457bb3de596d455d4a1jgong  specifications (although RFC 1122 comes pretty close) and will only be
92c6d0ee4b41589bcf5806b457bb3de596d455d4a1jgong  discussed in general in this specification. The timeout values that are
93c6d0ee4b41589bcf5806b457bb3de596d455d4a1jgong  used in the EFI Sample Implementation should be used only as a guideline.
94c6d0ee4b41589bcf5806b457bb3de596d455d4a1jgong  Final product implementations of the EFI network stack should be tuned for
95c6d0ee4b41589bcf5806b457bb3de596d455d4a1jgong  their expected network environments.
96c6d0ee4b41589bcf5806b457bb3de596d455d4a1jgong
97772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  @param  This                   Pointer to the EFI_ARP_PROTOCOL instance.
98772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  @param  DenyFlag               Set to TRUE if this entry is a deny entry. Set to
99772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff                                 FALSE if this  entry is a normal entry.
100772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  @param  TargetSwAddress        Pointer to a protocol address to add (or deny).
101772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff                                 May be set to NULL if DenyFlag is TRUE.
102772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  @param  TargetHwAddress        Pointer to a hardware address to add (or deny).
103772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff                                 May be set to NULL if DenyFlag is TRUE.
104772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  @param  TimeoutValue           Time in 100-ns units that this entry will remain
105772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff                                 in the ARP cache. A value of zero means that the
106772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff                                 entry is permanent. A nonzero value will override
107772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff                                 the one given by Configure() if the entry to be
108772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff                                 added is a dynamic entry.
109772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  @param  Overwrite              If TRUE, the matching cache entry will be
110772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff                                 overwritten with the supplied parameters. If
111772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff                                 FALSE, EFI_ACCESS_DENIED is returned if the
112772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff                                 corresponding cache entry already exists.
113772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff
114772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  @retval EFI_SUCCESS            The entry has been added or updated.
115772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  @retval EFI_INVALID_PARAMETER  One or more of the following conditions is TRUE:
116772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff                                 This is NULL. DenyFlag is FALSE and
117772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff                                 TargetHwAddress is NULL. DenyFlag is FALSE and
118772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff                                 TargetSwAddress is NULL. TargetHwAddress is NULL
119772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff                                 and TargetSwAddress is NULL. Both TargetSwAddress
120772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff                                 and TargetHwAddress are not NULL when DenyFlag is
121772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff                                 TRUE.
122772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  @retval EFI_OUT_OF_RESOURCES   The new ARP cache entry could not be allocated.
123772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  @retval EFI_ACCESS_DENIED      The ARP cache entry already exists and Overwrite
124772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff                                 is not true.
125772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  @retval EFI_NOT_STARTED        The ARP driver instance has not been configured.
126772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff
127772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff**/
128772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeffEFI_STATUS
129772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeffEFIAPI
130772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeffArpAdd (
131772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  IN EFI_ARP_PROTOCOL  *This,
132772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  IN BOOLEAN           DenyFlag,
133772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  IN VOID              *TargetSwAddress OPTIONAL,
134772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  IN VOID              *TargetHwAddress OPTIONAL,
135772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  IN UINT32            TimeoutValue,
136772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  IN BOOLEAN           Overwrite
137772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  )
138772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff{
139772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  EFI_STATUS               Status;
140772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  ARP_INSTANCE_DATA        *Instance;
141772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  ARP_SERVICE_DATA         *ArpService;
142772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  ARP_CACHE_ENTRY          *CacheEntry;
143772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  EFI_SIMPLE_NETWORK_MODE  *SnpMode;
144772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  NET_ARP_ADDRESS          MatchAddress[2];
14536ee91ca3661d3d020a7841aacbf858d885c4728vanjeff  EFI_TPL                  OldTpl;
146772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff
147772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  if (This == NULL) {
148772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff    return EFI_INVALID_PARAMETER;
149772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  }
150772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff
151772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  if (((!DenyFlag) && ((TargetHwAddress == NULL) || (TargetSwAddress == NULL))) ||
152772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff    (DenyFlag && (TargetHwAddress != NULL) && (TargetSwAddress != NULL)) ||
153772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff    ((TargetHwAddress == NULL) && (TargetSwAddress == NULL))) {
154772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff    return EFI_INVALID_PARAMETER;
155772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  }
156772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff
157772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  Instance = ARP_INSTANCE_DATA_FROM_THIS (This);
158772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff
159772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  if (!Instance->Configured) {
160772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff    return EFI_NOT_STARTED;
161772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  }
162772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff
163772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  Status     = EFI_SUCCESS;
164772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  ArpService = Instance->ArpService;
165772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  SnpMode    = &Instance->ArpService->SnpMode;
166772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff
167772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  //
168772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  // Fill the hardware address part in the MatchAddress.
169772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  //
170772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  MatchAddress[Hardware].Type       = SnpMode->IfType;
171772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  MatchAddress[Hardware].Length     = (UINT8) SnpMode->HwAddressSize;
172772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  MatchAddress[Hardware].AddressPtr = TargetHwAddress;
173772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff
174772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  //
175772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  // Fill the software address part in the MatchAddress.
176772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  //
177772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  MatchAddress[Protocol].Type       = Instance->ConfigData.SwAddressType;
178772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  MatchAddress[Protocol].Length     = Instance->ConfigData.SwAddressLength;
179772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  MatchAddress[Protocol].AddressPtr = TargetSwAddress;
180772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff
181e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff  OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
182772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff
183772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  //
184772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  // See whether the entry to add exists. Check the DeinedCacheTable first.
185772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  //
186772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  CacheEntry = ArpFindDeniedCacheEntry (
187772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff                 ArpService,
188772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff                 &MatchAddress[Protocol],
189772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff                 &MatchAddress[Hardware]
190772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff                 );
191772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff
192772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  if (CacheEntry == NULL) {
193772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff    //
194772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff    // Check the ResolvedCacheTable
195772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff    //
196772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff    CacheEntry = ArpFindNextCacheEntryInTable (
197772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff                   &ArpService->ResolvedCacheTable,
198772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff                   NULL,
199772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff                   ByBoth,
200772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff                   &MatchAddress[Protocol],
201772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff                   &MatchAddress[Hardware]
202772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff                   );
203772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  }
204772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff
205772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  if ((CacheEntry != NULL) && !Overwrite) {
206772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff    //
207772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff    // The entry to add exists, if not Overwirte, deny this add request.
208772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff    //
209772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff    Status = EFI_ACCESS_DENIED;
210772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff    goto UNLOCK_EXIT;
211772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  }
212772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff
213772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  if ((CacheEntry == NULL) && (TargetSwAddress != NULL)) {
214772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff    //
215772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff    // Check whether there are pending requests matching the entry to be added.
216772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff    //
217772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff    CacheEntry = ArpFindNextCacheEntryInTable (
218772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff                   &ArpService->PendingRequestTable,
219772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff                   NULL,
220772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff                   ByProtoAddress,
221772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff                   &MatchAddress[Protocol],
222772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff                   NULL
223772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff                   );
224772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  }
225772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff
226772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  if (CacheEntry != NULL) {
227772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff    //
228772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff    // Remove it from the Table.
229772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff    //
230e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff    RemoveEntryList (&CacheEntry->List);
231772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  } else {
232772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff    //
233772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff    // It's a new entry, allocate memory for the entry.
234772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff    //
235772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff    CacheEntry = ArpAllocCacheEntry (Instance);
236772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff
237772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff    if (CacheEntry == NULL) {
238e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff      DEBUG ((EFI_D_ERROR, "ArpAdd: Failed to allocate pool for CacheEntry.\n"));
239772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff      Status = EFI_OUT_OF_RESOURCES;
240772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff      goto UNLOCK_EXIT;
241772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff    }
242772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  }
243772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff
244772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  //
245772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  // Overwrite these parameters.
246772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  //
247772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  CacheEntry->DefaultDecayTime = TimeoutValue;
248772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  CacheEntry->DecayTime        = TimeoutValue;
249772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff
250772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  //
251772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  // Fill in the addresses.
252772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  //
253772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  ArpFillAddressInCacheEntry (
254772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff    CacheEntry,
255772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff    &MatchAddress[Hardware],
256772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff    &MatchAddress[Protocol]
257772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff    );
258772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff
259772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  //
260772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  // Inform the user if there is any.
261772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  //
262772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  ArpAddressResolved (CacheEntry, NULL, NULL);
263772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff
264772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  //
265772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  // Add this CacheEntry to the corresponding CacheTable.
266772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  //
267772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  if (DenyFlag) {
268e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff    InsertHeadList (&ArpService->DeniedCacheTable, &CacheEntry->List);
269772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  } else {
270e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff    InsertHeadList (&ArpService->ResolvedCacheTable, &CacheEntry->List);
271772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  }
272772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff
273772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeffUNLOCK_EXIT:
274772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff
275e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff  gBS->RestoreTPL (OldTpl);
276772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff
277772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  return Status;
278772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff}
279772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff
280772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff
281772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff/**
282772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  This function searches the ARP cache for matching entries and allocates a buffer into
283772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  which those entries are copied.
284c6d0ee4b41589bcf5806b457bb3de596d455d4a1jgong
285c6d0ee4b41589bcf5806b457bb3de596d455d4a1jgong  The first part of the allocated buffer is EFI_ARP_FIND_DATA, following which
286c6d0ee4b41589bcf5806b457bb3de596d455d4a1jgong  are protocol address pairs and hardware address pairs.
287c6d0ee4b41589bcf5806b457bb3de596d455d4a1jgong  When finding a specific protocol address (BySwAddress is TRUE and AddressBuffer
288c6d0ee4b41589bcf5806b457bb3de596d455d4a1jgong  is not NULL), the ARP cache timeout for the found entry is reset if Refresh is
289c6d0ee4b41589bcf5806b457bb3de596d455d4a1jgong  set to TRUE. If the found ARP cache entry is a permanent entry, it is not
290c6d0ee4b41589bcf5806b457bb3de596d455d4a1jgong  affected by Refresh.
291c6d0ee4b41589bcf5806b457bb3de596d455d4a1jgong
292772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  @param  This                   Pointer to the EFI_ARP_PROTOCOL instance.
293772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  @param  BySwAddress            Set to TRUE to look for matching software protocol
294772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff                                 addresses. Set to FALSE to look for matching
295772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff                                 hardware protocol addresses.
296772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  @param  AddressBuffer          Pointer to address buffer. Set to NULL to match
297772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff                                 all addresses.
298772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  @param  EntryLength            The size of an entry in the entries buffer.
299772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  @param  EntryCount             The number of ARP cache entries that are found by
300772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff                                 the specified criteria.
301772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  @param  Entries                Pointer to the buffer that will receive the ARP
302772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff                                 cache entries.
303772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  @param  Refresh                Set to TRUE to refresh the timeout value of the
304772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff                                 matching ARP cache entry.
305772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff
306772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  @retval EFI_SUCCESS            The requested ARP cache entries were copied into
307772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff                                 the buffer.
308772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  @retval EFI_INVALID_PARAMETER  One or more of the following conditions is TRUE:
309772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff                                 This is NULL. Both EntryCount and EntryLength are
310772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff                                 NULL, when Refresh is FALSE.
311772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  @retval EFI_NOT_FOUND          No matching entries were found.
312772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  @retval EFI_NOT_STARTED        The ARP driver instance has not been configured.
313772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff
314772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff**/
315772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeffEFI_STATUS
316772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeffEFIAPI
317772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeffArpFind (
318772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  IN EFI_ARP_PROTOCOL    *This,
319772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  IN BOOLEAN             BySwAddress,
320772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  IN VOID                *AddressBuffer OPTIONAL,
321772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  OUT UINT32             *EntryLength   OPTIONAL,
322772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  OUT UINT32             *EntryCount    OPTIONAL,
323772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  OUT EFI_ARP_FIND_DATA  **Entries      OPTIONAL,
324772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  IN BOOLEAN             Refresh
325772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  )
326772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff{
327772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  EFI_STATUS         Status;
328772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  ARP_INSTANCE_DATA  *Instance;
32936ee91ca3661d3d020a7841aacbf858d885c4728vanjeff  EFI_TPL            OldTpl;
330772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff
331772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  if ((This == NULL) ||
332772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff    (!Refresh && (EntryCount == NULL) && (EntryLength == NULL)) ||
333772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff    ((Entries != NULL) && ((EntryLength == NULL) || (EntryCount == NULL)))) {
334772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff    return EFI_INVALID_PARAMETER;
335772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  }
336772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff
337772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  Instance   = ARP_INSTANCE_DATA_FROM_THIS (This);
338772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff
339772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  if (!Instance->Configured) {
340772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff    return EFI_NOT_STARTED;
341772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  }
342772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff
343e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff  OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
344772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff
345772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  //
346772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  // All the check passed, find the cache entries now.
347772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  //
348772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  Status = ArpFindCacheEntry (
349772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff             Instance,
350772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff             BySwAddress,
351772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff             AddressBuffer,
352772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff             EntryLength,
353772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff             EntryCount,
354772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff             Entries,
355772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff             Refresh
356772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff             );
357772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff
358e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff  gBS->RestoreTPL (OldTpl);
359772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff
360772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  return Status;
361772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff}
362772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff
363772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff
364772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff/**
365772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  This function removes specified ARP cache entries.
366772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff
367772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  @param  This                   Pointer to the EFI_ARP_PROTOCOL instance.
368772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  @param  BySwAddress            Set to TRUE to delete matching protocol addresses.
369772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff                                 Set to FALSE to delete matching hardware
370772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff                                 addresses.
371772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  @param  AddressBuffer          Pointer to the address buffer that is used as a
372772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff                                 key to look for the cache entry. Set to NULL to
373772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff                                 delete all entries.
374772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff
375772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  @retval EFI_SUCCESS            The entry was removed from the ARP cache.
376772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  @retval EFI_INVALID_PARAMETER  This is NULL.
377772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  @retval EFI_NOT_FOUND          The specified deletion key was not found.
378772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  @retval EFI_NOT_STARTED        The ARP driver instance has not been configured.
379772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff
380772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff**/
381772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeffEFI_STATUS
382772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeffEFIAPI
383772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeffArpDelete (
384772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  IN EFI_ARP_PROTOCOL  *This,
385772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  IN BOOLEAN           BySwAddress,
386772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  IN VOID              *AddressBuffer OPTIONAL
387772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  )
388772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff{
389772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  ARP_INSTANCE_DATA  *Instance;
390772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  UINTN              Count;
39136ee91ca3661d3d020a7841aacbf858d885c4728vanjeff  EFI_TPL            OldTpl;
392772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff
393772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  if (This == NULL) {
394772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff    return EFI_INVALID_PARAMETER;
395772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  }
396772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff
397772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  Instance = ARP_INSTANCE_DATA_FROM_THIS (This);
398772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff
399772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  if (!Instance->Configured) {
400772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff    return EFI_NOT_STARTED;
401772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  }
402772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff
403e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff  OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
404772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff
405772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  //
406772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  // Delete the specified cache entries.
407772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  //
408772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  Count = ArpDeleteCacheEntry (Instance, BySwAddress, AddressBuffer, TRUE);
409772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff
410e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff  gBS->RestoreTPL (OldTpl);
411772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff
412772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  return (Count == 0) ? EFI_NOT_FOUND : EFI_SUCCESS;
413772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff}
414772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff
415772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff
416772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff/**
417772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  This function delete all dynamic entries from the ARP cache that match the specified
418772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  software protocol type.
419772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff
420772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  @param  This                   Pointer to the EFI_ARP_PROTOCOL instance.
421772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff
422772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  @retval EFI_SUCCESS            The cache has been flushed.
423772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  @retval EFI_INVALID_PARAMETER  This is NULL.
424772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  @retval EFI_NOT_FOUND          There are no matching dynamic cache entries.
425772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  @retval EFI_NOT_STARTED        The ARP driver instance has not been configured.
426772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff
427772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff**/
428772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeffEFI_STATUS
429772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeffEFIAPI
430772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeffArpFlush (
431772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  IN EFI_ARP_PROTOCOL  *This
432772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  )
433772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff{
434772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  ARP_INSTANCE_DATA  *Instance;
435772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  UINTN              Count;
43636ee91ca3661d3d020a7841aacbf858d885c4728vanjeff  EFI_TPL            OldTpl;
437772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff
438772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  if (This == NULL) {
439772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff    return EFI_INVALID_PARAMETER;
440772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  }
441772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff
442772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  Instance = ARP_INSTANCE_DATA_FROM_THIS (This);
443772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff
444772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  if (!Instance->Configured) {
445772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff    return EFI_NOT_STARTED;
446772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  }
447772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff
448e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff  OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
449772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff
450772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  //
451772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  // Delete the dynamic entries from the cache table.
452772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  //
453772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  Count = ArpDeleteCacheEntry (Instance, FALSE, NULL, FALSE);
454772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff
455e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff  gBS->RestoreTPL (OldTpl);
456772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff
457772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  return (Count == 0) ? EFI_NOT_FOUND : EFI_SUCCESS;
458772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff}
459772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff
460772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff
461772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff/**
462772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  This function tries to resolve the TargetSwAddress and optionally returns a
463772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  TargetHwAddress if it already exists in the ARP cache.
464772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff
465772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  @param  This                   Pointer to the EFI_ARP_PROTOCOL instance.
466772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  @param  TargetSwAddress        Pointer to the protocol address to resolve.
467772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  @param  ResolvedEvent          Pointer to the event that will be signaled when
468772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff                                 the address is resolved or some error occurs.
469772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  @param  TargetHwAddress        Pointer to the buffer for the resolved hardware
470772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff                                 address in network byte order.
471772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff
472772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  @retval EFI_SUCCESS            The data is copied from the ARP cache into the
473772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff                                 TargetHwAddress buffer.
474772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  @retval EFI_INVALID_PARAMETER  One or more of the following conditions is TRUE:
475772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff                                 This is NULL. TargetHwAddress is NULL.
476772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  @retval EFI_ACCESS_DENIED      The requested address is not present in the normal
477772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff                                 ARP cache but is present in the deny address list.
478772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff                                 Outgoing traffic to that address is forbidden.
479772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  @retval EFI_NOT_STARTED        The ARP driver instance has not been configured.
480772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  @retval EFI_NOT_READY          The request has been started and is not finished.
481772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff
482772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff**/
483772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeffEFI_STATUS
484772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeffEFIAPI
485772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeffArpRequest (
486772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  IN EFI_ARP_PROTOCOL  *This,
487772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  IN VOID              *TargetSwAddress OPTIONAL,
488772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  IN EFI_EVENT         ResolvedEvent    OPTIONAL,
489772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  OUT VOID             *TargetHwAddress
490772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  )
491772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff{
492772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  EFI_STATUS               Status;
493772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  ARP_INSTANCE_DATA        *Instance;
494772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  ARP_SERVICE_DATA         *ArpService;
495772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  EFI_SIMPLE_NETWORK_MODE  *SnpMode;
496772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  ARP_CACHE_ENTRY          *CacheEntry;
497772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  NET_ARP_ADDRESS          HardwareAddress;
498772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  NET_ARP_ADDRESS          ProtocolAddress;
499772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  USER_REQUEST_CONTEXT     *RequestContext;
50036ee91ca3661d3d020a7841aacbf858d885c4728vanjeff  EFI_TPL                  OldTpl;
501772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff
502772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  if ((This == NULL) || (TargetHwAddress == NULL)) {
503772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff    return EFI_INVALID_PARAMETER;
504772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  }
505772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff
506772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  Instance = ARP_INSTANCE_DATA_FROM_THIS (This);
507772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff
508772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  if (!Instance->Configured) {
509772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff    return EFI_NOT_STARTED;
510772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  }
511772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff
512772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  Status     = EFI_SUCCESS;
513772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  ArpService = Instance->ArpService;
514772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  SnpMode    = &ArpService->SnpMode;
515772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff
516772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  if ((TargetSwAddress == NULL) ||
5177bce0c5a0eb806a55d7231b05769d0efc71cdc59vanjeff    ((Instance->ConfigData.SwAddressType == IPV4_ETHER_PROTO_TYPE) &&
518772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff    IP4_IS_LOCAL_BROADCAST (*((UINT32 *)TargetSwAddress)))) {
519772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff    //
520772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff    // Return the hardware broadcast address.
521772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff    //
522e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff    CopyMem (TargetHwAddress, &SnpMode->BroadcastAddress, SnpMode->HwAddressSize);
523772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff
524772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff    goto SIGNAL_USER;
525772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  }
526772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff
5277bce0c5a0eb806a55d7231b05769d0efc71cdc59vanjeff  if ((Instance->ConfigData.SwAddressType == IPV4_ETHER_PROTO_TYPE) &&
528772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff    IP4_IS_MULTICAST (NTOHL (*((UINT32 *)TargetSwAddress)))) {
529772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff    //
530772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff    // If the software address is an IPv4 multicast address, invoke Mnp to
531772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff    // resolve the address.
532772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff    //
533772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff    Status = ArpService->Mnp->McastIpToMac (
534772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff                                ArpService->Mnp,
535772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff                                FALSE,
536772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff                                TargetSwAddress,
537772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff                                TargetHwAddress
538772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff                                );
539772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff    goto SIGNAL_USER;
540772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  }
541772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff
542772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  HardwareAddress.Type       = SnpMode->IfType;
543772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  HardwareAddress.Length     = (UINT8)SnpMode->HwAddressSize;
544772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  HardwareAddress.AddressPtr = NULL;
545772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff
546772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  ProtocolAddress.Type       = Instance->ConfigData.SwAddressType;
547772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  ProtocolAddress.Length     = Instance->ConfigData.SwAddressLength;
548772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  ProtocolAddress.AddressPtr = TargetSwAddress;
549772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff
550772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  //
551772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  // Initialize the TargetHwAddrss to a zero address.
552772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  //
553e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff  ZeroMem (TargetHwAddress, SnpMode->HwAddressSize);
554772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff
555e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff  OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
556772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff
557772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  //
558772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  // Check whether the software address is in the denied table.
559772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  //
560772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  CacheEntry = ArpFindDeniedCacheEntry (ArpService, &ProtocolAddress, NULL);
561772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  if (CacheEntry != NULL) {
562772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff    Status = EFI_ACCESS_DENIED;
563772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff    goto UNLOCK_EXIT;
564772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  }
565772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff
566772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  //
567772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  // Check whether the software address is already resolved.
568772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  //
569772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  CacheEntry = ArpFindNextCacheEntryInTable (
570772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff                 &ArpService->ResolvedCacheTable,
571772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff                 NULL,
572772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff                 ByProtoAddress,
573772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff                 &ProtocolAddress,
574772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff                 NULL
575772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff                 );
576772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  if (CacheEntry != NULL) {
577772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff    //
578772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff    // Resolved, copy the address into the user buffer.
579772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff    //
580e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff    CopyMem (
581772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff      TargetHwAddress,
582772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff      CacheEntry->Addresses[Hardware].AddressPtr,
583772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff      CacheEntry->Addresses[Hardware].Length
584772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff      );
585772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff
586772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff    goto UNLOCK_EXIT;
587772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  }
588772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff
589772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  if (ResolvedEvent == NULL) {
590772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff    Status = EFI_NOT_READY;
591772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff    goto UNLOCK_EXIT;
592772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  }
593772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff
594772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  //
595772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  // Create a request context for this arp request.
596772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  //
597e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff  RequestContext = AllocatePool (sizeof(USER_REQUEST_CONTEXT));
598772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  if (RequestContext == NULL) {
599e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff    DEBUG ((EFI_D_ERROR, "ArpRequest: Allocate memory for RequestContext failed.\n"));
600772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff
601772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff    Status = EFI_OUT_OF_RESOURCES;
602772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff    goto UNLOCK_EXIT;
603772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  }
604772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff
605772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  RequestContext->Instance         = Instance;
606772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  RequestContext->UserRequestEvent = ResolvedEvent;
607772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  RequestContext->UserHwAddrBuffer = TargetHwAddress;
608e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff  InitializeListHead (&RequestContext->List);
609772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff
610772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  //
611772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  // Check whether there is a same request.
612772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  //
613772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  CacheEntry = ArpFindNextCacheEntryInTable (
614772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff                 &ArpService->PendingRequestTable,
615772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff                 NULL,
616772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff                 ByProtoAddress,
617772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff                 &ProtocolAddress,
618772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff                 NULL
619772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff                 );
620772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  if (CacheEntry != NULL) {
621772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff
622772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff    CacheEntry->NextRetryTime = Instance->ConfigData.RetryTimeOut;
623772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff    CacheEntry->RetryCount    = Instance->ConfigData.RetryCount;
624772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  } else {
625772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff    //
626772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff    // Allocate a cache entry for this request.
627772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff    //
628772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff    CacheEntry = ArpAllocCacheEntry (Instance);
629772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff    if (CacheEntry == NULL) {
630e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff      DEBUG ((EFI_D_ERROR, "ArpRequest: Allocate memory for CacheEntry failed.\n"));
631766c7483c335931b190a78d78d62e5a5e69dc8b9xdu      FreePool (RequestContext);
632772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff
633772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff      Status = EFI_OUT_OF_RESOURCES;
634772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff      goto UNLOCK_EXIT;
635772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff    }
636772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff
637772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff    //
638772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff    // Fill the software address.
639772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff    //
640772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff    ArpFillAddressInCacheEntry (CacheEntry, &HardwareAddress, &ProtocolAddress);
641772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff
642772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff    //
643772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff    // Add this entry into the PendingRequestTable.
644772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff    //
645e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff    InsertTailList (&ArpService->PendingRequestTable, &CacheEntry->List);
646772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  }
647772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff
648772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  //
649772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  // Link this request context into the cache entry.
650772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  //
651e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff  InsertHeadList (&CacheEntry->UserRequestList, &RequestContext->List);
652772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff
653772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  //
654772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  // Send out the ARP Request frame.
655772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  //
656772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  ArpSendFrame (Instance, CacheEntry, ARP_OPCODE_REQUEST);
657772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  Status = EFI_NOT_READY;
658772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff
659772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeffUNLOCK_EXIT:
660772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff
661e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff  gBS->RestoreTPL (OldTpl);
662772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff
663772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeffSIGNAL_USER:
664772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff
665772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  if ((ResolvedEvent != NULL) && (Status == EFI_SUCCESS)) {
666772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff    gBS->SignalEvent (ResolvedEvent);
66736ee91ca3661d3d020a7841aacbf858d885c4728vanjeff
66836ee91ca3661d3d020a7841aacbf858d885c4728vanjeff    //
66936ee91ca3661d3d020a7841aacbf858d885c4728vanjeff    // Dispatch the DPC queued by the NotifyFunction of ResolvedEvent.
67036ee91ca3661d3d020a7841aacbf858d885c4728vanjeff    //
671d8d26fb207e02aa5ef57e2bcb213f9dda16166ccmdkinney    DispatchDpc ();
672772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  }
673772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff
674772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  return Status;
675772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff}
676772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff
677772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff
678772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff/**
679772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  This function aborts the previous ARP request (identified by This,  TargetSwAddress
680772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  and ResolvedEvent) that is issued by EFI_ARP_PROTOCOL.Request().
681c6d0ee4b41589bcf5806b457bb3de596d455d4a1jgong
682c6d0ee4b41589bcf5806b457bb3de596d455d4a1jgong  If the request is in the internal ARP request queue, the request is aborted
683c6d0ee4b41589bcf5806b457bb3de596d455d4a1jgong  immediately and its ResolvedEvent is signaled. Only an asynchronous address
684c6d0ee4b41589bcf5806b457bb3de596d455d4a1jgong  request needs to be canceled. If TargeSwAddress and ResolveEvent are both
685c6d0ee4b41589bcf5806b457bb3de596d455d4a1jgong  NULL, all the pending asynchronous requests that have been issued by This
686c6d0ee4b41589bcf5806b457bb3de596d455d4a1jgong  instance will be cancelled and their corresponding events will be signaled.
687c6d0ee4b41589bcf5806b457bb3de596d455d4a1jgong
688772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  @param  This                   Pointer to the EFI_ARP_PROTOCOL instance.
689772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  @param  TargetSwAddress        Pointer to the protocol address in previous
690772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff                                 request session.
691772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  @param  ResolvedEvent          Pointer to the event that is used as the
692772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff                                 notification event in previous request session.
693772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff
694772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  @retval EFI_SUCCESS            The pending request session(s) is/are aborted and
695772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff                                 corresponding event(s) is/are signaled.
696772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  @retval EFI_INVALID_PARAMETER  One or more of the following conditions is TRUE:
697772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff                                 This is NULL. TargetSwAddress is not NULL and
698772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff                                 ResolvedEvent is NULL. TargetSwAddress is NULL and
699772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff                                 ResolvedEvent is not NULL.
700772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  @retval EFI_NOT_STARTED        The ARP driver instance has not been configured.
701772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  @retval EFI_NOT_FOUND          The request is not issued by
702772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff                                 EFI_ARP_PROTOCOL.Request().
703772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff
704772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff**/
705772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeffEFI_STATUS
706772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeffEFIAPI
707772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeffArpCancel (
708772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  IN EFI_ARP_PROTOCOL  *This,
709772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  IN VOID              *TargetSwAddress OPTIONAL,
710772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  IN EFI_EVENT         ResolvedEvent    OPTIONAL
711772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  )
712772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff{
713772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  ARP_INSTANCE_DATA  *Instance;
714772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  UINTN              Count;
71536ee91ca3661d3d020a7841aacbf858d885c4728vanjeff  EFI_TPL            OldTpl;
716772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff
717772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  if ((This == NULL) ||
718772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff    ((TargetSwAddress != NULL) && (ResolvedEvent == NULL)) ||
719772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff    ((TargetSwAddress == NULL) && (ResolvedEvent != NULL))) {
720772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff    return EFI_INVALID_PARAMETER;
721772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  }
722772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff
723772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  Instance = ARP_INSTANCE_DATA_FROM_THIS (This);
724772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff
725772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  if (!Instance->Configured) {
726772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff    return EFI_NOT_STARTED;
727772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  }
728772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff
729e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff  OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
730772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff
731772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  //
732772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  // Cancel the specified request.
733772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  //
734772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  Count = ArpCancelRequest (Instance, TargetSwAddress, ResolvedEvent);
735772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff
73636ee91ca3661d3d020a7841aacbf858d885c4728vanjeff  //
73736ee91ca3661d3d020a7841aacbf858d885c4728vanjeff  // Dispatch the DPCs queued by the NotifyFunction of the events signaled
73836ee91ca3661d3d020a7841aacbf858d885c4728vanjeff  // by ArpCancleRequest.
73936ee91ca3661d3d020a7841aacbf858d885c4728vanjeff  //
740d8d26fb207e02aa5ef57e2bcb213f9dda16166ccmdkinney  DispatchDpc ();
74136ee91ca3661d3d020a7841aacbf858d885c4728vanjeff
742e48e37fce2611df7a52aff271835ff72ee396d9bvanjeff  gBS->RestoreTPL (OldTpl);
743772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff
744772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff  return (Count == 0) ? EFI_NOT_FOUND : EFI_SUCCESS;
745772db4bb33ae66fa20e39f786b5f80d107d450a5vanjeff}
746