Vishal Bhoj | 82c8071 | 2015-12-15 21:13:33 +0530 | [diff] [blame^] | 1 | /** @file
|
| 2 | Produces the CPU I/O PPI.
|
| 3 |
|
| 4 | Copyright (c) 2009 - 2012, Intel Corporation. All rights reserved.<BR>
|
| 5 | This program and the accompanying materials
|
| 6 | are licensed and made available under the terms and conditions of the BSD License
|
| 7 | which accompanies this distribution. The full text of the license may be found at
|
| 8 | http://opensource.org/licenses/bsd-license.php
|
| 9 |
|
| 10 | THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
| 11 | WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
| 12 |
|
| 13 | **/
|
| 14 |
|
| 15 | #include "CpuIoPei.h"
|
| 16 |
|
| 17 | //
|
| 18 | // Instance of CPU I/O PPI
|
| 19 | //
|
| 20 | EFI_PEI_CPU_IO_PPI gCpuIoPpi = {
|
| 21 | {
|
| 22 | CpuMemoryServiceRead,
|
| 23 | CpuMemoryServiceWrite
|
| 24 | },
|
| 25 | {
|
| 26 | CpuIoServiceRead,
|
| 27 | CpuIoServiceWrite
|
| 28 | },
|
| 29 | CpuIoRead8,
|
| 30 | CpuIoRead16,
|
| 31 | CpuIoRead32,
|
| 32 | CpuIoRead64,
|
| 33 | CpuIoWrite8,
|
| 34 | CpuIoWrite16,
|
| 35 | CpuIoWrite32,
|
| 36 | CpuIoWrite64,
|
| 37 | CpuMemRead8,
|
| 38 | CpuMemRead16,
|
| 39 | CpuMemRead32,
|
| 40 | CpuMemRead64,
|
| 41 | CpuMemWrite8,
|
| 42 | CpuMemWrite16,
|
| 43 | CpuMemWrite32,
|
| 44 | CpuMemWrite64
|
| 45 | };
|
| 46 |
|
| 47 | //
|
| 48 | // PPI Descriptor used to install the CPU I/O PPI
|
| 49 | //
|
| 50 | EFI_PEI_PPI_DESCRIPTOR gPpiList = {
|
| 51 | (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
|
| 52 | &gEfiPeiCpuIoPpiInstalledGuid,
|
| 53 | NULL
|
| 54 | };
|
| 55 |
|
| 56 | //
|
| 57 | // Lookup table for increment values based on transfer widths
|
| 58 | //
|
| 59 | UINT8 mInStride[] = {
|
| 60 | 1, // EfiPeiCpuIoWidthUint8
|
| 61 | 2, // EfiPeiCpuIoWidthUint16
|
| 62 | 4, // EfiPeiCpuIoWidthUint32
|
| 63 | 8, // EfiPeiCpuIoWidthUint64
|
| 64 | 0, // EfiPeiCpuIoWidthFifoUint8
|
| 65 | 0, // EfiPeiCpuIoWidthFifoUint16
|
| 66 | 0, // EfiPeiCpuIoWidthFifoUint32
|
| 67 | 0, // EfiPeiCpuIoWidthFifoUint64
|
| 68 | 1, // EfiPeiCpuIoWidthFillUint8
|
| 69 | 2, // EfiPeiCpuIoWidthFillUint16
|
| 70 | 4, // EfiPeiCpuIoWidthFillUint32
|
| 71 | 8 // EfiPeiCpuIoWidthFillUint64
|
| 72 | };
|
| 73 |
|
| 74 | //
|
| 75 | // Lookup table for increment values based on transfer widths
|
| 76 | //
|
| 77 | UINT8 mOutStride[] = {
|
| 78 | 1, // EfiPeiCpuIoWidthUint8
|
| 79 | 2, // EfiPeiCpuIoWidthUint16
|
| 80 | 4, // EfiPeiCpuIoWidthUint32
|
| 81 | 8, // EfiPeiCpuIoWidthUint64
|
| 82 | 1, // EfiPeiCpuIoWidthFifoUint8
|
| 83 | 2, // EfiPeiCpuIoWidthFifoUint16
|
| 84 | 4, // EfiPeiCpuIoWidthFifoUint32
|
| 85 | 8, // EfiPeiCpuIoWidthFifoUint64
|
| 86 | 0, // EfiPeiCpuIoWidthFillUint8
|
| 87 | 0, // EfiPeiCpuIoWidthFillUint16
|
| 88 | 0, // EfiPeiCpuIoWidthFillUint32
|
| 89 | 0 // EfiPeiCpuIoWidthFillUint64
|
| 90 | };
|
| 91 |
|
| 92 | /**
|
| 93 | Check parameters to a CPU I/O PPI service request.
|
| 94 |
|
| 95 | @param[in] MmioOperation TRUE for an MMIO operation, FALSE for I/O Port operation.
|
| 96 | @param[in] Width The width of the access. Enumerated in bytes.
|
| 97 | @param[in] Address The physical address of the access.
|
| 98 | @param[in] Count The number of accesses to perform.
|
| 99 | @param[in] Buffer A pointer to the buffer of data.
|
| 100 |
|
| 101 | @retval EFI_SUCCESS The parameters for this request pass the checks.
|
| 102 | @retval EFI_INVALID_PARAMETER Width is invalid for this EFI system.
|
| 103 | @retval EFI_INVALID_PARAMETER Buffer is NULL.
|
| 104 | @retval EFI_UNSUPPORTED The address range specified by Address, Width,
|
| 105 | and Count is not valid for this EFI system.
|
| 106 |
|
| 107 | **/
|
| 108 | EFI_STATUS
|
| 109 | CpuIoCheckParameter (
|
| 110 | IN BOOLEAN MmioOperation,
|
| 111 | IN EFI_PEI_CPU_IO_PPI_WIDTH Width,
|
| 112 | IN UINT64 Address,
|
| 113 | IN UINTN Count,
|
| 114 | IN VOID *Buffer
|
| 115 | )
|
| 116 | {
|
| 117 | UINT64 MaxCount;
|
| 118 | UINT64 Limit;
|
| 119 |
|
| 120 | //
|
| 121 | // Check to see if Buffer is NULL
|
| 122 | //
|
| 123 | if (Buffer == NULL) {
|
| 124 | return EFI_INVALID_PARAMETER;
|
| 125 | }
|
| 126 |
|
| 127 | //
|
| 128 | // Check to see if Width is in the valid range
|
| 129 | //
|
| 130 | if ((UINT32)Width >= EfiPeiCpuIoWidthMaximum) {
|
| 131 | return EFI_INVALID_PARAMETER;
|
| 132 | }
|
| 133 |
|
| 134 | //
|
| 135 | // For FIFO type, the target address won't increase during the access,
|
| 136 | // so treat Count as 1
|
| 137 | //
|
| 138 | if (Width >= EfiPeiCpuIoWidthFifoUint8 && Width <= EfiPeiCpuIoWidthFifoUint64) {
|
| 139 | Count = 1;
|
| 140 | }
|
| 141 |
|
| 142 | //
|
| 143 | // Check to see if Width is in the valid range for I/O Port operations
|
| 144 | //
|
| 145 | Width = (EFI_PEI_CPU_IO_PPI_WIDTH) (Width & 0x03);
|
| 146 | if (!MmioOperation && (Width == EfiPeiCpuIoWidthUint64)) {
|
| 147 | return EFI_INVALID_PARAMETER;
|
| 148 | }
|
| 149 |
|
| 150 | //
|
| 151 | // Check to see if any address associated with this transfer exceeds the maximum
|
| 152 | // allowed address. The maximum address implied by the parameters passed in is
|
| 153 | // Address + Size * Count. If the following condition is met, then the transfer
|
| 154 | // is not supported.
|
| 155 | //
|
| 156 | // Address + Size * Count > (MmioOperation ? MAX_ADDRESS : MAX_IO_PORT_ADDRESS) + 1
|
| 157 | //
|
| 158 | // Since MAX_ADDRESS can be the maximum integer value supported by the CPU and Count
|
| 159 | // can also be the maximum integer value supported by the CPU, this range
|
| 160 | // check must be adjusted to avoid all overflow conditions.
|
| 161 | //
|
| 162 | // The following form of the range check is equivalent but assumes that
|
| 163 | // MAX_ADDRESS and MAX_IO_PORT_ADDRESS are of the form (2^n - 1).
|
| 164 | //
|
| 165 | Limit = (MmioOperation ? MAX_ADDRESS : MAX_IO_PORT_ADDRESS);
|
| 166 | if (Count == 0) {
|
| 167 | if (Address > Limit) {
|
| 168 | return EFI_UNSUPPORTED;
|
| 169 | }
|
| 170 | } else {
|
| 171 | MaxCount = RShiftU64 (Limit, Width);
|
| 172 | if (MaxCount < (Count - 1)) {
|
| 173 | return EFI_UNSUPPORTED;
|
| 174 | }
|
| 175 | if (Address > LShiftU64 (MaxCount - Count + 1, Width)) {
|
| 176 | return EFI_UNSUPPORTED;
|
| 177 | }
|
| 178 | }
|
| 179 |
|
| 180 | return EFI_SUCCESS;
|
| 181 | }
|
| 182 |
|
| 183 | /**
|
| 184 | Reads memory-mapped registers.
|
| 185 |
|
| 186 | @param[in] PeiServices An indirect pointer to the PEI Services Table
|
| 187 | published by the PEI Foundation.
|
| 188 | @param[in] This Pointer to local data for the interface.
|
| 189 | @param[in] Width The width of the access. Enumerated in bytes.
|
| 190 | @param[in] Address The physical address of the access.
|
| 191 | @param[in] Count The number of accesses to perform.
|
| 192 | @param[out] Buffer A pointer to the buffer of data.
|
| 193 |
|
| 194 | @retval EFI_SUCCESS The function completed successfully.
|
| 195 | @retval EFI_INVALID_PARAMETER Width is invalid for this EFI system.
|
| 196 | @retval EFI_INVALID_PARAMETER Buffer is NULL.
|
| 197 | @retval EFI_UNSUPPORTED The address range specified by Address, Width,
|
| 198 | and Count is not valid for this EFI system.
|
| 199 |
|
| 200 | **/
|
| 201 | EFI_STATUS
|
| 202 | EFIAPI
|
| 203 | CpuMemoryServiceRead (
|
| 204 | IN CONST EFI_PEI_SERVICES **PeiServices,
|
| 205 | IN CONST EFI_PEI_CPU_IO_PPI *This,
|
| 206 | IN EFI_PEI_CPU_IO_PPI_WIDTH Width,
|
| 207 | IN UINT64 Address,
|
| 208 | IN UINTN Count,
|
| 209 | OUT VOID *Buffer
|
| 210 | )
|
| 211 | {
|
| 212 | EFI_STATUS Status;
|
| 213 | UINT8 InStride;
|
| 214 | UINT8 OutStride;
|
| 215 | EFI_PEI_CPU_IO_PPI_WIDTH OperationWidth;
|
| 216 | BOOLEAN Aligned;
|
| 217 | UINT8 *Uint8Buffer;
|
| 218 |
|
| 219 | Status = CpuIoCheckParameter (TRUE, Width, Address, Count, Buffer);
|
| 220 | if (EFI_ERROR (Status)) {
|
| 221 | return Status;
|
| 222 | }
|
| 223 |
|
| 224 | //
|
| 225 | // Select loop based on the width of the transfer
|
| 226 | //
|
| 227 | InStride = mInStride[Width];
|
| 228 | OutStride = mOutStride[Width];
|
| 229 | OperationWidth = (EFI_PEI_CPU_IO_PPI_WIDTH) (Width & 0x03);
|
| 230 | Aligned = (BOOLEAN)(((UINTN)Buffer & (mInStride[OperationWidth] - 1)) == 0x00);
|
| 231 | for (Uint8Buffer = Buffer; Count > 0; Address += InStride, Uint8Buffer += OutStride, Count--) {
|
| 232 | if (OperationWidth == EfiPeiCpuIoWidthUint8) {
|
| 233 | *Uint8Buffer = MmioRead8 ((UINTN)Address);
|
| 234 | } else if (OperationWidth == EfiPeiCpuIoWidthUint16) {
|
| 235 | if (Aligned) {
|
| 236 | *((UINT16 *)Uint8Buffer) = MmioRead16 ((UINTN)Address);
|
| 237 | } else {
|
| 238 | WriteUnaligned16 ((UINT16 *)Uint8Buffer, MmioRead16 ((UINTN)Address));
|
| 239 | }
|
| 240 | } else if (OperationWidth == EfiPeiCpuIoWidthUint32) {
|
| 241 | if (Aligned) {
|
| 242 | *((UINT32 *)Uint8Buffer) = MmioRead32 ((UINTN)Address);
|
| 243 | } else {
|
| 244 | WriteUnaligned32 ((UINT32 *)Uint8Buffer, MmioRead32 ((UINTN)Address));
|
| 245 | }
|
| 246 | } else if (OperationWidth == EfiPeiCpuIoWidthUint64) {
|
| 247 | if (Aligned) {
|
| 248 | *((UINT64 *)Uint8Buffer) = MmioRead64 ((UINTN)Address);
|
| 249 | } else {
|
| 250 | WriteUnaligned64 ((UINT64 *)Uint8Buffer, MmioRead64 ((UINTN)Address));
|
| 251 | }
|
| 252 | }
|
| 253 | }
|
| 254 | return EFI_SUCCESS;
|
| 255 | }
|
| 256 |
|
| 257 | /**
|
| 258 | Writes memory-mapped registers.
|
| 259 |
|
| 260 | @param[in] PeiServices An indirect pointer to the PEI Services Table
|
| 261 | published by the PEI Foundation.
|
| 262 | @param[in] This Pointer to local data for the interface.
|
| 263 | @param[in] Width The width of the access. Enumerated in bytes.
|
| 264 | @param[in] Address The physical address of the access.
|
| 265 | @param[in] Count The number of accesses to perform.
|
| 266 | @param[in] Buffer A pointer to the buffer of data.
|
| 267 |
|
| 268 | @retval EFI_SUCCESS The function completed successfully.
|
| 269 | @retval EFI_INVALID_PARAMETER Width is invalid for this EFI system.
|
| 270 | @retval EFI_INVALID_PARAMETER Buffer is NULL.
|
| 271 | @retval EFI_UNSUPPORTED The address range specified by Address, Width,
|
| 272 | and Count is not valid for this EFI system.
|
| 273 |
|
| 274 | **/
|
| 275 | EFI_STATUS
|
| 276 | EFIAPI
|
| 277 | CpuMemoryServiceWrite (
|
| 278 | IN CONST EFI_PEI_SERVICES **PeiServices,
|
| 279 | IN CONST EFI_PEI_CPU_IO_PPI *This,
|
| 280 | IN EFI_PEI_CPU_IO_PPI_WIDTH Width,
|
| 281 | IN UINT64 Address,
|
| 282 | IN UINTN Count,
|
| 283 | IN VOID *Buffer
|
| 284 | )
|
| 285 | {
|
| 286 | EFI_STATUS Status;
|
| 287 | UINT8 InStride;
|
| 288 | UINT8 OutStride;
|
| 289 | EFI_PEI_CPU_IO_PPI_WIDTH OperationWidth;
|
| 290 | BOOLEAN Aligned;
|
| 291 | UINT8 *Uint8Buffer;
|
| 292 |
|
| 293 | Status = CpuIoCheckParameter (TRUE, Width, Address, Count, Buffer);
|
| 294 | if (EFI_ERROR (Status)) {
|
| 295 | return Status;
|
| 296 | }
|
| 297 |
|
| 298 | //
|
| 299 | // Select loop based on the width of the transfer
|
| 300 | //
|
| 301 | InStride = mInStride[Width];
|
| 302 | OutStride = mOutStride[Width];
|
| 303 | OperationWidth = (EFI_PEI_CPU_IO_PPI_WIDTH) (Width & 0x03);
|
| 304 | Aligned = (BOOLEAN)(((UINTN)Buffer & (mInStride[OperationWidth] - 1)) == 0x00);
|
| 305 | for (Uint8Buffer = Buffer; Count > 0; Address += InStride, Uint8Buffer += OutStride, Count--) {
|
| 306 | if (OperationWidth == EfiPeiCpuIoWidthUint8) {
|
| 307 | MmioWrite8 ((UINTN)Address, *Uint8Buffer);
|
| 308 | } else if (OperationWidth == EfiPeiCpuIoWidthUint16) {
|
| 309 | if (Aligned) {
|
| 310 | MmioWrite16 ((UINTN)Address, *((UINT16 *)Uint8Buffer));
|
| 311 | } else {
|
| 312 | MmioWrite16 ((UINTN)Address, ReadUnaligned16 ((UINT16 *)Uint8Buffer));
|
| 313 | }
|
| 314 | } else if (OperationWidth == EfiPeiCpuIoWidthUint32) {
|
| 315 | if (Aligned) {
|
| 316 | MmioWrite32 ((UINTN)Address, *((UINT32 *)Uint8Buffer));
|
| 317 | } else {
|
| 318 | MmioWrite32 ((UINTN)Address, ReadUnaligned32 ((UINT32 *)Uint8Buffer));
|
| 319 | }
|
| 320 | } else if (OperationWidth == EfiPeiCpuIoWidthUint64) {
|
| 321 | if (Aligned) {
|
| 322 | MmioWrite64 ((UINTN)Address, *((UINT64 *)Uint8Buffer));
|
| 323 | } else {
|
| 324 | MmioWrite64 ((UINTN)Address, ReadUnaligned64 ((UINT64 *)Uint8Buffer));
|
| 325 | }
|
| 326 | }
|
| 327 | }
|
| 328 | return EFI_SUCCESS;
|
| 329 | }
|
| 330 |
|
| 331 | /**
|
| 332 | Reads I/O registers.
|
| 333 |
|
| 334 | @param[in] PeiServices An indirect pointer to the PEI Services Table
|
| 335 | published by the PEI Foundation.
|
| 336 | @param[in] This Pointer to local data for the interface.
|
| 337 | @param[in] Width The width of the access. Enumerated in bytes.
|
| 338 | @param[in] Address The physical address of the access.
|
| 339 | @param[in] Count The number of accesses to perform.
|
| 340 | @param[out] Buffer A pointer to the buffer of data.
|
| 341 |
|
| 342 | @retval EFI_SUCCESS The function completed successfully.
|
| 343 | @retval EFI_INVALID_PARAMETER Width is invalid for this EFI system.
|
| 344 | @retval EFI_INVALID_PARAMETER Buffer is NULL.
|
| 345 | @retval EFI_UNSUPPORTED The address range specified by Address, Width,
|
| 346 | and Count is not valid for this EFI system.
|
| 347 |
|
| 348 | **/
|
| 349 | EFI_STATUS
|
| 350 | EFIAPI
|
| 351 | CpuIoServiceRead (
|
| 352 | IN CONST EFI_PEI_SERVICES **PeiServices,
|
| 353 | IN CONST EFI_PEI_CPU_IO_PPI *This,
|
| 354 | IN EFI_PEI_CPU_IO_PPI_WIDTH Width,
|
| 355 | IN UINT64 Address,
|
| 356 | IN UINTN Count,
|
| 357 | OUT VOID *Buffer
|
| 358 | )
|
| 359 | {
|
| 360 | EFI_STATUS Status;
|
| 361 | UINT8 InStride;
|
| 362 | UINT8 OutStride;
|
| 363 | EFI_PEI_CPU_IO_PPI_WIDTH OperationWidth;
|
| 364 | BOOLEAN Aligned;
|
| 365 | UINT8 *Uint8Buffer;
|
| 366 |
|
| 367 | Status = CpuIoCheckParameter (FALSE, Width, Address, Count, Buffer);
|
| 368 | if (EFI_ERROR (Status)) {
|
| 369 | return Status;
|
| 370 | }
|
| 371 |
|
| 372 | //
|
| 373 | // Select loop based on the width of the transfer
|
| 374 | //
|
| 375 | InStride = mInStride[Width];
|
| 376 | OutStride = mOutStride[Width];
|
| 377 | OperationWidth = (EFI_PEI_CPU_IO_PPI_WIDTH) (Width & 0x03);
|
| 378 | Aligned = (BOOLEAN)(((UINTN)Buffer & (mInStride[OperationWidth] - 1)) == 0x00);
|
| 379 | for (Uint8Buffer = Buffer; Count > 0; Address += InStride, Uint8Buffer += OutStride, Count--) {
|
| 380 | if (OperationWidth == EfiPeiCpuIoWidthUint8) {
|
| 381 | *Uint8Buffer = IoRead8 ((UINTN)Address);
|
| 382 | } else if (OperationWidth == EfiPeiCpuIoWidthUint16) {
|
| 383 | if (Aligned) {
|
| 384 | *((UINT16 *)Uint8Buffer) = IoRead16 ((UINTN)Address);
|
| 385 | } else {
|
| 386 | WriteUnaligned16 ((UINT16 *)Uint8Buffer, IoRead16 ((UINTN)Address));
|
| 387 | }
|
| 388 | } else if (OperationWidth == EfiPeiCpuIoWidthUint32) {
|
| 389 | if (Aligned) {
|
| 390 | *((UINT32 *)Uint8Buffer) = IoRead32 ((UINTN)Address);
|
| 391 | } else {
|
| 392 | WriteUnaligned32 ((UINT32 *)Uint8Buffer, IoRead32 ((UINTN)Address));
|
| 393 | }
|
| 394 | }
|
| 395 | }
|
| 396 |
|
| 397 | return EFI_SUCCESS;
|
| 398 | }
|
| 399 |
|
| 400 | /**
|
| 401 | Write I/O registers.
|
| 402 |
|
| 403 | @param[in] PeiServices An indirect pointer to the PEI Services Table
|
| 404 | published by the PEI Foundation.
|
| 405 | @param[in] This Pointer to local data for the interface.
|
| 406 | @param[in] Width The width of the access. Enumerated in bytes.
|
| 407 | @param[in] Address The physical address of the access.
|
| 408 | @param[in] Count The number of accesses to perform.
|
| 409 | @param[in] Buffer A pointer to the buffer of data.
|
| 410 |
|
| 411 | @retval EFI_SUCCESS The function completed successfully.
|
| 412 | @retval EFI_INVALID_PARAMETER Width is invalid for this EFI system.
|
| 413 | @retval EFI_INVALID_PARAMETER Buffer is NULL.
|
| 414 | @retval EFI_UNSUPPORTED The address range specified by Address, Width,
|
| 415 | and Count is not valid for this EFI system.
|
| 416 |
|
| 417 | **/
|
| 418 | EFI_STATUS
|
| 419 | EFIAPI
|
| 420 | CpuIoServiceWrite (
|
| 421 | IN CONST EFI_PEI_SERVICES **PeiServices,
|
| 422 | IN CONST EFI_PEI_CPU_IO_PPI *This,
|
| 423 | IN EFI_PEI_CPU_IO_PPI_WIDTH Width,
|
| 424 | IN UINT64 Address,
|
| 425 | IN UINTN Count,
|
| 426 | IN VOID *Buffer
|
| 427 | )
|
| 428 | {
|
| 429 | EFI_STATUS Status;
|
| 430 | UINT8 InStride;
|
| 431 | UINT8 OutStride;
|
| 432 | EFI_PEI_CPU_IO_PPI_WIDTH OperationWidth;
|
| 433 | BOOLEAN Aligned;
|
| 434 | UINT8 *Uint8Buffer;
|
| 435 |
|
| 436 | //
|
| 437 | // Make sure the parameters are valid
|
| 438 | //
|
| 439 | Status = CpuIoCheckParameter (FALSE, Width, Address, Count, Buffer);
|
| 440 | if (EFI_ERROR (Status)) {
|
| 441 | return Status;
|
| 442 | }
|
| 443 |
|
| 444 | //
|
| 445 | // Select loop based on the width of the transfer
|
| 446 | //
|
| 447 | InStride = mInStride[Width];
|
| 448 | OutStride = mOutStride[Width];
|
| 449 | OperationWidth = (EFI_PEI_CPU_IO_PPI_WIDTH) (Width & 0x03);
|
| 450 | Aligned = (BOOLEAN)(((UINTN)Buffer & (mInStride[OperationWidth] - 1)) == 0x00);
|
| 451 | for (Uint8Buffer = (UINT8 *)Buffer; Count > 0; Address += InStride, Uint8Buffer += OutStride, Count--) {
|
| 452 | if (OperationWidth == EfiPeiCpuIoWidthUint8) {
|
| 453 | IoWrite8 ((UINTN)Address, *Uint8Buffer);
|
| 454 | } else if (OperationWidth == EfiPeiCpuIoWidthUint16) {
|
| 455 | if (Aligned) {
|
| 456 | IoWrite16 ((UINTN)Address, *((UINT16 *)Uint8Buffer));
|
| 457 | } else {
|
| 458 | IoWrite16 ((UINTN)Address, ReadUnaligned16 ((UINT16 *)Uint8Buffer));
|
| 459 | }
|
| 460 | } else if (OperationWidth == EfiPeiCpuIoWidthUint32) {
|
| 461 | if (Aligned) {
|
| 462 | IoWrite32 ((UINTN)Address, *((UINT32 *)Uint8Buffer));
|
| 463 | } else {
|
| 464 | IoWrite32 ((UINTN)Address, ReadUnaligned32 ((UINT32 *)Uint8Buffer));
|
| 465 | }
|
| 466 | }
|
| 467 | }
|
| 468 |
|
| 469 | return EFI_SUCCESS;
|
| 470 | }
|
| 471 |
|
| 472 | /**
|
| 473 | 8-bit I/O read operations.
|
| 474 |
|
| 475 | @param[in] PeiServices An indirect pointer to the PEI Services Table published
|
| 476 | by the PEI Foundation.
|
| 477 | @param[in] This Pointer to local data for the interface.
|
| 478 | @param[in] Address The physical address of the access.
|
| 479 |
|
| 480 | @return An 8-bit value returned from the I/O space.
|
| 481 | **/
|
| 482 | UINT8
|
| 483 | EFIAPI
|
| 484 | CpuIoRead8 (
|
| 485 | IN CONST EFI_PEI_SERVICES **PeiServices,
|
| 486 | IN CONST EFI_PEI_CPU_IO_PPI *This,
|
| 487 | IN UINT64 Address
|
| 488 | )
|
| 489 | {
|
| 490 | return IoRead8 ((UINTN)Address);
|
| 491 | }
|
| 492 |
|
| 493 | /**
|
| 494 | 16-bit I/O read operations.
|
| 495 |
|
| 496 | @param[in] PeiServices An indirect pointer to the PEI Services Table published
|
| 497 | by the PEI Foundation.
|
| 498 | @param[in] This Pointer to local data for the interface.
|
| 499 | @param[in] Address The physical address of the access.
|
| 500 |
|
| 501 | @return A 16-bit value returned from the I/O space.
|
| 502 |
|
| 503 | **/
|
| 504 | UINT16
|
| 505 | EFIAPI
|
| 506 | CpuIoRead16 (
|
| 507 | IN CONST EFI_PEI_SERVICES **PeiServices,
|
| 508 | IN CONST EFI_PEI_CPU_IO_PPI *This,
|
| 509 | IN UINT64 Address
|
| 510 | )
|
| 511 | {
|
| 512 | return IoRead16 ((UINTN)Address);
|
| 513 | }
|
| 514 |
|
| 515 | /**
|
| 516 | 32-bit I/O read operations.
|
| 517 |
|
| 518 | @param[in] PeiServices An indirect pointer to the PEI Services Table published
|
| 519 | by the PEI Foundation.
|
| 520 | @param[in] This Pointer to local data for the interface.
|
| 521 | @param[in] Address The physical address of the access.
|
| 522 |
|
| 523 | @return A 32-bit value returned from the I/O space.
|
| 524 |
|
| 525 | **/
|
| 526 | UINT32
|
| 527 | EFIAPI
|
| 528 | CpuIoRead32 (
|
| 529 | IN CONST EFI_PEI_SERVICES **PeiServices,
|
| 530 | IN CONST EFI_PEI_CPU_IO_PPI *This,
|
| 531 | IN UINT64 Address
|
| 532 | )
|
| 533 | {
|
| 534 | return IoRead32 ((UINTN)Address);
|
| 535 | }
|
| 536 |
|
| 537 | /**
|
| 538 | 64-bit I/O read operations.
|
| 539 |
|
| 540 | @param[in] PeiServices An indirect pointer to the PEI Services Table published
|
| 541 | by the PEI Foundation.
|
| 542 | @param[in] This Pointer to local data for the interface.
|
| 543 | @param[in] Address The physical address of the access.
|
| 544 |
|
| 545 | @return A 64-bit value returned from the I/O space.
|
| 546 |
|
| 547 | **/
|
| 548 | UINT64
|
| 549 | EFIAPI
|
| 550 | CpuIoRead64 (
|
| 551 | IN CONST EFI_PEI_SERVICES **PeiServices,
|
| 552 | IN CONST EFI_PEI_CPU_IO_PPI *This,
|
| 553 | IN UINT64 Address
|
| 554 | )
|
| 555 | {
|
| 556 | return IoRead64 ((UINTN)Address);
|
| 557 | }
|
| 558 |
|
| 559 | /**
|
| 560 | 8-bit I/O write operations.
|
| 561 |
|
| 562 | @param[in] PeiServices An indirect pointer to the PEI Services Table published
|
| 563 | by the PEI Foundation.
|
| 564 | @param[in] This Pointer to local data for the interface.
|
| 565 | @param[in] Address The physical address of the access.
|
| 566 | @param[in] Data The data to write.
|
| 567 |
|
| 568 | **/
|
| 569 | VOID
|
| 570 | EFIAPI
|
| 571 | CpuIoWrite8 (
|
| 572 | IN CONST EFI_PEI_SERVICES **PeiServices,
|
| 573 | IN CONST EFI_PEI_CPU_IO_PPI *This,
|
| 574 | IN UINT64 Address,
|
| 575 | IN UINT8 Data
|
| 576 | )
|
| 577 | {
|
| 578 | IoWrite8 ((UINTN)Address, Data);
|
| 579 | }
|
| 580 |
|
| 581 | /**
|
| 582 | 16-bit I/O write operations.
|
| 583 |
|
| 584 | @param[in] PeiServices An indirect pointer to the PEI Services Table published
|
| 585 | by the PEI Foundation.
|
| 586 | @param[in] This Pointer to local data for the interface.
|
| 587 | @param[in] Address The physical address of the access.
|
| 588 | @param[in] Data The data to write.
|
| 589 |
|
| 590 | **/
|
| 591 | VOID
|
| 592 | EFIAPI
|
| 593 | CpuIoWrite16 (
|
| 594 | IN CONST EFI_PEI_SERVICES **PeiServices,
|
| 595 | IN CONST EFI_PEI_CPU_IO_PPI *This,
|
| 596 | IN UINT64 Address,
|
| 597 | IN UINT16 Data
|
| 598 | )
|
| 599 | {
|
| 600 | IoWrite16 ((UINTN)Address, Data);
|
| 601 | }
|
| 602 |
|
| 603 | /**
|
| 604 | 32-bit I/O write operations.
|
| 605 |
|
| 606 | @param[in] PeiServices An indirect pointer to the PEI Services Table published
|
| 607 | by the PEI Foundation.
|
| 608 | @param[in] This Pointer to local data for the interface.
|
| 609 | @param[in] Address The physical address of the access.
|
| 610 | @param[in] Data The data to write.
|
| 611 |
|
| 612 | **/
|
| 613 | VOID
|
| 614 | EFIAPI
|
| 615 | CpuIoWrite32 (
|
| 616 | IN CONST EFI_PEI_SERVICES **PeiServices,
|
| 617 | IN CONST EFI_PEI_CPU_IO_PPI *This,
|
| 618 | IN UINT64 Address,
|
| 619 | IN UINT32 Data
|
| 620 | )
|
| 621 | {
|
| 622 | IoWrite32 ((UINTN)Address, Data);
|
| 623 | }
|
| 624 |
|
| 625 | /**
|
| 626 | 64-bit I/O write operations.
|
| 627 |
|
| 628 | @param[in] PeiServices An indirect pointer to the PEI Services Table published
|
| 629 | by the PEI Foundation.
|
| 630 | @param[in] This Pointer to local data for the interface.
|
| 631 | @param[in] Address The physical address of the access.
|
| 632 | @param[in] Data The data to write.
|
| 633 |
|
| 634 | **/
|
| 635 | VOID
|
| 636 | EFIAPI
|
| 637 | CpuIoWrite64 (
|
| 638 | IN CONST EFI_PEI_SERVICES **PeiServices,
|
| 639 | IN CONST EFI_PEI_CPU_IO_PPI *This,
|
| 640 | IN UINT64 Address,
|
| 641 | IN UINT64 Data
|
| 642 | )
|
| 643 | {
|
| 644 | IoWrite64 ((UINTN)Address, Data);
|
| 645 | }
|
| 646 |
|
| 647 | /**
|
| 648 | 8-bit memory read operations.
|
| 649 |
|
| 650 | @param[in] PeiServices An indirect pointer to the PEI Services Table published
|
| 651 | by the PEI Foundation.
|
| 652 | @param[in] This Pointer to local data for the interface.
|
| 653 | @param[in] Address The physical address of the access.
|
| 654 |
|
| 655 | @return An 8-bit value returned from the memory space.
|
| 656 |
|
| 657 | **/
|
| 658 | UINT8
|
| 659 | EFIAPI
|
| 660 | CpuMemRead8 (
|
| 661 | IN CONST EFI_PEI_SERVICES **PeiServices,
|
| 662 | IN CONST EFI_PEI_CPU_IO_PPI *This,
|
| 663 | IN UINT64 Address
|
| 664 | )
|
| 665 | {
|
| 666 | return MmioRead8 ((UINTN)Address);
|
| 667 | }
|
| 668 |
|
| 669 | /**
|
| 670 | 16-bit memory read operations.
|
| 671 |
|
| 672 | @param[in] PeiServices An indirect pointer to the PEI Services Table published
|
| 673 | by the PEI Foundation.
|
| 674 | @param[in] This Pointer to local data for the interface.
|
| 675 | @param[in] Address The physical address of the access.
|
| 676 |
|
| 677 | @return A 16-bit value returned from the memory space.
|
| 678 |
|
| 679 | **/
|
| 680 | UINT16
|
| 681 | EFIAPI
|
| 682 | CpuMemRead16 (
|
| 683 | IN CONST EFI_PEI_SERVICES **PeiServices,
|
| 684 | IN CONST EFI_PEI_CPU_IO_PPI *This,
|
| 685 | IN UINT64 Address
|
| 686 | )
|
| 687 | {
|
| 688 | return MmioRead16 ((UINTN)Address);
|
| 689 | }
|
| 690 |
|
| 691 | /**
|
| 692 | 32-bit memory read operations.
|
| 693 |
|
| 694 | @param[in] PeiServices An indirect pointer to the PEI Services Table published
|
| 695 | by the PEI Foundation.
|
| 696 | @param[in] This Pointer to local data for the interface.
|
| 697 | @param[in] Address The physical address of the access.
|
| 698 |
|
| 699 | @return A 32-bit value returned from the memory space.
|
| 700 |
|
| 701 | **/
|
| 702 | UINT32
|
| 703 | EFIAPI
|
| 704 | CpuMemRead32 (
|
| 705 | IN CONST EFI_PEI_SERVICES **PeiServices,
|
| 706 | IN CONST EFI_PEI_CPU_IO_PPI *This,
|
| 707 | IN UINT64 Address
|
| 708 | )
|
| 709 | {
|
| 710 | return MmioRead32 ((UINTN)Address);
|
| 711 | }
|
| 712 |
|
| 713 | /**
|
| 714 | 64-bit memory read operations.
|
| 715 |
|
| 716 | @param[in] PeiServices An indirect pointer to the PEI Services Table published
|
| 717 | by the PEI Foundation.
|
| 718 | @param[in] This Pointer to local data for the interface.
|
| 719 | @param[in] Address The physical address of the access.
|
| 720 |
|
| 721 | @return A 64-bit value returned from the memory space.
|
| 722 |
|
| 723 | **/
|
| 724 | UINT64
|
| 725 | EFIAPI
|
| 726 | CpuMemRead64 (
|
| 727 | IN CONST EFI_PEI_SERVICES **PeiServices,
|
| 728 | IN CONST EFI_PEI_CPU_IO_PPI *This,
|
| 729 | IN UINT64 Address
|
| 730 | )
|
| 731 | {
|
| 732 | return MmioRead64 ((UINTN)Address);
|
| 733 | }
|
| 734 |
|
| 735 | /**
|
| 736 | 8-bit memory write operations.
|
| 737 |
|
| 738 | @param[in] PeiServices An indirect pointer to the PEI Services Table published
|
| 739 | by the PEI Foundation.
|
| 740 | @param[in] This Pointer to local data for the interface.
|
| 741 | @param[in] Address The physical address of the access.
|
| 742 | @param[in] Data The data to write.
|
| 743 |
|
| 744 | **/
|
| 745 | VOID
|
| 746 | EFIAPI
|
| 747 | CpuMemWrite8 (
|
| 748 | IN CONST EFI_PEI_SERVICES **PeiServices,
|
| 749 | IN CONST EFI_PEI_CPU_IO_PPI *This,
|
| 750 | IN UINT64 Address,
|
| 751 | IN UINT8 Data
|
| 752 | )
|
| 753 | {
|
| 754 | MmioWrite8 ((UINTN)Address, Data);
|
| 755 | }
|
| 756 |
|
| 757 | /**
|
| 758 | 16-bit memory write operations.
|
| 759 |
|
| 760 | @param[in] PeiServices An indirect pointer to the PEI Services Table published
|
| 761 | by the PEI Foundation.
|
| 762 | @param[in] This Pointer to local data for the interface.
|
| 763 | @param[in] Address The physical address of the access.
|
| 764 | @param[in] Data The data to write.
|
| 765 |
|
| 766 | **/
|
| 767 | VOID
|
| 768 | EFIAPI
|
| 769 | CpuMemWrite16 (
|
| 770 | IN CONST EFI_PEI_SERVICES **PeiServices,
|
| 771 | IN CONST EFI_PEI_CPU_IO_PPI *This,
|
| 772 | IN UINT64 Address,
|
| 773 | IN UINT16 Data
|
| 774 | )
|
| 775 | {
|
| 776 | MmioWrite16 ((UINTN)Address, Data);
|
| 777 | }
|
| 778 |
|
| 779 | /**
|
| 780 | 32-bit memory write operations.
|
| 781 |
|
| 782 | @param[in] PeiServices An indirect pointer to the PEI Services Table published
|
| 783 | by the PEI Foundation.
|
| 784 | @param[in] This Pointer to local data for the interface.
|
| 785 | @param[in] Address The physical address of the access.
|
| 786 | @param[in] Data The data to write.
|
| 787 |
|
| 788 | **/
|
| 789 | VOID
|
| 790 | EFIAPI
|
| 791 | CpuMemWrite32 (
|
| 792 | IN CONST EFI_PEI_SERVICES **PeiServices,
|
| 793 | IN CONST EFI_PEI_CPU_IO_PPI *This,
|
| 794 | IN UINT64 Address,
|
| 795 | IN UINT32 Data
|
| 796 | )
|
| 797 | {
|
| 798 | MmioWrite32 ((UINTN)Address, Data);
|
| 799 | }
|
| 800 |
|
| 801 | /**
|
| 802 | 64-bit memory write operations.
|
| 803 |
|
| 804 | @param[in] PeiServices An indirect pointer to the PEI Services Table published
|
| 805 | by the PEI Foundation.
|
| 806 | @param[in] This Pointer to local data for the interface.
|
| 807 | @param[in] Address The physical address of the access.
|
| 808 | @param[in] Data The data to write.
|
| 809 |
|
| 810 | **/
|
| 811 | VOID
|
| 812 | EFIAPI
|
| 813 | CpuMemWrite64 (
|
| 814 | IN CONST EFI_PEI_SERVICES **PeiServices,
|
| 815 | IN CONST EFI_PEI_CPU_IO_PPI *This,
|
| 816 | IN UINT64 Address,
|
| 817 | IN UINT64 Data
|
| 818 | )
|
| 819 | {
|
| 820 | MmioWrite64 ((UINTN)Address, Data);
|
| 821 | }
|
| 822 |
|
| 823 | /**
|
| 824 | The Entry point of the CPU I/O PEIM
|
| 825 |
|
| 826 | This function is the Entry point of the CPU I/O PEIM which installs CpuIoPpi.
|
| 827 |
|
| 828 | @param[in] FileHandle Pointer to image file handle.
|
| 829 | @param[in] PeiServices Pointer to PEI Services Table
|
| 830 |
|
| 831 | @retval EFI_SUCCESS CPU I/O PPI successfully installed
|
| 832 |
|
| 833 | **/
|
| 834 | EFI_STATUS
|
| 835 | EFIAPI
|
| 836 | CpuIoInitialize (
|
| 837 | IN EFI_PEI_FILE_HANDLE FileHandle,
|
| 838 | IN CONST EFI_PEI_SERVICES **PeiServices
|
| 839 | )
|
| 840 | {
|
| 841 | EFI_STATUS Status;
|
| 842 |
|
| 843 | //
|
| 844 | // Register so it will be automatically shadowed to memory
|
| 845 | //
|
| 846 | Status = PeiServicesRegisterForShadow (FileHandle);
|
| 847 |
|
| 848 | //
|
| 849 | // Make CpuIo pointer in PeiService table point to gCpuIoPpi
|
| 850 | //
|
| 851 | (*((EFI_PEI_SERVICES **)PeiServices))->CpuIo = &gCpuIoPpi;
|
| 852 |
|
| 853 | if (Status == EFI_ALREADY_STARTED) {
|
| 854 | //
|
| 855 | // Shadow completed and running from memory
|
| 856 | //
|
| 857 | DEBUG ((EFI_D_INFO, "CpuIO PPI has been loaded into memory. Reinstalled PPI=0x%x\n", &gCpuIoPpi));
|
| 858 | } else {
|
| 859 | Status = PeiServicesInstallPpi (&gPpiList);
|
| 860 | ASSERT_EFI_ERROR (Status);
|
| 861 | }
|
| 862 |
|
| 863 | return EFI_SUCCESS;
|
| 864 | }
|