2018-05-15 21:27:23 +08:00
|
|
|
use core::str::Utf8Error;
|
2018-05-15 03:24:14 +08:00
|
|
|
use alloc::{Vec, String};
|
2016-09-27 21:36:55 +08:00
|
|
|
|
2018-05-15 21:27:23 +08:00
|
|
|
use io::{Read, ProtoRead, Write, ProtoWrite, Error as IoError, ReadStringError};
|
2018-05-14 21:33:38 +08:00
|
|
|
|
2018-05-15 21:27:23 +08:00
|
|
|
#[derive(Fail, Debug)]
|
|
|
|
pub enum Error<T> {
|
|
|
|
#[fail(display = "incorrect magic")]
|
|
|
|
WrongMagic,
|
|
|
|
#[fail(display = "unknown packet {:#02x}", _0)]
|
|
|
|
UnknownPacket(u8),
|
|
|
|
#[fail(display = "invalid UTF-8: {}", _0)]
|
|
|
|
Utf8(Utf8Error),
|
|
|
|
#[fail(display = "{}", _0)]
|
|
|
|
Io(#[cause] IoError<T>)
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T> From<IoError<T>> for Error<T> {
|
|
|
|
fn from(value: IoError<T>) -> Error<T> {
|
|
|
|
Error::Io(value)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T> From<ReadStringError<IoError<T>>> for Error<T> {
|
|
|
|
fn from(value: ReadStringError<IoError<T>>) -> Error<T> {
|
|
|
|
match value {
|
|
|
|
ReadStringError::Utf8(err) => Error::Utf8(err),
|
|
|
|
ReadStringError::Other(err) => Error::Io(err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn read_magic<R>(reader: &mut R) -> Result<(), Error<R::ReadError>>
|
|
|
|
where R: Read + ?Sized
|
|
|
|
{
|
|
|
|
const MAGIC: &'static [u8] = b"ARTIQ coredev\n";
|
|
|
|
|
|
|
|
let mut magic: [u8; 14] = [0; 14];
|
|
|
|
reader.read_exact(&mut magic)?;
|
|
|
|
if magic != MAGIC {
|
|
|
|
Err(Error::WrongMagic)
|
|
|
|
} else {
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn read_sync<R>(reader: &mut R) -> Result<(), IoError<R::ReadError>>
|
|
|
|
where R: Read + ?Sized
|
|
|
|
{
|
2016-09-27 21:36:55 +08:00
|
|
|
let mut sync = [0; 4];
|
|
|
|
for i in 0.. {
|
2017-02-27 02:20:46 +08:00
|
|
|
sync[i % 4] = reader.read_u8()?;
|
2016-09-27 21:36:55 +08:00
|
|
|
if sync == [0x5a; 4] { break }
|
|
|
|
}
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
2018-05-15 21:27:23 +08:00
|
|
|
fn write_sync<W>(writer: &mut W) -> Result<(), IoError<W::WriteError>>
|
|
|
|
where W: Write + ?Sized
|
|
|
|
{
|
2016-09-27 21:36:55 +08:00
|
|
|
writer.write_all(&[0x5a; 4])
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
pub enum Request {
|
2017-02-01 06:53:38 +08:00
|
|
|
SystemInfo,
|
2016-09-27 21:36:55 +08:00
|
|
|
|
2016-10-04 13:20:56 +08:00
|
|
|
LoadKernel(Vec<u8>),
|
2016-09-27 21:36:55 +08:00
|
|
|
RunKernel,
|
|
|
|
|
2016-10-07 01:25:43 +08:00
|
|
|
RpcReply { tag: Vec<u8> },
|
2016-10-06 21:42:35 +08:00
|
|
|
RpcException {
|
|
|
|
name: String,
|
|
|
|
message: String,
|
2016-11-22 01:09:58 +08:00
|
|
|
param: [i64; 3],
|
2016-10-06 21:42:35 +08:00
|
|
|
file: String,
|
|
|
|
line: u32,
|
|
|
|
column: u32,
|
|
|
|
function: String,
|
|
|
|
},
|
2016-09-27 21:36:55 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
pub enum Reply<'a> {
|
2017-02-01 06:53:38 +08:00
|
|
|
SystemInfo {
|
|
|
|
ident: &'a str,
|
|
|
|
finished_cleanly: bool
|
|
|
|
},
|
2016-09-27 21:36:55 +08:00
|
|
|
|
|
|
|
LoadCompleted,
|
2017-01-27 20:49:48 +08:00
|
|
|
LoadFailed(&'a str),
|
2016-09-27 21:36:55 +08:00
|
|
|
|
|
|
|
KernelFinished,
|
|
|
|
KernelStartupFailed,
|
2016-10-06 21:42:35 +08:00
|
|
|
KernelException {
|
|
|
|
name: &'a str,
|
|
|
|
message: &'a str,
|
2016-11-22 01:09:58 +08:00
|
|
|
param: [i64; 3],
|
2016-10-06 21:42:35 +08:00
|
|
|
file: &'a str,
|
|
|
|
line: u32,
|
|
|
|
column: u32,
|
|
|
|
function: &'a str,
|
|
|
|
backtrace: &'a [usize]
|
|
|
|
},
|
2016-09-27 21:36:55 +08:00
|
|
|
|
2016-11-01 14:51:44 +08:00
|
|
|
RpcRequest { async: bool },
|
2016-09-27 21:36:55 +08:00
|
|
|
|
|
|
|
ClockFailure,
|
|
|
|
}
|
|
|
|
|
2018-05-16 22:32:49 +08:00
|
|
|
impl Request {
|
|
|
|
pub fn read_from<R>(reader: &mut R) -> Result<Self, Error<R::ReadError>>
|
|
|
|
where R: Read + ?Sized
|
|
|
|
{
|
|
|
|
read_sync(reader)?;
|
|
|
|
Ok(match reader.read_u8()? {
|
|
|
|
3 => Request::SystemInfo,
|
|
|
|
|
|
|
|
5 => Request::LoadKernel(reader.read_bytes()?),
|
|
|
|
6 => Request::RunKernel,
|
|
|
|
|
|
|
|
7 => Request::RpcReply {
|
|
|
|
tag: reader.read_bytes()?
|
|
|
|
},
|
|
|
|
8 => Request::RpcException {
|
|
|
|
name: reader.read_string()?,
|
|
|
|
message: reader.read_string()?,
|
|
|
|
param: [reader.read_u64()? as i64,
|
|
|
|
reader.read_u64()? as i64,
|
|
|
|
reader.read_u64()? as i64],
|
|
|
|
file: reader.read_string()?,
|
|
|
|
line: reader.read_u32()?,
|
|
|
|
column: reader.read_u32()?,
|
|
|
|
function: reader.read_string()?
|
|
|
|
},
|
|
|
|
|
|
|
|
ty => return Err(Error::UnknownPacket(ty))
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-09-27 21:36:55 +08:00
|
|
|
impl<'a> Reply<'a> {
|
2018-05-15 21:27:23 +08:00
|
|
|
pub fn write_to<W>(&self, writer: &mut W) -> Result<(), IoError<W::WriteError>>
|
|
|
|
where W: Write + ?Sized
|
|
|
|
{
|
2017-02-01 06:18:59 +08:00
|
|
|
write_sync(writer)?;
|
2016-09-27 21:36:55 +08:00
|
|
|
match *self {
|
2017-02-01 06:53:38 +08:00
|
|
|
Reply::SystemInfo { ident, finished_cleanly } => {
|
2017-02-27 02:20:46 +08:00
|
|
|
writer.write_u8(2)?;
|
2017-02-01 06:18:59 +08:00
|
|
|
writer.write(b"AROR")?;
|
2017-02-27 02:20:46 +08:00
|
|
|
writer.write_string(ident)?;
|
|
|
|
writer.write_u8(finished_cleanly as u8)?;
|
2016-09-27 21:36:55 +08:00
|
|
|
},
|
|
|
|
|
|
|
|
Reply::LoadCompleted => {
|
2017-02-27 02:20:46 +08:00
|
|
|
writer.write_u8(5)?;
|
2016-09-27 21:36:55 +08:00
|
|
|
},
|
2017-01-27 20:49:48 +08:00
|
|
|
Reply::LoadFailed(reason) => {
|
2017-02-27 02:20:46 +08:00
|
|
|
writer.write_u8(6)?;
|
|
|
|
writer.write_string(reason)?;
|
2016-09-27 21:36:55 +08:00
|
|
|
},
|
|
|
|
|
|
|
|
Reply::KernelFinished => {
|
2017-02-27 02:20:46 +08:00
|
|
|
writer.write_u8(7)?;
|
2016-09-27 21:36:55 +08:00
|
|
|
},
|
|
|
|
Reply::KernelStartupFailed => {
|
2017-02-27 02:20:46 +08:00
|
|
|
writer.write_u8(8)?;
|
2016-09-27 21:36:55 +08:00
|
|
|
},
|
2016-10-06 21:42:35 +08:00
|
|
|
Reply::KernelException {
|
|
|
|
name, message, param, file, line, column, function, backtrace
|
|
|
|
} => {
|
2017-02-27 02:20:46 +08:00
|
|
|
writer.write_u8(9)?;
|
|
|
|
writer.write_string(name)?;
|
|
|
|
writer.write_string(message)?;
|
|
|
|
writer.write_u64(param[0] as u64)?;
|
|
|
|
writer.write_u64(param[1] as u64)?;
|
|
|
|
writer.write_u64(param[2] as u64)?;
|
|
|
|
writer.write_string(file)?;
|
|
|
|
writer.write_u32(line)?;
|
|
|
|
writer.write_u32(column)?;
|
|
|
|
writer.write_string(function)?;
|
|
|
|
writer.write_u32(backtrace.len() as u32)?;
|
2016-10-06 21:42:35 +08:00
|
|
|
for &addr in backtrace {
|
2017-02-27 02:20:46 +08:00
|
|
|
writer.write_u32(addr as u32)?
|
2016-10-06 21:42:35 +08:00
|
|
|
}
|
2016-09-27 21:36:55 +08:00
|
|
|
},
|
|
|
|
|
2016-11-01 14:51:44 +08:00
|
|
|
Reply::RpcRequest { async } => {
|
2017-02-27 02:20:46 +08:00
|
|
|
writer.write_u8(10)?;
|
|
|
|
writer.write_u8(async as u8)?;
|
2016-09-27 21:36:55 +08:00
|
|
|
},
|
|
|
|
|
|
|
|
Reply::ClockFailure => {
|
2017-02-27 02:20:46 +08:00
|
|
|
writer.write_u8(15)?;
|
2016-09-27 21:36:55 +08:00
|
|
|
},
|
|
|
|
}
|
2016-10-07 01:25:43 +08:00
|
|
|
Ok(())
|
2016-09-27 21:36:55 +08:00
|
|
|
}
|
|
|
|
}
|