]> git.proxmox.com Git - mirror_edk2.git/blob - EdkCompatibilityPkg/Sample/Tools/Source/GenFvImage/GenFvImageLib.c
EFI_FVB2_ALIGNMNET_512K should be EFI_FVB2_ALIGNMENT_512K.
[mirror_edk2.git] / EdkCompatibilityPkg / Sample / Tools / Source / GenFvImage / GenFvImageLib.c
1 /*++
2
3 Copyright (c) 2004 - 2011, Intel Corporation. All rights reserved.<BR>
4 This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
8
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
11
12 Module Name:
13
14 GenFvImageLib.c
15
16 Abstract:
17
18 This file contains functions required to generate a Firmware Volume.
19
20 --*/
21
22 //
23 // Include files
24 //
25 #include "GenFvImageLib.h"
26 #include "GenFvImageLibInternal.h"
27 #include <string.h>
28 #include EFI_GUID_DEFINITION (PeiPeCoffLoader)
29 #include "EfiFirmwareFileSystem.h"
30 #include "EfiWorkingBlockHeader.h"
31 #include "EfiVariable.h"
32 #include <io.h>
33 #include <assert.h>
34 #include "CommonLib.h"
35 #include "FvLib.h"
36 #include "EfiImage.h"
37 #include "crc32.h"
38 #include "EfiUtilityMsgs.h"
39 #include EFI_GUID_DEFINITION (FirmwareFileSystem)
40 #include EFI_GUID_DEFINITION (FirmwareFileSystem2)
41
42 //
43 // Define the PE/COFF loader
44 //
45 extern EFI_PEI_PE_COFF_LOADER_PROTOCOL mPeCoffLoader;
46
47 //
48 // Local function prototypes
49 //
50 EFI_STATUS
51 GetPe32Info (
52 IN UINT8 *Pe32,
53 OUT UINT32 *EntryPoint,
54 OUT UINT32 *BaseOfCode,
55 OUT UINT16 *MachineType
56 );
57
58 //
59 // Local function implementations.
60 //
61 #if (PI_SPECIFICATION_VERSION < 0x00010000)
62 EFI_GUID FfsGuid = EFI_FIRMWARE_FILE_SYSTEM_GUID;
63 #else
64 EFI_GUID FfsGuid = EFI_FIRMWARE_FILE_SYSTEM2_GUID;
65 #endif
66
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 #if (PI_SPECIFICATION_VERSION >= 0x00010000)
436 //
437 // Read the read lock capability attribute
438 //
439 Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_READ_LOCK_CAP_STRING, 0, Value);
440
441 if (Status == EFI_SUCCESS) {
442 //
443 // Update attribute
444 //
445 if (strcmp (Value, TRUE_STRING) == 0) {
446 FvInfo->FvAttributes |= EFI_FVB2_READ_LOCK_CAP;
447 } else if (strcmp (Value, FALSE_STRING) != 0) {
448 Error (NULL, 0, 0, EFI_FVB_READ_LOCK_CAP_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
449 return EFI_ABORTED;
450 }
451 } else {
452 Error (NULL, 0, 0, EFI_FVB_READ_LOCK_CAP_STRING, "value not specified");
453 return Status;
454 }
455
456 //
457 // Read the read lock status attribute
458 //
459 Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_READ_LOCK_STATUS_STRING, 0, Value);
460
461 if (Status == EFI_SUCCESS) {
462 //
463 // Update attribute
464 //
465 if (strcmp (Value, TRUE_STRING) == 0) {
466 FvInfo->FvAttributes |= EFI_FVB2_READ_LOCK_STATUS;
467 } else if (strcmp (Value, FALSE_STRING) != 0) {
468 Error (NULL, 0, 0, EFI_FVB_READ_LOCK_STATUS_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
469 return EFI_ABORTED;
470 }
471 } else {
472 Error (NULL, 0, 0, EFI_FVB_READ_LOCK_STATUS_STRING, "value not specified");
473 return Status;
474 }
475
476 //
477 // Read the write lock capability attribute
478 //
479 Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_WRITE_LOCK_CAP_STRING, 0, Value);
480
481 if (Status == EFI_SUCCESS) {
482 //
483 // Update attribute
484 //
485 if (strcmp (Value, TRUE_STRING) == 0) {
486 FvInfo->FvAttributes |= EFI_FVB2_WRITE_LOCK_CAP;
487 } else if (strcmp (Value, FALSE_STRING) != 0) {
488 Error (NULL, 0, 0, EFI_FVB_WRITE_LOCK_CAP_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
489 return EFI_ABORTED;
490 }
491 } else {
492 Error (NULL, 0, 0, EFI_FVB_WRITE_LOCK_CAP_STRING, "value not specified");
493 return Status;
494 }
495
496 //
497 // Read the write lock status attribute
498 //
499 Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_WRITE_LOCK_STATUS_STRING, 0, Value);
500
501 if (Status == EFI_SUCCESS) {
502 //
503 // Update attribute
504 //
505 if (strcmp (Value, TRUE_STRING) == 0) {
506 FvInfo->FvAttributes |= EFI_FVB2_WRITE_LOCK_STATUS;
507 } else if (strcmp (Value, FALSE_STRING) != 0) {
508 Error (NULL, 0, 0, EFI_FVB_WRITE_LOCK_STATUS_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
509 return EFI_ABORTED;
510 }
511 } else {
512 Error (NULL, 0, 0, EFI_FVB_WRITE_LOCK_STATUS_STRING, "value not specified");
513 return Status;
514 }
515 #endif
516
517 #if (PI_SPECIFICATION_VERSION < 0x00010000)
518 //
519 // Read the alignment capabilities attribute
520 //
521 Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_CAP_STRING, 0, Value);
522
523 if (Status == EFI_SUCCESS) {
524 //
525 // Update attribute
526 //
527 if (strcmp (Value, TRUE_STRING) == 0) {
528 FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_CAP;
529 } else if (strcmp (Value, FALSE_STRING) != 0) {
530 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_CAP_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
531 return EFI_ABORTED;
532 }
533 } else {
534 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_CAP_STRING, "value not specified");
535 return Status;
536 }
537
538 //
539 // Read the word alignment capability attribute
540 //
541 Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_2_STRING, 0, Value);
542
543 if (Status == EFI_SUCCESS) {
544 //
545 // Update attribute
546 //
547 if (strcmp (Value, TRUE_STRING) == 0) {
548 FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_2;
549 } else if (strcmp (Value, FALSE_STRING) != 0) {
550 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_2_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
551 return EFI_ABORTED;
552 }
553 } else {
554 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_2_STRING, "value not specified");
555 return Status;
556 }
557
558
559 //
560 // Read the dword alignment capability attribute
561 //
562 Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_4_STRING, 0, Value);
563
564 if (Status == EFI_SUCCESS) {
565 //
566 // Update attribute
567 //
568 if (strcmp (Value, TRUE_STRING) == 0) {
569 FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_4;
570 } else if (strcmp (Value, FALSE_STRING) != 0) {
571 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_4_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
572 return EFI_ABORTED;
573 }
574 } else {
575 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_4_STRING, "value not specified");
576 return Status;
577 }
578 //
579 // Read the word alignment capability attribute
580 //
581 Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_8_STRING, 0, Value);
582
583 if (Status == EFI_SUCCESS) {
584 //
585 // Update attribute
586 //
587 if (strcmp (Value, TRUE_STRING) == 0) {
588 FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_8;
589 } else if (strcmp (Value, FALSE_STRING) != 0) {
590 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_8_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
591 return EFI_ABORTED;
592 }
593 } else {
594 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_8_STRING, "value not specified");
595 return Status;
596 }
597 //
598 // Read the qword alignment capability attribute
599 //
600 Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_16_STRING, 0, Value);
601
602 if (Status == EFI_SUCCESS) {
603 //
604 // Update attribute
605 //
606 if (strcmp (Value, TRUE_STRING) == 0) {
607 FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_16;
608 } else if (strcmp (Value, FALSE_STRING) != 0) {
609 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_16_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
610 return EFI_ABORTED;
611 }
612 } else {
613 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_16_STRING, "value not specified");
614 return Status;
615 }
616 //
617 // Read the 32 byte alignment capability attribute
618 //
619 Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_32_STRING, 0, Value);
620
621 if (Status == EFI_SUCCESS) {
622 //
623 // Update attribute
624 //
625 if (strcmp (Value, TRUE_STRING) == 0) {
626 FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_32;
627 } else if (strcmp (Value, FALSE_STRING) != 0) {
628 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_32_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
629 return EFI_ABORTED;
630 }
631 } else {
632 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_32_STRING, "value not specified");
633 return Status;
634 }
635 //
636 // Read the 64 byte alignment capability attribute
637 //
638 Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_64_STRING, 0, Value);
639
640 if (Status == EFI_SUCCESS) {
641 //
642 // Update attribute
643 //
644 if (strcmp (Value, TRUE_STRING) == 0) {
645 FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_64;
646 } else if (strcmp (Value, FALSE_STRING) != 0) {
647 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_64_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
648 return EFI_ABORTED;
649 }
650 } else {
651 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_64_STRING, "value not specified");
652 return Status;
653 }
654 //
655 // Read the 128 byte alignment capability attribute
656 //
657 Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_128_STRING, 0, Value);
658
659 if (Status == EFI_SUCCESS) {
660 //
661 // Update attribute
662 //
663 if (strcmp (Value, TRUE_STRING) == 0) {
664 FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_128;
665 } else if (strcmp (Value, FALSE_STRING) != 0) {
666 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_128_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
667 return EFI_ABORTED;
668 }
669 } else {
670 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_128_STRING, "value not specified");
671 return Status;
672 }
673 //
674 // Read the 256 byte alignment capability attribute
675 //
676 Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_256_STRING, 0, Value);
677
678 if (Status == EFI_SUCCESS) {
679 //
680 // Update attribute
681 //
682 if (strcmp (Value, TRUE_STRING) == 0) {
683 FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_256;
684 } else if (strcmp (Value, FALSE_STRING) != 0) {
685 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_256_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
686 return EFI_ABORTED;
687 }
688 } else {
689 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_256_STRING, "value not specified");
690 return Status;
691 }
692 //
693 // Read the 512 byte alignment capability attribute
694 //
695 Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_512_STRING, 0, Value);
696
697 if (Status == EFI_SUCCESS) {
698 //
699 // Update attribute
700 //
701 if (strcmp (Value, TRUE_STRING) == 0) {
702 FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_512;
703 } else if (strcmp (Value, FALSE_STRING) != 0) {
704 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_512_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
705 return EFI_ABORTED;
706 }
707 } else {
708 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_512_STRING, "value not specified");
709 return Status;
710 }
711 //
712 // Read the 1K byte alignment capability attribute
713 //
714 Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_1K_STRING, 0, Value);
715
716 if (Status == EFI_SUCCESS) {
717 //
718 // Update attribute
719 //
720 if (strcmp (Value, TRUE_STRING) == 0) {
721 FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_1K;
722 } else if (strcmp (Value, FALSE_STRING) != 0) {
723 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_1K_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
724 return EFI_ABORTED;
725 }
726 } else {
727 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_1K_STRING, "value not specified");
728 return Status;
729 }
730 //
731 // Read the 2K byte alignment capability attribute
732 //
733 Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_2K_STRING, 0, Value);
734
735 if (Status == EFI_SUCCESS) {
736 //
737 // Update attribute
738 //
739 if (strcmp (Value, TRUE_STRING) == 0) {
740 FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_2K;
741 } else if (strcmp (Value, FALSE_STRING) != 0) {
742 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_2K_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
743 return EFI_ABORTED;
744 }
745 } else {
746 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_2K_STRING, "value not specified");
747 return Status;
748 }
749 //
750 // Read the 4K byte alignment capability attribute
751 //
752 Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_4K_STRING, 0, Value);
753
754 if (Status == EFI_SUCCESS) {
755 //
756 // Update attribute
757 //
758 if (strcmp (Value, TRUE_STRING) == 0) {
759 FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_4K;
760 } else if (strcmp (Value, FALSE_STRING) != 0) {
761 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_4K_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
762 return EFI_ABORTED;
763 }
764 } else {
765 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_4K_STRING, "value not specified");
766 return Status;
767 }
768 //
769 // Read the 8K byte alignment capability attribute
770 //
771 Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_8K_STRING, 0, Value);
772
773 if (Status == EFI_SUCCESS) {
774 //
775 // Update attribute
776 //
777 if (strcmp (Value, TRUE_STRING) == 0) {
778 FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_8K;
779 } else if (strcmp (Value, FALSE_STRING) != 0) {
780 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_8K_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
781 return EFI_ABORTED;
782 }
783 } else {
784 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_8K_STRING, "value not specified");
785 return Status;
786 }
787 //
788 // Read the 16K byte alignment capability attribute
789 //
790 Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_16K_STRING, 0, Value);
791
792 if (Status == EFI_SUCCESS) {
793 //
794 // Update attribute
795 //
796 if (strcmp (Value, TRUE_STRING) == 0) {
797 FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_16K;
798 } else if (strcmp (Value, FALSE_STRING) != 0) {
799 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_16K_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
800 return EFI_ABORTED;
801 }
802 } else {
803 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_16K_STRING, "value not specified");
804 return Status;
805 }
806 //
807 // Read the 32K byte alignment capability attribute
808 //
809 Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_32K_STRING, 0, Value);
810
811 if (Status == EFI_SUCCESS) {
812 //
813 // Update attribute
814 //
815 if (strcmp (Value, TRUE_STRING) == 0) {
816 FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_32K;
817 } else if (strcmp (Value, FALSE_STRING) != 0) {
818 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_32K_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
819 return EFI_ABORTED;
820 }
821 } else {
822 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_32K_STRING, "value not specified");
823 return Status;
824 }
825 //
826 // Read the 64K byte alignment capability attribute
827 //
828 Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_64K_STRING, 0, Value);
829
830 if (Status == EFI_SUCCESS) {
831 //
832 // Update attribute
833 //
834 if (strcmp (Value, TRUE_STRING) == 0) {
835 FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_64K;
836 } else if (strcmp (Value, FALSE_STRING) != 0) {
837 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_64K_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
838 return EFI_ABORTED;
839 }
840 } else {
841 Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_64K_STRING, "value not specified");
842 return Status;
843 }
844
845 if (!(FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_CAP) &&
846 (
847 (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_2) ||
848 (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_4) ||
849 (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_8) ||
850 (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_16) ||
851 (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_32) ||
852 (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_64) ||
853 (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_128) ||
854 (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_256) ||
855 (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_512) ||
856 (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_1K) ||
857 (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_2K) ||
858 (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_4K) ||
859 (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_8K) ||
860 (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_16K) ||
861 (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_32K) ||
862 (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_64K)
863 )
864 ){
865 Error (
866 NULL,
867 0,
868 0,
869 "illegal combination of alignment attributes",
870 "if %s is not %s, no individual alignments can be %s",
871 EFI_FVB_ALIGNMENT_CAP_STRING,
872 TRUE_STRING,
873 TRUE_STRING
874 );
875 return EFI_ABORTED;
876 }
877 #else
878 //
879 // Read the PI1.0 FVB2 Alignment Capabilities Attribute
880 //
881 Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB2_ALIGNMENT_STRING, 0, Value);
882
883 if (Status == EFI_SUCCESS) {
884 //
885 // Update attribute
886 //
887 if (strcmp (Value, EFI_FVB2_ALIGNMENT_1_STRING) == 0) {
888 FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_1;
889 } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_2_STRING) == 0) {
890 FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_2;
891 } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_4_STRING) == 0) {
892 FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_4;
893 } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_8_STRING) == 0) {
894 FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_8;
895 } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_16_STRING) == 0) {
896 FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_16;
897 } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_32_STRING) == 0) {
898 FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_32;
899 } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_64_STRING) == 0) {
900 FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_64;
901 } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_128_STRING) == 0) {
902 FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_128;
903 } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_256_STRING) == 0) {
904 FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_256;
905 } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_512_STRING) == 0) {
906 FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_512;
907 } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_1K_STRING) == 0) {
908 FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_1K;
909 } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_2K_STRING) == 0) {
910 FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_2K;
911 } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_4K_STRING) == 0) {
912 FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_4K;
913 } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_8K_STRING) == 0) {
914 FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_8K;
915 } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_16K_STRING) == 0) {
916 FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_16K;
917 } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_32K_STRING) == 0) {
918 FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_32K;
919 } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_64K_STRING) == 0) {
920 FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_64K;
921 } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_128K_STRING) == 0) {
922 FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_128K;
923 } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_256K_STRING) == 0) {
924 FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_256K;
925 } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_512K_STRING) == 0) {
926 FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_512K;
927 } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_1M_STRING) == 0) {
928 FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_1M;
929 } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_2M_STRING) == 0) {
930 FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_2M;
931 } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_4M_STRING) == 0) {
932 FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_4M;
933 } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_8M_STRING) == 0) {
934 FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_8M;
935 } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_16M_STRING) == 0) {
936 FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_16M;
937 } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_32M_STRING) == 0) {
938 FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_32M;
939 } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_64M_STRING) == 0) {
940 FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_64M;
941 } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_128M_STRING) == 0) {
942 FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_128M;
943 } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_256M_STRING) == 0) {
944 FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_256M;
945 } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_512M_STRING) == 0) {
946 FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_512M;
947 } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_1G_STRING) == 0) {
948 FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_1G;
949 } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_2G_STRING) == 0) {
950 FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_2G;
951 } else {
952 Error (NULL, 0, 0, EFI_FVB2_ALIGNMENT_STRING, "value not correct!");
953 return EFI_ABORTED;
954 }
955 } else {
956 Error (NULL, 0, 0, EFI_FVB2_ALIGNMENT_STRING, "value not specified");
957 return Status;
958 }
959
960 #endif
961 //
962 // Read block maps
963 //
964 for (Index = 0; Index < MAX_NUMBER_OF_FV_BLOCKS; Index++) {
965 //
966 // Read the number of blocks
967 //
968 Status = FindToken (InfFile, OPTIONS_SECTION_STRING, EFI_NUM_BLOCKS_STRING, Index, Value);
969
970 if (Status == EFI_SUCCESS) {
971 if (strcmp (Value, AUTO_STRING) == 0) {
972 Value64 = (UINT64) -1;
973 } else {
974 //
975 // Update the number of blocks
976 //
977 Status = AsciiStringToUint64 (Value, FALSE, &Value64);
978 if (EFI_ERROR (Status)) {
979 Error (NULL, 0, 0, Value, "invalid value for %s", EFI_NUM_BLOCKS_STRING);
980 return EFI_ABORTED;
981 }
982 }
983
984 FvInfo->FvBlocks[Index].NumBlocks = (UINT32) Value64;
985 } else {
986 //
987 // If there is no number of blocks, but there is a size, then we have a mismatched pair
988 // and should return an error.
989 //
990 Status = FindToken (InfFile, OPTIONS_SECTION_STRING, EFI_BLOCK_SIZE_STRING, Index, Value);
991 if (!EFI_ERROR (Status)) {
992 Error (NULL, 0, 0, "must specify both", "%s and %s", EFI_NUM_BLOCKS_STRING, EFI_BLOCK_SIZE_STRING);
993 return EFI_ABORTED;
994 } else {
995 //
996 // We are done
997 //
998 break;
999 }
1000 }
1001 //
1002 // Read the size of blocks
1003 //
1004 Status = FindToken (InfFile, OPTIONS_SECTION_STRING, EFI_BLOCK_SIZE_STRING, Index, Value);
1005
1006 if (Status == EFI_SUCCESS) {
1007 //
1008 // Update the number of blocks
1009 //
1010 Status = AsciiStringToUint64 (Value, FALSE, &Value64);
1011 if (EFI_ERROR (Status)) {
1012 Error (NULL, 0, 0, Value, "invalid value specified for %s", EFI_BLOCK_SIZE_STRING);
1013 return EFI_ABORTED;
1014 }
1015
1016 FvInfo->FvBlocks[Index].BlockLength = (UINT32) Value64;
1017 } else {
1018 //
1019 // There is a number of blocks, but there is no size, so we have a mismatched pair
1020 // and should return an error.
1021 //
1022 Error (NULL, 0, 0, "must specify both", "%s and %s", EFI_NUM_BLOCKS_STRING, EFI_BLOCK_SIZE_STRING);
1023 return EFI_ABORTED;
1024 }
1025 }
1026 //
1027 // Read files
1028 //
1029 for (Index = 0; Index < MAX_NUMBER_OF_FILES_IN_FV; Index++) {
1030 //
1031 // Read the number of blocks
1032 //
1033 Status = FindToken (InfFile, FILES_SECTION_STRING, EFI_FILE_NAME_STRING, Index, Value);
1034
1035 if (Status == EFI_SUCCESS) {
1036 //
1037 // Add the file
1038 //
1039 strcpy (FvInfo->FvFiles[Index], Value);
1040 } else {
1041 break;
1042 }
1043 }
1044
1045 if (FindSection (InfFile, COMPONENT_SECTION_STRING)) {
1046 Index = 0;
1047 while (TRUE) {
1048 Status = FindTokenInstanceInSection (
1049 InfFile,
1050 COMPONENT_SECTION_STRING,
1051 Index,
1052 FvInfo->FvComponents[Index].ComponentName,
1053 Value
1054 );
1055 if (EFI_ERROR (Status)) {
1056 break;
1057 }
1058 Status = AsciiStringToUint64 (Value, FALSE, &Value64);
1059 if (EFI_ERROR (Status)) {
1060 Error (NULL, 0, 0, Value, "not a valid integer");
1061 return EFI_ABORTED;
1062 }
1063
1064 FvInfo->FvComponents[Index].Size = (UINTN) Value64;
1065 Index++;
1066 }
1067 }
1068 //
1069 // Compute size for easy access later
1070 //
1071 FvInfo->Size = 0;
1072 for (Index = 0; FvInfo->FvBlocks[Index].NumBlocks; Index++) {
1073 if ((FvInfo->Size == (UINTN) -1 && Index > 0) ||
1074 (FvInfo->FvBlocks[Index].NumBlocks == (UINT32) -1 && Index > 0)
1075 ) {
1076 //
1077 // Error 1. more pairs after AUTO
1078 // Error 2. AUTO appear in non-first position
1079 //
1080 Error (NULL, 0, 0, NULL, "cannot have more than one pair of %s and %s if %s is set to %s",
1081 EFI_NUM_BLOCKS_STRING, EFI_BLOCK_SIZE_STRING,
1082 EFI_NUM_BLOCKS_STRING, AUTO_STRING
1083 );
1084 return EFI_ABORTED;
1085 }
1086
1087 if (FvInfo->FvBlocks[Index].NumBlocks == (UINT32) -1) {
1088 FvInfo->Size = (UINTN) -1;
1089 } else {
1090 FvInfo->Size += FvInfo->FvBlocks[Index].NumBlocks * FvInfo->FvBlocks[Index].BlockLength;
1091 }
1092 }
1093
1094 if (FvInfo->Size == (UINTN) -1 && FvInfo->FvFiles[0][0] == 0) {
1095 //
1096 // Non FFS FV cannot set block number to AUTO
1097 //
1098 Error (NULL, 0, 0, "non-FFS FV", "cannot set %s to %s", EFI_NUM_BLOCKS_STRING, AUTO_STRING);
1099 return EFI_ABORTED;
1100 }
1101
1102 return EFI_SUCCESS;
1103 }
1104
1105 VOID
1106 UpdateFfsFileState (
1107 IN EFI_FFS_FILE_HEADER *FfsFile,
1108 IN EFI_FIRMWARE_VOLUME_HEADER *FvHeader
1109 )
1110 /*++
1111
1112 Routine Description:
1113
1114 This function changes the FFS file attributes based on the erase polarity
1115 of the FV.
1116
1117 Arguments:
1118
1119 FfsFile File header.
1120 FvHeader FV header.
1121
1122 Returns:
1123
1124 None
1125
1126 --*/
1127 {
1128 if (FvHeader->Attributes & EFI_FVB_ERASE_POLARITY) {
1129 FfsFile->State = (UINT8)~(FfsFile->State);
1130 }
1131 }
1132
1133 EFI_STATUS
1134 ReadFfsAlignment (
1135 IN EFI_FFS_FILE_HEADER *FfsFile,
1136 IN OUT UINT32 *Alignment
1137 )
1138 /*++
1139
1140 Routine Description:
1141
1142 This function determines the alignment of the FFS input file from the file
1143 attributes.
1144
1145 Arguments:
1146
1147 FfsFile FFS file to parse
1148 Alignment The minimum required alignment of the FFS file, in bytes
1149
1150 Returns:
1151
1152 EFI_SUCCESS The function completed successfully.
1153 EFI_INVALID_PARAMETER One of the input parameters was invalid.
1154 EFI_ABORTED An error occurred.
1155
1156 --*/
1157 {
1158 //
1159 // Verify input parameters.
1160 //
1161 if (FfsFile == NULL || Alignment == NULL) {
1162 return EFI_INVALID_PARAMETER;
1163 }
1164
1165 switch ((FfsFile->Attributes >> 3) & 0x07) {
1166
1167 case 0:
1168 //
1169 // 1 byte alignment
1170 //
1171 *Alignment = (1 << 0);
1172 break;
1173
1174 case 1:
1175 //
1176 // 16 byte alignment
1177 //
1178 *Alignment = (1 << 4);
1179 break;
1180
1181 case 2:
1182 //
1183 // 128 byte alignment
1184 //
1185 *Alignment = (1 << 7);
1186 break;
1187
1188 case 3:
1189 //
1190 // 512 byte alignment
1191 //
1192 *Alignment = (1 << 9);
1193 break;
1194
1195 case 4:
1196 //
1197 // 1K byte alignment
1198 //
1199 *Alignment = (1 << 10);
1200 break;
1201
1202 case 5:
1203 //
1204 // 4K byte alignment
1205 //
1206 *Alignment = (1 << 12);
1207 break;
1208
1209 case 6:
1210 //
1211 // 32K byte alignment
1212 //
1213 *Alignment = (1 << 15);
1214 break;
1215
1216 case 7:
1217 //
1218 // 64K byte alignment
1219 //
1220 *Alignment = (1 << 16);
1221 break;
1222
1223 default:
1224 Error (NULL, 0, 0, "nvalid file attribute calculated, this is most likely a utility error", NULL);
1225 return EFI_ABORTED;
1226 }
1227
1228 return EFI_SUCCESS;
1229 }
1230
1231 EFI_STATUS
1232 AddPadFile (
1233 IN OUT MEMORY_FILE *FvImage,
1234 IN UINT32 DataAlignment
1235 )
1236 /*++
1237
1238 Routine Description:
1239
1240 This function adds a pad file to the FV image if it required to align the
1241 data of the next file.
1242
1243 Arguments:
1244
1245 FvImage The memory image of the FV to add it to. The current offset
1246 must be valid.
1247 DataAlignment The data alignment of the next FFS file.
1248
1249 Returns:
1250
1251 EFI_SUCCESS The function completed successfully.
1252 EFI_INVALID_PARAMETER One of the input parameters was invalid.
1253 EFI_OUT_OF_RESOURCES Insufficient resources exist in the FV to complete
1254 the pad file add.
1255
1256 --*/
1257 {
1258 EFI_FFS_FILE_HEADER *PadFile;
1259 UUID PadFileGuid;
1260 UINTN PadFileSize;
1261
1262 //
1263 // Verify input parameters.
1264 //
1265 if (FvImage == NULL) {
1266 return EFI_INVALID_PARAMETER;
1267 }
1268 //
1269 // Basic assumption is we start from an 8 byte aligned address
1270 // and our file header is a multiple of 8 bytes
1271 //
1272 assert ((UINTN) FvImage->CurrentFilePointer % 8 == 0);
1273 assert (sizeof (EFI_FFS_FILE_HEADER) % 8 == 0);
1274
1275 //
1276 // Check if a pad file is necessary
1277 //
1278 if (((UINTN) FvImage->CurrentFilePointer - (UINTN) FvImage->FileImage + sizeof (EFI_FFS_FILE_HEADER)) % DataAlignment == 0) {
1279 return EFI_SUCCESS;
1280 }
1281 //
1282 // Write pad file header
1283 //
1284 PadFile = (EFI_FFS_FILE_HEADER *) FvImage->CurrentFilePointer;
1285
1286 //
1287 // Verify that we have enough space for the file header
1288 //
1289 if ((UINTN) (PadFile + sizeof (EFI_FFS_FILE_HEADER)) >= (UINTN) FvImage->Eof) {
1290 return EFI_OUT_OF_RESOURCES;
1291 }
1292
1293 UuidCreate (&PadFileGuid);
1294 memset (PadFile, 0, sizeof (EFI_FFS_FILE_HEADER));
1295 memcpy (&PadFile->Name, &PadFileGuid, sizeof (EFI_GUID));
1296 PadFile->Type = EFI_FV_FILETYPE_FFS_PAD;
1297 PadFile->Attributes = 0;
1298
1299 //
1300 // Calculate the pad file size
1301 //
1302 //
1303 // This is the earliest possible valid offset (current plus pad file header
1304 // plus the next file header)
1305 //
1306 PadFileSize = (UINTN) FvImage->CurrentFilePointer - (UINTN) FvImage->FileImage + (sizeof (EFI_FFS_FILE_HEADER) * 2);
1307
1308 //
1309 // Add whatever it takes to get to the next aligned address
1310 //
1311 while ((PadFileSize % DataAlignment) != 0) {
1312 PadFileSize++;
1313 }
1314 //
1315 // Subtract the next file header size
1316 //
1317 PadFileSize -= sizeof (EFI_FFS_FILE_HEADER);
1318
1319 //
1320 // Subtract the starting offset to get size
1321 //
1322 PadFileSize -= (UINTN) FvImage->CurrentFilePointer - (UINTN) FvImage->FileImage;
1323
1324 //
1325 // Write pad file size (calculated size minus next file header size)
1326 //
1327 PadFile->Size[0] = (UINT8) (PadFileSize & 0xFF);
1328 PadFile->Size[1] = (UINT8) ((PadFileSize >> 8) & 0xFF);
1329 PadFile->Size[2] = (UINT8) ((PadFileSize >> 16) & 0xFF);
1330
1331 //
1332 // Fill in checksums and state, they must be 0 for checksumming.
1333 //
1334 PadFile->IntegrityCheck.Checksum.Header = 0;
1335 PadFile->IntegrityCheck.Checksum.File = 0;
1336 PadFile->State = 0;
1337 PadFile->IntegrityCheck.Checksum.Header = CalculateChecksum8 ((UINT8 *) PadFile, sizeof (EFI_FFS_FILE_HEADER));
1338 if (PadFile->Attributes & FFS_ATTRIB_CHECKSUM) {
1339 #if (PI_SPECIFICATION_VERSION < 0x00010000)
1340 PadFile->IntegrityCheck.Checksum.File = CalculateChecksum8 ((UINT8 *) PadFile, PadFileSize);
1341 #else
1342 PadFile->IntegrityCheck.Checksum.File = CalculateChecksum8 ((UINT8 *) ((UINTN)PadFile + sizeof (EFI_FFS_FILE_HEADER)), PadFileSize - sizeof (EFI_FFS_FILE_HEADER));
1343 #endif
1344 } else {
1345 PadFile->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM;
1346 }
1347
1348 PadFile->State = EFI_FILE_HEADER_CONSTRUCTION | EFI_FILE_HEADER_VALID | EFI_FILE_DATA_VALID;
1349 UpdateFfsFileState (
1350 (EFI_FFS_FILE_HEADER *) PadFile,
1351 (EFI_FIRMWARE_VOLUME_HEADER *) FvImage->FileImage
1352 );
1353
1354 //
1355 // Verify that we have enough space (including the padding
1356 //
1357 if ((UINTN) (PadFile + sizeof (EFI_FFS_FILE_HEADER)) >= (UINTN) FvImage->Eof) {
1358 return EFI_OUT_OF_RESOURCES;
1359 }
1360 //
1361 // Update the current FV pointer
1362 //
1363 FvImage->CurrentFilePointer += PadFileSize;
1364
1365 return EFI_SUCCESS;
1366 }
1367
1368 BOOLEAN
1369 IsVtfFile (
1370 IN EFI_FFS_FILE_HEADER *FileBuffer
1371 )
1372 /*++
1373
1374 Routine Description:
1375
1376 This function checks the header to validate if it is a VTF file
1377
1378 Arguments:
1379
1380 FileBuffer Buffer in which content of a file has been read.
1381
1382 Returns:
1383
1384 TRUE If this is a VTF file
1385 FALSE If this is not a VTF file
1386
1387 --*/
1388 {
1389 EFI_GUID VtfGuid = EFI_FFS_VOLUME_TOP_FILE_GUID;
1390 if (!memcmp (&FileBuffer->Name, &VtfGuid, sizeof (EFI_GUID))) {
1391 return TRUE;
1392 } else {
1393 return FALSE;
1394 }
1395 }
1396
1397 EFI_STATUS
1398 FfsRebaseImageRead (
1399 IN VOID *FileHandle,
1400 IN UINTN FileOffset,
1401 IN OUT UINT32 *ReadSize,
1402 OUT VOID *Buffer
1403 )
1404 /*++
1405
1406 Routine Description:
1407
1408 Support routine for the PE/COFF Loader that reads a buffer from a PE/COFF file
1409
1410 Arguments:
1411
1412 FileHandle - The handle to the PE/COFF file
1413
1414 FileOffset - The offset, in bytes, into the file to read
1415
1416 ReadSize - The number of bytes to read from the file starting at FileOffset
1417
1418 Buffer - A pointer to the buffer to read the data into.
1419
1420 Returns:
1421
1422 EFI_SUCCESS - ReadSize bytes of data were read into Buffer from the PE/COFF file starting at FileOffset
1423
1424 --*/
1425 {
1426 CHAR8 *Destination8;
1427 CHAR8 *Source8;
1428 UINT32 Length;
1429
1430 Destination8 = Buffer;
1431 Source8 = (CHAR8 *) ((UINTN) FileHandle + FileOffset);
1432 Length = *ReadSize;
1433 while (Length--) {
1434 *(Destination8++) = *(Source8++);
1435 }
1436
1437 return EFI_SUCCESS;
1438 }
1439
1440 EFI_STATUS
1441 RebaseFfsFile (
1442 IN OUT EFI_FFS_FILE_HEADER *FfsFile,
1443 IN EFI_PHYSICAL_ADDRESS BaseAddress
1444 )
1445 /*++
1446
1447 Routine Description:
1448
1449 This function determines if a file is XIP and should be rebased. It will
1450 rebase any PE32 sections found in the file using the base address.
1451
1452 Arguments:
1453
1454 FfsFile A pointer to Ffs file image.
1455 BaseAddress The base address to use for rebasing the file image.
1456
1457 Returns:
1458
1459 EFI_SUCCESS The image was properly rebased.
1460 EFI_INVALID_PARAMETER An input parameter is invalid.
1461 EFI_ABORTED An error occurred while rebasing the input file image.
1462 EFI_OUT_OF_RESOURCES Could not allocate a required resource.
1463
1464 --*/
1465 {
1466 EFI_STATUS Status;
1467 EFI_PEI_PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;
1468 UINTN MemoryImagePointer;
1469 UINTN MemoryImagePointerAligned;
1470
1471 EFI_PHYSICAL_ADDRESS ImageAddress;
1472 UINT64 ImageSize;
1473 EFI_PHYSICAL_ADDRESS EntryPoint;
1474
1475 UINT32 Pe32FileSize;
1476 UINT32 NewPe32BaseAddress;
1477
1478 UINTN Index;
1479 EFI_FILE_SECTION_POINTER CurrentPe32Section;
1480 UINT8 FileGuidString[80];
1481
1482 //
1483 // Verify input parameters
1484 //
1485 if (FfsFile == NULL) {
1486 return EFI_INVALID_PARAMETER;
1487 }
1488 //
1489 // Convert the GUID to a string so we can at least report which file
1490 // if we find an error.
1491 //
1492 PrintGuidToBuffer (&FfsFile->Name, FileGuidString, sizeof (FileGuidString), TRUE);
1493
1494 //
1495 // Do some nominal checks on the file, then check for XIP.
1496 //
1497 Status = VerifyFfsFile (FfsFile);
1498 if (EFI_ERROR (Status)) {
1499 Error (NULL, 0, 0, "invalid FFS file", FileGuidString);
1500 return EFI_INVALID_PARAMETER;
1501 }
1502
1503 if (FfsFile->Type != EFI_FV_FILETYPE_SECURITY_CORE &&
1504 FfsFile->Type != EFI_FV_FILETYPE_PEI_CORE &&
1505 FfsFile->Type != EFI_FV_FILETYPE_PEIM
1506 ) {
1507 //
1508 // File is not XIP, so don't rebase
1509 //
1510 return EFI_SUCCESS;
1511 }
1512 //
1513 // Rebase each PE32 section
1514 //
1515 for (Index = 1;; Index++) {
1516 Status = GetSectionByType (FfsFile, EFI_SECTION_PE32, Index, &CurrentPe32Section);
1517 if (EFI_ERROR (Status)) {
1518 break;
1519 }
1520 //
1521 // Calculate the PE32 base address, the FFS file base plus the offset of the PE32 section
1522 //
1523 NewPe32BaseAddress = ((UINT32) BaseAddress) + ((UINTN) CurrentPe32Section.Pe32Section - (UINTN) FfsFile);
1524
1525 //
1526 // Initialize context
1527 //
1528 memset (&ImageContext, 0, sizeof (ImageContext));
1529 ImageContext.Handle = (VOID *) ((UINTN) CurrentPe32Section.Pe32Section + sizeof (EFI_PE32_SECTION));
1530 ImageContext.ImageRead = (EFI_PEI_PE_COFF_LOADER_READ_FILE) FfsRebaseImageRead;
1531
1532 Status = mPeCoffLoader.GetImageInfo (&mPeCoffLoader, &ImageContext);
1533
1534 if (EFI_ERROR (Status)) {
1535 Error (NULL, 0, 0, "GetImageInfo() failed", FileGuidString);
1536 return Status;
1537 }
1538 //
1539 // Allocate a buffer for the image to be loaded into.
1540 //
1541 Pe32FileSize = GetLength (CurrentPe32Section.Pe32Section->CommonHeader.Size);
1542 MemoryImagePointer = (UINTN) (malloc (Pe32FileSize + 0x1000));
1543 MemoryImagePointerAligned = (MemoryImagePointer + 0x0FFF) & (-1 << 12);
1544 if (MemoryImagePointerAligned == 0) {
1545 Error (NULL, 0, 0, "memory allocation failure", NULL);
1546 return EFI_OUT_OF_RESOURCES;
1547 }
1548
1549 //
1550 // bugbug
1551 //
1552 ImageContext.ImageAddress = MemoryImagePointerAligned;
1553 Status = mPeCoffLoader.LoadImage (&mPeCoffLoader, &ImageContext);
1554 if (EFI_ERROR (Status)) {
1555 Error (NULL, 0, 0, "LoadImage() failure", FileGuidString);
1556 free ((VOID *) MemoryImagePointer);
1557 return Status;
1558 }
1559
1560 Status = mPeCoffLoader.RelocateImage (&mPeCoffLoader, &ImageContext);
1561 if (EFI_ERROR (Status)) {
1562 Error (NULL, 0, 0, "RelocateImage() failure", FileGuidString);
1563 free ((VOID *) MemoryImagePointer);
1564 return Status;
1565 }
1566
1567 ImageAddress = ImageContext.ImageAddress;
1568 ImageSize = ImageContext.ImageSize;
1569 EntryPoint = ImageContext.EntryPoint;
1570
1571 if (ImageSize > Pe32FileSize) {
1572 Error (
1573 NULL,
1574 0,
1575 0,
1576 "rebased PE32 is larger than original PE32 image",
1577 "0x%X > 0x%X on file %s",
1578 ImageSize,
1579 Pe32FileSize,
1580 FileGuidString
1581 );
1582 free ((VOID *) MemoryImagePointer);
1583 return EFI_ABORTED;
1584 }
1585
1586 memcpy (CurrentPe32Section.Pe32Section, (VOID *) MemoryImagePointerAligned, Pe32FileSize);
1587
1588 free ((VOID *) MemoryImagePointer);
1589 }
1590 //
1591 // the above for loop will always exit with EFI_NOT_FOUND if it completes
1592 // normally. If Index == 1 at exit, then no PE32 sections were found. If it
1593 // exits with any other error code, then something broke...
1594 //
1595 if (Status != EFI_NOT_FOUND) {
1596 Error (NULL, 0, 0, "failed to parse PE32 section", FileGuidString);
1597 return Status;
1598 }
1599
1600 return EFI_SUCCESS;
1601 }
1602
1603 EFI_STATUS
1604 AddSymFile (
1605 IN UINT64 BaseAddress,
1606 IN EFI_FFS_FILE_HEADER *FfsFile,
1607 IN OUT MEMORY_FILE *SymImage,
1608 IN CHAR8 *SourceFileName
1609 )
1610 /*++
1611
1612 Routine Description:
1613
1614 This function adds the SYM tokens in the source file to the destination file.
1615 The SYM tokens are updated to reflect the base address.
1616
1617 Arguments:
1618
1619 BaseAddress The base address for the new SYM tokens.
1620 FfsFile Pointer to the beginning of the FFS file in question.
1621 SymImage The memory file to update with symbol information.
1622 SourceFileName The source file.
1623
1624 Returns:
1625
1626 EFI_SUCCESS The function completed successfully.
1627 EFI_INVALID_PARAMETER One of the input parameters was invalid.
1628 EFI_ABORTED An error occurred.
1629
1630 --*/
1631 {
1632 FILE *SourceFile;
1633
1634 CHAR8 Buffer[_MAX_PATH];
1635 CHAR8 Type[_MAX_PATH];
1636 CHAR8 Address[_MAX_PATH];
1637 CHAR8 Section[_MAX_PATH];
1638 CHAR8 Token[_MAX_PATH];
1639 CHAR8 SymFileName[_MAX_PATH];
1640 CHAR8 CodeModuleName[_MAX_PATH];
1641 CHAR8 *Ptr;
1642
1643 UINT64 TokenAddress;
1644
1645 EFI_STATUS Status;
1646 EFI_FILE_SECTION_POINTER Pe32Section;
1647 UINT32 EntryPoint;
1648 UINT32 BaseOfCode;
1649 UINT16 MachineType;
1650
1651 //
1652 // Verify input parameters.
1653 //
1654 if (BaseAddress == 0 || FfsFile == NULL || SymImage == NULL || SourceFileName == NULL) {
1655 Error (NULL, 0, 0, "invalid parameter passed to AddSymFile()", NULL);
1656 return EFI_INVALID_PARAMETER;
1657 }
1658 //
1659 // Check if we want to add this file
1660 //
1661 //
1662 // Get the file name
1663 //
1664 strcpy (Buffer, SourceFileName);
1665
1666 //
1667 // Copy the file name for the path of the sym file and truncate the name portion.
1668 //
1669 strcpy (SymFileName, Buffer);
1670 Ptr = strrchr (SymFileName, '\\');
1671 assert (Ptr);
1672 Ptr[0] = 0;
1673
1674 //
1675 // Find the file extension and make it lower case
1676 //
1677 Ptr = strrchr (SymFileName, '.');
1678 if (Ptr != NULL) {
1679 _strlwr (Ptr);
1680 }
1681 //
1682 // Check if it is PEI file
1683 //
1684 if (strstr (Buffer, ".pei") != NULL) {
1685 //
1686 // Find the human readable portion
1687 //
1688 if (!strtok (Buffer, "-") ||
1689 !strtok (NULL, "-") ||
1690 !strtok (NULL, "-") ||
1691 !strtok (NULL, "-") ||
1692 !strtok (NULL, "-") ||
1693 !strcpy (Buffer, strtok (NULL, "."))
1694 ) {
1695 Error (NULL, 0, 0, "failed to find human readable portion of the file name in AddSymFile()", NULL);
1696 return EFI_ABORTED;
1697 }
1698 //
1699 // Save code module name
1700 //
1701 strcpy (CodeModuleName, Buffer);
1702
1703 //
1704 // Add the symbol file name and extension to the file path.
1705 //
1706 strcat (Buffer, ".sym");
1707 strcat (SymFileName, "\\");
1708 strcat (SymFileName, Buffer);
1709 } else {
1710 //
1711 // Only handle PEIM files.
1712 //
1713 return EFI_SUCCESS;
1714 }
1715 //
1716 // Find PE32 section
1717 //
1718 Status = GetSectionByType (FfsFile, EFI_SECTION_PE32, 1, &Pe32Section);
1719
1720 //
1721 // BUGBUG: Assume if no PE32 section it is PIC and hardcode base address
1722 //
1723 if (Status == EFI_NOT_FOUND) {
1724 Status = GetSectionByType (FfsFile, EFI_SECTION_TE, 1, &Pe32Section);
1725 }
1726
1727 if (Status == EFI_SUCCESS) {
1728 Status = GetPe32Info (
1729 (VOID *) ((UINTN) Pe32Section.Pe32Section + sizeof (EFI_SECTION_PE32)),
1730 &EntryPoint,
1731 &BaseOfCode,
1732 &MachineType
1733 );
1734 } else {
1735 if (Status == EFI_NOT_FOUND) {
1736 BaseOfCode = 0x60;
1737 Status = EFI_SUCCESS;
1738 } else {
1739 Error (NULL, 0, 0, "could not parse a PE32 section from the PEI file", NULL);
1740 return Status;
1741 }
1742 }
1743
1744 if (EFI_ERROR (Status)) {
1745 Error (NULL, 0, 0, "GetPe32Info() could not get PE32 entry point for PEI file", NULL);
1746 return Status;
1747 }
1748
1749 //
1750 // Open the source file
1751 //
1752 SourceFile = fopen (SymFileName, "r");
1753 if (SourceFile == NULL) {
1754 //
1755 // SYM files are not required.
1756 //
1757 return EFI_SUCCESS;
1758 }
1759 //
1760 // Read the first line
1761 //
1762 if (fgets (Buffer, _MAX_PATH, SourceFile) == NULL) {
1763 Buffer[0] = 0;
1764 }
1765 //
1766 // Make sure it matches the expected sym format
1767 //
1768 if (strcmp (Buffer, "TEXTSYM format | V1.0\n")) {
1769 fclose (SourceFile);
1770 Error (NULL, 0, 0, "AddSymFile() found unexpected sym format in input file", NULL);
1771 return EFI_ABORTED;
1772 }
1773 //
1774 // Read in the file
1775 //
1776 while (feof (SourceFile) == 0) {
1777 //
1778 // Read a line
1779 //
1780 if (fscanf (
1781 SourceFile,
1782 "%s | %s | %s | %s\n",
1783 Type,
1784 Address,
1785 Section,
1786 Token
1787 ) == 4) {
1788 //
1789 // If the token starts with "??" ignore it
1790 //
1791 if (Token[0] == '?' && Token[1] == '?') {
1792 continue;
1793 }
1794 //
1795 // Get the token address
1796 //
1797 AsciiStringToUint64 (Address, TRUE, &TokenAddress);
1798
1799 //
1800 // Add the base address
1801 //
1802 TokenAddress += BaseAddress;
1803
1804 //
1805 // If PE32 or TE section then find the start of code. For PIC it is hardcoded.
1806 //
1807 if (Pe32Section.Pe32Section) {
1808 //
1809 // Add the offset of the PE32 section
1810 //
1811 TokenAddress += (UINTN) Pe32Section.Pe32Section - (UINTN) FfsFile;
1812
1813 //
1814 // Add the size of the PE32 section header
1815 //
1816 TokenAddress += sizeof (EFI_PE32_SECTION);
1817 } else {
1818 //
1819 // BUGBUG: Don't know why this is 0x28 bytes.
1820 //
1821 TokenAddress += 0x28;
1822 }
1823 //
1824 // Add the beginning of the code
1825 //
1826 TokenAddress += BaseOfCode;
1827
1828 sprintf (
1829 Buffer,
1830 "%s | %016I64X | %s | _%s%s\n",
1831 Type,
1832 TokenAddress,
1833 Section,
1834 CodeModuleName,
1835 Token
1836 );
1837 memcpy (SymImage->CurrentFilePointer, Buffer, strlen (Buffer) + 1);
1838 SymImage->CurrentFilePointer = (UINT8 *) (((UINTN) SymImage->CurrentFilePointer) + strlen (Buffer) + 1);
1839 }
1840 }
1841
1842 fclose (SourceFile);
1843 return EFI_SUCCESS;
1844 }
1845
1846 EFI_STATUS
1847 ReallocateFvImage (
1848 IN OUT MEMORY_FILE *FvImage,
1849 IN OUT FV_INFO *FvInfo,
1850 IN OUT EFI_FFS_FILE_HEADER **VtfFileImage,
1851 IN OUT UINTN *FvImageCapacity
1852 )
1853 /*++
1854 Routine Description:
1855 Increase the size of FV image by 1 block. The routine may reallocate memory
1856 depending on the capacity of the FV image.
1857
1858 Arguments:
1859 FvImage The memory image of the FV to add it to. The current offset
1860 must be valid.
1861 FvInfo Pointer to information about the FV.
1862 VtfFileImage A pointer to the VTF file within the FvImage. If this is equal
1863 to the end of the FvImage then no VTF previously found.
1864 FvImageCapacity Capacity of image buffer for FV.
1865
1866 Returns:
1867 EFI_SUCCESS The function completed successfully.
1868 EFI_OUT_OF_RESOURCES Insufficient resources exist to complete the reallocation.
1869
1870 --*/
1871 {
1872 CHAR8 *FileImage;
1873 UINTN OldSize;
1874 UINTN IncreaseSize;
1875 EFI_FIRMWARE_VOLUME_HEADER *FvHeader;
1876 BOOLEAN AllocateNewMemory;
1877 EFI_FFS_FILE_HEADER *NewVtfFileImage;
1878 UINT32 VtfFileLength;
1879 UINT8 TempByte;
1880
1881 OldSize = (UINTN) FvImage->Eof - (UINTN) FvImage->FileImage;
1882 IncreaseSize = FvInfo->FvBlocks[0].BlockLength;
1883 assert (OldSize == FvInfo->FvBlocks[0].NumBlocks * FvInfo->FvBlocks[0].BlockLength);
1884
1885 //
1886 // Assume we have enough capacity
1887 //
1888 AllocateNewMemory = FALSE;
1889
1890
1891 if (OldSize + IncreaseSize > *FvImageCapacity) {
1892 AllocateNewMemory = TRUE;
1893 //
1894 // Increase capacity by one unit
1895 //
1896 *FvImageCapacity = OldSize + FV_CAPACITY_INCREASE_UNIT;
1897 FileImage = malloc (*FvImageCapacity);
1898
1899 if (FileImage == NULL) {
1900 Error (NULL, 0, 0, "memory allocation failure", NULL);
1901 return EFI_OUT_OF_RESOURCES;
1902 }
1903
1904 //
1905 // Initialize the content per FV polarity
1906 //
1907 if (FvInfo->FvAttributes & EFI_FVB_ERASE_POLARITY) {
1908 memset (FileImage, -1, *FvImageCapacity);
1909 } else {
1910 memset (FileImage, 0, *FvImageCapacity);
1911 }
1912
1913 //
1914 // Copy the FV content before VTF
1915 //
1916 memcpy (FileImage, FvImage->FileImage, (UINTN) *VtfFileImage - (UINTN) FvImage->FileImage);
1917 } else {
1918 FileImage = FvImage->FileImage;
1919 }
1920
1921 //
1922 // Move VTF if it exists
1923 //
1924 NewVtfFileImage = (EFI_FFS_FILE_HEADER *) (FileImage + ((UINTN) *VtfFileImage - (UINTN) FvImage->FileImage) + IncreaseSize);
1925 if ((UINTN) *VtfFileImage != (UINTN) FvImage->Eof) {
1926 //
1927 // Exchange the VTF buffer from end to start for two purpose:
1928 // 1. Exchange: Preserve the default value per FV polarity
1929 // 2. End->Start: Avoid destroying the VTF data during exchanging
1930 //
1931 VtfFileLength = GetLength ((*VtfFileImage)->Size);
1932 while (VtfFileLength-- != 0) {
1933 TempByte = ((UINT8 *) VtfFileImage)[VtfFileLength];
1934 ((UINT8 *) VtfFileImage)[VtfFileLength] = ((UINT8 *) NewVtfFileImage)[VtfFileLength];
1935 ((UINT8 *) NewVtfFileImage)[VtfFileLength] = TempByte;
1936 }
1937 }
1938
1939 //
1940 // Update VTF Pointer
1941 //
1942 *VtfFileImage = NewVtfFileImage;
1943
1944 //
1945 // Update FvInfo
1946 //
1947 FvInfo->FvBlocks[0].NumBlocks ++;
1948
1949 //
1950 // Update FV Header
1951 //
1952 FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) FileImage;
1953 FvHeader->FvBlockMap[0].NumBlocks = FvInfo->FvBlocks[0].NumBlocks;
1954 FvHeader->FvLength = OldSize + IncreaseSize;
1955 FvHeader->Checksum = 0;
1956 FvHeader->Checksum = CalculateChecksum16 ((UINT16 *) FvHeader, FvHeader->HeaderLength / sizeof (UINT16));
1957
1958 //
1959 // Update FvImage
1960 //
1961 if (AllocateNewMemory) {
1962 free (FvImage->FileImage);
1963 FvImage->CurrentFilePointer = FileImage + (FvImage->CurrentFilePointer - FvImage->FileImage);
1964 FvImage->FileImage = FileImage;
1965 }
1966 FvImage->Eof = FvImage->FileImage + OldSize + IncreaseSize;
1967
1968 InitializeFvLib (FvImage->FileImage, OldSize + IncreaseSize);
1969 return EFI_SUCCESS;
1970 }
1971
1972 EFI_STATUS
1973 AddFile (
1974 IN OUT MEMORY_FILE *FvImage,
1975 IN FV_INFO *FvInfo,
1976 IN UINTN Index,
1977 IN OUT EFI_FFS_FILE_HEADER **VtfFileImage,
1978 IN OUT MEMORY_FILE *SymImage,
1979 IN OUT UINTN *FvImageCapacity
1980 )
1981 /*++
1982
1983 Routine Description:
1984
1985 This function adds a file to the FV image. The file will pad to the
1986 appropriate alignment if required.
1987
1988 Arguments:
1989
1990 FvImage The memory image of the FV to add it to. The current offset
1991 must be valid.
1992 FvInfo Pointer to information about the FV.
1993 Index The file in the FvInfo file list to add.
1994 VtfFileImage A pointer to the VTF file within the FvImage. If this is equal
1995 to the end of the FvImage then no VTF previously found.
1996 SymImage The memory image of the Sym file to update if symbols are present.
1997 The current offset must be valid.
1998 FvImageCapacity Capacity of image buffer for FV.
1999
2000 Returns:
2001
2002 EFI_SUCCESS The function completed successfully.
2003 EFI_INVALID_PARAMETER One of the input parameters was invalid.
2004 EFI_ABORTED An error occurred.
2005 EFI_OUT_OF_RESOURCES Insufficient resources exist to complete the add.
2006
2007 --*/
2008 {
2009 FILE *NewFile;
2010 UINTN FileSize;
2011 UINT8 *FileBuffer;
2012 UINTN NumBytesRead;
2013 UINT32 CurrentFileAlignment;
2014 EFI_STATUS Status;
2015 EFI_PHYSICAL_ADDRESS CurrentFileBaseAddress;
2016 UINT8 VtfHeaderChecksum;
2017 UINT8 VtfFileChecksum;
2018 UINT8 FileState;
2019 UINT32 TailSize;
2020 #if (PI_SPECIFICATION_VERSION < 0x00010000)
2021 EFI_FFS_FILE_TAIL TailValue;
2022 #endif
2023 //
2024 // Verify input parameters.
2025 //
2026 if (FvImage == NULL || FvInfo == NULL || FvInfo->FvFiles[Index][0] == 0 || VtfFileImage == NULL || SymImage == NULL) {
2027 return EFI_INVALID_PARAMETER;
2028 }
2029 //
2030 // Read the file to add
2031 //
2032 NewFile = fopen (FvInfo->FvFiles[Index], "rb");
2033
2034 if (NewFile == NULL) {
2035 Error (NULL, 0, 0, FvInfo->FvFiles[Index], "failed to open file for reading");
2036 return EFI_ABORTED;
2037 }
2038 //
2039 // Get the file size
2040 //
2041 FileSize = _filelength (_fileno (NewFile));
2042
2043 //
2044 // Read the file into a buffer
2045 //
2046 FileBuffer = malloc (FileSize);
2047 if (FileBuffer == NULL) {
2048 Error (NULL, 0, 0, "memory allocation failure", NULL);
2049 return EFI_OUT_OF_RESOURCES;
2050 }
2051
2052 NumBytesRead = fread (FileBuffer, sizeof (UINT8), FileSize, NewFile);
2053
2054 //
2055 // Done with the file, from this point on we will just use the buffer read.
2056 //
2057 fclose (NewFile);
2058
2059 //
2060 // Verify read successful
2061 //
2062 if (NumBytesRead != sizeof (UINT8) * FileSize) {
2063 Error (NULL, 0, 0, FvInfo->FvFiles[Index], "failed to read input file contents");
2064 Status = EFI_ABORTED;
2065 goto Exit;
2066 }
2067 //
2068 // Verify space exists to add the file
2069 //
2070 while (FileSize > (UINTN) ((UINTN) *VtfFileImage - (UINTN) FvImage->CurrentFilePointer)) {
2071 if (FvInfo->Size != (UINTN) -1) {
2072 Error (NULL, 0, 0, FvInfo->FvFiles[Index], "insufficient space remains to add the file");
2073 Status = EFI_OUT_OF_RESOURCES;
2074 goto Exit;
2075 } else {
2076 //
2077 // FV Size is AUTO, increase by one block
2078 //
2079 Status = ReallocateFvImage (FvImage, FvInfo, VtfFileImage, FvImageCapacity);
2080 if (EFI_ERROR (Status)) {
2081 Error (NULL, 0, 0, FvInfo->FvFiles[Index], "insufficient resources to add the file");
2082 goto Exit;
2083 }
2084 }
2085 }
2086 //
2087 // Update the file state based on polarity of the FV.
2088 //
2089 UpdateFfsFileState (
2090 (EFI_FFS_FILE_HEADER *) FileBuffer,
2091 (EFI_FIRMWARE_VOLUME_HEADER *) FvImage->FileImage
2092 );
2093
2094 //
2095 // If we have a VTF file, add it at the top.
2096 //
2097 if (IsVtfFile ((EFI_FFS_FILE_HEADER *) FileBuffer)) {
2098 if ((UINTN) *VtfFileImage == (UINTN) FvImage->Eof) {
2099 //
2100 // No previous VTF, add this one.
2101 //
2102 *VtfFileImage = (EFI_FFS_FILE_HEADER *) (UINTN) ((UINTN) FvImage->FileImage + FvInfo->Size - FileSize);
2103 //
2104 // Sanity check. The file MUST align appropriately
2105 //
2106 if ((((UINTN) *VtfFileImage) & 0x07) != 0) {
2107 Error (NULL, 0, 0, "VTF file does not align on 8-byte boundary", NULL);
2108 }
2109 //
2110 // copy VTF File Header
2111 //
2112 memcpy (*VtfFileImage, FileBuffer, sizeof (EFI_FFS_FILE_HEADER));
2113
2114 //
2115 // Copy VTF body
2116 //
2117 memcpy (
2118 (UINT8 *) *VtfFileImage + sizeof (EFI_FFS_FILE_HEADER),
2119 FileBuffer + sizeof (EFI_FFS_FILE_HEADER),
2120 FileSize - sizeof (EFI_FFS_FILE_HEADER)
2121 );
2122
2123 //
2124 // re-calculate the VTF File Header
2125 //
2126 FileState = (*VtfFileImage)->State;
2127 (*VtfFileImage)->State = 0;
2128 *(UINT32 *) ((*VtfFileImage)->Size) = FileSize;
2129 (*VtfFileImage)->IntegrityCheck.Checksum.Header = 0;
2130 (*VtfFileImage)->IntegrityCheck.Checksum.File = 0;
2131
2132 VtfHeaderChecksum = CalculateChecksum8 ((UINT8 *) *VtfFileImage, sizeof (EFI_FFS_FILE_HEADER));
2133 (*VtfFileImage)->IntegrityCheck.Checksum.Header = VtfHeaderChecksum;
2134 //
2135 // Determine if it has a tail
2136 //
2137 if ((*VtfFileImage)->Attributes & FFS_ATTRIB_TAIL_PRESENT) {
2138 TailSize = sizeof (EFI_FFS_FILE_TAIL);
2139 } else {
2140 TailSize = 0;
2141 }
2142
2143 if ((*VtfFileImage)->Attributes & FFS_ATTRIB_CHECKSUM) {
2144 #if (PI_SPECIFICATION_VERSION < 0x00010000)
2145 VtfFileChecksum = CalculateChecksum8 ((UINT8 *) *VtfFileImage, FileSize - TailSize);
2146 #else
2147 VtfFileChecksum = CalculateChecksum8 ((UINT8 *) ((UINTN)*VtfFileImage + sizeof (EFI_FFS_FILE_HEADER)), FileSize - TailSize - sizeof(EFI_FFS_FILE_HEADER));
2148 #endif
2149 (*VtfFileImage)->IntegrityCheck.Checksum.File = VtfFileChecksum;
2150 } else {
2151 (*VtfFileImage)->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM;
2152 }
2153 #if (PI_SPECIFICATION_VERSION < 0x00010000)
2154 //
2155 // If it has a file tail, update it
2156 //
2157 if ((*VtfFileImage)->Attributes & FFS_ATTRIB_TAIL_PRESENT) {
2158 TailValue = (EFI_FFS_FILE_TAIL) (~((*VtfFileImage)->IntegrityCheck.TailReference));
2159 *(EFI_FFS_FILE_TAIL *) (((UINTN) (*VtfFileImage) + GetLength ((*VtfFileImage)->Size) - sizeof (EFI_FFS_FILE_TAIL))) = TailValue;
2160 }
2161 #endif
2162 (*VtfFileImage)->State = FileState;
2163 Status = EFI_SUCCESS;
2164 goto Exit;
2165 } else {
2166 //
2167 // Already found a VTF file.
2168 //
2169 Error (NULL, 0, 0, "multiple VTF files are illegal in a single FV", NULL);
2170 Status = EFI_ABORTED;
2171 goto Exit;
2172 }
2173 }
2174 //
2175 // Check if alignment is required
2176 //
2177 Status = ReadFfsAlignment ((EFI_FFS_FILE_HEADER *) FileBuffer, &CurrentFileAlignment);
2178 if (EFI_ERROR (Status)) {
2179 printf ("ERROR: Could not determine alignment of file %s.\n", FvInfo->FvFiles[Index]);
2180 Status = EFI_ABORTED;
2181 goto Exit;
2182 }
2183 //
2184 // Add pad file if necessary
2185 //
2186 while (EFI_ERROR (AddPadFile (FvImage, CurrentFileAlignment))) {
2187 if (FvInfo->Size != (UINTN) -1) {
2188 printf ("ERROR: Could not align the file data properly.\n");
2189 Status = EFI_ABORTED;
2190 goto Exit;
2191 } else {
2192 //
2193 // FV Size is AUTO, increase by one block
2194 //
2195 Status = ReallocateFvImage (FvImage, FvInfo, VtfFileImage, FvImageCapacity);
2196 if (EFI_ERROR (Status)) {
2197 Error (NULL, 0, 0, FvInfo->FvFiles[Index], "insufficient resources to add the file");
2198 goto Exit;
2199 }
2200 }
2201 }
2202
2203 //
2204 // Add file
2205 //
2206 while (FileSize > (UINTN) ((UINTN) *VtfFileImage - (UINTN) FvImage->CurrentFilePointer)) {
2207 if (FvInfo->Size != (UINTN) -1) {
2208 printf ("ERROR: The firmware volume is out of space, could not add file %s.\n", FvInfo->FvFiles[Index]);
2209 Status = EFI_ABORTED;
2210 goto Exit;
2211 } else {
2212 //
2213 // FV Size is AUTO, increase by one one block
2214 //
2215 Status = ReallocateFvImage (FvImage, FvInfo, VtfFileImage, FvImageCapacity);
2216 if (EFI_ERROR (Status)) {
2217 Error (NULL, 0, 0, FvInfo->FvFiles[Index], "insufficient resources to add the file");
2218 goto Exit;
2219 }
2220 }
2221 }
2222
2223 //
2224 // Copy the file
2225 //
2226 memcpy (FvImage->CurrentFilePointer, FileBuffer, FileSize);
2227
2228 //
2229 // If the file is XIP, rebase
2230 //
2231 CurrentFileBaseAddress = FvInfo->BaseAddress + ((UINTN) FvImage->CurrentFilePointer - (UINTN) FvImage->FileImage);
2232 //
2233 // Status = RebaseFfsFile ((EFI_FFS_FILE_HEADER*) FvImage->CurrentFilePointer, CurrentFileBaseAddress);
2234 // if (EFI_ERROR(Status)) {
2235 // printf ("ERROR: Could not rebase the file %s.\n", FvInfo->FvFiles[Index]);
2236 // return EFI_ABORTED;
2237 // }
2238 //
2239 // Update Symbol file
2240 //
2241 Status = AddSymFile (
2242 CurrentFileBaseAddress,
2243 (EFI_FFS_FILE_HEADER *) FvImage->CurrentFilePointer,
2244 SymImage,
2245 FvInfo->FvFiles[Index]
2246 );
2247 assert (!EFI_ERROR (Status));
2248
2249 //
2250 // Update the current pointer in the FV image
2251 //
2252 FvImage->CurrentFilePointer += FileSize;
2253
2254 //
2255 // Make next file start at QWord Boundry
2256 //
2257 while (((UINTN) FvImage->CurrentFilePointer & 0x07) != 0) {
2258 FvImage->CurrentFilePointer++;
2259 }
2260
2261 Exit:
2262 //
2263 // Free allocated memory.
2264 //
2265 free (FileBuffer);
2266 return Status;
2267 }
2268
2269 EFI_STATUS
2270 AddVariableBlock (
2271 IN UINT8 *FvImage,
2272 IN UINTN Size,
2273 IN FV_INFO *FvInfo
2274 )
2275 {
2276 EFI_FIRMWARE_VOLUME_HEADER *FvHeader;
2277 VARIABLE_STORE_HEADER *VarStoreHeader;
2278 //
2279 // Variable block should exclude FvHeader. Since the length of
2280 // FvHeader depends on the block map, which is variable length,
2281 // we could only decide the actual variable block length here.
2282 //
2283 FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) FvImage;
2284 FvImage = FvImage + FvHeader->HeaderLength;
2285
2286 VarStoreHeader = (VARIABLE_STORE_HEADER *) FvImage;
2287
2288 VarStoreHeader->Signature = VARIABLE_STORE_SIGNATURE;
2289 VarStoreHeader->Size = Size - FvHeader->HeaderLength;
2290 VarStoreHeader->Format = VARIABLE_STORE_FORMATTED;
2291 VarStoreHeader->State = VARIABLE_STORE_HEALTHY;
2292 VarStoreHeader->Reserved = 0;
2293 VarStoreHeader->Reserved1 = 0;
2294
2295 return EFI_SUCCESS;
2296 }
2297
2298 EFI_STATUS
2299 AddEventLogBlock (
2300 IN UINT8 *FvImage,
2301 IN UINTN Size,
2302 IN FV_INFO *FvInfo
2303 )
2304 {
2305 return EFI_SUCCESS;
2306 }
2307
2308 EFI_STATUS
2309 AddFTWWorkingBlock (
2310 IN UINT8 *FvImage,
2311 IN UINTN Size,
2312 IN FV_INFO *FvInfo
2313 )
2314 {
2315 EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *FTWHeader;
2316 UINT32 Crc32;
2317
2318 Crc32 = 0;
2319 FTWHeader = (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *) FvImage;
2320 memcpy (&FTWHeader->Signature, &(FvInfo->FvGuid), sizeof (EFI_GUID));
2321 FTWHeader->WriteQueueSize = Size - sizeof (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER);
2322 CalculateCrc32 (FvImage, sizeof (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER), &Crc32);
2323 FTWHeader->Crc = Crc32;
2324 if (FvInfo->FvAttributes & EFI_FVB_ERASE_POLARITY) {
2325 FTWHeader->WorkingBlockValid = 0;
2326 FTWHeader->WorkingBlockInvalid = 1;
2327 } else {
2328 FTWHeader->WorkingBlockValid = 1;
2329 FTWHeader->WorkingBlockInvalid = 0;
2330 }
2331
2332 return EFI_SUCCESS;
2333 }
2334
2335 EFI_STATUS
2336 AddFTWSpareBlock (
2337 IN UINT8 *FvImage,
2338 IN UINTN Size,
2339 IN FV_INFO *FvInfo
2340 )
2341 {
2342 return EFI_SUCCESS;
2343 }
2344
2345 EFI_STATUS
2346 GenNonFFSFv (
2347 IN UINT8 *FvImage,
2348 IN FV_INFO *FvInfo
2349 )
2350 /*++
2351
2352 Routine Description:
2353
2354 This function generate the non FFS FV image, such as the working block
2355 and spare block. How each component of the FV is built is component
2356 specific.
2357
2358 Arguments:
2359
2360 FvImage The memory image of the FV to add it to. The current offset
2361 must be valid.
2362 FvInfo Pointer to information about the FV.
2363
2364 Returns:
2365
2366 EFI_SUCCESS The function completed successfully.
2367 EFI_INVALID_PARAMETER One of the input parameters was invalid.
2368 EFI_ABORTED An error occurred.
2369 EFI_OUT_OF_RESOURCES Insufficient resources exist to complete the add.
2370
2371 --*/
2372 {
2373 UINTN Index;
2374 EFI_FIRMWARE_VOLUME_HEADER *FvHeader;
2375 UINT64 TotalSize;
2376
2377 FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) FvImage;
2378 TotalSize = 0;
2379
2380 for (Index = 0; FvInfo->FvComponents[Index].Size != 0; Index++) {
2381 if (_stricmp (FvInfo->FvComponents[Index].ComponentName, EFI_NV_VARIABLE_STRING) == 0) {
2382 AddVariableBlock (FvImage, FvInfo->FvComponents[Index].Size, FvInfo);
2383 } else if (_stricmp (FvInfo->FvComponents[Index].ComponentName, EFI_NV_EVENT_LOG_STRING) == 0) {
2384 AddEventLogBlock (FvImage, FvInfo->FvComponents[Index].Size, FvInfo);
2385 } else if (_stricmp (FvInfo->FvComponents[Index].ComponentName, EFI_NV_FTW_WORKING_STRING) == 0) {
2386 AddFTWWorkingBlock (FvImage, FvInfo->FvComponents[Index].Size, FvInfo);
2387 } else if (_stricmp (FvInfo->FvComponents[Index].ComponentName, EFI_NV_FTW_SPARE_STRING) == 0) {
2388 AddFTWSpareBlock (FvImage, FvInfo->FvComponents[Index].Size, FvInfo);
2389 } else {
2390 printf ("Warning: Unknown Non-FFS block %s \n", FvInfo->FvComponents[Index].ComponentName);
2391 }
2392
2393 FvImage = FvImage + FvInfo->FvComponents[Index].Size;
2394 TotalSize = TotalSize + FvInfo->FvComponents[Index].Size;
2395 }
2396 //
2397 // Index and TotalSize is zero mean there's no component, so this is an empty fv
2398 //
2399 if ((Index != 0 || TotalSize != 0) && TotalSize != FvInfo->Size) {
2400 printf ("Error. Component size does not sum up to FV size.\n");
2401 return EFI_ABORTED;
2402 }
2403
2404 return EFI_SUCCESS;
2405 }
2406
2407 EFI_STATUS
2408 PadFvImage (
2409 IN MEMORY_FILE *FvImage,
2410 IN EFI_FFS_FILE_HEADER *VtfFileImage
2411 )
2412 /*++
2413
2414 Routine Description:
2415
2416 This function places a pad file between the last file in the FV and the VTF
2417 file if the VTF file exists.
2418
2419 Arguments:
2420
2421 FvImage Memory file for the FV memory image
2422 VtfFileImage The address of the VTF file. If this is the end of the FV
2423 image, no VTF exists and no pad file is needed.
2424
2425 Returns:
2426
2427 EFI_SUCCESS Completed successfully.
2428 EFI_INVALID_PARAMETER One of the input parameters was NULL.
2429
2430 --*/
2431 {
2432 EFI_FFS_FILE_HEADER *PadFile;
2433 UINTN FileSize;
2434
2435 //
2436 // If there is no VTF or the VTF naturally follows the previous file without a
2437 // pad file, then there's nothing to do
2438 //
2439 if ((UINTN) VtfFileImage == (UINTN) FvImage->Eof || (void *) FvImage->CurrentFilePointer == (void *) VtfFileImage) {
2440 return EFI_SUCCESS;
2441 }
2442 //
2443 // Pad file starts at beginning of free space
2444 //
2445 PadFile = (EFI_FFS_FILE_HEADER *) FvImage->CurrentFilePointer;
2446
2447 //
2448 // write header
2449 //
2450 memset (PadFile, 0, sizeof (EFI_FFS_FILE_HEADER));
2451 memcpy (&PadFile->Name, &DefaultFvPadFileNameGuid, sizeof (EFI_GUID));
2452 PadFile->Type = EFI_FV_FILETYPE_FFS_PAD;
2453 PadFile->Attributes = 0;
2454
2455 //
2456 // FileSize includes the EFI_FFS_FILE_HEADER
2457 //
2458 FileSize = (UINTN) VtfFileImage - (UINTN) FvImage->CurrentFilePointer;
2459 PadFile->Size[0] = (UINT8) (FileSize & 0x000000FF);
2460 PadFile->Size[1] = (UINT8) ((FileSize & 0x0000FF00) >> 8);
2461 PadFile->Size[2] = (UINT8) ((FileSize & 0x00FF0000) >> 16);
2462
2463 //
2464 // Fill in checksums and state, must be zero during checksum calculation.
2465 //
2466 PadFile->IntegrityCheck.Checksum.Header = 0;
2467 PadFile->IntegrityCheck.Checksum.File = 0;
2468 PadFile->State = 0;
2469 PadFile->IntegrityCheck.Checksum.Header = CalculateChecksum8 ((UINT8 *) PadFile, sizeof (EFI_FFS_FILE_HEADER));
2470 if (PadFile->Attributes & FFS_ATTRIB_CHECKSUM) {
2471 #if (PI_SPECIFICATION_VERSION < 0x00010000)
2472 PadFile->IntegrityCheck.Checksum.File = CalculateChecksum8 ((UINT8 *) PadFile, FileSize);
2473 #else
2474 PadFile->IntegrityCheck.Checksum.File = CalculateChecksum8 ((UINT8 *) ((UINTN) PadFile + sizeof (EFI_FFS_FILE_HEADER)), FileSize - sizeof (EFI_FFS_FILE_HEADER));
2475 #endif
2476 } else {
2477 PadFile->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM;
2478 }
2479
2480 PadFile->State = EFI_FILE_HEADER_CONSTRUCTION | EFI_FILE_HEADER_VALID | EFI_FILE_DATA_VALID;
2481
2482 UpdateFfsFileState (
2483 (EFI_FFS_FILE_HEADER *) PadFile,
2484 (EFI_FIRMWARE_VOLUME_HEADER *) FvImage->FileImage
2485 );
2486 //
2487 // Update the current FV pointer
2488 //
2489 FvImage->CurrentFilePointer = FvImage->Eof;
2490
2491 return EFI_SUCCESS;
2492 }
2493
2494 EFI_STATUS
2495 UpdateResetVector (
2496 IN MEMORY_FILE *FvImage,
2497 IN FV_INFO *FvInfo,
2498 IN EFI_FFS_FILE_HEADER *VtfFile
2499 )
2500 /*++
2501
2502 Routine Description:
2503
2504 This parses the FV looking for the PEI core and then plugs the address into
2505 the SALE_ENTRY point of the BSF/VTF for IPF and does BUGBUG TBD action to
2506 complete an IA32 Bootstrap FV.
2507
2508 Arguments:
2509
2510 FvImage Memory file for the FV memory image
2511 FvInfo Information read from INF file.
2512 VtfFile Pointer to the VTF file in the FV image.
2513
2514 Returns:
2515
2516 EFI_SUCCESS Function Completed successfully.
2517 EFI_ABORTED Error encountered.
2518 EFI_INVALID_PARAMETER A required parameter was NULL.
2519 EFI_NOT_FOUND PEI Core file not found.
2520
2521 --*/
2522 {
2523 EFI_FFS_FILE_HEADER *PeiCoreFile;
2524 EFI_FFS_FILE_HEADER *SecCoreFile;
2525 EFI_STATUS Status;
2526 EFI_FILE_SECTION_POINTER Pe32Section;
2527 UINT32 EntryPoint;
2528 UINT32 BaseOfCode;
2529 UINT16 MachineType;
2530 EFI_PHYSICAL_ADDRESS PeiCorePhysicalAddress;
2531 EFI_PHYSICAL_ADDRESS SecCorePhysicalAddress;
2532 EFI_PHYSICAL_ADDRESS *SecCoreEntryAddressPtr;
2533 UINT32 *Ia32ResetAddressPtr;
2534 UINT8 *BytePointer;
2535 UINT8 *BytePointer2;
2536 UINT16 *WordPointer;
2537 UINT16 CheckSum;
2538 UINTN Index;
2539 EFI_FFS_FILE_STATE SavedState;
2540 UINT32 TailSize;
2541 UINT64 FitAddress;
2542 FIT_TABLE *FitTablePtr;
2543 #if (PI_SPECIFICATION_VERSION < 0x00010000)
2544 EFI_FFS_FILE_TAIL TailValue;
2545 #endif
2546 //
2547 // Verify input parameters
2548 //
2549 if (FvImage == NULL || FvInfo == NULL || VtfFile == NULL) {
2550 return EFI_INVALID_PARAMETER;
2551 }
2552 //
2553 // Initialize FV library
2554 //
2555 InitializeFvLib (FvImage->FileImage, (UINTN) FvImage->Eof - (UINTN) FvImage->FileImage);
2556
2557 //
2558 // Verify VTF file
2559 //
2560 Status = VerifyFfsFile (VtfFile);
2561 if (EFI_ERROR (Status)) {
2562 return EFI_INVALID_PARAMETER;
2563 }
2564 //
2565 // Find the PEI Core
2566 //
2567 Status = GetFileByType (EFI_FV_FILETYPE_PEI_CORE, 1, &PeiCoreFile);
2568 if (EFI_ERROR (Status) || PeiCoreFile == NULL) {
2569 Error (NULL, 0, 0, "could not find the PEI core in the FV", NULL);
2570 return EFI_ABORTED;
2571 }
2572 //
2573 // PEI Core found, now find PE32 or TE section
2574 //
2575 Status = GetSectionByType (PeiCoreFile, EFI_SECTION_PE32, 1, &Pe32Section);
2576 if (Status == EFI_NOT_FOUND) {
2577 Status = GetSectionByType (PeiCoreFile, EFI_SECTION_TE, 1, &Pe32Section);
2578 }
2579
2580 if (EFI_ERROR (Status)) {
2581 Error (NULL, 0, 0, "could not find PE32 or TE section in PEI core file", NULL);
2582 return EFI_ABORTED;
2583 }
2584
2585 Status = GetPe32Info (
2586 (VOID *) ((UINTN) Pe32Section.Pe32Section + sizeof (EFI_SECTION_PE32)),
2587 &EntryPoint,
2588 &BaseOfCode,
2589 &MachineType
2590 );
2591
2592 if (EFI_ERROR (Status)) {
2593 Error (NULL, 0, 0, "could not get PE32 entry point for PEI core", NULL);
2594 return EFI_ABORTED;
2595 }
2596 //
2597 // Physical address is FV base + offset of PE32 + offset of the entry point
2598 //
2599 PeiCorePhysicalAddress = FvInfo->BaseAddress;
2600 PeiCorePhysicalAddress += (UINTN) Pe32Section.Pe32Section + sizeof (EFI_SECTION_PE32) - (UINTN) FvImage->FileImage;
2601 PeiCorePhysicalAddress += EntryPoint;
2602
2603 if (MachineType == EFI_IMAGE_MACHINE_IA64) {
2604 //
2605 // Update PEI_CORE address
2606 //
2607 //
2608 // Set the uncached attribute bit in the physical address
2609 //
2610 PeiCorePhysicalAddress |= 0x8000000000000000;
2611
2612 //
2613 // Check if address is aligned on a 16 byte boundary
2614 //
2615 if (PeiCorePhysicalAddress & 0xF) {
2616 printf (
2617 "ERROR: PEI_CORE entry point is not aligned on a 16 byte boundary, address specified is %Xh.\n",
2618 PeiCorePhysicalAddress
2619 );
2620 return EFI_ABORTED;
2621 }
2622 //
2623 // First Get the FIT table address
2624 //
2625 FitAddress = (*(UINT64 *) (FvImage->Eof - IPF_FIT_ADDRESS_OFFSET)) & 0xFFFFFFFF;
2626
2627 FitTablePtr = (FIT_TABLE *) (FvImage->FileImage + (FitAddress - FvInfo->BaseAddress));
2628
2629 Status = UpdatePeiCoreEntryInFit (FitTablePtr, PeiCorePhysicalAddress);
2630
2631 if (!EFI_ERROR (Status)) {
2632 UpdateFitCheckSum (FitTablePtr);
2633 }
2634 //
2635 // Find the Sec Core
2636 //
2637 Status = GetFileByType (EFI_FV_FILETYPE_SECURITY_CORE, 1, &SecCoreFile);
2638 if (EFI_ERROR (Status) || SecCoreFile == NULL) {
2639 Error (NULL, 0, 0, "could not find the Sec core in the FV", NULL);
2640 return EFI_ABORTED;
2641 }
2642 //
2643 // Sec Core found, now find PE32 section
2644 //
2645 Status = GetSectionByType (SecCoreFile, EFI_SECTION_PE32, 1, &Pe32Section);
2646 if (EFI_ERROR (Status)) {
2647 Error (NULL, 0, 0, "could not find PE32 section in SEC core file", NULL);
2648 return EFI_ABORTED;
2649 }
2650
2651 Status = GetPe32Info (
2652 (VOID *) ((UINTN) Pe32Section.Pe32Section + sizeof (EFI_SECTION_PE32)),
2653 &EntryPoint,
2654 &BaseOfCode,
2655 &MachineType
2656 );
2657 if (EFI_ERROR (Status)) {
2658 Error (NULL, 0, 0, "could not get PE32 entry point for SEC core", NULL);
2659 return EFI_ABORTED;
2660 }
2661 //
2662 // Physical address is FV base + offset of PE32 + offset of the entry point
2663 //
2664 SecCorePhysicalAddress = FvInfo->BaseAddress;
2665 SecCorePhysicalAddress += (UINTN) Pe32Section.Pe32Section + sizeof (EFI_SECTION_PE32) - (UINTN) FvImage->FileImage;
2666 SecCorePhysicalAddress += EntryPoint;
2667
2668 //
2669 // Update SEC_CORE address
2670 //
2671 //
2672 // Set the uncached attribute bit in the physical address
2673 //
2674 SecCorePhysicalAddress |= 0x8000000000000000;
2675
2676 //
2677 // Update the address
2678 //
2679 SecCoreEntryAddressPtr = (EFI_PHYSICAL_ADDRESS *) ((UINTN) FvImage->Eof - IPF_SALE_ENTRY_ADDRESS_OFFSET);
2680 *SecCoreEntryAddressPtr = SecCorePhysicalAddress;
2681
2682 //
2683 // Check if address is aligned on a 16 byte boundary
2684 //
2685 if (SecCorePhysicalAddress & 0xF) {
2686 printf (
2687 "ERROR: SALE_ENTRY entry point is not aligned on a 16 byte boundary, address specified is %Xh.\n",
2688 SecCorePhysicalAddress
2689 );
2690 return EFI_ABORTED;
2691 }
2692 } else if ((MachineType == EFI_IMAGE_MACHINE_IA32) ||
2693 (MachineType == EFI_IMAGE_MACHINE_X64)) {
2694 //
2695 // Get the location to update
2696 //
2697 Ia32ResetAddressPtr = (UINT32 *) ((UINTN) FvImage->Eof - IA32_PEI_CORE_ENTRY_OFFSET);
2698
2699 //
2700 // Write lower 32 bits of physical address
2701 //
2702 *Ia32ResetAddressPtr = (UINT32) PeiCorePhysicalAddress;
2703
2704 //
2705 // Update the BFV base address
2706 //
2707 Ia32ResetAddressPtr = (UINT32 *) ((UINTN) FvImage->Eof - 4);
2708 *Ia32ResetAddressPtr = (UINT32) (FvInfo->BaseAddress);
2709
2710 CheckSum = 0x0000;
2711
2712 //
2713 // Update the Startup AP in the FVH header block ZeroVector region.
2714 //
2715 BytePointer = (UINT8 *) ((UINTN) FvImage->FileImage);
2716 BytePointer2 = (FvInfo->Size == 0x10000) ? m64kRecoveryStartupApDataArray : m128kRecoveryStartupApDataArray;
2717 for (Index = 0; Index < SIZEOF_STARTUP_DATA_ARRAY; Index++) {
2718 *BytePointer++ = *BytePointer2++;
2719 }
2720 //
2721 // Calculate the checksum
2722 //
2723 WordPointer = (UINT16 *) ((UINTN) FvImage->FileImage);
2724 for (Index = 0; Index < SIZEOF_STARTUP_DATA_ARRAY / 2; Index++) {
2725 CheckSum = (UINT16) (CheckSum + ((UINT16) *WordPointer));
2726 WordPointer++;
2727 }
2728 //
2729 // Update the checksum field
2730 //
2731 BytePointer = (UINT8 *) ((UINTN) FvImage->FileImage);
2732 BytePointer += (SIZEOF_STARTUP_DATA_ARRAY - 2);
2733 WordPointer = (UINT16 *) BytePointer;
2734 *WordPointer = (UINT16) (0x10000 - (UINT32) CheckSum);
2735 } else {
2736 Error (NULL, 0, 0, "invalid machine type in PEI core", "machine type=0x%X", (UINT32) MachineType);
2737 return EFI_ABORTED;
2738 }
2739 //
2740 // Determine if it has an FFS file tail.
2741 //
2742 if (VtfFile->Attributes & FFS_ATTRIB_TAIL_PRESENT) {
2743 TailSize = sizeof (EFI_FFS_FILE_TAIL);
2744 } else {
2745 TailSize = 0;
2746 }
2747 //
2748 // Now update file checksum
2749 //
2750 SavedState = VtfFile->State;
2751 VtfFile->IntegrityCheck.Checksum.File = 0;
2752 VtfFile->State = 0;
2753 if (VtfFile->Attributes & FFS_ATTRIB_CHECKSUM) {
2754 #if (PI_SPECIFICATION_VERSION < 0x00010000)
2755 VtfFile->IntegrityCheck.Checksum.File = CalculateChecksum8 (
2756 (UINT8 *) VtfFile,
2757 GetLength (VtfFile->Size) - TailSize
2758 );
2759
2760 #else
2761 VtfFile->IntegrityCheck.Checksum.File = CalculateChecksum8 (
2762 (UINT8 *) ((UINTN)VtfFile + sizeof (EFI_FFS_FILE_HEADER)),
2763 GetLength (VtfFile->Size) - TailSize - sizeof (EFI_FFS_FILE_HEADER)
2764 );
2765 #endif
2766 } else {
2767 VtfFile->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM;
2768 }
2769
2770 VtfFile->State = SavedState;
2771
2772 #if (PI_SPECIFICATION_VERSION < 0x00010000)
2773 //
2774 // Update tail if present
2775 //
2776 if (VtfFile->Attributes & FFS_ATTRIB_TAIL_PRESENT) {
2777 TailValue = (EFI_FFS_FILE_TAIL) (~(VtfFile->IntegrityCheck.TailReference));
2778 *(EFI_FFS_FILE_TAIL *) (((UINTN) (VtfFile) + GetLength (VtfFile->Size) - sizeof (EFI_FFS_FILE_TAIL))) = TailValue;
2779 }
2780 #endif
2781 return EFI_SUCCESS;
2782 }
2783
2784 EFI_STATUS
2785 GetPe32Info (
2786 IN UINT8 *Pe32,
2787 OUT UINT32 *EntryPoint,
2788 OUT UINT32 *BaseOfCode,
2789 OUT UINT16 *MachineType
2790 )
2791 /*++
2792
2793 Routine Description:
2794
2795 Retrieves the PE32 entry point offset and machine type from PE image or TE image.
2796 See EfiImage.h for machine types. The entry point offset is from the beginning
2797 of the PE32 buffer passed in.
2798
2799 Arguments:
2800
2801 Pe32 Beginning of the PE32.
2802 EntryPoint Offset from the beginning of the PE32 to the image entry point.
2803 BaseOfCode Base address of code.
2804 MachineType Magic number for the machine type.
2805
2806 Returns:
2807
2808 EFI_SUCCESS Function completed successfully.
2809 EFI_ABORTED Error encountered.
2810 EFI_INVALID_PARAMETER A required parameter was NULL.
2811 EFI_UNSUPPORTED The operation is unsupported.
2812
2813 --*/
2814 {
2815 EFI_IMAGE_DOS_HEADER *DosHeader;
2816 EFI_IMAGE_NT_HEADERS *NtHeader;
2817 EFI_TE_IMAGE_HEADER *TeHeader;
2818
2819 //
2820 // Verify input parameters
2821 //
2822 if (Pe32 == NULL) {
2823 return EFI_INVALID_PARAMETER;
2824 }
2825
2826 //
2827 // First check whether it is one TE Image.
2828 //
2829 TeHeader = (EFI_TE_IMAGE_HEADER *) Pe32;
2830 if (TeHeader->Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) {
2831 //
2832 // By TeImage Header to get output
2833 //
2834 *EntryPoint = TeHeader->AddressOfEntryPoint + sizeof (EFI_TE_IMAGE_HEADER) - TeHeader->StrippedSize;
2835 *BaseOfCode = TeHeader->BaseOfCode + sizeof (EFI_TE_IMAGE_HEADER) - TeHeader->StrippedSize;
2836 *MachineType = TeHeader->Machine;
2837 } else {
2838 //
2839 // Then check whether
2840 // is the DOS header
2841 //
2842 DosHeader = (EFI_IMAGE_DOS_HEADER *) Pe32;
2843
2844 //
2845 // Verify DOS header is expected
2846 //
2847 if (DosHeader->e_magic != EFI_IMAGE_DOS_SIGNATURE) {
2848 printf ("ERROR: Unknown magic number in the DOS header, 0x%04X.\n", DosHeader->e_magic);
2849 return EFI_UNSUPPORTED;
2850 }
2851 //
2852 // Immediately following is the NT header.
2853 //
2854 NtHeader = (EFI_IMAGE_NT_HEADERS *) ((UINTN) Pe32 + DosHeader->e_lfanew);
2855
2856 //
2857 // Verify NT header is expected
2858 //
2859 if (NtHeader->Signature != EFI_IMAGE_NT_SIGNATURE) {
2860 printf ("ERROR: Unrecognized image signature 0x%08X.\n", NtHeader->Signature);
2861 return EFI_UNSUPPORTED;
2862 }
2863 //
2864 // Get output
2865 //
2866 *EntryPoint = NtHeader->OptionalHeader.AddressOfEntryPoint;
2867 *BaseOfCode = NtHeader->OptionalHeader.BaseOfCode;
2868 *MachineType = NtHeader->FileHeader.Machine;
2869 }
2870
2871 //
2872 // Verify machine type is supported
2873 //
2874 if (*MachineType != EFI_IMAGE_MACHINE_IA32 &&
2875 *MachineType != EFI_IMAGE_MACHINE_IA64 &&
2876 *MachineType != EFI_IMAGE_MACHINE_X64) {
2877 printf ("ERROR: Unrecognized machine type in the PE32 file.\n");
2878 return EFI_UNSUPPORTED;
2879 }
2880
2881 return EFI_SUCCESS;
2882 }
2883 //
2884 // Exposed function implementations (prototypes are defined in GenFvImageLib.h)
2885 //
2886 EFI_STATUS
2887 GenerateFvImage (
2888 IN CHAR8 *InfFileImage,
2889 IN UINTN InfFileSize,
2890 OUT UINT8 **FvImage,
2891 OUT UINTN *FvImageSize,
2892 OUT CHAR8 **FvFileName,
2893 OUT UINT8 **SymImage,
2894 OUT UINTN *SymImageSize,
2895 OUT CHAR8 **SymFileName
2896 )
2897 /*++
2898
2899 Routine Description:
2900
2901 This is the main function which will be called from application.
2902
2903 Arguments:
2904
2905 InfFileImage Buffer containing the INF file contents.
2906 InfFileSize Size of the contents of the InfFileImage buffer.
2907 FvImage Pointer to the FV image created.
2908 FvImageSize Size of the FV image created and pointed to by FvImage.
2909 FvFileName Requested name for the FV file.
2910 SymImage Pointer to the Sym image created.
2911 SymImageSize Size of the Sym image created and pointed to by SymImage.
2912 SymFileName Requested name for the Sym file.
2913
2914 Returns:
2915
2916 EFI_SUCCESS Function completed successfully.
2917 EFI_OUT_OF_RESOURCES Could not allocate required resources.
2918 EFI_ABORTED Error encountered.
2919 EFI_INVALID_PARAMETER A required parameter was NULL.
2920
2921 --*/
2922 {
2923 EFI_STATUS Status;
2924 MEMORY_FILE InfMemoryFile;
2925 MEMORY_FILE FvImageMemoryFile;
2926 MEMORY_FILE SymImageMemoryFile;
2927 FV_INFO FvInfo;
2928 UINTN Index;
2929 EFI_FIRMWARE_VOLUME_HEADER *FvHeader;
2930 EFI_FFS_FILE_HEADER *VtfFileImage;
2931 UINTN FvImageCapacity;
2932
2933 //
2934 // Check for invalid parameter
2935 //
2936 if (InfFileImage == NULL || FvImage == NULL || FvImageSize == NULL || FvFileName == NULL) {
2937 return EFI_INVALID_PARAMETER;
2938 }
2939 //
2940 // Initialize file structures
2941 //
2942 InfMemoryFile.FileImage = InfFileImage;
2943 InfMemoryFile.CurrentFilePointer = InfFileImage;
2944 InfMemoryFile.Eof = InfFileImage + InfFileSize;
2945
2946 //
2947 // Parse the FV inf file for header information
2948 //
2949 Status = ParseFvInf (&InfMemoryFile, &FvInfo);
2950 if (EFI_ERROR (Status)) {
2951 printf ("ERROR: Could not parse the input INF file.\n");
2952 return EFI_ABORTED;
2953 }
2954 //
2955 // Update the file name return values
2956 //
2957 strcpy (*FvFileName, FvInfo.FvName);
2958 strcpy (*SymFileName, FvInfo.SymName);
2959
2960 //
2961 // Calculate the FV size
2962 //
2963 if (FvInfo.Size != (UINTN) -1) {
2964 *FvImageSize = FvInfo.Size;
2965 FvImageCapacity = FvInfo.Size;
2966 } else {
2967 //
2968 // For auto size, set default as one block
2969 //
2970 FvInfo.FvBlocks[0].NumBlocks = 1;
2971 *FvImageSize = FvInfo.FvBlocks[0].BlockLength;
2972 FvImageCapacity = FV_CAPACITY_INCREASE_UNIT;
2973 }
2974
2975 //
2976 // Allocate the FV
2977 //
2978 *FvImage = malloc (FvImageCapacity);
2979 if (*FvImage == NULL) {
2980 return EFI_OUT_OF_RESOURCES;
2981 }
2982 //
2983 // Allocate space for symbol file storage
2984 //
2985 *SymImage = malloc (SYMBOL_FILE_SIZE);
2986 if (*SymImage == NULL) {
2987 return EFI_OUT_OF_RESOURCES;
2988 }
2989 //
2990 // Initialize the FV to the erase polarity
2991 //
2992 if (FvInfo.FvAttributes & EFI_FVB_ERASE_POLARITY) {
2993 memset (*FvImage, -1, FvImageCapacity);
2994 } else {
2995 memset (*FvImage, 0, FvImageCapacity);
2996 }
2997 //
2998 // Initialize FV header
2999 //
3000 FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) *FvImage;
3001
3002 //
3003 // Initialize the zero vector to all zeros.
3004 //
3005 memset (FvHeader->ZeroVector, 0, 16);
3006
3007 //
3008 // Copy the FFS GUID
3009 //
3010 memcpy (&FvHeader->FileSystemGuid, &FvInfo.FvGuid, sizeof (EFI_GUID));
3011
3012 FvHeader->FvLength = *FvImageSize;
3013 FvHeader->Signature = EFI_FVH_SIGNATURE;
3014 FvHeader->Attributes = FvInfo.FvAttributes;
3015 #if (PI_SPECIFICATION_VERSION < 0x00010000)
3016 FvHeader->Revision = EFI_FVH_REVISION;
3017 FvHeader->Reserved[0] = 0;
3018 FvHeader->Reserved[1] = 0;
3019 FvHeader->Reserved[2] = 0;
3020 #else
3021 FvHeader->Revision = EFI_FVH_PI_REVISION;
3022 FvHeader->ExtHeaderOffset = 0;
3023 FvHeader->Reserved[0] = 0;
3024 #endif
3025 //
3026 // Copy firmware block map
3027 //
3028 for (Index = 0; FvInfo.FvBlocks[Index].NumBlocks != 0; Index++) {
3029 FvHeader->FvBlockMap[Index].NumBlocks = FvInfo.FvBlocks[Index].NumBlocks;
3030 FvHeader->FvBlockMap[Index].BlockLength = FvInfo.FvBlocks[Index].BlockLength;
3031 }
3032 //
3033 // Add block map terminator
3034 //
3035 FvHeader->FvBlockMap[Index].NumBlocks = 0;
3036 FvHeader->FvBlockMap[Index].BlockLength = 0;
3037
3038 //
3039 // Complete the header
3040 //
3041 FvHeader->HeaderLength = (UINT16) (((UINTN) &(FvHeader->FvBlockMap[Index + 1])) - (UINTN) *FvImage);
3042 FvHeader->Checksum = 0;
3043 FvHeader->Checksum = CalculateChecksum16 ((UINT16 *) FvHeader, FvHeader->HeaderLength / sizeof (UINT16));
3044
3045 //
3046 // If there is no FFS file, find and generate each components of the FV
3047 //
3048 if (FvInfo.FvFiles[0][0] == 0) {
3049 Status = GenNonFFSFv (*FvImage, &FvInfo);
3050 if (EFI_ERROR (Status)) {
3051 printf ("ERROR: Could not generate NonFFS FV.\n");
3052 free (*FvImage);
3053 return EFI_ABORTED;
3054 }
3055
3056 return EFI_SUCCESS;
3057 }
3058 //
3059 // Initialize our "file" view of the buffer
3060 //
3061 FvImageMemoryFile.FileImage = *FvImage;
3062 FvImageMemoryFile.CurrentFilePointer = *FvImage + FvHeader->HeaderLength;
3063 FvImageMemoryFile.Eof = *FvImage +*FvImageSize;
3064
3065 //
3066 // Initialize our "file" view of the symbol file.
3067 //
3068 SymImageMemoryFile.FileImage = *SymImage;
3069 SymImageMemoryFile.CurrentFilePointer = *SymImage;
3070 SymImageMemoryFile.Eof = *FvImage + SYMBOL_FILE_SIZE;
3071
3072 //
3073 // Initialize the FV library.
3074 //
3075 InitializeFvLib (FvImageMemoryFile.FileImage, *FvImageSize);
3076
3077 //
3078 // Files start on 8 byte alignments, so move to the next 8 byte aligned
3079 // address. For now, just assert if it isn't. Currently FV header is
3080 // always a multiple of 8 bytes.
3081 // BUGBUG: Handle this better
3082 //
3083 assert ((((UINTN) FvImageMemoryFile.CurrentFilePointer) % 8) == 0);
3084
3085 //
3086 // Initialize the VTF file address.
3087 //
3088 VtfFileImage = (EFI_FFS_FILE_HEADER *) FvImageMemoryFile.Eof;
3089
3090 //
3091 // Add files to FV
3092 //
3093 for (Index = 0; FvInfo.FvFiles[Index][0] != 0; Index++) {
3094 //
3095 // Add the file
3096 //
3097 Status = AddFile (&FvImageMemoryFile, &FvInfo, Index, &VtfFileImage, &SymImageMemoryFile, &FvImageCapacity);
3098
3099 //
3100 // Update FvImageSize and FvImage as they may be changed in AddFile routine
3101 //
3102 if (FvInfo.Size == (UINTN) -1) {
3103 *FvImageSize = FvInfo.FvBlocks[0].NumBlocks * FvInfo.FvBlocks[0].BlockLength;
3104 *FvImage = FvImageMemoryFile.FileImage;
3105 }
3106
3107 //
3108 // Exit if error detected while adding the file
3109 //
3110 if (EFI_ERROR (Status)) {
3111 printf ("ERROR: Could not add file %s.\n", FvInfo.FvFiles[Index]);
3112 free (*FvImage);
3113 return EFI_ABORTED;
3114 }
3115 }
3116 //
3117 // If there is a VTF file, some special actions need to occur.
3118 //
3119 if ((UINTN) VtfFileImage != (UINTN) FvImageMemoryFile.Eof) {
3120 //
3121 // Pad from the end of the last file to the beginning of the VTF file.
3122 //
3123 Status = PadFvImage (&FvImageMemoryFile, VtfFileImage);
3124 if (EFI_ERROR (Status)) {
3125 printf ("ERROR: Could not create the pad file between the last file and the VTF file.\n");
3126 free (*FvImage);
3127 return EFI_ABORTED;
3128 }
3129 //
3130 // Update reset vector (SALE_ENTRY for IPF)
3131 // Now for IA32 and IA64 platform, the fv which has bsf file must have the
3132 // EndAddress of 0xFFFFFFFF. Thus, only this type fv needs to update the
3133 // reset vector. If the PEI Core is found, the VTF file will probably get
3134 // corrupted by updating the entry point.
3135 //
3136 if ((FvInfo.BaseAddress + *FvImageSize) == FV_IMAGES_TOP_ADDRESS) {
3137 Status = UpdateResetVector (&FvImageMemoryFile, &FvInfo, VtfFileImage);
3138 if (EFI_ERROR(Status)) {
3139 printf ("ERROR: Could not update the reset vector.\n");
3140 free (*FvImage);
3141 return EFI_ABORTED;
3142 }
3143 }
3144 }
3145 //
3146 // Determine final Sym file size
3147 //
3148 *SymImageSize = SymImageMemoryFile.CurrentFilePointer - SymImageMemoryFile.FileImage;
3149
3150 return EFI_SUCCESS;
3151 }
3152
3153 EFI_STATUS
3154 UpdatePeiCoreEntryInFit (
3155 IN FIT_TABLE *FitTablePtr,
3156 IN UINT64 PeiCorePhysicalAddress
3157 )
3158 /*++
3159
3160 Routine Description:
3161
3162 This function is used to update the Pei Core address in FIT, this can be used by Sec core to pass control from
3163 Sec to Pei Core
3164
3165 Arguments:
3166
3167 FitTablePtr - The pointer of FIT_TABLE.
3168 PeiCorePhysicalAddress - The address of Pei Core entry.
3169
3170 Returns:
3171
3172 EFI_SUCCESS - The PEI_CORE FIT entry was updated successfully.
3173 EFI_NOT_FOUND - Not found the PEI_CORE FIT entry.
3174
3175 --*/
3176 {
3177 FIT_TABLE *TmpFitPtr;
3178 UINTN Index;
3179 UINTN NumFitComponents;
3180
3181 TmpFitPtr = FitTablePtr;
3182 NumFitComponents = TmpFitPtr->CompSize;
3183
3184 for (Index = 0; Index < NumFitComponents; Index++) {
3185 if ((TmpFitPtr->CvAndType & FIT_TYPE_MASK) == COMP_TYPE_FIT_PEICORE) {
3186 TmpFitPtr->CompAddress = PeiCorePhysicalAddress;
3187 return EFI_SUCCESS;
3188 }
3189
3190 TmpFitPtr++;
3191 }
3192
3193 return EFI_NOT_FOUND;
3194 }
3195
3196 VOID
3197 UpdateFitCheckSum (
3198 IN FIT_TABLE *FitTablePtr
3199 )
3200 /*++
3201
3202 Routine Description:
3203
3204 This function is used to update the checksum for FIT.
3205
3206
3207 Arguments:
3208
3209 FitTablePtr - The pointer of FIT_TABLE.
3210
3211 Returns:
3212
3213 None.
3214
3215 --*/
3216 {
3217 if ((FitTablePtr->CvAndType & CHECKSUM_BIT_MASK) >> 7) {
3218 FitTablePtr->CheckSum = 0;
3219 FitTablePtr->CheckSum = CalculateChecksum8 ((UINT8 *) FitTablePtr, FitTablePtr->CompSize * 16);
3220 }
3221 }