1 /*
2  * Copyright (C) 2020-2022 Intel Corporation.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #include <types.h>
8 #include <errno.h>
9 #include <asm/pgtable.h>
10 #include <boot.h>
11 #include "multiboot_priv.h"
12 
13 /**
14  * @pre abi != NULL
15  */
multiboot_to_acrn_bi(struct acrn_boot_info * abi,void * mb_info)16 int32_t multiboot_to_acrn_bi(struct acrn_boot_info *abi, void *mb_info) {
17 	uint32_t i;
18 	struct multiboot_info *mbi = (struct multiboot_info *)(hpa2hva_early((uint64_t)mb_info));
19 	struct multiboot_mmap *mmap = (struct multiboot_mmap *)hpa2hva_early((uint64_t)mbi->mi_mmap_addr);
20 	struct multiboot_module *mods = (struct multiboot_module *)hpa2hva_early((uint64_t)mbi->mi_mods_addr);
21 
22 	(void)strncpy_s((void *)(abi->cmdline), MAX_BOOTARGS_SIZE, (char *)hpa2hva_early((uint64_t)mbi->mi_cmdline),
23 				strnlen_s((char *)hpa2hva_early((uint64_t)mbi->mi_cmdline), (MAX_BOOTARGS_SIZE - 1U)));
24 
25 	(void)strncpy_s((void *)(abi->loader_name), MAX_LOADER_NAME_SIZE,
26 			(char *)hpa2hva_early((uint64_t)mbi->mi_loader_name),
27 			strnlen_s((char *)hpa2hva_early((uint64_t)mbi->mi_loader_name), (MAX_LOADER_NAME_SIZE - 1U)));
28 
29 	abi->mmap_entries = mbi->mi_mmap_length / sizeof(struct multiboot_mmap);
30 
31 	if (((mbi->mi_flags & MULTIBOOT_INFO_HAS_MMAP) != 0U) && (abi->mmap_entries != 0U) && (mmap != NULL)) {
32 
33 		if (abi->mmap_entries > MAX_MMAP_ENTRIES) {
34 			abi->mmap_entries = MAX_MMAP_ENTRIES;
35 		}
36 
37 		for (i = 0U; i < abi->mmap_entries; i++) {
38 			abi->mmap_entry[i].baseaddr = (mmap + i)->baseaddr;
39 			abi->mmap_entry[i].length = (mmap + i)->length;
40 			abi->mmap_entry[i].type = (mmap + i)->type;
41 		}
42 	} else {
43 		abi->mmap_entries = 0U;
44 	}
45 
46 	abi->mods_count = mbi->mi_mods_count;
47 	if (((mbi->mi_flags & MULTIBOOT_INFO_HAS_MODS) != 0U) && (mbi->mi_mods_count != 0U) && (mods != NULL)) {
48 		if (abi->mods_count > MAX_MODULE_NUM) {
49 			abi->mods_count = MAX_MODULE_NUM;
50 		}
51 
52 		for (i = 0U; i < abi->mods_count; i++) {
53 			abi->mods[i].start = hpa2hva_early((uint64_t)(mods + i)->mm_mod_start);
54 			if ((mods + i)->mm_mod_end > (mods + i)->mm_mod_start) {
55 				abi->mods[i].size = (mods + i)->mm_mod_end - (mods + i)->mm_mod_start;
56 			}
57 			(void)strncpy_s((void *)(abi->mods[i].string), MAX_MOD_STRING_SIZE,
58 				(char *)hpa2hva_early((uint64_t)(mods + i)->mm_string),
59 				strnlen_s((char *)hpa2hva_early((uint64_t)(mods + i)->mm_string), MAX_BOOTARGS_SIZE));
60 		}
61 	} else {
62 		abi->mods_count = 0U;
63 	}
64 
65 	return 0;
66 }
67 
init_multiboot_info(uint32_t * registers)68 int32_t init_multiboot_info(uint32_t *registers)
69 {
70 	int32_t ret = -ENODEV;
71 	uint32_t magic = registers[0];
72 	uint32_t info = registers[1];
73 	struct acrn_boot_info *abi = get_acrn_boot_info();
74 
75 	if (boot_from_multiboot(magic, info)) {
76 		if (multiboot_to_acrn_bi(abi, hpa2hva_early((uint64_t)info)) == 0) {
77 			strncpy_s(abi->protocol_name, MAX_PROTOCOL_NAME_SIZE,
78 					"Multiboot", (MAX_PROTOCOL_NAME_SIZE - 1U));
79 			ret = 0;
80 		}
81 #ifdef CONFIG_MULTIBOOT2
82 	} else if (boot_from_multiboot2(magic)) {
83 		if (multiboot2_to_acrn_bi(abi, hpa2hva_early((uint64_t)info)) == 0) {
84 			strncpy_s(abi->protocol_name, MAX_PROTOCOL_NAME_SIZE,
85 					"Multiboot2", (MAX_PROTOCOL_NAME_SIZE - 1U));
86 			ret = 0;
87 		}
88 #endif
89 	} else {
90 		/* Currently there are only multiboot and multiboot2 */
91 	}
92 	return ret;
93 }
94