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