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