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