1use crate::error::{Result, X86Error};
2use crate::machine::{ExecutionBackend, MachineConfig};
3use crate::state::SavedState;
4use native_v86_core::native_runtime::NativeCpu;
5use std::path::{Path, PathBuf};
6
7pub struct NativeBackend {
13 cpu: Option<NativeCpu>,
14 instructions_per_step: u32,
15 ninep_root: Option<PathBuf>,
16}
17
18impl NativeBackend {
19 pub fn new() -> Self {
20 Self {
21 cpu: None,
22 instructions_per_step: 10_000,
23 ninep_root: None,
24 }
25 }
26
27 pub fn with_instructions_per_step(mut self, value: u32) -> Self {
28 self.instructions_per_step = value.max(1);
29 self
30 }
31
32 pub fn cpu(&self) -> Option<&NativeCpu> {
33 self.cpu.as_ref()
34 }
35
36 pub fn cpu_mut(&mut self) -> Option<&mut NativeCpu> {
37 self.cpu.as_mut()
38 }
39
40 pub fn with_9p_root(mut self, path: impl AsRef<Path>) -> Self {
41 self.ninep_root = Some(path.as_ref().to_path_buf());
42 self
43 }
44
45 pub fn set_9p_root(&mut self, path: impl AsRef<Path>) -> Result<()> {
46 let path = path.as_ref();
47 if let Some(cpu) = self.cpu.as_mut() {
48 cpu.set_9p_root(path)
49 .map_err(X86Error::BackendUnavailable)?;
50 }
51 self.ninep_root = Some(path.to_path_buf());
52 Ok(())
53 }
54}
55
56impl Default for NativeBackend {
57 fn default() -> Self {
58 Self::new()
59 }
60}
61
62impl ExecutionBackend for NativeBackend {
63 fn reset(&mut self, config: &MachineConfig) -> Result<()> {
64 let ram = u32::try_from(config.ram_bytes).map_err(|_| {
65 X86Error::BackendUnavailable(format!(
66 "native v86 core supports guest RAM up to 4 GiB; requested {} bytes",
67 config.ram_bytes
68 ))
69 })?;
70 let vga = u32::try_from(config.vga_memory_bytes).map_err(|_| {
71 X86Error::BackendUnavailable(format!(
72 "native v86 core supports VGA memory up to 4 GiB; requested {} bytes",
73 config.vga_memory_bytes
74 ))
75 })?;
76 let mut cpu = NativeCpu::new(ram, vga);
77 if let Some(path) = &self.ninep_root {
78 cpu.set_9p_root(path)
79 .map_err(X86Error::BackendUnavailable)?;
80 }
81 self.cpu = Some(cpu);
82 Ok(())
83 }
84
85 fn restore_state(&mut self, state: &SavedState) -> Result<()> {
86 let cpu = self.cpu.as_mut().ok_or_else(|| {
87 X86Error::BackendUnavailable("native backend must be reset before restore".to_owned())
88 })?;
89 let (state_object, buffers) = state.cpu_state_and_buffers()?;
90 cpu.restore_v86_state(&state_object, &buffers)
91 .map_err(X86Error::InvalidState)
92 }
93
94 fn step(&mut self) -> Result<bool> {
95 let cpu = self.cpu.as_mut().ok_or_else(|| {
96 X86Error::BackendUnavailable("native backend is not prepared".to_owned())
97 })?;
98 let _executed = cpu.step(self.instructions_per_step);
99 Ok(false)
102 }
103
104 fn read_memory(&self, address: u64, buffer: &mut [u8]) -> Result<()> {
105 let cpu = self.cpu.as_ref().ok_or_else(|| {
106 X86Error::BackendUnavailable("native backend is not prepared".to_owned())
107 })?;
108 let address = u32::try_from(address).map_err(|_| {
109 X86Error::InvalidImage("guest memory address exceeds 32-bit x86 range".to_owned())
110 })?;
111 if cpu.read_memory(address, buffer) {
112 Ok(())
113 } else {
114 Err(X86Error::InvalidImage(
115 "guest memory read is out of bounds".to_owned(),
116 ))
117 }
118 }
119
120 fn write_memory(&mut self, address: u64, data: &[u8]) -> Result<()> {
121 let cpu = self.cpu.as_mut().ok_or_else(|| {
122 X86Error::BackendUnavailable("native backend is not prepared".to_owned())
123 })?;
124 let address = u32::try_from(address).map_err(|_| {
125 X86Error::InvalidImage("guest memory address exceeds 32-bit x86 range".to_owned())
126 })?;
127 if cpu.write_memory(address, data) {
128 Ok(())
129 } else {
130 Err(X86Error::InvalidImage(
131 "guest memory write is out of bounds".to_owned(),
132 ))
133 }
134 }
135
136 fn vga_framebuffer_rgb(&self) -> Option<(u32, u32, Vec<u8>)> {
137 self.cpu.as_ref()?.vga_framebuffer_rgb()
138 }
139
140 fn inject_text(&mut self, text: &str) -> Result<usize> {
141 if self.cpu.is_none() {
142 return Err(X86Error::BackendUnavailable(
143 "native backend is not prepared".to_owned(),
144 ));
145 }
146 Ok(native_v86_core::native_runtime::inject_keyboard_text(text))
147 }
148}