OpenCore  1.0.4
OpenCore Bootloader
Loading...
Searching...
No Matches
AppleRecovery.c
Go to the documentation of this file.
1
15#include <Guid/AppleVariable.h>
16
18
19#include <Library/MemoryAllocationLib.h>
20#include <Library/BaseMemoryLib.h>
21#include <Library/DevicePathLib.h>
23#include <Library/OcCryptoLib.h>
26#include <Library/OcRtcLib.h>
27#include <Library/UefiLib.h>
28#include <Library/UefiRuntimeServicesTableLib.h>
29
30STATIC
31EFI_DEVICE_PATH_PROTOCOL *
33 VOID
34 )
35{
36 EFI_STATUS Status;
37 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
38 UINTN DevicePathSize;
39
40 Status = GetVariable2 (
43 (VOID **)&DevicePath,
44 &DevicePathSize
45 );
46 if (EFI_ERROR (Status)) {
47 DEBUG ((DEBUG_INFO, "OCB: No recovery initiator found - %r\n", Status));
48 return NULL;
49 }
50
51 //
52 // Also delete recovery initiator just in case.
53 //
54 gRT->SetVariable (
57 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
58 0,
59 NULL
60 );
61
62 if (!IsDevicePathValid (DevicePath, DevicePathSize)) {
63 DEBUG ((DEBUG_INFO, "OCB: Recovery initiator (%u) is invalid\n", (UINT32)DevicePathSize));
64 FreePool (DevicePath);
65 return NULL;
66 }
67
68 DebugPrintDevicePath (DEBUG_INFO, "OC: Recovery initiator", DevicePath);
69 return DevicePath;
70}
71
72EFI_STATUS
74 OUT EFI_DEVICE_PATH_PROTOCOL **Initiator OPTIONAL
75 )
76{
77 EFI_STATUS Status;
78 CHAR8 *RecoveryBootMode;
79 UINTN RecoveryBootModeSize;
80
81 //
82 // Provide basic support for recovery-boot-mode variable, which is meant
83 // to perform one-time recovery boot. In general BootOrder and BootNext
84 // are set to the recovery path, but this is not the case for secure-boot.
85 //
86 RecoveryBootModeSize = 0;
87 Status = gRT->GetVariable (
90 NULL,
91 &RecoveryBootModeSize,
92 NULL
93 );
94
95 //
96 // Initialise right away.
97 //
98 if (Initiator != NULL) {
99 *Initiator = NULL;
100 }
101
102 //
103 // No need for recovery, this is a normal boot.
104 //
105 if (Status != EFI_BUFFER_TOO_SMALL) {
106 return EFI_NOT_FOUND;
107 }
108
109 //
110 // Debug recovery-boot-mode contents.
111 //
112 DEBUG_CODE_BEGIN ();
113 RecoveryBootMode = AllocatePool (RecoveryBootModeSize + 1);
114 if (RecoveryBootMode != NULL) {
115 DEBUG ((
116 DEBUG_INFO,
117 "OCB: Failed to allocate recovery-boot-mode %u\n",
118 (UINT32)(RecoveryBootModeSize + 1)
119 ));
120
121 Status = gRT->GetVariable (
124 NULL,
125 &RecoveryBootModeSize,
126 RecoveryBootMode
127 );
128 if (!EFI_ERROR (Status)) {
129 //
130 // Ensure null-termination.
131 //
132 RecoveryBootMode[RecoveryBootModeSize] = '\0';
133 DEBUG ((
134 DEBUG_INFO,
135 "OCB: recovery-boot-mode %u = %a - %r\n",
136 (UINT32)RecoveryBootModeSize,
137 RecoveryBootMode,
138 Status
139 ));
140 } else {
141 DEBUG ((
142 DEBUG_INFO,
143 "OCB: Failed to obtain recovery-boot-mode %u - %r\n",
144 (UINT32)RecoveryBootModeSize,
145 Status
146 ));
147 }
148
149 FreePool (RecoveryBootMode);
150 } else {
151 DEBUG ((
152 DEBUG_INFO,
153 "OCB: Failed to allocate recovery-boot-mode %u\n",
154 (UINT32)(RecoveryBootModeSize + 1)
155 ));
156 }
157
158 DEBUG_CODE_END ();
159
160 if (Initiator != NULL) {
161 *Initiator = InternalGetRecoveryInitiator ();
162 }
163
164 //
165 // Delete recovery-boot-mode.
166 // Failing to do so will result in bootloop at least when SecureBoot is enabled.
167 // In other cases EfiBoot may try to chainload into recovery, but it is unreliable.
168 //
169 gRT->SetVariable (
172 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
173 0,
174 NULL
175 );
176
177 return EFI_SUCCESS;
178}
STATIC EFI_DEVICE_PATH_PROTOCOL * InternalGetRecoveryInitiator(VOID)
EFI_STATUS OcHandleRecoveryRequest(OUT EFI_DEVICE_PATH_PROTOCOL **Initiator OPTIONAL)
#define APPLE_RECOVERY_BOOT_INITIATOR_VARIABLE_NAME
EFI_GUID gAppleBootVariableGuid
EFI_GUID gAppleVendorVariableGuid
#define APPLE_RECOVERY_BOOT_MODE_VARIABLE_NAME
VOID DebugPrintDevicePath(IN UINTN ErrorLevel, IN CONST CHAR8 *Message, IN EFI_DEVICE_PATH_PROTOCOL *DevicePath OPTIONAL)
EFI_RUNTIME_SERVICES * gRT