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