@@ -284,7 +284,7 @@ def fatal(msg):
284284 }
285285 #screen.disconnected {
286286 filter: grayscale(100%) brightness(0.7);
287- cursor: auto;
287+ cursor: auto !important ;
288288 }
289289 .error { color: #f87171 !important; border-color: #7f1d1d !important; }
290290 .toolbar {
@@ -2853,6 +2853,8 @@ def main():
28532853
28542854 ssh_passthrough = []
28552855 cpu_specified = False
2856+ serial_user_specified = False
2857+ vnc_user_specified = False
28562858
28572859
28582860 script_home = os .path .dirname (os .path .abspath (__file__ ))
@@ -2930,6 +2932,7 @@ def main():
29302932 i += 1
29312933 elif arg == "--vnc" :
29322934 config ['vnc' ] = args [i + 1 ]
2935+ vnc_user_specified = True
29332936 i += 1
29342937 elif arg in ["--res" , "--resolution" ]:
29352938 config ['resolution' ] = args [i + 1 ]
@@ -2951,6 +2954,7 @@ def main():
29512954 config ['whpx' ] = True
29522955 elif arg == "--serial" :
29532956 config ['serialport' ] = args [i + 1 ]
2957+ serial_user_specified = True
29542958 i += 1
29552959 elif arg == "--enable-ipv6" :
29562960 config ['enable_ipv6' ] = True
@@ -3384,13 +3388,15 @@ def find_image_link(releases, target_zst, target_xz):
33843388 else :
33853389 addr = "127.0.0.1"
33863390
3387- serial_bind_addr = "0.0.0.0" if config ['public' ] else "127.0.0.1"
3391+ if serial_user_specified :
3392+ serial_bind_addr = "0.0.0.0" if config ['public' ] else "127.0.0.1"
3393+ else :
3394+ serial_bind_addr = "127.0.0.1"
3395+
33883396 serial_chardev_def = None
33893397 serial_log_file = None
33903398
3391- if config ['console' ] and not is_vnc_console :
3392- serial_arg = "mon:stdio"
3393- else :
3399+ if is_vnc_console or serial_user_specified :
33943400 if not config ['serialport' ]:
33953401 serial_port = get_free_port (start = 7000 , end = 9000 )
33963402 if not serial_port :
@@ -3413,6 +3419,10 @@ def find_image_link(releases, target_zst, target_xz):
34133419 serial_arg = "tcp:{}:{},server,nowait" .format (serial_bind_addr , config ['serialport' ])
34143420
34153421 debuglog (config ['debug' ],"Serial console listening on {}:{} (tcp)" .format (serial_bind_addr , config ['serialport' ]))
3422+ elif config ['console' ]:
3423+ serial_arg = "mon:stdio"
3424+ else :
3425+ serial_arg = "none"
34163426
34173427 # QEMU Construction
34183428 bin_name = "qemu-system-x86_64"
@@ -3425,20 +3435,30 @@ def find_image_link(releases, target_zst, target_xz):
34253435 if not qemu_bin :
34263436 fatal ("QEMU binary '{}' not found. Please install QEMU or check PATH." .format (bin_name ))
34273437
3428- # Late detection of VNC Console requirement based on actual binary
3429- # If we are running a non-x86_64 QEMU (e.g. aarch64, riscv), default to VNC console
3430- if "x86_64" not in bin_name :
3431- if config .get ('vnc' ) != 'off' and not config .get ('vnc' ) and not is_vnc_console :
3432- debuglog (config ['debug' ], "Auto-enabling VNC Console for non-x86 arch ({})" .format (bin_name ))
3433- config ['vnc' ] = 'console'
3434- is_vnc_console = True
3438+ # VNC Console Auto-detection logic:
3439+ vnc_val = config .get ('vnc' , '' )
3440+ auto_reason = None
3441+
3442+ if not vnc_val and not is_vnc_console :
3443+ if config ['os' ] == "openindiana" :
3444+ # Rule for OpenIndiana: Default to 'console' if not specified.
3445+ auto_reason = "OpenIndiana (requires console for login display)"
3446+ elif "x86_64" not in bin_name :
3447+ # Rule for non-x86 architectures: Default to 'console' if not specified.
3448+ auto_reason = "non-x86 arch ({})" .format (bin_name )
34353449
3436- # If we previously defaulted to stdio, we must switch to TCP serial
3437- if serial_arg == "mon:stdio" :
3438- if not config ['serialport' ]:
3439- config ['serialport' ] = str (get_free_port (start = 7000 , end = 9000 ))
3440- serial_arg = "tcp:{}:{},server,nowait" .format (serial_bind_addr , config ['serialport' ])
3441- debuglog (config ['debug' ], "Switched serial to TCP for VNC Console: " + serial_arg )
3450+ if auto_reason :
3451+ debuglog (config ['debug' ], "Auto-enabling VNC Console: " + auto_reason )
3452+ config ['vnc' ] = 'console'
3453+ is_vnc_console = True
3454+
3455+ # If we previously defaulted to stdio or disabled serial, we must switch to TCP serial
3456+ if serial_arg in ["mon:stdio" , "none" ]:
3457+ if not config ['serialport' ]:
3458+ config ['serialport' ] = str (get_free_port (start = 7000 , end = 9000 ))
3459+ # In auto-enabling case, serial_bind_addr is already 127.0.0.1 because serial_user_specified is False
3460+ serial_arg = "tcp:{}:{},server,nowait" .format (serial_bind_addr , config ['serialport' ])
3461+ debuglog (config ['debug' ], "Switched serial to TCP for VNC Console: " + serial_arg )
34423462
34433463 # Acceleration determination
34443464 accel = "tcg"
@@ -3463,8 +3483,11 @@ def find_image_link(releases, target_zst, target_xz):
34633483 accel = "kvm"
34643484 else :
34653485 log ("Warning: /dev/kvm exists but is not writable. Falling back to TCG." )
3466- elif platform .system () == "Darwin" :
3467- accel = "hvf"
3486+ elif platform .system () == "Darwin" and hvf_supported ():
3487+ if config ['os' ] != "haiku" :
3488+ accel = "tcg"
3489+ else :
3490+ accel = "hvf"
34683491
34693492 # CPU optimization for TCG
34703493 if not cpu_specified and accel == "tcg" :
@@ -3515,6 +3538,11 @@ def find_image_link(releases, target_zst, target_xz):
35153538 "-drive" , "file={},format=qcow2,if={}" .format (qcow_name , disk_if )
35163539 ])
35173540
3541+ rtc_base = "utc"
3542+ if config ['os' ] in ["windows" , "haiku" ]:
3543+ rtc_base = "localtime"
3544+ args_qemu .extend (["-rtc" , "base={},clock=host,driftfix=slew" .format (rtc_base )])
3545+
35183546 if config ['snapshot' ]:
35193547 args_qemu .append ("-snapshot" )
35203548
@@ -3651,6 +3679,9 @@ def find_image_link(releases, target_zst, target_xz):
36513679 "-vga" , vga_type
36523680 ])
36533681
3682+ if accel == "kvm" :
3683+ args_qemu .extend (["-global" , "kvm-pit.lost_tick_policy=delay" ])
3684+
36543685 if config ['resolution' ]:
36553686 res_parts = config ['resolution' ].lower ().split ('x' )
36563687 if len (res_parts ) == 2 :
@@ -3722,6 +3753,14 @@ def find_image_link(releases, target_zst, target_xz):
37223753 if port is None :
37233754 fatal ("No available VNC display ports" )
37243755 disp = port - 5900
3756+
3757+ # Determine if VNC should listen on 0.0.0.0 or 127.0.0.1
3758+ # It should only listen on 0.0.0.0 if user specified --vnc (and it's not off/console) AND --public is set.
3759+ if vnc_user_specified and config ['vnc' ] not in ["off" , "console" ]:
3760+ vnc_addr = addr # Uses "" if --public else "127.0.0.1"
3761+ else :
3762+ vnc_addr = "127.0.0.1"
3763+
37253764 # Add audio support if the vnc driver is available (and not in console-only mode)
37263765 if not is_vnc_console and check_qemu_audio_backend (qemu_bin , "vnc" ):
37273766 if config ['arch' ] == "aarch64" :
@@ -3731,10 +3770,10 @@ def find_image_link(releases, target_zst, target_xz):
37313770 args_qemu .extend (["-device" , "intel-hda" , "-device" , "hda-duplex" ])
37323771 args_qemu .extend (["-audiodev" , "vnc,id=vnc_audio" ])
37333772 args_qemu .append ("-display" )
3734- args_qemu .append ("vnc={}:{},audiodev=vnc_audio" .format (addr , disp ))
3773+ args_qemu .append ("vnc={}:{},audiodev=vnc_audio" .format (vnc_addr , disp ))
37353774 else :
37363775 args_qemu .append ("-display" )
3737- args_qemu .append ("vnc={}:{}" .format (addr , disp ))
3776+ args_qemu .append ("vnc={}:{}" .format (vnc_addr , disp ))
37383777
37393778 # Use appropriate input devices for better VNC support
37403779 if not is_vnc_console :
@@ -3752,6 +3791,8 @@ def find_image_link(releases, target_zst, target_xz):
37523791 if not config ['qmon' ]:
37533792 config ['qmon' ] = str (get_free_port (start = 4444 , end = 4544 ))
37543793 debuglog (config ['debug' ], "Auto-selected QEMU monitor port: {}" .format (config ['qmon' ]))
3794+ else :
3795+ args_qemu .extend (["-display" , "none" ])
37553796
37563797 if config ['qmon' ]:
37573798 args_qemu .extend (["-monitor" , "tcp:127.0.0.1:{},server,nowait,nodelay" .format (config ['qmon' ])])
0 commit comments