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