]> git.proxmox.com Git - mirror_edk2.git/blob - EdkModulePkg/Bus/Pci/PciBus/Dxe/PciRomTable.c
Some library instance's PCD is missing in FPD file for a module, it break single...
[mirror_edk2.git] / EdkModulePkg / Bus / Pci / PciBus / Dxe / PciRomTable.c
1 /*++
2
3 Copyright (c) 2006, Intel Corporation
4 All rights reserved. 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 PciRomTable.c
15
16 Abstract:
17
18 Option Rom Support for PCI Bus Driver
19
20 Revision History
21
22 --*/
23
24 #include "pcibus.h"
25 #include "PciRomTable.h"
26
27 typedef struct {
28 EFI_HANDLE ImageHandle;
29 UINTN Seg;
30 UINT8 Bus;
31 UINT8 Dev;
32 UINT8 Func;
33 UINT64 RomAddress;
34 UINT64 RomLength;
35 } EFI_PCI_ROM_IMAGE_MAPPING;
36
37 static UINTN mNumberOfPciRomImages = 0;
38 static UINTN mMaxNumberOfPciRomImages = 0;
39 static EFI_PCI_ROM_IMAGE_MAPPING *mRomImageTable = NULL;
40
41 VOID
42 PciRomAddImageMapping (
43 IN EFI_HANDLE ImageHandle,
44 IN UINTN Seg,
45 IN UINT8 Bus,
46 IN UINT8 Dev,
47 IN UINT8 Func,
48 IN UINT64 RomAddress,
49 IN UINT64 RomLength
50 )
51 /*++
52
53 Routine Description:
54
55 TODO: Add function description
56
57 Arguments:
58
59 ImageHandle - TODO: add argument description
60 Seg - TODO: add argument description
61 Bus - TODO: add argument description
62 Dev - TODO: add argument description
63 Func - TODO: add argument description
64 RomAddress - TODO: add argument description
65 RomLength - TODO: add argument description
66
67 Returns:
68
69 TODO: add return values
70
71 --*/
72 {
73 EFI_PCI_ROM_IMAGE_MAPPING *TempMapping;
74
75 if (mNumberOfPciRomImages >= mMaxNumberOfPciRomImages) {
76
77 mMaxNumberOfPciRomImages += 0x20;
78
79 TempMapping = NULL;
80 TempMapping = AllocatePool (mMaxNumberOfPciRomImages * sizeof (EFI_PCI_ROM_IMAGE_MAPPING));
81 if (TempMapping == NULL) {
82 return ;
83 }
84
85 CopyMem (TempMapping, mRomImageTable, mNumberOfPciRomImages * sizeof (EFI_PCI_ROM_IMAGE_MAPPING));
86
87 if (mRomImageTable != NULL) {
88 gBS->FreePool (mRomImageTable);
89 }
90
91 mRomImageTable = TempMapping;
92 }
93
94 mRomImageTable[mNumberOfPciRomImages].ImageHandle = ImageHandle;
95 mRomImageTable[mNumberOfPciRomImages].Seg = Seg;
96 mRomImageTable[mNumberOfPciRomImages].Bus = Bus;
97 mRomImageTable[mNumberOfPciRomImages].Dev = Dev;
98 mRomImageTable[mNumberOfPciRomImages].Func = Func;
99 mRomImageTable[mNumberOfPciRomImages].RomAddress = RomAddress;
100 mRomImageTable[mNumberOfPciRomImages].RomLength = RomLength;
101 mNumberOfPciRomImages++;
102 }
103
104 VOID
105 HexToString (
106 CHAR16 *String,
107 UINTN Value,
108 UINTN Digits
109 )
110 /*++
111
112 Routine Description:
113
114 TODO: Add function description
115
116 Arguments:
117
118 String - TODO: add argument description
119 Value - TODO: add argument description
120 Digits - TODO: add argument description
121
122 Returns:
123
124 TODO: add return values
125
126 --*/
127 {
128 for (; Digits > 0; Digits--, String++) {
129 *String = (CHAR16) ((Value >> (4 * (Digits - 1))) & 0x0f);
130 if (*String > 9) {
131 (*String) += ('A' - 10);
132 } else {
133 (*String) += '0';
134 }
135 }
136 }
137 EFI_STATUS
138 PciRomLoadEfiDriversFromRomImage (
139 IN EFI_DRIVER_BINDING_PROTOCOL *This,
140 IN EFI_PCI_OPTION_ROM_DESCRIPTOR *PciOptionRomDescriptor
141 )
142 /*++
143
144 Routine Description:
145
146 Arguments:
147
148 Returns:
149
150 --*/
151 // TODO: This - add argument and description to function comment
152 // TODO: PciOptionRomDescriptor - add argument and description to function comment
153 {
154 VOID *RomBar;
155 UINTN RomSize;
156 CHAR16 *FileName;
157 EFI_PCI_EXPANSION_ROM_HEADER *EfiRomHeader;
158 PCI_DATA_STRUCTURE *Pcir;
159 UINTN ImageIndex;
160 UINTN RomBarOffset;
161 UINT32 ImageSize;
162 UINT16 ImageOffset;
163 EFI_HANDLE ImageHandle;
164 EFI_STATUS Status;
165 EFI_STATUS retStatus;
166 EFI_DEVICE_PATH_PROTOCOL *FilePath;
167 BOOLEAN SkipImage;
168 UINT32 DestinationSize;
169 UINT32 ScratchSize;
170 UINT8 *Scratch;
171 VOID *ImageBuffer;
172 VOID *DecompressedImageBuffer;
173 UINT32 ImageLength;
174 EFI_DECOMPRESS_PROTOCOL *Decompress;
175
176 RomBar = (VOID *) (UINTN) PciOptionRomDescriptor->RomAddress;
177 RomSize = (UINTN) PciOptionRomDescriptor->RomLength;
178 FileName = L"PciRom Seg=00000000 Bus=00 Dev=00 Func=00 Image=0000";
179
180 HexToString (&FileName[11], PciOptionRomDescriptor->Seg, 8);
181 HexToString (&FileName[24], PciOptionRomDescriptor->Bus, 2);
182 HexToString (&FileName[31], PciOptionRomDescriptor->Dev, 2);
183 HexToString (&FileName[39], PciOptionRomDescriptor->Func, 2);
184
185 ImageIndex = 0;
186 retStatus = EFI_NOT_FOUND;
187 RomBarOffset = (UINTN) RomBar;
188
189 do {
190
191 EfiRomHeader = (EFI_PCI_EXPANSION_ROM_HEADER *) (UINTN) RomBarOffset;
192
193 if (EfiRomHeader->Signature != 0xaa55) {
194 return retStatus;
195 }
196
197 Pcir = (PCI_DATA_STRUCTURE *) (UINTN) (RomBarOffset + EfiRomHeader->PcirOffset);
198 ImageSize = Pcir->ImageLength * 512;
199
200 if ((Pcir->CodeType == PCI_CODE_TYPE_EFI_IMAGE) &&
201 (EfiRomHeader->EfiSignature == EFI_PCI_EXPANSION_ROM_HEADER_EFISIGNATURE) ) {
202
203 if ((EfiRomHeader->EfiSubsystem == EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER) ||
204 (EfiRomHeader->EfiSubsystem == EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER) ) {
205
206 ImageOffset = EfiRomHeader->EfiImageHeaderOffset;
207 ImageSize = EfiRomHeader->InitializationSize * 512;
208
209 ImageBuffer = (VOID *) (UINTN) (RomBarOffset + ImageOffset);
210 ImageLength = ImageSize - ImageOffset;
211 DecompressedImageBuffer = NULL;
212
213 //
214 // decompress here if needed
215 //
216 SkipImage = FALSE;
217 if (EfiRomHeader->CompressionType > EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED) {
218 SkipImage = TRUE;
219 }
220
221 if (EfiRomHeader->CompressionType == EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED) {
222 Status = gBS->LocateProtocol (&gEfiDecompressProtocolGuid, NULL, (VOID **) &Decompress);
223 if (EFI_ERROR (Status)) {
224 SkipImage = TRUE;
225 } else {
226 SkipImage = TRUE;
227 Status = Decompress->GetInfo (
228 Decompress,
229 ImageBuffer,
230 ImageLength,
231 &DestinationSize,
232 &ScratchSize
233 );
234 if (!EFI_ERROR (Status)) {
235 DecompressedImageBuffer = NULL;
236 DecompressedImageBuffer = AllocatePool (DestinationSize);
237 if (DecompressedImageBuffer != NULL) {
238 Scratch = AllocatePool (ScratchSize);
239 if (Scratch != NULL) {
240 Status = Decompress->Decompress (
241 Decompress,
242 ImageBuffer,
243 ImageLength,
244 DecompressedImageBuffer,
245 DestinationSize,
246 Scratch,
247 ScratchSize
248 );
249 if (!EFI_ERROR (Status)) {
250 ImageBuffer = DecompressedImageBuffer;
251 ImageLength = DestinationSize;
252 SkipImage = FALSE;
253 }
254
255 gBS->FreePool (Scratch);
256 }
257 }
258 }
259 }
260 }
261
262 if (!SkipImage) {
263
264 //
265 // load image and start image
266 //
267
268 HexToString (&FileName[48], ImageIndex, 4);
269 FilePath = FileDevicePath (NULL, FileName);
270
271 Status = gBS->LoadImage (
272 FALSE,
273 This->ImageHandle,
274 FilePath,
275 ImageBuffer,
276 ImageLength,
277 &ImageHandle
278 );
279 if (!EFI_ERROR (Status)) {
280 Status = gBS->StartImage (ImageHandle, NULL, NULL);
281 if (!EFI_ERROR (Status)) {
282 PciRomAddImageMapping (
283 ImageHandle,
284 PciOptionRomDescriptor->Seg,
285 PciOptionRomDescriptor->Bus,
286 PciOptionRomDescriptor->Dev,
287 PciOptionRomDescriptor->Func,
288 PciOptionRomDescriptor->RomAddress,
289 PciOptionRomDescriptor->RomLength
290 );
291 retStatus = Status;
292 }
293 }
294 }
295
296 if (DecompressedImageBuffer != NULL) {
297 gBS->FreePool (DecompressedImageBuffer);
298 }
299
300 }
301 }
302
303 RomBarOffset = RomBarOffset + ImageSize;
304 ImageIndex++;
305 } while (((Pcir->Indicator & 0x80) == 0x00) && ((RomBarOffset - (UINTN) RomBar) < RomSize));
306
307 return retStatus;
308 }
309
310 EFI_STATUS
311 PciRomLoadEfiDriversFromOptionRomTable (
312 IN EFI_DRIVER_BINDING_PROTOCOL *This,
313 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo
314 )
315 /*++
316
317 Routine Description:
318
319 Arguments:
320
321 Returns:
322
323 --*/
324 // TODO: This - add argument and description to function comment
325 // TODO: PciRootBridgeIo - add argument and description to function comment
326 // TODO: EFI_NOT_FOUND - add return value to function comment
327 {
328 EFI_STATUS Status;
329 EFI_PCI_OPTION_ROM_TABLE *PciOptionRomTable;
330 EFI_PCI_OPTION_ROM_DESCRIPTOR *PciOptionRomDescriptor;
331 UINTN Index;
332 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors;
333 UINT16 MinBus;
334 UINT16 MaxBus;
335
336 Status = EfiGetSystemConfigurationTable (&gEfiPciOptionRomTableGuid, (VOID **) &PciOptionRomTable);
337 if (EFI_ERROR (Status)) {
338 return EFI_NOT_FOUND;
339 }
340
341 Status = EFI_NOT_FOUND;
342
343 for (Index = 0; Index < PciOptionRomTable->PciOptionRomCount; Index++) {
344 PciOptionRomDescriptor = &PciOptionRomTable->PciOptionRomDescriptors[Index];
345 if (!PciOptionRomDescriptor->DontLoadEfiRom) {
346 if (PciOptionRomDescriptor->Seg == PciRootBridgeIo->SegmentNumber) {
347 Status = PciRootBridgeIo->Configuration (PciRootBridgeIo, (VOID **) &Descriptors);
348 if (EFI_ERROR (Status)) {
349 return Status;
350 }
351
352 PciGetBusRange (&Descriptors, &MinBus, &MaxBus, NULL);
353 if ((MinBus <= PciOptionRomDescriptor->Bus) && (PciOptionRomDescriptor->Bus <= MaxBus)) {
354 Status = PciRomLoadEfiDriversFromRomImage (This, PciOptionRomDescriptor);
355 PciOptionRomDescriptor->DontLoadEfiRom |= 2;
356 }
357 }
358 }
359 }
360
361 return Status;
362 }
363
364 EFI_STATUS
365 PciRomGetRomResourceFromPciOptionRomTable (
366 IN EFI_DRIVER_BINDING_PROTOCOL *This,
367 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo,
368 PCI_IO_DEVICE *PciIoDevice
369 )
370 /*++
371
372 Routine Description:
373
374 Arguments:
375
376 Returns:
377
378 --*/
379 // TODO: This - add argument and description to function comment
380 // TODO: PciRootBridgeIo - add argument and description to function comment
381 // TODO: PciIoDevice - add argument and description to function comment
382 // TODO: EFI_NOT_FOUND - add return value to function comment
383 // TODO: EFI_SUCCESS - add return value to function comment
384 {
385 EFI_STATUS Status;
386 EFI_PCI_OPTION_ROM_TABLE *PciOptionRomTable;
387 EFI_PCI_OPTION_ROM_DESCRIPTOR *PciOptionRomDescriptor;
388 UINTN Index;
389
390 Status = EfiGetSystemConfigurationTable (&gEfiPciOptionRomTableGuid, (VOID **) &PciOptionRomTable);
391 if (EFI_ERROR (Status)) {
392 return EFI_NOT_FOUND;
393 }
394
395 for (Index = 0; Index < PciOptionRomTable->PciOptionRomCount; Index++) {
396 PciOptionRomDescriptor = &PciOptionRomTable->PciOptionRomDescriptors[Index];
397 if (PciOptionRomDescriptor->Seg == PciRootBridgeIo->SegmentNumber &&
398 PciOptionRomDescriptor->Bus == PciIoDevice->BusNumber &&
399 PciOptionRomDescriptor->Dev == PciIoDevice->DeviceNumber &&
400 PciOptionRomDescriptor->Func == PciIoDevice->FunctionNumber ) {
401
402 PciIoDevice->PciIo.RomImage = (VOID *) (UINTN) PciOptionRomDescriptor->RomAddress;
403 PciIoDevice->PciIo.RomSize = (UINTN) PciOptionRomDescriptor->RomLength;
404 }
405 }
406
407 for (Index = 0; Index < mNumberOfPciRomImages; Index++) {
408 if (mRomImageTable[Index].Seg == PciRootBridgeIo->SegmentNumber &&
409 mRomImageTable[Index].Bus == PciIoDevice->BusNumber &&
410 mRomImageTable[Index].Dev == PciIoDevice->DeviceNumber &&
411 mRomImageTable[Index].Func == PciIoDevice->FunctionNumber ) {
412
413 AddDriver (PciIoDevice, mRomImageTable[Index].ImageHandle);
414 }
415 }
416
417 return EFI_SUCCESS;
418 }
419
420 EFI_STATUS
421 PciRomGetImageMapping (
422 PCI_IO_DEVICE *PciIoDevice
423 )
424 /*++
425
426 Routine Description:
427
428 Arguments:
429
430 Returns:
431
432 --*/
433 // TODO: PciIoDevice - add argument and description to function comment
434 // TODO: EFI_SUCCESS - add return value to function comment
435 {
436 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
437 UINTN Index;
438
439 PciRootBridgeIo = PciIoDevice->PciRootBridgeIo;
440
441 for (Index = 0; Index < mNumberOfPciRomImages; Index++) {
442 if (mRomImageTable[Index].Seg == PciRootBridgeIo->SegmentNumber &&
443 mRomImageTable[Index].Bus == PciIoDevice->BusNumber &&
444 mRomImageTable[Index].Dev == PciIoDevice->DeviceNumber &&
445 mRomImageTable[Index].Func == PciIoDevice->FunctionNumber ) {
446
447 if (mRomImageTable[Index].ImageHandle != NULL) {
448 AddDriver (PciIoDevice, mRomImageTable[Index].ImageHandle);
449 } else {
450 PciIoDevice->PciIo.RomImage = (VOID *) (UINTN) mRomImageTable[Index].RomAddress;
451 PciIoDevice->PciIo.RomSize = (UINTN) mRomImageTable[Index].RomLength;
452 }
453 }
454 }
455
456 return EFI_SUCCESS;
457 }