]> git.proxmox.com Git - mirror_edk2.git/blob - UefiCpuPkg/CpuIoPei/CpuIoPei.c
8a24cde0ccfc73597260c54fee7003a31eb6f7f9
[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 if (Address > LShiftU64 (MaxCount - Count + 1, Width)) {
172 return EFI_UNSUPPORTED;
173 }
174 }
175
176 return EFI_SUCCESS;
177 }
178
179 /**
180 Reads memory-mapped registers.
181
182 @param[in] PeiServices An indirect pointer to the PEI Services Table
183 published by the PEI Foundation.
184 @param[in] This Pointer to local data for the interface.
185 @param[in] Width The width of the access. Enumerated in bytes.
186 @param[in] Address The physical address of the access.
187 @param[in] Count The number of accesses to perform.
188 @param[out] Buffer A pointer to the buffer of data.
189
190 @retval EFI_SUCCESS The function completed successfully.
191 @retval EFI_INVALID_PARAMETER Width is invalid for this EFI system.
192 @retval EFI_INVALID_PARAMETER Buffer is NULL.
193 @retval EFI_UNSUPPORTED The address range specified by Address, Width,
194 and Count is not valid for this EFI system.
195
196 **/
197 EFI_STATUS
198 EFIAPI
199 CpuMemoryServiceRead (
200 IN CONST EFI_PEI_SERVICES **PeiServices,
201 IN CONST EFI_PEI_CPU_IO_PPI *This,
202 IN EFI_PEI_CPU_IO_PPI_WIDTH Width,
203 IN UINT64 Address,
204 IN UINTN Count,
205 OUT VOID *Buffer
206 )
207 {
208 EFI_STATUS Status;
209 UINT8 InStride;
210 UINT8 OutStride;
211 EFI_PEI_CPU_IO_PPI_WIDTH OperationWidth;
212 BOOLEAN Aligned;
213 UINT8 *Uint8Buffer;
214
215 Status = CpuIoCheckParameter (TRUE, Width, Address, Count, Buffer);
216 if (EFI_ERROR (Status)) {
217 return Status;
218 }
219
220 //
221 // Select loop based on the width of the transfer
222 //
223 InStride = mInStride[Width];
224 OutStride = mOutStride[Width];
225 OperationWidth = (EFI_PEI_CPU_IO_PPI_WIDTH) (Width & 0x03);
226 Aligned = (BOOLEAN)(((UINTN)Buffer & (mInStride[OperationWidth] - 1)) == 0x00);
227 for (Uint8Buffer = Buffer; Count > 0; Address += InStride, Uint8Buffer += OutStride, Count--) {
228 if (OperationWidth == EfiPeiCpuIoWidthUint8) {
229 *Uint8Buffer = MmioRead8 ((UINTN)Address);
230 } else if (OperationWidth == EfiPeiCpuIoWidthUint16) {
231 if (Aligned) {
232 *((UINT16 *)Uint8Buffer) = MmioRead16 ((UINTN)Address);
233 } else {
234 WriteUnaligned16 ((UINT16 *)Uint8Buffer, MmioRead16 ((UINTN)Address));
235 }
236 } else if (OperationWidth == EfiPeiCpuIoWidthUint32) {
237 if (Aligned) {
238 *((UINT32 *)Uint8Buffer) = MmioRead32 ((UINTN)Address);
239 } else {
240 WriteUnaligned32 ((UINT32 *)Uint8Buffer, MmioRead32 ((UINTN)Address));
241 }
242 } else if (OperationWidth == EfiPeiCpuIoWidthUint64) {
243 if (Aligned) {
244 *((UINT64 *)Uint8Buffer) = MmioRead64 ((UINTN)Address);
245 } else {
246 WriteUnaligned64 ((UINT64 *)Uint8Buffer, MmioRead64 ((UINTN)Address));
247 }
248 }
249 }
250 return EFI_SUCCESS;
251 }
252
253 /**
254 Writes memory-mapped registers.
255
256 @param[in] PeiServices An indirect pointer to the PEI Services Table
257 published by the PEI Foundation.
258 @param[in] This Pointer to local data for the interface.
259 @param[in] Width The width of the access. Enumerated in bytes.
260 @param[in] Address The physical address of the access.
261 @param[in] Count The number of accesses to perform.
262 @param[in] Buffer A pointer to the buffer of data.
263
264 @retval EFI_SUCCESS The function completed successfully.
265 @retval EFI_INVALID_PARAMETER Width is invalid for this EFI system.
266 @retval EFI_INVALID_PARAMETER Buffer is NULL.
267 @retval EFI_UNSUPPORTED The address range specified by Address, Width,
268 and Count is not valid for this EFI system.
269
270 **/
271 EFI_STATUS
272 EFIAPI
273 CpuMemoryServiceWrite (
274 IN CONST EFI_PEI_SERVICES **PeiServices,
275 IN CONST EFI_PEI_CPU_IO_PPI *This,
276 IN EFI_PEI_CPU_IO_PPI_WIDTH Width,
277 IN UINT64 Address,
278 IN UINTN Count,
279 IN VOID *Buffer
280 )
281 {
282 EFI_STATUS Status;
283 UINT8 InStride;
284 UINT8 OutStride;
285 EFI_PEI_CPU_IO_PPI_WIDTH OperationWidth;
286 BOOLEAN Aligned;
287 UINT8 *Uint8Buffer;
288
289 Status = CpuIoCheckParameter (TRUE, Width, Address, Count, Buffer);
290 if (EFI_ERROR (Status)) {
291 return Status;
292 }
293
294 //
295 // Select loop based on the width of the transfer
296 //
297 InStride = mInStride[Width];
298 OutStride = mOutStride[Width];
299 OperationWidth = (EFI_PEI_CPU_IO_PPI_WIDTH) (Width & 0x03);
300 Aligned = (BOOLEAN)(((UINTN)Buffer & (mInStride[OperationWidth] - 1)) == 0x00);
301 for (Uint8Buffer = Buffer; Count > 0; Address += InStride, Uint8Buffer += OutStride, Count--) {
302 if (OperationWidth == EfiPeiCpuIoWidthUint8) {
303 MmioWrite8 ((UINTN)Address, *Uint8Buffer);
304 } else if (OperationWidth == EfiPeiCpuIoWidthUint16) {
305 if (Aligned) {
306 MmioWrite16 ((UINTN)Address, *((UINT16 *)Uint8Buffer));
307 } else {
308 MmioWrite16 ((UINTN)Address, ReadUnaligned16 ((UINT16 *)Uint8Buffer));
309 }
310 } else if (OperationWidth == EfiPeiCpuIoWidthUint32) {
311 if (Aligned) {
312 MmioWrite32 ((UINTN)Address, *((UINT32 *)Uint8Buffer));
313 } else {
314 MmioWrite32 ((UINTN)Address, ReadUnaligned32 ((UINT32 *)Uint8Buffer));
315 }
316 } else if (OperationWidth == EfiPeiCpuIoWidthUint64) {
317 if (Aligned) {
318 MmioWrite64 ((UINTN)Address, *((UINT64 *)Uint8Buffer));
319 } else {
320 MmioWrite64 ((UINTN)Address, ReadUnaligned64 ((UINT64 *)Uint8Buffer));
321 }
322 }
323 }
324 return EFI_SUCCESS;
325 }
326
327 /**
328 Reads I/O registers.
329
330 @param[in] PeiServices An indirect pointer to the PEI Services Table
331 published by the PEI Foundation.
332 @param[in] This Pointer to local data for the interface.
333 @param[in] Width The width of the access. Enumerated in bytes.
334 @param[in] Address The physical address of the access.
335 @param[in] Count The number of accesses to perform.
336 @param[out] Buffer A pointer to the buffer of data.
337
338 @retval EFI_SUCCESS The function completed successfully.
339 @retval EFI_INVALID_PARAMETER Width is invalid for this EFI system.
340 @retval EFI_INVALID_PARAMETER Buffer is NULL.
341 @retval EFI_UNSUPPORTED The address range specified by Address, Width,
342 and Count is not valid for this EFI system.
343
344 **/
345 EFI_STATUS
346 EFIAPI
347 CpuIoServiceRead (
348 IN CONST EFI_PEI_SERVICES **PeiServices,
349 IN CONST EFI_PEI_CPU_IO_PPI *This,
350 IN EFI_PEI_CPU_IO_PPI_WIDTH Width,
351 IN UINT64 Address,
352 IN UINTN Count,
353 OUT VOID *Buffer
354 )
355 {
356 EFI_STATUS Status;
357 UINT8 InStride;
358 UINT8 OutStride;
359 EFI_PEI_CPU_IO_PPI_WIDTH OperationWidth;
360 BOOLEAN Aligned;
361 UINT8 *Uint8Buffer;
362
363 Status = CpuIoCheckParameter (FALSE, Width, Address, Count, Buffer);
364 if (EFI_ERROR (Status)) {
365 return Status;
366 }
367
368 //
369 // Select loop based on the width of the transfer
370 //
371 InStride = mInStride[Width];
372 OutStride = mOutStride[Width];
373 OperationWidth = (EFI_PEI_CPU_IO_PPI_WIDTH) (Width & 0x03);
374
375 //
376 // Fifo operations supported for (mInStride[Width] == 0)
377 //
378 if (InStride == 0) {
379 switch (OperationWidth) {
380 case EfiPeiCpuIoWidthUint8:
381 IoReadFifo8 ((UINTN)Address, Count, Buffer);
382 return EFI_SUCCESS;
383 case EfiPeiCpuIoWidthUint16:
384 IoReadFifo16 ((UINTN)Address, Count, Buffer);
385 return EFI_SUCCESS;
386 case EfiPeiCpuIoWidthUint32:
387 IoReadFifo32 ((UINTN)Address, Count, Buffer);
388 return EFI_SUCCESS;
389 default:
390 //
391 // The CpuIoCheckParameter call above will ensure that this
392 // path is not taken.
393 //
394 ASSERT (FALSE);
395 break;
396 }
397 }
398
399 Aligned = (BOOLEAN)(((UINTN)Buffer & (mInStride[OperationWidth] - 1)) == 0x00);
400 for (Uint8Buffer = Buffer; Count > 0; Address += InStride, Uint8Buffer += OutStride, Count--) {
401 if (OperationWidth == EfiPeiCpuIoWidthUint8) {
402 *Uint8Buffer = IoRead8 ((UINTN)Address);
403 } else if (OperationWidth == EfiPeiCpuIoWidthUint16) {
404 if (Aligned) {
405 *((UINT16 *)Uint8Buffer) = IoRead16 ((UINTN)Address);
406 } else {
407 WriteUnaligned16 ((UINT16 *)Uint8Buffer, IoRead16 ((UINTN)Address));
408 }
409 } else if (OperationWidth == EfiPeiCpuIoWidthUint32) {
410 if (Aligned) {
411 *((UINT32 *)Uint8Buffer) = IoRead32 ((UINTN)Address);
412 } else {
413 WriteUnaligned32 ((UINT32 *)Uint8Buffer, IoRead32 ((UINTN)Address));
414 }
415 }
416 }
417
418 return EFI_SUCCESS;
419 }
420
421 /**
422 Write I/O registers.
423
424 @param[in] PeiServices An indirect pointer to the PEI Services Table
425 published by the PEI Foundation.
426 @param[in] This Pointer to local data for the interface.
427 @param[in] Width The width of the access. Enumerated in bytes.
428 @param[in] Address The physical address of the access.
429 @param[in] Count The number of accesses to perform.
430 @param[in] Buffer A pointer to the buffer of data.
431
432 @retval EFI_SUCCESS The function completed successfully.
433 @retval EFI_INVALID_PARAMETER Width is invalid for this EFI system.
434 @retval EFI_INVALID_PARAMETER Buffer is NULL.
435 @retval EFI_UNSUPPORTED The address range specified by Address, Width,
436 and Count is not valid for this EFI system.
437
438 **/
439 EFI_STATUS
440 EFIAPI
441 CpuIoServiceWrite (
442 IN CONST EFI_PEI_SERVICES **PeiServices,
443 IN CONST EFI_PEI_CPU_IO_PPI *This,
444 IN EFI_PEI_CPU_IO_PPI_WIDTH Width,
445 IN UINT64 Address,
446 IN UINTN Count,
447 IN VOID *Buffer
448 )
449 {
450 EFI_STATUS Status;
451 UINT8 InStride;
452 UINT8 OutStride;
453 EFI_PEI_CPU_IO_PPI_WIDTH OperationWidth;
454 BOOLEAN Aligned;
455 UINT8 *Uint8Buffer;
456
457 //
458 // Make sure the parameters are valid
459 //
460 Status = CpuIoCheckParameter (FALSE, Width, Address, Count, Buffer);
461 if (EFI_ERROR (Status)) {
462 return Status;
463 }
464
465 //
466 // Select loop based on the width of the transfer
467 //
468 InStride = mInStride[Width];
469 OutStride = mOutStride[Width];
470 OperationWidth = (EFI_PEI_CPU_IO_PPI_WIDTH) (Width & 0x03);
471
472 //
473 // Fifo operations supported for (mInStride[Width] == 0)
474 //
475 if (InStride == 0) {
476 switch (OperationWidth) {
477 case EfiPeiCpuIoWidthUint8:
478 IoWriteFifo8 ((UINTN)Address, Count, Buffer);
479 return EFI_SUCCESS;
480 case EfiPeiCpuIoWidthUint16:
481 IoWriteFifo16 ((UINTN)Address, Count, Buffer);
482 return EFI_SUCCESS;
483 case EfiPeiCpuIoWidthUint32:
484 IoWriteFifo32 ((UINTN)Address, Count, Buffer);
485 return EFI_SUCCESS;
486 default:
487 //
488 // The CpuIoCheckParameter call above will ensure that this
489 // path is not taken.
490 //
491 ASSERT (FALSE);
492 break;
493 }
494 }
495
496 Aligned = (BOOLEAN)(((UINTN)Buffer & (mInStride[OperationWidth] - 1)) == 0x00);
497 for (Uint8Buffer = (UINT8 *)Buffer; Count > 0; Address += InStride, Uint8Buffer += OutStride, Count--) {
498 if (OperationWidth == EfiPeiCpuIoWidthUint8) {
499 IoWrite8 ((UINTN)Address, *Uint8Buffer);
500 } else if (OperationWidth == EfiPeiCpuIoWidthUint16) {
501 if (Aligned) {
502 IoWrite16 ((UINTN)Address, *((UINT16 *)Uint8Buffer));
503 } else {
504 IoWrite16 ((UINTN)Address, ReadUnaligned16 ((UINT16 *)Uint8Buffer));
505 }
506 } else if (OperationWidth == EfiPeiCpuIoWidthUint32) {
507 if (Aligned) {
508 IoWrite32 ((UINTN)Address, *((UINT32 *)Uint8Buffer));
509 } else {
510 IoWrite32 ((UINTN)Address, ReadUnaligned32 ((UINT32 *)Uint8Buffer));
511 }
512 }
513 }
514
515 return EFI_SUCCESS;
516 }
517
518 /**
519 8-bit I/O read operations.
520
521 @param[in] PeiServices An indirect pointer to the PEI Services Table published
522 by the PEI Foundation.
523 @param[in] This Pointer to local data for the interface.
524 @param[in] Address The physical address of the access.
525
526 @return An 8-bit value returned from the I/O space.
527 **/
528 UINT8
529 EFIAPI
530 CpuIoRead8 (
531 IN CONST EFI_PEI_SERVICES **PeiServices,
532 IN CONST EFI_PEI_CPU_IO_PPI *This,
533 IN UINT64 Address
534 )
535 {
536 return IoRead8 ((UINTN)Address);
537 }
538
539 /**
540 16-bit I/O read operations.
541
542 @param[in] PeiServices An indirect pointer to the PEI Services Table published
543 by the PEI Foundation.
544 @param[in] This Pointer to local data for the interface.
545 @param[in] Address The physical address of the access.
546
547 @return A 16-bit value returned from the I/O space.
548
549 **/
550 UINT16
551 EFIAPI
552 CpuIoRead16 (
553 IN CONST EFI_PEI_SERVICES **PeiServices,
554 IN CONST EFI_PEI_CPU_IO_PPI *This,
555 IN UINT64 Address
556 )
557 {
558 return IoRead16 ((UINTN)Address);
559 }
560
561 /**
562 32-bit I/O read operations.
563
564 @param[in] PeiServices An indirect pointer to the PEI Services Table published
565 by the PEI Foundation.
566 @param[in] This Pointer to local data for the interface.
567 @param[in] Address The physical address of the access.
568
569 @return A 32-bit value returned from the I/O space.
570
571 **/
572 UINT32
573 EFIAPI
574 CpuIoRead32 (
575 IN CONST EFI_PEI_SERVICES **PeiServices,
576 IN CONST EFI_PEI_CPU_IO_PPI *This,
577 IN UINT64 Address
578 )
579 {
580 return IoRead32 ((UINTN)Address);
581 }
582
583 /**
584 64-bit I/O read operations.
585
586 @param[in] PeiServices An indirect pointer to the PEI Services Table published
587 by the PEI Foundation.
588 @param[in] This Pointer to local data for the interface.
589 @param[in] Address The physical address of the access.
590
591 @return A 64-bit value returned from the I/O space.
592
593 **/
594 UINT64
595 EFIAPI
596 CpuIoRead64 (
597 IN CONST EFI_PEI_SERVICES **PeiServices,
598 IN CONST EFI_PEI_CPU_IO_PPI *This,
599 IN UINT64 Address
600 )
601 {
602 return IoRead64 ((UINTN)Address);
603 }
604
605 /**
606 8-bit I/O write operations.
607
608 @param[in] PeiServices An indirect pointer to the PEI Services Table published
609 by the PEI Foundation.
610 @param[in] This Pointer to local data for the interface.
611 @param[in] Address The physical address of the access.
612 @param[in] Data The data to write.
613
614 **/
615 VOID
616 EFIAPI
617 CpuIoWrite8 (
618 IN CONST EFI_PEI_SERVICES **PeiServices,
619 IN CONST EFI_PEI_CPU_IO_PPI *This,
620 IN UINT64 Address,
621 IN UINT8 Data
622 )
623 {
624 IoWrite8 ((UINTN)Address, Data);
625 }
626
627 /**
628 16-bit I/O write operations.
629
630 @param[in] PeiServices An indirect pointer to the PEI Services Table published
631 by the PEI Foundation.
632 @param[in] This Pointer to local data for the interface.
633 @param[in] Address The physical address of the access.
634 @param[in] Data The data to write.
635
636 **/
637 VOID
638 EFIAPI
639 CpuIoWrite16 (
640 IN CONST EFI_PEI_SERVICES **PeiServices,
641 IN CONST EFI_PEI_CPU_IO_PPI *This,
642 IN UINT64 Address,
643 IN UINT16 Data
644 )
645 {
646 IoWrite16 ((UINTN)Address, Data);
647 }
648
649 /**
650 32-bit I/O write operations.
651
652 @param[in] PeiServices An indirect pointer to the PEI Services Table published
653 by the PEI Foundation.
654 @param[in] This Pointer to local data for the interface.
655 @param[in] Address The physical address of the access.
656 @param[in] Data The data to write.
657
658 **/
659 VOID
660 EFIAPI
661 CpuIoWrite32 (
662 IN CONST EFI_PEI_SERVICES **PeiServices,
663 IN CONST EFI_PEI_CPU_IO_PPI *This,
664 IN UINT64 Address,
665 IN UINT32 Data
666 )
667 {
668 IoWrite32 ((UINTN)Address, Data);
669 }
670
671 /**
672 64-bit I/O write operations.
673
674 @param[in] PeiServices An indirect pointer to the PEI Services Table published
675 by the PEI Foundation.
676 @param[in] This Pointer to local data for the interface.
677 @param[in] Address The physical address of the access.
678 @param[in] Data The data to write.
679
680 **/
681 VOID
682 EFIAPI
683 CpuIoWrite64 (
684 IN CONST EFI_PEI_SERVICES **PeiServices,
685 IN CONST EFI_PEI_CPU_IO_PPI *This,
686 IN UINT64 Address,
687 IN UINT64 Data
688 )
689 {
690 IoWrite64 ((UINTN)Address, Data);
691 }
692
693 /**
694 8-bit memory read operations.
695
696 @param[in] PeiServices An indirect pointer to the PEI Services Table published
697 by the PEI Foundation.
698 @param[in] This Pointer to local data for the interface.
699 @param[in] Address The physical address of the access.
700
701 @return An 8-bit value returned from the memory space.
702
703 **/
704 UINT8
705 EFIAPI
706 CpuMemRead8 (
707 IN CONST EFI_PEI_SERVICES **PeiServices,
708 IN CONST EFI_PEI_CPU_IO_PPI *This,
709 IN UINT64 Address
710 )
711 {
712 return MmioRead8 ((UINTN)Address);
713 }
714
715 /**
716 16-bit memory read operations.
717
718 @param[in] PeiServices An indirect pointer to the PEI Services Table published
719 by the PEI Foundation.
720 @param[in] This Pointer to local data for the interface.
721 @param[in] Address The physical address of the access.
722
723 @return A 16-bit value returned from the memory space.
724
725 **/
726 UINT16
727 EFIAPI
728 CpuMemRead16 (
729 IN CONST EFI_PEI_SERVICES **PeiServices,
730 IN CONST EFI_PEI_CPU_IO_PPI *This,
731 IN UINT64 Address
732 )
733 {
734 return MmioRead16 ((UINTN)Address);
735 }
736
737 /**
738 32-bit memory read operations.
739
740 @param[in] PeiServices An indirect pointer to the PEI Services Table published
741 by the PEI Foundation.
742 @param[in] This Pointer to local data for the interface.
743 @param[in] Address The physical address of the access.
744
745 @return A 32-bit value returned from the memory space.
746
747 **/
748 UINT32
749 EFIAPI
750 CpuMemRead32 (
751 IN CONST EFI_PEI_SERVICES **PeiServices,
752 IN CONST EFI_PEI_CPU_IO_PPI *This,
753 IN UINT64 Address
754 )
755 {
756 return MmioRead32 ((UINTN)Address);
757 }
758
759 /**
760 64-bit memory read operations.
761
762 @param[in] PeiServices An indirect pointer to the PEI Services Table published
763 by the PEI Foundation.
764 @param[in] This Pointer to local data for the interface.
765 @param[in] Address The physical address of the access.
766
767 @return A 64-bit value returned from the memory space.
768
769 **/
770 UINT64
771 EFIAPI
772 CpuMemRead64 (
773 IN CONST EFI_PEI_SERVICES **PeiServices,
774 IN CONST EFI_PEI_CPU_IO_PPI *This,
775 IN UINT64 Address
776 )
777 {
778 return MmioRead64 ((UINTN)Address);
779 }
780
781 /**
782 8-bit memory write operations.
783
784 @param[in] PeiServices An indirect pointer to the PEI Services Table published
785 by the PEI Foundation.
786 @param[in] This Pointer to local data for the interface.
787 @param[in] Address The physical address of the access.
788 @param[in] Data The data to write.
789
790 **/
791 VOID
792 EFIAPI
793 CpuMemWrite8 (
794 IN CONST EFI_PEI_SERVICES **PeiServices,
795 IN CONST EFI_PEI_CPU_IO_PPI *This,
796 IN UINT64 Address,
797 IN UINT8 Data
798 )
799 {
800 MmioWrite8 ((UINTN)Address, Data);
801 }
802
803 /**
804 16-bit memory write operations.
805
806 @param[in] PeiServices An indirect pointer to the PEI Services Table published
807 by the PEI Foundation.
808 @param[in] This Pointer to local data for the interface.
809 @param[in] Address The physical address of the access.
810 @param[in] Data The data to write.
811
812 **/
813 VOID
814 EFIAPI
815 CpuMemWrite16 (
816 IN CONST EFI_PEI_SERVICES **PeiServices,
817 IN CONST EFI_PEI_CPU_IO_PPI *This,
818 IN UINT64 Address,
819 IN UINT16 Data
820 )
821 {
822 MmioWrite16 ((UINTN)Address, Data);
823 }
824
825 /**
826 32-bit memory write operations.
827
828 @param[in] PeiServices An indirect pointer to the PEI Services Table published
829 by the PEI Foundation.
830 @param[in] This Pointer to local data for the interface.
831 @param[in] Address The physical address of the access.
832 @param[in] Data The data to write.
833
834 **/
835 VOID
836 EFIAPI
837 CpuMemWrite32 (
838 IN CONST EFI_PEI_SERVICES **PeiServices,
839 IN CONST EFI_PEI_CPU_IO_PPI *This,
840 IN UINT64 Address,
841 IN UINT32 Data
842 )
843 {
844 MmioWrite32 ((UINTN)Address, Data);
845 }
846
847 /**
848 64-bit memory write operations.
849
850 @param[in] PeiServices An indirect pointer to the PEI Services Table published
851 by the PEI Foundation.
852 @param[in] This Pointer to local data for the interface.
853 @param[in] Address The physical address of the access.
854 @param[in] Data The data to write.
855
856 **/
857 VOID
858 EFIAPI
859 CpuMemWrite64 (
860 IN CONST EFI_PEI_SERVICES **PeiServices,
861 IN CONST EFI_PEI_CPU_IO_PPI *This,
862 IN UINT64 Address,
863 IN UINT64 Data
864 )
865 {
866 MmioWrite64 ((UINTN)Address, Data);
867 }
868
869 /**
870 The Entry point of the CPU I/O PEIM
871
872 This function is the Entry point of the CPU I/O PEIM which installs CpuIoPpi.
873
874 @param[in] FileHandle Pointer to image file handle.
875 @param[in] PeiServices Pointer to PEI Services Table
876
877 @retval EFI_SUCCESS CPU I/O PPI successfully installed
878
879 **/
880 EFI_STATUS
881 EFIAPI
882 CpuIoInitialize (
883 IN EFI_PEI_FILE_HANDLE FileHandle,
884 IN CONST EFI_PEI_SERVICES **PeiServices
885 )
886 {
887 EFI_STATUS Status;
888
889 //
890 // Register so it will be automatically shadowed to memory
891 //
892 Status = PeiServicesRegisterForShadow (FileHandle);
893
894 //
895 // Make CpuIo pointer in PeiService table point to gCpuIoPpi
896 //
897 (*((EFI_PEI_SERVICES **)PeiServices))->CpuIo = &gCpuIoPpi;
898
899 if (Status == EFI_ALREADY_STARTED) {
900 //
901 // Shadow completed and running from memory
902 //
903 DEBUG ((EFI_D_INFO, "CpuIO PPI has been loaded into memory. Reinstalled PPI=0x%x\n", &gCpuIoPpi));
904 } else {
905 Status = PeiServicesInstallPpi (&gPpiList);
906 ASSERT_EFI_ERROR (Status);
907 }
908
909 return EFI_SUCCESS;
910 }