kernel/abi/mod.rs
1//! ABI module.
2//!
3//! This module provides the interface for ABI (Application Binary Interface) modules
4//! in the Scarlet kernel. ABI modules are responsible for handling system calls
5//! and providing the necessary functionality for different application binary
6//! interfaces.
7//!
8
9use crate::{arch::Trapframe, fs::{drivers::overlayfs::OverlayFS, VfsManager}, task::mytask};
10use alloc::{boxed::Box, string::{String, ToString}, sync::Arc, vec::Vec};
11use hashbrown::HashMap;
12use spin::Mutex;
13
14pub mod scarlet;
15pub mod xv6;
16
17pub const MAX_ABI_LENGTH: usize = 64;
18
19/// ABI module trait.
20///
21/// This trait defines the interface for ABI modules in the Scarlet kernel.
22/// ABI modules are responsible for handling system calls and providing
23/// the necessary functionality for different application binary interfaces.
24///
25/// Each ABI module must implement Clone to support task cloning with
26/// independent ABI state per task.
27///
28pub trait AbiModule: 'static {
29 fn name() -> &'static str
30 where
31 Self: Sized;
32
33 fn get_name(&self) -> String;
34
35 /// Clone this ABI module into a boxed trait object
36 ///
37 /// This method enables cloning ABI modules as trait objects,
38 /// allowing each task to have its own independent ABI instance.
39 fn clone_boxed(&self) -> Box<dyn AbiModule>;
40
41 fn handle_syscall(&mut self, trapframe: &mut Trapframe) -> Result<usize, &'static str>;
42
43 /// Determine if a binary can be executed by this ABI and return confidence
44 ///
45 /// This method reads binary content directly from the file object and
46 /// executes ABI-specific detection logic (magic bytes, header structure,
47 /// entry point validation, etc.).
48 ///
49 /// # Arguments
50 /// * `file_object` - Binary file to check (in KernelObject format)
51 /// * `file_path` - File path (for auxiliary detection like file extensions)
52 /// * `current_abi` - Current task's ABI reference for inheritance/compatibility decisions
53 ///
54 /// # Returns
55 /// * `Some(confidence)` - Confidence level (0-100) if executable by this ABI
56 /// * `None` - Not executable by this ABI
57 ///
58 /// # Implementation Guidelines
59 /// - Use file_object.as_file() to access FileObject
60 /// - Use StreamOps::read() to directly read file content
61 /// - Check ABI-specific magic bytes and header structures
62 /// - Validate entry point and architecture compatibility
63 /// - Consider current_abi for inheritance/compatibility bonus (same ABI = higher confidence)
64 /// - Return confidence based on how well the binary matches this ABI
65 /// - No need for artificial score limitations - let each ABI decide its own confidence
66 ///
67 /// # Recommended Scoring Guidelines
68 /// - 0-30: Basic compatibility (correct magic bytes, architecture)
69 /// - 31-60: Good match (+ file extension, path hints, valid entry point)
70 /// - 61-80: Strong match (+ ABI-specific headers, symbols, sections)
71 /// - 81-100: Perfect match (+ same ABI inheritance, full validation)
72 ///
73 /// # Example Scoring Strategy
74 /// ```rust
75 /// let mut confidence = 0;
76 ///
77 /// // Basic format check
78 /// if self.is_valid_format(file_object) { confidence += 30; }
79 ///
80 /// // Entry point validation
81 /// if self.is_valid_entry_point(file_object) { confidence += 15; }
82 ///
83 /// // File path hints
84 /// if file_path.contains(self.get_name()) { confidence += 15; }
85 ///
86 /// // ABI inheritance bonus
87 /// if let Some(abi) = current_abi {
88 /// if abi.get_name() == self.get_name() { confidence += 40; }
89 /// }
90 ///
91 /// Some(confidence.min(100))
92 /// ```
93 fn can_execute_binary(&self, _file_object: &crate::object::KernelObject, _file_path: &str, _current_abi: Option<&dyn AbiModule>) -> Option<u8> {
94 // Default implementation: cannot determine
95 None
96 }
97
98 /// Handle conversion when switching ABIs
99 fn initialize_from_existing_handles(&self, _task: &mut crate::task::Task) -> Result<(), &'static str> {
100 Ok(()) // Default: no conversion needed
101 }
102
103 /// Convert environment variables from this ABI to Scarlet canonical format (in-place)
104 ///
105 /// This method is called when switching from this ABI to another ABI.
106 /// It should convert ABI-specific environment variables to a canonical
107 /// Scarlet format that can then be converted to the target ABI.
108 ///
109 /// Uses in-place modification to avoid expensive allocations.
110 ///
111 /// # Arguments
112 /// * `envp` - Mutable reference to environment variables in "KEY=VALUE" format,
113 /// will be modified to contain Scarlet canonical format
114 ///
115 /// # Implementation Guidelines
116 /// - Convert paths to absolute Scarlet namespace paths
117 /// - Normalize variable names to Scarlet conventions
118 /// - Remove ABI-specific variables that don't translate
119 /// - Ensure all paths are absolute and start with /
120 /// - Modify the vector in-place for efficiency
121 fn normalize_env_to_scarlet(&self, _envp: &mut Vec<String>) {
122 // Default: no conversion needed (assuming already in Scarlet format)
123 }
124
125 /// Convert environment variables from Scarlet canonical format to this ABI's format (in-place)
126 ///
127 /// This method is called when switching to this ABI from another ABI.
128 /// It should convert canonical Scarlet environment variables to this ABI's
129 /// specific format and namespace.
130 ///
131 /// Uses in-place modification to avoid expensive allocations.
132 ///
133 /// # Arguments
134 /// * `envp` - Mutable reference to environment variables in Scarlet canonical format,
135 /// will be modified to contain this ABI's format
136 fn denormalize_env_from_scarlet(&self, _envp: &mut Vec<String>) {
137 // Default: no conversion needed (assuming target is Scarlet format)
138 }
139
140 /// Binary execution (each ABI supports its own binary format)
141 ///
142 /// This method actually executes a binary that has already been verified
143 /// by can_execute_binary. Use file_object.as_file() to access FileObject,
144 /// and call ABI-specific loaders (ELF, PE, etc.) to load and execute the binary.
145 ///
146 /// Environment variables are passed directly as envp array, not stored in task.
147 ///
148 /// # Arguments
149 /// * `file_object` - Binary file to execute (already opened, in KernelObject format)
150 /// * `argv` - Command line arguments
151 /// * `envp` - Environment variables in "KEY=VALUE" format
152 /// * `task` - Target task (modified by this method)
153 /// * `trapframe` - Execution context (modified by this method)
154 ///
155 /// # Implementation Notes
156 /// - Use file_object.as_file() to get FileObject
157 /// - Use ABI-specific loaders (e.g., task::elf_loader)
158 /// - Environment variables are passed directly as envp parameter
159 /// - Set task's memory space, registers, and entry point
160 /// - Update trapframe registers (PC, SP) for the new process
161 /// - Recommended to restore original state on execution failure
162 ///
163 /// # Return Value Handling in Syscall Context
164 /// The Scarlet syscall mechanism works as follows:
165 /// 1. sys_execve() calls this method
166 /// 2. sys_execve() returns usize to syscall_handler()
167 /// 3. syscall_handler() returns Ok(usize) to syscall_dispatcher()
168 /// 4. syscall_dispatcher() returns Ok(usize) to trap handler
169 /// 5. Trap handler calls trapframe.set_return_value(usize) automatically
170 fn execute_binary(
171 &self,
172 file_object: &crate::object::KernelObject,
173 argv: &[&str],
174 envp: &[&str],
175 task: &mut crate::task::Task,
176 trapframe: &mut Trapframe
177 ) -> Result<(), &'static str>;
178
179 /// Get default working directory for this ABI
180 fn get_default_cwd(&self) -> &str {
181 "/" // Default: root directory
182 }
183
184 /// Setup overlay environment for this ABI (read-only base + writable layer)
185 ///
186 /// Creates overlay filesystem with provided base VFS and paths.
187 /// The TransparentExecutor is responsible for providing base_vfs, paths,
188 /// and verifying that directories exist. This method assumes that required
189 /// directories (/system/{abi}, /data/config/{abi}) have been prepared
190 /// by the user/administrator as part of system setup.
191 ///
192 /// # Arguments
193 /// * `target_vfs` - VfsManager to configure with overlay filesystem
194 /// * `base_vfs` - Base VFS containing system and config directories
195 /// * `system_path` - Path to read-only base layer (e.g., "/system/scarlet")
196 /// * `config_path` - Path to writable persistence layer (e.g., "/data/config/scarlet")
197 fn setup_overlay_environment(
198 &self,
199 target_vfs: &Arc<VfsManager>,
200 base_vfs: &Arc<VfsManager>,
201 system_path: &str,
202 config_path: &str,
203 ) -> Result<(), &'static str> {
204 // cross-vfs overlay_mount_fromはv2では未サポートのため一旦コメントアウト
205 // let lower_vfs_list = alloc::vec![(base_vfs, system_path)];
206 // target_vfs.overlay_mount_from(
207 // Some(base_vfs), // upper_vfs (base VFS)
208 // config_path, // upperdir (read-write persistent layer)
209 // lower_vfs_list, // lowerdir (read-only base system)
210 // "/" // target mount point in task VFS
211 // ).map_err(|e| {
212 // crate::println!("Failed to create cross-VFS overlay for ABI: {}", e.message);
213 // "Failed to create overlay environment"
214 // })
215 Err("overlay_mount_from (cross-vfs) is not supported in v2")
216 }
217
218 /// Setup shared resources accessible across all ABIs
219 ///
220 /// Bind mounts common directories that should be shared from base VFS.
221 /// The TransparentExecutor is responsible for providing base_vfs.
222 ///
223 /// # Arguments
224 /// * `target_vfs` - VfsManager to configure
225 /// * `base_vfs` - Base VFS containing shared directories
226 fn setup_shared_resources(
227 &self,
228 _target_vfs: &Arc<VfsManager>,
229 _base_vfs: &Arc<VfsManager>,
230 ) -> Result<(), &'static str> {
231 // TODO: VFS v2 migration - update bind_mount_from API usage
232 // Current limitation: function signature uses VFS v1 types
233 // Bind mount shared directories from base VFS
234 // target_vfs.bind_mount_from(&base_vfs, "/home", "/home")
235 // .map_err(|_| "Failed to bind mount /home")?;
236 // target_vfs.bind_mount_from(&base_vfs, "/data/shared", "/data/shared")
237 // .map_err(|_| "Failed to bind mount /data/shared")?;
238 // target_vfs.bind_mount_from(&base_vfs, "/", "/scarlet") // Read-onlyは未サポート
239 // .map_err(|_| "Failed to bind mount native Scarlet root to /scarlet")
240 Ok(())
241 }
242}
243
244/// ABI registry.
245///
246/// This struct is responsible for managing the registration and instantiation
247/// of ABI modules in the Scarlet kernel.
248///
249pub struct AbiRegistry {
250 factories: HashMap<String, fn() -> Box<dyn AbiModule>>,
251}
252
253impl AbiRegistry {
254 fn new() -> Self {
255 Self {
256 factories: HashMap::new(),
257 }
258 }
259
260 #[allow(static_mut_refs)]
261 pub fn global() -> &'static Mutex<AbiRegistry> {
262 // Lazy initialization using spin lock
263 static mut INSTANCE: Option<Mutex<AbiRegistry>> = None;
264 static INIT: spin::Once = spin::Once::new();
265
266 unsafe {
267 INIT.call_once(|| {
268 INSTANCE = Some(Mutex::new(AbiRegistry::new()));
269 });
270
271 // Safe to access after INIT.call_once is called
272 INSTANCE.as_ref().unwrap()
273 }
274 }
275
276 pub fn register<T>()
277 where
278 T: AbiModule + Default + 'static,
279 {
280 crate::early_println!("Registering ABI module: {}", T::name());
281 let mut registry = Self::global().lock();
282 registry
283 .factories
284 .insert(T::name().to_string(), || Box::new(T::default()));
285 }
286
287 pub fn instantiate(name: &str) -> Option<Box<dyn AbiModule>> {
288 let registry = Self::global().lock();
289 if let Some(factory) = registry.factories.get(name) {
290 let abi = factory();
291 return Some(abi);
292 }
293 None
294 }
295
296 /// Detect the best ABI for a binary from all registered ABI modules
297 ///
298 /// This method tries all registered ABIs and selects the one with the highest
299 /// confidence score. Each ABI internally handles inheritance bonuses and
300 /// compatibility logic based on the current task's ABI.
301 ///
302 /// # Arguments
303 /// * `file_object` - Binary file to check
304 /// * `file_path` - File path
305 ///
306 /// # Returns
307 /// * `Some((abi_name, confidence))` - Best ABI name and confidence level
308 /// * `None` - No executable ABI found
309 pub fn detect_best_abi(file_object: &crate::object::KernelObject, file_path: &str) -> Option<(String, u8)> {
310 let registry = Self::global().lock();
311
312 // Get current task's ABI reference for inheritance consideration
313 let current_abi = if let Some(task) = mytask() {
314 task.abi.as_ref().map(|abi| abi.as_ref())
315 } else {
316 None
317 };
318
319 // Try all ABI modules and find the one with highest confidence
320 // Each ABI decides its own confidence based on:
321 // - Binary format compatibility
322 // - Architecture compatibility
323 // - Entry point validity
324 // - Inheritance bonus from current ABI
325 registry.factories.iter()
326 .filter_map(|(name, factory)| {
327 let abi = factory();
328 abi.can_execute_binary(file_object, file_path, current_abi)
329 .map(|confidence| (name.clone(), confidence))
330 })
331 .max_by_key(|(_, confidence)| *confidence)
332 }
333}
334
335#[macro_export]
336macro_rules! register_abi {
337 ($ty:ty) => {
338 crate::abi::AbiRegistry::register::<$ty>();
339 };
340}
341
342pub fn syscall_dispatcher(trapframe: &mut Trapframe) -> Result<usize, &'static str> {
343 let task = mytask().unwrap();
344 let abi = task.abi.as_mut().expect("ABI not set");
345 abi.handle_syscall(trapframe)
346}