]> git.proxmox.com Git - mirror_edk2.git/blame - IntelFrameworkModulePkg/Bus/Pci/PciBusDxe/PciOptionRomSupport.c
Fix build break for X64 cpu architecture.
[mirror_edk2.git] / IntelFrameworkModulePkg / Bus / Pci / PciBusDxe / PciOptionRomSupport.c
CommitLineData
3db51098 1/**@file\r
2\r
3Copyright (c) 2006, Intel Corporation \r
4All rights reserved. This program and the accompanying materials \r
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
12**/\r
ead42efc 13\r
14#include "pcibus.h"\r
15#include "PciResourceSupport.h"\r
16\r
b1ef4015 17#include <IndustryStandard/Pci23.h>\r
ead42efc 18\r
2d9d2abf 19//\r
20// Module global for a template of the PCI option ROM Image Device Path Node\r
21//\r
22MEMMAP_DEVICE_PATH mPciOptionRomImageDevicePathNodeTemplate = {\r
23 { \r
24 HARDWARE_DEVICE_PATH,\r
25 HW_MEMMAP_DP,\r
26 sizeof (MEMMAP_DEVICE_PATH)\r
27 },\r
28 EfiMemoryMappedIO,\r
29 0,\r
30 0\r
31};\r
32\r
ead42efc 33EFI_STATUS\r
34GetOpRomInfo (\r
35 IN PCI_IO_DEVICE *PciIoDevice\r
36 )\r
37/*++\r
38\r
39Routine Description:\r
40\r
41Arguments:\r
42\r
43Returns:\r
44\r
45--*/\r
46// TODO: PciIoDevice - add argument and description to function comment\r
47// TODO: EFI_NOT_FOUND - add return value to function comment\r
48// TODO: EFI_SUCCESS - add return value to function comment\r
49{\r
50 UINT8 RomBarIndex;\r
51 UINT32 AllOnes;\r
52 UINT64 Address;\r
53 EFI_STATUS Status;\r
54 UINT8 Bus;\r
55 UINT8 Device;\r
56 UINT8 Function;\r
57 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;\r
58\r
59 Bus = PciIoDevice->BusNumber;\r
60 Device = PciIoDevice->DeviceNumber;\r
61 Function = PciIoDevice->FunctionNumber;\r
62\r
63 PciRootBridgeIo = PciIoDevice->PciRootBridgeIo;\r
64\r
65 //\r
66 // offset is 0x30 if is not ppb\r
67 //\r
68\r
69 //\r
70 // 0x30\r
71 //\r
72 RomBarIndex = PCI_DEVICE_ROMBAR;\r
73\r
74 if (IS_PCI_BRIDGE (&PciIoDevice->Pci)) {\r
75 //\r
76 // if is ppb\r
77 //\r
78\r
79 //\r
80 // 0x38\r
81 //\r
82 RomBarIndex = PCI_BRIDGE_ROMBAR;\r
83 }\r
84 //\r
85 // the bit0 is 0 to prevent the enabling of the Rom address decoder\r
86 //\r
87 AllOnes = 0xfffffffe;\r
88 Address = EFI_PCI_ADDRESS (Bus, Device, Function, RomBarIndex);\r
89\r
90 Status = PciRootBridgeIoWrite (\r
91 PciRootBridgeIo,\r
92 &PciIoDevice->Pci,\r
93 EfiPciWidthUint32,\r
94 Address,\r
95 1,\r
96 &AllOnes\r
97 );\r
98 if (EFI_ERROR (Status)) {\r
99 return Status;\r
100 }\r
101\r
102 //\r
103 // read back\r
104 //\r
105 Status = PciRootBridgeIoRead (\r
106 PciRootBridgeIo,\r
107 &PciIoDevice->Pci,\r
108 EfiPciWidthUint32,\r
109 Address,\r
110 1,\r
111 &AllOnes\r
112 );\r
113 if (EFI_ERROR (Status)) {\r
114 return Status;\r
115 }\r
116 //\r
117 // Bits [1, 10] are reserved\r
118 //\r
119 AllOnes &= 0xFFFFF800;\r
120 if ((AllOnes == 0) || (AllOnes == 0xFFFFF800)) {\r
121 return EFI_NOT_FOUND;\r
122 }\r
123\r
124 PciIoDevice->RomSize = (UINT64) ((~AllOnes) + 1);\r
125 return EFI_SUCCESS;\r
126}\r
127\r
128EFI_STATUS\r
129LoadOpRomImage (\r
130 IN PCI_IO_DEVICE *PciDevice,\r
131 IN UINT64 RomBase\r
132 )\r
133/*++\r
134\r
135Routine Description:\r
136 \r
137 Load option rom image for specified PCI device\r
138\r
139Arguments:\r
140\r
141Returns:\r
142\r
143--*/\r
144// TODO: PciDevice - add argument and description to function comment\r
145// TODO: RomBase - add argument and description to function comment\r
146// TODO: EFI_OUT_OF_RESOURCES - add return value to function comment\r
147// TODO: EFI_OUT_OF_RESOURCES - add return value to function comment\r
148// TODO: EFI_OUT_OF_RESOURCES - add return value to function comment\r
149{\r
150 UINT8 RomBarIndex;\r
151 UINT8 Indicator;\r
152 UINT16 OffsetPcir;\r
153 UINT32 RomBarOffset;\r
154 UINT32 RomBar;\r
155 EFI_STATUS retStatus;\r
156 BOOLEAN FirstCheck;\r
157 UINT8 *Image;\r
158 PCI_EXPANSION_ROM_HEADER *RomHeader;\r
159 PCI_DATA_STRUCTURE *RomPcir;\r
160 UINT64 RomSize;\r
161 UINT64 RomImageSize;\r
162 UINT8 *RomInMemory;\r
163 UINT8 CodeType;\r
164\r
165 RomSize = PciDevice->RomSize;\r
166\r
167 Indicator = 0;\r
168 RomImageSize = 0;\r
169 RomInMemory = NULL;\r
170 CodeType = 0xFF;\r
171\r
172 //\r
173 // Get the RomBarIndex\r
174 //\r
175\r
176 //\r
177 // 0x30\r
178 //\r
179 RomBarIndex = PCI_DEVICE_ROMBAR;\r
180 if (IS_PCI_BRIDGE (&(PciDevice->Pci))) {\r
181 //\r
182 // if is ppb\r
183 //\r
184\r
185 //\r
186 // 0x38\r
187 //\r
188 RomBarIndex = PCI_BRIDGE_ROMBAR;\r
189 }\r
190 //\r
191 // Allocate memory for Rom header and PCIR\r
192 //\r
193 RomHeader = AllocatePool (sizeof (PCI_EXPANSION_ROM_HEADER));\r
194 if (RomHeader == NULL) {\r
195 return EFI_OUT_OF_RESOURCES;\r
196 }\r
197\r
198 RomPcir = AllocatePool (sizeof (PCI_DATA_STRUCTURE));\r
199 if (RomPcir == NULL) {\r
200 gBS->FreePool (RomHeader);\r
201 return EFI_OUT_OF_RESOURCES;\r
202 }\r
203\r
204 RomBar = (UINT32) RomBase;\r
205\r
206 //\r
207 // Enable RomBar\r
208 //\r
209 RomDecode (PciDevice, RomBarIndex, RomBar, TRUE);\r
210\r
211 RomBarOffset = RomBar;\r
212 retStatus = EFI_NOT_FOUND;\r
213 FirstCheck = TRUE;\r
214\r
215 do {\r
216 PciDevice->PciRootBridgeIo->Mem.Read (\r
217 PciDevice->PciRootBridgeIo,\r
218 EfiPciWidthUint8,\r
219 RomBarOffset,\r
220 sizeof (PCI_EXPANSION_ROM_HEADER),\r
221 (UINT8 *) RomHeader\r
222 );\r
223\r
224 if (RomHeader->Signature != PCI_EXPANSION_ROM_HEADER_SIGNATURE) {\r
225 RomBarOffset = RomBarOffset + 512;\r
226 if (FirstCheck) {\r
227 break;\r
228 } else {\r
229 RomImageSize = RomImageSize + 512;\r
230 continue;\r
231 }\r
232 }\r
233\r
234 FirstCheck = FALSE;\r
235 OffsetPcir = RomHeader->PcirOffset;\r
236 PciDevice->PciRootBridgeIo->Mem.Read (\r
237 PciDevice->PciRootBridgeIo,\r
238 EfiPciWidthUint8,\r
239 RomBarOffset + OffsetPcir,\r
240 sizeof (PCI_DATA_STRUCTURE),\r
241 (UINT8 *) RomPcir\r
242 );\r
243 if (RomPcir->CodeType == PCI_CODE_TYPE_PCAT_IMAGE) {\r
244 CodeType = PCI_CODE_TYPE_PCAT_IMAGE;\r
245 }\r
246 Indicator = RomPcir->Indicator;\r
247 RomImageSize = RomImageSize + RomPcir->ImageLength * 512;\r
248 RomBarOffset = RomBarOffset + RomPcir->ImageLength * 512;\r
249 } while (((Indicator & 0x80) == 0x00) && ((RomBarOffset - RomBar) < RomSize));\r
250\r
251 //\r
252 // Some Legacy Cards do not report the correct ImageLength so used the maximum\r
253 // of the legacy length and the PCIR Image Length\r
254 //\r
255 if (CodeType == PCI_CODE_TYPE_PCAT_IMAGE) {\r
a1e3528b 256 RomImageSize = MAX(RomImageSize, (((EFI_LEGACY_EXPANSION_ROM_HEADER *)RomHeader)->Size512 * 512));\r
ead42efc 257 }\r
258\r
259 if (RomImageSize > 0) {\r
260 retStatus = EFI_SUCCESS;\r
261 Image = AllocatePool ((UINT32) RomImageSize);\r
262 if (Image == NULL) {\r
263 RomDecode (PciDevice, RomBarIndex, RomBar, FALSE);\r
264 gBS->FreePool (RomHeader);\r
265 gBS->FreePool (RomPcir);\r
266 return EFI_OUT_OF_RESOURCES;\r
267 }\r
268 \r
269 //\r
270 // Copy Rom image into memory\r
271 //\r
272 PciDevice->PciRootBridgeIo->Mem.Read (\r
273 PciDevice->PciRootBridgeIo,\r
274 EfiPciWidthUint8,\r
275 RomBar,\r
276 (UINT32) RomImageSize,\r
277 Image\r
278 );\r
279 RomInMemory = Image;\r
280 }\r
281\r
282 RomDecode (PciDevice, RomBarIndex, RomBar, FALSE);\r
283\r
284 PciDevice->PciIo.RomSize = RomImageSize;\r
285 PciDevice->PciIo.RomImage = RomInMemory;\r
286\r
287 PciRomAddImageMapping (\r
288 NULL,\r
289 PciDevice->PciRootBridgeIo->SegmentNumber,\r
290 PciDevice->BusNumber,\r
291 PciDevice->DeviceNumber,\r
292 PciDevice->FunctionNumber,\r
293 (UINT64) (UINTN) PciDevice->PciIo.RomImage,\r
294 PciDevice->PciIo.RomSize\r
295 );\r
296\r
297 //\r
298 // Free allocated memory\r
299 //\r
300 gBS->FreePool (RomHeader);\r
301 gBS->FreePool (RomPcir);\r
302\r
303 return retStatus;\r
304}\r
305\r
306EFI_STATUS\r
307RomDecode (\r
308 IN PCI_IO_DEVICE *PciDevice,\r
309 IN UINT8 RomBarIndex,\r
310 IN UINT32 RomBar,\r
311 IN BOOLEAN Enable\r
312 )\r
313/*++\r
314\r
315Routine Description:\r
316\r
317Arguments:\r
318\r
319Returns:\r
320\r
321--*/\r
322// TODO: PciDevice - add argument and description to function comment\r
323// TODO: RomBarIndex - add argument and description to function comment\r
324// TODO: RomBar - add argument and description to function comment\r
325// TODO: Enable - add argument and description to function comment\r
326// TODO: EFI_SUCCESS - add return value to function comment\r
327{\r
328 UINT32 Value32;\r
329 UINT32 Offset;\r
330 EFI_PCI_IO_PROTOCOL *PciIo;\r
331\r
332 PciIo = &PciDevice->PciIo;\r
333 if (Enable) {\r
334 //\r
335 // Clear all bars\r
336 //\r
337 for (Offset = 0x10; Offset <= 0x24; Offset += sizeof (UINT32)) {\r
338 PciIoWrite (PciIo, EfiPciIoWidthUint32, Offset, 1, &gAllZero);\r
339 }\r
340 \r
341 //\r
342 // set the Rom base address: now is hardcode\r
343 // enable its decoder\r
344 //\r
345 Value32 = RomBar | 0x1;\r
346 PciIoWrite (\r
347 PciIo,\r
348 (EFI_PCI_IO_PROTOCOL_WIDTH) EfiPciWidthUint32,\r
349 RomBarIndex,\r
350 1,\r
351 &Value32\r
352 );\r
353\r
354 //\r
355 // Programe all upstream bridge\r
356 //\r
357 ProgrameUpstreamBridgeForRom(PciDevice, RomBar, TRUE);\r
358\r
359 //\r
360 // Setting the memory space bit in the function's command register\r
361 //\r
362 PciEnableCommandRegister(PciDevice, EFI_PCI_COMMAND_MEMORY_SPACE);\r
363\r
364 } else {\r
365 \r
366 //\r
367 // disable command register decode to memory\r
368 //\r
369 PciDisableCommandRegister(PciDevice, EFI_PCI_COMMAND_MEMORY_SPACE);\r
370\r
371 //\r
372 // Destroy the programmed bar in all the upstream bridge.\r
373 //\r
374 ProgrameUpstreamBridgeForRom(PciDevice, RomBar, FALSE);\r
375\r
376 //\r
377 // disable rom decode\r
378 //\r
379 Value32 = 0xFFFFFFFE;\r
380 PciIoWrite (\r
381 PciIo,\r
382 (EFI_PCI_IO_PROTOCOL_WIDTH) EfiPciWidthUint32,\r
383 RomBarIndex,\r
384 1,\r
385 &Value32\r
386 );\r
387\r
388 }\r
389\r
390 return EFI_SUCCESS;\r
391\r
392}\r
393\r
394EFI_STATUS\r
395ProcessOpRomImage (\r
396 PCI_IO_DEVICE *PciDevice\r
397 )\r
398/*++\r
399\r
400Routine Description:\r
401\r
402 Process the oprom image.\r
403 \r
404Arguments:\r
405 PciDevice A pointer to a pci device.\r
406\r
407Returns:\r
408\r
409 EFI Status.\r
410 \r
411--*/\r
412{\r
413 UINT8 Indicator;\r
414 UINT32 ImageSize;\r
415 UINT16 ImageOffset;\r
416 VOID *RomBar;\r
417 UINT8 *RomBarOffset;\r
418 EFI_HANDLE ImageHandle;\r
419 EFI_STATUS Status;\r
420 EFI_STATUS retStatus;\r
421 BOOLEAN FirstCheck;\r
422 BOOLEAN SkipImage;\r
423 UINT32 DestinationSize;\r
424 UINT32 ScratchSize;\r
425 UINT8 *Scratch;\r
426 VOID *ImageBuffer;\r
427 VOID *DecompressedImageBuffer;\r
428 UINT32 ImageLength;\r
429 EFI_DECOMPRESS_PROTOCOL *Decompress;\r
430 EFI_PCI_EXPANSION_ROM_HEADER *EfiRomHeader;\r
431 PCI_DATA_STRUCTURE *Pcir;\r
2d9d2abf 432 EFI_DEVICE_PATH_PROTOCOL *PciOptionRomImageDevicePath;\r
ead42efc 433\r
434 Indicator = 0;\r
435\r
436 //\r
437 // Get the Address of the Rom image\r
438 //\r
439 RomBar = PciDevice->PciIo.RomImage;\r
440 RomBarOffset = (UINT8 *) RomBar;\r
441 retStatus = EFI_NOT_FOUND;\r
442 FirstCheck = TRUE;\r
443\r
444 do {\r
445 EfiRomHeader = (EFI_PCI_EXPANSION_ROM_HEADER *) RomBarOffset;\r
446 if (EfiRomHeader->Signature != PCI_EXPANSION_ROM_HEADER_SIGNATURE) {\r
447 RomBarOffset = RomBarOffset + 512;\r
448 if (FirstCheck) {\r
449 break;\r
450 } else {\r
451 continue;\r
452 }\r
453 }\r
454\r
455 FirstCheck = FALSE;\r
456 Pcir = (PCI_DATA_STRUCTURE *) (RomBarOffset + EfiRomHeader->PcirOffset);\r
457 ImageSize = (UINT32) (Pcir->ImageLength * 512);\r
458 Indicator = Pcir->Indicator;\r
459\r
460 if ((Pcir->CodeType == PCI_CODE_TYPE_EFI_IMAGE) && \r
461 (EfiRomHeader->EfiSignature == EFI_PCI_EXPANSION_ROM_HEADER_EFISIGNATURE)) {\r
462\r
463 if ((EfiRomHeader->EfiSubsystem == EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER) ||\r
464 (EfiRomHeader->EfiSubsystem == EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER)) {\r
465\r
466 ImageOffset = EfiRomHeader->EfiImageHeaderOffset;\r
467 ImageSize = (UINT32) (EfiRomHeader->InitializationSize * 512);\r
468\r
469 ImageBuffer = (VOID *) (RomBarOffset + ImageOffset);\r
470 ImageLength = ImageSize - (UINT32)ImageOffset;\r
471 DecompressedImageBuffer = NULL;\r
472\r
473 //\r
474 // decompress here if needed\r
475 //\r
476 SkipImage = FALSE;\r
477 if (EfiRomHeader->CompressionType > EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED) {\r
478 SkipImage = TRUE;\r
479 }\r
480\r
481 if (EfiRomHeader->CompressionType == EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED) {\r
482 Status = gBS->LocateProtocol (&gEfiDecompressProtocolGuid, NULL, (VOID **) &Decompress);\r
483 if (EFI_ERROR (Status)) {\r
484 SkipImage = TRUE;\r
485 } else {\r
486 SkipImage = TRUE;\r
487 Status = Decompress->GetInfo (\r
488 Decompress,\r
489 ImageBuffer,\r
490 ImageLength,\r
491 &DestinationSize,\r
492 &ScratchSize\r
493 );\r
494 if (!EFI_ERROR (Status)) {\r
495 DecompressedImageBuffer = NULL;\r
496 DecompressedImageBuffer = AllocatePool (DestinationSize);\r
497 if (DecompressedImageBuffer != NULL) {\r
498 Scratch = AllocatePool (ScratchSize);\r
499 if (Scratch != NULL) {\r
500 Status = Decompress->Decompress (\r
501 Decompress,\r
502 ImageBuffer,\r
503 ImageLength,\r
504 DecompressedImageBuffer,\r
505 DestinationSize,\r
506 Scratch,\r
507 ScratchSize\r
508 );\r
509 if (!EFI_ERROR (Status)) {\r
510 ImageBuffer = DecompressedImageBuffer;\r
511 ImageLength = DestinationSize;\r
512 SkipImage = FALSE;\r
513 }\r
514\r
515 gBS->FreePool (Scratch);\r
516 }\r
517 }\r
518 }\r
519 }\r
520 }\r
521\r
522 if (!SkipImage) {\r
2d9d2abf 523 // \r
524 // Build full device path to the PCI Option ROM Image being loaded\r
525 //\r
526 mPciOptionRomImageDevicePathNodeTemplate.StartingAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)RomBarOffset;\r
527 mPciOptionRomImageDevicePathNodeTemplate.EndingAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)(RomBarOffset + ImageSize - 1);\r
528 PciOptionRomImageDevicePath = AppendDevicePathNode (PciDevice->DevicePath, (const EFI_DEVICE_PATH_PROTOCOL *)&mPciOptionRomImageDevicePathNodeTemplate);\r
529 ASSERT (PciOptionRomImageDevicePath != NULL);\r
530\r
ead42efc 531 //\r
532 // load image and start image\r
533 //\r
534 Status = gBS->LoadImage (\r
535 FALSE,\r
536 gPciBusDriverBinding.DriverBindingHandle,\r
2d9d2abf 537 PciOptionRomImageDevicePath,\r
ead42efc 538 ImageBuffer,\r
539 ImageLength,\r
540 &ImageHandle\r
541 );\r
2d9d2abf 542\r
543 //\r
544 // Free the device path after it has been used by LoadImage\r
545 //\r
546 gBS->FreePool (PciOptionRomImageDevicePath);\r
547\r
ead42efc 548 if (!EFI_ERROR (Status)) {\r
549 Status = gBS->StartImage (ImageHandle, NULL, NULL);\r
550 if (!EFI_ERROR (Status)) {\r
551 AddDriver (PciDevice, ImageHandle);\r
552 PciRomAddImageMapping (\r
553 ImageHandle,\r
554 PciDevice->PciRootBridgeIo->SegmentNumber,\r
555 PciDevice->BusNumber,\r
556 PciDevice->DeviceNumber,\r
557 PciDevice->FunctionNumber,\r
558 (UINT64) (UINTN) PciDevice->PciIo.RomImage,\r
559 PciDevice->PciIo.RomSize\r
560 );\r
561 retStatus = EFI_SUCCESS;\r
562 }\r
563 }\r
564 }\r
565\r
566 RomBarOffset = RomBarOffset + ImageSize;\r
567 } else {\r
568 RomBarOffset = RomBarOffset + ImageSize;\r
569 }\r
570 } else {\r
571 RomBarOffset = RomBarOffset + ImageSize;\r
572 }\r
573\r
574 } while (((Indicator & 0x80) == 0x00) && ((UINTN) (RomBarOffset - (UINT8 *) RomBar) < PciDevice->RomSize));\r
575\r
576 return retStatus;\r
577\r
578}\r