setup.c

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

C
1,957
字号
    );
  PrintAt (
    gScreenDimensions.RightColumn - (GetStringWidth (HomeEscapeString) / 2) - 2,
    gScreenDimensions.BottomRow - 3,
    L" %s",
    HomeEscapeString
    );
  gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));
  gBS->FreePool (HomeEscapeString);
  gBS->FreePool (HomePageString);

  return ;
}

CHAR16 *
GetToken (
  IN  STRING_REF                              Token,
  IN  EFI_HII_HANDLE                          HiiHandle
  )
/*++

Routine Description:
  
  Get the string based on the TokenID and HII Handle.

Arguments:

  Token       - The Token ID.
  HiiHandle   - Handle of Ifr to be fetched.
           
Returns:

  The output string.

--*/
{
  CHAR16      *Buffer;
  UINTN       BufferLength;
  EFI_STATUS  Status;

  //
  // Set default string size assumption at no more than 256 bytes
  //
  BufferLength  = 0x100;

  Buffer        = EfiLibAllocateZeroPool (BufferLength);
  ASSERT (Buffer != NULL);

  Status = Hii->GetString (Hii, HiiHandle, Token, TRUE, NULL, &BufferLength, Buffer);

  if (EFI_ERROR (Status)) {
    if (Status == EFI_BUFFER_TOO_SMALL) {
      //
      // Free the old pool
      //
      gBS->FreePool (Buffer);

      //
      // Allocate new pool with correct value
      //
      Buffer = EfiLibAllocatePool (BufferLength);
      ASSERT (Buffer != NULL);

      Status = Hii->GetString (Hii, HiiHandle, Token, TRUE, NULL, &BufferLength, Buffer);

      if (!EFI_ERROR (Status)) {
        return Buffer;
      }
    }

    ASSERT_EFI_ERROR (Status);
  }

  return Buffer;
}

EFI_STATUS
PopulateHomePage (
  IN UINTN                                    NumberOfIfrImages,
  IN EFI_FILE_FORM_TAGS                       *FileFormTagsHead
  )
{
  EFI_STATUS          Status;
  UINTN               Index;
  EFI_IFR_BINARY      *IfrBinary;
  CHAR16              *StringPtr;
  EFI_FILE_FORM_TAGS  *FileFormTags;
  EFI_FORM_TAGS       LocalTags;

  FileFormTags = FileFormTagsHead;

  UiInitMenu ();

  Status = EFI_SUCCESS;

  //
  // If there are no images
  //
  if (NumberOfIfrImages == 0) {
    Status = EFI_NO_MEDIA;
    return Status;
  }
  //
  // IfrBinary points to the beginning of the Binary data linked-list
  //
  IfrBinary = gBinaryDataHead;

  //
  // Print the entries which were in the default language.
  //
  for (Index = 0; Index < NumberOfIfrImages; Index++) {
    LocalTags = FileFormTags->FormTags;

    //
    // Populate the Menu
    //
    StringPtr = GetToken (IfrBinary->TitleToken, IfrBinary->Handle);

    //
    // If the default language doesn't exist, don't add a menu option yet
    //
    if (StringPtr[0] != CHAR_NULL) {
      //
      // We are NOT!! removing this StringPtr buffer via FreePool since it is being used in the menuoptions, we will do
      // it in UiFreeMenu.
      //
      UiAddMenuOption (StringPtr, IfrBinary->Handle, LocalTags.Tags, IfrBinary->FormBinary, Index);
    }
    //
    // Advance to the next HII handle
    //
    IfrBinary     = IfrBinary->Next;
    FileFormTags  = FileFormTags->NextFile;
  }

  return Status;
}

UI_MENU_OPTION *
DisplayHomePage (
  IN UINTN                                    NumberOfIfrImages,
  IN EFI_FILE_FORM_TAGS                       *FileFormTagsHead,
  IN UINT8                                    *CallbackData
  )
{
  EFI_STATUS      Status;
  UI_MENU_OPTION  *Selection;

  //
  // This prints the basic home page template which the user sees
  //
  InitPage ();

  Status = PopulateHomePage (NumberOfIfrImages, FileFormTagsHead);

  if (EFI_ERROR (Status)) {
    Selection = NULL;
    return Selection;
  }

  Selection = UiDisplayMenu (FALSE, FileFormTagsHead, (EFI_IFR_DATA_ARRAY *) CallbackData);

  return Selection;
}

EFI_STATUS
InitializeBinaryStructures (
  IN  EFI_HII_HANDLE                        *Handle,
  IN  BOOLEAN                               UseDatabase,
  IN  EFI_IFR_PACKET                        *Packet,
  IN  UINT8                                 *NvMapOverride,
  IN  UINTN                                 NumberOfIfrImages,
  OUT EFI_FILE_FORM_TAGS                    **FileFormTagsHead
  )
{
  UINTN                       HandleIndex;
  EFI_STATUS                  Status;
  EFI_IFR_BINARY              *BinaryData;
  EFI_FILE_FORM_TAGS          *FileFormTags;
  UINTN                       SizeOfNvStore;
  EFI_FORM_CALLBACK_PROTOCOL  *FormCallback;
  EFI_VARIABLE_DEFINITION     *VariableDefinition;
  EFI_VARIABLE_DEFINITION     *OverrideDefinition;
  VOID                        *NvMap;
  UINTN                       NvMapSize;
  EFI_HII_VARIABLE_PACK_LIST  *NvMapListHead;
  EFI_HII_VARIABLE_PACK_LIST  *NvMapListNode;

  //
  // Initialize some variables to avoid warnings
  //
  BinaryData        = NULL;
  *FileFormTagsHead = NULL;
  FileFormTags      = NULL;
  gBinaryDataHead   = NULL;
  Status            = EFI_SUCCESS;
  FormCallback      = NULL;
  NvMap             = NULL;
  NvMapSize         = 0;

  if (NumberOfIfrImages > 1) {
    NvMapOverride = NULL;
  }

  for (HandleIndex = 0; HandleIndex < NumberOfIfrImages; HandleIndex += 1) {
    //
    // If the buffers are uninitialized, allocate them, otherwise work on the ->Next members
    //
    if ((BinaryData == NULL) || (FileFormTags == NULL)) {
      //
      // Allocate memory for our Binary Data
      //
      BinaryData = EfiLibAllocateZeroPool (sizeof (EFI_IFR_BINARY));
      ASSERT (BinaryData);

      //
      // Preserve the Head of what will be a linked-list.
      //
      gBinaryDataHead       = BinaryData;
      gBinaryDataHead->Next = NULL;

      if (UseDatabase) {
        Status = GetIfrBinaryData (Hii, Handle[HandleIndex], NULL, BinaryData);
      } else {
        Status = GetIfrBinaryData (Hii, Handle[HandleIndex], Packet, BinaryData);
      }
      //
      // Allocate memory for our File Form Tags
      //
      FileFormTags = EfiLibAllocateZeroPool (sizeof (EFI_FILE_FORM_TAGS));
      ASSERT (FileFormTags);

      //
      // Preserve the Head of what will be a linked-list.
      //
      *FileFormTagsHead             = FileFormTags;
      (*FileFormTagsHead)->NextFile = NULL;

    } else {
      //
      // Allocate memory for our Binary Data linked-list
      // Each handle represents a Binary and we will store that data away.
      //
      BinaryData->Next = EfiLibAllocateZeroPool (sizeof (EFI_IFR_BINARY));
      ASSERT (BinaryData->Next);

      BinaryData        = BinaryData->Next;
      BinaryData->Next  = NULL;

      if (UseDatabase) {
        Status = GetIfrBinaryData (Hii, Handle[HandleIndex], NULL, BinaryData);
      } else {
        Status = GetIfrBinaryData (Hii, Handle[HandleIndex], Packet, BinaryData);
      }

      if (EFI_ERROR (Status)) {
        return EFI_DEVICE_ERROR;
      }
      //
      // Allocate memory for our FileFormTags linked-list
      // Each allocation reserves handle represents a Binary and we will store that data away.
      //
      FileFormTags->NextFile = EfiLibAllocateZeroPool (sizeof (EFI_FILE_FORM_TAGS));
      ASSERT (FileFormTags->NextFile);

      FileFormTags = FileFormTags->NextFile;
    }
    //
    // endif
    //
    // Tag Structure Initialization
    //
    Status              = InitializeTagStructures (BinaryData, FileFormTags);

    VariableDefinition  = FileFormTags->VariableDefinitions;

    //
    // Allocate memory for our NVRAM Maps for all of our variables
    //
    for (; VariableDefinition != NULL; VariableDefinition = VariableDefinition->Next) {
      //
      // Pad the fake variable size accordingly - this value should reflect the size of information that is not accounted by
      // the mainstream NVRAM variable such as DATE/TIME information that the browser needs to track but is saved to an RTC
      //
      VariableDefinition->VariableFakeSize = (UINT16) (VariableDefinition->VariableSize + VariableDefinition->VariableFakeSize);

      //
      // In the case where a file has no "real" NV data, we should pad the buffer accordingly
      //
      if (VariableDefinition->VariableSize == 0) {
        VariableDefinition->NvRamMap = EfiLibAllocateZeroPool (VariableDefinition->VariableFakeSize);
      } else {
        VariableDefinition->NvRamMap = EfiLibAllocateZeroPool (VariableDefinition->VariableSize);
      }

      VariableDefinition->FakeNvRamMap = EfiLibAllocateZeroPool (VariableDefinition->VariableFakeSize);
      ASSERT (VariableDefinition->NvRamMap);
      ASSERT (VariableDefinition->FakeNvRamMap);
    }

    Status = gBS->HandleProtocol (
                    (VOID *) (UINTN) FileFormTags->FormTags.Tags[0].CallbackHandle,
                    &gEfiFormCallbackProtocolGuid,
                    &FormCallback
                    );

    //
    // Since we might have multiple variables, if there is an NvMapOverride we need to use the EFI_VARIABLE_DEFINITION
    // information as the information that we pass back and forth.  NOTE that callbacks that are initiated will only have the
    // NVRAM data refreshed based on the op-code that initiated the callback.  In other words, we will pass to the caller a single
    // NVRAM map for a single variable based on the op-code that the user selected.
    //
    if (NvMapOverride != NULL) {
      VariableDefinition  = FileFormTags->VariableDefinitions;
      OverrideDefinition  = ((EFI_VARIABLE_DEFINITION *) NvMapOverride);

      //
      // Search through the variable definitions.  There should be sufficient passed in settings for the variable op-codes specified
      //
      for (; VariableDefinition != NULL; VariableDefinition = VariableDefinition->Next) {
        if ((!EfiCompareMem (VariableDefinition->VariableName, L"Setup", 10)) && (VariableDefinition->Next == NULL)) {
          if (VariableDefinition->VariableSize != 0) {
            EfiCopyMem (VariableDefinition->NvRamMap, NvMapOverride, VariableDefinition->VariableSize);
          } else {
            EfiCopyMem (VariableDefinition->NvRamMap, NvMapOverride, VariableDefinition->VariableFakeSize);
          }
          break;
        } else {
          VariableDefinition->NvRamMap = OverrideDefinition->NvRamMap;
        }
        //
        // There should NEVER be a ->Next for VariableDefinition and a NULL ->Next for the OverrideDefinition
        //
        ASSERT (OverrideDefinition->Next);
        OverrideDefinition = OverrideDefinition->Next;
      }
    } else {
      VariableDefinition = FileFormTags->VariableDefinitions;

      //
      // Search through the variable definitions.  There should be sufficient passed in settings for the variable op-codes specified
      //
      for (; VariableDefinition != NULL; VariableDefinition = VariableDefinition->Next) {
        SizeOfNvStore = VariableDefinition->VariableSize;

        //
        // Getting the NvStore and placing it into our Global Data
        //
        if ((FormCallback != NULL) && (FormCallback->NvRead != NULL)) {
          Status = FormCallback->NvRead (
                                  FormCallback,
                                  VariableDefinition->VariableName,
                                  &VariableDefinition->Guid,
                                  NULL,
                                  &SizeOfNvStore,
                                  (VOID *) VariableDefinition->NvRamMap
                                  );
        } else {
          Status = gRT->GetVariable (
                          VariableDefinition->VariableName,
                          &VariableDefinition->Guid,
                          NULL,
                          &SizeOfNvStore,
                          (VOID *) VariableDefinition->NvRamMap
                          );
        }

        if (EFI_ERROR (Status)) {
          //
          // If there is a variable that exists already and it is larger than what we calculated the
          // storage needs to be, we must assume the variable size from GetVariable is correct and not
          // allow the truncation of the variable.  It is very possible that the user who created the IFR
          // we are cracking is not referring to a variable that was in a previous map, however we cannot
          // allow it's truncation.
          //
          if (Status == EFI_BUFFER_TOO_SMALL) {
            //
            // If the buffer was too small, we should have the expanded size requirement in SizeOfNvStore now.
            //
            VariableDefinition->VariableSize = (UINT16) SizeOfNvStore;

            //
            // Free the buffer that was allocated that was too small
            //
            gBS->FreePool (VariableDefinition->NvRamMap);
            gBS->FreePool (VariableDefinition->FakeNvRamMap);

            VariableDefinition->NvRamMap = EfiLibAllocateZeroPool (SizeOfNvStore);
            Vari

⌨️ 快捷键说明

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