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