]> git.proxmox.com Git - mirror_edk2.git/blob - DuetPkg/PciBusNoEnumerationDxe/PciRomTable.c
Patch to remove STATIC modifier. This is on longer recommended by EFI Framework codin...
[mirror_edk2.git] / DuetPkg / PciBusNoEnumerationDxe / PciRomTable.c
1 /*++
2
3 Copyright (c) 2005 - 2007, 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
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
137 RomBar = (VOID *) (UINTN) PciOptionRomDescriptor->RomAddress;
138 RomSize = (UINTN) PciOptionRomDescriptor->RomLength;
139 FileName = L"PciRom Seg=00000000 Bus=00 Dev=00 Func=00 Image=0000";
140
141 HexToString (&FileName[11], PciOptionRomDescriptor->Seg, 8);
142 HexToString (&FileName[24], PciOptionRomDescriptor->Bus, 2);
143 HexToString (&FileName[31], PciOptionRomDescriptor->Dev, 2);
144 HexToString (&FileName[39], PciOptionRomDescriptor->Func, 2);
145
146 ImageIndex = 0;
147 retStatus = EFI_NOT_FOUND;
148 RomBarOffset = (UINTN) RomBar;
149
150 do {
151
152 EfiRomHeader = (EFI_PCI_EXPANSION_ROM_HEADER *) (UINTN) RomBarOffset;
153
154 if (EfiRomHeader->Signature != 0xaa55) {
155 return retStatus;
156 }
157
158 Pcir = (PCI_DATA_STRUCTURE *) (UINTN) (RomBarOffset + EfiRomHeader->PcirOffset);
159 ImageSize = Pcir->ImageLength * 512;
160
161 if ((Pcir->CodeType == PCI_CODE_TYPE_EFI_IMAGE) &&
162 (EfiRomHeader->EfiSignature == EFI_PCI_EXPANSION_ROM_HEADER_EFISIGNATURE) ) {
163
164 if ((EfiRomHeader->EfiSubsystem == EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER) ||
165 (EfiRomHeader->EfiSubsystem == EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER) ) {
166
167 ImageOffset = EfiRomHeader->EfiImageHeaderOffset;
168 ImageSize = EfiRomHeader->InitializationSize * 512;
169
170 ImageBuffer = (VOID *) (UINTN) (RomBarOffset + ImageOffset);
171 ImageLength = ImageSize - ImageOffset;
172 DecompressedImageBuffer = NULL;
173
174 //
175 // decompress here if needed
176 //
177 SkipImage = FALSE;
178 if (EfiRomHeader->CompressionType > EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED) {
179 SkipImage = TRUE;
180 }
181
182 if (EfiRomHeader->CompressionType == EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED) {
183 Status = gBS->LocateProtocol (&gEfiDecompressProtocolGuid, NULL, (VOID **) &Decompress);
184 if (EFI_ERROR (Status)) {
185 SkipImage = TRUE;
186 } else {
187 SkipImage = TRUE;
188 Status = Decompress->GetInfo (
189 Decompress,
190 ImageBuffer,
191 ImageLength,
192 &DestinationSize,
193 &ScratchSize
194 );
195 if (!EFI_ERROR (Status)) {
196 DecompressedImageBuffer = NULL;
197 DecompressedImageBuffer = AllocatePool (DestinationSize);
198 if (DecompressedImageBuffer != NULL) {
199 Scratch = AllocatePool (ScratchSize);
200 if (Scratch != NULL) {
201 Status = Decompress->Decompress (
202 Decompress,
203 ImageBuffer,
204 ImageLength,
205 DecompressedImageBuffer,
206 DestinationSize,
207 Scratch,
208 ScratchSize
209 );
210 if (!EFI_ERROR (Status)) {
211 ImageBuffer = DecompressedImageBuffer;
212 ImageLength = DestinationSize;
213 SkipImage = FALSE;
214 }
215
216 gBS->FreePool (Scratch);
217 }
218 }
219 }
220 }
221 }
222
223 if (!SkipImage) {
224
225 //
226 // load image and start image
227 //
228
229 HexToString (&FileName[48], ImageIndex, 4);
230 FilePath = FileDevicePath (NULL, FileName);
231
232 Status = gBS->LoadImage (
233 FALSE,
234 This->ImageHandle,
235 FilePath,
236 ImageBuffer,
237 ImageLength,
238 &ImageHandle
239 );
240 if (!EFI_ERROR (Status)) {
241 Status = gBS->StartImage (ImageHandle, NULL, NULL);
242 if (!EFI_ERROR (Status)) {
243 PciRomAddImageMapping (
244 ImageHandle,
245 PciOptionRomDescriptor->Seg,
246 PciOptionRomDescriptor->Bus,
247 PciOptionRomDescriptor->Dev,
248 PciOptionRomDescriptor->Func
249 );
250 retStatus = Status;
251 }
252 }
253 if (FilePath != NULL) {
254 gBS->FreePool (FilePath);
255 }
256 }
257
258 if (DecompressedImageBuffer != NULL) {
259 gBS->FreePool (DecompressedImageBuffer);
260 }
261
262 }
263 }
264
265 RomBarOffset = RomBarOffset + ImageSize;
266 ImageIndex++;
267 } while (((Pcir->Indicator & 0x80) == 0x00) && ((RomBarOffset - (UINTN) RomBar) < RomSize));
268
269 return retStatus;
270 }
271
272 EFI_STATUS
273 PciRomLoadEfiDriversFromOptionRomTable (
274 IN EFI_DRIVER_BINDING_PROTOCOL *This,
275 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo
276 )
277 /*++
278
279 Routine Description:
280
281 Arguments:
282
283 Returns:
284
285 --*/
286 {
287 EFI_STATUS Status;
288 EFI_PCI_OPTION_ROM_TABLE *PciOptionRomTable;
289 EFI_PCI_OPTION_ROM_DESCRIPTOR *PciOptionRomDescriptor;
290 UINTN Index;
291 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors;
292 UINT16 MinBus;
293 UINT16 MaxBus;
294
295 Status = EfiGetSystemConfigurationTable (&gEfiPciOptionRomTableGuid, (VOID **) &PciOptionRomTable);
296 if (EFI_ERROR (Status)) {
297 return EFI_NOT_FOUND;
298 }
299
300 Status = EFI_NOT_FOUND;
301
302 for (Index = 0; Index < PciOptionRomTable->PciOptionRomCount; Index++) {
303 PciOptionRomDescriptor = &PciOptionRomTable->PciOptionRomDescriptors[Index];
304 if (!PciOptionRomDescriptor->DontLoadEfiRom) {
305 if (PciOptionRomDescriptor->Seg == PciRootBridgeIo->SegmentNumber) {
306 Status = PciRootBridgeIo->Configuration (PciRootBridgeIo, (VOID **) &Descriptors);
307 if (EFI_ERROR (Status)) {
308 return Status;
309 }
310
311 PciGetBusRange (&Descriptors, &MinBus, &MaxBus, NULL);
312 if ((MinBus <= PciOptionRomDescriptor->Bus) && (PciOptionRomDescriptor->Bus <= MaxBus)) {
313 Status = PciRomLoadEfiDriversFromRomImage (This, PciOptionRomDescriptor);
314 PciOptionRomDescriptor->DontLoadEfiRom |= 2;
315 }
316 }
317 }
318 }
319
320 return Status;
321 }
322
323 EFI_STATUS
324 PciRomGetRomResourceFromPciOptionRomTable (
325 IN EFI_DRIVER_BINDING_PROTOCOL *This,
326 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo,
327 PCI_IO_DEVICE *PciIoDevice
328 )
329 /*++
330
331 Routine Description:
332
333 Arguments:
334
335 Returns:
336
337 --*/
338 {
339 EFI_STATUS Status;
340 EFI_PCI_OPTION_ROM_TABLE *PciOptionRomTable;
341 EFI_PCI_OPTION_ROM_DESCRIPTOR *PciOptionRomDescriptor;
342 UINTN Index;
343
344 Status = EfiGetSystemConfigurationTable (&gEfiPciOptionRomTableGuid, (VOID **) &PciOptionRomTable);
345 if (EFI_ERROR (Status)) {
346 return EFI_NOT_FOUND;
347 }
348
349 for (Index = 0; Index < PciOptionRomTable->PciOptionRomCount; Index++) {
350 PciOptionRomDescriptor = &PciOptionRomTable->PciOptionRomDescriptors[Index];
351 if (PciOptionRomDescriptor->Seg == PciRootBridgeIo->SegmentNumber &&
352 PciOptionRomDescriptor->Bus == PciIoDevice->BusNumber &&
353 PciOptionRomDescriptor->Dev == PciIoDevice->DeviceNumber &&
354 PciOptionRomDescriptor->Func == PciIoDevice->FunctionNumber ) {
355
356 PciIoDevice->PciIo.RomImage = (VOID *) (UINTN) PciOptionRomDescriptor->RomAddress;
357 PciIoDevice->PciIo.RomSize = (UINTN) PciOptionRomDescriptor->RomLength;
358 }
359 }
360
361 for (Index = 0; Index < mNumberOfPciRomImages; Index++) {
362 if (mRomImageTable[Index].Seg == PciRootBridgeIo->SegmentNumber &&
363 mRomImageTable[Index].Bus == PciIoDevice->BusNumber &&
364 mRomImageTable[Index].Dev == PciIoDevice->DeviceNumber &&
365 mRomImageTable[Index].Func == PciIoDevice->FunctionNumber ) {
366
367 AddDriver (PciIoDevice, mRomImageTable[Index].ImageHandle);
368 }
369 }
370
371 return EFI_SUCCESS;
372 }