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