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