fix bootloader options omitted
[tools/mic.git] / mic / imager / livecd.py
1 #!/usr/bin/python -tt
2 #
3 # Copyright (c) 2011 Intel, Inc.
4 #
5 # This program is free software; you can redistribute it and/or modify it
6 # under the terms of the GNU General Public License as published by the Free
7 # Software Foundation; version 2 of the License
8 #
9 # This program is distributed in the hope that it will be useful, but
10 # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
11 # or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12 # for more details.
13 #
14 # You should have received a copy of the GNU General Public License along
15 # with this program; if not, write to the Free Software Foundation, Inc., 59
16 # Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17
18 import os, sys
19 import glob
20 import shutil
21
22 from mic import kickstart, msger
23 from mic.utils import fs_related, rpmmisc, runner, misc
24 from mic.utils.errors import CreatorError
25 from mic.imager.loop import LoopImageCreator
26
27
28 class LiveImageCreatorBase(LoopImageCreator):
29     """A base class for LiveCD image creators.
30
31         This class serves as a base class for the architecture-specific LiveCD
32         image creator subclass, LiveImageCreator.
33
34         LiveImageCreator creates a bootable ISO containing the system image,
35         bootloader, bootloader configuration, kernel and initramfs.
36     """
37
38     def __init__(self, creatoropts = None, pkgmgr = None):
39         """Initialise a LiveImageCreator instance.
40
41            This method takes the same arguments as ImageCreator.__init__().
42         """
43         LoopImageCreator.__init__(self, creatoropts, pkgmgr)
44
45         #Controls whether to use squashfs to compress the image.
46         self.skip_compression = False
47
48         #Controls whether an image minimizing snapshot should be created.
49         #
50         #This snapshot can be used when copying the system image from the ISO in
51         #order to minimize the amount of data that needs to be copied; simply,
52         #it makes it possible to create a version of the image's filesystem with
53         #no spare space.
54         self.skip_minimize = False
55
56         #A flag which indicates i act as a convertor default false
57         self.actasconvertor = False
58
59         #The bootloader timeout from kickstart.
60         if self.ks:
61             self._timeout = kickstart.get_timeout(self.ks, 10)
62         else:
63             self._timeout = 10
64
65         #The default kernel type from kickstart.
66         if self.ks:
67             self._default_kernel = kickstart.get_default_kernel(self.ks,
68                                                                 "kernel")
69         else:
70             self._default_kernel = None
71
72         if self.ks:
73             parts = kickstart.get_partitions(self.ks)
74             if len(parts) > 1:
75                 raise CreatorError("Can't support multi partitions in ks file "
76                                    "for this image type")
77             # FIXME: rename rootfs img to self.name,
78             # else can't find files when create iso
79             self._instloops[0]['name'] = self.name + ".img"
80
81         self.__isodir = None
82
83         self.__modules = ["=ata",
84                           "sym53c8xx",
85                           "aic7xxx",
86                           "=usb",
87                           "=firewire",
88                           "=mmc",
89                           "=pcmcia",
90                           "mptsas"]
91         if self.ks:
92             self.__modules.extend(kickstart.get_modules(self.ks))
93
94         self._dep_checks.extend(["isohybrid",
95                                  "unsquashfs",
96                                  "mksquashfs",
97                                  "dd",
98                                  "genisoimage"])
99
100     #
101     # Hooks for subclasses
102     #
103     def _configure_bootloader(self, isodir):
104         """Create the architecture specific booloader configuration.
105
106             This is the hook where subclasses must create the booloader
107             configuration in order to allow a bootable ISO to be built.
108
109             isodir -- the directory where the contents of the ISO are to
110                       be staged
111         """
112         raise CreatorError("Bootloader configuration is arch-specific, "
113                            "but not implemented for this arch!")
114     def _get_menu_options(self):
115         """Return a menu options string for syslinux configuration.
116         """
117         if self.ks is None:
118             return "liveinst autoinst"
119         r = kickstart.get_menu_args(self.ks)
120         return r
121
122     def _get_kernel_options(self):
123         """Return a kernel options string for bootloader configuration.
124
125             This is the hook where subclasses may specify a set of kernel
126             options which should be included in the images bootloader
127             configuration.
128
129             A sensible default implementation is provided.
130         """
131
132         if self.ks is None:
133             r = "ro rd.live.image"
134         else:
135             r = kickstart.get_kernel_args(self.ks)
136
137         return r
138
139     def _get_mkisofs_options(self, isodir):
140         """Return the architecture specific mkisosfs options.
141
142             This is the hook where subclasses may specify additional arguments
143             to mkisofs, e.g. to enable a bootable ISO to be built.
144
145             By default, an empty list is returned.
146         """
147         return []
148
149     #
150     # Helpers for subclasses
151     #
152     def _has_checkisomd5(self):
153         """Check whether checkisomd5 is available in the install root."""
154         def _exists(path):
155             return os.path.exists(self._instroot + path)
156
157         if _exists("/usr/bin/checkisomd5") and os.path.exists("/usr/bin/implantisomd5"):
158             return True
159
160         return False
161
162     def __restore_file(self,path):
163         try:
164             os.unlink(path)
165         except:
166             pass
167         if os.path.exists(path + '.rpmnew'):
168             os.rename(path + '.rpmnew', path)
169
170     def _mount_instroot(self, base_on = None):
171         LoopImageCreator._mount_instroot(self, base_on)
172         self.__write_initrd_conf(self._instroot + "/etc/sysconfig/mkinitrd")
173         self.__write_dracut_conf(self._instroot + "/etc/dracut.conf.d/02livecd.conf")
174
175     def _unmount_instroot(self):
176         self.__restore_file(self._instroot + "/etc/sysconfig/mkinitrd")
177         self.__restore_file(self._instroot + "/etc/dracut.conf.d/02livecd.conf")
178         LoopImageCreator._unmount_instroot(self)
179
180     def __ensure_isodir(self):
181         if self.__isodir is None:
182             self.__isodir = self._mkdtemp("iso-")
183         return self.__isodir
184
185     def _get_isodir(self):
186         return self.__ensure_isodir()
187
188     def _set_isodir(self, isodir = None):
189         self.__isodir = isodir
190
191     def _create_bootconfig(self):
192         """Configure the image so that it's bootable."""
193         self._configure_bootloader(self.__ensure_isodir())
194
195     def _get_post_scripts_env(self, in_chroot):
196         env = LoopImageCreator._get_post_scripts_env(self, in_chroot)
197
198         if not in_chroot:
199             env["LIVE_ROOT"] = self.__ensure_isodir()
200
201         return env
202     def __write_dracut_conf(self, path):
203         if not os.path.exists(os.path.dirname(path)):
204             fs_related.makedirs(os.path.dirname(path))
205         f = open(path, "a")
206         f.write('add_dracutmodules+=" dmsquash-live pollcdrom "')
207         f.close()
208
209     def __write_initrd_conf(self, path):
210         content = ""
211         if not os.path.exists(os.path.dirname(path)):
212             fs_related.makedirs(os.path.dirname(path))
213         f = open(path, "w")
214
215         content += 'LIVEOS="yes"\n'
216         content += 'PROBE="no"\n'
217         content += 'MODULES+="squashfs ext3 ext2 vfat msdos "\n'
218         content += 'MODULES+="sr_mod sd_mod ide-cd cdrom "\n'
219
220         for module in self.__modules:
221             if module == "=usb":
222                 content += 'MODULES+="ehci_hcd uhci_hcd ohci_hcd "\n'
223                 content += 'MODULES+="usb_storage usbhid "\n'
224             elif module == "=firewire":
225                 content += 'MODULES+="firewire-sbp2 firewire-ohci "\n'
226                 content += 'MODULES+="sbp2 ohci1394 ieee1394 "\n'
227             elif module == "=mmc":
228                 content += 'MODULES+="mmc_block sdhci sdhci-pci "\n'
229             elif module == "=pcmcia":
230                 content += 'MODULES+="pata_pcmcia  "\n'
231             else:
232                 content += 'MODULES+="' + module + ' "\n'
233         f.write(content)
234         f.close()
235
236     def __create_iso(self, isodir):
237         iso = self._outdir + "/" + self.name + ".iso"
238         genisoimage = fs_related.find_binary_path("genisoimage")
239         args = [genisoimage,
240                 "-J", "-r",
241                 "-hide-rr-moved", "-hide-joliet-trans-tbl",
242                 "-V", self.fslabel,
243                 "-o", iso]
244
245         args.extend(self._get_mkisofs_options(isodir))
246
247         args.append(isodir)
248
249         if runner.show(args) != 0:
250             raise CreatorError("ISO creation failed!")
251
252         """ It should be ok still even if you haven't isohybrid """
253         isohybrid = None
254         try:
255             isohybrid = fs_related.find_binary_path("isohybrid")
256         except:
257             pass
258
259         if isohybrid:
260             args = [isohybrid, "-partok", iso ]
261             if runner.show(args) != 0:
262                 raise CreatorError("Hybrid ISO creation failed!")
263
264         self.__implant_md5sum(iso)
265
266     def __implant_md5sum(self, iso):
267         """Implant an isomd5sum."""
268         if os.path.exists("/usr/bin/implantisomd5"):
269             implantisomd5 = "/usr/bin/implantisomd5"
270         else:
271             msger.warning("isomd5sum not installed; not setting up mediacheck")
272             implantisomd5 = ""
273             return
274
275         runner.show([implantisomd5, iso])
276
277     def _stage_final_image(self):
278         try:
279             fs_related.makedirs(self.__ensure_isodir() + "/LiveOS")
280
281             minimal_size = self._resparse()
282
283             if not self.skip_minimize:
284                 fs_related.create_image_minimizer(self.__isodir + \
285                                                       "/LiveOS/osmin.img",
286                                                   self._image,
287                                                   minimal_size)
288
289             if self.skip_compression:
290                 shutil.move(self._image, self.__isodir + "/LiveOS/ext3fs.img")
291             else:
292                 fs_related.makedirs(os.path.join(
293                                         os.path.dirname(self._image),
294                                         "LiveOS"))
295                 shutil.move(self._image,
296                             os.path.join(os.path.dirname(self._image),
297                                          "LiveOS", "ext3fs.img"))
298                 fs_related.mksquashfs(os.path.dirname(self._image),
299                            self.__isodir + "/LiveOS/squashfs.img")
300
301             self.__create_iso(self.__isodir)
302
303             if self.pack_to:
304                 isoimg = os.path.join(self._outdir, self.name + ".iso")
305                 packimg = os.path.join(self._outdir, self.pack_to)
306                 misc.packing(packimg, isoimg)
307                 os.unlink(isoimg)
308
309         finally:
310             shutil.rmtree(self.__isodir, ignore_errors = True)
311             self.__isodir = None
312
313 class x86LiveImageCreator(LiveImageCreatorBase):
314     """ImageCreator for x86 machines"""
315     def _get_mkisofs_options(self, isodir):
316         return [ "-b", "isolinux/isolinux.bin",
317                  "-c", "isolinux/boot.cat",
318                  "-no-emul-boot", "-boot-info-table",
319                  "-boot-load-size", "4" ]
320
321     def _get_required_packages(self):
322         return ["syslinux", "syslinux-extlinux"] + \
323                LiveImageCreatorBase._get_required_packages(self)
324
325     def _get_isolinux_stanzas(self, isodir):
326         return ""
327
328     def __find_syslinux_menu(self):
329         for menu in ["vesamenu.c32", "menu.c32"]:
330             if os.path.isfile(self._instroot + "/usr/share/syslinux/" + menu):
331                 return menu
332
333         raise CreatorError("syslinux not installed : "
334                            "no suitable /usr/share/syslinux/*menu.c32 found")
335
336     def __find_syslinux_mboot(self):
337         #
338         # We only need the mboot module if we have any xen hypervisors
339         #
340         if not glob.glob(self._instroot + "/boot/xen.gz*"):
341             return None
342
343         return "mboot.c32"
344
345     def __copy_syslinux_files(self, isodir, menu, mboot = None):
346         files = ["isolinux.bin", menu]
347         if mboot:
348             files += [mboot]
349
350         for f in files:
351             path = self._instroot + "/usr/share/syslinux/" + f
352
353             if not os.path.isfile(path):
354                 raise CreatorError("syslinux not installed : "
355                                    "%s not found" % path)
356
357             shutil.copy(path, isodir + "/isolinux/")
358
359     def __copy_syslinux_background(self, isodest):
360         background_path = self._instroot + \
361                           "/usr/share/branding/default/syslinux/syslinux-vesa-splash.jpg"
362
363         if not os.path.exists(background_path):
364             return False
365
366         shutil.copyfile(background_path, isodest)
367
368         return True
369
370     def __copy_kernel_and_initramfs(self, isodir, version, index):
371         bootdir = self._instroot + "/boot"
372         isDracut = False
373
374         if self._alt_initrd_name:
375             src_initrd_path = os.path.join(bootdir, self._alt_initrd_name)
376         else:
377             if os.path.exists(bootdir + "/initramfs-" + version + ".img"):
378                 src_initrd_path = os.path.join(bootdir, "initramfs-" +version+ ".img")
379                 isDracut = True
380             else:
381                 src_initrd_path = os.path.join(bootdir, "initrd-" +version+ ".img")
382
383         try:
384             msger.debug("copy %s to %s" % (bootdir + "/vmlinuz-" + version, isodir + "/isolinux/vmlinuz" + index))
385             shutil.copyfile(bootdir + "/vmlinuz-" + version,
386                     isodir + "/isolinux/vmlinuz" + index)
387
388             msger.debug("copy %s to %s" % (src_initrd_path, isodir + "/isolinux/initrd" + index + ".img"))
389             shutil.copyfile(src_initrd_path,
390                             isodir + "/isolinux/initrd" + index + ".img")
391         except:
392             raise CreatorError("Unable to copy valid kernels or initrds, "
393                                "please check the repo.")
394
395         is_xen = False
396         if os.path.exists(bootdir + "/xen.gz-" + version[:-3]):
397             shutil.copyfile(bootdir + "/xen.gz-" + version[:-3],
398                             isodir + "/isolinux/xen" + index + ".gz")
399             is_xen = True
400
401         return (is_xen,isDracut)
402
403     def __is_default_kernel(self, kernel, kernels):
404         if len(kernels) == 1:
405             return True
406
407         if kernel == self._default_kernel:
408             return True
409
410         if kernel.startswith("kernel-") and kernel[7:] == self._default_kernel:
411             return True
412
413         return False
414
415     def __get_basic_syslinux_config(self, **args):
416         return """
417 default %(menu)s
418 timeout %(timeout)d
419
420 %(background)s
421 menu title Welcome to %(distroname)s!
422 menu color border 0 #ffffffff #00000000
423 menu color sel 7 #ff000000 #ffffffff
424 menu color title 0 #ffffffff #00000000
425 menu color tabmsg 0 #ffffffff #00000000
426 menu color unsel 0 #ffffffff #00000000
427 menu color hotsel 0 #ff000000 #ffffffff
428 menu color hotkey 7 #ffffffff #ff000000
429 menu color timeout_msg 0 #ffffffff #00000000
430 menu color timeout 0 #ffffffff #00000000
431 menu color cmdline 0 #ffffffff #00000000
432 menu hidden
433 menu clear
434 """ % args
435
436     def __get_image_stanza(self, is_xen, isDracut, **args):
437         if isDracut:
438             args["rootlabel"] = "live:CDLABEL=%(fslabel)s" % args
439         else:
440             args["rootlabel"] = "CDLABEL=%(fslabel)s" % args
441         if not is_xen:
442             template = """label %(short)s
443   menu label %(long)s
444   kernel vmlinuz%(index)s
445   append initrd=initrd%(index)s.img root=%(rootlabel)s rootfstype=iso9660 %(liveargs)s %(extra)s
446 """
447         else:
448             template = """label %(short)s
449   menu label %(long)s
450   kernel mboot.c32
451   append xen%(index)s.gz --- vmlinuz%(index)s root=%(rootlabel)s rootfstype=iso9660 %(liveargs)s %(extra)s --- initrd%(index)s.img
452 """
453         return template % args
454
455     def __get_image_stanzas(self, isodir):
456         versions = []
457         kernels = self._get_kernel_versions()
458         for kernel in kernels:
459             for version in kernels[kernel]:
460                 versions.append(version)
461
462         if not versions:
463             raise CreatorError("Unable to find valid kernels, "
464                                "please check the repo")
465
466         kernel_options = self._get_kernel_options()
467
468         """ menu can be customized highly, the format is:
469
470           short_name1:long_name1:extra_opts1;short_name2:long_name2:extra_opts2
471
472         e.g.: autoinst:InstallationOnly:systemd.unit=installer-graphical.service
473         but in order to keep compatible with old format, these are still ok:
474
475               liveinst autoinst
476               liveinst;autoinst
477               liveinst::;autoinst::
478         """
479         oldmenus = {"basic": {
480                         "short": "basic",
481                         "long": "Installation Only (Text based)",
482                         "extra": "basic nosplash 4"
483                     },
484                     "liveinst": {
485                         "short": "liveinst",
486                         "long": "Installation Only",
487                         "extra": "liveinst nosplash 4"
488                     },
489                     "autoinst": {
490                         "short": "autoinst",
491                         "long": "Autoinstall (Deletes all existing content)",
492                         "extra": "autoinst nosplash 4"
493                     },
494                     "netinst": {
495                         "short": "netinst",
496                         "long": "Network Installation",
497                         "extra": "netinst 4"
498                     },
499                     "verify": {
500                         "short": "check",
501                         "long": "Verify and",
502                         "extra": "check"
503                     }
504                    }
505         menu_options = self._get_menu_options()
506         menus = menu_options.split(";")
507         for i in range(len(menus)):
508             menus[i] = menus[i].split(":")
509         if len(menus) == 1 and len(menus[0]) == 1:
510             """ Keep compatible with the old usage way """
511             menus = menu_options.split()
512             for i in range(len(menus)):
513                 menus[i] = [menus[i]]
514
515         cfg = ""
516
517         default_version = None
518         default_index = None
519         index = "0"
520         netinst = None
521         for version in versions:
522             (is_xen, isDracut) = self.__copy_kernel_and_initramfs(isodir, version, index)
523             if index == "0":
524                 self._isDracut = isDracut
525
526             default = self.__is_default_kernel(kernel, kernels)
527
528             if default:
529                 long = "Boot %s" % self.distro_name
530             elif kernel.startswith("kernel-"):
531                 long = "Boot %s(%s)" % (self.name, kernel[7:])
532             else:
533                 long = "Boot %s(%s)" % (self.name, kernel)
534
535             oldmenus["verify"]["long"] = "%s %s" % (oldmenus["verify"]["long"],
536                                                     long)
537             # tell dracut not to ask for LUKS passwords or activate mdraid sets
538             if isDracut:
539                 kern_opts = kernel_options + " rd.luks=0 rd.md=0 rd.dm=0"
540             else:
541                 kern_opts = kernel_options
542
543             cfg += self.__get_image_stanza(is_xen, isDracut,
544                                            fslabel = self.fslabel,
545                                            liveargs = kern_opts,
546                                            long = long,
547                                            short = "linux" + index,
548                                            extra = "",
549                                            index = index)
550
551             if default:
552                 cfg += "menu default\n"
553                 default_version = version
554                 default_index = index
555
556             for menu in menus:
557                 if not menu[0]:
558                     continue
559                 short = menu[0] + index
560
561                 if len(menu) >= 2:
562                     long = menu[1]
563                 else:
564                     if menu[0] in oldmenus.keys():
565                         if menu[0] == "verify" and not self._has_checkisomd5():
566                             continue
567                         if menu[0] == "netinst":
568                             netinst = oldmenus[menu[0]]
569                             continue
570                         long = oldmenus[menu[0]]["long"]
571                         extra = oldmenus[menu[0]]["extra"]
572                     else:
573                         long = short.upper() + " X" + index
574                         extra = ""
575
576                 if len(menu) >= 3:
577                     extra = ' '.join(menu[2:])
578
579                 cfg += self.__get_image_stanza(is_xen, isDracut,
580                                                fslabel = self.fslabel,
581                                                liveargs = kernel_options,
582                                                long = long,
583                                                short = short,
584                                                extra = extra,
585                                                index = index)
586
587             index = str(int(index) + 1)
588
589         if not default_version:
590             default_version = versions[0]
591         if not default_index:
592             default_index = "0"
593
594         if netinst:
595             cfg += self.__get_image_stanza(is_xen, isDracut,
596                                            fslabel = self.fslabel,
597                                            liveargs = kernel_options,
598                                            long = netinst["long"],
599                                            short = netinst["short"],
600                                            extra = netinst["extra"],
601                                            index = default_index)
602
603         return cfg
604
605     def __get_memtest_stanza(self, isodir):
606         memtest = glob.glob(self._instroot + "/boot/memtest86*")
607         if not memtest:
608             return ""
609
610         shutil.copyfile(memtest[0], isodir + "/isolinux/memtest")
611
612         return """label memtest
613   menu label Memory Test
614   kernel memtest
615 """
616
617     def __get_local_stanza(self, isodir):
618         return """label local
619   menu label Boot from local drive
620   localboot 0xffff
621 """
622
623     def _configure_syslinux_bootloader(self, isodir):
624         """configure the boot loader"""
625         fs_related.makedirs(isodir + "/isolinux")
626
627         menu = self.__find_syslinux_menu()
628
629         self.__copy_syslinux_files(isodir, menu,
630                                    self.__find_syslinux_mboot())
631
632         background = ""
633         if self.__copy_syslinux_background(isodir + "/isolinux/splash.jpg"):
634             background = "menu background splash.jpg"
635
636         cfg = self.__get_basic_syslinux_config(menu = menu,
637                                                background = background,
638                                                name = self.name,
639                                                timeout = self._timeout * 10,
640                                                distroname = self.distro_name)
641
642         cfg += self.__get_image_stanzas(isodir)
643         cfg += self.__get_memtest_stanza(isodir)
644         cfg += self.__get_local_stanza(isodir)
645         cfg += self._get_isolinux_stanzas(isodir)
646
647         cfgf = open(isodir + "/isolinux/isolinux.cfg", "w")
648         cfgf.write(cfg)
649         cfgf.close()
650
651     def __copy_efi_files(self, isodir):
652         if not os.path.exists(self._instroot + "/boot/efi/EFI/redhat/grub.efi"):
653             return False
654         shutil.copy(self._instroot + "/boot/efi/EFI/redhat/grub.efi",
655                     isodir + "/EFI/boot/grub.efi")
656         shutil.copy(self._instroot + "/boot/grub/splash.xpm.gz",
657                     isodir + "/EFI/boot/splash.xpm.gz")
658
659         return True
660
661     def __get_basic_efi_config(self, **args):
662         return """
663 default=0
664 splashimage=/EFI/boot/splash.xpm.gz
665 timeout %(timeout)d
666 hiddenmenu
667
668 """ %args
669
670     def __get_efi_image_stanza(self, **args):
671         return """title %(long)s
672   kernel /EFI/boot/vmlinuz%(index)s root=CDLABEL=%(fslabel)s rootfstype=iso9660 %(liveargs)s %(extra)s
673   initrd /EFI/boot/initrd%(index)s.img
674 """ %args
675
676     def __get_efi_image_stanzas(self, isodir, name):
677         # FIXME: this only supports one kernel right now...
678
679         kernel_options = self._get_kernel_options()
680         checkisomd5 = self._has_checkisomd5()
681
682         cfg = ""
683
684         for index in range(0, 9):
685             # we don't support xen kernels
686             if os.path.exists("%s/EFI/boot/xen%d.gz" %(isodir, index)):
687                 continue
688             cfg += self.__get_efi_image_stanza(fslabel = self.fslabel,
689                                                liveargs = kernel_options,
690                                                long = name,
691                                                extra = "", index = index)
692             if checkisomd5:
693                 cfg += self.__get_efi_image_stanza(
694                                                fslabel = self.fslabel,
695                                                liveargs = kernel_options,
696                                                long = "Verify and Boot " + name,
697                                                extra = "check",
698                                                index = index)
699             break
700
701         return cfg
702
703     def _configure_efi_bootloader(self, isodir):
704         """Set up the configuration for an EFI bootloader"""
705         fs_related.makedirs(isodir + "/EFI/boot")
706
707         if not self.__copy_efi_files(isodir):
708             shutil.rmtree(isodir + "/EFI")
709             return
710
711         for f in os.listdir(isodir + "/isolinux"):
712             os.link("%s/isolinux/%s" %(isodir, f),
713                     "%s/EFI/boot/%s" %(isodir, f))
714
715
716         cfg = self.__get_basic_efi_config(name = self.name,
717                                           timeout = self._timeout)
718         cfg += self.__get_efi_image_stanzas(isodir, self.name)
719
720         cfgf = open(isodir + "/EFI/boot/grub.conf", "w")
721         cfgf.write(cfg)
722         cfgf.close()
723
724         # first gen mactel machines get the bootloader name wrong apparently
725         if rpmmisc.getBaseArch() == "i386":
726             os.link(isodir + "/EFI/boot/grub.efi",
727                     isodir + "/EFI/boot/boot.efi")
728             os.link(isodir + "/EFI/boot/grub.conf",
729                     isodir + "/EFI/boot/boot.conf")
730
731         # for most things, we want them named boot$efiarch
732         efiarch = {"i386": "ia32", "x86_64": "x64"}
733         efiname = efiarch[rpmmisc.getBaseArch()]
734         os.rename(isodir + "/EFI/boot/grub.efi",
735                   isodir + "/EFI/boot/boot%s.efi" %(efiname,))
736         os.link(isodir + "/EFI/boot/grub.conf",
737                 isodir + "/EFI/boot/boot%s.conf" %(efiname,))
738
739
740     def _configure_bootloader(self, isodir):
741         self._configure_syslinux_bootloader(isodir)
742         self._configure_efi_bootloader(isodir)
743
744 arch = rpmmisc.getBaseArch()
745 if arch in ("i386", "x86_64"):
746     LiveCDImageCreator = x86LiveImageCreator
747 elif arch.startswith("arm"):
748     LiveCDImageCreator = LiveImageCreatorBase
749 else:
750     raise CreatorError("Architecture not supported!")