Skip to content

Commit afb0213

Browse files
authored
Move request logic into a separate crate (#2745)
This moves the trivial echo code from the UEFI app code into a separate crate. The goals are two-fold: (a) First, the UEFI app crate should only be kind of hardware abstraction layer, with no cleverness of its own. All logic should be somewhere else. (b) Second, this allows us to create a bare-metal 'kernel' which offers a similar abstraction layer, and use the common runtime library shared with the UEFI app.
1 parent 012a520 commit afb0213

File tree

9 files changed

+149
-60
lines changed

9 files changed

+149
-60
lines changed

Cargo.lock

Lines changed: 35 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ members = [
1414
"experimental/trusted_shuffler/trusted_shuffler",
1515
"experimental/uefi/client",
1616
"experimental/uefi/loader",
17+
"experimental/uefi/runtime",
1718
"oak_functions/abi",
1819
"oak_functions/client/rust",
1920
"oak_functions/examples/benchmark/module",

experimental/uefi/app/Cargo.lock

Lines changed: 9 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

experimental/uefi/app/Cargo.toml

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,8 @@ support_emulated_runner = []
1212
[dependencies]
1313
uefi = { version = "*", features = ["exts"] }
1414
uefi-services = "*"
15-
log = { version = "*" }
16-
ciborium = { version = "*", default-features = false }
17-
ciborium-io = "*"
1815
oak_remote_attestation = { path = "../../../remote_attestation/rust" }
16+
runtime = { path = "../runtime" }
1917

2018
[dev-dependencies]
2119
anyhow = { version = "*", default-features = false }

experimental/uefi/app/src/main.rs

Lines changed: 4 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,7 @@
2424
#![test_runner(crate::test_runner)]
2525
#![reexport_test_harness_main = "test_main"]
2626

27-
#[macro_use]
28-
extern crate log;
29-
extern crate alloc;
30-
31-
use ciborium::{de, ser};
27+
use runtime::echo;
3228
use uefi::{prelude::*, table::runtime::ResetType};
3329

3430
mod serial;
@@ -68,44 +64,9 @@ fn main(handle: Handle, system_table: &mut SystemTable<Boot>) -> Status {
6864

6965
writeln!(system_table.stdout(), "Hello World!").unwrap();
7066

71-
serial_echo(handle, system_table.boot_services(), ECHO_SERIAL_PORT_INDEX).unwrap();
72-
}
73-
74-
// Opens the index-th serial port on the system and echoes back all frames sent over the serial
75-
// port.
76-
//
77-
// Panics if the index-th serial port does not exist.
78-
//
79-
// Arguments:
80-
// * `handle` - UEFI handle of the agent (eg of the UEFI app)
81-
// * `boot_services` - reference to the UEFI Boot Services struct (obtained from the system
82-
// table)
83-
// * `index` - index of the serial port, zero-based.
84-
//
85-
// Normally does not return, unless an error is raised.
86-
fn serial_echo(handle: Handle, bt: &BootServices, index: usize) -> Result<!, uefi::Error<()>> {
87-
let mut serial = serial::Serial::get(handle, bt, index)?;
88-
loop {
89-
let msg: alloc::vec::Vec<u8> = de::from_reader(&mut serial).map_err(|err| match err {
90-
de::Error::Io(err) => err,
91-
de::Error::Syntax(idx) => {
92-
error!("Error reading data at index {}", idx);
93-
uefi::Error::from(Status::INVALID_PARAMETER)
94-
}
95-
de::Error::Semantic(_, err) => {
96-
error!("Error parsing cbor data: {:?}", err);
97-
uefi::Error::from(Status::INVALID_PARAMETER)
98-
}
99-
de::Error::RecursionLimitExceeded => uefi::Error::from(Status::ABORTED),
100-
})?;
101-
ser::into_writer(&msg, &mut serial).map_err(|err| match err {
102-
ser::Error::Io(err) => err,
103-
ser::Error::Value(msg) => {
104-
error!("Error serializing value: {}", msg);
105-
uefi::Error::from(Status::INVALID_PARAMETER)
106-
}
107-
})?;
108-
}
67+
let mut serial =
68+
serial::Serial::get(handle, system_table.boot_services(), ECHO_SERIAL_PORT_INDEX).unwrap();
69+
echo::echo(&mut serial).unwrap();
10970
}
11071

11172
#[cfg(test)]

experimental/uefi/app/src/serial.rs

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -71,24 +71,16 @@ impl<'boot> Serial<'boot> {
7171
}
7272
}
7373

74-
impl<'boot> ciborium_io::Write for Serial<'boot> {
74+
impl<'boot> runtime::Channel for Serial<'boot> {
7575
type Error = Error<()>;
7676

77-
fn write_all(&mut self, data: &[u8]) -> Result<(), Self::Error> {
77+
fn send(&mut self, data: &[u8]) -> Result<(), Self::Error> {
7878
self.serial.write(data).discard_errdata()
7979
}
8080

81-
fn flush(&mut self) -> Result<(), Self::Error> {
82-
Ok(())
83-
}
84-
}
85-
86-
impl<'boot> ciborium_io::Read for Serial<'boot> {
87-
type Error = Error<()>;
88-
8981
// Try to fill the buffer, ignoring any timeout errors. Any other errors
9082
// are propagated upward.
91-
fn read_exact(&mut self, data: &mut [u8]) -> Result<(), Self::Error> {
83+
fn recv(&mut self, data: &mut [u8]) -> Result<(), Self::Error> {
9284
let mut bytes_read = 0;
9385
while bytes_read < data.len() {
9486
let len = self.read(&mut data[bytes_read..])?;
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
[package]
2+
name = "runtime"
3+
version = "0.1.0"
4+
authors = ["Andri Saar <[email protected]>"]
5+
edition = "2021"
6+
license = "Apache-2.0"
7+
8+
[dependencies]
9+
ciborium = { version = "*", default-features = false }
10+
ciborium-io = "*"
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
//
2+
// Copyright 2022 The Project Oak Authors
3+
//
4+
// Licensed under the Apache License, Version 2.0 (the "License");
5+
// you may not use this file except in compliance with the License.
6+
// You may obtain a copy of the License at
7+
//
8+
// http://www.apache.org/licenses/LICENSE-2.0
9+
//
10+
// Unless required by applicable law or agreed to in writing, software
11+
// distributed under the License is distributed on an "AS IS" BASIS,
12+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
// See the License for the specific language governing permissions and
14+
// limitations under the License.
15+
//
16+
17+
extern crate alloc;
18+
19+
use crate::Channel;
20+
use alloc::vec::Vec;
21+
use ciborium::{de, ser};
22+
23+
#[derive(Debug)]
24+
pub enum Error<T> {
25+
// An error occured while deserializing.
26+
De(ciborium::de::Error<T>),
27+
28+
// An error occured while serializing.
29+
Ser(ciborium::ser::Error<T>),
30+
}
31+
32+
impl<E> ciborium_io::Write for &mut dyn Channel<Error = E> {
33+
type Error = E;
34+
35+
fn write_all(&mut self, data: &[u8]) -> Result<(), Self::Error> {
36+
self.send(data)
37+
}
38+
39+
fn flush(&mut self) -> Result<(), Self::Error> {
40+
Ok(())
41+
}
42+
}
43+
44+
impl<E> ciborium_io::Read for &mut dyn Channel<Error = E> {
45+
type Error = E;
46+
47+
fn read_exact(&mut self, data: &mut [u8]) -> Result<(), Self::Error> {
48+
self.recv(data)
49+
}
50+
}
51+
52+
// Echoes all input on the interface back out.
53+
pub fn echo<E: core::fmt::Debug>(mut channel: &mut dyn Channel<Error = E>) -> Result<!, Error<E>> {
54+
loop {
55+
let msg: Vec<u8> = de::from_reader(&mut channel).map_err(Error::De)?;
56+
ser::into_writer(&msg, &mut channel).map_err(Error::Ser)?;
57+
}
58+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
//
2+
// Copyright 2022 The Project Oak Authors
3+
//
4+
// Licensed under the Apache License, Version 2.0 (the "License");
5+
// you may not use this file except in compliance with the License.
6+
// You may obtain a copy of the License at
7+
//
8+
// http://www.apache.org/licenses/LICENSE-2.0
9+
//
10+
// Unless required by applicable law or agreed to in writing, software
11+
// distributed under the License is distributed on an "AS IS" BASIS,
12+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
// See the License for the specific language governing permissions and
14+
// limitations under the License.
15+
//
16+
17+
#![no_std]
18+
#![feature(never_type)]
19+
20+
pub mod echo;
21+
22+
/// Basic hardware abstraction layer for sending data.
23+
pub trait Channel {
24+
type Error;
25+
26+
fn send(&mut self, data: &[u8]) -> Result<(), Self::Error>;
27+
fn recv(&mut self, data: &mut [u8]) -> Result<(), Self::Error>;
28+
}

0 commit comments

Comments
 (0)