]> git.proxmox.com Git - mirror_edk2.git/blame - EdkCompatibilityPkg/Sample/Tools/Source/ProcessDsc/FWVolume.c
Update the copyright notice format
[mirror_edk2.git] / EdkCompatibilityPkg / Sample / Tools / Source / ProcessDsc / FWVolume.c
CommitLineData
3eb9473e 1/*++\r
2\r
4b1e1121
HT
3Copyright (c) 2004 - 2007, Intel Corporation. All rights reserved.<BR>\r
4This program and the accompanying materials \r
3eb9473e 5are licensed and made available under the terms and conditions of the BSD License \r
6which accompanies this distribution. The full text of the license may be found at \r
7http://opensource.org/licenses/bsd-license.php \r
8 \r
9THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
10WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
11\r
12Module Name:\r
13\r
14 FWVolume.c\r
15\r
16Abstract:\r
17\r
18 This module contains functionality to keep track of files destined for\r
19 multiple firmware volues. It saves them up, and when told to, dumps the\r
20 file names out to some files used as input to other utilities that\r
21 actually generate the FVs.\r
22\r
23--*/\r
24\r
25#include <windows.h> // for max_path definition\r
26#include <stdio.h>\r
27#include <string.h>\r
28#include <stdlib.h> // for malloc()\r
29#include "Common.h"\r
30#include "DSCFile.h"\r
31#include "FWVolume.h"\r
32\r
33#define FV_INF_DIR "FV_INF_DIR" // symbol for where we create the FV INF file\r
34#define FV_FILENAME "FV_FILENAME" // symbol for the current FV.INF filename\r
35#define EFI_BASE_ADDRESS "EFI_BASE_ADDRESS"\r
36#define DEFAULT_FV_INF_DIR "FV" // default dir for where we create the FV INF file\r
37#define DEFAULT_FV_DIR "$(BUILD_DIR)" // where the FV file comes from\r
38#define MALLOC(size) malloc (size)\r
39#define FREE(ptr) free (ptr)\r
40\r
41//\r
42// Disable warning for unused function arguments\r
43//\r
44#pragma warning(disable : 4100)\r
45//\r
46// Disable warning for while(1) code\r
47//\r
48// #pragma warning (disable : 4127)\r
49//\r
50typedef struct {\r
51 char *ComponentType;\r
52 char *Extension;\r
53} COMP_TYPE_EXTENSION;\r
54\r
55//\r
56// Use a linked list of these to keep track of all the FV names used\r
57//\r
58typedef struct _FV_LIST {\r
59 struct _FV_LIST *Next;\r
60 char FVFileName[MAX_PATH];\r
61 char BaseAddress[MAX_LINE_LEN];\r
62 SMART_FILE *FVFilePtr;\r
63 SMART_FILE *AprioriFilePtr;\r
64 char *Processor;\r
65 int ComponentsInstance; // highest [components.n] section with a file for this FV\r
66} FV_LIST;\r
67\r
68//\r
69// Use a linked list of these to keep track of all FFS files built. When\r
70// we're done, we turn the info into the FV INF files used to build the\r
71// firmware volumes.\r
72//\r
73typedef struct _FILE_LIST {\r
74 struct _FILE_LIST *Next;\r
75 char *FileName;\r
76 char *BaseFileName;\r
77 char *FVs; // from FV=x,y,z\r
78 char *BaseName; // only needed for duplicate basename check\r
79 char *Processor; // only needed for duplicate basename check\r
80 char Apriori[100]; // of format "FVRecovery:1,FVMain:2" from APRIORI define\r
81 char *Guid; // guid string\r
82 int ComponentsInstance; // which [components.n] section it's in\r
83} FILE_LIST;\r
84\r
85typedef struct _LINKED_LIST {\r
86 struct _LINKED_LIST *Next;\r
87 void *Data;\r
88} LINKED_LIST;\r
89\r
90static FILE_LIST *mFileList;\r
91static FILE_LIST *mLastFile;\r
92static char *mXRefFileName = NULL;\r
93static FV_LIST *mNonFfsFVList = NULL;\r
94\r
95//\r
96// Whenever an FV name is referenced, then add it to our list of known\r
97// FV's using these.\r
98//\r
99static FV_LIST *mFVList = NULL;\r
100static FV_LIST *mFVListLast = NULL;\r
101\r
102//\r
103// We use this list so that from a given component type, we can determine\r
104// the name of the file on disk. For example, if we're given a file's\r
105// guid and base name, and we know it's a "bs_driver", then we can look\r
106// up "bs_driver" in this array and know that the file (after it's built)\r
107// name is GUID-BASENAME.DXE\r
108//\r
109static const COMP_TYPE_EXTENSION mCompTypeExtension[] = {\r
110 {\r
111 "bs_driver",\r
112 ".dxe"\r
113 },\r
114 {\r
115 "rt_driver",\r
116 ".dxe"\r
117 },\r
118 {\r
119 "sal_rt_driver",\r
120 ".dxe"\r
121 },\r
122 {\r
123 "security_core",\r
124 ".sec"\r
125 },\r
126 {\r
127 "pei_core",\r
128 ".pei"\r
129 },\r
130 {\r
131 "pic_peim",\r
132 ".pei"\r
133 },\r
134 {\r
135 "pe32_peim",\r
136 ".pei"\r
137 },\r
138 {\r
139 "relocatable_peim",\r
140 ".pei"\r
141 },\r
142 {\r
143 "binary",\r
144 ".ffs"\r
145 },\r
146 {\r
147 "application",\r
148 ".app"\r
149 },\r
150 {\r
151 "file",\r
152 ".ffs"\r
153 },\r
154 {\r
155 "fvimagefile",\r
156 ".fvi"\r
157 },\r
158 {\r
159 "rawfile",\r
160 ".raw"\r
161 },\r
162 {\r
163 "apriori",\r
164 ".ffs"\r
165 },\r
166 {\r
167 "combined_peim_driver",\r
168 ".pei"\r
169 },\r
170 {\r
171 NULL,\r
172 NULL\r
173 }\r
174};\r
175\r
176static\r
177void\r
178CFVFreeFileList (\r
179 VOID\r
180 );\r
181\r
182static\r
183char *\r
184UpperCaseString (\r
185 char *Str\r
186 );\r
187\r
188static\r
189BOOLEAN\r
190InSameFv (\r
191 char *FVs1,\r
192 char *FVs2\r
193);\r
194\r
195static\r
196void\r
197AddFirmwareVolumes (\r
198 char *FVs,\r
199 int ComponentsInstance,\r
200 FILE_LIST *FileListPtr\r
201 );\r
202\r
203static\r
204BOOLEAN\r
205OrderInFvList (\r
206 char *FvList,\r
207 char *FvName,\r
208 int *Order\r
209 );\r
210\r
211int\r
212GetBaseAddress (\r
213 char *Name,\r
214 char *BaseAddress\r
215 )\r
216{\r
217 char *Start;\r
218 char *Cptr;\r
219 char CSave;\r
220 char *Value;\r
221\r
222 Start = Name;\r
223 while (*Name && isspace (*Name)) {\r
224 Name++;\r
225 }\r
226\r
227 if (!*Name) {\r
228 return STATUS_ERROR;\r
229 }\r
230 //\r
231 // Find the end of the name. Either space or a '='.\r
232 //\r
233 for (Value = Name; *Value && !isspace (*Value) && (*Value != '='); Value++)\r
234 ;\r
235 if (!*Value) {\r
236 return STATUS_ERROR;\r
237 }\r
238 //\r
239 // Look for the '='\r
240 //\r
241 Cptr = Value;\r
242 while (*Value && (*Value != '=')) {\r
243 Value++;\r
244 }\r
245\r
246 if (!*Value) {\r
247 return STATUS_ERROR;\r
248 }\r
249 //\r
250 // Now truncate the name\r
251 //\r
252 CSave = *Cptr;\r
253 *Cptr = 0;\r
254 if (_stricmp (Name, EFI_BASE_ADDRESS) != 0) {\r
255 return STATUS_ERROR;\r
256 }\r
257\r
258 *Cptr = CSave;\r
259 //\r
260 // Skip over the = and then any spaces\r
261 //\r
262 Value++;\r
263 while (*Value && isspace (*Value)) {\r
264 Value++;\r
265 }\r
266 //\r
267 // Find end of string, checking for quoted string\r
268 //\r
269 if (*Value == '\"') {\r
270 Value++;\r
271 for (Cptr = Value; *Cptr && *Cptr != '\"'; Cptr++)\r
272 ;\r
273 } else {\r
274 for (Cptr = Value; *Cptr && !isspace (*Cptr); Cptr++)\r
275 ;\r
276 }\r
277 //\r
278 // Null terminate the value string\r
279 //\r
280 CSave = *Cptr;\r
281 *Cptr = 0;\r
282 strcpy (BaseAddress, Value);\r
283 *Cptr = CSave;\r
284\r
285 return STATUS_SUCCESS;\r
286}\r
287\r
288int\r
289CFVAddFVFile (\r
290 char *Name,\r
291 char *ComponentType,\r
292 char *FVs,\r
293 int ComponentsInstance,\r
294 char *FFSExt,\r
295 char *Processor,\r
296 char *Apriori,\r
297 char *BaseName,\r
298 char *Guid\r
299 )\r
300/*++\r
301\r
302Routine Description:\r
303\r
304 Add a file to the list of files in one or more firmware volumes.\r
305\r
306Arguments:\r
307\r
308 Name - $(FILE_GUID)-$(BASE_NAME), or filename\r
309 ComponentType - type of component being added. Required so we know the\r
310 resultant file name after it has been built\r
311 FVs - string of commma-separated FVs that the given file is\r
312 to be added to. For example, FVs="FV0001,FV0002"\r
313 FFSExt - FFS filename extension of the file after it has been built.\r
314 This is passed in to us in case we don't know the default\r
315 filename extension based on the component type.\r
316 Processor - the target processor which the FV is being built for\r
317 Apriori - pointer to the definition of APRIORI. For example APRIORI="FvRecovery:1,FvMain:4"\r
318\r
319Returns:\r
320\r
321 STATUS_SUCCESS if successful\r
322\r
323--*/\r
324{\r
325 FILE_LIST *Ptr;\r
326 char FileName[MAX_PATH];\r
327 char Str[MAX_PATH];\r
328 int i;\r
329 char *Sym;\r
330\r
331 // If they provided a filename extension for this type of file, then use it.\r
332 // If they did not provide a filename extension, search our list for a\r
333 // matching component type and use the extension appropriate for this\r
334 // component type.\r
335 //\r
336 if (FFSExt == NULL) {\r
337 //\r
338 // They didn't give us a filename extension. Figure it out from the\r
339 // component type.\r
340 //\r
341 for (i = 0; mCompTypeExtension[i].ComponentType != NULL; i++) {\r
342 if (_stricmp (ComponentType, mCompTypeExtension[i].ComponentType) == 0) {\r
343 FFSExt = mCompTypeExtension[i].Extension;\r
344 break;\r
345 }\r
346 }\r
347 //\r
348 // If we don't know the file extension, then error out. Just means\r
349 // the need to define "FFS_EXT = raw" in the component INF file.\r
350 //\r
351 if (mCompTypeExtension[i].ComponentType == NULL) {\r
352 Error (\r
353 NULL,\r
354 0,\r
355 0,\r
356 ComponentType,\r
357 "unknown component type - must define FFS_EXT for built filename extension in component INF file"\r
358 );\r
359 return STATUS_ERROR;\r
360 }\r
361 }\r
362 //\r
363 // We now have all the parts to the FFS filename. Prepend the path to it if\r
364 // it's not a full pathname.\r
365 // See if they overrode the default base directory for the FV files.\r
366 //\r
367 if (!IsAbsolutePath (Name)) {\r
368 Sym = GetSymbolValue (FV_DIR);\r
369 if (Sym == NULL) {\r
370 Sym = DEFAULT_FV_DIR;\r
371 }\r
372 //\r
373 // Create the file path. Something like $(BUILD_DIR)\$(PROCESSOR)\$(GUID)-$(BASE_NAME).ext\r
374 // If the extension is non-zero length, then make sure there's a dot in it.\r
375 //\r
376 if ((strlen (FFSExt) > 0) && (FFSExt[0] != '.')) {\r
377 sprintf (Str, "%s\\%s\\%s.%s", Sym, Processor, Name, FFSExt);\r
378 } else {\r
379 sprintf (Str, "%s\\%s\\%s%s", Sym, Processor, Name, FFSExt);\r
380 }\r
381\r
382 ExpandSymbols (Str, FileName, sizeof (FileName), EXPANDMODE_NO_UNDEFS);\r
383 } else {\r
384 strcpy (FileName, Name);\r
385 }\r
386 //\r
387 // Traverse the list of files we have so far and make sure we don't have\r
388 // any duplicate basenames. If the base name and processor match, then we'll\r
389 // have build issues, so don't allow it. We also don't allow the same file GUID\r
390 // in the same FV which will cause boot time error if we allow this.\r
391 //\r
392 Ptr = mFileList;\r
393 while (Ptr != NULL) {\r
394 if ((Ptr->BaseName != NULL) && (BaseName != NULL) && (_stricmp (BaseName, Ptr->BaseName) == 0)) {\r
395 if ((Ptr->Processor != NULL) && (Processor != NULL) && (_stricmp (Processor, Ptr->Processor) == 0)) {\r
396 Error (NULL, 0, 0, BaseName, "duplicate base name specified");\r
397 return STATUS_ERROR;\r
398 }\r
399 }\r
400 \r
401 if ((Ptr->Guid != NULL) && (Guid != NULL) && (_stricmp (Guid, Ptr->Guid) == 0)) {\r
402 if ((Ptr->FVs != NULL) && (FVs != NULL) && (InSameFv (FVs, Ptr->FVs))) {\r
403 Error (NULL, 0, 0, Guid, "duplicate Guid specified in the same FV for %s and %s", \r
404 (Ptr->BaseName==NULL)?"Unknown":Ptr->BaseName, \r
405 (BaseName==NULL)?"Unknown":BaseName);\r
406 return STATUS_ERROR;\r
407 }\r
408 }\r
409\r
410 Ptr = Ptr->Next;\r
411 }\r
412 //\r
413 // Allocate a new structure so we can add this file to the list of\r
414 // files.\r
415 //\r
416 Ptr = (FILE_LIST *) malloc (sizeof (FILE_LIST));\r
417 if (Ptr == NULL) {\r
418 Error (NULL, 0, 0, NULL, "failed to allocate memory");\r
419 return STATUS_ERROR;\r
420 }\r
421\r
422 memset ((char *) Ptr, 0, sizeof (FILE_LIST));\r
423 Ptr->FileName = (char *) malloc (strlen (FileName) + 1);\r
424 if (Ptr->FileName == NULL) {\r
425 Error (NULL, 0, 0, NULL, "failed to allocate memory");\r
426 return STATUS_ERROR;\r
427 }\r
428\r
429 strcpy (Ptr->FileName, FileName);\r
430 Ptr->ComponentsInstance = ComponentsInstance;\r
431 //\r
432 // Allocate memory to save the FV list if it's going into an FV.\r
433 //\r
434 if ((FVs != NULL) && (FVs[0] != 0)) {\r
435 Ptr->FVs = (char *) malloc (strlen (FVs) + 1);\r
436 if (Ptr->FVs == NULL) {\r
437 Error (NULL, 0, 0, NULL, "failed to allocate memory");\r
438 return STATUS_ERROR;\r
439 }\r
440\r
441 strcpy (Ptr->FVs, FVs);\r
442 }\r
443\r
444 Ptr->BaseFileName = (char *) malloc (strlen (Name) + 1);\r
445 if (Ptr->BaseFileName == NULL) {\r
446 Error (NULL, 0, 0, NULL, "failed to allocate memory");\r
447 return STATUS_ERROR;\r
448 }\r
449\r
450 strcpy (Ptr->BaseFileName, Name);\r
451 //\r
452 // Allocate memory for the basename if they gave us one. May not have one\r
453 // if the user is simply adding pre-existing binary files to the image.\r
454 //\r
455 if (BaseName != NULL) {\r
456 Ptr->BaseName = (char *) malloc (strlen (BaseName) + 1);\r
457 if (Ptr->BaseName == NULL) {\r
458 Error (NULL, 0, 0, NULL, "failed to allocate memory");\r
459 return STATUS_ERROR;\r
460 }\r
461\r
462 strcpy (Ptr->BaseName, BaseName);\r
463 }\r
464 //\r
465 // Allocate memory for the processor name\r
466 //\r
467 if (Processor != NULL) {\r
468 Ptr->Processor = (char *) malloc (strlen (Processor) + 1);\r
469 if (Ptr->Processor == NULL) {\r
470 Error (NULL, 0, 0, NULL, "failed to allocate memory");\r
471 return STATUS_ERROR;\r
472 }\r
473\r
474 strcpy (Ptr->Processor, Processor);\r
475 }\r
476 //\r
477 // Allocate memory for the guid name\r
478 //\r
479 if (Guid != NULL) {\r
480 Ptr->Guid = (char *) malloc (strlen (Guid) + 1);\r
481 if (Ptr->Guid == NULL) {\r
482 Error (NULL, 0, 0, NULL, "failed to allocate memory");\r
483 return STATUS_ERROR;\r
484 }\r
485\r
486 strcpy (Ptr->Guid, Guid);\r
487 }\r
488 //\r
489 // If non-null apriori symbol, then save the apriori list for this file\r
490 //\r
491 if (Apriori != NULL) {\r
492 strcpy (Ptr->Apriori, Apriori);\r
493 }\r
494\r
495 if (mFileList == NULL) {\r
496 mFileList = Ptr;\r
497 } else {\r
498 mLastFile->Next = Ptr;\r
499 }\r
500\r
501 mLastFile = Ptr;\r
502 //\r
503 // Add these firmware volumes to the list of known firmware\r
504 // volume names.\r
505 //\r
506 AddFirmwareVolumes (FVs, ComponentsInstance, Ptr);\r
507\r
508 return STATUS_SUCCESS;\r
509}\r
510\r
511void\r
512CFVConstructor (\r
513 VOID\r
514 )\r
515{\r
516 mFileList = NULL;\r
517 mLastFile = NULL;\r
518}\r
519\r
520void\r
521CFVDestructor (\r
522 VOID\r
523 )\r
524{\r
525 CFVFreeFileList ();\r
526 //\r
527 // Free up our firmware volume list\r
528 //\r
529 while (mFVList != NULL) {\r
530 mFVListLast = mFVList->Next;\r
531 FREE (mFVList);\r
532 mFVList = mFVListLast;\r
533 }\r
534}\r
535\r
536static\r
537void\r
538CFVFreeFileList (\r
539 VOID\r
540 )\r
541{\r
542 FILE_LIST *Next;\r
543 while (mFileList != NULL) {\r
544 if (mFileList->FileName != NULL) {\r
545 free (mFileList->FileName);\r
546 }\r
547\r
548 if (mFileList->FVs != NULL) {\r
549 free (mFileList->FVs);\r
550 }\r
551\r
552 free (mFileList->BaseFileName);\r
553 if (mFileList->BaseName != NULL) {\r
554 free (mFileList->BaseName);\r
555 }\r
556\r
557 if (mFileList->Processor != NULL) {\r
558 free (mFileList->Processor);\r
559 }\r
560\r
561 if (mFileList->Guid != NULL) {\r
562 free (mFileList->Guid);\r
563 }\r
564\r
565 Next = mFileList->Next;\r
566 free (mFileList);\r
567 mFileList = Next;\r
568 }\r
569\r
570 mFileList = NULL;\r
571}\r
572\r
573int\r
574CFVWriteInfFiles (\r
575 DSC_FILE *DSC,\r
576 FILE *MakeFptr\r
577 )\r
578/*++\r
579\r
580Routine Description:\r
581\r
582 After processing all components in a DSC file, create the firmware\r
583 volume INF files. We actually do a lot more here.\r
584\r
585 * Create the FVxxx.inf file that is used by GenFvImage\r
586 * Create the Apriori files for each firmware volume that requires one\r
587 * Create makefile.out macros for FVxxx_FILES = FVxxx_FILES AnotherFile\r
588 so you can do incremental builds of firmware volumes.\r
589 * For each FV, emit its build commands to makefile.out\r
590\r
591Arguments:\r
592\r
593 DSC - pointer to a DSC_FILE object to extract info from\r
594 MakeFptr - pointer to the output makefile\r
595\r
596Returns:\r
597\r
598 0 if successful\r
599 non-zero otherwise\r
600\r
601--*/\r
602{\r
603 FILE_LIST *FileListPtr;\r
604 FV_LIST *FVList;\r
605 FV_LIST *LastFVList;\r
606 FV_LIST *FVPtr;\r
607 SECTION *Section;\r
608 char *StartCptr;\r
609 char *EndCptr;\r
610 char CSave;\r
611 char Str[MAX_PATH];\r
612 char Line[MAX_LINE_LEN];\r
613 char ExpandedLine[MAX_LINE_LEN];\r
614 char FVDir[MAX_PATH];\r
615 FILE *XRefFptr;\r
616 int AprioriCounter;\r
617 int AprioriCount;\r
618 int AprioriPosition;\r
619 BOOLEAN AprioriFound;\r
620 int ComponentsInstance;\r
621 int ComponentCount;\r
622\r
623 //\r
624 // Use this to keep track of all the firmware volume names\r
625 //\r
626 FVList = NULL;\r
627 LastFVList = NULL;\r
628 //\r
629 // See if they specified a FV directory to dump the FV files out to. If not,\r
630 // then use the default. Then create the output directory.\r
631 //\r
632 StartCptr = GetSymbolValue (FV_INF_DIR);\r
633 if (StartCptr == NULL) {\r
634 ExpandSymbols (DEFAULT_FV_INF_DIR, FVDir, sizeof (FVDir), EXPANDMODE_NO_UNDEFS);\r
635 } else {\r
636 strcpy (FVDir, StartCptr);\r
637 }\r
638 //\r
639 // Make sure the fv directory path ends in /\r
640 //\r
641 CSave = FVDir[strlen (FVDir) - 1];\r
642 if ((CSave != '\\') && (CSave != '/')) {\r
643 strcat (FVDir, "\\");\r
644 }\r
645 //\r
646 // Traverse the list of all files, determine which FV each is in, then\r
647 // write out the file's name to the output FVxxx.inf file.\r
648 //\r
649 for (FileListPtr = mFileList; FileListPtr != NULL; FileListPtr = FileListPtr->Next) {\r
650 //\r
651 // Parse all the "FV1,FV2..." in the FVs\r
652 //\r
653 if (FileListPtr->FVs != NULL) {\r
654 //\r
655 // Process each fv this file is in\r
656 //\r
657 StartCptr = FileListPtr->FVs;\r
658 while (*StartCptr) {\r
659 EndCptr = StartCptr;\r
660 while (*EndCptr && (*EndCptr != ',')) {\r
661 EndCptr++;\r
662 }\r
663\r
664 CSave = *EndCptr;\r
665 *EndCptr = 0;\r
666 //\r
667 // Ok, we have a fv name, now see if we've already opened\r
668 // an fv output file of this name.\r
669 //\r
670 for (FVPtr = FVList; FVPtr != NULL; FVPtr = FVPtr->Next) {\r
671 if (_stricmp (FVPtr->FVFileName, StartCptr) == 0) {\r
672 break;\r
673 }\r
674 }\r
675 //\r
676 // If we didn't find one, then create a new one\r
677 //\r
678 if (FVPtr == NULL) {\r
679 //\r
680 // Create a new one, add it to the list\r
681 //\r
682 FVPtr = (FV_LIST *) malloc (sizeof (FV_LIST));\r
683 if (FVPtr == NULL) {\r
684 Error (NULL, 0, 0, NULL, "failed to allocate memory for FV");\r
685 return STATUS_ERROR;\r
686 }\r
687\r
688 memset ((char *) FVPtr, 0, sizeof (FV_LIST));\r
689 //\r
690 // Add it to the end of our list\r
691 //\r
692 if (FVList == NULL) {\r
693 FVList = FVPtr;\r
694 } else {\r
695 LastFVList->Next = FVPtr;\r
696 }\r
697\r
698 LastFVList = FVPtr;\r
699 //\r
700 // Save the FV name in the FileName pointer so we can compare\r
701 // for any future FV names specified.\r
702 //\r
703 strcpy (FVPtr->FVFileName, StartCptr);\r
704\r
705 //\r
706 // Add a symbol for the FV filename\r
707 //\r
708 UpperCaseString (FVPtr->FVFileName);\r
709 AddSymbol (FV_FILENAME, FVPtr->FVFileName, SYM_LOCAL | SYM_OVERWRITE);\r
710 //\r
711 // Now create the FVx.inf filename from the fv name and\r
712 // default filename extension. Dump it in the FV directory\r
713 // as well.\r
714 //\r
715 strcpy (Str, FVDir);\r
716 strcat (Str, FVPtr->FVFileName);\r
717 strcat (Str, ".inf");\r
718 //\r
719 // Create the directory path for our new fv.inf output file.\r
720 //\r
721 MakeFilePath (Str);\r
722 if ((FVPtr->FVFilePtr = SmartOpen (Str)) == NULL) {\r
723 Error (NULL, 0, 0, Str, "could not open FV output file");\r
724 return STATUS_ERROR;\r
725 }\r
726 //\r
727 // Now copy the [fv.$(FV).options] to the fv INF file\r
728 //\r
729 sprintf (Str, "fv.%s.options", StartCptr);\r
730 Section = DSCFileFindSection (DSC, Str);\r
731 if (Section != NULL) {\r
732 SmartWrite (FVPtr->FVFilePtr, "[options]\n");\r
733 while (DSCFileGetLine (DSC, Line, sizeof (Line)) != NULL) {\r
734 ExpandSymbols (Line, ExpandedLine, sizeof (ExpandedLine), 0);\r
735 SmartWrite (FVPtr->FVFilePtr, ExpandedLine);\r
736 GetBaseAddress (ExpandedLine, FVPtr->BaseAddress);\r
737 }\r
738 } else {\r
739 Error (NULL, 0, 0, Str, "could not find FV section in description file");\r
740 }\r
741 //\r
742 // Copy the [fv.$(FV).attributes] to the fv INF file\r
743 //\r
744 sprintf (Str, "fv.%s.attributes", StartCptr);\r
745 Section = DSCFileFindSection (DSC, Str);\r
746 if (Section != NULL) {\r
747 SmartWrite (FVPtr->FVFilePtr, "[attributes]\n");\r
748 while (DSCFileGetLine (DSC, Line, sizeof (Line)) != NULL) {\r
749 ExpandSymbols (Line, ExpandedLine, sizeof (ExpandedLine), 0);\r
750 SmartWrite (FVPtr->FVFilePtr, ExpandedLine);\r
751 }\r
752 } else {\r
753 Error (NULL, 0, 0, Str, "Could not find FV section in description file");\r
754 }\r
755 //\r
756 // Start the files section\r
757 //\r
758 SmartWrite (FVPtr->FVFilePtr, "\n[files]\n");\r
759 }\r
760 //\r
761 // Now write the FV filename to the FV.inf file. Prepend $(PROCESSOR) on\r
762 // it.\r
763 //\r
764 sprintf (ExpandedLine, "EFI_FILE_NAME = %s\n", FileListPtr->FileName);\r
765 SmartWrite (FVPtr->FVFilePtr, ExpandedLine);\r
766\r
767 //\r
768 // Next FV on the FV list\r
769 //\r
770 *EndCptr = CSave;\r
771 StartCptr = EndCptr;\r
772 if (*StartCptr) {\r
773 StartCptr++;\r
774 }\r
775 }\r
776 }\r
777 }\r
778 //\r
779 // Now we walk the list of firmware volumes and create the APRIORI list\r
780 // file for it .\r
781 //\r
782 for (FVPtr = FVList; FVPtr != NULL; FVPtr = FVPtr->Next) {\r
783 //\r
784 // Run through all the files and count up how many are to be\r
785 // added to the apriori list for this FV. Then when we're done\r
786 // we'll make sure we processed them all. We do this in case they\r
787 // skipped an apriori index for a given FV.\r
788 //\r
789 AprioriCount = 0;\r
790 for (FileListPtr = mFileList; FileListPtr != NULL; FileListPtr = FileListPtr->Next) {\r
791 if (OrderInFvList (FileListPtr->Apriori, FVPtr->FVFileName, &AprioriPosition)) {\r
792 //\r
793 // Emit an error if the index was 0, or they didn't give one.\r
794 //\r
795 if (AprioriPosition == 0) {\r
796 Error (\r
797 GetSymbolValue (DSC_FILENAME),\r
798 1,\r
799 0,\r
800 "apriori indexes are 1-based",\r
801 "component %s:APRIORI=%s",\r
802 FileListPtr->BaseName,\r
803 FileListPtr->Apriori\r
804 );\r
805 } else {\r
806 AprioriCount++;\r
807 }\r
808\r
809 }\r
810 }\r
811 //\r
812 // Now scan the files as we increment our apriori index\r
813 //\r
814 AprioriCounter = 0;\r
815 do {\r
816 AprioriFound = 0;\r
817 AprioriCounter++;\r
818 for (FileListPtr = mFileList; FileListPtr != NULL; FileListPtr = FileListPtr->Next) {\r
819 //\r
820 // If in the apriori list for this fv, print the name. Open the\r
821 // file first if we have to.\r
822 //\r
823 if ((FileListPtr->Apriori[0] != 0) &&\r
824 (OrderInFvList (FileListPtr->Apriori, FVPtr->FVFileName, &AprioriPosition))\r
825 ) {\r
826 if (AprioriPosition == AprioriCounter) {\r
827 //\r
828 // If we've already found one for this index, emit an error. Decrement the\r
829 // count of how files we are to process so we don't emit another error for\r
830 // a miscount below.\r
831 //\r
832 if (AprioriFound) {\r
833 Error (\r
834 GetSymbolValue (DSC_FILENAME),\r
835 1,\r
836 0,\r
837 "duplicate apriori index found",\r
838 "%s:%d",\r
839 FVPtr->FVFileName,\r
840 AprioriCounter\r
841 );\r
842 AprioriCount--;\r
843 }\r
844\r
845 AprioriFound = 1;\r
846 //\r
847 // Open the apriori output file if we haven't already\r
848 //\r
849 if (FVPtr->AprioriFilePtr == NULL) {\r
850 strcpy (Str, FVDir);\r
851 strcat (Str, FVPtr->FVFileName);\r
852 strcat (Str, ".apr");\r
853 if ((FVPtr->AprioriFilePtr = SmartOpen (Str)) == NULL) {\r
854 Error (NULL, 0, 0, Str, "could not open output Apriori file for writing");\r
855 return STATUS_ERROR;\r
856 }\r
857 }\r
858 \r
859 sprintf (ExpandedLine, "%s\n", FileListPtr->BaseFileName);\r
860 SmartWrite (FVPtr->AprioriFilePtr, ExpandedLine);\r
861 }\r
862 }\r
863 }\r
864 } while (AprioriFound);\r
865 //\r
866 // See if they skipped an apriori position for this FV\r
867 //\r
868 if (AprioriCount != (AprioriCounter - 1)) {\r
869 Error (\r
870 GetSymbolValue (DSC_FILENAME),\r
871 1,\r
872 0,\r
873 "apriori index skipped",\r
874 "%s:%d",\r
875 FVPtr->FVFileName,\r
876 AprioriCounter\r
877 );\r
878 }\r
879 }\r
880 //\r
881 // Traverse the list of all files again, and create a macro in the output makefile\r
882 // that defines all the files in each fv. For example, for each FV file, create a line:\r
883 // FV0001_FILES = $(FV_0001_FILES) xxxx-yyy.dxe.\r
884 // This can then be used as a dependency in their makefile.\r
885 // Also if they wanted us to dump a cross-reference, do that now.\r
886 //\r
887 if (mXRefFileName != NULL) {\r
888 if ((XRefFptr = fopen (mXRefFileName, "w")) == NULL) {\r
889 Message (\r
890 0,\r
891 "Failed to open cross-reference file '%s' for writing\n",\r
892 mXRefFileName\r
893 );\r
894 }\r
895 } else {\r
896 XRefFptr = NULL;\r
897 }\r
898\r
899 for (FileListPtr = mFileList; FileListPtr != NULL; FileListPtr = FileListPtr->Next) {\r
900 //\r
901 // Parse all the "FV1,FV2..." in the FV field that came from FV=FVa,FVb,... on the\r
902 // component line in the DSC file.\r
903 //\r
904 if (FileListPtr->FVs != NULL) {\r
905 //\r
906 // If generating a cross-reference file, dump the data\r
907 //\r
908 if (XRefFptr != NULL) {\r
909 if ((FileListPtr->Guid != NULL) && (FileListPtr->BaseName != NULL) && (FileListPtr->Processor)) {\r
910 fprintf (\r
911 XRefFptr,\r
912 "%s %s %s\n",\r
913 FileListPtr->Guid,\r
914 FileListPtr->BaseName,\r
915 FileListPtr->Processor\r
916 );\r
917 }\r
918 }\r
919 //\r
920 // Convert to uppercase since we're going to use the name as a macro variable name\r
921 // in the makefile.\r
922 //\r
923 UpperCaseString (FileListPtr->FVs);\r
924 //\r
925 // Process each FV this file is in to write fvxxx_FILES = $(fvxxx_FILES) Guid-BaseName.ffs\r
926 //\r
927 StartCptr = FileListPtr->FVs;\r
928 while (*StartCptr) {\r
929 EndCptr = StartCptr;\r
930 while (*EndCptr && (*EndCptr != ',')) {\r
931 EndCptr++;\r
932 }\r
933\r
934 CSave = *EndCptr;\r
935 *EndCptr = 0;\r
936 fprintf (\r
937 MakeFptr,\r
938 "%s_FILES = $(%s_FILES) %s\n",\r
939 StartCptr,\r
940 StartCptr,\r
941 FileListPtr->FileName\r
942 );\r
943 //\r
944 // Next FV on the FV list\r
945 //\r
946 *EndCptr = CSave;\r
947 StartCptr = EndCptr;\r
948 if (*StartCptr) {\r
949 StartCptr++;\r
950 }\r
951 }\r
952 }\r
953 }\r
954\r
955 fprintf (MakeFptr, "\n");\r
956\r
957 //\r
958 // Now go through the list of all NonFFS FVs they specified and search for\r
959 // a [build.fv.$(FV)] or [build.fv] command and emit the commands to the\r
960 // output makefile. Add them to the "fvs" target as well.\r
961 //\r
962 if (mNonFfsFVList != NULL) {\r
963 fprintf (MakeFptr, "fvs ::");\r
964 FVPtr = mNonFfsFVList;\r
965 while (FVPtr != NULL) {\r
966 fprintf (MakeFptr, " %s%s.fv", FVDir, FVPtr->FVFileName);\r
967 FVPtr = FVPtr->Next;\r
968 }\r
969\r
970 fprintf (MakeFptr, "\n\n");\r
971 FVPtr = mNonFfsFVList;\r
972 while (FVPtr != NULL) {\r
973 //\r
974 // Save the position in the file\r
975 //\r
976 DSCFileSavePosition (DSC);\r
977 //\r
978 // first try to find a build section specific for this fv.\r
979 //\r
980 sprintf (Str, "build.fv.%s", FVPtr->FVFileName);\r
981 Section = DSCFileFindSection (DSC, Str);\r
982 if (Section == NULL) {\r
983 sprintf (Str, "build.fv");\r
984 Section = DSCFileFindSection (DSC, Str);\r
985 }\r
986\r
987 if (Section == NULL) {\r
988 Warning (\r
989 NULL,\r
990 0,\r
991 0,\r
992 NULL,\r
993 "No [build.fv.%s] nor [%s] section found in description file for building %s",\r
994 FVPtr->FVFileName,\r
995 Str,\r
996 FVPtr->FVFileName\r
997 );\r
998 } else {\r
999 //\r
1000 // Add a symbol for the FV filename\r
1001 //\r
1002 UpperCaseString (FVPtr->FVFileName);\r
1003 AddSymbol (FV_FILENAME, FVPtr->FVFileName, SYM_LOCAL | SYM_OVERWRITE);\r
1004 AddSymbol (EFI_BASE_ADDRESS, FVPtr->BaseAddress, SYM_LOCAL | SYM_OVERWRITE);\r
1005\r
1006 //\r
1007 // Now copy the build commands from the section to the makefile\r
1008 //\r
1009 while (DSCFileGetLine (DSC, Line, sizeof (Line)) != NULL) {\r
1010 ExpandSymbols (\r
1011 Line,\r
1012 ExpandedLine,\r
1013 sizeof (ExpandedLine),\r
1014 EXPANDMODE_NO_DESTDIR | EXPANDMODE_NO_SOURCEDIR\r
1015 );\r
1016\r
1017 fprintf (MakeFptr, ExpandedLine);\r
1018 }\r
1019 }\r
1020\r
1021 FVPtr = FVPtr->Next;\r
1022 DSCFileRestorePosition (DSC);\r
1023 }\r
1024 }\r
1025 //\r
1026 // Go through our list of firmware volumes and create an "fvs" target that\r
1027 // builds everything. It has to be a mix of components and FV's in order.\r
1028 // For example: fvs : components_0 fv\fv001.fv fv\fv002.fv components_1 fv\fv003.fv\r
1029 //\r
1030 ComponentsInstance = 0;\r
1031 ComponentCount = 0;\r
1032 fprintf (MakeFptr, "fvs ::");\r
1033 for (;;) {\r
1034 //\r
1035 // First see if we have any components for this section. If we don't,\r
1036 // then we're done\r
1037 //\r
1038 for (FileListPtr = mFileList; FileListPtr != NULL; FileListPtr = FileListPtr->Next) {\r
1039 if (FileListPtr->ComponentsInstance == ComponentsInstance) {\r
1040 break;\r
1041 }\r
1042 }\r
1043\r
1044 if (FileListPtr == NULL) {\r
1045 break;\r
1046 }\r
1047\r
1048 fprintf (MakeFptr, " components_%d", ComponentsInstance);\r
1049 ComponentCount++;\r
1050 //\r
1051 // Now print any firmware volumes that match this components instance\r
1052 //\r
1053 for (FVPtr = mFVList; FVPtr != NULL; FVPtr = FVPtr->Next) {\r
1054 if (FVPtr->ComponentsInstance == ComponentsInstance) {\r
1055 fprintf (MakeFptr, " %s%s.fv", FVDir, FVPtr->FVFileName);\r
1056 }\r
1057 }\r
1058\r
1059 ComponentsInstance++;\r
1060 }\r
1061\r
1062 fprintf (MakeFptr, "\n\n");\r
1063\r
1064 //\r
1065 // Create a "components" target for build convenience. It should\r
1066 // look something like:\r
1067 // components : components_0 components_1...\r
1068 //\r
1069 if (ComponentCount > 0) {\r
1070 fprintf (MakeFptr, "components :");\r
1071 for (ComponentsInstance = 0; ComponentsInstance < ComponentCount; ComponentsInstance++) {\r
1072 fprintf (MakeFptr, " components_%d", ComponentsInstance);\r
1073 }\r
1074\r
1075 fprintf (MakeFptr, "\n\n");\r
1076 }\r
1077 //\r
1078 // Now go through the list of all FV's defined and search for\r
1079 // a [build.fv.$(FV)] or [build.fv] command and emit the commands to the\r
1080 // output makefile.\r
1081 //\r
1082 FVPtr = mFVList;\r
1083 while (FVPtr != NULL) {\r
1084 if (FVPtr->FVFileName[0]) {\r
1085 //\r
1086 // Save the position in the file\r
1087 //\r
1088 DSCFileSavePosition (DSC);\r
1089 //\r
1090 // First try to find a build section specific for this FV.\r
1091 //\r
1092 sprintf (Str, "build.fv.%s", FVPtr->FVFileName);\r
1093 Section = DSCFileFindSection (DSC, Str);\r
1094 if (Section == NULL) {\r
1095 sprintf (Str, "build.fv");\r
1096 Section = DSCFileFindSection (DSC, Str);\r
1097 }\r
1098\r
1099 if (Section == NULL) {\r
1100 Error (\r
1101 NULL,\r
1102 0,\r
1103 0,\r
1104 NULL,\r
1105 "no [build.fv.%s] nor [%s] section found in description file for building %s",\r
1106 FVPtr->FVFileName,\r
1107 Str,\r
1108 FVPtr->FVFileName\r
1109 );\r
1110 } else {\r
1111 //\r
1112 // Add a symbol for the FV filename\r
1113 //\r
1114 UpperCaseString (FVPtr->FVFileName);\r
1115 AddSymbol (FV_FILENAME, FVPtr->FVFileName, SYM_LOCAL | SYM_OVERWRITE);\r
1116 AddSymbol (EFI_BASE_ADDRESS, FVPtr->BaseAddress, SYM_LOCAL | SYM_OVERWRITE);\r
1117\r
1118 //\r
1119 // Now copy the build commands from the section to the makefile\r
1120 //\r
1121 while (DSCFileGetLine (DSC, Line, sizeof (Line)) != NULL) {\r
1122 ExpandSymbols (\r
1123 Line,\r
1124 ExpandedLine,\r
1125 sizeof (ExpandedLine),\r
1126 EXPANDMODE_NO_DESTDIR | EXPANDMODE_NO_SOURCEDIR\r
1127 );\r
1128 fprintf (MakeFptr, ExpandedLine);\r
1129 }\r
1130 }\r
1131\r
1132 DSCFileRestorePosition (DSC);\r
1133 }\r
1134\r
1135 FVPtr = FVPtr->Next;\r
1136 }\r
1137 //\r
1138 // Close all the files and free up the memory\r
1139 //\r
1140 while (FVList != NULL) {\r
1141 FVPtr = FVList->Next;\r
1142 if (FVList->FVFilePtr != NULL) {\r
1143 SmartClose (FVList->FVFilePtr);\r
1144 }\r
1145\r
1146 if (FVList->AprioriFilePtr != NULL) {\r
1147 SmartClose (FVList->AprioriFilePtr);\r
1148 }\r
1149\r
1150 free (FVList);\r
1151 FVList = FVPtr;\r
1152 }\r
1153\r
1154 while (mNonFfsFVList != NULL) {\r
1155 FVPtr = mNonFfsFVList->Next;\r
1156 free (mNonFfsFVList);\r
1157 mNonFfsFVList = FVPtr;\r
1158 }\r
1159\r
1160 if (XRefFptr != NULL) {\r
1161 fclose (XRefFptr);\r
1162 }\r
1163\r
1164 return STATUS_SUCCESS;\r
1165}\r
1166\r
1167int\r
1168NonFFSFVWriteInfFiles (\r
1169 DSC_FILE *DSC,\r
1170 char *FileName\r
1171 )\r
1172/*++\r
1173\r
1174Routine Description:\r
1175\r
1176 Generate a Non FFS fv file. It can only some variables,\r
1177 or simply contains nothing except header.\r
1178\r
1179Arguments:\r
1180\r
1181 DSC - pointer to a DSC_FILE object to extract info from\r
1182 FileName - pointer to the fv file\r
1183\r
1184Returns:\r
1185\r
1186 STATUS_SUCCESS if successful\r
1187 non-STATUS_SUCCESS otherwise\r
1188\r
1189--*/\r
1190{\r
1191 FV_LIST *FVPtr;\r
1192 SECTION *Section;\r
1193 char *StartCptr;\r
1194 char *EndCptr;\r
1195 char CSave;\r
1196 char Str[MAX_PATH];\r
1197 char Line[MAX_LINE_LEN];\r
1198 char ExpandedLine[MAX_LINE_LEN];\r
1199 char FVDir[MAX_PATH];\r
1200\r
1201 //\r
1202 // See if they specified a FV directory to dump the FV files out to. If not,\r
1203 // then use the default. Then create the output directory.\r
1204 //\r
1205 DSCFileSavePosition (DSC);\r
1206 StartCptr = GetSymbolValue (FV_INF_DIR);\r
1207 if (StartCptr == NULL) {\r
1208 ExpandSymbols (DEFAULT_FV_INF_DIR, FVDir, sizeof (FVDir), EXPANDMODE_NO_UNDEFS);\r
1209 } else {\r
1210 strcpy (FVDir, StartCptr);\r
1211 }\r
1212\r
1213 //\r
1214 // Make sure the fv directory path ends in /\r
1215 //\r
1216 CSave = FVDir[strlen (FVDir) - 1];\r
1217 if ((CSave != '\\') && (CSave != '/')) {\r
1218 strcat (FVDir, "\\");\r
1219 }\r
1220\r
1221 StartCptr = FileName;\r
1222 while (*StartCptr) {\r
1223 EndCptr = StartCptr;\r
1224 while (*EndCptr && (*EndCptr != ',')) {\r
1225 EndCptr++;\r
1226 }\r
1227\r
1228 CSave = *EndCptr;\r
1229 *EndCptr = 0;\r
1230 //\r
1231 // Ok, we have a fv name, now see if we've already opened\r
1232 // an fv output file of this name.\r
1233 //\r
1234 for (FVPtr = mNonFfsFVList; FVPtr != NULL; FVPtr = FVPtr->Next) {\r
1235 if (_stricmp (FVPtr->FVFileName, StartCptr) == 0) {\r
1236 break;\r
1237 }\r
1238 }\r
1239 //\r
1240 // If there is already one with the same name, wrong\r
1241 //\r
1242 if (FVPtr != NULL) {\r
1243 DSCFileRestorePosition (DSC);\r
1244 return STATUS_ERROR;\r
1245 }\r
1246 //\r
1247 // Create a new one, add it to the list\r
1248 //\r
1249 FVPtr = (FV_LIST *) malloc (sizeof (FV_LIST));\r
1250 if (FVPtr == NULL) {\r
1251 Error (__FILE__, __LINE__, 0, "failed to allocate memory", NULL);\r
1252 DSCFileRestorePosition (DSC);\r
1253 return STATUS_ERROR;\r
1254 }\r
1255\r
1256 memset ((char *) FVPtr, 0, sizeof (FV_LIST));\r
1257 FVPtr->Next = mNonFfsFVList;\r
1258 mNonFfsFVList = FVPtr;\r
1259 //\r
1260 // Save the FV name in the FileName pointer so we can compare\r
1261 // for any future FV names specified.\r
1262 //\r
1263 strcpy (FVPtr->FVFileName, StartCptr);\r
1264 //\r
1265 // Add a symbol for the FV filename\r
1266 //\r
1267 UpperCaseString (FVPtr->FVFileName);\r
1268 AddSymbol (FV_FILENAME, FVPtr->FVFileName, SYM_LOCAL | SYM_OVERWRITE);\r
1269\r
1270 //\r
1271 // Now create the FVx.inf filename from the fv name and\r
1272 // default filename extension. Dump it in the FV directory\r
1273 // as well.\r
1274 //\r
1275 strcpy (Str, FVDir);\r
1276 strcat (Str, FVPtr->FVFileName);\r
1277 strcat (Str, ".inf");\r
1278 //\r
1279 // Create the directory path for our new fv.inf output file.\r
1280 //\r
1281 MakeFilePath (Str);\r
1282 if ((FVPtr->FVFilePtr = SmartOpen (Str)) == NULL) {\r
1283 Error (NULL, 0, 0, Str, "could not open FV output file");\r
1284 DSCFileRestorePosition (DSC);\r
1285 return STATUS_ERROR;\r
1286 }\r
1287 //\r
1288 // Now copy the [fv.fvfile.options] to the fv file\r
1289 //\r
1290 sprintf (Str, "fv.%s.options", StartCptr);\r
1291 Section = DSCFileFindSection (DSC, Str);\r
1292 if (Section != NULL) {\r
1293 SmartWrite (FVPtr->FVFilePtr, "[options]\n");\r
1294 while (DSCFileGetLine (DSC, Line, sizeof (Line)) != NULL) {\r
1295 ExpandSymbols (Line, ExpandedLine, sizeof (ExpandedLine), 0);\r
1296 SmartWrite (FVPtr->FVFilePtr, ExpandedLine);\r
1297 GetBaseAddress (ExpandedLine, FVPtr->BaseAddress);\r
1298 }\r
1299 } else {\r
1300 Warning (NULL, 0, 0, NULL, "Could not find FV section '%s' in description file", Str);\r
1301 }\r
1302 //\r
1303 // Copy the [fv.fvfile.attributes] to the fv file\r
1304 //\r
1305 sprintf (Str, "fv.%s.attributes", StartCptr);\r
1306 Section = DSCFileFindSection (DSC, Str);\r
1307 if (Section != NULL) {\r
1308 SmartWrite (FVPtr->FVFilePtr, "[attributes]\n");\r
1309 while (DSCFileGetLine (DSC, Line, sizeof (Line)) != NULL) {\r
1310 ExpandSymbols (Line, ExpandedLine, sizeof (ExpandedLine), 0);\r
1311 SmartWrite (FVPtr->FVFilePtr, ExpandedLine);\r
1312 }\r
1313 } else {\r
1314 Warning (NULL, 0, 0, NULL, "Could not find FV section '%s' in description file", Str);\r
1315 }\r
1316 //\r
1317 // Copy the [fv.fvfile.components] to the fv file\r
1318 //\r
1319 sprintf (Str, "fv.%s.components", StartCptr);\r
1320 Section = DSCFileFindSection (DSC, Str);\r
1321 if (Section != NULL) {\r
1322 SmartWrite (FVPtr->FVFilePtr, "[components]\n");\r
1323 while (DSCFileGetLine (DSC, Line, sizeof (Line)) != NULL) {\r
1324 ExpandSymbols (Line, ExpandedLine, sizeof (ExpandedLine), 0);\r
1325 SmartWrite (FVPtr->FVFilePtr, ExpandedLine);\r
1326 }\r
1327 } else {\r
1328 //\r
1329 // An empty FV is allowed to contain nothing\r
1330 //\r
1331 }\r
1332 //\r
1333 // Close the file\r
1334 //\r
1335 SmartClose (FVPtr->FVFilePtr);\r
1336 //\r
1337 // Next FV in FileName\r
1338 //\r
1339 *EndCptr = CSave;\r
1340 StartCptr = EndCptr;\r
1341 if (*StartCptr) {\r
1342 StartCptr++;\r
1343 }\r
1344 }\r
1345\r
1346 DSCFileRestorePosition (DSC);\r
1347 return STATUS_SUCCESS;\r
1348}\r
1349\r
1350static\r
1351void\r
1352AddFirmwareVolumes (\r
1353 char *FVs,\r
1354 int ComponentsInstance,\r
1355 FILE_LIST *FileListPtr\r
1356 )\r
1357{\r
1358 FV_LIST *FvPtr;\r
1359 char *StartPtr;\r
1360 char *EndPtr;\r
1361 char SaveChar;\r
1362\r
1363 if ((FVs != NULL) && (FVs[0] != 0)) {\r
1364 //\r
1365 // Extract each FV name from the string. It's from the DSC file "FV=FvRecover,FvMain"\r
1366 //\r
1367 StartPtr = FVs;\r
1368 while (*StartPtr != 0) {\r
1369 EndPtr = StartPtr;\r
1370 while (*EndPtr && (*EndPtr != ',')) {\r
1371 EndPtr++;\r
1372 }\r
1373\r
1374 SaveChar = *EndPtr;\r
1375 *EndPtr = 0;\r
1376 //\r
1377 // Look through our list of known firmware volumes and see if we've\r
1378 // already added it.\r
1379 //\r
1380 for (FvPtr = mFVList; FvPtr != NULL; FvPtr = FvPtr->Next) {\r
1381 if (_stricmp (FvPtr->FVFileName, StartPtr) == 0) {\r
1382 break;\r
1383 }\r
1384 }\r
1385 //\r
1386 // If we didn't find a match, then create a new one\r
1387 //\r
1388 if (FvPtr == NULL) {\r
1389 FvPtr = MALLOC (sizeof (FV_LIST));\r
1390 if (FvPtr == NULL) {\r
1391 Error (__FILE__, __LINE__, 0, "application error", "memory allocation failed");\r
1392 return ;\r
1393 }\r
1394\r
1395 memset (FvPtr, 0, sizeof (FV_LIST));\r
1396 strcpy (FvPtr->FVFileName, StartPtr);\r
1397 if (mFVList == NULL) {\r
1398 mFVList = FvPtr;\r
1399 } else {\r
1400 mFVListLast->Next = FvPtr;\r
1401 }\r
1402\r
1403 mFVListLast = FvPtr;\r
1404 }\r
1405 //\r
1406 // If this component's section number is higher than that of this\r
1407 // FV, then set the FV's to it.\r
1408 //\r
1409 if (FvPtr->ComponentsInstance < ComponentsInstance) {\r
1410 FvPtr->ComponentsInstance = ComponentsInstance;\r
1411 }\r
1412 //\r
1413 // If we found then end of the FVs in the string, then we're done.\r
1414 // Always restore the original string's contents.\r
1415 //\r
1416 if (SaveChar != 0) {\r
1417 *EndPtr = SaveChar;\r
1418 StartPtr = EndPtr + 1;\r
1419 } else {\r
1420 StartPtr = EndPtr;\r
1421 }\r
1422 }\r
1423 }\r
1424}\r
1425\r
1426static\r
1427BOOLEAN\r
1428OrderInFvList (\r
1429 char *FvList,\r
1430 char *FvName,\r
1431 int *Order\r
1432 )\r
1433{\r
1434 //\r
1435 // Given FvList of format "FV_a,FV_b,FV_c" or "FV_a:1,FV_b:2" and\r
1436 // FvName of format "FV_c", determine if FvName is in FvList. If\r
1437 // FV_a:1 format, then return the value after the colon.\r
1438 //\r
1439 while (*FvList) {\r
1440 //\r
1441 // If it matches for the length of FvName...\r
1442 //\r
1443 if (_strnicmp (FvList, FvName, strlen (FvName)) == 0) {\r
1444 //\r
1445 // Then see if the match string in FvList is terminated at the\r
1446 // same length.\r
1447 //\r
1448 if ((FvList[strlen (FvName)] == ',') || (FvList[strlen (FvName)] == 0)) {\r
1449 *Order = 0;\r
1450 return TRUE;\r
1451 } else if (FvList[strlen (FvName)] == ':') {\r
1452 *Order = atoi (FvList + strlen (FvName) + 1);\r
1453 return TRUE;\r
1454 }\r
1455 }\r
1456 //\r
1457 // Skip to next FV in the comma-separated list\r
1458 //\r
1459 while ((*FvList != ',') && (*FvList != 0)) {\r
1460 FvList++;\r
1461 }\r
1462 //\r
1463 // Skip over comma\r
1464 //\r
1465 if (*FvList == ',') {\r
1466 FvList++;\r
1467 }\r
1468 }\r
1469\r
1470 return FALSE;\r
1471}\r
1472\r
1473static\r
1474char *\r
1475UpperCaseString (\r
1476 char *Str\r
1477 )\r
1478{\r
1479 char *Cptr;\r
1480\r
1481 for (Cptr = Str; *Cptr; Cptr++) {\r
1482 *Cptr = (char) toupper (*Cptr);\r
1483 }\r
1484\r
1485 return Str;\r
1486}\r
1487\r
1488static\r
1489BOOLEAN\r
1490InSameFv (\r
1491 char *FVs1,\r
1492 char *FVs2\r
1493)\r
1494{\r
1495 char *StartCptr1;\r
1496 char *StartCptr2;\r
1497 char *EndCptr1;\r
1498 char *EndCptr2;\r
1499 char CSave1;\r
1500 char CSave2;\r
1501 \r
1502 //\r
1503 // Process each FV in first FV list\r
1504 //\r
1505 StartCptr1 = FVs1;\r
1506 while (*StartCptr1) {\r
1507 EndCptr1 = StartCptr1;\r
1508 while (*EndCptr1 && (*EndCptr1 != ',')) {\r
1509 EndCptr1++;\r
1510 }\r
1511\r
1512 CSave1 = *EndCptr1;\r
1513 *EndCptr1 = 0; \r
1514 \r
1515 if (*StartCptr1) {\r
1516 //\r
1517 // Process each FV in second FV list\r
1518 //\r
1519 StartCptr2 = FVs2;\r
1520 while (*StartCptr2) {\r
1521 EndCptr2 = StartCptr2;\r
1522 while (*EndCptr2 && (*EndCptr2 != ',')) {\r
1523 EndCptr2++;\r
1524 }\r
1525 \r
1526 CSave2 = *EndCptr2;\r
1527 *EndCptr2 = 0; \r
1528 \r
1529 if (_stricmp (StartCptr1, StartCptr2) == 0) {\r
1530 *EndCptr1 = CSave1;\r
1531 *EndCptr2 = CSave2;\r
1532 return TRUE;\r
1533 }\r
1534 \r
1535 //\r
1536 // Next FV on the second FV list\r
1537 //\r
1538 *EndCptr2 = CSave2;\r
1539 StartCptr2 = EndCptr2;\r
1540 if (*StartCptr2) {\r
1541 StartCptr2++;\r
1542 }\r
1543 } \r
1544 }\r
1545 \r
1546 //\r
1547 // Next FV on the first FV list\r
1548 //\r
1549 *EndCptr1 = CSave1;\r
1550 StartCptr1 = EndCptr1;\r
1551 if (*StartCptr1) {\r
1552 StartCptr1++;\r
1553 }\r
1554 } \r
1555 \r
1556 return FALSE;\r
1557}\r
1558\r
1559int\r
1560CFVSetXRefFileName (\r
1561 char *FileName\r
1562 )\r
1563{\r
1564 mXRefFileName = FileName;\r
1565 return 0;\r
1566}\r