]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/Network/Ip4ConfigDxe/Ip4ConfigNv.c
1.fixed some issue to pass HII sct
[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, 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 GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8 Ip4HexString[] = "0123456789ABCDEFabcdef";
18
19 UINTN mNumberOfIp4Devices = 0;
20
21 IP4_FORM_CALLBACK_INFO *mCallbackInfo = NULL;
22
23 LIST_ENTRY mIp4ConfigFormList = {
24 &mIp4ConfigFormList,
25 &mIp4ConfigFormList
26 };
27
28 HII_VENDOR_DEVICE_PATH mIp4ConifgHiiVendorDevicePath = {
29 {
30 {
31 HARDWARE_DEVICE_PATH,
32 HW_VENDOR_DP,
33 {
34 (UINT8) (sizeof (VENDOR_DEVICE_PATH)),
35 (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8)
36 }
37 },
38 //
39 // {6D3FD906-42B9-4220-9E63-9D8C972D58EE}
40 //
41 { 0x6d3fd906, 0x42b9, 0x4220, { 0x9e, 0x63, 0x9d, 0x8c, 0x97, 0x2d, 0x58, 0xee } }
42 },
43 {
44 END_DEVICE_PATH_TYPE,
45 END_ENTIRE_DEVICE_PATH_SUBTYPE,
46 {
47 (UINT8) (END_DEVICE_PATH_LENGTH),
48 (UINT8) ((END_DEVICE_PATH_LENGTH) >> 8)
49 }
50 }
51 };
52
53 /**
54 Convert the mac address into a hexadecimal encoded "-" seperated string.
55
56 @param[in] Mac The mac address.
57 @param[in] Len Length in bytes of the mac address.
58 @param[out] Str The storage to return the mac string.
59
60 **/
61 VOID
62 Ip4MacAddrToStr (
63 IN EFI_MAC_ADDRESS *Mac,
64 IN UINT32 Len,
65 OUT CHAR16 *Str
66 )
67 {
68 UINT32 Index;
69
70 for (Index = 0; Index < Len; Index++) {
71 Str[3 * Index] = (CHAR16) Ip4HexString[(Mac->Addr[Index] >> 4) & 0x0F];
72 Str[3 * Index + 1] = (CHAR16) Ip4HexString[Mac->Addr[Index] & 0x0F];
73 Str[3 * Index + 2] = L'-';
74 }
75
76 Str[3 * Index - 1] = L'\0';
77 }
78
79 /**
80 Calculate the prefix length of the IPv4 subnet mask.
81
82 @param[in] SubnetMask The IPv4 subnet mask.
83
84 @return The prefix length of the subnet mask.
85 @retval 0 Other errors as indicated.
86 **/
87 UINT8
88 GetSubnetMaskPrefixLength (
89 IN EFI_IPv4_ADDRESS *SubnetMask
90 )
91 {
92 UINT8 Len;
93 UINT32 ReverseMask;
94
95 //
96 // The SubnetMask is in network byte order.
97 //
98 ReverseMask = (SubnetMask->Addr[0] << 24) | (SubnetMask->Addr[1] << 16) | (SubnetMask->Addr[2] << 8) | (SubnetMask->Addr[3]);
99
100 //
101 // Reverse it.
102 //
103 ReverseMask = ~ReverseMask;
104
105 if ((ReverseMask & (ReverseMask + 1)) != 0) {
106 return 0;
107 }
108
109 Len = 0;
110
111 while (ReverseMask != 0) {
112 ReverseMask = ReverseMask >> 1;
113 Len++;
114 }
115
116 return (UINT8) (32 - Len);
117 }
118
119 /**
120 Convert the decimal dotted IPv4 address into the binary IPv4 address.
121
122 @param[in] Str The UNICODE string.
123 @param[out] Ip The storage to return the ASCII string.
124
125 @retval EFI_SUCCESS The binary IP address is returned in Ip.
126 @retval EFI_INVALID_PARAMETER The IP string is malformatted.
127 **/
128 EFI_STATUS
129 Ip4AsciiStrToIp (
130 IN CHAR8 *Str,
131 OUT EFI_IPv4_ADDRESS *Ip
132 )
133 {
134 UINTN Index;
135 UINTN Number;
136
137 Index = 0;
138
139 while (*Str != 0) {
140
141 if (Index > 3) {
142 return EFI_INVALID_PARAMETER;
143 }
144
145 Number = 0;
146 while (NET_IS_DIGIT (*Str)) {
147 Number = Number * 10 + (*Str - '0');
148 Str++;
149 }
150
151 if (Number > 0xFF) {
152 return EFI_INVALID_PARAMETER;
153 }
154
155 Ip->Addr[Index] = (UINT8) Number;
156
157 if ((*Str != '\0') && (*Str != '.')) {
158 //
159 // The current character should be either the NULL terminator or
160 // the dot delimiter.
161 //
162 return EFI_INVALID_PARAMETER;
163 }
164
165 if (*Str == '.') {
166 //
167 // Skip the delimiter.
168 //
169 Str++;
170 }
171
172 Index++;
173 }
174
175 if (Index != 4) {
176 return EFI_INVALID_PARAMETER;
177 }
178
179 return EFI_SUCCESS;
180 }
181
182 /**
183 Convert the IPv4 address into a dotted string.
184
185 @param[in] Ip The IPv4 address.
186 @param[out] Str The dotted IP string.
187 **/
188 VOID
189 Ip4ConfigIpToStr (
190 IN EFI_IPv4_ADDRESS *Ip,
191 OUT CHAR16 *Str
192 )
193 {
194 UnicodeSPrint (Str, 2 * IP4_STR_MAX_SIZE, L"%d.%d.%d.%d", Ip->Addr[0], Ip->Addr[1], Ip->Addr[2], Ip->Addr[3]);
195 }
196
197
198 /**
199 Convert the network configuration data into the IFR data.
200
201 @param[in] ConfigFormEntry The IP4 configuration form entry.
202 @param[out] IfrNvData The IFR nv data.
203 **/
204 VOID
205 Ip4ConfigConvertDeviceConfigDataToIfrNvData (
206 IN IP4_CONFIG_INSTANCE *Ip4ConfigInstance,
207 OUT IP4_CONFIG_IFR_NVDATA *IfrFormNvData
208 )
209 {
210 EFI_STATUS Status;
211 NIC_IP4_CONFIG_INFO *NicConfig;
212 UINTN ConfigLen;
213
214 IfrFormNvData->DhcpEnable = 1;
215
216 ConfigLen = sizeof (NIC_IP4_CONFIG_INFO) + sizeof (EFI_IP4_ROUTE_TABLE) * 2;
217 NicConfig = AllocateZeroPool (ConfigLen);
218 ASSERT (NicConfig != NULL);
219 Status = EfiNicIp4ConfigGetInfo (Ip4ConfigInstance, &ConfigLen, NicConfig);
220 if (!EFI_ERROR (Status)) {
221 if (NicConfig->Source == IP4_CONFIG_SOURCE_DHCP) {
222 IfrFormNvData->DhcpEnable = 1;
223 } else {
224 IfrFormNvData->DhcpEnable = 0;
225 Ip4ConfigIpToStr (&NicConfig->Ip4Info.StationAddress, IfrFormNvData->StationAddress);
226 Ip4ConfigIpToStr (&NicConfig->Ip4Info.SubnetMask, IfrFormNvData->SubnetMask);
227 Ip4ConfigIpToStr (&NicConfig->Ip4Info.RouteTable[1].GatewayAddress, IfrFormNvData->GatewayAddress);
228 }
229 }
230 FreePool (NicConfig);
231 }
232
233 /**
234 Get the IP4 configuration form entry by the index of the goto opcode actived.
235
236 @param[in] Index The 0-based index of the goto opcode actived.
237
238 @return The IP4 configuration form entry found.
239 **/
240 IP4CONFIG_FORM_ENTRY *
241 Ip4GetConfigFormEntryByIndex (
242 IN UINT32 Index
243 )
244 {
245 UINT32 CurrentIndex;
246 LIST_ENTRY *Entry;
247 IP4CONFIG_FORM_ENTRY *ConfigFormEntry;
248
249 CurrentIndex = 0;
250 ConfigFormEntry = NULL;
251
252 NET_LIST_FOR_EACH (Entry, &mIp4ConfigFormList) {
253 if (CurrentIndex == Index) {
254 ConfigFormEntry = NET_LIST_USER_STRUCT (Entry, IP4CONFIG_FORM_ENTRY, Link);
255 break;
256 }
257
258 CurrentIndex++;
259 }
260
261 return ConfigFormEntry;
262 }
263
264 /**
265 This function allows the caller to request the current
266 configuration for one or more named elements. The resulting
267 string is in <ConfigAltResp> format. Any and all alternative
268 configuration strings shall also be appended to the end of the
269 current configuration string. If they are, they must appear
270 after the current configuration. They must contain the same
271 routing (GUID, NAME, PATH) as the current configuration string.
272 They must have an additional description indicating the type of
273 alternative configuration the string represents,
274 "ALTCFG=<StringToken>". That <StringToken> (when
275 converted from Hex UNICODE to binary) is a reference to a
276 string in the associated string pack.
277
278 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
279 @param[in] Request A null-terminated Unicode string in
280 <ConfigRequest> format. Note that this
281 includes the routing information as well as
282 the configurable name / value pairs. It is
283 invalid for this string to be in
284 <MultiConfigRequest> format.
285 @param[out] Progress On return, points to a character in the
286 Request string. Points to the string's null
287 terminator if request was successful. Points
288 to the most recent "&" before the first
289 failing name / value pair (or the beginning
290 of the string if the failure is in the first
291 name / value pair) if the request was not
292 successful.
293 @param[out] Results A null-terminated Unicode string in
294 <ConfigAltResp> format which has all values
295 filled in for the names in the Request string.
296 String to be allocated by the called function.
297
298 @retval EFI_SUCCESS The Results string is filled with the
299 values corresponding to all requested
300 names.
301 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the
302 parts of the results that must be
303 stored awaiting possible future
304 protocols.
305 @retval EFI_INVALID_PARAMETER For example, passing in a NULL
306 for the Request parameter
307 would result in this type of
308 error. In this case, the
309 Progress parameter would be
310 set to NULL.
311 @retval EFI_NOT_FOUND Routing data doesn't match any
312 known driver. Progress set to the
313 first character in the routing header.
314 Note: There is no requirement that the
315 driver validate the routing data. It
316 must skip the <ConfigHdr> in order to
317 process the names.
318 @retval EFI_INVALID_PARAMETER Illegal syntax. Progress set
319 to most recent & before the
320 error or the beginning of the
321 string.
322 @retval EFI_INVALID_PARAMETER Unknown name. Progress points
323 to the & before the name in
324 question.Currently not implemented.
325 **/
326 EFI_STATUS
327 EFIAPI
328 Ip4DeviceExtractConfig (
329 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
330 IN CONST EFI_STRING Request,
331 OUT EFI_STRING *Progress,
332 OUT EFI_STRING *Results
333 )
334 {
335 EFI_STATUS Status;
336 UINTN ConfigLen;
337 NIC_IP4_CONFIG_INFO *IfrDeviceNvData;
338 IP4_FORM_CALLBACK_INFO *Private;
339 EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting;
340 IP4_CONFIG_INSTANCE *Ip4ConfigInstance;
341
342 if (Request == NULL) {
343 return EFI_INVALID_PARAMETER;
344 }
345
346 *Progress = Request;
347
348 //
349 // Check Request data in <ConfigHdr>.
350 //
351 if (!HiiIsConfigHdrMatch (Request, &gEfiNicIp4ConfigVariableGuid, EFI_NIC_IP4_CONFIG_VARIABLE)) {
352 return EFI_NOT_FOUND;
353 }
354
355 Private = IP4CONFIG_FORM_CALLBACK_INFO_FROM_FORM_CALLBACK (This);
356 Ip4ConfigInstance = IP4_CONFIG_INSTANCE_FROM_IP4FORM_CALLBACK_INFO (Private);
357
358 IfrDeviceNvData = AllocateZeroPool (NIC_ITEM_CONFIG_SIZE);
359 if (IfrDeviceNvData == NULL) {
360 return EFI_OUT_OF_RESOURCES;
361 }
362
363 Status = EfiNicIp4ConfigGetInfo (Ip4ConfigInstance, &ConfigLen, IfrDeviceNvData);
364 if (EFI_ERROR (Status)) {
365 FreePool (IfrDeviceNvData);
366 return EFI_NOT_FOUND;
367 }
368
369 //
370 // Convert buffer data to <ConfigResp> by helper function BlockToConfig()
371 //
372 HiiConfigRouting = Private->ConfigRouting;
373 Status = HiiConfigRouting->BlockToConfig (
374 HiiConfigRouting,
375 Request,
376 (UINT8 *) IfrDeviceNvData,
377 NIC_ITEM_CONFIG_SIZE,
378 Results,
379 Progress
380 );
381
382 FreePool (IfrDeviceNvData);
383
384 return Status;
385 }
386
387 /**
388 This function applies changes in a driver's configuration.
389 Input is a Configuration, which has the routing data for this
390 driver followed by name / value configuration pairs. The driver
391 must apply those pairs to its configurable storage. If the
392 driver's configuration is stored in a linear block of data
393 and the driver's name / value pairs are in <BlockConfig>
394 format, it may use the ConfigToBlock helper function (above) to
395 simplify the job. Currently not implemented.
396
397 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
398 @param[in] Configuration A null-terminated Unicode string in
399 <ConfigString> format.
400 @param[out] Progress A pointer to a string filled in with the
401 offset of the most recent '&' before the
402 first failing name / value pair (or the
403 beginn ing of the string if the failure
404 is in the first name / value pair) or
405 the terminating NULL if all was
406 successful.
407
408 @retval EFI_SUCCESS The results have been distributed or are
409 awaiting distribution.
410 @retval EFI_OUT_OF_MEMORY Not enough memory to store the
411 parts of the results that must be
412 stored awaiting possible future
413 protocols.
414 @retval EFI_INVALID_PARAMETERS Passing in a NULL for the
415 Results parameter would result
416 in this type of error.
417 @retval EFI_NOT_FOUND Target for the specified routing data
418 was not found.
419 **/
420 EFI_STATUS
421 EFIAPI
422 Ip4DeviceRouteConfig (
423 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
424 IN CONST EFI_STRING Configuration,
425 OUT EFI_STRING *Progress
426 )
427 {
428 EFI_STATUS Status;
429 UINTN BufferSize;
430 NIC_IP4_CONFIG_INFO *IfrDeviceNvData;
431 NIC_IP4_CONFIG_INFO *NicInfo;
432 IP4_FORM_CALLBACK_INFO *Private;
433 EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting;
434 IP4_CONFIG_INSTANCE *Ip4ConfigInstance;
435 EFI_MAC_ADDRESS ZeroMac;
436
437 if (Configuration == NULL) {
438 return EFI_INVALID_PARAMETER;
439 }
440
441 *Progress = Configuration;
442
443 //
444 // Check Routing data in <ConfigHdr>.
445 //
446 if (!HiiIsConfigHdrMatch (Configuration, &gEfiNicIp4ConfigVariableGuid, EFI_NIC_IP4_CONFIG_VARIABLE)) {
447 return EFI_NOT_FOUND;
448 }
449
450 Private = IP4CONFIG_FORM_CALLBACK_INFO_FROM_FORM_CALLBACK (This);
451 Ip4ConfigInstance = IP4_CONFIG_INSTANCE_FROM_IP4FORM_CALLBACK_INFO (Private);
452
453 IfrDeviceNvData = AllocateZeroPool (NIC_ITEM_CONFIG_SIZE);
454 if (IfrDeviceNvData == NULL) {
455 return EFI_OUT_OF_RESOURCES;
456 }
457
458 //
459 // Convert buffer data to <ConfigResp> by helper function BlockToConfig()
460 //
461 HiiConfigRouting = Private->ConfigRouting;
462 BufferSize = NIC_ITEM_CONFIG_SIZE;
463 Status = HiiConfigRouting->ConfigToBlock (
464 HiiConfigRouting,
465 Configuration,
466 (UINT8 *) IfrDeviceNvData,
467 &BufferSize,
468 Progress
469 );
470 if (!EFI_ERROR (Status)) {
471 ZeroMem (&ZeroMac, sizeof (EFI_MAC_ADDRESS));
472 if (CompareMem (&IfrDeviceNvData->NicAddr.MacAddr, &ZeroMac, IfrDeviceNvData->NicAddr.Len) != 0) {
473 BufferSize = sizeof (NIC_IP4_CONFIG_INFO) + sizeof (EFI_IP4_ROUTE_TABLE) * IfrDeviceNvData->Ip4Info.RouteTableSize;
474 NicInfo = AllocateCopyPool (BufferSize, IfrDeviceNvData);
475 Status = EfiNicIp4ConfigSetInfo (Ip4ConfigInstance, NicInfo, TRUE);
476 } else {
477 Status = EfiNicIp4ConfigSetInfo (Ip4ConfigInstance, NULL, TRUE);
478 }
479 }
480
481 FreePool (IfrDeviceNvData);
482 return Status;
483
484 }
485
486 /**
487 This function allows the caller to request the current
488 configuration for one or more named elements. The resulting
489 string is in <ConfigAltResp> format. Any and all alternative
490 configuration strings shall also be appended to the end of the
491 current configuration string. If they are, they must appear
492 after the current configuration. They must contain the same
493 routing (GUID, NAME, PATH) as the current configuration string.
494 They must have an additional description indicating the type of
495 alternative configuration the string represents,
496 "ALTCFG=<StringToken>". That <StringToken> (when
497 converted from Hex UNICODE to binary) is a reference to a
498 string in the associated string pack.
499
500 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
501 @param[in] Request A null-terminated Unicode string in
502 <ConfigRequest> format. Note that this
503 includes the routing information as well as
504 the configurable name / value pairs. It is
505 invalid for this string to be in
506 <MultiConfigRequest> format.
507 @param[out] Progress On return, points to a character in the
508 Request string. Points to the string's null
509 terminator if request was successful. Points
510 to the most recent "&" before the first
511 failing name / value pair (or the beginning
512 of the string if the failure is in the first
513 name / value pair) if the request was not
514 successful.
515 @param[out] Results A null-terminated Unicode string in
516 <ConfigAltResp> format which has all values
517 filled in for the names in the Request string.
518 String to be allocated by the called function.
519
520 @retval EFI_SUCCESS The Results string is filled with the
521 values corresponding to all requested
522 names.
523 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the
524 parts of the results that must be
525 stored awaiting possible future
526 protocols.
527 @retval EFI_INVALID_PARAMETER For example, passing in a NULL
528 for the Request parameter
529 would result in this type of
530 error. In this case, the
531 Progress parameter would be
532 set to NULL.
533 @retval EFI_NOT_FOUND Routing data doesn't match any
534 known driver. Progress set to the
535 first character in the routing header.
536 Note: There is no requirement that the
537 driver validate the routing data. It
538 must skip the <ConfigHdr> in order to
539 process the names.
540 @retval EFI_INVALID_PARAMETER Illegal syntax. Progress set
541 to most recent & before the
542 error or the beginning of the
543 string.
544 @retval EFI_INVALID_PARAMETER Unknown name. Progress points
545 to the & before the name in
546 question.Currently not implemented.
547 **/
548 EFI_STATUS
549 EFIAPI
550 Ip4FormExtractConfig (
551 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
552 IN CONST EFI_STRING Request,
553 OUT EFI_STRING *Progress,
554 OUT EFI_STRING *Results
555 )
556 {
557 *Progress = Request;
558 return EFI_NOT_FOUND;
559 }
560
561 /**
562 This function applies changes in a driver's configuration.
563 Input is a Configuration, which has the routing data for this
564 driver followed by name / value configuration pairs. The driver
565 must apply those pairs to its configurable storage. If the
566 driver's configuration is stored in a linear block of data
567 and the driver's name / value pairs are in <BlockConfig>
568 format, it may use the ConfigToBlock helper function (above) to
569 simplify the job. Currently not implemented.
570
571 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
572 @param[in] Configuration A null-terminated Unicode string in
573 <ConfigString> format.
574 @param[out] Progress A pointer to a string filled in with the
575 offset of the most recent '&' before the
576 first failing name / value pair (or the
577 beginn ing of the string if the failure
578 is in the first name / value pair) or
579 the terminating NULL if all was
580 successful.
581
582 @retval EFI_SUCCESS The results have been distributed or are
583 awaiting distribution.
584 @retval EFI_OUT_OF_MEMORY Not enough memory to store the
585 parts of the results that must be
586 stored awaiting possible future
587 protocols.
588 @retval EFI_INVALID_PARAMETERS Passing in a NULL for the
589 Results parameter would result
590 in this type of error.
591 @retval EFI_NOT_FOUND Target for the specified routing data
592 was not found.
593 **/
594 EFI_STATUS
595 EFIAPI
596 Ip4FormRouteConfig (
597 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
598 IN CONST EFI_STRING Configuration,
599 OUT EFI_STRING *Progress
600 )
601 {
602 return EFI_NOT_FOUND;
603 }
604
605 /**
606 This function is called to provide results data to the driver.
607 This data consists of a unique key that is used to identify
608 which data is either being passed back or being asked for.
609
610 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
611 @param[in] Action Specifies the type of action taken by the browser.
612 @param[in] QuestionId A unique value which is sent to the original
613 exporting driver so that it can identify the type
614 of data to expect. The format of the data tends to
615 vary based on the opcode that enerated the callback.
616 @param[in] Type The type of value for the question.
617 @param[in] Value A pointer to the data being sent to the original
618 exporting driver.
619 @param[out] ActionRequest On return, points to the action requested by the
620 callback function.
621
622 @retval EFI_SUCCESS The callback successfully handled the action.
623 @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the
624 variable and its data.
625 @retval EFI_DEVICE_ERROR The variable could not be saved.
626 @retval EFI_UNSUPPORTED The specified Action is not supported by the
627 callback.Currently not implemented.
628 @retval EFI_INVALID_PARAMETERS Passing in wrong parameter.
629 @retval Others Other errors as indicated.
630 **/
631 EFI_STATUS
632 EFIAPI
633 Ip4FormCallback (
634 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
635 IN EFI_BROWSER_ACTION Action,
636 IN EFI_QUESTION_ID QuestionId,
637 IN UINT8 Type,
638 IN EFI_IFR_TYPE_VALUE *Value,
639 OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest
640 )
641 {
642 IP4_CONFIG_INSTANCE *Ip4ConfigInstance;
643 IP4_FORM_CALLBACK_INFO *Private;
644 CHAR8 Ip4String[IP4_STR_MAX_SIZE];
645 CHAR16 PortString[128];
646 EFI_STRING_ID DeviceFormTitleToken;
647 IP4_CONFIG_IFR_NVDATA *IfrFormNvData;
648 IP4CONFIG_FORM_ENTRY *ConfigFormEntry;
649 EFI_IP_ADDRESS HostIp;
650 EFI_IP_ADDRESS SubnetMask;
651 EFI_IP_ADDRESS Gateway;
652 EFI_STATUS Status;
653 EFI_INPUT_KEY Key;
654 NIC_IP4_CONFIG_INFO *NicInfo;
655 EFI_IP_ADDRESS Ip;
656
657 ConfigFormEntry = NULL;
658
659 Private = IP4CONFIG_FORM_CALLBACK_INFO_FROM_FORM_CALLBACK (This);
660
661 IfrFormNvData = AllocateZeroPool (sizeof (IP4_CONFIG_IFR_NVDATA));
662 if (IfrFormNvData == NULL) {
663 return EFI_OUT_OF_RESOURCES;
664 }
665
666 //
667 // Retrive uncommitted data from Browser
668 //
669 if (!HiiGetBrowserData (&gEfiNicIp4ConfigVariableGuid, EFI_NIC_IP4_CONFIG_VARIABLE, sizeof (IP4_CONFIG_IFR_NVDATA), (UINT8 *) IfrFormNvData)) {
670 FreePool (IfrFormNvData);
671 return EFI_NOT_FOUND;
672 }
673
674 Status = EFI_SUCCESS;
675
676 switch (QuestionId) {
677
678 case KEY_DHCP_ENABLE:
679 if (IfrFormNvData->DhcpEnable == 0) {
680 Private->Current->SessionConfigData.Enabled = FALSE;
681 } else {
682 Private->Current->SessionConfigData.Enabled = TRUE;
683 }
684
685 break;
686
687 case KEY_LOCAL_IP:
688 UnicodeStrToAsciiStr (IfrFormNvData->StationAddress, Ip4String);
689 Status = Ip4AsciiStrToIp (Ip4String, &HostIp.v4);
690 if (EFI_ERROR (Status) || !Ip4IsUnicast (NTOHL (HostIp.Addr[0]), 0)) {
691 CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Invalid IP address!", NULL);
692 Status = EFI_INVALID_PARAMETER;
693 } else {
694 CopyMem (&Private->Current->SessionConfigData.LocalIp, &HostIp.v4, sizeof (HostIp.v4));
695 }
696
697 break;
698
699 case KEY_SUBNET_MASK:
700 UnicodeStrToAsciiStr (IfrFormNvData->SubnetMask, Ip4String);
701 Status = Ip4AsciiStrToIp (Ip4String, &SubnetMask.v4);
702 if (EFI_ERROR (Status) || ((SubnetMask.Addr[0] != 0) && (GetSubnetMaskPrefixLength (&SubnetMask.v4) == 0))) {
703 CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Invalid SubnetMask!", NULL);
704 Status = EFI_INVALID_PARAMETER;
705 } else {
706 CopyMem (&Private->Current->SessionConfigData.SubnetMask, &SubnetMask.v4, sizeof (SubnetMask.v4));
707 }
708
709 break;
710
711 case KEY_GATE_WAY:
712 UnicodeStrToAsciiStr (IfrFormNvData->GatewayAddress, Ip4String);
713 Status = Ip4AsciiStrToIp (Ip4String, &Gateway.v4);
714 if (EFI_ERROR (Status) || ((Gateway.Addr[0] != 0) && !Ip4IsUnicast (NTOHL (Gateway.Addr[0]), 0))) {
715 CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Invalid Gateway!", NULL);
716 Status = EFI_INVALID_PARAMETER;
717 } else {
718 CopyMem (&Private->Current->SessionConfigData.Gateway, &Gateway.v4, sizeof (Gateway.v4));
719 }
720
721 break;
722
723 case KEY_SAVE_CHANGES:
724 Ip4ConfigInstance = Private->Current->Ip4ConfigInstance;
725 NicInfo = AllocateZeroPool (sizeof (NIC_IP4_CONFIG_INFO) + 2 * sizeof (EFI_IP4_ROUTE_TABLE));
726 NicInfo->Ip4Info.RouteTable = (EFI_IP4_ROUTE_TABLE *) (NicInfo + 1);
727
728 if (!Private->Current->SessionConfigData.Enabled) {
729 CopyMem (&HostIp.v4, &Private->Current->SessionConfigData.LocalIp, sizeof (HostIp.v4));
730 CopyMem (&SubnetMask.v4, &Private->Current->SessionConfigData.SubnetMask, sizeof (SubnetMask.v4));
731 CopyMem (&Gateway.v4, &Private->Current->SessionConfigData.Gateway, sizeof (Gateway.v4));
732
733 if ((Gateway.Addr[0] != 0)) {
734 if (SubnetMask.Addr[0] == 0) {
735 CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Gateway address is set but subnet mask is zero.", NULL);
736 Status = EFI_INVALID_PARAMETER;
737 break;
738 } else if (!IP4_NET_EQUAL (HostIp.Addr[0], Gateway.Addr[0], SubnetMask.Addr[0])) {
739 CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Local IP and Gateway are not in the same subnet.", NULL);
740 Status = EFI_INVALID_PARAMETER;
741 break;
742 }
743 }
744
745 NicInfo->Source = IP4_CONFIG_SOURCE_STATIC;
746 NicInfo->Ip4Info.RouteTableSize = 2;
747
748 CopyMem (&NicInfo->Ip4Info.StationAddress, &HostIp.v4, sizeof (EFI_IPv4_ADDRESS));
749 CopyMem (&NicInfo->Ip4Info.SubnetMask, &SubnetMask.v4, sizeof (EFI_IPv4_ADDRESS));
750
751 Ip.Addr[0] = HostIp.Addr[0] & SubnetMask.Addr[0];
752
753 CopyMem (&NicInfo->Ip4Info.RouteTable[0].SubnetAddress, &Ip.v4, sizeof (EFI_IPv4_ADDRESS));
754 CopyMem (&NicInfo->Ip4Info.RouteTable[0].SubnetMask, &SubnetMask.v4, sizeof (EFI_IPv4_ADDRESS));
755 CopyMem (&NicInfo->Ip4Info.RouteTable[1].GatewayAddress, &Gateway.v4, sizeof (EFI_IPv4_ADDRESS));
756 } else {
757 NicInfo->Source = IP4_CONFIG_SOURCE_DHCP;
758 }
759
760 NicInfo->Perment = TRUE;
761 CopyMem (&NicInfo->NicAddr, &Ip4ConfigInstance->NicAddr, sizeof (NIC_ADDR));
762
763 EfiNicIp4ConfigSetInfo (Ip4ConfigInstance, NicInfo, TRUE);
764
765 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_SUBMIT;
766 break;
767
768 default:
769 if ((QuestionId >= KEY_DEVICE_ENTRY_BASE) && (QuestionId < (mNumberOfIp4Devices + KEY_DEVICE_ENTRY_BASE))) {
770 //
771 // In case goto the device configuration form, update the device form title.
772 //
773 ConfigFormEntry = Ip4GetConfigFormEntryByIndex ((UINT32) (QuestionId - KEY_DEVICE_ENTRY_BASE));
774 ASSERT (ConfigFormEntry != NULL);
775
776 Ip4ConfigInstance = ConfigFormEntry->Ip4ConfigInstance;
777
778 UnicodeSPrint (PortString, (UINTN) 128, L"Port %s", ConfigFormEntry->MacString);
779 DeviceFormTitleToken = (EFI_STRING_ID) STR_IP4_DEVICE_FORM_TITLE;
780 HiiSetString (Private->RegisteredHandle, DeviceFormTitleToken, PortString, NULL);
781
782 Ip4ConfigConvertDeviceConfigDataToIfrNvData (Ip4ConfigInstance, IfrFormNvData);
783
784 Private->Current = ConfigFormEntry;
785 }
786
787 break;
788 }
789
790 if (!EFI_ERROR (Status)) {
791
792 //
793 // Pass changed uncommitted data back to Form Browser
794 //
795 HiiSetBrowserData (&gEfiNicIp4ConfigVariableGuid, EFI_NIC_IP4_CONFIG_VARIABLE, sizeof (IP4_CONFIG_IFR_NVDATA), (UINT8 *) IfrFormNvData, NULL);
796 }
797
798 FreePool (IfrFormNvData);
799 return Status;
800 }
801
802 /**
803 Install HII Config Access protocol for network device and allocate resource.
804
805 @param[in] Instance The IP4 Config instance.
806
807 @retval EFI_SUCCESS The HII Config Access protocol is installed.
808 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
809 @retval Others Other errors as indicated.
810 **/
811 EFI_STATUS
812 Ip4ConfigDeviceInit (
813 IN IP4_CONFIG_INSTANCE *Instance
814 )
815 {
816 EFI_STATUS Status;
817 EFI_HII_DATABASE_PROTOCOL *HiiDatabase;
818 IP4_FORM_CALLBACK_INFO *CallbackInfo;
819
820 Status = gBS->LocateProtocol (&gEfiHiiDatabaseProtocolGuid, NULL, (VOID **)&HiiDatabase);
821 if (EFI_ERROR (Status)) {
822 return Status;
823 }
824
825 CallbackInfo = &Instance->Ip4FormCallbackInfo;
826
827 CallbackInfo->Signature = IP4CONFIG_FORM_CALLBACK_INFO_SIGNATURE;
828 CallbackInfo->HiiDatabase = HiiDatabase;
829
830 CallbackInfo->ConfigAccess.ExtractConfig = Ip4DeviceExtractConfig;
831 CallbackInfo->ConfigAccess.RouteConfig = Ip4DeviceRouteConfig;
832 CallbackInfo->ConfigAccess.Callback = NULL;
833
834 Status = gBS->LocateProtocol (&gEfiHiiConfigRoutingProtocolGuid, NULL, (VOID **)&CallbackInfo->ConfigRouting);
835 if (EFI_ERROR (Status)) {
836 return Status;
837 }
838
839 CallbackInfo->DriverHandle = Instance->Controller;
840 //
841 // Install Device Path Protocol and Config Access protocol to driver handle
842 //
843 Status = gBS->InstallMultipleProtocolInterfaces (
844 &CallbackInfo->DriverHandle,
845 &gEfiHiiConfigAccessProtocolGuid,
846 &CallbackInfo->ConfigAccess,
847 NULL
848 );
849 ASSERT_EFI_ERROR (Status);
850
851 return Status;
852 }
853
854 /**
855 Uninstall HII Config Access protocol for network device and free resource.
856
857 @param[in] Instance The IP4 Config instance.
858
859 @retval EFI_SUCCESS The HII Config Access protocol is uninstalled.
860 @retval Others Other errors as indicated.
861 **/
862 EFI_STATUS
863 Ip4ConfigDeviceUnload (
864 IN IP4_CONFIG_INSTANCE *Instance
865 )
866 {
867 IP4_FORM_CALLBACK_INFO *CallbackInfo;
868
869 CallbackInfo = &Instance->Ip4FormCallbackInfo;
870
871 Ip4ConfigUpdateForm (Instance, FALSE);
872
873 //
874 // Uninstall EFI_HII_CONFIG_ACCESS_PROTOCOL
875 //
876 gBS->UninstallMultipleProtocolInterfaces (
877 CallbackInfo->DriverHandle,
878 &gEfiHiiConfigAccessProtocolGuid,
879 &CallbackInfo->ConfigAccess,
880 NULL
881 );
882
883 return EFI_SUCCESS;
884 }
885
886 /**
887 Unload the network configuration form, this includes: delete all the network
888 device configuration entries, uninstall the form callback protocol and
889 free the resources used.
890
891 @retval EFI_SUCCESS The network configuration form is unloaded.
892 **/
893 EFI_STATUS
894 Ip4ConfigFormUnload (
895 VOID
896 )
897 {
898 IP4CONFIG_FORM_ENTRY *ConfigFormEntry;
899
900 while (!IsListEmpty (&mIp4ConfigFormList)) {
901 //
902 // Uninstall the device forms as the network driver instance may fail to
903 // control the controller but still install the device configuration form.
904 // In such case, upon driver unloading, the driver instance's driverbinding.
905 // stop () won't be called, so we have to take this chance here to uninstall
906 // the device form.
907 //
908 ConfigFormEntry = NET_LIST_USER_STRUCT (mIp4ConfigFormList.ForwardLink, IP4CONFIG_FORM_ENTRY, Link);
909 Ip4ConfigUpdateForm (ConfigFormEntry->Ip4ConfigInstance, FALSE);
910 }
911
912 //
913 // Remove HII package list
914 //
915 mCallbackInfo->HiiDatabase->RemovePackageList (
916 mCallbackInfo->HiiDatabase,
917 mCallbackInfo->RegisteredHandle
918 );
919
920 //
921 // Uninstall EFI_HII_CONFIG_ACCESS_PROTOCOL
922 //
923 gBS->UninstallMultipleProtocolInterfaces (
924 mCallbackInfo->DriverHandle,
925 &gEfiDevicePathProtocolGuid,
926 &mIp4ConifgHiiVendorDevicePath,
927 &gEfiHiiConfigAccessProtocolGuid,
928 &mCallbackInfo->ConfigAccess,
929 NULL
930 );
931
932 FreePool (mCallbackInfo);
933
934 return EFI_SUCCESS;
935 }
936
937 /**
938 Updates the network configuration form to add/delete an entry for the network
939 device specified by the Instance.
940
941 @param[in] Instance The IP4 Config instance.
942 @param[in] AddForm Whether to add or delete a form entry.
943
944 @retval EFI_SUCCESS The network configuration form is updated.
945 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
946 @retval Others Other errors as indicated.
947 **/
948 EFI_STATUS
949 Ip4ConfigUpdateForm (
950 IN IP4_CONFIG_INSTANCE *Instance,
951 IN BOOLEAN AddForm
952 )
953 {
954 LIST_ENTRY *Entry;
955 IP4CONFIG_FORM_ENTRY *ConfigFormEntry;
956 BOOLEAN EntryExisted;
957 EFI_STATUS Status;
958 EFI_SIMPLE_NETWORK_PROTOCOL *Snp;
959 CHAR16 PortString[128];
960 UINT16 FormIndex;
961 VOID *StartOpCodeHandle;
962 VOID *EndOpCodeHandle;
963 EFI_IFR_GUID_LABEL *StartLabel;
964 EFI_IFR_GUID_LABEL *EndLabel;
965
966 ConfigFormEntry = NULL;
967 EntryExisted = FALSE;
968
969 NET_LIST_FOR_EACH (Entry, &mIp4ConfigFormList) {
970 ConfigFormEntry = NET_LIST_USER_STRUCT (Entry, IP4CONFIG_FORM_ENTRY, Link);
971
972 if (ConfigFormEntry->Controller == Instance->Controller) {
973 EntryExisted = TRUE;
974 break;
975 }
976 }
977
978 if (AddForm) {
979 if (EntryExisted) {
980 return EFI_SUCCESS;
981 } else {
982 //
983 // Add a new form.
984 //
985 ConfigFormEntry = (IP4CONFIG_FORM_ENTRY *) AllocateZeroPool (sizeof (IP4CONFIG_FORM_ENTRY));
986 if (ConfigFormEntry == NULL) {
987 return EFI_OUT_OF_RESOURCES;
988 }
989
990 ConfigFormEntry->Ip4ConfigInstance = Instance;
991 InitializeListHead (&ConfigFormEntry->Link);
992 ConfigFormEntry->Controller = Instance->Controller;
993
994 //
995 // Get the simple network protocol and convert the MAC address into
996 // the formatted string.
997 //
998 Status = gBS->HandleProtocol (
999 Instance->Controller,
1000 &gEfiSimpleNetworkProtocolGuid,
1001 (VOID **)&Snp
1002 );
1003 ASSERT (Status == EFI_SUCCESS);
1004
1005 Ip4MacAddrToStr (&Snp->Mode->PermanentAddress, Snp->Mode->HwAddressSize, ConfigFormEntry->MacString);
1006
1007 //
1008 // Compose the Port string and create a new EFI_STRING_ID.
1009 //
1010 UnicodeSPrint (PortString, 128, L"%s %s", Instance->NicName, ConfigFormEntry->MacString);
1011 ConfigFormEntry->PortTitleToken = HiiSetString (mCallbackInfo->RegisteredHandle, 0, PortString, NULL);
1012
1013 //
1014 // Compose the help string of this port and create a new EFI_STRING_ID.
1015 //
1016 UnicodeSPrint (PortString, 128, L"Set the network parameters on eth%d %s", 0, ConfigFormEntry->MacString);
1017 ConfigFormEntry->PortTitleHelpToken = HiiSetString (mCallbackInfo->RegisteredHandle, 0, PortString, NULL);
1018
1019 InsertTailList (&mIp4ConfigFormList, &ConfigFormEntry->Link);
1020 mNumberOfIp4Devices++;
1021 }
1022 } else {
1023 ASSERT (EntryExisted);
1024
1025 mNumberOfIp4Devices--;
1026 RemoveEntryList (&ConfigFormEntry->Link);
1027 gBS->FreePool (ConfigFormEntry);
1028 }
1029
1030 //
1031 // Init OpCode Handle
1032 //
1033 StartOpCodeHandle = HiiAllocateOpCodeHandle ();
1034 ASSERT (StartOpCodeHandle != NULL);
1035
1036 EndOpCodeHandle = HiiAllocateOpCodeHandle ();
1037 ASSERT (EndOpCodeHandle != NULL);
1038
1039 //
1040 // Create Hii Extend Label OpCode as the start opcode
1041 //
1042 StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (StartOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));
1043 StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
1044 StartLabel->Number = DEVICE_ENTRY_LABEL;
1045
1046 //
1047 // Create Hii Extend Label OpCode as the end opcode
1048 //
1049 EndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (EndOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));
1050 EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
1051 EndLabel->Number = LABEL_END;
1052
1053 FormIndex = 0;
1054
1055 FormIndex = 0;
1056 NET_LIST_FOR_EACH (Entry, &mIp4ConfigFormList) {
1057 ConfigFormEntry = NET_LIST_USER_STRUCT (Entry, IP4CONFIG_FORM_ENTRY, Link);
1058
1059 HiiCreateGotoOpCode (
1060 StartOpCodeHandle, // Container for dynamic created opcodes
1061 FORMID_DEVICE_FORM, // Target Form ID
1062 ConfigFormEntry->PortTitleToken, // Prompt text
1063 ConfigFormEntry->PortTitleHelpToken, // Help text
1064 EFI_IFR_FLAG_CALLBACK, // Question flag
1065 (UINT16)(KEY_DEVICE_ENTRY_BASE + FormIndex) // Question ID
1066 );
1067
1068 FormIndex++;
1069 }
1070
1071 HiiUpdateForm (
1072 mCallbackInfo->RegisteredHandle,
1073 &gEfiNicIp4ConfigVariableGuid,
1074 FORMID_MAIN_FORM,
1075 StartOpCodeHandle, // Label DEVICE_ENTRY_LABEL
1076 EndOpCodeHandle // LABEL_END
1077 );
1078
1079 HiiFreeOpCodeHandle (StartOpCodeHandle);
1080 HiiFreeOpCodeHandle (EndOpCodeHandle);
1081
1082 return EFI_SUCCESS;
1083 }
1084
1085 /**
1086 Initialize the network configuration form, this includes: delete all the network
1087 device configuration entries, install the form callback protocol and
1088 allocate the resources used.
1089
1090 @retval EFI_SUCCESS The network configuration form is unloaded.
1091 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
1092 **/
1093 EFI_STATUS
1094 Ip4ConfigFormInit (
1095 VOID
1096 )
1097 {
1098 EFI_STATUS Status;
1099 EFI_HII_DATABASE_PROTOCOL *HiiDatabase;
1100 IP4_FORM_CALLBACK_INFO *CallbackInfo;
1101
1102 Status = gBS->LocateProtocol (&gEfiHiiDatabaseProtocolGuid, NULL, (VOID **)&HiiDatabase);
1103 if (EFI_ERROR (Status)) {
1104 return Status;
1105 }
1106
1107 CallbackInfo = (IP4_FORM_CALLBACK_INFO *) AllocateZeroPool (sizeof (IP4_FORM_CALLBACK_INFO));
1108 if (CallbackInfo == NULL) {
1109 return EFI_OUT_OF_RESOURCES;
1110 }
1111
1112 CallbackInfo->Signature = IP4CONFIG_FORM_CALLBACK_INFO_SIGNATURE;
1113 CallbackInfo->HiiDatabase = HiiDatabase;
1114
1115 CallbackInfo->ConfigAccess.ExtractConfig = Ip4FormExtractConfig;
1116 CallbackInfo->ConfigAccess.RouteConfig = Ip4FormRouteConfig;
1117 CallbackInfo->ConfigAccess.Callback = Ip4FormCallback;
1118
1119 Status = gBS->LocateProtocol (&gEfiHiiConfigRoutingProtocolGuid, NULL, (VOID **)&CallbackInfo->ConfigRouting);
1120 if (EFI_ERROR (Status)) {
1121 return Status;
1122 }
1123
1124 CallbackInfo->DriverHandle = NULL;
1125 //
1126 // Install Device Path Protocol and Config Access protocol to driver handle
1127 //
1128 Status = gBS->InstallMultipleProtocolInterfaces (
1129 &CallbackInfo->DriverHandle,
1130 &gEfiDevicePathProtocolGuid,
1131 &mIp4ConifgHiiVendorDevicePath,
1132 &gEfiHiiConfigAccessProtocolGuid,
1133 &CallbackInfo->ConfigAccess,
1134 NULL
1135 );
1136 ASSERT_EFI_ERROR (Status);
1137
1138 //
1139 // Publish our HII data
1140 //
1141 CallbackInfo->RegisteredHandle = HiiAddPackages (
1142 &gEfiNicIp4ConfigVariableGuid,
1143 CallbackInfo->DriverHandle,
1144 Ip4ConfigDxeStrings,
1145 Ip4ConfigDxeBin,
1146 NULL
1147 );
1148 if (CallbackInfo->RegisteredHandle == NULL) {
1149 return EFI_OUT_OF_RESOURCES;
1150 }
1151
1152 mCallbackInfo = CallbackInfo;
1153
1154 return Status;
1155 }