| 1 | /*++\r |
| 2 | \r |
| 3 | Copyright (c) 2004, Intel Corporation \r |
| 4 | All rights reserved. This program and the accompanying materials \r |
| 5 | are licensed and made available under the terms and conditions of the BSD License \r |
| 6 | which accompanies this distribution. The full text of the license may be found at \r |
| 7 | http://opensource.org/licenses/bsd-license.php \r |
| 8 | \r |
| 9 | THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r |
| 10 | WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r |
| 11 | \r |
| 12 | Module Name:\r |
| 13 | \r |
| 14 | fwimage.c\r |
| 15 | \r |
| 16 | Abstract:\r |
| 17 | \r |
| 18 | Converts a pe32+ image to an FW image type\r |
| 19 | \r |
| 20 | --*/\r |
| 21 | \r |
| 22 | #include "WinNtInclude.h"\r |
| 23 | \r |
| 24 | #ifndef __GNUC__\r |
| 25 | #include <windows.h>\r |
| 26 | #endif\r |
| 27 | #include <stdio.h>\r |
| 28 | #include <stdlib.h>\r |
| 29 | #include <string.h>\r |
| 30 | #include <time.h>\r |
| 31 | \r |
| 32 | #include <Common/UefiBaseTypes.h>\r |
| 33 | #include <Common/EfiImage.h>\r |
| 34 | \r |
| 35 | #include "CommonLib.h"\r |
| 36 | #include "EfiUtilityMsgs.c"\r |
| 37 | \r |
| 38 | //\r |
| 39 | // Version of this utility\r |
| 40 | //\r |
| 41 | #define UTILITY_NAME "FwImage"\r |
| 42 | #define UTILITY_MAJOR_VERSION 1\r |
| 43 | #define UTILITY_MINOR_VERSION 0\r |
| 44 | \r |
| 45 | #ifdef __GNUC__\r |
| 46 | typedef unsigned long ULONG;\r |
| 47 | typedef unsigned char UCHAR;\r |
| 48 | typedef unsigned char *PUCHAR;\r |
| 49 | typedef unsigned short USHORT;\r |
| 50 | #endif\r |
| 51 | \r |
| 52 | static\r |
| 53 | void\r |
| 54 | Version (\r |
| 55 | VOID\r |
| 56 | )\r |
| 57 | {\r |
| 58 | printf ("%s v%d.%d -EDK Utility for Converting a pe32+ image to an FW image type.\n", UTILITY_NAME, UTILITY_MAJOR_VERSION, UTILITY_MINOR_VERSION);\r |
| 59 | printf ("Copyright (c) 1999-2006 Intel Corporation. All rights reserved.\n");\r |
| 60 | }\r |
| 61 | \r |
| 62 | \r |
| 63 | VOID\r |
| 64 | Usage (\r |
| 65 | VOID\r |
| 66 | )\r |
| 67 | {\r |
| 68 | Version();\r |
| 69 | printf ("\nUsage: " UTILITY_NAME " {-t time-date} {-h|--help|-?|/?|-V|--version} \n\\r |
| 70 | [BASE|SEC|PEI_CORE|PEIM|DXE_CORE|DXE_DRIVER|DXE_RUNTIME_DRIVER|\n\\r |
| 71 | DXE_SAL_DRIVER|DXE_SMM_DRIVER|TOOL|UEFI_DRIVER|UEFI_APPLICATION|\n\\r |
| 72 | USER_DEFINED] peimage [outimage]");\r |
| 73 | }\r |
| 74 | \r |
| 75 | static\r |
| 76 | STATUS\r |
| 77 | FCopyFile (\r |
| 78 | FILE *in,\r |
| 79 | FILE *out\r |
| 80 | )\r |
| 81 | {\r |
| 82 | ULONG filesize;\r |
| 83 | ULONG offset;\r |
| 84 | ULONG length;\r |
| 85 | UCHAR Buffer[8 * 1024];\r |
| 86 | \r |
| 87 | fseek (in, 0, SEEK_END);\r |
| 88 | filesize = ftell (in);\r |
| 89 | \r |
| 90 | fseek (in, 0, SEEK_SET);\r |
| 91 | fseek (out, 0, SEEK_SET);\r |
| 92 | \r |
| 93 | offset = 0;\r |
| 94 | while (offset < filesize) {\r |
| 95 | length = sizeof (Buffer);\r |
| 96 | if (filesize - offset < length) {\r |
| 97 | length = filesize - offset;\r |
| 98 | }\r |
| 99 | \r |
| 100 | fread (Buffer, length, 1, in);\r |
| 101 | fwrite (Buffer, length, 1, out);\r |
| 102 | offset += length;\r |
| 103 | }\r |
| 104 | \r |
| 105 | if ((ULONG) ftell (out) != filesize) {\r |
| 106 | Error (NULL, 0, 0, "write error", NULL);\r |
| 107 | return STATUS_ERROR;\r |
| 108 | }\r |
| 109 | \r |
| 110 | return STATUS_SUCCESS;\r |
| 111 | }\r |
| 112 | \r |
| 113 | static\r |
| 114 | STATUS\r |
| 115 | FReadFile (\r |
| 116 | FILE *in,\r |
| 117 | VOID **Buffer,\r |
| 118 | UINTN *Length\r |
| 119 | )\r |
| 120 | {\r |
| 121 | fseek (in, 0, SEEK_END);\r |
| 122 | *Length = ftell (in);\r |
| 123 | *Buffer = malloc (*Length);\r |
| 124 | fseek (in, 0, SEEK_SET);\r |
| 125 | fread (*Buffer, *Length, 1, in);\r |
| 126 | return STATUS_SUCCESS;\r |
| 127 | }\r |
| 128 | \r |
| 129 | static\r |
| 130 | STATUS\r |
| 131 | FWriteFile (\r |
| 132 | FILE *out,\r |
| 133 | VOID *Buffer,\r |
| 134 | UINTN Length\r |
| 135 | )\r |
| 136 | {\r |
| 137 | fseek (out, 0, SEEK_SET);\r |
| 138 | fwrite (Buffer, Length, 1, out);\r |
| 139 | if ((ULONG) ftell (out) != Length) {\r |
| 140 | Error (NULL, 0, 0, "write error", NULL);\r |
| 141 | return STATUS_ERROR;\r |
| 142 | }\r |
| 143 | free (Buffer);\r |
| 144 | return STATUS_SUCCESS;\r |
| 145 | }\r |
| 146 | \r |
| 147 | int\r |
| 148 | main (\r |
| 149 | int argc,\r |
| 150 | char *argv[]\r |
| 151 | )\r |
| 152 | /*++\r |
| 153 | \r |
| 154 | Routine Description:\r |
| 155 | \r |
| 156 | Main function.\r |
| 157 | \r |
| 158 | Arguments:\r |
| 159 | \r |
| 160 | argc - Number of command line parameters.\r |
| 161 | argv - Array of pointers to command line parameter strings.\r |
| 162 | \r |
| 163 | Returns:\r |
| 164 | STATUS_SUCCESS - Utility exits successfully.\r |
| 165 | STATUS_ERROR - Some error occurred during execution.\r |
| 166 | \r |
| 167 | --*/\r |
| 168 | {\r |
| 169 | ULONG Type;\r |
| 170 | PUCHAR Ext;\r |
| 171 | PUCHAR p;\r |
| 172 | PUCHAR pe;\r |
| 173 | PUCHAR OutImageName;\r |
| 174 | UCHAR outname[500];\r |
| 175 | FILE *fpIn;\r |
| 176 | FILE *fpOut;\r |
| 177 | VOID *ZeroBuffer;\r |
| 178 | EFI_IMAGE_DOS_HEADER *DosHdr;\r |
| 179 | EFI_IMAGE_NT_HEADERS *PeHdr;\r |
| 180 | EFI_IMAGE_OPTIONAL_HEADER32 *Optional32;\r |
| 181 | EFI_IMAGE_OPTIONAL_HEADER64 *Optional64;\r |
| 182 | time_t TimeStamp;\r |
| 183 | struct tm TimeStruct;\r |
| 184 | EFI_IMAGE_DOS_HEADER BackupDosHdr;\r |
| 185 | ULONG Index;\r |
| 186 | ULONG Index1;\r |
| 187 | ULONG Index2;\r |
| 188 | ULONG Index3;\r |
| 189 | BOOLEAN TimeStampPresent;\r |
| 190 | UINTN AllignedRelocSize;\r |
| 191 | UINTN Delta;\r |
| 192 | EFI_IMAGE_SECTION_HEADER *SectionHeader;\r |
| 193 | UINT8 *FileBuffer;\r |
| 194 | UINTN FileLength;\r |
| 195 | RUNTIME_FUNCTION *RuntimeFunction;\r |
| 196 | UNWIND_INFO *UnwindInfo;\r |
| 197 | \r |
| 198 | SetUtilityName (UTILITY_NAME);\r |
| 199 | //\r |
| 200 | // Assign to fix compile warning\r |
| 201 | //\r |
| 202 | OutImageName = NULL;\r |
| 203 | Type = 0;\r |
| 204 | Ext = 0;\r |
| 205 | TimeStamp = 0;\r |
| 206 | TimeStampPresent = FALSE;\r |
| 207 | \r |
| 208 | if (argc < 1) {\r |
| 209 | Usage();\r |
| 210 | return STATUS_ERROR;\r |
| 211 | }\r |
| 212 | \r |
| 213 | if ((strcmp(argv[1], "-h") == 0) || (strcmp(argv[1], "--help") == 0) ||\r |
| 214 | (strcmp(argv[1], "-?") == 0) || (strcmp(argv[1], "/?") == 0)) {\r |
| 215 | Usage();\r |
| 216 | return STATUS_ERROR;\r |
| 217 | }\r |
| 218 | \r |
| 219 | if ((strcmp(argv[1], "-V") == 0) || (strcmp(argv[1], "--version") == 0)) {\r |
| 220 | Version();\r |
| 221 | return STATUS_ERROR;\r |
| 222 | }\r |
| 223 | \r |
| 224 | //\r |
| 225 | // Look for -t time-date option first. If the time is "0", then\r |
| 226 | // skip it.\r |
| 227 | //\r |
| 228 | if ((argc > 2) && !strcmp (argv[1], "-t")) {\r |
| 229 | TimeStampPresent = TRUE;\r |
| 230 | if (strcmp (argv[2], "0") != 0) {\r |
| 231 | //\r |
| 232 | // Convert the string to a value\r |
| 233 | //\r |
| 234 | memset ((char *) &TimeStruct, 0, sizeof (TimeStruct));\r |
| 235 | if (sscanf(\r |
| 236 | argv[2], "%d/%d/%d,%d:%d:%d",\r |
| 237 | &TimeStruct.tm_mon, /* months since January - [0,11] */\r |
| 238 | &TimeStruct.tm_mday, /* day of the month - [1,31] */\r |
| 239 | &TimeStruct.tm_year, /* years since 1900 */\r |
| 240 | &TimeStruct.tm_hour, /* hours since midnight - [0,23] */\r |
| 241 | &TimeStruct.tm_min, /* minutes after the hour - [0,59] */\r |
| 242 | &TimeStruct.tm_sec /* seconds after the minute - [0,59] */\r |
| 243 | ) != 6) {\r |
| 244 | Error (NULL, 0, 0, argv[2], "failed to convert to mm/dd/yyyy,hh:mm:ss format");\r |
| 245 | return STATUS_ERROR;\r |
| 246 | }\r |
| 247 | //\r |
| 248 | // Now fixup some of the fields\r |
| 249 | //\r |
| 250 | TimeStruct.tm_mon--;\r |
| 251 | TimeStruct.tm_year -= 1900;\r |
| 252 | //\r |
| 253 | // Sanity-check values?\r |
| 254 | // Convert\r |
| 255 | //\r |
| 256 | TimeStamp = mktime (&TimeStruct);\r |
| 257 | if (TimeStamp == (time_t) - 1) {\r |
| 258 | Error (NULL, 0, 0, argv[2], "failed to convert time");\r |
| 259 | return STATUS_ERROR;\r |
| 260 | }\r |
| 261 | }\r |
| 262 | //\r |
| 263 | // Skip over the args\r |
| 264 | //\r |
| 265 | argc -= 2;\r |
| 266 | argv += 2;\r |
| 267 | }\r |
| 268 | //\r |
| 269 | // Check for enough args\r |
| 270 | //\r |
| 271 | if (argc < 3) {\r |
| 272 | Usage ();\r |
| 273 | return STATUS_ERROR;\r |
| 274 | }\r |
| 275 | \r |
| 276 | if (argc == 4) {\r |
| 277 | OutImageName = argv[3];\r |
| 278 | }\r |
| 279 | //\r |
| 280 | // Get new image type\r |
| 281 | //\r |
| 282 | p = argv[1];\r |
| 283 | if (*p == '/' || *p == '\\') {\r |
| 284 | p += 1;\r |
| 285 | }\r |
| 286 | \r |
| 287 | if (stricmp (p, "app") == 0 || stricmp (p, "UEFI_APPLICATION") == 0) {\r |
| 288 | Type = EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION;\r |
| 289 | Ext = ".efi";\r |
| 290 | \r |
| 291 | } else if (stricmp (p, "bsdrv") == 0 || stricmp (p, "DXE_DRIVER") == 0) {\r |
| 292 | Type = EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER;\r |
| 293 | Ext = ".efi";\r |
| 294 | \r |
| 295 | } else if (stricmp (p, "rtdrv") == 0 || stricmp (p, "DXE_RUNTIME_DRIVER") == 0) {\r |
| 296 | Type = EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER;\r |
| 297 | Ext = ".efi";\r |
| 298 | \r |
| 299 | } else if (stricmp (p, "rtdrv") == 0 || stricmp (p, "DXE_SAL_DRIVER") == 0) {\r |
| 300 | Type = EFI_IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER;\r |
| 301 | Ext = ".efi";\r |
| 302 | } else if (stricmp (p, "SEC") == 0) {\r |
| 303 | Type = EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER;\r |
| 304 | Ext = ".sec";\r |
| 305 | } else if (stricmp (p, "peim") == 0 ||\r |
| 306 | stricmp (p, "BASE") == 0 ||\r |
| 307 | stricmp (p, "PEI_CORE") == 0 ||\r |
| 308 | stricmp (p, "PEIM") == 0 ||\r |
| 309 | stricmp (p, "DXE_SMM_DRIVER") == 0 ||\r |
| 310 | stricmp (p, "TOOL") == 0 ||\r |
| 311 | stricmp (p, "UEFI_APPLICATION") == 0 ||\r |
| 312 | stricmp (p, "USER_DEFINED") == 0 ||\r |
| 313 | stricmp (p, "UEFI_DRIVER") == 0 ||\r |
| 314 | stricmp (p, "DXE_CORE") == 0\r |
| 315 | ) {\r |
| 316 | Type = EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER;\r |
| 317 | Ext = ".pei";\r |
| 318 | } else {\r |
| 319 | printf ("%s", p);\r |
| 320 | Usage ();\r |
| 321 | return STATUS_ERROR;\r |
| 322 | }\r |
| 323 | //\r |
| 324 | // open source file\r |
| 325 | //\r |
| 326 | fpIn = fopen (argv[2], "rb");\r |
| 327 | if (!fpIn) {\r |
| 328 | Error (NULL, 0, 0, argv[2], "failed to open input file for reading");\r |
| 329 | return STATUS_ERROR;\r |
| 330 | }\r |
| 331 | \r |
| 332 | FReadFile (fpIn, (VOID **)&FileBuffer, &FileLength);\r |
| 333 | \r |
| 334 | //\r |
| 335 | // Read the dos & pe hdrs of the image\r |
| 336 | //\r |
| 337 | DosHdr = (EFI_IMAGE_DOS_HEADER *)FileBuffer;\r |
| 338 | if (DosHdr->e_magic != EFI_IMAGE_DOS_SIGNATURE) {\r |
| 339 | Error (NULL, 0, 0, argv[2], "DOS header signature not found in source image");\r |
| 340 | fclose (fpIn);\r |
| 341 | return STATUS_ERROR;\r |
| 342 | }\r |
| 343 | \r |
| 344 | PeHdr = (EFI_IMAGE_NT_HEADERS *)(FileBuffer + DosHdr->e_lfanew);\r |
| 345 | if (PeHdr->Signature != EFI_IMAGE_NT_SIGNATURE) {\r |
| 346 | Error (NULL, 0, 0, argv[2], "PE header signature not found in source image");\r |
| 347 | fclose (fpIn);\r |
| 348 | return STATUS_ERROR;\r |
| 349 | }\r |
| 350 | \r |
| 351 | //\r |
| 352 | // open output file\r |
| 353 | //\r |
| 354 | strcpy (outname, argv[2]);\r |
| 355 | pe = NULL;\r |
| 356 | for (p = outname; *p; p++) {\r |
| 357 | if (*p == '.') {\r |
| 358 | pe = p;\r |
| 359 | }\r |
| 360 | }\r |
| 361 | \r |
| 362 | if (!pe) {\r |
| 363 | pe = p;\r |
| 364 | }\r |
| 365 | \r |
| 366 | strcpy (pe, Ext);\r |
| 367 | \r |
| 368 | if (!OutImageName) {\r |
| 369 | OutImageName = outname;\r |
| 370 | }\r |
| 371 | \r |
| 372 | fpOut = fopen (OutImageName, "w+b");\r |
| 373 | if (!fpOut) {\r |
| 374 | Error (NULL, 0, 0, OutImageName, "could not open output file for writing");\r |
| 375 | fclose (fpIn);\r |
| 376 | return STATUS_ERROR;\r |
| 377 | }\r |
| 378 | \r |
| 379 | //\r |
| 380 | // Zero all unused fields of the DOS header\r |
| 381 | //\r |
| 382 | memcpy (&BackupDosHdr, DosHdr, sizeof (EFI_IMAGE_DOS_HEADER));\r |
| 383 | memset (DosHdr, 0, sizeof (EFI_IMAGE_DOS_HEADER));\r |
| 384 | DosHdr->e_magic = BackupDosHdr.e_magic;\r |
| 385 | DosHdr->e_lfanew = BackupDosHdr.e_lfanew;\r |
| 386 | \r |
| 387 | for (Index = sizeof (EFI_IMAGE_DOS_HEADER); Index < (ULONG) DosHdr->e_lfanew; Index++) {\r |
| 388 | FileBuffer[Index] = DosHdr->e_cp;\r |
| 389 | }\r |
| 390 | \r |
| 391 | //\r |
| 392 | // Path the PE header\r |
| 393 | //\r |
| 394 | PeHdr->OptionalHeader.Subsystem = (USHORT) Type;\r |
| 395 | if (TimeStampPresent) {\r |
| 396 | PeHdr->FileHeader.TimeDateStamp = (UINT32) TimeStamp;\r |
| 397 | }\r |
| 398 | \r |
| 399 | if (PeHdr->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r |
| 400 | Optional32 = (EFI_IMAGE_OPTIONAL_HEADER32 *)&PeHdr->OptionalHeader;\r |
| 401 | Optional32->MajorLinkerVersion = 0;\r |
| 402 | Optional32->MinorLinkerVersion = 0;\r |
| 403 | Optional32->MajorOperatingSystemVersion = 0;\r |
| 404 | Optional32->MinorOperatingSystemVersion = 0;\r |
| 405 | Optional32->MajorImageVersion = 0;\r |
| 406 | Optional32->MinorImageVersion = 0;\r |
| 407 | Optional32->MajorSubsystemVersion = 0;\r |
| 408 | Optional32->MinorSubsystemVersion = 0;\r |
| 409 | Optional32->Win32VersionValue = 0;\r |
| 410 | Optional32->CheckSum = 0;\r |
| 411 | Optional32->SizeOfStackReserve = 0;\r |
| 412 | Optional32->SizeOfStackCommit = 0;\r |
| 413 | Optional32->SizeOfHeapReserve = 0;\r |
| 414 | Optional32->SizeOfHeapCommit = 0;\r |
| 415 | \r |
| 416 | //\r |
| 417 | // Strip zero padding at the end of the .reloc section \r |
| 418 | //\r |
| 419 | if (Optional32->NumberOfRvaAndSizes >= 6) {\r |
| 420 | if (Optional32->DataDirectory[5].Size != 0) {\r |
| 421 | SectionHeader = (EFI_IMAGE_SECTION_HEADER *)(FileBuffer + DosHdr->e_lfanew + sizeof(UINT32) + sizeof (EFI_IMAGE_FILE_HEADER) + PeHdr->FileHeader.SizeOfOptionalHeader);\r |
| 422 | for (Index = 0; Index < PeHdr->FileHeader.NumberOfSections; Index++, SectionHeader++) {\r |
| 423 | //\r |
| 424 | // Look for the Section Header that starts as the same virtual address as the Base Relocation Data Directory\r |
| 425 | //\r |
| 426 | if (SectionHeader->VirtualAddress == Optional32->DataDirectory[5].VirtualAddress) {\r |
| 427 | SectionHeader->Misc.VirtualSize = Optional32->DataDirectory[5].Size;\r |
| 428 | AllignedRelocSize = (Optional32->DataDirectory[5].Size + Optional32->FileAlignment - 1) & (~(Optional32->FileAlignment - 1));\r |
| 429 | //\r |
| 430 | // Check to see if there is zero padding at the end of the base relocations\r |
| 431 | //\r |
| 432 | if (AllignedRelocSize < SectionHeader->SizeOfRawData) {\r |
| 433 | //\r |
| 434 | // Check to see if the base relocations are at the end of the file\r |
| 435 | //\r |
| 436 | if (SectionHeader->PointerToRawData + SectionHeader->SizeOfRawData == Optional32->SizeOfImage) {\r |
| 437 | //\r |
| 438 | // All the required conditions are met to strip the zero padding of the end of the base relocations section\r |
| 439 | //\r |
| 440 | Optional32->SizeOfImage -= (SectionHeader->SizeOfRawData - AllignedRelocSize);\r |
| 441 | Optional32->SizeOfInitializedData -= (SectionHeader->SizeOfRawData - AllignedRelocSize);\r |
| 442 | SectionHeader->SizeOfRawData = AllignedRelocSize;\r |
| 443 | FileLength = Optional32->SizeOfImage;\r |
| 444 | }\r |
| 445 | }\r |
| 446 | }\r |
| 447 | }\r |
| 448 | }\r |
| 449 | }\r |
| 450 | } \r |
| 451 | if (PeHdr->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {\r |
| 452 | Optional64 = (EFI_IMAGE_OPTIONAL_HEADER64 *)&PeHdr->OptionalHeader;\r |
| 453 | Optional64->MajorLinkerVersion = 0;\r |
| 454 | Optional64->MinorLinkerVersion = 0;\r |
| 455 | Optional64->MajorOperatingSystemVersion = 0;\r |
| 456 | Optional64->MinorOperatingSystemVersion = 0;\r |
| 457 | Optional64->MajorImageVersion = 0;\r |
| 458 | Optional64->MinorImageVersion = 0;\r |
| 459 | Optional64->MajorSubsystemVersion = 0;\r |
| 460 | Optional64->MinorSubsystemVersion = 0;\r |
| 461 | Optional64->Win32VersionValue = 0;\r |
| 462 | Optional64->CheckSum = 0;\r |
| 463 | Optional64->SizeOfStackReserve = 0;\r |
| 464 | Optional64->SizeOfStackCommit = 0;\r |
| 465 | Optional64->SizeOfHeapReserve = 0;\r |
| 466 | Optional64->SizeOfHeapCommit = 0;\r |
| 467 | \r |
| 468 | //\r |
| 469 | // Zero the .pdata section if the machine type is X64 and the Debug Directory is empty\r |
| 470 | //\r |
| 471 | if (PeHdr->FileHeader.Machine == 0x8664) { // X64\r |
| 472 | if (Optional64->NumberOfRvaAndSizes >= 4) {\r |
| 473 | if (Optional64->NumberOfRvaAndSizes < 7 || (Optional64->NumberOfRvaAndSizes >= 7 && Optional64->DataDirectory[6].Size == 0)) {\r |
| 474 | SectionHeader = (EFI_IMAGE_SECTION_HEADER *)(FileBuffer + DosHdr->e_lfanew + sizeof(UINT32) + sizeof (EFI_IMAGE_FILE_HEADER) + PeHdr->FileHeader.SizeOfOptionalHeader);\r |
| 475 | for (Index = 0; Index < PeHdr->FileHeader.NumberOfSections; Index++, SectionHeader++) {\r |
| 476 | if (SectionHeader->VirtualAddress == Optional64->DataDirectory[3].VirtualAddress) {\r |
| 477 | RuntimeFunction = (RUNTIME_FUNCTION *)(FileBuffer + SectionHeader->PointerToRawData);\r |
| 478 | for (Index1 = 0; Index1 < Optional64->DataDirectory[3].Size / sizeof (RUNTIME_FUNCTION); Index1++, RuntimeFunction++) {\r |
| 479 | SectionHeader = (EFI_IMAGE_SECTION_HEADER *)(FileBuffer + DosHdr->e_lfanew + sizeof(UINT32) + sizeof (EFI_IMAGE_FILE_HEADER) + PeHdr->FileHeader.SizeOfOptionalHeader);\r |
| 480 | for (Index2 = 0; Index2 < PeHdr->FileHeader.NumberOfSections; Index2++, SectionHeader++) {\r |
| 481 | if (RuntimeFunction->UnwindInfoAddress > SectionHeader->VirtualAddress && RuntimeFunction->UnwindInfoAddress < (SectionHeader->VirtualAddress + SectionHeader->SizeOfRawData)) {\r |
| 482 | UnwindInfo = (UNWIND_INFO *)(FileBuffer + SectionHeader->PointerToRawData + (RuntimeFunction->UnwindInfoAddress - SectionHeader->VirtualAddress));\r |
| 483 | if (UnwindInfo->Version == 1) {\r |
| 484 | memset (UnwindInfo + 1, 0, UnwindInfo->CountOfUnwindCodes * sizeof (UINT16));\r |
| 485 | memset (UnwindInfo, 0, sizeof (UNWIND_INFO));\r |
| 486 | }\r |
| 487 | }\r |
| 488 | }\r |
| 489 | memset (RuntimeFunction, 0, sizeof (RUNTIME_FUNCTION));\r |
| 490 | }\r |
| 491 | \r |
| 492 | break;\r |
| 493 | }\r |
| 494 | }\r |
| 495 | Optional64->DataDirectory[3].Size = 0;\r |
| 496 | Optional64->DataDirectory[3].VirtualAddress = 0;\r |
| 497 | }\r |
| 498 | }\r |
| 499 | }\r |
| 500 | \r |
| 501 | //\r |
| 502 | // Strip zero padding at the end of the .reloc section \r |
| 503 | //\r |
| 504 | if (Optional64->NumberOfRvaAndSizes >= 6) {\r |
| 505 | if (Optional64->DataDirectory[5].Size != 0) {\r |
| 506 | SectionHeader = (EFI_IMAGE_SECTION_HEADER *)(FileBuffer + DosHdr->e_lfanew + sizeof(UINT32) + sizeof (EFI_IMAGE_FILE_HEADER) + PeHdr->FileHeader.SizeOfOptionalHeader);\r |
| 507 | for (Index = 0; Index < PeHdr->FileHeader.NumberOfSections; Index++, SectionHeader++) {\r |
| 508 | //\r |
| 509 | // Look for the Section Header that starts as the same virtual address as the Base Relocation Data Directory\r |
| 510 | //\r |
| 511 | if (SectionHeader->VirtualAddress == Optional64->DataDirectory[5].VirtualAddress) {\r |
| 512 | SectionHeader->Misc.VirtualSize = Optional64->DataDirectory[5].Size;\r |
| 513 | AllignedRelocSize = (Optional64->DataDirectory[5].Size + Optional64->FileAlignment - 1) & (~(Optional64->FileAlignment - 1));\r |
| 514 | //\r |
| 515 | // Check to see if there is zero padding at the end of the base relocations\r |
| 516 | //\r |
| 517 | if (AllignedRelocSize < SectionHeader->SizeOfRawData) {\r |
| 518 | //\r |
| 519 | // Check to see if the base relocations are at the end of the file\r |
| 520 | //\r |
| 521 | if (SectionHeader->PointerToRawData + SectionHeader->SizeOfRawData == Optional64->SizeOfImage) {\r |
| 522 | //\r |
| 523 | // All the required conditions are met to strip the zero padding of the end of the base relocations section\r |
| 524 | //\r |
| 525 | Optional64->SizeOfImage -= (SectionHeader->SizeOfRawData - AllignedRelocSize);\r |
| 526 | Optional64->SizeOfInitializedData -= (SectionHeader->SizeOfRawData - AllignedRelocSize);\r |
| 527 | SectionHeader->SizeOfRawData = AllignedRelocSize;\r |
| 528 | FileLength = Optional64->SizeOfImage;\r |
| 529 | }\r |
| 530 | }\r |
| 531 | }\r |
| 532 | }\r |
| 533 | }\r |
| 534 | }\r |
| 535 | }\r |
| 536 | \r |
| 537 | FWriteFile (fpOut, FileBuffer, FileLength);\r |
| 538 | \r |
| 539 | //\r |
| 540 | // Done\r |
| 541 | //\r |
| 542 | fclose (fpIn);\r |
| 543 | fclose (fpOut);\r |
| 544 | //\r |
| 545 | // printf ("Created %s\n", OutImageName);\r |
| 546 | //\r |
| 547 | return STATUS_SUCCESS;\r |
| 548 | }\r |