VeraCrypt
aboutsummaryrefslogtreecommitdiff
path: root/Library/PasswordLib/PicturePassword.c
diff options
context:
space:
mode:
Diffstat (limited to 'Library/PasswordLib/PicturePassword.c')
-rw-r--r--Library/PasswordLib/PicturePassword.c629
1 files changed, 629 insertions, 0 deletions
diff --git a/Library/PasswordLib/PicturePassword.c b/Library/PasswordLib/PicturePassword.c
new file mode 100644
index 0000000..f917899
--- /dev/null
+++ b/Library/PasswordLib/PicturePassword.c
@@ -0,0 +1,629 @@
+/** @file
+Picture password
+
+Copyright (c) 2016. Disk Cryptography Services for EFI (DCS), Alex Kolotnikov
+Copyright (c) 2016. VeraCrypt, Mounir IDRASSI
+
+This program and the accompanying materials
+are licensed and made available under the terms and conditions
+of the GNU Lesser General Public License, version 3.0 (LGPL-3.0).
+
+The full text of the license may be found at
+https://opensource.org/licenses/LGPL-3.0
+**/
+
+#include <Uefi.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/DebugLib.h>
+
+#include <Library/CommonLib.h>
+#include <Library/GraphLib.h>
+#include <Library/PasswordLib.h>
+
+CHAR16* gPasswordPictureFileName = NULL;
+
+CHAR8* gPasswordPictureChars = NULL;
+CHAR8* gPasswordPictureCharsDefault = "MN/[aQ-eyPr}GT: |V^UqiI_gbdA9YwZ%f8t6S@D\"7uXl\\30R#+zH*,W4J?=&BLFv]hx~E;$<.o'sp1`(>C)O{!5j2nmkcK";
+//CHAR8* gPicturePasswordCharsDefault = " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~";
+UINTN gPasswordPictureCharsLen = 95;
+
+UINT8 gPasswordVisible = 0;
+int gPasswordShowMark = 1;
+
+int gPlatformLocked = 0;
+int gTPMLocked = 0;
+int gSCLocked = 0;
+
+
+//////////////////////////////////////////////////////////////////////////
+// Picture password
+//////////////////////////////////////////////////////////////////////////
+CONST CHAR16* BmpName = L"Test.bmp";
+VOID* Bmp = NULL;
+UINTN BmpSize = 0;
+BLT_HEADER* bltPwd = NULL;
+UINTN posPictX, posPictY;
+BLT_HEADER* bltScrn = NULL;
+UINTN* cellSelected = NULL;
+UINTN picPwdIdx = 0;
+UINTN sHeight;
+UINTN sWidth;
+UINTN step;
+
+DRAW_CONTEXT ctxCursor;
+DRAW_CONTEXT ctxCell;
+DRAW_CONTEXT ctxMark;
+DRAW_CONTEXT ctxSet;
+
+VOID
+CellUpdate(
+ IN OUT BLT_HEADER* blt,
+ IN UINTN x,
+ IN UINTN y,
+ IN BOOLEAN selected) {
+ if (selected && gPasswordShowMark) {
+ BltCircle(blt, &ctxMark, (INT32)(x * step + step / 2), (INT32)(y * step + step / 2), (INT32)(step / 3), TRUE);
+ BltCircle(blt, &ctxCell, (INT32)(x * step + step / 2), (INT32)(y * step + step / 2), (INT32)(step / 9), TRUE);
+ }
+ else {
+ CHAR8 ch[2] = { 0,0 };
+ BltCircle(blt, &ctxCell, (INT32)(x * step + step / 2), (INT32)(y * step + step / 2), (INT32)(step / 3), FALSE);
+ if (gPasswordVisible) {
+ ch[0] = gPasswordPictureChars[(x + blt->Width / step * y) % gPasswordPictureCharsLen];
+ BltText(blt, &ctxCell, (INT32)(x * step + step / 2 - 12), (INT32)(y * step + step / 2 - 12), 256, ch);
+ }
+ }
+}
+
+BOOLEAN
+CellGetSelected(
+ IN OUT BLT_HEADER* blt,
+ IN UINTN x,
+ IN UINTN y,
+ OUT UINTN* cellX,
+ OUT UINTN* cellY) {
+ RECT reg;
+ UINTN sen;
+ if (x > blt->Width || y > blt->Height) return FALSE;
+ *cellX = x / step;
+ *cellY = y / step;
+ sen = step / 5; // zone sensible
+ reg.left = (UINT32)(*cellX * step + step / 2 - sen);
+ reg.right = (UINT32)(*cellX * step + step / 2 + sen);
+ reg.top = (UINT32)(*cellY * step + step / 2 - sen);
+ reg.bottom = (UINT32)(*cellY * step + step / 2 + sen);
+ return (x > reg.left && x < reg.right && y > reg.top && y < reg.bottom);
+}
+
+VOID
+DrawCursor(IN OUT BLT_HEADER* blt,
+ IN UINTN x,
+ IN UINTN y
+ ) {
+ BltLine(blt, &ctxCursor, (INT32)(x - 10), (INT32)y, (INT32)(x + 10), (INT32)y);
+ BltLine(blt, &ctxCursor, (INT32)x, (INT32)(y - 10), (INT32)x, (INT32)(y + 10));
+}
+
+typedef struct _TOUCH_ZONE {
+ UINTN Zone;
+ CHAR8* Message;
+ UINTN RetCode;
+ INT32 TextScale;
+} TOUCH_ZONE, *PTOUCH_ZONE;
+
+enum TouchZoneIds {
+ tznLogin = 1,
+ tznBeep,
+ tznShow,
+ tznChange
+};
+
+CHAR8* msgLogin = "LOGIN";
+CHAR8* msgBeepOn = "Beep\non";
+CHAR8* msgBeepOff = "Beep\noff";
+CHAR8* msgChg = "Change\npwd";
+CHAR8* msgShowPwd = "Show\npwd";
+CHAR8* msgHidePwd = "Hide\npwd";
+CHAR8* msgNewPwd = "New\npwd";
+CHAR8* msgConfirmPwd = "Confirm\npwd";
+CHAR8* msgPlatformLocked = "PLT\nlkd";
+CHAR8* msgPlatformUnLocked = "PLT\nunlkd";
+CHAR8* msgTpmLocked = "TPM\nlkd";
+CHAR8* msgTpmUnLocked = "TPM\nunlkd";
+
+TOUCH_ZONE TZN_Login = { 0, NULL, tznLogin, 128 };
+TOUCH_ZONE TZN_Speaker = { 2, NULL, tznBeep, 64 };
+TOUCH_ZONE TZN_Show = { 3, NULL, tznShow, 64 };
+TOUCH_ZONE TZN_Change = { 5, NULL, tznChange, 32 };
+TOUCH_ZONE TZN_Platform = { 6, NULL, 0, 32 };
+TOUCH_ZONE TZN_Tpm = { 7, NULL, 0, 32 };
+
+VOID
+DrawTouchZone(
+ IN PTOUCH_ZONE zone
+ ) {
+ BltFill(bltScrn, gColorBlack, (INT32)(sWidth - step), (INT32)(2 + zone->Zone * step), (INT32)(INT32)(sWidth - 2), (INT32)(step + zone->Zone * step));
+ BltBox(bltScrn, &ctxCell, (INT32)(sWidth - step), (INT32)(2 + zone->Zone * step), (INT32)(INT32)(sWidth - 2), (INT32)(step + zone->Zone * step));
+ BltText(bltScrn, &ctxCell, (INT32)(sWidth - step * 3 / 4), (INT32)(step * 1 / 3 + zone->Zone * step), 128, zone->Message);
+}
+
+BOOLEAN
+IsTouchZone(
+ IN PTOUCH_ZONE zone,
+ IN UINTN x,
+ IN UINTN y
+ ) {
+ if (x > sWidth - step &&
+ (y > (zone->Zone * step)) &&
+ (y < (step + zone->Zone * step))) {
+ return TRUE;
+ }
+ return FALSE;
+}
+
+VOID
+DrawPwdZone(
+ IN CHAR8* pwd,
+ IN UINT32 pwdMax)
+{
+ INT32 pwdGrphMaxLen = (INT32)(sWidth - 2 * step);
+ BltFill(bltScrn, gColorBlack, 0, 0, (INT32)(sWidth - 2 * step), (INT32)(posPictY));
+ if (gPasswordVisible) {
+ BltText(bltScrn, &ctxCell, 0, 0, 256, pwd);
+ }
+ else {
+ INT32 pwdGrphLen = (INT32)(pwdGrphMaxLen * picPwdIdx / pwdMax);
+ INT32 pwdGrphHeight = (INT32)(posPictY) / 2;
+ INT32 pwdGrphTop = (INT32)(posPictY) / 4;
+ BltFill(bltScrn, gColorGreen, 0, pwdGrphTop, pwdGrphLen, pwdGrphHeight + pwdGrphTop);
+ BltFill(bltScrn, gColorBlack, pwdGrphLen, pwdGrphTop, pwdGrphMaxLen, pwdGrphHeight + pwdGrphTop);
+ }
+}
+
+EFI_STATUS
+DrawPwdPicture()
+{
+ EFI_STATUS res;
+ UINTN idx;
+ UINTN cellX, cellY;
+
+ if (bltPwd != NULL) MEM_FREE(bltPwd);
+
+ res = BmpToBlt(Bmp, BmpSize, &bltPwd);
+ if (EFI_ERROR(res)) {
+ return res;
+ }
+ cellY = 0;
+ do {
+ cellX = 0;
+ do {
+ CellUpdate(bltPwd, cellX, cellY, FALSE);
+ cellX++;
+ } while ((cellX + 1) * step <= (bltPwd->Width));
+ cellY++;
+ } while ((cellY + 1)* step <= (bltPwd->Height));
+
+ // Update selected
+ for (idx = 0; idx < picPwdIdx; ++idx) {
+ if (cellSelected[idx * 2] != MAX_INTN) {
+ CellUpdate(bltPwd, cellSelected[idx * 2], cellSelected[idx * 2 + 1], TRUE);
+ }
+ }
+ return EFI_SUCCESS;
+}
+
+VOID
+CreateDraws() {
+ // Set
+ ctxSet.Color = gColorGray;
+ ctxSet.DashLine = 0xFFFFFFFF;
+ ctxSet.Op = DrawOpSet;
+ ctxSet.Brush = NULL;
+
+ // Cursor
+ ctxCursor.Color = gColorWhite;
+ ctxCursor.DashLine = 0xFFFFFFFF;
+ ctxCursor.Op = DrawOpXor;
+ ctxCursor.Brush = NULL;
+
+ // Cell
+ ctxCell.Color = gColorGreen;
+ ctxCell.DashLine = 0xFFFFFFFF;
+ ctxCell.Op = DrawOpSet;
+ ctxCell.Brush = gBrush3;
+
+ // Shade (close to black)
+ ctxMark.AlphaColor = gColorWhite;
+ ctxMark.Alpha = 128;
+ ctxMark.Op = DrawOpAlpha;
+ ctxMark.Brush = NULL;
+}
+
+enum PictPwdAction {
+ PwdActNone = 0,
+ PwdActLogin,
+ PwdActCancel,
+ PwdActChange,
+ PwdActShow,
+ PwdActBeep,
+ PwdActNewChar,
+ PwdActUpdateZones,
+};
+
+VOID
+AskPictPwdInt(
+ IN UINTN pwdType,
+ IN UINTN pwdMax,
+ OUT CHAR8* pwd,
+ OUT UINT32* pwdLen,
+ OUT INT32* retCode
+ ) {
+ EFI_STATUS res;
+ UINTN cellX, cellY;
+ UINTN cellPrevX, cellPrevY;
+ UINTN curX, curY;
+ UINTN curPrevX, curPrevY;
+ EFI_INPUT_KEY key;
+ EFI_EVENT UpdateEvent;
+ EFI_EVENT BeepOffEvent;
+ EFI_EVENT InputEvents[3];
+ UINTN EventIndex = 0;
+ UINTN eventsCount = 2;
+ EFI_ABSOLUTE_POINTER_STATE aps = {0};
+ BOOLEAN showCursor = FALSE;
+ BOOLEAN beepOn = FALSE;
+ UINTN pwdAction = PwdActNone;
+ CHAR8 pwdNewChar = 0;
+
+ InitConsoleControl();
+ if (gBeepEnabled) {
+ InitSpeaker();
+ }
+
+ if (Bmp == NULL) {
+ if (gPasswordPictureFileName != NULL) {
+ res = FileLoad(NULL, (CHAR16*)gPasswordPictureFileName, &Bmp, &BmpSize);
+ if (EFI_ERROR(res)) {
+ ERR_PRINT(L"File load - %r\n", res);
+ return;
+ }
+ } else {
+ ERR_PRINT(L"Picture file name undefined\n");
+ return;
+ }
+ }
+ // Init draws
+ CreateDraws();
+
+ // Init screen
+ if (bltScrn != NULL) MEM_FREE(bltScrn);
+ ScreenSaveBlt(&bltScrn);
+ sWidth = bltScrn->Width;
+ sHeight = bltScrn->Height;
+ step = sWidth >> 4;
+
+ // Init picture password
+ picPwdIdx = 0;
+ res = DrawPwdPicture();
+ if (EFI_ERROR(res)) {
+ MEM_FREE(bltScrn);
+ ERR_PRINT(L"BmpToBlt - %r", res);
+ return;
+ }
+
+ // Touch zones
+ switch (pwdType) {
+ case AskPwdConfirm:
+ TZN_Login.Message = msgConfirmPwd;
+ break;
+ case AskPwdNew:
+ TZN_Login.Message = msgNewPwd;
+ break;
+ case AskPwdLogin:
+ default:
+ TZN_Login.Message = msgLogin;
+ }
+ DrawTouchZone(&TZN_Login);
+
+ if (pwdType == AskPwdLogin) {
+ TZN_Change.Message = msgChg;
+ DrawTouchZone(&TZN_Change);
+ }
+
+ if (gBeepControlEnabled) {
+ TZN_Speaker.Message = gBeepEnabled ? msgBeepOff : msgBeepOn;
+ DrawTouchZone(&TZN_Speaker);
+ }
+
+ TZN_Platform.Message = gPlatformLocked? msgPlatformLocked : msgPlatformUnLocked;
+ DrawTouchZone(&TZN_Platform);
+
+ TZN_Tpm.Message = gTPMLocked ? msgTpmLocked : msgTpmUnLocked;
+ DrawTouchZone(&TZN_Tpm);
+
+ TZN_Show.Message = gPasswordVisible ? msgHidePwd : msgShowPwd;
+ DrawTouchZone(&TZN_Show);
+ cellSelected = MEM_ALLOC(sizeof(UINTN) * 2 * (pwdMax + 1));
+
+ ScreenUpdateDirty(bltScrn);
+
+ // Prepare cursors
+ posPictX = (sWidth - bltPwd->Width) >> 1;
+ posPictY = (sHeight - bltPwd->Height) >> 1;
+ cellPrevX = MAX_INTN;
+ cellPrevY = MAX_INTN;
+ curX = sWidth / 2;
+ curY = posPictY / 2;
+ BltDrawBlt(bltScrn, bltPwd, posPictX, posPictY);
+
+ // Prepare events
+ InputEvents[0] = gST->ConIn->WaitForKey;
+ gBS->CreateEvent(EVT_TIMER, 0, (EFI_EVENT_NOTIFY)NULL, NULL, &InputEvents[1]);
+ gBS->CreateEvent(EVT_TIMER, 0, (EFI_EVENT_NOTIFY)NULL, NULL, &BeepOffEvent);
+ gBS->CreateEvent(EVT_TIMER, 0, (EFI_EVENT_NOTIFY)NULL, NULL, &UpdateEvent);
+ gBS->SetTimer(UpdateEvent, TimerRelative, 500000); // 20 times per second to update
+ gBS->SetTimer(BeepOffEvent, TimerRelative, gBeepDurationDefault * 10);
+ gBS->SetTimer(InputEvents[1], TimerRelative, 5000000);
+
+ if (gTouchPointer != NULL) {
+ eventsCount = 3;
+ InputEvents[2] = gTouchPointer->WaitForInput;
+ while (gBS->CheckEvent(InputEvents[2]) == EFI_SUCCESS) {
+ gTouchPointer->GetState(gTouchPointer, &aps);
+ }
+ }
+ while (gBS->CheckEvent(InputEvents[0]) == EFI_SUCCESS) {
+ gST->ConIn->ReadKeyStroke(gST->ConIn, &key);
+ }
+ do
+ {
+ curPrevX = curX;
+ curPrevY = curY;
+ res = gBS->WaitForEvent(eventsCount, InputEvents, &EventIndex);
+ // OUT_PRINT(L" \r%05d %05d", (UINT32)curX, (UINT32)curY, );
+ // recharge timeout event and stop beep
+ if (gBeepControlEnabled && gBeepEnabled && beepOn) {
+ if (gBS->CheckEvent(BeepOffEvent) == EFI_SUCCESS) {
+ beepOn = FALSE;
+ SpeakerBeep((UINT16)gBeepToneDefault, 0, 0, 0);
+ gBS->SetTimer(InputEvents[1], TimerRelative, 5000000);
+ }
+ }
+ else {
+ gBS->SetTimer(InputEvents[1], TimerRelative, 5000000);
+ }
+
+ // hide cursor
+ if (showCursor && EventIndex != 1) {
+ DrawCursor(bltScrn, curX, curY);
+ showCursor = FALSE;
+ }
+
+ // Blink cursor
+ if (EventIndex == 1) {
+ DrawCursor(bltScrn, curX, curY);
+ showCursor = !showCursor;
+ }
+
+ if (EventIndex == 0) {
+ gST->ConIn->ReadKeyStroke(gST->ConIn, &key);
+ // OUT_PRINT(L" %04x, %04x\r", key.ScanCode, key.UnicodeChar);
+
+ // Remove dirty chars 0.1s
+ FlushInputDelay(100000);
+ switch (key.ScanCode)
+ {
+ case SCAN_HOME:
+ curX -= gTouchSimulateStep;
+ curY -= gTouchSimulateStep;
+ break;
+ case SCAN_LEFT:
+ curX -= gTouchSimulateStep;
+ break;
+ case SCAN_END:
+ curX -= gTouchSimulateStep;
+ curY += gTouchSimulateStep;
+ break;
+ case SCAN_DOWN:
+ curY += gTouchSimulateStep;
+ break;
+ case SCAN_PAGE_DOWN:
+ curX += gTouchSimulateStep;
+ curY += gTouchSimulateStep;
+ break;
+ case SCAN_RIGHT:
+ curX += gTouchSimulateStep;
+ break;
+ case SCAN_PAGE_UP:
+ curX += gTouchSimulateStep;
+ curY -= gTouchSimulateStep;
+ break;
+ case SCAN_UP:
+ curY -= gTouchSimulateStep;
+ break;
+ case SCAN_F11:
+ if (gTouchSimulateStep > 1)
+ gTouchSimulateStep--;
+ break;
+ case SCAN_F12:
+ gTouchSimulateStep++;
+ break;
+ case SCAN_ESC:
+ pwdAction = PwdActCancel;
+ break;
+ case SCAN_F2:
+ if (pwdType == AskPwdLogin) {
+ pwdAction = PwdActChange;
+ }
+ break;
+ case SCAN_F4:
+ if (gBeepControlEnabled) {
+ pwdAction = PwdActBeep;
+ }
+ break;
+ case SCAN_F5:
+ pwdAction = PwdActShow;
+ break;
+ case SCAN_F7:
+ gPlatformLocked = gPlatformLocked ? 0 : 1;
+ pwdAction = PwdActUpdateZones;
+ break;
+ case SCAN_F8:
+ gTPMLocked = gTPMLocked ? 0 : 1;
+ pwdAction = PwdActUpdateZones;
+ break;
+ default:
+ ;
+ }
+
+ if (key.UnicodeChar != 0) {
+ if (key.UnicodeChar == 0x0d) {
+ pwdAction = PwdActLogin;
+ }
+ else {
+ pwdNewChar = (CHAR8)key.UnicodeChar;
+ pwdAction = PwdActNewChar;
+ cellSelected[picPwdIdx * 2] = MAX_INTN;
+ }
+ }
+
+ }
+
+ if (EventIndex == 2) {
+ res = gTouchPointer->GetState(gTouchPointer, &aps);
+ if (!EFI_ERROR(res)) {
+ curX = (UINTN)(aps.CurrentX * sWidth / (gTouchPointer->Mode->AbsoluteMaxX - gTouchPointer->Mode->AbsoluteMinX));
+ curY = (UINTN)(aps.CurrentY * sHeight / (gTouchPointer->Mode->AbsoluteMaxY - gTouchPointer->Mode->AbsoluteMinY));
+ }
+ }
+
+ if (curX > sWidth) curX = sWidth;
+ if (curY > sHeight) curY = sHeight;
+
+ // Cell check
+ if (CellGetSelected(bltPwd, curX - posPictX, curY - posPictY, &cellX, &cellY) && picPwdIdx < pwdMax) {
+ if (cellPrevX != cellX || cellPrevY != cellY) {
+ cellPrevX = cellX;
+ cellPrevY = cellY;
+ cellSelected[picPwdIdx * 2] = cellX;
+ cellSelected[picPwdIdx * 2 + 1] = cellY;
+ CellUpdate(bltPwd, cellX, cellY, TRUE);
+ BltDrawBlt(bltScrn, bltPwd, posPictX, posPictY);
+ pwdAction = PwdActNewChar;
+ pwdNewChar = gPasswordPictureChars[(cellX + bltPwd->Width / step * cellY) % gPasswordPictureCharsLen];
+ }
+ else if (EventIndex == 2 && aps.ActiveButtons == 0) {
+ cellPrevX = MAX_INTN;
+ cellPrevY = MAX_INTN;
+ curX = posPictX + cellX * step;
+ curY = posPictY + cellY * step;
+ while (gBS->CheckEvent(InputEvents[2]) == EFI_SUCCESS) {
+ gTouchPointer->GetState(gTouchPointer, &aps);
+ }
+ }
+ }
+
+ if (pwdAction == PwdActNone) {
+ if (IsTouchZone(&TZN_Login, curX, curY)) {
+ pwdAction = PwdActLogin;
+ }
+
+ if (pwdType == AskPwdLogin && IsTouchZone(&TZN_Change, curX, curY)) {
+ pwdAction = PwdActChange;
+ }
+
+ if (curPrevX != curX || curPrevY != curY) {
+ if (gSpeakerCount > 0 && IsTouchZone(&TZN_Speaker, curX, curY)) {
+ pwdAction = PwdActBeep;
+ }
+ if (IsTouchZone(&TZN_Show, curX, curY)) {
+ pwdAction = PwdActShow;
+ }
+ if (IsTouchZone(&TZN_Tpm, curX, curY)) {
+ gTPMLocked = gTPMLocked ? 0 : 1;
+ pwdAction = PwdActUpdateZones;
+ }
+ if (IsTouchZone(&TZN_Platform, curX, curY)) {
+ gPlatformLocked = gPlatformLocked ? 0 : 1;
+ pwdAction = PwdActUpdateZones;
+ }
+ }
+ }
+
+ if (PwdActNewChar == pwdAction) {
+ BOOLEAN bUpdPwdZone = FALSE;
+ if (pwdNewChar == '\b' && picPwdIdx > 0) {
+ picPwdIdx--;
+ pwd[picPwdIdx] = 0;
+ bUpdPwdZone = TRUE;
+ } else if ((picPwdIdx < pwdMax - 1) && (pwdNewChar >= 32)) {
+ pwd[picPwdIdx++] = pwdNewChar;
+ pwd[picPwdIdx] = 0;
+ bUpdPwdZone = TRUE;
+ }
+ if(bUpdPwdZone) {
+ *pwdLen = (int)picPwdIdx;
+ DrawPwdZone(pwd, (INT32)pwdMax);
+ if (gBeepControlEnabled && gBeepEnabled) {
+ SpeakerBeep((UINT16)gBeepToneDefault, gBeepNumberDefault, 0, 0);
+ gBS->SetTimer(BeepOffEvent, TimerRelative, gBeepDurationDefault * 10);
+ gBS->SetTimer(InputEvents[1], TimerRelative, gBeepDurationDefault * 10);
+ beepOn = TRUE;
+ }
+ }
+ }
+ else if (PwdActBeep == pwdAction && gBeepControlEnabled) {
+ if (gBeepEnabled && beepOn) {
+ beepOn = FALSE;
+ SpeakerBeep((UINT16)gBeepToneDefault, 0, 0, 0);
+ }
+ gBeepEnabled = gBeepEnabled ? 0 : 1;
+ TZN_Speaker.Message = gBeepEnabled ? msgBeepOff : msgBeepOn;
+ DrawTouchZone(&TZN_Speaker);
+ }
+ else if (PwdActShow == pwdAction) {
+ gPasswordVisible = gPasswordVisible ? 0 : 1;
+ DrawPwdZone(pwd, (INT32)pwdMax);
+ DrawPwdPicture();
+ BltDrawBlt(bltScrn, bltPwd, posPictX, posPictY);
+ TZN_Show.Message = gPasswordVisible ? msgHidePwd : msgShowPwd;
+ DrawTouchZone(&TZN_Show);
+ }
+ else if (PwdActLogin == pwdAction) {
+ *retCode = AskPwdRetLogin;
+ break;
+ }
+ else if (pwdType == AskPwdLogin && PwdActChange == pwdAction) {
+ *retCode = AskPwdRetChange;
+ break;
+ }
+ else if (PwdActCancel == pwdAction){
+ *retCode = AskPwdRetCancel;
+ break;
+ }
+ else if (PwdActUpdateZones == pwdAction) {
+ TZN_Platform.Message = gPlatformLocked ? msgPlatformLocked : msgPlatformUnLocked;
+ DrawTouchZone(&TZN_Platform);
+
+ TZN_Tpm.Message = gTPMLocked ? msgTpmLocked : msgTpmUnLocked;
+ DrawTouchZone(&TZN_Tpm);
+ }
+
+ if (curPrevX != curX || curPrevY != curY) {
+ DrawCursor(bltScrn, curX, curY);
+ showCursor = TRUE;
+ }
+ // Time to update screen?
+ if (gBS->CheckEvent(UpdateEvent) == EFI_SUCCESS) {
+ ScreenUpdateDirty(bltScrn);
+ gBS->SetTimer(UpdateEvent, TimerRelative, 500000); // 20 times per second to update
+ }
+
+ pwdAction = PwdActNone;
+ } while (TRUE);
+ gBS->CloseEvent(InputEvents[1]);
+ gBS->CloseEvent(UpdateEvent);
+ gBS->CloseEvent(BeepOffEvent);
+ ScreenFillRect(&gColorBlack, 0, 0, sWidth, sHeight);
+ gBS->Stall(500000);
+}