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