]> git.proxmox.com Git - mirror_edk2.git/blob - EmulatorPkg/CpuRuntimeDxe/CpuIo.c
37905f892afd5c66fd5a9c5681c180a60c45a355
[mirror_edk2.git] / EmulatorPkg / CpuRuntimeDxe / CpuIo.c
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
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
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
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
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
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