1 /** @file
2   I/O Library. The implementations are based on EFI_PEI_SERVICE->CpuIo interface.
3 
4   Copyright (c) 2006 - 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 
12 #include <PiPei.h>
13 
14 #include <Library/IoLib.h>
15 #include <Library/DebugLib.h>
16 #include <Library/BaseLib.h>
17 #include <Library/PeiServicesTablePointerLib.h>
18 
19 
20 /**
21   Reads registers in the EFI CPU I/O space.
22 
23   Reads the I/O port specified by Port with registers width specified by Width.
24   The port is read Count times, and the read data is stored in the provided Buffer.
25 
26   This function must guarantee that all I/O read and write operations are serialized.
27   If such operations are not supported, then ASSERT().
28 
29   @param  Port          The base address of the I/O operation.
30                         The caller is responsible for aligning the Address if required.
31   @param  Width         The width of the I/O operation.
32   @param  Count         The number of times to read I/O port.
33   @param  Buffer        The buffer to store the read data into.
34 
35 **/
36 VOID
37 EFIAPI
IoReadFifoWorker(IN UINTN Port,IN EFI_PEI_CPU_IO_PPI_WIDTH Width,IN UINTN Count,IN VOID * Buffer)38 IoReadFifoWorker (
39   IN      UINTN                     Port,
40   IN      EFI_PEI_CPU_IO_PPI_WIDTH  Width,
41   IN      UINTN                     Count,
42   IN      VOID                      *Buffer
43   )
44 {
45   CONST EFI_PEI_SERVICES            **PeiServices;
46   EFI_PEI_CPU_IO_PPI                *CpuIo;
47   EFI_STATUS                        Status;
48 
49   PeiServices = GetPeiServicesTablePointer ();
50   CpuIo       = (*PeiServices)->CpuIo;
51   ASSERT (CpuIo != NULL);
52 
53   Status = CpuIo->Io.Read (PeiServices, CpuIo, Width, Port, Count, Buffer);
54   ASSERT_EFI_ERROR (Status);
55 }
56 
57 /**
58   Writes registers in the EFI CPU I/O space.
59 
60   Writes the I/O port specified by Port with registers width specified by Width.
61   The port is written Count times, and the write data is retrieved from the provided Buffer.
62 
63   This function must guarantee that all I/O read and write operations are serialized.
64   If such operations are not supported, then ASSERT().
65 
66   @param  Port          The base address of the I/O operation.
67                         The caller is responsible for aligning the Address if required.
68   @param  Width         The width of the I/O operation.
69   @param  Count         The number of times to write I/O port.
70   @param  Buffer        The buffer to store the read data into.
71 
72 **/
73 VOID
74 EFIAPI
IoWriteFifoWorker(IN UINTN Port,IN EFI_PEI_CPU_IO_PPI_WIDTH Width,IN UINTN Count,IN VOID * Buffer)75 IoWriteFifoWorker (
76   IN      UINTN                     Port,
77   IN      EFI_PEI_CPU_IO_PPI_WIDTH  Width,
78   IN      UINTN                     Count,
79   IN      VOID                      *Buffer
80   )
81 {
82   CONST EFI_PEI_SERVICES            **PeiServices;
83   EFI_PEI_CPU_IO_PPI                *CpuIo;
84   EFI_STATUS                        Status;
85 
86   PeiServices = GetPeiServicesTablePointer ();
87   CpuIo       = (*PeiServices)->CpuIo;
88   ASSERT (CpuIo != NULL);
89 
90   Status = CpuIo->Io.Write (PeiServices, CpuIo, Width, Port, Count, Buffer);
91   ASSERT_EFI_ERROR (Status);
92 }
93 
94 /**
95   Reads an 8-bit I/O port.
96 
97   Reads the 8-bit I/O port specified by Port. The 8-bit read value is returned.
98   This function must guarantee that all I/O read and write operations are
99   serialized.
100 
101   If 8-bit I/O port operations are not supported, then ASSERT().
102 
103   @param  Port  The I/O port to read.
104 
105   @return The value read.
106 
107 **/
108 UINT8
109 EFIAPI
IoRead8(IN UINTN Port)110 IoRead8 (
111   IN      UINTN                     Port
112   )
113 {
114   CONST EFI_PEI_SERVICES            **PeiServices;
115   EFI_PEI_CPU_IO_PPI                *CpuIo;
116 
117   PeiServices = GetPeiServicesTablePointer ();
118   CpuIo       = (*PeiServices)->CpuIo;
119   ASSERT (CpuIo != NULL);
120 
121   return CpuIo->IoRead8 (PeiServices, CpuIo, (UINT64) Port);
122 }
123 
124 /**
125   Writes an 8-bit I/O port.
126 
127   Writes the 8-bit I/O port specified by Port with the value specified by Value
128   and returns Value. This function must guarantee that all I/O read and write
129   operations are serialized.
130 
131   If 8-bit I/O port operations are not supported, then ASSERT().
132 
133   @param  Port  The I/O port to write.
134   @param  Value The value to write to the I/O port.
135 
136   @return The value written the I/O port.
137 
138 **/
139 UINT8
140 EFIAPI
IoWrite8(IN UINTN Port,IN UINT8 Value)141 IoWrite8 (
142   IN      UINTN                     Port,
143   IN      UINT8                     Value
144   )
145 {
146   CONST EFI_PEI_SERVICES            **PeiServices;
147   EFI_PEI_CPU_IO_PPI                *CpuIo;
148 
149   PeiServices = GetPeiServicesTablePointer ();
150   CpuIo       = (*PeiServices)->CpuIo;
151   ASSERT (CpuIo != NULL);
152 
153   CpuIo->IoWrite8 (PeiServices, CpuIo, (UINT64) Port, Value);
154   return Value;
155 }
156 
157 /**
158   Reads a 16-bit I/O port.
159 
160   Reads the 16-bit I/O port specified by Port. The 16-bit read value is returned.
161   This function must guarantee that all I/O read and write operations are
162   serialized.
163 
164   If 16-bit I/O port operations are not supported, then ASSERT().
165   If Port is not aligned on a 16-bit boundary, then ASSERT().
166 
167   @param  Port  The I/O port to read.
168 
169   @return The value read.
170 
171 **/
172 UINT16
173 EFIAPI
IoRead16(IN UINTN Port)174 IoRead16 (
175   IN      UINTN                     Port
176   )
177 {
178   CONST EFI_PEI_SERVICES            **PeiServices;
179   EFI_PEI_CPU_IO_PPI                *CpuIo;
180 
181   PeiServices = GetPeiServicesTablePointer ();
182   CpuIo       = (*PeiServices)->CpuIo;
183   ASSERT (CpuIo != NULL);
184   //
185   // Make sure Port is aligned on a 16-bit boundary.
186   //
187   ASSERT ((Port & 1) == 0);
188   return CpuIo->IoRead16 (PeiServices, CpuIo, (UINT64) Port);
189 }
190 
191 /**
192   Writes a 16-bit I/O port.
193 
194   Writes the 16-bit I/O port specified by Port with the value specified by Value
195   and returns Value. This function must guarantee that all I/O read and write
196   operations are serialized.
197 
198   If 16-bit I/O port operations are not supported, then ASSERT().
199   If Port is not aligned on a 16-bit boundary, then ASSERT().
200 
201   @param  Port  The I/O port to write.
202   @param  Value The value to write to the I/O port.
203 
204   @return The value written the I/O port.
205 
206 **/
207 UINT16
208 EFIAPI
IoWrite16(IN UINTN Port,IN UINT16 Value)209 IoWrite16 (
210   IN      UINTN                     Port,
211   IN      UINT16                    Value
212   )
213 {
214   CONST EFI_PEI_SERVICES            **PeiServices;
215   EFI_PEI_CPU_IO_PPI                *CpuIo;
216 
217   PeiServices = GetPeiServicesTablePointer ();
218   CpuIo       = (*PeiServices)->CpuIo;
219   ASSERT (CpuIo != NULL);
220   //
221   // Make sure Port is aligned on a 16-bit boundary.
222   //
223   ASSERT ((Port & 1) == 0);
224   CpuIo->IoWrite16 (PeiServices, CpuIo, (UINT64) Port, Value);
225   return Value;
226 }
227 
228 /**
229   Reads a 32-bit I/O port.
230 
231   Reads the 32-bit I/O port specified by Port. The 32-bit read value is returned.
232   This function must guarantee that all I/O read and write operations are
233   serialized.
234 
235   If 32-bit I/O port operations are not supported, then ASSERT().
236   If Port is not aligned on a 32-bit boundary, then ASSERT().
237 
238   @param  Port  The I/O port to read.
239 
240   @return The value read.
241 
242 **/
243 UINT32
244 EFIAPI
IoRead32(IN UINTN Port)245 IoRead32 (
246   IN      UINTN                     Port
247   )
248 {
249   CONST EFI_PEI_SERVICES            **PeiServices;
250   EFI_PEI_CPU_IO_PPI                *CpuIo;
251 
252   PeiServices = GetPeiServicesTablePointer ();
253   CpuIo       = (*PeiServices)->CpuIo;
254   ASSERT (CpuIo != NULL);
255   //
256   // Make sure Port is aligned on a 32-bit boundary.
257   //
258   ASSERT ((Port & 3) == 0);
259   return CpuIo->IoRead32 (PeiServices, CpuIo, (UINT64) Port);
260 }
261 
262 /**
263   Writes a 32-bit I/O port.
264 
265   Writes the 32-bit I/O port specified by Port with the value specified by Value
266   and returns Value. This function must guarantee that all I/O read and write
267   operations are serialized.
268 
269   If 32-bit I/O port operations are not supported, then ASSERT().
270   If Port is not aligned on a 32-bit boundary, then ASSERT().
271 
272   @param  Port  The I/O port to write.
273   @param  Value The value to write to the I/O port.
274 
275   @return The value written the I/O port.
276 
277 **/
278 UINT32
279 EFIAPI
IoWrite32(IN UINTN Port,IN UINT32 Value)280 IoWrite32 (
281   IN      UINTN                     Port,
282   IN      UINT32                    Value
283   )
284 {
285   CONST EFI_PEI_SERVICES            **PeiServices;
286   EFI_PEI_CPU_IO_PPI                *CpuIo;
287 
288   PeiServices = GetPeiServicesTablePointer ();
289   CpuIo       = (*PeiServices)->CpuIo;
290   ASSERT (CpuIo != NULL);
291   //
292   // Make sure Port is aligned on a 32-bit boundary.
293   //
294   ASSERT ((Port & 3) == 0);
295   CpuIo->IoWrite32 (PeiServices, CpuIo, (UINT64) Port, Value);
296   return Value;
297 }
298 
299 /**
300   Reads a 64-bit I/O port.
301 
302   Reads the 64-bit I/O port specified by Port. The 64-bit read value is returned.
303   This function must guarantee that all I/O read and write operations are
304   serialized.
305 
306   If 64-bit I/O port operations are not supported, then ASSERT().
307   If Port is not aligned on a 64-bit boundary, then ASSERT().
308 
309   @param  Port  The I/O port to read.
310 
311   @return The value read.
312 
313 **/
314 UINT64
315 EFIAPI
IoRead64(IN UINTN Port)316 IoRead64 (
317   IN      UINTN                     Port
318   )
319 {
320   CONST EFI_PEI_SERVICES            **PeiServices;
321   EFI_PEI_CPU_IO_PPI                *CpuIo;
322 
323   PeiServices = GetPeiServicesTablePointer ();
324   CpuIo       = (*PeiServices)->CpuIo;
325   ASSERT (CpuIo != NULL);
326   //
327   // Make sure Port is aligned on a 64-bit boundary.
328   //
329   ASSERT ((Port & 7) == 0);
330   return CpuIo->IoRead64 (PeiServices, CpuIo, (UINT64) Port);
331 }
332 
333 /**
334   Writes a 64-bit I/O port.
335 
336   Writes the 64-bit I/O port specified by Port with the value specified by Value
337   and returns Value. This function must guarantee that all I/O read and write
338   operations are serialized.
339 
340   If 64-bit I/O port operations are not supported, then ASSERT().
341   If Port is not aligned on a 64-bit boundary, then ASSERT().
342 
343   @param  Port  The I/O port to write.
344   @param  Value The value to write to the I/O port.
345 
346   @return The value written the I/O port.
347 
348 **/
349 UINT64
350 EFIAPI
IoWrite64(IN UINTN Port,IN UINT64 Value)351 IoWrite64 (
352   IN      UINTN                     Port,
353   IN      UINT64                    Value
354   )
355 {
356   CONST EFI_PEI_SERVICES            **PeiServices;
357   EFI_PEI_CPU_IO_PPI                *CpuIo;
358 
359   PeiServices = GetPeiServicesTablePointer ();
360   CpuIo       = (*PeiServices)->CpuIo;
361   ASSERT (CpuIo != NULL);
362   //
363   // Make sure Port is aligned on a 64-bit boundary.
364   //
365   ASSERT ((Port & 7) == 0);
366   CpuIo->IoWrite64 (PeiServices, CpuIo, (UINT64) Port, Value);
367   return Value;;
368 }
369 
370 /**
371   Reads an 8-bit I/O port fifo into a block of memory.
372 
373   Reads the 8-bit I/O fifo port specified by Port.
374   The port is read Count times, and the read data is
375   stored in the provided Buffer.
376 
377   This function must guarantee that all I/O read and write operations are
378   serialized.
379 
380   If 8-bit I/O port operations are not supported, then ASSERT().
381 
382   @param  Port    The I/O port to read.
383   @param  Count   The number of times to read I/O port.
384   @param  Buffer  The buffer to store the read data into.
385 
386 **/
387 VOID
388 EFIAPI
IoReadFifo8(IN UINTN Port,IN UINTN Count,OUT VOID * Buffer)389 IoReadFifo8 (
390   IN      UINTN                     Port,
391   IN      UINTN                     Count,
392   OUT     VOID                      *Buffer
393   )
394 {
395   IoReadFifoWorker (Port, EfiPeiCpuIoWidthFifoUint8, Count, Buffer);
396 }
397 
398 /**
399   Writes a block of memory into an 8-bit I/O port fifo.
400 
401   Writes the 8-bit I/O fifo port specified by Port.
402   The port is written Count times, and the write data is
403   retrieved from the provided Buffer.
404 
405   This function must guarantee that all I/O write and write operations are
406   serialized.
407 
408   If 8-bit I/O port operations are not supported, then ASSERT().
409 
410   @param  Port    The I/O port to write.
411   @param  Count   The number of times to write I/O port.
412   @param  Buffer  The buffer to retrieve the write data from.
413 
414 **/
415 VOID
416 EFIAPI
IoWriteFifo8(IN UINTN Port,IN UINTN Count,IN VOID * Buffer)417 IoWriteFifo8 (
418   IN      UINTN                     Port,
419   IN      UINTN                     Count,
420   IN      VOID                      *Buffer
421   )
422 {
423   IoWriteFifoWorker (Port, EfiPeiCpuIoWidthFifoUint8, Count, Buffer);
424 }
425 
426 /**
427   Reads a 16-bit I/O port fifo into a block of memory.
428 
429   Reads the 16-bit I/O fifo port specified by Port.
430   The port is read Count times, and the read data is
431   stored in the provided Buffer.
432 
433   This function must guarantee that all I/O read and write operations are
434   serialized.
435 
436   If 16-bit I/O port operations are not supported, then ASSERT().
437 
438   @param  Port    The I/O port to read.
439   @param  Count   The number of times to read I/O port.
440   @param  Buffer  The buffer to store the read data into.
441 
442 **/
443 VOID
444 EFIAPI
IoReadFifo16(IN UINTN Port,IN UINTN Count,OUT VOID * Buffer)445 IoReadFifo16 (
446   IN      UINTN                     Port,
447   IN      UINTN                     Count,
448   OUT     VOID                      *Buffer
449   )
450 {
451   //
452   // Make sure Port is aligned on a 16-bit boundary.
453   //
454   ASSERT ((Port & 1) == 0);
455   IoReadFifoWorker (Port, EfiPeiCpuIoWidthFifoUint16, Count, Buffer);
456 }
457 
458 /**
459   Writes a block of memory into a 16-bit I/O port fifo.
460 
461   Writes the 16-bit I/O fifo port specified by Port.
462   The port is written Count times, and the write data is
463   retrieved from the provided Buffer.
464 
465   This function must guarantee that all I/O write and write operations are
466   serialized.
467 
468   If 16-bit I/O port operations are not supported, then ASSERT().
469 
470   @param  Port    The I/O port to write.
471   @param  Count   The number of times to write I/O port.
472   @param  Buffer  The buffer to retrieve the write data from.
473 
474 **/
475 VOID
476 EFIAPI
IoWriteFifo16(IN UINTN Port,IN UINTN Count,IN VOID * Buffer)477 IoWriteFifo16 (
478   IN      UINTN                     Port,
479   IN      UINTN                     Count,
480   IN      VOID                      *Buffer
481   )
482 {
483   //
484   // Make sure Port is aligned on a 16-bit boundary.
485   //
486   ASSERT ((Port & 1) == 0);
487   IoWriteFifoWorker (Port, EfiPeiCpuIoWidthFifoUint16, Count, Buffer);
488 }
489 
490 /**
491   Reads a 32-bit I/O port fifo into a block of memory.
492 
493   Reads the 32-bit I/O fifo port specified by Port.
494   The port is read Count times, and the read data is
495   stored in the provided Buffer.
496 
497   This function must guarantee that all I/O read and write operations are
498   serialized.
499 
500   If 32-bit I/O port operations are not supported, then ASSERT().
501 
502   @param  Port    The I/O port to read.
503   @param  Count   The number of times to read I/O port.
504   @param  Buffer  The buffer to store the read data into.
505 
506 **/
507 VOID
508 EFIAPI
IoReadFifo32(IN UINTN Port,IN UINTN Count,OUT VOID * Buffer)509 IoReadFifo32 (
510   IN      UINTN                     Port,
511   IN      UINTN                     Count,
512   OUT     VOID                      *Buffer
513   )
514 {
515   //
516   // Make sure Port is aligned on a 32-bit boundary.
517   //
518   ASSERT ((Port & 3) == 0);
519   IoReadFifoWorker (Port, EfiPeiCpuIoWidthFifoUint32, Count, Buffer);
520 }
521 
522 /**
523   Writes a block of memory into a 32-bit I/O port fifo.
524 
525   Writes the 32-bit I/O fifo port specified by Port.
526   The port is written Count times, and the write data is
527   retrieved from the provided Buffer.
528 
529   This function must guarantee that all I/O write and write operations are
530   serialized.
531 
532   If 32-bit I/O port operations are not supported, then ASSERT().
533 
534   @param  Port    The I/O port to write.
535   @param  Count   The number of times to write I/O port.
536   @param  Buffer  The buffer to retrieve the write data from.
537 
538 **/
539 VOID
540 EFIAPI
IoWriteFifo32(IN UINTN Port,IN UINTN Count,IN VOID * Buffer)541 IoWriteFifo32 (
542   IN      UINTN                     Port,
543   IN      UINTN                     Count,
544   IN      VOID                      *Buffer
545   )
546 {
547   //
548   // Make sure Port is aligned on a 32-bit boundary.
549   //
550   ASSERT ((Port & 3) == 0);
551   IoWriteFifoWorker (Port, EfiPeiCpuIoWidthFifoUint32, Count, Buffer);
552 }
553 
554 /**
555   Reads an 8-bit MMIO register.
556 
557   Reads the 8-bit MMIO register specified by Address. The 8-bit read value is
558   returned. This function must guarantee that all MMIO read and write
559   operations are serialized.
560 
561   If 8-bit MMIO register operations are not supported, then ASSERT().
562 
563   @param  Address The MMIO register to read.
564 
565   @return The value read.
566 
567 **/
568 UINT8
569 EFIAPI
MmioRead8(IN UINTN Address)570 MmioRead8 (
571   IN      UINTN                     Address
572   )
573 {
574   CONST EFI_PEI_SERVICES            **PeiServices;
575   EFI_PEI_CPU_IO_PPI                *CpuIo;
576 
577   PeiServices = GetPeiServicesTablePointer ();
578   CpuIo       = (*PeiServices)->CpuIo;
579   ASSERT (CpuIo != NULL);
580 
581   return CpuIo->MemRead8 (PeiServices, CpuIo, (UINT64) Address);
582 }
583 
584 /**
585   Writes an 8-bit MMIO register.
586 
587   Writes the 8-bit MMIO register specified by Address with the value specified
588   by Value and returns Value. This function must guarantee that all MMIO read
589   and write operations are serialized.
590 
591   If 8-bit MMIO register operations are not supported, then ASSERT().
592 
593   @param  Address The MMIO register to write.
594   @param  Value   The value to write to the MMIO register.
595 
596   @return Value.
597 
598 **/
599 UINT8
600 EFIAPI
MmioWrite8(IN UINTN Address,IN UINT8 Value)601 MmioWrite8 (
602   IN      UINTN                     Address,
603   IN      UINT8                     Value
604   )
605 {
606   CONST EFI_PEI_SERVICES            **PeiServices;
607   EFI_PEI_CPU_IO_PPI                *CpuIo;
608 
609   PeiServices = GetPeiServicesTablePointer ();
610   CpuIo       = (*PeiServices)->CpuIo;
611   ASSERT (CpuIo != NULL);
612 
613   CpuIo->MemWrite8 (PeiServices, CpuIo, (UINT64) Address, Value);
614   return Value;
615 }
616 
617 /**
618   Reads a 16-bit MMIO register.
619 
620   Reads the 16-bit MMIO register specified by Address. The 16-bit read value is
621   returned. This function must guarantee that all MMIO read and write
622   operations are serialized.
623 
624   If 16-bit MMIO register operations are not supported, then ASSERT().
625   If Address is not aligned on a 16-bit boundary, then ASSERT().
626 
627   @param  Address The MMIO register to read.
628 
629   @return The value read.
630 
631 **/
632 UINT16
633 EFIAPI
MmioRead16(IN UINTN Address)634 MmioRead16 (
635   IN      UINTN                     Address
636   )
637 {
638   CONST EFI_PEI_SERVICES            **PeiServices;
639   EFI_PEI_CPU_IO_PPI                *CpuIo;
640 
641   PeiServices = GetPeiServicesTablePointer ();
642   CpuIo       = (*PeiServices)->CpuIo;
643   ASSERT (CpuIo != NULL);
644   //
645   // Make sure Address is aligned on a 16-bit boundary.
646   //
647   ASSERT ((Address & 1) == 0);
648   return CpuIo->MemRead16 (PeiServices, CpuIo, (UINT64) Address);
649 
650 }
651 
652 /**
653   Writes a 16-bit MMIO register.
654 
655   Writes the 16-bit MMIO register specified by Address with the value specified
656   by Value and returns Value. This function must guarantee that all MMIO read
657   and write operations are serialized.
658 
659   If 16-bit MMIO register operations are not supported, then ASSERT().
660   If Address is not aligned on a 16-bit boundary, then ASSERT().
661 
662   @param  Address The MMIO register to write.
663   @param  Value   The value to write to the MMIO register.
664 
665   @return Value.
666 
667 **/
668 UINT16
669 EFIAPI
MmioWrite16(IN UINTN Address,IN UINT16 Value)670 MmioWrite16 (
671   IN      UINTN                     Address,
672   IN      UINT16                    Value
673   )
674 {
675   CONST EFI_PEI_SERVICES            **PeiServices;
676   EFI_PEI_CPU_IO_PPI                *CpuIo;
677 
678   PeiServices = GetPeiServicesTablePointer ();
679   CpuIo       = (*PeiServices)->CpuIo;
680   ASSERT (CpuIo != NULL);
681   //
682   // Make sure Address is aligned on a 16-bit boundary.
683   //
684   ASSERT ((Address & 1) == 0);
685   CpuIo->MemWrite16 (PeiServices, CpuIo, (UINT64) Address, Value);
686   return Value;
687 }
688 
689 /**
690   Reads a 32-bit MMIO register.
691 
692   Reads the 32-bit MMIO register specified by Address. The 32-bit read value is
693   returned. This function must guarantee that all MMIO read and write
694   operations are serialized.
695 
696   If 32-bit MMIO register operations are not supported, then ASSERT().
697   If Address is not aligned on a 32-bit boundary, then ASSERT().
698 
699   @param  Address The MMIO register to read.
700 
701   @return The value read.
702 
703 **/
704 UINT32
705 EFIAPI
MmioRead32(IN UINTN Address)706 MmioRead32 (
707   IN      UINTN                     Address
708   )
709 {
710   CONST EFI_PEI_SERVICES            **PeiServices;
711   EFI_PEI_CPU_IO_PPI                *CpuIo;
712 
713   PeiServices = GetPeiServicesTablePointer ();
714   CpuIo       = (*PeiServices)->CpuIo;
715   ASSERT (CpuIo != NULL);
716   //
717   // Make sure Address is aligned on a 32-bit boundary.
718   //
719   ASSERT ((Address & 3) == 0);
720   return CpuIo->MemRead32 (PeiServices, CpuIo, (UINT64) Address);
721 
722 }
723 
724 /**
725   Writes a 32-bit MMIO register.
726 
727   Writes the 32-bit MMIO register specified by Address with the value specified
728   by Value and returns Value. This function must guarantee that all MMIO read
729   and write operations are serialized.
730 
731   If 32-bit MMIO register operations are not supported, then ASSERT().
732   If Address is not aligned on a 32-bit boundary, then ASSERT().
733 
734   @param  Address The MMIO register to write.
735   @param  Value   The value to write to the MMIO register.
736 
737   @return Value.
738 
739 **/
740 UINT32
741 EFIAPI
MmioWrite32(IN UINTN Address,IN UINT32 Value)742 MmioWrite32 (
743   IN      UINTN                     Address,
744   IN      UINT32                    Value
745   )
746 {
747   CONST EFI_PEI_SERVICES            **PeiServices;
748   EFI_PEI_CPU_IO_PPI                *CpuIo;
749 
750   PeiServices = GetPeiServicesTablePointer ();
751   CpuIo       = (*PeiServices)->CpuIo;
752   ASSERT (CpuIo != NULL);
753   //
754   // Make sure Address is aligned on a 32-bit boundary.
755   //
756   ASSERT ((Address & 3) == 0);
757   CpuIo->MemWrite32 (PeiServices, CpuIo, (UINT64) Address, Value);
758   return Value;
759 }
760 
761 /**
762   Reads a 64-bit MMIO register.
763 
764   Reads the 64-bit MMIO register specified by Address. The 64-bit read value is
765   returned. This function must guarantee that all MMIO read and write
766   operations are serialized.
767 
768   If 64-bit MMIO register operations are not supported, then ASSERT().
769   If Address is not aligned on a 64-bit boundary, then ASSERT().
770 
771   @param  Address The MMIO register to read.
772 
773   @return The value read.
774 
775 **/
776 UINT64
777 EFIAPI
MmioRead64(IN UINTN Address)778 MmioRead64 (
779   IN      UINTN                     Address
780   )
781 {
782   CONST EFI_PEI_SERVICES            **PeiServices;
783   EFI_PEI_CPU_IO_PPI                *CpuIo;
784 
785   PeiServices = GetPeiServicesTablePointer ();
786   CpuIo       = (*PeiServices)->CpuIo;
787   ASSERT (CpuIo != NULL);
788   //
789   // Make sure Address is aligned on a 64-bit boundary.
790   //
791   ASSERT ((Address & (sizeof (UINT64) - 1)) == 0);
792   return CpuIo->MemRead64 (PeiServices, CpuIo, (UINT64) Address);
793 
794 }
795 
796 /**
797   Writes a 64-bit MMIO register.
798 
799   Writes the 64-bit MMIO register specified by Address with the value specified
800   by Value and returns Value. This function must guarantee that all MMIO read
801   and write operations are serialized.
802 
803   If 64-bit MMIO register operations are not supported, then ASSERT().
804   If Address is not aligned on a 64-bit boundary, then ASSERT().
805 
806   @param  Address The MMIO register to write.
807   @param  Value   The value to write to the MMIO register.
808 
809 **/
810 UINT64
811 EFIAPI
MmioWrite64(IN UINTN Address,IN UINT64 Value)812 MmioWrite64 (
813   IN      UINTN                     Address,
814   IN      UINT64                    Value
815   )
816 {
817   CONST EFI_PEI_SERVICES            **PeiServices;
818   EFI_PEI_CPU_IO_PPI                *CpuIo;
819 
820   PeiServices = GetPeiServicesTablePointer ();
821   CpuIo       = (*PeiServices)->CpuIo;
822   ASSERT (CpuIo != NULL);
823   //
824   // Make sure Address is aligned on a 64-bit boundary.
825   //
826   ASSERT ((Address & 7) == 0);
827   CpuIo->MemWrite64 (PeiServices, CpuIo, (UINT64) Address, Value);
828   return Value;
829 }
830