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
EfiAcpiResetSystem(IN EFI_RESET_TYPE ResetType,IN EFI_STATUS ResetStatus,IN UINTN DataSize,IN VOID * ResetData OPTIONAL)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
InitializeReset(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)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