]> git.proxmox.com Git - mirror_edk2.git/blame - DuetPkg/PciBusNoEnumerationDxe/PciOptionRomSupport.c
Remove the duplicated definitins.
[mirror_edk2.git] / DuetPkg / PciBusNoEnumerationDxe / PciOptionRomSupport.c
CommitLineData
10590588 1/*++\r
2\r
3Copyright (c) 2005 - 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
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
71 RomBarIndex = PCI_DEVICE_ROMBAR;\r
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
151 UINT64 Temp;\r
152 EFI_STATUS retStatus;\r
153 BOOLEAN FirstCheck;\r
154 UINT8 *Image;\r
155 PCI_EXPANSION_ROM_HEADER *RomHeader;\r
156 PCI_DATA_STRUCTURE *RomPcir;\r
157 UINT64 RomSize;\r
158 UINT64 RomImageSize;\r
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
167 Temp = 0;\r
168 CodeType = 0xFF;\r
169\r
170 //\r
171 // Get the RomBarIndex\r
172 //\r
173\r
174 //\r
175 // 0x30\r
176 //\r
177 RomBarIndex = PCI_DEVICE_ROMBAR;\r
178 if (IS_PCI_BRIDGE (&(PciDevice->Pci))) {\r
179 //\r
180 // if is ppb\r
181 //\r
182\r
183 //\r
184 // 0x38\r
185 //\r
186 RomBarIndex = PCI_BRIDGE_ROMBAR;\r
187 }\r
188 //\r
189 // Allocate memory for Rom header and PCIR\r
190 //\r
191 RomHeader = AllocatePool (sizeof (PCI_EXPANSION_ROM_HEADER));\r
192 if (RomHeader == NULL) {\r
193 return EFI_OUT_OF_RESOURCES;\r
194 }\r
195\r
196 RomPcir = AllocatePool (sizeof (PCI_DATA_STRUCTURE));\r
197 if (RomPcir == NULL) {\r
198 gBS->FreePool (RomHeader);\r
199 return EFI_OUT_OF_RESOURCES;\r
200 }\r
201\r
202 RomBar = (UINT32)ReservedMemoryBase; \r
203\r
204 //\r
205 // Enable RomBar\r
206 //\r
207 RomDecode (PciDevice, RomBarIndex, RomBar, TRUE);\r
208\r
209 RomBarOffset = RomBar;\r
210 retStatus = EFI_NOT_FOUND;\r
211 FirstCheck = TRUE;\r
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
234 PciDevice->PciRootBridgeIo->Mem.Read (\r
235 PciDevice->PciRootBridgeIo,\r
236 EfiPciWidthUint8,\r
237 RomBarOffset + OffsetPcir,\r
238 sizeof (PCI_DATA_STRUCTURE),\r
239 (UINT8 *) RomPcir\r
240 );\r
241 if (RomPcir->CodeType == PCI_CODE_TYPE_PCAT_IMAGE) {\r
242 CodeType = PCI_CODE_TYPE_PCAT_IMAGE;\r
243 }\r
244 Indicator = RomPcir->Indicator;\r
245 RomImageSize = RomImageSize + RomPcir->ImageLength * 512;\r
246 RomBarOffset = RomBarOffset + RomPcir->ImageLength * 512;\r
247 } while (((Indicator & 0x80) == 0x00) && ((RomBarOffset - RomBar) < RomSize));\r
248\r
249 //\r
250 // Some Legacy Cards do not report the correct ImageLength so used the maximum\r
251 // of the legacy length and the PCIR Image Length\r
252 //\r
253 if (CodeType == PCI_CODE_TYPE_PCAT_IMAGE) {\r
254 RomImageSize = MAX(RomImageSize, (((EFI_LEGACY_EXPANSION_ROM_HEADER *)RomHeader)->Size512 * 512));\r
255 }\r
256\r
257 if (RomImageSize > 0) {\r
258 retStatus = EFI_SUCCESS;\r
259 Image = AllocatePool ((UINT32) RomImageSize);\r
260 if (Image == NULL) {\r
261 RomDecode (PciDevice, RomBarIndex, RomBar, FALSE);\r
262 gBS->FreePool (RomHeader);\r
263 gBS->FreePool (RomPcir);\r
264 return EFI_OUT_OF_RESOURCES;\r
265 }\r
266 \r
267 //\r
268 // Copy Rom image into memory\r
269 //\r
270 PciDevice->PciRootBridgeIo->Mem.Read (\r
271 PciDevice->PciRootBridgeIo,\r
272 EfiPciWidthUint8,\r
273 RomBar,\r
274 (UINT32) RomImageSize,\r
275 Image\r
276 );\r
277 RomInMemory = Image;\r
278 }\r
279\r
280 RomDecode (PciDevice, RomBarIndex, RomBar, FALSE);\r
281\r
282 PciDevice->PciIo.RomSize = RomImageSize;\r
283 PciDevice->PciIo.RomImage = RomInMemory;\r
284\r
285 //\r
286 // Free allocated memory\r
287 //\r
288 gBS->FreePool (RomHeader);\r
289 gBS->FreePool (RomPcir);\r
290\r
291 return retStatus;\r
292}\r
293\r
294EFI_STATUS\r
295RomDecode (\r
296 IN PCI_IO_DEVICE *PciDevice,\r
297 IN UINT8 RomBarIndex,\r
298 IN UINT32 RomBar,\r
299 IN BOOLEAN Enable\r
300 )\r
301/*++\r
302\r
303Routine Description:\r
304\r
305Arguments:\r
306\r
307Returns:\r
308\r
309--*/\r
310{\r
311 UINT16 CommandValue;\r
312 UINT32 Value32;\r
313 UINT64 Address;\r
314 //EFI_STATUS Status;\r
315 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;\r
316 \r
317 PciRootBridgeIo = PciDevice->PciRootBridgeIo;\r
318 if (Enable) {\r
319 Address = EFI_PCI_ADDRESS (PciDevice->BusNumber, PciDevice->DeviceNumber, PciDevice->FunctionNumber, RomBarIndex);\r
320 //\r
321 // set the Rom base address: now is hardcode\r
322 //\r
323 PciRootBridgeIo->Pci.Write(\r
324 PciRootBridgeIo, \r
325 EfiPciWidthUint32, \r
326 Address, \r
327 1, \r
328 &RomBar);\r
329 \r
330 //\r
331 // enable its decoder\r
332 //\r
333 Value32 = RomBar | 0x1;\r
334 PciRootBridgeIo->Pci.Write(\r
335 PciRootBridgeIo, \r
336 EfiPciWidthUint32, \r
337 Address, \r
338 1, \r
339 &Value32);\r
340 \r
341 //\r
342 //setting the memory space bit in the function's command register\r
343 //\r
344 Address = EFI_PCI_ADDRESS (PciDevice->BusNumber, PciDevice->DeviceNumber, PciDevice->FunctionNumber, 0x04);\r
345 PciRootBridgeIo->Pci.Read(\r
346 PciRootBridgeIo, \r
347 EfiPciWidthUint16, \r
348 Address, \r
349 1, \r
350 &CommandValue);\r
351 \r
352 CommandValue = (UINT16)(CommandValue | 0x0002); //0x0003\r
353 PciRootBridgeIo->Pci.Write(\r
354 PciRootBridgeIo, \r
355 EfiPciWidthUint16, \r
356 Address, \r
357 1, \r
358 &CommandValue);\r
359 } else {\r
360 //\r
361 // disable rom decode\r
362 // \r
363 Address = EFI_PCI_ADDRESS (PciDevice->BusNumber, PciDevice->DeviceNumber, PciDevice->FunctionNumber, RomBarIndex);\r
364 Value32 = 0xfffffffe;\r
365 PciRootBridgeIo->Pci.Write(\r
366 PciRootBridgeIo, \r
367 EfiPciWidthUint32, \r
368 Address, \r
369 1, \r
370 &Value32);\r
371 }\r
372\r
373 return EFI_SUCCESS;\r
374\r
375}\r
376\r
377EFI_STATUS\r
378ProcessOpRomImage (\r
379 PCI_IO_DEVICE *PciDevice\r
380 )\r
381/*++\r
382\r
383Routine Description:\r
384\r
385 Process the oprom image.\r
386 \r
387Arguments:\r
388 PciDevice A pointer to a pci device.\r
389\r
390Returns:\r
391\r
392 EFI Status.\r
393 \r
394--*/\r
395{\r
396 UINT8 Indicator;\r
397 UINT32 ImageSize;\r
398 UINT16 ImageOffset;\r
399 VOID *RomBar;\r
400 UINT8 *RomBarOffset;\r
401 EFI_HANDLE ImageHandle;\r
402 EFI_STATUS Status;\r
403 EFI_STATUS retStatus;\r
404 BOOLEAN FirstCheck;\r
405 BOOLEAN SkipImage;\r
406 UINT32 DestinationSize;\r
407 UINT32 ScratchSize;\r
408 UINT8 *Scratch;\r
409 VOID *ImageBuffer;\r
410 VOID *DecompressedImageBuffer;\r
411 UINT32 ImageLength;\r
412 EFI_DECOMPRESS_PROTOCOL *Decompress;\r
413 EFI_PCI_EXPANSION_ROM_HEADER *EfiRomHeader;\r
414 PCI_DATA_STRUCTURE *Pcir;\r
415\r
416 Indicator = 0;\r
417\r
418 //\r
419 // Get the Address of the Rom image\r
420 //\r
421 RomBar = PciDevice->PciIo.RomImage;\r
422 RomBarOffset = (UINT8 *) RomBar;\r
423 retStatus = EFI_NOT_FOUND;\r
424 FirstCheck = TRUE;\r
425\r
426 do {\r
427 EfiRomHeader = (EFI_PCI_EXPANSION_ROM_HEADER *) RomBarOffset;\r
428 if (EfiRomHeader->Signature != PCI_EXPANSION_ROM_HEADER_SIGNATURE) {\r
429 RomBarOffset = RomBarOffset + 512;\r
430 if (FirstCheck) {\r
431 break;\r
432 } else {\r
433 continue;\r
434 }\r
435 }\r
436\r
437 FirstCheck = FALSE;\r
438 Pcir = (PCI_DATA_STRUCTURE *) (RomBarOffset + EfiRomHeader->PcirOffset);\r
439 ImageSize = (UINT32) (Pcir->ImageLength * 512);\r
440 Indicator = Pcir->Indicator;\r
441\r
442 if ((Pcir->CodeType == PCI_CODE_TYPE_EFI_IMAGE) && \r
443 (EfiRomHeader->EfiSignature == EFI_PCI_EXPANSION_ROM_HEADER_EFISIGNATURE)) {\r
444\r
445 if ((EfiRomHeader->EfiSubsystem == EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER) ||\r
446 (EfiRomHeader->EfiSubsystem == EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER)) {\r
447\r
448 ImageOffset = EfiRomHeader->EfiImageHeaderOffset;\r
449 ImageSize = (UINT32) (EfiRomHeader->InitializationSize * 512);\r
450\r
451 ImageBuffer = (VOID *) (RomBarOffset + ImageOffset);\r
452 ImageLength = ImageSize - (UINT32)ImageOffset;\r
453 DecompressedImageBuffer = NULL;\r
454\r
455 //\r
456 // decompress here if needed\r
457 //\r
458 SkipImage = FALSE;\r
459 if (EfiRomHeader->CompressionType > EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED) {\r
460 SkipImage = TRUE;\r
461 }\r
462\r
463 if (EfiRomHeader->CompressionType == EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED) {\r
464 Status = gBS->LocateProtocol (&gEfiDecompressProtocolGuid, NULL, (VOID **) &Decompress);\r
465 if (EFI_ERROR (Status)) {\r
466 SkipImage = TRUE;\r
467 } else {\r
468 SkipImage = TRUE;\r
469 Status = Decompress->GetInfo (\r
470 Decompress,\r
471 ImageBuffer,\r
472 ImageLength,\r
473 &DestinationSize,\r
474 &ScratchSize\r
475 );\r
476 if (!EFI_ERROR (Status)) {\r
477 DecompressedImageBuffer = NULL;\r
478 DecompressedImageBuffer = AllocatePool (DestinationSize);\r
479 if (DecompressedImageBuffer != NULL) {\r
480 Scratch = AllocatePool (ScratchSize);\r
481 if (Scratch != NULL) {\r
482 Status = Decompress->Decompress (\r
483 Decompress,\r
484 ImageBuffer,\r
485 ImageLength,\r
486 DecompressedImageBuffer,\r
487 DestinationSize,\r
488 Scratch,\r
489 ScratchSize\r
490 );\r
491 if (!EFI_ERROR (Status)) {\r
492 ImageBuffer = DecompressedImageBuffer;\r
493 ImageLength = DestinationSize;\r
494 SkipImage = FALSE;\r
495 }\r
496\r
497 gBS->FreePool (Scratch);\r
498 }\r
499 }\r
500 }\r
501 }\r
502 }\r
503\r
504 if (!SkipImage) {\r
505 //\r
506 // load image and start image\r
507 //\r
508 Status = gBS->LoadImage (\r
509 FALSE,\r
510 gPciBusDriverBinding.DriverBindingHandle,\r
511 NULL,\r
512 ImageBuffer,\r
513 ImageLength,\r
514 &ImageHandle\r
515 );\r
516 if (!EFI_ERROR (Status)) {\r
517 Status = gBS->StartImage (ImageHandle, NULL, NULL);\r
518 if (!EFI_ERROR (Status)) {\r
519 AddDriver (PciDevice, ImageHandle);\r
520 retStatus = EFI_SUCCESS;\r
521 }\r
522 }\r
523 }\r
524\r
525 RomBarOffset = RomBarOffset + ImageSize;\r
526 } else {\r
527 RomBarOffset = RomBarOffset + ImageSize;\r
528 }\r
529 } else {\r
530 RomBarOffset = RomBarOffset + ImageSize;\r
531 }\r
532\r
533 } while (((Indicator & 0x80) == 0x00) && ((UINTN) (RomBarOffset - (UINT8 *) RomBar) < PciDevice->RomSize));\r
534\r
535 return retStatus;\r
536\r
537}\r