Skip to content

Commit 7bf0c6a

Browse files
committed
Do not require OS for BootOptions.
1 parent 67673c8 commit 7bf0c6a

6 files changed

Lines changed: 77 additions & 91 deletions

File tree

pixie-uefi/src/flash.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ use pixie_shared::util::BytesFmt;
1414
use pixie_shared::{ChunkHash, Image, TcpRequest, UdpRequest, CHUNKS_PORT, MAX_CHUNK_SIZE};
1515
use uefi::proto::console::text::Color;
1616

17+
use crate::os::boot_options::BootOptions;
1718
use crate::os::error::{Error, Result};
1819
use crate::os::{memory, TcpStream, UefiOS, PACKET_SIZE};
1920
use crate::MIN_MEMORY;
@@ -230,9 +231,8 @@ pub async fn flash(os: UefiOS, server_addr: SocketAddrV4) -> Result<()> {
230231

231232
info!("Fetch complete, updating boot options");
232233

233-
let bo = os.boot_options();
234-
let mut order = bo.order();
235-
let reboot_target = bo.reboot_target();
234+
let mut order = BootOptions::order();
235+
let reboot_target = BootOptions::reboot_target();
236236
if let Some(target) = reboot_target {
237237
order = order
238238
.into_iter()
@@ -241,8 +241,8 @@ pub async fn flash(os: UefiOS, server_addr: SocketAddrV4) -> Result<()> {
241241
} else {
242242
order.push(image.boot_option_id);
243243
};
244-
bo.set_order(&order);
245-
bo.set(image.boot_option_id, &image.boot_entry);
244+
BootOptions::set_order(&order);
245+
BootOptions::set(image.boot_option_id, &image.boot_entry);
246246

247247
Ok(())
248248
}

pixie-uefi/src/os/boot_options.rs

Lines changed: 57 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,100 +1,120 @@
1+
use alloc::boxed::Box;
12
use alloc::string::{String, ToString};
23
use alloc::vec::Vec;
34

45
use uefi::proto::device_path::DevicePath;
56
use uefi::runtime::{VariableAttributes, VariableVendor};
6-
use uefi::CString16;
7+
use uefi::{CStr16, CString16};
78

8-
use super::UefiOS;
9+
use crate::os::error::{Error, Result};
910

10-
pub struct BootOptions {
11-
pub(super) os: UefiOS,
11+
#[derive(Debug)]
12+
pub struct Variable {
13+
name: CString16,
14+
vendor: VariableVendor,
1215
}
1316

17+
impl Variable {
18+
pub fn new(name: &str, vendor: VariableVendor) -> Self {
19+
// name.len() should be enough, but...
20+
let mut name_buf = vec![0u16; name.len() * 2 + 16];
21+
let name = CStr16::from_str_with_buf(name, &mut name_buf).unwrap();
22+
Self {
23+
name: name.into(),
24+
vendor,
25+
}
26+
}
27+
28+
pub fn get(&self) -> Result<(Box<[u8]>, VariableAttributes)> {
29+
uefi::runtime::get_variable_boxed(&self.name, &self.vendor)
30+
.map_err(|e| Error(format!("Error getting variable: {e:?}")))
31+
}
32+
33+
pub fn set(&self, data: &[u8], attrs: VariableAttributes) -> Result<()> {
34+
uefi::runtime::set_variable(&self.name, &self.vendor, attrs, data)
35+
.map_err(|e| Error(format!("Error setting variable: {e:?}")))
36+
}
37+
}
38+
39+
pub struct BootOptions;
40+
1441
impl BootOptions {
15-
pub fn current(&self) -> u16 {
16-
let cur = self
17-
.os
18-
.get_variable("BootCurrent", &VariableVendor::GLOBAL_VARIABLE)
42+
pub fn current() -> u16 {
43+
let cur = Variable::new("BootCurrent", VariableVendor::GLOBAL_VARIABLE)
44+
.get()
1945
.unwrap()
2046
.0;
21-
u16::from_le_bytes(cur.try_into().unwrap())
47+
u16::from_le_bytes((*cur).try_into().unwrap())
2248
}
2349

24-
pub fn order(&self) -> Vec<u16> {
25-
self.os
26-
.get_variable("BootOrder", &VariableVendor::GLOBAL_VARIABLE)
50+
pub fn order() -> Vec<u16> {
51+
Variable::new("BootOrder", VariableVendor::GLOBAL_VARIABLE)
52+
.get()
2753
.unwrap()
2854
.0
2955
.chunks(2)
3056
.map(|x| u16::from_le_bytes(x.try_into().unwrap()))
3157
.collect()
3258
}
3359

34-
pub fn set_order(&self, order: &[u16]) {
60+
pub fn set_order(order: &[u16]) {
3561
let order: Vec<_> = order
3662
.iter()
3763
.flat_map(|x| x.to_le_bytes().into_iter())
3864
.collect();
39-
self.os
40-
.set_variable(
41-
"BootOrder",
42-
&VariableVendor::GLOBAL_VARIABLE,
65+
Variable::new("BootOrder", VariableVendor::GLOBAL_VARIABLE)
66+
.set(
67+
&order[..],
4368
VariableAttributes::NON_VOLATILE
4469
| VariableAttributes::BOOTSERVICE_ACCESS
4570
| VariableAttributes::RUNTIME_ACCESS,
46-
&order[..],
4771
)
4872
.unwrap()
4973
}
5074

51-
pub fn set_next(&self, next: u16) {
52-
self.os
53-
.set_variable(
54-
"BootNext",
55-
&VariableVendor::GLOBAL_VARIABLE,
75+
pub fn set_next(next: u16) {
76+
Variable::new("BootNext", VariableVendor::GLOBAL_VARIABLE)
77+
.set(
78+
&next.to_le_bytes(),
5679
VariableAttributes::NON_VOLATILE
5780
| VariableAttributes::BOOTSERVICE_ACCESS
5881
| VariableAttributes::RUNTIME_ACCESS,
59-
&next.to_le_bytes(),
6082
)
6183
.unwrap();
6284
}
6385

64-
pub fn reboot_target(&self) -> Option<u16> {
65-
let order = self.order();
86+
pub fn reboot_target() -> Option<u16> {
87+
let order = Self::order();
6688
let num_skip = order
6789
.iter()
6890
.cloned()
69-
.position(|x| x == self.current())
91+
.position(|x| x == Self::current())
7092
.map(|x| x + 1)
7193
.unwrap_or(0);
7294
order.iter().cloned().skip(num_skip).find(|x| *x < 0x2000)
7395
}
7496

75-
pub fn get(&self, id: u16) -> Vec<u8> {
76-
self.os
77-
.get_variable(&format!("Boot{id:04X}"), &VariableVendor::GLOBAL_VARIABLE)
97+
pub fn get(id: u16) -> Box<[u8]> {
98+
Variable::new(&format!("Boot{id:04X}"), VariableVendor::GLOBAL_VARIABLE)
99+
.get()
78100
.unwrap()
79101
.0
80102
}
81103

82-
pub fn set(&self, id: u16, data: &[u8]) {
83-
self.os
84-
.set_variable(
85-
&format!("Boot{id:04X}"),
86-
&VariableVendor::GLOBAL_VARIABLE,
104+
pub fn set(id: u16, data: &[u8]) {
105+
Variable::new(&format!("Boot{id:04X}"), VariableVendor::GLOBAL_VARIABLE)
106+
.set(
107+
data,
87108
VariableAttributes::NON_VOLATILE
88109
| VariableAttributes::BOOTSERVICE_ACCESS
89110
| VariableAttributes::RUNTIME_ACCESS,
90-
data,
91111
)
92112
.unwrap();
93113
}
94114

95115
/// Boot entry *must* be valid (TODO).
96116
/// Returns boot option description and device path of the option.
97-
pub fn boot_entry_info<'a>(&self, entry: &'a [u8]) -> (String, &'a DevicePath) {
117+
pub fn boot_entry_info(entry: &[u8]) -> (String, &DevicePath) {
98118
let skip_attropt = &entry[6..];
99119
let end_of_description = skip_attropt
100120
.chunks(2)

pixie-uefi/src/os/mod.rs

Lines changed: 3 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -19,18 +19,16 @@ use uefi::proto::device_path::build::DevicePathBuilder;
1919
use uefi::proto::device_path::text::{AllowShortcuts, DevicePathToText, DisplayOnly};
2020
use uefi::proto::device_path::DevicePath;
2121
use uefi::proto::Protocol;
22-
use uefi::runtime::{VariableAttributes, VariableVendor};
23-
use uefi::{CStr16, Event, Handle, Status};
22+
use uefi::{Event, Handle, Status};
2423

25-
use self::boot_options::BootOptions;
2624
use self::disk::Disk;
27-
use self::error::{Error, Result};
25+
use self::error::Result;
2826
use self::executor::{Executor, Task};
2927
use self::net::NetworkInterface;
3028
use self::sync::SyncRefCell;
3129
use self::timer::Timer;
3230

33-
mod boot_options;
31+
pub mod boot_options;
3432
pub mod disk;
3533
pub mod error;
3634
mod executor;
@@ -310,38 +308,6 @@ impl UefiOS {
310308
uefi::boot::wait_for_event(&mut [e]).unwrap();
311309
}
312310

313-
pub fn get_variable(
314-
&self,
315-
name: &str,
316-
vendor: &VariableVendor,
317-
) -> Result<(Vec<u8>, VariableAttributes)> {
318-
// name.len() should be enough, but...
319-
let mut name_buf = vec![0u16; name.len() * 2 + 16];
320-
let name = CStr16::from_str_with_buf(name, &mut name_buf).unwrap();
321-
let (var, attrs) = uefi::runtime::get_variable_boxed(name, vendor)
322-
.map_err(|e| Error(format!("Error getting variable: {e:?}")))?;
323-
Ok((var.to_vec(), attrs))
324-
}
325-
326-
pub fn set_variable(
327-
&self,
328-
name: &str,
329-
vendor: &VariableVendor,
330-
attrs: VariableAttributes,
331-
data: &[u8],
332-
) -> Result<()> {
333-
// name.len() should be enough, but...
334-
let mut name_buf = vec![0u16; name.len() * 2 + 16];
335-
let name = CStr16::from_str_with_buf(name, &mut name_buf).unwrap();
336-
uefi::runtime::set_variable(name, vendor, attrs, data)
337-
.map_err(|e| Error(format!("Error setting variable: {e:?}")))?;
338-
Ok(())
339-
}
340-
341-
pub fn boot_options(&self) -> BootOptions {
342-
BootOptions { os: *self }
343-
}
344-
345311
pub fn device_path_to_string(&self, device: &DevicePath) -> String {
346312
let handle = uefi::boot::get_handle_for_protocol::<DevicePathToText>().unwrap();
347313
let device_path_to_text =

pixie-uefi/src/os/net.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ use uefi::Status;
1919
use super::error::{Error, Result};
2020
use super::timer::Timer;
2121
use super::UefiOS;
22+
use crate::os::boot_options::BootOptions;
2223
use crate::os::timer::rdtsc;
2324

2425
pub const PACKET_SIZE: usize = 1514;
@@ -151,9 +152,8 @@ pub struct NetworkInterface {
151152

152153
impl NetworkInterface {
153154
pub fn new(os: UefiOS) -> NetworkInterface {
154-
let bo = os.boot_options();
155-
let curopt = bo.get(bo.current());
156-
let (descr, device) = bo.boot_entry_info(&curopt[..]);
155+
let curopt = BootOptions::get(BootOptions::current());
156+
let (descr, device) = BootOptions::boot_entry_info(&curopt[..]);
157157
log::info!(
158158
"Configuring network on interface used for booting ({} -- {})",
159159
descr,

pixie-uefi/src/reboot_to_os.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
1+
use crate::os::boot_options::BootOptions;
12
use crate::os::UefiOS;
23

34
pub async fn reboot_to_os(os: UefiOS) -> ! {
4-
let bo = os.boot_options();
5-
let next = bo.reboot_target();
5+
let next = BootOptions::reboot_target();
66
if let Some(next) = next {
77
// Reboot to next boot option.
8-
bo.set_next(next);
8+
BootOptions::set_next(next);
99
} else {
1010
log::warn!(
1111
"Did not find a valid boot order entry! current: {}",
12-
bo.current()
12+
BootOptions::current()
1313
);
14-
log::warn!("{:?}", bo.order());
14+
log::warn!("{:?}", BootOptions::order());
1515
os.sleep_us(100_000_000).await;
1616
}
1717
os.reset();

pixie-uefi/src/store.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ use pixie_shared::util::BytesFmt;
99
use pixie_shared::{Chunk, Image, Offset, TcpRequest, UdpRequest, MAX_CHUNK_SIZE};
1010
use uefi::proto::console::text::Color;
1111

12+
use crate::os::boot_options::BootOptions;
1213
use crate::os::error::{Error, Result};
1314
use crate::os::{memory, TcpStream, UefiOS};
1415
use crate::{parse_disk, MIN_MEMORY};
@@ -65,9 +66,8 @@ pub async fn store(os: UefiOS, server_address: SocketAddrV4) -> Result<()> {
6566
}
6667
});
6768

68-
let bo = os.boot_options();
69-
let boid = bo.reboot_target().expect("Could not find reboot target");
70-
let bo_command = bo.get(boid);
69+
let boid = BootOptions::reboot_target().expect("Could not find reboot target");
70+
let bo_command = BootOptions::get(boid);
7171

7272
let mut disk = os.open_first_disk();
7373
let chunks = parse_disk::parse_disk(&mut disk).await?;
@@ -198,7 +198,7 @@ pub async fn store(os: UefiOS, server_address: SocketAddrV4) -> Result<()> {
198198
&stream_upload_chunk,
199199
Image {
200200
boot_option_id: boid,
201-
boot_entry: bo_command,
201+
boot_entry: bo_command.to_vec(),
202202
disk: chunk_hashes,
203203
},
204204
)

0 commit comments

Comments
 (0)