]> git.proxmox.com Git - mirror_edk2.git/blame - ShellPkg/Library/UefiShellDebug1CommandsLib/LoadPciRom.c
ShellPkg/UefiShellDebug1CommandsLib
[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
ba0014b9 5 Copyright (c) 2005 - 2018, 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
42 VOID *RomBar,\r
43 UINTN RomSize,\r
44 CONST CHAR16 *FileName\r
45 );\r
46\r
47STATIC CONST SHELL_PARAM_ITEM ParamList[] = {\r
48 {L"-nc", TypeFlag},\r
49 {NULL, TypeMax}\r
50 };\r
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
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
77 // Local variable initializations\r
78 //\r
79 File1Buffer = NULL;\r
80 ShellStatus = SHELL_SUCCESS;\r
81 FileList = NULL;\r
82\r
83\r
84 //\r
85 // verify number of arguments\r
86 //\r
87 Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE);\r
88 if (EFI_ERROR(Status)) {\r
89 if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {\r
ba0014b9 90 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDebug1HiiHandle, L"loadpcirom", ProblemParam);\r
5d73d92f 91 FreePool(ProblemParam);\r
92 ShellStatus = SHELL_INVALID_PARAMETER;\r
93 } else {\r
94 ASSERT(FALSE);\r
95 }\r
96 } else {\r
3737ac2b 97 if (ShellCommandLineGetCount(Package) < 2) {\r
ba0014b9 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
3737ac2b 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
111 for ( ParamCount = 1, Param = ShellCommandLineGetRawValue(Package, ParamCount)\r
112 ; Param != NULL\r
113 ; ParamCount++, Param = ShellCommandLineGetRawValue(Package, ParamCount)\r
114 ){\r
115 Status = ShellOpenFileMetaArg((CHAR16*)Param, EFI_FILE_MODE_WRITE|EFI_FILE_MODE_READ, &FileList);\r
116 if (EFI_ERROR(Status)) {\r
ba0014b9 117 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL), gShellDebug1HiiHandle, L"loadpcirom", Param);\r
5d73d92f 118 ShellStatus = SHELL_ACCESS_DENIED;\r
119 break;\r
120 }\r
121 }\r
3737ac2b 122 if (ShellStatus == SHELL_SUCCESS && FileList != NULL) {\r
5d73d92f 123 //\r
124 // loop through the list and make sure we are not aborting...\r
125 //\r
126 for ( Node = (EFI_SHELL_FILE_INFO*)GetFirstNode(&FileList->Link)\r
127 ; !IsNull(&FileList->Link, &Node->Link) && !ShellGetExecutionBreakFlag()\r
128 ; Node = (EFI_SHELL_FILE_INFO*)GetNextNode(&FileList->Link, &Node->Link)\r
129 ){\r
130 if (EFI_ERROR(Node->Status)){\r
ba0014b9 131 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL), gShellDebug1HiiHandle, L"loadpcirom", Node->FullName);\r
5d73d92f 132 ShellStatus = SHELL_INVALID_PARAMETER;\r
133 continue;\r
134 }\r
135 if (FileHandleIsDirectory(Node->Handle) == EFI_SUCCESS) {\r
ba0014b9 136 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_FILE_NOT_DIR), gShellDebug1HiiHandle, L"loadpcirom", Node->FullName);\r
5d73d92f 137 ShellStatus = SHELL_INVALID_PARAMETER;\r
138 continue;\r
139 }\r
140 SourceSize = (UINTN) Node->Info->FileSize;\r
3737ac2b 141 File1Buffer = AllocateZeroPool (SourceSize);\r
20cfed16
RN
142 if (File1Buffer == NULL) {\r
143 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_OUT_MEM), gShellDebug1HiiHandle, L"loadpcirom");\r
144 ShellStatus = SHELL_OUT_OF_RESOURCES;\r
145 continue;\r
146 }\r
5d73d92f 147 Status = gEfiShellProtocol->ReadFile(Node->Handle, &SourceSize, File1Buffer);\r
148 if (EFI_ERROR(Status)) {\r
ba0014b9 149 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_FILE_READ_FAIL), gShellDebug1HiiHandle, L"loadpcirom", Node->FullName);\r
5d73d92f 150 ShellStatus = SHELL_INVALID_PARAMETER;\r
151 } else {\r
152 Status = LoadEfiDriversFromRomImage (\r
153 File1Buffer,\r
154 SourceSize,\r
155 Node->FullName\r
156 );\r
157\r
158 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_LOAD_PCI_ROM_RES), gShellDebug1HiiHandle, Node->FullName, Status);\r
159 }\r
160 FreePool(File1Buffer);\r
161 }\r
3737ac2b 162 } else if (ShellStatus == SHELL_SUCCESS) {\r
ba0014b9 163 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_FILE_NOT_SPEC), gShellDebug1HiiHandle, "loadpcirom");\r
3737ac2b 164 ShellStatus = SHELL_NOT_FOUND;\r
5d73d92f 165 }\r
166 if (FileList != NULL && !IsListEmpty(&FileList->Link)) {\r
167 Status = ShellCloseFileMetaArg(&FileList);\r
168 }\r
169 FileList = NULL;\r
170\r
171 if (Connect) {\r
172 Status = LoadPciRomConnectAllDriversToAllControllers ();\r
173 }\r
174 }\r
175 }\r
176\r
177 return (ShellStatus);\r
178}\r
179\r
3737ac2b 180/**\r
181 Command entry point.\r
182\r
183 @param[in] RomBar The Rom Base address.\r
184 @param[in] RomSize The Rom size.\r
185 @param[in] FileName The file name.\r
186\r
187 @retval EFI_SUCCESS The command completed successfully.\r
188 @retval EFI_INVALID_PARAMETER Command usage error.\r
189 @retval EFI_UNSUPPORTED Protocols unsupported.\r
190 @retval EFI_OUT_OF_RESOURCES Out of memory.\r
191 @retval Other value Unknown error.\r
192**/\r
5d73d92f 193EFI_STATUS\r
194LoadEfiDriversFromRomImage (\r
195 VOID *RomBar,\r
196 UINTN RomSize,\r
197 CONST CHAR16 *FileName\r
198 )\r
5d73d92f 199\r
5d73d92f 200{\r
201 EFI_PCI_EXPANSION_ROM_HEADER *EfiRomHeader;\r
202 PCI_DATA_STRUCTURE *Pcir;\r
203 UINTN ImageIndex;\r
204 UINTN RomBarOffset;\r
205 UINT32 ImageSize;\r
206 UINT16 ImageOffset;\r
207 EFI_HANDLE ImageHandle;\r
208 EFI_STATUS Status;\r
3737ac2b 209 EFI_STATUS ReturnStatus;\r
5d73d92f 210 CHAR16 RomFileName[280];\r
211 EFI_DEVICE_PATH_PROTOCOL *FilePath;\r
212 BOOLEAN SkipImage;\r
213 UINT32 DestinationSize;\r
214 UINT32 ScratchSize;\r
215 UINT8 *Scratch;\r
216 VOID *ImageBuffer;\r
217 VOID *DecompressedImageBuffer;\r
218 UINT32 ImageLength;\r
219 EFI_DECOMPRESS_PROTOCOL *Decompress;\r
94020bb4 220 UINT32 InitializationSize;\r
5d73d92f 221\r
222 ImageIndex = 0;\r
3737ac2b 223 ReturnStatus = EFI_NOT_FOUND;\r
5d73d92f 224 RomBarOffset = (UINTN) RomBar;\r
225\r
226 do {\r
227\r
228 EfiRomHeader = (EFI_PCI_EXPANSION_ROM_HEADER *) (UINTN) RomBarOffset;\r
229\r
94020bb4 230 if (EfiRomHeader->Signature != PCI_EXPANSION_ROM_HEADER_SIGNATURE) {\r
ba0014b9 231 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_LOADPCIROM_CORRUPT), gShellDebug1HiiHandle, L"loadpcirom", FileName, ImageIndex);\r
5d73d92f 232// PrintToken (STRING_TOKEN (STR_LOADPCIROM_IMAGE_CORRUPT), HiiHandle, ImageIndex);\r
3737ac2b 233 return ReturnStatus;\r
5d73d92f 234 }\r
235\r
94020bb4 236 //\r
ba0014b9
LG
237 // If the pointer to the PCI Data Structure is invalid, no further images can be located.\r
238 // The PCI Data Structure must be DWORD aligned.\r
94020bb4 239 //\r
240 if (EfiRomHeader->PcirOffset == 0 ||\r
241 (EfiRomHeader->PcirOffset & 3) != 0 ||\r
242 RomBarOffset - (UINTN)RomBar + EfiRomHeader->PcirOffset + sizeof (PCI_DATA_STRUCTURE) > RomSize) {\r
243 break;\r
244 }\r
245\r
5d73d92f 246 Pcir = (PCI_DATA_STRUCTURE *) (UINTN) (RomBarOffset + EfiRomHeader->PcirOffset);\r
94020bb4 247 //\r
248 // If a valid signature is not present in the PCI Data Structure, no further images can be located.\r
249 //\r
250 if (Pcir->Signature != PCI_DATA_STRUCTURE_SIGNATURE) {\r
251 break;\r
252 }\r
5d73d92f 253 ImageSize = Pcir->ImageLength * 512;\r
94020bb4 254 if (RomBarOffset - (UINTN)RomBar + ImageSize > RomSize) {\r
255 break;\r
256 }\r
5d73d92f 257\r
258 if ((Pcir->CodeType == PCI_CODE_TYPE_EFI_IMAGE) &&\r
94020bb4 259 (EfiRomHeader->EfiSignature == EFI_PCI_EXPANSION_ROM_HEADER_EFISIGNATURE) &&\r
260 ((EfiRomHeader->EfiSubsystem == EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER) ||\r
261 (EfiRomHeader->EfiSubsystem == EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER))) {\r
262\r
263 ImageOffset = EfiRomHeader->EfiImageHeaderOffset;\r
264 InitializationSize = EfiRomHeader->InitializationSize * 512;\r
5d73d92f 265\r
94020bb4 266 if (InitializationSize <= ImageSize && ImageOffset < InitializationSize) {\r
5d73d92f 267\r
268 ImageBuffer = (VOID *) (UINTN) (RomBarOffset + ImageOffset);\r
94020bb4 269 ImageLength = InitializationSize - ImageOffset;\r
5d73d92f 270 DecompressedImageBuffer = NULL;\r
271\r
272 //\r
273 // decompress here if needed\r
274 //\r
275 SkipImage = FALSE;\r
276 if (EfiRomHeader->CompressionType > EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED) {\r
277 SkipImage = TRUE;\r
278 }\r
279\r
280 if (EfiRomHeader->CompressionType == EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED) {\r
281 Status = gBS->LocateProtocol (&gEfiDecompressProtocolGuid, NULL, (VOID**)&Decompress);\r
282 ASSERT_EFI_ERROR(Status);\r
283 if (EFI_ERROR (Status)) {\r
284 SkipImage = TRUE;\r
285 } else {\r
286 SkipImage = TRUE;\r
287 Status = Decompress->GetInfo (\r
288 Decompress,\r
289 ImageBuffer,\r
290 ImageLength,\r
291 &DestinationSize,\r
292 &ScratchSize\r
293 );\r
294 if (!EFI_ERROR (Status)) {\r
3737ac2b 295 DecompressedImageBuffer = AllocateZeroPool (DestinationSize);\r
5d73d92f 296 if (ImageBuffer != NULL) {\r
3737ac2b 297 Scratch = AllocateZeroPool (ScratchSize);\r
5d73d92f 298 if (Scratch != NULL) {\r
299 Status = Decompress->Decompress (\r
300 Decompress,\r
301 ImageBuffer,\r
302 ImageLength,\r
303 DecompressedImageBuffer,\r
304 DestinationSize,\r
305 Scratch,\r
306 ScratchSize\r
307 );\r
308 if (!EFI_ERROR (Status)) {\r
309 ImageBuffer = DecompressedImageBuffer;\r
310 ImageLength = DestinationSize;\r
311 SkipImage = FALSE;\r
312 }\r
313\r
314 FreePool (Scratch);\r
315 }\r
316 }\r
317 }\r
318 }\r
319 }\r
320\r
321 if (!SkipImage) {\r
322 //\r
323 // load image and start image\r
324 //\r
325 UnicodeSPrint (RomFileName, sizeof (RomFileName), L"%s[%d]", FileName, ImageIndex);\r
326 FilePath = FileDevicePath (NULL, RomFileName);\r
327\r
328 Status = gBS->LoadImage (\r
329 TRUE,\r
330 gImageHandle,\r
331 FilePath,\r
332 ImageBuffer,\r
333 ImageLength,\r
334 &ImageHandle\r
335 );\r
336 if (EFI_ERROR (Status)) {\r
ba0014b9 337 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_LOADPCIROM_LOAD_FAIL), gShellDebug1HiiHandle, L"loadpcirom", FileName, ImageIndex);\r
5d73d92f 338// PrintToken (STRING_TOKEN (STR_LOADPCIROM_LOAD_IMAGE_ERROR), HiiHandle, ImageIndex, Status);\r
339 } else {\r
340 Status = gBS->StartImage (ImageHandle, NULL, NULL);\r
341 if (EFI_ERROR (Status)) {\r
ba0014b9 342 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_LOADPCIROM_START_FAIL), gShellDebug1HiiHandle, L"loadpcirom", FileName, ImageIndex);\r
5d73d92f 343// PrintToken (STRING_TOKEN (STR_LOADPCIROM_START_IMAGE), HiiHandle, ImageIndex, Status);\r
344 } else {\r
3737ac2b 345 ReturnStatus = Status;\r
5d73d92f 346 }\r
347 }\r
348 }\r
349\r
350 if (DecompressedImageBuffer != NULL) {\r
351 FreePool (DecompressedImageBuffer);\r
352 }\r
353\r
354 }\r
355 }\r
356\r
357 RomBarOffset = RomBarOffset + ImageSize;\r
358 ImageIndex++;\r
359 } while (((Pcir->Indicator & 0x80) == 0x00) && ((RomBarOffset - (UINTN) RomBar) < RomSize));\r
360\r
3737ac2b 361 return ReturnStatus;\r
5d73d92f 362}\r
363\r
3737ac2b 364/**\r
365 Connects all available drives and controllers.\r
366\r
367 @retval EFI_SUCCESS The operation was successful.\r
368 @retval EFI_ABORTED The abort mechanism was received.\r
369**/\r
5d73d92f 370EFI_STATUS\r
371LoadPciRomConnectAllDriversToAllControllers (\r
372 VOID\r
373 )\r
5d73d92f 374{\r
375 EFI_STATUS Status;\r
5d73d92f 376 UINTN HandleCount;\r
377 EFI_HANDLE *HandleBuffer;\r
fc41b97f
RN
378 UINTN Index;\r
379\r
380 Status = gBS->LocateHandleBuffer (\r
381 AllHandles,\r
382 NULL,\r
383 NULL,\r
384 &HandleCount,\r
385 &HandleBuffer\r
386 );\r
5d73d92f 387 if (EFI_ERROR (Status)) {\r
388 return Status;\r
389 }\r
390\r
fc41b97f 391 for (Index = 0; Index < HandleCount; Index++) {\r
5d73d92f 392 if (ShellGetExecutionBreakFlag ()) {\r
393 Status = EFI_ABORTED;\r
fc41b97f 394 break;\r
5d73d92f 395 }\r
fc41b97f
RN
396 gBS->ConnectController (HandleBuffer[Index], NULL, NULL, TRUE);\r
397 }\r
5d73d92f 398\r
fc41b97f 399 if (HandleBuffer != NULL) {\r
5d73d92f 400 FreePool (HandleBuffer);\r
5d73d92f 401 }\r
5d73d92f 402 return Status;\r
403}\r