Rust, as a language, doesn’t know anything about heap allocation. The “running out of memory” stuff you’re talking about is a feature of some APIs of the standard library, which you often completely forego in an embedded context. Or you can use the (still unstable, to be fair) APIs that return results instead. This is what the Linux kernel is doing, for example. It was a hard line for Linus, but didn’t prove to be an obstacle in the end.
One could, of course, write their own allocator and heap tracking system as part of the UEFI firmware, or reimplement the entire thing without any of the standard library and simply relying on the core library, but if you want to deal with fallibility, you'll have to reimplement every part of the language toolkit and use Option<> or Result<> for every API call, which would only complicate the rewrite more.