gensection.c

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

C
938
字号
  //
  // Add the section header for the compressed data
  //
  CompressionSect.CommonHeader.Type     = (EFI_SECTION_TYPE) SectionType;
  CompressionSect.CommonHeader.Size[0]  = (UINT8) (TotalLength & 0xff);
  CompressionSect.CommonHeader.Size[1]  = (UINT8) ((TotalLength & 0xff00) >> 8);
  CompressionSect.CommonHeader.Size[2]  = (UINT8) ((TotalLength & 0xff0000) >> 16);
  CompressionSect.CompressionType       = (UINT8) SectionSubType;
  CompressionSect.UncompressedLength    = InputLength;

  fwrite (&CompressionSect, sizeof (CompressionSect), 1, OutFile);
  fwrite (FileBuffer, CompressedLength, 1, OutFile);
  free (FileBuffer);
  return EFI_SUCCESS;
}

EFI_STATUS
GenSectionGuidDefinedSection (
  char    **InputFileName,
  int     InputFileNum,
  UINTN   SectionType,
  UINTN   SectionSubType,
  FILE    *OutFile
  )
/*++
        
Routine Description:
           
  Generate an encapsulating section of type EFI_SECTION_GUID_DEFINED
  Input file must be already sectioned. The function won't validate
  the input files' contents. Caller should hand in files already 
  with section header.
            
Arguments:
               
  InputFileName  - Name of the input file.
                
  InputFileNum   - Number of input files. Should be at least 1.

  SectionType    - Section type to generate. Should be 
                   EFI_SECTION_GUID_DEFINED

  SectionSubType - Specify the authentication algorithm requested. 
  
  OutFile        - Output file handle

Returns:
                       
  EFI_SUCCESS on successful return
  EFI_INVALID_PARAMETER if InputFileNum is less than 1
  EFI_ABORTED if unable to open input file.
  EFI_OUT_OF_RESOURCES  No resource to complete the operation.

--*/
{
  INTN                  TotalLength;
  INTN                  InputLength;
  UINT8                 *FileBuffer;
  UINT32                Crc32Checksum;
  EFI_STATUS            Status;
  CRC32_SECTION_HEADER  Crc32GuidSect;

  if (SectionType != EFI_SECTION_GUID_DEFINED) {
    Error (NULL, 0, 0, "parameter must be EFI_SECTION_GUID_DEFINED", NULL);
    return EFI_INVALID_PARAMETER;
  }

  InputLength = 0;
  FileBuffer  = NULL;
  FileBuffer  = (UINT8 *) malloc ((1024 * 1024 * 4) * sizeof (UINT8));
  if (FileBuffer == NULL) {
    Error (__FILE__, __LINE__, 0, "application error", "failed to allocate memory");
    return EFI_OUT_OF_RESOURCES;
  }
  //
  // read all input file contents into a buffer
  //
  Status = GetSectionContents (
            InputFileName,
            InputFileNum,
            FileBuffer,
            &InputLength
            );
  if (EFI_ERROR (Status)) {
    free (FileBuffer);
    return Status;
  }
  //
  // Now data is in FileBuffer, compress the data
  //
  switch (SectionSubType) {
  case EFI_SECTION_CRC32_GUID_DEFINED:
    Crc32Checksum = 0;
    CalculateCrc32 (FileBuffer, InputLength, &Crc32Checksum);
    if (EFI_ERROR (Status)) {
      free (FileBuffer);
      return Status;
    }

    TotalLength = InputLength + CRC32_SECTION_HEADER_SIZE;
    Crc32GuidSect.GuidSectionHeader.CommonHeader.Type     = (EFI_SECTION_TYPE) SectionType;
    Crc32GuidSect.GuidSectionHeader.CommonHeader.Size[0]  = (UINT8) (TotalLength & 0xff);
    Crc32GuidSect.GuidSectionHeader.CommonHeader.Size[1]  = (UINT8) ((TotalLength & 0xff00) >> 8);
    Crc32GuidSect.GuidSectionHeader.CommonHeader.Size[2]  = (UINT8) ((TotalLength & 0xff0000) >> 16);
    memcpy (&(Crc32GuidSect.GuidSectionHeader.SectionDefinitionGuid), &gEfiCrc32SectionGuid, sizeof (EFI_GUID));
    Crc32GuidSect.GuidSectionHeader.Attributes  = EFI_GUIDED_SECTION_AUTH_STATUS_VALID;
    Crc32GuidSect.GuidSectionHeader.DataOffset  = CRC32_SECTION_HEADER_SIZE;
    Crc32GuidSect.CRC32Checksum                 = Crc32Checksum;

    break;

  default:
    Error (NULL, 0, 0, "invalid parameter", "unknown GUID defined type");
    free (FileBuffer);
    return EFI_ABORTED;
  }

  fwrite (&Crc32GuidSect, sizeof (Crc32GuidSect), 1, OutFile);
  fwrite (FileBuffer, InputLength, 1, OutFile);

  free (FileBuffer);

  return EFI_SUCCESS;
}

int
main (
  int  argc,
  char *argv[]
  )
/*++

Routine Description:

  Main

Arguments:

  command line parameters

Returns:

  EFI_SUCCESS    Section header successfully generated and section concatenated.
  EFI_ABORTED    Could not generate the section
  EFI_OUT_OF_RESOURCES  No resource to complete the operation.

--*/
{
  INTN                      Index;
  INTN                      VersionNumber;
  UINTN                     SectionType;
  UINTN                     SectionSubType;
  BOOLEAN                   InputFileRequired;
  BOOLEAN                   SubTypeRequired;
  FILE                      *InFile;
  FILE                      *OutFile;
  INTN                      InputFileNum;

  char                      **InputFileName;
  char                      *OutputFileName;
  char                      AuxString[500] = { 0 };

  char                      *ParamSectionType;
  char                      *ParamSectionSubType;
  char                      *ParamLength;
  char                      *ParamVersion;
  char                      *ParamDigitalSignature;

  EFI_STATUS                Status;
  EFI_COMMON_SECTION_HEADER CommonSect;

  InputFileName         = NULL;
  OutputFileName        = PARAMETER_NOT_SPECIFIED;
  ParamSectionType      = PARAMETER_NOT_SPECIFIED;
  ParamSectionSubType   = PARAMETER_NOT_SPECIFIED;
  ParamLength           = PARAMETER_NOT_SPECIFIED;
  ParamVersion          = PARAMETER_NOT_SPECIFIED;
  ParamDigitalSignature = PARAMETER_NOT_SPECIFIED;
  Status                = EFI_SUCCESS;

  VersionNumber         = 0;
  SectionType           = 0;
  SectionSubType        = 0;
  InputFileRequired     = TRUE;
  SubTypeRequired       = FALSE;
  InFile                = NULL;
  OutFile               = NULL;
  InputFileNum          = 0;
  Status                = EFI_SUCCESS;

  SetUtilityName (UTILITY_NAME);
  if (argc == 1) {
    PrintUsageMessage ();
    return STATUS_ERROR;
  }
  //
  // Parse command line
  //
  Index = 1;
  while (Index < argc) {
    if (_strcmpi (argv[Index], "-i") == 0) {
      //
      // Input File found
      //
      Index++;
      InputFileName = (char **) malloc (MAXIMUM_INPUT_FILE_NUM * sizeof (char *));
      if (InputFileName == NULL) {
        Error (__FILE__, __LINE__, 0, "application error", "failed to allocate memory");
        return EFI_OUT_OF_RESOURCES;
      }

      memset (InputFileName, 0, (MAXIMUM_INPUT_FILE_NUM * sizeof (char *)));
      InputFileName[InputFileNum] = argv[Index];
      InputFileNum++;
      Index++;
      //
      // Parse subsequent parameters until another switch is encountered
      //
      while ((Index < argc) && (argv[Index][0] != '-')) {
        if ((InputFileNum % MAXIMUM_INPUT_FILE_NUM) == 0) {
          //
          // InputFileName buffer too small, need to realloc
          //
          InputFileName = (char **) realloc (
                                      InputFileName,
                                      (InputFileNum + MAXIMUM_INPUT_FILE_NUM) * sizeof (char *)
                                      );
          if (InputFileName == NULL) {
            Error (__FILE__, __LINE__, 0, "application error", "failed to allocate memory");
            return EFI_OUT_OF_RESOURCES;
          }

          memset (&(InputFileName[InputFileNum]), 0, (MAXIMUM_INPUT_FILE_NUM * sizeof (char *)));
        }

        InputFileName[InputFileNum] = argv[Index];
        InputFileNum++;
        Index++;
      }

    }

    if (_strcmpi (argv[Index], "-o") == 0) {
      //
      // Output file found
      //
      Index++;
      OutputFileName = argv[Index];
    } else if (_strcmpi (argv[Index], "-s") == 0) {
      //
      // Section Type found
      //
      Index++;
      ParamSectionType = argv[Index];
    } else if (_strcmpi (argv[Index], "-t") == 0) {
      //
      // Compression or Authentication type
      //
      Index++;
      ParamSectionSubType = argv[Index];
    } else if (_strcmpi (argv[Index], "-l") == 0) {
      //
      // Length
      //
      Index++;
      ParamLength = argv[Index];
    } else if (_strcmpi (argv[Index], "-v") == 0) {
      //
      // VersionNumber
      //
      Index++;
      ParamVersion = argv[Index];
    } else if (_strcmpi (argv[Index], "-a") == 0) {
      //
      // Aux string
      //
      Index++;
      //
      // Note, the MSVC C-Start parses out and consolidates quoted strings from the command
      // line.  Quote characters are stripped.  If this tool is ported to other environments
      // this will need to be taken into account
      //
      strncpy (AuxString, argv[Index], 499);
    } else if (_strcmpi (argv[Index], "-d") == 0) {
      //
      // Digital signature for EFI_TEST_AUTHENTICAION (must be 0 or 1)
      //
      Index++;
      ParamDigitalSignature = argv[Index];
    } else if (_strcmpi (argv[Index], "-?") == 0) {
      PrintUsageMessage ();
      return STATUS_ERROR;
    } else {
      Error (NULL, 0, 0, argv[Index], "unknown option");
      return GetUtilityStatus ();
    }

    Index++;
  }
  //
  // At this point, all command line parameters are verified as not being totally
  // bogus.  Next verify the command line parameters are complete and make
  // sense...
  //
  if (_stricmp (ParamSectionType, SectionTypeName[EFI_SECTION_COMPRESSION]) == 0) {
    SectionType     = EFI_SECTION_COMPRESSION;
    SubTypeRequired = TRUE;
    if (_stricmp (ParamSectionSubType, CompressionTypeName[EFI_NOT_COMPRESSED]) == 0) {
      SectionSubType = EFI_NOT_COMPRESSED;
    } else if (_stricmp (ParamSectionSubType, CompressionTypeName[EFI_STANDARD_COMPRESSION]) == 0) {
      SectionSubType = EFI_STANDARD_COMPRESSION;
    } else {
      Error (NULL, 0, 0, ParamSectionSubType, "unknown compression type");
      PrintUsageMessage ();
      return GetUtilityStatus ();
    }
  } else if (_stricmp (ParamSectionType, SectionTypeName[EFI_SECTION_GUID_DEFINED]) == 0) {
    SectionType     = EFI_SECTION_GUID_DEFINED;
    SubTypeRequired = TRUE;
    if (_stricmp (ParamSectionSubType, GUIDedSectionTypeName[EFI_SECTION_CRC32_GUID_DEFINED]) == 0) {
      SectionSubType = EFI_SECTION_CRC32_GUID_DEFINED;
    } else {
      Error (NULL, 0, 0, ParamSectionSubType, "unknown GUID defined section type", ParamSectionSubType);
      PrintUsageMessage ();
      return GetUtilityStatus ();
    }
  } else if (_stricmp (ParamSectionType, SectionTypeName[EFI_SECTION_PE32]) == 0) {
    SectionType = EFI_SECTION_PE32;
  } else if (_stricmp (ParamSectionType, SectionTypeName[EFI_SECTION_PIC]) == 0) {
    SectionType = EFI_SECTION_PIC;
  } else if (_stricmp (ParamSectionType, SectionTypeName[EFI_SECTION_TE]) == 0) {
    SectionType = EFI_SECTION_TE;
  } else if (_stricmp (ParamSectionType, SectionTypeName[EFI_SECTION_DXE_DEPEX]) == 0) {
    SectionType = EFI_SECTION_DXE_DEPEX;
  } else if (_stricmp (ParamSectionType, SectionTypeName[EFI_SECTION_VERSION]) == 0) {
    SectionType       = EFI_SECTION_VERSION;
    InputFileRequired = FALSE;
    Index             = sscanf (ParamVersion, "%d", &VersionNumber);
    if (Index != 1 || VersionNumber < 0 || VersionNumber > 65565) {
      Error (NULL, 0, 0, ParamVersion, "illegal version number");
      PrintUsageMessage ();
      return GetUtilityStatus ();
    }

    if (strcmp (AuxString, PARAMETER_NOT_SPECIFIED) == 0) {
      AuxString[0] = 0;
    }
  } else if (_stricmp (ParamSectionType, SectionTypeName[EFI_SECTION_USER_INTERFACE]) == 0) {
    SectionType       = EFI_SECTION_USER_INTERFACE;
    InputFileRequired = FALSE;
    if (strcmp (AuxString, PARAMETER_NOT_SPECIFIED) == 0) {
      Error (NULL, 0, 0, "user interface string not specified", NULL);
      PrintUsageMessage ();
      return GetUtilityStatus ();
    }
  } else if (_stricmp (ParamSectionType, SectionTypeName[EFI_SECTION_COMPATIBILITY16]) == 0) {
    SectionType = EFI_SECTION_COMPATIBILITY16;
  } else if (_stricmp (ParamSectionType, SectionTypeName[EFI_SECTION_FIRMWARE_VOLUME_IMAGE]) == 0) {
    SectionType = EFI_SECTION_FIRMWARE_VOLUME_IMAGE;
  } else if (_stricmp (ParamSectionType, SectionTypeName[EFI_SECTION_FREEFORM_SUBTYPE_GUID]) == 0) {
    SectionType = EFI_SECTION_FREEFORM_SUBTYPE_GUID;
  } else if (_stricmp (ParamSectionType, SectionTypeName[EFI_SECTION_RAW]) == 0) {
    SectionType = EFI_SECTION_RAW;
  } else if (_stricmp (ParamSectionType, SectionTypeName[EFI_SECTION_PEI_DEPEX]) == 0) {
    SectionType = EFI_SECTION_PEI_DEPEX;
  } else {
    Error (NULL, 0, 0, ParamSectionType, "unknown section type");
    PrintUsageMessage ();
    return GetUtilityStatus ();
  }
  //
  // Open output file
  //
  OutFile = fopen (OutputFileName, "wb");
  if (OutFile == NULL) {
    Error (NULL, 0, 0, OutputFileName, "failed to open output file for writing");
    if (InFile != NULL) {
      fclose (InFile);
    }

    return GetUtilityStatus ();
  }
  //
  // At this point, we've fully validated the command line, and opened appropriate
  // files, so let's go and do what we've been asked to do...
  //
  //
  // Within this switch, build and write out the section header including any
  // section type specific pieces.  If there's an input file, it's tacked on later
  //
  switch (SectionType) {
  case EFI_SECTION_COMPRESSION:
    Status = GenSectionCompressionSection (
              InputFileName,
              InputFileNum,
              SectionType,
              SectionSubType,
              OutFile
              );
    break;

  case EFI_SECTION_GUID_DEFINED:
    Status = GenSectionGuidDefinedSection (
              InputFileName,
              InputFileNum,
              SectionType,
              SectionSubType,
              OutFile
              );
    break;

  case EFI_SECTION_VERSION:
    CommonSect.Type = (EFI_SECTION_TYPE) SectionType;

    Index           = sizeof (CommonSect);
    //
    // 2 characters for the build number
    //
    Index += 2;
    //
    // Aux string is ascii.. unicode is 2X + 2 bytes for terminating unicode null.
    //
    Index += (strlen (AuxString) * 2) + 2;
    memcpy (&CommonSect.Size, &Index, 3);
    fwrite (&CommonSect, sizeof (CommonSect), 1, OutFile);
    fwrite (&VersionNumber, 2, 1, OutFile);
    Ascii2UnicodeWriteString (AuxString, OutFile, FALSE);
    break;

  case EFI_SECTION_USER_INTERFACE:
    CommonSect.Type = (EFI_SECTION_TYPE) SectionType;
    Index           = sizeof (CommonSect);
    //
    // Aux string is ascii.. unicode is 2X + 2 bytes for terminating unicode null.
    //
    Index += (strlen (AuxString) * 2) + 2;
    memcpy (&CommonSect.Size, &Index, 3);
    fwrite (&CommonSect, sizeof (CommonSect), 1, OutFile);
    Ascii2UnicodeWriteString (AuxString, OutFile, FALSE);
    break;

  default:
    //
    // All other section types are caught by default (they're all the same)
    //
    Status = GenSectionCommonLeafSection (
              InputFileName,
              InputFileNum,
              SectionType,
              OutFile
              );
    break;
  }

  if (InputFileName != NULL) {
    free (InputFileName);
  }

  fclose (OutFile);
  //
  // If we had errors, then delete the output file
  //
  if (GetUtilityStatus () == STATUS_ERROR) {
    remove (OutputFileName);
  }

  return GetUtilityStatus ();
}

⌨️ 快捷键说明

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