genffs.c 44 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760
  1. /*++
  2. Copyright (c) 2014 Minoca Corp. All Rights Reserved
  3. Module Name:
  4. genffs.c
  5. Abstract:
  6. This module implements a build tool that generates one EFI FFS file.
  7. Author:
  8. Evan Green 6-Mar-2014
  9. Environment:
  10. Build
  11. --*/
  12. //
  13. // ------------------------------------------------------------------- Includes
  14. //
  15. #include <assert.h>
  16. #include <stdio.h>
  17. #include <stdlib.h>
  18. #include <string.h>
  19. #include <time.h>
  20. #include <unistd.h>
  21. #include "uefifw.h"
  22. #include "efiffs.h"
  23. #include "peimage.h"
  24. //
  25. // --------------------------------------------------------------------- Macros
  26. //
  27. #define GFFS_LOG_ERROR(...) \
  28. fprintf(stderr, __VA_ARGS__); GffsErrorOccurred = TRUE;
  29. #define GFFS_LOG_VERBOSE(...) \
  30. if (GffsDebugLevel >= LOG_LEVEL_VERBOSE) { \
  31. fprintf(stderr, __VA_ARGS__); \
  32. }
  33. #define GFFS_LOG_DEBUG(...) \
  34. if (GffsDebugLevel >= LOG_LEVEL_DEBUG) { \
  35. fprintf(stderr, __VA_ARGS__); \
  36. }
  37. //
  38. // ---------------------------------------------------------------- Definitions
  39. //
  40. #define STATUS_SUCCESS 0
  41. #define STATUS_WARNING 1
  42. #define STATUS_ERROR 2
  43. #define UTILITY_NAME "GenFfs"
  44. #define UTILITY_MAJOR_VERSION 0
  45. #define UTILITY_MINOR_VERSION 1
  46. #define MAXIMUM_INPUT_FILE_COUNT 10
  47. #define LOG_LEVEL_QUIET 0
  48. #define LOG_LEVEL_DEFAULT 1
  49. #define LOG_LEVEL_VERBOSE 2
  50. #define LOG_LEVEL_DEBUG 3
  51. //
  52. // ------------------------------------------------------ Data Type Definitions
  53. //
  54. //
  55. // ----------------------------------------------- Internal Function Prototypes
  56. //
  57. EFI_STATUS
  58. GffsGetSectionContents (
  59. CHAR8 **InputFileName,
  60. UINT32 *InputFileAlignment,
  61. UINT8 *InputFileSectionType,
  62. UINT32 InputFileCount,
  63. UINT8 *FileBuffer,
  64. UINT32 *BufferLength,
  65. UINT32 *MaxAlignment
  66. );
  67. UINT8
  68. GffsStringToType (
  69. CHAR8 *String
  70. );
  71. UINT8
  72. GffsStringToSectionType (
  73. CHAR8 *String
  74. );
  75. EFI_STATUS
  76. GffsStringtoAlignment (
  77. CHAR8 *AlignBuffer,
  78. UINT32 *AlignNumber
  79. );
  80. EFI_STATUS
  81. GffsStringToGuid (
  82. CHAR8 *AsciiGuidBuffer,
  83. EFI_GUID *GuidBuffer
  84. );
  85. VOID
  86. GffsConvertAsciiStringToUnicode (
  87. CHAR8 *String,
  88. CHAR16 *UnicodeString
  89. );
  90. VOID
  91. GffsCreateRandomGuid (
  92. EFI_GUID *Guid
  93. );
  94. UINT8
  95. GffsCalculateChecksum8 (
  96. UINT8 *Buffer,
  97. UINTN Size
  98. );
  99. UINT8
  100. GffsCalculateSum8 (
  101. UINT8 *Buffer,
  102. UINTN Size
  103. );
  104. BOOLEAN
  105. GffsCompareGuids (
  106. EFI_GUID *FirstGuid,
  107. EFI_GUID *SecondGuid
  108. );
  109. VOID
  110. GffsPrintVersion (
  111. VOID
  112. );
  113. VOID
  114. GffsPrintUsage (
  115. VOID
  116. );
  117. //
  118. // -------------------------------------------------------------------- Globals
  119. //
  120. CHAR8 *GffsFileTypes[] = {
  121. NULL,
  122. "EFI_FV_FILETYPE_RAW",
  123. "EFI_FV_FILETYPE_FREEFORM",
  124. "EFI_FV_FILETYPE_SECURITY_CORE",
  125. "EFI_FV_FILETYPE_PEI_CORE",
  126. "EFI_FV_FILETYPE_DXE_CORE",
  127. "EFI_FV_FILETYPE_PEIM",
  128. "EFI_FV_FILETYPE_DRIVER",
  129. "EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER",
  130. "EFI_FV_FILETYPE_APPLICATION",
  131. "EFI_FV_FILETYPE_SMM",
  132. "EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE",
  133. "EFI_FV_FILETYPE_COMBINED_SMM_DXE",
  134. "EFI_FV_FILETYPE_SMM_CORE"
  135. };
  136. CHAR8 *GffsFileSectionTypes[] = {
  137. NULL,
  138. "EFI_SECTION_COMPRESSION",
  139. "EFI_SECTION_GUID_DEFINED",
  140. NULL,
  141. NULL,
  142. NULL,
  143. NULL,
  144. NULL,
  145. NULL,
  146. NULL,
  147. NULL,
  148. NULL,
  149. NULL,
  150. NULL,
  151. NULL,
  152. NULL,
  153. "EFI_SECTION_PE32",
  154. "EFI_SECTION_PIC",
  155. "EFI_SECTION_TE",
  156. "EFI_SECTION_DXE_DEPEX",
  157. "EFI_SECTION_VERSION",
  158. "EFI_SECTION_USER_INTERFACE",
  159. "EFI_SECTION_COMPATIBILITY16",
  160. "EFI_SECTION_FIRMWARE_VOLUME_IMAGE",
  161. "EFI_SECTION_FREEFORM_SUBTYPE_GUID",
  162. "EFI_SECTION_RAW",
  163. NULL,
  164. "EFI_SECTION_PEI_DEPEX",
  165. "EFI_SECTION_SMM_DEPEX"
  166. };
  167. CHAR8 *GffsAlignmentStrings[] = {
  168. "1", "2", "4", "8", "16", "32", "64", "128", "256", "512",
  169. "1K", "2K", "4K", "8K", "16K", "32K", "64K"
  170. };
  171. CHAR8 *GffsValidAlignmentStrings[] = {
  172. "8", "16", "128", "512", "1K", "4K", "32K", "64K"
  173. };
  174. UINT32 GffsValidAlignments[] = {0, 8, 16, 128, 512, 1024, 4096, 32768, 65536};
  175. EFI_GUID GffsZeroGuid = {0};
  176. UINTN GffsDebugLevel = LOG_LEVEL_DEFAULT;
  177. BOOLEAN GffsErrorOccurred = FALSE;
  178. //
  179. // ------------------------------------------------------------------ Functions
  180. //
  181. int
  182. main (
  183. int ArgumentCount,
  184. CHAR8 *Arguments[]
  185. )
  186. /*++
  187. Routine Description:
  188. This routine is the main entry point into the GenFFS utility, which creates
  189. a single FFS file from an input file.
  190. Arguments:
  191. ArgumentCount - Supplies the number of command line parameters.
  192. Arguments - Supplies the array of pointers to parameter strings.
  193. Return Value:
  194. STATUS_SUCCESS - Utility exits successfully.
  195. STATUS_ERROR- Some error occurred during execution.
  196. --*/
  197. {
  198. CHAR8 *AfterScan;
  199. UINT32 Alignment;
  200. EFI_FFS_FILE_ATTRIBUTES Attributes;
  201. UINT32 DefaultFileAlignment;
  202. UINT8 DefaultFileSectionType;
  203. FILE *FfsFile;
  204. EFI_FFS_FILE_HEADER2 FfsFileHeader;
  205. UINT8 *FileBuffer;
  206. EFI_GUID FileGuid;
  207. UINT32 FileSize;
  208. EFI_FV_FILETYPE FileType;
  209. UINT32 HeaderSize;
  210. UINT32 Index;
  211. UINT32 *InputFileAlignment;
  212. UINT32 InputFileCount;
  213. CHAR8 **InputFileName;
  214. UINT8 *InputFileSectionType;
  215. UINT64 LogLevel;
  216. UINT32 MaxAlignment;
  217. UINTN NewSize;
  218. CHAR8 *OutputFileName;
  219. EFI_STATUS Status;
  220. LogLevel = 0;
  221. Index = 0;
  222. Attributes = 0;
  223. Alignment = 0;
  224. DefaultFileSectionType = 0;
  225. DefaultFileAlignment = 0;
  226. FileType = EFI_FV_FILETYPE_ALL;
  227. OutputFileName = NULL;
  228. InputFileCount = 0;
  229. InputFileName = NULL;
  230. InputFileAlignment = NULL;
  231. InputFileSectionType = NULL;
  232. FileBuffer = NULL;
  233. FileSize = 0;
  234. MaxAlignment = 1;
  235. FfsFile = NULL;
  236. Status = EFI_SUCCESS;
  237. srand(time(NULL) ^ getpid());
  238. memset(&FileGuid, 0, sizeof(EFI_GUID));
  239. if (ArgumentCount == 1) {
  240. GFFS_LOG_ERROR("Missing options.\n");
  241. GffsPrintUsage();
  242. return STATUS_ERROR;
  243. }
  244. //
  245. // Parse the arguments.
  246. //
  247. ArgumentCount -= 1;
  248. Arguments += 1;
  249. if ((strcasecmp(Arguments[0], "-h") == 0) ||
  250. (strcasecmp(Arguments[0], "--help") == 0)) {
  251. GffsPrintVersion();
  252. GffsPrintUsage();
  253. return STATUS_SUCCESS;
  254. }
  255. if (strcasecmp(Arguments[0], "--version") == 0) {
  256. GffsPrintVersion();
  257. return STATUS_SUCCESS;
  258. }
  259. while (ArgumentCount > 0) {
  260. if ((strcasecmp(Arguments[0], "-t") == 0) ||
  261. (strcasecmp(Arguments[0], "--filetype") == 0)) {
  262. if ((Arguments[1] == NULL) || Arguments[1][0] == '-') {
  263. GFFS_LOG_ERROR("file type is missing for -t option");
  264. goto mainEnd;
  265. }
  266. FileType = GffsStringToType(Arguments[1]);
  267. if (FileType == EFI_FV_FILETYPE_ALL) {
  268. GFFS_LOG_ERROR("%s is not a valid file type.\n", Arguments[1]);
  269. goto mainEnd;
  270. }
  271. ArgumentCount -= 2;
  272. Arguments += 2;
  273. continue;
  274. }
  275. if ((strcasecmp(Arguments[0], "-o") == 0) ||
  276. (strcasecmp(Arguments[0], "--outputfile") == 0)) {
  277. if ((Arguments[1] == NULL) || (Arguments[1][0] == '-')) {
  278. GFFS_LOG_ERROR("Output file is missing for -o options.\n");
  279. goto mainEnd;
  280. }
  281. OutputFileName = Arguments[1];
  282. ArgumentCount -= 2;
  283. Arguments += 2;
  284. continue;
  285. }
  286. if ((strcasecmp(Arguments[0], "-g") == 0) ||
  287. (strcasecmp(Arguments[0], "--fileguid") == 0)) {
  288. Status = GffsStringToGuid(Arguments[1], &FileGuid);
  289. if (EFI_ERROR(Status)) {
  290. GFFS_LOG_ERROR("Invalid option value %s = %s.\n",
  291. Arguments[0],
  292. Arguments[1]);
  293. goto mainEnd;
  294. }
  295. ArgumentCount -= 2;
  296. Arguments += 2;
  297. continue;
  298. }
  299. if ((strcasecmp(Arguments[0], "-x") == 0) ||
  300. (strcasecmp(Arguments[0], "--fixed") == 0)) {
  301. Attributes |= FFS_ATTRIB_FIXED;
  302. ArgumentCount -= 1;
  303. Arguments += 1;
  304. continue;
  305. }
  306. if ((strcasecmp(Arguments[0], "-s") == 0) ||
  307. (strcasecmp(Arguments[0], "--checksum") == 0)) {
  308. Attributes |= FFS_ATTRIB_CHECKSUM;
  309. ArgumentCount -= 1;
  310. Arguments += 1;
  311. continue;
  312. }
  313. if ((strcasecmp(Arguments[0], "-a") == 0) ||
  314. (strcasecmp(Arguments[0], "--align") == 0)) {
  315. if ((Arguments[1] == NULL) || (Arguments[1][0] == '-')) {
  316. GFFS_LOG_ERROR("Align value is missing for -a option.\n");
  317. goto mainEnd;
  318. }
  319. for (Index = 0;
  320. Index < sizeof(GffsValidAlignmentStrings) / sizeof(CHAR8 *);
  321. Index += 1) {
  322. if (strcasecmp(Arguments[1],
  323. GffsValidAlignmentStrings[Index]) == 0) {
  324. break;
  325. }
  326. }
  327. if (Index == sizeof(GffsValidAlignmentStrings) / sizeof(CHAR8 *)) {
  328. if ((strcasecmp(Arguments[1], "1") == 0) ||
  329. (strcasecmp(Arguments[1], "2") == 0) ||
  330. (strcasecmp(Arguments[1], "4") == 0)) {
  331. //
  332. // 1, 2, 4 byte alignment same to 8 byte alignment
  333. //
  334. Index = 0;
  335. } else {
  336. GFFS_LOG_ERROR(
  337. "Invalid option %s = %s.\n",
  338. Arguments[0],
  339. Arguments[1]);
  340. goto mainEnd;
  341. }
  342. }
  343. Alignment = Index;
  344. ArgumentCount -= 2;
  345. Arguments += 2;
  346. continue;
  347. }
  348. if ((strcasecmp(Arguments[0], "-n") == 0) ||
  349. (strcasecmp(Arguments[0], "--sectionalign") == 0)) {
  350. Arguments += 1;
  351. ArgumentCount -= 1;
  352. if (ArgumentCount == 0) {
  353. GFFS_LOG_ERROR("Error: -n requires an argument.\n");
  354. goto mainEnd;
  355. }
  356. Status = GffsStringtoAlignment(Arguments[0],
  357. &DefaultFileAlignment);
  358. if (EFI_ERROR(Status)) {
  359. GFFS_LOG_ERROR("Invalid default alignment.\n");
  360. goto mainEnd;
  361. }
  362. Arguments += 1;
  363. ArgumentCount -= 1;
  364. continue;
  365. }
  366. if ((strcasecmp(Arguments[0], "-r") == 0) ||
  367. (strcasecmp(Arguments[0], "--sectiontype") == 0)) {
  368. Arguments += 1;
  369. ArgumentCount -= 1;
  370. if (ArgumentCount == 0) {
  371. GFFS_LOG_ERROR("Error: -n requires an argument.\n");
  372. goto mainEnd;
  373. }
  374. DefaultFileSectionType = GffsStringToSectionType(Arguments[0]);
  375. if (DefaultFileSectionType == 0) {
  376. GFFS_LOG_ERROR("Invalid section type %s.\n",
  377. Arguments[0]);
  378. goto mainEnd;
  379. }
  380. Arguments += 1;
  381. ArgumentCount -= 1;
  382. continue;
  383. }
  384. if ((strcasecmp(Arguments[0], "-v") == 0) ||
  385. (strcasecmp(Arguments[0], "--verbose") == 0)) {
  386. GffsDebugLevel = LOG_LEVEL_VERBOSE;
  387. GFFS_LOG_VERBOSE("Verbose output Mode Set!\n");
  388. ArgumentCount -= 1;
  389. Arguments += 1;
  390. continue;
  391. }
  392. if ((strcasecmp(Arguments[0], "-q") == 0) ||
  393. (strcasecmp(Arguments[0], "--quiet") == 0)) {
  394. GffsDebugLevel = LOG_LEVEL_QUIET;
  395. ArgumentCount -= 1;
  396. Arguments += 1;
  397. continue;
  398. }
  399. if ((strcasecmp(Arguments[0], "-d") == 0) ||
  400. (strcasecmp(Arguments[0], "--debug") == 0)) {
  401. LogLevel = strtoul(Arguments[1], &AfterScan, 0);
  402. if (AfterScan == Arguments[1]) {
  403. GFFS_LOG_ERROR(
  404. "Invalid option value %s = %s.\n",
  405. Arguments[0],
  406. Arguments[1]);
  407. goto mainEnd;
  408. }
  409. if (LogLevel > 9) {
  410. GFFS_LOG_ERROR(
  411. "Debug Level range is 0-9, current input level is %d",
  412. (int)LogLevel);
  413. goto mainEnd;
  414. }
  415. GffsDebugLevel = LOG_LEVEL_DEBUG;
  416. GFFS_LOG_DEBUG("Debug Output Mode Level %s is set!\n",
  417. Arguments[1]);
  418. ArgumentCount -= 2;
  419. Arguments += 2;
  420. continue;
  421. }
  422. if ((strcasecmp(Arguments[0], "-i") == 0) ||
  423. (strcasecmp(Arguments[0], "--sectionfile") == 0) ||
  424. (Arguments[0][0] != '-')) {
  425. if (Arguments[0][0] == '-') {
  426. Arguments += 1;
  427. ArgumentCount -= 1;
  428. }
  429. //
  430. // Get the input file name and its alignment.
  431. //
  432. if ((ArgumentCount == 0) || (Arguments[0][0] == '-')) {
  433. GFFS_LOG_ERROR("Input section file is missing for -i "
  434. "option.\n");
  435. goto mainEnd;
  436. }
  437. //
  438. // Allocate Input file name buffer and its alignment buffer.
  439. //
  440. if (InputFileCount % MAXIMUM_INPUT_FILE_COUNT == 0) {
  441. NewSize = (InputFileCount + MAXIMUM_INPUT_FILE_COUNT) *
  442. sizeof(CHAR8 *);
  443. InputFileName = (CHAR8 **)realloc(InputFileName, NewSize);
  444. if (InputFileName == NULL) {
  445. GffsErrorOccurred = TRUE;
  446. goto mainEnd;
  447. }
  448. memset(&(InputFileName[InputFileCount]),
  449. 0,
  450. (MAXIMUM_INPUT_FILE_COUNT * sizeof(CHAR8 *)));
  451. NewSize = (InputFileCount + MAXIMUM_INPUT_FILE_COUNT) *
  452. sizeof(UINT32);
  453. InputFileAlignment = (UINT32 *)realloc(InputFileAlignment,
  454. NewSize);
  455. if (InputFileAlignment == NULL) {
  456. GffsErrorOccurred = TRUE;
  457. goto mainEnd;
  458. }
  459. memset(&(InputFileAlignment[InputFileCount]),
  460. 0,
  461. (MAXIMUM_INPUT_FILE_COUNT * sizeof(UINT32)));
  462. NewSize = (InputFileCount + MAXIMUM_INPUT_FILE_COUNT) *
  463. sizeof(UINT8);
  464. InputFileSectionType = (UINT8 *)realloc(InputFileSectionType,
  465. NewSize);
  466. if (InputFileSectionType == NULL) {
  467. GffsErrorOccurred = TRUE;
  468. goto mainEnd;
  469. }
  470. memset(&(InputFileSectionType[InputFileCount]),
  471. 0,
  472. (MAXIMUM_INPUT_FILE_COUNT * sizeof(UINT8)));
  473. }
  474. InputFileName[InputFileCount] = Arguments[0];
  475. ArgumentCount -= 1;
  476. Arguments += 1;
  477. //
  478. // Assign the default alignment and type.
  479. //
  480. InputFileAlignment[InputFileCount] = DefaultFileAlignment;
  481. InputFileSectionType[InputFileCount] = DefaultFileSectionType;
  482. if (ArgumentCount <= 0) {
  483. InputFileCount += 1;
  484. break;
  485. }
  486. //
  487. // Process a section file alignment requirement.
  488. //
  489. if ((strcasecmp(Arguments[0], "-n") == 0) ||
  490. (strcasecmp(Arguments[0], "--sectionalign") == 0)) {
  491. Status = GffsStringtoAlignment(
  492. Arguments[1],
  493. &(InputFileAlignment[InputFileCount]));
  494. if (EFI_ERROR(Status)) {
  495. GFFS_LOG_ERROR("Invalid option value %s = %s.\n",
  496. Arguments[0],
  497. Arguments[1]);
  498. goto mainEnd;
  499. }
  500. ArgumentCount -= 2;
  501. Arguments += 2;
  502. }
  503. //
  504. // Process a section type.
  505. //
  506. if ((strcasecmp(Arguments[0], "-r") == 0) ||
  507. (strcasecmp(Arguments[0], "--sectiontype") == 0)) {
  508. InputFileSectionType[InputFileCount] =
  509. GffsStringToSectionType(Arguments[1]);
  510. if (InputFileSectionType[InputFileCount] == 0) {
  511. GFFS_LOG_ERROR("Invalid section type %s.\n",
  512. Arguments[1]);
  513. goto mainEnd;
  514. }
  515. ArgumentCount -= 2;
  516. Arguments += 2;
  517. }
  518. InputFileCount += 1;
  519. continue;
  520. }
  521. GFFS_LOG_ERROR("Unknown option %s.\n", Arguments[0]);
  522. goto mainEnd;
  523. }
  524. GFFS_LOG_VERBOSE("%s tool start.", UTILITY_NAME);
  525. //
  526. // Check the complete input paramters.
  527. //
  528. if (FileType == EFI_FV_FILETYPE_ALL) {
  529. GFFS_LOG_ERROR("Missing option filetype.\n");
  530. goto mainEnd;
  531. }
  532. if (GffsCompareGuids(&FileGuid, &GffsZeroGuid) != FALSE) {
  533. GFFS_LOG_VERBOSE("Creating random GUID for the file.\n");
  534. GffsCreateRandomGuid(&FileGuid);
  535. }
  536. if (InputFileCount == 0) {
  537. GFFS_LOG_ERROR("Missing option input files.\n");
  538. goto mainEnd;
  539. }
  540. //
  541. // Output input parameter information
  542. //
  543. GFFS_LOG_VERBOSE("Fv File type is %s\n", GffsFileTypes[FileType]);
  544. GFFS_LOG_VERBOSE("Output file name is %s\n", OutputFileName);
  545. GFFS_LOG_VERBOSE("FFS File Guid is "
  546. "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X\n",
  547. (unsigned)FileGuid.Data1,
  548. FileGuid.Data2,
  549. FileGuid.Data3,
  550. FileGuid.Data4[0],
  551. FileGuid.Data4[1],
  552. FileGuid.Data4[2],
  553. FileGuid.Data4[3],
  554. FileGuid.Data4[4],
  555. FileGuid.Data4[5],
  556. FileGuid.Data4[6],
  557. FileGuid.Data4[7]);
  558. if ((Attributes & FFS_ATTRIB_FIXED) != 0) {
  559. GFFS_LOG_VERBOSE("FFS File has the fixed file attribute\n");
  560. }
  561. if ((Attributes & FFS_ATTRIB_CHECKSUM) != 0) {
  562. GFFS_LOG_VERBOSE("FFS File requires the checksum of the whole file\n");
  563. }
  564. GFFS_LOG_VERBOSE("FFS file alignment is %s\n",
  565. GffsValidAlignmentStrings[Alignment]);
  566. for (Index = 0; Index < InputFileCount; Index += 1) {
  567. if (InputFileAlignment[Index] == 0) {
  568. InputFileAlignment[Index] = 1;
  569. }
  570. GFFS_LOG_VERBOSE("the %dth input section name is %s and section "
  571. "alignment s %u\n",
  572. Index,
  573. InputFileName[Index],
  574. (unsigned)InputFileAlignment[Index]);
  575. }
  576. //
  577. // Calculate the size of all input section files.
  578. //
  579. Status = GffsGetSectionContents(InputFileName,
  580. InputFileAlignment,
  581. InputFileSectionType,
  582. InputFileCount,
  583. FileBuffer,
  584. &FileSize,
  585. &MaxAlignment);
  586. if (Status == EFI_BUFFER_TOO_SMALL) {
  587. FileBuffer = (UINT8 *)malloc(FileSize);
  588. if (FileBuffer == NULL) {
  589. goto mainEnd;
  590. }
  591. memset(FileBuffer, 0, FileSize);
  592. //
  593. // Read all input file contents into a buffer.
  594. //
  595. Status = GffsGetSectionContents(InputFileName,
  596. InputFileAlignment,
  597. InputFileSectionType,
  598. InputFileCount,
  599. FileBuffer,
  600. &FileSize,
  601. &MaxAlignment);
  602. }
  603. if (EFI_ERROR(Status)) {
  604. goto mainEnd;
  605. }
  606. //
  607. // Create the Ffs file header.
  608. //
  609. memset(&FfsFileHeader, 0, sizeof(EFI_FFS_FILE_HEADER2));
  610. memcpy(&(FfsFileHeader.Name), &FileGuid, sizeof(EFI_GUID));
  611. FfsFileHeader.Type = FileType;
  612. //
  613. // Update the FFS Alignment based on the max alignment required by input
  614. // section files.
  615. //
  616. GFFS_LOG_VERBOSE("the max alignment of all input sections is %u\n",
  617. (unsigned)MaxAlignment);
  618. for (Index = 0;
  619. Index < sizeof(GffsValidAlignments) / sizeof(UINT32) - 1;
  620. Index += 1) {
  621. if ((MaxAlignment > GffsValidAlignments[Index]) &&
  622. (MaxAlignment <= GffsValidAlignments[Index + 1])) {
  623. break;
  624. }
  625. }
  626. if (Alignment < Index) {
  627. Alignment = Index;
  628. }
  629. GFFS_LOG_VERBOSE("the alignment of the generated FFS file is %u\n",
  630. (unsigned)GffsValidAlignments[Alignment + 1]);
  631. //
  632. // Now the file size includes the EFI_FFS_FILE_HEADER.
  633. //
  634. if (FileSize + sizeof(EFI_FFS_FILE_HEADER) >= MAX_FFS_SIZE) {
  635. HeaderSize = sizeof(EFI_FFS_FILE_HEADER2);
  636. FileSize += sizeof(EFI_FFS_FILE_HEADER2);
  637. FfsFileHeader.ExtendedSize = FileSize;
  638. Attributes |= FFS_ATTRIB_LARGE_FILE;
  639. } else {
  640. HeaderSize = sizeof(EFI_FFS_FILE_HEADER);
  641. FileSize += sizeof(EFI_FFS_FILE_HEADER);
  642. FfsFileHeader.Size[0] = (UINT8)(FileSize & 0xFF);
  643. FfsFileHeader.Size[1] = (UINT8)((FileSize & 0xFF00) >> 8);
  644. FfsFileHeader.Size[2] = (UINT8)((FileSize & 0xFF0000) >> 16);
  645. }
  646. GFFS_LOG_VERBOSE("the size of the generated FFS file is %u bytes\n",
  647. (unsigned)FileSize);
  648. FfsFileHeader.Attributes =
  649. (EFI_FFS_FILE_ATTRIBUTES)(Attributes | (Alignment << 3));
  650. //
  651. // Fill in checksums and state, these must be zero for checksumming
  652. //
  653. // FileHeader.IntegrityCheck.Checksum.Header = 0;
  654. // FileHeader.IntegrityCheck.Checksum.File = 0;
  655. // FileHeader.State = 0;
  656. //
  657. assert((FfsFileHeader.IntegrityCheck.Checksum.Header == 0) &&
  658. (FfsFileHeader.IntegrityCheck.Checksum.File == 0) &&
  659. (FfsFileHeader.State == 0));
  660. FfsFileHeader.IntegrityCheck.Checksum.Header = GffsCalculateChecksum8(
  661. (UINT8 *)&FfsFileHeader,
  662. HeaderSize);
  663. if ((FfsFileHeader.Attributes & FFS_ATTRIB_CHECKSUM) != 0) {
  664. //
  665. // The Ffs header checksum is zero, so just calculate the CRC on the
  666. // FFS body.
  667. //
  668. FfsFileHeader.IntegrityCheck.Checksum.File = GffsCalculateChecksum8(
  669. FileBuffer,
  670. FileSize - HeaderSize);
  671. } else {
  672. FfsFileHeader.IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM;
  673. }
  674. FfsFileHeader.State = EFI_FILE_HEADER_CONSTRUCTION |
  675. EFI_FILE_HEADER_VALID | EFI_FILE_DATA_VALID;
  676. if (OutputFileName == NULL) {
  677. GFFS_LOG_ERROR("Error: output file was not specified.\n");
  678. goto mainEnd;
  679. }
  680. FfsFile = fopen(OutputFileName, "wb");
  681. if (FfsFile == NULL) {
  682. GFFS_LOG_ERROR("Error opening output file %s.\n", OutputFileName);
  683. goto mainEnd;
  684. }
  685. //
  686. // Write the header.
  687. //
  688. fwrite(&FfsFileHeader, 1, HeaderSize, FfsFile);
  689. //
  690. // Write the data.
  691. //
  692. fwrite(FileBuffer, 1, FileSize - HeaderSize, FfsFile);
  693. fclose(FfsFile);
  694. mainEnd:
  695. if (InputFileName != NULL) {
  696. free(InputFileName);
  697. }
  698. if (InputFileAlignment != NULL) {
  699. free(InputFileAlignment);
  700. }
  701. if (InputFileSectionType != NULL) {
  702. free(InputFileSectionType);
  703. }
  704. if (FileBuffer != NULL) {
  705. free(FileBuffer);
  706. }
  707. //
  708. // If any errors were reported via the standard error reporting
  709. // routines, then the status has been saved. Get the value and
  710. // return it to the caller.
  711. //
  712. GFFS_LOG_VERBOSE("%s tool done with return code is 0x%x.\n",
  713. UTILITY_NAME,
  714. GffsErrorOccurred);
  715. return GffsErrorOccurred;
  716. }
  717. //
  718. // --------------------------------------------------------- Internal Functions
  719. //
  720. EFI_STATUS
  721. GffsGetSectionContents (
  722. CHAR8 **InputFileName,
  723. UINT32 *InputFileAlignment,
  724. UINT8 *InputFileSectionType,
  725. UINT32 InputFileCount,
  726. UINT8 *FileBuffer,
  727. UINT32 *BufferLength,
  728. UINT32 *MaxAlignment
  729. )
  730. /*++
  731. Routine Description:
  732. This routine gets the contents of all the given section files.
  733. Arguments:
  734. InputFileName - Supplies the name of the input file.
  735. InputFileAlignment - Supplies an array of alignments for each input file.
  736. InputFileSectionType - Supplies an array of section types for each input
  737. file.
  738. InputFileCount - Supplies the number of input files. This should be at
  739. least 1.
  740. FileBuffer - Supplies buffer where the data will be returned.
  741. BufferLength - Supplies a pointer that on input contains the size of the
  742. file buffer. On output, this is the actual length of the data.
  743. MaxAlignment - Supplies the max alignment required by all the input file
  744. datas.
  745. Return Value:
  746. EFI_SUCCESS on successful return.
  747. EFI_INVALID_PARAMETER if the input file count is less than 1 or buffer
  748. length pointer is NULL.
  749. EFI_ABORTED if unable to open input file.
  750. EFI_BUFFER_TOO_SMALL if the file buffer is not enough to contain all file
  751. data.
  752. --*/
  753. {
  754. UINT32 FileSize;
  755. UINT32 HeaderSize;
  756. UINT32 Index;
  757. FILE *InFile;
  758. size_t ItemsRead;
  759. EFI_COMMON_SECTION_HEADER2 *SectionHeader;
  760. UINT32 SectionSize;
  761. UINT32 Size;
  762. EFI_VERSION_SECTION *VersionSection;
  763. Size = 0;
  764. //
  765. // Go through the array of file names and copy their contents to the output
  766. // buffer.
  767. //
  768. for (Index = 0; Index < InputFileCount; Index += 1) {
  769. //
  770. // Make sure the section ends on a DWORD boundary.
  771. //
  772. while ((Size & 0x03) != 0) {
  773. Size += 1;
  774. }
  775. //
  776. // Get the Max alignment of all input file data.
  777. //
  778. if (*MaxAlignment < InputFileAlignment[Index]) {
  779. *MaxAlignment = InputFileAlignment[Index];
  780. }
  781. InFile = NULL;
  782. if (InputFileAlignment[Index] != 1) {
  783. GFFS_LOG_ERROR("Error: File alignment is not supported.\n");
  784. return EFI_UNSUPPORTED;
  785. }
  786. //
  787. // Compute the header size.
  788. //
  789. switch (InputFileSectionType[Index]) {
  790. case 0:
  791. GFFS_LOG_ERROR("Error: File %s missing section type.\n",
  792. InputFileName[Index]);
  793. return EFI_UNSUPPORTED;
  794. case EFI_SECTION_COMPRESSION:
  795. case EFI_SECTION_GUID_DEFINED:
  796. GFFS_LOG_ERROR("Error: Encapsulation sections not supported.\n");
  797. return EFI_UNSUPPORTED;
  798. case EFI_SECTION_PE32:
  799. case EFI_SECTION_PIC:
  800. case EFI_SECTION_TE:
  801. case EFI_SECTION_DXE_DEPEX:
  802. case EFI_SECTION_COMPATIBILITY16:
  803. case EFI_SECTION_FIRMWARE_VOLUME_IMAGE:
  804. case EFI_SECTION_FREEFORM_SUBTYPE_GUID:
  805. case EFI_SECTION_RAW:
  806. case EFI_SECTION_PEI_DEPEX:
  807. //
  808. // Open the file and read its contents.
  809. //
  810. InFile = fopen(InputFileName[Index], "rb");
  811. if (InFile == NULL) {
  812. GFFS_LOG_ERROR("Error opening file %s.\n",
  813. InputFileName[Index]);
  814. return EFI_ABORTED;
  815. }
  816. fseek(InFile, 0, SEEK_END);
  817. FileSize = ftell(InFile);
  818. fseek(InFile, 0, SEEK_SET);
  819. GFFS_LOG_DEBUG("the input section name is %s and the size is %u "
  820. "bytes.\n",
  821. InputFileName[Index],
  822. (unsigned)FileSize);
  823. if (FileSize >= MAX_FFS_SIZE) {
  824. HeaderSize = sizeof(EFI_COMMON_SECTION_HEADER2);
  825. } else {
  826. HeaderSize = sizeof(EFI_COMMON_SECTION_HEADER);
  827. }
  828. //
  829. // Write the section header out to the buffer.
  830. //
  831. if ((FileBuffer != NULL) && (Size + HeaderSize <= *BufferLength)) {
  832. SectionHeader =
  833. (EFI_COMMON_SECTION_HEADER2 *)(FileBuffer + Size);
  834. SectionSize = FileSize + HeaderSize;
  835. if (FileSize >= MAX_FFS_SIZE) {
  836. SectionHeader->Elements.ExtendedSize = FileSize;
  837. } else {
  838. SectionHeader->AsUint32 = SectionSize & 0x00FFFFFF;
  839. }
  840. SectionHeader->Elements.Type = InputFileSectionType[Index];
  841. }
  842. Size += HeaderSize;
  843. //
  844. // Write the file contents out to the buffer.
  845. //
  846. if ((FileSize > 0) && (FileBuffer != NULL) &&
  847. ((Size + FileSize) <= *BufferLength)) {
  848. ItemsRead = fread(FileBuffer + Size,
  849. (size_t)FileSize,
  850. 1,
  851. InFile);
  852. if (ItemsRead != 1) {
  853. GFFS_LOG_ERROR("Error reading file %s.\n",
  854. InputFileName[Index]);
  855. fclose(InFile);
  856. return EFI_ABORTED;
  857. }
  858. }
  859. fclose(InFile);
  860. Size += FileSize;
  861. break;
  862. //
  863. // For version sections, the file name is actually the version
  864. // information.
  865. //
  866. case EFI_SECTION_VERSION:
  867. HeaderSize = sizeof(EFI_VERSION_SECTION);
  868. FileSize = (strlen(InputFileName[Index]) + 1) * sizeof(CHAR16);
  869. SectionSize = HeaderSize + FileSize;
  870. if ((FileBuffer != NULL) && (Size + HeaderSize <= *BufferLength)) {
  871. VersionSection = (EFI_VERSION_SECTION *)(FileBuffer + Size);
  872. VersionSection->CommonHeader.AsUint32 =
  873. SectionSize & 0x00FFFFFF;
  874. VersionSection->CommonHeader.Elements.Type =
  875. EFI_SECTION_VERSION;
  876. VersionSection->BuildNumber = strtoul(InputFileName[Index],
  877. NULL,
  878. 0);
  879. }
  880. Size += HeaderSize;
  881. if ((FileSize > 0) && (FileBuffer != NULL) &&
  882. ((Size + FileSize) <= *BufferLength)) {
  883. GffsConvertAsciiStringToUnicode(InputFileName[Index],
  884. (CHAR16 *)(FileBuffer + Size));
  885. }
  886. Size += FileSize;
  887. break;
  888. //
  889. // For user interface sections, the file name is the value of the
  890. // section.
  891. //
  892. case EFI_SECTION_USER_INTERFACE:
  893. HeaderSize = sizeof(EFI_COMMON_SECTION_HEADER);
  894. FileSize = (strlen(InputFileName[Index]) + 1) * sizeof(CHAR16);
  895. SectionSize = HeaderSize + FileSize;
  896. if ((FileBuffer != NULL) && (Size + HeaderSize <= *BufferLength)) {
  897. SectionHeader =
  898. (EFI_COMMON_SECTION_HEADER2 *)(FileBuffer + Size);
  899. SectionHeader->AsUint32 = SectionSize & 0x00FFFFFF;
  900. SectionHeader->Elements.Type = InputFileSectionType[Index];
  901. }
  902. Size += HeaderSize;
  903. if ((FileSize > 0) && (FileBuffer != NULL) &&
  904. ((Size + FileSize) <= *BufferLength)) {
  905. GffsConvertAsciiStringToUnicode(InputFileName[Index],
  906. (CHAR16 *)(FileBuffer + Size));
  907. }
  908. Size += FileSize;
  909. break;
  910. default:
  911. GFFS_LOG_ERROR("Error: Unsupported section type %d.\n",
  912. InputFileSectionType[Index]);
  913. return EFI_UNSUPPORTED;
  914. }
  915. }
  916. //
  917. // Set the actual length of the data.
  918. //
  919. if (Size > *BufferLength) {
  920. *BufferLength = Size;
  921. return EFI_BUFFER_TOO_SMALL;
  922. }
  923. *BufferLength = Size;
  924. return EFI_SUCCESS;
  925. }
  926. UINT8
  927. GffsStringToType (
  928. CHAR8 *String
  929. )
  930. /*++
  931. Routine Description:
  932. This routine converts a file type string to a file type value. The value
  933. EFI_FV_FILETYPE_ALL indicates that an unrecognized file type was specified.
  934. Arguments:
  935. String - Supplies the file type string.
  936. Return Value:
  937. Returns the file type value.
  938. --*/
  939. {
  940. UINTN Index;
  941. if (String == NULL) {
  942. return EFI_FV_FILETYPE_ALL;
  943. }
  944. for (Index = 0;
  945. Index < sizeof(GffsFileTypes) / sizeof(CHAR8 *);
  946. Index += 1) {
  947. if ((GffsFileTypes[Index] != NULL) &&
  948. (strcasecmp(String, GffsFileTypes[Index]) == 0)) {
  949. return Index;
  950. }
  951. }
  952. return EFI_FV_FILETYPE_ALL;
  953. }
  954. UINT8
  955. GffsStringToSectionType (
  956. CHAR8 *String
  957. )
  958. /*++
  959. Routine Description:
  960. This routine converts a file section type string to a file section value.
  961. Arguments:
  962. String - Supplies the file section string.
  963. Return Value:
  964. Returns the file section value.
  965. --*/
  966. {
  967. UINTN Index;
  968. if (String == NULL) {
  969. return EFI_FV_FILETYPE_ALL;
  970. }
  971. for (Index = 0;
  972. Index < sizeof(GffsFileSectionTypes) / sizeof(CHAR8 *);
  973. Index += 1) {
  974. if ((GffsFileSectionTypes[Index] != NULL) &&
  975. (strcasecmp(String, GffsFileSectionTypes[Index]) == 0)) {
  976. return Index;
  977. }
  978. }
  979. return 0;
  980. }
  981. EFI_STATUS
  982. GffsStringtoAlignment (
  983. CHAR8 *AlignBuffer,
  984. UINT32 *AlignNumber
  985. )
  986. /*++
  987. Routine Description:
  988. This routine converts an alignment string to an alignment value in the
  989. range of 1 to 64K.
  990. Arguments:
  991. AlignBuffer - Supplies a pointer to the alignment string.
  992. AlignNumber - Supplies a pointer where the alignment value will be returned
  993. on success.
  994. Return Value:
  995. EFI_SUCCESS if a value was converted successfully.
  996. EFI_INVALID_PARAMETER if the alignment string is invalid or align value is
  997. not in scope.
  998. --*/
  999. {
  1000. UINT32 Index;
  1001. if (AlignBuffer == NULL) {
  1002. return EFI_INVALID_PARAMETER;
  1003. }
  1004. for (Index = 0;
  1005. Index < sizeof(GffsAlignmentStrings) / sizeof(CHAR8 *);
  1006. Index += 1) {
  1007. if (strcasecmp(AlignBuffer, GffsAlignmentStrings[Index]) == 0) {
  1008. *AlignNumber = 1 << Index;
  1009. return EFI_SUCCESS;
  1010. }
  1011. }
  1012. return EFI_INVALID_PARAMETER;
  1013. }
  1014. EFI_STATUS
  1015. GffsStringToGuid (
  1016. CHAR8 *AsciiGuidBuffer,
  1017. EFI_GUID *GuidBuffer
  1018. )
  1019. /*++
  1020. Routine Description:
  1021. This routine converts a string to an EFI_GUID. The string must be in the
  1022. xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx format.
  1023. Arguments:
  1024. AsciiGuidBuffer - Supplies a pointer to ascii string.
  1025. GuidBuffer - Supplies a pointer where the GUID will be returned on
  1026. success.
  1027. Return Value:
  1028. EFI_ABORTED if the string could not be converted.
  1029. EFI_SUCCESS if the string was successfully converted.
  1030. EFI_INVALID_PARAMETER if the input parameter is not valid.
  1031. --*/
  1032. {
  1033. unsigned Data1;
  1034. unsigned Data2;
  1035. unsigned Data3;
  1036. unsigned Data4[8];
  1037. INT32 Index;
  1038. if (AsciiGuidBuffer == NULL || GuidBuffer == NULL) {
  1039. return EFI_INVALID_PARAMETER;
  1040. }
  1041. //
  1042. // Check that the Guid Format is strictly
  1043. // xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
  1044. //
  1045. for (Index = 0;
  1046. (AsciiGuidBuffer[Index] != '\0') && (Index < 37);
  1047. Index += 1) {
  1048. if ((Index == 8) || (Index == 13) || (Index == 18) || (Index == 23)) {
  1049. if (AsciiGuidBuffer[Index] != '-') {
  1050. break;
  1051. }
  1052. } else {
  1053. if (((AsciiGuidBuffer[Index] >= '0') &&
  1054. (AsciiGuidBuffer[Index] <= '9')) ||
  1055. ((AsciiGuidBuffer[Index] >= 'a') &&
  1056. (AsciiGuidBuffer[Index] <= 'f')) ||
  1057. ((AsciiGuidBuffer[Index] >= 'A') &&
  1058. (AsciiGuidBuffer[Index] <= 'F'))) {
  1059. continue;
  1060. } else {
  1061. break;
  1062. }
  1063. }
  1064. }
  1065. if ((Index < 36) || (AsciiGuidBuffer[36] != '\0')) {
  1066. GFFS_LOG_ERROR("Incorrect GUID \"%s\"\n"
  1067. "Correct Format \"xxxxxxxx-xxxx-xxxx-xxxx-"
  1068. "xxxxxxxxxxxx\".\n",
  1069. AsciiGuidBuffer);
  1070. return EFI_ABORTED;
  1071. }
  1072. //
  1073. // Scan the guid string into the buffer.
  1074. //
  1075. Index = sscanf(AsciiGuidBuffer,
  1076. "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
  1077. &Data1,
  1078. &Data2,
  1079. &Data3,
  1080. &Data4[0],
  1081. &Data4[1],
  1082. &Data4[2],
  1083. &Data4[3],
  1084. &Data4[4],
  1085. &Data4[5],
  1086. &Data4[6],
  1087. &Data4[7]);
  1088. //
  1089. // Verify the correct number of items were scanned.
  1090. //
  1091. if (Index != 11) {
  1092. GFFS_LOG_ERROR("Incorrect GUID \"%s\"\n"
  1093. "Correct Format \"xxxxxxxx-xxxx-xxxx-xxxx-"
  1094. "xxxxxxxxxxxx\".\n",
  1095. AsciiGuidBuffer);
  1096. return EFI_ABORTED;
  1097. }
  1098. //
  1099. // Copy the data into the output GUID.
  1100. //
  1101. GuidBuffer->Data1 = (UINT32)Data1;
  1102. GuidBuffer->Data2 = (UINT16)Data2;
  1103. GuidBuffer->Data3 = (UINT16)Data3;
  1104. GuidBuffer->Data4[0] = (UINT8)Data4[0];
  1105. GuidBuffer->Data4[1] = (UINT8)Data4[1];
  1106. GuidBuffer->Data4[2] = (UINT8)Data4[2];
  1107. GuidBuffer->Data4[3] = (UINT8)Data4[3];
  1108. GuidBuffer->Data4[4] = (UINT8)Data4[4];
  1109. GuidBuffer->Data4[5] = (UINT8)Data4[5];
  1110. GuidBuffer->Data4[6] = (UINT8)Data4[6];
  1111. GuidBuffer->Data4[7] = (UINT8)Data4[7];
  1112. return EFI_SUCCESS;
  1113. }
  1114. VOID
  1115. GffsConvertAsciiStringToUnicode (
  1116. CHAR8 *String,
  1117. CHAR16 *UnicodeString
  1118. )
  1119. /*++
  1120. Routine Description:
  1121. This routine converts and ASCII string into a unicode string.
  1122. Arguments:
  1123. String - Supplies a pointer to the ASCII string.
  1124. UnicodeString - Supplies a pointer to the Unicode string.
  1125. Return Value:
  1126. None.
  1127. --*/
  1128. {
  1129. while (*String != '\0') {
  1130. *UnicodeString = (CHAR16)*String;
  1131. String += 1;
  1132. UnicodeString += 1;
  1133. }
  1134. *UnicodeString = L'\0';
  1135. }
  1136. VOID
  1137. GffsCreateRandomGuid (
  1138. EFI_GUID *Guid
  1139. )
  1140. /*++
  1141. Routine Description:
  1142. This routine creates a random GUID.
  1143. Arguments:
  1144. Guid - Supplies a pointer where the GUID will be returned.
  1145. Return Value:
  1146. None.
  1147. --*/
  1148. {
  1149. UINT16 *Buffer;
  1150. UINTN BufferSize;
  1151. int Value;
  1152. Buffer = (UINT16 *)Guid;
  1153. BufferSize = sizeof(EFI_GUID) / sizeof(UINT16);
  1154. while (BufferSize != 0) {
  1155. Value = rand();
  1156. *Buffer = Value;
  1157. Buffer += 1;
  1158. BufferSize -= 1;
  1159. }
  1160. return;
  1161. }
  1162. UINT8
  1163. GffsCalculateChecksum8 (
  1164. UINT8 *Buffer,
  1165. UINTN Size
  1166. )
  1167. /*++
  1168. Routine Description:
  1169. This routine calculates the value needed for a valid UINT8 checksum.
  1170. Arguments:
  1171. Buffer - Supplies a pointer to a buffer containing byte data.
  1172. Size - Supplies the size of the buffer.
  1173. Return Value:
  1174. Returns the 8-bit checksum of the field.
  1175. --*/
  1176. {
  1177. return (UINT8)(0x100 - GffsCalculateSum8(Buffer, Size));
  1178. }
  1179. UINT8
  1180. GffsCalculateSum8 (
  1181. UINT8 *Buffer,
  1182. UINTN Size
  1183. )
  1184. /*++
  1185. Routine Description:
  1186. This routine calculates the sum of the bytes in the given buffer.
  1187. Arguments:
  1188. Buffer - Supplies a pointer to a buffer containing byte data.
  1189. Size - Supplies the size of the buffer.
  1190. Return Value:
  1191. Returns the 8-bit sum of each byte in the buffer.
  1192. --*/
  1193. {
  1194. UINTN Index;
  1195. UINT8 Sum;
  1196. Sum = 0;
  1197. for (Index = 0; Index < Size; Index += 1) {
  1198. Sum = (UINT8)(Sum + Buffer[Index]);
  1199. }
  1200. return Sum;
  1201. }
  1202. BOOLEAN
  1203. GffsCompareGuids (
  1204. EFI_GUID *FirstGuid,
  1205. EFI_GUID *SecondGuid
  1206. )
  1207. /*++
  1208. Routine Description:
  1209. This routine compares two GUIDs.
  1210. Arguments:
  1211. FirstGuid - Supplies a pointer to the first GUID.
  1212. SecondGuid - Supplies a pointer to the second GUID.
  1213. Return Value:
  1214. TRUE if the GUIDs are equal.
  1215. FALSE if the GUIDs are different.
  1216. --*/
  1217. {
  1218. UINT32 *FirstPointer;
  1219. UINT32 *SecondPointer;
  1220. //
  1221. // Compare GUIDs 32 bits at a time.
  1222. //
  1223. FirstPointer = (UINT32 *)FirstGuid;
  1224. SecondPointer = (UINT32 *)SecondGuid;
  1225. if ((FirstPointer[0] == SecondPointer[0]) &&
  1226. (FirstPointer[1] == SecondPointer[1]) &&
  1227. (FirstPointer[2] == SecondPointer[2]) &&
  1228. (FirstPointer[3] == SecondPointer[3])) {
  1229. return TRUE;
  1230. }
  1231. return FALSE;
  1232. }
  1233. VOID
  1234. GffsPrintVersion (
  1235. VOID
  1236. )
  1237. /*++
  1238. Routine Description:
  1239. This routine prints the utility version information.
  1240. Arguments:
  1241. None.
  1242. Return Value:
  1243. None.
  1244. --*/
  1245. {
  1246. fprintf(stdout,
  1247. "%s Version %d.%d\n",
  1248. UTILITY_NAME,
  1249. UTILITY_MAJOR_VERSION,
  1250. UTILITY_MINOR_VERSION);
  1251. return;
  1252. }
  1253. VOID
  1254. GffsPrintUsage (
  1255. VOID
  1256. )
  1257. /*++
  1258. Routine Description:
  1259. This routine prints application usage information.
  1260. Arguments:
  1261. None.
  1262. Return Value:
  1263. None.
  1264. --*/
  1265. {
  1266. fprintf(stdout,
  1267. "\n%s Creates a single FFS file from one or more input files.\n",
  1268. UTILITY_NAME);
  1269. fprintf(stdout, "\nUsage: %s [options] [files...]\n\n", UTILITY_NAME);
  1270. fprintf(stdout, "Options:\n");
  1271. fprintf(stdout,
  1272. " -r SectionType, --sectiontype SectionType\n"
  1273. "Define the section type of the input file just specified. \n"
  1274. "Valid values are EFI_SECTION_COMPRESSION, \n"
  1275. "EFI_SECTION_GUID_DEFINED, EFI_SECTION_PE32, EFI_SECTION_PIC, \n"
  1276. "EFI_SECTION_TE, EFI_SECTION_DXE_DEPEX, \n"
  1277. "EFI_SECTION_COMPATIBILITY16, EFI_SECTION_USER_INTERFACE, \n"
  1278. "EFI_SECTION_VERSION, EFI_SECTION_FIRMWARE_VOLUME_IMAGE, \n"
  1279. "EFI_SECTION_RAW, EFI_SECTION_FREEFORM_SUBTYPE_GUID, \n"
  1280. "EFI_SECTION_PEI_DEPEX, EFI_SECTION_SMM_DEPEX.\n\n"
  1281. " -o FileName, --outputfile FileName\n"
  1282. "File is FFS file to be created.\n"
  1283. " -t Type, --filetype Type\n"
  1284. "Type is one FV file type defined in PI spec, which is\n"
  1285. "EFI_FV_FILETYPE_RAW, EFI_FV_FILETYPE_FREEFORM,\n"
  1286. "EFI_FV_FILETYPE_SECURITY_CORE, EFI_FV_FILETYPE_PEIM,\n"
  1287. "EFI_FV_FILETYPE_PEI_CORE, EFI_FV_FILETYPE_DXE_CORE,\n"
  1288. "EFI_FV_FILETYPE_DRIVER, EFI_FV_FILETYPE_APPLICATION,\n"
  1289. "EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER,\n"
  1290. "EFI_FV_FILETYPE_SMM, EFI_FV_FILETYPE_SMM_CORE,\n"
  1291. "EFI_FV_FILETYPE_COMBINED_SMM_DXE, \n"
  1292. "EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE.\n\n"
  1293. " -g FileGuid, --fileguid FileGuid\n"
  1294. "FileGuid is one module guid.\n"
  1295. "Its format is xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\n"
  1296. " -x, --fixed Indicates that the file may not be moved\n"
  1297. "from its present location.\n"
  1298. " -s, --checksum Indicates to calculate file checksum.\n"
  1299. " -a FileAlign, --align FileAlign\n"
  1300. "FileAlign points to file alignment, which only support\n"
  1301. "the following align: 1,2,4,8,16,128,512,1K,4K,32K,64K\n"
  1302. " -i SectionFile, --sectionfile SectionFile\n"
  1303. "Section file will be contained in this FFS file.\n"
  1304. " -n SectionAlign, --sectionalign SectionAlign\n"
  1305. "SectionAlign points to section alignment, which support\n"
  1306. "the alignment scope 1~64K. It is specified together\n"
  1307. "with sectionfile to point its alignment in FFS file.\n"
  1308. " -v, --verbose Turn on verbose output with informational "
  1309. "messages.\n"
  1310. " -q, --quiet Disable all messages except key message "
  1311. "and fatal error\n"
  1312. " -d, --debug level Enable debug messages, at input debug "
  1313. "level.\n"
  1314. " --version Show program's version number "
  1315. "and exit.\n"
  1316. " -h, --help Show this help message and exit.\n");
  1317. return;
  1318. }