]> git.proxmox.com Git - mirror_edk2.git/blob - DuetPkg/PciBusNoEnumerationDxe/PciRomTable.c
BaseTools/BinToPcd: Fix Python 2.7.x compatibility issue
[mirror_edk2.git] / DuetPkg / PciBusNoEnumerationDxe / PciRomTable.c
1 /*++
2
3 Copyright (c) 2005 - 2012, 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 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
26 typedef struct {
27 EFI_HANDLE ImageHandle;
28 UINTN Seg;
29 UINT8 Bus;
30 UINT8 Dev;
31 UINT8 Func;
32 } EFI_PCI_ROM_IMAGE_MAPPING;
33
34 UINTN mNumberOfPciRomImages = 0;
35 UINTN mMaxNumberOfPciRomImages = 0;
36 EFI_PCI_ROM_IMAGE_MAPPING *mRomImageTable = NULL;
37
38 CHAR16 mHexDigit[17] = L"0123456789ABCDEF";
39
40 VOID
41 PciRomAddImageMapping (
42 IN EFI_HANDLE ImageHandle,
43 IN UINTN Seg,
44 IN UINT8 Bus,
45 IN UINT8 Dev,
46 IN UINT8 Func
47 )
48
49 {
50 EFI_PCI_ROM_IMAGE_MAPPING *TempMapping;
51
52 if (mNumberOfPciRomImages >= mMaxNumberOfPciRomImages) {
53
54 mMaxNumberOfPciRomImages += 0x20;
55
56 TempMapping = NULL;
57 TempMapping = AllocatePool (mMaxNumberOfPciRomImages * sizeof (EFI_PCI_ROM_IMAGE_MAPPING));
58 if (TempMapping == NULL) {
59 return ;
60 }
61
62 CopyMem (TempMapping, mRomImageTable, mNumberOfPciRomImages * sizeof (EFI_PCI_ROM_IMAGE_MAPPING));
63
64 if (mRomImageTable != NULL) {
65 gBS->FreePool (mRomImageTable);
66 }
67
68 mRomImageTable = TempMapping;
69 }
70
71 mRomImageTable[mNumberOfPciRomImages].ImageHandle = ImageHandle;
72 mRomImageTable[mNumberOfPciRomImages].Seg = Seg;
73 mRomImageTable[mNumberOfPciRomImages].Bus = Bus;
74 mRomImageTable[mNumberOfPciRomImages].Dev = Dev;
75 mRomImageTable[mNumberOfPciRomImages].Func = Func;
76 mNumberOfPciRomImages++;
77 }
78
79 VOID
80 HexToString (
81 CHAR16 *String,
82 UINTN Value,
83 UINTN Digits
84 )
85
86 {
87 for (; Digits > 0; Digits--, String++) {
88 *String = mHexDigit[((Value >> (4*(Digits-1))) & 0x0f)];
89 }
90 }
91
92 EFI_STATUS
93 PciRomLoadEfiDriversFromRomImage (
94 IN EFI_DRIVER_BINDING_PROTOCOL *This,
95 IN EFI_PCI_OPTION_ROM_DESCRIPTOR *PciOptionRomDescriptor
96 )
97 /*++
98
99 Routine Description:
100 Command entry point.
101
102 Arguments:
103 ImageHandle The image handle.
104 SystemTable The system table.
105
106 Returns:
107 EFI_SUCCESS - The command completed successfully
108 EFI_INVALID_PARAMETER - Command usage error
109 EFI_UNSUPPORTED - Protocols unsupported
110 EFI_OUT_OF_RESOURCES - Out of memory
111 Other value - Unknown error
112
113 --*/
114 {
115 VOID *RomBar;
116 UINTN RomSize;
117 CHAR16 *FileName;
118 EFI_PCI_EXPANSION_ROM_HEADER *EfiRomHeader;
119 PCI_DATA_STRUCTURE *Pcir;
120 UINTN ImageIndex;
121 UINTN RomBarOffset;
122 UINT32 ImageSize;
123 UINT16 ImageOffset;
124 EFI_HANDLE ImageHandle;
125 EFI_STATUS Status;
126 EFI_STATUS retStatus;
127 EFI_DEVICE_PATH_PROTOCOL *FilePath;
128 BOOLEAN SkipImage;
129 UINT32 DestinationSize;
130 UINT32 ScratchSize;
131 UINT8 *Scratch;
132 VOID *ImageBuffer;
133 VOID *DecompressedImageBuffer;
134 UINT32 ImageLength;
135 EFI_DECOMPRESS_PROTOCOL *Decompress;
136 UINT32 InitializationSize;
137
138 RomBar = (VOID *) (UINTN) PciOptionRomDescriptor->RomAddress;
139 RomSize = (UINTN) PciOptionRomDescriptor->RomLength;
140 FileName = L"PciRom Seg=00000000 Bus=00 Dev=00 Func=00 Image=0000";
141
142 HexToString (&FileName[11], PciOptionRomDescriptor->Seg, 8);
143 HexToString (&FileName[24], PciOptionRomDescriptor->Bus, 2);
144 HexToString (&FileName[31], PciOptionRomDescriptor->Dev, 2);
145 HexToString (&FileName[39], PciOptionRomDescriptor->Func, 2);
146
147 ImageIndex = 0;
148 retStatus = EFI_NOT_FOUND;
149 RomBarOffset = (UINTN) RomBar;
150
151 do {
152
153 EfiRomHeader = (EFI_PCI_EXPANSION_ROM_HEADER *) (UINTN) RomBarOffset;
154
155
156 if (EfiRomHeader->Signature != PCI_EXPANSION_ROM_HEADER_SIGNATURE) {
157 return retStatus;
158 }
159
160 //
161 // If the pointer to the PCI Data Structure is invalid, no further images can be located.
162 // The PCI Data Structure must be DWORD aligned.
163 //
164 if (EfiRomHeader->PcirOffset == 0 ||
165 (EfiRomHeader->PcirOffset & 3) != 0 ||
166 RomBarOffset - (UINTN)RomBar + EfiRomHeader->PcirOffset + sizeof (PCI_DATA_STRUCTURE) > RomSize) {
167 break;
168 }
169 Pcir = (PCI_DATA_STRUCTURE *) (UINTN) (RomBarOffset + EfiRomHeader->PcirOffset);
170 //
171 // If a valid signature is not present in the PCI Data Structure, no further images can be located.
172 //
173 if (Pcir->Signature != PCI_DATA_STRUCTURE_SIGNATURE) {
174 break;
175 }
176 ImageSize = Pcir->ImageLength * 512;
177 if (RomBarOffset - (UINTN)RomBar + ImageSize > RomSize) {
178 break;
179 }
180
181 if ((Pcir->CodeType == PCI_CODE_TYPE_EFI_IMAGE) &&
182 (EfiRomHeader->EfiSignature == EFI_PCI_EXPANSION_ROM_HEADER_EFISIGNATURE) &&
183 ((EfiRomHeader->EfiSubsystem == EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER) ||
184 (EfiRomHeader->EfiSubsystem == EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER))) {
185
186 ImageOffset = EfiRomHeader->EfiImageHeaderOffset;
187 InitializationSize = EfiRomHeader->InitializationSize * 512;
188
189 if (InitializationSize <= ImageSize && ImageOffset < InitializationSize) {
190
191 ImageBuffer = (VOID *) (UINTN) (RomBarOffset + ImageOffset);
192 ImageLength = InitializationSize - ImageOffset;
193 DecompressedImageBuffer = NULL;
194
195 //
196 // decompress here if needed
197 //
198 SkipImage = FALSE;
199 if (EfiRomHeader->CompressionType > EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED) {
200 SkipImage = TRUE;
201 }
202
203 if (EfiRomHeader->CompressionType == EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED) {
204 Status = gBS->LocateProtocol (&gEfiDecompressProtocolGuid, NULL, (VOID **) &Decompress);
205 if (EFI_ERROR (Status)) {
206 SkipImage = TRUE;
207 } else {
208 SkipImage = TRUE;
209 Status = Decompress->GetInfo (
210 Decompress,
211 ImageBuffer,
212 ImageLength,
213 &DestinationSize,
214 &ScratchSize
215 );
216 if (!EFI_ERROR (Status)) {
217 DecompressedImageBuffer = NULL;
218 DecompressedImageBuffer = AllocatePool (DestinationSize);
219 if (DecompressedImageBuffer != NULL) {
220 Scratch = AllocatePool (ScratchSize);
221 if (Scratch != NULL) {
222 Status = Decompress->Decompress (
223 Decompress,
224 ImageBuffer,
225 ImageLength,
226 DecompressedImageBuffer,
227 DestinationSize,
228 Scratch,
229 ScratchSize
230 );
231 if (!EFI_ERROR (Status)) {
232 ImageBuffer = DecompressedImageBuffer;
233 ImageLength = DestinationSize;
234 SkipImage = FALSE;
235 }
236
237 gBS->FreePool (Scratch);
238 }
239 }
240 }
241 }
242 }
243
244 if (!SkipImage) {
245
246 //
247 // load image and start image
248 //
249
250 HexToString (&FileName[48], ImageIndex, 4);
251 FilePath = FileDevicePath (NULL, FileName);
252
253 Status = gBS->LoadImage (
254 FALSE,
255 This->ImageHandle,
256 FilePath,
257 ImageBuffer,
258 ImageLength,
259 &ImageHandle
260 );
261 if (!EFI_ERROR (Status)) {
262 Status = gBS->StartImage (ImageHandle, NULL, NULL);
263 if (!EFI_ERROR (Status)) {
264 PciRomAddImageMapping (
265 ImageHandle,
266 PciOptionRomDescriptor->Seg,
267 PciOptionRomDescriptor->Bus,
268 PciOptionRomDescriptor->Dev,
269 PciOptionRomDescriptor->Func
270 );
271 retStatus = Status;
272 }
273 }
274 if (FilePath != NULL) {
275 gBS->FreePool (FilePath);
276 }
277 }
278
279 if (DecompressedImageBuffer != NULL) {
280 gBS->FreePool (DecompressedImageBuffer);
281 }
282
283 }
284 }
285
286 RomBarOffset = RomBarOffset + ImageSize;
287 ImageIndex++;
288 } while (((Pcir->Indicator & 0x80) == 0x00) && ((RomBarOffset - (UINTN) RomBar) < RomSize));
289
290 return retStatus;
291 }
292
293 EFI_STATUS
294 PciRomLoadEfiDriversFromOptionRomTable (
295 IN EFI_DRIVER_BINDING_PROTOCOL *This,
296 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo
297 )
298 /*++
299
300 Routine Description:
301
302 Arguments:
303
304 Returns:
305
306 --*/
307 {
308 EFI_STATUS Status;
309 EFI_PCI_OPTION_ROM_TABLE *PciOptionRomTable;
310 EFI_PCI_OPTION_ROM_DESCRIPTOR *PciOptionRomDescriptor;
311 UINTN Index;
312 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors;
313 UINT16 MinBus;
314 UINT16 MaxBus;
315
316 Status = EfiGetSystemConfigurationTable (&gEfiPciOptionRomTableGuid, (VOID **) &PciOptionRomTable);
317 if (EFI_ERROR (Status)) {
318 return EFI_NOT_FOUND;
319 }
320
321 Status = EFI_NOT_FOUND;
322
323 for (Index = 0; Index < PciOptionRomTable->PciOptionRomCount; Index++) {
324 PciOptionRomDescriptor = &PciOptionRomTable->PciOptionRomDescriptors[Index];
325 if (!PciOptionRomDescriptor->DontLoadEfiRom) {
326 if (PciOptionRomDescriptor->Seg == PciRootBridgeIo->SegmentNumber) {
327 Status = PciRootBridgeIo->Configuration (PciRootBridgeIo, (VOID **) &Descriptors);
328 if (EFI_ERROR (Status)) {
329 return Status;
330 }
331
332 PciGetBusRange (&Descriptors, &MinBus, &MaxBus, NULL);
333 if ((MinBus <= PciOptionRomDescriptor->Bus) && (PciOptionRomDescriptor->Bus <= MaxBus)) {
334 Status = PciRomLoadEfiDriversFromRomImage (This, PciOptionRomDescriptor);
335 PciOptionRomDescriptor->DontLoadEfiRom |= 2;
336 }
337 }
338 }
339 }
340
341 return Status;
342 }
343
344 EFI_STATUS
345 PciRomGetRomResourceFromPciOptionRomTable (
346 IN EFI_DRIVER_BINDING_PROTOCOL *This,
347 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo,
348 PCI_IO_DEVICE *PciIoDevice
349 )
350 /*++
351
352 Routine Description:
353
354 Arguments:
355
356 Returns:
357
358 --*/
359 {
360 EFI_STATUS Status;
361 EFI_PCI_OPTION_ROM_TABLE *PciOptionRomTable;
362 EFI_PCI_OPTION_ROM_DESCRIPTOR *PciOptionRomDescriptor;
363 UINTN Index;
364
365 Status = EfiGetSystemConfigurationTable (&gEfiPciOptionRomTableGuid, (VOID **) &PciOptionRomTable);
366 if (EFI_ERROR (Status)) {
367 return EFI_NOT_FOUND;
368 }
369
370 for (Index = 0; Index < PciOptionRomTable->PciOptionRomCount; Index++) {
371 PciOptionRomDescriptor = &PciOptionRomTable->PciOptionRomDescriptors[Index];
372 if (PciOptionRomDescriptor->Seg == PciRootBridgeIo->SegmentNumber &&
373 PciOptionRomDescriptor->Bus == PciIoDevice->BusNumber &&
374 PciOptionRomDescriptor->Dev == PciIoDevice->DeviceNumber &&
375 PciOptionRomDescriptor->Func == PciIoDevice->FunctionNumber ) {
376
377 PciIoDevice->PciIo.RomImage = (VOID *) (UINTN) PciOptionRomDescriptor->RomAddress;
378 PciIoDevice->PciIo.RomSize = (UINTN) PciOptionRomDescriptor->RomLength;
379 }
380 }
381
382 for (Index = 0; Index < mNumberOfPciRomImages; Index++) {
383 if (mRomImageTable[Index].Seg == PciRootBridgeIo->SegmentNumber &&
384 mRomImageTable[Index].Bus == PciIoDevice->BusNumber &&
385 mRomImageTable[Index].Dev == PciIoDevice->DeviceNumber &&
386 mRomImageTable[Index].Func == PciIoDevice->FunctionNumber ) {
387
388 AddDriver (PciIoDevice, mRomImageTable[Index].ImageHandle);
389 }
390 }
391
392 return EFI_SUCCESS;
393 }