]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/Network/Ip4ConfigDxe/Ip4ConfigNv.c
Update HiiConfigAccess.ExtractConfig interface to support NULL request string and...
[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 EFI_STRING ConfigRequestHdr;
346 EFI_STRING ConfigRequest;
347 EFI_STRING DeviceResult;
348 EFI_STRING FormResult;
349 CHAR16 *StrPointer;
350 BOOLEAN AllocatedRequest;
351 UINTN Size;
352 UINTN BufferSize;
353
354 if (Progress == NULL || Results == NULL) {
355 return EFI_INVALID_PARAMETER;
356 }
357
358 *Progress = Request;
359 Size = 0;
360 DeviceResult = NULL;
361 FormResult = NULL;
362 ConfigRequest = NULL;
363 Status = EFI_SUCCESS;
364 AllocatedRequest = FALSE;
365 Ip4ConfigInstance = IP4_CONFIG_INSTANCE_FROM_CONFIG_ACCESS (This);
366
367 //
368 // Check Request data in <ConfigHdr>.
369 //
370 if ((Request == NULL) || HiiIsConfigHdrMatch (Request, &gEfiNicIp4ConfigVariableGuid, EFI_NIC_IP4_CONFIG_VARIABLE)) {
371 IfrDeviceNvData = AllocateZeroPool (NIC_ITEM_CONFIG_SIZE);
372 if (IfrDeviceNvData == NULL) {
373 return EFI_OUT_OF_RESOURCES;
374 }
375
376 ConfigLen = sizeof (NIC_IP4_CONFIG_INFO) + sizeof (EFI_IP4_ROUTE_TABLE) * 2;
377 Status = EfiNicIp4ConfigGetInfo (Ip4ConfigInstance, &ConfigLen, IfrDeviceNvData);
378 if (EFI_ERROR (Status)) {
379 FreePool (IfrDeviceNvData);
380 return EFI_NOT_FOUND;
381 }
382
383 ConfigRequest = Request;
384 if ((Request == NULL) || (StrStr (Request, L"OFFSET") == NULL)) {
385 //
386 // Request has no request element, construct full request string.
387 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
388 // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator
389 //
390 ConfigRequestHdr = HiiConstructConfigHdr (&gEfiNicIp4ConfigVariableGuid, EFI_NIC_IP4_CONFIG_VARIABLE, Ip4ConfigInstance->ChildHandle);
391 Size = (StrLen (ConfigRequestHdr) + 32 + 1) * sizeof (CHAR16);
392 ConfigRequest = AllocateZeroPool (Size);
393 ASSERT (ConfigRequest != NULL);
394 AllocatedRequest = TRUE;
395 BufferSize = NIC_ITEM_CONFIG_SIZE;
396 UnicodeSPrint (ConfigRequest, Size, L"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr, (UINT64)BufferSize);
397 FreePool (ConfigRequestHdr);
398 }
399
400 //
401 // Convert buffer data to <ConfigResp> by helper function BlockToConfig()
402 //
403 Status = gHiiConfigRouting->BlockToConfig (
404 gHiiConfigRouting,
405 ConfigRequest,
406 (UINT8 *) IfrDeviceNvData,
407 NIC_ITEM_CONFIG_SIZE,
408 &DeviceResult,
409 Progress
410 );
411
412 FreePool (IfrDeviceNvData);
413 //
414 // Free the allocated config request string.
415 //
416 if (AllocatedRequest) {
417 FreePool (ConfigRequest);
418 ConfigRequest = NULL;
419 }
420
421 if (EFI_ERROR (Status)) {
422 goto Failure;
423 }
424 }
425
426 if ((Request == NULL) || HiiIsConfigHdrMatch (Request, &mNicIp4ConfigNvDataGuid, EFI_NIC_IP4_CONFIG_VARIABLE)) {
427
428 IfrFormNvData = AllocateZeroPool (NIC_ITEM_CONFIG_SIZE);
429 if (IfrFormNvData == NULL) {
430 return EFI_OUT_OF_RESOURCES;
431 }
432
433 Ip4ConfigConvertDeviceConfigDataToIfrNvData (Ip4ConfigInstance, IfrFormNvData);
434
435 ConfigRequest = Request;
436 if ((Request == NULL) || (StrStr (Request, L"OFFSET") == NULL)) {
437 //
438 // Request has no request element, construct full request string.
439 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
440 // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator
441 //
442 ConfigRequestHdr = HiiConstructConfigHdr (&mNicIp4ConfigNvDataGuid, EFI_NIC_IP4_CONFIG_VARIABLE, Ip4ConfigInstance->ChildHandle);
443 Size = (StrLen (ConfigRequestHdr) + 32 + 1) * sizeof (CHAR16);
444 ConfigRequest = AllocateZeroPool (Size);
445 ASSERT (ConfigRequest != NULL);
446 AllocatedRequest = TRUE;
447 BufferSize = sizeof (IP4_CONFIG_IFR_NVDATA);
448 UnicodeSPrint (ConfigRequest, Size, L"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr, (UINT64)BufferSize);
449 FreePool (ConfigRequestHdr);
450 }
451
452 //
453 // Convert buffer data to <ConfigResp> by helper function BlockToConfig()
454 //
455 Status = gHiiConfigRouting->BlockToConfig (
456 gHiiConfigRouting,
457 ConfigRequest,
458 (UINT8 *) IfrFormNvData,
459 sizeof (IP4_CONFIG_IFR_NVDATA),
460 &FormResult,
461 Progress
462 );
463
464 FreePool (IfrFormNvData);
465 //
466 // Free the allocated config request string.
467 //
468 if (AllocatedRequest) {
469 FreePool (ConfigRequest);
470 ConfigRequest = NULL;
471 }
472
473 if (EFI_ERROR (Status)) {
474 goto Failure;
475 }
476 }
477
478 if (Request == NULL) {
479 Size = StrLen (DeviceResult);
480 Size = Size + 1;
481 Size = Size + StrLen (FormResult) + 1;
482 *Results = AllocateZeroPool (Size * sizeof (CHAR16));
483 ASSERT (*Results != NULL);
484 StrPointer = *Results;
485 StrCpy (StrPointer, DeviceResult);
486 StrPointer = StrPointer + StrLen (StrPointer);
487 *StrPointer = L'&';
488 StrCpy (StrPointer + 1, FormResult);
489 FreePool (DeviceResult);
490 FreePool (FormResult);
491 } else if (HiiIsConfigHdrMatch (ConfigRequest, &gEfiNicIp4ConfigVariableGuid, EFI_NIC_IP4_CONFIG_VARIABLE)) {
492 *Results = DeviceResult;
493 } else if (HiiIsConfigHdrMatch (ConfigRequest, &mNicIp4ConfigNvDataGuid, EFI_NIC_IP4_CONFIG_VARIABLE)) {
494 *Results = FormResult;
495 } else {
496 return EFI_NOT_FOUND;
497 }
498
499 Failure:
500 //
501 // Set Progress string to the original request string.
502 //
503 if (Request == NULL) {
504 *Progress = NULL;
505 } else if (StrStr (Request, L"OFFSET") == NULL) {
506 *Progress = Request + StrLen (Request);
507 }
508
509 return Status;
510 }
511
512 /**
513 This function applies changes in a driver's configuration.
514 Input is a Configuration, which has the routing data for this
515 driver followed by name / value configuration pairs. The driver
516 must apply those pairs to its configurable storage. If the
517 driver's configuration is stored in a linear block of data
518 and the driver's name / value pairs are in <BlockConfig>
519 format, it may use the ConfigToBlock helper function (above) to
520 simplify the job. Currently not implemented.
521
522 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
523 @param[in] Configuration A null-terminated Unicode string in
524 <ConfigString> format.
525 @param[out] Progress A pointer to a string filled in with the
526 offset of the most recent '&' before the
527 first failing name / value pair (or the
528 beginn ing of the string if the failure
529 is in the first name / value pair) or
530 the terminating NULL if all was
531 successful.
532
533 @retval EFI_SUCCESS The results have been distributed or are
534 awaiting distribution.
535 @retval EFI_OUT_OF_MEMORY Not enough memory to store the
536 parts of the results that must be
537 stored awaiting possible future
538 protocols.
539 @retval EFI_INVALID_PARAMETERS Passing in a NULL for the
540 Results parameter would result
541 in this type of error.
542 @retval EFI_NOT_FOUND Target for the specified routing data
543 was not found.
544 **/
545 EFI_STATUS
546 EFIAPI
547 Ip4DeviceRouteConfig (
548 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
549 IN CONST EFI_STRING Configuration,
550 OUT EFI_STRING *Progress
551 )
552 {
553 EFI_STATUS Status;
554 UINTN BufferSize;
555 NIC_IP4_CONFIG_INFO *IfrDeviceNvData;
556 IP4_CONFIG_IFR_NVDATA *IfrFormNvData;
557 NIC_IP4_CONFIG_INFO *NicInfo;
558 IP4_CONFIG_INSTANCE *Ip4ConfigInstance;
559 EFI_MAC_ADDRESS ZeroMac;
560
561 if (Configuration == NULL || Progress == NULL) {
562 return EFI_INVALID_PARAMETER;
563 }
564
565 *Progress = Configuration;
566
567 Ip4ConfigInstance = IP4_CONFIG_INSTANCE_FROM_CONFIG_ACCESS (This);
568
569 //
570 // Check Routing data in <ConfigHdr>.
571 //
572 if (HiiIsConfigHdrMatch (Configuration, &mNicIp4ConfigNvDataGuid, EFI_NIC_IP4_CONFIG_VARIABLE)) {
573 //
574 // Convert buffer data to <ConfigResp> by helper function BlockToConfig()
575 //
576 IfrFormNvData = AllocateZeroPool (sizeof (IP4_CONFIG_IFR_NVDATA));
577 if (IfrFormNvData == NULL) {
578 return EFI_OUT_OF_RESOURCES;
579 }
580
581 BufferSize = NIC_ITEM_CONFIG_SIZE;
582 Status = gHiiConfigRouting->ConfigToBlock (
583 gHiiConfigRouting,
584 Configuration,
585 (UINT8 *) IfrFormNvData,
586 &BufferSize,
587 Progress
588 );
589 if (!EFI_ERROR (Status)) {
590 Status = Ip4ConfigConvertIfrNvDataToDeviceConfigData (Ip4ConfigInstance);
591 }
592
593 FreePool (IfrFormNvData);
594
595 } else if (HiiIsConfigHdrMatch (Configuration, &gEfiNicIp4ConfigVariableGuid, EFI_NIC_IP4_CONFIG_VARIABLE)) {
596
597 IfrDeviceNvData = AllocateZeroPool (NIC_ITEM_CONFIG_SIZE);
598 if (IfrDeviceNvData == NULL) {
599 return EFI_OUT_OF_RESOURCES;
600 }
601
602 BufferSize = NIC_ITEM_CONFIG_SIZE;
603 Status = gHiiConfigRouting->ConfigToBlock (
604 gHiiConfigRouting,
605 Configuration,
606 (UINT8 *) IfrDeviceNvData,
607 &BufferSize,
608 Progress
609 );
610 if (!EFI_ERROR (Status)) {
611 ZeroMem (&ZeroMac, sizeof (EFI_MAC_ADDRESS));
612 if (CompareMem (&IfrDeviceNvData->NicAddr.MacAddr, &ZeroMac, IfrDeviceNvData->NicAddr.Len) != 0) {
613 BufferSize = sizeof (NIC_IP4_CONFIG_INFO) + sizeof (EFI_IP4_ROUTE_TABLE) * IfrDeviceNvData->Ip4Info.RouteTableSize;
614 NicInfo = AllocateCopyPool (BufferSize, IfrDeviceNvData);
615 Status = EfiNicIp4ConfigSetInfo (Ip4ConfigInstance, NicInfo, TRUE);
616 } else {
617 ZeroMem (&Ip4ConfigInstance->Ip4ConfigCallbackInfo, sizeof (IP4_SETTING_INFO));
618 Status = EfiNicIp4ConfigSetInfo (Ip4ConfigInstance, NULL, TRUE);
619 }
620 }
621
622 FreePool (IfrDeviceNvData);
623
624 } else {
625
626 return EFI_NOT_FOUND;
627 }
628
629 return Status;
630
631 }
632
633 /**
634 This function is called to provide results data to the driver.
635 This data consists of a unique key that is used to identify
636 which data is either being passed back or being asked for.
637
638 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
639 @param[in] Action Specifies the type of action taken by the browser.
640 @param[in] QuestionId A unique value which is sent to the original
641 exporting driver so that it can identify the type
642 of data to expect. The format of the data tends to
643 vary based on the opcode that enerated the callback.
644 @param[in] Type The type of value for the question.
645 @param[in] Value A pointer to the data being sent to the original
646 exporting driver.
647 @param[out] ActionRequest On return, points to the action requested by the
648 callback function.
649
650 @retval EFI_SUCCESS The callback successfully handled the action.
651 @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the
652 variable and its data.
653 @retval EFI_DEVICE_ERROR The variable could not be saved.
654 @retval EFI_UNSUPPORTED The specified Action is not supported by the
655 callback.Currently not implemented.
656 @retval EFI_INVALID_PARAMETERS Passing in wrong parameter.
657 @retval Others Other errors as indicated.
658 **/
659 EFI_STATUS
660 EFIAPI
661 Ip4FormCallback (
662 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
663 IN EFI_BROWSER_ACTION Action,
664 IN EFI_QUESTION_ID QuestionId,
665 IN UINT8 Type,
666 IN EFI_IFR_TYPE_VALUE *Value,
667 OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest
668 )
669 {
670 IP4_CONFIG_INSTANCE *Ip4ConfigInstance;
671 CHAR8 Ip4String[IP4_STR_MAX_SIZE];
672 IP4_CONFIG_IFR_NVDATA *IfrFormNvData;
673 EFI_IP_ADDRESS HostIp;
674 EFI_IP_ADDRESS SubnetMask;
675 EFI_IP_ADDRESS Gateway;
676 EFI_STATUS Status;
677 EFI_INPUT_KEY Key;
678
679 Ip4ConfigInstance = IP4_CONFIG_INSTANCE_FROM_CONFIG_ACCESS (This);
680
681 IfrFormNvData = AllocateZeroPool (sizeof (IP4_CONFIG_IFR_NVDATA));
682 if (IfrFormNvData == NULL) {
683 return EFI_OUT_OF_RESOURCES;
684 }
685
686 //
687 // Retrive uncommitted data from Browser
688 //
689 if (!HiiGetBrowserData (&mNicIp4ConfigNvDataGuid, EFI_NIC_IP4_CONFIG_VARIABLE, sizeof (IP4_CONFIG_IFR_NVDATA), (UINT8 *) IfrFormNvData)) {
690 FreePool (IfrFormNvData);
691 return EFI_NOT_FOUND;
692 }
693
694 Status = EFI_SUCCESS;
695
696 switch (QuestionId) {
697
698 case KEY_ENABLE:
699 if (IfrFormNvData->Configure == 0) {
700 Ip4ConfigInstance->Ip4ConfigCallbackInfo.Configured = FALSE;
701 } else {
702 Ip4ConfigInstance->Ip4ConfigCallbackInfo.Configured = TRUE;
703 }
704 break;
705
706 case KEY_DHCP_ENABLE:
707 if (IfrFormNvData->DhcpEnable == 0) {
708 Ip4ConfigInstance->Ip4ConfigCallbackInfo.DhcpEnabled = FALSE;
709 } else {
710 Ip4ConfigInstance->Ip4ConfigCallbackInfo.DhcpEnabled = TRUE;
711 }
712
713 break;
714
715 case KEY_LOCAL_IP:
716 UnicodeStrToAsciiStr (IfrFormNvData->StationAddress, Ip4String);
717 Status = Ip4AsciiStrToIp (Ip4String, &HostIp.v4);
718 if (EFI_ERROR (Status) || !NetIp4IsUnicast (NTOHL (HostIp.Addr[0]), 0)) {
719 CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Invalid IP address!", NULL);
720 Status = EFI_INVALID_PARAMETER;
721 } else {
722 CopyMem (&Ip4ConfigInstance->Ip4ConfigCallbackInfo.LocalIp, &HostIp.v4, sizeof (HostIp.v4));
723 }
724
725 break;
726
727 case KEY_SUBNET_MASK:
728 UnicodeStrToAsciiStr (IfrFormNvData->SubnetMask, Ip4String);
729 Status = Ip4AsciiStrToIp (Ip4String, &SubnetMask.v4);
730 if (EFI_ERROR (Status) || ((SubnetMask.Addr[0] != 0) && (GetSubnetMaskPrefixLength (&SubnetMask.v4) == 0))) {
731 CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Invalid SubnetMask!", NULL);
732 Status = EFI_INVALID_PARAMETER;
733 } else {
734 CopyMem (&Ip4ConfigInstance->Ip4ConfigCallbackInfo.SubnetMask, &SubnetMask.v4, sizeof (SubnetMask.v4));
735 }
736
737 break;
738
739 case KEY_GATE_WAY:
740 UnicodeStrToAsciiStr (IfrFormNvData->GatewayAddress, Ip4String);
741 Status = Ip4AsciiStrToIp (Ip4String, &Gateway.v4);
742 if (EFI_ERROR (Status) || ((Gateway.Addr[0] != 0) && !NetIp4IsUnicast (NTOHL (Gateway.Addr[0]), 0))) {
743 CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Invalid Gateway!", NULL);
744 Status = EFI_INVALID_PARAMETER;
745 } else {
746 CopyMem (&Ip4ConfigInstance->Ip4ConfigCallbackInfo.Gateway, &Gateway.v4, sizeof (Gateway.v4));
747 }
748
749 break;
750
751 case KEY_SAVE_CHANGES:
752
753 Status = Ip4ConfigConvertIfrNvDataToDeviceConfigData (Ip4ConfigInstance);
754
755 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_SUBMIT;
756
757 break;
758
759 default:
760
761 break;
762 }
763
764 if (!EFI_ERROR (Status)) {
765 //
766 // Pass changed uncommitted data back to Form Browser
767 //
768 HiiSetBrowserData (&gEfiNicIp4ConfigVariableGuid, EFI_NIC_IP4_CONFIG_VARIABLE, sizeof (IP4_CONFIG_IFR_NVDATA), (UINT8 *) IfrFormNvData, NULL);
769 }
770
771 FreePool (IfrFormNvData);
772
773 return Status;
774 }
775
776 /**
777 Install HII Config Access protocol for network device and allocate resource.
778
779 @param[in] Instance The IP4 Config instance.
780
781 @retval EFI_SUCCESS The HII Config Access protocol is installed.
782 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
783 @retval Others Other errors as indicated.
784 **/
785 EFI_STATUS
786 Ip4ConfigDeviceInit (
787 IN IP4_CONFIG_INSTANCE *Instance
788 )
789 {
790 EFI_STATUS Status;
791 EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;
792 VENDOR_DEVICE_PATH VendorDeviceNode;
793 EFI_SERVICE_BINDING_PROTOCOL *MnpSb;
794 CHAR16 *MacString;
795 CHAR16 MenuString[128];
796 CHAR16 PortString[128];
797 CHAR16 *OldMenuString;
798
799 ConfigAccess = &Instance->HiiConfigAccessProtocol;
800 ConfigAccess->ExtractConfig = Ip4DeviceExtractConfig;
801 ConfigAccess->RouteConfig = Ip4DeviceRouteConfig;
802 ConfigAccess->Callback = Ip4FormCallback;
803
804 //
805 // Construct device path node for EFI HII Config Access protocol,
806 // which consists of controller physical device path and one hardware
807 // vendor guid node.
808 //
809 ZeroMem (&VendorDeviceNode, sizeof (VENDOR_DEVICE_PATH));
810 VendorDeviceNode.Header.Type = HARDWARE_DEVICE_PATH;
811 VendorDeviceNode.Header.SubType = HW_VENDOR_DP;
812
813 CopyGuid (&VendorDeviceNode.Guid, &gEfiNicIp4ConfigVariableGuid);
814
815 SetDevicePathNodeLength (&VendorDeviceNode.Header, sizeof (VENDOR_DEVICE_PATH));
816 Instance->HiiVendorDevicePath = AppendDevicePathNode (
817 Instance->ParentDevicePath,
818 (EFI_DEVICE_PATH_PROTOCOL *) &VendorDeviceNode
819 );
820
821 Instance->ChildHandle = NULL;
822 //
823 // Install Device Path Protocol and Config Access protocol on new handle
824 //
825 Status = gBS->InstallMultipleProtocolInterfaces (
826 &Instance->ChildHandle,
827 &gEfiDevicePathProtocolGuid,
828 Instance->HiiVendorDevicePath,
829 &gEfiHiiConfigAccessProtocolGuid,
830 ConfigAccess,
831 NULL
832 );
833 if (!EFI_ERROR (Status)) {
834 //
835 // Open the Parent Handle for the child
836 //
837 Status = gBS->OpenProtocol (
838 Instance->Controller,
839 &gEfiManagedNetworkServiceBindingProtocolGuid,
840 (VOID **) &MnpSb,
841 Instance->Image,
842 Instance->ChildHandle,
843 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
844 );
845 }
846
847 ASSERT_EFI_ERROR (Status);
848
849 //
850 // Publish our HII data
851 //
852 Instance->RegisteredHandle = HiiAddPackages (
853 &mNicIp4ConfigNvDataGuid,
854 Instance->ChildHandle,
855 Ip4ConfigDxeStrings,
856 Ip4ConfigDxeBin,
857 NULL
858 );
859 if (Instance->RegisteredHandle == NULL) {
860 return EFI_OUT_OF_RESOURCES;
861 }
862
863 //
864 // Append MAC string in the menu string and tile string
865 //
866 Status = NetLibGetMacString (Instance->Controller, Instance->Image, &MacString);
867 if (!EFI_ERROR (Status)) {
868 OldMenuString = HiiGetString (Instance->RegisteredHandle, STRING_TOKEN (STR_IP4_CONFIG_FORM_TITLE), NULL);
869 UnicodeSPrint (MenuString, 128, L"%s (MAC:%s)", OldMenuString, MacString);
870 HiiSetString (Instance->RegisteredHandle, STRING_TOKEN (STR_IP4_CONFIG_FORM_TITLE), MenuString, NULL);
871
872 UnicodeSPrint (PortString, 128, L"MAC:%s", MacString);
873 HiiSetString (Instance->RegisteredHandle, STRING_TOKEN (STR_IP4_DEVICE_FORM_TITLE), PortString, NULL);
874 FreePool (MacString);
875 }
876
877 return Status;
878 }
879
880 /**
881 Uninstall HII Config Access protocol for network device and free resource.
882
883 @param[in] Instance The IP4 Config instance.
884
885 @retval EFI_SUCCESS The HII Config Access protocol is uninstalled.
886 @retval Others Other errors as indicated.
887 **/
888 EFI_STATUS
889 Ip4ConfigDeviceUnload (
890 IN IP4_CONFIG_INSTANCE *Instance
891 )
892 {
893 //
894 // Remove HII package list
895 //
896 HiiRemovePackages (Instance->RegisteredHandle);
897
898 //
899 // Close the child handle
900 //
901 gBS->CloseProtocol (
902 Instance->Controller,
903 &gEfiManagedNetworkServiceBindingProtocolGuid,
904 Instance->Image,
905 Instance->ChildHandle
906 );
907
908 //
909 // Uninstall EFI_HII_CONFIG_ACCESS_PROTOCOL
910 //
911 gBS->UninstallMultipleProtocolInterfaces (
912 Instance->ChildHandle,
913 &gEfiDevicePathProtocolGuid,
914 Instance->HiiVendorDevicePath,
915 &gEfiHiiConfigAccessProtocolGuid,
916 &Instance->HiiConfigAccessProtocol,
917 NULL
918 );
919
920 return EFI_SUCCESS;
921 }