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