]> git.proxmox.com Git - mirror_edk2.git/blame - IntelFrameworkModulePkg/Universal/CpuIoDxe/CpuIo.c
TcgPei need to measure anything to PCR in S3 bootpath, so skip shadow logic.
[mirror_edk2.git] / IntelFrameworkModulePkg / Universal / CpuIoDxe / CpuIo.c
CommitLineData
806bf4f2 1/** @file\r
2 Uses the services of the I/O Library to produce the CPU I/O Protocol\r
3\r
20f6ac14 4Copyright (c) 2004 - 2011, Intel Corporation. All rights reserved.<BR>\r
180a5a35 5This program and the accompanying materials \r
806bf4f2 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
12\r
13**/\r
14\r
55a503bc 15#include "CpuIo.h"\r
806bf4f2 16\r
17//\r
18// Handle for the CPU I/O Protocol\r
19//\r
20EFI_HANDLE mHandle = NULL;\r
21\r
22//\r
23// CPU I/O Protocol inatance\r
24//\r
25EFI_CPU_IO_PROTOCOL mCpuIo = {\r
26 {\r
27 CpuMemoryServiceRead,\r
28 CpuMemoryServiceWrite\r
29 },\r
30 {\r
31 CpuIoServiceRead,\r
32 CpuIoServiceWrite\r
33 }\r
34};\r
35\r
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
53\r
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
71\r
72/**\r
73 Check parameters to a CPU I/O Protocol service request.\r
74\r
7a7f916a 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
806bf4f2 95\r
96**/\r
97EFI_STATUS\r
98CpuIoCheckParameter (\r
99 IN BOOLEAN MmioOperation,\r
100 IN EFI_CPU_IO_PROTOCOL_WIDTH Width,\r
101 IN UINT64 Address,\r
102 IN UINTN Count,\r
103 IN VOID *Buffer\r
104 )\r
105{\r
106 UINT64 MaxCount;\r
107 UINT64 Limit;\r
7a7f916a 108\r
806bf4f2 109 //\r
110 // Check to see if Buffer is NULL\r
111 //\r
112 if (Buffer == NULL) {\r
113 return EFI_INVALID_PARAMETER;\r
114 }\r
115\r
116 //\r
117 // Check to see if Width is in the valid range\r
118 //\r
119 if (Width < 0 || Width >= EfiCpuIoWidthMaximum) {\r
120 return EFI_INVALID_PARAMETER;\r
121 }\r
122\r
123 //\r
124 // For FIFO type, the target address won't increase during the access,\r
125 // so treat Count as 1\r
126 //\r
127 if (Width >= EfiCpuIoWidthFifoUint8 && Width <= EfiCpuIoWidthFifoUint64) {\r
128 Count = 1;\r
129 }\r
130\r
131 //\r
132 // Check to see if Width is in the valid range for I/O Port operations\r
133 //\r
6b9ddb42 134 Width = (EFI_CPU_IO_PROTOCOL_WIDTH) (Width & 0x03);\r
806bf4f2 135 if (!MmioOperation && (Width == EfiCpuIoWidthUint64)) {\r
136 return EFI_INVALID_PARAMETER;\r
137 }\r
138 \r
7a7f916a 139 //\r
6b9ddb42 140 // Check to see if Address is aligned\r
7a7f916a 141 //\r
142 if ((Address & (UINT64)(mInStride[Width] - 1)) != 0) {\r
143 return EFI_UNSUPPORTED;\r
144 }\r
145\r
806bf4f2 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
6b9ddb42 156 // check must be adjusted to avoid all overflow conditions.\r
806bf4f2 157 // \r
6b9ddb42 158 // The following form of the range check is equivalent but assumes that \r
806bf4f2 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
165 }\r
166 } else { \r
167 MaxCount = RShiftU64 (Limit, Width);\r
168 if (MaxCount < (Count - 1)) {\r
169 return EFI_UNSUPPORTED;\r
170 }\r
171 if (Address > LShiftU64 (MaxCount - Count + 1, Width)) {\r
172 return EFI_UNSUPPORTED;\r
173 }\r
174 }\r
7a7f916a 175\r
806bf4f2 176 //\r
6b9ddb42 177 // Check to see if Buffer is aligned\r
20f6ac14 178 // (IA-32 allows UINT64 and INT64 data types to be 32-bit aligned.)\r
806bf4f2 179 //\r
20f6ac14 180 if (((UINTN)Buffer & ((MIN (sizeof (UINTN), mInStride[Width]) - 1))) != 0) {\r
806bf4f2 181 return EFI_UNSUPPORTED;\r
182 }\r
183\r
184 return EFI_SUCCESS;\r
185}\r
186\r
187/**\r
188 Reads memory-mapped registers.\r
189\r
7a7f916a 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_IO_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
806bf4f2 224\r
225**/\r
226EFI_STATUS\r
227EFIAPI\r
228CpuMemoryServiceRead (\r
229 IN EFI_CPU_IO_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
234 )\r
235{\r
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
241\r
242 Status = CpuIoCheckParameter (TRUE, Width, Address, Count, Buffer);\r
243 if (EFI_ERROR (Status)) {\r
244 return Status;\r
245 }\r
246\r
247 //\r
248 // Select loop based on the width of the transfer\r
249 //\r
250 InStride = mInStride[Width];\r
251 OutStride = mOutStride[Width];\r
6b9ddb42 252 OperationWidth = (EFI_CPU_IO_PROTOCOL_WIDTH) (Width & 0x03);\r
806bf4f2 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
263 }\r
264 return EFI_SUCCESS;\r
265}\r
266\r
267/**\r
268 Writes memory-mapped registers.\r
269\r
7a7f916a 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_IO_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
806bf4f2 304\r
305**/\r
306EFI_STATUS\r
307EFIAPI\r
308CpuMemoryServiceWrite (\r
309 IN EFI_CPU_IO_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
314 )\r
315{\r
316 EFI_STATUS Status;\r
317 UINT8 InStride;\r
318 UINT8 OutStride;\r
319 EFI_CPU_IO_PROTOCOL_WIDTH OperationWidth;\r
320 UINT8 *Uint8Buffer;\r
321\r
322 Status = CpuIoCheckParameter (TRUE, Width, Address, Count, Buffer);\r
323 if (EFI_ERROR (Status)) {\r
324 return Status;\r
325 }\r
326\r
327 //\r
328 // Select loop based on the width of the transfer\r
329 //\r
330 InStride = mInStride[Width];\r
331 OutStride = mOutStride[Width];\r
6b9ddb42 332 OperationWidth = (EFI_CPU_IO_PROTOCOL_WIDTH) (Width & 0x03);\r
806bf4f2 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
343 }\r
344 return EFI_SUCCESS;\r
345}\r
346\r
347/**\r
348 Reads I/O registers.\r
349\r
7a7f916a 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_IO_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
806bf4f2 384\r
385**/\r
386EFI_STATUS\r
387EFIAPI\r
388CpuIoServiceRead (\r
389 IN EFI_CPU_IO_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
394 )\r
395{\r
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
401\r
402 Status = CpuIoCheckParameter (FALSE, Width, Address, Count, Buffer);\r
403 if (EFI_ERROR (Status)) {\r
404 return Status;\r
405 }\r
406\r
407 //\r
408 // Select loop based on the width of the transfer\r
409 //\r
410 InStride = mInStride[Width];\r
411 OutStride = mOutStride[Width];\r
6b9ddb42 412 OperationWidth = (EFI_CPU_IO_PROTOCOL_WIDTH) (Width & 0x03);\r
806bf4f2 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
420 }\r
421 }\r
422\r
423 return EFI_SUCCESS;\r
424}\r
425\r
426/**\r
427 Write I/O registers.\r
428\r
7a7f916a 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_IO_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
806bf4f2 464**/\r
465EFI_STATUS\r
466EFIAPI\r
467CpuIoServiceWrite (\r
468 IN EFI_CPU_IO_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
473 )\r
474{\r
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
480\r
481 //\r
482 // Make sure the parameters are valid\r
483 //\r
484 Status = CpuIoCheckParameter (FALSE, Width, Address, Count, Buffer);\r
485 if (EFI_ERROR (Status)) {\r
486 return Status;\r
487 }\r
488\r
489 //\r
490 // Select loop based on the width of the transfer\r
491 //\r
492 InStride = mInStride[Width];\r
493 OutStride = mOutStride[Width];\r
6b9ddb42 494 OperationWidth = (EFI_CPU_IO_PROTOCOL_WIDTH) (Width & 0x03);\r
806bf4f2 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
502 }\r
503 }\r
504 \r
505 return EFI_SUCCESS;\r
506}\r
507\r
508/**\r
509 The user Entry Point for module CpuIo. 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
513 \r
514 @retval EFI_SUCCESS The entry point is executed successfully.\r
515 @retval other Some error occurs when executing this entry point.\r
516\r
517**/\r
518EFI_STATUS\r
519EFIAPI\r
520CpuIoInitialize (\r
521 IN EFI_HANDLE ImageHandle,\r
522 IN EFI_SYSTEM_TABLE *SystemTable\r
523 )\r
524{\r
525 EFI_STATUS Status;\r
526\r
527 ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gEfiCpuIoProtocolGuid);\r
528 Status = gBS->InstallMultipleProtocolInterfaces (\r
529 &mHandle,\r
530 &gEfiCpuIoProtocolGuid, &mCpuIo,\r
531 NULL\r
532 );\r
533 ASSERT_EFI_ERROR (Status);\r
534\r
535 return Status;\r
536}\r