Home | History | Annotate | Download | only in AcpiResetDxe
      1 /*++ @file
      2   Reset Architectural Protocol implementation.
      3 
      4 Copyright (c) 2006 - 2010, 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 <PiDxe.h>
     16 
     17 #include <Protocol/Reset.h>
     18 
     19 #include <Guid/AcpiDescription.h>
     20 
     21 #include <Library/BaseLib.h>
     22 #include <Library/IoLib.h>
     23 #include <Library/PciLib.h>
     24 #include <Library/HobLib.h>
     25 #include <Library/DebugLib.h>
     26 #include <Library/BaseMemoryLib.h>
     27 #include <Library/UefiBootServicesTableLib.h>
     28 
     29 ///
     30 /// Handle for the Reset Architectural Protocol
     31 ///
     32 EFI_HANDLE            mResetHandle = NULL;
     33 
     34 ///
     35 /// Copy of ACPI Description HOB in runtime memory
     36 ///
     37 EFI_ACPI_DESCRIPTION  mAcpiDescription;
     38 
     39 /**
     40   Reset the system.
     41 
     42   @param[in] ResetType       Warm or cold
     43   @param[in] ResetStatus     Possible cause of reset
     44   @param[in] DataSize        Size of ResetData in bytes
     45   @param[in] ResetData       Optional Unicode string
     46 
     47 **/
     48 VOID
     49 EFIAPI
     50 EfiAcpiResetSystem (
     51   IN EFI_RESET_TYPE   ResetType,
     52   IN EFI_STATUS       ResetStatus,
     53   IN UINTN            DataSize,
     54   IN VOID             *ResetData OPTIONAL
     55   )
     56 {
     57   UINT8   Dev;
     58   UINT8   Func;
     59   UINT8   Register;
     60 
     61   switch (ResetType) {
     62   case EfiResetShutdown:
     63     //
     64     // 1. Write SLP_TYPa
     65     //
     66     if ((mAcpiDescription.PM1a_CNT_BLK.Address != 0) && (mAcpiDescription.SLP_TYPa != 0)) {
     67       switch (mAcpiDescription.PM1a_CNT_BLK.AddressSpaceId) {
     68       case EFI_ACPI_3_0_SYSTEM_IO:
     69         IoAndThenOr16 ((UINTN)mAcpiDescription.PM1a_CNT_BLK.Address, 0xc3ff, (UINT16)(0x2000 | (mAcpiDescription.SLP_TYPa << 10)));
     70         break;
     71       case EFI_ACPI_3_0_SYSTEM_MEMORY:
     72         MmioAndThenOr16 ((UINTN)mAcpiDescription.PM1a_CNT_BLK.Address, 0xc3ff, (UINT16)(0x2000 | (mAcpiDescription.SLP_TYPa << 10)));
     73         break;
     74       }
     75     }
     76 
     77     //
     78     // 2. Write SLP_TYPb
     79     //
     80     if ((mAcpiDescription.PM1b_CNT_BLK.Address != 0) && (mAcpiDescription.SLP_TYPb != 0)) {
     81       switch (mAcpiDescription.PM1b_CNT_BLK.AddressSpaceId) {
     82       case EFI_ACPI_3_0_SYSTEM_IO:
     83         IoAndThenOr16 ((UINTN)mAcpiDescription.PM1b_CNT_BLK.Address, 0xc3ff, (UINT16)(0x2000 | (mAcpiDescription.SLP_TYPb << 10)));
     84         break;
     85       case EFI_ACPI_3_0_SYSTEM_MEMORY:
     86         MmioAndThenOr16 ((UINTN)mAcpiDescription.PM1b_CNT_BLK.Address, 0xc3ff, (UINT16)(0x2000 | (mAcpiDescription.SLP_TYPb << 10)));
     87         break;
     88       }
     89     }
     90     //
     91     // If Shutdown fails, then let fall through to reset
     92     //
     93   case EfiResetWarm:
     94   case EfiResetCold:
     95     if ((mAcpiDescription.RESET_REG.Address != 0) &&
     96         ((mAcpiDescription.RESET_REG.AddressSpaceId == EFI_ACPI_3_0_SYSTEM_IO) ||
     97          (mAcpiDescription.RESET_REG.AddressSpaceId == EFI_ACPI_3_0_SYSTEM_MEMORY) ||
     98          (mAcpiDescription.RESET_REG.AddressSpaceId == EFI_ACPI_3_0_PCI_CONFIGURATION_SPACE))) {
     99       //
    100       // Use ACPI System Reset
    101       //
    102       switch (mAcpiDescription.RESET_REG.AddressSpaceId) {
    103       case EFI_ACPI_3_0_SYSTEM_IO:
    104         //
    105         // Send reset request through I/O port register
    106         //
    107         IoWrite8 ((UINTN)mAcpiDescription.RESET_REG.Address, mAcpiDescription.RESET_VALUE);
    108         //
    109         // Halt
    110         //
    111         CpuDeadLoop ();
    112       case EFI_ACPI_3_0_SYSTEM_MEMORY:
    113         //
    114         // Send reset request through MMIO register
    115         //
    116         MmioWrite8 ((UINTN)mAcpiDescription.RESET_REG.Address, mAcpiDescription.RESET_VALUE);
    117         //
    118         // Halt
    119         //
    120         CpuDeadLoop ();
    121       case EFI_ACPI_3_0_PCI_CONFIGURATION_SPACE:
    122         //
    123         // Send reset request through PCI register
    124         //
    125         Register = (UINT8)mAcpiDescription.RESET_REG.Address;
    126         Func     = (UINT8) (RShiftU64 (mAcpiDescription.RESET_REG.Address, 16) & 0x7);
    127         Dev      = (UINT8) (RShiftU64 (mAcpiDescription.RESET_REG.Address, 32) & 0x1F);
    128         PciWrite8 (PCI_LIB_ADDRESS (0, Dev, Func, Register), mAcpiDescription.RESET_VALUE);
    129         //
    130         // Halt
    131         //
    132         CpuDeadLoop ();
    133       }
    134     }
    135 
    136     //
    137     // If system comes here, means ACPI reset is not supported, so do Legacy System Reset, assume 8042 available
    138     //
    139     IoWrite8 (0x64, 0xfe);
    140     CpuDeadLoop ();
    141 
    142   default:
    143     break;
    144   }
    145 
    146   //
    147   // Given we should have reset getting here would be bad
    148   //
    149   ASSERT (FALSE);
    150   CpuDeadLoop();
    151 }
    152 
    153 /**
    154   Initialize the state information for the Reset Architectural Protocol.
    155 
    156   @param[in] ImageHandle  Image handle of the loaded driver
    157   @param[in] SystemTable  Pointer to the System Table
    158 
    159   @retval EFI_SUCCESS           Thread can be successfully created
    160   @retval EFI_UNSUPPORTED       Cannot find the info to reset system
    161 
    162 **/
    163 EFI_STATUS
    164 EFIAPI
    165 InitializeReset (
    166   IN EFI_HANDLE        ImageHandle,
    167   IN EFI_SYSTEM_TABLE  *SystemTable
    168   )
    169 {
    170   EFI_STATUS         Status;
    171   EFI_HOB_GUID_TYPE  *HobAcpiDescription;
    172 
    173   //
    174   // Make sure the Reset Architectural Protocol is not already installed in the system
    175   //
    176   ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gEfiResetArchProtocolGuid);
    177 
    178   //
    179   // Get ACPI Description HOB
    180   //
    181   HobAcpiDescription = GetFirstGuidHob (&gEfiAcpiDescriptionGuid);
    182   if (HobAcpiDescription == NULL) {
    183     return EFI_UNSUPPORTED;
    184   }
    185 
    186   //
    187   // Copy it to Runtime Memory
    188   //
    189   ASSERT (sizeof (EFI_ACPI_DESCRIPTION) == GET_GUID_HOB_DATA_SIZE (HobAcpiDescription));
    190   CopyMem (&mAcpiDescription, GET_GUID_HOB_DATA (HobAcpiDescription), sizeof (EFI_ACPI_DESCRIPTION));
    191 
    192   DEBUG ((DEBUG_INFO, "ACPI Reset Base  - %lx\n", mAcpiDescription.RESET_REG.Address));
    193   DEBUG ((DEBUG_INFO, "ACPI Reset Value - %02x\n", (UINTN)mAcpiDescription.RESET_VALUE));
    194   DEBUG ((DEBUG_INFO, "IAPC support     - %x\n", (UINTN)(mAcpiDescription.IAPC_BOOT_ARCH)));
    195 
    196   //
    197   // Hook the runtime service table
    198   //
    199   SystemTable->RuntimeServices->ResetSystem = EfiAcpiResetSystem;
    200 
    201   //
    202   // Install the Reset Architectural Protocol onto a new handle
    203   //
    204   Status = gBS->InstallMultipleProtocolInterfaces (
    205                   &mResetHandle,
    206                   &gEfiResetArchProtocolGuid, NULL,
    207                   NULL
    208                   );
    209   ASSERT_EFI_ERROR (Status);
    210 
    211   return Status;
    212 }
    213