Skip to content

Commit

Permalink
Implement support for C programs
Browse files Browse the repository at this point in the history
  • Loading branch information
fruhland committed Sep 13, 2024
1 parent 313c873 commit 0b86bc7
Show file tree
Hide file tree
Showing 39 changed files with 275 additions and 143 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ jobs:
- name: Install packages
uses: amitie10g/[email protected]
with:
brew: x86_64-elf-binutils nasm
brew: x86_64-elf-binutils x86_64-elf-gcc nasm

- name: Install Rust
uses: dtolnay/rust-toolchain@nightly
Expand Down Expand Up @@ -84,7 +84,7 @@ jobs:
- name: Install packages
uses: amitie10g/[email protected]
with:
brew: x86_64-elf-binutils nasm
brew: x86_64-elf-binutils x86_64-elf-gcc nasm

- name: Install Rust
uses: dtolnay/rust-toolchain@nightly
Expand Down
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ resolver = "2"
members = [
"os/kernel",
"os/application/hello",
"os/application/helloc",
"os/application/shell",
"os/application/uptime",
"os/application/date",
Expand Down
12 changes: 4 additions & 8 deletions Makefile.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ INITRD_DIRECTORY = "${BOOTLOADER_DIRECTORY}/initrd"
OVMF_URL = "https://retrage.github.io/edk2-nightly/bin/RELEASEX64_OVMF.fd"
TOWBOOT_VERSION = "0.9.0"
TOWBOOT_URL = "https://github.com/hhuOS/towboot/releases/download/v${TOWBOOT_VERSION}/towbootctl-v${TOWBOOT_VERSION}"
LINKER = "ld"
LINKER_MAC = "x86_64-elf-ld"
TAR = { source = "${CARGO_MAKE_RUST_TARGET_OS}", default_value = "tar", mapping = { "macos" = "gtar" } }
LINKER = { source = "${CARGO_MAKE_RUST_TARGET_OS}", default_value = "ld", mapping = { "macos" = "x86_64-elf-ld" } }

[tasks.default]
alias = "qemu"
Expand Down Expand Up @@ -152,15 +152,11 @@ condition = { files_not_exist = [ "${INITRD_DIRECTORY}" ] }

[tasks.initrd]
cwd = "${INITRD_DIRECTORY}"
command = "tar"
args = [ "-cf", "${BOOTLOADER_DIRECTORY}/initrd.tar", "hello", "shell", "uptime", "date", "mkentry" ]
command = "${TAR}"
args = [ "-cf", "${BOOTLOADER_DIRECTORY}/initrd.tar", "hello", "helloc", "shell", "uptime", "date", "mkentry" ]
dependencies = [ "link-members" ]
condition = { files_modified = { input = [ "${INITRD_DIRECTORY}/*" ], output = [ "${BOOTLOADER_DIRECTORY}/initrd.tar" ] } }

[tasks.initrd.mac]
cwd = "${INITRD_DIRECTORY}"
command = "gtar"

[tasks.image]
cwd = "${BOOTLOADER_DIRECTORY}"
command = "${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/towbootctl"
Expand Down
3 changes: 0 additions & 3 deletions os/application/date/Makefile.toml
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,6 @@ args = [ "-n", "-T", "${LINKER_FILE}", "-o", "${APPLICATION}", "${RUST_OBJECT}"
dependencies = [ "compile" ]
condition = { files_modified = { input = [ "${BUILD_DIRECTORY}/lib${CARGO_MAKE_PROJECT_NAME}*" ], output = [ "${BOOTLOADER_DIRECTORY}/initrd/${CARGO_MAKE_PROJECT_NAME}" ] } }

[tasks.link.mac]
command = "${LINKER_MAC}"

# Cleanup tasks

[tasks.clean]
Expand Down
3 changes: 0 additions & 3 deletions os/application/hello/Makefile.toml
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,6 @@ args = [ "-n", "-T", "${LINKER_FILE}", "-o", "${APPLICATION}", "${RUST_OBJECT}"
dependencies = [ "compile" ]
condition = { files_modified = { input = [ "${BUILD_DIRECTORY}/lib${CARGO_MAKE_PROJECT_NAME}*" ], output = [ "${BOOTLOADER_DIRECTORY}/initrd/${CARGO_MAKE_PROJECT_NAME}" ] } }

[tasks.link.mac]
command = "${LINKER_MAC}"

# Cleanup tasks

[tasks.clean]
Expand Down
7 changes: 4 additions & 3 deletions os/application/hello/src/hello.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,11 @@ pub fn main() {
let process = process::current().unwrap();
let thread = thread::current().unwrap();

println!("Hello from Thread [{}] in Process [{}]!", thread.id(), process.id());
println!("Hello from Thread [{}] in Process [{}]!\n", thread.id(), process.id());

println!("Arguments:");
let args = env::args();
for (i, arg) in args.enumerate() {
println!("Arg[{}]: {}", i, arg);
for arg in args {
println!(" {}", arg);
}
}
19 changes: 19 additions & 0 deletions os/application/helloc/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
cargo-features = ["edition2024"]

[package]
edition = "2024"
name = "helloc"
version = "0.1.0"
authors = ["Michael Schöttner <[email protected]>, Fabian Ruhland <[email protected]>"]
build = "build.rs"

[lib]
crate-type = ["staticlib"]

[dependencies]
# Local dependencies
runtime = { path = "../../library/runtime" }
libc = { path = "../../library/libc" }

[build-dependencies]
cc = "1.1.18"
55 changes: 55 additions & 0 deletions os/application/helloc/Makefile.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
[env.development]
CARGO_CFG_TARGET_FAMILY = "${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/d3os_application.json"
BUILD_DIRECTORY = "${CARGO_MAKE_CRATE_TARGET_DIRECTORY}/d3os_application/debug"
CARGO_BUILD_OPTION = "--lib"

[env.production]
CARGO_CFG_TARGET_FAMILY = "${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/d3os_application.json"
BUILD_DIRECTORY = "${CARGO_MAKE_CRATE_TARGET_DIRECTORY}/d3os_application/release"
CARGO_BUILD_OPTION = "--release"

[env]
CARGO_MAKE_EXTEND_WORKSPACE_MAKEFILE = true
RUST_TARGET_PATH = "${CARGO_MAKE_WORKING_DIRECTORY}"
SOURCE_DIRECTORY = "${CARGO_MAKE_WORKING_DIRECTORY}/src"
LIBRARY_DIRECTORY = "${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/os/library"
LINKER_FILE = "${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/os/application/link.ld"
RUST_OBJECT = "${BUILD_DIRECTORY}/lib${CARGO_MAKE_PROJECT_NAME}.a"
APPLICATION = "${INITRD_DIRECTORY}/${CARGO_MAKE_PROJECT_NAME}"
CC = { source = "${CARGO_MAKE_RUST_TARGET_OS}", default_value = "gcc", mapping = { "macos" = "x86_64-elf-gcc" } }
CRATE_CC_NO_DEFAULTS = "true"

# Build tasks

[tasks.default]
alias = "link"

[tasks.compile]
command = "cargo"
args = [ "build", "-Z", "build-std=core,alloc", "-Z", "build-std-features=compiler-builtins-mem", "--target", "${CARGO_CFG_TARGET_FAMILY}", "${CARGO_BUILD_OPTION}" ]
condition = { files_modified = { input = [
"${CARGO_MAKE_WORKING_DIRECTORY}/Cargo.toml", "${SOURCE_DIRECTORY}/**/*.rs",
"${CARGO_MAKE_WORKING_DIRECTORY}/Cargo.toml", "${SOURCE_DIRECTORY}/**/*.c",
"${LIBRARY_DIRECTORY}/libc/Cargo.toml", "${LIBRARY_DIRECTORY}/libc/src/**/*.rs",
"${LIBRARY_DIRECTORY}/libc/Cargo.toml", "${LIBRARY_DIRECTORY}/libc/src/**/*.h",
"${LIBRARY_DIRECTORY}/runtime/Cargo.toml", "${LIBRARY_DIRECTORY}/runtime/src/**/*.rs",
"${LIBRARY_DIRECTORY}/terminal/Cargo.toml", "${LIBRARY_DIRECTORY}/terminal/src/**/*.rs",
"${LIBRARY_DIRECTORY}/concurrent/Cargo.toml", "${LIBRARY_DIRECTORY}/concurrent/src/**/*.rs",
"${LIBRARY_DIRECTORY}/syscall/Cargo.toml", "${LIBRARY_DIRECTORY}/syscall/src/**/*.rs" ], output = [ "${BUILD_DIRECTORY}/lib${CARGO_MAKE_PROJECT_NAME}*" ] } }

[tasks.link]
command = "${LINKER}"
args = [ "-n", "-T", "${LINKER_FILE}", "-o", "${APPLICATION}", "${RUST_OBJECT}" ]
dependencies = [ "compile" ]
condition = { files_modified = { input = [ "${BUILD_DIRECTORY}/lib${CARGO_MAKE_PROJECT_NAME}*" ], output = [ "${BOOTLOADER_DIRECTORY}/initrd/${CARGO_MAKE_PROJECT_NAME}" ] } }

# Cleanup tasks

[tasks.clean]
command = "cargo"
args = [ "clean" ]
dependencies = [ "remove-application" ]

[tasks.remove-application]
command = "rm"
args = [ "-f", "${APPLICATION}" ]
11 changes: 11 additions & 0 deletions os/application/helloc/build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
fn main() {
println!("cargo:rerun-if-changed=src,../../library/libc/src/");

cc::Build::new()
.file("src/hello.c")
.flag("-nostdlib")
.flag("-ffreestanding")
.flag("-fno-stack-protector")
.flag("-fpic")
.compile("hello");
}
14 changes: 14 additions & 0 deletions os/application/helloc/src/hello.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#include "../../../library/libc/src/runtime.h"

int main(int argc, char *argv[]) {
terminal_write("Hello from C!\n\n");

terminal_write("Arguments:\n");
for (int i = 0; i < argc; i++) {
terminal_write(" ");
terminal_write(argv[i]);
terminal_write("\n");
}

return 0;
}
6 changes: 6 additions & 0 deletions os/application/helloc/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#![no_std]

#[allow(unused_imports)]
use runtime::*;
#[allow(unused_imports)]
use libc::*;
3 changes: 0 additions & 3 deletions os/application/mkentry/Makefile.toml
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,6 @@ args = [ "-n", "-T", "${LINKER_FILE}", "-o", "${APPLICATION}", "${RUST_OBJECT}"
dependencies = [ "compile" ]
condition = { files_modified = { input = [ "${BUILD_DIRECTORY}/lib${CARGO_MAKE_PROJECT_NAME}*" ], output = [ "${BOOTLOADER_DIRECTORY}/initrd/${CARGO_MAKE_PROJECT_NAME}" ] } }

[tasks.link.mac]
command = "${LINKER_MAC}"

# Cleanup tasks

[tasks.clean]
Expand Down
3 changes: 0 additions & 3 deletions os/application/shell/Makefile.toml
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,6 @@ args = [ "-n", "-T", "${LINKER_FILE}", "-o", "${APPLICATION}", "${RUST_OBJECT}"
dependencies = [ "compile" ]
condition = { files_modified = { input = [ "${BUILD_DIRECTORY}/lib${CARGO_MAKE_PROJECT_NAME}*" ], output = [ "${BOOTLOADER_DIRECTORY}/initrd/${CARGO_MAKE_PROJECT_NAME}" ] } }

[tasks.link.mac]
command = "${LINKER_MAC}"

# Cleanup tasks

[tasks.clean]
Expand Down
3 changes: 0 additions & 3 deletions os/application/uptime/Makefile.toml
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,6 @@ args = [ "-n", "-T", "${LINKER_FILE}", "-o", "${APPLICATION}", "${RUST_OBJECT}"
dependencies = [ "compile" ]
condition = { files_modified = { input = [ "${BUILD_DIRECTORY}/lib${CARGO_MAKE_PROJECT_NAME}*" ], output = [ "${BOOTLOADER_DIRECTORY}/initrd/${CARGO_MAKE_PROJECT_NAME}" ] } }

[tasks.link.mac]
command = "${LINKER_MAC}"

# Cleanup tasks

[tasks.clean]
Expand Down
3 changes: 0 additions & 3 deletions os/kernel/Makefile.toml
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,6 @@ args = [ "-n", "-T", "${LINKER_FILE}", "-o", "${KERNEL}", "${ASM_OBJECT}", "${RU
dependencies = [ "compile", "build-asm" ]
condition = { files_modified = { input = [ "${BUILD_DIRECTORY}/lib${CARGO_MAKE_PROJECT_NAME}*" ], output = [ "${BOOTLOADER_DIRECTORY}/kernel.elf" ] } }

[tasks.link.mac]
command = "${LINKER_MAC}"

# Cleanup tasks

[tasks.clean]
Expand Down
27 changes: 10 additions & 17 deletions os/kernel/src/process/thread.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ use x86_64::structures::paging::page::PageRange;
use x86_64::structures::paging::{Page, PageTableFlags, Size4KiB};
use x86_64::PrivilegeLevel::Ring3;
use x86_64::VirtAddr;

use crate::consts::{KERNEL_STACK_PAGES, USER_SPACE_ENV_START};
use crate::consts::MAIN_USER_STACK_START;
use crate::consts::MAX_USER_STACK_SIZE;
Expand Down Expand Up @@ -166,26 +165,20 @@ impl Thread {
let args_begin_virt = env_virt_start.start_address() + size_of::<usize>() as u64 + ((args.len() + 1) * size_of::<usize>()) as u64; // Virtual start address of arguments (they will be visible here in user space)

// copy program name as first argument
let mut current_arg = args_begin;
let mut current_arg_len = current_arg as *mut usize;
let mut current_arg_str = current_arg.offset(size_of::<usize>() as isize);

current_arg_len.write_unaligned(name.len());
current_arg_str.copy_from(name.as_bytes().as_ptr(), name.len());
args_begin.copy_from(name.as_bytes().as_ptr(), name.len());
args_begin.add(name.len()).write(0); // null-terminate the string for C compatibility
argv.write(args_begin_virt.as_ptr());
let mut offset = size_of::<usize>() + name.len();

// copy remaining arguments
for i in 0..args.len() {
current_arg = args_begin.offset(offset as isize);
current_arg_len = current_arg as *mut usize;
current_arg_str = current_arg.offset(size_of::<usize>() as isize);
let mut offset = name.len() + 1;

current_arg_len.write_unaligned(args[i].len());
current_arg_str.copy_from(args[i].as_bytes().as_ptr(), args[i].len());
// copy remaining arguments
for (i, arg) in args.iter().enumerate() {
let target = args_begin.add(offset);
target.copy_from(arg.as_bytes().as_ptr(), arg.len());
target.add(arg.len()).write(0); // null-terminate the string for C compatibility

argv.offset((i + 1) as isize).write((args_begin_virt + offset as u64).as_ptr());
offset += size_of::<usize>() + args[i].len();
argv.add(i + 1).write((args_begin_virt + offset as u64).as_ptr());
offset += arg.len() + 1;
}
}

Expand Down
37 changes: 21 additions & 16 deletions os/kernel/src/syscall/sys_concurrent.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,57 +10,62 @@ use alloc::vec::Vec;
use alloc::rc::Rc;
use core::ptr::slice_from_raw_parts;
use core::str::from_utf8;
use x86_64::VirtAddr;
use x86_64::VirtAddr;
use syscall::return_vals::Errno;
use crate::{initrd, process_manager, scheduler};
use crate::process::thread::Thread;


pub fn sys_process_id() -> usize {
process_manager().read().current_process().id()
pub fn sys_process_id() -> isize {
process_manager().read().current_process().id() as isize
}

pub fn sys_process_exit() {
pub fn sys_process_exit() -> isize {
scheduler().current_thread().process().exit();
scheduler().exit();
0
}

#[allow(improper_ctypes_definitions)] // 'entry' takes no arguments and has no return value, so we just assume that the "C" and "Rust" ABIs act the same way in this case
pub fn sys_thread_create(kickoff_addr: u64, entry: fn()) -> usize {
pub fn sys_thread_create(kickoff_addr: u64, entry: fn()) -> isize {
let thread = Thread::new_user_thread(process_manager().read().current_process(), VirtAddr::new(kickoff_addr), entry);
let id = thread.id();

scheduler().ready(thread);
id
id as isize
}

pub fn sys_thread_id() -> usize {
scheduler().current_thread().id()
pub fn sys_thread_id() -> isize {
scheduler().current_thread().id() as isize
}

pub fn sys_thread_switch() {
pub fn sys_thread_switch() -> isize {
scheduler().switch_thread_no_interrupt();
0
}

pub fn sys_thread_sleep(ms: usize) {
pub fn sys_thread_sleep(ms: usize) -> isize {
scheduler().sleep(ms);
0
}

pub fn sys_thread_join(id: usize) {
pub fn sys_thread_join(id: usize) -> isize {
scheduler().join(id);
0
}

pub fn sys_thread_exit() {
pub fn sys_thread_exit() -> isize {
scheduler().exit();
0
}

pub fn sys_process_execute_binary(name_buffer: *const u8, name_length: usize, args: *const Vec<&str>) -> usize {
pub fn sys_process_execute_binary(name_buffer: *const u8, name_length: usize, args: *const Vec<&str>) -> isize {
let app_name = from_utf8(unsafe { slice_from_raw_parts(name_buffer, name_length).as_ref().unwrap() }).unwrap();
match initrd().entries().find(|entry| entry.filename().as_str().unwrap() == app_name) {
Some(app) => {
let thread = Thread::load_application(app.data(), app_name, unsafe { args.as_ref().unwrap() });
scheduler().ready(Rc::clone(&thread));
thread.id()
thread.id() as isize
}
None => 0,
None => Errno::ENOENT.into(),
}
}
Loading

0 comments on commit 0b86bc7

Please sign in to comment.