1 /** @file
2
3 Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.<BR>
4
5
6 This program and the accompanying materials are licensed and made available under
7
8 the terms and conditions of the BSD License that accompanies this distribution.
9
10 The full text of the license may be found at
11
12 http://opensource.org/licenses/bsd-license.php.
13
14
15
16 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
17
18 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
19
20
21
22
23 Module Name:
24
25
26 PciPlatform.c
27
28 Abstract:
29 --*/
30
31
32 #include "PciPlatform.h"
33 #include "PchRegs.h"
34 #include "PchAccess.h"
35 #include "VlvCommonDefinitions.h"
36 #include "PlatformBootMode.h"
37
38 #include <Library/BaseLib.h>
39 #include <Library/BaseMemoryLib.h>
40 #include <Protocol/CpuIo.h>
41 #include <Protocol/PciIo.h>
42 #include <Guid/SetupVariable.h>
43 #include <Protocol/PciRootBridgeIo.h>
44 #include "SetupMode.h"
45 #include <Library/UefiBootServicesTableLib.h>
46 #include <Library/UefiRuntimeServicesTableLib.h>
47 #include <Library/DebugLib.h>
48 #include <Protocol/FirmwareVolume.h>
49 #include <Library/HobLib.h>
50 #include <IndustryStandard/Pci22.h>
51
52 extern PCI_OPTION_ROM_TABLE mPciOptionRomTable[];
53 extern UINTN mSizeOptionRomTable;
54
55 EFI_PCI_PLATFORM_PROTOCOL mPciPlatform = {
56 PhaseNotify,
57 PlatformPrepController,
58 GetPlatformPolicy,
GetRawImage(IN EFI_GUID * NameGuid,IN OUT VOID ** Buffer,IN OUT UINTN * Size)59 GetPciRom
60 };
61
62 EFI_HANDLE mPciPlatformHandle = NULL;
63
64
65 SYSTEM_CONFIGURATION mSystemConfiguration;
66
67 EFI_STATUS
68 GetRawImage (
69 IN EFI_GUID *NameGuid,
70 IN OUT VOID **Buffer,
71 IN OUT UINTN *Size
72 )
73 {
74 EFI_STATUS Status;
75 EFI_HANDLE *HandleBuffer;
76 UINTN HandleCount;
77 UINTN Index;
78 EFI_FIRMWARE_VOLUME_PROTOCOL *Fv;
79 UINT32 AuthenticationStatus;
80
81 Status = gBS->LocateHandleBuffer (
82 ByProtocol,
83 &gEfiFirmwareVolumeProtocolGuid,
84 NULL,
85 &HandleCount,
86 &HandleBuffer
87 );
88 if (EFI_ERROR (Status) || HandleCount == 0) {
89 return EFI_NOT_FOUND;
90 }
91
92 //
93 // Find desired image in all Fvs
94 //
95 for (Index = 0; Index < HandleCount; Index++) {
96 Status = gBS->HandleProtocol(
97 HandleBuffer[Index],
98 &gEfiFirmwareVolumeProtocolGuid,
99 (VOID **) &Fv
100 );
101
102 if ( EFI_ERROR ( Status ) ) {
103 return EFI_LOAD_ERROR;
104 }
105
106 //
107 // Try a raw file
108 //
109 *Buffer = NULL;
110 *Size = 0;
111 Status = Fv->ReadSection (
112 Fv,
113 NameGuid,
114 EFI_SECTION_RAW,
115 0,
116 Buffer,
117 Size,
118 &AuthenticationStatus
119 );
120
121 if ( !EFI_ERROR ( Status )) {
122 break;
123 }
124 }
125
PhaseNotify(IN EFI_PCI_PLATFORM_PROTOCOL * This,IN EFI_HANDLE HostBridge,IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE Phase,IN EFI_PCI_CHIPSET_EXECUTION_PHASE ChipsetPhase)126 if ( Index >= HandleCount ) {
127 return EFI_NOT_FOUND;
128 }
129
130 return EFI_SUCCESS;
131 }
132
133 EFI_STATUS
134 EFIAPI
135 PhaseNotify (
136 IN EFI_PCI_PLATFORM_PROTOCOL *This,
137 IN EFI_HANDLE HostBridge,
138 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE Phase,
PlatformPrepController(IN EFI_PCI_PLATFORM_PROTOCOL * This,IN EFI_HANDLE HostBridge,IN EFI_HANDLE RootBridge,IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS PciAddress,IN EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE Phase,IN EFI_PCI_CHIPSET_EXECUTION_PHASE ChipsetPhase)139 IN EFI_PCI_CHIPSET_EXECUTION_PHASE ChipsetPhase
140 )
141 {
142 return EFI_UNSUPPORTED;
143 }
144
145
146 EFI_STATUS
147 EFIAPI
148 PlatformPrepController (
149 IN EFI_PCI_PLATFORM_PROTOCOL *This,
150 IN EFI_HANDLE HostBridge,
151 IN EFI_HANDLE RootBridge,
152 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS PciAddress,
GetPlatformPolicy(IN CONST EFI_PCI_PLATFORM_PROTOCOL * This,OUT EFI_PCI_PLATFORM_POLICY * PciPolicy)153 IN EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE Phase,
154 IN EFI_PCI_CHIPSET_EXECUTION_PHASE ChipsetPhase
155 )
156 {
157 return EFI_UNSUPPORTED;
158 }
159
160 EFI_STATUS
161 EFIAPI
162 GetPlatformPolicy (
163 IN CONST EFI_PCI_PLATFORM_PROTOCOL *This,
164 OUT EFI_PCI_PLATFORM_POLICY *PciPolicy
165 )
166 {
167 *PciPolicy = EFI_RESERVE_VGA_IO_ALIAS;
168 return EFI_SUCCESS;
169 }
170
171 /**
172 GetPciRom from platform specific location for specific PCI device
173
174 @param This Protocol instance
175 @param PciHandle Identify the specific PCI devic
176 @param RomImage Returns the ROM Image memory location
GetPciRom(IN CONST EFI_PCI_PLATFORM_PROTOCOL * This,IN EFI_HANDLE PciHandle,OUT VOID ** RomImage,OUT UINTN * RomSize)177 @param RomSize Returns Rom Image size
178
179 @retval EFI_SUCCESS
180 @retval EFI_NOT_FOUND
181 @retval EFI_OUT_OF_RESOURCES
182
183 **/
184 EFI_STATUS
185 EFIAPI
186 GetPciRom (
187 IN CONST EFI_PCI_PLATFORM_PROTOCOL *This,
188 IN EFI_HANDLE PciHandle,
189 OUT VOID **RomImage,
190 OUT UINTN *RomSize
191 )
192 {
193 EFI_STATUS Status;
194 EFI_PCI_IO_PROTOCOL *PciIo;
195 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
196 UINTN Segment;
197 UINTN Bus;
198 UINTN Device;
199 UINTN Function;
200 UINT16 VendorId;
201 UINT16 DeviceId;
202 UINT16 DeviceClass;
203 UINTN TableIndex;
204 UINT8 Data8;
205 BOOLEAN MfgMode;
206 EFI_PLATFORM_SETUP_ID *BootModeBuffer;
207
208 EFI_PEI_HOB_POINTERS GuidHob;
209
210 MfgMode = FALSE;
211
212 //
213 // Check if system is in manufacturing mode.
214 //
215 GuidHob.Raw = GetHobList ();
216 if (GuidHob.Raw == NULL) {
217 return EFI_NOT_FOUND;
218 }
219
220 if ((GuidHob.Raw = GetNextGuidHob (&gEfiPlatformBootModeGuid, GuidHob.Raw)) != NULL) {
221 BootModeBuffer = GET_GUID_HOB_DATA (GuidHob.Guid);
222 if (!CompareMem (&BootModeBuffer->SetupName, MANUFACTURE_SETUP_NAME,
223 StrSize (MANUFACTURE_SETUP_NAME)))
224 {
225 //
226 // System is in manufacturing mode.
227 //
228 MfgMode = TRUE;
229 }
230 }
231
232 Status = gBS->HandleProtocol (
233 PciHandle,
234 &gEfiPciIoProtocolGuid,
235 (void **)&PciIo
236 );
237 if (EFI_ERROR (Status)) {
238 return EFI_NOT_FOUND;
239 }
240
241 Status = gBS->LocateProtocol (
242 &gEfiPciRootBridgeIoProtocolGuid,
243 NULL,
244 (void **)&PciRootBridgeIo
245 );
246
247 if (EFI_ERROR (Status)) {
248 return EFI_NOT_FOUND;
249 }
250
251 PciIo->Pci.Read (PciIo, EfiPciIoWidthUint16, 0x0A, 1, &DeviceClass);
252
253 PciIo->GetLocation (PciIo, &Segment, &Bus, &Device, &Function);
254
255 PciIo->Pci.Read (PciIo, EfiPciIoWidthUint16, 0, 1, &VendorId);
256
257 PciIo->Pci.Read (PciIo, EfiPciIoWidthUint16, 2, 1, &DeviceId);
258
259 //
260 // WA for PCIe SATA card (SYBA SY-PEX400-40)
261 //
262 if ((VendorId == 0x1B21) && (DeviceId == 0x0612)) {
263 Data8 = 0x07;
264 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 4, 1, &Data8);
265 }
266
267 //
268 // Do not run RAID or AHCI Option ROM if IDE
269 //
270 if ( (DeviceClass == ((PCI_CLASS_MASS_STORAGE << 8 ) | PCI_CLASS_MASS_STORAGE_IDE)) ) {
271 return EFI_NOT_FOUND;
272 }
273
274 //
275 // Run PXE ROM only if Boot network is enabled and not in MFG mode
276 //
277 if (DeviceClass == ((PCI_CLASS_NETWORK << 8 ) | PCI_CLASS_NETWORK_ETHERNET)) {
278 if (((mSystemConfiguration.BootNetwork == 0) && (MfgMode == FALSE )) || (mSystemConfiguration.FastBoot == 1)) {
279 return EFI_NOT_FOUND;
280 }
281 }
282
283 //
284 // Loop through table of Onboard option rom descriptions
285 //
286 for (TableIndex = 0; mPciOptionRomTable[TableIndex].VendorId != 0xffff; TableIndex++) {
287
288 //
289 // See if the PCI device specified by PciHandle matches at device in mPciOptionRomTable
290 //
291 if (VendorId != mPciOptionRomTable[TableIndex].VendorId ||
292 DeviceId != mPciOptionRomTable[TableIndex].DeviceId ||
293 ((DeviceClass == ((PCI_CLASS_NETWORK << 8 ) | PCI_CLASS_NETWORK_ETHERNET)) &&
294 (mPciOptionRomTable[TableIndex].Flag != mSystemConfiguration.BootNetwork)) ) {
295 continue;
296 }
297
298 Status = GetRawImage(
299 &mPciOptionRomTable[TableIndex].FileName,
300 RomImage,
301 RomSize
302 );
303
304 if ((VendorId == IGD_VID) && (DeviceId == IGD_DID_VLV_A0)) {
305 *(UINT16 *)(((UINTN) *RomImage) + OPROM_DID_OFFSET) = IGD_DID_VLV_A0;
306 }
307
308 if ((VendorId == IGD_VID) && (DeviceId == IGD_DID_II)) {
309 *(UINT16 *)(((UINTN) *RomImage) + OPROM_DID_OFFSET) = IGD_DID_II;
310 }
311
312 if ((VendorId == IGD_VID) && (DeviceId == IGD_DID_0BE4)) {
313 *(UINT16 *)(((UINTN) *RomImage) + OPROM_DID_OFFSET) = IGD_DID_0BE4;
314 }
315
316 if ((VendorId == IGD_VID) && (DeviceId == IGD_DID_QS)) {
317 *(UINT16 *)(((UINTN) *RomImage) + OPROM_DID_OFFSET) = IGD_DID_QS;
318 }
319
320
321 if (EFI_ERROR (Status)) {
322 continue;
323 }
324 return EFI_SUCCESS;
325 }
326
327 return EFI_NOT_FOUND;
328 }
329
PciPlatformDriverEntry(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)330 /**
331
332 @param (Standard EFI Image entry - EFI_IMAGE_ENTRY_POINT)
333
334 @retval EFI_STATUS
335
336 **/
337 EFI_STATUS
338 EFIAPI
339 PciPlatformDriverEntry (
340 IN EFI_HANDLE ImageHandle,
341 IN EFI_SYSTEM_TABLE *SystemTable
342 )
343 {
344 EFI_STATUS Status;
345 UINTN VarSize;
346
347 VarSize = sizeof(SYSTEM_CONFIGURATION);
348 Status = gRT->GetVariable(
349 L"Setup",
350 &gEfiNormalSetupGuid,
351 NULL,
352 &VarSize,
353 &mSystemConfiguration
354 );
355 if (EFI_ERROR (Status) || VarSize != sizeof(SYSTEM_CONFIGURATION)) {
356 //The setup variable is corrupted
357 VarSize = sizeof(SYSTEM_CONFIGURATION);
358 Status = gRT->GetVariable(
359 L"SetupRecovery",
360 &gEfiNormalSetupGuid,
361 NULL,
362 &VarSize,
363 &mSystemConfiguration
364 );
365 ASSERT_EFI_ERROR (Status);
366 }
367
368 //
369 // Install on a new handle
370 //
371 Status = gBS->InstallProtocolInterface (
372 &mPciPlatformHandle,
373 &gEfiPciPlatformProtocolGuid,
374 EFI_NATIVE_INTERFACE,
375 &mPciPlatform
376 );
377
378 return Status;
379 }
380
381
382