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 } 865