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