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