package pages import ( "encoding/base64" "fmt" "log" "os" "os/user" "strings" "syscall" "github.com/HikariKnight/quickpassthrough/internal/configs" "github.com/HikariKnight/quickpassthrough/internal/logger" "github.com/HikariKnight/quickpassthrough/pkg/command" "github.com/HikariKnight/quickpassthrough/pkg/fileio" "github.com/HikariKnight/quickpassthrough/pkg/menu" "github.com/HikariKnight/quickpassthrough/pkg/uname" "github.com/gookit/color" "golang.org/x/term" ) func prepModules(config *configs.Config) { // If we have files for modprobe if fileio.FileExist(config.Path.MODPROBE) { // Configure modprobe configs.Set_Modprobe(config.Gpu_IDs) } // If we have a folder for dracut if fileio.FileExist(config.Path.DRACUT) { // Configure dracut configs.Set_Dracut() } // If we have a mkinitcpio.conf file if fileio.FileExist(config.Path.MKINITCPIO) { configs.Set_Mkinitcpio() } // Configure grub2 here as we can make the config without sudo if config.Bootloader == "grub2" { // Write to logger logger.Printf("Configuring grub2 manually") configs.Configure_Grub2() } // Finalize changes finalize(config) } func finalize(config *configs.Config) { // Clear the screen command.Clear() // Write a title title := color.New(color.BgHiBlue, color.White, color.Bold) title.Println("Finalizing configuration") color.Print( "The configuration files have been generated and are\n", "located inside the \"config\" folder\n", "\n", "* The \"kernel_args\" file contains kernel arguments that your bootloader needs\n", //"* The \"quickemu\" folder contains files that might be\n useable for quickemu in the future\n", "* The files inside the \"etc\" folder must be copied to your system.\n", " NOTE: Verify that these files are correctly formated/edited!\n", "* Once all files have been copied, you need to update your bootloader and rebuild\n", " your initramfs using the tools to do so by your system.\n", "\n", "This program can do this for you, however the program will have to\n", "type your password to sudo using STDIN, to avoid using STDIN press CTRL+C\n", "and copy the files, update your bootloader and rebuild your initramfs manually.\n", "If you want to go back and change something, choose Back\n", "\nNOTE: A backup of the original files from the first run can be found in the backup folder\n", ) // Make a choice of going next or back choice := menu.Next("Press Next to continue with sudo using STDIN, ESC to exit or Back to go back.") // Parse the choice switch choice { case "next": installPassthrough(config) case "back": // Go back disableVideo(config) } } func installPassthrough(config *configs.Config) { // Get the user data user, err := user.Current() if err != nil { log.Fatalf(err.Error()) } // Provide a password prompt fmt.Printf("[sudo] password for %s: ", user.Username) bytep, err := term.ReadPassword(int(syscall.Stdin)) if err != nil { os.Exit(1) } fmt.Print("\n") // Elevate with sudo command.Elevate( base64.StdEncoding.EncodeToString( bytep, ), ) // Make an output string var output string // Based on the bootloader, setup the configuration if config.Bootloader == "kernelstub" { // Write to logger logger.Printf("Configuring systemd-boot using kernelstub") // Configure kernelstub output = configs.Set_KernelStub() fmt.Printf("%s\n", output) } else if config.Bootloader == "grubby" { // Write to logger logger.Printf("Configuring bootloader using grubby") // Configure kernelstub output = configs.Set_Grubby() fmt.Printf("%s\n", output) } else if config.Bootloader == "grub2" { // Write to logger logger.Printf("Applying grub2 changes") grub_output, _ := configs.Set_Grub2() fmt.Printf("%s\n", strings.Join(grub_output, "\n")) } else { kernel_args := fileio.ReadFile(config.Path.CMDLINE) logger.Printf("Unsupported bootloader, please add the below line to your bootloaders kernel arguments\n%s", kernel_args) } // A lot of linux systems support modprobe along with their own module system // So copy the modprobe files if we have them modprobeFile := fmt.Sprintf("%s/vfio.conf", config.Path.MODPROBE) if fileio.FileExist(modprobeFile) { // Copy initramfs-tools module to system output = configs.CopyToSystem(modprobeFile, "/etc/modprobe.d/vfio.conf") fmt.Printf("%s\n", output) } // Copy the config files for the system we have initramfsFile := fmt.Sprintf("%s/modules", config.Path.INITRAMFS) dracutFile := fmt.Sprintf("%s/vfio.conf", config.Path.DRACUT) if fileio.FileExist(initramfsFile) { // Copy initramfs-tools module to system output = configs.CopyToSystem(initramfsFile, "/etc/initramfs-tools/modules") fmt.Printf("%s\n", output) // Copy the modules file to /etc/modules output = configs.CopyToSystem(config.Path.ETCMODULES, "/etc/modules") fmt.Printf("%s\n", output) // Write to logger logger.Printf("Executing: sudo update-initramfs -u") // Update initramfs fmt.Println("Executed: sudo update-initramfs -u\nSee debug.log for detailed output") cmd_out, cmd_err, _ := command.RunErr("sudo", "update-initramfs", "-u") cmd_out = append(cmd_out, cmd_err...) // Write to logger logger.Printf(strings.Join(cmd_out, "\n")) } else if fileio.FileExist(dracutFile) { // Copy dracut config to /etc/dracut.conf.d/vfio output = configs.CopyToSystem(dracutFile, "/etc/dracut.conf.d/vfio") fmt.Printf("%s\n", output) // Get systeminfo sysinfo := uname.New() // Write to logger logger.Printf("Executing: sudo dracut -f -v --kver %s", sysinfo.Release) // Update initramfs fmt.Printf("Executed: sudo dracut -f -v --kver %s\nSee debug.log for detailed output", sysinfo.Release) _, cmd_err, _ := command.RunErr("sudo", "dracut", "-f", "-v", "--kver", sysinfo.Release) // Write to logger logger.Printf(strings.Join(cmd_err, "\n")) } else if fileio.FileExist(config.Path.MKINITCPIO) { // Copy dracut config to /etc/dracut.conf.d/vfio output = configs.CopyToSystem(config.Path.MKINITCPIO, "/etc/mkinitcpio.conf") fmt.Printf("%s\n", output) // Write to logger logger.Printf("Executing: sudo mkinitcpio -P") // Update initramfs fmt.Println("Executed: sudo mkinitcpio -P\nSee debug.log for detailed output") cmd_out, cmd_err, _ := command.RunErr("sudo", "mkinitcpio", "-P") cmd_out = append(cmd_out, cmd_err...) // Write to logger logger.Printf(strings.Join(cmd_out, "\n")) } // Make sure prompt end up on next line fmt.Print("\n") }