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