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