2022-05-05 04:33:54 +01:00

850 lines
23 KiB
C

#include <Uefi.h>
#include <Library/BaseLib.h>
#include <Library/DebugLib.h>
#include <Library/OcCryptoLib.h>
#include <Library/OcMiscLib.h>
#include <Library/ResetSystemLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include "../OpenCanopy.h"
#include "../GuiApp.h"
#include "../GuiIo.h"
#include "BootPicker.h"
#include "Common.h"
#define PASSWORD_FIRST_DOT_SPACE 11U
//
// Due to the embedded ENTER button of the 'Modern' theme, the last dot needs
// less padding.
//
#define PASSWORD_LAST_DOT_SPACE 9U
#define PASSWORD_INTER_DOT_SPACE 5U
//
// Offset the ENTER button is offset into the right end of the password prompt.
//
#define PASSWORD_ENTER_INTERNAL_OFFSET 25U
//
// Space between the password lock and the password box.
//
#define PASSWORD_BOX_SPACE 30U
typedef struct {
CHAR8 Password[OC_PASSWORD_MAX_LEN];
UINT8 PasswordLen;
} GUI_PASSWORD_INFO;
typedef struct {
GUI_OBJ_CHILD Hdr;
GUI_PASSWORD_INFO PasswordInfo;
BOOLEAN RequestConfirm;
UINT8 MaxPasswordDots;
} GUI_PASSWORD_BOX;
extern GUI_KEY_CONTEXT *mKeyContext;
extern GUI_PASSWORD_BOX mPasswordBox;
extern GUI_OBJ_CLICKABLE mPasswordEnter;
extern GUI_OBJ_CHILD mPasswordLock;
extern GUI_OBJ_CHILD mPasswordBoxContainer;
// FIXME: Create one context for drawing, pointers, and keys.
extern GUI_POINTER_CONTEXT *mPointerContext;
STATIC GUI_INTERPOLATION mPasswordIncorrectInterpol = {
GuiInterpolTypeLinear,
0,
3,
0,
0,
0
};
STATIC GUI_OBJ *mPasswordFocusList[] = {
&mPasswordBoxContainer.Obj,
&mCommonRestart.Hdr.Obj,
&mCommonShutDown.Hdr.Obj
};
STATIC GUI_OBJ *mPasswordFocusListMinimal[] = {
&mPasswordBoxContainer.Obj
};
STATIC UINT8 mPasswordNumTries = 0;
STATIC
VOID
InternalInitPasswordIncorrectInterpol (
IN CONST GUI_DRAWING_CONTEXT *DrawContext,
IN UINT64 StartTime
)
{
mPasswordIncorrectInterpol.StartTime = StartTime;
mPasswordIncorrectInterpol.EndValue = 20 * DrawContext->Scale;
}
BOOLEAN
InternalPasswordAnimateIncorrect (
IN BOOT_PICKER_GUI_CONTEXT *Context,
IN OUT GUI_DRAWING_CONTEXT *DrawContext,
IN UINT64 CurrentTime
)
{
STATIC UINT32 LastOff = 0;
STATIC BOOLEAN Left = FALSE;
STATIC UINT8 Iteration = 0;
UINT32 DeltaOrig;
UINT32 DeltaAdd;
DeltaOrig = GuiGetInterpolatedValue (
&mPasswordIncorrectInterpol,
CurrentTime
);
DeltaAdd = DeltaOrig - LastOff;
LastOff = DeltaOrig;
if (Left) {
mPasswordBoxContainer.Obj.OffsetX -= DeltaAdd;
GuiRequestDraw (
(UINT32)mPasswordBoxContainer.Obj.OffsetX,
(UINT32)mPasswordBoxContainer.Obj.OffsetY,
mPasswordBoxContainer.Obj.Width + DeltaAdd,
mPasswordBoxContainer.Obj.Height
);
} else {
GuiRequestDraw (
(UINT32)mPasswordBoxContainer.Obj.OffsetX,
(UINT32)mPasswordBoxContainer.Obj.OffsetY,
mPasswordBoxContainer.Obj.Width + DeltaAdd,
mPasswordBoxContainer.Obj.Height
);
mPasswordBoxContainer.Obj.OffsetX += DeltaAdd;
}
if (CurrentTime - mPasswordIncorrectInterpol.StartTime >= mPasswordIncorrectInterpol.Duration) {
LastOff = 0;
if (Iteration == 5) {
Iteration = 0;
mPasswordEnter.Hdr.Obj.Opacity = 0xFF;
return TRUE;
}
mPasswordIncorrectInterpol.StartTime = CurrentTime + 1;
++Iteration;
//
// Left/Right start toggles between tries.
//
Left = !Left;
}
return FALSE;
}
STATIC
VOID
InternalQueueIncorrectPassword (
OUT GUI_DRAWING_CONTEXT *DrawContext
)
{
STATIC GUI_ANIMATION PwAnim = {
INITIALIZE_LIST_HEAD_VARIABLE (PwAnim.Link),
NULL,
InternalPasswordAnimateIncorrect
};
if (!IsNodeInList (&PwAnim.Link, &DrawContext->Animations)) {
InternalInitPasswordIncorrectInterpol (DrawContext, DrawContext->FrameTime);
InsertHeadList (&DrawContext->Animations, &PwAnim.Link);
}
}
STATIC
VOID
InternalRedrawPaswordBox (
VOID
)
{
GuiRequestDraw (
(UINT32)mPasswordBoxContainer.Obj.OffsetX,
(UINT32)mPasswordBoxContainer.Obj.OffsetY,
mPasswordBoxContainer.Obj.Width,
mPasswordBoxContainer.Obj.Height
);
}
BOOLEAN
InternalConfirmPassword (
IN OUT GUI_DRAWING_CONTEXT *DrawContext,
IN CONST BOOT_PICKER_GUI_CONTEXT *Context
)
{
BOOLEAN Result;
CONST OC_PRIVILEGE_CONTEXT *Privilege;
GUI_PTR_POSITION PtrPosition;
if (mPointerContext != NULL) {
GuiPointerGetPosition (mPointerContext, &PtrPosition);
}
Privilege = Context->PickerContext->PrivilegeContext;
Result = Context->PickerContext->VerifyPassword (
(CONST UINT8 *)mPasswordBox.PasswordInfo.Password,
mPasswordBox.PasswordInfo.PasswordLen,
Privilege
);
GuiKeyReset (mKeyContext);
if (mPointerContext != NULL) {
GuiPointerReset (mPointerContext);
GuiPointerSetPosition (mPointerContext, &PtrPosition);
}
DrawContext->CursorOpacity = 0xFF;
SecureZeroMem (mPasswordBox.PasswordInfo.Password, mPasswordBox.PasswordInfo.PasswordLen);
if (Result) {
if (Context->PickerContext->PickerAudioAssist) {
Context->PickerContext->PlayAudioFile (
Context->PickerContext,
OC_VOICE_OVER_AUDIO_FILE_PASSWORD_ACCEPTED,
OC_VOICE_OVER_AUDIO_BASE_TYPE_OPEN_CORE,
TRUE
);
}
mPasswordNumTries = 0;
return TRUE;
}
if (Context->PickerContext->PickerAudioAssist) {
Context->PickerContext->PlayAudioFile (
Context->PickerContext,
OC_VOICE_OVER_AUDIO_FILE_PASSWORD_INCORRECT,
OC_VOICE_OVER_AUDIO_BASE_TYPE_OPEN_CORE,
TRUE
);
}
++mPasswordNumTries;
if (mPasswordNumTries == OC_PASSWORD_MAX_RETRIES) {
if (Context->PickerContext->PickerAudioAssist) {
Context->PickerContext->PlayAudioFile (
Context->PickerContext,
OC_VOICE_OVER_AUDIO_FILE_PASSWORD_RETRY_LIMIT,
OC_VOICE_OVER_AUDIO_BASE_TYPE_OPEN_CORE,
TRUE
);
DEBUG ((DEBUG_WARN, "OCB: User failed to verify password %d times running\n", OC_PASSWORD_MAX_RETRIES));
}
//
// Hide all UI except the password lock when retries have been exceeded.
//
mPasswordBoxContainer.Obj.Opacity = 0;
InternalRedrawPaswordBox ();
mCommonActionButtonsContainer.Obj.Opacity = 0;
GuiRequestDraw (
(UINT32)mCommonActionButtonsContainer.Obj.OffsetX,
(UINT32)mCommonActionButtonsContainer.Obj.OffsetY,
mCommonActionButtonsContainer.Obj.Width,
mCommonActionButtonsContainer.Obj.Height
);
DrawContext->CursorOpacity = 0;
}
return FALSE;
}
STATIC
VOID
InternalRequestPasswordConfirmation (
IN OUT GUI_DRAWING_CONTEXT *DrawContext
)
{
DrawContext->CursorOpacity = 0;
mPasswordEnter.Hdr.Obj.Opacity = 0x100 / 2;
mPasswordBox.RequestConfirm = TRUE;
InternalRedrawPaswordBox ();
GuiRequestDraw (
(UINT32)(mPasswordBoxContainer.Obj.OffsetX + mPasswordEnter.Hdr.Obj.OffsetX),
(UINT32)(mPasswordBoxContainer.Obj.OffsetY + mPasswordEnter.Hdr.Obj.OffsetY),
mPasswordEnter.Hdr.Obj.Width,
mPasswordEnter.Hdr.Obj.Height
);
}
VOID
InternalPasswordBoxKeyEvent (
IN OUT GUI_OBJ *This,
IN OUT GUI_DRAWING_CONTEXT *DrawContext,
IN BOOT_PICKER_GUI_CONTEXT *Context,
IN CONST GUI_KEY_EVENT *KeyEvent
)
{
if (KeyEvent->UnicodeChar == CHAR_CARRIAGE_RETURN) {
//
// RETURN finalizes the input.
//
InternalRequestPasswordConfirmation (DrawContext);
return;
}
if (KeyEvent->UnicodeChar == CHAR_BACKSPACE) {
//
// Delete the last entered character, if such exists.
//
if (mPasswordBox.PasswordInfo.PasswordLen > 0) {
--mPasswordBox.PasswordInfo.PasswordLen;
mPasswordBox.PasswordInfo.Password[mPasswordBox.PasswordInfo.PasswordLen] = 0;
}
if (Context->PickerContext->PickerAudioAssist) {
Context->PickerContext->PlayAudioFile (
Context->PickerContext,
APPLE_VOICE_OVER_AUDIO_FILE_BEEP,
OC_VOICE_OVER_AUDIO_BASE_TYPE_APPLE,
TRUE
);
}
} else if ( (KeyEvent->UnicodeChar != CHAR_NULL)
&& (KeyEvent->UnicodeChar == (CHAR8)KeyEvent->UnicodeChar)
&& (mPasswordBox.PasswordInfo.PasswordLen < ARRAY_SIZE (mPasswordBox.PasswordInfo.Password)))
{
mPasswordBox.PasswordInfo.Password[mPasswordBox.PasswordInfo.PasswordLen] = (CHAR8)KeyEvent->UnicodeChar;
++mPasswordBox.PasswordInfo.PasswordLen;
} else {
//
// Only ASCII characters are supported.
//
if (Context->PickerContext->PickerAudioAssist) {
Context->PickerContext->PlayAudioBeep (
Context->PickerContext,
OC_VOICE_OVER_SIGNALS_ERROR,
OC_VOICE_OVER_SIGNAL_ERROR_MS,
OC_VOICE_OVER_SILENCE_ERROR_MS
);
}
return;
}
ASSERT (mPasswordBoxContainer.Parent == NULL);
ASSERT (mPasswordBoxContainer.Obj.OffsetX >= 0);
ASSERT (mPasswordBoxContainer.Obj.OffsetY >= 0);
ASSERT (mPasswordBoxContainer.Obj.OffsetX + mPasswordBoxContainer.Obj.Width <= DrawContext->Screen.Width);
ASSERT (mPasswordBoxContainer.Obj.OffsetX + mPasswordBoxContainer.Obj.Height <= DrawContext->Screen.Height);
GuiRequestDraw (
(UINT32)mPasswordBoxContainer.Obj.OffsetX,
(UINT32)mPasswordBoxContainer.Obj.OffsetY,
mPasswordBoxContainer.Obj.Width,
mPasswordBoxContainer.Obj.Height
);
}
VOID
InternalPasswordBoxFocus (
IN CONST GUI_OBJ *This,
IN OUT GUI_DRAWING_CONTEXT *DrawContext,
IN BOOLEAN Focus
)
{
if (Focus) {
mPasswordBoxContainer.Obj.Opacity = 0xFF;
DrawContext->GuiContext->AudioPlaybackTimeout = 0;
DrawContext->GuiContext->VoAction = CanopyVoFocusPassword;
} else {
mPasswordBoxContainer.Obj.Opacity = 0x100 / 2;
}
InternalRedrawPaswordBox ();
}
VOID
InternalPasswordViewKeyEvent (
IN OUT GUI_OBJ *This,
IN OUT GUI_DRAWING_CONTEXT *DrawContext,
IN BOOT_PICKER_GUI_CONTEXT *Context,
IN CONST GUI_KEY_EVENT *KeyEvent
)
{
//
// Disable input when maximum password retries have been reached.
//
if (mPasswordNumTries >= OC_PASSWORD_MAX_RETRIES) {
return;
}
if (KeyEvent->OcKeyCode == OC_INPUT_VOICE_OVER) {
DrawContext->GuiContext->PickerContext->ToggleVoiceOver (
DrawContext->GuiContext->PickerContext,
OC_VOICE_OVER_AUDIO_FILE_ENTER_PASSWORD,
OC_VOICE_OVER_AUDIO_BASE_TYPE_OPEN_CORE
);
return;
}
InternalFocusKeyHandler (
DrawContext,
Context,
KeyEvent
);
}
GUI_OBJ *
InternalPasswordViewPtrEvent (
IN OUT GUI_OBJ *This,
IN OUT GUI_DRAWING_CONTEXT *DrawContext,
IN BOOT_PICKER_GUI_CONTEXT *Context,
IN INT64 BaseX,
IN INT64 BaseY,
IN CONST GUI_PTR_EVENT *Event
)
{
//
// Disable input when maximum password retries have been reached.
//
if (mPasswordNumTries >= OC_PASSWORD_MAX_RETRIES) {
return NULL;
}
return InternalCommonViewPtrEvent (
This,
DrawContext,
Context,
BaseX,
BaseY,
Event
);
}
VOID
InternalPasswordLockDraw (
IN OUT GUI_OBJ *This,
IN OUT GUI_DRAWING_CONTEXT *DrawContext,
IN BOOT_PICKER_GUI_CONTEXT *Context,
IN INT64 BaseX,
IN INT64 BaseY,
IN UINT32 OffsetX,
IN UINT32 OffsetY,
IN UINT32 Width,
IN UINT32 Height,
IN UINT8 Opacity
)
{
GuiDrawToBuffer (
&Context->Icons[ICON_LOCK][ICON_TYPE_BASE],
Opacity,
DrawContext,
BaseX,
BaseY,
OffsetX,
OffsetY,
Width,
Height
);
}
VOID
InternalPasswordBoxDraw (
IN OUT GUI_OBJ *This,
IN OUT GUI_DRAWING_CONTEXT *DrawContext,
IN BOOT_PICKER_GUI_CONTEXT *Context,
IN INT64 BaseX,
IN INT64 BaseY,
IN UINT32 OffsetX,
IN UINT32 OffsetY,
IN UINT32 Width,
IN UINT32 Height,
IN UINT8 Opacity
)
{
CONST GUI_IMAGE *BoxImage;
CONST GUI_IMAGE *DotImage;
UINT8 DotIndex;
BoxImage = &Context->Icons[ICON_PASSWORD][ICON_TYPE_BASE];
DotImage = &Context->Icons[ICON_DOT][ICON_TYPE_BASE];
GuiDrawToBuffer (
BoxImage,
Opacity,
DrawContext,
BaseX,
BaseY,
OffsetX,
OffsetY,
Width,
Height
);
//
// Selective drawing is unlikely worth it.
//
for (
DotIndex = 0;
DotIndex < MIN (mPasswordBox.PasswordInfo.PasswordLen, mPasswordBox.MaxPasswordDots);
++DotIndex
)
{
GuiDrawChildImage (
DotImage,
Opacity,
DrawContext,
BaseX,
BaseY,
DotIndex * (DotImage->Width + PASSWORD_INTER_DOT_SPACE * DrawContext->Scale) + PASSWORD_FIRST_DOT_SPACE * DrawContext->Scale,
(BoxImage->Height - DotImage->Height) / 2,
OffsetX,
OffsetY,
Width,
Height
);
}
}
GUI_OBJ *
InternalPasswordEnterPtrEvent (
IN OUT GUI_OBJ *This,
IN OUT GUI_DRAWING_CONTEXT *DrawContext,
IN BOOT_PICKER_GUI_CONTEXT *Context,
IN INT64 BaseX,
IN INT64 BaseY,
IN CONST GUI_PTR_EVENT *Event
)
{
UINT8 Result;
Result = InternalCommonSimpleButtonPtrEvent (
This,
DrawContext,
Context,
BaseX,
BaseY,
Event
);
switch (Result) {
case CommonPtrNotHit:
{
return NULL;
}
case CommonPtrAction:
{
InternalRequestPasswordConfirmation (DrawContext);
//
// Falthrough to 'hit' case.
//
}
case CommonPtrHit:
{
break;
}
}
return This;
}
BOOLEAN
InternalPasswordExitLoop (
IN OUT GUI_DRAWING_CONTEXT *DrawContext,
IN BOOT_PICKER_GUI_CONTEXT *Context
)
{
BOOLEAN Confirmed;
ASSERT (Context != NULL);
//
// This is done here to have one more draw loop iteration to flush hiding
// the UI elements.
//
if (mPasswordNumTries >= OC_PASSWORD_MAX_RETRIES) {
gBS->Stall (SECONDS_TO_MICROSECONDS (5));
ResetWarm ();
}
if (mPasswordBox.RequestConfirm) {
mPasswordBox.RequestConfirm = FALSE;
if (!Context->PickerContext->PickerAudioAssist) {
InternalQueueIncorrectPassword (DrawContext);
}
Confirmed = InternalConfirmPassword (DrawContext, Context);
SecureZeroMem (&mPasswordBox.PasswordInfo, sizeof (mPasswordBox.PasswordInfo));
return Confirmed;
}
return FALSE;
}
STATIC GUI_OBJ_CHILD *mPasswordViewChildren[] = {
&mPasswordLock,
&mPasswordBoxContainer,
&mCommonActionButtonsContainer
};
STATIC GUI_OBJ_CHILD *mPasswordViewChildrenMinimal[] = {
&mPasswordLock,
&mPasswordBoxContainer
};
STATIC GUI_VIEW_CONTEXT mPasswordViewContext = {
InternalCommonViewDraw,
InternalPasswordViewPtrEvent,
ARRAY_SIZE (mPasswordViewChildren),
mPasswordViewChildren,
InternalPasswordViewKeyEvent,
InternalGetCursorImage,
InternalPasswordExitLoop,
mPasswordFocusList,
ARRAY_SIZE (mPasswordFocusList)
};
STATIC GUI_VIEW_CONTEXT mPasswordViewContextMinimal = {
InternalCommonViewDraw,
InternalPasswordViewPtrEvent,
ARRAY_SIZE (mPasswordViewChildrenMinimal),
mPasswordViewChildrenMinimal,
InternalPasswordViewKeyEvent,
InternalGetCursorImage,
InternalPasswordExitLoop,
mPasswordFocusListMinimal,
ARRAY_SIZE (mPasswordFocusListMinimal)
};
GLOBAL_REMOVE_IF_UNREFERENCED GUI_OBJ_CHILD mPasswordLock = {
{
0, 0, 0, 0, 0xFF,
InternalPasswordLockDraw,
NULL,
GuiObjDelegatePtrEvent,
NULL,
0,
NULL
},
NULL
};
GLOBAL_REMOVE_IF_UNREFERENCED GUI_PASSWORD_BOX mPasswordBox = {
{
{
0, 0, 0, 0, 0xFF,
InternalPasswordBoxDraw,
NULL,
GuiObjDelegatePtrEvent,
NULL,
0,
NULL
},
&mPasswordBoxContainer.Obj
},
{
{ '\0' }, 0
},
FALSE,
0
};
GLOBAL_REMOVE_IF_UNREFERENCED GUI_OBJ_CLICKABLE mPasswordEnter = {
{
{
0, 0, 0, 0, 0xFF,
InternalCommonSimpleButtonDraw,
NULL,
InternalPasswordEnterPtrEvent,
NULL,
0,
NULL
},
&mPasswordBoxContainer.Obj
},
0,
0
};
STATIC GUI_OBJ_CHILD *mPasswordBoxContainerChildren[] = {
&mPasswordBox.Hdr,
&mPasswordEnter.Hdr
};
GLOBAL_REMOVE_IF_UNREFERENCED GUI_OBJ_CHILD mPasswordBoxContainer = {
{
0, 0, 0, 0, 0xFF,
GuiObjDrawDelegate,
InternalPasswordBoxKeyEvent,
GuiObjDelegatePtrEvent,
InternalPasswordBoxFocus,
ARRAY_SIZE (mPasswordBoxContainerChildren),
mPasswordBoxContainerChildren
},
NULL
};
BOOLEAN
InternalPasswordAnimateIntro (
IN BOOT_PICKER_GUI_CONTEXT *Context,
IN OUT GUI_DRAWING_CONTEXT *DrawContext,
IN UINT64 CurrentTime
)
{
UINT8 Opacity;
Opacity = (UINT8)GuiGetInterpolatedValue (
&mCommonIntroOpacityInterpol,
CurrentTime
);
DrawContext->Screen.Opacity = Opacity;
GuiRequestDraw (
(UINT32)mPasswordLock.Obj.OffsetX,
(UINT32)mPasswordLock.Obj.OffsetY,
mPasswordLock.Obj.Width,
mPasswordLock.Obj.Height
);
GuiRequestDraw (
(UINT32)mPasswordBoxContainer.Obj.OffsetX,
(UINT32)mPasswordBoxContainer.Obj.OffsetY,
mPasswordBoxContainer.Obj.Width,
mPasswordBoxContainer.Obj.Height
);
GuiRequestDraw (
(UINT32)mCommonActionButtonsContainer.Obj.OffsetX,
(UINT32)mCommonActionButtonsContainer.Obj.OffsetY,
mCommonActionButtonsContainer.Obj.Width,
mCommonActionButtonsContainer.Obj.Height
);
return CurrentTime - mCommonIntroOpacityInterpol.StartTime >= mCommonIntroOpacityInterpol.Duration;
}
STATIC GUI_ANIMATION mPasswordIntroAnimation = {
INITIALIZE_LIST_HEAD_VARIABLE (mPasswordIntroAnimation.Link),
NULL,
InternalPasswordAnimateIntro
};
EFI_STATUS
PasswordViewInitialize (
OUT GUI_DRAWING_CONTEXT *DrawContext,
IN BOOT_PICKER_GUI_CONTEXT *GuiContext
)
{
CONST GUI_IMAGE *LockImage;
CONST GUI_IMAGE *BoxImage;
CONST GUI_IMAGE *DotImage;
CONST GUI_IMAGE *EnterImage;
UINT32 EnterOffset;
UINT32 BoxOffset;
UINT32 ImageMidOffset;
UINT32 FirstOffset;
UINT32 EnterInternalOffset;
mKeyContext->KeyFilter = OC_PICKER_KEYS_FOR_TYPING;
CommonViewInitialize (
DrawContext,
GuiContext,
(GuiContext->PickerContext->PickerAttributes & OC_ATTR_USE_MINIMAL_UI) == 0
? &mPasswordViewContext
: &mPasswordViewContextMinimal
);
LockImage = &GuiContext->Icons[ICON_LOCK][ICON_TYPE_BASE];
BoxImage = &GuiContext->Icons[ICON_PASSWORD][ICON_TYPE_BASE];
DotImage = &GuiContext->Icons[ICON_DOT][ICON_TYPE_BASE];
EnterImage = &GuiContext->Icons[ICON_ENTER][ICON_TYPE_BASE];
if (EnterImage->Height > BoxImage->Height) {
BoxOffset = (EnterImage->Height - BoxImage->Height) / 2;
EnterOffset = 0;
} else {
BoxOffset = 0;
EnterOffset = (BoxImage->Height - EnterImage->Height) / 2;
}
mPasswordLock.Obj.Width = LockImage->Width;
mPasswordLock.Obj.Height = LockImage->Height;
mPasswordLock.Obj.OffsetX = (DrawContext->Screen.Width - mPasswordLock.Obj.Width) / 2;
mPasswordLock.Obj.OffsetY = (DrawContext->Screen.Height - mPasswordLock.Obj.Height) / 2;
ImageMidOffset = (EnterImage->Height / 2) * EnterImage->Width;
for (
FirstOffset = ImageMidOffset;
FirstOffset < ImageMidOffset + EnterImage->Width;
++FirstOffset
)
{
if (EnterImage->Buffer[FirstOffset].Reserved > 0) {
break;
}
}
if (PASSWORD_ENTER_INTERNAL_OFFSET * DrawContext->Scale > FirstOffset - ImageMidOffset) {
EnterInternalOffset = PASSWORD_ENTER_INTERNAL_OFFSET * DrawContext->Scale - (FirstOffset - ImageMidOffset);
} else {
EnterInternalOffset = 0;
}
mPasswordBox.Hdr.Obj.Width = BoxImage->Width;
mPasswordBox.Hdr.Obj.Height = BoxImage->Height;
mPasswordBox.Hdr.Obj.OffsetX = 0;
mPasswordBox.Hdr.Obj.OffsetY = BoxOffset;
mPasswordBox.MaxPasswordDots = (UINT8)(
(mPasswordBox.Hdr.Obj.Width - EnterInternalOffset - (PASSWORD_FIRST_DOT_SPACE + PASSWORD_LAST_DOT_SPACE - PASSWORD_INTER_DOT_SPACE) * DrawContext->Scale) / (DotImage->Width + PASSWORD_INTER_DOT_SPACE * DrawContext->Scale)
);
mPasswordEnter.Hdr.Obj.Width = EnterImage->Width;
mPasswordEnter.Hdr.Obj.Height = EnterImage->Height;
mPasswordEnter.Hdr.Obj.OffsetX = mPasswordBox.Hdr.Obj.Width - PASSWORD_ENTER_INTERNAL_OFFSET * DrawContext->Scale;
mPasswordEnter.Hdr.Obj.OffsetY = EnterOffset;
mPasswordEnter.ImageId = ICON_ENTER;
mPasswordEnter.ImageState = ICON_TYPE_BASE;
mPasswordBoxContainer.Obj.Width = BoxImage->Width + EnterImage->Width - PASSWORD_ENTER_INTERNAL_OFFSET * DrawContext->Scale;
mPasswordBoxContainer.Obj.Height = MAX (BoxImage->Height, EnterImage->Height);
mPasswordBoxContainer.Obj.OffsetX = (DrawContext->Screen.Width - mPasswordBox.Hdr.Obj.Width) / 2;
mPasswordBoxContainer.Obj.OffsetY = mPasswordLock.Obj.OffsetY + mPasswordLock.Obj.Height + PASSWORD_BOX_SPACE * DrawContext->Scale - BoxOffset;
if (!GuiContext->PickerContext->PickerAudioAssist) {
//
// Fade-in the entire screen.
//
DrawContext->Screen.Opacity = 0;
InsertHeadList (&DrawContext->Animations, &mPasswordIntroAnimation.Link);
}
//
// Action Buttons fade-in is handled by screen opacity.
//
mCommonActionButtonsContainer.Obj.Opacity = 0xFF;
if (GuiContext->PickerContext->PickerAudioAssist) {
GuiContext->PickerContext->PlayAudioFile (
GuiContext->PickerContext,
OC_VOICE_OVER_AUDIO_FILE_ENTER_PASSWORD,
OC_VOICE_OVER_AUDIO_BASE_TYPE_OPEN_CORE,
TRUE
);
}
return EFI_SUCCESS;
}
VOID
PasswordViewDeinitialize (
IN OUT GUI_DRAWING_CONTEXT *DrawContext,
IN OUT BOOT_PICKER_GUI_CONTEXT *GuiContext
)
{
GuiViewDeinitialize (DrawContext, GuiContext);
}