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