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