]> git.proxmox.com Git - mirror_edk2.git/blob - ShellPkg/Library/UefiShellNetwork1CommandsLib/Ifconfig.c
remove unused variable.
[mirror_edk2.git] / ShellPkg / Library / UefiShellNetwork1CommandsLib / Ifconfig.c
1 /** @file
2 The implementation for ifcommand shell command.
3
4 Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>
5
6 This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php.
10
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13 **/
14
15 #include "UefiShellNetwork1CommandsLib.h"
16
17 #define NIC_ITEM_CONFIG_SIZE (sizeof (NIC_IP4_CONFIG_INFO) + sizeof (EFI_IP4_ROUTE_TABLE) * MAX_IP4_CONFIG_IN_VARIABLE)
18 #define EFI_IP4_TO_U32(EfiIpAddr) (*(IP4_ADDR*)((EfiIpAddr).Addr))
19
20 BOOLEAN mIp4ConfigExist = FALSE;
21 STATIC EFI_HII_CONFIG_ROUTING_PROTOCOL *mHiiConfigRouting = NULL;
22
23 STATIC CONST UINTN SEC_TO_NS = 10000000;
24 STATIC CONST CHAR16 DhcpString[5] = L"DHCP";
25 STATIC CONST CHAR16 StaticString[7] = L"STATIC";
26 STATIC CONST CHAR16 PermanentString[10] = L"PERMANENT";
27
28 typedef struct {
29 LIST_ENTRY Link;
30 EFI_HANDLE Handle;
31 NIC_ADDR NicAddress;
32 CHAR16 Name[IP4_NIC_NAME_LENGTH];
33 BOOLEAN MediaPresentSupported;
34 BOOLEAN MediaPresent;
35 EFI_IP4_CONFIG_PROTOCOL *Ip4Config;
36 NIC_IP4_CONFIG_INFO *ConfigInfo;
37 } NIC_INFO;
38
39 typedef struct {
40 EFI_IP_ADDRESS DestIp;
41 EFI_MAC_ADDRESS DestMac;
42 EFI_IP_ADDRESS LocalIp;
43 EFI_MAC_ADDRESS LocalMac;
44 UINT8 MacLen;
45 EFI_EVENT OnResolved;
46 BOOLEAN Duplicate;
47 } ARP_REQUEST;
48
49 STATIC CONST SHELL_PARAM_ITEM ParamList[] = {
50 {L"-c", TypeValue},
51 {L"-l", TypeValue},
52 {L"-s", TypeMaxValue},
53 {NULL, TypeMax}
54 };
55
56 STATIC LIST_ENTRY NicInfoList;
57 STATIC BOOLEAN ArpResolved;
58 STATIC BOOLEAN mTimeout;
59
60 /**
61 Count the space delimited items in a string.
62
63 @param[in] String A pointer to the string to count.
64
65 @return The number of space-delimited items.
66 @retval 0xFF an error occured.
67 **/
68 UINT8
69 EFIAPI
70 CountSubItems (
71 IN CONST CHAR16 *String
72 )
73 {
74 CONST CHAR16 *Walker;
75 UINT8 Count;
76
77 if (String == NULL || *String == CHAR_NULL) {
78 return (0xFF);
79 }
80
81 for (Walker = String, Count = 0 ; Walker != NULL && *Walker != CHAR_NULL ; Walker = (StrStr(Walker, L" ")==NULL?NULL:StrStr(Walker, L" ")+1), Count++);
82 return (Count);
83 }
84
85 /**
86 Find the NIC_INFO by the specified nic name.
87
88 @param[in] Name The pointer to the string containing the NIC name.
89
90 @return The pointer to the NIC_INFO if there is a NIC_INFO named by Name.
91 @retval NULL No NIC_INFO was found for Name.
92 **/
93 NIC_INFO*
94 EFIAPI
95 IfconfigFindNicByName (
96 IN CONST CHAR16 *Name
97 )
98 {
99 LIST_ENTRY *Entry;
100 LIST_ENTRY *NextEntry;
101 NIC_INFO *Info;
102 CHAR16 *TempString;
103
104 NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &NicInfoList) {
105 Info = BASE_CR (Entry, NIC_INFO, Link);
106 TempString = (CHAR16*)Info->Name;
107
108 if (StringNoCaseCompare (&Name, &TempString) == 0) {
109 return Info;
110 }
111 }
112
113 return NULL;
114 }
115
116 /**
117 Tests whether a child handle is a child device of the controller.
118
119 @param[in] ControllerHandle A handle for a (parent) controller to test.
120 @param[in] ChildHandle A child handle to test.
121 @param[in] ProtocolGuid Supplies the protocol that the child controller
122 opens on its parent controller.
123
124 @retval EFI_SUCCESS ChildHandle is a child of the ControllerHandle.
125 @retval EFI_UNSUPPORTED ChildHandle is not a child of the ControllerHandle.
126 **/
127 EFI_STATUS
128 EFIAPI
129 TestChildHandle (
130 IN CONST EFI_HANDLE ControllerHandle,
131 IN CONST EFI_HANDLE ChildHandle,
132 IN CONST EFI_GUID *ProtocolGuid
133 )
134 {
135 EFI_STATUS Status;
136 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfoBuffer;
137 UINTN EntryCount;
138 UINTN Index;
139
140 ASSERT (ProtocolGuid != NULL);
141
142 //
143 // Retrieve the list of agents that are consuming the specific protocol
144 // on ControllerHandle.
145 //
146 Status = gBS->OpenProtocolInformation (
147 ControllerHandle,
148 (EFI_GUID *) ProtocolGuid,
149 &OpenInfoBuffer,
150 &EntryCount
151 );
152 if (EFI_ERROR (Status)) {
153 return EFI_UNSUPPORTED;
154 }
155
156 //
157 // Inspect if ChildHandle is one of the agents.
158 //
159 Status = EFI_UNSUPPORTED;
160 for (Index = 0; Index < EntryCount; Index++) {
161 if ((OpenInfoBuffer[Index].ControllerHandle == ChildHandle) &&
162 (OpenInfoBuffer[Index].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) {
163 Status = EFI_SUCCESS;
164 break;
165 }
166 }
167
168 FreePool (OpenInfoBuffer);
169 return Status;
170 }
171
172 /**
173 Get the child handle of the NIC handle.
174
175 @param[in] Controller Routing information: GUID.
176 @param[in] ChildHandle Returned child handle.
177
178 @retval EFI_SUCCESS Successfully to get child handle.
179 **/
180 EFI_STATUS
181 GetChildHandle (
182 IN EFI_HANDLE Controller,
183 OUT EFI_HANDLE *ChildHandle
184 )
185 {
186 EFI_STATUS Status;
187 EFI_HANDLE *Handles;
188 UINTN HandleCount;
189 UINTN Index;
190 EFI_DEVICE_PATH_PROTOCOL *ChildDeviceDevicePath;
191 VENDOR_DEVICE_PATH *VendorDeviceNode;
192
193 //
194 // Locate all EFI Hii Config Access protocols
195 //
196 Status = gBS->LocateHandleBuffer (
197 ByProtocol,
198 &gEfiHiiConfigAccessProtocolGuid,
199 NULL,
200 &HandleCount,
201 &Handles
202 );
203 if (EFI_ERROR (Status) || (HandleCount == 0)) {
204 return Status;
205 }
206
207 Status = EFI_NOT_FOUND;
208
209 for (Index = 0; Index < HandleCount; Index++) {
210
211 Status = TestChildHandle (Controller, Handles[Index], &gEfiManagedNetworkServiceBindingProtocolGuid);
212 if (!EFI_ERROR (Status)) {
213 //
214 // Get device path on the child handle
215 //
216 Status = gBS->HandleProtocol (
217 Handles[Index],
218 &gEfiDevicePathProtocolGuid,
219 (VOID **) &ChildDeviceDevicePath
220 );
221
222 if (!EFI_ERROR (Status)) {
223 while (!IsDevicePathEnd (ChildDeviceDevicePath)) {
224 ChildDeviceDevicePath = NextDevicePathNode (ChildDeviceDevicePath);
225 //
226 // Parse one instance
227 //
228 if (ChildDeviceDevicePath->Type == HARDWARE_DEVICE_PATH &&
229 ChildDeviceDevicePath->SubType == HW_VENDOR_DP) {
230 VendorDeviceNode = (VENDOR_DEVICE_PATH *) ChildDeviceDevicePath;
231 if (CompareMem (&VendorDeviceNode->Guid, &gEfiNicIp4ConfigVariableGuid, sizeof (EFI_GUID)) == 0) {
232 //
233 // Found item matched gEfiNicIp4ConfigVariableGuid
234 //
235 *ChildHandle = Handles[Index];
236 FreePool (Handles);
237 return EFI_SUCCESS;
238 }
239 }
240 }
241 }
242 }
243 }
244
245 FreePool (Handles);
246 return Status;
247 }
248
249 /**
250 Append OFFSET/WIDTH/VALUE items at the beginning of string.
251
252 @param[in,out] String The pointer to the string to append onto.
253 @param[in] Offset Offset value.
254 @param[in] Width Width value.
255 @param[in] Block Point to data buffer.
256
257 @return The count of unicode character that were appended.
258 **/
259 UINTN
260 EFIAPI
261 AppendOffsetWidthValue (
262 IN OUT CHAR16 *String,
263 IN UINTN Offset,
264 IN UINTN Width,
265 IN CONST UINT8 *Block
266 )
267
268 {
269 CHAR16 *OriString;
270
271 OriString = String;
272
273 StrCpy (String, L"&OFFSET=");
274 String += StrLen (L"&OFFSET=");
275 String += UnicodeSPrint (String, 20, L"%x", Offset);
276
277 StrCpy (String,L"&WIDTH=");
278 String += StrLen (L"&WIDTH=");
279 String += UnicodeSPrint (String, 20, L"%x", Width);
280
281 if (Block != NULL) {
282 StrCpy (String,L"&VALUE=");
283 String += StrLen (L"&VALUE=");
284 while ((Width--) != 0) {
285 String += UnicodeSPrint (String, 20, L"%x", Block[Width]);
286 }
287 }
288
289 return String - OriString;
290 }
291
292 /**
293 Converts the unicode character of the string from uppercase to lowercase.
294 This is a internal function.
295
296 @param ConfigString String to be converted
297 **/
298 CHAR16*
299 EFIAPI
300 HiiToLower (
301 IN CHAR16 *ConfigString
302 )
303 {
304 CHAR16 *String;
305 BOOLEAN Lower;
306
307 //
308 // Convert all hex digits in range [A-F] in the configuration header to [a-f]
309 //
310 for (String = ConfigString, Lower = FALSE; String != NULL && *String != L'\0'; String++) {
311 if (*String == L'=') {
312 Lower = TRUE;
313 } else if (*String == L'&') {
314 Lower = FALSE;
315 } else if (Lower && *String >= L'A' && *String <= L'F') {
316 *String = (CHAR16) (*String - L'A' + L'a');
317 }
318 }
319
320 return (ConfigString);
321 }
322
323
324 /**
325 Construct <ConfigHdr> using routing information GUID/NAME/PATH.
326
327 @param[in] Guid Routing information: GUID.
328 @param[in] Name Routing information: NAME.
329 @param[in] DriverHandle Driver handle which contains the routing information: PATH.
330
331 @retval NULL An error occured.
332 @return The pointer to configHdr string.
333 **/
334 CHAR16 *
335 EFIAPI
336 ConstructConfigHdr (
337 IN CONST EFI_GUID *Guid,
338 IN CONST CHAR16 *Name,
339 IN EFI_HANDLE DriverHandle
340 )
341 {
342 EFI_STATUS Status;
343 CHAR16 *ConfigHdr;
344 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
345 CHAR16 *String;
346 UINTN Index;
347 UINT8 *Buffer;
348 UINTN DevicePathLength;
349 UINTN NameLength;
350
351 //
352 // Get the device path from handle installed EFI HII Config Access protocol
353 //
354 Status = gBS->HandleProtocol (
355 DriverHandle,
356 &gEfiDevicePathProtocolGuid,
357 (VOID **) &DevicePath
358 );
359 if (EFI_ERROR (Status)) {
360 return NULL;
361 }
362
363 DevicePathLength = GetDevicePathSize (DevicePath);
364 NameLength = StrLen (Name);
365 ConfigHdr = AllocateZeroPool ((5 + sizeof (EFI_GUID) * 2 + 6 + NameLength * 4 + 6 + DevicePathLength * 2 + 1) * sizeof (CHAR16));
366 if (ConfigHdr == NULL) {
367 return NULL;
368 }
369
370 String = ConfigHdr;
371 StrCpy (String, L"GUID=");
372 String += StrLen (L"GUID=");
373
374 //
375 // Append Guid converted to <HexCh>32
376 //
377 for (Index = 0, Buffer = (UINT8 *)Guid; Index < sizeof (EFI_GUID); Index++) {
378 String += UnicodeSPrint (String, 6, L"%02x", *Buffer++);
379 }
380
381 //
382 // Append L"&NAME="
383 //
384 StrCpy (String, L"&NAME=");
385 String += StrLen (L"&NAME=");
386 for (Index = 0; Index < NameLength ; Index++) {
387 String += UnicodeSPrint (String, 10, L"00%x", Name[Index]);
388 }
389
390 //
391 // Append L"&PATH="
392 //
393 StrCpy (String, L"&PATH=");
394 String += StrLen (L"&PATH=");
395 for (Index = 0, Buffer = (UINT8 *) DevicePath; Index < DevicePathLength; Index++) {
396 String += UnicodeSPrint (String, 6, L"%02x", *Buffer++);
397 }
398
399 return (HiiToLower(ConfigHdr));
400 }
401
402 /**
403 Get network physical device NIC information.
404
405 @param[in] Handle The network physical device handle.
406 @param[out] NicAddr NIC information.
407
408 @retval EFI_SUCCESS Get NIC information successfully.
409 **/
410 EFI_STATUS
411 EFIAPI
412 IfConfigGetNicMacInfo (
413 IN EFI_HANDLE Handle,
414 OUT NIC_ADDR *NicAddr
415 )
416 {
417 EFI_STATUS Status;
418 EFI_HANDLE MnpHandle;
419 EFI_SIMPLE_NETWORK_MODE SnpMode;
420 EFI_MANAGED_NETWORK_PROTOCOL *Mnp;
421
422 MnpHandle = NULL;
423 Mnp = NULL;
424
425 Status = NetLibCreateServiceChild (
426 Handle,
427 gImageHandle,
428 &gEfiManagedNetworkServiceBindingProtocolGuid,
429 &MnpHandle
430 );
431 if (EFI_ERROR (Status)) {
432 return Status;
433 }
434
435 Status = gBS->HandleProtocol (
436 MnpHandle,
437 &gEfiManagedNetworkProtocolGuid,
438 (VOID **) &Mnp
439 );
440 if (EFI_ERROR (Status)) {
441 goto ON_ERROR;
442 }
443
444 Status = Mnp->GetModeData (Mnp, NULL, &SnpMode);
445 if (EFI_ERROR (Status) && (Status != EFI_NOT_STARTED)) {
446 goto ON_ERROR;
447 }
448
449 NicAddr->Type = (UINT16) SnpMode.IfType;
450 NicAddr->Len = (UINT8) SnpMode.HwAddressSize;
451 CopyMem (&NicAddr->MacAddr, &SnpMode.CurrentAddress, NicAddr->Len);
452
453 ON_ERROR:
454
455 NetLibDestroyServiceChild (
456 Handle,
457 gImageHandle,
458 &gEfiManagedNetworkServiceBindingProtocolGuid,
459 MnpHandle
460 );
461
462 return Status;
463
464 }
465
466 /**
467 Get network physical device NIC information.
468
469 @param[in] Handle The network physical device handle.
470 @param[out] MediaPresentSupported
471 Upon successful return, TRUE is media present
472 is supported. FALSE otherwise.
473 @param[out] MediaPresent Upon successful return, TRUE is media present
474 is enabled. FALSE otherwise.
475
476 @retval EFI_SUCCESS The operation was successful.
477 **/
478 EFI_STATUS
479 EFIAPI
480 IfConfigGetNicMediaStatus (
481 IN EFI_HANDLE Handle,
482 OUT BOOLEAN *MediaPresentSupported,
483 OUT BOOLEAN *MediaPresent
484 )
485
486 {
487 EFI_STATUS Status;
488 EFI_HANDLE MnpHandle;
489 EFI_SIMPLE_NETWORK_MODE SnpMode;
490 EFI_MANAGED_NETWORK_PROTOCOL *Mnp;
491
492 MnpHandle = NULL;
493 Mnp = NULL;
494
495 Status = NetLibCreateServiceChild (
496 Handle,
497 gImageHandle,
498 &gEfiManagedNetworkServiceBindingProtocolGuid,
499 &MnpHandle
500 );
501 if (EFI_ERROR (Status)) {
502 return Status;
503 }
504
505 Status = gBS->HandleProtocol (
506 MnpHandle,
507 &gEfiManagedNetworkProtocolGuid,
508 (VOID **) &Mnp
509 );
510 if (EFI_ERROR (Status)) {
511 goto ON_ERROR;
512 }
513
514 Status = Mnp->GetModeData (Mnp, NULL, &SnpMode);
515 if (EFI_ERROR (Status) && (Status != EFI_NOT_STARTED)) {
516 goto ON_ERROR;
517 }
518
519 *MediaPresentSupported = SnpMode.MediaPresentSupported;
520 *MediaPresent = SnpMode.MediaPresent;
521
522 ON_ERROR:
523
524 NetLibDestroyServiceChild (
525 Handle,
526 gImageHandle,
527 &gEfiManagedNetworkServiceBindingProtocolGuid,
528 MnpHandle
529 );
530
531 return Status;
532
533 }
534
535 /**
536 Get all Nic's information through HII service.
537
538 @retval EFI_SUCCESS All the nic information is collected.
539 **/
540 EFI_STATUS
541 EFIAPI
542 IfconfigGetAllNicInfoByHii (
543 VOID
544 )
545 {
546 EFI_STATUS Status;
547 EFI_HANDLE *Handles;
548 UINTN HandleCount;
549 CHAR16 *ConfigResp;
550 CHAR16 *ConfigHdr;
551 UINTN Index;
552 CHAR16 *AccessProgress;
553 CHAR16 *AccessResults;
554 UINTN BufferSize;
555 NIC_INFO *NicInfo;
556 NIC_IP4_CONFIG_INFO *NicConfigRequest;
557 NIC_IP4_CONFIG_INFO *NicConfig;
558 CHAR16 *String;
559 UINTN Length;
560 UINTN Offset;
561 EFI_HANDLE ChildHandle;
562
563 AccessResults = NULL;
564 ConfigHdr = NULL;
565 ConfigResp = NULL;
566 NicConfigRequest = NULL;
567 NicInfo = NULL;
568
569 InitializeListHead (&NicInfoList);
570
571 //
572 // Check if HII Config Routing protocol available.
573 //
574 Status = gBS->LocateProtocol (
575 &gEfiHiiConfigRoutingProtocolGuid,
576 NULL,
577 (VOID**)&mHiiConfigRouting
578 );
579 if (EFI_ERROR (Status)) {
580 return EFI_NOT_FOUND;
581 }
582
583 //
584 // Locate all network device handles
585 //
586 Status = gBS->LocateHandleBuffer (
587 ByProtocol,
588 &gEfiManagedNetworkServiceBindingProtocolGuid,
589 NULL,
590 &HandleCount,
591 &Handles
592 );
593 if (EFI_ERROR (Status) || (HandleCount == 0)) {
594 return EFI_NOT_FOUND;
595 }
596
597 for (Index = 0; Index < HandleCount; Index++) {
598 Status = GetChildHandle (Handles[Index], &ChildHandle);
599 if (EFI_ERROR (Status)) {
600 //
601 // If failed to get Child handle, try NIC controller handle for back-compatibility.
602 //
603 ChildHandle = Handles[Index];
604 }
605 //
606 // Construct configuration request string header
607 //
608 ConfigHdr = ConstructConfigHdr (&gEfiNicIp4ConfigVariableGuid, EFI_NIC_IP4_CONFIG_VARIABLE, ChildHandle);
609 Length = StrLen (ConfigHdr);
610 ConfigResp = AllocateZeroPool ((Length + NIC_ITEM_CONFIG_SIZE * 2 + 100) * sizeof (CHAR16));
611 if (ConfigResp == NULL) {
612 Status = EFI_OUT_OF_RESOURCES;
613 goto ON_ERROR;
614 }
615 StrCpy (ConfigResp, ConfigHdr);
616
617 //
618 // Append OFFSET/WIDTH pair
619 //
620 String = ConfigResp + Length;
621 Offset = 0;
622 AppendOffsetWidthValue (String, Offset, NIC_ITEM_CONFIG_SIZE, NULL);
623
624 NicInfo = AllocateZeroPool (sizeof (NIC_INFO));
625 if (NicInfo == NULL) {
626 Status = EFI_OUT_OF_RESOURCES;
627 goto ON_ERROR;
628 }
629 NicInfo->Handle = Handles[Index];
630
631 //
632 // Get network physical devcie MAC information
633 //
634 IfConfigGetNicMacInfo (Handles[Index], &NicInfo->NicAddress);
635 if (NicInfo->NicAddress.Type == NET_IFTYPE_ETHERNET) {
636 UnicodeSPrint (NicInfo->Name, IP4_NIC_NAME_LENGTH, L"eth%d", Index);
637 } else {
638 UnicodeSPrint (NicInfo->Name, IP4_NIC_NAME_LENGTH, L"unk%d", Index);
639 }
640
641 //
642 // Get media status
643 //
644 IfConfigGetNicMediaStatus (Handles[Index], &NicInfo->MediaPresentSupported, &NicInfo->MediaPresent);
645
646 NicConfigRequest = AllocateZeroPool (NIC_ITEM_CONFIG_SIZE);
647 if (NicConfigRequest == NULL) {
648 Status = EFI_OUT_OF_RESOURCES;
649 goto ON_ERROR;
650 }
651
652 //
653 // Get network parameters by HII service
654 //
655 Status = mHiiConfigRouting->ExtractConfig (
656 mHiiConfigRouting,
657 ConfigResp,
658 &AccessProgress,
659 &AccessResults
660 );
661 if (!EFI_ERROR (Status)) {
662 BufferSize = NIC_ITEM_CONFIG_SIZE;
663 Status = mHiiConfigRouting->ConfigToBlock (
664 mHiiConfigRouting,
665 AccessResults,
666 (UINT8 *) NicConfigRequest,
667 &BufferSize,
668 &AccessProgress
669 );
670 if (!EFI_ERROR (Status)) {
671 BufferSize = sizeof (NIC_IP4_CONFIG_INFO) + sizeof (EFI_IP4_ROUTE_TABLE) * NicConfigRequest->Ip4Info.RouteTableSize;
672 NicConfig = AllocateZeroPool (BufferSize);
673 if (NicConfig == NULL) {
674 Status = EFI_OUT_OF_RESOURCES;
675 goto ON_ERROR;
676 }
677 CopyMem (NicConfig, NicConfigRequest, BufferSize);
678
679 //
680 // If succeeds to get NIC configuration, fix up routetable pointer.
681 //
682 NicConfig->Ip4Info.RouteTable = (EFI_IP4_ROUTE_TABLE *) (&NicConfig->Ip4Info + 1);
683 NicInfo->ConfigInfo = NicConfig;
684
685 } else {
686 NicInfo->ConfigInfo = NULL;
687 }
688
689 FreePool (AccessResults);
690
691 } else {
692 NicInfo->ConfigInfo = NULL;
693 }
694
695 //
696 // Add the Nic's info to the global NicInfoList.
697 //
698 InsertTailList (&NicInfoList, &NicInfo->Link);
699
700 FreePool (NicConfigRequest);
701 FreePool (ConfigResp);
702 FreePool (ConfigHdr);
703 }
704
705 FreePool (Handles);
706
707 return EFI_SUCCESS;
708
709 ON_ERROR:
710 if (AccessResults != NULL) {
711 FreePool (AccessResults);
712 }
713 if (NicConfigRequest != NULL) {
714 FreePool (NicConfigRequest);
715 }
716 if (NicInfo != NULL) {
717 FreePool (NicInfo);
718 }
719 if (ConfigResp != NULL) {
720 FreePool (ConfigResp);
721 }
722 if (ConfigHdr != NULL) {
723 FreePool (ConfigHdr);
724 }
725
726 FreePool (Handles);
727
728 return Status;
729 }
730
731 /**
732 Set the address for the specified nic by HII service.
733
734 @param[in] NicInfo A pointer to the NIC_INFO of the Nic to be configured.
735 @param[in] Config The command line arguments for the set operation.
736
737 @retval EFI_SUCCESS The address set operation is done.
738 **/
739 SHELL_STATUS
740 EFIAPI
741 IfconfigSetNicAddrByHii (
742 IN CONST NIC_INFO *NicInfo,
743 IN CONST NIC_IP4_CONFIG_INFO *Config
744 )
745 {
746 EFI_STATUS Status;
747 SHELL_STATUS ShellStatus;
748 NIC_IP4_CONFIG_INFO *NicConfig;
749 CHAR16 *ConfigResp;
750 CHAR16 *ConfigHdr;
751 CHAR16 *AccessProgress;
752 CHAR16 *AccessResults;
753 CHAR16 *String;
754 UINTN Length;
755 UINTN Offset;
756 EFI_HANDLE ChildHandle;
757
758 AccessResults = NULL;
759 ConfigHdr = NULL;
760 ConfigResp = NULL;
761 NicConfig = NULL;
762 ShellStatus = SHELL_SUCCESS;
763
764 Status = GetChildHandle (NicInfo->Handle, &ChildHandle);
765 if (EFI_ERROR (Status)) {
766 //
767 // If failed to get Child handle, try NIC controller handle for back-compatibility
768 //
769 ChildHandle = NicInfo->Handle;
770 }
771 //
772 // Construct config request string header
773 //
774 ConfigHdr = ConstructConfigHdr (&gEfiNicIp4ConfigVariableGuid, EFI_NIC_IP4_CONFIG_VARIABLE, ChildHandle);
775
776 Length = StrLen (ConfigHdr);
777 ConfigResp = AllocateZeroPool ((Length + NIC_ITEM_CONFIG_SIZE * 2 + 100) * sizeof (CHAR16));
778 StrCpy (ConfigResp, ConfigHdr);
779
780 NicConfig = AllocateZeroPool (NIC_ITEM_CONFIG_SIZE);
781 if (NicConfig == NULL) {
782 ShellStatus = SHELL_OUT_OF_RESOURCES;
783 goto ON_EXIT;
784 }
785
786 if (Config != NULL) {
787 CopyMem (NicConfig, Config, sizeof (NIC_IP4_CONFIG_INFO) + sizeof (EFI_IP4_ROUTE_TABLE) * Config->Ip4Info.RouteTableSize);
788 }
789
790 //
791 // Append OFFSET/WIDTH pair
792 //
793 String = ConfigResp + Length;
794 Offset = 0;
795 AppendOffsetWidthValue (String, Offset, NIC_ITEM_CONFIG_SIZE, NULL);
796
797 //
798 // Call HII helper function to generate configuration string
799 //
800 Status = mHiiConfigRouting->BlockToConfig (
801 mHiiConfigRouting,
802 ConfigResp,
803 (UINT8 *) NicConfig,
804 NIC_ITEM_CONFIG_SIZE,
805 &AccessResults,
806 &AccessProgress
807 );
808 if (EFI_ERROR (Status)) {
809 ShellStatus = SHELL_NOT_FOUND;
810 goto ON_EXIT;
811 }
812
813 //
814 // Set IP setting by HII servie
815 //
816 Status = mHiiConfigRouting->RouteConfig (
817 mHiiConfigRouting,
818 AccessResults,
819 &AccessProgress
820 );
821 if (EFI_ERROR(Status)) {
822 ShellStatus = SHELL_ACCESS_DENIED;
823 }
824
825 ON_EXIT:
826 SHELL_FREE_NON_NULL(AccessResults);
827 SHELL_FREE_NON_NULL(NicConfig);
828 SHELL_FREE_NON_NULL(ConfigResp);
829 SHELL_FREE_NON_NULL(ConfigHdr);
830
831 return ShellStatus;
832 }
833
834 /**
835 The callback function for the Arp address resolved event.
836
837 @param[in] Event The event this function is registered to.
838 @param[in] Context The context registered to the event.
839 **/
840 VOID
841 EFIAPI
842 IfconfigOnArpResolved (
843 IN EFI_EVENT Event,
844 IN VOID *Context
845 )
846 {
847 ARP_REQUEST *Request;
848 UINT8 Index;
849
850 Request = (ARP_REQUEST *) Context;
851 ASSERT (Request != NULL);
852
853 Request->Duplicate = FALSE;
854
855 if (0 == CompareMem (&Request->LocalMac, &Request->DestMac, Request->MacLen)) {
856 ShellPrintHiiEx(
857 -1,
858 -1,
859 NULL,
860 STRING_TOKEN (STR_IFCONFIG_SHOW_IP_ADDR),
861 gShellNetwork1HiiHandle,
862 L"Already Configured",
863 (UINTN)Request->DestIp.v4.Addr[0],
864 (UINTN)Request->DestIp.v4.Addr[1],
865 (UINTN)Request->DestIp.v4.Addr[2],
866 (UINTN)Request->DestIp.v4.Addr[3]
867 );
868 ArpResolved = TRUE;
869 return;
870 }
871
872 for (Index = 0; Index < Request->MacLen; Index++) {
873 if (Request->DestMac.Addr[Index] != 0) {
874 Request->Duplicate = TRUE;
875 }
876 }
877
878 if (Request->Duplicate) {
879 ShellPrintHiiEx(
880 -1,
881 -1,
882 NULL,
883 STRING_TOKEN(STR_IFCONFIG_CONF_IP_ADDR),
884 gShellNetwork1HiiHandle,
885 (UINTN)Request->DestMac.Addr[0],
886 (UINTN)Request->DestMac.Addr[1],
887 (UINTN)Request->DestMac.Addr[2],
888 (UINTN)Request->DestMac.Addr[3],
889 (UINTN)Request->DestMac.Addr[4],
890 (UINTN)Request->DestMac.Addr[5]
891 );
892 }
893
894 ArpResolved = TRUE;
895 return ;
896 }
897
898 /**
899 Check whether the address to be configured conflicts with other hosts.
900
901 @param[in] NicInfo The pointer to the NIC_INFO of the Nic to be configured.
902 @param[in] IpAddr The IPv4 address to be configured to the Nic.
903
904 @return TRUE Some other host already uses the IpAddr.
905 @return FALSE The address is unused.
906 **/
907 BOOLEAN
908 EFIAPI
909 IfconfigIsIpDuplicate (
910 IN NIC_INFO *NicInfo,
911 IN IP4_ADDR IpAddr
912 )
913 {
914 EFI_ARP_PROTOCOL *Arp;
915 EFI_ARP_CONFIG_DATA ArpCfgData;
916 EFI_HANDLE ArpHandle;
917 ARP_REQUEST Request;
918 EFI_STATUS Status;
919
920 Arp = NULL;
921 ArpHandle = NULL;
922 ZeroMem (&Request, sizeof (ARP_REQUEST));
923
924 Status = NetLibCreateServiceChild (
925 NicInfo->Handle,
926 gImageHandle,
927 &gEfiArpServiceBindingProtocolGuid,
928 &ArpHandle
929 );
930
931 if (EFI_ERROR (Status)) {
932 return FALSE;
933 }
934
935 Status = gBS->OpenProtocol (
936 ArpHandle,
937 &gEfiArpProtocolGuid,
938 (VOID**)&Arp,
939 gImageHandle,
940 ArpHandle,
941 EFI_OPEN_PROTOCOL_GET_PROTOCOL
942 );
943
944 if (EFI_ERROR (Status)) {
945 goto ON_EXIT;
946 }
947
948 //
949 // Set up the Arp requests
950 //
951 EFI_IP4_TO_U32 (Request.DestIp.v4) = IpAddr;
952 EFI_IP4_TO_U32 (Request.LocalIp.v4) = 0xffffffff;
953 Request.LocalMac = NicInfo->NicAddress.MacAddr;
954 Request.MacLen = NicInfo->NicAddress.Len;
955
956 Status = gBS->CreateEvent (
957 EVT_NOTIFY_SIGNAL,
958 TPL_CALLBACK,
959 IfconfigOnArpResolved,
960 (VOID *) &Request,
961 &Request.OnResolved
962 );
963
964 if (EFI_ERROR (Status)) {
965 goto ON_EXIT;
966 }
967
968 ArpCfgData.SwAddressType = 0x0800;
969 ArpCfgData.SwAddressLength = 4;
970 ArpCfgData.StationAddress = &Request.LocalIp;
971 ArpCfgData.EntryTimeOut = 0;
972 ArpCfgData.RetryCount = 3;
973 ArpCfgData.RetryTimeOut = 0;
974
975 Status = Arp->Configure (Arp, &ArpCfgData);
976
977 if (EFI_ERROR (Status)) {
978 goto ON_EXIT;
979 }
980
981 Status = Arp->Request (
982 Arp,
983 &Request.DestIp,
984 Request.OnResolved,
985 &Request.DestMac
986 );
987
988 if (EFI_ERROR (Status) && (Status != EFI_NOT_READY)) {
989 goto ON_EXIT;
990 }
991
992 while (!ArpResolved) {
993
994 }
995
996 ON_EXIT:
997 if (Request.OnResolved != NULL) {
998 gBS->CloseEvent (Request.OnResolved);
999 }
1000
1001 NetLibDestroyServiceChild (
1002 NicInfo->Handle,
1003 gImageHandle,
1004 &gEfiArpServiceBindingProtocolGuid,
1005 ArpHandle
1006 );
1007
1008 return Request.Duplicate;
1009 }
1010
1011 /**
1012 The callback function for the timer event used to get map.
1013
1014 @param[in] Event The event this function is registered to.
1015 @param[in] Context The context registered to the event.
1016 **/
1017 VOID
1018 EFIAPI
1019 TimeoutToGetMap (
1020 IN EFI_EVENT Event,
1021 IN VOID *Context
1022 )
1023 {
1024 mTimeout = TRUE;
1025 return ;
1026 }
1027
1028 /**
1029 Create an IP child, use it to start the auto configuration, then destory it.
1030
1031 @param[in] NicInfo The pointer to the NIC_INFO of the Nic to be configured.
1032
1033 @retval EFI_SUCCESS The configuration is done.
1034 **/
1035 EFI_STATUS
1036 EFIAPI
1037 IfconfigStartIp4(
1038 IN NIC_INFO *NicInfo
1039 )
1040 {
1041 EFI_IP4_PROTOCOL *Ip4;
1042 EFI_HANDLE Ip4Handle;
1043 EFI_HANDLE TimerToGetMap;
1044 EFI_IP4_CONFIG_DATA Ip4ConfigData;
1045 EFI_IP4_MODE_DATA Ip4Mode;
1046 EFI_STATUS Status;
1047
1048 //
1049 // Get the Ip4ServiceBinding Protocol
1050 //
1051 Ip4Handle = NULL;
1052 Ip4 = NULL;
1053 TimerToGetMap = NULL;
1054
1055 ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_START_SET_ADDR), gShellNetwork1HiiHandle);
1056
1057 Status = NetLibCreateServiceChild (
1058 NicInfo->Handle,
1059 gImageHandle,
1060 &gEfiIp4ServiceBindingProtocolGuid,
1061 &Ip4Handle
1062 );
1063
1064 if (EFI_ERROR (Status)) {
1065 return Status;
1066 }
1067
1068 Status = gBS->OpenProtocol (
1069 Ip4Handle,
1070 &gEfiIp4ProtocolGuid,
1071 (VOID **) &Ip4,
1072 NicInfo->Handle,
1073 gImageHandle,
1074 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1075 );
1076
1077 if (EFI_ERROR (Status)) {
1078 goto ON_EXIT;
1079 }
1080
1081 Ip4ConfigData.DefaultProtocol = EFI_IP_PROTO_ICMP;
1082 Ip4ConfigData.AcceptAnyProtocol = FALSE;
1083 Ip4ConfigData.AcceptIcmpErrors = FALSE;
1084 Ip4ConfigData.AcceptBroadcast = FALSE;
1085 Ip4ConfigData.AcceptPromiscuous = FALSE;
1086 Ip4ConfigData.UseDefaultAddress = TRUE;
1087 ZeroMem (&Ip4ConfigData.StationAddress, sizeof (EFI_IPv4_ADDRESS));
1088 ZeroMem (&Ip4ConfigData.SubnetMask, sizeof (EFI_IPv4_ADDRESS));
1089 Ip4ConfigData.TypeOfService = 0;
1090 Ip4ConfigData.TimeToLive = 1;
1091 Ip4ConfigData.DoNotFragment = FALSE;
1092 Ip4ConfigData.RawData = FALSE;
1093 Ip4ConfigData.ReceiveTimeout = 0;
1094 Ip4ConfigData.TransmitTimeout = 0;
1095
1096 Status = Ip4->Configure (Ip4, &Ip4ConfigData);
1097
1098 if (Status == EFI_NO_MAPPING) {
1099 mTimeout = FALSE;
1100 Status = gBS->CreateEvent (
1101 EVT_NOTIFY_SIGNAL | EVT_TIMER,
1102 TPL_CALLBACK - 1,
1103 TimeoutToGetMap,
1104 NULL,
1105 &TimerToGetMap
1106 );
1107
1108 if (EFI_ERROR (Status)) {
1109 goto ON_EXIT;
1110 }
1111
1112 Status = gBS->SetTimer (
1113 TimerToGetMap,
1114 TimerRelative,
1115 MultU64x32 (SEC_TO_NS, 5)
1116 );
1117
1118 if (EFI_ERROR (Status)) {
1119 goto ON_EXIT;
1120 }
1121
1122 ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_WAIT_SET_DONE), gShellNetwork1HiiHandle);
1123
1124 while (!mTimeout) {
1125 Ip4->Poll (Ip4);
1126
1127 if (!EFI_ERROR (Ip4->GetModeData (Ip4, &Ip4Mode, NULL, NULL)) &&
1128 Ip4Mode.IsConfigured) {
1129 break;
1130 }
1131 }
1132 }
1133
1134 Status = Ip4->GetModeData (Ip4, &Ip4Mode, NULL, NULL);
1135
1136 if ((Status == EFI_SUCCESS) && Ip4Mode.IsConfigured) {
1137 ShellPrintHiiEx(
1138 -1,
1139 -1,
1140 NULL,
1141 STRING_TOKEN (STR_IFCONFIG_SHOW_IP_ADDR),
1142 gShellNetwork1HiiHandle,
1143 L"Default",
1144 (UINTN)Ip4Mode.ConfigData.StationAddress.Addr[0],
1145 (UINTN)Ip4Mode.ConfigData.StationAddress.Addr[1],
1146 (UINTN)Ip4Mode.ConfigData.StationAddress.Addr[2],
1147 (UINTN)Ip4Mode.ConfigData.StationAddress.Addr[3]
1148 );
1149 }
1150
1151 ON_EXIT:
1152
1153 if (EFI_ERROR (Status)) {
1154 ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_GET_DEF_ADDR_FAIL), gShellNetwork1HiiHandle);
1155 }
1156
1157 if (TimerToGetMap != NULL) {
1158 gBS->SetTimer (TimerToGetMap, TimerCancel, 0);
1159 gBS->CloseEvent (TimerToGetMap);
1160 }
1161
1162 NetLibDestroyServiceChild (
1163 NicInfo->Handle,
1164 gImageHandle,
1165 &gEfiIp4ServiceBindingProtocolGuid,
1166 Ip4Handle
1167 );
1168
1169 return Status;
1170 }
1171
1172 /**
1173 Set the address for the nic specified by the params.
1174
1175 @param[in] Argc The count of the passed in Params.
1176 @param[in] Params The command line arguments for the set operation.
1177
1178 @retval EFI_SUCCESS The address set operation is done.
1179 @return Some error occurs.
1180 **/
1181 SHELL_STATUS
1182 EFIAPI
1183 IfconfigSetNicAddr (
1184 IN UINTN Argc,
1185 IN CONST CHAR16 *Params
1186 )
1187 {
1188 NIC_IP4_CONFIG_INFO *Config;
1189 NIC_IP4_CONFIG_INFO *OldConfig;
1190 EFI_IP_ADDRESS Ip;
1191 EFI_IP_ADDRESS Mask;
1192 EFI_IP_ADDRESS Gateway;
1193 NIC_INFO *Info;
1194 BOOLEAN Permanent;
1195 SHELL_STATUS ShellStatus;
1196 CONST CHAR16 *Walker;
1197 CHAR16 *Temp;
1198 CONST CHAR16 *DhcpTemp;
1199 CONST CHAR16 *StaticTemp;
1200 CONST CHAR16 *PermTemp;
1201 UINT32 NetworkBytes1;
1202 UINT32 NetworkBytes2;
1203 EFI_STATUS Status;
1204
1205 Walker = Params;
1206 Temp = NULL;
1207 Temp = StrnCatGrow(&Temp, NULL, Walker, StrStr(Walker, L" ")-Walker);
1208 Info = IfconfigFindNicByName (Temp);
1209
1210 if (Info == NULL) {
1211 ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_INTERFACE_NOT_FOUND), gShellNetwork1HiiHandle, Temp);
1212 return SHELL_NOT_FOUND;
1213 }
1214
1215 Walker += StrLen(Temp) + 1;
1216 FreePool(Temp);
1217 Temp = NULL;
1218 Temp = StrnCatGrow(&Temp, NULL, Walker, StrStr(Walker, L" ")==NULL?0:StrStr(Walker, L" ")-Walker);
1219
1220 Config = AllocateZeroPool (sizeof (NIC_IP4_CONFIG_INFO) + 2 * sizeof (EFI_IP4_ROUTE_TABLE));
1221 if (Config == NULL) {
1222 return SHELL_OUT_OF_RESOURCES;
1223 }
1224
1225 Config->Ip4Info.RouteTable = (EFI_IP4_ROUTE_TABLE *) (Config + 1);
1226
1227 OldConfig = Info->ConfigInfo;
1228 Permanent = FALSE;
1229 ShellStatus = SHELL_INVALID_PARAMETER;
1230
1231 DhcpTemp = DhcpString;
1232 StaticTemp = StaticString;
1233
1234 if (StringNoCaseCompare(&Temp, &DhcpTemp) == 0) {
1235 //
1236 // Validate the parameter for DHCP, two valid forms: eth0 DHCP and eth0 DHCP perment
1237 //
1238 if ((Argc != 2) && (Argc!= 3)) {
1239 ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_GEN_PROBLEM_VAL), gShellNetwork1HiiHandle, Temp);
1240 ASSERT(ShellStatus == SHELL_INVALID_PARAMETER);
1241 goto ON_EXIT;
1242 }
1243
1244 if (Argc == 3) {
1245 Walker += StrLen(Temp) + 1;
1246 FreePool(Temp);
1247 Temp = NULL;
1248 Temp = StrnCatGrow(&Temp, NULL, Walker, 0);
1249
1250 PermTemp = PermanentString;
1251 if (StringNoCaseCompare(&Temp, &PermTemp) != 0) {
1252 ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_GEN_PROBLEM_OP2), gShellNetwork1HiiHandle, Temp, PermanentString, L"Nothing");
1253 ASSERT(ShellStatus == SHELL_INVALID_PARAMETER);
1254 goto ON_EXIT;
1255 }
1256
1257 Permanent = TRUE;
1258 }
1259
1260 if ((OldConfig != NULL) && (OldConfig->Source == IP4_CONFIG_SOURCE_DHCP) &&
1261 (OldConfig->Perment == Permanent)) {
1262
1263 ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_INTERFACE_CONFIGURED), gShellNetwork1HiiHandle, Info->Name);
1264 ShellStatus = SHELL_ALREADY_STARTED;
1265 goto ON_EXIT;
1266 }
1267
1268 Config->Source = IP4_CONFIG_SOURCE_DHCP;
1269 } else if (StringNoCaseCompare(&Temp, &StaticTemp) == 0) {
1270 //
1271 // validate the parameter, two forms: eth0 static IP NETMASK GATEWAY and
1272 // eth0 static IP NETMASK GATEWAY perment
1273 //
1274 if ((Argc != 5) && (Argc != 6)) {
1275 ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_GEN_PROBLEM_VAL), gShellNetwork1HiiHandle, Temp);
1276 ASSERT(ShellStatus == SHELL_INVALID_PARAMETER);
1277 goto ON_EXIT;
1278 }
1279
1280 Walker += StrLen(Temp) + 1;
1281 FreePool(Temp);
1282 Temp = NULL;
1283 Temp = StrnCatGrow(&Temp, NULL, Walker, StrStr(Walker, L" ")-Walker);
1284
1285 if (EFI_ERROR (NetLibStrToIp4 (Temp, &Ip.v4))) {
1286 ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_INVALID_IP_STR), gShellNetwork1HiiHandle, Temp);
1287 ASSERT(ShellStatus == SHELL_INVALID_PARAMETER);
1288 goto ON_EXIT;
1289 }
1290
1291 Walker += StrLen(Temp) + 1;
1292 FreePool(Temp);
1293 Temp = NULL;
1294 Temp = StrnCatGrow(&Temp, NULL, Walker, StrStr(Walker, L" ")-Walker);
1295 if (EFI_ERROR (NetLibStrToIp4 (Temp, &Mask.v4))) {
1296 ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_INVALID_IP_STR), gShellNetwork1HiiHandle, Temp);
1297 ASSERT(ShellStatus == SHELL_INVALID_PARAMETER);
1298 goto ON_EXIT;
1299 }
1300
1301 Walker += StrLen(Temp) + 1;
1302 FreePool(Temp);
1303 Temp = NULL;
1304 if (Argc == 6) {
1305 Temp = StrnCatGrow(&Temp, NULL, Walker, StrStr(Walker, L" ")-Walker);
1306 } else {
1307 Temp = StrnCatGrow(&Temp, NULL, Walker, 0);
1308 }
1309 if (EFI_ERROR (NetLibStrToIp4 (Temp, &Gateway.v4))) {
1310 ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_INVALID_IP_STR), gShellNetwork1HiiHandle, Temp);
1311 ASSERT(ShellStatus == SHELL_INVALID_PARAMETER);
1312 goto ON_EXIT;
1313 }
1314
1315 if (Argc == 6) {
1316 Walker += StrLen(Temp) + 1;
1317 FreePool(Temp);
1318 Temp = NULL;
1319 Temp = StrnCatGrow(&Temp, NULL, Walker, 0);
1320
1321 PermTemp = PermanentString;
1322 if (StringNoCaseCompare(&Temp, &PermTemp) != 0) {
1323 ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_GEN_PROBLEM_OP2), gShellNetwork1HiiHandle, Temp, PermanentString, L"Nothing");
1324 ASSERT(ShellStatus == SHELL_INVALID_PARAMETER);
1325 goto ON_EXIT;
1326 }
1327
1328 Permanent = TRUE;
1329 }
1330
1331 NetworkBytes1 = NTOHL (Ip.Addr[0]);
1332 NetworkBytes2 = NTOHL (Mask.Addr[0]);
1333 if ((Ip.Addr[0] == 0) || (Mask.Addr[0] == 0) ||
1334 !NetIp4IsUnicast (NetworkBytes1, NetworkBytes2)) {
1335
1336 ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_INVALID_ADDR_PAIR), gShellNetwork1HiiHandle);
1337 ASSERT(ShellStatus == SHELL_INVALID_PARAMETER);
1338 goto ON_EXIT;
1339 }
1340
1341 NetworkBytes1 = NTOHL (Gateway.Addr[0]);
1342 if (!IP4_NET_EQUAL (Ip.Addr[0], Gateway.Addr[0], Mask.Addr[0]) ||
1343 !NetIp4IsUnicast (NetworkBytes1, NetworkBytes2)) {
1344
1345 ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_INVALID_GATEWAY), gShellNetwork1HiiHandle);
1346 ASSERT(ShellStatus == SHELL_INVALID_PARAMETER);
1347 goto ON_EXIT;
1348 }
1349
1350 //
1351 // Set the configuration up, two route table entries are added:
1352 // one for the direct connected network, and another for the
1353 // default gateway. Remember, some structure members are cleared
1354 // by AllocateZeroPool
1355 //
1356 Config->Source = IP4_CONFIG_SOURCE_STATIC;
1357 Config->Ip4Info.RouteTableSize = 2;
1358
1359 CopyMem (&Config->Ip4Info.StationAddress, &Ip.v4, sizeof (EFI_IPv4_ADDRESS));
1360 CopyMem (&Config->Ip4Info.SubnetMask, &Mask.v4, sizeof (EFI_IPv4_ADDRESS));
1361
1362 Ip.Addr[0] = Ip.Addr[0] & Mask.Addr[0];
1363
1364 CopyMem (&Config->Ip4Info.RouteTable[0].SubnetAddress, &Ip.v4, sizeof (EFI_IPv4_ADDRESS));
1365 CopyMem (&Config->Ip4Info.RouteTable[0].SubnetMask, &Mask.v4, sizeof (EFI_IPv4_ADDRESS));
1366 CopyMem (&Config->Ip4Info.RouteTable[1].GatewayAddress, &Gateway.v4, sizeof (EFI_IPv4_ADDRESS));
1367 } else {
1368 // neither static or DHCP. error.
1369 ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_GEN_TOO_FEW), gShellNetwork1HiiHandle);
1370 ASSERT(ShellStatus == SHELL_INVALID_PARAMETER);
1371 goto ON_EXIT;
1372 }
1373
1374 CopyMem (&Config->NicAddr, &Info->NicAddress, sizeof (NIC_ADDR));
1375 Config->Perment = Permanent;
1376
1377 //
1378 // Use HII service to set NIC address
1379 //
1380 ShellStatus = IfconfigSetNicAddrByHii (Info, Config);
1381 if (ShellStatus != SHELL_SUCCESS) {
1382 ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_SET_FAIL), gShellNetwork1HiiHandle, ShellStatus^MAX_BIT);
1383 goto ON_EXIT;
1384 }
1385
1386 Status = IfconfigStartIp4 (Info);
1387 if (EFI_ERROR(Status)) {
1388 ShellStatus = SHELL_ACCESS_DENIED;
1389 }
1390
1391 if (ShellStatus != SHELL_SUCCESS) {
1392 ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_IP_CHILD_FAIL), gShellNetwork1HiiHandle, ShellStatus^MAX_BIT);
1393 }
1394
1395 ON_EXIT:
1396 SHELL_FREE_NON_NULL(Config);
1397
1398 return ShellStatus;
1399 }
1400
1401 /**
1402 Show the address information for the nic specified.
1403
1404 @param[in] Name A pointer to the string containg the nic's name, if NULL,
1405 all nics' information is shown.
1406 **/
1407 VOID
1408 EFIAPI
1409 IfconfigShowNicInfo (
1410 IN CONST CHAR16 *Name
1411 )
1412 {
1413 LIST_ENTRY *Entry;
1414 LIST_ENTRY *NextEntry;
1415 NIC_INFO *NicInfo;
1416 UINT32 Index;
1417 EFI_IP4_IPCONFIG_DATA *Ip4Config;
1418 EFI_IPv4_ADDRESS Gateway;
1419 CONST CHAR16 *TempString;
1420
1421 NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &NicInfoList) {
1422 NicInfo = BASE_CR (Entry, NIC_INFO, Link);
1423
1424 TempString = (CHAR16*)NicInfo->Name;
1425 if ((Name != NULL) && (StringNoCaseCompare (&Name, &TempString) != 0)) {
1426 continue;
1427 }
1428
1429 ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_NIC_NAME), gShellNetwork1HiiHandle, NicInfo->Name);
1430
1431 ShellPrintHiiEx(
1432 -1,
1433 -1,
1434 NULL,
1435 STRING_TOKEN(STR_IFCONFIG_SHOW_MAC_ADDR),
1436 gShellNetwork1HiiHandle,
1437 (UINTN)NicInfo->NicAddress.MacAddr.Addr[0],
1438 (UINTN)NicInfo->NicAddress.MacAddr.Addr[1],
1439 (UINTN)NicInfo->NicAddress.MacAddr.Addr[2],
1440 (UINTN)NicInfo->NicAddress.MacAddr.Addr[3],
1441 (UINTN)NicInfo->NicAddress.MacAddr.Addr[4],
1442 (UINTN)NicInfo->NicAddress.MacAddr.Addr[5]
1443 );
1444
1445 Print (L" Media State: %s\n", NicInfo->MediaPresent ? L"Media present" : L"Media disconnected");
1446
1447 if (NicInfo->ConfigInfo == NULL) {
1448 ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_NIC_NOT_CONFIGURED), gShellNetwork1HiiHandle);
1449 continue;
1450 }
1451
1452 if (NicInfo->ConfigInfo->Source == IP4_CONFIG_SOURCE_DHCP) {
1453 ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_CONFIG_SOURCE), gShellNetwork1HiiHandle, L"DHCP");
1454 } else if (NicInfo->ConfigInfo->Source == IP4_CONFIG_SOURCE_STATIC) {
1455 ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_CONFIG_SOURCE), gShellNetwork1HiiHandle, L"STATIC");
1456 } else {
1457 ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_CONFIG_SOURCE), gShellNetwork1HiiHandle, L"Unknown");
1458 }
1459
1460 ShellPrintHiiEx(-1, -1, NULL,
1461 STRING_TOKEN (STR_IFCONFIG_PERMENT_STATUS),
1462 gShellNetwork1HiiHandle,
1463 (NicInfo->ConfigInfo->Perment? L"TRUE":L"FALSE")
1464 );
1465
1466 Ip4Config = &NicInfo->ConfigInfo->Ip4Info;
1467
1468 ShellPrintHiiEx(
1469 -1,
1470 -1,
1471 NULL,
1472 STRING_TOKEN (STR_IFCONFIG_SHOW_IP_ADDR),
1473 gShellNetwork1HiiHandle,
1474 L"IP address",
1475 (UINTN)Ip4Config->StationAddress.Addr[0],
1476 (UINTN)Ip4Config->StationAddress.Addr[1],
1477 (UINTN)Ip4Config->StationAddress.Addr[2],
1478 (UINTN)Ip4Config->StationAddress.Addr[3]
1479 );
1480 ShellPrintHiiEx(
1481 -1,
1482 -1,
1483 NULL,
1484 STRING_TOKEN (STR_IFCONFIG_SHOW_IP_ADDR),
1485 gShellNetwork1HiiHandle,
1486 L"Mask",
1487 (UINTN)Ip4Config->SubnetMask.Addr[0],
1488 (UINTN)Ip4Config->SubnetMask.Addr[1],
1489 (UINTN)Ip4Config->SubnetMask.Addr[2],
1490 (UINTN)Ip4Config->SubnetMask.Addr[3]
1491 );
1492
1493 ZeroMem (&Gateway, sizeof (EFI_IPv4_ADDRESS));
1494
1495 for (Index = 0; Index < Ip4Config->RouteTableSize; Index++) {
1496 if ((CompareMem (&Ip4Config->RouteTable[Index].SubnetAddress, &mZeroIp4Addr, sizeof (EFI_IPv4_ADDRESS)) == 0) &&
1497 (CompareMem (&Ip4Config->RouteTable[Index].SubnetMask , &mZeroIp4Addr, sizeof (EFI_IPv4_ADDRESS)) == 0) ){
1498 CopyMem (&Gateway, &Ip4Config->RouteTable[Index].GatewayAddress, sizeof (EFI_IPv4_ADDRESS));
1499 }
1500 }
1501
1502 ShellPrintHiiEx(
1503 -1,
1504 -1,
1505 NULL,
1506 STRING_TOKEN (STR_IFCONFIG_SHOW_IP_ADDR),
1507 gShellNetwork1HiiHandle,
1508 L"Gateway",
1509 (UINTN)Gateway.Addr[0],
1510 (UINTN)Gateway.Addr[1],
1511 (UINTN)Gateway.Addr[2],
1512 (UINTN)Gateway.Addr[3]
1513 );
1514
1515 ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_ROUTES_SIZE), gShellNetwork1HiiHandle, Ip4Config->RouteTableSize);
1516
1517 for (Index = 0; Index < Ip4Config->RouteTableSize; Index++) {
1518 ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_ROUTES_ENTRY_INDEX), gShellNetwork1HiiHandle, Index);
1519
1520 ShellPrintHiiEx(
1521 -1,
1522 -1,
1523 NULL,
1524 STRING_TOKEN (STR_IFCONFIG_SHOW_IP_ADDR),
1525 gShellNetwork1HiiHandle,
1526 L"Subnet",
1527 (UINTN)Ip4Config->RouteTable[Index].SubnetAddress.Addr[0],
1528 (UINTN)Ip4Config->RouteTable[Index].SubnetAddress.Addr[1],
1529 (UINTN)Ip4Config->RouteTable[Index].SubnetAddress.Addr[2],
1530 (UINTN)Ip4Config->RouteTable[Index].SubnetAddress.Addr[3]
1531 );
1532
1533 ShellPrintHiiEx(
1534 -1,
1535 -1,
1536 NULL,
1537 STRING_TOKEN (STR_IFCONFIG_SHOW_IP_ADDR),
1538 gShellNetwork1HiiHandle,
1539 L"Netmask",
1540 (UINTN)Ip4Config->RouteTable[Index].SubnetMask.Addr[0],
1541 (UINTN)Ip4Config->RouteTable[Index].SubnetMask.Addr[1],
1542 (UINTN)Ip4Config->RouteTable[Index].SubnetMask.Addr[2],
1543 (UINTN)Ip4Config->RouteTable[Index].SubnetMask.Addr[3]
1544 );
1545
1546 ShellPrintHiiEx(
1547 -1,
1548 -1,
1549 NULL,
1550 STRING_TOKEN (STR_IFCONFIG_SHOW_IP_ADDR),
1551 gShellNetwork1HiiHandle,
1552 L"Gateway",
1553 (UINTN)Ip4Config->RouteTable[Index].GatewayAddress.Addr[0],
1554 (UINTN)Ip4Config->RouteTable[Index].GatewayAddress.Addr[1],
1555 (UINTN)Ip4Config->RouteTable[Index].GatewayAddress.Addr[2],
1556 (UINTN)Ip4Config->RouteTable[Index].GatewayAddress.Addr[3]
1557 );
1558 }
1559 }
1560
1561 return ;
1562 }
1563
1564 /**
1565 Clear address configuration for the nic specified.
1566
1567 @param[in] Name A pointer to the string containg the nic's name,
1568 if NULL, all nics address configurations are cleared.
1569
1570 @retval EFI_SUCCESS The address configuration is cleared.
1571 @return Some error occurs.
1572 **/
1573 EFI_STATUS
1574 EFIAPI
1575 IfconfigClearNicAddr (
1576 IN CONST CHAR16 *Name
1577 )
1578 {
1579 LIST_ENTRY *Entry;
1580 LIST_ENTRY *NextEntry;
1581 NIC_INFO *Info;
1582 EFI_STATUS Status;
1583
1584 NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &NicInfoList) {
1585 Info = BASE_CR (Entry, NIC_INFO, Link);
1586
1587 if ((Name != NULL) && (StrCmp (Name, Info->Name) != 0)) {
1588 continue;
1589 }
1590
1591 // if (Info->NicIp4Config == NULL) {
1592 Status = IfconfigSetNicAddrByHii (Info, NULL);
1593 // } else {
1594 // Status = Info->NicIp4Config->SetInfo (Info->NicIp4Config, NULL, TRUE);
1595 // }
1596
1597 if (EFI_ERROR (Status)) {
1598 return Status;
1599 }
1600 }
1601
1602 return EFI_SUCCESS;
1603
1604 }
1605
1606 /**
1607 Function for 'ifconfig' command.
1608
1609 @param[in] ImageHandle Handle to the Image (NULL if Internal).
1610 @param[in] SystemTable Pointer to the System Table (NULL if Internal).
1611 **/
1612 SHELL_STATUS
1613 EFIAPI
1614 ShellCommandRunIfconfig (
1615 IN EFI_HANDLE ImageHandle,
1616 IN EFI_SYSTEM_TABLE *SystemTable
1617 )
1618 {
1619 EFI_STATUS Status;
1620 LIST_ENTRY *Package;
1621 CHAR16 *ProblemParam;
1622 SHELL_STATUS ShellStatus;
1623 BOOLEAN ListOperation;
1624 BOOLEAN ClearOperation;
1625 BOOLEAN SetOperation;
1626 CONST CHAR16 *Item;
1627 LIST_ENTRY *Entry;
1628 NIC_INFO *Info;
1629
1630 InitializeListHead (&NicInfoList);
1631 Status = EFI_INVALID_PARAMETER;
1632 ShellStatus = SHELL_SUCCESS;
1633
1634 //
1635 // initialize the shell lib (we must be in non-auto-init...)
1636 //
1637 Status = ShellInitialize();
1638 ASSERT_EFI_ERROR(Status);
1639
1640 //
1641 // parse the command line
1642 //
1643 Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE);
1644 if (EFI_ERROR(Status)) {
1645 if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
1646 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellNetwork1HiiHandle, ProblemParam);
1647 FreePool(ProblemParam);
1648 ShellStatus = SHELL_INVALID_PARAMETER;
1649 } else {
1650 ASSERT(FALSE);
1651 }
1652
1653 goto Done;
1654 }
1655
1656 ClearOperation = ShellCommandLineGetFlag(Package, L"-c");
1657 ListOperation = ShellCommandLineGetFlag(Package, L"-l");
1658 SetOperation = ShellCommandLineGetFlag(Package, L"-s");
1659
1660 if ((ClearOperation && ListOperation)
1661 ||(SetOperation && ListOperation)
1662 ||(ClearOperation && SetOperation)
1663 ) {
1664 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_CON), gShellNetwork1HiiHandle);
1665 ShellStatus = SHELL_INVALID_PARAMETER;
1666 goto Done;
1667 } else if (!ClearOperation && !ListOperation && !SetOperation) {
1668 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellNetwork1HiiHandle);
1669 ShellStatus = SHELL_INVALID_PARAMETER;
1670 goto Done;
1671 }
1672
1673
1674 Status = IfconfigGetAllNicInfoByHii ();
1675 if (EFI_ERROR (Status)) {
1676 if (mIp4ConfigExist) {
1677 ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_GET_NIC_FAIL), gShellNetwork1HiiHandle, Status);
1678 } else {
1679 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROTOCOL_NF), gShellNetwork1HiiHandle, L"gEfiIp4ConfigProtocolGuid", &gEfiIp4ConfigProtocolGuid);
1680 }
1681
1682 return SHELL_NOT_FOUND;
1683 }
1684
1685 if (ListOperation) {
1686 Item = ShellCommandLineGetValue (Package, L"-l");
1687
1688 if (Item != NULL && CountSubItems(Item) > 1) {
1689 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM_VAL), gShellNetwork1HiiHandle, L"-l");
1690 ShellStatus = SHELL_INVALID_PARAMETER;
1691 goto Done;
1692 }
1693
1694 //
1695 // Show the configuration.
1696 //
1697 IfconfigShowNicInfo (Item);
1698 } else if (SetOperation) {
1699 Item = ShellCommandLineGetValue (Package, L"-s");
1700
1701 //
1702 // The correct command line arguments for setting address are:
1703 // IfConfig -s eth0 DHCP [perment]
1704 // IfConfig -s eth0 static ip netmask gateway [perment]
1705 //
1706 if (Item == NULL || (CountSubItems(Item) < 2) || (CountSubItems(Item) > 6) || (CountSubItems(Item) == 4)) {
1707 ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_GEN_PROBLEM_VAL), gShellNetwork1HiiHandle, L"-s");
1708 ShellStatus = SHELL_INVALID_PARAMETER;
1709 goto Done;
1710 }
1711
1712 ShellStatus = IfconfigSetNicAddr (CountSubItems(Item), Item);
1713 } else if (ClearOperation) {
1714 Item = ShellCommandLineGetValue (Package, L"-c");
1715
1716 if (Item != NULL && CountSubItems(Item) > 1) {
1717 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM_VAL), gShellNetwork1HiiHandle, L"-c");
1718 ShellStatus = SHELL_INVALID_PARAMETER;
1719 goto Done;
1720 }
1721
1722 IfconfigClearNicAddr (Item);
1723 } else {
1724 ASSERT(FALSE);
1725 }
1726
1727 Done:
1728 while (!IsListEmpty (&NicInfoList)) {
1729 Entry = NicInfoList.ForwardLink;
1730 Info = BASE_CR (Entry, NIC_INFO, Link);
1731
1732 RemoveEntryList (Entry);
1733
1734 if (Info->ConfigInfo != NULL) {
1735 FreePool (Info->ConfigInfo);
1736 }
1737
1738 FreePool (Info);
1739 }
1740
1741 if (Package != NULL) {
1742 ShellCommandLineFreeVarList(Package);
1743 }
1744
1745 return (ShellStatus);
1746 }