At http://git.infradead.org/?p=users/dwmw2/livecd-ppc.git (git://git.infradead.org/~dwmw2/livecd-ppc.git) there's a set of patches which first introduces a little abstraction for the arch-specific configureBootloader() and createIso() functions, then implements the PPC version.
1. Allow mayflower path to be specified, to run from git tree 2, Remove syslinux from package lists; add it dynamically instead. 3. Move x86-specific functions (createIso, configureBootloader) into subclass 4. Only create isolinux/ directory in x86-specific configureBootloader() 5. Add PowerPC support, add pata_mpc52xx module to mayflower.conf
The full patch is as follows...
diff --git a/config/livecd-fedora-desktop.ks b/config/livecd-fedora-desktop.ks index 1ee6fba..780e201 100644 --- a/config/livecd-fedora-desktop.ks +++ b/config/livecd-fedora-desktop.ks @@ -23,7 +23,6 @@ services --enabled=NetworkManager,dhcdbd --disabled=network,sshd @dial-up @hardware-support @printing -syslinux kernel
scim* diff --git a/config/livecd-fedora-kde.ks b/config/livecd-fedora-kde.ks index 20413b1..9aeceed 100644 --- a/config/livecd-fedora-kde.ks +++ b/config/livecd-fedora-kde.ks @@ -23,7 +23,6 @@ kernel dejavu-lgc-fonts setroubleshoot smolt -syslinux system-config-display xorg-x11-drivers
diff --git a/config/livecd-fedora-minimal.ks b/config/livecd-fedora-minimal.ks index e8065b6..db52912 100644 --- a/config/livecd-fedora-minimal.ks +++ b/config/livecd-fedora-minimal.ks @@ -17,7 +17,6 @@ repo --name=a-extras-dev --baseurl=http://download.fedora.redhat.com/pub/fedora/ %packages bash kernel -syslinux passwd policycoreutils chkconfig diff --git a/config/livedvd-fedora-kde.ks b/config/livedvd-fedora-kde.ks index 1ed2f57..71aa122 100644 --- a/config/livedvd-fedora-kde.ks +++ b/config/livedvd-fedora-kde.ks @@ -23,7 +23,6 @@ kernel dejavu-lgc-fonts setroubleshoot smolt -syslinux system-config-display xorg-x11-drivers
diff --git a/creator/livecd-creator b/creator/livecd-creator index a526b07..755e659 100755 --- a/creator/livecd-creator +++ b/creator/livecd-creator @@ -27,6 +27,8 @@ import traceback import subprocess import shutil import yum +import rpmUtils.arch +import rhpl import pykickstart.parser import pykickstart.version
@@ -277,6 +279,178 @@ class LiveCDYum(yum.YumBase): cb.filelog = False return self.runTransaction(cb)
+class InstallationArchPPC: + def __init__(self): + # For now we need anaconda-runtime, for bits like ofboot.b and mapping files. + # We could generate those ourselves though... + self.bootldr_package = ("yaboot","anaconda-runtime") + + def createIso(self, target): + """write out the live CD ISO""" + subprocess.call(["/usr/bin/mkisofs", "-o", "%s.iso" %(target.fs_label,), + "-hfs", "-hfs-bless", "%s/out/ppc/mac" %(target.build_dir), + "-hfs-volid", "%s" %(target.fs_label,), "-part", + "-map", "/usr/lib/anaconda-runtime/boot/mapping", + "-J", "-r", "-hide-rr-moved", "-no-desktop", + "-V", "%s" %(target.fs_label,), "%s/out" %(target.build_dir)]) + + def configureBootloader(self, target): + """configure the boot loader""" + + # Copy yaboot and ofboot.b in to mac directory + os.makedirs(target.build_dir + "/out/ppc/mac") + shutil.copyfile("%s/install_root/usr/lib/anaconda-runtime/boot/ofboot.b" %(target.build_dir), + "%s/out/ppc/mac/ofboot.b" %(target.build_dir,)) + shutil.copyfile("%s/install_root/usr/lib/yaboot/yaboot" %(target.build_dir), + "%s/out/ppc/mac/yaboot" %(target.build_dir,)) + + # Copy yaboot and ofboot.b in to mac directory + os.makedirs(target.build_dir + "/out/ppc/chrp") + shutil.copyfile("%s/install_root/usr/lib/anaconda-runtime/boot/bootinfo.txt" %(target.build_dir), + "%s/out/ppc/bootinfo.txt" %(target.build_dir,)) + shutil.copyfile("%s/install_root/usr/lib/yaboot/yaboot" %(target.build_dir), + "%s/out/ppc/chrp/yaboot" %(target.build_dir,)) + subprocess.call(["/usr/sbin/addnote", "%s/out/ppc/chrp/yaboot" %(target.build_dir,)]) + + os.makedirs(target.build_dir + "/out/ppc/ppc32") + shutil.copyfile("%s/install_root/boot/vmlinuz-%s" + %(target.build_dir, target.get_kernel_version()), + "%s/out/ppc/ppc32/vmlinuz" %(target.build_dir,)) + shutil.copyfile("%s/install_root/boot/livecd-initramfs.img" + %(target.build_dir,), + "%s/out/ppc/ppc32/initrd.img" %(target.build_dir,)) + os.unlink("%s/install_root/boot/livecd-initramfs.img" + %(target.build_dir,)) + + os.makedirs(target.build_dir + "/out/ppc/ppc64") + # FIXME: Need 64-bit kernel and initrd + + cfg32 = """ +init-message = "Welcome to the Fedora %(label)s LiveCD" +timeout=6000 + +""" %{"label": target.fs_label} + + stanzas = [("linux", "Run from image", ""), + ("runfromram", "Run from RAM - requires 1 GiB+", "live_ram")] + if os.path.exists("%s/install_root/usr/lib/anaconda-runtime/checkisomd5" %(target.build_dir,)): + stanzas.append( ("check", "Verify and run from image", "check") ) + + for (short, long, extra) in stanzas: + cfg32 += """ + +image=/ppc/ppc32/vmlinuz + label=%(short)s + initrd=/ppc/ppc32/initrd.img + read-only + append="ro quiet root=CDLABEL=%(label)s rootfstype=iso9660 %(extra)s" +""" %{"label": target.fs_label, + "short": short, "long": long, "extra": extra} + + cfgf = open("%s/out/ppc/ppc32/yaboot.conf" %(target.build_dir,), "w") + cfgf.write(cfg32) + cfgf.close() + os.makedirs(target.build_dir + "/out/etc") + cfgf = open("%s/out/etc/yaboot.conf" %(target.build_dir,), "w") + cfgf.write(cfg32) + cfgf.close() + + # FIXME. Obviously + cfg64 = """ +init-message = "Sorry, this LiveCD only supports 32-bit hardware" +""" + cfgf = open("%s/out/ppc/ppc64/yaboot.conf" %(target.build_dir,), "w") + cfgf.write(cfg64) + cfgf.close() + + # TODO: enable external entitity to partipate in adding boot entries + # build 'netboot' images with kernel+initrd, like mk-images.ppc + +class InstallationArchX86: + def __init__(self): + self.bootldr_package = ("syslinux",) + + def createIso(self, target): + """write out the live CD ISO""" + subprocess.call(["/usr/bin/mkisofs", "-o", "%s.iso" %(target.fs_label,), + "-b", "isolinux/isolinux.bin", + "-c", "isolinux/boot.cat", + "-no-emul-boot", "-boot-load-size", "4", + "-boot-info-table", "-J", "-r", "-hide-rr-moved", + "-V", "%s" %(target.fs_label,), "%s/out" %(target.build_dir)]) + + def configureBootloader(self, target): + """configure the boot loader""" + + # set up boot loader + # + # TODO: + # - fix for archs not using grub + # - fix for non-i386 + # - error handling + # + os.makedirs(target.build_dir + "/out/isolinux") + + shutil.copyfile("%s/install_root/boot/vmlinuz-%s" + %(target.build_dir, target.get_kernel_version()), + "%s/out/isolinux/vmlinuz" %(target.build_dir,)) + + shutil.copyfile("%s/install_root/boot/livecd-initramfs.img" + %(target.build_dir,), + "%s/out/isolinux/initrd.img" %(target.build_dir,)) + os.unlink("%s/install_root/boot/livecd-initramfs.img" + %(target.build_dir,)) + + for p in ["isolinux.bin", "vesamenu.c32"]: + path = "%s/install_root/usr/lib/syslinux/%s" % (target.build_dir, p) + + if not os.path.isfile(path): + raise InstallationError("syslinux not installed : %s not found" % path) + + shutil.copy(path, "%s/out/isolinux/%s" % (target.build_dir, p)) + + if os.path.exists("%s/install_root/usr/lib/anaconda-runtime/syslinux-vesa-splash.jpg" %(target.build_dir,)): + shutil.copy("%s/install_root/usr/lib/anaconda-runtime/syslinux-vesa-splash.jpg" %(target.build_dir,), + "%s/out/isolinux/splash.jpg" %(target.build_dir,)) + have_background = "menu background splash.jpg" + else: + have_background = "" + + cfg = """ +default vesamenu.c32 +timeout 600 + +%(background)s +menu title Welcome to %(label)s! +menu color border 0 #ffffffff #00000000 +menu color sel 0 #ffffffff #ff000000 +menu color title 0 #ffffffff #00000000 +menu color tabmsg 0 #ffffffff #00000000 +menu color unsel 0 #ffffffff #00000000 +menu color hotsel 0 #ff000000 #ffffffff +menu color hotkey 0 #ffffffff #ff000000 +""" %{"label": target.fs_label, "background" : have_background} + + stanzas = [("linux", "Run from image", ""), + ("runfromram", "Run from RAM - requires 1 GiB+", "live_ram")] + if os.path.exists("%s/install_root/usr/lib/anaconda-runtime/checkisomd5" %(target.build_dir,)): + stanzas.append( ("check", "Verify and run from image", "check") ) + + for (short, long, extra) in stanzas: + cfg += """label %(short)s + menu label %(long)s + kernel vmlinuz + append initrd=initrd.img ro quiet root=CDLABEL=%(label)s rootfstype=iso9660 liveimg %(extra)s +""" %{"label": target.fs_label, "background" : have_background, + "short": short, "long": long, "extra": extra} + + cfgf = open("%s/out/isolinux/isolinux.cfg" %(target.build_dir,), "w") + cfgf.write(cfg) + cfgf.close() + + # TODO: enable external entitity to partipate in adding boot entries + + class InstallationTarget: def __init__(self, repos, packages, epackages, groups, fs_label, skip_compression, skip_prelink): self.ayum = None @@ -293,6 +467,14 @@ class InstallationTarget: self.bindmounts = [] self.ksparser = None
+ myarch = rhpl.getArch() + if myarch == "i386" or myarch == "x86_64": + self.arch = InstallationArchX86() + elif myarch == "ppc": + self.arch = InstallationArchPPC() + else: + raise InstallationError("Do not know how to build LiveCD for arch '%s'" % (myarch,)) + def parse(self, kscfg): ksversion = pykickstart.version.makeVersion() self.ksparser = pykickstart.parser.KickstartParser(ksversion) @@ -377,7 +559,6 @@ class InstallationTarget: except OSError, (err, msg): raise InstallationError("Failed create build directory in /var/tmp: %s" % msg)
- os.makedirs(self.build_dir + "/out/isolinux") os.makedirs(self.build_dir + "/out/sysroot") os.makedirs(self.build_dir + "/data/sysroot") os.makedirs(self.build_dir + "/install_root") @@ -748,12 +929,12 @@ class InstallationTarget:
return kernels[0]
- def createInitramfs(self): + def createInitramfs(self, mayflower_path): # Create initramfs - if not os.path.isfile("/usr/lib/livecd-creator/mayflower"): + if not os.path.isfile(mayflower_path): raise InstallationError("livecd-creator not correctly installed : "+ - "/usr/lib/livecd-creator/mayflower not found") - shutil.copy("/usr/lib/livecd-creator/mayflower", + mayflower_path+" not found") + shutil.copy(mayflower_path, "%s/install_root/sbin/mayflower" %(self.build_dir,)) # modules needed for booting (this is butt ugly and we need to retrieve this from elsewhere, e.g. the kernel) mayflowerconf = open(self.build_dir + "/install_root/etc/mayflower.conf", "w") @@ -761,7 +942,7 @@ class InstallationTarget: mayflowerconf.write('MODULES+="sata_mv sata_qstor sata_sis sata_uli "\n') mayflowerconf.write('MODULES+="sata_nv sata_sil24 sata_svw sata_via "\n') mayflowerconf.write('MODULES+="sata_promise sata_sil sata_sx4 sata_vsc "\n') - mayflowerconf.write('MODULES+="ata_generic pata_ali pata_amd pata_artop pata_atiixp pata_cmd64x pata_cs5520 pata_cs5530 pata_cs5535 pata_cypress pata_efar pata_hpt366 pata_hpt37x pata_hpt3x2n pata_hpt3x3 pata_isapnp pata_it821x pata_jmicron pata_marvell pata_mpiix pata_netcell pata_ns87410 pata_oldpiix pata_optidma pata_opti pata_pcmcia pata_pdc2027x pata_pdc202xx_old pata_qdi pata_serverworks pata_sil680 pata_sis pata_sl82c105 pata_triflex pata_via pdc_adma "\n') + mayflowerconf.write('MODULES+="ata_generic pata_ali pata_amd pata_artop pata_atiixp pata_cmd64x pata_cs5520 pata_cs5530 pata_cs5535 pata_cypress pata_efar pata_hpt366 pata_hpt37x pata_hpt3x2n pata_hpt3x3 pata_isapnp pata_it821x pata_jmicron pata_marvell pata_mpiix pata_netcell pata_ns87410 pata_oldpiix pata_optidma pata_opti pata_pcmcia pata_pdc2027x pata_pdc202xx_old pata_qdi pata_serverworks pata_sil680 pata_sis pata_sl82c105 pata_triflex pata_via pdc_adma pata_mpc52xx "\n') mayflowerconf.close()
subprocess.call(["/sbin/mayflower", "-f", "/boot/livecd-initramfs.img", @@ -789,76 +970,8 @@ class InstallationTarget: def launchShell(self): subprocess.call(["/bin/bash"], preexec_fn=self.run_in_root)
- def configureBootloader(self): - """configure the boot loader""" - - # set up boot loader - # - # TODO: - # - fix for archs not using grub - # - fix for non-i386 - # - error handling - # - shutil.copyfile("%s/install_root/boot/vmlinuz-%s" - %(self.build_dir, self.get_kernel_version()), - "%s/out/isolinux/vmlinuz" %(self.build_dir,)) - - shutil.copyfile("%s/install_root/boot/livecd-initramfs.img" - %(self.build_dir,), - "%s/out/isolinux/initrd.img" %(self.build_dir,)) - os.unlink("%s/install_root/boot/livecd-initramfs.img" - %(self.build_dir,)) - - for p in ["isolinux.bin", "vesamenu.c32"]: - path = "%s/install_root/usr/lib/syslinux/%s" % (self.build_dir, p) - - if not os.path.isfile(path): - raise InstallationError("syslinux not installed : %s not found" % path) - - shutil.copy(path, "%s/out/isolinux/%s" % (self.build_dir, p)) - - if os.path.exists("%s/install_root/usr/lib/anaconda-runtime/syslinux-vesa-splash.jpg" %(self.build_dir,)): - shutil.copy("%s/install_root/usr/lib/anaconda-runtime/syslinux-vesa-splash.jpg" %(self.build_dir,), - "%s/out/isolinux/splash.jpg" %(self.build_dir,)) - have_background = "menu background splash.jpg" - else: - have_background = "" - - cfg = """ -default vesamenu.c32 -timeout 600 - -%(background)s -menu title Welcome to %(label)s! -menu color border 0 #ffffffff #00000000 -menu color sel 0 #ffffffff #ff000000 -menu color title 0 #ffffffff #00000000 -menu color tabmsg 0 #ffffffff #00000000 -menu color unsel 0 #ffffffff #00000000 -menu color hotsel 0 #ff000000 #ffffffff -menu color hotkey 0 #ffffffff #ff000000 -""" %{"label": self.fs_label, "background" : have_background} - - stanzas = [("linux", "Run from image", ""), - ("runfromram", "Run from RAM - requires 1 GB+", "live_ram")] - if os.path.exists("%s/install_root/usr/lib/anaconda-runtime/checkisomd5" %(self.build_dir,)): - stanzas.append( ("check", "Verify and run from image", "check") ) - - for (short, long, extra) in stanzas: - cfg += """label %(short)s - menu label %(long)s - kernel vmlinuz - append initrd=initrd.img ro quiet root=CDLABEL=%(label)s rootfstype=iso9660 liveimg %(extra)s -""" %{"label": self.fs_label, "background" : have_background, - "short": short, "long": long, "extra": extra} - - cfgf = open("%s/out/isolinux/isolinux.cfg" %(self.build_dir,), "w") - cfgf.write(cfg) - cfgf.close()
- # TODO: enable external entitity to partipate in adding boot entries - - def install(self): + def install(self, mayflower_path): for (name, url) in self.repos: self.ayum.addRepository(name, url)
@@ -868,24 +981,8 @@ menu color hotkey 0 #ffffffff #ff000000 self.relabelSystem() if not self.skip_prelink: self.prelinkSystem() - self.createInitramfs() - self.configureBootloader() - - def createIso(self): - """write out the live CD ISO""" - subprocess.call(["/usr/bin/mkisofs", "-o", "%s.iso" %(self.fs_label,), - "-b", "isolinux/isolinux.bin", - "-c", "isolinux/boot.cat", - "-no-emul-boot", "-boot-load-size", "4", - "-boot-info-table", "-J", "-r", "-hide-rr-moved", - "-V", "%s" %(self.fs_label,), "%s/out" %(self.build_dir)]) - - # implant an isomd5sum - if os.path.exists("/usr/lib/anaconda-runtime/implantisomd5"): - subprocess.call(["/usr/lib/anaconda-runtime/implantisomd5", - "%s.iso" %(self.fs_label,)]) - else: - print >> sys.stderr, "anaconda-runtime not installed; not setting up mediacheck" + self.createInitramfs(mayflower_path) + self.arch.configureBootloader(self)
def createSquashFS(self): """create compressed squashfs file system""" @@ -901,7 +998,14 @@ menu color hotkey 0 #ffffffff #ff000000
def package(self): self.createSquashFS() - self.createIso() + self.arch.createIso(self) + # implant an isomd5sum + if os.path.exists("/usr/lib/anaconda-runtime/implantisomd5"): + subprocess.call(["/usr/lib/anaconda-runtime/implantisomd5", + "%s.iso" %(self.fs_label,)]) + else: + print >> sys.stderr, "anaconda-runtime not installed; not setting up mediacheck" +
def usage(out): print >> out, """ @@ -911,9 +1015,9 @@ usage: livecd-creator [--help] [--package=<p1>] [--package=<p2> ...] [--exclude-package=<e1>] [--exclude-package=<e2> ...] [--base-on=<path-to-iso-file>] - [--fslabel=<label>] + [--fslabel=<label>] [--mayflower=<path-to-mayflower-script>] [--skip-compression] - [--uncompressed-size=<size-in-MB>] + [--uncompressed-size=<size-in-MiB>] [--shell]
--help : Print usage and exit @@ -923,9 +1027,10 @@ usage: livecd-creator [--help] --exclude-package : Exclude this package --base-on : Add packages to an existing live CD iso9660 image --fslabel : File system label (default: livecd-YYYYMMDD-HHMI) + --mayflower : Path to mayflower script --skip-compression : Don't compress the image --prelink : Prelink the image - --uncompressed-size : Size of uncompressed fs in MB (default: 4096) + --uncompressed-size : Size of uncompressed fs in MiB (default: 4096) --shell : Start a shell in the chroot for post-configuration
Examples: @@ -952,6 +1057,7 @@ class Options: self.fs_label = "livecd-" + time.strftime("%Y%m%d-%H%M") self.base_on = None self.kscfg = None + self.mayflower_path = "/usr/lib/livecd-creator/mayflower" self.skip_compression = False self.skip_prelink = True self.uncompressed_size = 4096 @@ -963,7 +1069,7 @@ def parse_options(args): ["help", "repo=", "base-on=", "package=", "exclude-package=", "fslabel=", "config=", "skip-compression", "uncompressed-size=", - "shell", "no-prelink", "prelink"]) + "mayflower=", "shell", "no-prelink", "prelink"]) except getopt.GetoptError, msg: raise Usage(msg)
@@ -992,6 +1098,11 @@ def parse_options(args): if not os.path.isfile(options.kscfg): raise Usage("Kickstart config '%s' does not exist" % options.kscfg) continue + if o in ("--mayflower"): + options.mayflower_path = a + if not os.path.isfile(options.mayflower_path): + raise Usage("Mayflower script '%s' does not exist" % options.mayflower_path) + continue if o in ("-r", "--repo"): (name, url) = a.split(",") for (n, u) in options.repos: @@ -1057,10 +1168,12 @@ def main():
try: target.parse(options.kscfg) + + target.packages.extend(target.arch.bootldr_package)
target.setup(options.uncompressed_size, options.base_on)
- target.install() + target.install(options.mayflower_path)
if options.give_shell: print "Launching shell. Exit to continue."