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