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