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[];
43 void * vgabios_dst = 0;
45 if (v3_gpa_to_hva(&(vm->cores[0]), VGABIOS_START, (addr_t *)&vgabios_dst) == -1) {
46 PrintError(vm, VCORE_NONE, "Could not find VGABIOS destination address\n");
50 V3_Print(vm,VCORE_NONE,"Mapping VGA BIOS of %llu bytes at gpa %p (hva %p)\n", (uint64_t)(v3_vgabios_end-v3_vgabios_start), (void*)VGABIOS_START,vgabios_dst);
51 memcpy(vgabios_dst, v3_vgabios_start, v3_vgabios_end - v3_vgabios_start);
59 if (!v3_cfg_val(bios_tree, "disable_rombios")) {
63 extern uint8_t v3_rombios_start[];
64 extern uint8_t v3_rombios_end[];
65 void * rombios_dst = 0;
69 if (v3_gpa_to_hva(&(vm->cores[0]), V3_CONFIG_BIOS_START, (addr_t *)&rombios_dst) == -1) {
70 PrintError(vm, VCORE_NONE, "Could not find ROMBIOS destination address\n");
74 V3_Print(vm,VCORE_NONE,"Mapping BIOS of %llu bytes at gpa %p (hva %p)\n", (uint64_t)(v3_rombios_end-v3_rombios_start), (void*)V3_CONFIG_BIOS_START,rombios_dst);
75 memcpy(rombios_dst, v3_rombios_start, v3_rombios_end - v3_rombios_start);
77 #ifdef V3_CONFIG_SEABIOS
79 #define SEABIOS_HIGH_START 0xfffe0000
80 #define SEABIOS_HIGH_END 0xffffffff
82 if (v3_get_mem_region(vm,V3_MEM_CORE_ANY, SEABIOS_HIGH_START)) {
83 // it is already mapped, we are done
84 // note it's mapped to the same place as the low memory copy
85 // so it's now pointing to the fresh copy
86 V3_Print(vm,VCORE_NONE,"BIOS is already mapped\n");
88 if (v3_add_shadow_mem(vm, V3_MEM_CORE_ANY,
89 SEABIOS_HIGH_START, SEABIOS_HIGH_END,
90 (addr_t)V3_PAddr(rombios_dst)) == -1) {
91 PrintError(vm, VCORE_NONE, "Error mapping SEABIOS to end of memory\n");
94 V3_Print(vm,VCORE_NONE,"BIOS mapped\n");
97 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);
105 // traditional BIOS data area (and IVT, etc). Technically only 0x400-0x4ff is the BDA
106 #define BDA_START 0x0
107 #define BDA_END 0xfff
109 // Extended BDA and EBDA2. Technically not standardized. Usually at the
110 // end of the 640K chunk. We're just using that last page to play it save
111 #define EBDA_START 0x9f000
112 #define EBDA_END 0x9ffff
114 if (v3_gpa_to_hva(&(vm->cores[0]), BDA_START, (addr_t *)&ba) == -1) {
115 PrintError(vm, VCORE_NONE, "Could not find BDA destination address\n");
119 memset(ba,0,(BDA_END-BDA_START+1));
121 V3_Print(vm,VCORE_NONE,"Cleared BDA %p (HVA %p) through %p\n",(void*)BDA_START,ba,(void*)BDA_END);
123 if (v3_gpa_to_hva(&(vm->cores[0]), EBDA_START, (addr_t *)&ba) == -1) {
124 PrintError(vm, VCORE_NONE, "Could not find EBDA destination address\n");
128 memset(ba,0,(EBDA_END-EBDA_START+1));
130 V3_Print(vm,VCORE_NONE,"Cleared EBDA %p (HVA %p) through %p\n",(void*)EBDA_START,ba,(void*)EBDA_END);
137 bios_list = v3_cfg_subtree(bios_tree, "bios");
140 char * id = v3_cfg_val(bios_list, "file");
141 char * addr = v3_cfg_val(bios_list, "address");
142 uint64_t file_ptr = 0;
144 struct v3_cfg_file * file = NULL;
147 PrintError(vm, VCORE_NONE, "Could not find bios file\n");
152 PrintError(vm, VCORE_NONE, "Could not find bios address\n");
156 file = v3_cfg_get_file(vm, id);
158 PrintError(vm, VCORE_NONE, "Invalid BIOS file: %s\n", id);
162 file_ptr = atox(addr);
164 V3_Print(vm, VCORE_NONE, "Copying BIOS ROM (%s) to %p (size=%lld)\n",
169 if (v3_gpa_to_hva(&(vm->cores[0]), (addr_t)file_ptr, (addr_t *)&dest) == -1) {
170 PrintError(vm, VCORE_NONE, "Could not find BIOS (%s) destination address\n", id);
174 memcpy((void*)dest, file->data, file->size);
176 V3_Print(vm, VCORE_NONE, "Moving on to next BIOS file\n");
177 bios_list = v3_cfg_next_branch(bios_list);
180 // NOW BLOW AWAY BDA and EBDA here
181 // possibly also reset CMOS