Skip to content

Commit 5abb3f1

Browse files
retragerbradford
authored andcommitted
efi: Fixup RuntimeServices pointers on SetVirtualAddressMap
When SetVirtualAddressMap is called, the RuntimeServices should be relocated from physical address to given virtual address. This requires our firmware to be relocatable. It's still hard to implement it with current design. In this commit, it just convert the RuntimeServices function pointers to the virtual address of the function that just returns EFI_UNSUPPORTED to avoid access to the physical assresses at Runtime phase. Signed-off-by: Akira Moroo <[email protected]>
1 parent dd5d187 commit 5abb3f1

File tree

1 file changed

+152
-102
lines changed

1 file changed

+152
-102
lines changed

src/efi/mod.rs

Lines changed: 152 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
// See the License for the specific language governing permissions and
1313
// limitations under the License.
1414

15-
use core::ffi::c_void;
15+
use core::{ffi::c_void, mem::transmute};
1616

1717
use atomic_refcell::AtomicRefCell;
1818
use r_efi::{
@@ -52,11 +52,142 @@ struct HandleWrapper {
5252

5353
pub static ALLOCATOR: AtomicRefCell<Allocator> = AtomicRefCell::new(Allocator::new());
5454

55+
static mut RS: efi::RuntimeServices = efi::RuntimeServices {
56+
hdr: efi::TableHeader {
57+
signature: efi::RUNTIME_SERVICES_SIGNATURE,
58+
revision: efi::RUNTIME_SERVICES_REVISION,
59+
header_size: core::mem::size_of::<efi::RuntimeServices>() as u32,
60+
crc32: 0, // TODO
61+
reserved: 0,
62+
},
63+
get_time,
64+
set_time,
65+
get_wakeup_time,
66+
set_wakeup_time,
67+
set_virtual_address_map,
68+
convert_pointer,
69+
get_variable,
70+
get_next_variable_name,
71+
set_variable,
72+
get_next_high_mono_count,
73+
reset_system,
74+
update_capsule,
75+
query_capsule_capabilities,
76+
query_variable_info,
77+
};
78+
79+
static mut BS: efi::BootServices = efi::BootServices {
80+
hdr: efi::TableHeader {
81+
signature: efi::BOOT_SERVICES_SIGNATURE,
82+
revision: efi::BOOT_SERVICES_REVISION,
83+
header_size: core::mem::size_of::<efi::BootServices>() as u32,
84+
crc32: 0, // TODO
85+
reserved: 0,
86+
},
87+
raise_tpl,
88+
restore_tpl,
89+
allocate_pages,
90+
free_pages,
91+
get_memory_map,
92+
allocate_pool,
93+
free_pool,
94+
create_event,
95+
set_timer,
96+
wait_for_event,
97+
signal_event,
98+
close_event,
99+
check_event,
100+
install_protocol_interface,
101+
reinstall_protocol_interface,
102+
uninstall_protocol_interface,
103+
handle_protocol,
104+
register_protocol_notify,
105+
locate_handle,
106+
locate_device_path,
107+
install_configuration_table,
108+
load_image,
109+
start_image,
110+
exit,
111+
unload_image,
112+
exit_boot_services,
113+
get_next_monotonic_count,
114+
stall,
115+
set_watchdog_timer,
116+
connect_controller,
117+
disconnect_controller,
118+
open_protocol,
119+
close_protocol,
120+
open_protocol_information,
121+
protocols_per_handle,
122+
locate_handle_buffer,
123+
locate_protocol,
124+
install_multiple_protocol_interfaces,
125+
uninstall_multiple_protocol_interfaces,
126+
calculate_crc32,
127+
copy_mem,
128+
set_mem,
129+
create_event_ex,
130+
reserved: core::ptr::null_mut(),
131+
};
132+
133+
static mut ST: efi::SystemTable = efi::SystemTable {
134+
hdr: efi::TableHeader {
135+
signature: efi::SYSTEM_TABLE_SIGNATURE,
136+
revision: (2 << 16) | (80),
137+
header_size: core::mem::size_of::<efi::SystemTable>() as u32,
138+
crc32: 0, // TODO
139+
reserved: 0,
140+
},
141+
firmware_vendor: core::ptr::null_mut(), // TODO,
142+
firmware_revision: 0,
143+
console_in_handle: console::STDIN_HANDLE,
144+
con_in: core::ptr::null_mut(),
145+
console_out_handle: console::STDOUT_HANDLE,
146+
con_out: core::ptr::null_mut(),
147+
standard_error_handle: console::STDERR_HANDLE,
148+
std_err: core::ptr::null_mut(),
149+
runtime_services: core::ptr::null_mut(),
150+
boot_services: core::ptr::null_mut(),
151+
number_of_table_entries: 0,
152+
configuration_table: core::ptr::null_mut(),
153+
};
154+
55155
static mut BLOCK_WRAPPERS: block::BlockWrappers = block::BlockWrappers {
56156
wrappers: [core::ptr::null_mut(); 16],
57157
count: 0,
58158
};
59159

160+
unsafe fn fixup_at_virtual(offset: u64) {
161+
let mut st = &mut ST;
162+
let mut rs = &mut RS;
163+
164+
let ptr = offset + (rs as *const efi::RuntimeServices) as u64;
165+
st.runtime_services = transmute(ptr);
166+
167+
let ct = st.configuration_table;
168+
let ptr = offset + (ct as *const efi::ConfigurationTable) as u64;
169+
st.configuration_table = transmute(ptr);
170+
171+
let ptr = offset + (not_available as *const ()) as u64;
172+
rs.get_time = transmute(ptr);
173+
rs.set_time = transmute(ptr);
174+
rs.get_wakeup_time = transmute(ptr);
175+
rs.set_wakeup_time = transmute(ptr);
176+
rs.set_virtual_address_map = transmute(ptr);
177+
rs.convert_pointer = transmute(ptr);
178+
rs.get_variable = transmute(ptr);
179+
rs.set_variable = transmute(ptr);
180+
rs.get_next_variable_name = transmute(ptr);
181+
rs.reset_system = transmute(ptr);
182+
rs.update_capsule = transmute(ptr);
183+
rs.query_capsule_capabilities = transmute(ptr);
184+
rs.query_variable_info = transmute(ptr);
185+
}
186+
187+
pub extern "win64" fn not_available() -> Status {
188+
Status::UNSUPPORTED
189+
}
190+
60191
pub extern "win64" fn get_time(_: *mut Time, _: *mut TimeCapabilities) -> Status {
61192
Status::DEVICE_ERROR
62193
}
@@ -89,6 +220,16 @@ pub extern "win64" fn set_virtual_address_map(
89220
core::slice::from_raw_parts_mut(descriptors as *mut alloc::MemoryDescriptor, count)
90221
};
91222

223+
for descriptor in descriptors.iter() {
224+
if descriptor.r#type == MemoryType::RuntimeServicesCode as u32 {
225+
let offset = descriptor.virtual_start - descriptor.physical_start;
226+
unsafe {
227+
fixup_at_virtual(offset);
228+
}
229+
break;
230+
}
231+
}
232+
92233
ALLOCATOR.borrow_mut().update_virtual_addresses(descriptors)
93234
}
94235

@@ -627,84 +768,6 @@ pub fn efi_exec(
627768
fs: &crate::fat::Filesystem,
628769
block: *const crate::block::VirtioBlockDevice,
629770
) {
630-
let mut rs = efi::RuntimeServices {
631-
hdr: efi::TableHeader {
632-
signature: efi::RUNTIME_SERVICES_SIGNATURE,
633-
revision: efi::RUNTIME_SERVICES_REVISION,
634-
header_size: core::mem::size_of::<efi::RuntimeServices>() as u32,
635-
crc32: 0, // TODO
636-
reserved: 0,
637-
},
638-
get_time,
639-
set_time,
640-
get_wakeup_time,
641-
set_wakeup_time,
642-
set_virtual_address_map,
643-
convert_pointer,
644-
get_variable,
645-
get_next_variable_name,
646-
set_variable,
647-
get_next_high_mono_count,
648-
reset_system,
649-
update_capsule,
650-
query_capsule_capabilities,
651-
query_variable_info,
652-
};
653-
654-
let mut bs = efi::BootServices {
655-
hdr: efi::TableHeader {
656-
signature: efi::BOOT_SERVICES_SIGNATURE,
657-
revision: efi::BOOT_SERVICES_REVISION,
658-
header_size: core::mem::size_of::<efi::BootServices>() as u32,
659-
crc32: 0, // TODO
660-
reserved: 0,
661-
},
662-
raise_tpl,
663-
restore_tpl,
664-
allocate_pages,
665-
free_pages,
666-
get_memory_map,
667-
allocate_pool,
668-
free_pool,
669-
create_event,
670-
set_timer,
671-
wait_for_event,
672-
signal_event,
673-
close_event,
674-
check_event,
675-
install_protocol_interface,
676-
reinstall_protocol_interface,
677-
uninstall_protocol_interface,
678-
handle_protocol,
679-
register_protocol_notify,
680-
locate_handle,
681-
locate_device_path,
682-
install_configuration_table,
683-
load_image,
684-
start_image,
685-
exit,
686-
unload_image,
687-
exit_boot_services,
688-
get_next_monotonic_count,
689-
stall,
690-
set_watchdog_timer,
691-
connect_controller,
692-
disconnect_controller,
693-
open_protocol,
694-
close_protocol,
695-
open_protocol_information,
696-
protocols_per_handle,
697-
locate_handle_buffer,
698-
locate_protocol,
699-
install_multiple_protocol_interfaces,
700-
uninstall_multiple_protocol_interfaces,
701-
calculate_crc32,
702-
copy_mem,
703-
set_mem,
704-
create_event_ex,
705-
reserved: core::ptr::null_mut(),
706-
};
707-
708771
let vendor_data = 0u32;
709772
let acpi_rsdp_ptr = info.rsdp_addr();
710773

@@ -736,27 +799,14 @@ pub fn efi_exec(
736799

737800
let mut stdin = console::STDIN;
738801
let mut stdout = console::STDOUT;
739-
let mut st = efi::SystemTable {
740-
hdr: efi::TableHeader {
741-
signature: efi::SYSTEM_TABLE_SIGNATURE,
742-
revision: efi::SYSTEM_TABLE_REVISION_2_70,
743-
header_size: core::mem::size_of::<efi::SystemTable>() as u32,
744-
crc32: 0, // TODO
745-
reserved: 0,
746-
},
747-
firmware_vendor: core::ptr::null_mut(), // TODO,
748-
firmware_revision: 0,
749-
console_in_handle: console::STDIN_HANDLE,
750-
con_in: &mut stdin,
751-
console_out_handle: console::STDOUT_HANDLE,
752-
con_out: &mut stdout,
753-
standard_error_handle: console::STDERR_HANDLE,
754-
std_err: &mut stdout,
755-
runtime_services: &mut rs,
756-
boot_services: &mut bs,
757-
number_of_table_entries: 1,
758-
configuration_table: &mut ct,
759-
};
802+
let mut st = unsafe { &mut ST };
803+
st.con_in = &mut stdin;
804+
st.con_out = &mut stdout;
805+
st.std_err = &mut stdout;
806+
st.runtime_services = unsafe { &mut RS };
807+
st.boot_services = unsafe { &mut BS };
808+
st.number_of_table_entries = 1;
809+
st.configuration_table = &mut ct;
760810

761811
populate_allocator(info, loaded_address, loaded_size);
762812

@@ -801,7 +851,7 @@ pub fn efi_exec(
801851
proto: LoadedImageProtocol {
802852
revision: r_efi::protocols::loaded_image::REVISION,
803853
parent_handle: 0 as Handle,
804-
system_table: &mut st,
854+
system_table: &mut *st,
805855
device_handle: &wrapped_fs as *const _ as Handle,
806856
file_path: &mut file_paths[0].device_path, // Pointer to first path entry
807857
load_options_size: 0,
@@ -818,5 +868,5 @@ pub fn efi_exec(
818868
let ptr = address as *const ();
819869
let code: extern "win64" fn(Handle, *mut efi::SystemTable) -> Status =
820870
unsafe { core::mem::transmute(ptr) };
821-
(code)((&image as *const _) as Handle, &mut st);
871+
(code)((&image as *const _) as Handle, &mut *st);
822872
}

0 commit comments

Comments
 (0)