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