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