]> git.proxmox.com Git - mirror_edk2.git/blame - DuetPkg/PciBusNoEnumerationDxe/PciOptionRomSupport.c
BaseTools/BinToPcd: Fix Python 2.7.x compatibility issue
[mirror_edk2.git] / DuetPkg / PciBusNoEnumerationDxe / PciOptionRomSupport.c
CommitLineData
10590588 1/*++\r
2\r
94020bb4 3Copyright (c) 2005 - 2012, Intel Corporation. All rights reserved.<BR>\r
b1f700a8 4This program and the accompanying materials \r
10590588 5are licensed and made available under the terms and conditions of the BSD License \r
6which accompanies this distribution. The full text of the license may be found at \r
7http://opensource.org/licenses/bsd-license.php \r
8 \r
9THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
10WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
11\r
12Module Name:\r
13\r
14 PciOptionRomSupport.c\r
15 \r
16Abstract:\r
17\r
18 PCI Bus Driver\r
19\r
20Revision History\r
21\r
22--*/\r
23\r
24#include "PciBus.h"\r
25\r
26\r
27EFI_STATUS\r
28RomDecode (\r
29 IN PCI_IO_DEVICE *PciDevice,\r
30 IN UINT8 RomBarIndex,\r
31 IN UINT32 RomBar,\r
32 IN BOOLEAN Enable\r
33);\r
34\r
35EFI_STATUS\r
36GetOpRomInfo (\r
37 IN PCI_IO_DEVICE *PciIoDevice\r
38 )\r
39/*++\r
40\r
41Routine Description:\r
42\r
43Arguments:\r
44\r
45Returns:\r
46\r
47--*/\r
48{\r
49 UINT8 RomBarIndex;\r
50 UINT32 AllOnes;\r
51 UINT64 Address;\r
52 EFI_STATUS Status;\r
53 UINT8 Bus;\r
54 UINT8 Device;\r
55 UINT8 Function;\r
56 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;\r
57\r
58 Bus = PciIoDevice->BusNumber;\r
59 Device = PciIoDevice->DeviceNumber;\r
60 Function = PciIoDevice->FunctionNumber;\r
61\r
62 PciRootBridgeIo = PciIoDevice->PciRootBridgeIo;\r
63\r
64 //\r
65 // offset is 0x30 if is not ppb\r
66 //\r
67\r
68 //\r
69 // 0x30\r
70 //\r
bc14bdb3 71 RomBarIndex = PCI_EXPANSION_ROM_BASE;\r
10590588 72\r
73 if (IS_PCI_BRIDGE (&PciIoDevice->Pci)) {\r
74 //\r
75 // if is ppb\r
76 //\r
77\r
78 //\r
79 // 0x38\r
80 //\r
81 RomBarIndex = PCI_BRIDGE_ROMBAR;\r
82 }\r
83 //\r
84 // the bit0 is 0 to prevent the enabling of the Rom address decoder\r
85 //\r
86 AllOnes = 0xfffffffe;\r
87 Address = EFI_PCI_ADDRESS (Bus, Device, Function, RomBarIndex);\r
88\r
89 Status = PciRootBridgeIo->Pci.Write (\r
90 PciRootBridgeIo,\r
91 EfiPciWidthUint32,\r
92 Address,\r
93 1,\r
94 &AllOnes\r
95 );\r
96 if (EFI_ERROR (Status)) {\r
97 return Status;\r
98 }\r
99 \r
100 //\r
101 // read back\r
102 //\r
103 Status = PciRootBridgeIo->Pci.Read (\r
104 PciRootBridgeIo,\r
105 EfiPciWidthUint32,\r
106 Address,\r
107 1,\r
108 &AllOnes\r
109 );\r
110 if (EFI_ERROR (Status)) {\r
111 return Status;\r
112 }\r
113\r
114 //\r
115 // Bits [1, 10] are reserved\r
116 //\r
117 AllOnes &= 0xFFFFF800;\r
118 if ((AllOnes == 0) || (AllOnes == 0xFFFFF800)) {\r
119 return EFI_NOT_FOUND;\r
120 }\r
121 \r
122 DEBUG ((EFI_D_ERROR, "PCIBUS: GetOpRomInfo: OPROM detected!\n"));\r
123 DEBUG ((EFI_D_ERROR, "PCIBUS: GetOpRomInfo: B-%x, D-%x, F-%x\n", (UINTN)Bus, (UINTN)Device, (UINTN)Function));\r
124\r
125 PciIoDevice->RomSize = (UINT64) ((~AllOnes) + 1);\r
126 return EFI_SUCCESS;\r
127}\r
128\r
129EFI_STATUS\r
130LoadOpRomImage (\r
131 IN PCI_IO_DEVICE *PciDevice,\r
132 IN UINT64 ReservedMemoryBase\r
133 )\r
134/*++\r
135\r
136Routine Description:\r
137 \r
138 Load option rom image for specified PCI device\r
139\r
140Arguments:\r
141\r
142Returns:\r
143\r
144--*/\r
145{\r
146 UINT8 RomBarIndex;\r
147 UINT8 Indicator;\r
148 UINT16 OffsetPcir;\r
149 UINT32 RomBarOffset;\r
150 UINT32 RomBar;\r
10590588 151 EFI_STATUS retStatus;\r
152 BOOLEAN FirstCheck;\r
153 UINT8 *Image;\r
154 PCI_EXPANSION_ROM_HEADER *RomHeader;\r
155 PCI_DATA_STRUCTURE *RomPcir;\r
156 UINT64 RomSize;\r
157 UINT64 RomImageSize;\r
94020bb4 158 UINT32 LegacyImageLength;\r
10590588 159 UINT8 *RomInMemory;\r
160 UINT8 CodeType;\r
161\r
162 RomSize = PciDevice->RomSize;\r
163\r
164 Indicator = 0;\r
165 RomImageSize = 0;\r
166 RomInMemory = NULL;\r
10590588 167 CodeType = 0xFF;\r
168\r
169 //\r
170 // Get the RomBarIndex\r
171 //\r
172\r
173 //\r
174 // 0x30\r
175 //\r
bc14bdb3 176 RomBarIndex = PCI_EXPANSION_ROM_BASE;\r
10590588 177 if (IS_PCI_BRIDGE (&(PciDevice->Pci))) {\r
178 //\r
179 // if is ppb\r
180 //\r
181\r
182 //\r
183 // 0x38\r
184 //\r
185 RomBarIndex = PCI_BRIDGE_ROMBAR;\r
186 }\r
187 //\r
188 // Allocate memory for Rom header and PCIR\r
189 //\r
190 RomHeader = AllocatePool (sizeof (PCI_EXPANSION_ROM_HEADER));\r
191 if (RomHeader == NULL) {\r
192 return EFI_OUT_OF_RESOURCES;\r
193 }\r
194\r
195 RomPcir = AllocatePool (sizeof (PCI_DATA_STRUCTURE));\r
196 if (RomPcir == NULL) {\r
197 gBS->FreePool (RomHeader);\r
198 return EFI_OUT_OF_RESOURCES;\r
199 }\r
200\r
201 RomBar = (UINT32)ReservedMemoryBase; \r
202\r
203 //\r
204 // Enable RomBar\r
205 //\r
206 RomDecode (PciDevice, RomBarIndex, RomBar, TRUE);\r
207\r
208 RomBarOffset = RomBar;\r
209 retStatus = EFI_NOT_FOUND;\r
210 FirstCheck = TRUE;\r
94020bb4 211 LegacyImageLength = 0;\r
10590588 212\r
213 do {\r
214 PciDevice->PciRootBridgeIo->Mem.Read (\r
215 PciDevice->PciRootBridgeIo,\r
216 EfiPciWidthUint8,\r
217 RomBarOffset,\r
218 sizeof (PCI_EXPANSION_ROM_HEADER),\r
219 (UINT8 *) RomHeader\r
220 );\r
221\r
222 if (RomHeader->Signature != PCI_EXPANSION_ROM_HEADER_SIGNATURE) {\r
223 RomBarOffset = RomBarOffset + 512;\r
224 if (FirstCheck) {\r
225 break;\r
226 } else {\r
227 RomImageSize = RomImageSize + 512;\r
228 continue;\r
229 }\r
230 }\r
231\r
232 FirstCheck = FALSE;\r
233 OffsetPcir = RomHeader->PcirOffset;\r
94020bb4 234 //\r
235 // If the pointer to the PCI Data Structure is invalid, no further images can be located. \r
236 // The PCI Data Structure must be DWORD aligned. \r
237 //\r
238 if (OffsetPcir == 0 ||\r
239 (OffsetPcir & 3) != 0 ||\r
240 RomImageSize + OffsetPcir + sizeof (PCI_DATA_STRUCTURE) > RomSize) {\r
241 break;\r
242 }\r
10590588 243 PciDevice->PciRootBridgeIo->Mem.Read (\r
244 PciDevice->PciRootBridgeIo,\r
245 EfiPciWidthUint8,\r
246 RomBarOffset + OffsetPcir,\r
247 sizeof (PCI_DATA_STRUCTURE),\r
248 (UINT8 *) RomPcir\r
249 );\r
94020bb4 250 //\r
251 // If a valid signature is not present in the PCI Data Structure, no further images can be located.\r
252 //\r
253 if (RomPcir->Signature != PCI_DATA_STRUCTURE_SIGNATURE) {\r
254 break;\r
255 }\r
256 if (RomImageSize + RomPcir->ImageLength * 512 > RomSize) {\r
257 break;\r
258 }\r
10590588 259 if (RomPcir->CodeType == PCI_CODE_TYPE_PCAT_IMAGE) {\r
260 CodeType = PCI_CODE_TYPE_PCAT_IMAGE;\r
94020bb4 261 LegacyImageLength = ((UINT32)((EFI_LEGACY_EXPANSION_ROM_HEADER *)RomHeader)->Size512) * 512;\r
10590588 262 }\r
263 Indicator = RomPcir->Indicator;\r
264 RomImageSize = RomImageSize + RomPcir->ImageLength * 512;\r
265 RomBarOffset = RomBarOffset + RomPcir->ImageLength * 512;\r
266 } while (((Indicator & 0x80) == 0x00) && ((RomBarOffset - RomBar) < RomSize));\r
267\r
268 //\r
269 // Some Legacy Cards do not report the correct ImageLength so used the maximum\r
270 // of the legacy length and the PCIR Image Length\r
271 //\r
272 if (CodeType == PCI_CODE_TYPE_PCAT_IMAGE) {\r
94020bb4 273 RomImageSize = MAX (RomImageSize, LegacyImageLength);\r
10590588 274 }\r
275\r
276 if (RomImageSize > 0) {\r
277 retStatus = EFI_SUCCESS;\r
278 Image = AllocatePool ((UINT32) RomImageSize);\r
279 if (Image == NULL) {\r
280 RomDecode (PciDevice, RomBarIndex, RomBar, FALSE);\r
281 gBS->FreePool (RomHeader);\r
282 gBS->FreePool (RomPcir);\r
283 return EFI_OUT_OF_RESOURCES;\r
284 }\r
285 \r
286 //\r
287 // Copy Rom image into memory\r
288 //\r
289 PciDevice->PciRootBridgeIo->Mem.Read (\r
290 PciDevice->PciRootBridgeIo,\r
291 EfiPciWidthUint8,\r
292 RomBar,\r
293 (UINT32) RomImageSize,\r
294 Image\r
295 );\r
296 RomInMemory = Image;\r
297 }\r
298\r
299 RomDecode (PciDevice, RomBarIndex, RomBar, FALSE);\r
300\r
301 PciDevice->PciIo.RomSize = RomImageSize;\r
302 PciDevice->PciIo.RomImage = RomInMemory;\r
303\r
304 //\r
305 // Free allocated memory\r
306 //\r
307 gBS->FreePool (RomHeader);\r
308 gBS->FreePool (RomPcir);\r
309\r
310 return retStatus;\r
311}\r
312\r
313EFI_STATUS\r
314RomDecode (\r
315 IN PCI_IO_DEVICE *PciDevice,\r
316 IN UINT8 RomBarIndex,\r
317 IN UINT32 RomBar,\r
318 IN BOOLEAN Enable\r
319 )\r
320/*++\r
321\r
322Routine Description:\r
323\r
324Arguments:\r
325\r
326Returns:\r
327\r
328--*/\r
329{\r
330 UINT16 CommandValue;\r
331 UINT32 Value32;\r
332 UINT64 Address;\r
333 //EFI_STATUS Status;\r
334 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;\r
335 \r
336 PciRootBridgeIo = PciDevice->PciRootBridgeIo;\r
337 if (Enable) {\r
338 Address = EFI_PCI_ADDRESS (PciDevice->BusNumber, PciDevice->DeviceNumber, PciDevice->FunctionNumber, RomBarIndex);\r
339 //\r
340 // set the Rom base address: now is hardcode\r
341 //\r
342 PciRootBridgeIo->Pci.Write(\r
343 PciRootBridgeIo, \r
344 EfiPciWidthUint32, \r
345 Address, \r
346 1, \r
347 &RomBar);\r
348 \r
349 //\r
350 // enable its decoder\r
351 //\r
352 Value32 = RomBar | 0x1;\r
353 PciRootBridgeIo->Pci.Write(\r
354 PciRootBridgeIo, \r
355 EfiPciWidthUint32, \r
356 Address, \r
357 1, \r
358 &Value32);\r
359 \r
360 //\r
361 //setting the memory space bit in the function's command register\r
362 //\r
363 Address = EFI_PCI_ADDRESS (PciDevice->BusNumber, PciDevice->DeviceNumber, PciDevice->FunctionNumber, 0x04);\r
364 PciRootBridgeIo->Pci.Read(\r
365 PciRootBridgeIo, \r
366 EfiPciWidthUint16, \r
367 Address, \r
368 1, \r
369 &CommandValue);\r
370 \r
371 CommandValue = (UINT16)(CommandValue | 0x0002); //0x0003\r
372 PciRootBridgeIo->Pci.Write(\r
373 PciRootBridgeIo, \r
374 EfiPciWidthUint16, \r
375 Address, \r
376 1, \r
377 &CommandValue);\r
378 } else {\r
379 //\r
380 // disable rom decode\r
381 // \r
382 Address = EFI_PCI_ADDRESS (PciDevice->BusNumber, PciDevice->DeviceNumber, PciDevice->FunctionNumber, RomBarIndex);\r
383 Value32 = 0xfffffffe;\r
384 PciRootBridgeIo->Pci.Write(\r
385 PciRootBridgeIo, \r
386 EfiPciWidthUint32, \r
387 Address, \r
388 1, \r
389 &Value32);\r
390 }\r
391\r
392 return EFI_SUCCESS;\r
393\r
394}\r
395\r
396EFI_STATUS\r
397ProcessOpRomImage (\r
398 PCI_IO_DEVICE *PciDevice\r
399 )\r
400/*++\r
401\r
402Routine Description:\r
403\r
404 Process the oprom image.\r
405 \r
406Arguments:\r
407 PciDevice A pointer to a pci device.\r
408\r
409Returns:\r
410\r
411 EFI Status.\r
412 \r
413--*/\r
414{\r
415 UINT8 Indicator;\r
416 UINT32 ImageSize;\r
417 UINT16 ImageOffset;\r
418 VOID *RomBar;\r
419 UINT8 *RomBarOffset;\r
420 EFI_HANDLE ImageHandle;\r
421 EFI_STATUS Status;\r
422 EFI_STATUS retStatus;\r
10590588 423 BOOLEAN SkipImage;\r
424 UINT32 DestinationSize;\r
425 UINT32 ScratchSize;\r
426 UINT8 *Scratch;\r
427 VOID *ImageBuffer;\r
428 VOID *DecompressedImageBuffer;\r
429 UINT32 ImageLength;\r
430 EFI_DECOMPRESS_PROTOCOL *Decompress;\r
431 EFI_PCI_EXPANSION_ROM_HEADER *EfiRomHeader;\r
432 PCI_DATA_STRUCTURE *Pcir;\r
94020bb4 433 UINT32 InitializationSize;\r
10590588 434\r
435 Indicator = 0;\r
436\r
437 //\r
438 // Get the Address of the Rom image\r
439 //\r
440 RomBar = PciDevice->PciIo.RomImage;\r
441 RomBarOffset = (UINT8 *) RomBar;\r
442 retStatus = EFI_NOT_FOUND;\r
94020bb4 443\r
444 if (RomBarOffset == NULL) {\r
445 return retStatus;\r
446 }\r
447 ASSERT (((EFI_PCI_EXPANSION_ROM_HEADER *) RomBarOffset)->Signature == PCI_EXPANSION_ROM_HEADER_SIGNATURE);\r
10590588 448\r
449 do {\r
450 EfiRomHeader = (EFI_PCI_EXPANSION_ROM_HEADER *) RomBarOffset;\r
451 if (EfiRomHeader->Signature != PCI_EXPANSION_ROM_HEADER_SIGNATURE) {\r
452 RomBarOffset = RomBarOffset + 512;\r
94020bb4 453 continue;\r
10590588 454 }\r
455\r
10590588 456 Pcir = (PCI_DATA_STRUCTURE *) (RomBarOffset + EfiRomHeader->PcirOffset);\r
94020bb4 457 ASSERT (Pcir->Signature == PCI_DATA_STRUCTURE_SIGNATURE);\r
10590588 458 ImageSize = (UINT32) (Pcir->ImageLength * 512);\r
459 Indicator = Pcir->Indicator;\r
460\r
94020bb4 461 if ((Pcir->CodeType == PCI_CODE_TYPE_EFI_IMAGE) &&\r
462 (EfiRomHeader->EfiSignature == EFI_PCI_EXPANSION_ROM_HEADER_EFISIGNATURE) &&\r
463 ((EfiRomHeader->EfiSubsystem == EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER) ||\r
464 (EfiRomHeader->EfiSubsystem == EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER))) {\r
10590588 465\r
94020bb4 466 ImageOffset = EfiRomHeader->EfiImageHeaderOffset;\r
467 InitializationSize = EfiRomHeader->InitializationSize * 512;\r
10590588 468\r
94020bb4 469 if (InitializationSize <= ImageSize && ImageOffset < InitializationSize) {\r
10590588 470\r
471 ImageBuffer = (VOID *) (RomBarOffset + ImageOffset);\r
94020bb4 472 ImageLength = InitializationSize - (UINT32)ImageOffset;\r
10590588 473 DecompressedImageBuffer = NULL;\r
474\r
475 //\r
476 // decompress here if needed\r
477 //\r
478 SkipImage = FALSE;\r
479 if (EfiRomHeader->CompressionType > EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED) {\r
480 SkipImage = TRUE;\r
481 }\r
482\r
483 if (EfiRomHeader->CompressionType == EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED) {\r
484 Status = gBS->LocateProtocol (&gEfiDecompressProtocolGuid, NULL, (VOID **) &Decompress);\r
485 if (EFI_ERROR (Status)) {\r
486 SkipImage = TRUE;\r
487 } else {\r
488 SkipImage = TRUE;\r
489 Status = Decompress->GetInfo (\r
490 Decompress,\r
491 ImageBuffer,\r
492 ImageLength,\r
493 &DestinationSize,\r
494 &ScratchSize\r
495 );\r
496 if (!EFI_ERROR (Status)) {\r
497 DecompressedImageBuffer = NULL;\r
498 DecompressedImageBuffer = AllocatePool (DestinationSize);\r
499 if (DecompressedImageBuffer != NULL) {\r
500 Scratch = AllocatePool (ScratchSize);\r
501 if (Scratch != NULL) {\r
502 Status = Decompress->Decompress (\r
503 Decompress,\r
504 ImageBuffer,\r
505 ImageLength,\r
506 DecompressedImageBuffer,\r
507 DestinationSize,\r
508 Scratch,\r
509 ScratchSize\r
510 );\r
511 if (!EFI_ERROR (Status)) {\r
512 ImageBuffer = DecompressedImageBuffer;\r
513 ImageLength = DestinationSize;\r
514 SkipImage = FALSE;\r
515 }\r
516\r
517 gBS->FreePool (Scratch);\r
518 }\r
519 }\r
520 }\r
521 }\r
522 }\r
523\r
524 if (!SkipImage) {\r
525 //\r
526 // load image and start image\r
527 //\r
528 Status = gBS->LoadImage (\r
529 FALSE,\r
530 gPciBusDriverBinding.DriverBindingHandle,\r
531 NULL,\r
532 ImageBuffer,\r
533 ImageLength,\r
534 &ImageHandle\r
535 );\r
536 if (!EFI_ERROR (Status)) {\r
537 Status = gBS->StartImage (ImageHandle, NULL, NULL);\r
538 if (!EFI_ERROR (Status)) {\r
539 AddDriver (PciDevice, ImageHandle);\r
540 retStatus = EFI_SUCCESS;\r
541 }\r
542 }\r
543 }\r
544\r
545 RomBarOffset = RomBarOffset + ImageSize;\r
546 } else {\r
547 RomBarOffset = RomBarOffset + ImageSize;\r
548 }\r
549 } else {\r
550 RomBarOffset = RomBarOffset + ImageSize;\r
551 }\r
552\r
553 } while (((Indicator & 0x80) == 0x00) && ((UINTN) (RomBarOffset - (UINT8 *) RomBar) < PciDevice->RomSize));\r
554\r
555 return retStatus;\r
556\r
557}\r