ui.c

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

C
2,158
字号
  IN EFI_FILE_FORM_TAGS           *FileFormTagsHead,
  IN CHAR16                       *FormattedString,
  IN CHAR16                       *OptionString
  )
/*++

Routine Description:
  
  Used to remove the allocated data instances

Arguments:
             
Returns:

--*/
{
  EFI_FILE_FORM_TAGS      *FileForm;
  EFI_FILE_FORM_TAGS      *PreviousFileForm;
  EFI_FORM_TAGS           *FormTags;
  EFI_FORM_TAGS           *PreviousFormTags;
  EFI_IFR_BINARY          *IfrBinary;
  EFI_IFR_BINARY          *PreviousIfrBinary;
  EFI_INCONSISTENCY_DATA  *Inconsistent;
  EFI_VARIABLE_DEFINITION *VariableDefinition;
  EFI_VARIABLE_DEFINITION *PreviousVariableDefinition;
  VOID                    *Buffer;
  UINTN                   Index;

  FileForm = FileFormTagsHead;

  if (FormattedString != NULL) {
    gBS->FreePool (FormattedString);
  }

  if (OptionString != NULL) {
    gBS->FreePool (OptionString);
  }

  for (; FileForm != NULL;) {
    PreviousFileForm = NULL;

    //
    // Advance FileForm to the last entry
    //
    for (; FileForm->NextFile != NULL; FileForm = FileForm->NextFile) {
      PreviousFileForm = FileForm;
    }

    FormTags = &FileForm->FormTags;

    for (; FormTags != NULL;) {
      FormTags          = &FileForm->FormTags;
      PreviousFormTags  = NULL;

      //
      // Advance FormTags to the last entry
      //
      for (; FormTags->Next != NULL; FormTags = FormTags->Next) {
        PreviousFormTags = FormTags;
      }
      //
      // Walk through each of the tags and free the IntList allocation
      //
      for (Index = 0; FormTags->Tags[Index].Operand != EFI_IFR_END_FORM_OP; Index++) {
        //
        // It is more than likely that the very last page will contain an end formset
        //
        if (FormTags->Tags[Index].Operand == EFI_IFR_END_FORM_SET_OP) {
          break;
        }

        if (FormTags->Tags[Index].IntList != NULL) {
          gBS->FreePool (FormTags->Tags[Index].IntList);
        }
      }

      if (PreviousFormTags != NULL) {
        gBS->FreePool (FormTags->Tags);
        FormTags = PreviousFormTags;
        gBS->FreePool (FormTags->Next);
        FormTags->Next = NULL;
      } else {
        gBS->FreePool (FormTags->Tags);
        FormTags = NULL;
      }
    }
    //
    // Last FileForm entry's Inconsistent database
    //
    Inconsistent = FileForm->InconsistentTags;

    //
    // Advance Inconsistent to the last entry
    //
    for (; Inconsistent->Next != NULL; Inconsistent = Inconsistent->Next)
      ;

    for (; Inconsistent != NULL;) {
      //
      // Preserve the Previous pointer
      //
      Buffer = (VOID *) Inconsistent->Previous;

      //
      // Free the current entry
      //
      gBS->FreePool (Inconsistent);

      //
      // Restore the Previous pointer
      //
      Inconsistent = (EFI_INCONSISTENCY_DATA *) Buffer;
    }

    VariableDefinition = FileForm->VariableDefinitions;

    for (; VariableDefinition != NULL;) {
      VariableDefinition          = FileForm->VariableDefinitions;
      PreviousVariableDefinition  = NULL;

      //
      // Advance VariableDefinitions to the last entry
      //
      for (; VariableDefinition->Next != NULL; VariableDefinition = VariableDefinition->Next) {
        PreviousVariableDefinition = VariableDefinition;
      }

      gBS->FreePool (VariableDefinition->VariableName);
      gBS->FreePool (VariableDefinition->NvRamMap);
      gBS->FreePool (VariableDefinition->FakeNvRamMap);

      if (PreviousVariableDefinition != NULL) {
        VariableDefinition = PreviousVariableDefinition;
        gBS->FreePool (VariableDefinition->Next);
        VariableDefinition->Next = NULL;
      } else {
        gBS->FreePool (VariableDefinition);
        VariableDefinition = NULL;
      }
    }

    if (PreviousFileForm != NULL) {
      FileForm = PreviousFileForm;
      gBS->FreePool (FileForm->NextFile);
      FileForm->NextFile = NULL;
    } else {
      gBS->FreePool (FileForm);
      FileForm = NULL;
    }
  }

  IfrBinary = gBinaryDataHead;

  for (; IfrBinary != NULL;) {
    IfrBinary         = gBinaryDataHead;
    PreviousIfrBinary = NULL;

    //
    // Advance IfrBinary to the last entry
    //
    for (; IfrBinary->Next != NULL; IfrBinary = IfrBinary->Next) {
      PreviousIfrBinary = IfrBinary;
    }

    gBS->FreePool (IfrBinary->IfrPackage);

    if (PreviousIfrBinary != NULL) {
      IfrBinary = PreviousIfrBinary;
      gBS->FreePool (IfrBinary->Next);
      IfrBinary->Next = NULL;
    } else {
      gBS->FreePool (IfrBinary);
      IfrBinary = NULL;
    }
  }

  gBS->FreePool (gPreviousValue);
  gPreviousValue = NULL;

  //
  // Free Browser Strings
  //
  gBS->FreePool (gPressEnter);
  gBS->FreePool (gConfirmError);
  gBS->FreePool (gConfirmPassword);
  gBS->FreePool (gPromptForNewPassword);
  gBS->FreePool (gPromptForPassword);
  gBS->FreePool (gToggleCheckBox);
  gBS->FreePool (gNumericInput);
  gBS->FreePool (gMakeSelection);
  gBS->FreePool (gMoveHighlight);
  gBS->FreePool (gEscapeString);
  gBS->FreePool (gEnterCommitString);
  gBS->FreePool (gEnterString);
  gBS->FreePool (gFunctionOneString);
  gBS->FreePool (gFunctionTwoString);
  gBS->FreePool (gFunctionNineString);
  gBS->FreePool (gFunctionTenString);
  return ;
}

BOOLEAN
SelectionsAreValid (
  IN  UI_MENU_OPTION               *MenuOption,
  IN  EFI_FILE_FORM_TAGS           *FileFormTagsHead
  )
/*++

Routine Description:
  Initiate late consistency checks against the current page.  

Arguments:
  None
           
Returns:

--*/
{
  EFI_LIST_ENTRY          *Link;
  EFI_TAG                 *Tag;
  EFI_FILE_FORM_TAGS      *FileFormTags;
  CHAR16                  *StringPtr;
  CHAR16                  NullCharacter;
  EFI_STATUS              Status;
  UINTN                   Index;
  UINT16                  *NvRamMap;
  STRING_REF              PopUp;
  EFI_INPUT_KEY           Key;
  EFI_VARIABLE_DEFINITION *VariableDefinition;

  StringPtr     = L"\0";
  NullCharacter = CHAR_NULL;

  FileFormTags  = FileFormTagsHead;

  for (Index = 0; Index < MenuOption->IfrNumber; Index++) {
    FileFormTags = FileFormTags->NextFile;
  }

  for (Link = Menu.ForwardLink; Link != &Menu; Link = Link->ForwardLink) {
    MenuOption  = CR (Link, UI_MENU_OPTION, Link, UI_MENU_OPTION_SIGNATURE);

    Tag         = MenuOption->ThisTag;

    ExtractRequestedNvMap (FileFormTags, Tag->VariableNumber, &VariableDefinition);
    NvRamMap = (UINT16 *) &VariableDefinition->NvRamMap[Tag->StorageStart];

    //
    // If the op-code has a late check, ensure consistency checks are now applied
    //
    if (Tag->Flags & EFI_IFR_FLAG_LATE_CHECK) {
      if (ValueIsNotValid (TRUE, 0, Tag, FileFormTags, &PopUp)) {
        if (PopUp != 0x0000) {
          StringPtr = GetToken (PopUp, MenuOption->Handle);

          CreatePopUp (GetStringWidth (StringPtr) / 2, 3, &NullCharacter, StringPtr, &NullCharacter);

          do {
            Status = WaitForKeyStroke (&Key);

            switch (Key.UnicodeChar) {

            case CHAR_CARRIAGE_RETURN:
              //
              // Since the value can be one byte long or two bytes long, do a CopyMem based on StorageWidth
              //
              EfiCopyMem (NvRamMap, &Tag->OldValue, Tag->StorageWidth);
              gBS->FreePool (StringPtr);
              break;

            default:
              break;
            }
          } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
        }

        return FALSE;
      }
    }
  }

  return TRUE;
}

UINT16
GetWidth (
  IN EFI_TAG                        *Tag,
  IN EFI_HII_HANDLE                 Handle
  )
/*++

Routine Description:
  Get the supported width for a particular op-code

Arguments:
  Tag - The Tag structure passed in.
  Handle - The handle in the HII database being used
  
Returns:
  Returns the number of CHAR16 characters that is support.


--*/
{
  CHAR16  *String;
  UINTN   Size;

  Size = 0x00;

  //
  // See if the second text parameter is really NULL
  //
  if ((Tag->Operand == EFI_IFR_TEXT_OP) && (Tag->TextTwo != 0)) {
    String  = GetToken (Tag->TextTwo, Handle);
    Size    = EfiStrLen (String);
    gBS->FreePool (String);
  }

  if ((Tag->Operand == EFI_IFR_SUBTITLE_OP) ||
      (Tag->Operand == EFI_IFR_REF_OP) ||
      (Tag->Operand == EFI_IFR_PASSWORD_OP) ||
      (Tag->Operand == EFI_IFR_STRING_OP) ||
      (Tag->Operand == EFI_IFR_INVENTORY_OP) ||
      //
      // Allow a wide display if text op-code and no secondary text op-code
      //
      ((Tag->Operand == EFI_IFR_TEXT_OP) && (Size == 0x0000))
      ) {
    return (UINT16) (gPromptBlockWidth + gOptionBlockWidth);
  } else {
    return (UINT16) gPromptBlockWidth;
  }
}

UINT16
GetLineByWidth (
  IN      CHAR16                      *InputString,
  IN      UINT16                      LineWidth,
  IN OUT  UINTN                       *Index,
  OUT     CHAR16                      **OutputString
  )
/*++

Routine Description:
  Will copy LineWidth amount of a string in the OutputString buffer and return the
  number of CHAR16 characters that were copied into the OutputString buffer.

Arguments:
  InputString - String description for this option.
  LineWidth - Width of the desired string to extract in CHAR16 characters
  Index - Where in InputString to start the copy process
  OutputString - Buffer to copy the string into
           
Returns:
  Returns the number of CHAR16 characters that were copied into the OutputString buffer.


--*/
{
  static BOOLEAN  Finished;
  UINT16          Count;
  UINT16          Count2;

  if (Finished) {
    Finished = FALSE;
    return (UINT16) 0;
  }

  Count         = LineWidth;
  Count2        = 0;

  *OutputString = EfiLibAllocateZeroPool (((UINTN) (LineWidth + 1) * 2));

  //
  // Ensure we have got a valid buffer
  //
  if (*OutputString != NULL) {
  
    //
    //NARROW_CHAR can not be printed in screen, so if a line only contain  the two CHARs: 'NARROW_CHAR + CHAR_CARRIAGE_RETURN' , it is a empty line  in Screen.
    //To avoid displaying this  empty line in screen,  just skip  the two CHARs here.
    //
   if ((InputString[*Index] == NARROW_CHAR) && (InputString[*Index + 1] == CHAR_CARRIAGE_RETURN)) {
     *Index = *Index + 2;
   } 

    //
    // Fast-forward the string and see if there is a carriage-return in the string
    //
    for (; (InputString[*Index + Count2] != CHAR_CARRIAGE_RETURN) && (Count2 != LineWidth); Count2++)
      ;

    //
    // Copy the desired LineWidth of data to the output buffer.
    // Also make sure that we don't copy more than the string.
    // Also make sure that if there are linefeeds, we account for them.
    //
    if ((EfiStrSize (&InputString[*Index]) <= ((UINTN) (LineWidth + 1) * 2)) &&
        (EfiStrSize (&InputString[*Index]) <= ((UINTN) (Count2 + 1) * 2))
        ) {
      //
      // Convert to CHAR16 value and show that we are done with this operation
      //
      LineWidth = (UINT16) ((EfiStrSize (&InputString[*Index]) - 2) / 2);
      if (LineWidth != 0) {
        Finished = TRUE;
      }
    } else {
      if (Count2 == LineWidth) {
        //
        // Rewind the string from the maximum size until we see a space to break the line
        //
        for (; (InputString[*Index + LineWidth] != CHAR_SPACE) && (LineWidth != 0); LineWidth--)
          ;
        if (LineWidth == 0) {
          LineWidth = Count;
        }
      } else {
        LineWidth = Count2;
      }
    }

    EfiCopyMem (*OutputString, &InputString[*Index], LineWidth * 2);

    //
    // If currently pointing to a space, increment the index to the first non-space character
    //
    for (;
         (InputString[*Index + LineWidth] == CHAR_SPACE) || (InputString[*Index + LineWidth] == CHAR_CARRIAGE_RETURN);
         (*Index)++
        )
      ;

⌨️ 快捷键说明

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