Firmware port: Pretend to be qemu, implement all indexes used by seabios
This commit is contained in:
parent
753fcb25c7
commit
04d282c298
12
src/const.js
12
src/const.js
|
@ -304,9 +304,21 @@ var IA32_APIC_BASE_EN = 1 << 11;
|
|||
/** @const */ var TSR_LDT = 0x60;
|
||||
|
||||
|
||||
// https://github.com/qemu/seabios/blob/14221cd86eadba82255fdc55ed174d401c7a0a04/src/fw/paravirt.c#L205-L219
|
||||
|
||||
/** @const */ var FW_CFG_SIGNATURE = 0x00;
|
||||
/** @const */ var FW_CFG_ID = 0x01;
|
||||
/** @const */ var FW_CFG_RAM_SIZE = 0x03;
|
||||
/** @const */ var FW_CFG_NB_CPUS = 0x05;
|
||||
/** @const */ var FW_CFG_MAX_CPUS = 0x0F;
|
||||
/** @const */ var FW_CFG_NUMA = 0x0D;
|
||||
/** @const */ var FW_CFG_FILE_DIR = 0x19;
|
||||
|
||||
/** @const */ var FW_CFG_CUSTOM_START = 0x8000;
|
||||
// This value is specific to v86, choosen to hopefully not collide with other indexes
|
||||
/** @const */ var FW_CFG_FILE_START = 0xC000;
|
||||
|
||||
/** @const */ var FW_CFG_SIGNATURE_QEMU = 0x554D4551;
|
||||
|
||||
|
||||
/** @const */
|
||||
|
|
103
src/cpu.js
103
src/cpu.js
|
@ -231,7 +231,9 @@ function CPU(bus, wm, v86oxide, coverage_logger)
|
|||
// debug registers
|
||||
this.dreg = v86util.view(Int32Array, memory, 684, 8);
|
||||
|
||||
this.fw_value = v86util.view(Int32Array, memory, 720, 1);
|
||||
this.fw_value = [];
|
||||
this.fw_pointer = 0;
|
||||
this.option_roms = [];
|
||||
|
||||
this.io = undefined;
|
||||
|
||||
|
@ -439,7 +441,7 @@ CPU.prototype.get_state = function()
|
|||
state[60] = this.devices.pic;
|
||||
|
||||
state[61] = this.a20_enabled[0];
|
||||
state[62] = this.fw_value[0];
|
||||
state[62] = this.fw_value;
|
||||
|
||||
state[63] = this.devices.ioapic;
|
||||
|
||||
|
@ -531,7 +533,7 @@ CPU.prototype.set_state = function(state)
|
|||
this.devices.pic = state[60];
|
||||
|
||||
this.a20_enabled[0] = state[61];
|
||||
this.fw_value[0] = state[62];
|
||||
this.fw_value[0] = state;
|
||||
|
||||
this.devices.ioapic = state[63];
|
||||
|
||||
|
@ -676,7 +678,7 @@ CPU.prototype.reset = function()
|
|||
this.devices.virtio.reset();
|
||||
}
|
||||
|
||||
this.fw_value[0] = 0;
|
||||
this.fw_value = [];
|
||||
|
||||
this.jit_clear_cache();
|
||||
};
|
||||
|
@ -756,32 +758,107 @@ CPU.prototype.init = function(settings, device_bus)
|
|||
io.register_read(0x511, this, function()
|
||||
{
|
||||
// bios config port (used by seabios and kvm-unit-test)
|
||||
let result = this.fw_value[0] & 0xFF;
|
||||
this.fw_value[0] >>>= 8;
|
||||
return result;
|
||||
if(this.fw_pointer < this.fw_value.length)
|
||||
{
|
||||
return this.fw_value[this.fw_pointer++];
|
||||
}
|
||||
else
|
||||
{
|
||||
dbg_assert(false, "config port: Read past value");
|
||||
return 0;
|
||||
}
|
||||
});
|
||||
io.register_write(0x510, this, undefined, function(value)
|
||||
{
|
||||
dbg_log("bios config port, index=" + h(value));
|
||||
|
||||
function i32(x)
|
||||
{
|
||||
return new Uint8Array(new Int32Array([x]).buffer);
|
||||
}
|
||||
|
||||
function i64(x0, x1)
|
||||
{
|
||||
return new Uint8Array(new Int32Array([x0, x1]).buffer);
|
||||
}
|
||||
|
||||
function to_be16(x)
|
||||
{
|
||||
return x >> 8 | x << 8 & 0xFF00;
|
||||
}
|
||||
|
||||
function to_be32(x)
|
||||
{
|
||||
return x << 24 | x << 8 & 0xFF0000 | x >> 8 & 0xFF00 | x >>> 24;
|
||||
}
|
||||
|
||||
this.fw_pointer = 0;
|
||||
|
||||
if(value === FW_CFG_SIGNATURE)
|
||||
{
|
||||
// We could pretend to be QEMU here to control certain options in
|
||||
// seabios, but for now this isn't needed
|
||||
this.fw_value[0] = 0xfab0fab0|0;
|
||||
// Pretend to be qemu (for seabios)
|
||||
this.fw_value = i32(FW_CFG_SIGNATURE_QEMU);
|
||||
}
|
||||
else if(value === FW_CFG_ID)
|
||||
{
|
||||
this.fw_value = i32(0);
|
||||
}
|
||||
else if(value === FW_CFG_RAM_SIZE)
|
||||
{
|
||||
this.fw_value[0] = this.memory_size[0];
|
||||
this.fw_value = i32(this.memory_size[0]);
|
||||
}
|
||||
else if(value === FW_CFG_NB_CPUS)
|
||||
{
|
||||
this.fw_value[0] = 1;
|
||||
this.fw_value = i32(1);
|
||||
}
|
||||
else if(value === FW_CFG_MAX_CPUS)
|
||||
{
|
||||
this.fw_value = i32(1);
|
||||
}
|
||||
else if(value === FW_CFG_NUMA)
|
||||
{
|
||||
this.fw_value = i64(0);
|
||||
}
|
||||
else if(value === FW_CFG_FILE_DIR)
|
||||
{
|
||||
const buffer_size = 4 + 64 * this.option_roms.length;
|
||||
const buffer32 = new Int32Array(buffer_size);
|
||||
const buffer8 = new Uint8Array(buffer32.buffer);
|
||||
|
||||
buffer32[0] = to_be32(this.option_roms.length);
|
||||
|
||||
for(let i = 0; i < this.option_roms.length; i++)
|
||||
{
|
||||
const { name, data } = this.option_roms[i];
|
||||
const file_struct_ptr = 4 + 64 * i;
|
||||
|
||||
dbg_assert(FW_CFG_FILE_START + i < 0x10000);
|
||||
buffer32[file_struct_ptr + 0 >> 2] = to_be32(data.length);
|
||||
buffer32[file_struct_ptr + 4 >> 2] = to_be16(FW_CFG_FILE_START + i);
|
||||
|
||||
dbg_assert(name.length < 64 - 8);
|
||||
|
||||
for(let j = 0; j < name.length; j++)
|
||||
{
|
||||
buffer8[file_struct_ptr + 8 + j] = name.charCodeAt(j);
|
||||
}
|
||||
}
|
||||
|
||||
this.fw_value = buffer8;
|
||||
}
|
||||
else if(value >= FW_CFG_CUSTOM_START && value < FW_CFG_FILE_START)
|
||||
{
|
||||
this.fw_value = i32(0);
|
||||
}
|
||||
else if(value >= FW_CFG_FILE_START && value - FW_CFG_FILE_START < this.option_roms.length)
|
||||
{
|
||||
const i = value - FW_CFG_FILE_START;
|
||||
this.fw_value = this.option_roms[i].data;
|
||||
}
|
||||
else
|
||||
{
|
||||
dbg_assert(false, "Unimplemented fw index: " + h(value));
|
||||
this.fw_value[0] = 0;
|
||||
this.fw_value = i32(0);
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -36,7 +36,7 @@ pub const prefixes: *mut u8 = 648 as *mut u8;
|
|||
pub const timestamp_counter: *mut u32 = 664 as *mut u32;
|
||||
pub const sreg: *mut u16 = 668 as *mut u16;
|
||||
pub const dreg: *mut i32 = 684 as *mut i32;
|
||||
pub const fw_value: *mut i32 = 720 as *mut i32;
|
||||
|
||||
pub const segment_is_null: *mut bool = 724 as *mut bool;
|
||||
pub const segment_offsets: *mut i32 = 736 as *mut i32;
|
||||
pub const segment_limits: *mut u32 = 768 as *mut u32;
|
||||
|
|
Loading…
Reference in a new issue