abi: split definitions into multiple files

This commit is contained in:
Mark Poliakov 2024-03-13 14:25:02 +02:00
parent 12b481398d
commit ae09849fda
31 changed files with 368 additions and 342 deletions

7
Cargo.lock generated
View File

@ -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",
]

View File

@ -11,7 +11,6 @@ members = [
"kernel/tools/gentables",
"kernel",
"lib/abi",
"lib/abi-def",
"lib/libyalloc",
"lib/runtime",
]

View File

@ -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]

View File

@ -39,15 +39,28 @@ fn build_x86_64() {
}
}
fn generate_syscall_dispatcher<P: AsRef<Path>>(out_dir: P) {
fn load_abi_definitions<P: AsRef<Path>>(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<A: AsRef<Path>, P: AsRef<Path>>(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");

View File

@ -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::{

View File

@ -1 +0,0 @@
/target

View File

@ -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"

View File

@ -1,6 +0,0 @@
[package]
name = "yggdrasil-abi-def"
version = "0.1.0"
edition = "2021"
[dependencies]

View File

@ -1 +0,0 @@
pub const ABI_FILE: &str = include_str!("../yggdrasil.abi");

View File

@ -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"

View File

@ -6,18 +6,31 @@ use abi_generator::{
TargetEnv,
};
fn generate_abi() {
fn load_abi_definitions<P: AsRef<Path>>(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<P: AsRef<Path>>(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");
}

30
lib/abi/def/error.abi Normal file
View File

@ -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,
}

191
lib/abi/def/io.abi Normal file
View File

@ -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,
}

View File

@ -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,
}

View File

@ -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) {

View File

@ -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)]

View File

@ -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 {

View File

@ -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);

View File

@ -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"));
}

View File

@ -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)]

View File

@ -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)]

View File

@ -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,
}

View File

@ -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 = "*"

View File

@ -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<P: AsRef<Path>>(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<P: AsRef<Path>>(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");
}

View File

@ -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,
};

View File

@ -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>)

View File

@ -40,7 +40,7 @@ impl DocumentItemAttributes for BitfieldType {
}
impl syn::parse::Parse for BitfieldDefaultValue {
fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
fn parse(input: syn::parse::ParseStream<'_>) -> syn::Result<Self> {
let items = input.parse_terminated(syn::Ident::parse, Token![|])?;
Ok(Self { items })
}

View File

@ -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<SyntaxError> 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)
}
}
}

View File

@ -96,7 +96,17 @@ fn process_type(t: &syn::Type, known_types: &TypeEnv) -> Result<Rc<ComplexType>,
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,

View File

@ -8,7 +8,7 @@ pub struct StructType {
}
impl syn::parse::Parse for StructType {
fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
fn parse(input: syn::parse::ParseStream<'_>) -> syn::Result<Self> {
let mut inner: syn::ItemStruct = input.parse()?;
inner.vis = syn::Visibility::Public(syn::token::Pub(input.span()));
Ok(Self { inner })

6
userspace/Cargo.lock generated
View File

@ -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]]