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