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}