Squashed some bugs; implemented first iteration of kernel items

This commit is contained in:
Arthur Beck 2025-02-11 21:30:43 +00:00
parent a2311366f2
commit 04ee0a1cb2
13 changed files with 245 additions and 111 deletions

View file

@ -4,6 +4,7 @@
"rust-analyzer.linkedProjects": [ "rust-analyzer.linkedProjects": [
"kernel/Cargo.toml", "kernel/Cargo.toml",
"kernel/aphrodite_proc_macros/Cargo.toml", "kernel/aphrodite_proc_macros/Cargo.toml",
"kernel/aphrodite_common/Cargo.toml" "kernel/aphrodite_common/Cargo.toml",
"user/Cargo.toml"
], ],
} }

View file

@ -1,6 +1,6 @@
display_library: x, options="gui_debug" display_library: x, options="gui_debug"
port_e9_hack: enabled=1 port_e9_hack: enabled=1
cpu: reset_on_triple_fault=0, model=tigerlake cpu: reset_on_triple_fault=0, model=corei7_icelake_u
magic_break: enabled=1 magic_break: enabled=1
ata0-master: type=cdrom, path=../kernel/aphrodite.iso, status=inserted ata0-master: type=cdrom, path=../kernel/aphrodite.iso, status=inserted

View file

@ -1,6 +1,6 @@
# config.aphro for aphrodite devel-6a2a677-out-of-tree # config.aphro for aphrodite devel-6a2a677-out-of-tree
CFG_VERSION=devel-6a2a677-out-of-tree CFG_VERSION=devel-6a2a677-out-of-tree
CONT_WITH_DIFFERENT_VERSION=false CONT_WITH_DIFFERENT_VERSION=true
# Begin metadata # Begin metadata

View file

@ -1,3 +1,3 @@
#!/bin/bash #!/bin/bash
RUSTFLAGS='-Clink-arg=--script=link.x' cargo expand --target i686-unknown-none.json --release -Zbuild-std --bin entrypoint RUSTFLAGS='-Clink-arg=--script=link.x' cargo expand --target i686-unknown-none.json --release -Zbuild-std --bin entrypoint_x86

View file

@ -220,18 +220,18 @@ extern "C" fn _start() -> ! {
ptr = (ptr + current_tag.tag_len as usize + 7) & !7; ptr = (ptr + current_tag.tag_len as usize + 7) & !7;
if ptr>end_addr { if ptr>end_addr {
cfg_match! { cfg_match! {
cfg(all(CONFIG_PREUSER_ERROR_ON_INVALID_LENGTH = "true", CONFIG_PREUSER_PANIC_ON_INVALID_LENGTH = "false")) => { all(CONFIG_PREUSER_ERROR_ON_INVALID_LENGTH = "true", CONFIG_PREUSER_PANIC_ON_INVALID_LENGTH = "false") => {
serrorsln("Current tag length would put pointer out-of-bounds; CONFIG_PREUSER_ERROR_ON_INVALID_LENGTH is set, continuing"); serrorsln("Current tag length would put pointer out-of-bounds; CONFIG_PREUSER_ERROR_ON_INVALID_LENGTH is set, continuing");
} }
cfg(all(CONFIG_PREUSER_WARN_ON_INVALID_LENGTH = "true", CONFIG_PREUSER_PANIC_ON_INVALID_LENGTH = "false")) => { all(CONFIG_PREUSER_WARN_ON_INVALID_LENGTH = "true", CONFIG_PREUSER_PANIC_ON_INVALID_LENGTH = "false") => {
swarningsln("Current tag length would put pointer out-of-bounds; CONFIG_PREUSER_WARN_ON_INVALID_LENGTH is set, continuing"); swarningsln("Current tag length would put pointer out-of-bounds; CONFIG_PREUSER_WARN_ON_INVALID_LENGTH is set, continuing");
} }
} }
cfg_match! { cfg_match! {
cfg(not(CONFIG_PREUSER_PANIC_ON_INVALID_LENGTH = "false")) => { not(CONFIG_PREUSER_PANIC_ON_INVALID_LENGTH = "false") => {
panic!("current tag length would put pointer out-of-bounds") panic!("current tag length would put pointer out-of-bounds")
} }
cfg(CONFIG_PREUSER_EXIT_LOOP_ON_INVALID_LENGTH = "true") => { CONFIG_PREUSER_EXIT_LOOP_ON_INVALID_LENGTH = "true" => {
sinfos("Exiting loop as current tag length would put pointer out-of-bounds "); sinfos("Exiting loop as current tag length would put pointer out-of-bounds ");
sinfosnpln("and CONFIG_PREUSER_EXIT_LOOP_ON_INVALID_LENGTH is set"); sinfosnpln("and CONFIG_PREUSER_EXIT_LOOP_ON_INVALID_LENGTH is set");
break; break;
@ -263,7 +263,7 @@ extern "C" fn _start() -> ! {
sdebugs("Framebuffer bpp: "); sdebugs("Framebuffer bpp: ");
sdebugbnpln(&aphrodite::u8_as_u8_slice(framebuffer_info.bpp)); sdebugbnpln(&aphrodite::u8_as_u8_slice(framebuffer_info.bpp));
sdebugsln("Beginning output to screen..."); sdebugsln("Beginning test output to screen...");
let ega: &dyn aphrodite::display::TextDisplay = &framebuffer_info; let ega: &dyn aphrodite::display::TextDisplay = &framebuffer_info;
framebuffer_info.disable_cursor(); framebuffer_info.disable_cursor();
@ -272,11 +272,11 @@ extern "C" fn _start() -> ! {
toutputsln("Testing EGA Text framebuffer...", ega).unwrap(); toutputsln("Testing EGA Text framebuffer...", ega).unwrap();
toutputsln("Testing EGA Text framebuffer...", ega).unwrap(); toutputsln("Testing EGA Text framebuffer...", ega).unwrap();
aphrodite::indep_boot_entry::indep_boot_entry(Some(ega), &BI); aphrodite::indep_boot_entry::IndepBootEntry(Some(ega), &BI);
} }
} }
aphrodite::indep_boot_entry::indep_boot_entry(None, &BI); aphrodite::indep_boot_entry::IndepBootEntry(None, &BI);
} }
#[unsafe(link_section = ".panic")] #[unsafe(link_section = ".panic")]

View file

@ -1,37 +0,0 @@
use syn::{parse::Parse, Ident};
use strum::IntoEnumIterator;
use strum_macros::EnumIter;
#[derive(Debug, Clone, Copy, EnumIter)]
pub enum KernelItem {
IndepBootEntry,
ArchBootEntry,
SyscallSetup,
MemMapGen,
MemMapAlloc,
PreuserModLoad,
InitEnv,
KernelFSMount,
StorageFSMount,
PreuserMod,
RamLoader,
UserInit,
UserModLoad,
ProcessFSMount
}
impl Parse for KernelItem {
fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
let ident: Ident = input.parse()?;
for variant in Self::iter() {
let name = format!("{:?}", variant);
if ident.to_string().as_str() == name {
return Ok(variant);
}
}
Err(syn::Error::new(ident.span(), "Expected one of aphrodite_common::KernelItem's variants"))
}
}

View file

@ -13,7 +13,11 @@ const MEM_TEST_SIZES: [usize; 8] = [1, 2, 4, 8, 16, 32, 64, 128];
/// The real entrypoint to the kernel. `internel/arch/*/entry.rs` files eventually call this. /// The real entrypoint to the kernel. `internel/arch/*/entry.rs` files eventually call this.
#[kernel_item(IndepBootEntry)] #[kernel_item(IndepBootEntry)]
pub fn indep_boot_entry(display: Option<&dyn crate::display::TextDisplay>, BI: &crate::boot::BootInfo) -> ! { fn indep_boot_entry(
display: Option<&dyn crate::display::TextDisplay>,
#[allow(non_snake_case)]
BI: &crate::boot::BootInfo,
) -> ! {
crate::arch::output::sdebugsln("Entrypoint called"); crate::arch::output::sdebugsln("Entrypoint called");
let display = display.unwrap(); let display = display.unwrap();
@ -21,18 +25,19 @@ pub fn indep_boot_entry(display: Option<&dyn crate::display::TextDisplay>, BI: &
display.clear_screen(COLOR_DEFAULT); display.clear_screen(COLOR_DEFAULT);
sreset(); sreset();
let mut mem_map = BI.memory_map.unwrap(); let mem_map = BI.memory_map.unwrap();
let allocator_res = crate::mem::MemoryMapAlloc::new(&mut mem_map); crate::mem::MemMapAllocInit(mem_map).unwrap();
if allocator_res.is_err() { let allocator = crate::mem::MemMapAlloc().unwrap();
panic!("{}", allocator_res.unwrap_err());
}
let allocator = allocator_res.unwrap();
tdebugsln("Testing allocator...", display).unwrap(); tdebugsln("Testing allocator...", display).unwrap();
for size in MEM_TEST_SIZES { for size in MEM_TEST_SIZES {
tdebugs("Number of allocations: ", display).unwrap(); tdebugs("Number of allocations: ", display).unwrap();
tdebugbnpln(&crate::u64_as_u8_slice(allocator.number_of_allocations()), display).unwrap(); tdebugbnpln(
&crate::u64_as_u8_slice(allocator.number_of_allocations()),
display,
)
.unwrap();
tdebugs("Allocating ", display).unwrap(); tdebugs("Allocating ", display).unwrap();
tdebugbnp(&crate::usize_as_u8_slice(size), display).unwrap(); tdebugbnp(&crate::usize_as_u8_slice(size), display).unwrap();
@ -49,7 +54,12 @@ pub fn indep_boot_entry(display: Option<&dyn crate::display::TextDisplay>, BI: &
tdebugsnpln(".", display).unwrap(); tdebugsnpln(".", display).unwrap();
tdebugsln("", display).unwrap(); tdebugsln("", display).unwrap();
tdebugsln("Deallocating memory...", display).unwrap(); tdebugsln("Deallocating memory...", display).unwrap();
unsafe { allocator.deallocate(ptr.as_non_null_ptr(), Layout::from_size_align(size, 1).unwrap()) } unsafe {
allocator.deallocate(
ptr.as_non_null_ptr(),
Layout::from_size_align(size, 1).unwrap(),
)
}
if let Err(err) = unsafe { crate::mem::LAST_MEMMAP_ERR } { if let Err(err) = unsafe { crate::mem::LAST_MEMMAP_ERR } {
terrors("Failed to deallocate: ", display).unwrap(); terrors("Failed to deallocate: ", display).unwrap();
err.display_np(display); err.display_np(display);

View file

@ -1,10 +1,17 @@
//! Memory allocation. //! Memory allocation.
use core::{ use core::{
alloc::{Allocator, GlobalAlloc}, fmt::Debug, num::NonZero, ops::Range, ptr::{null_mut, NonNull} alloc::{Allocator, GlobalAlloc},
fmt::Debug,
mem::MaybeUninit,
num::NonZero,
ops::Range,
ptr::{NonNull, null_mut},
}; };
use crate::boot::MemoryType; use crate::boot::{MemoryMap, MemoryType};
use aphrodite_proc_macros::*;
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
struct Allocation { struct Allocation {
@ -56,6 +63,42 @@ impl Iterator for AllocationIter {
} }
} }
static mut ALLOCATOR: MaybeUninit<MemoryMapAlloc<'static>> = MaybeUninit::uninit();
static mut ALLOCATOR_MEMMAP: MaybeUninit<MemoryMap> = MaybeUninit::uninit();
static mut ALLOCATOR_INITALIZED: bool = false;
#[kernel_item(MemMapAlloc)]
fn get_allocator() -> Option<&'static MemoryMapAlloc<'static>> {
if unsafe { ALLOCATOR_INITALIZED } {
#[allow(static_mut_refs)]
return Some(unsafe { ALLOCATOR.assume_init_ref() });
} else {
return None;
}
}
#[kernel_item(MemMapAllocInit)]
fn memory_map_alloc_init(
memmap: crate::boot::MemoryMap,
) -> Result<(), crate::Error<'static>> {
#[allow(static_mut_refs)]
unsafe {
ALLOCATOR_MEMMAP.write(memmap);
}
#[allow(static_mut_refs)]
let alloc = MemoryMapAlloc::new(unsafe { ALLOCATOR_MEMMAP.assume_init_mut() })?;
#[allow(static_mut_refs)]
unsafe {
ALLOCATOR.write(alloc);
}
unsafe {
ALLOCATOR_INITALIZED = true;
}
Ok(())
}
/// A implementation of a physical memory allocator that uses a [crate::boot::MemoryMap]. /// A implementation of a physical memory allocator that uses a [crate::boot::MemoryMap].
pub struct MemoryMapAlloc<'a> { pub struct MemoryMapAlloc<'a> {
/// The memory map to use to allocate memory. /// The memory map to use to allocate memory.
@ -84,7 +127,12 @@ const EXTEND_ALLOCATION_OTHER_ALLOCATION: i16 = -6;
impl<'a> Debug for MemoryMapAlloc<'a> { impl<'a> Debug for MemoryMapAlloc<'a> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.write_str("MemoryMapAlloc with ")?; f.write_str("MemoryMapAlloc with ")?;
f.write_str(core::str::from_utf8(&crate::u64_as_u8_slice(unsafe { *self.allocationheader }.num_allocations)).unwrap())?; f.write_str(
core::str::from_utf8(&crate::u64_as_u8_slice(
unsafe { *self.allocationheader }.num_allocations,
))
.unwrap(),
)?;
f.write_str(" allocations")?; f.write_str(" allocations")?;
Ok(()) Ok(())
} }
@ -115,7 +163,9 @@ impl<'a> MemoryMapAlloc<'a> {
(), (),
); );
out.allocations = core::ptr::from_raw_parts_mut( out.allocations = core::ptr::from_raw_parts_mut(
core::ptr::without_provenance_mut::<()>(mapping.start as usize+size_of::<AllocationHeader>()), core::ptr::without_provenance_mut::<()>(
mapping.start as usize + size_of::<AllocationHeader>(),
),
(), (),
); );
out.max_allocations_size = mapping.len; out.max_allocations_size = mapping.len;
@ -126,7 +176,9 @@ impl<'a> MemoryMapAlloc<'a> {
(), (),
); );
out.allocations = core::ptr::from_raw_parts_mut( out.allocations = core::ptr::from_raw_parts_mut(
core::ptr::without_provenance_mut::<()>(mapping.start as usize+size_of::<AllocationHeader>()), core::ptr::without_provenance_mut::<()>(
mapping.start as usize + size_of::<AllocationHeader>(),
),
(), (),
); );
out.max_allocations_size = mapping.len; out.max_allocations_size = mapping.len;
@ -149,7 +201,7 @@ impl<'a> MemoryMapAlloc<'a> {
used: true, used: true,
addr: out.allocations as usize as u64, addr: out.allocations as usize as u64,
len: (size_of::<Allocation>() * 32) as u64, len: (size_of::<Allocation>() * 32) as u64,
num_allocations: 1 num_allocations: 1,
} }
} }
Ok(out) Ok(out)
@ -182,10 +234,10 @@ impl<'a> MemoryMapAlloc<'a> {
let num_allocations = unsafe { *self.allocationheader }.num_allocations; let num_allocations = unsafe { *self.allocationheader }.num_allocations;
if unsafe { *self.allocations }.len if unsafe { *self.allocations }.len < (size_of::<Allocation>() as u64 * (num_allocations)) {
< (size_of::<Allocation>() as u64 * (num_allocations)) if unsafe { *self.allocationheader }.len + size_of::<Allocation>() as u64
>= self.max_allocations_size
{ {
if unsafe { *self.allocationheader }.len + size_of::<Allocation>() as u64 >= self.max_allocations_size {
return Err(crate::Error::new( return Err(crate::Error::new(
"not enough space for another allocation", "not enough space for another allocation",
TOO_MANY_ALLOCATIONS, TOO_MANY_ALLOCATIONS,
@ -266,7 +318,9 @@ impl<'a> MemoryMapAlloc<'a> {
/// Check to see if any allocations contain the given address. Returns true if so. /// Check to see if any allocations contain the given address. Returns true if so.
fn check_addr(&self, addr: u64) -> bool { fn check_addr(&self, addr: u64) -> bool {
if addr >= (self.allocationheader as u64) && addr < (self.allocationheader as u64+unsafe { *self.allocationheader }.len) { if addr >= (self.allocationheader as u64)
&& addr < (self.allocationheader as u64 + unsafe { *self.allocationheader }.len)
{
return true; return true;
} }
for ele in self.allocations_iter() { for ele in self.allocations_iter() {
@ -346,10 +400,16 @@ unsafe impl<'a> Allocator for MemoryMapAlloc<'a> {
} }
if allocatable { if allocatable {
addr = mapping.start + mapping.len - layout.size() as u64; addr = mapping.start + mapping.len - layout.size() as u64;
while self.check_range(addr..addr+layout.size() as u64) && (addr as usize % layout.align() != 0) && addr >= mapping.start { while self.check_range(addr..addr + layout.size() as u64)
&& (addr as usize % layout.align() != 0)
&& addr >= mapping.start
{
addr -= layout.size() as u64 / crate::cfg_int!("CONFIG_ALLOC_PRECISION", u64); addr -= layout.size() as u64 / crate::cfg_int!("CONFIG_ALLOC_PRECISION", u64);
} }
if (!self.check_range(addr..addr+layout.size() as u64)) && (addr as usize % layout.align() == 0) && addr >= mapping.start { if (!self.check_range(addr..addr + layout.size() as u64))
&& (addr as usize % layout.align() == 0)
&& addr >= mapping.start
{
break; break;
} }
continue; continue;
@ -364,7 +424,11 @@ unsafe impl<'a> Allocator for MemoryMapAlloc<'a> {
} }
return Err(core::alloc::AllocError {}); return Err(core::alloc::AllocError {});
} }
if let Err(err) = self.add_allocation(Allocation { used: true, addr, len: layout.size() as u64 }) { if let Err(err) = self.add_allocation(Allocation {
used: true,
addr,
len: layout.size() as u64,
}) {
unsafe { LAST_MEMMAP_ERR = Err(err) } unsafe { LAST_MEMMAP_ERR = Err(err) }
return Err(core::alloc::AllocError {}); return Err(core::alloc::AllocError {});
} }
@ -387,7 +451,9 @@ unsafe impl<'a> Allocator for MemoryMapAlloc<'a> {
} }
return; return;
} }
crate::arch::output::sdebugbln(&crate::u64_as_u8_slice(unsafe { *self.allocationheader }.num_allocations)); crate::arch::output::sdebugbln(&crate::u64_as_u8_slice(
unsafe { *self.allocationheader }.num_allocations,
));
for allocation in self.allocations_iter() { for allocation in self.allocations_iter() {
crate::arch::output::sdebugsln("Allocation"); crate::arch::output::sdebugsln("Allocation");
let alloc = unsafe { *allocation }.clone(); let alloc = unsafe { *allocation }.clone();
@ -401,7 +467,12 @@ unsafe impl<'a> Allocator for MemoryMapAlloc<'a> {
} }
} }
// Memory not allocated, something is up, this is put after the loop to prevent a costly call to check_addr // Memory not allocated, something is up, this is put after the loop to prevent a costly call to check_addr
unsafe { LAST_MEMMAP_ERR = Err(crate::Error::new("memory not allocated", MEMORY_NOT_ALLOCATED)) } unsafe {
LAST_MEMMAP_ERR = Err(crate::Error::new(
"memory not allocated",
MEMORY_NOT_ALLOCATED,
))
}
return; return;
} }
} }

View file

@ -1,26 +1,32 @@
use proc_macro::TokenStream; use proc_macro::TokenStream;
use quote::{quote_spanned, ToTokens}; use quote::{ToTokens, quote};
use syn::{parse::{Parse, ParseStream}, spanned::Spanned, ItemFn, Signature, Token}; use syn::{
ItemFn, Signature, Token,
parse::{Parse, ParseStream}
};
struct KernelItemNameInput { struct KernelItemNameInput {
item: aphrodite_common::KernelItem item: syn::Ident,
} }
impl Parse for KernelItemNameInput { impl Parse for KernelItemNameInput {
fn parse(input: ParseStream) -> syn::Result<Self> { fn parse(input: ParseStream) -> syn::Result<Self> {
let item: aphrodite_common::KernelItem = input.parse()?; let item: syn::Ident = input.parse()?;
Ok(KernelItemNameInput { item }) Ok(KernelItemNameInput { item })
} }
} }
fn to_tokens(signature: Signature, tokens: &mut TokenStream) { fn to_tokens(signature: Signature, tokens: &mut proc_macro2::TokenStream) {
signature.constness.to_tokens(&mut (*tokens).clone().into()); let ts = tokens;
signature.asyncness.to_tokens(&mut (*tokens).clone().into()); signature.constness.to_tokens(ts.into());
signature.unsafety.to_tokens(&mut (*tokens).clone().into()); signature.asyncness.to_tokens(ts.into());
signature.abi.to_tokens(&mut (*tokens).clone().into()); signature.unsafety.to_tokens(ts.into());
signature.fn_token.to_tokens(&mut (*tokens).clone().into()); signature.abi.to_tokens(ts.into());
signature.generics.to_tokens(&mut (*tokens).clone().into()); signature.fn_token.to_tokens(ts.into());
signature.paren_token.surround(&mut (*tokens).clone().into(), |tokens| { signature.generics.to_tokens(ts.into());
signature
.paren_token
.surround(ts.into(), |tokens| {
signature.inputs.to_tokens(tokens); signature.inputs.to_tokens(tokens);
if let Some(variadic) = &signature.variadic { if let Some(variadic) = &signature.variadic {
if !signature.inputs.empty_or_trailing() { if !signature.inputs.empty_or_trailing() {
@ -29,12 +35,15 @@ fn to_tokens(signature: Signature, tokens: &mut TokenStream) {
variadic.to_tokens(tokens); variadic.to_tokens(tokens);
} }
}); });
signature.output.to_tokens(&mut (*tokens).clone().into()); signature.output.to_tokens(ts.into());
signature.generics.where_clause.to_tokens(&mut (*tokens).clone().into()); signature
.generics
.where_clause
.to_tokens(ts.into());
} }
fn to_token_stream(signature: Signature) -> TokenStream { fn to_token_stream(signature: Signature) -> proc_macro2::TokenStream {
let mut tokens = proc_macro::TokenStream::new(); let mut tokens = proc_macro2::TokenStream::new();
to_tokens(signature, &mut tokens); to_tokens(signature, &mut tokens);
tokens.into() tokens.into()
} }
@ -42,18 +51,19 @@ fn to_token_stream(signature: Signature) -> TokenStream {
/// Implement a kernel item. /// Implement a kernel item.
#[proc_macro_attribute] #[proc_macro_attribute]
pub fn kernel_item(attr: TokenStream, item: TokenStream) -> TokenStream { pub fn kernel_item(attr: TokenStream, item: TokenStream) -> TokenStream {
let item_name_input: KernelItemNameInput = syn::parse_macro_input!(attr); let name: KernelItemNameInput = syn::parse_macro_input!(attr);
let item_name = format!("{:?}", item_name_input.item); let item_name = name.item;
let input_fn: ItemFn = syn::parse_macro_input!(item as ItemFn); let input_fn = syn::parse_macro_input!(item as ItemFn);
let fn_name = input_fn.clone().sig.ident; let fn_name = input_fn.clone().sig.ident;
let fn_sig = to_token_stream(input_fn.clone().sig); let fn_sig = to_token_stream(input_fn.clone().sig);
quote_spanned!(input_fn.span()=>{ quote!{
// The #item_name kernel item. /// The #item_name kernel item.
#[allow(non_upper_case_globals)] #[allow(non_upper_case_globals)]
pub const #item_name: #fn_sig = #fn_name; pub const #item_name: #fn_sig = #fn_name;
#input_fn #input_fn
}).into() }
.into()
} }

6
user/Cargo.toml Normal file
View file

@ -0,0 +1,6 @@
[package]
name = "user"
version = "0.1.0"
edition = "2024"
[dependencies]

6
user/src/arch/mod.rs Normal file
View file

@ -0,0 +1,6 @@
//! Architecture-specific stuff, mainly syscall methods.
#[macro_use]
mod x86;
pub use x86::*;

62
user/src/arch/x86/mod.rs Normal file
View file

@ -0,0 +1,62 @@
//! x86 syscall method.
/// Syscall method.
#[macro_export]
macro_rules! syscall {
($id: expr) => {
unsafe {
let out = 0u32;
asm!(
"int 0xA0",
id = in("eax") const $id,
out("eax") out
)
out
}
};
($id: expr, $d0: expr) => {
unsafe {
let out = 0u32;
let d0 = $d0;
asm!(
"int 0xA0",
id = in("eax") const $id,
d0 = in("ebx") $d0,
out("eax") out
)
out
}
};
($id: expr, $d0: expr, $d1: expr) => {
unsafe {
let out = 0u32;
let d0 = $d0;
let d1 = $d1;
asm!(
"int 0xA0",
id = in("eax") const $id,
d0 = in("ebx") $d0,
d1 = in("ecx") $d1,
out("eax") out
)
out
}
};
($id: expr, $d0: expr, $d1: expr, $d2: expr) => {
unsafe {
let out = 0u32;
let d0 = $d0;
let d1 = $d1;
let d2 = $d2;
asm!(
"int 0xA0",
id = in("eax") const $id,
d0 = in("ebx") $d0,
d1 = in("ecx") $d1,
d2 = in("edx") $d2,
out("eax") out
)
out
}
}
}

5
user/src/lib.rs Normal file
View file

@ -0,0 +1,5 @@
#[warn(missing_docs)]
mod arch;
use arch::*;