1 /*-
2  * Copyright (c) 2018-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  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
14  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16  * ARE DISCLAIMED.  IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
17  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23  * SUCH DAMAGE.
24  *
25  */
26 
27 /* This is a very simple elf binary loader. It only support static elf32 binary
28  * loading. So we don't need to handle elf relocation. Just need to load the
29  * PT_LOAD section to correct memory address and set correct entry.
30  *
31  * It also prepare simple multiboot info (only memory info) to guest. If some
32  * other things are necessary for guest, we could add it per requirement.
33  */
34 
35 #include <string.h>
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <stdbool.h>
39 #include <elf.h>
40 
41 #include "types.h"
42 #include "dm.h"
43 #include "vmmapi.h"
44 #include "sw_load.h"
45 #include "acpi.h"
46 #include "log.h"
47 
48 #define	ELF_BUF_LEN			(1024UL*8UL)
49 #define	MULTIBOOT_HEAD_MAGIC		(0x1BADB002U)
50 #define	MULTIBOOT_MACHINE_STATE_MAGIC	(0x2BADB002U)
51 /* The max length for GDT is 8192 * 8 bytes */
52 #define	GDT_LOAD_OFF(ctx)		(ctx->lowmem - 64U * KB)
53 
54 static char elf_path[STR_LEN];
55 /* Whether we need to setup multiboot info for guest */
56 static int multiboot_image = 0;
57 
58 /* Multiboot info. Compatible with Multiboot spec 0.6.96 with vesa removed */
59 #define	MULTIBOOT_INFO_MEMORY		(0x00000001U)
60 #define	MULTIBOOT_INFO_BOOTDEV		(0x00000002U)
61 #define	MULTIBOOT_INFO_CMDLINE		(0x00000004U)
62 #define	MULTIBOOT_INFO_MODS		(0x00000008U)
63 #define	MULTIBOOT_INFO_AOUT_SYMS	(0x00000010U)
64 #define	MULTIBOOT_INFO_ELF_SHDR		(0x00000020U)
65 #define	MULTIBOOT_INFO_MEM_MAP		(0x00000040U)
66 #define	MULTIBOOT_INFO_DRIVE_INFO	(0x00000080U)
67 #define	MULTIBOOT_INFO_CONFIG_TABLE	(0x00000100U)
68 #define	MULTIBOOT_INFO_BOOT_LOADER_NAME	(0x00000200U)
69 #define	MULTIBOOT_INFO_BOOT_APM_TABLE	(0x00000400U)
70 
71 struct multiboot_info {
72 	uint32_t	flags;
73 	uint32_t	mem_lower;
74 	uint32_t	mem_upper;
75 
76 	uint32_t	boot_device;
77 	uint32_t	cmdline;
78 	uint32_t	mods_count;
79 	uint32_t	mods_addr;
80 
81 	uint32_t	bin_sec[4];
82 
83 	uint32_t	mmap_length;
84 	uint32_t	mmap_addr;
85 
86 	uint32_t	drives_length;
87 	uint32_t	drives_addr;
88 
89 	uint32_t	config_table;
90 
91 	uint32_t	boot_loader_name;
92 };
93 
94 int
acrn_parse_elf(char * arg)95 acrn_parse_elf(char *arg)
96 {
97 	int err = -1;
98 	size_t len = strnlen(arg, STR_LEN);
99 	size_t elfsz;
100 
101 	if (len < STR_LEN) {
102 		strncpy(elf_path, arg, len + 1);
103 		if (check_image(elf_path, 0, &elfsz) == 0) {
104 			elf_file_name = elf_path;
105 			pr_notice("SW_LOAD: get elf path %s\n", elf_path);
106 			err = 0;
107 		}
108 	}
109 	return err;
110 }
111 
load_elf32(struct vmctx * ctx,FILE * fp,void * buf)112 static int load_elf32(struct vmctx *ctx, FILE *fp, void *buf)
113 {
114 	int i;
115 	size_t phd_size, read_len;
116 	Elf32_Ehdr *elf32_header = (Elf32_Ehdr *)buf;
117 	Elf32_Phdr *elf32_phdr, *elf32_phdr_bk;
118 
119 	phd_size = elf32_header->e_phentsize * elf32_header->e_phnum;
120 	elf32_phdr_bk = elf32_phdr = (Elf32_Phdr *)calloc(1, phd_size);
121 	if (elf32_phdr == NULL) {
122 		pr_err("Can't allocate memory for elf program header\n");
123 		return -1;
124 	}
125 
126 	fseek(fp, elf32_header->e_phoff, SEEK_SET);
127 	read_len = fread((void *)elf32_phdr, 1, phd_size, fp);
128 	if (read_len != phd_size) {
129 		pr_err("can't get %ld data from elf file\n", phd_size);
130 	}
131 
132 	for (i = 0; i < elf32_header->e_phnum; i++) {
133 		if (elf32_phdr->p_type == PT_LOAD) {
134 			if ((elf32_phdr->p_vaddr + elf32_phdr->p_memsz) >
135 					ctx->lowmem) {
136 				pr_err("No enough memory to load elf file\n");
137 				free(elf32_phdr_bk);
138 				return -1;
139 			}
140 
141 			void *seg_ptr = ctx->baseaddr + elf32_phdr->p_vaddr;
142 
143 			/* Clear the segment memory in memory.
144 			 * This is required for BSS section
145 			 */
146 			memset(seg_ptr, 0, elf32_phdr->p_memsz);
147 			fseek(fp, elf32_phdr->p_offset, SEEK_SET);
148 			read_len = fread(seg_ptr, 1, elf32_phdr->p_filesz, fp);
149 			if (read_len != elf32_phdr->p_filesz) {
150 				pr_err("Can't get %d data\n",
151 						elf32_phdr->p_filesz);
152 			}
153 		}
154 
155 		elf32_phdr++;
156 	}
157 
158 	free(elf32_phdr_bk);
159 	return 0;
160 }
161 
162 static int
acrn_load_elf(struct vmctx * ctx,char * elf_file_name,unsigned long * entry,uint32_t * multiboot_flags)163 acrn_load_elf(struct vmctx *ctx, char *elf_file_name, unsigned long *entry,
164 		uint32_t *multiboot_flags)
165 {
166 	int i, ret = 0;
167 	FILE *fp;
168 	size_t read_len = 0;
169 	unsigned int *ptr32;
170 	char *elf_buf;
171 	Elf32_Ehdr *elf_ehdr;
172 
173 
174 	elf_buf = calloc(1, ELF_BUF_LEN);
175 	if (elf_buf == NULL) {
176 		pr_err("Can't allocate elf buf\r\n");
177 		return -1;
178 	}
179 
180 	fp = fopen(elf_file_name, "r");
181 	if (fp == NULL) {
182 		pr_err("Can't open elf file: %s\r\n", elf_file_name);
183 		free(elf_buf);
184 		return -1;
185 	}
186 
187 	read_len = fread(elf_buf, 1, ELF_BUF_LEN, fp);
188 	if (read_len != ELF_BUF_LEN) {
189 		pr_err("Can't get %ld data from elf file\n",
190 				ELF_BUF_LEN);
191 	}
192 
193 	/* Scan the first 8k to detect whether the elf needs multboot
194 	 * info prepared.
195 	 */
196 	ptr32 = (unsigned int *) elf_buf;
197 	for (i = 0; i <= ((ELF_BUF_LEN/4) - 3); i++) {
198 		if (ptr32[i] == MULTIBOOT_HEAD_MAGIC) {
199 			int j = 0;
200 			unsigned int sum = 0;
201 
202 			/* According to multiboot spec 0.6.96 sec 3.1.2.
203 			 * There are three u32:
204 			 *  offset   field
205 			 *    0      multiboot_head_magic
206 			 *    4      flags
207 			 *    8      checksum
208 			 * The sum of these three u32 should be u32 zero.
209 			 */
210 			for (j = 0; j < 3; j++) {
211 				sum += ptr32[j + i];
212 			}
213 
214 			if (0 == sum) {
215 				multiboot_image = 1;
216 				*multiboot_flags = ptr32[i + 1];
217 			}
218 			break;
219 		}
220 	}
221 
222 	elf_ehdr = (Elf32_Ehdr *) elf_buf;
223 
224 	if ((elf_ehdr->e_ident[EI_MAG0] != ELFMAG0) ||
225 		(elf_ehdr->e_ident[EI_MAG1] != ELFMAG1) ||
226 		(elf_ehdr->e_ident[EI_MAG2] != ELFMAG2) ||
227 		(elf_ehdr->e_ident[EI_MAG3] != ELFMAG3)) {
228 		pr_err("This is not elf file\n");
229 		fclose(fp);
230 		free(elf_buf);
231 
232 		return -1;
233 	}
234 
235 	if (elf_ehdr->e_ident[EI_CLASS] == ELFCLASS32) {
236 		ret = load_elf32(ctx, fp, elf_buf);
237 	} else {
238 		pr_err("No available 64bit elf loader ready yet\n");
239 		fclose(fp);
240 		free(elf_buf);
241 		return -1;
242 	}
243 
244 	*entry = elf_ehdr->e_entry;
245 	fclose(fp);
246 	free(elf_buf);
247 
248 	return ret;
249 }
250 
251 /* Where we put multboot info to */
252 #define	MULTIBOOT_OFFSET	(0x20000)
253 static const uint64_t acrn_init_gdt[] = {
254 	0x0UL,
255 	0x00CF9B000000FFFFUL,	/* Linear Code */
256 	0x00CF93000000FFFFUL,	/* Linear Data */
257 };
258 
259 int
acrn_sw_load_elf(struct vmctx * ctx)260 acrn_sw_load_elf(struct vmctx *ctx)
261 {
262 	int ret;
263 	uint32_t multiboot_flags = 0;
264 	uint64_t entry = 0;
265 	struct multiboot_info *mi;
266 
267 	ret = acrn_load_elf(ctx, elf_file_name, &entry, &multiboot_flags);
268 	if (ret < 0)
269 		return ret;
270 
271 	/* set guest bsp state. Will call hypercall set bsp state
272 	 * after bsp is created.
273 	 */
274 	memset(&ctx->bsp_regs, 0, sizeof( struct acrn_vcpu_regs));
275 	ctx->bsp_regs.vcpu_id = 0;
276 
277 	memcpy(ctx->baseaddr + GDT_LOAD_OFF(ctx), &acrn_init_gdt,
278 			sizeof(acrn_init_gdt));
279 	ctx->bsp_regs.vcpu_regs.gdt.limit = sizeof(acrn_init_gdt) - 1;
280 	ctx->bsp_regs.vcpu_regs.gdt.base = GDT_LOAD_OFF(ctx);
281 
282 	/* CR0_ET | CR0_NE | CR0_PE */
283 	ctx->bsp_regs.vcpu_regs.cr0 = 0x31U;
284 
285 	ctx->bsp_regs.vcpu_regs.cs_ar = 0xCF9BU;
286 	ctx->bsp_regs.vcpu_regs.cs_sel = 0x8U;
287 	ctx->bsp_regs.vcpu_regs.cs_limit = 0xFFFFFFFFU;
288 
289 	ctx->bsp_regs.vcpu_regs.ds_sel = 0x10U;
290 	ctx->bsp_regs.vcpu_regs.ss_sel = 0x10U;
291 	ctx->bsp_regs.vcpu_regs.es_sel = 0x10U;
292 	ctx->bsp_regs.vcpu_regs.gs_sel = 0x10U;
293 	ctx->bsp_regs.vcpu_regs.fs_sel = 0x10U;
294 
295 	ctx->bsp_regs.vcpu_regs.rip = entry;
296 	ctx->bsp_regs.vcpu_regs.gprs.rax = MULTIBOOT_MACHINE_STATE_MAGIC;
297 
298 	if (multiboot_image == 1) {
299 		mi = (struct multiboot_info *)(ctx->baseaddr + MULTIBOOT_OFFSET);
300 		memset(mi, 0, sizeof(*mi));
301 
302 		if (multiboot_flags == (1 << 1)) {
303 			/* Now, we only support elf binary request multiboot
304 			 * info with memory info filled case.
305 			 *
306 			 * TODO:
307 			 * For other elf image with multiboot enabled, they
308 			 * may need more fileds initialized here. We will add
309 			 * them here per each requirement.
310 			 */
311 			mi->flags = MULTIBOOT_INFO_MEMORY;
312 			mi->mem_lower = 0;
313 			mi->mem_upper = GDT_LOAD_OFF(ctx) / 1024U;
314 			ctx->bsp_regs.vcpu_regs.gprs.rbx = MULTIBOOT_OFFSET;
315 		} else {
316 			pr_err("Invalid multiboot header in elf binary\n");
317 			return -1;
318 		}
319 	}
320 
321 	return 0;
322 }
323