OpenCore  1.0.4
OpenCore Bootloader
Loading...
Searching...
No Matches
OcBootstrap.c
Go to the documentation of this file.
1
8#include <Library/OcMainLib.h>
9#include <Uefi.h>
10
11#include <Protocol/DevicePath.h>
12#include <Protocol/LoadedImage.h>
15
16#include <Library/UefiLib.h>
17#include <Library/BaseMemoryLib.h>
21#include <Library/DevicePathLib.h>
22#include <Library/MemoryAllocationLib.h>
24#include <Library/OcFileLib.h>
25#include <Library/UefiBootServicesTableLib.h>
26#include <Library/UefiRuntimeServicesTableLib.h>
27#include <Library/UefiApplicationEntryPoint.h>
28
29#include "OpenCanopy.h"
30#include "BmfLib.h"
31#include "GuiApp.h"
32
33//
34// Add slight x offset of cursor by its position within its icon file,
35// in order to match look of Apple picker initial position.
36//
37#define DEFAULT_CURSOR_OFFSET_X BOOT_CURSOR_OFFSET
38#define DEFAULT_CURSOR_OFFSET_Y 112U
39
41
44
45STATIC
46EFI_STATUS
48 IN BOOT_PICKER_GUI_CONTEXT *GuiContext
49 )
50{
51 EFI_STATUS Status;
52
53 Status = GuiLibConstruct (
54 GuiContext,
57 );
58 if (EFI_ERROR (Status)) {
59 return Status;
60 }
61
63
64 return EFI_SUCCESS;
65}
66
67STATIC
68VOID
76
77STATIC
78VOID
80 VOID
81 )
82{
83 //
84 // The cursor position is updated on GUI exit, so don't overwrite it.
85 //
86 if (mGuiContext.PickerContext == NULL) {
89 }
90}
91
92EFI_STATUS
93EFIAPI
95 IN OC_BOOT_CONTEXT *BootContext,
96 IN OC_BOOT_ENTRY **BootEntries,
97 OUT OC_BOOT_ENTRY **ChosenBootEntry
98 )
99{
100 EFI_STATUS Status;
101 UINTN Index;
102
103 *ChosenBootEntry = NULL;
105 mGuiContext.BootEntry = NULL;
106 mGuiContext.ReadyToBoot = FALSE;
107
108 //
109 // When enabled, re-run intro animation on each entry into menu, to avoid
110 // stuck animation which happens otherwise, if a menu item which returns to
111 // the menu is selected before the animation ends.
112 // Do not play intro animation for visually impaired users.
113 //
114 mGuiContext.UseMenuEaseIn = !BootContext->PickerContext->PickerAudioAssist
115 && ((BootContext->PickerContext->PickerAttributes & OC_ATTR_REDUCE_MOTION) == 0);
116
117 mGuiContext.HideAuxiliary = BootContext->PickerContext->HideAuxiliary;
118 mGuiContext.Refresh = FALSE;
119 mGuiContext.PickerContext = BootContext->PickerContext;
121
123 if (EFI_ERROR (Status)) {
124 return Status;
125 }
126
127 mDrawContext.TimeOutSeconds = BootContext->PickerContext->TimeoutSeconds;
128
129 Status = BootPickerViewInitialize (
133 (UINT8)BootContext->BootEntryCount
134 );
135 if (EFI_ERROR (Status)) {
137 return Status;
138 }
139
140 for (Index = 0; Index < BootContext->BootEntryCount; ++Index) {
141 Status = BootPickerEntriesSet (
142 BootContext->PickerContext,
144 BootEntries[Index],
145 (UINT8)Index
146 );
147 if (EFI_ERROR (Status)) {
149 return Status;
150 }
151 }
152
156 (UINT8)BootContext->DefaultEntry->EntryIndex - 1
157 );
158
160
161 if (BootContext->PickerContext->PickerAudioAssist) {
162 BootContext->PickerContext->PlayAudioFile (
163 BootContext->PickerContext,
166 FALSE
167 );
168 for (Index = 0; Index < BootContext->BootEntryCount; ++Index) {
169 BootContext->PickerContext->PlayAudioEntry (
170 BootContext->PickerContext,
171 BootEntries[Index]
172 );
173 if ((BootContext->PickerContext->TimeoutSeconds > 0) && (BootContext->DefaultEntry->EntryIndex - 1 == Index)) {
174 BootContext->PickerContext->PlayAudioFile (
175 BootContext->PickerContext,
178 FALSE
179 );
180 }
181 }
182
183 BootContext->PickerContext->PlayAudioBeep (
184 BootContext->PickerContext,
188 );
189 }
190
193
194 //
195 // There are reasons to prefer not to perform this screen clear:
196 // - If starting macOS, boot.efi performs the same screen clear to the same UI theme colour
197 // immediately afterwards anyway
198 // - The native Apple picker does not clear its graphics before exit (i.e. does not do this)
199 // - Most OS booters in most circumstance perform their own screen clear
200 // - Each screen clear on a slow GOP (such as direct GOP rendering) is a noticeable slowdown
201 // However:
202 // - Windows without ACPI->Quirks->ResetLogoStatus does not clear any pre-existing graphics
203 // - Ref: https://github.com/acidanthera/bugtracker/issues/2231
204 // - Peforming this screen clear gives a sense of progress (i.e. something happens immediately
205 // rather than nothing) if the selected entry will be very slow to start (e.g. Recovery, in
207 //
208 if (!mGuiContext.Refresh) {
209 //
210 // Clear the screen only when we exit.
211 //
213 }
214
215 //
216 // Note, it is important to destruct GUI here, as we must ensure
217 // that keyboard/mouse polling does not conflict with FV2 ui.
218 //
221
222 *ChosenBootEntry = mGuiContext.BootEntry;
223 BootContext->PickerContext->HideAuxiliary = mGuiContext.HideAuxiliary;
224 if (mGuiContext.Refresh) {
225 return EFI_ABORTED;
226 }
227
228 return EFI_SUCCESS;
229}
230
231EFI_STATUS
232EFIAPI
234 IN OC_PICKER_CONTEXT *Context,
235 IN OC_PRIVILEGE_LEVEL Level
236 )
237{
238 EFI_STATUS Status;
239
241 mGuiContext.BootEntry = NULL;
242 mGuiContext.ReadyToBoot = FALSE;
244 mGuiContext.Refresh = FALSE;
245 mGuiContext.PickerContext = Context;
247
249 if (EFI_ERROR (Status)) {
250 return Status;
251 }
252
254
255 mGuiContext.UsePasswordEaseIn = !Context->PickerAudioAssist
256 && ((Context->PickerAttributes & OC_ATTR_REDUCE_MOTION) == 0);
257
258 Status = PasswordViewInitialize (
261 );
262 if (EFI_ERROR (Status)) {
264 return Status;
265 }
266
268
270
271 //
272 // This screen clear is useful, even though the boot entry started will in general
273 // perform its own screen clear eventually anyway, since this gives a better sense
274 // of progress between (intentionally slow - computationally intensive) password
275 // verification and (can be slow) start of Recovery.
276 //
277 if (Context->PickerCommand != OcPickerShowPicker) {
278 //
279 // Clear the screen only if we will not show BootPicker afterwards.
280 //
282 }
283
284 //
285 // Note, it is important to destruct GUI here, as we must ensure
286 // that keyboard/mouse polling does not conflict with FV2 ui.
287 //
290
291 return EFI_SUCCESS;
292}
293
294EFI_STATUS
296 OUT BOOT_PICKER_GUI_CONTEXT *Context,
297 IN OC_STORAGE_CONTEXT *Storage,
298 IN OC_PICKER_CONTEXT *Picker
299 );
300
301STATIC
302EFI_STATUS
303EFIAPI
305 IN OC_INTERFACE_PROTOCOL *This,
306 IN OC_STORAGE_CONTEXT *Storage,
307 IN OC_PICKER_CONTEXT *Context
308 )
309{
310 EFI_STATUS Status;
311
312 Status = InternalContextConstruct (&mGuiContext, Storage, Context);
313 if (EFI_ERROR (Status)) {
314 return Status;
315 }
316
317 Context->ShowMenu = OcShowMenuByOc;
318 Context->RequestPrivilege = OcShowPasswordByOc;
319
320 return EFI_SUCCESS;
321}
322
327
328EFI_STATUS
329EFIAPI
331 IN EFI_HANDLE ImageHandle,
332 IN EFI_SYSTEM_TABLE *SystemTable
333 )
334{
335 EFI_STATUS Status;
336 VOID *PrevInterface;
337 EFI_HANDLE NewHandle;
338
339 //
340 // Check for previous GUI protocols.
341 //
342 Status = gBS->LocateProtocol (
344 NULL,
345 &PrevInterface
346 );
347
348 if (!EFI_ERROR (Status)) {
349 DEBUG ((DEBUG_WARN, "OCUI: Another GUI is already present\n"));
350 return EFI_ALREADY_STARTED;
351 }
352
353 //
354 // Install new GUI protocol
355 //
356 NewHandle = NULL;
357 Status = gBS->InstallMultipleProtocolInterfaces (
358 &NewHandle,
361 NULL
362 );
363
364 if (!EFI_ERROR (Status)) {
365 DEBUG ((DEBUG_INFO, "OCUI: Registered custom GUI protocol\n"));
366 } else {
367 DEBUG ((DEBUG_WARN, "OCUI: Failed to install GUI protocol - %r\n", Status));
368 }
369
370 return Status;
371}
EFI_CONSOLE_CONTROL_SCREEN_MODE
@ EfiConsoleControlScreenGraphics
CONST GUI_IMAGE * InternalGetCursorImage(IN BOOT_PICKER_GUI_CONTEXT *Context)
Definition GuiApp.c:663
VOID BootPickerViewLateInitialize(IN OUT GUI_DRAWING_CONTEXT *DrawContext, IN BOOT_PICKER_GUI_CONTEXT *GuiContext, IN UINT8 DefaultIndex)
EFI_STATUS BootPickerEntriesSet(IN OC_PICKER_CONTEXT *Context, IN BOOT_PICKER_GUI_CONTEXT *GuiContext, IN OC_BOOT_ENTRY *Entry, IN UINT8 EntryIndex)
EFI_STATUS PasswordViewInitialize(OUT GUI_DRAWING_CONTEXT *DrawContext, IN BOOT_PICKER_GUI_CONTEXT *GuiContext)
Definition Password.c:753
VOID BootPickerViewDeinitialize(IN OUT GUI_DRAWING_CONTEXT *DrawContext, IN OUT BOOT_PICKER_GUI_CONTEXT *GuiContext)
EFI_STATUS BootPickerViewInitialize(OUT GUI_DRAWING_CONTEXT *DrawContext, IN BOOT_PICKER_GUI_CONTEXT *GuiContext, IN GUI_CURSOR_GET_IMAGE GetCursorImage, IN UINT8 NumBootEntries)
VOID PasswordViewDeinitialize(IN OUT GUI_DRAWING_CONTEXT *DrawContext, IN OUT BOOT_PICKER_GUI_CONTEXT *GuiContext)
Definition Password.c:864
#define OC_VOICE_OVER_AUDIO_FILE_DEFAULT
Definition OcAudio.h:45
#define OC_VOICE_OVER_AUDIO_FILE_CHOOSE_OS
Definition OcAudio.h:44
#define OC_VOICE_OVER_AUDIO_BASE_TYPE_OPEN_CORE
Definition OcAudio.h:38
#define OC_ATTR_REDUCE_MOTION
@ OcPickerShowPicker
#define OC_VOICE_OVER_SILENCE_NORMAL_MS
From boot.efi, constant.
#define OC_VOICE_OVER_SIGNAL_NORMAL_MS
From boot.efi, constant.
OC_PRIVILEGE_LEVEL
#define OC_VOICE_OVER_SIGNALS_NORMAL
Username prompt or any input for boot.efi.
EFI_BOOT_SERVICES * gBS
#define DEFAULT_CURSOR_OFFSET_X
Definition OcBootstrap.c:37
EFI_STATUS EFIAPI OcShowMenuByOc(IN OC_BOOT_CONTEXT *BootContext, IN OC_BOOT_ENTRY **BootEntries, OUT OC_BOOT_ENTRY **ChosenBootEntry)
Definition OcBootstrap.c:94
STATIC VOID OcSetInitialCursorOffset(VOID)
Definition OcBootstrap.c:79
EFI_STATUS EFIAPI UefiMain(IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable)
STATIC EFI_CONSOLE_CONTROL_SCREEN_MODE mPreviousMode
Definition OcBootstrap.c:43
STATIC EFI_STATUS OcShowMenuByOcEnter(IN BOOT_PICKER_GUI_CONTEXT *GuiContext)
Definition OcBootstrap.c:47
STATIC VOID OcShowMenuByOcLeave(VOID)
Definition OcBootstrap.c:69
STATIC EFI_STATUS EFIAPI GuiOcInterfacePopulate(IN OC_INTERFACE_PROTOCOL *This, IN OC_STORAGE_CONTEXT *Storage, IN OC_PICKER_CONTEXT *Context)
STATIC GUI_DRAWING_CONTEXT mDrawContext
Definition OcBootstrap.c:42
EFI_STATUS EFIAPI OcShowPasswordByOc(IN OC_PICKER_CONTEXT *Context, IN OC_PRIVILEGE_LEVEL Level)
EFI_STATUS InternalContextConstruct(OUT BOOT_PICKER_GUI_CONTEXT *Context, IN OC_STORAGE_CONTEXT *Storage, IN OC_PICKER_CONTEXT *Picker)
Definition GuiApp.c:389
#define DEFAULT_CURSOR_OFFSET_Y
Definition OcBootstrap.c:38
STATIC OC_INTERFACE_PROTOCOL mOcInterface
BOOT_PICKER_GUI_CONTEXT mGuiContext
Definition GuiApp.c:29
EFI_CONSOLE_CONTROL_SCREEN_MODE OcConsoleControlSetMode(IN EFI_CONSOLE_CONTROL_SCREEN_MODE Mode)
#define OC_INTERFACE_REVISION
Definition OcInterface.h:27
EFI_GUID gOcInterfaceProtocolGuid
VOID GuiRedrawAndFlushScreen(IN OUT GUI_DRAWING_CONTEXT *DrawContext)
Definition OpenCanopy.c:833
VOID GuiClearScreen(IN OUT GUI_DRAWING_CONTEXT *DrawContext, IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Pixel)
EFI_STATUS GuiLibConstruct(IN BOOT_PICKER_GUI_CONTEXT *GuiContext, IN INT32 CursorOffsetX, IN INT32 CursorOffsetY)
Definition OpenCanopy.c:846
VOID GuiDrawLoop(IN OUT GUI_DRAWING_CONTEXT *DrawContext)
VOID GuiLibDestruct(VOID)
Definition OpenCanopy.c:922
#define ASSERT(x)
Definition coder.h:55
OC_PICKER_CONTEXT * PickerContext
Definition GuiApp.h:136
EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION BackgroundColor
Definition GuiApp.h:124