]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - UefiCpuPkg/CpuIo2Dxe/CpuIo2Dxe.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / UefiCpuPkg / CpuIo2Dxe / CpuIo2Dxe.c
... / ...
CommitLineData
1/** @file\r
2 Produces the CPU I/O 2 Protocol.\r
3\r
4Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>\r
5Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR>\r
6\r
7SPDX-License-Identifier: BSD-2-Clause-Patent\r
8\r
9**/\r
10\r
11#include "CpuIo2Dxe.h"\r
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
21EFI_CPU_IO2_PROTOCOL mCpuIo2 = {\r
22 {\r
23 CpuMemoryServiceRead,\r
24 CpuMemoryServiceWrite\r
25 },\r
26 {\r
27 CpuIoServiceRead,\r
28 CpuIoServiceWrite\r
29 }\r
30};\r
31\r
32//\r
33// Lookup table for increment values based on transfer widths\r
34//\r
35UINT8 mInStride[] = {\r
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
49\r
50//\r
51// Lookup table for increment values based on transfer widths\r
52//\r
53UINT8 mOutStride[] = {\r
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
67\r
68/**\r
69 Check parameters to a CPU I/O 2 Protocol service request.\r
70\r
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
75 be handled by the driver.\r
76\r
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
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
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
89 @retval EFI_UNSUPPORTED The address range specified by Address, Width,\r
90 and Count is not valid for this PI system.\r
91\r
92**/\r
93EFI_STATUS\r
94CpuIoCheckParameter (\r
95 IN BOOLEAN MmioOperation,\r
96 IN EFI_CPU_IO_PROTOCOL_WIDTH Width,\r
97 IN UINT64 Address,\r
98 IN UINTN Count,\r
99 IN VOID *Buffer\r
100 )\r
101{\r
102 UINT64 MaxCount;\r
103 UINT64 Limit;\r
104\r
105 //\r
106 // Check to see if Buffer is NULL\r
107 //\r
108 if (Buffer == NULL) {\r
109 return EFI_INVALID_PARAMETER;\r
110 }\r
111\r
112 //\r
113 // Check to see if Width is in the valid range\r
114 //\r
115 if ((UINT32)Width >= EfiCpuIoWidthMaximum) {\r
116 return EFI_INVALID_PARAMETER;\r
117 }\r
118\r
119 //\r
120 // For FIFO type, the target address won't increase during the access,\r
121 // so treat Count as 1\r
122 //\r
123 if ((Width >= EfiCpuIoWidthFifoUint8) && (Width <= EfiCpuIoWidthFifoUint64)) {\r
124 Count = 1;\r
125 }\r
126\r
127 //\r
128 // Check to see if Width is in the valid range for I/O Port operations\r
129 //\r
130 Width = (EFI_CPU_IO_PROTOCOL_WIDTH)(Width & 0x03);\r
131 if (!MmioOperation && (Width == EfiCpuIoWidthUint64)) {\r
132 return EFI_INVALID_PARAMETER;\r
133 }\r
134\r
135 //\r
136 // Check to see if Address is aligned\r
137 //\r
138 if ((Address & ((UINT64)mInStride[Width] - 1)) != 0) {\r
139 return EFI_UNSUPPORTED;\r
140 }\r
141\r
142 //\r
143 // Check to see if any address associated with this transfer exceeds the maximum\r
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
150 // Since MAX_ADDRESS can be the maximum integer value supported by the CPU and Count\r
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
153 //\r
154 // The following form of the range check is equivalent but assumes that\r
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
161 }\r
162 } else {\r
163 MaxCount = RShiftU64 (Limit, Width);\r
164 if (MaxCount < (Count - 1)) {\r
165 return EFI_UNSUPPORTED;\r
166 }\r
167\r
168 if (Address > LShiftU64 (MaxCount - Count + 1, Width)) {\r
169 return EFI_UNSUPPORTED;\r
170 }\r
171 }\r
172\r
173 //\r
174 // Check to see if Buffer is aligned\r
175 // (IA-32 allows UINT64 and INT64 data types to be 32-bit aligned.)\r
176 //\r
177 if (((UINTN)Buffer & ((MIN (sizeof (UINTN), mInStride[Width]) - 1))) != 0) {\r
178 return EFI_UNSUPPORTED;\r
179 }\r
180\r
181 return EFI_SUCCESS;\r
182}\r
183\r
184/**\r
185 Reads memory-mapped registers.\r
186\r
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
191 be handled by the driver.\r
192\r
193 If Width is EfiCpuIoWidthUint8, EfiCpuIoWidthUint16, EfiCpuIoWidthUint32,\r
194 or EfiCpuIoWidthUint64, then both Address and Buffer are incremented for\r
195 each of the Count operations that is performed.\r
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
200 write operation is performed Count times on the same Address.\r
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
205 write operation is performed Count times from the first element of Buffer.\r
206\r
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
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
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
219 @retval EFI_UNSUPPORTED The address range specified by Address, Width,\r
220 and Count is not valid for this PI system.\r
221\r
222**/\r
223EFI_STATUS\r
224EFIAPI\r
225CpuMemoryServiceRead (\r
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
231 )\r
232{\r
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
238\r
239 Status = CpuIoCheckParameter (TRUE, Width, Address, Count, Buffer);\r
240 if (EFI_ERROR (Status)) {\r
241 return Status;\r
242 }\r
243\r
244 //\r
245 // Select loop based on the width of the transfer\r
246 //\r
247 InStride = mInStride[Width];\r
248 OutStride = mOutStride[Width];\r
249 OperationWidth = (EFI_CPU_IO_PROTOCOL_WIDTH)(Width & 0x03);\r
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
260 }\r
261\r
262 return EFI_SUCCESS;\r
263}\r
264\r
265/**\r
266 Writes memory-mapped registers.\r
267\r
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
272 be handled by the driver.\r
273\r
274 If Width is EfiCpuIoWidthUint8, EfiCpuIoWidthUint16, EfiCpuIoWidthUint32,\r
275 or EfiCpuIoWidthUint64, then both Address and Buffer are incremented for\r
276 each of the Count operations that is performed.\r
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
281 write operation is performed Count times on the same Address.\r
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
286 write operation is performed Count times from the first element of Buffer.\r
287\r
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
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
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
300 @retval EFI_UNSUPPORTED The address range specified by Address, Width,\r
301 and Count is not valid for this PI system.\r
302\r
303**/\r
304EFI_STATUS\r
305EFIAPI\r
306CpuMemoryServiceWrite (\r
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
312 )\r
313{\r
314 EFI_STATUS Status;\r
315 UINT8 InStride;\r
316 UINT8 OutStride;\r
317 EFI_CPU_IO_PROTOCOL_WIDTH OperationWidth;\r
318 UINT8 *Uint8Buffer;\r
319\r
320 Status = CpuIoCheckParameter (TRUE, Width, Address, Count, Buffer);\r
321 if (EFI_ERROR (Status)) {\r
322 return Status;\r
323 }\r
324\r
325 //\r
326 // Select loop based on the width of the transfer\r
327 //\r
328 InStride = mInStride[Width];\r
329 OutStride = mOutStride[Width];\r
330 OperationWidth = (EFI_CPU_IO_PROTOCOL_WIDTH)(Width & 0x03);\r
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
341 }\r
342\r
343 return EFI_SUCCESS;\r
344}\r
345\r
346/**\r
347 Reads I/O registers.\r
348\r
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
353 be handled by the driver.\r
354\r
355 If Width is EfiCpuIoWidthUint8, EfiCpuIoWidthUint16, EfiCpuIoWidthUint32,\r
356 or EfiCpuIoWidthUint64, then both Address and Buffer are incremented for\r
357 each of the Count operations that is performed.\r
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
362 write operation is performed Count times on the same Address.\r
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
367 write operation is performed Count times from the first element of Buffer.\r
368\r
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
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
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
381 @retval EFI_UNSUPPORTED The address range specified by Address, Width,\r
382 and Count is not valid for this PI system.\r
383\r
384**/\r
385EFI_STATUS\r
386EFIAPI\r
387CpuIoServiceRead (\r
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
393 )\r
394{\r
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
400\r
401 Status = CpuIoCheckParameter (FALSE, Width, Address, Count, Buffer);\r
402 if (EFI_ERROR (Status)) {\r
403 return Status;\r
404 }\r
405\r
406 //\r
407 // Select loop based on the width of the transfer\r
408 //\r
409 InStride = mInStride[Width];\r
410 OutStride = mOutStride[Width];\r
411 OperationWidth = (EFI_CPU_IO_PROTOCOL_WIDTH)(Width & 0x03);\r
412\r
413 //\r
414 // Fifo operations supported for (mInStride[Width] == 0)\r
415 //\r
416 if (InStride == 0) {\r
417 switch (OperationWidth) {\r
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
434 }\r
435 }\r
436\r
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
444 }\r
445 }\r
446\r
447 return EFI_SUCCESS;\r
448}\r
449\r
450/**\r
451 Write I/O registers.\r
452\r
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
457 be handled by the driver.\r
458\r
459 If Width is EfiCpuIoWidthUint8, EfiCpuIoWidthUint16, EfiCpuIoWidthUint32,\r
460 or EfiCpuIoWidthUint64, then both Address and Buffer are incremented for\r
461 each of the Count operations that is performed.\r
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
466 write operation is performed Count times on the same Address.\r
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
471 write operation is performed Count times from the first element of Buffer.\r
472\r
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
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
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
485 @retval EFI_UNSUPPORTED The address range specified by Address, Width,\r
486 and Count is not valid for this PI system.\r
487\r
488**/\r
489EFI_STATUS\r
490EFIAPI\r
491CpuIoServiceWrite (\r
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
497 )\r
498{\r
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
504\r
505 //\r
506 // Make sure the parameters are valid\r
507 //\r
508 Status = CpuIoCheckParameter (FALSE, Width, Address, Count, Buffer);\r
509 if (EFI_ERROR (Status)) {\r
510 return Status;\r
511 }\r
512\r
513 //\r
514 // Select loop based on the width of the transfer\r
515 //\r
516 InStride = mInStride[Width];\r
517 OutStride = mOutStride[Width];\r
518 OperationWidth = (EFI_CPU_IO_PROTOCOL_WIDTH)(Width & 0x03);\r
519\r
520 //\r
521 // Fifo operations supported for (mInStride[Width] == 0)\r
522 //\r
523 if (InStride == 0) {\r
524 switch (OperationWidth) {\r
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
541 }\r
542 }\r
543\r
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
551 }\r
552 }\r
553\r
554 return EFI_SUCCESS;\r
555}\r
556\r
557/**\r
558 The user Entry Point for module CpuIo2Dxe. The user code starts with this function.\r
559\r
560 @param[in] ImageHandle The firmware allocated handle for the EFI image.\r
561 @param[in] SystemTable A pointer to the EFI System Table.\r
562\r
563 @retval EFI_SUCCESS The entry point is executed successfully.\r
564 @retval other Some error occurs when executing this entry point.\r
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
574 EFI_STATUS Status;\r
575\r
576 ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gEfiCpuIo2ProtocolGuid);\r
577 Status = gBS->InstallMultipleProtocolInterfaces (\r
578 &mHandle,\r
579 &gEfiCpuIo2ProtocolGuid,\r
580 &mCpuIo2,\r
581 NULL\r
582 );\r
583 ASSERT_EFI_ERROR (Status);\r
584\r
585 return Status;\r
586}\r