]> git.proxmox.com Git - mirror_edk2.git/blame - ShellPkg/Library/UefiShellDebug1CommandsLib/LoadPciRom.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / ShellPkg / Library / UefiShellDebug1CommandsLib / LoadPciRom.c
CommitLineData
5d73d92f 1/** @file\r
2 Main file for LoadPciRom shell Debug1 function.\r
3\r
c011b6c9 4 (C) Copyright 2015 Hewlett-Packard Development Company, L.P.<BR>\r
c671c910 5 Copyright (c) 2005 - 2019, Intel Corporation. All rights reserved.<BR>\r
56ba3746 6 SPDX-License-Identifier: BSD-2-Clause-Patent\r
5d73d92f 7\r
8**/\r
9\r
10#include "UefiShellDebug1CommandsLib.h"\r
11#include <IndustryStandard/Pci22.h>\r
12#include <IndustryStandard/Pci23.h>\r
13#include <IndustryStandard/PeImage.h>\r
14#include <Protocol/Decompress.h>\r
15\r
3737ac2b 16/**\r
17 Connects all available drives and controllers.\r
18\r
19 @retval EFI_SUCCESS The operation was successful.\r
20 @retval EFI_ABORTED The abort mechanism was received.\r
21**/\r
5d73d92f 22EFI_STATUS\r
5d73d92f 23LoadPciRomConnectAllDriversToAllControllers (\r
24 VOID\r
25 );\r
26\r
3737ac2b 27/**\r
28 Command entry point.\r
5d73d92f 29\r
3737ac2b 30 @param[in] RomBar The Rom Base address.\r
31 @param[in] RomSize The Rom size.\r
32 @param[in] FileName The file name.\r
33\r
34 @retval EFI_SUCCESS The command completed successfully.\r
35 @retval EFI_INVALID_PARAMETER Command usage error.\r
36 @retval EFI_UNSUPPORTED Protocols unsupported.\r
37 @retval EFI_OUT_OF_RESOURCES Out of memory.\r
38 @retval Other value Unknown error.\r
39**/\r
5d73d92f 40EFI_STATUS\r
5d73d92f 41LoadEfiDriversFromRomImage (\r
47d20b54
MK
42 VOID *RomBar,\r
43 UINTN RomSize,\r
44 CONST CHAR16 *FileName\r
5d73d92f 45 );\r
46\r
47d20b54
MK
47STATIC CONST SHELL_PARAM_ITEM ParamList[] = {\r
48 { L"-nc", TypeFlag },\r
49 { NULL, TypeMax }\r
50};\r
5d73d92f 51\r
3737ac2b 52/**\r
53 Function for 'loadpcirom' command.\r
54\r
55 @param[in] ImageHandle Handle to the Image (NULL if Internal).\r
56 @param[in] SystemTable Pointer to the System Table (NULL if Internal).\r
57**/\r
5d73d92f 58SHELL_STATUS\r
59EFIAPI\r
60ShellCommandRunLoadPciRom (\r
61 IN EFI_HANDLE ImageHandle,\r
62 IN EFI_SYSTEM_TABLE *SystemTable\r
63 )\r
64{\r
47d20b54
MK
65 EFI_SHELL_FILE_INFO *FileList;\r
66 UINTN SourceSize;\r
67 UINT8 *File1Buffer;\r
68 EFI_STATUS Status;\r
69 LIST_ENTRY *Package;\r
70 CHAR16 *ProblemParam;\r
71 SHELL_STATUS ShellStatus;\r
72 BOOLEAN Connect;\r
73 CONST CHAR16 *Param;\r
74 UINTN ParamCount;\r
75 EFI_SHELL_FILE_INFO *Node;\r
76\r
5d73d92f 77 //\r
78 // Local variable initializations\r
79 //\r
80 File1Buffer = NULL;\r
81 ShellStatus = SHELL_SUCCESS;\r
82 FileList = NULL;\r
83\r
5d73d92f 84 //\r
85 // verify number of arguments\r
86 //\r
87 Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE);\r
47d20b54
MK
88 if (EFI_ERROR (Status)) {\r
89 if ((Status == EFI_VOLUME_CORRUPTED) && (ProblemParam != NULL)) {\r
90 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDebug1HiiHandle, L"loadpcirom", ProblemParam);\r
91 FreePool (ProblemParam);\r
5d73d92f 92 ShellStatus = SHELL_INVALID_PARAMETER;\r
93 } else {\r
47d20b54 94 ASSERT (FALSE);\r
5d73d92f 95 }\r
96 } else {\r
47d20b54
MK
97 if (ShellCommandLineGetCount (Package) < 2) {\r
98 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellDebug1HiiHandle, L"loadpcirom");\r
5d73d92f 99 ShellStatus = SHELL_INVALID_PARAMETER;\r
100 } else {\r
47d20b54 101 if (ShellCommandLineGetFlag (Package, L"-nc")) {\r
5d73d92f 102 Connect = FALSE;\r
103 } else {\r
104 Connect = TRUE;\r
105 }\r
106\r
107 //\r
108 // get a list with each file specified by parameters\r
109 // if parameter is a directory then add all the files below it to the list\r
110 //\r
47d20b54
MK
111 for ( ParamCount = 1, Param = ShellCommandLineGetRawValue (Package, ParamCount)\r
112 ; Param != NULL\r
113 ; ParamCount++, Param = ShellCommandLineGetRawValue (Package, ParamCount)\r
114 )\r
115 {\r
116 Status = ShellOpenFileMetaArg ((CHAR16 *)Param, EFI_FILE_MODE_WRITE|EFI_FILE_MODE_READ, &FileList);\r
117 if (EFI_ERROR (Status)) {\r
118 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL), gShellDebug1HiiHandle, L"loadpcirom", Param);\r
5d73d92f 119 ShellStatus = SHELL_ACCESS_DENIED;\r
120 break;\r
121 }\r
122 }\r
47d20b54
MK
123\r
124 if ((ShellStatus == SHELL_SUCCESS) && (FileList != NULL)) {\r
5d73d92f 125 //\r
126 // loop through the list and make sure we are not aborting...\r
127 //\r
47d20b54
MK
128 for ( Node = (EFI_SHELL_FILE_INFO *)GetFirstNode (&FileList->Link)\r
129 ; !IsNull (&FileList->Link, &Node->Link) && !ShellGetExecutionBreakFlag ()\r
130 ; Node = (EFI_SHELL_FILE_INFO *)GetNextNode (&FileList->Link, &Node->Link)\r
131 )\r
132 {\r
133 if (EFI_ERROR (Node->Status)) {\r
134 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL), gShellDebug1HiiHandle, L"loadpcirom", Node->FullName);\r
5d73d92f 135 ShellStatus = SHELL_INVALID_PARAMETER;\r
136 continue;\r
137 }\r
47d20b54
MK
138\r
139 if (FileHandleIsDirectory (Node->Handle) == EFI_SUCCESS) {\r
140 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_FILE_NOT_DIR), gShellDebug1HiiHandle, L"loadpcirom", Node->FullName);\r
5d73d92f 141 ShellStatus = SHELL_INVALID_PARAMETER;\r
142 continue;\r
143 }\r
47d20b54
MK
144\r
145 SourceSize = (UINTN)Node->Info->FileSize;\r
3737ac2b 146 File1Buffer = AllocateZeroPool (SourceSize);\r
20cfed16
RN
147 if (File1Buffer == NULL) {\r
148 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_OUT_MEM), gShellDebug1HiiHandle, L"loadpcirom");\r
149 ShellStatus = SHELL_OUT_OF_RESOURCES;\r
150 continue;\r
151 }\r
47d20b54
MK
152\r
153 Status = gEfiShellProtocol->ReadFile (Node->Handle, &SourceSize, File1Buffer);\r
154 if (EFI_ERROR (Status)) {\r
155 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_FILE_READ_FAIL), gShellDebug1HiiHandle, L"loadpcirom", Node->FullName);\r
5d73d92f 156 ShellStatus = SHELL_INVALID_PARAMETER;\r
157 } else {\r
158 Status = LoadEfiDriversFromRomImage (\r
47d20b54
MK
159 File1Buffer,\r
160 SourceSize,\r
161 Node->FullName\r
162 );\r
5d73d92f 163\r
47d20b54 164 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_LOAD_PCI_ROM_RES), gShellDebug1HiiHandle, Node->FullName, Status);\r
5d73d92f 165 }\r
47d20b54
MK
166\r
167 FreePool (File1Buffer);\r
5d73d92f 168 }\r
3737ac2b 169 } else if (ShellStatus == SHELL_SUCCESS) {\r
47d20b54 170 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_FILE_NOT_SPEC), gShellDebug1HiiHandle, "loadpcirom");\r
3737ac2b 171 ShellStatus = SHELL_NOT_FOUND;\r
5d73d92f 172 }\r
47d20b54
MK
173\r
174 if ((FileList != NULL) && !IsListEmpty (&FileList->Link)) {\r
175 Status = ShellCloseFileMetaArg (&FileList);\r
5d73d92f 176 }\r
47d20b54 177\r
5d73d92f 178 FileList = NULL;\r
179\r
180 if (Connect) {\r
181 Status = LoadPciRomConnectAllDriversToAllControllers ();\r
182 }\r
183 }\r
184 }\r
185\r
186 return (ShellStatus);\r
187}\r
188\r
3737ac2b 189/**\r
190 Command entry point.\r
191\r
192 @param[in] RomBar The Rom Base address.\r
193 @param[in] RomSize The Rom size.\r
194 @param[in] FileName The file name.\r
195\r
196 @retval EFI_SUCCESS The command completed successfully.\r
197 @retval EFI_INVALID_PARAMETER Command usage error.\r
198 @retval EFI_UNSUPPORTED Protocols unsupported.\r
199 @retval EFI_OUT_OF_RESOURCES Out of memory.\r
200 @retval Other value Unknown error.\r
201**/\r
5d73d92f 202EFI_STATUS\r
203LoadEfiDriversFromRomImage (\r
47d20b54
MK
204 VOID *RomBar,\r
205 UINTN RomSize,\r
206 CONST CHAR16 *FileName\r
5d73d92f 207 )\r
5d73d92f 208\r
5d73d92f 209{\r
210 EFI_PCI_EXPANSION_ROM_HEADER *EfiRomHeader;\r
211 PCI_DATA_STRUCTURE *Pcir;\r
212 UINTN ImageIndex;\r
213 UINTN RomBarOffset;\r
214 UINT32 ImageSize;\r
215 UINT16 ImageOffset;\r
216 EFI_HANDLE ImageHandle;\r
217 EFI_STATUS Status;\r
3737ac2b 218 EFI_STATUS ReturnStatus;\r
5d73d92f 219 CHAR16 RomFileName[280];\r
220 EFI_DEVICE_PATH_PROTOCOL *FilePath;\r
221 BOOLEAN SkipImage;\r
222 UINT32 DestinationSize;\r
223 UINT32 ScratchSize;\r
224 UINT8 *Scratch;\r
225 VOID *ImageBuffer;\r
226 VOID *DecompressedImageBuffer;\r
227 UINT32 ImageLength;\r
228 EFI_DECOMPRESS_PROTOCOL *Decompress;\r
94020bb4 229 UINT32 InitializationSize;\r
5d73d92f 230\r
47d20b54
MK
231 ImageIndex = 0;\r
232 ReturnStatus = EFI_NOT_FOUND;\r
233 RomBarOffset = (UINTN)RomBar;\r
5d73d92f 234\r
235 do {\r
47d20b54 236 EfiRomHeader = (EFI_PCI_EXPANSION_ROM_HEADER *)(UINTN)RomBarOffset;\r
5d73d92f 237\r
94020bb4 238 if (EfiRomHeader->Signature != PCI_EXPANSION_ROM_HEADER_SIGNATURE) {\r
47d20b54
MK
239 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_LOADPCIROM_CORRUPT), gShellDebug1HiiHandle, L"loadpcirom", FileName, ImageIndex);\r
240 // PrintToken (STRING_TOKEN (STR_LOADPCIROM_IMAGE_CORRUPT), HiiHandle, ImageIndex);\r
3737ac2b 241 return ReturnStatus;\r
5d73d92f 242 }\r
243\r
94020bb4 244 //\r
ba0014b9
LG
245 // If the pointer to the PCI Data Structure is invalid, no further images can be located.\r
246 // The PCI Data Structure must be DWORD aligned.\r
94020bb4 247 //\r
47d20b54
MK
248 if ((EfiRomHeader->PcirOffset == 0) ||\r
249 ((EfiRomHeader->PcirOffset & 3) != 0) ||\r
250 (RomBarOffset - (UINTN)RomBar + EfiRomHeader->PcirOffset + sizeof (PCI_DATA_STRUCTURE) > RomSize))\r
251 {\r
94020bb4 252 break;\r
253 }\r
254\r
47d20b54 255 Pcir = (PCI_DATA_STRUCTURE *)(UINTN)(RomBarOffset + EfiRomHeader->PcirOffset);\r
94020bb4 256 //\r
257 // If a valid signature is not present in the PCI Data Structure, no further images can be located.\r
258 //\r
259 if (Pcir->Signature != PCI_DATA_STRUCTURE_SIGNATURE) {\r
260 break;\r
261 }\r
47d20b54 262\r
5d73d92f 263 ImageSize = Pcir->ImageLength * 512;\r
94020bb4 264 if (RomBarOffset - (UINTN)RomBar + ImageSize > RomSize) {\r
265 break;\r
266 }\r
5d73d92f 267\r
268 if ((Pcir->CodeType == PCI_CODE_TYPE_EFI_IMAGE) &&\r
94020bb4 269 (EfiRomHeader->EfiSignature == EFI_PCI_EXPANSION_ROM_HEADER_EFISIGNATURE) &&\r
270 ((EfiRomHeader->EfiSubsystem == EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER) ||\r
47d20b54
MK
271 (EfiRomHeader->EfiSubsystem == EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER)))\r
272 {\r
273 ImageOffset = EfiRomHeader->EfiImageHeaderOffset;\r
274 InitializationSize = EfiRomHeader->InitializationSize * 512;\r
5d73d92f 275\r
47d20b54
MK
276 if ((InitializationSize <= ImageSize) && (ImageOffset < InitializationSize)) {\r
277 ImageBuffer = (VOID *)(UINTN)(RomBarOffset + ImageOffset);\r
94020bb4 278 ImageLength = InitializationSize - ImageOffset;\r
5d73d92f 279 DecompressedImageBuffer = NULL;\r
280\r
281 //\r
282 // decompress here if needed\r
283 //\r
284 SkipImage = FALSE;\r
285 if (EfiRomHeader->CompressionType > EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED) {\r
286 SkipImage = TRUE;\r
287 }\r
288\r
289 if (EfiRomHeader->CompressionType == EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED) {\r
47d20b54
MK
290 Status = gBS->LocateProtocol (&gEfiDecompressProtocolGuid, NULL, (VOID **)&Decompress);\r
291 ASSERT_EFI_ERROR (Status);\r
5d73d92f 292 if (EFI_ERROR (Status)) {\r
293 SkipImage = TRUE;\r
294 } else {\r
295 SkipImage = TRUE;\r
47d20b54
MK
296 Status = Decompress->GetInfo (\r
297 Decompress,\r
298 ImageBuffer,\r
299 ImageLength,\r
300 &DestinationSize,\r
301 &ScratchSize\r
302 );\r
5d73d92f 303 if (!EFI_ERROR (Status)) {\r
3737ac2b 304 DecompressedImageBuffer = AllocateZeroPool (DestinationSize);\r
5d73d92f 305 if (ImageBuffer != NULL) {\r
3737ac2b 306 Scratch = AllocateZeroPool (ScratchSize);\r
5d73d92f 307 if (Scratch != NULL) {\r
308 Status = Decompress->Decompress (\r
47d20b54
MK
309 Decompress,\r
310 ImageBuffer,\r
311 ImageLength,\r
312 DecompressedImageBuffer,\r
313 DestinationSize,\r
314 Scratch,\r
315 ScratchSize\r
316 );\r
5d73d92f 317 if (!EFI_ERROR (Status)) {\r
318 ImageBuffer = DecompressedImageBuffer;\r
319 ImageLength = DestinationSize;\r
320 SkipImage = FALSE;\r
321 }\r
322\r
323 FreePool (Scratch);\r
324 }\r
325 }\r
326 }\r
327 }\r
328 }\r
329\r
330 if (!SkipImage) {\r
331 //\r
332 // load image and start image\r
333 //\r
334 UnicodeSPrint (RomFileName, sizeof (RomFileName), L"%s[%d]", FileName, ImageIndex);\r
335 FilePath = FileDevicePath (NULL, RomFileName);\r
336\r
337 Status = gBS->LoadImage (\r
47d20b54
MK
338 TRUE,\r
339 gImageHandle,\r
340 FilePath,\r
341 ImageBuffer,\r
342 ImageLength,\r
343 &ImageHandle\r
344 );\r
5d73d92f 345 if (EFI_ERROR (Status)) {\r
c671c910
DB
346 //\r
347 // With EFI_SECURITY_VIOLATION retval, the Image was loaded and an ImageHandle was created\r
348 // with a valid EFI_LOADED_IMAGE_PROTOCOL, but the image can not be started right now.\r
349 // If the caller doesn't have the option to defer the execution of an image, we should\r
350 // unload image for the EFI_SECURITY_VIOLATION to avoid resource leak.\r
351 //\r
352 if (Status == EFI_SECURITY_VIOLATION) {\r
353 gBS->UnloadImage (ImageHandle);\r
354 }\r
47d20b54
MK
355\r
356 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_LOADPCIROM_LOAD_FAIL), gShellDebug1HiiHandle, L"loadpcirom", FileName, ImageIndex);\r
357 // PrintToken (STRING_TOKEN (STR_LOADPCIROM_LOAD_IMAGE_ERROR), HiiHandle, ImageIndex, Status);\r
5d73d92f 358 } else {\r
359 Status = gBS->StartImage (ImageHandle, NULL, NULL);\r
360 if (EFI_ERROR (Status)) {\r
47d20b54
MK
361 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_LOADPCIROM_START_FAIL), gShellDebug1HiiHandle, L"loadpcirom", FileName, ImageIndex);\r
362 // PrintToken (STRING_TOKEN (STR_LOADPCIROM_START_IMAGE), HiiHandle, ImageIndex, Status);\r
5d73d92f 363 } else {\r
3737ac2b 364 ReturnStatus = Status;\r
5d73d92f 365 }\r
366 }\r
367 }\r
368\r
369 if (DecompressedImageBuffer != NULL) {\r
370 FreePool (DecompressedImageBuffer);\r
371 }\r
5d73d92f 372 }\r
373 }\r
374\r
375 RomBarOffset = RomBarOffset + ImageSize;\r
376 ImageIndex++;\r
47d20b54 377 } while (((Pcir->Indicator & 0x80) == 0x00) && ((RomBarOffset - (UINTN)RomBar) < RomSize));\r
5d73d92f 378\r
3737ac2b 379 return ReturnStatus;\r
5d73d92f 380}\r
381\r
3737ac2b 382/**\r
383 Connects all available drives and controllers.\r
384\r
385 @retval EFI_SUCCESS The operation was successful.\r
386 @retval EFI_ABORTED The abort mechanism was received.\r
387**/\r
5d73d92f 388EFI_STATUS\r
389LoadPciRomConnectAllDriversToAllControllers (\r
390 VOID\r
391 )\r
5d73d92f 392{\r
393 EFI_STATUS Status;\r
5d73d92f 394 UINTN HandleCount;\r
395 EFI_HANDLE *HandleBuffer;\r
fc41b97f
RN
396 UINTN Index;\r
397\r
398 Status = gBS->LocateHandleBuffer (\r
399 AllHandles,\r
400 NULL,\r
401 NULL,\r
402 &HandleCount,\r
403 &HandleBuffer\r
404 );\r
5d73d92f 405 if (EFI_ERROR (Status)) {\r
406 return Status;\r
407 }\r
408\r
fc41b97f 409 for (Index = 0; Index < HandleCount; Index++) {\r
5d73d92f 410 if (ShellGetExecutionBreakFlag ()) {\r
411 Status = EFI_ABORTED;\r
fc41b97f 412 break;\r
5d73d92f 413 }\r
47d20b54 414\r
fc41b97f
RN
415 gBS->ConnectController (HandleBuffer[Index], NULL, NULL, TRUE);\r
416 }\r
5d73d92f 417\r
fc41b97f 418 if (HandleBuffer != NULL) {\r
5d73d92f 419 FreePool (HandleBuffer);\r
5d73d92f 420 }\r
47d20b54 421\r
5d73d92f 422 return Status;\r
423}\r