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