]> git.proxmox.com Git - mirror_edk2.git/blob - ShellPkg/Library/UefiShellDebug1CommandsLib/LoadPciRom.c
Add "Debug1" profile (all but Edit and HexEdit commands)
[mirror_edk2.git] / ShellPkg / Library / UefiShellDebug1CommandsLib / LoadPciRom.c
1 /** @file
2 Main file for LoadPciRom shell Debug1 function.
3
4 Copyright (c) 2005 - 2010, 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 EFI_STATUS
22 EFIAPI
23 LoadPciRomConnectAllDriversToAllControllers (
24 VOID
25 );
26
27 EFI_STATUS
28 EFIAPI
29 InitializeLoadPciRom (
30 IN EFI_HANDLE ImageHandle,
31 IN EFI_SYSTEM_TABLE *SystemTable
32 );
33
34 EFI_STATUS
35 EFIAPI
36 LoadEfiDriversFromRomImage (
37 VOID *RomBar,
38 UINTN RomSize,
39 CONST CHAR16 *FileName
40 );
41
42 STATIC CONST SHELL_PARAM_ITEM ParamList[] = {
43 {L"-nc", TypeFlag},
44 {NULL, TypeMax}
45 };
46
47 SHELL_STATUS
48 EFIAPI
49 ShellCommandRunLoadPciRom (
50 IN EFI_HANDLE ImageHandle,
51 IN EFI_SYSTEM_TABLE *SystemTable
52 )
53 {
54 EFI_SHELL_FILE_INFO *FileList;
55 UINTN SourceSize;
56 UINT8 *File1Buffer;
57 EFI_STATUS Status;
58 LIST_ENTRY *Package;
59 CHAR16 *ProblemParam;
60 SHELL_STATUS ShellStatus;
61 BOOLEAN Connect;
62 CONST CHAR16 *Param;
63 UINTN ParamCount;
64 EFI_SHELL_FILE_INFO *Node;
65 //
66 // Local variable initializations
67 //
68 File1Buffer = NULL;
69 ShellStatus = SHELL_SUCCESS;
70 FileList = NULL;
71
72
73 //
74 // verify number of arguments
75 //
76 Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE);
77 if (EFI_ERROR(Status)) {
78 if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
79 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDebug1HiiHandle, ProblemParam);
80 FreePool(ProblemParam);
81 ShellStatus = SHELL_INVALID_PARAMETER;
82 } else {
83 ASSERT(FALSE);
84 }
85 } else {
86 if (ShellCommandLineGetCount(Package) < 1) {
87 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellDebug1HiiHandle);
88 ShellStatus = SHELL_INVALID_PARAMETER;
89 } else {
90 if (!ShellCommandLineGetFlag(Package, L"-nc")) {
91 Connect = FALSE;
92 } else {
93 Connect = TRUE;
94 }
95
96 //
97 // get a list with each file specified by parameters
98 // if parameter is a directory then add all the files below it to the list
99 //
100 for ( ParamCount = 1, Param = ShellCommandLineGetRawValue(Package, ParamCount)
101 ; Param != NULL
102 ; ParamCount++, Param = ShellCommandLineGetRawValue(Package, ParamCount)
103 ){
104 Status = ShellOpenFileMetaArg((CHAR16*)Param, EFI_FILE_MODE_WRITE|EFI_FILE_MODE_READ, &FileList);
105 if (EFI_ERROR(Status)) {
106 ShellStatus = SHELL_ACCESS_DENIED;
107 break;
108 }
109 }
110 if (FileList == NULL || IsListEmpty(&FileList->Link)) {
111 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellDebug1HiiHandle);
112 } else if (ShellStatus == SHELL_SUCCESS) {
113
114
115 //
116 // loop through the list and make sure we are not aborting...
117 //
118 for ( Node = (EFI_SHELL_FILE_INFO*)GetFirstNode(&FileList->Link)
119 ; !IsNull(&FileList->Link, &Node->Link) && !ShellGetExecutionBreakFlag()
120 ; Node = (EFI_SHELL_FILE_INFO*)GetNextNode(&FileList->Link, &Node->Link)
121 ){
122 if (EFI_ERROR(Node->Status)){
123 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_FILE_OPEN_FAIL), gShellDebug1HiiHandle, Node->FullName);
124 ShellStatus = SHELL_INVALID_PARAMETER;
125 continue;
126 }
127 if (FileHandleIsDirectory(Node->Handle) == EFI_SUCCESS) {
128 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_FILE_NOT_DIR), gShellDebug1HiiHandle, Node->FullName);
129 ShellStatus = SHELL_INVALID_PARAMETER;
130 continue;
131 }
132 SourceSize = (UINTN) Node->Info->FileSize;
133 File1Buffer = AllocatePool (SourceSize);
134 ASSERT(File1Buffer != NULL);
135 Status = gEfiShellProtocol->ReadFile(Node->Handle, &SourceSize, File1Buffer);
136 if (EFI_ERROR(Status)) {
137 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_READ_FAIL), gShellDebug1HiiHandle, Node->FullName);
138 ShellStatus = SHELL_INVALID_PARAMETER;
139 } else {
140 Status = LoadEfiDriversFromRomImage (
141 File1Buffer,
142 SourceSize,
143 Node->FullName
144 );
145
146 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_LOAD_PCI_ROM_RES), gShellDebug1HiiHandle, Node->FullName, Status);
147 }
148 FreePool(File1Buffer);
149 }
150 }
151 if (FileList != NULL && !IsListEmpty(&FileList->Link)) {
152 Status = ShellCloseFileMetaArg(&FileList);
153 }
154 FileList = NULL;
155
156 if (Connect) {
157 Status = LoadPciRomConnectAllDriversToAllControllers ();
158 }
159 }
160 }
161
162 return (ShellStatus);
163 }
164
165 EFI_STATUS
166 LoadEfiDriversFromRomImage (
167 VOID *RomBar,
168 UINTN RomSize,
169 CONST CHAR16 *FileName
170 )
171 /*++
172
173 Routine Description:
174 Command entry point.
175
176 Arguments:
177
178 RomBar - Rom
179 RomSize - Rom size
180 FileName - The file name
181
182 Returns:
183 EFI_SUCCESS - The command completed successfully
184 EFI_INVALID_PARAMETER - Command usage error
185 EFI_UNSUPPORTED - Protocols unsupported
186 EFI_OUT_OF_RESOURCES - Out of memory
187 Other value - Unknown error
188
189 **/
190 {
191 EFI_PCI_EXPANSION_ROM_HEADER *EfiRomHeader;
192 PCI_DATA_STRUCTURE *Pcir;
193 UINTN ImageIndex;
194 UINTN RomBarOffset;
195 UINT32 ImageSize;
196 UINT16 ImageOffset;
197 EFI_HANDLE ImageHandle;
198 EFI_STATUS Status;
199 EFI_STATUS retStatus;
200 CHAR16 RomFileName[280];
201 EFI_DEVICE_PATH_PROTOCOL *FilePath;
202 BOOLEAN SkipImage;
203 UINT32 DestinationSize;
204 UINT32 ScratchSize;
205 UINT8 *Scratch;
206 VOID *ImageBuffer;
207 VOID *DecompressedImageBuffer;
208 UINT32 ImageLength;
209 EFI_DECOMPRESS_PROTOCOL *Decompress;
210
211 ImageIndex = 0;
212 retStatus = EFI_NOT_FOUND;
213 RomBarOffset = (UINTN) RomBar;
214
215 do {
216
217 EfiRomHeader = (EFI_PCI_EXPANSION_ROM_HEADER *) (UINTN) RomBarOffset;
218
219 if (EfiRomHeader->Signature != 0xaa55) {
220 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_LOADPCIROM_CORRUPT), gShellDebug1HiiHandle, FileName, ImageIndex);
221 // PrintToken (STRING_TOKEN (STR_LOADPCIROM_IMAGE_CORRUPT), HiiHandle, ImageIndex);
222 return retStatus;
223 }
224
225 Pcir = (PCI_DATA_STRUCTURE *) (UINTN) (RomBarOffset + EfiRomHeader->PcirOffset);
226 ImageSize = Pcir->ImageLength * 512;
227
228 if ((Pcir->CodeType == PCI_CODE_TYPE_EFI_IMAGE) &&
229 (EfiRomHeader->EfiSignature == EFI_PCI_EXPANSION_ROM_HEADER_EFISIGNATURE)
230 ) {
231
232 if ((EfiRomHeader->EfiSubsystem == EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER) ||
233 (EfiRomHeader->EfiSubsystem == EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER)
234 ) {
235 ImageOffset = EfiRomHeader->EfiImageHeaderOffset;
236 ImageSize = EfiRomHeader->InitializationSize * 512;
237
238 ImageBuffer = (VOID *) (UINTN) (RomBarOffset + ImageOffset);
239 ImageLength = ImageSize - ImageOffset;
240 DecompressedImageBuffer = NULL;
241
242 //
243 // decompress here if needed
244 //
245 SkipImage = FALSE;
246 if (EfiRomHeader->CompressionType > EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED) {
247 SkipImage = TRUE;
248 }
249
250 if (EfiRomHeader->CompressionType == EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED) {
251 Status = gBS->LocateProtocol (&gEfiDecompressProtocolGuid, NULL, (VOID**)&Decompress);
252 ASSERT_EFI_ERROR(Status);
253 if (EFI_ERROR (Status)) {
254 SkipImage = TRUE;
255 } else {
256 SkipImage = TRUE;
257 Status = Decompress->GetInfo (
258 Decompress,
259 ImageBuffer,
260 ImageLength,
261 &DestinationSize,
262 &ScratchSize
263 );
264 if (!EFI_ERROR (Status)) {
265 DecompressedImageBuffer = AllocatePool (DestinationSize);
266 if (ImageBuffer != NULL) {
267 Scratch = AllocatePool (ScratchSize);
268 if (Scratch != NULL) {
269 Status = Decompress->Decompress (
270 Decompress,
271 ImageBuffer,
272 ImageLength,
273 DecompressedImageBuffer,
274 DestinationSize,
275 Scratch,
276 ScratchSize
277 );
278 if (!EFI_ERROR (Status)) {
279 ImageBuffer = DecompressedImageBuffer;
280 ImageLength = DestinationSize;
281 SkipImage = FALSE;
282 }
283
284 FreePool (Scratch);
285 }
286 }
287 }
288 }
289 }
290
291 if (!SkipImage) {
292 //
293 // load image and start image
294 //
295 UnicodeSPrint (RomFileName, sizeof (RomFileName), L"%s[%d]", FileName, ImageIndex);
296 FilePath = FileDevicePath (NULL, RomFileName);
297
298 Status = gBS->LoadImage (
299 TRUE,
300 gImageHandle,
301 FilePath,
302 ImageBuffer,
303 ImageLength,
304 &ImageHandle
305 );
306 if (EFI_ERROR (Status)) {
307 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_LOADPCIROM_LOAD_FAIL), gShellDebug1HiiHandle, FileName, ImageIndex, Status);
308 // PrintToken (STRING_TOKEN (STR_LOADPCIROM_LOAD_IMAGE_ERROR), HiiHandle, ImageIndex, Status);
309 } else {
310 Status = gBS->StartImage (ImageHandle, NULL, NULL);
311 if (EFI_ERROR (Status)) {
312 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_LOADPCIROM_START_FAIL), gShellDebug1HiiHandle, FileName, ImageIndex, Status);
313 // PrintToken (STRING_TOKEN (STR_LOADPCIROM_START_IMAGE), HiiHandle, ImageIndex, Status);
314 } else {
315 retStatus = Status;
316 }
317 }
318 }
319
320 if (DecompressedImageBuffer != NULL) {
321 FreePool (DecompressedImageBuffer);
322 }
323
324 }
325 }
326
327 RomBarOffset = RomBarOffset + ImageSize;
328 ImageIndex++;
329 } while (((Pcir->Indicator & 0x80) == 0x00) && ((RomBarOffset - (UINTN) RomBar) < RomSize));
330
331 return retStatus;
332 }
333
334 EFI_STATUS
335 LoadPciRomConnectAllDriversToAllControllers (
336 VOID
337 )
338
339 {
340 EFI_STATUS Status;
341 UINTN AllHandleCount;
342 EFI_HANDLE *AllHandleBuffer;
343 UINTN Index;
344 UINTN HandleCount;
345 EFI_HANDLE *HandleBuffer;
346 UINTN *HandleType;
347 UINTN HandleIndex;
348 BOOLEAN Parent;
349 BOOLEAN Device;
350
351 Status = gBS->LocateHandleBuffer(
352 AllHandles,
353 NULL,
354 NULL,
355 &AllHandleCount,
356 &AllHandleBuffer
357 );
358 if (EFI_ERROR (Status)) {
359 return Status;
360 }
361
362 for (Index = 0; Index < AllHandleCount; Index++) {
363 if (ShellGetExecutionBreakFlag ()) {
364 Status = EFI_ABORTED;
365 goto Done;
366 }
367 //
368 // Scan the handle database
369 //
370 Status = ParseHandleDatabaseByRelationshipWithType(
371 NULL,
372 AllHandleBuffer[Index],
373 &HandleCount,
374 &HandleBuffer,
375 &HandleType
376 );
377 /*
378 Status = LibScanHandleDatabase (
379 NULL,
380 NULL,
381 AllHandleBuffer[Index],
382 NULL,
383 &HandleCount,
384 &HandleBuffer,
385 &HandleType
386 );
387 */
388 if (EFI_ERROR (Status)) {
389 goto Done;
390 }
391
392 Device = TRUE;
393 if ((HandleType[Index] & HR_DRIVER_BINDING_HANDLE) != 0) {
394 Device = FALSE;
395 }
396
397 if ((HandleType[Index] & HR_IMAGE_HANDLE) != 0) {
398 Device = FALSE;
399 }
400
401 if (Device) {
402 Parent = FALSE;
403 for (HandleIndex = 0; HandleIndex < HandleCount; HandleIndex++) {
404 if ((HandleType[HandleIndex] & HR_PARENT_HANDLE) != 0) {
405 Parent = TRUE;
406 }
407 }
408
409 if (!Parent) {
410 if ((HandleType[Index] & HR_DEVICE_HANDLE) != 0) {
411 Status = gBS->ConnectController (
412 AllHandleBuffer[Index],
413 NULL,
414 NULL,
415 TRUE
416 );
417 }
418 }
419 }
420
421 FreePool (HandleBuffer);
422 FreePool (HandleType);
423 }
424
425 Done:
426 FreePool (AllHandleBuffer);
427 return Status;
428 }