]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/Network/Ip4ConfigDxe/NicIp4Variable.c
Scrubbed some code for Ip4ConfigDxe.
[mirror_edk2.git] / MdeModulePkg / Universal / Network / Ip4ConfigDxe / NicIp4Variable.c
1 /** @file
2 Routines used to operate the Ip4 configure variable
3
4 Copyright (c) 2006 - 2008, Intel Corporation.<BR>
5 All rights reserved. This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at<BR>
8 http://opensource.org/licenses/bsd-license.php
9
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12
13 **/
14
15 #include <Uefi.h>
16
17 #include <Library/NetLib.h>
18 #include <Library/DebugLib.h>
19 #include <Library/BaseMemoryLib.h>
20 #include <Library/MemoryAllocationLib.h>
21 #include <Library/UefiBootServicesTableLib.h>
22 #include <Library/UefiRuntimeServicesTableLib.h>
23
24 #include "NicIp4Variable.h"
25
26
27 /**
28 Check whether the configure parameter is valid.
29
30 @param NicConfig The configure parameter to check
31
32 @return TRUE if the parameter is valid for the interface, otherwise FALSE.
33
34 **/
35 BOOLEAN
36 Ip4ConfigIsValid (
37 IN NIC_IP4_CONFIG_INFO *NicConfig
38 )
39 {
40 EFI_IP4_IPCONFIG_DATA *IpConfig;
41 IP4_ADDR Station;
42 IP4_ADDR Netmask;
43 IP4_ADDR Gateway;
44 UINT32 Index;
45
46 IpConfig = &NicConfig->Ip4Info;
47
48 if (NicConfig->Source == IP4_CONFIG_SOURCE_STATIC) {
49 //
50 // Validate that the addresses are unicast and mask
51 // is properly formated
52 //
53 Station = EFI_NTOHL (IpConfig->StationAddress);
54 Netmask = EFI_NTOHL (IpConfig->SubnetMask);
55
56 if ((Netmask == 0) || !IP4_IS_VALID_NETMASK (Netmask) ||
57 (Station == 0) || !Ip4IsUnicast (Station, Netmask)) {
58 return FALSE;
59 }
60
61 //
62 // Validate that the next hops are on the connected network
63 // or that is a direct route (Gateway == 0).
64 //
65 for (Index = 0; Index < IpConfig->RouteTableSize; Index++) {
66 Gateway = EFI_NTOHL (IpConfig->RouteTable[Index].GatewayAddress);
67
68 if ((Gateway != 0) && (!IP4_NET_EQUAL (Station, Gateway, Netmask) ||
69 !Ip4IsUnicast (Gateway, Netmask))) {
70 return FALSE;
71 }
72 }
73
74 return TRUE;
75 }
76
77 //
78 // return false if it is an unkown configure source. Valid
79 // sources are static and dhcp.
80 //
81 return (BOOLEAN) (NicConfig->Source == IP4_CONFIG_SOURCE_DHCP);
82 }
83
84
85
86 /**
87 Read the ip4 configure variable from the EFI variable.
88
89 None
90
91 @return The IP4 configure read if it is there and is valid, otherwise NULL
92
93 **/
94 IP4_CONFIG_VARIABLE *
95 Ip4ConfigReadVariable (
96 VOID
97 )
98 {
99 IP4_CONFIG_VARIABLE *Variable;
100 EFI_STATUS Status;
101 UINTN Size;
102 UINT16 CheckSum;
103
104 //
105 // Get the size of variable, then allocate a buffer to read the variable.
106 //
107 Size = 0;
108 Variable = NULL;
109 Status = gRT->GetVariable (
110 EFI_NIC_IP4_CONFIG_VARIABLE,
111 &gEfiNicIp4ConfigVariableGuid,
112 NULL,
113 &Size,
114 NULL
115 );
116
117 if (Status != EFI_BUFFER_TOO_SMALL) {
118 return NULL;
119 }
120
121 if (Size < sizeof (IP4_CONFIG_VARIABLE)) {
122 goto REMOVE_VARIABLE;
123 }
124
125 Variable = AllocatePool (Size);
126
127 if (Variable == NULL) {
128 return NULL;
129 }
130
131 Status = gRT->GetVariable (
132 EFI_NIC_IP4_CONFIG_VARIABLE,
133 &gEfiNicIp4ConfigVariableGuid,
134 NULL,
135 &Size,
136 Variable
137 );
138
139 if (EFI_ERROR (Status)) {
140 goto ON_ERROR;
141 }
142
143 //
144 // Verify the checksum, variable size and count
145 //
146 CheckSum = (UINT16) (~NetblockChecksum ((UINT8 *) Variable, (UINT32)Size));
147
148 if ((CheckSum != 0) || (Size != Variable->Len)) {
149 goto REMOVE_VARIABLE;
150 }
151
152 if ((Variable->Count < 1) || (Variable->Count > MAX_IP4_CONFIG_IN_VARIABLE)) {
153 goto REMOVE_VARIABLE;
154 }
155
156 return Variable;
157
158 REMOVE_VARIABLE:
159 Ip4ConfigWriteVariable (NULL);
160
161 ON_ERROR:
162 if (Variable != NULL) {
163 gBS->FreePool (Variable);
164 }
165
166 return NULL;
167 }
168
169
170 /**
171 Write the IP4 configure variable to the NVRAM. If Config
172 is NULL, remove the variable.
173
174 @param Config The IP4 configure data to write
175
176 @retval EFI_SUCCESS The variable is written to the NVRam
177 @retval Others Failed to write the variable.
178
179 **/
180 EFI_STATUS
181 Ip4ConfigWriteVariable (
182 IN IP4_CONFIG_VARIABLE *Config OPTIONAL
183 )
184 {
185 EFI_STATUS Status;
186
187 Status = gRT->SetVariable (
188 EFI_NIC_IP4_CONFIG_VARIABLE,
189 &gEfiNicIp4ConfigVariableGuid,
190 IP4_CONFIG_VARIABLE_ATTRIBUTES,
191 (Config == NULL) ? 0 : Config->Len,
192 Config
193 );
194
195 return Status;
196 }
197
198
199 /**
200 Locate the IP4 configure parameters from the variable.If a
201 configuration is found, copy it to a newly allocated block
202 of memory to avoid the alignment problem. Caller should
203 release the memory after use.
204
205 @param Variable The IP4 configure variable to search in
206 @param NicAddr The interface address to check
207
208 @return The point to the NIC's IP4 configure info if it is found
209 @return in the IP4 variable, otherwise NULL.
210
211 **/
212 NIC_IP4_CONFIG_INFO *
213 Ip4ConfigFindNicVariable (
214 IN IP4_CONFIG_VARIABLE *Variable,
215 IN NIC_ADDR *NicAddr
216 )
217 {
218 NIC_IP4_CONFIG_INFO Temp;
219 NIC_IP4_CONFIG_INFO *Config;
220 UINT32 Index;
221 UINT8 *Cur;
222 UINT32 Len;
223
224 Cur = (UINT8*)&Variable->ConfigInfo;
225
226 for (Index = 0; Index < Variable->Count; Index++) {
227 //
228 // Copy the data to Temp to avoid the alignment problems
229 //
230 CopyMem (&Temp, Cur, sizeof (NIC_IP4_CONFIG_INFO));
231 Len = SIZEOF_NIC_IP4_CONFIG_INFO (&Temp);
232
233 //
234 // Found the matching configuration parameters, allocate
235 // a block of memory then copy it out.
236 //
237 if (NIC_ADDR_EQUAL (&Temp.NicAddr, NicAddr)) {
238 Config = AllocatePool (Len);
239
240 if (Config == NULL) {
241 return NULL;
242 }
243
244 CopyMem (Config, Cur, Len);
245 Ip4ConfigFixRouteTablePointer (&Config->Ip4Info);
246 return Config;
247 }
248
249 Cur += Len;
250 }
251
252 return NULL;
253 }
254
255
256 /**
257 Modify the configuration parameter for the NIC in the variable.
258 If Config is NULL, old configuration will be remove from the new
259 variable. Otherwise, append it or replace the old one.
260
261 @param Variable The IP4 variable to change
262 @param NicAddr The interface to search
263 @param Config The new configuration parameter (NULL to remove the old)
264
265 @return The new IP4_CONFIG_VARIABLE variable if the new variable has at
266 @return least one NIC configure and no EFI_OUT_OF_RESOURCES failure.
267 @return Return NULL either because failed to locate memory for new variable
268 @return or the only NIC configure is removed from the Variable.
269
270 **/
271 IP4_CONFIG_VARIABLE *
272 Ip4ConfigModifyVariable (
273 IN IP4_CONFIG_VARIABLE *Variable, OPTIONAL
274 IN NIC_ADDR *NicAddr,
275 IN NIC_IP4_CONFIG_INFO *Config OPTIONAL
276 )
277 {
278 NIC_IP4_CONFIG_INFO Temp;
279 NIC_IP4_CONFIG_INFO *Old;
280 IP4_CONFIG_VARIABLE *NewVar;
281 UINT32 Len;
282 UINT32 TotalLen;
283 UINT32 Count;
284 UINT8 *Next;
285 UINT8 *Cur;
286 UINT32 Index;
287
288 ASSERT ((Variable != NULL) || (Config != NULL));
289
290 //
291 // Compute the total length
292 //
293 if (Variable != NULL) {
294 //
295 // Variable != NULL, then Config can be NULL or not. and so is
296 // the Old. If old configure exists, it is removed from the
297 // Variable. New configure is append to the variable.
298 //
299 //
300 Count = Variable->Count;
301 Cur = (UINT8 *)&Variable->ConfigInfo;
302 TotalLen = Variable->Len;
303
304 Old = Ip4ConfigFindNicVariable (Variable, NicAddr);
305
306 if (Old != NULL) {
307 TotalLen -= SIZEOF_NIC_IP4_CONFIG_INFO (Old);
308 gBS->FreePool (Old);
309 }
310
311 if (Config != NULL) {
312 TotalLen += SIZEOF_NIC_IP4_CONFIG_INFO (Config);
313 }
314
315 //
316 // Return NULL if the only NIC_IP4_CONFIG_INFO is being removed.
317 //
318 if (TotalLen < sizeof (IP4_CONFIG_VARIABLE)) {
319 return NULL;
320 }
321
322 } else {
323 //
324 // Variable == NULL and Config != NULL, Create a new variable with
325 // this NIC configure.
326 //
327 Count = 0;
328 Cur = NULL;
329 TotalLen = sizeof (IP4_CONFIG_VARIABLE) - sizeof (NIC_IP4_CONFIG_INFO)
330 + SIZEOF_NIC_IP4_CONFIG_INFO (Config);
331 }
332
333 ASSERT (TotalLen >= sizeof (IP4_CONFIG_VARIABLE));
334
335 NewVar = AllocateZeroPool (TotalLen);
336
337 if (NewVar == NULL) {
338 return NULL;
339 }
340
341 NewVar->Len = TotalLen;
342
343 //
344 // Copy the other configure parameters from the old variable
345 //
346 Next = (UINT8 *)&NewVar->ConfigInfo;
347
348 for (Index = 0; Index < Count; Index++) {
349 CopyMem (&Temp, Cur, sizeof (NIC_IP4_CONFIG_INFO));
350 Len = SIZEOF_NIC_IP4_CONFIG_INFO (&Temp);
351
352 if (!NIC_ADDR_EQUAL (&Temp.NicAddr, NicAddr)) {
353 CopyMem (Next, Cur, Len);
354 Next += Len;
355 NewVar->Count++;
356 }
357
358 Cur += Len;
359 }
360
361 //
362 // Append the new configure if it isn't NULL.
363 //
364 Len = 0;
365
366 if (Config != NULL) {
367 Len = SIZEOF_NIC_IP4_CONFIG_INFO (Config);
368
369 CopyMem (Next, Config, Len);
370 NewVar->Count++;
371 }
372
373 ASSERT (Next + Len == (UINT8 *) NewVar + TotalLen);
374
375 NewVar->CheckSum = (UINT16) (~NetblockChecksum ((UINT8 *) NewVar, TotalLen));
376 return NewVar;
377 }
378
379 /**
380 Fix the RouteTable pointer in an EFI_IP4_IPCONFIG_DATA structure.
381
382 The pointer is set to be immediately follow the ConfigData if there're entries
383 in the RouteTable. Otherwise it is set to NULL.
384
385 @param ConfigData The IP4 IP configure data.
386
387 **/
388 VOID
389 Ip4ConfigFixRouteTablePointer (
390 IN EFI_IP4_IPCONFIG_DATA *ConfigData
391 )
392 {
393 //
394 // The memory used for route table entries must immediately follow
395 // the ConfigData and be not packed.
396 //
397 if (ConfigData->RouteTableSize > 0) {
398 ConfigData->RouteTable = (EFI_IP4_ROUTE_TABLE *) (ConfigData + 1);
399 } else {
400 ConfigData->RouteTable = NULL;
401 }
402 }
403