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