]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/PcatSingleSegmentPciCfg2Pei/PciCfg2.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / MdeModulePkg / Universal / PcatSingleSegmentPciCfg2Pei / PciCfg2.c
CommitLineData
fb0b259e 1/** @file\r
d1102dba
LG
2 This driver installs Single Segment Pci Configuration 2 PPI\r
3 to provide read, write and modify access to Pci configuration space in PEI phase.\r
109e9a61 4 To follow PI specification, these services also support access to the unaligned Pci address.\r
12232778 5\r
d1102dba 6 Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>\r
9d510e61 7 SPDX-License-Identifier: BSD-2-Clause-Patent\r
12232778 8\r
9**/\r
10\r
11#include <PiPei.h>\r
12232778 12#include <Ppi/PciCfg2.h>\r
12232778 13#include <Library/BaseLib.h>\r
14#include <Library/DebugLib.h>\r
15#include <Library/PciLib.h>\r
16#include <Library/PeimEntryPoint.h>\r
77dfa7c7 17#include <Library/PeiServicesLib.h>\r
2d85ada2 18#include <IndustryStandard/Pci.h>\r
12232778 19\r
aa79b0b3 20/**\r
21 Convert EFI_PEI_PCI_CFG_PPI_PCI_ADDRESS to PCI_LIB_ADDRESS.\r
22\r
109e9a61 23 @param Address PCI address with EFI_PEI_PCI_CFG_PPI_PCI_ADDRESS format.\r
aa79b0b3 24\r
109e9a61 25 @return PCI address with PCI_LIB_ADDRESS format.\r
aa79b0b3 26\r
27**/\r
28UINTN\r
29PciCfgAddressConvert (\r
1436aea4 30 EFI_PEI_PCI_CFG_PPI_PCI_ADDRESS *Address\r
aa79b0b3 31 )\r
32{\r
33 if (Address->ExtendedRegister == 0) {\r
34 return PCI_LIB_ADDRESS (Address->Bus, Address->Device, Address->Function, Address->Register);\r
35 }\r
36\r
37 return PCI_LIB_ADDRESS (Address->Bus, Address->Device, Address->Function, Address->ExtendedRegister);\r
38}\r
39\r
12232778 40/**\r
41 Reads from a given location in the PCI configuration space.\r
42\r
43 @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation.\r
12232778 44 @param This Pointer to local data for the interface.\r
12232778 45 @param Width The width of the access. Enumerated in bytes.\r
46 See EFI_PEI_PCI_CFG_PPI_WIDTH above.\r
12232778 47 @param Address The physical address of the access. The format of\r
48 the address is described by EFI_PEI_PCI_CFG_PPI_PCI_ADDRESS.\r
109e9a61 49 @param Buffer A pointer to the buffer of data.\r
12232778 50\r
51 @retval EFI_SUCCESS The function completed successfully.\r
109e9a61 52 @retval EFI_INVALID_PARAMETER The invalid access width.\r
d1102dba 53\r
12232778 54**/\r
55EFI_STATUS\r
fb0b259e 56EFIAPI\r
12232778 57PciCfg2Read (\r
1436aea4
MK
58 IN CONST EFI_PEI_SERVICES **PeiServices,\r
59 IN CONST EFI_PEI_PCI_CFG2_PPI *This,\r
60 IN EFI_PEI_PCI_CFG_PPI_WIDTH Width,\r
61 IN UINT64 Address,\r
62 IN OUT VOID *Buffer\r
cebc8d48 63 )\r
12232778 64{\r
65 UINTN PciLibAddress;\r
66\r
1436aea4 67 PciLibAddress = PciCfgAddressConvert ((EFI_PEI_PCI_CFG_PPI_PCI_ADDRESS *)&Address);\r
12232778 68\r
69 if (Width == EfiPeiPciCfgWidthUint8) {\r
1436aea4 70 *((UINT8 *)Buffer) = PciRead8 (PciLibAddress);\r
12232778 71 } else if (Width == EfiPeiPciCfgWidthUint16) {\r
8501ba4c
LG
72 if ((PciLibAddress & 0x01) == 0) {\r
73 //\r
74 // Aligned Pci address access\r
75 //\r
1436aea4 76 WriteUnaligned16 (((UINT16 *)Buffer), PciRead16 (PciLibAddress));\r
8501ba4c
LG
77 } else {\r
78 //\r
79 // Unaligned Pci address access, break up the request into byte by byte.\r
80 //\r
1436aea4
MK
81 *((UINT8 *)Buffer) = PciRead8 (PciLibAddress);\r
82 *((UINT8 *)Buffer + 1) = PciRead8 (PciLibAddress + 1);\r
8501ba4c 83 }\r
12232778 84 } else if (Width == EfiPeiPciCfgWidthUint32) {\r
8501ba4c
LG
85 if ((PciLibAddress & 0x03) == 0) {\r
86 //\r
87 // Aligned Pci address access\r
88 //\r
1436aea4 89 WriteUnaligned32 (((UINT32 *)Buffer), PciRead32 (PciLibAddress));\r
8501ba4c
LG
90 } else if ((PciLibAddress & 0x01) == 0) {\r
91 //\r
92 // Unaligned Pci address access, break up the request into word by word.\r
93 //\r
1436aea4
MK
94 WriteUnaligned16 (((UINT16 *)Buffer), PciRead16 (PciLibAddress));\r
95 WriteUnaligned16 (((UINT16 *)Buffer + 1), PciRead16 (PciLibAddress + 2));\r
8501ba4c
LG
96 } else {\r
97 //\r
98 // Unaligned Pci address access, break up the request into byte by byte.\r
99 //\r
1436aea4
MK
100 *((UINT8 *)Buffer) = PciRead8 (PciLibAddress);\r
101 *((UINT8 *)Buffer + 1) = PciRead8 (PciLibAddress + 1);\r
102 *((UINT8 *)Buffer + 2) = PciRead8 (PciLibAddress + 2);\r
103 *((UINT8 *)Buffer + 3) = PciRead8 (PciLibAddress + 3);\r
8501ba4c 104 }\r
12232778 105 } else {\r
106 return EFI_INVALID_PARAMETER;\r
107 }\r
108\r
109 return EFI_SUCCESS;\r
110}\r
111\r
112/**\r
113 Write to a given location in the PCI configuration space.\r
114\r
115 @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation.\r
12232778 116 @param This Pointer to local data for the interface.\r
12232778 117 @param Width The width of the access. Enumerated in bytes.\r
118 See EFI_PEI_PCI_CFG_PPI_WIDTH above.\r
12232778 119 @param Address The physical address of the access. The format of\r
120 the address is described by EFI_PEI_PCI_CFG_PPI_PCI_ADDRESS.\r
109e9a61 121 @param Buffer A pointer to the buffer of data.\r
12232778 122\r
123 @retval EFI_SUCCESS The function completed successfully.\r
109e9a61 124 @retval EFI_INVALID_PARAMETER The invalid access width.\r
12232778 125\r
126**/\r
127EFI_STATUS\r
fb0b259e 128EFIAPI\r
12232778 129PciCfg2Write (\r
1436aea4
MK
130 IN CONST EFI_PEI_SERVICES **PeiServices,\r
131 IN CONST EFI_PEI_PCI_CFG2_PPI *This,\r
132 IN EFI_PEI_PCI_CFG_PPI_WIDTH Width,\r
133 IN UINT64 Address,\r
134 IN OUT VOID *Buffer\r
cebc8d48 135 )\r
12232778 136{\r
137 UINTN PciLibAddress;\r
138\r
1436aea4 139 PciLibAddress = PciCfgAddressConvert ((EFI_PEI_PCI_CFG_PPI_PCI_ADDRESS *)&Address);\r
12232778 140\r
141 if (Width == EfiPeiPciCfgWidthUint8) {\r
1436aea4 142 PciWrite8 (PciLibAddress, *((UINT8 *)Buffer));\r
12232778 143 } else if (Width == EfiPeiPciCfgWidthUint16) {\r
8501ba4c
LG
144 if ((PciLibAddress & 0x01) == 0) {\r
145 //\r
146 // Aligned Pci address access\r
147 //\r
1436aea4 148 PciWrite16 (PciLibAddress, ReadUnaligned16 ((UINT16 *)Buffer));\r
8501ba4c
LG
149 } else {\r
150 //\r
151 // Unaligned Pci address access, break up the request into byte by byte.\r
152 //\r
1436aea4
MK
153 PciWrite8 (PciLibAddress, *((UINT8 *)Buffer));\r
154 PciWrite8 (PciLibAddress + 1, *((UINT8 *)Buffer + 1));\r
8501ba4c 155 }\r
12232778 156 } else if (Width == EfiPeiPciCfgWidthUint32) {\r
8501ba4c
LG
157 if ((PciLibAddress & 0x03) == 0) {\r
158 //\r
159 // Aligned Pci address access\r
160 //\r
1436aea4 161 PciWrite32 (PciLibAddress, ReadUnaligned32 ((UINT32 *)Buffer));\r
8501ba4c
LG
162 } else if ((PciLibAddress & 0x01) == 0) {\r
163 //\r
164 // Unaligned Pci address access, break up the request into word by word.\r
165 //\r
1436aea4
MK
166 PciWrite16 (PciLibAddress, ReadUnaligned16 ((UINT16 *)Buffer));\r
167 PciWrite16 (PciLibAddress + 2, ReadUnaligned16 ((UINT16 *)Buffer + 1));\r
8501ba4c
LG
168 } else {\r
169 //\r
170 // Unaligned Pci address access, break up the request into byte by byte.\r
171 //\r
1436aea4
MK
172 PciWrite8 (PciLibAddress, *((UINT8 *)Buffer));\r
173 PciWrite8 (PciLibAddress + 1, *((UINT8 *)Buffer + 1));\r
174 PciWrite8 (PciLibAddress + 2, *((UINT8 *)Buffer + 2));\r
175 PciWrite8 (PciLibAddress + 3, *((UINT8 *)Buffer + 3));\r
8501ba4c 176 }\r
12232778 177 } else {\r
178 return EFI_INVALID_PARAMETER;\r
179 }\r
180\r
181 return EFI_SUCCESS;\r
182}\r
183\r
12232778 184/**\r
109e9a61
LG
185 This function performs a read-modify-write operation on the contents from a given\r
186 location in the PCI configuration space.\r
12232778 187\r
188 @param PeiServices An indirect pointer to the PEI Services Table\r
189 published by the PEI Foundation.\r
12232778 190 @param This Pointer to local data for the interface.\r
12232778 191 @param Width The width of the access. Enumerated in bytes. Type\r
192 EFI_PEI_PCI_CFG_PPI_WIDTH is defined in Read().\r
12232778 193 @param Address The physical address of the access.\r
12232778 194 @param SetBits Points to value to bitwise-OR with the read configuration value.\r
12232778 195 The size of the value is determined by Width.\r
12232778 196 @param ClearBits Points to the value to negate and bitwise-AND with the read configuration value.\r
197 The size of the value is determined by Width.\r
198\r
12232778 199 @retval EFI_SUCCESS The function completed successfully.\r
109e9a61 200 @retval EFI_INVALID_PARAMETER The invalid access width.\r
12232778 201\r
202**/\r
203EFI_STATUS\r
fb0b259e 204EFIAPI\r
12232778 205PciCfg2Modify (\r
1436aea4
MK
206 IN CONST EFI_PEI_SERVICES **PeiServices,\r
207 IN CONST EFI_PEI_PCI_CFG2_PPI *This,\r
208 IN EFI_PEI_PCI_CFG_PPI_WIDTH Width,\r
209 IN UINT64 Address,\r
210 IN VOID *SetBits,\r
211 IN VOID *ClearBits\r
cebc8d48 212 )\r
12232778 213{\r
702887db 214 UINTN PciLibAddress;\r
215 UINT16 ClearValue16;\r
216 UINT16 SetValue16;\r
217 UINT32 ClearValue32;\r
218 UINT32 SetValue32;\r
12232778 219\r
1436aea4 220 PciLibAddress = PciCfgAddressConvert ((EFI_PEI_PCI_CFG_PPI_PCI_ADDRESS *)&Address);\r
12232778 221\r
222 if (Width == EfiPeiPciCfgWidthUint8) {\r
1436aea4 223 PciAndThenOr8 (PciLibAddress, (UINT8)(~(*(UINT8 *)ClearBits)), *((UINT8 *)SetBits));\r
12232778 224 } else if (Width == EfiPeiPciCfgWidthUint16) {\r
8501ba4c
LG
225 if ((PciLibAddress & 0x01) == 0) {\r
226 //\r
227 // Aligned Pci address access\r
228 //\r
1436aea4
MK
229 ClearValue16 = (UINT16)(~ReadUnaligned16 ((UINT16 *)ClearBits));\r
230 SetValue16 = ReadUnaligned16 ((UINT16 *)SetBits);\r
8501ba4c
LG
231 PciAndThenOr16 (PciLibAddress, ClearValue16, SetValue16);\r
232 } else {\r
233 //\r
234 // Unaligned Pci address access, break up the request into byte by byte.\r
235 //\r
1436aea4
MK
236 PciAndThenOr8 (PciLibAddress, (UINT8)(~(*(UINT8 *)ClearBits)), *((UINT8 *)SetBits));\r
237 PciAndThenOr8 (PciLibAddress + 1, (UINT8)(~(*((UINT8 *)ClearBits + 1))), *((UINT8 *)SetBits + 1));\r
8501ba4c 238 }\r
12232778 239 } else if (Width == EfiPeiPciCfgWidthUint32) {\r
8501ba4c
LG
240 if ((PciLibAddress & 0x03) == 0) {\r
241 //\r
242 // Aligned Pci address access\r
243 //\r
1436aea4
MK
244 ClearValue32 = (UINT32)(~ReadUnaligned32 ((UINT32 *)ClearBits));\r
245 SetValue32 = ReadUnaligned32 ((UINT32 *)SetBits);\r
8501ba4c
LG
246 PciAndThenOr32 (PciLibAddress, ClearValue32, SetValue32);\r
247 } else if ((PciLibAddress & 0x01) == 0) {\r
248 //\r
249 // Unaligned Pci address access, break up the request into word by word.\r
250 //\r
1436aea4
MK
251 ClearValue16 = (UINT16)(~ReadUnaligned16 ((UINT16 *)ClearBits));\r
252 SetValue16 = ReadUnaligned16 ((UINT16 *)SetBits);\r
8501ba4c
LG
253 PciAndThenOr16 (PciLibAddress, ClearValue16, SetValue16);\r
254\r
1436aea4
MK
255 ClearValue16 = (UINT16)(~ReadUnaligned16 ((UINT16 *)ClearBits + 1));\r
256 SetValue16 = ReadUnaligned16 ((UINT16 *)SetBits + 1);\r
8501ba4c
LG
257 PciAndThenOr16 (PciLibAddress + 2, ClearValue16, SetValue16);\r
258 } else {\r
259 //\r
260 // Unaligned Pci address access, break up the request into byte by byte.\r
261 //\r
1436aea4
MK
262 PciAndThenOr8 (PciLibAddress, (UINT8)(~(*(UINT8 *)ClearBits)), *((UINT8 *)SetBits));\r
263 PciAndThenOr8 (PciLibAddress + 1, (UINT8)(~(*((UINT8 *)ClearBits + 1))), *((UINT8 *)SetBits + 1));\r
264 PciAndThenOr8 (PciLibAddress + 2, (UINT8)(~(*((UINT8 *)ClearBits + 2))), *((UINT8 *)SetBits + 2));\r
265 PciAndThenOr8 (PciLibAddress + 3, (UINT8)(~(*((UINT8 *)ClearBits + 3))), *((UINT8 *)SetBits + 3));\r
8501ba4c 266 }\r
12232778 267 } else {\r
268 return EFI_INVALID_PARAMETER;\r
269 }\r
109e9a61 270\r
12232778 271 return EFI_SUCCESS;\r
272}\r
273\r
1436aea4 274EFI_PEI_PCI_CFG2_PPI gPciCfg2Ppi = {\r
109e9a61
LG
275 PciCfg2Read,\r
276 PciCfg2Write,\r
277 PciCfg2Modify,\r
278 0\r
279};\r
280\r
1436aea4 281EFI_PEI_PPI_DESCRIPTOR gPciCfg2PpiList = {\r
109e9a61
LG
282 (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),\r
283 &gEfiPciCfg2PpiGuid,\r
284 &gPciCfg2Ppi\r
285};\r
286\r
cebc8d48 287/**\r
d1102dba 288 Module's entry function.\r
cebc8d48 289 This routine will install EFI_PEI_PCI_CFG2_PPI.\r
d1102dba 290\r
cebc8d48
LG
291 @param FileHandle Handle of the file being invoked.\r
292 @param PeiServices Describes the list of possible PEI Services.\r
12232778 293\r
cebc8d48
LG
294 @return Whether success to install service.\r
295**/\r
12232778 296EFI_STATUS\r
297EFIAPI\r
298PeimInitializePciCfg (\r
8bd22b8a
LG
299 IN EFI_PEI_FILE_HANDLE FileHandle,\r
300 IN CONST EFI_PEI_SERVICES **PeiServices\r
12232778 301 )\r
302{\r
1436aea4 303 EFI_STATUS Status;\r
12232778 304\r
8bd22b8a 305 (**(EFI_PEI_SERVICES **)PeiServices).PciCfg = &gPciCfg2Ppi;\r
1436aea4 306 Status = PeiServicesInstallPpi (&gPciCfg2PpiList);\r
77dfa7c7 307 ASSERT_EFI_ERROR (Status);\r
12232778 308\r
309 return Status;\r
310}\r