1 /** @file
2   Produces the CPU I/O 2 Protocol.
3 
4 Copyright (c) 2009 - 2012, Intel Corporation. All rights reserved.<BR>
5 Copyright (c) 2016, Linaro Ltd. 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 <PiDxe.h>
18 
19 #include <Protocol/CpuIo2.h>
20 
21 #include <Library/BaseLib.h>
22 #include <Library/DebugLib.h>
23 #include <Library/IoLib.h>
24 #include <Library/PcdLib.h>
25 #include <Library/UefiBootServicesTableLib.h>
26 
27 #define MAX_IO_PORT_ADDRESS   0xFFFF
28 
29 //
30 // Handle for the CPU I/O 2 Protocol
31 //
32 STATIC EFI_HANDLE  mHandle = NULL;
33 
34 //
35 // Lookup table for increment values based on transfer widths
36 //
37 STATIC CONST UINT8 mInStride[] = {
38   1, // EfiCpuIoWidthUint8
39   2, // EfiCpuIoWidthUint16
40   4, // EfiCpuIoWidthUint32
41   8, // EfiCpuIoWidthUint64
42   0, // EfiCpuIoWidthFifoUint8
43   0, // EfiCpuIoWidthFifoUint16
44   0, // EfiCpuIoWidthFifoUint32
45   0, // EfiCpuIoWidthFifoUint64
46   1, // EfiCpuIoWidthFillUint8
47   2, // EfiCpuIoWidthFillUint16
48   4, // EfiCpuIoWidthFillUint32
49   8  // EfiCpuIoWidthFillUint64
50 };
51 
52 //
53 // Lookup table for increment values based on transfer widths
54 //
55 STATIC CONST UINT8 mOutStride[] = {
56   1, // EfiCpuIoWidthUint8
57   2, // EfiCpuIoWidthUint16
58   4, // EfiCpuIoWidthUint32
59   8, // EfiCpuIoWidthUint64
60   1, // EfiCpuIoWidthFifoUint8
61   2, // EfiCpuIoWidthFifoUint16
62   4, // EfiCpuIoWidthFifoUint32
63   8, // EfiCpuIoWidthFifoUint64
64   0, // EfiCpuIoWidthFillUint8
65   0, // EfiCpuIoWidthFillUint16
66   0, // EfiCpuIoWidthFillUint32
67   0  // EfiCpuIoWidthFillUint64
68 };
69 
70 /**
71   Check parameters to a CPU I/O 2 Protocol service request.
72 
73   The I/O operations are carried out exactly as requested. The caller is responsible
74   for satisfying any alignment and I/O width restrictions that a PI System on a
75   platform might require. For example on some platforms, width requests of
76   EfiCpuIoWidthUint64 do not work. Misaligned buffers, on the other hand, will
77   be handled by the driver.
78 
79   @param[in] MmioOperation  TRUE for an MMIO operation, FALSE for I/O Port operation.
80   @param[in] Width          Signifies the width of the I/O or Memory operation.
81   @param[in] Address        The base address of the I/O operation.
82   @param[in] Count          The number of I/O operations to perform. The number of
83                             bytes moved is Width size * Count, starting at Address.
84   @param[in] Buffer         For read operations, the destination buffer to store the results.
85                             For write operations, the source buffer from which to write data.
86 
87   @retval EFI_SUCCESS            The parameters for this request pass the checks.
88   @retval EFI_INVALID_PARAMETER  Width is invalid for this PI system.
89   @retval EFI_INVALID_PARAMETER  Buffer is NULL.
90   @retval EFI_UNSUPPORTED        The Buffer is not aligned for the given Width.
91   @retval EFI_UNSUPPORTED        The address range specified by Address, Width,
92                                  and Count is not valid for this PI system.
93 
94 **/
95 STATIC
96 EFI_STATUS
CpuIoCheckParameter(IN BOOLEAN MmioOperation,IN EFI_CPU_IO_PROTOCOL_WIDTH Width,IN UINT64 Address,IN UINTN Count,IN VOID * Buffer)97 CpuIoCheckParameter (
98   IN BOOLEAN                    MmioOperation,
99   IN EFI_CPU_IO_PROTOCOL_WIDTH  Width,
100   IN UINT64                     Address,
101   IN UINTN                      Count,
102   IN VOID                       *Buffer
103   )
104 {
105   UINT64  MaxCount;
106   UINT64  Limit;
107 
108   //
109   // Check to see if Buffer is NULL
110   //
111   if (Buffer == NULL) {
112     return EFI_INVALID_PARAMETER;
113   }
114 
115   //
116   // Check to see if Width is in the valid range
117   //
118   if ((UINT32)Width >= EfiCpuIoWidthMaximum) {
119     return EFI_INVALID_PARAMETER;
120   }
121 
122   //
123   // For FIFO type, the target address won't increase during the access,
124   // so treat Count as 1
125   //
126   if (Width >= EfiCpuIoWidthFifoUint8 && Width <= EfiCpuIoWidthFifoUint64) {
127     Count = 1;
128   }
129 
130   //
131   // Check to see if Width is in the valid range for I/O Port operations
132   //
133   Width = (EFI_CPU_IO_PROTOCOL_WIDTH) (Width & 0x03);
134   if (!MmioOperation && (Width == EfiCpuIoWidthUint64)) {
135     return EFI_INVALID_PARAMETER;
136   }
137 
138   //
139   // Check to see if Address is aligned
140   //
141   if ((Address & (UINT64)(mInStride[Width] - 1)) != 0) {
142     return EFI_UNSUPPORTED;
143   }
144 
145   //
146   // Check to see if any address associated with this transfer exceeds the maximum
147   // allowed address.  The maximum address implied by the parameters passed in is
148   // Address + Size * Count.  If the following condition is met, then the transfer
149   // is not supported.
150   //
151   //    Address + Size * Count > (MmioOperation ? MAX_ADDRESS : MAX_IO_PORT_ADDRESS) + 1
152   //
153   // Since MAX_ADDRESS can be the maximum integer value supported by the CPU and Count
154   // can also be the maximum integer value supported by the CPU, this range
155   // check must be adjusted to avoid all oveflow conditions.
156   //
157   // The following form of the range check is equivalent but assumes that
158   // MAX_ADDRESS and MAX_IO_PORT_ADDRESS are of the form (2^n - 1).
159   //
160   Limit = (MmioOperation ? MAX_ADDRESS : MAX_IO_PORT_ADDRESS);
161   if (Count == 0) {
162     if (Address > Limit) {
163       return EFI_UNSUPPORTED;
164     }
165   } else {
166     MaxCount = RShiftU64 (Limit, Width);
167     if (MaxCount < (Count - 1)) {
168       return EFI_UNSUPPORTED;
169     }
170     if (Address > LShiftU64 (MaxCount - Count + 1, Width)) {
171       return EFI_UNSUPPORTED;
172     }
173   }
174 
175   //
176   // Check to see if Buffer is aligned
177   //
178   if (((UINTN)Buffer & ((MIN (sizeof (UINTN), mInStride[Width])  - 1))) != 0) {
179     return EFI_UNSUPPORTED;
180   }
181 
182   return EFI_SUCCESS;
183 }
184 
185 /**
186   Reads memory-mapped registers.
187 
188   The I/O operations are carried out exactly as requested. The caller is responsible
189   for satisfying any alignment and I/O width restrictions that a PI System on a
190   platform might require. For example on some platforms, width requests of
191   EfiCpuIoWidthUint64 do not work. Misaligned buffers, on the other hand, will
192   be handled by the driver.
193 
194   If Width is EfiCpuIoWidthUint8, EfiCpuIoWidthUint16, EfiCpuIoWidthUint32,
195   or EfiCpuIoWidthUint64, then both Address and Buffer are incremented for
196   each of the Count operations that is performed.
197 
198   If Width is EfiCpuIoWidthFifoUint8, EfiCpuIoWidthFifoUint16,
199   EfiCpuIoWidthFifoUint32, or EfiCpuIoWidthFifoUint64, then only Buffer is
200   incremented for each of the Count operations that is performed. The read or
201   write operation is performed Count times on the same Address.
202 
203   If Width is EfiCpuIoWidthFillUint8, EfiCpuIoWidthFillUint16,
204   EfiCpuIoWidthFillUint32, or EfiCpuIoWidthFillUint64, then only Address is
205   incremented for each of the Count operations that is performed. The read or
206   write operation is performed Count times from the first element of Buffer.
207 
208   @param[in]  This     A pointer to the EFI_CPU_IO2_PROTOCOL instance.
209   @param[in]  Width    Signifies the width of the I/O or Memory operation.
210   @param[in]  Address  The base address of the I/O operation.
211   @param[in]  Count    The number of I/O operations to perform. The number of
212                        bytes moved is Width size * Count, starting at Address.
213   @param[out] Buffer   For read operations, the destination buffer to store the results.
214                        For write operations, the source buffer from which to write data.
215 
216   @retval EFI_SUCCESS            The data was read from or written to the PI system.
217   @retval EFI_INVALID_PARAMETER  Width is invalid for this PI system.
218   @retval EFI_INVALID_PARAMETER  Buffer is NULL.
219   @retval EFI_UNSUPPORTED        The Buffer is not aligned for the given Width.
220   @retval EFI_UNSUPPORTED        The address range specified by Address, Width,
221                                  and Count is not valid for this PI system.
222 
223 **/
224 STATIC
225 EFI_STATUS
226 EFIAPI
CpuMemoryServiceRead(IN EFI_CPU_IO2_PROTOCOL * This,IN EFI_CPU_IO_PROTOCOL_WIDTH Width,IN UINT64 Address,IN UINTN Count,OUT VOID * Buffer)227 CpuMemoryServiceRead (
228   IN  EFI_CPU_IO2_PROTOCOL       *This,
229   IN  EFI_CPU_IO_PROTOCOL_WIDTH  Width,
230   IN  UINT64                     Address,
231   IN  UINTN                      Count,
232   OUT VOID                       *Buffer
233   )
234 {
235   EFI_STATUS                 Status;
236   UINT8                      InStride;
237   UINT8                      OutStride;
238   EFI_CPU_IO_PROTOCOL_WIDTH  OperationWidth;
239   UINT8                      *Uint8Buffer;
240 
241   Status = CpuIoCheckParameter (TRUE, Width, Address, Count, Buffer);
242   if (EFI_ERROR (Status)) {
243     return Status;
244   }
245 
246   //
247   // Select loop based on the width of the transfer
248   //
249   InStride = mInStride[Width];
250   OutStride = mOutStride[Width];
251   OperationWidth = (EFI_CPU_IO_PROTOCOL_WIDTH) (Width & 0x03);
252   for (Uint8Buffer = Buffer; Count > 0; Address += InStride, Uint8Buffer += OutStride, Count--) {
253     if (OperationWidth == EfiCpuIoWidthUint8) {
254       *Uint8Buffer = MmioRead8 ((UINTN)Address);
255     } else if (OperationWidth == EfiCpuIoWidthUint16) {
256       *((UINT16 *)Uint8Buffer) = MmioRead16 ((UINTN)Address);
257     } else if (OperationWidth == EfiCpuIoWidthUint32) {
258       *((UINT32 *)Uint8Buffer) = MmioRead32 ((UINTN)Address);
259     } else if (OperationWidth == EfiCpuIoWidthUint64) {
260       *((UINT64 *)Uint8Buffer) = MmioRead64 ((UINTN)Address);
261     }
262   }
263   return EFI_SUCCESS;
264 }
265 
266 /**
267   Writes memory-mapped registers.
268 
269   The I/O operations are carried out exactly as requested. The caller is responsible
270   for satisfying any alignment and I/O width restrictions that a PI System on a
271   platform might require. For example on some platforms, width requests of
272   EfiCpuIoWidthUint64 do not work. Misaligned buffers, on the other hand, will
273   be handled by the driver.
274 
275   If Width is EfiCpuIoWidthUint8, EfiCpuIoWidthUint16, EfiCpuIoWidthUint32,
276   or EfiCpuIoWidthUint64, then both Address and Buffer are incremented for
277   each of the Count operations that is performed.
278 
279   If Width is EfiCpuIoWidthFifoUint8, EfiCpuIoWidthFifoUint16,
280   EfiCpuIoWidthFifoUint32, or EfiCpuIoWidthFifoUint64, then only Buffer is
281   incremented for each of the Count operations that is performed. The read or
282   write operation is performed Count times on the same Address.
283 
284   If Width is EfiCpuIoWidthFillUint8, EfiCpuIoWidthFillUint16,
285   EfiCpuIoWidthFillUint32, or EfiCpuIoWidthFillUint64, then only Address is
286   incremented for each of the Count operations that is performed. The read or
287   write operation is performed Count times from the first element of Buffer.
288 
289   @param[in]  This     A pointer to the EFI_CPU_IO2_PROTOCOL instance.
290   @param[in]  Width    Signifies the width of the I/O or Memory operation.
291   @param[in]  Address  The base address of the I/O operation.
292   @param[in]  Count    The number of I/O operations to perform. The number of
293                        bytes moved is Width size * Count, starting at Address.
294   @param[in]  Buffer   For read operations, the destination buffer to store the results.
295                        For write operations, the source buffer from which to write data.
296 
297   @retval EFI_SUCCESS            The data was read from or written to the PI system.
298   @retval EFI_INVALID_PARAMETER  Width is invalid for this PI system.
299   @retval EFI_INVALID_PARAMETER  Buffer is NULL.
300   @retval EFI_UNSUPPORTED        The Buffer is not aligned for the given Width.
301   @retval EFI_UNSUPPORTED        The address range specified by Address, Width,
302                                  and Count is not valid for this PI system.
303 
304 **/
305 STATIC
306 EFI_STATUS
307 EFIAPI
CpuMemoryServiceWrite(IN EFI_CPU_IO2_PROTOCOL * This,IN EFI_CPU_IO_PROTOCOL_WIDTH Width,IN UINT64 Address,IN UINTN Count,IN VOID * Buffer)308 CpuMemoryServiceWrite (
309   IN EFI_CPU_IO2_PROTOCOL       *This,
310   IN EFI_CPU_IO_PROTOCOL_WIDTH  Width,
311   IN UINT64                     Address,
312   IN UINTN                      Count,
313   IN VOID                       *Buffer
314   )
315 {
316   EFI_STATUS                 Status;
317   UINT8                      InStride;
318   UINT8                      OutStride;
319   EFI_CPU_IO_PROTOCOL_WIDTH  OperationWidth;
320   UINT8                      *Uint8Buffer;
321 
322   Status = CpuIoCheckParameter (TRUE, Width, Address, Count, Buffer);
323   if (EFI_ERROR (Status)) {
324     return Status;
325   }
326 
327   //
328   // Select loop based on the width of the transfer
329   //
330   InStride = mInStride[Width];
331   OutStride = mOutStride[Width];
332   OperationWidth = (EFI_CPU_IO_PROTOCOL_WIDTH) (Width & 0x03);
333   for (Uint8Buffer = Buffer; Count > 0; Address += InStride, Uint8Buffer += OutStride, Count--) {
334     if (OperationWidth == EfiCpuIoWidthUint8) {
335       MmioWrite8 ((UINTN)Address, *Uint8Buffer);
336     } else if (OperationWidth == EfiCpuIoWidthUint16) {
337       MmioWrite16 ((UINTN)Address, *((UINT16 *)Uint8Buffer));
338     } else if (OperationWidth == EfiCpuIoWidthUint32) {
339       MmioWrite32 ((UINTN)Address, *((UINT32 *)Uint8Buffer));
340     } else if (OperationWidth == EfiCpuIoWidthUint64) {
341       MmioWrite64 ((UINTN)Address, *((UINT64 *)Uint8Buffer));
342     }
343   }
344   return EFI_SUCCESS;
345 }
346 
347 /**
348   Reads I/O registers.
349 
350   The I/O operations are carried out exactly as requested. The caller is responsible
351   for satisfying any alignment and I/O width restrictions that a PI System on a
352   platform might require. For example on some platforms, width requests of
353   EfiCpuIoWidthUint64 do not work. Misaligned buffers, on the other hand, will
354   be handled by the driver.
355 
356   If Width is EfiCpuIoWidthUint8, EfiCpuIoWidthUint16, EfiCpuIoWidthUint32,
357   or EfiCpuIoWidthUint64, then both Address and Buffer are incremented for
358   each of the Count operations that is performed.
359 
360   If Width is EfiCpuIoWidthFifoUint8, EfiCpuIoWidthFifoUint16,
361   EfiCpuIoWidthFifoUint32, or EfiCpuIoWidthFifoUint64, then only Buffer is
362   incremented for each of the Count operations that is performed. The read or
363   write operation is performed Count times on the same Address.
364 
365   If Width is EfiCpuIoWidthFillUint8, EfiCpuIoWidthFillUint16,
366   EfiCpuIoWidthFillUint32, or EfiCpuIoWidthFillUint64, then only Address is
367   incremented for each of the Count operations that is performed. The read or
368   write operation is performed Count times from the first element of Buffer.
369 
370   @param[in]  This     A pointer to the EFI_CPU_IO2_PROTOCOL instance.
371   @param[in]  Width    Signifies the width of the I/O or Memory operation.
372   @param[in]  Address  The base address of the I/O operation.
373   @param[in]  Count    The number of I/O operations to perform. The number of
374                        bytes moved is Width size * Count, starting at Address.
375   @param[out] Buffer   For read operations, the destination buffer to store the results.
376                        For write operations, the source buffer from which to write data.
377 
378   @retval EFI_SUCCESS            The data was read from or written to the PI system.
379   @retval EFI_INVALID_PARAMETER  Width is invalid for this PI system.
380   @retval EFI_INVALID_PARAMETER  Buffer is NULL.
381   @retval EFI_UNSUPPORTED        The Buffer is not aligned for the given Width.
382   @retval EFI_UNSUPPORTED        The address range specified by Address, Width,
383                                  and Count is not valid for this PI system.
384 
385 **/
386 STATIC
387 EFI_STATUS
388 EFIAPI
CpuIoServiceRead(IN EFI_CPU_IO2_PROTOCOL * This,IN EFI_CPU_IO_PROTOCOL_WIDTH Width,IN UINT64 Address,IN UINTN Count,OUT VOID * Buffer)389 CpuIoServiceRead (
390   IN  EFI_CPU_IO2_PROTOCOL       *This,
391   IN  EFI_CPU_IO_PROTOCOL_WIDTH  Width,
392   IN  UINT64                     Address,
393   IN  UINTN                      Count,
394   OUT VOID                       *Buffer
395   )
396 {
397   EFI_STATUS                 Status;
398   UINT8                      InStride;
399   UINT8                      OutStride;
400   EFI_CPU_IO_PROTOCOL_WIDTH  OperationWidth;
401   UINT8                      *Uint8Buffer;
402 
403   Status = CpuIoCheckParameter (FALSE, Width, Address, Count, Buffer);
404   if (EFI_ERROR (Status)) {
405     return Status;
406   }
407 
408   Address += PcdGet64 (PcdPciIoTranslation);
409 
410   //
411   // Select loop based on the width of the transfer
412   //
413   InStride = mInStride[Width];
414   OutStride = mOutStride[Width];
415   OperationWidth = (EFI_CPU_IO_PROTOCOL_WIDTH) (Width & 0x03);
416 
417   for (Uint8Buffer = Buffer; Count > 0; Address += InStride, Uint8Buffer += OutStride, Count--) {
418     if (OperationWidth == EfiCpuIoWidthUint8) {
419       *Uint8Buffer = MmioRead8 ((UINTN)Address);
420     } else if (OperationWidth == EfiCpuIoWidthUint16) {
421       *((UINT16 *)Uint8Buffer) = MmioRead16 ((UINTN)Address);
422     } else if (OperationWidth == EfiCpuIoWidthUint32) {
423       *((UINT32 *)Uint8Buffer) = MmioRead32 ((UINTN)Address);
424     }
425   }
426 
427   return EFI_SUCCESS;
428 }
429 
430 /**
431   Write I/O registers.
432 
433   The I/O operations are carried out exactly as requested. The caller is responsible
434   for satisfying any alignment and I/O width restrictions that a PI System on a
435   platform might require. For example on some platforms, width requests of
436   EfiCpuIoWidthUint64 do not work. Misaligned buffers, on the other hand, will
437   be handled by the driver.
438 
439   If Width is EfiCpuIoWidthUint8, EfiCpuIoWidthUint16, EfiCpuIoWidthUint32,
440   or EfiCpuIoWidthUint64, then both Address and Buffer are incremented for
441   each of the Count operations that is performed.
442 
443   If Width is EfiCpuIoWidthFifoUint8, EfiCpuIoWidthFifoUint16,
444   EfiCpuIoWidthFifoUint32, or EfiCpuIoWidthFifoUint64, then only Buffer is
445   incremented for each of the Count operations that is performed. The read or
446   write operation is performed Count times on the same Address.
447 
448   If Width is EfiCpuIoWidthFillUint8, EfiCpuIoWidthFillUint16,
449   EfiCpuIoWidthFillUint32, or EfiCpuIoWidthFillUint64, then only Address is
450   incremented for each of the Count operations that is performed. The read or
451   write operation is performed Count times from the first element of Buffer.
452 
453   @param[in]  This     A pointer to the EFI_CPU_IO2_PROTOCOL instance.
454   @param[in]  Width    Signifies the width of the I/O or Memory operation.
455   @param[in]  Address  The base address of the I/O operation.
456   @param[in]  Count    The number of I/O operations to perform. The number of
457                        bytes moved is Width size * Count, starting at Address.
458   @param[in]  Buffer   For read operations, the destination buffer to store the results.
459                        For write operations, the source buffer from which to write data.
460 
461   @retval EFI_SUCCESS            The data was read from or written to the PI system.
462   @retval EFI_INVALID_PARAMETER  Width is invalid for this PI system.
463   @retval EFI_INVALID_PARAMETER  Buffer is NULL.
464   @retval EFI_UNSUPPORTED        The Buffer is not aligned for the given Width.
465   @retval EFI_UNSUPPORTED        The address range specified by Address, Width,
466                                  and Count is not valid for this PI system.
467 
468 **/
469 STATIC
470 EFI_STATUS
471 EFIAPI
CpuIoServiceWrite(IN EFI_CPU_IO2_PROTOCOL * This,IN EFI_CPU_IO_PROTOCOL_WIDTH Width,IN UINT64 Address,IN UINTN Count,IN VOID * Buffer)472 CpuIoServiceWrite (
473   IN EFI_CPU_IO2_PROTOCOL       *This,
474   IN EFI_CPU_IO_PROTOCOL_WIDTH  Width,
475   IN UINT64                     Address,
476   IN UINTN                      Count,
477   IN VOID                       *Buffer
478   )
479 {
480   EFI_STATUS                 Status;
481   UINT8                      InStride;
482   UINT8                      OutStride;
483   EFI_CPU_IO_PROTOCOL_WIDTH  OperationWidth;
484   UINT8                      *Uint8Buffer;
485 
486   //
487   // Make sure the parameters are valid
488   //
489   Status = CpuIoCheckParameter (FALSE, Width, Address, Count, Buffer);
490   if (EFI_ERROR (Status)) {
491     return Status;
492   }
493 
494   Address += PcdGet64 (PcdPciIoTranslation);
495 
496   //
497   // Select loop based on the width of the transfer
498   //
499   InStride = mInStride[Width];
500   OutStride = mOutStride[Width];
501   OperationWidth = (EFI_CPU_IO_PROTOCOL_WIDTH) (Width & 0x03);
502 
503   for (Uint8Buffer = (UINT8 *)Buffer; Count > 0; Address += InStride, Uint8Buffer += OutStride, Count--) {
504     if (OperationWidth == EfiCpuIoWidthUint8) {
505       MmioWrite8 ((UINTN)Address, *Uint8Buffer);
506     } else if (OperationWidth == EfiCpuIoWidthUint16) {
507       MmioWrite16 ((UINTN)Address, *((UINT16 *)Uint8Buffer));
508     } else if (OperationWidth == EfiCpuIoWidthUint32) {
509       MmioWrite32 ((UINTN)Address, *((UINT32 *)Uint8Buffer));
510     }
511   }
512 
513   return EFI_SUCCESS;
514 }
515 
516 //
517 // CPU I/O 2 Protocol instance
518 //
519 STATIC EFI_CPU_IO2_PROTOCOL mCpuIo2 = {
520   {
521     CpuMemoryServiceRead,
522     CpuMemoryServiceWrite
523   },
524   {
525     CpuIoServiceRead,
526     CpuIoServiceWrite
527   }
528 };
529 
530 
531 /**
532   The user Entry Point for module CpuIo2Dxe. The user code starts with this function.
533 
534   @param[in] ImageHandle    The firmware allocated handle for the EFI image.
535   @param[in] SystemTable    A pointer to the EFI System Table.
536 
537   @retval EFI_SUCCESS       The entry point is executed successfully.
538   @retval other             Some error occurs when executing this entry point.
539 
540 **/
541 EFI_STATUS
542 EFIAPI
ArmPciCpuIo2Initialize(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)543 ArmPciCpuIo2Initialize (
544   IN EFI_HANDLE        ImageHandle,
545   IN EFI_SYSTEM_TABLE  *SystemTable
546   )
547 {
548   EFI_STATUS Status;
549 
550   ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gEfiCpuIo2ProtocolGuid);
551   Status = gBS->InstallMultipleProtocolInterfaces (
552                   &mHandle,
553                   &gEfiCpuIo2ProtocolGuid, &mCpuIo2,
554                   NULL
555                   );
556   ASSERT_EFI_ERROR (Status);
557 
558   return Status;
559 }
560