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