]> git.proxmox.com Git - mirror_edk2.git/blob - ShellPkg/Library/UefiShellLevel2CommandsLib/Map.c
Verify memory allocations were successful.
[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 Status = gBS->LocateHandle(
668 ByProtocol,
669 &gEfiDevicePathProtocolGuid,
670 NULL,
671 &BufferSize,
672 HandleBuffer);
673 }
674 ASSERT_EFI_ERROR(Status);
675 ASSERT(HandleBuffer != NULL);
676
677 //
678 // Get the map name(s) for each one.
679 //
680 for ( LoopVar = 0
681 ; LoopVar < BufferSize / sizeof(EFI_HANDLE)
682 ; LoopVar ++
683 ){
684 if (PerformSingleMappingDelete(Specific,HandleBuffer[LoopVar]) == SHELL_SUCCESS) {
685 Deleted = TRUE;
686 }
687 }
688
689 //
690 // Look up all BlockIo in the platform
691 //
692 Status = gBS->LocateHandle(
693 ByProtocol,
694 &gEfiBlockIoProtocolGuid,
695 NULL,
696 &BufferSize,
697 HandleBuffer);
698 if (Status == EFI_BUFFER_TOO_SMALL) {
699 FreePool(HandleBuffer);
700 HandleBuffer = AllocatePool(BufferSize);
701 Status = gBS->LocateHandle(
702 ByProtocol,
703 &gEfiBlockIoProtocolGuid,
704 NULL,
705 &BufferSize,
706 HandleBuffer);
707 }
708 ASSERT_EFI_ERROR(Status);
709
710 //
711 // Get the map name(s) for each one.
712 //
713 for ( LoopVar = 0
714 ; LoopVar < BufferSize / sizeof(EFI_HANDLE)
715 ; LoopVar ++
716 ){
717 //
718 // Skip any that were already done...
719 //
720 if (gBS->OpenProtocol(
721 HandleBuffer[LoopVar],
722 &gEfiDevicePathProtocolGuid,
723 NULL,
724 gImageHandle,
725 NULL,
726 EFI_OPEN_PROTOCOL_TEST_PROTOCOL) == EFI_SUCCESS) {
727 continue;
728 }
729 if (PerformSingleMappingDelete(Specific,HandleBuffer[LoopVar]) == SHELL_SUCCESS) {
730 Deleted = TRUE;
731 }
732 }
733 FreePool(HandleBuffer);
734 if (!Deleted) {
735 return (EFI_NOT_FOUND);
736 }
737 return (EFI_SUCCESS);
738 }
739
740 /**
741 function to add a mapping from mapping.
742
743 This function will get the device path associated with the mapping and call SetMap.
744
745 @param[in] Map The Map to add a mapping for
746 @param[in] SName The name of the new mapping
747
748 @retval SHELL_SUCCESS the mapping was added
749 @retval SHELL_INVALID_PARAMETER the device path for Map could not be retrieved.
750 @return Shell version of a return value from EfiShellProtocol->SetMap
751
752 **/
753 SHELL_STATUS
754 EFIAPI
755 AddMappingFromMapping(
756 IN CONST CHAR16 *Map,
757 IN CONST CHAR16 *SName
758 )
759 {
760 CONST EFI_DEVICE_PATH_PROTOCOL *DevPath;
761 EFI_STATUS Status;
762
763 if (StrStr(SName, L"*") != NULL
764 ||StrStr(SName, L"?") != NULL
765 ||StrStr(SName, L"[") != NULL
766 ||StrStr(SName, L"]") != NULL) {
767 return (SHELL_INVALID_PARAMETER);
768 }
769
770 DevPath = gEfiShellProtocol->GetDevicePathFromMap(Map);
771 if (DevPath == NULL) {
772 return (SHELL_INVALID_PARAMETER);
773 }
774
775 Status = gEfiShellProtocol->SetMap(DevPath, SName);
776 if (EFI_ERROR(Status)) {
777 return (SHELL_DEVICE_ERROR);
778 }
779 return (SHELL_SUCCESS);
780 }
781
782 /**
783 function to determine if a string has only numbers and letters
784
785 This is useful for such things as Map names which can only be letters and numbers
786
787 @param[in] String pointer to the string to analyze
788
789 @retval TRUE String has only numbers and letters
790 @retval FALSE String has at least one other character.
791 **/
792 BOOLEAN
793 EFIAPI
794 IsNumberLetterOnly(
795 IN CONST CHAR16 *String
796 )
797 {
798 while(String != NULL && *String != CHAR_NULL) {
799 if (! ((*String >= L'a' && *String <= L'z') ||
800 (*String >= L'A' && *String <= L'Z') ||
801 (*String >= L'0' && *String <= L'9'))
802 ){
803 return (FALSE);
804 }
805 String++;
806 }
807 return (TRUE);
808 }
809
810 /**
811 function to add a mapping from an EFI_HANDLE.
812
813 This function will get the device path associated with the Handle and call SetMap.
814
815 @param[in] Handle The handle to add a mapping for
816 @param[in] SName The name of the new mapping
817
818 @retval SHELL_SUCCESS the mapping was added
819 @retval SHELL_INVALID_PARAMETER SName was not valid for a map name.
820 @return Shell version of a return value from either
821 gBS->OpenProtocol or EfiShellProtocol->SetMap
822
823 **/
824 SHELL_STATUS
825 EFIAPI
826 AddMappingFromHandle(
827 IN CONST EFI_HANDLE Handle,
828 IN CONST CHAR16 *SName
829 )
830 {
831 EFI_DEVICE_PATH_PROTOCOL *DevPath;
832 EFI_STATUS Status;
833
834 if (!IsNumberLetterOnly(SName)) {
835 return (SHELL_INVALID_PARAMETER);
836 }
837
838 Status = gBS->OpenProtocol(
839 Handle,
840 &gEfiDevicePathProtocolGuid,
841 (VOID**)&DevPath,
842 gImageHandle,
843 NULL,
844 EFI_OPEN_PROTOCOL_GET_PROTOCOL
845 );
846 if (EFI_ERROR(Status)) {
847 return (SHELL_DEVICE_ERROR);
848 }
849 Status = gEfiShellProtocol->SetMap(DevPath, SName);
850 if (EFI_ERROR(Status)) {
851 return (SHELL_DEVICE_ERROR);
852 }
853 return (SHELL_SUCCESS);
854 }
855
856 STATIC CONST SHELL_PARAM_ITEM MapParamList[] = {
857 {L"-d", TypeValue},
858 {L"-r", TypeFlag},
859 {L"-v", TypeFlag},
860 {L"-c", TypeFlag},
861 {L"-f", TypeFlag},
862 {L"-u", TypeFlag},
863 {L"-t", TypeValue},
864 {L"-sfo", TypeValue},
865 {NULL, TypeMax}
866 };
867
868 /**
869 Function for 'map' command.
870
871 @param[in] ImageHandle Handle to the Image (NULL if Internal).
872 @param[in] SystemTable Pointer to the System Table (NULL if Internal).
873 **/
874 SHELL_STATUS
875 EFIAPI
876 ShellCommandRunMap (
877 IN EFI_HANDLE ImageHandle,
878 IN EFI_SYSTEM_TABLE *SystemTable
879 )
880 {
881 EFI_STATUS Status;
882 LIST_ENTRY *Package;
883 CHAR16 *ProblemParam;
884 CONST CHAR16 *SName;
885 CONST CHAR16 *Mapping;
886 EFI_HANDLE MappingAsHandle;
887 CONST EFI_DEVICE_PATH_PROTOCOL *DevPath;
888 SHELL_STATUS ShellStatus;
889 BOOLEAN SfoMode;
890 BOOLEAN ConstMode;
891 BOOLEAN NormlMode;
892 CONST CHAR16 *Param1;
893 CONST CHAR16 *TypeString;
894
895 ProblemParam = NULL;
896 Mapping = NULL;
897 SName = NULL;
898 DevPath = NULL;
899 ShellStatus = SHELL_SUCCESS;
900 MappingAsHandle = NULL;
901
902 //
903 // initialize the shell lib (we must be in non-auto-init...)
904 //
905 Status = ShellInitialize();
906 ASSERT_EFI_ERROR(Status);
907
908 Status = CommandInit();
909 ASSERT_EFI_ERROR(Status);
910
911 //
912 // parse the command line
913 //
914 Status = ShellCommandLineParse (MapParamList, &Package, &ProblemParam, TRUE);
915 if (EFI_ERROR(Status)) {
916 if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
917 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel2HiiHandle, ProblemParam);
918 FreePool(ProblemParam);
919 ShellStatus = SHELL_INVALID_PARAMETER;
920 } else {
921 ASSERT(FALSE);
922 }
923 } else {
924 //
925 // check for "-?"
926 //
927 SfoMode = ShellCommandLineGetFlag(Package, L"-sfo");
928 ConstMode = ShellCommandLineGetFlag(Package, L"-c");
929 NormlMode = ShellCommandLineGetFlag(Package, L"-f");
930 if (ShellCommandLineGetFlag(Package, L"-?")) {
931 ASSERT(FALSE);
932 } else if (ShellCommandLineGetRawValue(Package, 3) != NULL) {
933 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel2HiiHandle);
934 ShellStatus = SHELL_INVALID_PARAMETER;
935 } else {
936 //
937 // Deleting a map name...
938 //
939 if (ShellCommandLineGetFlag(Package, L"-d")) {
940 if ( ShellCommandLineGetFlag(Package, L"-r")
941 || ShellCommandLineGetFlag(Package, L"-v")
942 || ConstMode
943 || NormlMode
944 || ShellCommandLineGetFlag(Package, L"-u")
945 || ShellCommandLineGetFlag(Package, L"-t")
946 ){
947 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_CON), gShellLevel2HiiHandle);
948 ShellStatus = SHELL_INVALID_PARAMETER;
949 } else {
950 SName = ShellCommandLineGetValue(Package, L"-d");
951 if (SName != NULL) {
952 Status = PerformMappingDelete(SName);
953 if (EFI_ERROR(Status)) {
954 switch (Status) {
955 case EFI_ACCESS_DENIED:
956 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_AD), gShellLevel2HiiHandle);
957 ShellStatus = SHELL_ACCESS_DENIED;
958 break;
959 case EFI_NOT_FOUND:
960 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MAP_NF), gShellLevel2HiiHandle, SName);
961 ShellStatus = SHELL_INVALID_PARAMETER;
962 break;
963 default:
964 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_UK), gShellLevel2HiiHandle, Status);
965 ShellStatus = SHELL_UNSUPPORTED;
966 }
967 }
968 } else {
969 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellLevel2HiiHandle);
970 ShellStatus = SHELL_INVALID_PARAMETER;
971 }
972 }
973 } else if ( ShellCommandLineGetFlag(Package, L"-r")
974 // || ShellCommandLineGetFlag(Package, L"-v")
975 || ConstMode
976 || NormlMode
977 || ShellCommandLineGetFlag(Package, L"-u")
978 || ShellCommandLineGetFlag(Package, L"-t")
979 ){
980 if ( ShellCommandLineGetFlag(Package, L"-r")) {
981 //
982 // Do the reset
983 //
984 Status = ShellCommandCreateInitialMappingsAndPaths();
985 if (EFI_ERROR(Status)) {
986 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_UK), gShellLevel2HiiHandle, Status);
987 ShellStatus = SHELL_UNSUPPORTED;
988 }
989 }
990 if ( ShellStatus == SHELL_SUCCESS && ShellCommandLineGetFlag(Package, L"-u")) {
991 //
992 // Do the Update
993 //
994 Status = UpdateMapping();
995 if (EFI_ERROR(Status)) {
996 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_UK), gShellLevel2HiiHandle, Status);
997 ShellStatus = SHELL_UNSUPPORTED;
998 }
999 }
1000 if (ShellStatus == SHELL_SUCCESS) {
1001 Param1 = ShellCommandLineGetRawValue(Package, 1);
1002 TypeString = ShellCommandLineGetValue(Package, L"-t");
1003 if (!ConstMode
1004 &&!NormlMode
1005 &&TypeString == NULL
1006 ) {
1007 //
1008 // now do the display...
1009 //
1010 ShellStatus = PerformMappingDisplay(
1011 ShellCommandLineGetFlag(Package, L"-v"),
1012 TRUE,
1013 TRUE,
1014 NULL,
1015 SfoMode,
1016 Param1,
1017 TRUE
1018 );
1019 } else {
1020 //
1021 // now do the display...
1022 //
1023 ShellStatus = PerformMappingDisplay2(
1024 ShellCommandLineGetFlag(Package, L"-v"),
1025 ConstMode,
1026 NormlMode,
1027 TypeString,
1028 SfoMode,
1029 Param1
1030 );
1031 }
1032 }
1033 } else {
1034 //
1035 // adding or displaying (there were no flags)
1036 //
1037 SName = ShellCommandLineGetRawValue(Package, 1);
1038 Mapping = ShellCommandLineGetRawValue(Package, 2);
1039 if ( SName == NULL
1040 && Mapping == NULL
1041 ){
1042 //
1043 // display only since no flags
1044 //
1045 ShellStatus = PerformMappingDisplay(
1046 ShellCommandLineGetFlag(Package, L"-v"),
1047 TRUE,
1048 TRUE,
1049 NULL,
1050 SfoMode,
1051 NULL,
1052 TRUE
1053 );
1054 } else if ( SName == NULL
1055 || Mapping == NULL
1056 ){
1057 //
1058 // Display only the one specified
1059 //
1060 ShellStatus = PerformMappingDisplay(
1061 FALSE,
1062 FALSE,
1063 FALSE,
1064 NULL,
1065 SfoMode,
1066 SName, // note the variable here...
1067 TRUE
1068 );
1069 } else {
1070 if (ShellIsHexOrDecimalNumber(Mapping, TRUE, FALSE)) {
1071 MappingAsHandle = ConvertHandleIndexToHandle(StrHexToUintn(Mapping));
1072 } else {
1073 MappingAsHandle = NULL;
1074 }
1075 if (MappingAsHandle == NULL && Mapping[StrLen(Mapping)-1] != L':') {
1076 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel2HiiHandle, Mapping);
1077 ShellStatus = SHELL_INVALID_PARAMETER;
1078 } else {
1079 if (MappingAsHandle != NULL) {
1080 ShellStatus = AddMappingFromHandle(MappingAsHandle, SName);
1081 } else {
1082 ShellStatus = AddMappingFromMapping(Mapping, SName);
1083 }
1084 if (ShellStatus != SHELL_SUCCESS) {
1085 switch (ShellStatus) {
1086 case SHELL_ACCESS_DENIED:
1087 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_AD), gShellLevel2HiiHandle);
1088 break;
1089 case SHELL_INVALID_PARAMETER:
1090 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellLevel2HiiHandle);
1091 break;
1092 default:
1093 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_UK), gShellLevel2HiiHandle, ShellStatus|MAX_BIT);
1094 }
1095 } else {
1096 //
1097 // now do the display...
1098 //
1099 ShellStatus = PerformMappingDisplay(
1100 FALSE,
1101 FALSE,
1102 FALSE,
1103 NULL,
1104 SfoMode,
1105 SName,
1106 TRUE
1107 );
1108 } // we were sucessful so do an output
1109 } // got a valid map target
1110 } // got 2 variables
1111 } // we are adding a mapping
1112 } // got valid parameters
1113 }
1114
1115 //
1116 // free the command line package
1117 //
1118 ShellCommandLineFreeVarList (Package);
1119
1120 return (ShellStatus);
1121 }
1122