hyperlight_guest/
host_function_call.rs1use alloc::format;
18use alloc::string::ToString;
19use alloc::vec::Vec;
20use core::arch;
21
22use hyperlight_common::flatbuffer_wrappers::function_call::{FunctionCall, FunctionCallType};
23use hyperlight_common::flatbuffer_wrappers::function_types::{
24 ParameterValue, ReturnType, ReturnValue,
25};
26use hyperlight_common::flatbuffer_wrappers::guest_error::ErrorCode;
27use hyperlight_common::flatbuffer_wrappers::util::get_flatbuffer_result;
28use hyperlight_common::outb::OutBAction;
29
30use crate::error::{HyperlightGuestError, Result};
31use crate::shared_input_data::try_pop_shared_input_data_into;
32use crate::shared_output_data::push_shared_output_data;
33
34pub fn get_host_return_value<T: TryFrom<ReturnValue>>() -> Result<T> {
39 let return_value = try_pop_shared_input_data_into::<ReturnValue>()
40 .expect("Unable to deserialize a return value from host");
41 T::try_from(return_value).map_err(|_| {
42 HyperlightGuestError::new(
43 ErrorCode::GuestError,
44 format!(
45 "Host return value was not a {} as expected",
46 core::any::type_name::<T>()
47 ),
48 )
49 })
50}
51
52pub fn call_host_function_internal(
58 function_name: &str,
59 parameters: Option<Vec<ParameterValue>>,
60 return_type: ReturnType,
61) -> Result<()> {
62 let host_function_call = FunctionCall::new(
63 function_name.to_string(),
64 parameters,
65 FunctionCallType::Host,
66 return_type,
67 );
68
69 let host_function_call_buffer: Vec<u8> = host_function_call
70 .try_into()
71 .expect("Unable to serialize host function call");
72
73 push_shared_output_data(host_function_call_buffer)?;
74
75 outb(OutBAction::CallFunction as u16, &[0]);
76
77 Ok(())
78}
79
80pub fn call_host_function<T: TryFrom<ReturnValue>>(
86 function_name: &str,
87 parameters: Option<Vec<ParameterValue>>,
88 return_type: ReturnType,
89) -> Result<T> {
90 call_host_function_internal(function_name, parameters, return_type)?;
91 get_host_return_value::<T>()
92}
93
94pub fn outb(port: u16, data: &[u8]) {
95 unsafe {
96 let mut i = 0;
97 while i < data.len() {
98 let remaining = data.len() - i;
99 let chunk_len = remaining.min(3);
100 let mut chunk = [0u8; 4];
101 chunk[0] = chunk_len as u8;
102 chunk[1..1 + chunk_len].copy_from_slice(&data[i..i + chunk_len]);
103 let val = u32::from_le_bytes(chunk);
104 out32(port, val);
105 i += chunk_len;
106 }
107 }
108}
109
110pub(crate) unsafe fn out32(port: u16, val: u32) {
111 arch::asm!("out dx, eax", in("dx") port, in("eax") val, options(preserves_flags, nomem, nostack));
112}
113
114pub fn debug_print(msg: &str) {
121 outb(OutBAction::DebugPrint as u16, msg.as_bytes());
122}
123
124pub fn print_output_with_host_print(function_call: &FunctionCall) -> Result<Vec<u8>> {
129 if let ParameterValue::String(message) = function_call.parameters.clone().unwrap()[0].clone() {
130 let res = call_host_function::<i32>(
131 "HostPrint",
132 Some(Vec::from(&[ParameterValue::String(message.to_string())])),
133 ReturnType::Int,
134 )?;
135
136 Ok(get_flatbuffer_result(res))
137 } else {
138 Err(HyperlightGuestError::new(
139 ErrorCode::GuestError,
140 "Wrong Parameters passed to print_output_with_host_print".to_string(),
141 ))
142 }
143}