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