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