blob: 5d6a200c196abe88e45b129bb95c447deed2dc07 [file] [log] [blame]
jcarseya405b862010-09-14 05:18:09 +00001/** @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
22BOOLEAN
23EFIAPI
24SearchList(
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
78EFI_STATUS
79EFIAPI
80UpdateMapping (
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 = GetHandleListByPotocol(&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
175CHAR16*
176EFIAPI
177GetDeviceMediaType (
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**/
221BOOLEAN
222EFIAPI
223IsRemoveableDevice (
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**/
258BOOLEAN
259EFIAPI
260MappingListHasType(
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
297VOID
298EFIAPI
299PerformSingleMappingDisplay(
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
390EFI_STATUS
391EFIAPI
392PerformSingleMappingDelete(
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**/
436CONST CHAR16 Cd[] = L"cd*";
437CONST CHAR16 Hd[] = L"hd*";
438CONST CHAR16 Fp[] = L"fp*";
439CONST CHAR16 F[] = L"F*";
440SHELL_STATUS
441EFIAPI
442PerformMappingDisplay(
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 Status = gBS->LocateHandle(
507 ByProtocol,
508 &gEfiDevicePathProtocolGuid,
509 NULL,
510 &BufferSize,
511 HandleBuffer);
512 }
513 ASSERT_EFI_ERROR(Status);
514 ASSERT(HandleBuffer != NULL);
515
516 //
517 // Get the map name(s) for each one.
518 //
519 for ( LoopVar = 0
520 ; LoopVar < (BufferSize / sizeof(EFI_HANDLE))
521 ; LoopVar ++
522 ){
523 PerformSingleMappingDisplay(
524 Verbose,
525 Consist,
526 Normal,
527 Test,
528 SFO,
529 Specific,
530 HandleBuffer[LoopVar]);
531 }
532
533 //
534 // Look up all BlockIo in the platform
535 //
536 Status = gBS->LocateHandle(
537 ByProtocol,
538 &gEfiBlockIoProtocolGuid,
539 NULL,
540 &BufferSize,
541 HandleBuffer);
542 if (Status == EFI_BUFFER_TOO_SMALL) {
543 FreePool(HandleBuffer);
544 HandleBuffer = AllocatePool(BufferSize);
545 Status = gBS->LocateHandle(
546 ByProtocol,
547 &gEfiBlockIoProtocolGuid,
548 NULL,
549 &BufferSize,
550 HandleBuffer);
551 }
552 ASSERT_EFI_ERROR(Status);
553
554 //
555 // Get the map name(s) for each one.
556 //
557 for ( LoopVar = 0
558 ; LoopVar < BufferSize / sizeof(EFI_HANDLE)
559 ; LoopVar ++
560 ){
561 //
562 // Skip any that were already done...
563 //
564 if (gBS->OpenProtocol(
565 HandleBuffer[LoopVar],
566 &gEfiDevicePathProtocolGuid,
567 NULL,
568 gImageHandle,
569 NULL,
570 EFI_OPEN_PROTOCOL_TEST_PROTOCOL) == EFI_SUCCESS) {
571 continue;
572 }
573 PerformSingleMappingDisplay(
574 Verbose,
575 Consist,
576 Normal,
577 Test,
578 SFO,
579 Specific,
580 HandleBuffer[LoopVar]);
581 }
582 FreePool(HandleBuffer);
583 return (SHELL_SUCCESS);
584}
585
586SHELL_STATUS
587EFIAPI
588PerformMappingDisplay2(
589 IN CONST BOOLEAN Verbose,
590 IN CONST BOOLEAN Consist,
591 IN CONST BOOLEAN Normal,
592 IN CONST CHAR16 *TypeString,
593 IN CONST BOOLEAN SFO,
594 IN CONST CHAR16 *Specific OPTIONAL
595 )
596{
597 CONST CHAR16 *TypeWalker;
598 SHELL_STATUS ShellStatus;
599 CHAR16 *Comma;
600
601
602 if (TypeString == NULL) {
603 return (PerformMappingDisplay(Verbose, Consist, Normal, NULL, SFO, Specific, TRUE));
604 }
605 ShellStatus = SHELL_SUCCESS;
606 for (TypeWalker = TypeString ; TypeWalker != NULL && *TypeWalker != CHAR_NULL ;) {
607 Comma = StrStr(TypeWalker, L",");
608 if (Comma == NULL) {
609 if (ShellStatus == SHELL_SUCCESS) {
610 ShellStatus = PerformMappingDisplay(Verbose, Consist, Normal, TypeWalker, SFO, Specific, (BOOLEAN)(TypeWalker == TypeString));
611 } else {
612 PerformMappingDisplay(Verbose, Consist, Normal, TypeWalker, SFO, Specific, (BOOLEAN)(TypeWalker == TypeString));
613 }
614 break;
615 } else {
616 *Comma = CHAR_NULL;
617 if (ShellStatus == SHELL_SUCCESS) {
618 ShellStatus = PerformMappingDisplay(Verbose, Consist, Normal, TypeWalker, SFO, Specific, (BOOLEAN)(TypeWalker == TypeString));
619 } else {
620 PerformMappingDisplay(Verbose, Consist, Normal, TypeWalker, SFO, Specific, (BOOLEAN)(TypeWalker == TypeString));
621 }
622 *Comma = L',';
623 TypeWalker = Comma + 1;
624 }
625 }
626
627 return (ShellStatus);
628}
629
630EFI_STATUS
631EFIAPI
632PerformMappingDelete(
633 IN CONST CHAR16 *Specific
634 )
635{
636 EFI_STATUS Status;
637 EFI_HANDLE *HandleBuffer;
638 UINTN BufferSize;
639 UINTN LoopVar;
640 BOOLEAN Deleted;
641
642 if (Specific == NULL) {
643 return (EFI_INVALID_PARAMETER);
644 }
645
646 BufferSize = 0;
647 HandleBuffer = NULL;
648 Deleted = FALSE;
649
650 //
651 // Look up all SimpleFileSystems in the platform
652 //
653 Status = gBS->LocateHandle(
654 ByProtocol,
655 &gEfiDevicePathProtocolGuid,
656 NULL,
657 &BufferSize,
658 HandleBuffer);
659 if (Status == EFI_BUFFER_TOO_SMALL) {
660 HandleBuffer = AllocatePool(BufferSize);
661 Status = gBS->LocateHandle(
662 ByProtocol,
663 &gEfiDevicePathProtocolGuid,
664 NULL,
665 &BufferSize,
666 HandleBuffer);
667 }
668 ASSERT_EFI_ERROR(Status);
669 ASSERT(HandleBuffer != NULL);
670
671 //
672 // Get the map name(s) for each one.
673 //
674 for ( LoopVar = 0
675 ; LoopVar < BufferSize / sizeof(EFI_HANDLE)
676 ; LoopVar ++
677 ){
678 if (PerformSingleMappingDelete(Specific,HandleBuffer[LoopVar]) == SHELL_SUCCESS) {
679 Deleted = TRUE;
680 }
681 }
682
683 //
684 // Look up all BlockIo in the platform
685 //
686 Status = gBS->LocateHandle(
687 ByProtocol,
688 &gEfiBlockIoProtocolGuid,
689 NULL,
690 &BufferSize,
691 HandleBuffer);
692 if (Status == EFI_BUFFER_TOO_SMALL) {
693 FreePool(HandleBuffer);
694 HandleBuffer = AllocatePool(BufferSize);
695 Status = gBS->LocateHandle(
696 ByProtocol,
697 &gEfiBlockIoProtocolGuid,
698 NULL,
699 &BufferSize,
700 HandleBuffer);
701 }
702 ASSERT_EFI_ERROR(Status);
703
704 //
705 // Get the map name(s) for each one.
706 //
707 for ( LoopVar = 0
708 ; LoopVar < BufferSize / sizeof(EFI_HANDLE)
709 ; LoopVar ++
710 ){
711 //
712 // Skip any that were already done...
713 //
714 if (gBS->OpenProtocol(
715 HandleBuffer[LoopVar],
716 &gEfiDevicePathProtocolGuid,
717 NULL,
718 gImageHandle,
719 NULL,
720 EFI_OPEN_PROTOCOL_TEST_PROTOCOL) == EFI_SUCCESS) {
721 continue;
722 }
723 if (PerformSingleMappingDelete(Specific,HandleBuffer[LoopVar]) == SHELL_SUCCESS) {
724 Deleted = TRUE;
725 }
726 }
727 FreePool(HandleBuffer);
728 if (!Deleted) {
729 return (EFI_NOT_FOUND);
730 }
731 return (EFI_SUCCESS);
732}
733
734/**
735 function to add a mapping from mapping.
736
737 This function will get the device path associated with the mapping and call SetMap.
738
739 @param[in] Map The Map to add a mapping for
740 @param[in] SName The name of the new mapping
741
742 @retval SHELL_SUCCESS the mapping was added
743 @retval SHELL_INVALID_PARAMETER the device path for Map could not be retrieved.
744 @return Shell version of a return value from EfiShellProtocol->SetMap
745
746**/
747SHELL_STATUS
748EFIAPI
749AddMappingFromMapping(
750 IN CONST CHAR16 *Map,
751 IN CONST CHAR16 *SName
752 )
753{
754 CONST EFI_DEVICE_PATH_PROTOCOL *DevPath;
755 EFI_STATUS Status;
756
757 if (StrStr(SName, L"*") != NULL
758 ||StrStr(SName, L"?") != NULL
759 ||StrStr(SName, L"[") != NULL
760 ||StrStr(SName, L"]") != NULL) {
761 return (SHELL_INVALID_PARAMETER);
762 }
763
764 DevPath = gEfiShellProtocol->GetDevicePathFromMap(Map);
765 if (DevPath == NULL) {
766 return (SHELL_INVALID_PARAMETER);
767 }
768
769 Status = gEfiShellProtocol->SetMap(DevPath, SName);
770 if (EFI_ERROR(Status)) {
771 return (SHELL_DEVICE_ERROR);
772 }
773 return (SHELL_SUCCESS);
774}
775
776/**
777 function to determine if a string has only numbers and letters
778
779 This is useful for such things as Map names which can only be letters and numbers
780
781 @param[in] String pointer to the string to analyze
782
783 @retval TRUE String has only numbers and letters
784 @retval FALSE String has at least one other character.
785**/
786BOOLEAN
787EFIAPI
788IsNumberLetterOnly(
789 IN CONST CHAR16 *String
790 )
791{
792 while(String != NULL && *String != CHAR_NULL) {
793 if (! ( *String >= L'a' && *String <= L'z'
794 || *String >= L'A' && *String <= L'Z'
795 || *String >= L'0' && *String <= L'9')
796 ){
797 return (FALSE);
798 }
799 String++;
800 }
801 return (TRUE);
802}
803
804/**
805 function to add a mapping from an EFI_HANDLE.
806
807 This function will get the device path associated with the Handle and call SetMap.
808
809 @param[in] Handle The handle to add a mapping for
810 @param[in] SName The name of the new mapping
811
812 @retval SHELL_SUCCESS the mapping was added
813 @retval SHELL_INVALID_PARAMETER SName was not valid for a map name.
814 @return Shell version of a return value from either
815 gBS->OpenProtocol or EfiShellProtocol->SetMap
816
817**/
818SHELL_STATUS
819EFIAPI
820AddMappingFromHandle(
821 IN CONST EFI_HANDLE Handle,
822 IN CONST CHAR16 *SName
823 )
824{
825 EFI_DEVICE_PATH_PROTOCOL *DevPath;
826 EFI_STATUS Status;
827
828 if (!IsNumberLetterOnly(SName)) {
829 return (SHELL_INVALID_PARAMETER);
830 }
831
832 Status = gBS->OpenProtocol(
833 Handle,
834 &gEfiDevicePathProtocolGuid,
835 (VOID**)&DevPath,
836 gImageHandle,
837 NULL,
838 EFI_OPEN_PROTOCOL_GET_PROTOCOL
839 );
840 if (EFI_ERROR(Status)) {
841 return (SHELL_DEVICE_ERROR);
842 }
843 Status = gEfiShellProtocol->SetMap(DevPath, SName);
844 if (EFI_ERROR(Status)) {
845 return (SHELL_DEVICE_ERROR);
846 }
847 return (SHELL_SUCCESS);
848}
849
850STATIC CONST SHELL_PARAM_ITEM MapParamList[] = {
851 {L"-d", TypeValue},
852 {L"-r", TypeFlag},
853 {L"-v", TypeFlag},
854 {L"-c", TypeFlag},
855 {L"-f", TypeFlag},
856 {L"-u", TypeFlag},
857 {L"-t", TypeValue},
858 {L"-sfo", TypeValue},
859 {NULL, TypeMax}
860 };
861
862/**
863 Function for 'map' command.
864
865 @param[in] ImageHandle Handle to the Image (NULL if Internal).
866 @param[in] SystemTable Pointer to the System Table (NULL if Internal).
867**/
868SHELL_STATUS
869EFIAPI
870ShellCommandRunMap (
871 IN EFI_HANDLE ImageHandle,
872 IN EFI_SYSTEM_TABLE *SystemTable
873 )
874{
875 EFI_STATUS Status;
876 LIST_ENTRY *Package;
877 CHAR16 *ProblemParam;
878 CONST CHAR16 *SName;
879 CONST CHAR16 *Mapping;
880 EFI_HANDLE MappingAsHandle;
881 CONST EFI_DEVICE_PATH_PROTOCOL *DevPath;
882 SHELL_STATUS ShellStatus;
883 BOOLEAN SfoMode;
884 BOOLEAN ConstMode;
885 BOOLEAN NormlMode;
886 CONST CHAR16 *Param1;
887 CONST CHAR16 *TypeString;
888
889 ProblemParam = NULL;
890 Mapping = NULL;
891 SName = NULL;
892 DevPath = NULL;
893 ShellStatus = SHELL_SUCCESS;
894 MappingAsHandle = NULL;
895
896 //
897 // initialize the shell lib (we must be in non-auto-init...)
898 //
899 Status = ShellInitialize();
900 ASSERT_EFI_ERROR(Status);
901
902 Status = CommandInit();
903 ASSERT_EFI_ERROR(Status);
904
905 //
906 // parse the command line
907 //
908 Status = ShellCommandLineParse (MapParamList, &Package, &ProblemParam, TRUE);
909 if (EFI_ERROR(Status)) {
910 if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
911 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel2HiiHandle, ProblemParam);
912 FreePool(ProblemParam);
913 ShellStatus = SHELL_INVALID_PARAMETER;
914 } else {
915 ASSERT(FALSE);
916 }
917 } else {
918 //
919 // check for "-?"
920 //
921 SfoMode = ShellCommandLineGetFlag(Package, L"-sfo");
922 ConstMode = ShellCommandLineGetFlag(Package, L"-c");
923 NormlMode = ShellCommandLineGetFlag(Package, L"-f");
924 if (ShellCommandLineGetFlag(Package, L"-?")) {
925 ASSERT(FALSE);
926 } else if (ShellCommandLineGetRawValue(Package, 3) != NULL) {
927 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel2HiiHandle);
928 ShellStatus = SHELL_INVALID_PARAMETER;
929 } else {
930 //
931 // Deleting a map name...
932 //
933 if (ShellCommandLineGetFlag(Package, L"-d")) {
934 if ( ShellCommandLineGetFlag(Package, L"-r")
935 || ShellCommandLineGetFlag(Package, L"-v")
936 || ConstMode
937 || NormlMode
938 || ShellCommandLineGetFlag(Package, L"-u")
939 || ShellCommandLineGetFlag(Package, L"-t")
940 ){
941 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_CON), gShellLevel2HiiHandle);
942 ShellStatus = SHELL_INVALID_PARAMETER;
943 } else {
944 SName = ShellCommandLineGetValue(Package, L"-d");
945 if (SName != NULL) {
946 Status = PerformMappingDelete(SName);
947 if (EFI_ERROR(Status)) {
948 switch (Status) {
949 case EFI_ACCESS_DENIED:
950 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_AD), gShellLevel2HiiHandle);
951 ShellStatus = SHELL_ACCESS_DENIED;
952 break;
953 case EFI_NOT_FOUND:
954 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MAP_NF), gShellLevel2HiiHandle, SName);
955 ShellStatus = SHELL_INVALID_PARAMETER;
956 break;
957 default:
958 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_UK), gShellLevel2HiiHandle, Status);
959 ShellStatus = SHELL_UNSUPPORTED;
960 }
961 }
962 } else {
963 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellLevel2HiiHandle);
964 ShellStatus = SHELL_INVALID_PARAMETER;
965 }
966 }
967 } else if ( ShellCommandLineGetFlag(Package, L"-r")
968// || ShellCommandLineGetFlag(Package, L"-v")
969 || ConstMode
970 || NormlMode
971 || ShellCommandLineGetFlag(Package, L"-u")
972 || ShellCommandLineGetFlag(Package, L"-t")
973 ){
974 if ( ShellCommandLineGetFlag(Package, L"-r")) {
975 //
976 // Do the reset
977 //
978 Status = ShellCommandCreateInitialMappingsAndPaths();
979 if (EFI_ERROR(Status)) {
980 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_UK), gShellLevel2HiiHandle, Status);
981 ShellStatus = SHELL_UNSUPPORTED;
982 }
983 }
984 if ( ShellStatus == SHELL_SUCCESS && ShellCommandLineGetFlag(Package, L"-u")) {
985 //
986 // Do the Update
987 //
988 Status = UpdateMapping();
989 if (EFI_ERROR(Status)) {
990 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_UK), gShellLevel2HiiHandle, Status);
991 ShellStatus = SHELL_UNSUPPORTED;
992 }
993 }
994 if (ShellStatus == SHELL_SUCCESS) {
995 Param1 = ShellCommandLineGetRawValue(Package, 1);
996 TypeString = ShellCommandLineGetValue(Package, L"-t");
997 if (!ConstMode
998 &&!NormlMode
999 &&TypeString == NULL
1000 ) {
1001 //
1002 // now do the display...
1003 //
1004 ShellStatus = PerformMappingDisplay(
1005 ShellCommandLineGetFlag(Package, L"-v"),
1006 TRUE,
1007 TRUE,
1008 NULL,
1009 SfoMode,
1010 Param1,
1011 TRUE
1012 );
1013 } else {
1014 //
1015 // now do the display...
1016 //
1017 ShellStatus = PerformMappingDisplay2(
1018 ShellCommandLineGetFlag(Package, L"-v"),
1019 ConstMode,
1020 NormlMode,
1021 TypeString,
1022 SfoMode,
1023 Param1
1024 );
1025 }
1026 }
1027 } else {
1028 //
1029 // adding or displaying (there were no flags)
1030 //
1031 SName = ShellCommandLineGetRawValue(Package, 1);
1032 Mapping = ShellCommandLineGetRawValue(Package, 2);
1033 if ( SName == NULL
1034 && Mapping == NULL
1035 ){
1036 //
1037 // display only since no flags
1038 //
1039 ShellStatus = PerformMappingDisplay(
1040 ShellCommandLineGetFlag(Package, L"-v"),
1041 TRUE,
1042 TRUE,
1043 NULL,
1044 SfoMode,
1045 NULL,
1046 TRUE
1047 );
1048 } else if ( SName == NULL
1049 || Mapping == NULL
1050 ){
1051 //
1052 // Display only the one specified
1053 //
1054 ShellStatus = PerformMappingDisplay(
1055 FALSE,
1056 FALSE,
1057 FALSE,
1058 NULL,
1059 SfoMode,
1060 SName, // note the variable here...
1061 TRUE
1062 );
1063 } else {
1064 if (ShellIsHexOrDecimalNumber(Mapping, TRUE, FALSE)) {
1065 MappingAsHandle = ConvertHandleIndexToHandle(StrHexToUintn(Mapping));
1066 } else {
1067 MappingAsHandle = NULL;
1068 }
1069 if (MappingAsHandle == NULL && Mapping[StrLen(Mapping)-1] != L':') {
1070 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel2HiiHandle, Mapping);
1071 ShellStatus = SHELL_INVALID_PARAMETER;
1072 } else {
1073 if (MappingAsHandle != NULL) {
1074 ShellStatus = AddMappingFromHandle(MappingAsHandle, SName);
1075 } else {
1076 ShellStatus = AddMappingFromMapping(Mapping, SName);
1077 }
1078 if (ShellStatus != SHELL_SUCCESS) {
1079 switch (ShellStatus) {
1080 case SHELL_ACCESS_DENIED:
1081 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_AD), gShellLevel2HiiHandle);
1082 break;
1083 case SHELL_INVALID_PARAMETER:
1084 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellLevel2HiiHandle);
1085 break;
1086 default:
1087 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_UK), gShellLevel2HiiHandle, ShellStatus|MAX_BIT);
1088 }
1089 } else {
1090 //
1091 // now do the display...
1092 //
1093 ShellStatus = PerformMappingDisplay(
1094 FALSE,
1095 FALSE,
1096 FALSE,
1097 NULL,
1098 SfoMode,
1099 SName,
1100 TRUE
1101 );
1102 } // we were sucessful so do an output
1103 } // got a valid map target
1104 } // got 2 variables
1105 } // we are adding a mapping
1106 } // got valid parameters
1107 }
1108
1109 //
1110 // free the command line package
1111 //
1112 ShellCommandLineFreeVarList (Package);
1113
1114 return (ShellStatus);
1115}
1116