]> git.proxmox.com Git - mirror_edk2.git/blob - ShellPkg/Library/UefiShellDebug1CommandsLib/LoadPciRom.c
8f1015800003c1851d950c208865d6a8b54a9db1
[mirror_edk2.git] / ShellPkg / Library / UefiShellDebug1CommandsLib / LoadPciRom.c
1 /** @file
2 Main file for LoadPciRom shell Debug1 function.
3
4 Copyright (c) 2005 - 2011, 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
225 ImageIndex = 0;
226 ReturnStatus = EFI_NOT_FOUND;
227 RomBarOffset = (UINTN) RomBar;
228
229 do {
230
231 EfiRomHeader = (EFI_PCI_EXPANSION_ROM_HEADER *) (UINTN) RomBarOffset;
232
233 if (EfiRomHeader->Signature != 0xaa55) {
234 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_LOADPCIROM_CORRUPT), gShellDebug1HiiHandle, FileName, ImageIndex);
235 // PrintToken (STRING_TOKEN (STR_LOADPCIROM_IMAGE_CORRUPT), HiiHandle, ImageIndex);
236 return ReturnStatus;
237 }
238
239 Pcir = (PCI_DATA_STRUCTURE *) (UINTN) (RomBarOffset + EfiRomHeader->PcirOffset);
240 ImageSize = Pcir->ImageLength * 512;
241
242 if ((Pcir->CodeType == PCI_CODE_TYPE_EFI_IMAGE) &&
243 (EfiRomHeader->EfiSignature == EFI_PCI_EXPANSION_ROM_HEADER_EFISIGNATURE)
244 ) {
245
246 if ((EfiRomHeader->EfiSubsystem == EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER) ||
247 (EfiRomHeader->EfiSubsystem == EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER)
248 ) {
249 ImageOffset = EfiRomHeader->EfiImageHeaderOffset;
250 ImageSize = EfiRomHeader->InitializationSize * 512;
251
252 ImageBuffer = (VOID *) (UINTN) (RomBarOffset + ImageOffset);
253 ImageLength = ImageSize - ImageOffset;
254 DecompressedImageBuffer = NULL;
255
256 //
257 // decompress here if needed
258 //
259 SkipImage = FALSE;
260 if (EfiRomHeader->CompressionType > EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED) {
261 SkipImage = TRUE;
262 }
263
264 if (EfiRomHeader->CompressionType == EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED) {
265 Status = gBS->LocateProtocol (&gEfiDecompressProtocolGuid, NULL, (VOID**)&Decompress);
266 ASSERT_EFI_ERROR(Status);
267 if (EFI_ERROR (Status)) {
268 SkipImage = TRUE;
269 } else {
270 SkipImage = TRUE;
271 Status = Decompress->GetInfo (
272 Decompress,
273 ImageBuffer,
274 ImageLength,
275 &DestinationSize,
276 &ScratchSize
277 );
278 if (!EFI_ERROR (Status)) {
279 DecompressedImageBuffer = AllocateZeroPool (DestinationSize);
280 if (ImageBuffer != NULL) {
281 Scratch = AllocateZeroPool (ScratchSize);
282 if (Scratch != NULL) {
283 Status = Decompress->Decompress (
284 Decompress,
285 ImageBuffer,
286 ImageLength,
287 DecompressedImageBuffer,
288 DestinationSize,
289 Scratch,
290 ScratchSize
291 );
292 if (!EFI_ERROR (Status)) {
293 ImageBuffer = DecompressedImageBuffer;
294 ImageLength = DestinationSize;
295 SkipImage = FALSE;
296 }
297
298 FreePool (Scratch);
299 }
300 }
301 }
302 }
303 }
304
305 if (!SkipImage) {
306 //
307 // load image and start image
308 //
309 UnicodeSPrint (RomFileName, sizeof (RomFileName), L"%s[%d]", FileName, ImageIndex);
310 FilePath = FileDevicePath (NULL, RomFileName);
311
312 Status = gBS->LoadImage (
313 TRUE,
314 gImageHandle,
315 FilePath,
316 ImageBuffer,
317 ImageLength,
318 &ImageHandle
319 );
320 if (EFI_ERROR (Status)) {
321 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_LOADPCIROM_LOAD_FAIL), gShellDebug1HiiHandle, FileName, ImageIndex, Status);
322 // PrintToken (STRING_TOKEN (STR_LOADPCIROM_LOAD_IMAGE_ERROR), HiiHandle, ImageIndex, Status);
323 } else {
324 Status = gBS->StartImage (ImageHandle, NULL, NULL);
325 if (EFI_ERROR (Status)) {
326 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_LOADPCIROM_START_FAIL), gShellDebug1HiiHandle, FileName, ImageIndex, Status);
327 // PrintToken (STRING_TOKEN (STR_LOADPCIROM_START_IMAGE), HiiHandle, ImageIndex, Status);
328 } else {
329 ReturnStatus = Status;
330 }
331 }
332 }
333
334 if (DecompressedImageBuffer != NULL) {
335 FreePool (DecompressedImageBuffer);
336 }
337
338 }
339 }
340
341 RomBarOffset = RomBarOffset + ImageSize;
342 ImageIndex++;
343 } while (((Pcir->Indicator & 0x80) == 0x00) && ((RomBarOffset - (UINTN) RomBar) < RomSize));
344
345 return ReturnStatus;
346 }
347
348 /**
349 Connects all available drives and controllers.
350
351 @retval EFI_SUCCESS The operation was successful.
352 @retval EFI_ABORTED The abort mechanism was received.
353 **/
354 EFI_STATUS
355 EFIAPI
356 LoadPciRomConnectAllDriversToAllControllers (
357 VOID
358 )
359
360 {
361 EFI_STATUS Status;
362 UINTN AllHandleCount;
363 EFI_HANDLE *AllHandleBuffer;
364 UINTN Index;
365 UINTN HandleCount;
366 EFI_HANDLE *HandleBuffer;
367 UINTN *HandleType;
368 UINTN HandleIndex;
369 BOOLEAN Parent;
370 BOOLEAN Device;
371
372 Status = gBS->LocateHandleBuffer(
373 AllHandles,
374 NULL,
375 NULL,
376 &AllHandleCount,
377 &AllHandleBuffer
378 );
379 if (EFI_ERROR (Status)) {
380 return Status;
381 }
382
383 for (Index = 0; Index < AllHandleCount; Index++) {
384 if (ShellGetExecutionBreakFlag ()) {
385 Status = EFI_ABORTED;
386 goto Done;
387 }
388 //
389 // Scan the handle database
390 //
391 Status = ParseHandleDatabaseByRelationshipWithType(
392 NULL,
393 AllHandleBuffer[Index],
394 &HandleCount,
395 &HandleBuffer,
396 &HandleType
397 );
398 /*
399 Status = LibScanHandleDatabase (
400 NULL,
401 NULL,
402 AllHandleBuffer[Index],
403 NULL,
404 &HandleCount,
405 &HandleBuffer,
406 &HandleType
407 );
408 */
409 if (EFI_ERROR (Status)) {
410 goto Done;
411 }
412
413 Device = TRUE;
414 if ((HandleType[Index] & HR_DRIVER_BINDING_HANDLE) != 0) {
415 Device = FALSE;
416 }
417
418 if ((HandleType[Index] & HR_IMAGE_HANDLE) != 0) {
419 Device = FALSE;
420 }
421
422 if (Device) {
423 Parent = FALSE;
424 for (HandleIndex = 0; HandleIndex < HandleCount; HandleIndex++) {
425 if ((HandleType[HandleIndex] & HR_PARENT_HANDLE) != 0) {
426 Parent = TRUE;
427 }
428 }
429
430 if (!Parent) {
431 if ((HandleType[Index] & HR_DEVICE_HANDLE) != 0) {
432 Status = gBS->ConnectController (
433 AllHandleBuffer[Index],
434 NULL,
435 NULL,
436 TRUE
437 );
438 }
439 }
440 }
441
442 FreePool (HandleBuffer);
443 FreePool (HandleType);
444 }
445
446 Done:
447 FreePool (AllHandleBuffer);
448 return Status;
449 }