OpenCore  1.0.4
OpenCore Bootloader
Loading...
Searching...
No Matches
BootEntryProtocol.c
Go to the documentation of this file.
1
9
11
12#include <Library/BaseLib.h>
13#include <Library/UefiBootServicesTableLib.h>
14#include <Library/MemoryAllocationLib.h>
15#include <Library/OcFileLib.h>
17
26
27VOID
29 IN OUT EFI_HANDLE **EntryProtocolHandles,
30 IN OUT UINTN *EntryProtocolHandleCount
31 )
32{
33 EFI_STATUS Status;
34
35 Status = gBS->LocateHandleBuffer (
36 ByProtocol,
38 NULL,
39 EntryProtocolHandleCount,
40 EntryProtocolHandles
41 );
42
43 if (EFI_ERROR (Status)) {
44 //
45 // No loaded drivers is fine
46 //
47 if (Status != EFI_NOT_FOUND) {
48 DEBUG ((DEBUG_ERROR, "BEP: Error locating driver handles - %r\n", Status));
49 }
50
51 *EntryProtocolHandleCount = 0;
52 *EntryProtocolHandles = NULL;
53 }
54}
55
56VOID
58 EFI_HANDLE **EntryProtocolHandles
59 )
60{
61 if (*EntryProtocolHandles == NULL) {
62 return;
63 }
64
65 FreePool (*EntryProtocolHandles);
66 *EntryProtocolHandles = NULL;
67}
68
69STATIC
70BOOLEAN
71EFIAPI
73 IN OUT OC_PICKER_CONTEXT *PickerContext,
74 IN EFI_HANDLE BootEntryProtocolHandle,
75 IN OC_BOOT_ENTRY_PROTOCOL *BootEntryProtocol,
76 IN VOID *Context
77 )
78{
79 EFI_STATUS Status;
80 UINTN EntryIndex;
81 OC_PICKER_ENTRY *Entries;
82 UINTN NumEntries;
83 BEP_ADD_ENTRIES_CONTEXT *AddEntriesContext;
84
85 ASSERT (Context != NULL);
86 AddEntriesContext = Context;
87
88 ASSERT (!AddEntriesContext->CreateForHotKey || AddEntriesContext->CreateDefault);
89
90 Status = EFI_NOT_FOUND;
91 if (BootEntryProtocol->GetBootEntries) {
92 Status = BootEntryProtocol->GetBootEntries (
93 PickerContext,
94 ((AddEntriesContext->FileSystem->Handle == OC_CUSTOM_FS_HANDLE) ? NULL : AddEntriesContext->FileSystem->Handle),
95 &Entries,
96 &NumEntries
97 );
98 }
99
100 if (EFI_ERROR (Status)) {
101 //
102 // No entries for any given driver on any given filesystem is normal.
103 //
104 if (Status != EFI_NOT_FOUND) {
105 DEBUG ((DEBUG_WARN, "BEP: Unable to fetch boot entries - %r\n", Status));
106 }
107
108 return TRUE;
109 }
110
111 for (EntryIndex = 0; EntryIndex < NumEntries; EntryIndex++) {
112 if (Entries[EntryIndex].Id == NULL) {
113 DEBUG ((DEBUG_WARN, "BEP: Entry->Id is required, ignoring entry.\n"));
114 }
115
116 if ((AddEntriesContext->DefaultEntryId == NULL) ||
117 (((AddEntriesContext->CreateForHotKey
118 ? AsciiStrCmp (AddEntriesContext->DefaultEntryId, Entries[EntryIndex].Id)
119 : MixedStrCmp (AddEntriesContext->DefaultEntryId, Entries[EntryIndex].Id)) == 0) == AddEntriesContext->CreateDefault))
120 {
122 AddEntriesContext->BootContext,
123 AddEntriesContext->FileSystem,
124 &Entries[EntryIndex],
125 TRUE
126 );
127
128 if (EFI_ERROR (Status)) {
129 //
130 // EFI_UNSUPPORTED is auxiliary entry when HideAuxiliary=true.
131 //
132 if (Status != EFI_UNSUPPORTED) {
133 DEBUG ((DEBUG_WARN, "BEP: Error adding entries - %r\n", Status));
134 break;
135 }
136 } else {
137 AddEntriesContext->ReturnStatus = EFI_SUCCESS;
138
139 //
140 // Stop searching after first match for default entry. Possible additional
141 // matches, e.g. older versions of Linux kernel, are normal.
142 //
143 if (AddEntriesContext->CreateDefault) {
144 return FALSE;
145 }
146 }
147 } else {
148 //
149 // Create remaining matches after skipping first match for pre-created entry.
150 //
151 if (!AddEntriesContext->CreateDefault) {
152 AddEntriesContext->DefaultEntryId = NULL;
153 }
154 }
155 }
156
157 if (BootEntryProtocol->FreeBootEntries) {
158 BootEntryProtocol->FreeBootEntries (
159 &Entries,
160 NumEntries
161 );
162 }
163
164 //
165 // If not found, keep hunting for default entry on other installed drivers.
166 //
167 if (AddEntriesContext->CreateDefault) {
168 if (AddEntriesContext->ReturnStatus == EFI_NOT_FOUND) {
169 return TRUE;
170 }
171
172 return FALSE;
173 }
174
175 //
176 // On other error adding entry, which should not fail, abort.
177 // Context->ReturnStatus reflects whether any entry was added.
178 //
179 if (EFI_ERROR (Status) && (Status != EFI_UNSUPPORTED)) {
180 return FALSE;
181 }
182
183 return TRUE;
184}
185
186VOID
188 IN OUT OC_PICKER_CONTEXT *PickerContext,
189 IN EFI_HANDLE *EntryProtocolHandles,
190 IN UINTN EntryProtocolHandleCount,
192 IN VOID *Context
193 )
194{
195 EFI_STATUS Status;
196 UINTN Index;
197 OC_BOOT_ENTRY_PROTOCOL *BootEntryProtocol;
198
199 ASSERT (EntryProtocolHandleCount == 0 || EntryProtocolHandles != NULL);
200
201 for (Index = 0; Index < EntryProtocolHandleCount; ++Index) {
202 //
203 // Previously marked as invalid.
204 //
205 if (EntryProtocolHandles[Index] == NULL) {
206 continue;
207 }
208
209 Status = gBS->HandleProtocol (
210 EntryProtocolHandles[Index],
212 (VOID **)&BootEntryProtocol
213 );
214
215 if (EFI_ERROR (Status)) {
216 DEBUG ((DEBUG_ERROR, "BEP: HandleProtocol failed - %r\n", Status));
217 EntryProtocolHandles[Index] = NULL;
218 continue;
219 }
220
221 if (BootEntryProtocol->Revision != OC_BOOT_ENTRY_PROTOCOL_REVISION) {
222 DEBUG ((
223 DEBUG_ERROR,
224 "BEP: Invalid revision %u (!= %u) in loaded driver\n",
225 BootEntryProtocol->Revision,
227 ));
228 EntryProtocolHandles[Index] = NULL;
229 continue;
230 }
231
232 if (!Action (PickerContext, EntryProtocolHandles[Index], BootEntryProtocol, Context)) {
233 break;
234 }
235 }
236}
237
238EFI_STATUS
240 IN OUT OC_BOOT_CONTEXT *BootContext,
241 IN OUT OC_BOOT_FILESYSTEM *FileSystem,
242 IN EFI_HANDLE *EntryProtocolHandles,
243 IN UINTN EntryProtocolHandleCount,
244 IN CONST VOID *DefaultEntryId, OPTIONAL
245 IN BOOLEAN CreateDefault,
246 IN BOOLEAN CreateForHotKey
247 )
248{
249 BEP_ADD_ENTRIES_CONTEXT AddEntriesContext;
250
251 //
252 // May be CustomFileSystem, but not NULL.
253 //
254 ASSERT (FileSystem != NULL);
255 ASSERT (!CreateDefault || (DefaultEntryId != NULL));
256
257 AddEntriesContext.ReturnStatus = EFI_NOT_FOUND;
258 AddEntriesContext.BootContext = BootContext;
259 AddEntriesContext.FileSystem = FileSystem;
260 AddEntriesContext.CreateDefault = CreateDefault;
261 AddEntriesContext.CreateForHotKey = CreateForHotKey;
262 AddEntriesContext.DefaultEntryId = DefaultEntryId;
263
265 BootContext->PickerContext,
266 EntryProtocolHandles,
267 EntryProtocolHandleCount,
269 &AddEntriesContext
270 );
271
272 return AddEntriesContext.ReturnStatus;
273}
EFI_STATUS InternalAddBootEntryFromCustomEntry(IN OUT OC_BOOT_CONTEXT *BootContext, IN OUT OC_BOOT_FILESYSTEM *FileSystem, IN OC_PICKER_ENTRY *CustomEntry, IN BOOLEAN IsBootEntryProtocol)
VOID OcLocateBootEntryProtocolHandles(IN OUT EFI_HANDLE **EntryProtocolHandles, IN OUT UINTN *EntryProtocolHandleCount)
VOID OcFreeBootEntryProtocolHandles(EFI_HANDLE **EntryProtocolHandles)
VOID OcConsumeBootEntryProtocol(IN OUT OC_PICKER_CONTEXT *PickerContext, IN EFI_HANDLE *EntryProtocolHandles, IN UINTN EntryProtocolHandleCount, IN OC_CONSUME_ENTRY_PROTOCOL_ACTION Action, IN VOID *Context)
STATIC BOOLEAN EFIAPI InternalAddEntriesFromProtocol(IN OUT OC_PICKER_CONTEXT *PickerContext, IN EFI_HANDLE BootEntryProtocolHandle, IN OC_BOOT_ENTRY_PROTOCOL *BootEntryProtocol, IN VOID *Context)
EFI_STATUS OcAddEntriesFromBootEntryProtocol(IN OUT OC_BOOT_CONTEXT *BootContext, IN OUT OC_BOOT_FILESYSTEM *FileSystem, IN EFI_HANDLE *EntryProtocolHandles, IN UINTN EntryProtocolHandleCount, IN CONST VOID *DefaultEntryId, OPTIONAL IN BOOLEAN CreateDefault, IN BOOLEAN CreateForHotKey)
#define OC_CUSTOM_FS_HANDLE
EFI_GUID gOcBootEntryProtocolGuid
BOOLEAN(EFIAPI * OC_CONSUME_ENTRY_PROTOCOL_ACTION)(IN OUT OC_PICKER_CONTEXT *PickerContext, IN EFI_HANDLE BootEntryProtocolHandle, IN OC_BOOT_ENTRY_PROTOCOL *BootEntryProtocol, IN VOID *Context)
#define OC_BOOT_ENTRY_PROTOCOL_REVISION
Definition OcBootEntry.h:31
EFI_BOOT_SERVICES * gBS
INTN MixedStrCmp(IN CONST CHAR16 *FirstString, IN CONST CHAR8 *SecondString)
#define ASSERT(x)
Definition coder.h:55
OC_BOOT_CONTEXT * BootContext
OC_BOOT_FILESYSTEM * FileSystem