@@ -919,6 +919,9 @@ fn build_object_for_triple_with_config(
919919
920920 let mut module = ObjectModule :: new ( builder) ;
921921 let ptr_ty = module. target_config ( ) . pointer_type ( ) ;
922+ let emit_kernel_handoff = emit_strings
923+ . iter ( )
924+ . any ( |s| s == "xdv-boot: handoff to kernel.bin" ) ;
922925
923926 // For bare-metal, we don't declare puts - kernel handles output differently
924927 let puts_func = if config. mode == BuildMode :: BareMetal {
@@ -1028,6 +1031,9 @@ fn build_object_for_triple_with_config(
10281031 break ;
10291032 }
10301033 }
1034+ if emit_kernel_handoff {
1035+ emit_boot_kernel_handoff_call ( & mut b, ptr_ty) ?;
1036+ }
10311037 }
10321038
10331039 let zero = b. ins ( ) . iconst ( cranelift_codegen:: ir:: types:: I32 , 0 ) ;
@@ -1047,6 +1053,33 @@ fn build_object_for_triple_with_config(
10471053 Ok ( obj. write ( ) . context ( "emit object" ) ?)
10481054}
10491055
1056+ /// In boot.bin mode, transfer control to preloaded kernel image.
1057+ /// Reads entry offset from boot record (0x0600 + 44), adds kernel image base
1058+ /// (0x00020000), and performs an indirect call.
1059+ fn emit_boot_kernel_handoff_call (
1060+ b : & mut FunctionBuilder < ' _ > ,
1061+ ptr_ty : cranelift_codegen:: ir:: Type ,
1062+ ) -> Result < ( ) > {
1063+ let bootrec_kernel_entry_ptr = b. ins ( ) . iconst ( ptr_ty, i64:: from ( 0x0600 + 44 ) ) ;
1064+ let kernel_entry_off_i32 = b. ins ( ) . load (
1065+ cranelift_codegen:: ir:: types:: I32 ,
1066+ cranelift_codegen:: ir:: MemFlags :: new ( ) ,
1067+ bootrec_kernel_entry_ptr,
1068+ 0 ,
1069+ ) ;
1070+ let kernel_entry_off_ptr = b. ins ( ) . uextend ( ptr_ty, kernel_entry_off_i32) ;
1071+ let kernel_image_base = b. ins ( ) . iconst ( ptr_ty, 0x0002_0000 ) ;
1072+ let kernel_entry_addr = b. ins ( ) . iadd ( kernel_image_base, kernel_entry_off_ptr) ;
1073+
1074+ let mut kernel_sig = Signature :: new ( b. func . signature . call_conv ) ;
1075+ kernel_sig
1076+ . returns
1077+ . push ( AbiParam :: new ( cranelift_codegen:: ir:: types:: I32 ) ) ;
1078+ let kernel_sig_ref = b. import_signature ( kernel_sig) ;
1079+ b. ins ( ) . call_indirect ( kernel_sig_ref, kernel_entry_addr, & [ ] ) ;
1080+ Ok ( ( ) )
1081+ }
1082+
10501083/// Kernel sector window reserved by xdv-os boot stage (128 * 512 bytes).
10511084const KERNEL_MAX_BYTES : usize = 128 * 512 ;
10521085/// VGA text mode base physical address.
0 commit comments