package.c

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

C
679
字号
    //
    // Advance to the Form Set Op-code
    //
    for (Count = 0; ((EFI_IFR_OP_HEADER *) &Location[Count])->OpCode != EFI_IFR_FORM_SET_OP;) {
      Count = Count + ((EFI_IFR_OP_HEADER *) &Location[Count])->Length;
    }
    //
    // Copy to local variable
    //
    EfiCopyMem (&Guid, &((EFI_IFR_FORM_SET *) &Location[Count])->Guid, sizeof (EFI_GUID));

    //
    // Check to see if IfrPack->Guid != GuidId
    //
    if (!EfiCompareGuid (&Guid, Packages->GuidId)) {
      //
      // If a string package is present, the GUIDs should have agreed.  Return an error
      //
      if (StringPack != NULL) {
        return EFI_INVALID_PARAMETER;
      }
    }
  }
  //
  // If someone is passing in a string only, create a dummy IfrPack with a Guid
  // to enable future searching of this data.
  //
  if ((IfrPack == NULL) && (StringPack != NULL)) {
    EfiZeroMem (&FormSetStub, sizeof (FormSetStub));

    FormSetStub.Header.Type           = EFI_HII_IFR;
    FormSetStub.Header.Length         = sizeof (EFI_FORM_SET_STUB);

    FormSetStub.FormSet.Header.OpCode = EFI_IFR_FORM_SET_OP;
    FormSetStub.FormSet.Header.Length = (UINT8) sizeof (EFI_IFR_FORM_SET);
    //
    // Dummy string
    //
    FormSetStub.FormSet.FormSetTitle  = 0x02;
    EfiCopyMem (&FormSetStub.FormSet.Guid, Packages->GuidId, sizeof (EFI_GUID));

    FormSetStub.EndFormSet.Header.OpCode  = EFI_IFR_END_FORM_SET_OP;
    FormSetStub.EndFormSet.Header.Length  = (UINT8) sizeof (EFI_IFR_END_FORM_SET);
    IfrPack = (EFI_HII_IFR_PACK *) &FormSetStub;
  }

  if (IfrPack != NULL) {
    //
    // Sending me an IFR Package. Get its size.
    //
    Status = GetPackSize ((VOID *) IfrPack, &IfrSize, NULL);
    ASSERT (!EFI_ERROR (Status));
  }
  //
  // Prepare the internal package instace buffer to store package data.
  //
  InstanceSize = IfrSize + TotalStringSize;

  if (InstanceSize != 0) {
    PackageInstance = EfiLibAllocateZeroPool (InstanceSize + sizeof (EFI_HII_PACKAGE_INSTANCE));

    ASSERT (PackageInstance);

    //
    // If there is no DatabaseHead allocated - allocate one
    //
    if (HiiData->DatabaseHead == NULL) {
      HiiData->DatabaseHead = EfiLibAllocateZeroPool (sizeof (EFI_HII_HANDLE_DATABASE));
      ASSERT (HiiData->DatabaseHead);
    }
    //
    // If the head is being used (Handle is non-zero), allocate next Database and
    // add it to the linked-list
    //
    if (HiiData->DatabaseHead->Handle != 0) {
      HandleDatabase = EfiLibAllocateZeroPool (sizeof (EFI_HII_HANDLE_DATABASE));

      ASSERT (HandleDatabase);

      for (; Database->NextHandleDatabase != NULL; Database = Database->NextHandleDatabase)
        ;

      //
      // We are sitting on the Database entry which contains the null Next pointer.  Fix it.
      //
      Database->NextHandleDatabase = HandleDatabase;

    }

    Database = HiiData->DatabaseHead;

    //
    // Initialize this instance data
    //
    for (*Handle = 1; Database->NextHandleDatabase != NULL; Database = Database->NextHandleDatabase) {
      //
      // Since the first Database instance will have a passed back handle of 1, we will continue
      // down the linked list of entries until we encounter the end of the linked list.  Each time
      // we go down one level deeper, increment the handle value that will be passed back.
      //
      if (Database->Handle >= *Handle) {
        *Handle = Database->Handle + 1;
      }
    }

    PackageInstance->Handle     = *Handle;
    PackageInstance->IfrSize    = IfrSize;
    PackageInstance->StringSize = TotalStringSize;
    if (Packages->GuidId != NULL) {
      EfiCopyMem (&PackageInstance->Guid, Packages->GuidId, sizeof (EFI_GUID));
    }

    Database->Buffer              = PackageInstance;
    Database->Handle              = PackageInstance->Handle;
    Database->NumberOfTokens      = TotalTokenNumber;
    Database->NextHandleDatabase  = NULL;
  }
  //
  // Copy the Ifr package data into package instance.
  //
  if (IfrSize > 0) {
    EfiCopyMem (&PackageInstance->IfrData, IfrPack, IfrSize);
  }
  //
  // Main loop to store package data into HII database.
  //
  StringSize      = 0;
  TotalStringSize = 0;

  for (Index = 0; Index < Packages->NumberOfPackages; Index++) {

    PackageHeader = *(EFI_HII_PACK_HEADER **) (((UINT8 *) Packages) + sizeof (EFI_HII_PACKAGES) + Index * sizeof (VOID *));

    switch (PackageHeader->Type) {
    case EFI_HII_STRING:
      StringPack = (EFI_HII_STRING_PACK *) PackageHeader;
      //
      // The size which GetPackSize() returns include the null terminator. So if multiple
      // string packages are passed in, merge all these packages, and only pad one null terminator.
      //
      if (TotalStringSize > 0) {
        TotalStringSize -= sizeof (EFI_HII_STRING_PACK);
      }

      GetPackSize ((VOID *) StringPack, &StringSize, &NumberOfTokens);
      EfiCopyMem ((CHAR8 *) (&PackageInstance->IfrData) + IfrSize + TotalStringSize, StringPack, StringSize);

      TotalStringSize += StringSize;
      break;

    case EFI_HII_HANDLES:
      Handlepack                  = (EFI_HII_HANDLE_PACK *) PackageHeader;
      PackageInstance->HandlePack = *Handlepack;
      break;

    case EFI_HII_FONT:
      FontPack = (EFI_HII_FONT_PACK *) PackageHeader;
      //
      // Add whatever narrow glyphs were passed to us if undefined
      //
      EfiCopyMem (&NumNarrowGlyphs, &FontPack->NumberOfNarrowGlyphs, sizeof (UINT16));
      for (Count = 0; Count <= NumNarrowGlyphs; Count++) {
        Local       = (UINT8 *) (&FontPack->NumberOfWideGlyphs + sizeof (UINT8)) + (sizeof (EFI_NARROW_GLYPH)) * Count;
        NarrowGlyph = (EFI_NARROW_GLYPH *) Local;
        EfiCopyMem (&Member, &NarrowGlyph->UnicodeWeight, sizeof (UINT16));
        //
        // If the glyph is already defined, do not overwrite it.  It is what it is.
        //
        EfiCopyMem (&Unicode, &GlobalData->NarrowGlyphs[Member].UnicodeWeight, sizeof (UINT16));
        if (Unicode == 0) {
          EfiCopyMem (&GlobalData->NarrowGlyphs[Member], Local, sizeof (EFI_NARROW_GLYPH));
        }
      }
      //
      // Add whatever wide glyphs were passed to us if undefined
      //
      EfiCopyMem (&NumWideGlyphs, &FontPack->NumberOfWideGlyphs, sizeof (UINT16));
      for (Count = 0; Count <= NumWideGlyphs; Count++) {
        Local = (UINT8 *) (&FontPack->NumberOfWideGlyphs + sizeof (UINT8)) +
          (sizeof (EFI_NARROW_GLYPH)) *
          NumNarrowGlyphs;
        WideGlyph = (EFI_WIDE_GLYPH *) Local;
        EfiCopyMem (
          &Member,
          (UINTN *) (Local + sizeof (EFI_WIDE_GLYPH) * Count),
          sizeof (UINT16)
          );
        //
        // If the glyph is already defined, do not overwrite it.  It is what it is.
        //
        EfiCopyMem (&Unicode, &GlobalData->WideGlyphs[Member].UnicodeWeight, sizeof (UINT16));
        if (Unicode == 0) {
          Local = (UINT8*)(&FontPack->NumberOfWideGlyphs + sizeof(UINT8)) + (sizeof(EFI_NARROW_GLYPH)) * NumNarrowGlyphs;
          WideGlyph = (EFI_WIDE_GLYPH *) Local;
          EfiCopyMem (
            &GlobalData->WideGlyphs[Member],
            (UINTN *) (Local + sizeof (EFI_WIDE_GLYPH) * Count),
            sizeof (EFI_WIDE_GLYPH)
            );
        }
      }
      break;

    case EFI_HII_KEYBOARD:
      KeyboardPack = (EFI_HII_KEYBOARD_PACK *) PackageHeader;
      //
      // Sending me a Keyboard Package
      //
      if (KeyboardPack->DescriptorCount > 105) {
        return EFI_INVALID_PARAMETER;
      }
      //
      // If someone updates the Descriptors with a count of 0, blow aware the overrides.
      //
      if (KeyboardPack->DescriptorCount == 0) {
        EfiZeroMem (GlobalData->OverrideKeyboardLayout, sizeof (EFI_KEY_DESCRIPTOR) * 106);
      }

      if (KeyboardPack->DescriptorCount < 106 && KeyboardPack->DescriptorCount > 0) {
        //
        // If SystemKeyboard was updated already, then steer changes to the override database
        //
        if (GlobalData->SystemKeyboardUpdate) {
          EfiZeroMem (GlobalData->OverrideKeyboardLayout, sizeof (EFI_KEY_DESCRIPTOR) * 106);
          for (Count = 0; Count < KeyboardPack->DescriptorCount; Count++) {
            EfiCopyMem (&Member, &KeyboardPack->Descriptor[Count].Key, sizeof (UINT16));
            EfiCopyMem (
              &GlobalData->OverrideKeyboardLayout[Member],
              &KeyboardPack->Descriptor[Count],
              sizeof (EFI_KEY_DESCRIPTOR)
              );
          }
        } else {
          //
          // SystemKeyboard was never updated, so this is likely the keyboard driver setting the System database.
          //
          EfiZeroMem (GlobalData->SystemKeyboardLayout, sizeof (EFI_KEY_DESCRIPTOR) * 106);
          for (Count = 0; Count < KeyboardPack->DescriptorCount; Count++) {
            EfiCopyMem (&Member, &KeyboardPack->Descriptor->Key, sizeof (UINT16));
            EfiCopyMem (
              &GlobalData->SystemKeyboardLayout[Member],
              &KeyboardPack->Descriptor[Count],
              sizeof (EFI_KEY_DESCRIPTOR)
              );
          }
          //
          // Just updated the system keyboard database, reflect that in the global flag.
          //
          GlobalData->SystemKeyboardUpdate = TRUE;
        }
      }
      break;

    default:
      break;
    }
  }

  return EFI_SUCCESS;
}

EFI_STATUS
EFIAPI
HiiRemovePack (
  IN EFI_HII_PROTOCOL    *This,
  IN EFI_HII_HANDLE      Handle
  )
/*++

Routine Description:
  Removes the various packs from a Handle
  
Arguments:

Returns: 

--*/
{
  EFI_HII_PACKAGE_INSTANCE  *PackageInstance;
  EFI_HII_DATA              *HiiData;
  EFI_HII_HANDLE_DATABASE   *HandleDatabase;
  EFI_HII_HANDLE_DATABASE   *PreviousHandleDatabase;
  UINTN                     Count;

  if (This == NULL || Handle == 0) {
    return EFI_INVALID_PARAMETER;
  }

  HiiData         = EFI_HII_DATA_FROM_THIS (This);

  HandleDatabase  = HiiData->DatabaseHead;
  PackageInstance = NULL;

  //
  // Initialize the Previous with the Head of the Database
  //
  PreviousHandleDatabase = HandleDatabase;

  for (Count = 0; HandleDatabase != NULL; HandleDatabase = HandleDatabase->NextHandleDatabase) {
    //
    // Match the numeric value with the database entry - if matched,
    // free the package instance and apply fix-up to database linked list
    //
    if (Handle == HandleDatabase->Handle) {
      PackageInstance = HandleDatabase->Buffer;

      //
      // Free the Package Instance
      //
      gBS->FreePool (PackageInstance);

      //
      // If this was the only Handle in the database
      //
      if (HiiData->DatabaseHead == HandleDatabase) {
        HiiData->DatabaseHead = NULL;
      }
      //
      // Make the parent->Next point to the current->Next
      //
      PreviousHandleDatabase->NextHandleDatabase = HandleDatabase->NextHandleDatabase;
      gBS->FreePool (HandleDatabase);
      return EFI_SUCCESS;
    }
    //
    // If this was not the HandleDatabase entry we were looking for, cache it just in case the next one is
    //
    PreviousHandleDatabase = HandleDatabase;
  }
  //
  // No handle was found - error condition
  //
  if (PackageInstance == NULL) {
    return EFI_INVALID_PARAMETER;
  }

  return EFI_SUCCESS;
}

⌨️ 快捷键说明

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