inputhandler.c

来自「EFI BIOS是Intel提出的下一代的BIOS标准。这里上传的Edk源代码是」· C语言 代码 · 共 1,569 行 · 第 1/4 页

C
1,569
字号
            PageData->Data->Length  = sizeof (EFI_IFR_DATA_ENTRY);
            PageData->Data->Data    = (VOID *) TempString2;
          }

          if ((FormCallback != NULL) && (FormCallback->Callback != NULL)) {
            Status = FormCallback->Callback (
                                    FormCallback,
                                    Tag->Key,
                                    PageData,
                                    &Packet
                                    );
          }
          //
          // If this was the confirmation round of callbacks
          // and an error comes back, display an error
          //
          if (Confirmation) {
            if (EFI_ERROR (Status)) {
              if (Packet->String == NULL) {
                ScreenSize = EFI_MAX (GetStringWidth (gConfirmError), GetStringWidth (gPressEnter)) / 2;
                CreatePopUp (ScreenSize, 4, &NullCharacter, gConfirmError, gPressEnter, &NullCharacter);
              } else {
                ScreenSize = EFI_MAX (GetStringWidth (Packet->String), GetStringWidth (gPressEnter)) / 2;
                CreatePopUp (ScreenSize, 4, &NullCharacter, Packet->String, gPressEnter, &NullCharacter);
                gBS->FreePool (Packet);
              }

              StringPtr[0] = CHAR_NULL;
              do {
                Status = WaitForKeyStroke (&Key);

                if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {
                  gBS->FreePool (TempString);
                  gBS->FreePool (TempString2);
                  return EFI_NOT_READY;
                }
              } while (1);
            } else {
              gBS->FreePool (TempString);
              gBS->FreePool (TempString2);
              return EFI_NOT_READY;
            }
          } else {
            //
            // User typed a string in and it wasn't valid somehow from the callback
            // For instance, callback may have said that some invalid characters were contained in the string
            //
            if (Status == EFI_NOT_READY) {
              goto Error;
            }

            if (PromptForPassword && EFI_ERROR (Status)) {
              gBS->FreePool (TempString);
              gBS->FreePool (TempString2);
              return EFI_DEVICE_ERROR;
            }
          }
        }

        if (Confirmation) {
          //
          // Compare tempstring and tempstring2, if the same, return with StringPtr success
          // Otherwise, kick and error box, and return an error
          //
          if (EfiStrCmp (TempString, TempString2) == 0) {
            gBS->FreePool (TempString);
            gBS->FreePool (TempString2);
            return EFI_SUCCESS;
          } else {
            ScreenSize = EFI_MAX (GetStringWidth (gConfirmError), GetStringWidth (gPressEnter)) / 2;
            CreatePopUp (ScreenSize, 4, &NullCharacter, gConfirmError, gPressEnter, &NullCharacter);
            StringPtr[0] = CHAR_NULL;
            do {
              Status = WaitForKeyStroke (&Key);
              if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {
                gBS->FreePool (TempString);
                gBS->FreePool (TempString2);
                return EFI_DEVICE_ERROR;
              }
            } while (1);
          }
        }

        if (PromptForPassword) {
          //
          // I was asked for a password, return it back in StringPtr
          //
          gBS->FreePool (TempString);
          gBS->FreePool (TempString2);
          return EFI_SUCCESS;
        } else {
          //
          // If the two passwords were not the same kick an error popup
          //
          Confirmation          = TRUE;
          ConfirmationComplete  = TRUE;
          break;
        }

      case CHAR_BACKSPACE:
        if (StringPtr[0] != CHAR_NULL) {
          if (!Confirmation) {
            for (Index = 0; StringPtr[Index] != CHAR_NULL; Index++) {
              TempString[Index] = StringPtr[Index];
            }
            //
            // Effectively truncate string by 1 character
            //
            TempString[Index - 1] = CHAR_NULL;
            EfiStrCpy (StringPtr, TempString);
          } else {
            for (Index = 0; StringPtr[Index] != CHAR_NULL; Index++) {
              TempString2[Index] = StringPtr[Index];
            }
            //
            // Effectively truncate string by 1 character
            //
            TempString2[Index - 1] = CHAR_NULL;
            EfiStrCpy (StringPtr, TempString2);
          }

          ConfirmationComplete = FALSE;
        } else {
          ConfirmationComplete = FALSE;
        }

      //
      // Must be a character we are interested in!
      //
      default:
        if ((StringPtr[0] == CHAR_NULL) && (Key.UnicodeChar != CHAR_BACKSPACE)) {
          if (!Confirmation) {
            StrnCpy (StringPtr, &Key.UnicodeChar, 1);
            StrnCpy (TempString, &Key.UnicodeChar, 1);
          } else {
            StrnCpy (StringPtr, &Key.UnicodeChar, 1);
            StrnCpy (TempString2, &Key.UnicodeChar, 1);
            ConfirmationComplete = FALSE;
          }
        } else if ((GetStringWidth (StringPtr) / 2 <= (UINTN) (MenuOption->ThisTag->Maximum - 1) / 2) &&
                 (Key.UnicodeChar != CHAR_BACKSPACE)
                ) {
          KeyPad[0] = Key.UnicodeChar;
          KeyPad[1] = CHAR_NULL;
          if (!Confirmation) {
            EfiStrCat (StringPtr, KeyPad);
            EfiStrCat (TempString, KeyPad);
          } else {
            EfiStrCat (StringPtr, KeyPad);
            EfiStrCat (TempString2, KeyPad);
          }
        }

        gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_BLACK, EFI_LIGHTGRAY));
        for (Index = 1; Index < ScreenSize; Index++) {
          PrintCharAt (Start + Index, Top + 3, L' ');
        }

        gST->ConOut->SetCursorPosition (
                      gST->ConOut,
                      (DimensionsWidth - GetStringWidth (StringPtr) / 2) / 2 + gScreenDimensions.LeftColumn,
                      Top + 3
                      );
        for (Index = 0; Index + 1 < GetStringWidth (StringPtr) / 2; Index++) {
          PrintChar (L'*');
        }

        gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));
        break;
      }
      //
      // end switch
      //
    } while (!ConfirmationComplete);

  } while (1);
  gBS->FreePool (TempString);
  gBS->FreePool (TempString2);
  return Status;
}

VOID
EncodePassword (
  IN  CHAR16                      *Password,
  IN  UINT8                       MaxSize
  )
{
  UINTN   Index;
  UINTN   Loop;
  CHAR16  *Buffer;
  CHAR16  *Key;

  Key     = L"MAR10648567";
  Buffer  = EfiLibAllocateZeroPool (MaxSize);

  ASSERT (Buffer);

  for (Index = 0; Key[Index] != 0; Index++) {
    for (Loop = 0; Loop < (UINT8) (MaxSize / 2); Loop++) {
      Buffer[Loop] = (CHAR16) (Password[Loop] ^ Key[Index]);
    }
  }

  EfiCopyMem (Password, Buffer, MaxSize);

  gBS->FreePool (Buffer);
  return ;
}

EFI_STATUS
GetNumericInput (
  IN  UI_MENU_OPTION              *MenuOption,
  IN  EFI_FILE_FORM_TAGS          *FileFormTagsHead,
  IN  BOOLEAN                     ManualInput,
  IN  EFI_TAG                     *Tag,
  IN  UINTN                       NumericType,
  OUT UINT16                      *Value
  )
/*++

Routine Description:

  This routine reads a numeric value from the user input.  

Arguments:

  MenuOption       -  Pointer to the current input menu.

  FileFormTagsHead -  Pointer to the root of formset.

  ManualInput      -  If the input is manual or not.

  Tag              -  Pointer to all the attributes and values associated with a tag.
                 
  Value            -  Pointer to the numeric value that is going to be read.

Returns: 

  EFI_SUCCESS       - If numerical input is read successfully
  EFI_DEVICE_ERROR  - If operation fails
  
--*/
{
  EFI_INPUT_KEY           Key;
  BOOLEAN                 SelectionComplete;
  UINTN                   Column;
  UINTN                   Row;
  CHAR16                  FormattedNumber[6];
  UINTN                   PreviousNumber[6];
  INTN                    Number;
  UINTN                   Count;
  UINT16                  BackupValue;
  STRING_REF              PopUp;
  CHAR16                  NullCharacter;
  CHAR16                  *StringPtr;
  EFI_FILE_FORM_TAGS      *FileFormTags;
  EFI_STATUS              Status;
  EFI_VARIABLE_DEFINITION *VariableDefinition;
  UINTN                   Loop;

  NullCharacter     = CHAR_NULL;
  StringPtr         = NULL;
  Column            = MenuOption->OptCol;
  Row               = MenuOption->Row;
  Number            = 0;
  PreviousNumber[0] = 0;
  Count             = 0;
  SelectionComplete = FALSE;
  BackupValue       = Tag->Value;
  FileFormTags      = FileFormTagsHead;

  if (ManualInput) {
    PrintAt (Column, Row, L"[     ]");
    Column++;
    if (Tag->Operand != EFI_IFR_TIME_OP) {
      *Value = BackupValue;
    }
  }
  //
  // First time we enter this handler, we need to check to see if
  // we were passed an increment or decrement directive
  //
  do {
    Key.UnicodeChar = CHAR_NULL;
    if (gDirection != 0) {
      Key.ScanCode  = gDirection;
      gDirection    = 0;
      goto TheKey2;
    }

    Status = WaitForKeyStroke (&Key);

TheKey2:
    switch (Key.UnicodeChar) {
    case '+':
    case '-':
      if ((Tag->Operand == EFI_IFR_DATE_OP) || (Tag->Operand == EFI_IFR_TIME_OP)) {
        Key.UnicodeChar = CHAR_NULL;
        if (Key.UnicodeChar == '+') {
          Key.ScanCode = SCAN_RIGHT;
        } else {
          Key.ScanCode = SCAN_LEFT;
        }

        goto TheKey2;
      }
      break;

    case CHAR_NULL:
      switch (Key.ScanCode) {
      case SCAN_LEFT:
      case SCAN_RIGHT:
        if ((Tag->Operand == EFI_IFR_DATE_OP) || (Tag->Operand == EFI_IFR_TIME_OP)) {
          //
          // By setting this value, we will return back to the caller.
          // We need to do this since an auto-refresh will destroy the adjustment
          // based on what the real-time-clock is showing.  So we always commit
          // upon changing the value.
          //
          gDirection = SCAN_DOWN;
        }

        if (!ManualInput) {
          Tag->Value = *Value;
          if (Key.ScanCode == SCAN_LEFT) {
            Number = *Value - Tag->Step;
            if (Number < Tag->Minimum) {
              Number = Tag->Minimum;
            }
          } else if (Key.ScanCode == SCAN_RIGHT) {
            Number = *Value + Tag->Step;
            if (Number > Tag->Maximum) {
              Number = Tag->Maximum;
            }
          }

          Tag->Value  = (UINT16) Number;
          *Value      = (UINT16) Number;
          ValueToString (FormattedNumber, FALSE, (UINT64) Number);
          Number = (UINT16) GetStringWidth (FormattedNumber);

          gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT | FIELD_BACKGROUND);
          if ((Tag->Operand == EFI_IFR_DATE_OP) || (Tag->Operand == EFI_IFR_TIME_OP)) {
            for (Loop = 0; Loop < (UINTN) ((Number >= 8) ? 4 : 2); Loop++) {
              PrintAt (MenuOption->OptCol + Loop, MenuOption->Row, L" ");
            }
          } else {
            for (Loop = 0; Loop < gOptionBlockWidth; Loop++) {
              PrintAt (MenuOption->OptCol + Loop, MenuOption->Row, L" ");
            }
          }

          gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT_HIGHLIGHT | FIELD_BACKGROUND_HIGHLIGHT);

          if ((MenuOption->Col + gPromptBlockWidth + 1) == MenuOption->OptCol) {
            PrintCharAt (MenuOption->OptCol, Row, LEFT_NUMERIC_DELIMITER);
            Column = MenuOption->OptCol + 1;
          }
          //
          // If Number looks like "3", convert it to "03/"
          //
          if (Number == 4 && (NumericType == DATE_NUMERIC)) {
            FormattedNumber[3]  = FormattedNumber[1];
            FormattedNumber[2]  = DATE_SEPARATOR;
            FormattedNumber[1]  = FormattedNumber[0];
            FormattedNumber[0]  = L'0';
            Number              = 8;
          }
          //
          // If Number looks like "13", convert it to "13/"
          //
          if (Number == 6 && (NumericType == DATE_NUMERIC)) {
            FormattedNumber[3]  = FormattedNumber[2];
            FormattedNumber[2]  = DATE_SEPARATOR;
            Number              = 8;
          }

          if (Number == 4 &&
              (NumericType == TIME_NUMERIC) &&
              (MenuOption->Col + gPromptBlockWidth + 8) != MenuOption->OptCol
              ) {
            FormattedNumber[3]  = FormattedNumber[1];
            FormattedNumber[2]  = TIME_SEPARATOR;
            FormattedNumber[1]  = FormattedNumber[0];
            FormattedNumber[0]  = L'0';
            Number              = 8;
          }

          if (Number == 4 &&
              (NumericType == TIME_NUMERIC) &&
              (MenuOption->Col + gPromptBlockWidth + 8) == MenuOption->OptCol
              ) {
            FormattedNumber[3]  = FormattedNumber[1];

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?