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