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
33 #ifndef __ACRNBOOT_H__
34 #define __ACRNBOOT_H__
35
36 #include "multiboot.h"
37
38 #define E820_RAM 1
39 #define E820_RESERVED 2
40 #define E820_ACPI 3
41 #define E820_NVS 4
42 #define E820_UNUSABLE 5
43
44 #define ERROR_STRING_LENGTH 32
45 #define EFI_LOADER_SIGNATURE "EL64"
46
47 #define ACPI_XSDT_ENTRY_SIZE (sizeof(UINT64))
48 #define ACPI_NAME_SIZE 4
49 #define ACPI_OEM_ID_SIZE 6
50 #define ACPI_OEM_TABLE_ID_SIZE 8
51
52 #define MSR_IA32_PAT 0x00000277 /* PAT */
53 #define MSR_IA32_EFER 0xC0000080
54 #define MSR_IA32_FS_BASE 0xC0000100U
55 #define MSR_IA32_GS_BASE 0xC0000101
56 #define MSR_IA32_SYSENTER_ESP 0x00000175 /* ESP for sysenter */
57 #define MSR_IA32_SYSENTER_EIP 0x00000176 /* EIP for sysenter */
58
59 #define UEFI_BOOT_LOADER_NAME "ACRN UEFI loader"
60
61 #define EFI_VAR_MORCTL_NAME L"MemoryOverwriteRequestControl"
62 #define EFI_VAR_MORCTL_GUID \
63 { 0xe20939be, 0x32d4, 0x41be, { 0xa1, 0x50, 0x89, 0x7f, 0x85, 0xd4, 0x98, 0x29 } }
64 #define EFI_VAR_MORCTLLOCK_NAME L"MemoryOverwriteRequestControlLock"
65 #define EFI_VAR_MORCTLLOCK_GUID \
66 { 0xBB983CCF, 0x151D, 0x40E1, { 0xA0, 0x7B, 0x4A, 0x17, 0xBE, 0x16, 0x82, 0x92 } }
67
68 #define ALIGN_UP(addr, align) \
69 (((addr) + (typeof (addr)) (align) - 1) & ~((typeof (addr)) (align) - 1))
70
71 /* Read MSR */
72 #define CPU_MSR_READ(reg, msr_val_ptr) \
73 { \
74 uint32_t msrl, msrh; \
75 asm volatile ("rdmsr" : "=a"(msrl), \
76 "=d"(msrh) : "c" (reg)); \
77 *msr_val_ptr = ((uint64_t)msrh << 32U) | msrl; \
78 }
79
80 EFI_STATUS get_pe_section(CHAR8 *base, char *section_name, UINTN section_name_len, UINTN *vaddr, UINTN *size);
81 typedef void(*hv_func)(int32_t, struct multiboot_info*);
82
83 /*
84 * We allocate memory for the following struct together with hyperivosr itself
85 * memory allocation during boot.
86 */
87 #define MBOOT_MMAP_NUMS 256
88 #define MBOOT_MMAP_SIZE (sizeof(struct multiboot_mmap) * MBOOT_MMAP_NUMS)
89 #define MBOOT_INFO_SIZE (sizeof(struct multiboot_info))
90 #define MBOOT_MODS_NUMS 4
91 #define MBOOT_MODS_SIZE (sizeof(struct multiboot_module) * MBOOT_MODS_NUMS)
92 #define BOOT_LOADER_NAME_SIZE 17U
93 #define EFI_BOOT_MEM_SIZE \
94 (MBOOT_MMAP_SIZE + MBOOT_INFO_SIZE + MBOOT_MODS_SIZE + BOOT_LOADER_NAME_SIZE)
95 #define MBOOT_MMAP_PTR(addr) \
96 ((struct multiboot_mmap *)((VOID *)(addr)))
97 #define MBOOT_INFO_PTR(addr) \
98 ((struct multiboot_info *)((VOID *)(addr) + MBOOT_MMAP_SIZE))
99 #define MBOOT_MODS_PTR(addr) \
100 ((struct multiboot_module *)((VOID *)(addr) + MBOOT_MMAP_SIZE + MBOOT_INFO_SIZE))
101 #define BOOT_LOADER_NAME_PTR(addr) \
102 ((char *)((VOID *)(addr) + MBOOT_MMAP_SIZE + MBOOT_INFO_SIZE + MBOOT_MODS_SIZE))
103
104 struct efi_memmap_info {
105 UINTN map_size;
106 UINTN map_key;
107 UINT32 desc_version;
108 UINTN desc_size;
109 EFI_MEMORY_DESCRIPTOR *mmap;
110 };
111
112 typedef struct mb_module_info {
113 UINTN mod_start;
114 UINTN mod_end;
115 const char *cmd;
116 UINTN cmdsize;
117 } MB_MODULE_INFO;
118
119 struct efi_info {
120 UINT32 efi_loader_signature;
121 UINT32 efi_systab;
122 UINT32 efi_memdesc_size;
123 UINT32 efi_memdesc_version;
124 UINT32 efi_memmap;
125 UINT32 efi_memmap_size;
126 UINT32 efi_systab_hi;
127 UINT32 efi_memmap_hi;
128 };
129
130 struct e820_entry {
131 UINT64 addr; /* start of memory segment */
132 UINT64 size; /* size of memory segment */
133 UINT32 type; /* type of memory segment */
134 } __attribute__((packed));
135
136 struct acpi_table_rsdp {
137 /* ACPI signature, contains "RSD PTR " */
138 char signature[8];
139 /* ACPI 1.0 checksum */
140 UINT8 checksum;
141 /* OEM identification */
142 char oem_id[ACPI_OEM_ID_SIZE];
143 /* Must be (0) for ACPI 1.0 or (2) for ACPI 2.0+ */
144 UINT8 revision;
145 /* 32-bit physical address of the RSDT */
146 UINT32 rsdt_physical_address;
147 /* Table length in bytes, including header (ACPI 2.0+) */
148 UINT32 length;
149 /* 64-bit physical address of the XSDT (ACPI 2.0+) */
150 UINT64 xsdt_physical_address;
151 /* Checksum of entire table (ACPI 2.0+) */
152 UINT8 extended_checksum;
153 /* Reserved, must be zero */
154 UINT8 reserved[3];
155 };
156
157 struct acpi_table_header {
158 /* ASCII table signature */
159 char signature[ACPI_NAME_SIZE];
160 /* Length of table in bytes, including this header */
161 UINT32 length;
162 /* ACPI Specification minor version number */
163 UINT8 revision;
164 /* To make sum of entire table == 0 */
165 UINT8 checksum;
166 /* ASCII OEM identification */
167 char oem_id[ACPI_OEM_ID_SIZE];
168 /* ASCII OEM table identification */
169 char oem_table_id[ACPI_OEM_TABLE_ID_SIZE];
170 /* OEM revision number */
171 UINT32 oem_revision;
172 /* ASCII ASL compiler vendor ID */
173 char asl_compiler_id[ACPI_NAME_SIZE];
174 /* ASL compiler version */
175 UINT32 asl_compiler_revision;
176 };
177
178 /* hypervisor loader operation table */
179 typedef struct hv_loader *HV_LOADER;
180 struct hv_loader {
181 /* Load ACRN hypervisor image into memory */
182 EFI_STATUS (*load_boot_image)(IN HV_LOADER hvld);
183 /* Load VM Kernels and ACPI Tables into memory */
184 EFI_STATUS (*load_modules)(IN HV_LOADER hvld);
185
186 const char *(*get_boot_cmd)(IN HV_LOADER hvld);
187 /* Get hypervisor boot command length */
188 UINTN (*get_boot_cmdsize)(IN HV_LOADER hvld);
189
190 MB_MODULE_INFO *(*get_mods_info)(IN HV_LOADER hvld, UINTN index);
191 /* Get the number of multiboot2 modules */
192 UINTN (*get_mod_count)(IN HV_LOADER hvld);
193 /* Get the total memory size allocated to load module files */
194 UINTN (*get_total_modsize)(IN HV_LOADER hvld);
195 /* Get the total lengths of the module commands */
196 UINTN (*get_total_modcmdsize)(IN HV_LOADER hvld);
197
198 /* Get the total memory size of hv image */
199 UINTN (*get_hv_ram_size)(IN HV_LOADER hvld);
200
201 /* Get the start address of the memory region stored ACRN hypervisor image */
202 EFI_PHYSICAL_ADDRESS (*get_hv_hpa)(IN HV_LOADER hvld);
203 /* Get the start address of the memory region stored module files */
204 EFI_PHYSICAL_ADDRESS (*get_mod_hpa)(IN HV_LOADER hvld);
205 /* Get the entry point of ACRN hypervisor */
206 EFI_PHYSICAL_ADDRESS (*get_hv_entry)(IN HV_LOADER hvld);
207
208 /* Get the supported multiboot version of ACRN hypervisor image */
209 int (*get_multiboot_version)(IN HV_LOADER hvld);
210
211 /* free up memory allocated by hypervisor loader */
212 void (*deinit)(IN HV_LOADER hvld);
213 };
214
215 EFI_STATUS get_efi_memmap(struct efi_memmap_info *mmap_info, int size_only);
216
217 static inline uint64_t
msr_read(uint32_t reg_num)218 msr_read(uint32_t reg_num)
219 {
220 uint64_t msr_val;
221
222 CPU_MSR_READ(reg_num, &msr_val);
223 return msr_val;
224 }
225
226 #endif
227