Update the copyright notice format
[mirror_edk2.git] / UefiCpuPkg / CpuIoPei / CpuIoPei.c
CommitLineData
e643315b 1/** @file\r
2 Produces the CPU I/O PPI.\r
3\r
01a1c0fc
HT
4Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>\r
5This program and the accompanying materials \r
e643315b 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
15#include <PiDxe.h>\r
16\r
17#include <Ppi/CpuIo.h>\r
18\r
19#include <Library/BaseLib.h>\r
20#include <Library/DebugLib.h>\r
21#include <Library/IoLib.h>\r
22#include <Library/PeiServicesLib.h>\r
23\r
24#define MAX_IO_PORT_ADDRESS 0xFFFF\r
25\r
26//\r
27// Function Prototypes\r
28//\r
29EFI_STATUS\r
30EFIAPI\r
31CpuMemoryServiceRead (\r
32 IN CONST EFI_PEI_SERVICES **PeiServices,\r
33 IN CONST EFI_PEI_CPU_IO_PPI *This,\r
34 IN EFI_PEI_CPU_IO_PPI_WIDTH Width,\r
35 IN UINT64 Address,\r
36 IN UINTN Count,\r
37 OUT VOID *Buffer\r
38 );\r
39\r
40EFI_STATUS\r
41EFIAPI\r
42CpuMemoryServiceWrite (\r
43 IN CONST EFI_PEI_SERVICES **PeiServices,\r
44 IN CONST EFI_PEI_CPU_IO_PPI *This,\r
45 IN EFI_PEI_CPU_IO_PPI_WIDTH Width,\r
46 IN UINT64 Address,\r
47 IN UINTN Count,\r
48 IN VOID *Buffer\r
49 );\r
50\r
51EFI_STATUS\r
52EFIAPI\r
53CpuIoServiceRead (\r
54 IN CONST EFI_PEI_SERVICES **PeiServices,\r
55 IN CONST EFI_PEI_CPU_IO_PPI *This,\r
56 IN EFI_PEI_CPU_IO_PPI_WIDTH Width,\r
57 IN UINT64 Address,\r
58 IN UINTN Count,\r
59 OUT VOID *Buffer\r
60 );\r
61\r
62EFI_STATUS\r
63EFIAPI\r
64CpuIoServiceWrite (\r
65 IN CONST EFI_PEI_SERVICES **PeiServices,\r
66 IN CONST EFI_PEI_CPU_IO_PPI *This,\r
67 IN EFI_PEI_CPU_IO_PPI_WIDTH Width,\r
68 IN UINT64 Address,\r
69 IN UINTN Count,\r
70 IN VOID *Buffer\r
71 );\r
72\r
73UINT8\r
74EFIAPI\r
75CpuIoRead8 (\r
76 IN CONST EFI_PEI_SERVICES **PeiServices,\r
77 IN CONST EFI_PEI_CPU_IO_PPI *This,\r
78 IN UINT64 Address\r
79 );\r
80\r
81UINT16\r
82EFIAPI\r
83CpuIoRead16 (\r
84 IN CONST EFI_PEI_SERVICES **PeiServices,\r
85 IN CONST EFI_PEI_CPU_IO_PPI *This,\r
86 IN UINT64 Address\r
87 );\r
88\r
89UINT32\r
90EFIAPI\r
91CpuIoRead32 (\r
92 IN CONST EFI_PEI_SERVICES **PeiServices,\r
93 IN CONST EFI_PEI_CPU_IO_PPI *This,\r
94 IN UINT64 Address\r
95 );\r
96\r
97UINT64\r
98EFIAPI\r
99CpuIoRead64 (\r
100 IN CONST EFI_PEI_SERVICES **PeiServices,\r
101 IN CONST EFI_PEI_CPU_IO_PPI *This,\r
102 IN UINT64 Address\r
103 );\r
104\r
105VOID\r
106EFIAPI\r
107CpuIoWrite8 (\r
108 IN CONST EFI_PEI_SERVICES **PeiServices,\r
109 IN CONST EFI_PEI_CPU_IO_PPI *This,\r
110 IN UINT64 Address,\r
111 IN UINT8 Data\r
112 );\r
113\r
114VOID\r
115EFIAPI\r
116CpuIoWrite16 (\r
117 IN CONST EFI_PEI_SERVICES **PeiServices,\r
118 IN CONST EFI_PEI_CPU_IO_PPI *This,\r
119 IN UINT64 Address,\r
120 IN UINT16 Data\r
121 );\r
122\r
123VOID\r
124EFIAPI\r
125CpuIoWrite32 (\r
126 IN CONST EFI_PEI_SERVICES **PeiServices,\r
127 IN CONST EFI_PEI_CPU_IO_PPI *This,\r
128 IN UINT64 Address,\r
129 IN UINT32 Data\r
130 );\r
131\r
132VOID\r
133EFIAPI\r
134CpuIoWrite64 (\r
135 IN CONST EFI_PEI_SERVICES **PeiServices,\r
136 IN CONST EFI_PEI_CPU_IO_PPI *This,\r
137 IN UINT64 Address,\r
138 IN UINT64 Data\r
139 );\r
140\r
141UINT8\r
142EFIAPI\r
143CpuMemRead8 (\r
144 IN CONST EFI_PEI_SERVICES **PeiServices,\r
145 IN CONST EFI_PEI_CPU_IO_PPI *This,\r
146 IN UINT64 Address\r
147 );\r
148\r
149UINT16\r
150EFIAPI\r
151CpuMemRead16 (\r
152 IN CONST EFI_PEI_SERVICES **PeiServices,\r
153 IN CONST EFI_PEI_CPU_IO_PPI *This,\r
154 IN UINT64 Address\r
155 );\r
156\r
157UINT32\r
158EFIAPI\r
159CpuMemRead32 (\r
160 IN CONST EFI_PEI_SERVICES **PeiServices,\r
161 IN CONST EFI_PEI_CPU_IO_PPI *This,\r
162 IN UINT64 Address\r
163 );\r
164\r
165UINT64\r
166EFIAPI\r
167CpuMemRead64 (\r
168 IN CONST EFI_PEI_SERVICES **PeiServices,\r
169 IN CONST EFI_PEI_CPU_IO_PPI *This,\r
170 IN UINT64 Address\r
171 );\r
172\r
173VOID\r
174EFIAPI\r
175CpuMemWrite8 (\r
176 IN CONST EFI_PEI_SERVICES **PeiServices,\r
177 IN CONST EFI_PEI_CPU_IO_PPI *This,\r
178 IN UINT64 Address,\r
179 IN UINT8 Data\r
180 );\r
181\r
182VOID\r
183EFIAPI\r
184CpuMemWrite16 (\r
185 IN CONST EFI_PEI_SERVICES **PeiServices,\r
186 IN CONST EFI_PEI_CPU_IO_PPI *This,\r
187 IN UINT64 Address,\r
188 IN UINT16 Data\r
189 );\r
190\r
191VOID\r
192EFIAPI\r
193CpuMemWrite32 (\r
194 IN CONST EFI_PEI_SERVICES **PeiServices,\r
195 IN CONST EFI_PEI_CPU_IO_PPI *This,\r
196 IN UINT64 Address,\r
197 IN UINT32 Data\r
198 );\r
199\r
200VOID\r
201EFIAPI\r
202CpuMemWrite64 (\r
203 IN CONST EFI_PEI_SERVICES **PeiServices,\r
204 IN CONST EFI_PEI_CPU_IO_PPI *This,\r
205 IN UINT64 Address,\r
206 IN UINT64 Data\r
207 );\r
208 \r
209//\r
210// Instance of CPU I/O PPI\r
211//\r
212EFI_PEI_CPU_IO_PPI gCpuIoPpi = {\r
213 {\r
214 CpuMemoryServiceRead,\r
215 CpuMemoryServiceWrite\r
216 },\r
217 {\r
218 CpuIoServiceRead,\r
219 CpuIoServiceWrite\r
220 },\r
221 CpuIoRead8,\r
222 CpuIoRead16,\r
223 CpuIoRead32,\r
224 CpuIoRead64,\r
225 CpuIoWrite8,\r
226 CpuIoWrite16,\r
227 CpuIoWrite32,\r
228 CpuIoWrite64,\r
229 CpuMemRead8,\r
230 CpuMemRead16,\r
231 CpuMemRead32,\r
232 CpuMemRead64,\r
233 CpuMemWrite8,\r
234 CpuMemWrite16,\r
235 CpuMemWrite32,\r
236 CpuMemWrite64\r
237};\r
238\r
239//\r
240// PPI Descriptor used to install the CPU I/O PPI\r
241//\r
242EFI_PEI_PPI_DESCRIPTOR gPpiList = {\r
243 (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),\r
244 &gEfiPeiCpuIoPpiInstalledGuid,\r
245 NULL\r
246};\r
247 \r
248//\r
249// Lookup table for increment values based on transfer widths\r
250//\r
251UINT8 mInStride[] = {\r
252 1, // EfiPeiCpuIoWidthUint8\r
253 2, // EfiPeiCpuIoWidthUint16\r
254 4, // EfiPeiCpuIoWidthUint32\r
255 8, // EfiPeiCpuIoWidthUint64\r
256 0, // EfiPeiCpuIoWidthFifoUint8\r
257 0, // EfiPeiCpuIoWidthFifoUint16\r
258 0, // EfiPeiCpuIoWidthFifoUint32\r
259 0, // EfiPeiCpuIoWidthFifoUint64\r
260 1, // EfiPeiCpuIoWidthFillUint8\r
261 2, // EfiPeiCpuIoWidthFillUint16\r
262 4, // EfiPeiCpuIoWidthFillUint32\r
263 8 // EfiPeiCpuIoWidthFillUint64\r
264};\r
265\r
266//\r
267// Lookup table for increment values based on transfer widths\r
268//\r
269UINT8 mOutStride[] = {\r
270 1, // EfiPeiCpuIoWidthUint8\r
271 2, // EfiPeiCpuIoWidthUint16\r
272 4, // EfiPeiCpuIoWidthUint32\r
273 8, // EfiPeiCpuIoWidthUint64\r
274 1, // EfiPeiCpuIoWidthFifoUint8\r
275 2, // EfiPeiCpuIoWidthFifoUint16\r
276 4, // EfiPeiCpuIoWidthFifoUint32\r
277 8, // EfiPeiCpuIoWidthFifoUint64\r
278 0, // EfiPeiCpuIoWidthFillUint8\r
279 0, // EfiPeiCpuIoWidthFillUint16\r
280 0, // EfiPeiCpuIoWidthFillUint32\r
281 0 // EfiPeiCpuIoWidthFillUint64\r
282};\r
283\r
284/**\r
285 Check parameters to a CPU I/O PPI service request.\r
286\r
287 @param[in] MmioOperation TRUE for an MMIO operation, FALSE for I/O Port operation.\r
288 @param[in] Width The width of the access. Enumerated in bytes.\r
289 @param[in] Address The physical address of the access.\r
290 @param[in] Count The number of accesses to perform.\r
291 @param[in] Buffer A pointer to the buffer of data.\r
292\r
293 @retval EFI_SUCCESS The parameters for this request pass the checks.\r
294 @retval EFI_INVALID_PARAMETER Width is invalid for this EFI system.\r
295 @retval EFI_INVALID_PARAMETER Buffer is NULL.\r
296 @retval EFI_UNSUPPORTED The address range specified by Address, Width, \r
297 and Count is not valid for this EFI system.\r
298 \r
299**/\r
300EFI_STATUS\r
301CpuIoCheckParameter (\r
302 IN BOOLEAN MmioOperation,\r
303 IN EFI_PEI_CPU_IO_PPI_WIDTH Width,\r
304 IN UINT64 Address,\r
305 IN UINTN Count,\r
306 IN VOID *Buffer\r
307 )\r
308{\r
309 UINT64 MaxCount;\r
310 UINT64 Limit;\r
311\r
312 //\r
313 // Check to see if Buffer is NULL\r
314 //\r
315 if (Buffer == NULL) {\r
316 return EFI_INVALID_PARAMETER;\r
317 }\r
318\r
319 //\r
320 // Check to see if Width is in the valid range\r
321 //\r
322 if (Width < 0 || Width >= EfiPeiCpuIoWidthMaximum) {\r
323 return EFI_INVALID_PARAMETER;\r
324 }\r
325\r
326 //\r
327 // For FIFO type, the target address won't increase during the access,\r
328 // so treat Count as 1\r
329 //\r
330 if (Width >= EfiPeiCpuIoWidthFifoUint8 && Width <= EfiPeiCpuIoWidthFifoUint64) {\r
331 Count = 1;\r
332 }\r
333\r
334 //\r
335 // Check to see if Width is in the valid range for I/O Port operations\r
336 //\r
311004b2 337 Width = (EFI_PEI_CPU_IO_PPI_WIDTH) (Width & 0x03);\r
e643315b 338 if (!MmioOperation && (Width == EfiPeiCpuIoWidthUint64)) {\r
339 return EFI_INVALID_PARAMETER;\r
340 }\r
341 \r
342 //\r
343 // Check to see if any address associated with this transfer exceeds the maximum \r
344 // allowed address. The maximum address implied by the parameters passed in is\r
345 // Address + Size * Count. If the following condition is met, then the transfer\r
346 // is not supported.\r
347 //\r
348 // Address + Size * Count > (MmioOperation ? MAX_ADDRESS : MAX_IO_PORT_ADDRESS) + 1\r
349 //\r
350 // Since MAX_ADDRESS can be the maximum integer value supported by the CPU and Count \r
351 // can also be the maximum integer value supported by the CPU, this range\r
311004b2 352 // check must be adjusted to avoid all overflow conditions.\r
e643315b 353 // \r
311004b2 354 // The following form of the range check is equivalent but assumes that \r
e643315b 355 // MAX_ADDRESS and MAX_IO_PORT_ADDRESS are of the form (2^n - 1).\r
356 //\r
357 Limit = (MmioOperation ? MAX_ADDRESS : MAX_IO_PORT_ADDRESS);\r
358 if (Count == 0) {\r
359 if (Address > Limit) {\r
360 return EFI_UNSUPPORTED;\r
361 }\r
362 } else { \r
363 MaxCount = RShiftU64 (Limit, Width);\r
364 if (MaxCount < (Count - 1)) {\r
365 return EFI_UNSUPPORTED;\r
366 }\r
367 if (Address > LShiftU64 (MaxCount - Count + 1, Width)) {\r
368 return EFI_UNSUPPORTED;\r
369 }\r
370 }\r
371 \r
372 return EFI_SUCCESS;\r
373}\r
374\r
375/**\r
376 Reads memory-mapped registers.\r
377\r
378 @param[in] PeiServices An indirect pointer to the PEI Services Table\r
379 published by the PEI Foundation.\r
380 @param[in] This Pointer to local data for the interface.\r
381 @param[in] Width The width of the access. Enumerated in bytes.\r
382 @param[in] Address The physical address of the access.\r
383 @param[in] Count The number of accesses to perform.\r
384 @param[out] Buffer A pointer to the buffer of data.\r
385\r
386 @retval EFI_SUCCESS The function completed successfully.\r
387 @retval EFI_INVALID_PARAMETER Width is invalid for this EFI system.\r
388 @retval EFI_INVALID_PARAMETER Buffer is NULL.\r
389 @retval EFI_UNSUPPORTED The address range specified by Address, Width, \r
390 and Count is not valid for this EFI system.\r
391\r
392**/\r
393EFI_STATUS\r
394EFIAPI\r
395CpuMemoryServiceRead (\r
396 IN CONST EFI_PEI_SERVICES **PeiServices,\r
397 IN CONST EFI_PEI_CPU_IO_PPI *This,\r
398 IN EFI_PEI_CPU_IO_PPI_WIDTH Width,\r
399 IN UINT64 Address,\r
400 IN UINTN Count,\r
401 OUT VOID *Buffer\r
402 )\r
403{\r
404 EFI_STATUS Status;\r
405 UINT8 InStride;\r
406 UINT8 OutStride;\r
407 EFI_PEI_CPU_IO_PPI_WIDTH OperationWidth;\r
408 BOOLEAN Aligned;\r
409 UINT8 *Uint8Buffer;\r
410\r
411 Status = CpuIoCheckParameter (TRUE, Width, Address, Count, Buffer);\r
412 if (EFI_ERROR (Status)) {\r
413 return Status;\r
414 }\r
415\r
416 //\r
417 // Select loop based on the width of the transfer\r
418 //\r
419 InStride = mInStride[Width];\r
420 OutStride = mOutStride[Width];\r
311004b2 421 OperationWidth = (EFI_PEI_CPU_IO_PPI_WIDTH) (Width & 0x03);\r
e643315b 422 Aligned = (BOOLEAN)(((UINTN)Buffer & (mInStride[OperationWidth] - 1)) == 0x00);\r
423 for (Uint8Buffer = Buffer; Count > 0; Address += InStride, Uint8Buffer += OutStride, Count--) {\r
424 if (OperationWidth == EfiPeiCpuIoWidthUint8) {\r
425 *Uint8Buffer = MmioRead8 ((UINTN)Address);\r
426 } else if (OperationWidth == EfiPeiCpuIoWidthUint16) {\r
427 if (Aligned) {\r
428 *((UINT16 *)Uint8Buffer) = MmioRead16 ((UINTN)Address);\r
429 } else {\r
430 WriteUnaligned16 ((UINT16 *)Uint8Buffer, MmioRead16 ((UINTN)Address));\r
431 }\r
432 } else if (OperationWidth == EfiPeiCpuIoWidthUint32) {\r
433 if (Aligned) {\r
434 *((UINT32 *)Uint8Buffer) = MmioRead32 ((UINTN)Address);\r
435 } else {\r
436 WriteUnaligned32 ((UINT32 *)Uint8Buffer, MmioRead32 ((UINTN)Address));\r
437 }\r
438 } else if (OperationWidth == EfiPeiCpuIoWidthUint64) {\r
439 if (Aligned) {\r
440 *((UINT64 *)Uint8Buffer) = MmioRead64 ((UINTN)Address);\r
441 } else {\r
442 WriteUnaligned64 ((UINT64 *)Uint8Buffer, MmioRead64 ((UINTN)Address));\r
443 }\r
444 }\r
445 }\r
446 return EFI_SUCCESS;\r
447}\r
448\r
449/**\r
450 Writes memory-mapped registers.\r
451\r
452 @param[in] PeiServices An indirect pointer to the PEI Services Table\r
453 published by the PEI Foundation.\r
454 @param[in] This Pointer to local data for the interface.\r
455 @param[in] Width The width of the access. Enumerated in bytes.\r
456 @param[in] Address The physical address of the access.\r
457 @param[in] Count The number of accesses to perform.\r
458 @param[in] Buffer A pointer to the buffer of data.\r
459\r
460 @retval EFI_SUCCESS The function completed successfully.\r
461 @retval EFI_INVALID_PARAMETER Width is invalid for this EFI system.\r
462 @retval EFI_INVALID_PARAMETER Buffer is NULL.\r
463 @retval EFI_UNSUPPORTED The address range specified by Address, Width, \r
464 and Count is not valid for this EFI system.\r
465\r
466**/\r
467EFI_STATUS\r
468EFIAPI\r
469CpuMemoryServiceWrite (\r
470 IN CONST EFI_PEI_SERVICES **PeiServices,\r
471 IN CONST EFI_PEI_CPU_IO_PPI *This,\r
472 IN EFI_PEI_CPU_IO_PPI_WIDTH Width,\r
473 IN UINT64 Address,\r
474 IN UINTN Count,\r
475 IN VOID *Buffer\r
476 )\r
477{\r
478 EFI_STATUS Status;\r
479 UINT8 InStride;\r
480 UINT8 OutStride;\r
481 EFI_PEI_CPU_IO_PPI_WIDTH OperationWidth;\r
482 BOOLEAN Aligned;\r
483 UINT8 *Uint8Buffer;\r
484\r
485 Status = CpuIoCheckParameter (TRUE, Width, Address, Count, Buffer);\r
486 if (EFI_ERROR (Status)) {\r
487 return Status;\r
488 }\r
489\r
490 //\r
491 // Select loop based on the width of the transfer\r
492 //\r
493 InStride = mInStride[Width];\r
494 OutStride = mOutStride[Width];\r
311004b2 495 OperationWidth = (EFI_PEI_CPU_IO_PPI_WIDTH) (Width & 0x03);\r
e643315b 496 Aligned = (BOOLEAN)(((UINTN)Buffer & (mInStride[OperationWidth] - 1)) == 0x00);\r
497 for (Uint8Buffer = Buffer; Count > 0; Address += InStride, Uint8Buffer += OutStride, Count--) {\r
498 if (OperationWidth == EfiPeiCpuIoWidthUint8) {\r
499 MmioWrite8 ((UINTN)Address, *Uint8Buffer);\r
500 } else if (OperationWidth == EfiPeiCpuIoWidthUint16) {\r
501 if (Aligned) {\r
502 MmioWrite16 ((UINTN)Address, *((UINT16 *)Uint8Buffer));\r
503 } else {\r
504 MmioWrite16 ((UINTN)Address, ReadUnaligned16 ((UINT16 *)Uint8Buffer));\r
505 }\r
506 } else if (OperationWidth == EfiPeiCpuIoWidthUint32) {\r
507 if (Aligned) {\r
508 MmioWrite32 ((UINTN)Address, *((UINT32 *)Uint8Buffer));\r
509 } else {\r
510 MmioWrite32 ((UINTN)Address, ReadUnaligned32 ((UINT32 *)Uint8Buffer));\r
511 }\r
512 } else if (OperationWidth == EfiPeiCpuIoWidthUint64) {\r
513 if (Aligned) {\r
514 MmioWrite64 ((UINTN)Address, *((UINT64 *)Uint8Buffer));\r
515 } else {\r
516 MmioWrite64 ((UINTN)Address, ReadUnaligned64 ((UINT64 *)Uint8Buffer));\r
517 }\r
518 }\r
519 }\r
520 return EFI_SUCCESS;\r
521}\r
522\r
523/**\r
524 Reads I/O registers.\r
525\r
526 @param[in] PeiServices An indirect pointer to the PEI Services Table\r
527 published by the PEI Foundation.\r
528 @param[in] This Pointer to local data for the interface.\r
529 @param[in] Width The width of the access. Enumerated in bytes.\r
530 @param[in] Address The physical address of the access.\r
531 @param[in] Count The number of accesses to perform.\r
532 @param[out] Buffer A pointer to the buffer of data.\r
533\r
534 @retval EFI_SUCCESS The function completed successfully.\r
535 @retval EFI_INVALID_PARAMETER Width is invalid for this EFI system.\r
536 @retval EFI_INVALID_PARAMETER Buffer is NULL.\r
537 @retval EFI_UNSUPPORTED The address range specified by Address, Width, \r
538 and Count is not valid for this EFI system.\r
539\r
540**/\r
541EFI_STATUS\r
542EFIAPI\r
543CpuIoServiceRead (\r
544 IN CONST EFI_PEI_SERVICES **PeiServices,\r
545 IN CONST EFI_PEI_CPU_IO_PPI *This,\r
546 IN EFI_PEI_CPU_IO_PPI_WIDTH Width,\r
547 IN UINT64 Address,\r
548 IN UINTN Count,\r
549 OUT VOID *Buffer\r
550 )\r
551{\r
552 EFI_STATUS Status;\r
553 UINT8 InStride;\r
554 UINT8 OutStride;\r
555 EFI_PEI_CPU_IO_PPI_WIDTH OperationWidth;\r
556 BOOLEAN Aligned;\r
557 UINT8 *Uint8Buffer;\r
558\r
559 Status = CpuIoCheckParameter (FALSE, Width, Address, Count, Buffer);\r
560 if (EFI_ERROR (Status)) {\r
561 return Status;\r
562 }\r
563\r
564 //\r
565 // Select loop based on the width of the transfer\r
566 //\r
567 InStride = mInStride[Width];\r
568 OutStride = mOutStride[Width];\r
311004b2 569 OperationWidth = (EFI_PEI_CPU_IO_PPI_WIDTH) (Width & 0x03);\r
e643315b 570 Aligned = (BOOLEAN)(((UINTN)Buffer & (mInStride[OperationWidth] - 1)) == 0x00);\r
571 for (Uint8Buffer = Buffer; Count > 0; Address += InStride, Uint8Buffer += OutStride, Count--) {\r
572 if (OperationWidth == EfiPeiCpuIoWidthUint8) {\r
573 *Uint8Buffer = IoRead8 ((UINTN)Address);\r
574 } else if (OperationWidth == EfiPeiCpuIoWidthUint16) {\r
575 if (Aligned) {\r
576 *((UINT16 *)Uint8Buffer) = IoRead16 ((UINTN)Address);\r
577 } else {\r
578 WriteUnaligned16 ((UINT16 *)Uint8Buffer, IoRead16 ((UINTN)Address));\r
579 }\r
580 } else if (OperationWidth == EfiPeiCpuIoWidthUint32) {\r
581 if (Aligned) {\r
582 *((UINT32 *)Uint8Buffer) = IoRead32 ((UINTN)Address);\r
583 } else {\r
584 WriteUnaligned32 ((UINT32 *)Uint8Buffer, IoRead32 ((UINTN)Address));\r
585 }\r
586 }\r
587 }\r
588\r
589 return EFI_SUCCESS;\r
590}\r
591\r
592/**\r
593 Write I/O registers.\r
594\r
595 @param[in] PeiServices An indirect pointer to the PEI Services Table\r
596 published by the PEI Foundation.\r
597 @param[in] This Pointer to local data for the interface.\r
598 @param[in] Width The width of the access. Enumerated in bytes.\r
599 @param[in] Address The physical address of the access.\r
600 @param[in] Count The number of accesses to perform.\r
601 @param[in] Buffer A pointer to the buffer of data.\r
602\r
603 @retval EFI_SUCCESS The function completed successfully.\r
604 @retval EFI_INVALID_PARAMETER Width is invalid for this EFI system.\r
605 @retval EFI_INVALID_PARAMETER Buffer is NULL.\r
606 @retval EFI_UNSUPPORTED The address range specified by Address, Width, \r
607 and Count is not valid for this EFI system.\r
608\r
609**/\r
610EFI_STATUS\r
611EFIAPI\r
612CpuIoServiceWrite (\r
613 IN CONST EFI_PEI_SERVICES **PeiServices,\r
614 IN CONST EFI_PEI_CPU_IO_PPI *This,\r
615 IN EFI_PEI_CPU_IO_PPI_WIDTH Width,\r
616 IN UINT64 Address,\r
617 IN UINTN Count,\r
618 IN VOID *Buffer\r
619 )\r
620{\r
621 EFI_STATUS Status;\r
622 UINT8 InStride;\r
623 UINT8 OutStride;\r
624 EFI_PEI_CPU_IO_PPI_WIDTH OperationWidth;\r
625 BOOLEAN Aligned;\r
626 UINT8 *Uint8Buffer;\r
627\r
628 //\r
629 // Make sure the parameters are valid\r
630 //\r
631 Status = CpuIoCheckParameter (FALSE, Width, Address, Count, Buffer);\r
632 if (EFI_ERROR (Status)) {\r
633 return Status;\r
634 }\r
635\r
636 //\r
637 // Select loop based on the width of the transfer\r
638 //\r
639 InStride = mInStride[Width];\r
640 OutStride = mOutStride[Width];\r
311004b2 641 OperationWidth = (EFI_PEI_CPU_IO_PPI_WIDTH) (Width & 0x03);\r
e643315b 642 Aligned = (BOOLEAN)(((UINTN)Buffer & (mInStride[OperationWidth] - 1)) == 0x00);\r
643 for (Uint8Buffer = (UINT8 *)Buffer; Count > 0; Address += InStride, Uint8Buffer += OutStride, Count--) {\r
644 if (OperationWidth == EfiPeiCpuIoWidthUint8) {\r
645 IoWrite8 ((UINTN)Address, *Uint8Buffer);\r
646 } else if (OperationWidth == EfiPeiCpuIoWidthUint16) {\r
647 if (Aligned) {\r
648 IoWrite16 ((UINTN)Address, *((UINT16 *)Uint8Buffer));\r
649 } else {\r
650 IoWrite16 ((UINTN)Address, ReadUnaligned16 ((UINT16 *)Uint8Buffer));\r
651 }\r
652 } else if (OperationWidth == EfiPeiCpuIoWidthUint32) {\r
653 if (Aligned) {\r
654 IoWrite32 ((UINTN)Address, *((UINT32 *)Uint8Buffer));\r
655 } else {\r
656 IoWrite32 ((UINTN)Address, ReadUnaligned32 ((UINT32 *)Uint8Buffer));\r
657 }\r
658 }\r
659 }\r
660 \r
661 return EFI_SUCCESS;\r
662}\r
663\r
664/**\r
665 8-bit I/O read operations.\r
666\r
667 @param[in] PeiServices An indirect pointer to the PEI Services Table published \r
668 by the PEI Foundation.\r
669 @param[in] This Pointer to local data for the interface.\r
670 @param[in] Address The physical address of the access.\r
671\r
672 @return An 8-bit value returned from the I/O space.\r
673**/\r
674UINT8\r
675EFIAPI\r
676CpuIoRead8 (\r
677 IN CONST EFI_PEI_SERVICES **PeiServices,\r
678 IN CONST EFI_PEI_CPU_IO_PPI *This,\r
679 IN UINT64 Address\r
680 )\r
681{\r
682 return IoRead8 ((UINTN)Address);\r
683}\r
684\r
685/**\r
686 16-bit I/O read operations.\r
687\r
688 @param[in] PeiServices An indirect pointer to the PEI Services Table published \r
689 by the PEI Foundation.\r
690 @param[in] This Pointer to local data for the interface.\r
691 @param[in] Address The physical address of the access.\r
692\r
693 @return A 16-bit value returned from the I/O space.\r
694\r
695**/\r
696UINT16\r
697EFIAPI\r
698CpuIoRead16 (\r
699 IN CONST EFI_PEI_SERVICES **PeiServices,\r
700 IN CONST EFI_PEI_CPU_IO_PPI *This,\r
701 IN UINT64 Address\r
702 )\r
703{\r
704 return IoRead16 ((UINTN)Address);\r
705}\r
706\r
707/**\r
708 32-bit I/O read operations.\r
709\r
710 @param[in] PeiServices An indirect pointer to the PEI Services Table published \r
711 by the PEI Foundation.\r
712 @param[in] This Pointer to local data for the interface.\r
713 @param[in] Address The physical address of the access.\r
714\r
715 @return A 32-bit value returned from the I/O space.\r
716\r
717**/\r
718UINT32\r
719EFIAPI\r
720CpuIoRead32 (\r
721 IN CONST EFI_PEI_SERVICES **PeiServices,\r
722 IN CONST EFI_PEI_CPU_IO_PPI *This,\r
723 IN UINT64 Address\r
724 )\r
725{\r
726 return IoRead32 ((UINTN)Address);\r
727}\r
728\r
729/**\r
730 64-bit I/O read operations.\r
731\r
732 @param[in] PeiServices An indirect pointer to the PEI Services Table published \r
733 by the PEI Foundation.\r
734 @param[in] This Pointer to local data for the interface.\r
735 @param[in] Address The physical address of the access.\r
736\r
737 @return A 64-bit value returned from the I/O space.\r
738\r
739**/\r
740UINT64\r
741EFIAPI\r
742CpuIoRead64 (\r
743 IN CONST EFI_PEI_SERVICES **PeiServices,\r
744 IN CONST EFI_PEI_CPU_IO_PPI *This,\r
745 IN UINT64 Address\r
746 )\r
747{\r
748 return IoRead64 ((UINTN)Address);\r
749}\r
750\r
751/**\r
752 8-bit I/O write operations.\r
753\r
754 @param[in] PeiServices An indirect pointer to the PEI Services Table published \r
755 by the PEI Foundation.\r
756 @param[in] This Pointer to local data for the interface.\r
757 @param[in] Address The physical address of the access.\r
758 @param[in] Data The data to write.\r
759\r
760**/\r
761VOID\r
762EFIAPI\r
763CpuIoWrite8 (\r
764 IN CONST EFI_PEI_SERVICES **PeiServices,\r
765 IN CONST EFI_PEI_CPU_IO_PPI *This,\r
766 IN UINT64 Address,\r
767 IN UINT8 Data\r
768 )\r
769{\r
770 IoWrite8 ((UINTN)Address, Data);\r
771}\r
772\r
773/**\r
774 16-bit I/O write operations.\r
775\r
776 @param[in] PeiServices An indirect pointer to the PEI Services Table published \r
777 by the PEI Foundation.\r
778 @param[in] This Pointer to local data for the interface.\r
779 @param[in] Address The physical address of the access.\r
780 @param[in] Data The data to write.\r
781\r
782**/\r
783VOID\r
784EFIAPI\r
785CpuIoWrite16 (\r
786 IN CONST EFI_PEI_SERVICES **PeiServices,\r
787 IN CONST EFI_PEI_CPU_IO_PPI *This,\r
788 IN UINT64 Address,\r
789 IN UINT16 Data\r
790 )\r
791{\r
792 IoWrite16 ((UINTN)Address, Data);\r
793}\r
794\r
795/**\r
796 32-bit I/O write operations.\r
797\r
798 @param[in] PeiServices An indirect pointer to the PEI Services Table published \r
799 by the PEI Foundation.\r
800 @param[in] This Pointer to local data for the interface.\r
801 @param[in] Address The physical address of the access.\r
802 @param[in] Data The data to write.\r
803\r
804**/\r
805VOID\r
806EFIAPI\r
807CpuIoWrite32 (\r
808 IN CONST EFI_PEI_SERVICES **PeiServices,\r
809 IN CONST EFI_PEI_CPU_IO_PPI *This,\r
810 IN UINT64 Address,\r
811 IN UINT32 Data\r
812 )\r
813{\r
814 IoWrite32 ((UINTN)Address, Data);\r
815}\r
816\r
817/**\r
818 64-bit I/O write operations.\r
819\r
820 @param[in] PeiServices An indirect pointer to the PEI Services Table published \r
821 by the PEI Foundation.\r
822 @param[in] This Pointer to local data for the interface.\r
823 @param[in] Address The physical address of the access.\r
824 @param[in] Data The data to write.\r
825\r
826**/\r
827VOID\r
828EFIAPI\r
829CpuIoWrite64 (\r
830 IN CONST EFI_PEI_SERVICES **PeiServices,\r
831 IN CONST EFI_PEI_CPU_IO_PPI *This,\r
832 IN UINT64 Address,\r
833 IN UINT64 Data\r
834 )\r
835{\r
836 IoWrite64 ((UINTN)Address, Data);\r
837}\r
838\r
839/**\r
840 8-bit memory read operations.\r
841\r
842 @param[in] PeiServices An indirect pointer to the PEI Services Table published \r
843 by the PEI Foundation.\r
844 @param[in] This Pointer to local data for the interface.\r
845 @param[in] Address The physical address of the access.\r
846\r
847 @return An 8-bit value returned from the memory space.\r
848\r
849**/\r
850UINT8\r
851EFIAPI\r
852CpuMemRead8 (\r
853 IN CONST EFI_PEI_SERVICES **PeiServices,\r
854 IN CONST EFI_PEI_CPU_IO_PPI *This,\r
855 IN UINT64 Address\r
856 )\r
857{\r
858 return MmioRead8 ((UINTN)Address);\r
859}\r
860\r
861/**\r
862 16-bit memory read operations.\r
863\r
864 @param[in] PeiServices An indirect pointer to the PEI Services Table published \r
865 by the PEI Foundation.\r
866 @param[in] This Pointer to local data for the interface.\r
867 @param[in] Address The physical address of the access.\r
868\r
869 @return A 16-bit value returned from the memory space.\r
870\r
871**/\r
872UINT16\r
873EFIAPI\r
874CpuMemRead16 (\r
875 IN CONST EFI_PEI_SERVICES **PeiServices,\r
876 IN CONST EFI_PEI_CPU_IO_PPI *This,\r
877 IN UINT64 Address\r
878 )\r
879{\r
880 return MmioRead16 ((UINTN)Address);\r
881}\r
882\r
883/**\r
884 32-bit memory read operations.\r
885\r
886 @param[in] PeiServices An indirect pointer to the PEI Services Table published \r
887 by the PEI Foundation.\r
888 @param[in] This Pointer to local data for the interface.\r
889 @param[in] Address The physical address of the access.\r
890\r
891 @return A 32-bit value returned from the memory space.\r
892\r
893**/\r
894UINT32\r
895EFIAPI\r
896CpuMemRead32 (\r
897 IN CONST EFI_PEI_SERVICES **PeiServices,\r
898 IN CONST EFI_PEI_CPU_IO_PPI *This,\r
899 IN UINT64 Address\r
900 )\r
901{\r
902 return MmioRead32 ((UINTN)Address);\r
903}\r
904\r
905/**\r
906 64-bit memory read operations.\r
907\r
908 @param[in] PeiServices An indirect pointer to the PEI Services Table published \r
909 by the PEI Foundation.\r
910 @param[in] This Pointer to local data for the interface.\r
911 @param[in] Address The physical address of the access.\r
912\r
913 @return A 64-bit value returned from the memory space.\r
914\r
915**/\r
916UINT64\r
917EFIAPI\r
918CpuMemRead64 (\r
919 IN CONST EFI_PEI_SERVICES **PeiServices,\r
920 IN CONST EFI_PEI_CPU_IO_PPI *This,\r
921 IN UINT64 Address\r
922 )\r
923{\r
924 return MmioRead64 ((UINTN)Address);\r
925}\r
926\r
927/**\r
928 8-bit memory write operations.\r
929\r
930 @param[in] PeiServices An indirect pointer to the PEI Services Table published \r
931 by the PEI Foundation.\r
932 @param[in] This Pointer to local data for the interface.\r
933 @param[in] Address The physical address of the access.\r
934 @param[in] Data The data to write.\r
935\r
936**/\r
937VOID\r
938EFIAPI\r
939CpuMemWrite8 (\r
940 IN CONST EFI_PEI_SERVICES **PeiServices,\r
941 IN CONST EFI_PEI_CPU_IO_PPI *This,\r
942 IN UINT64 Address,\r
943 IN UINT8 Data\r
944 )\r
945{\r
946 MmioWrite8 ((UINTN)Address, Data);\r
947}\r
948\r
949/**\r
950 16-bit memory write operations.\r
951\r
952 @param[in] PeiServices An indirect pointer to the PEI Services Table published \r
953 by the PEI Foundation.\r
954 @param[in] This Pointer to local data for the interface.\r
955 @param[in] Address The physical address of the access.\r
956 @param[in] Data The data to write.\r
957\r
958**/\r
959VOID\r
960EFIAPI\r
961CpuMemWrite16 (\r
962 IN CONST EFI_PEI_SERVICES **PeiServices,\r
963 IN CONST EFI_PEI_CPU_IO_PPI *This,\r
964 IN UINT64 Address,\r
965 IN UINT16 Data\r
966 )\r
967{\r
968 MmioWrite16 ((UINTN)Address, Data);\r
969}\r
970\r
971/**\r
972 32-bit memory write operations.\r
973\r
974 @param[in] PeiServices An indirect pointer to the PEI Services Table published \r
975 by the PEI Foundation.\r
976 @param[in] This Pointer to local data for the interface.\r
977 @param[in] Address The physical address of the access.\r
978 @param[in] Data The data to write.\r
979\r
980**/\r
981VOID\r
982EFIAPI\r
983CpuMemWrite32 (\r
984 IN CONST EFI_PEI_SERVICES **PeiServices,\r
985 IN CONST EFI_PEI_CPU_IO_PPI *This,\r
986 IN UINT64 Address,\r
987 IN UINT32 Data\r
988 )\r
989{\r
990 MmioWrite32 ((UINTN)Address, Data);\r
991}\r
992\r
993/**\r
994 64-bit memory write operations.\r
995\r
996 @param[in] PeiServices An indirect pointer to the PEI Services Table published \r
997 by the PEI Foundation.\r
998 @param[in] This Pointer to local data for the interface.\r
999 @param[in] Address The physical address of the access.\r
1000 @param[in] Data The data to write.\r
1001\r
1002**/\r
1003VOID\r
1004EFIAPI\r
1005CpuMemWrite64 (\r
1006 IN CONST EFI_PEI_SERVICES **PeiServices,\r
1007 IN CONST EFI_PEI_CPU_IO_PPI *This,\r
1008 IN UINT64 Address,\r
1009 IN UINT64 Data\r
1010 )\r
1011{\r
1012 MmioWrite64 ((UINTN)Address, Data);\r
1013}\r
1014\r
1015/**\r
1016 The Entry point of the CPU I/O PEIM\r
1017\r
1018 This function is the Entry point of the CPU I/O PEIM which installs CpuIoPpi.\r
1019\r
1020 @param[in] FileHandle Pointer to image file handle.\r
1021 @param[in] PeiServices Pointer to PEI Services Table \r
1022\r
1023 @retval EFI_SUCCESS CPU I/O PPI successfully installed\r
1024\r
1025**/\r
1026EFI_STATUS\r
1027EFIAPI\r
1028CpuIoInitialize (\r
1029 IN EFI_PEI_FILE_HANDLE FileHandle,\r
1030 IN CONST EFI_PEI_SERVICES **PeiServices\r
1031 )\r
1032{\r
1033 EFI_STATUS Status;\r
1034\r
1035 //\r
1036 // Register so it will be automatically shadowed to memory\r
1037 //\r
1038 Status = PeiServicesRegisterForShadow (FileHandle);\r
1039 \r
1040 //\r
1041 // Make CpuIo pointer in PeiService table point to gCpuIoPpi\r
1042 //\r
1043 (*((EFI_PEI_SERVICES **)PeiServices))->CpuIo = &gCpuIoPpi;\r
1044 \r
1045 if (Status == EFI_ALREADY_STARTED) {\r
1046 //\r
1047 // Shadow completed and running from memory\r
1048 //\r
1049 DEBUG ((EFI_D_INFO, "CpuIO PPI has been loaded into memory. Reinstalled PPI=0x%x\n", &gCpuIoPpi));\r
1050 } else {\r
1051 Status = PeiServicesInstallPpi (&gPpiList);\r
1052 ASSERT_EFI_ERROR (Status);\r
1053 }\r
1054 \r
1055 return EFI_SUCCESS;\r
1056}\r