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