GenSec.c 60 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817
  1. /** @file
  2. Creates output file that is a properly formed section per the PI spec.
  3. Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>
  4. This program and the accompanying materials
  5. are licensed and made available under the terms and conditions of the BSD License
  6. which accompanies this distribution. The full text of the license may be found at
  7. http://opensource.org/licenses/bsd-license.php
  8. THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
  10. **/
  11. #ifndef __GNUC__
  12. #include <windows.h>
  13. #include <io.h>
  14. #include <sys/types.h>
  15. #include <sys/stat.h>
  16. #endif
  17. #include <stdio.h>
  18. #include <stdlib.h>
  19. #include <string.h>
  20. #include <ctype.h>
  21. #include <Common/UefiBaseTypes.h>
  22. #include <Common/PiFirmwareFile.h>
  23. #include <Protocol/GuidedSectionExtraction.h>
  24. #include <IndustryStandard/PeImage.h>
  25. #include "CommonLib.h"
  26. #include "Compress.h"
  27. #include "Crc32.h"
  28. #include "EfiUtilityMsgs.h"
  29. #include "ParseInf.h"
  30. #include "FvLib.h"
  31. #include "PeCoffLib.h"
  32. //
  33. // GenSec Tool Information
  34. //
  35. #define UTILITY_NAME "GenSec"
  36. #define UTILITY_MAJOR_VERSION 0
  37. #define UTILITY_MINOR_VERSION 1
  38. STATIC CHAR8 *mSectionTypeName[] = {
  39. NULL, // 0x00 - reserved
  40. "EFI_SECTION_COMPRESSION", // 0x01
  41. "EFI_SECTION_GUID_DEFINED", // 0x02
  42. NULL, // 0x03 - reserved
  43. NULL, // 0x04 - reserved
  44. NULL, // 0x05 - reserved
  45. NULL, // 0x06 - reserved
  46. NULL, // 0x07 - reserved
  47. NULL, // 0x08 - reserved
  48. NULL, // 0x09 - reserved
  49. NULL, // 0x0A - reserved
  50. NULL, // 0x0B - reserved
  51. NULL, // 0x0C - reserved
  52. NULL, // 0x0D - reserved
  53. NULL, // 0x0E - reserved
  54. NULL, // 0x0F - reserved
  55. "EFI_SECTION_PE32", // 0x10
  56. "EFI_SECTION_PIC", // 0x11
  57. "EFI_SECTION_TE", // 0x12
  58. "EFI_SECTION_DXE_DEPEX", // 0x13
  59. "EFI_SECTION_VERSION", // 0x14
  60. "EFI_SECTION_USER_INTERFACE", // 0x15
  61. "EFI_SECTION_COMPATIBILITY16", // 0x16
  62. "EFI_SECTION_FIRMWARE_VOLUME_IMAGE", // 0x17
  63. "EFI_SECTION_FREEFORM_SUBTYPE_GUID", // 0x18
  64. "EFI_SECTION_RAW", // 0x19
  65. NULL, // 0x1A
  66. "EFI_SECTION_PEI_DEPEX", // 0x1B
  67. "EFI_SECTION_SMM_DEPEX" // 0x1C
  68. };
  69. STATIC CHAR8 *mCompressionTypeName[] = { "PI_NONE", "PI_STD" };
  70. #define EFI_GUIDED_SECTION_NONE 0x80
  71. STATIC CHAR8 *mGUIDedSectionAttribue[] = { "NONE", "PROCESSING_REQUIRED", "AUTH_STATUS_VALID"};
  72. STATIC CHAR8 *mAlignName[] = {
  73. "1", "2", "4", "8", "16", "32", "64", "128", "256", "512",
  74. "1K", "2K", "4K", "8K", "16K", "32K", "64K", "128K", "256K",
  75. "512K", "1M", "2M", "4M", "8M", "16M"
  76. };
  77. //
  78. // Crc32 GUID section related definitions.
  79. //
  80. typedef struct {
  81. EFI_GUID_DEFINED_SECTION GuidSectionHeader;
  82. UINT32 CRC32Checksum;
  83. } CRC32_SECTION_HEADER;
  84. typedef struct {
  85. EFI_GUID_DEFINED_SECTION2 GuidSectionHeader;
  86. UINT32 CRC32Checksum;
  87. } CRC32_SECTION_HEADER2;
  88. STATIC EFI_GUID mZeroGuid = {0x0, 0x0, 0x0, {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}};
  89. STATIC EFI_GUID mEfiCrc32SectionGuid = EFI_CRC32_GUIDED_SECTION_EXTRACTION_PROTOCOL_GUID;
  90. STATIC
  91. VOID
  92. Version (
  93. VOID
  94. )
  95. /*++
  96. Routine Description:
  97. Print out version information for this utility.
  98. Arguments:
  99. None
  100. Returns:
  101. None
  102. --*/
  103. {
  104. fprintf (stdout, "%s Version %d.%d %s \n", UTILITY_NAME, UTILITY_MAJOR_VERSION, UTILITY_MINOR_VERSION, __BUILD_VERSION);
  105. }
  106. STATIC
  107. VOID
  108. Usage (
  109. VOID
  110. )
  111. /*++
  112. Routine Description:
  113. Print Help message.
  114. Arguments:
  115. VOID
  116. Returns:
  117. None
  118. --*/
  119. {
  120. //
  121. // Summary usage
  122. //
  123. fprintf (stdout, "\nUsage: %s [options] [input_file]\n\n", UTILITY_NAME);
  124. //
  125. // Copyright declaration
  126. //
  127. fprintf (stdout, "Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.\n\n");
  128. //
  129. // Details Option
  130. //
  131. fprintf (stdout, "Options:\n");
  132. fprintf (stdout, " -o FileName, --outputfile FileName\n\
  133. File is the SectionFile to be created.\n");
  134. fprintf (stdout, " -s [SectionType], --sectiontype [SectionType]\n\
  135. SectionType defined in PI spec is one type of\n\
  136. EFI_SECTION_COMPRESSION, EFI_SECTION_GUID_DEFINED,\n\
  137. EFI_SECTION_PE32, EFI_SECTION_PIC, EFI_SECTION_TE,\n\
  138. EFI_SECTION_DXE_DEPEX, EFI_SECTION_COMPATIBILITY16,\n\
  139. EFI_SECTION_USER_INTERFACE, EFI_SECTION_VERSION,\n\
  140. EFI_SECTION_FIRMWARE_VOLUME_IMAGE, EFI_SECTION_RAW,\n\
  141. EFI_SECTION_FREEFORM_SUBTYPE_GUID,\n\
  142. EFI_SECTION_PEI_DEPEX, EFI_SECTION_SMM_DEPEX.\n\
  143. if -s option is not given, \n\
  144. EFI_SECTION_ALL is default section type.\n");
  145. fprintf (stdout, " -c [Type], --compress [Type]\n\
  146. Compress method type can be PI_NONE or PI_STD.\n\
  147. if -c option is not given, PI_STD is default type.\n");
  148. fprintf (stdout, " -g GuidValue, --vendor GuidValue\n\
  149. GuidValue is one specific vendor guid value.\n\
  150. Its format is xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\n");
  151. fprintf (stdout, " -l GuidHeaderLength, --HeaderLength GuidHeaderLength\n\
  152. GuidHeaderLength is the size of header of guided data\n");
  153. fprintf (stdout, " -r GuidAttr, --attributes GuidAttr\n\
  154. GuidAttr is guid section atttributes, which may be\n\
  155. PROCESSING_REQUIRED, AUTH_STATUS_VALID and NONE. \n\
  156. if -r option is not given, default PROCESSING_REQUIRED\n");
  157. fprintf (stdout, " -n String, --name String\n\
  158. String is a NULL terminated string used in Ui section.\n");
  159. fprintf (stdout, " -j Number, --buildnumber Number\n\
  160. Number is an integer value between 0 and 65535\n\
  161. used in Ver section.\n");
  162. fprintf (stdout, " --sectionalign SectionAlign\n\
  163. SectionAlign points to section alignment, which support\n\
  164. the alignment scope 0~16M. If SectionAlign is specified\n\
  165. as 0, tool get alignment value from SectionFile. It is\n\
  166. specified in same order that the section file is input.\n");
  167. fprintf (stdout, " --dummy dummyfile\n\
  168. compare dummpyfile with input_file to decide whether\n\
  169. need to set PROCESSING_REQUIRED attribute.\n");
  170. fprintf (stdout, " -v, --verbose Turn on verbose output with informational messages.\n");
  171. fprintf (stdout, " -q, --quiet Disable all messages except key message and fatal error\n");
  172. fprintf (stdout, " -d, --debug level Enable debug messages, at input debug level.\n");
  173. fprintf (stdout, " --version Show program's version number and exit.\n");
  174. fprintf (stdout, " -h, --help Show this help message and exit.\n");
  175. }
  176. VOID
  177. Ascii2UnicodeString (
  178. CHAR8 *String,
  179. CHAR16 *UniString
  180. )
  181. /*++
  182. Routine Description:
  183. Write ascii string as unicode string format to FILE
  184. Arguments:
  185. String - Pointer to string that is written to FILE.
  186. UniString - Pointer to unicode string
  187. Returns:
  188. NULL
  189. --*/
  190. {
  191. while (*String != '\0') {
  192. *(UniString++) = (CHAR16) *(String++);
  193. }
  194. //
  195. // End the UniString with a NULL.
  196. //
  197. *UniString = '\0';
  198. }
  199. STATUS
  200. GenSectionCommonLeafSection (
  201. CHAR8 **InputFileName,
  202. UINT32 InputFileNum,
  203. UINT8 SectionType,
  204. UINT8 **OutFileBuffer
  205. )
  206. /*++
  207. Routine Description:
  208. Generate a leaf section of type other than EFI_SECTION_VERSION
  209. and EFI_SECTION_USER_INTERFACE. Input file must be well formed.
  210. The function won't validate the input file's contents. For
  211. common leaf sections, the input file may be a binary file.
  212. The utility will add section header to the file.
  213. Arguments:
  214. InputFileName - Name of the input file.
  215. InputFileNum - Number of input files. Should be 1 for leaf section.
  216. SectionType - A valid section type string
  217. OutFileBuffer - Buffer pointer to Output file contents
  218. Returns:
  219. STATUS_ERROR - can't continue
  220. STATUS_SUCCESS - successful return
  221. --*/
  222. {
  223. UINT32 InputFileLength;
  224. FILE *InFile;
  225. UINT8 *Buffer;
  226. UINT32 TotalLength;
  227. UINT32 HeaderLength;
  228. EFI_COMMON_SECTION_HEADER *CommonSect;
  229. STATUS Status;
  230. if (InputFileNum > 1) {
  231. Error (NULL, 0, 2000, "Invalid parameter", "more than one input file specified");
  232. return STATUS_ERROR;
  233. } else if (InputFileNum < 1) {
  234. Error (NULL, 0, 2000, "Invalid parameter", "no input file specified");
  235. return STATUS_ERROR;
  236. }
  237. //
  238. // Open the input file
  239. //
  240. InFile = fopen (LongFilePath (InputFileName[0]), "rb");
  241. if (InFile == NULL) {
  242. Error (NULL, 0, 0001, "Error opening file", InputFileName[0]);
  243. return STATUS_ERROR;
  244. }
  245. Status = STATUS_ERROR;
  246. Buffer = NULL;
  247. //
  248. // Seek to the end of the input file so we can determine its size
  249. //
  250. fseek (InFile, 0, SEEK_END);
  251. InputFileLength = ftell (InFile);
  252. fseek (InFile, 0, SEEK_SET);
  253. DebugMsg (NULL, 0, 9, "Input file", "File name is %s and File size is %u bytes", InputFileName[0], (unsigned) InputFileLength);
  254. TotalLength = sizeof (EFI_COMMON_SECTION_HEADER) + InputFileLength;
  255. //
  256. // Size must fit in 3 bytes
  257. //
  258. //if (TotalLength >= MAX_SECTION_SIZE) {
  259. // Error (NULL, 0, 2000, "Invalid parameter", "%s file size (0x%X) exceeds section size limit(%uM).", InputFileName[0], (unsigned) TotalLength, MAX_SECTION_SIZE>>20);
  260. // goto Done;
  261. //}
  262. HeaderLength = sizeof (EFI_COMMON_SECTION_HEADER);
  263. if (TotalLength >= MAX_SECTION_SIZE) {
  264. TotalLength = sizeof (EFI_COMMON_SECTION_HEADER2) + InputFileLength;
  265. HeaderLength = sizeof (EFI_COMMON_SECTION_HEADER2);
  266. }
  267. VerboseMsg ("the size of the created section file is %u bytes", (unsigned) TotalLength);
  268. //
  269. // Fill in the fields in the local section header structure
  270. //
  271. Buffer = (UINT8 *) malloc ((size_t) TotalLength);
  272. if (Buffer == NULL) {
  273. Error (NULL, 0, 4001, "Resource", "memory cannot be allocated");
  274. goto Done;
  275. }
  276. CommonSect = (EFI_COMMON_SECTION_HEADER *) Buffer;
  277. CommonSect->Type = SectionType;
  278. if (TotalLength < MAX_SECTION_SIZE) {
  279. CommonSect->Size[0] = (UINT8) (TotalLength & 0xff);
  280. CommonSect->Size[1] = (UINT8) ((TotalLength & 0xff00) >> 8);
  281. CommonSect->Size[2] = (UINT8) ((TotalLength & 0xff0000) >> 16);
  282. } else {
  283. memset(CommonSect->Size, 0xff, sizeof(UINT8) * 3);
  284. ((EFI_COMMON_SECTION_HEADER2 *)CommonSect)->ExtendedSize = TotalLength;
  285. }
  286. //
  287. // read data from the input file.
  288. //
  289. if (InputFileLength != 0) {
  290. if (fread (Buffer + HeaderLength, (size_t) InputFileLength, 1, InFile) != 1) {
  291. Error (NULL, 0, 0004, "Error reading file", InputFileName[0]);
  292. goto Done;
  293. }
  294. }
  295. //
  296. // Set OutFileBuffer
  297. //
  298. *OutFileBuffer = Buffer;
  299. Status = STATUS_SUCCESS;
  300. Done:
  301. fclose (InFile);
  302. return Status;
  303. }
  304. STATIC
  305. EFI_STATUS
  306. StringtoAlignment (
  307. IN CHAR8 *AlignBuffer,
  308. OUT UINT32 *AlignNumber
  309. )
  310. /*++
  311. Routine Description:
  312. Converts Align String to align value (1~16M).
  313. Arguments:
  314. AlignBuffer - Pointer to Align string.
  315. AlignNumber - Pointer to Align value.
  316. Returns:
  317. EFI_SUCCESS Successfully convert align string to align value.
  318. EFI_INVALID_PARAMETER Align string is invalid or align value is not in scope.
  319. --*/
  320. {
  321. UINT32 Index = 0;
  322. //
  323. // Check AlignBuffer
  324. //
  325. if (AlignBuffer == NULL) {
  326. return EFI_INVALID_PARAMETER;
  327. }
  328. for (Index = 0; Index < sizeof (mAlignName) / sizeof (CHAR8 *); Index ++) {
  329. if (stricmp (AlignBuffer, mAlignName [Index]) == 0) {
  330. *AlignNumber = 1 << Index;
  331. return EFI_SUCCESS;
  332. }
  333. }
  334. return EFI_INVALID_PARAMETER;
  335. }
  336. EFI_STATUS
  337. GetSectionContents (
  338. CHAR8 **InputFileName,
  339. UINT32 *InputFileAlign,
  340. UINT32 InputFileNum,
  341. UINT8 *FileBuffer,
  342. UINT32 *BufferLength
  343. )
  344. /*++
  345. Routine Description:
  346. Get the contents of all section files specified in InputFileName
  347. into FileBuffer.
  348. Arguments:
  349. InputFileName - Name of the input file.
  350. InputFileAlign - Alignment required by the input file data.
  351. InputFileNum - Number of input files. Should be at least 1.
  352. FileBuffer - Output buffer to contain data
  353. BufferLength - On input, this is size of the FileBuffer.
  354. On output, this is the actual length of the data.
  355. Returns:
  356. EFI_SUCCESS on successful return
  357. EFI_INVALID_PARAMETER if InputFileNum is less than 1 or BufferLength point is NULL.
  358. EFI_ABORTED if unable to open input file.
  359. EFI_BUFFER_TOO_SMALL FileBuffer is not enough to contain all file data.
  360. --*/
  361. {
  362. UINT32 Size;
  363. UINT32 Offset;
  364. UINT32 FileSize;
  365. UINT32 Index;
  366. FILE *InFile;
  367. EFI_COMMON_SECTION_HEADER *SectHeader;
  368. EFI_COMMON_SECTION_HEADER2 TempSectHeader;
  369. EFI_TE_IMAGE_HEADER TeHeader;
  370. UINT32 TeOffset;
  371. EFI_GUID_DEFINED_SECTION GuidSectHeader;
  372. EFI_GUID_DEFINED_SECTION2 GuidSectHeader2;
  373. UINT32 HeaderSize;
  374. if (InputFileNum < 1) {
  375. Error (NULL, 0, 2000, "Invalid parameter", "must specify at least one input file");
  376. return EFI_INVALID_PARAMETER;
  377. }
  378. if (BufferLength == NULL) {
  379. Error (NULL, 0, 2000, "Invalid parameter", "BufferLength can't be NULL");
  380. return EFI_INVALID_PARAMETER;
  381. }
  382. Size = 0;
  383. Offset = 0;
  384. TeOffset = 0;
  385. //
  386. // Go through our array of file names and copy their contents
  387. // to the output buffer.
  388. //
  389. for (Index = 0; Index < InputFileNum; Index++) {
  390. //
  391. // make sure section ends on a DWORD boundary
  392. //
  393. while ((Size & 0x03) != 0) {
  394. if (FileBuffer != NULL && Size < *BufferLength) {
  395. FileBuffer[Size] = 0;
  396. }
  397. Size++;
  398. }
  399. //
  400. // Open file and read contents
  401. //
  402. InFile = fopen (LongFilePath (InputFileName[Index]), "rb");
  403. if (InFile == NULL) {
  404. Error (NULL, 0, 0001, "Error opening file", InputFileName[Index]);
  405. return EFI_ABORTED;
  406. }
  407. fseek (InFile, 0, SEEK_END);
  408. FileSize = ftell (InFile);
  409. fseek (InFile, 0, SEEK_SET);
  410. DebugMsg (NULL, 0, 9, "Input files", "the input file name is %s and the size is %u bytes", InputFileName[Index], (unsigned) FileSize);
  411. //
  412. // Adjust section buffer when section alignment is required.
  413. //
  414. if (InputFileAlign != NULL) {
  415. //
  416. // Check this section is Te/Pe section, and Calculate the numbers of Te/Pe section.
  417. //
  418. TeOffset = 0;
  419. //
  420. // The section might be EFI_COMMON_SECTION_HEADER2
  421. // But only Type needs to be checked
  422. //
  423. if (FileSize >= MAX_SECTION_SIZE) {
  424. HeaderSize = sizeof (EFI_COMMON_SECTION_HEADER2);
  425. } else {
  426. HeaderSize = sizeof (EFI_COMMON_SECTION_HEADER);
  427. }
  428. fread (&TempSectHeader, 1, HeaderSize, InFile);
  429. if (TempSectHeader.Type == EFI_SECTION_TE) {
  430. fread (&TeHeader, 1, sizeof (TeHeader), InFile);
  431. if (TeHeader.Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) {
  432. TeOffset = TeHeader.StrippedSize - sizeof (TeHeader);
  433. }
  434. } else if (TempSectHeader.Type == EFI_SECTION_GUID_DEFINED) {
  435. fseek (InFile, 0, SEEK_SET);
  436. if (FileSize >= MAX_SECTION_SIZE) {
  437. fread (&GuidSectHeader2, 1, sizeof (GuidSectHeader2), InFile);
  438. if ((GuidSectHeader2.Attributes & EFI_GUIDED_SECTION_PROCESSING_REQUIRED) == 0) {
  439. HeaderSize = GuidSectHeader2.DataOffset;
  440. }
  441. } else {
  442. fread (&GuidSectHeader, 1, sizeof (GuidSectHeader), InFile);
  443. if ((GuidSectHeader.Attributes & EFI_GUIDED_SECTION_PROCESSING_REQUIRED) == 0) {
  444. HeaderSize = GuidSectHeader.DataOffset;
  445. }
  446. }
  447. }
  448. fseek (InFile, 0, SEEK_SET);
  449. //
  450. // Revert TeOffset to the converse value relative to Alignment
  451. // This is to assure the original PeImage Header at Alignment.
  452. //
  453. if (TeOffset != 0) {
  454. TeOffset = InputFileAlign [Index] - (TeOffset % InputFileAlign [Index]);
  455. TeOffset = TeOffset % InputFileAlign [Index];
  456. }
  457. //
  458. // make sure section data meet its alignment requirement by adding one raw pad section.
  459. //
  460. if ((InputFileAlign [Index] != 0) && (((Size + HeaderSize + TeOffset) % InputFileAlign [Index]) != 0)) {
  461. Offset = (Size + sizeof (EFI_COMMON_SECTION_HEADER) + HeaderSize + TeOffset + InputFileAlign [Index] - 1) & ~(InputFileAlign [Index] - 1);
  462. Offset = Offset - Size - HeaderSize - TeOffset;
  463. if (FileBuffer != NULL && ((Size + Offset) < *BufferLength)) {
  464. //
  465. // The maximal alignment is 64K, the raw section size must be less than 0xffffff
  466. //
  467. memset (FileBuffer + Size, 0, Offset);
  468. SectHeader = (EFI_COMMON_SECTION_HEADER *) (FileBuffer + Size);
  469. SectHeader->Type = EFI_SECTION_RAW;
  470. SectHeader->Size[0] = (UINT8) (Offset & 0xff);
  471. SectHeader->Size[1] = (UINT8) ((Offset & 0xff00) >> 8);
  472. SectHeader->Size[2] = (UINT8) ((Offset & 0xff0000) >> 16);
  473. }
  474. DebugMsg (NULL, 0, 9, "Pad raw section for section data alignment", "Pad Raw section size is %u", (unsigned) Offset);
  475. Size = Size + Offset;
  476. }
  477. }
  478. //
  479. // Now read the contents of the file into the buffer
  480. // Buffer must be enough to contain the file content.
  481. //
  482. if ((FileSize > 0) && (FileBuffer != NULL) && ((Size + FileSize) <= *BufferLength)) {
  483. if (fread (FileBuffer + Size, (size_t) FileSize, 1, InFile) != 1) {
  484. Error (NULL, 0, 0004, "Error reading file", InputFileName[Index]);
  485. fclose (InFile);
  486. return EFI_ABORTED;
  487. }
  488. }
  489. fclose (InFile);
  490. Size += FileSize;
  491. }
  492. //
  493. // Set the real required buffer size.
  494. //
  495. if (Size > *BufferLength) {
  496. *BufferLength = Size;
  497. return EFI_BUFFER_TOO_SMALL;
  498. } else {
  499. *BufferLength = Size;
  500. return EFI_SUCCESS;
  501. }
  502. }
  503. EFI_STATUS
  504. GenSectionCompressionSection (
  505. CHAR8 **InputFileName,
  506. UINT32 *InputFileAlign,
  507. UINT32 InputFileNum,
  508. UINT8 SectCompSubType,
  509. UINT8 **OutFileBuffer
  510. )
  511. /*++
  512. Routine Description:
  513. Generate an encapsulating section of type EFI_SECTION_COMPRESSION
  514. Input file must be already sectioned. The function won't validate
  515. the input files' contents. Caller should hand in files already
  516. with section header.
  517. Arguments:
  518. InputFileName - Name of the input file.
  519. InputFileAlign - Alignment required by the input file data.
  520. InputFileNum - Number of input files. Should be at least 1.
  521. SectCompSubType - Specify the compression algorithm requested.
  522. OutFileBuffer - Buffer pointer to Output file contents
  523. Returns:
  524. EFI_SUCCESS on successful return
  525. EFI_INVALID_PARAMETER if InputFileNum is less than 1
  526. EFI_ABORTED if unable to open input file.
  527. EFI_OUT_OF_RESOURCES No resource to complete the operation.
  528. --*/
  529. {
  530. UINT32 TotalLength;
  531. UINT32 InputLength;
  532. UINT32 CompressedLength;
  533. UINT32 HeaderLength;
  534. UINT8 *FileBuffer;
  535. UINT8 *OutputBuffer;
  536. EFI_STATUS Status;
  537. EFI_COMPRESSION_SECTION *CompressionSect;
  538. EFI_COMPRESSION_SECTION2 *CompressionSect2;
  539. COMPRESS_FUNCTION CompressFunction;
  540. InputLength = 0;
  541. FileBuffer = NULL;
  542. OutputBuffer = NULL;
  543. CompressedLength = 0;
  544. TotalLength = 0;
  545. //
  546. // read all input file contents into a buffer
  547. // first get the size of all file contents
  548. //
  549. Status = GetSectionContents (
  550. InputFileName,
  551. InputFileAlign,
  552. InputFileNum,
  553. FileBuffer,
  554. &InputLength
  555. );
  556. if (Status == EFI_BUFFER_TOO_SMALL) {
  557. FileBuffer = (UINT8 *) malloc (InputLength);
  558. if (FileBuffer == NULL) {
  559. Error (NULL, 0, 4001, "Resource", "memory cannot be allocated");
  560. return EFI_OUT_OF_RESOURCES;
  561. }
  562. //
  563. // read all input file contents into a buffer
  564. //
  565. Status = GetSectionContents (
  566. InputFileName,
  567. InputFileAlign,
  568. InputFileNum,
  569. FileBuffer,
  570. &InputLength
  571. );
  572. }
  573. if (EFI_ERROR (Status)) {
  574. if (FileBuffer != NULL) {
  575. free (FileBuffer);
  576. }
  577. return Status;
  578. }
  579. if (FileBuffer == NULL) {
  580. return EFI_OUT_OF_RESOURCES;
  581. }
  582. CompressFunction = NULL;
  583. //
  584. // Now data is in FileBuffer, compress the data
  585. //
  586. switch (SectCompSubType) {
  587. case EFI_NOT_COMPRESSED:
  588. CompressedLength = InputLength;
  589. HeaderLength = sizeof (EFI_COMPRESSION_SECTION);
  590. if (CompressedLength + HeaderLength >= MAX_SECTION_SIZE) {
  591. HeaderLength = sizeof (EFI_COMPRESSION_SECTION2);
  592. }
  593. TotalLength = CompressedLength + HeaderLength;
  594. //
  595. // Copy file buffer to the none compressed data.
  596. //
  597. OutputBuffer = malloc (TotalLength);
  598. if (OutputBuffer == NULL) {
  599. free (FileBuffer);
  600. return EFI_OUT_OF_RESOURCES;
  601. }
  602. memcpy (OutputBuffer + HeaderLength, FileBuffer, CompressedLength);
  603. free (FileBuffer);
  604. FileBuffer = OutputBuffer;
  605. break;
  606. case EFI_STANDARD_COMPRESSION:
  607. CompressFunction = (COMPRESS_FUNCTION) EfiCompress;
  608. break;
  609. default:
  610. Error (NULL, 0, 2000, "Invalid parameter", "unknown compression type");
  611. free (FileBuffer);
  612. return EFI_ABORTED;
  613. }
  614. if (CompressFunction != NULL) {
  615. Status = CompressFunction (FileBuffer, InputLength, OutputBuffer, &CompressedLength);
  616. if (Status == EFI_BUFFER_TOO_SMALL) {
  617. HeaderLength = sizeof (EFI_COMPRESSION_SECTION);
  618. if (CompressedLength + HeaderLength >= MAX_SECTION_SIZE) {
  619. HeaderLength = sizeof (EFI_COMPRESSION_SECTION2);
  620. }
  621. TotalLength = CompressedLength + HeaderLength;
  622. OutputBuffer = malloc (TotalLength);
  623. if (!OutputBuffer) {
  624. free (FileBuffer);
  625. return EFI_OUT_OF_RESOURCES;
  626. }
  627. Status = CompressFunction (FileBuffer, InputLength, OutputBuffer + HeaderLength, &CompressedLength);
  628. }
  629. free (FileBuffer);
  630. FileBuffer = OutputBuffer;
  631. if (EFI_ERROR (Status)) {
  632. if (FileBuffer != NULL) {
  633. free (FileBuffer);
  634. }
  635. return Status;
  636. }
  637. if (FileBuffer == NULL) {
  638. return EFI_OUT_OF_RESOURCES;
  639. }
  640. }
  641. DebugMsg (NULL, 0, 9, "comprss file size",
  642. "the original section size is %d bytes and the compressed section size is %u bytes", (unsigned) InputLength, (unsigned) CompressedLength);
  643. //if (TotalLength >= MAX_SECTION_SIZE) {
  644. // Error (NULL, 0, 2000, "Invalid parameter", "The size of all files exceeds section size limit(%uM).", MAX_SECTION_SIZE>>20);
  645. // if (FileBuffer != NULL) {
  646. // free (FileBuffer);
  647. // }
  648. // if (OutputBuffer != NULL) {
  649. // free (OutputBuffer);
  650. // }
  651. // return STATUS_ERROR;
  652. //}
  653. VerboseMsg ("the size of the created section file is %u bytes", (unsigned) TotalLength);
  654. //
  655. // Add the section header for the compressed data
  656. //
  657. if (TotalLength >= MAX_SECTION_SIZE) {
  658. CompressionSect2 = (EFI_COMPRESSION_SECTION2 *)FileBuffer;
  659. memset(CompressionSect2->CommonHeader.Size, 0xff, sizeof(UINT8) * 3);
  660. CompressionSect2->CommonHeader.Type = EFI_SECTION_COMPRESSION;
  661. CompressionSect2->CommonHeader.ExtendedSize = TotalLength;
  662. CompressionSect2->CompressionType = SectCompSubType;
  663. CompressionSect2->UncompressedLength = InputLength;
  664. } else {
  665. CompressionSect = (EFI_COMPRESSION_SECTION *) FileBuffer;
  666. CompressionSect->CommonHeader.Type = EFI_SECTION_COMPRESSION;
  667. CompressionSect->CommonHeader.Size[0] = (UINT8) (TotalLength & 0xff);
  668. CompressionSect->CommonHeader.Size[1] = (UINT8) ((TotalLength & 0xff00) >> 8);
  669. CompressionSect->CommonHeader.Size[2] = (UINT8) ((TotalLength & 0xff0000) >> 16);
  670. CompressionSect->CompressionType = SectCompSubType;
  671. CompressionSect->UncompressedLength = InputLength;
  672. }
  673. //
  674. // Set OutFileBuffer
  675. //
  676. *OutFileBuffer = FileBuffer;
  677. return EFI_SUCCESS;
  678. }
  679. EFI_STATUS
  680. GenSectionGuidDefinedSection (
  681. CHAR8 **InputFileName,
  682. UINT32 *InputFileAlign,
  683. UINT32 InputFileNum,
  684. EFI_GUID *VendorGuid,
  685. UINT16 DataAttribute,
  686. UINT32 DataHeaderSize,
  687. UINT8 **OutFileBuffer
  688. )
  689. /*++
  690. Routine Description:
  691. Generate an encapsulating section of type EFI_SECTION_GUID_DEFINED
  692. Input file must be already sectioned. The function won't validate
  693. the input files' contents. Caller should hand in files already
  694. with section header.
  695. Arguments:
  696. InputFileName - Name of the input file.
  697. InputFileAlign - Alignment required by the input file data.
  698. InputFileNum - Number of input files. Should be at least 1.
  699. VendorGuid - Specify vendor guid value.
  700. DataAttribute - Specify attribute for the vendor guid data.
  701. DataHeaderSize- Guided Data Header Size
  702. OutFileBuffer - Buffer pointer to Output file contents
  703. Returns:
  704. EFI_SUCCESS on successful return
  705. EFI_INVALID_PARAMETER if InputFileNum is less than 1
  706. EFI_ABORTED if unable to open input file.
  707. EFI_OUT_OF_RESOURCES No resource to complete the operation.
  708. --*/
  709. {
  710. UINT32 TotalLength;
  711. UINT32 InputLength;
  712. UINT32 Offset;
  713. UINT8 *FileBuffer;
  714. UINT32 Crc32Checksum;
  715. EFI_STATUS Status;
  716. CRC32_SECTION_HEADER *Crc32GuidSect;
  717. CRC32_SECTION_HEADER2 *Crc32GuidSect2;
  718. EFI_GUID_DEFINED_SECTION *VendorGuidSect;
  719. EFI_GUID_DEFINED_SECTION2 *VendorGuidSect2;
  720. InputLength = 0;
  721. Offset = 0;
  722. FileBuffer = NULL;
  723. TotalLength = 0;
  724. //
  725. // read all input file contents into a buffer
  726. // first get the size of all file contents
  727. //
  728. Status = GetSectionContents (
  729. InputFileName,
  730. InputFileAlign,
  731. InputFileNum,
  732. FileBuffer,
  733. &InputLength
  734. );
  735. if (Status == EFI_BUFFER_TOO_SMALL) {
  736. if (CompareGuid (VendorGuid, &mZeroGuid) == 0) {
  737. Offset = sizeof (CRC32_SECTION_HEADER);
  738. if (InputLength + Offset >= MAX_SECTION_SIZE) {
  739. Offset = sizeof (CRC32_SECTION_HEADER2);
  740. }
  741. } else {
  742. Offset = sizeof (EFI_GUID_DEFINED_SECTION);
  743. if (InputLength + Offset >= MAX_SECTION_SIZE) {
  744. Offset = sizeof (EFI_GUID_DEFINED_SECTION2);
  745. }
  746. }
  747. TotalLength = InputLength + Offset;
  748. FileBuffer = (UINT8 *) malloc (InputLength + Offset);
  749. if (FileBuffer == NULL) {
  750. Error (NULL, 0, 4001, "Resource", "memory cannot be allocated");
  751. return EFI_OUT_OF_RESOURCES;
  752. }
  753. //
  754. // read all input file contents into a buffer
  755. //
  756. Status = GetSectionContents (
  757. InputFileName,
  758. InputFileAlign,
  759. InputFileNum,
  760. FileBuffer + Offset,
  761. &InputLength
  762. );
  763. }
  764. if (EFI_ERROR (Status)) {
  765. if (FileBuffer != NULL) {
  766. free (FileBuffer);
  767. }
  768. Error (NULL, 0, 0001, "Error opening file for reading", InputFileName[0]);
  769. return Status;
  770. }
  771. if (InputLength == 0) {
  772. if (FileBuffer != NULL) {
  773. free (FileBuffer);
  774. }
  775. Error (NULL, 0, 2000, "Invalid parameter", "the size of input file %s can't be zero", InputFileName);
  776. return EFI_NOT_FOUND;
  777. }
  778. //
  779. // InputLength != 0, but FileBuffer == NULL means out of resources.
  780. //
  781. if (FileBuffer == NULL) {
  782. Error (NULL, 0, 4001, "Resource", "memory cannot be allocated");
  783. return EFI_OUT_OF_RESOURCES;
  784. }
  785. //
  786. // Now data is in FileBuffer + Offset
  787. //
  788. if (CompareGuid (VendorGuid, &mZeroGuid) == 0) {
  789. //
  790. // Default Guid section is CRC32.
  791. //
  792. Crc32Checksum = 0;
  793. CalculateCrc32 (FileBuffer + Offset, InputLength, &Crc32Checksum);
  794. if (TotalLength >= MAX_SECTION_SIZE) {
  795. Crc32GuidSect2 = (CRC32_SECTION_HEADER2 *) FileBuffer;
  796. Crc32GuidSect2->GuidSectionHeader.CommonHeader.Type = EFI_SECTION_GUID_DEFINED;
  797. Crc32GuidSect2->GuidSectionHeader.CommonHeader.Size[0] = (UINT8) 0xff;
  798. Crc32GuidSect2->GuidSectionHeader.CommonHeader.Size[1] = (UINT8) 0xff;
  799. Crc32GuidSect2->GuidSectionHeader.CommonHeader.Size[2] = (UINT8) 0xff;
  800. Crc32GuidSect2->GuidSectionHeader.CommonHeader.ExtendedSize = TotalLength;
  801. memcpy (&(Crc32GuidSect2->GuidSectionHeader.SectionDefinitionGuid), &mEfiCrc32SectionGuid, sizeof (EFI_GUID));
  802. Crc32GuidSect2->GuidSectionHeader.Attributes = EFI_GUIDED_SECTION_AUTH_STATUS_VALID;
  803. Crc32GuidSect2->GuidSectionHeader.DataOffset = sizeof (CRC32_SECTION_HEADER2);
  804. Crc32GuidSect2->CRC32Checksum = Crc32Checksum;
  805. DebugMsg (NULL, 0, 9, "Guided section", "Data offset is %u", Crc32GuidSect2->GuidSectionHeader.DataOffset);
  806. } else {
  807. Crc32GuidSect = (CRC32_SECTION_HEADER *) FileBuffer;
  808. Crc32GuidSect->GuidSectionHeader.CommonHeader.Type = EFI_SECTION_GUID_DEFINED;
  809. Crc32GuidSect->GuidSectionHeader.CommonHeader.Size[0] = (UINT8) (TotalLength & 0xff);
  810. Crc32GuidSect->GuidSectionHeader.CommonHeader.Size[1] = (UINT8) ((TotalLength & 0xff00) >> 8);
  811. Crc32GuidSect->GuidSectionHeader.CommonHeader.Size[2] = (UINT8) ((TotalLength & 0xff0000) >> 16);
  812. memcpy (&(Crc32GuidSect->GuidSectionHeader.SectionDefinitionGuid), &mEfiCrc32SectionGuid, sizeof (EFI_GUID));
  813. Crc32GuidSect->GuidSectionHeader.Attributes = EFI_GUIDED_SECTION_AUTH_STATUS_VALID;
  814. Crc32GuidSect->GuidSectionHeader.DataOffset = sizeof (CRC32_SECTION_HEADER);
  815. Crc32GuidSect->CRC32Checksum = Crc32Checksum;
  816. DebugMsg (NULL, 0, 9, "Guided section", "Data offset is %u", Crc32GuidSect->GuidSectionHeader.DataOffset);
  817. }
  818. } else {
  819. if (TotalLength >= MAX_SECTION_SIZE) {
  820. VendorGuidSect2 = (EFI_GUID_DEFINED_SECTION2 *) FileBuffer;
  821. VendorGuidSect2->CommonHeader.Type = EFI_SECTION_GUID_DEFINED;
  822. VendorGuidSect2->CommonHeader.Size[0] = (UINT8) 0xff;
  823. VendorGuidSect2->CommonHeader.Size[1] = (UINT8) 0xff;
  824. VendorGuidSect2->CommonHeader.Size[2] = (UINT8) 0xff;
  825. VendorGuidSect2->CommonHeader.ExtendedSize = InputLength + sizeof (EFI_GUID_DEFINED_SECTION2);
  826. memcpy (&(VendorGuidSect2->SectionDefinitionGuid), VendorGuid, sizeof (EFI_GUID));
  827. VendorGuidSect2->Attributes = DataAttribute;
  828. VendorGuidSect2->DataOffset = (UINT16) (sizeof (EFI_GUID_DEFINED_SECTION2) + DataHeaderSize);
  829. DebugMsg (NULL, 0, 9, "Guided section", "Data offset is %u", VendorGuidSect2->DataOffset);
  830. } else {
  831. VendorGuidSect = (EFI_GUID_DEFINED_SECTION *) FileBuffer;
  832. VendorGuidSect->CommonHeader.Type = EFI_SECTION_GUID_DEFINED;
  833. VendorGuidSect->CommonHeader.Size[0] = (UINT8) (TotalLength & 0xff);
  834. VendorGuidSect->CommonHeader.Size[1] = (UINT8) ((TotalLength & 0xff00) >> 8);
  835. VendorGuidSect->CommonHeader.Size[2] = (UINT8) ((TotalLength & 0xff0000) >> 16);
  836. memcpy (&(VendorGuidSect->SectionDefinitionGuid), VendorGuid, sizeof (EFI_GUID));
  837. VendorGuidSect->Attributes = DataAttribute;
  838. VendorGuidSect->DataOffset = (UINT16) (sizeof (EFI_GUID_DEFINED_SECTION) + DataHeaderSize);
  839. DebugMsg (NULL, 0, 9, "Guided section", "Data offset is %u", VendorGuidSect->DataOffset);
  840. }
  841. }
  842. VerboseMsg ("the size of the created section file is %u bytes", (unsigned) TotalLength);
  843. //
  844. // Set OutFileBuffer
  845. //
  846. *OutFileBuffer = FileBuffer;
  847. return EFI_SUCCESS;
  848. }
  849. EFI_STATUS
  850. FfsRebaseImageRead (
  851. IN VOID *FileHandle,
  852. IN UINTN FileOffset,
  853. IN OUT UINT32 *ReadSize,
  854. OUT VOID *Buffer
  855. )
  856. /*++
  857. Routine Description:
  858. Support routine for the PE/COFF Loader that reads a buffer from a PE/COFF file
  859. Arguments:
  860. FileHandle - The handle to the PE/COFF file
  861. FileOffset - The offset, in bytes, into the file to read
  862. ReadSize - The number of bytes to read from the file starting at FileOffset
  863. Buffer - A pointer to the buffer to read the data into.
  864. Returns:
  865. EFI_SUCCESS - ReadSize bytes of data were read into Buffer from the PE/COFF file starting at FileOffset
  866. --*/
  867. {
  868. CHAR8 *Destination8;
  869. CHAR8 *Source8;
  870. UINT32 Length;
  871. Destination8 = Buffer;
  872. Source8 = (CHAR8 *) ((UINTN) FileHandle + FileOffset);
  873. Length = *ReadSize;
  874. while (Length--) {
  875. *(Destination8++) = *(Source8++);
  876. }
  877. return EFI_SUCCESS;
  878. }
  879. STATIC
  880. EFI_STATUS
  881. GetAlignmentFromFile(char *InFile, UINT32 *Alignment)
  882. /*
  883. InFile is input file for getting alignment
  884. return the alignment
  885. */
  886. {
  887. FILE *InFileHandle;
  888. UINT8 *PeFileBuffer;
  889. UINTN PeFileSize;
  890. UINT32 CurSecHdrSize;
  891. PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;
  892. EFI_COMMON_SECTION_HEADER *CommonHeader;
  893. EFI_STATUS Status;
  894. InFileHandle = NULL;
  895. PeFileBuffer = NULL;
  896. *Alignment = 0;
  897. memset (&ImageContext, 0, sizeof (ImageContext));
  898. InFileHandle = fopen(LongFilePath(InFile), "rb");
  899. if (InFileHandle == NULL){
  900. Error (NULL, 0, 0001, "Error opening file", InFile);
  901. return EFI_ABORTED;
  902. }
  903. PeFileSize = _filelength (fileno(InFileHandle));
  904. PeFileBuffer = (UINT8 *) malloc (PeFileSize);
  905. if (PeFileBuffer == NULL) {
  906. fclose (InFileHandle);
  907. Error(NULL, 0, 4001, "Resource", "memory cannot be allocated of %s", InFileHandle);
  908. return EFI_OUT_OF_RESOURCES;
  909. }
  910. fread (PeFileBuffer, sizeof (UINT8), PeFileSize, InFileHandle);
  911. fclose (InFileHandle);
  912. CommonHeader = (EFI_COMMON_SECTION_HEADER *) PeFileBuffer;
  913. CurSecHdrSize = GetSectionHeaderLength(CommonHeader);
  914. ImageContext.Handle = (VOID *) ((UINTN)PeFileBuffer + CurSecHdrSize);
  915. ImageContext.ImageRead = (PE_COFF_LOADER_READ_FILE)FfsRebaseImageRead;
  916. Status = PeCoffLoaderGetImageInfo(&ImageContext);
  917. if (EFI_ERROR (Status)) {
  918. Error (NULL, 0, 3000, "Invalid PeImage", "The input file is %s and return status is %x", InFile, (int) Status);
  919. return Status;
  920. }
  921. *Alignment = ImageContext.SectionAlignment;
  922. // Free the allocated memory resource
  923. if (PeFileBuffer != NULL) {
  924. free (PeFileBuffer);
  925. PeFileBuffer = NULL;
  926. }
  927. return EFI_SUCCESS;
  928. }
  929. int
  930. main (
  931. int argc,
  932. char *argv[]
  933. )
  934. /*++
  935. Routine Description:
  936. Main
  937. Arguments:
  938. command line parameters
  939. Returns:
  940. EFI_SUCCESS Section header successfully generated and section concatenated.
  941. EFI_ABORTED Could not generate the section
  942. EFI_OUT_OF_RESOURCES No resource to complete the operation.
  943. --*/
  944. {
  945. UINT32 Index;
  946. UINT32 InputFileNum;
  947. FILE *OutFile;
  948. CHAR8 **InputFileName;
  949. CHAR8 *OutputFileName;
  950. CHAR8 *SectionName;
  951. CHAR8 *CompressionName;
  952. CHAR8 *StringBuffer;
  953. EFI_GUID VendorGuid = mZeroGuid;
  954. int VersionNumber;
  955. UINT8 SectType;
  956. UINT8 SectCompSubType;
  957. UINT16 SectGuidAttribute;
  958. UINT64 SectGuidHeaderLength;
  959. EFI_VERSION_SECTION *VersionSect;
  960. EFI_USER_INTERFACE_SECTION *UiSect;
  961. UINT32 InputLength;
  962. UINT8 *OutFileBuffer;
  963. EFI_STATUS Status;
  964. UINT64 LogLevel;
  965. UINT32 *InputFileAlign;
  966. UINT32 InputFileAlignNum;
  967. EFI_COMMON_SECTION_HEADER *SectionHeader;
  968. CHAR8 *DummyFileName;
  969. FILE *DummyFile;
  970. UINTN DummyFileSize;
  971. UINT8 *DummyFileBuffer;
  972. FILE *InFile;
  973. UINT8 *InFileBuffer;
  974. UINTN InFileSize;
  975. InputFileAlign = NULL;
  976. InputFileAlignNum = 0;
  977. InputFileName = NULL;
  978. OutputFileName = NULL;
  979. SectionName = NULL;
  980. CompressionName = NULL;
  981. StringBuffer = "";
  982. OutFile = NULL;
  983. VersionNumber = 0;
  984. InputFileNum = 0;
  985. SectType = EFI_SECTION_ALL;
  986. SectCompSubType = 0;
  987. SectGuidAttribute = EFI_GUIDED_SECTION_NONE;
  988. OutFileBuffer = NULL;
  989. InputLength = 0;
  990. Status = STATUS_SUCCESS;
  991. LogLevel = 0;
  992. SectGuidHeaderLength = 0;
  993. VersionSect = NULL;
  994. UiSect = NULL;
  995. DummyFileSize = 0;
  996. DummyFileName = NULL;
  997. DummyFile = NULL;
  998. DummyFileBuffer = NULL;
  999. InFile = NULL;
  1000. InFileSize = 0;
  1001. InFileBuffer = NULL;
  1002. SetUtilityName (UTILITY_NAME);
  1003. if (argc == 1) {
  1004. Error (NULL, 0, 1001, "Missing options", "No options input");
  1005. Usage ();
  1006. return STATUS_ERROR;
  1007. }
  1008. //
  1009. // Parse command line
  1010. //
  1011. argc --;
  1012. argv ++;
  1013. if ((stricmp (argv[0], "-h") == 0) || (stricmp (argv[0], "--help") == 0)) {
  1014. Version ();
  1015. Usage ();
  1016. return STATUS_SUCCESS;
  1017. }
  1018. if (stricmp (argv[0], "--version") == 0) {
  1019. Version ();
  1020. return STATUS_SUCCESS;
  1021. }
  1022. while (argc > 0) {
  1023. if ((stricmp (argv[0], "-s") == 0) || (stricmp (argv[0], "--SectionType") == 0)) {
  1024. SectionName = argv[1];
  1025. if (SectionName == NULL) {
  1026. Error (NULL, 0, 1003, "Invalid option value", "Section Type can't be NULL");
  1027. goto Finish;
  1028. }
  1029. argc -= 2;
  1030. argv += 2;
  1031. continue;
  1032. }
  1033. if ((stricmp (argv[0], "-o") == 0) || (stricmp (argv[0], "--outputfile") == 0)) {
  1034. OutputFileName = argv[1];
  1035. if (OutputFileName == NULL) {
  1036. Error (NULL, 0, 1003, "Invalid option value", "Output file can't be NULL");
  1037. goto Finish;
  1038. }
  1039. argc -= 2;
  1040. argv += 2;
  1041. continue;
  1042. }
  1043. if ((stricmp (argv[0], "-c") == 0) || (stricmp (argv[0], "--compress") == 0)) {
  1044. CompressionName = argv[1];
  1045. if (CompressionName == NULL) {
  1046. Error (NULL, 0, 1003, "Invalid option value", "Compression Type can't be NULL");
  1047. goto Finish;
  1048. }
  1049. argc -= 2;
  1050. argv += 2;
  1051. continue;
  1052. }
  1053. if ((stricmp (argv[0], "-g") == 0) || (stricmp (argv[0], "--vendor") == 0)) {
  1054. Status = StringToGuid (argv[1], &VendorGuid);
  1055. if (EFI_ERROR (Status)) {
  1056. Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);
  1057. goto Finish;
  1058. }
  1059. argc -= 2;
  1060. argv += 2;
  1061. continue;
  1062. }
  1063. if (stricmp (argv[0], "--dummy") == 0) {
  1064. DummyFileName = argv[1];
  1065. if (DummyFileName == NULL) {
  1066. Error (NULL, 0, 1003, "Invalid option value", "Dummy file can't be NULL");
  1067. goto Finish;
  1068. }
  1069. argc -= 2;
  1070. argv += 2;
  1071. continue;
  1072. }
  1073. if ((stricmp (argv[0], "-r") == 0) || (stricmp (argv[0], "--attributes") == 0)) {
  1074. if (argv[1] == NULL) {
  1075. Error (NULL, 0, 1003, "Invalid option value", "Guid section attributes can't be NULL");
  1076. goto Finish;
  1077. }
  1078. if (stricmp (argv[1], mGUIDedSectionAttribue[EFI_GUIDED_SECTION_PROCESSING_REQUIRED]) == 0) {
  1079. SectGuidAttribute |= EFI_GUIDED_SECTION_PROCESSING_REQUIRED;
  1080. } else if (stricmp (argv[1], mGUIDedSectionAttribue[EFI_GUIDED_SECTION_AUTH_STATUS_VALID]) == 0) {
  1081. SectGuidAttribute |= EFI_GUIDED_SECTION_AUTH_STATUS_VALID;
  1082. } else if (stricmp (argv[1], mGUIDedSectionAttribue[0]) == 0) {
  1083. //
  1084. // NONE attribute
  1085. //
  1086. SectGuidAttribute |= EFI_GUIDED_SECTION_NONE;
  1087. } else {
  1088. Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);
  1089. goto Finish;
  1090. }
  1091. argc -= 2;
  1092. argv += 2;
  1093. continue;
  1094. }
  1095. if ((stricmp (argv[0], "-l") == 0) || (stricmp (argv[0], "--HeaderLength") == 0)) {
  1096. Status = AsciiStringToUint64 (argv[1], FALSE, &SectGuidHeaderLength);
  1097. if (EFI_ERROR (Status)) {
  1098. Error (NULL, 0, 1003, "Invalid option value for GuidHeaderLength", "%s = %s", argv[0], argv[1]);
  1099. goto Finish;
  1100. }
  1101. argc -= 2;
  1102. argv += 2;
  1103. continue;
  1104. }
  1105. if ((stricmp (argv[0], "-n") == 0) || (stricmp (argv[0], "--name") == 0)) {
  1106. StringBuffer = argv[1];
  1107. if (StringBuffer == NULL) {
  1108. Error (NULL, 0, 1003, "Invalid option value", "Name can't be NULL");
  1109. goto Finish;
  1110. }
  1111. argc -= 2;
  1112. argv += 2;
  1113. continue;
  1114. }
  1115. if ((stricmp (argv[0], "-j") == 0) || (stricmp (argv[0], "--buildnumber") == 0)) {
  1116. if (argv[1] == NULL) {
  1117. Error (NULL, 0, 1003, "Invalid option value", "build number can't be NULL");
  1118. goto Finish;
  1119. }
  1120. //
  1121. // Verify string is a integrator number
  1122. //
  1123. for (Index = 0; Index < strlen (argv[1]); Index++) {
  1124. if ((argv[1][Index] != '-') && (isdigit ((int)argv[1][Index]) == 0)) {
  1125. Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);
  1126. goto Finish;
  1127. }
  1128. }
  1129. sscanf (argv[1], "%d", &VersionNumber);
  1130. argc -= 2;
  1131. argv += 2;
  1132. continue;
  1133. }
  1134. if ((stricmp (argv[0], "-v") == 0) || (stricmp (argv[0], "--verbose") == 0)) {
  1135. SetPrintLevel (VERBOSE_LOG_LEVEL);
  1136. VerboseMsg ("Verbose output Mode Set!");
  1137. argc --;
  1138. argv ++;
  1139. continue;
  1140. }
  1141. if ((stricmp (argv[0], "-q") == 0) || (stricmp (argv[0], "--quiet") == 0)) {
  1142. SetPrintLevel (KEY_LOG_LEVEL);
  1143. KeyMsg ("Quiet output Mode Set!");
  1144. argc --;
  1145. argv ++;
  1146. continue;
  1147. }
  1148. if ((stricmp (argv[0], "-d") == 0) || (stricmp (argv[0], "--debug") == 0)) {
  1149. Status = AsciiStringToUint64 (argv[1], FALSE, &LogLevel);
  1150. if (EFI_ERROR (Status)) {
  1151. Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);
  1152. goto Finish;
  1153. }
  1154. if (LogLevel > 9) {
  1155. Error (NULL, 0, 1003, "Invalid option value", "Debug Level range is 0~9, current input level is %d", (int) LogLevel);
  1156. goto Finish;
  1157. }
  1158. SetPrintLevel (LogLevel);
  1159. DebugMsg (NULL, 0, 9, "Debug Mode Set", "Debug Output Mode Level %s is set!", argv[1]);
  1160. argc -= 2;
  1161. argv += 2;
  1162. continue;
  1163. }
  1164. //
  1165. // Section File alignment requirement
  1166. //
  1167. if (stricmp (argv[0], "--sectionalign") == 0) {
  1168. if (InputFileAlignNum == 0) {
  1169. InputFileAlign = (UINT32 *) malloc (MAXIMUM_INPUT_FILE_NUM * sizeof (UINT32));
  1170. if (InputFileAlign == NULL) {
  1171. Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");
  1172. goto Finish;
  1173. }
  1174. memset (InputFileAlign, 1, MAXIMUM_INPUT_FILE_NUM * sizeof (UINT32));
  1175. } else if (InputFileAlignNum % MAXIMUM_INPUT_FILE_NUM == 0) {
  1176. InputFileAlign = (UINT32 *) realloc (
  1177. InputFileAlign,
  1178. (InputFileNum + MAXIMUM_INPUT_FILE_NUM) * sizeof (UINT32)
  1179. );
  1180. if (InputFileAlign == NULL) {
  1181. Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");
  1182. goto Finish;
  1183. }
  1184. memset (&(InputFileAlign[InputFileNum]), 1, (MAXIMUM_INPUT_FILE_NUM * sizeof (UINT32)));
  1185. }
  1186. if (stricmp(argv[1], "0") == 0) {
  1187. InputFileAlign[InputFileAlignNum] = 0;
  1188. } else {
  1189. Status = StringtoAlignment (argv[1], &(InputFileAlign[InputFileAlignNum]));
  1190. if (EFI_ERROR (Status)) {
  1191. Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);
  1192. goto Finish;
  1193. }
  1194. }
  1195. argc -= 2;
  1196. argv += 2;
  1197. InputFileAlignNum ++;
  1198. continue;
  1199. }
  1200. //
  1201. // Get Input file name
  1202. //
  1203. if ((InputFileNum == 0) && (InputFileName == NULL)) {
  1204. InputFileName = (CHAR8 **) malloc (MAXIMUM_INPUT_FILE_NUM * sizeof (CHAR8 *));
  1205. if (InputFileName == NULL) {
  1206. Error (NULL, 0, 4001, "Resource", "memory cannot be allocated");
  1207. goto Finish;
  1208. }
  1209. memset (InputFileName, 0, (MAXIMUM_INPUT_FILE_NUM * sizeof (CHAR8 *)));
  1210. } else if (InputFileNum % MAXIMUM_INPUT_FILE_NUM == 0) {
  1211. //
  1212. // InputFileName buffer too small, need to realloc
  1213. //
  1214. InputFileName = (CHAR8 **) realloc (
  1215. InputFileName,
  1216. (InputFileNum + MAXIMUM_INPUT_FILE_NUM) * sizeof (CHAR8 *)
  1217. );
  1218. if (InputFileName == NULL) {
  1219. Error (NULL, 0, 4001, "Resource", "memory cannot be allocated");
  1220. goto Finish;
  1221. }
  1222. memset (&(InputFileName[InputFileNum]), 0, (MAXIMUM_INPUT_FILE_NUM * sizeof (CHAR8 *)));
  1223. }
  1224. InputFileName[InputFileNum++] = argv[0];
  1225. argc --;
  1226. argv ++;
  1227. }
  1228. if (InputFileAlignNum > 0 && InputFileAlignNum != InputFileNum) {
  1229. Error (NULL, 0, 1003, "Invalid option", "section alignment must be set for each section");
  1230. goto Finish;
  1231. }
  1232. for (Index = 0; Index < InputFileAlignNum; Index++)
  1233. {
  1234. if (InputFileAlign[Index] == 0) {
  1235. Status = GetAlignmentFromFile(InputFileName[Index], &(InputFileAlign[Index]));
  1236. if (EFI_ERROR(Status)) {
  1237. Error (NULL, 0, 1003, "Fail to get Alignment from %s", InputFileName[InputFileNum]);
  1238. goto Finish;
  1239. }
  1240. }
  1241. }
  1242. VerboseMsg ("%s tool start.", UTILITY_NAME);
  1243. if (DummyFileName != NULL) {
  1244. //
  1245. // Open file and read contents
  1246. //
  1247. DummyFile = fopen (LongFilePath (DummyFileName), "rb");
  1248. if (DummyFile == NULL) {
  1249. Error (NULL, 0, 0001, "Error opening file", DummyFileName);
  1250. goto Finish;
  1251. }
  1252. fseek (DummyFile, 0, SEEK_END);
  1253. DummyFileSize = ftell (DummyFile);
  1254. fseek (DummyFile, 0, SEEK_SET);
  1255. DummyFileBuffer = (UINT8 *) malloc (DummyFileSize);
  1256. if (DummyFileBuffer == NULL) {
  1257. fclose(DummyFile);
  1258. Error (NULL, 0, 4001, "Resource", "memory cannot be allocated");
  1259. goto Finish;
  1260. }
  1261. fread(DummyFileBuffer, 1, DummyFileSize, DummyFile);
  1262. fclose(DummyFile);
  1263. DebugMsg (NULL, 0, 9, "Dummy files", "the dummy file name is %s and the size is %u bytes", DummyFileName, (unsigned) DummyFileSize);
  1264. if (InputFileName == NULL) {
  1265. Error (NULL, 0, 4001, "Resource", "memory cannot be allocated");
  1266. goto Finish;
  1267. }
  1268. InFile = fopen(LongFilePath(InputFileName[0]), "rb");
  1269. if (InFile == NULL) {
  1270. Error (NULL, 0, 0001, "Error opening file", InputFileName[0]);
  1271. goto Finish;
  1272. }
  1273. fseek (InFile, 0, SEEK_END);
  1274. InFileSize = ftell (InFile);
  1275. fseek (InFile, 0, SEEK_SET);
  1276. InFileBuffer = (UINT8 *) malloc (InFileSize);
  1277. if (InFileBuffer == NULL) {
  1278. fclose(InFile);
  1279. Error (NULL, 0, 4001, "Resource", "memory cannot be allocated");
  1280. goto Finish;
  1281. }
  1282. fread(InFileBuffer, 1, InFileSize, InFile);
  1283. fclose(InFile);
  1284. DebugMsg (NULL, 0, 9, "Input files", "the input file name is %s and the size is %u bytes", InputFileName[0], (unsigned) InFileSize);
  1285. if (InFileSize > DummyFileSize){
  1286. if (stricmp((CHAR8 *)DummyFileBuffer, (CHAR8 *)(InFileBuffer + (InFileSize - DummyFileSize))) == 0){
  1287. SectGuidHeaderLength = InFileSize - DummyFileSize;
  1288. }
  1289. }
  1290. if (SectGuidHeaderLength == 0) {
  1291. SectGuidAttribute |= EFI_GUIDED_SECTION_PROCESSING_REQUIRED;
  1292. }
  1293. if (DummyFileBuffer != NULL) {
  1294. free (DummyFileBuffer);
  1295. DummyFileBuffer = NULL;
  1296. }
  1297. if (InFileBuffer != NULL) {
  1298. free (InFileBuffer);
  1299. }
  1300. }
  1301. //
  1302. // Parse all command line parameters to get the corresponding section type.
  1303. //
  1304. VerboseMsg ("Section type is %s", SectionName);
  1305. if (SectionName == NULL) {
  1306. //
  1307. // No specified Section type, default is SECTION_ALL.
  1308. //
  1309. SectType = EFI_SECTION_ALL;
  1310. } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_COMPRESSION]) == 0) {
  1311. SectType = EFI_SECTION_COMPRESSION;
  1312. if (CompressionName == NULL) {
  1313. //
  1314. // Default is PI_STD compression algorithm.
  1315. //
  1316. SectCompSubType = EFI_STANDARD_COMPRESSION;
  1317. } else if (stricmp (CompressionName, mCompressionTypeName[EFI_NOT_COMPRESSED]) == 0) {
  1318. SectCompSubType = EFI_NOT_COMPRESSED;
  1319. } else if (stricmp (CompressionName, mCompressionTypeName[EFI_STANDARD_COMPRESSION]) == 0) {
  1320. SectCompSubType = EFI_STANDARD_COMPRESSION;
  1321. } else {
  1322. Error (NULL, 0, 1003, "Invalid option value", "--compress = %s", CompressionName);
  1323. goto Finish;
  1324. }
  1325. VerboseMsg ("Compress method is %s", mCompressionTypeName [SectCompSubType]);
  1326. } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_GUID_DEFINED]) == 0) {
  1327. SectType = EFI_SECTION_GUID_DEFINED;
  1328. if ((SectGuidAttribute & EFI_GUIDED_SECTION_NONE) != 0) {
  1329. //
  1330. // NONE attribute, clear attribute value.
  1331. //
  1332. SectGuidAttribute = SectGuidAttribute & ~EFI_GUIDED_SECTION_NONE;
  1333. }
  1334. VerboseMsg ("Vendor Guid is %08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",
  1335. (unsigned) VendorGuid.Data1,
  1336. VendorGuid.Data2,
  1337. VendorGuid.Data3,
  1338. VendorGuid.Data4[0],
  1339. VendorGuid.Data4[1],
  1340. VendorGuid.Data4[2],
  1341. VendorGuid.Data4[3],
  1342. VendorGuid.Data4[4],
  1343. VendorGuid.Data4[5],
  1344. VendorGuid.Data4[6],
  1345. VendorGuid.Data4[7]);
  1346. if ((SectGuidAttribute & EFI_GUIDED_SECTION_PROCESSING_REQUIRED) != 0) {
  1347. VerboseMsg ("Guid Attribute is %s", mGUIDedSectionAttribue[EFI_GUIDED_SECTION_PROCESSING_REQUIRED]);
  1348. }
  1349. if ((SectGuidAttribute & EFI_GUIDED_SECTION_AUTH_STATUS_VALID) != 0) {
  1350. VerboseMsg ("Guid Attribute is %s", mGUIDedSectionAttribue[EFI_GUIDED_SECTION_AUTH_STATUS_VALID]);
  1351. }
  1352. if (SectGuidHeaderLength != 0) {
  1353. VerboseMsg ("Guid Data Header size is 0x%llx", (unsigned long long) SectGuidHeaderLength);
  1354. }
  1355. } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_PE32]) == 0) {
  1356. SectType = EFI_SECTION_PE32;
  1357. } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_PIC]) == 0) {
  1358. SectType = EFI_SECTION_PIC;
  1359. } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_TE]) == 0) {
  1360. SectType = EFI_SECTION_TE;
  1361. } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_DXE_DEPEX]) == 0) {
  1362. SectType = EFI_SECTION_DXE_DEPEX;
  1363. } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_SMM_DEPEX]) == 0) {
  1364. SectType = EFI_SECTION_SMM_DEPEX;
  1365. } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_VERSION]) == 0) {
  1366. SectType = EFI_SECTION_VERSION;
  1367. if (VersionNumber < 0 || VersionNumber > 65535) {
  1368. Error (NULL, 0, 1003, "Invalid option value", "%d is not in 0~65535", VersionNumber);
  1369. goto Finish;
  1370. }
  1371. VerboseMsg ("Version section number is %d", VersionNumber);
  1372. } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_USER_INTERFACE]) == 0) {
  1373. SectType = EFI_SECTION_USER_INTERFACE;
  1374. if (StringBuffer[0] == '\0') {
  1375. Error (NULL, 0, 1001, "Missing option", "user interface string");
  1376. goto Finish;
  1377. }
  1378. VerboseMsg ("UI section string name is %s", StringBuffer);
  1379. } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_COMPATIBILITY16]) == 0) {
  1380. SectType = EFI_SECTION_COMPATIBILITY16;
  1381. } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_FIRMWARE_VOLUME_IMAGE]) == 0) {
  1382. SectType = EFI_SECTION_FIRMWARE_VOLUME_IMAGE;
  1383. } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_FREEFORM_SUBTYPE_GUID]) == 0) {
  1384. SectType = EFI_SECTION_FREEFORM_SUBTYPE_GUID;
  1385. } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_RAW]) == 0) {
  1386. SectType = EFI_SECTION_RAW;
  1387. } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_PEI_DEPEX]) == 0) {
  1388. SectType = EFI_SECTION_PEI_DEPEX;
  1389. } else {
  1390. Error (NULL, 0, 1003, "Invalid option value", "SectionType = %s", SectionName);
  1391. goto Finish;
  1392. }
  1393. //
  1394. // GuidValue is only required by Guided section.
  1395. //
  1396. if ((SectType != EFI_SECTION_GUID_DEFINED) &&
  1397. (SectionName != NULL) &&
  1398. (CompareGuid (&VendorGuid, &mZeroGuid) != 0)) {
  1399. fprintf (stdout, "Warning: the input guid value is not required for this section type %s\n", SectionName);
  1400. }
  1401. //
  1402. // Check whether there is input file
  1403. //
  1404. if ((SectType != EFI_SECTION_VERSION) && (SectType != EFI_SECTION_USER_INTERFACE)) {
  1405. //
  1406. // The input file are required for other section type.
  1407. //
  1408. if (InputFileNum == 0) {
  1409. Error (NULL, 0, 1001, "Missing options", "Input files");
  1410. goto Finish;
  1411. }
  1412. }
  1413. //
  1414. // Check whether there is output file
  1415. //
  1416. for (Index = 0; Index < InputFileNum; Index ++) {
  1417. VerboseMsg ("the %uth input file name is %s", (unsigned) Index, InputFileName[Index]);
  1418. }
  1419. if (OutputFileName == NULL) {
  1420. Error (NULL, 0, 1001, "Missing options", "Output file");
  1421. goto Finish;
  1422. // OutFile = stdout;
  1423. }
  1424. VerboseMsg ("Output file name is %s", OutputFileName);
  1425. //
  1426. // At this point, we've fully validated the command line, and opened appropriate
  1427. // files, so let's go and do what we've been asked to do...
  1428. //
  1429. //
  1430. // Within this switch, build and write out the section header including any
  1431. // section type specific pieces. If there's an input file, it's tacked on later
  1432. //
  1433. switch (SectType) {
  1434. case EFI_SECTION_COMPRESSION:
  1435. if (InputFileAlign != NULL) {
  1436. free (InputFileAlign);
  1437. InputFileAlign = NULL;
  1438. }
  1439. Status = GenSectionCompressionSection (
  1440. InputFileName,
  1441. InputFileAlign,
  1442. InputFileNum,
  1443. SectCompSubType,
  1444. &OutFileBuffer
  1445. );
  1446. break;
  1447. case EFI_SECTION_GUID_DEFINED:
  1448. if (InputFileAlign != NULL && (CompareGuid (&VendorGuid, &mZeroGuid) != 0)) {
  1449. //
  1450. // Only process alignment for the default known CRC32 guided section.
  1451. // For the unknown guided section, the alignment is processed when the dummy all section (EFI_SECTION_ALL) is generated.
  1452. //
  1453. free (InputFileAlign);
  1454. InputFileAlign = NULL;
  1455. }
  1456. Status = GenSectionGuidDefinedSection (
  1457. InputFileName,
  1458. InputFileAlign,
  1459. InputFileNum,
  1460. &VendorGuid,
  1461. SectGuidAttribute,
  1462. (UINT32) SectGuidHeaderLength,
  1463. &OutFileBuffer
  1464. );
  1465. break;
  1466. case EFI_SECTION_VERSION:
  1467. Index = sizeof (EFI_COMMON_SECTION_HEADER);
  1468. //
  1469. // 2 bytes for the build number UINT16
  1470. //
  1471. Index += 2;
  1472. //
  1473. // StringBuffer is ascii.. unicode is 2X + 2 bytes for terminating unicode null.
  1474. //
  1475. Index += (strlen (StringBuffer) * 2) + 2;
  1476. OutFileBuffer = (UINT8 *) malloc (Index);
  1477. if (OutFileBuffer == NULL) {
  1478. Error (NULL, 0, 4001, "Resource", "memory cannot be allocated");
  1479. goto Finish;
  1480. }
  1481. VersionSect = (EFI_VERSION_SECTION *) OutFileBuffer;
  1482. VersionSect->CommonHeader.Type = SectType;
  1483. VersionSect->CommonHeader.Size[0] = (UINT8) (Index & 0xff);
  1484. VersionSect->CommonHeader.Size[1] = (UINT8) ((Index & 0xff00) >> 8);
  1485. VersionSect->CommonHeader.Size[2] = (UINT8) ((Index & 0xff0000) >> 16);
  1486. VersionSect->BuildNumber = (UINT16) VersionNumber;
  1487. Ascii2UnicodeString (StringBuffer, VersionSect->VersionString);
  1488. VerboseMsg ("the size of the created section file is %u bytes", (unsigned) Index);
  1489. break;
  1490. case EFI_SECTION_USER_INTERFACE:
  1491. Index = sizeof (EFI_COMMON_SECTION_HEADER);
  1492. //
  1493. // StringBuffer is ascii.. unicode is 2X + 2 bytes for terminating unicode null.
  1494. //
  1495. Index += (strlen (StringBuffer) * 2) + 2;
  1496. OutFileBuffer = (UINT8 *) malloc (Index);
  1497. if (OutFileBuffer == NULL) {
  1498. Error (NULL, 0, 4001, "Resource", "memory cannot be allocated");
  1499. goto Finish;
  1500. }
  1501. UiSect = (EFI_USER_INTERFACE_SECTION *) OutFileBuffer;
  1502. UiSect->CommonHeader.Type = SectType;
  1503. UiSect->CommonHeader.Size[0] = (UINT8) (Index & 0xff);
  1504. UiSect->CommonHeader.Size[1] = (UINT8) ((Index & 0xff00) >> 8);
  1505. UiSect->CommonHeader.Size[2] = (UINT8) ((Index & 0xff0000) >> 16);
  1506. Ascii2UnicodeString (StringBuffer, UiSect->FileNameString);
  1507. VerboseMsg ("the size of the created section file is %u bytes", (unsigned) Index);
  1508. break;
  1509. case EFI_SECTION_ALL:
  1510. //
  1511. // read all input file contents into a buffer
  1512. // first get the size of all file contents
  1513. //
  1514. Status = GetSectionContents (
  1515. InputFileName,
  1516. InputFileAlign,
  1517. InputFileNum,
  1518. OutFileBuffer,
  1519. &InputLength
  1520. );
  1521. if (Status == EFI_BUFFER_TOO_SMALL) {
  1522. OutFileBuffer = (UINT8 *) malloc (InputLength);
  1523. if (OutFileBuffer == NULL) {
  1524. Error (NULL, 0, 4001, "Resource", "memory cannot be allocated");
  1525. goto Finish;
  1526. }
  1527. //
  1528. // read all input file contents into a buffer
  1529. //
  1530. Status = GetSectionContents (
  1531. InputFileName,
  1532. InputFileAlign,
  1533. InputFileNum,
  1534. OutFileBuffer,
  1535. &InputLength
  1536. );
  1537. }
  1538. VerboseMsg ("the size of the created section file is %u bytes", (unsigned) InputLength);
  1539. break;
  1540. default:
  1541. //
  1542. // All other section types are caught by default (they're all the same)
  1543. //
  1544. Status = GenSectionCommonLeafSection (
  1545. InputFileName,
  1546. InputFileNum,
  1547. SectType,
  1548. &OutFileBuffer
  1549. );
  1550. break;
  1551. }
  1552. if (Status != EFI_SUCCESS || OutFileBuffer == NULL) {
  1553. Error (NULL, 0, 2000, "Status is not successful", "Status value is 0x%X", (int) Status);
  1554. goto Finish;
  1555. }
  1556. //
  1557. // Get output file length
  1558. //
  1559. if (SectType != EFI_SECTION_ALL) {
  1560. SectionHeader = (EFI_COMMON_SECTION_HEADER *)OutFileBuffer;
  1561. InputLength = *(UINT32 *)SectionHeader->Size & 0x00ffffff;
  1562. if (InputLength == 0xffffff) {
  1563. InputLength = ((EFI_COMMON_SECTION_HEADER2 *)SectionHeader)->ExtendedSize;
  1564. }
  1565. }
  1566. //
  1567. // Write the output file
  1568. //
  1569. OutFile = fopen (LongFilePath (OutputFileName), "wb");
  1570. if (OutFile == NULL) {
  1571. Error (NULL, 0, 0001, "Error opening file for writing", OutputFileName);
  1572. goto Finish;
  1573. }
  1574. fwrite (OutFileBuffer, InputLength, 1, OutFile);
  1575. Finish:
  1576. if (InputFileName != NULL) {
  1577. free (InputFileName);
  1578. }
  1579. if (InputFileAlign != NULL) {
  1580. free (InputFileAlign);
  1581. }
  1582. if (OutFileBuffer != NULL) {
  1583. free (OutFileBuffer);
  1584. }
  1585. if (OutFile != NULL) {
  1586. fclose (OutFile);
  1587. }
  1588. if (DummyFileBuffer != NULL) {
  1589. free (DummyFileBuffer);
  1590. }
  1591. VerboseMsg ("%s tool done with return code is 0x%x.", UTILITY_NAME, GetUtilityStatus ());
  1592. return GetUtilityStatus ();
  1593. }