]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/Network/Ip4ConfigDxe/Ip4ConfigNv.c
1. update to use 1 EFI Variable per NIC (instead of converge all NIC configuration...
[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 #include "NicIp4Variable.h"
17
18 EFI_GUID mNicIp4ConfigNvDataGuid = EFI_NIC_IP4_CONFIG_NVDATA_GUID;
19
20
21 /**
22 Calculate the prefix length of the IPv4 subnet mask.
23
24 @param[in] SubnetMask The IPv4 subnet mask.
25
26 @return The prefix length of the subnet mask.
27 @retval 0 Other errors as indicated.
28 **/
29 UINT8
30 GetSubnetMaskPrefixLength (
31 IN EFI_IPv4_ADDRESS *SubnetMask
32 )
33 {
34 UINT8 Len;
35 UINT32 ReverseMask;
36
37 //
38 // The SubnetMask is in network byte order.
39 //
40 ReverseMask = (SubnetMask->Addr[0] << 24) | (SubnetMask->Addr[1] << 16) | (SubnetMask->Addr[2] << 8) | (SubnetMask->Addr[3]);
41
42 //
43 // Reverse it.
44 //
45 ReverseMask = ~ReverseMask;
46
47 if ((ReverseMask & (ReverseMask + 1)) != 0) {
48 return 0;
49 }
50
51 Len = 0;
52
53 while (ReverseMask != 0) {
54 ReverseMask = ReverseMask >> 1;
55 Len++;
56 }
57
58 return (UINT8) (32 - Len);
59 }
60
61 /**
62 Convert the decimal dotted IPv4 address into the binary IPv4 address.
63
64 @param[in] Str The UNICODE string.
65 @param[out] Ip The storage to return the IPv4 address.
66
67 @retval EFI_SUCCESS The binary IP address is returned in Ip.
68 @retval EFI_INVALID_PARAMETER The IP string is malformatted.
69 **/
70 EFI_STATUS
71 Ip4StrToIp (
72 IN CHAR16 *Str,
73 OUT EFI_IPv4_ADDRESS *Ip
74 )
75 {
76 UINTN Index;
77 UINTN Number;
78
79 Index = 0;
80
81 while (*Str != L'\0') {
82
83 if (Index > 3) {
84 return EFI_INVALID_PARAMETER;
85 }
86
87 Number = 0;
88 while ((*Str >= L'0') && (*Str <= L'9')) {
89 Number = Number * 10 + (*Str - L'0');
90 Str++;
91 }
92
93 if (Number > 0xFF) {
94 return EFI_INVALID_PARAMETER;
95 }
96
97 Ip->Addr[Index] = (UINT8) Number;
98
99 if ((*Str != L'\0') && (*Str != L'.')) {
100 //
101 // The current character should be either the NULL terminator or
102 // the dot delimiter.
103 //
104 return EFI_INVALID_PARAMETER;
105 }
106
107 if (*Str == L'.') {
108 //
109 // Skip the delimiter.
110 //
111 Str++;
112 }
113
114 Index++;
115 }
116
117 if (Index != 4) {
118 return EFI_INVALID_PARAMETER;
119 }
120
121 return EFI_SUCCESS;
122 }
123
124 /**
125 Convert the IPv4 address into a dotted string.
126
127 @param[in] Ip The IPv4 address.
128 @param[out] Str The dotted IP string.
129 **/
130 VOID
131 Ip4ConfigIpToStr (
132 IN EFI_IPv4_ADDRESS *Ip,
133 OUT CHAR16 *Str
134 )
135 {
136 UnicodeSPrint (Str, 2 * IP4_STR_MAX_SIZE, L"%d.%d.%d.%d", Ip->Addr[0], Ip->Addr[1], Ip->Addr[2], Ip->Addr[3]);
137 }
138
139
140 /**
141 Convert the network configuration data into the IFR data.
142
143 @param[in] Ip4ConfigInstance The IP4Config instance
144 @param[out] IfrFormNvData The IFR nv data.
145 **/
146 VOID
147 Ip4ConfigConvertDeviceConfigDataToIfrNvData (
148 IN IP4_CONFIG_INSTANCE *Ip4ConfigInstance,
149 OUT IP4_CONFIG_IFR_NVDATA *IfrFormNvData
150 )
151 {
152 NIC_IP4_CONFIG_INFO *NicConfig;
153
154 NicConfig = EfiNicIp4ConfigGetInfo (Ip4ConfigInstance);
155 if (NicConfig != NULL) {
156 IfrFormNvData->Configure = 1;
157 if (NicConfig->Source == IP4_CONFIG_SOURCE_DHCP) {
158 IfrFormNvData->DhcpEnable = 1;
159 } else {
160 IfrFormNvData->DhcpEnable = 0;
161 Ip4ConfigIpToStr (&NicConfig->Ip4Info.StationAddress, IfrFormNvData->StationAddress);
162 Ip4ConfigIpToStr (&NicConfig->Ip4Info.SubnetMask, IfrFormNvData->SubnetMask);
163 Ip4ConfigIpToStr (&NicConfig->Ip4Info.RouteTable[1].GatewayAddress, IfrFormNvData->GatewayAddress);
164 }
165
166 FreePool (NicConfig);
167 } else {
168 IfrFormNvData->Configure = 0;
169 }
170 }
171
172 /**
173 Convert the IFR data into the network configuration data and set the IP
174 configure parameters for the NIC.
175
176 @param[in] IfrFormNvData The IFR NV data.
177 @param[in, out] Ip4ConfigInstance The IP4Config instance.
178
179 @retval EFI_SUCCESS The configure parameter for this NIC was
180 set successfully.
181 @retval EFI_ALREADY_STARTED There is a pending auto configuration.
182 @retval EFI_NOT_FOUND No auto configure parameter is found.
183
184 **/
185 EFI_STATUS
186 Ip4ConfigConvertIfrNvDataToDeviceConfigData (
187 IN IP4_CONFIG_IFR_NVDATA *IfrFormNvData,
188 IN OUT IP4_CONFIG_INSTANCE *Ip4ConfigInstance
189 )
190 {
191 EFI_STATUS Status;
192 EFI_IP_ADDRESS HostIp;
193 EFI_IP_ADDRESS SubnetMask;
194 EFI_IP_ADDRESS Gateway;
195 EFI_INPUT_KEY Key;
196 NIC_IP4_CONFIG_INFO *NicInfo;
197 EFI_IP_ADDRESS Ip;
198
199 ZeroMem (&Ip4ConfigInstance->Ip4ConfigCallbackInfo, sizeof (IP4_SETTING_INFO));
200
201 Ip4ConfigInstance->Ip4ConfigCallbackInfo.Configured = IfrFormNvData->Configure;
202 Ip4ConfigInstance->Ip4ConfigCallbackInfo.DhcpEnabled = IfrFormNvData->DhcpEnable;
203 Ip4StrToIp (IfrFormNvData->StationAddress, &Ip4ConfigInstance->Ip4ConfigCallbackInfo.LocalIp);
204 Ip4StrToIp (IfrFormNvData->SubnetMask, &Ip4ConfigInstance->Ip4ConfigCallbackInfo.SubnetMask);
205 Ip4StrToIp (IfrFormNvData->GatewayAddress, &Ip4ConfigInstance->Ip4ConfigCallbackInfo.Gateway);
206
207 if (!Ip4ConfigInstance->Ip4ConfigCallbackInfo.Configured) {
208 //
209 // Clear the variable
210 //
211 ZeroMem (&Ip4ConfigInstance->Ip4ConfigCallbackInfo, sizeof (IP4_SETTING_INFO));
212
213 Status = EfiNicIp4ConfigSetInfo (Ip4ConfigInstance, NULL, TRUE);
214 if (Status == EFI_NOT_FOUND) {
215 return EFI_SUCCESS;
216 }
217
218 return Status;
219 }
220
221 NicInfo = AllocateZeroPool (sizeof (NIC_IP4_CONFIG_INFO) + 2 * sizeof (EFI_IP4_ROUTE_TABLE));
222 ASSERT (NicInfo != NULL);
223
224 NicInfo->Ip4Info.RouteTable = (EFI_IP4_ROUTE_TABLE *) (NicInfo + 1);
225
226 if (!Ip4ConfigInstance->Ip4ConfigCallbackInfo.DhcpEnabled) {
227 CopyMem (&HostIp.v4, &Ip4ConfigInstance->Ip4ConfigCallbackInfo.LocalIp, sizeof (HostIp.v4));
228 CopyMem (&SubnetMask.v4, &Ip4ConfigInstance->Ip4ConfigCallbackInfo.SubnetMask, sizeof (SubnetMask.v4));
229 CopyMem (&Gateway.v4, &Ip4ConfigInstance->Ip4ConfigCallbackInfo.Gateway, sizeof (Gateway.v4));
230
231 if (!NetIp4IsUnicast (NTOHL (HostIp.Addr[0]), 0)) {
232 CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Invalid IP address!", NULL);
233 return EFI_INVALID_PARAMETER;
234 }
235 if (EFI_IP4_EQUAL (&SubnetMask, &mZeroIp4Addr)) {
236 CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Invalid Subnet Mask!", NULL);
237 return EFI_INVALID_PARAMETER;
238 }
239
240 if ((Gateway.Addr[0] != 0)) {
241 if (SubnetMask.Addr[0] == 0) {
242 CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Gateway address is set but subnet mask is zero.", NULL);
243 return EFI_INVALID_PARAMETER;
244
245 } else if (!IP4_NET_EQUAL (HostIp.Addr[0], Gateway.Addr[0], SubnetMask.Addr[0])) {
246 CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Local IP and Gateway are not in the same subnet.", NULL);
247 return EFI_INVALID_PARAMETER; }
248 }
249
250 NicInfo->Source = IP4_CONFIG_SOURCE_STATIC;
251 NicInfo->Ip4Info.RouteTableSize = 2;
252
253 CopyMem (&NicInfo->Ip4Info.StationAddress, &HostIp.v4, sizeof (EFI_IPv4_ADDRESS));
254 CopyMem (&NicInfo->Ip4Info.SubnetMask, &SubnetMask.v4, sizeof (EFI_IPv4_ADDRESS));
255
256 Ip.Addr[0] = HostIp.Addr[0] & SubnetMask.Addr[0];
257
258 CopyMem (&NicInfo->Ip4Info.RouteTable[0].SubnetAddress, &Ip.v4, sizeof (EFI_IPv4_ADDRESS));
259 CopyMem (&NicInfo->Ip4Info.RouteTable[0].SubnetMask, &SubnetMask.v4, sizeof (EFI_IPv4_ADDRESS));
260 CopyMem (&NicInfo->Ip4Info.RouteTable[1].GatewayAddress, &Gateway.v4, sizeof (EFI_IPv4_ADDRESS));
261
262 } else {
263 NicInfo->Source = IP4_CONFIG_SOURCE_DHCP;
264 ZeroMem (&Ip4ConfigInstance->Ip4ConfigCallbackInfo.LocalIp, sizeof (EFI_IPv4_ADDRESS));
265 ZeroMem (&Ip4ConfigInstance->Ip4ConfigCallbackInfo.SubnetMask, sizeof (EFI_IPv4_ADDRESS));
266 ZeroMem (&Ip4ConfigInstance->Ip4ConfigCallbackInfo.Gateway, sizeof (EFI_IPv4_ADDRESS));
267 }
268
269 NicInfo->Perment = TRUE;
270 CopyMem (&NicInfo->NicAddr, &Ip4ConfigInstance->NicAddr, sizeof (NIC_ADDR));
271
272 return EfiNicIp4ConfigSetInfo (Ip4ConfigInstance, NicInfo, TRUE);
273 }
274
275 /**
276 This function allows the caller to request the current
277 configuration for one or more named elements. The resulting
278 string is in <ConfigAltResp> format. Any and all alternative
279 configuration strings shall also be appended to the end of the
280 current configuration string. If they are, they must appear
281 after the current configuration. They must contain the same
282 routing (GUID, NAME, PATH) as the current configuration string.
283 They must have an additional description indicating the type of
284 alternative configuration the string represents,
285 "ALTCFG=<StringToken>". That <StringToken> (when
286 converted from Hex UNICODE to binary) is a reference to a
287 string in the associated string pack.
288
289 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
290 @param[in] Request A null-terminated Unicode string in
291 <ConfigRequest> format. Note that this
292 includes the routing information as well as
293 the configurable name / value pairs. It is
294 invalid for this string to be in
295 <MultiConfigRequest> format.
296 @param[out] Progress On return, points to a character in the
297 Request string. Points to the string's null
298 terminator if request was successful. Points
299 to the most recent "&" before the first
300 failing name / value pair (or the beginning
301 of the string if the failure is in the first
302 name / value pair) if the request was not
303 successful.
304 @param[out] Results A null-terminated Unicode string in
305 <ConfigAltResp> format which has all values
306 filled in for the names in the Request string.
307 String to be allocated by the called function.
308
309 @retval EFI_SUCCESS The Results string is filled with the
310 values corresponding to all requested
311 names.
312 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the
313 parts of the results that must be
314 stored awaiting possible future
315 protocols.
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 NIC_IP4_CONFIG_INFO *IfrDeviceNvData;
342 NIC_IP4_CONFIG_INFO *NicConfig;
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 NicConfig = EfiNicIp4ConfigGetInfo (Ip4ConfigInstance);
377 if (NicConfig == NULL) {
378 return EFI_NOT_FOUND;
379 }
380 CopyMem (IfrDeviceNvData, NicConfig, SIZEOF_NIC_IP4_CONFIG_INFO (NicConfig));
381 FreePool (NicConfig);
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 (sizeof (IP4_CONFIG_IFR_NVDATA));
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 (Request, &gEfiNicIp4ConfigVariableGuid, EFI_NIC_IP4_CONFIG_VARIABLE)) {
492 *Results = DeviceResult;
493 } else if (HiiIsConfigHdrMatch (Request, &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 //
566 // Reclaim Ip4Config variable
567 //
568 Ip4ConfigReclaimVariable ();
569
570 *Progress = Configuration;
571
572 Ip4ConfigInstance = IP4_CONFIG_INSTANCE_FROM_CONFIG_ACCESS (This);
573
574 //
575 // Check Routing data in <ConfigHdr>.
576 //
577 if (HiiIsConfigHdrMatch (Configuration, &mNicIp4ConfigNvDataGuid, EFI_NIC_IP4_CONFIG_VARIABLE)) {
578 //
579 // Convert buffer data to <ConfigResp> by helper function BlockToConfig()
580 //
581 IfrFormNvData = AllocateZeroPool (sizeof (IP4_CONFIG_IFR_NVDATA));
582 if (IfrFormNvData == NULL) {
583 return EFI_OUT_OF_RESOURCES;
584 }
585
586 BufferSize = NIC_ITEM_CONFIG_SIZE;
587 Status = gHiiConfigRouting->ConfigToBlock (
588 gHiiConfigRouting,
589 Configuration,
590 (UINT8 *) IfrFormNvData,
591 &BufferSize,
592 Progress
593 );
594 if (!EFI_ERROR (Status)) {
595 Status = Ip4ConfigConvertIfrNvDataToDeviceConfigData (IfrFormNvData, Ip4ConfigInstance);
596 }
597
598 FreePool (IfrFormNvData);
599
600 } else if (HiiIsConfigHdrMatch (Configuration, &gEfiNicIp4ConfigVariableGuid, EFI_NIC_IP4_CONFIG_VARIABLE)) {
601
602 IfrDeviceNvData = AllocateZeroPool (NIC_ITEM_CONFIG_SIZE);
603 if (IfrDeviceNvData == NULL) {
604 return EFI_OUT_OF_RESOURCES;
605 }
606
607 BufferSize = NIC_ITEM_CONFIG_SIZE;
608 Status = gHiiConfigRouting->ConfigToBlock (
609 gHiiConfigRouting,
610 Configuration,
611 (UINT8 *) IfrDeviceNvData,
612 &BufferSize,
613 Progress
614 );
615 if (!EFI_ERROR (Status)) {
616 ZeroMem (&ZeroMac, sizeof (EFI_MAC_ADDRESS));
617 if (CompareMem (&IfrDeviceNvData->NicAddr.MacAddr, &ZeroMac, IfrDeviceNvData->NicAddr.Len) != 0) {
618 BufferSize = SIZEOF_NIC_IP4_CONFIG_INFO (IfrDeviceNvData);
619 NicInfo = AllocateCopyPool (BufferSize, IfrDeviceNvData);
620 if (NicInfo == NULL) {
621 return EFI_OUT_OF_RESOURCES;
622 }
623 Status = EfiNicIp4ConfigSetInfo (Ip4ConfigInstance, NicInfo, TRUE);
624 FreePool (NicInfo);
625 } else {
626 ZeroMem (&Ip4ConfigInstance->Ip4ConfigCallbackInfo, sizeof (IP4_SETTING_INFO));
627 Status = EfiNicIp4ConfigSetInfo (Ip4ConfigInstance, NULL, TRUE);
628 }
629 }
630
631 FreePool (IfrDeviceNvData);
632
633 } else {
634
635 return EFI_NOT_FOUND;
636 }
637
638 return Status;
639
640 }
641
642 /**
643 This function is called to provide results data to the driver.
644 This data consists of a unique key that is used to identify
645 which data is either being passed back or being asked for.
646
647 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
648 @param[in] Action Specifies the type of action taken by the browser.
649 @param[in] QuestionId A unique value which is sent to the original
650 exporting driver so that it can identify the type
651 of data to expect. The format of the data tends to
652 vary based on the opcode that enerated the callback.
653 @param[in] Type The type of value for the question.
654 @param[in] Value A pointer to the data being sent to the original
655 exporting driver.
656 @param[out] ActionRequest On return, points to the action requested by the
657 callback function.
658
659 @retval EFI_SUCCESS The callback successfully handled the action.
660 @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the
661 variable and its data.
662 @retval EFI_DEVICE_ERROR The variable could not be saved.
663 @retval EFI_UNSUPPORTED The specified Action is not supported by the
664 callback.Currently not implemented.
665 @retval EFI_INVALID_PARAMETERS Passing in wrong parameter.
666 @retval Others Other errors as indicated.
667 **/
668 EFI_STATUS
669 EFIAPI
670 Ip4FormCallback (
671 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
672 IN EFI_BROWSER_ACTION Action,
673 IN EFI_QUESTION_ID QuestionId,
674 IN UINT8 Type,
675 IN EFI_IFR_TYPE_VALUE *Value,
676 OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest
677 )
678 {
679 IP4_CONFIG_INSTANCE *Ip4ConfigInstance;
680 IP4_CONFIG_IFR_NVDATA *IfrFormNvData;
681 EFI_IP_ADDRESS HostIp;
682 EFI_IP_ADDRESS SubnetMask;
683 EFI_IP_ADDRESS Gateway;
684 EFI_STATUS Status;
685 EFI_INPUT_KEY Key;
686
687 if ((Action == EFI_BROWSER_ACTION_FORM_OPEN) || (Action == EFI_BROWSER_ACTION_FORM_CLOSE)) {
688 //
689 // Do nothing for UEFI OPEN/CLOSE Action
690 //
691 return EFI_SUCCESS;
692 }
693
694 Ip4ConfigInstance = IP4_CONFIG_INSTANCE_FROM_CONFIG_ACCESS (This);
695
696 IfrFormNvData = AllocateZeroPool (sizeof (IP4_CONFIG_IFR_NVDATA));
697 if (IfrFormNvData == NULL) {
698 return EFI_OUT_OF_RESOURCES;
699 }
700
701 //
702 // Retrive uncommitted data from Browser
703 //
704 if (!HiiGetBrowserData (&mNicIp4ConfigNvDataGuid, EFI_NIC_IP4_CONFIG_VARIABLE, sizeof (IP4_CONFIG_IFR_NVDATA), (UINT8 *) IfrFormNvData)) {
705 FreePool (IfrFormNvData);
706 return EFI_NOT_FOUND;
707 }
708
709 Status = EFI_SUCCESS;
710
711 switch (QuestionId) {
712 case KEY_LOCAL_IP:
713 Status = Ip4StrToIp (IfrFormNvData->StationAddress, &HostIp.v4);
714 if (EFI_ERROR (Status) || !NetIp4IsUnicast (NTOHL (HostIp.Addr[0]), 0)) {
715 CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Invalid IP address!", NULL);
716 Status = EFI_INVALID_PARAMETER;
717 } else {
718 CopyMem (&Ip4ConfigInstance->Ip4ConfigCallbackInfo.LocalIp, &HostIp.v4, sizeof (HostIp.v4));
719 }
720
721 break;
722
723 case KEY_SUBNET_MASK:
724 Status = Ip4StrToIp (IfrFormNvData->SubnetMask, &SubnetMask.v4);
725 if (EFI_ERROR (Status) || ((SubnetMask.Addr[0] != 0) && (GetSubnetMaskPrefixLength (&SubnetMask.v4) == 0))) {
726 CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Invalid Subnet Mask!", NULL);
727 Status = EFI_INVALID_PARAMETER;
728 } else {
729 CopyMem (&Ip4ConfigInstance->Ip4ConfigCallbackInfo.SubnetMask, &SubnetMask.v4, sizeof (SubnetMask.v4));
730 }
731
732 break;
733
734 case KEY_GATE_WAY:
735 Status = Ip4StrToIp (IfrFormNvData->GatewayAddress, &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 Status = Ip4ConfigConvertIfrNvDataToDeviceConfigData (IfrFormNvData, Ip4ConfigInstance);
747 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_SUBMIT;
748 break;
749
750 default:
751 break;
752 }
753
754 FreePool (IfrFormNvData);
755
756 return Status;
757 }
758
759 /**
760 Install HII Config Access protocol for network device and allocate resource.
761
762 @param[in] Instance The IP4 Config instance.
763
764 @retval EFI_SUCCESS The HII Config Access protocol is installed.
765 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
766 @retval Others Other errors as indicated.
767 **/
768 EFI_STATUS
769 Ip4ConfigDeviceInit (
770 IN IP4_CONFIG_INSTANCE *Instance
771 )
772 {
773 EFI_STATUS Status;
774 EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;
775 VENDOR_DEVICE_PATH VendorDeviceNode;
776 EFI_SERVICE_BINDING_PROTOCOL *MnpSb;
777 CHAR16 *MacString;
778 CHAR16 MenuString[128];
779 CHAR16 PortString[128];
780 CHAR16 *OldMenuString;
781
782 ConfigAccess = &Instance->HiiConfigAccessProtocol;
783 ConfigAccess->ExtractConfig = Ip4DeviceExtractConfig;
784 ConfigAccess->RouteConfig = Ip4DeviceRouteConfig;
785 ConfigAccess->Callback = Ip4FormCallback;
786
787 //
788 // Construct device path node for EFI HII Config Access protocol,
789 // which consists of controller physical device path and one hardware
790 // vendor guid node.
791 //
792 ZeroMem (&VendorDeviceNode, sizeof (VENDOR_DEVICE_PATH));
793 VendorDeviceNode.Header.Type = HARDWARE_DEVICE_PATH;
794 VendorDeviceNode.Header.SubType = HW_VENDOR_DP;
795
796 CopyGuid (&VendorDeviceNode.Guid, &gEfiNicIp4ConfigVariableGuid);
797
798 SetDevicePathNodeLength (&VendorDeviceNode.Header, sizeof (VENDOR_DEVICE_PATH));
799 Instance->HiiVendorDevicePath = AppendDevicePathNode (
800 Instance->ParentDevicePath,
801 (EFI_DEVICE_PATH_PROTOCOL *) &VendorDeviceNode
802 );
803
804 Instance->ChildHandle = NULL;
805 //
806 // Install Device Path Protocol and Config Access protocol on new handle
807 //
808 Status = gBS->InstallMultipleProtocolInterfaces (
809 &Instance->ChildHandle,
810 &gEfiDevicePathProtocolGuid,
811 Instance->HiiVendorDevicePath,
812 &gEfiHiiConfigAccessProtocolGuid,
813 ConfigAccess,
814 NULL
815 );
816 if (!EFI_ERROR (Status)) {
817 //
818 // Open the Parent Handle for the child
819 //
820 Status = gBS->OpenProtocol (
821 Instance->Controller,
822 &gEfiManagedNetworkServiceBindingProtocolGuid,
823 (VOID **) &MnpSb,
824 Instance->Image,
825 Instance->ChildHandle,
826 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
827 );
828 }
829
830 ASSERT_EFI_ERROR (Status);
831
832 //
833 // Publish our HII data
834 //
835 Instance->RegisteredHandle = HiiAddPackages (
836 &mNicIp4ConfigNvDataGuid,
837 Instance->ChildHandle,
838 Ip4ConfigDxeStrings,
839 Ip4ConfigDxeBin,
840 NULL
841 );
842 if (Instance->RegisteredHandle == NULL) {
843 return EFI_OUT_OF_RESOURCES;
844 }
845
846 //
847 // Append MAC string in the menu string and tile string
848 //
849 Status = NetLibGetMacString (Instance->Controller, Instance->Image, &MacString);
850 if (!EFI_ERROR (Status)) {
851 OldMenuString = HiiGetString (Instance->RegisteredHandle, STRING_TOKEN (STR_IP4_CONFIG_FORM_TITLE), NULL);
852 UnicodeSPrint (MenuString, 128, L"%s (MAC:%s)", OldMenuString, MacString);
853 HiiSetString (Instance->RegisteredHandle, STRING_TOKEN (STR_IP4_CONFIG_FORM_TITLE), MenuString, NULL);
854
855 UnicodeSPrint (PortString, 128, L"MAC:%s", MacString);
856 HiiSetString (Instance->RegisteredHandle, STRING_TOKEN (STR_IP4_DEVICE_FORM_TITLE), PortString, NULL);
857 FreePool (MacString);
858 }
859
860 return Status;
861 }
862
863 /**
864 Uninstall HII Config Access protocol for network device and free resource.
865
866 @param[in] Instance The IP4 Config instance.
867
868 @retval EFI_SUCCESS The HII Config Access protocol is uninstalled.
869 @retval Others Other errors as indicated.
870 **/
871 EFI_STATUS
872 Ip4ConfigDeviceUnload (
873 IN IP4_CONFIG_INSTANCE *Instance
874 )
875 {
876 //
877 // Remove HII package list
878 //
879 HiiRemovePackages (Instance->RegisteredHandle);
880
881 //
882 // Close the child handle
883 //
884 gBS->CloseProtocol (
885 Instance->Controller,
886 &gEfiManagedNetworkServiceBindingProtocolGuid,
887 Instance->Image,
888 Instance->ChildHandle
889 );
890
891 //
892 // Uninstall EFI_HII_CONFIG_ACCESS_PROTOCOL
893 //
894 gBS->UninstallMultipleProtocolInterfaces (
895 Instance->ChildHandle,
896 &gEfiDevicePathProtocolGuid,
897 Instance->HiiVendorDevicePath,
898 &gEfiHiiConfigAccessProtocolGuid,
899 &Instance->HiiConfigAccessProtocol,
900 NULL
901 );
902
903 return EFI_SUCCESS;
904 }