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