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