]> git.proxmox.com Git - mirror_edk2.git/blob - Tools/Source/TianoTools/GenFvImage/GenFvImageLib.c
c4515001d8820c9136f422616d316d3e787548e7
[mirror_edk2.git] / Tools / Source / TianoTools / 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 #define EFI_SPECIFICATION_VERSION 0x00020000
27 #define EDK_RELEASE_VERSION 0x00020000
28 #ifdef __GNUC__
29 #include <uuid/uuid.h>
30 #include <sys/stat.h>
31 #endif
32 #include <string.h>
33 #ifndef __GNUC__
34 #include <io.h>
35 #endif
36 #include <assert.h>
37 #include <Dxe.h>
38 #include <Library/PeCoffLib.h>
39 #include "GenFvImageLib.h"
40 #include "GenFvImageLibInternal.h"
41 #include <CommonLib.h>
42 #include <FirmwareVolumeImageFormat.h>
43 #include <Crc32.h>
44 #include <EfiUtilityMsgs.h>
45 #include <FvLib.h>
46 #include <EfiCompress.h>
47 #include <Variable.h>
48 #include <WinNtInclude.h>
49 #include <WorkingBlockHeader.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 EFI_STATUS
1310 RebaseFfsFile (
1311 IN OUT EFI_FFS_FILE_HEADER *FfsFile,
1312 IN EFI_PHYSICAL_ADDRESS BaseAddress
1313 )
1314 /*++
1315
1316 Routine Description:
1317
1318 This function determines if a file is XIP and should be rebased. It will
1319 rebase any PE32 sections found in the file using the base address.
1320
1321 Arguments:
1322
1323 FfsFile A pointer to Ffs file image.
1324 BaseAddress The base address to use for rebasing the file image.
1325
1326 Returns:
1327
1328 EFI_SUCCESS The image was properly rebased.
1329 EFI_INVALID_PARAMETER An input parameter is invalid.
1330 EFI_ABORTED An error occurred while rebasing the input file image.
1331 EFI_OUT_OF_RESOURCES Could not allocate a required resource.
1332
1333 --*/
1334 {
1335 EFI_STATUS Status;
1336 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;
1337 UINTN MemoryImagePointer;
1338 UINTN MemoryImagePointerAligned;
1339
1340 EFI_PHYSICAL_ADDRESS ImageAddress;
1341 UINT64 ImageSize;
1342 EFI_PHYSICAL_ADDRESS EntryPoint;
1343
1344 UINT32 Pe32FileSize;
1345 UINT32 NewPe32BaseAddress;
1346
1347 UINTN Index;
1348 EFI_FILE_SECTION_POINTER CurrentPe32Section;
1349 UINT8 FileGuidString[80];
1350
1351 //
1352 // Verify input parameters
1353 //
1354 if (FfsFile == NULL) {
1355 return EFI_INVALID_PARAMETER;
1356 }
1357 //
1358 // Convert the GUID to a string so we can at least report which file
1359 // if we find an error.
1360 //
1361 PrintGuidToBuffer (&FfsFile->Name, FileGuidString, sizeof (FileGuidString), TRUE);
1362
1363 //
1364 // Do some nominal checks on the file, then check for XIP.
1365 //
1366 Status = VerifyFfsFile (FfsFile);
1367 if (EFI_ERROR (Status)) {
1368 Error (NULL, 0, 0, "invalid FFS file", FileGuidString);
1369 return EFI_INVALID_PARAMETER;
1370 }
1371
1372 if (FfsFile->Type != EFI_FV_FILETYPE_SECURITY_CORE &&
1373 FfsFile->Type != EFI_FV_FILETYPE_PEI_CORE &&
1374 FfsFile->Type != EFI_FV_FILETYPE_PEIM
1375 ) {
1376 //
1377 // File is not XIP, so don't rebase
1378 //
1379 return EFI_SUCCESS;
1380 }
1381 //
1382 // Rebase each PE32 section
1383 //
1384 for (Index = 1;; Index++) {
1385 Status = GetSectionByType (FfsFile, EFI_SECTION_PE32, Index, &CurrentPe32Section);
1386 if (EFI_ERROR (Status)) {
1387 break;
1388 }
1389 //
1390 // Calculate the PE32 base address, the FFS file base plus the offset of the PE32 section
1391 //
1392 NewPe32BaseAddress = ((UINT32) BaseAddress) + ((UINTN) CurrentPe32Section.Pe32Section - (UINTN) FfsFile);
1393
1394 //
1395 // Initialize context
1396 //
1397 memset (&ImageContext, 0, sizeof (ImageContext));
1398 ImageContext.Handle = (VOID *) ((UINTN) CurrentPe32Section.Pe32Section + sizeof (EFI_PE32_SECTION));
1399 ImageContext.ImageRead = (PE_COFF_LOADER_READ_FILE) FfsRebaseImageRead;
1400
1401 Status = PeCoffLoaderGetImageInfo (&ImageContext);
1402
1403 if (EFI_ERROR (Status)) {
1404 Error (NULL, 0, 0, "GetImageInfo() failed", FileGuidString);
1405 return Status;
1406 }
1407 //
1408 // Allocate a buffer for the image to be loaded into.
1409 //
1410 Pe32FileSize = GetLength (CurrentPe32Section.Pe32Section->CommonHeader.Size);
1411 MemoryImagePointer = (UINTN) (malloc (Pe32FileSize + 0x1000));
1412 MemoryImagePointerAligned = (MemoryImagePointer + 0x0FFF) & (-1 << 12);
1413 if (MemoryImagePointerAligned == 0) {
1414 Error (NULL, 0, 0, "memory allocation failure", NULL);
1415 return EFI_OUT_OF_RESOURCES;
1416 }
1417
1418 //
1419 // bugbug
1420 //
1421 ImageContext.ImageAddress = MemoryImagePointerAligned;
1422 Status = PeCoffLoaderLoadImage (&ImageContext);
1423 if (EFI_ERROR (Status)) {
1424 Error (NULL, 0, 0, "LoadImage() failure", FileGuidString);
1425 free ((VOID *) MemoryImagePointer);
1426 return Status;
1427 }
1428
1429 Status = PeCoffLoaderRelocateImage (&ImageContext);
1430 if (EFI_ERROR (Status)) {
1431 Error (NULL, 0, 0, "RelocateImage() failure", FileGuidString);
1432 free ((VOID *) MemoryImagePointer);
1433 return Status;
1434 }
1435
1436 ImageAddress = ImageContext.ImageAddress;
1437 ImageSize = ImageContext.ImageSize;
1438 EntryPoint = ImageContext.EntryPoint;
1439
1440 if (ImageSize > Pe32FileSize) {
1441 Error (
1442 NULL,
1443 0,
1444 0,
1445 "rebased PE32 is larger than original PE32 image",
1446 "0x%X > 0x%X on file %s",
1447 ImageSize,
1448 Pe32FileSize,
1449 FileGuidString
1450 );
1451 free ((VOID *) MemoryImagePointer);
1452 return EFI_ABORTED;
1453 }
1454
1455 memcpy (CurrentPe32Section.Pe32Section, (VOID *) MemoryImagePointerAligned, Pe32FileSize);
1456
1457 free ((VOID *) MemoryImagePointer);
1458 }
1459 //
1460 // the above for loop will always exit with EFI_NOT_FOUND if it completes
1461 // normally. If Index == 1 at exit, then no PE32 sections were found. If it
1462 // exits with any other error code, then something broke...
1463 //
1464 if (Status != EFI_NOT_FOUND) {
1465 Error (NULL, 0, 0, "failed to parse PE32 section", FileGuidString);
1466 return Status;
1467 }
1468
1469 return EFI_SUCCESS;
1470 }
1471
1472 EFI_STATUS
1473 AddSymFile (
1474 IN UINT64 BaseAddress,
1475 IN EFI_FFS_FILE_HEADER *FfsFile,
1476 IN OUT MEMORY_FILE *SymImage,
1477 IN CHAR8 *SourceFileName
1478 )
1479 /*++
1480
1481 Routine Description:
1482
1483 This function adds the SYM tokens in the source file to the destination file.
1484 The SYM tokens are updated to reflect the base address.
1485
1486 Arguments:
1487
1488 BaseAddress The base address for the new SYM tokens.
1489 FfsFile Pointer to the beginning of the FFS file in question.
1490 SymImage The memory file to update with symbol information.
1491 SourceFileName The source file.
1492
1493 Returns:
1494
1495 EFI_SUCCESS The function completed successfully.
1496 EFI_INVALID_PARAMETER One of the input parameters was invalid.
1497 EFI_ABORTED An error occurred.
1498
1499 --*/
1500 {
1501 FILE *SourceFile;
1502
1503 CHAR8 Buffer[_MAX_PATH];
1504 CHAR8 Type[_MAX_PATH];
1505 CHAR8 Address[_MAX_PATH];
1506 CHAR8 Section[_MAX_PATH];
1507 CHAR8 Token[_MAX_PATH];
1508 CHAR8 SymFileName[_MAX_PATH];
1509 CHAR8 CodeModuleName[_MAX_PATH];
1510 CHAR8 *Ptr;
1511
1512 UINT64 TokenAddress;
1513
1514 EFI_STATUS Status;
1515 EFI_FILE_SECTION_POINTER Pe32Section;
1516 UINT32 EntryPoint;
1517 UINT32 BaseOfCode;
1518 UINT16 MachineType;
1519 EFI_TE_IMAGE_HEADER *TeHdr;
1520
1521 TeHdr = NULL;
1522 //
1523 // Verify input parameters.
1524 //
1525 if (BaseAddress == 0 || FfsFile == NULL || SymImage == NULL || SourceFileName == NULL) {
1526 Error (NULL, 0, 0, "invalid parameter passed to AddSymFile()", NULL);
1527 return EFI_INVALID_PARAMETER;
1528 }
1529 //
1530 // Check if we want to add this file
1531 //
1532 //
1533 // Get the file name
1534 //
1535 strcpy (Buffer, SourceFileName);
1536
1537 //
1538 // Copy the file name for the path of the sym file and truncate the name portion.
1539 //
1540 strcpy (SymFileName, Buffer);
1541 Ptr = strrchr (SymFileName, '\\');
1542 assert (Ptr);
1543 Ptr[0] = 0;
1544
1545 //
1546 // Find the file extension and make it lower case
1547 //
1548 Ptr = strrchr (SymFileName, '.');
1549 if (Ptr != NULL) {
1550 strlwr (Ptr);
1551 }
1552 //
1553 // Check if it is PEI file
1554 //
1555 if (strstr (Buffer, ".pei") != NULL) {
1556 //
1557 // Find the human readable portion
1558 //
1559 if (!strtok (Buffer, "-") ||
1560 !strtok (NULL, "-") ||
1561 !strtok (NULL, "-") ||
1562 !strtok (NULL, "-") ||
1563 !strtok (NULL, "-") ||
1564 !strcpy (Buffer, strtok (NULL, "."))
1565 ) {
1566 Error (NULL, 0, 0, "failed to find human readable portion of the file name in AddSymFile()", NULL);
1567 return EFI_ABORTED;
1568 }
1569 //
1570 // Save code module name
1571 //
1572 strcpy (CodeModuleName, Buffer);
1573
1574 //
1575 // Add the symbol file name and extension to the file path.
1576 //
1577 strcat (Buffer, ".sym");
1578 strcat (SymFileName, "\\");
1579 strcat (SymFileName, Buffer);
1580 } else {
1581 //
1582 // Only handle PEIM files.
1583 //
1584 return EFI_SUCCESS;
1585 }
1586 //
1587 // Find PE32 section
1588 //
1589 Status = GetSectionByType (FfsFile, EFI_SECTION_PE32, 1, &Pe32Section);
1590
1591 //
1592 // BUGBUG: Assume if no PE32 section it is PIC and hardcode base address
1593 //
1594 if (Status == EFI_NOT_FOUND) {
1595 Status = GetSectionByType (FfsFile, EFI_SECTION_TE, 1, &Pe32Section);
1596 if (Status == EFI_NOT_FOUND) {
1597 BaseOfCode = 0x60;
1598 } else {
1599 TeHdr = (EFI_TE_IMAGE_HEADER *) ((UINTN) Pe32Section.Pe32Section + sizeof (EFI_COMMON_SECTION_HEADER));
1600 BaseOfCode = TeHdr->BaseOfCode - TeHdr->StrippedSize;
1601 }
1602 } else if (EFI_ERROR (Status)) {
1603 Error (NULL, 0, 0, "could not parse a PE32 section from the PEI file", NULL);
1604 return Status;
1605 } else {
1606 Status = GetPe32Info (
1607 (VOID *) ((UINTN) Pe32Section.Pe32Section + sizeof (EFI_SECTION_PE32)),
1608 &EntryPoint,
1609 &BaseOfCode,
1610 &MachineType
1611 );
1612 if (EFI_ERROR (Status)) {
1613 Error (NULL, 0, 0, "GetPe32Info() could not get PE32 entry point for PEI file", NULL);
1614 return Status;
1615 }
1616 }
1617 //
1618 // Open the source file
1619 //
1620 SourceFile = fopen (SymFileName, "r");
1621 if (SourceFile == NULL) {
1622 //
1623 // SYM files are not required.
1624 //
1625 return EFI_SUCCESS;
1626 }
1627 //
1628 // Read the first line
1629 //
1630 if (fgets (Buffer, _MAX_PATH, SourceFile) == NULL) {
1631 Buffer[0] = 0;
1632 }
1633 //
1634 // Make sure it matches the expected sym format
1635 //
1636 if (strcmp (Buffer, "TEXTSYM format | V1.0\n")) {
1637 fclose (SourceFile);
1638 Error (NULL, 0, 0, "AddSymFile() found unexpected sym format in input file", NULL);
1639 return EFI_ABORTED;
1640 }
1641 //
1642 // Read in the file
1643 //
1644 while (feof (SourceFile) == 0) {
1645 //
1646 // Read a line
1647 //
1648 if (fscanf (
1649 SourceFile,
1650 "%s | %s | %s | %s\n",
1651 Type,
1652 Address,
1653 Section,
1654 Token
1655 ) == 4) {
1656 //
1657 // If the token starts with "??" ignore it
1658 //
1659 if (Token[0] == '?' && Token[1] == '?') {
1660 continue;
1661 }
1662 //
1663 // Get the token address
1664 //
1665 AsciiStringToUint64 (Address, TRUE, &TokenAddress);
1666
1667 //
1668 // Add the base address
1669 //
1670 TokenAddress += BaseAddress;
1671
1672 //
1673 // If PE32 then find the start of code. For PIC it is hardcoded.
1674 //
1675 if (TeHdr == NULL && Pe32Section.Pe32Section) {
1676 //
1677 // Add the offset of the PE32 section
1678 //
1679 TokenAddress += (UINTN) Pe32Section.Pe32Section - (UINTN) FfsFile;
1680
1681 //
1682 // Add the size of the PE32 section header
1683 //
1684 TokenAddress += sizeof (EFI_PE32_SECTION);
1685 } else if (TeHdr != NULL) {
1686 //
1687 // Add the Te section and FfsHeader
1688 //
1689 //
1690 // BUGBUG: Don't know why this is 0x28 bytes.
1691 //
1692 TokenAddress += (UINTN) TeHdr - (UINTN) FfsFile + 0x28;
1693 } else {
1694 //
1695 // BUGBUG: Don't know why this is 0x28 bytes.
1696 //
1697 TokenAddress += 0x28;
1698 }
1699 //
1700 // Add the beginning of the code
1701 //
1702 TokenAddress += BaseOfCode;
1703
1704 sprintf (
1705 Buffer,
1706 "%s | %016I64X | %s | _%s%s\n",
1707 Type,
1708 TokenAddress,
1709 Section,
1710 CodeModuleName,
1711 Token
1712 );
1713 memcpy (SymImage->CurrentFilePointer, Buffer, strlen (Buffer) + 1);
1714 SymImage->CurrentFilePointer = (UINT8 *) (((UINTN) SymImage->CurrentFilePointer) + strlen (Buffer) + 1);
1715 }
1716 }
1717
1718 fclose (SourceFile);
1719 return EFI_SUCCESS;
1720 }
1721
1722 EFI_STATUS
1723 AddFile (
1724 IN OUT MEMORY_FILE *FvImage,
1725 IN FV_INFO *FvInfo,
1726 IN UINTN Index,
1727 IN OUT EFI_FFS_FILE_HEADER **VtfFileImage,
1728 IN OUT MEMORY_FILE *SymImage
1729 )
1730 /*++
1731
1732 Routine Description:
1733
1734 This function adds a file to the FV image. The file will pad to the
1735 appropriate alignment if required.
1736
1737 Arguments:
1738
1739 FvImage The memory image of the FV to add it to. The current offset
1740 must be valid.
1741 FvInfo Pointer to information about the FV.
1742 Index The file in the FvInfo file list to add.
1743 VtfFileImage A pointer to the VTF file within the FvImage. If this is equal
1744 to the end of the FvImage then no VTF previously found.
1745 SymImage The memory image of the Sym file to update if symbols are present.
1746 The current offset must be valid.
1747
1748 Returns:
1749
1750 EFI_SUCCESS The function completed successfully.
1751 EFI_INVALID_PARAMETER One of the input parameters was invalid.
1752 EFI_ABORTED An error occurred.
1753 EFI_OUT_OF_RESOURCES Insufficient resources exist to complete the add.
1754
1755 --*/
1756 {
1757 FILE *NewFile;
1758 UINTN FileSize;
1759 UINT8 *FileBuffer;
1760 UINTN NumBytesRead;
1761 UINT32 CurrentFileAlignment;
1762 EFI_STATUS Status;
1763 EFI_PHYSICAL_ADDRESS CurrentFileBaseAddress;
1764 UINT8 VtfHeaderChecksum;
1765 UINT8 VtfFileChecksum;
1766 UINT8 FileState;
1767 EFI_FFS_FILE_TAIL TailValue;
1768 UINT32 TailSize;
1769 //
1770 // Verify input parameters.
1771 //
1772 if (FvImage == NULL || FvInfo == NULL || FvInfo->FvFiles[Index][0] == 0 || VtfFileImage == NULL || SymImage == NULL) {
1773 return EFI_INVALID_PARAMETER;
1774 }
1775 //
1776 // Read the file to add
1777 //
1778 NewFile = fopen (FvInfo->FvFiles[Index], "rb");
1779
1780 if (NewFile == NULL) {
1781 Error (NULL, 0, 0, FvInfo->FvFiles[Index], "failed to open file for reading");
1782 return EFI_ABORTED;
1783 }
1784 //
1785 // Get the file size
1786 //
1787 #ifdef __GNUC__
1788 {
1789 struct stat stat_buf;
1790 fstat(fileno(NewFile), &stat_buf);
1791 FileSize = stat_buf.st_size;
1792 }
1793 #else
1794 FileSize = _filelength (fileno (NewFile));
1795 #endif
1796
1797 //
1798 // Read the file into a buffer
1799 //
1800 FileBuffer = malloc (FileSize);
1801 if (FileBuffer == NULL) {
1802 Error (NULL, 0, 0, "memory allocation failure", NULL);
1803 return EFI_OUT_OF_RESOURCES;
1804 }
1805
1806 NumBytesRead = fread (FileBuffer, sizeof (UINT8), FileSize, NewFile);
1807
1808 //
1809 // Done with the file, from this point on we will just use the buffer read.
1810 //
1811 fclose (NewFile);
1812
1813 //
1814 // Verify read successful
1815 //
1816 if (NumBytesRead != sizeof (UINT8) * FileSize) {
1817 free (FileBuffer);
1818 Error (NULL, 0, 0, FvInfo->FvFiles[Index], "failed to read input file contents");
1819 return EFI_ABORTED;
1820 }
1821 //
1822 // Verify space exists to add the file
1823 //
1824 if (FileSize > (UINTN) ((UINTN) *VtfFileImage - (UINTN) FvImage->CurrentFilePointer)) {
1825 Error (NULL, 0, 0, FvInfo->FvFiles[Index], "insufficient space remains to add the file");
1826 return EFI_OUT_OF_RESOURCES;
1827 }
1828 //
1829 // Update the file state based on polarity of the FV.
1830 //
1831 UpdateFfsFileState (
1832 (EFI_FFS_FILE_HEADER *) FileBuffer,
1833 (EFI_FIRMWARE_VOLUME_HEADER *) FvImage->FileImage
1834 );
1835
1836 //
1837 // If we have a VTF file, add it at the top.
1838 //
1839 if (IsVtfFile ((EFI_FFS_FILE_HEADER *) FileBuffer)) {
1840 if ((UINTN) *VtfFileImage == (UINTN) FvImage->Eof) {
1841 //
1842 // No previous VTF, add this one.
1843 //
1844 *VtfFileImage = (EFI_FFS_FILE_HEADER *) (UINTN) ((UINTN) FvImage->FileImage + FvInfo->Size - FileSize);
1845 //
1846 // Sanity check. The file MUST align appropriately
1847 //
1848 if ((((UINTN) *VtfFileImage) & 0x07) != 0) {
1849 Error (NULL, 0, 0, "VTF file does not align on 8-byte boundary", NULL);
1850 }
1851 //
1852 // copy VTF File Header
1853 //
1854 memcpy (*VtfFileImage, FileBuffer, sizeof (EFI_FFS_FILE_HEADER));
1855
1856 //
1857 // Copy VTF body
1858 //
1859 memcpy (
1860 (UINT8 *) *VtfFileImage + sizeof (EFI_FFS_FILE_HEADER),
1861 FileBuffer + sizeof (EFI_FFS_FILE_HEADER),
1862 FileSize - sizeof (EFI_FFS_FILE_HEADER)
1863 );
1864
1865 //
1866 // re-calculate the VTF File Header
1867 //
1868 FileState = (*VtfFileImage)->State;
1869 (*VtfFileImage)->State = 0;
1870 *(UINT32 *) ((*VtfFileImage)->Size) = FileSize;
1871 (*VtfFileImage)->IntegrityCheck.Checksum.Header = 0;
1872 (*VtfFileImage)->IntegrityCheck.Checksum.File = 0;
1873
1874 VtfHeaderChecksum = CalculateChecksum8 ((UINT8 *) *VtfFileImage, sizeof (EFI_FFS_FILE_HEADER));
1875 (*VtfFileImage)->IntegrityCheck.Checksum.Header = VtfHeaderChecksum;
1876 //
1877 // Determine if it has a tail
1878 //
1879 if ((*VtfFileImage)->Attributes & FFS_ATTRIB_TAIL_PRESENT) {
1880 TailSize = sizeof (EFI_FFS_FILE_TAIL);
1881 } else {
1882 TailSize = 0;
1883 }
1884
1885 if ((*VtfFileImage)->Attributes & FFS_ATTRIB_CHECKSUM) {
1886 VtfFileChecksum = CalculateChecksum8 ((UINT8 *) *VtfFileImage, FileSize - TailSize);
1887 (*VtfFileImage)->IntegrityCheck.Checksum.File = VtfFileChecksum;
1888 } else {
1889 (*VtfFileImage)->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM;
1890 }
1891 //
1892 // If it has a file tail, update it
1893 //
1894 if ((*VtfFileImage)->Attributes & FFS_ATTRIB_TAIL_PRESENT) {
1895 TailValue = (EFI_FFS_FILE_TAIL) (~((*VtfFileImage)->IntegrityCheck.TailReference));
1896 *(EFI_FFS_FILE_TAIL *) (((UINTN) (*VtfFileImage) + GetLength ((*VtfFileImage)->Size) - sizeof (EFI_FFS_FILE_TAIL))) = TailValue;
1897 }
1898 (*VtfFileImage)->State = FileState;
1899 free (FileBuffer);
1900 return EFI_SUCCESS;
1901 } else {
1902 //
1903 // Already found a VTF file.
1904 //
1905 Error (NULL, 0, 0, "multiple VTF files are illegal in a single FV", NULL);
1906 free (FileBuffer);
1907 return EFI_ABORTED;
1908 }
1909 }
1910 //
1911 // Check if alignment is required
1912 //
1913 Status = ReadFfsAlignment ((EFI_FFS_FILE_HEADER *) FileBuffer, &CurrentFileAlignment);
1914 if (EFI_ERROR (Status)) {
1915 printf ("ERROR: Could not determine alignment of file %s.\n", FvInfo->FvFiles[Index]);
1916 free (FileBuffer);
1917 return EFI_ABORTED;
1918 }
1919 //
1920 // Add pad file if necessary
1921 //
1922 Status = AddPadFile (FvImage, CurrentFileAlignment);
1923 if (EFI_ERROR (Status)) {
1924 printf ("ERROR: Could not align the file data properly.\n");
1925 free (FileBuffer);
1926 return EFI_ABORTED;
1927 }
1928 //
1929 // Add file
1930 //
1931 if ((FvImage->CurrentFilePointer + FileSize) < FvImage->Eof) {
1932 //
1933 // Copy the file
1934 //
1935 memcpy (FvImage->CurrentFilePointer, FileBuffer, FileSize);
1936
1937 //
1938 // If the file is XIP, rebase
1939 //
1940 CurrentFileBaseAddress = FvInfo->BaseAddress + ((UINTN) FvImage->CurrentFilePointer - (UINTN) FvImage->FileImage);
1941 //
1942 // Status = RebaseFfsFile ((EFI_FFS_FILE_HEADER*) FvImage->CurrentFilePointer, CurrentFileBaseAddress);
1943 // if (EFI_ERROR(Status)) {
1944 // printf ("ERROR: Could not rebase the file %s.\n", FvInfo->FvFiles[Index]);
1945 // return EFI_ABORTED;
1946 // }
1947 //
1948 // Update Symbol file
1949 //
1950 Status = AddSymFile (
1951 CurrentFileBaseAddress,
1952 (EFI_FFS_FILE_HEADER *) FvImage->CurrentFilePointer,
1953 SymImage,
1954 FvInfo->FvFiles[Index]
1955 );
1956 assert (!EFI_ERROR (Status));
1957
1958 //
1959 // Update the current pointer in the FV image
1960 //
1961 FvImage->CurrentFilePointer += FileSize;
1962 } else {
1963 printf ("ERROR: The firmware volume is out of space, could not add file %s.\n", FvInfo->FvFiles[Index]);
1964 return EFI_ABORTED;
1965 }
1966 //
1967 // Make next file start at QWord Boundry
1968 //
1969 while (((UINTN) FvImage->CurrentFilePointer & 0x07) != 0) {
1970 FvImage->CurrentFilePointer++;
1971 }
1972 //
1973 // Free allocated memory.
1974 //
1975 free (FileBuffer);
1976
1977 return EFI_SUCCESS;
1978 }
1979
1980 EFI_STATUS
1981 AddVariableBlock (
1982 IN UINT8 *FvImage,
1983 IN UINTN Size,
1984 IN FV_INFO *FvInfo
1985 )
1986 {
1987 EFI_FIRMWARE_VOLUME_HEADER *FvHeader;
1988 VARIABLE_STORE_HEADER *VarStoreHeader;
1989 //
1990 // Variable block should exclude FvHeader. Since the length of
1991 // FvHeader depends on the block map, which is variable length,
1992 // we could only decide the actual variable block length here.
1993 //
1994 FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) FvImage;
1995 FvImage = FvImage + FvHeader->HeaderLength;
1996
1997 VarStoreHeader = (VARIABLE_STORE_HEADER *) FvImage;
1998
1999 VarStoreHeader->Signature = VARIABLE_STORE_SIGNATURE;
2000 VarStoreHeader->Size = Size - FvHeader->HeaderLength;
2001 VarStoreHeader->Format = VARIABLE_STORE_FORMATTED;
2002 VarStoreHeader->State = VARIABLE_STORE_HEALTHY;
2003 VarStoreHeader->Reserved = 0;
2004 VarStoreHeader->Reserved1 = 0;
2005
2006 return EFI_SUCCESS;
2007 }
2008
2009 EFI_STATUS
2010 AddEventLogBlock (
2011 IN UINT8 *FvImage,
2012 IN UINTN Size,
2013 IN FV_INFO *FvInfo
2014 )
2015 {
2016 return EFI_SUCCESS;
2017 }
2018
2019 EFI_STATUS
2020 AddFTWWorkingBlock (
2021 IN UINT8 *FvImage,
2022 IN UINTN Size,
2023 IN FV_INFO *FvInfo
2024 )
2025 {
2026 EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *FTWHeader;
2027 UINT32 Crc32;
2028
2029 Crc32 = 0;
2030 FTWHeader = (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *) FvImage;
2031 memcpy (&FTWHeader->Signature, &(FvInfo->FvGuid), sizeof (EFI_GUID));
2032 FTWHeader->WriteQueueSize = Size - sizeof (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER);
2033 CalculateCrc32 (FvImage, sizeof (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER), &Crc32);
2034 FTWHeader->Crc = Crc32;
2035 if (FvInfo->FvAttributes & EFI_FVB_ERASE_POLARITY) {
2036 FTWHeader->WorkingBlockValid = 0;
2037 FTWHeader->WorkingBlockInvalid = 1;
2038 } else {
2039 FTWHeader->WorkingBlockValid = 1;
2040 FTWHeader->WorkingBlockInvalid = 0;
2041 }
2042
2043 return EFI_SUCCESS;
2044 }
2045
2046 EFI_STATUS
2047 AddFTWSpareBlock (
2048 IN UINT8 *FvImage,
2049 IN UINTN Size,
2050 IN FV_INFO *FvInfo
2051 )
2052 {
2053 return EFI_SUCCESS;
2054 }
2055
2056 EFI_STATUS
2057 GenNonFFSFv (
2058 IN UINT8 *FvImage,
2059 IN FV_INFO *FvInfo
2060 )
2061 /*++
2062
2063 Routine Description:
2064
2065 This function generate the non FFS FV image, such as the working block
2066 and spare block. How each component of the FV is built is component
2067 specific.
2068
2069 Arguments:
2070
2071 FvImage The memory image of the FV to add it to. The current offset
2072 must be valid.
2073 FvInfo Pointer to information about the FV.
2074
2075 Returns:
2076
2077 EFI_SUCCESS The function completed successfully.
2078 EFI_INVALID_PARAMETER One of the input parameters was invalid.
2079 EFI_ABORTED An error occurred.
2080 EFI_OUT_OF_RESOURCES Insufficient resources exist to complete the add.
2081
2082 --*/
2083 {
2084 UINTN Index;
2085 EFI_FIRMWARE_VOLUME_HEADER *FvHeader;
2086 UINT64 TotalSize;
2087
2088 FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) FvImage;
2089 TotalSize = 0;
2090
2091 for (Index = 0; FvInfo->FvComponents[Index].Size != 0; Index++) {
2092 if (stricmp (FvInfo->FvComponents[Index].ComponentName, EFI_NV_VARIABLE_STRING) == 0) {
2093 AddVariableBlock (FvImage, FvInfo->FvComponents[Index].Size, FvInfo);
2094 } else if (stricmp (FvInfo->FvComponents[Index].ComponentName, EFI_NV_EVENT_LOG_STRING) == 0) {
2095 AddEventLogBlock (FvImage, FvInfo->FvComponents[Index].Size, FvInfo);
2096 } else if (stricmp (FvInfo->FvComponents[Index].ComponentName, EFI_NV_FTW_WORKING_STRING) == 0) {
2097 AddFTWWorkingBlock (FvImage, FvInfo->FvComponents[Index].Size, FvInfo);
2098 } else if (stricmp (FvInfo->FvComponents[Index].ComponentName, EFI_NV_FTW_SPARE_STRING) == 0) {
2099 AddFTWSpareBlock (FvImage, FvInfo->FvComponents[Index].Size, FvInfo);
2100 } else {
2101 printf ("Error. Unknown Non-FFS block %s \n", FvInfo->FvComponents[Index].ComponentName);
2102 return EFI_ABORTED;
2103 }
2104
2105 FvImage = FvImage + FvInfo->FvComponents[Index].Size;
2106 TotalSize = TotalSize + FvInfo->FvComponents[Index].Size;
2107 }
2108 //
2109 // Index and TotalSize is zero mean there's no component, so this is an empty fv
2110 //
2111 if ((Index != 0 || TotalSize != 0) && TotalSize != FvInfo->Size) {
2112 printf ("Error. Component size does not sum up to FV size.\n");
2113 return EFI_ABORTED;
2114 }
2115
2116 return EFI_SUCCESS;
2117 }
2118
2119 EFI_STATUS
2120 PadFvImage (
2121 IN MEMORY_FILE *FvImage,
2122 IN EFI_FFS_FILE_HEADER *VtfFileImage
2123 )
2124 /*++
2125
2126 Routine Description:
2127
2128 This function places a pad file between the last file in the FV and the VTF
2129 file if the VTF file exists.
2130
2131 Arguments:
2132
2133 FvImage Memory file for the FV memory image
2134 VtfFileImage The address of the VTF file. If this is the end of the FV
2135 image, no VTF exists and no pad file is needed.
2136
2137 Returns:
2138
2139 EFI_SUCCESS Completed successfully.
2140 EFI_INVALID_PARAMETER One of the input parameters was NULL.
2141
2142 --*/
2143 {
2144 EFI_FFS_FILE_HEADER *PadFile;
2145 UINTN FileSize;
2146
2147 //
2148 // If there is no VTF or the VTF naturally follows the previous file without a
2149 // pad file, then there's nothing to do
2150 //
2151 if ((UINTN) VtfFileImage == (UINTN) FvImage->Eof || (void *) FvImage->CurrentFilePointer == (void *) VtfFileImage) {
2152 return EFI_SUCCESS;
2153 }
2154 //
2155 // Pad file starts at beginning of free space
2156 //
2157 PadFile = (EFI_FFS_FILE_HEADER *) FvImage->CurrentFilePointer;
2158
2159 //
2160 // write header
2161 //
2162 memset (PadFile, 0, sizeof (EFI_FFS_FILE_HEADER));
2163 memcpy (&PadFile->Name, &DefaultFvPadFileNameGuid, sizeof (EFI_GUID));
2164 PadFile->Type = EFI_FV_FILETYPE_FFS_PAD;
2165 PadFile->Attributes = 0;
2166
2167 //
2168 // FileSize includes the EFI_FFS_FILE_HEADER
2169 //
2170 FileSize = (UINTN) VtfFileImage - (UINTN) FvImage->CurrentFilePointer;
2171 PadFile->Size[0] = (UINT8) (FileSize & 0x000000FF);
2172 PadFile->Size[1] = (UINT8) ((FileSize & 0x0000FF00) >> 8);
2173 PadFile->Size[2] = (UINT8) ((FileSize & 0x00FF0000) >> 16);
2174
2175 //
2176 // Fill in checksums and state, must be zero during checksum calculation.
2177 //
2178 PadFile->IntegrityCheck.Checksum.Header = 0;
2179 PadFile->IntegrityCheck.Checksum.File = 0;
2180 PadFile->State = 0;
2181 PadFile->IntegrityCheck.Checksum.Header = CalculateChecksum8 ((UINT8 *) PadFile, sizeof (EFI_FFS_FILE_HEADER));
2182 if (PadFile->Attributes & FFS_ATTRIB_CHECKSUM) {
2183 PadFile->IntegrityCheck.Checksum.File = CalculateChecksum8 ((UINT8 *) PadFile, FileSize);
2184 } else {
2185 PadFile->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM;
2186 }
2187
2188 PadFile->State = EFI_FILE_HEADER_CONSTRUCTION | EFI_FILE_HEADER_VALID | EFI_FILE_DATA_VALID;
2189
2190 UpdateFfsFileState (
2191 (EFI_FFS_FILE_HEADER *) PadFile,
2192 (EFI_FIRMWARE_VOLUME_HEADER *) FvImage->FileImage
2193 );
2194 //
2195 // Update the current FV pointer
2196 //
2197 FvImage->CurrentFilePointer = FvImage->Eof;
2198
2199 return EFI_SUCCESS;
2200 }
2201
2202 EFI_STATUS
2203 UpdateResetVector (
2204 IN MEMORY_FILE *FvImage,
2205 IN FV_INFO *FvInfo,
2206 IN EFI_FFS_FILE_HEADER *VtfFile
2207 )
2208 /*++
2209
2210 Routine Description:
2211
2212 This parses the FV looking for the PEI core and then plugs the address into
2213 the SALE_ENTRY point of the BSF/VTF for IPF and does BUGBUG TBD action to
2214 complete an IA32 Bootstrap FV.
2215
2216 Arguments:
2217
2218 FvImage Memory file for the FV memory image
2219 FvInfo Information read from INF file.
2220 VtfFile Pointer to the VTF file in the FV image.
2221
2222 Returns:
2223
2224 EFI_SUCCESS Function Completed successfully.
2225 EFI_ABORTED Error encountered.
2226 EFI_INVALID_PARAMETER A required parameter was NULL.
2227 EFI_NOT_FOUND PEI Core file not found.
2228
2229 --*/
2230 {
2231 EFI_FFS_FILE_HEADER *PeiCoreFile;
2232 EFI_FFS_FILE_HEADER *SecCoreFile;
2233 EFI_STATUS Status;
2234 EFI_FILE_SECTION_POINTER Pe32Section;
2235 UINT32 EntryPoint;
2236 UINT32 BaseOfCode;
2237 UINT16 MachineType;
2238 EFI_PHYSICAL_ADDRESS PeiCorePhysicalAddress;
2239 EFI_PHYSICAL_ADDRESS SecCorePhysicalAddress;
2240 EFI_PHYSICAL_ADDRESS *SecCoreEntryAddressPtr;
2241 UINT32 *Ia32ResetAddressPtr;
2242 UINT8 *BytePointer;
2243 UINT8 *BytePointer2;
2244 UINT16 *WordPointer;
2245 UINT16 CheckSum;
2246 UINTN Index;
2247 EFI_FFS_FILE_STATE SavedState;
2248 EFI_FFS_FILE_TAIL TailValue;
2249 UINT32 TailSize;
2250 UINT64 FitAddress;
2251 FIT_TABLE *FitTablePtr;
2252
2253 //
2254 // Verify input parameters
2255 //
2256 if (FvImage == NULL || FvInfo == NULL || VtfFile == NULL) {
2257 return EFI_INVALID_PARAMETER;
2258 }
2259 //
2260 // Initialize FV library
2261 //
2262 InitializeFvLib (FvImage->FileImage, (UINTN) FvImage->Eof - (UINTN) FvImage->FileImage);
2263
2264 //
2265 // Verify VTF file
2266 //
2267 Status = VerifyFfsFile (VtfFile);
2268 if (EFI_ERROR (Status)) {
2269 return EFI_INVALID_PARAMETER;
2270 }
2271 //
2272 // Find the PEI Core
2273 //
2274 Status = GetFileByType (EFI_FV_FILETYPE_PEI_CORE, 1, &PeiCoreFile);
2275 if (EFI_ERROR (Status) || PeiCoreFile == NULL) {
2276 Error (NULL, 0, 0, "could not find the PEI core in the FV", NULL);
2277 return EFI_ABORTED;
2278 }
2279 //
2280 // PEI Core found, now find PE32 section
2281 //
2282 Status = GetSectionByType (PeiCoreFile, EFI_SECTION_PE32, 1, &Pe32Section);
2283 if (EFI_ERROR (Status)) {
2284 Error (NULL, 0, 0, "could not find PE32 section in PEI core file", NULL);
2285 return EFI_ABORTED;
2286 }
2287
2288 Status = GetPe32Info (
2289 (VOID *) ((UINTN) Pe32Section.Pe32Section + sizeof (EFI_SECTION_PE32)),
2290 &EntryPoint,
2291 &BaseOfCode,
2292 &MachineType
2293 );
2294 if (EFI_ERROR (Status)) {
2295 Error (NULL, 0, 0, "could not get PE32 entry point for PEI core", NULL);
2296 return EFI_ABORTED;
2297 }
2298 //
2299 // Physical address is FV base + offset of PE32 + offset of the entry point
2300 //
2301 PeiCorePhysicalAddress = FvInfo->BaseAddress;
2302 PeiCorePhysicalAddress += (UINTN) Pe32Section.Pe32Section + sizeof (EFI_SECTION_PE32) - (UINTN) FvImage->FileImage;
2303 PeiCorePhysicalAddress += EntryPoint;
2304
2305 if (MachineType == EFI_IMAGE_MACHINE_IA64) {
2306 //
2307 // Update PEI_CORE address
2308 //
2309 //
2310 // Set the uncached attribute bit in the physical address
2311 //
2312 PeiCorePhysicalAddress |= 0x8000000000000000ULL;
2313
2314 //
2315 // Check if address is aligned on a 16 byte boundary
2316 //
2317 if (PeiCorePhysicalAddress & 0xF) {
2318 printf (
2319 "ERROR: PEI_CORE entry point is not aligned on a 16 byte boundary, address specified is %Xh.\n",
2320 PeiCorePhysicalAddress
2321 );
2322 return EFI_ABORTED;
2323 }
2324 //
2325 // First Get the FIT table address
2326 //
2327 FitAddress = (*(UINT64 *) (FvImage->Eof - IPF_FIT_ADDRESS_OFFSET)) & 0xFFFFFFFF;
2328
2329 FitTablePtr = (FIT_TABLE *) (FvImage->FileImage + (FitAddress - FvInfo->BaseAddress));
2330
2331 Status = UpdatePeiCoreEntryInFit (FitTablePtr, PeiCorePhysicalAddress);
2332
2333 if (!EFI_ERROR (Status)) {
2334 UpdateFitCheckSum (FitTablePtr);
2335 }
2336 //
2337 // Find the Sec Core
2338 //
2339 Status = GetFileByType (EFI_FV_FILETYPE_SECURITY_CORE, 1, &SecCoreFile);
2340 if (EFI_ERROR (Status) || SecCoreFile == NULL) {
2341 Error (NULL, 0, 0, "could not find the Sec core in the FV", NULL);
2342 return EFI_ABORTED;
2343 }
2344 //
2345 // Sec Core found, now find PE32 section
2346 //
2347 Status = GetSectionByType (SecCoreFile, EFI_SECTION_PE32, 1, &Pe32Section);
2348 if (EFI_ERROR (Status)) {
2349 Error (NULL, 0, 0, "could not find PE32 section in SEC core file", NULL);
2350 return EFI_ABORTED;
2351 }
2352
2353 Status = GetPe32Info (
2354 (VOID *) ((UINTN) Pe32Section.Pe32Section + sizeof (EFI_SECTION_PE32)),
2355 &EntryPoint,
2356 &BaseOfCode,
2357 &MachineType
2358 );
2359 if (EFI_ERROR (Status)) {
2360 Error (NULL, 0, 0, "could not get PE32 entry point for SEC core", NULL);
2361 return EFI_ABORTED;
2362 }
2363 //
2364 // Physical address is FV base + offset of PE32 + offset of the entry point
2365 //
2366 SecCorePhysicalAddress = FvInfo->BaseAddress;
2367 SecCorePhysicalAddress += (UINTN) Pe32Section.Pe32Section + sizeof (EFI_SECTION_PE32) - (UINTN) FvImage->FileImage;
2368 SecCorePhysicalAddress += EntryPoint;
2369
2370 //
2371 // Update SEC_CORE address
2372 //
2373 //
2374 // Set the uncached attribute bit in the physical address
2375 //
2376 SecCorePhysicalAddress |= 0x8000000000000000ULL;
2377
2378 //
2379 // Update the address
2380 //
2381 SecCoreEntryAddressPtr = (EFI_PHYSICAL_ADDRESS *) ((UINTN) FvImage->Eof - IPF_SALE_ENTRY_ADDRESS_OFFSET);
2382 *SecCoreEntryAddressPtr = SecCorePhysicalAddress;
2383
2384 //
2385 // Check if address is aligned on a 16 byte boundary
2386 //
2387 if (SecCorePhysicalAddress & 0xF) {
2388 printf (
2389 "ERROR: SALE_ENTRY entry point is not aligned on a 16 byte boundary, address specified is %Xh.\n",
2390 SecCorePhysicalAddress
2391 );
2392 return EFI_ABORTED;
2393 }
2394 } else if (MachineType == EFI_IMAGE_MACHINE_IA32) {
2395 //
2396 // Get the location to update
2397 //
2398 Ia32ResetAddressPtr = (UINT32 *) ((UINTN) FvImage->Eof - IA32_PEI_CORE_ENTRY_OFFSET);
2399
2400 //
2401 // Write lower 32 bits of physical address
2402 //
2403 *Ia32ResetAddressPtr = (UINT32) PeiCorePhysicalAddress;
2404
2405 //
2406 // Update the BFV base address
2407 //
2408 Ia32ResetAddressPtr = (UINT32 *) ((UINTN) FvImage->Eof - 4);
2409 *Ia32ResetAddressPtr = (UINT32) (FvInfo->BaseAddress);
2410
2411 CheckSum = 0x0000;
2412
2413 //
2414 // Update the Startup AP in the FVH header block ZeroVector region.
2415 //
2416 BytePointer = (UINT8 *) ((UINTN) FvImage->FileImage);
2417 BytePointer2 = (FvInfo->Size == 0x10000) ? m64kRecoveryStartupApDataArray : m128kRecoveryStartupApDataArray;
2418 for (Index = 0; Index < SIZEOF_STARTUP_DATA_ARRAY; Index++) {
2419 *BytePointer++ = *BytePointer2++;
2420 }
2421 //
2422 // Calculate the checksum
2423 //
2424 WordPointer = (UINT16 *) ((UINTN) FvImage->FileImage);
2425 for (Index = 0; Index < SIZEOF_STARTUP_DATA_ARRAY / 2; Index++) {
2426 CheckSum = (UINT16) (CheckSum + ((UINT16) *WordPointer));
2427 WordPointer++;
2428 }
2429 //
2430 // Update the checksum field
2431 //
2432 BytePointer = (UINT8 *) ((UINTN) FvImage->FileImage);
2433 BytePointer += (SIZEOF_STARTUP_DATA_ARRAY - 2);
2434 WordPointer = (UINT16 *) BytePointer;
2435 *WordPointer = (UINT16) (0x10000 - (UINT32) CheckSum);
2436 } else {
2437 Error (NULL, 0, 0, "invalid machine type in PEI core", "machine type=0x%X", (UINT32) MachineType);
2438 return EFI_ABORTED;
2439 }
2440 //
2441 // Determine if it has an FFS file tail.
2442 //
2443 if (VtfFile->Attributes & FFS_ATTRIB_TAIL_PRESENT) {
2444 TailSize = sizeof (EFI_FFS_FILE_TAIL);
2445 } else {
2446 TailSize = 0;
2447 }
2448 //
2449 // Now update file checksum
2450 //
2451 SavedState = VtfFile->State;
2452 VtfFile->IntegrityCheck.Checksum.File = 0;
2453 VtfFile->State = 0;
2454 if (VtfFile->Attributes & FFS_ATTRIB_CHECKSUM) {
2455 VtfFile->IntegrityCheck.Checksum.File = CalculateChecksum8 (
2456 (UINT8 *) VtfFile,
2457 GetLength (VtfFile->Size) - TailSize
2458 );
2459 } else {
2460 VtfFile->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM;
2461 }
2462
2463 VtfFile->State = SavedState;
2464
2465 //
2466 // Update tail if present
2467 //
2468 if (VtfFile->Attributes & FFS_ATTRIB_TAIL_PRESENT) {
2469 TailValue = (EFI_FFS_FILE_TAIL) (~(VtfFile->IntegrityCheck.TailReference));
2470 *(EFI_FFS_FILE_TAIL *) (((UINTN) (VtfFile) + GetLength (VtfFile->Size) - sizeof (EFI_FFS_FILE_TAIL))) = TailValue;
2471 }
2472
2473 return EFI_SUCCESS;
2474 }
2475
2476 EFI_STATUS
2477 GetPe32Info (
2478 IN UINT8 *Pe32,
2479 OUT UINT32 *EntryPoint,
2480 OUT UINT32 *BaseOfCode,
2481 OUT UINT16 *MachineType
2482 )
2483 /*++
2484
2485 Routine Description:
2486
2487 Retrieves the PE32 entry point offset and machine type. See EfiImage.h for
2488 machine types. The entry point offset is from the beginning of the PE32
2489 buffer passed in.
2490
2491 Arguments:
2492
2493 Pe32 Beginning of the PE32.
2494 EntryPoint Offset from the beginning of the PE32 to the image entry point.
2495 BaseOfCode Base address of code.
2496 MachineType Magic number for the machine type.
2497
2498 Returns:
2499
2500 EFI_SUCCESS Function completed successfully.
2501 EFI_ABORTED Error encountered.
2502 EFI_INVALID_PARAMETER A required parameter was NULL.
2503 EFI_UNSUPPORTED The operation is unsupported.
2504
2505 --*/
2506 {
2507 EFI_IMAGE_DOS_HEADER *DosHeader;
2508 EFI_IMAGE_NT_HEADERS *NtHeader;
2509
2510 //
2511 // Verify input parameters
2512 //
2513 if (Pe32 == NULL) {
2514 return EFI_INVALID_PARAMETER;
2515 }
2516 //
2517 // First is the DOS header
2518 //
2519 DosHeader = (EFI_IMAGE_DOS_HEADER *) Pe32;
2520
2521 //
2522 // Verify DOS header is expected
2523 //
2524 if (DosHeader->e_magic != EFI_IMAGE_DOS_SIGNATURE) {
2525 printf ("ERROR: Unknown magic number in the DOS header, 0x%04X.\n", DosHeader->e_magic);
2526 return EFI_UNSUPPORTED;
2527 }
2528 //
2529 // Immediately following is the NT header.
2530 //
2531 NtHeader = (EFI_IMAGE_NT_HEADERS *) ((UINTN) Pe32 + DosHeader->e_lfanew);
2532
2533 //
2534 // Verify NT header is expected
2535 //
2536 if (NtHeader->Signature != EFI_IMAGE_NT_SIGNATURE) {
2537 printf ("ERROR: Unrecognized image signature 0x%08X.\n", NtHeader->Signature);
2538 return EFI_UNSUPPORTED;
2539 }
2540 //
2541 // Get output
2542 //
2543 *EntryPoint = NtHeader->OptionalHeader.AddressOfEntryPoint;
2544 *BaseOfCode = NtHeader->OptionalHeader.BaseOfCode;
2545 *MachineType = NtHeader->FileHeader.Machine;
2546
2547 //
2548 // Verify machine type is supported
2549 //
2550 if (*MachineType != EFI_IMAGE_MACHINE_IA32 && *MachineType != EFI_IMAGE_MACHINE_IA64 && *MachineType != EFI_IMAGE_MACHINE_X64 && *MachineType != EFI_IMAGE_MACHINE_EBC) {
2551 printf ("ERROR: Unrecognized machine type in the PE32 file.\n");
2552 return EFI_UNSUPPORTED;
2553 }
2554
2555 return EFI_SUCCESS;
2556 }
2557 //
2558 // Exposed function implementations (prototypes are defined in GenFvImageLib.h)
2559 //
2560 EFI_STATUS
2561 GenerateFvImage (
2562 IN CHAR8 *InfFileImage,
2563 IN UINTN InfFileSize,
2564 OUT UINT8 **FvImage,
2565 OUT UINTN *FvImageSize,
2566 OUT CHAR8 **FvFileName,
2567 OUT UINT8 **SymImage,
2568 OUT UINTN *SymImageSize,
2569 OUT CHAR8 **SymFileName
2570 )
2571 /*++
2572
2573 Routine Description:
2574
2575 This is the main function which will be called from application.
2576
2577 Arguments:
2578
2579 InfFileImage Buffer containing the INF file contents.
2580 InfFileSize Size of the contents of the InfFileImage buffer.
2581 FvImage Pointer to the FV image created.
2582 FvImageSize Size of the FV image created and pointed to by FvImage.
2583 FvFileName Requested name for the FV file.
2584 SymImage Pointer to the Sym image created.
2585 SymImageSize Size of the Sym image created and pointed to by SymImage.
2586 SymFileName Requested name for the Sym file.
2587
2588 Returns:
2589
2590 EFI_SUCCESS Function completed successfully.
2591 EFI_OUT_OF_RESOURCES Could not allocate required resources.
2592 EFI_ABORTED Error encountered.
2593 EFI_INVALID_PARAMETER A required parameter was NULL.
2594
2595 --*/
2596 {
2597 EFI_STATUS Status;
2598 MEMORY_FILE InfMemoryFile;
2599 MEMORY_FILE FvImageMemoryFile;
2600 MEMORY_FILE SymImageMemoryFile;
2601 FV_INFO FvInfo;
2602 UINTN Index;
2603 EFI_FIRMWARE_VOLUME_HEADER *FvHeader;
2604 EFI_FFS_FILE_HEADER *VtfFileImage;
2605
2606 //
2607 // Check for invalid parameter
2608 //
2609 if (InfFileImage == NULL || FvImage == NULL || FvImageSize == NULL || FvFileName == NULL) {
2610 return EFI_INVALID_PARAMETER;
2611 }
2612 //
2613 // Initialize file structures
2614 //
2615 InfMemoryFile.FileImage = InfFileImage;
2616 InfMemoryFile.CurrentFilePointer = InfFileImage;
2617 InfMemoryFile.Eof = InfFileImage + InfFileSize;
2618
2619 //
2620 // Parse the FV inf file for header information
2621 //
2622 Status = ParseFvInf (&InfMemoryFile, &FvInfo);
2623 if (EFI_ERROR (Status)) {
2624 printf ("ERROR: Could not parse the input INF file.\n");
2625 return EFI_ABORTED;
2626 }
2627 //
2628 // Update the file name return values
2629 //
2630 strcpy (*FvFileName, FvInfo.FvName);
2631 strcpy (*SymFileName, FvInfo.SymName);
2632
2633 //
2634 // Calculate the FV size
2635 //
2636 *FvImageSize = FvInfo.Size;
2637
2638 //
2639 // Allocate the FV
2640 //
2641 *FvImage = malloc (*FvImageSize);
2642 if (*FvImage == NULL) {
2643 return EFI_OUT_OF_RESOURCES;
2644 }
2645 //
2646 // Allocate space for symbol file storage
2647 //
2648 *SymImage = malloc (SYMBOL_FILE_SIZE);
2649 if (*SymImage == NULL) {
2650 return EFI_OUT_OF_RESOURCES;
2651 }
2652 //
2653 // Initialize the FV to the erase polarity
2654 //
2655 if (FvInfo.FvAttributes & EFI_FVB_ERASE_POLARITY) {
2656 memset (*FvImage, -1, *FvImageSize);
2657 } else {
2658 memset (*FvImage, 0, *FvImageSize);
2659 }
2660 //
2661 // Initialize FV header
2662 //
2663 FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) *FvImage;
2664
2665 //
2666 // Initialize the zero vector to all zeros.
2667 //
2668 memset (FvHeader->ZeroVector, 0, 16);
2669
2670 //
2671 // Copy the FFS GUID
2672 //
2673 memcpy (&FvHeader->FileSystemGuid, &FvInfo.FvGuid, sizeof (EFI_GUID));
2674
2675 FvHeader->FvLength = *FvImageSize;
2676 FvHeader->Signature = EFI_FVH_SIGNATURE;
2677 FvHeader->Attributes = FvInfo.FvAttributes;
2678 FvHeader->Revision = EFI_FVH_REVISION;
2679 FvHeader->Reserved[0] = 0;
2680 FvHeader->Reserved[1] = 0;
2681 FvHeader->Reserved[2] = 0;
2682
2683 //
2684 // Copy firmware block map
2685 //
2686 for (Index = 0; FvInfo.FvBlocks[Index].NumBlocks != 0; Index++) {
2687 FvHeader->FvBlockMap[Index].NumBlocks = FvInfo.FvBlocks[Index].NumBlocks;
2688 FvHeader->FvBlockMap[Index].BlockLength = FvInfo.FvBlocks[Index].BlockLength;
2689 }
2690 //
2691 // Add block map terminator
2692 //
2693 FvHeader->FvBlockMap[Index].NumBlocks = 0;
2694 FvHeader->FvBlockMap[Index].BlockLength = 0;
2695
2696 //
2697 // Complete the header
2698 //
2699 FvHeader->HeaderLength = (UINT16) (((UINTN) &(FvHeader->FvBlockMap[Index + 1])) - (UINTN) *FvImage);
2700 FvHeader->Checksum = 0;
2701 FvHeader->Checksum = CalculateChecksum16 ((UINT16 *) FvHeader, FvHeader->HeaderLength / sizeof (UINT16));
2702
2703 //
2704 // If there is no FFS file, find and generate each components of the FV
2705 //
2706 if (FvInfo.FvFiles[0][0] == 0) {
2707 Status = GenNonFFSFv (*FvImage, &FvInfo);
2708 if (EFI_ERROR (Status)) {
2709 printf ("ERROR: Could not generate NonFFS FV.\n");
2710 free (*FvImage);
2711 return EFI_ABORTED;
2712 }
2713
2714 return EFI_SUCCESS;
2715 }
2716 //
2717 // Initialize our "file" view of the buffer
2718 //
2719 FvImageMemoryFile.FileImage = *FvImage;
2720 FvImageMemoryFile.CurrentFilePointer = *FvImage + FvHeader->HeaderLength;
2721 FvImageMemoryFile.Eof = *FvImage +*FvImageSize;
2722
2723 //
2724 // Initialize our "file" view of the symbol file.
2725 //
2726 SymImageMemoryFile.FileImage = *SymImage;
2727 SymImageMemoryFile.CurrentFilePointer = *SymImage;
2728 SymImageMemoryFile.Eof = *FvImage + SYMBOL_FILE_SIZE;
2729
2730 //
2731 // Initialize the FV library.
2732 //
2733 InitializeFvLib (FvImageMemoryFile.FileImage, FvInfo.Size);
2734
2735 //
2736 // Files start on 8 byte alignments, so move to the next 8 byte aligned
2737 // address. For now, just assert if it isn't. Currently FV header is
2738 // always a multiple of 8 bytes.
2739 // BUGBUG: Handle this better
2740 //
2741 assert ((((UINTN) FvImageMemoryFile.CurrentFilePointer) % 8) == 0);
2742
2743 //
2744 // Initialize the VTF file address.
2745 //
2746 VtfFileImage = (EFI_FFS_FILE_HEADER *) FvImageMemoryFile.Eof;
2747
2748 //
2749 // Add files to FV
2750 //
2751 for (Index = 0; FvInfo.FvFiles[Index][0] != 0; Index++) {
2752 //
2753 // Add the file
2754 //
2755 Status = AddFile (&FvImageMemoryFile, &FvInfo, Index, &VtfFileImage, &SymImageMemoryFile);
2756
2757 //
2758 // Exit if error detected while adding the file
2759 //
2760 if (EFI_ERROR (Status)) {
2761 printf ("ERROR: Could not add file %s.\n", FvInfo.FvFiles[Index]);
2762 free (*FvImage);
2763 return EFI_ABORTED;
2764 }
2765 }
2766 //
2767 // If there is a VTF file, some special actions need to occur.
2768 //
2769 if ((UINTN) VtfFileImage != (UINTN) FvImageMemoryFile.Eof) {
2770 //
2771 // Pad from the end of the last file to the beginning of the VTF file.
2772 //
2773 Status = PadFvImage (&FvImageMemoryFile, VtfFileImage);
2774 if (EFI_ERROR (Status)) {
2775 printf ("ERROR: Could not create the pad file between the last file and the VTF file.\n");
2776 free (*FvImage);
2777 return EFI_ABORTED;
2778 }
2779 //
2780 // Update reset vector (SALE_ENTRY for IPF)
2781 // Now for IA32 and IA64 platform, the fv which has bsf file must have the
2782 // EndAddress of 0xFFFFFFFF. Thus, only this type fv needs to update the
2783 // reset vector. If the PEI Core is found, the VTF file will probably get
2784 // corrupted by updating the entry point.
2785 //
2786 if ((FvInfo.BaseAddress + FvInfo.Size) == FV_IMAGES_TOP_ADDRESS) {
2787 Status = UpdateResetVector (&FvImageMemoryFile, &FvInfo, VtfFileImage);
2788 if (EFI_ERROR(Status)) {
2789 printf ("ERROR: Could not update the reset vector.\n");
2790 free (*FvImage);
2791 return EFI_ABORTED;
2792 }
2793 }
2794 }
2795 //
2796 // Determine final Sym file size
2797 //
2798 *SymImageSize = SymImageMemoryFile.CurrentFilePointer - SymImageMemoryFile.FileImage;
2799
2800 return EFI_SUCCESS;
2801 }
2802
2803 EFI_STATUS
2804 UpdatePeiCoreEntryInFit (
2805 IN FIT_TABLE *FitTablePtr,
2806 IN UINT64 PeiCorePhysicalAddress
2807 )
2808 /*++
2809
2810 Routine Description:
2811
2812 This function is used to update the Pei Core address in FIT, this can be used by Sec core to pass control from
2813 Sec to Pei Core
2814
2815 Arguments:
2816
2817 FitTablePtr - The pointer of FIT_TABLE.
2818 PeiCorePhysicalAddress - The address of Pei Core entry.
2819
2820 Returns:
2821
2822 EFI_SUCCESS - The PEI_CORE FIT entry was updated successfully.
2823 EFI_NOT_FOUND - Not found the PEI_CORE FIT entry.
2824
2825 --*/
2826 {
2827 FIT_TABLE *TmpFitPtr;
2828 UINTN Index;
2829 UINTN NumFitComponents;
2830
2831 TmpFitPtr = FitTablePtr;
2832 NumFitComponents = TmpFitPtr->CompSize;
2833
2834 for (Index = 0; Index < NumFitComponents; Index++) {
2835 if ((TmpFitPtr->CvAndType & FIT_TYPE_MASK) == COMP_TYPE_FIT_PEICORE) {
2836 TmpFitPtr->CompAddress = PeiCorePhysicalAddress;
2837 return EFI_SUCCESS;
2838 }
2839
2840 TmpFitPtr++;
2841 }
2842
2843 return EFI_NOT_FOUND;
2844 }
2845
2846 VOID
2847 UpdateFitCheckSum (
2848 IN FIT_TABLE *FitTablePtr
2849 )
2850 /*++
2851
2852 Routine Description:
2853
2854 This function is used to update the checksum for FIT.
2855
2856
2857 Arguments:
2858
2859 FitTablePtr - The pointer of FIT_TABLE.
2860
2861 Returns:
2862
2863 None.
2864
2865 --*/
2866 {
2867 if ((FitTablePtr->CvAndType & CHECKSUM_BIT_MASK) >> 7) {
2868 FitTablePtr->CheckSum = 0;
2869 FitTablePtr->CheckSum = CalculateChecksum8 ((UINT8 *) FitTablePtr, FitTablePtr->CompSize * 16);
2870 }
2871 }