• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*++ @file
2   This is the code that publishes the CPU I/O Protocol.
3   The intent herein is to have a single I/O service that can load
4   as early as possible, extend into runtime, and be layered upon by
5   the implementations of architectural protocols and the PCI Root
6   Bridge I/O Protocol.
7 
8 
9 Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>
10 Portions copyright (c) 2011, Apple Inc. All rights reserved.
11 This program and the accompanying materials
12 are licensed and made available under the terms and conditions of the BSD License
13 which accompanies this distribution.  The full text of the license may be found at
14 http://opensource.org/licenses/bsd-license.php
15 
16 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
17 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 
19 **/
20 
21 #include <PiDxe.h>
22 #include <Protocol/Cpu.h>
23 #include <Protocol/CpuIo2.h>
24 
25 #include <Library/BaseLib.h>
26 #include <Library/DebugLib.h>
27 #include <Library/HiiLib.h>
28 #include <Library/UefiLib.h>
29 #include <Library/UefiDriverEntryPoint.h>
30 #include <Library/BaseMemoryLib.h>
31 #include <Library/MemoryAllocationLib.h>
32 #include <Library/UefiBootServicesTableLib.h>
33 #include <CpuDriver.h>
34 
35 #define IA32_MAX_IO_ADDRESS   0xFFFF
36 #define IA32_MAX_MEM_ADDRESS  0xFFFFFFFF
37 
38 EFI_STATUS
39 CpuIoCheckAddressRange (
40   IN  EFI_CPU_IO_PROTOCOL_WIDTH         Width,
41   IN  UINT64                            Address,
42   IN  UINTN                             Count,
43   IN  VOID                              *Buffer,
44   IN  UINT64                            Limit
45   );
46 
47 EFI_STATUS
48 EFIAPI
CpuMemoryServiceRead(IN EFI_CPU_IO2_PROTOCOL * This,IN EFI_CPU_IO_PROTOCOL_WIDTH Width,IN UINT64 Address,IN UINTN Count,IN OUT VOID * Buffer)49 CpuMemoryServiceRead (
50   IN  EFI_CPU_IO2_PROTOCOL              *This,
51   IN  EFI_CPU_IO_PROTOCOL_WIDTH         Width,
52   IN  UINT64                            Address,
53   IN  UINTN                             Count,
54   IN  OUT VOID                          *Buffer
55   )
56 /*++
57 
58 Routine Description:
59 
60   Perform the Memory Access Read service for the CPU I/O Protocol
61 
62 Arguments:
63 
64   Pointer to an instance of the CPU I/O Protocol
65   Width of the Memory Access
66   Address of the Memory access
67   Count of the number of accesses to perform
68   Pointer to the buffer to read or write from memory
69 
70 Returns:
71 
72   Status
73 
74   EFI_SUCCESS             - The data was read from or written to the EFI
75                             System.
76   EFI_INVALID_PARAMETER   - Width is invalid for this EFI System.
77   EFI_INVALID_PARAMETER   - Buffer is NULL.
78   EFI_UNSUPPORTED         - The Buffer is not aligned for the given Width.
79   EFI_UNSUPPORTED         - The address range specified by Address, Width,
80                             and Count is not valid for this EFI System.
81 
82 **/
83 {
84   EFI_STATUS  Status;
85 
86   if (!Buffer) {
87     return EFI_INVALID_PARAMETER;
88   }
89 
90   Status = CpuIoCheckAddressRange (Width, Address, Count, Buffer, IA32_MAX_MEM_ADDRESS);
91   if (EFI_ERROR (Status)) {
92     return Status;
93   }
94 
95   //
96   // Do nothing for Nt32 version
97   //
98   return EFI_SUCCESS;
99 }
100 
101 EFI_STATUS
102 EFIAPI
CpuMemoryServiceWrite(IN EFI_CPU_IO2_PROTOCOL * This,IN EFI_CPU_IO_PROTOCOL_WIDTH Width,IN UINT64 Address,IN UINTN Count,IN OUT VOID * Buffer)103 CpuMemoryServiceWrite (
104   IN EFI_CPU_IO2_PROTOCOL               *This,
105   IN  EFI_CPU_IO_PROTOCOL_WIDTH         Width,
106   IN  UINT64                            Address,
107   IN  UINTN                             Count,
108   IN  OUT VOID                          *Buffer
109   )
110 /*++
111 
112 Routine Description:
113 
114   Perform the Memory Access Read service for the CPU I/O Protocol
115 
116 Arguments:
117 
118   Pointer to an instance of the CPU I/O Protocol
119   Width of the Memory Access
120   Address of the Memory access
121   Count of the number of accesses to perform
122   Pointer to the buffer to read or write from memory
123 
124 Returns:
125 
126   Status
127 
128   EFI_SUCCESS             - The data was read from or written to the EFI System.
129   EFI_INVALID_PARAMETER   - Width is invalid for this EFI System.
130   EFI_INVALID_PARAMETER   - Buffer is NULL.
131   EFI_UNSUPPORTED         - The Buffer is not aligned for the given Width.
132   EFI_UNSUPPORTED         - The address range specified by Address, Width, and
133                             Count is not valid for this EFI System.
134 
135 **/
136 {
137   EFI_STATUS  Status;
138 
139   if (!Buffer) {
140     return EFI_INVALID_PARAMETER;
141   }
142 
143   Status = CpuIoCheckAddressRange (Width, Address, Count, Buffer, IA32_MAX_MEM_ADDRESS);
144   if (EFI_ERROR (Status)) {
145     return Status;
146   }
147 
148   //
149   // Do nothing for Nt32 version
150   //
151   return EFI_SUCCESS;
152 }
153 
154 EFI_STATUS
155 EFIAPI
CpuIoServiceRead(IN EFI_CPU_IO2_PROTOCOL * This,IN EFI_CPU_IO_PROTOCOL_WIDTH Width,IN UINT64 UserAddress,IN UINTN Count,IN OUT VOID * UserBuffer)156 CpuIoServiceRead (
157   IN EFI_CPU_IO2_PROTOCOL               *This,
158   IN  EFI_CPU_IO_PROTOCOL_WIDTH         Width,
159   IN  UINT64                            UserAddress,
160   IN  UINTN                             Count,
161   IN  OUT VOID                          *UserBuffer
162   )
163 /*++
164 
165 Routine Description:
166 
167   This is the service that implements the I/O read
168 
169 Arguments:
170 
171   Pointer to an instance of the CPU I/O Protocol
172   Width of the Memory Access
173   Address of the I/O access
174   Count of the number of accesses to perform
175   Pointer to the buffer to read or write from I/O space
176 
177 Returns:
178 
179   Status
180   EFI_SUCCESS             - The data was read from or written to the EFI System.
181   EFI_INVALID_PARAMETER   - Width is invalid for this EFI System.
182   EFI_INVALID_PARAMETER   - Buffer is NULL.
183   EFI_UNSUPPORTED         - The Buffer is not aligned for the given Width.
184   EFI_UNSUPPORTED         - The address range specified by Address, Width, and
185                             Count is not valid for this EFI System.
186 **/
187 {
188   UINTN       Address;
189   EFI_STATUS  Status;
190 
191   if (!UserBuffer) {
192     return EFI_INVALID_PARAMETER;
193   }
194 
195   Address = (UINTN) UserAddress;
196 
197   if (Width >= EfiCpuIoWidthMaximum) {
198     return EFI_INVALID_PARAMETER;
199   }
200 
201   Status = CpuIoCheckAddressRange (Width, Address, Count, UserBuffer, IA32_MAX_IO_ADDRESS);
202   if (EFI_ERROR (Status)) {
203     return Status;
204   }
205 
206   //
207   // Do nothing for Nt32 version
208   //
209   return EFI_SUCCESS;
210 }
211 
212 EFI_STATUS
213 EFIAPI
CpuIoServiceWrite(IN EFI_CPU_IO2_PROTOCOL * This,IN EFI_CPU_IO_PROTOCOL_WIDTH Width,IN UINT64 UserAddress,IN UINTN Count,IN OUT VOID * UserBuffer)214 CpuIoServiceWrite (
215   IN EFI_CPU_IO2_PROTOCOL               *This,
216   IN  EFI_CPU_IO_PROTOCOL_WIDTH         Width,
217   IN  UINT64                            UserAddress,
218   IN  UINTN                             Count,
219   IN  OUT VOID                          *UserBuffer
220   )
221 /*++
222 
223 Routine Description:
224 
225 
226   This is the service that implements the I/O Write
227 
228 Arguments:
229 
230   Pointer to an instance of the CPU I/O Protocol
231   Width of the Memory Access
232   Address of the I/O access
233   Count of the number of accesses to perform
234   Pointer to the buffer to read or write from I/O space
235 
236 Returns:
237 
238   Status
239 
240   Status
241   EFI_SUCCESS             - The data was read from or written to the EFI System.
242   EFI_INVALID_PARAMETER   - Width is invalid for this EFI System.
243   EFI_INVALID_PARAMETER   - Buffer is NULL.
244   EFI_UNSUPPORTED         - The Buffer is not aligned for the given Width.
245   EFI_UNSUPPORTED         - The address range specified by Address, Width, and
246                             Count is not valid for this EFI System.
247 
248 **/
249 {
250   UINTN       Address;
251   EFI_STATUS  Status;
252 
253   if (!UserBuffer) {
254     return EFI_INVALID_PARAMETER;
255   }
256 
257   Address = (UINTN) UserAddress;
258 
259   if (Width >= EfiCpuIoWidthMaximum) {
260     return EFI_INVALID_PARAMETER;
261   }
262 
263   Status = CpuIoCheckAddressRange (Width, Address, Count, UserBuffer, IA32_MAX_IO_ADDRESS);
264   if (EFI_ERROR (Status)) {
265     return Status;
266   }
267 
268   //
269   // Do nothing for Nt32 version
270   //
271   return EFI_SUCCESS;
272 }
273 
274 
275 /*++
276 
277 Routine Description:
278 
279 Arguments:
280 
281   Width   - TODO: add argument description
282   Address - TODO: add argument description
283   Count   - TODO: add argument description
284   Buffer  - TODO: add argument description
285   Limit   - TODO: add argument description
286 
287 Returns:
288 
289   EFI_UNSUPPORTED - TODO: Add description for return value
290   EFI_UNSUPPORTED - TODO: Add description for return value
291   EFI_UNSUPPORTED - TODO: Add description for return value
292   EFI_SUCCESS - TODO: Add description for return value
293 
294 **/
295 EFI_STATUS
CpuIoCheckAddressRange(IN EFI_CPU_IO_PROTOCOL_WIDTH Width,IN UINT64 Address,IN UINTN Count,IN VOID * Buffer,IN UINT64 Limit)296 CpuIoCheckAddressRange (
297   IN  EFI_CPU_IO_PROTOCOL_WIDTH         Width,
298   IN  UINT64                            Address,
299   IN  UINTN                             Count,
300   IN  VOID                              *Buffer,
301   IN  UINT64                            Limit
302   )
303 {
304   UINTN AlignMask;
305 
306   if (Address > Limit) {
307     return EFI_UNSUPPORTED;
308   }
309 
310   //
311   // For FiFo type, the target address won't increase during the access, so treat count as 1
312   //
313   if (Width >= EfiCpuIoWidthFifoUint8 && Width <= EfiCpuIoWidthFifoUint64) {
314     Count = 1;
315   }
316 
317   Width = Width & 0x03;
318   if ((Address - 1 + LShiftU64 (Count, Width)) > Limit) {
319     return EFI_UNSUPPORTED;
320   }
321 
322   AlignMask = (1 << Width) - 1;
323   if ((UINTN) Buffer & AlignMask) {
324     return EFI_UNSUPPORTED;
325   }
326 
327   return EFI_SUCCESS;
328 }
329 
330 
331