def __init__(self, image, device): """In case of SPECIAL_BOARDS: Writes RBF Generated Image to microSD In case of Other Boards: Writes Generic/QEMU image to microSD and then Board Specific U-Boot to microSD""" self.imagePath = image self.devicePath = device self.supportedBoards = {} self.boardCount = 0 self.stage1Loader = "none" self.ubootPath = "none" self.rbfUtils = RbfUtils() self.rbfInstaller = None
def __init__(self, action, xmlTemplate): """Constructor for BoardTemplateParser""" logging.info("Xml Template: "+xmlTemplate) self.action = action self.imagePath = "" self.xmlTemplate = xmlTemplate self.boardDom = None self.workDir = "" self.packageGroups = [] self.packages = [] self.rbfUtils = RbfUtils(); self.imageData = [] self.stockKernels = [] self.repoNames = [] self.rbfScript = open("rbf.sh","w") self.initramfsScript = None self.cleanupScript = None
def __init__(self, imagePath, devicePath): """In case of SPECIAL_BOARDS: Writes RBF Generated Image to microSD""" """In case of Other Boards: Writes Generic/QEMU image to microSD and then Board Specific U-Boot to microSD""" self.imagePath = imagePath self.devicePath = devicePath self.supportedBoards = {} self.boardCount = 0 self.stage1Loader = "none" self.ubootPath = "none" self.rbfUtils = RbfUtils() try: for board in sorted(os.listdir(BoardInstaller.BOARDS_DIR)): if board in ("finalize.sh","qemu.sh"): continue board = board[:-3] self.boardCount = self.boardCount + 1 self.supportedBoards[self.boardCount] = board except: print("Could not find " + BoardInstaller.BOARDS_DIR) sys.exit(BoardInstaller.NO_BOARDS)
class BoardInstaller(): BOARDS_DIR="boards.d" SPECIAL_BOARDS=['odroidc1','rpi2'] MLO_BOARDS=['beaglebone','pandaboard'] NOT_ROOT,SHOW_HELP, NOT_FILE, NO_WRITE_PERMISSION, NO_BOARDS, NO_FILES = range(0,6) def __init__(self, imagePath, devicePath): """In case of SPECIAL_BOARDS: Writes RBF Generated Image to microSD""" """In case of Other Boards: Writes Generic/QEMU image to microSD and then Board Specific U-Boot to microSD""" self.imagePath = imagePath self.devicePath = devicePath self.supportedBoards = {} self.boardCount = 0 self.stage1Loader = "none" self.ubootPath = "none" self.rbfUtils = RbfUtils() try: for board in sorted(os.listdir(BoardInstaller.BOARDS_DIR)): if board in ("finalize.sh","qemu.sh"): continue board = board[:-3] self.boardCount = self.boardCount + 1 self.supportedBoards[self.boardCount] = board except: print("Could not find " + BoardInstaller.BOARDS_DIR) sys.exit(BoardInstaller.NO_BOARDS) def chooseBoard(self): """Choose from Supported Boards""" print("Select Board:") for b in self.supportedBoards.keys(): print("\t" + str(b) + ": " + self.supportedBoards[b].title()) while True: x = raw_input("Which Board? ") if self.rbfUtils.isSizeInt(x): boardIndex = int(x) if boardIndex <= self.boardCount: return boardIndex else: print("Invalid Input") def findUboot(self,boardName): """Find u-boot for specified board""" path = "files/"+boardName+"/" try: for u in os.listdir(path): if u.startswith("u-boot"): return path+u return "none" except: print("Could not find board files") sys.exit(BoardInstaller.NO_FILES) def createScript(self, boardIndex): """Create rbfinstaller.sh""" self.rbfInstaller = open("rbfinstaller.sh","w") self.rbfInstaller.write("dd if=\"" + self.imagePath + "\" of=" + self.devicePath + " bs=1M\n") boardName = self.supportedBoards[boardIndex] print("Writing U-Boot for " + boardName) if boardName in BoardInstaller.SPECIAL_BOARDS: print("For " + boardName + ", can only write image " + self.getFilename(self.imagePath) + " to microSD. Cannot run board script.") elif boardName in BoardInstaller.MLO_BOARDS: print("Will also install MLO to device " + self.devicePath) self.stage1Loader = "files/" + boardName + "/MLO" self.ubootPath = self.findUboot(boardName) if self.ubootPath != "none": self.rbfInstaller.write("boards.d/" + boardName + ".sh " + self.devicePath + " " + self.stage1Loader + " " + self.ubootPath + "\n") else: self.stage1Loader = "none" self.ubootPath = self.findUboot(boardName) if self.ubootPath != "none": self.rbfInstaller.write("boards.d/" + boardName + ".sh " + self.devicePath + " " + self.stage1Loader + " " + self.ubootPath + "\n") self.rbfInstaller.write("sync\n") self.rbfInstaller.close() def getDeviceName(self): blockDevice = self.devicePath[self.devicePath.rfind("/")+1:] blockDeviceVendor = "none" blockDeviceModel = "none" try: blockDeviceFile = open("/sys/class/block/" + blockDevice + "/device/model","r") blockDeviceModel = blockDeviceFile.readlines()[0].strip() blockDeviceFile.close() blockDeviceFile = open("/sys/class/block/" + blockDevice + "/device/vendor","r") blockDeviceVendor = blockDeviceFile.readlines()[0].strip() blockDeviceFile.close() return "[" + blockDeviceVendor + " " + blockDeviceModel + "]" except: return "" def getFilename(self, filePath): if "/" not in filePath: return filePath else: return filePath[filePath.rfind("/")+1:]
class BoardInstaller(object): """Board Installer""" BOARDS_DIR = "boards.d" SPECIAL_BOARDS = ['odroidc1', 'rpi2', 'lamobor1'] MLO_BOARDS = ['beaglebone', 'pandaboard'] NOT_ROOT, SHOW_HELP, NOT_FILE, NO_WRITE_PERMISSION, NO_BOARDS, NO_FILES = \ range(0, 6) def __init__(self, image, device): """In case of SPECIAL_BOARDS: Writes RBF Generated Image to microSD In case of Other Boards: Writes Generic/QEMU image to microSD and then Board Specific U-Boot to microSD""" self.imagePath = image self.devicePath = device self.supportedBoards = {} self.boardCount = 0 self.stage1Loader = "none" self.ubootPath = "none" self.rbfUtils = RbfUtils() self.rbfInstaller = None def loadBoards(self): """Load Board Names from boards.d""" try: for board in sorted(os.listdir(BoardInstaller.BOARDS_DIR)): if board in ("finalize.sh", "qemu.sh"): continue board = board[:-3] self.boardCount = self.boardCount + 1 self.supportedBoards[self.boardCount] = board except OSError: print("Could not find " + BoardInstaller.BOARDS_DIR) return BoardInstaller.NO_BOARDS return 0 def chooseBoard(self): """Choose from Supported Boards""" print("Select Board:") for b in self.supportedBoards.keys(): print("\t" + str(b) + ": " + self.supportedBoards[b].title()) while True: x = raw_input("Which Board? ") if self.rbfUtils.isSizeInt(x): index = int(x) if index <= self.boardCount: return index else: print("Invalid Input") @classmethod def findUboot(cls, boardName): """Find u-boot for specified board""" path = "files/" + boardName + "/" try: for u in os.listdir(path): if u.startswith("u-boot"): return path + u return "none" except OSError: print("Could not find board files") return "none" def createScript(self, bIndex): """Create rbfinstaller.sh""" self.rbfInstaller = open("rbfinstaller.sh", "w") self.rbfInstaller.write("dd if=\"" + self.imagePath + "\" of="\ + self.devicePath + " bs=1M\n") boardName = self.supportedBoards[bIndex] print("Writing U-Boot for " + boardName) if boardName in BoardInstaller.SPECIAL_BOARDS: print("For " + boardName + ", can only write image "\ + self.getFilename(self.imagePath)\ + " to microSD. Cannot run board script.") elif boardName in BoardInstaller.MLO_BOARDS: print("Will also install MLO to device " + self.devicePath) self.stage1Loader = "files/" + boardName + "/MLO" self.ubootPath = self.findUboot(boardName) if self.ubootPath != "none": self.rbfInstaller.write("boards.d/" + boardName + ".sh "\ + self.devicePath + " "\ + self.stage1Loader + " "\ + self.ubootPath + "\n") else: self.stage1Loader = "none" self.ubootPath = self.findUboot(boardName) if self.ubootPath != "none": self.rbfInstaller.write("boards.d/" + boardName + ".sh "\ + self.devicePath + " "\ + self.stage1Loader + " "\ + self.ubootPath + "\n") self.rbfInstaller.write("sync\n") self.rbfInstaller.close() def getDeviceName(self): """Tries to get block device name""" blockDevice = self.devicePath[self.devicePath.rfind("/") + 1:] blockDeviceVendor = "none" blockDeviceModel = "none" try: blockDeviceFile = open("/sys/class/block/" + blockDevice +\ "/device/model", "r") blockDeviceModel = blockDeviceFile.readlines()[0].strip() blockDeviceFile.close() blockDeviceFile = open("/sys/class/block/" + blockDevice +\ "/device/vendor", "r") blockDeviceVendor = blockDeviceFile.readlines()[0].strip() blockDeviceFile.close() return "[" + blockDeviceVendor + " " + blockDeviceModel + "]" except IOError: return "" @classmethod def getFilename(cls, filePath): """Extracts filename from filepath""" if "/" not in filePath: return filePath else: return filePath[filePath.rfind("/") + 1:]
class BoardTemplateParser(): """BoardTemplateParser Class. Parses XML Template and performs required actions on image file """ INDEX, SIZE, BEGIN, PTYPE, FS, MOUNTPOINT, UUID = range (0,7) INCORRECT_ARGUMENTS, ERROR_PARSING_XML, ERROR_IMAGE_FILE, INVALID_PARTITION_DATA, NO_PACKAGES, NO_KERNEL_TYPE, INCORRECT_REPOSITORY, IMAGE_EXISTS, NO_UBOOT, LOGICAL_PART_ERROR, PRIMARY_PART_ERROR, PARTITION_SIZES_ERROR, FSTAB_ERROR, CLEANUP_ERROR, NOT_ROOT, COMMANDS_NOT_FOUND, SYS_MKFS_COMMANDS_NOT_FOUND, NO_FIRMWARE_FOUND, TEMPLATE_NOT_FOUND, TOTAL_PARTITIONS_ERROR = range(100,120) LOOP_DEVICE_EXISTS, FALLOCATE_ERROR, PARTED_ERROR, LOOP_DEVICE_CREATE_ERROR, PARTITION_DOES_NOT_EXIST, MOUNTING_ERROR, WRITE_REPO_ERROR, COPY_KERNEL_ERROR, COPY_FIRMWARE_ERROR, RPMDB_INIT_ERROR, GROUP_INSTALL_ERROR, PACKAGE_INSTALL_ERROR, ETC_OVERLAY_ERROR, ROOT_PASS_ERROR, SELINUX_ERROR, BOARD_SCRIPT_ERROR, FINALIZE_SCRIPT_ERROR, EXTLINUXCONF_ERROR, NO_ETC_OVERLAY, LOOP_DEVICE_DELETE_ERROR = range (200,220) RbfScriptErrors = { LOOP_DEVICE_EXISTS: "LOOP_DEVICE_EXISTS: Specified Loop Device Already Exists. Check losetup -l", FALLOCATE_ERROR : "FALLOCATE_ERROR: Error While Creating Image File", PARTED_ERROR: "PARTED_ERROR: Could Not Partition Image", LOOP_DEVICE_CREATE_ERROR: "LOOP_DEVICE_CREATE_ERROR: Could Not Create Loop Device. Device Might Be Busy. Check \"losetup -l\"", PARTITION_DOES_NOT_EXIST: "PARTITION_DOES_NOT_EXIST: Could Not Find Specified Partition", MOUNTING_ERROR: "MOUNTING_ERROR: Could Not Mount Partitions", WRITE_REPO_ERROR: "WRITE_REPO_ERROR: Could Not Write Repo Files", COPY_KERNEL_ERROR: "COPY_KERNEL_ERROR: Could Not Copy Kernel", COPY_FIRMWARE_ERROR: "COPY_FIRMWARE_ERROR: Could Not Copy Firmware", RPMDB_INIT_ERROR: "RPMDB_INIT_ERROR: Could Not Init RPM DB", GROUP_INSTALL_ERROR: "GROUP_INSTALL_ERROR: Error Installing Some Package Groups", PACKAGE_INSTALL_ERROR: "PACKAGE_INSTALL_ERROR: Error Installing Some Packages", ETC_OVERLAY_ERROR: "ETC_OVERLAY_ERROR: Could Not Copy /etc Overlay", ROOT_PASS_ERROR: "ROOT_PASS_ERROR: Could Not Set Empty Root Pass", SELINUX_ERROR: "SELINUX_ERROR: Could Not Set SELINUX Status", BOARD_SCRIPT_ERROR: "BOARD_SCRIPT_ERROR: Error In Board Script", FINALIZE_SCRIPT_ERROR: "FINALIZE_SCRIPT_ERROR: Error In Finalize Script", EXTLINUXCONF_ERROR: "EXTLINUXCONF_ERROR: Error Creating /boot/extlinux/extlinux.conf", NO_ETC_OVERLAY: "No Etc Overlay Found", LOOP_DEVICE_DELETE_ERROR: "Could Not Delete Loop Device. Device Might Be Busy. Check \"losetup -l\"" } def __init__(self, action, xmlTemplate): """Constructor for BoardTemplateParser""" logging.info("Xml Template: "+xmlTemplate) self.action = action self.imagePath = "" self.xmlTemplate = xmlTemplate self.boardDom = None self.workDir = "" self.packageGroups = [] self.packages = [] self.rbfUtils = RbfUtils(); self.imageData = [] self.stockKernels = [] self.repoNames = [] self.rbfScript = open("rbf.sh","w") self.initramfsScript = None self.cleanupScript = None def __del__(self): """Destructor for BoardTemplateParser""" self.rbfScript.close() def getTagValue(self, dom, domTag): """Extracts Tag Value from DOMTree""" xmlTag = dom.getElementsByTagName(domTag) for x in xmlTag: return x.childNodes[0].data def parseTemplate(self): """Parses xmlTemplate""" logging.info("Parsing: "+ self.xmlTemplate) try: self.boardDom = xml.dom.minidom.parse(self.xmlTemplate) except: logging.error("Error Parsing XML Template File") sys.exit(BoardTemplateParser.ERROR_PARSING_XML) self.boardName = self.getTagValue(self.boardDom,"board") self.workDir = self.getTagValue(self.boardDom,"workdir") self.finalizeScript = self.getTagValue(self.boardDom,"finalizescript") self.loopDevice = subprocess.check_output(['losetup','-f']).strip() self.selinuxConf = self.getTagValue(self.boardDom,"selinux") self.etcOverlay = self.getTagValue(self.boardDom,"etcoverlay") self.linuxDistro = self.getTagValue(self.boardDom,"distro") self.extlinuxConf = self.getTagValue(self.boardDom,"extlinuxconf") self.hostName = self.getTagValue(self.boardDom,"hostname") self.rootFiles = self.getTagValue(self.boardDom,"rootfiles") self.ubootPath = self.getTagValue(self.boardDom,"uboot") self.firmwareDir = self.getTagValue(self.boardDom,"firmware") logging.info("Successfully Parsed Board Template For: " + self.boardName) def getShellExitString(self,exitCode): """Generates Shell Exit command. Used to check successful command execution""" return "if [ $? != 0 ]; then exit " + str(exitCode) + "; fi\n\n" def getShellErrorString(self,exitCode): """Generates Shell Error command. Used to check successful command execution""" return "if [ $? != 0 ]; then echo [INFO ] " + self.RbfScriptErrors[exitCode] + "; read -p \"Press Enter To Continue\"; fi\n\n" def createImage(self): """Creates Image File""" self.rbfScript.write("echo [INFO ] $0 Detacing Loop Device If Busy: " + self.loopDevice+"\n") self.rbfScript.write(self.delDeviceIfExists(self.loopDevice)) logging.info("Creating Image File") imageDom = self.boardDom.getElementsByTagName("image")[0] if imageDom.hasAttribute("size") and imageDom.hasAttribute("size") and imageDom.hasAttribute("size"): self.imageSize = imageDom.getAttribute("size") imageType = imageDom.getAttribute("type") self.imagePath = imageDom.getAttribute("path") if self.imageSize[len(self.imageSize)-1] == "M" or self.imageSize[len(self.imageSize)-1] == "G": logging.info("Creating Image: " + self.imageSize + " " + imageType + " " + self.imagePath) else: logging.error("Invalid Image Size: " + self.imageSize) sys.exit(BoardTemplateParser.ERROR_IMAGE_FILE) else: logging.error("No image tag found or image tag incomplete.") sys.exit(BoardTemplateParser.ERROR_IMAGE_FILE) self.imageSize = self.rbfUtils.getImageSizeInM(self.imageSize) if os.path.exists(self.imagePath): logging.error("Image Already Exists") sys.exit(BoardTemplateParser.IMAGE_EXISTS) self.rbfScript.write("echo [INFO ] $0 Creating " + self.imagePath + "\n") self.rbfScript.write("fallocate -l " + self.imageSize + " " + self.imagePath + " &>> rbf.log \n") self.rbfScript.write(self.getShellExitString(BoardTemplateParser.FALLOCATE_ERROR)) def verifyPartitionSizes(self,partitionsDom): """Checks if partition size is exceeding total image size""" partitionSizeSum = 0 for partitions in partitionsDom: partition = partitions.getElementsByTagName("partition") for p in partition: sizeString = p.getAttribute("size") sizeNumber = sizeString[0:-1] if not (self.rbfUtils.isSizeInt(sizeNumber)): logging.error("Parititon Size Error. Only Integers with suffix G or M allowed. You Specified " + sizeString) sys.exit(BoardTemplateParser.PARTITION_SIZES_ERROR) size = self.rbfUtils.getImageSizeInM(sizeString) sizeSuffix=size[-1:] if not (sizeSuffix=="M" or sizeSuffix=="G"): logging.error("Parititon Size Error. Only Integers with suffix G or M allowed. You Specified " + sizeString) sys.exit(BoardTemplateParser.PARTITION_SIZES_ERROR) if p.getAttribute("type") == "extended": continue partitionSizeSum = partitionSizeSum + int(size[0:-1]) logging.info("Image Size: " + self.imageSize + " Parititon Size Sum: " + str(partitionSizeSum)+"M") if int(self.imageSize[0:-1]) >= partitionSizeSum: return True else: return False def createPartitions(self): """Creates Partitions""" logging.info("Creating Partitions") try: partitionsDom = self.boardDom.getElementsByTagName("partitions") except: logging.error("No Partitions Found") if not self.verifyPartitionSizes(partitionsDom): logging.error("Parititon Sizes Exceed Image Size") sys.exit(BoardTemplateParser.PARTITION_SIZES_ERROR) partedString = "parted " + self.imagePath + " -s mklabel msdos " extendedStart = False totalPartitionCount = 0 begin = self.rbfUtils.PARTITION_BEGIN for partitions in partitionsDom: partition = partitions.getElementsByTagName("partition") primaryCount = 0 for p in partition: partuuid = str(uuid.uuid4()) if p.hasAttribute("index") and p.hasAttribute("size") and p.hasAttribute("type") and p.hasAttribute("fs") and p.hasAttribute("mountpoint"): index = p.getAttribute("index") size = self.rbfUtils.getImageSizeInM(p.getAttribute("size")) ptype = p.getAttribute("type") fs = p.getAttribute("fs") mountpoint = p.getAttribute("mountpoint") if fs == "vfat": partuuid = partuuid.upper()[:8] if (ptype =="primary" or ptype == "extended") and totalPartitionCount == 4: logging.error("Cannot Have More Than 4 Primary Partitions") sys.exit(BoardTemplateParser.TOTAL_PARTITIONS_ERROR) if ptype == "primary": primaryCount = primaryCount + 1 if ptype == "primary" or ptype == "extended": totalPartitionCount = totalPartitionCount + 1 """Adjust partition indexes. parted seems to skip a partition number if a logical partition is create before 3 primary ones""" if primaryCount < 3 and extendedStart == True: index = str(int(index) + 1) logging.info("Creating Partition " + index + " " + size + " " + ptype + " " + fs + " " + mountpoint + " " + partuuid) x = [index, size, begin, ptype, fs, mountpoint, partuuid] self.imageData.append(x) end = self.rbfUtils.calcParitionEndSize(begin,size) if fs == "swap": fs = "linux-swap" elif fs == "vfat": fs = "fat32" partedString = partedString + "mkpart " + ptype + " " + fs + " " + begin[0:-1] + " " + end[0:-1] + " " if ptype == "logical" and extendedStart == False: logging.error("Cannot Create Logical Parititon before Extended") sys.exit(BoardTemplateParser.LOGICAL_PART_ERROR) if ptype == "primary" and extendedStart == True: logging.error("Cannot Create Primary Parititon after Extended") sys.exit(BoardTemplateParser.PRIMARY_PART_ERROR) elif ptype == "extended": extendedStart = True else: begin = end else: logging.error("Invalid Partition Data") sys.exit(BoardTemplateParser.INVALID_PARTITION_DATA) self.rbfScript.write("echo [INFO ] $0 Creating Parititons\n") self.rbfScript.write(partedString + " &>> rbf.log \n") self.rbfScript.write(self.getShellExitString(BoardTemplateParser.PARTED_ERROR)) def delDeviceIfExists(self, device): """Generates command to detach loop device if it exists""" return "[ -b " + device + " ] && losetup -d " + device + " &>> rbf.log \nsleep 2\n" def createFilesystems(self): """Creates Filesystem""" self.rbfScript.write("losetup " + self.loopDevice + " " + self.imagePath + "\n") self.rbfScript.write("partprobe " + self.loopDevice + "\nsleep 2\n") for i in range(0, len(self.imageData)): if self.imageData[i][BoardTemplateParser.PTYPE] == "extended": continue fs = self.imageData[i][BoardTemplateParser.FS] index = self.imageData[i][BoardTemplateParser.INDEX] partuuid = self.imageData[i][BoardTemplateParser.UUID] ptype = self.imageData[i][BoardTemplateParser.PTYPE] size = self.rbfUtils.getImageSizeInM(self.imageData[i][BoardTemplateParser.SIZE]) begin = self.rbfUtils.getImageSizeInM(self.imageData[i][BoardTemplateParser.BEGIN]) self.rbfScript.write("[ -b " + self.loopDevice + "p" + index + " ] && echo [INFO ] $0 Creating Filesystem " + fs + " on partition " + index + " || exit " + str(BoardTemplateParser.PARTITION_DOES_NOT_EXIST) + "\n") if fs == "vfat": if not checkCommandExistsAccess(['mkfs.vfat']): logging.error("Please Install mkfs.vfat") sys.exit(BoardTemplateParser.SYS_MKFS_COMMANDS_NOT_FOUND) self.rbfScript.write("mkfs.vfat -n " + partuuid + " " + self.loopDevice + "p"+ index + " &>> rbf.log \n") elif fs == "swap": if not checkCommandExistsAccess(['mkswap']): logging.error("Please Install mkswap") sys.exit(BoardTemplateParser.SYS_MKFS_COMMANDS_NOT_FOUND) self.rbfScript.write("mkswap -U " + partuuid + " " + self.loopDevice + "p" + index +" &>> rbf.log \n") else: if not checkCommandExistsAccess(['mkfs.'+fs]): logging.error("Please Install mkfs."+fs) sys.exit(BoardTemplateParser.SYS_MKFS_COMMANDS_NOT_FOUND) self.rbfScript.write("mkfs." + fs + " -U " + partuuid + " " + self.loopDevice + "p" + index + " &>> rbf.log \n") def mountPartitions(self): """Mounting Partitions""" logging.info("Mounting Partitions") self.rbfScript.write("mkdir -p " + self.workDir + "\n") for i in range(0, len(self.imageData)): index = self.imageData[i][BoardTemplateParser.INDEX] mountpoint = self.imageData[i][BoardTemplateParser.MOUNTPOINT] begin = self.imageData[i][BoardTemplateParser.BEGIN] fs = self.imageData[i][BoardTemplateParser.FS] if mountpoint == "/": logging.info("Mounting Parititon "+ index + " on " + self.workDir + mountpoint) self.rbfScript.write("echo [INFO ] $0 Mouting Parititon " + index + " on " + mountpoint+"\n") self.rbfScript.write("mount " + self.loopDevice + "p" + index +" " +self.workDir + mountpoint + "\n") self.rbfScript.write(self.getShellExitString(BoardTemplateParser.MOUNTING_ERROR)) for j in range(0, len(self.imageData)): pm = self.imageData[j][BoardTemplateParser.MOUNTPOINT] if pm != "/" and pm != "swap": self.rbfScript.write("mkdir -p " + self.workDir + mountpoint + pm + "\n") for i in range(0, len(self.imageData)): if self.imageData[i][BoardTemplateParser.PTYPE] == "extended": continue index = self.imageData[i][BoardTemplateParser.INDEX] mountpoint = self.imageData[i][BoardTemplateParser.MOUNTPOINT] begin = self.imageData[i][BoardTemplateParser.BEGIN] fs = self.imageData[i][BoardTemplateParser.FS] ptype = self.imageData[i][BoardTemplateParser.PTYPE] if mountpoint != "/" and mountpoint !="swap": logging.info("Mounting Parititon "+ index + " on " + self.workDir + mountpoint) self.rbfScript.write("echo [INFO ] $0 Mouting Parititon " + index + " on " + mountpoint+"\n") self.rbfScript.write("mount " + self.loopDevice + "p" + index +" " +self.workDir + mountpoint + "\n") self.rbfScript.write(self.getShellExitString(BoardTemplateParser.MOUNTING_ERROR)) self.rbfScript.write("mkdir " + self.workDir + "/proc " + self.workDir + "/sys\n") self.rbfScript.write("mount -t proc proc " + self.workDir + "/proc\n") def writeRepos(self): """Writes Repos to /etc/yum.repos.d""" self.rbfScript.write("rm -rf " + self.workDir + "/etc/yum.repos.d\n") self.rbfScript.write("mkdir -p " + self.workDir + "/etc/yum.repos.d\n") try: self.reposDom = self.boardDom.getElementsByTagName("repos") for repos in self.reposDom: repo = repos.getElementsByTagName("repo") for r in repo: name = r.getAttribute("name") path = r.getAttribute("path") self.repoNames.append(name) logging.info("Found Repo: " + name + " " + path) repoString = "cat > " + self.workDir + "/etc/yum.repos.d/" + name + ".repo << EOF\n" repoString = repoString + "["+name+"]\n" repoString = repoString + "name="+name+"\n" repoString = repoString + "baseurl="+path+"\n" repoString = repoString + "gpgcheck=0\nenabled=1\n" repoString = repoString + "EOF\n" self.rbfScript.write(repoString) self.rbfScript.write(self.getShellExitString(BoardTemplateParser.WRITE_REPO_ERROR)) except: logging.error("Distro Repository Information Incorrect") sys.exit(BoardTemplateParser.INCORRECT_REPOSITORY) def generatePackageString(self, packageList): """Generates String from supplied List""" packageString = "" for p in packageList: packageString = p + ' ' + packageString return packageString def installPackages(self): """Installing Packages""" try: packagesDom = self.boardDom.getElementsByTagName("packages") except: logging.error("No Packages Supplied. Please Fix Template") sys.exit(BoardTemplateParser.NO_PACKAGES) for packageElement in packagesDom: try: groupPackageString = packageElement.getElementsByTagName('group')[0].childNodes[0].data except: groupPackageString = "" p = groupPackageString.split(',') for i in range(0,len(p)): self.packageGroups.append(p[i]) try: packageString = packageElement.getElementsByTagName('package')[0].childNodes[0].data except: packageString = "" p = packageString.split(',') for i in range(0,len(p)): self.packages.append(p[i]) packageGroupsString = self.generatePackageString(self.packageGroups).strip() packagesString = self.generatePackageString(self.packages).strip() logging.info("Installing Package Groups: " + packageGroupsString) logging.info("Installing Packages: " + packagesString) repoEnableString = "--disablerepo=* --enablerepo=" for r in self.repoNames: repoEnableString = repoEnableString + r + "," self.rbfScript.write("rpm --root " + self.workDir + " --initdb\n") self.rbfScript.write(self.getShellExitString(BoardTemplateParser.RPMDB_INIT_ERROR)) if len(packageGroupsString) > 0: self.rbfScript.write("echo [INFO ] $0 Installing Package Groups. Please Wait\n") self.rbfScript.write("yum "+ repoEnableString[0:-1] + " --installroot=" + self.workDir + " groupinstall " + packageGroupsString+" 2>> rbf.log\n") self.rbfScript.write(self.getShellErrorString(BoardTemplateParser.GROUP_INSTALL_ERROR)) if len(packagesString) > 0: self.rbfScript.write("echo [INFO ] $0 Installing Packages. Please Wait\n") self.rbfScript.write("yum "+ repoEnableString[0:-1] + " --installroot=" + self.workDir + " install " + packagesString+" 2>> rbf.log\n") self.rbfScript.write(self.getShellErrorString(BoardTemplateParser.PACKAGE_INSTALL_ERROR)) def installKernel(self): """Installing Kernel""" if self.ubootPath != "none" and not os.path.exists(self.ubootPath): logging.error("Could Not Find uboot in:" + self.ubootPath) sys.exit(BoardTemplateParser.NO_UBOOT) logging.info("Installing Kernel") kernelDom = self.boardDom.getElementsByTagName("kernel") for k in kernelDom: if k.hasAttribute("type"): self.kernelType = k.getAttribute("type") logging.info("Kernel Type: " + self.kernelType) else: logging.error("No Kernel Type Specified") sys.exit(BoardTemplateParser.NO_KERNEL_TYPE) if self.kernelType == "custom": for k in kernelDom: self.kernelPath = k.getElementsByTagName('image')[0].childNodes[0].data self.initrdPath = k.getElementsByTagName('initrd')[0].childNodes[0].data self.dtbDir = k.getElementsByTagName('dtbdir')[0].childNodes[0].data self.dtbFile = k.getElementsByTagName('dtb')[0].childNodes[0].data modulesPath = k.getElementsByTagName('modules')[0].childNodes[0].data logging.info("Using Custom Kernel: " + self.kernelPath) logging.info("Using Initrd: " + self.initrdPath) logging.info("Using Modules: " + modulesPath) logging.info("Using DTP Dir: " + self.dtbDir) logging.info("Using DTB: " + self.dtbFile) self.rbfScript.write("cp -rv " + self.kernelPath + " " + self.initrdPath + " " + self.dtbDir + " " + self.workDir + "/boot &>> rbf.log \n") self.rbfScript.write(self.getShellExitString(BoardTemplateParser.COPY_KERNEL_ERROR)) self.rbfScript.write("mkdir -p " + self.workDir + "/lib/modules &>> rbf.log \n") self.rbfScript.write(self.getShellExitString(BoardTemplateParser.COPY_KERNEL_ERROR)) self.rbfScript.write("cp -rv " + modulesPath + " " + self.workDir + "/lib/modules/" + " &>> rbf.log \n") self.rbfScript.write(self.getShellExitString(BoardTemplateParser.COPY_KERNEL_ERROR)) elif self.kernelType == "stock": for k in kernelDom: logging.info("Using Stock Kernel") self.packages.append('kernel') #Required for generation of generic initramfs self.packages.append('dracut-config-generic') elif self.kernelType == "none": logging.info("Not Installing Any Kernel") if self.firmwareDir != "none" and not os.path.exists(self.firmwareDir): logging.error("Could Not Find Firmware in:" + self.firmwareDir) sys.exit(BoardTemplateParser.NO_FIRMWARE_FOUND) if self.firmwareDir != "none": self.rbfScript.write("mkdir -p " + self.workDir + "/lib/firmware &>> rbf.log \n") self.rbfScript.write(self.getShellExitString(BoardTemplateParser.COPY_FIRMWARE_ERROR)) self.rbfScript.write("cp -rv " + self.firmwareDir + "/* " + self.workDir + "/lib/firmware &>> rbf.log \n") self.rbfScript.write(self.getShellExitString(BoardTemplateParser.COPY_FIRMWARE_ERROR)) def createInitramfs(self): """Creates Initramfs for stock kernel""" self.initramfsScript = open("initramfs.sh","w") if self.kernelType == "stock": logging.info("Creating Initramfs") if not os.path.exists(self.workDir+"/lib/modules"): logging.info("No Kernels Found") self.stockKernels = [] return self.stockKernels = os.listdir(self.workDir+"/lib/modules") for kernelVer in self.stockKernels: self.initramfsScript.write("echo [INFO ] $0 Creating Initramfs\n") self.initramfsScript.write("chroot "+ self.workDir + " /usr/bin/dracut --no-compress -f /boot/initramfs-" + kernelVer + ".img " + kernelVer + " &>> rbf.log\n") def finalActions(self): """Sets Hostname, Root Pass, SELinux Status & runs Board Script & Finalize Script""" hostnameConfig = open(self.etcOverlay+"/hostname","w") hostnameConfig.write(self.hostName) hostnameConfig.close() logging.info("Copying Etc Overlay: " + self.etcOverlay) self.rbfScript.write("cp -rpv "+ self.etcOverlay + " " + self.workDir+" &>> rbf.log \n") self.rbfScript.write(self.getShellExitString(BoardTemplateParser.ETC_OVERLAY_ERROR)) logging.info("Setting empty root pass") self.rbfScript.write("sed -i 's/root:x:/root::/' " + self.workDir + "/etc/passwd &>> rbf.log \n") self.rbfScript.write(self.getShellErrorString(BoardTemplateParser.ROOT_PASS_ERROR)) logging.info("Setting SELinux status to " + self.selinuxConf) self.rbfScript.write("sed -i 's/SELINUX=enforcing/SELINUX=" + self.selinuxConf + "/' " + self.workDir + "/etc/selinux/config &>> rbf.log \n") self.rbfScript.write(self.getShellErrorString(BoardTemplateParser.SELINUX_ERROR)) if os.path.isfile("boards.d/"+self.boardName+".sh"): logging.info("Board Script: " + "boards.d/"+self.boardName+".sh") self.rbfScript.write("echo [INFO ] $0 Running Board Script: " + "boards.d/"+self.boardName+".sh\n") self.rbfScript.write("./boards.d/" + self.boardName + ".sh " + self.imagePath + " " + self.ubootPath + " " + self.workDir + " " + self.rootFiles + "\n") self.rbfScript.write(self.getShellExitString(BoardTemplateParser.BOARD_SCRIPT_ERROR)) logging.info("Finalize Script: " + self.finalizeScript) self.rbfScript.write("echo [INFO ] $0 Running Finalize Script: " + self.finalizeScript +"\n") self.rbfScript.write(self.finalizeScript+"\n") self.rbfScript.write(self.getShellExitString(BoardTemplateParser.FINALIZE_SCRIPT_ERROR)) self.rbfScript.write("exit 0\n") self.rbfScript.close() def getPartition(self,mountpoint): """Gets Partition UUID/LABEL From Dict""" for i in range(0,len(self.imageData)): if self.imageData[i][BoardTemplateParser.MOUNTPOINT] == mountpoint: if self.imageData[i][BoardTemplateParser.FS] == "vfat": return "LABEL="+self.imageData[i][BoardTemplateParser.UUID] else: return "UUID=" + self.imageData[i][BoardTemplateParser.UUID] def getBootPath(self,path): """Returns Path for extlinux.conf""" if "/" not in path: bootPath = "/" + path else: bootPath = path[path.rfind("/"):] return bootPath def extLinuxConf(self): """Creating extlinux.conf""" if self.extLinuxConf == "false": self.initramfsScript.close() return self.initramfsScript.write("mkdir " + self.workDir +"/boot/extlinux\n") self.initramfsScript.write(self.getShellExitString(BoardTemplateParser.EXTLINUXCONF_ERROR)) extlinuxContents = "#Created by RootFS Build Factory\nui menu.c32\nmenu autoboot " + self.linuxDistro + "\nmenu title " + self.linuxDistro +" Options\n#menu hidden\ntimeout 60\ntotaltimeout 600\n" if self.kernelType == "custom": logging.info("Creating extlinux.conf in " + self.workDir +"/boot/extlinux" ) bootKernelPath = self.getBootPath(self.kernelPath) if len(self.initrdPath)!=0: bootInitrdPath = self.getBootPath(self.initrdPath) else: bootInitrdPath = "" bootFdtdir = self.getBootPath(self.dtbDir) extlinuxContents = extlinuxContents + "label " + self.linuxDistro + "\n\t" + "kernel " + bootKernelPath +"\n\tappend enforcing=0 root=" + self.getPartition("/") +"\n\t" + "fdtdir " + bootFdtdir +"\n" if bootInitrdPath != "none": extlinuxContents = extlinuxContents + "\tinitrd " + bootInitrdPath + "\n" self.initramfsScript.write ("cat > " + self.workDir +"/boot/extlinux/extlinux.conf << EOF\n" + extlinuxContents + "EOF\n") self.initramfsScript.write(self.getShellExitString(BoardTemplateParser.EXTLINUXCONF_ERROR)) elif self.kernelType == "stock": for kernelVer in self.stockKernels: extlinuxContents = extlinuxContents + "label " + self.linuxDistro + "\n\t" + "kernel /vmlinuz-" + kernelVer + "\n\tappend enforcing=0 root=" + self.getPartition("/") + "\n\tfdtdir /dtb-" + kernelVer + "\n\tinitrd /initramfs-" + kernelVer + ".img\n\n" self.initramfsScript.write ("cat > " + self.workDir +"/boot/extlinux/extlinux.conf << EOF\n" + extlinuxContents + "EOF\n") self.initramfsScript.write(self.getShellExitString(BoardTemplateParser.EXTLINUXCONF_ERROR)) self.initramfsScript.close() def makeBootable(self): """Creates /etc/fstab""" if not os.path.exists(self.etcOverlay): logging.error("Need Etc Overlay To Continue") sys.exit(BoardTemplateParser.NO_ETC_OVERLAY) try: fstab = open(self.etcOverlay+"/fstab","w") except: logging.error("Could Not Create fstab") sys.exit(BoardTemplateParser.FSTAB_ERROR) fstab.write("#Generated by RootFS Build Factory\n") for i in range(0,len(self.imageData)): if self.imageData[i][BoardTemplateParser.PTYPE] == "extended": continue partuuid = self.imageData[i][BoardTemplateParser.UUID] mountpoint = self.imageData[i][BoardTemplateParser.MOUNTPOINT] partitionPath = self.getPartition(mountpoint) fs = self.imageData[i][BoardTemplateParser.FS] fstab.write(partitionPath + " " + mountpoint + " " + fs + " noatime 0 0\n") fstab.close() def configureNetwork(self): """Configure Network""" logging.info("Reading Network Config") try: networkDom = self.boardDom.getElementsByTagName("network") except: logging.error("No Network Config Found") return networkConfigPath = self.etcOverlay+"/sysconfig/network-scripts" try: os.makedirs(networkConfigPath) except OSError as exc: if exc.errno == errno.EEXIST and os.path.isdir(networkConfigPath): pass else: raise for n in networkDom: interface = n.getElementsByTagName("interface") for i in interface: name = i.getAttribute("name") config = i.getAttribute("config") logging.info("Found Network Interface: " + name + " " + config) if config == "static": ipaddress = i.getElementsByTagName("ipaddress")[0].childNodes[0].data subnetmask = i.getElementsByTagName("subnetmask")[0].childNodes[0].data gateway = i.getElementsByTagName("gateway")[0].childNodes[0].data nameserver = i.getElementsByTagName("nameserver")[0].childNodes[0].data logging.info("IP Addres: " + ipaddress) ifcfg = open (networkConfigPath+"/ifcfg-"+name,"w") ifcfg.write("DEVICE=" + name + "\nBOOTPROTO=static\nNM_CONTROLLED=no\nONBOOT=yes\nIPADDR=" + ipaddress +"\nNETMASK=" + subnetmask + "\nGATEWAY=" + gateway+"\n") ifcfg.close() ifcfg = open (self.etcOverlay + "/resolv.conf", "a") ifcfg.write("nameserver " + nameserver+"\n") ifcfg.close() else: logging.info("IP Address: DHCP") ifcfg = open (networkConfigPath+"/ifcfg-"+name,"w") ifcfg.write("DEVICE=" + name + "\nBOOTPROTO=dhcp\nNM_CONTROLLED=no\nONBOOT=yes\n") ifcfg.close() def cleanUp(self): """CleanUp Steps""" logging.info("Clean Up") self.cleanupScript = open("cleanup.sh","w") for i in range(0,len(self.imageData)): if self.imageData[i][BoardTemplateParser.PTYPE] == "extended": continue if self.imageData[i][BoardTemplateParser.MOUNTPOINT] != "/" and self.imageData[i][BoardTemplateParser.MOUNTPOINT] != "swap": self.cleanupScript.write("umount " + self.workDir + self.imageData[i][BoardTemplateParser.MOUNTPOINT]+"\n") self.cleanupScript.write("umount " + self.workDir + "/proc\n") self.cleanupScript.write("umount " + self.workDir + "\n") self.cleanupScript.write(self.delDeviceIfExists(self.loopDevice)) self.cleanupScript.write("exit 0\n") self.cleanupScript.close() if self.action == "build": cleanupRet = subprocess.call(["/usr/bin/bash", "cleanup.sh"]) if cleanupRet != 0: logging.error (boardParser.RbfScriptErrors[cleanupRet]) sys.exit(BoardTemplateParser.CLEANUP_ERROR) logging.info("If you need any help, please provide rbf.log rbf.sh initramfs.sh cleanup.sh " + self.xmlTemplate + " and the above output.")