11use crate :: { actions, context:: SproutContext } ;
22use alloc:: rc:: Rc ;
3- use alloc:: string :: String ;
3+ use alloc:: vec :: Vec ;
44use alloc:: { format, vec} ;
55use anyhow:: { Context , Result } ;
66use edera_sprout_config:: actions:: chainload:: ChainloadConfiguration ;
@@ -12,74 +12,96 @@ use eficore::media_loader::{
1212 XEN_EFI_CONFIG_MEDIA_GUID , XEN_EFI_KERNEL_MEDIA_GUID , XEN_EFI_RAMDISK_MEDIA_GUID ,
1313 } ,
1414} ;
15+ use eficore:: platform:: tpm:: PlatformTpm ;
1516use uefi:: Guid ;
1617
17- /// Builds a configuration string for the Xen EFI stub using the specified `configuration`.
18- fn make_xen_config ( context : Rc < SproutContext > , configuration : & EderaConfiguration ) -> String {
19- let xen_options = combine_options ( context. stamp_iter ( configuration. xen_options . iter ( ) ) ) ;
20- let kernel_options = combine_options ( context. stamp_iter ( configuration. kernel_options . iter ( ) ) ) ;
21- build_xen_config ( & xen_options, & kernel_options)
22- }
23-
24- /// Register a media loader for some `text` with the vendor `guid`.
25- /// `what` should indicate some identifying value for error messages
26- /// like `config` or `kernel`.
27- /// Provides a [MediaLoaderHandle] that can be used to unregister the media loader.
28- fn register_media_loader_text ( guid : Guid , what : & str , text : String ) -> Result < MediaLoaderHandle > {
29- MediaLoaderHandle :: register ( guid, text. as_bytes ( ) . to_vec ( ) . into_boxed_slice ( ) )
30- . context ( format ! ( "unable to register {} media loader" , what) ) /* */
31- }
32-
33- /// Register a media loader for the file `path` with the vendor `guid`.
18+ /// Register a media loader for the provided `bytes` with the vendor `guid`.
3419/// `what` should indicate some identifying value for error messages
3520/// like `config` or `kernel`.
3621/// Provides a [MediaLoaderHandle] that can be used to unregister the media loader.
37- fn register_media_loader_file (
38- context : & Rc < SproutContext > ,
22+ fn register_media_loader_bytes (
3923 guid : Guid ,
4024 what : & str ,
41- path : & str ,
25+ bytes : Vec < u8 > ,
4226) -> Result < MediaLoaderHandle > {
43- // Stamp the path to the file.
27+ MediaLoaderHandle :: register ( guid, bytes. into_boxed_slice ( ) )
28+ . context ( format ! ( "unable to register {} media loader" , what) )
29+ }
30+
31+ /// Read the contents of the loader payload at `path` relative to the sprout image.
32+ /// `what` should indicate some identifying value for error messages
33+ /// like `kernel` or `initrd`.
34+ fn read_loader_payload ( context : & Rc < SproutContext > , what : & str , path : & str ) -> Result < Vec < u8 > > {
4435 let path = context. stamp ( path) ;
45- // Read the file contents.
46- let content =
47- eficore:: path:: read_file_contents ( Some ( context. root ( ) . loaded_image_path ( ) ?) , & path)
48- . context ( format ! ( "unable to read {} file" , what) ) ?;
49- // Register the media loader.
50- let handle = MediaLoaderHandle :: register ( guid, content. into_boxed_slice ( ) )
51- . context ( format ! ( "unable to register {} media loader" , what) ) ?;
52- Ok ( handle)
36+ eficore:: path:: read_file_contents ( Some ( context. root ( ) . loaded_image_path ( ) ?) , & path)
37+ . context ( format ! ( "unable to read {} file" , what) )
5338}
5439
5540/// Executes the edera action which will boot the Edera hypervisor with the specified
5641/// `configuration` and `context`. This action uses Edera-specific Xen EFI stub functionality.
5742pub fn edera ( context : Rc < SproutContext > , configuration : & EderaConfiguration ) -> Result < ( ) > {
58- // Build the Xen config file content for this configuration.
59- let config = make_xen_config ( context. clone ( ) , configuration) ;
43+ // Only register the initrd media loader if the user actually configured one.
44+ let xen_opts = combine_options ( context. stamp_iter ( configuration. xen_options . iter ( ) ) ) ;
45+ let dom0_args = combine_options ( context. stamp_iter ( configuration. kernel_options . iter ( ) ) ) ;
46+
47+ // Measure xen options and dom0 cmdline into PCR 12 in a fixed order.
48+ PlatformTpm :: log_event (
49+ PlatformTpm :: PCR_KERNEL_PARAMETERS ,
50+ xen_opts. as_bytes ( ) ,
51+ "sprout: xen options" ,
52+ )
53+ . context ( "unable to measure xen options into the TPM" ) ?;
54+ PlatformTpm :: log_event (
55+ PlatformTpm :: PCR_KERNEL_PARAMETERS ,
56+ dom0_args. as_bytes ( ) ,
57+ "sprout: dom0 cmdline" ,
58+ )
59+ . context ( "unable to measure dom0 cmdline into the TPM" ) ?;
60+
61+ // Build the Xen config text and register it as the config media loader. The
62+ // assembled text is a derived artifact, intentionally not measured.
63+ let config_handle = register_media_loader_bytes (
64+ XEN_EFI_CONFIG_MEDIA_GUID ,
65+ "config" ,
66+ build_xen_config ( & xen_opts, & dom0_args) . into_bytes ( ) ,
67+ )
68+ . context ( "unable to register config media loader" ) ?;
6069
61- // Register the media loader for the config.
62- let config = register_media_loader_text ( XEN_EFI_CONFIG_MEDIA_GUID , "config" , config)
63- . context ( "unable to register config media loader" ) ?;
70+ // Read the dom0 kernel, measure it into PCR 11, then register the kernel
71+ // media loader.
72+ let kernel_bytes = read_loader_payload ( & context, "kernel" , & configuration. kernel ) ?;
73+ PlatformTpm :: log_event (
74+ PlatformTpm :: PCR_KERNEL ,
75+ & kernel_bytes,
76+ "sprout: dom0 kernel" ,
77+ )
78+ . context ( "unable to measure dom0 kernel into the TPM" ) ?;
79+ let kernel_handle =
80+ register_media_loader_bytes ( XEN_EFI_KERNEL_MEDIA_GUID , "kernel" , kernel_bytes)
81+ . context ( "unable to register kernel media loader" ) ?;
6482
65- // Register the media loaders for the kernel.
66- let kernel = register_media_loader_file (
67- & context,
68- XEN_EFI_KERNEL_MEDIA_GUID ,
69- "kernel" ,
70- & configuration. kernel ,
83+ // Extend PCR 9 with the initrd bytes (empty when no initrd is
84+ // configured).
85+ let initrd_bytes = match empty_is_none ( configuration. initrd . as_ref ( ) ) {
86+ Some ( p) => read_loader_payload ( & context, "initrd" , p) ?,
87+ None => Vec :: new ( ) ,
88+ } ;
89+ PlatformTpm :: log_event (
90+ PlatformTpm :: PCR_INITRD ,
91+ & initrd_bytes,
92+ "sprout: dom0 initrd" ,
7193 )
72- . context ( "unable to register kernel media loader " ) ?;
94+ . context ( "unable to measure dom0 initrd into the TPM " ) ?;
7395
7496 // Create a vector of media loaders to drop them only after this function completes.
75- let mut media_loaders = vec ! [ config , kernel ] ;
97+ let mut media_loaders = vec ! [ config_handle , kernel_handle ] ;
7698
7799 // Register the initrd if it is provided.
78- if let Some ( initrd ) = empty_is_none ( configuration . initrd . as_ref ( ) ) {
79- let initrd =
80- register_media_loader_file ( & context , XEN_EFI_RAMDISK_MEDIA_GUID , "initrd" , initrd )
100+ if !initrd_bytes . is_empty ( ) {
101+ let initrd_handle =
102+ register_media_loader_bytes ( XEN_EFI_RAMDISK_MEDIA_GUID , "initrd" , initrd_bytes )
81103 . context ( "unable to register initrd media loader" ) ?;
82- media_loaders. push ( initrd ) ;
104+ media_loaders. push ( initrd_handle ) ;
83105 }
84106
85107 // Chainload to the Xen EFI stub.
0 commit comments