kernel/object/handle/
syscall.rs

1//! Handle introspection system call
2//! 
3//! Provides sys_handle_query for KernelObject type and capability discovery
4
5use crate::{
6    arch::Trapframe, 
7    task::mytask, 
8    object::{
9        introspection::KernelObjectInfo,
10        handle::HandleType,
11        handle::StandardInputOutput,
12        handle::HandleMetadata
13    }
14};
15
16/// sys_handle_query - Get information about a KernelObject handle
17/// 
18/// This system call allows user space to discover the type and capabilities
19/// of a KernelObject, enabling type-safe wrapper implementations.
20/// 
21/// # Arguments
22/// - handle: The handle to query
23/// - info_ptr: Pointer to KernelObjectInfo structure to fill
24/// 
25/// # Returns
26/// - 0 on success
27/// - usize::MAX on error
28pub fn sys_handle_query(trapframe: &mut Trapframe) -> usize {
29    let task = match mytask() {
30        Some(task) => task,
31        None => return usize::MAX,
32    };
33    
34    let handle = trapframe.get_arg(0) as u32;
35    let info_ptr = trapframe.get_arg(1);
36    
37    // Increment PC to avoid infinite loop
38    trapframe.increment_pc_next(task);
39    
40    // Translate the pointer to get access to the info structure
41    let info_vaddr = match task.vm_manager.translate_vaddr(info_ptr) {
42        Some(addr) => addr as *mut KernelObjectInfo,
43        None => return usize::MAX, // Invalid pointer
44    };
45    
46    // Get object information
47    match task.handle_table.get_object_info(handle) {
48        Some(info) => {
49            // Write the information to user space
50            unsafe {
51                *info_vaddr = info;
52            }
53            0 // Success
54        }
55        None => usize::MAX, // Invalid handle
56    }
57}
58
59/// Change handle role after creation
60/// 
61/// Arguments:
62/// - handle: Handle to modify
63/// - new_role: New HandleType role
64/// - flags: Additional flags
65/// 
66/// Returns:
67/// - 0 on success
68/// - usize::MAX on error
69pub fn sys_handle_set_role(trapframe: &mut Trapframe) -> usize {
70    let task = match mytask() {
71        Some(task) => task,
72        None => return usize::MAX,
73    };
74    
75    let handle = trapframe.get_arg(0) as u32;
76    let new_role_raw = trapframe.get_arg(1);
77    let _flags = trapframe.get_arg(2);
78    
79    trapframe.increment_pc_next(task);
80    
81    // Decode new role from raw value
82    let new_role = match decode_handle_type(new_role_raw) {
83        Some(role) => role,
84        None => return usize::MAX, // Invalid role
85    };
86    
87    // Get current metadata and verify handle exists
88    let current_metadata = match task.handle_table.get_metadata(handle) {
89        Some(meta) => meta.clone(),
90        None => return usize::MAX, // Invalid handle
91    };
92    
93    // Create new metadata with updated role
94    let new_metadata = HandleMetadata {
95        handle_type: new_role,
96        access_mode: current_metadata.access_mode,
97        special_semantics: current_metadata.special_semantics,
98    };
99    
100    // Update metadata in handle table
101    if let Err(_) = task.handle_table.update_metadata(handle, new_metadata) {
102        return usize::MAX; // Update failed
103    }
104    
105    0 // Success
106}
107
108/// Close a handle (sys_handle_close)
109/// 
110/// This system call closes a handle and removes it from the handle table.
111/// 
112/// # Arguments
113/// - handle: The handle to close
114/// 
115/// # Returns
116/// - 0 on success
117/// - usize::MAX on error (invalid handle)
118pub fn sys_handle_close(trapframe: &mut Trapframe) -> usize {
119    let task = match mytask() {
120        Some(task) => task,
121        None => return usize::MAX,
122    };
123    
124    let handle = trapframe.get_arg(0) as u32;
125    trapframe.increment_pc_next(task);
126    
127    if task.handle_table.remove(handle).is_some() {
128        0 // Success
129    } else {
130        usize::MAX // Invalid handle
131    }
132}
133
134/// Duplicate a handle (sys_handle_duplicate)
135/// 
136/// This system call creates a new handle that refers to the same kernel object
137/// as the original handle.
138/// 
139/// # Arguments
140/// - handle: The handle to duplicate
141/// 
142/// # Returns
143/// - New handle number on success
144/// - usize::MAX on error (invalid handle, handle table full)
145pub fn sys_handle_duplicate(trapframe: &mut Trapframe) -> usize {
146    let task = match mytask() {
147        Some(task) => task,
148        None => return usize::MAX,
149    };
150    
151    let handle = trapframe.get_arg(0) as u32;
152    trapframe.increment_pc_next(task);
153    
154    // Check if the handle exists and get the kernel object
155    if let Some(kernel_obj) = task.handle_table.get(handle) {
156        // Insert a new handle for the same object
157        match task.handle_table.insert(kernel_obj.clone()) {
158            Ok(new_handle) => new_handle as usize,
159            Err(_) => usize::MAX, // Handle table full
160        }
161    } else {
162        usize::MAX // Invalid handle
163    }
164}
165
166/// Decode HandleType from raw value
167fn decode_handle_type(raw: usize) -> Option<HandleType> {
168    match raw {
169        0 => Some(HandleType::Regular),
170        1 => Some(HandleType::IpcChannel),
171        2 => Some(HandleType::StandardInputOutput(StandardInputOutput::Stdin)),
172        3 => Some(HandleType::StandardInputOutput(StandardInputOutput::Stdout)),
173        4 => Some(HandleType::StandardInputOutput(StandardInputOutput::Stderr)),
174        _ => None,
175    }
176}
177
178/// Encode HandleType to raw value for user space
179pub fn encode_handle_type(handle_type: &HandleType) -> usize {
180    match handle_type {
181        HandleType::Regular => 0,
182        HandleType::IpcChannel => 1,
183        HandleType::StandardInputOutput(StandardInputOutput::Stdin) => 2,
184        HandleType::StandardInputOutput(StandardInputOutput::Stdout) => 3,
185        HandleType::StandardInputOutput(StandardInputOutput::Stderr) => 4,
186    }
187}