|
| 1 | +From 9ba52e2620d0c674ed791b9e9bdf0dbf15900d92 Mon Sep 17 00:00:00 2001 |
| 2 | +From: Bingxing Wang <i@imbushuo.net> |
| 3 | +Date: Sun, 25 Oct 2020 01:00:24 -0400 |
| 4 | +Subject: [PATCH] BaseTools: support generation of Windows Boot Application |
| 5 | + |
| 6 | +Introduce the support for generating Windows Boot Application PE |
| 7 | +files with an override switch. In addition, Windows Boot Apps re |
| 8 | +quire PE checksum to be valid. GenFw doesn't populate the PE che |
| 9 | +cksum field, so this is also added. |
| 10 | + |
| 11 | +The checksum generation algorithm is taken from Windows NT 3.51 |
| 12 | +public SDK's source. |
| 13 | + |
| 14 | +Signed-off-by: Bingxing Wang <i@imbushuo.net> |
| 15 | +--- |
| 16 | + BaseTools/Source/C/Common/BasePeCoff.c | 6 +- |
| 17 | + BaseTools/Source/C/GenFw/GenFw.c | 114 ++++++++++++++++++ |
| 18 | + .../C/Include/IndustryStandard/PeImage.h | 5 + |
| 19 | + 3 files changed, 123 insertions(+), 2 deletions(-) |
| 20 | + |
| 21 | +diff --git a/BaseTools/Source/C/Common/BasePeCoff.c b/BaseTools/Source/C/Common/BasePeCoff.c |
| 22 | +index 62fbb2985c..6b536772f1 100644 |
| 23 | +--- a/BaseTools/Source/C/Common/BasePeCoff.c |
| 24 | ++++ b/BaseTools/Source/C/Common/BasePeCoff.c |
| 25 | +@@ -185,7 +185,8 @@ Returns: |
| 26 | + ImageContext->Machine != EFI_IMAGE_MACHINE_EBC && \ |
| 27 | + ImageContext->Machine != EFI_IMAGE_MACHINE_AARCH64 && \ |
| 28 | + ImageContext->Machine != EFI_IMAGE_MACHINE_RISCV64) { |
| 29 | +- if (ImageContext->Machine == IMAGE_FILE_MACHINE_ARM) { |
| 30 | ++ if (ImageContext->Machine == IMAGE_FILE_MACHINE_ARM || |
| 31 | ++ ImageContext->Machine == IMAGE_FILE_MACHINE_ARMNT) { |
| 32 | + // |
| 33 | + // There are two types of ARM images. Pure ARM and ARM/Thumb. |
| 34 | + // If we see the ARM say it is the ARM/Thumb so there is only |
| 35 | +@@ -219,7 +220,8 @@ Returns: |
| 36 | + if (ImageContext->ImageType != EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION && \ |
| 37 | + ImageContext->ImageType != EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER && \ |
| 38 | + ImageContext->ImageType != EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER && \ |
| 39 | +- ImageContext->ImageType != EFI_IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER) { |
| 40 | ++ ImageContext->ImageType != EFI_IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER && |
| 41 | ++ ImageContext->ImageType != EFI_IMAGE_SUBSYSTEM_WINDOWS_BOOT_APPLICATION) { |
| 42 | + // |
| 43 | + // unsupported PeImage subsystem type |
| 44 | + // |
| 45 | +diff --git a/BaseTools/Source/C/GenFw/GenFw.c b/BaseTools/Source/C/GenFw/GenFw.c |
| 46 | +index 8cab70ba4d..28b4c48f8c 100644 |
| 47 | +--- a/BaseTools/Source/C/GenFw/GenFw.c |
| 48 | ++++ b/BaseTools/Source/C/GenFw/GenFw.c |
| 49 | +@@ -87,6 +87,7 @@ UINT32 mImageTimeStamp = 0; |
| 50 | + UINT32 mImageSize = 0; |
| 51 | + UINT32 mOutImageType = FW_DUMMY_IMAGE; |
| 52 | + BOOLEAN mIsConvertXip = FALSE; |
| 53 | ++BOOLEAN mIsConvertArmToArmThumb2 = FALSE; |
| 54 | + |
| 55 | + |
| 56 | + STATIC |
| 57 | +@@ -251,6 +252,11 @@ Returns: |
| 58 | + fprintf (stdout, " -r, --replace Overwrite the input file with the output content.\n\ |
| 59 | + If more input files are specified,\n\ |
| 60 | + the last input file will be as the output file.\n"); |
| 61 | ++ fprintf (stdout, " --convert-output-machine-arm-to-thumb2\n\ |
| 62 | ++ If the output machine type is IMAGE_FILE_MACHINE_ARM\n\ |
| 63 | ++ or ARMT, convert to IMAGE_FILE_MACHINE_ARMNT (Thumb2)\n"); |
| 64 | ++ fprintf (stdout, " --windows-boot-application\n\ |
| 65 | ++ Force subsystem type to WINDOWS_BOOT_APPLICATION\n"); |
| 66 | + fprintf (stdout, " -g HiiPackageListGuid, --hiiguid HiiPackageListGuid\n\ |
| 67 | + Guid is used to specify hii package list guid.\n\ |
| 68 | + Its format is xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\n\ |
| 69 | +@@ -1032,6 +1038,46 @@ Returns: |
| 70 | + return Status; |
| 71 | + } |
| 72 | + |
| 73 | ++UINT16 ChkSum( |
| 74 | ++ UINT32 PartialSum, |
| 75 | ++ UINT16* Source, |
| 76 | ++ UINT32 Length |
| 77 | ++ ) |
| 78 | ++/*++ |
| 79 | ++ |
| 80 | ++Routine description: |
| 81 | ++ |
| 82 | ++ ChkSum() - Compute a partial checksum on a portion of an imagefile. |
| 83 | ++ Taken from Windows NT 3.51 SDK distribution. |
| 84 | ++ |
| 85 | ++ FROM "imagehlp/imagedir.c": Steve Wood 18-Aug-1989 |
| 86 | ++ |
| 87 | ++Arguments: |
| 88 | ++ |
| 89 | ++ PartialSum Supplies the initial checksum value. |
| 90 | ++ Sources Supplies a pointer to the array of words for which the |
| 91 | ++ checksum is computed. |
| 92 | ++ Length Supplies the length of the array in words. |
| 93 | ++ |
| 94 | ++Returns: |
| 95 | ++ The computed checksum value is returned as the function value. |
| 96 | ++ |
| 97 | ++--*/ |
| 98 | ++{ |
| 99 | ++ // Compute the word wise checksum allowing carries to occur into the |
| 100 | ++ // high order half of the checksum longword. |
| 101 | ++ while (Length--) { |
| 102 | ++ PartialSum += *Source++; |
| 103 | ++ PartialSum = (PartialSum >> 16) + (PartialSum & 0xffff); |
| 104 | ++ } |
| 105 | ++ |
| 106 | ++ // |
| 107 | ++ // Fold final carry into a single word result and return the resultant |
| 108 | ++ // value. |
| 109 | ++ // |
| 110 | ++ return (UINT16)(((PartialSum >> 16) + PartialSum) & 0xffff); |
| 111 | ++} |
| 112 | ++ |
| 113 | + int |
| 114 | + main ( |
| 115 | + int argc, |
| 116 | +@@ -1116,6 +1162,9 @@ Returns: |
| 117 | + time_t OutputFileTime; |
| 118 | + struct stat Stat_Buf; |
| 119 | + BOOLEAN ZeroDebugFlag; |
| 120 | ++ UINTN DesiredSubsystemOverride; |
| 121 | ++ UINT16 PartialSum; |
| 122 | ++ UINT16 *AdjustSum; |
| 123 | + |
| 124 | + SetUtilityName (UTILITY_NAME); |
| 125 | + |
| 126 | +@@ -1165,6 +1214,10 @@ Returns: |
| 127 | + OutputFileTime = 0; |
| 128 | + ZeroDebugFlag = FALSE; |
| 129 | + |
| 130 | ++ DesiredSubsystemOverride = -1; |
| 131 | ++ PartialSum = 0; |
| 132 | ++ AdjustSum = NULL; |
| 133 | ++ |
| 134 | + if (argc == 1) { |
| 135 | + Error (NULL, 0, 1001, "Missing options", "No input options."); |
| 136 | + Usage (); |
| 137 | +@@ -1304,6 +1357,20 @@ Returns: |
| 138 | + continue; |
| 139 | + } |
| 140 | + |
| 141 | ++ if (stricmp (argv[0], "--convert-output-machine-arm-to-thumb2") == 0) { |
| 142 | ++ mIsConvertArmToArmThumb2 = TRUE; |
| 143 | ++ argc --; |
| 144 | ++ argv ++; |
| 145 | ++ continue; |
| 146 | ++ } |
| 147 | ++ |
| 148 | ++ if (stricmp (argv[0], "--windows-boot-application") == 0) { |
| 149 | ++ DesiredSubsystemOverride = EFI_IMAGE_SUBSYSTEM_WINDOWS_BOOT_APPLICATION; |
| 150 | ++ argc --; |
| 151 | ++ argv ++; |
| 152 | ++ continue; |
| 153 | ++ } |
| 154 | ++ |
| 155 | + if ((stricmp (argv[0], "-m") == 0) || (stricmp (argv[0], "--mcifile") == 0)) { |
| 156 | + mOutImageType = FW_MCI_IMAGE; |
| 157 | + argc --; |
| 158 | +@@ -2045,6 +2112,11 @@ Returns: |
| 159 | + Type = EFI_IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER; |
| 160 | + VerboseMsg ("Efi Image subsystem type is efi sal runtime driver."); |
| 161 | + |
| 162 | ++ } else if (stricmp (ModuleType, "WINDOWS_BOOT_APPLICATION") == 0 || |
| 163 | ++ stricmp (ModuleType, "BOOT_APPLICATION") == 0) { |
| 164 | ++ Type = EFI_IMAGE_SUBSYSTEM_WINDOWS_BOOT_APPLICATION; |
| 165 | ++ VerboseMsg ("Efi Image subsystem type is windows boot application."); |
| 166 | ++ |
| 167 | + } else { |
| 168 | + Error (NULL, 0, 1003, "Invalid option value", "EFI_FILETYPE = %s", ModuleType); |
| 169 | + goto Finish; |
| 170 | +@@ -2052,6 +2124,11 @@ Returns: |
| 171 | + } |
| 172 | + } |
| 173 | + |
| 174 | ++ if (DesiredSubsystemOverride != -1) { |
| 175 | ++ VerboseMsg ("Forcibly converting Efi Image subsystem type to windows boot application."); |
| 176 | ++ Type = EFI_IMAGE_SUBSYSTEM_WINDOWS_BOOT_APPLICATION; |
| 177 | ++ } |
| 178 | ++ |
| 179 | + // |
| 180 | + // Convert ELF image to PeImage |
| 181 | + // |
| 182 | +@@ -2187,6 +2264,13 @@ Returns: |
| 183 | + PeHdr->Pe32.FileHeader.Machine = IMAGE_FILE_MACHINE_ARMT; |
| 184 | + } |
| 185 | + |
| 186 | ++ if (mIsConvertArmToArmThumb2 && |
| 187 | ++ (PeHdr->Pe32.FileHeader.Machine == IMAGE_FILE_MACHINE_ARM || |
| 188 | ++ PeHdr->Pe32.FileHeader.Machine == IMAGE_FILE_MACHINE_ARMT)) { |
| 189 | ++ VerboseMsg ("Converting output subsystem to IMAGE_FILE_MACHINE_ARMNT"); |
| 190 | ++ PeHdr->Pe32.FileHeader.Machine = IMAGE_FILE_MACHINE_ARMNT; |
| 191 | ++ } |
| 192 | ++ |
| 193 | + // |
| 194 | + // Set new base address into image |
| 195 | + // |
| 196 | +@@ -2657,6 +2741,36 @@ Returns: |
| 197 | + } |
| 198 | + } |
| 199 | + |
| 200 | ++ // |
| 201 | ++ // Normally PE/COFF checksum is not required, but in certain scenarios |
| 202 | ++ // This is useful (for instance, Windows Boot Manager checks it) |
| 203 | ++ // |
| 204 | ++ // The following code is taken from Windows NT 3.51 SDK distribution. |
| 205 | ++ // |
| 206 | ++ if (mOutImageType == FW_EFI_IMAGE && PeHdr->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) { |
| 207 | ++ Optional32 = (EFI_IMAGE_OPTIONAL_HEADER32 *)&PeHdr->Pe32.OptionalHeader; |
| 208 | ++ PartialSum = ChkSum(0, (UINT16*) FileBuffer, (FileLength + 1) >> 1); |
| 209 | ++ |
| 210 | ++ AdjustSum = (UINT16*) &Optional32->CheckSum; |
| 211 | ++ PartialSum -= (PartialSum < AdjustSum[0]); |
| 212 | ++ PartialSum -= AdjustSum[0]; |
| 213 | ++ PartialSum -= (PartialSum < AdjustSum[1]); |
| 214 | ++ PartialSum -= AdjustSum[1]; |
| 215 | ++ |
| 216 | ++ Optional32->CheckSum = (UINT32) PartialSum + FileLength; |
| 217 | ++ } else if (mOutImageType == FW_EFI_IMAGE && PeHdr->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) { |
| 218 | ++ Optional64 = (EFI_IMAGE_OPTIONAL_HEADER64 *)&PeHdr->Pe32.OptionalHeader; |
| 219 | ++ PartialSum = ChkSum(0, (UINT16*) FileBuffer, (FileLength + 1) >> 1); |
| 220 | ++ |
| 221 | ++ AdjustSum = (UINT16*) &Optional64->CheckSum; |
| 222 | ++ PartialSum -= (PartialSum < AdjustSum[0]); |
| 223 | ++ PartialSum -= AdjustSum[0]; |
| 224 | ++ PartialSum -= (PartialSum < AdjustSum[1]); |
| 225 | ++ PartialSum -= AdjustSum[1]; |
| 226 | ++ |
| 227 | ++ Optional64->CheckSum = (UINT32) PartialSum + FileLength; |
| 228 | ++ } |
| 229 | ++ |
| 230 | + WriteFile: |
| 231 | + // |
| 232 | + // Update Image to EfiImage or TE image |
| 233 | +diff --git a/BaseTools/Source/C/Include/IndustryStandard/PeImage.h b/BaseTools/Source/C/Include/IndustryStandard/PeImage.h |
| 234 | +index f17b8ee19b..0b025a549a 100644 |
| 235 | +--- a/BaseTools/Source/C/Include/IndustryStandard/PeImage.h |
| 236 | ++++ b/BaseTools/Source/C/Include/IndustryStandard/PeImage.h |
| 237 | +@@ -23,6 +23,8 @@ |
| 238 | + #define EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER 12 |
| 239 | + #define EFI_IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER 13 |
| 240 | + |
| 241 | ++#define EFI_IMAGE_SUBSYSTEM_WINDOWS_BOOT_APPLICATION 16 |
| 242 | ++ |
| 243 | + // |
| 244 | + // BugBug: Need to get a real answer for this problem. This is not in the |
| 245 | + // PE specification. |
| 246 | +@@ -33,12 +35,14 @@ |
| 247 | + // |
| 248 | + #define EFI_IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER 13 |
| 249 | + |
| 250 | ++ |
| 251 | + // |
| 252 | + // PE32+ Machine type for EFI images |
| 253 | + // |
| 254 | + #define IMAGE_FILE_MACHINE_I386 0x014c |
| 255 | + #define IMAGE_FILE_MACHINE_EBC 0x0EBC |
| 256 | + #define IMAGE_FILE_MACHINE_X64 0x8664 |
| 257 | ++#define IMAGE_FILE_MACHINE_ARMNT 0x01c4 // 32-bit ARMv7-based Thumb2 |
| 258 | + #define IMAGE_FILE_MACHINE_ARM 0x01c0 // Thumb only |
| 259 | + #define IMAGE_FILE_MACHINE_ARMT 0x01c2 // 32bit Mixed ARM and Thumb/Thumb 2 Little Endian |
| 260 | + #define IMAGE_FILE_MACHINE_ARM64 0xAA64 // 64bit ARM Architecture, Little Endian |
| 261 | +@@ -50,6 +54,7 @@ |
| 262 | + #define EFI_IMAGE_MACHINE_IA32 IMAGE_FILE_MACHINE_I386 |
| 263 | + #define EFI_IMAGE_MACHINE_EBC IMAGE_FILE_MACHINE_EBC |
| 264 | + #define EFI_IMAGE_MACHINE_X64 IMAGE_FILE_MACHINE_X64 |
| 265 | ++#define EFI_IMAGE_MACHINE_ARMNT IMAGE_FILE_MACHINE_ARMNT |
| 266 | + #define EFI_IMAGE_MACHINE_ARMT IMAGE_FILE_MACHINE_ARMT |
| 267 | + #define EFI_IMAGE_MACHINE_AARCH64 IMAGE_FILE_MACHINE_ARM64 |
| 268 | + #define EFI_IMAGE_MACHINE_RISCV64 IMAGE_FILE_MACHINE_RISCV64 |
| 269 | +-- |
| 270 | +2.17.1 |
| 271 | + |
0 commit comments