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