@@ -8,7 +8,9 @@ use std::env;
8
8
use std:: ffi:: CStr ;
9
9
#[ cfg( target_os = "linux" ) ]
10
10
use std:: ffi:: CString ;
11
- #[ cfg( target_os = "linux" ) ]
11
+ #[ cfg( all( target_arch = "aarch64" , not( feature = "efi" ) ) ) ]
12
+ use std:: fs:: File ;
13
+ #[ cfg( not( feature = "efi" ) ) ]
12
14
use std:: os:: fd:: AsRawFd ;
13
15
use std:: os:: fd:: RawFd ;
14
16
use std:: path:: PathBuf ;
@@ -55,10 +57,10 @@ const MAX_ARGS: usize = 4096;
55
57
56
58
// krunfw library name for each context
57
59
#[ cfg( all( target_os = "linux" , not( feature = "amd-sev" ) ) ) ]
58
- const KRUNKW_NAME : & str = "libkrunfw.so.4" ;
60
+ const KRUNFW_NAME : & str = "libkrunfw.so.4" ;
59
61
#[ cfg( all( target_os = "linux" , feature = "amd-sev" ) ) ]
60
62
const KRUNFW_NAME : & str = "libkrunfw-sev.so.4" ;
61
- #[ cfg( target_os = "macos" ) ]
63
+ #[ cfg( all ( target_os = "macos" , not ( feature = "efi" ) ) ) ]
62
64
const KRUNFW_NAME : & str = "libkrunfw.4.dylib" ;
63
65
64
66
// Path to the init binary to be executed inside the VM.
@@ -106,6 +108,8 @@ struct ContextConfig {
106
108
gpu_shm_size : Option < usize > ,
107
109
enable_snd : bool ,
108
110
console_output : Option < PathBuf > ,
111
+ #[ cfg( not( feature = "efi" ) ) ]
112
+ external_kernel : bool ,
109
113
}
110
114
111
115
impl ContextConfig {
@@ -1029,6 +1033,77 @@ fn create_virtio_net(ctx_cfg: &mut ContextConfig, backend: VirtioNetBackend) {
1029
1033
. expect ( "Failed to create network interface" ) ;
1030
1034
}
1031
1035
1036
+ #[ cfg( any( target_arch = "x86_64" , feature = "tee" , feature = "efi" ) ) ]
1037
+ #[ allow( clippy:: format_collect) ]
1038
+ #[ allow( clippy:: missing_safety_doc) ]
1039
+ #[ no_mangle]
1040
+ pub unsafe extern "C" fn krun_set_kernel ( _ctx_id : u32 , _c_kernel_path : * const c_char ) -> i32 {
1041
+ -libc:: EOPNOTSUPP
1042
+ }
1043
+
1044
+ #[ cfg( all( target_arch = "aarch64" , not( feature = "efi" ) ) ) ]
1045
+ #[ allow( clippy:: format_collect) ]
1046
+ #[ allow( clippy:: missing_safety_doc) ]
1047
+ #[ no_mangle]
1048
+ pub unsafe extern "C" fn krun_set_kernel ( ctx_id : u32 , c_kernel_path : * const c_char ) -> i32 {
1049
+ let kernel_path = match CStr :: from_ptr ( c_kernel_path) . to_str ( ) {
1050
+ Ok ( path) => path,
1051
+ Err ( e) => {
1052
+ error ! ( "Error parsing kernel_path: {:?}" , e) ;
1053
+ return -libc:: EINVAL ;
1054
+ }
1055
+ } ;
1056
+
1057
+ let file = match File :: options ( ) . read ( true ) . write ( false ) . open ( kernel_path) {
1058
+ Ok ( file) => file,
1059
+ Err ( err) => {
1060
+ error ! ( "Error opening external kernel: {err}" ) ;
1061
+ return -libc:: EINVAL ;
1062
+ }
1063
+ } ;
1064
+
1065
+ let kernel_size = file. metadata ( ) . unwrap ( ) . len ( ) ;
1066
+
1067
+ let kernel_host_addr = unsafe {
1068
+ libc:: mmap (
1069
+ std:: ptr:: null_mut ( ) ,
1070
+ kernel_size as usize ,
1071
+ libc:: PROT_READ ,
1072
+ libc:: MAP_SHARED ,
1073
+ file. as_raw_fd ( ) ,
1074
+ 0_i64 ,
1075
+ )
1076
+ } ;
1077
+ if kernel_host_addr == libc:: MAP_FAILED {
1078
+ error ! ( "Can't load kernel into process map" ) ;
1079
+ return -libc:: EINVAL ;
1080
+ }
1081
+
1082
+ let kernel_bundle = KernelBundle {
1083
+ host_addr : kernel_host_addr as u64 ,
1084
+ guest_addr : 0x8000_0000 ,
1085
+ entry_addr : 0x8000_0000 ,
1086
+ size : kernel_size as usize ,
1087
+ } ;
1088
+
1089
+ match CTX_MAP . lock ( ) . unwrap ( ) . entry ( ctx_id) {
1090
+ Entry :: Occupied ( mut ctx_cfg) => {
1091
+ let ctx_cfg = ctx_cfg. get_mut ( ) ;
1092
+ if ctx_cfg. external_kernel {
1093
+ error ! ( "An extenal kernel was already configured" ) ;
1094
+ return -libc:: EINVAL ;
1095
+ } else {
1096
+ ctx_cfg. external_kernel = true ;
1097
+ }
1098
+ ctx_cfg. vmr . set_kernel_bundle ( kernel_bundle) . unwrap ( )
1099
+ }
1100
+ Entry :: Vacant ( _) => return -libc:: ENOENT ,
1101
+ }
1102
+
1103
+ KRUN_SUCCESS
1104
+ }
1105
+
1106
+ #[ cfg( not( feature = "efi" ) ) ]
1032
1107
unsafe fn load_krunfw_payload (
1033
1108
krunfw : & libloading:: Library ,
1034
1109
vmr : & mut VmResources ,
@@ -1072,15 +1147,15 @@ unsafe fn load_krunfw_payload(
1072
1147
host_addr : qboot_host_addr as u64 ,
1073
1148
size : qboot_size,
1074
1149
} ;
1075
- ctx_cfg . vmr . set_qboot_bundle ( qboot_bundle) . unwrap ( ) ;
1150
+ vmr. set_qboot_bundle ( qboot_bundle) . unwrap ( ) ;
1076
1151
1077
1152
let mut initrd_size: usize = 0 ;
1078
1153
let initrd_host_addr = unsafe { krunfw_get_initrd ( & mut initrd_size as * mut usize ) } ;
1079
1154
let initrd_bundle = InitrdBundle {
1080
1155
host_addr : initrd_host_addr as u64 ,
1081
1156
size : initrd_size,
1082
1157
} ;
1083
- ctx_cfg . vmr . set_initrd_bundle ( initrd_bundle) . unwrap ( ) ;
1158
+ vmr. set_initrd_bundle ( initrd_bundle) . unwrap ( ) ;
1084
1159
}
1085
1160
1086
1161
Ok ( ( ) )
@@ -1110,18 +1185,24 @@ pub extern "C" fn krun_start_enter(ctx_id: u32) -> i32 {
1110
1185
None => return -libc:: ENOENT ,
1111
1186
} ;
1112
1187
1113
- // The reference to the dynamically loaded library must be kept alive.
1114
- let krunfw = match unsafe { libloading:: Library :: new ( KRUNKW_NAME ) } {
1115
- Ok ( lib) => lib,
1116
- Err ( err) => {
1117
- eprintln ! ( "Can't load libkrunfw: {err}" ) ;
1188
+ #[ cfg( not( feature = "efi" ) ) ]
1189
+ let _krunfw = if !ctx_cfg. external_kernel {
1190
+ // The reference to the dynamically loaded library must be kept alive.
1191
+ let krunfw = match unsafe { libloading:: Library :: new ( KRUNFW_NAME ) } {
1192
+ Ok ( lib) => lib,
1193
+ Err ( err) => {
1194
+ eprintln ! ( "Can't load libkrunfw: {err}" ) ;
1195
+ return -libc:: ENOENT ;
1196
+ }
1197
+ } ;
1198
+ if let Err ( err) = unsafe { load_krunfw_payload ( & krunfw, & mut ctx_cfg. vmr ) } {
1199
+ eprintln ! ( "Can't load libkrunfw symbols: {err}" ) ;
1118
1200
return -libc:: ENOENT ;
1119
1201
}
1202
+ Some ( krunfw)
1203
+ } else {
1204
+ None
1120
1205
} ;
1121
- if let Err ( err) = unsafe { load_krunfw_payload ( & krunfw, & mut ctx_cfg. vmr ) } {
1122
- eprintln ! ( "Can't load libkrunfw symbols: {err}" ) ;
1123
- return -libc:: ENOENT ;
1124
- }
1125
1206
1126
1207
#[ cfg( feature = "blk" ) ]
1127
1208
for block_cfg in ctx_cfg. get_block_cfg ( ) {
0 commit comments