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