]> git.proxmox.com Git - mirror_edk2.git/blame - BaseTools/Source/C/BfmLib/BinFileManager.c
BaseTools: Fix various typos
[mirror_edk2.git] / BaseTools / Source / C / BfmLib / BinFileManager.c
CommitLineData
dc7b0dc8
SZ
1/** @file\r
2\r
3 The main entry of BFM tool.\r
4\r
5 Copyright (c) 2011-2019, Intel Corporation. All rights reserved.<BR>\r
6 SPDX-License-Identifier: BSD-2-Clause-Patent\r
7\r
8**/\r
9\r
10#include "BinFileManager.h"\r
11\r
12BOOLEAN mFvGuidIsSet = FALSE;\r
13EFI_GUID mFvNameGuid = {0};\r
14CHAR8* mFvNameGuidString = NULL;\r
15CHAR8* mGuidToolDefinition = "GuidToolDefinitionConf.ini";\r
16\r
17//\r
18// Store GUIDed Section guid->tool mapping\r
19//\r
20EFI_HANDLE mParsedGuidedSectionTools = NULL;\r
21\r
22\r
23/**\r
24 Search the config file from the path list.\r
25\r
26 Split the path from env PATH, and then search the cofig\r
27 file from these paths. The priority is from left to\r
28 right of PATH string. When met the first Config file, it\r
29 will break and return the pointer to the full file name.\r
30\r
31 @param PathList the pointer to the path list.\r
32 @param FileName the pointer to the file name.\r
33\r
34 @retval The pointer to the file name.\r
35 @return NULL An error occurred.\r
36**/\r
37CHAR8 *\r
38SearchConfigFromPathList (\r
39 IN CHAR8 *PathList,\r
40 IN CHAR8 *FileName\r
41)\r
42{\r
43 CHAR8 *CurDir;\r
44 CHAR8 *FileNamePath;\r
45\r
46 CurDir = NULL;\r
47 FileNamePath = NULL;\r
48#ifndef __GNUC__\r
49 CurDir = strtok (PathList,";");\r
50#else\r
51 CurDir = strtok (PathList,":");\r
52#endif\r
53 while (CurDir != NULL) {\r
54 FileNamePath = (char *)calloc(\r
55 strlen (CurDir) + strlen (OS_SEP_STR) +strlen (FileName) + 1,\r
56 sizeof(char)\r
57 );\r
58 if (FileNamePath == NULL) {\r
59 return NULL;\r
60 }\r
61 sprintf(FileNamePath, "%s%c%s", CurDir, OS_SEP, FileName);\r
62 if (access (FileNamePath, 0) != -1) {\r
63 return FileNamePath;\r
64 }\r
65#ifndef __GNUC__\r
66 CurDir = strtok(NULL, ";");\r
67#else\r
68 CurDir = strtok(NULL, ":");\r
69#endif\r
70 free (FileNamePath);\r
71 FileNamePath = NULL;\r
72 }\r
73 return NULL;\r
74}\r
75\r
76/**\r
77\r
78 Show the FD image layout information. Only display the modules with UI name.\r
79\r
80 @param[in] FdInName Input FD binary/image file name;\r
81 @param[in] FvName The FV ID in the FD file;\r
82 @param[in] ViewFlag Is this call for view or other operate(add/del/replace)\r
83 @param[in] FdData The Fd data structure store the FD information.\r
84\r
85 @retval EFI_SUCCESS\r
86 @retval EFI_INVALID_PARAMETER\r
87 @retval EFI_ABORTED\r
88\r
89**/\r
90EFI_STATUS\r
91BfmImageView (\r
92 IN CHAR8* FdInName,\r
93 IN CHAR8* FvName,\r
94 IN BOOLEAN ViewFlag,\r
95 IN FIRMWARE_DEVICE **FdData\r
96)\r
97{\r
98 EFI_STATUS Status;\r
99 FIRMWARE_DEVICE *LocalFdData;\r
100 FV_INFORMATION *CurrentFv;\r
101 FILE *InputFile;\r
102 UINT32 FvSize;\r
103 UINTN BytesRead;\r
104 EFI_FIRMWARE_VOLUME_HEADER *FvImage;\r
105 UINT32 FfsCount;\r
106 UINT8 FvCount;\r
107 UINT8 LastFvNumber;\r
108\r
109 LocalFdData = NULL;\r
110 CurrentFv = NULL;\r
111 FvImage = NULL;\r
112 FvSize = 0;\r
113 BytesRead = 0;\r
114 FfsCount = 0;\r
115 FvCount = 0;\r
116 LastFvNumber = 0;\r
117\r
118 //\r
119 // Check the FD file name/path.\r
120 //\r
121 if (FdInName == NULL) {\r
122 return EFI_INVALID_PARAMETER;\r
123 }\r
124\r
125 //\r
126 // Open the file containing the FV\r
127 //\r
128 InputFile = fopen (FdInName, "rb");\r
129 if (InputFile == NULL) {\r
130 return EFI_INVALID_PARAMETER;\r
131 }\r
132\r
133 Status = LibFindFvInFd (InputFile, &LocalFdData);\r
134\r
135 if (EFI_ERROR(Status)) {\r
136 fclose (InputFile);\r
137 return EFI_ABORTED;\r
138 }\r
139\r
140 CurrentFv = LocalFdData->Fv;\r
141\r
142 do {\r
143\r
144 memset (CurrentFv->FvName, '\0', _MAX_PATH);\r
145\r
146 if (LastFvNumber == 0) {\r
147 sprintf (CurrentFv->FvName, "FV%d", LastFvNumber);\r
148 } else {\r
149 sprintf (CurrentFv->FvName, "FV%d", LastFvNumber);\r
150 }\r
151\r
152 //\r
153 // Determine size of FV\r
154 //\r
155 if (fseek (InputFile, CurrentFv->ImageAddress, SEEK_SET) != 0) {\r
156 fclose (InputFile);\r
157 LibBfmFreeFd( LocalFdData);\r
158 return EFI_ABORTED;\r
159 }\r
160\r
161 Status = LibGetFvSize(InputFile, &FvSize);\r
162 if (EFI_ERROR (Status)) {\r
163 fclose (InputFile);\r
164 return EFI_ABORTED;\r
165 }\r
166\r
167 //\r
168 // Seek to the start of the image, then read the entire FV to the buffer\r
169 //\r
170 fseek (InputFile, CurrentFv->ImageAddress, SEEK_SET);\r
171\r
172 FvImage = (EFI_FIRMWARE_VOLUME_HEADER *) malloc (FvSize);\r
173\r
174 if (FvImage == NULL) {\r
175 fclose (InputFile);\r
176 LibBfmFreeFd( LocalFdData);\r
177 return EFI_ABORTED;\r
178 }\r
179\r
180 BytesRead = fread (FvImage, 1, FvSize, InputFile);\r
181 if ((unsigned int) BytesRead != FvSize) {\r
182 free (FvImage);\r
183 fclose (InputFile);\r
184 LibBfmFreeFd( LocalFdData);\r
185 return EFI_ABORTED;\r
186 }\r
187\r
188 //\r
189 // Collect FV information each by each.\r
190 //\r
191 Status = LibGetFvInfo (FvImage, CurrentFv, FvName, 0, &FfsCount, ViewFlag, FALSE);\r
192 free (FvImage);\r
193 FvImage = NULL;\r
194 if (EFI_ERROR (Status)) {\r
195 fclose (InputFile);\r
196 LibBfmFreeFd( LocalFdData);\r
197 return Status;\r
198 }\r
199 FvCount = CurrentFv->FvLevel;\r
200 LastFvNumber = LastFvNumber+FvCount;\r
201\r
202 FfsCount = 0;\r
203\r
204 CurrentFv = CurrentFv->FvNext;\r
205\r
206 } while (CurrentFv != NULL);\r
207\r
208 if (!ViewFlag) {\r
209 *FdData = LocalFdData;\r
210 } else {\r
211 LibBfmFreeFd( LocalFdData);\r
212 }\r
213\r
214 fclose (InputFile);\r
215\r
216 return EFI_SUCCESS;\r
217}\r
218\r
219/**\r
220 Add an FFS file into a specify FV.\r
221\r
222 @param[in] FdInName Input FD binary/image file name;\r
223 @param[in] NewFile The name of the file add in;\r
224 @param[in] FdOutName Name of output fd file.\r
225\r
226 @retval EFI_SUCCESS\r
227 @retval EFI_INVALID_PARAMETER\r
228 @retval EFI_ABORTED\r
229\r
230**/\r
231EFI_STATUS\r
232BfmImageAdd (\r
233 IN CHAR8* FdInName,\r
234 IN CHAR8* NewFile,\r
235 IN CHAR8* FdOutName\r
236)\r
237{\r
238 EFI_STATUS Status;\r
239 FIRMWARE_DEVICE *FdData;\r
240 FV_INFORMATION *FvInFd;\r
241 ENCAP_INFO_DATA *LocalEncapData;\r
242 ENCAP_INFO_DATA *LocalEncapDataTemp;\r
243 FILE* NewFdFile;\r
244 FILE* NewFvFile;\r
245 UINT64 NewFvLength;\r
246 UINT64 NewFfsLength;\r
247 VOID* Buffer;\r
248 CHAR8 *TemDir;\r
249 UINT8 FvEncapLevel;\r
250 UINT8 NewAddedFfsLevel;\r
251 BOOLEAN FfsLevelFoundFlag;\r
252 CHAR8 *OutputFileName;\r
253 CHAR8 *FvId;\r
254 BOOLEAN FirstInFlag;\r
255 BOOLEAN FvGuidExisted;\r
256\r
257 NewFvLength = 0;\r
258 FvEncapLevel = 0;\r
259 NewAddedFfsLevel = 0;\r
260\r
261 FfsLevelFoundFlag = FALSE;\r
262 FirstInFlag = TRUE;\r
263 FdData = NULL;\r
264 FvInFd = NULL;\r
265 LocalEncapData = NULL;\r
266 NewFdFile = NULL;\r
267 NewFvFile = NULL;\r
268 Buffer = NULL;\r
269 TemDir = NULL;\r
270 LocalEncapDataTemp = NULL;\r
271 OutputFileName = NULL;\r
272 FvId = NULL;\r
273 FvGuidExisted = FALSE;\r
274\r
275 //\r
276 // Get the size of ffs file to be inserted.\r
277 //\r
278 NewFfsLength = GetFileSize(NewFile);\r
279\r
280 Status = BfmImageView (FdInName, NULL, FALSE, &FdData);\r
281\r
282 if (EFI_ERROR (Status)) {\r
283 printf ("Error while parse %s FD image.\n", FdInName);\r
284 return Status;\r
285 }\r
286 //\r
287 // Check the FvGuid whether exists or not when the BIOS hasn't default setting.\r
288 // If the FV image with -g GUID can't be found, the storage is still saved into the BFV and report warning message.\r
289 //\r
290 FvInFd = FdData->Fv;\r
291 do {\r
292 if (mFvGuidIsSet && FvInFd->IsInputFvFlag) {\r
293 FvGuidExisted = TRUE;\r
294 break;\r
295 }\r
296 FvInFd = FvInFd->FvNext;\r
297 } while (FvInFd != NULL);\r
298\r
299 if (mFvGuidIsSet && !FvGuidExisted) {\r
300 printf ("Fv image with the specified FV Name Guid %s can't be found in current FD.\n", mFvNameGuidString);\r
301 LibBfmFreeFd(FdData);\r
302 return EFI_ABORTED;\r
303 }\r
304 //\r
305 // Iterate to write FFS to each BFV.\r
306 //\r
307 FvInFd = FdData->Fv;\r
308 do {\r
309 if ((FvGuidExisted && mFvGuidIsSet && FvInFd->IsInputFvFlag) || ((!FvGuidExisted || (!mFvGuidIsSet)) && FvInFd->IsBfvFlag)) {\r
310\r
311 Status = LibLocateBfv (FdData, &FvId, &FvInFd);\r
312\r
313 if (EFI_ERROR (Status)) {\r
314 printf("Error while locate BFV from FD.\n");\r
315 LibBfmFreeFd(FdData);\r
316 return Status;\r
317 }\r
318\r
319 //\r
320 // Determine the new added ffs file level in the FV.\r
321 //\r
322 LocalEncapData = FvInFd->EncapData;\r
323\r
324 while (LocalEncapData != NULL && !FfsLevelFoundFlag ) {\r
325 if (LocalEncapData->Type == BFM_ENCAP_TREE_FV) {\r
326 if (FvEncapLevel == ((UINT8) atoi (FvId + 2) - (UINT8) atoi (FvInFd->FvName + 2))) {\r
327 //\r
328 // Found the FFS level in this FV.\r
329 //\r
330 LocalEncapDataTemp = LocalEncapData;\r
331 while (LocalEncapDataTemp != NULL) {\r
332 if (LocalEncapDataTemp->Type == BFM_ENCAP_TREE_FFS) {\r
333 NewAddedFfsLevel = LocalEncapDataTemp->Level;\r
334 FfsLevelFoundFlag = TRUE;\r
335 break;\r
336 }\r
337 if (LocalEncapDataTemp->NextNode != NULL) {\r
338 LocalEncapDataTemp = LocalEncapDataTemp->NextNode;\r
339 } else {\r
340 break;\r
341 }\r
342 }\r
343 }\r
344 FvEncapLevel ++;\r
345 }\r
346\r
347 if (LocalEncapData->NextNode == NULL) {\r
348 break;\r
349 } else {\r
350 LocalEncapData = LocalEncapData->NextNode;\r
351 }\r
352 }\r
353\r
354 //\r
355 // Add the new file into FV.\r
356 //\r
357 FvInFd->FfsNumbers += 1;\r
358 if (strlen (NewFile) > _MAX_PATH - 1) {\r
359 printf ("The NewFile name is too long \n");\r
360 LibBfmFreeFd(FdData);\r
361 return EFI_ABORTED;\r
362 }\r
363 strncpy (FvInFd->FfsAttuibutes[FvInFd->FfsNumbers].FfsName, NewFile, _MAX_PATH - 1);\r
364 FvInFd->FfsAttuibutes[FvInFd->FfsNumbers].FfsName[_MAX_PATH - 1] = 0;\r
365 FvInFd->FfsAttuibutes[FvInFd->FfsNumbers].Level = NewAddedFfsLevel;\r
366\r
367 TemDir = getcwd (NULL, _MAX_PATH);\r
368 if (strlen (TemDir) + strlen (OS_SEP_STR) + strlen (TEMP_DIR_NAME) > _MAX_PATH - 1) {\r
369 printf ("The directory is too long \n");\r
370 LibBfmFreeFd(FdData);\r
371 return EFI_ABORTED;\r
372 }\r
373 strncat (TemDir, OS_SEP_STR, _MAX_PATH - strlen (TemDir) - 1);\r
374 strncat (TemDir, TEMP_DIR_NAME, _MAX_PATH - strlen (TemDir) - 1);\r
375 mkdir(TemDir, S_IRWXU | S_IRWXG | S_IRWXO);\r
376 Status = LibEncapNewFvFile (FvInFd, TemDir, &OutputFileName);\r
377\r
378 if (EFI_ERROR (Status)) {\r
379 printf("Error. The boot firmware volume (BFV) has only the spare space 0x%lx bytes. But the default setting data takes 0x%llx bytes, which can't be inserted into BFV. \n",(unsigned long) GetBfvPadSize (), (unsigned long long)NewFfsLength);\r
380 LibBfmFreeFd(FdData);\r
381 return Status;\r
382 }\r
383\r
384 if (FirstInFlag) {\r
385 //\r
386 // Write New Fv file into the NewFd file.\r
387 //\r
388 Status = LibCreateNewFdCopy (FdInName, FdOutName);\r
389 if (EFI_ERROR (Status)) {\r
390 printf("Error while copy from %s to %s file. \n", FdInName, FdOutName);\r
391 LibBfmFreeFd(FdData);\r
392 return Status;\r
393 }\r
394 FirstInFlag = FALSE;\r
395 }\r
396\r
397 NewFdFile = fopen (FdOutName, "rb+");\r
398 if (NewFdFile == NULL) {\r
399 printf("Error while create FD file %s. \n", FdOutName);\r
400 LibBfmFreeFd(FdData);\r
401 return EFI_ABORTED;\r
402 }\r
403\r
404 NewFvFile = fopen (OutputFileName, "rb+");\r
405\r
406 if (NewFvFile == NULL) {\r
407 printf("Error while create Fv file %s. \n", OutputFileName);\r
408 fclose(NewFdFile);\r
409 LibBfmFreeFd(FdData);\r
410 return EFI_ABORTED;\r
411 }\r
412\r
413 fseek(NewFvFile,0,SEEK_SET);\r
414 fseek(NewFvFile,0,SEEK_END);\r
415\r
416 NewFvLength = ftell(NewFvFile);\r
417\r
418 fseek(NewFvFile,0,SEEK_SET);\r
419\r
420 Buffer = malloc ((size_t)NewFvLength);\r
421\r
422 if (Buffer == NULL) {\r
423 printf ("Error while allocate resource! \n");\r
424 fclose(NewFdFile);\r
425 fclose(NewFvFile);\r
426 LibBfmFreeFd(FdData);\r
427 return EFI_ABORTED;\r
428 }\r
429\r
430 if (fread (Buffer, 1, (size_t) NewFvLength, NewFvFile) != (size_t) NewFvLength) {\r
431 printf("Error while reading Fv file %s. \n", OutputFileName);\r
432 free (Buffer);\r
433 fclose(NewFdFile);\r
434 fclose(NewFvFile);\r
435 LibBfmFreeFd(FdData);\r
436 return EFI_ABORTED;\r
437 }\r
438\r
439 fseek(NewFdFile, FvInFd->ImageAddress, SEEK_SET);\r
440 fseek(NewFdFile, FvInFd->ImageAddress, SEEK_SET);\r
441\r
442 if (NewFvLength <= FvInFd->FvHeader->FvLength) {\r
443 if (fwrite (Buffer, 1, (size_t) NewFvLength, NewFdFile) != (size_t) NewFvLength) {\r
444 printf("Error while writing FD file %s. \n", FdOutName);\r
445 fclose(NewFdFile);\r
446 fclose (NewFvFile);\r
447 free (Buffer);\r
448 LibBfmFreeFd(FdData);\r
449 return EFI_ABORTED;\r
450 }\r
451 } else {\r
452 printf("Error. The new size of BFV is 0x%llx bytes, which is larger than the previous size of BFV 0x%llx bytes. \n", (unsigned long long) NewFvLength, (unsigned long long) FvInFd->FvHeader->FvLength);\r
453 free (Buffer);\r
454 fclose(NewFdFile);\r
455 fclose(NewFvFile);\r
456 LibBfmFreeFd(FdData);\r
457 return EFI_ABORTED;\r
458 }\r
459\r
460 fclose(NewFdFile);\r
461 fclose(NewFvFile);\r
462 free (Buffer);\r
463 Buffer = NULL;\r
464\r
465 }\r
466 FvInFd = FvInFd->FvNext;\r
467 } while (FvInFd != NULL);\r
468\r
469\r
470 LibBfmFreeFd(FdData);\r
471\r
472 if (TemDir == NULL) {\r
473 if (mFvGuidIsSet) {\r
474 printf ("Fv image with the specified FV Name Guid %s can't be found.\n", mFvNameGuidString);\r
475 } else {\r
476 printf ("BFV image can't be found.\n");\r
477 }\r
478 return EFI_NOT_FOUND;\r
479 }\r
480\r
481 Status = LibRmDir (TemDir);\r
482\r
483 if (EFI_ERROR (Status)) {\r
484 printf("Error while remove temporary directory. \n");\r
485 return Status;\r
486 }\r
487\r
488 return EFI_SUCCESS;\r
489}\r
490\r
491\r
492/**\r
493 Replace an FFS file into a specify FV.\r
494\r
495 @param[in] FdInName Input FD binary/image file name;\r
496 @param[in] NewFile The name of the file add in;\r
497 @param[in] FdOutName Name of output fd file.\r
498\r
499 @retval EFI_SUCCESS\r
500 @retval EFI_INVALID_PARAMETER\r
501 @retval EFI_ABORTED\r
502\r
503**/\r
504EFI_STATUS\r
505BfmImageReplace (\r
506 IN CHAR8* FdInName,\r
507 IN CHAR8* NewFile,\r
508 IN CHAR8* FdOutName\r
509)\r
510{\r
511 EFI_STATUS Status;\r
512 FIRMWARE_DEVICE *FdData;\r
513 FV_INFORMATION *FvInFd;\r
514 FILE* NewFdFile;\r
515 FILE* NewFvFile;\r
516 UINT64 NewFvLength;\r
517 UINT64 NewFfsLength;\r
518 VOID* Buffer;\r
519 CHAR8 *TemDir;\r
520 CHAR8 *OutputFileName;\r
521 CHAR8 *FvId;\r
522 BOOLEAN FirstInFlag;\r
523 UINT32 Index;\r
524 BOOLEAN FvToBeUpdate;\r
525 BOOLEAN FdIsUpdate;\r
526 ENCAP_INFO_DATA *LocalEncapData;\r
527 ENCAP_INFO_DATA *LocalEncapDataTemp;\r
528 UINT8 FvEncapLevel;\r
529 UINT8 NewAddedFfsLevel;\r
530 BOOLEAN FfsLevelFoundFlag;\r
531 EFI_GUID EfiNewAddToBfvGuid;\r
532 FILE* FfsFile;\r
533 UINTN BytesRead;\r
534 BOOLEAN ReplaceSameFv;\r
535 BOOLEAN FvGuidExisted;\r
536\r
537 NewFvLength = 0;\r
538 FdIsUpdate = FALSE;\r
539 FirstInFlag = TRUE;\r
540 FdData = NULL;\r
541 FvInFd = NULL;\r
542 NewFdFile = NULL;\r
543 NewFvFile = NULL;\r
544 Buffer = NULL;\r
545 TemDir = NULL;\r
546 OutputFileName = NULL;\r
547 FvId = NULL;\r
548 FfsFile = NULL;\r
549 BytesRead = 0;\r
550 ReplaceSameFv = FALSE;\r
551 FvGuidExisted = FALSE;\r
552\r
553 //\r
554 // Get the size of ffs file to be inserted.\r
555 //\r
556 NewFfsLength = GetFileSize(NewFile);\r
557 //\r
558 // Get FFS GUID\r
559 //\r
560 FfsFile = fopen (NewFile, "rb");\r
561 if (FfsFile == NULL) {\r
562 printf ("Error while read %s.\n", NewFile);\r
563 return EFI_ABORTED;\r
564 }\r
565 fseek (FfsFile, 0, SEEK_SET);\r
566 BytesRead = fread (&EfiNewAddToBfvGuid, 1, sizeof(EFI_GUID), FfsFile);\r
567 fclose (FfsFile);\r
568 if (BytesRead != sizeof(EFI_GUID)) {\r
569 printf ("Error while read the GUID from %s.\n", NewFile);\r
570 return EFI_ABORTED;\r
571 }\r
572 Status = BfmImageView (FdInName, NULL, FALSE, &FdData);\r
573\r
574 if (EFI_ERROR (Status)) {\r
575 printf ("Error while parse %s FD image.\n", FdInName);\r
576 return Status;\r
577 }\r
578\r
579 //\r
580 // Check the FvGuid whether exists or not when the BIOS has default setting.\r
581 // 1. No option means the storage is saved into the same FV image.\r
582 // 2. The FV image with -g GUID can't be found. The storage is still saved into the same FV image and report warning message.\r
583 //\r
584 if (!mFvGuidIsSet) {\r
585 ReplaceSameFv = TRUE;\r
586 }\r
587 FvInFd = FdData->Fv;\r
588 do {\r
589 if (mFvGuidIsSet && FvInFd->IsInputFvFlag) {\r
590 FvGuidExisted = TRUE;\r
591 break;\r
592 }\r
593 FvInFd = FvInFd->FvNext;\r
594 } while (FvInFd != NULL);\r
595\r
596 if (mFvGuidIsSet && !FvGuidExisted) {\r
597 printf ("Fv image with the specified FV Name Guid %s can't be found in current FD.\n", mFvNameGuidString);\r
598 ReplaceSameFv = TRUE;\r
599 LibBfmFreeFd(FdData);\r
600 return EFI_ABORTED;\r
601 }\r
602 //\r
603 // Interate to insert or replace default setting to Fv\r
604 //\r
605 FvInFd = FdData->Fv;\r
606 do {\r
607 FvToBeUpdate = FALSE;\r
608 if (mFvGuidIsSet && FvInFd->IsInputFvFlag) {\r
609 FvToBeUpdate = TRUE;\r
610 }\r
611\r
612 Status = LibLocateBfv (FdData, &FvId, &FvInFd);\r
613\r
614 if (EFI_ERROR (Status)) {\r
615 printf("Error while locate BFV from FD.\n");\r
616 LibBfmFreeFd(FdData);\r
617 return Status;\r
618 }\r
619\r
620 Index = 0;\r
621 while (Index <= FvInFd->FfsNumbers) {\r
622 //\r
623 // Locate the multi-platform ffs in Fv and then replace or delete it.\r
624 //\r
625 if (!CompareGuid(&FvInFd->FfsHeader[Index].Name, &EfiNewAddToBfvGuid)) {\r
626 if (ReplaceSameFv) {\r
627 FvToBeUpdate = TRUE;\r
628 }\r
629 break;\r
630 }\r
631 Index ++;\r
632 }\r
633\r
634 if (FvToBeUpdate || (Index <= FvInFd->FfsNumbers)) {\r
635 if (FvToBeUpdate) {\r
636 FdIsUpdate = TRUE;\r
637 if (Index <= FvInFd->FfsNumbers) {\r
638 //\r
639 // Override original default data by New File\r
640 //\r
641 if (strlen (NewFile) > _MAX_PATH - 1) {\r
642 printf ("The NewFile name is too long \n");\r
643 LibBfmFreeFd(FdData);\r
644 return EFI_ABORTED;\r
645 }\r
646 strncpy (FvInFd->FfsAttuibutes[Index].FfsName, NewFile, _MAX_PATH - 1);\r
647 FvInFd->FfsAttuibutes[Index].FfsName[_MAX_PATH - 1] = 0;\r
648 } else {\r
649 FfsLevelFoundFlag = FALSE;\r
650 FvEncapLevel = 0;\r
651 NewAddedFfsLevel = 0;\r
652 //\r
653 // Determine the new added ffs file level in the FV.\r
654 //\r
655 LocalEncapData = FvInFd->EncapData;\r
656\r
657 while (LocalEncapData != NULL && !FfsLevelFoundFlag ) {\r
658 if (LocalEncapData->Type == BFM_ENCAP_TREE_FV) {\r
659 if (FvEncapLevel == ((UINT8) atoi (FvId + 2) - (UINT8) atoi (FvInFd->FvName + 2))) {\r
660 //\r
661 // Found the FFS level in this FV.\r
662 //\r
663 LocalEncapDataTemp = LocalEncapData;\r
664 while (LocalEncapDataTemp != NULL) {\r
665 if (LocalEncapDataTemp->Type == BFM_ENCAP_TREE_FFS) {\r
666 NewAddedFfsLevel = LocalEncapDataTemp->Level;\r
667 FfsLevelFoundFlag = TRUE;\r
668 break;\r
669 }\r
670 if (LocalEncapDataTemp->NextNode != NULL) {\r
671 LocalEncapDataTemp = LocalEncapDataTemp->NextNode;\r
672 } else {\r
673 break;\r
674 }\r
675 }\r
676 }\r
677 FvEncapLevel ++;\r
678 }\r
679\r
680 if (LocalEncapData->NextNode == NULL) {\r
681 break;\r
682 } else {\r
683 LocalEncapData = LocalEncapData->NextNode;\r
684 }\r
685 }\r
686\r
687 //\r
688 // Add the new file into FV.\r
689 //\r
690 FvInFd->FfsNumbers += 1;\r
691 memcpy (FvInFd->FfsAttuibutes[FvInFd->FfsNumbers].FfsName, NewFile, _MAX_PATH);\r
692 FvInFd->FfsAttuibutes[FvInFd->FfsNumbers].Level = NewAddedFfsLevel;\r
693 }\r
694 } else {\r
695 //\r
696 // Remove original default data from FV.\r
697 //\r
698 FvInFd->FfsAttuibutes[Index].FfsName[0] = '\0';\r
699 }\r
700\r
701 if (TemDir == NULL) {\r
702 TemDir = getcwd (NULL, _MAX_PATH);\r
703 if (strlen (TemDir) + strlen (OS_SEP_STR)+ strlen (TEMP_DIR_NAME) > _MAX_PATH - 1) {\r
704 printf ("The directory is too long \n");\r
705 LibBfmFreeFd(FdData);\r
706 return EFI_ABORTED;\r
707 }\r
708 strncat (TemDir, OS_SEP_STR, _MAX_PATH - strlen (TemDir) - 1);\r
709 strncat (TemDir, TEMP_DIR_NAME, _MAX_PATH - strlen (TemDir) - 1);\r
710 mkdir(TemDir, S_IRWXU | S_IRWXG | S_IRWXO);\r
711 }\r
712\r
713 Status = LibEncapNewFvFile (FvInFd, TemDir, &OutputFileName);\r
714\r
715 if (EFI_ERROR (Status)) {\r
716 printf("Error. The boot firmware volume (BFV) has only the spare space 0x%lx bytes. But the default setting data takes 0x%llx bytes, which can't be inserted into BFV. \n", (unsigned long) GetBfvPadSize (), (unsigned long long) NewFfsLength);\r
717 LibBfmFreeFd(FdData);\r
718 return Status;\r
719 }\r
720\r
721 if (FirstInFlag) {\r
722 //\r
723 // Write New Fv file into the NewFd file.\r
724 //\r
725 Status = LibCreateNewFdCopy (FdInName, FdOutName);\r
726 if (EFI_ERROR (Status)) {\r
727 printf("Error while copy from %s to %s file. \n", FdInName, FdOutName);\r
728 LibBfmFreeFd(FdData);\r
729 return Status;\r
730 }\r
731 FirstInFlag = FALSE;\r
732 }\r
733\r
734 NewFdFile = fopen (FdOutName, "rb+");\r
735 if (NewFdFile == NULL) {\r
736 printf("Error while create FD file %s. \n", FdOutName);\r
737 LibBfmFreeFd(FdData);\r
738 return EFI_ABORTED;\r
739 }\r
740\r
741 NewFvFile = fopen (OutputFileName, "rb+");\r
742\r
743 if (NewFvFile == NULL) {\r
744 printf("Error while create Fv file %s. \n", OutputFileName);\r
745 LibBfmFreeFd(FdData);\r
746 fclose (NewFdFile);\r
747 return EFI_ABORTED;\r
748 }\r
749\r
750 fseek(NewFvFile,0,SEEK_SET);\r
751 fseek(NewFvFile,0,SEEK_END);\r
752\r
753 NewFvLength = ftell(NewFvFile);\r
754\r
755 fseek(NewFvFile,0,SEEK_SET);\r
756\r
757 Buffer = malloc ((size_t)NewFvLength);\r
758\r
759 if (Buffer == NULL) {\r
760 LibBfmFreeFd(FdData);\r
761 fclose (NewFdFile);\r
762 fclose (NewFvFile);\r
763 return EFI_ABORTED;\r
764 }\r
765\r
766 if (fread (Buffer, 1, (size_t) NewFvLength, NewFvFile) != (size_t) NewFvLength) {\r
767 printf("Error while read Fv file %s. \n", OutputFileName);\r
768 LibBfmFreeFd(FdData);\r
769 free (Buffer);\r
770 fclose (NewFdFile);\r
771 fclose (NewFvFile);\r
772 return EFI_ABORTED;\r
773 }\r
774\r
775 fseek(NewFdFile, FvInFd->ImageAddress, SEEK_SET);\r
776 fseek(NewFdFile, FvInFd->ImageAddress, SEEK_SET);\r
777\r
778 if (NewFvLength <= FvInFd->FvHeader->FvLength) {\r
779 if (fwrite (Buffer, 1, (size_t) NewFvLength, NewFdFile) != (size_t) NewFvLength) {\r
780 printf("Error while write FD file %s. \n", FdOutName);\r
781 fclose(NewFdFile);\r
782 fclose (NewFvFile);\r
783 LibBfmFreeFd(FdData);\r
784 free (Buffer);\r
785 return EFI_ABORTED;\r
786 }\r
787 } else {\r
788 printf("Error. The new size of BFV is 0x%llx bytes, which is larger than the previous size of BFV 0x%llx bytes. \n", (unsigned long long) NewFvLength, (unsigned long long) FvInFd->FvHeader->FvLength);\r
789 free (Buffer);\r
790 LibBfmFreeFd(FdData);\r
791 fclose (NewFdFile);\r
792 fclose (NewFvFile);\r
793 return EFI_ABORTED;\r
794 }\r
795\r
796 fclose(NewFdFile);\r
797 fclose(NewFvFile);\r
798 free (Buffer);\r
799 Buffer = NULL;\r
800\r
801 }\r
802 FvInFd = FvInFd->FvNext;\r
803 } while (FvInFd != NULL);\r
804\r
805 LibBfmFreeFd(FdData);\r
806\r
807 if (TemDir == NULL || !FdIsUpdate) {\r
808 if (mFvGuidIsSet) {\r
809 printf ("Fv image with the specified FV Name Guid %s can't be found.\n", mFvNameGuidString);\r
810 } else {\r
811 printf ("BFV image can't be found.\n");\r
812 }\r
813 return EFI_NOT_FOUND;\r
814 }\r
815\r
816 Status = LibRmDir (TemDir);\r
817\r
818 if (EFI_ERROR (Status)) {\r
819 printf("Error while remove temporary directory. \n");\r
820 return Status;\r
821 }\r
822\r
823 return EFI_SUCCESS;\r
824}\r
825\r
826/**\r
827\r
828 The main entry of BFM tool.\r
829\r
830**/\r
831int main(\r
832 int Argc,\r
833 char *Argv[]\r
834)\r
835{\r
836 EFI_STATUS Status;\r
837 FIRMWARE_DEVICE *FdData;\r
838 CHAR8 *InFilePath;\r
839 CHAR8 FullGuidToolDefinition[_MAX_PATH];\r
840 CHAR8 *FileName;\r
841 UINTN FileNameIndex;\r
842 CHAR8 *PathList;\r
843 UINTN EnvLen;\r
844 CHAR8 *NewPathList;\r
845\r
846 FdData = NULL;\r
847 PathList = NULL;\r
848 NewPathList = NULL;\r
849 EnvLen = 0;\r
850\r
851 if (Argc <= 1) {\r
852 return -1;\r
853 }\r
854 FileName = Argv[0];\r
855 //\r
856 // Save, skip filename arg\r
857 //\r
858 Argc--;\r
859 Argv++;\r
860\r
861 if ((stricmp(Argv[0], "-v") == 0)) {\r
862 //\r
863 // Check the revison of BfmLib\r
864 // BfmLib -v\r
865 //\r
866 printf("%s\n", __BUILD_VERSION);\r
867 return 1;\r
868\r
869 }\r
870 //\r
871 // Workaroud: the first call to this function\r
872 // returns a file name ends with dot\r
873 //\r
874#ifndef __GNUC__\r
875 tmpnam (NULL);\r
876#else\r
877 CHAR8 tmp[] = "/tmp/fileXXXXXX";\r
878 UINTN Fdtmp;\r
879 Fdtmp = mkstemp(tmp);\r
880 close(Fdtmp);\r
881#endif\r
882 //\r
883 // Get the same path with the application itself\r
884 //\r
885 if (strlen (FileName) > _MAX_PATH - 1) {\r
886 Error (NULL, 0, 2000, "Parameter: Input file name is too long", NULL);\r
887 return -1;\r
888 }\r
889 strncpy (FullGuidToolDefinition, FileName, _MAX_PATH - 1);\r
890 FullGuidToolDefinition[_MAX_PATH - 1] = 0;\r
891 FileNameIndex = strlen (FullGuidToolDefinition);\r
892 while (FileNameIndex != 0) {\r
893 FileNameIndex --;\r
894 if (FullGuidToolDefinition[FileNameIndex] == OS_SEP) {\r
895 FullGuidToolDefinition[FileNameIndex] = 0;\r
896 break;\r
897 }\r
898 }\r
899 //\r
900 // Build the path list for Config file scan. The priority is below.\r
901 // 1. Scan the current path\r
902 // 2. Scan the same path with the application itself\r
903 // 3. Scan the current %PATH% of OS environment\r
904 // 4. Use the build-in default configuration\r
905 //\r
906 PathList = getenv("PATH");\r
907 if (PathList == NULL) {\r
908 Error (NULL, 0, 1001, "Option: Environment variable 'PATH' does not exist", NULL);\r
909 return -1;\r
910 }\r
911 EnvLen = strlen(PathList);\r
912 NewPathList = (char *)calloc(\r
913 strlen (".")\r
914 + strlen (";")\r
915 + strlen (FullGuidToolDefinition)\r
916 + strlen (";")\r
917 + EnvLen\r
918 + 1,\r
919 sizeof(char)\r
920 );\r
921 if (NewPathList == NULL) {\r
922 Error (NULL, 0, 4001, "Resource: Memory can't be allocated", NULL);\r
923 PathList = NULL;\r
924 free (PathList);\r
925 return -1;\r
926 }\r
927#ifndef __GNUC__\r
928 sprintf (NewPathList, "%s;%s;%s", ".", FullGuidToolDefinition, PathList);\r
929#else\r
930 sprintf (NewPathList, "%s:%s:%s", ".", FullGuidToolDefinition, PathList);\r
931#endif\r
932\r
933 PathList = NULL;\r
934 free (PathList);\r
935 //\r
936 // Load Guid Tools definition\r
937 //\r
938 InFilePath = SearchConfigFromPathList(NewPathList, mGuidToolDefinition);\r
939 free (NewPathList);\r
940 if (InFilePath != NULL) {\r
941 printf ("\nThe Guid Tool Definition of BfmLib comes from the '%s'. \n", InFilePath);\r
942 mParsedGuidedSectionTools = ParseGuidedSectionToolsFile (InFilePath);\r
943 free (InFilePath);\r
944 } else {\r
945 //\r
946 // Use the pre-defined standard guided tools.\r
947 //\r
948 printf ("\nThe Guid Tool Definition of BfmLib comes from the build-in default configuration. \n");\r
949 mParsedGuidedSectionTools = LibPreDefinedGuidedTools ();\r
950 }\r
951\r
952 //\r
953 // BfmLib -e FdName.Fd\r
954 //\r
955 if ((stricmp(Argv[0], "-e") == 0)) {\r
956\r
957 if (Argc != 2) {\r
958 return -1;\r
959 }\r
960 //\r
961 // Extract FFS files.\r
962 //\r
963 Status = BfmImageView (Argv[1], NULL, FALSE, &FdData);\r
964\r
965 if (EFI_ERROR (Status)) {\r
966 return -1;\r
967 }\r
968\r
969 if (FdData == NULL) {\r
970 return -1;\r
971 }\r
972\r
973 LibBfmFreeFd(FdData);\r
974\r
975 } else if ((stricmp(Argv[0], "-i") == 0)) {\r
976 //\r
977 // Insert FFS files to BFV\r
978 // BfmLib -i InFdName.Fd FfsName.ffs OutFdName.Fd -g FvNameGuid\r
979 //\r
980 if (Argc == 6) {\r
981 mFvGuidIsSet = TRUE;\r
982 mFvNameGuidString = Argv[5];\r
983 StringToGuid (Argv[5], &mFvNameGuid);\r
984 Argc -= 2;\r
985 }\r
986 if (Argc != 4) {\r
987 return -1;\r
988 }\r
989 Status = BfmImageAdd(Argv[1], Argv[2], Argv[3]);\r
990\r
991 if (EFI_ERROR (Status)) {\r
992 return -1;\r
993 }\r
994\r
995 } else if ((stricmp(Argv[0], "-r") == 0)) {\r
996 //\r
997 // Replace FFS files in BFV\r
998 // BfmLib -r InFdName.Fd FfsName.ffs OutFdName.Fd -g FvNameGuid\r
999 //\r
1000 if (Argc == 6) {\r
1001 mFvGuidIsSet = TRUE;\r
1002 mFvNameGuidString = Argv[5];\r
1003 StringToGuid (Argv[5], &mFvNameGuid);\r
1004 Argc -= 2;\r
1005 }\r
1006 if (Argc != 4) {\r
1007 return -1;\r
1008 }\r
1009 Status = BfmImageReplace (Argv[1], Argv[2], Argv[3]);\r
1010\r
1011 if (EFI_ERROR (Status)) {\r
1012 return -1;\r
1013 }\r
1014\r
1015 } else {\r
1016 //\r
1017 // Invalid parameter.\r
1018 //\r
1019 return -1;\r
1020 }\r
1021\r
1022 return 1;\r
1023}\r
1024\r