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