1 /*
2 * Copyright (c) 2011 - 2022, Intel Corporation.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 *
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer
12 * in the documentation and/or other materials provided with the
13 * distribution.
14 * * Neither the name of Intel Corporation nor the names of its
15 * contributors may be used to endorse or promote products
16 * derived from this software without specific prior written
17 * permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
22 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
23 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
24 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
25 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
28 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
30 * OF THE POSSIBILITY OF SUCH DAMAGE.
31 *
32 * This file contains some wrappers around the gnu-efi functions. As
33 * we're not going through uefi_call_wrapper() directly, this allows
34 * us to get some type-safety for function call arguments and for the
35 * compiler to check that the number of function call arguments is
36 * correct.
37 *
38 * It's also a good place to document the EFI interface.
39 */
40
41 #include <efi.h>
42 #include <efilib.h>
43 #include "stdlib.h"
44
45 #define DOS_FILE_MAGIC_NUMBER 0x5A4D /* "MZ" */
46 struct DosFileHeader {
47 uint16_t mMagic;
48 uint16_t LastSize;
49 uint16_t nBlocks;
50 uint16_t nReloc;
51 uint16_t HdrSize;
52 uint16_t MinAlloc;
53 uint16_t MaxAlloc;
54 uint16_t ss;
55 uint16_t sp;
56 uint16_t Checksum;
57 uint16_t ip;
58 uint16_t cs;
59 uint16_t RelocPos;
60 uint16_t nOverlay;
61 uint16_t reserved[4];
62 uint16_t OEMId;
63 uint16_t OEMInfo;
64 uint16_t reserved2[10];
65 uint32_t ExeHeader;
66 } __attribute__((packed));
67
68 #define IMAGE_FILE_MACHINE_I386 0x14c
69 #define IMAGE_FILE_MACHINE_AMD64 0x8664
70 #define PE_FILE_MAGIC_NUMBER 0x00004550 /* "PE\0\0" */
71 struct PeHeader {
72 uint32_t mMagic;
73 uint16_t mMachine;
74 uint16_t mNumberOfSections;
75 uint32_t mTimeDateStamp;
76 uint32_t mPointerToSymbolTable;
77 uint32_t mNumberOfSymbols;
78 uint16_t mSizeOfOptionalHeader;
79 uint16_t mCharacteristics;
80 } __attribute__((packed));
81
82 struct OptionHeader {
83 uint16_t Format;
84 uint8_t MajorLinkVer;
85 uint8_t MinorLinkVer;
86 uint32_t CodeSize;
87 uint32_t InitializedDataSize;
88 uint32_t UninitializedDataSize;
89 uint32_t EntryPoint;
90 uint32_t BaseOfCode;
91 uint32_t BaseOfDate;
92 } __attribute__((packed));
93
94
95 struct PeSectionHeader {
96 char mName[8];
97 uint32_t mVirtualSize;
98 uint32_t mVirtualAddress;
99 uint32_t mSizeOfRawData;
100 uint32_t mPointerToRawData;
101 uint32_t mPointerToRealocations;
102 uint32_t mPointerToLinenumbers;
103 uint16_t mNumberOfRealocations;
104 uint16_t mNumberOfLinenumbers;
105 uint32_t mCharacteristics;
106 } __attribute__((packed));
107
108
get_pe_section(CHAR8 * base,char * section_name,UINTN section_name_len,UINTN * vaddr,UINTN * size)109 EFI_STATUS get_pe_section(CHAR8 *base, char *section_name,
110 UINTN section_name_len, UINTN *vaddr, UINTN *size)
111 {
112 struct PeSectionHeader *ph;
113 struct DosFileHeader *dh;
114 struct PeHeader *pe;
115 UINTN i;
116 UINTN offset;
117
118 dh = (struct DosFileHeader *)base;
119
120 if (dh->mMagic != DOS_FILE_MAGIC_NUMBER)
121 return EFI_LOAD_ERROR;
122
123 pe = (struct PeHeader *)&base[dh->ExeHeader];
124 if (pe->mMagic != PE_FILE_MAGIC_NUMBER)
125 return EFI_LOAD_ERROR;
126
127 if ((pe->mMachine != IMAGE_FILE_MACHINE_AMD64)
128 && (pe->mMachine != IMAGE_FILE_MACHINE_I386))
129 return EFI_LOAD_ERROR;
130
131 offset = dh->ExeHeader + sizeof(*pe) + pe->mSizeOfOptionalHeader;
132
133 for (i = 0; i < pe->mNumberOfSections; i++) {
134 ph = (struct PeSectionHeader *)&base[offset];
135 if (CompareMem(ph->mName, section_name, section_name_len) == 0) {
136 *vaddr = (UINTN)ph->mVirtualAddress;
137 *size = (UINTN)ph->mVirtualSize;
138 break;
139 }
140
141 offset += sizeof(*ph);
142 }
143
144 return EFI_SUCCESS;
145 }
146
147
get_pe_entry(CHAR8 * base)148 EFI_IMAGE_ENTRY_POINT get_pe_entry(CHAR8 *base)
149 {
150 struct DosFileHeader* dh;
151 struct PeHeader* pe;
152 struct OptionHeader* oh;
153 UINTN offset;
154
155 dh = (struct DosFileHeader *)base;
156
157 if (dh->mMagic != DOS_FILE_MAGIC_NUMBER)
158 return NULL;
159
160 pe = (struct PeHeader *)&base[dh->ExeHeader];
161 if (pe->mMagic != PE_FILE_MAGIC_NUMBER)
162 return NULL;
163
164 if ((pe->mMachine != IMAGE_FILE_MACHINE_AMD64)
165 && (pe->mMachine != IMAGE_FILE_MACHINE_I386))
166 return NULL;
167
168 offset = dh->ExeHeader + sizeof(*pe);
169 oh = (struct OptionHeader*)&base[offset];
170
171 return (EFI_IMAGE_ENTRY_POINT)((UINT64)base + oh->EntryPoint);
172 }
173