Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 8 additions & 9 deletions uefi-test-runner/src/proto/network/http.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,13 +53,15 @@ fn fetch_http(handle: Handle, url: &str) -> Option<Vec<u8>> {
error!("http server error: {:?}", rsp.status);
return None;
}
let Some(cl_hdr) = rsp.headers.iter().find(|h| h.0 == "content-length") else {
let cl_hdr = rsp.headers.iter().find(|h| h.0 == "content-length");
if cl_hdr.is_none() {
// The only way to figure when your transfer is complete is to
// get the content length header and count the bytes you got.
// So missing header -> fatal error.
error!("no content length");
return None;
// So missing header -> give up and pretend things are okay.
warn!("no content length header, we might not have the whole body");
return Some(rsp.body);
};
let cl_hdr = cl_hdr.unwrap();
let Ok(cl) = cl_hdr.1.parse::<usize>() else {
error!("parse content length ({})", cl_hdr.1);
return None;
Expand All @@ -72,14 +74,11 @@ fn fetch_http(handle: Handle, url: &str) -> Option<Vec<u8>> {
break;
}

let res = http.response_more();
let res = http.response_more(&mut data);
if let Err(e) = res {
error!("read response: {e}");
return None;
}

let mut buf = res.unwrap();
data.append(&mut buf);
}

Some(data)
Expand All @@ -100,7 +99,7 @@ pub fn test() {

// hard to find web sites which still allow plain http these days ...
info!("Testing HTTP");
fetch_http(*h, "http://example.com/").expect("http request failed");
fetch_http(*h, "http://example.com/").expect("http request failed: http://example.com");

// FYI: not all firmware builds support modern tls versions.
// request() -> ABORTED typically is a tls handshake error.
Expand Down
2 changes: 2 additions & 0 deletions uefi/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
- Return request with status as error data object for `proto::ata::pass_thru::AtaDevice`.
- **Breaking:** `proto::network::snp::SimpleNetwork::wait_for_packet` now
returns `Option<Event>` instead of `&Event`.
- `Http::get_mode_data` doesn't consume a parameter anymore and instead return
an owned value of type `HttpConfigData`

# uefi - v0.36.1 (2025-11-05)

Expand Down
47 changes: 33 additions & 14 deletions uefi/src/proto/network/http.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,11 @@ pub struct Http(HttpProtocol);

impl Http {
/// Receive HTTP Protocol configuration.
pub fn get_mode_data(&mut self, config_data: &mut HttpConfigData) -> uefi::Result<()> {
let status = unsafe { (self.0.get_mode_data)(&mut self.0, config_data) };
pub fn get_mode_data(&mut self) -> uefi::Result<HttpConfigData> {
let mut config_data = HttpConfigData::default();
let status = unsafe { (self.0.get_mode_data)(&mut self.0, &mut config_data) };
match status {
Status::SUCCESS => Ok(()),
Status::SUCCESS => Ok(config_data),
_ => Err(status.into()),
}
}
Expand Down Expand Up @@ -116,18 +117,23 @@ impl HttpBinding {
}
}

/// HTTP Response data
/// Representation of the underlying UEFI HTTP response.
///
/// Helper type for [`HttpHelper`].
#[derive(Debug)]
pub struct HttpHelperResponse {
/// HTTP Status
pub status: HttpStatusCode,
/// HTTP Response Headers
pub headers: Vec<(String, String)>,
/// HTTP Body
/// Partial or entire HTTP body, depending on context.
pub body: Vec<u8>,
}

/// HTTP Helper, makes using the HTTP protocol more convenient.
/// HTTP Helper, makes using the [HTTP] [`Protocol`] more convenient.
///
/// [HTTP]: Http
/// [`Protocol`]: uefi::proto::Protocol
#[derive(Debug)]
pub struct HttpHelper {
child_handle: Handle,
Expand Down Expand Up @@ -270,7 +276,12 @@ impl HttpHelper {
Ok(())
}

/// Receive the start of the http response, the headers and (parts of) the body.
/// Receive the start of the http response, the headers and (parts of) the
/// body.
///
/// Depending on the HTTP response, its length, its encoding, and its
/// transmission method (chunked or not), users may have to call
/// [`Self::response_more`] afterward.
pub fn response_first(&mut self, expect_body: bool) -> uefi::Result<HttpHelperResponse> {
let mut rx_rsp = HttpResponseData {
status_code: HttpStatusCode::STATUS_UNSUPPORTED,
Expand Down Expand Up @@ -336,12 +347,13 @@ impl HttpHelper {
Ok(rsp)
}

/// Receive more body data.
pub fn response_more(&mut self) -> uefi::Result<Vec<u8>> {
let mut body = vec![0; 16 * 1024];
/// Try to receive more of the HTTP response and append any new data to the
/// provided `body` vector.
pub fn response_more<'a>(&mut self, body: &'a mut Vec<u8>) -> uefi::Result<&'a [u8]> {
let mut body_recv_buffer = vec![0; 16 * 1024];
let mut rx_msg = HttpMessage {
body_length: body.len(),
body: body.as_mut_ptr().cast::<c_void>(),
body_length: body_recv_buffer.len(),
body: body_recv_buffer.as_mut_ptr().cast::<c_void>(),
..Default::default()
};

Expand All @@ -367,9 +379,16 @@ impl HttpHelper {
return Err(rx_token.status.into());
};

debug!("http: body: {}/{}", rx_msg.body_length, body.len());
debug!(
"http: body: {}/{}",
rx_msg.body_length,
body_recv_buffer.len()
);

Ok(body[0..rx_msg.body_length].to_vec())
let new_data = &body_recv_buffer[0..rx_msg.body_length];
body.extend(new_data);
let new_data_slice = &body[body.len() - new_data.len()..];
Ok(new_data_slice)
}
}

Expand Down