2 * This file is part of the Palacios Virtual Machine Monitor developed
3 * by the V3VEE Project with funding from the United States National
4 * Science Foundation and the Department of Energy.
6 * The V3VEE Project is a joint project between Northwestern University
7 * and the University of New Mexico. You can find out more at
10 * Copyright (c) 2015, The V3VEE Project <http://www.v3vee.org>
11 * All rights reserved.
13 * Author: Peter Dinda <pdinda@northwestern.edu>
15 * This is free software. You are permitted to use,
16 * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
19 #include <palacios/vmm_bios.h>
20 #include <palacios/vm_guest_mem.h>
21 #include <palacios/vmm_xml.h>
25 int v3_setup_bioses(struct v3_vm_info * vm, v3_cfg_tree_t * cfg)
28 v3_cfg_tree_t * bios_tree = NULL;
29 v3_cfg_tree_t * bios_list = NULL;
31 bios_tree = v3_cfg_subtree(cfg, "bioses");
34 if (!v3_cfg_val(bios_tree, "disable_vgabios")) {
36 #if defined(V3_CONFIG_SEABIOS) || defined(V3_CONFIG_BOCHSBIOS)
38 #define VGABIOS_START 0x000c0000
41 extern uint8_t v3_vgabios_start[];
42 extern uint8_t v3_vgabios_end[];
44 V3_Print(vm,VCORE_NONE,"Mapping VGA BIOS of %llu bytes at gpa %p\n", (uint64_t)(v3_vgabios_end-v3_vgabios_start), (void*)VGABIOS_START);
46 if (v3_write_gpa_memory(&(vm->cores[0]), VGABIOS_START, v3_vgabios_end - v3_vgabios_start, v3_vgabios_start) != (v3_vgabios_end - v3_vgabios_start)) {
47 PrintError(vm, VCORE_NONE, "Could not write VGA BIOS\n");
57 if (!v3_cfg_val(bios_tree, "disable_rombios")) {
61 extern uint8_t v3_rombios_start[];
62 extern uint8_t v3_rombios_end[];
64 V3_Print(vm,VCORE_NONE,"Mapping BIOS of %llu bytes at gpa %p\n", (uint64_t)(v3_rombios_end-v3_rombios_start), (void*)V3_CONFIG_BIOS_START);
66 if (v3_write_gpa_memory(&(vm->cores[0]), V3_CONFIG_BIOS_START, v3_rombios_end - v3_rombios_start, v3_rombios_start) != (v3_rombios_end - v3_rombios_start)) {
67 PrintError(vm, VCORE_NONE, "Could not write ROM BIOS\n");
71 #ifdef V3_CONFIG_SEABIOS
73 #define SEABIOS_HIGH_START 0xfffe0000ULL
74 #define SEABIOS_HIGH_END 0x100000000ULL
76 V3_Print(vm,VCORE_NONE,"Additionally mapping SEABIOS of %llu bytes at gpa %p\n", (uint64_t)(v3_rombios_end-v3_rombios_start), (void*)SEABIOS_HIGH_START);
78 if (v3_get_mem_region(vm,V3_MEM_CORE_ANY, SEABIOS_HIGH_START)) {
79 // it is already mapped, we are done
80 // note it's mapped to the same place as the low memory copy
81 // so it's now pointing to the fresh copy
82 V3_Print(vm,VCORE_NONE,"BIOS is already mapped\n");
84 extern uint64_t v3_mem_block_size;
87 if (v3_gpa_to_hva(&(vm->cores[0]), V3_CONFIG_BIOS_START, (addr_t *)&rombios_dst) == -1) {
88 PrintError(vm, VCORE_NONE, "Could not find ROMBIOS destination address\n");
92 if (v3_add_shadow_mem(vm, V3_MEM_CORE_ANY,
93 SEABIOS_HIGH_START, SEABIOS_HIGH_END,
94 (addr_t)V3_PAddr(rombios_dst)) == -1) {
95 PrintError(vm, VCORE_NONE, "Error mapping SEABIOS to end of memory\n");
99 if ((V3_CONFIG_BIOS_START / v3_mem_block_size) !=
100 ((V3_CONFIG_BIOS_START+(SEABIOS_HIGH_END-SEABIOS_HIGH_START-1)) / v3_mem_block_size)) {
101 PrintError(vm,VCORE_NONE, "ALERT: MAPPING OF SEABIOS SPANS MEMORY BLOCKS: %llx %llx %llx\n",
102 (uint64_t) V3_CONFIG_BIOS_START,(uint64_t)(V3_CONFIG_BIOS_START+(SEABIOS_HIGH_END-SEABIOS_HIGH_START-1)), v3_mem_block_size);
105 V3_Print(vm,VCORE_NONE,"BIOS mapped\n");
115 // traditional BIOS data area (and IVT, etc). Technically only 0x400-0x4ff is the BDA
116 #define BDA_START 0x0
117 #define BDA_END 0xfff
119 // Extended BDA and EBDA2. Technically not standardized. Usually at the
120 // end of the 640K chunk. We're just using that last page to play it save
121 #define EBDA_START 0x9f000
122 #define EBDA_END 0x9ffff
124 V3_Print(vm,VCORE_NONE,"Clearing BDA %p through %p\n",(void*)BDA_START,(void*)BDA_END);
126 if (v3_set_gpa_memory(&vm->cores[0],BDA_START,BDA_END-BDA_START,0)!=BDA_END-BDA_START) {
127 PrintError(vm, VCORE_NONE, "Could not zero BDA\n");
131 V3_Print(vm,VCORE_NONE,"Clearing EBDA %p through %p\n",(void*)EBDA_START,(void*)EBDA_END);
133 if (v3_set_gpa_memory(&vm->cores[0],EBDA_START,EBDA_END-EBDA_START,0)!=EBDA_END-EBDA_START) {
134 PrintError(vm, VCORE_NONE, "Could not zero eBDA\n");
145 bios_list = v3_cfg_subtree(bios_tree, "bios");
148 char * id = v3_cfg_val(bios_list, "file");
149 char * addr = v3_cfg_val(bios_list, "address");
150 uint64_t file_ptr = 0;
151 struct v3_cfg_file * file = NULL;
154 PrintError(vm, VCORE_NONE, "Could not find bios file\n");
159 PrintError(vm, VCORE_NONE, "Could not find bios address\n");
163 file = v3_cfg_get_file(vm, id);
165 PrintError(vm, VCORE_NONE, "Invalid BIOS file: %s\n", id);
169 file_ptr = atox(addr);
171 V3_Print(vm, VCORE_NONE, "Copying BIOS ROM (%s) to %p (size=%lld)\n",
176 if (v3_write_gpa_memory(&vm->cores[0],(addr_t)file_ptr,file->size,file->data)!=file->size) {
177 PrintError(vm, VCORE_NONE, "Could not copy BIOS (%s)\n",id);
181 V3_Print(vm, VCORE_NONE, "Moving on to next BIOS file\n");
182 bios_list = v3_cfg_next_branch(bios_list);
185 // NOW BLOW AWAY BDA and EBDA here
186 // possibly also reset CMOS