Fix the issues caused by EfiCompress.h was changed to Compress.h.
[mirror_edk2.git] / Tools / CCode / Source / GenFvImage / GenFvImageLib.c
1 /*++
2 i
3
4 Copyright (c) 2004, Intel Corporation
5 All rights reserved. This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
9
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12
13 Module Name:
14
15 GenFvImageLib.c
16
17 Abstract:
18
19 This file contains functions required to generate a Firmware Volume.
20
21 --*/
22
23 //
24 // Include files
25 //
26 #ifdef __GNUC__
27 #include <uuid/uuid.h>
28 #include <sys/stat.h>
29 #endif
30 #include <string.h>
31 #ifndef __GNUC__
32 #include <io.h>
33 #endif
34 #include <assert.h>
35
36 #include <Common/UefiBaseTypes.h>
37 #include <Common/FirmwareVolumeImageFormat.h>
38 #include <Common/Variable.h>
39 #include <Common/WorkingBlockHeader.h>
40 #include <Guid/FirmwareFileSystem.h>
41
42 #include "GenFvImageLib.h"
43 #include "GenFvImageLibInternal.h"
44 #include "CommonLib.h"
45 #include "Crc32.h"
46 #include "EfiUtilityMsgs.h"
47 #include "FvLib.h"
48 #include "Compress.h"
49 #include "WinNtInclude.h"
50
51 //
52 // Different file separater for Linux and Windows
53 //
54 #ifdef __GNUC__
55 #define FILE_SEP_CHAR '/'
56 #define FILE_SEP_STRING "/"
57 #else
58 #define FILE_SEP_CHAR '\\'
59 #define FILE_SEP_STRING "\\"
60 #endif
61
62 static UINT32 MaxFfsAlignment = 0;
63 //
64 // Local function prototypes
65 //
66 EFI_STATUS
67 GetPe32Info (
68 IN UINT8 *Pe32,
69 OUT UINT32 *EntryPoint,
70 OUT UINT32 *BaseOfCode,
71 OUT UINT16 *MachineType
72 );
73
74 //
75 // Local function implementations.
76 //
77 EFI_GUID FfsGuid = EFI_FIRMWARE_FILE_SYSTEM_GUID;
78 EFI_GUID DefaultFvPadFileNameGuid = { 0x78f54d4, 0xcc22, 0x4048, 0x9e, 0x94, 0x87, 0x9c, 0x21, 0x4d, 0x56, 0x2f };
79
80 //
81 // This data array will be located at the base of the Firmware Volume Header (FVH)
82 // in the boot block. It must not exceed 14 bytes of code. The last 2 bytes
83 // will be used to keep the FVH checksum consistent.
84 // This code will be run in response to a starutp IPI for HT-enabled systems.
85 //
86 #define SIZEOF_STARTUP_DATA_ARRAY 0x10
87
88 UINT8 m128kRecoveryStartupApDataArray[SIZEOF_STARTUP_DATA_ARRAY] = {
89 //
90 // EA D0 FF 00 F0 ; far jmp F000:FFD0
91 // 0, 0, 0, 0, 0, 0, 0, 0, 0, ; Reserved bytes
92 // 0, 0 ; Checksum Padding
93 //
94 0xEA,
95 0xD0,
96 0xFF,
97 0x0,
98 0xF0,
99 0x00,
100 0x00,
101 0x00,
102 0x00,
103 0x00,
104 0x00,
105 0x00,
106 0x00,
107 0x00,
108 0x00,
109 0x00
110 };
111
112 UINT8 m64kRecoveryStartupApDataArray[SIZEOF_STARTUP_DATA_ARRAY] = {
113 //
114 // EB CE ; jmp short ($-0x30)
115 // ; (from offset 0x0 to offset 0xFFD0)
116 // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ; Reserved bytes
117 // 0, 0 ; Checksum Padding
118 //
119 0xEB,
120 0xCE,
121 0x00,
122 0x00,
123 0x00,
124 0x00,
125 0x00,
126 0x00,
127 0x00,
128 0x00,
129 0x00,
130 0x00,
131 0x00,
132 0x00,
133 0x00,
134 0x00
135 };
136
137 EFI_STATUS
138 ParseFvInf (
139 IN MEMORY_FILE *InfFile,
140 IN FV_INFO *FvInfo
141 )
142 /*++
143
144 Routine Description:
145
146 This function parses a FV.INF file and copies info into a FV_INFO structure.
147
148 Arguments:
149
150 InfFile Memory file image.
151 FvInfo Information read from INF file.
152
153 Returns:
154
155 EFI_SUCCESS INF file information successfully retrieved.
156 EFI_ABORTED INF file has an invalid format.
157 EFI_NOT_FOUND A required string was not found in the INF file.
158 --*/
159 {
160 CHAR8 Value[_MAX_PATH];
161 UINT64 Value64;
162 UINTN Index;
163 EFI_STATUS Status;
164
165 //
166 // Initialize FV info
167 //
168 memset (FvInfo, 0, sizeof (FV_INFO));
169
170 //
171 // Read the FV base address
172 //
173 Status = FindToken (InfFile, OPTIONS_SECTION_STRING, EFI_FV_BASE_ADDRESS_STRING, 0, Value);
174
175 if (Status == EFI_SUCCESS) {
176 //
177 // Get the base address
178 //
179 Status = AsciiStringToUint64 (Value, FALSE, &Value64);
180 if (EFI_ERROR (Status)) {
181 Error (NULL, 0, 0, EFI_FV_BASE_ADDRESS_STRING, "invalid value");
182 return EFI_ABORTED;
183 }
184
185 FvInfo->BaseAddress = Value64;
186 } else {
187 Error (NULL, 0, 0, EFI_FV_BASE_ADDRESS_STRING, "could not find value");
188 return EFI_ABORTED;
189 }
190 //
191 // Read the FV Guid
192 //
193 Status = FindToken (InfFile, OPTIONS_SECTION_STRING, EFI_FV_GUID_STRING, 0, Value);
194
195 if (Status == EFI_SUCCESS) {
196 //
197 // Get the guid value
198 //
199 Status = StringToGuid (Value, &FvInfo->FvGuid);
200 if (EFI_ERROR (Status)) {
201 memcpy (&FvInfo->FvGuid, &FfsGuid, sizeof (EFI_GUID));
202 }
203 } else {
204 memcpy (&FvInfo->FvGuid, &FfsGuid, sizeof (EFI_GUID));
205 }
206 //
207 // Read the FV file name
208 //
209 Status = FindToken (InfFile, OPTIONS_SECTION_STRING, EFI_FV_FILE_NAME_STRING, 0, Value);
210
211 if (Status == EFI_SUCCESS) {
212 //
213 // copy the file name
214 //
215 strcpy (FvInfo->FvName, Value);
216 } else {
217 Error (NULL, 0, 0, EFI_FV_FILE_NAME_STRING, "value not specified");
218 return EFI_ABORTED;
219 }
220 //
221 // Read the Sym file name
222 //
223 Status = FindToken (InfFile, OPTIONS_SECTION_STRING, EFI_SYM_FILE_NAME_STRING, 0, Value);
224
225 if (Status == EFI_SUCCESS) {
226 //
227 // copy the file name
228 //
229 strcpy (FvInfo->SymName, Value);
230 } else {
231 //
232 // Symbols not required, so init to NULL.
233 //
234 strcpy (FvInfo->SymName, "");
235 }
236 //
237 // Read the read disabled capability attribute
238 //
239 Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_READ_DISABLED_CAP_STRING, 0, Value);
240
241 if (Status == EFI_SUCCESS) {
242 //
243 // Update the read disabled flag
244 //
245 if (strcmp (Value, TRUE_STRING) == 0) {
246 FvInfo->FvAttributes |= EFI_FVB_READ_DISABLED_CAP;
247 } else if (strcmp (Value, FALSE_STRING) != 0) {
248 Error (NULL, 0, 0, EFI_FVB_READ_DISABLED_CAP_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
249 return EFI_ABORTED;
250 }
251 } else {
252 Error (NULL, 0, 0, EFI_FVB_READ_DISABLED_CAP_STRING, "value not specified");
253 return Status;
254 }
255 //
256 // Read the read enabled capability attribute
257 //
258 Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_READ_ENABLED_CAP_STRING, 0, Value);
259
260 if (Status == EFI_SUCCESS) {
261 //
262 // Update the read disabled flag
263 //
264 if (strcmp (Value, TRUE_STRING) == 0) {
265 FvInfo->FvAttributes |= EFI_FVB_READ_ENABLED_CAP;
266 } else if (strcmp (Value, FALSE_STRING) != 0) {
267 Error (NULL, 0, 0, EFI_FVB_READ_ENABLED_CAP_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
268 return EFI_ABORTED;
269 }
270 } else {
271 Error (NULL, 0, 0, EFI_FVB_READ_ENABLED_CAP_STRING, "value not specified");
272 return Status;
273 }
274 //
275 // Read the read status attribute
276 //
277 Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_READ_STATUS_STRING, 0, Value);
278
279 if (Status == EFI_SUCCESS) {
280 //
281 // Update the read disabled flag
282 //
283 if (strcmp (Value, TRUE_STRING) == 0) {
284 FvInfo->FvAttributes |= EFI_FVB_READ_STATUS;
285 } else if (strcmp (Value, FALSE_STRING) != 0) {
286 Error (NULL, 0, 0, EFI_FVB_READ_STATUS_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
287 return EFI_ABORTED;
288 }
289 } else {
290 Error (NULL, 0, 0, EFI_FVB_READ_STATUS_STRING, "value not specified");
291 return Status;
292 }
293 //
294 // Read the write disabled capability attribute
295 //
296 Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_WRITE_DISABLED_CAP_STRING, 0, Value);
297
298 if (Status == EFI_SUCCESS) {
299 //
300 // Update the write disabled flag
301 //
302 if (strcmp (Value, TRUE_STRING) == 0) {
303 FvInfo->FvAttributes |= EFI_FVB_WRITE_DISABLED_CAP;
304 } else if (strcmp (Value, FALSE_STRING) != 0) {
305 Error (NULL, 0, 0, EFI_FVB_WRITE_DISABLED_CAP_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
306 return EFI_ABORTED;
307 }
308 } else {
309 Error (NULL, 0, 0, EFI_FVB_WRITE_DISABLED_CAP_STRING, "value not specified");
310 return Status;
311 }
312 //
313 // Read the write enabled capability attribute
314 //
315 Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_WRITE_ENABLED_CAP_STRING, 0, Value);
316
317 if (Status == EFI_SUCCESS) {
318 //
319 // Update the write disabled flag
320 //
321 if (strcmp (Value, TRUE_STRING) == 0) {
322 FvInfo->FvAttributes |= EFI_FVB_WRITE_ENABLED_CAP;
323 } else if (strcmp (Value, FALSE_STRING) != 0) {
324 Error (NULL, 0, 0, EFI_FVB_WRITE_ENABLED_CAP_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
325 return EFI_ABORTED;
326 }
327 } else {
328 Error (NULL, 0, 0, EFI_FVB_WRITE_ENABLED_CAP_STRING, "value not specified");
329 return Status;
330 }
331 //
332 // Read the write status attribute
333 //
334 Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_WRITE_STATUS_STRING, 0, Value);
335
336 if (Status == EFI_SUCCESS) {
337 //
338 // Update the write disabled flag
339 //
340 if (strcmp (Value, TRUE_STRING) == 0) {
341 FvInfo->FvAttributes |= EFI_FVB_WRITE_STATUS;
342 } else if (strcmp (Value, FALSE_STRING) != 0) {
343 Error (NULL, 0, 0, EFI_FVB_WRITE_STATUS_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
344 return EFI_ABORTED;
345 }
346 } else {
347 Error (NULL, 0, 0, EFI_FVB_WRITE_STATUS_STRING, "value not specified");
348 return Status;
349 }
350 //
351 // Read the lock capability attribute
352 //
353 Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_LOCK_CAP_STRING, 0, Value);
354
355 if (Status == EFI_SUCCESS) {
356 //
357 // Update the attribute flag
358 //
359 if (strcmp (Value, TRUE_STRING) == 0) {
360 FvInfo->FvAttributes |= EFI_FVB_LOCK_CAP;
361 } else if (strcmp (Value, FALSE_STRING) != 0) {
362 Error (NULL, 0, 0, EFI_FVB_LOCK_CAP_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
363 return EFI_ABORTED;
364 }
365 } else {
366 Error (NULL, 0, 0, EFI_FVB_LOCK_CAP_STRING, "value not specified");
367 return Status;
368 }
369 //
370 // Read the lock status attribute
371 //
372 Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_LOCK_STATUS_STRING, 0, Value);
373
374 if (Status == EFI_SUCCESS) {
375 //
376 // Update the attribute flag
377 //
378 if (strcmp (Value, TRUE_STRING) == 0) {
379 FvInfo->FvAttributes |= EFI_FVB_LOCK_STATUS;
380 } else if (strcmp (Value, FALSE_STRING) != 0) {
381 Error (NULL, 0, 0, EFI_FVB_LOCK_STATUS_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
382 return EFI_ABORTED;
383 }
384 } else {
385 Error (NULL, 0, 0, EFI_FVB_LOCK_STATUS_STRING, "value not specified");
386 return Status;
387 }
388 //
389 // Read the sticky write attribute
390 //
391 Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_STICKY_WRITE_STRING, 0, Value);
392
393 if (Status == EFI_SUCCESS) {
394 //
395 // Update the attribute flag
396 //
397 if (strcmp (Value, TRUE_STRING) == 0) {
398 FvInfo->FvAttributes |= EFI_FVB_STICKY_WRITE;
399 } else if (strcmp (Value, FALSE_STRING) != 0) {
400 Error (NULL, 0, 0, EFI_FVB_STICKY_WRITE_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
401 return EFI_ABORTED;
402 }
403 } else {
404 Error (NULL, 0, 0, EFI_FVB_STICKY_WRITE_STRING, "value not specified");
405 return Status;
406 }
407 //
408 // Read the memory mapped attribute
409 //
410 Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_MEMORY_MAPPED_STRING, 0, Value);
411
412 if (Status == EFI_SUCCESS) {
413 //
414 // Update the attribute flag
415 //
416 if (strcmp (Value, TRUE_STRING) == 0) {
417 FvInfo->FvAttributes |= EFI_FVB_MEMORY_MAPPED;
418 } else if (strcmp (Value, FALSE_STRING) != 0) {
419 Error (NULL, 0, 0, EFI_FVB_MEMORY_MAPPED_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
420 return EFI_ABORTED;
421 }
422 } else {
423 Error (NULL, 0, 0, EFI_FVB_MEMORY_MAPPED_STRING, "value not specified");
424 return Status;
425 }
426 //
427 // Read the erase polarity attribute
428 //
429 Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ERASE_POLARITY_STRING, 0, Value);
430
431 if (Status == EFI_SUCCESS) {
432 //
433 // Update the attribute flag
434 //
435 if (strcmp (Value, ONE_STRING) == 0) {
436 FvInfo->FvAttributes |= EFI_FVB_ERASE_POLARITY;
437 } else if (strcmp (Value, ZERO_STRING) != 0) {
438 Error (NULL, 0, 0, EFI_FVB_ERASE_POLARITY_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
439 return EFI_ABORTED;
440 }
441 } else {
442 Error (NULL, 0, 0, EFI_FVB_ERASE_POLARITY_STRING, "value not specified");
443 return Status;
444 }
445 //
446 // Read the alignment capabilities attribute
447 //
448 Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_CAP_STRING, 0, Value);
449
450 if (Status == EFI_SUCCESS) {
451 //
452 // Update attribute
453 //
454 if (strcmp (Value, TRUE_STRING) == 0) {
455 FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_CAP;
456 } else if (strcmp (Value, FALSE_STRING) != 0) {
457 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_CAP_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
458 return EFI_ABORTED;
459 }
460 } else {
461 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_CAP_STRING, "value not specified");
462 return Status;
463 }
464 //
465 // Read the word alignment capability attribute
466 //
467 Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_2_STRING, 0, Value);
468
469 if (Status == EFI_SUCCESS) {
470 //
471 // Update attribute
472 //
473 if (strcmp (Value, TRUE_STRING) == 0) {
474 FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_2;
475 } else if (strcmp (Value, FALSE_STRING) != 0) {
476 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_2_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
477 return EFI_ABORTED;
478 }
479 } else {
480 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_2_STRING, "value not specified");
481 return Status;
482 }
483 //
484 // Read the dword alignment capability attribute
485 //
486 Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_4_STRING, 0, Value);
487
488 if (Status == EFI_SUCCESS) {
489 //
490 // Update attribute
491 //
492 if (strcmp (Value, TRUE_STRING) == 0) {
493 FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_4;
494 } else if (strcmp (Value, FALSE_STRING) != 0) {
495 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_4_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
496 return EFI_ABORTED;
497 }
498 } else {
499 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_4_STRING, "value not specified");
500 return Status;
501 }
502 //
503 // Read the word alignment capability attribute
504 //
505 Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_8_STRING, 0, Value);
506
507 if (Status == EFI_SUCCESS) {
508 //
509 // Update attribute
510 //
511 if (strcmp (Value, TRUE_STRING) == 0) {
512 FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_8;
513 } else if (strcmp (Value, FALSE_STRING) != 0) {
514 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_8_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
515 return EFI_ABORTED;
516 }
517 } else {
518 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_8_STRING, "value not specified");
519 return Status;
520 }
521 //
522 // Read the qword alignment capability attribute
523 //
524 Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_16_STRING, 0, Value);
525
526 if (Status == EFI_SUCCESS) {
527 //
528 // Update attribute
529 //
530 if (strcmp (Value, TRUE_STRING) == 0) {
531 FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_16;
532 } else if (strcmp (Value, FALSE_STRING) != 0) {
533 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_16_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
534 return EFI_ABORTED;
535 }
536 } else {
537 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_16_STRING, "value not specified");
538 return Status;
539 }
540 //
541 // Read the 32 byte alignment capability attribute
542 //
543 Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_32_STRING, 0, Value);
544
545 if (Status == EFI_SUCCESS) {
546 //
547 // Update attribute
548 //
549 if (strcmp (Value, TRUE_STRING) == 0) {
550 FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_32;
551 } else if (strcmp (Value, FALSE_STRING) != 0) {
552 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_32_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
553 return EFI_ABORTED;
554 }
555 } else {
556 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_32_STRING, "value not specified");
557 return Status;
558 }
559 //
560 // Read the 64 byte alignment capability attribute
561 //
562 Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_64_STRING, 0, Value);
563
564 if (Status == EFI_SUCCESS) {
565 //
566 // Update attribute
567 //
568 if (strcmp (Value, TRUE_STRING) == 0) {
569 FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_64;
570 } else if (strcmp (Value, FALSE_STRING) != 0) {
571 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_64_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
572 return EFI_ABORTED;
573 }
574 } else {
575 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_64_STRING, "value not specified");
576 return Status;
577 }
578 //
579 // Read the 128 byte alignment capability attribute
580 //
581 Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_128_STRING, 0, Value);
582
583 if (Status == EFI_SUCCESS) {
584 //
585 // Update attribute
586 //
587 if (strcmp (Value, TRUE_STRING) == 0) {
588 FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_128;
589 } else if (strcmp (Value, FALSE_STRING) != 0) {
590 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_128_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
591 return EFI_ABORTED;
592 }
593 } else {
594 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_128_STRING, "value not specified");
595 return Status;
596 }
597 //
598 // Read the 256 byte alignment capability attribute
599 //
600 Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_256_STRING, 0, Value);
601
602 if (Status == EFI_SUCCESS) {
603 //
604 // Update attribute
605 //
606 if (strcmp (Value, TRUE_STRING) == 0) {
607 FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_256;
608 } else if (strcmp (Value, FALSE_STRING) != 0) {
609 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_256_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
610 return EFI_ABORTED;
611 }
612 } else {
613 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_256_STRING, "value not specified");
614 return Status;
615 }
616 //
617 // Read the 512 byte alignment capability attribute
618 //
619 Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_512_STRING, 0, Value);
620
621 if (Status == EFI_SUCCESS) {
622 //
623 // Update attribute
624 //
625 if (strcmp (Value, TRUE_STRING) == 0) {
626 FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_512;
627 } else if (strcmp (Value, FALSE_STRING) != 0) {
628 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_512_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
629 return EFI_ABORTED;
630 }
631 } else {
632 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_512_STRING, "value not specified");
633 return Status;
634 }
635 //
636 // Read the 1K byte alignment capability attribute
637 //
638 Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_1K_STRING, 0, Value);
639
640 if (Status == EFI_SUCCESS) {
641 //
642 // Update attribute
643 //
644 if (strcmp (Value, TRUE_STRING) == 0) {
645 FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_1K;
646 } else if (strcmp (Value, FALSE_STRING) != 0) {
647 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_1K_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
648 return EFI_ABORTED;
649 }
650 } else {
651 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_1K_STRING, "value not specified");
652 return Status;
653 }
654 //
655 // Read the 2K byte alignment capability attribute
656 //
657 Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_2K_STRING, 0, Value);
658
659 if (Status == EFI_SUCCESS) {
660 //
661 // Update attribute
662 //
663 if (strcmp (Value, TRUE_STRING) == 0) {
664 FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_2K;
665 } else if (strcmp (Value, FALSE_STRING) != 0) {
666 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_2K_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
667 return EFI_ABORTED;
668 }
669 } else {
670 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_2K_STRING, "value not specified");
671 return Status;
672 }
673 //
674 // Read the 4K byte alignment capability attribute
675 //
676 Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_4K_STRING, 0, Value);
677
678 if (Status == EFI_SUCCESS) {
679 //
680 // Update attribute
681 //
682 if (strcmp (Value, TRUE_STRING) == 0) {
683 FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_4K;
684 } else if (strcmp (Value, FALSE_STRING) != 0) {
685 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_4K_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
686 return EFI_ABORTED;
687 }
688 } else {
689 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_4K_STRING, "value not specified");
690 return Status;
691 }
692 //
693 // Read the 8K byte alignment capability attribute
694 //
695 Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_8K_STRING, 0, Value);
696
697 if (Status == EFI_SUCCESS) {
698 //
699 // Update attribute
700 //
701 if (strcmp (Value, TRUE_STRING) == 0) {
702 FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_8K;
703 } else if (strcmp (Value, FALSE_STRING) != 0) {
704 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_8K_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
705 return EFI_ABORTED;
706 }
707 } else {
708 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_8K_STRING, "value not specified");
709 return Status;
710 }
711 //
712 // Read the 16K byte alignment capability attribute
713 //
714 Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_16K_STRING, 0, Value);
715
716 if (Status == EFI_SUCCESS) {
717 //
718 // Update attribute
719 //
720 if (strcmp (Value, TRUE_STRING) == 0) {
721 FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_16K;
722 } else if (strcmp (Value, FALSE_STRING) != 0) {
723 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_16K_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
724 return EFI_ABORTED;
725 }
726 } else {
727 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_16K_STRING, "value not specified");
728 return Status;
729 }
730 //
731 // Read the 32K byte alignment capability attribute
732 //
733 Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_32K_STRING, 0, Value);
734
735 if (Status == EFI_SUCCESS) {
736 //
737 // Update attribute
738 //
739 if (strcmp (Value, TRUE_STRING) == 0) {
740 FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_32K;
741 } else if (strcmp (Value, FALSE_STRING) != 0) {
742 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_32K_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
743 return EFI_ABORTED;
744 }
745 } else {
746 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_32K_STRING, "value not specified");
747 return Status;
748 }
749 //
750 // Read the 64K byte alignment capability attribute
751 //
752 Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_64K_STRING, 0, Value);
753
754 if (Status == EFI_SUCCESS) {
755 //
756 // Update attribute
757 //
758 if (strcmp (Value, TRUE_STRING) == 0) {
759 FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_64K;
760 } else if (strcmp (Value, FALSE_STRING) != 0) {
761 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_64K_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
762 return EFI_ABORTED;
763 }
764 } else {
765 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_64K_STRING, "value not specified");
766 return Status;
767 }
768
769 if (!(FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_CAP) &&
770 (
771 (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_2) ||
772 (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_4) ||
773 (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_8) ||
774 (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_16) ||
775 (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_32) ||
776 (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_64) ||
777 (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_128) ||
778 (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_256) ||
779 (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_512) ||
780 (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_1K) ||
781 (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_2K) ||
782 (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_4K) ||
783 (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_8K) ||
784 (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_16K) ||
785 (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_32K) ||
786 (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_64K)
787 )
788 ) {
789 Error (
790 NULL,
791 0,
792 0,
793 "illegal combination of alignment attributes",
794 "if %s is not %s, no individual alignments can be %s",
795 EFI_FVB_ALIGNMENT_CAP_STRING,
796 TRUE_STRING,
797 TRUE_STRING
798 );
799 return EFI_ABORTED;
800 }
801 //
802 // Read block maps
803 //
804 for (Index = 0; Index < MAX_NUMBER_OF_FV_BLOCKS; Index++) {
805 //
806 // Read the number of blocks
807 //
808 Status = FindToken (InfFile, OPTIONS_SECTION_STRING, EFI_NUM_BLOCKS_STRING, Index, Value);
809
810 if (Status == EFI_SUCCESS) {
811 //
812 // Update the number of blocks
813 //
814 Status = AsciiStringToUint64 (Value, FALSE, &Value64);
815 if (EFI_ERROR (Status)) {
816 Error (NULL, 0, 0, Value, "invalid value for %s", EFI_NUM_BLOCKS_STRING);
817 return EFI_ABORTED;
818 }
819
820 FvInfo->FvBlocks[Index].NumBlocks = (UINT32) Value64;
821 } else {
822 //
823 // If there is no number of blocks, but there is a size, then we have a mismatched pair
824 // and should return an error.
825 //
826 Status = FindToken (InfFile, OPTIONS_SECTION_STRING, EFI_BLOCK_SIZE_STRING, Index, Value);
827 if (!EFI_ERROR (Status)) {
828 Error (NULL, 0, 0, "must specify both", "%s and %s", EFI_NUM_BLOCKS_STRING, EFI_BLOCK_SIZE_STRING);
829 return EFI_ABORTED;
830 } else {
831 //
832 // We are done
833 //
834 break;
835 }
836 }
837 //
838 // Read the size of blocks
839 //
840 Status = FindToken (InfFile, OPTIONS_SECTION_STRING, EFI_BLOCK_SIZE_STRING, Index, Value);
841
842 if (Status == EFI_SUCCESS) {
843 //
844 // Update the number of blocks
845 //
846 Status = AsciiStringToUint64 (Value, FALSE, &Value64);
847 if (EFI_ERROR (Status)) {
848 Error (NULL, 0, 0, Value, "invalid value specified for %s", EFI_BLOCK_SIZE_STRING);
849 return EFI_ABORTED;
850 }
851
852 FvInfo->FvBlocks[Index].BlockLength = (UINT32) Value64;
853 } else {
854 //
855 // There is a number of blocks, but there is no size, so we have a mismatched pair
856 // and should return an error.
857 //
858 Error (NULL, 0, 0, "must specify both", "%s and %s", EFI_NUM_BLOCKS_STRING, EFI_BLOCK_SIZE_STRING);
859 return EFI_ABORTED;
860 }
861 }
862 //
863 // Read files
864 //
865 for (Index = 0; Index < MAX_NUMBER_OF_FILES_IN_FV; Index++) {
866 //
867 // Read the number of blocks
868 //
869 Status = FindToken (InfFile, FILES_SECTION_STRING, EFI_FILE_NAME_STRING, Index, Value);
870
871 if (Status == EFI_SUCCESS) {
872 //
873 // Add the file
874 //
875 strcpy (FvInfo->FvFiles[Index], Value);
876 } else {
877 break;
878 }
879 }
880
881 if (FindSection (InfFile, COMPONENT_SECTION_STRING)) {
882 Index = 0;
883 //
884 // Read component FV_VARIABLE
885 //
886 Status = FindToken (InfFile, COMPONENT_SECTION_STRING, EFI_NV_VARIABLE_STRING, 0, Value);
887
888 if (Status == EFI_SUCCESS) {
889 //
890 // Add the component
891 //
892 strcpy (FvInfo->FvComponents[Index].ComponentName, EFI_NV_VARIABLE_STRING);
893 Status = AsciiStringToUint64 (Value, FALSE, &Value64);
894 if (EFI_ERROR (Status)) {
895 printf ("ERROR: %s is not a valid integer.\n", EFI_NV_VARIABLE_STRING);
896 return EFI_ABORTED;
897 }
898
899 FvInfo->FvComponents[Index].Size = (UINTN) Value64;
900 } else {
901 printf ("WARNING: Could not read %s.\n", EFI_NV_VARIABLE_STRING);
902 }
903
904 Index++;
905 //
906 // Read component FV_EVENT_LOG
907 //
908 Status = FindToken (InfFile, COMPONENT_SECTION_STRING, EFI_NV_EVENT_LOG_STRING, 0, Value);
909
910 if (Status == EFI_SUCCESS) {
911 //
912 // Add the component
913 //
914 strcpy (FvInfo->FvComponents[Index].ComponentName, EFI_NV_EVENT_LOG_STRING);
915 Status = AsciiStringToUint64 (Value, FALSE, &Value64);
916 if (EFI_ERROR (Status)) {
917 printf ("ERROR: %s is not a valid integer.\n", EFI_NV_EVENT_LOG_STRING);
918 return EFI_ABORTED;
919 }
920
921 FvInfo->FvComponents[Index].Size = (UINTN) Value64;
922 } else {
923 printf ("WARNING: Could not read %s.\n", EFI_NV_EVENT_LOG_STRING);
924 }
925
926 Index++;
927 //
928 // Read component FV_FTW_WORKING
929 //
930 Status = FindToken (InfFile, COMPONENT_SECTION_STRING, EFI_NV_FTW_WORKING_STRING, 0, Value);
931
932 if (Status == EFI_SUCCESS) {
933 //
934 // Add the component
935 //
936 strcpy (FvInfo->FvComponents[Index].ComponentName, EFI_NV_FTW_WORKING_STRING);
937 Status = AsciiStringToUint64 (Value, FALSE, &Value64);
938 if (EFI_ERROR (Status)) {
939 printf ("ERROR: %s is not a valid integer.\n", EFI_NV_FTW_WORKING_STRING);
940 return EFI_ABORTED;
941 }
942
943 FvInfo->FvComponents[Index].Size = (UINTN) Value64;
944 } else {
945 printf ("WARNING: Could not read %s.\n", EFI_NV_FTW_WORKING_STRING);
946 }
947
948 Index++;
949 //
950 // Read component FV_FTW_SPARE
951 //
952 Status = FindToken (InfFile, COMPONENT_SECTION_STRING, EFI_NV_FTW_SPARE_STRING, 0, Value);
953
954 if (Status == EFI_SUCCESS) {
955 //
956 // Add the component
957 //
958 strcpy (FvInfo->FvComponents[Index].ComponentName, EFI_NV_FTW_SPARE_STRING);
959 Status = AsciiStringToUint64 (Value, FALSE, &Value64);
960 if (EFI_ERROR (Status)) {
961 printf ("ERROR: %s is not a valid integer.\n", EFI_NV_FTW_SPARE_STRING);
962 return EFI_ABORTED;
963 }
964
965 FvInfo->FvComponents[Index].Size = (UINTN) Value64;
966 } else {
967 printf ("WARNING: Could not read %s.\n", EFI_NV_FTW_SPARE_STRING);
968 }
969 }
970 //
971 // Compute size for easy access later
972 //
973 FvInfo->Size = 0;
974 for (Index = 0; FvInfo->FvBlocks[Index].NumBlocks; Index++) {
975 FvInfo->Size += FvInfo->FvBlocks[Index].NumBlocks * FvInfo->FvBlocks[Index].BlockLength;
976 }
977
978 return EFI_SUCCESS;
979 }
980
981 VOID
982 UpdateFfsFileState (
983 IN EFI_FFS_FILE_HEADER *FfsFile,
984 IN EFI_FIRMWARE_VOLUME_HEADER *FvHeader
985 )
986 /*++
987
988 Routine Description:
989
990 This function changes the FFS file attributes based on the erase polarity
991 of the FV.
992
993 Arguments:
994
995 FfsFile File header.
996 FvHeader FV header.
997
998 Returns:
999
1000 None
1001
1002 --*/
1003 {
1004 if (FvHeader->Attributes & EFI_FVB_ERASE_POLARITY) {
1005 FfsFile->State = (UINT8)~(FfsFile->State);
1006 }
1007 }
1008
1009 EFI_STATUS
1010 ReadFfsAlignment (
1011 IN EFI_FFS_FILE_HEADER *FfsFile,
1012 IN OUT UINT32 *Alignment
1013 )
1014 /*++
1015
1016 Routine Description:
1017
1018 This function determines the alignment of the FFS input file from the file
1019 attributes.
1020
1021 Arguments:
1022
1023 FfsFile FFS file to parse
1024 Alignment The minimum required alignment of the FFS file, in bytes
1025
1026 Returns:
1027
1028 EFI_SUCCESS The function completed successfully.
1029 EFI_INVALID_PARAMETER One of the input parameters was invalid.
1030 EFI_ABORTED An error occurred.
1031
1032 --*/
1033 {
1034 //
1035 // Verify input parameters.
1036 //
1037 if (FfsFile == NULL || Alignment == NULL) {
1038 return EFI_INVALID_PARAMETER;
1039 }
1040
1041 switch ((FfsFile->Attributes >> 3) & 0x07) {
1042
1043 case 0:
1044 //
1045 // 8 byte alignment, mini alignment requirement for FFS file.
1046 //
1047 *Alignment = (1 << 3);
1048 break;
1049
1050 case 1:
1051 //
1052 // 16 byte alignment
1053 //
1054 *Alignment = (1 << 4);
1055 break;
1056
1057 case 2:
1058 //
1059 // 128 byte alignment
1060 //
1061 *Alignment = (1 << 7);
1062 break;
1063
1064 case 3:
1065 //
1066 // 512 byte alignment
1067 //
1068 *Alignment = (1 << 9);
1069 break;
1070
1071 case 4:
1072 //
1073 // 1K byte alignment
1074 //
1075 *Alignment = (1 << 10);
1076 break;
1077
1078 case 5:
1079 //
1080 // 4K byte alignment
1081 //
1082 *Alignment = (1 << 12);
1083 break;
1084
1085 case 6:
1086 //
1087 // 32K byte alignment
1088 //
1089 *Alignment = (1 << 15);
1090 break;
1091
1092 case 7:
1093 //
1094 // 64K byte alignment
1095 //
1096 *Alignment = (1 << 16);
1097 break;
1098
1099 default:
1100 Error (NULL, 0, 0, "nvalid file attribute calculated, this is most likely a utility error", NULL);
1101 return EFI_ABORTED;
1102 }
1103
1104 return EFI_SUCCESS;
1105 }
1106
1107 EFI_STATUS
1108 AddPadFile (
1109 IN OUT MEMORY_FILE *FvImage,
1110 IN UINT32 DataAlignment
1111 )
1112 /*++
1113
1114 Routine Description:
1115
1116 This function adds a pad file to the FV image if it required to align the
1117 data of the next file.
1118
1119 Arguments:
1120
1121 FvImage The memory image of the FV to add it to. The current offset
1122 must be valid.
1123 DataAlignment The data alignment of the next FFS file.
1124
1125 Returns:
1126
1127 EFI_SUCCESS The function completed successfully.
1128 EFI_INVALID_PARAMETER One of the input parameters was invalid.
1129 EFI_OUT_OF_RESOURCES Insufficient resources exist in the FV to complete
1130 the pad file add.
1131
1132 --*/
1133 {
1134 EFI_FFS_FILE_HEADER *PadFile;
1135 EFI_GUID PadFileGuid;
1136 UINTN PadFileSize;
1137
1138 //
1139 // Verify input parameters.
1140 //
1141 if (FvImage == NULL) {
1142 return EFI_INVALID_PARAMETER;
1143 }
1144 //
1145 // Basic assumption is we start from an 8 byte aligned address
1146 // and our file header is a multiple of 8 bytes
1147 //
1148 assert ((UINTN) FvImage->CurrentFilePointer % 8 == 0);
1149 assert (sizeof (EFI_FFS_FILE_HEADER) % 8 == 0);
1150
1151 //
1152 // Check if a pad file is necessary
1153 //
1154 if (((UINTN) FvImage->CurrentFilePointer - (UINTN) FvImage->FileImage + sizeof (EFI_FFS_FILE_HEADER)) % DataAlignment == 0) {
1155 return EFI_SUCCESS;
1156 }
1157 //
1158 // Write pad file header
1159 //
1160 PadFile = (EFI_FFS_FILE_HEADER *) FvImage->CurrentFilePointer;
1161
1162 //
1163 // Verify that we have enough space for the file header
1164 //
1165 if ((UINTN) (PadFile + sizeof (EFI_FFS_FILE_HEADER)) >= (UINTN) FvImage->Eof) {
1166 return EFI_OUT_OF_RESOURCES;
1167 }
1168
1169 #ifdef __GNUC__
1170 {
1171 uuid_t tmp_id;
1172 uuid_generate (tmp_id);
1173 memcpy (&PadFileGuid, tmp_id, sizeof (EFI_GUID));
1174 }
1175 #else
1176 UuidCreate (&PadFileGuid);
1177 #endif
1178 memset (PadFile, 0, sizeof (EFI_FFS_FILE_HEADER));
1179 memcpy (&PadFile->Name, &PadFileGuid, sizeof (EFI_GUID));
1180 PadFile->Type = EFI_FV_FILETYPE_FFS_PAD;
1181 PadFile->Attributes = 0;
1182
1183 //
1184 // Calculate the pad file size
1185 //
1186 //
1187 // This is the earliest possible valid offset (current plus pad file header
1188 // plus the next file header)
1189 //
1190 PadFileSize = (UINTN) FvImage->CurrentFilePointer - (UINTN) FvImage->FileImage + (sizeof (EFI_FFS_FILE_HEADER) * 2);
1191
1192 //
1193 // Add whatever it takes to get to the next aligned address
1194 //
1195 while ((PadFileSize % DataAlignment) != 0) {
1196 PadFileSize++;
1197 }
1198 //
1199 // Subtract the next file header size
1200 //
1201 PadFileSize -= sizeof (EFI_FFS_FILE_HEADER);
1202
1203 //
1204 // Subtract the starting offset to get size
1205 //
1206 PadFileSize -= (UINTN) FvImage->CurrentFilePointer - (UINTN) FvImage->FileImage;
1207
1208 //
1209 // Write pad file size (calculated size minus next file header size)
1210 //
1211 PadFile->Size[0] = (UINT8) (PadFileSize & 0xFF);
1212 PadFile->Size[1] = (UINT8) ((PadFileSize >> 8) & 0xFF);
1213 PadFile->Size[2] = (UINT8) ((PadFileSize >> 16) & 0xFF);
1214
1215 //
1216 // Fill in checksums and state, they must be 0 for checksumming.
1217 //
1218 PadFile->IntegrityCheck.Checksum.Header = 0;
1219 PadFile->IntegrityCheck.Checksum.File = 0;
1220 PadFile->State = 0;
1221 PadFile->IntegrityCheck.Checksum.Header = CalculateChecksum8 ((UINT8 *) PadFile, sizeof (EFI_FFS_FILE_HEADER));
1222 if (PadFile->Attributes & FFS_ATTRIB_CHECKSUM) {
1223 PadFile->IntegrityCheck.Checksum.File = CalculateChecksum8 ((UINT8 *) PadFile, PadFileSize);
1224 } else {
1225 PadFile->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM;
1226 }
1227
1228 PadFile->State = EFI_FILE_HEADER_CONSTRUCTION | EFI_FILE_HEADER_VALID | EFI_FILE_DATA_VALID;
1229 UpdateFfsFileState (
1230 (EFI_FFS_FILE_HEADER *) PadFile,
1231 (EFI_FIRMWARE_VOLUME_HEADER *) FvImage->FileImage
1232 );
1233
1234 //
1235 // Verify that we have enough space (including the padding
1236 //
1237 if ((UINTN) (PadFile + sizeof (EFI_FFS_FILE_HEADER)) >= (UINTN) FvImage->Eof) {
1238 return EFI_OUT_OF_RESOURCES;
1239 }
1240 //
1241 // Update the current FV pointer
1242 //
1243 FvImage->CurrentFilePointer += PadFileSize;
1244
1245 return EFI_SUCCESS;
1246 }
1247
1248 BOOLEAN
1249 IsVtfFile (
1250 IN EFI_FFS_FILE_HEADER *FileBuffer
1251 )
1252 /*++
1253
1254 Routine Description:
1255
1256 This function checks the header to validate if it is a VTF file
1257
1258 Arguments:
1259
1260 FileBuffer Buffer in which content of a file has been read.
1261
1262 Returns:
1263
1264 TRUE If this is a VTF file
1265 FALSE If this is not a VTF file
1266
1267 --*/
1268 {
1269 EFI_GUID VtfGuid = EFI_FFS_VOLUME_TOP_FILE_GUID;
1270 if (!memcmp (&FileBuffer->Name, &VtfGuid, sizeof (EFI_GUID))) {
1271 return TRUE;
1272 } else {
1273 return FALSE;
1274 }
1275 }
1276
1277 EFI_STATUS
1278 FfsRebaseImageRead (
1279 IN VOID *FileHandle,
1280 IN UINTN FileOffset,
1281 IN OUT UINT32 *ReadSize,
1282 OUT VOID *Buffer
1283 )
1284 /*++
1285
1286 Routine Description:
1287
1288 Support routine for the PE/COFF Loader that reads a buffer from a PE/COFF file
1289
1290 Arguments:
1291
1292 FileHandle - The handle to the PE/COFF file
1293
1294 FileOffset - The offset, in bytes, into the file to read
1295
1296 ReadSize - The number of bytes to read from the file starting at FileOffset
1297
1298 Buffer - A pointer to the buffer to read the data into.
1299
1300 Returns:
1301
1302 EFI_SUCCESS - ReadSize bytes of data were read into Buffer from the PE/COFF file starting at FileOffset
1303
1304 --*/
1305 {
1306 CHAR8 *Destination8;
1307 CHAR8 *Source8;
1308 UINT32 Length;
1309
1310 Destination8 = Buffer;
1311 Source8 = (CHAR8 *) ((UINTN) FileHandle + FileOffset);
1312 Length = *ReadSize;
1313 while (Length--) {
1314 *(Destination8++) = *(Source8++);
1315 }
1316
1317 return EFI_SUCCESS;
1318 }
1319
1320
1321 EFI_STATUS
1322 AddSymFile (
1323 IN UINT64 BaseAddress,
1324 IN EFI_FFS_FILE_HEADER *FfsFile,
1325 IN OUT MEMORY_FILE *SymImage,
1326 IN CHAR8 *SourceFileName
1327 )
1328 /*++
1329
1330 Routine Description:
1331
1332 This function adds the SYM tokens in the source file to the destination file.
1333 The SYM tokens are updated to reflect the base address.
1334
1335 Arguments:
1336
1337 BaseAddress The base address for the new SYM tokens.
1338 FfsFile Pointer to the beginning of the FFS file in question.
1339 SymImage The memory file to update with symbol information.
1340 SourceFileName The source file.
1341
1342 Returns:
1343
1344 EFI_SUCCESS The function completed successfully.
1345 EFI_INVALID_PARAMETER One of the input parameters was invalid.
1346 EFI_ABORTED An error occurred.
1347
1348 --*/
1349 {
1350 FILE *SourceFile;
1351
1352 CHAR8 Buffer[_MAX_PATH];
1353 CHAR8 Type[_MAX_PATH];
1354 CHAR8 Address[_MAX_PATH];
1355 CHAR8 Section[_MAX_PATH];
1356 CHAR8 Token[_MAX_PATH];
1357 CHAR8 SymFileName[_MAX_PATH];
1358 CHAR8 CodeModuleName[_MAX_PATH];
1359 CHAR8 *Ptr;
1360
1361 UINT64 TokenAddress;
1362
1363 EFI_STATUS Status;
1364 EFI_FILE_SECTION_POINTER Pe32Section;
1365 UINT32 EntryPoint;
1366 UINT32 BaseOfCode;
1367 UINT16 MachineType;
1368
1369 //
1370 // Verify input parameters.
1371 //
1372 if (BaseAddress == 0 || FfsFile == NULL || SymImage == NULL || SourceFileName == NULL) {
1373 Error (NULL, 0, 0, "invalid parameter passed to AddSymFile()", NULL);
1374 return EFI_INVALID_PARAMETER;
1375 }
1376 //
1377 // Check if we want to add this file
1378 //
1379 //
1380 // Get the file name
1381 //
1382 strcpy (Buffer, SourceFileName);
1383
1384 //
1385 // Copy the file name for the path of the sym file and truncate the name portion.
1386 //
1387 strcpy (SymFileName, Buffer);
1388 Ptr = strrchr (SymFileName, FILE_SEP_CHAR);
1389 assert (Ptr);
1390 Ptr[0] = 0;
1391
1392 //
1393 // Find the file extension and make it lower case
1394 //
1395 Ptr = strrchr (SymFileName, '.');
1396 if (Ptr != NULL) {
1397 strlwr (Ptr);
1398 }
1399 //
1400 // Check if it is PEI file
1401 //
1402 if (strstr (Buffer, ".pei") != NULL) {
1403 //
1404 // Find the human readable portion
1405 //
1406 if (!strtok (Buffer, "-") ||
1407 !strtok (NULL, "-") ||
1408 !strtok (NULL, "-") ||
1409 !strtok (NULL, "-") ||
1410 !strtok (NULL, "-") ||
1411 !strcpy (Buffer, strtok (NULL, "."))
1412 ) {
1413 Error (NULL, 0, 0, "failed to find human readable portion of the file name in AddSymFile()", NULL);
1414 return EFI_ABORTED;
1415 }
1416 //
1417 // Save code module name
1418 //
1419 strcpy (CodeModuleName, Buffer);
1420
1421 //
1422 // Add the symbol file name and extension to the file path.
1423 //
1424 strcat (Buffer, ".sym");
1425 strcat (SymFileName, FILE_SEP_CHAR);
1426 strcat (SymFileName, Buffer);
1427 } else {
1428 //
1429 // Only handle PEIM files.
1430 //
1431 return EFI_SUCCESS;
1432 }
1433 //
1434 // Find PE32 section
1435 //
1436 Status = GetSectionByType (FfsFile, EFI_SECTION_PE32, 1, &Pe32Section);
1437
1438 //
1439 // BUGBUG: Assume if no PE32 section it is PIC and hardcode base address
1440 //
1441 if (Status == EFI_NOT_FOUND) {
1442 Status = GetSectionByType (FfsFile, EFI_SECTION_TE, 1, &Pe32Section);
1443 }
1444
1445 if (Status == EFI_SUCCESS) {
1446 Status = GetPe32Info (
1447 (VOID *) ((UINTN) Pe32Section.Pe32Section + sizeof (EFI_SECTION_PE32)),
1448 &EntryPoint,
1449 &BaseOfCode,
1450 &MachineType
1451 );
1452 } else if (Status == EFI_NOT_FOUND) {
1453 //
1454 // For PIC, hardcode.
1455 //
1456 BaseOfCode = 0x60;
1457 Status = EFI_SUCCESS;
1458 } else {
1459 Error (NULL, 0, 0, "could not parse a PE32 section from the PEI file", NULL);
1460 return Status;
1461 }
1462
1463 if (EFI_ERROR (Status)) {
1464 Error (NULL, 0, 0, "GetPe32Info() could not get PE32 entry point for PEI file", NULL);
1465 return Status;
1466 }
1467
1468 //
1469 // Open the source file
1470 //
1471 SourceFile = fopen (SymFileName, "r");
1472 if (SourceFile == NULL) {
1473 //
1474 // SYM files are not required.
1475 //
1476 return EFI_SUCCESS;
1477 }
1478 //
1479 // Read the first line
1480 //
1481 if (fgets (Buffer, _MAX_PATH, SourceFile) == NULL) {
1482 Buffer[0] = 0;
1483 }
1484 //
1485 // Make sure it matches the expected sym format
1486 //
1487 if (strcmp (Buffer, "TEXTSYM format | V1.0\n")) {
1488 fclose (SourceFile);
1489 Error (NULL, 0, 0, "AddSymFile() found unexpected sym format in input file", NULL);
1490 return EFI_ABORTED;
1491 }
1492 //
1493 // Read in the file
1494 //
1495 while (feof (SourceFile) == 0) {
1496 //
1497 // Read a line
1498 //
1499 if (fscanf (
1500 SourceFile,
1501 "%s | %s | %s | %s\n",
1502 Type,
1503 Address,
1504 Section,
1505 Token
1506 ) == 4) {
1507 //
1508 // If the token starts with "??" ignore it
1509 //
1510 if (Token[0] == '?' && Token[1] == '?') {
1511 continue;
1512 }
1513 //
1514 // Get the token address
1515 //
1516 AsciiStringToUint64 (Address, TRUE, &TokenAddress);
1517
1518 //
1519 // Add the base address
1520 //
1521 TokenAddress += BaseAddress;
1522
1523 //
1524 // If PE32 or TE section then find the start of code. For PIC it is hardcoded.
1525 //
1526 if (Pe32Section.Pe32Section) {
1527 //
1528 // Add the offset of the PE32 section
1529 //
1530 TokenAddress += (UINTN) Pe32Section.Pe32Section - (UINTN) FfsFile;
1531
1532 //
1533 // Add the size of the PE32 section header
1534 //
1535 TokenAddress += sizeof (EFI_PE32_SECTION);
1536 } else {
1537 //
1538 // For PIC hardcoded.
1539 //
1540 TokenAddress += 0x28;
1541 }
1542
1543 //
1544 // Add the beginning of the code
1545 //
1546 TokenAddress += BaseOfCode;
1547
1548 sprintf (
1549 Buffer,
1550 "%s | %016I64X | %s | _%s%s\n",
1551 Type,
1552 TokenAddress,
1553 Section,
1554 CodeModuleName,
1555 Token
1556 );
1557 memcpy (SymImage->CurrentFilePointer, Buffer, strlen (Buffer) + 1);
1558 SymImage->CurrentFilePointer = (UINT8 *) (((UINTN) SymImage->CurrentFilePointer) + strlen (Buffer) + 1);
1559 }
1560 }
1561
1562 fclose (SourceFile);
1563 return EFI_SUCCESS;
1564 }
1565
1566 EFI_STATUS
1567 AddFile (
1568 IN OUT MEMORY_FILE *FvImage,
1569 IN FV_INFO *FvInfo,
1570 IN UINTN Index,
1571 IN OUT EFI_FFS_FILE_HEADER **VtfFileImage,
1572 IN OUT MEMORY_FILE *SymImage
1573 )
1574 /*++
1575
1576 Routine Description:
1577
1578 This function adds a file to the FV image. The file will pad to the
1579 appropriate alignment if required.
1580
1581 Arguments:
1582
1583 FvImage The memory image of the FV to add it to. The current offset
1584 must be valid.
1585 FvInfo Pointer to information about the FV.
1586 Index The file in the FvInfo file list to add.
1587 VtfFileImage A pointer to the VTF file within the FvImage. If this is equal
1588 to the end of the FvImage then no VTF previously found.
1589 SymImage The memory image of the Sym file to update if symbols are present.
1590 The current offset must be valid.
1591
1592 Returns:
1593
1594 EFI_SUCCESS The function completed successfully.
1595 EFI_INVALID_PARAMETER One of the input parameters was invalid.
1596 EFI_ABORTED An error occurred.
1597 EFI_OUT_OF_RESOURCES Insufficient resources exist to complete the add.
1598
1599 --*/
1600 {
1601 FILE *NewFile;
1602 UINTN FileSize;
1603 UINT8 *FileBuffer;
1604 UINTN NumBytesRead;
1605 UINT32 CurrentFileAlignment;
1606 EFI_STATUS Status;
1607 EFI_PHYSICAL_ADDRESS CurrentFileBaseAddress;
1608 UINT8 VtfHeaderChecksum;
1609 UINT8 VtfFileChecksum;
1610 UINT8 FileState;
1611 EFI_FFS_FILE_TAIL TailValue;
1612 UINT32 TailSize;
1613 //
1614 // Verify input parameters.
1615 //
1616 if (FvImage == NULL || FvInfo == NULL || FvInfo->FvFiles[Index][0] == 0 || VtfFileImage == NULL || SymImage == NULL) {
1617 return EFI_INVALID_PARAMETER;
1618 }
1619 //
1620 // Read the file to add
1621 //
1622 NewFile = fopen (FvInfo->FvFiles[Index], "rb");
1623
1624 if (NewFile == NULL) {
1625 Error (NULL, 0, 0, FvInfo->FvFiles[Index], "failed to open file for reading");
1626 return EFI_ABORTED;
1627 }
1628 //
1629 // Get the file size
1630 //
1631 FileSize = _filelength (fileno (NewFile));
1632
1633 //
1634 // Read the file into a buffer
1635 //
1636 FileBuffer = malloc (FileSize);
1637 if (FileBuffer == NULL) {
1638 Error (NULL, 0, 0, "memory allocation failure", NULL);
1639 return EFI_OUT_OF_RESOURCES;
1640 }
1641
1642 NumBytesRead = fread (FileBuffer, sizeof (UINT8), FileSize, NewFile);
1643
1644 //
1645 // Done with the file, from this point on we will just use the buffer read.
1646 //
1647 fclose (NewFile);
1648
1649 //
1650 // Verify read successful
1651 //
1652 if (NumBytesRead != sizeof (UINT8) * FileSize) {
1653 free (FileBuffer);
1654 Error (NULL, 0, 0, FvInfo->FvFiles[Index], "failed to read input file contents");
1655 return EFI_ABORTED;
1656 }
1657 //
1658 // Verify space exists to add the file
1659 //
1660 if (FileSize > (UINTN) ((UINTN) *VtfFileImage - (UINTN) FvImage->CurrentFilePointer)) {
1661 Error (NULL, 0, 0, FvInfo->FvFiles[Index], "insufficient space remains to add the file");
1662 return EFI_OUT_OF_RESOURCES;
1663 }
1664 //
1665 // Update the file state based on polarity of the FV.
1666 //
1667 UpdateFfsFileState (
1668 (EFI_FFS_FILE_HEADER *) FileBuffer,
1669 (EFI_FIRMWARE_VOLUME_HEADER *) FvImage->FileImage
1670 );
1671
1672 //
1673 // If we have a VTF file, add it at the top.
1674 //
1675 if (IsVtfFile ((EFI_FFS_FILE_HEADER *) FileBuffer)) {
1676 if ((UINTN) *VtfFileImage == (UINTN) FvImage->Eof) {
1677 //
1678 // No previous VTF, add this one.
1679 //
1680 *VtfFileImage = (EFI_FFS_FILE_HEADER *) (UINTN) ((UINTN) FvImage->FileImage + FvInfo->Size - FileSize);
1681 //
1682 // Sanity check. The file MUST align appropriately
1683 //
1684 if ((((UINTN) *VtfFileImage) & 0x07) != 0) {
1685 Error (NULL, 0, 0, "VTF file does not align on 8-byte boundary", NULL);
1686 }
1687 //
1688 // copy VTF File Header
1689 //
1690 memcpy (*VtfFileImage, FileBuffer, sizeof (EFI_FFS_FILE_HEADER));
1691
1692 //
1693 // Copy VTF body
1694 //
1695 memcpy (
1696 (UINT8 *) *VtfFileImage + sizeof (EFI_FFS_FILE_HEADER),
1697 FileBuffer + sizeof (EFI_FFS_FILE_HEADER),
1698 FileSize - sizeof (EFI_FFS_FILE_HEADER)
1699 );
1700
1701 //
1702 // re-calculate the VTF File Header
1703 //
1704 FileState = (*VtfFileImage)->State;
1705 (*VtfFileImage)->State = 0;
1706 *(UINT32 *) ((*VtfFileImage)->Size) = FileSize;
1707 (*VtfFileImage)->IntegrityCheck.Checksum.Header = 0;
1708 (*VtfFileImage)->IntegrityCheck.Checksum.File = 0;
1709
1710 VtfHeaderChecksum = CalculateChecksum8 ((UINT8 *) *VtfFileImage, sizeof (EFI_FFS_FILE_HEADER));
1711 (*VtfFileImage)->IntegrityCheck.Checksum.Header = VtfHeaderChecksum;
1712 //
1713 // Determine if it has a tail
1714 //
1715 if ((*VtfFileImage)->Attributes & FFS_ATTRIB_TAIL_PRESENT) {
1716 TailSize = sizeof (EFI_FFS_FILE_TAIL);
1717 } else {
1718 TailSize = 0;
1719 }
1720
1721 if ((*VtfFileImage)->Attributes & FFS_ATTRIB_CHECKSUM) {
1722 VtfFileChecksum = CalculateChecksum8 ((UINT8 *) *VtfFileImage, FileSize - TailSize);
1723 (*VtfFileImage)->IntegrityCheck.Checksum.File = VtfFileChecksum;
1724 } else {
1725 (*VtfFileImage)->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM;
1726 }
1727 //
1728 // If it has a file tail, update it
1729 //
1730 if ((*VtfFileImage)->Attributes & FFS_ATTRIB_TAIL_PRESENT) {
1731 TailValue = (EFI_FFS_FILE_TAIL) (~((*VtfFileImage)->IntegrityCheck.TailReference));
1732 *(EFI_FFS_FILE_TAIL *) (((UINTN) (*VtfFileImage) + GetLength ((*VtfFileImage)->Size) - sizeof (EFI_FFS_FILE_TAIL))) = TailValue;
1733 }
1734 (*VtfFileImage)->State = FileState;
1735 free (FileBuffer);
1736 return EFI_SUCCESS;
1737 } else {
1738 //
1739 // Already found a VTF file.
1740 //
1741 Error (NULL, 0, 0, "multiple VTF files are illegal in a single FV", NULL);
1742 free (FileBuffer);
1743 return EFI_ABORTED;
1744 }
1745 }
1746 //
1747 // Check if alignment is required
1748 //
1749 Status = ReadFfsAlignment ((EFI_FFS_FILE_HEADER *) FileBuffer, &CurrentFileAlignment);
1750 if (EFI_ERROR (Status)) {
1751 printf ("ERROR: Could not determine alignment of file %s.\n", FvInfo->FvFiles[Index]);
1752 free (FileBuffer);
1753 return EFI_ABORTED;
1754 }
1755
1756 //
1757 // Find the largest alignment of all the FFS files in the FV
1758 //
1759 if (CurrentFileAlignment > MaxFfsAlignment) {
1760 MaxFfsAlignment = CurrentFileAlignment;
1761 }
1762 //
1763 // Add pad file if necessary
1764 //
1765 Status = AddPadFile (FvImage, CurrentFileAlignment);
1766 if (EFI_ERROR (Status)) {
1767 printf ("ERROR: Could not align the file data properly.\n");
1768 free (FileBuffer);
1769 return EFI_ABORTED;
1770 }
1771 //
1772 // Add file
1773 //
1774 if ((FvImage->CurrentFilePointer + FileSize) < FvImage->Eof) {
1775 //
1776 // Copy the file
1777 //
1778 memcpy (FvImage->CurrentFilePointer, FileBuffer, FileSize);
1779
1780 //
1781 // If the file is XIP, rebase
1782 //
1783 CurrentFileBaseAddress = FvInfo->BaseAddress + ((UINTN) FvImage->CurrentFilePointer - (UINTN) FvImage->FileImage);
1784 //
1785 // Status = RebaseFfsFile ((EFI_FFS_FILE_HEADER*) FvImage->CurrentFilePointer, CurrentFileBaseAddress);
1786 // if (EFI_ERROR(Status)) {
1787 // printf ("ERROR: Could not rebase the file %s.\n", FvInfo->FvFiles[Index]);
1788 // return EFI_ABORTED;
1789 // }
1790 //
1791 // Update Symbol file
1792 //
1793 Status = AddSymFile (
1794 CurrentFileBaseAddress,
1795 (EFI_FFS_FILE_HEADER *) FvImage->CurrentFilePointer,
1796 SymImage,
1797 FvInfo->FvFiles[Index]
1798 );
1799 assert (!EFI_ERROR (Status));
1800
1801 //
1802 // Update the current pointer in the FV image
1803 //
1804 FvImage->CurrentFilePointer += FileSize;
1805 } else {
1806 printf ("ERROR: The firmware volume is out of space, could not add file %s.\n", FvInfo->FvFiles[Index]);
1807 return EFI_ABORTED;
1808 }
1809 //
1810 // Make next file start at QWord Boundry
1811 //
1812 while (((UINTN) FvImage->CurrentFilePointer & 0x07) != 0) {
1813 FvImage->CurrentFilePointer++;
1814 }
1815 //
1816 // Free allocated memory.
1817 //
1818 free (FileBuffer);
1819
1820 return EFI_SUCCESS;
1821 }
1822
1823 EFI_STATUS
1824 AddVariableBlock (
1825 IN UINT8 *FvImage,
1826 IN UINTN Size,
1827 IN FV_INFO *FvInfo
1828 )
1829 {
1830 EFI_FIRMWARE_VOLUME_HEADER *FvHeader;
1831 VARIABLE_STORE_HEADER *VarStoreHeader;
1832 //
1833 // Variable block should exclude FvHeader. Since the length of
1834 // FvHeader depends on the block map, which is variable length,
1835 // we could only decide the actual variable block length here.
1836 //
1837 FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) FvImage;
1838 FvImage = FvImage + FvHeader->HeaderLength;
1839
1840 VarStoreHeader = (VARIABLE_STORE_HEADER *) FvImage;
1841
1842 VarStoreHeader->Signature = VARIABLE_STORE_SIGNATURE;
1843 VarStoreHeader->Size = Size - FvHeader->HeaderLength;
1844 VarStoreHeader->Format = VARIABLE_STORE_FORMATTED;
1845 VarStoreHeader->State = VARIABLE_STORE_HEALTHY;
1846 VarStoreHeader->Reserved = 0;
1847 VarStoreHeader->Reserved1 = 0;
1848
1849 return EFI_SUCCESS;
1850 }
1851
1852 EFI_STATUS
1853 AddEventLogBlock (
1854 IN UINT8 *FvImage,
1855 IN UINTN Size,
1856 IN FV_INFO *FvInfo
1857 )
1858 {
1859 return EFI_SUCCESS;
1860 }
1861
1862 EFI_STATUS
1863 AddFTWWorkingBlock (
1864 IN UINT8 *FvImage,
1865 IN UINTN Size,
1866 IN FV_INFO *FvInfo
1867 )
1868 {
1869 EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *FTWHeader;
1870 UINT32 Crc32;
1871
1872 Crc32 = 0;
1873 FTWHeader = (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *) FvImage;
1874 memcpy (&FTWHeader->Signature, &(FvInfo->FvGuid), sizeof (EFI_GUID));
1875 FTWHeader->WriteQueueSize = Size - sizeof (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER);
1876 CalculateCrc32 (FvImage, sizeof (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER), &Crc32);
1877 FTWHeader->Crc = Crc32;
1878 if (FvInfo->FvAttributes & EFI_FVB_ERASE_POLARITY) {
1879 FTWHeader->WorkingBlockValid = 0;
1880 FTWHeader->WorkingBlockInvalid = 1;
1881 } else {
1882 FTWHeader->WorkingBlockValid = 1;
1883 FTWHeader->WorkingBlockInvalid = 0;
1884 }
1885
1886 return EFI_SUCCESS;
1887 }
1888
1889 EFI_STATUS
1890 AddFTWSpareBlock (
1891 IN UINT8 *FvImage,
1892 IN UINTN Size,
1893 IN FV_INFO *FvInfo
1894 )
1895 {
1896 return EFI_SUCCESS;
1897 }
1898
1899 EFI_STATUS
1900 GenNonFFSFv (
1901 IN UINT8 *FvImage,
1902 IN FV_INFO *FvInfo
1903 )
1904 /*++
1905
1906 Routine Description:
1907
1908 This function generate the non FFS FV image, such as the working block
1909 and spare block. How each component of the FV is built is component
1910 specific.
1911
1912 Arguments:
1913
1914 FvImage The memory image of the FV to add it to. The current offset
1915 must be valid.
1916 FvInfo Pointer to information about the FV.
1917
1918 Returns:
1919
1920 EFI_SUCCESS The function completed successfully.
1921 EFI_INVALID_PARAMETER One of the input parameters was invalid.
1922 EFI_ABORTED An error occurred.
1923 EFI_OUT_OF_RESOURCES Insufficient resources exist to complete the add.
1924
1925 --*/
1926 {
1927 UINTN Index;
1928 EFI_FIRMWARE_VOLUME_HEADER *FvHeader;
1929 UINT64 TotalSize;
1930
1931 FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) FvImage;
1932 TotalSize = 0;
1933
1934 for (Index = 0; FvInfo->FvComponents[Index].Size != 0; Index++) {
1935 if (stricmp (FvInfo->FvComponents[Index].ComponentName, EFI_NV_VARIABLE_STRING) == 0) {
1936 AddVariableBlock (FvImage, FvInfo->FvComponents[Index].Size, FvInfo);
1937 } else if (stricmp (FvInfo->FvComponents[Index].ComponentName, EFI_NV_EVENT_LOG_STRING) == 0) {
1938 AddEventLogBlock (FvImage, FvInfo->FvComponents[Index].Size, FvInfo);
1939 } else if (stricmp (FvInfo->FvComponents[Index].ComponentName, EFI_NV_FTW_WORKING_STRING) == 0) {
1940 AddFTWWorkingBlock (FvImage, FvInfo->FvComponents[Index].Size, FvInfo);
1941 } else if (stricmp (FvInfo->FvComponents[Index].ComponentName, EFI_NV_FTW_SPARE_STRING) == 0) {
1942 AddFTWSpareBlock (FvImage, FvInfo->FvComponents[Index].Size, FvInfo);
1943 } else {
1944 printf ("Error. Unknown Non-FFS block %s \n", FvInfo->FvComponents[Index].ComponentName);
1945 return EFI_ABORTED;
1946 }
1947
1948 FvImage = FvImage + FvInfo->FvComponents[Index].Size;
1949 TotalSize = TotalSize + FvInfo->FvComponents[Index].Size;
1950 }
1951 //
1952 // Index and TotalSize is zero mean there's no component, so this is an empty fv
1953 //
1954 if ((Index != 0 || TotalSize != 0) && TotalSize != FvInfo->Size) {
1955 printf ("Error. Component size does not sum up to FV size.\n");
1956 return EFI_ABORTED;
1957 }
1958
1959 return EFI_SUCCESS;
1960 }
1961
1962 EFI_STATUS
1963 PadFvImage (
1964 IN MEMORY_FILE *FvImage,
1965 IN EFI_FFS_FILE_HEADER *VtfFileImage
1966 )
1967 /*++
1968
1969 Routine Description:
1970
1971 This function places a pad file between the last file in the FV and the VTF
1972 file if the VTF file exists.
1973
1974 Arguments:
1975
1976 FvImage Memory file for the FV memory image
1977 VtfFileImage The address of the VTF file. If this is the end of the FV
1978 image, no VTF exists and no pad file is needed.
1979
1980 Returns:
1981
1982 EFI_SUCCESS Completed successfully.
1983 EFI_INVALID_PARAMETER One of the input parameters was NULL.
1984
1985 --*/
1986 {
1987 EFI_FFS_FILE_HEADER *PadFile;
1988 UINTN FileSize;
1989
1990 //
1991 // If there is no VTF or the VTF naturally follows the previous file without a
1992 // pad file, then there's nothing to do
1993 //
1994 if ((UINTN) VtfFileImage == (UINTN) FvImage->Eof || (void *) FvImage->CurrentFilePointer == (void *) VtfFileImage) {
1995 return EFI_SUCCESS;
1996 }
1997 //
1998 // Pad file starts at beginning of free space
1999 //
2000 PadFile = (EFI_FFS_FILE_HEADER *) FvImage->CurrentFilePointer;
2001
2002 //
2003 // write header
2004 //
2005 memset (PadFile, 0, sizeof (EFI_FFS_FILE_HEADER));
2006 memcpy (&PadFile->Name, &DefaultFvPadFileNameGuid, sizeof (EFI_GUID));
2007 PadFile->Type = EFI_FV_FILETYPE_FFS_PAD;
2008 PadFile->Attributes = 0;
2009
2010 //
2011 // FileSize includes the EFI_FFS_FILE_HEADER
2012 //
2013 FileSize = (UINTN) VtfFileImage - (UINTN) FvImage->CurrentFilePointer;
2014 PadFile->Size[0] = (UINT8) (FileSize & 0x000000FF);
2015 PadFile->Size[1] = (UINT8) ((FileSize & 0x0000FF00) >> 8);
2016 PadFile->Size[2] = (UINT8) ((FileSize & 0x00FF0000) >> 16);
2017
2018 //
2019 // Fill in checksums and state, must be zero during checksum calculation.
2020 //
2021 PadFile->IntegrityCheck.Checksum.Header = 0;
2022 PadFile->IntegrityCheck.Checksum.File = 0;
2023 PadFile->State = 0;
2024 PadFile->IntegrityCheck.Checksum.Header = CalculateChecksum8 ((UINT8 *) PadFile, sizeof (EFI_FFS_FILE_HEADER));
2025 if (PadFile->Attributes & FFS_ATTRIB_CHECKSUM) {
2026 PadFile->IntegrityCheck.Checksum.File = CalculateChecksum8 ((UINT8 *) PadFile, FileSize);
2027 } else {
2028 PadFile->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM;
2029 }
2030
2031 PadFile->State = EFI_FILE_HEADER_CONSTRUCTION | EFI_FILE_HEADER_VALID | EFI_FILE_DATA_VALID;
2032
2033 UpdateFfsFileState (
2034 (EFI_FFS_FILE_HEADER *) PadFile,
2035 (EFI_FIRMWARE_VOLUME_HEADER *) FvImage->FileImage
2036 );
2037 //
2038 // Update the current FV pointer
2039 //
2040 FvImage->CurrentFilePointer = FvImage->Eof;
2041
2042 return EFI_SUCCESS;
2043 }
2044
2045 EFI_STATUS
2046 UpdateResetVector (
2047 IN MEMORY_FILE *FvImage,
2048 IN FV_INFO *FvInfo,
2049 IN EFI_FFS_FILE_HEADER *VtfFile
2050 )
2051 /*++
2052
2053 Routine Description:
2054
2055 This parses the FV looking for the PEI core and then plugs the address into
2056 the SALE_ENTRY point of the BSF/VTF for IPF and does BUGBUG TBD action to
2057 complete an IA32 Bootstrap FV.
2058
2059 Arguments:
2060
2061 FvImage Memory file for the FV memory image
2062 FvInfo Information read from INF file.
2063 VtfFile Pointer to the VTF file in the FV image.
2064
2065 Returns:
2066
2067 EFI_SUCCESS Function Completed successfully.
2068 EFI_ABORTED Error encountered.
2069 EFI_INVALID_PARAMETER A required parameter was NULL.
2070 EFI_NOT_FOUND PEI Core file not found.
2071
2072 --*/
2073 {
2074 EFI_FFS_FILE_HEADER *PeiCoreFile;
2075 EFI_FFS_FILE_HEADER *SecCoreFile;
2076 EFI_STATUS Status;
2077 EFI_FILE_SECTION_POINTER Pe32Section;
2078 UINT32 EntryPoint;
2079 UINT32 BaseOfCode;
2080 UINT16 MachineType;
2081 EFI_PHYSICAL_ADDRESS PeiCorePhysicalAddress;
2082 EFI_PHYSICAL_ADDRESS SecCorePhysicalAddress;
2083 EFI_PHYSICAL_ADDRESS *SecCoreEntryAddressPtr;
2084 UINT32 *Ia32ResetAddressPtr;
2085 UINT8 *BytePointer;
2086 UINT8 *BytePointer2;
2087 UINT16 *WordPointer;
2088 UINT16 CheckSum;
2089 UINTN Index;
2090 EFI_FFS_FILE_STATE SavedState;
2091 EFI_FFS_FILE_TAIL TailValue;
2092 UINT32 TailSize;
2093 UINT64 FitAddress;
2094 FIT_TABLE *FitTablePtr;
2095
2096 //
2097 // Verify input parameters
2098 //
2099 if (FvImage == NULL || FvInfo == NULL || VtfFile == NULL) {
2100 return EFI_INVALID_PARAMETER;
2101 }
2102 //
2103 // Initialize FV library
2104 //
2105 InitializeFvLib (FvImage->FileImage, (UINTN) FvImage->Eof - (UINTN) FvImage->FileImage);
2106
2107 //
2108 // Verify VTF file
2109 //
2110 Status = VerifyFfsFile (VtfFile);
2111 if (EFI_ERROR (Status)) {
2112 return EFI_INVALID_PARAMETER;
2113 }
2114 //
2115 // Find the PEI Core
2116 //
2117 Status = GetFileByType (EFI_FV_FILETYPE_PEI_CORE, 1, &PeiCoreFile);
2118 if (EFI_ERROR (Status) || PeiCoreFile == NULL) {
2119 Error (NULL, 0, 0, "could not find the PEI core in the FV", NULL);
2120 return EFI_ABORTED;
2121 }
2122
2123 //
2124 // PEI Core found, now find PE32 or TE section
2125 //
2126 Status = GetSectionByType (PeiCoreFile, EFI_SECTION_PE32, 1, &Pe32Section);
2127 if (Status == EFI_NOT_FOUND) {
2128 Status = GetSectionByType (PeiCoreFile, EFI_SECTION_TE, 1, &Pe32Section);
2129 }
2130
2131 if (EFI_ERROR (Status)) {
2132 Error (NULL, 0, 0, "could not find PE32 or TE section in PEI core file", NULL);
2133 return EFI_ABORTED;
2134 }
2135
2136 Status = GetPe32Info (
2137 (VOID *) ((UINTN) Pe32Section.Pe32Section + sizeof (EFI_SECTION_PE32)),
2138 &EntryPoint,
2139 &BaseOfCode,
2140 &MachineType
2141 );
2142
2143 if (EFI_ERROR (Status)) {
2144 Error (NULL, 0, 0, "could not get PE32 entry point for PEI core", NULL);
2145 return EFI_ABORTED;
2146 }
2147 //
2148 // Physical address is FV base + offset of PE32 + offset of the entry point
2149 //
2150 PeiCorePhysicalAddress = FvInfo->BaseAddress;
2151 PeiCorePhysicalAddress += (UINTN) Pe32Section.Pe32Section + sizeof (EFI_SECTION_PE32) - (UINTN) FvImage->FileImage;
2152 PeiCorePhysicalAddress += EntryPoint;
2153
2154 if (MachineType == EFI_IMAGE_MACHINE_IA64) {
2155 //
2156 // Update PEI_CORE address
2157 //
2158 //
2159 // Set the uncached attribute bit in the physical address
2160 //
2161 PeiCorePhysicalAddress |= 0x8000000000000000ULL;
2162
2163 //
2164 // Check if address is aligned on a 16 byte boundary
2165 //
2166 if (PeiCorePhysicalAddress & 0xF) {
2167 printf (
2168 "ERROR: PEI_CORE entry point is not aligned on a 16 byte boundary, address specified is %Xh.\n",
2169 PeiCorePhysicalAddress
2170 );
2171 return EFI_ABORTED;
2172 }
2173 //
2174 // First Get the FIT table address
2175 //
2176 FitAddress = (*(UINT64 *) (FvImage->Eof - IPF_FIT_ADDRESS_OFFSET)) & 0xFFFFFFFF;
2177
2178 FitTablePtr = (FIT_TABLE *) (FvImage->FileImage + (FitAddress - FvInfo->BaseAddress));
2179
2180 Status = UpdatePeiCoreEntryInFit (FitTablePtr, PeiCorePhysicalAddress);
2181
2182 if (!EFI_ERROR (Status)) {
2183 UpdateFitCheckSum (FitTablePtr);
2184 }
2185 //
2186 // Find the Sec Core
2187 //
2188 Status = GetFileByType (EFI_FV_FILETYPE_SECURITY_CORE, 1, &SecCoreFile);
2189 if (EFI_ERROR (Status) || SecCoreFile == NULL) {
2190 Error (NULL, 0, 0, "could not find the Sec core in the FV", NULL);
2191 return EFI_ABORTED;
2192 }
2193 //
2194 // Sec Core found, now find PE32 section
2195 //
2196 Status = GetSectionByType (SecCoreFile, EFI_SECTION_PE32, 1, &Pe32Section);
2197 if (EFI_ERROR (Status)) {
2198 Error (NULL, 0, 0, "could not find PE32 section in SEC core file", NULL);
2199 return EFI_ABORTED;
2200 }
2201
2202 Status = GetPe32Info (
2203 (VOID *) ((UINTN) Pe32Section.Pe32Section + sizeof (EFI_SECTION_PE32)),
2204 &EntryPoint,
2205 &BaseOfCode,
2206 &MachineType
2207 );
2208 if (EFI_ERROR (Status)) {
2209 Error (NULL, 0, 0, "could not get PE32 entry point for SEC core", NULL);
2210 return EFI_ABORTED;
2211 }
2212 //
2213 // Physical address is FV base + offset of PE32 + offset of the entry point
2214 //
2215 SecCorePhysicalAddress = FvInfo->BaseAddress;
2216 SecCorePhysicalAddress += (UINTN) Pe32Section.Pe32Section + sizeof (EFI_SECTION_PE32) - (UINTN) FvImage->FileImage;
2217 SecCorePhysicalAddress += EntryPoint;
2218
2219 //
2220 // Update SEC_CORE address
2221 //
2222 //
2223 // Set the uncached attribute bit in the physical address
2224 //
2225 SecCorePhysicalAddress |= 0x8000000000000000ULL;
2226
2227 //
2228 // Update the address
2229 //
2230 SecCoreEntryAddressPtr = (EFI_PHYSICAL_ADDRESS *) ((UINTN) FvImage->Eof - IPF_SALE_ENTRY_ADDRESS_OFFSET);
2231 *SecCoreEntryAddressPtr = SecCorePhysicalAddress;
2232
2233 //
2234 // Check if address is aligned on a 16 byte boundary
2235 //
2236 if (SecCorePhysicalAddress & 0xF) {
2237 printf (
2238 "ERROR: SALE_ENTRY entry point is not aligned on a 16 byte boundary, address specified is %Xh.\n",
2239 SecCorePhysicalAddress
2240 );
2241 return EFI_ABORTED;
2242 }
2243 } else if (MachineType == EFI_IMAGE_MACHINE_IA32) {
2244 //
2245 // Get the location to update
2246 //
2247 Ia32ResetAddressPtr = (UINT32 *) ((UINTN) FvImage->Eof - IA32_PEI_CORE_ENTRY_OFFSET);
2248
2249 //
2250 // Write lower 32 bits of physical address
2251 //
2252 *Ia32ResetAddressPtr = (UINT32) PeiCorePhysicalAddress;
2253
2254 //
2255 // Update the BFV base address
2256 //
2257 Ia32ResetAddressPtr = (UINT32 *) ((UINTN) FvImage->Eof - 4);
2258 *Ia32ResetAddressPtr = (UINT32) (FvInfo->BaseAddress);
2259
2260 CheckSum = 0x0000;
2261
2262 //
2263 // Update the Startup AP in the FVH header block ZeroVector region.
2264 //
2265 BytePointer = (UINT8 *) ((UINTN) FvImage->FileImage);
2266 BytePointer2 = (FvInfo->Size == 0x10000) ? m64kRecoveryStartupApDataArray : m128kRecoveryStartupApDataArray;
2267 for (Index = 0; Index < SIZEOF_STARTUP_DATA_ARRAY; Index++) {
2268 *BytePointer++ = *BytePointer2++;
2269 }
2270 //
2271 // Calculate the checksum
2272 //
2273 WordPointer = (UINT16 *) ((UINTN) FvImage->FileImage);
2274 for (Index = 0; Index < SIZEOF_STARTUP_DATA_ARRAY / 2; Index++) {
2275 CheckSum = (UINT16) (CheckSum + ((UINT16) *WordPointer));
2276 WordPointer++;
2277 }
2278 //
2279 // Update the checksum field
2280 //
2281 BytePointer = (UINT8 *) ((UINTN) FvImage->FileImage);
2282 BytePointer += (SIZEOF_STARTUP_DATA_ARRAY - 2);
2283 WordPointer = (UINT16 *) BytePointer;
2284 *WordPointer = (UINT16) (0x10000 - (UINT32) CheckSum);
2285 } else {
2286 Error (NULL, 0, 0, "invalid machine type in PEI core", "machine type=0x%X", (UINT32) MachineType);
2287 return EFI_ABORTED;
2288 }
2289 //
2290 // Determine if it has an FFS file tail.
2291 //
2292 if (VtfFile->Attributes & FFS_ATTRIB_TAIL_PRESENT) {
2293 TailSize = sizeof (EFI_FFS_FILE_TAIL);
2294 } else {
2295 TailSize = 0;
2296 }
2297 //
2298 // Now update file checksum
2299 //
2300 SavedState = VtfFile->State;
2301 VtfFile->IntegrityCheck.Checksum.File = 0;
2302 VtfFile->State = 0;
2303 if (VtfFile->Attributes & FFS_ATTRIB_CHECKSUM) {
2304 VtfFile->IntegrityCheck.Checksum.File = CalculateChecksum8 (
2305 (UINT8 *) VtfFile,
2306 GetLength (VtfFile->Size) - TailSize
2307 );
2308 } else {
2309 VtfFile->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM;
2310 }
2311
2312 VtfFile->State = SavedState;
2313
2314 //
2315 // Update tail if present
2316 //
2317 if (VtfFile->Attributes & FFS_ATTRIB_TAIL_PRESENT) {
2318 TailValue = (EFI_FFS_FILE_TAIL) (~(VtfFile->IntegrityCheck.TailReference));
2319 *(EFI_FFS_FILE_TAIL *) (((UINTN) (VtfFile) + GetLength (VtfFile->Size) - sizeof (EFI_FFS_FILE_TAIL))) = TailValue;
2320 }
2321
2322 return EFI_SUCCESS;
2323 }
2324
2325 EFI_STATUS
2326 GetPe32Info (
2327 IN UINT8 *Pe32,
2328 OUT UINT32 *EntryPoint,
2329 OUT UINT32 *BaseOfCode,
2330 OUT UINT16 *MachineType
2331 )
2332 /*++
2333
2334 Routine Description:
2335
2336 Retrieves the PE32 entry point offset and machine type from PE image or TeImage.
2337 See EfiImage.h for machine types. The entry point offset is from the beginning
2338 of the PE32 buffer passed in.
2339
2340 Arguments:
2341
2342 Pe32 Beginning of the PE32.
2343 EntryPoint Offset from the beginning of the PE32 to the image entry point.
2344 BaseOfCode Base address of code.
2345 MachineType Magic number for the machine type.
2346
2347 Returns:
2348
2349 EFI_SUCCESS Function completed successfully.
2350 EFI_ABORTED Error encountered.
2351 EFI_INVALID_PARAMETER A required parameter was NULL.
2352 EFI_UNSUPPORTED The operation is unsupported.
2353
2354 --*/
2355 {
2356 EFI_IMAGE_DOS_HEADER *DosHeader;
2357 EFI_IMAGE_NT_HEADERS *NtHeader;
2358 EFI_TE_IMAGE_HEADER *TeHeader;
2359
2360 //
2361 // Verify input parameters
2362 //
2363 if (Pe32 == NULL) {
2364 return EFI_INVALID_PARAMETER;
2365 }
2366
2367 //
2368 // First check whether it is one TE Image.
2369 //
2370 TeHeader = (EFI_TE_IMAGE_HEADER *) Pe32;
2371 if (TeHeader->Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) {
2372 //
2373 // By TeImage Header to get output
2374 //
2375 *EntryPoint = TeHeader->AddressOfEntryPoint + sizeof (EFI_TE_IMAGE_HEADER) - TeHeader->StrippedSize;
2376 *BaseOfCode = TeHeader->BaseOfCode + sizeof (EFI_TE_IMAGE_HEADER) - TeHeader->StrippedSize;
2377 *MachineType = TeHeader->Machine;
2378 } else {
2379
2380 //
2381 // Then check whether
2382 // First is the DOS header
2383 //
2384 DosHeader = (EFI_IMAGE_DOS_HEADER *) Pe32;
2385
2386 //
2387 // Verify DOS header is expected
2388 //
2389 if (DosHeader->e_magic != EFI_IMAGE_DOS_SIGNATURE) {
2390 printf ("ERROR: Unknown magic number in the DOS header, 0x%04X.\n", DosHeader->e_magic);
2391 return EFI_UNSUPPORTED;
2392 }
2393 //
2394 // Immediately following is the NT header.
2395 //
2396 NtHeader = (EFI_IMAGE_NT_HEADERS *) ((UINTN) Pe32 + DosHeader->e_lfanew);
2397
2398 //
2399 // Verify NT header is expected
2400 //
2401 if (NtHeader->Signature != EFI_IMAGE_NT_SIGNATURE) {
2402 printf ("ERROR: Unrecognized image signature 0x%08X.\n", NtHeader->Signature);
2403 return EFI_UNSUPPORTED;
2404 }
2405 //
2406 // Get output
2407 //
2408 *EntryPoint = NtHeader->OptionalHeader.AddressOfEntryPoint;
2409 *BaseOfCode = NtHeader->OptionalHeader.BaseOfCode;
2410 *MachineType = NtHeader->FileHeader.Machine;
2411 }
2412
2413 //
2414 // Verify machine type is supported
2415 //
2416 if (*MachineType != EFI_IMAGE_MACHINE_IA32 && *MachineType != EFI_IMAGE_MACHINE_IA64 && *MachineType != EFI_IMAGE_MACHINE_X64 && *MachineType != EFI_IMAGE_MACHINE_EBC) {
2417 printf ("ERROR: Unrecognized machine type in the PE32 file.\n");
2418 return EFI_UNSUPPORTED;
2419 }
2420
2421 return EFI_SUCCESS;
2422 }
2423 //
2424 // Exposed function implementations (prototypes are defined in GenFvImageLib.h)
2425 //
2426 EFI_STATUS
2427 GenerateFvImage (
2428 IN CHAR8 *InfFileImage,
2429 IN UINTN InfFileSize,
2430 OUT UINT8 **FvImage,
2431 OUT UINTN *FvImageSize,
2432 OUT CHAR8 **FvFileName,
2433 OUT UINT8 **SymImage,
2434 OUT UINTN *SymImageSize,
2435 OUT CHAR8 **SymFileName
2436 )
2437 /*++
2438
2439 Routine Description:
2440
2441 This is the main function which will be called from application.
2442
2443 Arguments:
2444
2445 InfFileImage Buffer containing the INF file contents.
2446 InfFileSize Size of the contents of the InfFileImage buffer.
2447 FvImage Pointer to the FV image created.
2448 FvImageSize Size of the FV image created and pointed to by FvImage.
2449 FvFileName Requested name for the FV file.
2450 SymImage Pointer to the Sym image created.
2451 SymImageSize Size of the Sym image created and pointed to by SymImage.
2452 SymFileName Requested name for the Sym file.
2453
2454 Returns:
2455
2456 EFI_SUCCESS Function completed successfully.
2457 EFI_OUT_OF_RESOURCES Could not allocate required resources.
2458 EFI_ABORTED Error encountered.
2459 EFI_INVALID_PARAMETER A required parameter was NULL.
2460
2461 --*/
2462 {
2463 EFI_STATUS Status;
2464 MEMORY_FILE InfMemoryFile;
2465 MEMORY_FILE FvImageMemoryFile;
2466 MEMORY_FILE SymImageMemoryFile;
2467 FV_INFO FvInfo;
2468 UINTN Index;
2469 EFI_FIRMWARE_VOLUME_HEADER *FvHeader;
2470 EFI_FFS_FILE_HEADER *VtfFileImage;
2471
2472 //
2473 // Check for invalid parameter
2474 //
2475 if (InfFileImage == NULL || FvImage == NULL || FvImageSize == NULL || FvFileName == NULL) {
2476 return EFI_INVALID_PARAMETER;
2477 }
2478 //
2479 // Initialize file structures
2480 //
2481 InfMemoryFile.FileImage = InfFileImage;
2482 InfMemoryFile.CurrentFilePointer = InfFileImage;
2483 InfMemoryFile.Eof = InfFileImage + InfFileSize;
2484
2485 //
2486 // Parse the FV inf file for header information
2487 //
2488 Status = ParseFvInf (&InfMemoryFile, &FvInfo);
2489 if (EFI_ERROR (Status)) {
2490 printf ("ERROR: Could not parse the input INF file.\n");
2491 return EFI_ABORTED;
2492 }
2493 //
2494 // Update the file name return values
2495 //
2496 strcpy (*FvFileName, FvInfo.FvName);
2497 strcpy (*SymFileName, FvInfo.SymName);
2498
2499 //
2500 // Calculate the FV size
2501 //
2502 *FvImageSize = FvInfo.Size;
2503
2504 //
2505 // Allocate the FV
2506 //
2507 *FvImage = malloc (*FvImageSize);
2508 if (*FvImage == NULL) {
2509 return EFI_OUT_OF_RESOURCES;
2510 }
2511 //
2512 // Allocate space for symbol file storage
2513 //
2514 *SymImage = malloc (SYMBOL_FILE_SIZE);
2515 if (*SymImage == NULL) {
2516 return EFI_OUT_OF_RESOURCES;
2517 }
2518 //
2519 // Initialize the FV to the erase polarity
2520 //
2521 if (FvInfo.FvAttributes & EFI_FVB_ERASE_POLARITY) {
2522 memset (*FvImage, -1, *FvImageSize);
2523 } else {
2524 memset (*FvImage, 0, *FvImageSize);
2525 }
2526 //
2527 // Initialize FV header
2528 //
2529 FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) *FvImage;
2530
2531 //
2532 // Initialize the zero vector to all zeros.
2533 //
2534 memset (FvHeader->ZeroVector, 0, 16);
2535
2536 //
2537 // Copy the FFS GUID
2538 //
2539 memcpy (&FvHeader->FileSystemGuid, &FvInfo.FvGuid, sizeof (EFI_GUID));
2540
2541 FvHeader->FvLength = *FvImageSize;
2542 FvHeader->Signature = EFI_FVH_SIGNATURE;
2543 FvHeader->Attributes = FvInfo.FvAttributes;
2544 FvHeader->Revision = EFI_FVH_REVISION;
2545 FvHeader->Reserved[0] = 0;
2546 FvHeader->Reserved[1] = 0;
2547 FvHeader->Reserved[2] = 0;
2548
2549 //
2550 // Copy firmware block map
2551 //
2552 for (Index = 0; FvInfo.FvBlocks[Index].NumBlocks != 0; Index++) {
2553 FvHeader->FvBlockMap[Index].NumBlocks = FvInfo.FvBlocks[Index].NumBlocks;
2554 FvHeader->FvBlockMap[Index].BlockLength = FvInfo.FvBlocks[Index].BlockLength;
2555 }
2556 //
2557 // Add block map terminator
2558 //
2559 FvHeader->FvBlockMap[Index].NumBlocks = 0;
2560 FvHeader->FvBlockMap[Index].BlockLength = 0;
2561
2562 //
2563 // Complete the header
2564 //
2565 FvHeader->HeaderLength = (UINT16) (((UINTN) &(FvHeader->FvBlockMap[Index + 1])) - (UINTN) *FvImage);
2566 FvHeader->Checksum = 0;
2567 FvHeader->Checksum = CalculateChecksum16 ((UINT16 *) FvHeader, FvHeader->HeaderLength / sizeof (UINT16));
2568
2569 //
2570 // If there is no FFS file, find and generate each components of the FV
2571 //
2572 if (FvInfo.FvFiles[0][0] == 0) {
2573 Status = GenNonFFSFv (*FvImage, &FvInfo);
2574 if (EFI_ERROR (Status)) {
2575 printf ("ERROR: Could not generate NonFFS FV.\n");
2576 free (*FvImage);
2577 return EFI_ABORTED;
2578 }
2579
2580 return EFI_SUCCESS;
2581 }
2582 //
2583 // Initialize our "file" view of the buffer
2584 //
2585 FvImageMemoryFile.FileImage = *FvImage;
2586 FvImageMemoryFile.CurrentFilePointer = *FvImage + FvHeader->HeaderLength;
2587 FvImageMemoryFile.Eof = *FvImage +*FvImageSize;
2588
2589 //
2590 // Initialize our "file" view of the symbol file.
2591 //
2592 SymImageMemoryFile.FileImage = *SymImage;
2593 SymImageMemoryFile.CurrentFilePointer = *SymImage;
2594 SymImageMemoryFile.Eof = *FvImage + SYMBOL_FILE_SIZE;
2595
2596 //
2597 // Initialize the FV library.
2598 //
2599 InitializeFvLib (FvImageMemoryFile.FileImage, FvInfo.Size);
2600
2601 //
2602 // Files start on 8 byte alignments, so move to the next 8 byte aligned
2603 // address. For now, just assert if it isn't. Currently FV header is
2604 // always a multiple of 8 bytes.
2605 // BUGBUG: Handle this better
2606 //
2607 assert ((((UINTN) FvImageMemoryFile.CurrentFilePointer) % 8) == 0);
2608
2609 //
2610 // Initialize the VTF file address.
2611 //
2612 VtfFileImage = (EFI_FFS_FILE_HEADER *) FvImageMemoryFile.Eof;
2613
2614 //
2615 // Add files to FV
2616 //
2617 for (Index = 0; FvInfo.FvFiles[Index][0] != 0; Index++) {
2618 //
2619 // Add the file
2620 //
2621 Status = AddFile (&FvImageMemoryFile, &FvInfo, Index, &VtfFileImage, &SymImageMemoryFile);
2622
2623 //
2624 // Exit if error detected while adding the file
2625 //
2626 if (EFI_ERROR (Status)) {
2627 printf ("ERROR: Could not add file %s.\n", FvInfo.FvFiles[Index]);
2628 free (*FvImage);
2629 return EFI_ABORTED;
2630 }
2631 }
2632 //
2633 // If there is a VTF file, some special actions need to occur.
2634 //
2635 if ((UINTN) VtfFileImage != (UINTN) FvImageMemoryFile.Eof) {
2636 //
2637 // Pad from the end of the last file to the beginning of the VTF file.
2638 //
2639 Status = PadFvImage (&FvImageMemoryFile, VtfFileImage);
2640 if (EFI_ERROR (Status)) {
2641 printf ("ERROR: Could not create the pad file between the last file and the VTF file.\n");
2642 free (*FvImage);
2643 return EFI_ABORTED;
2644 }
2645 //
2646 // Update reset vector (SALE_ENTRY for IPF)
2647 // Now for IA32 and IA64 platform, the fv which has bsf file must have the
2648 // EndAddress of 0xFFFFFFFF. Thus, only this type fv needs to update the
2649 // reset vector. If the PEI Core is found, the VTF file will probably get
2650 // corrupted by updating the entry point.
2651 //
2652 if ((FvInfo.BaseAddress + FvInfo.Size) == FV_IMAGES_TOP_ADDRESS) {
2653 Status = UpdateResetVector (&FvImageMemoryFile, &FvInfo, VtfFileImage);
2654 if (EFI_ERROR(Status)) {
2655 printf ("ERROR: Could not update the reset vector.\n");
2656 free (*FvImage);
2657 return EFI_ABORTED;
2658 }
2659 }
2660 }
2661 //
2662 // Determine final Sym file size
2663 //
2664 *SymImageSize = SymImageMemoryFile.CurrentFilePointer - SymImageMemoryFile.FileImage;
2665
2666 //
2667 // Update FV Alignment attribute to the largest alignment of all the FFS files in the FV
2668 //
2669 if (FvHeader->Attributes | EFI_FVB_ALIGNMENT_CAP) {
2670 for (Index = 1; Index <= 16; Index ++) {
2671 if ((1 << Index) < MaxFfsAlignment) {
2672 //
2673 // Unset the unsupported alignment attribute.
2674 //
2675 FvHeader->Attributes = FvHeader->Attributes & ~((1 << Index) * EFI_FVB_ALIGNMENT_CAP);
2676 } else {
2677 //
2678 // Set the supported alignment attribute.
2679 //
2680 FvHeader->Attributes = FvHeader->Attributes | ((1 << Index) * EFI_FVB_ALIGNMENT_CAP);
2681 }
2682 }
2683
2684 //
2685 // Update Checksum for FvHeader
2686 //
2687 FvHeader->Checksum = 0;
2688 FvHeader->Checksum = CalculateChecksum16 ((UINT16 *) FvHeader, FvHeader->HeaderLength / sizeof (UINT16));
2689 }
2690
2691 return EFI_SUCCESS;
2692 }
2693
2694 EFI_STATUS
2695 UpdatePeiCoreEntryInFit (
2696 IN FIT_TABLE *FitTablePtr,
2697 IN UINT64 PeiCorePhysicalAddress
2698 )
2699 /*++
2700
2701 Routine Description:
2702
2703 This function is used to update the Pei Core address in FIT, this can be used by Sec core to pass control from
2704 Sec to Pei Core
2705
2706 Arguments:
2707
2708 FitTablePtr - The pointer of FIT_TABLE.
2709 PeiCorePhysicalAddress - The address of Pei Core entry.
2710
2711 Returns:
2712
2713 EFI_SUCCESS - The PEI_CORE FIT entry was updated successfully.
2714 EFI_NOT_FOUND - Not found the PEI_CORE FIT entry.
2715
2716 --*/
2717 {
2718 FIT_TABLE *TmpFitPtr;
2719 UINTN Index;
2720 UINTN NumFitComponents;
2721
2722 TmpFitPtr = FitTablePtr;
2723 NumFitComponents = TmpFitPtr->CompSize;
2724
2725 for (Index = 0; Index < NumFitComponents; Index++) {
2726 if ((TmpFitPtr->CvAndType & FIT_TYPE_MASK) == COMP_TYPE_FIT_PEICORE) {
2727 TmpFitPtr->CompAddress = PeiCorePhysicalAddress;
2728 return EFI_SUCCESS;
2729 }
2730
2731 TmpFitPtr++;
2732 }
2733
2734 return EFI_NOT_FOUND;
2735 }
2736
2737 VOID
2738 UpdateFitCheckSum (
2739 IN FIT_TABLE *FitTablePtr
2740 )
2741 /*++
2742
2743 Routine Description:
2744
2745 This function is used to update the checksum for FIT.
2746
2747
2748 Arguments:
2749
2750 FitTablePtr - The pointer of FIT_TABLE.
2751
2752 Returns:
2753
2754 None.
2755
2756 --*/
2757 {
2758 if ((FitTablePtr->CvAndType & CHECKSUM_BIT_MASK) >> 7) {
2759 FitTablePtr->CheckSum = 0;
2760 FitTablePtr->CheckSum = CalculateChecksum8 ((UINT8 *) FitTablePtr, FitTablePtr->CompSize * 16);
2761 }
2762 }