]>
Commit | Line | Data |
---|---|---|
81a23a0f LL |
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 | } |