]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/Network/Ip4ConfigDxe/Ip4ConfigNv.c
f09bd51744af97e0212d54b8b349fd66576ccce9
[mirror_edk2.git] / MdeModulePkg / Universal / Network / Ip4ConfigDxe / Ip4ConfigNv.c
1 /** @file
2 Helper functions for configuring or getting the parameters relating to Ip4.
3
4 Copyright (c) 2009 - 2012, Intel Corporation. All rights reserved.<BR>
5 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
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 "Ip4ConfigNv.h"
16 #include "NicIp4Variable.h"
17
18 /**
19 Calculate the prefix length of the IPv4 subnet mask.
20
21 @param[in] SubnetMask The IPv4 subnet mask.
22
23 @return The prefix length of the subnet mask.
24 @retval 0 Other errors as indicated.
25 **/
26 UINT8
27 GetSubnetMaskPrefixLength (
28 IN EFI_IPv4_ADDRESS *SubnetMask
29 )
30 {
31 UINT8 Len;
32 UINT32 ReverseMask;
33
34 //
35 // The SubnetMask is in network byte order.
36 //
37 ReverseMask = SwapBytes32 (*(UINT32 *)&SubnetMask[0]);
38
39 //
40 // Reverse it.
41 //
42 ReverseMask = ~ReverseMask;
43
44 if ((ReverseMask & (ReverseMask + 1)) != 0) {
45 return 0;
46 }
47
48 Len = 0;
49
50 while (ReverseMask != 0) {
51 ReverseMask = ReverseMask >> 1;
52 Len++;
53 }
54
55 return (UINT8) (32 - Len);
56 }
57
58 /**
59 Convert the decimal dotted IPv4 address into the binary IPv4 address.
60
61 @param[in] Str The UNICODE string.
62 @param[out] Ip The storage to return the IPv4 address.
63
64 @retval EFI_SUCCESS The binary IP address is returned in Ip.
65 @retval EFI_INVALID_PARAMETER The IP string is malformatted.
66 **/
67 EFI_STATUS
68 Ip4StrToIp (
69 IN CHAR16 *Str,
70 OUT EFI_IPv4_ADDRESS *Ip
71 )
72 {
73 UINTN Index;
74 UINTN Number;
75
76 Index = 0;
77
78 while (*Str != L'\0') {
79
80 if (Index > 3) {
81 return EFI_INVALID_PARAMETER;
82 }
83
84 Number = 0;
85 while ((*Str >= L'0') && (*Str <= L'9')) {
86 Number = Number * 10 + (*Str - L'0');
87 Str++;
88 }
89
90 if (Number > 0xFF) {
91 return EFI_INVALID_PARAMETER;
92 }
93
94 Ip->Addr[Index] = (UINT8) Number;
95
96 if ((*Str != L'\0') && (*Str != L'.')) {
97 //
98 // The current character should be either the NULL terminator or
99 // the dot delimiter.
100 //
101 return EFI_INVALID_PARAMETER;
102 }
103
104 if (*Str == L'.') {
105 //
106 // Skip the delimiter.
107 //
108 Str++;
109 }
110
111 Index++;
112 }
113
114 if (Index != 4) {
115 return EFI_INVALID_PARAMETER;
116 }
117
118 return EFI_SUCCESS;
119 }
120
121 /**
122 Convert the IPv4 address into a dotted string.
123
124 @param[in] Ip The IPv4 address.
125 @param[out] Str The dotted IP string.
126 **/
127 VOID
128 Ip4ConfigIpToStr (
129 IN EFI_IPv4_ADDRESS *Ip,
130 OUT CHAR16 *Str
131 )
132 {
133 UnicodeSPrint (Str, 2 * IP4_STR_MAX_SIZE, L"%d.%d.%d.%d", Ip->Addr[0], Ip->Addr[1], Ip->Addr[2], Ip->Addr[3]);
134 }
135
136
137 /**
138 Convert the network configuration data into the IFR data.
139
140 @param[in] Ip4ConfigInstance The IP4Config instance
141 @param[out] IfrFormNvData The IFR nv data.
142 **/
143 VOID
144 Ip4ConfigConvertDeviceConfigDataToIfrNvData (
145 IN IP4_CONFIG_INSTANCE *Ip4ConfigInstance,
146 OUT IP4_CONFIG_IFR_NVDATA *IfrFormNvData
147 )
148 {
149 NIC_IP4_CONFIG_INFO *NicConfig;
150
151 NicConfig = EfiNicIp4ConfigGetInfo (Ip4ConfigInstance);
152 if (NicConfig != NULL) {
153 IfrFormNvData->Configure = 1;
154 Ip4ConfigInstance->Ip4ConfigCallbackInfo.Configured = TRUE;
155 if (NicConfig->Source == IP4_CONFIG_SOURCE_DHCP) {
156 IfrFormNvData->DhcpEnable = 1;
157 Ip4ConfigInstance->Ip4ConfigCallbackInfo.DhcpEnabled = TRUE;
158 } else {
159 IfrFormNvData->DhcpEnable = 0;
160 Ip4ConfigIpToStr (&NicConfig->Ip4Info.StationAddress, IfrFormNvData->StationAddress);
161 Ip4ConfigIpToStr (&NicConfig->Ip4Info.SubnetMask, IfrFormNvData->SubnetMask);
162 Ip4ConfigIpToStr (&NicConfig->Ip4Info.RouteTable[1].GatewayAddress, IfrFormNvData->GatewayAddress);
163
164 Ip4ConfigInstance->Ip4ConfigCallbackInfo.DhcpEnabled = FALSE;
165 CopyMem (&Ip4ConfigInstance->Ip4ConfigCallbackInfo.LocalIp, &NicConfig->Ip4Info.StationAddress, sizeof (EFI_IPv4_ADDRESS));
166 CopyMem (&Ip4ConfigInstance->Ip4ConfigCallbackInfo.SubnetMask, &NicConfig->Ip4Info.SubnetMask, sizeof (EFI_IPv4_ADDRESS));
167 CopyMem (&Ip4ConfigInstance->Ip4ConfigCallbackInfo.Gateway, &NicConfig->Ip4Info.RouteTable[1].GatewayAddress, sizeof (EFI_IPv4_ADDRESS));
168 }
169
170 FreePool (NicConfig);
171 } else {
172 IfrFormNvData->Configure = 0;
173 Ip4ConfigInstance->Ip4ConfigCallbackInfo.Configured = FALSE;
174 }
175 }
176
177 /**
178 Convert the IFR data into the network configuration data and set the IP
179 configure parameters for the NIC.
180
181 @param[in] IfrFormNvData The IFR NV data.
182 @param[in, out] Ip4ConfigInstance The IP4Config instance.
183
184 @retval EFI_SUCCESS The configure parameter for this NIC was
185 set successfully.
186 @retval EFI_ALREADY_STARTED There is a pending auto configuration.
187 @retval EFI_NOT_FOUND No auto configure parameter is found.
188
189 **/
190 EFI_STATUS
191 Ip4ConfigConvertIfrNvDataToDeviceConfigData (
192 IN IP4_CONFIG_IFR_NVDATA *IfrFormNvData,
193 IN OUT IP4_CONFIG_INSTANCE *Ip4ConfigInstance
194 )
195 {
196 EFI_STATUS Status;
197 EFI_IP_ADDRESS HostIp;
198 EFI_IP_ADDRESS SubnetMask;
199 EFI_IP_ADDRESS Gateway;
200 EFI_INPUT_KEY Key;
201 NIC_IP4_CONFIG_INFO *NicInfo;
202 EFI_IP_ADDRESS Ip;
203
204 ZeroMem (&Ip4ConfigInstance->Ip4ConfigCallbackInfo, sizeof (IP4_SETTING_INFO));
205
206 Ip4ConfigInstance->Ip4ConfigCallbackInfo.Configured = IfrFormNvData->Configure;
207 Ip4ConfigInstance->Ip4ConfigCallbackInfo.DhcpEnabled = IfrFormNvData->DhcpEnable;
208 Ip4StrToIp (IfrFormNvData->StationAddress, &Ip4ConfigInstance->Ip4ConfigCallbackInfo.LocalIp);
209 Ip4StrToIp (IfrFormNvData->SubnetMask, &Ip4ConfigInstance->Ip4ConfigCallbackInfo.SubnetMask);
210 Ip4StrToIp (IfrFormNvData->GatewayAddress, &Ip4ConfigInstance->Ip4ConfigCallbackInfo.Gateway);
211
212 if (!Ip4ConfigInstance->Ip4ConfigCallbackInfo.Configured) {
213 //
214 // Clear the variable
215 //
216 ZeroMem (&Ip4ConfigInstance->Ip4ConfigCallbackInfo, sizeof (IP4_SETTING_INFO));
217
218 Status = EfiNicIp4ConfigSetInfo (Ip4ConfigInstance, NULL, TRUE);
219 if (Status == EFI_NOT_FOUND) {
220 return EFI_SUCCESS;
221 }
222
223 return Status;
224 }
225
226 NicInfo = AllocateZeroPool (sizeof (NIC_IP4_CONFIG_INFO) + 2 * sizeof (EFI_IP4_ROUTE_TABLE));
227 ASSERT (NicInfo != NULL);
228
229 NicInfo->Ip4Info.RouteTable = (EFI_IP4_ROUTE_TABLE *) (NicInfo + 1);
230
231 if (!Ip4ConfigInstance->Ip4ConfigCallbackInfo.DhcpEnabled) {
232 CopyMem (&HostIp.v4, &Ip4ConfigInstance->Ip4ConfigCallbackInfo.LocalIp, sizeof (HostIp.v4));
233 CopyMem (&SubnetMask.v4, &Ip4ConfigInstance->Ip4ConfigCallbackInfo.SubnetMask, sizeof (SubnetMask.v4));
234 CopyMem (&Gateway.v4, &Ip4ConfigInstance->Ip4ConfigCallbackInfo.Gateway, sizeof (Gateway.v4));
235
236 if (!NetIp4IsUnicast (NTOHL (HostIp.Addr[0]), 0)) {
237 CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Invalid IP address!", NULL);
238 return EFI_INVALID_PARAMETER;
239 }
240 if (EFI_IP4_EQUAL (&SubnetMask, &mZeroIp4Addr)) {
241 CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Invalid Subnet Mask!", NULL);
242 return EFI_INVALID_PARAMETER;
243 }
244
245 if ((Gateway.Addr[0] != 0)) {
246 if (SubnetMask.Addr[0] == 0) {
247 CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Gateway address is set but subnet mask is zero.", NULL);
248 return EFI_INVALID_PARAMETER;
249
250 } else if (!IP4_NET_EQUAL (HostIp.Addr[0], Gateway.Addr[0], SubnetMask.Addr[0])) {
251 CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Local IP and Gateway are not in the same subnet.", NULL);
252 return EFI_INVALID_PARAMETER; }
253 }
254
255 NicInfo->Source = IP4_CONFIG_SOURCE_STATIC;
256 NicInfo->Ip4Info.RouteTableSize = 2;
257
258 CopyMem (&NicInfo->Ip4Info.StationAddress, &HostIp.v4, sizeof (EFI_IPv4_ADDRESS));
259 CopyMem (&NicInfo->Ip4Info.SubnetMask, &SubnetMask.v4, sizeof (EFI_IPv4_ADDRESS));
260
261 Ip.Addr[0] = HostIp.Addr[0] & SubnetMask.Addr[0];
262
263 CopyMem (&NicInfo->Ip4Info.RouteTable[0].SubnetAddress, &Ip.v4, sizeof (EFI_IPv4_ADDRESS));
264 CopyMem (&NicInfo->Ip4Info.RouteTable[0].SubnetMask, &SubnetMask.v4, sizeof (EFI_IPv4_ADDRESS));
265 CopyMem (&NicInfo->Ip4Info.RouteTable[1].GatewayAddress, &Gateway.v4, sizeof (EFI_IPv4_ADDRESS));
266
267 } else {
268 NicInfo->Source = IP4_CONFIG_SOURCE_DHCP;
269 ZeroMem (&Ip4ConfigInstance->Ip4ConfigCallbackInfo.LocalIp, sizeof (EFI_IPv4_ADDRESS));
270 ZeroMem (&Ip4ConfigInstance->Ip4ConfigCallbackInfo.SubnetMask, sizeof (EFI_IPv4_ADDRESS));
271 ZeroMem (&Ip4ConfigInstance->Ip4ConfigCallbackInfo.Gateway, sizeof (EFI_IPv4_ADDRESS));
272 }
273
274 NicInfo->Perment = TRUE;
275 CopyMem (&NicInfo->NicAddr, &Ip4ConfigInstance->NicAddr, sizeof (NIC_ADDR));
276
277 return EfiNicIp4ConfigSetInfo (Ip4ConfigInstance, NicInfo, TRUE);
278 }
279
280 /**
281 This function allows the caller to request the current
282 configuration for one or more named elements. The resulting
283 string is in <ConfigAltResp> format. Any and all alternative
284 configuration strings shall also be appended to the end of the
285 current configuration string. If they are, they must appear
286 after the current configuration. They must contain the same
287 routing (GUID, NAME, PATH) as the current configuration string.
288 They must have an additional description indicating the type of
289 alternative configuration the string represents,
290 "ALTCFG=<StringToken>". That <StringToken> (when
291 converted from Hex UNICODE to binary) is a reference to a
292 string in the associated string pack.
293
294 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
295 @param[in] Request A null-terminated Unicode string in
296 <ConfigRequest> format. Note that this
297 includes the routing information as well as
298 the configurable name / value pairs. It is
299 invalid for this string to be in
300 <MultiConfigRequest> format.
301 @param[out] Progress On return, points to a character in the
302 Request string. Points to the string's null
303 terminator if request was successful. Points
304 to the most recent "&" before the first
305 failing name / value pair (or the beginning
306 of the string if the failure is in the first
307 name / value pair) if the request was not
308 successful.
309 @param[out] Results A null-terminated Unicode string in
310 <ConfigAltResp> format which has all values
311 filled in for the names in the Request string.
312 String to be allocated by the called function.
313
314 @retval EFI_SUCCESS The Results string is filled with the
315 values corresponding to all requested
316 names.
317 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the
318 parts of the results that must be
319 stored awaiting possible future
320 protocols.
321 @retval EFI_NOT_FOUND Routing data doesn't match any
322 known driver. Progress set to the
323 first character in the routing header.
324 Note: There is no requirement that the
325 driver validate the routing data. It
326 must skip the <ConfigHdr> in order to
327 process the names.
328 @retval EFI_INVALID_PARAMETER Illegal syntax. Progress set
329 to most recent & before the
330 error or the beginning of the
331 string.
332 @retval EFI_INVALID_PARAMETER Unknown name. Progress points
333 to the & before the name in
334 question.Currently not implemented.
335 **/
336 EFI_STATUS
337 EFIAPI
338 Ip4DeviceExtractConfig (
339 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
340 IN CONST EFI_STRING Request,
341 OUT EFI_STRING *Progress,
342 OUT EFI_STRING *Results
343 )
344 {
345 EFI_STATUS Status;
346 NIC_IP4_CONFIG_INFO *IfrDeviceNvData;
347 NIC_IP4_CONFIG_INFO *NicConfig;
348 IP4_CONFIG_INSTANCE *Ip4ConfigInstance;
349 IP4_CONFIG_IFR_NVDATA *IfrFormNvData;
350 EFI_STRING ConfigRequestHdr;
351 EFI_STRING ConfigRequest;
352 EFI_STRING DeviceResult;
353 EFI_STRING FormResult;
354 CHAR16 *StrPointer;
355 BOOLEAN AllocatedRequest;
356 UINTN Size;
357 UINTN BufferSize;
358
359 if (Progress == NULL || Results == NULL) {
360 return EFI_INVALID_PARAMETER;
361 }
362
363 *Progress = Request;
364 Size = 0;
365 DeviceResult = NULL;
366 FormResult = NULL;
367 ConfigRequest = NULL;
368 Status = EFI_SUCCESS;
369 AllocatedRequest = FALSE;
370 Ip4ConfigInstance = IP4_CONFIG_INSTANCE_FROM_CONFIG_ACCESS (This);
371
372 //
373 // Check Request data in <ConfigHdr>.
374 //
375 if ((Request == NULL) || HiiIsConfigHdrMatch (Request, &gEfiNicIp4ConfigVariableGuid, EFI_NIC_IP4_CONFIG_VARIABLE)) {
376 IfrDeviceNvData = AllocateZeroPool (NIC_ITEM_CONFIG_SIZE);
377 if (IfrDeviceNvData == NULL) {
378 return EFI_OUT_OF_RESOURCES;
379 }
380
381 NicConfig = EfiNicIp4ConfigGetInfo (Ip4ConfigInstance);
382 if (NicConfig == NULL) {
383 return EFI_NOT_FOUND;
384 }
385 CopyMem (IfrDeviceNvData, NicConfig, SIZEOF_NIC_IP4_CONFIG_INFO (NicConfig));
386 FreePool (NicConfig);
387
388 ConfigRequest = Request;
389 if ((Request == NULL) || (StrStr (Request, L"OFFSET") == NULL)) {
390 //
391 // Request has no request element, construct full request string.
392 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
393 // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator
394 //
395 ConfigRequestHdr = HiiConstructConfigHdr (&gEfiNicIp4ConfigVariableGuid, EFI_NIC_IP4_CONFIG_VARIABLE, Ip4ConfigInstance->ChildHandle);
396 Size = (StrLen (ConfigRequestHdr) + 32 + 1) * sizeof (CHAR16);
397 ConfigRequest = AllocateZeroPool (Size);
398 ASSERT (ConfigRequest != NULL);
399 AllocatedRequest = TRUE;
400 BufferSize = NIC_ITEM_CONFIG_SIZE;
401 UnicodeSPrint (ConfigRequest, Size, L"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr, (UINT64)BufferSize);
402 FreePool (ConfigRequestHdr);
403 }
404
405 //
406 // Convert buffer data to <ConfigResp> by helper function BlockToConfig()
407 //
408 Status = gHiiConfigRouting->BlockToConfig (
409 gHiiConfigRouting,
410 ConfigRequest,
411 (UINT8 *) IfrDeviceNvData,
412 NIC_ITEM_CONFIG_SIZE,
413 &DeviceResult,
414 Progress
415 );
416
417 FreePool (IfrDeviceNvData);
418 //
419 // Free the allocated config request string.
420 //
421 if (AllocatedRequest) {
422 FreePool (ConfigRequest);
423 ConfigRequest = NULL;
424 }
425
426 if (EFI_ERROR (Status)) {
427 goto Failure;
428 }
429 }
430
431 if ((Request == NULL) || HiiIsConfigHdrMatch (Request, &gNicIp4ConfigNvDataGuid, EFI_NIC_IP4_CONFIG_VARIABLE)) {
432
433 IfrFormNvData = AllocateZeroPool (sizeof (IP4_CONFIG_IFR_NVDATA));
434 if (IfrFormNvData == NULL) {
435 return EFI_OUT_OF_RESOURCES;
436 }
437
438 Ip4ConfigConvertDeviceConfigDataToIfrNvData (Ip4ConfigInstance, IfrFormNvData);
439
440 ConfigRequest = Request;
441 if ((Request == NULL) || (StrStr (Request, L"OFFSET") == NULL)) {
442 //
443 // Request has no request element, construct full request string.
444 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
445 // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator
446 //
447 ConfigRequestHdr = HiiConstructConfigHdr (&gNicIp4ConfigNvDataGuid, EFI_NIC_IP4_CONFIG_VARIABLE, Ip4ConfigInstance->ChildHandle);
448 Size = (StrLen (ConfigRequestHdr) + 32 + 1) * sizeof (CHAR16);
449 ConfigRequest = AllocateZeroPool (Size);
450 ASSERT (ConfigRequest != NULL);
451 AllocatedRequest = TRUE;
452 BufferSize = sizeof (IP4_CONFIG_IFR_NVDATA);
453 UnicodeSPrint (ConfigRequest, Size, L"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr, (UINT64)BufferSize);
454 FreePool (ConfigRequestHdr);
455 }
456
457 //
458 // Convert buffer data to <ConfigResp> by helper function BlockToConfig()
459 //
460 Status = gHiiConfigRouting->BlockToConfig (
461 gHiiConfigRouting,
462 ConfigRequest,
463 (UINT8 *) IfrFormNvData,
464 sizeof (IP4_CONFIG_IFR_NVDATA),
465 &FormResult,
466 Progress
467 );
468
469 FreePool (IfrFormNvData);
470 //
471 // Free the allocated config request string.
472 //
473 if (AllocatedRequest) {
474 FreePool (ConfigRequest);
475 ConfigRequest = NULL;
476 }
477
478 if (EFI_ERROR (Status)) {
479 goto Failure;
480 }
481 }
482
483 if (Request == NULL) {
484 Size = StrLen (DeviceResult);
485 Size = Size + 1;
486 Size = Size + StrLen (FormResult) + 1;
487 *Results = AllocateZeroPool (Size * sizeof (CHAR16));
488 ASSERT (*Results != NULL);
489 StrPointer = *Results;
490 StrCpy (StrPointer, DeviceResult);
491 StrPointer = StrPointer + StrLen (StrPointer);
492 *StrPointer = L'&';
493 StrCpy (StrPointer + 1, FormResult);
494 FreePool (DeviceResult);
495 FreePool (FormResult);
496 } else if (HiiIsConfigHdrMatch (Request, &gEfiNicIp4ConfigVariableGuid, EFI_NIC_IP4_CONFIG_VARIABLE)) {
497 *Results = DeviceResult;
498 } else if (HiiIsConfigHdrMatch (Request, &gNicIp4ConfigNvDataGuid, EFI_NIC_IP4_CONFIG_VARIABLE)) {
499 *Results = FormResult;
500 } else {
501 return EFI_NOT_FOUND;
502 }
503
504 Failure:
505 //
506 // Set Progress string to the original request string.
507 //
508 if (Request == NULL) {
509 *Progress = NULL;
510 } else if (StrStr (Request, L"OFFSET") == NULL) {
511 *Progress = Request + StrLen (Request);
512 }
513
514 return Status;
515 }
516
517 /**
518 This function applies changes in a driver's configuration.
519 Input is a Configuration, which has the routing data for this
520 driver followed by name / value configuration pairs. The driver
521 must apply those pairs to its configurable storage. If the
522 driver's configuration is stored in a linear block of data
523 and the driver's name / value pairs are in <BlockConfig>
524 format, it may use the ConfigToBlock helper function (above) to
525 simplify the job. Currently not implemented.
526
527 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
528 @param[in] Configuration A null-terminated Unicode string in
529 <ConfigString> format.
530 @param[out] Progress A pointer to a string filled in with the
531 offset of the most recent '&' before the
532 first failing name / value pair (or the
533 beginn ing of the string if the failure
534 is in the first name / value pair) or
535 the terminating NULL if all was
536 successful.
537
538 @retval EFI_SUCCESS The results have been distributed or are
539 awaiting distribution.
540 @retval EFI_OUT_OF_MEMORY Not enough memory to store the
541 parts of the results that must be
542 stored awaiting possible future
543 protocols.
544 @retval EFI_INVALID_PARAMETERS Passing in a NULL for the
545 Results parameter would result
546 in this type of error.
547 @retval EFI_NOT_FOUND Target for the specified routing data
548 was not found.
549 **/
550 EFI_STATUS
551 EFIAPI
552 Ip4DeviceRouteConfig (
553 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
554 IN CONST EFI_STRING Configuration,
555 OUT EFI_STRING *Progress
556 )
557 {
558 EFI_STATUS Status;
559 UINTN BufferSize;
560 NIC_IP4_CONFIG_INFO *IfrDeviceNvData;
561 IP4_CONFIG_IFR_NVDATA *IfrFormNvData;
562 NIC_IP4_CONFIG_INFO *NicInfo;
563 IP4_CONFIG_INSTANCE *Ip4ConfigInstance;
564 EFI_MAC_ADDRESS ZeroMac;
565
566 if (Configuration == NULL || Progress == NULL) {
567 return EFI_INVALID_PARAMETER;
568 }
569
570 //
571 // Reclaim Ip4Config variable
572 //
573 Ip4ConfigReclaimVariable ();
574
575 *Progress = Configuration;
576
577 Ip4ConfigInstance = IP4_CONFIG_INSTANCE_FROM_CONFIG_ACCESS (This);
578
579 //
580 // Check Routing data in <ConfigHdr>.
581 //
582 if (HiiIsConfigHdrMatch (Configuration, &gNicIp4ConfigNvDataGuid, EFI_NIC_IP4_CONFIG_VARIABLE)) {
583 //
584 // Convert buffer data to <ConfigResp> by helper function BlockToConfig()
585 //
586 IfrFormNvData = AllocateZeroPool (sizeof (IP4_CONFIG_IFR_NVDATA));
587 if (IfrFormNvData == NULL) {
588 return EFI_OUT_OF_RESOURCES;
589 }
590
591 BufferSize = NIC_ITEM_CONFIG_SIZE;
592 Status = gHiiConfigRouting->ConfigToBlock (
593 gHiiConfigRouting,
594 Configuration,
595 (UINT8 *) IfrFormNvData,
596 &BufferSize,
597 Progress
598 );
599 if (!EFI_ERROR (Status)) {
600 Status = Ip4ConfigConvertIfrNvDataToDeviceConfigData (IfrFormNvData, Ip4ConfigInstance);
601 }
602
603 FreePool (IfrFormNvData);
604
605 } else if (HiiIsConfigHdrMatch (Configuration, &gEfiNicIp4ConfigVariableGuid, EFI_NIC_IP4_CONFIG_VARIABLE)) {
606
607 IfrDeviceNvData = AllocateZeroPool (NIC_ITEM_CONFIG_SIZE);
608 if (IfrDeviceNvData == NULL) {
609 return EFI_OUT_OF_RESOURCES;
610 }
611
612 BufferSize = NIC_ITEM_CONFIG_SIZE;
613 Status = gHiiConfigRouting->ConfigToBlock (
614 gHiiConfigRouting,
615 Configuration,
616 (UINT8 *) IfrDeviceNvData,
617 &BufferSize,
618 Progress
619 );
620 if (!EFI_ERROR (Status)) {
621 ZeroMem (&ZeroMac, sizeof (EFI_MAC_ADDRESS));
622 if (CompareMem (&IfrDeviceNvData->NicAddr.MacAddr, &ZeroMac, IfrDeviceNvData->NicAddr.Len) != 0) {
623 BufferSize = SIZEOF_NIC_IP4_CONFIG_INFO (IfrDeviceNvData);
624 NicInfo = AllocateCopyPool (BufferSize, IfrDeviceNvData);
625 if (NicInfo == NULL) {
626 return EFI_OUT_OF_RESOURCES;
627 }
628 Status = EfiNicIp4ConfigSetInfo (Ip4ConfigInstance, NicInfo, TRUE);
629 FreePool (NicInfo);
630 } else {
631 ZeroMem (&Ip4ConfigInstance->Ip4ConfigCallbackInfo, sizeof (IP4_SETTING_INFO));
632 Status = EfiNicIp4ConfigSetInfo (Ip4ConfigInstance, NULL, TRUE);
633 }
634 }
635
636 FreePool (IfrDeviceNvData);
637
638 } else {
639
640 return EFI_NOT_FOUND;
641 }
642
643 return Status;
644
645 }
646
647 /**
648 This function is called to provide results data to the driver.
649 This data consists of a unique key that is used to identify
650 which data is either being passed back or being asked for.
651
652 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
653 @param[in] Action Specifies the type of action taken by the browser.
654 @param[in] QuestionId A unique value which is sent to the original
655 exporting driver so that it can identify the type
656 of data to expect. The format of the data tends to
657 vary based on the opcode that enerated the callback.
658 @param[in] Type The type of value for the question.
659 @param[in] Value A pointer to the data being sent to the original
660 exporting driver.
661 @param[out] ActionRequest On return, points to the action requested by the
662 callback function.
663
664 @retval EFI_SUCCESS The callback successfully handled the action.
665 @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the
666 variable and its data.
667 @retval EFI_DEVICE_ERROR The variable could not be saved.
668 @retval EFI_UNSUPPORTED The specified Action is not supported by the
669 callback.Currently not implemented.
670 @retval EFI_INVALID_PARAMETERS Passing in wrong parameter.
671 @retval Others Other errors as indicated.
672 **/
673 EFI_STATUS
674 EFIAPI
675 Ip4FormCallback (
676 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
677 IN EFI_BROWSER_ACTION Action,
678 IN EFI_QUESTION_ID QuestionId,
679 IN UINT8 Type,
680 IN EFI_IFR_TYPE_VALUE *Value,
681 OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest
682 )
683 {
684 IP4_CONFIG_INSTANCE *Ip4ConfigInstance;
685 IP4_CONFIG_IFR_NVDATA *IfrFormNvData;
686 EFI_IP_ADDRESS HostIp;
687 EFI_IP_ADDRESS SubnetMask;
688 EFI_IP_ADDRESS Gateway;
689 EFI_STATUS Status;
690 EFI_INPUT_KEY Key;
691
692 if (Action == EFI_BROWSER_ACTION_CHANGED) {
693 Ip4ConfigInstance = IP4_CONFIG_INSTANCE_FROM_CONFIG_ACCESS (This);
694
695 IfrFormNvData = AllocateZeroPool (sizeof (IP4_CONFIG_IFR_NVDATA));
696 if (IfrFormNvData == NULL) {
697 return EFI_OUT_OF_RESOURCES;
698 }
699
700 //
701 // Retrive uncommitted data from Browser
702 //
703 if (!HiiGetBrowserData (&gNicIp4ConfigNvDataGuid, EFI_NIC_IP4_CONFIG_VARIABLE, sizeof (IP4_CONFIG_IFR_NVDATA), (UINT8 *) IfrFormNvData)) {
704 FreePool (IfrFormNvData);
705 return EFI_NOT_FOUND;
706 }
707
708 Status = EFI_SUCCESS;
709
710 switch (QuestionId) {
711 case KEY_LOCAL_IP:
712 Status = Ip4StrToIp (IfrFormNvData->StationAddress, &HostIp.v4);
713 if (EFI_ERROR (Status) || !NetIp4IsUnicast (NTOHL (HostIp.Addr[0]), 0)) {
714 CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Invalid IP address!", NULL);
715 Status = EFI_INVALID_PARAMETER;
716 } else {
717 CopyMem (&Ip4ConfigInstance->Ip4ConfigCallbackInfo.LocalIp, &HostIp.v4, sizeof (HostIp.v4));
718 }
719
720 break;
721
722 case KEY_SUBNET_MASK:
723 Status = Ip4StrToIp (IfrFormNvData->SubnetMask, &SubnetMask.v4);
724 if (EFI_ERROR (Status) || ((SubnetMask.Addr[0] != 0) && (GetSubnetMaskPrefixLength (&SubnetMask.v4) == 0))) {
725 CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Invalid Subnet Mask!", NULL);
726 Status = EFI_INVALID_PARAMETER;
727 } else {
728 CopyMem (&Ip4ConfigInstance->Ip4ConfigCallbackInfo.SubnetMask, &SubnetMask.v4, sizeof (SubnetMask.v4));
729 }
730
731 break;
732
733 case KEY_GATE_WAY:
734 Status = Ip4StrToIp (IfrFormNvData->GatewayAddress, &Gateway.v4);
735 if (EFI_ERROR (Status) || ((Gateway.Addr[0] != 0) && !NetIp4IsUnicast (NTOHL (Gateway.Addr[0]), 0))) {
736 CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Invalid Gateway!", NULL);
737 Status = EFI_INVALID_PARAMETER;
738 } else {
739 CopyMem (&Ip4ConfigInstance->Ip4ConfigCallbackInfo.Gateway, &Gateway.v4, sizeof (Gateway.v4));
740 }
741
742 break;
743
744 case KEY_SAVE_CHANGES:
745 Status = Ip4ConfigConvertIfrNvDataToDeviceConfigData (IfrFormNvData, Ip4ConfigInstance);
746 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_SUBMIT;
747 break;
748
749 default:
750 break;
751 }
752
753 FreePool (IfrFormNvData);
754
755 return Status;
756 }
757
758 //
759 // All other action return unsupported.
760 //
761 return EFI_UNSUPPORTED;
762 }
763
764 /**
765 Install HII Config Access protocol for network device and allocate resource.
766
767 @param[in] Instance The IP4 Config instance.
768
769 @retval EFI_SUCCESS The HII Config Access protocol is installed.
770 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
771 @retval Others Other errors as indicated.
772 **/
773 EFI_STATUS
774 Ip4ConfigDeviceInit (
775 IN IP4_CONFIG_INSTANCE *Instance
776 )
777 {
778 EFI_STATUS Status;
779 EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;
780 VENDOR_DEVICE_PATH VendorDeviceNode;
781 EFI_SERVICE_BINDING_PROTOCOL *MnpSb;
782 CHAR16 *MacString;
783 CHAR16 MenuString[128];
784 CHAR16 PortString[128];
785 CHAR16 *OldMenuString;
786
787 ConfigAccess = &Instance->HiiConfigAccessProtocol;
788 ConfigAccess->ExtractConfig = Ip4DeviceExtractConfig;
789 ConfigAccess->RouteConfig = Ip4DeviceRouteConfig;
790 ConfigAccess->Callback = Ip4FormCallback;
791
792 //
793 // Construct device path node for EFI HII Config Access protocol,
794 // which consists of controller physical device path and one hardware
795 // vendor guid node.
796 //
797 ZeroMem (&VendorDeviceNode, sizeof (VENDOR_DEVICE_PATH));
798 VendorDeviceNode.Header.Type = HARDWARE_DEVICE_PATH;
799 VendorDeviceNode.Header.SubType = HW_VENDOR_DP;
800
801 CopyGuid (&VendorDeviceNode.Guid, &gEfiNicIp4ConfigVariableGuid);
802
803 SetDevicePathNodeLength (&VendorDeviceNode.Header, sizeof (VENDOR_DEVICE_PATH));
804 Instance->HiiVendorDevicePath = AppendDevicePathNode (
805 Instance->ParentDevicePath,
806 (EFI_DEVICE_PATH_PROTOCOL *) &VendorDeviceNode
807 );
808
809 Instance->ChildHandle = NULL;
810 //
811 // Install Device Path Protocol and Config Access protocol on new handle
812 //
813 Status = gBS->InstallMultipleProtocolInterfaces (
814 &Instance->ChildHandle,
815 &gEfiDevicePathProtocolGuid,
816 Instance->HiiVendorDevicePath,
817 &gEfiHiiConfigAccessProtocolGuid,
818 ConfigAccess,
819 NULL
820 );
821 if (!EFI_ERROR (Status)) {
822 //
823 // Open the Parent Handle for the child
824 //
825 Status = gBS->OpenProtocol (
826 Instance->Controller,
827 &gEfiManagedNetworkServiceBindingProtocolGuid,
828 (VOID **) &MnpSb,
829 Instance->Image,
830 Instance->ChildHandle,
831 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
832 );
833 }
834
835 ASSERT_EFI_ERROR (Status);
836
837 //
838 // Publish our HII data
839 //
840 Instance->RegisteredHandle = HiiAddPackages (
841 &gNicIp4ConfigNvDataGuid,
842 Instance->ChildHandle,
843 Ip4ConfigDxeStrings,
844 Ip4ConfigDxeBin,
845 NULL
846 );
847 if (Instance->RegisteredHandle == NULL) {
848 return EFI_OUT_OF_RESOURCES;
849 }
850
851 //
852 // Append MAC string in the menu help string and tile help string
853 //
854 Status = NetLibGetMacString (Instance->Controller, Instance->Image, &MacString);
855 if (!EFI_ERROR (Status)) {
856 OldMenuString = HiiGetString (Instance->RegisteredHandle, STRING_TOKEN (STR_IP4_CONFIG_FORM_HELP), NULL);
857 UnicodeSPrint (MenuString, 128, L"%s (MAC:%s)", OldMenuString, MacString);
858 HiiSetString (Instance->RegisteredHandle, STRING_TOKEN (STR_IP4_CONFIG_FORM_HELP), MenuString, NULL);
859
860 UnicodeSPrint (PortString, 128, L"MAC:%s", MacString);
861 HiiSetString (Instance->RegisteredHandle, STRING_TOKEN (STR_IP4_DEVICE_FORM_HELP), PortString, NULL);
862 FreePool (MacString);
863 }
864
865 return Status;
866 }
867
868 /**
869 Uninstall HII Config Access protocol for network device and free resource.
870
871 @param[in] Instance The IP4 Config instance.
872
873 @retval EFI_SUCCESS The HII Config Access protocol is uninstalled.
874 @retval Others Other errors as indicated.
875 **/
876 EFI_STATUS
877 Ip4ConfigDeviceUnload (
878 IN IP4_CONFIG_INSTANCE *Instance
879 )
880 {
881 //
882 // Remove HII package list
883 //
884 HiiRemovePackages (Instance->RegisteredHandle);
885
886 //
887 // Close the child handle
888 //
889 gBS->CloseProtocol (
890 Instance->Controller,
891 &gEfiManagedNetworkServiceBindingProtocolGuid,
892 Instance->Image,
893 Instance->ChildHandle
894 );
895
896 //
897 // Uninstall EFI_HII_CONFIG_ACCESS_PROTOCOL
898 //
899 gBS->UninstallMultipleProtocolInterfaces (
900 Instance->ChildHandle,
901 &gEfiDevicePathProtocolGuid,
902 Instance->HiiVendorDevicePath,
903 &gEfiHiiConfigAccessProtocolGuid,
904 &Instance->HiiConfigAccessProtocol,
905 NULL
906 );
907
908 return EFI_SUCCESS;
909 }