#!/usr/bin/python # -*- coding: utf-8 -*- import os import string try: from subprocess import getoutput except ImportError: from commands import getoutput import shutil import sys # Variables xorgfile = "/etc/X11/xorg.conf" xorgfile_backup = "/etc/X11/xorg.conf.sabayon" lspci = '/usr/sbin/lspci' nvidia_settings = "/usr/share/applications/nvidia-settings.desktop" device_id_prefix = "SabayonVga" argb_visual_prefix = "--argbvisuals--" screen_layout_sections = [] device_sections = [] xorg_conf_structure = """ Section "Module" SubSection "extmod" Option "omit xfree86-dga" EndSubSection Load "i2c" Load "ddc" Load "vbe" Load "dri" Load "glx" Load "synaptics" EndSection Section "ServerFlags" Option "AllowMouseOpenFail" "true" EndSection Section "Monitor" Identifier "Generic Monitor" VertRefresh 43 - 60 HorizSync 28 - 80 EndSection __device_section__ __screen_section__ Section "DRI" Mode 0666 EndSection Section "ServerLayout" Identifier "Main Layout" __screen_layout_section__ EndSection Section "Extensions" #Option "Composite" "Enable" EndSection """ screen_sections = [] screen_section = """ Section "Screen" Identifier "Screen __screen_id__" Device "%s__screen_id__" Monitor "Generic Monitor" %sOption "AddARGBGLXVisuals" "true" DefaultDepth 24 SubSection "Display" Depth 8 ViewPort 0 0 #Modes "1024x768" "800x600" "640x480" EndSubsection SubSection "Display" Depth 16 ViewPort 0 0 #Modes "1024x768" "800x600" "640x480" EndSubsection SubSection "Display" Depth 24 ViewPort 0 0 #Modes "1024x768" "800x600" "640x480" EndSubsection EndSection """ % (device_id_prefix, argb_visual_prefix,) # cmdlines options = sys.argv[1:] dryrun = False noproprietary = False nvidia_forcefail = False nvidia_disablelegacy = False legacy = False noopengl = False noexa = False livecd = False steps = [] forced_xdriver = '' current_arch = os.uname()[4] if current_arch == "x86_64": ld_arch = "elf_x86_64" else: ld_arch = "elf_i386" fglrx_supported = sorted(getoutput("""/sbin/modinfo fglrx | grep alias | grep pci | cut -d':' -f 3 | cut -d'*' -f 1 | sed 's/.*1002d//' | sed 's/^0000//' | sed 's/sv$//'""").lower().split()) nvidia_71xx_supported = ['0020', '0028', '0029', '002c', '002d', '00a0', '0100', '0101', '0103', '0150', '0151', '0152', '0153'] nvidia_96xx_supported = ['0110', '0111', '0112', '0113', '0170', '0171', '0172', '0173', '0174', '0175', '0176', '0177', '0178', '0179', '017a', '017c', '017d', '0181', '0182', '0183', '0185', '0188', '018a', '018b', '018c', '01a0', '01f0', '0200', '0201', '0202', '0203', '0250', '0251', '0253', '0258', '0259', '025b', '0280', '0281', '0282', '0286', '0288', '0289', '028c'] nvidia_173xx_supported = ['00fa', '00fb', '00fc', '00fd', '00fe', '0301', '0302', '0308', '0309', '0311', '0312', '0314', '031a', '031b', '031c', '0320', '0321', '0322', '0323', '0324', '0325', '0326', '0327', '0328', '032a', '032b', '032c', '032d', '0330', '0331', '0332', '0333', '0334', '0338', '033f', '0341', '0342', '0343', '0344', '0347', '0348', '034c', '034e'] savage_supported = ['8a20', '8a21', '8a22', '9102', '8c10', '8c11', '8c12', '8c13', '8c22', '8c24', '8c26', '8c2a', '8c2b', '8c2c', '8c2d', '8c2e', '8c2f', '8a25', '8a26', '8d01', '8d02', '8d03', '8d04'] unichrome_supported = ['3108', '3118', '3157', '3343', '3344', '7205'] lspci_output = '' for option in options: if option == "--dry-run": dryrun = True elif option.startswith('--with-lspci=') and len(option.split("=")) >= 2: option = option.split("=")[1:] option = string.join(option,"=") if option.startswith('"'): option = option[1:] if option.startswith("'"): option = option[1:] if option.endswith("'"): option = option[:len(option)-1] if option.endswith('"'): option = option[:len(option)-1] lspci_output = option elif option.startswith('--forced-xdriver=') and len(option.split("=")) == 2: forced_xdriver = option.split("=")[1] elif option == "--noopengl": noopengl = True elif option == "--noexa": noexa = True if not lspci_output: lspci_output = getoutput(lspci+' -mm -n') # parse cmdline f = open("/proc/cmdline","r") cmdline = f.readline().split() f.close() for cmd in cmdline: if cmd == "noproprietary": noproprietary = True elif cmd == "nvidia=forcefail": nvidia_forcefail = True elif cmd == "nvidia=disablelegacy": nvidia_disablelegacy = True elif cmd == "legacy": legacy = True elif cmd == "noopengl": noopengl = True elif cmd == "cdroot": livecd = True elif cmd == "noexa": noexa = True elif cmd.startswith("xdriver=") and (len(cmd.split("=")) == 2): if (not forced_xdriver): forced_xdriver = cmd.split("=")[1] # --forced-xdriver= owns # Functions def remove_proprietary_opengl(): if (not dryrun): os.system(''' mount -t tmpfs none /usr/lib/opengl/ati &> /dev/null mount -t tmpfs none /usr/lib/opengl/nvidia &> /dev/null sed -i '/LIBGL_DRIVERS_PATH/ s/.*//' /etc/profile.env ''') fix_possible_opengl_misconfiguration('xorg-x11') else: print("I was about to remove proprietary OpenGL libraries") def remove_tar_members_from_sys(tarpath): import tarfile tar = tarfile.open(tarpath) for el in sorted(tar.getnames(), reverse = True): el = "/%s" % (el,) if os.path.isfile(el): try: os.remove(el) except OSError: pass if os.path.isdir(el): try: os.rmdir(el) except OSError: pass tar.close() def check_if_driver_is_available(xdriver): if os.path.isfile('/usr/lib/xorg/modules/drivers/'+xdriver+'_drv.so'): print("check_if_driver_is_available for "+xdriver+": available") return True print("check_if_driver_is_available for "+xdriver+": not available") return False def check_if_proprietary_driver_system_is_healthy(kernelmod): rc = os.system('modprobe '+kernelmod+' &> /dev/null') if (rc == 0): if kernelmod == "nvidia": if os.path.exists('/usr/lib/opengl/nvidia/lib'): print("check_if_proprietary_driver_system_is_healthy: nvidia healthy") return True print("check_if_proprietary_driver_system_is_healthy: nvidia NOT healthy") return False if kernelmod == "fglrx": if os.path.exists('/usr/lib/opengl/ati/lib'): print("check_if_proprietary_driver_system_is_healthy: ati healthy") return True print("check_if_proprietary_driver_system_is_healthy: ati NOT healthy") return False else: return False def deploy_nvidia_xxxxxx_drivers(ver): if (not dryrun): # are they available ? we're on livecd... if not os.path.isdir("/install-data/drivers"): print("No /install-data/drivers available") return False packages = os.listdir("/install-data/drivers") packages = [x for x in packages if x.startswith("x11-drivers:nvidia-drivers-"+ver) and x.endswith(".tbz2")] if not packages: return False package_file = "/install-data/drivers/"+packages[0] if not os.path.isfile(package_file): print(package_file+" does not exist???") return False from entropy.client.interfaces import Client from entropy.const import const_kill_threads Equo = Client() # prepare system idpackage, result = Equo.installed_repository().atomMatch('x11-drivers/nvidia-drivers') if idpackage != -1: content = Equo.installed_repository().retrieveContent(idpackage) for myfile in content: if os.path.isfile(myfile) and os.access(myfile,os.W_OK): try: os.remove(myfile) except OSError: pass del content if hasattr(Equo,'destroy'): Equo.destroy() del Equo # Entropy Cacher still running const_kill_threads() # remove old garbage - copy over - create module os.system("tar xjf %s -C / &> /dev/null" % (package_file,)) # try to check driver status now rc = check_if_proprietary_driver_system_is_healthy("nvidia") if not rc: remove_tar_members_from_sys(package_file) return rc else: print("I was about to run deploy_nvidia_xxxxxx_drivers, ver: %s" % (ver,)) return False def set_xorg_device(xdriver, cardnum, total_cards, bus_id): if (xdriver not in ("nvidia", "fglrx",)) and \ (not check_if_driver_is_available(xdriver)): xdriver = "vesa" # fallback to vesa bus_id_mark = '#' if total_cards > 1: bus_id_mark = '' device_sections.append(""" Section "Device" Identifier "%s%s" Driver "%s" %sBusID "%s" #Option "RenderAccel" "on" #Option "XAANoOffscreenPixmaps" #Option "BusType" "PCI" #Option "ColorTiling" "on" #Option "EnablePageFlip" "on" Option "UseEvents" "True" Option "LogoPath" "/usr/share/backgrounds/sabayonlinux-nvidia.png" EndSection """ % (device_id_prefix,cardnum,xdriver,bus_id_mark,bus_id,) ) my_screen_section = screen_section.replace('__screen_id__',str(cardnum)) # setup Option AddARGBVisuals # especially needed for legacy nvidia drivers, but works # on all of them if xdriver == "nvidia": my_screen_section = my_screen_section.replace(argb_visual_prefix,'') else: my_screen_section = my_screen_section.replace(argb_visual_prefix,'#') screen_sections.append(my_screen_section) screen_layout_sections.append('Screen %s "Screen %s"' % (cardnum,cardnum,)) def opengl_activate(profile): current = opengl_show() default_profile = "xorg-x11" if (not dryrun): if (livecd): if (profile != default_profile) or (profile == default_profile and current != default_profile): os.system("opengl-activator "+profile+" &> /dev/null") else: os.system("eselect opengl set "+profile+" &> /dev/null") else: print("I was about to set opengl subsystem to: "+profile) def opengl_show(): if livecd: return getoutput("opengl-activator show").split("\n")[0].strip() return getoutput("eselect opengl show").split("\n")[0].strip() def fix_possible_opengl_misconfiguration(profile): # get current subsystem current = opengl_show() if (not dryrun): if (profile in ("ati","nvidia","xorg-x11")) and (profile != current): if profile == "ati" or profile == "nvidia": os.system(""" umount /usr/lib/opengl/"""+profile+""" &> /dev/null umount /usr/lib/opengl/"""+profile+""" &> /dev/null """) opengl_activate(profile) else: print("I was about to fix OpenGL subsystem to: "+profile+" while the current implementation is: "+current) def copy_nvidia_settings_on_desktop(): if os.path.isfile(nvidia_settings): homes = os.listdir("/home") homes = [x for x in homes if os.path.isdir("/home/"+x+"/Desktop")] for home in homes: try: full_home = os.path.join("/home", home) st = os.stat(full_home) dest_path = "/home/" + home + "/Desktop/" + os.path.basename(nvidia_settings) shutil.copy2(nvidia_settings, dest_path) os.chmod(dest_path, 0o755) os.chown(dest_path, st.st_uid, st.st_gid) except: pass if os.path.isdir("/etc/skel/Desktop"): dest_path = "/etc/skel/Desktop/"+os.path.basename(nvidia_settings) shutil.copy2(nvidia_settings, dest_path) os.chmod(dest_path, 0o755) def copy_ati_settings_on_desktop(): desktop_files = getoutput('equo query files ati-drivers --quiet | grep ".desktop"').split("\n") desktop_files = [x for x in desktop_files if os.path.isfile(x)] print("copy_ati_settings_on_desktop: found files: "+str(desktop_files)) for ati_settings in desktop_files: homes = os.listdir("/home") homes = [x for x in homes if os.path.isdir("/home/"+x+"/Desktop")] for home in homes: try: full_home = os.path.join("/home", home) st = os.stat(full_home) dest_path = "/home/"+home+"/Desktop/"+os.path.basename(ati_settings) shutil.copy2(ati_settings, dest_path) os.chmod(dest_path, 0o755) os.chown(dest_path, st.st_uid, st.st_gid) except: pass if os.path.isdir("/etc/skel/Desktop"): dest_path = "/etc/skel/Desktop/"+os.path.basename(ati_settings) shutil.copy2(nvidia_settings, dest_path) os.chmod(dest_path, 0o755) def generate_nvidia_steps(videocard, cardnumber, total_cards, bus_id): comp_id, card_id = extract_pci_ids(videocard) drv_string = '' done_legacy = False if card_id in nvidia_173xx_supported: print("NVIDIA 173.xx driver selected") drv_string = "17x.xx.xx" if livecd: rc = deploy_nvidia_xxxxxx_drivers("17") if rc: print("NVIDIA 17x.xx deployed correctly") done_legacy = True elif card_id in nvidia_96xx_supported: print("NVIDIA 96.xx driver selected") drv_string = "9x.xx.xx" if livecd: rc = deploy_nvidia_xxxxxx_drivers("9") if rc: print("NVIDIA 96.xx deployed correctly") done_legacy = True elif card_id in nvidia_71xx_supported: print("NVIDIA 7x.xx driver selected") drv_string = "7x.xx.xx" if livecd: rc = deploy_nvidia_xxxxxx_drivers("7") if rc: print("NVIDIA 7x.xx deployed correctly") done_legacy = True else: print("latest and greatest NVIDIA driver selected or unsupported") if check_if_proprietary_driver_system_is_healthy("nvidia"): print("NVIDIA proprietary driver %s is loaded" % (drv_string,)) if done_legacy: # then activate nvidia opengl subsystem after resetting it steps.append(('opengl_activate','xorg-x11')) steps.append(('opengl_activate','nvidia')) os.makedirs("/lib/nvidia/legacy") f = open("/lib/nvidia/legacy/running","w") f.write("NVIDIA %s\n" % (drv_string,)) f.flush() f.close() steps.append(('set_xorg_device','nvidia',cardnumber,total_cards,bus_id,)) steps.append(('fix_possible_opengl_misconfiguration','nvidia')) steps.append(('copy_nvidia_settings_on_desktop',)) else: steps.append(('fix_possible_opengl_misconfiguration','nvidia')) steps.append(('copy_nvidia_settings_on_desktop',)) steps.append(('opengl_activate','nvidia')) steps.append(('set_xorg_device','nvidia',cardnumber,total_cards,bus_id,)) else: print("NVIDIA drivers couldn't be loaded, switchting to nv driver") steps.append(('opengl_activate','xorg-x11')) steps.append(('set_xorg_device','nv',cardnumber,total_cards,bus_id,)) def generate_generic_steps(): if noopengl: return steps.append(('remove_proprietary_opengl',)) steps.append(('opengl_activate','xorg-x11',)) def drop_kernel_mod(kmod): return os.system("modprobe -r %s &> /dev/null" % (kmod,)) def extract_pci_ids(videocard_str): videocard_split = [x.strip() for x in videocard_str.strip().split('"') \ if x.strip()] try: card_id = videocard_split[3].split()[-1].lower().strip("[]") except IndexError: card_id = None try: company_id = videocard_split[2].split()[-1].lower().strip("[]") except IndexError: company_id = None return company_id, card_id def extract_vga_cards(lspci_list): cards = [] for item in lspci_list: try: class_type = item.split()[1].strip('"') if class_type == "0300": cards.append(item) except IndexError: continue return cards ### APPLICATION # Create videocards list videocards = extract_vga_cards(lspci_output.split("\n")) # Run the program cardnumber = -1 total_cards = len(videocards) forced_monitor_modes = False for videocard in videocards: # setup card number cardnumber += 1 print("Card Number: "+str(cardnumber)) try: bus_id = "PCI:%s" % (videocard.split()[0].split(".",1)[0],) except (IndexError,ValueError,TypeError,): bus_id = None steps = [] if forced_xdriver: print("You have chosen to force X driver: "+forced_xdriver) if forced_xdriver == "fglrx": if noopengl or check_if_proprietary_driver_system_is_healthy("fglrx") or noproprietary: steps.append(('opengl_activate','xorg-x11')) forced_xdriver = "ati" steps.append(('drop_kernel_mod','fglrx',)) else: steps.append(('fix_possible_opengl_misconfiguration','ati')) steps.append(('copy_ati_settings_on_desktop',)) steps.append(('opengl_activate','ati')) elif forced_xdriver == "nvidia" and (not noproprietary): generate_nvidia_steps(videocard, cardnumber, total_cards, bus_id) elif forced_xdriver == "vesa": forced_monitor_modes = True elif forced_xdriver == "sisusb": steps.append(('remove_proprietary_opengl',)) else: generate_generic_steps() steps.append(('set_xorg_device',forced_xdriver,cardnumber,total_cards,bus_id,)) else: company_id, card_id = extract_pci_ids(videocard) print("[%s] company_id: %s | card_id: %s" % (cardnumber, company_id, card_id,)) if os.path.isfile('/sys/module/sisusbvga'): generate_generic_steps() steps.append(('set_xorg_device','sisusb',cardnumber,total_cards,bus_id,)) print("SiS USB!") elif company_id == "10c8": generate_generic_steps() steps.append(('set_xorg_device','neomagic',cardnumber,total_cards,bus_id,)) print("Neomagic!") elif company_id == "1078": # Cyrix generate_generic_steps() print("Cyrix!") elif company_id == "105d": # Number 9 generate_generic_steps() steps.append(('set_xorg_device','i128',cardnumber,total_cards,bus_id,)) print("i128!") elif company_id == "1163": # Rendition generate_generic_steps() steps.append(('set_xorg_device','rendition',cardnumber,total_cards,bus_id,)) print("Rendition!") elif company_id == "100c": # Tseng! generate_generic_steps() steps.append(('set_xorg_device','tseng',cardnumber,total_cards,bus_id,)) print("Tseng!") elif company_id == "121a": # 3dfx generate_generic_steps() steps.append(('set_xorg_device','tdfx',cardnumber,total_cards,bus_id,)) print("3Dfx!") elif company_id == "1023": # Trident generate_generic_steps() steps.append(('set_xorg_device','trident',cardnumber,total_cards,bus_id,)) print("Trident!") elif company_id == "102b": # Matrox generate_generic_steps() steps.append(('set_xorg_device','mga',cardnumber,total_cards,bus_id,)) print("Matrox!") elif company_id == "1013": # Cirrus generate_generic_steps() steps.append(('set_xorg_device','cirrus',cardnumber,total_cards,bus_id,)) print("Cirrus!") elif company_id == "1039": # SiS generate_generic_steps() steps.append(('set_xorg_device','sis',cardnumber,total_cards,bus_id,)) print("SiS!") elif company_id == "18ca": # XGI generate_generic_steps() steps.append(('set_xorg_device','sis',cardnumber,total_cards,bus_id,)) print("XGI Volari!") elif company_id in ["15ad", "fffe"]: # VMware generate_generic_steps() steps.append(('set_xorg_device','vmware',cardnumber,total_cards,bus_id,)) print("VMware!") elif company_id == "80ee": # VirtualBox, InnoTek generate_generic_steps() steps.append(('set_xorg_device','vboxvideo',cardnumber,total_cards,bus_id,)) print("VirtualBox!") elif company_id == "5333": generate_generic_steps() if card_id in savage_supported: steps.append(('set_xorg_device','savage',cardnumber,total_cards,bus_id,)) print("Savage!") else: steps.append(('set_xorg_device','s3virge',cardnumber,total_cards,bus_id,)) print("S3Virge!") elif company_id == "1106": # Via Tech. generate_generic_steps() if card_id in unichrome_supported: if check_if_driver_is_available('openchrome'): steps.append(('set_xorg_device','openchrome',cardnumber,total_cards,bus_id,)) else: steps.append(('set_xorg_device','via',cardnumber,total_cards,bus_id,)) print("UniChrome!") else: steps.append(('set_xorg_device','via',cardnumber,total_cards,bus_id,)) print("VIA Tech!") elif company_id == "126f": # Silicon Motion generate_generic_steps() steps.append(('set_xorg_device','siliconmotion',cardnumber,total_cards,bus_id,)) print("Silicon Motion!") elif company_id == "8086": if card_id == "7800": # i740 generate_generic_steps() steps.append(('set_xorg_device','i740',cardnumber,total_cards,bus_id,)) else: generate_generic_steps() steps.append(('set_xorg_device','intel',cardnumber,total_cards,bus_id,)) print("Intel >= 810!") elif company_id == "10de": # NVIDIA if noproprietary: steps.append(('set_xorg_device','nv',cardnumber,total_cards,bus_id,)) else: generate_nvidia_steps(videocard, cardnumber, total_cards, bus_id) print("NVIDIA!") elif company_id == "1002": print("ATI/AMD!") print("total supported ATI cards: %s" % (len(fglrx_supported),)) print("supported list:", fglrx_supported) if card_id in fglrx_supported: # fglrx supported print("fglrx driver SUPPORTS this card") if noproprietary: steps.append(('set_xorg_device','ati',cardnumber,total_cards,bus_id,)) steps.append(('drop_kernel_mod','fglrx',)) else: if not noopengl: steps.append(('fix_possible_opengl_misconfiguration','ati')) steps.append(('copy_ati_settings_on_desktop',)) steps.append(('opengl_activate','ati')) steps.append(('set_xorg_device','fglrx',cardnumber,total_cards,bus_id,)) else: # video card not supported by fglrx print("NOT supported by fglrx") generate_generic_steps() # This works for Mach64, Rage128, Radeon and in future RadeonHD driver steps.append(('set_xorg_device','ati',cardnumber,total_cards,bus_id,)) steps.append(('drop_kernel_mod','fglrx',)) else: steps.append(('set_xorg_device','vesa',cardnumber,total_cards,bus_id,)) print("ATTENTION !!!") print("ATTENTION !!!") print("ATTENTION !!!") print("--> Video Card undetected: "+videocard) print("SETTING TO VESA") print("Please report this output to Sabayon Linux developers or mail to LXNAY SABAYON ORG") # now create the file for step in steps: if len(step) == 1: eval(step[0])() else: param = step[1:] eval(step[0])(*param) # Generate xorg.conf xorg_conf_structure = xorg_conf_structure.replace('__device_section__','\n\n'.join(device_sections)) xorg_conf_structure = xorg_conf_structure.replace('__screen_section__','\n\n'.join(screen_sections)) xorg_conf_structure = xorg_conf_structure.replace('__screen_layout_section__','\n '.join(screen_layout_sections)) if forced_monitor_modes: xorg_conf_structure = xorg_conf_structure.replace('#Modes','Modes') if not dryrun: f = open(xorgfile,"w") g = open(xorgfile_backup,"w") f.write(xorg_conf_structure) f.flush() f.close() g.flush() g.close() raise SystemExit(0)