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