blob: 5085431b08a2328fe1c32fe5847a5a0e802310e5 [file] [log] [blame]
Vishal Bhoj82c80712015-12-15 21:13:33 +05301/*++
2
3Copyright (c) 2005 - 2012, Intel Corporation. All rights reserved.<BR>
4This program and the accompanying materials
5are licensed and made available under the terms and conditions of the BSD License
6which accompanies this distribution. The full text of the license may be found at
7http://opensource.org/licenses/bsd-license.php
8
9THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
11
12Module Name:
13
14 PciRomTable.c
15
16Abstract:
17
18 Option Rom Support for PCI Bus Driver
19
20Revision History
21
22--*/
23
24#include "PciBus.h"
25
26typedef struct {
27 EFI_HANDLE ImageHandle;
28 UINTN Seg;
29 UINT8 Bus;
30 UINT8 Dev;
31 UINT8 Func;
32} EFI_PCI_ROM_IMAGE_MAPPING;
33
34UINTN mNumberOfPciRomImages = 0;
35UINTN mMaxNumberOfPciRomImages = 0;
36EFI_PCI_ROM_IMAGE_MAPPING *mRomImageTable = NULL;
37
38CHAR16 mHexDigit[17] = L"0123456789ABCDEF";
39
40VOID
41PciRomAddImageMapping (
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
79VOID
80HexToString (
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
92EFI_STATUS
93PciRomLoadEfiDriversFromRomImage (
94 IN EFI_DRIVER_BINDING_PROTOCOL *This,
95 IN EFI_PCI_OPTION_ROM_DESCRIPTOR *PciOptionRomDescriptor
96 )
97/*++
98
99Routine Description:
100 Command entry point.
101
102Arguments:
103 ImageHandle The image handle.
104 SystemTable The system table.
105
106Returns:
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
293EFI_STATUS
294PciRomLoadEfiDriversFromOptionRomTable (
295 IN EFI_DRIVER_BINDING_PROTOCOL *This,
296 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo
297 )
298/*++
299
300Routine Description:
301
302Arguments:
303
304Returns:
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
344EFI_STATUS
345PciRomGetRomResourceFromPciOptionRomTable (
346 IN EFI_DRIVER_BINDING_PROTOCOL *This,
347 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo,
348 PCI_IO_DEVICE *PciIoDevice
349 )
350/*++
351
352Routine Description:
353
354Arguments:
355
356Returns:
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}