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