fwvolume.c

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

C
1,503
字号
CFVConstructor (
  VOID
  )
{
  mFileList = NULL;
  mLastFile = NULL;
}

void
CFVDestructor (
  VOID
  )
{
  CFVFreeFileList ();
  //
  // Free up our firmware volume list
  //
  while (mFVList != NULL) {
    mFVListLast = mFVList->Next;
    FREE (mFVList);
    mFVList = mFVListLast;
  }
}

static
void
CFVFreeFileList (
  VOID
  )
{
  FILE_LIST *Next;
  while (mFileList != NULL) {
    if (mFileList->FileName != NULL) {
      free (mFileList->FileName);
    }

    if (mFileList->FVs != NULL) {
      free (mFileList->FVs);
    }

    free (mFileList->BaseFileName);
    if (mFileList->BaseName != NULL) {
      free (mFileList->BaseName);
    }

    if (mFileList->Processor != NULL) {
      free (mFileList->Processor);
    }

    if (mFileList->Guid != NULL) {
      free (mFileList->Guid);
    }

    Next = mFileList->Next;
    free (mFileList);
    mFileList = Next;
  }

  mFileList = NULL;
}

int
CFVWriteInfFiles (
  DSC_FILE  *DSC,
  FILE      *MakeFptr
  )
/*++

Routine Description:

  After processing all components in a DSC file, create the firmware
  volume INF files. We actually do a lot more here.

  * Create the FVxxx.inf file that is used by GenFvImage
  * Create the Apriori files for each firmware volume that requires one
  * Create makefile.out macros for FVxxx_FILES = FVxxx_FILES AnotherFile
    so you can do incremental builds of firmware volumes.
  * For each FV, emit its build commands to makefile.out

Arguments:

  DSC       - pointer to a DSC_FILE object to extract info from
  MakeFptr  - pointer to the output makefile

Returns:

  0  if successful
  non-zero otherwise

--*/
{
  FILE_LIST *FileListPtr;
  FV_LIST   *FVList;
  FV_LIST   *LastFVList;
  FV_LIST   *FVPtr;
  SECTION   *Section;
  char      *StartCptr;
  char      *EndCptr;
  char      CSave;
  char      Str[MAX_PATH];
  char      Line[MAX_LINE_LEN];
  char      ExpandedLine[MAX_LINE_LEN];
  char      FVDir[MAX_PATH];
  FILE      *XRefFptr;
  int       AprioriCounter;
  int       AprioriCount;
  int       AprioriPosition;
  BOOLEAN   AprioriFound;
  int       ComponentsInstance;
  int       ComponentCount;

  //
  // Use this to keep track of all the firmware volume names
  //
  FVList      = NULL;
  LastFVList  = NULL;
  //
  // See if they specified a FV directory to dump the FV files out to. If not,
  // then use the default. Then create the output directory.
  //
  StartCptr = GetSymbolValue (FV_INF_DIR);
  if (StartCptr == NULL) {
    strcpy (Str, DEFAULT_FV_INF_DIR);
    ExpandMacros (Str, FVDir, sizeof (FVDir), 0);
  } else {
    strcpy (FVDir, StartCptr);
  }
  //
  // Make sure the fv directory path ends in /
  //
  CSave = FVDir[strlen (FVDir) - 1];
  if ((CSave != '\\') && (CSave != '/')) {
    strcat (FVDir, "\\");
  }
  //
  // Traverse the list of all files, determine which FV each is in, then
  // write out the file's name to the output FVxxx.inf file.
  //
  for (FileListPtr = mFileList; FileListPtr != NULL; FileListPtr = FileListPtr->Next) {
    //
    // Parse all the "FV1,FV2..." in the FVs
    //
    if (FileListPtr->FVs != NULL) {
      //
      // Process each fv this file is in
      //
      StartCptr = FileListPtr->FVs;
      while (*StartCptr) {
        EndCptr = StartCptr;
        while (*EndCptr && (*EndCptr != ',')) {
          EndCptr++;
        }

        CSave     = *EndCptr;
        *EndCptr  = 0;
        //
        // Ok, we have a fv name, now see if we've already opened
        // an fv output file of this name.
        //
        for (FVPtr = FVList; FVPtr != NULL; FVPtr = FVPtr->Next) {
          if (_stricmp (FVPtr->FVFileName, StartCptr) == 0) {
            break;
          }
        }
        //
        // If we didn't find one, then create a new one
        //
        if (FVPtr == NULL) {
          //
          // Create a new one, add it to the list
          //
          FVPtr = (FV_LIST *) malloc (sizeof (FV_LIST));
          if (FVPtr == NULL) {
            Error (NULL, 0, 0, NULL, "failed to allocate memory for FV");
            return STATUS_ERROR;
          }

          memset ((char *) FVPtr, 0, sizeof (FV_LIST));
          //
          // Add it to the end of our list
          //
          if (FVList == NULL) {
            FVList = FVPtr;
          } else {
            LastFVList->Next = FVPtr;
          }

          LastFVList = FVPtr;
          //
          // Save the FV name in the FileName pointer so we can compare
          // for any future FV names specified.
          //
          strcpy (FVPtr->FVFileName, StartCptr);

          //
          // Add a symbol for the FV filename
          //
          UpperCaseString (FVPtr->FVFileName);
          AddSymbol (FV_FILENAME, FVPtr->FVFileName, SYM_LOCAL | SYM_OVERWRITE);
          //
          // Now create the FVx.inf filename from the fv name and
          // default filename extension. Dump it in the FV directory
          // as well.
          //
          strcpy (Str, FVDir);
          strcat (Str, FVPtr->FVFileName);
          strcat (Str, ".inf");
          //
          // Create the directory path for our new fv.inf output file.
          //
          MakeFilePath (Str);
          if ((FVPtr->FVFilePtr = fopen (Str, "w")) == NULL) {
            Error (NULL, 0, 0, Str, "could not open FV output file");
            return STATUS_ERROR;
          }
          //
          // Now copy the [fv.$(FV).options] to the fv INF file
          //
          sprintf (Str, "fv.%s.options", StartCptr);
          Section = DSCFileFindSection (DSC, Str);
          if (Section != NULL) {
            fprintf (FVPtr->FVFilePtr, "[options]\n");
            while (DSCFileGetLine (DSC, Line, sizeof (Line)) != NULL) {
              ExpandMacros (
                Line,
                ExpandedLine,
                sizeof (ExpandedLine),
                EXPANDMODE_NO_DESTDIR | EXPANDMODE_NO_SOURCEDIR
                );
              fprintf (FVPtr->FVFilePtr, ExpandedLine);
              GetBaseAddress (ExpandedLine, FVPtr->BaseAddress);
            }
          } else {
            Error (NULL, 0, 0, Str, "could not find FV section in description file");
          }
          //
          // Copy the [fv.$(FV).attributes] to the fv INF file
          //
          sprintf (Str, "fv.%s.attributes", StartCptr);
          Section = DSCFileFindSection (DSC, Str);
          if (Section != NULL) {
            fprintf (FVPtr->FVFilePtr, "[attributes]\n");
            while (DSCFileGetLine (DSC, Line, sizeof (Line)) != NULL) {
              fprintf (FVPtr->FVFilePtr, Line);
            }
          } else {
            Error (NULL, 0, 0, Str, "Could not find FV section in description file");
          }
          //
          // Start the files section
          //
          fprintf (FVPtr->FVFilePtr, "\n[files]\n");
        }
        //
        // Now write the FV filename to the FV.inf file. Prepend $(PROCESSOR) on
        // it.
        //
        fprintf (FVPtr->FVFilePtr, "EFI_FILE_NAME = %s\n", FileListPtr->FileName);

        //
        // Next FV on the FV list
        //
        *EndCptr  = CSave;
        StartCptr = EndCptr;
        if (*StartCptr) {
          StartCptr++;
        }
      }
    }
  }
  //
  // Now we walk the list of firmware volumes and create the APRIORI list
  // file for it .
  //
  for (FVPtr = FVList; FVPtr != NULL; FVPtr = FVPtr->Next) {
    //
    // Run through all the files and count up how many are to be
    // added to the apriori list for this FV. Then when we're done
    // we'll make sure we processed them all. We do this in case they
    // skipped an apriori index for a given FV.
    //
    AprioriCount = 0;
    for (FileListPtr = mFileList; FileListPtr != NULL; FileListPtr = FileListPtr->Next) {
      if (OrderInFvList (FileListPtr->Apriori, FVPtr->FVFileName, &AprioriPosition)) {
        //
        // Emit an error if the index was 0, or they didn't give one.
        //
        if (AprioriPosition == 0) {
          Error (
            GetSymbolValue (DSC_FILENAME),
            1,
            0,
            "apriori indexes are 1-based",
            "component %s:APRIORI=%s",
            FileListPtr->BaseName,
            FileListPtr->Apriori
            );
        } else {
          AprioriCount++;
        }

      }
    }
    //
    // Now scan the files as we increment our apriori index
    //
    AprioriCounter = 0;
    do {
      AprioriFound = 0;
      AprioriCounter++;
      for (FileListPtr = mFileList; FileListPtr != NULL; FileListPtr = FileListPtr->Next) {
        //
        // If in the apriori list for this fv, print the name. Open the
        // file first if we have to.
        //
        if ((FileListPtr->Apriori[0] != 0) &&
            (OrderInFvList (FileListPtr->Apriori, FVPtr->FVFileName, &AprioriPosition))
            ) {
          if (AprioriPosition == AprioriCounter) {
            //
            // If we've already found one for this index, emit an error. Decrement the
            // count of how files we are to process so we don't emit another error for
            // a miscount below.
            //
            if (AprioriFound) {
              Error (
                GetSymbolValue (DSC_FILENAME),
                1,
                0,
                "duplicate apriori index found",
                "%s:%d",
                FVPtr->FVFileName,
                AprioriCounter
                );
              AprioriCount--;
            }

            AprioriFound = 1;
            //
            // Open the apriori output file if we haven't already
            //
            if (FVPtr->AprioriFilePtr == NULL) {
              strcpy (Str, FVDir);
              strcat (Str, FVPtr->FVFileName);
              strcat (Str, ".apr");
              if ((FVPtr->AprioriFilePtr = fopen (Str, "w")) == NULL) {
                Error (NULL, 0, 0, Str, "could not open output Apriori file for writing");
                return STATUS_ERROR;
              }
            }

            fprintf (FVPtr->AprioriFilePtr, "%s\n", FileListPtr->BaseFileName);
          }
        }
      }
    } while (AprioriFound);
    //
    // See if they skipped an apriori position for this FV
    //
    if (AprioriCount != (AprioriCounter - 1)) {
      Error (
        GetSymbolValue (DSC_FILENAME),
        1,
        0,
        "apriori index skipped",
        "%s:%d",
        FVPtr->FVFileName,
        AprioriCounter
        );
    }
  }
  //
  // Traverse the list of all files again, and create a macro in the output makefile
  // that defines all the files in each fv. For example, for each FV file, create a line:
  // FV0001_FILES = $(FV_0001_FILES) xxxx-yyy.dxe.
  // This can then be used as a dependency in their makefile.
  // Also if they wanted us to dump a cross-reference, do that now.
  //
  if (mXRefFileName != NULL) {
    if ((XRefFptr = fopen (mXRefFileName, "w")) == NULL) {
      Message (
        0,
        "Failed to open cross-reference file '%s' for writing\n",
        mXRefFileName
        );
    }
  } else {
    XRefFptr = NULL;
  }

  for (FileListPtr = mFileList; FileListPtr != NULL; FileListPtr = FileListPtr->Next) {
    //
    // Parse all the "FV1,FV2..." in the FV field that came from FV=FVa,FVb,... on the
    // component line in the DSC file.
    //
    if (FileListPtr->FVs != NULL) {
      //
      // If generating a cross-reference file, dump the data
      //
      if (XRefFptr != NULL) {
        if ((FileListPtr->Guid != NULL) && (FileListPtr->BaseName != NULL) && (FileListPtr->Processor)) {
          fprintf (
            XRefFptr,
            "%s %s %s\n",
            FileListPtr->Guid,
            FileListPtr->BaseName,
            FileListPtr->Processor
            );
        }
      }
      //
      // Convert to uppercase since we're going to use the name as a macro variable name
      // in the makefile.
      //
      UpperCaseString (FileListPtr->FVs);
      //
      // Process each FV this file is in to write fvxxx_FILES = $(fvxxx_FILES) Guid-BaseName.ffs
      //
      StartCptr = FileListPtr->FVs;
      while (*StartCptr) {
        EndCptr = StartCptr;
        while (*EndCptr && (*EndCptr != ',')) {
          EndCptr++;
        }

        CSave     = *EndCptr;
        *EndCptr  = 0;
        fprintf (
          MakeFptr,
          "%s_FILES = $(%s_FILES) %s\n",
          StartCptr,
          StartCptr,
          FileListPtr->FileName
          );
        //
        // Next FV on the FV list
        //
        *EndCptr  = CSave;
        StartCptr = EndCptr;
        if (*StartCptr) {
          StartCptr++;
        }
      }
    }
  }

  fprintf (MakeFptr, "\n");

  //
  // Now go through the list of all NonFFS FVs they specified and search for
  // a [build.fv.$(FV)] or [build.fv] command and emit the commands to the
  // output makefile. Add them to the "fvs" target as well.
  //
  if (mNonFfsFVList != NULL) {
    fprintf (MakeFptr, "fvs ::");
    FVPtr = mNonFfsFVList;
    while (FVPtr != NULL) {
      fprintf (MakeFptr, " %s%s.fv", FVDir, FVPtr->FVFileName);
      FVPtr = FVPtr->Next;
    }

    fprintf (MakeFptr, "\n\n");
    FVPtr = mNonFfsFVList;
    while (FVPtr != NULL) {
      //
      // Save the position in the file
      //
      DSCFileSavePosition (DSC);
      //
      // first try to find a build section specific for this fv.
      //
      sprintf (Str, "build.fv.%s", FVPtr->FVFileName);
      Section = DSCFileFindSection (DSC, Str);
      if (Section == NULL) {
        sprintf (Str, "build.fv");
        Section = DSCFileFindSection (DSC, Str);
      }

      if (Section == NULL) {
        Warning (
          NULL,
          0,
          0,
          NULL,
          "No [build.fv.%s] nor [%s] section found in description file for building %s",
          FVPtr->FVFileName,
          Str,
          FVPtr->FVFileName
          );
      } else {
        //
        // Add a symbol for the FV filename
        //
        UpperCaseString (FVPtr->FVFileName);
        AddSymbol (FV_FILENAME, FVPtr->FVFileName, SYM_LOCAL | SYM_OVERWRITE);
        AddSymbol (EFI_BASE_ADDRESS, FVPtr->BaseAddress, SYM_LOCAL | SYM_OVERWRITE);

        //
        // Now copy the build commands from the section to the makefile
        //
        while (DSCFileGetLine (DSC, Line, sizeof (Line)) != NULL) {

⌨️ 快捷键说明

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