def GetDesiredKernel(cls): if not var.kernel: current_kernel = check_output(["uname", "-r"], universal_newlines=True).strip() message = ("Do you want to use the current kernel: " + current_kernel + " [Y/n]: ") choice = Tools.Question(message) Tools.NewLine() if choice == "y" or choice == "Y" or not choice: var.kernel = current_kernel elif choice == "n" or choice == "N": var.kernel = Tools.Question("Please enter the kernel name: ") Tools.NewLine() if not var.kernel: Tools.Fail("You didn't enter a kernel. Exiting...") else: Tools.Fail("Invalid Option. Exiting.") # Set modules path to correct location and sets kernel name for initramfs var.modules = "/lib/modules/" + var.kernel + "/" var.lmodules = var.temp + "/" + var.modules var.initrd = "initrd-" + var.kernel # Check modules directory cls.VerifyModulesDirectory()
def CopyModules(cls): moddeps = set() # Build the list of module dependencies Tools.Info("Copying modules ...") # Checks to see if all the modules in the list exist (if any) for file in Modules.GetFiles(): try: cmd = ("find " + var.modules + ' -iname "' + file + '.ko" | grep ' + file + ".ko") result = check_output(cmd, universal_newlines=True, shell=True).strip() cls._modset.add(result) except CalledProcessError: Tools.ModuleDoesntExist(file) # If a kernel has been set, try to update the module dependencies # database before searching it if var.kernel: try: result = call(["depmod", var.kernel]) if result: Tools.Fail("Error updating module dependency database!") except FileNotFoundError: # This should never occur because the application checks # that root is the user that is running the application. # Non-administraative users normally don't have access # to the 'depmod' command. Tools.Fail("The 'depmod' command wasn't found.") # Get the dependencies for all the modules in our set for file in cls._modset: # Get only the name of the module match = re.search("(?<=/)[a-zA-Z0-9_-]+.ko", file) if match: sFile = match.group().split(".")[0] cmd = ("modprobe -S " + var.kernel + " --show-depends " + sFile + " | awk -F ' ' '{print $2}'") results = check_output(cmd, shell=True, universal_newlines=True).strip() for i in results.split("\n"): moddeps.add(i.strip()) # Copy the modules/dependencies if moddeps: for module in moddeps: Tools.Copy(module) # Update module dependency database inside the initramfs cls.GenerateModprobeInfo()
def LastSteps(cls): Tools.Info("Performing finishing steps ...") # Create mtab file call(["touch", var.temp + "/etc/mtab"]) if not os.path.isfile(var.temp + "/etc/mtab"): Tools.Fail("Error creating the mtab file. Exiting.") cls.CreateLibraryLinks() # Copy the init script Tools.SafeCopy(var.files_dir + "/init", var.temp) # Give execute permissions to the script cr = call(["chmod", "u+x", var.temp + "/init"]) if cr != 0: Tools.Fail("Failed to give executive privileges to " + var.temp + "/init") # Sets initramfs script version number cmd = f"echo {var.version} > {var.temp}/version.bliss" call(cmd, shell=True) # Copy all of the modprobe configurations if os.path.isdir("/etc/modprobe.d/"): shutil.copytree("/etc/modprobe.d/", var.temp + "/etc/modprobe.d/") cls.CopyUdevAndSupportFiles() cls.DumpSystemKeymap() # Any last substitutions or additions/modifications should be done here if Luks.IsEnabled(): # Copy over our keyfile if the user activated it if Luks.IsKeyfileEnabled(): Tools.Flag("Embedding our keyfile into the initramfs...") Tools.SafeCopy(Luks.GetKeyfilePath(), var.temp + "/etc", "keyfile") # Copy over our detached header if the user activated it if Luks.IsDetachedHeaderEnabled(): Tools.Flag( "Embedding our detached header into the initramfs...") Tools.SafeCopy(Luks.GetDetachedHeaderPath(), var.temp + "/etc", "header") # Add any modules needed into the initramfs requiredModules = ",".join(Modules.GetFiles()) cmd = f"echo {requiredModules} > {var.temp}/modules.bliss" call(cmd, shell=True) cls.CopyLibGccLibrary()
def CopyLibGccLibrary(cls): """Copy the 'libgcc' library so that when libpthreads loads it during runtime.""" # https://github.com/zfsonlinux/zfs/issues/4749. # Find the correct path for libgcc libgccFilename = "libgcc_s.so" libgccFilenameMain = libgccFilename + ".1" # check for gcc-config gccConfigPath = Tools.GetProgramPath("gcc-config") if gccConfigPath: # Try gcc-config cmd = "gcc-config -L | cut -d ':' -f 1" res = Tools.Run(cmd) if res: # Use path from gcc-config libgccPath = res[0] + "/" + libgccFilenameMain Tools.SafeCopy(libgccPath, var.GetTempLib64Dir()) os.chdir(var.GetTempLib64Dir()) os.symlink(libgccFilenameMain, libgccFilename) return # Doing a 'whereis <name of libgcc library>' will not work because it seems # that it finds libraries in /lib, /lib64, /usr/lib, /usr/lib64, but not in # /usr/lib/gcc/ (x86_64-pc-linux-gnu/5.4.0, etc) # When a better approach is found, we can plug it in here directly and return # in the event that it succeeds. If it fails, we just continue execution # until the end of the function. # If we've reached this point, we have failed to copy the gcc library. Tools.Fail("Unable to retrieve the gcc library path!")
def CopyFirmware(cls): if Firmware.IsEnabled(): Tools.Info("Copying firmware...") if os.path.isdir("/lib/firmware/"): if Firmware.IsCopyAllEnabled(): shutil.copytree("/lib/firmware/", var.temp + "/lib/firmware/") else: # Copy the firmware in the files list if Firmware.GetFiles(): try: for fw in Firmware.GetFiles(): Tools.Copy( fw, directoryPrefix=var.firmwareDirectory) except FileNotFoundError: Tools.Warn( "An error occured while copying the following firmware: " + fw) else: Tools.Warn( "No firmware files were found in the firmware list!" ) else: Tools.Fail("The /lib/firmware/ directory does not exist")
def CopyLibGccLibrary(cls): # Find the correct path for libgcc libgcc_filename = "libgcc_s.so" libgcc_filename_main = libgcc_filename + ".1" # check for gcc-config cmd = 'whereis gcc-config | cut -d " " -f 2' res = Tools.Run(cmd) if res: # Try gcc-config cmd = "gcc-config -L | cut -d ':' -f 1" res = Tools.Run(cmd) if res: # Use path from gcc-config libgcc_path = res[0] + "/" + libgcc_filename_main Tools.SafeCopy(libgcc_path, var.llib64) os.chdir(var.llib64) os.symlink(libgcc_filename_main, libgcc_filename) return # Doing a 'whereis <name of libgcc library>' will not work because it seems # that it finds libraries in /lib, /lib64, /usr/lib, /usr/lib64, but not in # /usr/lib/gcc/ (x86_64-pc-linux-gnu/5.4.0, etc) # When a better approach is found, we can plug it in here directly and return # in the event that it succeeds. If it fails, we just continue execution # until the end of the function. # If we've reached this point, we have failed to copy the gcc library. Tools.Fail("Unable to retrieve the gcc library path!")
def CreateLinks(cls): Tools.Info("Creating symlinks ...") # Needs to be from this directory so that the links are relative os.chdir(var.lbin) # Create busybox links cmd = ("chroot " + var.temp + ' /bin/busybox sh -c "cd /bin && /bin/busybox --install -s ."') callResult = call(cmd, shell=True) if callResult != 0: Tools.Fail("Unable to create busybox links via chroot!") # Create 'sh' symlink to 'bash' os.remove(var.temp + "/bin/sh") os.symlink("bash", "sh") # Switch to the kmod directory, delete the corresponding busybox # symlink and create the symlinks pointing to kmod if os.path.isfile(var.lsbin + "/kmod"): os.chdir(var.lsbin) elif os.path.isfile(var.lbin + "/kmod"): os.chdir(var.lbin) for link in Base.GetKmodLinks(): os.remove(var.temp + "/bin/" + link) os.symlink("kmod", link)
def CopyDependencies(cls): Tools.Info("Copying library dependencies ...") bindeps = set() # Musl and non-musl systems are supported. possible_libc_paths = [ var.lib64 + "/ld-linux-x86-64.so*", var.lib + "/ld-musl-x86_64.so*", ] libc_found = False for libc in possible_libc_paths: try: # (Dirty implementation) Use the exit code of grep with no messages being outputed to see if this interpreter exists. # We don't know the name yet which is why we are using the wildcard in the variable declaration. result = call("grep -Uqs thiswillnevermatch " + libc, shell=True) # 0 = match found # 1 = file exists but not found # 2 = file doesn't exist # In situations 0 or 1, we are good, since we just care that the file exists. if result != 0 and result != 1: continue # Get the interpreter name that is on this system result = check_output("ls " + libc, shell=True, universal_newlines=True).strip() # Add intepreter to deps since everything will depend on it bindeps.add(result) libc_found = True except Exception as e: pass if not libc_found: Tools.Fail("No libc interpreters were found!") # Get the dependencies for the binaries we've collected and add them to # our bindeps set. These will all be copied into the initramfs later. for binary in cls._binset: cmd = ( "ldd " + binary + " | awk -F '=>' '{print $2}' | awk -F ' ' '{print $1}' | sed '/^ *$/d'" ) results = check_output(cmd, shell=True, universal_newlines=True).strip() if results: for library in results.split("\n"): bindeps.add(library) # Copy all the dependencies of the binary files into the initramfs for library in bindeps: Tools.Copy(library)
def LastSteps(cls): """Performes any last minute steps like copying zfs.conf, giving init execute permissions, setting up symlinks, etc. """ Tools.Info("Performing finishing steps ...") # Create mtab file call(["touch", var.temp + "/etc/mtab"]) if not os.path.isfile(var.temp + "/etc/mtab"): Tools.Fail("Error creating the mtab file. Exiting.") cls.CreateLibraryLinks() # Copy the init script Tools.SafeCopy(var.filesDirectory + "/init", var.temp) # Give execute permissions to the script cr = call(["chmod", "u+x", var.temp + "/init"]) if cr != 0: Tools.Fail("Failed to give executive privileges to " + var.temp + "/init") # Sets initramfs script version number cmd = f"echo {var.version} > {var.temp}/version.bliss" call(cmd, shell=True) # Copy all of the modprobe configurations if os.path.isdir(var.modprobeDirectory): Tools.CopyTree(var.modprobeDirectory, var.temp + var.modprobeDirectory) cls.CopyUdevAndSupportFiles() cls.DumpSystemKeymap() # Any last substitutions or additions/modifications should be done here # Add any modules needed into the initramfs requiredModules = ",".join(Modules.GetFiles()) cmd = f"echo {requiredModules} > {var.temp}/modules.bliss" call(cmd, shell=True) cls.CopyLibGccLibrary()
def GenerateModprobeInfo(cls): Tools.Info("Generating modprobe information ...") # Copy modules.order and modules.builtin just so depmod doesn't spit out warnings. -_- Tools.Copy(var.modules + "/modules.order") Tools.Copy(var.modules + "/modules.builtin") result = call(["depmod", "-b", var.temp, var.kernel]) if result != 0: Tools.Fail("Depmod was unable to refresh the dependency information for your initramfs!")
def CreateInitramfs(cls): Tools.Info("Creating the initramfs ...") # The find command must use the `find .` and not `find ${T}` # because if not, then the initramfs layout will be prefixed with # the ${T} path. os.chdir(var.temp) call(["find . -print0 | cpio -o --null --format=newc | gzip -9 > " + var.home + "/" + var.initrd], shell=True) if not os.path.isfile(var.home + "/" + var.initrd): Tools.Fail("Error creating the initramfs. Exiting.")
def CopyLibGccLibrary(cls): cmd = "gcc-config -L | cut -d ':' -f 1" res = Tools.Run(cmd) if len(res) < 1: Tools.Fail("Unable to retrieve gcc library path!") libgcc_filename = "libgcc_s.so" libgcc_filename_main = libgcc_filename + ".1" libgcc_path = res[0] + "/" + libgcc_filename_main Tools.SafeCopy(libgcc_path, var.llib64) os.chdir(var.llib64) os.symlink(libgcc_filename_main, libgcc_filename)
def CopyFirmware(cls): """Copies the firmware files/directories if necessary.""" if Firmware.IsEnabled(): Tools.Info("Copying firmware...") if os.path.isdir(var.firmwareDirectory): if Firmware.IsCopyAllEnabled(): Tools.CopyTree( var.firmwareDirectory, var.temp + var.firmwareDirectory ) else: # Copy the firmware files if Firmware.GetFiles(): try: for fw in Firmware.GetFiles(): Tools.Into(fw, directoryPrefix=var.firmwareDirectory) except FileNotFoundError: Tools.Warn( "An error occurred while copying the following firmware file: {}".format( fw ) ) # Copy the firmware directories if Firmware.GetDirectories(): try: for fw in Firmware.GetDirectories(): sourceFirmwareDirectory = os.path.join( var.firmwareDirectory, fw ) targetFirmwareDirectory = ( var.temp + sourceFirmwareDirectory ) Tools.CopyTree( sourceFirmwareDirectory, targetFirmwareDirectory ) except FileNotFoundError: Tools.Warn( "An error occurred while copying the following directory: {}".format( fw ) ) else: Tools.Fail( "The {} directory does not exist".format(var.firmwareDirectory) )
def CreateInitramfs(cls): Tools.PrintCompressAlgos() cmp_cmd = cls.CompressAlgo(Tools.Question("Algorithm [1]: ")) Tools.Info("Creating the initramfs ...") # The find command must use the `find .` and not `find ${T}` # because if not, then the initramfs layout will be prefixed with # the ${T} path. os.chdir(var.temp) call([ "find . -print0 | cpio -o --null --format=newc | " + cmp_cmd + " > " + var.home + "/" + var.initrd ], shell=True) if not os.path.isfile(var.home + "/" + var.initrd): Tools.Fail("Error creating the initramfs. Exiting.")
def LastSteps(cls): Tools.Info("Performing finishing steps ...") # Create mtab file call(["touch", var.temp + "/etc/mtab"]) if not os.path.isfile(var.temp + "/etc/mtab"): Tools.Fail("Error creating the mtab file. Exiting.") cls.CreateLibraryLinks() # Copy the init script Tools.SafeCopy(var.files_dir + "/init", var.temp) # Give execute permissions to the script cr = call(["chmod", "u+x", var.temp + "/init"]) if cr != 0: Tools.Fail("Failed to give executive privileges to " + var.temp + "/init") # Copy the bash related files bash_files = [ var.files_dir + "/bash/profile", var.files_dir + "/bash/DIR_COLORS" ] for bash_file in bash_files: Tools.SafeCopy(bash_file, var.temp + "/etc/") Tools.SafeCopy(var.files_dir + "/bash/bashrc", var.temp + "/etc/bash") # Sets initramfs script version number call([ "sed", "-i", "-e", var.initrdVersionLine + "s/0/" + var.version + "/", var.temp + "/init" ]) # Copy all of the modprobe configurations if os.path.isdir("/etc/modprobe.d/"): shutil.copytree("/etc/modprobe.d/", var.temp + "/etc/modprobe.d/") cls.CopyUdevAndSupportFiles() cls.DumpSystemKeymap() # Any last substitutions or additions/modifications should be done here # Enable LUKS in the init if LUKS is being used if Luks.IsEnabled(): Tools.ActivateTriggerInInit(var.useLuksLine) # Copy over our keyfile if the user activated it if Luks.IsKeyfileEnabled(): Tools.Flag("Embedding our keyfile into the initramfs...") Tools.SafeCopy(Luks.GetKeyfilePath(), var.temp + "/etc", "keyfile") # Copy over our detached header if the user activated it if Luks.IsDetachedHeaderEnabled(): Tools.Flag( "Embedding our detached header into the initramfs...") Tools.SafeCopy(Luks.GetDetachedHeaderPath(), var.temp + "/etc", "header") # Enable RAID in the init if RAID is being used if Raid.IsEnabled(): Tools.ActivateTriggerInInit(var.useRaidLine) # Make sure to copy the mdadm.conf from our current system. # If not, the kernel autodetection while assembling the array # will not know what name to give them, so it will name it something # like /dev/md126, /dev/md127 rather than /dev/md0, /dev/md1. # If the user didn't modify the default (all commented) mdadm.conf file, # then they will obviously get wrong raid array numbers being assigned # by the kernel. The user needs to run a "mdadm --examine --scan > /etc/mdadm.conf" # to fix this, and re-run the initramfs creator. mdadm_conf = "/etc/mdadm.conf" Tools.CopyConfigOrWarn(mdadm_conf) # Enable LVM in the init if LVM is being used if Lvm.IsEnabled(): Tools.ActivateTriggerInInit(var.useLvmLine) lvm_conf = "/etc/lvm/lvm.conf" Tools.CopyConfigOrWarn(lvm_conf) # Enable ZFS in the init if ZFS is being used if Zfs.IsEnabled(): Tools.ActivateTriggerInInit(var.useZfsLine) # Enable ADDON in the init and add our modules to the initramfs # if addon is being used if Addon.IsEnabled(): Tools.ActivateTriggerInInit(var.useAddonLine) call([ "sed", "-i", "-e", var.addonModulesLine + "s/\"\"/\"" + " ".join(Addon.GetFiles()) + "\"/", var.temp + "/init" ]) cls.CopyLibGccLibrary()
def VerifySupportedArchitecture(cls): if var.arch != "x86_64": Tools.Fail("Your architecture isn't supported. Exiting.")
def VerifyModulesDirectory(cls): if not os.path.exists(var.modules): Tools.Fail("The modules directory for " + var.modules + " doesn't exist!")
def VerifySupportedArchitecture(cls): """Checks to see that the architecture is supported.""" if var.arch != "x86_64": Tools.Fail("Your architecture isn't supported. Exiting.")
def VerifyModulesDirectory(cls): """Check to make sure the kernel modules directory exists.""" if not os.path.exists(var.modules): Tools.Fail("The modules directory for " + var.modules + " doesn't exist!")
def RemoveFile(cls, vFile): try: cls._files.remove(vFile) except ValueError: Tools.Fail('The file "' + vFile + '" was not found on the list!')
def RemoveFile(cls, vFile): try: cls._files.remove(vFile) except ValueError: Tools.Fail("The file \"" + vFile + "\" was not found on the list!")
def RemoveFile(cls, vFile): """Deletes a required file from the hook.""" try: cls._files.remove(vFile) except ValueError: Tools.Fail('The file "' + vFile + '" was not found on the list!')