+++ /dev/null
-/*++\r
-\r
-Copyright (c) 2004 - 2010, Intel Corporation. All rights reserved.<BR>\r
-This program and the accompanying materials \r
-are licensed and made available under the terms and conditions of the BSD License \r
-which accompanies this distribution. The full text of the license may be found at \r
-http://opensource.org/licenses/bsd-license.php \r
- \r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
-\r
-Module Name:\r
-\r
- FWVolume.c\r
-\r
-Abstract:\r
-\r
- This module contains functionality to keep track of files destined for\r
- multiple firmware volues. It saves them up, and when told to, dumps the\r
- file names out to some files used as input to other utilities that\r
- actually generate the FVs.\r
-\r
---*/\r
-\r
-#include <windows.h> // for max_path definition\r
-#include <stdio.h>\r
-#include <string.h>\r
-#include <stdlib.h> // for malloc()\r
-#include "Common.h"\r
-#include "DSCFile.h"\r
-#include "FWVolume.h"\r
-\r
-#define FV_INF_DIR "FV_INF_DIR" // symbol for where we create the FV INF file\r
-#define FV_FILENAME "FV_FILENAME" // symbol for the current FV.INF filename\r
-#define EFI_BASE_ADDRESS "EFI_BASE_ADDRESS"\r
-#define DEFAULT_FV_INF_DIR "FV" // default dir for where we create the FV INF file\r
-#define DEFAULT_FV_DIR "$(BUILD_DIR)" // where the FV file comes from\r
-\r
-typedef struct {\r
- char *ComponentType;\r
- char *Extension;\r
-} COMP_TYPE_EXTENSION;\r
-\r
-//\r
-// Use a linked list of these to keep track of all the FV names used\r
-//\r
-typedef struct _FV_LIST {\r
- struct _FV_LIST *Next;\r
- char FVFileName[MAX_PATH];\r
- char BaseAddress[MAX_LINE_LEN];\r
- SMART_FILE *FVFilePtr;\r
- SMART_FILE *AprioriFilePtr;\r
- char *Processor;\r
- int ComponentsInstance; // highest [components.n] section with a file for this FV\r
-} FV_LIST;\r
-\r
-//\r
-// Use a linked list of these to keep track of all FFS files built. When\r
-// we're done, we turn the info into the FV INF files used to build the\r
-// firmware volumes.\r
-//\r
-typedef struct _FILE_LIST {\r
- struct _FILE_LIST *Next;\r
- char *FileName;\r
- char *BaseFileName;\r
- char *FVs; // from FV=x,y,z\r
- char *BaseName; // only needed for duplicate basename check\r
- char *Processor; // only needed for duplicate basename check\r
- char Apriori[100]; // of format "FVRecovery:1,FVMain:2" from APRIORI define\r
- char *Guid; // guid string\r
- int ComponentsInstance; // which [components.n] section it's in\r
-} FILE_LIST;\r
-\r
-typedef struct _LINKED_LIST {\r
- struct _LINKED_LIST *Next;\r
- void *Data;\r
-} LINKED_LIST;\r
-\r
-static FILE_LIST *mFileList;\r
-static FILE_LIST *mLastFile;\r
-static char *mXRefFileName = NULL;\r
-static FV_LIST *mNonFfsFVList = NULL;\r
-\r
-//\r
-// Whenever an FV name is referenced, then add it to our list of known\r
-// FV's using these.\r
-//\r
-static FV_LIST *mFVList = NULL;\r
-static FV_LIST *mFVListLast = NULL;\r
-\r
-//\r
-// We use this list so that from a given component type, we can determine\r
-// the name of the file on disk. For example, if we're given a file's\r
-// guid and base name, and we know it's a "bs_driver", then we can look\r
-// up "bs_driver" in this array and know that the file (after it's built)\r
-// name is GUID-BASENAME.DXE\r
-//\r
-static const COMP_TYPE_EXTENSION mCompTypeExtension[] = {\r
- {\r
- "bs_driver",\r
- ".dxe"\r
- },\r
- {\r
- "rt_driver",\r
- ".dxe"\r
- },\r
- {\r
- "sal_rt_driver",\r
- ".dxe"\r
- },\r
- {\r
- "security_core",\r
- ".sec"\r
- },\r
- {\r
- "pei_core",\r
- ".pei"\r
- },\r
- {\r
- "pic_peim",\r
- ".pei"\r
- },\r
- {\r
- "pe32_peim",\r
- ".pei"\r
- },\r
- {\r
- "relocatable_peim",\r
- ".pei"\r
- },\r
- {\r
- "binary",\r
- ".ffs"\r
- },\r
- {\r
- "application",\r
- ".app"\r
- },\r
- {\r
- "file",\r
- ".ffs"\r
- },\r
- {\r
- "fvimagefile",\r
- ".fvi"\r
- },\r
- {\r
- "rawfile",\r
- ".raw"\r
- },\r
- {\r
- "apriori",\r
- ".ffs"\r
- },\r
- {\r
- "combined_peim_driver",\r
- ".pei"\r
- },\r
- {\r
- NULL,\r
- NULL\r
- }\r
-};\r
-\r
-static\r
-void\r
-CFVFreeFileList (\r
- VOID\r
- );\r
-\r
-static\r
-char *\r
-UpperCaseString (\r
- char *Str\r
- );\r
-\r
-static\r
-BOOLEAN\r
-InSameFv (\r
- char *FVs1,\r
- char *FVs2\r
-);\r
-\r
-static\r
-void\r
-AddFirmwareVolumes (\r
- char *FVs,\r
- int ComponentsInstance\r
- );\r
-\r
-static\r
-BOOLEAN\r
-OrderInFvList (\r
- char *FvList,\r
- char *FvName,\r
- int *Order\r
- );\r
-\r
-int\r
-GetBaseAddress (\r
- char *Name,\r
- char *BaseAddress\r
- )\r
-{\r
- char *Start;\r
- char *Cptr;\r
- char CSave;\r
- char *Value;\r
-\r
- Start = Name;\r
- while (*Name && isspace (*Name)) {\r
- Name++;\r
- }\r
-\r
- if (!*Name) {\r
- return STATUS_ERROR;\r
- }\r
- //\r
- // Find the end of the name. Either space or a '='.\r
- //\r
- for (Value = Name; *Value && !isspace (*Value) && (*Value != '='); Value++)\r
- ;\r
- if (!*Value) {\r
- return STATUS_ERROR;\r
- }\r
- //\r
- // Look for the '='\r
- //\r
- Cptr = Value;\r
- while (*Value && (*Value != '=')) {\r
- Value++;\r
- }\r
-\r
- if (!*Value) {\r
- return STATUS_ERROR;\r
- }\r
- //\r
- // Now truncate the name\r
- //\r
- CSave = *Cptr;\r
- *Cptr = 0;\r
- if (_stricmp (Name, EFI_BASE_ADDRESS) != 0) {\r
- return STATUS_ERROR;\r
- }\r
-\r
- *Cptr = CSave;\r
- //\r
- // Skip over the = and then any spaces\r
- //\r
- Value++;\r
- while (*Value && isspace (*Value)) {\r
- Value++;\r
- }\r
- //\r
- // Find end of string, checking for quoted string\r
- //\r
- if (*Value == '\"') {\r
- Value++;\r
- for (Cptr = Value; *Cptr && *Cptr != '\"'; Cptr++)\r
- ;\r
- } else {\r
- for (Cptr = Value; *Cptr && !isspace (*Cptr); Cptr++)\r
- ;\r
- }\r
- //\r
- // Null terminate the value string\r
- //\r
- CSave = *Cptr;\r
- *Cptr = 0;\r
- strcpy (BaseAddress, Value);\r
- *Cptr = CSave;\r
-\r
- return STATUS_SUCCESS;\r
-}\r
-\r
-int\r
-CFVAddFVFile (\r
- char *Name,\r
- char *ComponentType,\r
- char *FVs,\r
- int ComponentsInstance,\r
- char *FFSExt,\r
- char *Processor,\r
- char *Apriori,\r
- char *BaseName,\r
- char *Guid\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Add a file to the list of files in one or more firmware volumes.\r
-\r
-Arguments:\r
-\r
- Name - $(FILE_GUID)-$(BASE_NAME), or filename\r
- ComponentType - type of component being added. Required so we know the\r
- resultant file name after it has been built\r
- FVs - string of commma-separated FVs that the given file is\r
- to be added to. For example, FVs="FV0001,FV0002"\r
- FFSExt - FFS filename extension of the file after it has been built.\r
- This is passed in to us in case we don't know the default\r
- filename extension based on the component type.\r
- Processor - the target processor which the FV is being built for\r
- Apriori - pointer to the definition of APRIORI. For example APRIORI="FvRecovery:1,FvMain:4"\r
-\r
-Returns:\r
-\r
- STATUS_SUCCESS if successful\r
-\r
---*/\r
-{\r
- FILE_LIST *Ptr;\r
- char FileName[MAX_PATH];\r
- char Str[MAX_PATH];\r
- int i;\r
- char *Sym;\r
-\r
- // If they provided a filename extension for this type of file, then use it.\r
- // If they did not provide a filename extension, search our list for a\r
- // matching component type and use the extension appropriate for this\r
- // component type.\r
- //\r
- if (FFSExt == NULL) {\r
- //\r
- // They didn't give us a filename extension. Figure it out from the\r
- // component type.\r
- //\r
- for (i = 0; mCompTypeExtension[i].ComponentType != NULL; i++) {\r
- if (_stricmp (ComponentType, mCompTypeExtension[i].ComponentType) == 0) {\r
- FFSExt = mCompTypeExtension[i].Extension;\r
- break;\r
- }\r
- }\r
- //\r
- // If we don't know the file extension, then error out. Just means\r
- // the need to define "FFS_EXT = raw" in the component INF file.\r
- //\r
- if (mCompTypeExtension[i].ComponentType == NULL) {\r
- Error (\r
- NULL,\r
- 0,\r
- 0,\r
- ComponentType,\r
- "unknown component type - must define FFS_EXT for built filename extension in component INF file"\r
- );\r
- return STATUS_ERROR;\r
- }\r
- }\r
- //\r
- // We now have all the parts to the FFS filename. Prepend the path to it if\r
- // it's not a full pathname.\r
- // See if they overrode the default base directory for the FV files.\r
- //\r
- if (!IsAbsolutePath (Name)) {\r
- Sym = GetSymbolValue (FV_DIR);\r
- if (Sym == NULL) {\r
- Sym = DEFAULT_FV_DIR;\r
- }\r
- //\r
- // Create the file path. Something like $(BUILD_DIR)\$(PROCESSOR)\$(GUID)-$(BASE_NAME).ext\r
- // If the extension is non-zero length, then make sure there's a dot in it.\r
- //\r
- if ((strlen (FFSExt) > 0) && (FFSExt[0] != '.')) {\r
- sprintf (Str, "%s\\%s\\%s.%s", Sym, Processor, Name, FFSExt);\r
- } else {\r
- sprintf (Str, "%s\\%s\\%s%s", Sym, Processor, Name, FFSExt);\r
- }\r
-\r
- ExpandSymbols (Str, FileName, sizeof (FileName), EXPANDMODE_NO_UNDEFS);\r
- } else {\r
- strcpy (FileName, Name);\r
- }\r
- //\r
- // Traverse the list of files we have so far and make sure we don't have\r
- // any duplicate basenames. If the base name and processor match, then we'll\r
- // have build issues, so don't allow it. We also don't allow the same file GUID\r
- // in the same FV which will cause boot time error if we allow this.\r
- //\r
- Ptr = mFileList;\r
- while (Ptr != NULL) {\r
- if ((Ptr->BaseName != NULL) && (BaseName != NULL) && (_stricmp (BaseName, Ptr->BaseName) == 0)) {\r
- if ((Ptr->Processor != NULL) && (Processor != NULL) && (_stricmp (Processor, Ptr->Processor) == 0)) {\r
- Error (NULL, 0, 0, BaseName, "duplicate base name specified");\r
- return STATUS_ERROR;\r
- }\r
- }\r
- \r
- if ((Ptr->Guid != NULL) && (Guid != NULL) && (_stricmp (Guid, Ptr->Guid) == 0)) {\r
- if ((Ptr->FVs != NULL) && (FVs != NULL) && (InSameFv (FVs, Ptr->FVs))) {\r
- Error (NULL, 0, 0, Guid, "duplicate Guid specified in the same FV for %s and %s", \r
- (Ptr->BaseName==NULL)?"Unknown":Ptr->BaseName, \r
- (BaseName==NULL)?"Unknown":BaseName);\r
- return STATUS_ERROR;\r
- }\r
- }\r
-\r
- Ptr = Ptr->Next;\r
- }\r
- //\r
- // Allocate a new structure so we can add this file to the list of\r
- // files.\r
- //\r
- Ptr = (FILE_LIST *) malloc (sizeof (FILE_LIST));\r
- if (Ptr == NULL) {\r
- Error (NULL, 0, 0, NULL, "failed to allocate memory");\r
- return STATUS_ERROR;\r
- }\r
-\r
- memset ((char *) Ptr, 0, sizeof (FILE_LIST));\r
- Ptr->FileName = (char *) malloc (strlen (FileName) + 1);\r
- if (Ptr->FileName == NULL) {\r
- Error (NULL, 0, 0, NULL, "failed to allocate memory");\r
- return STATUS_ERROR;\r
- }\r
-\r
- strcpy (Ptr->FileName, FileName);\r
- Ptr->ComponentsInstance = ComponentsInstance;\r
- //\r
- // Allocate memory to save the FV list if it's going into an FV.\r
- //\r
- if ((FVs != NULL) && (FVs[0] != 0)) {\r
- Ptr->FVs = (char *) malloc (strlen (FVs) + 1);\r
- if (Ptr->FVs == NULL) {\r
- Error (NULL, 0, 0, NULL, "failed to allocate memory");\r
- return STATUS_ERROR;\r
- }\r
-\r
- strcpy (Ptr->FVs, FVs);\r
- }\r
-\r
- Ptr->BaseFileName = (char *) malloc (strlen (Name) + 1);\r
- if (Ptr->BaseFileName == NULL) {\r
- Error (NULL, 0, 0, NULL, "failed to allocate memory");\r
- return STATUS_ERROR;\r
- }\r
-\r
- strcpy (Ptr->BaseFileName, Name);\r
- //\r
- // Allocate memory for the basename if they gave us one. May not have one\r
- // if the user is simply adding pre-existing binary files to the image.\r
- //\r
- if (BaseName != NULL) {\r
- Ptr->BaseName = (char *) malloc (strlen (BaseName) + 1);\r
- if (Ptr->BaseName == NULL) {\r
- Error (NULL, 0, 0, NULL, "failed to allocate memory");\r
- return STATUS_ERROR;\r
- }\r
-\r
- strcpy (Ptr->BaseName, BaseName);\r
- }\r
- //\r
- // Allocate memory for the processor name\r
- //\r
- if (Processor != NULL) {\r
- Ptr->Processor = (char *) malloc (strlen (Processor) + 1);\r
- if (Ptr->Processor == NULL) {\r
- Error (NULL, 0, 0, NULL, "failed to allocate memory");\r
- return STATUS_ERROR;\r
- }\r
-\r
- strcpy (Ptr->Processor, Processor);\r
- }\r
- //\r
- // Allocate memory for the guid name\r
- //\r
- if (Guid != NULL) {\r
- Ptr->Guid = (char *) malloc (strlen (Guid) + 1);\r
- if (Ptr->Guid == NULL) {\r
- Error (NULL, 0, 0, NULL, "failed to allocate memory");\r
- return STATUS_ERROR;\r
- }\r
-\r
- strcpy (Ptr->Guid, Guid);\r
- }\r
- //\r
- // If non-null apriori symbol, then save the apriori list for this file\r
- //\r
- if (Apriori != NULL) {\r
- strcpy (Ptr->Apriori, Apriori);\r
- }\r
-\r
- if (mFileList == NULL) {\r
- mFileList = Ptr;\r
- } else {\r
- mLastFile->Next = Ptr;\r
- }\r
-\r
- mLastFile = Ptr;\r
- //\r
- // Add these firmware volumes to the list of known firmware\r
- // volume names.\r
- //\r
- AddFirmwareVolumes (FVs, ComponentsInstance);\r
-\r
- return STATUS_SUCCESS;\r
-}\r
-\r
-void\r
-CFVConstructor (\r
- VOID\r
- )\r
-{\r
- mFileList = NULL;\r
- mLastFile = NULL;\r
-}\r
-\r
-void\r
-CFVDestructor (\r
- VOID\r
- )\r
-{\r
- CFVFreeFileList ();\r
- //\r
- // Free up our firmware volume list\r
- //\r
- while (mFVList != NULL) {\r
- mFVListLast = mFVList->Next;\r
- free (mFVList);\r
- mFVList = mFVListLast;\r
- }\r
-}\r
-\r
-static\r
-void\r
-CFVFreeFileList (\r
- VOID\r
- )\r
-{\r
- FILE_LIST *Next;\r
- while (mFileList != NULL) {\r
- if (mFileList->FileName != NULL) {\r
- free (mFileList->FileName);\r
- }\r
-\r
- if (mFileList->FVs != NULL) {\r
- free (mFileList->FVs);\r
- }\r
-\r
- free (mFileList->BaseFileName);\r
- if (mFileList->BaseName != NULL) {\r
- free (mFileList->BaseName);\r
- }\r
-\r
- if (mFileList->Processor != NULL) {\r
- free (mFileList->Processor);\r
- }\r
-\r
- if (mFileList->Guid != NULL) {\r
- free (mFileList->Guid);\r
- }\r
-\r
- Next = mFileList->Next;\r
- free (mFileList);\r
- mFileList = Next;\r
- }\r
-\r
- mFileList = NULL;\r
-}\r
-\r
-int\r
-CFVWriteInfFiles (\r
- DSC_FILE *DSC,\r
- FILE *MakeFptr\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- After processing all components in a DSC file, create the firmware\r
- volume INF files. We actually do a lot more here.\r
-\r
- * Create the FVxxx.inf file that is used by GenFvImage\r
- * Create the Apriori files for each firmware volume that requires one\r
- * Create makefile.out macros for FVxxx_FILES = FVxxx_FILES AnotherFile\r
- so you can do incremental builds of firmware volumes.\r
- * For each FV, emit its build commands to makefile.out\r
-\r
-Arguments:\r
-\r
- DSC - pointer to a DSC_FILE object to extract info from\r
- MakeFptr - pointer to the output makefile\r
-\r
-Returns:\r
-\r
- 0 if successful\r
- non-zero otherwise\r
-\r
---*/\r
-{\r
- FILE_LIST *FileListPtr;\r
- FV_LIST *FVList;\r
- FV_LIST *LastFVList;\r
- FV_LIST *FVPtr;\r
- SECTION *Section;\r
- char *StartCptr;\r
- char *EndCptr;\r
- char CSave;\r
- char Str[MAX_PATH];\r
- char Line[MAX_LINE_LEN];\r
- char ExpandedLine[MAX_LINE_LEN];\r
- char FVDir[MAX_PATH];\r
- FILE *XRefFptr;\r
- int AprioriCounter;\r
- int AprioriCount;\r
- int AprioriPosition;\r
- BOOLEAN AprioriFound;\r
- int ComponentsInstance;\r
- int ComponentCount;\r
-\r
- //\r
- // Use this to keep track of all the firmware volume names\r
- //\r
- FVList = NULL;\r
- LastFVList = NULL;\r
- //\r
- // See if they specified a FV directory to dump the FV files out to. If not,\r
- // then use the default. Then create the output directory.\r
- //\r
- StartCptr = GetSymbolValue (FV_INF_DIR);\r
- if (StartCptr == NULL) {\r
- ExpandSymbols (DEFAULT_FV_INF_DIR, FVDir, sizeof (FVDir), EXPANDMODE_NO_UNDEFS);\r
- } else {\r
- strcpy (FVDir, StartCptr);\r
- }\r
- //\r
- // Make sure the fv directory path ends in /\r
- //\r
- CSave = FVDir[strlen (FVDir) - 1];\r
- if ((CSave != '\\') && (CSave != '/')) {\r
- strcat (FVDir, "\\");\r
- }\r
- //\r
- // Traverse the list of all files, determine which FV each is in, then\r
- // write out the file's name to the output FVxxx.inf file.\r
- //\r
- for (FileListPtr = mFileList; FileListPtr != NULL; FileListPtr = FileListPtr->Next) {\r
- //\r
- // Parse all the "FV1,FV2..." in the FVs\r
- //\r
- if (FileListPtr->FVs != NULL) {\r
- //\r
- // Process each fv this file is in\r
- //\r
- StartCptr = FileListPtr->FVs;\r
- while (*StartCptr) {\r
- EndCptr = StartCptr;\r
- while (*EndCptr && (*EndCptr != ',')) {\r
- EndCptr++;\r
- }\r
-\r
- CSave = *EndCptr;\r
- *EndCptr = 0;\r
- //\r
- // Ok, we have a fv name, now see if we've already opened\r
- // an fv output file of this name.\r
- //\r
- for (FVPtr = FVList; FVPtr != NULL; FVPtr = FVPtr->Next) {\r
- if (_stricmp (FVPtr->FVFileName, StartCptr) == 0) {\r
- break;\r
- }\r
- }\r
- //\r
- // If we didn't find one, then create a new one\r
- //\r
- if (FVPtr == NULL) {\r
- //\r
- // Create a new one, add it to the list\r
- //\r
- FVPtr = (FV_LIST *) malloc (sizeof (FV_LIST));\r
- if (FVPtr == NULL) {\r
- Error (NULL, 0, 0, NULL, "failed to allocate memory for FV");\r
- return STATUS_ERROR;\r
- }\r
-\r
- memset ((char *) FVPtr, 0, sizeof (FV_LIST));\r
- //\r
- // Add it to the end of our list\r
- //\r
- if (FVList == NULL) {\r
- FVList = FVPtr;\r
- } else {\r
- LastFVList->Next = FVPtr;\r
- }\r
-\r
- LastFVList = FVPtr;\r
- //\r
- // Save the FV name in the FileName pointer so we can compare\r
- // for any future FV names specified.\r
- //\r
- strcpy (FVPtr->FVFileName, StartCptr);\r
-\r
- //\r
- // Add a symbol for the FV filename\r
- //\r
- UpperCaseString (FVPtr->FVFileName);\r
- AddSymbol (FV_FILENAME, FVPtr->FVFileName, SYM_LOCAL | SYM_OVERWRITE);\r
- //\r
- // Now create the FVx.inf filename from the fv name and\r
- // default filename extension. Dump it in the FV directory\r
- // as well.\r
- //\r
- strcpy (Str, FVDir);\r
- strcat (Str, FVPtr->FVFileName);\r
- strcat (Str, ".inf");\r
- //\r
- // Create the directory path for our new fv.inf output file.\r
- //\r
- MakeFilePath (Str);\r
- if ((FVPtr->FVFilePtr = SmartOpen (Str)) == NULL) {\r
- Error (NULL, 0, 0, Str, "could not open FV output file");\r
- return STATUS_ERROR;\r
- }\r
- //\r
- // Now copy the [fv.$(FV).options] to the fv INF file\r
- //\r
- sprintf (Str, "fv.%s.options", StartCptr);\r
- Section = DSCFileFindSection (DSC, Str);\r
- if (Section != NULL) {\r
- SmartWrite (FVPtr->FVFilePtr, "[options]\n");\r
- while (DSCFileGetLine (DSC, Line, sizeof (Line)) != NULL) {\r
- ExpandSymbols (Line, ExpandedLine, sizeof (ExpandedLine), 0);\r
- SmartWrite (FVPtr->FVFilePtr, ExpandedLine);\r
- GetBaseAddress (ExpandedLine, FVPtr->BaseAddress);\r
- }\r
- } else {\r
- Error (NULL, 0, 0, Str, "could not find FV section in description file");\r
- }\r
- //\r
- // Copy the [fv.$(FV).attributes] to the fv INF file\r
- //\r
- sprintf (Str, "fv.%s.attributes", StartCptr);\r
- Section = DSCFileFindSection (DSC, Str);\r
- if (Section != NULL) {\r
- SmartWrite (FVPtr->FVFilePtr, "[attributes]\n");\r
- while (DSCFileGetLine (DSC, Line, sizeof (Line)) != NULL) {\r
- ExpandSymbols (Line, ExpandedLine, sizeof (ExpandedLine), 0);\r
- SmartWrite (FVPtr->FVFilePtr, ExpandedLine);\r
- }\r
- } else {\r
- Error (NULL, 0, 0, Str, "Could not find FV section in description file");\r
- }\r
- //\r
- // Start the files section\r
- //\r
- SmartWrite (FVPtr->FVFilePtr, "\n[files]\n");\r
- }\r
- //\r
- // Now write the FV filename to the FV.inf file. Prepend $(PROCESSOR) on\r
- // it.\r
- //\r
- sprintf (ExpandedLine, "EFI_FILE_NAME = %s\n", FileListPtr->FileName);\r
- SmartWrite (FVPtr->FVFilePtr, ExpandedLine);\r
-\r
- //\r
- // Next FV on the FV list\r
- //\r
- *EndCptr = CSave;\r
- StartCptr = EndCptr;\r
- if (*StartCptr) {\r
- StartCptr++;\r
- }\r
- }\r
- }\r
- }\r
- //\r
- // Now we walk the list of firmware volumes and create the APRIORI list\r
- // file for it .\r
- //\r
- for (FVPtr = FVList; FVPtr != NULL; FVPtr = FVPtr->Next) {\r
- //\r
- // Run through all the files and count up how many are to be\r
- // added to the apriori list for this FV. Then when we're done\r
- // we'll make sure we processed them all. We do this in case they\r
- // skipped an apriori index for a given FV.\r
- //\r
- AprioriCount = 0;\r
- for (FileListPtr = mFileList; FileListPtr != NULL; FileListPtr = FileListPtr->Next) {\r
- if (OrderInFvList (FileListPtr->Apriori, FVPtr->FVFileName, &AprioriPosition)) {\r
- //\r
- // Emit an error if the index was 0, or they didn't give one.\r
- //\r
- if (AprioriPosition == 0) {\r
- Error (\r
- GetSymbolValue (DSC_FILENAME),\r
- 1,\r
- 0,\r
- "apriori indexes are 1-based",\r
- "component %s:APRIORI=%s",\r
- FileListPtr->BaseName,\r
- FileListPtr->Apriori\r
- );\r
- } else {\r
- AprioriCount++;\r
- }\r
-\r
- }\r
- }\r
- //\r
- // Now scan the files as we increment our apriori index\r
- //\r
- AprioriCounter = 0;\r
- do {\r
- AprioriFound = 0;\r
- AprioriCounter++;\r
- for (FileListPtr = mFileList; FileListPtr != NULL; FileListPtr = FileListPtr->Next) {\r
- //\r
- // If in the apriori list for this fv, print the name. Open the\r
- // file first if we have to.\r
- //\r
- if ((FileListPtr->Apriori[0] != 0) &&\r
- (OrderInFvList (FileListPtr->Apriori, FVPtr->FVFileName, &AprioriPosition))\r
- ) {\r
- if (AprioriPosition == AprioriCounter) {\r
- //\r
- // If we've already found one for this index, emit an error. Decrement the\r
- // count of how files we are to process so we don't emit another error for\r
- // a miscount below.\r
- //\r
- if (AprioriFound) {\r
- Error (\r
- GetSymbolValue (DSC_FILENAME),\r
- 1,\r
- 0,\r
- "duplicate apriori index found",\r
- "%s:%d",\r
- FVPtr->FVFileName,\r
- AprioriCounter\r
- );\r
- AprioriCount--;\r
- }\r
-\r
- AprioriFound = 1;\r
- //\r
- // Open the apriori output file if we haven't already\r
- //\r
- if (FVPtr->AprioriFilePtr == NULL) {\r
- strcpy (Str, FVDir);\r
- strcat (Str, FVPtr->FVFileName);\r
- strcat (Str, ".apr");\r
- if ((FVPtr->AprioriFilePtr = SmartOpen (Str)) == NULL) {\r
- Error (NULL, 0, 0, Str, "could not open output Apriori file for writing");\r
- return STATUS_ERROR;\r
- }\r
- }\r
- \r
- sprintf (ExpandedLine, "%s\n", FileListPtr->BaseFileName);\r
- SmartWrite (FVPtr->AprioriFilePtr, ExpandedLine);\r
- }\r
- }\r
- }\r
- } while (AprioriFound);\r
- //\r
- // See if they skipped an apriori position for this FV\r
- //\r
- if (AprioriCount != (AprioriCounter - 1)) {\r
- Error (\r
- GetSymbolValue (DSC_FILENAME),\r
- 1,\r
- 0,\r
- "apriori index skipped",\r
- "%s:%d",\r
- FVPtr->FVFileName,\r
- AprioriCounter\r
- );\r
- }\r
- }\r
- //\r
- // Traverse the list of all files again, and create a macro in the output makefile\r
- // that defines all the files in each fv. For example, for each FV file, create a line:\r
- // FV0001_FILES = $(FV_0001_FILES) xxxx-yyy.dxe.\r
- // This can then be used as a dependency in their makefile.\r
- // Also if they wanted us to dump a cross-reference, do that now.\r
- //\r
- if (mXRefFileName != NULL) {\r
- if ((XRefFptr = fopen (mXRefFileName, "w")) == NULL) {\r
- Message (\r
- 0,\r
- "Failed to open cross-reference file '%s' for writing\n",\r
- mXRefFileName\r
- );\r
- }\r
- } else {\r
- XRefFptr = NULL;\r
- }\r
-\r
- for (FileListPtr = mFileList; FileListPtr != NULL; FileListPtr = FileListPtr->Next) {\r
- //\r
- // Parse all the "FV1,FV2..." in the FV field that came from FV=FVa,FVb,... on the\r
- // component line in the DSC file.\r
- //\r
- if (FileListPtr->FVs != NULL) {\r
- //\r
- // If generating a cross-reference file, dump the data\r
- //\r
- if (XRefFptr != NULL) {\r
- if ((FileListPtr->Guid != NULL) && (FileListPtr->BaseName != NULL) && (FileListPtr->Processor)) {\r
- fprintf (\r
- XRefFptr,\r
- "%s %s %s\n",\r
- FileListPtr->Guid,\r
- FileListPtr->BaseName,\r
- FileListPtr->Processor\r
- );\r
- }\r
- }\r
- //\r
- // Convert to uppercase since we're going to use the name as a macro variable name\r
- // in the makefile.\r
- //\r
- UpperCaseString (FileListPtr->FVs);\r
- //\r
- // Process each FV this file is in to write fvxxx_FILES = $(fvxxx_FILES) Guid-BaseName.ffs\r
- //\r
- StartCptr = FileListPtr->FVs;\r
- while (*StartCptr) {\r
- EndCptr = StartCptr;\r
- while (*EndCptr && (*EndCptr != ',')) {\r
- EndCptr++;\r
- }\r
-\r
- CSave = *EndCptr;\r
- *EndCptr = 0;\r
- fprintf (\r
- MakeFptr,\r
- "%s_FILES = $(%s_FILES) %s\n",\r
- StartCptr,\r
- StartCptr,\r
- FileListPtr->FileName\r
- );\r
- //\r
- // Next FV on the FV list\r
- //\r
- *EndCptr = CSave;\r
- StartCptr = EndCptr;\r
- if (*StartCptr) {\r
- StartCptr++;\r
- }\r
- }\r
- }\r
- }\r
-\r
- fprintf (MakeFptr, "\n");\r
-\r
- //\r
- // Now go through the list of all NonFFS FVs they specified and search for\r
- // a [build.fv.$(FV)] or [build.fv] command and emit the commands to the\r
- // output makefile. Add them to the "fvs_0" target as well.\r
- //\r
- if (mNonFfsFVList != NULL) {\r
- fprintf (MakeFptr, "fvs_0 ::");\r
- FVPtr = mNonFfsFVList;\r
- while (FVPtr != NULL) {\r
- fprintf (MakeFptr, " %s%s.fv", FVDir, FVPtr->FVFileName);\r
- FVPtr = FVPtr->Next;\r
- }\r
-\r
- fprintf (MakeFptr, "\n\n");\r
- FVPtr = mNonFfsFVList;\r
- while (FVPtr != NULL) {\r
- //\r
- // Save the position in the file\r
- //\r
- DSCFileSavePosition (DSC);\r
- //\r
- // first try to find a build section specific for this fv.\r
- //\r
- sprintf (Str, "build.fv.%s", FVPtr->FVFileName);\r
- Section = DSCFileFindSection (DSC, Str);\r
- if (Section == NULL) {\r
- sprintf (Str, "build.fv");\r
- Section = DSCFileFindSection (DSC, Str);\r
- }\r
-\r
- if (Section == NULL) {\r
- Warning (\r
- NULL,\r
- 0,\r
- 0,\r
- NULL,\r
- "No [build.fv.%s] nor [%s] section found in description file for building %s",\r
- FVPtr->FVFileName,\r
- Str,\r
- FVPtr->FVFileName\r
- );\r
- } else {\r
- //\r
- // Add a symbol for the FV filename\r
- //\r
- UpperCaseString (FVPtr->FVFileName);\r
- AddSymbol (FV_FILENAME, FVPtr->FVFileName, SYM_LOCAL | SYM_OVERWRITE);\r
- AddSymbol (EFI_BASE_ADDRESS, FVPtr->BaseAddress, SYM_LOCAL | SYM_OVERWRITE);\r
-\r
- //\r
- // Now copy the build commands from the section to the makefile\r
- //\r
- while (DSCFileGetLine (DSC, Line, sizeof (Line)) != NULL) {\r
- ExpandSymbols (\r
- Line,\r
- ExpandedLine,\r
- sizeof (ExpandedLine),\r
- EXPANDMODE_NO_DESTDIR | EXPANDMODE_NO_SOURCEDIR\r
- );\r
-\r
- fprintf (MakeFptr, ExpandedLine);\r
- }\r
- }\r
-\r
- FVPtr = FVPtr->Next;\r
- DSCFileRestorePosition (DSC);\r
- }\r
- }\r
-\r
- //\r
- // Get the components count\r
- //\r
- ComponentCount = -1;\r
- for (FileListPtr = mFileList; FileListPtr != NULL; FileListPtr = FileListPtr->Next) {\r
- if (FileListPtr->ComponentsInstance > ComponentCount) {\r
- ComponentCount = FileListPtr->ComponentsInstance;\r
- }\r
- }\r
- ComponentCount++;\r
-\r
- //\r
- // Now print firmware volumes build targets fvs_0, fvs_1 etc.\r
- //\r
- for (ComponentsInstance = 0; ComponentsInstance < ComponentCount; ComponentsInstance++) {\r
- fprintf (MakeFptr, "fvs_%d ::", ComponentsInstance);\r
- for (FVPtr = mFVList; FVPtr != NULL; FVPtr = FVPtr->Next) {\r
- if (FVPtr->ComponentsInstance == ComponentsInstance) {\r
- fprintf (MakeFptr, " %s%s.fv", FVDir, FVPtr->FVFileName);\r
- }\r
- }\r
- fprintf (MakeFptr, "\n\n");\r
- }\r
- \r
- //\r
- // Create an "fvs" target that builds everything. It has to be a mix of \r
- // components and FV's in order. For example:\r
- // fvs :: components_0 fvs_0 components_1 fvs_1\r
- //\r
- fprintf (MakeFptr, "fvs ::");\r
- for (ComponentsInstance = 0; ComponentsInstance < ComponentCount; ComponentsInstance++) {\r
- fprintf (MakeFptr, " components_%d fvs_%d", ComponentsInstance, ComponentsInstance);\r
- }\r
- fprintf (MakeFptr, "\n\n");\r
-\r
- //\r
- // Create a "components" target for build convenience. It should\r
- // look something like:\r
- // components : components_0 components_1...\r
- //\r
- if (ComponentCount > 0) {\r
- fprintf (MakeFptr, "components :");\r
- for (ComponentsInstance = 0; ComponentsInstance < ComponentCount; ComponentsInstance++) {\r
- fprintf (MakeFptr, " components_%d", ComponentsInstance);\r
- }\r
-\r
- fprintf (MakeFptr, "\n\n");\r
- }\r
- //\r
- // Now go through the list of all FV's defined and search for\r
- // a [build.fv.$(FV)] or [build.fv] command and emit the commands to the\r
- // output makefile.\r
- //\r
- FVPtr = mFVList;\r
- while (FVPtr != NULL) {\r
- if (FVPtr->FVFileName[0]) {\r
- //\r
- // Save the position in the file\r
- //\r
- DSCFileSavePosition (DSC);\r
- //\r
- // First try to find a build section specific for this FV.\r
- //\r
- sprintf (Str, "build.fv.%s", FVPtr->FVFileName);\r
- Section = DSCFileFindSection (DSC, Str);\r
- if (Section == NULL) {\r
- sprintf (Str, "build.fv");\r
- Section = DSCFileFindSection (DSC, Str);\r
- }\r
-\r
- if (Section == NULL) {\r
- Error (\r
- NULL,\r
- 0,\r
- 0,\r
- NULL,\r
- "no [build.fv.%s] nor [%s] section found in description file for building %s",\r
- FVPtr->FVFileName,\r
- Str,\r
- FVPtr->FVFileName\r
- );\r
- } else {\r
- //\r
- // Add a symbol for the FV filename\r
- //\r
- UpperCaseString (FVPtr->FVFileName);\r
- AddSymbol (FV_FILENAME, FVPtr->FVFileName, SYM_LOCAL | SYM_OVERWRITE);\r
- AddSymbol (EFI_BASE_ADDRESS, FVPtr->BaseAddress, SYM_LOCAL | SYM_OVERWRITE);\r
-\r
- //\r
- // Now copy the build commands from the section to the makefile\r
- //\r
- while (DSCFileGetLine (DSC, Line, sizeof (Line)) != NULL) {\r
- ExpandSymbols (\r
- Line,\r
- ExpandedLine,\r
- sizeof (ExpandedLine),\r
- EXPANDMODE_NO_DESTDIR | EXPANDMODE_NO_SOURCEDIR\r
- );\r
- fprintf (MakeFptr, ExpandedLine);\r
- }\r
- }\r
-\r
- DSCFileRestorePosition (DSC);\r
- }\r
-\r
- FVPtr = FVPtr->Next;\r
- }\r
- //\r
- // Close all the files and free up the memory\r
- //\r
- while (FVList != NULL) {\r
- FVPtr = FVList->Next;\r
- if (FVList->FVFilePtr != NULL) {\r
- SmartClose (FVList->FVFilePtr);\r
- }\r
-\r
- if (FVList->AprioriFilePtr != NULL) {\r
- SmartClose (FVList->AprioriFilePtr);\r
- }\r
-\r
- free (FVList);\r
- FVList = FVPtr;\r
- }\r
-\r
- while (mNonFfsFVList != NULL) {\r
- FVPtr = mNonFfsFVList->Next;\r
- free (mNonFfsFVList);\r
- mNonFfsFVList = FVPtr;\r
- }\r
-\r
- if (XRefFptr != NULL) {\r
- fclose (XRefFptr);\r
- }\r
-\r
- return STATUS_SUCCESS;\r
-}\r
-\r
-int\r
-NonFFSFVWriteInfFiles (\r
- DSC_FILE *DSC,\r
- char *FileName\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Generate a Non FFS fv file. It can only some variables,\r
- or simply contains nothing except header.\r
-\r
-Arguments:\r
-\r
- DSC - pointer to a DSC_FILE object to extract info from\r
- FileName - pointer to the fv file\r
-\r
-Returns:\r
-\r
- STATUS_SUCCESS if successful\r
- non-STATUS_SUCCESS otherwise\r
-\r
---*/\r
-{\r
- FV_LIST *FVPtr;\r
- SECTION *Section;\r
- char *StartCptr;\r
- char *EndCptr;\r
- char CSave;\r
- char Str[MAX_PATH];\r
- char Line[MAX_LINE_LEN];\r
- char ExpandedLine[MAX_LINE_LEN];\r
- char FVDir[MAX_PATH];\r
-\r
- //\r
- // See if they specified a FV directory to dump the FV files out to. If not,\r
- // then use the default. Then create the output directory.\r
- //\r
- DSCFileSavePosition (DSC);\r
- StartCptr = GetSymbolValue (FV_INF_DIR);\r
- if (StartCptr == NULL) {\r
- ExpandSymbols (DEFAULT_FV_INF_DIR, FVDir, sizeof (FVDir), EXPANDMODE_NO_UNDEFS);\r
- } else {\r
- strcpy (FVDir, StartCptr);\r
- }\r
-\r
- //\r
- // Make sure the fv directory path ends in /\r
- //\r
- CSave = FVDir[strlen (FVDir) - 1];\r
- if ((CSave != '\\') && (CSave != '/')) {\r
- strcat (FVDir, "\\");\r
- }\r
-\r
- StartCptr = FileName;\r
- while (*StartCptr) {\r
- EndCptr = StartCptr;\r
- while (*EndCptr && (*EndCptr != ',')) {\r
- EndCptr++;\r
- }\r
-\r
- CSave = *EndCptr;\r
- *EndCptr = 0;\r
- //\r
- // Ok, we have a fv name, now see if we've already opened\r
- // an fv output file of this name.\r
- //\r
- for (FVPtr = mNonFfsFVList; FVPtr != NULL; FVPtr = FVPtr->Next) {\r
- if (_stricmp (FVPtr->FVFileName, StartCptr) == 0) {\r
- break;\r
- }\r
- }\r
- //\r
- // If there is already one with the same name, wrong\r
- //\r
- if (FVPtr != NULL) {\r
- DSCFileRestorePosition (DSC);\r
- return STATUS_ERROR;\r
- }\r
- //\r
- // Create a new one, add it to the list\r
- //\r
- FVPtr = (FV_LIST *) malloc (sizeof (FV_LIST));\r
- if (FVPtr == NULL) {\r
- Error (__FILE__, __LINE__, 0, "failed to allocate memory", NULL);\r
- DSCFileRestorePosition (DSC);\r
- return STATUS_ERROR;\r
- }\r
-\r
- memset ((char *) FVPtr, 0, sizeof (FV_LIST));\r
- FVPtr->Next = mNonFfsFVList;\r
- mNonFfsFVList = FVPtr;\r
- //\r
- // Save the FV name in the FileName pointer so we can compare\r
- // for any future FV names specified.\r
- //\r
- strcpy (FVPtr->FVFileName, StartCptr);\r
- //\r
- // Add a symbol for the FV filename\r
- //\r
- UpperCaseString (FVPtr->FVFileName);\r
- AddSymbol (FV_FILENAME, FVPtr->FVFileName, SYM_LOCAL | SYM_OVERWRITE);\r
-\r
- //\r
- // Now create the FVx.inf filename from the fv name and\r
- // default filename extension. Dump it in the FV directory\r
- // as well.\r
- //\r
- strcpy (Str, FVDir);\r
- strcat (Str, FVPtr->FVFileName);\r
- strcat (Str, ".inf");\r
- //\r
- // Create the directory path for our new fv.inf output file.\r
- //\r
- MakeFilePath (Str);\r
- if ((FVPtr->FVFilePtr = SmartOpen (Str)) == NULL) {\r
- Error (NULL, 0, 0, Str, "could not open FV output file");\r
- DSCFileRestorePosition (DSC);\r
- return STATUS_ERROR;\r
- }\r
- //\r
- // Now copy the [fv.fvfile.options] to the fv file\r
- //\r
- sprintf (Str, "fv.%s.options", StartCptr);\r
- Section = DSCFileFindSection (DSC, Str);\r
- if (Section != NULL) {\r
- SmartWrite (FVPtr->FVFilePtr, "[options]\n");\r
- while (DSCFileGetLine (DSC, Line, sizeof (Line)) != NULL) {\r
- ExpandSymbols (Line, ExpandedLine, sizeof (ExpandedLine), 0);\r
- SmartWrite (FVPtr->FVFilePtr, ExpandedLine);\r
- GetBaseAddress (ExpandedLine, FVPtr->BaseAddress);\r
- }\r
- } else {\r
- Warning (NULL, 0, 0, NULL, "Could not find FV section '%s' in description file", Str);\r
- }\r
- //\r
- // Copy the [fv.fvfile.attributes] to the fv file\r
- //\r
- sprintf (Str, "fv.%s.attributes", StartCptr);\r
- Section = DSCFileFindSection (DSC, Str);\r
- if (Section != NULL) {\r
- SmartWrite (FVPtr->FVFilePtr, "[attributes]\n");\r
- while (DSCFileGetLine (DSC, Line, sizeof (Line)) != NULL) {\r
- ExpandSymbols (Line, ExpandedLine, sizeof (ExpandedLine), 0);\r
- SmartWrite (FVPtr->FVFilePtr, ExpandedLine);\r
- }\r
- } else {\r
- Warning (NULL, 0, 0, NULL, "Could not find FV section '%s' in description file", Str);\r
- }\r
- //\r
- // Copy the [fv.fvfile.components] to the fv file\r
- //\r
- sprintf (Str, "fv.%s.components", StartCptr);\r
- Section = DSCFileFindSection (DSC, Str);\r
- if (Section != NULL) {\r
- SmartWrite (FVPtr->FVFilePtr, "[components]\n");\r
- while (DSCFileGetLine (DSC, Line, sizeof (Line)) != NULL) {\r
- ExpandSymbols (Line, ExpandedLine, sizeof (ExpandedLine), 0);\r
- SmartWrite (FVPtr->FVFilePtr, ExpandedLine);\r
- }\r
- } else {\r
- //\r
- // An empty FV is allowed to contain nothing\r
- //\r
- }\r
- //\r
- // Close the file\r
- //\r
- SmartClose (FVPtr->FVFilePtr);\r
- //\r
- // Next FV in FileName\r
- //\r
- *EndCptr = CSave;\r
- StartCptr = EndCptr;\r
- if (*StartCptr) {\r
- StartCptr++;\r
- }\r
- }\r
-\r
- DSCFileRestorePosition (DSC);\r
- return STATUS_SUCCESS;\r
-}\r
-\r
-static\r
-void\r
-AddFirmwareVolumes (\r
- char *FVs,\r
- int ComponentsInstance\r
- )\r
-{\r
- FV_LIST *FvPtr;\r
- char *StartPtr;\r
- char *EndPtr;\r
- char SaveChar;\r
-\r
- if ((FVs != NULL) && (FVs[0] != 0)) {\r
- //\r
- // Extract each FV name from the string. It's from the DSC file "FV=FvRecover,FvMain"\r
- //\r
- StartPtr = FVs;\r
- while (*StartPtr != 0) {\r
- EndPtr = StartPtr;\r
- while (*EndPtr && (*EndPtr != ',')) {\r
- EndPtr++;\r
- }\r
-\r
- SaveChar = *EndPtr;\r
- *EndPtr = 0;\r
- //\r
- // Look through our list of known firmware volumes and see if we've\r
- // already added it.\r
- //\r
- for (FvPtr = mFVList; FvPtr != NULL; FvPtr = FvPtr->Next) {\r
- if (_stricmp (FvPtr->FVFileName, StartPtr) == 0) {\r
- break;\r
- }\r
- }\r
- //\r
- // If we didn't find a match, then create a new one\r
- //\r
- if (FvPtr == NULL) {\r
- FvPtr = malloc (sizeof (FV_LIST));\r
- if (FvPtr == NULL) {\r
- Error (__FILE__, __LINE__, 0, "application error", "memory allocation failed");\r
- return ;\r
- }\r
-\r
- memset (FvPtr, 0, sizeof (FV_LIST));\r
- strcpy (FvPtr->FVFileName, StartPtr);\r
- if (mFVList == NULL) {\r
- mFVList = FvPtr;\r
- } else {\r
- mFVListLast->Next = FvPtr;\r
- }\r
-\r
- mFVListLast = FvPtr;\r
- }\r
- //\r
- // If this component's section number is higher than that of this\r
- // FV, then set the FV's to it.\r
- //\r
- if (FvPtr->ComponentsInstance < ComponentsInstance) {\r
- FvPtr->ComponentsInstance = ComponentsInstance;\r
- }\r
- //\r
- // If we found then end of the FVs in the string, then we're done.\r
- // Always restore the original string's contents.\r
- //\r
- if (SaveChar != 0) {\r
- *EndPtr = SaveChar;\r
- StartPtr = EndPtr + 1;\r
- } else {\r
- StartPtr = EndPtr;\r
- }\r
- }\r
- }\r
-}\r
-\r
-static\r
-BOOLEAN\r
-OrderInFvList (\r
- char *FvList,\r
- char *FvName,\r
- int *Order\r
- )\r
-{\r
- //\r
- // Given FvList of format "FV_a,FV_b,FV_c" or "FV_a:1,FV_b:2" and\r
- // FvName of format "FV_c", determine if FvName is in FvList. If\r
- // FV_a:1 format, then return the value after the colon.\r
- //\r
- while (*FvList) {\r
- //\r
- // If it matches for the length of FvName...\r
- //\r
- if (_strnicmp (FvList, FvName, strlen (FvName)) == 0) {\r
- //\r
- // Then see if the match string in FvList is terminated at the\r
- // same length.\r
- //\r
- if ((FvList[strlen (FvName)] == ',') || (FvList[strlen (FvName)] == 0)) {\r
- *Order = 0;\r
- return TRUE;\r
- } else if (FvList[strlen (FvName)] == ':') {\r
- *Order = atoi (FvList + strlen (FvName) + 1);\r
- return TRUE;\r
- }\r
- }\r
- //\r
- // Skip to next FV in the comma-separated list\r
- //\r
- while ((*FvList != ',') && (*FvList != 0)) {\r
- FvList++;\r
- }\r
- //\r
- // Skip over comma\r
- //\r
- if (*FvList == ',') {\r
- FvList++;\r
- }\r
- }\r
-\r
- return FALSE;\r
-}\r
-\r
-static\r
-char *\r
-UpperCaseString (\r
- char *Str\r
- )\r
-{\r
- char *Cptr;\r
-\r
- for (Cptr = Str; *Cptr; Cptr++) {\r
- *Cptr = (char) toupper (*Cptr);\r
- }\r
-\r
- return Str;\r
-}\r
-\r
-static\r
-BOOLEAN\r
-InSameFv (\r
- char *FVs1,\r
- char *FVs2\r
-)\r
-{\r
- char *StartCptr1;\r
- char *StartCptr2;\r
- char *EndCptr1;\r
- char *EndCptr2;\r
- char CSave1;\r
- char CSave2;\r
- \r
- //\r
- // Process each FV in first FV list\r
- //\r
- StartCptr1 = FVs1;\r
- while (*StartCptr1) {\r
- EndCptr1 = StartCptr1;\r
- while (*EndCptr1 && (*EndCptr1 != ',')) {\r
- EndCptr1++;\r
- }\r
-\r
- CSave1 = *EndCptr1;\r
- *EndCptr1 = 0; \r
- \r
- if (*StartCptr1) {\r
- //\r
- // Process each FV in second FV list\r
- //\r
- StartCptr2 = FVs2;\r
- while (*StartCptr2) {\r
- EndCptr2 = StartCptr2;\r
- while (*EndCptr2 && (*EndCptr2 != ',')) {\r
- EndCptr2++;\r
- }\r
- \r
- CSave2 = *EndCptr2;\r
- *EndCptr2 = 0; \r
- \r
- if (_stricmp (StartCptr1, StartCptr2) == 0) {\r
- *EndCptr1 = CSave1;\r
- *EndCptr2 = CSave2;\r
- return TRUE;\r
- }\r
- \r
- //\r
- // Next FV on the second FV list\r
- //\r
- *EndCptr2 = CSave2;\r
- StartCptr2 = EndCptr2;\r
- if (*StartCptr2) {\r
- StartCptr2++;\r
- }\r
- } \r
- }\r
- \r
- //\r
- // Next FV on the first FV list\r
- //\r
- *EndCptr1 = CSave1;\r
- StartCptr1 = EndCptr1;\r
- if (*StartCptr1) {\r
- StartCptr1++;\r
- }\r
- } \r
- \r
- return FALSE;\r
-}\r
-\r
-int\r
-CFVSetXRefFileName (\r
- char *FileName\r
- )\r
-{\r
- mXRefFileName = FileName;\r
- return 0;\r
-}\r