]> git.proxmox.com Git - mirror_edk2.git/blob - ShellPkg/Library/UefiShellLevel2CommandsLib/Map.c
d74a47ba52585f2a95355fbb58f34bf22af0e4c4
[mirror_edk2.git] / ShellPkg / Library / UefiShellLevel2CommandsLib / Map.c
1 /** @file
2 Main file for map shell level 2 command.
3
4 Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
9
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12
13 **/
14
15 #include "UefiShellLevel2CommandsLib.h"
16 #include <Protocol/SimpleFileSystem.h>
17 #include <Protocol/BlockIo.h>
18 #include <Library/DevicePathLib.h>
19 #include <Library/HandleParsingLib.h>
20 #include <Library/SortLib.h>
21
22 BOOLEAN
23 EFIAPI
24 SearchList(
25 IN CONST CHAR16 *List,
26 IN CONST CHAR16 *MetaTarget,
27 OUT CHAR16 **FullName OPTIONAL,
28 IN CONST BOOLEAN Meta,
29 IN CONST BOOLEAN SkipTrailingNumbers,
30 IN CONST CHAR16 *Target
31
32 )
33 {
34 CHAR16 *TempList;
35 CONST CHAR16 *ListWalker;
36 BOOLEAN Result;
37 CHAR16 *TempSpot;
38
39 for (ListWalker = List , TempList = NULL
40 ; ListWalker != NULL && *ListWalker != CHAR_NULL
41 ;
42 ) {
43 TempList = StrnCatGrow(&TempList, NULL, ListWalker, 0);
44 ASSERT(TempList != NULL);
45 TempSpot = StrStr(TempList, Target);
46 if (TempSpot != NULL) {
47 *TempSpot = CHAR_NULL;
48 }
49
50 while (SkipTrailingNumbers && (ShellIsDecimalDigitCharacter(TempList[StrLen(TempList)-1]) || TempList[StrLen(TempList)-1] == L':')) {
51 TempList[StrLen(TempList)-1] = CHAR_NULL;
52 }
53
54 ListWalker = StrStr(ListWalker, Target);
55 while(ListWalker != NULL && *ListWalker == *Target) {
56 ListWalker++;
57 }
58 if (Meta) {
59 Result = gUnicodeCollation->MetaiMatch(gUnicodeCollation, (CHAR16*)TempList, (CHAR16*)MetaTarget);
60 } else {
61 Result = (BOOLEAN)(StrCmp(TempList, MetaTarget)==0);
62 }
63 if (Result) {
64 if (FullName != NULL) {
65 *FullName = TempList;
66 } else {
67 FreePool(TempList);
68 }
69 return (TRUE);
70 }
71 FreePool(TempList);
72 TempList = NULL;
73 }
74
75 return (FALSE);
76 }
77
78 EFI_STATUS
79 EFIAPI
80 UpdateMapping (
81 VOID
82 )
83 {
84 EFI_STATUS Status;
85 EFI_HANDLE *HandleList;
86 UINTN Count;
87 EFI_DEVICE_PATH_PROTOCOL **DevicePathList;
88 CHAR16 *NewDefaultName;
89 CHAR16 *NewConsistName;
90 EFI_DEVICE_PATH_PROTOCOL **ConsistMappingTable;
91
92 HandleList = NULL;
93 Status = EFI_SUCCESS;
94
95 //
96 // remove mappings that represent removed devices.
97 //
98
99 //
100 // Find each handle with Simple File System
101 //
102 HandleList = GetHandleListByProtocol(&gEfiSimpleFileSystemProtocolGuid);
103 if (HandleList != NULL) {
104 //
105 // Do a count of the handles
106 //
107 for (Count = 0 ; HandleList[Count] != NULL ; Count++);
108
109 //
110 // Get all Device Paths
111 //
112 DevicePathList = AllocatePool(sizeof(EFI_DEVICE_PATH_PROTOCOL*) * Count);
113 ASSERT(DevicePathList != NULL);
114
115 for (Count = 0 ; HandleList[Count] != NULL ; Count++) {
116 DevicePathList[Count] = DevicePathFromHandle(HandleList[Count]);
117 }
118
119 //
120 // Sort all DevicePaths
121 //
122 PerformQuickSort(DevicePathList, Count, sizeof(EFI_DEVICE_PATH_PROTOCOL*), DevicePathCompare);
123
124 ShellCommandConsistMappingInitialize(&ConsistMappingTable);
125
126 //
127 // Assign new Mappings to remainders
128 //
129 for (Count = 0 ; HandleList[Count] != NULL && !EFI_ERROR(Status); Count++) {
130 //
131 // Skip ones that already have
132 //
133 if (gEfiShellProtocol->GetMapFromDevicePath(&DevicePathList[Count]) != NULL) {
134 continue;
135 }
136 //
137 // Get default name
138 //
139 NewDefaultName = ShellCommandCreateNewMappingName(MappingTypeFileSystem);
140 ASSERT(NewDefaultName != NULL);
141
142 //
143 // Call shell protocol SetMap function now...
144 //
145 Status = gEfiShellProtocol->SetMap(DevicePathList[Count], NewDefaultName);
146
147 if (!EFI_ERROR(Status)) {
148 //
149 // Now do consistent name
150 //
151 NewConsistName = ShellCommandConsistMappingGenMappingName(DevicePathList[Count], ConsistMappingTable);
152 if (NewConsistName != NULL) {
153 Status = gEfiShellProtocol->SetMap(DevicePathList[Count], NewConsistName);
154 FreePool(NewConsistName);
155 }
156 }
157
158 FreePool(NewDefaultName);
159 }
160 ShellCommandConsistMappingUnInitialize(ConsistMappingTable);
161 SHELL_FREE_NON_NULL(HandleList);
162 SHELL_FREE_NON_NULL(DevicePathList);
163
164 HandleList = NULL;
165 } else {
166 Count = (UINTN)-1;
167 }
168 //
169 // Do it all over again for gEfiBlockIoProtocolGuid
170 //
171
172 return (Status);
173 }
174
175 CHAR16*
176 EFIAPI
177 GetDeviceMediaType (
178 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
179 )
180 {
181 ACPI_HID_DEVICE_PATH *Acpi;
182
183 //
184 // Parse the device path:
185 // Devicepath sub type mediatype
186 // MEDIA_HANRDDRIVE_DP -> Hard Disk
187 // MEDIA_CDROM_DP -> CD Rom
188 // Acpi.HID = 0X0604 -> Floppy
189 //
190 if (NULL == DevicePath) {
191 return HiiGetString(gShellLevel2HiiHandle, STRING_TOKEN(STR_MAP_MEDIA_UNKNOWN), NULL);
192 }
193
194 for (;!IsDevicePathEndType (DevicePath) ;DevicePath = NextDevicePathNode (DevicePath)) {
195 if (DevicePathType (DevicePath) == MEDIA_DEVICE_PATH) {
196 switch (DevicePathSubType (DevicePath)) {
197 case MEDIA_HARDDRIVE_DP:
198 return HiiGetString(gShellLevel2HiiHandle, STRING_TOKEN(STR_MAP_MEDIA_HARDDISK), NULL);
199 case MEDIA_CDROM_DP:
200 return HiiGetString(gShellLevel2HiiHandle, STRING_TOKEN(STR_MAP_MEDIA_CDROM), NULL);
201 }
202 } else if (DevicePathType (DevicePath) == ACPI_DEVICE_PATH) {
203 Acpi = (ACPI_HID_DEVICE_PATH *) DevicePath;
204 if (EISA_ID_TO_NUM (Acpi->HID) == 0x0604) {
205 return HiiGetString(gShellLevel2HiiHandle, STRING_TOKEN(STR_MAP_MEDIA_FLOPPY), NULL);
206 }
207 }
208 }
209
210 return HiiGetString(gShellLevel2HiiHandle, STRING_TOKEN(STR_MAP_MEDIA_UNKNOWN), NULL);
211 }
212
213 /**
214 Function to detemine if a handle has removable storage.
215
216 @param[in] DevicePath DevicePath to test.
217
218 @retval TRUE The handle has removable storage.
219 @retval FALSE The handle does not have removable storage.
220 **/
221 BOOLEAN
222 EFIAPI
223 IsRemoveableDevice (
224 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
225 )
226 {
227 if (NULL == DevicePath) {
228 return FALSE;
229 }
230
231 while (!IsDevicePathEndType (DevicePath)) {
232 if (DevicePathType (DevicePath) == MESSAGING_DEVICE_PATH) {
233 switch (DevicePathSubType (DevicePath)) {
234 case MSG_USB_DP:
235 case MSG_SCSI_DP:
236 return TRUE;
237 default:
238 return FALSE;
239 }
240 }
241 DevicePath = NextDevicePathNode (DevicePath);
242 }
243 return FALSE;
244 }
245
246 /**
247 Function to detemine if a something on the map list matches.
248
249 @param[in] MapList The pointer to the list to test.
250 @param[in] Specific The pointer to a specific name to test for.
251 @param[in] TypeString The pointer to the list of types.
252 @param[in] Normal Always show normal mappings.
253 @param[in] Consist Always show consistent mappings.
254
255 @retval TRUE The map should be displayed.
256 @retval FALSE The map should not be displayed.
257 **/
258 BOOLEAN
259 EFIAPI
260 MappingListHasType(
261 IN CONST CHAR16 *MapList,
262 IN CONST CHAR16 *Specific,
263 IN CONST CHAR16 *TypeString,
264 IN CONST BOOLEAN Normal,
265 IN CONST BOOLEAN Consist
266 )
267 {
268 //
269 // specific has priority
270 //
271 if ( Specific != NULL
272 && SearchList(MapList, Specific, NULL, TRUE, FALSE, L";")) {
273 return (TRUE);
274 }
275
276 if ( Consist
277 && (SearchList(MapList, L"HD*", NULL, TRUE, TRUE, L";")
278 ||SearchList(MapList, L"CD*", NULL, TRUE, TRUE, L";")
279 ||SearchList(MapList, L"F*", NULL, TRUE, TRUE, L";")
280 ||SearchList(MapList, L"FP*", NULL, TRUE, TRUE, L";"))){
281 return (TRUE);
282 }
283
284 if ( Normal
285 && (SearchList(MapList, L"FS", NULL, FALSE, TRUE, L";")
286 ||SearchList(MapList, L"BLK", NULL, FALSE, TRUE, L";"))){
287 return (TRUE);
288 }
289
290 if (TypeString != NULL && SearchList(MapList, TypeString, NULL, TRUE, TRUE, L";")) {
291 return (TRUE);
292 }
293 return (FALSE);
294 }
295
296
297 VOID
298 EFIAPI
299 PerformSingleMappingDisplay(
300 IN CONST BOOLEAN Verbose,
301 IN CONST BOOLEAN Consist,
302 IN CONST BOOLEAN Normal,
303 IN CONST CHAR16 *TypeString,
304 IN CONST BOOLEAN SFO,
305 IN CONST CHAR16 *Specific OPTIONAL,
306 IN CONST EFI_HANDLE Handle
307 )
308 {
309 EFI_DEVICE_PATH_PROTOCOL *DevPath;
310 EFI_DEVICE_PATH_PROTOCOL *DevPathCopy;
311 CONST CHAR16 *MapList;
312 CHAR16 *CurrentName;
313 CHAR16 *MediaType;
314 CHAR16 *DevPathString;
315 CHAR16 *TempSpot;
316 UINTN TempLen;
317 BOOLEAN Removable;
318 CONST CHAR16 *TempSpot2;
319
320 DevPath = DevicePathFromHandle(Handle);
321 DevPathCopy = DevPath;
322 MapList = gEfiShellProtocol->GetMapFromDevicePath(&DevPathCopy);
323 if (MapList == NULL) {
324 return;
325 }
326
327 if (!MappingListHasType(MapList, Specific, TypeString, Normal, Consist)){
328 return;
329 }
330
331 CurrentName = NULL;
332 CurrentName = StrnCatGrow(&CurrentName, 0, MapList, 0);
333 TempSpot = StrStr(CurrentName, L";");
334 if (TempSpot != NULL) {
335 *TempSpot = CHAR_NULL;
336 }
337 DevPathString = gDevPathToText->ConvertDevicePathToText(DevPath, TRUE, FALSE);
338 if (!SFO) {
339 TempLen = StrLen(CurrentName);
340 ShellPrintHiiEx (
341 -1,
342 -1,
343 NULL,
344 STRING_TOKEN (STR_MAP_ENTRY),
345 gShellLevel2HiiHandle,
346 CurrentName,
347 TempLen < StrLen(MapList)?MapList + TempLen+1:L"",
348 DevPathString
349 );
350 if (Verbose) {
351 //
352 // also print handle, media type, removable (y/n), and current directory
353 //
354 MediaType = GetDeviceMediaType(DevPath);
355 if ((TypeString != NULL &&MediaType != NULL && StrStr(TypeString, MediaType) != NULL) || TypeString == NULL) {
356 Removable = IsRemoveableDevice(DevPath);
357 TempSpot2 = ShellGetCurrentDir(CurrentName);
358 ShellPrintHiiEx (
359 -1,
360 -1,
361 NULL,
362 STRING_TOKEN (STR_MAP_ENTRY_VERBOSE),
363 gShellLevel2HiiHandle,
364 ConvertHandleToHandleIndex(Handle),
365 MediaType,
366 Removable?L"Yes":L"No",
367 TempSpot2
368 );
369 }
370 FreePool(MediaType);
371 }
372 } else {
373 TempLen = StrLen(CurrentName);
374 ShellPrintHiiEx (
375 -1,
376 -1,
377 NULL,
378 STRING_TOKEN (STR_MAP_SFO_MAPPINGS),
379 gShellLevel2HiiHandle,
380 CurrentName,
381 DevPathString,
382 TempLen < StrLen(MapList)?MapList + TempLen+1:L""
383 );
384 }
385 FreePool(DevPathString);
386 FreePool(CurrentName);
387 return;
388 }
389
390 EFI_STATUS
391 EFIAPI
392 PerformSingleMappingDelete(
393 IN CONST CHAR16 *Specific,
394 IN CONST EFI_HANDLE Handle
395 )
396 {
397 EFI_DEVICE_PATH_PROTOCOL *DevPath;
398 EFI_DEVICE_PATH_PROTOCOL *DevPathCopy;
399 CONST CHAR16 *MapList;
400 CHAR16 *CurrentName;
401
402 DevPath = DevicePathFromHandle(Handle);
403 DevPathCopy = DevPath;
404 MapList = gEfiShellProtocol->GetMapFromDevicePath(&DevPathCopy);
405 CurrentName = NULL;
406
407 if (MapList == NULL) {
408 return (EFI_NOT_FOUND);
409 }
410 //
411 // if there is a specific and its not on the list...
412 //
413 if (!SearchList(MapList, Specific, &CurrentName, TRUE, FALSE, L";")) {
414 return (EFI_NOT_FOUND);
415 }
416 return (gEfiShellProtocol->SetMap(NULL, CurrentName));
417 }
418
419 /**
420 Function to display mapping information to the user.
421
422 if Specific is specified then Consist and Normal will be ignored since information will
423 be printed for the specific item only.
424
425 @param[in] Verbose TRUE to display (extra) verbose information
426 @param[in] Consist TRUE to display consistent mappings
427 @param[in] Normal TRUE to display normal (not consist) mappings
428 @param[in] TypeString pointer to string of filter types
429 @param[in] SFO TRUE to display output in Standard Output Format
430 @param[in] Specific pointer to string for specific map to display
431
432 @retval SHELL_SUCCESS the display was printed
433 @retval SHELL_INVALID_PARAMETER one of Consist or Normal must be TRUE if no Specific
434
435 **/
436 CONST CHAR16 Cd[] = L"cd*";
437 CONST CHAR16 Hd[] = L"hd*";
438 CONST CHAR16 Fp[] = L"fp*";
439 CONST CHAR16 F[] = L"F*";
440 SHELL_STATUS
441 EFIAPI
442 PerformMappingDisplay(
443 IN CONST BOOLEAN Verbose,
444 IN CONST BOOLEAN Consist,
445 IN CONST BOOLEAN Normal,
446 IN CONST CHAR16 *TypeString,
447 IN CONST BOOLEAN SFO,
448 IN CONST CHAR16 *Specific OPTIONAL,
449 IN CONST BOOLEAN Header
450 )
451 {
452 EFI_STATUS Status;
453 EFI_HANDLE *HandleBuffer;
454 UINTN BufferSize;
455 UINTN LoopVar;
456 CHAR16 *Test;
457
458 if (!Consist && !Normal && Specific == NULL && TypeString == NULL) {
459 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellLevel2HiiHandle);
460 return (SHELL_INVALID_PARAMETER);
461 }
462
463 if (TypeString != NULL) {
464 Test = (CHAR16*)Cd;
465 if (StrnCmp(TypeString, Test, StrLen(Test)-1) != 0) {
466 Test = (CHAR16*)Hd;
467 if (StrnCmp(TypeString, Test, StrLen(Test)-1) != 0) {
468 Test = (CHAR16*)Fp;
469 if (StrnCmp(TypeString, Test, StrLen(Test)-1) != 0) {
470 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel2HiiHandle, TypeString);
471 return (SHELL_INVALID_PARAMETER);
472 }
473 } else if (Test == NULL) {
474 Test = (CHAR16*)F;
475 }
476 }
477 } else {
478 Test = NULL;
479 }
480
481 if (Header) {
482 //
483 // Print the header
484 //
485 if (!SFO) {
486 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MAP_HEADER), gShellLevel2HiiHandle);
487 } else {
488 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_SFO_HEADER), gShellLevel2HiiHandle, L"map");
489 }
490 }
491
492 BufferSize = 0;
493 HandleBuffer = NULL;
494
495 //
496 // Look up all SimpleFileSystems in the platform
497 //
498 Status = gBS->LocateHandle(
499 ByProtocol,
500 &gEfiDevicePathProtocolGuid,
501 NULL,
502 &BufferSize,
503 HandleBuffer);
504 if (Status == EFI_BUFFER_TOO_SMALL) {
505 HandleBuffer = AllocatePool(BufferSize);
506 if (HandleBuffer == NULL) {
507 return (SHELL_OUT_OF_RESOURCES);
508 }
509 Status = gBS->LocateHandle(
510 ByProtocol,
511 &gEfiDevicePathProtocolGuid,
512 NULL,
513 &BufferSize,
514 HandleBuffer);
515 }
516 ASSERT_EFI_ERROR(Status);
517 ASSERT(HandleBuffer != NULL);
518
519 //
520 // Get the map name(s) for each one.
521 //
522 for ( LoopVar = 0
523 ; LoopVar < (BufferSize / sizeof(EFI_HANDLE))
524 ; LoopVar ++
525 ){
526 PerformSingleMappingDisplay(
527 Verbose,
528 Consist,
529 Normal,
530 Test,
531 SFO,
532 Specific,
533 HandleBuffer[LoopVar]);
534 }
535
536 //
537 // Look up all BlockIo in the platform
538 //
539 Status = gBS->LocateHandle(
540 ByProtocol,
541 &gEfiBlockIoProtocolGuid,
542 NULL,
543 &BufferSize,
544 HandleBuffer);
545 if (Status == EFI_BUFFER_TOO_SMALL) {
546 FreePool(HandleBuffer);
547 HandleBuffer = AllocatePool(BufferSize);
548 if (HandleBuffer == NULL) {
549 return (SHELL_OUT_OF_RESOURCES);
550 }
551 Status = gBS->LocateHandle(
552 ByProtocol,
553 &gEfiBlockIoProtocolGuid,
554 NULL,
555 &BufferSize,
556 HandleBuffer);
557 }
558 if (!EFI_ERROR(Status)) {
559 //
560 // Get the map name(s) for each one.
561 //
562 for ( LoopVar = 0
563 ; LoopVar < BufferSize / sizeof(EFI_HANDLE)
564 ; LoopVar ++
565 ){
566 //
567 // Skip any that were already done...
568 //
569 if (gBS->OpenProtocol(
570 HandleBuffer[LoopVar],
571 &gEfiDevicePathProtocolGuid,
572 NULL,
573 gImageHandle,
574 NULL,
575 EFI_OPEN_PROTOCOL_TEST_PROTOCOL) == EFI_SUCCESS) {
576 continue;
577 }
578 PerformSingleMappingDisplay(
579 Verbose,
580 Consist,
581 Normal,
582 Test,
583 SFO,
584 Specific,
585 HandleBuffer[LoopVar]);
586 }
587 FreePool(HandleBuffer);
588 }
589 return (SHELL_SUCCESS);
590 }
591
592 SHELL_STATUS
593 EFIAPI
594 PerformMappingDisplay2(
595 IN CONST BOOLEAN Verbose,
596 IN CONST BOOLEAN Consist,
597 IN CONST BOOLEAN Normal,
598 IN CONST CHAR16 *TypeString,
599 IN CONST BOOLEAN SFO,
600 IN CONST CHAR16 *Specific OPTIONAL
601 )
602 {
603 CONST CHAR16 *TypeWalker;
604 SHELL_STATUS ShellStatus;
605 CHAR16 *Comma;
606
607
608 if (TypeString == NULL) {
609 return (PerformMappingDisplay(Verbose, Consist, Normal, NULL, SFO, Specific, TRUE));
610 }
611 ShellStatus = SHELL_SUCCESS;
612 for (TypeWalker = TypeString ; TypeWalker != NULL && *TypeWalker != CHAR_NULL ;) {
613 Comma = StrStr(TypeWalker, L",");
614 if (Comma == NULL) {
615 if (ShellStatus == SHELL_SUCCESS) {
616 ShellStatus = PerformMappingDisplay(Verbose, Consist, Normal, TypeWalker, SFO, Specific, (BOOLEAN)(TypeWalker == TypeString));
617 } else {
618 PerformMappingDisplay(Verbose, Consist, Normal, TypeWalker, SFO, Specific, (BOOLEAN)(TypeWalker == TypeString));
619 }
620 break;
621 } else {
622 *Comma = CHAR_NULL;
623 if (ShellStatus == SHELL_SUCCESS) {
624 ShellStatus = PerformMappingDisplay(Verbose, Consist, Normal, TypeWalker, SFO, Specific, (BOOLEAN)(TypeWalker == TypeString));
625 } else {
626 PerformMappingDisplay(Verbose, Consist, Normal, TypeWalker, SFO, Specific, (BOOLEAN)(TypeWalker == TypeString));
627 }
628 *Comma = L',';
629 TypeWalker = Comma + 1;
630 }
631 }
632
633 return (ShellStatus);
634 }
635
636 EFI_STATUS
637 EFIAPI
638 PerformMappingDelete(
639 IN CONST CHAR16 *Specific
640 )
641 {
642 EFI_STATUS Status;
643 EFI_HANDLE *HandleBuffer;
644 UINTN BufferSize;
645 UINTN LoopVar;
646 BOOLEAN Deleted;
647
648 if (Specific == NULL) {
649 return (EFI_INVALID_PARAMETER);
650 }
651
652 BufferSize = 0;
653 HandleBuffer = NULL;
654 Deleted = FALSE;
655
656 //
657 // Look up all SimpleFileSystems in the platform
658 //
659 Status = gBS->LocateHandle(
660 ByProtocol,
661 &gEfiDevicePathProtocolGuid,
662 NULL,
663 &BufferSize,
664 HandleBuffer);
665 if (Status == EFI_BUFFER_TOO_SMALL) {
666 HandleBuffer = AllocatePool(BufferSize);
667 if (HandleBuffer == NULL) {
668 return (EFI_OUT_OF_RESOURCES);
669 }
670 Status = gBS->LocateHandle(
671 ByProtocol,
672 &gEfiDevicePathProtocolGuid,
673 NULL,
674 &BufferSize,
675 HandleBuffer);
676 }
677 if (EFI_ERROR(Status)) {
678 SHELL_FREE_NON_NULL(HandleBuffer);
679 return (Status);
680 }
681
682 if (HandleBuffer != NULL) {
683 //
684 // Get the map name(s) for each one.
685 //
686 for ( LoopVar = 0
687 ; LoopVar < BufferSize / sizeof(EFI_HANDLE)
688 ; LoopVar ++
689 ){
690 if (PerformSingleMappingDelete(Specific,HandleBuffer[LoopVar]) == SHELL_SUCCESS) {
691 Deleted = TRUE;
692 }
693 }
694 }
695 //
696 // Look up all BlockIo in the platform
697 //
698 Status = gBS->LocateHandle(
699 ByProtocol,
700 &gEfiBlockIoProtocolGuid,
701 NULL,
702 &BufferSize,
703 HandleBuffer);
704 if (Status == EFI_BUFFER_TOO_SMALL) {
705 FreePool(HandleBuffer);
706 HandleBuffer = AllocatePool(BufferSize);
707 if (HandleBuffer == NULL) {
708 return (EFI_OUT_OF_RESOURCES);
709 }
710 Status = gBS->LocateHandle(
711 ByProtocol,
712 &gEfiBlockIoProtocolGuid,
713 NULL,
714 &BufferSize,
715 HandleBuffer);
716 }
717 if (EFI_ERROR(Status)) {
718 SHELL_FREE_NON_NULL(HandleBuffer);
719 return (Status);
720 }
721
722 if (HandleBuffer != NULL) {
723 //
724 // Get the map name(s) for each one.
725 //
726 for ( LoopVar = 0
727 ; LoopVar < BufferSize / sizeof(EFI_HANDLE)
728 ; LoopVar ++
729 ){
730 //
731 // Skip any that were already done...
732 //
733 if (gBS->OpenProtocol(
734 HandleBuffer[LoopVar],
735 &gEfiDevicePathProtocolGuid,
736 NULL,
737 gImageHandle,
738 NULL,
739 EFI_OPEN_PROTOCOL_TEST_PROTOCOL) == EFI_SUCCESS) {
740 continue;
741 }
742 if (PerformSingleMappingDelete(Specific,HandleBuffer[LoopVar]) == SHELL_SUCCESS) {
743 Deleted = TRUE;
744 }
745 }
746 }
747 SHELL_FREE_NON_NULL(HandleBuffer);
748 if (!Deleted) {
749 return (EFI_NOT_FOUND);
750 }
751 return (EFI_SUCCESS);
752 }
753
754 /**
755 function to add a mapping from mapping.
756
757 This function will get the device path associated with the mapping and call SetMap.
758
759 @param[in] Map The Map to add a mapping for
760 @param[in] SName The name of the new mapping
761
762 @retval SHELL_SUCCESS the mapping was added
763 @retval SHELL_INVALID_PARAMETER the device path for Map could not be retrieved.
764 @return Shell version of a return value from EfiShellProtocol->SetMap
765
766 **/
767 SHELL_STATUS
768 EFIAPI
769 AddMappingFromMapping(
770 IN CONST CHAR16 *Map,
771 IN CONST CHAR16 *SName
772 )
773 {
774 CONST EFI_DEVICE_PATH_PROTOCOL *DevPath;
775 EFI_STATUS Status;
776
777 if (StrStr(SName, L"*") != NULL
778 ||StrStr(SName, L"?") != NULL
779 ||StrStr(SName, L"[") != NULL
780 ||StrStr(SName, L"]") != NULL) {
781 return (SHELL_INVALID_PARAMETER);
782 }
783
784 DevPath = gEfiShellProtocol->GetDevicePathFromMap(Map);
785 if (DevPath == NULL) {
786 return (SHELL_INVALID_PARAMETER);
787 }
788
789 Status = gEfiShellProtocol->SetMap(DevPath, SName);
790 if (EFI_ERROR(Status)) {
791 return (SHELL_DEVICE_ERROR);
792 }
793 return (SHELL_SUCCESS);
794 }
795
796 /**
797 function to determine if a string has only numbers and letters
798
799 This is useful for such things as Map names which can only be letters and numbers
800
801 @param[in] String pointer to the string to analyze
802
803 @retval TRUE String has only numbers and letters
804 @retval FALSE String has at least one other character.
805 **/
806 BOOLEAN
807 EFIAPI
808 IsNumberLetterOnly(
809 IN CONST CHAR16 *String
810 )
811 {
812 while(String != NULL && *String != CHAR_NULL) {
813 if (! ((*String >= L'a' && *String <= L'z') ||
814 (*String >= L'A' && *String <= L'Z') ||
815 (*String >= L'0' && *String <= L'9'))
816 ){
817 return (FALSE);
818 }
819 String++;
820 }
821 return (TRUE);
822 }
823
824 /**
825 function to add a mapping from an EFI_HANDLE.
826
827 This function will get the device path associated with the Handle and call SetMap.
828
829 @param[in] Handle The handle to add a mapping for
830 @param[in] SName The name of the new mapping
831
832 @retval SHELL_SUCCESS the mapping was added
833 @retval SHELL_INVALID_PARAMETER SName was not valid for a map name.
834 @return Shell version of a return value from either
835 gBS->OpenProtocol or EfiShellProtocol->SetMap
836
837 **/
838 SHELL_STATUS
839 EFIAPI
840 AddMappingFromHandle(
841 IN CONST EFI_HANDLE Handle,
842 IN CONST CHAR16 *SName
843 )
844 {
845 EFI_DEVICE_PATH_PROTOCOL *DevPath;
846 EFI_STATUS Status;
847
848 if (!IsNumberLetterOnly(SName)) {
849 return (SHELL_INVALID_PARAMETER);
850 }
851
852 Status = gBS->OpenProtocol(
853 Handle,
854 &gEfiDevicePathProtocolGuid,
855 (VOID**)&DevPath,
856 gImageHandle,
857 NULL,
858 EFI_OPEN_PROTOCOL_GET_PROTOCOL
859 );
860 if (EFI_ERROR(Status)) {
861 return (SHELL_DEVICE_ERROR);
862 }
863 Status = gEfiShellProtocol->SetMap(DevPath, SName);
864 if (EFI_ERROR(Status)) {
865 return (SHELL_DEVICE_ERROR);
866 }
867 return (SHELL_SUCCESS);
868 }
869
870 STATIC CONST SHELL_PARAM_ITEM MapParamList[] = {
871 {L"-d", TypeValue},
872 {L"-r", TypeFlag},
873 {L"-v", TypeFlag},
874 {L"-c", TypeFlag},
875 {L"-f", TypeFlag},
876 {L"-u", TypeFlag},
877 {L"-t", TypeValue},
878 {L"-sfo", TypeValue},
879 {NULL, TypeMax}
880 };
881
882 /**
883 Function for 'map' command.
884
885 @param[in] ImageHandle Handle to the Image (NULL if Internal).
886 @param[in] SystemTable Pointer to the System Table (NULL if Internal).
887 **/
888 SHELL_STATUS
889 EFIAPI
890 ShellCommandRunMap (
891 IN EFI_HANDLE ImageHandle,
892 IN EFI_SYSTEM_TABLE *SystemTable
893 )
894 {
895 EFI_STATUS Status;
896 LIST_ENTRY *Package;
897 CHAR16 *ProblemParam;
898 CONST CHAR16 *SName;
899 CONST CHAR16 *Mapping;
900 EFI_HANDLE MappingAsHandle;
901 CONST EFI_DEVICE_PATH_PROTOCOL *DevPath;
902 SHELL_STATUS ShellStatus;
903 BOOLEAN SfoMode;
904 BOOLEAN ConstMode;
905 BOOLEAN NormlMode;
906 CONST CHAR16 *Param1;
907 CONST CHAR16 *TypeString;
908
909 ProblemParam = NULL;
910 Mapping = NULL;
911 SName = NULL;
912 DevPath = NULL;
913 ShellStatus = SHELL_SUCCESS;
914 MappingAsHandle = NULL;
915
916 //
917 // initialize the shell lib (we must be in non-auto-init...)
918 //
919 Status = ShellInitialize();
920 ASSERT_EFI_ERROR(Status);
921
922 Status = CommandInit();
923 ASSERT_EFI_ERROR(Status);
924
925 //
926 // parse the command line
927 //
928 Status = ShellCommandLineParse (MapParamList, &Package, &ProblemParam, TRUE);
929 if (EFI_ERROR(Status)) {
930 if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
931 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel2HiiHandle, ProblemParam);
932 FreePool(ProblemParam);
933 ShellStatus = SHELL_INVALID_PARAMETER;
934 } else {
935 ASSERT(FALSE);
936 }
937 } else {
938 //
939 // check for "-?"
940 //
941 SfoMode = ShellCommandLineGetFlag(Package, L"-sfo");
942 ConstMode = ShellCommandLineGetFlag(Package, L"-c");
943 NormlMode = ShellCommandLineGetFlag(Package, L"-f");
944 if (ShellCommandLineGetFlag(Package, L"-?")) {
945 ASSERT(FALSE);
946 } else if (ShellCommandLineGetRawValue(Package, 3) != NULL) {
947 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel2HiiHandle);
948 ShellStatus = SHELL_INVALID_PARAMETER;
949 } else {
950 //
951 // Deleting a map name...
952 //
953 if (ShellCommandLineGetFlag(Package, L"-d")) {
954 if ( ShellCommandLineGetFlag(Package, L"-r")
955 || ShellCommandLineGetFlag(Package, L"-v")
956 || ConstMode
957 || NormlMode
958 || ShellCommandLineGetFlag(Package, L"-u")
959 || ShellCommandLineGetFlag(Package, L"-t")
960 ){
961 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_CON), gShellLevel2HiiHandle);
962 ShellStatus = SHELL_INVALID_PARAMETER;
963 } else {
964 SName = ShellCommandLineGetValue(Package, L"-d");
965 if (SName != NULL) {
966 Status = PerformMappingDelete(SName);
967 if (EFI_ERROR(Status)) {
968 switch (Status) {
969 case EFI_ACCESS_DENIED:
970 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_AD), gShellLevel2HiiHandle);
971 ShellStatus = SHELL_ACCESS_DENIED;
972 break;
973 case EFI_NOT_FOUND:
974 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MAP_NF), gShellLevel2HiiHandle, SName);
975 ShellStatus = SHELL_INVALID_PARAMETER;
976 break;
977 default:
978 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_UK), gShellLevel2HiiHandle, Status);
979 ShellStatus = SHELL_UNSUPPORTED;
980 }
981 }
982 } else {
983 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellLevel2HiiHandle);
984 ShellStatus = SHELL_INVALID_PARAMETER;
985 }
986 }
987 } else if ( ShellCommandLineGetFlag(Package, L"-r")
988 // || ShellCommandLineGetFlag(Package, L"-v")
989 || ConstMode
990 || NormlMode
991 || ShellCommandLineGetFlag(Package, L"-u")
992 || ShellCommandLineGetFlag(Package, L"-t")
993 ){
994 if ( ShellCommandLineGetFlag(Package, L"-r")) {
995 //
996 // Do the reset
997 //
998 Status = ShellCommandCreateInitialMappingsAndPaths();
999 if (EFI_ERROR(Status)) {
1000 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_UK), gShellLevel2HiiHandle, Status);
1001 ShellStatus = SHELL_UNSUPPORTED;
1002 }
1003 }
1004 if ( ShellStatus == SHELL_SUCCESS && ShellCommandLineGetFlag(Package, L"-u")) {
1005 //
1006 // Do the Update
1007 //
1008 Status = UpdateMapping();
1009 if (EFI_ERROR(Status)) {
1010 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_UK), gShellLevel2HiiHandle, Status);
1011 ShellStatus = SHELL_UNSUPPORTED;
1012 }
1013 }
1014 if (ShellStatus == SHELL_SUCCESS) {
1015 Param1 = ShellCommandLineGetRawValue(Package, 1);
1016 TypeString = ShellCommandLineGetValue(Package, L"-t");
1017 if (!ConstMode
1018 &&!NormlMode
1019 &&TypeString == NULL
1020 ) {
1021 //
1022 // now do the display...
1023 //
1024 ShellStatus = PerformMappingDisplay(
1025 ShellCommandLineGetFlag(Package, L"-v"),
1026 TRUE,
1027 TRUE,
1028 NULL,
1029 SfoMode,
1030 Param1,
1031 TRUE
1032 );
1033 } else {
1034 //
1035 // now do the display...
1036 //
1037 ShellStatus = PerformMappingDisplay2(
1038 ShellCommandLineGetFlag(Package, L"-v"),
1039 ConstMode,
1040 NormlMode,
1041 TypeString,
1042 SfoMode,
1043 Param1
1044 );
1045 }
1046 }
1047 } else {
1048 //
1049 // adding or displaying (there were no flags)
1050 //
1051 SName = ShellCommandLineGetRawValue(Package, 1);
1052 Mapping = ShellCommandLineGetRawValue(Package, 2);
1053 if ( SName == NULL
1054 && Mapping == NULL
1055 ){
1056 //
1057 // display only since no flags
1058 //
1059 ShellStatus = PerformMappingDisplay(
1060 ShellCommandLineGetFlag(Package, L"-v"),
1061 TRUE,
1062 TRUE,
1063 NULL,
1064 SfoMode,
1065 NULL,
1066 TRUE
1067 );
1068 } else if ( SName == NULL
1069 || Mapping == NULL
1070 ){
1071 //
1072 // Display only the one specified
1073 //
1074 ShellStatus = PerformMappingDisplay(
1075 FALSE,
1076 FALSE,
1077 FALSE,
1078 NULL,
1079 SfoMode,
1080 SName, // note the variable here...
1081 TRUE
1082 );
1083 } else {
1084 if (ShellIsHexOrDecimalNumber(Mapping, TRUE, FALSE)) {
1085 MappingAsHandle = ConvertHandleIndexToHandle(StrHexToUintn(Mapping));
1086 } else {
1087 MappingAsHandle = NULL;
1088 }
1089 if (MappingAsHandle == NULL && Mapping[StrLen(Mapping)-1] != L':') {
1090 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel2HiiHandle, Mapping);
1091 ShellStatus = SHELL_INVALID_PARAMETER;
1092 } else {
1093 if (MappingAsHandle != NULL) {
1094 ShellStatus = AddMappingFromHandle(MappingAsHandle, SName);
1095 } else {
1096 ShellStatus = AddMappingFromMapping(Mapping, SName);
1097 }
1098 if (ShellStatus != SHELL_SUCCESS) {
1099 switch (ShellStatus) {
1100 case SHELL_ACCESS_DENIED:
1101 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_AD), gShellLevel2HiiHandle);
1102 break;
1103 case SHELL_INVALID_PARAMETER:
1104 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellLevel2HiiHandle);
1105 break;
1106 default:
1107 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_UK), gShellLevel2HiiHandle, ShellStatus|MAX_BIT);
1108 }
1109 } else {
1110 //
1111 // now do the display...
1112 //
1113 ShellStatus = PerformMappingDisplay(
1114 FALSE,
1115 FALSE,
1116 FALSE,
1117 NULL,
1118 SfoMode,
1119 SName,
1120 TRUE
1121 );
1122 } // we were sucessful so do an output
1123 } // got a valid map target
1124 } // got 2 variables
1125 } // we are adding a mapping
1126 } // got valid parameters
1127 }
1128
1129 //
1130 // free the command line package
1131 //
1132 ShellCommandLineFreeVarList (Package);
1133
1134 return (ShellStatus);
1135 }
1136