1 | /** @file
|
---|
2 |
|
---|
3 | Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
|
---|
4 |
|
---|
5 | SPDX-License-Identifier: BSD-2-Clause-Patent
|
---|
6 |
|
---|
7 | **/
|
---|
8 |
|
---|
9 | #include "LegacyBiosInterface.h"
|
---|
10 | #include <IndustryStandard/Pci30.h>
|
---|
11 |
|
---|
12 | #define PCI_START_ADDRESS(x) (((x) + 0x7ff) & ~0x7ff)
|
---|
13 |
|
---|
14 | #define MAX_BRIDGE_INDEX 0x20
|
---|
15 | typedef struct {
|
---|
16 | UINTN PciSegment;
|
---|
17 | UINTN PciBus;
|
---|
18 | UINTN PciDevice;
|
---|
19 | UINTN PciFunction;
|
---|
20 | UINT8 PrimaryBus;
|
---|
21 | UINT8 SecondaryBus;
|
---|
22 | UINT8 SubordinateBus;
|
---|
23 | } BRIDGE_TABLE;
|
---|
24 |
|
---|
25 | #define ROM_MAX_ENTRIES 24
|
---|
26 | BRIDGE_TABLE Bridges[MAX_BRIDGE_INDEX];
|
---|
27 | UINTN SortedBridgeIndex[MAX_BRIDGE_INDEX];
|
---|
28 | UINTN NumberOfBridges;
|
---|
29 | LEGACY_PNP_EXPANSION_HEADER *mBasePnpPtr;
|
---|
30 | UINT16 mBbsRomSegment;
|
---|
31 | UINTN mHandleCount;
|
---|
32 | EFI_HANDLE mVgaHandle;
|
---|
33 | BOOLEAN mIgnoreBbsUpdateFlag;
|
---|
34 | BOOLEAN mVgaInstallationInProgress = FALSE;
|
---|
35 | UINT32 mRomCount = 0x00;
|
---|
36 | ROM_INSTANCE_ENTRY mRomEntry[ROM_MAX_ENTRIES];
|
---|
37 | EDKII_IOMMU_PROTOCOL *mIoMmu;
|
---|
38 |
|
---|
39 | /**
|
---|
40 | Query shadowed legacy ROM parameters registered by RomShadow() previously.
|
---|
41 |
|
---|
42 | @param PciHandle PCI device whos ROM has been shadowed
|
---|
43 | @param DiskStart DiskStart value from EFI_LEGACY_BIOS_PROTOCOL.InstallPciRom
|
---|
44 | @param DiskEnd DiskEnd value from EFI_LEGACY_BIOS_PROTOCOL.InstallPciRom
|
---|
45 | @param RomShadowAddress Address where ROM was shadowed
|
---|
46 | @param ShadowedSize Runtime size of ROM
|
---|
47 |
|
---|
48 | @retval EFI_SUCCESS Query Logging successful.
|
---|
49 | @retval EFI_NOT_FOUND No logged data found about PciHandle.
|
---|
50 |
|
---|
51 | **/
|
---|
52 | EFI_STATUS
|
---|
53 | GetShadowedRomParameters (
|
---|
54 | IN EFI_HANDLE PciHandle,
|
---|
55 | OUT UINT8 *DiskStart, OPTIONAL
|
---|
56 | OUT UINT8 *DiskEnd, OPTIONAL
|
---|
57 | OUT VOID **RomShadowAddress, OPTIONAL
|
---|
58 | OUT UINTN *ShadowedSize OPTIONAL
|
---|
59 | )
|
---|
60 | {
|
---|
61 | EFI_STATUS Status;
|
---|
62 | EFI_PCI_IO_PROTOCOL *PciIo;
|
---|
63 | UINTN Index;
|
---|
64 | UINTN PciSegment;
|
---|
65 | UINTN PciBus;
|
---|
66 | UINTN PciDevice;
|
---|
67 | UINTN PciFunction;
|
---|
68 |
|
---|
69 | //
|
---|
70 | // Get the PCI I/O Protocol on PciHandle
|
---|
71 | //
|
---|
72 | Status = gBS->HandleProtocol (
|
---|
73 | PciHandle,
|
---|
74 | &gEfiPciIoProtocolGuid,
|
---|
75 | (VOID **) &PciIo
|
---|
76 | );
|
---|
77 | if (EFI_ERROR (Status)) {
|
---|
78 | return Status;
|
---|
79 | }
|
---|
80 |
|
---|
81 | //
|
---|
82 | // Get the location of the PCI device
|
---|
83 | //
|
---|
84 | PciIo->GetLocation (
|
---|
85 | PciIo,
|
---|
86 | &PciSegment,
|
---|
87 | &PciBus,
|
---|
88 | &PciDevice,
|
---|
89 | &PciFunction
|
---|
90 | );
|
---|
91 |
|
---|
92 | for(Index = 0; Index < mRomCount; Index++) {
|
---|
93 | if ((mRomEntry[Index].PciSegment == PciSegment) &&
|
---|
94 | (mRomEntry[Index].PciBus == PciBus) &&
|
---|
95 | (mRomEntry[Index].PciDevice == PciDevice) &&
|
---|
96 | (mRomEntry[Index].PciFunction == PciFunction)) {
|
---|
97 | break;
|
---|
98 | }
|
---|
99 | }
|
---|
100 |
|
---|
101 | if (Index == mRomCount) {
|
---|
102 | return EFI_NOT_FOUND;
|
---|
103 | }
|
---|
104 |
|
---|
105 | if (DiskStart != NULL) {
|
---|
106 | *DiskStart = mRomEntry[Index].DiskStart;
|
---|
107 | }
|
---|
108 |
|
---|
109 | if (DiskEnd != NULL) {
|
---|
110 | *DiskEnd = mRomEntry[Index].DiskEnd;
|
---|
111 | }
|
---|
112 |
|
---|
113 | if (RomShadowAddress != NULL) {
|
---|
114 | *RomShadowAddress = (VOID *)(UINTN)mRomEntry[Index].ShadowAddress;
|
---|
115 | }
|
---|
116 |
|
---|
117 | if (ShadowedSize != NULL) {
|
---|
118 | *ShadowedSize = mRomEntry[Index].ShadowedSize;
|
---|
119 | }
|
---|
120 |
|
---|
121 | return EFI_SUCCESS;
|
---|
122 | }
|
---|
123 |
|
---|
124 | /**
|
---|
125 | Every legacy ROM that is shadowed by the Legacy BIOS driver will be
|
---|
126 | registered into this API so that the policy code can know what has
|
---|
127 | happend
|
---|
128 |
|
---|
129 | @param PciHandle PCI device whos ROM is being shadowed
|
---|
130 | @param ShadowAddress Address that ROM was shadowed
|
---|
131 | @param ShadowedSize Runtime size of ROM
|
---|
132 | @param DiskStart DiskStart value from
|
---|
133 | EFI_LEGACY_BIOS_PROTOCOL.InstallPciRom
|
---|
134 | @param DiskEnd DiskEnd value from
|
---|
135 | EFI_LEGACY_BIOS_PROTOCOL.InstallPciRom
|
---|
136 |
|
---|
137 | @retval EFI_SUCCESS Logging successful.
|
---|
138 | @retval EFI_OUT_OF_RESOURCES No remaining room for registering another option
|
---|
139 | ROM.
|
---|
140 |
|
---|
141 | **/
|
---|
142 | EFI_STATUS
|
---|
143 | RomShadow (
|
---|
144 | IN EFI_HANDLE PciHandle,
|
---|
145 | IN UINT32 ShadowAddress,
|
---|
146 | IN UINT32 ShadowedSize,
|
---|
147 | IN UINT8 DiskStart,
|
---|
148 | IN UINT8 DiskEnd
|
---|
149 | )
|
---|
150 | {
|
---|
151 | EFI_STATUS Status;
|
---|
152 | EFI_PCI_IO_PROTOCOL *PciIo;
|
---|
153 |
|
---|
154 | //
|
---|
155 | // See if there is room to register another option ROM
|
---|
156 | //
|
---|
157 | if (mRomCount >= ROM_MAX_ENTRIES) {
|
---|
158 | return EFI_OUT_OF_RESOURCES;
|
---|
159 | }
|
---|
160 | //
|
---|
161 | // Get the PCI I/O Protocol on PciHandle
|
---|
162 | //
|
---|
163 | Status = gBS->HandleProtocol (
|
---|
164 | PciHandle,
|
---|
165 | &gEfiPciIoProtocolGuid,
|
---|
166 | (VOID **) &PciIo
|
---|
167 | );
|
---|
168 | if (EFI_ERROR (Status)) {
|
---|
169 | return Status;
|
---|
170 | }
|
---|
171 | //
|
---|
172 | // Get the location of the PCI device
|
---|
173 | //
|
---|
174 | PciIo->GetLocation (
|
---|
175 | PciIo,
|
---|
176 | &mRomEntry[mRomCount].PciSegment,
|
---|
177 | &mRomEntry[mRomCount].PciBus,
|
---|
178 | &mRomEntry[mRomCount].PciDevice,
|
---|
179 | &mRomEntry[mRomCount].PciFunction
|
---|
180 | );
|
---|
181 | mRomEntry[mRomCount].ShadowAddress = ShadowAddress;
|
---|
182 | mRomEntry[mRomCount].ShadowedSize = ShadowedSize;
|
---|
183 | mRomEntry[mRomCount].DiskStart = DiskStart;
|
---|
184 | mRomEntry[mRomCount].DiskEnd = DiskEnd;
|
---|
185 |
|
---|
186 | mRomCount++;
|
---|
187 |
|
---|
188 | return EFI_SUCCESS;
|
---|
189 | }
|
---|
190 |
|
---|
191 |
|
---|
192 | /**
|
---|
193 | Return EFI_SUCCESS if PciHandle has had a legacy BIOS ROM shadowed. This
|
---|
194 | information represents every call to RomShadow ()
|
---|
195 |
|
---|
196 | @param PciHandle PCI device to get status for
|
---|
197 |
|
---|
198 | @retval EFI_SUCCESS Legacy ROM loaded for this device
|
---|
199 | @retval EFI_NOT_FOUND No Legacy ROM loaded for this device
|
---|
200 |
|
---|
201 | **/
|
---|
202 | EFI_STATUS
|
---|
203 | IsLegacyRom (
|
---|
204 | IN EFI_HANDLE PciHandle
|
---|
205 | )
|
---|
206 | {
|
---|
207 | EFI_STATUS Status;
|
---|
208 | EFI_PCI_IO_PROTOCOL *PciIo;
|
---|
209 | UINTN Index;
|
---|
210 | UINTN Segment;
|
---|
211 | UINTN Bus;
|
---|
212 | UINTN Device;
|
---|
213 | UINTN Function;
|
---|
214 |
|
---|
215 | //
|
---|
216 | // Get the PCI I/O Protocol on PciHandle
|
---|
217 | //
|
---|
218 | Status = gBS->HandleProtocol (
|
---|
219 | PciHandle,
|
---|
220 | &gEfiPciIoProtocolGuid,
|
---|
221 | (VOID **) &PciIo
|
---|
222 | );
|
---|
223 | if (EFI_ERROR (Status)) {
|
---|
224 | return Status;
|
---|
225 | }
|
---|
226 | //
|
---|
227 | // Get the location of the PCI device
|
---|
228 | //
|
---|
229 | PciIo->GetLocation (
|
---|
230 | PciIo,
|
---|
231 | &Segment,
|
---|
232 | &Bus,
|
---|
233 | &Device,
|
---|
234 | &Function
|
---|
235 | );
|
---|
236 |
|
---|
237 | //
|
---|
238 | // See if the option ROM from PciHandle has been previously posted
|
---|
239 | //
|
---|
240 | for (Index = 0; Index < mRomCount; Index++) {
|
---|
241 | if (mRomEntry[Index].PciSegment == Segment &&
|
---|
242 | mRomEntry[Index].PciBus == Bus &&
|
---|
243 | mRomEntry[Index].PciDevice == Device &&
|
---|
244 | mRomEntry[Index].PciFunction == Function
|
---|
245 | ) {
|
---|
246 | return EFI_SUCCESS;
|
---|
247 | }
|
---|
248 | }
|
---|
249 |
|
---|
250 | return EFI_NOT_FOUND;
|
---|
251 | }
|
---|
252 |
|
---|
253 | /**
|
---|
254 | Find the PC-AT ROM Image in the raw PCI Option ROM. Also return the
|
---|
255 | related information from the header.
|
---|
256 |
|
---|
257 | @param Csm16Revision The PCI interface version of underlying CSM16
|
---|
258 | @param VendorId Vendor ID of the PCI device
|
---|
259 | @param DeviceId Device ID of the PCI device
|
---|
260 | @param Rom On input pointing to beginning of the raw PCI OpROM
|
---|
261 | On output pointing to the first legacy PCI OpROM
|
---|
262 | @param ImageSize On input is the size of Raw PCI Rom
|
---|
263 | On output is the size of the first legacy PCI ROM
|
---|
264 | @param MaxRuntimeImageLength The max runtime image length only valid if OpRomRevision >= 3
|
---|
265 | @param OpRomRevision Revision of the PCI Rom
|
---|
266 | @param ConfigUtilityCodeHeader Pointer to Configuration Utility Code Header
|
---|
267 |
|
---|
268 | @retval EFI_SUCCESS Successfully find the legacy PCI ROM
|
---|
269 | @retval EFI_NOT_FOUND Failed to find the legacy PCI ROM
|
---|
270 |
|
---|
271 | **/
|
---|
272 | EFI_STATUS
|
---|
273 | GetPciLegacyRom (
|
---|
274 | IN UINT16 Csm16Revision,
|
---|
275 | IN UINT16 VendorId,
|
---|
276 | IN UINT16 DeviceId,
|
---|
277 | IN OUT VOID **Rom,
|
---|
278 | IN OUT UINTN *ImageSize,
|
---|
279 | OUT UINTN *MaxRuntimeImageLength, OPTIONAL
|
---|
280 | OUT UINT8 *OpRomRevision, OPTIONAL
|
---|
281 | OUT VOID **ConfigUtilityCodeHeader OPTIONAL
|
---|
282 | )
|
---|
283 | {
|
---|
284 | BOOLEAN Match;
|
---|
285 | UINT16 *DeviceIdList;
|
---|
286 | EFI_PCI_ROM_HEADER RomHeader;
|
---|
287 | PCI_3_0_DATA_STRUCTURE *Pcir;
|
---|
288 | VOID *BackupImage;
|
---|
289 | VOID *BestImage;
|
---|
290 |
|
---|
291 |
|
---|
292 | if (*ImageSize < sizeof (EFI_PCI_ROM_HEADER)) {
|
---|
293 | return EFI_NOT_FOUND;
|
---|
294 | }
|
---|
295 |
|
---|
296 | BestImage = NULL;
|
---|
297 | BackupImage = NULL;
|
---|
298 | RomHeader.Raw = *Rom;
|
---|
299 | while (RomHeader.Generic->Signature == PCI_EXPANSION_ROM_HEADER_SIGNATURE) {
|
---|
300 | if (RomHeader.Generic->PcirOffset == 0 ||
|
---|
301 | (RomHeader.Generic->PcirOffset & 3) !=0 ||
|
---|
302 | *ImageSize < RomHeader.Raw - (UINT8 *) *Rom + RomHeader.Generic->PcirOffset + sizeof (PCI_DATA_STRUCTURE)) {
|
---|
303 | break;
|
---|
304 | }
|
---|
305 |
|
---|
306 | Pcir = (PCI_3_0_DATA_STRUCTURE *) (RomHeader.Raw + RomHeader.Generic->PcirOffset);
|
---|
307 | //
|
---|
308 | // Check signature in the PCI Data Structure.
|
---|
309 | //
|
---|
310 | if (Pcir->Signature != PCI_DATA_STRUCTURE_SIGNATURE) {
|
---|
311 | break;
|
---|
312 | }
|
---|
313 |
|
---|
314 | if (((UINTN)RomHeader.Raw - (UINTN)*Rom) + Pcir->ImageLength * 512 > *ImageSize) {
|
---|
315 | break;
|
---|
316 | }
|
---|
317 |
|
---|
318 | if (Pcir->CodeType == PCI_CODE_TYPE_PCAT_IMAGE) {
|
---|
319 | Match = FALSE;
|
---|
320 | if (Pcir->VendorId == VendorId) {
|
---|
321 | if (Pcir->DeviceId == DeviceId) {
|
---|
322 | Match = TRUE;
|
---|
323 | } else if ((Pcir->Revision >= 3) && (Pcir->DeviceListOffset != 0)) {
|
---|
324 | DeviceIdList = (UINT16 *)(((UINT8 *) Pcir) + Pcir->DeviceListOffset);
|
---|
325 | //
|
---|
326 | // Checking the device list
|
---|
327 | //
|
---|
328 | while (*DeviceIdList != 0) {
|
---|
329 | if (*DeviceIdList == DeviceId) {
|
---|
330 | Match = TRUE;
|
---|
331 | break;
|
---|
332 | }
|
---|
333 | DeviceIdList ++;
|
---|
334 | }
|
---|
335 | }
|
---|
336 | }
|
---|
337 |
|
---|
338 | if (Match) {
|
---|
339 | if (Csm16Revision >= 0x0300) {
|
---|
340 | //
|
---|
341 | // Case 1: CSM16 3.0
|
---|
342 | //
|
---|
343 | if (Pcir->Revision >= 3) {
|
---|
344 | //
|
---|
345 | // case 1.1: meets OpRom 3.0
|
---|
346 | // Perfect!!!
|
---|
347 | //
|
---|
348 | BestImage = RomHeader.Raw;
|
---|
349 | break;
|
---|
350 | } else {
|
---|
351 | //
|
---|
352 | // case 1.2: meets OpRom 2.x
|
---|
353 | // Store it and try to find the OpRom 3.0
|
---|
354 | //
|
---|
355 | BackupImage = RomHeader.Raw;
|
---|
356 | }
|
---|
357 | } else {
|
---|
358 | //
|
---|
359 | // Case 2: CSM16 2.x
|
---|
360 | //
|
---|
361 | if (Pcir->Revision >= 3) {
|
---|
362 | //
|
---|
363 | // case 2.1: meets OpRom 3.0
|
---|
364 | // Store it and try to find the OpRom 2.x
|
---|
365 | //
|
---|
366 | BackupImage = RomHeader.Raw;
|
---|
367 | } else {
|
---|
368 | //
|
---|
369 | // case 2.2: meets OpRom 2.x
|
---|
370 | // Perfect!!!
|
---|
371 | //
|
---|
372 | BestImage = RomHeader.Raw;
|
---|
373 | break;
|
---|
374 | }
|
---|
375 | }
|
---|
376 | } else {
|
---|
377 | DEBUG ((EFI_D_ERROR, "GetPciLegacyRom - OpRom not match (%04x-%04x)\n", (UINTN)VendorId, (UINTN)DeviceId));
|
---|
378 | }
|
---|
379 | }
|
---|
380 |
|
---|
381 | if ((Pcir->Indicator & 0x80) == 0x80) {
|
---|
382 | break;
|
---|
383 | } else {
|
---|
384 | RomHeader.Raw += 512 * Pcir->ImageLength;
|
---|
385 | }
|
---|
386 | }
|
---|
387 |
|
---|
388 | if (BestImage == NULL) {
|
---|
389 | if (BackupImage == NULL) {
|
---|
390 | return EFI_NOT_FOUND;
|
---|
391 | }
|
---|
392 | //
|
---|
393 | // The versions of CSM16 and OpRom don't match exactly
|
---|
394 | //
|
---|
395 | BestImage = BackupImage;
|
---|
396 | }
|
---|
397 | RomHeader.Raw = BestImage;
|
---|
398 | Pcir = (PCI_3_0_DATA_STRUCTURE *) (RomHeader.Raw + RomHeader.Generic->PcirOffset);
|
---|
399 | *Rom = BestImage;
|
---|
400 | *ImageSize = Pcir->ImageLength * 512;
|
---|
401 |
|
---|
402 | if (MaxRuntimeImageLength != NULL) {
|
---|
403 | if (Pcir->Revision < 3) {
|
---|
404 | *MaxRuntimeImageLength = 0;
|
---|
405 | } else {
|
---|
406 | *MaxRuntimeImageLength = Pcir->MaxRuntimeImageLength * 512;
|
---|
407 | }
|
---|
408 | }
|
---|
409 |
|
---|
410 | if (OpRomRevision != NULL) {
|
---|
411 | //
|
---|
412 | // Optional return PCI Data Structure revision
|
---|
413 | //
|
---|
414 | if (Pcir->Length >= 0x1C) {
|
---|
415 | *OpRomRevision = Pcir->Revision;
|
---|
416 | } else {
|
---|
417 | *OpRomRevision = 0;
|
---|
418 | }
|
---|
419 | }
|
---|
420 |
|
---|
421 | if (ConfigUtilityCodeHeader != NULL) {
|
---|
422 | //
|
---|
423 | // Optional return ConfigUtilityCodeHeaderOffset supported by the PC-AT ROM
|
---|
424 | //
|
---|
425 | if ((Pcir->Revision < 3) || (Pcir->ConfigUtilityCodeHeaderOffset == 0)) {
|
---|
426 | *ConfigUtilityCodeHeader = NULL;
|
---|
427 | } else {
|
---|
428 | *ConfigUtilityCodeHeader = RomHeader.Raw + Pcir->ConfigUtilityCodeHeaderOffset;
|
---|
429 | }
|
---|
430 | }
|
---|
431 |
|
---|
432 | return EFI_SUCCESS;
|
---|
433 | }
|
---|
434 |
|
---|
435 | /**
|
---|
436 | Build a table of bridge info for PIRQ translation.
|
---|
437 |
|
---|
438 | @param RoutingTable RoutingTable obtained from Platform.
|
---|
439 | @param RoutingTableEntries Number of RoutingTable entries.
|
---|
440 |
|
---|
441 | @retval EFI_SUCCESS New Subordinate bus.
|
---|
442 | @retval EFI_NOT_FOUND No more Subordinate busses.
|
---|
443 |
|
---|
444 | **/
|
---|
445 | EFI_STATUS
|
---|
446 | CreateBridgeTable (
|
---|
447 | IN EFI_LEGACY_IRQ_ROUTING_ENTRY *RoutingTable,
|
---|
448 | IN UINTN RoutingTableEntries
|
---|
449 | )
|
---|
450 | {
|
---|
451 | EFI_STATUS Status;
|
---|
452 | UINTN HandleCount;
|
---|
453 | EFI_HANDLE *HandleBuffer;
|
---|
454 | UINTN BridgeIndex;
|
---|
455 | UINTN Index;
|
---|
456 | UINTN Index1;
|
---|
457 | EFI_PCI_IO_PROTOCOL *PciIo;
|
---|
458 | PCI_TYPE01 PciConfigHeader;
|
---|
459 | BRIDGE_TABLE SlotBridges[MAX_BRIDGE_INDEX];
|
---|
460 | UINTN SlotBridgeIndex;
|
---|
461 |
|
---|
462 | BridgeIndex = 0x00;
|
---|
463 | SlotBridgeIndex = 0x00;
|
---|
464 |
|
---|
465 | //
|
---|
466 | // Assumption is table is built from low bus to high bus numbers.
|
---|
467 | //
|
---|
468 | Status = gBS->LocateHandleBuffer (
|
---|
469 | ByProtocol,
|
---|
470 | &gEfiPciIoProtocolGuid,
|
---|
471 | NULL,
|
---|
472 | &HandleCount,
|
---|
473 | &HandleBuffer
|
---|
474 | );
|
---|
475 | if (EFI_ERROR (Status)) {
|
---|
476 | return EFI_NOT_FOUND;
|
---|
477 | }
|
---|
478 | for (Index = 0; Index < HandleCount; Index++) {
|
---|
479 | Status = gBS->HandleProtocol (
|
---|
480 | HandleBuffer[Index],
|
---|
481 | &gEfiPciIoProtocolGuid,
|
---|
482 | (VOID **) &PciIo
|
---|
483 | );
|
---|
484 | if (EFI_ERROR (Status)) {
|
---|
485 | continue;
|
---|
486 | }
|
---|
487 |
|
---|
488 | PciIo->Pci.Read (
|
---|
489 | PciIo,
|
---|
490 | EfiPciIoWidthUint32,
|
---|
491 | 0,
|
---|
492 | sizeof (PciConfigHeader) / sizeof (UINT32),
|
---|
493 | &PciConfigHeader
|
---|
494 | );
|
---|
495 |
|
---|
496 | if (IS_PCI_P2P (&PciConfigHeader) && (BridgeIndex < MAX_BRIDGE_INDEX)) {
|
---|
497 | PciIo->GetLocation (
|
---|
498 | PciIo,
|
---|
499 | &Bridges[BridgeIndex].PciSegment,
|
---|
500 | &Bridges[BridgeIndex].PciBus,
|
---|
501 | &Bridges[BridgeIndex].PciDevice,
|
---|
502 | &Bridges[BridgeIndex].PciFunction
|
---|
503 | );
|
---|
504 |
|
---|
505 | Bridges[BridgeIndex].PrimaryBus = PciConfigHeader.Bridge.PrimaryBus;
|
---|
506 |
|
---|
507 | Bridges[BridgeIndex].SecondaryBus = PciConfigHeader.Bridge.SecondaryBus;
|
---|
508 |
|
---|
509 | Bridges[BridgeIndex].SubordinateBus = PciConfigHeader.Bridge.SubordinateBus;
|
---|
510 |
|
---|
511 | for (Index1 = 0; Index1 < RoutingTableEntries; Index1++){
|
---|
512 | //
|
---|
513 | // Test whether we have found the Bridge in the slot, must be the one that directly interfaced to the board
|
---|
514 | // Once we find one, store it in the SlotBridges[]
|
---|
515 | //
|
---|
516 | if ((RoutingTable[Index1].Slot != 0) && (Bridges[BridgeIndex].PrimaryBus == RoutingTable[Index1].Bus)
|
---|
517 | && ((Bridges[BridgeIndex].PciDevice << 3) == RoutingTable[Index1].Device)) {
|
---|
518 | CopyMem (&SlotBridges[SlotBridgeIndex], &Bridges[BridgeIndex], sizeof (BRIDGE_TABLE));
|
---|
519 | SlotBridgeIndex++;
|
---|
520 |
|
---|
521 | break;
|
---|
522 | }
|
---|
523 | }
|
---|
524 |
|
---|
525 | ++BridgeIndex;
|
---|
526 | }
|
---|
527 | }
|
---|
528 |
|
---|
529 | //
|
---|
530 | // Pack up Bridges by removing those useless ones
|
---|
531 | //
|
---|
532 | for (Index = 0; Index < BridgeIndex;){
|
---|
533 | for (Index1 = 0; Index1 < SlotBridgeIndex; Index1++) {
|
---|
534 | if (((Bridges[Index].PciBus == SlotBridges[Index1].PrimaryBus) && (Bridges[Index].PciDevice == SlotBridges[Index1].PciDevice)) ||
|
---|
535 | ((Bridges[Index].PciBus >= SlotBridges[Index1].SecondaryBus) && (Bridges[Index].PciBus <= SlotBridges[Index1].SubordinateBus))) {
|
---|
536 | //
|
---|
537 | // We have found one that meets our criteria
|
---|
538 | //
|
---|
539 | Index++;
|
---|
540 | break;
|
---|
541 | }
|
---|
542 | }
|
---|
543 |
|
---|
544 | //
|
---|
545 | // This one doesn't meet criteria, pack it
|
---|
546 | //
|
---|
547 | if (Index1 >= SlotBridgeIndex) {
|
---|
548 | for (Index1 = Index; BridgeIndex > 1 && Index1 < BridgeIndex - 1 ; Index1++) {
|
---|
549 | CopyMem (&Bridges[Index1], &Bridges[Index1 + 1], sizeof (BRIDGE_TABLE));
|
---|
550 | }
|
---|
551 |
|
---|
552 | BridgeIndex--;
|
---|
553 | }
|
---|
554 | }
|
---|
555 |
|
---|
556 | NumberOfBridges = BridgeIndex;
|
---|
557 |
|
---|
558 | //
|
---|
559 | // Sort bridges low to high by Secondary bus followed by subordinate bus
|
---|
560 | //
|
---|
561 | if (NumberOfBridges > 1) {
|
---|
562 | Index = 0;
|
---|
563 | do {
|
---|
564 | SortedBridgeIndex[Index] = Index;
|
---|
565 | ++Index;
|
---|
566 | } while (Index < NumberOfBridges);
|
---|
567 |
|
---|
568 | for (Index = 0; Index < NumberOfBridges - 1; Index++) {
|
---|
569 | for (Index1 = Index + 1; Index1 < NumberOfBridges; Index1++) {
|
---|
570 | if (Bridges[Index].SecondaryBus > Bridges[Index1].SecondaryBus) {
|
---|
571 | SortedBridgeIndex[Index] = Index1;
|
---|
572 | SortedBridgeIndex[Index1] = Index;
|
---|
573 | }
|
---|
574 |
|
---|
575 | if ((Bridges[Index].SecondaryBus == Bridges[Index1].SecondaryBus) &&
|
---|
576 | (Bridges[Index].SubordinateBus > Bridges[Index1].SubordinateBus)
|
---|
577 | ) {
|
---|
578 | SortedBridgeIndex[Index] = Index1;
|
---|
579 | SortedBridgeIndex[Index1] = Index;
|
---|
580 | }
|
---|
581 | }
|
---|
582 | }
|
---|
583 | }
|
---|
584 | FreePool (HandleBuffer);
|
---|
585 | return EFI_SUCCESS;
|
---|
586 | }
|
---|
587 |
|
---|
588 |
|
---|
589 | /**
|
---|
590 | Find base Bridge for device.
|
---|
591 |
|
---|
592 | @param Private Legacy BIOS Instance data
|
---|
593 | @param PciBus Input = Bus of device.
|
---|
594 | @param PciDevice Input = Device.
|
---|
595 | @param RoutingTable The platform specific routing table
|
---|
596 | @param RoutingTableEntries Number of entries in table
|
---|
597 |
|
---|
598 | @retval EFI_SUCCESS At base bus.
|
---|
599 | @retval EFI_NOT_FOUND Behind a bridge.
|
---|
600 |
|
---|
601 | **/
|
---|
602 | EFI_STATUS
|
---|
603 | GetBaseBus (
|
---|
604 | IN LEGACY_BIOS_INSTANCE *Private,
|
---|
605 | IN UINTN PciBus,
|
---|
606 | IN UINTN PciDevice,
|
---|
607 | IN EFI_LEGACY_IRQ_ROUTING_ENTRY *RoutingTable,
|
---|
608 | IN UINTN RoutingTableEntries
|
---|
609 | )
|
---|
610 | {
|
---|
611 | UINTN Index;
|
---|
612 | for (Index = 0; Index < RoutingTableEntries; Index++) {
|
---|
613 | if ((RoutingTable[Index].Bus == PciBus) && (RoutingTable[Index].Device == (PciDevice << 3))) {
|
---|
614 | return EFI_SUCCESS;
|
---|
615 | }
|
---|
616 | }
|
---|
617 |
|
---|
618 | return EFI_NOT_FOUND;
|
---|
619 | }
|
---|
620 |
|
---|
621 | /**
|
---|
622 | Translate PIRQ through busses
|
---|
623 |
|
---|
624 | @param Private Legacy BIOS Instance data
|
---|
625 | @param PciBus Input = Bus of device. Output = Translated Bus
|
---|
626 | @param PciDevice Input = Device. Output = Translated Device
|
---|
627 | @param PciFunction Input = Function. Output = Translated Function
|
---|
628 | @param PirqIndex Input = Original PIRQ index. If single function
|
---|
629 | device then 0, otherwise 0-3.
|
---|
630 | Output = Translated Index
|
---|
631 |
|
---|
632 | @retval EFI_SUCCESS Pirq successfully translated.
|
---|
633 | @retval EFI_NOT_FOUND The device is not behind any known bridge.
|
---|
634 |
|
---|
635 | **/
|
---|
636 | EFI_STATUS
|
---|
637 | TranslateBusPirq (
|
---|
638 | IN LEGACY_BIOS_INSTANCE *Private,
|
---|
639 | IN OUT UINTN *PciBus,
|
---|
640 | IN OUT UINTN *PciDevice,
|
---|
641 | IN OUT UINTN *PciFunction,
|
---|
642 | IN OUT UINT8 *PirqIndex
|
---|
643 | )
|
---|
644 | {
|
---|
645 | /*
|
---|
646 | This routine traverses the PCI busses from base slot
|
---|
647 | and translates the PIRQ register to the appropriate one.
|
---|
648 |
|
---|
649 | Example:
|
---|
650 |
|
---|
651 | Bus 0, Device 1 is PCI-PCI bridge that all PCI slots reside on.
|
---|
652 | Primary bus# = 0
|
---|
653 | Secondary bus # = 1
|
---|
654 | Subordinate bus # is highest bus # behind this bus
|
---|
655 | Bus 1, Device 0 is Slot 0 and is not a bridge.
|
---|
656 | Bus 1, Device 1 is Slot 1 and is a bridge.
|
---|
657 | Slot PIRQ routing is A,B,C,D.
|
---|
658 | Primary bus # = 1
|
---|
659 | Secondary bus # = 2
|
---|
660 | Subordinate bus # = 5
|
---|
661 | Bus 2, Device 6 is a bridge. It has no bridges behind it.
|
---|
662 | Primary bus # = 2
|
---|
663 | Secondary bus # = 3
|
---|
664 | Subordinate bus # = 3
|
---|
665 | Bridge PIRQ routing is C,D,A,B
|
---|
666 | Bus 2, Device 7 is a bridge. It has 1 bridge behind it.
|
---|
667 | Primary bus # = 2
|
---|
668 | Secondary bus = 4 Device 6 takes bus 2.
|
---|
669 | Subordinate bus = 5.
|
---|
670 | Bridge PIRQ routing is D,A,B,C
|
---|
671 | Bus 4, Device 2 is a bridge. It has no bridges behind it.
|
---|
672 | Primary bus # = 4
|
---|
673 | Secondary bus # = 5
|
---|
674 | Subordinate bus = 5
|
---|
675 | Bridge PIRQ routing is B,C,D,A
|
---|
676 | Bus 5, Device 1 is to be programmed.
|
---|
677 | Device PIRQ routing is C,D,A,B
|
---|
678 |
|
---|
679 |
|
---|
680 | Search busses starting from slot bus for final bus >= Secondary bus and
|
---|
681 | final bus <= Suborninate bus. Assumption is bus entries increase in bus
|
---|
682 | number.
|
---|
683 | Starting PIRQ is A,B,C,D.
|
---|
684 | Bus 2, Device 7 satisfies search criteria. Rotate (A,B,C,D) left by device
|
---|
685 | 7 modulo 4 giving (D,A,B,C).
|
---|
686 | Bus 4, Device 2 satisfies search criteria. Rotate (D,A,B,C) left by 2 giving
|
---|
687 | (B,C,D,A).
|
---|
688 | No other busses match criteria. Device to be programmed is Bus 5, Device 1.
|
---|
689 | Rotate (B,C,D,A) by 1 giving C,D,A,B. Translated PIRQ is C.
|
---|
690 |
|
---|
691 | */
|
---|
692 | UINTN LocalBus;
|
---|
693 | UINTN LocalDevice;
|
---|
694 | UINTN BaseBus;
|
---|
695 | UINTN BaseDevice;
|
---|
696 | UINTN BaseFunction;
|
---|
697 | UINT8 LocalPirqIndex;
|
---|
698 | BOOLEAN BaseIndexFlag;
|
---|
699 | UINTN BridgeIndex;
|
---|
700 | UINTN SBridgeIndex;
|
---|
701 | BaseIndexFlag = FALSE;
|
---|
702 | BridgeIndex = 0x00;
|
---|
703 |
|
---|
704 | LocalPirqIndex = *PirqIndex;
|
---|
705 | LocalBus = *PciBus;
|
---|
706 | LocalDevice = *PciDevice;
|
---|
707 | BaseBus = *PciBus;
|
---|
708 | BaseDevice = *PciDevice;
|
---|
709 | BaseFunction = *PciFunction;
|
---|
710 |
|
---|
711 | //
|
---|
712 | // LocalPirqIndex list PIRQs in rotated fashion
|
---|
713 | // = 0 A,B,C,D
|
---|
714 | // = 1 B,C,D,A
|
---|
715 | // = 2 C,D,A,B
|
---|
716 | // = 3 D,A,B,C
|
---|
717 | //
|
---|
718 |
|
---|
719 | for (BridgeIndex = 0; BridgeIndex < NumberOfBridges; BridgeIndex++) {
|
---|
720 | SBridgeIndex = SortedBridgeIndex[BridgeIndex];
|
---|
721 | //
|
---|
722 | // Check if device behind this bridge
|
---|
723 | //
|
---|
724 | if ((LocalBus >= Bridges[SBridgeIndex].SecondaryBus) && (LocalBus <= Bridges[SBridgeIndex].SubordinateBus)) {
|
---|
725 | //
|
---|
726 | // If BaseIndexFlag = FALSE then have found base bridge, i.e
|
---|
727 | // bridge in slot. Save info for use by IRQ routing table.
|
---|
728 | //
|
---|
729 | if (!BaseIndexFlag) {
|
---|
730 | BaseBus = Bridges[SBridgeIndex].PciBus;
|
---|
731 | BaseDevice = Bridges[SBridgeIndex].PciDevice;
|
---|
732 | BaseFunction = Bridges[SBridgeIndex].PciFunction;
|
---|
733 | BaseIndexFlag = TRUE;
|
---|
734 | } else {
|
---|
735 | LocalPirqIndex = (UINT8) ((LocalPirqIndex + (UINT8)Bridges[SBridgeIndex].PciDevice)%4);
|
---|
736 | }
|
---|
737 |
|
---|
738 | //
|
---|
739 | // Check if at device. If not get new PCI location & PIRQ
|
---|
740 | //
|
---|
741 | if (Bridges[SBridgeIndex].SecondaryBus == (UINT8) LocalBus) {
|
---|
742 | //
|
---|
743 | // Translate PIRQ
|
---|
744 | //
|
---|
745 | LocalPirqIndex = (UINT8) ((LocalPirqIndex + (UINT8) (LocalDevice)) % 4);
|
---|
746 | break;
|
---|
747 | }
|
---|
748 | }
|
---|
749 | }
|
---|
750 |
|
---|
751 | //
|
---|
752 | // In case we fail to find the Bridge just above us, this is some potential error and we want to warn the user
|
---|
753 | //
|
---|
754 | if(BridgeIndex >= NumberOfBridges){
|
---|
755 | DEBUG ((EFI_D_ERROR, "Cannot Find IRQ Routing for Bus %d, Device %d, Function %d\n", *PciBus, *PciDevice, *PciFunction));
|
---|
756 | }
|
---|
757 |
|
---|
758 | *PirqIndex = LocalPirqIndex;
|
---|
759 | *PciBus = BaseBus;
|
---|
760 | *PciDevice = BaseDevice;
|
---|
761 | *PciFunction = BaseFunction;
|
---|
762 |
|
---|
763 | return EFI_SUCCESS;
|
---|
764 | }
|
---|
765 |
|
---|
766 |
|
---|
767 | /**
|
---|
768 | Copy the $PIR table as required.
|
---|
769 |
|
---|
770 | @param Private Legacy BIOS Instance data
|
---|
771 | @param RoutingTable Pointer to IRQ routing table
|
---|
772 | @param RoutingTableEntries IRQ routing table entries
|
---|
773 | @param PirqTable Pointer to $PIR table
|
---|
774 | @param PirqTableSize Length of table
|
---|
775 |
|
---|
776 | **/
|
---|
777 | VOID
|
---|
778 | CopyPirqTable (
|
---|
779 | IN LEGACY_BIOS_INSTANCE *Private,
|
---|
780 | IN EFI_LEGACY_IRQ_ROUTING_ENTRY *RoutingTable,
|
---|
781 | IN UINTN RoutingTableEntries,
|
---|
782 | IN EFI_LEGACY_PIRQ_TABLE_HEADER *PirqTable,
|
---|
783 | IN UINTN PirqTableSize
|
---|
784 | )
|
---|
785 | {
|
---|
786 | EFI_IA32_REGISTER_SET Regs;
|
---|
787 | UINT32 Granularity;
|
---|
788 |
|
---|
789 | //
|
---|
790 | // Copy $PIR table, if it exists.
|
---|
791 | //
|
---|
792 | if (PirqTable != NULL) {
|
---|
793 | Private->LegacyRegion->UnLock (
|
---|
794 | Private->LegacyRegion,
|
---|
795 | 0xE0000,
|
---|
796 | 0x20000,
|
---|
797 | &Granularity
|
---|
798 | );
|
---|
799 |
|
---|
800 | Private->InternalIrqRoutingTable = RoutingTable;
|
---|
801 | Private->NumberIrqRoutingEntries = (UINT16) (RoutingTableEntries);
|
---|
802 | ZeroMem (&Regs, sizeof (EFI_IA32_REGISTER_SET));
|
---|
803 |
|
---|
804 | Regs.X.AX = Legacy16GetTableAddress;
|
---|
805 | Regs.X.CX = (UINT16) PirqTableSize;
|
---|
806 | //
|
---|
807 | // Allocate at F segment according to PCI IRQ Routing Table Specification
|
---|
808 | //
|
---|
809 | Regs.X.BX = (UINT16) 0x1;
|
---|
810 | //
|
---|
811 | // 16-byte boundary alignment requirement according to
|
---|
812 | // PCI IRQ Routing Table Specification
|
---|
813 | //
|
---|
814 | Regs.X.DX = 0x10;
|
---|
815 | Private->LegacyBios.FarCall86 (
|
---|
816 | &Private->LegacyBios,
|
---|
817 | Private->Legacy16CallSegment,
|
---|
818 | Private->Legacy16CallOffset,
|
---|
819 | &Regs,
|
---|
820 | NULL,
|
---|
821 | 0
|
---|
822 | );
|
---|
823 |
|
---|
824 | Private->Legacy16Table->IrqRoutingTablePointer = (UINT32) (Regs.X.DS * 16 + Regs.X.BX);
|
---|
825 | if (Regs.X.AX != 0) {
|
---|
826 | DEBUG ((EFI_D_ERROR, "PIRQ table length insufficient - %x\n", PirqTableSize));
|
---|
827 | } else {
|
---|
828 | DEBUG ((EFI_D_INFO, "PIRQ table in legacy region - %x\n", Private->Legacy16Table->IrqRoutingTablePointer));
|
---|
829 | Private->Legacy16Table->IrqRoutingTableLength = (UINT32)PirqTableSize;
|
---|
830 | CopyMem (
|
---|
831 | (VOID *) (UINTN)Private->Legacy16Table->IrqRoutingTablePointer,
|
---|
832 | PirqTable,
|
---|
833 | PirqTableSize
|
---|
834 | );
|
---|
835 | }
|
---|
836 |
|
---|
837 | Private->Cpu->FlushDataCache (Private->Cpu, 0xE0000, 0x20000, EfiCpuFlushTypeWriteBackInvalidate);
|
---|
838 | Private->LegacyRegion->Lock (
|
---|
839 | Private->LegacyRegion,
|
---|
840 | 0xE0000,
|
---|
841 | 0x20000,
|
---|
842 | &Granularity
|
---|
843 | );
|
---|
844 | }
|
---|
845 |
|
---|
846 | Private->PciInterruptLine = TRUE;
|
---|
847 | mHandleCount = 0;
|
---|
848 | }
|
---|
849 |
|
---|
850 | /**
|
---|
851 | Dump EFI_LEGACY_INSTALL_PCI_HANDLER structure information.
|
---|
852 |
|
---|
853 | @param PciHandle The pointer to EFI_LEGACY_INSTALL_PCI_HANDLER structure
|
---|
854 |
|
---|
855 | **/
|
---|
856 | VOID
|
---|
857 | DumpPciHandle (
|
---|
858 | IN EFI_LEGACY_INSTALL_PCI_HANDLER *PciHandle
|
---|
859 | )
|
---|
860 | {
|
---|
861 | DEBUG ((EFI_D_INFO, "PciBus - %02x\n", (UINTN)PciHandle->PciBus));
|
---|
862 | DEBUG ((EFI_D_INFO, "PciDeviceFun - %02x\n", (UINTN)PciHandle->PciDeviceFun));
|
---|
863 | DEBUG ((EFI_D_INFO, "PciSegment - %02x\n", (UINTN)PciHandle->PciSegment));
|
---|
864 | DEBUG ((EFI_D_INFO, "PciClass - %02x\n", (UINTN)PciHandle->PciClass));
|
---|
865 | DEBUG ((EFI_D_INFO, "PciSubclass - %02x\n", (UINTN)PciHandle->PciSubclass));
|
---|
866 | DEBUG ((EFI_D_INFO, "PciInterface - %02x\n", (UINTN)PciHandle->PciInterface));
|
---|
867 |
|
---|
868 | DEBUG ((EFI_D_INFO, "PrimaryIrq - %02x\n", (UINTN)PciHandle->PrimaryIrq));
|
---|
869 | DEBUG ((EFI_D_INFO, "PrimaryReserved - %02x\n", (UINTN)PciHandle->PrimaryReserved));
|
---|
870 | DEBUG ((EFI_D_INFO, "PrimaryControl - %04x\n", (UINTN)PciHandle->PrimaryControl));
|
---|
871 | DEBUG ((EFI_D_INFO, "PrimaryBase - %04x\n", (UINTN)PciHandle->PrimaryBase));
|
---|
872 | DEBUG ((EFI_D_INFO, "PrimaryBusMaster - %04x\n", (UINTN)PciHandle->PrimaryBusMaster));
|
---|
873 |
|
---|
874 | DEBUG ((EFI_D_INFO, "SecondaryIrq - %02x\n", (UINTN)PciHandle->SecondaryIrq));
|
---|
875 | DEBUG ((EFI_D_INFO, "SecondaryReserved - %02x\n", (UINTN)PciHandle->SecondaryReserved));
|
---|
876 | DEBUG ((EFI_D_INFO, "SecondaryControl - %04x\n", (UINTN)PciHandle->SecondaryControl));
|
---|
877 | DEBUG ((EFI_D_INFO, "SecondaryBase - %04x\n", (UINTN)PciHandle->SecondaryBase));
|
---|
878 | DEBUG ((EFI_D_INFO, "SecondaryBusMaster - %04x\n", (UINTN)PciHandle->SecondaryBusMaster));
|
---|
879 | return;
|
---|
880 | }
|
---|
881 |
|
---|
882 | /**
|
---|
883 | Copy the $PIR table as required.
|
---|
884 |
|
---|
885 | @param Private Legacy BIOS Instance data
|
---|
886 | @param PciIo Pointer to PCI_IO protocol
|
---|
887 | @param PciIrq Pci IRQ number
|
---|
888 | @param PciConfigHeader Type00 Pci configuration header
|
---|
889 |
|
---|
890 | **/
|
---|
891 | VOID
|
---|
892 | InstallLegacyIrqHandler (
|
---|
893 | IN LEGACY_BIOS_INSTANCE *Private,
|
---|
894 | IN EFI_PCI_IO_PROTOCOL *PciIo,
|
---|
895 | IN UINT8 PciIrq,
|
---|
896 | IN PCI_TYPE00 *PciConfigHeader
|
---|
897 | )
|
---|
898 | {
|
---|
899 | EFI_IA32_REGISTER_SET Regs;
|
---|
900 | UINT16 LegMask;
|
---|
901 | UINTN PciSegment;
|
---|
902 | UINTN PciBus;
|
---|
903 | UINTN PciDevice;
|
---|
904 | UINTN PciFunction;
|
---|
905 | EFI_LEGACY_8259_PROTOCOL *Legacy8259;
|
---|
906 | UINT16 PrimaryMaster;
|
---|
907 | UINT16 SecondaryMaster;
|
---|
908 | UINTN TempData;
|
---|
909 | UINTN RegisterAddress;
|
---|
910 | UINT32 Granularity;
|
---|
911 |
|
---|
912 | PrimaryMaster = 0;
|
---|
913 | SecondaryMaster = 0;
|
---|
914 | Legacy8259 = Private->Legacy8259;
|
---|
915 | //
|
---|
916 | // Disable interrupt in PIC, in case shared, to prevent an
|
---|
917 | // interrupt from occuring.
|
---|
918 | //
|
---|
919 | Legacy8259->GetMask (
|
---|
920 | Legacy8259,
|
---|
921 | &LegMask,
|
---|
922 | NULL,
|
---|
923 | NULL,
|
---|
924 | NULL
|
---|
925 | );
|
---|
926 |
|
---|
927 | LegMask = (UINT16) (LegMask | (UINT16) (1 << PciIrq));
|
---|
928 |
|
---|
929 | Legacy8259->SetMask (
|
---|
930 | Legacy8259,
|
---|
931 | &LegMask,
|
---|
932 | NULL,
|
---|
933 | NULL,
|
---|
934 | NULL
|
---|
935 | );
|
---|
936 |
|
---|
937 | PciIo->GetLocation (
|
---|
938 | PciIo,
|
---|
939 | &PciSegment,
|
---|
940 | &PciBus,
|
---|
941 | &PciDevice,
|
---|
942 | &PciFunction
|
---|
943 | );
|
---|
944 | Private->IntThunk->PciHandler.PciBus = (UINT8) PciBus;
|
---|
945 | Private->IntThunk->PciHandler.PciDeviceFun = (UINT8) ((PciDevice << 3) + PciFunction);
|
---|
946 | Private->IntThunk->PciHandler.PciSegment = (UINT8) PciSegment;
|
---|
947 | Private->IntThunk->PciHandler.PciClass = PciConfigHeader->Hdr.ClassCode[2];
|
---|
948 | Private->IntThunk->PciHandler.PciSubclass = PciConfigHeader->Hdr.ClassCode[1];
|
---|
949 | Private->IntThunk->PciHandler.PciInterface = PciConfigHeader->Hdr.ClassCode[0];
|
---|
950 |
|
---|
951 | //
|
---|
952 | // Use native mode base address registers in two cases:
|
---|
953 | // 1. Programming Interface (PI) register indicates Primary Controller is
|
---|
954 | // in native mode OR
|
---|
955 | // 2. PCI device Sub Class Code is not IDE
|
---|
956 | //
|
---|
957 | Private->IntThunk->PciHandler.PrimaryBusMaster = (UINT16)(PciConfigHeader->Device.Bar[4] & 0xfffc);
|
---|
958 | if (((PciConfigHeader->Hdr.ClassCode[0] & 0x01) != 0) || (PciConfigHeader->Hdr.ClassCode[1] != PCI_CLASS_MASS_STORAGE_IDE)) {
|
---|
959 | Private->IntThunk->PciHandler.PrimaryIrq = PciIrq;
|
---|
960 | Private->IntThunk->PciHandler.PrimaryBase = (UINT16) (PciConfigHeader->Device.Bar[0] & 0xfffc);
|
---|
961 | Private->IntThunk->PciHandler.PrimaryControl = (UINT16) ((PciConfigHeader->Device.Bar[1] & 0xfffc) + 2);
|
---|
962 | } else {
|
---|
963 | Private->IntThunk->PciHandler.PrimaryIrq = 14;
|
---|
964 | Private->IntThunk->PciHandler.PrimaryBase = 0x1f0;
|
---|
965 | Private->IntThunk->PciHandler.PrimaryControl = 0x3f6;
|
---|
966 | }
|
---|
967 | //
|
---|
968 | // Secondary controller data
|
---|
969 | //
|
---|
970 | if (Private->IntThunk->PciHandler.PrimaryBusMaster != 0) {
|
---|
971 | Private->IntThunk->PciHandler.SecondaryBusMaster = (UINT16) ((PciConfigHeader->Device.Bar[4] & 0xfffc) + 8);
|
---|
972 | PrimaryMaster = (UINT16) (Private->IntThunk->PciHandler.PrimaryBusMaster + 2);
|
---|
973 | SecondaryMaster = (UINT16) (Private->IntThunk->PciHandler.SecondaryBusMaster + 2);
|
---|
974 |
|
---|
975 | //
|
---|
976 | // Clear pending interrupts in Bus Master registers
|
---|
977 | //
|
---|
978 | IoWrite16 (PrimaryMaster, 0x04);
|
---|
979 | IoWrite16 (SecondaryMaster, 0x04);
|
---|
980 |
|
---|
981 | }
|
---|
982 |
|
---|
983 | //
|
---|
984 | // Use native mode base address registers in two cases:
|
---|
985 | // 1. Programming Interface (PI) register indicates Secondary Controller is
|
---|
986 | // in native mode OR
|
---|
987 | // 2. PCI device Sub Class Code is not IDE
|
---|
988 | //
|
---|
989 | if (((PciConfigHeader->Hdr.ClassCode[0] & 0x04) != 0) || (PciConfigHeader->Hdr.ClassCode[1] != PCI_CLASS_MASS_STORAGE_IDE)) {
|
---|
990 | Private->IntThunk->PciHandler.SecondaryIrq = PciIrq;
|
---|
991 | Private->IntThunk->PciHandler.SecondaryBase = (UINT16) (PciConfigHeader->Device.Bar[2] & 0xfffc);
|
---|
992 | Private->IntThunk->PciHandler.SecondaryControl = (UINT16) ((PciConfigHeader->Device.Bar[3] & 0xfffc) + 2);
|
---|
993 | } else {
|
---|
994 |
|
---|
995 | Private->IntThunk->PciHandler.SecondaryIrq = 15;
|
---|
996 | Private->IntThunk->PciHandler.SecondaryBase = 0x170;
|
---|
997 | Private->IntThunk->PciHandler.SecondaryControl = 0x376;
|
---|
998 | }
|
---|
999 |
|
---|
1000 | //
|
---|
1001 | // Clear pending interrupts in IDE Command Block Status reg before we
|
---|
1002 | // Thunk to CSM16 below. Don't want a pending Interrupt before we
|
---|
1003 | // install the handlers as wierd corruption would occur and hang system.
|
---|
1004 | //
|
---|
1005 | //
|
---|
1006 | // Read IDE CMD blk status reg to clear out any pending interrupts.
|
---|
1007 | // Do here for Primary and Secondary IDE channels
|
---|
1008 | //
|
---|
1009 | RegisterAddress = (UINT16)Private->IntThunk->PciHandler.PrimaryBase + 0x07;
|
---|
1010 | IoRead8 (RegisterAddress);
|
---|
1011 | RegisterAddress = (UINT16)Private->IntThunk->PciHandler.SecondaryBase + 0x07;
|
---|
1012 | IoRead8 (RegisterAddress);
|
---|
1013 |
|
---|
1014 | Private->IntThunk->PciHandler.PrimaryReserved = 0;
|
---|
1015 | Private->IntThunk->PciHandler.SecondaryReserved = 0;
|
---|
1016 | Private->LegacyRegion->UnLock (
|
---|
1017 | Private->LegacyRegion,
|
---|
1018 | 0xE0000,
|
---|
1019 | 0x20000,
|
---|
1020 | &Granularity
|
---|
1021 | );
|
---|
1022 |
|
---|
1023 | Regs.X.AX = Legacy16InstallPciHandler;
|
---|
1024 | TempData = (UINTN) &Private->IntThunk->PciHandler;
|
---|
1025 | Regs.X.ES = EFI_SEGMENT ((UINT32) TempData);
|
---|
1026 | Regs.X.BX = EFI_OFFSET ((UINT32) TempData);
|
---|
1027 |
|
---|
1028 | DumpPciHandle (&Private->IntThunk->PciHandler);
|
---|
1029 |
|
---|
1030 | Private->LegacyBios.FarCall86 (
|
---|
1031 | &Private->LegacyBios,
|
---|
1032 | Private->Legacy16CallSegment,
|
---|
1033 | Private->Legacy16CallOffset,
|
---|
1034 | &Regs,
|
---|
1035 | NULL,
|
---|
1036 | 0
|
---|
1037 | );
|
---|
1038 |
|
---|
1039 | Private->Cpu->FlushDataCache (Private->Cpu, 0xE0000, 0x20000, EfiCpuFlushTypeWriteBackInvalidate);
|
---|
1040 | Private->LegacyRegion->Lock (
|
---|
1041 | Private->LegacyRegion,
|
---|
1042 | 0xE0000,
|
---|
1043 | 0x20000,
|
---|
1044 | &Granularity
|
---|
1045 | );
|
---|
1046 |
|
---|
1047 | }
|
---|
1048 |
|
---|
1049 |
|
---|
1050 | /**
|
---|
1051 | Program the interrupt routing register in all the PCI devices. On a PC AT system
|
---|
1052 | this register contains the 8259 IRQ vector that matches it's PCI interrupt.
|
---|
1053 |
|
---|
1054 | @param Private Legacy BIOS Instance data
|
---|
1055 |
|
---|
1056 | @retval EFI_SUCCESS Succeed.
|
---|
1057 | @retval EFI_ALREADY_STARTED All PCI devices have been processed.
|
---|
1058 |
|
---|
1059 | **/
|
---|
1060 | EFI_STATUS
|
---|
1061 | PciProgramAllInterruptLineRegisters (
|
---|
1062 | IN LEGACY_BIOS_INSTANCE *Private
|
---|
1063 | )
|
---|
1064 | {
|
---|
1065 | EFI_STATUS Status;
|
---|
1066 | EFI_PCI_IO_PROTOCOL *PciIo;
|
---|
1067 | EFI_LEGACY_8259_PROTOCOL *Legacy8259;
|
---|
1068 | EFI_LEGACY_INTERRUPT_PROTOCOL *LegacyInterrupt;
|
---|
1069 | EFI_LEGACY_BIOS_PLATFORM_PROTOCOL *LegacyBiosPlatform;
|
---|
1070 | UINT8 InterruptPin;
|
---|
1071 | UINTN Index;
|
---|
1072 | UINTN HandleCount;
|
---|
1073 | EFI_HANDLE *HandleBuffer;
|
---|
1074 | UINTN MassStorageHandleCount;
|
---|
1075 | EFI_HANDLE *MassStorageHandleBuffer;
|
---|
1076 | UINTN MassStorageHandleIndex;
|
---|
1077 | UINT8 PciIrq;
|
---|
1078 | UINT16 Command;
|
---|
1079 | UINTN PciSegment;
|
---|
1080 | UINTN PciBus;
|
---|
1081 | UINTN PciDevice;
|
---|
1082 | UINTN PciFunction;
|
---|
1083 | EFI_LEGACY_IRQ_ROUTING_ENTRY *RoutingTable;
|
---|
1084 | UINTN RoutingTableEntries;
|
---|
1085 | UINT16 LegMask;
|
---|
1086 | UINT16 LegEdgeLevel;
|
---|
1087 | PCI_TYPE00 PciConfigHeader;
|
---|
1088 | EFI_LEGACY_PIRQ_TABLE_HEADER *PirqTable;
|
---|
1089 | UINTN PirqTableSize;
|
---|
1090 | UINTN Flags;
|
---|
1091 | HDD_INFO *HddInfo;
|
---|
1092 | UINT64 Supports;
|
---|
1093 |
|
---|
1094 | //
|
---|
1095 | // Note - This routine use to return immediately if Private->PciInterruptLine
|
---|
1096 | // was true. Routine changed since resets etc can cause not all
|
---|
1097 | // PciIo protocols to be registered the first time through.
|
---|
1098 | // New algorithm is to do the copy $PIR table on first pass and save
|
---|
1099 | // HandleCount on first pass. If subsequent passes LocateHandleBuffer gives
|
---|
1100 | // a larger handle count then proceed with body of function else return
|
---|
1101 | // EFI_ALREADY_STARTED. In addition check if PCI device InterruptLine != 0.
|
---|
1102 | // If zero then function unprogrammed else skip function.
|
---|
1103 | //
|
---|
1104 | Legacy8259 = Private->Legacy8259;
|
---|
1105 | LegacyInterrupt = Private->LegacyInterrupt;
|
---|
1106 | LegacyBiosPlatform = Private->LegacyBiosPlatform;
|
---|
1107 |
|
---|
1108 | LegacyBiosPlatform->GetRoutingTable (
|
---|
1109 | Private->LegacyBiosPlatform,
|
---|
1110 | (VOID *) &RoutingTable,
|
---|
1111 | &RoutingTableEntries,
|
---|
1112 | (VOID *) &PirqTable,
|
---|
1113 | &PirqTableSize,
|
---|
1114 | NULL,
|
---|
1115 | NULL
|
---|
1116 | );
|
---|
1117 | CreateBridgeTable (RoutingTable, RoutingTableEntries);
|
---|
1118 |
|
---|
1119 | if (!Private->PciInterruptLine) {
|
---|
1120 | CopyPirqTable (
|
---|
1121 | Private,
|
---|
1122 | RoutingTable,
|
---|
1123 | RoutingTableEntries,
|
---|
1124 | PirqTable,
|
---|
1125 | PirqTableSize
|
---|
1126 | );
|
---|
1127 | }
|
---|
1128 |
|
---|
1129 | Status = gBS->LocateHandleBuffer (
|
---|
1130 | ByProtocol,
|
---|
1131 | &gEfiPciIoProtocolGuid,
|
---|
1132 | NULL,
|
---|
1133 | &HandleCount,
|
---|
1134 | &HandleBuffer
|
---|
1135 | );
|
---|
1136 | if (EFI_ERROR (Status)) {
|
---|
1137 | return EFI_NOT_FOUND;
|
---|
1138 | }
|
---|
1139 | if (HandleCount == mHandleCount) {
|
---|
1140 | FreePool (HandleBuffer);
|
---|
1141 | return EFI_ALREADY_STARTED;
|
---|
1142 | }
|
---|
1143 |
|
---|
1144 | if (mHandleCount == 0x00) {
|
---|
1145 | mHandleCount = HandleCount;
|
---|
1146 | }
|
---|
1147 |
|
---|
1148 | for (Index = 0; Index < HandleCount; Index++) {
|
---|
1149 | //
|
---|
1150 | // If VGA then only do VGA to allow drives fore time to spin up
|
---|
1151 | // otherwise assign PCI IRQs to all potential devices.
|
---|
1152 | //
|
---|
1153 | if ((mVgaInstallationInProgress) && (HandleBuffer[Index] != mVgaHandle)) {
|
---|
1154 | continue;
|
---|
1155 | } else {
|
---|
1156 | //
|
---|
1157 | // Force code to go through all handles next time called if video.
|
---|
1158 | // This will catch case where HandleCount doesn't change but want
|
---|
1159 | // to get drive info etc.
|
---|
1160 | //
|
---|
1161 | mHandleCount = 0x00;
|
---|
1162 | }
|
---|
1163 |
|
---|
1164 | Status = gBS->HandleProtocol (
|
---|
1165 | HandleBuffer[Index],
|
---|
1166 | &gEfiPciIoProtocolGuid,
|
---|
1167 | (VOID **) &PciIo
|
---|
1168 | );
|
---|
1169 | ASSERT_EFI_ERROR (Status);
|
---|
1170 |
|
---|
1171 | //
|
---|
1172 | // Test whether the device can be enabled or not.
|
---|
1173 | // If it can't be enabled, then just skip it to avoid further operation.
|
---|
1174 | //
|
---|
1175 | PciIo->Pci.Read (
|
---|
1176 | PciIo,
|
---|
1177 | EfiPciIoWidthUint32,
|
---|
1178 | 0,
|
---|
1179 | sizeof (PciConfigHeader) / sizeof (UINT32),
|
---|
1180 | &PciConfigHeader
|
---|
1181 | );
|
---|
1182 | Command = PciConfigHeader.Hdr.Command;
|
---|
1183 |
|
---|
1184 | //
|
---|
1185 | // Note PciIo->Attributes does not program the PCI command register
|
---|
1186 | //
|
---|
1187 | Status = PciIo->Attributes (
|
---|
1188 | PciIo,
|
---|
1189 | EfiPciIoAttributeOperationSupported,
|
---|
1190 | 0,
|
---|
1191 | &Supports
|
---|
1192 | );
|
---|
1193 | if (!EFI_ERROR (Status)) {
|
---|
1194 | Supports &= (UINT64)EFI_PCI_DEVICE_ENABLE;
|
---|
1195 | Status = PciIo->Attributes (
|
---|
1196 | PciIo,
|
---|
1197 | EfiPciIoAttributeOperationEnable,
|
---|
1198 | Supports,
|
---|
1199 | NULL
|
---|
1200 | );
|
---|
1201 | }
|
---|
1202 | PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x04, 1, &Command);
|
---|
1203 |
|
---|
1204 | if (EFI_ERROR (Status)) {
|
---|
1205 | continue;
|
---|
1206 | }
|
---|
1207 |
|
---|
1208 | InterruptPin = PciConfigHeader.Device.InterruptPin;
|
---|
1209 |
|
---|
1210 | if ((InterruptPin != 0) && (PciConfigHeader.Device.InterruptLine == PCI_INT_LINE_UNKNOWN)) {
|
---|
1211 | PciIo->GetLocation (
|
---|
1212 | PciIo,
|
---|
1213 | &PciSegment,
|
---|
1214 | &PciBus,
|
---|
1215 | &PciDevice,
|
---|
1216 | &PciFunction
|
---|
1217 | );
|
---|
1218 | //
|
---|
1219 | // Translate PIRQ index back thru busses to slot bus with InterruptPin
|
---|
1220 | // zero based
|
---|
1221 | //
|
---|
1222 | InterruptPin -= 1;
|
---|
1223 |
|
---|
1224 | Status = GetBaseBus (
|
---|
1225 | Private,
|
---|
1226 | PciBus,
|
---|
1227 | PciDevice,
|
---|
1228 | RoutingTable,
|
---|
1229 | RoutingTableEntries
|
---|
1230 | );
|
---|
1231 |
|
---|
1232 | if (Status == EFI_NOT_FOUND) {
|
---|
1233 | TranslateBusPirq (
|
---|
1234 | Private,
|
---|
1235 | &PciBus,
|
---|
1236 | &PciDevice,
|
---|
1237 | &PciFunction,
|
---|
1238 | &InterruptPin
|
---|
1239 | );
|
---|
1240 | }
|
---|
1241 | //
|
---|
1242 | // Translate InterruptPin(0-3) into PIRQ
|
---|
1243 | //
|
---|
1244 | Status = LegacyBiosPlatform->TranslatePirq (
|
---|
1245 | LegacyBiosPlatform,
|
---|
1246 | PciBus,
|
---|
1247 | (PciDevice << 3),
|
---|
1248 | PciFunction,
|
---|
1249 | &InterruptPin,
|
---|
1250 | &PciIrq
|
---|
1251 | );
|
---|
1252 | //
|
---|
1253 | // TranslatePirq() should never fail or we are in trouble
|
---|
1254 | // If it does return failure status, check your PIRQ routing table to see if some item is missing or incorrect
|
---|
1255 | //
|
---|
1256 | if (EFI_ERROR (Status)) {
|
---|
1257 | DEBUG ((EFI_D_ERROR, "Translate Pirq Failed - Status = %r\n ", Status));
|
---|
1258 | continue;
|
---|
1259 | }
|
---|
1260 |
|
---|
1261 | LegacyInterrupt->WritePirq (
|
---|
1262 | LegacyInterrupt,
|
---|
1263 | InterruptPin,
|
---|
1264 | PciIrq
|
---|
1265 | );
|
---|
1266 |
|
---|
1267 | //
|
---|
1268 | // Check if device has an OPROM associated with it.
|
---|
1269 | // If not invoke special 16-bit function, to allow 16-bit
|
---|
1270 | // code to install an interrupt handler.
|
---|
1271 | //
|
---|
1272 | Status = LegacyBiosCheckPciRom (
|
---|
1273 | &Private->LegacyBios,
|
---|
1274 | HandleBuffer[Index],
|
---|
1275 | NULL,
|
---|
1276 | NULL,
|
---|
1277 | &Flags
|
---|
1278 | );
|
---|
1279 | if ((EFI_ERROR (Status)) && (PciConfigHeader.Hdr.ClassCode[2] == PCI_CLASS_MASS_STORAGE)) {
|
---|
1280 | //
|
---|
1281 | // Device has no OPROM associated with it and is a mass storage
|
---|
1282 | // device. It needs to have an PCI IRQ handler installed. To
|
---|
1283 | // correctly install the handler we need to insure device is
|
---|
1284 | // connected. The device may just have register itself but not
|
---|
1285 | // been connected. Re-read PCI config space after as it can
|
---|
1286 | // change
|
---|
1287 | //
|
---|
1288 | //
|
---|
1289 | // Get IDE Handle. If matches handle then skip ConnectController
|
---|
1290 | // since ConnectController may force native mode and we don't
|
---|
1291 | // want that for primary IDE controller
|
---|
1292 | //
|
---|
1293 | MassStorageHandleCount = 0;
|
---|
1294 | MassStorageHandleBuffer = NULL;
|
---|
1295 | LegacyBiosPlatform->GetPlatformHandle (
|
---|
1296 | Private->LegacyBiosPlatform,
|
---|
1297 | EfiGetPlatformIdeHandle,
|
---|
1298 | 0,
|
---|
1299 | &MassStorageHandleBuffer,
|
---|
1300 | &MassStorageHandleCount,
|
---|
1301 | NULL
|
---|
1302 | );
|
---|
1303 |
|
---|
1304 | HddInfo = &Private->IntThunk->EfiToLegacy16BootTable.HddInfo[0];
|
---|
1305 |
|
---|
1306 | LegacyBiosBuildIdeData (Private, &HddInfo, 0);
|
---|
1307 | PciIo->Pci.Read (
|
---|
1308 | PciIo,
|
---|
1309 | EfiPciIoWidthUint32,
|
---|
1310 | 0,
|
---|
1311 | sizeof (PciConfigHeader) / sizeof (UINT32),
|
---|
1312 | &PciConfigHeader
|
---|
1313 | );
|
---|
1314 |
|
---|
1315 | for (MassStorageHandleIndex = 0; MassStorageHandleIndex < MassStorageHandleCount; MassStorageHandleIndex++) {
|
---|
1316 | if (MassStorageHandleBuffer[MassStorageHandleIndex] == HandleBuffer[Index]) {
|
---|
1317 | //
|
---|
1318 | // InstallLegacyIrqHandler according to Platform requirement
|
---|
1319 | //
|
---|
1320 | InstallLegacyIrqHandler (
|
---|
1321 | Private,
|
---|
1322 | PciIo,
|
---|
1323 | PciIrq,
|
---|
1324 | &PciConfigHeader
|
---|
1325 | );
|
---|
1326 | break;
|
---|
1327 | }
|
---|
1328 | }
|
---|
1329 | }
|
---|
1330 | //
|
---|
1331 | // Write InterruptPin and enable 8259.
|
---|
1332 | //
|
---|
1333 | PciIo->Pci.Write (
|
---|
1334 | PciIo,
|
---|
1335 | EfiPciIoWidthUint8,
|
---|
1336 | 0x3c,
|
---|
1337 | 1,
|
---|
1338 | &PciIrq
|
---|
1339 | );
|
---|
1340 | Private->IntThunk->EfiToLegacy16BootTable.PciIrqMask = (UINT16) (Private->IntThunk->EfiToLegacy16BootTable.PciIrqMask | (UINT16) (1 << PciIrq));
|
---|
1341 |
|
---|
1342 | Legacy8259->GetMask (
|
---|
1343 | Legacy8259,
|
---|
1344 | &LegMask,
|
---|
1345 | &LegEdgeLevel,
|
---|
1346 | NULL,
|
---|
1347 | NULL
|
---|
1348 | );
|
---|
1349 |
|
---|
1350 | LegMask = (UINT16) (LegMask & (UINT16)~(1 << PciIrq));
|
---|
1351 | LegEdgeLevel = (UINT16) (LegEdgeLevel | (UINT16) (1 << PciIrq));
|
---|
1352 | Legacy8259->SetMask (
|
---|
1353 | Legacy8259,
|
---|
1354 | &LegMask,
|
---|
1355 | &LegEdgeLevel,
|
---|
1356 | NULL,
|
---|
1357 | NULL
|
---|
1358 | );
|
---|
1359 | }
|
---|
1360 | }
|
---|
1361 | FreePool (HandleBuffer);
|
---|
1362 | return EFI_SUCCESS;
|
---|
1363 | }
|
---|
1364 |
|
---|
1365 |
|
---|
1366 | /**
|
---|
1367 | Find & verify PnP Expansion header in ROM image
|
---|
1368 |
|
---|
1369 | @param Private Protocol instance pointer.
|
---|
1370 | @param FirstHeader 1 = Find first header, 0 = Find successive headers
|
---|
1371 | @param PnpPtr Input Rom start if FirstHeader =1, Current Header
|
---|
1372 | otherwise Output Next header, if it exists
|
---|
1373 |
|
---|
1374 | @retval EFI_SUCCESS Next Header found at BasePnpPtr
|
---|
1375 | @retval EFI_NOT_FOUND No more headers
|
---|
1376 |
|
---|
1377 | **/
|
---|
1378 | EFI_STATUS
|
---|
1379 | FindNextPnpExpansionHeader (
|
---|
1380 | IN LEGACY_BIOS_INSTANCE *Private,
|
---|
1381 | IN BOOLEAN FirstHeader,
|
---|
1382 | IN OUT LEGACY_PNP_EXPANSION_HEADER **PnpPtr
|
---|
1383 |
|
---|
1384 | )
|
---|
1385 | {
|
---|
1386 | UINTN TempData;
|
---|
1387 | LEGACY_PNP_EXPANSION_HEADER *LocalPnpPtr;
|
---|
1388 | LocalPnpPtr = *PnpPtr;
|
---|
1389 | if (FirstHeader == FIRST_INSTANCE) {
|
---|
1390 | mBasePnpPtr = LocalPnpPtr;
|
---|
1391 | mBbsRomSegment = (UINT16) ((UINTN) mBasePnpPtr >> 4);
|
---|
1392 | //
|
---|
1393 | // Offset 0x1a gives offset to PnP expansion header for the first
|
---|
1394 | // instance, there after the structure gives the offset to the next
|
---|
1395 | // structure
|
---|
1396 | //
|
---|
1397 | LocalPnpPtr = (LEGACY_PNP_EXPANSION_HEADER *) ((UINT8 *) LocalPnpPtr + 0x1a);
|
---|
1398 | TempData = (*((UINT16 *) LocalPnpPtr));
|
---|
1399 | } else {
|
---|
1400 | TempData = (UINT16) LocalPnpPtr->NextHeader;
|
---|
1401 | }
|
---|
1402 |
|
---|
1403 | LocalPnpPtr = (LEGACY_PNP_EXPANSION_HEADER *) (((UINT8 *) mBasePnpPtr + TempData));
|
---|
1404 |
|
---|
1405 | //
|
---|
1406 | // Search for PnP table in Shadowed ROM
|
---|
1407 | //
|
---|
1408 | *PnpPtr = LocalPnpPtr;
|
---|
1409 | if (*(UINT32 *) LocalPnpPtr == SIGNATURE_32 ('$', 'P', 'n', 'P')) {
|
---|
1410 | return EFI_SUCCESS;
|
---|
1411 | } else {
|
---|
1412 | return EFI_NOT_FOUND;
|
---|
1413 | }
|
---|
1414 | }
|
---|
1415 |
|
---|
1416 |
|
---|
1417 | /**
|
---|
1418 | Update list of Bev or BCV table entries.
|
---|
1419 |
|
---|
1420 | @param Private Protocol instance pointer.
|
---|
1421 | @param RomStart Table of ROM start address in RAM/ROM. PciIo _
|
---|
1422 | Handle to PCI IO for this device
|
---|
1423 | @param PciIo Instance of PCI I/O Protocol
|
---|
1424 |
|
---|
1425 | @retval EFI_SUCCESS Always should succeed.
|
---|
1426 |
|
---|
1427 | **/
|
---|
1428 | EFI_STATUS
|
---|
1429 | UpdateBevBcvTable (
|
---|
1430 | IN LEGACY_BIOS_INSTANCE *Private,
|
---|
1431 | IN EFI_LEGACY_EXPANSION_ROM_HEADER *RomStart,
|
---|
1432 | IN EFI_PCI_IO_PROTOCOL *PciIo
|
---|
1433 | )
|
---|
1434 | {
|
---|
1435 | VOID *RomEnd;
|
---|
1436 | BBS_TABLE *BbsTable;
|
---|
1437 | UINTN BbsIndex;
|
---|
1438 | EFI_LEGACY_EXPANSION_ROM_HEADER *PciPtr;
|
---|
1439 | LEGACY_PNP_EXPANSION_HEADER *PnpPtr;
|
---|
1440 | BOOLEAN Instance;
|
---|
1441 | EFI_STATUS Status;
|
---|
1442 | UINTN Segment;
|
---|
1443 | UINTN Bus;
|
---|
1444 | UINTN Device;
|
---|
1445 | UINTN Function;
|
---|
1446 | UINT8 Class;
|
---|
1447 | UINT16 DeviceType;
|
---|
1448 | Segment = 0;
|
---|
1449 | Bus = 0;
|
---|
1450 | Device = 0;
|
---|
1451 | Function = 0;
|
---|
1452 | Class = 0;
|
---|
1453 | DeviceType = BBS_UNKNOWN;
|
---|
1454 |
|
---|
1455 | //
|
---|
1456 | // Skip floppy and 2*onboard IDE controller entries(Master/Slave per
|
---|
1457 | // controller).
|
---|
1458 | //
|
---|
1459 | BbsIndex = Private->IntThunk->EfiToLegacy16BootTable.NumberBbsEntries;
|
---|
1460 |
|
---|
1461 | BbsTable = (BBS_TABLE*)(UINTN) Private->IntThunk->EfiToLegacy16BootTable.BbsTable;
|
---|
1462 | PnpPtr = (LEGACY_PNP_EXPANSION_HEADER *) RomStart;
|
---|
1463 | PciPtr = (EFI_LEGACY_EXPANSION_ROM_HEADER *) RomStart;
|
---|
1464 |
|
---|
1465 | RomEnd = (VOID *) (PciPtr->Size512 * 512 + (UINTN) PciPtr);
|
---|
1466 | Instance = FIRST_INSTANCE;
|
---|
1467 | //
|
---|
1468 | // OPROMs like PXE may not be tied to a piece of hardware and thus
|
---|
1469 | // don't have a PciIo associated with them
|
---|
1470 | //
|
---|
1471 | if (PciIo != NULL) {
|
---|
1472 | PciIo->GetLocation (
|
---|
1473 | PciIo,
|
---|
1474 | &Segment,
|
---|
1475 | &Bus,
|
---|
1476 | &Device,
|
---|
1477 | &Function
|
---|
1478 | );
|
---|
1479 | PciIo->Pci.Read (
|
---|
1480 | PciIo,
|
---|
1481 | EfiPciIoWidthUint8,
|
---|
1482 | 0x0b,
|
---|
1483 | 1,
|
---|
1484 | &Class
|
---|
1485 | );
|
---|
1486 |
|
---|
1487 | if (Class == PCI_CLASS_MASS_STORAGE) {
|
---|
1488 | DeviceType = BBS_HARDDISK;
|
---|
1489 | } else {
|
---|
1490 | if (Class == PCI_CLASS_NETWORK) {
|
---|
1491 | DeviceType = BBS_EMBED_NETWORK;
|
---|
1492 | }
|
---|
1493 | }
|
---|
1494 | }
|
---|
1495 |
|
---|
1496 | while (TRUE) {
|
---|
1497 | Status = FindNextPnpExpansionHeader (Private, Instance, &PnpPtr);
|
---|
1498 | Instance = NOT_FIRST_INSTANCE;
|
---|
1499 | if (EFI_ERROR (Status)) {
|
---|
1500 | break;
|
---|
1501 | }
|
---|
1502 | //
|
---|
1503 | // There can be additional $PnP headers within the OPROM.
|
---|
1504 | // Example: SCSI can have one per drive.
|
---|
1505 | //
|
---|
1506 | BbsTable[BbsIndex].BootPriority = BBS_UNPRIORITIZED_ENTRY;
|
---|
1507 | BbsTable[BbsIndex].DeviceType = DeviceType;
|
---|
1508 | BbsTable[BbsIndex].Bus = (UINT32) Bus;
|
---|
1509 | BbsTable[BbsIndex].Device = (UINT32) Device;
|
---|
1510 | BbsTable[BbsIndex].Function = (UINT32) Function;
|
---|
1511 | BbsTable[BbsIndex].StatusFlags.OldPosition = 0;
|
---|
1512 | BbsTable[BbsIndex].StatusFlags.Reserved1 = 0;
|
---|
1513 | BbsTable[BbsIndex].StatusFlags.Enabled = 0;
|
---|
1514 | BbsTable[BbsIndex].StatusFlags.Failed = 0;
|
---|
1515 | BbsTable[BbsIndex].StatusFlags.MediaPresent = 0;
|
---|
1516 | BbsTable[BbsIndex].StatusFlags.Reserved2 = 0;
|
---|
1517 | BbsTable[BbsIndex].Class = PnpPtr->Class;
|
---|
1518 | BbsTable[BbsIndex].SubClass = PnpPtr->SubClass;
|
---|
1519 | BbsTable[BbsIndex].DescStringOffset = PnpPtr->ProductNamePointer;
|
---|
1520 | BbsTable[BbsIndex].DescStringSegment = mBbsRomSegment;
|
---|
1521 | BbsTable[BbsIndex].MfgStringOffset = PnpPtr->MfgPointer;
|
---|
1522 | BbsTable[BbsIndex].MfgStringSegment = mBbsRomSegment;
|
---|
1523 | BbsTable[BbsIndex].BootHandlerSegment = mBbsRomSegment;
|
---|
1524 |
|
---|
1525 | //
|
---|
1526 | // Have seen case where PXE base code have PnP expansion ROM
|
---|
1527 | // header but no Bcv or Bev vectors.
|
---|
1528 | //
|
---|
1529 | if (PnpPtr->Bcv != 0) {
|
---|
1530 | BbsTable[BbsIndex].BootHandlerOffset = PnpPtr->Bcv;
|
---|
1531 | ++BbsIndex;
|
---|
1532 | }
|
---|
1533 |
|
---|
1534 | if (PnpPtr->Bev != 0) {
|
---|
1535 | BbsTable[BbsIndex].BootHandlerOffset = PnpPtr->Bev;
|
---|
1536 | BbsTable[BbsIndex].DeviceType = BBS_BEV_DEVICE;
|
---|
1537 | ++BbsIndex;
|
---|
1538 | }
|
---|
1539 |
|
---|
1540 | if ((PnpPtr == (LEGACY_PNP_EXPANSION_HEADER *) PciPtr) || (PnpPtr > (LEGACY_PNP_EXPANSION_HEADER *) RomEnd)) {
|
---|
1541 | break;
|
---|
1542 | }
|
---|
1543 | }
|
---|
1544 |
|
---|
1545 | BbsTable[BbsIndex].BootPriority = BBS_IGNORE_ENTRY;
|
---|
1546 | Private->IntThunk->EfiToLegacy16BootTable.NumberBbsEntries = (UINT32) BbsIndex;
|
---|
1547 | return EFI_SUCCESS;
|
---|
1548 | }
|
---|
1549 |
|
---|
1550 |
|
---|
1551 | /**
|
---|
1552 | Shadow all the PCI legacy ROMs. Use data from the Legacy BIOS Protocol
|
---|
1553 | to chose the order. Skip any devices that have already have legacy
|
---|
1554 | BIOS run.
|
---|
1555 |
|
---|
1556 | @param Private Protocol instance pointer.
|
---|
1557 |
|
---|
1558 | @retval EFI_SUCCESS Succeed.
|
---|
1559 | @retval EFI_UNSUPPORTED Cannot get VGA device handle.
|
---|
1560 |
|
---|
1561 | **/
|
---|
1562 | EFI_STATUS
|
---|
1563 | PciShadowRoms (
|
---|
1564 | IN LEGACY_BIOS_INSTANCE *Private
|
---|
1565 | )
|
---|
1566 | {
|
---|
1567 | EFI_STATUS Status;
|
---|
1568 | EFI_PCI_IO_PROTOCOL *PciIo;
|
---|
1569 | PCI_TYPE00 Pci;
|
---|
1570 | UINTN Index;
|
---|
1571 | UINTN HandleCount;
|
---|
1572 | EFI_HANDLE *HandleBuffer;
|
---|
1573 | EFI_HANDLE VgaHandle;
|
---|
1574 | EFI_HANDLE FirstHandle;
|
---|
1575 | VOID **RomStart;
|
---|
1576 | UINTN Flags;
|
---|
1577 | PCI_TYPE00 PciConfigHeader;
|
---|
1578 | UINT16 *Command;
|
---|
1579 | UINT64 Supports;
|
---|
1580 |
|
---|
1581 | //
|
---|
1582 | // Make the VGA device first
|
---|
1583 | //
|
---|
1584 | Status = Private->LegacyBiosPlatform->GetPlatformHandle (
|
---|
1585 | Private->LegacyBiosPlatform,
|
---|
1586 | EfiGetPlatformVgaHandle,
|
---|
1587 | 0,
|
---|
1588 | &HandleBuffer,
|
---|
1589 | &HandleCount,
|
---|
1590 | NULL
|
---|
1591 | );
|
---|
1592 | if (EFI_ERROR (Status)) {
|
---|
1593 | return EFI_UNSUPPORTED;
|
---|
1594 | }
|
---|
1595 |
|
---|
1596 | VgaHandle = HandleBuffer[0];
|
---|
1597 |
|
---|
1598 | Status = gBS->LocateHandleBuffer (
|
---|
1599 | ByProtocol,
|
---|
1600 | &gEfiPciIoProtocolGuid,
|
---|
1601 | NULL,
|
---|
1602 | &HandleCount,
|
---|
1603 | &HandleBuffer
|
---|
1604 | );
|
---|
1605 |
|
---|
1606 | if (EFI_ERROR (Status)) {
|
---|
1607 | return Status;
|
---|
1608 | }
|
---|
1609 | //
|
---|
1610 | // Place the VGA handle as first.
|
---|
1611 | //
|
---|
1612 | for (Index = 0; Index < HandleCount; Index++) {
|
---|
1613 | if (HandleBuffer[Index] == VgaHandle) {
|
---|
1614 | FirstHandle = HandleBuffer[0];
|
---|
1615 | HandleBuffer[0] = HandleBuffer[Index];
|
---|
1616 | HandleBuffer[Index] = FirstHandle;
|
---|
1617 | break;
|
---|
1618 | }
|
---|
1619 | }
|
---|
1620 | //
|
---|
1621 | // Allocate memory to save Command WORD from each device. We do this
|
---|
1622 | // to restore devices to same state as EFI after switching to legacy.
|
---|
1623 | //
|
---|
1624 | Command = (UINT16 *) AllocatePool (
|
---|
1625 | sizeof (UINT16) * (HandleCount + 1)
|
---|
1626 | );
|
---|
1627 | if (NULL == Command) {
|
---|
1628 | FreePool (HandleBuffer);
|
---|
1629 | return EFI_OUT_OF_RESOURCES;
|
---|
1630 | }
|
---|
1631 | //
|
---|
1632 | // Disconnect all EFI devices first. This covers cases where alegacy BIOS
|
---|
1633 | // may control multiple PCI devices.
|
---|
1634 | //
|
---|
1635 | for (Index = 0; Index < HandleCount; Index++) {
|
---|
1636 |
|
---|
1637 | Status = gBS->HandleProtocol (
|
---|
1638 | HandleBuffer[Index],
|
---|
1639 | &gEfiPciIoProtocolGuid,
|
---|
1640 | (VOID **) &PciIo
|
---|
1641 | );
|
---|
1642 | ASSERT_EFI_ERROR (Status);
|
---|
1643 |
|
---|
1644 | //
|
---|
1645 | // Save command register for "connect" loop
|
---|
1646 | //
|
---|
1647 | PciIo->Pci.Read (
|
---|
1648 | PciIo,
|
---|
1649 | EfiPciIoWidthUint32,
|
---|
1650 | 0,
|
---|
1651 | sizeof (PciConfigHeader) / sizeof (UINT32),
|
---|
1652 | &PciConfigHeader
|
---|
1653 | );
|
---|
1654 | Command[Index] = PciConfigHeader.Hdr.Command;
|
---|
1655 | //
|
---|
1656 | // Skip any device that already has a legacy ROM run
|
---|
1657 | //
|
---|
1658 | Status = IsLegacyRom (HandleBuffer[Index]);
|
---|
1659 | if (!EFI_ERROR (Status)) {
|
---|
1660 | continue;
|
---|
1661 | }
|
---|
1662 | //
|
---|
1663 | // Stop EFI Drivers with oprom.
|
---|
1664 | //
|
---|
1665 | gBS->DisconnectController (
|
---|
1666 | HandleBuffer[Index],
|
---|
1667 | NULL,
|
---|
1668 | NULL
|
---|
1669 | );
|
---|
1670 | }
|
---|
1671 | //
|
---|
1672 | // For every device that has not had a legacy ROM started. Start a legacy ROM.
|
---|
1673 | //
|
---|
1674 | for (Index = 0; Index < HandleCount; Index++) {
|
---|
1675 |
|
---|
1676 | Status = gBS->HandleProtocol (
|
---|
1677 | HandleBuffer[Index],
|
---|
1678 | &gEfiPciIoProtocolGuid,
|
---|
1679 | (VOID **) &PciIo
|
---|
1680 | );
|
---|
1681 |
|
---|
1682 | ASSERT_EFI_ERROR (Status);
|
---|
1683 |
|
---|
1684 | //
|
---|
1685 | // Here make sure if one VGA have been shadowed,
|
---|
1686 | // then wil not shadowed another one.
|
---|
1687 | //
|
---|
1688 | PciIo->Pci.Read (
|
---|
1689 | PciIo,
|
---|
1690 | EfiPciIoWidthUint32,
|
---|
1691 | 0,
|
---|
1692 | sizeof (Pci) / sizeof (UINT32),
|
---|
1693 | &Pci
|
---|
1694 | );
|
---|
1695 |
|
---|
1696 | //
|
---|
1697 | // Only one Video OPROM can be given control in BIOS phase. If there are multiple Video devices,
|
---|
1698 | // one will work in legacy mode (OPROM will be given control) and
|
---|
1699 | // other Video devices will work in native mode (OS driver will handle these devices).
|
---|
1700 | //
|
---|
1701 | if (IS_PCI_DISPLAY (&Pci) && Index != 0) {
|
---|
1702 | continue;
|
---|
1703 | }
|
---|
1704 | //
|
---|
1705 | // Skip any device that already has a legacy ROM run
|
---|
1706 | //
|
---|
1707 | Status = IsLegacyRom (HandleBuffer[Index]);
|
---|
1708 | if (!EFI_ERROR (Status)) {
|
---|
1709 | continue;
|
---|
1710 | }
|
---|
1711 |
|
---|
1712 | //
|
---|
1713 | // If legacy VBIOS Oprom has not been dispatched before, install legacy VBIOS here.
|
---|
1714 | //
|
---|
1715 | if (IS_PCI_DISPLAY (&Pci) && Index == 0) {
|
---|
1716 | Status = LegacyBiosInstallVgaRom (Private);
|
---|
1717 | //
|
---|
1718 | // A return status of EFI_NOT_FOUND is considered valid (No EFI
|
---|
1719 | // driver is controlling video).
|
---|
1720 | //
|
---|
1721 | ASSERT ((Status == EFI_SUCCESS) || (Status == EFI_NOT_FOUND));
|
---|
1722 | continue;
|
---|
1723 | }
|
---|
1724 |
|
---|
1725 | //
|
---|
1726 | // Install legacy ROM
|
---|
1727 | //
|
---|
1728 | Status = LegacyBiosInstallPciRom (
|
---|
1729 | &Private->LegacyBios,
|
---|
1730 | HandleBuffer[Index],
|
---|
1731 | NULL,
|
---|
1732 | &Flags,
|
---|
1733 | NULL,
|
---|
1734 | NULL,
|
---|
1735 | (VOID **) &RomStart,
|
---|
1736 | NULL
|
---|
1737 | );
|
---|
1738 | if (EFI_ERROR (Status)) {
|
---|
1739 | if (!((Status == EFI_UNSUPPORTED) && (Flags == NO_ROM))) {
|
---|
1740 | continue;
|
---|
1741 | }
|
---|
1742 | }
|
---|
1743 | //
|
---|
1744 | // Restore Command register so legacy has same devices enabled or disabled
|
---|
1745 | // as EFI.
|
---|
1746 | // If Flags = NO_ROM use command register as is. This covers the
|
---|
1747 | // following cases:
|
---|
1748 | // Device has no ROMs associated with it.
|
---|
1749 | // Device has ROM associated with it but was already
|
---|
1750 | // installed.
|
---|
1751 | // = ROM_FOUND but not VALID_LEGACY_ROM, disable it.
|
---|
1752 | // = ROM_FOUND and VALID_LEGACY_ROM, enable it.
|
---|
1753 | //
|
---|
1754 | if ((Flags & ROM_FOUND) == ROM_FOUND) {
|
---|
1755 | if ((Flags & VALID_LEGACY_ROM) == 0) {
|
---|
1756 | Command[Index] = 0;
|
---|
1757 | } else {
|
---|
1758 | //
|
---|
1759 | // For several VGAs, only one of them can be enabled.
|
---|
1760 | //
|
---|
1761 | Status = PciIo->Attributes (
|
---|
1762 | PciIo,
|
---|
1763 | EfiPciIoAttributeOperationSupported,
|
---|
1764 | 0,
|
---|
1765 | &Supports
|
---|
1766 | );
|
---|
1767 | if (!EFI_ERROR (Status)) {
|
---|
1768 | Supports &= (UINT64)EFI_PCI_DEVICE_ENABLE;
|
---|
1769 | Status = PciIo->Attributes (
|
---|
1770 | PciIo,
|
---|
1771 | EfiPciIoAttributeOperationEnable,
|
---|
1772 | Supports,
|
---|
1773 | NULL
|
---|
1774 | );
|
---|
1775 | }
|
---|
1776 | if (!EFI_ERROR (Status)) {
|
---|
1777 | Command[Index] = 0x1f;
|
---|
1778 | }
|
---|
1779 | }
|
---|
1780 | }
|
---|
1781 |
|
---|
1782 | PciIo->Pci.Write (
|
---|
1783 | PciIo,
|
---|
1784 | EfiPciIoWidthUint16,
|
---|
1785 | 0x04,
|
---|
1786 | 1,
|
---|
1787 | &Command[Index]
|
---|
1788 | );
|
---|
1789 | }
|
---|
1790 |
|
---|
1791 | FreePool (Command);
|
---|
1792 | FreePool (HandleBuffer);
|
---|
1793 | return EFI_SUCCESS;
|
---|
1794 | }
|
---|
1795 |
|
---|
1796 |
|
---|
1797 | /**
|
---|
1798 | Test to see if a legacy PCI ROM exists for this device. Optionally return
|
---|
1799 | the Legacy ROM instance for this PCI device.
|
---|
1800 |
|
---|
1801 | @param This Protocol instance pointer.
|
---|
1802 | @param PciHandle The PCI PC-AT OPROM from this devices ROM BAR will
|
---|
1803 | be loaded
|
---|
1804 | @param RomImage Return the legacy PCI ROM for this device
|
---|
1805 | @param RomSize Size of ROM Image
|
---|
1806 | @param Flags Indicates if ROM found and if PC-AT.
|
---|
1807 |
|
---|
1808 | @retval EFI_SUCCESS Legacy Option ROM available for this device
|
---|
1809 | @retval EFI_UNSUPPORTED Legacy Option ROM not supported.
|
---|
1810 |
|
---|
1811 | **/
|
---|
1812 | EFI_STATUS
|
---|
1813 | EFIAPI
|
---|
1814 | LegacyBiosCheckPciRom (
|
---|
1815 | IN EFI_LEGACY_BIOS_PROTOCOL *This,
|
---|
1816 | IN EFI_HANDLE PciHandle,
|
---|
1817 | OUT VOID **RomImage, OPTIONAL
|
---|
1818 | OUT UINTN *RomSize, OPTIONAL
|
---|
1819 | OUT UINTN *Flags
|
---|
1820 | )
|
---|
1821 | {
|
---|
1822 | return LegacyBiosCheckPciRomEx (
|
---|
1823 | This,
|
---|
1824 | PciHandle,
|
---|
1825 | RomImage,
|
---|
1826 | RomSize,
|
---|
1827 | NULL,
|
---|
1828 | Flags,
|
---|
1829 | NULL,
|
---|
1830 | NULL
|
---|
1831 | );
|
---|
1832 |
|
---|
1833 | }
|
---|
1834 |
|
---|
1835 | /**
|
---|
1836 |
|
---|
1837 | Routine Description:
|
---|
1838 | Test to see if a legacy PCI ROM exists for this device. Optionally return
|
---|
1839 | the Legacy ROM instance for this PCI device.
|
---|
1840 |
|
---|
1841 | @param[in] This Protocol instance pointer.
|
---|
1842 | @param[in] PciHandle The PCI PC-AT OPROM from this devices ROM BAR will be loaded
|
---|
1843 | @param[out] RomImage Return the legacy PCI ROM for this device
|
---|
1844 | @param[out] RomSize Size of ROM Image
|
---|
1845 | @param[out] RuntimeImageLength Runtime size of ROM Image
|
---|
1846 | @param[out] Flags Indicates if ROM found and if PC-AT.
|
---|
1847 | @param[out] OpromRevision Revision of the PCI Rom
|
---|
1848 | @param[out] ConfigUtilityCodeHeaderPointer of Configuration Utility Code Header
|
---|
1849 |
|
---|
1850 | @return EFI_SUCCESS Legacy Option ROM available for this device
|
---|
1851 | @return EFI_ALREADY_STARTED This device is already managed by its Oprom
|
---|
1852 | @return EFI_UNSUPPORTED Legacy Option ROM not supported.
|
---|
1853 |
|
---|
1854 | **/
|
---|
1855 | EFI_STATUS
|
---|
1856 | LegacyBiosCheckPciRomEx (
|
---|
1857 | IN EFI_LEGACY_BIOS_PROTOCOL *This,
|
---|
1858 | IN EFI_HANDLE PciHandle,
|
---|
1859 | OUT VOID **RomImage, OPTIONAL
|
---|
1860 | OUT UINTN *RomSize, OPTIONAL
|
---|
1861 | OUT UINTN *RuntimeImageLength, OPTIONAL
|
---|
1862 | OUT UINTN *Flags, OPTIONAL
|
---|
1863 | OUT UINT8 *OpromRevision, OPTIONAL
|
---|
1864 | OUT VOID **ConfigUtilityCodeHeader OPTIONAL
|
---|
1865 | )
|
---|
1866 | {
|
---|
1867 | EFI_STATUS Status;
|
---|
1868 | LEGACY_BIOS_INSTANCE *Private;
|
---|
1869 | EFI_PCI_IO_PROTOCOL *PciIo;
|
---|
1870 | UINTN LocalRomSize;
|
---|
1871 | VOID *LocalRomImage;
|
---|
1872 | PCI_TYPE00 PciConfigHeader;
|
---|
1873 | VOID *LocalConfigUtilityCodeHeader;
|
---|
1874 |
|
---|
1875 | LocalConfigUtilityCodeHeader = NULL;
|
---|
1876 | *Flags = NO_ROM;
|
---|
1877 | Status = gBS->HandleProtocol (
|
---|
1878 | PciHandle,
|
---|
1879 | &gEfiPciIoProtocolGuid,
|
---|
1880 | (VOID **) &PciIo
|
---|
1881 | );
|
---|
1882 | if (EFI_ERROR (Status)) {
|
---|
1883 | return EFI_UNSUPPORTED;
|
---|
1884 | }
|
---|
1885 |
|
---|
1886 | //
|
---|
1887 | // See if the option ROM for PciHandle has already been executed
|
---|
1888 | //
|
---|
1889 | Status = IsLegacyRom (PciHandle);
|
---|
1890 | if (!EFI_ERROR (Status)) {
|
---|
1891 | *Flags |= (UINTN)(ROM_FOUND | VALID_LEGACY_ROM);
|
---|
1892 | return EFI_SUCCESS;
|
---|
1893 | }
|
---|
1894 | //
|
---|
1895 | // Check for PCI ROM Bar
|
---|
1896 | //
|
---|
1897 | LocalRomSize = (UINTN) PciIo->RomSize;
|
---|
1898 | LocalRomImage = PciIo->RomImage;
|
---|
1899 | if (LocalRomSize != 0) {
|
---|
1900 | *Flags |= ROM_FOUND;
|
---|
1901 | }
|
---|
1902 |
|
---|
1903 | //
|
---|
1904 | // PCI specification states you should check VendorId and Device Id.
|
---|
1905 | //
|
---|
1906 | PciIo->Pci.Read (
|
---|
1907 | PciIo,
|
---|
1908 | EfiPciIoWidthUint32,
|
---|
1909 | 0,
|
---|
1910 | sizeof (PciConfigHeader) / sizeof (UINT32),
|
---|
1911 | &PciConfigHeader
|
---|
1912 | );
|
---|
1913 |
|
---|
1914 | Private = LEGACY_BIOS_INSTANCE_FROM_THIS (This);
|
---|
1915 | Status = GetPciLegacyRom (
|
---|
1916 | Private->Csm16PciInterfaceVersion,
|
---|
1917 | PciConfigHeader.Hdr.VendorId,
|
---|
1918 | PciConfigHeader.Hdr.DeviceId,
|
---|
1919 | &LocalRomImage,
|
---|
1920 | &LocalRomSize,
|
---|
1921 | RuntimeImageLength,
|
---|
1922 | OpromRevision,
|
---|
1923 | &LocalConfigUtilityCodeHeader
|
---|
1924 | );
|
---|
1925 | if (EFI_ERROR (Status)) {
|
---|
1926 | return EFI_UNSUPPORTED;
|
---|
1927 | }
|
---|
1928 |
|
---|
1929 | *Flags |= VALID_LEGACY_ROM;
|
---|
1930 |
|
---|
1931 | //
|
---|
1932 | // See if Configuration Utility Code Header valid
|
---|
1933 | //
|
---|
1934 | if (LocalConfigUtilityCodeHeader != NULL) {
|
---|
1935 | *Flags |= ROM_WITH_CONFIG;
|
---|
1936 | }
|
---|
1937 |
|
---|
1938 | if (ConfigUtilityCodeHeader != NULL) {
|
---|
1939 | *ConfigUtilityCodeHeader = LocalConfigUtilityCodeHeader;
|
---|
1940 | }
|
---|
1941 |
|
---|
1942 | if (RomImage != NULL) {
|
---|
1943 | *RomImage = LocalRomImage;
|
---|
1944 | }
|
---|
1945 |
|
---|
1946 | if (RomSize != NULL) {
|
---|
1947 | *RomSize = LocalRomSize;
|
---|
1948 | }
|
---|
1949 |
|
---|
1950 | return EFI_SUCCESS;
|
---|
1951 | }
|
---|
1952 |
|
---|
1953 | /**
|
---|
1954 | Load a legacy PC-AT OPROM on the PciHandle device. Return information
|
---|
1955 | about how many disks were added by the OPROM and the shadow address and
|
---|
1956 | size. DiskStart & DiskEnd are INT 13h drive letters. Thus 0x80 is C:
|
---|
1957 |
|
---|
1958 | @retval EFI_SUCCESS Legacy ROM loaded for this device
|
---|
1959 | @retval EFI_NOT_FOUND No PS2 Keyboard found
|
---|
1960 |
|
---|
1961 | **/
|
---|
1962 | EFI_STATUS
|
---|
1963 | EnablePs2Keyboard (
|
---|
1964 | VOID
|
---|
1965 | )
|
---|
1966 | {
|
---|
1967 | EFI_STATUS Status;
|
---|
1968 | EFI_HANDLE *HandleBuffer;
|
---|
1969 | UINTN HandleCount;
|
---|
1970 | EFI_ISA_IO_PROTOCOL *IsaIo;
|
---|
1971 | UINTN Index;
|
---|
1972 |
|
---|
1973 | //
|
---|
1974 | // Get SimpleTextIn and find PS2 controller
|
---|
1975 | //
|
---|
1976 | Status = gBS->LocateHandleBuffer (
|
---|
1977 | ByProtocol,
|
---|
1978 | &gEfiSimpleTextInProtocolGuid,
|
---|
1979 | NULL,
|
---|
1980 | &HandleCount,
|
---|
1981 | &HandleBuffer
|
---|
1982 | );
|
---|
1983 | if (EFI_ERROR (Status)) {
|
---|
1984 | return EFI_NOT_FOUND;
|
---|
1985 | }
|
---|
1986 | for (Index = 0; Index < HandleCount; Index++) {
|
---|
1987 | //
|
---|
1988 | // Open the IO Abstraction(s) needed to perform the supported test
|
---|
1989 | //
|
---|
1990 | Status = gBS->OpenProtocol (
|
---|
1991 | HandleBuffer[Index],
|
---|
1992 | &gEfiIsaIoProtocolGuid,
|
---|
1993 | (VOID **) &IsaIo,
|
---|
1994 | NULL,
|
---|
1995 | HandleBuffer[Index],
|
---|
1996 | EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL
|
---|
1997 | );
|
---|
1998 |
|
---|
1999 | if (!EFI_ERROR (Status)) {
|
---|
2000 | //
|
---|
2001 | // Use the ISA I/O Protocol to see if Controller is the Keyboard
|
---|
2002 | // controller
|
---|
2003 | //
|
---|
2004 | if (IsaIo->ResourceList->Device.HID != EISA_PNP_ID (0x303) || IsaIo->ResourceList->Device.UID != 0) {
|
---|
2005 | Status = EFI_UNSUPPORTED;
|
---|
2006 | }
|
---|
2007 |
|
---|
2008 | gBS->CloseProtocol (
|
---|
2009 | HandleBuffer[Index],
|
---|
2010 | &gEfiIsaIoProtocolGuid,
|
---|
2011 | NULL,
|
---|
2012 | HandleBuffer[Index]
|
---|
2013 | );
|
---|
2014 | }
|
---|
2015 |
|
---|
2016 | if (!EFI_ERROR (Status)) {
|
---|
2017 | gBS->ConnectController (HandleBuffer[Index], NULL, NULL, FALSE);
|
---|
2018 | }
|
---|
2019 | }
|
---|
2020 | FreePool (HandleBuffer);
|
---|
2021 | return EFI_SUCCESS;
|
---|
2022 | }
|
---|
2023 |
|
---|
2024 |
|
---|
2025 | /**
|
---|
2026 | Load a legacy PC-AT OpROM for VGA controller.
|
---|
2027 |
|
---|
2028 | @param Private Driver private data.
|
---|
2029 |
|
---|
2030 | @retval EFI_SUCCESS Legacy ROM successfully installed for this device.
|
---|
2031 | @retval EFI_DEVICE_ERROR No VGA device handle found, or native EFI video
|
---|
2032 | driver cannot be successfully disconnected, or VGA
|
---|
2033 | thunk driver cannot be successfully connected.
|
---|
2034 |
|
---|
2035 | **/
|
---|
2036 | EFI_STATUS
|
---|
2037 | LegacyBiosInstallVgaRom (
|
---|
2038 | IN LEGACY_BIOS_INSTANCE *Private
|
---|
2039 | )
|
---|
2040 | {
|
---|
2041 | EFI_STATUS Status;
|
---|
2042 | EFI_HANDLE VgaHandle;
|
---|
2043 | UINTN HandleCount;
|
---|
2044 | EFI_HANDLE *HandleBuffer;
|
---|
2045 | EFI_HANDLE *ConnectHandleBuffer;
|
---|
2046 | EFI_PCI_IO_PROTOCOL *PciIo;
|
---|
2047 | PCI_TYPE00 PciConfigHeader;
|
---|
2048 | UINT64 Supports;
|
---|
2049 | EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfoBuffer;
|
---|
2050 | UINTN EntryCount;
|
---|
2051 | UINTN Index;
|
---|
2052 | VOID *Interface;
|
---|
2053 |
|
---|
2054 | //
|
---|
2055 | // EfiLegacyBiosGuild attached to a device implies that there is a legacy
|
---|
2056 | // BIOS associated with that device.
|
---|
2057 | //
|
---|
2058 | // There are 3 cases to consider.
|
---|
2059 | // Case 1: No EFI driver is controlling the video.
|
---|
2060 | // Action: Return EFI_SUCCESS from DisconnectController, search
|
---|
2061 | // video thunk driver, and connect it.
|
---|
2062 | // Case 2: EFI driver is controlling the video and EfiLegacyBiosGuid is
|
---|
2063 | // not on the image handle.
|
---|
2064 | // Action: Disconnect EFI driver.
|
---|
2065 | // ConnectController for video thunk
|
---|
2066 | // Case 3: EFI driver is controlling the video and EfiLegacyBiosGuid is
|
---|
2067 | // on the image handle.
|
---|
2068 | // Action: Do nothing and set Private->VgaInstalled = TRUE.
|
---|
2069 | // Then this routine is not called any more.
|
---|
2070 | //
|
---|
2071 | //
|
---|
2072 | // Get the VGA device.
|
---|
2073 | //
|
---|
2074 | Status = Private->LegacyBiosPlatform->GetPlatformHandle (
|
---|
2075 | Private->LegacyBiosPlatform,
|
---|
2076 | EfiGetPlatformVgaHandle,
|
---|
2077 | 0,
|
---|
2078 | &HandleBuffer,
|
---|
2079 | &HandleCount,
|
---|
2080 | NULL
|
---|
2081 | );
|
---|
2082 | if (EFI_ERROR (Status)) {
|
---|
2083 | return EFI_DEVICE_ERROR;
|
---|
2084 | }
|
---|
2085 |
|
---|
2086 | VgaHandle = HandleBuffer[0];
|
---|
2087 |
|
---|
2088 | //
|
---|
2089 | // Check whether video thunk driver already starts.
|
---|
2090 | //
|
---|
2091 | Status = gBS->OpenProtocolInformation (
|
---|
2092 | VgaHandle,
|
---|
2093 | &gEfiPciIoProtocolGuid,
|
---|
2094 | &OpenInfoBuffer,
|
---|
2095 | &EntryCount
|
---|
2096 | );
|
---|
2097 | if (EFI_ERROR (Status)) {
|
---|
2098 | return Status;
|
---|
2099 | }
|
---|
2100 |
|
---|
2101 | for (Index = 0; Index < EntryCount; Index++) {
|
---|
2102 | if ((OpenInfoBuffer[Index].Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) != 0) {
|
---|
2103 | Status = gBS->HandleProtocol (
|
---|
2104 | OpenInfoBuffer[Index].AgentHandle,
|
---|
2105 | &gEfiLegacyBiosGuid,
|
---|
2106 | (VOID **) &Interface
|
---|
2107 | );
|
---|
2108 | if (!EFI_ERROR (Status)) {
|
---|
2109 | //
|
---|
2110 | // This should be video thunk driver which is managing video device
|
---|
2111 | // So it need not start again
|
---|
2112 | //
|
---|
2113 | DEBUG ((EFI_D_INFO, "Video thunk driver already start! Return!\n"));
|
---|
2114 | Private->VgaInstalled = TRUE;
|
---|
2115 | return EFI_SUCCESS;
|
---|
2116 | }
|
---|
2117 | }
|
---|
2118 | }
|
---|
2119 |
|
---|
2120 | //
|
---|
2121 | // Kick off the native EFI driver
|
---|
2122 | //
|
---|
2123 | Status = gBS->DisconnectController (
|
---|
2124 | VgaHandle,
|
---|
2125 | NULL,
|
---|
2126 | NULL
|
---|
2127 | );
|
---|
2128 | if (EFI_ERROR (Status)) {
|
---|
2129 | if (Status != EFI_NOT_FOUND) {
|
---|
2130 | return EFI_DEVICE_ERROR;
|
---|
2131 | } else {
|
---|
2132 | return Status;
|
---|
2133 | }
|
---|
2134 | }
|
---|
2135 | //
|
---|
2136 | // Find all the Thunk Driver
|
---|
2137 | //
|
---|
2138 | HandleBuffer = NULL;
|
---|
2139 | Status = gBS->LocateHandleBuffer (
|
---|
2140 | ByProtocol,
|
---|
2141 | &gEfiLegacyBiosGuid,
|
---|
2142 | NULL,
|
---|
2143 | &HandleCount,
|
---|
2144 | &HandleBuffer
|
---|
2145 | );
|
---|
2146 | ASSERT_EFI_ERROR (Status);
|
---|
2147 | ConnectHandleBuffer = (EFI_HANDLE *) AllocatePool (sizeof (EFI_HANDLE) * (HandleCount + 1));
|
---|
2148 | ASSERT (ConnectHandleBuffer != NULL);
|
---|
2149 |
|
---|
2150 | CopyMem (
|
---|
2151 | ConnectHandleBuffer,
|
---|
2152 | HandleBuffer,
|
---|
2153 | sizeof (EFI_HANDLE) * HandleCount
|
---|
2154 | );
|
---|
2155 | ConnectHandleBuffer[HandleCount] = NULL;
|
---|
2156 |
|
---|
2157 | FreePool (HandleBuffer);
|
---|
2158 |
|
---|
2159 | //
|
---|
2160 | // Enable the device and make sure VGA cycles are being forwarded to this VGA device
|
---|
2161 | //
|
---|
2162 | Status = gBS->HandleProtocol (
|
---|
2163 | VgaHandle,
|
---|
2164 | &gEfiPciIoProtocolGuid,
|
---|
2165 | (VOID **) &PciIo
|
---|
2166 | );
|
---|
2167 | ASSERT_EFI_ERROR (Status);
|
---|
2168 | PciIo->Pci.Read (
|
---|
2169 | PciIo,
|
---|
2170 | EfiPciIoWidthUint32,
|
---|
2171 | 0,
|
---|
2172 | sizeof (PciConfigHeader) / sizeof (UINT32),
|
---|
2173 | &PciConfigHeader
|
---|
2174 | );
|
---|
2175 |
|
---|
2176 | Status = PciIo->Attributes (
|
---|
2177 | PciIo,
|
---|
2178 | EfiPciIoAttributeOperationSupported,
|
---|
2179 | 0,
|
---|
2180 | &Supports
|
---|
2181 | );
|
---|
2182 | if (!EFI_ERROR (Status)) {
|
---|
2183 | Supports &= (UINT64)(EFI_PCI_DEVICE_ENABLE | EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY | \
|
---|
2184 | EFI_PCI_IO_ATTRIBUTE_VGA_IO | EFI_PCI_IO_ATTRIBUTE_VGA_IO_16);
|
---|
2185 | Status = PciIo->Attributes (
|
---|
2186 | PciIo,
|
---|
2187 | EfiPciIoAttributeOperationEnable,
|
---|
2188 | Supports,
|
---|
2189 | NULL
|
---|
2190 | );
|
---|
2191 | }
|
---|
2192 |
|
---|
2193 | if (Status == EFI_SUCCESS) {
|
---|
2194 | Private->VgaInstalled = TRUE;
|
---|
2195 |
|
---|
2196 | //
|
---|
2197 | // Attach the VGA thunk driver.
|
---|
2198 | // Assume the video is installed. This prevents potential of infinite recursion.
|
---|
2199 | //
|
---|
2200 | Status = gBS->ConnectController (
|
---|
2201 | VgaHandle,
|
---|
2202 | ConnectHandleBuffer,
|
---|
2203 | NULL,
|
---|
2204 | TRUE
|
---|
2205 | );
|
---|
2206 | }
|
---|
2207 |
|
---|
2208 | FreePool (ConnectHandleBuffer);
|
---|
2209 |
|
---|
2210 | if (EFI_ERROR (Status)) {
|
---|
2211 |
|
---|
2212 | Private->VgaInstalled = FALSE;
|
---|
2213 |
|
---|
2214 | //
|
---|
2215 | // Reconnect the EFI VGA driver.
|
---|
2216 | //
|
---|
2217 | gBS->ConnectController (VgaHandle, NULL, NULL, TRUE);
|
---|
2218 | return EFI_DEVICE_ERROR;
|
---|
2219 | }
|
---|
2220 |
|
---|
2221 | return EFI_SUCCESS;
|
---|
2222 | }
|
---|
2223 |
|
---|
2224 |
|
---|
2225 | /**
|
---|
2226 | Load a legacy PC-AT OpROM.
|
---|
2227 |
|
---|
2228 | @param This Protocol instance pointer.
|
---|
2229 | @param Private Driver's private data.
|
---|
2230 | @param PciHandle The EFI handle for the PCI device. It could be
|
---|
2231 | NULL if the OpROM image is not associated with
|
---|
2232 | any device.
|
---|
2233 | @param OpromRevision The revision of PCI PC-AT ROM image.
|
---|
2234 | @param RomImage Pointer to PCI PC-AT ROM image header. It must not
|
---|
2235 | be NULL.
|
---|
2236 | @param ImageSize Size of the PCI PC-AT ROM image.
|
---|
2237 | @param RuntimeImageLength On input is the max runtime image length indicated by the PCIR structure
|
---|
2238 | On output is the actual runtime image length
|
---|
2239 | @param DiskStart Disk number of first device hooked by the ROM. If
|
---|
2240 | DiskStart is the same as DiskEnd no disked were
|
---|
2241 | hooked.
|
---|
2242 | @param DiskEnd Disk number of the last device hooked by the ROM.
|
---|
2243 | @param RomShadowAddress Shadow address of PC-AT ROM
|
---|
2244 |
|
---|
2245 | @retval EFI_SUCCESS Legacy ROM loaded for this device
|
---|
2246 | @retval EFI_OUT_OF_RESOURCES No more space for this ROM
|
---|
2247 |
|
---|
2248 | **/
|
---|
2249 | EFI_STATUS
|
---|
2250 | EFIAPI
|
---|
2251 | LegacyBiosInstallRom (
|
---|
2252 | IN EFI_LEGACY_BIOS_PROTOCOL *This,
|
---|
2253 | IN LEGACY_BIOS_INSTANCE *Private,
|
---|
2254 | IN EFI_HANDLE PciHandle,
|
---|
2255 | IN UINT8 OpromRevision,
|
---|
2256 | IN VOID *RomImage,
|
---|
2257 | IN UINTN ImageSize,
|
---|
2258 | IN OUT UINTN *RuntimeImageLength,
|
---|
2259 | OUT UINT8 *DiskStart, OPTIONAL
|
---|
2260 | OUT UINT8 *DiskEnd, OPTIONAL
|
---|
2261 | OUT VOID **RomShadowAddress OPTIONAL
|
---|
2262 | )
|
---|
2263 | {
|
---|
2264 | EFI_STATUS Status;
|
---|
2265 | EFI_STATUS PciEnableStatus;
|
---|
2266 | EFI_PCI_IO_PROTOCOL *PciIo;
|
---|
2267 | UINT8 LocalDiskStart;
|
---|
2268 | UINT8 LocalDiskEnd;
|
---|
2269 | UINTN Segment;
|
---|
2270 | UINTN Bus;
|
---|
2271 | UINTN Device;
|
---|
2272 | UINTN Function;
|
---|
2273 | EFI_IA32_REGISTER_SET Regs;
|
---|
2274 | UINT8 VideoMode;
|
---|
2275 | UINT8 OldVideoMode;
|
---|
2276 | EFI_TIME BootTime;
|
---|
2277 | UINT32 *BdaPtr;
|
---|
2278 | UINT32 LocalTime;
|
---|
2279 | UINT32 StartBbsIndex;
|
---|
2280 | UINT32 EndBbsIndex;
|
---|
2281 | UINT32 MaxRomAddr;
|
---|
2282 | UINTN TempData;
|
---|
2283 | UINTN InitAddress;
|
---|
2284 | UINTN RuntimeAddress;
|
---|
2285 | EFI_PHYSICAL_ADDRESS PhysicalAddress;
|
---|
2286 | UINT32 Granularity;
|
---|
2287 |
|
---|
2288 | PciIo = NULL;
|
---|
2289 | LocalDiskStart = 0;
|
---|
2290 | LocalDiskEnd = 0;
|
---|
2291 | Segment = 0;
|
---|
2292 | Bus = 0;
|
---|
2293 | Device = 0;
|
---|
2294 | Function = 0;
|
---|
2295 | VideoMode = 0;
|
---|
2296 | OldVideoMode = 0;
|
---|
2297 | PhysicalAddress = 0;
|
---|
2298 | MaxRomAddr = PcdGet32 (PcdEndOpromShadowAddress);
|
---|
2299 |
|
---|
2300 | if ((Private->Legacy16Table->TableLength >= OFFSET_OF(EFI_COMPATIBILITY16_TABLE, HiPermanentMemoryAddress)) &&
|
---|
2301 | (Private->Legacy16Table->UmaAddress != 0) &&
|
---|
2302 | (Private->Legacy16Table->UmaSize != 0) &&
|
---|
2303 | (MaxRomAddr > (Private->Legacy16Table->UmaAddress))) {
|
---|
2304 | MaxRomAddr = Private->Legacy16Table->UmaAddress;
|
---|
2305 | }
|
---|
2306 |
|
---|
2307 |
|
---|
2308 | PciProgramAllInterruptLineRegisters (Private);
|
---|
2309 |
|
---|
2310 | if ((OpromRevision >= 3) && (Private->Csm16PciInterfaceVersion >= 0x0300)) {
|
---|
2311 | //
|
---|
2312 | // CSM16 3.0 meets PCI 3.0 OpROM
|
---|
2313 | // first test if there is enough space for its INIT code
|
---|
2314 | //
|
---|
2315 | PhysicalAddress = CONVENTIONAL_MEMORY_TOP;
|
---|
2316 | Status = gBS->AllocatePages (
|
---|
2317 | AllocateMaxAddress,
|
---|
2318 | EfiBootServicesCode,
|
---|
2319 | EFI_SIZE_TO_PAGES (ImageSize),
|
---|
2320 | &PhysicalAddress
|
---|
2321 | );
|
---|
2322 |
|
---|
2323 | if (EFI_ERROR (Status)) {
|
---|
2324 | DEBUG ((EFI_D_ERROR, "return LegacyBiosInstallRom(%d): EFI_OUT_OF_RESOURCES (no more space for OpROM)\n", __LINE__));
|
---|
2325 | //
|
---|
2326 | // Report Status Code to indicate that there is no enough space for OpROM
|
---|
2327 | //
|
---|
2328 | REPORT_STATUS_CODE (
|
---|
2329 | EFI_ERROR_CODE | EFI_ERROR_MINOR,
|
---|
2330 | (EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_DXE_BS_EC_LEGACY_OPROM_NO_SPACE)
|
---|
2331 | );
|
---|
2332 | return EFI_OUT_OF_RESOURCES;
|
---|
2333 | }
|
---|
2334 | InitAddress = (UINTN) PhysicalAddress;
|
---|
2335 | //
|
---|
2336 | // then test if there is enough space for its RT code
|
---|
2337 | //
|
---|
2338 | RuntimeAddress = Private->OptionRom;
|
---|
2339 | if (RuntimeAddress + *RuntimeImageLength > MaxRomAddr) {
|
---|
2340 | DEBUG ((EFI_D_ERROR, "return LegacyBiosInstallRom(%d): EFI_OUT_OF_RESOURCES (no more space for OpROM)\n", __LINE__));
|
---|
2341 | gBS->FreePages (PhysicalAddress, EFI_SIZE_TO_PAGES (ImageSize));
|
---|
2342 | //
|
---|
2343 | // Report Status Code to indicate that there is no enough space for OpROM
|
---|
2344 | //
|
---|
2345 | REPORT_STATUS_CODE (
|
---|
2346 | EFI_ERROR_CODE | EFI_ERROR_MINOR,
|
---|
2347 | (EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_DXE_BS_EC_LEGACY_OPROM_NO_SPACE)
|
---|
2348 | );
|
---|
2349 | return EFI_OUT_OF_RESOURCES;
|
---|
2350 | }
|
---|
2351 | } else {
|
---|
2352 | // CSM16 3.0 meets PCI 2.x OpROM
|
---|
2353 | // CSM16 2.x meets PCI 2.x/3.0 OpROM
|
---|
2354 | // test if there is enough space for its INIT code
|
---|
2355 | //
|
---|
2356 | InitAddress = PCI_START_ADDRESS (Private->OptionRom);
|
---|
2357 | if (InitAddress + ImageSize > MaxRomAddr) {
|
---|
2358 | DEBUG ((EFI_D_ERROR, "return LegacyBiosInstallRom(%d): EFI_OUT_OF_RESOURCES (no more space for OpROM)\n", __LINE__));
|
---|
2359 | //
|
---|
2360 | // Report Status Code to indicate that there is no enough space for OpROM
|
---|
2361 | //
|
---|
2362 | REPORT_STATUS_CODE (
|
---|
2363 | EFI_ERROR_CODE | EFI_ERROR_MINOR,
|
---|
2364 | (EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_DXE_BS_EC_LEGACY_OPROM_NO_SPACE)
|
---|
2365 | );
|
---|
2366 | return EFI_OUT_OF_RESOURCES;
|
---|
2367 | }
|
---|
2368 |
|
---|
2369 | RuntimeAddress = InitAddress;
|
---|
2370 | }
|
---|
2371 |
|
---|
2372 | Private->LegacyRegion->UnLock (
|
---|
2373 | Private->LegacyRegion,
|
---|
2374 | 0xE0000,
|
---|
2375 | 0x20000,
|
---|
2376 | &Granularity
|
---|
2377 | );
|
---|
2378 |
|
---|
2379 | Private->LegacyRegion->UnLock (
|
---|
2380 | Private->LegacyRegion,
|
---|
2381 | (UINT32) RuntimeAddress,
|
---|
2382 | (UINT32) ImageSize,
|
---|
2383 | &Granularity
|
---|
2384 | );
|
---|
2385 |
|
---|
2386 | DEBUG ((EFI_D_INFO, " Shadowing OpROM init/runtime/isize = %x/%x/%x\n", InitAddress, RuntimeAddress, ImageSize));
|
---|
2387 |
|
---|
2388 | CopyMem ((VOID *) InitAddress, RomImage, ImageSize);
|
---|
2389 |
|
---|
2390 | //
|
---|
2391 | // Read the highest disk number "installed: and assume a new disk will
|
---|
2392 | // show up on the first drive past the current value.
|
---|
2393 | // There are several considerations here:
|
---|
2394 | // 1. Non-BBS compliant drives will change 40:75 but 16-bit CSM will undo
|
---|
2395 | // the change until boot selection time frame.
|
---|
2396 | // 2. BBS compliants drives will not change 40:75 until boot time.
|
---|
2397 | // 3. Onboard IDE controllers will change 40:75
|
---|
2398 | //
|
---|
2399 | ACCESS_PAGE0_CODE (
|
---|
2400 | LocalDiskStart = (UINT8) ((*(UINT8 *) ((UINTN) 0x475)) + 0x80);
|
---|
2401 | if ((Private->Disk4075 + 0x80) < LocalDiskStart) {
|
---|
2402 | //
|
---|
2403 | // Update table since onboard IDE drives found
|
---|
2404 | //
|
---|
2405 | Private->LegacyEfiHddTable[Private->LegacyEfiHddTableIndex].PciSegment = 0xff;
|
---|
2406 | Private->LegacyEfiHddTable[Private->LegacyEfiHddTableIndex].PciBus = 0xff;
|
---|
2407 | Private->LegacyEfiHddTable[Private->LegacyEfiHddTableIndex].PciDevice = 0xff;
|
---|
2408 | Private->LegacyEfiHddTable[Private->LegacyEfiHddTableIndex].PciFunction = 0xff;
|
---|
2409 | Private->LegacyEfiHddTable[Private->LegacyEfiHddTableIndex].StartDriveNumber = (UINT8) (Private->Disk4075 + 0x80);
|
---|
2410 | Private->LegacyEfiHddTable[Private->LegacyEfiHddTableIndex].EndDriveNumber = LocalDiskStart;
|
---|
2411 | Private->LegacyEfiHddTableIndex ++;
|
---|
2412 | Private->Disk4075 = (UINT8) (LocalDiskStart & 0x7f);
|
---|
2413 | Private->DiskEnd = LocalDiskStart;
|
---|
2414 | }
|
---|
2415 |
|
---|
2416 | if (PciHandle != mVgaHandle) {
|
---|
2417 |
|
---|
2418 | EnablePs2Keyboard ();
|
---|
2419 |
|
---|
2420 | //
|
---|
2421 | // Store current mode settings since PrepareToScanRom may change mode.
|
---|
2422 | //
|
---|
2423 | VideoMode = *(UINT8 *) ((UINTN) (0x400 + BDA_VIDEO_MODE));
|
---|
2424 | }
|
---|
2425 | );
|
---|
2426 |
|
---|
2427 | //
|
---|
2428 | // Notify the platform that we are about to scan the ROM
|
---|
2429 | //
|
---|
2430 | Status = Private->LegacyBiosPlatform->PlatformHooks (
|
---|
2431 | Private->LegacyBiosPlatform,
|
---|
2432 | EfiPlatformHookPrepareToScanRom,
|
---|
2433 | 0,
|
---|
2434 | PciHandle,
|
---|
2435 | &InitAddress,
|
---|
2436 | NULL,
|
---|
2437 | NULL
|
---|
2438 | );
|
---|
2439 |
|
---|
2440 | //
|
---|
2441 | // If Status returned is EFI_UNSUPPORTED then abort due to platform
|
---|
2442 | // policy.
|
---|
2443 | //
|
---|
2444 | if (Status == EFI_UNSUPPORTED) {
|
---|
2445 | goto Done;
|
---|
2446 | }
|
---|
2447 |
|
---|
2448 | //
|
---|
2449 | // Report corresponding status code
|
---|
2450 | //
|
---|
2451 | REPORT_STATUS_CODE (
|
---|
2452 | EFI_PROGRESS_CODE,
|
---|
2453 | (EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_CSM_LEGACY_ROM_INIT)
|
---|
2454 | );
|
---|
2455 |
|
---|
2456 | //
|
---|
2457 | // Generate number of ticks since midnight for BDA. Some OPROMs require
|
---|
2458 | // this. Place result in 40:6C-6F
|
---|
2459 | //
|
---|
2460 | gRT->GetTime (&BootTime, NULL);
|
---|
2461 | LocalTime = BootTime.Hour * 3600 + BootTime.Minute * 60 + BootTime.Second;
|
---|
2462 |
|
---|
2463 | //
|
---|
2464 | // Multiply result by 18.2 for number of ticks since midnight.
|
---|
2465 | // Use 182/10 to avoid floating point math.
|
---|
2466 | //
|
---|
2467 | ACCESS_PAGE0_CODE (
|
---|
2468 | LocalTime = (LocalTime * 182) / 10;
|
---|
2469 | BdaPtr = (UINT32 *) ((UINTN) 0x46C);
|
---|
2470 | *BdaPtr = LocalTime;
|
---|
2471 | );
|
---|
2472 |
|
---|
2473 | //
|
---|
2474 | // Pass in handoff data
|
---|
2475 | //
|
---|
2476 | PciEnableStatus = EFI_UNSUPPORTED;
|
---|
2477 | ZeroMem (&Regs, sizeof (Regs));
|
---|
2478 | if (PciHandle != NULL) {
|
---|
2479 |
|
---|
2480 | Status = gBS->HandleProtocol (
|
---|
2481 | PciHandle,
|
---|
2482 | &gEfiPciIoProtocolGuid,
|
---|
2483 | (VOID **) &PciIo
|
---|
2484 | );
|
---|
2485 | ASSERT_EFI_ERROR (Status);
|
---|
2486 |
|
---|
2487 | //
|
---|
2488 | // Enable command register.
|
---|
2489 | //
|
---|
2490 | PciEnableStatus = PciIo->Attributes (
|
---|
2491 | PciIo,
|
---|
2492 | EfiPciIoAttributeOperationEnable,
|
---|
2493 | EFI_PCI_DEVICE_ENABLE,
|
---|
2494 | NULL
|
---|
2495 | );
|
---|
2496 |
|
---|
2497 | PciIo->GetLocation (
|
---|
2498 | PciIo,
|
---|
2499 | &Segment,
|
---|
2500 | &Bus,
|
---|
2501 | &Device,
|
---|
2502 | &Function
|
---|
2503 | );
|
---|
2504 | DEBUG ((EFI_D_INFO, "Shadowing OpROM on the PCI device %x/%x/%x\n", Bus, Device, Function));
|
---|
2505 | }
|
---|
2506 |
|
---|
2507 | mIgnoreBbsUpdateFlag = FALSE;
|
---|
2508 | Regs.X.AX = Legacy16DispatchOprom;
|
---|
2509 |
|
---|
2510 | //
|
---|
2511 | // Generate DispatchOpRomTable data
|
---|
2512 | //
|
---|
2513 | Private->IntThunk->DispatchOpromTable.PnPInstallationCheckSegment = Private->Legacy16Table->PnPInstallationCheckSegment;
|
---|
2514 | Private->IntThunk->DispatchOpromTable.PnPInstallationCheckOffset = Private->Legacy16Table->PnPInstallationCheckOffset;
|
---|
2515 | Private->IntThunk->DispatchOpromTable.OpromSegment = (UINT16) (InitAddress >> 4);
|
---|
2516 | Private->IntThunk->DispatchOpromTable.PciBus = (UINT8) Bus;
|
---|
2517 | Private->IntThunk->DispatchOpromTable.PciDeviceFunction = (UINT8) ((Device << 3) | Function);
|
---|
2518 | Private->IntThunk->DispatchOpromTable.NumberBbsEntries = (UINT8) Private->IntThunk->EfiToLegacy16BootTable.NumberBbsEntries;
|
---|
2519 | Private->IntThunk->DispatchOpromTable.BbsTablePointer = (UINT32) (UINTN) Private->BbsTablePtr;
|
---|
2520 | Private->IntThunk->DispatchOpromTable.RuntimeSegment = (UINT16)((OpromRevision < 3) ? 0xffff : (RuntimeAddress >> 4));
|
---|
2521 | TempData = (UINTN) &Private->IntThunk->DispatchOpromTable;
|
---|
2522 | Regs.X.ES = EFI_SEGMENT ((UINT32) TempData);
|
---|
2523 | Regs.X.BX = EFI_OFFSET ((UINT32) TempData);
|
---|
2524 | //
|
---|
2525 | // Skip dispatching ROM for those PCI devices that can not be enabled by PciIo->Attributes
|
---|
2526 | // Otherwise, it may cause the system to hang in some cases
|
---|
2527 | //
|
---|
2528 | if (!EFI_ERROR (PciEnableStatus)) {
|
---|
2529 | DEBUG ((EFI_D_INFO, " Legacy16DispatchOprom - %02x/%02x/%02x\n", Bus, Device, Function));
|
---|
2530 | Private->LegacyBios.FarCall86 (
|
---|
2531 | &Private->LegacyBios,
|
---|
2532 | Private->Legacy16CallSegment,
|
---|
2533 | Private->Legacy16CallOffset,
|
---|
2534 | &Regs,
|
---|
2535 | NULL,
|
---|
2536 | 0
|
---|
2537 | );
|
---|
2538 | } else {
|
---|
2539 | Regs.X.BX = 0;
|
---|
2540 | }
|
---|
2541 |
|
---|
2542 | if (Private->IntThunk->DispatchOpromTable.NumberBbsEntries != (UINT8) Private->IntThunk->EfiToLegacy16BootTable.NumberBbsEntries) {
|
---|
2543 | Private->IntThunk->EfiToLegacy16BootTable.NumberBbsEntries = (UINT8) Private->IntThunk->DispatchOpromTable.NumberBbsEntries;
|
---|
2544 | mIgnoreBbsUpdateFlag = TRUE;
|
---|
2545 | }
|
---|
2546 | //
|
---|
2547 | // Check if non-BBS compliant drives found
|
---|
2548 | //
|
---|
2549 | if (Regs.X.BX != 0) {
|
---|
2550 | LocalDiskEnd = (UINT8) (LocalDiskStart + Regs.H.BL);
|
---|
2551 | Private->LegacyEfiHddTable[Private->LegacyEfiHddTableIndex].PciSegment = (UINT8) Segment;
|
---|
2552 | Private->LegacyEfiHddTable[Private->LegacyEfiHddTableIndex].PciBus = (UINT8) Bus;
|
---|
2553 | Private->LegacyEfiHddTable[Private->LegacyEfiHddTableIndex].PciDevice = (UINT8) Device;
|
---|
2554 | Private->LegacyEfiHddTable[Private->LegacyEfiHddTableIndex].PciFunction = (UINT8) Function;
|
---|
2555 | Private->LegacyEfiHddTable[Private->LegacyEfiHddTableIndex].StartDriveNumber = Private->DiskEnd;
|
---|
2556 | Private->DiskEnd = LocalDiskEnd;
|
---|
2557 | Private->LegacyEfiHddTable[Private->LegacyEfiHddTableIndex].EndDriveNumber = Private->DiskEnd;
|
---|
2558 | Private->LegacyEfiHddTableIndex += 1;
|
---|
2559 | }
|
---|
2560 | //
|
---|
2561 | // Skip video mode set, if installing VGA
|
---|
2562 | //
|
---|
2563 | if (PciHandle != mVgaHandle) {
|
---|
2564 | //
|
---|
2565 | // Set mode settings since PrepareToScanRom may change mode
|
---|
2566 | //
|
---|
2567 | ACCESS_PAGE0_CODE ({
|
---|
2568 | OldVideoMode = *(UINT8 *) ((UINTN) (0x400 + BDA_VIDEO_MODE));
|
---|
2569 | });
|
---|
2570 |
|
---|
2571 | if (VideoMode != OldVideoMode) {
|
---|
2572 | //
|
---|
2573 | // The active video mode is changed, restore it to original mode.
|
---|
2574 | //
|
---|
2575 | Regs.H.AH = 0x00;
|
---|
2576 | Regs.H.AL = VideoMode;
|
---|
2577 | Private->LegacyBios.Int86 (&Private->LegacyBios, 0x10, &Regs);
|
---|
2578 | }
|
---|
2579 | }
|
---|
2580 | //
|
---|
2581 | // Regs.X.AX from the adapter initializion is ignored since some adapters
|
---|
2582 | // do not follow the standard of setting AX = 0 on success.
|
---|
2583 | //
|
---|
2584 | //
|
---|
2585 | // The ROM could have updated it's size so we need to read again.
|
---|
2586 | //
|
---|
2587 | if (((EFI_LEGACY_EXPANSION_ROM_HEADER *) RuntimeAddress)->Signature != PCI_EXPANSION_ROM_HEADER_SIGNATURE) {
|
---|
2588 | //
|
---|
2589 | // Now we check the signature (0xaa55) to judge whether the run-time code is truly generated by INIT function.
|
---|
2590 | // If signature is not valid, that means the INIT function didn't copy the run-time code to RuntimeAddress.
|
---|
2591 | //
|
---|
2592 | *RuntimeImageLength = 0;
|
---|
2593 | } else {
|
---|
2594 | *RuntimeImageLength = ((EFI_LEGACY_EXPANSION_ROM_HEADER *) RuntimeAddress)->Size512 * 512;
|
---|
2595 | }
|
---|
2596 |
|
---|
2597 | DEBUG ((EFI_D_INFO, " fsize = %x\n", *RuntimeImageLength));
|
---|
2598 |
|
---|
2599 | //
|
---|
2600 | // If OpROM runs in 2.0 mode
|
---|
2601 | //
|
---|
2602 | if (PhysicalAddress == 0) {
|
---|
2603 | if (*RuntimeImageLength < ImageSize) {
|
---|
2604 | //
|
---|
2605 | // Make area from end of shadowed rom to end of original rom all ffs
|
---|
2606 | //
|
---|
2607 | gBS->SetMem ((VOID *) (InitAddress + *RuntimeImageLength), ImageSize - *RuntimeImageLength, 0xff);
|
---|
2608 | }
|
---|
2609 | }
|
---|
2610 |
|
---|
2611 | ACCESS_PAGE0_CODE (
|
---|
2612 | LocalDiskEnd = (UINT8) ((*(UINT8 *) ((UINTN) 0x475)) + 0x80);
|
---|
2613 | );
|
---|
2614 |
|
---|
2615 | //
|
---|
2616 | // Allow platform to perform any required actions after the
|
---|
2617 | // OPROM has been initialized.
|
---|
2618 | //
|
---|
2619 | Status = Private->LegacyBiosPlatform->PlatformHooks (
|
---|
2620 | Private->LegacyBiosPlatform,
|
---|
2621 | EfiPlatformHookAfterRomInit,
|
---|
2622 | 0,
|
---|
2623 | PciHandle,
|
---|
2624 | &RuntimeAddress,
|
---|
2625 | NULL,
|
---|
2626 | NULL
|
---|
2627 | );
|
---|
2628 | if (PciHandle != NULL) {
|
---|
2629 | //
|
---|
2630 | // If no PCI Handle then no header or Bevs.
|
---|
2631 | //
|
---|
2632 | if ((*RuntimeImageLength != 0) && (!mIgnoreBbsUpdateFlag)) {
|
---|
2633 | StartBbsIndex = Private->IntThunk->EfiToLegacy16BootTable.NumberBbsEntries;
|
---|
2634 | TempData = RuntimeAddress;
|
---|
2635 | UpdateBevBcvTable (
|
---|
2636 | Private,
|
---|
2637 | (EFI_LEGACY_EXPANSION_ROM_HEADER *) TempData,
|
---|
2638 | PciIo
|
---|
2639 | );
|
---|
2640 | EndBbsIndex = Private->IntThunk->EfiToLegacy16BootTable.NumberBbsEntries;
|
---|
2641 | LocalDiskEnd = (UINT8) (LocalDiskStart + (UINT8) (EndBbsIndex - StartBbsIndex));
|
---|
2642 | if (LocalDiskEnd != LocalDiskStart) {
|
---|
2643 | Private->LegacyEfiHddTable[Private->LegacyEfiHddTableIndex].PciSegment = (UINT8) Segment;
|
---|
2644 | Private->LegacyEfiHddTable[Private->LegacyEfiHddTableIndex].PciBus = (UINT8) Bus;
|
---|
2645 | Private->LegacyEfiHddTable[Private->LegacyEfiHddTableIndex].PciDevice = (UINT8) Device;
|
---|
2646 | Private->LegacyEfiHddTable[Private->LegacyEfiHddTableIndex].PciFunction = (UINT8) Function;
|
---|
2647 | Private->LegacyEfiHddTable[Private->LegacyEfiHddTableIndex].StartDriveNumber = Private->DiskEnd;
|
---|
2648 | Private->DiskEnd = LocalDiskEnd;
|
---|
2649 | Private->LegacyEfiHddTable[Private->LegacyEfiHddTableIndex].EndDriveNumber = Private->DiskEnd;
|
---|
2650 | Private->LegacyEfiHddTableIndex += 1;
|
---|
2651 | }
|
---|
2652 | }
|
---|
2653 | //
|
---|
2654 | // Mark PCI device as having a legacy BIOS ROM loaded.
|
---|
2655 | //
|
---|
2656 | RomShadow (
|
---|
2657 | PciHandle,
|
---|
2658 | (UINT32) RuntimeAddress,
|
---|
2659 | (UINT32) *RuntimeImageLength,
|
---|
2660 | LocalDiskStart,
|
---|
2661 | LocalDiskEnd
|
---|
2662 | );
|
---|
2663 | }
|
---|
2664 |
|
---|
2665 | //
|
---|
2666 | // Stuff caller's OPTIONAL return parameters.
|
---|
2667 | //
|
---|
2668 | if (RomShadowAddress != NULL) {
|
---|
2669 | *RomShadowAddress = (VOID *) RuntimeAddress;
|
---|
2670 | }
|
---|
2671 |
|
---|
2672 | if (DiskStart != NULL) {
|
---|
2673 | *DiskStart = LocalDiskStart;
|
---|
2674 | }
|
---|
2675 |
|
---|
2676 | if (DiskEnd != NULL) {
|
---|
2677 | *DiskEnd = LocalDiskEnd;
|
---|
2678 | }
|
---|
2679 |
|
---|
2680 | Private->OptionRom = (UINT32) (RuntimeAddress + *RuntimeImageLength);
|
---|
2681 |
|
---|
2682 | Status = EFI_SUCCESS;
|
---|
2683 |
|
---|
2684 | Done:
|
---|
2685 | if (PhysicalAddress != 0) {
|
---|
2686 | //
|
---|
2687 | // Free pages when OpROM is 3.0
|
---|
2688 | //
|
---|
2689 | gBS->FreePages (PhysicalAddress, EFI_SIZE_TO_PAGES (ImageSize));
|
---|
2690 | }
|
---|
2691 |
|
---|
2692 | //
|
---|
2693 | // Insure all shadowed areas are locked
|
---|
2694 | //
|
---|
2695 | Private->LegacyRegion->Lock (
|
---|
2696 | Private->LegacyRegion,
|
---|
2697 | 0xC0000,
|
---|
2698 | 0x40000,
|
---|
2699 | &Granularity
|
---|
2700 | );
|
---|
2701 |
|
---|
2702 | return Status;
|
---|
2703 | }
|
---|
2704 |
|
---|
2705 | /**
|
---|
2706 | Let IOMMU grant DMA access for the PCI device.
|
---|
2707 |
|
---|
2708 | @param PciHandle The EFI handle for the PCI device.
|
---|
2709 | @param HostAddress The system memory address to map to the PCI controller.
|
---|
2710 | @param NumberOfBytes The number of bytes to map.
|
---|
2711 |
|
---|
2712 | @retval EFI_SUCCESS The DMA access is granted.
|
---|
2713 | **/
|
---|
2714 | EFI_STATUS
|
---|
2715 | IoMmuGrantAccess (
|
---|
2716 | IN EFI_HANDLE PciHandle,
|
---|
2717 | IN EFI_PHYSICAL_ADDRESS HostAddress,
|
---|
2718 | IN UINTN NumberOfBytes
|
---|
2719 | )
|
---|
2720 | {
|
---|
2721 | EFI_PHYSICAL_ADDRESS DeviceAddress;
|
---|
2722 | VOID *Mapping;
|
---|
2723 | EFI_STATUS Status;
|
---|
2724 |
|
---|
2725 | if (PciHandle == NULL) {
|
---|
2726 | return EFI_UNSUPPORTED;
|
---|
2727 | }
|
---|
2728 |
|
---|
2729 | Status = EFI_SUCCESS;
|
---|
2730 | if (mIoMmu == NULL) {
|
---|
2731 | gBS->LocateProtocol (&gEdkiiIoMmuProtocolGuid, NULL, (VOID **)&mIoMmu);
|
---|
2732 | }
|
---|
2733 | if (mIoMmu != NULL) {
|
---|
2734 | Status = mIoMmu->Map (
|
---|
2735 | mIoMmu,
|
---|
2736 | EdkiiIoMmuOperationBusMasterCommonBuffer,
|
---|
2737 | (VOID *)(UINTN)HostAddress,
|
---|
2738 | &NumberOfBytes,
|
---|
2739 | &DeviceAddress,
|
---|
2740 | &Mapping
|
---|
2741 | );
|
---|
2742 | if (EFI_ERROR(Status)) {
|
---|
2743 | DEBUG ((DEBUG_ERROR, "LegacyPci - IoMmuMap - %r\n", Status));
|
---|
2744 | } else {
|
---|
2745 | ASSERT (DeviceAddress == HostAddress);
|
---|
2746 | Status = mIoMmu->SetAttribute (
|
---|
2747 | mIoMmu,
|
---|
2748 | PciHandle,
|
---|
2749 | Mapping,
|
---|
2750 | EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE
|
---|
2751 | );
|
---|
2752 | if (EFI_ERROR(Status)) {
|
---|
2753 | DEBUG ((DEBUG_ERROR, "LegacyPci - IoMmuSetAttribute - %r\n", Status));
|
---|
2754 | }
|
---|
2755 | }
|
---|
2756 | }
|
---|
2757 | return Status;
|
---|
2758 | }
|
---|
2759 |
|
---|
2760 | /**
|
---|
2761 | Load a legacy PC-AT OPROM on the PciHandle device. Return information
|
---|
2762 | about how many disks were added by the OPROM and the shadow address and
|
---|
2763 | size. DiskStart & DiskEnd are INT 13h drive letters. Thus 0x80 is C:
|
---|
2764 |
|
---|
2765 | @param This Protocol instance pointer.
|
---|
2766 | @param PciHandle The PCI PC-AT OPROM from this devices ROM BAR will
|
---|
2767 | be loaded. This value is NULL if RomImage is
|
---|
2768 | non-NULL. This is the normal case.
|
---|
2769 | @param RomImage A PCI PC-AT ROM image. This argument is non-NULL
|
---|
2770 | if there is no hardware associated with the ROM
|
---|
2771 | and thus no PciHandle, otherwise is must be NULL.
|
---|
2772 | Example is PXE base code.
|
---|
2773 | @param Flags Indicates if ROM found and if PC-AT.
|
---|
2774 | @param DiskStart Disk number of first device hooked by the ROM. If
|
---|
2775 | DiskStart is the same as DiskEnd no disked were
|
---|
2776 | hooked.
|
---|
2777 | @param DiskEnd Disk number of the last device hooked by the ROM.
|
---|
2778 | @param RomShadowAddress Shadow address of PC-AT ROM
|
---|
2779 | @param RomShadowedSize Size of RomShadowAddress in bytes
|
---|
2780 |
|
---|
2781 | @retval EFI_SUCCESS Legacy ROM loaded for this device
|
---|
2782 | @retval EFI_INVALID_PARAMETER PciHandle not found
|
---|
2783 | @retval EFI_UNSUPPORTED There is no PCI ROM in the ROM BAR or no onboard
|
---|
2784 | ROM
|
---|
2785 |
|
---|
2786 | **/
|
---|
2787 | EFI_STATUS
|
---|
2788 | EFIAPI
|
---|
2789 | LegacyBiosInstallPciRom (
|
---|
2790 | IN EFI_LEGACY_BIOS_PROTOCOL * This,
|
---|
2791 | IN EFI_HANDLE PciHandle,
|
---|
2792 | IN VOID **RomImage,
|
---|
2793 | OUT UINTN *Flags,
|
---|
2794 | OUT UINT8 *DiskStart, OPTIONAL
|
---|
2795 | OUT UINT8 *DiskEnd, OPTIONAL
|
---|
2796 | OUT VOID **RomShadowAddress, OPTIONAL
|
---|
2797 | OUT UINT32 *RomShadowedSize OPTIONAL
|
---|
2798 | )
|
---|
2799 | {
|
---|
2800 | EFI_STATUS Status;
|
---|
2801 | LEGACY_BIOS_INSTANCE *Private;
|
---|
2802 | VOID *LocalRomImage;
|
---|
2803 | UINTN ImageSize;
|
---|
2804 | UINTN RuntimeImageLength;
|
---|
2805 | EFI_PCI_IO_PROTOCOL *PciIo;
|
---|
2806 | PCI_TYPE01 PciConfigHeader;
|
---|
2807 | UINTN HandleCount;
|
---|
2808 | EFI_HANDLE *HandleBuffer;
|
---|
2809 | UINTN PciSegment;
|
---|
2810 | UINTN PciBus;
|
---|
2811 | UINTN PciDevice;
|
---|
2812 | UINTN PciFunction;
|
---|
2813 | UINTN LastBus;
|
---|
2814 | UINTN Index;
|
---|
2815 | UINT8 OpromRevision;
|
---|
2816 | UINT32 Granularity;
|
---|
2817 | PCI_3_0_DATA_STRUCTURE *Pcir;
|
---|
2818 |
|
---|
2819 | OpromRevision = 0;
|
---|
2820 |
|
---|
2821 | Private = LEGACY_BIOS_INSTANCE_FROM_THIS (This);
|
---|
2822 | if (Private->Legacy16Table->LastPciBus == 0) {
|
---|
2823 | //
|
---|
2824 | // Get last bus number if not already found
|
---|
2825 | //
|
---|
2826 | Status = gBS->LocateHandleBuffer (
|
---|
2827 | ByProtocol,
|
---|
2828 | &gEfiPciIoProtocolGuid,
|
---|
2829 | NULL,
|
---|
2830 | &HandleCount,
|
---|
2831 | &HandleBuffer
|
---|
2832 | );
|
---|
2833 |
|
---|
2834 | LastBus = 0;
|
---|
2835 | for (Index = 0; Index < HandleCount; Index++) {
|
---|
2836 | Status = gBS->HandleProtocol (
|
---|
2837 | HandleBuffer[Index],
|
---|
2838 | &gEfiPciIoProtocolGuid,
|
---|
2839 | (VOID **) &PciIo
|
---|
2840 | );
|
---|
2841 | if (EFI_ERROR (Status)) {
|
---|
2842 | continue;
|
---|
2843 | }
|
---|
2844 |
|
---|
2845 | Status = PciIo->GetLocation (
|
---|
2846 | PciIo,
|
---|
2847 | &PciSegment,
|
---|
2848 | &PciBus,
|
---|
2849 | &PciDevice,
|
---|
2850 | &PciFunction
|
---|
2851 | );
|
---|
2852 | if (PciBus > LastBus) {
|
---|
2853 | LastBus = PciBus;
|
---|
2854 | }
|
---|
2855 | }
|
---|
2856 |
|
---|
2857 | Private->LegacyRegion->UnLock (
|
---|
2858 | Private->LegacyRegion,
|
---|
2859 | 0xE0000,
|
---|
2860 | 0x20000,
|
---|
2861 | &Granularity
|
---|
2862 | );
|
---|
2863 | Private->Legacy16Table->LastPciBus = (UINT8) LastBus;
|
---|
2864 | Private->LegacyRegion->Lock (
|
---|
2865 | Private->LegacyRegion,
|
---|
2866 | 0xE0000,
|
---|
2867 | 0x20000,
|
---|
2868 | &Granularity
|
---|
2869 | );
|
---|
2870 | }
|
---|
2871 |
|
---|
2872 | *Flags = 0;
|
---|
2873 | if ((PciHandle != NULL) && (RomImage == NULL)) {
|
---|
2874 | //
|
---|
2875 | // If PciHandle has OpRom to Execute
|
---|
2876 | // and OpRom are all associated with Hardware
|
---|
2877 | //
|
---|
2878 | Status = gBS->HandleProtocol (
|
---|
2879 | PciHandle,
|
---|
2880 | &gEfiPciIoProtocolGuid,
|
---|
2881 | (VOID **) &PciIo
|
---|
2882 | );
|
---|
2883 |
|
---|
2884 | if (!EFI_ERROR (Status)) {
|
---|
2885 | PciIo->Pci.Read (
|
---|
2886 | PciIo,
|
---|
2887 | EfiPciIoWidthUint32,
|
---|
2888 | 0,
|
---|
2889 | sizeof (PciConfigHeader) / sizeof (UINT32),
|
---|
2890 | &PciConfigHeader
|
---|
2891 | );
|
---|
2892 |
|
---|
2893 | //
|
---|
2894 | // if video installed & OPROM is video return
|
---|
2895 | //
|
---|
2896 | if (
|
---|
2897 | (
|
---|
2898 | ((PciConfigHeader.Hdr.ClassCode[2] == PCI_CLASS_OLD) &&
|
---|
2899 | (PciConfigHeader.Hdr.ClassCode[1] == PCI_CLASS_OLD_VGA))
|
---|
2900 | ||
|
---|
2901 | ((PciConfigHeader.Hdr.ClassCode[2] == PCI_CLASS_DISPLAY) &&
|
---|
2902 | (PciConfigHeader.Hdr.ClassCode[1] == PCI_CLASS_DISPLAY_VGA))
|
---|
2903 | )
|
---|
2904 | &&
|
---|
2905 | (!Private->VgaInstalled)
|
---|
2906 | ) {
|
---|
2907 | mVgaInstallationInProgress = TRUE;
|
---|
2908 |
|
---|
2909 | //
|
---|
2910 | // return EFI_UNSUPPORTED;
|
---|
2911 | //
|
---|
2912 | }
|
---|
2913 | }
|
---|
2914 | //
|
---|
2915 | // To run any legacy image, the VGA needs to be installed first.
|
---|
2916 | // if installing the video, then don't need the thunk as already installed.
|
---|
2917 | //
|
---|
2918 | Status = Private->LegacyBiosPlatform->GetPlatformHandle (
|
---|
2919 | Private->LegacyBiosPlatform,
|
---|
2920 | EfiGetPlatformVgaHandle,
|
---|
2921 | 0,
|
---|
2922 | &HandleBuffer,
|
---|
2923 | &HandleCount,
|
---|
2924 | NULL
|
---|
2925 | );
|
---|
2926 |
|
---|
2927 | if (!EFI_ERROR (Status)) {
|
---|
2928 | mVgaHandle = HandleBuffer[0];
|
---|
2929 | if ((!Private->VgaInstalled) && (PciHandle != mVgaHandle)) {
|
---|
2930 | //
|
---|
2931 | // A return status of EFI_NOT_FOUND is considered valid (No EFI
|
---|
2932 | // driver is controlling video.
|
---|
2933 | //
|
---|
2934 | mVgaInstallationInProgress = TRUE;
|
---|
2935 | Status = LegacyBiosInstallVgaRom (Private);
|
---|
2936 | if (EFI_ERROR (Status)) {
|
---|
2937 | if (Status != EFI_NOT_FOUND) {
|
---|
2938 | mVgaInstallationInProgress = FALSE;
|
---|
2939 | return Status;
|
---|
2940 | }
|
---|
2941 | } else {
|
---|
2942 | mVgaInstallationInProgress = FALSE;
|
---|
2943 | }
|
---|
2944 | }
|
---|
2945 | }
|
---|
2946 | //
|
---|
2947 | // See if the option ROM for PciHandle has already been executed
|
---|
2948 | //
|
---|
2949 | Status = IsLegacyRom (PciHandle);
|
---|
2950 |
|
---|
2951 | if (!EFI_ERROR (Status)) {
|
---|
2952 | mVgaInstallationInProgress = FALSE;
|
---|
2953 | GetShadowedRomParameters (
|
---|
2954 | PciHandle,
|
---|
2955 | DiskStart,
|
---|
2956 | DiskEnd,
|
---|
2957 | RomShadowAddress,
|
---|
2958 | (UINTN *) RomShadowedSize
|
---|
2959 | );
|
---|
2960 | return EFI_SUCCESS;
|
---|
2961 | }
|
---|
2962 |
|
---|
2963 | Status = LegacyBiosCheckPciRomEx (
|
---|
2964 | &Private->LegacyBios,
|
---|
2965 | PciHandle,
|
---|
2966 | &LocalRomImage,
|
---|
2967 | &ImageSize,
|
---|
2968 | &RuntimeImageLength,
|
---|
2969 | Flags,
|
---|
2970 | &OpromRevision,
|
---|
2971 | NULL
|
---|
2972 | );
|
---|
2973 | if (EFI_ERROR (Status)) {
|
---|
2974 | //
|
---|
2975 | // There is no PCI ROM in the ROM BAR or no onboard ROM
|
---|
2976 | //
|
---|
2977 | mVgaInstallationInProgress = FALSE;
|
---|
2978 | return EFI_UNSUPPORTED;
|
---|
2979 | }
|
---|
2980 | } else {
|
---|
2981 | if ((RomImage == NULL) || (*RomImage == NULL)) {
|
---|
2982 | //
|
---|
2983 | // If PciHandle is NULL, and no OpRom is to be associated
|
---|
2984 | //
|
---|
2985 | mVgaInstallationInProgress = FALSE;
|
---|
2986 | return EFI_UNSUPPORTED;
|
---|
2987 | }
|
---|
2988 |
|
---|
2989 | Status = Private->LegacyBiosPlatform->GetPlatformHandle (
|
---|
2990 | Private->LegacyBiosPlatform,
|
---|
2991 | EfiGetPlatformVgaHandle,
|
---|
2992 | 0,
|
---|
2993 | &HandleBuffer,
|
---|
2994 | &HandleCount,
|
---|
2995 | NULL
|
---|
2996 | );
|
---|
2997 | if ((!EFI_ERROR (Status)) && (!Private->VgaInstalled)) {
|
---|
2998 | //
|
---|
2999 | // A return status of EFI_NOT_FOUND is considered valid (No EFI
|
---|
3000 | // driver is controlling video.
|
---|
3001 | //
|
---|
3002 | mVgaInstallationInProgress = TRUE;
|
---|
3003 | Status = LegacyBiosInstallVgaRom (Private);
|
---|
3004 | if (EFI_ERROR (Status)) {
|
---|
3005 | if (Status != EFI_NOT_FOUND) {
|
---|
3006 | mVgaInstallationInProgress = FALSE;
|
---|
3007 | return Status;
|
---|
3008 | }
|
---|
3009 | } else {
|
---|
3010 | mVgaInstallationInProgress = FALSE;
|
---|
3011 | }
|
---|
3012 | }
|
---|
3013 |
|
---|
3014 | LocalRomImage = *RomImage;
|
---|
3015 | if (((PCI_EXPANSION_ROM_HEADER *) LocalRomImage)->Signature != PCI_EXPANSION_ROM_HEADER_SIGNATURE ||
|
---|
3016 | ((PCI_EXPANSION_ROM_HEADER *) LocalRomImage)->PcirOffset == 0 ||
|
---|
3017 | (((PCI_EXPANSION_ROM_HEADER *) LocalRomImage)->PcirOffset & 3 ) != 0) {
|
---|
3018 | mVgaInstallationInProgress = FALSE;
|
---|
3019 | return EFI_UNSUPPORTED;
|
---|
3020 | }
|
---|
3021 |
|
---|
3022 | Pcir = (PCI_3_0_DATA_STRUCTURE *)
|
---|
3023 | ((UINT8 *) LocalRomImage + ((PCI_EXPANSION_ROM_HEADER *) LocalRomImage)->PcirOffset);
|
---|
3024 |
|
---|
3025 | if ((Pcir->Signature != PCI_DATA_STRUCTURE_SIGNATURE) || (Pcir->CodeType != PCI_CODE_TYPE_PCAT_IMAGE)) {
|
---|
3026 | mVgaInstallationInProgress = FALSE;
|
---|
3027 | return EFI_UNSUPPORTED;
|
---|
3028 | }
|
---|
3029 |
|
---|
3030 | ImageSize = Pcir->ImageLength * 512;
|
---|
3031 | if (Pcir->Length >= 0x1C) {
|
---|
3032 | OpromRevision = Pcir->Revision;
|
---|
3033 | } else {
|
---|
3034 | OpromRevision = 0;
|
---|
3035 | }
|
---|
3036 | if (Pcir->Revision < 3) {
|
---|
3037 | RuntimeImageLength = 0;
|
---|
3038 | } else {
|
---|
3039 | RuntimeImageLength = Pcir->MaxRuntimeImageLength * 512;
|
---|
3040 | }
|
---|
3041 | }
|
---|
3042 |
|
---|
3043 | //
|
---|
3044 | // Grant access for below 1M
|
---|
3045 | // BDA/EBDA/LowPMM and scratch memory for OPROM.
|
---|
3046 | //
|
---|
3047 | IoMmuGrantAccess (PciHandle, 0, SIZE_1MB);
|
---|
3048 | //
|
---|
3049 | // Grant access for HiPmm
|
---|
3050 | //
|
---|
3051 | IoMmuGrantAccess (
|
---|
3052 | PciHandle,
|
---|
3053 | Private->IntThunk->EfiToLegacy16InitTable.HiPmmMemory,
|
---|
3054 | Private->IntThunk->EfiToLegacy16InitTable.HiPmmMemorySizeInBytes
|
---|
3055 | );
|
---|
3056 |
|
---|
3057 | //
|
---|
3058 | // Shadow and initialize the OpROM.
|
---|
3059 | //
|
---|
3060 | ASSERT (Private->TraceIndex < 0x200);
|
---|
3061 | Private->Trace[Private->TraceIndex] = LEGACY_PCI_TRACE_000;
|
---|
3062 | Private->TraceIndex ++;
|
---|
3063 | Private->TraceIndex = (UINT16) (Private->TraceIndex % 0x200);
|
---|
3064 | Status = LegacyBiosInstallRom (
|
---|
3065 | This,
|
---|
3066 | Private,
|
---|
3067 | PciHandle,
|
---|
3068 | OpromRevision,
|
---|
3069 | LocalRomImage,
|
---|
3070 | ImageSize,
|
---|
3071 | &RuntimeImageLength,
|
---|
3072 | DiskStart,
|
---|
3073 | DiskEnd,
|
---|
3074 | RomShadowAddress
|
---|
3075 | );
|
---|
3076 | if (RomShadowedSize != NULL) {
|
---|
3077 | *RomShadowedSize = (UINT32) RuntimeImageLength;
|
---|
3078 | }
|
---|
3079 |
|
---|
3080 | mVgaInstallationInProgress = FALSE;
|
---|
3081 | return Status;
|
---|
3082 | }
|
---|
3083 |
|
---|