use patina::{
BinaryGuid,
component::{IntoComponent, Storage, component, prelude::*},
};
use zerocopy_derive::FromBytes;
#[derive(Debug, FromHob, FromBytes)]
#[repr(C)]
#[hob = "00000000-0000-0000-0000-000000000001"]
pub struct CustomHob1 {
pub data1: u32,
pub data2: u32,
pub data3: u64,
pub data4: u8,
padding: [u8; 7],
}
#[derive(Debug, Clone)]
pub struct CustomHob2(String);
impl FromHob for CustomHob2 {
const HOB_GUID: BinaryGuid = BinaryGuid::from_string("00000000-0000-0000-0000-000000000002");
fn parse(bytes: &[u8]) -> Self {
let out = String::from_utf8(bytes.to_vec()).expect("Failed to parse string from bytes");
CustomHob2(out)
}
}
#[derive(Debug, Default)]
pub struct BooleanConfig(pub bool);
pub struct MultipleHobConsumer;
#[component]
impl MultipleHobConsumer {
pub fn entry_point(self, hob1: Hob<CustomHob1>, hob2: Option<Hob<CustomHob2>>) -> Result<()> {
for hob in hob1.iter() {
println!(" Hob1 data: {hob:?}");
}
match hob2 {
Some(hob) => println!(" Hob2 exists with data: {:?}", *hob),
None => println!(" Hob2 does not exist, continuing without it."),
};
Ok(())
}
}
pub struct HobToConfigConverter;
#[component]
impl HobToConfigConverter {
fn entry_point(self, hob: Hob<CustomHob1>, mut cfg: ConfigMut<BooleanConfig>) -> Result<()> {
cfg.0 = hob.data4 != 0;
println!(" Hob data converted to config. Config Value: {:?}", cfg.0);
cfg.lock();
Ok(())
}
}
fn main() {
let mut storage = Storage::default();
let components = vec![
util::register_component(MultipleHobConsumer, &mut storage),
util::register_component(HobToConfigConverter, &mut storage),
];
util::setup_storage(
&mut storage,
vec![
util::Custom::Hob1(CustomHob1 { data1: 42, data2: 100, data3: 50, data4: 1, padding: [0; 7] }),
util::Custom::Hob1(CustomHob1 { data1: 43, data2: 101, data3: 10, data4: 0, padding: [0; 7] }),
util::Custom::Hob2(CustomHob2("Hello".to_string())),
],
);
for mut component in components {
println!("Running component: {:?}", component.metadata().name());
component.run(&mut storage).expect("Component execution failed");
}
}
mod util {
use patina::{component::Component, pi::hob::GuidHob};
use super::{CustomHob1, CustomHob2, FromHob, IntoComponent, Storage};
pub enum Custom {
Hob1(CustomHob1),
Hob2(CustomHob2),
}
impl Custom {
fn insert(self, hob_list: &mut patina::pi::hob::HobList) {
match self {
Custom::Hob1(hob) => insert_custom_hob1(hob_list, hob),
Custom::Hob2(hob) => insert_custom_hob2(hob_list, hob),
}
}
}
pub fn register_component<H>(component: impl IntoComponent<H>, storage: &mut Storage) -> Box<dyn Component> {
let mut component = component.into_component();
component.initialize(storage);
component
}
pub fn setup_storage(storage: &mut Storage, hobs: Vec<Custom>) {
let mut hob_list = patina::pi::hob::HobList::new();
for hob in hobs {
hob.insert(&mut hob_list);
}
for hob in hob_list.iter() {
match hob {
patina::pi::hob::Hob::GuidHob(hob, data) => {
for parser in storage.get_hob_parsers(&hob.name) {
parser(data, storage);
}
}
_ => continue, }
}
}
fn insert_custom_hob1(hob_list: &mut patina::pi::hob::HobList, hob: CustomHob1) {
let mut data = Vec::new();
data.extend_from_slice(&hob.data1.to_le_bytes());
data.extend_from_slice(&hob.data2.to_le_bytes());
data.extend_from_slice(&hob.data3.to_le_bytes());
data.push(hob.data4);
data.extend_from_slice(&hob.padding);
let as_slice = Box::leak(data.into_boxed_slice());
let hob = Box::leak(Box::new(GuidHob {
header: patina::pi::hob::header::Hob {
r#type: patina::pi::hob::GUID_EXTENSION,
length: std::mem::size_of::<CustomHob1>() as u16,
reserved: 0,
},
name: patina::BinaryGuid::from_string("00000000-0000-0000-0000-000000000001"),
}));
hob_list.push(patina::pi::hob::Hob::GuidHob(hob, as_slice));
}
fn insert_custom_hob2(hob_list: &mut patina::pi::hob::HobList, hob: CustomHob2) {
let mut data = Vec::new();
data.extend_from_slice(hob.0.as_bytes());
let as_slice = Box::leak(data.into_boxed_slice());
let hob = Box::leak(Box::new(GuidHob {
header: patina::pi::hob::header::Hob {
r#type: patina::pi::hob::GUID_EXTENSION,
length: std::mem::size_of::<CustomHob2>() as u16,
reserved: 0,
},
name: CustomHob2::HOB_GUID,
}));
hob_list.push(patina::pi::hob::Hob::GuidHob(hob, as_slice));
}
}