Hi, I'm doing embedded development using the Rust language. I'm sorta a newbie to Rust, the lifetime system kinda confuses me atm. I'm writing an UEFI bootloader, and I have my own boot protocol for booting kernels. It uses a tag system, consisting of a reference to a slice of tag enum variants. I push the tag values after exiting the boot services, then give the slice reference to a structure (so I can't make any allocations). However, the compiler complains with the following message:
error[E0597]: `memory_map_entries` does not live long enough
--> src/main.rs:223:52
|
223 | tags.push(TagType::MemoryMap(memory_map_entries.as_slice()));
| ^^^^^^^^^^^^^^^^^^-----------
| |
| borrowed value does not live long enough
| argument requires that `memory_map_entries` is borrowed for `'static`
...
234 | } else {
| - `memory_map_entries` dropped here while still borrowed
error[E0597]: `tags` does not live long enough
--> src/main.rs:226:26
|
226 | explosion.tags = tags.as_slice();
| ^^^^-----------
| |
| borrowed value does not live long enough
| argument requires that `tags` is borrowed for `'static`
...
234 | } else {
| - `tags` dropped here while still borrowed
For more information about this error, try `rustc --explain E0597`.
I don't understand how to leak a Vec without allocating a box
Here is reference code for what I'm doing
// This code is inside an if let statement which is used to check if the elf is 64-bit
let mut boot_data = Box::new(BootProtoData::new(Default::default()));
let mut tags = Vec::<TagType>::with_capacity(3);
// [...]
let mut mmap_buf = vec![0; system_table.boot_services().memory_map_size()];
let mut memory_map_entries = Vec::with_capacity(
mmap_buf.capacity() / size_of::<uefi::table::boot::MemoryDescriptor>(),
);
mmap_buf.resize(system_table.boot_services().memory_map_size(), 0);
// Can't make allocations after here
for desc in system_table
.exit_boot_services(image, &mut mmap_buf)
.expect_success("Failed to exit boot services.")
.1
{
match desc.ty {
// Here, depending on the memory type, I call memory_map_entries.push();
}
}
tags.push(TagType::MemoryMap(memory_map_entries.as_slice()));
boot_data.tags = tags.as_slice();
// Then I call the kernel entry point, passing Box::leak(boot_data) as the argument
BootProtoData::tags is of type &'a [TagType<'a>]
TagType<'a> contains enum variant MemoryMap(&'a [MemoryEntry])
Also, I can't use the alloc crate in the kernel I'm booting yet to use types like Box and Vec in the structures because it's currently very bare-bones.