]> git.proxmox.com Git - mirror_edk2.git/blame - ShellPkg/Library/UefiShellLevel2CommandsLib/Map.c
Verify memory allocations were successful.
[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
667 Status = gBS->LocateHandle(\r
668 ByProtocol,\r
669 &gEfiDevicePathProtocolGuid,\r
670 NULL,\r
671 &BufferSize,\r
672 HandleBuffer);\r
673 }\r
674 ASSERT_EFI_ERROR(Status);\r
675 ASSERT(HandleBuffer != NULL);\r
676\r
677 //\r
678 // Get the map name(s) for each one.\r
679 //\r
680 for ( LoopVar = 0\r
681 ; LoopVar < BufferSize / sizeof(EFI_HANDLE)\r
682 ; LoopVar ++\r
683 ){\r
684 if (PerformSingleMappingDelete(Specific,HandleBuffer[LoopVar]) == SHELL_SUCCESS) {\r
685 Deleted = TRUE;\r
686 }\r
687 }\r
688\r
689 //\r
690 // Look up all BlockIo in the platform\r
691 //\r
692 Status = gBS->LocateHandle(\r
693 ByProtocol,\r
694 &gEfiBlockIoProtocolGuid,\r
695 NULL,\r
696 &BufferSize,\r
697 HandleBuffer);\r
698 if (Status == EFI_BUFFER_TOO_SMALL) {\r
699 FreePool(HandleBuffer);\r
700 HandleBuffer = AllocatePool(BufferSize);\r
701 Status = gBS->LocateHandle(\r
702 ByProtocol,\r
703 &gEfiBlockIoProtocolGuid,\r
704 NULL,\r
705 &BufferSize,\r
706 HandleBuffer);\r
707 }\r
708 ASSERT_EFI_ERROR(Status);\r
709\r
710 //\r
711 // Get the map name(s) for each one.\r
712 //\r
713 for ( LoopVar = 0\r
714 ; LoopVar < BufferSize / sizeof(EFI_HANDLE)\r
715 ; LoopVar ++\r
716 ){\r
717 //\r
718 // Skip any that were already done...\r
719 //\r
720 if (gBS->OpenProtocol(\r
721 HandleBuffer[LoopVar],\r
722 &gEfiDevicePathProtocolGuid,\r
723 NULL,\r
724 gImageHandle,\r
725 NULL,\r
726 EFI_OPEN_PROTOCOL_TEST_PROTOCOL) == EFI_SUCCESS) {\r
727 continue;\r
728 }\r
729 if (PerformSingleMappingDelete(Specific,HandleBuffer[LoopVar]) == SHELL_SUCCESS) {\r
730 Deleted = TRUE;\r
731 }\r
732 }\r
733 FreePool(HandleBuffer);\r
734 if (!Deleted) {\r
735 return (EFI_NOT_FOUND);\r
736 }\r
737 return (EFI_SUCCESS);\r
738}\r
739\r
740/**\r
741 function to add a mapping from mapping.\r
742\r
743 This function will get the device path associated with the mapping and call SetMap.\r
744\r
745 @param[in] Map The Map to add a mapping for\r
746 @param[in] SName The name of the new mapping\r
747\r
748 @retval SHELL_SUCCESS the mapping was added\r
749 @retval SHELL_INVALID_PARAMETER the device path for Map could not be retrieved.\r
750 @return Shell version of a return value from EfiShellProtocol->SetMap\r
751\r
752**/\r
753SHELL_STATUS\r
754EFIAPI\r
755AddMappingFromMapping(\r
756 IN CONST CHAR16 *Map,\r
757 IN CONST CHAR16 *SName\r
758 )\r
759{\r
760 CONST EFI_DEVICE_PATH_PROTOCOL *DevPath;\r
761 EFI_STATUS Status;\r
762\r
763 if (StrStr(SName, L"*") != NULL\r
764 ||StrStr(SName, L"?") != NULL\r
765 ||StrStr(SName, L"[") != NULL\r
766 ||StrStr(SName, L"]") != NULL) {\r
767 return (SHELL_INVALID_PARAMETER);\r
768 }\r
769\r
770 DevPath = gEfiShellProtocol->GetDevicePathFromMap(Map);\r
771 if (DevPath == NULL) {\r
772 return (SHELL_INVALID_PARAMETER);\r
773 }\r
774\r
775 Status = gEfiShellProtocol->SetMap(DevPath, SName);\r
776 if (EFI_ERROR(Status)) {\r
777 return (SHELL_DEVICE_ERROR);\r
778 }\r
779 return (SHELL_SUCCESS);\r
780}\r
781\r
782/**\r
783 function to determine if a string has only numbers and letters\r
784\r
785 This is useful for such things as Map names which can only be letters and numbers\r
786\r
787 @param[in] String pointer to the string to analyze\r
788\r
789 @retval TRUE String has only numbers and letters\r
790 @retval FALSE String has at least one other character.\r
791**/\r
792BOOLEAN\r
793EFIAPI\r
794IsNumberLetterOnly(\r
795 IN CONST CHAR16 *String\r
796 )\r
797{\r
798 while(String != NULL && *String != CHAR_NULL) {\r
e9723321 799 if (! ((*String >= L'a' && *String <= L'z') ||\r
800 (*String >= L'A' && *String <= L'Z') ||\r
801 (*String >= L'0' && *String <= L'9'))\r
a405b86d 802 ){\r
803 return (FALSE);\r
804 }\r
805 String++;\r
806 }\r
807 return (TRUE);\r
808}\r
809\r
810/**\r
811 function to add a mapping from an EFI_HANDLE.\r
812\r
813 This function will get the device path associated with the Handle and call SetMap.\r
814\r
815 @param[in] Handle The handle to add a mapping for\r
816 @param[in] SName The name of the new mapping\r
817\r
818 @retval SHELL_SUCCESS the mapping was added\r
819 @retval SHELL_INVALID_PARAMETER SName was not valid for a map name.\r
820 @return Shell version of a return value from either\r
821 gBS->OpenProtocol or EfiShellProtocol->SetMap\r
822\r
823**/\r
824SHELL_STATUS\r
825EFIAPI\r
826AddMappingFromHandle(\r
827 IN CONST EFI_HANDLE Handle,\r
828 IN CONST CHAR16 *SName\r
829 )\r
830{\r
831 EFI_DEVICE_PATH_PROTOCOL *DevPath;\r
832 EFI_STATUS Status;\r
833\r
834 if (!IsNumberLetterOnly(SName)) {\r
835 return (SHELL_INVALID_PARAMETER);\r
836 }\r
837\r
838 Status = gBS->OpenProtocol(\r
839 Handle,\r
840 &gEfiDevicePathProtocolGuid,\r
841 (VOID**)&DevPath,\r
842 gImageHandle,\r
843 NULL,\r
844 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
845 );\r
846 if (EFI_ERROR(Status)) {\r
847 return (SHELL_DEVICE_ERROR);\r
848 }\r
849 Status = gEfiShellProtocol->SetMap(DevPath, SName);\r
850 if (EFI_ERROR(Status)) {\r
851 return (SHELL_DEVICE_ERROR);\r
852 }\r
853 return (SHELL_SUCCESS);\r
854}\r
855\r
856STATIC CONST SHELL_PARAM_ITEM MapParamList[] = {\r
857 {L"-d", TypeValue},\r
858 {L"-r", TypeFlag},\r
859 {L"-v", TypeFlag},\r
860 {L"-c", TypeFlag},\r
861 {L"-f", TypeFlag},\r
862 {L"-u", TypeFlag},\r
863 {L"-t", TypeValue},\r
864 {L"-sfo", TypeValue},\r
865 {NULL, TypeMax}\r
866 };\r
867\r
868/**\r
869 Function for 'map' command.\r
870\r
871 @param[in] ImageHandle Handle to the Image (NULL if Internal).\r
872 @param[in] SystemTable Pointer to the System Table (NULL if Internal).\r
873**/\r
874SHELL_STATUS\r
875EFIAPI\r
876ShellCommandRunMap (\r
877 IN EFI_HANDLE ImageHandle,\r
878 IN EFI_SYSTEM_TABLE *SystemTable\r
879 )\r
880{\r
881 EFI_STATUS Status;\r
882 LIST_ENTRY *Package;\r
883 CHAR16 *ProblemParam;\r
884 CONST CHAR16 *SName;\r
885 CONST CHAR16 *Mapping;\r
886 EFI_HANDLE MappingAsHandle;\r
887 CONST EFI_DEVICE_PATH_PROTOCOL *DevPath;\r
888 SHELL_STATUS ShellStatus;\r
889 BOOLEAN SfoMode;\r
890 BOOLEAN ConstMode;\r
891 BOOLEAN NormlMode;\r
892 CONST CHAR16 *Param1;\r
893 CONST CHAR16 *TypeString;\r
894\r
895 ProblemParam = NULL;\r
896 Mapping = NULL;\r
897 SName = NULL;\r
898 DevPath = NULL;\r
899 ShellStatus = SHELL_SUCCESS;\r
900 MappingAsHandle = NULL;\r
901\r
902 //\r
903 // initialize the shell lib (we must be in non-auto-init...)\r
904 //\r
905 Status = ShellInitialize();\r
906 ASSERT_EFI_ERROR(Status);\r
907\r
908 Status = CommandInit();\r
909 ASSERT_EFI_ERROR(Status);\r
910\r
911 //\r
912 // parse the command line\r
913 //\r
914 Status = ShellCommandLineParse (MapParamList, &Package, &ProblemParam, TRUE);\r
915 if (EFI_ERROR(Status)) {\r
916 if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {\r
917 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel2HiiHandle, ProblemParam);\r
918 FreePool(ProblemParam);\r
919 ShellStatus = SHELL_INVALID_PARAMETER;\r
920 } else {\r
921 ASSERT(FALSE);\r
922 }\r
923 } else {\r
924 //\r
925 // check for "-?"\r
926 //\r
927 SfoMode = ShellCommandLineGetFlag(Package, L"-sfo");\r
928 ConstMode = ShellCommandLineGetFlag(Package, L"-c");\r
929 NormlMode = ShellCommandLineGetFlag(Package, L"-f");\r
930 if (ShellCommandLineGetFlag(Package, L"-?")) {\r
931 ASSERT(FALSE);\r
932 } else if (ShellCommandLineGetRawValue(Package, 3) != NULL) {\r
933 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel2HiiHandle);\r
934 ShellStatus = SHELL_INVALID_PARAMETER;\r
935 } else {\r
936 //\r
937 // Deleting a map name...\r
938 //\r
939 if (ShellCommandLineGetFlag(Package, L"-d")) {\r
940 if ( ShellCommandLineGetFlag(Package, L"-r")\r
941 || ShellCommandLineGetFlag(Package, L"-v")\r
942 || ConstMode\r
943 || NormlMode\r
944 || ShellCommandLineGetFlag(Package, L"-u")\r
945 || ShellCommandLineGetFlag(Package, L"-t")\r
946 ){\r
947 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_CON), gShellLevel2HiiHandle);\r
948 ShellStatus = SHELL_INVALID_PARAMETER;\r
949 } else {\r
950 SName = ShellCommandLineGetValue(Package, L"-d");\r
951 if (SName != NULL) {\r
952 Status = PerformMappingDelete(SName);\r
953 if (EFI_ERROR(Status)) {\r
954 switch (Status) {\r
955 case EFI_ACCESS_DENIED:\r
956 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_AD), gShellLevel2HiiHandle);\r
957 ShellStatus = SHELL_ACCESS_DENIED;\r
958 break;\r
959 case EFI_NOT_FOUND:\r
960 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MAP_NF), gShellLevel2HiiHandle, SName);\r
961 ShellStatus = SHELL_INVALID_PARAMETER;\r
962 break;\r
963 default:\r
964 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_UK), gShellLevel2HiiHandle, Status);\r
965 ShellStatus = SHELL_UNSUPPORTED;\r
966 }\r
967 }\r
968 } else {\r
969 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellLevel2HiiHandle);\r
970 ShellStatus = SHELL_INVALID_PARAMETER;\r
971 }\r
972 }\r
973 } else if ( ShellCommandLineGetFlag(Package, L"-r")\r
974// || ShellCommandLineGetFlag(Package, L"-v")\r
975 || ConstMode\r
976 || NormlMode\r
977 || ShellCommandLineGetFlag(Package, L"-u")\r
978 || ShellCommandLineGetFlag(Package, L"-t")\r
979 ){\r
980 if ( ShellCommandLineGetFlag(Package, L"-r")) {\r
981 //\r
982 // Do the reset\r
983 //\r
984 Status = ShellCommandCreateInitialMappingsAndPaths();\r
985 if (EFI_ERROR(Status)) {\r
986 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_UK), gShellLevel2HiiHandle, Status);\r
987 ShellStatus = SHELL_UNSUPPORTED;\r
988 }\r
989 }\r
990 if ( ShellStatus == SHELL_SUCCESS && ShellCommandLineGetFlag(Package, L"-u")) {\r
991 //\r
992 // Do the Update\r
993 //\r
994 Status = UpdateMapping();\r
995 if (EFI_ERROR(Status)) {\r
996 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_UK), gShellLevel2HiiHandle, Status);\r
997 ShellStatus = SHELL_UNSUPPORTED;\r
998 }\r
999 }\r
1000 if (ShellStatus == SHELL_SUCCESS) {\r
1001 Param1 = ShellCommandLineGetRawValue(Package, 1);\r
1002 TypeString = ShellCommandLineGetValue(Package, L"-t");\r
1003 if (!ConstMode\r
1004 &&!NormlMode\r
1005 &&TypeString == NULL\r
1006 ) {\r
1007 //\r
1008 // now do the display...\r
1009 //\r
1010 ShellStatus = PerformMappingDisplay(\r
1011 ShellCommandLineGetFlag(Package, L"-v"),\r
1012 TRUE,\r
1013 TRUE,\r
1014 NULL,\r
1015 SfoMode,\r
1016 Param1,\r
1017 TRUE\r
1018 );\r
1019 } else {\r
1020 //\r
1021 // now do the display...\r
1022 //\r
1023 ShellStatus = PerformMappingDisplay2(\r
1024 ShellCommandLineGetFlag(Package, L"-v"),\r
1025 ConstMode,\r
1026 NormlMode,\r
1027 TypeString,\r
1028 SfoMode,\r
1029 Param1\r
1030 );\r
1031 }\r
1032 }\r
1033 } else {\r
1034 //\r
1035 // adding or displaying (there were no flags)\r
1036 //\r
1037 SName = ShellCommandLineGetRawValue(Package, 1);\r
1038 Mapping = ShellCommandLineGetRawValue(Package, 2);\r
1039 if ( SName == NULL\r
1040 && Mapping == NULL\r
1041 ){\r
1042 //\r
1043 // display only since no flags\r
1044 //\r
1045 ShellStatus = PerformMappingDisplay(\r
1046 ShellCommandLineGetFlag(Package, L"-v"),\r
1047 TRUE,\r
1048 TRUE,\r
1049 NULL,\r
1050 SfoMode,\r
1051 NULL,\r
1052 TRUE\r
1053 );\r
1054 } else if ( SName == NULL\r
1055 || Mapping == NULL\r
1056 ){\r
1057 //\r
1058 // Display only the one specified\r
1059 //\r
1060 ShellStatus = PerformMappingDisplay(\r
1061 FALSE,\r
1062 FALSE,\r
1063 FALSE,\r
1064 NULL,\r
1065 SfoMode,\r
1066 SName, // note the variable here...\r
1067 TRUE\r
1068 );\r
1069 } else {\r
1070 if (ShellIsHexOrDecimalNumber(Mapping, TRUE, FALSE)) {\r
1071 MappingAsHandle = ConvertHandleIndexToHandle(StrHexToUintn(Mapping));\r
1072 } else {\r
1073 MappingAsHandle = NULL;\r
1074 }\r
1075 if (MappingAsHandle == NULL && Mapping[StrLen(Mapping)-1] != L':') {\r
1076 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel2HiiHandle, Mapping);\r
1077 ShellStatus = SHELL_INVALID_PARAMETER;\r
1078 } else {\r
1079 if (MappingAsHandle != NULL) {\r
1080 ShellStatus = AddMappingFromHandle(MappingAsHandle, SName);\r
1081 } else {\r
1082 ShellStatus = AddMappingFromMapping(Mapping, SName);\r
1083 }\r
1084 if (ShellStatus != SHELL_SUCCESS) {\r
1085 switch (ShellStatus) {\r
1086 case SHELL_ACCESS_DENIED:\r
1087 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_AD), gShellLevel2HiiHandle);\r
1088 break;\r
1089 case SHELL_INVALID_PARAMETER:\r
1090 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellLevel2HiiHandle);\r
1091 break;\r
1092 default:\r
1093 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_UK), gShellLevel2HiiHandle, ShellStatus|MAX_BIT);\r
1094 }\r
1095 } else {\r
1096 //\r
1097 // now do the display...\r
1098 //\r
1099 ShellStatus = PerformMappingDisplay(\r
1100 FALSE,\r
1101 FALSE,\r
1102 FALSE,\r
1103 NULL,\r
1104 SfoMode,\r
1105 SName,\r
1106 TRUE\r
1107 );\r
1108 } // we were sucessful so do an output\r
1109 } // got a valid map target\r
1110 } // got 2 variables\r
1111 } // we are adding a mapping\r
1112 } // got valid parameters\r
1113 }\r
1114\r
1115 //\r
1116 // free the command line package\r
1117 //\r
1118 ShellCommandLineFreeVarList (Package);\r
1119\r
1120 return (ShellStatus);\r
1121}\r
1122\r