]> git.proxmox.com Git - mirror_edk2.git/blame - EmbeddedPkg/Ebl/EfiDevice.c
ARM Packages: Removed trailing spaces
[mirror_edk2.git] / EmbeddedPkg / Ebl / EfiDevice.c
CommitLineData
2ef2b01e
A
1/** @file\r
2 EBL commands for EFI and PI Devices\r
3\r
60274cca
HT
4 Copyright (c) 2007, Intel Corporation. All rights reserved.<BR>\r
5 Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>\r
2ef2b01e 6\r
60274cca 7 This program and the accompanying materials\r
2ef2b01e
A
8 are licensed and made available under the terms and conditions of the BSD License\r
9 which accompanies this distribution. The full text of the license may be found at\r
10 http://opensource.org/licenses/bsd-license.php\r
11\r
12 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
13 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
14\r
15**/\r
16\r
17#include "Ebl.h"\r
18\r
19\r
20EFI_DXE_SERVICES *gDS = NULL;\r
21\r
22\r
23/**\r
24 Print information about the File System device.\r
25\r
26 @param File Open File for the device\r
27\r
28**/\r
29VOID\r
30EblPrintFsInfo (\r
31 IN EFI_OPEN_FILE *File\r
32 )\r
33{\r
638909f1 34 CHAR16 *Str;\r
35\r
2ef2b01e
A
36 if (File == NULL) {\r
37 return;\r
38 }\r
39\r
40 AsciiPrint (" %a: ", File->DeviceName);\r
41 if (File->FsInfo != NULL) {\r
638909f1 42 for (Str = File->FsInfo->VolumeLabel; *Str != '\0'; Str++) {\r
43 if (*Str == ' ') {\r
44 // UI makes you enter _ for space, so make the printout match that\r
45 *Str = '_';\r
46 }\r
47 AsciiPrint ("%c", *Str);\r
48 }\r
49 AsciiPrint (":");\r
2ef2b01e
A
50 if (File->FsInfo->ReadOnly) {\r
51 AsciiPrint ("ReadOnly");\r
52 }\r
53 }\r
54\r
55 AsciiPrint ("\n");\r
56 EfiClose (File);\r
57}\r
58\r
59\r
60/**\r
61 Print information about the FV devices.\r
62\r
63 @param File Open File for the device\r
64\r
65**/\r
66VOID\r
67EblPrintFvbInfo (\r
68 IN EFI_OPEN_FILE *File\r
69 )\r
70{\r
71 if (File == NULL) {\r
72 return;\r
73 }\r
74\r
75 AsciiPrint (" %a: 0x%08lx - 0x%08lx : 0x%08x\n", File->DeviceName, File->FvStart, File->FvStart + File->FvSize - 1, File->FvSize);\r
76 EfiClose (File);\r
77}\r
78\r
79\r
80/**\r
81 Print information about the Blk IO devices.\r
82 If the device supports PXE dump out extra information\r
83\r
84 @param File Open File for the device\r
85\r
86**/\r
87VOID\r
88EblPrintBlkIoInfo (\r
89 IN EFI_OPEN_FILE *File\r
90 )\r
91{\r
92 UINT64 DeviceSize;\r
6f72e28d 93 UINTN Index;\r
94 UINTN Max;\r
95 EFI_OPEN_FILE *FsFile;\r
2ef2b01e
A
96\r
97 if (File == NULL) {\r
98 return;\r
99 }\r
100\r
101 AsciiPrint (" %a: ", File->DeviceName);\r
6f72e28d 102\r
103 // print out name of file system, if any, on this block device\r
104 Max = EfiGetDeviceCounts (EfiOpenFileSystem);\r
105 if (Max != 0) {\r
106 for (Index = 0; Index < Max; Index++) {\r
107 FsFile = EfiDeviceOpenByType (EfiOpenFileSystem, Index);\r
108 if (FsFile != NULL) {\r
109 if (FsFile->EfiHandle == File->EfiHandle) {\r
110 AsciiPrint ("fs%d: ", Index);\r
111 EfiClose (FsFile);\r
112 break;\r
113 }\r
0a0951ea 114 EfiClose (FsFile);\r
6f72e28d 115 }\r
6f72e28d 116 }\r
117 }\r
118\r
119 // Print out useful Block IO media properties\r
0a0951ea 120 if (File->FsBlockIoMedia->RemovableMedia) {\r
2ef2b01e
A
121 AsciiPrint ("Removable ");\r
122 }\r
0a0951ea 123 if (!File->FsBlockIoMedia->MediaPresent) {\r
124 AsciiPrint ("No Media\n");\r
125 } else {\r
126 if (File->FsBlockIoMedia->LogicalPartition) {\r
127 AsciiPrint ("Partition ");\r
128 }\r
129 DeviceSize = MultU64x32 (File->FsBlockIoMedia->LastBlock + 1, File->FsBlockIoMedia->BlockSize);\r
130 AsciiPrint ("Size = 0x%lX\n", DeviceSize);\r
2ef2b01e 131 }\r
2ef2b01e
A
132 EfiClose (File);\r
133}\r
134\r
2ef2b01e
A
135 /**\r
136 Print information about the Load File devices.\r
137 If the device supports PXE dump out extra information\r
138\r
139 @param File Open File for the device\r
140\r
141**/\r
142VOID\r
143EblPrintLoadFileInfo (\r
144 IN EFI_OPEN_FILE *File\r
145 )\r
146{\r
147 EFI_DEVICE_PATH_PROTOCOL *DevicePathNode;\r
148 MAC_ADDR_DEVICE_PATH *MacAddr;\r
149 UINTN HwAddressSize;\r
150 UINTN Index;\r
151\r
152 if (File == NULL) {\r
153 return;\r
154 }\r
155\r
156 AsciiPrint (" %a: %a ", File->DeviceName, EblLoadFileBootTypeString (File->EfiHandle));\r
157\r
158 if (File->DevicePath != NULL) {\r
159 // Try to print out the MAC address\r
3402aac7
RC
160 for (DevicePathNode = File->DevicePath;\r
161 !IsDevicePathEnd (DevicePathNode);\r
2ef2b01e 162 DevicePathNode = NextDevicePathNode (DevicePathNode)) {\r
3402aac7 163\r
2ef2b01e
A
164 if ((DevicePathType (DevicePathNode) == MESSAGING_DEVICE_PATH) && (DevicePathSubType (DevicePathNode) == MSG_MAC_ADDR_DP)) {\r
165 MacAddr = (MAC_ADDR_DEVICE_PATH *)DevicePathNode;\r
3402aac7 166\r
2ef2b01e
A
167 HwAddressSize = sizeof (EFI_MAC_ADDRESS);\r
168 if (MacAddr->IfType == 0x01 || MacAddr->IfType == 0x00) {\r
169 HwAddressSize = 6;\r
170 }\r
3402aac7 171\r
2ef2b01e
A
172 AsciiPrint ("MAC ");\r
173 for (Index = 0; Index < HwAddressSize; Index++) {\r
174 AsciiPrint ("%02x", MacAddr->MacAddress.Addr[Index] & 0xff);\r
175 }\r
3402aac7 176 }\r
2ef2b01e
A
177 }\r
178 }\r
179\r
180 AsciiPrint ("\n");\r
181 EfiClose (File);\r
182 return;\r
183}\r
184\r
185\r
186\r
187/**\r
3402aac7 188 Dump information about devices in the system.\r
2ef2b01e
A
189\r
190 fv: PI Firmware Volume\r
191 fs: EFI Simple File System\r
192 blk: EFI Block IO\r
193 LoadFile: EFI Load File Protocol (commonly PXE network boot)\r
194\r
195 Argv[0] - "device"\r
196\r
197 @param Argc Number of command arguments in Argv\r
3402aac7 198 @param Argv Array of strings that represent the parsed command line.\r
7ca9e5a4 199 Argv[0] is the command name\r
2ef2b01e
A
200\r
201 @return EFI_SUCCESS\r
202\r
203**/\r
204EFI_STATUS\r
205EblDeviceCmd (\r
206 IN UINTN Argc,\r
207 IN CHAR8 **Argv\r
208 )\r
209{\r
210 UINTN Index;\r
211 UINTN CurrentRow;\r
212 UINTN Max;\r
213\r
214 CurrentRow = 0;\r
208a8330 215\r
2ef2b01e
A
216 // Need to call here to make sure Device Counts are valid\r
217 EblUpdateDeviceLists ();\r
218\r
f6381f4c 219 // Now we can print out the info...\r
2ef2b01e
A
220 Max = EfiGetDeviceCounts (EfiOpenFirmwareVolume);\r
221 if (Max != 0) {\r
222 AsciiPrint ("Firmware Volume Devices:\n");\r
223 for (Index = 0; Index < Max; Index++) {\r
224 EblPrintFvbInfo (EfiDeviceOpenByType (EfiOpenFirmwareVolume, Index));\r
225 if (EblAnyKeyToContinueQtoQuit (&CurrentRow, TRUE)) {\r
226 break;\r
227 }\r
228 }\r
229 }\r
230\r
231 Max = EfiGetDeviceCounts (EfiOpenFileSystem);\r
232 if (Max != 0) {\r
233 AsciiPrint ("File System Devices:\n");\r
234 for (Index = 0; Index < Max; Index++) {\r
235 EblPrintFsInfo (EfiDeviceOpenByType (EfiOpenFileSystem, Index));\r
236 if (EblAnyKeyToContinueQtoQuit (&CurrentRow, TRUE)) {\r
237 break;\r
238 }\r
239 }\r
240 }\r
241\r
242 Max = EfiGetDeviceCounts (EfiOpenBlockIo);\r
243 if (Max != 0) {\r
244 AsciiPrint ("Block IO Devices:\n");\r
245 for (Index = 0; Index < Max; Index++) {\r
246 EblPrintBlkIoInfo (EfiDeviceOpenByType (EfiOpenBlockIo, Index));\r
247 if (EblAnyKeyToContinueQtoQuit (&CurrentRow, TRUE)) {\r
248 break;\r
249 }\r
250 }\r
251 }\r
3402aac7 252\r
2ef2b01e
A
253 Max = EfiGetDeviceCounts (EfiOpenLoadFile);\r
254 if (Max != 0) {\r
255 AsciiPrint ("LoadFile Devices: (usually network)\n");\r
256 for (Index = 0; Index < Max; Index++) {\r
257 EblPrintLoadFileInfo (EfiDeviceOpenByType (EfiOpenLoadFile, Index));\r
258 if (EblAnyKeyToContinueQtoQuit (&CurrentRow, TRUE)) {\r
259 break;\r
260 }\r
261 }\r
262 }\r
263\r
264 return EFI_SUCCESS;\r
265}\r
266\r
267\r
268/**\r
3402aac7 269 Start an EFI image (PE32+ with EFI defined entry point).\r
2ef2b01e
A
270\r
271 Argv[0] - "start"\r
272 Argv[1] - device name and path\r
273 Argv[2] - "" string to pass into image being started\r
274\r
275 start fs1:\Temp\Fv.Fv "arg to pass" ; load an FV from the disk and pass the\r
276 ; ascii string arg to pass to the image\r
277 start fv0:\FV ; load an FV from an FV (not common)\r
278 start LoadFile0: ; load an FV via a PXE boot\r
279\r
280 @param Argc Number of command arguments in Argv\r
3402aac7 281 @param Argv Array of strings that represent the parsed command line.\r
7ca9e5a4 282 Argv[0] is the command name\r
2ef2b01e
A
283\r
284 @return EFI_SUCCESS\r
285\r
286**/\r
287EFI_STATUS\r
288EblStartCmd (\r
289 IN UINTN Argc,\r
290 IN CHAR8 **Argv\r
291 )\r
292{\r
293 EFI_STATUS Status;\r
294 EFI_OPEN_FILE *File;\r
295 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
296 EFI_HANDLE ImageHandle;\r
297 UINTN ExitDataSize;\r
298 CHAR16 *ExitData;\r
299 VOID *Buffer;\r
300 UINTN BufferSize;\r
301 EFI_LOADED_IMAGE_PROTOCOL *ImageInfo;\r
302\r
303 ImageHandle = NULL;\r
304\r
305 if (Argc < 2) {\r
306 return EFI_INVALID_PARAMETER;\r
307 }\r
308\r
309 File = EfiOpen (Argv[1], EFI_FILE_MODE_READ, 0);\r
310 if (File == NULL) {\r
3402aac7 311 return EFI_INVALID_PARAMETER;\r
2ef2b01e
A
312 }\r
313\r
314 DevicePath = File->DevicePath;\r
315 if (DevicePath != NULL) {\r
316 // check for device path form: blk, fv, fs, and loadfile\r
317 Status = gBS->LoadImage (FALSE, gImageHandle, DevicePath, NULL, 0, &ImageHandle);\r
318 } else {\r
319 // Check for buffer form: A0x12345678:0x1234 syntax.\r
320 // Means load using buffer starting at 0x12345678 of size 0x1234.\r
321\r
322 Status = EfiReadAllocatePool (File, &Buffer, &BufferSize);\r
323 if (EFI_ERROR (Status)) {\r
324 EfiClose (File);\r
325 return Status;\r
326 }\r
327 Status = gBS->LoadImage (FALSE, gImageHandle, DevicePath, Buffer, BufferSize, &ImageHandle);\r
328\r
329 FreePool (Buffer);\r
330 }\r
3402aac7 331\r
2ef2b01e
A
332 EfiClose (File);\r
333\r
334 if (!EFI_ERROR (Status)) {\r
335 if (Argc >= 3) {\r
336 // Argv[2] is a "" string that we pass directly to the EFI application without the ""\r
337 // We don't pass Argv[0] to the EFI Application (it's name) just the args\r
338 Status = gBS->HandleProtocol (ImageHandle, &gEfiLoadedImageProtocolGuid, (VOID **)&ImageInfo);\r
339 ASSERT_EFI_ERROR (Status);\r
3402aac7 340\r
2ef2b01e
A
341 ImageInfo->LoadOptionsSize = (UINT32)AsciiStrSize (Argv[2]);\r
342 ImageInfo->LoadOptions = AllocatePool (ImageInfo->LoadOptionsSize);\r
343 AsciiStrCpy (ImageInfo->LoadOptions, Argv[2]);\r
344 }\r
345\r
346 // Transfer control to the EFI image we loaded with LoadImage()\r
347 Status = gBS->StartImage (ImageHandle, &ExitDataSize, &ExitData);\r
348 }\r
349\r
350 return Status;\r
351}\r
352\r
353\r
354/**\r
355 Load a Firmware Volume (FV) into memory from a device. This causes drivers in\r
7ca9e5a4 356 the FV to be dispatched if the dependencies of the drivers are met.\r
3402aac7 357\r
2ef2b01e
A
358 Argv[0] - "loadfv"\r
359 Argv[1] - device name and path\r
360\r
361 loadfv fs1:\Temp\Fv.Fv ; load an FV from the disk\r
362 loadfv fv0:\FV ; load an FV from an FV (not common)\r
363 loadfv LoadFile0: ; load an FV via a PXE boot\r
364\r
365 @param Argc Number of command arguments in Argv\r
3402aac7 366 @param Argv Array of strings that represent the parsed command line.\r
7ca9e5a4 367 Argv[0] is the command name\r
2ef2b01e
A
368\r
369 @return EFI_SUCCESS\r
370\r
371**/\r
372EFI_STATUS\r
373EblLoadFvCmd (\r
374 IN UINTN Argc,\r
375 IN CHAR8 **Argv\r
376 )\r
377{\r
378 EFI_STATUS Status;\r
379 EFI_OPEN_FILE *File;\r
380 VOID *FvStart;\r
381 UINTN FvSize;\r
382 EFI_HANDLE FvHandle;\r
383\r
384\r
385 if (Argc < 2) {\r
386 return EFI_INVALID_PARAMETER;\r
387 }\r
388\r
389 File = EfiOpen (Argv[1], EFI_FILE_MODE_READ, 0);\r
390 if (File == NULL) {\r
3402aac7 391 return EFI_INVALID_PARAMETER;\r
2ef2b01e
A
392 }\r
393\r
394 if (File->Type == EfiOpenMemoryBuffer) {\r
395 // If it is a address just use it.\r
396 Status = gDS->ProcessFirmwareVolume (File->Buffer, File->Size, &FvHandle);\r
397 } else {\r
398 // If it is a file read it into memory and use it\r
399 Status = EfiReadAllocatePool (File, &FvStart, &FvSize);\r
400 EfiClose (File);\r
401 if (EFI_ERROR (Status)) {\r
402 return Status;\r
403 }\r
3402aac7 404\r
2ef2b01e 405 Status = gDS->ProcessFirmwareVolume (FvStart, FvSize, &FvHandle);\r
abeca79a 406 if (EFI_ERROR (Status)) {\r
407 FreePool (FvStart);\r
3402aac7 408 }\r
2ef2b01e
A
409 }\r
410 return Status;\r
411}\r
412\r
413\r
414/**\r
3402aac7 415 Perform an EFI connect to connect devices that follow the EFI driver model.\r
2ef2b01e 416 If it is a PI system also call the dispatcher in case a new FV was made\r
7ca9e5a4 417 available by one of the connect EFI drivers (this is not a common case).\r
3402aac7 418\r
2ef2b01e
A
419 Argv[0] - "connect"\r
420\r
421 @param Argc Number of command arguments in Argv\r
3402aac7 422 @param Argv Array of strings that represent the parsed command line.\r
7ca9e5a4 423 Argv[0] is the command name\r
2ef2b01e
A
424\r
425 @return EFI_SUCCESS\r
426\r
427**/\r
428EFI_STATUS\r
429EblConnectCmd (\r
430 IN UINTN Argc,\r
431 IN CHAR8 **Argv\r
432 )\r
433{\r
434 EFI_STATUS Status;\r
435 UINTN HandleCount;\r
436 EFI_HANDLE *HandleBuffer;\r
437 UINTN Index;\r
438 BOOLEAN Dispatch;\r
439 EFI_OPEN_FILE *File;\r
440\r
441\r
442 if (Argc > 1) {\r
443 if ((*Argv[1] == 'd') || (*Argv[1] == 'D')) {\r
444 Status = gBS->LocateHandleBuffer (\r
445 AllHandles,\r
446 NULL,\r
447 NULL,\r
448 &HandleCount,\r
449 &HandleBuffer\r
450 );\r
451 if (EFI_ERROR (Status)) {\r
452 return Status;\r
453 }\r
3402aac7 454\r
2ef2b01e
A
455 for (Index = 0; Index < HandleCount; Index++) {\r
456 gBS->DisconnectController (HandleBuffer[Index], NULL, NULL);\r
457 }\r
3402aac7 458\r
2ef2b01e
A
459 //\r
460 // Given we disconnect our console we should go and do a connect now\r
461 //\r
462 } else {\r
463 File = EfiOpen (Argv[1], EFI_FILE_MODE_READ, 0);\r
464 if (File != NULL) {\r
465 AsciiPrint ("Connecting %a\n", Argv[1]);\r
466 gBS->ConnectController (File->EfiHandle, NULL, NULL, TRUE);\r
467 EfiClose (File);\r
468 return EFI_SUCCESS;\r
469 }\r
470 }\r
471 }\r
472\r
473 Dispatch = FALSE;\r
474 do {\r
475 Status = gBS->LocateHandleBuffer (\r
476 AllHandles,\r
477 NULL,\r
478 NULL,\r
479 &HandleCount,\r
480 &HandleBuffer\r
481 );\r
482 if (EFI_ERROR (Status)) {\r
483 return Status;\r
484 }\r
485\r
486 for (Index = 0; Index < HandleCount; Index++) {\r
487 gBS->ConnectController (HandleBuffer[Index], NULL, NULL, TRUE);\r
488 }\r
489\r
490 FreePool (HandleBuffer);\r
491\r
492 //\r
493 // Check to see if it's possible to dispatch an more DXE drivers.\r
494 // The BdsLibConnectAllEfi () may have made new DXE drivers show up.\r
495 // If anything is Dispatched Status == EFI_SUCCESS and we will try\r
496 // the connect again.\r
497 //\r
498 if (gDS == NULL) {\r
499 Status = EFI_NOT_FOUND;\r
500 } else {\r
501 Status = gDS->Dispatch ();\r
502 if (!EFI_ERROR (Status)) {\r
503 Dispatch = TRUE;\r
504 }\r
505 }\r
506\r
507 } while (!EFI_ERROR (Status));\r
508\r
509 if (Dispatch) {\r
510 AsciiPrint ("Connected and dispatched\n");\r
511 } else {\r
512 AsciiPrint ("Connect\n");\r
513 }\r
514\r
515 return EFI_SUCCESS;\r
516}\r
517\r
518\r
519\r
520CHAR8 *gMemMapType[] = {\r
521 "reserved ",\r
522 "LoaderCode",\r
523 "LoaderData",\r
524 "BS_code ",\r
525 "BS_data ",\r
526 "RT_code ",\r
527 "RT_data ",\r
528 "available ",\r
529 "Unusable ",\r
530 "ACPI_recl ",\r
531 "ACPI_NVS ",\r
532 "MemMapIO ",\r
533 "MemPortIO ",\r
534 "PAL_code "\r
535};\r
536\r
537\r
538/**\r
539 Dump out the EFI memory map\r
3402aac7 540\r
2ef2b01e
A
541 Argv[0] - "memmap"\r
542\r
543 @param Argc Number of command arguments in Argv\r
3402aac7 544 @param Argv Array of strings that represent the parsed command line.\r
7ca9e5a4 545 Argv[0] is the command name\r
2ef2b01e
A
546\r
547 @return EFI_SUCCESS\r
548\r
549**/\r
550EFI_STATUS\r
551EblMemMapCmd (\r
552 IN UINTN Argc,\r
553 IN CHAR8 **Argv\r
554 )\r
555{\r
556 EFI_STATUS Status;\r
557 EFI_MEMORY_DESCRIPTOR *MemMap;\r
558 EFI_MEMORY_DESCRIPTOR *OrigMemMap;\r
559 UINTN MemMapSize;\r
560 UINTN MapKey;\r
561 UINTN DescriptorSize;\r
562 UINT32 DescriptorVersion;\r
563 UINT64 PageCount[EfiMaxMemoryType];\r
564 UINTN Index;\r
565 UINT64 EntrySize;\r
566 UINTN CurrentRow;\r
567 UINT64 TotalMemory;\r
568\r
569 ZeroMem (PageCount, sizeof (PageCount));\r
570\r
571 AsciiPrint ("EFI Memory Map\n");\r
3402aac7 572\r
2ef2b01e
A
573 // First call is to figure out how big the buffer needs to be\r
574 MemMapSize = 0;\r
575 MemMap = NULL;\r
576 Status = gBS->GetMemoryMap (&MemMapSize, MemMap, &MapKey, &DescriptorSize, &DescriptorVersion);\r
577 if (Status == EFI_BUFFER_TOO_SMALL) {\r
578 // In case the AllocatPool changes the memory map we added in some extra descriptors\r
579 MemMapSize += (DescriptorSize * 0x100);\r
580 OrigMemMap = MemMap = AllocatePool (MemMapSize);\r
581 if (OrigMemMap != NULL) {\r
582 // 2nd time we get the data\r
583 Status = gBS->GetMemoryMap (&MemMapSize, MemMap, &MapKey, &DescriptorSize, &DescriptorVersion);\r
584 if (!EFI_ERROR (Status)) {\r
585 for (Index = 0, CurrentRow = 0; Index < MemMapSize/DescriptorSize; Index++) {\r
586 EntrySize = LShiftU64 (MemMap->NumberOfPages, 12);\r
587 AsciiPrint ("\n%a %016lx - %016lx: # %08lx %016lx", gMemMapType[MemMap->Type % EfiMaxMemoryType], MemMap->PhysicalStart, MemMap->PhysicalStart + EntrySize -1, MemMap->NumberOfPages, MemMap->Attribute);\r
588 if (EblAnyKeyToContinueQtoQuit (&CurrentRow, TRUE)) {\r
589 break;\r
590 }\r
591\r
592 PageCount[MemMap->Type % EfiMaxMemoryType] += MemMap->NumberOfPages;\r
593 MemMap = NEXT_MEMORY_DESCRIPTOR (MemMap, DescriptorSize);\r
594 }\r
595 }\r
3402aac7 596\r
2ef2b01e
A
597 for (Index = 0, TotalMemory = 0; Index < EfiMaxMemoryType; Index++) {\r
598 if (PageCount[Index] != 0) {\r
599 AsciiPrint ("\n %a %,7ld Pages (%,14ld)", gMemMapType[Index], PageCount[Index], LShiftU64 (PageCount[Index], 12));\r
600 if (Index == EfiLoaderCode ||\r
601 Index == EfiLoaderData ||\r
602 Index == EfiBootServicesCode ||\r
603 Index == EfiBootServicesData ||\r
604 Index == EfiRuntimeServicesCode ||\r
605 Index == EfiRuntimeServicesData ||\r
606 Index == EfiConventionalMemory ||\r
607 Index == EfiACPIReclaimMemory ||\r
608 Index == EfiACPIMemoryNVS ||\r
609 Index == EfiPalCode\r
610 ) {\r
611 // Count total memory\r
612 TotalMemory += PageCount[Index];\r
613 }\r
614 }\r
615 }\r
616\r
617 AsciiPrint ("\nTotal Memory: %,ld MB (%,ld bytes)\n", RShiftU64 (TotalMemory, 8), LShiftU64 (TotalMemory, 12));\r
618\r
619 FreePool (OrigMemMap);\r
620\r
621 }\r
622 }\r
623\r
624 return EFI_SUCCESS;\r
625}\r
626\r
627\r
628\r
629\r
630/**\r
7ca9e5a4 631 Load a file into memory and optionally jump to it. A load address can be\r
2ef2b01e 632 specified or automatically allocated. A quoted command line can optionally\r
3402aac7 633 be passed into the image.\r
2ef2b01e
A
634\r
635 Argv[0] - "go"\r
636 Argv[1] - Device Name:path for the file to load\r
637 Argv[2] - Address to load to or '*' if the load address will be allocated\r
638 Argv[3] - Optional Entry point to the image. Image will be called if present\r
3402aac7 639 Argv[4] - "" string that will be passed as Argc & Argv to EntryPoint. Needs\r
2ef2b01e
A
640 to include the command name\r
641\r
3402aac7
RC
642 go fv1:\EblCmdX 0x10000 0x10010 "EblCmdX Arg2 Arg3 Arg4"; - load EblCmdX\r
643 from FV1 to location 0x10000 and call the entry point at 0x10010 passing\r
2ef2b01e
A
644 in "EblCmdX Arg2 Arg3 Arg4" as the arguments.\r
645\r
3402aac7 646 go fv0:\EblCmdX * 0x10 "EblCmdX Arg2 Arg3 Arg4"; - load EblCmdX from FS0\r
7ca9e5a4 647 to location allocated by this command and call the entry point at offset 0x10\r
2ef2b01e
A
648 passing in "EblCmdX Arg2 Arg3 Arg4" as the arguments.\r
649\r
650 go fv1:\EblCmdX 0x10000; Load EblCmdX to address 0x10000 and return\r
651\r
652 @param Argc Number of command arguments in Argv\r
3402aac7 653 @param Argv Array of strings that represent the parsed command line.\r
7ca9e5a4 654 Argv[0] is the command name\r
2ef2b01e
A
655\r
656 @return EFI_SUCCESS\r
657\r
658**/\r
659EFI_STATUS\r
660EblGoCmd (\r
661 IN UINTN Argc,\r
662 IN CHAR8 **Argv\r
663 )\r
664{\r
665 EFI_STATUS Status;\r
666 EFI_OPEN_FILE *File;\r
667 VOID *Address;\r
668 UINTN Size;\r
669 EBL_COMMMAND EntryPoint;\r
670 UINTN EntryPointArgc;\r
671 CHAR8 *EntryPointArgv[MAX_ARGS];\r
3402aac7 672\r
2ef2b01e
A
673\r
674 if (Argc <= 2) {\r
675 // device name and laod address are required\r
676 return EFI_SUCCESS;\r
677 }\r
678\r
679 File = EfiOpen (Argv[1], EFI_FILE_MODE_READ, 0);\r
680 if (File == NULL) {\r
681 AsciiPrint (" %a is not a valid path\n", Argv[1]);\r
682 return EFI_SUCCESS;\r
683 }\r
684\r
685 EntryPoint = (EBL_COMMMAND)((Argc > 3) ? (UINTN)AsciiStrHexToUintn (Argv[3]) : (UINTN)NULL);\r
686 if (Argv[2][0] == '*') {\r
687 // * Means allocate the buffer\r
688 Status = EfiReadAllocatePool (File, &Address, &Size);\r
3402aac7 689\r
7ca9e5a4 690 // EntryPoint is relative to the start of the image\r
2ef2b01e
A
691 EntryPoint = (EBL_COMMMAND)((UINTN)EntryPoint + (UINTN)Address);\r
692\r
693 } else {\r
694 Address = (VOID *)AsciiStrHexToUintn (Argv[2]);\r
695 Size = File->Size;\r
696\r
697 // File->Size for LoadFile is lazy so we need to use the tell to figure it out\r
698 EfiTell (File, NULL);\r
699 Status = EfiRead (File, Address, &Size);\r
700 }\r
701\r
702 if (!EFI_ERROR (Status)) {\r
703 AsciiPrint ("Loaded %,d bytes to 0x%08x\n", Size, Address);\r
704\r
705 if (Argc > 3) {\r
706 if (Argc > 4) {\r
707 ParseArguments (Argv[4], &EntryPointArgc, EntryPointArgv);\r
708 } else {\r
709 EntryPointArgc = 1;\r
710 EntryPointArgv[0] = File->FileName;\r
711 }\r
3402aac7 712\r
2ef2b01e
A
713 Status = EntryPoint (EntryPointArgc, EntryPointArgv);\r
714 }\r
715 }\r
716\r
717 EfiClose (File);\r
718 return Status;\r
719}\r
720\r
721#define FILE_COPY_CHUNK 0x20000\r
722\r
723EFI_STATUS\r
724EblFileCopyCmd (\r
725 IN UINTN Argc,\r
726 IN CHAR8 **Argv\r
727 )\r
728{\r
729 EFI_OPEN_FILE *Source = NULL;\r
730 EFI_OPEN_FILE *Destination = NULL;\r
731 EFI_STATUS Status = EFI_SUCCESS;\r
732 VOID *Buffer = NULL;\r
733 UINTN Size;\r
734 UINTN Offset;\r
5439ccda 735 UINTN Chunk = FILE_COPY_CHUNK;\r
736 UINTN FileNameLen;\r
737 CHAR8* DestFileName;\r
738 CHAR8* SrcFileName;\r
739 CHAR8* SrcPtr;\r
f6381f4c 740\r
2ef2b01e
A
741 if (Argc < 3) {\r
742 return EFI_INVALID_PARAMETER;\r
743 }\r
3402aac7 744\r
5439ccda 745 DestFileName = Argv[2];\r
746 FileNameLen = AsciiStrLen (DestFileName);\r
747\r
748 // Check if the destination file name looks like a directory\r
749 if ((DestFileName[FileNameLen-1] == '\\') || (DestFileName[FileNameLen-1] == ':')) {\r
750 // Set the pointer after the source drive (eg: after fs1:)\r
751 SrcPtr = AsciiStrStr (Argv[1], ":");\r
752 if (SrcPtr == NULL) {\r
753 SrcPtr = Argv[1];\r
754 } else {\r
755 SrcPtr++;\r
756 if (*SrcPtr == '\\') {\r
757 SrcPtr++;\r
758 }\r
759 }\r
760\r
761 if (*SrcPtr == '\0') {\r
762 AsciiPrint("Source file incorrect.\n");\r
763 }\r
764\r
765 // Skip the Source Directories\r
766 while (1) {\r
767 SrcFileName = SrcPtr;\r
768 SrcPtr = AsciiStrStr (SrcPtr,"\\");\r
769 if (SrcPtr != NULL) {\r
770 SrcPtr++;\r
771 } else {\r
772 break;\r
773 }\r
774 }\r
775\r
776 if (*SrcFileName == '\0') {\r
777 AsciiPrint("Source file incorrect (Error 2).\n");\r
778 }\r
779\r
780 // Construct the destination filepath\r
781 DestFileName = (CHAR8*)AllocatePool (FileNameLen + AsciiStrLen (SrcFileName) + 1);\r
782 AsciiStrCpy (DestFileName, Argv[2]);\r
783 AsciiStrCat (DestFileName, SrcFileName);\r
784 }\r
785\r
2ef2b01e
A
786 Source = EfiOpen(Argv[1], EFI_FILE_MODE_READ, 0);\r
787 if (Source == NULL) {\r
788 AsciiPrint("Source file open error.\n");\r
789 return EFI_NOT_FOUND;\r
790 }\r
3402aac7 791\r
5439ccda 792 Destination = EfiOpen(DestFileName, EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE, 0);\r
2ef2b01e
A
793 if (Destination == NULL) {\r
794 AsciiPrint("Destination file open error.\n");\r
795 return EFI_NOT_FOUND;\r
796 }\r
797\r
798 Buffer = AllocatePool(FILE_COPY_CHUNK);\r
799 if (Buffer == NULL) {\r
800 goto Exit;\r
801 }\r
3402aac7 802\r
2ef2b01e
A
803 Size = EfiTell(Source, NULL);\r
804\r
805 for (Offset = 0; Offset + FILE_COPY_CHUNK <= Size; Offset += Chunk) {\r
806 Chunk = FILE_COPY_CHUNK;\r
3402aac7 807\r
2ef2b01e
A
808 Status = EfiRead(Source, Buffer, &Chunk);\r
809 if (EFI_ERROR(Status)) {\r
f6381f4c 810 AsciiPrint("Read file error %r\n", Status);\r
2ef2b01e
A
811 goto Exit;\r
812 }\r
813\r
814 Status = EfiWrite(Destination, Buffer, &Chunk);\r
815 if (EFI_ERROR(Status)) {\r
f6381f4c 816 AsciiPrint("Write file error %r\n", Status);\r
2ef2b01e 817 goto Exit;\r
3402aac7 818 }\r
2ef2b01e 819 }\r
3402aac7 820\r
2ef2b01e
A
821 // Any left over?\r
822 if (Offset < Size) {\r
823 Chunk = Size - Offset;\r
3402aac7 824\r
2ef2b01e
A
825 Status = EfiRead(Source, Buffer, &Chunk);\r
826 if (EFI_ERROR(Status)) {\r
f6381f4c 827 AsciiPrint("Read file error %r\n", Status);\r
2ef2b01e
A
828 goto Exit;\r
829 }\r
830\r
831 Status = EfiWrite(Destination, Buffer, &Chunk);\r
832 if (EFI_ERROR(Status)) {\r
f6381f4c 833 AsciiPrint("Write file error %r\n", Status);\r
2ef2b01e 834 goto Exit;\r
3402aac7 835 }\r
2ef2b01e
A
836 }\r
837\r
f6381f4c 838\r
2ef2b01e
A
839Exit:\r
840 if (Source != NULL) {\r
841 Status = EfiClose(Source);\r
842 if (EFI_ERROR(Status)) {\r
843 AsciiPrint("Source close error %r\n", Status);\r
844 }\r
845 }\r
2ef2b01e
A
846 if (Destination != NULL) {\r
847 Status = EfiClose(Destination);\r
848 if (EFI_ERROR(Status)) {\r
849 AsciiPrint("Destination close error %r\n", Status);\r
850 }\r
5439ccda 851\r
852 // Case when we have concated the filename to the destination directory\r
853 if (DestFileName != Argv[2]) {\r
854 FreePool (DestFileName);\r
855 }\r
2ef2b01e 856 }\r
3402aac7 857\r
2ef2b01e
A
858 if (Buffer != NULL) {\r
859 FreePool(Buffer);\r
860 }\r
3402aac7 861\r
2ef2b01e
A
862 return Status;\r
863}\r
864\r
865EFI_STATUS\r
866EblFileDiffCmd (\r
867 IN UINTN Argc,\r
868 IN CHAR8 **Argv\r
869 )\r
870{\r
871 EFI_OPEN_FILE *File1 = NULL;\r
872 EFI_OPEN_FILE *File2 = NULL;\r
873 EFI_STATUS Status = EFI_SUCCESS;\r
874 VOID *Buffer1 = NULL;\r
875 VOID *Buffer2 = NULL;\r
876 UINTN Size1;\r
877 UINTN Size2;\r
878 UINTN Offset;\r
879 UINTN Chunk = FILE_COPY_CHUNK;\r
3402aac7 880\r
2ef2b01e
A
881 if (Argc != 3) {\r
882 return EFI_INVALID_PARAMETER;\r
883 }\r
3402aac7 884\r
2ef2b01e
A
885 File1 = EfiOpen(Argv[1], EFI_FILE_MODE_READ, 0);\r
886 if (File1 == NULL) {\r
887 AsciiPrint("File 1 open error.\n");\r
888 return EFI_NOT_FOUND;\r
889 }\r
3402aac7 890\r
2ef2b01e
A
891 File2 = EfiOpen(Argv[2], EFI_FILE_MODE_READ, 0);\r
892 if (File2 == NULL) {\r
893 AsciiPrint("File 2 open error.\n");\r
894 return EFI_NOT_FOUND;\r
895 }\r
896\r
897 Size1 = EfiTell(File1, NULL);\r
898 Size2 = EfiTell(File2, NULL);\r
899\r
900 if (Size1 != Size2) {\r
901 AsciiPrint("Files differ.\n");\r
902 goto Exit;\r
903 }\r
904\r
905 Buffer1 = AllocatePool(FILE_COPY_CHUNK);\r
906 if (Buffer1 == NULL) {\r
907 goto Exit;\r
908 }\r
3402aac7 909\r
2ef2b01e
A
910 Buffer2 = AllocatePool(FILE_COPY_CHUNK);\r
911 if (Buffer2 == NULL) {\r
912 goto Exit;\r
3402aac7 913 }\r
2ef2b01e
A
914\r
915 for (Offset = 0; Offset + FILE_COPY_CHUNK <= Size1; Offset += Chunk) {\r
916 Chunk = FILE_COPY_CHUNK;\r
3402aac7 917\r
2ef2b01e
A
918 Status = EfiRead(File1, Buffer1, &Chunk);\r
919 if (EFI_ERROR(Status)) {\r
920 AsciiPrint("File 1 read error\n");\r
921 goto Exit;\r
922 }\r
923\r
924 Status = EfiRead(File2, Buffer2, &Chunk);\r
925 if (EFI_ERROR(Status)) {\r
926 AsciiPrint("File 2 read error\n");\r
927 goto Exit;\r
928 }\r
3402aac7 929\r
2ef2b01e
A
930 if (CompareMem(Buffer1, Buffer2, Chunk) != 0) {\r
931 AsciiPrint("Files differ.\n");\r
932 goto Exit;\r
933 };\r
934 }\r
3402aac7 935\r
2ef2b01e
A
936 // Any left over?\r
937 if (Offset < Size1) {\r
938 Chunk = Size1 - Offset;\r
3402aac7 939\r
2ef2b01e
A
940 Status = EfiRead(File1, Buffer1, &Chunk);\r
941 if (EFI_ERROR(Status)) {\r
942 AsciiPrint("File 1 read error\n");\r
943 goto Exit;\r
944 }\r
945\r
946 Status = EfiRead(File2, Buffer2, &Chunk);\r
947 if (EFI_ERROR(Status)) {\r
948 AsciiPrint("File 2 read error\n");\r
949 goto Exit;\r
3402aac7 950 }\r
2ef2b01e 951 }\r
3402aac7 952\r
2ef2b01e
A
953 if (CompareMem(Buffer1, Buffer2, Chunk) != 0) {\r
954 AsciiPrint("Files differ.\n");\r
955 } else {\r
956 AsciiPrint("Files are identical.\n");\r
957 }\r
958\r
959Exit:\r
960 if (File1 != NULL) {\r
961 Status = EfiClose(File1);\r
962 if (EFI_ERROR(Status)) {\r
963 AsciiPrint("File 1 close error %r\n", Status);\r
964 }\r
965 }\r
3402aac7 966\r
2ef2b01e
A
967 if (File2 != NULL) {\r
968 Status = EfiClose(File2);\r
969 if (EFI_ERROR(Status)) {\r
970 AsciiPrint("File 2 close error %r\n", Status);\r
971 }\r
972 }\r
3402aac7 973\r
2ef2b01e
A
974 if (Buffer1 != NULL) {\r
975 FreePool(Buffer1);\r
976 }\r
3402aac7 977\r
2ef2b01e
A
978 if (Buffer2 != NULL) {\r
979 FreePool(Buffer2);\r
980 }\r
3402aac7 981\r
2ef2b01e
A
982 return Status;\r
983}\r
984\r
985GLOBAL_REMOVE_IF_UNREFERENCED const EBL_COMMAND_TABLE mCmdDeviceTemplate[] =\r
986{\r
987 {\r
988 "connect",\r
989 "[d]; Connect all EFI devices. d means disconnect",\r
990 NULL,\r
991 EblConnectCmd\r
992 },\r
993 {\r
994 "device",\r
995 "; Show information about boot devices",\r
996 NULL,\r
997 EblDeviceCmd\r
998 },\r
999 {\r
1000 "go",\r
3402aac7 1001 " dev:path loadaddress entrypoint args; load to given address and jump in",\r
2ef2b01e
A
1002 NULL,\r
1003 EblGoCmd\r
1004 },\r
1005 {\r
1006 "loadfv",\r
3402aac7 1007 " devname; Load PI FV from device",\r
2ef2b01e
A
1008 NULL,\r
1009 EblLoadFvCmd\r
1010 },\r
1011 {\r
1012 "start",\r
3402aac7 1013 " path; EFI Boot Device:filepath. fs1:\\EFI\\BOOT.EFI",\r
2ef2b01e
A
1014 NULL,\r
1015 EblStartCmd\r
1016 },\r
1017 {\r
1018 "memmap",\r
3402aac7 1019 "; dump EFI memory map",\r
2ef2b01e
A
1020 NULL,\r
1021 EblMemMapCmd\r
1022 },\r
1023 {\r
1024 "cp",\r
5439ccda 1025 " file1 file2; copy file only.",\r
2ef2b01e
A
1026 NULL,\r
1027 EblFileCopyCmd\r
1028 },\r
1029 {\r
1030 "diff",\r
1031 " file1 file2; compare files",\r
1032 NULL,\r
1033 EblFileDiffCmd\r
1034 }\r
1035};\r
1036\r
1037\r
1038/**\r
1039 Initialize the commands in this in this file\r
1040**/\r
1041\r
1042VOID\r
1043EblInitializeDeviceCmd (\r
1044 VOID\r
1045 )\r
1046{\r
1047 EfiGetSystemConfigurationTable (&gEfiDxeServicesTableGuid, (VOID **) &gDS);\r
1048 EblAddCommands (mCmdDeviceTemplate, sizeof (mCmdDeviceTemplate)/sizeof (EBL_COMMAND_TABLE));\r
1049}\r
1050\r