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