presentation.c

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

C
1,477
字号
  
  Selection         - The current selection of the form.
  CallbackData      - The pointer to host the data passed back by the callback function.
  FileFormTagsHead  - Prompt string token of the one-of box
  IdValue           - The current page number.
  FormHandle        - Output the  the handle of the form.
  TitleToken        - Output the  TitleToken of the new page.
  FormTags          - Output the  FormFags of the new page.
  
Returns: 
  VOID
  
--*/
{
  UINTN                       Index;
  UINTN                       BackupIndex;
  EFI_FILE_FORM_TAGS          *FileFormTags;
  EFI_FORM_TAGS               *LocalTags;
  EFI_FORM_CALLBACK_PROTOCOL  *FormCallback;
  EFI_STATUS                  Status;
  UINTN                       Length;
  UINT8                       *Buffer;
  EFI_PHYSICAL_ADDRESS        CallbackHandle;
  EFI_GUID                    TagGuid;
  UINT16                      TargetPage;
  EFI_HII_CALLBACK_PACKET     *Packet;
  UINTN                       ScreenSize;
  CHAR16                      NullCharacter;
  EFI_INPUT_KEY               Key;
  UINT16                      ConsistencyId;
  UINT16                      CurrentVariable;
  EFI_VARIABLE_DEFINITION     *VariableDefinition;

  VariableDefinition  = NULL;
  NullCharacter       = CHAR_NULL;

  CurrentVariable     = 0;
  FileFormTags        = FileFormTagsHead;
  Length              = 0;
  CallbackHandle      = 0;
  TargetPage          = (UINT16) IdValue;
  Packet              = NULL;
  ConsistencyId       = 0;

  //
  // Advance FileFormTags to the correct file's tag information.
  // For instance, if Selection->IfrNumber is 3, that means the 4th
  // file (0-based) in the FileFormTags linked-list contains the tag
  // information.
  //
  for (Index = 0; Index < Selection->IfrNumber; Index++) {
    FileFormTags = FileFormTags->NextFile;
  }

  LocalTags = &FileFormTags->FormTags;

  //
  // Advance Index to the FormOp with the correct ID value
  //
  for (; LocalTags->Next != NULL; LocalTags = LocalTags->Next) {
    if ((LocalTags->Tags[0].CallbackHandle != 0) && (CallbackHandle == 0)) {
      CallbackHandle = LocalTags->Tags[0].CallbackHandle;
      EfiCopyMem (&TagGuid, &LocalTags->Tags[0].GuidValue, sizeof (EFI_GUID));
    }

    for (Index = 0; LocalTags->Tags[Index].Operand != EFI_IFR_FORM_OP; Index++)
      ;
    if (LocalTags->Tags[Index].Id == IdValue) {
      break;
    }
  }
  //
  // If we are going to callback on a non-goto opcode, make sure we don't change pages
  //
  if (Selection->ThisTag->Operand != EFI_IFR_REF_OP) {
    TargetPage = Selection->FormId;
  }
  //
  // The first tag below should be the form op-code.  We need to store away the
  // current variable setting to ensure if we have to reload the page, that we
  // can correctly restore the values for the active variable
  //
  CurrentVariable = Selection->Tags[0].VariableNumber;

  //
  // Remember that dynamic pages in an environment where all pages are not
  // dynamic require us to call back to the user to give them an opportunity
  // to register fresh information in the HII database so that we can extract it.
  //
  Status = gBS->HandleProtocol (
                  (VOID *) (UINTN) CallbackHandle,
                  &gEfiFormCallbackProtocolGuid,
                  &FormCallback
                  );

  if (EFI_ERROR (Status)) {
    gBS->FreePool (LocalTags->Tags);
    return ;
  }

  ExtractRequestedNvMap (FileFormTags, CurrentVariable, &VariableDefinition);

  if (Selection->ThisTag->Flags & (EFI_IFR_FLAG_INTERACTIVE | EFI_IFR_FLAG_NV_ACCESS)) {
    ((EFI_IFR_DATA_ARRAY *) CallbackData)->NvRamMap = VariableDefinition->NvRamMap;
  } else {
    ((EFI_IFR_DATA_ARRAY *) CallbackData)->NvRamMap = NULL;
  }

  if ((FormCallback != NULL) && (FormCallback->Callback != NULL)) {
    Status = FormCallback->Callback (
                            FormCallback,
                            Selection->ThisTag->Key,
                            (EFI_IFR_DATA_ARRAY *) CallbackData,
                            &Packet
                            );
  }

  if (EFI_ERROR (Status)) {
    //
    // Restore Previous Value
    //
    EfiCopyMem (
      &VariableDefinition->NvRamMap[Selection->ThisTag->StorageStart],
      gPreviousValue,
      Selection->ThisTag->StorageWidth
      );

    if (Packet != NULL) {
      //
      // Upon error, we will likely receive a string to print out
      //
      ScreenSize = GetStringWidth (Packet->String) / 2;

      //
      // Display error popup
      //
      CreatePopUp (ScreenSize, 3, &NullCharacter, Packet->String, &NullCharacter);

      do {
        Status = WaitForKeyStroke (&Key);
      } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
    } else {
      UpdateStatusBar (INPUT_ERROR, (UINT8) 0, TRUE);
    }

  } else {
    if (Packet != NULL) {
      //
      // We need to on a non-error, look in the outbound Packet for information and update the NVRAM
      // location associated with the op-code specified there.  This is used on single op-code instances
      // and not for when a hyperlink sent us a whole page of data.
      //
      if (Packet->DataArray.EntryCount == 1) {
        switch (Packet->DataArray.Data->OpCode) {
        case EFI_IFR_STRING_OP:
        case EFI_IFR_NUMERIC_OP:
        case EFI_IFR_ORDERED_LIST_OP:
        case EFI_IFR_ONE_OF_OP:
        case EFI_IFR_CHECKBOX_OP:
          EfiCopyMem (
            &VariableDefinition->NvRamMap[Selection->ThisTag->StorageStart],
            &Packet->DataArray.Data[0].Data,
            Selection->ThisTag->StorageWidth
            );
          break;

        case EFI_IFR_NV_ACCESS_COMMAND:
          EfiCopyMem (
            &VariableDefinition->NvRamMap[((EFI_IFR_NV_DATA *) Packet)->QuestionId],
            ((EFI_IFR_NV_DATA *) Packet)->Data,
            ((EFI_IFR_NV_DATA *) Packet)->StorageWidth
            );
          break;

        }

        if (Packet->DataArray.Data->Flags & RESET_REQUIRED) {
          gResetRequired = TRUE;
        }

        if (Packet->DataArray.Data->Flags & EXIT_REQUIRED) {
          gExitRequired = TRUE;
        }

        if (Packet->DataArray.Data->Flags & SAVE_REQUIRED) {
          gSaveRequired = TRUE;
        }

        if (Packet->DataArray.Data->Flags & NV_CHANGED) {
          gNvUpdateRequired = TRUE;
        }

        if (Packet->DataArray.Data->Flags & NV_NOT_CHANGED) {
          gNvUpdateRequired = FALSE;
        }
      }
    }
  }

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

  for (BackupIndex = 0; LocalTags->Tags[BackupIndex].Operand != EFI_IFR_END_FORM_OP; BackupIndex++) {
    switch (LocalTags->Tags[BackupIndex].Operand) {
    case EFI_IFR_EQ_VAR_VAL_OP:
    case EFI_IFR_EQ_ID_VAL_OP:
    case EFI_IFR_EQ_ID_ID_OP:
    case EFI_IFR_AND_OP:
    case EFI_IFR_OR_OP:
    case EFI_IFR_NOT_OP:
    case EFI_IFR_TRUE_OP:
    case EFI_IFR_FALSE_OP:
    case EFI_IFR_GT_OP:
    case EFI_IFR_GE_OP:
    case EFI_IFR_EQ_ID_LIST_OP:
      //
      // If we encountered a ConsistencyId value, on this page they will be incremental
      // So register the first value we encounter.  We will pass this in when we re-create this page
      //
      if ((LocalTags->Tags[BackupIndex].ConsistencyId != 0) && (ConsistencyId == 0)) {
        ConsistencyId = (UINT16) (LocalTags->Tags[BackupIndex].ConsistencyId - 1);
      }
      break;
    }
  }
  //
  // Delete the buffer associated with previous dynamic page
  // We will re-allocate a buffer....
  //
  gBS->FreePool (LocalTags->Tags);

  Length  = 0xF000;
  Buffer  = EfiLibAllocateZeroPool (Length);
  ASSERT (Buffer != NULL);

  //
  // Get the form that was updated by the callback
  //
  Hii->GetForms (
        Hii,
        Selection->Handle,
        TargetPage,
        &Length,
        Buffer
        );

  //
  // Ok, we have the new page.....now we must purge the old page and re-allocate
  // the tag page with the new data
  //
  UpdateNewTagData (
    Buffer,
    ConsistencyId,
    CurrentVariable,
    LocalTags,
    FileFormTags
    );

  //
  // return the Form Id, Text, and the File's FormTags structure
  //
  *FormHandle                       = LocalTags->Tags[0].Id;
  *TitleToken                       = LocalTags->Tags[0].Text;
  *FormTags                         = *LocalTags;

  FormTags->Tags[0].CallbackHandle  = CallbackHandle;
  EfiCopyMem (&FormTags->Tags[0].GuidValue, &TagGuid, sizeof (EFI_GUID));

  return ;
}

UI_MENU_OPTION *
SetupBrowser (
  IN  UI_MENU_OPTION              *Selection,
  IN  BOOLEAN                     Callback,
  IN  EFI_FILE_FORM_TAGS          *FileFormTagsHead,
  IN  UINT8                       *CallbackData
  )
{
  UINT16        FormHandle;
  UINT16        TitleToken;
  EFI_FORM_TAGS FormTags;

  gEntryNumber  = -1;
  gLastOpr      = FALSE;
  //
  // Displays the Header and Footer borders
  //
  DisplayPageFrame ();

  //
  // Id of 0 yields the getting of the top form whatever the ID is.  Usually the first form in the IFR
  //
  ExtractFormHandle (Selection, FileFormTagsHead, 0, &FormHandle, &TitleToken, &FormTags);

  Selection = DisplayForm (Selection, FormHandle, TitleToken, FormTags, FileFormTagsHead, CallbackData);

  //
  // If selection is null use the former selection
  //
  if (Selection == NULL) {
    return Selection;
  }

  if (Callback) {
    return Selection;
  }

  while (Selection->Tags != NULL) {
    if (Selection->Previous) {
      ExtractFormHandle (Selection, FileFormTagsHead, Selection->FormId, &FormHandle, &TitleToken, &FormTags);
    } else {
      //
      // True if a hyperlink/jump is selected
      //
      if (Selection->ThisTag->Operand == EFI_IFR_REF_OP && Selection->ThisTag->Id != 0x0000) {
        if (Selection->ThisTag->Flags & EFI_IFR_FLAG_INTERACTIVE) {
          ExtractDynamicFormHandle (
            Selection,
            CallbackData,
            FileFormTagsHead,
            Selection->ThisTag->Id,
            &FormHandle,
            &TitleToken,
            &FormTags
            );
          goto DisplayPage;
        } else {
          ExtractFormHandle (Selection, FileFormTagsHead, Selection->ThisTag->Id, &FormHandle, &TitleToken, &FormTags);
          goto DisplayPage;
        }
      }

      if ((Selection->ThisTag->Flags & EFI_IFR_FLAG_INTERACTIVE) &&
          (Selection->ThisTag->Operand != EFI_IFR_PASSWORD_OP)
          ) {
        ExtractDynamicFormHandle (
          Selection,
          CallbackData,
          FileFormTagsHead,
          Selection->FormId,
          &FormHandle,
          &TitleToken,
          &FormTags
          );
      } else {
        ExtractFormHandle (Selection, FileFormTagsHead, Selection->FormId, &FormHandle, &TitleToken, &FormTags);
      }
    }

DisplayPage:
    //
    // Displays the Header and Footer borders
    //
    DisplayPageFrame ();

    Selection = DisplayForm (Selection, FormHandle, TitleToken, FormTags, FileFormTagsHead, CallbackData);

    if (Selection == NULL) {
      break;
    }
  };

  return Selection;
}

⌨️ 快捷键说明

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