forms.c

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

C
1,564
字号
  TempValue             = 0;
  SizeNeeded            = sizeof (EFI_HII_EXPORT_TABLE);

  //
  // How many total tables are there?
  //
  for (; HandleDatabase != NULL; HandleDatabase = HandleDatabase->NextHandleDatabase) {
    if ((Handle != 0) && (Handle != HandleDatabase->Handle)) {
      continue;
    }

    VariableExist = FALSE;
    NumberOfHiiDataTables++;
    PackageInstance = HandleDatabase->Buffer;
    if (PackageInstance == NULL) {
      continue;
    }
    //
    // Extract Size of Export Package
    //
    SizeNeeded = SizeNeeded + PackageInstance->IfrSize 
                            + PackageInstance->StringSize
                            + sizeof (EFI_HII_DATA_TABLE)
                            + sizeof (EFI_HII_DEVICE_PATH_PACK);

    //
    // BUGBUG We aren't inserting Device path data yet
    //
    SizeNeeded = SizeNeeded + sizeof (EFI_DEVICE_PATH_PROTOCOL);

    //
    // Extract Size of Variable Data
    //
    if (PackageInstance->IfrSize > 0) {
      FormPack = (EFI_HII_IFR_PACK *) ((CHAR8 *) (&PackageInstance->IfrData) + sizeof (EFI_HII_PACK_HEADER));
    } else {
      //
      // No IFR? No variable information
      //
      continue;
    }

    RawData = (UINT8 *) FormPack;

    for (Index = 0; RawData[Index] != EFI_IFR_END_FORM_SET_OP;) {
      switch (RawData[Index]) {
      case EFI_IFR_FORM_SET_OP:
        EfiCopyMem (&VariableSize, &((EFI_IFR_FORM_SET *) &RawData[Index])->NvDataSize, sizeof (UINT16));
        SizeNeeded    = SizeNeeded + VariableSize + sizeof (SETUP_MAP_NAME) + sizeof (EFI_HII_VARIABLE_PACK);
        VariableExist = TRUE;
        break;

      case EFI_IFR_VARSTORE_OP:
        EfiCopyMem (&VariableSize, &((EFI_IFR_VARSTORE *) &RawData[Index])->Size, sizeof (UINT16));
        SizeNeeded = SizeNeeded + VariableSize + sizeof (EFI_HII_VARIABLE_PACK);
        //
        // We will be expanding the stored ASCII name to a Unicode string.  This will cause some memory overhead
        // Since the VARSTORE size already takes in consideration the ASCII size, we need to size it and add another
        // instance of it.  Essentially, 2 ASCII strings == 1 Unicode string in size.
        //
        TempValue     = (UINTN) ((EFI_IFR_VARSTORE *) &RawData[Index])->Header.Length - sizeof (EFI_IFR_VARSTORE);
        SizeNeeded    = SizeNeeded + TempValue * 2;
        VariableExist = TRUE;
        break;
      }

      Index = RawData[Index + 1] + Index;
    }
    //
    // If a variable exists for this handle, add an additional variable pack overhead to
    // indicate that we will have an extra null Variable Pack to signify the end of the Variable Packs
    //
    if (VariableExist) {
      SizeNeeded = SizeNeeded + sizeof (EFI_HII_VARIABLE_PACK);
    }
  }

  if (SizeNeeded > *BufferSize) {
    *BufferSize = SizeNeeded;
    return EFI_BUFFER_TOO_SMALL;
  }
  //
  // Zero out the incoming buffer
  //
  EfiZeroMem (Buffer, *BufferSize);

  //
  // Cast the Buffer to EFI_HII_EXPORT_TABLE
  //
  ExportTable = (EFI_HII_EXPORT_TABLE *) Buffer;

  //
  // Set the Revision for the Export Table
  //
  EfiCopyMem (&ExportTable->Revision, &gEfiHiiProtocolGuid, sizeof (EFI_GUID));

  ExportBuffer    = (UINT8 *) (UINTN) (((UINT8 *) ExportTable) + sizeof (EFI_HII_EXPORT_TABLE));
  HandleDatabase  = HiiData->DatabaseHead;

  //
  // Check numeric value against the head of the database
  //
  for (; HandleDatabase != NULL; HandleDatabase = HandleDatabase->NextHandleDatabase) {
    DataTable       = (EFI_HII_DATA_TABLE *) ExportBuffer;
    PackageInstance = HandleDatabase->Buffer;
    //
    // If not asking for a specific handle, export the entire database
    //
    if (Handle == 0) {
      ExportTable->NumberOfHiiDataTables = NumberOfHiiDataTables;
      EfiCopyMem (&DataTable->PackageGuid, &PackageInstance->Guid, sizeof (EFI_GUID));
      DataTable->HiiHandle        = PackageInstance->Handle;
      DataTable->DevicePathOffset = (UINT32) (sizeof (EFI_HII_DATA_TABLE));

      //
      // Start Dumping DevicePath
      //
      ExtractDevicePathData (DataTable, RawData, &ExportBuffer);

      if (((UINTN) ExportBuffer) == ((UINTN) DataTable)) {
        //
        // If there is no DevicePath information - set offset to 0 to signify the absence of data to parse
        //
        DataTable->DevicePathOffset = 0;
      }

      DataTable->VariableDataOffset = (UINT32) (((UINTN) ExportBuffer) - ((UINTN) DataTable));

      if (PackageInstance->IfrSize > 0) {
        FormPack  = (EFI_HII_IFR_PACK *) ((CHAR8 *) (&PackageInstance->IfrData) + sizeof (EFI_HII_PACK_HEADER));

        RawData   = (UINT8 *) FormPack;
        TempValue = 0;

        //
        // Start dumping the Variable Data
        //
        ExtractVariableData (DataTable, RawData, &ExportBuffer);
        DataTable->IfrDataOffset = (UINT32) (((UINTN) ExportBuffer) - ((UINTN) DataTable));

        if (DataTable->VariableDataOffset == DataTable->IfrDataOffset) {
          DataTable->VariableDataOffset = 0;
        }
        //
        // Start dumping the IFR data (Note:  It is in an IFR PACK)
        //
        EfiCopyMem (ExportBuffer, &PackageInstance->IfrData, PackageInstance->IfrSize);
        ExportBuffer                = (UINT8 *) (UINTN) (((UINTN) ExportBuffer) + PackageInstance->IfrSize);
        DataTable->StringDataOffset = (UINT32) (((UINTN) ExportBuffer) - ((UINTN) DataTable));

        //
        // Start dumping the String data (Note:  It is in a String PACK)
        //
        if (PackageInstance->StringSize > 0) {
          RawData = (UINT8 *) (((UINTN) &PackageInstance->IfrData) + PackageInstance->IfrSize);
          EfiCopyMem (ExportBuffer, RawData, PackageInstance->StringSize);
          DataTable->DataTableSize = (UINT32) (DataTable->StringDataOffset + PackageInstance->StringSize);

          EfiCopyMem (&TempValue, &((EFI_HII_STRING_PACK *) ExportBuffer)->Header.Length, sizeof (UINT32));
          for (; TempValue != 0;) {
            DataTable->NumberOfLanguages++;
            ExportBuffer = ExportBuffer + ((EFI_HII_STRING_PACK *) ExportBuffer)->Header.Length;
            EfiCopyMem (&TempValue, &((EFI_HII_STRING_PACK *) ExportBuffer)->Header.Length, sizeof (UINT32));
          }

          ExportBuffer = ExportBuffer + sizeof (EFI_HII_STRING_PACK);
        } else {
          DataTable->StringDataOffset = 0;
        }
      } else {
        //
        // No IFR? No variable information.  If Offset is 0, means there is none.  (Hmm - this might be prunable - no strings to export if no IFR - we always have a stub)
        //
        DataTable->VariableDataOffset = 0;
        DataTable->IfrDataOffset      = 0;
        DataTable->StringDataOffset   = (UINT32) (((UINTN) ExportBuffer) - ((UINTN) DataTable));

        //
        // Start dumping the String data - NOTE:  It is in String Pack form
        //
        if (PackageInstance->StringSize > 0) {
          RawData = (UINT8 *) (((UINTN) &PackageInstance->IfrData) + PackageInstance->IfrSize);
          EfiCopyMem (ExportBuffer, RawData, PackageInstance->StringSize);
          DataTable->DataTableSize = (UINT32) (DataTable->StringDataOffset + PackageInstance->StringSize);

          EfiCopyMem (&TempValue, &((EFI_HII_STRING_PACK *) ExportBuffer)->Header.Length, sizeof (UINT32));
          for (; TempValue != 0;) {
            DataTable->NumberOfLanguages++;
            ExportBuffer = ExportBuffer + ((EFI_HII_STRING_PACK *) ExportBuffer)->Header.Length;
            EfiCopyMem (&TempValue, &((EFI_HII_STRING_PACK *) ExportBuffer)->Header.Length, sizeof (UINT32));
          }

          ExportBuffer = ExportBuffer + sizeof (EFI_HII_STRING_PACK);
        } else {
          DataTable->StringDataOffset = 0;
        }
      }
    } else {
      //
      // Match the numeric value with the database entry - if matched, extract PackageInstance
      //
      if (Handle == HandleDatabase->Handle) {
        PackageInstance                     = HandleDatabase->Buffer;
        ExportTable->NumberOfHiiDataTables  = NumberOfHiiDataTables;
        DataTable->HiiHandle                = PackageInstance->Handle;
        EfiCopyMem (&DataTable->PackageGuid, &PackageInstance->Guid, sizeof (EFI_GUID));

        //
        // Start Dumping DevicePath
        //
        ExtractDevicePathData (DataTable, RawData, &ExportBuffer);
        DataTable->VariableDataOffset = (UINT32) (((UINTN) ExportBuffer) - ((UINTN) DataTable));

        if (PackageInstance->IfrSize > 0) {
          FormPack  = (EFI_HII_IFR_PACK *) ((CHAR8 *) (&PackageInstance->IfrData) + sizeof (EFI_HII_PACK_HEADER));

          RawData   = (UINT8 *) FormPack;
          TempValue = 0;

          //
          // Start dumping the Variable Data
          //
          ExtractVariableData (DataTable, RawData, &ExportBuffer);
          DataTable->IfrDataOffset = (UINT32) (((UINTN) ExportBuffer) - ((UINTN) DataTable));

          if (DataTable->VariableDataOffset == DataTable->IfrDataOffset) {
            DataTable->VariableDataOffset = 0;
          }
          //
          // Start dumping the IFR data
          //
          EfiCopyMem (ExportBuffer, &PackageInstance->IfrData, PackageInstance->IfrSize);
          ExportBuffer                = (UINT8 *) (UINTN) (((UINTN) ExportBuffer) + PackageInstance->IfrSize);
          DataTable->StringDataOffset = (UINT32) (((UINTN) ExportBuffer) - ((UINTN) DataTable));

          //
          // Start dumping the String data - NOTE:  It is in String Pack form
          //
          if (PackageInstance->StringSize > 0) {
            RawData = (UINT8 *) (((UINTN) &PackageInstance->IfrData) + PackageInstance->IfrSize);
            EfiCopyMem (ExportBuffer, RawData, PackageInstance->StringSize);
            DataTable->DataTableSize = (UINT32) (DataTable->StringDataOffset + PackageInstance->StringSize);

            EfiCopyMem (&TempValue, &((EFI_HII_STRING_PACK *) ExportBuffer)->Header.Length, sizeof (UINT32));
            for (; TempValue != 0;) {
              DataTable->NumberOfLanguages++;
              ExportBuffer = ExportBuffer + ((EFI_HII_STRING_PACK *) ExportBuffer)->Header.Length;
              EfiCopyMem (&TempValue, &((EFI_HII_STRING_PACK *) ExportBuffer)->Header.Length, sizeof (UINT32));
            }

            ExportBuffer = ExportBuffer + sizeof (EFI_HII_STRING_PACK);
          } else {
            DataTable->StringDataOffset = 0;
          }
        } else {
          //
          // No IFR? No variable information.  If Offset is 0, means there is none.
          //
          DataTable->VariableDataOffset = 0;
          DataTable->IfrDataOffset      = 0;
          DataTable->StringDataOffset   = (UINT32) (((UINTN) ExportBuffer) - ((UINTN) DataTable));

          //
          // Start dumping the String data - Note:  It is in String Pack form
          //
          if (PackageInstance->StringSize > 0) {
            RawData = (UINT8 *) (((UINTN) &PackageInstance->IfrData) + PackageInstance->IfrSize);
            EfiCopyMem (ExportBuffer, RawData, PackageInstance->StringSize);
            DataTable->DataTableSize = (UINT32) (DataTable->StringDataOffset + PackageInstance->StringSize);

            EfiCopyMem (&TempValue, &((EFI_HII_STRING_PACK *) ExportBuffer)->Header.Length, sizeof (UINT32));
            for (; TempValue != 0;) {
              DataTable->NumberOfLanguages++;
              ExportBuffer = ExportBuffer + ((EFI_HII_STRING_PACK *) ExportBuffer)->Header.Length;
              EfiCopyMem (&TempValue, &((EFI_HII_STRING_PACK *) ExportBuffer)->Header.Length, sizeof (UINT32));
            }

            ExportBuffer = ExportBuffer + sizeof (EFI_HII_STRING_PACK);
          } else {
            DataTable->StringDataOffset = 0;
          }
        }
        break;
      }
    }
  }

  return EFI_SUCCESS;
}

EFI_STATUS
EFIAPI
HiiGetForms (
  IN     EFI_HII_PROTOCOL   *This,
  IN     EFI_HII_HANDLE     Handle,
  IN     EFI_FORM_ID        FormId,
  IN OUT UINTN              *BufferLength,
  OUT    UINT8              *Buffer
  )
/*++

Routine Description:
  
  This function allows a program to extract a form or form package that has 
  previously been registered with the EFI HII database.

Arguments:
  This         - A pointer to the EFI_HII_PROTOCOL instance.
  
  Handle       - Handle on which the form resides. Type EFI_HII_HANDLE is defined in 
                 EFI_HII_PROTOCOL.NewPack() in the Packages section.
            
  FormId       - The ID of the form to return. If the ID is zero, the entire form package is returned.
                 Type EFI_FORM_ID is defined in "Related Definitions" below.
            
  BufferLength - On input, the length of the Buffer. On output, the length of the returned buffer, if
                 the length was sufficient and, if it was not, the length that is required to fit the
                 requested form(s).
                  
  Buffer       - The buffer designed to receive the form(s).

Returns: 

  EFI_SUCCESS           -  Buffer filled with the requested forms. BufferLength
                           was updated.
                           
  EFI_INVALID_PARAMETER -  The handle is unknown.
  
  EFI_NOT_FOUND         -  A form on the requested handle cannot be found with the
                           requested FormId.
                           
  EFI_BUFFER_TOO_SMALL  - The buffer provided was not large enough to allow the form to be stored.

--*/
{
  EFI_HII_PACKAGE_INSTANCE  *PackageInstance;
  EFI_HII_DATA              *HiiData;
  EFI_HII_HANDLE_DATABASE   *HandleDatabase;
  EFI_HII_IFR_PACK          *FormPack;
  EFI_IFR_FORM              *Form;
  EFI_IFR_OP_HEADER         *Location;

  if (This == NULL) {
    return EFI_INVALID_PARAMETER;
  }

  HiiData         = EFI_HII_DATA_FROM_THIS (This);

  HandleDatabase  = HiiData->DatabaseHead;

  PackageInstance = NULL;

  //
  // Check numeric value against the head of the database
  //
  for (; HandleDatabase != NULL; HandleDatabase = HandleDatabase->NextHandleDatabase) {
    //
    // Match the numeric value with the database entry - if matched, extract PackageInstance
    //
    if (Handle == HandleDatabase->Handle) {
      PackageInstance = HandleDatabase->Buffer;
      break;
    }
  }
  //
  // No handle was found - error condition
  //
  if (PackageInstance == NULL) {
    return EFI_NOT_FOUND;
  }
  //
  // Based on if there is IFR data in this package instance, determine
  // what the location is of the beginning of the string data.
  //
  if (PackageInstance->IfrSize > 0) {
    FormPack = (EFI_HII_IFR_PACK *) (&PackageInstance->IfrData);
  } else {
    //
    // If there is no IFR data return an error
    //
    return EFI_NOT_FOUND;
  }
  //
  // If requesting the entire Form Package
  //
  if (FormId == 0) {
    //
    // Return an error if buffer is too small
    //
    if (PackageInstance->IfrSize > *BufferLength || Buffer == NULL) {
      *BufferLength = PackageInstance->IfrSize;

⌨️ 快捷键说明

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