IPC dissecting initial start

This commit is contained in:
pjht 2025-02-25 22:00:26 -06:00
parent ab0c22ecc9
commit 1c8540d851
Signed by: pjht
GPG Key ID: CA239FC6934E6F3A
15 changed files with 1675 additions and 8 deletions

132
Cargo.lock generated
View File

@ -20,6 +20,15 @@ version = "0.2.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "45862d1c77f2228b9e10bc609d5bc203d86ebc9b87ad8d5d5167a6c9abf739d9"
[[package]]
name = "atomic-polyfill"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8cf2bce30dfe09ef0bfaef228b9d414faaf7e563035494d7fe092dba54b300f4"
dependencies = [
"critical-section",
]
[[package]]
name = "autocfg"
version = "1.4.0"
@ -46,9 +55,12 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "bitflags"
version = "2.6.0"
version = "2.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de"
checksum = "8f68f53c83ab957f72c32642f3868eec03eb974d1fb82e453128456482613d36"
dependencies = [
"serde",
]
[[package]]
name = "bootloader_api"
@ -65,6 +77,12 @@ dependencies = [
"spin",
]
[[package]]
name = "byteorder"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
[[package]]
name = "cast"
version = "0.3.0"
@ -77,6 +95,18 @@ version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "cobs"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "67ba02a97a2bd10f4b59b25c7973101c79642302776489e030cd13cdab09ed15"
[[package]]
name = "critical-section"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b"
[[package]]
name = "crossbeam-queue"
version = "0.3.11"
@ -109,12 +139,33 @@ version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4445909572dbd556c457c849c4ca58623d84b27c8fff1e74b0b4227d8b90d17b"
[[package]]
name = "embedded-io"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ef1a6892d9eef45c8fa6b9e0086428a2cca8491aca8f787c534a3d6d0bcb3ced"
[[package]]
name = "embedded-io"
version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "edd0f118536f44f5ccd48bcb8b111bdc3de888b58c74639dfb034a357d0f206d"
[[package]]
name = "gimli"
version = "0.28.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253"
[[package]]
name = "hash32"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b0c35f58762feb77d74ebe43bdbc3210f09be9fe6742234d573bacc26ed92b67"
dependencies = [
"byteorder",
]
[[package]]
name = "hashbrown"
version = "0.14.5"
@ -125,6 +176,20 @@ dependencies = [
"allocator-api2",
]
[[package]]
name = "heapless"
version = "0.7.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cdc6457c0eb62c71aac4bc17216026d8410337c4126773b9c5daba343f17964f"
dependencies = [
"atomic-polyfill",
"hash32",
"rustc_version",
"serde",
"spin",
"stable_deref_trait",
]
[[package]]
name = "humansize"
version = "2.1.3"
@ -148,6 +213,7 @@ name = "kernel"
version = "0.1.0"
dependencies = [
"az",
"bitflags 2.8.0",
"bootloader_api",
"buddy_system_allocator",
"cast",
@ -159,8 +225,10 @@ dependencies = [
"intrusive-collections",
"linked_list_allocator",
"pic8259",
"postcard",
"replace_with",
"saturating_cast",
"serde",
"slab",
"spin",
"static_assertions",
@ -242,6 +310,19 @@ dependencies = [
"x86_64",
]
[[package]]
name = "postcard"
version = "1.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "170a2601f67cc9dba8edd8c4870b15f71a6a2dc196daec8c83f72b59dff628a8"
dependencies = [
"cobs",
"embedded-io 0.4.0",
"embedded-io 0.6.1",
"heapless",
"serde",
]
[[package]]
name = "proc-macro2"
version = "1.0.92"
@ -275,6 +356,15 @@ version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3a8614ee435691de62bcffcf4a66d91b3594bf1428a5722e79103249a095690"
[[package]]
name = "rustc_version"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92"
dependencies = [
"semver",
]
[[package]]
name = "rustversion"
version = "1.0.18"
@ -293,6 +383,32 @@ version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
[[package]]
name = "semver"
version = "1.0.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b"
[[package]]
name = "serde"
version = "1.0.218"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e8dfc9d19bdbf6d17e22319da49161d5d0108e4188e8b680aef6299eed22df60"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.218"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f09503e191f4e797cb8aac08e9a4a4695c5edf6a2e70e376d961ddd5c969f82b"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.89",
]
[[package]]
name = "slab"
version = "0.4.9"
@ -320,6 +436,12 @@ dependencies = [
"lock_api",
]
[[package]]
name = "stable_deref_trait"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
[[package]]
name = "static_assertions"
version = "1.1.0"
@ -360,7 +482,7 @@ version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0f3702156d45f3b61411186a2555956d57d94f63049bbfaa3fd4856729f7c14a"
dependencies = [
"bitflags 2.6.0",
"bitflags 2.8.0",
"log",
"memchr",
"num-traits",
@ -372,7 +494,7 @@ version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e492212ac378a5e00da953718dafb1340d9fbaf4f27d6f3c5cab03d931d1c049"
dependencies = [
"bitflags 2.6.0",
"bitflags 2.8.0",
"rustversion",
"x86",
]
@ -426,7 +548,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4bc79523af8abf92fb1a970c3e086c5a343f6bcc1a0eb890f575cbb3b45743df"
dependencies = [
"bit_field",
"bitflags 2.6.0",
"bitflags 2.8.0",
"rustversion",
"volatile",
]

View File

@ -29,6 +29,9 @@ humansize = "2.1.3"
cast = "0.3.0"
az = "1.2.1"
unsigned-varint = "0.8.0"
postcard = { version = "1.1.1", features = ["alloc"] }
serde = { version = "1.0.218", features = ["alloc", "derive"], default-features = false }
bitflags = { version = "2.8.0", features = ["serde"] }
[features]
log-rpc = []

View File

@ -1,5 +1,6 @@
use crate::{
bootinfo::BOOTINFO,
ipc_dump::dump_ipc_message,
pit::NUM_INTERRUPTS,
print, println,
tasking::{InvalidPid, IpcMessage, SleepReason},
@ -176,6 +177,7 @@ pub fn send_ipc_to(
)]
TASKING.current_pid().unwrap()
};
dump_ipc_message(from, pid, &buffer[0..len]);
#[cfg(feature = "log-rpc")]
{
#[expect(
@ -201,7 +203,7 @@ pub fn send_ipc_to(
SECOND_PORT.write_u32s(&[
0x3, // SPB type
total_len, // Total block length
len.saturating_cast::<u32>().saturating_add(16), // Packet length
trunc_len.saturating_cast::<u32>().saturating_add(16), // Packet length
]);
SECOND_PORT.write_bytes(&pid.to_ne_bytes());
SECOND_PORT.write_bytes(&from.to_ne_bytes());

567
src/ipc_dump/errno.rs Normal file
View File

@ -0,0 +1,567 @@
use core::fmt::{self, Display, Formatter};
use serde::{Deserialize, Serialize};
#[repr(i32)]
#[derive(Serialize, Deserialize, Debug, Copy, Clone, PartialEq, Eq)]
pub enum Errno {
/// Operation not permitted
EPERM = 1,
/// No such file or directory
ENOENT = 2,
/// No such process
ESRCH = 3,
/// Interrupted system call
EINTR = 4,
/// Input/output error
EIO = 5,
/// No such device or address
ENXIO = 6,
/// Argument list too long
E2BIG = 7,
/// Exec format error
ENOEXEC = 8,
/// Bad file descriptor
EBADF = 9,
/// No child processes
ECHILD = 10,
/// Resource temporarily unavailable
EWOULDBLOCK = 11,
/// Cannot allocate memory
ENOMEM = 12,
/// Permission denied
EACCES = 13,
/// Bad address
EFAULT = 14,
/// Block device required
ENOTBLK = 15,
/// Device or resource busy
EBUSY = 16,
/// File exists
EEXIST = 17,
/// Invalid cross-device link
EXDEV = 18,
/// No such device
ENODEV = 19,
/// Not a directory
ENOTDIR = 20,
/// Is a directory
EISDIR = 21,
/// Invalid argument
EINVAL = 22,
/// Too many open files in system
ENFILE = 23,
/// Too many open files
EMFILE = 24,
/// Inappropriate ioctl for device
ENOTTY = 25,
/// Text file busy
ETXTBSY = 26,
/// File too large
EFBIG = 27,
/// No space left on device
ENOSPC = 28,
/// Illegal seek
ESPIPE = 29,
/// Read-only file system
EROFS = 30,
/// Too many links
EMLINK = 31,
/// Broken pipe
EPIPE = 32,
/// Numerical argument out of domain
EDOM = 33,
/// Numerical result out of range
ERANGE = 34,
/// Resource deadlock avoided
EDEADLK = 35,
/// File name too long
ENAMETOOLONG = 36,
/// No locks available
ENOLCK = 37,
/// Function not implemented
ENOSYS = 38,
/// Directory not empty
ENOTEMPTY = 39,
/// Too many levels of symbolic links
ELOOP = 40,
/// No message of desired type
ENOMSG = 42,
/// Identifier removed
EIDRM = 43,
/// Channel number out of range
ECHRNG = 44,
/// Level 2 not synchronized
EL2NSYNC = 45,
/// Level 3 halted
EL3HLT = 46,
/// Level 3 reset
EL3RST = 47,
/// Link number out of range
ELNRNG = 48,
/// Protocol driver not attached
EUNATCH = 49,
/// No CSI structure available
ENOCSI = 50,
/// Level 2 halted
EL2HLT = 51,
/// Invalid exchange
EBADE = 52,
/// Invalid request descriptor
EBADR = 53,
/// Exchange full
EXFULL = 54,
/// No anode
ENOANO = 55,
/// Invalid request code
EBADRQC = 56,
/// Invalid slot
EBADSLT = 57,
/// Bad font file format
EBFONT = 59,
/// Device not a stream
ENOSTR = 60,
/// No data available
ENODATA = 61,
/// Timer expired
ETIME = 62,
/// Out of streams resources
ENOSR = 63,
/// Machine is not on the network
ENONET = 64,
/// Package not installed
ENOPKG = 65,
/// Object is remote
EREMOTE = 66,
/// Link has been severed
ENOLINK = 67,
/// Advertise error
EADV = 68,
/// Srmount error
ESRMNT = 69,
/// Communication error on send
ECOMM = 70,
/// Protocol error
EPROTO = 71,
/// Multihop attempted
EMULTIHOP = 72,
/// RFS specific error
EDOTDOT = 73,
/// Bad message
EBADMSG = 74,
/// Value too large for defined data type
EOVERFLOW = 75,
/// Name not unique on network
ENOTUNIQ = 76,
/// File descriptor in bad state
EBADFD = 77,
/// Remote address changed
EREMCHG = 78,
/// Can not access a needed shared library
ELIBACC = 79,
/// Accessing a corrupted shared library
ELIBBAD = 80,
/// .lib section in a.out corrupted
ELIBSCN = 81,
/// Attempting to link in too many shared libraries
ELIBMAX = 82,
/// Cannot exec a shared library directly
ELIBEXEC = 83,
/// Invalid or incomplete multibyte or wide character
EILSEQ = 84,
/// Interrupted system call should be restarted
ERESTART = 85,
/// Streams pipe error
ESTRPIPE = 86,
/// Too many users
EUSERS = 87,
/// Socket operation on non-socket
ENOTSOCK = 88,
/// Destination address required
EDESTADDRREQ = 89,
/// Message too long
EMSGSIZE = 90,
/// Protocol wrong type for socket
EPROTOTYPE = 91,
/// Protocol not available
ENOPROTOOPT = 92,
/// Protocol not supported
EPROTONOSUPPORT = 93,
/// Socket type not supported
ESOCKTNOSUPPORT = 94,
/// Operation not supported
ENOTSUP = 95,
/// Protocol family not supported
EPFNOSUPPORT = 96,
/// Address family not supported by protocol
EAFNOSUPPORT = 97,
/// Address already in use
EADDRINUSE = 98,
/// Cannot assign requested address
EADDRNOTAVAIL = 99,
/// Network is down
ENETDOWN = 100,
/// Network is unreachable
ENETUNREACH = 101,
/// Network dropped connection on reset
ENETRESET = 102,
/// Software caused connection abort
ECONNABORTED = 103,
/// Connection reset by peer
ECONNRESET = 104,
/// No buffer space available
ENOBUFS = 105,
/// Transport endpoint is already connected
EISCONN = 106,
/// Transport endpoint is not connected
ENOTCONN = 107,
/// Cannot send after transport endpoint shutdown
ESHUTDOWN = 108,
/// Too many references: cannot splice
ETOOMANYREFS = 109,
/// Connection timed out
ETIMEDOUT = 110,
/// Connection refused
ECONNREFUSED = 111,
/// Host is down
EHOSTDOWN = 112,
/// No route to host
EHOSTUNREACH = 113,
/// Operation already in progress
EALREADY = 114,
/// Operation now in progress
EINPROGRESS = 115,
/// Stale file handle
ESTALE = 116,
/// Structure needs cleaning
EUCLEAN = 117,
/// Not a XENIX named type file
ENOTNAM = 118,
/// No XENIX semaphores available
ENAVAIL = 119,
/// Is a named type file
EISNAM = 120,
/// Remote I/O error
EREMOTEIO = 121,
/// Disk quota exceeded
EDQUOT = 122,
/// No medium found
ENOMEDIUM = 123,
/// Wrong medium type
EMEDIUMTYPE = 124,
/// Operation canceled
ECANCELED = 125,
/// Required key not available
ENOKEY = 126,
/// Key has expired
EKEYEXPIRED = 127,
/// Key has been revoked
EKEYREVOKED = 128,
/// Key was rejected by service
EKEYREJECTED = 129,
/// Owner died
EOWNERDEAD = 130,
/// State not recoverable
ENOTRECOVERABLE = 131,
/// Operation not possible due to RF-kill
ERFKILL = 132,
/// Memory page has hardware error
EHWPOISON = 133,
/// Resource temporarily unavailable
EAGAIN = 134,
/// Unexpected EOF
EEOF = 135,
/// Invalid data
EINVALDAT = 136,
/// Write zero
EWRZERO = 137,
}
impl TryFrom<i32> for Errno {
type Error = i32;
fn try_from(value: i32) -> Result<Self, Self::Error> {
use Errno::*;
match value {
1 => Ok(EPERM),
2 => Ok(ENOENT),
3 => Ok(ESRCH),
4 => Ok(EINTR),
5 => Ok(EIO),
6 => Ok(ENXIO),
7 => Ok(E2BIG),
8 => Ok(ENOEXEC),
9 => Ok(EBADF),
10 => Ok(ECHILD),
11 => Ok(EWOULDBLOCK),
12 => Ok(ENOMEM),
13 => Ok(EACCES),
14 => Ok(EFAULT),
15 => Ok(ENOTBLK),
16 => Ok(EBUSY),
17 => Ok(EEXIST),
18 => Ok(EXDEV),
19 => Ok(ENODEV),
20 => Ok(ENOTDIR),
21 => Ok(EISDIR),
22 => Ok(EINVAL),
23 => Ok(ENFILE),
24 => Ok(EMFILE),
25 => Ok(ENOTTY),
26 => Ok(ETXTBSY),
27 => Ok(EFBIG),
28 => Ok(ENOSPC),
29 => Ok(ESPIPE),
30 => Ok(EROFS),
31 => Ok(EMLINK),
32 => Ok(EPIPE),
33 => Ok(EDOM),
34 => Ok(ERANGE),
35 => Ok(EDEADLK),
36 => Ok(ENAMETOOLONG),
37 => Ok(ENOLCK),
38 => Ok(ENOSYS),
39 => Ok(ENOTEMPTY),
40 => Ok(ELOOP),
42 => Ok(ENOMSG),
43 => Ok(EIDRM),
44 => Ok(ECHRNG),
45 => Ok(EL2NSYNC),
46 => Ok(EL3HLT),
47 => Ok(EL3RST),
48 => Ok(ELNRNG),
49 => Ok(EUNATCH),
50 => Ok(ENOCSI),
51 => Ok(EL2HLT),
52 => Ok(EBADE),
53 => Ok(EBADR),
54 => Ok(EXFULL),
55 => Ok(ENOANO),
56 => Ok(EBADRQC),
57 => Ok(EBADSLT),
59 => Ok(EBFONT),
60 => Ok(ENOSTR),
61 => Ok(ENODATA),
62 => Ok(ETIME),
63 => Ok(ENOSR),
64 => Ok(ENONET),
65 => Ok(ENOPKG),
66 => Ok(EREMOTE),
67 => Ok(ENOLINK),
68 => Ok(EADV),
69 => Ok(ESRMNT),
70 => Ok(ECOMM),
71 => Ok(EPROTO),
72 => Ok(EMULTIHOP),
73 => Ok(EDOTDOT),
74 => Ok(EBADMSG),
75 => Ok(EOVERFLOW),
76 => Ok(ENOTUNIQ),
77 => Ok(EBADFD),
78 => Ok(EREMCHG),
79 => Ok(ELIBACC),
80 => Ok(ELIBBAD),
81 => Ok(ELIBSCN),
82 => Ok(ELIBMAX),
83 => Ok(ELIBEXEC),
84 => Ok(EILSEQ),
85 => Ok(ERESTART),
86 => Ok(ESTRPIPE),
87 => Ok(EUSERS),
88 => Ok(ENOTSOCK),
89 => Ok(EDESTADDRREQ),
90 => Ok(EMSGSIZE),
91 => Ok(EPROTOTYPE),
92 => Ok(ENOPROTOOPT),
93 => Ok(EPROTONOSUPPORT),
94 => Ok(ESOCKTNOSUPPORT),
95 => Ok(ENOTSUP),
96 => Ok(EPFNOSUPPORT),
97 => Ok(EAFNOSUPPORT),
98 => Ok(EADDRINUSE),
99 => Ok(EADDRNOTAVAIL),
100 => Ok(ENETDOWN),
101 => Ok(ENETUNREACH),
102 => Ok(ENETRESET),
103 => Ok(ECONNABORTED),
104 => Ok(ECONNRESET),
105 => Ok(ENOBUFS),
106 => Ok(EISCONN),
107 => Ok(ENOTCONN),
108 => Ok(ESHUTDOWN),
109 => Ok(ETOOMANYREFS),
110 => Ok(ETIMEDOUT),
111 => Ok(ECONNREFUSED),
112 => Ok(EHOSTDOWN),
113 => Ok(EHOSTUNREACH),
114 => Ok(EALREADY),
115 => Ok(EINPROGRESS),
116 => Ok(ESTALE),
117 => Ok(EUCLEAN),
118 => Ok(ENOTNAM),
119 => Ok(ENAVAIL),
120 => Ok(EISNAM),
121 => Ok(EREMOTEIO),
122 => Ok(EDQUOT),
123 => Ok(ENOMEDIUM),
124 => Ok(EMEDIUMTYPE),
125 => Ok(ECANCELED),
126 => Ok(ENOKEY),
127 => Ok(EKEYEXPIRED),
128 => Ok(EKEYREVOKED),
129 => Ok(EKEYREJECTED),
130 => Ok(EOWNERDEAD),
131 => Ok(ENOTRECOVERABLE),
132 => Ok(ERFKILL),
133 => Ok(EHWPOISON),
134 => Ok(EAGAIN),
135 => Ok(EEOF),
136 => Ok(EINVALDAT),
137 => Ok(EWRZERO),
x => Err(x),
}
}
}
impl Display for Errno {
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
use Errno::*;
let errno_name = match self {
EPERM => "EPERM",
ENOENT => "ENOENT",
ESRCH => "ESRCH",
EINTR => "EINTR",
EIO => "EIO",
ENXIO => "ENXIO",
E2BIG => "E2BIG",
ENOEXEC => "ENOEXEC",
EBADF => "EBADF",
ECHILD => "ECHILD",
EAGAIN => "EAGAIN",
EWOULDBLOCK => "EWOULDBLOCK",
ENOMEM => "ENOMEM",
EACCES => "EACCES",
EFAULT => "EFAULT",
ENOTBLK => "ENOTBLK",
EBUSY => "EBUSY",
EEXIST => "EEXIST",
EXDEV => "EXDEV",
ENODEV => "ENODEV",
ENOTDIR => "ENOTDIR",
EISDIR => "EISDIR",
EINVAL => "EINVAL",
ENFILE => "ENFILE",
EMFILE => "EMFILE",
ENOTTY => "ENOTTY",
ETXTBSY => "ETXTBSY",
EFBIG => "EFBIG",
ENOSPC => "ENOSPC",
ESPIPE => "ESPIPE",
EROFS => "EROFS",
EMLINK => "EMLINK",
EPIPE => "EPIPE",
EDOM => "EDOM",
ERANGE => "ERANGE",
EDEADLK => "EDEADLK",
ENAMETOOLONG => "ENAMETOOLONG",
ENOLCK => "ENOLCK",
ENOSYS => "ENOSYS",
ENOTEMPTY => "ENOTEMPTY",
ELOOP => "ELOOP",
ENOMSG => "ENOMSG",
EIDRM => "EIDRM",
ECHRNG => "ECHRNG",
EL2NSYNC => "EL2NSYNC",
EL3HLT => "EL3HLT",
EL3RST => "EL3RST",
ELNRNG => "ELNRNG",
EUNATCH => "EUNATCH",
ENOCSI => "ENOCSI",
EL2HLT => "EL2HLT",
EBADE => "EBADE",
EBADR => "EBADR",
EXFULL => "EXFULL",
ENOANO => "ENOANO",
EBADRQC => "EBADRQC",
EBADSLT => "EBADSLT",
EBFONT => "EBFONT",
ENOSTR => "ENOSTR",
ENODATA => "ENODATA",
ETIME => "ETIME",
ENOSR => "ENOSR",
ENONET => "ENONET",
ENOPKG => "ENOPKG",
EREMOTE => "EREMOTE",
ENOLINK => "ENOLINK",
EADV => "EADV",
ESRMNT => "ESRMNT",
ECOMM => "ECOMM",
EPROTO => "EPROTO",
EMULTIHOP => "EMULTIHOP",
EDOTDOT => "EDOTDOT",
EBADMSG => "EBADMSG",
EOVERFLOW => "EOVERFLOW",
ENOTUNIQ => "ENOTUNIQ",
EBADFD => "EBADFD",
EREMCHG => "EREMCHG",
ELIBACC => "ELIBACC",
ELIBBAD => "ELIBBAD",
ELIBSCN => "ELIBSCN",
ELIBMAX => "ELIBMAX",
ELIBEXEC => "ELIBEXEC",
EILSEQ => "EILSEQ",
ERESTART => "ERESTART",
ESTRPIPE => "ESTRPIPE",
EUSERS => "EUSERS",
ENOTSOCK => "ENOTSOCK",
EDESTADDRREQ => "EDESTADDRREQ",
EMSGSIZE => "EMSGSIZE",
EPROTOTYPE => "EPROTOTYPE",
ENOPROTOOPT => "ENOPROTOOPT",
EPROTONOSUPPORT => "EPROTONOSUPPORT",
ESOCKTNOSUPPORT => "ESOCKTNOSUPPORT",
ENOTSUP => "ENOTSUP",
EPFNOSUPPORT => "EPFNOSUPPORT",
EAFNOSUPPORT => "EAFNOSUPPORT",
EADDRINUSE => "EADDRINUSE",
EADDRNOTAVAIL => "EADDRNOTAVAIL",
ENETDOWN => "ENETDOWN",
ENETUNREACH => "ENETUNREACH",
ENETRESET => "ENETRESET",
ECONNABORTED => "ECONNABORTED",
ECONNRESET => "ECONNRESET",
ENOBUFS => "ENOBUFS",
EISCONN => "EISCONN",
ENOTCONN => "ENOTCONN",
ESHUTDOWN => "ESHUTDOWN",
ETOOMANYREFS => "ETOOMANYREFS",
ETIMEDOUT => "ETIMEDOUT",
ECONNREFUSED => "ECONNREFUSED",
EHOSTDOWN => "EHOSTDOWN",
EHOSTUNREACH => "EHOSTUNREACH",
EALREADY => "EALREADY",
EINPROGRESS => "EINPROGRESS",
ESTALE => "ESTALE",
EUCLEAN => "EUCLEAN",
ENOTNAM => "ENOTNAM",
ENAVAIL => "ENAVAIL",
EISNAM => "EISNAM",
EREMOTEIO => "EREMOTEIO",
EDQUOT => "EDQUOT",
ENOMEDIUM => "ENOMEDIUM",
EMEDIUMTYPE => "EMEDIUMTYPE",
ECANCELED => "ECANCELED",
ENOKEY => "ENOKEY",
EKEYEXPIRED => "EKEYEXPIRED",
EKEYREVOKED => "EKEYREVOKED",
EKEYREJECTED => "EKEYREJECTED",
EOWNERDEAD => "EOWNERDEAD",
ENOTRECOVERABLE => "ENOTRECOVERABLE",
ERFKILL => "ERFKILL",
EHWPOISON => "EHWPOISON",
EEOF => "EEOF",
EINVALDAT => "EINVALDAT",
EWRZERO => "EWRZERO",
};
f.write_str(errno_name)
}
}

195
src/ipc_dump/file_rpc.rs Normal file
View File

@ -0,0 +1,195 @@
use core::fmt::Display;
use alloc::vec;
use alloc::vec::Vec;
use bitflags::bitflags;
use serde::{Deserialize, Serialize};
use super::{
errno::Errno,
message::DissectedMessage,
rpc_header::{RpcHeader, RpcMessageType},
};
#[derive(Deserialize, Serialize, Clone, Copy, Debug)]
pub enum SeekFrom {
Start(u64),
End(i64),
Current(i64),
}
bitflags! {
#[derive(Serialize, Deserialize, Clone, Copy, Debug)]
pub struct PollEvents: u16 {
const POLLIN = 1<<0 | 1<<1;
const POLLRDNORM = 1<<0;
const POLLRDBAND = 1<<1;
const POLLPRI = 1<<2;
const POLLOUT = 1<<3;
const POLLWRNORM = 1<<3;
const POLLWRBAND = 1<<4;
const POLLERR = 1<<5;
const POLLHUP = 1<<6;
const POLLNVAL = 1<<7;
}
}
pub enum FileRpcCall {
Read { fd: u64, len: usize },
Write { fd: u64 },
Close { fd: u64 },
Size { fd: u64 },
Dup { fd: u64 },
RegisterPoll { fd: u64, events: PollEvents },
Poll { poll_id: u64 },
CancelPoll { poll_id: u64 },
Seek { fd: u64, pos: SeekFrom },
Invalid,
}
pub enum FileRpcReturn {
Read(Result<(), Errno>),
Write(Result<(), Errno>),
Close(Result<(), Errno>),
Size(Result<u64, Errno>),
Dup(Result<u64, Errno>),
RegisterPoll(u64),
Poll(PollEvents),
CancelPoll,
Seek(Result<u64, Errno>),
Invalid,
}
pub enum FileRpcMessage {
Call(FileRpcCall),
Return(FileRpcReturn),
}
impl FileRpcMessage {
pub fn dissect(buffer: &[u8], message: &DissectedMessage<RpcHeader>) -> (Self, Vec<u8>) {
let rpc_header = message.get_l1();
match rpc_header.typ {
RpcMessageType::Call => {
let mut rem_data = vec![];
let call = match rpc_header.func {
0 => {
let (fd, len) = postcard::from_bytes(buffer).unwrap();
FileRpcCall::Read { fd, len }
}
1 => {
let (fd, data) = postcard::from_bytes(buffer).unwrap();
rem_data = data;
FileRpcCall::Write { fd }
}
2 => {
let fd = postcard::from_bytes(buffer).unwrap();
FileRpcCall::Close { fd }
}
3 => {
let fd = postcard::from_bytes(buffer).unwrap();
FileRpcCall::Size { fd }
}
4 => {
let fd = postcard::from_bytes(buffer).unwrap();
FileRpcCall::Dup { fd }
}
5 => {
let (fd, events) = postcard::from_bytes(buffer).unwrap();
FileRpcCall::RegisterPoll { fd, events }
}
6 => {
let poll_id = postcard::from_bytes(buffer).unwrap();
FileRpcCall::Poll { poll_id }
}
7 => {
let poll_id = postcard::from_bytes(buffer).unwrap();
FileRpcCall::CancelPoll { poll_id }
}
8 => {
let (fd, pos) = postcard::from_bytes(buffer).unwrap();
FileRpcCall::Seek { fd, pos }
}
_ => {
rem_data = buffer.to_vec();
FileRpcCall::Invalid
}
};
(Self::Call(call), rem_data)
}
RpcMessageType::Return => {
let mut rem_data = vec![];
let call = match rpc_header.func {
0 => {
let ret = postcard::from_bytes(buffer).unwrap();
match ret {
Ok(data) => {
rem_data = data;
FileRpcReturn::Read(Ok(()))
}
Err(e) => FileRpcReturn::Read(Err(e)),
}
}
1 => FileRpcReturn::Write(postcard::from_bytes(buffer).unwrap()),
2 => FileRpcReturn::Close(postcard::from_bytes(buffer).unwrap()),
3 => FileRpcReturn::Size(postcard::from_bytes(buffer).unwrap()),
4 => FileRpcReturn::Dup(postcard::from_bytes(buffer).unwrap()),
5 => FileRpcReturn::RegisterPoll(postcard::from_bytes(buffer).unwrap()),
6 => FileRpcReturn::Poll(postcard::from_bytes(buffer).unwrap()),
7 => FileRpcReturn::CancelPoll,
8 => FileRpcReturn::Seek(postcard::from_bytes(buffer).unwrap()),
_ => {
rem_data = buffer.to_vec();
FileRpcReturn::Invalid
}
};
(Self::Return(call), rem_data)
}
}
}
}
impl Display for FileRpcMessage {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self {
Self::Call(call) => match call {
FileRpcCall::Read { fd, len } => {
f.write_fmt(format_args!("Read {len:#x} bytes from FD {fd:#x}"))?;
}
FileRpcCall::Write { fd } => f.write_fmt(format_args!("Write to FD {fd:#x}"))?,
FileRpcCall::Close { fd } => f.write_fmt(format_args!("Close FD {fd:#x}"))?,
FileRpcCall::Size { fd } => {
f.write_fmt(format_args!("Get size of FD {fd:#x}"))?;
}
FileRpcCall::Dup { fd } => f.write_fmt(format_args!("Duplicate FD {fd:#x}"))?,
FileRpcCall::RegisterPoll { fd, events } => f.write_fmt(format_args!(
"Register a poll for FD {fd:#x} for events {events:?}"
))?,
FileRpcCall::Poll { poll_id } => {
f.write_fmt(format_args!("Poll on poll ID {poll_id}"))?;
}
FileRpcCall::CancelPoll { poll_id } => {
f.write_fmt(format_args!("Cancel poll with ID {poll_id}"))?;
}
FileRpcCall::Seek { fd, pos } => {
f.write_fmt(format_args!("Seek FD {fd:#x} to position {pos:?}"))?;
}
FileRpcCall::Invalid => f.write_fmt(format_args!("Invalid call!"))?,
},
Self::Return(ret) => match ret {
FileRpcReturn::Read(ret) => f.write_fmt(format_args!("Read return {ret:?}"))?,
FileRpcReturn::Write(ret) => f.write_fmt(format_args!("Write return {ret:?}"))?,
FileRpcReturn::Close(ret) => f.write_fmt(format_args!("Close return {ret:?}"))?,
FileRpcReturn::Size(ret) => f.write_fmt(format_args!("Size return {ret:?}"))?,
FileRpcReturn::Dup(ret) => f.write_fmt(format_args!("Duplicate return {ret:?}"))?,
FileRpcReturn::RegisterPoll(ret) => {
f.write_fmt(format_args!("Poll register return {ret}"))?;
}
FileRpcReturn::Poll(ret) => f.write_fmt(format_args!("Poll return {ret:?}"))?,
FileRpcReturn::CancelPoll => f.write_fmt(format_args!("Cancel poll return"))?,
FileRpcReturn::Seek(ret) => f.write_fmt(format_args!("Seek return {ret:?}"))?,
FileRpcReturn::Invalid => f.write_fmt(format_args!("Invalid return!"))?,
},
};
Ok(())
}
}

68
src/ipc_dump/hexdump.rs Normal file
View File

@ -0,0 +1,68 @@
use alloc::fmt::Display;
use cast::{u32, usize};
pub struct HexdumpLayer<'a> {
data: &'a [u8],
max_len: usize,
}
impl<'a> HexdumpLayer<'a> {
pub fn new(data: &'a [u8], max_len: usize) -> Self {
Self { data, max_len }
}
}
impl Display for HexdumpLayer<'_> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
let hexdump_len = usize::min(self.data.len(), self.max_len);
let data = &self.data[0..hexdump_len];
let num_groups = data.len().div_ceil(16);
let offset_char_width = if num_groups == 0 {
1
} else if num_groups == 1 {
2
} else {
usize(num_groups.next_power_of_two().ilog2().div_ceil(4) + 1)
};
let mut chunk_iter = data.chunks_exact(16);
for (group_num, chunk) in (&mut chunk_iter).enumerate() {
if group_num == 0 {
f.write_fmt(format_args!("{:01$}:", 0, offset_char_width))?;
} else {
f.write_fmt(format_args!("\n{:01$}0:", group_num, offset_char_width - 1))?;
}
for &byte in chunk {
f.write_fmt(format_args!(" {byte:02x}"))?;
}
f.write_str(" |")?;
for &byte in chunk {
let ch = char::from_u32(u32(byte)).unwrap_or('.');
let ch = if ch.is_ascii() && !ch.is_ascii_control() { ch } else { '.' };
f.write_fmt(format_args!("{ch}"))?;
}
}
let chunk = chunk_iter.remainder();
if !chunk.is_empty() {
let group_num = num_groups - 1;
if group_num == 0 {
f.write_fmt(format_args!("{:01$}:", 0, offset_char_width))?;
} else {
f.write_fmt(format_args!("\n{:01$}0:", group_num, offset_char_width - 1))?;
}
for &byte in chunk {
f.write_fmt(format_args!(" {byte:02x}"))?;
}
let missing_bytes = 16 - chunk.len();
for _ in 0..missing_bytes {
f.write_str(" ")?;
}
f.write_str(" |")?;
for &byte in chunk {
let ch = char::from_u32(u32(byte)).unwrap_or('.');
let ch = if ch.is_ascii() && !ch.is_ascii_control() { ch } else { '.' };
f.write_fmt(format_args!("{ch}"))?;
}
}
Ok(())
}
}

View File

@ -0,0 +1,23 @@
use cast::usize;
use core::fmt::Display;
pub struct InterruptProto {
irq: u8,
}
impl InterruptProto {
pub fn dissect(buffer: &[u8]) -> Self {
Self { irq: buffer[0] }
}
}
static IRQ_NAMES: [&str; 16] = [
"Timer", "Keyboard", "Cascade", "COM2", "COM1", "LPT2", "Floppy", "LPT1", "RTC", "Free1",
"Free2", "Free3", "Mouse", "FPU", "ATA1", "ATA2",
];
impl Display for InterruptProto {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
let irq_name = *IRQ_NAMES.get(usize(self.irq)).unwrap_or(&"Invalid");
f.write_fmt(format_args!("IRQ {} ({})", self.irq, irq_name))
}
}

190
src/ipc_dump/message.rs Normal file
View File

@ -0,0 +1,190 @@
use alloc::fmt::{self, Display};
use alloc::string::{String, ToString};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum IpcFrom {
Kernel,
Process(usize),
}
impl IpcFrom {
pub fn as_pid(self) -> usize {
match self {
Self::Kernel => usize::MAX,
Self::Process(pid) => pid,
}
}
}
impl Display for IpcFrom {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Kernel => f.write_str("Kernel"),
Self::Process(pid) => f.write_fmt(format_args!("{pid}")),
}
}
}
pub trait MessageHeader: Display {}
impl<T: Display> MessageHeader for T {}
pub struct DissectedMessage<L1 = NoHeader, L2 = NoHeader, L3 = NoHeader> {
pub ipc_from: IpcFrom,
pub ipc_dest: usize,
pub ipc_proto: u16,
l1: L1,
l2: L2,
l3: L3,
}
pub struct NoHeader;
impl DissectedMessage<NoHeader, NoHeader, NoHeader> {
pub fn new(ipc_from: IpcFrom, ipc_dest: usize, ipc_proto: u16) -> Self {
Self { ipc_from, ipc_dest, ipc_proto, l1: NoHeader, l2: NoHeader, l3: NoHeader }
}
pub fn set_l1<T: MessageHeader>(self, l1: T) -> DissectedMessage<T, NoHeader, NoHeader> {
DissectedMessage {
ipc_from: self.ipc_from,
ipc_dest: self.ipc_dest,
ipc_proto: self.ipc_proto,
l1,
l2: NoHeader,
l3: NoHeader,
}
}
}
impl<L1: MessageHeader> DissectedMessage<L1, NoHeader, NoHeader> {
pub fn get_l1(&self) -> &L1 {
&self.l1
}
pub fn set_l2<T: MessageHeader>(self, l2: T) -> DissectedMessage<L1, T, NoHeader> {
DissectedMessage {
ipc_from: self.ipc_from,
ipc_dest: self.ipc_dest,
ipc_proto: self.ipc_proto,
l1: self.l1,
l2,
l3: NoHeader,
}
}
}
impl<L1: MessageHeader, L2: MessageHeader> DissectedMessage<L1, L2, NoHeader> {
pub fn get_l2(&self) -> &L2 {
&self.l2
}
pub fn set_l3<T: MessageHeader>(self, l3: T) -> DissectedMessage<L1, L2, T> {
DissectedMessage {
ipc_from: self.ipc_from,
ipc_dest: self.ipc_dest,
ipc_proto: self.ipc_proto,
l1: self.l1,
l2: self.l2,
l3,
}
}
}
impl<L1: MessageHeader, L2: MessageHeader, L3: MessageHeader> DissectedMessage<L1, L2, L3> {
pub fn get_l3(&self) -> &L3 {
&self.l3
}
}
impl<L1, L2, L3> DissectedMessage<L1, L2, L3> {
fn fmt_ipc_header(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_fmt(format_args!(
"IPC: {} sending to {}, protocol {}",
self.ipc_from, self.ipc_dest, self.ipc_proto,
))
}
}
impl<L1: MessageHeader, L2, L3> DissectedMessage<L1, L2, L3> {
fn fmt_l1(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let l1_raw = self.l1.to_string();
let l1_indented =
l1_raw.split('\n').map(|line| " ".to_string() + line + "\n").collect::<String>();
f.write_str(l1_indented.strip_suffix("\n").unwrap())
}
}
impl<L1: MessageHeader, L2: MessageHeader, L3> DissectedMessage<L1, L2, L3> {
fn fmt_l2(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let l2_raw = self.l2.to_string();
let l2_indented =
l2_raw.split('\n').map(|line| " ".to_string() + line + "\n").collect::<String>();
f.write_str(l2_indented.strip_suffix("\n").unwrap())
}
}
impl<L1: MessageHeader, L2: MessageHeader, L3: MessageHeader> DissectedMessage<L1, L2, L3> {
fn fmt_l3(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let l3_raw = self.l3.to_string();
let l3_indented = l3_raw
.split('\n')
.map(|line| " ".to_string() + line + "\n")
.collect::<String>();
f.write_str(l3_indented.strip_suffix("\n").unwrap())
}
}
impl Display for DissectedMessage<NoHeader, NoHeader, NoHeader> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("-----------------------------------------\n")?;
self.fmt_ipc_header(f)?;
f.write_str("\n")?;
f.write_str("-----------------------------------------\n")?;
Ok(())
}
}
impl<L1: MessageHeader> Display for DissectedMessage<L1, NoHeader, NoHeader> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("-----------------------------------------\n")?;
self.fmt_ipc_header(f)?;
f.write_str("\n")?;
self.fmt_l1(f)?;
f.write_str("\n")?;
f.write_str("-----------------------------------------\n")?;
Ok(())
}
}
impl<L1: MessageHeader, L2: MessageHeader> Display for DissectedMessage<L1, L2, NoHeader> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("-----------------------------------------\n")?;
self.fmt_ipc_header(f)?;
f.write_str("\n")?;
self.fmt_l1(f)?;
f.write_str("\n")?;
self.fmt_l2(f)?;
f.write_str("\n")?;
f.write_str("-----------------------------------------\n")?;
Ok(())
}
}
impl<L1: MessageHeader, L2: MessageHeader, L3: MessageHeader> Display
for DissectedMessage<L1, L2, L3>
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("-----------------------------------------\n")?;
self.fmt_ipc_header(f)?;
f.write_str("\n")?;
self.fmt_l1(f)?;
f.write_str("\n")?;
self.fmt_l2(f)?;
f.write_str("\n")?;
self.fmt_l3(f)?;
f.write_str("\n")?;
f.write_str("-----------------------------------------\n")?;
Ok(())
}
}

66
src/ipc_dump/mod.rs Normal file
View File

@ -0,0 +1,66 @@
#![allow(clippy::arithmetic_side_effects, reason = "temp for debugging")]
#![allow(clippy::indexing_slicing, reason = "temp for debugging")]
#![allow(clippy::unwrap_used, reason = "temp for debugging")]
mod errno;
mod file_rpc;
mod hexdump;
mod interrupt_proto;
mod message;
mod proc_man_rpc;
mod rpc_header;
mod syslog_ipc;
mod syslog_msg;
mod syslog_rpc;
use file_rpc::FileRpcMessage;
use hexdump::HexdumpLayer;
use interrupt_proto::InterruptProto;
use message::{DissectedMessage, IpcFrom};
use proc_man_rpc::ProcManRpcMessage;
use rpc_header::RpcHeader;
use syslog_ipc::SyslogIpc;
use syslog_rpc::SyslogRpcMessage;
use crate::println;
pub fn dump_ipc_message(from: usize, dest: usize, buffer: &[u8]) {
let ipc_proto = u16::from_ne_bytes([buffer[0], buffer[1]]);
let buffer = &buffer[2..];
let from = if from == usize::MAX { IpcFrom::Kernel } else { IpcFrom::Process(from) };
let msg = DissectedMessage::new(from, dest, ipc_proto);
if ipc_proto == 0 {
let (rpc_header, buffer) = RpcHeader::dissect(buffer, &msg);
let msg = msg.set_l1(rpc_header);
if msg.get_l1().proto == 1 {
let (file_rpc, rem_data) = FileRpcMessage::dissect(buffer, &msg);
let msg = msg.set_l2(file_rpc);
if rem_data.is_empty() {
println!("{msg}");
} else {
let msg = msg.set_l3(HexdumpLayer::new(&rem_data, 128));
println!("{msg}");
}
} else if msg.get_l1().proto == 5 {
let syslog_rpc = SyslogRpcMessage::dissect(buffer, &msg);
let msg = msg.set_l2(syslog_rpc);
println!("{msg}");
} else if msg.get_l1().proto == 8 {
let syslog_rpc = ProcManRpcMessage::dissect(buffer, &msg);
let msg = msg.set_l2(syslog_rpc);
println!("{msg}");
} else {
let msg = msg.set_l2(HexdumpLayer::new(buffer, 128));
println!("{msg}");
}
} else if ipc_proto == 1 {
let msg = msg.set_l1(SyslogIpc::dissect(buffer));
println!("{msg}");
} else if ipc_proto == 2 {
let msg = msg.set_l1(InterruptProto::dissect(buffer));
println!("{msg}");
} else {
let msg = msg.set_l1(HexdumpLayer::new(buffer, 128));
println!("{msg}");
}
}

View File

@ -0,0 +1,207 @@
use core::fmt::{Debug, Display};
use alloc::string::String;
use alloc::vec::Vec;
use serde::{Deserialize, Serialize};
use super::{
errno::Errno,
message::DissectedMessage,
rpc_header::{RpcHeader, RpcMessageType},
};
#[derive(Serialize, Deserialize, Debug)]
pub struct WaitResult {
pub pid: u64,
pub exit_code: u8,
}
#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
pub enum ProcessStatus {
Running,
Exited(u8),
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct Process {
pub pid: u64,
pub stdio: [Option<(u64, u64)>; 3],
pub cli_args: Vec<String>,
pub status: ProcessStatus,
pub parent: Option<u64>,
pub children: Vec<u64>,
}
#[derive(Deserialize)]
pub struct OsString {
#[expect(unused, reason = "this is a dummy for deserialization")]
kind: u8,
str: String,
}
impl Debug for OsString {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.write_fmt(format_args!("{:?}", self.str))
}
}
pub enum ProcManRpcCall {
NewProc { pid: u64, parent: Option<u64> },
SetStdio { pid: u64, stdio: [Option<(u64, u64)>; 3] },
GetStdio,
SetCliArgs { pid: u64, args: Vec<OsString> },
GetCliArgs,
Exit { pid: u64, code: u8 },
Wait { pid: u64, block: bool },
GetProcesses,
SetCwd { pid: u64, path: String },
GetCwd,
Invalid,
}
pub enum ProcManRpcReturn {
NewProc(Result<(), Errno>),
SetStdio(Result<(), Errno>),
GetStdio([Option<(u64, u64)>; 3]),
SetCliArgs(Result<(), Errno>),
GetCliArgs(Vec<OsString>),
Wait(Result<WaitResult, Errno>),
GetProcesses(
#[expect(unused, reason = "currently we do not use the full parsed message in output")]
Vec<Process>,
),
SetCwd(Result<(), Errno>),
GetCwd(String),
Invalid,
}
pub enum ProcManRpcMessage {
Call(ProcManRpcCall),
Return(ProcManRpcReturn),
}
impl ProcManRpcMessage {
pub fn dissect(buffer: &[u8], message: &DissectedMessage<RpcHeader>) -> Self {
let rpc_header = message.get_l1();
match rpc_header.typ {
RpcMessageType::Call => {
let call = match rpc_header.func {
0 => {
let (pid, stdio) = postcard::from_bytes(buffer).unwrap();
ProcManRpcCall::SetStdio { pid, stdio }
}
1 => ProcManRpcCall::GetStdio,
2 => {
let (pid, args) = postcard::from_bytes(buffer).unwrap();
ProcManRpcCall::SetCliArgs { pid, args }
}
3 => ProcManRpcCall::GetCliArgs,
4 => {
let (pid, code) = postcard::from_bytes(buffer).unwrap();
ProcManRpcCall::Exit { pid, code }
}
5 => {
let (pid, block) = postcard::from_bytes(buffer).unwrap();
ProcManRpcCall::Wait { pid, block }
}
6 | 7 => {
let (pid, parent) = postcard::from_bytes(buffer).unwrap();
ProcManRpcCall::NewProc { pid, parent }
}
8 => ProcManRpcCall::GetProcesses,
9 => {
let (pid, path) = postcard::from_bytes(buffer).unwrap();
ProcManRpcCall::SetCwd { pid, path }
}
10 => ProcManRpcCall::GetCwd,
_ => ProcManRpcCall::Invalid,
};
Self::Call(call)
}
RpcMessageType::Return => {
let call = match rpc_header.func {
0 => ProcManRpcReturn::SetStdio(postcard::from_bytes(buffer).unwrap()),
1 => ProcManRpcReturn::GetStdio(postcard::from_bytes(buffer).unwrap()),
2 => ProcManRpcReturn::SetCliArgs(postcard::from_bytes(buffer).unwrap()),
3 => ProcManRpcReturn::GetCliArgs(postcard::from_bytes(buffer).unwrap()),
5 => ProcManRpcReturn::Wait(postcard::from_bytes(buffer).unwrap()),
7 => ProcManRpcReturn::NewProc(postcard::from_bytes(buffer).unwrap()),
8 => ProcManRpcReturn::GetProcesses(postcard::from_bytes(buffer).unwrap()),
9 => ProcManRpcReturn::SetCwd(postcard::from_bytes(buffer).unwrap()),
10 => ProcManRpcReturn::GetCwd(postcard::from_bytes(buffer).unwrap()),
_ => ProcManRpcReturn::Invalid,
};
Self::Return(call)
}
}
}
}
impl Display for ProcManRpcMessage {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self {
Self::Call(call) => match call {
ProcManRpcCall::NewProc { pid, parent } => {
if let Some(parent) = parent {
f.write_fmt(format_args!(
"New process with PID {pid} and parent {parent}"
))?;
} else {
f.write_fmt(format_args!("New process with PID {pid} and no parent"))?;
}
}
ProcManRpcCall::SetStdio { pid, stdio } => {
f.write_fmt(format_args!("Set PID {pid}'s stdio to {stdio:?}"))?;
}
ProcManRpcCall::GetStdio => f.write_str("Get stdio")?,
ProcManRpcCall::SetCliArgs { pid, args } => {
f.write_fmt(format_args!("Set PID {pid}'s CLI args to {args:?}"))?;
}
ProcManRpcCall::GetCliArgs => f.write_str("Get CLI args")?,
ProcManRpcCall::Exit { pid, code } => {
f.write_fmt(format_args!("PID {pid} exiting with code {code}"))?;
}
ProcManRpcCall::Wait { pid, block } => {
if *block {
f.write_fmt(format_args!("Wait blocking on PID {pid}"))?;
} else {
f.write_fmt(format_args!("Wait nonblocking on PID {pid}"))?;
}
}
ProcManRpcCall::GetProcesses => f.write_str("Get processes")?,
ProcManRpcCall::SetCwd { pid, path } => {
f.write_fmt(format_args!("Set PID {pid}'s CWD to {path}"))?;
}
ProcManRpcCall::GetCwd => f.write_str("Get CWD")?,
ProcManRpcCall::Invalid => f.write_str("Invalid call!")?,
},
Self::Return(ret) => match ret {
ProcManRpcReturn::NewProc(ret) => {
f.write_fmt(format_args!("New process return {ret:?}"))?;
}
ProcManRpcReturn::SetStdio(ret) => {
f.write_fmt(format_args!("Set stdio return {ret:?}"))?;
}
ProcManRpcReturn::GetStdio(ret) => {
f.write_fmt(format_args!("Get stdio return {ret:?}"))?;
}
ProcManRpcReturn::SetCliArgs(ret) => {
f.write_fmt(format_args!("Set CLI args return {ret:?}"))?;
}
ProcManRpcReturn::GetCliArgs(ret) => {
f.write_fmt(format_args!("Get CLI args return {ret:?}"))?;
}
ProcManRpcReturn::Wait(ret) => f.write_fmt(format_args!("Wait return {ret:?}"))?,
ProcManRpcReturn::GetProcesses(_) => f.write_str("Get processes return")?,
ProcManRpcReturn::SetCwd(ret) => {
f.write_fmt(format_args!("Set CWD return {ret:?}"))?;
}
ProcManRpcReturn::GetCwd(ret) => {
f.write_fmt(format_args!("Get CWD return {ret:?}"))?;
}
ProcManRpcReturn::Invalid => f.write_str("Invalid return!")?,
},
};
Ok(())
}
}

View File

@ -0,0 +1,79 @@
use alloc::fmt::Display;
use hashbrown::HashMap;
use spin::{Lazy, Mutex};
use super::message::DissectedMessage;
static RPC_CALL_MAP: Lazy<Mutex<HashMap<(usize, u64), (u16, u16)>>> =
Lazy::new(|| Mutex::new(HashMap::new()));
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum RpcMessageType {
Call,
Return,
}
pub struct RpcHeader {
pub typ: RpcMessageType,
pub call_id: u64,
pub proto: u16,
pub func: u16,
//from: IpcFrom,
//dest: usize,
}
impl RpcHeader {
pub fn dissect<'a>(buffer: &'a [u8], message: &DissectedMessage) -> (Self, &'a [u8]) {
let typ = match buffer[0] {
0 => RpcMessageType::Call,
1 => RpcMessageType::Return,
_ => panic!(),
};
let call_id = u64::from_ne_bytes(buffer[1..9].try_into().unwrap());
let (proto, func) = if typ == RpcMessageType::Call {
let proto = u16::from_ne_bytes(buffer[9..11].try_into().unwrap());
let func = u16::from_ne_bytes(buffer[11..13].try_into().unwrap());
RPC_CALL_MAP.lock().insert((message.ipc_from.as_pid(), call_id), (proto, func));
(proto, func)
} else if let Some((proto, func)) = RPC_CALL_MAP.lock().remove(&(message.ipc_dest, call_id))
{
(proto, func)
} else {
(u16::MAX, u16::MAX)
};
let slf = Self {
typ,
call_id,
proto,
func,
//from: message.ipc_from,
//dest: message.ipc_dest,
};
(slf, &buffer[13..])
}
}
impl Display for RpcHeader {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self.typ {
RpcMessageType::Call => {
f.write_fmt(format_args!(
"RPC: call w/ID {}, protocol {}, function {}",
self.call_id, self.proto, self.func
))?;
}
RpcMessageType::Return => {
if self.proto == u16::MAX && self.func == u16::MAX {
f.write_fmt(format_args!("RPC: return for call {} (Not seen!)", self.call_id))?;
} else {
f.write_fmt(format_args!(
"RPC: return for call {} (proto {}, func {})",
self.call_id, self.proto, self.func
))?;
}
}
}
Ok(())
}
}

View File

@ -0,0 +1,18 @@
use core::fmt::Display;
use super::syslog_msg::SyslogMessage;
pub struct SyslogIpc {
message: SyslogMessage,
}
impl SyslogIpc {
pub fn dissect(buffer: &[u8]) -> Self {
Self { message: postcard::from_bytes(buffer).unwrap() }
}
}
impl Display for SyslogIpc {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.write_fmt(format_args!("{}", self.message))
}
}

View File

@ -0,0 +1,37 @@
use core::fmt::Display;
use alloc::{string::String, vec::Vec};
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct SyslogMessage {
pub from: String,
pub text: Option<String>,
pub binary: Option<SyslogBinaryMessage>,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct SyslogBinaryMessage {
pub kind: u64,
pub data: Vec<u8>,
}
impl Display for SyslogMessage {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match (&self.text, &self.binary) {
(None, None) => f.write_fmt(format_args!("Message from {}", self.from))?,
(None, Some(binary)) => f.write_fmt(format_args!(
"Message from {}: kind {}, data {:?}",
self.from, binary.kind, binary.data
))?,
(Some(text), None) => {
f.write_fmt(format_args!("Message from {}: {}", self.from, text))?;
}
(Some(text), Some(binary)) => f.write_fmt(format_args!(
"Message from {}: {} (kind {}, data {:?})",
self.from, text, binary.kind, binary.data,
))?,
};
Ok(())
}
}

View File

@ -0,0 +1,89 @@
use core::fmt::Display;
use alloc::string::String;
use alloc::vec::Vec;
use super::{
message::DissectedMessage,
rpc_header::{RpcHeader, RpcMessageType},
syslog_msg::SyslogMessage,
};
pub enum SyslogRpcCall {
SendMessage { message: SyslogMessage },
SubscribeToText,
SubscribeToBinary { message_from: String, kinds: Vec<u64> },
Invalid,
}
pub enum SyslogRpcReturn {
SendMessage(Result<(), ()>),
SubscribeToText,
SubscribeToBinary,
Invalid,
}
pub enum SyslogRpcMessage {
Call(SyslogRpcCall),
Return(SyslogRpcReturn),
}
impl SyslogRpcMessage {
pub fn dissect(buffer: &[u8], message: &DissectedMessage<RpcHeader>) -> Self {
let rpc_header = message.get_l1();
match rpc_header.typ {
RpcMessageType::Call => {
let call = match rpc_header.func {
0 => {
let message = postcard::from_bytes(buffer).unwrap();
SyslogRpcCall::SendMessage { message }
}
1 => SyslogRpcCall::SubscribeToText,
2 => {
let (message_from, kinds) = postcard::from_bytes(buffer).unwrap();
SyslogRpcCall::SubscribeToBinary { message_from, kinds }
}
_ => SyslogRpcCall::Invalid,
};
Self::Call(call)
}
RpcMessageType::Return => {
let call = match rpc_header.func {
0 => SyslogRpcReturn::SendMessage(postcard::from_bytes(buffer).unwrap()),
1 => SyslogRpcReturn::SubscribeToText,
2 => SyslogRpcReturn::SubscribeToBinary,
_ => SyslogRpcReturn::Invalid,
};
Self::Return(call)
}
}
}
}
impl Display for SyslogRpcMessage {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self {
Self::Call(call) => match call {
SyslogRpcCall::SendMessage { message } => {
f.write_fmt(format_args!("{message}"))?;
}
SyslogRpcCall::SubscribeToText => f.write_str("Subscribe to text")?,
SyslogRpcCall::SubscribeToBinary { message_from, kinds } => {
f.write_fmt(format_args!(
"Subscribe to binary from {message_from} with kinds {kinds:?}",
))?;
}
SyslogRpcCall::Invalid => f.write_str("Invalid call!")?,
},
Self::Return(ret) => match ret {
SyslogRpcReturn::SendMessage(ret) => {
f.write_fmt(format_args!("Send message return {ret:?}"))?;
}
SyslogRpcReturn::SubscribeToText => f.write_str("Subscribe to text return")?,
SyslogRpcReturn::SubscribeToBinary => f.write_str("Subscribe to binary return")?,
SyslogRpcReturn::Invalid => f.write_str("Invalid return!")?,
},
};
Ok(())
}
}

View File

@ -74,6 +74,7 @@ extern crate alloc;
mod bootinfo;
mod gdt;
mod interrupts;
mod ipc_dump;
mod kernel_heap;
mod panic_handler;
mod physical_memory;