For qcom/quality improvements - #18
Conversation
fastboot.efi is commonly used to boot images cross-compiled on X86 machines, but if the user forgets to force the UKI to be built for aarch64, fastboot.efi will determine that it's not a valid PE image and end up failing to load the image without clear indication of what's wrong. Handle this case in a cleaner way to aid the user in determining the cause of such issues. Signed-off-by: Bjorn Andersson <bjorn.andersson@oss.qualcomm.com>
fastboot_respond() has been allocating a new USB transfer buffer for every response and never released it. Allocate one 64-byte IN transfer buffer in main(), pass it through command handlers, and free it at shutdown. This keeps response semantics unchanged while fixing the response-buffer lifetime and leak. Signed-off-by: Bjorn Andersson <bjorn.andersson@oss.qualcomm.com>
Handle malformed command payloads more defensively by truncating at NUL, trimming CR/LF, validating UTF-8, and rejecting invalid download/getvar syntax with explicit FAIL responses. Also avoid panicking if boot fails after acknowledging a boot request: send a single OKAY before StartImage, then only log StartImage failures. This preserves fastboot protocol expectations and avoids a second response after OKAY. Signed-off-by: Bjorn Andersson <bjorn.andersson@oss.qualcomm.com>
| fn handle_boot(usb_device: &ScopedProtocol<EfiUsbDevice>, payload: &[u8]) -> Result { | ||
| let (handle, _initrd) = if is_peimage(payload) { | ||
| (handle_peimage(payload)?, None) | ||
| } else if let Some(machine) = pe_machine(payload) { |
There was a problem hiding this comment.
My immediate reaction would be to move this near the:
if machine != PE_ARM64 {
return false;
}check in is_peimage, however that function currently only returns a boolean.. but OTOH it may be useful to have it define a couple of related error types
|
|
||
| fn fastboot_respond( | ||
| usb_device: &ScopedProtocol<EfiUsbDevice>, | ||
| response_buffer: *mut u8, |
There was a problem hiding this comment.
Can we do without the boilerplate argument, i.e. perhaps by declaring a global Option<T> and initializing it in main?
| .unwrap_or(data.len()); | ||
| let request = core::str::from_utf8(&data[..request_end]).map_err(|_| ())?; | ||
| let request = request.trim_end_matches(|ch| ch == '\r' || ch == '\n'); | ||
|
|
There was a problem hiding this comment.
String::from_utf8().trim_ascii()?
| fastboot_respond( | ||
| usb_device, | ||
| response_buffer, | ||
| &format!("FAILfailed: {:?}", err.status()), |
There was a problem hiding this comment.
I'm not quite sure, but I think that this will only print the textual representation of the UEFI error, but give no clues to what function it came from
| .expect("Failed to send response"); | ||
| usb_device | ||
| .send(usb_device::ENDPOINT_OUT, 1024 * 1024, command_buffer) | ||
| .expect("failed to queue command buffer"); |
There was a problem hiding this comment.
nit: there are some Faileds and some faileds
No description provided.