]> git.proxmox.com Git - mirror_edk2.git/blob - EmulatorPkg/CpuRuntimeDxe/CpuIo.c
EmulatorPkg: Replace BSD License with BSD+Patent License
[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 SPDX-License-Identifier: BSD-2-Clause-Patent
12
13 **/
14
15 #include <PiDxe.h>
16 #include <Protocol/Cpu.h>
17 #include <Protocol/CpuIo2.h>
18
19 #include <Library/BaseLib.h>
20 #include <Library/DebugLib.h>
21 #include <Library/HiiLib.h>
22 #include <Library/UefiLib.h>
23 #include <Library/UefiDriverEntryPoint.h>
24 #include <Library/BaseMemoryLib.h>
25 #include <Library/MemoryAllocationLib.h>
26 #include <Library/UefiBootServicesTableLib.h>
27 #include <CpuDriver.h>
28
29 #define IA32_MAX_IO_ADDRESS 0xFFFF
30 #define IA32_MAX_MEM_ADDRESS 0xFFFFFFFF
31
32 EFI_STATUS
33 CpuIoCheckAddressRange (
34 IN EFI_CPU_IO_PROTOCOL_WIDTH Width,
35 IN UINT64 Address,
36 IN UINTN Count,
37 IN VOID *Buffer,
38 IN UINT64 Limit
39 );
40
41 EFI_STATUS
42 EFIAPI
43 CpuMemoryServiceRead (
44 IN EFI_CPU_IO2_PROTOCOL *This,
45 IN EFI_CPU_IO_PROTOCOL_WIDTH Width,
46 IN UINT64 Address,
47 IN UINTN Count,
48 IN OUT VOID *Buffer
49 )
50 /*++
51
52 Routine Description:
53
54 Perform the Memory Access Read service for the CPU I/O Protocol
55
56 Arguments:
57
58 Pointer to an instance of the CPU I/O Protocol
59 Width of the Memory Access
60 Address of the Memory access
61 Count of the number of accesses to perform
62 Pointer to the buffer to read or write from memory
63
64 Returns:
65
66 Status
67
68 EFI_SUCCESS - The data was read from or written to the EFI
69 System.
70 EFI_INVALID_PARAMETER - Width is invalid for this EFI System.
71 EFI_INVALID_PARAMETER - Buffer is NULL.
72 EFI_UNSUPPORTED - The Buffer is not aligned for the given Width.
73 EFI_UNSUPPORTED - The address range specified by Address, Width,
74 and Count is not valid for this EFI System.
75
76 **/
77 {
78 EFI_STATUS Status;
79
80 if (!Buffer) {
81 return EFI_INVALID_PARAMETER;
82 }
83
84 Status = CpuIoCheckAddressRange (Width, Address, Count, Buffer, IA32_MAX_MEM_ADDRESS);
85 if (EFI_ERROR (Status)) {
86 return Status;
87 }
88
89 //
90 // Do nothing for Nt32 version
91 //
92 return EFI_SUCCESS;
93 }
94
95 EFI_STATUS
96 EFIAPI
97 CpuMemoryServiceWrite (
98 IN EFI_CPU_IO2_PROTOCOL *This,
99 IN EFI_CPU_IO_PROTOCOL_WIDTH Width,
100 IN UINT64 Address,
101 IN UINTN Count,
102 IN OUT VOID *Buffer
103 )
104 /*++
105
106 Routine Description:
107
108 Perform the Memory Access Read service for the CPU I/O Protocol
109
110 Arguments:
111
112 Pointer to an instance of the CPU I/O Protocol
113 Width of the Memory Access
114 Address of the Memory access
115 Count of the number of accesses to perform
116 Pointer to the buffer to read or write from memory
117
118 Returns:
119
120 Status
121
122 EFI_SUCCESS - The data was read from or written to the EFI System.
123 EFI_INVALID_PARAMETER - Width is invalid for this EFI System.
124 EFI_INVALID_PARAMETER - Buffer is NULL.
125 EFI_UNSUPPORTED - The Buffer is not aligned for the given Width.
126 EFI_UNSUPPORTED - The address range specified by Address, Width, and
127 Count is not valid for this EFI System.
128
129 **/
130 {
131 EFI_STATUS Status;
132
133 if (!Buffer) {
134 return EFI_INVALID_PARAMETER;
135 }
136
137 Status = CpuIoCheckAddressRange (Width, Address, Count, Buffer, IA32_MAX_MEM_ADDRESS);
138 if (EFI_ERROR (Status)) {
139 return Status;
140 }
141
142 //
143 // Do nothing for Nt32 version
144 //
145 return EFI_SUCCESS;
146 }
147
148 EFI_STATUS
149 EFIAPI
150 CpuIoServiceRead (
151 IN EFI_CPU_IO2_PROTOCOL *This,
152 IN EFI_CPU_IO_PROTOCOL_WIDTH Width,
153 IN UINT64 UserAddress,
154 IN UINTN Count,
155 IN OUT VOID *UserBuffer
156 )
157 /*++
158
159 Routine Description:
160
161 This is the service that implements the I/O read
162
163 Arguments:
164
165 Pointer to an instance of the CPU I/O Protocol
166 Width of the Memory Access
167 Address of the I/O access
168 Count of the number of accesses to perform
169 Pointer to the buffer to read or write from I/O space
170
171 Returns:
172
173 Status
174 EFI_SUCCESS - The data was read from or written to the EFI System.
175 EFI_INVALID_PARAMETER - Width is invalid for this EFI System.
176 EFI_INVALID_PARAMETER - Buffer is NULL.
177 EFI_UNSUPPORTED - The Buffer is not aligned for the given Width.
178 EFI_UNSUPPORTED - The address range specified by Address, Width, and
179 Count is not valid for this EFI System.
180 **/
181 {
182 UINTN Address;
183 EFI_STATUS Status;
184
185 if (!UserBuffer) {
186 return EFI_INVALID_PARAMETER;
187 }
188
189 Address = (UINTN) UserAddress;
190
191 if (Width >= EfiCpuIoWidthMaximum) {
192 return EFI_INVALID_PARAMETER;
193 }
194
195 Status = CpuIoCheckAddressRange (Width, Address, Count, UserBuffer, IA32_MAX_IO_ADDRESS);
196 if (EFI_ERROR (Status)) {
197 return Status;
198 }
199
200 //
201 // Do nothing for Nt32 version
202 //
203 return EFI_SUCCESS;
204 }
205
206 EFI_STATUS
207 EFIAPI
208 CpuIoServiceWrite (
209 IN EFI_CPU_IO2_PROTOCOL *This,
210 IN EFI_CPU_IO_PROTOCOL_WIDTH Width,
211 IN UINT64 UserAddress,
212 IN UINTN Count,
213 IN OUT VOID *UserBuffer
214 )
215 /*++
216
217 Routine Description:
218
219
220 This is the service that implements the I/O Write
221
222 Arguments:
223
224 Pointer to an instance of the CPU I/O Protocol
225 Width of the Memory Access
226 Address of the I/O access
227 Count of the number of accesses to perform
228 Pointer to the buffer to read or write from I/O space
229
230 Returns:
231
232 Status
233
234 Status
235 EFI_SUCCESS - The data was read from or written to the EFI System.
236 EFI_INVALID_PARAMETER - Width is invalid for this EFI System.
237 EFI_INVALID_PARAMETER - Buffer is NULL.
238 EFI_UNSUPPORTED - The Buffer is not aligned for the given Width.
239 EFI_UNSUPPORTED - The address range specified by Address, Width, and
240 Count is not valid for this EFI System.
241
242 **/
243 {
244 UINTN Address;
245 EFI_STATUS Status;
246
247 if (!UserBuffer) {
248 return EFI_INVALID_PARAMETER;
249 }
250
251 Address = (UINTN) UserAddress;
252
253 if (Width >= EfiCpuIoWidthMaximum) {
254 return EFI_INVALID_PARAMETER;
255 }
256
257 Status = CpuIoCheckAddressRange (Width, Address, Count, UserBuffer, IA32_MAX_IO_ADDRESS);
258 if (EFI_ERROR (Status)) {
259 return Status;
260 }
261
262 //
263 // Do nothing for Nt32 version
264 //
265 return EFI_SUCCESS;
266 }
267
268
269 /*++
270
271 Routine Description:
272
273 Arguments:
274
275 Width - TODO: add argument description
276 Address - TODO: add argument description
277 Count - TODO: add argument description
278 Buffer - TODO: add argument description
279 Limit - TODO: add argument description
280
281 Returns:
282
283 EFI_UNSUPPORTED - TODO: Add description for return value
284 EFI_UNSUPPORTED - TODO: Add description for return value
285 EFI_UNSUPPORTED - TODO: Add description for return value
286 EFI_SUCCESS - TODO: Add description for return value
287
288 **/
289 EFI_STATUS
290 CpuIoCheckAddressRange (
291 IN EFI_CPU_IO_PROTOCOL_WIDTH Width,
292 IN UINT64 Address,
293 IN UINTN Count,
294 IN VOID *Buffer,
295 IN UINT64 Limit
296 )
297 {
298 UINTN AlignMask;
299
300 if (Address > Limit) {
301 return EFI_UNSUPPORTED;
302 }
303
304 //
305 // For FiFo type, the target address won't increase during the access, so treat count as 1
306 //
307 if (Width >= EfiCpuIoWidthFifoUint8 && Width <= EfiCpuIoWidthFifoUint64) {
308 Count = 1;
309 }
310
311 Width = Width & 0x03;
312 if ((Address - 1 + LShiftU64 (Count, Width)) > Limit) {
313 return EFI_UNSUPPORTED;
314 }
315
316 AlignMask = (1 << Width) - 1;
317 if ((UINTN) Buffer & AlignMask) {
318 return EFI_UNSUPPORTED;
319 }
320
321 return EFI_SUCCESS;
322 }
323
324