Skip to content

Commit 2c7e1e3

Browse files
loaded image: add set_image function
This allows overriding the data in `LoadedImage`. It's useful in the following scenario: 1. Secure boot is enabled, so images loaded with `LoadImage` must be signed with an appropriate key known to the firmware. 2. The bootloader has its own key embedded, and uses that key to verify the next stage. This key is not known to the firmware, so the next stage's image can't be loaded with `LoadImage`. 3. Since image handles are created by `LoadImage`, which we can't call, we have to make use of an existing image handle -- the one passed into the bootloader's entry function. By modifying that image handle (after appropriately verifying the signature of the new data of course), we can repurpose the image handle for the next stage. See [shim] for an example of this scenario in action. [shim]: https://github.com/rhboot/shim/blob/4d64389c6c941d21548b06423b8131c872e3c3c7/pe.c#L1143
1 parent 8fbb126 commit 2c7e1e3

File tree

1 file changed

+30
-2
lines changed

1 file changed

+30
-2
lines changed

src/proto/loaded_image.rs

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ pub struct LoadedImage {
2727
load_options: *const Char16,
2828

2929
// Location where image was loaded
30-
image_base: usize,
30+
image_base: *const c_void,
3131
image_size: u64,
3232
image_code_type: MemoryType,
3333
image_data_type: MemoryType,
@@ -65,6 +65,34 @@ impl LoadedImage {
6565
}
6666
}
6767

68+
/// Set the image data address and size.
69+
///
70+
/// This is useful in the following scenario:
71+
/// 1. Secure boot is enabled, so images loaded with `LoadImage` must be
72+
/// signed with an appropriate key known to the firmware.
73+
/// 2. The bootloader has its own key embedded, and uses that key to
74+
/// verify the next stage. This key is not known to the firmware, so
75+
/// the next stage's image can't be loaded with `LoadImage`.
76+
/// 3. Since image handles are created by `LoadImage`, which we can't
77+
/// call, we have to make use of an existing image handle -- the one
78+
/// passed into the bootloader's entry function. By modifying that
79+
/// image handle (after appropriately verifying the signature of the
80+
/// new data), we can repurpose the image handle for the next stage.
81+
///
82+
/// See [shim] for an example of this scenario.
83+
///
84+
/// # Safety
85+
///
86+
/// This function takes `data` as a raw pointer because the data is not
87+
/// owned by `LoadedImage`. The caller must ensure that the memory lives
88+
/// long enough.
89+
///
90+
/// [shim]: https://github.com/rhboot/shim/blob/4d64389c6c941d21548b06423b8131c872e3c3c7/pe.c#L1143
91+
pub unsafe fn set_image(&mut self, data: *const c_void, size: u64) {
92+
self.image_base = data;
93+
self.image_size = size;
94+
}
95+
6896
/// Set the load options for the image. This can be used prior to
6997
/// calling `BootServices.start_image` to control the command line
7098
/// passed to the image.
@@ -80,7 +108,7 @@ impl LoadedImage {
80108
}
81109

82110
/// Returns the base address and the size in bytes of the loaded image.
83-
pub fn info(&self) -> (usize, u64) {
111+
pub fn info(&self) -> (*const c_void, u64) {
84112
(self.image_base, self.image_size)
85113
}
86114
}

0 commit comments

Comments
 (0)