IPC dissecting initial start
This commit is contained in:
parent
ab0c22ecc9
commit
1c8540d851
132
Cargo.lock
generated
132
Cargo.lock
generated
@ -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",
|
||||
]
|
||||
|
@ -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 = []
|
||||
|
@ -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(
|
||||
@ -199,9 +201,9 @@ pub fn send_ipc_to(
|
||||
)]
|
||||
let total_len = padded_len + 16 + (4 * 4);
|
||||
SECOND_PORT.write_u32s(&[
|
||||
0x3, // SPB type
|
||||
total_len, // Total block length
|
||||
len.saturating_cast::<u32>().saturating_add(16), // Packet length
|
||||
0x3, // SPB type
|
||||
total_len, // Total block 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
567
src/ipc_dump/errno.rs
Normal 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
195
src/ipc_dump/file_rpc.rs
Normal 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
68
src/ipc_dump/hexdump.rs
Normal 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(())
|
||||
}
|
||||
}
|
23
src/ipc_dump/interrupt_proto.rs
Normal file
23
src/ipc_dump/interrupt_proto.rs
Normal 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
190
src/ipc_dump/message.rs
Normal 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
66
src/ipc_dump/mod.rs
Normal 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}");
|
||||
}
|
||||
}
|
207
src/ipc_dump/proc_man_rpc.rs
Normal file
207
src/ipc_dump/proc_man_rpc.rs
Normal 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(())
|
||||
}
|
||||
}
|
79
src/ipc_dump/rpc_header.rs
Normal file
79
src/ipc_dump/rpc_header.rs
Normal 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(())
|
||||
}
|
||||
}
|
18
src/ipc_dump/syslog_ipc.rs
Normal file
18
src/ipc_dump/syslog_ipc.rs
Normal 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))
|
||||
}
|
||||
}
|
37
src/ipc_dump/syslog_msg.rs
Normal file
37
src/ipc_dump/syslog_msg.rs
Normal 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(())
|
||||
}
|
||||
}
|
89
src/ipc_dump/syslog_rpc.rs
Normal file
89
src/ipc_dump/syslog_rpc.rs
Normal 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(())
|
||||
}
|
||||
}
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user