diff --git a/Cargo.lock b/Cargo.lock index fb137983..24bff133 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1930,13 +1930,8 @@ dependencies = [ "rustc-std-workspace-alloc", "rustc-std-workspace-core", "serde", - "yggdrasil-abi-def", ] -[[package]] -name = "yggdrasil-abi-def" -version = "0.1.0" - [[package]] name = "yggdrasil-kernel" version = "0.1.0" @@ -1989,7 +1984,6 @@ dependencies = [ "ygg_driver_usb_xhci", "ygg_driver_virtio_net", "yggdrasil-abi", - "yggdrasil-abi-def", ] [[package]] @@ -2004,5 +1998,4 @@ dependencies = [ "rustc-std-workspace-alloc", "rustc-std-workspace-core", "yggdrasil-abi", - "yggdrasil-abi-def", ] diff --git a/Cargo.toml b/Cargo.toml index ed95e763..47f75c5f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,7 +11,6 @@ members = [ "kernel/tools/gentables", "kernel", "lib/abi", - "lib/abi-def", "lib/libyalloc", "lib/runtime", ] diff --git a/kernel/Cargo.toml b/kernel/Cargo.toml index 93ce1cb3..a05b4749 100644 --- a/kernel/Cargo.toml +++ b/kernel/Cargo.toml @@ -74,7 +74,6 @@ kernel-arch-x86_64 = { path = "arch/x86_64" } [build-dependencies] prettyplease = "0.2.15" -yggdrasil-abi-def = { path = "../lib/abi-def" } abi-generator = { path = "../tool/abi-generator" } [features] diff --git a/kernel/build.rs b/kernel/build.rs index 19008adc..68b8d902 100644 --- a/kernel/build.rs +++ b/kernel/build.rs @@ -39,15 +39,28 @@ fn build_x86_64() { } } -fn generate_syscall_dispatcher>(out_dir: P) { +fn load_abi_definitions>(path: P) -> String { + let mut content = String::new(); + for file in fs::read_dir(path).unwrap() { + let file = file.unwrap(); + if file.path().extension().map(|x| x == "abi").unwrap_or(false) { + println!("cargo:rerun-if-changed={}", file.path().display()); + content.extend(fs::read_to_string(file.path())); + } + } + content +} + +fn generate_syscall_dispatcher, P: AsRef>(abi_path: A, out_dir: P) { + let abi = load_abi_definitions(abi_path); let abi: AbiBuilder = AbiBuilder::from_string( - yggdrasil_abi_def::ABI_FILE, + &abi, TargetEnv { thin_pointer_width: TypeWidth::U64, fat_pointer_width: TypeWidth::U128, }, ) - .unwrap_fancy(yggdrasil_abi_def::ABI_FILE); + .unwrap_fancy(&abi); let generated_dispatcher = out_dir.as_ref().join("generated_dispatcher.rs"); let file = prettyplease::unparse( @@ -62,7 +75,7 @@ fn main() { let out_dir = env::var("OUT_DIR").unwrap(); let arch = env::var("CARGO_CFG_TARGET_ARCH").unwrap(); - generate_syscall_dispatcher(out_dir); + generate_syscall_dispatcher("../lib/abi/def", out_dir); println!("cargo:rerun-if-changed=build.rs"); diff --git a/kernel/src/syscall/mod.rs b/kernel/src/syscall/mod.rs index ab1f7676..e1ecdbd0 100644 --- a/kernel/src/syscall/mod.rs +++ b/kernel/src/syscall/mod.rs @@ -835,7 +835,11 @@ mod impls { mod generated { #![allow(unreachable_code)] - use abi::{io::ChannelPublisherId, process::ProcessId, SyscallFunction}; + use abi::{ + io::ChannelPublisherId, + process::{ExecveOptions, ProcessId}, + SyscallFunction, + }; use abi_lib::SyscallRegister; use super::{ diff --git a/lib/abi-def/.gitignore b/lib/abi-def/.gitignore deleted file mode 100644 index ea8c4bf7..00000000 --- a/lib/abi-def/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/target diff --git a/lib/abi-def/Cargo.lock b/lib/abi-def/Cargo.lock deleted file mode 100644 index 738141c2..00000000 --- a/lib/abi-def/Cargo.lock +++ /dev/null @@ -1,7 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "yggdrasil-abi-def" -version = "0.1.0" diff --git a/lib/abi-def/Cargo.toml b/lib/abi-def/Cargo.toml deleted file mode 100644 index aca414f9..00000000 --- a/lib/abi-def/Cargo.toml +++ /dev/null @@ -1,6 +0,0 @@ -[package] -name = "yggdrasil-abi-def" -version = "0.1.0" -edition = "2021" - -[dependencies] diff --git a/lib/abi-def/src/lib.rs b/lib/abi-def/src/lib.rs deleted file mode 100644 index c8ef1980..00000000 --- a/lib/abi-def/src/lib.rs +++ /dev/null @@ -1 +0,0 @@ -pub const ABI_FILE: &str = include_str!("../yggdrasil.abi"); diff --git a/lib/abi/Cargo.toml b/lib/abi/Cargo.toml index e5ea1b8c..59a2cbc5 100644 --- a/lib/abi/Cargo.toml +++ b/lib/abi/Cargo.toml @@ -17,7 +17,6 @@ bytemuck = { version = "1.14.0", features = ["derive"], optional = true } abi-lib = { path = "../../lib/abi-lib" } [build-dependencies] -yggdrasil-abi-def = { path = "../abi-def" } abi-generator = { path = "../../tool/abi-generator" } prettyplease = "0.2.15" diff --git a/lib/abi/build.rs b/lib/abi/build.rs index 88591e51..20583283 100644 --- a/lib/abi/build.rs +++ b/lib/abi/build.rs @@ -6,18 +6,31 @@ use abi_generator::{ TargetEnv, }; -fn generate_abi() { +fn load_abi_definitions>(path: P) -> String { + let mut content = String::new(); + for file in fs::read_dir(path).unwrap() { + let file = file.unwrap(); + if file.path().extension().map(|x| x == "abi").unwrap_or(false) { + println!("cargo:rerun-if-changed={}", file.path().display()); + content.extend(fs::read_to_string(file.path())); + } + } + content +} + +fn generate_abi>(abi_path: P) { let output_dir = std::env::var("OUT_DIR").expect("$OUT_DIR not set"); let generated_types = Path::new(&output_dir).join("generated_types.rs"); + let abi = load_abi_definitions(abi_path); let abi = AbiBuilder::from_string( - yggdrasil_abi_def::ABI_FILE, + &abi, TargetEnv { thin_pointer_width: TypeWidth::U64, fat_pointer_width: TypeWidth::U64, }, ) - .unwrap_fancy(yggdrasil_abi_def::ABI_FILE); + .unwrap_fancy(&abi); let types = prettyplease::unparse( &abi.emit_file(true, false) @@ -28,5 +41,5 @@ fn generate_abi() { } fn main() { - generate_abi(); + generate_abi("def"); } diff --git a/lib/abi/def/error.abi b/lib/abi/def/error.abi new file mode 100644 index 00000000..5e49ef77 --- /dev/null +++ b/lib/abi/def/error.abi @@ -0,0 +1,30 @@ +// vi:syntax=yggdrasil_abi: + +enum Error(u32) { + OutOfMemory = 1, + AlreadyExists = 2, + NotImplemented = 3, + DoesNotExist = 4, + InvalidFile = 5, + InvalidArgument = 6, + Interrupted = 7, + WouldBlock = 8, + UnrecognizedExecutable = 9, + InvalidOperation = 10, + InvalidMemoryOperation = 11, + NotADirectory = 12, + IsADirectory = 13, + ReadOnly = 14, + PermissionDenied = 15, + AddrInUse = 16, + QueueFull = 17, + BufferTooSmall = 18, + ConnectionReset = 19, + MissingData = 20, + NetworkUnreachable = 21, + TimedOut = 22, + ConnectionRefused = 23, + HostUnreachable = 24, + UndefinedSyscall = 25, + DirectoryNotEmpty = 26, +} diff --git a/lib/abi/def/io.abi b/lib/abi/def/io.abi new file mode 100644 index 00000000..d8c2945a --- /dev/null +++ b/lib/abi/def/io.abi @@ -0,0 +1,191 @@ +// vi:syntax=yggdrasil_abi: + +// abi::io + +newtype RawFd(u32); + +newtype UserId(u32); +newtype GroupId(u32); + +newtype ChannelPublisherId(u32); + +bitfield FileMode(u32) { + /// Other user execution access + OTHER_EXEC: 0, + /// Other user write access + OTHER_WRITE: 1, + /// Other user read access + OTHER_READ: 2, + + /// Group execution access + GROUP_EXEC: 3, + /// Group write access + GROUP_WRITE: 4, + /// Group read access + GROUP_READ: 5, + + /// User execution access + USER_EXEC: 6, + /// User write access + USER_WRITE: 7, + /// User read access + USER_READ: 8, +} + +bitfield OpenOptions(u32) { + /// The file is to be opened with read capability + READ: 0, + /// The file is to be opened with write capability + WRITE: 1, + + /// Open file at the end + APPEND: 2, + /// Truncate the file to zero bytes when opening + TRUNCATE: 3, + + /// Create the file if it does not exist + CREATE: 4, + /// When combined with CREATE, will fail if the file already exists + CREATE_EXCL: 5, +} + +enum FileType(u32) { + /// Regular file + File = 1, + /// Directory + Directory = 2, + /// Not yet implemented + Symlink = 3, + /// Block device + Block = 4, + /// Character device (e.g. terminal) + Char = 5, +} + +/// Describes metadata associated with a filesystem entry +#[derive(Debug, Clone, Copy, PartialEq)] +#[repr(C)] +struct FileAttr { + /// Data size for files, UNSPECIFIED for the rest + pub size: u64, + /// Entry type + pub ty: FileType, + /// Entry access permissions + pub mode: FileMode, + + /// Owner user ID + pub uid: UserId, + /// Owner group ID + pub gid: GroupId, +} + +/// Raw directory entry representation +#[derive(Clone, Copy, Debug, PartialEq)] +#[repr(C)] +struct DirectoryEntry { + /// Name of the entry + pub name: FixedString<256>, + /// Type of the entry + pub ty: FileType, +} + +enum PollControl(u32) { + AddFd = 1, +} + +// abi::io::terminal + +#[derive(Clone, Copy, Debug)] +#[repr(C)] +struct TerminalControlCharacters { + /// End-of-file character (0x04, ^D) + pub eof: u8, + /// Erase character (0x7F, ^?) + pub erase: u8, + /// Word erase character (0x17, ^W) + pub werase: u8, + /// Interrupt character (0x03, ^C) + pub interrupt: u8, + /// Kill character (0x15, ^U) + pub kill: u8, +} + +/// Controls the line discipline of the terminal +#[default(SIGNAL | CANONICAL | ECHO | ECHO_ERASE | ECHO_KILL | ECHO_NL)] +bitfield TerminalLineOptions(u32) { + /// Enables signal processing for special bytes (INTR, QUIT, etc.) + SIGNAL: 0, + /// Enables canonical mode + CANONICAL: 1, + /// Echo input characters back + ECHO: 2, + /// If CANONICAL is set, ERASE character erases chars, WORD_ERASE erases words + ECHO_ERASE: 3, + /// If CANONICAL is set, KILL erases lines + ECHO_KILL: 4, + /// If CANONICAL is set, echo newline even if ECHO is not set + ECHO_NL: 5, +} + +/// Defines how output to the terminal should be processed +#[default(NL_TO_CRNL)] +bitfield TerminalOutputOptions(u32) { + /// Translate \n to \r\n + NL_TO_CRNL: 0, +} + +/// Defines how input should be presented to the reader +#[default(CR_TO_NL)] +bitfield TerminalInputOptions(u32) { + /// Translate \n to \r on input + NL_TO_CR: 0, + /// Translate \r to \n on input + CR_TO_NL: 1, +} + +/// Terminal I/O transformation and control settings +#[derive(Clone, Copy, Debug)] +#[repr(C)] +struct TerminalOptions { + /// Controls output processing + pub output: TerminalOutputOptions, + /// Controls input processing + pub input: TerminalInputOptions, + /// Controls special bytes and line discipline + pub line: TerminalLineOptions, + /// Specifies control characters of the terminal + pub chars: TerminalControlCharacters, +} + +/// Describes terminal size in rows and columns +#[derive(Clone, Copy, Debug)] +#[repr(C)] +struct TerminalSize { + /// Number of text rows + pub rows: usize, + /// Number of text columns + pub columns: usize, +} + +// abi::io::device + +/// Describes how a mount operation should be performed +#[derive(Clone, Debug)] +#[repr(C)] +struct MountOptions<'a> { + /// Block device to use as a mount source. May be empty when mounting virtual filesystems. + pub source: Option<&'a str>, + /// Filesystem to use when mounting. Empty means "deduce automatically" and source must be set. + pub filesystem: Option<&'a str>, + /// Path to a directory to mount the filesystem to + pub target: &'a str, +} + +/// Describes how an unmount operation should be performed +#[derive(Clone, Debug)] +#[repr(C)] +struct UnmountOptions { + /// Path to the mountpoint to unmount + pub mountpoint: &'static str, +} + diff --git a/lib/abi/src/process/spawn.rs b/lib/abi/def/process.abi similarity index 56% rename from lib/abi/src/process/spawn.rs rename to lib/abi/def/process.abi index 6800db3a..09b38d1e 100644 --- a/lib/abi/src/process/spawn.rs +++ b/lib/abi/def/process.abi @@ -1,27 +1,26 @@ -use crate::io::RawFd; +// vi:syntax=yggdrasil_abi: -use super::ProcessId; - -/// Defines an optional argument for controlling process creation -#[derive(Debug)] -pub enum SpawnOption { - /// Indicates a new process should inherit a file descriptor from its creator - InheritFile { - /// FD on the creator side - source: RawFd, - /// What FD number should be used in the child - child: RawFd, - }, - /// The new process should be placed in the specified group - SetProcessGroup(ProcessId), - /// Gain terminal control for the given FD - GainTerminal(RawFd), +enum Signal(u32) { + /// Process has tried to perform an illegal memory operation + MemoryAccessViolation = 1, + /// Process has hit a breakpoint or was aborted + Aborted = 2, + /// Process was killed + Killed = 3, + /// Process was interrupted + Interrupted = 4, } +newtype ProcessId(u32); +newtype ProcessGroupId(u32); +newtype ThreadId(u32); + +// Spawn + /// Controls how processes are created #[derive(Clone, Debug)] #[repr(C)] -pub struct SpawnOptions<'a> { +struct SpawnOptions<'a> { /// Creator-relative path to the binary to execute pub program: &'a str, /// Arguments to the child process @@ -36,7 +35,7 @@ pub struct SpawnOptions<'a> { #[allow(missing_docs)] #[derive(Clone, Debug)] #[repr(C)] -pub struct ExecveOptions<'a> { +struct ExecveOptions<'a> { pub program: &'a str, pub arguments: &'a [&'a str], pub environment: &'a [&'a str], @@ -45,7 +44,7 @@ pub struct ExecveOptions<'a> { /// Controls how threads are spawned within a process #[derive(Clone, Debug)] #[repr(C)] -pub struct ThreadSpawnOptions { +struct ThreadSpawnOptions { /// Thread entry function pub entry: extern "C" fn(u64) -> !, /// Thread argument value @@ -54,3 +53,15 @@ pub struct ThreadSpawnOptions { /// the thread. pub stack_top: usize, } + +// Signal + +/// Data provided by the kernel to signal entry function +#[derive(Clone, Debug)] +#[repr(C)] +struct SignalEntryData { + /// Which signal was issued + pub signal: Signal, + /// Saved frame of the context that was interrupted + pub frame: SavedFrame, +} diff --git a/lib/abi-def/yggdrasil.abi b/lib/abi/def/yggdrasil.abi similarity index 51% rename from lib/abi-def/yggdrasil.abi rename to lib/abi/def/yggdrasil.abi index 4e37258e..dcd49aba 100644 --- a/lib/abi-def/yggdrasil.abi +++ b/lib/abi/def/yggdrasil.abi @@ -5,14 +5,13 @@ extern { type SocketAddr = core::net::SocketAddr; type AtomicU32 = core::sync::atomic::AtomicU32; + // TODO "tagged union" enums are not yet implemented type MappingSource; type SystemInfo = yggdrasil_abi::system::SystemInfo; type SignalEntryData = yggdrasil_abi::process::SignalEntryData; - type SpawnOptions = yggdrasil_abi::process::SpawnOptions; type MutexOperation = yggdrasil_abi::process::MutexOperation; - type ExecveOptions = yggdrasil_abi::process::ExecveOptions; #[thin] type ExitCode = yggdrasil_abi::process::ExitCode; @@ -20,12 +19,8 @@ extern { type SentMessage = yggdrasil_abi::io::SentMessage; type ReceivedMessageMetadata = yggdrasil_abi::io::ReceivedMessageMetadata; - type MountOptions = yggdrasil_abi::io::MountOptions; - type UnmountOptions = yggdrasil_abi::io::UnmountOptions; type DeviceRequest = yggdrasil_abi::io::DeviceRequest; type FileMetadataUpdate = yggdrasil_abi::io::FileMetadataUpdate; - type DirectoryEntry = yggdrasil_abi::io::DirectoryEntry; - type FileAttr = yggdrasil_abi::io::FileAttr; #[thin] type SeekFrom = yggdrasil_abi::io::SeekFrom; @@ -33,194 +28,6 @@ extern { type MessageDestination = yggdrasil_abi::io::MessageDestination; } -// abi::error - -enum Error(u32) { - OutOfMemory = 1, - AlreadyExists = 2, - NotImplemented = 3, - DoesNotExist = 4, - InvalidFile = 5, - InvalidArgument = 6, - Interrupted = 7, - WouldBlock = 8, - UnrecognizedExecutable = 9, - InvalidOperation = 10, - InvalidMemoryOperation = 11, - NotADirectory = 12, - IsADirectory = 13, - ReadOnly = 14, - PermissionDenied = 15, - AddrInUse = 16, - QueueFull = 17, - BufferTooSmall = 18, - ConnectionReset = 19, - MissingData = 20, - NetworkUnreachable = 21, - TimedOut = 22, - ConnectionRefused = 23, - HostUnreachable = 24, - UndefinedSyscall = 25, - DirectoryNotEmpty = 26, -} - -// abi::process - -enum Signal(u32) { - /// Process has tried to perform an illegal memory operation - MemoryAccessViolation = 1, - /// Process has hit a breakpoint or was aborted - Aborted = 2, - /// Process was killed - Killed = 3, - /// Process was interrupted - Interrupted = 4, -} - -newtype ProcessId(u32); -newtype ProcessGroupId(u32); -newtype ThreadId(u32); - -// abi::io - -newtype RawFd(u32); - -newtype UserId(u32); -newtype GroupId(u32); - -newtype ChannelPublisherId(u32); - -bitfield FileMode(u32) { - /// Other user execution access - OTHER_EXEC: 0, - /// Other user write access - OTHER_WRITE: 1, - /// Other user read access - OTHER_READ: 2, - - /// Group execution access - GROUP_EXEC: 3, - /// Group write access - GROUP_WRITE: 4, - /// Group read access - GROUP_READ: 5, - - /// User execution access - USER_EXEC: 6, - /// User write access - USER_WRITE: 7, - /// User read access - USER_READ: 8, -} - -bitfield OpenOptions(u32) { - /// The file is to be opened with read capability - READ: 0, - /// The file is to be opened with write capability - WRITE: 1, - - /// Open file at the end - APPEND: 2, - /// Truncate the file to zero bytes when opening - TRUNCATE: 3, - - /// Create the file if it does not exist - CREATE: 4, - /// When combined with CREATE, will fail if the file already exists - CREATE_EXCL: 5, -} - -enum FileType(u32) { - /// Regular file - File = 1, - /// Directory - Directory = 2, - /// Not yet implemented - Symlink = 3, - /// Block device - Block = 4, - /// Character device (e.g. terminal) - Char = 5, -} - -enum PollControl(u32) { - AddFd = 1, -} - -// abi::io::terminal - -#[derive(Clone, Copy, Debug)] -#[repr(C)] -struct TerminalControlCharacters { - /// End-of-file character (0x04, ^D) - pub eof: u8, - /// Erase character (0x7F, ^?) - pub erase: u8, - /// Word erase character (0x17, ^W) - pub werase: u8, - /// Interrupt character (0x03, ^C) - pub interrupt: u8, - /// Kill character (0x15, ^U) - pub kill: u8, -} - -/// Controls the line discipline of the terminal -#[default(SIGNAL | CANONICAL | ECHO | ECHO_ERASE | ECHO_KILL | ECHO_NL)] -bitfield TerminalLineOptions(u32) { - /// Enables signal processing for special bytes (INTR, QUIT, etc.) - SIGNAL: 0, - /// Enables canonical mode - CANONICAL: 1, - /// Echo input characters back - ECHO: 2, - /// If CANONICAL is set, ERASE character erases chars, WORD_ERASE erases words - ECHO_ERASE: 3, - /// If CANONICAL is set, KILL erases lines - ECHO_KILL: 4, - /// If CANONICAL is set, echo newline even if ECHO is not set - ECHO_NL: 5, -} - -/// Defines how output to the terminal should be processed -#[default(NL_TO_CRNL)] -bitfield TerminalOutputOptions(u32) { - /// Translate \n to \r\n - NL_TO_CRNL: 0, -} - -/// Defines how input should be presented to the reader -#[default(CR_TO_NL)] -bitfield TerminalInputOptions(u32) { - /// Translate \n to \r on input - NL_TO_CR: 0, - /// Translate \r to \n on input - CR_TO_NL: 1, -} - -/// Terminal I/O transformation and control settings -#[derive(Clone, Copy, Debug)] -#[repr(C)] -struct TerminalOptions { - /// Controls output processing - pub output: TerminalOutputOptions, - /// Controls input processing - pub input: TerminalInputOptions, - /// Controls special bytes and line discipline - pub line: TerminalLineOptions, - /// Specifies control characters of the terminal - pub chars: TerminalControlCharacters, -} - -/// Describes terminal size in rows and columns -#[derive(Clone, Copy, Debug)] -#[repr(C)] -struct TerminalSize { - /// Number of text rows - pub rows: usize, - /// Number of text columns - pub columns: usize, -} - // abi::net enum SocketType(u32) { diff --git a/lib/abi/src/io/device.rs b/lib/abi/src/io/device.rs index 43cf56d8..20932515 100644 --- a/lib/abi/src/io/device.rs +++ b/lib/abi/src/io/device.rs @@ -4,26 +4,6 @@ use crate::generated::ProcessId; use super::terminal; -/// Describes how a mount operation should be performed -#[derive(Clone, Debug)] -#[repr(C)] -pub struct MountOptions<'a> { - /// Block device to use as a mount source. May be empty when mounting virtual filesystems. - pub source: Option<&'a str>, - /// Filesystem to use when mounting. Empty means "deduce automatically" and source must be set. - pub filesystem: Option<&'a str>, - /// Path to a directory to mount the filesystem to - pub target: &'a str, -} - -/// Describes how an unmount operation should be performed -#[derive(Clone, Debug)] -#[repr(C)] -pub struct UnmountOptions { - /// Path to the mountpoint to unmount - pub mountpoint: &'static str, -} - // TODO make this accept references when "reading" something /// Describes device-specific requests #[derive(Clone, Debug)] diff --git a/lib/abi/src/io/file.rs b/lib/abi/src/io/file.rs index 89a84f55..68266889 100644 --- a/lib/abi/src/io/file.rs +++ b/lib/abi/src/io/file.rs @@ -2,7 +2,7 @@ use core::fmt; use abi_lib::SyscallRegister; -use super::{FileMode, FileType, GroupId, UserId}; +use super::FileMode; /// Describes an operation to perform when updating certain file metadata elements #[derive(Debug, Clone)] @@ -24,23 +24,6 @@ pub enum FileMetadataUpdate { Permissions(FileMode, FileMetadataUpdateMode), } -/// Describes metadata associated with a filesystem entry -#[derive(Debug, Clone, Copy, PartialEq)] -#[repr(C)] -pub struct FileAttr { - /// Data size for files, UNSPECIFIED for the rest - pub size: u64, - /// Entry type - pub ty: FileType, - /// Entry access permissions - pub mode: FileMode, - - /// Owner user ID - pub uid: UserId, - /// Owner group ID - pub gid: GroupId, -} - /// Describes a seek operation for a regular file #[derive(Clone, Copy, Debug, PartialEq)] pub enum SeekFrom { diff --git a/lib/abi/src/io/mod.rs b/lib/abi/src/io/mod.rs index 08444da1..74e2fbea 100644 --- a/lib/abi/src/io/mod.rs +++ b/lib/abi/src/io/mod.rs @@ -1,15 +1,16 @@ -use crate::util::FixedString; - mod channel; mod device; mod file; mod input; mod terminal; -pub use crate::generated::{FileMode, FileType, GroupId, OpenOptions, PollControl, RawFd, UserId}; +pub use crate::generated::{ + DirectoryEntry, FileAttr, FileMode, FileType, GroupId, MountOptions, OpenOptions, PollControl, + RawFd, UnmountOptions, UserId, +}; pub use channel::{ChannelPublisherId, MessageDestination, ReceivedMessageMetadata, SentMessage}; -pub use device::{DeviceRequest, MountOptions, UnmountOptions}; -pub use file::{FileAttr, FileMetadataUpdate, FileMetadataUpdateMode, SeekFrom}; +pub use device::DeviceRequest; +pub use file::{FileMetadataUpdate, FileMetadataUpdateMode, SeekFrom}; pub use input::{KeyboardKey, KeyboardKeyCode, KeyboardKeyEvent}; pub use terminal::{ TerminalControlCharacters, TerminalInputOptions, TerminalLineOptions, TerminalOptions, @@ -52,16 +53,6 @@ impl FileMode { } } -/// Raw directory entry representation -#[derive(Clone, Copy, Debug, PartialEq)] -#[repr(C)] -pub struct DirectoryEntry { - /// Name of the entry - pub name: FixedString<256>, - /// Type of the entry - pub ty: FileType, -} - impl RawFd { pub const STDIN: Self = Self(0); pub const STDOUT: Self = Self(1); diff --git a/lib/abi/src/lib.rs b/lib/abi/src/lib.rs index d6ef1b48..ffadd0d5 100644 --- a/lib/abi/src/lib.rs +++ b/lib/abi/src/lib.rs @@ -21,6 +21,8 @@ pub mod pass; pub mod util; mod generated { + use crate::{arch::SavedFrame, process::SpawnOption, util::FixedString}; + include!(concat!(env!("OUT_DIR"), "/generated_types.rs")); } diff --git a/lib/abi/src/process/exit.rs b/lib/abi/src/process/exit.rs index 22943300..d8a228ad 100644 --- a/lib/abi/src/process/exit.rs +++ b/lib/abi/src/process/exit.rs @@ -2,7 +2,7 @@ use core::num::NonZeroI32; use abi_lib::SyscallRegister; -use super::signal::Signal; +use super::Signal; /// Code signalled by a process when it finishes or is terminated by a signal #[derive(Debug, Clone, Copy, PartialEq, Eq)] diff --git a/lib/abi/src/process/mod.rs b/lib/abi/src/process/mod.rs index 8dcd4ffd..a6adcc0c 100644 --- a/lib/abi/src/process/mod.rs +++ b/lib/abi/src/process/mod.rs @@ -2,16 +2,33 @@ use core::{fmt, time::Duration}; -use crate::{impl_place_lifetime, io::FileMode}; +use crate::{ + impl_place_lifetime, + io::{FileMode, RawFd}, +}; mod exit; -mod signal; -mod spawn; -pub use crate::generated::{ProcessId, ThreadId}; +pub use crate::generated::{ + ExecveOptions, ProcessId, Signal, SignalEntryData, SpawnOptions, ThreadId, ThreadSpawnOptions, +}; pub use exit::ExitCode; -pub use signal::{Signal, SignalEntryData}; -pub use spawn::{ExecveOptions, SpawnOption, SpawnOptions, ThreadSpawnOptions}; + +/// Defines an optional argument for controlling process creation +#[derive(Debug)] +pub enum SpawnOption { + /// Indicates a new process should inherit a file descriptor from its creator + InheritFile { + /// FD on the creator side + source: RawFd, + /// What FD number should be used in the child + child: RawFd, + }, + /// The new process should be placed in the specified group + SetProcessGroup(ProcessId), + /// Gain terminal control for the given FD + GainTerminal(RawFd), +} /// Describes a single mutex operation #[derive(Clone, Debug)] diff --git a/lib/abi/src/process/signal.rs b/lib/abi/src/process/signal.rs deleted file mode 100644 index 9765c015..00000000 --- a/lib/abi/src/process/signal.rs +++ /dev/null @@ -1,13 +0,0 @@ -use crate::arch::SavedFrame; - -pub use crate::generated::Signal; - -/// Data provided by the kernel to signal entry function -#[derive(Clone, Debug)] -#[repr(C)] -pub struct SignalEntryData { - /// Which signal was issued - pub signal: Signal, - /// Saved frame of the context that was interrupted - pub frame: SavedFrame, -} diff --git a/lib/runtime/Cargo.toml b/lib/runtime/Cargo.toml index e3c60814..602f0412 100644 --- a/lib/runtime/Cargo.toml +++ b/lib/runtime/Cargo.toml @@ -16,7 +16,6 @@ abi-lib = { path = "../abi-lib" } [build-dependencies] abi-generator = { path = "../../tool/abi-generator" } -yggdrasil-abi-def = { path = "../abi-def" } prettyplease = "0.2.15" cc = "*" diff --git a/lib/runtime/build.rs b/lib/runtime/build.rs index 7d829841..42e5a23c 100644 --- a/lib/runtime/build.rs +++ b/lib/runtime/build.rs @@ -11,6 +11,18 @@ fn add_file<'a>(build: &'a mut cc::Build, name: &'a str) -> &'a mut cc::Build { build.file(name) } +fn load_abi_definitions>(path: P) -> String { + let mut content = String::new(); + for file in fs::read_dir(path).unwrap() { + let file = file.unwrap(); + if file.path().extension().map(|x| x == "abi").unwrap_or(false) { + println!("cargo:rerun-if-changed={}", file.path().display()); + content.extend(fs::read_to_string(file.path())); + } + } + content +} + fn build_libm() { println!("cargo:rerun-if-changed=libm/private.h"); @@ -38,18 +50,19 @@ fn build_libm() { build.compile("m"); } -fn generate_abi() { +fn generate_abi>(abi_path: P) { let output_dir = std::env::var("OUT_DIR").expect("$OUT_DIR not set"); let generated_calls = Path::new(&output_dir).join("generated_calls.rs"); + let abi = load_abi_definitions(abi_path); let abi = AbiBuilder::from_string( - yggdrasil_abi_def::ABI_FILE, + &abi, TargetEnv { thin_pointer_width: TypeWidth::U64, fat_pointer_width: TypeWidth::U64, }, ) - .unwrap_fancy(yggdrasil_abi_def::ABI_FILE); + .unwrap_fancy(&abi); let calls = prettyplease::unparse( &abi.emit_file(false, true) @@ -61,5 +74,5 @@ fn generate_abi() { fn main() { build_libm(); - generate_abi(); + generate_abi("../abi/def"); } diff --git a/lib/runtime/src/sys/mod.rs b/lib/runtime/src/sys/mod.rs index 80368d83..b3fe65eb 100644 --- a/lib/runtime/src/sys/mod.rs +++ b/lib/runtime/src/sys/mod.rs @@ -13,12 +13,12 @@ mod generated { use abi::{ error::Error, io::{ - ChannelPublisherId, FileMode, OpenOptions, PollControl, RawFd, TerminalOptions, - TerminalSize, + ChannelPublisherId, DirectoryEntry, FileAttr, FileMode, MountOptions, OpenOptions, + PollControl, RawFd, TerminalOptions, TerminalSize, UnmountOptions, }, mem::MappingSource, net::SocketType, - process::{ProcessId, Signal}, + process::{ExecveOptions, ProcessId, Signal, SignalEntryData, SpawnOptions}, SyscallFunction, }; diff --git a/tool/abi-generator/src/abi/ty/complex.rs b/tool/abi-generator/src/abi/ty/complex.rs index 67687b4f..65871692 100644 --- a/tool/abi-generator/src/abi/ty/complex.rs +++ b/tool/abi-generator/src/abi/ty/complex.rs @@ -105,7 +105,9 @@ impl Type for ComplexType { } => { quote!(#alias #arguments) } - Self::Struct { name, .. } => quote!(#name), + Self::Struct { + name, arguments, .. + } => quote!(#name #arguments), Self::MaybeUninit(ty) => { let ty = ty.as_rust_type(); quote!(core::mem::MaybeUninit<#ty>) diff --git a/tool/abi-generator/src/syntax/bitfield_type.rs b/tool/abi-generator/src/syntax/bitfield_type.rs index 902c6538..3b33f4c9 100644 --- a/tool/abi-generator/src/syntax/bitfield_type.rs +++ b/tool/abi-generator/src/syntax/bitfield_type.rs @@ -40,7 +40,7 @@ impl DocumentItemAttributes for BitfieldType { } impl syn::parse::Parse for BitfieldDefaultValue { - fn parse(input: syn::parse::ParseStream) -> syn::Result { + fn parse(input: syn::parse::ParseStream<'_>) -> syn::Result { let items = input.parse_terminated(syn::Ident::parse, Token![|])?; Ok(Self { items }) } diff --git a/tool/abi-generator/src/syntax/error.rs b/tool/abi-generator/src/syntax/error.rs index 994915a6..39aa97db 100644 --- a/tool/abi-generator/src/syntax/error.rs +++ b/tool/abi-generator/src/syntax/error.rs @@ -24,7 +24,7 @@ impl SpanHelper for Span { pub enum SyntaxError { UnhandledType(syn::Type), UndefinedIdentifier(syn::Ident), - + UnexpectedAttributes(syn::Ident), PrimitiveReprRequired(syn::Ident), } @@ -59,9 +59,10 @@ impl From for ParseError { impl SyntaxError { pub fn span(&self) -> Span { match self { - Self::UndefinedIdentifier(id) => id.span(), Self::UnhandledType(ty) => ty.span(), - Self::PrimitiveReprRequired(id) => id.span(), + Self::PrimitiveReprRequired(id) + | Self::UnexpectedAttributes(id) + | Self::UndefinedIdentifier(id) => id.span(), } } @@ -72,6 +73,9 @@ impl SyntaxError { Self::PrimitiveReprRequired(id) => { format!("Primitive repr required in type definition, got '{}'", id) } + Self::UnexpectedAttributes(id) => { + format!("Unexpected attributes for type '{}'", id) + } } } diff --git a/tool/abi-generator/src/syntax/mod.rs b/tool/abi-generator/src/syntax/mod.rs index d4a97a20..bfbd7f44 100644 --- a/tool/abi-generator/src/syntax/mod.rs +++ b/tool/abi-generator/src/syntax/mod.rs @@ -96,7 +96,17 @@ fn process_type(t: &syn::Type, known_types: &TypeEnv) -> Result, let ty = process_type(ty, known_types)?; Ok(Rc::new(ComplexType::MaybeUninit(ty))) } - name if let Some((ty, _)) = known_types.lookup_local(name) => Ok(ty.clone()), + name if let Some((ty, _)) = known_types.lookup_local(name) => match ty.as_ref() { + ComplexType::Struct { name, kind, .. } => Ok(Rc::new(ComplexType::Struct { + name: name.clone(), + kind: *kind, + arguments: segment.arguments.clone(), + })), + _ if !segment.arguments.is_empty() => Err(ParseError::syntax1( + SyntaxError::UnexpectedAttributes(segment.ident.clone()), + )), + _ => Ok(ty.clone()), + }, name if let Some((ty, kind)) = known_types.lookup_extern(name) => { Ok(Rc::new(ComplexType::Extern { kind: *kind, diff --git a/tool/abi-generator/src/syntax/struct_type.rs b/tool/abi-generator/src/syntax/struct_type.rs index c02d997c..a1423cb0 100644 --- a/tool/abi-generator/src/syntax/struct_type.rs +++ b/tool/abi-generator/src/syntax/struct_type.rs @@ -8,7 +8,7 @@ pub struct StructType { } impl syn::parse::Parse for StructType { - fn parse(input: syn::parse::ParseStream) -> syn::Result { + fn parse(input: syn::parse::ParseStream<'_>) -> syn::Result { let mut inner: syn::ItemStruct = input.parse()?; inner.vis = syn::Visibility::Public(syn::token::Pub(input.span())); Ok(Self { inner }) diff --git a/userspace/Cargo.lock b/userspace/Cargo.lock index a79b06a8..971988e7 100644 --- a/userspace/Cargo.lock +++ b/userspace/Cargo.lock @@ -1091,13 +1091,8 @@ dependencies = [ "bytemuck", "prettyplease", "serde", - "yggdrasil-abi-def", ] -[[package]] -name = "yggdrasil-abi-def" -version = "0.1.0" - [[package]] name = "yggdrasil-rt" version = "0.1.0" @@ -1107,7 +1102,6 @@ dependencies = [ "cc", "prettyplease", "yggdrasil-abi", - "yggdrasil-abi-def", ] [[package]]