]> git.proxmox.com Git - mirror_edk2.git/blame - UefiCpuPkg/CpuIo2Dxe/CpuIo2Dxe.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / UefiCpuPkg / CpuIo2Dxe / CpuIo2Dxe.c
CommitLineData
3ca55ed4 1/** @file\r
2 Produces the CPU I/O 2 Protocol.\r
3\r
7367cc6c 4Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>\r
200b4223
LD
5Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR>\r
6\r
0acd8697 7SPDX-License-Identifier: BSD-2-Clause-Patent\r
3ca55ed4 8\r
9**/\r
10\r
430fbbe0 11#include "CpuIo2Dxe.h"\r
3ea1d3e6 12\r
13//\r
14// Handle for the CPU I/O 2 Protocol\r
15//\r
16EFI_HANDLE mHandle = NULL;\r
17\r
18//\r
19// CPU I/O 2 Protocol instance\r
20//\r
053e878b 21EFI_CPU_IO2_PROTOCOL mCpuIo2 = {\r
3ca55ed4 22 {\r
23 CpuMemoryServiceRead,\r
24 CpuMemoryServiceWrite\r
25 },\r
26 {\r
27 CpuIoServiceRead,\r
28 CpuIoServiceWrite\r
29 }\r
30};\r
31\r
3ea1d3e6 32//\r
33// Lookup table for increment values based on transfer widths\r
34//\r
053e878b 35UINT8 mInStride[] = {\r
3ea1d3e6 36 1, // EfiCpuIoWidthUint8\r
37 2, // EfiCpuIoWidthUint16\r
38 4, // EfiCpuIoWidthUint32\r
39 8, // EfiCpuIoWidthUint64\r
40 0, // EfiCpuIoWidthFifoUint8\r
41 0, // EfiCpuIoWidthFifoUint16\r
42 0, // EfiCpuIoWidthFifoUint32\r
43 0, // EfiCpuIoWidthFifoUint64\r
44 1, // EfiCpuIoWidthFillUint8\r
45 2, // EfiCpuIoWidthFillUint16\r
46 4, // EfiCpuIoWidthFillUint32\r
47 8 // EfiCpuIoWidthFillUint64\r
48};\r
3ca55ed4 49\r
3ea1d3e6 50//\r
51// Lookup table for increment values based on transfer widths\r
52//\r
053e878b 53UINT8 mOutStride[] = {\r
3ea1d3e6 54 1, // EfiCpuIoWidthUint8\r
55 2, // EfiCpuIoWidthUint16\r
56 4, // EfiCpuIoWidthUint32\r
57 8, // EfiCpuIoWidthUint64\r
58 1, // EfiCpuIoWidthFifoUint8\r
59 2, // EfiCpuIoWidthFifoUint16\r
60 4, // EfiCpuIoWidthFifoUint32\r
61 8, // EfiCpuIoWidthFifoUint64\r
62 0, // EfiCpuIoWidthFillUint8\r
63 0, // EfiCpuIoWidthFillUint16\r
64 0, // EfiCpuIoWidthFillUint32\r
65 0 // EfiCpuIoWidthFillUint64\r
66};\r
3ca55ed4 67\r
3ea1d3e6 68/**\r
69 Check parameters to a CPU I/O 2 Protocol service request.\r
3ca55ed4 70\r
7367cc6c
LG
71 The I/O operations are carried out exactly as requested. The caller is responsible\r
72 for satisfying any alignment and I/O width restrictions that a PI System on a\r
73 platform might require. For example on some platforms, width requests of\r
74 EfiCpuIoWidthUint64 do not work. Misaligned buffers, on the other hand, will\r
3ea1d3e6 75 be handled by the driver.\r
7367cc6c 76\r
3ea1d3e6 77 @param[in] MmioOperation TRUE for an MMIO operation, FALSE for I/O Port operation.\r
78 @param[in] Width Signifies the width of the I/O or Memory operation.\r
7367cc6c
LG
79 @param[in] Address The base address of the I/O operation.\r
80 @param[in] Count The number of I/O operations to perform. The number of\r
3ea1d3e6 81 bytes moved is Width size * Count, starting at Address.\r
82 @param[in] Buffer For read operations, the destination buffer to store the results.\r
83 For write operations, the source buffer from which to write data.\r
84\r
85 @retval EFI_SUCCESS The parameters for this request pass the checks.\r
86 @retval EFI_INVALID_PARAMETER Width is invalid for this PI system.\r
87 @retval EFI_INVALID_PARAMETER Buffer is NULL.\r
88 @retval EFI_UNSUPPORTED The Buffer is not aligned for the given Width.\r
7367cc6c 89 @retval EFI_UNSUPPORTED The address range specified by Address, Width,\r
3ea1d3e6 90 and Count is not valid for this PI system.\r
3ca55ed4 91\r
92**/\r
93EFI_STATUS\r
94CpuIoCheckParameter (\r
3ea1d3e6 95 IN BOOLEAN MmioOperation,\r
3ca55ed4 96 IN EFI_CPU_IO_PROTOCOL_WIDTH Width,\r
97 IN UINT64 Address,\r
98 IN UINTN Count,\r
3ea1d3e6 99 IN VOID *Buffer\r
3ca55ed4 100 )\r
101{\r
3ea1d3e6 102 UINT64 MaxCount;\r
103 UINT64 Limit;\r
3ca55ed4 104\r
3ea1d3e6 105 //\r
106 // Check to see if Buffer is NULL\r
107 //\r
3ca55ed4 108 if (Buffer == NULL) {\r
109 return EFI_INVALID_PARAMETER;\r
110 }\r
111\r
3ea1d3e6 112 //\r
113 // Check to see if Width is in the valid range\r
114 //\r
3d78c020 115 if ((UINT32)Width >= EfiCpuIoWidthMaximum) {\r
3ea1d3e6 116 return EFI_INVALID_PARAMETER;\r
3ca55ed4 117 }\r
118\r
119 //\r
3ea1d3e6 120 // For FIFO type, the target address won't increase during the access,\r
121 // so treat Count as 1\r
3ca55ed4 122 //\r
053e878b 123 if ((Width >= EfiCpuIoWidthFifoUint8) && (Width <= EfiCpuIoWidthFifoUint64)) {\r
3ca55ed4 124 Count = 1;\r
125 }\r
126\r
3ea1d3e6 127 //\r
128 // Check to see if Width is in the valid range for I/O Port operations\r
129 //\r
053e878b 130 Width = (EFI_CPU_IO_PROTOCOL_WIDTH)(Width & 0x03);\r
3ea1d3e6 131 if (!MmioOperation && (Width == EfiCpuIoWidthUint64)) {\r
132 return EFI_INVALID_PARAMETER;\r
3ca55ed4 133 }\r
7367cc6c 134\r
3ea1d3e6 135 //\r
44fdeb35 136 // Check to see if Address is aligned\r
3ea1d3e6 137 //\r
8491e302 138 if ((Address & ((UINT64)mInStride[Width] - 1)) != 0) {\r
3ca55ed4 139 return EFI_UNSUPPORTED;\r
140 }\r
141\r
3ea1d3e6 142 //\r
7367cc6c 143 // Check to see if any address associated with this transfer exceeds the maximum\r
3ea1d3e6 144 // allowed address. The maximum address implied by the parameters passed in is\r
145 // Address + Size * Count. If the following condition is met, then the transfer\r
146 // is not supported.\r
147 //\r
148 // Address + Size * Count > (MmioOperation ? MAX_ADDRESS : MAX_IO_PORT_ADDRESS) + 1\r
149 //\r
7367cc6c 150 // Since MAX_ADDRESS can be the maximum integer value supported by the CPU and Count\r
3ea1d3e6 151 // can also be the maximum integer value supported by the CPU, this range\r
152 // check must be adjusted to avoid all oveflow conditions.\r
7367cc6c
LG
153 //\r
154 // The following form of the range check is equivalent but assumes that\r
3ea1d3e6 155 // MAX_ADDRESS and MAX_IO_PORT_ADDRESS are of the form (2^n - 1).\r
156 //\r
157 Limit = (MmioOperation ? MAX_ADDRESS : MAX_IO_PORT_ADDRESS);\r
158 if (Count == 0) {\r
159 if (Address > Limit) {\r
160 return EFI_UNSUPPORTED;\r
3ca55ed4 161 }\r
7367cc6c 162 } else {\r
3ea1d3e6 163 MaxCount = RShiftU64 (Limit, Width);\r
164 if (MaxCount < (Count - 1)) {\r
165 return EFI_UNSUPPORTED;\r
3ca55ed4 166 }\r
053e878b 167\r
3ea1d3e6 168 if (Address > LShiftU64 (MaxCount - Count + 1, Width)) {\r
169 return EFI_UNSUPPORTED;\r
3ca55ed4 170 }\r
3ca55ed4 171 }\r
172\r
3ca55ed4 173 //\r
44fdeb35 174 // Check to see if Buffer is aligned\r
36de8606 175 // (IA-32 allows UINT64 and INT64 data types to be 32-bit aligned.)\r
3ca55ed4 176 //\r
36de8606 177 if (((UINTN)Buffer & ((MIN (sizeof (UINTN), mInStride[Width]) - 1))) != 0) {\r
3ea1d3e6 178 return EFI_UNSUPPORTED;\r
3ca55ed4 179 }\r
180\r
181 return EFI_SUCCESS;\r
182}\r
183\r
184/**\r
3ea1d3e6 185 Reads memory-mapped registers.\r
3ca55ed4 186\r
7367cc6c
LG
187 The I/O operations are carried out exactly as requested. The caller is responsible\r
188 for satisfying any alignment and I/O width restrictions that a PI System on a\r
189 platform might require. For example on some platforms, width requests of\r
190 EfiCpuIoWidthUint64 do not work. Misaligned buffers, on the other hand, will\r
3ea1d3e6 191 be handled by the driver.\r
7367cc6c
LG
192\r
193 If Width is EfiCpuIoWidthUint8, EfiCpuIoWidthUint16, EfiCpuIoWidthUint32,\r
194 or EfiCpuIoWidthUint64, then both Address and Buffer are incremented for\r
3ea1d3e6 195 each of the Count operations that is performed.\r
7367cc6c
LG
196\r
197 If Width is EfiCpuIoWidthFifoUint8, EfiCpuIoWidthFifoUint16,\r
198 EfiCpuIoWidthFifoUint32, or EfiCpuIoWidthFifoUint64, then only Buffer is\r
199 incremented for each of the Count operations that is performed. The read or\r
3ea1d3e6 200 write operation is performed Count times on the same Address.\r
7367cc6c
LG
201\r
202 If Width is EfiCpuIoWidthFillUint8, EfiCpuIoWidthFillUint16,\r
203 EfiCpuIoWidthFillUint32, or EfiCpuIoWidthFillUint64, then only Address is\r
204 incremented for each of the Count operations that is performed. The read or\r
3ea1d3e6 205 write operation is performed Count times from the first element of Buffer.\r
7367cc6c 206\r
3ea1d3e6 207 @param[in] This A pointer to the EFI_CPU_IO2_PROTOCOL instance.\r
208 @param[in] Width Signifies the width of the I/O or Memory operation.\r
7367cc6c
LG
209 @param[in] Address The base address of the I/O operation.\r
210 @param[in] Count The number of I/O operations to perform. The number of\r
3ea1d3e6 211 bytes moved is Width size * Count, starting at Address.\r
212 @param[out] Buffer For read operations, the destination buffer to store the results.\r
213 For write operations, the source buffer from which to write data.\r
214\r
215 @retval EFI_SUCCESS The data was read from or written to the PI system.\r
216 @retval EFI_INVALID_PARAMETER Width is invalid for this PI system.\r
217 @retval EFI_INVALID_PARAMETER Buffer is NULL.\r
218 @retval EFI_UNSUPPORTED The Buffer is not aligned for the given Width.\r
7367cc6c 219 @retval EFI_UNSUPPORTED The address range specified by Address, Width,\r
3ea1d3e6 220 and Count is not valid for this PI system.\r
3ca55ed4 221\r
222**/\r
223EFI_STATUS\r
224EFIAPI\r
225CpuMemoryServiceRead (\r
3ea1d3e6 226 IN EFI_CPU_IO2_PROTOCOL *This,\r
227 IN EFI_CPU_IO_PROTOCOL_WIDTH Width,\r
228 IN UINT64 Address,\r
229 IN UINTN Count,\r
230 OUT VOID *Buffer\r
3ca55ed4 231 )\r
232{\r
3ea1d3e6 233 EFI_STATUS Status;\r
234 UINT8 InStride;\r
235 UINT8 OutStride;\r
236 EFI_CPU_IO_PROTOCOL_WIDTH OperationWidth;\r
237 UINT8 *Uint8Buffer;\r
3ca55ed4 238\r
3ea1d3e6 239 Status = CpuIoCheckParameter (TRUE, Width, Address, Count, Buffer);\r
3ca55ed4 240 if (EFI_ERROR (Status)) {\r
241 return Status;\r
242 }\r
243\r
3ca55ed4 244 //\r
3ea1d3e6 245 // Select loop based on the width of the transfer\r
3ca55ed4 246 //\r
053e878b
MK
247 InStride = mInStride[Width];\r
248 OutStride = mOutStride[Width];\r
249 OperationWidth = (EFI_CPU_IO_PROTOCOL_WIDTH)(Width & 0x03);\r
3ea1d3e6 250 for (Uint8Buffer = Buffer; Count > 0; Address += InStride, Uint8Buffer += OutStride, Count--) {\r
251 if (OperationWidth == EfiCpuIoWidthUint8) {\r
252 *Uint8Buffer = MmioRead8 ((UINTN)Address);\r
253 } else if (OperationWidth == EfiCpuIoWidthUint16) {\r
254 *((UINT16 *)Uint8Buffer) = MmioRead16 ((UINTN)Address);\r
255 } else if (OperationWidth == EfiCpuIoWidthUint32) {\r
256 *((UINT32 *)Uint8Buffer) = MmioRead32 ((UINTN)Address);\r
257 } else if (OperationWidth == EfiCpuIoWidthUint64) {\r
258 *((UINT64 *)Uint8Buffer) = MmioRead64 ((UINTN)Address);\r
259 }\r
3ca55ed4 260 }\r
053e878b 261\r
3ea1d3e6 262 return EFI_SUCCESS;\r
3ca55ed4 263}\r
264\r
265/**\r
3ea1d3e6 266 Writes memory-mapped registers.\r
3ca55ed4 267\r
7367cc6c
LG
268 The I/O operations are carried out exactly as requested. The caller is responsible\r
269 for satisfying any alignment and I/O width restrictions that a PI System on a\r
270 platform might require. For example on some platforms, width requests of\r
271 EfiCpuIoWidthUint64 do not work. Misaligned buffers, on the other hand, will\r
3ea1d3e6 272 be handled by the driver.\r
7367cc6c
LG
273\r
274 If Width is EfiCpuIoWidthUint8, EfiCpuIoWidthUint16, EfiCpuIoWidthUint32,\r
275 or EfiCpuIoWidthUint64, then both Address and Buffer are incremented for\r
3ea1d3e6 276 each of the Count operations that is performed.\r
7367cc6c
LG
277\r
278 If Width is EfiCpuIoWidthFifoUint8, EfiCpuIoWidthFifoUint16,\r
279 EfiCpuIoWidthFifoUint32, or EfiCpuIoWidthFifoUint64, then only Buffer is\r
280 incremented for each of the Count operations that is performed. The read or\r
3ea1d3e6 281 write operation is performed Count times on the same Address.\r
7367cc6c
LG
282\r
283 If Width is EfiCpuIoWidthFillUint8, EfiCpuIoWidthFillUint16,\r
284 EfiCpuIoWidthFillUint32, or EfiCpuIoWidthFillUint64, then only Address is\r
285 incremented for each of the Count operations that is performed. The read or\r
3ea1d3e6 286 write operation is performed Count times from the first element of Buffer.\r
7367cc6c 287\r
3ea1d3e6 288 @param[in] This A pointer to the EFI_CPU_IO2_PROTOCOL instance.\r
289 @param[in] Width Signifies the width of the I/O or Memory operation.\r
7367cc6c
LG
290 @param[in] Address The base address of the I/O operation.\r
291 @param[in] Count The number of I/O operations to perform. The number of\r
3ea1d3e6 292 bytes moved is Width size * Count, starting at Address.\r
293 @param[in] Buffer For read operations, the destination buffer to store the results.\r
294 For write operations, the source buffer from which to write data.\r
295\r
296 @retval EFI_SUCCESS The data was read from or written to the PI system.\r
297 @retval EFI_INVALID_PARAMETER Width is invalid for this PI system.\r
298 @retval EFI_INVALID_PARAMETER Buffer is NULL.\r
299 @retval EFI_UNSUPPORTED The Buffer is not aligned for the given Width.\r
7367cc6c 300 @retval EFI_UNSUPPORTED The address range specified by Address, Width,\r
3ea1d3e6 301 and Count is not valid for this PI system.\r
3ca55ed4 302\r
303**/\r
304EFI_STATUS\r
305EFIAPI\r
306CpuMemoryServiceWrite (\r
3ea1d3e6 307 IN EFI_CPU_IO2_PROTOCOL *This,\r
308 IN EFI_CPU_IO_PROTOCOL_WIDTH Width,\r
309 IN UINT64 Address,\r
310 IN UINTN Count,\r
311 IN VOID *Buffer\r
3ca55ed4 312 )\r
313{\r
3ca55ed4 314 EFI_STATUS Status;\r
3ea1d3e6 315 UINT8 InStride;\r
316 UINT8 OutStride;\r
317 EFI_CPU_IO_PROTOCOL_WIDTH OperationWidth;\r
318 UINT8 *Uint8Buffer;\r
3ca55ed4 319\r
3ea1d3e6 320 Status = CpuIoCheckParameter (TRUE, Width, Address, Count, Buffer);\r
3ca55ed4 321 if (EFI_ERROR (Status)) {\r
322 return Status;\r
323 }\r
324\r
3ca55ed4 325 //\r
3ea1d3e6 326 // Select loop based on the width of the transfer\r
3ca55ed4 327 //\r
053e878b
MK
328 InStride = mInStride[Width];\r
329 OutStride = mOutStride[Width];\r
330 OperationWidth = (EFI_CPU_IO_PROTOCOL_WIDTH)(Width & 0x03);\r
3ea1d3e6 331 for (Uint8Buffer = Buffer; Count > 0; Address += InStride, Uint8Buffer += OutStride, Count--) {\r
332 if (OperationWidth == EfiCpuIoWidthUint8) {\r
333 MmioWrite8 ((UINTN)Address, *Uint8Buffer);\r
334 } else if (OperationWidth == EfiCpuIoWidthUint16) {\r
335 MmioWrite16 ((UINTN)Address, *((UINT16 *)Uint8Buffer));\r
336 } else if (OperationWidth == EfiCpuIoWidthUint32) {\r
337 MmioWrite32 ((UINTN)Address, *((UINT32 *)Uint8Buffer));\r
338 } else if (OperationWidth == EfiCpuIoWidthUint64) {\r
339 MmioWrite64 ((UINTN)Address, *((UINT64 *)Uint8Buffer));\r
340 }\r
3ca55ed4 341 }\r
053e878b 342\r
3ea1d3e6 343 return EFI_SUCCESS;\r
3ca55ed4 344}\r
345\r
346/**\r
3ea1d3e6 347 Reads I/O registers.\r
3ca55ed4 348\r
7367cc6c
LG
349 The I/O operations are carried out exactly as requested. The caller is responsible\r
350 for satisfying any alignment and I/O width restrictions that a PI System on a\r
351 platform might require. For example on some platforms, width requests of\r
352 EfiCpuIoWidthUint64 do not work. Misaligned buffers, on the other hand, will\r
3ea1d3e6 353 be handled by the driver.\r
7367cc6c
LG
354\r
355 If Width is EfiCpuIoWidthUint8, EfiCpuIoWidthUint16, EfiCpuIoWidthUint32,\r
356 or EfiCpuIoWidthUint64, then both Address and Buffer are incremented for\r
3ea1d3e6 357 each of the Count operations that is performed.\r
7367cc6c
LG
358\r
359 If Width is EfiCpuIoWidthFifoUint8, EfiCpuIoWidthFifoUint16,\r
360 EfiCpuIoWidthFifoUint32, or EfiCpuIoWidthFifoUint64, then only Buffer is\r
361 incremented for each of the Count operations that is performed. The read or\r
3ea1d3e6 362 write operation is performed Count times on the same Address.\r
7367cc6c
LG
363\r
364 If Width is EfiCpuIoWidthFillUint8, EfiCpuIoWidthFillUint16,\r
365 EfiCpuIoWidthFillUint32, or EfiCpuIoWidthFillUint64, then only Address is\r
366 incremented for each of the Count operations that is performed. The read or\r
3ea1d3e6 367 write operation is performed Count times from the first element of Buffer.\r
7367cc6c 368\r
3ea1d3e6 369 @param[in] This A pointer to the EFI_CPU_IO2_PROTOCOL instance.\r
370 @param[in] Width Signifies the width of the I/O or Memory operation.\r
7367cc6c
LG
371 @param[in] Address The base address of the I/O operation.\r
372 @param[in] Count The number of I/O operations to perform. The number of\r
3ea1d3e6 373 bytes moved is Width size * Count, starting at Address.\r
374 @param[out] Buffer For read operations, the destination buffer to store the results.\r
375 For write operations, the source buffer from which to write data.\r
376\r
377 @retval EFI_SUCCESS The data was read from or written to the PI system.\r
378 @retval EFI_INVALID_PARAMETER Width is invalid for this PI system.\r
379 @retval EFI_INVALID_PARAMETER Buffer is NULL.\r
380 @retval EFI_UNSUPPORTED The Buffer is not aligned for the given Width.\r
7367cc6c 381 @retval EFI_UNSUPPORTED The address range specified by Address, Width,\r
3ea1d3e6 382 and Count is not valid for this PI system.\r
3ca55ed4 383\r
384**/\r
385EFI_STATUS\r
386EFIAPI\r
387CpuIoServiceRead (\r
3ea1d3e6 388 IN EFI_CPU_IO2_PROTOCOL *This,\r
389 IN EFI_CPU_IO_PROTOCOL_WIDTH Width,\r
390 IN UINT64 Address,\r
391 IN UINTN Count,\r
392 OUT VOID *Buffer\r
3ca55ed4 393 )\r
394{\r
3ea1d3e6 395 EFI_STATUS Status;\r
396 UINT8 InStride;\r
397 UINT8 OutStride;\r
398 EFI_CPU_IO_PROTOCOL_WIDTH OperationWidth;\r
399 UINT8 *Uint8Buffer;\r
3ca55ed4 400\r
3ea1d3e6 401 Status = CpuIoCheckParameter (FALSE, Width, Address, Count, Buffer);\r
3ca55ed4 402 if (EFI_ERROR (Status)) {\r
403 return Status;\r
404 }\r
405\r
406 //\r
3ea1d3e6 407 // Select loop based on the width of the transfer\r
3ca55ed4 408 //\r
053e878b
MK
409 InStride = mInStride[Width];\r
410 OutStride = mOutStride[Width];\r
411 OperationWidth = (EFI_CPU_IO_PROTOCOL_WIDTH)(Width & 0x03);\r
fb8b5469 412\r
200b4223
LD
413 //\r
414 // Fifo operations supported for (mInStride[Width] == 0)\r
415 //\r
fb8b5469
LE
416 if (InStride == 0) {\r
417 switch (OperationWidth) {\r
053e878b
MK
418 case EfiCpuIoWidthUint8:\r
419 IoReadFifo8 ((UINTN)Address, Count, Buffer);\r
420 return EFI_SUCCESS;\r
421 case EfiCpuIoWidthUint16:\r
422 IoReadFifo16 ((UINTN)Address, Count, Buffer);\r
423 return EFI_SUCCESS;\r
424 case EfiCpuIoWidthUint32:\r
425 IoReadFifo32 ((UINTN)Address, Count, Buffer);\r
426 return EFI_SUCCESS;\r
427 default:\r
428 //\r
429 // The CpuIoCheckParameter call above will ensure that this\r
430 // path is not taken.\r
431 //\r
432 ASSERT (FALSE);\r
433 break;\r
fb8b5469
LE
434 }\r
435 }\r
fb8b5469 436\r
3ea1d3e6 437 for (Uint8Buffer = Buffer; Count > 0; Address += InStride, Uint8Buffer += OutStride, Count--) {\r
438 if (OperationWidth == EfiCpuIoWidthUint8) {\r
439 *Uint8Buffer = IoRead8 ((UINTN)Address);\r
440 } else if (OperationWidth == EfiCpuIoWidthUint16) {\r
441 *((UINT16 *)Uint8Buffer) = IoRead16 ((UINTN)Address);\r
442 } else if (OperationWidth == EfiCpuIoWidthUint32) {\r
443 *((UINT32 *)Uint8Buffer) = IoRead32 ((UINTN)Address);\r
3ca55ed4 444 }\r
3ca55ed4 445 }\r
446\r
447 return EFI_SUCCESS;\r
448}\r
449\r
450/**\r
3ea1d3e6 451 Write I/O registers.\r
3ca55ed4 452\r
7367cc6c
LG
453 The I/O operations are carried out exactly as requested. The caller is responsible\r
454 for satisfying any alignment and I/O width restrictions that a PI System on a\r
455 platform might require. For example on some platforms, width requests of\r
456 EfiCpuIoWidthUint64 do not work. Misaligned buffers, on the other hand, will\r
3ea1d3e6 457 be handled by the driver.\r
7367cc6c
LG
458\r
459 If Width is EfiCpuIoWidthUint8, EfiCpuIoWidthUint16, EfiCpuIoWidthUint32,\r
460 or EfiCpuIoWidthUint64, then both Address and Buffer are incremented for\r
3ea1d3e6 461 each of the Count operations that is performed.\r
7367cc6c
LG
462\r
463 If Width is EfiCpuIoWidthFifoUint8, EfiCpuIoWidthFifoUint16,\r
464 EfiCpuIoWidthFifoUint32, or EfiCpuIoWidthFifoUint64, then only Buffer is\r
465 incremented for each of the Count operations that is performed. The read or\r
3ea1d3e6 466 write operation is performed Count times on the same Address.\r
7367cc6c
LG
467\r
468 If Width is EfiCpuIoWidthFillUint8, EfiCpuIoWidthFillUint16,\r
469 EfiCpuIoWidthFillUint32, or EfiCpuIoWidthFillUint64, then only Address is\r
470 incremented for each of the Count operations that is performed. The read or\r
3ea1d3e6 471 write operation is performed Count times from the first element of Buffer.\r
7367cc6c 472\r
3ea1d3e6 473 @param[in] This A pointer to the EFI_CPU_IO2_PROTOCOL instance.\r
474 @param[in] Width Signifies the width of the I/O or Memory operation.\r
7367cc6c
LG
475 @param[in] Address The base address of the I/O operation.\r
476 @param[in] Count The number of I/O operations to perform. The number of\r
3ea1d3e6 477 bytes moved is Width size * Count, starting at Address.\r
478 @param[in] Buffer For read operations, the destination buffer to store the results.\r
479 For write operations, the source buffer from which to write data.\r
480\r
481 @retval EFI_SUCCESS The data was read from or written to the PI system.\r
482 @retval EFI_INVALID_PARAMETER Width is invalid for this PI system.\r
483 @retval EFI_INVALID_PARAMETER Buffer is NULL.\r
484 @retval EFI_UNSUPPORTED The Buffer is not aligned for the given Width.\r
7367cc6c 485 @retval EFI_UNSUPPORTED The address range specified by Address, Width,\r
3ea1d3e6 486 and Count is not valid for this PI system.\r
7367cc6c 487\r
3ca55ed4 488**/\r
489EFI_STATUS\r
490EFIAPI\r
491CpuIoServiceWrite (\r
3ea1d3e6 492 IN EFI_CPU_IO2_PROTOCOL *This,\r
493 IN EFI_CPU_IO_PROTOCOL_WIDTH Width,\r
494 IN UINT64 Address,\r
495 IN UINTN Count,\r
496 IN VOID *Buffer\r
3ca55ed4 497 )\r
498{\r
3ea1d3e6 499 EFI_STATUS Status;\r
500 UINT8 InStride;\r
501 UINT8 OutStride;\r
502 EFI_CPU_IO_PROTOCOL_WIDTH OperationWidth;\r
503 UINT8 *Uint8Buffer;\r
3ca55ed4 504\r
505 //\r
3ea1d3e6 506 // Make sure the parameters are valid\r
3ca55ed4 507 //\r
3ea1d3e6 508 Status = CpuIoCheckParameter (FALSE, Width, Address, Count, Buffer);\r
509 if (EFI_ERROR (Status)) {\r
510 return Status;\r
3ca55ed4 511 }\r
512\r
513 //\r
3ea1d3e6 514 // Select loop based on the width of the transfer\r
3ca55ed4 515 //\r
053e878b
MK
516 InStride = mInStride[Width];\r
517 OutStride = mOutStride[Width];\r
518 OperationWidth = (EFI_CPU_IO_PROTOCOL_WIDTH)(Width & 0x03);\r
fb8b5469 519\r
200b4223
LD
520 //\r
521 // Fifo operations supported for (mInStride[Width] == 0)\r
522 //\r
fb8b5469
LE
523 if (InStride == 0) {\r
524 switch (OperationWidth) {\r
053e878b
MK
525 case EfiCpuIoWidthUint8:\r
526 IoWriteFifo8 ((UINTN)Address, Count, Buffer);\r
527 return EFI_SUCCESS;\r
528 case EfiCpuIoWidthUint16:\r
529 IoWriteFifo16 ((UINTN)Address, Count, Buffer);\r
530 return EFI_SUCCESS;\r
531 case EfiCpuIoWidthUint32:\r
532 IoWriteFifo32 ((UINTN)Address, Count, Buffer);\r
533 return EFI_SUCCESS;\r
534 default:\r
535 //\r
536 // The CpuIoCheckParameter call above will ensure that this\r
537 // path is not taken.\r
538 //\r
539 ASSERT (FALSE);\r
540 break;\r
fb8b5469
LE
541 }\r
542 }\r
fb8b5469 543\r
3ea1d3e6 544 for (Uint8Buffer = (UINT8 *)Buffer; Count > 0; Address += InStride, Uint8Buffer += OutStride, Count--) {\r
545 if (OperationWidth == EfiCpuIoWidthUint8) {\r
546 IoWrite8 ((UINTN)Address, *Uint8Buffer);\r
547 } else if (OperationWidth == EfiCpuIoWidthUint16) {\r
548 IoWrite16 ((UINTN)Address, *((UINT16 *)Uint8Buffer));\r
549 } else if (OperationWidth == EfiCpuIoWidthUint32) {\r
550 IoWrite32 ((UINTN)Address, *((UINT32 *)Uint8Buffer));\r
3ca55ed4 551 }\r
3ca55ed4 552 }\r
7367cc6c 553\r
3ca55ed4 554 return EFI_SUCCESS;\r
555}\r
556\r
557/**\r
3ea1d3e6 558 The user Entry Point for module CpuIo2Dxe. The user code starts with this function.\r
559\r
7367cc6c 560 @param[in] ImageHandle The firmware allocated handle for the EFI image.\r
3ea1d3e6 561 @param[in] SystemTable A pointer to the EFI System Table.\r
7367cc6c 562\r
3ea1d3e6 563 @retval EFI_SUCCESS The entry point is executed successfully.\r
564 @retval other Some error occurs when executing this entry point.\r
3ca55ed4 565\r
566**/\r
567EFI_STATUS\r
568EFIAPI\r
569CpuIo2Initialize (\r
570 IN EFI_HANDLE ImageHandle,\r
571 IN EFI_SYSTEM_TABLE *SystemTable\r
572 )\r
573{\r
053e878b 574 EFI_STATUS Status;\r
3ca55ed4 575\r
3ea1d3e6 576 ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gEfiCpuIo2ProtocolGuid);\r
577 Status = gBS->InstallMultipleProtocolInterfaces (\r
3ca55ed4 578 &mHandle,\r
053e878b
MK
579 &gEfiCpuIo2ProtocolGuid,\r
580 &mCpuIo2,\r
3ea1d3e6 581 NULL\r
3ca55ed4 582 );\r
583 ASSERT_EFI_ERROR (Status);\r
584\r
585 return Status;\r
586}\r