1 /** @file
2 Elf convert solution
3
4 Copyright (c) 2010 - 2014, Intel Corporation. All rights reserved.<BR>
5
6 This program and the accompanying materials are licensed and made available
7 under the terms and conditions of the BSD License which accompanies this
8 distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
10
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13
14 **/
15
16 #include "WinNtInclude.h"
17
18 #ifndef __GNUC__
19 #include <windows.h>
20 #include <io.h>
21 #endif
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <time.h>
26 #include <ctype.h>
27
28 #include <Common/UefiBaseTypes.h>
29 #include <IndustryStandard/PeImage.h>
30
31 #include "EfiUtilityMsgs.h"
32
33 #include "GenFw.h"
34 #include "ElfConvert.h"
35 #include "Elf32Convert.h"
36 #include "Elf64Convert.h"
37
38 //
39 // Result Coff file in memory.
40 //
41 UINT8 *mCoffFile = NULL;
42
43 //
44 // COFF relocation data
45 //
46 EFI_IMAGE_BASE_RELOCATION *mCoffBaseRel;
47 UINT16 *mCoffEntryRel;
48
49 //
50 // Current offset in coff file.
51 //
52 UINT32 mCoffOffset;
53
54 //
55 // Offset in Coff file of headers and sections.
56 //
57 UINT32 mTableOffset;
58
59 //
60 //*****************************************************************************
61 // Common ELF Functions
62 //*****************************************************************************
63 //
64
65 VOID
CoffAddFixupEntry(UINT16 Val)66 CoffAddFixupEntry(
67 UINT16 Val
68 )
69 {
70 *mCoffEntryRel = Val;
71 mCoffEntryRel++;
72 mCoffBaseRel->SizeOfBlock += 2;
73 mCoffOffset += 2;
74 }
75
76 VOID
CoffAddFixup(UINT32 Offset,UINT8 Type)77 CoffAddFixup(
78 UINT32 Offset,
79 UINT8 Type
80 )
81 {
82 if (mCoffBaseRel == NULL
83 || mCoffBaseRel->VirtualAddress != (Offset & ~0xfff)) {
84 if (mCoffBaseRel != NULL) {
85 //
86 // Add a null entry (is it required ?)
87 //
88 CoffAddFixupEntry (0);
89
90 //
91 // Pad for alignment.
92 //
93 if (mCoffOffset % 4 != 0)
94 CoffAddFixupEntry (0);
95 }
96
97 mCoffFile = realloc (
98 mCoffFile,
99 mCoffOffset + sizeof(EFI_IMAGE_BASE_RELOCATION) + 2 * MAX_COFF_ALIGNMENT
100 );
101 memset (
102 mCoffFile + mCoffOffset, 0,
103 sizeof(EFI_IMAGE_BASE_RELOCATION) + 2 * MAX_COFF_ALIGNMENT
104 );
105
106 mCoffBaseRel = (EFI_IMAGE_BASE_RELOCATION*)(mCoffFile + mCoffOffset);
107 mCoffBaseRel->VirtualAddress = Offset & ~0xfff;
108 mCoffBaseRel->SizeOfBlock = sizeof(EFI_IMAGE_BASE_RELOCATION);
109
110 mCoffEntryRel = (UINT16 *)(mCoffBaseRel + 1);
111 mCoffOffset += sizeof(EFI_IMAGE_BASE_RELOCATION);
112 }
113
114 //
115 // Fill the entry.
116 //
117 CoffAddFixupEntry((UINT16) ((Type << 12) | (Offset & 0xfff)));
118 }
119
120 VOID
CreateSectionHeader(const CHAR8 * Name,UINT32 Offset,UINT32 Size,UINT32 Flags)121 CreateSectionHeader (
122 const CHAR8 *Name,
123 UINT32 Offset,
124 UINT32 Size,
125 UINT32 Flags
126 )
127 {
128 EFI_IMAGE_SECTION_HEADER *Hdr;
129 Hdr = (EFI_IMAGE_SECTION_HEADER*)(mCoffFile + mTableOffset);
130
131 strcpy((char *)Hdr->Name, Name);
132 Hdr->Misc.VirtualSize = Size;
133 Hdr->VirtualAddress = Offset;
134 Hdr->SizeOfRawData = Size;
135 Hdr->PointerToRawData = Offset;
136 Hdr->PointerToRelocations = 0;
137 Hdr->PointerToLinenumbers = 0;
138 Hdr->NumberOfRelocations = 0;
139 Hdr->NumberOfLinenumbers = 0;
140 Hdr->Characteristics = Flags;
141
142 mTableOffset += sizeof (EFI_IMAGE_SECTION_HEADER);
143 }
144
145 //
146 //*****************************************************************************
147 // Functions called from GenFw main code.
148 //*****************************************************************************
149 //
150
151 INTN
IsElfHeader(UINT8 * FileBuffer)152 IsElfHeader (
153 UINT8 *FileBuffer
154 )
155 {
156 return (FileBuffer[EI_MAG0] == ELFMAG0 &&
157 FileBuffer[EI_MAG1] == ELFMAG1 &&
158 FileBuffer[EI_MAG2] == ELFMAG2 &&
159 FileBuffer[EI_MAG3] == ELFMAG3);
160 }
161
162 BOOLEAN
ConvertElf(UINT8 ** FileBuffer,UINT32 * FileLength)163 ConvertElf (
164 UINT8 **FileBuffer,
165 UINT32 *FileLength
166 )
167 {
168 ELF_FUNCTION_TABLE ElfFunctions;
169 UINT8 EiClass;
170
171 //
172 // Determine ELF type and set function table pointer correctly.
173 //
174 VerboseMsg ("Check Elf Image Header");
175 EiClass = (*FileBuffer)[EI_CLASS];
176 if (EiClass == ELFCLASS32) {
177 if (!InitializeElf32 (*FileBuffer, &ElfFunctions)) {
178 return FALSE;
179 }
180 } else if (EiClass == ELFCLASS64) {
181 if (!InitializeElf64 (*FileBuffer, &ElfFunctions)) {
182 return FALSE;
183 }
184 } else {
185 Error (NULL, 0, 3000, "Unsupported", "ELF EI_CLASS not supported.");
186 return FALSE;
187 }
188
189 //
190 // Compute sections new address.
191 //
192 VerboseMsg ("Compute sections new address.");
193 ElfFunctions.ScanSections ();
194
195 //
196 // Write and relocate sections.
197 //
198 VerboseMsg ("Write and relocate sections.");
199 ElfFunctions.WriteSections (SECTION_TEXT);
200 ElfFunctions.WriteSections (SECTION_DATA);
201 ElfFunctions.WriteSections (SECTION_HII);
202
203 //
204 // Translate and write relocations.
205 //
206 VerboseMsg ("Translate and write relocations.");
207 ElfFunctions.WriteRelocations ();
208
209 //
210 // Write debug info.
211 //
212 VerboseMsg ("Write debug info.");
213 ElfFunctions.WriteDebug ();
214
215 //
216 // Make sure image size is correct before returning the new image.
217 //
218 VerboseMsg ("Set image size.");
219 ElfFunctions.SetImageSize ();
220
221 //
222 // Replace.
223 //
224 free (*FileBuffer);
225 *FileBuffer = mCoffFile;
226 *FileLength = mCoffOffset;
227
228 //
229 // Free resources used by ELF functions.
230 //
231 ElfFunctions.CleanUp ();
232
233 return TRUE;
234 }
235