VirtualBox

source: vbox/trunk/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/PcatSingleSegmentPciCfg2Pei/PciCfg2.c

Last change on this file was 99404, checked in by vboxsync, 21 months ago

Devices/EFI/FirmwareNew: Update to edk2-stable202302 and make it build, bugref:4643

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

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette