1use alloc::{boxed::Box, collections::btree_map::BTreeMap, format, string::{String, ToString}, sync::Arc, vec::Vec};
9
10use crate::{arch::{vm, Registers, Trapframe}, early_initcall, fs::{drivers::overlayfs::OverlayFS, FileSystemError, FileSystemErrorKind, SeekFrom, VfsManager}, register_abi, syscall::syscall_handler, task::elf_loader::load_elf_into_task, vm::{setup_trampoline, setup_user_stack}};
11
12use super::AbiModule;
13
14#[derive(Default, Copy, Clone)]
15pub struct ScarletAbi;
16
17impl AbiModule for ScarletAbi {
18 fn name() -> &'static str {
19 "scarlet"
20 }
21
22 fn get_name(&self) -> alloc::string::String {
23 Self::name().to_string()
24 }
25
26 fn clone_boxed(&self) -> Box<dyn AbiModule> {
27 Box::new(*self) }
29
30 fn handle_syscall(&mut self, trapframe: &mut Trapframe) -> Result<usize, &'static str> {
31 syscall_handler(trapframe)
32 }
33
34 fn can_execute_binary(&self, file_object: &crate::object::KernelObject, file_path: &str, current_abi: Option<&dyn crate::abi::AbiModule>) -> Option<u8> {
35 let magic_score = match file_object.as_file() {
37 Some(file_obj) => {
38 let mut magic_buffer = [0u8; 4];
40 file_obj.seek(SeekFrom::Start(0)).ok(); match file_obj.read(&mut magic_buffer) {
42 Ok(bytes_read) if bytes_read >= 4 => {
43 if magic_buffer == [0x7F, b'E', b'L', b'F'] {
44 30 } else {
46 return None; }
48 }
49 _ => return None }
51 }
52 None => return None };
54
55 let mut confidence = magic_score;
56
57 if let Some(file_obj) = file_object.as_file() {
59 let mut osabi_buffer = [0u8; 1];
61 file_obj.seek(SeekFrom::Start(7)).ok(); match file_obj.read(&mut osabi_buffer) {
63 Ok(bytes_read) if bytes_read == 1 => {
64 if osabi_buffer[0] == 83 { confidence += 70; }
67 }
68 _ => return None }
70 } else {
71 return None; }
73
74 if file_path.ends_with(".elf") || file_path.contains("scarlet") {
76 confidence += 15; }
78
79 if let Some(abi) = current_abi {
81 if abi.get_name() == self.get_name() {
82 confidence += 40; }
84 }
85
86 Some(confidence.min(100))
87 }
88
89 fn execute_binary(
90 &self,
91 file_object: &crate::object::KernelObject,
92 argv: &[&str],
93 envp: &[&str],
94 task: &mut crate::task::Task,
95 trapframe: &mut Trapframe
96 ) -> Result<(), &'static str> {
97 match file_object.as_file() {
99 Some(file_obj) => {
100 task.text_size = 0;
101 task.data_size = 0;
102 task.stack_size = 0;
103 task.brk = None;
104
105 match load_elf_into_task(file_obj, task) {
107 Ok(entry_point) => {
108 task.name = argv.get(0).map_or("Unnamed Task".to_string(), |s| s.to_string());
110
111 let root_page_table = vm::get_root_pagetable(task.vm_manager.get_asid()).unwrap();
113 root_page_table.unmap_all();
114
115 setup_trampoline(&mut task.vm_manager);
117 let stack_pointer = setup_user_stack(task).1;
118
119 task.set_entry_point(entry_point as usize);
121
122 task.vcpu.regs = Registers::new();
124 task.vcpu.set_sp(stack_pointer);
125
126 let (adjusted_sp, argv_ptr) = self.setup_arguments_on_stack(task, argv, envp, stack_pointer)?;
128 task.vcpu.set_sp(adjusted_sp);
129
130 task.vcpu.regs.reg[10] = argv.len(); task.vcpu.regs.reg[11] = argv_ptr; task.vcpu.switch(trapframe);
144 Ok(())
145 },
146 Err(e) => {
147 crate::println!("ELF loading failed: {}", e.message);
149 Err("Failed to load ELF binary")
150 }
151 }
152 },
153 None => Err("Invalid file object type for binary execution"),
154 }
155 }
156
157 fn normalize_env_to_scarlet(&self, envp: &mut Vec<String>) {
158 for env_var in envp.iter_mut() {
162 if let Some(eq_pos) = env_var.find('=') {
163 let key = &env_var[..eq_pos];
164 let value = &env_var[eq_pos + 1..];
165
166 let normalized_value = match key {
167 "PATH" | "LD_LIBRARY_PATH" => {
168 self.normalize_path_to_absolute_scarlet(value)
170 }
171 "HOME" => {
172 if value.starts_with('/') {
174 value.to_string()
175 } else {
176 format!("/home/{}", value)
177 }
178 }
179 _ => value.to_string(), };
181
182 let new_env_var = format!("{}={}", key, normalized_value);
184 if new_env_var != *env_var {
185 *env_var = new_env_var;
186 }
187 }
188 }
189 }
190
191 fn denormalize_env_from_scarlet(&self, envp: &mut Vec<String>) {
192 let mut env_map = BTreeMap::new();
197 for env_var in envp.iter() {
198 if let Some(eq_pos) = env_var.find('=') {
199 let key = env_var[..eq_pos].to_string();
200 let value = env_var[eq_pos + 1..].to_string();
201 env_map.insert(key, value);
202 }
203 }
204
205 if !env_map.contains_key("PATH") {
207 env_map.insert("PATH".to_string(), "/system/scarlet/bin:/bin:/usr/bin".to_string());
208 }
209
210 if !env_map.contains_key("SHELL") {
211 env_map.insert("SHELL".to_string(), "/system/scarlet/bin/sh".to_string());
212 }
213
214 envp.clear();
216 for (key, value) in env_map.iter() {
217 envp.push(format!("{}={}", key, value));
218 }
219 }
220
221 fn setup_overlay_environment(
222 &self,
223 target_vfs: &Arc<VfsManager>,
224 base_vfs: &Arc<VfsManager>,
225 system_path: &str,
226 config_path: &str,
227 ) -> Result<(), &'static str> {
228 let lower_vfs_list = alloc::vec![(base_vfs, system_path)];
231 let upper_vfs = base_vfs;
232 let fs = match OverlayFS::new_from_paths_and_vfs(Some((upper_vfs, config_path)), lower_vfs_list, "/") {
233 Ok(fs) => fs,
234 Err(e) => {
235 crate::println!("Failed to create overlay filesystem for Scarlet ABI: {}", e.message);
236 return Err("Failed to create Scarlet overlay environment");
237 }
238 };
239
240 match target_vfs.mount(fs, "/", 0) {
241 Ok(()) => Ok(()),
242 Err(e) => {
243 crate::println!("Failed to create cross-VFS overlay for Scarlet ABI: {}", e.message);
244 Err("Failed to create Scarlet overlay environment")
245 }
246 }
247 }
248
249 fn setup_shared_resources(
250 &self,
251 target_vfs: &Arc<VfsManager>,
252 base_vfs: &Arc<VfsManager>,
253 ) -> Result<(), &'static str> {
254 match create_dir_if_not_exists(target_vfs, "/home") {
257 Ok(()) => {}
258 Err(e) => {
259 crate::println!("Failed to create /home directory for Scarlet: {}", e.message);
260 return Err("Failed to create /home directory for Scarlet");
261 }
262 }
263
264 match target_vfs.bind_mount_from(base_vfs, "/home", "/home") {
265 Ok(()) => {}
266 Err(_e) => {
267 }
269 }
270
271 match create_dir_if_not_exists(target_vfs, "/data") {
272 Ok(()) => {}
273 Err(e) => {
274 crate::println!("Failed to create /data directory for Scarlet: {}", e.message);
275 return Err("Failed to create /data directory for Scarlet");
276 }
277 }
278
279 match target_vfs.bind_mount_from(base_vfs, "/data/shared", "/data/shared") {
280 Ok(()) => {}
281 Err(_e) => {
282 }
284 }
285
286 match create_dir_if_not_exists(target_vfs, "/dev") {
288 Ok(()) => {}
289 Err(e) => {
290 crate::println!("Failed to create /dev directory for Scarlet: {}", e.message);
291 return Err("Failed to create /dev directory for Scarlet");
292 }
293 }
294 match target_vfs.bind_mount_from(base_vfs, "/dev", "/dev") {
295 Ok(()) => {}
296 Err(e) => {
297 crate::println!("Failed to bind mount /dev for Scarlet: {}", e.message);
298 return Err("Failed to bind mount /dev for Scarlet");
299 }
300 }
301
302 match create_dir_if_not_exists(target_vfs, "/scarlet") {
304 Ok(()) => {}
305 Err(e) => {
306 crate::println!("Failed to create /scarlet directory for Scarlet: {}", e.message);
307 return Err("Failed to create /scarlet directory for Scarlet");
308 }
309 }
310 match target_vfs.bind_mount_from(base_vfs, "/", "/scarlet") {
311 Ok(()) => Ok(()),
312 Err(e) => {
313 crate::println!("Failed to bind mount native Scarlet root to /scarlet for Scarlet: {}", e.message);
314 return Err("Failed to bind mount native Scarlet root to /scarlet for Scarlet");
315 }
316 }
317 }
318}
319
320impl ScarletAbi {
321 fn setup_arguments_on_stack(
343 &self,
344 task: &mut crate::task::Task,
345 argv: &[&str],
346 envp: &[&str],
347 initial_sp: usize
348 ) -> Result<(usize, usize), &'static str> {
349 let argc = argv.len();
351 let envc = envp.len();
352
353 let argv_strings_size: usize = argv.iter().map(|s| s.len() + 1).sum();
355 let envp_strings_size: usize = envp.iter().map(|s| s.len() + 1).sum();
356
357 let argv_array_size = (argc + 1) * core::mem::size_of::<usize>(); let envp_array_size = (envc + 1) * core::mem::size_of::<usize>(); let argc_size = core::mem::size_of::<usize>();
361
362 let total_size = argc_size + argv_array_size + envp_array_size + argv_strings_size + envp_strings_size;
364
365 let aligned_total_size = (total_size + 15) & !15;
367
368 let new_sp = initial_sp - aligned_total_size;
370
371 let mut current_addr = new_sp;
375
376 self.write_to_stack_memory(task, current_addr, &argc.to_le_bytes())?;
378 current_addr += argc_size;
379
380 let argv_ptr = current_addr;
382
383 let argv_strings_start = current_addr + argv_array_size + envp_array_size;
385 let envp_strings_start = argv_strings_start + argv_strings_size;
386
387 let mut string_addr = argv_strings_start;
389 for i in 0..argc {
390 self.write_to_stack_memory(task, current_addr, &string_addr.to_le_bytes())?;
391 current_addr += core::mem::size_of::<usize>();
392 string_addr += argv[i].len() + 1; }
394 let null_ptr: usize = 0;
396 self.write_to_stack_memory(task, current_addr, &null_ptr.to_le_bytes())?;
397 current_addr += core::mem::size_of::<usize>();
398
399 string_addr = envp_strings_start;
401 for i in 0..envc {
402 self.write_to_stack_memory(task, current_addr, &string_addr.to_le_bytes())?;
403 current_addr += core::mem::size_of::<usize>();
404 string_addr += envp[i].len() + 1; }
406 self.write_to_stack_memory(task, current_addr, &null_ptr.to_le_bytes())?;
408 current_addr += core::mem::size_of::<usize>();
409
410 for arg in argv {
412 self.write_string_to_stack(task, current_addr, arg)?;
413 current_addr += arg.len() + 1; }
415
416 for env in envp {
418 self.write_string_to_stack(task, current_addr, env)?;
419 current_addr += env.len() + 1; }
421
422 Ok((new_sp, argv_ptr))
423 }
424
425 fn write_to_stack_memory(
427 &self,
428 task: &mut crate::task::Task,
429 vaddr: usize,
430 data: &[u8]
431 ) -> Result<(), &'static str> {
432 match task.vm_manager.translate_vaddr(vaddr) {
433 Some(paddr) => {
434 unsafe {
435 core::ptr::copy_nonoverlapping(
436 data.as_ptr(),
437 paddr as *mut u8,
438 data.len()
439 );
440 }
441 Ok(())
442 }
443 None => Err("Failed to translate virtual address for stack write")
444 }
445 }
446
447 fn write_string_to_stack(
449 &self,
450 task: &mut crate::task::Task,
451 vaddr: usize,
452 string: &str
453 ) -> Result<(), &'static str> {
454 self.write_to_stack_memory(task, vaddr, string.as_bytes())?;
456 self.write_to_stack_memory(task, vaddr + string.len(), &[0u8])?;
458 Ok(())
459 }
460
461 fn normalize_path_to_absolute_scarlet(&self, path_value: &str) -> String {
466 let paths: Vec<&str> = path_value.split(':').collect();
467 let mut normalized_paths = Vec::new();
468
469 for path in paths {
470 if path.starts_with('/') {
471 if path.starts_with("/system/scarlet/") || path.starts_with("/scarlet/") {
473 normalized_paths.push(path.to_string());
474 } else {
475 let mapped_path = match path {
477 "/bin" => "/system/scarlet/bin",
478 "/usr/bin" => "/system/scarlet/usr/bin",
479 "/usr/local/bin" => "/system/scarlet/usr/local/bin",
480 "/sbin" => "/system/scarlet/sbin",
481 "/usr/sbin" => "/system/scarlet/usr/sbin",
482 "/lib" => "/system/scarlet/lib",
483 "/usr/lib" => "/system/scarlet/usr/lib",
484 "/usr/local/lib" => "/system/scarlet/usr/local/lib",
485 _ => path, };
487 normalized_paths.push(mapped_path.to_string());
488 }
489 } else if !path.is_empty() {
490 normalized_paths.push(format!("/{}", path));
492 }
493 }
495
496 normalized_paths.join(":")
497 }
498}
499
500fn create_dir_if_not_exists(vfs: &Arc<VfsManager>, path: &str) -> Result<(), FileSystemError> {
501 match vfs.create_dir(path) {
502 Ok(()) => Ok(()),
503 Err(e) => {
504 if e.kind == FileSystemErrorKind::AlreadyExists {
505 Ok(()) } else {
507 Err(e) }
509 }
510 }
511}
512
513fn register_scarlet_abi() {
514 register_abi!(ScarletAbi);
515}
516
517early_initcall!(register_scarlet_abi);